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.0 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: 10/01/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[9A68] 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[346B] mov [mem_1m_1k], cx 175 00000017 8916[386B] 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 !' 207 00000042 656E74206D656D6F72- 207 0000004B 792021 208 0000004E 0D0A db 0Dh, 0Ah 209 _int13h_48h_buffer: ; 07/07/2016 210 00000050 284D696E696D756D20- db '(Minimum 2MB memory is needed.)' 210 00000059 324D42206D656D6F72- 210 00000062 79206973206E656564- 210 0000006B 65642E29 211 0000006F 0D0A00 db 0Dh, 0Ah, 0 212 213 L0: 214 %include 'diskinit.s' ; 07/03/2015 215 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 216 <1> ; (re-write kernel for test by using previous version without a major defect) 217 <1> ; **************************************************************************** 218 <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC 219 <1> ; Last Modification: 02/01/2022 220 <1> 221 <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project) 222 <1> 223 <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION /////////////// 224 <1> 225 <1> ; 02/01/2022 (Retro UNIX 386 v1.2) 226 <1> ; 10/12/2014 - 02/02/2015 - dsectrm2.s 227 <1> ;L0: 228 <1> ; 12/11/2014 (Retro UNIX 386 v1 - beginning) 229 <1> ; Detecting disk drives... (by help of ROM-BIOS) 230 00000072 BA7F00 <1> mov dx, 7Fh 231 <1> L1: 232 00000075 FEC2 <1> inc dl 233 00000077 B441 <1> mov ah, 41h ; Check extensions present 234 <1> ; Phoenix EDD v1.1 - EDD v3 235 00000079 BBAA55 <1> mov bx, 55AAh 236 0000007C CD13 <1> int 13h 237 0000007E 721A <1> jc short L2 238 <1> 239 00000080 81FB55AA <1> cmp bx, 0AA55h 240 00000084 7514 <1> jne short L2 241 00000086 FE06[9D68] <1> inc byte [hdc] ; count of hard disks (EDD present) 242 0000008A 8816[9C68] <1> mov [last_drv], dl ; last hard disk number 243 0000008E BB[2068] <1> mov bx, hd0_type - 80h 244 00000091 01D3 <1> add bx, dx 245 00000093 880F <1> mov [bx], cl ; Interface support bit map in CX 246 <1> ; Bit 0 - 1, Fixed disk access subset ready 247 <1> ; Bit 1 - 1, Drv locking and ejecting ready 248 <1> ; Bit 2 - 1, Enhanced Disk Drive Support 249 <1> ; (EDD) ready (DPTE ready) 250 <1> ; Bit 3 - 1, 64bit extensions are present 251 <1> ; (EDD-3) 252 <1> ; Bit 4 to 15 - 0, Reserved 253 00000095 80FA83 <1> cmp dl, 83h ; drive number < 83h 254 00000098 72DB <1> jb short L1 255 <1> L2: 256 <1> ; 23/11/2014 257 <1> ; 19/11/2014 258 0000009A 30D2 <1> xor dl, dl ; 0 259 <1> ; 04/02/2016 (esi -> si) 260 0000009C BE[9E68] <1> mov si, fd0_type 261 <1> L3: 262 <1> ; 14/01/2015 263 0000009F 8816[9B68] <1> mov [drv], dl 264 <1> ; 265 000000A3 B408 <1> mov ah, 08h ; Return drive parameters 266 000000A5 CD13 <1> int 13h 267 000000A7 7210 <1> jc short L4 268 <1> ; BL = drive type (for floppy drives) 269 <1> ; DL = number of floppy drives 270 <1> ; 271 <1> ; ES:DI = Address of DPT from BIOS 272 <1> ; 273 000000A9 881C <1> mov [si], bl ; Drive type 274 <1> ; 4 = 1.44 MB, 80 track, 3 1/2" 275 <1> ; 14/01/2015 276 000000AB E8BB01 <1> call set_disk_parms 277 <1> ; 10/12/2014 278 000000AE 81FE[9E68] <1> cmp si, fd0_type 279 000000B2 7705 <1> ja short L4 280 000000B4 46 <1> inc si ; fd1_type 281 000000B5 B201 <1> mov dl, 1 282 000000B7 EBE6 <1> jmp short L3 283 <1> L4: 284 <1> ; Older BIOS (INT 13h, AH = 48h is not available) 285 000000B9 B27F <1> mov dl, 7Fh 286 <1> ; 24/12/2014 (Temporary) 287 000000BB 803E[9D68]00 <1> cmp byte [hdc], 0 ; EDD present or not ? 288 <1> ;ja L10 ; yes, all fixed disk operations 289 <1> ; will be performed according to 290 <1> ; present EDD specification 291 <1> ; 02/01/2022 292 000000C0 7603 <1> jna short L5 293 000000C2 E99100 <1> jmp L10 294 <1> L5: 295 000000C5 FEC2 <1> inc dl 296 000000C7 8816[9B68] <1> mov [drv], dl 297 000000CB 8816[9C68] <1> mov [last_drv], dl ; 14/01/2015 298 000000CF B408 <1> mov ah, 08h ; Return drive parameters 299 000000D1 CD13 <1> int 13h ; (conventional function) 300 <1> ;jc L13 ; fixed disk drive not ready 301 <1> ; 02/01/2022 302 000000D3 7303 <1> jnc short L6 303 000000D5 E98301 <1> jmp L13 304 <1> L6: 305 000000D8 8816[9D68] <1> mov [hdc], dl ; number of drives 306 <1> ;; 14/01/2013 307 <1> ;;push cx 308 000000DC E88A01 <1> call set_disk_parms 309 <1> ;;pop cx 310 <1> ; 311 <1> ;;and cl, 3Fh ; sectors per track (bits 0-6) 312 000000DF 8A16[9B68] <1> mov dl, [drv] 313 000000E3 BB0401 <1> mov bx, 65*4 ; hd0 parameters table (INT 41h) 314 000000E6 80FA80 <1> cmp dl, 80h 315 000000E9 7603 <1> jna short L7 316 000000EB 83C314 <1> add bx, 5*4 ; hd1 parameters table (INT 46h) 317 <1> L7: 318 000000EE 31C0 <1> xor ax, ax 319 000000F0 8ED8 <1> mov ds, ax 320 000000F2 8B37 <1> mov si, [bx] 321 000000F4 8B4702 <1> mov ax, [bx+2] 322 000000F7 8ED8 <1> mov ds, ax 323 000000F9 3A4C0E <1> cmp cl, [si+FDPT_SPT] ; sectors per track 324 <1> ;jne L12 ; invalid FDPT 325 <1> ; 02/01/2022 326 000000FC 7403 <1> je short L7_8 327 000000FE E95601 <1> jmp L12 328 <1> L7_8: 329 00000101 BF0000 <1> mov di, HD0_DPT 330 00000104 80FA80 <1> cmp dl, 80h 331 00000107 7603 <1> jna short L8 332 00000109 BF2000 <1> mov di, HD1_DPT 333 <1> L8: 334 <1> ; 30/12/2014 335 0000010C B80090 <1> mov ax, DPT_SEGM 336 0000010F 8EC0 <1> mov es, ax 337 <1> ; 24/12/2014 338 00000111 B90800 <1> mov cx, 8 339 00000114 F3A5 <1> rep movsw ; copy 16 bytes to the kernel's DPT location 340 00000116 8CC8 <1> mov ax, cs 341 00000118 8ED8 <1> mov ds, ax 342 <1> ; 02/02/2015 343 0000011A 8A0E[9B68] <1> mov cl, [drv] 344 0000011E 88CB <1> mov bl, cl 345 00000120 B8F001 <1> mov ax, 1F0h 346 00000123 80E301 <1> and bl, 1 347 00000126 7406 <1> jz short L9 348 00000128 C0E304 <1> shl bl, 4 349 0000012B 2D8000 <1> sub ax, 1F0h-170h 350 <1> L9: 351 0000012E AB <1> stosw ; I/O PORT Base Address (1F0h, 170h) 352 0000012F 050602 <1> add ax, 206h 353 00000132 AB <1> stosw ; CONTROL PORT Address (3F6h, 376h) 354 00000133 88D8 <1> mov al, bl 355 00000135 04A0 <1> add al, 0A0h 356 00000137 AA <1> stosb ; Device/Head Register upper nibble 357 <1> ; 358 00000138 FE06[9B68] <1> inc byte [drv] 359 0000013C BB[2068] <1> mov bx, hd0_type - 80h 360 0000013F 01CB <1> add bx, cx 361 00000141 800F80 <1> or byte [bx], 80h ; present sign (when lower nibble is 0) 362 00000144 A0[9D68] <1> mov al, [hdc] 363 00000147 FEC8 <1> dec al 364 <1> ;jz L13 365 <1> ; 02/01/2022 366 00000149 7408 <1> jz short L9_10 367 0000014B 80FA80 <1> cmp dl, 80h 368 <1> ;jna L5 369 <1> ;jmp L13 370 <1> ; 02/01/2022 371 0000014E 7703 <1> ja short L9_10 372 00000150 E972FF <1> jmp L5 373 <1> L9_10: 374 00000153 E90501 <1> jmp L13 375 <1> L10: 376 00000156 FEC2 <1> inc dl 377 <1> ; 25/12/2014 378 00000158 8816[9B68] <1> mov [drv], dl 379 0000015C B408 <1> mov ah, 08h ; Return drive parameters 380 0000015E CD13 <1> int 13h ; (conventional function) 381 <1> ;jc L13 382 <1> ; 02/01/2022 383 00000160 72F1 <1> jc short L9_10 384 <1> ; 14/01/2015 385 00000162 8A16[9B68] <1> mov dl, [drv] 386 00000166 52 <1> push dx 387 00000167 51 <1> push cx 388 00000168 E8FE00 <1> call set_disk_parms 389 0000016B 59 <1> pop cx 390 0000016C 5A <1> pop dx 391 <1> ; 02/01/2022 - Retro UNIX 386 v1.2 392 <1> ; 04/02/2016 (esi -> si) 393 <1> ;mov si, _end ; 30 byte temporary buffer address 394 <1> ; ; at the '_end' of kernel. 395 <1> ;mov word [si], 30 396 <1> ; 06/07/2016 397 0000016D BE[5000] <1> mov si, _int13h_48h_buffer 398 <1> ; 09/07/2016 399 00000170 B81E00 <1> mov ax, 001Eh 400 00000173 8824 <1> mov [si], ah ; 0 401 00000175 46 <1> inc si 402 00000176 8904 <1> mov word [si], ax 403 <1> ; word [si] = 30 404 <1> ; 405 00000178 B448 <1> mov ah, 48h ; Get drive parameters (EDD function) 406 0000017A CD13 <1> int 13h 407 <1> ;jc L13 408 <1> ; 02/01/2022 409 0000017C 72D5 <1> jc short L9_10 410 <1> ; 04/02/2016 (ebx -> bx) 411 <1> ; 14/01/2015 412 <1> ;sub bx, bx 413 0000017E 28FF <1> sub bh, bh ; 02/01/2022 414 00000180 88D3 <1> mov bl, dl 415 00000182 80EB80 <1> sub bl, 80h 416 00000185 81C3[A068] <1> add bx, hd0_type 417 00000189 8A07 <1> mov al, [bx] 418 0000018B 0C80 <1> or al, 80h 419 0000018D 8807 <1> mov [bx], al 420 0000018F 81EB[9E68] <1> sub bx, hd0_type - 2 ; 15/01/2015 421 00000193 81C3[EA68] <1> add bx, drv.status 422 00000197 8807 <1> mov [bx], al 423 <1> ; 04/02/2016 (eax -> ax) 424 00000199 8B4410 <1> mov ax, [si+16] 425 0000019C 854412 <1> test ax, [si+18] 426 0000019F 7413 <1> jz short L10_A0h 427 <1> ; 'CHS only' disks on EDD system 428 <1> ; are reported with ZERO disk size 429 000001A1 81EB[EA68] <1> sub bx, drv.status 430 000001A5 C1E302 <1> shl bx, 2 431 000001A8 81C3[CE68] <1> add bx, drv.size ; disk size (in sectors) 432 000001AC 8907 <1> mov [bx], ax 433 000001AE 8B4412 <1> mov ax, [si+18] 434 <1> ;mov [bx], ax 435 <1> ; 02/01/2022 (BugFix) 436 000001B1 894702 <1> mov [bx+2], ax 437 <1> 438 <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 439 <1> ; for CHS disks (28/02/2015) 440 <1> ; 30/12/2014 441 000001B4 BF0000 <1> mov di, HD0_DPT 442 000001B7 88D0 <1> mov al, dl 443 000001B9 83E003 <1> and ax, 3 444 000001BC C0E005 <1> shl al, 5 ; *32 445 000001BF 01C7 <1> add di, ax 446 000001C1 B80090 <1> mov ax, DPT_SEGM 447 000001C4 8EC0 <1> mov es, ax 448 <1> ; 449 000001C6 88E8 <1> mov al, ch ; max. cylinder number (bits 0-7) 450 000001C8 88CC <1> mov ah, cl 451 000001CA C0EC06 <1> shr ah, 6 ; max. cylinder number (bits 8-9) 452 000001CD 40 <1> inc ax ; logical cylinders (limit 1024) 453 000001CE AB <1> stosw 454 000001CF 88F0 <1> mov al, dh ; max. head number 455 000001D1 FEC0 <1> inc al 456 000001D3 AA <1> stosb ; logical heads (limits 256) 457 000001D4 B0A0 <1> mov al, 0A0h ; Indicates translated table 458 000001D6 AA <1> stosb 459 000001D7 8A440C <1> mov al, [si+12] 460 000001DA AA <1> stosb ; physical sectors per track 461 000001DB 31C0 <1> xor ax, ax 462 <1> ;dec ax ; 02/01/2015 463 000001DD AB <1> stosw ; precompensation (obsolete) 464 <1> ;xor al, al ; 02/01/2015 465 000001DE AA <1> stosb ; reserved 466 000001DF B008 <1> mov al, 8 ; drive control byte 467 <1> ; (do not disable retries, 468 <1> ; more than 8 heads) 469 000001E1 AA <1> stosb 470 000001E2 8B4404 <1> mov ax, [si+4] 471 000001E5 AB <1> stosw ; physical number of cylinders 472 <1> ;push ax ; 02/01/2015 473 000001E6 8A4408 <1> mov al, [si+8] 474 000001E9 AA <1> stosb ; physical num. of heads (limit 16) 475 000001EA 29C0 <1> sub ax, ax 476 <1> ;pop ax ; 02/01/2015 477 000001EC AB <1> stosw ; landing zone (obsolete) 478 000001ED 88C8 <1> mov al, cl ; logical sectors per track (limit 63) 479 000001EF 243F <1> and al, 3Fh 480 000001F1 AA <1> stosb 481 <1> ;sub al, al ; checksum 482 <1> ;stosb 483 <1> ; 484 000001F2 83C61A <1> add si, 26 ; (BIOS) DPTE address pointer 485 000001F5 AD <1> lodsw 486 000001F6 50 <1> push ax ; (BIOS) DPTE offset 487 000001F7 AD <1> lodsw 488 000001F8 50 <1> push ax ; (BIOS) DPTE segment 489 <1> ; 490 <1> ; checksum calculation 491 000001F9 89FE <1> mov si, di 492 000001FB 06 <1> push es 493 000001FC 1F <1> pop ds 494 <1> ;mov cx, 16 495 000001FD B90F00 <1> mov cx, 15 496 00000200 29CE <1> sub si, cx 497 00000202 30E4 <1> xor ah, ah 498 <1> ;del cl 499 <1> L11: 500 00000204 AC <1> lodsb 501 00000205 00C4 <1> add ah, al 502 00000207 E2FB <1> loop L11 503 <1> ; 504 00000209 88E0 <1> mov al, ah 505 0000020B F6D8 <1> neg al ; -x+x = 0 506 0000020D AA <1> stosb ; put checksum in byte 15 of the tbl 507 <1> ; 508 0000020E 1F <1> pop ds ; (BIOS) DPTE segment 509 0000020F 5E <1> pop si ; (BIOS) DPTE offset 510 <1> ; 511 <1> ; 23/02/2015 512 00000210 57 <1> push di 513 <1> ; ES:DI points to DPTE (FDPTE) location 514 <1> ;mov cx, 8 515 00000211 B108 <1> mov cl, 8 516 00000213 F3A5 <1> rep movsw 517 <1> ; 518 <1> ; 23/02/2015 519 <1> ; (P)ATA drive and LBA validation 520 <1> ; (invalidating SATA drives and setting 521 <1> ; CHS type I/O for old type fixed disks) 522 00000215 5B <1> pop bx 523 00000216 8CC8 <1> mov ax, cs 524 00000218 8ED8 <1> mov ds, ax 525 0000021A 268B07 <1> mov ax, [es:bx] 526 0000021D 3DF001 <1> cmp ax, 1F0h 527 00000220 7418 <1> je short L11a 528 00000222 3D7001 <1> cmp ax, 170h 529 00000225 7413 <1> je short L11a 530 <1> ; invalidation 531 <1> ; (because base port address is not 1F0h or 170h) 532 00000227 30FF <1> xor bh, bh 533 00000229 88D3 <1> mov bl, dl 534 0000022B 80EB80 <1> sub bl, 80h 535 0000022E C687[A068]00 <1> mov byte [bx+hd0_type], 0 ; not a valid disk drive ! 536 00000233 808F[EC68]F0 <1> or byte [bx+drv.status+2], 0F0h ; (failure sign) 537 00000238 EB14 <1> jmp short L11b 538 <1> L11a: 539 <1> ; LBA validation 540 0000023A 268A4704 <1> mov al, [es:bx+4] ; Head register upper nibble 541 0000023E A840 <1> test al, 40h ; LBA bit (bit 6) 542 00000240 750C <1> jnz short L11b ; LBA type I/O is OK! (E0h or F0h) 543 <1> ; force CHS type I/O for this drive (A0h or B0h) 544 00000242 28FF <1> sub bh, bh 545 00000244 88D3 <1> mov bl, dl 546 00000246 80EB80 <1> sub bl, 80h ; 26/02/2015 547 00000249 80A7[EC68]FE <1> and byte [bx+drv.status+2], 0FEh ; clear bit 0 548 <1> ; bit 0 = LBA ready bit 549 <1> ; 'diskio' procedure will check this bit ! 550 <1> L11b: 551 0000024E 3A16[9C68] <1> cmp dl, [last_drv] ; 25/12/2014 552 00000252 7307 <1> jnb short L13 553 00000254 E9FFFE <1> jmp L10 554 <1> L12: 555 <1> ; Restore data registers 556 00000257 8CC8 <1> mov ax, cs 557 00000259 8ED8 <1> mov ds, ax 558 <1> L13: 559 <1> ; 13/12/2014 560 0000025B 0E <1> push cs 561 0000025C 07 <1> pop es 562 <1> L14: 563 0000025D B411 <1> mov ah, 11h 564 0000025F CD16 <1> int 16h 565 <1> ;jz short L15 ; no keys in keyboard buffer 566 <1> ; 02/01/2022 567 00000261 7466 <1> jz short L16 568 00000263 B010 <1> mov al, 10h 569 00000265 CD16 <1> int 16h 570 00000267 EBF4 <1> jmp short L14 571 <1> L15: 572 <1> 573 <1> ; ////// 574 <1> 575 <1> ; 02/01/2022 - Retro UNIX 386 v1.2 576 <1> %if 0 577 <1> ; 24/11/2014 578 <1> ; 19/11/2014 579 <1> ; 14/11/2014 580 <1> ; Temporary code for disk searching code check 581 <1> ; 582 <1> ; This code will show existing (usable) drives and also 583 <1> ; will show EDD interface support status for hard disks 584 <1> ; (If status bit 7 is 1, Identify Device info is ready, 585 <1> ; no need to get it again in protected mode...) 586 <1> ; 587 <1> ; 13/11/2014 588 <1> mov bx, 7 589 <1> mov ah, 0Eh 590 <1> mov al, [fd0_type] 591 <1> and al, al 592 <1> jz short L15a 593 <1> mov dl, al 594 <1> mov al, 'F' 595 <1> int 10h 596 <1> mov al, 'D' 597 <1> int 10h 598 <1> mov al, '0' 599 <1> int 10h 600 <1> mov al, ' ' 601 <1> int 10h 602 <1> call L15c 603 <1> mov al, ' ' 604 <1> int 10h 605 <1> ; 606 <1> mov al, [fd1_type] 607 <1> and al, al 608 <1> jz short L15a 609 <1> mov dl, al 610 <1> mov al, 'F' 611 <1> int 10h 612 <1> mov al, 'D' 613 <1> int 10h 614 <1> mov al, '1' 615 <1> int 10h 616 <1> mov al, ' ' 617 <1> int 10h 618 <1> call L15c 619 <1> mov al, ' ' 620 <1> int 10h 621 <1> mov al, ' ' 622 <1> int 10h 623 <1> L15a: 624 <1> mov al, [hd0_type] 625 <1> and al, al 626 <1> jz short L15b 627 <1> mov dl, al 628 <1> mov al, 'H' 629 <1> int 10h 630 <1> mov al, 'D' 631 <1> int 10h 632 <1> mov al, '0' 633 <1> int 10h 634 <1> mov al, ' ' 635 <1> int 10h 636 <1> call L15c 637 <1> mov al, ' ' 638 <1> int 10h 639 <1> ; 640 <1> mov al, [hd1_type] 641 <1> and al, al 642 <1> jz short L15b 643 <1> mov dl, al 644 <1> mov al, 'H' 645 <1> int 10h 646 <1> mov al, 'D' 647 <1> int 10h 648 <1> mov al, '1' 649 <1> int 10h 650 <1> mov al, ' ' 651 <1> int 10h 652 <1> call L15c 653 <1> mov al, ' ' 654 <1> int 10h 655 <1> ; 656 <1> mov al, [hd2_type] 657 <1> and al, al 658 <1> jz short L15b 659 <1> mov dl, al 660 <1> mov al, 'H' 661 <1> int 10h 662 <1> mov al, 'D' 663 <1> int 10h 664 <1> mov al, '2' 665 <1> int 10h 666 <1> mov al, ' ' 667 <1> int 10h 668 <1> call L15c 669 <1> mov al, ' ' 670 <1> int 10h 671 <1> ; 672 <1> mov al, [hd3_type] 673 <1> and al, al 674 <1> jz short L15b 675 <1> mov dl, al 676 <1> mov al, 'H' 677 <1> int 10h 678 <1> mov al, 'D' 679 <1> int 10h 680 <1> mov al, '3' 681 <1> int 10h 682 <1> mov al, ' ' 683 <1> int 10h 684 <1> call L15c 685 <1> mov al, ' ' 686 <1> int 10h 687 <1> ; 688 <1> L15b: 689 <1> mov al, 0Dh 690 <1> int 10h 691 <1> mov al, 0Ah 692 <1> int 10h 693 <1> ;;xor ah, ah 694 <1> ;;int 16h 695 <1> ; 696 <1> ;jmp L16 ; jmp short L16 697 <1> ; 02/01/2022 698 <1> jmp short L16 699 <1> ; 700 <1> L15c: 701 <1> mov dh, dl 702 <1> shr dh, 4 703 <1> add dh, 30h 704 <1> and dl, 15 705 <1> add dl, 30h 706 <1> mov al, dh 707 <1> int 10h 708 <1> mov al, dl 709 <1> int 10h 710 <1> retn 711 <1> ; 712 <1> ; end of temporary code for disk searching code check 713 <1> 714 <1> %endif 715 <1> 716 <1> ; ////// 717 <1> 718 <1> set_disk_parms: 719 <1> ; 04/02/2016 (ebx -> bx) 720 <1> ; 10/07/2015 721 <1> ; 14/01/2015 722 <1> ;push bx 723 00000269 28FF <1> sub bh, bh 724 0000026B 8A1E[9B68] <1> mov bl, [drv] 725 0000026F 80FB80 <1> cmp bl, 80h 726 00000272 7203 <1> jb short sdp0 727 00000274 80EB7E <1> sub bl, 7Eh 728 <1> sdp0: 729 00000277 81C3[EA68] <1> add bx, drv.status 730 0000027B C60780 <1> mov byte [bx], 80h ; 'Present' flag 731 <1> ; 732 0000027E 88E8 <1> mov al, ch ; last cylinder (bits 0-7) 733 00000280 88CC <1> mov ah, cl ; 734 00000282 C0EC06 <1> shr ah, 6 ; last cylinder (bits 8-9) 735 00000285 81EB[EA68] <1> sub bx, drv.status 736 00000289 D0E3 <1> shl bl, 1 737 0000028B 81C3[A468] <1> add bx, drv.cylinders 738 0000028F 40 <1> inc ax ; convert max. cyl number to cyl count 739 00000290 8907 <1> mov [bx], ax 740 00000292 50 <1> push ax ; ** cylinders 741 00000293 81EB[A468] <1> sub bx, drv.cylinders 742 00000297 81C3[B268] <1> add bx, drv.heads 743 0000029B 30E4 <1> xor ah, ah 744 0000029D 88F0 <1> mov al, dh ; heads 745 0000029F 40 <1> inc ax 746 000002A0 8907 <1> mov [bx], ax 747 000002A2 81EB[B268] <1> sub bx, drv.heads 748 000002A6 81C3[C068] <1> add bx, drv.spt 749 000002AA 30ED <1> xor ch, ch 750 000002AC 80E13F <1> and cl, 3Fh ; sectors (bits 0-6) 751 000002AF 890F <1> mov [bx], cx 752 000002B1 81EB[C068] <1> sub bx, drv.spt 753 000002B5 D1E3 <1> shl bx, 1 754 000002B7 81C3[CE68] <1> add bx, drv.size ; disk size (in sectors) 755 <1> ; LBA size = cylinders * heads * secpertrack 756 000002BB F7E1 <1> mul cx 757 000002BD 89C2 <1> mov dx, ax ; heads*spt 758 000002BF 58 <1> pop ax ; ** cylinders 759 000002C0 48 <1> dec ax ; 1 cylinder reserved (!?) 760 000002C1 F7E2 <1> mul dx ; cylinders * (heads*spt) 761 000002C3 8907 <1> mov [bx], ax 762 000002C5 895702 <1> mov [bx+2], dx 763 <1> ; 764 <1> ;pop bx 765 000002C8 C3 <1> retn 766 <1> 767 <1> ;align 2 768 <1> 769 <1> ;cylinders : dw 0, 0, 0, 0, 0, 0 770 <1> ;heads : dw 0, 0, 0, 0, 0, 0 771 <1> ;spt : dw 0, 0, 0, 0, 0, 0 772 <1> ;disk_size : dd 0, 0, 0, 0, 0, 0 773 <1> 774 <1> ;last_drv: 775 <1> ; db 0 776 <1> ;drv_status: 777 <1> ; db 0,0,0,0,0,0 778 <1> ; db 0 779 <1> 780 <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015 781 <1> 782 <1> L16: 215 _L0: 216 ; 10/11/2014 217 000002C9 FA cli ; Disable interrupts (clear interrupt flag) 218 ; Reset Interrupt MASK Registers (Master&Slave) 219 ;mov al, 0FFh ; mask off all interrupts 220 ;out 21h, al ; on master PIC (8259) 221 ;jmp $+2 ; (delay) 222 ;out 0A1h, al ; on slave PIC (8259) 223 ; 224 ; Disable NMI 225 000002CA B080 mov al, 80h 226 000002CC E670 out 70h, al ; set bit 7 to 1 for disabling NMI 227 ;23/02/2015 228 000002CE 90 nop ; 229 ;in al, 71h ; read in 71h just after writing out to 70h 230 ; for preventing unknown state (!?) 231 232 ; 01/01/2022 (Retro UNIX 386 v1.2) 233 %define KERNELFSIZE KEND-KSTART 234 ; 235 ; 20/08/2014 236 ; Moving the kernel 64 KB back (to physical address 0) 237 ; DS = CS = 1000h 238 ; 05/11/2014 239 000002CF 31C0 xor ax, ax 240 000002D1 8EC0 mov es, ax ; ES = 0 241 ; 242 ;;mov cx, (KEND - KLOAD)/4 243 ;mov cx, (KERNELFSIZE+3)/4 ; 01/01/2022 244 000002D3 B99E35 mov cx, (KERNELFSIZE+1)/2 ; 02/01/2022 245 000002D6 31F6 xor si, si 246 000002D8 31FF xor di, di 247 ;rep movsd 248 000002DA F3A5 rep movsw ; 02/01/2022 249 ; 250 000002DC 06 push es ; 0 251 000002DD 68[E102] push L17 252 000002E0 CB retf 253 ; 254 L17: 255 ; Turn off the floppy drive motor 256 000002E1 BAF203 mov dx, 3F2h 257 000002E4 EE out dx, al ; 0 ; 31/12/2013 258 259 ; Enable access to memory above one megabyte 260 L18: 261 000002E5 E464 in al, 64h 262 000002E7 A802 test al, 2 263 000002E9 75FA jnz short L18 264 000002EB B0D1 mov al, 0D1h ; Write output port 265 000002ED E664 out 64h, al 266 L19: 267 000002EF E464 in al, 64h 268 000002F1 A802 test al, 2 269 000002F3 75FA jnz short L19 270 000002F5 B0DF mov al, 0DFh ; Enable A20 line 271 000002F7 E660 out 60h, al 272 ;L20: 273 ; 274 ; Load global descriptor table register 275 276 ;mov ax, cs 277 ;mov ds, ax 278 279 000002F9 2E0F0116[C065] lgdt [cs:gdtd] 280 281 000002FF 0F20C0 mov eax, cr0 282 ;or eax, 1 283 00000302 40 inc ax 284 00000303 0F22C0 mov cr0, eax 285 286 ; Jump to 32 bit code 287 288 00000306 66 db 66h ; Prefix for 32-bit 289 00000307 EA db 0EAh ; Opcode for far jump 290 00000308 [0E030000] dd StartPM ; Offset to start, 32-bit 291 ; (1000h:StartPM = StartPM + 10000h) 292 0000030C 0800 dw KCODE ; This is the selector for CODE32_DESCRIPTOR, 293 ; assuming that StartPM resides in code32 294 295 [BITS 32] 296 297 StartPM: 298 ; Kernel Base Address = 0 ; 30/12/2013 299 0000030E 66B81000 mov ax, KDATA ; Save data segment identifier 300 00000312 8ED8 mov ds, ax ; Move a valid data segment into DS register 301 00000314 8EC0 mov es, ax ; Move data segment into ES register 302 00000316 8EE0 mov fs, ax ; Move data segment into FS register 303 00000318 8EE8 mov gs, ax ; Move data segment into GS register 304 0000031A 8ED0 mov ss, ax ; Move data segment into SS register 305 0000031C BC00000900 mov esp, 90000h ; Move the stack pointer to 090000h 306 307 clear_bss: ; Clear uninitialized data area 308 ; 11/03/2015 309 00000321 31C0 xor eax, eax ; 0 310 ;mov ecx, (bss_end - bss_start)/4 311 ;;shr ecx, 2 ; bss section is already aligned for double words 312 ; 12/12/2021 313 00000323 B913060000 mov ecx, BSS_SIZE/4 314 00000328 BF[406B0000] mov edi, bss_start 315 0000032D F3AB rep stosd 316 317 memory_init: 318 ; Initialize memory allocation table and page tables 319 ; 320 ; 02/01/2022 (Retro UNIX 386 v1.2) 321 ; 16/11/2014 322 ; 15/11/2014 323 ; 07/11/2014 324 ; 06/11/2014 325 ; 05/11/2014 326 ; 04/11/2014 327 ; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 328 ; 329 ; xor eax, eax 330 ; xor ecx, ecx 331 0000032F B108 mov cl, 8 332 00000331 BF00001000 mov edi, MEM_ALLOC_TBL 333 00000336 F3AB rep stosd ; clear Memory Allocation Table 334 ; for the first 1 MB memory 335 ; 336 00000338 8B0D[346B0000] mov ecx, [mem_1m_1k] ; 02/01/2022 337 ;mov cx, [mem_1m_1k] ; Number of contiguous KB between 338 ; 1 and 16 MB, max. 3C00h = 15 MB. 339 ;shr cx, 2 ; convert 1 KB count to 4 KB count 340 0000033E C1E902 shr ecx, 2 ; 02/01/2022 341 00000341 890D[B06D0000] mov [free_pages], ecx 342 00000347 8B15[386B0000] mov edx, [mem_16m_64k] ; 02/01/2022 343 ;mov dx, [mem_16m_64k] ; Number of contiguous 64 KB blocks 344 ; between 16 MB and 4 GB. 345 ;or dx, dx 346 0000034D 09D2 or edx, edx ; 02/01/2022 347 0000034F 7412 jz short mi_0 348 ; 349 ;mov ax, dx 350 00000351 89D0 mov eax, edx ; 02/01/2022 351 00000353 C1E004 shl eax, 4 ; 64 KB -> 4 KB (page count) 352 00000356 0105[B06D0000] add [free_pages], eax 353 0000035C 0500100000 add eax, 4096 ; 16 MB = 4096 pages 354 00000361 EB06 jmp short mi_1 355 mi_0: 356 ;mov ax, cx 357 00000363 89C8 mov eax, ecx ; 02/01/2022 358 00000365 66050001 add ax, 256 ; add 256 pages for the first 1 MB 359 mi_1: 360 00000369 A3[AC6D0000] mov [memory_size], eax ; Total available memory in pages 361 ; 1 alloc. tbl. bit = 1 memory page 362 ; 32 allocation bits = 32 mem. pages 363 ; 364 0000036E 05FF7F0000 add eax, 32767 ; 32768 memory pages per 1 M.A.T. page 365 00000373 C1E80F shr eax, 15 ; ((32768 * x) + y) pages (y < 32768) 366 ; --> x + 1 M.A.T. pages, if y > 0 367 ; --> x M.A.T. pages, if y = 0 368 ;mov [mat_size], ax ; Memory Alloc. Table Size in pages 369 00000376 A3[C06D0000] mov [mat_size], eax ; 02/01/2022 370 0000037B C1E00C shl eax, 12 ; 1 M.A.T. page = 4096 bytes 371 ; ; Max. 32 M.A.T. pages (4 GB memory) 372 0000037E 89C3 mov ebx, eax ; M.A.T. size in bytes 373 ; Set/Calculate Kernel's Page Directory Address 374 00000380 81C300001000 add ebx, MEM_ALLOC_TBL 375 00000386 891D[A86D0000] mov [k_page_dir], ebx ; Kernel's Page Directory address 376 ; just after the last M.A.T. page 377 ; 378 0000038C 83E804 sub eax, 4 ; convert M.A.T. size to offset value 379 0000038F A3[B86D0000] mov [last_page], eax ; last page ofset in the M.A.T. 380 ; ; (allocation status search must be 381 ; stopped after here) 382 00000394 31C0 xor eax, eax 383 00000396 48 dec eax ; FFFFFFFFh (set all bits to 1) 384 ;push cx 385 00000397 51 push ecx ; 02/01/2022 386 00000398 C1E905 shr ecx, 5 ; convert 1 - 16 MB page count to 387 ; count of 32 allocation bits 388 0000039B F3AB rep stosd 389 ;pop cx 390 0000039D 59 pop ecx ; 02/01/2022 391 0000039E 40 inc eax ; 0 392 0000039F 80E11F and cl, 31 ; remain bits 393 000003A2 7412 jz short mi_4 394 000003A4 8907 mov [edi], eax ; reset 395 mi_2: 396 000003A6 0FAB07 bts [edi], eax ; 06/11/2014 397 000003A9 FEC9 dec cl 398 000003AB 7404 jz short mi_3 399 000003AD FEC0 inc al 400 000003AF EBF5 jmp short mi_2 401 mi_3: 402 000003B1 28C0 sub al, al ; 0 403 000003B3 83C704 add edi, 4 ; 15/11/2014 404 mi_4: 405 000003B6 09D2 or edx, edx ; 02/01/2022 406 ;or dx, dx ; check 16M to 4G memory space 407 000003B8 741F jz short mi_6 ; max. 16 MB memory, no more... 408 ; 409 000003BA B900021000 mov ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory 410 ; 411 000003BF 29F9 sub ecx, edi ; displacement (to end of 16 MB) 412 000003C1 7405 jz short mi_5 ; jump if EDI points to 413 ; end of first 16 MB 414 ;shr ecx, 1 ; convert to dword count 415 ;shr ecx, 1 ; (shift 2 bits right) 416 000003C3 C1E902 shr ecx, 2 ; 02/01/2022 417 000003C6 F3AB rep stosd ; reset all bits for reserved pages 418 ; (memory hole under 16 MB) 419 mi_5: 420 000003C8 89D1 mov ecx, edx ; 02/01/2022 421 ;mov cx, dx ; count of 64 KB memory blocks 422 000003CA D1E9 shr ecx, 1 ; 1 alloc. dword per 128 KB memory 423 000003CC 9C pushf ; 16/11/2014 424 000003CD 48 dec eax ; FFFFFFFFh (set all bits to 1) 425 000003CE F3AB rep stosd 426 000003D0 40 inc eax ; 0 427 000003D1 9D popf ; 16/11/2014 428 000003D2 7305 jnc short mi_6 429 000003D4 6648 dec ax ; eax = 0000FFFFh 430 000003D6 AB stosd 431 000003D7 6640 inc ax ; 0 432 mi_6: 433 000003D9 39DF cmp edi, ebx ; check if EDI points to 434 000003DB 7309 jnb short mi_7 ; end of memory allocation table 435 ; ; (>= MEM_ALLOC_TBL + 4906) 436 000003DD 89D9 mov ecx, ebx ; end of memory allocation table 437 000003DF 29F9 sub ecx, edi ; convert displacement/offset 438 ;shr ecx, 1 ; to dword count 439 ;shr ecx, 1 ; (shift 2 bits right) 440 000003E1 C1E902 shr ecx, 2 ; 02/01/2022 441 000003E4 F3AB rep stosd ; reset all remain M.A.T. bits 442 mi_7: 443 ; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages) 444 000003E6 BA00001000 mov edx, MEM_ALLOC_TBL 445 ;sub ebx, edx ; Mem. Alloc. Tbl. size in bytes 446 ;shr ebx, 12 ; Mem. Alloc. Tbl. size in pages 447 000003EB 8B0D[C06D0000] mov ecx, [mat_size] ; 02/01/2022 448 ;mov cx, [mat_size] ; Mem. Alloc. Tbl. size in pages 449 000003F1 89D7 mov edi, edx 450 000003F3 C1EF0F shr edi, 15 ; convert M.A.T. address to 451 ; byte offset in M.A.T. 452 ; (1 M.A.T. byte points to 453 ; 32768 bytes) 454 ; Note: MEM_ALLOC_TBL address 455 ; must be aligned on 128 KB 456 ; boundary! 457 000003F6 01D7 add edi, edx ; points to M.A.T.'s itself 458 ; eax = 0 459 000003F8 290D[B06D0000] sub [free_pages], ecx ; 07/11/2014 460 mi_8: 461 000003FE 0FB307 btr [edi], eax ; clear bit 0 to bit x (1 to 31) 462 ;dec bl 463 00000401 FEC9 dec cl 464 00000403 7404 jz short mi_9 465 00000405 FEC0 inc al 466 00000407 EBF5 jmp short mi_8 467 mi_9: 468 ; 469 ; Reset Kernel's Page Dir. and Page Table bits in M.A.T. 470 ; (allocate pages for system page tables) 471 472 ; edx = MEM_ALLOC_TBL 473 00000409 8B0D[AC6D0000] mov ecx, [memory_size] ; memory size in pages (PTEs) 474 0000040F 81C1FF030000 add ecx, 1023 ; round up (1024 PTEs per table) 475 00000415 C1E90A shr ecx, 10 ; convert memory page count to 476 ; page table count (PDE count) 477 ; 478 00000418 51 push ecx ; (**) PDE count (<= 1024) 479 ; 480 00000419 41 inc ecx ; +1 for kernel page directory 481 ; 482 0000041A 290D[B06D0000] sub [free_pages], ecx ; 07/11/2014 483 ; 484 00000420 8B35[A86D0000] mov esi, [k_page_dir] ; Kernel's Page Directory address 485 00000426 C1EE0C shr esi, 12 ; convert to page number 486 mi_10: 487 00000429 89F0 mov eax, esi ; allocation bit offset 488 0000042B 89C3 mov ebx, eax 489 0000042D C1EB03 shr ebx, 3 ; convert to alloc. byte offset 490 00000430 80E3FC and bl, 0FCh ; clear bit 0 and bit 1 491 ; to align on dword boundary 492 00000433 83E01F and eax, 31 ; set allocation bit position 493 ; (bit 0 to bit 31) 494 ; 495 00000436 01D3 add ebx, edx ; offset in M.A.T. + M.A.T. address 496 ; 497 00000438 0FB303 btr [ebx], eax ; reset relevant bit (0 to 31) 498 ; 499 0000043B 46 inc esi ; next page table 500 0000043C E2EB loop mi_10 ; allocate next kernel page table 501 ; (ecx = page table count + 1) 502 ; 503 0000043E 59 pop ecx ; (**) PDE count (= pg. tbl. count) 504 ; 505 ; Initialize Kernel Page Directory and Kernel Page Tables 506 ; 507 ; Initialize Kernel's Page Directory 508 0000043F 8B3D[A86D0000] mov edi, [k_page_dir] 509 00000445 89F8 mov eax, edi 510 00000447 0C03 or al, PDE_A_PRESENT + PDE_A_WRITE 511 ; supervisor + read&write + present 512 00000449 89CA mov edx, ecx ; (**) PDE count (= pg. tbl. count) 513 mi_11: 514 0000044B 0500100000 add eax, 4096 ; Add page size (PGSZ) 515 ; EAX points to next page table 516 00000450 AB stosd 517 00000451 E2F8 loop mi_11 518 00000453 29C0 sub eax, eax ; Empty PDE 519 ;mov cx, 1024 ; Entry count (PGSZ/4) 520 ; 02/01/2022 521 00000455 B504 mov ch, 4 ; cx = 4*256 = 1024 522 00000457 29D1 sub ecx, edx 523 00000459 7402 jz short mi_12 524 0000045B F3AB rep stosd ; clear remain (empty) PDEs 525 ; 526 ; Initialization of Kernel's Page Directory is OK, here. 527 mi_12: 528 ; Initialize Kernel's Page Tables 529 ; 530 ; (EDI points to address of page table 0) 531 ; eax = 0 532 0000045D 8B0D[AC6D0000] mov ecx, [memory_size] ; memory size in pages 533 00000463 89CA mov edx, ecx ; (***) 534 00000465 B003 mov al, PTE_A_PRESENT + PTE_A_WRITE 535 ; supervisor + read&write + present 536 mi_13: 537 00000467 AB stosd 538 00000468 0500100000 add eax, 4096 539 0000046D E2F8 loop mi_13 540 ; 02/01/2022 541 0000046F 66B9FF03 mov cx, 1023 542 00000473 21CA and edx, ecx 543 ;and dx, 1023 ; (***) 544 00000475 7407 jz short mi_14 545 ;mov cx, 1024 546 ; 02/01/2022 547 ;mov ch, 4 ; cx = 4*256 = 1024 548 00000477 41 inc ecx ; ecx = 1024 549 00000478 29D1 sub ecx, edx 550 ;sub cx, dx ; from dx (<= 1023) to 1024 551 0000047A 31C0 xor eax, eax 552 0000047C F3AB rep stosd ; clear remain (empty) PTEs 553 ; of the last page table 554 mi_14: 555 ; Initialization of Kernel's Page Tables is OK, here. 556 ; 557 0000047E 89F8 mov eax, edi ; end of the last page table page 558 ; (beginging of user space pages) 559 00000480 C1E80F shr eax, 15 ; convert to M.A.T. byte offset 560 00000483 24FC and al, 0FCh ; clear bit 0 and bit 1 for 561 ; aligning on dword boundary 562 563 00000485 A3[BC6D0000] mov [first_page], eax 564 0000048A A3[B46D0000] mov [next_page], eax ; The first free page pointer 565 ; for user programs 566 ; (Offset in Mem. Alloc. Tbl.) 567 ; 568 ; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here. 569 ; 570 571 ; Enable paging 572 ; 573 0000048F A1[A86D0000] mov eax, [k_page_dir] 574 00000494 0F22D8 mov cr3, eax 575 00000497 0F20C0 mov eax, cr0 576 0000049A 0D00000080 or eax, 80000000h ; set paging bit (bit 31) 577 0000049F 0F22C0 mov cr0, eax 578 ;jmp KCODE:StartPMP 579 580 000004A2 EA db 0EAh ; Opcode for far jump 581 000004A3 [A9040000] dd StartPMP ; 32 bit offset 582 000004A7 0800 dw KCODE ; kernel code segment descriptor 583 584 StartPMP: 585 ; 06/11//2014 586 ; Clear video page 0 587 ; 588 ; Temporary Code 589 ; 590 ;mov ecx, 80*25/2 591 000004A9 66B9E803 mov cx, (80*25)/2 ; 02/01/2022 592 000004AD BF00800B00 mov edi, 0B8000h 593 000004B2 57 push edi ; * ; 02/01/2022 594 000004B3 31C0 xor eax, eax ; black background, black fore color 595 000004B5 F3AB rep stosd 596 597 ; 19/08/2014 598 ; Kernel Base Address = 0 599 ; It is mapped to (physically) 0 in the page table. 600 ; So, here is exactly 'StartPMP' address. 601 ; 602 ;;mov ah, 4Eh ; Red background, yellow forecolor 603 ;;mov esi, msgPM 604 ;; 14/08/2015 (kernel version message will appear 605 ;; when protected mode and paging is enabled) 606 000004B7 B40B mov ah, 0Bh ; Black background, light cyan forecolor 607 000004B9 BE[00690000] mov esi, msgKVER 608 000004BE 5F pop edi ; * ; 02/01/2022 609 ;mov edi, 0B8000h ; 27/08/2014 610 ; 20/08/2014 611 000004BF E890010000 call printk 612 613 ; 'UNIX v7/x86' source code by Robert Nordier (1999) 614 ; // Set IRQ offsets 615 ; 616 ; Linux (v0.12) source code by Linus Torvalds (1991) 617 ; 618 ;; ICW1 619 000004C4 B011 mov al, 11h ; Initialization sequence 620 000004C6 E620 out 20h, al ; 8259A-1 621 ; jmp $+2 622 000004C8 E6A0 out 0A0h, al ; 8259A-2 623 ;; ICW2 624 000004CA B020 mov al, 20h ; Start of hardware ints (20h) 625 000004CC E621 out 21h, al ; for 8259A-1 626 ; jmp $+2 627 000004CE B028 mov al, 28h ; Start of hardware ints (28h) 628 000004D0 E6A1 out 0A1h, al ; for 8259A-2 629 ; 630 000004D2 B004 mov al, 04h ;; ICW3 631 000004D4 E621 out 21h, al ; IRQ2 of 8259A-1 (master) 632 ; jmp $+2 633 000004D6 B002 mov al, 02h ; is 8259A-2 (slave) 634 000004D8 E6A1 out 0A1h, al ; 635 ;; ICW4 636 000004DA B001 mov al, 01h ; 637 000004DC E621 out 21h, al ; 8086 mode, normal EOI 638 ; jmp $+2 639 000004DE E6A1 out 0A1h, al ; for both chips. 640 641 ;mov al, 0FFh ; mask off all interrupts for now 642 ;out 21h, al 643 ;; jmp $+2 644 ;out 0A1h, al 645 646 ; 02/04/2015 647 ; 26/03/2015 System call (INT 30h) modification 648 ; DPL = 3 (Interrupt service routine can be called from user mode) 649 ; 650 ;; Linux (v0.12) source code by Linus Torvalds (1991) 651 ; setup_idt: 652 ; 653 ;; 16/02/2015 654 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 655 ; 21/08/2014 (timer_int) 656 000004E0 BE[CC650000] mov esi, ilist 657 000004E5 8D3D[406B0000] lea edi, [idt] 658 ; 26/03/2015 659 ;mov ecx, 48 ; 48 hardware interrupts (INT 0 to INT 2Fh) 660 ; 02/01/2022 661 000004EB B130 mov cl, 48 ; ecx = 48 662 ; 02/04/2015 663 000004ED BB00000800 mov ebx, 80000h 664 rp_sidt1: 665 000004F2 AD lodsd 666 000004F3 89C2 mov edx, eax 667 000004F5 66BA008E mov dx, 8E00h 668 000004F9 6689C3 mov bx, ax 669 000004FC 89D8 mov eax, ebx ; /* selector = 0x0008 = cs */ 670 ; /* interrupt gate - dpl=0, present */ 671 000004FE AB stosd ; selector & offset bits 0-15 672 000004FF 89D0 mov eax, edx 673 00000501 AB stosd ; attributes & offset bits 16-23 674 00000502 E2EE loop rp_sidt1 675 00000504 B110 mov cl, 16 ; 16 software interrupts (INT 30h to INT 3Fh) 676 rp_sidt2: 677 00000506 AD lodsd 678 00000507 21C0 and eax, eax 679 00000509 7413 jz short rp_sidt3 680 0000050B 89C2 mov edx, eax 681 0000050D 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 682 00000511 6689C3 mov bx, ax 683 00000514 89D8 mov eax, ebx ; selector & offset bits 0-15 684 00000516 AB stosd 685 00000517 89D0 mov eax, edx 686 00000519 AB stosd 687 0000051A E2EA loop rp_sidt2 688 0000051C EB16 jmp short sidt_OK 689 rp_sidt3: 690 0000051E B8[75090000] mov eax, ignore_int 691 00000523 89C2 mov edx, eax 692 00000525 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 693 00000529 6689C3 mov bx, ax 694 0000052C 89D8 mov eax, ebx ; selector & offset bits 0-15 695 rp_sidt4: 696 0000052E AB stosd 697 0000052F 92 xchg eax, edx 698 00000530 AB stosd 699 00000531 92 xchg edx, eax 700 00000532 E2FA loop rp_sidt4 701 sidt_OK: 702 00000534 0F011D[C6650000] lidt [idtd] 703 ; 704 ; TSS descriptor setup ; 24/03/2015 705 0000053B B8[406D0000] mov eax, task_state_segment 706 00000540 66A3[BA650000] mov [gdt_tss0], ax 707 00000546 C1C010 rol eax, 16 708 00000549 A2[BC650000] mov [gdt_tss1], al 709 0000054E 8825[BF650000] mov [gdt_tss2], ah 710 00000554 66C705[A66D0000]68- mov word [tss.IOPB], tss_end - task_state_segment 710 0000055C 00 711 ; 712 ; IO Map Base address (When this address points 713 ; to end of the TSS, CPU does not use IO port 714 ; permission bit map for RING 3 IO permissions, 715 ; access to any IO ports in ring 3 will be forbidden.) 716 ; 717 ;mov [tss.esp0], esp ; TSS offset 4 718 ;mov word [tss.ss0], KDATA ; TSS offset 8 (SS) 719 0000055D 66B82800 mov ax, TSS ; It is needed when an interrupt 720 ; occurs (or a system call -software INT- is requested) 721 ; while cpu running in ring 3 (in user mode). 722 ; (Kernel stack pointer and segment will be loaded 723 ; from offset 4 and 8 of the TSS, by the CPU.) 724 00000561 0F00D8 ltr ax ; Load task register 725 ; 726 esp0_set0: 727 ; 30/07/2015 728 00000564 8B0D[AC6D0000] mov ecx, [memory_size] ; memory size in pages 729 0000056A C1E10C shl ecx, 12 ; convert page count to byte count 730 0000056D 81F900004000 cmp ecx, CORE ; beginning of user's memory space (400000h) 731 ; (kernel mode virtual address) 732 00000573 7605 jna short esp0_set1 733 ; 734 ; If available memory > CORE (end of the 1st 4 MB) 735 ; set stack pointer to CORE 736 ;(Because, PDE 0 is reserved for kernel space in user's page directory) 737 ;(PDE 0 points to page table of the 1st 4 MB virtual address space) 738 00000575 B900004000 mov ecx, CORE 739 esp0_set1: 740 0000057A 89CC mov esp, ecx ; top of kernel stack (**tss.esp0**) 741 esp0_set_ok: 742 ; 30/07/2015 (**tss.esp0**) 743 0000057C 8925[446D0000] mov [tss.esp0], esp 744 00000582 66C705[486D0000]10- mov word [tss.ss0], KDATA 744 0000058A 00 745 ; 14/08/2015 746 ; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan) 747 ; 748 ;cli ; Disable interrupts (for CPU) 749 ; (CPU will not handle hardware interrupts, except NMI!) 750 ; 751 0000058B 30C0 xor al, al ; Enable all hardware interrupts! 752 0000058D E621 out 21h, al ; (IBM PC-AT compatibility) 753 0000058F EB00 jmp $+2 ; (All conventional PC-AT hardware 754 00000591 E6A1 out 0A1h, al ; interrupts will be in use.) 755 ; (Even if related hardware component 756 ; does not exist!) 757 ; Enable NMI 758 00000593 B07F mov al, 7Fh ; Clear bit 7 to enable NMI (again) 759 00000595 E670 out 70h, al 760 ; 23/02/2015 761 00000597 90 nop 762 00000598 E471 in al, 71h ; read in 71h just after writing out to 70h 763 ; for preventing unknown state (!?) 764 ; 765 ; Only a NMI can occur here... (Before a 'STI' instruction) 766 ; 767 ; 02/09/2014 768 0000059A 6631DB xor bx, bx 769 0000059D 66BA0002 mov dx, 0200h ; Row 2, column 0 ; 07/03/2015 770 000005A1 E8380F0000 call set_cpos 771 ; 772 ; 06/11/2014 773 ; Temporary Code 774 ; 775 000005A6 E855110000 call memory_info 776 ; 14/08/2015 777 ;call getch ; 28/02/2015 778 drv_init: 779 000005AB FB sti ; Enable Interrupts 780 ; 06/02/2015 781 000005AC 8B15[A0680000] mov edx, [hd0_type] ; hd0, hd1, hd2, hd3 782 000005B2 668B1D[9E680000] mov bx, [fd0_type] ; fd0, fd1 783 ; 22/02/2015 784 000005B9 6621DB and bx, bx 785 000005BC 751B jnz short di1 786 ; 787 000005BE 09D2 or edx, edx 788 000005C0 7529 jnz short di2 789 ; 790 setup_error: 791 000005C2 BE[E9690000] mov esi, setup_error_msg 792 psem: 793 000005C7 AC lodsb 794 000005C8 08C0 or al, al 795 ;jz short haltx ; 22/02/2015 796 000005CA 7426 jz short di3 797 000005CC 56 push esi 798 000005CD 31DB xor ebx, ebx ; 0 799 ; Video page 0 (bl=0) 800 000005CF B407 mov ah, 07h ; Black background, 801 ; light gray forecolor 802 000005D1 E8E60D0000 call write_tty 803 000005D6 5E pop esi 804 000005D7 EBEE jmp short psem 805 806 di1: 807 ; supress 'jmp short T6' 808 ; (activate fdc motor control code) 809 000005D9 66C705[D5060000]90- mov word [T5], 9090h ; nop 809 000005E1 90 810 ; 811 ;mov ax, int_0Eh ; IRQ 6 handler 812 ;mov di, 0Eh*4 ; IRQ 6 vector 813 ;stosw 814 ;mov ax, cs 815 ;stosw 816 ;; 16/02/2015 817 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 818 ; 819 000005E2 E82A200000 CALL DSKETTE_SETUP ; Initialize Floppy Disks 820 ; 821 000005E7 09D2 or edx, edx 822 000005E9 7407 jz short di3 823 di2: 824 000005EB E866200000 call DISK_SETUP ; Initialize Fixed Disks 825 000005F0 72D0 jc short setup_error 826 di3: 827 000005F2 E8DD100000 call setup_rtc_int ; 22/05/2015 (dsectrpm.s) 828 ; 829 000005F7 E8E55E0000 call display_disks ; 07/03/2015 (Temporary) 830 ;haltx: 831 ; 14/08/2015 832 ;call getch ; 22/02/2015 833 000005FC FB sti ; Enable interrupts (for CPU) 834 ; 14/08/2015 835 ;mov ecx, 0FFFFFFFh 836 ; 22/11/2021 837 000005FD B9FFFF2F00 mov ecx, 02FFFFFh 838 md_info_msg_wait: 839 00000602 51 push ecx 840 00000603 B001 mov al, 1 841 00000605 8A25[D66D0000] mov ah, [ptty] ; active (current) video page 842 0000060B E81C5C0000 call getc_n 843 00000610 59 pop ecx 844 00000611 7502 jnz short md_info_msg_ok 845 00000613 E2ED loop md_info_msg_wait 846 md_info_msg_ok: 847 ; 30/06/2015 848 00000615 E8472D0000 call sys_init 849 ; 850 ;jmp cpu_reset ; 22/02/2015 851 hang: 852 ; 04/12/2021 853 0000061A 29C0 sub eax, eax 854 _hang: 855 ; 23/02/2015 856 ;sti ; Enable interrupts 857 0000061C F4 hlt 858 ; 859 ;nop 860 ;; 03/12/2014 861 ;; 28/08/2014 862 ;mov ah, 11h 863 ;call getc 864 ;jz _c8 865 ; 866 ; 23/02/2015 867 ; 06/02/2015 868 ; 07/09/2014 869 0000061D 31DB xor ebx, ebx 870 0000061F 8A1D[D66D0000] mov bl, [ptty] ; active_page 871 00000625 89DE mov esi, ebx 872 00000627 66D1E6 shl si, 1 873 0000062A 81C6[D86D0000] add esi, ttychr 874 00000630 668B06 mov ax, [esi] 875 ;and ax, ax 876 ;;jz short _c8 877 ;jz short hang 878 ; 04/12/2021 879 00000633 21C0 and eax, eax 880 00000635 74E5 jz short _hang 881 00000637 66C7060000 mov word [esi], 0 882 0000063C 80FB03 cmp bl, 3 ; Video page 3 883 ;jb short _c8 884 0000063F 72D9 jb short hang 885 ; 886 ; 02/09/2014 887 00000641 B40E mov ah, 0Eh ; Yellow character 888 ; on black background 889 ; 30/11/2021 (32 bit reg push-pop) 890 ; 07/09/2014 891 nxtl: 892 00000643 53 push ebx 893 ; 894 ;xor ebx, ebx ; bl = 0 (video page 0) 895 ; bh = 0 (video mode) 896 ; Retro UNIX 386 v1 - Video Mode 0 897 ; (PC/AT Video Mode 3 - 80x25 Alpha.) 898 00000644 50 push eax 899 00000645 E8720D0000 call write_tty 900 0000064A 58 pop eax 901 ;pop bx 902 0000064B 5B pop ebx 903 0000064C 3C0D cmp al, 0Dh ; carriage return (enter) 904 ;jne short _c8 905 0000064E 75CA jne short hang 906 00000650 B00A mov al, 0Ah ; next line 907 00000652 EBEF jmp short nxtl 908 909 ;_c8: 910 ; ; 25/08/2014 911 ; cli ; Disable interrupts 912 ; mov al, [scounter + 1] 913 ; and al, al 914 ; jnz hang 915 ; call rtc_p 916 ; jmp hang 917 918 919 ; 27/08/2014 920 ; 20/08/2014 921 printk: 922 ;mov edi, [scr_row] 923 pkl: 924 00000654 AC lodsb 925 00000655 08C0 or al, al 926 00000657 7404 jz short pkr 927 00000659 66AB stosw 928 0000065B EBF7 jmp short pkl 929 pkr: 930 0000065D C3 retn 931 932 ; 25/07/2015 933 ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer) 934 ; 17/02/2015 935 ; 06/02/2015 (unix386.s) 936 ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 937 ; 938 ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85) 939 ; 940 ;-- HARDWARE INT 08 H - ( IRQ LEVEL 0 ) --------------------------------------- 941 ; THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF : 942 ; THE 8254 TIMER. INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR : 943 ; IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND. : 944 ; : 945 ; THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE : 946 ; POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY. : 947 ; THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40) : 948 ; OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE : 949 ; DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS. : 950 ; THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH : 951 ; INTERRUPT 1CH AT EVERY TIME TICK. THE USER MUST CODE A : 952 ; ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE. : 953 ;------------------------------------------------------------------------------- 954 ; 955 956 timer_int: ; IRQ 0 957 ;int_08h: ; Timer 958 ; 14/10/2015 959 ; Here, we are simulating system call entry (for task switch) 960 ; (If multitasking is enabled, 961 ; 'clock' procedure may jump to 'sysrelease') 962 0000065E 1E push ds 963 0000065F 06 push es 964 00000660 0FA0 push fs 965 00000662 0FA8 push gs 966 00000664 60 pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 967 00000665 66B91000 mov cx, KDATA 968 00000669 8ED9 mov ds, cx 969 0000066B 8EC1 mov es, cx 970 0000066D 8EE1 mov fs, cx 971 0000066F 8EE9 mov gs, cx 972 ; 973 00000671 0F20D9 mov ecx, cr3 974 00000674 890D[13070000] mov [cr3reg], ecx ; save current cr3 register value/content 975 ; 976 0000067A 3B0D[A86D0000] cmp ecx, [k_page_dir] 977 00000680 741F je short T3 978 ; 979 ; timer interrupt has been occurred while OS is in user mode 980 00000682 A3[A46E0000] mov [u.r0], eax 981 00000687 89E1 mov ecx, esp 982 00000689 83C130 add ecx, ESPACE ; 4 * 12 (stack frame) 983 0000068C 890D[9C6E0000] mov [u.sp], ecx ; kernel stack pointer at the start of interrupt 984 00000692 8925[A06E0000] mov [u.usp], esp ; kernel stack points to user's registers 985 ; 986 00000698 8B0D[A86D0000] mov ecx, [k_page_dir] 987 0000069E 0F22D9 mov cr3, ecx 988 T3: 989 000006A1 FB sti ; INTERRUPTS BACK ON 990 000006A2 66FF05[246E0000] INC word [TIMER_LOW] ; INCREMENT TIME 991 000006A9 7507 JNZ short T4 ; GO TO TEST_DAY 992 000006AB 66FF05[266E0000] INC word [TIMER_HIGH] ; INCREMENT HIGH WORD OF TIME 993 T4: ; TEST_DAY 994 000006B2 66833D[266E0000]18 CMP word [TIMER_HIGH],018H ; TEST FOR COUNT EQUALING 24 HOURS 995 000006BA 7519 JNZ short T5 ; GO TO DISKETTE_CTL 996 000006BC 66813D[246E0000]B0- CMP word [TIMER_LOW],0B0H 996 000006C4 00 997 000006C5 750E JNZ short T5 ; GO TO DISKETTE_CTL 998 999 ;----- TIMER HAS GONE 24 HOURS 1000 ;;SUB AX,AX 1001 ;MOV [TIMER_HIGH],AX 1002 ;MOV [TIMER_LOW],AX 1003 000006C7 29C0 sub eax, eax 1004 000006C9 A3[246E0000] mov [TIMER_LH], eax 1005 ; 1006 000006CE C605[286E0000]01 MOV byte [TIMER_OFL],1 1007 1008 ;----- TEST FOR DISKETTE TIME OUT 1009 1010 T5: 1011 ; 23/12/2014 1012 000006D5 EB1D jmp short T6 ; will be replaced with nop, nop 1013 ; (9090h) if a floppy disk 1014 ; is detected. 1015 ;mov al,[CS:MOTOR_COUNT] 1016 000006D7 A0[2B6E0000] mov al, [MOTOR_COUNT] 1017 000006DC FEC8 dec al 1018 ;mov [CS:MOTOR_COUNT], al ; DECREMENT DISKETTE MOTOR CONTROL 1019 000006DE A2[2B6E0000] mov [MOTOR_COUNT], al 1020 ;mov [ORG_MOTOR_COUNT], al 1021 000006E3 750F JNZ short T6 ; RETURN IF COUNT NOT OUT 1022 000006E5 B0F0 mov al,0F0h 1023 ;AND [CS:MOTOR_STATUS],al ; TURN OFF MOTOR RUNNING BITS 1024 000006E7 2005[2A6E0000] and [MOTOR_STATUS], al 1025 ;and [ORG_MOTOR_STATUS], al 1026 000006ED B00C MOV AL,0CH ; bit 3 = enable IRQ & DMA, 1027 ; bit 2 = enable controller 1028 ; 1 = normal operation 1029 ; 0 = reset 1030 ; bit 0, 1 = drive select 1031 ; bit 4-7 = motor running bits 1032 000006EF 66BAF203 MOV DX,03F2H ; FDC CTL PORT 1033 000006F3 EE OUT DX,AL ; TURN OFF THE MOTOR 1034 T6: 1035 ;inc word [CS:wait_count] ; 22/12/2014 (byte -> word) 1036 ; TIMER TICK INTERRUPT 1037 ;;inc word [wait_count] ;;27/02/2015 1038 ;INT 1CH ; TRANSFER CONTROL TO A USER ROUTINE 1039 ;;;;cli 1040 ;call u_timer ; TRANSFER CONTROL TO A USER ROUTINE 1041 000006F4 FF15[0F070000] call [x_timer] ; 14/05/2015 1042 T7: 1043 ; 14/10/2015 1044 000006FA B020 MOV AL,EOI ; GET END OF INTERRUPT MASK 1045 000006FC FA CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 1046 000006FD E620 OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 1047 ; 1048 000006FF A1[13070000] mov eax, [cr3reg] ; previous value/content of cr3 register 1049 00000704 0F22D8 mov cr3, eax ; restore cr3 register content 1050 ; 1051 00000707 61 popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 1052 ; 1053 00000708 0FA9 pop gs 1054 0000070A 0FA1 pop fs 1055 0000070C 07 pop es 1056 0000070D 1F pop ds 1057 0000070E CF iretd ; return from interrupt 1058 1059 1060 ; //////////////// 1061 1062 ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt) 1063 x_timer: 1064 0000070F [17070000] dd u_timer ; 14/05/2015 1065 ;dd clock 1066 1067 ; 14/10/2015 1068 00000713 00000000 cr3reg: dd 0 1069 1070 ; 04/12/2021 - Retro UNIX 386 v1.2 1071 ; 06/02/2015 1072 ; 07/09/2014 1073 ; 21/08/2014 1074 u_timer: 1075 1076 ; 31/12/2021 - temporary ! 1077 00000717 C3 retn 1078 1079 ;timer_int: ; IRQ 0 1080 ; 06/02/2015 1081 ;push eax 1082 ;push edx 1083 ;push ecx 1084 ;push ebx 1085 ;push ds 1086 ;push es 1087 ;mov eax, KDATA 1088 ;mov ds, ax 1089 ;mov es, ax 1090 00000718 FF05[EC6D0000] inc dword [tcount] 1091 0000071E BB[72690000] mov ebx, tcountstr + 4 1092 ;mov ax, [tcount] 1093 ; 04/12/2021 1094 00000723 A1[EC6D0000] mov eax, [tcount] 1095 00000728 B90A000000 mov ecx, 10 1096 rp_divtcnt: 1097 0000072D 31D2 xor edx, edx 1098 0000072F F7F1 div ecx 1099 00000731 80C230 add dl, 30h 1100 00000734 8813 mov [ebx], dl 1101 ;or ax, ax 1102 ; 04/12/2021 1103 00000736 09C0 or eax, eax 1104 00000738 7403 jz short print_lzero 1105 0000073A 4B dec ebx 1106 0000073B EBF0 jmp short rp_divtcnt 1107 print_lzero: 1108 0000073D 81FB[6E690000] cmp ebx, tcountstr 1109 00000743 7606 jna short print_tcount 1110 00000745 4B dec ebx 1111 00000746 C60330 mov byte [ebx], 30h 1112 00000749 EBF2 jmp short print_lzero 1113 print_tcount: 1114 0000074B 56 push esi 1115 0000074C 57 push edi 1116 0000074D BE[4A690000] mov esi, timer_msg ; Timer interrupt message 1117 ; 07/09/2014 1118 ;mov bx, 1 ; Video page 1 1119 ; 04/12/2021 1120 00000752 29DB sub ebx, ebx 1121 ;inc bl ; ebx = 1 1122 ; 02/01/2022 1123 00000754 B306 mov bl, 6 ; Video page 6 1124 ptmsg: 1125 00000756 AC lodsb 1126 00000757 08C0 or al, al 1127 00000759 740D jz short ptmsg_ok 1128 0000075B 56 push esi 1129 ;push bx 1130 ; 04/12/2021 1131 0000075C 53 push ebx 1132 0000075D B42F mov ah, 2Fh ; Green background, white forecolor 1133 0000075F E8580C0000 call write_tty 1134 ;pop bx 1135 ; 04/12/2021 1136 00000764 5B pop ebx 1137 00000765 5E pop esi 1138 00000766 EBEE jmp short ptmsg 1139 ;; 27/08/2014 1140 ;mov edi, 0B8000h + 0A0h ; Row 1 1141 ;call printk 1142 ; 1143 ptmsg_ok: 1144 ; 07/09/2014 1145 ;xor dx, dx ; column 0, row 0 1146 ; 04/12/2021 1147 00000768 31D2 xor edx, edx 1148 0000076A E86F0D0000 call set_cpos ; set cursor position to 0,0 1149 ; 23/02/2015 1150 ; 25/08/2014 1151 ;mov ebx, scounter ; (seconds counter) 1152 ;dec byte [ebx+1] ; (for reading real time clock) 1153 ; dec byte [scounter+1] 1154 ;; jns short timer_eoi ; 0 -> 0FFh ? 1155 ; jns short u_timer_retn 1156 ; 26/02/2015 1157 ; call rtc_p 1158 ; mov ebx, scounter ; (seconds counter) 1159 ; mov byte [ebx+1], 18 ; (18.2 timer ticks per second) 1160 ; dec byte [ebx] ; 19+18+18+18+18 (5) 1161 ; jnz short timer_eoi ; (109 timer ticks in 5 seconds) 1162 ; jnz short u_timer_retn ; 06/02/2015 1163 ; mov byte [ebx], 5 1164 ; inc byte [ebx+1] ; 19 1165 ;;timer_eoi: 1166 ;; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1167 ;; out 20h, al ; 8259 PORT 1168 ; 1169 ;u_timer_retn: ; 06/02/2015 1170 0000076F 5F pop edi 1171 00000770 5E pop esi 1172 ;pop es 1173 ;pop ds 1174 ;pop ebx 1175 ;pop ecx 1176 ;pop edx 1177 ;pop eax 1178 ;iret 1179 00000771 C3 retn ; 06/02/2015 1180 1181 ; 28/08/2014 1182 irq0: 1183 00000772 6A00 push dword 0 1184 00000774 EB48 jmp short which_irq 1185 irq1: 1186 00000776 6A01 push dword 1 1187 00000778 EB44 jmp short which_irq 1188 irq2: 1189 0000077A 6A02 push dword 2 1190 0000077C EB40 jmp short which_irq 1191 irq3: 1192 ; 20/11/2015 1193 ; 24/10/2015 1194 0000077E 2EFF15[A33A0000] call dword [cs:com2_irq3] 1195 00000785 6A03 push dword 3 1196 00000787 EB35 jmp short which_irq 1197 irq4: 1198 ; 20/11/2015 1199 ; 24/10/2015 1200 00000789 2EFF15[9F3A0000] call dword [cs:com1_irq4] 1201 00000790 6A04 push dword 4 1202 00000792 EB2A jmp short which_irq 1203 irq5: 1204 00000794 6A05 push dword 5 1205 00000796 EB26 jmp short which_irq 1206 irq6: 1207 00000798 6A06 push dword 6 1208 0000079A EB22 jmp short which_irq 1209 irq7: 1210 0000079C 6A07 push dword 7 1211 0000079E EB1E jmp short which_irq 1212 irq8: 1213 000007A0 6A08 push dword 8 1214 000007A2 EB1A jmp short which_irq 1215 irq9: 1216 000007A4 6A09 push dword 9 1217 000007A6 EB16 jmp short which_irq 1218 irq10: 1219 000007A8 6A0A push dword 10 1220 000007AA EB12 jmp short which_irq 1221 irq11: 1222 000007AC 6A0B push dword 11 1223 000007AE EB0E jmp short which_irq 1224 irq12: 1225 000007B0 6A0C push dword 12 1226 000007B2 EB0A jmp short which_irq 1227 irq13: 1228 000007B4 6A0D push dword 13 1229 000007B6 EB06 jmp short which_irq 1230 irq14: 1231 000007B8 6A0E push dword 14 1232 000007BA EB02 jmp short which_irq 1233 irq15: 1234 000007BC 6A0F push dword 15 1235 ;jmp short which_irq 1236 1237 ; 19/10/2015 1238 ; 29/08/2014 1239 ; 21/08/2014 1240 which_irq: 1241 000007BE 870424 xchg eax, [esp] ; 28/08/2014 1242 000007C1 53 push ebx 1243 000007C2 56 push esi 1244 000007C3 57 push edi 1245 000007C4 1E push ds 1246 000007C5 06 push es 1247 ; 1248 000007C6 88C3 mov bl, al 1249 ; 1250 000007C8 B810000000 mov eax, KDATA 1251 000007CD 8ED8 mov ds, ax 1252 000007CF 8EC0 mov es, ax 1253 ; 19/10/2015 1254 000007D1 FC cld 1255 ; 27/08/2014 1256 000007D2 8105[F8680000]A000- add dword [scr_row], 0A0h 1256 000007DA 0000 1257 ; 1258 000007DC B417 mov ah, 17h ; blue (1) background, 1259 ; light gray (7) forecolor 1260 000007DE 8B3D[F8680000] mov edi, [scr_row] 1261 000007E4 B049 mov al, 'I' 1262 000007E6 66AB stosw 1263 000007E8 B052 mov al, 'R' 1264 000007EA 66AB stosw 1265 000007EC B051 mov al, 'Q' 1266 000007EE 66AB stosw 1267 000007F0 B020 mov al, ' ' 1268 000007F2 66AB stosw 1269 000007F4 88D8 mov al, bl 1270 000007F6 3C0A cmp al, 10 1271 000007F8 7208 jb short iix 1272 000007FA B031 mov al, '1' 1273 000007FC 66AB stosw 1274 000007FE 88D8 mov al, bl 1275 00000800 2C0A sub al, 10 1276 iix: 1277 00000802 0430 add al, '0' 1278 00000804 66AB stosw 1279 00000806 B020 mov al, ' ' 1280 00000808 66AB stosw 1281 0000080A B021 mov al, '!' 1282 0000080C 66AB stosw 1283 0000080E B020 mov al, ' ' 1284 00000810 66AB stosw 1285 ; 23/02/2015 1286 00000812 80FB07 cmp bl, 7 ; check for IRQ 8 to IRQ 15 1287 ;jna iiret 1288 ; 04/12/2021 1289 00000815 7604 jna short iiz 1290 iiy: 1291 00000817 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1292 00000819 E6A0 out 0A0h, al ; the 2nd 8259 1293 iiz: 1294 0000081B E983010000 jmp iiret 1295 ; 1296 ; 22/08/2014 1297 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1298 ;out 20h, al ; 8259 PORT 1299 ; 1300 ;pop es 1301 ;pop ds 1302 ;pop edi 1303 ;pop esi 1304 ;pop ebx 1305 ;pop eax 1306 ;iret 1307 1308 ; 02/04/2015 1309 ; 25/08/2014 1310 exc0: 1311 00000820 6A00 push dword 0 1312 00000822 E990000000 jmp cpu_except 1313 exc1: 1314 00000827 6A01 push dword 1 1315 00000829 E989000000 jmp cpu_except 1316 exc2: 1317 0000082E 6A02 push dword 2 1318 00000830 E982000000 jmp cpu_except 1319 exc3: 1320 00000835 6A03 push dword 3 1321 00000837 EB7E jmp cpu_except 1322 exc4: 1323 00000839 6A04 push dword 4 1324 0000083B EB7A jmp cpu_except 1325 exc5: 1326 0000083D 6A05 push dword 5 1327 0000083F EB76 jmp cpu_except 1328 exc6: 1329 00000841 6A06 push dword 6 1330 00000843 EB72 jmp cpu_except 1331 exc7: 1332 00000845 6A07 push dword 7 1333 00000847 EB6E jmp cpu_except 1334 exc8: 1335 ; [esp] = Error code 1336 00000849 6A08 push dword 8 1337 0000084B EB5C jmp cpu_except_en 1338 exc9: 1339 0000084D 6A09 push dword 9 1340 0000084F EB66 jmp cpu_except 1341 exc10: 1342 ; [esp] = Error code 1343 00000851 6A0A push dword 10 1344 00000853 EB54 jmp cpu_except_en 1345 exc11: 1346 ; [esp] = Error code 1347 00000855 6A0B push dword 11 1348 00000857 EB50 jmp cpu_except_en 1349 exc12: 1350 ; [esp] = Error code 1351 00000859 6A0C push dword 12 1352 0000085B EB4C jmp cpu_except_en 1353 exc13: 1354 ; [esp] = Error code 1355 0000085D 6A0D push dword 13 1356 0000085F EB48 jmp cpu_except_en 1357 exc14: 1358 ; [esp] = Error code 1359 00000861 6A0E push dword 14 1360 00000863 EB44 jmp short cpu_except_en 1361 exc15: 1362 00000865 6A0F push dword 15 1363 00000867 EB4E jmp cpu_except 1364 exc16: 1365 00000869 6A10 push dword 16 1366 0000086B EB4A jmp cpu_except 1367 exc17: 1368 ; [esp] = Error code 1369 0000086D 6A11 push dword 17 1370 0000086F EB38 jmp short cpu_except_en 1371 exc18: 1372 00000871 6A12 push dword 18 1373 00000873 EB42 jmp short cpu_except 1374 exc19: 1375 00000875 6A13 push dword 19 1376 00000877 EB3E jmp short cpu_except 1377 exc20: 1378 00000879 6A14 push dword 20 1379 0000087B EB3A jmp short cpu_except 1380 exc21: 1381 0000087D 6A15 push dword 21 1382 0000087F EB36 jmp short cpu_except 1383 exc22: 1384 00000881 6A16 push dword 22 1385 00000883 EB32 jmp short cpu_except 1386 exc23: 1387 00000885 6A17 push dword 23 1388 00000887 EB2E jmp short cpu_except 1389 exc24: 1390 00000889 6A18 push dword 24 1391 0000088B EB2A jmp short cpu_except 1392 exc25: 1393 0000088D 6A19 push dword 25 1394 0000088F EB26 jmp short cpu_except 1395 exc26: 1396 00000891 6A1A push dword 26 1397 00000893 EB22 jmp short cpu_except 1398 exc27: 1399 00000895 6A1B push dword 27 1400 00000897 EB1E jmp short cpu_except 1401 exc28: 1402 00000899 6A1C push dword 28 1403 0000089B EB1A jmp short cpu_except 1404 exc29: 1405 0000089D 6A1D push dword 29 1406 0000089F EB16 jmp short cpu_except 1407 exc30: 1408 000008A1 6A1E push dword 30 1409 000008A3 EB04 jmp short cpu_except_en 1410 exc31: 1411 000008A5 6A1F push dword 31 1412 000008A7 EB0E jmp short cpu_except 1413 1414 ; 02/01/2022 (Retro UNIX 386 v1.2) 1415 ; 19/10/2015 1416 ; 19/09/2015 1417 ; 01/09/2015 1418 ; 28/08/2015 1419 ; 28/08/2014 1420 cpu_except_en: 1421 000008A9 87442404 xchg eax, [esp+4] ; Error code 1422 000008AD 36A3[586E0000] mov [ss:error_code], eax 1423 000008B3 58 pop eax ; Exception number 1424 000008B4 870424 xchg eax, [esp] 1425 ; eax = eax before exception 1426 ; [esp] -> exception number 1427 ; [esp+4] -> EIP to return 1428 ; 19/10/2015 1429 ; 19/09/2015 1430 ; 01/09/2015 1431 ; 28/08/2015 1432 ; 29/08/2014 1433 ; 28/08/2014 1434 ; 25/08/2014 1435 ; 21/08/2014 1436 cpu_except: ; CPU Exceptions 1437 000008B7 FC cld 1438 000008B8 870424 xchg eax, [esp] 1439 ; eax = Exception number 1440 ; [esp] = eax (before exception) 1441 000008BB 53 push ebx 1442 000008BC 56 push esi 1443 000008BD 57 push edi 1444 000008BE 1E push ds 1445 000008BF 06 push es 1446 ; 28/08/2015 1447 000008C0 66BB1000 mov bx, KDATA 1448 000008C4 8EDB mov ds, bx 1449 000008C6 8EC3 mov es, bx 1450 000008C8 0F20DB mov ebx, cr3 1451 000008CB 53 push ebx ; (*) page directory 1452 ; 19/10/2015 1453 000008CC FC cld 1454 ; 25/03/2015 1455 000008CD 8B1D[A86D0000] mov ebx, [k_page_dir] 1456 000008D3 0F22DB mov cr3, ebx 1457 ; 28/08/2015 1458 000008D6 83F80E cmp eax, 0Eh ; 14, PAGE FAULT 1459 000008D9 7513 jne short cpu_except_nfp 1460 000008DB E83B280000 call page_fault_handler 1461 000008E0 21C0 and eax, eax 1462 ;jz iiretp ; 01/09/2015 1463 ; 02/01/2022 1464 000008E2 7505 jnz short cpu_except_pf 1465 000008E4 E9B6000000 jmp iiretp 1466 cpu_except_pf: 1467 000008E9 B80E000000 mov eax, 0Eh ; 14 1468 cpu_except_nfp: 1469 ; 02/04/2015 1470 000008EE BB[1A060000] mov ebx, hang 1471 000008F3 875C241C xchg ebx, [esp+28] 1472 ; EIP (points to instruction which faults) 1473 ; New EIP (hang) 1474 000008F7 891D[5C6E0000] mov [FaultOffset], ebx 1475 000008FD C744242008000000 mov dword [esp+32], KCODE ; kernel's code segment 1476 00000905 814C242400020000 or dword [esp+36], 200h ; enable interrupts (set IF) 1477 ; 1478 0000090D 88C4 mov ah, al 1479 0000090F 240F and al, 0Fh 1480 00000911 3C09 cmp al, 9 1481 00000913 7602 jna short h1ok 1482 00000915 0407 add al, 'A'-':' 1483 h1ok: 1484 00000917 D0EC shr ah, 1 1485 00000919 D0EC shr ah, 1 1486 0000091B D0EC shr ah, 1 1487 0000091D D0EC shr ah, 1 1488 0000091F 80FC09 cmp ah, 9 1489 00000922 7603 jna short h2ok 1490 00000924 80C407 add ah, 'A'-':' 1491 h2ok: 1492 00000927 86E0 xchg ah, al 1493 00000929 66053030 add ax, '00' 1494 0000092D 66A3[86690000] mov [excnstr], ax 1495 ; 1496 ; 29/08/2014 1497 00000933 A1[5C6E0000] mov eax, [FaultOffset] 1498 00000938 51 push ecx 1499 00000939 52 push edx 1500 0000093A 89E3 mov ebx, esp 1501 ; 28/08/2015 1502 0000093C B910000000 mov ecx, 16 ; divisor value to convert binary number 1503 ; to hexadecimal string 1504 ;mov ecx, 10 ; divisor to convert 1505 ; binary number to decimal string 1506 b2d1: 1507 00000941 31D2 xor edx, edx 1508 00000943 F7F1 div ecx 1509 ;push dx 1510 ; 02/01/2022 1511 00000945 52 push edx 1512 00000946 39C8 cmp eax, ecx 1513 00000948 73F7 jnb short b2d1 1514 0000094A BF[91690000] mov edi, EIPstr ; EIP value 1515 ; points to instruction which faults 1516 ; 28/08/2015 1517 0000094F 89C2 mov edx, eax 1518 b2d2: 1519 ;add al, '0' 1520 00000951 8A82[B8170000] mov al, [edx+hexchrs] 1521 00000957 AA stosb ; write hexadecimal digit to its place 1522 00000958 39E3 cmp ebx, esp 1523 0000095A 7605 jna short b2d3 1524 ; 02/01/2022 1525 0000095C 58 pop eax 1526 ;pop ax 1527 0000095D 88C2 mov dl, al 1528 0000095F EBF0 jmp short b2d2 1529 b2d3: 1530 00000961 B068 mov al, 'h' ; 28/08/2015 1531 00000963 AA stosb 1532 00000964 B020 mov al, 20h ; space 1533 00000966 AA stosb 1534 00000967 30C0 xor al, al ; to do it an ASCIIZ string 1535 00000969 AA stosb 1536 ; 1537 0000096A 5A pop edx 1538 0000096B 59 pop ecx 1539 ; 1540 0000096C B44F mov ah, 4Fh ; red (4) background, 1541 ; white (F) forecolor 1542 0000096E BE[76690000] mov esi, exc_msg ; message offset 1543 ; 1544 00000973 EB11 jmp short piemsg 1545 ; 1546 ;add dword [scr_row], 0A0h 1547 ;mov edi, [scr_row] 1548 ; 1549 ;call printk 1550 ; 1551 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1552 ;out 20h, al ; 8259 PORT 1553 ; 1554 ;pop es 1555 ;pop ds 1556 ;pop edi 1557 ;pop esi 1558 ;pop eax 1559 ;iret 1560 1561 ; 28/08/2015 1562 ; 23/02/2015 1563 ; 20/08/2014 1564 ignore_int: 1565 00000975 50 push eax 1566 00000976 53 push ebx ; 23/02/2015 1567 00000977 56 push esi 1568 00000978 57 push edi 1569 00000979 1E push ds 1570 0000097A 06 push es 1571 ; 28/08/2015 1572 0000097B 0F20D8 mov eax, cr3 1573 0000097E 50 push eax ; (*) page directory 1574 ; 1575 0000097F B467 mov ah, 67h ; brown (6) background, 1576 ; light gray (7) forecolor 1577 00000981 BE[34690000] mov esi, int_msg ; message offset 1578 piemsg: 1579 ; 27/08/2014 1580 00000986 8105[F8680000]A000- add dword [scr_row], 0A0h 1580 0000098E 0000 1581 00000990 8B3D[F8680000] mov edi, [scr_row] 1582 ; 1583 00000996 E8B9FCFFFF call printk 1584 ; 1585 ; 23/02/2015 1586 0000099B B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1587 0000099D E6A0 out 0A0h, al ; the 2nd 8259 1588 iiretp: ; 01/09/2015 1589 ; 28/08/2015 1590 0000099F 58 pop eax ; (*) page directory 1591 000009A0 0F22D8 mov cr3, eax 1592 ; 1593 iiret: 1594 ; 22/08/2014 1595 000009A3 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1596 000009A5 E620 out 20h, al ; 8259 PORT 1597 ; 1598 000009A7 07 pop es 1599 000009A8 1F pop ds 1600 000009A9 5F pop edi 1601 000009AA 5E pop esi 1602 000009AB 5B pop ebx ; 29/08/2014 1603 000009AC 58 pop eax 1604 000009AD CF iretd 1605 1606 ; 26/02/2015 1607 ; 07/09/2014 1608 ; 25/08/2014 1609 rtc_int: ; Real Time Clock Interrupt (IRQ 8) 1610 ; 22/08/2014 1611 000009AE 50 push eax 1612 000009AF 53 push ebx ; 29/08/2014 1613 000009B0 56 push esi 1614 000009B1 57 push edi 1615 000009B2 1E push ds 1616 000009B3 06 push es 1617 ; 1618 000009B4 B810000000 mov eax, KDATA 1619 000009B9 8ED8 mov ds, ax 1620 000009BB 8EC0 mov es, ax 1621 ; 1622 ; 25/08/2014 1623 000009BD E884000000 call rtc_p 1624 ; 1625 ; 22/02/2015 - dsectpm.s 1626 ; [ source: http://wiki.osdev.org/RTC ] 1627 ; read status register C to complete procedure 1628 ;(it is needed to get a next IRQ 8) 1629 000009C2 B00C mov al, 0Ch ; 1630 000009C4 E670 out 70h, al ; select register C 1631 000009C6 90 nop 1632 000009C7 E471 in al, 71h ; just throw away contents 1633 ; 22/02/2015 1634 000009C9 B020 MOV AL,EOI ; END OF INTERRUPT 1635 000009CB E6A0 OUT INTB00,AL ; FOR CONTROLLER #2 1636 ; 1637 000009CD EBD4 jmp short iiret 1638 1639 ; 22/08/2014 1640 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm) 1641 ; (INT 1Ah) 1642 ;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991) 1643 time_of_day: 1644 000009CF E860010000 call UPD_IPR ; WAIT TILL UPDATE NOT IN PROGRESS 1645 000009D4 726F jc short rtc_retn 1646 000009D6 B000 mov al, CMOS_SECONDS 1647 000009D8 E841010000 call CMOS_READ 1648 000009DD A2[1C6E0000] mov [time_seconds], al 1649 000009E2 B002 mov al, CMOS_MINUTES 1650 000009E4 E835010000 call CMOS_READ 1651 000009E9 A2[1D6E0000] mov [time_minutes], al 1652 000009EE B004 mov al, CMOS_HOURS 1653 000009F0 E829010000 call CMOS_READ 1654 000009F5 A2[1E6E0000] mov [time_hours], al 1655 000009FA B006 mov al, CMOS_DAY_WEEK 1656 000009FC E81D010000 call CMOS_READ 1657 00000A01 A2[1F6E0000] mov [date_wday], al 1658 00000A06 B007 mov al, CMOS_DAY_MONTH 1659 00000A08 E811010000 call CMOS_READ 1660 00000A0D A2[206E0000] mov [date_day], al 1661 00000A12 B008 mov al, CMOS_MONTH 1662 00000A14 E805010000 call CMOS_READ 1663 00000A19 A2[216E0000] mov [date_month], al 1664 00000A1E B009 mov al, CMOS_YEAR 1665 00000A20 E8F9000000 call CMOS_READ 1666 00000A25 A2[226E0000] mov [date_year], al 1667 00000A2A B032 mov al, CMOS_CENTURY 1668 00000A2C E8ED000000 call CMOS_READ 1669 00000A31 A2[236E0000] mov [date_century], al 1670 ; 1671 00000A36 B000 mov al, CMOS_SECONDS 1672 00000A38 E8E1000000 call CMOS_READ 1673 00000A3D 3A05[1C6E0000] cmp al, [time_seconds] 1674 00000A43 758A jne short time_of_day 1675 1676 rtc_retn: 1677 00000A45 C3 retn 1678 1679 rtc_p: 1680 ; 31/12/2021 - temporary ! 1681 00000A46 C3 retn 1682 ; 27/12/2021 (Retro UNIX 386 v1.2) 1683 ; 07/09/2014 1684 ; 29/08/2014 1685 ; 27/08/2014 1686 ; 25/08/2014 1687 ; Print Real Time Clock content 1688 ; 1689 ; 1690 00000A47 E883FFFFFF call time_of_day 1691 00000A4C 72F7 jc short rtc_retn 1692 ; 1693 00000A4E 3A05[E8690000] cmp al, [ptime_seconds] 1694 00000A54 74EF je short rtc_retn ; 29/08/2014 1695 ; 1696 00000A56 A2[E8690000] mov [ptime_seconds], al 1697 ; 1698 00000A5B A0[236E0000] mov al, [date_century] 1699 00000A60 E8EA000000 call bcd_to_ascii 1700 00000A65 66A3[B5690000] mov [datestr+6], ax 1701 00000A6B A0[226E0000] mov al, [date_year] 1702 00000A70 E8DA000000 call bcd_to_ascii 1703 00000A75 66A3[B7690000] mov [datestr+8], ax 1704 00000A7B A0[216E0000] mov al, [date_month] 1705 00000A80 E8CA000000 call bcd_to_ascii 1706 00000A85 66A3[B2690000] mov [datestr+3], ax 1707 00000A8B A0[206E0000] mov al, [date_day] 1708 00000A90 E8BA000000 call bcd_to_ascii 1709 00000A95 66A3[AF690000] mov [datestr], ax 1710 ; 1711 00000A9B 0FB61D[1F6E0000] movzx ebx, byte [date_wday] 1712 00000AA2 C0E302 shl bl, 2 1713 00000AA5 81C3[C8690000] add ebx, daytmp 1714 00000AAB 8B03 mov eax, [ebx] 1715 00000AAD A3[BA690000] mov [daystr], eax 1716 ; 1717 00000AB2 A0[1E6E0000] mov al, [time_hours] 1718 00000AB7 E893000000 call bcd_to_ascii 1719 00000ABC 66A3[BE690000] mov [timestr], ax 1720 00000AC2 A0[1D6E0000] mov al, [time_minutes] 1721 00000AC7 E883000000 call bcd_to_ascii 1722 00000ACC 66A3[C1690000] mov [timestr+3], ax 1723 00000AD2 A0[1C6E0000] mov al, [time_seconds] 1724 00000AD7 E873000000 call bcd_to_ascii 1725 00000ADC 66A3[C4690000] mov [timestr+6], ax 1726 ; 1727 00000AE2 BE[9D690000] mov esi, rtc_msg ; message offset 1728 ; 23/02/2015 1729 00000AE7 52 push edx 1730 00000AE8 51 push ecx 1731 ; 07/09/2014 1732 ;mov bx, 2 ; Video page 2 1733 ; 27/12/2021 1734 00000AE9 29DB sub ebx, ebx 1735 00000AEB B302 mov bl, 2 1736 prtmsg: 1737 00000AED AC lodsb 1738 00000AEE 08C0 or al, al 1739 00000AF0 740D jz short prtmsg_ok 1740 00000AF2 56 push esi 1741 ;push bx 1742 00000AF3 53 push ebx ; 27/12/2021 1743 00000AF4 B43F mov ah, 3Fh ; cyan (6) background, 1744 ; white (F) forecolor 1745 00000AF6 E8C1080000 call write_tty 1746 ;pop bx 1747 00000AFB 5B pop ebx ; 27/12/2021 1748 00000AFC 5E pop esi 1749 00000AFD EBEE jmp short prtmsg 1750 ; 1751 ;mov edi, 0B8000h+0A0h+0A0h ; Row 2 1752 ;call printk 1753 prtmsg_ok: 1754 ; 07/09/2014 1755 ;xor dx, dx ; column 0, row 0 1756 ; 27/12/2021 1757 00000AFF 31D2 xor edx, edx 1758 00000B01 E8D8090000 call set_cpos ; set curspor position to 0,0 1759 ; 23/02/2015 1760 00000B06 59 pop ecx 1761 00000B07 5A pop edx 1762 00000B08 C3 retn 1763 1764 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 1765 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 1766 default_irq7: 1767 ; 04/12/2021 1768 ;push ax 1769 00000B09 50 push eax 1770 00000B0A B00B mov al, 0Bh ; In-Service register 1771 00000B0C E620 out 20h, al 1772 00000B0E EB00 jmp short $+2 1773 00000B10 EB00 jmp short $+2 1774 00000B12 E420 in al, 20h 1775 00000B14 2480 and al, 80h ; bit 7 (is it real IRQ 7 or fake?) 1776 00000B16 7404 jz short irq7_iret ; Fake (spurious) IRQ, do not send EOI 1777 00000B18 B020 mov al, 20h ; EOI 1778 00000B1A E620 out 20h, al 1779 irq7_iret: 1780 ;pop ax 1781 ; 04/12/2021 1782 00000B1C 58 pop eax 1783 00000B1D CF iretd 1784 1785 ; 04/12/2021 1786 ; 22/08/2014 1787 ; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm) 1788 CMOS_READ: 1789 00000B1E 9C pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 1790 00000B1F D0C0 rol al, 1 ; MOVE NMI BIT TO LOW POSITION 1791 00000B21 F9 stc ; FORCE NMI BIT ON IN CARRY FLAG 1792 00000B22 D0D8 rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 1793 00000B24 FA cli ; DISABLE INTERRUPTS 1794 00000B25 E670 out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 1795 00000B27 90 nop ; I/O DELAY 1796 00000B28 E471 in al, CMOS_DATA ; READ THE REQUESTED CMOS LOCATION 1797 ;push ax ; SAVE (AH) REGISTER VALUE AND CMOS BYTE 1798 ; 04/12/2021 1799 00000B2A 50 push eax 1800 ; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 1801 ; ----- 10/06/85 (test4.asm) 1802 00000B2B B01E mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 1803 ;mov al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION 1804 00000B2D D0D8 rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 1805 00000B2F E670 out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 1806 ;pop ax ; RESTORE (AH) AND (AL), CMOS BYTE 1807 ; 04/12/2021 1808 00000B31 58 pop eax 1809 00000B32 9D popf 1810 00000B33 C3 retn ; RETURN WITH FLAGS RESTORED 1811 1812 ; 22/08/2014 1813 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm) 1814 UPD_IPR: ; WAIT TILL UPDATE NOT IN PROGRESS 1815 00000B34 51 push ecx 1816 00000B35 B9FFFF0000 mov ecx, 65535 ; SET TIMEOUT LOOP COUNT (= 800) 1817 ; mov cx, 800 1818 UPD_10: 1819 00000B3A B00A mov al, CMOS_REG_A ; ADDRESS STATUS REGISTER A 1820 00000B3C FA cli ; NO TIMER INTERRUPTS DURING UPDATES 1821 00000B3D E8DCFFFFFF call CMOS_READ ; READ UPDATE IN PROCESS FLAG 1822 00000B42 A880 test al, 80h ; IF UIP BIT IS ON ( CANNOT READ TIME ) 1823 00000B44 7406 jz short UPD_90 ; EXIT WITH CY= 0 IF CAN READ CLOCK NOW 1824 00000B46 FB sti ; ALLOW INTERRUPTS WHILE WAITING 1825 00000B47 E2F1 loop UPD_10 ; LOOP TILL READY OR TIMEOUT 1826 00000B49 31C0 xor eax, eax ; CLEAR RESULTS IF ERROR 1827 ; xor ax, ax 1828 00000B4B F9 stc ; SET CARRY FOR ERROR 1829 UPD_90: 1830 00000B4C 59 pop ecx ; RESTORE CALLERS REGISTER 1831 00000B4D FA cli ; INTERRUPTS OFF DURING SET 1832 00000B4E C3 retn ; RETURN WITH CY FLAG SET 1833 1834 bcd_to_ascii: 1835 ; 25/08/2014 1836 ; INPUT -> 1837 ; al = Packed BCD number 1838 ; OUTPUT -> 1839 ; ax = ASCII word/number 1840 ; 1841 ; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011) 1842 ; 1843 00000B4F D410 db 0D4h, 10h ; Undocumented inst. AAM 1844 ; AH = AL / 10h 1845 ; AL = AL MOD 10h 1846 00000B51 660D3030 or ax, '00' ; Make it ASCII based 1847 1848 00000B55 86E0 xchg ah, al 1849 1850 00000B57 C3 retn 1851 1852 1853 %include 'keyboard.s' ; 07/03/2015 1854 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 1855 <1> ; (re-write kernel for test by using previous version without a major defect) 1856 <1> ; **************************************************************************** 1857 <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC 1858 <1> ; Last Modification: 05/12/2021 1859 <1> ; (Keyboard Data is in 'KYBDATA.INC') 1860 <1> ; 1861 <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) /////////////// 1862 <1> 1863 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 1864 <1> ; 30/06/2015 1865 <1> ; 11/03/2015 1866 <1> ; 28/02/2015 1867 <1> ; 25/02/2015 1868 <1> ; 20/02/2015 1869 <1> ; 18/02/2015 1870 <1> ; 03/12/2014 1871 <1> ; 07/09/2014 1872 <1> ; KEYBOARD INTERRUPT HANDLER 1873 <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014) 1874 <1> 1875 <1> ;getch: 1876 <1> ; ; 18/02/2015 1877 <1> ; ; This routine will be replaced with Retro UNIX 386 1878 <1> ; ; version of Retro UNIX 8086 getch (tty input) 1879 <1> ; ; routine, later... (multi tasking ability) 1880 <1> ; ; 28/02/2015 1881 <1> ; sti ; enable interrupts 1882 <1> ; ; 1883 <1> ; ;push esi 1884 <1> ; ;push ebx 1885 <1> ; ;xor ebx, ebx 1886 <1> ; ;mov bl, [ptty] ; active_page 1887 <1> ; ;mov esi, ebx 1888 <1> ; ;shl si, 1 1889 <1> ; ;add esi, ttychr 1890 <1> ;getch_1: 1891 <1> ; ;mov ax, [esi] 1892 <1> ; mov ax, [ttychr] ; video page 0 (tty0) 1893 <1> ; and ax, ax 1894 <1> ; jz short getch_2 1895 <1> ; mov word [ttychr], 0 1896 <1> ; ;mov word [esi], 0 1897 <1> ; ;pop ebx 1898 <1> ; ;pop esi 1899 <1> ; retn 1900 <1> ;getch_2: 1901 <1> ; hlt ; not proper for multi tasking! 1902 <1> ; ; (temporary halt for now) 1903 <1> ; ; 'sleep' on tty 1904 <1> ; ; will (must) be located here 1905 <1> ; nop 1906 <1> ; jmp short getch_1 1907 <1> 1908 <1> keyb_int: 1909 <1> ; 30/06/2015 1910 <1> ; 25/02/2015 1911 <1> ; 20/02/2015 1912 <1> ; 03/12/2014 (getc_int - INT 16h modifications) 1913 <1> ; 07/09/2014 - Retro UNIX 386 v1 1914 <1> ; 30/06/2014 1915 <1> ; 10/05/2013 1916 <1> ; Retro Unix 8086 v1 feature only! 1917 <1> ; 03/03/2014 1918 <1> 1919 00000B58 1E <1> push ds 1920 00000B59 53 <1> push ebx 1921 00000B5A 50 <1> push eax 1922 <1> ; 1923 00000B5B 66B81000 <1> mov ax, KDATA 1924 00000B5F 8ED8 <1> mov ds, ax 1925 <1> ; 1926 00000B61 9C <1> pushfd 1927 00000B62 0E <1> push cs 1928 00000B63 E812020000 <1> call kb_int ; int_09h 1929 <1> ; 1930 00000B68 B411 <1> mov ah, 11h ; 03/12/2014 1931 <1> ;call getc 1932 00000B6A E856000000 <1> call int_16h ; 30/06/2015 1933 00000B6F 7450 <1> jz short keyb_int4 1934 <1> ; 1935 00000B71 B410 <1> mov ah, 10h ; 03/12/2014 1936 <1> ;call getc 1937 00000B73 E84D000000 <1> call int_16h ; 30/06/2015 1938 <1> ; 1939 <1> ; 20/02/2015 1940 00000B78 0FB61D[D66D0000] <1> movzx ebx, byte [ptty] ; active_page 1941 <1> ; 1942 00000B7F 20C0 <1> and al, al 1943 00000B81 751E <1> jnz short keyb_int1 1944 <1> ; 1945 00000B83 80FC68 <1> cmp ah, 68h ; ALT + F1 key 1946 00000B86 7219 <1> jb short keyb_int1 1947 00000B88 80FC6F <1> cmp ah, 6Fh ; ALT + F8 key 1948 00000B8B 7714 <1> ja short keyb_int1 1949 <1> ; 1950 00000B8D 88D8 <1> mov al, bl 1951 00000B8F 0468 <1> add al, 68h 1952 00000B91 38E0 <1> cmp al, ah 1953 00000B93 7409 <1> je short keyb_int0 1954 00000B95 88E0 <1> mov al, ah 1955 00000B97 2C68 <1> sub al, 68h 1956 00000B99 E8FB0A0000 <1> call tty_sw 1957 <1> ;movzx ebx, [ptty] ; active_page 1958 <1> keyb_int0: ; 30/06/2015 1959 00000B9E 6631C0 <1> xor ax, ax 1960 <1> keyb_int1: 1961 00000BA1 D0E3 <1> shl bl, 1 1962 00000BA3 81C3[D86D0000] <1> add ebx, ttychr 1963 <1> ; 1964 00000BA9 6609C0 <1> or ax, ax 1965 00000BAC 7406 <1> jz short keyb_int2 1966 <1> ; 1967 00000BAE 66833B00 <1> cmp word [ebx], 0 1968 00000BB2 7703 <1> ja short keyb_int3 1969 <1> keyb_int2: 1970 00000BB4 668903 <1> mov [ebx], ax ; Save ascii code 1971 <1> ; and scan code of the character 1972 <1> ; for current tty (or last tty 1973 <1> ; just before tty switch). 1974 <1> keyb_int3: 1975 00000BB7 A0[D66D0000] <1> mov al, [ptty] 1976 00000BBC E88D420000 <1> call wakeup 1977 <1> ; 1978 <1> keyb_int4: 1979 00000BC1 58 <1> pop eax 1980 00000BC2 5B <1> pop ebx 1981 00000BC3 1F <1> pop ds 1982 00000BC4 CF <1> iret 1983 <1> 1984 <1> ; 18/02/2015 1985 <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc. 1986 <1> ; 'keyb_int' always handles 'getc' at 1st and puts the 1987 <1> ; scancode and ascii code of the character 1988 <1> ; in the tty input (ttychr) buffer. 1989 <1> ; Test procedures must call 'getch' for tty input 1990 <1> ; otherwise, 'getc' will not be able to return to the caller 1991 <1> ; due to infinite (key press) waiting loop. 1992 <1> ; 1993 <1> ; 03/12/2014 1994 <1> ; 26/08/2014 1995 <1> ; KEYBOARD I/O 1996 <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014) 1997 <1> 1998 <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers. 1999 <1> ; (The reason of using '_k' labels!!!) (27/08/2014) 2000 <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM. 2001 <1> ; ('NOT LC_HC' --> '~LC_HC') (bit reversing operator) 2002 <1> 2003 <1> int_16h: ; 30/06/2015 2004 <1> ;getc: 2005 00000BC5 9C <1> pushfd ; 28/08/2014 2006 00000BC6 0E <1> push cs 2007 00000BC7 E826000000 <1> call getc_int 2008 00000BCC C3 <1> retn 2009 <1> 2010 <1> ; 05/12/2021 2011 <1> 2012 <1> ;----- SHIFT STATUS 2013 <1> _K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2014 00000BCD 8A25[D4670000] <1> mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2015 00000BD3 80E404 <1> and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2016 <1> ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2017 <1> ;shl ah, cl ; BIT 7 POSITION 2018 00000BD6 C0E405 <1> shl ah, 5 2019 00000BD9 A0[D4670000] <1> mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2020 00000BDE 2473 <1> and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2021 00000BE0 08C4 <1> or ah, al ; MERGE REMAINING BITS INTO AH 2022 00000BE2 A0[D6670000] <1> mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2023 00000BE7 240C <1> and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2024 00000BE9 08C4 <1> or ah, al ; OR THE SHIFT FLAGS TOGETHER 2025 <1> _K3: 2026 00000BEB A0[D3670000] <1> mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2027 00000BF0 EB2B <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2028 <1> 2029 <1> getc_int: 2030 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2031 <1> ; 28/02/2015 2032 <1> ; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2033 <1> ; instead of pc-at bios - 1985-) 2034 <1> ; 28/08/2014 (_k1d) 2035 <1> ; 30/06/2014 2036 <1> ; 03/03/2014 2037 <1> ; 28/02/2014 2038 <1> ; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 2039 <1> ; rombios source code (21/04/1986) 2040 <1> ; 'keybd.asm', INT 16H, KEYBOARD_IO 2041 <1> ; 2042 <1> ; KYBD --- 03/06/86 KEYBOARD BIOS 2043 <1> ; 2044 <1> ;--- INT 16 H ----------------------------------------------------------------- 2045 <1> ; KEYBOARD I/O : 2046 <1> ; THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT : 2047 <1> ; INPUT : 2048 <1> ; (AH)= 00H READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD, : 2049 <1> ; RETURN THE RESULT IN (AL), SCAN CODE IN (AH). : 2050 <1> ; THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE : 2051 <1> ; STANDARD PC OR PCAT KEYBOARD : 2052 <1> ;-----------------------------------------------------------------------------: 2053 <1> ; (AH)= 01H SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS : 2054 <1> ; AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER. : 2055 <1> ; (ZF)= 1 -- NO CODE AVAILABLE : 2056 <1> ; (ZF)= 0 -- CODE IS AVAILABLE (AX)= CHARACTER : 2057 <1> ; IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS : 2058 <1> ; IN (AX), AND THE ENTRY REMAINS IN THE BUFFER. : 2059 <1> ; THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES : 2060 <1> ;-----------------------------------------------------------------------------: 2061 <1> ; (AH)= 02H RETURN THE CURRENT SHIFT STATUS IN AL REGISTER : 2062 <1> ; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE : 2063 <1> ; EQUATES FOR @KB_FLAG : 2064 <1> ;-----------------------------------------------------------------------------: 2065 <1> ; (AH)= 03H SET TYPAMATIC RATE AND DELAY : 2066 <1> ; (AL) = 05H : 2067 <1> ; (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0) : 2068 <1> ; : 2069 <1> ; REGISTER RATE REGISTER RATE : 2070 <1> ; VALUE SELECTED VALUE SELECTED : 2071 <1> ; -------------------------------------------- : 2072 <1> ; 00H 30.0 10H 7.5 : 2073 <1> ; 01H 26.7 11H 6.7 : 2074 <1> ; 02H 24.0 12H 6.0 : 2075 <1> ; 03H 21.8 13H 5.5 : 2076 <1> ; 04H 20.0 14H 5.0 : 2077 <1> ; 05H 18.5 15H 4.6 : 2078 <1> ; 06H 17.1 16H 4.3 : 2079 <1> ; 07H 16.0 17H 4.0 : 2080 <1> ; 08H 15.0 18H 3.7 : 2081 <1> ; 09H 13.3 19H 3.3 : 2082 <1> ; 0AH 12.0 1AH 3.0 : 2083 <1> ; 0BH 10.9 1BH 2.7 : 2084 <1> ; 0CH 10.0 1CH 2.5 : 2085 <1> ; 0DH 9.2 1DH 2.3 : 2086 <1> ; 0EH 8.6 1EH 2.1 : 2087 <1> ; 0FH 8.0 1FH 2.0 : 2088 <1> ; : 2089 <1> ; (BH) = TYPAMATIC DELAY (BITS 2 - 7 MUST BE RESET TO 0) : 2090 <1> ; : 2091 <1> ; REGISTER DELAY : 2092 <1> ; VALUE VALUE : 2093 <1> ; ------------------ : 2094 <1> ; 00H 250 ms : 2095 <1> ; 01H 500 ms : 2096 <1> ; 02H 750 ms : 2097 <1> ; 03H 1000 ms : 2098 <1> ;-----------------------------------------------------------------------------: 2099 <1> ; (AH)= 05H PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD : 2100 <1> ; BUFFER AS IF STRUCK FROM KEYBOARD : 2101 <1> ; ENTRY: (CL) = ASCII CHARACTER : 2102 <1> ; (CH) = SCAN CODE : 2103 <1> ; EXIT: (AH) = 00H = SUCCESSFUL OPERATION : 2104 <1> ; (AL) = 01H = UNSUCCESSFUL - BUFFER FULL : 2105 <1> ; FLAGS: CARRY IF ERROR : 2106 <1> ;-----------------------------------------------------------------------------: 2107 <1> ; (AH)= 10H EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD, : 2108 <1> ; OTHERWISE SAME AS FUNCTION AH=0 : 2109 <1> ;-----------------------------------------------------------------------------: 2110 <1> ; (AH)= 11H EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD, : 2111 <1> ; OTHERWISE SAME AS FUNCTION AH=1 : 2112 <1> ;-----------------------------------------------------------------------------: 2113 <1> ; (AH)= 12H RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER : 2114 <1> ; AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT : 2115 <1> ; CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3 : 2116 <1> ; OUTPUT : 2117 <1> ; AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED : 2118 <1> ; ALL REGISTERS RETAINED : 2119 <1> ;------------------------------------------------------------------------------ 2120 <1> 2121 00000BF2 FB <1> sti ; INTERRUPTS BACK ON 2122 00000BF3 1E <1> push ds ; SAVE CURRENT DS 2123 00000BF4 53 <1> push ebx ; SAVE BX TEMPORARILY 2124 <1> ;push ecx ; SAVE CX TEMPORARILY 2125 00000BF5 66BB1000 <1> mov bx, KDATA 2126 00000BF9 8EDB <1> mov ds, bx ; PUT SEGMENT VALUE OF DATA AREA INTO DS 2127 00000BFB 08E4 <1> or ah, ah ; CHECK FOR (AH)= 00H 2128 00000BFD 742D <1> jz short _K1 ; ASCII_READ 2129 00000BFF FECC <1> dec ah ; CHECK FOR (AH)= 01H 2130 00000C01 7446 <1> jz short _K2 ; ASCII_STATUS 2131 00000C03 FECC <1> dec ah ; CHECK FOR (AH)= 02H 2132 00000C05 74E4 <1> jz short _K3 ; SHIFT STATUS 2133 00000C07 FECC <1> dec ah ; CHECK FOR (AH)= 03H 2134 00000C09 745B <1> jz short _K300 ; SET TYPAMATIC RATE/DELAY 2135 00000C0B 80EC02 <1> sub ah, 2 ; CHECK FOR (AH)= 05H 2136 00000C0E 7479 <1> jz short _K500 ; KEYBOARD WRITE 2137 <1> _KIO1: 2138 00000C10 80EC0B <1> sub ah, 11 ; AH = 10H 2139 00000C13 740B <1> jz short _K1E ; EXTENDED ASCII READ 2140 00000C15 FECC <1> dec ah ; CHECK FOR (AH)= 11H 2141 00000C17 7421 <1> jz short _K2E ; EXTENDED_ASCII_STATUS 2142 00000C19 FECC <1> dec ah ; CHECK FOR (AH)= 12H 2143 00000C1B 74B0 <1> jz short _K3E ; EXTENDED_SHIFT_STATUS 2144 <1> _KIO_EXIT: 2145 <1> ;pop ecx ; RECOVER REGISTER 2146 00000C1D 5B <1> pop ebx ; RECOVER REGISTER 2147 00000C1E 1F <1> pop ds ; RECOVER SEGMENT 2148 00000C1F CF <1> iretd ; INVALID COMMAND, EXIT 2149 <1> 2150 <1> ;----- ASCII CHARACTER 2151 <1> _K1E: 2152 00000C20 E891000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER (EXTENDED) 2153 00000C25 E804010000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2154 00000C2A EBF1 <1> jmp short _KIO_EXIT ; GIVE IT TO THE CALLER 2155 <1> _K1: 2156 00000C2C E885000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER 2157 00000C31 E803010000 <1> call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2158 00000C36 72F4 <1> jc short _K1 ; CARRY SET MEANS TROW CODE AWAY 2159 <1> _K1A: 2160 00000C38 EBE3 <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2161 <1> 2162 <1> ;----- ASCII STATUS 2163 <1> _K2E: 2164 00000C3A E8C2000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER (EXTENDED) 2165 00000C3F 7420 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2166 00000C41 9C <1> pushf ; SAVE ZF FROM TEST 2167 00000C42 E8E7000000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2168 00000C47 EB17 <1> jmp short _K2A ; GIVE IT TO THE CALLER 2169 <1> _K2: 2170 00000C49 E8B3000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER 2171 00000C4E 7411 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2172 00000C50 9C <1> pushf ; SAVE ZF FROM TEST 2173 00000C51 E8E3000000 <1> call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2174 00000C56 7308 <1> jnc short _K2A ; CARRY CLEAR MEANS PASS VALID CODE 2175 00000C58 9D <1> popf ; INVALID CODE FOR THIS TYPE OF CALL 2176 00000C59 E858000000 <1> call _K1S ; THROW THE CHARACTER AWAY 2177 00000C5E EBE9 <1> jmp short _K2 ; GO LOOK FOR NEXT CHAR, IF ANY 2178 <1> _K2A: 2179 00000C60 9D <1> popf ; RESTORE ZF FROM TEST 2180 <1> _K2B: 2181 <1> ;pop ecx ; RECOVER REGISTER 2182 00000C61 5B <1> pop ebx ; RECOVER REGISTER 2183 00000C62 1F <1> pop ds ; RECOVER SEGMENT 2184 00000C63 CA0400 <1> retf 4 ; THROW AWAY (e)FLAGS 2185 <1> 2186 <1> ; 05/12/2021 2187 <1> ; ;----- SHIFT STATUS 2188 <1> ;_K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2189 <1> ; mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2190 <1> ; and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2191 <1> ; ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2192 <1> ; ;shl ah, cl ; BIT 7 POSITION 2193 <1> ; shl ah, 5 2194 <1> ; mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2195 <1> ; and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2196 <1> ; or ah, al ; MERGE REMAINING BITS INTO AH 2197 <1> ; mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2198 <1> ; and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2199 <1> ; or ah, al ; OR THE SHIFT FLAGS TOGETHER 2200 <1> ;_K3: 2201 <1> ; mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2202 <1> ; jmp short _KIO_EXIT ; RETURN TO CALLER 2203 <1> 2204 <1> ;----- SET TYPAMATIC RATE AND DELAY 2205 <1> _K300: 2206 00000C66 3C05 <1> cmp al, 5 ; CORRECT FUNCTION CALL? 2207 00000C68 75B3 <1> jne short _KIO_EXIT ; NO, RETURN 2208 00000C6A F6C3E0 <1> test bl, 0E0h ; TEST FOR OUT-OF-RANGE RATE 2209 00000C6D 75AE <1> jnz short _KIO_EXIT ; RETURN IF SO 2210 00000C6F F6C7FC <1> test BH, 0FCh ; TEST FOR OUT-OF-RANGE DELAY 2211 00000C72 75A9 <1> jnz short _KIO_EXIT ; RETURN IF SO 2212 00000C74 B0F3 <1> mov al, KB_TYPA_RD ; COMMAND FOR TYPAMATIC RATE/DELAY 2213 00000C76 E880060000 <1> call SND_DATA ; SEND TO KEYBOARD 2214 <1> ;mov cx, 5 ; SHIFT COUNT 2215 <1> ;shl bh, cl ; SHIFT DELAY OVER 2216 00000C7B C0E705 <1> shl bh, 5 2217 00000C7E 88D8 <1> mov al, bl ; PUT IN RATE 2218 00000C80 08F8 <1> or al, bh ; AND DELAY 2219 00000C82 E874060000 <1> call SND_DATA ; SEND TO KEYBOARD 2220 00000C87 EB94 <1> jmp _KIO_EXIT ; RETURN TO CALLER 2221 <1> 2222 <1> ;----- WRITE TO KEYBOARD BUFFER 2223 <1> _K500: 2224 00000C89 56 <1> push esi ; SAVE SI (esi) 2225 00000C8A FA <1> cli ; 2226 00000C8B 8B1D[E4670000] <1> mov ebx, [BUFFER_TAIL] ; GET THE 'IN TO' POINTER TO THE BUFFER 2227 00000C91 89DE <1> mov esi, ebx ; SAVE A COPY IN CASE BUFFER NOT FULL 2228 00000C93 E8D1000000 <1> call _K4 ; BUMP THE POINTER TO SEE IF BUFFER IS FULL 2229 00000C98 3B1D[E0670000] <1> cmp ebx, [BUFFER_HEAD] ; WILL THE BUFFER OVERRUN IF WE STORE THIS? 2230 00000C9E 740D <1> je short _K502 ; YES - INFORM CALLER OF ERROR 2231 00000CA0 66890E <1> mov [esi], cx ; NO - PUT ASCII/SCAN CODE INTO BUFFER 2232 00000CA3 891D[E4670000] <1> mov [BUFFER_TAIL], ebx ; ADJUST 'IN TO' POINTER TO REFLECT CHANGE 2233 00000CA9 28C0 <1> sub al, al ; TELL CALLER THAT OPERATION WAS SUCCESSFUL 2234 00000CAB EB02 <1> jmp short _K504 ; SUB INSTRUCTION ALSO RESETS CARRY FLAG 2235 <1> _K502: 2236 00000CAD B001 <1> mov al, 01h ; BUFFER FULL INDICATION 2237 <1> _K504: 2238 00000CAF FB <1> sti 2239 00000CB0 5E <1> pop esi ; RECOVER SI (esi) 2240 00000CB1 E967FFFFFF <1> jmp _KIO_EXIT ; RETURN TO CALLER WITH STATUS IN AL 2241 <1> 2242 <1> ;----- READ THE KEY TO FIGURE OUT WHAT TO DO ----- 2243 <1> _K1S: 2244 00000CB6 FA <1> cli ; 03/12/2014 2245 00000CB7 8B1D[E0670000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2246 00000CBD 3B1D[E4670000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2247 <1> ;jne short _K1U ; IF ANYTHING IN BUFFER SKIP INTERRUPT 2248 00000CC3 750F <1> jne short _k1x ; 03/12/2014 2249 <1> ; 2250 <1> ; 03/12/2014 2251 <1> ; 28/08/2014 2252 <1> ; PERFORM OTHER FUNCTION ?? here ! 2253 <1> ;; MOV AX, 9002h ; MOVE IN WAIT CODE & TYPE 2254 <1> ;; INT 15H ; PERFORM OTHER FUNCTION 2255 <1> _K1T: ; ASCII READ 2256 00000CC5 FB <1> sti ; INTERRUPTS BACK ON DURING LOOP 2257 00000CC6 90 <1> nop ; ALLOW AN INTERRUPT TO OCCUR 2258 <1> _K1U: 2259 00000CC7 FA <1> cli ; INTERRUPTS BACK OFF 2260 00000CC8 8B1D[E0670000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2261 00000CCE 3B1D[E4670000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2262 <1> _k1x: 2263 00000CD4 53 <1> push ebx ; SAVE ADDRESS 2264 00000CD5 9C <1> pushf ; SAVE FLAGS 2265 00000CD6 E8D4060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2266 00000CDB 8A1D[D5670000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2267 00000CE1 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2268 00000CE3 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2269 00000CE6 7406 <1> jz short _K1V ; IF NO CHANGE BYPASS UPDATE 2270 00000CE8 E86E060000 <1> call SND_LED1 2271 00000CED FA <1> cli ; DISABLE INTERRUPTS 2272 <1> _K1V: 2273 00000CEE 9D <1> popf ; RESTORE FLAGS 2274 00000CEF 5B <1> pop ebx ; RESTORE ADDRESS 2275 00000CF0 74D3 <1> je short _K1T ; LOOP UNTIL SOMETHING IN BUFFER 2276 <1> ; 2277 00000CF2 668B03 <1> mov ax, [ebx] ; GET SCAN CODE AND ASCII CODE 2278 00000CF5 E86F000000 <1> call _K4 ; MOVE POINTER TO NEXT POSITION 2279 00000CFA 891D[E0670000] <1> mov [BUFFER_HEAD], ebx ; STORE VALUE IN VARIABLE 2280 00000D00 C3 <1> retn ; RETURN 2281 <1> 2282 <1> ;----- READ THE KEY TO SEE IF ONE IS PRESENT ----- 2283 <1> _K2S: 2284 00000D01 FA <1> cli ; INTERRUPTS OFF 2285 00000D02 8B1D[E0670000] <1> mov ebx, [BUFFER_HEAD] ; GET HEAD POINTER 2286 00000D08 3B1D[E4670000] <1> cmp ebx, [BUFFER_TAIL] ; IF EQUAL (Z=1) THEN NOTHING THERE 2287 00000D0E 668B03 <1> mov ax, [ebx] 2288 00000D11 9C <1> pushf ; SAVE FLAGS 2289 <1> ;push ax ; SAVE CODE 2290 <1> ; 05/12/2021 2291 00000D12 50 <1> push eax 2292 00000D13 E897060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2293 00000D18 8A1D[D5670000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2294 00000D1E 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2295 00000D20 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2296 00000D23 7405 <1> jz short _K2T ; IF NO CHANGE BYPASS UPDATE 2297 00000D25 E81A060000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2298 <1> _K2T: 2299 <1> ;pop ax ; RESTORE CODE 2300 <1> ; 05/12/2021 2301 00000D2A 58 <1> pop eax 2302 00000D2B 9D <1> popf ; RESTORE FLAGS 2303 00000D2C FB <1> sti ; INTERRUPTS BACK ON 2304 00000D2D C3 <1> retn ; RETURN 2305 <1> 2306 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS ----- 2307 <1> _KIO_E_XLAT: 2308 00000D2E 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2309 00000D30 7506 <1> jne short _KIO_E_RET ; NO, PASS IT ON 2310 00000D32 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2311 00000D34 7402 <1> jz short _KIO_E_RET ; PASS THIS ON UNCHANGED 2312 00000D36 30C0 <1> xor al, al ; OTHERWISE SET AL = 0 2313 <1> _KIO_E_RET: 2314 00000D38 C3 <1> retn ; GO BACK 2315 <1> 2316 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS ----- 2317 <1> _KIO_S_XLAT: 2318 00000D39 80FCE0 <1> cmp ah, 0E0h ; IS IT KEYPAD ENTER OR / ? 2319 00000D3C 750F <1> jne short _KIO_S2 ; NO, CONTINUE 2320 00000D3E 3C0D <1> cmp al, 0Dh ; KEYPAD ENTER CODE? 2321 00000D40 7408 <1> je short _KIO_S1 ; YES, MASSAGE A BIT 2322 00000D42 3C0A <1> cmp al, 0Ah ; CTRL KEYPAD ENTER CODE? 2323 00000D44 7404 <1> je short _KIO_S1 ; YES, MASSAGE THE SAME 2324 00000D46 B435 <1> mov ah, 35h ; NO, MUST BE KEYPAD / 2325 <1> _kio_ret: ; 03/12/2014 2326 00000D48 F8 <1> clc 2327 00000D49 C3 <1> retn 2328 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2329 <1> _KIO_S1: 2330 00000D4A B41C <1> mov ah, 1Ch ; CONVERT TO COMPATIBLE OUTPUT 2331 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2332 00000D4C C3 <1> retn 2333 <1> _KIO_S2: 2334 00000D4D 80FC84 <1> cmp ah, 84h ; IS IT ONE OF EXTENDED ONES? 2335 00000D50 7715 <1> ja short _KIO_DIS ; YES, THROW AWAY AND GET ANOTHER CHAR 2336 00000D52 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2337 00000D54 7506 <1> jne short _KIO_S3 ; NO, TRY LAST TEST 2338 00000D56 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2339 00000D58 740C <1> jz short _KIO_USE ; PASS THIS ON UNCHANGED 2340 00000D5A EB0B <1> jmp short _KIO_DIS ; THROW AWAY THE REST 2341 <1> _KIO_S3: 2342 00000D5C 3CE0 <1> cmp al, 0E0h ; IS IT AN EXTENSION OF A PREVIOUS ONE? 2343 <1> ;jne short _KIO_USE ; NO, MUST BE A STANDARD CODE 2344 00000D5E 75E8 <1> jne short _kio_ret 2345 00000D60 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2346 00000D62 7402 <1> jz short _KIO_USE ; JUMP IF AH = 0 2347 00000D64 30C0 <1> xor al, al ; CONVERT TO COMPATIBLE OUTPUT 2348 <1> ;jmp short _KIO_USE ; PASS IT ON TO CALLER 2349 <1> _KIO_USE: 2350 <1> ;clc ; CLEAR CARRY TO INDICATE GOOD CODE 2351 00000D66 C3 <1> retn ; RETURN 2352 <1> _KIO_DIS: 2353 00000D67 F9 <1> stc ; SET CARRY TO INDICATE DISCARD CODE 2354 00000D68 C3 <1> retn ; RETURN 2355 <1> 2356 <1> ;----- INCREMENT BUFFER POINTER ROUTINE ----- 2357 <1> _K4: 2358 00000D69 43 <1> inc ebx 2359 00000D6A 43 <1> inc ebx ; MOVE TO NEXT WORD IN LIST 2360 00000D6B 3B1D[DC670000] <1> cmp ebx, [BUFFER_END] ; AT END OF BUFFER? 2361 <1> ;jne short _K5 ; NO, CONTINUE 2362 00000D71 7206 <1> jb short _K5 2363 00000D73 8B1D[D8670000] <1> mov ebx, [BUFFER_START] ; YES, RESET TO BUFFER BEGINNING 2364 <1> _K5: 2365 00000D79 C3 <1> retn 2366 <1> 2367 <1> ; 20/02/2015 2368 <1> ; 05/12/2014 2369 <1> ; 26/08/2014 2370 <1> ; KEYBOARD (HARDWARE) INTERRUPT - IRQ LEVEL 1 2371 <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014) 2372 <1> ; 2373 <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 2374 <1> ; rombios source code (06/10/1985) 2375 <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1) 2376 <1> 2377 <1> ;--------- 8042 COMMANDS ------------------------------------------------------- 2378 <1> ENA_KBD equ 0AEh ; ENABLE KEYBOARD COMMAND 2379 <1> DIS_KBD equ 0ADh ; DISABLE KEYBOARD COMMAND 2380 <1> SHUT_CMD equ 0FEh ; CAUSE A SHUTDOWN COMMAND 2381 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2382 <1> STATUS_PORT equ 064h ; 8042 STATUS PORT 2383 <1> INPT_BUF_FULL equ 00000010b ; 1 = +INPUT BUFFER FULL 2384 <1> PORT_A equ 060h ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2385 <1> ;---------- 8042 KEYBOARD RESPONSE --------------------------------------------- 2386 <1> KB_ACK equ 0FAh ; ACKNOWLEDGE PROM TRANSMISSION 2387 <1> KB_RESEND equ 0FEh ; RESEND REQUEST 2388 <1> KB_OVER_RUN equ 0FFh ; OVER RUN SCAN CODE 2389 <1> ;---------- KEYBOARD/LED COMMANDS ---------------------------------------------- 2390 <1> KB_ENABLE equ 0F4h ; KEYBOARD ENABLE 2391 <1> LED_CMD equ 0EDh ; LED WRITE COMMAND 2392 <1> KB_TYPA_RD equ 0F3h ; TYPAMATIC RATE/DELAY COMMAND 2393 <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------ 2394 <1> NUM_KEY equ 69 ; SCAN CODE FOR NUMBER LOCK KEY 2395 <1> SCROLL_KEY equ 70 ; SCAN CODE FOR SCROLL LOCK KEY 2396 <1> ALT_KEY equ 56 ; SCAN CODE FOR ALTERNATE SHIFT KEY 2397 <1> CTL_KEY equ 29 ; SCAN CODE FOR CONTROL KEY 2398 <1> CAPS_KEY equ 58 ; SCAN CODE FOR SHIFT LOCK KEY 2399 <1> DEL_KEY equ 83 ; SCAN CODE FOR DELETE KEY 2400 <1> INS_KEY equ 82 ; SCAN CODE FOR INSERT KEY 2401 <1> LEFT_KEY equ 42 ; SCAN CODE FOR LEFT SHIFT 2402 <1> RIGHT_KEY equ 54 ; SCAN CODE FOR RIGHT SHIFT 2403 <1> SYS_KEY equ 84 ; SCAN CODE FOR SYSTEM KEY 2404 <1> ;---------- ENHANCED KEYBOARD SCAN CODES --------------------------------------- 2405 <1> ID_1 equ 0ABh ; 1ST ID CHARACTER FOR KBX 2406 <1> ID_2 equ 041h ; 2ND ID CHARACTER FOR KBX 2407 <1> ID_2A equ 054h ; ALTERNATE 2ND ID CHARACTER FOR KBX 2408 <1> F11_M equ 87 ; F11 KEY MAKE 2409 <1> F12_M equ 88 ; F12 KEY MAKE 2410 <1> MC_E0 equ 224 ; GENERAL MARKER CODE 2411 <1> MC_E1 equ 225 ; PAUSE KEY MARKER CODE 2412 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG---------------------------------------- 2413 <1> RIGHT_SHIFT equ 00000001b ; RIGHT SHIFT KEY DEPRESSED 2414 <1> LEFT_SHIFT equ 00000010b ; LEFT SHIFT KEY DEPRESSED 2415 <1> CTL_SHIFT equ 00000100b ; CONTROL SHIFT KEY DEPRESSED 2416 <1> ALT_SHIFT equ 00001000b ; ALTERNATE SHIFT KEY DEPRESSED 2417 <1> SCROLL_STATE equ 00010000b ; SCROLL LOCK STATE IS ACTIVE 2418 <1> NUM_STATE equ 00100000b ; NUM LOCK STATE IS ACTIVE 2419 <1> CAPS_STATE equ 01000000b ; CAPS LOCK STATE IS ACTIVE 2420 <1> INS_STATE equ 10000000b ; INSERT STATE IS ACTIVE 2421 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG_1 ------------------------------------- 2422 <1> L_CTL_SHIFT equ 00000001b ; LEFT CTL KEY DOWN 2423 <1> L_ALT_SHIFT equ 00000010b ; LEFT ALT KEY DOWN 2424 <1> SYS_SHIFT equ 00000100b ; SYSTEM KEY DEPRESSED AND HELD 2425 <1> HOLD_STATE equ 00001000b ; SUSPEND KEY HAS BEEN TOGGLED 2426 <1> SCROLL_SHIFT equ 00010000b ; SCROLL LOCK KEY IS DEPRESSED 2427 <1> NUM_SHIFT equ 00100000b ; NUM LOCK KEY IS DEPRESSED 2428 <1> CAPS_SHIFT equ 01000000b ; CAPS LOCK KEY IS DEPRE55ED 2429 <1> INS_SHIFT equ 10000000b ; INSERT KEY IS DEPRESSED 2430 <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 ----------------------------------- 2431 <1> KB_LEDS equ 00000111b ; KEYBOARD LED STATE BITS 2432 <1> ; equ 00000001b ; SCROLL LOCK INDICATOR 2433 <1> ; equ 00000010b ; NUM LOCK INDICATOR 2434 <1> ; equ 00000100b ; CAPS LOCK INDICATOR 2435 <1> ; equ 00001000b ; RESERVED (MUST BE ZERO) 2436 <1> KB_FA equ 00010000b ; ACKNOWLEDGMENT RECEIVED 2437 <1> KB_FE equ 00100000b ; RESEND RECEIVED FLAG 2438 <1> KB_PR_LED equ 01000000b ; MODE INDICATOR UPDATE 2439 <1> KB_ERR equ 10000000b ; KEYBOARD TRANSMIT ERROR FLAG 2440 <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 ----------------------------------- 2441 <1> LC_E1 equ 00000001b ; LAST CODE WAS THE E1 HIDDEN CODE 2442 <1> LC_E0 equ 00000010b ; LAST CODE WAS THE E0 HIDDEN CODE 2443 <1> R_CTL_SHIFT equ 00000100b ; RIGHT CTL KEY DOWN 2444 <1> R_ALT_SHIFT equ 00001000b ; RIGHT ALT KEY DOWN 2445 <1> GRAPH_ON equ 00001000b ; ALT GRAPHICS KEY DOWN (WT ONLY) 2446 <1> KBX equ 00010000b ; ENHANCED KEYBOARD INSTALLED 2447 <1> SET_NUM_LK equ 00100000b ; FORCE NUM LOCK IF READ ID AND KBX 2448 <1> LC_AB equ 01000000b ; LAST CHARACTER WAS FIRST ID CHARACTER 2449 <1> RD_ID equ 10000000b ; DOING A READ ID (MUST BE BIT0) 2450 <1> ; 2451 <1> ;----------- INTERRUPT EQUATES ------------------------------------------------- 2452 <1> EOI equ 020h ; END OF INTERRUPT COMMAND TO 8259 2453 <1> INTA00 equ 020h ; 8259 PORT 2454 <1> 2455 <1> 2456 <1> kb_int: 2457 <1> 2458 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2459 <1> ; 17/10/2015 ('ctrlbrk') 2460 <1> ; 05/12/2014 2461 <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2462 <1> ; instead of pc-at bios - 1985-) 2463 <1> ; 26/08/2014 2464 <1> ; 2465 <1> ; 03/06/86 KEYBOARD BIOS 2466 <1> ; 2467 <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------ 2468 <1> ; ; 2469 <1> ; KEYBOARD INTERRUPT ROUTINE ; 2470 <1> ; ; 2471 <1> ;-------------------------------------------------------------------------------- 2472 <1> 2473 <1> KB_INT_1: 2474 00000D7A FB <1> sti ; ENABLE INTERRUPTS 2475 <1> ;push ebp 2476 00000D7B 50 <1> push eax 2477 00000D7C 53 <1> push ebx 2478 00000D7D 51 <1> push ecx 2479 00000D7E 52 <1> push edx 2480 00000D7F 56 <1> push esi 2481 00000D80 57 <1> push edi 2482 00000D81 1E <1> push ds 2483 00000D82 06 <1> push es 2484 00000D83 FC <1> cld ; FORWARD DIRECTION 2485 00000D84 66B81000 <1> mov ax, KDATA 2486 00000D88 8ED8 <1> mov ds, ax 2487 00000D8A 8EC0 <1> mov es, ax 2488 <1> ; 2489 <1> ;----- WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED 2490 00000D8C B0AD <1> mov al, DIS_KBD ; DISABLE THE KEYBOARD COMMAND 2491 00000D8E E856050000 <1> call SHIP_IT ; EXECUTE DISABLE 2492 00000D93 FA <1> cli ; DISABLE INTERRUPTS 2493 00000D94 B900000100 <1> mov ecx, 10000h ; SET MAXIMUM TIMEOUT 2494 <1> KB_INT_01: 2495 00000D99 E464 <1> in al, STATUS_PORT ; READ ADAPTER STATUS 2496 00000D9B A802 <1> test al, INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT 2497 00000D9D E0FA <1> loopnz KB_INT_01 ; WAIT FOR COMMAND TO BE ACCEPTED 2498 <1> ; 2499 <1> ;----- READ CHARACTER FROM KEYBOARD INTERFACE 2500 00000D9F E460 <1> in al, PORT_A ; READ IN THE CHARACTER 2501 <1> ; 2502 <1> ;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 2503 <1> ;MOV AH, 04FH ; SYSTEM INTERCEPT - KEY CODE FUNCTION 2504 <1> ;STC ; SET CY=1 (IN CASE OF IRET) 2505 <1> ;INT 15H ; CASETTE CALL (AL)=KEY SCAN CODE 2506 <1> ; ; RETURNS CY=1 FOR INVALID FUNCTION 2507 <1> ;JC KB_INT_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) 2508 <1> ;JMP K26 ; EXIT IF SYSTEM HANDLES SCAN CODE 2509 <1> ; ; EXÝT HANDLES HARDWARE EOI AND ENABLE 2510 <1> ; 2511 <1> ;----- CHECK FOR A RESEND COMMAND TO KEYBOARD 2512 <1> KB_INT_02: ; (AL)= SCAN CODE 2513 00000DA1 FB <1> sti ; ENABLE INTERRUPTS AGAIN 2514 00000DA2 3CFE <1> cmp al, KB_RESEND ; IS THE INPUT A RESEND 2515 00000DA4 7411 <1> je short KB_INT_4 ; GO IF RESEND 2516 <1> ; 2517 <1> ;----- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD 2518 00000DA6 3CFA <1> cmp al, KB_ACK ; IS THE INPUT AN ACKNOWLEDGE 2519 00000DA8 751A <1> jne short KB_INT_2 ; GO IF NOT 2520 <1> ; 2521 <1> ;----- A COMMAND TO THE KEYBOARD WAS ISSUED 2522 00000DAA FA <1> cli ; DISABLE INTERRUPTS 2523 00000DAB 800D[D5670000]10 <1> or byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED 2524 00000DB2 E963020000 <1> jmp K26 ; RETURN IF NOT (ACK RETURNED FOR DATA) 2525 <1> ; 2526 <1> ;----- RESEND THE LAST BYTE 2527 <1> KB_INT_4: 2528 00000DB7 FA <1> cli ; DISABLE INTERRUPTS 2529 00000DB8 800D[D5670000]20 <1> or byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED 2530 00000DBF E956020000 <1> jmp K26 ; RETURN IF NOT ACK RETURNED FOR DATA) 2531 <1> ; 2532 <1> ;----- UPDATE MODE INDICATORS IF CHANGE IN STATE 2533 <1> KB_INT_2: 2534 <1> ;push ax ; SAVE DATA IN 2535 <1> ; 05/12/2021 2536 00000DC4 50 <1> push eax 2537 00000DC5 E8E5050000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2538 00000DCA 8A1D[D5670000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2539 00000DD0 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2540 00000DD2 80E307 <1> and bl, KB_LEDS ; ISOLATE INDICATOR BITS 2541 00000DD5 7405 <1> jz short UP0 ; IF NO CHANGE BYPASS UPDATE 2542 00000DD7 E868050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2543 <1> UP0: 2544 <1> ;pop ax ; RESTORE DATA IN 2545 <1> ; 05/12/2021 2546 00000DDC 58 <1> pop eax 2547 <1> ;------------------------------------------------------------------------ 2548 <1> ; START OF KEY PROCESSING ; 2549 <1> ;------------------------------------------------------------------------ 2550 00000DDD 88C4 <1> mov ah, al ; SAVE SCAN CODE IN AH ALSO 2551 <1> ; 2552 <1> ;----- TEST FOR OVERRUN SCAN CODE FROM KEYBOARD 2553 00000DDF 3CFF <1> cmp al, KB_OVER_RUN ; IS THIS AN OVERRUN CHAR 2554 <1> ;je K62 ; BUFFER_FULL_BEEP 2555 <1> ; 05/12/2021 2556 00000DE1 7505 <1> jne short K16 2557 00000DE3 E9ED040000 <1> jmp K62 2558 <1> K16: 2559 00000DE8 8A3D[D6670000] <1> mov bh, [KB_FLAG_3] ; LOAD FLAGS FOR TESTING 2560 <1> ; 2561 <1> ;----- TEST TO SEE IF A READ_ID IS IN PROGRESS 2562 00000DEE F6C7C0 <1> test bh, RD_ID+LC_AB ; ARE WE DOING A READ ID? 2563 00000DF1 7442 <1> jz short NOT_ID ; CONTINUE IF NOT 2564 00000DF3 7914 <1> jns short TST_ID_2 ; IS THE RD_ID FLAG ON? 2565 00000DF5 3CAB <1> cmp al, ID_1 ; IS THIS THE 1ST ID CHARACTER? 2566 00000DF7 7507 <1> jne short RST_RD_ID 2567 00000DF9 800D[D6670000]40 <1> or byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK 2568 <1> RST_RD_ID: 2569 00000E00 8025[D6670000]7F <1> and byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG 2570 00000E07 EB27 <1> jmp short ID_EX ; AND EXIT 2571 <1> ; 05/12/2021 2572 <1> ;jmp K26 2573 <1> ; 2574 <1> TST_ID_2: 2575 00000E09 8025[D6670000]BF <1> and byte [KB_FLAG_3], ~LC_AB ; RESET FLAG 2576 00000E10 3C54 <1> cmp al, ID_2A ; IS THIS THE 2ND ID CHARACTER? 2577 00000E12 7415 <1> je short KX_BIT ; JUMP IF SO 2578 00000E14 3C41 <1> cmp al, ID_2 ; IS THIS THE 2ND ID CHARACTER? 2579 00000E16 7518 <1> jne short ID_EX ; LEAVE IF NOT 2580 <1> ; 05/12/2021 2581 <1> ;jne K26 2582 <1> ; 2583 <1> ;----- A READ ID SAID THAT IT WAS ENHANCED KEYBOARD 2584 00000E18 F6C720 <1> test bh, SET_NUM_LK ; SHOULD WE SET NUM LOCK? 2585 00000E1B 740C <1> jz short KX_BIT ; EXIT IF NOT 2586 00000E1D 800D[D3670000]20 <1> or byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON 2587 00000E24 E81B050000 <1> call SND_LED ; GO SET THE NUM LOCK INDICATOR 2588 <1> KX_BIT: 2589 00000E29 800D[D6670000]10 <1> or byte [KB_FLAG_3], KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND 2590 00000E30 E9E5010000 <1> ID_EX: jmp K26 ; EXIT 2591 <1> ; 2592 <1> NOT_ID: 2593 00000E35 3CE0 <1> cmp al, MC_E0 ; IS THIS THE GENERAL MARKER CODE? 2594 00000E37 750E <1> jne short TEST_E1 2595 00000E39 800D[D6670000]12 <1> or byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND 2596 00000E40 EB10 <1> jmp short EXIT ; THROW AWAY THIS CODE 2597 <1> ; 05/12/2021 2598 00000E42 E9DA010000 <1> jmp K26A 2599 <1> TEST_E1: 2600 00000E47 3CE1 <1> cmp al, MC_E1 ; IS THIS THE PAUSE KEY? 2601 00000E49 750C <1> jne short NOT_HC 2602 00000E4B 800D[D6670000]11 <1> or byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND 2603 00000E52 E9CA010000 <1> EXIT: jmp K26A ; THROW AWAY THIS CODE 2604 <1> ; 2605 <1> NOT_HC: 2606 00000E57 247F <1> and al, 07Fh ; TURN OFF THE BREAK BIT 2607 00000E59 F6C702 <1> test bh, LC_E0 ; LAST CODE THE E0 MARKER CODE 2608 00000E5C 740D <1> jz short NOT_LC_E0 ; JUMP IF NOT 2609 <1> ; 2610 00000E5E BF[BE660000] <1> mov edi, _K6+6 ; IS THIS A SHIFT KEY? 2611 00000E63 AE <1> scasb 2612 <1> ;je K26 ; K16B ; YES, THROW AWAY & RESET FLAG 2613 <1> ; 05/12/2021 2614 00000E64 7458 <1> je short K16B 2615 00000E66 AE <1> scasb 2616 00000E67 756A <1> jne short K16A ; NO, CONTINUE KEY PROCESSING 2617 00000E69 EB53 <1> jmp short K16B ; YES, THROW AWAY & RESET FLAG 2618 <1> ; 05/12/2021 2619 <1> ;jmp K26 2620 <1> ; 2621 <1> NOT_LC_E0: 2622 00000E6B F6C701 <1> test bh, LC_E1 ; LAST CODE THE E1 MARKER CODE? 2623 00000E6E 7425 <1> jz short T_SYS_KEY ; JUMP IF NOT 2624 00000E70 B904000000 <1> mov ecx, 4 ; LENGHT OF SEARCH 2625 00000E75 BF[BC660000] <1> mov edi, _K6+4 ; IS THIS AN ALT, CTL, OR SHIFT? 2626 00000E7A F2AE <1> repne scasb ; CHECK IT 2627 00000E7C 74D4 <1> je short EXIT ; THROW AWAY IF SO 2628 <1> ; 05/12/2021 2629 <1> ;je K26A 2630 <1> ; 2631 00000E7E 3C45 <1> cmp al, NUM_KEY ; IS IT THE PAUSE KEY? 2632 00000E80 753C <1> jne short K16B ; NO, THROW AWAY & RESET FLAG 2633 <1> ; 05/12/2021 2634 <1> ;jne K26 2635 00000E82 F6C480 <1> test ah, 80h ; YES, IS IT THE BREAK OF THE KEY? 2636 00000E85 7537 <1> jnz short K16B ; YES, THROW THIS AWAY, TOO 2637 <1> ; 05/12/2021 2638 <1> ;jnz K26 2639 <1> ; 20/02/2015 2640 00000E87 F605[D4670000]08 <1> test byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY? 2641 00000E8E 752E <1> jnz short K16B ; YES, THROW AWAY 2642 <1> ; 05/12/2021 2643 <1> ;jnz K26 2644 00000E90 E9D6020000 <1> jmp K39P ; NO, THIS IS THE REAL PAUSE STATE 2645 <1> ; 2646 <1> ;----- TEST FOR SYSTEM KEY 2647 <1> T_SYS_KEY: 2648 00000E95 3C54 <1> cmp al, SYS_KEY ; IS IT THE SYSTEM KEY? 2649 00000E97 753A <1> jnz short K16A ; CONTINUE IF NOT 2650 <1> ; 2651 00000E99 F6C480 <1> test ah, 80h ; CHECK IF THIS A BREAK CODE 2652 00000E9C 7525 <1> jnz short K16C ; DO NOT TOUCH SYSTEM INDICATOR IF TRUE 2653 <1> ; 2654 00000E9E F605[D4670000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 2655 00000EA5 7517 <1> jnz short K16B ; IF YES, DO NOT PROCESS SYSTEM INDICATOR 2656 <1> ;jnz K26 2657 <1> ; 2658 00000EA7 800D[D4670000]04 <1> or byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED 2659 00000EAE B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2660 00000EB0 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2661 <1> ; INTERRUPT-RETURN-NO-EOI 2662 00000EB2 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2663 00000EB4 E830040000 <1> call SHIP_IT ; EXECUTE ENABLE 2664 <1> ; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!! 2665 <1> ;MOV AL, 8500H ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY 2666 <1> ;STI ; MAKE SURE INTERRUPTS ENABLED 2667 <1> ;INT 15H ; USER INTERRUPT 2668 00000EB9 E96F010000 <1> jmp K27A ; END PROCESSING 2669 <1> ; 2670 00000EBE E957010000 <1> K16B: jmp K26 ; IGNORE SYSTEM KEY 2671 <1> ; 2672 <1> K16C: 2673 00000EC3 8025[D4670000]FB <1> and byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN 2674 00000ECA B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2675 00000ECC E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2676 <1> ; INTERRUPT-RETURN-NO-EOI 2677 <1> ;MOV AL, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2678 <1> ;CALL SHIP_IT ; EXECUTE ENABLE 2679 <1> ; 2680 <1> ;MOV AX, 8501H ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY 2681 <1> ;STI ; MAKE SURE INTERRUPTS ENABLED 2682 <1> ;INT 15H ; USER INTERRUPT 2683 <1> ;JMP K27A ; INGONRE SYSTEM KEY 2684 <1> ; 2685 00000ECE E953010000 <1> jmp K27 ; IGNORE SYSTEM KEY 2686 <1> ; 2687 <1> ;----- TEST FOR SHIFT KEYS 2688 <1> K16A: 2689 00000ED3 8A1D[D3670000] <1> mov bl, [KB_FLAG] ; PUT STATE FLAGS IN BL 2690 00000ED9 BF[B8660000] <1> mov edi, _K6 ; SHIFT KEY TABLE offset 2691 00000EDE B908000000 <1> mov ecx, _K6L ; LENGTH 2692 00000EE3 F2AE <1> repne scasb ; LOOK THROUGH THE TABLE FOR A MATCH 2693 00000EE5 88E0 <1> mov al, ah ; RECOVER SCAN CODE 2694 <1> ;jne K25 ; IF NO MATCH, THEN SHIFT NOT FOUND 2695 <1> ; 05/12/2021 2696 00000EE7 7405 <1> je short K17 2697 00000EE9 E914010000 <1> jmp K25 2698 <1> ; 2699 <1> ;------ SHIFT KEY FOUND 2700 <1> K17: 2701 00000EEE 81EF[B9660000] <1> sub edi, _K6+1 ; ADJUST PTR TO SCAN CODE MATCH 2702 00000EF4 8AA7[C0660000] <1> mov ah, [edi+_K7] ; GET MASK INTO AH 2703 00000EFA B102 <1> mov cl, 2 ; SETUP COUNT FOR FLAG SHIFTS 2704 00000EFC A880 <1> test al, 80h ; TEST FOR BREAK KEY 2705 <1> ;jnz K23 ; JUMP OF BREAK 2706 <1> ; 05/12/2021 2707 00000EFE 7405 <1> jz short K17C 2708 00000F00 E999000000 <1> jmp K23 2709 <1> ; 2710 <1> ;----- SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE 2711 <1> K17C: 2712 00000F05 80FC10 <1> cmp ah, SCROLL_SHIFT 2713 00000F08 732C <1> jae short K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY 2714 <1> ; 2715 <1> ;----- PLAIN SHIFT KEY, SET SHIFT ON 2716 00000F0A 0825[D3670000] <1> or [KB_FLAG], ah ; TURN ON SHIFT BIT 2717 00000F10 A80C <1> test al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL? 2718 00000F12 7505 <1> jnz short K17D ; YES, MORE FLAGS TO SET 2719 <1> ;jz K26 ; NO, INTERRUPT RETURN 2720 <1> ; 05/12/2021 2721 00000F14 E901010000 <1> jmp K26 2722 <1> K17D: 2723 00000F19 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF NEW KEYS? 2724 00000F1C 740B <1> jz short K17E ; NO, JUMP 2725 00000F1E 0825[D6670000] <1> or [KB_FLAG_3], ah ; SET BITS FOR RIGHT CTRL, ALT 2726 00000F24 E9F1000000 <1> jmp K26 ; INTERRUPT RETURN 2727 <1> K17E: 2728 00000F29 D2EC <1> shr ah, cl ; MOVE FLAG BITS TWO POSITIONS 2729 00000F2B 0825[D4670000] <1> or [KB_FLAG_1], ah ; SET BITS FOR LEFT CTRL, ALT 2730 00000F31 E9E4000000 <1> jmp K26 2731 <1> ; 2732 <1> ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT 2733 <1> K18: ; SHIFT-TOGGLE 2734 00000F36 F6C304 <1> test bl, CTL_SHIFT ; CHECK CTL SHIFT STATE 2735 00000F39 7405 <1> jz short K18A ; JUMP IF NOT CTL STATE 2736 <1> ;jnz K25 ; JUMP IF CTL STATE 2737 <1> ; 05/12/2021 2738 00000F3B E9C2000000 <1> jmp K25 2739 <1> K18A: 2740 00000F40 3C52 <1> cmp al, INS_KEY ; CHECK FOR INSERT KEY 2741 00000F42 7525 <1> jne short K22 ; JUMP IF NOT INSERT KEY 2742 00000F44 F6C308 <1> test bl, ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT 2743 00000F47 7405 <1> jz short K18B ; JUMP IF NOT ALTERNATE SHIFT 2744 <1> ;jnz K25 ; JUMP IF ALTERNATE SHIFT 2745 <1> ; 05/12/2021 2746 00000F49 E9B4000000 <1> jmp K25 2747 <1> K18B: 2748 00000F4E F6C702 <1> test bh, LC_E0 ;20/02/2015 ; IS THIS NEW INSERT KEY? 2749 00000F51 7516 <1> jnz short K22 ; YES, THIS ONE'S NEVER A '0' 2750 <1> K19: 2751 00000F53 F6C320 <1> test bl, NUM_STATE ; CHECK FOR BASE STATE 2752 00000F56 750C <1> jnz short K21 ; JUMP IF NUM LOCK IS ON 2753 00000F58 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE 2754 00000F5B 740C <1> jz short K22 ; JUMP IF BASE STATE 2755 <1> K20: ; NUMERIC ZERO, NOT INSERT KEY 2756 00000F5D 88C4 <1> mov ah, al ; PUT SCAN CODE BACK IN AH 2757 00000F5F E99E000000 <1> jmp K25 ; NUMERAL '0', STNDRD. PROCESSING 2758 <1> K21: ; MIGHT BE NUMERIC 2759 00000F64 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 2760 00000F67 74F4 <1> jz short K20 ; IS NUMERIC, STD. PROC. 2761 <1> ; 2762 <1> K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT 2763 00000F69 8425[D4670000] <1> test ah, [KB_FLAG_1] ; IS KEY ALREADY DEPRESSED 2764 <1> ;jnz K26 2765 <1> ; 05/12/2021 2766 00000F6F 7405 <1> jz short K22A 2767 00000F71 E9A4000000 <1> jmp K26 ; JUMP IF KEY ALREADY DEPRESSED 2768 <1> K22A: 2769 00000F76 0825[D4670000] <1> or [KB_FLAG_1], ah ; INDICATE THAT THE KEY IS DEPRESSED 2770 00000F7C 3025[D3670000] <1> xor [KB_FLAG], ah ; TOGGLE THE SHIFT STATE 2771 <1> ; 2772 <1> ;----- TOGGLE LED IF CAPS, NUM OR SCROLL KEY DEPRESSED 2773 00000F82 F6C470 <1> test ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? 2774 00000F85 7407 <1> jz short K22B ; GO IF NOT 2775 <1> ; 2776 <1> ; 05/12/2021 2777 <1> ;push ax ; SAVE SCAN CODE AND SHIFT MASK 2778 00000F87 50 <1> push eax 2779 00000F88 E8B7030000 <1> call SND_LED ; GO TURN MODE INDICATORS ON 2780 <1> ;pop ax ; RESTORE SCAN CODE 2781 00000F8D 58 <1> pop eax 2782 <1> K22B: 2783 00000F8E 3C52 <1> cmp al, INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY 2784 <1> ;jne K26 ; JUMP IF NOT INSERT KEY 2785 <1> ; 05/12/2021 2786 00000F90 7405 <1> je short K22C 2787 00000F92 E983000000 <1> jmp K26 ; JUMP IF NOT INSERT KEY 2788 <1> K22C: 2789 00000F97 88C4 <1> mov ah, al ; SCAN CODE IN BOTH HALVES OF AX 2790 00000F99 E999000000 <1> jmp K28 ; FLAGS UPDATED, PROC. FOR BUFFER 2791 <1> ; 2792 <1> ;----- BREAK SHIFT FOUND 2793 <1> K23: ; BREAK-SHIFT-FOUND 2794 00000F9E 80FC10 <1> cmp ah, SCROLL_SHIFT ; IS THIS A TOGGLE KEY 2795 00000FA1 F6D4 <1> not ah ; INVERT MASK 2796 00000FA3 7355 <1> jae short K24 ; YES, HANDLE BREAK TOGGLE 2797 00000FA5 2025[D3670000] <1> and [KB_FLAG], ah ; TURN OFF SHIFT BIT 2798 00000FAB 80FCFB <1> cmp ah, ~CTL_SHIFT ; IS THIS ALT OR CTL? 2799 00000FAE 7730 <1> ja short K23D ; NO, ALL DONE 2800 <1> ; 2801 00000FB0 F6C702 <1> test bh, LC_E0 ; 2ND ALT OR CTL? 2802 00000FB3 7408 <1> jz short K23A ; NO, HANSLE NORMALLY 2803 00000FB5 2025[D6670000] <1> and [KB_FLAG_3], ah ; RESET BIT FOR RIGHT ALT OR CTL 2804 00000FBB EB08 <1> jmp short K23B ; CONTINUE 2805 <1> K23A: 2806 00000FBD D2FC <1> sar ah, cl ; MOVE THE MASK BIT TWO POSITIONS 2807 00000FBF 2025[D4670000] <1> and [KB_FLAG_1], ah ; RESET BIT FOR LEFT ALT AND CTL 2808 <1> K23B: 2809 00000FC5 88C4 <1> mov ah, al ; SAVE SCAN CODE 2810 00000FC7 A0[D6670000] <1> mov al, [KB_FLAG_3] ; GET RIGHT ALT & CTRL FLAGS 2811 00000FCC D2E8 <1> shr al, cl ; MOVE TO BITS 1 & 0 2812 00000FCE 0A05[D4670000] <1> or al, [KB_FLAG_1] ; PUT IN LEFT ALÞT & CTL FLAGS 2813 00000FD4 D2E0 <1> shl al, cl ; MOVE BACK TO BITS 3 & 2 2814 00000FD6 240C <1> and al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE 2815 00000FD8 0805[D3670000] <1> or [KB_FLAG], al ; PUT RESULT IN THE REAL FLAGS 2816 00000FDE 88E0 <1> mov al, ah 2817 <1> K23D: 2818 00000FE0 3CB8 <1> cmp al, ALT_KEY+80h ; IS THIS ALTERNATE SHIFT RELEASE 2819 00000FE2 7536 <1> jne short K26 ; INTERRUPT RETURN 2820 <1> ; 2821 <1> ;----- ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER 2822 00000FE4 A0[D7670000] <1> mov al, [ALT_INPUT] 2823 00000FE9 B400 <1> mov ah, 0 ; SCAN CODE OF 0 2824 00000FEB 8825[D7670000] <1> mov [ALT_INPUT], ah ; ZERO OUT THE FIELD 2825 00000FF1 3C00 <1> cmp al, 0 ; WAS THE INPUT = 0? 2826 00000FF3 7425 <1> je short K26 ; INTERRUPT_RETURN 2827 00000FF5 E9B8020000 <1> jmp K61 ; IT WASN'T, SO PUT IN BUFFER 2828 <1> ; 2829 <1> K24: ; BREAK-TOGGLE 2830 00000FFA 2025[D4670000] <1> and [KB_FLAG_1], ah ; INDICATE NO LONGER DEPRESSED 2831 00001000 EB18 <1> jmp short K26 ; INTERRUPT_RETURN 2832 <1> ; 2833 <1> ;----- TEST FOR HOLD STATE 2834 <1> ; AL, AH = SCAN CODE 2835 <1> K25: ; NO-SHIFT-FOUND 2836 00001002 3C80 <1> cmp al, 80h ; TEST FOR BREAK KEY 2837 00001004 7314 <1> jae short K26 ; NOTHING FOR BREAK CHARS FROM HERE ON 2838 00001006 F605[D4670000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE 2839 0000100D 7428 <1> jz short K28 ; BRANCH AROUND TEST IF NOT 2840 0000100F 3C45 <1> cmp al, NUM_KEY 2841 00001011 7407 <1> je short K26 ; CAN'T END HOLD ON NUM_LOCK 2842 00001013 8025[D4670000]F7 <1> and byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT 2843 <1> ; 2844 <1> K26: 2845 0000101A 8025[D6670000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 2846 <1> K26A: ; INTERRUPT-RETURN 2847 00001021 FA <1> cli ; TURN OFF INTERRUPTS 2848 00001022 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2849 00001024 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2850 <1> K27: ; INTERRUPT-RETURN-NO-EOI 2851 00001026 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2852 00001028 E8BC020000 <1> call SHIP_IT ; EXECUTE ENABLE 2853 <1> K27A: 2854 0000102D FA <1> cli ; DISABLE INTERRUPTS 2855 0000102E 07 <1> pop es ; RESTORE REGISTERS 2856 0000102F 1F <1> pop ds 2857 00001030 5F <1> pop edi 2858 00001031 5E <1> pop esi 2859 00001032 5A <1> pop edx 2860 00001033 59 <1> pop ecx 2861 00001034 5B <1> pop ebx 2862 00001035 58 <1> pop eax 2863 <1> ;pop ebp 2864 00001036 CF <1> iret ; RETURN 2865 <1> 2866 <1> ;----- NOT IN HOLD STATE 2867 <1> K28: ; NO-HOLD-STATE 2868 00001037 3C58 <1> cmp al, 88 ; TEST FOR OUT-OF-RANGE SCAN CODES 2869 00001039 77DF <1> ja short K26 ; IGNORE IF OUT-OF-RANGE 2870 <1> ; 2871 0000103B F6C308 <1> test bl, ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT 2872 0000103E 740E <1> jz short K28A ; IF NOT ALTERNATE 2873 <1> ; 05/12/2021 2874 <1> ;jz K38 2875 <1> ; 2876 00001040 F6C710 <1> test bh, KBX ; IS THIS THE ENCHANCED KEYBOARD? 2877 00001043 740E <1> jz short K29 ; NO, ALT STATE IS REAL 2878 <1> ; 28/02/2015 2879 00001045 F605[D4670000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN? 2880 0000104C 7405 <1> jz short K29 ; NO, ALT STATE IS REAL 2881 <1> ; 05/12/2021 2882 <1> ;jnz K38 ; YES, THIS IS PHONY ALT STATE 2883 <1> ; ; DUE TO PRESSING SYSREQ 2884 0000104E E9D1000000 <1> K28A: jmp K38 2885 <1> ; 2886 <1> ;----- TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) 2887 <1> K29: ; TEST-RESET 2888 00001053 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO? 2889 00001056 740B <1> jz short K31 ; NO_RESET 2890 00001058 3C53 <1> cmp al, DEL_KEY ; CTL-ALT STATE, TEST FOR DELETE KEY 2891 0000105A 7507 <1> jne short K31 ; NO_RESET, IGNORE 2892 <1> ; 2893 <1> ;----- CTL-ALT-DEL HAS BEEN FOUND 2894 <1> ; 26/08/2014 2895 <1> cpu_reset: 2896 <1> ; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN) 2897 <1> ; Send FEh (system reset command) to the keyboard controller. 2898 0000105C B0FE <1> mov al, SHUT_CMD ; SHUTDOWN COMMAND 2899 0000105E E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROL PORT 2900 <1> khere: 2901 00001060 F4 <1> hlt ; WAIT FOR 80286 RESET 2902 00001061 EBFD <1> jmp short khere ; INSURE HALT 2903 <1> 2904 <1> ; 2905 <1> ;----- IN ALTERNATE SHIFT, RESET NOT FOUND 2906 <1> K31: ; NO-RESET 2907 00001063 3C39 <1> cmp al, 57 ; TEST FOR SPACE KEY 2908 00001065 7507 <1> jne short K311 ; NOT THERE 2909 00001067 B020 <1> mov al, ' ' ; SET SPACE CHAR 2910 00001069 E936020000 <1> jmp K57 ; BUFFER_FILL 2911 <1> K311: 2912 0000106E 3C0F <1> cmp al, 15 ; TEST FOR TAB KEY 2913 00001070 7509 <1> jne short K312 ; NOT THERE 2914 00001072 66B800A5 <1> mov ax, 0A500h ; SET SPECIAL CODE FOR ALT-TAB 2915 00001076 E929020000 <1> jmp K57 ; BUFFER_FILL 2916 <1> K312: 2917 0000107B 3C4A <1> cmp al, 74 ; TEST FOR KEY PAD - 2918 0000107D 7471 <1> je short K37B ; GO PROCESS 2919 0000107F 3C4E <1> cmp al, 78 ; TEST FOR KEY PAD + 2920 00001081 746D <1> je short K37B ; GO PROCESS 2921 <1> ; 2922 <1> ;----- LOOK FOR KEY PAD ENTRY 2923 <1> K32: ; ALT-KEY-PAD 2924 00001083 BF[94660000] <1> mov edi, K30 ; ALT-INPUT-TABLE offset 2925 00001088 B90A000000 <1> mov ecx, 10 ; LOOK FOR ENTRY USING KEYPAD 2926 0000108D F2AE <1> repne scasb ; LOOK FOR MATCH 2927 0000108F 7523 <1> jne short K33 ; NO_ALT_KEYPAD 2928 00001091 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF THE NEW KEYS? 2929 <1> ;jnz short K37C ; YES, JUMP, NOT NUMPAD KEY 2930 <1> ; 05/12/2021 2931 00001094 751C <1> jnz short K32B 2932 00001096 81EF[95660000] <1> sub edi, K30+1 ; DI NOW HAS ENTRY VALUE 2933 0000109C A0[D7670000] <1> mov al, [ALT_INPUT] ; GET THE CURRENT BYTE 2934 000010A1 B40A <1> mov ah, 10 ; MULTIPLY BY 10 2935 000010A3 F6E4 <1> mul ah 2936 000010A5 6601F8 <1> add ax, di ; ADD IN THE LATEST ENTRY 2937 000010A8 A2[D7670000] <1> mov [ALT_INPUT], al ; STORE IT AWAY 2938 <1> K32A: 2939 000010AD E968FFFFFF <1> jmp K26 ; THROW AWAY THAT KEYSTROKE 2940 <1> K32B: 2941 <1> ; 05/12/2021 2942 000010B2 EB6A <1> jmp K37C 2943 <1> ; 2944 <1> ;----- LOOK FOR SUPERSHIFT ENTRY 2945 <1> K33: ; NO-ALT-KEYPAD 2946 000010B4 C605[D7670000]00 <1> mov byte [ALT_INPUT], 0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT 2947 000010BB B91A000000 <1> mov ecx, 26 ; (DI),(ES) ALREADY POINTING 2948 000010C0 F2AE <1> repne scasb ; LOOK FOR MATCH IN ALPHABET 2949 000010C2 7453 <1> je short K37A ; MATCH FOUND, GO FILLL THE BUFFER 2950 <1> ; 2951 <1> ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT 2952 <1> K34: ; ALT-TOP-ROW 2953 000010C4 3C02 <1> cmp al, 2 ; KEY WITH '1' ON IT 2954 000010C6 7228 <1> jb short K37B ; MUST BE ESCAPE 2955 000010C8 3C0D <1> cmp al, 13 ; IS IT IN THE REGION 2956 000010CA 7705 <1> ja short K35 ; NO, ALT SOMETHING ELSE 2957 000010CC 80C476 <1> add ah, 118 ; CONVERT PSEUDO SCAN CODE TO RANGE 2958 000010CF EB46 <1> jmp short K37A ; GO FILL THE BUFFER 2959 <1> ; 2960 <1> ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES 2961 <1> K35: ; ALT-FUNCTION 2962 000010D1 3C57 <1> cmp al, F11_M ; IS IT F11? 2963 000010D3 7209 <1> jb short K35A ; 20/02/2015 ; NO, BRANCH 2964 000010D5 3C58 <1> cmp al, F12_M ; IS IT F12? 2965 000010D7 7705 <1> ja short K35A ; 20/02/2015 ; NO, BRANCH 2966 000010D9 80C434 <1> add ah, 52 ; CONVERT TO PSEUDO SCAN CODE 2967 000010DC EB39 <1> jmp short K37A ; GO FILL THE BUFFER 2968 <1> K35A: 2969 000010DE F6C702 <1> test bh, LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS? 2970 000010E1 7425 <1> jz short K37 ; NO, JUMP 2971 000010E3 3C1C <1> cmp al, 28 ; TEST FOR KEYPAD ENTER 2972 000010E5 7510 <1> jne short K35B ; NOT THERE 2973 000010E7 66B800A6 <1> mov ax, 0A600h ; SPECIAL CODE 2974 000010EB E9B4010000 <1> jmp K57 ; BUFFER FILL 2975 <1> K37B: 2976 000010F0 B0F0 <1> mov al, 0F0h ; USE SPECIAL ASCII CODE 2977 000010F2 E9AD010000 <1> jmp K57 ; PUT IT IN THE BUFFER 2978 <1> K35B: 2979 000010F7 3C53 <1> cmp al, 83 ; TEST FOR DELETE KEY 2980 000010F9 7423 <1> je short K37C ; HANDLE WITH OTHER EDIT KEYS 2981 000010FB 3C35 <1> cmp al, 53 ; TEST FOR KEYPAD / 2982 000010FD 75AE <1> jne short K32A ; NOT THERE, NO OTHER E0 SPECIALS 2983 <1> ; 05/12/2021 2984 <1> ;jne K26 2985 000010FF 66B800A4 <1> mov ax, 0A400h ; SPECIAL CODE 2986 00001103 E99C010000 <1> jmp K57 ; BUFFER FILL 2987 <1> K37: 2988 00001108 3C3B <1> cmp al, 59 ; TEST FOR FUNCTION KEYS (F1) 2989 0000110A 72E4 <1> jb short K37B ; NO FN, HANDLE W/OTHER EXTENDED 2990 0000110C 3C44 <1> cmp al, 68 ; IN KEYPAD REGION? 2991 <1> ;ja short K32A ; IF SO, IGNORE 2992 0000110E 0F8706FFFFFF <1> ja K26 2993 00001114 80C42D <1> add ah, 45 ; CONVERT TO PSEUDO SCAN CODE 2994 <1> K37A: 2995 00001117 B000 <1> mov al, 0 ; ASCII CODE OF ZERO 2996 00001119 E986010000 <1> jmp K57 ; PUT IT IN THE BUFFER 2997 <1> K37C: 2998 0000111E 0450 <1> add al, 80 ; CONVERT SCAN CODE (EDIT KEYS) 2999 00001120 88C4 <1> mov ah, al ; (SCAN CODE NOT IN AH FOR INSERT) 3000 00001122 EBF3 <1> jmp short K37A ; PUT IT IN THE BUFFER 3001 <1> ; 3002 <1> ;----- NOT IN ALTERNATE SHIFT 3003 <1> K38: ; NOT-ALT-SHIFT 3004 <1> ; BL STILL HAS SHIFT FLAGS 3005 00001124 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT? 3006 00001127 7505 <1> jnz short K38A ; YES, START PROCESSING 3007 <1> ;jz K44 ; NOT-CTL-SHIFT 3008 <1> ; 05/12/2021 3009 00001129 E9AB000000 <1> jmp K44 3010 <1> ; 3011 <1> ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS 3012 <1> ;----- TEST FOR BREAK 3013 <1> K38A: 3014 0000112E 3C46 <1> cmp al, SCROLL_KEY ; TEST FOR BREAK 3015 00001130 7530 <1> jne short K39 ; JUMP, NO-BREAK 3016 00001132 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3017 00001135 7405 <1> jz short K38B ; NO, BREAK IS VALID 3018 00001137 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3019 0000113A 7426 <1> jz short K39 ; NO-BREAK, TEST FOR PAUSE 3020 <1> K38B: 3021 0000113C 8B1D[E0670000] <1> mov ebx, [BUFFER_HEAD] ; RESET BUFFER TO EMPTY 3022 00001142 891D[E4670000] <1> mov [BUFFER_TAIL], ebx 3023 00001148 C605[D2670000]80 <1> mov byte [BIOS_BREAK], 80h ; TURN ON BIOS_BREAK BIT 3024 <1> ; 3025 <1> ;----- ENABLE KEYBOARD 3026 0000114F B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3027 00001151 E893010000 <1> call SHIP_IT ; EXECUTE ENABLE 3028 <1> ; 3029 <1> ; CTRL+BREAK code here !!! 3030 <1> ;INT 1BH ; BREAK INTERRUPT VECTOR 3031 <1> ; 17/10/2015 3032 00001156 E823230000 <1> call ctrlbrk ; control+break subroutine 3033 <1> ; 3034 <1> ;sub ax, ax ; PUT OUT DUMMY CHARACTER 3035 <1> ; 05/12/2021 3036 0000115B 29C0 <1> sub eax, eax 3037 0000115D E942010000 <1> jmp K57 ; BUFFER_FILL 3038 <1> ; 3039 <1> ;----- TEST FOR PAUSE 3040 <1> K39: ; NO_BREAK 3041 00001162 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3042 00001165 7537 <1> jnz short K41 ; YES, THEN THIS CAN'T BE PAUSE 3043 00001167 3C45 <1> cmp al, NUM_KEY ; LOOK FOR PAUSE KEY 3044 00001169 7533 <1> jne short K41 ; NO-PAUSE 3045 <1> K39P: 3046 0000116B 800D[D4670000]08 <1> or byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG 3047 <1> ; 3048 <1> ;----- ENABLE KEYBOARD 3049 00001172 B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3050 00001174 E870010000 <1> call SHIP_IT ; EXECUTE ENABLE 3051 <1> K39A: 3052 00001179 B020 <1> mov al, EOI ; END OF INTERRUPT TO CONTROL PORT 3053 0000117B E620 <1> out 20h, al ;out INTA00, al ; ALLOW FURTHER KEYSTROKE INTERRUPTS 3054 <1> ; 3055 <1> ;----- DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON 3056 0000117D 803D[D0670000]07 <1> cmp byte [CRT_MODE], 7 ; IS THIS BLACK AND WHITE CARD 3057 00001184 740A <1> je short K40 ; YES, NOTHING TO DO 3058 00001186 66BAD803 <1> mov dx, 03D8h ; PORT FOR COLOR CARD 3059 0000118A A0[D1670000] <1> mov al, [CRT_MODE_SET] ; GET THE VALUE OF THE CURRENT MODE 3060 0000118F EE <1> out dx, al ; SET THE CRT MODE, SO THAT CRT IS ON 3061 <1> ; 3062 <1> K40: ; PAUSE-LOOP 3063 00001190 F605[D4670000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG 3064 00001197 75F7 <1> jnz short K40 ; LOOP UNTIL FLAG TURNED OFF 3065 <1> ; 3066 00001199 E988FEFFFF <1> jmp K27 ; INTERRUPT_RETURN_NO_EOI 3067 <1> ; 3068 <1> ;----- TEST SPECIAL CASE KEY 55 3069 <1> K41: ; NO-PAUSE 3070 0000119E 3C37 <1> cmp al, 55 ; TEST FOR */PRTSC KEY 3071 000011A0 7513 <1> jne short K42 ; NOT-KEY-55 3072 000011A2 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3073 000011A5 7405 <1> jz short K41A ; NO, CTL-PRTSC IS VALID 3074 000011A7 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3075 000011AA 7421 <1> jz short K42B ; NO, TRANSLATE TO A FUNCTION 3076 <1> K41A: 3077 000011AC 66B80072 <1> mov ax, 114*256 ; START/STOP PRINTING SWITCH 3078 000011B0 E9EF000000 <1> jmp K57 ; BUFFER_FILL 3079 <1> ; 3080 <1> ;----- SET UP TO TRANSLATE CONTROL SHIFT 3081 <1> K42: ; NOT-KEY-55 3082 000011B5 3C0F <1> cmp al, 15 ; IS IT THE TAB KEY? 3083 000011B7 7414 <1> je short K42B ; YES, XLATE TO FUNCTION CODE 3084 000011B9 3C35 <1> cmp al, 53 ; IS IT THE / KEY? 3085 000011BB 750E <1> jne short K42A ; NO, NO MORE SPECIAL CASES 3086 000011BD F6C702 <1> test bh, LC_E0 ; YES, IS IT FROM THE KEY PAD? 3087 000011C0 7409 <1> jz short K42A ; NO, JUST TRANSLATE 3088 000011C2 66B80095 <1> mov ax, 9500h ; YES, SPECIAL CODE FOR THIS ONE 3089 000011C6 E9D9000000 <1> jmp K57 ; BUFFER FILL 3090 <1> K42A: 3091 <1> ;mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3092 000011CB 3C3B <1> cmp al, 59 ; IS IT IN CHARACTER TABLE? 3093 <1> ;jb short K45F ; YES, GO TRANSLATE CHAR 3094 <1> ;;jb K56 ; 20/02/2015 3095 <1> ;;jmp K64 ; 20/02/2015 3096 <1> K42B: 3097 000011CD BB[C8660000] <1> mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3098 <1> ;;jmp K64 3099 <1> ;jb K56 ;; 20/02/2015 3100 <1> ; 05/12/2021 3101 000011D2 7267 <1> jb short K45F 3102 000011D4 E9B9000000 <1> jmp K64 3103 <1> ; 3104 <1> ;----- NOT IN CONTROL SHIFT 3105 <1> K44: ; NOT-CTL-SHIFT 3106 000011D9 3C37 <1> cmp al, 55 ; PRINT SCREEN KEY? 3107 000011DB 7528 <1> jne short K45 ; NOT PRINT SCREEN 3108 000011DD F6C710 <1> test bh, KBX ; IS THIS ENHANCED KEYBOARD? 3109 000011E0 7407 <1> jz short K44A ; NO, TEST FOR SHIFT STATE 3110 000011E2 F6C702 <1> test bh, LC_E0 ; YES, LAST CODE A MARKER? 3111 000011E5 7507 <1> jnz short K44B ; YES, IS PRINT SCREEN 3112 000011E7 EB41 <1> jmp short K45C ; NO, TRANSLATE TO '*' CHARACTER 3113 <1> K44A: 3114 000011E9 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN? 3115 000011EC 743C <1> jz short K45C ; NO, TRANSLATE TO '*' CHARACTER 3116 <1> ; 3117 <1> ;----- ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION 3118 <1> K44B: 3119 000011EE B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3120 000011F0 E8F4000000 <1> call SHIP_IT ; EXECUTE ENABLE 3121 000011F5 B020 <1> mov al, EOI ; END OF CURRENT INTERRUPT 3122 000011F7 E620 <1> out 20h, al ;out INTA00, al ; SO FURTHER THINGS CAN HAPPEN 3123 <1> ; Print Screen !!! ; ISSUE PRINT SCREEN INTERRUPT (INT 05h) 3124 <1> ;PUSH BP ; SAVE POINTER 3125 <1> ;INT 5H ; ISSUE PRINT SCREEN INTERRUPT 3126 <1> ;POP BP ; RESTORE POINTER 3127 000011F9 8025[D6670000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS 3128 00001200 E921FEFFFF <1> jmp K27 ; GO BACK WITHOUT EOI OCCURRING 3129 <1> ; 3130 <1> ;----- HANDLE IN-CORE KEYS 3131 <1> K45: ; NOT-PRINT-SCREEN 3132 00001205 3C3A <1> cmp al, 58 ; TEST FOR IN-CORE AREA 3133 00001207 7734 <1> ja short K46 ; JUMP IF NOT 3134 00001209 3C35 <1> cmp al, 53 ; IS THIS THE '/' KEY? 3135 0000120B 7505 <1> jne short K45A ; NO, JUMP 3136 0000120D F6C702 <1> test bh, LC_E0 ; WAS THE LAST CODE THE MARKER? 3137 00001210 7518 <1> jnz short K45C ; YES, TRANSLATE TO CHARACTER 3138 <1> K45A: 3139 00001212 B91A000000 <1> mov ecx, 26 ; LENGHT OF SEARCH 3140 00001217 BF[9E660000] <1> mov edi, K30+10 ; POINT TO TABLE OF A-Z CHARS 3141 0000121C F2AE <1> repne scasb ; IS THIS A LETTER KEY? 3142 <1> ; 20/02/2015 3143 0000121E 7505 <1> jne short K45B ; NO, SYMBOL KEY 3144 <1> ; 3145 00001220 F6C340 <1> test bl, CAPS_STATE ; ARE WE IN CAPS_LOCK? 3146 00001223 750C <1> jnz short K45D ; TEST FOR SURE 3147 <1> K45B: 3148 00001225 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3149 00001228 750C <1> jnz short K45E ; YES, UPPERCASE 3150 <1> ; NO, LOWERCASE 3151 <1> K45C: 3152 0000122A BB[20670000] <1> mov ebx, K10 ; TRANSLATE TO LOWERCASE LETTERS 3153 0000122F EB51 <1> jmp short K56 3154 <1> K45D: ; ALMOST-CAPS-STATE 3155 00001231 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO? 3156 00001234 75F4 <1> jnz short K45C ; SHIFTED TEMP OUT OF CAPS STATE 3157 <1> K45E: 3158 00001236 BB[78670000] <1> mov ebx, K11 ; TRANSLATE TO UPPER CASE LETTERS 3159 0000123B EB45 <1> K45F: jmp short K56 3160 <1> ; 3161 <1> ;----- TEST FOR KEYS F1 - F10 3162 <1> K46: ; NOT IN-CORE AREA 3163 0000123D 3C44 <1> cmp al, 68 ; TEST FOR F1 - F10 3164 <1> ;ja short K47 ; JUMP IF NOT 3165 <1> ;jmp short K53 ; YES, GO DO FN KEY PROCESS 3166 0000123F 7635 <1> jna short K53 3167 <1> ; 3168 <1> ;----- HANDLE THE NUMERIC PAD KEYS 3169 <1> K47: ; NOT F1 - F10 3170 00001241 3C53 <1> cmp al, 83 ; TEST NUMPAD KEYS 3171 00001243 772D <1> ja short K52 ; JUMP IF NOT 3172 <1> ; 3173 <1> ;----- KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION 3174 <1> K48: 3175 00001245 3C4A <1> cmp al , 74 ; SPECIAL CASE FOR MINUS 3176 00001247 74ED <1> je short K45E ; GO TRANSLATE 3177 00001249 3C4E <1> cmp al , 78 ; SPECIAL CASE FOR PLUS 3178 0000124B 74E9 <1> je short K45E ; GO TRANSLATE 3179 0000124D F6C702 <1> test bh, LC_E0 ; IS THIS ONE OFTHE NEW KEYS? 3180 00001250 750A <1> jnz short K49 ; YES, TRANSLATE TO BASE STATE 3181 <1> ; 3182 00001252 F6C320 <1> test bl, NUM_STATE ; ARE WE IN NUM LOCK 3183 00001255 7514 <1> jnz short K50 ; TEST FOR SURE 3184 00001257 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3185 <1> ;jnz short K51 ; IF SHIFTED, REALLY NUM STATE 3186 0000125A 75DA <1> jnz short K45E 3187 <1> ; 3188 <1> ;----- BASE CASE FOR KEYPAD 3189 <1> K49: 3190 0000125C 3C4C <1> cmp al, 76 ; SPECIAL CASE FOR BASE STATE 5 3191 0000125E 7504 <1> jne short K49A ; CONTINUE IF NOT KEYPAD 5 3192 00001260 B0F0 <1> mov al, 0F0h ; SPECIAL ASCII CODE 3193 00001262 EB40 <1> jmp short K57 ; BUFFER FILL 3194 <1> K49A: 3195 00001264 BB[20670000] <1> mov ebx, K10 ; BASE CASE TABLE 3196 00001269 EB27 <1> jmp short K64 ; CONVERT TO PSEUDO SCAN 3197 <1> ; 3198 <1> ;----- MIGHT BE NUM LOCK, TEST SHIFT STATUS 3199 <1> K50: ; ALMOST-NUM-STATE 3200 0000126B F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3201 0000126E 75EC <1> jnz short K49 ; SHIFTED TEMP OUT OF NUM STATE 3202 00001270 EBC4 <1> K51: jmp short K45E ; REALLY NUM STATE 3203 <1> ; 3204 <1> ;----- TEST FOR THE NEW KEYS ON WT KEYBOARDS 3205 <1> K52: ; NOT A NUMPAD KEY 3206 00001272 3C56 <1> cmp al, 86 ; IS IT THE NEW WT KEY? 3207 <1> ;jne short K53 ; JUMP IF NOT 3208 <1> ;jmp short K45B ; HANDLE WITH REST OF LETTER KEYS 3209 00001274 74AF <1> je short K45B 3210 <1> ; 3211 <1> ;----- MUST BE F11 OR F12 3212 <1> K53: ; F1 - F10 COME HERE, TOO 3213 00001276 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE 3214 00001279 74E1 <1> jz short K49 ; JUMP, LOWER CASE PSEUDO SC'S 3215 <1> ; 20/02/2015 3216 0000127B BB[78670000] <1> mov ebx, K11 ; UPPER CASE PSEUDO SCAN CODES 3217 00001280 EB10 <1> jmp short K64 ; TRANSLATE SCAN 3218 <1> ; 3219 <1> ;----- TRANSLATE THE CHARACTER 3220 <1> K56: ; TRANSLATE-CHAR 3221 00001282 FEC8 <1> dec al ; CONVERT ORIGIN 3222 00001284 D7 <1> xlat ; CONVERT THE SCAN CODE TO ASCII 3223 00001285 F605[D6670000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3224 0000128C 7416 <1> jz short K57 ; NO, GO FILL BUFFER 3225 0000128E B4E0 <1> mov ah, MC_E0 ; YES, PUT SPECIAL MARKER IN AH 3226 00001290 EB12 <1> jmp short K57 ; PUT IT INTO THE BUFFER 3227 <1> ; 3228 <1> ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES 3229 <1> K64: ; TRANSLATE-SCAN-ORGD 3230 00001292 FEC8 <1> dec al ; CONVERT ORIGIN 3231 00001294 D7 <1> xlat ; CTL TABLE SCAN 3232 00001295 88C4 <1> mov ah, al ; PUT VALUE INTO AH 3233 00001297 B000 <1> mov al, 0 ; ZERO ASCII CODE 3234 00001299 F605[D6670000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3235 000012A0 7402 <1> jz short K57 ; NO, GO FILL BUFFER 3236 000012A2 B0E0 <1> mov al, MC_E0 ; YES, PUT SPECIAL MARKER IN AL 3237 <1> ; 3238 <1> ;----- PUT CHARACTER INTO BUFFER 3239 <1> K57: ; BUFFER_FILL 3240 000012A4 3CFF <1> cmp al, -1 ; IS THIS AN IGNORE CHAR 3241 000012A6 7405 <1> je short K59 ; YES, DO NOTHING WITH IT 3242 <1> ; 05/12/2021 3243 <1> ;je K26 ; YES, DO NOTHING WITH IT 3244 000012A8 80FCFF <1> cmp ah, -1 ; LOOK FOR -1 PSEUDO SCAN 3245 <1> ; 05/12/2021 3246 000012AB 7505 <1> jne short K61 ; NEAR_INTERRUPT_RETURN 3247 <1> ;je K26 ; INTERRUPT_RETURN 3248 <1> K59: ; NEAR_INTERRUPT_RETURN 3249 000012AD E968FDFFFF <1> jmp K26 ; INTERRUPT_RETURN 3250 <1> K61: ; NOT-CAPS-STATE 3251 000012B2 8B1D[E4670000] <1> mov ebx, [BUFFER_TAIL] ; GET THE END POINTER TO THE BUFFER 3252 000012B8 89DE <1> mov esi, ebx ; SAVE THE VALUE 3253 000012BA E8AAFAFFFF <1> call _K4 ; ADVANCE THE TAIL 3254 000012BF 3B1D[E0670000] <1> cmp ebx, [BUFFER_HEAD] ; HAS THE BUFFER WRAPPED AROUND 3255 000012C5 740E <1> je short K62 ; BUFFER_FULL_BEEP 3256 000012C7 668906 <1> mov [esi], ax ; STORE THE VALUE 3257 000012CA 891D[E4670000] <1> mov [BUFFER_TAIL], ebx ; MOVE THE POINTER UP 3258 000012D0 E945FDFFFF <1> jmp K26 3259 <1> ;;cli ; TURN OFF INTERRUPTS 3260 <1> ;;mov al, EOI ; END OF INTERRUPT COMMAND 3261 <1> ;;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3262 <1> ;MOV AL, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3263 <1> ;CALL SHIP_IT ; EXECUTE ENABLE 3264 <1> ;MOV AX, 9102H ; MOVE IN POST CODE & TYPE 3265 <1> ;INT 15H ; PERFORM OTHER FUNCTION 3266 <1> ;;and byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3267 <1> ;JMP K27A ; INTERRUPT_RETURN 3268 <1> ;;jmp K27 3269 <1> ; 3270 <1> ;----- BUFFER IS FULL SOUND THE BEEPER 3271 <1> K62: 3272 000012D5 B020 <1> mov al, EOI ; ENABLE INTERRUPT CONTROLLER CHIP 3273 000012D7 E620 <1> out INTA00, al 3274 000012D9 66B9A602 <1> mov cx, 678 ; DIVISOR FOR 1760 HZ 3275 000012DD B304 <1> mov bl, 4 ; SHORT BEEP COUNT (1/16 + 1/64 DELAY) 3276 000012DF E89B010000 <1> call beep ; GO TO COMMON BEEP HANDLER 3277 000012E4 E93DFDFFFF <1> jmp K27 ; EXIT 3278 <1> 3279 <1> SHIP_IT: 3280 <1> ;--------------------------------------------------------------------------------- 3281 <1> ; SHIP_IT 3282 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3283 <1> ; TO THE KEYBOARD CONTROLLER. 3284 <1> ;--------------------------------------------------------------------------------- 3285 <1> ; 3286 <1> ;push ax ; SAVE DATA TO SEND 3287 <1> ; 05/12/2021 3288 000012E9 50 <1> push eax 3289 <1> ;----- WAIT FOR COMMAND TO ACCEPTED 3290 000012EA FA <1> cli ; DISABLE INTERRUPTS TILL DATA SENT 3291 <1> ; xor ecx, ecx ; CLEAR TIMEOUT COUNTER 3292 000012EB B900000100 <1> mov ecx, 10000h 3293 <1> S10: 3294 000012F0 E464 <1> in al, STATUS_PORT ; READ KEYBOARD CONTROLLER STATUS 3295 000012F2 A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ITS INPUT BUFFER BUSY 3296 000012F4 E0FA <1> loopnz S10 ; WAIT FOR COMMAND TO BE ACCEPTED 3297 <1> 3298 <1> ;pop ax ; GET DATA TO SEND 3299 <1> ; 05/12/2021 3300 000012F6 58 <1> pop eax 3301 000012F7 E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROLLER 3302 000012F9 FB <1> sti ; ENABLE INTERRUPTS AGAIN 3303 000012FA C3 <1> retn ; RETURN TO CALLER 3304 <1> 3305 <1> SND_DATA: 3306 <1> ; --------------------------------------------------------------------------------- 3307 <1> ; SND_DATA 3308 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3309 <1> ; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO 3310 <1> ; HANDLES ANY RETRIES IF REQUIRED 3311 <1> ; --------------------------------------------------------------------------------- 3312 <1> ; 3313 <1> ;push ax ; SAVE REGISTERS 3314 <1> ;push bx 3315 <1> ; 05/12/2021 3316 000012FB 50 <1> push eax 3317 000012FC 53 <1> push ebx 3318 000012FD 51 <1> push ecx 3319 000012FE 88C7 <1> mov bh, al ; SAVE TRANSMITTED BYTE FOR RETRIES 3320 00001300 B303 <1> mov bl, 3 ; LOAD RETRY COUNT 3321 <1> SD0: 3322 00001302 FA <1> cli ; DISABLE INTERRUPTS 3323 00001303 8025[D5670000]CF <1> and byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS 3324 <1> ; 3325 <1> ;----- WAIT FOR COMMAND TO BE ACCEPTED 3326 0000130A B900000100 <1> mov ecx, 10000h ; MAXIMUM WAIT COUNT 3327 <1> SD5: 3328 0000130F E464 <1> in al, STATUS_PORT ; READ KEYBOARD PROCESSOR STATUS PORT 3329 00001311 A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ANY PENDING COMMAND 3330 00001313 E0FA <1> loopnz SD5 ; WAIT FOR COMMAND TO BE ACCEPTED 3331 <1> ; 3332 00001315 88F8 <1> mov al, bh ; REESTABLISH BYTE TO TRANSMIT 3333 00001317 E660 <1> out PORT_A, al ; SEND BYTE 3334 00001319 FB <1> sti ; ENABLE INTERRUPTS 3335 <1> ;mov cx, 01A00h ; LOAD COUNT FOR 10 ms+ 3336 0000131A B9FFFF0000 <1> mov ecx, 0FFFFh 3337 <1> SD1: 3338 0000131F F605[D5670000]30 <1> test byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET 3339 00001326 750F <1> jnz short SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS 3340 00001328 E2F5 <1> loop SD1 ; OTHERWISE WAIT 3341 <1> SD2: 3342 0000132A FECB <1> dec bl ; DECREMENT RETRY COUNT 3343 0000132C 75D4 <1> jnz short SD0 ; RETRY TRANSMISSION 3344 0000132E 800D[D5670000]80 <1> or byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG 3345 00001335 EB09 <1> jmp short SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION 3346 <1> SD3: 3347 00001337 F605[D5670000]10 <1> test byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE 3348 0000133E 74EA <1> jz short SD2 ; IF NOT, GO RESEND 3349 <1> SD4: 3350 00001340 59 <1> pop ecx ; RESTORE REGISTERS 3351 <1> ;pop bx 3352 <1> ;pop ax 3353 <1> ; 05/12/2021 3354 00001341 5B <1> pop ebx 3355 00001342 58 <1> pop eax 3356 00001343 C3 <1> retn ; RETURN, GOOD TRANSMISSION 3357 <1> 3358 <1> SND_LED: 3359 <1> ; --------------------------------------------------------------------------------- 3360 <1> ; SND_LED 3361 <1> ; THIS ROUTINES TURNS ON THE MODE INDICATORS. 3362 <1> ; 3363 <1> ;---------------------------------------------------------------------------------- 3364 <1> ; 3365 00001344 FA <1> cli ; TURN OFF INTERRUPTS 3366 00001345 F605[D5670000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3367 0000134C 755F <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3368 <1> ; 3369 0000134E 800D[D5670000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3370 00001355 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3371 00001357 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3372 00001359 EB11 <1> jmp short SL0 ; GO SEND MODE INDICATOR COMMAND 3373 <1> SND_LED1: 3374 0000135B FA <1> cli ; TURN OFF INTERRUPTS 3375 0000135C F605[D5670000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3376 00001363 7548 <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3377 <1> ; 3378 00001365 800D[D5670000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3379 <1> SL0: 3380 0000136C B0ED <1> mov al, LED_CMD ; LED CMD BYTE 3381 0000136E E888FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3382 00001373 FA <1> cli 3383 00001374 E836000000 <1> call MAKE_LED ; GO FORM INDICATOR DATA BYTE 3384 00001379 8025[D5670000]F8 <1> and byte [KB_FLAG_2], 0F8h ; ~KB_LEDS ; CLEAR MODE INDICATOR BITS 3385 00001380 0805[D5670000] <1> or [KB_FLAG_2], al ; SAVE PRESENT INDICATORS FOR NEXT TIME 3386 00001386 F605[D5670000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3387 0000138D 750F <1> jnz short SL2 ; IF SO, BYPASS SECOND BYTE TRANSMISSION 3388 <1> ; 3389 0000138F E867FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3390 00001394 FA <1> cli ; TURN OFF INTERRUPTS 3391 00001395 F605[D5670000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3392 0000139C 7408 <1> jz short SL3 ; IF NOT, DON'T SEND AN ENABLE COMMAND 3393 <1> SL2: 3394 0000139E B0F4 <1> mov al, KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND 3395 000013A0 E856FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3396 000013A5 FA <1> cli ; TURN OFF INTERRUPTS 3397 <1> SL3: 3398 000013A6 8025[D5670000]3F <1> and byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR 3399 <1> SL1: ; UPDATE AND TRANSMIT ERROR FLAG 3400 000013AD FB <1> sti ; ENABLE INTERRUPTS 3401 000013AE C3 <1> retn ; RETURN TO CALLER 3402 <1> 3403 <1> MAKE_LED: 3404 <1> ;--------------------------------------------------------------------------------- 3405 <1> ; MAKE_LED 3406 <1> ; THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF 3407 <1> ; THE MODE INDICATORS. 3408 <1> ;--------------------------------------------------------------------------------- 3409 <1> ; 3410 <1> ;push cx ; SAVE CX 3411 000013AF A0[D3670000] <1> mov al, [KB_FLAG] ; GET CAPS & NUM LOCK INDICATORS 3412 000013B4 2470 <1> and al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS 3413 <1> ;mov cl, 4 ; SHIFT COUNT 3414 <1> ;rol al, cl ; SHIFT BITS OVER TO TURN ON INDICATORS 3415 000013B6 C0C004 <1> rol al, 4 ; 20/02/2015 3416 000013B9 2407 <1> and al, 07h ; MAKE SURE ONLY MODE BITS ON 3417 <1> ;pop cx 3418 000013BB C3 <1> retn ; RETURN TO CALLER 3419 <1> 3420 <1> ; % include 'kybdata.inc' ; KEYBOARD DATA ; 11/03/2015 3421 <1> 3422 <1> 3423 <1> ; /// End Of KEYBOARD FUNCTIONS /// 1854 1855 %include 'video.s' ; 07/03/2015 1856 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 1857 <1> ; (re-write kernel for test by using previous version without a major defect) 1858 <1> ; **************************************************************************** 1859 <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC 1860 <1> ; Last Modification: 05/12/2021 1861 <1> ; (Video Data is in 'VIDATA.INC') 1862 <1> ; 1863 <1> ; ///////// VIDEO (CGA) FUNCTIONS /////////////// 1864 <1> 1865 <1> ; 05/12/2021 1866 <1> ; 30/06/2015 1867 <1> ; 27/06/2015 1868 <1> ; 11/03/2015 1869 <1> ; 02/09/2014 1870 <1> ; 30/08/2014 1871 <1> ; VIDEO FUNCTIONS 1872 <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014) 1873 <1> 1874 <1> write_tty: 1875 <1> ; 13/08/2015 1876 <1> ; 02/09/2014 1877 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 1878 <1> ; 01/02/2014 (Retro UNIX 8086 v1 - last update) 1879 <1> ; 03/12/2013 (Retro UNIX 8086 v1 - beginning) 1880 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 1881 <1> ; 1882 <1> ; INPUT -> AH = Color (Forecolor, Backcolor) 1883 <1> ; AL = Character to be written 1884 <1> ; EBX = Video Page (0 to 7) 1885 <1> ; (BH = 0 --> Video Mode 3) 1886 <1> 1887 <1> RVRT equ 00001000b ; VIDEO VERTICAL RETRACE BIT 1888 <1> RHRZ equ 00000001b ; VIDEO HORIZONTAL RETRACE BIT 1889 <1> 1890 <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code 1891 <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO 1892 <1> ; 1893 <1> ; 06/10/85 VIDEO DISPLAY BIOS 1894 <1> ; 1895 <1> ;--- WRITE_TTY ------------------------------------------------------------------ 1896 <1> ; : 1897 <1> ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE : 1898 <1> ; VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT : 1899 <1> ; CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. : 1900 <1> ; IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN : 1901 <1> ; IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW : 1902 <1> ; ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, : 1903 <1> ; FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. : 1904 <1> ; WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE : 1905 <1> ; NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : 1906 <1> ; LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE, : 1907 <1> ; THE 0 COLOR IS USED. : 1908 <1> ; ENTRY -- : 1909 <1> ; (AH) = CURRENT CRT MODE : 1910 <1> ; (AL) = CHARACTER TO BE WRITTEN : 1911 <1> ; NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE : 1912 <1> ; HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS : 1913 <1> ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE : 1914 <1> ; EXIT -- : 1915 <1> ; ALL REGISTERS SAVED : 1916 <1> ;-------------------------------------------------------------------------------- 1917 <1> 1918 000013BC FA <1> cli 1919 <1> ; 1920 <1> ; READ CURSOR (04/12/2013) 1921 <1> ; Retro UNIX 386 v1 Modifications: 30/08/2014 1922 000013BD 08FF <1> or bh, bh 1923 000013BF 0F85AB000000 <1> jnz beeper 1924 <1> ; 01/09/2014 1925 000013C5 803D[D0670000]03 <1> cmp byte [CRT_MODE], 3 1926 000013CC 7405 <1> je short m3 1927 <1> ; 1928 000013CE E876020000 <1> call set_mode 1929 <1> m3: 1930 000013D3 89DE <1> mov esi, ebx ; 13/08/2015 (0 to 7) 1931 000013D5 66D1E6 <1> shl si, 1 1932 000013D8 81C6[C66D0000] <1> add esi, cursor_posn 1933 000013DE 668B16 <1> mov dx, [esi] 1934 <1> ; 1935 <1> ; dx now has the current cursor position 1936 <1> ; 1937 000013E1 3C0D <1> cmp al, 0Dh ; is it carriage return or control character 1938 000013E3 764D <1> jbe short u8 1939 <1> ; 1940 <1> ; write the char to the screen 1941 <1> u0: 1942 <1> ; ah = attribute/color 1943 <1> ; al = character 1944 <1> ; bl = video page number (0 to 7) 1945 <1> ; bh = 0 1946 <1> ; 1947 000013E5 E832020000 <1> call write_c_current 1948 <1> ; 1949 <1> ; position the cursor for next char 1950 000013EA FEC2 <1> inc dl ; next column 1951 <1> ;cmp dl, [CRT_COLS] 1952 000013EC 80FA50 <1> cmp dl, 80 ; test for column overflow 1953 000013EF 0F85E9000000 <1> jne set_cpos 1954 000013F5 B200 <1> mov dl, 0 ; column = 0 1955 <1> u10: ; (line feed found) 1956 000013F7 80FE18 <1> cmp dh, 25-1 ; check for last row 1957 000013FA 722F <1> jb short u6 1958 <1> ; 1959 <1> ; scroll required 1960 <1> u1: 1961 <1> ; SET CURSOR POSITION (04/12/2013) 1962 000013FC E8DD000000 <1> call set_cpos 1963 <1> ; 1964 <1> ; determine value to fill with during scroll 1965 <1> u2: 1966 <1> ; READ_AC_CURRENT : 1967 <1> ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER 1968 <1> ; AT THE CURRENT CURSOR POSITION 1969 <1> ; 1970 <1> ; INPUT 1971 <1> ; (AH) = CURRENT CRT MODE 1972 <1> ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) 1973 <1> ; (DS) = DATA SEGMENT 1974 <1> ; (ES) = REGEN SEGMENT 1975 <1> ; OUTPUT 1976 <1> ; (AL) = CHARACTER READ 1977 <1> ; (AH) = ATTRIBUTE READ 1978 <1> ; 1979 <1> ; mov ah, [CRT_MODE] ; move current mode into ah 1980 <1> ; 1981 <1> ; bl = video page number 1982 <1> ; 1983 00001401 E834010000 <1> call find_position ; get regen location and port address 1984 <1> ; dx = status port 1985 <1> ; esi = cursor location/address 1986 <1> p11: 1987 00001406 FB <1> sti ; enable interrupts 1988 00001407 90 <1> nop ; allow for small interupts window 1989 00001408 FA <1> cli ; blocks interrupts for single loop 1990 00001409 EC <1> in al, dx ; get status from adapter 1991 0000140A A801 <1> test al, RHRZ ; is horizontal retrace low 1992 0000140C 75F8 <1> jnz short p11 ; wait until it is 1993 <1> p12: ; now wait for either retrace high 1994 0000140E EC <1> in al, dx ; get status 1995 0000140F A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 1996 00001411 74FB <1> jz short p12 ; wait until either is active 1997 <1> p13: 1998 00001413 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 1999 00001419 668B06 <1> mov ax, [esi] ; get the character and attribute 2000 <1> ; 2001 <1> ; al = character, ah = attribute 2002 <1> ; 2003 0000141C FB <1> sti 2004 <1> ; bl = video page number 2005 <1> u3: 2006 <1> ;;mov ax, 0601h ; scroll one line 2007 <1> ;;sub cx, cx ; upper left corner 2008 <1> ;;mov dh, 25-1 ; lower right row 2009 <1> ;;;mov dl, [CRT_COLS] 2010 <1> ;mov dl, 80 ; lower right column 2011 <1> ;;dec dl 2012 <1> ;;mov dl, 79 2013 <1> 2014 <1> ;;call scroll_up ; 04/12/2013 2015 <1> ;;; 11/03/2015 2016 <1> ; 02/09/2014 2017 <1> ;;;mov cx, [crt_ulc] ; Upper left corner (0000h) 2018 <1> ;;;mov dx, [crt_lrc] ; Lower right corner (184Fh) 2019 <1> ; 11/03/2015 2020 0000141D 6629C9 <1> sub cx, cx 2021 00001420 66BA4F18 <1> mov dx, 184Fh ; dl= 79 (column), dh = 24 (row) 2022 <1> ; 2023 00001424 B001 <1> mov al, 1 ; scroll 1 line up 2024 <1> ; ah = attribute 2025 00001426 E939010000 <1> jmp scroll_up 2026 <1> ;u4: 2027 <1> ;;int 10h ; video-call return 2028 <1> ; scroll up the screen 2029 <1> ; tty return 2030 <1> ;u5: 2031 <1> ;retn ; return to the caller 2032 <1> 2033 <1> u6: ; set-cursor-inc 2034 0000142B FEC6 <1> inc dh ; next row 2035 <1> ; set cursor 2036 <1> ;u7: 2037 <1> ;;mov ah, 02h 2038 <1> ;;jmp short u4 ; establish the new cursor 2039 <1> ;call set_cpos 2040 <1> ;jmp short u5 2041 0000142D E9AC000000 <1> jmp set_cpos 2042 <1> 2043 <1> ; check for control characters 2044 <1> u8: 2045 00001432 7438 <1> je short u9 2046 00001434 3C0A <1> cmp al, 0Ah ; is it a line feed (0Ah) 2047 00001436 74BF <1> je short u10 2048 00001438 3C07 <1> cmp al, 07h ; is it a bell 2049 0000143A 7434 <1> je short u11 2050 0000143C 3C08 <1> cmp al, 08h ; is it a backspace 2051 <1> ;jne short u0 2052 0000143E 7424 <1> je short bs ; 12/12/2013 2053 <1> ; 12/12/2013 (tab stop) 2054 00001440 3C09 <1> cmp al, 09h ; is it a tab stop 2055 00001442 75A1 <1> jne short u0 2056 00001444 88D0 <1> mov al, dl 2057 00001446 6698 <1> cbw 2058 00001448 B108 <1> mov cl, 8 2059 0000144A F6F1 <1> div cl 2060 0000144C 28E1 <1> sub cl, ah 2061 <1> ts: 2062 <1> ; 02/09/2014 2063 <1> ; 01/09/2014 2064 0000144E B020 <1> mov al, 20h 2065 <1> tsloop: 2066 00001450 6651 <1> push cx 2067 00001452 6650 <1> push ax 2068 00001454 30FF <1> xor bh, bh 2069 <1> ;mov bl, [active_page] 2070 00001456 E878FFFFFF <1> call m3 2071 0000145B 6658 <1> pop ax ; ah = attribute/color 2072 0000145D 6659 <1> pop cx 2073 0000145F FEC9 <1> dec cl 2074 00001461 75ED <1> jnz short tsloop 2075 00001463 C3 <1> retn 2076 <1> bs: 2077 <1> ; back space found 2078 <1> 2079 00001464 08D2 <1> or dl, dl ; is it already at start of line 2080 <1> ;je short u7 ; set_cursor 2081 00001466 7476 <1> jz short set_cpos 2082 00001468 664A <1> dec dx ; no -- just move it back 2083 <1> ;jmp short u7 2084 0000146A EB72 <1> jmp short set_cpos 2085 <1> 2086 <1> ; carriage return found 2087 <1> u9: 2088 0000146C B200 <1> mov dl, 0 ; move to first column 2089 <1> ;jmp short u7 2090 0000146E EB6E <1> jmp short set_cpos 2091 <1> 2092 <1> ; line feed found 2093 <1> ;u10: 2094 <1> ; cmp dh, 25-1 ; bottom of screen 2095 <1> ; jne short u6 ; no, just set the cursor 2096 <1> ; jmp u1 ; yes, scroll the screen 2097 <1> 2098 <1> beeper: 2099 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2100 <1> ; 18/01/2014 2101 <1> ; 03/12/2013 2102 <1> ; bell found 2103 <1> u11: 2104 00001470 FB <1> sti 2105 00001471 3A1D[D66D0000] <1> cmp bl, [active_page] 2106 00001477 7551 <1> jne short u12 ; Do not sound the beep 2107 <1> ; if it is not written on the active page 2108 00001479 66B93305 <1> mov cx, 1331 ; divisor for 896 hz tone 2109 0000147D B31F <1> mov bl, 31 ; set count for 31/64 second for beep 2110 <1> ;call beep ; sound the pod bell 2111 <1> ;jmp short u5 ; tty_return 2112 <1> ;retn 2113 <1> 2114 <1> TIMER equ 040h ; 8254 TIMER - BASE ADDRESS 2115 <1> PORT_B equ 061h ; PORT B READ/WRITE DIAGNOSTIC REGISTER 2116 <1> GATE2 equ 00000001b ; TIMER 2 INPUT CATE CLOCK BIT 2117 <1> SPK2 equ 00000010b ; SPEAKER OUTPUT DATA ENABLE BIT 2118 <1> 2119 <1> beep: 2120 <1> ; 07/02/2015 2121 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2122 <1> ; 18/01/2014 2123 <1> ; 03/12/2013 2124 <1> ; 2125 <1> ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES 2126 <1> ; 2127 <1> ; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE 2128 <1> ; 2129 <1> ; ENTRY: 2130 <1> ; (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND ) 2131 <1> ; (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ) 2132 <1> ; EXIT: : 2133 <1> ; (AX),(BL),(CX) MODIFIED. 2134 <1> 2135 0000147F 9C <1> pushf ; 18/01/2014 ; save interrupt status 2136 00001480 FA <1> cli ; block interrupts during update 2137 00001481 B0B6 <1> mov al, 10110110b ; select timer 2, lsb, msb binary 2138 00001483 E643 <1> out TIMER+3, al ; write timer mode register 2139 00001485 EB00 <1> jmp $+2 ; I/O delay 2140 00001487 88C8 <1> mov al, cl ; divisor for hz (low) 2141 00001489 E642 <1> out TIMER+2,AL ; write timer 2 count - lsb 2142 0000148B EB00 <1> jmp $+2 ; I/O delay 2143 0000148D 88E8 <1> mov al, ch ; divisor for hz (high) 2144 0000148F E642 <1> out TIMER+2, al ; write timer 2 count - msb 2145 00001491 E461 <1> in al, PORT_B ; get current setting of port 2146 00001493 88C4 <1> mov ah, al ; save that setting 2147 00001495 0C03 <1> or al, GATE2+SPK2 ; gate timer 2 and turn speaker on 2148 00001497 E661 <1> out PORT_B, al ; and restore interrupt status 2149 <1> ;popf ; 18/01/2014 2150 00001499 FB <1> sti 2151 <1> g7: ; 1/64 second per count (bl) 2152 0000149A B90B040000 <1> mov ecx, 1035 ; delay count for 1/64 of a second 2153 0000149F E827000000 <1> call waitf ; go to beep delay 1/64 count 2154 000014A4 FECB <1> dec bl ; (bl) length count expired? 2155 000014A6 75F2 <1> jnz short g7 ; no - continue beeping speaker 2156 <1> ; 2157 <1> ;pushf ; save interrupt status 2158 000014A8 FA <1> cli ; 18/01/2014 ; block interrupts during update 2159 000014A9 E461 <1> in al, PORT_B ; get current port value 2160 <1> ;or al, not (GATE2+SPK2) ; isolate current speaker bits in case 2161 000014AB 0CFC <1> or al, ~(GATE2+SPK2) 2162 000014AD 20C4 <1> and ah, al ; someone turned them off during beep 2163 000014AF 88E0 <1> mov al, ah ; recover value of port 2164 <1> ;or al, not (GATE2+SPK2) ; force speaker data off 2165 000014B1 0CFC <1> or al, ~(GATE2+SPK2) ; isolate current speaker bits in case 2166 000014B3 E661 <1> out PORT_B, al ; and stop speaker timer 2167 <1> ;popf ; restore interrupt flag state 2168 000014B5 FB <1> sti 2169 000014B6 B90B040000 <1> mov ecx, 1035 ; force 1/64 second delay (short) 2170 000014BB E80B000000 <1> call waitf ; minimum delay between all beeps 2171 <1> ;pushf ; save interrupt status 2172 000014C0 FA <1> cli ; block interrupts during update 2173 000014C1 E461 <1> in al, PORT_B ; get current port value in case 2174 000014C3 2403 <1> and al, GATE2+SPK2 ; someone turned them on 2175 000014C5 08E0 <1> or al, ah ; recover value of port_b 2176 000014C7 E661 <1> out PORT_B, al ; restore speaker status 2177 000014C9 9D <1> popf ; restore interrupt flag state 2178 <1> u12: 2179 000014CA C3 <1> retn 2180 <1> 2181 <1> REFRESH_BIT equ 00010000b ; REFRESH TEST BIT 2182 <1> 2183 <1> WAITF: 2184 <1> waitf: 2185 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2186 <1> ; 03/12/2013 2187 <1> ; 2188 <1> ; push ax ; save work register (ah) 2189 <1> ;waitf1: 2190 <1> ; use timer 1 output bits 2191 <1> ; in al, PORT_B ; read current counter output status 2192 <1> ; and al, REFRESH_BIT ; mask for refresh determine bit 2193 <1> ; cmp al, ah ; did it just change 2194 <1> ; je short waitf1 ; wait for a change in output line 2195 <1> ; ; 2196 <1> ; mov ah, al ; save new lflag state 2197 <1> ; loop waitf1 ; decrement half cycles till count end 2198 <1> ; ; 2199 <1> ; pop ax ; restore (ah) 2200 <1> ; retn ; return (cx)=0 2201 <1> 2202 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2203 <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s) 2204 <1> ; 17/12/2014 (dsectrm2.s) 2205 <1> ; WAITF 2206 <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 /// 2207 <1> ; 2208 <1> ;---WAITF----------------------------------------------------------------------- 2209 <1> ; FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR) 2210 <1> ; ENTRY: 2211 <1> ; (CX) = COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT 2212 <1> ; MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE 2213 <1> ; EXIT: 2214 <1> ; AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS) 2215 <1> ; (CX) = 0 2216 <1> ;------------------------------------------------------------------------------- 2217 <1> 2218 <1> ; Refresh period: 30 micro seconds (15-80 us) 2219 <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH) 2220 <1> 2221 <1> ;WAITF: ; DELAY FOR (CX)*15.085737 US 2222 <1> ;PUSH AX ; SAVE WORK REGISTER (AH) 2223 <1> ; 05/12/2021 2224 000014CB 50 <1> push eax 2225 <1> ; 16/12/2014 2226 <1> ;shr cx, 1 ; convert to count of 30 micro seconds 2227 000014CC D1E9 <1> shr ecx, 1 ; 21/02/2015 2228 <1> ;17/12/2014 2229 <1> ;WAITF1: 2230 <1> ; IN AL, PORT_B ;061h ; READ CURRENT COUNTER OUTPUT STATUS 2231 <1> ; AND AL, REFRESH_BIT ;00010000b ; MASK FOR REFRESH DETERMINE BIT 2232 <1> ; CMP AL, AH ; DID IT JUST CHANGE 2233 <1> ; JE short WAITF1 ; WAIT FOR A CHANGE IN OUTPUT LINE 2234 <1> ; MOV AH, AL ; SAVE NEW FLAG STATE 2235 <1> ; LOOP WAITF1 ; DECREMENT HALF CYCLES TILL COUNT END 2236 <1> ; 2237 <1> ; 17/12/2014 2238 <1> ; 2239 <1> ; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999 2240 <1> ; 2241 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 2242 <1> ; INPUT: CX = number of refresh periods to wait 2243 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2244 <1> WR_STATE_0: 2245 000014CE E461 <1> IN AL,PORT_B ; IN AL,SYS1 2246 000014D0 A810 <1> TEST AL,010H 2247 000014D2 74FA <1> JZ SHORT WR_STATE_0 2248 <1> WR_STATE_1: 2249 000014D4 E461 <1> IN AL,PORT_B ; IN AL,SYS1 2250 000014D6 A810 <1> TEST AL,010H 2251 000014D8 75FA <1> JNZ SHORT WR_STATE_1 2252 000014DA E2F2 <1> LOOP WR_STATE_0 2253 <1> ; 2254 <1> ;POP AX ; RESTORE (AH) 2255 <1> ; 05/12/2021 2256 000014DC 58 <1> pop eax 2257 000014DD C3 <1> RETn ; (CX) = 0 2258 <1> 2259 <1> set_cpos: 2260 <1> ; 27/06/2015 2261 <1> ; 01/09/2014 2262 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 2263 <1> ; 2264 <1> ; 12/12/2013 (Retro UNIX 8086 v1 - last update) 2265 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - beginning) 2266 <1> ; 2267 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2268 <1> ; 2269 <1> ; SET_CPOS 2270 <1> ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE 2271 <1> ; NEW X-Y VALUES PASSED 2272 <1> ; INPUT 2273 <1> ; DX - ROW,COLUMN OF NEW CURSOR 2274 <1> ; BH - DISPLAY PAGE OF CURSOR 2275 <1> ; OUTPUT 2276 <1> ; CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY 2277 <1> ; 2278 000014DE 0FB6C3 <1> movzx eax, bl ; BL = video page number ; 27/06/2015 (movzx) 2279 000014E1 D0E0 <1> shl al, 1 ; word offset 2280 000014E3 BE[C66D0000] <1> mov esi, cursor_posn 2281 000014E8 01C6 <1> add esi, eax 2282 000014EA 668916 <1> mov [esi], dx ; save the pointer 2283 000014ED 381D[D66D0000] <1> cmp [active_page], bl 2284 000014F3 7532 <1> jne short m17 2285 <1> ;call m18 ; CURSOR SET 2286 <1> ;m17: ; SET_CPOS_RETURN 2287 <1> ; 01/09/2014 2288 <1> ; retn 2289 <1> ; DX = row/column 2290 <1> m18: 2291 000014F5 E832000000 <1> call position ; determine location in regen buffer 2292 000014FA 668B0D[C46D0000] <1> mov cx, [CRT_START] 2293 00001501 6601C1 <1> add cx, ax ; add char position in regen buffer 2294 <1> ; to the start address (offset) for this page 2295 00001504 66D1E9 <1> shr cx, 1 ; divide by 2 for char only count 2296 00001507 B40E <1> mov ah, 14 ; register number for cursor 2297 <1> ;call m16 ; output value to the 6845 2298 <1> ;retn 2299 <1> 2300 <1> ;----- THIS ROUTINE OUTPUTS THE CX REGISTER 2301 <1> ; TO THE 6845 REGISTERS NAMED IN (AH) 2302 <1> m16: 2303 00001509 FA <1> cli 2304 <1> ;mov dx, [addr_6845] ; address register 2305 0000150A 66BAD403 <1> mov dx, 03D4h ; I/O address of color card 2306 0000150E 88E0 <1> mov al, ah ; get value 2307 00001510 EE <1> out dx, al ; register set 2308 00001511 6642 <1> inc dx ; data register 2309 00001513 EB00 <1> jmp $+2 ; i/o delay 2310 00001515 88E8 <1> mov al, ch ; data 2311 00001517 EE <1> out dx, al 2312 00001518 664A <1> dec dx 2313 0000151A 88E0 <1> mov al, ah 2314 0000151C FEC0 <1> inc al ; point to other data register 2315 0000151E EE <1> out dx, al ; set for second register 2316 0000151F 6642 <1> inc dx 2317 00001521 EB00 <1> jmp $+2 ; i/o delay 2318 00001523 88C8 <1> mov al, cl ; second data value 2319 00001525 EE <1> out dx, al 2320 00001526 FB <1> sti 2321 <1> m17: 2322 00001527 C3 <1> retn 2323 <1> 2324 <1> set_ctype: 2325 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2326 <1> ; 2327 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2328 <1> 2329 <1> ; CH) = BITS 4-0 = START LINE FOR CURSOR 2330 <1> ; ** HARDWARE WILL ALWAYS CAUSE BLINK 2331 <1> ; ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING 2332 <1> ; OR NO CURSOR AT ALL 2333 <1> ; (CL) = BITS 4-0 = END LINE FOR CURSOR 2334 <1> 2335 <1> ;------------------------------------------------ 2336 <1> ; SET_CTYPE 2337 <1> ; THIS ROUTINE SETS THE CURSOR VALUE 2338 <1> ; INPUT 2339 <1> ; (CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE 2340 <1> ; OUTPUT 2341 <1> ; NONE 2342 <1> ;------------------------------------------------ 2343 <1> 2344 00001528 B40A <1> mov ah, 10 ; 6845 register for cursor set 2345 <1> ;mov [CURSOR_MODE], cx ; save in data area 2346 <1> ;call m16 ; output cx register 2347 <1> ;retn 2348 0000152A EBDD <1> jmp m16 2349 <1> 2350 <1> 2351 <1> position: 2352 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2353 <1> ; 27/06/2015 2354 <1> ; 02/09/2014 2355 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2356 <1> ; 04/12/2013 (Retro UNIX 8086 v1) 2357 <1> ; 2358 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2359 <1> ; 2360 <1> ; POSITION 2361 <1> ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS 2362 <1> ; OF A CHARACTER IN THE ALPHA MODE 2363 <1> ; INPUT 2364 <1> ; AX = ROW, COLUMN POSITION 2365 <1> ; OUTPUT 2366 <1> ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 2367 <1> 2368 <1> ; DX = ROW, COLUMN POSITION 2369 <1> ;movzx eax, byte [CRT_COLS] ; 27/06/2015 2370 0000152C 31C0 <1> xor eax, eax ; 02/09/2014 2371 0000152E B050 <1> mov al, 80 ; determine bytes to row 2372 00001530 F6E6 <1> mul dh ; row value 2373 00001532 30F6 <1> xor dh, dh ; 0 2374 00001534 6601D0 <1> add ax, dx ; add column value to the result 2375 <1> ;shl ax, 1 ; * 2 for attribute bytes 2376 <1> ; 05/12/2021 2377 00001537 D1E0 <1> shl eax, 1 2378 <1> ; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 2379 00001539 C3 <1> retn 2380 <1> 2381 <1> find_position: 2382 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2383 <1> ; 27/06/2015 2384 <1> ; 07/09/2014 2385 <1> ; 02/09/2014 2386 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2387 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2388 0000153A 0FB6CB <1> movzx ecx, bl ; video page number ; 27/06/2015 (movzx) 2389 0000153D 89CE <1> mov esi, ecx 2390 <1> ;shl si, 1 2391 0000153F D1E6 <1> shl esi, 1 ; 05/12/2021 2392 00001541 668B96[C66D0000] <1> mov dx, [esi+cursor_posn] 2393 00001548 7409 <1> jz short p21 2394 <1> ;xor si, si 2395 0000154A 31F6 <1> xor esi, esi ; 05/12/2021 2396 <1> p20: 2397 <1> ;add si, [CRT_LEN] 2398 0000154C 6681C6A00F <1> add si, 80*25*2 ; add length of buffer for one page 2399 00001551 E2F9 <1> loop p20 2400 <1> p21: 2401 00001553 6621D2 <1> and dx, dx 2402 00001556 7407 <1> jz short p22 2403 00001558 E8CFFFFFFF <1> call position ; determine location in regen in page 2404 0000155D 01C6 <1> add esi, eax ; add location to start of regen page 2405 <1> p22: 2406 <1> ;mov dx, [addr_6845] ; get base address of active display 2407 <1> ;mov dx, 03D4h ; I/O address of color card 2408 <1> ;add dx, 6 ; point at status port 2409 0000155F 66BADA03 <1> mov dx, 03DAh ; status port 2410 <1> ; cx = 0 2411 00001563 C3 <1> retn 2412 <1> 2413 <1> scroll_up: 2414 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2415 <1> ; 16/01/2016 2416 <1> ; 07/09/2014 2417 <1> ; 02/09/2014 2418 <1> ; 01/09/2014 (Retro UNIX 386 v1 - beginning) 2419 <1> ; 04/04/2014 2420 <1> ; 04/12/2013 2421 <1> ; 2422 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2423 <1> ; 2424 <1> ; SCROLL UP 2425 <1> ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP 2426 <1> ; ON THE SCREEN 2427 <1> ; INPUT 2428 <1> ; (AH) = CURRENT CRT MODE 2429 <1> ; (AL) = NUMBER OF ROWS TO SCROLL 2430 <1> ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER 2431 <1> ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER 2432 <1> ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE 2433 <1> ; (DS) = DATA SEGMENT 2434 <1> ; (ES) = REGEN BUFFER SEGMENT 2435 <1> ; OUTPUT 2436 <1> ; NONE -- THE REGEN BUFFER IS MODIFIED 2437 <1> ; 2438 <1> ; bh = 0 (02/09/2014) 2439 <1> ; 2440 <1> ; ((ah = 3)) 2441 <1> ; cl = left upper column 2442 <1> ; ch = left upper row 2443 <1> ; dl = right lower column 2444 <1> ; dh = right lower row 2445 <1> ; 2446 <1> ; al = line count 2447 <1> ; ah = attribute to be used on blanked line 2448 <1> ; bl = video page number (0 to 7) 2449 <1> ; 2450 <1> 2451 <1> ; Test Line Count 2452 00001564 08C0 <1> or al, al 2453 00001566 740C <1> jz short al_set 2454 00001568 88F7 <1> mov bh, dh ; subtract lower row from upper row 2455 0000156A 28EF <1> sub bh, ch 2456 0000156C FEC7 <1> inc bh ; adjust difference by 1 2457 0000156E 38C7 <1> cmp bh, al ; line count = amount of rows in window? 2458 00001570 7502 <1> jne short al_set ; if not the we're all set 2459 00001572 30C0 <1> xor al, al ; otherwise set al to zero 2460 <1> al_set: 2461 00001574 30FF <1> xor bh, bh ; 0 2462 <1> ;push ax 2463 00001576 50 <1> push eax ; 05/12/2021 2464 <1> ;mov esi, [crt_base] 2465 00001577 BE00800B00 <1> mov esi, 0B8000h 2466 0000157C 3A1D[D66D0000] <1> cmp bl, [active_page] 2467 00001582 750B <1> jne short n0 2468 <1> ; 2469 00001584 66A1[C46D0000] <1> mov ax, [CRT_START] 2470 0000158A 6601C6 <1> add si, ax 2471 0000158D EB0F <1> jmp short n1 2472 <1> n0: 2473 0000158F 20DB <1> and bl, bl 2474 00001591 740B <1> jz short n1 2475 00001593 88D8 <1> mov al, bl 2476 <1> n0x: 2477 <1> ;add si, [CRT_LEN] 2478 <1> ;add esi, 80*25*2 2479 00001595 6681C6A00F <1> add si, 80*25*2 2480 0000159A FEC8 <1> dec al 2481 0000159C 75F7 <1> jnz short n0x 2482 <1> n1: 2483 <1> ;Scroll position 2484 <1> ;push dx 2485 <1> ; 05/12/2021 2486 0000159E 52 <1> push edx 2487 0000159F 6689CA <1> mov dx, cx ; now, upper left position in DX 2488 000015A2 E885FFFFFF <1> call position 2489 000015A7 01C6 <1> add esi, eax 2490 000015A9 89F7 <1> mov edi, esi 2491 <1> ;pop dx ; lower right position in DX 2492 000015AB 5A <1> pop edx ; 05/12/2021 2493 000015AC 6629CA <1> sub dx, cx 2494 000015AF FEC6 <1> inc dh ; dh = #rows 2495 000015B1 FEC2 <1> inc dl ; dl = #cols in block 2496 <1> ;pop ax ; al = line count, ah = attribute 2497 <1> ; 05/12/2021 2498 000015B3 58 <1> pop eax ; al = line count, ah = attribute 2499 000015B4 31C9 <1> xor ecx, ecx 2500 000015B6 6689C1 <1> mov cx, ax 2501 <1> ;mov ah, [CRT_COLS] 2502 000015B9 B450 <1> mov ah, 80 2503 000015BB F6E4 <1> mul ah ; determine offset to from address 2504 000015BD 6601C0 <1> add ax, ax ; *2 for attribute byte 2505 <1> ; 2506 <1> ;push ax ; offset 2507 <1> ;push dx 2508 <1> ; 05/12/2021 2509 000015C0 50 <1> push eax 2510 000015C1 52 <1> push edx 2511 <1> ; 2512 <1> ; 04/04/2014 2513 000015C2 66BADA03 <1> mov dx, 3DAh ; guaranteed to be color card here 2514 <1> n8: ; wait_display_enable 2515 000015C6 EC <1> in al, dx ; get port 2516 000015C7 A808 <1> test al, RVRT ; wait for vertical retrace 2517 000015C9 74FB <1> jz short n8 ; wait_display_enable 2518 000015CB B025 <1> mov al, 25h 2519 000015CD B2D8 <1> mov dl, 0D8h ; address control port 2520 000015CF EE <1> out dx, al ; turn off video during vertical retrace 2521 <1> ;pop dx ; #rows, #cols 2522 <1> ;pop ax ; offset 2523 <1> ; 05/12/2021 2524 000015D0 5A <1> pop edx 2525 000015D1 58 <1> pop eax 2526 000015D2 6691 <1> xchg ax, cx ; 2527 <1> ; ecx = offset, al = line count, ah = attribute 2528 <1> ;n9: 2529 000015D4 08C0 <1> or al, al 2530 000015D6 7420 <1> jz short n3 2531 000015D8 01CE <1> add esi, ecx ; from address for scroll 2532 000015DA 88F7 <1> mov bh, dh ; #rows in block 2533 000015DC 28C7 <1> sub bh, al ; #rows to be moved 2534 <1> n2: 2535 <1> ; Move rows 2536 000015DE 88D1 <1> mov cl, dl ; get # of cols to move 2537 000015E0 56 <1> push esi 2538 000015E1 57 <1> push edi ; save start address 2539 <1> n10: 2540 000015E2 66A5 <1> movsw ; move that line on screen 2541 000015E4 FEC9 <1> dec cl 2542 000015E6 75FA <1> jnz short n10 2543 000015E8 5F <1> pop edi 2544 000015E9 5E <1> pop esi ; recover addresses 2545 <1> ;mov cl, [CRT_COLS] 2546 <1> ;add cl, cl 2547 <1> ;mov ecx, 80*2 2548 000015EA 66B9A000 <1> mov cx, 80*2 2549 000015EE 01CE <1> add esi, ecx ; next line 2550 000015F0 01CF <1> add edi, ecx 2551 000015F2 FECF <1> dec bh ; count of lines to move 2552 000015F4 75E8 <1> jnz short n2 ; row loop 2553 <1> ; bh = 0 2554 000015F6 88C6 <1> mov dh, al ; #rows 2555 <1> n3: 2556 <1> ; attribute in ah 2557 000015F8 B020 <1> mov al, ' ' ; fill with blanks 2558 <1> n3x: 2559 <1> ; Clear rows 2560 <1> ; dh = #rows 2561 000015FA 88D1 <1> mov cl, dl ; get # of cols to clear 2562 000015FC 57 <1> push edi ; save address 2563 <1> n11: 2564 000015FD 66AB <1> stosw ; store fill character 2565 000015FF FEC9 <1> dec cl 2566 00001601 75FA <1> jnz short n11 2567 00001603 5F <1> pop edi ; recover address 2568 <1> ;mov cl, [CRT_COLS] 2569 <1> ;add cl, cl 2570 <1> ;mov ecx, 80*2 2571 00001604 B1A0 <1> mov cl, 80*2 2572 00001606 01CF <1> add edi, ecx 2573 00001608 FECE <1> dec dh 2574 0000160A 75EE <1> jnz short n3x ; 16/01/2016 2575 <1> ; 2576 0000160C 3A1D[D66D0000] <1> cmp bl, [active_page] 2577 00001612 7507 <1> jne short n6 2578 <1> ;mov al, [CRT_MODE_SET] ; get the value of mode set 2579 00001614 B029 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 2580 00001616 66BAD803 <1> mov dx, 03D8h ; always set color card port 2581 0000161A EE <1> out dx, al 2582 <1> n6: 2583 0000161B C3 <1> retn 2584 <1> 2585 <1> 2586 <1> write_c_current: 2587 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2588 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2589 <1> ; 18/01/2014 2590 <1> ; 04/12/2013 2591 <1> ; 2592 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2593 <1> ; 2594 <1> ; WRITE_C_CURRENT 2595 <1> ; THIS ROUTINE WRITES THE CHARACTER AT 2596 <1> ; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED 2597 <1> ; INPUT 2598 <1> ; (AH) = CURRENT CRT MODE 2599 <1> ; (BH) = DISPLAY PAGE 2600 <1> ; (CX) = COUNT OF CHARACTERS TO WRITE 2601 <1> ; (AL) = CHAR TO WRITE 2602 <1> ; (DS) = DATA SEGMENT 2603 <1> ; (ES) = REGEN SEGMENT 2604 <1> ; OUTPUT 2605 <1> ; DISPLAY REGEN BUFFER UPDATED 2606 <1> 2607 0000161C FA <1> cli 2608 <1> ; bl = video page 2609 <1> ; al = character 2610 <1> ; ah = color/attribute 2611 <1> ;push dx 2612 <1> ;push ax ; save character & attribute/color 2613 <1> ; 05/12/2021 2614 0000161D 52 <1> push edx 2615 0000161E 50 <1> push eax 2616 0000161F E816FFFFFF <1> call find_position ; get regen location and port address 2617 <1> ; esi = regen location 2618 <1> ; dx = status port 2619 <1> ; 2620 <1> ; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE 2621 <1> ; 2622 <1> p41: ; wait for horizontal retrace is low or vertical 2623 00001624 FB <1> sti ; enable interrupts first 2624 00001625 3A1D[D66D0000] <1> cmp bl, [active_page] 2625 0000162B 7510 <1> jne short p44 2626 0000162D FA <1> cli ; block interrupts for single loop 2627 0000162E EC <1> in al, dx ; get status from the adapter 2628 0000162F A808 <1> test al, RVRT ; check for vertical retrace first 2629 00001631 7509 <1> jnz short p43 ; Do fast write now if vertical retrace 2630 00001633 A801 <1> test al, RHRZ ; is horizontal retrace low 2631 00001635 75ED <1> jnz short p41 ; wait until it is 2632 <1> p42: ; wait for either retrace high 2633 00001637 EC <1> in al, dx ; get status again 2634 00001638 A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 2635 0000163A 74FB <1> jz short p42 ; wait until either retrace active 2636 <1> p43: 2637 0000163C FB <1> sti 2638 <1> p44: 2639 <1> ;pop ax ; restore the character (al) & attribute (ah) 2640 <1> ; 05/12/2021 2641 0000163D 58 <1> pop eax 2642 0000163E 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (crt_base) 2643 <1> ; Retro UNIX 386 v1 feature only! 2644 00001644 668906 <1> mov [esi], ax 2645 <1> ;pop dx 2646 <1> ; 05/12/2021 2647 00001647 5A <1> pop edx 2648 00001648 C3 <1> retn 2649 <1> 2650 <1> set_mode: 2651 <1> ; 16/01/2016 2652 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2653 <1> ; 2654 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2655 <1> 2656 <1> ;------------------------------------------------------ 2657 <1> ; SET MODE : 2658 <1> ; THIS ROUTINE INITIALIZES THE ATTACHMENT TO : 2659 <1> ; THE SELECTED MODE, THE SCREEN IS BLANKED. : 2660 <1> ; INPUT : 2661 <1> ; (AL) - MODE SELECTED (RANGE 0-7) : 2662 <1> ; OUTPUT : 2663 <1> ; NONE : 2664 <1> ;------------------------------------------------------ 2665 <1> 2666 00001649 57 <1> push edi ; 16/01/2016 2667 0000164A 53 <1> push ebx 2668 0000164B 52 <1> push edx 2669 0000164C 51 <1> push ecx ; 16/01/2016 2670 0000164D 50 <1> push eax 2671 <1> 2672 <1> ;mov dx, 03D4h ; address or color card 2673 0000164E B003 <1> mov al, 3 2674 <1> ;M8: 2675 00001650 A2[D0670000] <1> mov [CRT_MODE], al ; save mode in global variable 2676 00001655 B029 <1> mov al, 29h 2677 <1> ;mov [CRT_MODE_SET], al ; save the mode set value 2678 00001657 2437 <1> and al, 037h ; video off, save high resolution bit 2679 <1> ;push dx ; save port value 2680 <1> ;add dx, 4 ; point to control register 2681 00001659 66BAD803 <1> mov dx, 3D8h 2682 0000165D EE <1> out dx, al ; reset video to off to suppress rolling 2683 <1> ;pop dx 2684 <1> ;M9: 2685 0000165E BB[08680000] <1> mov ebx, video_params ; initialization table 2686 <1> ;mov ax, [ebx+10] ; get the cursor mode from the table 2687 <1> ;xchg ah, al 2688 <1> ;mov [CURSOR_MODE], ax ; save cursor mode 2689 00001663 30E4 <1> xor ah, ah ; ah is register number during loop 2690 <1> 2691 <1> ;----- LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE 2692 00001665 B910000000 <1> mov ecx, 16 ; 16/01/2016 2693 <1> M10: ; initialization loop 2694 0000166A 88E0 <1> mov al, ah ; get 6845 register number 2695 0000166C EE <1> out dx, al 2696 0000166D 6642 <1> inc dx ; point to data port 2697 0000166F FEC4 <1> inc ah ; next register value 2698 00001671 8A03 <1> mov al, [ebx] ; get table value 2699 00001673 EE <1> out dx, al ; out to chip 2700 00001674 43 <1> inc ebx ; next in table 2701 00001675 664A <1> dec dx ; back to pointer register 2702 00001677 E2F1 <1> loop M10 ; do the whole table 2703 <1> 2704 <1> ;----- FILL REGEN AREA WITH BLANK 2705 <1> ;xor ax, ax 2706 <1> ;mov [CRT_START], ax ; start address saved in global 2707 <1> ;mov [ACTIVE_PAGE], al ; 0 ; (re)set page value 2708 <1> ;mov ecx, 8192 ; number of words in color card 2709 <1> ; black background, light gray characeter color, space character 2710 <1> ;mov ax, 0720h ; fill char for alpha - attribute 2711 <1> ;M13: ; clear buffer 2712 <1> ;add edi, 0B8000h ; [crt_base] 2713 <1> ;rep stosw ; FILL THE REGEN BUFFER WITH BLANKS 2714 <1> 2715 <1> ;----- ENABLE VIDEO AND CORRECT PORT SETTING 2716 <1> ;mov dx, 3D4h ; mov dx, word [ADDR_6845] 2717 <1> ; prepare to output to video enable port 2718 <1> ;add dx,4 ; point to the mode control gerister 2719 00001679 66BAD803 <1> mov dx, 3D8h 2720 <1> ;mov al, [CRT_MODE_SET] ; get the mode set value 2721 0000167D B029 <1> mov al, 29h 2722 0000167F EE <1> out dx, al ; set video enable port 2723 <1> 2724 <1> ;----- DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY 2725 <1> ;----- AND THE NUMBER TO BE USED FOR TTY INTERFACE 2726 <1> ; 2727 <1> ;mov byte [CRT_COLS], 80h ; initialize number of columns count 2728 <1> ; 2729 <1> ;----- SET CURSOR POSITIONS 2730 <1> ;push edi 2731 <1> ;mov word [CRT_LEN], 80*25*2 2732 00001680 BF[C66D0000] <1> mov edi, cursor_posn 2733 00001685 B904000000 <1> mov ecx, 4 ; clear all cursor positions (16 bytes) 2734 0000168A 31C0 <1> xor eax, eax 2735 0000168C F3AB <1> rep stosd ; fill with zeroes 2736 <1> ;pop edi 2737 <1> 2738 <1> ;----- SET UP OVERSCAN REGISTER 2739 0000168E 6642 <1> inc dx ; set overscan port to a default 2740 00001690 B030 <1> mov al, 30h ; 30H valuye for all modes except 640X200 bw 2741 <1> ;M14: 2742 00001692 EE <1> out dx, al ; output the correct value to 3D9 port 2743 <1> ;mov [CRT_PALETTE], al ; save the value for future use 2744 <1> 2745 <1> ;----- NORMAL RETURN FROM ALL VIDEO RETURNS 2746 <1> ; 2747 00001693 58 <1> pop eax 2748 00001694 59 <1> pop ecx ; 16/01/2016 2749 00001695 5A <1> pop edx 2750 00001696 5B <1> pop ebx 2751 00001697 5F <1> pop edi ; 16/01/2016 2752 00001698 C3 <1> retn 2753 <1> 2754 <1> tty_sw: 2755 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2756 <1> ; 30/06/2015 2757 <1> ; 27/06/2015 2758 <1> ; 07/09/2014 2759 <1> ; 02/09/2014 (Retro UNIX 386 v1 - beginning) 2760 <1> ; 2761 <1> ; (Modified registers : EAX) 2762 <1> ; 2763 <1> ;mov byte [u.quant], 0 ; 04/03/2014 2764 <1> ; 2765 <1> ;act_disp_page: 2766 <1> ; 30/06/2015 2767 <1> ; 04/03/2014 (act_disp_page --> tty_sw) 2768 <1> ; 10/12/2013 2769 <1> ; 04/12/2013 2770 <1> ; 2771 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2772 <1> ; 2773 <1> ; ACT_DISP_PAGE 2774 <1> ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING 2775 <1> ; THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT 2776 <1> ; INPUT 2777 <1> ; AL HAS THE NEW ACTIVE DISPLAY PAGE 2778 <1> ; OUTPUT 2779 <1> ; THE 6845 IS RESET TO DISPLAY THAT PAGE 2780 <1> 2781 <1> ;cli 2782 <1> 2783 00001699 53 <1> push ebx 2784 <1> ;push cx 2785 <1> ;push dx 2786 <1> ; 05/12/2021 2787 0000169A 51 <1> push ecx 2788 0000169B 52 <1> push edx 2789 <1> ; 2790 0000169C A2[D66D0000] <1> mov [active_page], al ; save active page value ; [ptty] 2791 <1> ;mov cx, [CRT_LEN] ; get saved length of regen buffer 2792 000016A1 66B9A00F <1> mov cx, 25*80*2 2793 <1> ; 27/06/2015 2794 000016A5 0FB6D8 <1> movzx ebx, al 2795 <1> ; 2796 000016A8 6698 <1> cbw ; 07/09/2014 (ah=0) 2797 000016AA 66F7E1 <1> mul cx ; display page times regen length 2798 <1> ; 10/12/2013 2799 000016AD 66A3[C46D0000] <1> mov [CRT_START], ax ; save start address for later 2800 000016B3 6689C1 <1> mov cx, ax ; start address to cx 2801 <1> ;sar cx, 1 2802 000016B6 66D1E9 <1> shr cx, 1 ; divide by 2 for 6845 handling 2803 000016B9 B40C <1> mov ah, 12 ; 6845 register for start address 2804 000016BB E849FEFFFF <1> call m16 2805 <1> ;sal bx, 1 2806 <1> ; 01/09/2014 2807 000016C0 D0E3 <1> shl bl, 1 ; *2 for word offset 2808 000016C2 81C3[C66D0000] <1> add ebx, cursor_posn 2809 000016C8 668B13 <1> mov dx, [ebx] ; get cursor for this page 2810 000016CB E825FEFFFF <1> call m18 2811 <1> ; 2812 <1> ;pop dx 2813 <1> ;pop cx 2814 <1> ; 05/12/2021 2815 000016D0 5A <1> pop edx 2816 000016D1 59 <1> pop ecx 2817 000016D2 5B <1> pop ebx 2818 <1> ; 2819 <1> ;sti 2820 <1> ; 2821 000016D3 C3 <1> retn 2822 <1> 2823 <1> ; % include 'vidata.inc' ; VIDEO DATA ; 11/03/2015 2824 <1> 2825 <1> ; /// End Of VIDEO FUNCTIONS /// 1856 1857 setup_rtc_int: 1858 ; source: http://wiki.osdev.org/RTC 1859 000016D4 FA cli ; disable interrupts 1860 ; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6) 1861 ; in order to change this ... 1862 ; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024 1863 ; (rate must be above 2 and not over 15) 1864 ; new rate = 15 --> 32768 >> (15-1) = 2 Hz 1865 000016D5 B08A mov al, 8Ah 1866 000016D7 E670 out 70h, al ; set index to register A, disable NMI 1867 000016D9 90 nop 1868 000016DA E471 in al, 71h ; get initial value of register A 1869 000016DC 88C4 mov ah, al 1870 000016DE 80E4F0 and ah, 0F0h 1871 000016E1 B08A mov al, 8Ah 1872 000016E3 E670 out 70h, al ; reset index to register A 1873 000016E5 88E0 mov al, ah 1874 000016E7 0C0F or al, 0Fh ; new rate (0Fh -> 15) 1875 000016E9 E671 out 71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 1876 ; enable RTC interrupt 1877 000016EB B08B mov al, 8Bh ; 1878 000016ED E670 out 70h, al ; select register B and disable NMI 1879 000016EF 90 nop 1880 000016F0 E471 in al, 71h ; read the current value of register B 1881 000016F2 88C4 mov ah, al ; 1882 000016F4 B08B mov al, 8Bh ; 1883 000016F6 E670 out 70h, al ; set the index again (a read will reset the index to register B) 1884 000016F8 88E0 mov al, ah ; 1885 000016FA 0C40 or al, 40h ; 1886 000016FC E671 out 71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B 1887 000016FE FB sti 1888 000016FF C3 retn 1889 1890 ; Write memory information 1891 ; Temporary Code 1892 ; 06/11/2014 1893 ; 14/08/2015 1894 memory_info: 1895 00001700 A1[AC6D0000] mov eax, [memory_size] ; in pages 1896 00001705 50 push eax 1897 00001706 C1E00C shl eax, 12 ; in bytes 1898 00001709 BB0A000000 mov ebx, 10 1899 0000170E 89D9 mov ecx, ebx ; 10 1900 00001710 BE[116A0000] mov esi, mem_total_b_str 1901 00001715 E8AE000000 call bintdstr 1902 0000171A 58 pop eax 1903 0000171B B107 mov cl, 7 1904 0000171D BE[356A0000] mov esi, mem_total_p_str 1905 00001722 E8A1000000 call bintdstr 1906 ; 14/08/2015 1907 00001727 E8B9000000 call calc_free_mem 1908 ; edx = calculated free pages 1909 ; ecx = 0 1910 0000172C A1[B06D0000] mov eax, [free_pages] 1911 00001731 39D0 cmp eax, edx ; calculated free mem value 1912 ; and initial free mem value are same or not? 1913 00001733 751D jne short pmim ; print mem info with '?' if not 1914 00001735 52 push edx ; free memory in pages 1915 ;mov eax, edx 1916 00001736 C1E00C shl eax, 12 ; convert page count 1917 ; to byte count 1918 00001739 B10A mov cl, 10 1919 0000173B BE[556A0000] mov esi, free_mem_b_str 1920 00001740 E883000000 call bintdstr 1921 00001745 58 pop eax 1922 00001746 B107 mov cl, 7 1923 00001748 BE[796A0000] mov esi, free_mem_p_str 1924 0000174D E876000000 call bintdstr 1925 pmim: 1926 00001752 BE[FF690000] mov esi, msg_memory_info 1927 pmim_nb: 1928 00001757 AC lodsb 1929 00001758 08C0 or al, al 1930 0000175A 740D jz short pmim_ok 1931 0000175C 56 push esi 1932 0000175D 31DB xor ebx, ebx ; 0 1933 ; Video page 0 (bl=0) 1934 0000175F B407 mov ah, 07h ; Black background, 1935 ; light gray forecolor 1936 00001761 E856FCFFFF call write_tty 1937 00001766 5E pop esi 1938 00001767 EBEE jmp short pmim_nb 1939 pmim_ok: 1940 00001769 C3 retn 1941 1942 ; Convert binary number to hexadecimal string 1943 ; 10/05/2015 1944 ; dsectpm.s (28/02/2015) 1945 ; Retro UNIX 386 v1 - Kernel v0.2.0.6 1946 ; 01/12/2014 1947 ; 25/11/2014 1948 ; 1949 bytetohex: 1950 ; INPUT -> 1951 ; AL = byte (binary number) 1952 ; OUTPUT -> 1953 ; AX = hexadecimal string 1954 ; 1955 0000176A 53 push ebx 1956 0000176B 31DB xor ebx, ebx 1957 0000176D 88C3 mov bl, al 1958 0000176F C0EB04 shr bl, 4 1959 00001772 8A9B[B8170000] mov bl, [ebx+hexchrs] 1960 00001778 86D8 xchg bl, al 1961 0000177A 80E30F and bl, 0Fh 1962 0000177D 8AA3[B8170000] mov ah, [ebx+hexchrs] 1963 00001783 5B pop ebx 1964 00001784 C3 retn 1965 1966 wordtohex: 1967 ; INPUT -> 1968 ; AX = word (binary number) 1969 ; OUTPUT -> 1970 ; EAX = hexadecimal string 1971 ; 1972 00001785 53 push ebx 1973 00001786 31DB xor ebx, ebx 1974 00001788 86E0 xchg ah, al 1975 0000178A 6650 push ax 1976 0000178C 88E3 mov bl, ah 1977 0000178E C0EB04 shr bl, 4 1978 00001791 8A83[B8170000] mov al, [ebx+hexchrs] 1979 00001797 88E3 mov bl, ah 1980 00001799 80E30F and bl, 0Fh 1981 0000179C 8AA3[B8170000] mov ah, [ebx+hexchrs] 1982 000017A2 C1E010 shl eax, 16 1983 000017A5 6658 pop ax 1984 000017A7 5B pop ebx 1985 000017A8 EBC0 jmp short bytetohex 1986 ;mov bl, al 1987 ;shr bl, 4 1988 ;mov bl, [ebx+hexchrs] 1989 ;xchg bl, al 1990 ;and bl, 0Fh 1991 ;mov ah, [ebx+hexchrs] 1992 ;pop ebx 1993 ;retn 1994 1995 dwordtohex: 1996 ; INPUT -> 1997 ; EAX = dword (binary number) 1998 ; OUTPUT -> 1999 ; EDX:EAX = hexadecimal string 2000 ; 2001 000017AA 50 push eax 2002 000017AB C1E810 shr eax, 16 2003 000017AE E8D2FFFFFF call wordtohex 2004 000017B3 89C2 mov edx, eax 2005 000017B5 58 pop eax 2006 ;call wordtohex 2007 ;retn 2008 ; 02/01/2022 2009 000017B6 EBCD jmp short wordtohex 2010 2011 ; 10/05/2015 2012 hex_digits: 2013 hexchrs: 2014 000017B8 303132333435363738- db '0123456789ABCDEF' 2014 000017C1 39414243444546 2015 2016 ; Convert binary number to decimal/numeric string 2017 ; 06/11/2014 2018 ; Temporary Code 2019 ; 2020 2021 bintdstr: 2022 ; EAX = binary number 2023 ; ESI = decimal/numeric string address 2024 ; EBX = divisor (10) 2025 ; ECX = string length (<=10) 2026 000017C8 01CE add esi, ecx 2027 btdstr0: 2028 000017CA 4E dec esi 2029 000017CB 31D2 xor edx, edx 2030 000017CD F7F3 div ebx 2031 000017CF 80C230 add dl, 30h 2032 000017D2 8816 mov [esi], dl 2033 000017D4 FEC9 dec cl 2034 000017D6 740C jz short btdstr2 ; 02/01/2022 (short jump) 2035 000017D8 09C0 or eax, eax 2036 000017DA 75EE jnz short btdstr0 2037 btdstr1: 2038 000017DC 4E dec esi 2039 000017DD C60620 mov byte [esi], 20h ; blank space 2040 000017E0 FEC9 dec cl 2041 000017E2 75F8 jnz short btdstr1 2042 btdstr2: 2043 000017E4 C3 retn 2044 2045 ; Calculate free memory pages on M.A.T. 2046 ; 06/11/2014 2047 ; Temporary Code 2048 ; 2049 2050 calc_free_mem: 2051 000017E5 31D2 xor edx, edx 2052 ;xor ecx, ecx 2053 ;mov cx, [mat_size] ; in pages 2054 ; 02/01/2022 2055 000017E7 8B0D[C06D0000] mov ecx, [mat_size] ; in pages 2056 000017ED C1E10A shl ecx, 10 ; 1024 dwords per page 2057 000017F0 BE00001000 mov esi, MEM_ALLOC_TBL 2058 cfm0: 2059 000017F5 AD lodsd 2060 000017F6 51 push ecx 2061 000017F7 B920000000 mov ecx, 32 2062 cfm1: 2063 000017FC D1E8 shr eax, 1 2064 000017FE 7301 jnc short cfm2 2065 00001800 42 inc edx 2066 cfm2: 2067 00001801 E2F9 loop cfm1 2068 00001803 59 pop ecx 2069 00001804 E2EF loop cfm0 2070 00001806 C3 retn 2071 2072 %include 'diskio.s' ; 07/03/2015 2073 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2074 <1> ; (re-write kernel for test by using previous version without a major defect) 2075 <1> ; **************************************************************************** 2076 <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC 2077 <1> ; Last Modification: 05/12/2021 2078 <1> ; 2079 <1> ; (Initialized Disk Parameters Data is in 'DISKDATA.INC') 2080 <1> ; (Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 2081 <1> 2082 <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project) 2083 <1> 2084 <1> ; ///////// DISK I/O SYSTEM /////////////// 2085 <1> 2086 <1> ; 06/02/2015 2087 <1> diskette_io: 2088 00001807 9C <1> pushfd 2089 00001808 0E <1> push cs 2090 00001809 E809000000 <1> call DISKETTE_IO_1 2091 0000180E C3 <1> retn 2092 <1> 2093 <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;; 2094 <1> ;////////////////////////////////////////////////////// 2095 <1> 2096 <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project) 2097 <1> ; 20/02/2015 2098 <1> ; 06/02/2015 (unix386.s) 2099 <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s) 2100 <1> ; 2101 <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC) 2102 <1> ; 2103 <1> ; ADISK.EQU 2104 <1> 2105 <1> ;----- Wait control constants 2106 <1> 2107 <1> ;amount of time to wait while RESET is active. 2108 <1> 2109 <1> WAITCPU_RESET_ON EQU 21 ;Reset on must last at least 14us 2110 <1> ;at 250 KBS xfer rate. 2111 <1> ;see INTEL MCS, 1985, pg. 5-456 2112 <1> 2113 <1> WAITCPU_FOR_STATUS EQU 100 ;allow 30 microseconds for 2114 <1> ;status register to become valid 2115 <1> ;before re-reading. 2116 <1> 2117 <1> ;After sending a byte to NEC, status register may remain 2118 <1> ;incorrectly set for 24 us. 2119 <1> 2120 <1> WAITCPU_RQM_LOW EQU 24 ;number of loops to check for 2121 <1> ;RQM low. 2122 <1> 2123 <1> ; COMMON.MAC 2124 <1> ; 2125 <1> ; Timing macros 2126 <1> ; 2127 <1> 2128 <1> %macro SIODELAY 0 ; SHORT IODELAY 2129 <1> jmp short $+2 2130 <1> %endmacro 2131 <1> 2132 <1> %macro IODELAY 0 ; NORMAL IODELAY 2133 <1> jmp short $+2 2134 <1> jmp short $+2 2135 <1> %endmacro 2136 <1> 2137 <1> %macro NEWIODELAY 0 2138 <1> out 0EBh,al 2139 <1> %endmacro 2140 <1> 2141 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 2142 <1> ;;; WAIT_FOR_MEM 2143 <1> ;WAIT_FDU_INT_LO equ 017798 ; 2.5 secs in 30 micro units. 2144 <1> ;WAIT_FDU_INT_HI equ 1 2145 <1> WAIT_FDU_INT_LH equ 83334 ; 27/02/2015 (2.5 seconds waiting) 2146 <1> ;;; WAIT_FOR_PORT 2147 <1> ;WAIT_FDU_SEND_LO equ 16667 ; .5 secons in 30 us units. 2148 <1> ;WAIT_FDU_SEND_HI equ 0 2149 <1> WAIT_FDU_SEND_LH equ 16667 ; 27/02/2015 2150 <1> ;Time to wait while waiting for each byte of NEC results = .5 2151 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 2152 <1> ;WAIT_FDU_RESULTS_LO equ 16667 ; .5 seconds in 30 micro units. 2153 <1> ;WAIT_FDU_RESULTS_HI equ 0 2154 <1> WAIT_FDU_RESULTS_LH equ 16667 ; 27/02/2015 2155 <1> ;;; WAIT_REFRESH 2156 <1> ;amount of time to wait for head settle, per unit in parameter 2157 <1> ;table = 1 ms. 2158 <1> WAIT_FDU_HEAD_SETTLE equ 33 ; 1 ms in 30 micro units. 2159 <1> 2160 <1> 2161 <1> ; //////////////// DISKETTE I/O //////////////// 2162 <1> 2163 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC) 2164 <1> 2165 <1> ;---------------------------------------- 2166 <1> ; EQUATES USED BY POST AND BIOS : 2167 <1> ;---------------------------------------- 2168 <1> 2169 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2170 <1> ;PORT_A EQU 060H ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2171 <1> ;PORT_B EQU 061H ; PORT B READ/WRITE DIAGNOSTIC REGISTER 2172 <1> ;REFRESH_BIT EQU 00010000B ; REFRESH TEST BIT 2173 <1> 2174 <1> ;---------------------------------------- 2175 <1> ; CMOS EQUATES FOR THIS SYSTEM : 2176 <1> ;------------------------------------------------------------------------------- 2177 <1> ;CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 2178 <1> ;CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 2179 <1> ;NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 2180 <1> ; HIGH BIT OF CMOS LOCATION ADDRESS 2181 <1> 2182 <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- 2183 <1> CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; 2184 <1> ; EQU 011H ; - RESERVED ;C 2185 <1> CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H 2186 <1> ; EQU 013H ; - RESERVED ;E 2187 <1> CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C 2188 <1> 2189 <1> ;---------- DISKETTE EQUATES --------------------------------------------------- 2190 <1> INT_FLAG EQU 10000000B ; INTERRUPT OCCURRENCE FLAG 2191 <1> DSK_CHG EQU 10000000B ; DISKETTE CHANGE FLAG MASK BIT 2192 <1> DETERMINED EQU 00010000B ; SET STATE DETERMINED IN STATE BITS 2193 <1> HOME EQU 00010000B ; TRACK 0 MASK 2194 <1> SENSE_DRV_ST EQU 00000100B ; SENSE DRIVE STATUS COMMAND 2195 <1> TRK_SLAP EQU 030H ; CRASH STOP (48 TPI DRIVES) 2196 <1> QUIET_SEEK EQU 00AH ; SEEK TO TRACK 10 2197 <1> ;MAX_DRV EQU 2 ; MAX NUMBER OF DRIVES 2198 <1> HD12_SETTLE EQU 15 ; 1.2 M HEAD SETTLE TIME 2199 <1> HD320_SETTLE EQU 20 ; 320 K HEAD SETTLE TIME 2200 <1> MOTOR_WAIT EQU 37 ; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF 2201 <1> 2202 <1> ;---------- DISKETTE ERRORS ---------------------------------------------------- 2203 <1> ;TIME_OUT EQU 080H ; ATTACHMENT FAILED TO RESPOND 2204 <1> ;BAD_SEEK EQU 040H ; SEEK OPERATION FAILED 2205 <1> BAD_NEC EQU 020H ; DISKETTE CONTROLLER HAS FAILED 2206 <1> BAD_CRC EQU 010H ; BAD CRC ON DISKETTE READ 2207 <1> MED_NOT_FND EQU 00CH ; MEDIA TYPE NOT FOUND 2208 <1> DMA_BOUNDARY EQU 009H ; ATTEMPT TO DMA ACROSS 64K BOUNDARY 2209 <1> BAD_DMA EQU 008H ; DMA OVERRUN ON OPERATION 2210 <1> MEDIA_CHANGE EQU 006H ; MEDIA REMOVED ON DUAL ATTACH CARD 2211 <1> RECORD_NOT_FND EQU 004H ; REQUESTED SECTOR NOT FOUND 2212 <1> WRITE_PROTECT EQU 003H ; WRITE ATTEMPTED ON WRITE PROTECT DISK 2213 <1> BAD_ADDR_MARK EQU 002H ; ADDRESS MARK NOT FOUND 2214 <1> BAD_CMD EQU 001H ; BAD COMMAND PASSED TO DISKETTE I/O 2215 <1> 2216 <1> ;---------- DISK CHANGE LINE EQUATES ------------------------------------------- 2217 <1> NOCHGLN EQU 001H ; NO DISK CHANGE LINE AVAILABLE 2218 <1> CHGLN EQU 002H ; DISK CHANGE LINE AVAILABLE 2219 <1> 2220 <1> ;---------- MEDIA/DRIVE STATE INDICATORS --------------------------------------- 2221 <1> TRK_CAPA EQU 00000001B ; 80 TRACK CAPABILITY 2222 <1> FMT_CAPA EQU 00000010B ; MULTIPLE FORMAT CAPABILITY (1.2M) 2223 <1> DRV_DET EQU 00000100B ; DRIVE DETERMINED 2224 <1> MED_DET EQU 00010000B ; MEDIA DETERMINED BIT 2225 <1> DBL_STEP EQU 00100000B ; DOUBLE STEP BIT 2226 <1> RATE_MSK EQU 11000000B ; MASK FOR CLEARING ALL BUT RATE 2227 <1> RATE_500 EQU 00000000B ; 500 KBS DATA RATE 2228 <1> RATE_300 EQU 01000000B ; 300 KBS DATA RATE 2229 <1> RATE_250 EQU 10000000B ; 250 KBS DATA RATE 2230 <1> STRT_MSK EQU 00001100B ; OPERATION START RATE MASK 2231 <1> SEND_MSK EQU 11000000B ; MASK FOR SEND RATE BITS 2232 <1> 2233 <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY ------------------------- 2234 <1> M3D3U EQU 00000000B ; 360 MEDIA/DRIVE NOT ESTABLISHED 2235 <1> M3D1U EQU 00000001B ; 360 MEDIA,1.2DRIVE NOT ESTABLISHED 2236 <1> M1D1U EQU 00000010B ; 1.2 MEDIA/DRIVE NOT ESTABLISHED 2237 <1> MED_UNK EQU 00000111B ; NONE OF THE ABOVE 2238 <1> 2239 <1> ;---------- INTERRUPT EQUATES -------------------------------------------------- 2240 <1> ;EOI EQU 020H ; END OF INTERRUPT COMMAND TO 8259 2241 <1> ;INTA00 EQU 020H ; 8259 PORT 2242 <1> INTA01 EQU 021H ; 8259 PORT 2243 <1> INTB00 EQU 0A0H ; 2ND 8259 2244 <1> INTB01 EQU 0A1H ; 2245 <1> 2246 <1> ;------------------------------------------------------------------------------- 2247 <1> DMA08 EQU 008H ; DMA STATUS REGISTER PORT ADDRESS 2248 <1> DMA EQU 000H ; DMA CH.0 ADDRESS REGISTER PORT ADDRESS 2249 <1> DMA18 EQU 0D0H ; 2ND DMA STATUS PORT ADDRESS 2250 <1> DMA1 EQU 0C0H ; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS 2251 <1> ;------------------------------------------------------------------------------- 2252 <1> ;TIMER EQU 040H ; 8254 TIMER - BASE ADDRESS 2253 <1> 2254 <1> ;------------------------------------------------------------------------------- 2255 <1> DMA_PAGE EQU 081H ; START OF DMA PAGE REGISTERS 2256 <1> 2257 <1> ; 06/02/2015 (unix386.s, protected mode modifications) 2258 <1> ; (unix386.s <-- dsectrm2.s) 2259 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC) 2260 <1> 2261 <1> ; 10/12/2014 2262 <1> ; 2263 <1> ;int40h: 2264 <1> ; pushf 2265 <1> ; push cs 2266 <1> ; ;cli 2267 <1> ; call DISKETTE_IO_1 2268 <1> ; retn 2269 <1> 2270 <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS 2271 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 2272 <1> ; 2273 <1> 2274 <1> ;-- INT13H --------------------------------------------------------------------- 2275 <1> ; DISKETTE I/O 2276 <1> ; THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB, 2277 <1> ; 1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES. 2278 <1> ; INPUT 2279 <1> ; (AH) = 00H RESET DISKETTE SYSTEM 2280 <1> ; HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED 2281 <1> ; ON ALL DRIVES 2282 <1> ;------------------------------------------------------------------------------- 2283 <1> ; (AH)= 01H READ THE STATUS OF THE SYSTEM INTO (AH) 2284 <1> ; @DISKETTE_STATUS FROM LAST OPERATION IS USED 2285 <1> ;------------------------------------------------------------------------------- 2286 <1> ; REGISTERS FOR READ/WRITE/VERIFY/FORMAT 2287 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 2288 <1> ; (DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED) 2289 <1> ; (CH) - TRACK NUMBER (NOT VALUE CHECKED) 2290 <1> ; MEDIA DRIVE TRACK NUMBER 2291 <1> ; 320/360 320/360 0-39 2292 <1> ; 320/360 1.2M 0-39 2293 <1> ; 1.2M 1.2M 0-79 2294 <1> ; 720K 720K 0-79 2295 <1> ; 1.44M 1.44M 0-79 2296 <1> ; (CL) - SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT) 2297 <1> ; MEDIA DRIVE SECTOR NUMBER 2298 <1> ; 320/360 320/360 1-8/9 2299 <1> ; 320/360 1.2M 1-8/9 2300 <1> ; 1.2M 1.2M 1-15 2301 <1> ; 720K 720K 1-9 2302 <1> ; 1.44M 1.44M 1-18 2303 <1> ; (AL) NUMBER OF SECTORS (NOT VALUE CHECKED) 2304 <1> ; MEDIA DRIVE MAX NUMBER OF SECTORS 2305 <1> ; 320/360 320/360 8/9 2306 <1> ; 320/360 1.2M 8/9 2307 <1> ; 1.2M 1.2M 15 2308 <1> ; 720K 720K 9 2309 <1> ; 1.44M 1.44M 18 2310 <1> ; 2311 <1> ; (ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY) 2312 <1> ; 2313 <1> ;------------------------------------------------------------------------------- 2314 <1> ; (AH)= 02H READ THE DESIRED SECTORS INTO MEMORY 2315 <1> ;------------------------------------------------------------------------------- 2316 <1> ; (AH)= 03H WRITE THE DESIRED SECTORS FROM MEMORY 2317 <1> ;------------------------------------------------------------------------------- 2318 <1> ; (AH)= 04H VERIFY THE DESIRED SECTORS 2319 <1> ;------------------------------------------------------------------------------- 2320 <1> ; (AH)= 05H FORMAT THE DESIRED TRACK 2321 <1> ; (ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS 2322 <1> ; FOR THE TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N), 2323 <1> ; WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 2324 <1> ; N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024), 2325 <1> ; THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK. 2326 <1> ; THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 2327 <1> ; READ/WRITE ACCESS. 2328 <1> ; PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN 2329 <1> ; ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION, 2330 <1> ; THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE' 2331 <1> ; (INT 13H, AH = 18H) MUST BE CALLED TO SET THE DISKETTE TYPE 2332 <1> ; THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE" 2333 <1> ; IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 2334 <1> ; MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE. 2335 <1> ; 2336 <1> ; THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO 2337 <1> ; FORMAT THE FOLLOWING MEDIAS: 2338 <1> ; --------------------------------------------- 2339 <1> ; : MEDIA : DRIVE : PARM 1 : PARM 2 : 2340 <1> ; --------------------------------------------- 2341 <1> ; : 320K : 320K/360K/1.2M : 50H : 8 : 2342 <1> ; : 360K : 320K/360K/1.2M : 50H : 9 : 2343 <1> ; : 1.2M : 1.2M : 54H : 15 : 2344 <1> ; : 720K : 720K/1.44M : 50H : 9 : 2345 <1> ; : 1.44M : 1.44M : 6CH : 18 : 2346 <1> ; --------------------------------------------- 2347 <1> ; NOTES: - PARM 1 = GAP LENGTH FOR FORMAT 2348 <1> ; - PARM 2 = EOT (LAST SECTOR ON TRACK) 2349 <1> ; - DISK BASE IS POINTED BY DISK POINTER LOCATED 2350 <1> ; AT ABSOLUTE ADDRESS 0:78. 2351 <1> ; - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS 2352 <1> ; SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES. 2353 <1> ;------------------------------------------------------------------------------- 2354 <1> ; (AH) = 08H READ DRIVE PARAMETERS 2355 <1> ; REGISTERS 2356 <1> ; INPUT 2357 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 2358 <1> ; OUTPUT 2359 <1> ; (ES:DI) POINTS TO DRIVE PARAMETER TABLE 2360 <1> ; (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS 2361 <1> ; (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS 2362 <1> ; BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK 2363 <1> ; (DH) - MAXIMUM HEAD NUMBER 2364 <1> ; (DL) - NUMBER OF DISKETTE DRIVES INSTALLED 2365 <1> ; (BH) - 0 2366 <1> ; (BL) - BITS 7 THRU 4 - 0 2367 <1> ; BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS 2368 <1> ; (AX) - 0 2369 <1> ; UNDER THE FOLLOWING CIRCUMSTANCES: 2370 <1> ; (1) THE DRIVE NUMBER IS INVALID, 2371 <1> ; (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 2372 <1> ; (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD, 2373 <1> ; (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID 2374 <1> ; THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 2375 <1> ; IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0. 2376 <1> ; @DISKETTE_STATUS = 0 AND CY IS RESET. 2377 <1> ;------------------------------------------------------------------------------- 2378 <1> ; (AH)= 15H READ DASD TYPE 2379 <1> ; OUTPUT REGISTERS 2380 <1> ; (AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR 2381 <1> ; 00 - DRIVE NOT PRESENT 2382 <1> ; 01 - DISKETTE, NO CHANGE LINE AVAILABLE 2383 <1> ; 02 - DISKETTE, CHANGE LINE AVAILABLE 2384 <1> ; 03 - RESERVED (FIXED DISK) 2385 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 2386 <1> ;------------------------------------------------------------------------------- 2387 <1> ; (AH)= 16H DISK CHANGE LINE STATUS 2388 <1> ; OUTPUT REGISTERS 2389 <1> ; (AH) - 00 - DISK CHANGE LINE NOT ACTIVE 2390 <1> ; 06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON 2391 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 2392 <1> ;------------------------------------------------------------------------------- 2393 <1> ; (AH)= 17H SET DASD TYPE FOR FORMAT 2394 <1> ; INPUT REGISTERS 2395 <1> ; (AL) - 00 - NOT USED 2396 <1> ; 01 - DISKETTE 320/360K IN 360K DRIVE 2397 <1> ; 02 - DISKETTE 360K IN 1.2M DRIVE 2398 <1> ; 03 - DISKETTE 1.2M IN 1.2M DRIVE 2399 <1> ; 04 - DISKETTE 720K IN 720K DRIVE 2400 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED: 2401 <1> ; (DO NOT USE WHEN DISKETTE ATTACH CARD USED) 2402 <1> ;------------------------------------------------------------------------------- 2403 <1> ; (AH)= 18H SET MEDIA TYPE FOR FORMAT 2404 <1> ; INPUT REGISTERS 2405 <1> ; (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS 2406 <1> ; (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS 2407 <1> ; BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK 2408 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED) 2409 <1> ; OUTPUT REGISTERS: 2410 <1> ; (ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE, 2411 <1> ; UNCHANGED IF (AH) IS NON-ZERO 2412 <1> ; (AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED 2413 <1> ; - 01H, CY = 1, FUNCTION IS NOT AVAILABLE 2414 <1> ; - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED 2415 <1> ; - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT) 2416 <1> ;------------------------------------------------------------------------------- 2417 <1> ; DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER 2418 <1> ; THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE 2419 <1> ; ACTIVE THE FOLLOWING ACTIONS TAKE PLACE: 2420 <1> ; ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 2421 <1> ; IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 2422 <1> ; CHANGE ERROR CODE 2423 <1> ; IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 2424 <1> ; TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN. 2425 <1> ; IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT. 2426 <1> ; 2427 <1> ; DATA VARIABLE -- @DISK_POINTER 2428 <1> ; DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS 2429 <1> ;------------------------------------------------------------------------------- 2430 <1> ; OUTPUT FOR ALL FUNCTIONS 2431 <1> ; AH = STATUS OF OPERATION 2432 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS 2433 <1> ; VARIABLE IN THE DATA SEGMENT OF THIS MODULE 2434 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD 2435 <1> ; TYPE AH=(15)). 2436 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) 2437 <1> ; FOR READ/WRITE/VERIFY 2438 <1> ; DS,BX,DX,CX PRESERVED 2439 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 2440 <1> ; ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION. 2441 <1> ; ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 2442 <1> ; THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 2443 <1> ; PROBLEM IS NOT DUE TO MOTOR START-UP. 2444 <1> ;------------------------------------------------------------------------------- 2445 <1> ; 2446 <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B) 2447 <1> ; 2448 <1> ; ----------------------------------------------------------------- 2449 <1> ; | | | | | | | | | 2450 <1> ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 2451 <1> ; | | | | | | | | | 2452 <1> ; ----------------------------------------------------------------- 2453 <1> ; | | | | | | | | 2454 <1> ; | | | | | ----------------- 2455 <1> ; | | | | | | 2456 <1> ; | | | | RESERVED | 2457 <1> ; | | | | PRESENT STATE 2458 <1> ; | | | | 000: 360K IN 360K DRIVE UNESTABLISHED 2459 <1> ; | | | | 001: 360K IN 1.2M DRIVE UNESTABLISHED 2460 <1> ; | | | | 010: 1.2M IN 1.2M DRIVE UNESTABLISHED 2461 <1> ; | | | | 011: 360K IN 360K DRIVE ESTABLISHED 2462 <1> ; | | | | 100: 360K IN 1.2M DRIVE ESTABLISHED 2463 <1> ; | | | | 101: 1.2M IN 1.2M DRIVE ESTABLISHED 2464 <1> ; | | | | 110: RESERVED 2465 <1> ; | | | | 111: NONE OF THE ABOVE 2466 <1> ; | | | | 2467 <1> ; | | | ------> MEDIA/DRIVE ESTABLISHED 2468 <1> ; | | | 2469 <1> ; | | --------------> DOUBLE STEPPING REQUIRED (360K IN 1.2M 2470 <1> ; | | DRIVE) 2471 <1> ; | | 2472 <1> ; ------------------------------> DATA TRANSFER RATE FOR THIS DRIVE: 2473 <1> ; 2474 <1> ; 00: 500 KBS 2475 <1> ; 01: 300 KBS 2476 <1> ; 10: 250 KBS 2477 <1> ; 11: RESERVED 2478 <1> ; 2479 <1> ; 2480 <1> ;------------------------------------------------------------------------------- 2481 <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B) 2482 <1> ;------------------------------------------------------------------------------- 2483 <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B) 2484 <1> ;------------------------------------------------------------------------------- 2485 <1> 2486 <1> struc MD 2487 00000000 ?? <1> .SPEC1 resb 1 ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2488 00000001 ?? <1> .SPEC2 resb 1 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2489 00000002 ?? <1> .OFF_TIM resb 1 ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2490 00000003 ?? <1> .BYT_SEC resb 1 ; 512 BYTES/SECTOR 2491 00000004 ?? <1> .SEC_TRK resb 1 ; EOT (LAST SECTOR ON TRACK) 2492 00000005 ?? <1> .GAP resb 1 ; GAP LENGTH 2493 00000006 ?? <1> .DTL resb 1 ; DTL 2494 00000007 ?? <1> .GAP3 resb 1 ; GAP LENGTH FOR FORMAT 2495 00000008 ?? <1> .FIL_BYT resb 1 ; FILL BYTE FOR FORMAT 2496 00000009 ?? <1> .HD_TIM resb 1 ; HEAD SETTLE TIME (MILLISECONDS) 2497 0000000A ?? <1> .STR_TIM resb 1 ; MOTOR START TIME (1/8 SECONDS) 2498 0000000B ?? <1> .MAX_TRK resb 1 ; MAX. TRACK NUMBER 2499 0000000C ?? <1> .RATE resb 1 ; DATA TRANSFER RATE 2500 <1> endstruc 2501 <1> 2502 <1> BIT7OFF EQU 7FH 2503 <1> BIT7ON EQU 80H 2504 <1> 2505 <1> ;;int13h: ; 16/02/2015 2506 <1> ;; 16/02/2015 - 21/02/2015 2507 <1> int40h: 2508 0000180F 9C <1> pushfd 2509 00001810 0E <1> push cs 2510 00001811 E801000000 <1> call DISKETTE_IO_1 2511 00001816 C3 <1> retn 2512 <1> 2513 <1> DISKETTE_IO_1: 2514 <1> 2515 00001817 FB <1> STI ; INTERRUPTS BACK ON 2516 00001818 55 <1> PUSH eBP ; USER REGISTER 2517 00001819 57 <1> PUSH eDI ; USER REGISTER 2518 0000181A 52 <1> PUSH eDX ; HEAD #, DRIVE # OR USER REGISTER 2519 0000181B 53 <1> PUSH eBX ; BUFFER OFFSET PARAMETER OR REGISTER 2520 0000181C 51 <1> PUSH eCX ; TRACK #-SECTOR # OR USER REGISTER 2521 0000181D 89E5 <1> MOV eBP,eSP ; BP => PARAMETER LIST DEP. ON AH 2522 <1> ; [BP] = SECTOR # 2523 <1> ; [BP+1] = TRACK # 2524 <1> ; [BP+2] = BUFFER OFFSET 2525 <1> ; FOR RETURN OF DRIVE PARAMETERS: 2526 <1> ; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL 2527 <1> ; BITS 0-5 MAX SECTORS/TRACK 2528 <1> ; CH/[BP+1] = LOW 8 BITS OF MAX CYL. 2529 <1> ; BL/[BP+2] = BITS 7-4 = 0 2530 <1> ; BITS 3-0 = VALID CMOS TYPE 2531 <1> ; BH/[BP+3] = 0 2532 <1> ; DL/[BP+4] = # DRIVES INSTALLED 2533 <1> ; DH/[BP+5] = MAX HEAD # 2534 <1> ; DI/[BP+6] = OFFSET TO DISK BASE 2535 0000181F 06 <1> push es ; 06/02/2015 2536 00001820 1E <1> PUSH DS ; BUFFER SEGMENT PARM OR USER REGISTER 2537 00001821 56 <1> PUSH eSI ; USER REGISTERS 2538 <1> ;CALL DDS ; SEGMENT OF BIOS DATA AREA TO DS 2539 <1> ;mov cx, cs 2540 <1> ;mov ds, cx 2541 00001822 66B91000 <1> mov cx, KDATA 2542 00001826 8ED9 <1> mov ds, cx 2543 00001828 8EC1 <1> mov es, cx 2544 <1> 2545 <1> ;CMP AH,(FNC_TAE-FNC_TAB)/2 ; CHECK FOR > LARGEST FUNCTION 2546 0000182A 80FC19 <1> cmp ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015 2547 0000182D 7202 <1> JB short OK_FUNC ; FUNCTION OK 2548 0000182F B414 <1> MOV AH,14H ; REPLACE WITH KNOWN INVALID FUNCTION 2549 <1> OK_FUNC: 2550 00001831 80FC01 <1> CMP AH,1 ; RESET OR STATUS ? 2551 00001834 760C <1> JBE short OK_DRV ; IF RESET OR STATUS DRIVE ALWAYS OK 2552 00001836 80FC08 <1> CMP AH,8 ; READ DRIVE PARMS ? 2553 00001839 7407 <1> JZ short OK_DRV ; IF SO DRIVE CHECKED LATER 2554 0000183B 80FA01 <1> CMP DL,1 ; DRIVES 0 AND 1 OK 2555 0000183E 7602 <1> JBE short OK_DRV ; IF 0 OR 1 THEN JUMP 2556 00001840 B414 <1> MOV AH,14H ; REPLACE WITH KNOWN INVALID FUNCTION 2557 <1> OK_DRV: 2558 00001842 31C9 <1> xor ecx, ecx 2559 <1> ;mov esi, ecx ; 08/02/2015 2560 <1> ; 05/12/2021 2561 00001844 89CE <1> mov esi, ecx 2562 00001846 89CF <1> mov edi, ecx ; 08/02/2015 2563 00001848 88E1 <1> MOV CL,AH ; CL = FUNCTION 2564 <1> ;XOR CH,CH ; CX = FUNCTION 2565 <1> ;SHL CL, 1 ; FUNCTION TIMES 2 2566 0000184A C0E102 <1> SHL CL, 2 ; 20/02/2015 ; FUNCTION TIMES 4 (for 32 bit offset) 2567 0000184D BB[85180000] <1> MOV eBX,FNC_TAB ; LOAD START OF FUNCTION TABLE 2568 00001852 01CB <1> ADD eBX,eCX ; ADD OFFSET INTO TABLE => ROUTINE 2569 00001854 88F4 <1> MOV AH,DH ; AX = HEAD #,# OF SECTORS OR DASD TYPE 2570 00001856 30F6 <1> XOR DH,DH ; DX = DRIVE # 2571 00001858 6689C6 <1> MOV SI,AX ; SI = HEAD #,# OF SECTORS OR DASD TYPE 2572 0000185B 6689D7 <1> MOV DI,DX ; DI = DRIVE # 2573 <1> ; 2574 <1> ; 11/12/2014 2575 0000185E 8815[91680000] <1> mov [cfd], dl ; current floppy drive (for 'GET_PARM') 2576 <1> ; 2577 00001864 8A25[2C6E0000] <1> MOV AH, [DSKETTE_STATUS] ; LOAD STATUS TO AH FOR STATUS FUNCTION 2578 0000186A C605[2C6E0000]00 <1> MOV byte [DSKETTE_STATUS],0 ; INITIALIZE FOR ALL OTHERS 2579 <1> 2580 <1> ; THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN 2581 <1> ; THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS 2582 <1> ; FUNCTIONS REQUIRE ALL OF THESE PARAMETERS. 2583 <1> ; 2584 <1> ; DI : DRIVE # 2585 <1> ; SI-HI : HEAD # 2586 <1> ; SI-LOW : # OF SECTORS OR DASD TYPE FOR FORMAT 2587 <1> ; ES : BUFFER SEGMENT 2588 <1> ; [BP] : SECTOR # 2589 <1> ; [BP+1] : TRACK # 2590 <1> ; [BP+2] : BUFFER OFFSET 2591 <1> ; 2592 <1> ; ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 2593 <1> ; SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 2594 <1> ; CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 2595 <1> ; SPECIFIC ERROR CODE. 2596 <1> ; 2597 <1> ; (AH) = @DSKETTE_STATUS 2598 00001871 FF13 <1> CALL dWORD [eBX] ; CALL THE REQUESTED FUNCTION 2599 00001873 5E <1> POP eSI ; RESTORE ALL REGISTERS 2600 00001874 1F <1> POP DS 2601 00001875 07 <1> pop es ; 06/02/2015 2602 00001876 59 <1> POP eCX 2603 00001877 5B <1> POP eBX 2604 00001878 5A <1> POP eDX 2605 00001879 5F <1> POP eDI 2606 0000187A 89E5 <1> MOV eBP, eSP 2607 0000187C 50 <1> PUSH eAX 2608 0000187D 9C <1> PUSHFd 2609 0000187E 58 <1> POP eAX 2610 <1> ;MOV [BP+6], AX 2611 0000187F 89450C <1> mov [ebp+12], eax ; 18/02/2015, flags 2612 00001882 58 <1> POP eAX 2613 00001883 5D <1> POP eBP 2614 00001884 CF <1> IRETd 2615 <1> 2616 <1> ;------------------------------------------------------------------------------- 2617 <1> ; DW --> dd (06/02/2015) 2618 00001885 [E9180000] <1> FNC_TAB dd DSK_RESET ; AH = 00H; RESET 2619 00001889 [5E190000] <1> dd DSK_STATUS ; AH = 01H; STATUS 2620 0000188D [6E190000] <1> dd DSK_READ ; AH = 02H; READ 2621 00001891 [7F190000] <1> dd DSK_WRITE ; AH = 03H; WRITE 2622 00001895 [90190000] <1> dd DSK_VERF ; AH = 04H; VERIFY 2623 00001899 [A1190000] <1> dd DSK_FORMAT ; AH = 05H; FORMAT 2624 0000189D [251A0000] <1> dd FNC_ERR ; AH = 06H; INVALID 2625 000018A1 [251A0000] <1> dd FNC_ERR ; AH = 07H; INVALID 2626 000018A5 [311A0000] <1> dd DSK_PARMS ; AH = 08H; READ DRIVE PARAMETERS 2627 000018A9 [251A0000] <1> dd FNC_ERR ; AH = 09H; INVALID 2628 000018AD [251A0000] <1> dd FNC_ERR ; AH = 0AH; INVALID 2629 000018B1 [251A0000] <1> dd FNC_ERR ; AH = 0BH; INVALID 2630 000018B5 [251A0000] <1> dd FNC_ERR ; AH = 0CH; INVALID 2631 000018B9 [251A0000] <1> dd FNC_ERR ; AH = 0DH; INVALID 2632 000018BD [251A0000] <1> dd FNC_ERR ; AH = 0EH; INVALID 2633 000018C1 [251A0000] <1> dd FNC_ERR ; AH = 0FH; INVALID 2634 000018C5 [251A0000] <1> dd FNC_ERR ; AH = 10H; INVALID 2635 000018C9 [251A0000] <1> dd FNC_ERR ; AH = 11H; INVALID 2636 000018CD [251A0000] <1> dd FNC_ERR ; AH = 12H; INVALID 2637 000018D1 [251A0000] <1> dd FNC_ERR ; AH = 13H; INVALID 2638 000018D5 [251A0000] <1> dd FNC_ERR ; AH = 14H; INVALID 2639 000018D9 [F01A0000] <1> dd DSK_TYPE ; AH = 15H; READ DASD TYPE 2640 000018DD [181B0000] <1> dd DSK_CHANGE ; AH = 16H; CHANGE STATUS 2641 000018E1 [511B0000] <1> dd FORMAT_SET ; AH = 17H; SET DASD TYPE 2642 000018E5 [D21B0000] <1> dd SET_MEDIA ; AH = 18H; SET MEDIA TYPE 2643 <1> FNC_TAE EQU $ ; END 2644 <1> 2645 <1> ;------------------------------------------------------------------------------- 2646 <1> ; DISK_RESET (AH = 00H) 2647 <1> ; RESET THE DISKETTE SYSTEM. 2648 <1> ; 2649 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2650 <1> ;------------------------------------------------------------------------------- 2651 <1> DSK_RESET: 2652 000018E9 66BAF203 <1> MOV DX,03F2H ; ADAPTER CONTROL PORT 2653 000018ED FA <1> CLI ; NO INTERRUPTS 2654 000018EE A0[2A6E0000] <1> MOV AL,[MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 2655 000018F3 243F <1> AND AL,00111111B ; KEEP SELECTED AND MOTOR ON BITS 2656 000018F5 C0C004 <1> ROL AL,4 ; MOTOR VALUE TO HIGH NIBBLE 2657 <1> ; DRIVE SELECT TO LOW NIBBLE 2658 000018F8 0C08 <1> OR AL,00001000B ; TURN ON INTERRUPT ENABLE 2659 000018FA EE <1> OUT DX,AL ; RESET THE ADAPTER 2660 000018FB C605[296E0000]00 <1> MOV byte [SEEK_STATUS],0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 2661 <1> ;JMP $+2 ; WAIT FOR I/O 2662 <1> ;JMP $+2 ; WAIT FOR I/O (TO INSURE MINIMUM 2663 <1> ; PULSE WIDTH) 2664 <1> ; 19/12/2014 2665 <1> NEWIODELAY 2138 00001902 E6EB <2> out 0EBh,al 2666 <1> 2667 <1> ; 17/12/2014 2668 <1> ; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM) 2669 00001904 B915000000 <1> mov ecx, WAITCPU_RESET_ON ; cx = 21 -- Min. 14 micro seconds !? 2670 <1> wdw1: 2671 <1> NEWIODELAY ; 27/02/2015 2138 00001909 E6EB <2> out 0EBh,al 2672 0000190B E2FC <1> loop wdw1 2673 <1> ; 2674 0000190D 0C04 <1> OR AL,00000100B ; TURN OFF RESET BIT 2675 0000190F EE <1> OUT DX,AL ; RESET THE ADAPTER 2676 <1> ; 16/12/2014 2677 <1> IODELAY 2133 00001910 EB00 <2> jmp short $+2 2134 00001912 EB00 <2> jmp short $+2 2678 <1> ; 2679 <1> ;STI ; ENABLE THE INTERRUPTS 2680 00001914 E8EC0B0000 <1> CALL WAIT_INT ; WAIT FOR THE INTERRUPT 2681 00001919 723A <1> JC short DR_ERR ; IF ERROR, RETURN IT 2682 0000191B 66B9C000 <1> MOV CX,11000000B ; CL = EXPECTED @NEC_STATUS 2683 <1> NXT_DRV: 2684 <1> ;PUSH CX ; SAVE FOR CALL 2685 <1> ; 05/12/2021 2686 0000191F 51 <1> push ecx 2687 00001920 B8[54190000] <1> MOV eAX, DR_POP_ERR ; LOAD NEC_OUTPUT ERROR ADDRESS 2688 00001925 50 <1> PUSH eAX ; " 2689 00001926 B408 <1> MOV AH,08H ; SENSE INTERRUPT STATUS COMMAND 2690 00001928 E8CE0A0000 <1> CALL NEC_OUTPUT 2691 0000192D 58 <1> POP eAX ; THROW AWAY ERROR RETURN 2692 0000192E E8020C0000 <1> CALL RESULTS ; READ IN THE RESULTS 2693 <1> ;POP CX ; RESTORE AFTER CALL 2694 <1> ; 05/12/2021 2695 00001933 59 <1> pop ecx 2696 00001934 721F <1> JC short DR_ERR ; ERROR RETURN 2697 00001936 3A0D[2D6E0000] <1> CMP CL, [NEC_STATUS] ; TEST FOR DRIVE READY TRANSITION 2698 0000193C 7517 <1> JNZ short DR_ERR ; EVERYTHING OK 2699 0000193E FEC1 <1> INC CL ; NEXT EXPECTED @NEC_STATUS 2700 00001940 80F9C3 <1> CMP CL,11000011B ; ALL POSSIBLE DRIVES CLEARED 2701 00001943 76DA <1> JBE short NXT_DRV ; FALL THRU IF 11000100B OR > 2702 <1> ; 2703 00001945 E843030000 <1> CALL SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 2704 <1> RESBAC: 2705 0000194A E8D8080000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 2706 <1> ;MOV BX,SI ; GET SAVED AL TO BL 2707 <1> ; 05/12/2021 2708 0000194F 89F3 <1> mov ebx, esi 2709 00001951 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 2710 00001953 C3 <1> RETn 2711 <1> DR_POP_ERR: 2712 <1> ;POP CX ; CLEAR STACK 2713 <1> ; 05/12/2021 2714 00001954 59 <1> pop ecx 2715 <1> DR_ERR: 2716 00001955 800D[2C6E0000]20 <1> OR byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE 2717 0000195C EBEC <1> JMP SHORT RESBAC ; RETURN FROM RESET 2718 <1> 2719 <1> ;------------------------------------------------------------------------------- 2720 <1> ; DISK_STATUS (AH = 01H) 2721 <1> ; DISKETTE STATUS. 2722 <1> ; 2723 <1> ; ON ENTRY: AH : STATUS OF PREVIOUS OPERATION 2724 <1> ; 2725 <1> ; ON EXIT: AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION. 2726 <1> ;------------------------------------------------------------------------------- 2727 <1> DSK_STATUS: 2728 0000195E 8825[2C6E0000] <1> MOV [DSKETTE_STATUS],AH ; PUT BACK FOR SETUP END 2729 00001964 E8BE080000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 2730 <1> ;MOV BX,SI ; GET SAVED AL TO BL 2731 <1> ; 05/12/2021 2732 00001969 89F3 <1> mov ebx, esi 2733 0000196B 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 2734 0000196D C3 <1> RETn 2735 <1> 2736 <1> ;------------------------------------------------------------------------------- 2737 <1> ; DISK_READ (AH = 02H) 2738 <1> ; DISKETTE READ. 2739 <1> ; 2740 <1> ; ON ENTRY: DI : DRIVE # 2741 <1> ; SI-HI : HEAD # 2742 <1> ; SI-LOW : # OF SECTORS 2743 <1> ; ES : BUFFER SEGMENT 2744 <1> ; [BP] : SECTOR # 2745 <1> ; [BP+1] : TRACK # 2746 <1> ; [BP+2] : BUFFER OFFSET 2747 <1> ; 2748 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2749 <1> ;------------------------------------------------------------------------------- 2750 <1> 2751 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 2752 <1> 2753 <1> DSK_READ: 2754 0000196E 8025[2A6E0000]7F <1> AND byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION 2755 00001975 66B846E6 <1> MOV AX,0E646H ; AX = NEC COMMAND, DMA COMMAND 2756 00001979 E815040000 <1> CALL RD_WR_VF ; COMMON READ/WRITE/VERIFY 2757 0000197E C3 <1> RETn 2758 <1> 2759 <1> ;------------------------------------------------------------------------------- 2760 <1> ; DISK_WRITE (AH = 03H) 2761 <1> ; DISKETTE WRITE. 2762 <1> ; 2763 <1> ; ON ENTRY: DI : DRIVE # 2764 <1> ; SI-HI : HEAD # 2765 <1> ; SI-LOW : # OF SECTORS 2766 <1> ; ES : BUFFER SEGMENT 2767 <1> ; [BP] : SECTOR # 2768 <1> ; [BP+1] : TRACK # 2769 <1> ; [BP+2] : BUFFER OFFSET 2770 <1> ; 2771 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2772 <1> ;------------------------------------------------------------------------------- 2773 <1> 2774 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 2775 <1> 2776 <1> DSK_WRITE: 2777 0000197F 66B84AC5 <1> MOV AX,0C54AH ; AX = NEC COMMAND, DMA COMMAND 2778 00001983 800D[2A6E0000]80 <1> OR byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION 2779 0000198A E804040000 <1> CALL RD_WR_VF ; COMMON READ/WRITE/VERIFY 2780 0000198F C3 <1> RETn 2781 <1> 2782 <1> ;------------------------------------------------------------------------------- 2783 <1> ; DISK_VERF (AH = 04H) 2784 <1> ; DISKETTE VERIFY. 2785 <1> ; 2786 <1> ; ON ENTRY: DI : DRIVE # 2787 <1> ; SI-HI : HEAD # 2788 <1> ; SI-LOW : # OF SECTORS 2789 <1> ; ES : BUFFER SEGMENT 2790 <1> ; [BP] : SECTOR # 2791 <1> ; [BP+1] : TRACK # 2792 <1> ; [BP+2] : BUFFER OFFSET 2793 <1> ; 2794 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2795 <1> ;------------------------------------------------------------------------------- 2796 <1> DSK_VERF: 2797 00001990 8025[2A6E0000]7F <1> AND byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION 2798 00001997 66B842E6 <1> MOV AX,0E642H ; AX = NEC COMMAND, DMA COMMAND 2799 0000199B E8F3030000 <1> CALL RD_WR_VF ; COMMON READ/WRITE/VERIFY 2800 000019A0 C3 <1> RETn 2801 <1> 2802 <1> ;------------------------------------------------------------------------------- 2803 <1> ; DISK_FORMAT (AH = 05H) 2804 <1> ; DISKETTE FORMAT. 2805 <1> ; 2806 <1> ; ON ENTRY: DI : DRIVE # 2807 <1> ; SI-HI : HEAD # 2808 <1> ; SI-LOW : # OF SECTORS 2809 <1> ; ES : BUFFER SEGMENT 2810 <1> ; [BP] : SECTOR # 2811 <1> ; [BP+1] : TRACK # 2812 <1> ; [BP+2] : BUFFER OFFSET 2813 <1> ; @DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE 2814 <1> ; 2815 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2816 <1> ;------------------------------------------------------------------------------- 2817 <1> DSK_FORMAT: 2818 000019A1 E830030000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 2819 000019A6 E81D050000 <1> CALL FMT_INIT ; ESTABLISH STATE IF UNESTABLISHED 2820 000019AB 800D[2A6E0000]80 <1> OR byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION 2821 000019B2 E865050000 <1> CALL MED_CHANGE ; CHECK MEDIA CHANGE AND RESET IF SO 2822 000019B7 725D <1> JC short FM_DON ; MEDIA CHANGED, SKIP 2823 000019B9 E8CF020000 <1> CALL SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 2824 000019BE E8C9050000 <1> CALL CHK_LASTRATE ; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE 2825 000019C3 7405 <1> JZ short FM_WR ; YES, SKIP SPECIFY COMMAND 2826 000019C5 E8A2050000 <1> CALL SEND_RATE ; SEND DATA RATE TO CONTROLLER 2827 <1> FM_WR: 2828 000019CA E84F060000 <1> CALL FMTDMA_SET ; SET UP THE DMA FOR FORMAT 2829 000019CF 7245 <1> JC short FM_DON ; RETURN WITH ERROR 2830 000019D1 B44D <1> MOV AH,04DH ; ESTABLISH THE FORMAT COMMAND 2831 000019D3 E8A7060000 <1> CALL NEC_INIT ; INITIALIZE THE NEC 2832 000019D8 723C <1> JC short FM_DON ; ERROR - EXIT 2833 000019DA B8[161A0000] <1> MOV eAX, FM_DON ; LOAD ERROR ADDRESS 2834 000019DF 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 2835 000019E0 B203 <1> MOV DL,3 ; BYTES/SECTOR VALUE TO NEC 2836 000019E2 E80E090000 <1> CALL GET_PARM 2837 000019E7 E80F0A0000 <1> CALL NEC_OUTPUT 2838 000019EC B204 <1> MOV DL,4 ; SECTORS/TRACK VALUE TO NEC 2839 000019EE E802090000 <1> CALL GET_PARM 2840 000019F3 E8030A0000 <1> CALL NEC_OUTPUT 2841 000019F8 B207 <1> MOV DL,7 ; GAP LENGTH VALUE TO NEC 2842 000019FA E8F6080000 <1> CALL GET_PARM 2843 000019FF E8F7090000 <1> CALL NEC_OUTPUT 2844 00001A04 B208 <1> MOV DL,8 ; FILLER BYTE TO NEC 2845 00001A06 E8EA080000 <1> CALL GET_PARM 2846 00001A0B E8EB090000 <1> CALL NEC_OUTPUT 2847 00001A10 58 <1> POP eAX ; THROW AWAY ERROR 2848 00001A11 E8E5060000 <1> CALL NEC_TERM ; TERMINATE, RECEIVE STATUS, ETC, 2849 <1> FM_DON: 2850 00001A16 E8EC020000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 2851 00001A1B E807080000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 2852 <1> ;MOV BX,SI ; GET SAVED AL TO BL 2853 00001A20 89F3 <1> mov ebx, esi ; 05/12/2021 2854 00001A22 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 2855 00001A24 C3 <1> RETn 2856 <1> 2857 <1> ;------------------------------------------------------------------------------- 2858 <1> ; FNC_ERR 2859 <1> ; INVALID FUNCTION REQUESTED OR INVALID DRIVE: 2860 <1> ; SET BAD COMMAND IN STATUS. 2861 <1> ; 2862 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2863 <1> ;------------------------------------------------------------------------------- 2864 <1> FNC_ERR: ; INVALID FUNCTION REQUEST 2865 <1> ;MOV AX,SI ; RESTORE AL 2866 <1> ; 05/12/2021 2867 00001A25 89F0 <1> mov eax, esi 2868 00001A27 B401 <1> MOV AH,BAD_CMD ; SET BAD COMMAND ERROR 2869 00001A29 8825[2C6E0000] <1> MOV [DSKETTE_STATUS],AH ; STORE IN DATA AREA 2870 00001A2F F9 <1> STC ; SET CARRY INDICATING ERROR 2871 00001A30 C3 <1> RETn 2872 <1> 2873 <1> ;------------------------------------------------------------------------------- 2874 <1> ; DISK_PARMS (AH = 08H) 2875 <1> ; READ DRIVE PARAMETERS. 2876 <1> ; 2877 <1> ; ON ENTRY: DI : DRIVE # 2878 <1> ; 2879 <1> ; ON EXIT: CL/[BP] = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER 2880 <1> ; BITS 0-5 MAX SECTORS/TRACK 2881 <1> ; CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER 2882 <1> ; BL/[BP+2] = BITS 7-4 = 0 2883 <1> ; BITS 3-0 = VALID CMOS DRIVE TYPE 2884 <1> ; BH/[BP+3] = 0 2885 <1> ; DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED) 2886 <1> ; DH/[BP+5] = MAX HEAD # 2887 <1> ; DI/[BP+6] = OFFSET TO DISK_BASE 2888 <1> ; ES = SEGMENT OF DISK_BASE 2889 <1> ; AX = 0 2890 <1> ; 2891 <1> ; NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT 2892 <1> ; THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM 2893 <1> ; INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE 2894 <1> ; CALLER. 2895 <1> ;------------------------------------------------------------------------------- 2896 <1> DSK_PARMS: 2897 00001A31 E8A0020000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH, 2898 <1> ; MOV WORD [BP+2],0 ; DRIVE TYPE = 0 2899 00001A36 29D2 <1> sub edx, edx ; 20/02/2015 2900 00001A38 895504 <1> mov [ebp+4], edx ; 20/02/2015 2901 <1> ; MOV AX, [EQUIP_FLAG] ; LOAD EQUIPMENT FLAG FOR # DISKETTES 2902 <1> ; AND AL,11000001B ; KEEP DISKETTE DRIVE BITS 2903 <1> ; MOV DL,2 ; DISKETTE DRIVES = 2 2904 <1> ; CMP AL,01000001B ; 2 DRIVES INSTALLED ? 2905 <1> ; JZ short STO_DL ; IF YES JUMP 2906 <1> ; DEC DL ; DISKETTE DRIVES = 1 2907 <1> ; CMP AL,00000001B ; 1 DRIVE INSTALLED ? 2908 <1> ; JNZ short NON_DRV ; IF NO JUMP 2909 <1> ;sub edx, edx 2910 00001A3B 66A1[9E680000] <1> mov ax, [fd0_type] 2911 00001A41 6621C0 <1> and ax, ax 2912 00001A44 7473 <1> jz short NON_DRV 2913 00001A46 FEC2 <1> inc dl 2914 00001A48 20E4 <1> and ah, ah 2915 00001A4A 7402 <1> jz short STO_DL 2916 00001A4C FEC2 <1> inc dl 2917 <1> STO_DL: 2918 <1> ;MOV [BP+4],DL ; STORE NUMBER OF DRIVES 2919 00001A4E 895508 <1> mov [ebp+8], edx ; 20/02/2015 2920 00001A51 6683FF01 <1> CMP DI,1 ; CHECK FOR VALID DRIVE 2921 00001A55 7765 <1> JA short NON_DRV1 ; DRIVE INVALID 2922 <1> ;MOV BYTE [BP+5],1 ; MAXIMUM HEAD NUMBER = 1 2923 00001A57 C6450901 <1> mov byte [ebp+9], 1 ; 20/02/2015 2924 00001A5B E88C080000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL 2925 <1> ;;20/02/2015 2926 <1> ;;JC short CHK_EST ; IF CMOS BAD CHECKSUM ESTABLISHED 2927 <1> ;;OR AL,AL ; TEST FOR NO DRIVE TYPE 2928 00001A60 7412 <1> JZ short CHK_EST ; JUMP IF SO 2929 00001A62 E8FD010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 2930 00001A67 720B <1> JC short CHK_EST ; TYPE NOT IN TABLE (POSSIBLE BAD CMOS) 2931 <1> ;MOV [BP+2],AL ; STORE VALID CMOS DRIVE TYPE 2932 00001A69 884504 <1> mov [ebp+4], al ; 06/02/2015 2933 00001A6C 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 2934 00001A6F 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 2935 00001A72 EB36 <1> JMP SHORT STO_CX ; CMOS GOOD, USE CMOS 2936 <1> CHK_EST: 2937 00001A74 8AA7[396E0000] <1> MOV AH, [DSK_STATE+eDI] ; LOAD STATE FOR THIS DRIVE 2938 00001A7A F6C410 <1> TEST AH,MED_DET ; CHECK FOR ESTABLISHED STATE 2939 00001A7D 743D <1> JZ short NON_DRV1 ; CMOS BAD/INVALID OR UNESTABLISHED 2940 <1> USE_EST: 2941 00001A7F 80E4C0 <1> AND AH,RATE_MSK ; ISOLATE STATE 2942 00001A82 80FC80 <1> CMP AH,RATE_250 ; RATE 250 ? 2943 00001A85 7555 <1> JNE short USE_EST2 ; NO, GO CHECK OTHER RATE 2944 <1> 2945 <1> ;----- DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST 2946 <1> 2947 00001A87 B001 <1> MOV AL,01 ; DRIVE TYPE 1 (360KB) 2948 00001A89 E8D6010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 2949 00001A8E 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 2950 00001A91 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 2951 00001A94 F687[396E0000]01 <1> TEST byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ? 2952 00001A9B 740D <1> JZ short STO_CX ; MUST BE 360KB DRIVE 2953 <1> 2954 <1> ;----- IT IS 1.44 MB DRIVE 2955 <1> 2956 <1> PARM144: 2957 00001A9D B004 <1> MOV AL,04 ; DRIVE TYPE 4 (1.44MB) 2958 00001A9F E8C0010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 2959 00001AA4 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 2960 00001AA7 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 2961 <1> STO_CX: 2962 00001AAA 894D00 <1> MOV [eBP],eCX ; SAVE POINTER IN STACK FOR RETURN 2963 <1> ES_DI: 2964 <1> ;MOV [BP+6],BX ; ADDRESS OF MEDIA/DRIVE PARM TABLE 2965 00001AAD 895D0C <1> mov [ebp+12], ebx ; 06/02/2015 2966 <1> ;MOV AX,CS ; SEGMENT MEDIA/DRIVE PARAMETER TABLE 2967 <1> ;MOV ES,AX ; ES IS SEGMENT OF TABLE 2968 <1> DP_OUT: 2969 00001AB0 E852020000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 2970 <1> ;XOR AX,AX ; CLEAR 2971 <1> ; 05/12/2021 2972 00001AB5 31C0 <1> xor eax, eax 2973 00001AB7 F8 <1> CLC 2974 00001AB8 C3 <1> RETn 2975 <1> 2976 <1> ;----- NO DRIYE PRESENT HANDLER 2977 <1> 2978 <1> NON_DRV: 2979 <1> ;MOV BYTE [BP+4],0 ; CLEAR NUMBER OF DRIVES 2980 00001AB9 895508 <1> mov [ebp+8], edx ; 0 ; 20/02/2015 2981 <1> NON_DRV1: 2982 00001ABC 6681FF8000 <1> CMP DI,80H ; CHECK FOR FIXED MEDIA TYPE REQUEST 2983 00001AC1 720B <1> JB short NON_DRV2 ; CONTINUE IF NOT REQUEST FALL THROUGH 2984 <1> 2985 <1> ;----- FIXED DISK REQUEST FALL THROUGH ERROR 2986 <1> 2987 00001AC3 E83F020000 <1> CALL XLAT_OLD ; ELSE TRANSLATE TO COMPATIBLE MODE 2988 <1> ;MOV AX,SI ; RESTORE AL 2989 00001AC8 89F0 <1> mov eax, esi ; 05/12/2021 2990 00001ACA B401 <1> MOV AH,BAD_CMD ; SET BAD COMMAND ERROR 2991 00001ACC F9 <1> STC 2992 00001ACD C3 <1> RETn 2993 <1> 2994 <1> NON_DRV2: 2995 <1> ;XOR AX,AX ; CLEAR PARMS IF NO DRIVES OR CMOS BAD 2996 00001ACE 31C0 <1> xor eax, eax 2997 00001AD0 66894500 <1> MOV [eBP],AX ; TRACKS, SECTORS/TRACK = 0 2998 <1> ;MOV [BP+5],AH ; HEAD = 0 2999 00001AD4 886509 <1> mov [ebp+9], ah ; 06/02/2015 3000 <1> ;MOV [BP+6],AX ; OFFSET TO DISK_BASE = 0 3001 00001AD7 89450C <1> mov [ebp+12], eax 3002 <1> ;MOV ES,AX ; ES IS SEGMENT OF TABLE 3003 00001ADA EBD4 <1> JMP SHORT DP_OUT 3004 <1> 3005 <1> ;----- DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST 3006 <1> 3007 <1> USE_EST2: 3008 00001ADC B002 <1> MOV AL,02 ; DRIVE TYPE 2 (1.2MB) 3009 00001ADE E881010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 3010 00001AE3 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 3011 00001AE6 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 3012 00001AE9 80FC40 <1> CMP AH,RATE_300 ; RATE 300 ? 3013 00001AEC 74BC <1> JZ short STO_CX ; MUST BE 1.2MB DRIVE 3014 00001AEE EBAD <1> JMP SHORT PARM144 ; ELSE, IT IS 1.44MB DRIVE 3015 <1> 3016 <1> ;------------------------------------------------------------------------------- 3017 <1> ; DISK_TYPE (AH = 15H) 3018 <1> ; THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED. 3019 <1> ; 3020 <1> ; ON ENTRY: DI = DRIVE # 3021 <1> ; 3022 <1> ; ON EXIT: AH = DRIVE TYPE, CY=0 3023 <1> ;------------------------------------------------------------------------------- 3024 <1> DSK_TYPE: 3025 00001AF0 E8E1010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 3026 00001AF5 8A87[396E0000] <1> MOV AL, [DSK_STATE+eDI] ; GET PRESENT STATE INFORMATION 3027 00001AFB 08C0 <1> OR AL,AL ; CHECK FOR NO DRIVE 3028 00001AFD 7415 <1> JZ short NO_DRV 3029 00001AFF B401 <1> MOV AH,NOCHGLN ; NO CHANGE LINE FOR 40 TRACK DRIVE 3030 00001B01 A801 <1> TEST AL,TRK_CAPA ; IS THIS DRIVE AN 80 TRACK DRIVE? 3031 00001B03 7402 <1> JZ short DT_BACK ; IF NO JUMP 3032 00001B05 B402 <1> MOV AH,CHGLN ; CHANGE LINE FOR 80 TRACK DRIVE 3033 <1> DT_BACK: 3034 <1> ;PUSH AX ; SAVE RETURN VALUE 3035 00001B07 50 <1> push eax ; 05/12/2021 3036 00001B08 E8FA010000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3037 <1> ;POP AX ; RESTORE RETURN VALUE 3038 00001B0D 58 <1> pop eax ; 05/12/2021 3039 00001B0E F8 <1> CLC ; NO ERROR 3040 <1> ;MOV BX,SI ; GET SAVED AL TO BL 3041 <1> ; 05/12/2021 3042 00001B0F 89F3 <1> mov ebx, esi 3043 00001B11 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 3044 00001B13 C3 <1> RETn 3045 <1> NO_DRV: 3046 00001B14 30E4 <1> XOR AH,AH ; NO DRIVE PRESENT OR UNKNOWN 3047 00001B16 EBEF <1> JMP SHORT DT_BACK 3048 <1> 3049 <1> ;------------------------------------------------------------------------------- 3050 <1> ; DISK_CHANGE (AH = 16H) 3051 <1> ; THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE. 3052 <1> ; 3053 <1> ; ON ENTRY: DI = DRIVE # 3054 <1> ; 3055 <1> ; ON EXIT: AH = @DSKETTE_STATUS 3056 <1> ; 00 - DISK CHANGE LINE INACTIVE, CY = 0 3057 <1> ; 06 - DISK CHANGE LINE ACTIVE, CY = 1 3058 <1> ;------------------------------------------------------------------------------- 3059 <1> DSK_CHANGE: 3060 00001B18 E8B9010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 3061 00001B1D 8A87[396E0000] <1> MOV AL, [DSK_STATE+eDI] ; GET MEDIA STATE INFORMATION 3062 00001B23 08C0 <1> OR AL,AL ; DRIVE PRESENT ? 3063 00001B25 7421 <1> JZ short DC_NON ; JUMP IF NO DRIVE 3064 00001B27 A801 <1> TEST AL,TRK_CAPA ; 80 TRACK DRIVE ? 3065 00001B29 7407 <1> JZ short SETIT ; IF SO , CHECK CHANGE LINE 3066 <1> DC0: 3067 00001B2B E8600A0000 <1> CALL READ_DSKCHNG ; GO CHECK STATE OF DISK CHANGE LINE 3068 00001B30 7407 <1> JZ short FINIS ; CHANGE LINE NOT ACTIVE 3069 <1> 3070 00001B32 C605[2C6E0000]06 <1> SETIT: MOV byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED 3071 <1> 3072 00001B39 E8C9010000 <1> FINIS: CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3073 00001B3E E8E4060000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 3074 <1> ;MOV BX,SI ; GET SAVED AL TO BL 3075 <1> ; 05/12/2021 3076 00001B43 89F3 <1> mov ebx, esi 3077 00001B45 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 3078 00001B47 C3 <1> RETn 3079 <1> DC_NON: 3080 00001B48 800D[2C6E0000]80 <1> OR byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE 3081 00001B4F EBE8 <1> JMP SHORT FINIS 3082 <1> 3083 <1> ;------------------------------------------------------------------------------- 3084 <1> ; FORMAT_SET (AH = 17H) 3085 <1> ; THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED 3086 <1> ; FOR THE FOLLOWING FORMAT OPERATION. 3087 <1> ; 3088 <1> ; ON ENTRY: SI LOW = DASD TYPE FOR FORMAT 3089 <1> ; DI = DRIVE # 3090 <1> ; 3091 <1> ; ON EXIT: @DSKETTE_STATUS REFLECTS STATUS 3092 <1> ; AH = @DSKETTE_STATUS 3093 <1> ; CY = 1 IF ERROR 3094 <1> ;------------------------------------------------------------------------------- 3095 <1> FORMAT_SET: 3096 00001B51 E880010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 3097 <1> ;PUSH SI ; SAVE DASD TYPE 3098 <1> ; 05/12/2021 3099 00001B56 56 <1> push esi 3100 00001B57 6689F0 <1> MOV AX,SI ; AH = ? , AL , DASD TYPE 3101 00001B5A 30E4 <1> XOR AH,AH ; AH , 0 , AL , DASD TYPE 3102 00001B5C 6689C6 <1> MOV SI,AX ; SI = DASD TYPE 3103 00001B5F 80A7[396E0000]0F <1> AND byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE 3104 00001B66 664E <1> DEC SI ; CHECK FOR 320/360K MEDIA & DRIVE 3105 00001B68 7509 <1> JNZ short NOT_320 ; BYPASS IF NOT 3106 00001B6A 808F[396E0000]90 <1> OR byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360 3107 00001B71 EB48 <1> JMP SHORT S0 3108 <1> NOT_320: 3109 00001B73 E8A4030000 <1> CALL MED_CHANGE ; CHECK FOR TIME_OUT 3110 00001B78 803D[2C6E0000]80 <1> CMP byte [DSKETTE_STATUS], TIME_OUT 3111 00001B7F 743A <1> JZ short S0 ; IF TIME OUT TELL CALLER 3112 <1> S3: 3113 00001B81 664E <1> DEC SI ; CHECK FOR 320/360K IN 1.2M DRIVE 3114 00001B83 7509 <1> JNZ short NOT_320_12 ; BYPASS IF NOT 3115 00001B85 808F[396E0000]70 <1> OR byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE 3116 00001B8C EB2D <1> JMP SHORT S0 3117 <1> NOT_320_12: 3118 00001B8E 664E <1> DEC SI ; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE 3119 00001B90 7509 <1> JNZ short NOT_12 ; BYPASS IF NOT 3120 00001B92 808F[396E0000]10 <1> OR byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE 3121 00001B99 EB20 <1> JMP SHORT S0 ; RETURN TO CALLER 3122 <1> NOT_12: 3123 00001B9B 664E <1> DEC SI ; CHECK FOR SET DASD TYPE 04 3124 00001B9D 752A <1> JNZ short FS_ERR ; BAD COMMAND EXIT IF NOT VALID TYPE 3125 <1> 3126 00001B9F F687[396E0000]04 <1> TEST byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ? 3127 00001BA6 740B <1> JZ short ASSUME ; IF STILL NOT DETERMINED ASSUME 3128 00001BA8 B050 <1> MOV AL,MED_DET+RATE_300 3129 00001BAA F687[396E0000]02 <1> TEST byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ? 3130 00001BB1 7502 <1> JNZ short OR_IT_IN ; IF 1.2 M THEN DATA RATE 300 3131 <1> ASSUME: 3132 00001BB3 B090 <1> MOV AL,MED_DET+RATE_250 ; SET UP 3133 <1> OR_IT_IN: 3134 00001BB5 0887[396E0000] <1> OR [DSK_STATE+eDI], AL ; OR IN THE CORRECT STATE 3135 <1> S0: 3136 00001BBB E847010000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3137 00001BC0 E862060000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 3138 <1> ;POP BX ; GET SAVED AL TO BL 3139 <1> ; 05/12/2021 3140 00001BC5 5B <1> pop ebx 3141 00001BC6 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 3142 00001BC8 C3 <1> RETn 3143 <1> FS_ERR: 3144 00001BC9 C605[2C6E0000]01 <1> MOV byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND 3145 00001BD0 EBE9 <1> JMP SHORT S0 3146 <1> 3147 <1> ;------------------------------------------------------------------------------- 3148 <1> ; SET_MEDIA (AH = 18H) 3149 <1> ; THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 3150 <1> ; TO BE USED FOR THE FOLLOWING FORMAT OPERATION. 3151 <1> ; 3152 <1> ; ON ENTRY: 3153 <1> ; [BP] = SECTOR PER TRACK 3154 <1> ; [BP+1] = TRACK # 3155 <1> ; DI = DRIVE # 3156 <1> ; 3157 <1> ; ON EXIT: 3158 <1> ; @DSKETTE_STATUS REFLECTS STATUS 3159 <1> ; IF NO ERROR: 3160 <1> ; AH = 0 3161 <1> ; CY = 0 3162 <1> ; ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE 3163 <1> ; DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE 3164 <1> ; IF ERROR: 3165 <1> ; AH = @DSKETTE_STATUS 3166 <1> ; CY = 1 3167 <1> ;------------------------------------------------------------------------------- 3168 <1> SET_MEDIA: 3169 00001BD2 E8FF000000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 3170 00001BD7 F687[396E0000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE 3171 00001BDE 7415 <1> JZ short SM_CMOS ; JUMP IF 40 TRACK DRIVE 3172 00001BE0 E837030000 <1> CALL MED_CHANGE ; RESET CHANGE LINE 3173 00001BE5 803D[2C6E0000]80 <1> CMP byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER 3174 00001BEC 746B <1> JE short SM_RTN 3175 00001BEE C605[2C6E0000]00 <1> MOV byte [DSKETTE_STATUS], 0 ; CLEAR STATUS 3176 <1> SM_CMOS: 3177 00001BF5 E8F2060000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 3178 <1> ;;20/02/2015 3179 <1> ;;JC short MD_NOT_FND ; ERROR IN CMOS 3180 <1> ;;OR AL,AL ; TEST FOR NO DRIVE 3181 00001BFA 745D <1> JZ short SM_RTN ; RETURN IF SO 3182 00001BFC E863000000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 3183 00001C01 7231 <1> JC short MD_NOT_FND ; TYPE NOT IN TABLE (BAD CMOS) 3184 00001C03 57 <1> PUSH eDI ; SAVE REG. 3185 00001C04 31DB <1> XOR eBX,eBX ; BX = INDEX TO DR. TYPE TABLE 3186 00001C06 B906000000 <1> MOV eCX,DR_CNT ; CX = LOOP COUNT 3187 <1> DR_SEARCH: 3188 00001C0B 8AA3[1C680000] <1> MOV AH, [DR_TYPE+eBX] ; GET DRIVE TYPE 3189 00001C11 80E47F <1> AND AH,BIT7OFF ; MASK OUT MSB 3190 00001C14 38E0 <1> CMP AL,AH ; DRIVE TYPE MATCH ? 3191 00001C16 7516 <1> JNE short NXT_MD ; NO, CHECK NEXT DRIVE TYPE 3192 <1> DR_FND: 3193 00001C18 8BBB[1D680000] <1> MOV eDI, [DR_TYPE+eBX+1] ; DI = MEDIA/DRIVE PARAM TABLE 3194 <1> MD_SEARCH: 3195 00001C1E 8A6704 <1> MOV AH, [eDI+MD.SEC_TRK] ; GET SECTOR/TRACK 3196 00001C21 386500 <1> CMP [eBP],AH ; MATCH? 3197 00001C24 7508 <1> JNE short NXT_MD ; NO, CHECK NEXT MEDIA 3198 00001C26 8A670B <1> MOV AH, [eDI+MD.MAX_TRK] ; GET MAX. TRACK # 3199 00001C29 386501 <1> CMP [eBP+1],AH ; MATCH? 3200 00001C2C 740F <1> JE short MD_FND ; YES, GO GET RATE 3201 <1> NXT_MD: 3202 <1> ;ADD BX,3 ; CHECK NEXT DRIVE TYPE 3203 00001C2E 83C305 <1> add ebx, 5 ; 18/02/2015 3204 00001C31 E2D8 <1> LOOP DR_SEARCH 3205 00001C33 5F <1> POP eDI ; RESTORE REG. 3206 <1> MD_NOT_FND: 3207 00001C34 C605[2C6E0000]0C <1> MOV byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND 3208 00001C3B EB1C <1> JMP SHORT SM_RTN ; RETURN 3209 <1> MD_FND: 3210 00001C3D 8A470C <1> MOV AL, [eDI+MD.RATE] ; GET RATE 3211 00001C40 3C40 <1> CMP AL,RATE_300 ; DOUBLE STEP REQUIRED FOR RATE 300 3212 00001C42 7502 <1> JNE short MD_SET 3213 00001C44 0C20 <1> OR AL,DBL_STEP 3214 <1> MD_SET: 3215 <1> ;MOV [BP+6],DI ; SAVE TABLE POINTER IN STACK 3216 00001C46 897D0C <1> mov [ebp+12], edi ; 18/02/2015 3217 00001C49 0C10 <1> OR AL,MED_DET ; SET MEDIA ESTABLISHED 3218 00001C4B 5F <1> POP eDI 3219 00001C4C 80A7[396E0000]0F <1> AND byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE 3220 00001C53 0887[396E0000] <1> OR [DSK_STATE+eDI], AL 3221 <1> ;MOV AX, CS ; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE 3222 <1> ;MOV ES, AX ; ES IS SEGMENT OF TABLE 3223 <1> SM_RTN: 3224 00001C59 E8A9000000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3225 00001C5E E8C4050000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 3226 00001C63 C3 <1> RETn 3227 <1> 3228 <1> ;---------------------------------------------------------------- 3229 <1> ; DR_TYPE_CHECK : 3230 <1> ; CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL) : 3231 <1> ; IS SUPPORTED IN BIOS DRIVE TYPE TABLE : 3232 <1> ; ON ENTRY: : 3233 <1> ; AL = DRIVE TYPE : 3234 <1> ; ON EXIT: : 3235 <1> ; CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE) : 3236 <1> ; CY = 0 DRIVE TYPE SUPPORTED : 3237 <1> ; BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE : 3238 <1> ; CY = 1 DRIVE TYPE NOT SUPPORTED : 3239 <1> ; REGISTERS ALTERED: eBX : 3240 <1> ;---------------------------------------------------------------- 3241 <1> DR_TYPE_CHECK: 3242 <1> ;PUSH AX 3243 <1> ; 05/12/2021 3244 00001C64 50 <1> push eax 3245 00001C65 51 <1> PUSH eCX 3246 00001C66 31DB <1> XOR eBX,eBX ; BX = INDEX TO DR_TYPE TABLE 3247 00001C68 B906000000 <1> MOV eCX,DR_CNT ; CX = LOOP COUNT 3248 <1> TYPE_CHK: 3249 00001C6D 8AA3[1C680000] <1> MOV AH,[DR_TYPE+eBX] ; GET DRIVE TYPE 3250 00001C73 38E0 <1> CMP AL,AH ; DRIVE TYPE MATCH? 3251 00001C75 740D <1> JE short DR_TYPE_VALID ; YES, RETURN WITH CARRY RESET 3252 <1> ;ADD BX,3 ; CHECK NEXT DRIVE TYPE 3253 00001C77 83C305 <1> add ebx, 5 ; 16/02/2015 (32 bit address modification) 3254 00001C7A E2F1 <1> LOOP TYPE_CHK 3255 <1> ; 3256 00001C7C BB[7B680000] <1> mov ebx, MD_TBL6 ; 1.44MB fd parameter table 3257 <1> ; Default for GET_PARM (11/12/2014) 3258 <1> ; 3259 00001C81 F9 <1> STC ; DRIVE TYPE NOT FOUND IN TABLE 3260 00001C82 EB06 <1> JMP SHORT TYPE_RTN 3261 <1> DR_TYPE_VALID: 3262 00001C84 8B9B[1D680000] <1> MOV eBX,[DR_TYPE+eBX+1] ; BX = MEDIA TABLE 3263 <1> TYPE_RTN: 3264 00001C8A 59 <1> POP eCX 3265 <1> ;POP AX 3266 <1> ; 05/12/2021 3267 00001C8B 58 <1> pop eax 3268 00001C8C C3 <1> RETn 3269 <1> 3270 <1> ;---------------------------------------------------------------- 3271 <1> ; SEND_SPEC : 3272 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 3273 <1> ; THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER : 3274 <1> ; ON ENTRY: @DISK_POINTER = DRIVE PARAMETER TABLE : 3275 <1> ; ON EXIT: NONE : 3276 <1> ; REGISTERS ALTERED: CX, DX : 3277 <1> ;---------------------------------------------------------------- 3278 <1> SEND_SPEC: 3279 00001C8D 50 <1> PUSH eAX ; SAVE AX 3280 00001C8E B8[B41C0000] <1> MOV eAX, SPECBAC ; LOAD ERROR ADDRESS 3281 00001C93 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 3282 00001C94 B403 <1> MOV AH,03H ; SPECIFY COMMAND 3283 00001C96 E860070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 3284 00001C9B 28D2 <1> SUB DL,DL ; FIRST SPECIFY BYTE 3285 00001C9D E853060000 <1> CALL GET_PARM ; GET PARAMETER TO AH 3286 00001CA2 E854070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 3287 00001CA7 B201 <1> MOV DL,1 ; SECOND SPECIFY BYTE 3288 00001CA9 E847060000 <1> CALL GET_PARM ; GET PARAMETER TO AH 3289 00001CAE E848070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 3290 00001CB3 58 <1> POP eAX ; POP ERROR RETURN 3291 <1> SPECBAC: 3292 00001CB4 58 <1> POP eAX ; RESTORE ORIGINAL AX VALUE 3293 00001CB5 C3 <1> RETn 3294 <1> 3295 <1> ;---------------------------------------------------------------- 3296 <1> ; SEND_SPEC_MD : 3297 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 3298 <1> ; THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX) : 3299 <1> ; ON ENTRY: CS:BX = MEDIA/DRIVE PARAMETER TABLE : 3300 <1> ; ON EXIT: NONE : 3301 <1> ; REGISTERS ALTERED: AX : 3302 <1> ;---------------------------------------------------------------- 3303 <1> SEND_SPEC_MD: 3304 00001CB6 50 <1> PUSH eAX ; SAVE RATE DATA 3305 00001CB7 B8[D41C0000] <1> MOV eAX, SPEC_ESBAC ; LOAD ERROR ADDRESS 3306 00001CBC 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 3307 00001CBD B403 <1> MOV AH,03H ; SPECIFY COMMAND 3308 00001CBF E837070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 3309 00001CC4 8A23 <1> MOV AH, [eBX+MD.SPEC1] ; GET 1ST SPECIFY BYTE 3310 00001CC6 E830070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 3311 00001CCB 8A6301 <1> MOV AH, [eBX+MD.SPEC2] ; GET SECOND SPECIFY BYTE 3312 00001CCE E828070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 3313 00001CD3 58 <1> POP eAX ; POP ERROR RETURN 3314 <1> SPEC_ESBAC: 3315 00001CD4 58 <1> POP eAX ; RESTORE ORIGINAL AX VALUE 3316 00001CD5 C3 <1> RETn 3317 <1> 3318 <1> ;------------------------------------------------------------------------------- 3319 <1> ; XLAT_NEW 3320 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE 3321 <1> ; MODE TO NEW ARCHITECTURE. 3322 <1> ; 3323 <1> ; ON ENTRY: DI = DRIVE # 3324 <1> ;------------------------------------------------------------------------------- 3325 <1> XLAT_NEW: 3326 00001CD6 83FF01 <1> CMP eDI,1 ; VALID DRIVE 3327 00001CD9 7725 <1> JA short XN_OUT ; IF INVALID BACK 3328 00001CDB 80BF[396E0000]00 <1> CMP byte [DSK_STATE+eDI], 0 ; NO DRIVE ? 3329 00001CE2 741D <1> JZ short DO_DET ; IF NO DRIVE ATTEMPT DETERMINE 3330 00001CE4 6689F9 <1> MOV CX,DI ; CX = DRIVE NUMBER 3331 00001CE7 C0E102 <1> SHL CL,2 ; CL = SHIFT COUNT, A=0, B=4 3332 00001CEA A0[386E0000] <1> MOV AL, [HF_CNTRL] ; DRIVE INFORMATION 3333 00001CEF D2C8 <1> ROR AL,CL ; TO LOW NIBBLE 3334 00001CF1 2407 <1> AND AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 3335 00001CF3 80A7[396E0000]F8 <1> AND byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) 3336 00001CFA 0887[396E0000] <1> OR [DSK_STATE+eDI], AL ; UPDATE DRIVE STATE 3337 <1> XN_OUT: 3338 00001D00 C3 <1> RETn 3339 <1> DO_DET: 3340 00001D01 E897080000 <1> CALL DRIVE_DET ; TRY TO DETERMINE 3341 00001D06 C3 <1> RETn 3342 <1> 3343 <1> ;------------------------------------------------------------------------------- 3344 <1> ; XLAT_OLD 3345 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM NEW 3346 <1> ; ARCHITECTURE TO COMPATIBLE MODE. 3347 <1> ; 3348 <1> ; ON ENTRY: DI = DRIVE 3349 <1> ;------------------------------------------------------------------------------- 3350 <1> XLAT_OLD: 3351 00001D07 83FF01 <1> CMP eDI,1 ; VALID DRIVE ? 3352 <1> ;JA short XO_OUT ; IF INVALID BACK 3353 <1> ;ja XO_OUT 3354 <1> ; 05/12/2021 3355 00001D0A 77F4 <1> ja short XN_OUT 3356 00001D0C 80BF[396E0000]00 <1> CMP byte [DSK_STATE+eDI],0 ; NO DRIVE ? 3357 00001D13 747D <1> JZ short XO_OUT ; IF NO DRIVE TRANSLATE DONE 3358 <1> 3359 <1> ;----- TEST FOR SAVED DRIVE INFORMATION ALREADY SET 3360 <1> 3361 00001D15 6689F9 <1> MOV CX,DI ; CX = DRIVE NUMBER 3362 00001D18 C0E102 <1> SHL CL,2 ; CL = SHIFT COUNT, A=0, B=4 3363 00001D1B B402 <1> MOV AH,FMT_CAPA ; LOAD MULTIPLE DATA RATE BIT MASK 3364 00001D1D D2CC <1> ROR AH,CL ; ROTATE BY MASK 3365 00001D1F 8425[386E0000] <1> TEST [HF_CNTRL], AH ; MULTIPLE-DATA RATE DETERMINED ? 3366 00001D25 751C <1> JNZ short SAVE_SET ; IF SO, NO NEED TO RE-SAVE 3367 <1> 3368 <1> ;----- ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE 3369 <1> 3370 00001D27 B407 <1> MOV AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP 3371 00001D29 D2CC <1> ROR AH,CL ; FIX MASK TO KEEP 3372 00001D2B F6D4 <1> NOT AH ; TRANSLATE MASK 3373 00001D2D 2025[386E0000] <1> AND [HF_CNTRL], AH ; KEEP BITS FROM OTHER DRIVE INTACT 3374 <1> 3375 <1> ;----- ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL 3376 <1> 3377 00001D33 8A87[396E0000] <1> MOV AL,[DSK_STATE+eDI] ; ACCESS STATE 3378 00001D39 2407 <1> AND AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 3379 00001D3B D2C8 <1> ROR AL,CL ; FIX FOR THIS DRIVE 3380 00001D3D 0805[386E0000] <1> OR [HF_CNTRL], AL ; UPDATE SAVED DRIVE STATE 3381 <1> 3382 <1> ;----- TRANSLATE TO COMPATIBILITY MODE 3383 <1> 3384 <1> SAVE_SET: 3385 00001D43 8AA7[396E0000] <1> MOV AH, [DSK_STATE+eDI] ; ACCESS STATE 3386 00001D49 88E7 <1> MOV BH,AH ; TO BH FOR LATER 3387 00001D4B 80E4C0 <1> AND AH,RATE_MSK ; KEEP ONLY RATE 3388 00001D4E 80FC00 <1> CMP AH,RATE_500 ; RATE 500 ? 3389 00001D51 7410 <1> JZ short CHK_144 ; YES 1.2/1.2 OR 1.44/1.44 3390 00001D53 B001 <1> MOV AL,M3D1U ; AL = 360 IN 1.2 UNESTABLISHED 3391 00001D55 80FC40 <1> CMP AH,RATE_300 ; RATE 300 ? 3392 00001D58 7518 <1> JNZ short CHK_250 ; NO, 360/360, 720/720 OR 720/1.44 3393 00001D5A F6C720 <1> TEST BH,DBL_STEP ; CHECK FOR DOUBLE STEP 3394 00001D5D 751F <1> JNZ short TST_DET ; MUST BE 360 IN 1.2 3395 <1> UNKNO: 3396 00001D5F B007 <1> MOV AL,MED_UNK ; NONE OF THE ABOVE 3397 00001D61 EB22 <1> JMP SHORT AL_SET ; PROCESS COMPLETE 3398 <1> CHK_144: 3399 00001D63 E884050000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 3400 <1> ;;20/02/2015 3401 <1> ;;JC short UNKNO ; ERROR, SET 'NONE OF ABOVE' 3402 00001D68 74F5 <1> jz short UNKNO ;; 20/02/2015 3403 00001D6A 3C02 <1> CMP AL,2 ; 1.2MB DRIVE ? 3404 00001D6C 75F1 <1> JNE short UNKNO ; NO, GO SET 'NONE OF ABOVE' 3405 00001D6E B002 <1> MOV AL,M1D1U ; AL = 1.2 IN 1.2 UNESTABLISHED 3406 00001D70 EB0C <1> JMP SHORT TST_DET 3407 <1> CHK_250: 3408 00001D72 B000 <1> MOV AL,M3D3U ; AL = 360 IN 360 UNESTABLISHED 3409 00001D74 80FC80 <1> CMP AH,RATE_250 ; RATE 250 ? 3410 00001D77 75E6 <1> JNZ short UNKNO ; IF SO FALL IHRU 3411 00001D79 F6C701 <1> TEST BH,TRK_CAPA ; 80 TRACK CAPABILITY ? 3412 00001D7C 75E1 <1> JNZ short UNKNO ; IF SO JUMP, FALL THRU TEST DET 3413 <1> TST_DET: 3414 00001D7E F6C710 <1> TEST BH,MED_DET ; DETERMINED ? 3415 00001D81 7402 <1> JZ short AL_SET ; IF NOT THEN SET 3416 00001D83 0403 <1> ADD AL,3 ; MAKE DETERMINED/ESTABLISHED 3417 <1> AL_SET: 3418 00001D85 80A7[396E0000]F8 <1> AND byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE 3419 00001D8C 0887[396E0000] <1> OR [DSK_STATE+eDI], AL ; REPLACE WITH COMPATIBLE MODE 3420 <1> XO_OUT: 3421 00001D92 C3 <1> RETn 3422 <1> 3423 <1> ;------------------------------------------------------------------------------- 3424 <1> ; RD_WR_VF 3425 <1> ; COMMON READ, WRITE AND VERIFY: 3426 <1> ; MAIN LOOP FOR STATE RETRIES. 3427 <1> ; 3428 <1> ; ON ENTRY: AH = READ/WRITE/VERIFY NEC PARAMETER 3429 <1> ; AL = READ/WRITE/VERIFY DMA PARAMETER 3430 <1> ; 3431 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3432 <1> ;------------------------------------------------------------------------------- 3433 <1> RD_WR_VF: 3434 <1> ;PUSH AX ; SAVE DMA, NEC PARAMETERS 3435 00001D93 50 <1> push eax ; 05/12/2021 3436 00001D94 E83DFFFFFF <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 3437 00001D99 E8E9000000 <1> CALL SETUP_STATE ; INITIALIZE START AND END RATE 3438 <1> ;POP AX ; RESTORE READ/WRITE/VERIFY 3439 00001D9E 58 <1> pop eax ; 05/12/2021 3440 <1> DO_AGAIN: 3441 <1> ;PUSH AX ; SAVE READ/WRITE/VERIFY PARAMETER 3442 00001D9F 50 <1> push eax ; 05/12/2021 3443 00001DA0 E877010000 <1> CALL MED_CHANGE ; MEDIA CHANGE AND RESET IF CHANGED 3444 <1> ;POP AX ; RESTORE READ/WRITE/VERIFY 3445 00001DA5 58 <1> pop eax ; 05/12/2021 3446 <1> ;JC RWV_END ; MEDIA CHANGE ERROR OR TIME-OUT 3447 <1> ; 05/12/2021 3448 00001DA6 7305 <1> jnc short RWV 3449 00001DA8 E9C3000000 <1> jmp RWV_END 3450 <1> RWV: 3451 <1> ;PUSH AX ; SAVE READ/WRITE/VERIFY PARAMETER 3452 00001DAD 50 <1> push eax ; 05/12/2021 3453 00001DAE 8AB7[396E0000] <1> MOV DH, [DSK_STATE+eDI] ; GET RATE STATE OF THIS DRIVE 3454 00001DB4 80E6C0 <1> AND DH,RATE_MSK ; KEEP ONLY RATE 3455 00001DB7 E830050000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL (AL) 3456 <1> ;;20/02/2015 3457 <1> ;;JC short RWV_ASSUME ; ERROR IN CMOS 3458 00001DBC 7451 <1> jz short RWV_ASSUME ; 20/02/2015 3459 00001DBE 3C01 <1> CMP AL,1 ; 40 TRACK DRIVE? 3460 00001DC0 750D <1> JNE short RWV_1 ; NO, BYPASS CMOS VALIDITY CHECK 3461 00001DC2 F687[396E0000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE 3462 00001DC9 7413 <1> JZ short RWV_2 ; YES, CMOS IS CORRECT 3463 00001DCB B002 <1> MOV AL,2 ; CHANGE TO 1.2M 3464 00001DCD EB0F <1> JMP SHORT RWV_2 3465 <1> RWV_1: 3466 00001DCF 720D <1> JB short RWV_2 ; NO DRIVE SPECIFIED, CONTINUE 3467 00001DD1 F687[396E0000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK? 3468 00001DD8 7504 <1> JNZ short RWV_2 ; NO, 80 TRACK 3469 00001DDA B001 <1> MOV AL,1 ; IT IS 40 TRACK, FIX CMOS VALUE 3470 00001DDC EB04 <1> jmp short rwv_3 3471 <1> RWV_2: 3472 00001DDE 08C0 <1> OR AL,AL ; TEST FOR NO DRIVE 3473 00001DE0 742D <1> JZ short RWV_ASSUME ; ASSUME TYPE, USE MAX TRACK 3474 <1> rwv_3: 3475 00001DE2 E87DFEFFFF <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL. 3476 00001DE7 7226 <1> JC short RWV_ASSUME ; TYPE NOT IN TABLE (BAD CMOS) 3477 <1> 3478 <1> ;----- SEARCH FOR MEDIA/DRIVE PARAMETER TABLE 3479 <1> 3480 00001DE9 57 <1> PUSH eDI ; SAVE DRIVE # 3481 00001DEA 31DB <1> XOR eBX,eBX ; BX = INDEX TO DR_TYPE TABLE 3482 00001DEC B906000000 <1> MOV eCX,DR_CNT ; CX = LOOP COUNT 3483 <1> RWV_DR_SEARCH: 3484 00001DF1 8AA3[1C680000] <1> MOV AH, [DR_TYPE+eBX] ; GET DRIVE TYPE 3485 00001DF7 80E47F <1> AND AH,BIT7OFF ; MASK OUT MSB 3486 00001DFA 38E0 <1> CMP AL,AH ; DRIVE TYPE MATCH? 3487 00001DFC 750B <1> JNE short RWV_NXT_MD ; NO, CHECK NEXT DRIVE TYPE 3488 <1> RWV_DR_FND: 3489 00001DFE 8BBB[1D680000] <1> MOV eDI, [DR_TYPE+eBX+1] ; DI = MEDIA/DRIVE PARAMETER TABLE 3490 <1> RWV_MD_SEARH: 3491 00001E04 3A770C <1> CMP DH, [eDI+MD.RATE] ; MATCH? 3492 00001E07 741B <1> JE short RWV_MD_FND ; YES, GO GET 1ST SPECIFY BYTE 3493 <1> RWV_NXT_MD: 3494 <1> ;ADD BX,3 ; CHECK NEXT DRIVE TYPE 3495 00001E09 83C305 <1> add eBX, 5 3496 00001E0C E2E3 <1> LOOP RWV_DR_SEARCH 3497 00001E0E 5F <1> POP eDI ; RESTORE DRIVE # 3498 <1> 3499 <1> ;----- ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED 3500 <1> 3501 <1> RWV_ASSUME: 3502 00001E0F BB[3A680000] <1> MOV eBX, MD_TBL1 ; POINT TO 40 TRACK 250 KBS 3503 00001E14 F687[396E0000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK 3504 00001E1B 740A <1> JZ short RWV_MD_FND1 ; MUST BE 40 TRACK 3505 00001E1D BB[54680000] <1> MOV eBX, MD_TBL3 ; POINT TO 80 TRACK 500 KBS 3506 00001E22 EB03 <1> JMP short RWV_MD_FND1 ; GO SPECIFY PARAMTERS 3507 <1> 3508 <1> ;----- CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE 3509 <1> 3510 <1> RWV_MD_FND: 3511 00001E24 89FB <1> MOV eBX,eDI ; BX = MEDIA/DRIVE PARAMETER TABLE 3512 00001E26 5F <1> POP eDI ; RESTORE DRIVE # 3513 <1> 3514 <1> ;----- SEND THE SPECIFY COMMAND TO THE CONTROLLER 3515 <1> 3516 <1> RWV_MD_FND1: 3517 00001E27 E88AFEFFFF <1> CALL SEND_SPEC_MD 3518 00001E2C E85B010000 <1> CALL CHK_LASTRATE ; ZF=1 ATTEMP RATE IS SAME AS LAST RATE 3519 00001E31 7405 <1> JZ short RWV_DBL ; YES,SKIP SEND RATE COMMAND 3520 00001E33 E834010000 <1> CALL SEND_RATE ; SEND DATA RATE TO NEC 3521 <1> RWV_DBL: 3522 00001E38 53 <1> PUSH eBX ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 3523 00001E39 E809040000 <1> CALL SETUP_DBL ; CHECK FOR DOUBLE STEP 3524 00001E3E 5B <1> POP eBX ; RESTORE ADDRESS 3525 00001E3F 7222 <1> JC short CHK_RET ; ERROR FROM READ ID, POSSIBLE RETRY 3526 <1> ;POP AX ; RESTORE NEC, DMA COMMAND 3527 00001E41 58 <1> pop eax ; 05/12/2021 3528 <1> ;PUSH AX ; SAVE NEC COMMAND 3529 00001E42 50 <1> push eax ; 05/12/2021 3530 00001E43 53 <1> PUSH eBX ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 3531 00001E44 E858010000 <1> CALL DMA_SETUP ; SET UP THE DMA 3532 00001E49 5B <1> POP eBX 3533 <1> ;POP AX ; RESTORE NEC COMMAND 3534 00001E4A 58 <1> pop eax ; 05/12/2021 3535 00001E4B 722D <1> JC short RWV_BAC ; CHECK FOR DMA BOUNDARY ERROR 3536 <1> ;PUSH AX ; SAVE NEC COMMAND 3537 00001E4D 50 <1> push eax ; 05/12/2021 3538 00001E4E 53 <1> PUSH eBX ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 3539 00001E4F E82B020000 <1> CALL NEC_INIT ; INITIALIZE NEC 3540 00001E54 5B <1> POP eBX ; RESTORE ADDRESS 3541 00001E55 720C <1> JC short CHK_RET ; ERROR - EXIT 3542 00001E57 E853020000 <1> CALL RWV_COM ; OP CODE COMMON TO READ/WRITE/VERIFY 3543 00001E5C 7205 <1> JC short CHK_RET ; ERROR - EXIT 3544 00001E5E E898020000 <1> CALL NEC_TERM ; TERMINATE, GET STATUS, ETC. 3545 <1> CHK_RET: 3546 00001E63 E837030000 <1> CALL RETRY ; CHECK FOR, SETUP RETRY 3547 <1> ;POP AX ; RESTORE READ/WRITE/VERIFY PARAMETER 3548 00001E68 58 <1> pop eax ; 05/12/2021 3549 00001E69 7305 <1> JNC short RWV_END ; CY = 0 NO RETRY 3550 00001E6B E92FFFFFFF <1> JMP DO_AGAIN ; CY = 1 MEANS RETRY 3551 <1> RWV_END: 3552 00001E70 E8E2020000 <1> CALL DSTATE ; ESTABLISH STATE IF SUCCESSFUL 3553 00001E75 E875030000 <1> CALL NUM_TRANS ; AL = NUMBER TRANSFERRED 3554 <1> RWV_BAC: ; BAD DMA ERROR ENTRY 3555 <1> ;PUSH AX ; SAVE NUMBER TRANSFERRED 3556 00001E7A 50 <1> push eax ; 05/12/2021 3557 00001E7B E887FEFFFF <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3558 <1> ;POP AX ; RESTORE NUMBER TRANSFERRED 3559 00001E80 58 <1> pop eax ; 05/12/2021 3560 00001E81 E8A1030000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 3561 00001E86 C3 <1> RETn 3562 <1> 3563 <1> ;------------------------------------------------------------------------------- 3564 <1> ; SETUP_STATE: INITIALIZES START AND END RATES. 3565 <1> ;------------------------------------------------------------------------------- 3566 <1> SETUP_STATE: 3567 00001E87 F687[396E0000]10 <1> TEST byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ? 3568 00001E8E 7537 <1> JNZ short J1C ; NO STATES IF DETERMINED 3569 00001E90 66B84000 <1> MOV AX,(RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE 3570 00001E94 F687[396E0000]04 <1> TEST byte [DSK_STATE+eDI],DRV_DET ; DRIVE ? 3571 00001E9B 740D <1> JZ short AX_SET ; DO NOT KNOW DRIVE 3572 00001E9D F687[396E0000]02 <1> TEST byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE? 3573 00001EA4 7504 <1> JNZ short AX_SET ; JUMP IF YES 3574 00001EA6 66B88080 <1> MOV AX,RATE_250*257 ; START A END RATE 250 FOR 360 DRIVE 3575 <1> AX_SET: 3576 00001EAA 80A7[396E0000]1F <1> AND byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE 3577 00001EB1 08A7[396E0000] <1> OR [DSK_STATE+eDI], AH ; RATE FIRST TO TRY 3578 00001EB7 8025[346E0000]F3 <1> AND byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS 3579 00001EBE C0C804 <1> ROR AL,4 ; TO OPERATION LAST RATE LOCATION 3580 00001EC1 0805[346E0000] <1> OR [LASTRATE], AL ; LAST RATE 3581 <1> J1C: 3582 00001EC7 C3 <1> RETn 3583 <1> 3584 <1> ;------------------------------------------------------------------------------- 3585 <1> ; FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME. 3586 <1> ;------------------------------------------------------------------------------- 3587 <1> FMT_INIT: 3588 00001EC8 F687[396E0000]10 <1> TEST byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED 3589 00001ECF 7546 <1> JNZ short F1_OUT ; IF SO RETURN 3590 00001ED1 E816040000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL 3591 <1> ;; 20/02/2015 3592 <1> ;;JC short CL_DRV ; ERROR IN CMOS ASSUME NO DRIVE 3593 00001ED6 7440 <1> jz short CL_DRV ;; 20/02/2015 3594 00001ED8 FEC8 <1> DEC AL ; MAKE ZERO ORIGIN 3595 <1> ;;JS short CL_DRV ; NO DRIVE IF AL 0 3596 00001EDA 8AA7[396E0000] <1> MOV AH, [DSK_STATE+eDI] ; AH = CURRENT STATE 3597 00001EE0 80E40F <1> AND AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR 3598 00001EE3 08C0 <1> OR AL,AL ; CHECK FOR 360 3599 00001EE5 7505 <1> JNZ short N_360 ; IF 360 WILL BE 0 3600 00001EE7 80CC90 <1> OR AH,MED_DET+RATE_250 ; ESTABLISH MEDIA 3601 00001EEA EB25 <1> JMP SHORT SKP_STATE ; SKIP OTHER STATE PROCESSING 3602 <1> N_360: 3603 00001EEC FEC8 <1> DEC AL ; 1.2 M DRIVE 3604 00001EEE 7505 <1> JNZ short N_12 ; JUMP IF NOT 3605 <1> F1_RATE: 3606 00001EF0 80CC10 <1> OR AH,MED_DET+RATE_500 ; SET FORMAT RATE 3607 00001EF3 EB1C <1> JMP SHORT SKP_STATE ; SKIP OTHER STATE PROCESSING 3608 <1> N_12: 3609 00001EF5 FEC8 <1> DEC AL ; CHECK FOR TYPE 3 3610 00001EF7 750F <1> JNZ short N_720 ; JUMP IF NOT 3611 00001EF9 F6C404 <1> TEST AH,DRV_DET ; IS DRIVE DETERMINED 3612 00001EFC 7410 <1> JZ short ISNT_12 ; TREAT AS NON 1.2 DRIVE 3613 00001EFE F6C402 <1> TEST AH,FMT_CAPA ; IS 1.2M 3614 00001F01 740B <1> JZ short ISNT_12 ; JUMP IF NOT 3615 00001F03 80CC50 <1> OR AH,MED_DET+RATE_300 ; RATE 300 3616 00001F06 EB09 <1> JMP SHORT SKP_STATE ; CONTINUE 3617 <1> N_720: 3618 00001F08 FEC8 <1> DEC AL ; CHECK FOR TYPE 4 3619 00001F0A 750C <1> JNZ short CL_DRV ; NO DRIVE, CMOS BAD 3620 00001F0C EBE2 <1> JMP SHORT F1_RATE 3621 <1> ISNT_12: 3622 00001F0E 80CC90 <1> OR AH,MED_DET+RATE_250 ; MUST BE RATE 250 3623 <1> 3624 <1> SKP_STATE: 3625 00001F11 88A7[396E0000] <1> MOV [DSK_STATE+eDI], AH ; STORE AWAY 3626 <1> F1_OUT: 3627 00001F17 C3 <1> RETn 3628 <1> CL_DRV: 3629 00001F18 30E4 <1> XOR AH,AH ; CLEAR STATE 3630 00001F1A EBF5 <1> JMP SHORT SKP_STATE ; SAVE IT 3631 <1> 3632 <1> ;------------------------------------------------------------------------------- 3633 <1> ; MED_CHANGE 3634 <1> ; CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 3635 <1> ; CHECKS MEDIA CHANGE AGAIN. 3636 <1> ; 3637 <1> ; ON EXIT: CY = 1 MEANS MEDIA CHANGE OR TIMEOUT 3638 <1> ; @DSKETTE_STATUS = ERROR CODE 3639 <1> ;------------------------------------------------------------------------------- 3640 <1> MED_CHANGE: 3641 00001F1C E86F060000 <1> CALL READ_DSKCHNG ; READ DISK CHANCE LINE STATE 3642 00001F21 7447 <1> JZ short MC_OUT ; BYPASS HANDLING DISK CHANGE LINE 3643 00001F23 80A7[396E0000]EF <1> AND byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE 3644 <1> 3645 <1> ; THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT 3646 <1> ; ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL 3647 <1> ; BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING). 3648 <1> 3649 00001F2A 6689F9 <1> MOV CX,DI ; CL = DRIVE 0 3650 00001F2D B001 <1> MOV AL,1 ; MOTOR ON BIT MASK 3651 00001F2F D2E0 <1> SHL AL,CL ; TO APPROPRIATE POSITION 3652 00001F31 F6D0 <1> NOT AL ; KEEP ALL BUT MOTOR ON 3653 00001F33 FA <1> CLI ; NO INTERRUPTS 3654 00001F34 2005[2A6E0000] <1> AND [MOTOR_STATUS], AL ; TURN MOTOR OFF INDICATOR 3655 00001F3A FB <1> STI ; INTERRUPTS ENABLED 3656 00001F3B E8FA030000 <1> CALL MOTOR_ON ; TURN MOTOR ON 3657 <1> 3658 <1> ;----- THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL 3659 <1> 3660 00001F40 E8A4F9FFFF <1> CALL DSK_RESET ; RESET NEC 3661 00001F45 B501 <1> MOV CH,01H ; MOVE TO CYLINDER 1 3662 00001F47 E8E8040000 <1> CALL SEEK ; ISSUE SEEK 3663 00001F4C 30ED <1> XOR CH,CH ; MOVE TO CYLINDER 0 3664 00001F4E E8E1040000 <1> CALL SEEK ; ISSUE SEEK 3665 00001F53 C605[2C6E0000]06 <1> MOV byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS 3666 <1> OK1: 3667 00001F5A E831060000 <1> CALL READ_DSKCHNG ; CHECK MEDIA CHANGED AGAIN 3668 00001F5F 7407 <1> JZ short OK2 ; IF ACTIVE, NO DISKETTE, TIMEOUT 3669 <1> OK4: 3670 00001F61 C605[2C6E0000]80 <1> MOV byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY 3671 <1> OK2: 3672 00001F68 F9 <1> STC ; MEDIA CHANGED, SET CY 3673 00001F69 C3 <1> RETn 3674 <1> MC_OUT: 3675 00001F6A F8 <1> CLC ; NO MEDIA CHANGED, CLEAR CY 3676 00001F6B C3 <1> RETn 3677 <1> 3678 <1> ;------------------------------------------------------------------------------- 3679 <1> ; SEND_RATE 3680 <1> ; SENDS DATA RATE COMMAND TO NEC 3681 <1> ; ON ENTRY: DI = DRIVE # 3682 <1> ; ON EXIT: NONE 3683 <1> ; REGISTERS ALTERED: DX 3684 <1> ;------------------------------------------------------------------------------- 3685 <1> SEND_RATE: 3686 <1> ;PUSH AX ; SAVE REG. 3687 <1> ; 05/12/2021 3688 00001F6C 50 <1> push eax 3689 00001F6D 8025[346E0000]3F <1> AND byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED 3690 00001F74 8A87[396E0000] <1> MOV AL, [DSK_STATE+eDI] ; GET RATE STATE OF THIS DRIVE 3691 00001F7A 24C0 <1> AND AL,SEND_MSK ; KEEP ONLY RATE BITS 3692 00001F7C 0805[346E0000] <1> OR [LASTRATE], AL ; SAVE NEW RATE FOR NEXT CHECK 3693 00001F82 C0C002 <1> ROL AL,2 ; MOVE TO BIT OUTPUT POSITIONS 3694 00001F85 66BAF703 <1> MOV DX,03F7H ; OUTPUT NEW DATA RATE 3695 00001F89 EE <1> OUT DX,AL 3696 <1> ;POP AX ; RESTORE REG. 3697 <1> ; 05/12/2021 3698 00001F8A 58 <1> pop eax 3699 00001F8B C3 <1> RETn 3700 <1> 3701 <1> ;------------------------------------------------------------------------------- 3702 <1> ; CHK_LASTRATE 3703 <1> ; CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER. 3704 <1> ; ON ENTRY: 3705 <1> ; DI = DRIVE # 3706 <1> ; ON EXIT: 3707 <1> ; ZF = 1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC 3708 <1> ; ZF = 0 DATA RATE IS DIFFERENT FROM LAST RATE 3709 <1> ; REGISTERS ALTERED: DX 3710 <1> ;------------------------------------------------------------------------------- 3711 <1> CHK_LASTRATE: 3712 <1> ;PUSH AX ; SAVE REG. 3713 <1> ; 05/12/2021 3714 00001F8C 50 <1> push eax 3715 00001F8D 2225[346E0000] <1> AND AH, [LASTRATE] ; GET LAST DATA RATE SELECTED 3716 00001F93 8A87[396E0000] <1> MOV AL, [DSK_STATE+eDI] ; GET RATE STATE OF THIS DRIVE 3717 00001F99 6625C0C0 <1> AND AX, SEND_MSK*257 ; KEEP ONLY RATE BITS OF BOTH 3718 00001F9D 38E0 <1> CMP AL, AH ; COMPARE TO PREVIOUSLY TRIED 3719 <1> ; ZF = 1 RATE IS THE SAME 3720 <1> ;POP AX ; RESTORE REG. 3721 <1> ; 05/12/2021 3722 00001F9F 58 <1> pop eax 3723 00001FA0 C3 <1> RETn 3724 <1> 3725 <1> ;------------------------------------------------------------------------------- 3726 <1> ; DMA_SETUP 3727 <1> ; THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS. 3728 <1> ; 3729 <1> ; ON ENTRY: AL = DMA COMMAND 3730 <1> ; 3731 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3732 <1> ;------------------------------------------------------------------------------- 3733 <1> 3734 <1> ; SI = Head #, # of Sectors or DASD Type 3735 <1> 3736 <1> ; 22/08/2015 3737 <1> ; 08/02/2015 - Protected Mode Modification 3738 <1> ; 06/02/2015 - 07/02/2015 3739 <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit). 3740 <1> ; (DMA Addres = Physical Address) 3741 <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address) 3742 <1> ; 3743 <1> ; 04/02/2016 (clc) 3744 <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP) 3745 <1> ; 16/12/2014 (IODELAY) 3746 <1> 3747 <1> DMA_SETUP: 3748 <1> 3749 <1> ;; 20/02/2015 3750 00001FA1 8B5504 <1> mov edx, [ebp+4] ; Buffer address 3751 00001FA4 F7C2000000FF <1> test edx, 0FF000000h ; 16 MB limit (22/08/2015, bugfix) 3752 00001FAA 7569 <1> jnz short dma_bnd_err_stc 3753 <1> ; 3754 <1> ;push ax ; DMA command 3755 <1> ; 05/12/2021 3756 00001FAC 50 <1> push eax 3757 00001FAD 52 <1> push edx ; * 3758 00001FAE B203 <1> mov dl, 3 ; GET BYTES/SECTOR PARAMETER 3759 00001FB0 E840030000 <1> call GET_PARM ; 3760 00001FB5 88E1 <1> mov cl, ah ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 3761 <1> ;mov ax, si ; Sector count 3762 <1> ;mov ah, al ; AH = # OF SECTORS 3763 <1> ;sub al, al ; AL = 0, AX = # SECTORS * 256 3764 <1> ;shr ax, 1 ; AX = # SECTORS * 128 3765 <1> ;shl ax, cl ; SHIFT BY PARAMETER VALUE 3766 <1> ; 05/12/2021 3767 00001FB7 89F2 <1> mov edx, esi 3768 00001FB9 29C0 <1> sub eax, eax 3769 00001FBB 88D4 <1> mov ah, dl 3770 00001FBD D1E8 <1> shr eax, 1 3771 00001FBF D3E0 <1> shl eax, cl 3772 <1> ; 3773 00001FC1 6648 <1> dec ax ; -1 FOR DMA VALUE 3774 00001FC3 6689C1 <1> mov cx, ax 3775 00001FC6 5A <1> pop edx ; * 3776 <1> ;pop ax 3777 <1> ; 05/12/2021 3778 00001FC7 58 <1> pop eax 3779 00001FC8 3C42 <1> cmp al, 42h 3780 00001FCA 7507 <1> jne short NOT_VERF 3781 00001FCC BA0000FF00 <1> mov edx, 0FF0000h 3782 00001FD1 EB08 <1> jmp short J33 3783 <1> NOT_VERF: 3784 00001FD3 6601CA <1> add dx, cx ; check for overflow 3785 00001FD6 723E <1> jc short dma_bnd_err 3786 <1> ; 3787 00001FD8 6629CA <1> sub dx, cx ; Restore start address 3788 <1> J33: 3789 00001FDB FA <1> CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 3790 00001FDC E60C <1> OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 3791 <1> IODELAY ; WAIT FOR I/O 2133 00001FDE EB00 <2> jmp short $+2 2134 00001FE0 EB00 <2> jmp short $+2 3792 00001FE2 E60B <1> OUT DMA+11,AL ; OUTPUT THE MODE BYTE 3793 00001FE4 89D0 <1> mov eax,edx ; Buffer address 3794 00001FE6 E604 <1> OUT DMA+4,AL ; OUTPUT LOW ADDRESS 3795 <1> IODELAY ; WAIT FOR I/O 2133 00001FE8 EB00 <2> jmp short $+2 2134 00001FEA EB00 <2> jmp short $+2 3796 00001FEC 88E0 <1> MOV AL,AH 3797 00001FEE E604 <1> OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 3798 00001FF0 C1E810 <1> shr eax,16 3799 <1> IODELAY ; I/O WAIT STATE 2133 00001FF3 EB00 <2> jmp short $+2 2134 00001FF5 EB00 <2> jmp short $+2 3800 00001FF7 E681 <1> OUT 081H,AL ; OUTPUT highest BITS TO PAGE REGISTER 3801 <1> IODELAY 2133 00001FF9 EB00 <2> jmp short $+2 2134 00001FFB EB00 <2> jmp short $+2 3802 00001FFD 6689C8 <1> mov ax,cx ; Byte count - 1 3803 00002000 E605 <1> OUT DMA+5,AL ; LOW BYTE OF COUNT 3804 <1> IODELAY ; WAIT FOR I/O 2133 00002002 EB00 <2> jmp short $+2 2134 00002004 EB00 <2> jmp short $+2 3805 00002006 88E0 <1> MOV AL,AH 3806 00002008 E605 <1> OUT DMA+5,AL ; HIGH BYTE OF COUNT 3807 <1> IODELAY 2133 0000200A EB00 <2> jmp short $+2 2134 0000200C EB00 <2> jmp short $+2 3808 0000200E FB <1> STI ; RE-ENABLE INTERRUPTS 3809 0000200F B002 <1> MOV AL,2 ; MODE FOR 8237 3810 00002011 E60A <1> OUT DMA+10,AL ; INITIALIZE THE DISKETTE CHANNEL 3811 <1> 3812 00002013 F8 <1> clc ; 04/02/2016 3813 00002014 C3 <1> retn 3814 <1> 3815 <1> dma_bnd_err_stc: 3816 00002015 F9 <1> stc 3817 <1> dma_bnd_err: 3818 00002016 C605[2C6E0000]09 <1> MOV byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 3819 0000201D C3 <1> RETn ; CY SET BY ABOVE IF ERROR 3820 <1> 3821 <1> ;; 16/12/2014 3822 <1> ;; CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 3823 <1> ;; OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 3824 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3825 <1> ;; IODELAY 3826 <1> ;; OUT DMA+11,AL ; OUTPUT THE MODE BYTE 3827 <1> ;; ;SIODELAY 3828 <1> ;; ;CMP AL, 42H ; DMA VERIFY COMMAND 3829 <1> ;; ;JNE short NOT_VERF ; NO 3830 <1> ;; ;XOR AX, AX ; START ADDRESS 3831 <1> ;; ;JMP SHORT J33 3832 <1> ;;;NOT_VERF: 3833 <1> ;; ;MOV AX,ES ; GET THE ES VALUE 3834 <1> ;; ;ROL AX,4 ; ROTATE LEFT 3835 <1> ;; ;MOV CH,AL ; GET HIGHEST NIBBLE OF ES TO CH 3836 <1> ;; ;AND AL,11110000B ; ZERO THE LOW NIBBLE FROM SEGMENT 3837 <1> ;; ;ADD AX,[BP+2] ; TEST FOR CARRY FROM ADDITION 3838 <1> ;; mov eax, [ebp+4] ; 06/02/2015 3839 <1> ;; ;JNC short J33 3840 <1> ;; ;INC CH ; CARRY MEANS HIGH 4 BITS MUST BE INC 3841 <1> ;;;J33: 3842 <1> ;; PUSH eAX ; SAVE START ADDRESS 3843 <1> ;; OUT DMA+4,AL ; OUTPUT LOW ADDRESS 3844 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3845 <1> ;; IODELAY 3846 <1> ;; MOV AL,AH 3847 <1> ;; OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 3848 <1> ;; shr eax, 16 ; 07/02/2015 3849 <1> ;; ;MOV AL,CH ; GET HIGH 4 BITS 3850 <1> ;; ;JMP $+2 ; I/O WAIT STATE 3851 <1> ;; IODELAY 3852 <1> ;; ;AND AL,00001111B 3853 <1> ;; OUT 081H,AL ; OUTPUT HIGH 4 BITS TO PAGE REGISTER 3854 <1> ;; ;SIODELAY 3855 <1> ;; 3856 <1> ;;;----- DETERMINE COUNT 3857 <1> ;; sub eax, eax ; 08/02/2015 3858 <1> ;; MOV AX, SI ; AL = # OF SECTORS 3859 <1> ;; XCHG AL, AH ; AH = # OF SECTORS 3860 <1> ;; SUB AL, AL ; AL = 0, AX = # SECTORS * 256 3861 <1> ;; SHR AX, 1 ; AX = # SECTORS * 128 3862 <1> ;; PUSH AX ; SAVE # OF SECTORS * 128 3863 <1> ;; MOV DL, 3 ; GET BYTES/SECTOR PARAMETER 3864 <1> ;; CALL GET_PARM ; " 3865 <1> ;; MOV CL,AH ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 3866 <1> ;; POP AX ; AX = # SECTORS * 128 3867 <1> ;; SHL AX,CL ; SHIFT BY PARAMETER VALUE 3868 <1> ;; DEC AX ; -1 FOR DMA VALUE 3869 <1> ;; PUSH eAX ; 08/02/2015 ; SAVE COUNT VALUE 3870 <1> ;; OUT DMA+5,AL ; LOW BYTE OF COUNT 3871 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3872 <1> ;; IODELAY 3873 <1> ;; MOV AL, AH 3874 <1> ;; OUT DMA+5,AL ; HIGH BYTE OF COUNT 3875 <1> ;; ;IODELAY 3876 <1> ;; STI ; RE-ENABLE INTERRUPTS 3877 <1> ;; POP eCX ; 08/02/2015 ; RECOVER COUNT VALUE 3878 <1> ;; POP eAX ; 08/02/2015 ; RECOVER ADDRESS VALUE 3879 <1> ;; ;ADD AX, CX ; ADD, TEST FOR 64K OVERFLOW 3880 <1> ;; add ecx, eax ; 08/02/2015 3881 <1> ;; MOV AL, 2 ; MODE FOR 8237 3882 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3883 <1> ;; SIODELAY 3884 <1> ;; OUT DMA+10, AL ; INITIALIZE THE DISKETTE CHANNEL 3885 <1> ;; ;JNC short NO_BAD ; CHECK FOR ERROR 3886 <1> ;; jc short dma_bnd_err ; 08/02/2015 3887 <1> ;; and ecx, 0FFF00000h ; 16 MB limit 3888 <1> ;; jz short NO_BAD 3889 <1> ;;dma_bnd_err: 3890 <1> ;; MOV byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 3891 <1> ;;NO_BAD: 3892 <1> ;; RETn ; CY SET BY ABOVE IF ERROR 3893 <1> 3894 <1> ;------------------------------------------------------------------------------- 3895 <1> ; FMTDMA_SET 3896 <1> ; THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION. 3897 <1> ; 3898 <1> ; ON ENTRY: NOTHING REQUIRED 3899 <1> ; 3900 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3901 <1> ;------------------------------------------------------------------------------- 3902 <1> 3903 <1> ; 05/12/2021 3904 <1> FMTDMA_SET: 3905 <1> ;; 20/02/2015 modification 3906 0000201E 8B5504 <1> mov edx, [ebp+4] ; Buffer address 3907 00002021 F7C20000F0FF <1> test edx, 0FFF00000h ; 16 MB limit 3908 00002027 75EC <1> jnz short dma_bnd_err_stc 3909 <1> ; 3910 <1> ;push dx ; * 3911 <1> ; 05/12/2021 3912 00002029 52 <1> push edx 3913 0000202A B204 <1> mov DL, 4 ; SECTORS/TRACK VALUE IN PARM TABLE 3914 0000202C E8C4020000 <1> call GET_PARM ; " 3915 <1> ;mov al, ah ; AL = SECTORS/TRACK VALUE 3916 <1> ;sub ah, ah ; AX = SECTORS/TRACK VALUE 3917 <1> ;shl ax, 2 ; AX = SEC/TRK * 4 (OFFSET C,H,R,N) 3918 <1> ;dec ax ; -1 FOR DMA VALUE 3919 <1> ;mov cx, ax 3920 <1> ; 05/12/2021 3921 00002031 29C9 <1> sub ecx, ecx 3922 00002033 88E1 <1> mov cl, ah ; SECTORS/TRACK VALUE 3923 00002035 D1E1 <1> shl ecx, 1 3924 00002037 D1E1 <1> shl ecx, 1 ; cx = SEC/TRK * 4 (OFFSET C,H,R,N) 3925 00002039 6649 <1> dec cx 3926 <1> ;pop dx ; * 3927 <1> ; 05/12/2021 3928 0000203B 5A <1> pop edx 3929 0000203C 6601CA <1> add dx, cx ; check for overflow 3930 0000203F 72D5 <1> jc short dma_bnd_err 3931 <1> ; 3932 00002041 6629CA <1> sub dx, cx ; Restore start address 3933 <1> ; 3934 00002044 B04A <1> MOV AL,04AH ; WILL WRITE TO THE DISKETTE 3935 00002046 FA <1> CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 3936 00002047 E60C <1> OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 3937 <1> IODELAY ; WAIT FOR I/O 2133 00002049 EB00 <2> jmp short $+2 2134 0000204B EB00 <2> jmp short $+2 3938 0000204D E60B <1> OUT DMA+11,AL ; OUTPUT THE MODE BYTE 3939 0000204F 89D0 <1> mov eax,edx ; Buffer address 3940 00002051 E604 <1> OUT DMA+4,AL ; OUTPUT LOW ADDRESS 3941 <1> IODELAY ; WAIT FOR I/O 2133 00002053 EB00 <2> jmp short $+2 2134 00002055 EB00 <2> jmp short $+2 3942 00002057 88E0 <1> MOV AL,AH 3943 00002059 E604 <1> OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 3944 0000205B C1E810 <1> shr eax,16 3945 <1> IODELAY ; I/O WAIT STATE 2133 0000205E EB00 <2> jmp short $+2 2134 00002060 EB00 <2> jmp short $+2 3946 00002062 E681 <1> OUT 081H,AL ; OUTPUT highest BITS TO PAGE REGISTER 3947 <1> IODELAY 2133 00002064 EB00 <2> jmp short $+2 2134 00002066 EB00 <2> jmp short $+2 3948 00002068 6689C8 <1> mov ax,cx ; Byte count - 1 3949 0000206B E605 <1> OUT DMA+5,AL ; LOW BYTE OF COUNT 3950 <1> IODELAY ; WAIT FOR I/O 2133 0000206D EB00 <2> jmp short $+2 2134 0000206F EB00 <2> jmp short $+2 3951 00002071 88E0 <1> MOV AL,AH 3952 00002073 E605 <1> OUT DMA+5,AL ; HIGH BYTE OF COUNT 3953 <1> IODELAY 2133 00002075 EB00 <2> jmp short $+2 2134 00002077 EB00 <2> jmp short $+2 3954 00002079 FB <1> STI ; RE-ENABLE INTERRUPTS 3955 0000207A B002 <1> MOV AL,2 ; MODE FOR 8237 3956 0000207C E60A <1> OUT DMA+10,AL ; INITIALIZE THE DISKETTE CHANNEL 3957 0000207E C3 <1> retn 3958 <1> 3959 <1> ;; 08/02/2015 - Protected Mode Modification 3960 <1> ;; MOV AL, 04AH ; WILL WRITE TO THE DISKETTE 3961 <1> ;; CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 3962 <1> ;; OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 3963 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3964 <1> ;; IODELAY 3965 <1> ;; OUT DMA+11,AL ; OUTPUT THE MODE BYTE 3966 <1> ;; ;MOV AX,ES ; GET THE ES VALUE 3967 <1> ;; ;ROL AX,4 ; ROTATE LEFT 3968 <1> ;; ;MOV CH,AL ; GET HIGHEST NIBBLE OF ES TO CH 3969 <1> ;; ;AND AL,11110000B ; ZERO THE LOW NIBBLE FROM SEGMENT 3970 <1> ;; ;ADD AX,[BP+2] ; TEST FOR CARRY FROM ADDITION 3971 <1> ;; ;JNC short J33A 3972 <1> ;; ;INC CH ; CARRY MEANS HIGH 4 BITS MUST BE INC 3973 <1> ;; mov eax, [ebp+4] ; 08/02/2015 3974 <1> ;;;J33A: 3975 <1> ;; PUSH eAX ; 08/02/2015 ; SAVE START ADDRESS 3976 <1> ;; OUT DMA+4,AL ; OUTPUT LOW ADDRESS 3977 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3978 <1> ;; IODELAY 3979 <1> ;; MOV AL,AH 3980 <1> ;; OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 3981 <1> ;; shr eax, 16 ; 08/02/2015 3982 <1> ;; ;MOV AL,CH ; GET HIGH 4 BITS 3983 <1> ;; ;JMP $+2 ; I/O WAIT STATE 3984 <1> ;; IODELAY 3985 <1> ;; ;AND AL,00001111B 3986 <1> ;; OUT 081H,AL ; OUTPUT HIGH 4 BITS TO PAGE REGISTER 3987 <1> ;; 3988 <1> ;;;----- DETERMINE COUNT 3989 <1> ;; sub eax, eax ; 08/02/2015 3990 <1> ;; MOV DL, 4 ; SECTORS/TRACK VALUE IN PARM TABLE 3991 <1> ;; CALL GET_PARM ; " 3992 <1> ;; XCHG AL, AH ; AL = SECTORS/TRACK VALUE 3993 <1> ;; SUB AH, AH ; AX = SECTORS/TRACK VALUE 3994 <1> ;; SHL AX, 2 ; AX = SEC/TRK * 4 (OFFSET C,H,R,N) 3995 <1> ;; DEC AX ; -1 FOR DMA VALUE 3996 <1> ;; PUSH eAX ; 08/02/2015 ; SAVE # OF BYTES TO BE TRANSFERED 3997 <1> ;; OUT DMA+5,AL ; LOW BYTE OF COUNT 3998 <1> ;; ;JMP $+2 ; WAIT FOR I/O 3999 <1> ;; IODELAY 4000 <1> ;; MOV AL, AH 4001 <1> ;; OUT DMA+5,AL ; HIGH BYTE OF COUNT 4002 <1> ;; STI ; RE-ENABLE INTERRUPTS 4003 <1> ;; POP eCX ; 08/02/2015 ; RECOVER COUNT VALUE 4004 <1> ;; POP eAX ; 08/02/2015 ; RECOVER ADDRESS VALUE 4005 <1> ;; ;ADD AX, CX ; ADD, TEST FOR 64K OVERFLOW 4006 <1> ;; add ecx, eax ; 08/02/2015 4007 <1> ;; MOV AL, 2 ; MODE FOR 8237 4008 <1> ;; ;JMP $+2 ; WAIT FOR I/O 4009 <1> ;; SIODELAY 4010 <1> ;; OUT DMA+10, AL ; INITIALIZE THE DISKETTE CHANNEL 4011 <1> ;; ;JNC short FMTDMA_OK ; CHECK FOR ERROR 4012 <1> ;; jc short fmtdma_bnd_err ; 08/02/2015 4013 <1> ;; and ecx, 0FFF00000h ; 16 MB limit 4014 <1> ;; jz short FMTDMA_OK 4015 <1> ;; stc ; 20/02/2015 4016 <1> ;;fmtdma_bnd_err: 4017 <1> ;; MOV byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 4018 <1> ;;FMTDMA_OK: 4019 <1> ;; RETn ; CY SET BY ABOVE IF ERROR 4020 <1> 4021 <1> ;------------------------------------------------------------------------------- 4022 <1> ; NEC_INIT 4023 <1> ; THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES 4024 <1> ; THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION. 4025 <1> ; 4026 <1> ; ON ENTRY: AH = NEC COMMAND TO BE PERFORMED 4027 <1> ; 4028 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 4029 <1> ;------------------------------------------------------------------------------- 4030 <1> NEC_INIT: 4031 <1> ;PUSH AX ; SAVE NEC COMMAND 4032 <1> ; 05/12/2021 4033 0000207F 50 <1> push eax 4034 00002080 E8B5020000 <1> CALL MOTOR_ON ; TURN MOTOR ON FOR SPECIFIC DRIVE 4035 <1> 4036 <1> ;----- DO THE SEEK OPERATION 4037 <1> 4038 00002085 8A6D01 <1> MOV CH,[eBP+1] ; CH = TRACK # 4039 00002088 E8A7030000 <1> CALL SEEK ; MOVE TO CORRECT TRACK 4040 <1> ;POP AX ; RECOVER COMMAND 4041 <1> ; 05/12/2021 4042 0000208D 58 <1> pop eax 4043 0000208E 721E <1> JC short ER_1 ; ERROR ON SEEK 4044 00002090 BB[AE200000] <1> MOV eBX, ER_1 ; LOAD ERROR ADDRESS 4045 00002095 53 <1> PUSH eBX ; PUSH NEC_OUT ERROR RETURN 4046 <1> 4047 <1> ;----- SEND OUT THE PARAMETERS TO THE CONTROLLER 4048 <1> 4049 00002096 E860030000 <1> CALL NEC_OUTPUT ; OUTPUT THE OPERATION COMMAND 4050 0000209B 6689F0 <1> MOV AX,SI ; AH = HEAD # 4051 0000209E 89FB <1> MOV eBX,eDI ; BL = DRIVE # 4052 000020A0 C0E402 <1> SAL AH,2 ; MOVE IT TO BIT 2 4053 000020A3 80E404 <1> AND AH,00000100B ; ISOLATE THAT BIT 4054 000020A6 08DC <1> OR AH,BL ; OR IN THE DRIVE NUMBER 4055 000020A8 E84E030000 <1> CALL NEC_OUTPUT ; FALL THRU CY SET IF ERROR 4056 000020AD 5B <1> POP eBX ; THROW AWAY ERROR RETURN 4057 <1> ER_1: 4058 000020AE C3 <1> RETn 4059 <1> 4060 <1> ;------------------------------------------------------------------------------- 4061 <1> ; RWV_COM 4062 <1> ; THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 4063 <1> ; READ/WRITE/VERIFY OPERATIONS. 4064 <1> ; 4065 <1> ; ON ENTRY: CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE 4066 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 4067 <1> ;------------------------------------------------------------------------------- 4068 <1> RWV_COM: 4069 000020AF B8[FA200000] <1> MOV eAX, ER_2 ; LOAD ERROR ADDRESS 4070 000020B4 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 4071 000020B5 8A6501 <1> MOV AH,[eBP+1] ; OUTPUT TRACK # 4072 000020B8 E83E030000 <1> CALL NEC_OUTPUT 4073 000020BD 6689F0 <1> MOV AX,SI ; OUTPUT HEAD # 4074 000020C0 E836030000 <1> CALL NEC_OUTPUT 4075 000020C5 8A6500 <1> MOV AH,[eBP] ; OUTPUT SECTOR # 4076 000020C8 E82E030000 <1> CALL NEC_OUTPUT 4077 000020CD B203 <1> MOV DL,3 ; BYTES/SECTOR PARAMETER FROM BLOCK 4078 000020CF E821020000 <1> CALL GET_PARM ; ... TO THE NEC 4079 000020D4 E822030000 <1> CALL NEC_OUTPUT ; OUTPUT TO CONTROLLER 4080 000020D9 B204 <1> MOV DL,4 ; EOT PARAMETER FROM BLOCK 4081 000020DB E815020000 <1> CALL GET_PARM ; ... TO THE NEC 4082 000020E0 E816030000 <1> CALL NEC_OUTPUT ; OUTPUT TO CONTROLLER 4083 000020E5 8A6305 <1> MOV AH, [eBX+MD.GAP] ; GET GAP LENGTH 4084 <1> _R15: 4085 000020E8 E80E030000 <1> CALL NEC_OUTPUT 4086 000020ED B206 <1> MOV DL,6 ; DTL PARAMETER PROM BLOCK 4087 000020EF E801020000 <1> CALL GET_PARM ; TO THE NEC 4088 000020F4 E802030000 <1> CALL NEC_OUTPUT ; OUTPUT TO CONTROLLER 4089 000020F9 58 <1> POP eAX ; THROW AWAY ERROR EXIT 4090 <1> ER_2: 4091 000020FA C3 <1> RETn 4092 <1> 4093 <1> ;------------------------------------------------------------------------------- 4094 <1> ; NEC_TERM 4095 <1> ; THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 4096 <1> ; FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION. 4097 <1> ; 4098 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 4099 <1> ;------------------------------------------------------------------------------- 4100 <1> NEC_TERM: 4101 <1> 4102 <1> ;----- LET THE OPERATION HAPPEN 4103 <1> 4104 000020FB 56 <1> PUSH eSI ; SAVE HEAD #, # OF SECTORS 4105 000020FC E804040000 <1> CALL WAIT_INT ; WAIT FOR THE INTERRUPT 4106 00002101 9C <1> PUSHFd ; 05/12/2021 4107 00002102 E82E040000 <1> CALL RESULTS ; GET THE NEC STATUS 4108 00002107 724B <1> JC short SET_END_POP 4109 00002109 9D <1> POPFd ; 05/12/2021 4110 0000210A 723E <1> JC short SET_END ; LOOK FOR ERROR 4111 <1> 4112 <1> ;----- CHECK THE RESULTS RETURNED BY THE CONTROLLER 4113 <1> 4114 0000210C FC <1> CLD ; SET THE CORRECT DIRECTION 4115 0000210D BE[2D6E0000] <1> MOV eSI, NEC_STATUS ; POINT TO STATUS FIELD 4116 00002112 AC <1> lodsb ; GET ST0 4117 00002113 24C0 <1> AND AL,11000000B ; TEST FOR NORMAL TERMINATION 4118 00002115 7433 <1> JZ short SET_END 4119 00002117 3C40 <1> CMP AL,01000000B ; TEST FOR ABNORMAL TERMINATION 4120 00002119 7527 <1> JNZ short J18 ; NOT ABNORMAL, BAD NEC 4121 <1> 4122 <1> ;----- ABNORMAL TERMINATION, FIND OUT WHY 4123 <1> 4124 0000211B AC <1> lodsb ; GET ST1 4125 0000211C D0E0 <1> SAL AL,1 ; TEST FOR EDT FOUND 4126 0000211E B404 <1> MOV AH,RECORD_NOT_FND 4127 00002120 7222 <1> JC short J19 4128 00002122 C0E002 <1> SAL AL,2 4129 00002125 B410 <1> MOV AH,BAD_CRC 4130 00002127 721B <1> JC short J19 4131 00002129 D0E0 <1> SAL AL,1 ; TEST FOR DMA OVERRUN 4132 0000212B B408 <1> MOV AH,BAD_DMA 4133 0000212D 7215 <1> JC short J19 4134 0000212F C0E002 <1> SAL AL,2 ; TEST FOR RECORD NOT FOUND 4135 00002132 B404 <1> MOV AH,RECORD_NOT_FND 4136 00002134 720E <1> JC short J19 4137 00002136 D0E0 <1> SAL AL,1 4138 00002138 B403 <1> MOV AH,WRITE_PROTECT ; TEST FOR WRITE_PROTECT 4139 0000213A 7208 <1> JC short J19 4140 0000213C D0E0 <1> SAL AL,1 ; TEST MISSING ADDRESS MARK 4141 0000213E B402 <1> MOV AH,BAD_ADDR_MARK 4142 00002140 7202 <1> JC short J19 4143 <1> 4144 <1> ;----- NEC MUST HAVE FAILED 4145 <1> J18: 4146 00002142 B420 <1> MOV AH,BAD_NEC 4147 <1> J19: 4148 00002144 0825[2C6E0000] <1> OR [DSKETTE_STATUS],AH 4149 <1> SET_END: 4150 0000214A 803D[2C6E0000]01 <1> CMP byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION 4151 00002151 F5 <1> CMC 4152 00002152 5E <1> POP eSI 4153 00002153 C3 <1> RETn ; RESTORE HEAD #, # OF SECTORS 4154 <1> 4155 <1> SET_END_POP: 4156 00002154 9D <1> POPFd ; 05/12/2021 4157 00002155 EBF3 <1> JMP SHORT SET_END 4158 <1> 4159 <1> ;------------------------------------------------------------------------------- 4160 <1> ; DSTATE: ESTABLISH STATE UPON SUCCESSFUL OPERATION. 4161 <1> ;------------------------------------------------------------------------------- 4162 <1> DSTATE: 4163 00002157 803D[2C6E0000]00 <1> CMP byte [DSKETTE_STATUS],0 ; CHECK FOR ERROR 4164 0000215E 753E <1> JNZ short SETBAC ; IF ERROR JUMP 4165 00002160 808F[396E0000]10 <1> OR byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED 4166 00002167 F687[396E0000]04 <1> TEST byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ? 4167 0000216E 752E <1> JNZ short SETBAC ; IF DETERMINED NO TRY TO DETERMINE 4168 00002170 8A87[396E0000] <1> MOV AL,[DSK_STATE+eDI] ; LOAD STATE 4169 00002176 24C0 <1> AND AL,RATE_MSK ; KEEP ONLY RATE 4170 00002178 3C80 <1> CMP AL,RATE_250 ; RATE 250 ? 4171 0000217A 751B <1> JNE short M_12 ; NO, MUST BE 1.2M OR 1.44M DRIVE 4172 <1> 4173 <1> ;----- CHECK IF IT IS 1.44M 4174 <1> 4175 0000217C E86B010000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 4176 <1> ;;20/02/2015 4177 <1> ;;JC short M_12 ; CMOS BAD 4178 00002181 7414 <1> jz short M_12 ;; 20/02/2015 4179 00002183 3C04 <1> CMP AL, 4 ; 1.44MB DRIVE ? 4180 00002185 7410 <1> JE short M_12 ; YES 4181 <1> M_720: 4182 00002187 80A7[396E0000]FD <1> AND byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY 4183 0000218E 808F[396E0000]04 <1> OR byte [DSK_STATE+eDI],DRV_DET ; MARK DRIVE DETERMINED 4184 00002195 EB07 <1> JMP SHORT SETBAC ; BACK 4185 <1> M_12: 4186 00002197 808F[396E0000]06 <1> OR byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 4187 <1> ; TURN ON DETERMINED & FMT CAPA 4188 <1> SETBAC: 4189 0000219E C3 <1> RETn 4190 <1> 4191 <1> ;------------------------------------------------------------------------------- 4192 <1> ; RETRY 4193 <1> ; DETERMINES WHETHER A RETRY IS NECESSARY. 4194 <1> ; IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY. 4195 <1> ; 4196 <1> ; ON EXIT: CY = 1 FOR RETRY, CY = 0 FOR NO RETRY 4197 <1> ;------------------------------------------------------------------------------- 4198 <1> RETRY: 4199 0000219F 803D[2C6E0000]00 <1> CMP byte [DSKETTE_STATUS],0 ; GET STATUS OF OPERATION 4200 000021A6 7445 <1> JZ short NO_RETRY ; SUCCESSFUL OPERATION 4201 000021A8 803D[2C6E0000]80 <1> CMP byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY 4202 000021AF 743C <1> JZ short NO_RETRY 4203 000021B1 8AA7[396E0000] <1> MOV AH,[DSK_STATE+eDI] ; GET MEDIA STATE OF DRIVE 4204 000021B7 F6C410 <1> TEST AH,MED_DET ; ESTABLISHED/DETERMINED ? 4205 000021BA 7531 <1> JNZ short NO_RETRY ; IF ESTABLISHED STATE THEN TRUE ERROR 4206 000021BC 80E4C0 <1> AND AH,RATE_MSK ; ISOLATE RATE 4207 000021BF 8A2D[346E0000] <1> MOV CH,[LASTRATE] ; GET START OPERATION STATE 4208 000021C5 C0C504 <1> ROL CH,4 ; TO CORRESPONDING BITS 4209 000021C8 80E5C0 <1> AND CH,RATE_MSK ; ISOLATE RATE BITS 4210 000021CB 38E5 <1> CMP CH,AH ; ALL RATES TRIED 4211 000021CD 741E <1> JE short NO_RETRY ; IF YES, THEN TRUE ERROR 4212 <1> 4213 <1> ; SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE 4214 <1> ; 00000000B (500) -> 10000000B (250) 4215 <1> ; 10000000B (250) -> 01000000B (300) 4216 <1> ; 01000000B (300) -> 00000000B (500) 4217 <1> 4218 000021CF 80FC01 <1> CMP AH,RATE_500+1 ; SET CY FOR RATE 500 4219 000021D2 D0DC <1> RCR AH,1 ; TO NEXT STATE 4220 000021D4 80E4C0 <1> AND AH,RATE_MSK ; KEEP ONLY RATE BITS 4221 000021D7 80A7[396E0000]1F <1> AND byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) 4222 <1> ; RATE, DBL STEP OFF 4223 000021DE 08A7[396E0000] <1> OR [DSK_STATE+eDI],AH ; TURN ON NEW RATE 4224 000021E4 C605[2C6E0000]00 <1> MOV byte [DSKETTE_STATUS],0 ; RESET STATUS FOR RETRY 4225 000021EB F9 <1> STC ; SET CARRY FOR RETRY 4226 000021EC C3 <1> RETn ; RETRY RETURN 4227 <1> 4228 <1> NO_RETRY: 4229 000021ED F8 <1> CLC ; CLEAR CARRY NO RETRY 4230 000021EE C3 <1> RETn ; NO RETRY RETURN 4231 <1> 4232 <1> ;------------------------------------------------------------------------------- 4233 <1> ; NUM_TRANS 4234 <1> ; THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE 4235 <1> ; ACTUALLY TRANSFERRED TO/FROM THE DISKETTE. 4236 <1> ; 4237 <1> ; ON ENTRY: [BP+1] = TRACK 4238 <1> ; SI-HI = HEAD 4239 <1> ; [BP] = START SECTOR 4240 <1> ; 4241 <1> ; ON EXIT: AL = NUMBER ACTUALLY TRANSFERRED 4242 <1> ;------------------------------------------------------------------------------- 4243 <1> NUM_TRANS: 4244 000021EF 30C0 <1> XOR AL,AL ; CLEAR FOR ERROR 4245 000021F1 803D[2C6E0000]00 <1> CMP byte [DSKETTE_STATUS],0 ; CHECK FOR ERROR 4246 <1> ; 05/12/2021 4247 000021F8 752C <1> JNZ short NT_OUT ; IF ERROR 0 TRANSFERRED 4248 000021FA B204 <1> MOV DL,4 ; SECTORS/TRACK OFFSET TO DL 4249 000021FC E8F4000000 <1> CALL GET_PARM ; AH = SECTORS/TRACK 4250 00002201 8A1D[326E0000] <1> MOV BL, [NEC_STATUS+5] ; GET ENDING SECTOR 4251 00002207 6689F1 <1> MOV CX,SI ; CH = HEAD # STARTED 4252 0000220A 3A2D[316E0000] <1> CMP CH, [NEC_STATUS+4] ; GET HEAD ENDED UP ON 4253 00002210 750D <1> JNZ DIF_HD ; IF ON SAME HEAD, THEN NO ADJUST 4254 00002212 8A2D[306E0000] <1> MOV CH, [NEC_STATUS+3] ; GET TRACK ENDED UP ON 4255 00002218 3A6D01 <1> CMP CH,[eBP+1] ; IS IT ASKED FOR TRACK 4256 0000221B 7404 <1> JZ short SAME_TRK ; IF SAME TRACK NO INCREASE 4257 0000221D 00E3 <1> ADD BL,AH ; ADD SECTORS/TRACK 4258 <1> DIF_HD: 4259 0000221F 00E3 <1> ADD BL,AH ; ADD SECTORS/TRACK 4260 <1> SAME_TRK: 4261 00002221 2A5D00 <1> SUB BL,[eBP] ; SUBTRACT START FROM END 4262 00002224 88D8 <1> MOV AL,BL ; TO AL 4263 <1> NT_OUT: 4264 00002226 C3 <1> RETn 4265 <1> 4266 <1> ;------------------------------------------------------------------------------- 4267 <1> ; SETUP_END 4268 <1> ; RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 4269 <1> ; AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY. 4270 <1> ; 4271 <1> ; ON EXIT: 4272 <1> ; AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 4273 <1> ;------------------------------------------------------------------------------- 4274 <1> SETUP_END: 4275 00002227 B202 <1> MOV DL,2 ; GET THE MOTOR WAIT PARAMETER 4276 <1> ;PUSH AX ; SAVE NUMBER TRANSFERRED 4277 00002229 50 <1> push eax ; 05/12/2021 4278 0000222A E8C6000000 <1> CALL GET_PARM 4279 0000222F 8825[2B6E0000] <1> MOV [MOTOR_COUNT],AH ; STORE UPON RETURN 4280 <1> ;POP AX ; RESTORE NUMBER TRANSFERRED 4281 00002235 58 <1> pop eax ; 05/12/2021 4282 00002236 8A25[2C6E0000] <1> MOV AH, [DSKETTE_STATUS] ; GET STATUS OF OPERATION 4283 0000223C 08E4 <1> OR AH,AH ; CHECK FOR ERROR 4284 0000223E 7402 <1> JZ short NUN_ERR ; NO ERROR 4285 00002240 30C0 <1> XOR AL,AL ; CLEAR NUMBER RETURNED 4286 <1> NUN_ERR: 4287 00002242 80FC01 <1> CMP AH,1 ; SET THE CARRY FLAG TO INDICATE 4288 00002245 F5 <1> CMC ; SUCCESS OR FAILURE 4289 00002246 C3 <1> RETn 4290 <1> 4291 <1> ;------------------------------------------------------------------------------- 4292 <1> ; SETUP_DBL 4293 <1> ; CHECK DOUBLE STEP. 4294 <1> ; 4295 <1> ; ON ENTRY : DI = DRIVE 4296 <1> ; 4297 <1> ; ON EXIT : CY = 1 MEANS ERROR 4298 <1> ;------------------------------------------------------------------------------- 4299 <1> SETUP_DBL: 4300 00002247 8AA7[396E0000] <1> MOV AH, [DSK_STATE+eDI] ; ACCESS STATE 4301 0000224D F6C410 <1> TEST AH,MED_DET ; ESTABLISHED STATE ? 4302 00002250 757A <1> JNZ short NO_DBL ; IF ESTABLISHED THEN DOUBLE DONE 4303 <1> 4304 <1> ;----- CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE 4305 <1> 4306 00002252 C605[296E0000]00 <1> MOV byte [SEEK_STATUS],0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 4307 00002259 E8DC000000 <1> CALL MOTOR_ON ; ENSURE MOTOR STAY ON 4308 0000225E B500 <1> MOV CH,0 ; LOAD TRACK 0 4309 00002260 E8CF010000 <1> CALL SEEK ; SEEK TO TRACK 0 4310 00002265 E864000000 <1> CALL READ_ID ; READ ID FUNCTION 4311 0000226A 7245 <1> JC short SD_ERR ; IF ERROR NO TRACK 0 4312 <1> 4313 <1> ;----- INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS) 4314 <1> 4315 0000226C 66B95004 <1> MOV CX,0450H ; START, MAX TRACKS 4316 00002270 F687[396E0000]01 <1> TEST byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY 4317 00002277 7402 <1> JZ short CNT_OK ; IF NOT COUNT IS SETUP 4318 00002279 B1A0 <1> MOV CL,0A0H ; MAXIMUM TRACK 1.2 MB 4319 <1> 4320 <1> ; ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS, 4321 <1> ; MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT 4322 <1> ; THEN SET DOUBLE STEP ON. 4323 <1> 4324 <1> CNT_OK: 4325 0000227B C605[2B6E0000]FF <1> MOV byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 4326 <1> ;PUSH CX ; SAVE TRACK, COUNT 4327 <1> ; 05/12/2021 4328 00002282 51 <1> push ecx 4329 00002283 C605[2C6E0000]00 <1> MOV byte [DSKETTE_STATUS],0 ; CLEAR STATUS, EXPECT ERRORS 4330 0000228A 6631C0 <1> XOR AX,AX ; CLEAR AX 4331 0000228D D0ED <1> SHR CH,1 ; HALVE TRACK, CY = HEAD 4332 0000228F C0D003 <1> RCL AL,3 ; AX = HEAD IN CORRECT BIT 4333 <1> ;PUSH AX ; SAVE HEAD 4334 <1> ; 05/12/2021 4335 00002292 50 <1> push eax 4336 00002293 E89C010000 <1> CALL SEEK ; SEEK TO TRACK 4337 <1> ;POP AX ; RESTORE HEAD 4338 <1> ; 05/12/2021 4339 00002298 58 <1> pop eax 4340 00002299 6609C7 <1> OR DI,AX ; DI = HEAD OR'ED DRIVE 4341 0000229C E82D000000 <1> CALL READ_ID ; READ ID HEAD 0 4342 000022A1 9C <1> PUSHF ; SAVE RETURN FROM READ_ID 4343 000022A2 6681E7FB00 <1> AND DI,11111011B ; TURN OFF HEAD 1 BIT 4344 000022A7 9D <1> POPF ; RESTORE ERROR RETURN 4345 <1> ;POP CX ; RESTORE COUNT 4346 <1> ; 05/12/2021 4347 000022A8 59 <1> pop ecx 4348 000022A9 7308 <1> JNC short DO_CHK ; IF OK, ASKED = RETURNED TRACK ? 4349 000022AB FEC5 <1> INC CH ; INC FOR NEXT TRACK 4350 000022AD 38CD <1> CMP CH,CL ; REACHED MAXIMUM YET 4351 000022AF 75CA <1> JNZ short CNT_OK ; CONTINUE TILL ALL TRIED 4352 <1> 4353 <1> ;----- FALL THRU, READ ID FAILED FOR ALL TRACKS 4354 <1> 4355 <1> SD_ERR: 4356 000022B1 F9 <1> STC ; SET CARRY FOR ERROR 4357 000022B2 C3 <1> RETn ; SETUP_DBL ERROR EXIT 4358 <1> 4359 <1> DO_CHK: 4360 000022B3 8A0D[306E0000] <1> MOV CL, [NEC_STATUS+3] ; LOAD RETURNED TRACK 4361 000022B9 888F[3D6E0000] <1> MOV [DSK_TRK+eDI], CL ; STORE TRACK NUMBER 4362 000022BF D0ED <1> SHR CH,1 ; HALVE TRACK 4363 000022C1 38CD <1> CMP CH,CL ; IS IT THE SAME AS ASKED FOR TRACK 4364 000022C3 7407 <1> JZ short NO_DBL ; IF SAME THEN NO DOUBLE STEP 4365 000022C5 808F[396E0000]20 <1> OR byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED 4366 <1> NO_DBL: 4367 000022CC F8 <1> CLC ; CLEAR ERROR FLAG 4368 000022CD C3 <1> RETn 4369 <1> 4370 <1> ;------------------------------------------------------------------------------- 4371 <1> ; READ_ID 4372 <1> ; READ ID FUNCTION. 4373 <1> ; 4374 <1> ; ON ENTRY: DI : BIT 2 = HEAD; BITS 1,0 = DRIVE 4375 <1> ; 4376 <1> ; ON EXIT: DI : BIT 2 IS RESET, BITS 1,0 = DRIVE 4377 <1> ; @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 4378 <1> ;------------------------------------------------------------------------------- 4379 <1> READ_ID: 4380 000022CE B8[EB220000] <1> MOV eAX, ER_3 ; MOVE NEC OUTPUT ERROR ADDRESS 4381 000022D3 50 <1> PUSH eAX 4382 000022D4 B44A <1> MOV AH,4AH ; READ ID COMMAND 4383 000022D6 E820010000 <1> CALL NEC_OUTPUT ; TO CONTROLLER 4384 000022DB 6689F8 <1> MOV AX,DI ; DRIVE # TO AH, HEAD 0 4385 000022DE 88C4 <1> MOV AH,AL 4386 000022E0 E816010000 <1> CALL NEC_OUTPUT ; TO CONTROLLER 4387 000022E5 E811FEFFFF <1> CALL NEC_TERM ; WAIT FOR OPERATION, GET STATUS 4388 000022EA 58 <1> POP eAX ; THROW AWAY ERROR ADDRESS 4389 <1> ER_3: 4390 000022EB C3 <1> RETn 4391 <1> 4392 <1> ;------------------------------------------------------------------------------- 4393 <1> ; CMOS_TYPE 4394 <1> ; RETURNS DISKETTE TYPE FROM CMOS 4395 <1> ; 4396 <1> ; ON ENTRY: DI = DRIVE # 4397 <1> ; 4398 <1> ; ON EXIT: AL = TYPE; CY REFLECTS STATUS 4399 <1> ;------------------------------------------------------------------------------- 4400 <1> 4401 <1> CMOS_TYPE: ; 11/12/2014 4402 000022EC 8A87[9E680000] <1> mov al, [eDI+fd0_type] 4403 000022F2 20C0 <1> and al, al ; 18/12/2014 4404 000022F4 C3 <1> retn 4405 <1> 4406 <1> ;CMOS_TYPE: 4407 <1> ; MOV AL, CMOS_DIAG ; CMOS DIAGNOSTIC STATUS BYTE ADDRESS 4408 <1> ; CALL CMOS_READ ; GET CMOS STATUS 4409 <1> ; TEST AL,BAD_BAT+BAD_CKSUM ; BATTERY GOOD AND CHECKSUM VALID 4410 <1> ; STC ; SET CY = 1 INDICATING ERROR FOR RETURN 4411 <1> ; JNZ short BAD_CM ; ERROR IF EITHER BIT ON 4412 <1> ; MOV AL,CMOS_DISKETTE ; ADDRESS OF DISKETTE BYTE IN CMOS 4413 <1> ; CALL CMOS_READ ; GET DISKETTE BYTE 4414 <1> ; OR DI,DI ; SEE WHICH DRIVE IN QUESTION 4415 <1> ; JNZ short TB ; IF DRIVE 1, DATA IN LOW NIBBLE 4416 <1> ; ROR AL,4 ; EXCHANGE NIBBLES IF SECOND DRIVE 4417 <1> ;TB: 4418 <1> ; AND AL,0FH ; KEEP ONLY DRIVE DATA, RESET CY, 0 4419 <1> ;BAD_CM: 4420 <1> ; RETn ; CY, STATUS OF READ 4421 <1> 4422 <1> ;------------------------------------------------------------------------------- 4423 <1> ; GET_PARM 4424 <1> ; THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE 4425 <1> ; BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM 4426 <1> ; THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING 4427 <1> ; THE PARAMETER IN DL. 4428 <1> ; 4429 <1> ; ON ENTRY: DL = INDEX OF BYTE TO BE FETCHED 4430 <1> ; 4431 <1> ; ON EXIT: AH = THAT BYTE FROM BLOCK 4432 <1> ; AL,DH DESTROYED 4433 <1> ;------------------------------------------------------------------------------- 4434 <1> GET_PARM: 4435 <1> ;PUSH DS 4436 000022F5 56 <1> PUSH eSI 4437 <1> ;SUB AX,AX ; DS = 0, BIOS DATA AREA 4438 <1> ;MOV DS,AX 4439 <1> ;;mov ax, cs 4440 <1> ;;mov ds, ax 4441 <1> ; 08/02/2015 (protected mode modifications, bx -> ebx) 4442 000022F6 87D3 <1> XCHG eDX,eBX ; BL = INDEX 4443 <1> ;SUB BH,BH ; BX = INDEX 4444 000022F8 81E3FF000000 <1> and ebx, 0FFh 4445 <1> ;LDS SI, [DISK_POINTER] ; POINT TO BLOCK 4446 <1> ; 4447 <1> ; 17/12/2014 4448 000022FE 66A1[91680000] <1> mov ax, [cfd] ; current (AL) and previous fd (AH) 4449 00002304 38E0 <1> cmp al, ah 4450 00002306 7425 <1> je short gpndc 4451 00002308 A2[92680000] <1> mov [pfd], al ; current drive -> previous drive 4452 0000230D 53 <1> push ebx ; 08/02/2015 4453 0000230E 88C3 <1> mov bl, al 4454 <1> ; 11/12/2014 4455 00002310 8A83[9E680000] <1> mov al, [eBX+fd0_type] ; Drive type (0,1,2,3,4) 4456 <1> ; 18/12/2014 4457 00002316 20C0 <1> and al, al 4458 00002318 7507 <1> jnz short gpdtc 4459 0000231A BB[7B680000] <1> mov ebx, MD_TBL6 ; 1.44 MB param. tbl. (default) 4460 0000231F EB05 <1> jmp short gpdpu 4461 <1> gpdtc: 4462 00002321 E83EF9FFFF <1> call DR_TYPE_CHECK 4463 <1> ; cf = 1 -> eBX points to 1.44MB fd parameter table (default) 4464 <1> gpdpu: 4465 00002326 891D[18680000] <1> mov [DISK_POINTER], ebx 4466 0000232C 5B <1> pop ebx 4467 <1> gpndc: 4468 0000232D 8B35[18680000] <1> mov esi, [DISK_POINTER] ; 08/02/2015, si -> esi 4469 00002333 8A241E <1> MOV AH, [eSI+eBX] ; GET THE WORD 4470 00002336 87D3 <1> XCHG eDX,eBX ; RESTORE BX 4471 00002338 5E <1> POP eSI 4472 <1> ;POP DS 4473 00002339 C3 <1> RETn 4474 <1> 4475 <1> ;------------------------------------------------------------------------------- 4476 <1> ; MOTOR_ON 4477 <1> ; TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT 4478 <1> ; IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE 4479 <1> ; THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE 4480 <1> ; MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION 4481 <1> ; (AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM 4482 <1> ; THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS 4483 <1> ; FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT 4484 <1> ; HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE 4485 <1> ; THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID 4486 <1> ; NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE 4487 <1> ; PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN, 4488 <1> ; IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE 4489 <1> ; WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT. 4490 <1> ; 4491 <1> ; ON ENTRY: DI = DRIVE # 4492 <1> ; ON EXIT: AX,CX,DX DESTROYED 4493 <1> ;------------------------------------------------------------------------------- 4494 <1> MOTOR_ON: 4495 0000233A 53 <1> PUSH eBX ; SAVE REG. 4496 0000233B E82A000000 <1> CALL TURN_ON ; TURN ON MOTOR 4497 00002340 7226 <1> JC short MOT_IS_ON ; IF CY=1 NO WAIT 4498 00002342 E8C0F9FFFF <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 4499 00002347 E88AF9FFFF <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH, 4500 <1> ;CALL TURN_ON ; CHECK AGAIN IF MOTOR ON 4501 <1> ;JC MOT_IS_ON ; IF NO WAIT MEANS IT IS ON 4502 <1> M_WAIT: 4503 0000234C B20A <1> MOV DL,10 ; GET THE MOTOR WAIT PARAMETER 4504 0000234E E8A2FFFFFF <1> CALL GET_PARM 4505 <1> ;MOV AL,AH ; AL = MOTOR WAIT PARAMETER 4506 <1> ;XOR AH,AH ; AX = MOTOR WAIT PARAMETER 4507 <1> ;CMP AL,8 ; SEE IF AT LEAST A SECOND IS SPECIFIED 4508 00002353 80FC08 <1> cmp ah, 8 4509 <1> ;JAE short GP2 ; IF YES, CONTINUE 4510 00002356 7702 <1> ja short J13 4511 <1> ;MOV AL,8 ; ONE SECOND WAIT FOR MOTOR START UP 4512 00002358 B408 <1> mov ah, 8 4513 <1> 4514 <1> ;----- AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT 4515 <1> GP2: 4516 <1> ;----- FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE 4517 <1> J13: ; WAIT FOR 1/8 SECOND PER (AL) 4518 0000235A B95E200000 <1> MOV eCX,8286 ; COUNT FOR 1/8 SECOND AT 15.085737 US 4519 0000235F E867F1FFFF <1> CALL WAITF ; GO TO FIXED WAIT ROUTINE 4520 <1> ;DEC AL ; DECREMENT TIME VALUE 4521 00002364 FECC <1> dec ah 4522 00002366 75F2 <1> JNZ short J13 ; ARE WE DONE YET 4523 <1> MOT_IS_ON: 4524 00002368 5B <1> POP eBX ; RESTORE REG. 4525 00002369 C3 <1> RETn 4526 <1> 4527 <1> ;------------------------------------------------------------------------------- 4528 <1> ; TURN_ON 4529 <1> ; TURN MOTOR ON AND RETURN WAIT STATE. 4530 <1> ; 4531 <1> ; ON ENTRY: DI = DRIVE # 4532 <1> ; 4533 <1> ; ON EXIT: CY = 0 MEANS WAIT REQUIRED 4534 <1> ; CY = 1 MEANS NO WAIT REQUIRED 4535 <1> ; AX,BX,CX,DX DESTROYED 4536 <1> ;------------------------------------------------------------------------------- 4537 <1> TURN_ON: 4538 0000236A 89FB <1> MOV eBX,eDI ; BX = DRIVE # 4539 0000236C 88D9 <1> MOV CL,BL ; CL = DRIVE # 4540 0000236E C0C304 <1> ROL BL,4 ; BL = DRIVE SELECT 4541 00002371 FA <1> CLI ; NO INTERRUPTS WHILE DETERMINING STATUS 4542 00002372 C605[2B6E0000]FF <1> MOV byte [MOTOR_COUNT],0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 4543 00002379 A0[2A6E0000] <1> MOV AL, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 4544 0000237E 2430 <1> AND AL,00110000B ; KEEP ONLY DRIVE SELECT BITS 4545 00002380 B401 <1> MOV AH,1 ; MASK FOR DETERMINING MOTOR BIT 4546 00002382 D2E4 <1> SHL AH,CL ; AH = MOTOR ON, A=00000001, B=00000010 4547 <1> 4548 <1> ; AL = DRIVE SELECT FROM @MOTOR_STATUS 4549 <1> ; BL = DRIVE SELECT DESIRED 4550 <1> ; AH = MOTOR ON MASK DESIRED 4551 <1> 4552 00002384 38D8 <1> CMP AL,BL ; REQUESTED DRIVE ALREADY SELECTED ? 4553 00002386 7508 <1> JNZ short TURN_IT_ON ; IF NOT SELECTED JUMP 4554 00002388 8425[2A6E0000] <1> TEST AH, [MOTOR_STATUS] ; TEST MOTOR ON BIT 4555 0000238E 7535 <1> JNZ short NO_MOT_WAIT ; JUMP IF MOTOR ON AND SELECTED 4556 <1> 4557 <1> TURN_IT_ON: 4558 00002390 08DC <1> OR AH,BL ; AH = DRIVE SELECT AND MOTOR ON 4559 00002392 8A3D[2A6E0000] <1> MOV BH,[MOTOR_STATUS] ; SAVE COPY OF @MOTOR_STATUS BEFORE 4560 00002398 80E70F <1> AND BH,00001111B ; KEEP ONLY MOTOR BITS 4561 0000239B 8025[2A6E0000]CF <1> AND byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT 4562 000023A2 0825[2A6E0000] <1> OR [MOTOR_STATUS],AH ; OR IN DRIVE SELECTED AND MOTOR ON 4563 000023A8 A0[2A6E0000] <1> MOV AL,[MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 4564 000023AD 88C3 <1> MOV BL,AL ; BL=@MOTOR_STATUS AFTER, BH=BEFORE 4565 000023AF 80E30F <1> AND BL,00001111B ; KEEP ONLY MOTOR BITS 4566 000023B2 FB <1> STI ; ENABLE INTERRUPTS AGAIN 4567 000023B3 243F <1> AND AL,00111111B ; STRIP AWAY UNWANTED BITS 4568 000023B5 C0C004 <1> ROL AL,4 ; PUT BITS IN DESIRED POSITIONS 4569 000023B8 0C0C <1> OR AL,00001100B ; NO RESET, ENABLE DMA/INTERRUPT 4570 000023BA 66BAF203 <1> MOV DX,03F2H ; SELECT DRIVE AND TURN ON MOTOR 4571 000023BE EE <1> OUT DX,AL 4572 000023BF 38FB <1> CMP BL,BH ; NEW MOTOR TURNED ON ? 4573 <1> ;JZ short NO_MOT_WAIT ; NO WAIT REQUIRED IF JUST SELECT 4574 000023C1 7403 <1> je short no_mot_w1 ; 27/02/2015 4575 000023C3 F8 <1> CLC ; (re)SET CARRY MEANING WAIT 4576 000023C4 C3 <1> RETn 4577 <1> 4578 <1> NO_MOT_WAIT: 4579 000023C5 FB <1> sti 4580 <1> no_mot_w1: ; 27/02/2015 4581 000023C6 F9 <1> STC ; SET NO WAIT REQUIRED 4582 <1> ;STI ; INTERRUPTS BACK ON 4583 000023C7 C3 <1> RETn 4584 <1> 4585 <1> ;------------------------------------------------------------------------------- 4586 <1> ; HD_WAIT 4587 <1> ; WAIT FOR HEAD SETTLE TIME. 4588 <1> ; 4589 <1> ; ON ENTRY: DI = DRIVE # 4590 <1> ; 4591 <1> ; ON EXIT: AX,BX,CX,DX DESTROYED 4592 <1> ;------------------------------------------------------------------------------- 4593 <1> HD_WAIT: 4594 000023C8 B209 <1> MOV DL,9 ; GET HEAD SETTLE PARAMETER 4595 000023CA E826FFFFFF <1> CALL GET_PARM 4596 000023CF 08E4 <1> or ah, ah ; 17/12/2014 4597 000023D1 7519 <1> jnz short DO_WAT 4598 000023D3 F605[2A6E0000]80 <1> TEST byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION 4599 <1> ;JZ short ISNT_WRITE ; IF NOT, DO NOT ENFORCE ANY VALUES 4600 <1> ;OR AH,AH ; CHECK FOR ANY WAIT? 4601 <1> ;JNZ short DO_WAT ; IF THERE DO NOT ENFORCE 4602 000023DA 741E <1> jz short HW_DONE 4603 000023DC B40F <1> MOV AH,HD12_SETTLE ; LOAD 1.2M HEAD SETTLE MINIMUM 4604 000023DE 8A87[396E0000] <1> MOV AL,[DSK_STATE+eDI] ; LOAD STATE 4605 000023E4 24C0 <1> AND AL,RATE_MSK ; KEEP ONLY RATE 4606 000023E6 3C80 <1> CMP AL,RATE_250 ; 1.2 M DRIVE ? 4607 000023E8 7502 <1> JNZ short DO_WAT ; DEFAULT HEAD SETTLE LOADED 4608 <1> ;GP3: 4609 000023EA B414 <1> MOV AH,HD320_SETTLE ; USE 320/360 HEAD SETTLE 4610 <1> ; JMP SHORT DO_WAT 4611 <1> 4612 <1> ;ISNT_WRITE: 4613 <1> ; OR AH,AH ; CHECK FOR NO WAIT 4614 <1> ; JZ short HW_DONE ; IF NOT WRITE AND 0 ITS OK 4615 <1> 4616 <1> ;----- AH CONTAINS NUMBER OF MILLISECONDS TO WAIT 4617 <1> DO_WAT: 4618 <1> ; MOV AL,AH ; AL = # MILLISECONDS 4619 <1> ; ;XOR AH,AH ; AX = # MILLISECONDS 4620 <1> J29: ; 1 MILLISECOND LOOP 4621 <1> ;mov cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units. 4622 000023EC B942000000 <1> MOV eCX,66 ; COUNT AT 15.085737 US PER COUNT 4623 000023F1 E8D5F0FFFF <1> CALL WAITF ; DELAY FOR 1 MILLISECOND 4624 <1> ;DEC AL ; DECREMENT THE COUNT 4625 000023F6 FECC <1> dec ah 4626 000023F8 75F2 <1> JNZ short J29 ; DO AL MILLISECOND # OF TIMES 4627 <1> HW_DONE: 4628 000023FA C3 <1> RETn 4629 <1> 4630 <1> ;------------------------------------------------------------------------------- 4631 <1> ; NEC_OUTPUT 4632 <1> ; THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING 4633 <1> ; FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL 4634 <1> ; TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT 4635 <1> ; OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION. 4636 <1> ; 4637 <1> ; ON ENTRY: AH = BYTE TO BE OUTPUT 4638 <1> ; 4639 <1> ; ON EXIT: CY = 0 SUCCESS 4640 <1> ; CY = 1 FAILURE -- DISKETTE STATUS UPDATED 4641 <1> ; IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL 4642 <1> ; HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE 4643 <1> ; REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT. 4644 <1> ; AX,CX,DX DESTROYED 4645 <1> ;------------------------------------------------------------------------------- 4646 <1> 4647 <1> ; 09/12/2014 [Erdogan Tan] 4648 <1> ; (from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.) 4649 <1> ; Diskette Drive Controller Status Register (3F4h) 4650 <1> ; This read only register facilitates the transfer of data between 4651 <1> ; the system microprocessor and the controller. 4652 <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 4653 <1> ; with the system micrprocessor. 4654 <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0, 4655 <1> ; the transfer is to the controller. 4656 <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode. 4657 <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed. 4658 <1> ; Bit 3 - Reserved. 4659 <1> ; Bit 2 - Reserved. 4660 <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode. 4661 <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode. 4662 <1> 4663 <1> ; Data Register (3F5h) 4664 <1> ; This read/write register passes data, commands and parameters, and provides 4665 <1> ; diskette status information. 4666 <1> 4667 <1> NEC_OUTPUT: 4668 <1> ;PUSH BX ; SAVE REG. 4669 000023FB 66BAF403 <1> MOV DX,03F4H ; STATUS PORT 4670 <1> ;MOV BL,2 ; HIGH ORDER COUNTER 4671 <1> ;XOR CX,CX ; COUNT FOR TIME OUT 4672 <1> ; 16/12/2014 4673 <1> ; waiting for (max.) 0.5 seconds 4674 <1> ;;mov byte [wait_count], 0 ;; 27/02/2015 4675 <1> ; 4676 <1> ; 17/12/2014 4677 <1> ; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND 4678 <1> ; 4679 <1> ;WAIT_FOR_PORT: Waits for a bit at a port pointed to by DX to 4680 <1> ; go on. 4681 <1> ;INPUT: 4682 <1> ; AH=Mask for isolation bits. 4683 <1> ; AL=pattern to look for. 4684 <1> ; DX=Port to test for 4685 <1> ; BH:CX=Number of memory refresh periods to delay. 4686 <1> ; (normally 30 microseconds per period.) 4687 <1> ; 4688 <1> ;WFP_SHORT: 4689 <1> ; Wait for port if refresh cycle is short (15-80 Us range). 4690 <1> ; 4691 <1> 4692 <1> ; mov bl, WAIT_FDU_SEND_HI+1 ; 0+1 4693 <1> ; mov cx, WAIT_FDU_SEND_LO ; 16667 4694 000023FF B91B410000 <1> mov ecx, WAIT_FDU_SEND_LH ; 16667 (27/02/2015) 4695 <1> ; 4696 <1> ;WFPS_OUTER_LP: 4697 <1> ; ; 4698 <1> ;WFPS_CHECK_PORT: 4699 <1> J23: 4700 00002404 EC <1> IN AL,DX ; GET STATUS 4701 00002405 24C0 <1> AND AL,11000000B ; KEEP STATUS AND DIRECTION 4702 00002407 3C80 <1> CMP AL,10000000B ; STATUS 1 AND DIRECTION 0 ? 4703 00002409 7418 <1> JZ short J27 ; STATUS AND DIRECTION OK 4704 <1> WFPS_HI: 4705 0000240B E461 <1> IN AL, PORT_B ;061h ; SYS1 ; wait for hi to lo 4706 0000240D A810 <1> TEST AL,010H ; transition on memory 4707 0000240F 75FA <1> JNZ SHORT WFPS_HI ; refresh. 4708 <1> WFPS_LO: 4709 00002411 E461 <1> IN AL, PORT_B ; SYS1 4710 00002413 A810 <1> TEST AL,010H 4711 00002415 74FA <1> JZ SHORT WFPS_LO 4712 <1> ;LOOP SHORT WFPS_CHECK_PORT 4713 00002417 E2EB <1> loop J23 ; 27/02/2015 4714 <1> ; ; 4715 <1> ; dec bl 4716 <1> ; jnz short WFPS_OUTER_LP 4717 <1> ; jmp short WFPS_TIMEOUT ; fail 4718 <1> ;J23: 4719 <1> ; IN AL,DX ; GET STATUS 4720 <1> ; AND AL,11000000B ; KEEP STATUS AND DIRECTION 4721 <1> ; CMP AL,10000000B ; STATUS 1 AND DIRECTION 0 ? 4722 <1> ; JZ short J27 ; STATUS AND DIRECTION OK 4723 <1> ;LOOP J23 ; CONTINUE TILL CX EXHAUSTED 4724 <1> ;DEC BL ; DECREMENT COUNTER 4725 <1> ;JNZ short J23 ; REPEAT TILL DELAY FINISHED, CX = 0 4726 <1> 4727 <1> ;;27/02/2015 4728 <1> ;16/12/2014 4729 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 4730 <1> ;;jb short J23 4731 <1> 4732 <1> ;WFPS_TIMEOUT: 4733 <1> 4734 <1> ;----- FALL THRU TO ERROR RETURN 4735 <1> 4736 00002419 800D[2C6E0000]80 <1> OR byte [DSKETTE_STATUS],TIME_OUT 4737 <1> ;POP BX ; RESTORE REG. 4738 00002420 58 <1> POP eAX ; 08/02/2015 ; DISCARD THE RETURN ADDRESS 4739 00002421 F9 <1> STC ; INDICATE ERROR TO CALLER 4740 00002422 C3 <1> RETn 4741 <1> 4742 <1> ;----- DIRECTION AND STATUS OK; OUTPUT BYTE 4743 <1> 4744 <1> J27: 4745 00002423 88E0 <1> MOV AL,AH ; GET BYTE TO OUTPUT 4746 00002425 6642 <1> INC DX ; DATA PORT = STATUS PORT + 1 4747 00002427 EE <1> OUT DX,AL ; OUTPUT THE BYTE 4748 <1> ;;NEWIODELAY ;; 27/02/2015 4749 <1> ; 27/02/2015 4750 00002428 9C <1> PUSHFd ; 05/12/2021 ; SAVE FLAGS 4751 <1> ;MOV eCX, 3 ; 30 TO 45 MICROSECONDS WAIT FOR 4752 00002429 29C9 <1> sub ecx, ecx 4753 0000242B B103 <1> mov cl, 3 ; 05/12/2021 4754 0000242D E899F0FFFF <1> CALL WAITF ; NEC FLAGS UPDATE CYCLE 4755 00002432 9D <1> POPFd ; 05/12/2021 ; RESTORE FLAGS FOR EXIT 4756 <1> ;POP BX ; RESTORE REG 4757 00002433 C3 <1> RETn ; CY = 0 FROM TEST INSTRUCTION 4758 <1> 4759 <1> ;------------------------------------------------------------------------------- 4760 <1> ; SEEK 4761 <1> ; THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED 4762 <1> ; TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE 4763 <1> ; RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED. 4764 <1> ; 4765 <1> ; ON ENTRY: DI = DRIVE # 4766 <1> ; CH = TRACK # 4767 <1> ; 4768 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4769 <1> ; AX,BX,CX DX DESTROYED 4770 <1> ;------------------------------------------------------------------------------- 4771 <1> SEEK: 4772 00002434 89FB <1> MOV eBX,eDI ; BX = DRIVE # 4773 00002436 B001 <1> MOV AL,1 ; ESTABLISH MASK FOR RECALIBRATE TEST 4774 00002438 86CB <1> XCHG CL,BL ; SET DRIVE VALULE INTO CL 4775 0000243A D2C0 <1> ROL AL,CL ; SHIFT MASK BY THE DRIVE VALUE 4776 0000243C 86CB <1> XCHG CL,BL ; RECOVER TRACK VALUE 4777 0000243E 8405[296E0000] <1> TEST AL,[SEEK_STATUS] ; TEST FOR RECALIBRATE REQUIRED 4778 00002444 7526 <1> JNZ short J28A ; JUMP IF RECALIBRATE NOT REQUIRED 4779 <1> 4780 00002446 0805[296E0000] <1> OR [SEEK_STATUS],AL ; TURN ON THE NO RECALIBRATE BIT IN FLAG 4781 0000244C E862000000 <1> CALL RECAL ; RECALIBRATE DRIVE 4782 00002451 730E <1> JNC short AFT_RECAL ; RECALIBRATE DONE 4783 <1> 4784 <1> ;----- ISSUE RECALIBRATE FOR 80 TRACK DISKETTES 4785 <1> 4786 00002453 C605[2C6E0000]00 <1> MOV byte [DSKETTE_STATUS],0 ; CLEAR OUT INVALID STATUS 4787 0000245A E854000000 <1> CALL RECAL ; RECALIBRATE DRIVE 4788 0000245F 7251 <1> JC short RB ; IF RECALIBRATE FAILS TWICE THEN ERROR 4789 <1> 4790 <1> AFT_RECAL: 4791 00002461 C687[3D6E0000]00 <1> MOV byte [DSK_TRK+eDI],0 ; SAVE NEW CYLINDER AS PRESENT POSITION 4792 00002468 08ED <1> OR CH,CH ; CHECK FOR SEEK TO TRACK 0 4793 0000246A 743F <1> JZ short DO_WAIT ; HEAD SETTLE, CY = 0 IF JUMP 4794 <1> 4795 <1> ;----- DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK 4796 <1> 4797 0000246C F687[396E0000]20 <1> J28A: TEST byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED 4798 00002473 7402 <1> JZ short _R7 ; SINGLE STEP REQUIRED BYPASS DOUBLE 4799 00002475 D0E5 <1> SHL CH,1 ; DOUBLE NUMBER OF STEP TO TAKE 4800 <1> 4801 00002477 3AAF[3D6E0000] <1> _R7: CMP CH, [DSK_TRK+eDI] ; SEE IF ALREADY AT THE DESIRED TRACK 4802 0000247D 7433 <1> JE short RB ; IF YES, DO NOT NEED TO SEEK 4803 <1> 4804 0000247F BA[B2240000] <1> MOV eDX, NEC_ERR ; LOAD RETURN ADDRESS 4805 00002484 52 <1> PUSH eDX ; (*) ; ON STACK FOR NEC OUTPUT ERROR 4806 00002485 88AF[3D6E0000] <1> MOV [DSK_TRK+eDI],CH ; SAVE NEW CYLINDER AS PRESENT POSITION 4807 0000248B B40F <1> MOV AH,0FH ; SEEK COMMAND TO NEC 4808 0000248D E869FFFFFF <1> CALL NEC_OUTPUT 4809 00002492 89FB <1> MOV eBX,eDI ; BX = DRIVE # 4810 00002494 88DC <1> MOV AH,BL ; OUTPUT DRIVE NUMBER 4811 00002496 E860FFFFFF <1> CALL NEC_OUTPUT 4812 0000249B 8AA7[3D6E0000] <1> MOV AH, [DSK_TRK+eDI] ; GET CYLINDER NUMBER 4813 000024A1 E855FFFFFF <1> CALL NEC_OUTPUT 4814 000024A6 E827000000 <1> CALL CHK_STAT_2 ; ENDING INTERRUPT AND SENSE STATUS 4815 <1> 4816 <1> ;----- WAIT FOR HEAD SETTLE 4817 <1> 4818 <1> DO_WAIT: 4819 000024AB 9C <1> PUSHFd ; 05/12/2021 ; SAVE STATUS 4820 000024AC E817FFFFFF <1> CALL HD_WAIT ; WAIT FOR HEAD SETTLE TIME 4821 000024B1 9D <1> POPFd ; 05/12/2021 ; RESTORE STATUS 4822 <1> RB: 4823 <1> NEC_ERR: 4824 <1> ; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM) 4825 <1> ; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn 4826 000024B2 C3 <1> RETn ; RETURN TO CALLER 4827 <1> 4828 <1> ;------------------------------------------------------------------------------- 4829 <1> ; RECAL 4830 <1> ; RECALIBRATE DRIVE 4831 <1> ; 4832 <1> ; ON ENTRY: DI = DRIVE # 4833 <1> ; 4834 <1> ; ON EXIT: CY REFLECTS STATUS OF OPERATION. 4835 <1> ;------------------------------------------------------------------------------- 4836 <1> RECAL: 4837 <1> ;PUSH CX 4838 <1> ; 05/12/2021 4839 000024B3 51 <1> push ecx 4840 000024B4 B8[D0240000] <1> MOV eAX, RC_BACK ; LOAD NEC_OUTPUT ERROR 4841 000024B9 50 <1> PUSH eAX 4842 000024BA B407 <1> MOV AH,07H ; RECALIBRATE COMMAND 4843 000024BC E83AFFFFFF <1> CALL NEC_OUTPUT 4844 000024C1 89FB <1> MOV eBX,eDI ; BX = DRIVE # 4845 000024C3 88DC <1> MOV AH,BL 4846 000024C5 E831FFFFFF <1> CALL NEC_OUTPUT ; OUTPUT THE DRIVE NUMBER 4847 000024CA E803000000 <1> CALL CHK_STAT_2 ; GET THE INTERRUPT AND SENSE INT STATUS 4848 000024CF 58 <1> POP eAX ; THROW AWAY ERROR 4849 <1> RC_BACK: 4850 <1> ;POP CX 4851 <1> ; 05/12/2021 4852 000024D0 59 <1> pop ecx 4853 000024D1 C3 <1> RETn 4854 <1> 4855 <1> ;------------------------------------------------------------------------------- 4856 <1> ; CHK_STAT_2 4857 <1> ; THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE, 4858 <1> ; OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE 4859 <1> ; INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER. 4860 <1> ; 4861 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4862 <1> ;------------------------------------------------------------------------------- 4863 <1> CHK_STAT_2: 4864 000024D2 B8[FA240000] <1> MOV eAX, CS_BACK ; LOAD NEC_OUTPUT ERROR ADDRESS 4865 000024D7 50 <1> PUSH eAX 4866 000024D8 E828000000 <1> CALL WAIT_INT ; WAIT FOR THE INTERRUPT 4867 000024DD 721A <1> JC short J34 ; IF ERROR, RETURN IT 4868 000024DF B408 <1> MOV AH,08H ; SENSE INTERRUPT STATUS COMMAND 4869 000024E1 E815FFFFFF <1> CALL NEC_OUTPUT 4870 000024E6 E84A000000 <1> CALL RESULTS ; READ IN THE RESULTS 4871 000024EB 720C <1> JC short J34 4872 000024ED A0[2D6E0000] <1> MOV AL,[NEC_STATUS] ; GET THE FIRST STATUS BYTE 4873 000024F2 2460 <1> AND AL,01100000B ; ISOLATE THE BITS 4874 000024F4 3C60 <1> CMP AL,01100000B ; TEST FOR CORRECT VALUE 4875 000024F6 7403 <1> JZ short J35 ; IF ERROR, GO MARK IT 4876 000024F8 F8 <1> CLC ; GOOD RETURN 4877 <1> J34: 4878 000024F9 58 <1> POP eAX ; THROW AWAY ERROR RETURN 4879 <1> CS_BACK: 4880 000024FA C3 <1> RETn 4881 <1> J35: 4882 000024FB 800D[2C6E0000]40 <1> OR byte [DSKETTE_STATUS], BAD_SEEK 4883 00002502 F9 <1> STC ; ERROR RETURN CODE 4884 00002503 EBF4 <1> JMP SHORT J34 4885 <1> 4886 <1> ;------------------------------------------------------------------------------- 4887 <1> ; WAIT_INT 4888 <1> ; THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE 4889 <1> ; TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED 4890 <1> ; IF THE DRIVE IS NOT READY. 4891 <1> ; 4892 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4893 <1> ;------------------------------------------------------------------------------- 4894 <1> 4895 <1> ; 17/12/2014 4896 <1> ; 2.5 seconds waiting ! 4897 <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI) 4898 <1> ; amount of time to wait for completion interrupt from NEC. 4899 <1> 4900 <1> 4901 <1> WAIT_INT: 4902 00002505 FB <1> STI ; TURN ON INTERRUPTS, JUST IN CASE 4903 00002506 F8 <1> CLC ; CLEAR TIMEOUT INDICATOR 4904 <1> ;MOV BL,10 ; CLEAR THE COUNTERS 4905 <1> ;XOR CX,CX ; FOR 2 SECOND WAIT 4906 <1> 4907 <1> ; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT 4908 <1> ; 4909 <1> ;WAIT_FOR_MEM: 4910 <1> ; Waits for a bit at a specified memory location pointed 4911 <1> ; to by ES:[DI] to become set. 4912 <1> ;INPUT: 4913 <1> ; AH=Mask to test with. 4914 <1> ; ES:[DI] = memory location to watch. 4915 <1> ; BH:CX=Number of memory refresh periods to delay. 4916 <1> ; (normally 30 microseconds per period.) 4917 <1> 4918 <1> ; waiting for (max.) 2.5 secs in 30 micro units. 4919 <1> ; mov cx, WAIT_FDU_INT_LO ; 017798 4920 <1> ;; mov bl, WAIT_FDU_INT_HI 4921 <1> ; mov bl, WAIT_FDU_INT_HI + 1 4922 <1> ; 27/02/2015 4923 00002507 B986450100 <1> mov ecx, WAIT_FDU_INT_LH ; 83334 (2.5 seconds) 4924 <1> WFMS_CHECK_MEM: 4925 0000250C F605[296E0000]80 <1> test byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING 4926 00002513 7516 <1> jnz short J37 4927 <1> WFMS_HI: 4928 00002515 E461 <1> IN AL,PORT_B ; 061h ; SYS1, wait for lo to hi 4929 00002517 A810 <1> TEST AL,010H ; transition on memory 4930 00002519 75FA <1> JNZ SHORT WFMS_HI ; refresh. 4931 <1> WFMS_LO: 4932 0000251B E461 <1> IN AL,PORT_B ;SYS1 4933 0000251D A810 <1> TEST AL,010H 4934 0000251F 74FA <1> JZ SHORT WFMS_LO 4935 00002521 E2E9 <1> LOOP WFMS_CHECK_MEM 4936 <1> ;WFMS_OUTER_LP: 4937 <1> ;; or bl, bl ; check outer counter 4938 <1> ;; jz short J36A ; WFMS_TIMEOUT 4939 <1> ; dec bl 4940 <1> ; jz short J36A 4941 <1> ; jmp short WFMS_CHECK_MEM 4942 <1> 4943 <1> ;17/12/2014 4944 <1> ;16/12/2014 4945 <1> ; mov byte [wait_count], 0 ; Reset (INT 08H) counter 4946 <1> ;J36: 4947 <1> ; TEST byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING 4948 <1> ; JNZ short J37 4949 <1> ;16/12/2014 4950 <1> ;LOOP J36 ; COUNT DOWN WHILE WAITING 4951 <1> ;DEC BL ; SECOND LEVEL COUNTER 4952 <1> ;JNZ short J36 4953 <1> ; cmp byte [wait_count], 46 ; (46/18.2 seconds) 4954 <1> ; jb short J36 4955 <1> 4956 <1> ;WFMS_TIMEOUT: 4957 <1> ;J36A: 4958 00002523 800D[2C6E0000]80 <1> OR byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED 4959 0000252A F9 <1> STC ; ERROR RETURN 4960 <1> J37: 4961 0000252B 9C <1> PUSHF ; SAVE CURRENT CARRY 4962 0000252C 8025[296E0000]7F <1> AND byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG 4963 00002533 9D <1> POPF ; RECOVER CARRY 4964 00002534 C3 <1> RETn ; GOOD RETURN CODE 4965 <1> 4966 <1> ;------------------------------------------------------------------------------- 4967 <1> ; RESULTS 4968 <1> ; THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 4969 <1> ; FOLLOWING AN INTERRUPT. 4970 <1> ; 4971 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4972 <1> ; AX,BX,CX,DX DESTROYED 4973 <1> ;------------------------------------------------------------------------------- 4974 <1> RESULTS: 4975 00002535 57 <1> PUSH eDI 4976 00002536 BF[2D6E0000] <1> MOV eDI, NEC_STATUS ; POINTER TO DATA AREA 4977 0000253B B307 <1> MOV BL,7 ; MAX STATUS BYTES 4978 0000253D 66BAF403 <1> MOV DX,03F4H ; STATUS PORT 4979 <1> 4980 <1> ;----- WAIT FOR REQUEST FOR MASTER 4981 <1> 4982 <1> _R10: 4983 <1> ; 16/12/2014 4984 <1> ; wait for (max) 0.5 seconds 4985 <1> ;MOV BH,2 ; HIGH ORDER COUNTER 4986 <1> ;XOR CX,CX ; COUNTER 4987 <1> 4988 <1> ;Time to wait while waiting for each byte of NEC results = .5 4989 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 4990 <1> ; 27/02/2015 4991 00002541 B91B410000 <1> mov ecx, WAIT_FDU_RESULTS_LH ; 16667 4992 <1> ;mov cx, WAIT_FDU_RESULTS_LO ; 16667 4993 <1> ;mov bh, WAIT_FDU_RESULTS_HI+1 ; 0+1 4994 <1> 4995 <1> WFPSR_OUTER_LP: 4996 <1> ; 4997 <1> WFPSR_CHECK_PORT: 4998 <1> J39: ; WAIT FOR MASTER 4999 00002546 EC <1> IN AL,DX ; GET STATUS 5000 00002547 24C0 <1> AND AL,11000000B ; KEEP ONLY STATUS AND DIRECTION 5001 00002549 3CC0 <1> CMP AL,11000000B ; STATUS 1 AND DIRECTION 1 ? 5002 0000254B 7418 <1> JZ short J42 ; STATUS AND DIRECTION OK 5003 <1> WFPSR_HI: 5004 0000254D E461 <1> IN AL, PORT_B ;061h ; SYS1 ; wait for hi to lo 5005 0000254F A810 <1> TEST AL,010H ; transition on memory 5006 00002551 75FA <1> JNZ SHORT WFPSR_HI ; refresh. 5007 <1> WFPSR_LO: 5008 00002553 E461 <1> IN AL, PORT_B ; SYS1 5009 00002555 A810 <1> TEST AL,010H 5010 00002557 74FA <1> JZ SHORT WFPSR_LO 5011 00002559 E2EB <1> LOOP WFPSR_CHECK_PORT 5012 <1> ;; 27/02/2015 5013 <1> ;;dec bh 5014 <1> ;;jnz short WFPSR_OUTER_LP 5015 <1> ;jmp short WFPSR_TIMEOUT ; fail 5016 <1> 5017 <1> ;;mov byte [wait_count], 0 5018 <1> ;J39: ; WAIT FOR MASTER 5019 <1> ; IN AL,DX ; GET STATUS 5020 <1> ; AND AL,11000000B ; KEEP ONLY STATUS AND DIRECTION 5021 <1> ; CMP AL,11000000B ; STATUS 1 AND DIRECTION 1 ? 5022 <1> ; JZ short J42 ; STATUS AND DIRECTION OK 5023 <1> ;LOOP J39 ; LOOP TILL TIMEOUT 5024 <1> ;DEC BH ; DECREMENT HIGH ORDER COUNTER 5025 <1> ;JNZ short J39 ; REPEAT TILL DELAY DONE 5026 <1> ; 5027 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 5028 <1> ;;jb short J39 5029 <1> 5030 <1> ;WFPSR_TIMEOUT: 5031 0000255B 800D[2C6E0000]80 <1> OR byte [DSKETTE_STATUS],TIME_OUT 5032 00002562 F9 <1> STC ; SET ERROR RETURN 5033 00002563 EB29 <1> JMP SHORT POPRES ; POP REGISTERS AND RETURN 5034 <1> 5035 <1> ;----- READ IN THE STATUS 5036 <1> 5037 <1> J42: 5038 00002565 EB00 <1> JMP $+2 ; I/O DELAY 5039 00002567 6642 <1> INC DX ; POINT AT DATA PORT 5040 00002569 EC <1> IN AL,DX ; GET THE DATA 5041 <1> ; 16/12/2014 5042 <1> NEWIODELAY 2138 0000256A E6EB <2> out 0EBh,al 5043 0000256C 8807 <1> MOV [eDI],AL ; STORE THE BYTE 5044 0000256E 47 <1> INC eDI ; INCREMENT THE POINTER 5045 <1> ; 16/12/2014 5046 <1> ; push cx 5047 <1> ; mov cx, 30 5048 <1> ;wdw2: 5049 <1> ; NEWIODELAY 5050 <1> ; loop wdw2 5051 <1> ; pop cx 5052 <1> 5053 0000256F B903000000 <1> MOV eCX,3 ; MINIMUM 24 MICROSECONDS FOR NEC 5054 00002574 E852EFFFFF <1> CALL WAITF ; WAIT 30 TO 45 MICROSECONDS 5055 00002579 664A <1> DEC DX ; POINT AT STATUS PORT 5056 0000257B EC <1> IN AL,DX ; GET STATUS 5057 <1> ; 16/12/2014 5058 <1> NEWIODELAY 2138 0000257C E6EB <2> out 0EBh,al 5059 <1> ; 5060 0000257E A810 <1> TEST AL,00010000B ; TEST FOR NEC STILL BUSY 5061 00002580 740C <1> JZ short POPRES ; RESULTS DONE ? 5062 <1> 5063 00002582 FECB <1> DEC BL ; DECREMENT THE STATUS COUNTER 5064 00002584 75BB <1> JNZ short _R10 ; GO BACK FOR MORE 5065 00002586 800D[2C6E0000]20 <1> OR byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES 5066 0000258D F9 <1> STC ; SET ERROR FLAG 5067 <1> 5068 <1> ;----- RESULT OPERATION IS DONE 5069 <1> POPRES: 5070 0000258E 5F <1> POP eDI 5071 0000258F C3 <1> RETn ; RETURN WITH CARRY SET 5072 <1> 5073 <1> ;------------------------------------------------------------------------------- 5074 <1> ; READ_DSKCHNG 5075 <1> ; READS THE STATE OF THE DISK CHANGE LINE. 5076 <1> ; 5077 <1> ; ON ENTRY: DI = DRIVE # 5078 <1> ; 5079 <1> ; ON EXIT: DI = DRIVE # 5080 <1> ; ZF = 0 : DISK CHANGE LINE INACTIVE 5081 <1> ; ZF = 1 : DISK CHANGE LINE ACTIVE 5082 <1> ; AX,CX,DX DESTROYED 5083 <1> ;------------------------------------------------------------------------------- 5084 <1> READ_DSKCHNG: 5085 00002590 E8A5FDFFFF <1> CALL MOTOR_ON ; TURN ON THE MOTOR IF OFF 5086 00002595 66BAF703 <1> MOV DX,03F7H ; ADDRESS DIGITAL INPUT REGISTER 5087 00002599 EC <1> IN AL,DX ; INPUT DIGITAL INPUT REGISTER 5088 0000259A A880 <1> TEST AL,DSK_CHG ; CHECK FOR DISK CHANGE LINE ACTIVE 5089 0000259C C3 <1> RETn ; RETURN TO CALLER WITH ZERO FLAG SET 5090 <1> 5091 <1> ;------------------------------------------------------------------------------- 5092 <1> ; DRIVE_DET 5093 <1> ; DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND 5094 <1> ; UPDATES STATE INFORMATION ACCORDINGLY. 5095 <1> ; ON ENTRY: DI = DRIVE # 5096 <1> ;------------------------------------------------------------------------------- 5097 <1> DRIVE_DET: 5098 0000259D E898FDFFFF <1> CALL MOTOR_ON ; TURN ON MOTOR IF NOT ALREADY ON 5099 000025A2 E80CFFFFFF <1> CALL RECAL ; RECALIBRATE DRIVE 5100 000025A7 724F <1> JC short DD_BAC ; ASSUME NO DRIVE PRESENT 5101 000025A9 B530 <1> MOV CH,TRK_SLAP ; SEEK TO TRACK 48 5102 000025AB E884FEFFFF <1> CALL SEEK 5103 000025B0 7246 <1> JC short DD_BAC ; ERROR NO DRIVE 5104 000025B2 B50B <1> MOV CH,QUIET_SEEK+1 ; SEEK TO TRACK 10 5105 <1> SK_GIN: 5106 000025B4 FECD <1> DEC CH ; DECREMENT TO NEXT TRACK 5107 <1> ;PUSH CX ; SAVE TRACK 5108 <1> ; 05/12/2021 5109 000025B6 51 <1> push ecx 5110 000025B7 E878FEFFFF <1> CALL SEEK 5111 000025BC 723B <1> JC short POP_BAC ; POP AND RETURN 5112 000025BE B8[F9250000] <1> MOV eAX, POP_BAC ; LOAD NEC OUTPUT ERROR ADDRESS 5113 000025C3 50 <1> PUSH eAX 5114 000025C4 B404 <1> MOV AH,SENSE_DRV_ST ; SENSE DRIVE STATUS COMMAND BYTE 5115 000025C6 E830FEFFFF <1> CALL NEC_OUTPUT ; OUTPUT TO NEC 5116 000025CB 6689F8 <1> MOV AX,DI ; AL = DRIVE 5117 000025CE 88C4 <1> MOV AH,AL ; AH = DRIVE 5118 000025D0 E826FEFFFF <1> CALL NEC_OUTPUT ; OUTPUT TO NEC 5119 000025D5 E85BFFFFFF <1> CALL RESULTS ; GO GET STATUS 5120 000025DA 58 <1> POP eAX ; THROW AWAY ERROR ADDRESS 5121 <1> ;POP CX ; RESTORE TRACK 5122 <1> ; 05/12/2021 5123 000025DB 59 <1> pop ecx 5124 000025DC F605[2D6E0000]10 <1> TEST byte [NEC_STATUS], HOME ; TRACK 0 ? 5125 000025E3 74CF <1> JZ short SK_GIN ; GO TILL TRACK 0 5126 000025E5 08ED <1> OR CH,CH ; IS HOME AT TRACK 0 5127 000025E7 7408 <1> JZ short IS_80 ; MUST BE 80 TRACK DRIVE 5128 <1> 5129 <1> ; DRIVE IS A 360; SET DRIVE TO DETERMINED; 5130 <1> ; SET MEDIA TO DETERMINED AT RATE 250. 5131 <1> 5132 000025E9 808F[396E0000]94 <1> OR byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250 5133 000025F0 C3 <1> RETn ; ALL INFORMATION SET 5134 <1> IS_80: 5135 000025F1 808F[396E0000]01 <1> OR byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY 5136 <1> DD_BAC: 5137 000025F8 C3 <1> RETn 5138 <1> POP_BAC: 5139 <1> ;POP CX ; THROW AWAY 5140 <1> ; 05/12/2021 5141 000025F9 59 <1> pop ecx 5142 000025FA C3 <1> RETn 5143 <1> 5144 <1> fdc_int: 5145 <1> ; 30/07/2015 5146 <1> ; 16/02/2015 5147 <1> ;int_0Eh: ; 11/12/2014 5148 <1> 5149 <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL 6 ) -------------------------------------- 5150 <1> ; DISK_INT 5151 <1> ; THIS ROUTINE HANDLES THE DISKETTE INTERRUPT. 5152 <1> ; 5153 <1> ; ON EXIT: THE INTERRUPT FLAG IS SET IN @SEEK_STATUS. 5154 <1> ;------------------------------------------------------------------------------- 5155 <1> DISK_INT_1: 5156 <1> 5157 <1> ;PUSH AX ; SAVE WORK REGISTER 5158 <1> ; 05/12/2021 5159 000025FB 50 <1> push eax 5160 000025FC 1E <1> push ds 5161 000025FD 66B81000 <1> mov ax, KDATA 5162 00002601 8ED8 <1> mov ds, ax 5163 00002603 800D[296E0000]80 <1> OR byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED 5164 0000260A B020 <1> MOV AL,EOI ; END OF INTERRUPT MARKER 5165 0000260C E620 <1> OUT INTA00,AL ; INTERRUPT CONTROL PORT 5166 0000260E 1F <1> pop ds 5167 <1> ;POP AX ; RECOVER REGISTER 5168 <1> ; 05/12/2021 5169 0000260F 58 <1> pop eax 5170 00002610 CF <1> IRETd ; RETURN FROM INTERRUPT 5171 <1> 5172 <1> ;------------------------------------------------------------------------------- 5173 <1> ; DSKETTE_SETUP 5174 <1> ; THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF 5175 <1> ; DISKETTE DRIVES ARE ATTACH TO THE SYSTEM. 5176 <1> ;------------------------------------------------------------------------------- 5177 <1> DSKETTE_SETUP: 5178 <1> ;PUSH AX ; SAVE REGISTERS 5179 <1> ;PUSH BX 5180 <1> ;PUSH CX 5181 00002611 52 <1> PUSH eDX 5182 <1> ;PUSH DI 5183 <1> ;;PUSH DS 5184 <1> ; 14/12/2014 5185 <1> ;mov word [DISK_POINTER], MD_TBL6 5186 <1> ;mov [DISK_POINTER+2], cs 5187 <1> ; 5188 <1> ;OR byte [RTC_WAIT_FLAG], 1 ; NO RTC WAIT, FORCE USE OF LOOP 5189 00002612 31FF <1> XOR eDI,eDI ; INITIALIZE DRIVE POINTER 5190 00002614 66C705[396E0000]00- <1> MOV WORD [DSK_STATE],0 ; INITIALIZE STATES 5190 0000261C 00 <1> 5191 0000261D 8025[346E0000]33 <1> AND byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND 5192 00002624 800D[346E0000]C0 <1> OR byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE 5193 0000262B C605[296E0000]00 <1> MOV byte [SEEK_STATUS],0 ; INDICATE RECALIBRATE NEEDED 5194 00002632 C605[2B6E0000]00 <1> MOV byte [MOTOR_COUNT],0 ; INITIALIZE MOTOR COUNT 5195 00002639 C605[2A6E0000]00 <1> MOV byte [MOTOR_STATUS],0 ; INITIALIZE DRIVES TO OFF STATE 5196 00002640 C605[2C6E0000]00 <1> MOV byte [DSKETTE_STATUS],0 ; NO ERRORS 5197 <1> ; 5198 <1> ; 28/02/2015 5199 <1> ;mov word [cfd], 100h 5200 00002647 E89DF2FFFF <1> call DSK_RESET 5201 0000264C 5A <1> pop edx 5202 0000264D C3 <1> retn 5203 <1> 5204 <1> ;SUP0: 5205 <1> ; CALL DRIVE_DET ; DETERMINE DRIVE 5206 <1> ; CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 5207 <1> ; ; 02/01/2015 5208 <1> ; ;INC DI ; POINT TO NEXT DRIVE 5209 <1> ; ;CMP DI,MAX_DRV ; SEE IF DONE 5210 <1> ; ;JNZ short SUP0 ; REPEAT FOR EACH ORIVE 5211 <1> ; cmp byte [fd1_type], 0 5212 <1> ; jna short sup1 5213 <1> ; or di, di 5214 <1> ; jnz short sup1 5215 <1> ; inc di 5216 <1> ; jmp short SUP0 5217 <1> ;sup1: 5218 <1> ; MOV byte [SEEK_STATUS],0 ; FORCE RECALIBRATE 5219 <1> ; ;AND byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT 5220 <1> ; CALL SETUP_END ; VARIOUS CLEANUPS 5221 <1> ; ;;POP DS ; RESTORE CALLERS REGISTERS 5222 <1> ; ;POP DI 5223 <1> ; POP eDX 5224 <1> ; ;POP CX 5225 <1> ; ;POP BX 5226 <1> ; ;POP AX 5227 <1> ; RETn 5228 <1> 5229 <1> ;////////////////////////////////////////////////////// 5230 <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5231 <1> ; 5232 <1> 5233 <1> int13h: ; 21/02/2015 5234 0000264E 9C <1> pushfd 5235 0000264F 0E <1> push cs 5236 00002650 E858000000 <1> call DISK_IO 5237 00002655 C3 <1> retn 5238 <1> 5239 <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;; 5240 <1> ;///////////////////////////////////////////////////////////////////// 5241 <1> 5242 <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project) 5243 <1> ; 23/02/2015 5244 <1> ; 21/02/2015 (unix386.s) 5245 <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s) 5246 <1> ; 5247 <1> ; Original Source Code: 5248 <1> ; DISK ----- 09/25/85 FIXED DISK BIOS 5249 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 5250 <1> ; 5251 <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 5252 <1> ; Source Code - ATORGS.ASM, AHDSK.ASM 5253 <1> ; 5254 <1> 5255 <1> ;The wait for controller to be not busy is 10 seconds. 5256 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 5257 <1> ;;WAIT_HDU_CTLR_BUSY_LO equ 1615h 5258 <1> ;;WAIT_HDU_CTLR_BUSY_HI equ 05h 5259 <1> WAIT_HDU_CTRL_BUSY_LH equ 51615h ;21/02/2015 5260 <1> 5261 <1> ;The wait for controller to issue completion interrupt is 10 seconds. 5262 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 5263 <1> ;;WAIT_HDU_INT_LO equ 1615h 5264 <1> ;;WAIT_HDU_INT_HI equ 05h 5265 <1> WAIT_HDU_INT_LH equ 51615h ; 21/02/2015 5266 <1> 5267 <1> ;The wait for Data request on read and write longs is 5268 <1> ;2000 us. (?) 5269 <1> ;;WAIT_HDU_DRQ_LO equ 1000 ; 03E8h 5270 <1> ;;WAIT_HDU_DRQ_HI equ 0 5271 <1> WAIT_HDU_DRQ_LH equ 1000 ; 21/02/2015 5272 <1> 5273 <1> ; Port 61h (PORT_B) 5274 <1> SYS1 equ 61h ; PORT_B (diskette.inc) 5275 <1> 5276 <1> ; 23/12/2014 5277 <1> %define CMD_BLOCK eBP-8 ; 21/02/2015 5278 <1> 5279 <1> ;--- INT 13H ------------------------------------------------------------------- 5280 <1> ; : 5281 <1> ; FIXED DISK I/O INTERFACE : 5282 <1> ; : 5283 <1> ; THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH : 5284 <1> ; THE IBM FIXED DISK CONTROLLER. : 5285 <1> ; : 5286 <1> ; THE BIOS ROUTINES ARE MEANT TO BE ACCESSED THROUGH : 5287 <1> ; SOFTWARE INTERRUPTS ONLY. ANY ADDRESSES PRESENT IN : 5288 <1> ; THESE LISTINGS ARE INCLUDED ONLY FOR COMPLETENESS, : 5289 <1> ; NOT FOR REFERENCE. APPLICATIONS WHICH REFERENCE ANY : 5290 <1> ; ABSOLUTE ADDRESSES WITHIN THE CODE SEGMENTS OF BIOS : 5291 <1> ; VIOLATE THE STRUCTURE AND DESIGN OF BIOS. : 5292 <1> ; : 5293 <1> ;------------------------------------------------------------------------------: 5294 <1> ; : 5295 <1> ; INPUT (AH)= HEX COMMAND VALUE : 5296 <1> ; : 5297 <1> ; (AH)= 00H RESET DISK (DL = 80H,81H) / DISKETTE : 5298 <1> ; (AH)= 01H READ THE STATUS OF THE LAST DISK OPERATION INTO (AL) : 5299 <1> ; NOTE: DL < 80H - DISKETTE : 5300 <1> ; DL > 80H - DISK : 5301 <1> ; (AH)= 02H READ THE DESIRED SECTORS INTO MEMORY : 5302 <1> ; (AH)= 03H WRITE THE DESIRED SECTORS FROM MEMORY : 5303 <1> ; (AH)= 04H VERIFY THE DESIRED SECTORS : 5304 <1> ; (AH)= 05H FORMAT THE DESIRED TRACK : 5305 <1> ; (AH)= 06H UNUSED : 5306 <1> ; (AH)= 07H UNUSED : 5307 <1> ; (AH)= 08H RETURN THE CURRENT DRIVE PARAMETERS : 5308 <1> ; (AH)= 09H INITIALIZE DRIVE PAIR CHARACTERISTICS : 5309 <1> ; INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0 : 5310 <1> ; INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1 : 5311 <1> ; (AH)= 0AH READ LONG : 5312 <1> ; (AH)= 0BH WRITE LONG (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) : 5313 <1> ; (AH)= 0CH SEEK : 5314 <1> ; (AH)= 0DH ALTERNATE DISK RESET (SEE DL) : 5315 <1> ; (AH)= 0EH UNUSED : 5316 <1> ; (AH)= 0FH UNUSED : 5317 <1> ; (AH)= 10H TEST DRIVE READY : 5318 <1> ; (AH)= 11H RECALIBRATE : 5319 <1> ; (AH)= 12H UNUSED : 5320 <1> ; (AH)= 13H UNUSED : 5321 <1> ; (AH)= 14H CONTROLLER INTERNAL DIAGNOSTIC : 5322 <1> ; (AH)= 15H READ DASD TYPE : 5323 <1> ; : 5324 <1> ;------------------------------------------------------------------------------- 5325 <1> ; : 5326 <1> ; REGISTERS USED FOR FIXED DISK OPERATIONS : 5327 <1> ; : 5328 <1> ; (DL) - DRIVE NUMBER (80H-81H FOR DISK. VALUE CHECKED) : 5329 <1> ; (DH) - HEAD NUMBER (0-15 ALLOWED, NOT VALUE CHECKED) : 5330 <1> ; (CH) - CYLINDER NUMBER (0-1023, NOT VALUE CHECKED)(SEE CL): 5331 <1> ; (CL) - SECTOR NUMBER (1-17, NOT VALUE CHECKED) : 5332 <1> ; : 5333 <1> ; NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED : 5334 <1> ; IN THE HIGH 2 BITS OF THE CL REGISTER : 5335 <1> ; (10 BITS TOTAL) : 5336 <1> ; : 5337 <1> ; (AL) - NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H, : 5338 <1> ; FOR READ/WRITE LONG 1-79H) : 5339 <1> ; : 5340 <1> ; (ES:BX) - ADDRESS OF BUFFER FOR READS AND WRITES, : 5341 <1> ; (NOT REQUIRED FOR VERIFY) : 5342 <1> ; : 5343 <1> ; FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST : 5344 <1> ; 2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.: 5345 <1> ; F = 00H FOR A GOOD SECTOR : 5346 <1> ; 80H FOR A BAD SECTOR : 5347 <1> ; N = SECTOR NUMBER : 5348 <1> ; FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK : 5349 <1> ; THE TABLE SHOULD BE: : 5350 <1> ; : 5351 <1> ; DB 00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH : 5352 <1> ; DB 00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH : 5353 <1> ; DB 00H,07H,00H,10H,00H,08H,00H,11H,00H,09H : 5354 <1> ; : 5355 <1> ;------------------------------------------------------------------------------- 5356 <1> 5357 <1> ;------------------------------------------------------------------------------- 5358 <1> ; OUTPUT : 5359 <1> ; AH = STATUS OF CURRENT OPERATION : 5360 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES BELOW : 5361 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) : 5362 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) : 5363 <1> ; : 5364 <1> ; NOTE: ERROR 11H INDICATES THAT THE DATA READ HAD A RECOVERABLE : 5365 <1> ; ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM. THE DATA : 5366 <1> ; IS PROBABLY GOOD, HOWEVER THE BIOS ROUTINE INDICATES AN : 5367 <1> ; ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE : 5368 <1> ; FOR ITSELF. THE ERROR MAY NOT RECUR IF THE DATA IS : 5369 <1> ; REWRITTEN. : 5370 <1> ; : 5371 <1> ; IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), : 5372 <1> ; INPUT: : 5373 <1> ; (DL) = DRIVE NUMBER : 5374 <1> ; OUTPUT: : 5375 <1> ; (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2) : 5376 <1> ; (CONTROLLER CARD ZERO TALLY ONLY) : 5377 <1> ; (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER : 5378 <1> ; (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER : 5379 <1> ; (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER : 5380 <1> ; AND CYLINDER NUMBER HIGH BITS : 5381 <1> ; : 5382 <1> ; IF READ DASD TYPE WAS REQUESTED, : 5383 <1> ; : 5384 <1> ; AH = 0 - NOT PRESENT : 5385 <1> ; 1 - DISKETTE - NO CHANGE LINE AVAILABLE : 5386 <1> ; 2 - DISKETTE - CHANGE LINE AVAILABLE : 5387 <1> ; 3 - FIXED DISK : 5388 <1> ; : 5389 <1> ; CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3 : 5390 <1> ; : 5391 <1> ; REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN : 5392 <1> ; INFORMATION. : 5393 <1> ; : 5394 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE : 5395 <1> ; ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION. : 5396 <1> ; : 5397 <1> ;------------------------------------------------------------------------------- 5398 <1> 5399 <1> SENSE_FAIL EQU 0FFH ; NOT IMPLEMENTED 5400 <1> NO_ERR EQU 0E0H ; STATUS ERROR/ERROR REGISTER=0 5401 <1> WRITE_FAULT EQU 0CCH ; WRITE FAULT ON SELECTED DRIVE 5402 <1> UNDEF_ERR EQU 0BBH ; UNDEFINED ERROR OCCURRED 5403 <1> NOT_RDY EQU 0AAH ; DRIVE NOT READY 5404 <1> TIME_OUT EQU 80H ; ATTACHMENT FAILED TO RESPOND 5405 <1> BAD_SEEK EQU 40H ; SEEK OPERATION FAILED 5406 <1> BAD_CNTLR EQU 20H ; CONTROLLER HAS FAILED 5407 <1> DATA_CORRECTED EQU 11H ; ECC CORRECTED DATA ERROR 5408 <1> BAD_ECC EQU 10H ; BAD ECC ON DISK READ 5409 <1> BAD_TRACK EQU 0BH ; NOT IMPLEMENTED 5410 <1> BAD_SECTOR EQU 0AH ; BAD SECTOR FLAG DETECTED 5411 <1> ;DMA_BOUNDARY EQU 09H ; DATA EXTENDS TOO FAR 5412 <1> INIT_FAIL EQU 07H ; DRIVE PARAMETER ACTIVITY FAILED 5413 <1> BAD_RESET EQU 05H ; RESET FAILED 5414 <1> ;RECORD_NOT_FND EQU 04H ; REQUESTED SECTOR NOT FOUND 5415 <1> ;BAD_ADDR_MARK EQU 02H ; ADDRESS MARK NOT FOUND 5416 <1> ;BAD_CMD EQU 01H ; BAD COMMAND PASSED TO DISK I/O 5417 <1> 5418 <1> ;-------------------------------------------------------- 5419 <1> ; : 5420 <1> ; FIXED DISK PARAMETER TABLE : 5421 <1> ; - THE TABLE IS COMPOSED OF A BLOCK DEFINED AS: : 5422 <1> ; : 5423 <1> ; +0 (1 WORD) - MAXIMUM NUMBER OF CYLINDERS : 5424 <1> ; +2 (1 BYTE) - MAXIMUM NUMBER OF HEADS : 5425 <1> ; +3 (1 WORD) - NOT USED/SEE PC-XT : 5426 <1> ; +5 (1 WORD) - STARTING WRITE PRECOMPENSATION CYL : 5427 <1> ; +7 (1 BYTE) - MAXIMUM ECC DATA BURST LENGTH : 5428 <1> ; +8 (1 BYTE) - CONTROL BYTE : 5429 <1> ; BIT 7 DISABLE RETRIES -OR- : 5430 <1> ; BIT 6 DISABLE RETRIES : 5431 <1> ; BIT 3 MORE THAN 8 HEADS : 5432 <1> ; +9 (3 BYTES)- NOT USED/SEE PC-XT : 5433 <1> ; +12 (1 WORD) - LANDING ZONE : 5434 <1> ; +14 (1 BYTE) - NUMBER OF SECTORS/TRACK : 5435 <1> ; +15 (1 BYTE) - RESERVED FOR FUTURE USE : 5436 <1> ; : 5437 <1> ; - TO DYNAMICALLY DEFINE A SET OF PARAMETERS : 5438 <1> ; BUILD A TABLE FOR UP TO 15 TYPES AND PLACE : 5439 <1> ; THE CORRESPONDING VECTOR INTO INTERRUPT 41 : 5440 <1> ; FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1. : 5441 <1> ; : 5442 <1> ;-------------------------------------------------------- 5443 <1> 5444 <1> ;-------------------------------------------------------- 5445 <1> ; : 5446 <1> ; HARDWARE SPECIFIC VALUES : 5447 <1> ; : 5448 <1> ; - CONTROLLER I/O PORT : 5449 <1> ; : 5450 <1> ; > WHEN READ FROM: : 5451 <1> ; HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU) : 5452 <1> ; HF_PORT+1 - GET ERROR REGISTER : 5453 <1> ; HF_PORT+2 - GET SECTOR COUNT : 5454 <1> ; HF_PORT+3 - GET SECTOR NUMBER : 5455 <1> ; HF_PORT+4 - GET CYLINDER LOW : 5456 <1> ; HF_PORT+5 - GET CYLINDER HIGH (2 BITS) : 5457 <1> ; HF_PORT+6 - GET SIZE/DRIVE/HEAD : 5458 <1> ; HF_PORT+7 - GET STATUS REGISTER : 5459 <1> ; : 5460 <1> ; > WHEN WRITTEN TO: : 5461 <1> ; HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) : 5462 <1> ; HF_PORT+1 - SET PRECOMPENSATION CYLINDER : 5463 <1> ; HF_PORT+2 - SET SECTOR COUNT : 5464 <1> ; HF_PORT+3 - SET SECTOR NUMBER : 5465 <1> ; HF_PORT+4 - SET CYLINDER LOW : 5466 <1> ; HF_PORT+5 - SET CYLINDER HIGH (2 BITS) : 5467 <1> ; HF_PORT+6 - SET SIZE/DRIVE/HEAD : 5468 <1> ; HF_PORT+7 - SET COMMAND REGISTER : 5469 <1> ; : 5470 <1> ;-------------------------------------------------------- 5471 <1> 5472 <1> ;HF_PORT EQU 01F0H ; DISK PORT 5473 <1> ;HF1_PORT equ 0170h 5474 <1> ;HF_REG_PORT EQU 03F6H 5475 <1> ;HF1_REG_PORT equ 0376h 5476 <1> 5477 <1> HDC1_BASEPORT equ 1F0h 5478 <1> HDC2_BASEPORT equ 170h 5479 <1> 5480 <1> align 2 5481 <1> 5482 <1> ;----- STATUS REGISTER 5483 <1> 5484 <1> ST_ERROR EQU 00000001B ; 5485 <1> ST_INDEX EQU 00000010B ; 5486 <1> ST_CORRCTD EQU 00000100B ; ECC CORRECTION SUCCESSFUL 5487 <1> ST_DRQ EQU 00001000B ; 5488 <1> ST_SEEK_COMPL EQU 00010000B ; SEEK COMPLETE 5489 <1> ST_WRT_FLT EQU 00100000B ; WRITE FAULT 5490 <1> ST_READY EQU 01000000B ; 5491 <1> ST_BUSY EQU 10000000B ; 5492 <1> 5493 <1> ;----- ERROR REGISTER 5494 <1> 5495 <1> ERR_DAM EQU 00000001B ; DATA ADDRESS MARK NOT FOUND 5496 <1> ERR_TRK_0 EQU 00000010B ; TRACK 0 NOT FOUND ON RECAL 5497 <1> ERR_ABORT EQU 00000100B ; ABORTED COMMAND 5498 <1> ; EQU 00001000B ; NOT USED 5499 <1> ERR_ID EQU 00010000B ; ID NOT FOUND 5500 <1> ; EQU 00100000B ; NOT USED 5501 <1> ERR_DATA_ECC EQU 01000000B 5502 <1> ERR_BAD_BLOCK EQU 10000000B 5503 <1> 5504 <1> 5505 <1> RECAL_CMD EQU 00010000B ; DRIVE RECAL (10H) 5506 <1> READ_CMD EQU 00100000B ; READ (20H) 5507 <1> WRITE_CMD EQU 00110000B ; WRITE (30H) 5508 <1> VERIFY_CMD EQU 01000000B ; VERIFY (40H) 5509 <1> FMTTRK_CMD EQU 01010000B ; FORMAT TRACK (50H) 5510 <1> INIT_CMD EQU 01100000B ; INITIALIZE (60H) 5511 <1> SEEK_CMD EQU 01110000B ; SEEK (70H) 5512 <1> DIAG_CMD EQU 10010000B ; DIAGNOSTIC (90H) 5513 <1> SET_PARM_CMD EQU 10010001B ; DRIVE PARMS (91H) 5514 <1> NO_RETRIES EQU 00000001B ; CHD MODIFIER (01H) 5515 <1> ECC_MODE EQU 00000010B ; CMD MODIFIER (02H) 5516 <1> BUFFER_MODE EQU 00001000B ; CMD MODIFIER (08H) 5517 <1> 5518 <1> ;MAX_FILE EQU 2 5519 <1> ;S_MAX_FILE EQU 2 5520 <1> MAX_FILE equ 4 ; 22/12/2014 5521 <1> S_MAX_FILE equ 4 ; 22/12/2014 5522 <1> 5523 <1> DELAY_1 EQU 25H ; DELAY FOR OPERATION COMPLETE 5524 <1> DELAY_2 EQU 0600H ; DELAY FOR READY 5525 <1> DELAY_3 EQU 0100H ; DELAY FOR DATA REQUEST 5526 <1> 5527 <1> HF_FAIL EQU 08H ; CMOS FLAG IN BYTE 0EH 5528 <1> 5529 <1> ;----- COMMAND BLOCK REFERENCE 5530 <1> 5531 <1> ;CMD_BLOCK EQU BP-8 ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS 5532 <1> ; (BP) POINTS TO COMMAND BLOCK TAIL 5533 <1> ; AS DEFINED BY THE "ENTER" PARMS 5534 <1> ; 19/12/2014 5535 <1> ORG_VECTOR equ 4*13h ; INT 13h vector 5536 <1> DISK_VECTOR equ 4*40h ; INT 40h vector (for floppy disks) 5537 <1> ;HDISK_INT equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 5538 <1> ;HDISK_INT1 equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 5539 <1> ;HDISK_INT2 equ 4*77h ; Secondary HDC - Hardware interrupt (IRQ15) 5540 <1> ;HF_TBL_VEC equ 4*41h ; Pointer to 1st fixed disk parameter table 5541 <1> ;HF1_TBL_VEC equ 4*46h ; Pointer to 2nd fixed disk parameter table 5542 <1> 5543 <1> align 2 5544 <1> 5545 <1> ;---------------------------------------------------------------- 5546 <1> ; FIXED DISK I/O SETUP : 5547 <1> ; : 5548 <1> ; - ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK : 5549 <1> ; - PERFORM POWER ON DIAGNOSTICS : 5550 <1> ; SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED : 5551 <1> ; : 5552 <1> ;---------------------------------------------------------------- 5553 <1> 5554 <1> DISK_SETUP: 5555 <1> ;CLI 5556 <1> ;;MOV AX,ABS0 ; GET ABSOLUTE SEGMENT 5557 <1> ;xor ax,ax 5558 <1> ;MOV DS,AX ; SET SEGMENT REGISTER 5559 <1> ;MOV AX, [ORG_VECTOR] ; GET DISKETTE VECTOR 5560 <1> ;MOV [DISK_VECTOR],AX ; INTO INT 40H 5561 <1> ;MOV AX, [ORG_VECTOR+2] 5562 <1> ;MOV [DISK_VECTOR+2],AX 5563 <1> ;MOV word [ORG_VECTOR],DISK_IO ; FIXED DISK HANDLER 5564 <1> ;MOV [ORG_VECTOR+2],CS 5565 <1> ; 1st controller (primary master, slave) - IRQ 14 5566 <1> ;;MOV word [HDISK_INT],HD_INT ; FIXED DISK INTERRUPT 5567 <1> ;mov word [HDISK_INT1],HD_INT ; 5568 <1> ;;MOV [HDISK_INT+2],CS 5569 <1> ;mov [HDISK_INT1+2],CS 5570 <1> ; 2nd controller (secondary master, slave) - IRQ 15 5571 <1> ;mov word [HDISK_INT2],HD1_INT ; 5572 <1> ;mov [HDISK_INT2+2],CS 5573 <1> ; 5574 <1> ;;MOV word [HF_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80 5575 <1> ;;MOV word [HF_TBL_VEC+2],DPT_SEGM 5576 <1> ;;MOV word [HF1_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81 5577 <1> ;;MOV word [HF1_TBL_VEC+2],DPT_SEGM 5578 <1> ;push cs 5579 <1> ;pop ds 5580 <1> ;mov word [HDPM_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80h 5581 <1> ;mov word [HDPM_TBL_VEC+2],DPT_SEGM 5582 00002656 C705[446E0000]0000- <1> mov dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT 5582 0000265E 0900 <1> 5583 <1> ;mov word [HDPS_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81h 5584 <1> ;mov word [HDPS_TBL_VEC+2],DPT_SEGM 5585 00002660 C705[486E0000]2000- <1> mov dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT 5585 00002668 0900 <1> 5586 <1> ;mov word [HDSM_TBL_VEC],HD2_DPT ; PARM TABLE DRIVE 82h 5587 <1> ;mov word [HDSM_TBL_VEC+2],DPT_SEGM 5588 0000266A C705[4C6E0000]4000- <1> mov dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT 5588 00002672 0900 <1> 5589 <1> ;mov word [HDSS_TBL_VEC],HD3_DPT ; PARM TABLE DRIVE 83h 5590 <1> ;mov word [HDSS_TBL_VEC+2],DPT_SEGM 5591 00002674 C705[506E0000]6000- <1> mov dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT 5591 0000267C 0900 <1> 5592 <1> ; 5593 <1> ;;IN AL,INTB01 ; TURN ON SECOND INTERRUPT CHIP 5594 <1> ;;;AND AL,0BFH 5595 <1> ;;and al, 3Fh ; enable IRQ 14 and IRQ 15 5596 <1> ;;;JMP $+2 5597 <1> ;;IODELAY 5598 <1> ;;OUT INTB01,AL 5599 <1> ;;IODELAY 5600 <1> ;;IN AL,INTA01 ; LET INTERRUPTS PASS THRU TO 5601 <1> ;;AND AL,0FBH ; SECOND CHIP 5602 <1> ;;;JMP $+2 5603 <1> ;;IODELAY 5604 <1> ;;OUT INTA01,AL 5605 <1> ; 5606 <1> ;STI 5607 <1> ;;PUSH DS ; MOVE ABS0 POINTER TO 5608 <1> ;;POP ES ; EXTRA SEGMENT POINTER 5609 <1> ;;;CALL DDS ; ESTABLISH DATA SEGMENT 5610 <1> ;;MOV byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 5611 <1> ;;MOV byte [HF_NUM],0 ; ZERO NUMBER OF FIXED DISKS 5612 <1> ;;MOV byte [CONTROL_BYTE],0 5613 <1> ;;MOV byte [PORT_OFF],0 ; ZERO CARD OFFSET 5614 <1> ; 20/12/2014 - private code by Erdogan Tan 5615 <1> ; (out of original PC-AT, PC-XT BIOS code) 5616 <1> ;mov si, hd0_type 5617 0000267E BE[A0680000] <1> mov esi, hd0_type 5618 <1> ;mov cx, 4 5619 00002683 B904000000 <1> mov ecx, 4 5620 <1> hde_l: 5621 00002688 AC <1> lodsb 5622 00002689 3C80 <1> cmp al, 80h ; 8?h = existing 5623 0000268B 7206 <1> jb short _L4 5624 0000268D FE05[406E0000] <1> inc byte [HF_NUM] ; + 1 hard (fixed) disk drives 5625 <1> _L4: ; 26/02/2015 5626 00002693 E2F3 <1> loop hde_l 5627 <1> ;_L4: ; 0 <= [HF_NUM] =< 4 5628 <1> ;L4: 5629 <1> ; 5630 <1> ;; 31/12/2014 - cancel controller diagnostics here 5631 <1> ;;;mov cx, 3 ; 26/12/2014 (Award BIOS 1999) 5632 <1> ;;mov cl, 3 5633 <1> ;; 5634 <1> ;;MOV DL,80H ; CHECK THE CONTROLLER 5635 <1> ;;hdc_dl: 5636 <1> ;;MOV AH,14H ; USE CONTROLLER DIAGNOSTIC COMMAND 5637 <1> ;;INT 13H ; CALL BIOS WITH DIAGNOSTIC COMMAND 5638 <1> ;;;JC short CTL_ERRX ; DISPLAY ERROR MESSAGE IF BAD RETURN 5639 <1> ;;;jc short POD_DONE ;22/12/2014 5640 <1> ;;jnc short hdc_reset0 5641 <1> ;;loop hdc_dl 5642 <1> ;;; 27/12/2014 5643 <1> ;;stc 5644 <1> ;;retn 5645 <1> ; 5646 <1> ;;hdc_reset0: 5647 <1> ; 18/01/2015 5648 00002695 8A0D[406E0000] <1> mov cl, [HF_NUM] 5649 0000269B 20C9 <1> and cl, cl 5650 0000269D 740D <1> jz short POD_DONE 5651 <1> ; 5652 0000269F B27F <1> mov dl, 7Fh 5653 <1> hdc_reset1: 5654 000026A1 FEC2 <1> inc dl 5655 <1> ;; 31/12/2015 5656 <1> ;;push dx 5657 <1> ;;push cx 5658 <1> ;;push ds 5659 <1> ;;sub ax, ax 5660 <1> ;;mov ds, ax 5661 <1> ;;MOV AX, [TIMER_LOW] ; GET START TIMER COUNTS 5662 <1> ;;pop ds 5663 <1> ;;MOV BX,AX 5664 <1> ;;ADD AX,6*182 ; 60 SECONDS* 18.2 5665 <1> ;;MOV CX,AX 5666 <1> ;;mov word [wait_count], 0 ; 22/12/2014 (reset wait counter) 5667 <1> ;; 5668 <1> ;; 31/12/2014 - cancel HD_RESET_1 5669 <1> ;;CALL HD_RESET_1 ; SET UP DRIVE 0, (1,2,3) 5670 <1> ;;pop cx 5671 <1> ;;pop dx 5672 <1> ;; 5673 <1> ; 18/01/2015 5674 000026A3 B40D <1> mov ah, 0Dh ; ALTERNATE RESET 5675 <1> ;int 13h 5676 000026A5 E8A4FFFFFF <1> call int13h 5677 000026AA E2F5 <1> loop hdc_reset1 5678 <1> POD_DONE: 5679 000026AC C3 <1> RETn 5680 <1> 5681 <1> ;;----- POD_ERROR 5682 <1> 5683 <1> ;;CTL_ERRX: 5684 <1> ; ;MOV SI,OFFSET F1782 ; CONTROLLER ERROR 5685 <1> ; ;CALL SET_FAIL ; DO NOT IPL FROM DISK 5686 <1> ; ;CALL E_MSG ; DISPLAY ERROR AND SET (BP) ERROR FLAG 5687 <1> ; ;JMP short POD_DONE 5688 <1> 5689 <1> ;;HD_RESET_1: 5690 <1> ;; ;PUSH BX ; SAVE TIMER LIMITS 5691 <1> ;; ;PUSH CX 5692 <1> ;;RES_1: MOV AH,09H ; SET DRIVE PARAMETERS 5693 <1> ;; INT 13H 5694 <1> ;; JC short RES_2 5695 <1> ;; MOV AH,11H ; RECALIBRATE DRIVE 5696 <1> ;; INT 13H 5697 <1> ;; JNC short RES_CK ; DRIVE OK 5698 <1> ;;RES_2: ;CALL POD_TCHK ; CHECK TIME OUT 5699 <1> ;; cmp word [wait_count], 6*182 ; waiting time (in timer ticks) 5700 <1> ;; ; (30 seconds) 5701 <1> ;; ;cmc 5702 <1> ;; ;JNC short RES_1 5703 <1> ;; jb short RES_1 5704 <1> ;;;RES_FL: ;MOV SI,OFFSET F1781 ; INDICATE DISK 1 FAILURE; 5705 <1> ;; ;TEST DL,1 5706 <1> ;; ;JNZ RES_E1 5707 <1> ;; ;MOV SI,OFFSET F1780 ; INDICATE DISK 0 FAILURE 5708 <1> ;; ;CALL SET_FAIL ; DO NOT TRY TO IPL DISK 0 5709 <1> ;; ;JMP SHORT RES_E1 5710 <1> ;;RES_ER: ; 22/12/2014 5711 <1> ;;RES_OK: 5712 <1> ;; ;POP CX ; RESTORE TIMER LIMITS 5713 <1> ;; ;POP BX 5714 <1> ;; RETn 5715 <1> ;; 5716 <1> ;;RES_RS: MOV AH,00H ; RESET THE DRIVE 5717 <1> ;; INT 13H 5718 <1> ;;RES_CK: MOV AH,08H ; GET MAX CYLINDER,HEAD,SECTOR 5719 <1> ;; MOV BL,DL ; SAVE DRIVE CODE 5720 <1> ;; INT 13H 5721 <1> ;; JC short RES_ER 5722 <1> ;; MOV [NEC_STATUS],CX ; SAVE MAX CYLINDER, SECTOR 5723 <1> ;; MOV DL,BL ; RESTORE DRIVE CODE 5724 <1> ;;RES_3: MOV AX,0401H ; VERIFY THE LAST SECTOR 5725 <1> ;; INT 13H 5726 <1> ;; JNC short RES_OK ; VERIFY OK 5727 <1> ;; CMP AH,BAD_SECTOR ; OK ALSO IF JUST ID READ 5728 <1> ;; JE short RES_OK 5729 <1> ;; CMP AH,DATA_CORRECTED 5730 <1> ;; JE short RES_OK 5731 <1> ;; CMP AH,BAD_ECC 5732 <1> ;; JE short RES_OK 5733 <1> ;; ;CALL POD_TCHK ; CHECK FOR TIME OUT 5734 <1> ;; cmp word [wait_count], 6*182 ; waiting time (in timer ticks) 5735 <1> ;; ; (60 seconds) 5736 <1> ;; cmc 5737 <1> ;; JC short RES_ER ; FAILED 5738 <1> ;; MOV CX,[NEC_STATUS] ; GET SECTOR ADDRESS, AND CYLINDER 5739 <1> ;; MOV AL,CL ; SEPARATE OUT SECTOR NUMBER 5740 <1> ;; AND AL,3FH 5741 <1> ;; DEC AL ; TRY PREVIOUS ONE 5742 <1> ;; JZ short RES_RS ; WE'VE TRIED ALL SECTORS ON TRACK 5743 <1> ;; AND CL,0C0H ; KEEP CYLINDER BITS 5744 <1> ;; OR CL,AL ; MERGE SECTOR WITH CYLINDER BITS 5745 <1> ;; MOV [NEC_STATUS],CX ; SAVE CYLINDER, NEW SECTOR NUMBER 5746 <1> ;; JMP short RES_3 ; TRY AGAIN 5747 <1> ;;;RES_ER: MOV SI,OFFSET F1791 ; INDICATE DISK 1 ERROR 5748 <1> ;; ;TEST DL,1 5749 <1> ;; ;JNZ short RES_E1 5750 <1> ;; ;MOV SI,OFFSET F1790 ; INDICATE DISK 0 ERROR 5751 <1> ;;;RES_E1: 5752 <1> ;; ;CALL E_MSG ; DISPLAY ERROR AND SET (BP) ERROR FLAG 5753 <1> ;;;RES_OK: 5754 <1> ;; ;POP CX ; RESTORE TIMER LIMITS 5755 <1> ;; ;POP BX 5756 <1> ;; ;RETn 5757 <1> ; 5758 <1> ;;SET_FAIL: 5759 <1> ; ;MOV AX,X*(CMOS_DIAG+NMI) ; GET CMOS ERROR BYTE 5760 <1> ; ;CALL CMOS_READ 5761 <1> ; ;OR AL,HF_FAIL ; SET DO NOT IPL FROM DISK FLAG 5762 <1> ; ;XCHG AH,AL ; SAVE IT 5763 <1> ; ;CALL CMOS_WRITE ; PUT IT OUT 5764 <1> ; ;RETn 5765 <1> ; 5766 <1> ;;POD_TCHK: ; CHECK FOR 30 SECOND TIME OUT 5767 <1> ; ;POP AX ; SAVE RETURN 5768 <1> ; ;POP CX ; GET TIME OUT LIMITS 5769 <1> ; ;POP BX 5770 <1> ; ;PUSH BX ; AND SAVE THEM AGAIN 5771 <1> ; ;PUSH CX 5772 <1> ; ;PUSH AX 5773 <1> ; ;push ds 5774 <1> ; ;xor ax, ax 5775 <1> ; ;mov ds, ax ; RESTORE RETURN 5776 <1> ; ;MOV AX, [TIMER_LOW] ; AX = CURRENT TIME 5777 <1> ; ; ; BX = START TIME 5778 <1> ; ; ; CX = END TIME 5779 <1> ; ;pop ds 5780 <1> ; ;CMP BX,CX 5781 <1> ; ;JB short TCHK1 ; START < END 5782 <1> ; ;CMP BX,AX 5783 <1> ; ;JB short TCHKG ; END < START < CURRENT 5784 <1> ; ;JMP SHORT TCHK2 ; END, CURRENT < START 5785 <1> ;;TCHK1: CMP AX,BX 5786 <1> ;; JB short TCHKNG ; CURRENT < START < END 5787 <1> ;;TCHK2: CMP AX,CX 5788 <1> ;; JB short TCHKG ; START < CURRENT < END 5789 <1> ;; ; OR CURRENT < END < START 5790 <1> ;;TCHKNG: STC ; CARRY SET INDICATES TIME OUT 5791 <1> ;; RETn 5792 <1> ;;TCHKG: CLC ; INDICATE STILL TIME 5793 <1> ;; RETn 5794 <1> ;; 5795 <1> ;;int_13h: 5796 <1> 5797 <1> ;---------------------------------------- 5798 <1> ; FIXED DISK BIOS ENTRY POINT : 5799 <1> ;---------------------------------------- 5800 <1> 5801 <1> DISK_IO: 5802 000026AD 80FA80 <1> CMP DL,80H ; TEST FOR FIXED DISK DRIVE 5803 <1> ;JAE short A1 ; YES, HANDLE HERE 5804 <1> ;;;INT 40H ; DISKETTE HANDLER 5805 <1> ;;call int40h 5806 <1> ;jb DISKETTE_IO_1 5807 <1> ; 05/12/2021 5808 000026B0 7305 <1> jnb short A1 5809 000026B2 E960F1FFFF <1> jmp DISKETTE_IO_1 5810 <1> ;RET_2: 5811 <1> ;RETf 2 ; BACK TO CALLER 5812 <1> ; retf 4 5813 <1> A1: 5814 000026B7 FB <1> STI ; ENABLE INTERRUPTS 5815 <1> ;; 04/01/2015 5816 <1> ;;OR AH,AH 5817 <1> ;;JNZ short A2 5818 <1> ;;INT 40H ; RESET NEC WHEN AH=0 5819 <1> ;;SUB AH,AH 5820 000026B8 80FA83 <1> CMP DL,(80H + S_MAX_FILE - 1) 5821 000026BB 772E <1> JA short RET_2 5822 <1> ; 18/01/2015 5823 000026BD 08E4 <1> or ah,ah 5824 000026BF 742D <1> jz short A4 5825 000026C1 80FC0D <1> cmp ah, 0Dh ; Alternate reset 5826 000026C4 7504 <1> jne short A2 5827 000026C6 28E4 <1> sub ah,ah ; Reset 5828 000026C8 EB24 <1> jmp short A4 5829 <1> A2: 5830 000026CA 80FC08 <1> CMP AH,08H ; GET PARAMETERS IS A SPECIAL CASE 5831 <1> ;JNZ short A3 5832 <1> ;JMP GET_PARM_N 5833 <1> ;je GET_PARM_N 5834 <1> ; 05/12/2021 5835 000026CD 7505 <1> jne short A3 5836 000026CF E90D030000 <1> jmp GET_PARM_N 5837 <1> A3: 5838 000026D4 80FC15 <1> CMP AH,15H ; READ DASD TYPE IS ALSO 5839 <1> ;JNZ short A4 5840 <1> ;JMP READ_DASD_TYPE 5841 <1> ;je READ_DASD_TYPE 5842 <1> ; 05/12/2021 5843 000026D7 7505 <1> jne short A3_A4 5844 000026D9 E9BA020000 <1> jmp READ_DASD_TYPE 5845 <1> A3_A4: 5846 <1> ; 02/02/2015 5847 000026DE 80FC1D <1> cmp ah, 1Dh ; (Temporary for Retro UNIX 386 v1) 5848 <1> ; 12/01/2015 5849 000026E1 F5 <1> cmc 5850 000026E2 730A <1> jnc short A4 5851 <1> ; 30/01/2015 5852 <1> ;mov byte [CS:DISK_STATUS1],BAD_CMD ; COMMAND ERROR 5853 000026E4 C605[3F6E0000]01 <1> mov byte [DISK_STATUS1], BAD_CMD 5854 <1> ;jmp short RET_2 5855 <1> RET_2: 5856 000026EB CA0400 <1> retf 4 5857 <1> A4: ; SAVE REGISTERS DURING OPERATION 5858 000026EE C8080000 <1> ENTER 8,0 ; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK 5859 000026F2 53 <1> PUSH eBX ; IN THE STACK, THE COMMAND BLOCK IS: 5860 000026F3 51 <1> PUSH eCX ; @CMD_BLOCK == BYTE PTR [BP]-8 5861 000026F4 52 <1> PUSH eDX 5862 000026F5 1E <1> PUSH DS 5863 000026F6 06 <1> PUSH ES 5864 000026F7 56 <1> PUSH eSI 5865 000026F8 57 <1> PUSH eDI 5866 <1> ;;04/01/2015 5867 <1> ;;OR AH,AH ; CHECK FOR RESET 5868 <1> ;;JNZ short A5 5869 <1> ;;MOV DL,80H ; FORCE DRIVE 80 FOR RESET 5870 <1> ;;A5: 5871 <1> ;push cs 5872 <1> ;pop ds 5873 <1> ; 21/02/2015 5874 <1> ;push ax 5875 <1> ; 05/12/2021 5876 000026F9 50 <1> push eax 5877 000026FA 66B81000 <1> mov ax, KDATA 5878 000026FE 8ED8 <1> mov ds, ax 5879 00002700 8EC0 <1> mov es, ax 5880 <1> ;pop ax 5881 <1> ; 05/12/2021 5882 00002702 58 <1> pop eax 5883 00002703 E889000000 <1> CALL DISK_IO_CONT ; PERFORM THE OPERATION 5884 <1> ;;CALL DDS ; ESTABLISH SEGMENT 5885 00002708 8A25[3F6E0000] <1> MOV AH,[DISK_STATUS1] ; GET STATUS FROM OPERATION 5886 0000270E 80FC01 <1> CMP AH,1 ; SET THE CARRY FLAG TO INDICATE 5887 00002711 F5 <1> CMC ; SUCCESS OR FAILURE 5888 00002712 5F <1> POP eDI ; RESTORE REGISTERS 5889 00002713 5E <1> POP eSI 5890 00002714 07 <1> POP ES 5891 00002715 1F <1> POP DS 5892 00002716 5A <1> POP eDX 5893 00002717 59 <1> POP eCX 5894 00002718 5B <1> POP eBX 5895 00002719 C9 <1> LEAVE ; ADJUST (SP) AND RESTORE (BP) 5896 <1> ;RETf 2 ; THROW AWAY SAVED FLAGS 5897 0000271A CA0400 <1> retf 4 5898 <1> ; 21/02/2015 5899 <1> ; dw --> dd 5900 <1> M1: ; FUNCTION TRANSFER TABLE 5901 0000271D [D6280000] <1> dd DISK_RESET ; 000H 5902 00002721 [4B290000] <1> dd RETURN_STATUS ; 001H 5903 00002725 [58290000] <1> dd DISK_READ ; 002H 5904 00002729 [61290000] <1> dd DISK_WRITE ; 003H 5905 0000272D [6A290000] <1> dd DISK_VERF ; 004H 5906 00002731 [82290000] <1> dd FMT_TRK ; 005H 5907 00002735 [CC280000] <1> dd BAD_COMMAND ; 006H FORMAT BAD SECTORS 5908 00002739 [CC280000] <1> dd BAD_COMMAND ; 007H FORMAT DRIVE 5909 0000273D [CC280000] <1> dd BAD_COMMAND ; 008H RETURN PARAMETERS 5910 00002741 [432A0000] <1> dd INIT_DRV ; 009H 5911 00002745 [A22A0000] <1> dd RD_LONG ; 00AH 5912 00002749 [AB2A0000] <1> dd WR_LONG ; 00BH 5913 0000274D [B42A0000] <1> dd DISK_SEEK ; 00CH 5914 00002751 [D6280000] <1> dd DISK_RESET ; 00DH 5915 00002755 [CC280000] <1> dd BAD_COMMAND ; 00EH READ BUFFER 5916 00002759 [CC280000] <1> dd BAD_COMMAND ; 00FH WRITE BUFFER 5917 0000275D [DC2A0000] <1> dd TST_RDY ; 010H 5918 00002761 [002B0000] <1> dd HDISK_RECAL ; 011H 5919 00002765 [CC280000] <1> dd BAD_COMMAND ; 012H MEMORY DIAGNOSTIC 5920 00002769 [CC280000] <1> dd BAD_COMMAND ; 013H DRIVE DIAGNOSTIC 5921 0000276D [362B0000] <1> dd CTLR_DIAGNOSTIC ; 014H CONTROLLER DIAGNOSTIC 5922 <1> ; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test) 5923 00002771 [CC280000] <1> dd BAD_COMMAND ; 015h 5924 00002775 [CC280000] <1> dd BAD_COMMAND ; 016h 5925 00002779 [CC280000] <1> dd BAD_COMMAND ; 017h 5926 0000277D [CC280000] <1> dd BAD_COMMAND ; 018h 5927 00002781 [CC280000] <1> dd BAD_COMMAND ; 019h 5928 00002785 [CC280000] <1> dd BAD_COMMAND ; 01Ah 5929 00002789 [58290000] <1> dd DISK_READ ; 01Bh ; LBA read 5930 0000278D [61290000] <1> dd DISK_WRITE ; 01Ch ; LBA write 5931 <1> M1L EQU $-M1 5932 <1> 5933 <1> DISK_IO_CONT: 5934 <1> ;;CALL DDS ; ESTABLISH SEGMENT 5935 00002791 80FC01 <1> CMP AH,01H ; RETURN STATUS 5936 <1> ;;JNZ short SU0 5937 <1> ;;JMP RETURN_STATUS 5938 <1> ;je RETURN_STATUS 5939 <1> ; 05/12/2021 5940 00002794 7505 <1> jne short SU0 5941 00002796 E9B0010000 <1> jmp RETURN_STATUS 5942 <1> SU0: 5943 0000279B C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 5944 <1> ;;PUSH BX ; SAVE DATA ADDRESS 5945 <1> ;mov si, bx ;; 14/02/2015 5946 000027A2 89DE <1> mov esi, ebx ; 21/02/2015 5947 000027A4 8A1D[406E0000] <1> MOV BL,[HF_NUM] ; GET NUMBER OF DRIVES 5948 <1> ;; 04/01/2015 5949 <1> ;;PUSH AX 5950 000027AA 80E27F <1> AND DL,7FH ; GET DRIVE AS 0 OR 1 5951 <1> ; (get drive number as 0 to 3) 5952 000027AD 38D3 <1> CMP BL,DL 5953 <1> ;;JBE BAD_COMMAND_POP ; INVALID DRIVE 5954 <1> ;jbe BAD_COMMAND ;; 14/02/2015 5955 <1> ; 05/12/2021 5956 000027AF 7705 <1> ja short su0_su1 5957 000027B1 E916010000 <1> jmp BAD_COMMAND 5958 <1> su0_su1: 5959 <1> ;;03/01/2015 5960 000027B6 29DB <1> sub ebx, ebx 5961 000027B8 88D3 <1> mov bl, dl 5962 <1> ;sub bh, bh 5963 000027BA 883D[546E0000] <1> mov [LBAMode], bh ; 0 5964 <1> ;;test byte [bx+hd0_type], 1 ; LBA ready ? 5965 <1> ;test byte [ebx+hd0_type], 1 5966 <1> ;jz short su1 ; no 5967 <1> ;inc byte [LBAMode] 5968 <1> ;su1: 5969 <1> ; 21/02/2015 (32 bit modification) 5970 <1> ; 04/01/2015 5971 <1> ;push ax ; *** 5972 <1> ; 05/12/2021 5973 000027C0 50 <1> push eax ; *** 5974 <1> ;PUSH ES ; ** 5975 <1> ;PUSH DX ; * 5976 <1> ; 05/12/2021 5977 000027C1 52 <1> push edx ; * 5978 <1> ;push ax 5979 000027C2 50 <1> push eax 5980 000027C3 E849060000 <1> CALL GET_VEC ; GET DISK PARAMETERS 5981 <1> ; 02/02/2015 5982 <1> ;mov ax, [ES:BX+16] ; I/O port base address (1F0h, 170h) 5983 000027C8 668B4310 <1> mov ax, [ebx+16] 5984 000027CC 66A3[94680000] <1> mov [HF_PORT], ax 5985 <1> ;mov dx, [ES:BX+18] ; control port address (3F6h, 376h) 5986 000027D2 668B5312 <1> mov dx, [ebx+18] 5987 000027D6 668915[96680000] <1> mov [HF_REG_PORT], dx 5988 <1> ;mov al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h) 5989 000027DD 8A4314 <1> mov al, [ebx+20] 5990 <1> ; 23/02/2015 5991 000027E0 A840 <1> test al, 40h ; LBA bit (bit 6) 5992 000027E2 7406 <1> jz short su1 5993 000027E4 FE05[546E0000] <1> inc byte [LBAMode] ; 1 5994 <1> su1: 5995 000027EA C0E804 <1> shr al, 4 5996 000027ED 2401 <1> and al, 1 5997 000027EF A2[98680000] <1> mov [hf_m_s], al 5998 <1> ; 5999 <1> ; 03/01/2015 6000 <1> ;MOV AL,byte [ES:BX+8] ; GET CONTROL BYTE MODIFIER 6001 000027F4 8A4308 <1> mov al, [ebx+8] 6002 <1> ;MOV DX,[HF_REG_PORT] ; Device Control register 6003 000027F7 EE <1> OUT DX,AL ; SET EXTRA HEAD OPTION 6004 <1> ; Control Byte: (= 08h, here) 6005 <1> ; bit 0 - 0 6006 <1> ; bit 1 - nIEN (1 = disable irq) 6007 <1> ; bit 2 - SRST (software RESET) 6008 <1> ; bit 3 - use extra heads (8 to 15) 6009 <1> ; -always set to 1- 6010 <1> ; (bits 3 to 7 are reserved 6011 <1> ; for ATA devices) 6012 000027F8 8A25[416E0000] <1> MOV AH,[CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 6013 000027FE 80E4C0 <1> AND AH,0C0H ; CONTROL BYTE 6014 00002801 08C4 <1> OR AH,AL 6015 00002803 8825[416E0000] <1> MOV [CONTROL_BYTE],AH 6016 <1> ; 04/01/2015 6017 <1> ;pop ax 6018 <1> ; 05/12/2021 6019 00002809 58 <1> pop eax 6020 <1> ;pop dx ; * ;; 14/02/2015 6021 <1> ; 05/12/2021 6022 0000280A 5A <1> pop edx ; * 6023 0000280B 20E4 <1> and ah, ah ; Reset function ? 6024 0000280D 7506 <1> jnz short su2 6025 <1> ;;pop dx ; * ;; 14/02/2015 6026 <1> ;pop es ; ** 6027 <1> ;pop ax ; *** 6028 <1> ; 05/12/2021 6029 0000280F 58 <1> pop eax ; *** 6030 <1> ;;pop bx 6031 00002810 E9C1000000 <1> jmp DISK_RESET 6032 <1> su2: 6033 00002815 803D[546E0000]00 <1> cmp byte [LBAMode], 0 6034 0000281C 765E <1> jna short su3 6035 <1> ; 6036 <1> ; 02/02/2015 (LBA read/write function calls) 6037 0000281E 80FC1B <1> cmp ah, 1Bh 6038 00002821 720B <1> jb short lbarw1 6039 00002823 80FC1C <1> cmp ah, 1Ch 6040 00002826 7759 <1> ja short invldfnc 6041 <1> ;;pop dx ; * ; 14/02/2015 6042 <1> ;mov ax, cx ; Lower word of LBA address (bits 0-15) 6043 00002828 89C8 <1> mov eax, ecx ; LBA address (21/02/2015) 6044 <1> ;; 14/02/2015 6045 0000282A 88D1 <1> mov cl, dl ; 14/02/2015 6046 <1> ;;mov dx, bx 6047 <1> ;mov dx, si ; higher word of LBA address (bits 16-23) 6048 <1> ;;mov bx, di 6049 <1> ;mov si, di ; Buffer offset 6050 0000282C EB2E <1> jmp short lbarw2 6051 <1> lbarw1: 6052 <1> ; convert CHS to LBA 6053 <1> ; 6054 <1> ; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM 6055 <1> ; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track 6056 <1> ; + Sector - 1 6057 <1> ;push dx ; * ;; 14/02/2015 6058 <1> ; 05/12/2021 6059 0000282E 52 <1> push edx ; * 6060 <1> ;xor dh, dh 6061 0000282F 31D2 <1> xor edx, edx 6062 <1> ;mov dl, [ES:BX+14] ; sectors per track (logical) 6063 00002831 8A530E <1> mov dl, [ebx+14] 6064 <1> ;xor ah, ah 6065 00002834 31C0 <1> xor eax, eax 6066 <1> ;mov al, [ES:BX+2] ; heads (logical) 6067 00002836 8A4302 <1> mov al, [ebx+2] 6068 00002839 FEC8 <1> dec al 6069 <1> ;inc ax ; 0 = 256 6070 0000283B 40 <1> inc eax ; 05/12/2021 6071 0000283C 66F7E2 <1> mul dx 6072 <1> ; AX = # of Heads" * Sectors/Track 6073 0000283F 6689CA <1> mov dx, cx 6074 <1> ;and cx, 3Fh ; sector (1 to 63) 6075 00002842 83E13F <1> and ecx, 3fh 6076 00002845 86D6 <1> xchg dl, dh 6077 00002847 C0EE06 <1> shr dh, 6 6078 <1> ; DX = cylinder (0 to 1023) 6079 <1> ;mul dx 6080 <1> ; DX:AX = # of Heads" * Sectors/Track * Cylinder 6081 0000284A F7E2 <1> mul edx 6082 0000284C FEC9 <1> dec cl ; sector - 1 6083 <1> ;add ax, cx 6084 <1> ;adc dx, 0 6085 <1> ; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1 6086 0000284E 01C8 <1> add eax, ecx 6087 <1> ;pop cx ; * ; ch = head, cl = drive number (zero based) 6088 <1> ; 05/12/2021 6089 00002850 59 <1> pop ecx ; * ; ch = head, cl = drive number (zero based) 6090 <1> ;push dx 6091 <1> ;push ax 6092 00002851 50 <1> push eax 6093 <1> ;mov al, [ES:BX+14] ; sectors per track (logical) 6094 00002852 8A430E <1> mov al, [ebx+14] 6095 00002855 F6E5 <1> mul ch 6096 <1> ; AX = Head * Sectors/Track 6097 00002857 6699 <1> cwd 6098 <1> ;pop dx 6099 00002859 5A <1> pop edx 6100 <1> ;add ax, dx 6101 <1> ;pop dx 6102 <1> ;adc dx, 0 ; add carry bit 6103 0000285A 01D0 <1> add eax, edx 6104 <1> lbarw2: 6105 0000285C 29D2 <1> sub edx, edx ; 21/02/2015 6106 0000285E 88CA <1> mov dl, cl ; 21/02/2015 6107 00002860 C645F800 <1> mov byte [CMD_BLOCK], 0 ; Features Register 6108 <1> ; NOTE: Features register (1F1h, 171h) 6109 <1> ; is not used for ATA device R/W functions. 6110 <1> ; It is old/obsolete 'write precompensation' 6111 <1> ; register and error register 6112 <1> ; for old ATA/IDE devices. 6113 <1> ; 18/01/2014 6114 <1> ;mov ch, [hf_m_s] ; Drive 0 (master) or 1 (slave) 6115 00002864 8A0D[98680000] <1> mov cl, [hf_m_s] 6116 <1> ;shl ch, 4 ; bit 4 (drive bit) 6117 <1> ;or ch, 0E0h ; bit 5 = 1 6118 <1> ; bit 6 = 1 = LBA mode 6119 <1> ; bit 7 = 1 6120 0000286A 80C90E <1> or cl, 0Eh ; 1110b 6121 <1> ;and dh, 0Fh ; LBA byte 4 (bits 24 to 27) 6122 0000286D 25FFFFFF0F <1> and eax, 0FFFFFFFh 6123 00002872 C1E11C <1> shl ecx, 28 ; 21/02/2015 6124 <1> ;or dh, ch 6125 00002875 09C8 <1> or eax, ecx 6126 <1> ;;mov [CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7) 6127 <1> ; (Sector Number Register) 6128 <1> ;;mov [CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15) 6129 <1> ; (Cylinder Low Register) 6130 <1> ;mov [CMD_BLOCK+2], ax ; LBA byte 1, 2 6131 <1> ;mov [CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23) 6132 <1> ; (Cylinder High Register) 6133 <1> ;;mov [CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27) 6134 <1> ; (Drive/Head Register) 6135 <1> 6136 <1> ;mov [CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits 6137 00002877 8945FA <1> mov [CMD_BLOCK+2], eax ; 21/02/2015 6138 <1> ;14/02/2015 6139 <1> ;mov dl, cl ; Drive number (INIT_DRV) 6140 0000287A EB37 <1> jmp short su4 6141 <1> su3: 6142 <1> ; 02/02/2015 6143 <1> ; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 6144 0000287C 80FC14 <1> cmp ah, 14h 6145 0000287F 7603 <1> jna short chsfnc 6146 <1> invldfnc: 6147 <1> ; 14/02/2015 6148 <1> ;pop es ; ** 6149 <1> ;pop ax ; *** 6150 <1> ; 05/12/2021 6151 00002881 58 <1> pop eax ; *** 6152 <1> ;jmp short BAD_COMMAND_POP 6153 00002882 EB48 <1> jmp short BAD_COMMAND 6154 <1> chsfnc: 6155 <1> ;MOV AX,[ES:BX+5] ; GET WRITE PRE-COMPENSATION CYLINDER 6156 00002884 668B4305 <1> mov ax, [ebx+5] 6157 00002888 66C1E802 <1> SHR AX,2 6158 0000288C 8845F8 <1> MOV [CMD_BLOCK],AL 6159 <1> ;;MOV AL,[ES:BX+8] ; GET CONTROL BYTE MODIFIER 6160 <1> ;;PUSH DX 6161 <1> ;;MOV DX,[HF_REG_PORT] 6162 <1> ;;OUT DX,AL ; SET EXTRA HEAD OPTION 6163 <1> ;;POP DX ; * 6164 <1> ;;POP ES ; ** 6165 <1> ;;MOV AH,[CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 6166 <1> ;;AND AH,0C0H ; CONTROL BYTE 6167 <1> ;;OR AH,AL 6168 <1> ;;MOV [CONTROL_BYTE],AH 6169 <1> ; 6170 0000288F 88C8 <1> MOV AL,CL ; GET SECTOR NUMBER 6171 00002891 243F <1> AND AL,3FH 6172 00002893 8845FA <1> MOV [CMD_BLOCK+2],AL 6173 00002896 886DFB <1> MOV [CMD_BLOCK+3],CH ; GET CYLINDER NUMBER 6174 00002899 88C8 <1> MOV AL,CL 6175 0000289B C0E806 <1> SHR AL,6 6176 0000289E 8845FC <1> MOV [CMD_BLOCK+4],AL ; CYLINDER HIGH ORDER 2 BITS 6177 <1> ;;05/01/2015 6178 <1> ;;MOV AL,DL ; DRIVE NUMBER 6179 000028A1 A0[98680000] <1> mov al, [hf_m_s] 6180 000028A6 C0E004 <1> SHL AL,4 6181 000028A9 80E60F <1> AND DH,0FH ; HEAD NUMBER 6182 000028AC 08F0 <1> OR AL,DH 6183 <1> ;OR AL,80H or 20H 6184 000028AE 0CA0 <1> OR AL,80h+20h ; ECC AND 512 BYTE SECTORS 6185 000028B0 8845FD <1> MOV [CMD_BLOCK+5],AL ; ECC/SIZE/DRIVE/HEAD 6186 <1> su4: 6187 <1> ;POP ES ; ** 6188 <1> ;; 14/02/2015 6189 <1> ;;POP AX 6190 <1> ;;MOV [CMD_BLOCK+1],AL ; SECTOR COUNT 6191 <1> ;;PUSH AX 6192 <1> ;;MOV AL,AH ; GET INTO LOW BYTE 6193 <1> ;;XOR AH,AH ; ZERO HIGH BYTE 6194 <1> ;;SAL AX,1 ; *2 FOR TABLE LOOKUP 6195 <1> ;pop ax ; *** 6196 <1> ; 05/12/2021 6197 000028B3 58 <1> pop eax ; *** 6198 000028B4 8845F9 <1> mov [CMD_BLOCK+1], al 6199 000028B7 29DB <1> sub ebx, ebx 6200 000028B9 88E3 <1> mov bl, ah 6201 <1> ;xor bh, bh 6202 <1> ;sal bx, 1 6203 000028BB 66C1E302 <1> sal bx, 2 ; 32 bit offset (21/02/2015) 6204 <1> ;;MOV SI,AX ; PUT INTO SI FOR BRANCH 6205 <1> ;;CMP AX,M1L ; TEST WITHIN RANGE 6206 <1> ;;JNB short BAD_COMMAND_POP 6207 <1> ;cmp bx, M1L 6208 000028BF 83FB74 <1> cmp ebx, M1L 6209 000028C2 7308 <1> jnb short BAD_COMMAND 6210 <1> ;xchg bx, si 6211 000028C4 87DE <1> xchg ebx, esi 6212 <1> ;;;POP AX ; RESTORE AX 6213 <1> ;;;POP BX ; AND DATA ADDRESS 6214 <1> 6215 <1> ;;PUSH CX 6216 <1> ;;PUSH AX ; ADJUST ES:BX 6217 <1> ;MOV CX,BX ; GET 3 HIGH ORDER NIBBLES OF BX 6218 <1> ;SHR CX,4 6219 <1> ;MOV AX,ES 6220 <1> ;ADD AX,CX 6221 <1> ;MOV ES,AX 6222 <1> ;AND BX,000FH ; ES:BX CHANGED TO ES:000X 6223 <1> ;;POP AX 6224 <1> ;;POP CX 6225 <1> ;;JMP word [CS:SI+M1] 6226 <1> ;jmp word [SI+M1] 6227 000028C6 FFA6[1D270000] <1> jmp dword [esi+M1] 6228 <1> ;;BAD_COMMAND_POP: 6229 <1> ;; POP AX 6230 <1> ;; POP BX 6231 <1> BAD_COMMAND: 6232 000028CC C605[3F6E0000]01 <1> MOV byte [DISK_STATUS1],BAD_CMD ; COMMAND ERROR 6233 000028D3 B000 <1> MOV AL,0 6234 000028D5 C3 <1> RETn 6235 <1> 6236 <1> ;---------------------------------------- 6237 <1> ; RESET THE DISK SYSTEM (AH=00H) : 6238 <1> ;---------------------------------------- 6239 <1> 6240 <1> ; 18-1-2015 : one controller reset (not other one) 6241 <1> 6242 <1> DISK_RESET: 6243 000028D6 FA <1> CLI 6244 000028D7 E4A1 <1> IN AL,INTB01 ; GET THE MASK REGISTER 6245 <1> ;JMP $+2 6246 <1> IODELAY 2133 000028D9 EB00 <2> jmp short $+2 2134 000028DB EB00 <2> jmp short $+2 6247 <1> ;AND AL,0BFH ; ENABLE FIXED DISK INTERRUPT 6248 000028DD 243F <1> and al,3Fh ; 22/12/2014 (IRQ 14 & IRQ 15) 6249 000028DF E6A1 <1> OUT INTB01,AL 6250 000028E1 FB <1> STI ; START INTERRUPTS 6251 <1> ; 14/02/2015 6252 <1> ;mov di, dx 6253 <1> ; 05/12/2021 6254 000028E2 89D7 <1> mov edi, edx 6255 <1> ; 04/01/2015 6256 <1> ;xor di,di 6257 <1> drst0: 6258 000028E4 B004 <1> MOV AL,04H ; bit 2 - SRST 6259 <1> ;MOV DX,HF_REG_PORT 6260 000028E6 668B15[96680000] <1> MOV DX,[HF_REG_PORT] 6261 000028ED EE <1> OUT DX,AL ; RESET 6262 <1> ; MOV CX,10 ; DELAY COUNT 6263 <1> ;DRD: DEC CX 6264 <1> ; JNZ short DRD ; WAIT 4.8 MICRO-SEC 6265 <1> ;mov cx,2 ; wait for 30 micro seconds 6266 000028EE B902000000 <1> mov ecx, 2 ; 21/02/2015 6267 000028F3 E8D3EBFFFF <1> call WAITF ; (Award Bios 1999 - WAIT_REFRESH, 6268 <1> ; 40 micro seconds) 6269 000028F8 A0[416E0000] <1> mov al,[CONTROL_BYTE] 6270 000028FD 240F <1> AND AL,0FH ; SET HEAD OPTION 6271 000028FF EE <1> OUT DX,AL ; TURN RESET OFF 6272 00002900 E807040000 <1> CALL NOT_BUSY 6273 00002905 7515 <1> JNZ short DRERR ; TIME OUT ON RESET 6274 00002907 668B15[94680000] <1> MOV DX,[HF_PORT] 6275 0000290E FEC2 <1> inc dl ; HF_PORT+1 6276 <1> ; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM 6277 <1> ;mov cl, 10 6278 00002910 B90A000000 <1> mov ecx, 10 ; 21/02/2015 6279 <1> drst1: 6280 00002915 EC <1> IN AL,DX ; GET RESET STATUS 6281 00002916 3C01 <1> CMP AL,1 6282 <1> ; 04/01/2015 6283 00002918 740A <1> jz short drst2 6284 <1> ;JNZ short DRERR ; BAD RESET STATUS 6285 <1> ; Drive/Head Register - bit 4 6286 0000291A E2F9 <1> loop drst1 6287 <1> DRERR: 6288 0000291C C605[3F6E0000]05 <1> MOV byte [DISK_STATUS1],BAD_RESET ; CARD FAILED 6289 00002923 C3 <1> RETn 6290 <1> drst2: 6291 <1> ; 14/02/2015 6292 <1> ;mov dx, di 6293 <1> ; 05/12/2021 6294 00002924 89FA <1> mov edx, edi 6295 <1> ;drst3: 6296 <1> ; ; 05/01/2015 6297 <1> ; shl di,1 6298 <1> ; ; 04/01/2015 6299 <1> ; mov ax,[di+hd_cports] 6300 <1> ; cmp ax,[HF_REG_PORT] 6301 <1> ; je short drst4 6302 <1> ; mov [HF_REG_PORT], ax 6303 <1> ; ; 03/01/2015 6304 <1> ; mov ax,[di+hd_ports] 6305 <1> ; mov [HF_PORT], ax 6306 <1> ; ; 05/01/2014 6307 <1> ; shr di,1 6308 <1> ; ; 04/01/2015 6309 <1> ; jmp short drst0 ; reset other controller 6310 <1> ;drst4: 6311 <1> ; ; 05/01/2015 6312 <1> ; shr di,1 6313 <1> ; mov al,[di+hd_dregs] 6314 <1> ; and al,10h ; bit 4 only 6315 <1> ; shr al,4 ; bit 4 -> bit 0 6316 <1> ; mov [hf_m_s], al ; (0 = master, 1 = slave) 6317 <1> ; 6318 00002926 A0[98680000] <1> mov al, [hf_m_s] ; 18/01/2015 6319 0000292B A801 <1> test al,1 6320 <1> ; jnz short drst6 6321 0000292D 7516 <1> jnz short drst4 6322 0000292F 8065FDEF <1> AND byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0 6323 <1> ;drst5: 6324 <1> drst3: 6325 00002933 E80B010000 <1> CALL INIT_DRV ; SET MAX HEADS 6326 <1> ;mov dx,di 6327 00002938 E8C3010000 <1> CALL HDISK_RECAL ; RECAL TO RESET SEEK SPEED 6328 <1> ; 04/01/2014 6329 <1> ; inc di 6330 <1> ; mov dx,di 6331 <1> ; cmp dl,[HF_NUM] 6332 <1> ; jb short drst3 6333 <1> ;DRE: 6334 0000293D C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 ; IGNORE ANY SET UP ERRORS 6335 00002944 C3 <1> RETn 6336 <1> ;drst6: 6337 <1> drst4: ; Drive/Head Register - bit 4 6338 00002945 804DFD10 <1> OR byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1 6339 <1> ;jmp short drst5 6340 00002949 EBE8 <1> jmp short drst3 6341 <1> 6342 <1> ;---------------------------------------- 6343 <1> ; DISK STATUS ROUTINE (AH = 01H) : 6344 <1> ;---------------------------------------- 6345 <1> 6346 <1> RETURN_STATUS: 6347 0000294B A0[3F6E0000] <1> MOV AL,[DISK_STATUS1] ; OBTAIN PREVIOUS STATUS 6348 00002950 C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 ; RESET STATUS 6349 00002957 C3 <1> RETn 6350 <1> 6351 <1> ;---------------------------------------- 6352 <1> ; DISK READ ROUTINE (AH = 02H) : 6353 <1> ;---------------------------------------- 6354 <1> 6355 <1> DISK_READ: 6356 00002958 C645FE20 <1> MOV byte [CMD_BLOCK+6],READ_CMD 6357 0000295C E92A020000 <1> JMP COMMANDI 6358 <1> 6359 <1> ;---------------------------------------- 6360 <1> ; DISK WRITE ROUTINE (AH = 03H) : 6361 <1> ;---------------------------------------- 6362 <1> 6363 <1> DISK_WRITE: 6364 00002961 C645FE30 <1> MOV byte [CMD_BLOCK+6],WRITE_CMD 6365 00002965 E976020000 <1> JMP COMMANDO 6366 <1> 6367 <1> ;---------------------------------------- 6368 <1> ; DISK VERIFY (AH = 04H) : 6369 <1> ;---------------------------------------- 6370 <1> 6371 <1> DISK_VERF: 6372 0000296A C645FE40 <1> MOV byte [CMD_BLOCK+6],VERIFY_CMD 6373 0000296E E8E4020000 <1> CALL COMMAND 6374 00002973 750C <1> JNZ short VERF_EXIT ; CONTROLLER STILL BUSY 6375 00002975 E856030000 <1> CALL _WAIT ; (Original: CALL WAIT) 6376 0000297A 7505 <1> JNZ short VERF_EXIT ; TIME OUT 6377 0000297C E8E3030000 <1> CALL CHECK_STATUS 6378 <1> VERF_EXIT: 6379 00002981 C3 <1> RETn 6380 <1> 6381 <1> ;---------------------------------------- 6382 <1> ; FORMATTING (AH = 05H) : 6383 <1> ;---------------------------------------- 6384 <1> 6385 <1> FMT_TRK: ; FORMAT TRACK (AH = 005H) 6386 00002982 C645FE50 <1> MOV byte [CMD_BLOCK+6],FMTTRK_CMD 6387 <1> ;PUSH ES 6388 <1> ;PUSH BX 6389 00002986 53 <1> push ebx 6390 00002987 E885040000 <1> CALL GET_VEC ; GET DISK PARAMETERS ADDRESS 6391 <1> ;MOV AL,[ES:BX+14] ; GET SECTORS/TRACK 6392 0000298C 8A430E <1> mov al, [ebx+14] 6393 0000298F 8845F9 <1> MOV [CMD_BLOCK+1],AL ; SET SECTOR COUNT IN COMMAND 6394 00002992 5B <1> pop ebx 6395 <1> ;POP BX 6396 <1> ;POP ES 6397 00002993 E94F020000 <1> JMP CMD_OF ; GO EXECUTE THE COMMAND 6398 <1> 6399 <1> ;---------------------------------------- 6400 <1> ; READ DASD TYPE (AH = 15H) : 6401 <1> ;---------------------------------------- 6402 <1> 6403 <1> READ_DASD_TYPE: 6404 <1> READ_D_T: ; GET DRIVE PARAMETERS 6405 00002998 1E <1> PUSH DS ; SAVE REGISTERS 6406 <1> ;PUSH ES 6407 00002999 53 <1> PUSH eBX 6408 <1> ;CALL DDS ; ESTABLISH ADDRESSING 6409 <1> ;push cs 6410 <1> ;pop ds 6411 0000299A 66BB1000 <1> mov bx, KDATA 6412 0000299E 8EDB <1> mov ds, bx 6413 <1> ;mov es, bx 6414 000029A0 C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 6415 000029A7 8A1D[406E0000] <1> MOV BL,[HF_NUM] ; GET NUMBER OF DRIVES 6416 000029AD 80E27F <1> AND DL,7FH ; GET DRIVE NUMBER 6417 000029B0 38D3 <1> CMP BL,DL 6418 000029B2 7625 <1> JBE short RDT_NOT_PRESENT ; RETURN DRIVE NOT PRESENT 6419 000029B4 E858040000 <1> CALL GET_VEC ; GET DISK PARAMETER ADDRESS 6420 <1> ;MOV AL,[ES:BX+2] ; HEADS 6421 000029B9 8A4302 <1> mov al, [ebx+2] 6422 <1> ;MOV CL,[ES:BX+14] 6423 000029BC 8A4B0E <1> mov cl, [ebx+14] 6424 000029BF F6E9 <1> IMUL CL ; * NUMBER OF SECTORS 6425 <1> ;MOV CX,[ES:BX] ; MAX NUMBER OF CYLINDERS 6426 000029C1 668B0B <1> mov cx, [ebx] 6427 <1> ; 6428 <1> ; 02/01/2015 6429 <1> ; ** leave the last cylinder as reserved for diagnostics ** 6430 <1> ; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1) 6431 000029C4 6649 <1> DEC CX ; LEAVE ONE FOR DIAGNOSTICS 6432 <1> ; 6433 000029C6 66F7E9 <1> IMUL CX ; NUMBER OF SECTORS 6434 000029C9 6689D1 <1> MOV CX,DX ; HIGH ORDER HALF 6435 000029CC 6689C2 <1> MOV DX,AX ; LOW ORDER HALF 6436 <1> ;SUB AX,AX 6437 000029CF 28C0 <1> sub al, al 6438 000029D1 B403 <1> MOV AH,03H ; INDICATE FIXED DISK 6439 000029D3 5B <1> RDT2: POP eBX ; RESTORE REGISTERS 6440 <1> ;POP ES 6441 000029D4 1F <1> POP DS 6442 000029D5 F8 <1> CLC ; CLEAR CARRY 6443 <1> ;RETf 2 6444 000029D6 CA0400 <1> retf 4 6445 <1> RDT_NOT_PRESENT: 6446 <1> ;SUB AX,AX ; DRIVE NOT PRESENT RETURN 6447 <1> ; 05/12/2021 6448 000029D9 29C0 <1> sub eax, eax 6449 <1> ;MOV CX,AX ; ZERO BLOCK COUNT 6450 <1> ;MOV DX,AX 6451 000029DB 89C1 <1> mov ecx, eax 6452 000029DD 89C2 <1> mov edx, eax 6453 000029DF EBF2 <1> JMP short RDT2 6454 <1> 6455 <1> ;---------------------------------------- 6456 <1> ; GET PARAMETERS (AH = 08H) : 6457 <1> ;---------------------------------------- 6458 <1> 6459 <1> GET_PARM_N: 6460 <1> ;GET_PARM: ; GET DRIVE PARAMETERS 6461 000029E1 1E <1> PUSH DS ; SAVE REGISTERS 6462 <1> ;PUSH ES 6463 000029E2 53 <1> PUSH eBX 6464 <1> ;MOV AX,ABS0 ; ESTABLISH ADDRESSING 6465 <1> ;MOV DS,AX 6466 <1> ;TEST DL,1 ; CHECK FOR DRIVE 1 6467 <1> ;JZ short G0 6468 <1> ;LES BX,@HF1_TBL_VEC 6469 <1> ;JMP SHORT G1 6470 <1> ;G0: LES BX,@HF_TBL_VEC 6471 <1> ;G1: 6472 <1> ;CALL DDS ; ESTABLISH SEGMENT 6473 <1> ; 22/12/2014 6474 <1> ;push cs 6475 <1> ;pop ds 6476 000029E3 66BB1000 <1> mov bx, KDATA 6477 000029E7 8EDB <1> mov ds, bx 6478 <1> ;mov es, bx 6479 <1> ; 6480 000029E9 80EA80 <1> SUB DL,80H 6481 000029EC 80FA04 <1> CMP DL,MAX_FILE ; TEST WITHIN RANGE 6482 000029EF 7340 <1> JAE short G4 6483 <1> ; 6484 000029F1 31DB <1> xor ebx, ebx ; 21/02/2015 6485 <1> ; 22/12/2014 6486 000029F3 88D3 <1> mov bl, dl 6487 <1> ;xor bh, bh 6488 000029F5 C0E302 <1> shl bl, 2 ; convert index to offset 6489 <1> ;add bx, HF_TBL_VEC 6490 000029F8 81C3[446E0000] <1> add ebx, HF_TBL_VEC 6491 <1> ;mov ax, [bx+2] 6492 <1> ;mov es, ax ; dpt segment 6493 <1> ;mov bx, [bx] ; dpt offset 6494 000029FE 8B1B <1> mov ebx, [ebx] ; 32 bit offset 6495 <1> 6496 00002A00 C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 6497 <1> ;MOV AX,[ES:BX] ; MAX NUMBER OF CYLINDERS 6498 00002A07 668B03 <1> mov ax, [ebx] 6499 <1> ;;SUB AX,2 ; ADJUST FOR 0-N 6500 00002A0A 6648 <1> dec ax ; max. cylinder number 6501 00002A0C 88C5 <1> MOV CH,AL 6502 00002A0E 66250003 <1> AND AX,0300H ; HIGH TWO BITS OF CYLINDER 6503 00002A12 66D1E8 <1> SHR AX,1 6504 00002A15 66D1E8 <1> SHR AX,1 6505 <1> ;OR AL,[ES:BX+14] ; SECTORS 6506 00002A18 0A430E <1> or al, [ebx+14] 6507 00002A1B 88C1 <1> MOV CL,AL 6508 <1> ;MOV DH,[ES:BX+2] ; HEADS 6509 00002A1D 8A7302 <1> mov dh, [ebx+2] 6510 00002A20 FECE <1> DEC DH ; 0-N RANGE 6511 00002A22 8A15[406E0000] <1> MOV DL,[HF_NUM] ; DRIVE COUNT 6512 <1> ;SUB AX,AX 6513 <1> ; 05/12/2021 6514 00002A28 29C0 <1> sub eax, eax 6515 <1> ; 27/12/2014 6516 <1> ; ES:DI = Address of disk parameter table from BIOS 6517 <1> ; (Programmer's Guide to the AMIBIOS - 1993) 6518 <1> ;mov di, bx ; HDPT offset 6519 00002A2A 89DF <1> mov edi, ebx 6520 <1> G5: 6521 00002A2C 5B <1> POP eBX ; RESTORE REGISTERS 6522 <1> ;POP ES 6523 00002A2D 1F <1> POP DS 6524 <1> ;RETf 2 6525 00002A2E CA0400 <1> retf 4 6526 <1> G4: 6527 00002A31 C605[3F6E0000]07 <1> MOV byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED 6528 <1> ; 05/12/2021 6529 00002A38 29C0 <1> sub eax, eax 6530 00002A3A B407 <1> MOV AH,INIT_FAIL 6531 <1> ;SUB AL,AL 6532 <1> ;SUB DX,DX 6533 00002A3C 29D2 <1> sub edx, edx 6534 <1> ;SUB CX,CX 6535 00002A3E 29C9 <1> sub ecx, ecx 6536 00002A40 F9 <1> STC ; SET ERROR FLAG 6537 00002A41 EBE9 <1> JMP short G5 6538 <1> 6539 <1> ;---------------------------------------- 6540 <1> ; INITIALIZE DRIVE (AH = 09H) : 6541 <1> ;---------------------------------------- 6542 <1> ; 03/01/2015 6543 <1> ; According to ATA-ATAPI specification v2.0 to v5.0 6544 <1> ; logical sector per logical track 6545 <1> ; and logical heads - 1 would be set but 6546 <1> ; it is seen as it will be good 6547 <1> ; if physical parameters will be set here 6548 <1> ; because, number of heads <= 16. 6549 <1> ; (logical heads usually more than 16) 6550 <1> ; NOTE: ATA logical parameters (software C, H, S) 6551 <1> ; == INT 13h physical parameters 6552 <1> 6553 <1> ;INIT_DRV: 6554 <1> ; MOV byte [CMD_BLOCK+6],SET_PARM_CMD 6555 <1> ; CALL GET_VEC ; ES:BX -> PARAMETER BLOCK 6556 <1> ; MOV AL,[ES:BX+2] ; GET NUMBER OF HEADS 6557 <1> ; DEC AL ; CONVERT TO 0-INDEX 6558 <1> ; MOV AH,[CMD_BLOCK+5] ; GET SDH REGISTER 6559 <1> ; AND AH,0F0H ; CHANGE HEAD NUMBER 6560 <1> ; OR AH,AL ; TO MAX HEAD 6561 <1> ; MOV [CMD_BLOCK+5],AH 6562 <1> ; MOV AL,[ES:BX+14] ; MAX SECTOR NUMBER 6563 <1> ; MOV [CMD_BLOCK+1],AL 6564 <1> ; SUB AX,AX 6565 <1> ; MOV [CMD_BLOCK+3],AL ; ZERO FLAGS 6566 <1> ; CALL COMMAND ; TELL CONTROLLER 6567 <1> ; JNZ short INIT_EXIT ; CONTROLLER BUSY ERROR 6568 <1> ; CALL NOT_BUSY ; WAIT FOR IT TO BE DONE 6569 <1> ; JNZ short INIT_EXIT ; TIME OUT 6570 <1> ; CALL CHECK_STATUS 6571 <1> ;INIT_EXIT: 6572 <1> ; RETn 6573 <1> 6574 <1> ; 04/01/2015 6575 <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999 6576 <1> ; AHDSK.ASM - INIT_DRIVE 6577 <1> INIT_DRV: 6578 <1> ;xor ah,ah 6579 00002A43 31C0 <1> xor eax,eax ; 21/02/2015 6580 00002A45 B00B <1> mov al,11 ; Physical heads from translated HDPT 6581 00002A47 3825[546E0000] <1> cmp [LBAMode], ah ; 0 6582 00002A4D 7702 <1> ja short idrv0 6583 00002A4F B002 <1> mov al,2 ; Physical heads from standard HDPT 6584 <1> idrv0: 6585 <1> ; DL = drive number (0 based) 6586 00002A51 E8BB030000 <1> call GET_VEC 6587 <1> ;push bx 6588 00002A56 53 <1> push ebx ; 21/02/2015 6589 <1> ;add bx,ax 6590 00002A57 01C3 <1> add ebx,eax 6591 <1> ;; 05/01/2015 6592 00002A59 8A25[98680000] <1> mov ah,[hf_m_s] ; drive number (0= master, 1= slave) 6593 <1> ;;and ah,1 6594 00002A5F C0E404 <1> shl ah,4 6595 00002A62 80CCA0 <1> or ah,0A0h ; Drive/Head register - 10100000b (A0h) 6596 <1> ;mov al,[es:bx] 6597 00002A65 8A03 <1> mov al,[ebx] ; 21/02/2015 6598 00002A67 FEC8 <1> dec al ; last head number 6599 <1> ;and al,0Fh 6600 00002A69 08E0 <1> or al,ah ; lower 4 bits for head number 6601 <1> ; 6602 00002A6B C645FE91 <1> mov byte [CMD_BLOCK+6],SET_PARM_CMD 6603 00002A6F 8845FD <1> mov [CMD_BLOCK+5],al 6604 <1> ;pop bx 6605 00002A72 5B <1> pop ebx 6606 00002A73 29C0 <1> sub eax,eax ; 21/02/2015 6607 00002A75 B004 <1> mov al,4 ; Physical sec per track from translated HDPT 6608 00002A77 803D[546E0000]00 <1> cmp byte [LBAMode],0 6609 00002A7E 7702 <1> ja short idrv1 6610 00002A80 B00E <1> mov al,14 ; Physical sec per track from standard HDPT 6611 <1> idrv1: 6612 <1> ;xor ah,ah 6613 <1> ;add bx,ax 6614 00002A82 01C3 <1> add ebx,eax ; 21/02/2015 6615 <1> ;mov al,[es:bx] 6616 <1> ; sector number 6617 00002A84 8A03 <1> mov al,[ebx] 6618 00002A86 8845F9 <1> mov [CMD_BLOCK+1],al 6619 00002A89 28C0 <1> sub al,al 6620 00002A8B 8845FB <1> mov [CMD_BLOCK+3],al ; ZERO FLAGS 6621 00002A8E E8C4010000 <1> call COMMAND ; TELL CONTROLLER 6622 00002A93 750C <1> jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 6623 00002A95 E872020000 <1> call NOT_BUSY ; WAIT FOR IT TO BE DONE 6624 00002A9A 7505 <1> jnz short INIT_EXIT ; TIME OUT 6625 00002A9C E8C3020000 <1> call CHECK_STATUS 6626 <1> INIT_EXIT: 6627 00002AA1 C3 <1> RETn 6628 <1> 6629 <1> ;---------------------------------------- 6630 <1> ; READ LONG (AH = 0AH) : 6631 <1> ;---------------------------------------- 6632 <1> 6633 <1> RD_LONG: 6634 <1> ;MOV @CMD_BLOCK+6,READ_CMD OR ECC_MODE 6635 00002AA2 C645FE22 <1> mov byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 6636 00002AA6 E9E0000000 <1> JMP COMMANDI 6637 <1> 6638 <1> ;---------------------------------------- 6639 <1> ; WRITE LONG (AH = 0BH) : 6640 <1> ;---------------------------------------- 6641 <1> 6642 <1> WR_LONG: 6643 <1> ;MOV @CMD_BLOCK+6,WRITE_CMD OR ECC_MODE 6644 00002AAB C645FE32 <1> MOV byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE 6645 00002AAF E92C010000 <1> JMP COMMANDO 6646 <1> 6647 <1> ;---------------------------------------- 6648 <1> ; SEEK (AH = 0CH) : 6649 <1> ;---------------------------------------- 6650 <1> 6651 <1> DISK_SEEK: 6652 00002AB4 C645FE70 <1> MOV byte [CMD_BLOCK+6],SEEK_CMD 6653 00002AB8 E89A010000 <1> CALL COMMAND 6654 00002ABD 751C <1> JNZ short DS_EXIT ; CONTROLLER BUSY ERROR 6655 00002ABF E80C020000 <1> CALL _WAIT 6656 00002AC4 7515 <1> JNZ DS_EXIT ; TIME OUT ON SEEK 6657 00002AC6 E899020000 <1> CALL CHECK_STATUS 6658 00002ACB 803D[3F6E0000]40 <1> CMP byte [DISK_STATUS1],BAD_SEEK 6659 00002AD2 7507 <1> JNE short DS_EXIT 6660 00002AD4 C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 6661 <1> DS_EXIT: 6662 00002ADB C3 <1> RETn 6663 <1> 6664 <1> ;---------------------------------------- 6665 <1> ; TEST DISK READY (AH = 10H) : 6666 <1> ;---------------------------------------- 6667 <1> 6668 <1> TST_RDY: ; WAIT FOR CONTROLLER 6669 00002ADC E82B020000 <1> CALL NOT_BUSY 6670 00002AE1 751C <1> JNZ short TR_EX 6671 00002AE3 8A45FD <1> MOV AL,[CMD_BLOCK+5] ; SELECT DRIVE 6672 00002AE6 668B15[94680000] <1> MOV DX,[HF_PORT] 6673 00002AED 80C206 <1> add dl,6 6674 00002AF0 EE <1> OUT DX,AL 6675 00002AF1 E886020000 <1> CALL CHECK_ST ; CHECK STATUS ONLY 6676 00002AF6 7507 <1> JNZ short TR_EX 6677 00002AF8 C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 ; WIPE OUT DATA CORRECTED ERROR 6678 <1> TR_EX: 6679 00002AFF C3 <1> RETn 6680 <1> 6681 <1> ;---------------------------------------- 6682 <1> ; RECALIBRATE (AH = 11H) : 6683 <1> ;---------------------------------------- 6684 <1> 6685 <1> HDISK_RECAL: 6686 00002B00 C645FE10 <1> MOV byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16 6687 00002B04 E84E010000 <1> CALL COMMAND ; START THE OPERATION 6688 00002B09 7523 <1> JNZ short RECAL_EXIT ; ERROR 6689 00002B0B E8C0010000 <1> CALL _WAIT ; WAIT FOR COMPLETION 6690 00002B10 7407 <1> JZ short RECAL_X ; TIME OUT ONE OK ? 6691 00002B12 E8B9010000 <1> CALL _WAIT ; WAIT FOR COMPLETION LONGER 6692 00002B17 7515 <1> JNZ short RECAL_EXIT ; TIME OUT TWO TIMES IS ERROR 6693 <1> RECAL_X: 6694 00002B19 E846020000 <1> CALL CHECK_STATUS 6695 00002B1E 803D[3F6E0000]40 <1> CMP byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE 6696 00002B25 7507 <1> JNE short RECAL_EXIT ; IS OK 6697 00002B27 C605[3F6E0000]00 <1> MOV byte [DISK_STATUS1],0 6698 <1> RECAL_EXIT: 6699 00002B2E 803D[3F6E0000]00 <1> CMP byte [DISK_STATUS1],0 6700 00002B35 C3 <1> RETn 6701 <1> 6702 <1> ;---------------------------------------- 6703 <1> ; CONTROLLER DIAGNOSTIC (AH = 14H) : 6704 <1> ;---------------------------------------- 6705 <1> 6706 <1> CTLR_DIAGNOSTIC: 6707 00002B36 FA <1> CLI ; DISABLE INTERRUPTS WHILE CHANGING MASK 6708 00002B37 E4A1 <1> IN AL,INTB01 ; TURN ON SECOND INTERRUPT CHIP 6709 <1> ;AND AL,0BFH 6710 00002B39 243F <1> and al, 3Fh ; enable IRQ 14 & IRQ 15 6711 <1> ;JMP $+2 6712 <1> IODELAY 2133 00002B3B EB00 <2> jmp short $+2 2134 00002B3D EB00 <2> jmp short $+2 6713 00002B3F E6A1 <1> OUT INTB01,AL 6714 <1> IODELAY 2133 00002B41 EB00 <2> jmp short $+2 2134 00002B43 EB00 <2> jmp short $+2 6715 00002B45 E421 <1> IN AL,INTA01 ; LET INTERRUPTS PASS THRU TO 6716 00002B47 24FB <1> AND AL,0FBH ; SECOND CHIP 6717 <1> ;JMP $+2 6718 <1> IODELAY 2133 00002B49 EB00 <2> jmp short $+2 2134 00002B4B EB00 <2> jmp short $+2 6719 00002B4D E621 <1> OUT INTA01,AL 6720 00002B4F FB <1> STI 6721 00002B50 E8B7010000 <1> CALL NOT_BUSY ; WAIT FOR CARD 6722 00002B55 752B <1> JNZ short CD_ERR ; BAD CARD 6723 <1> ;MOV DX, HF_PORT+7 6724 00002B57 668B15[94680000] <1> mov dx, [HF_PORT] 6725 00002B5E 80C207 <1> add dl, 7 6726 00002B61 B090 <1> MOV AL,DIAG_CMD ; START DIAGNOSE 6727 00002B63 EE <1> OUT DX,AL 6728 00002B64 E8A3010000 <1> CALL NOT_BUSY ; WAIT FOR IT TO COMPLETE 6729 00002B69 B480 <1> MOV AH,TIME_OUT 6730 00002B6B 7517 <1> JNZ short CD_EXIT ; TIME OUT ON DIAGNOSTIC 6731 <1> ;MOV DX,HF_PORT+1 ; GET ERROR REGISTER 6732 00002B6D 668B15[94680000] <1> mov dx, [HF_PORT] 6733 00002B74 FEC2 <1> inc dl 6734 00002B76 EC <1> IN AL,DX 6735 00002B77 A2[366E0000] <1> MOV [HF_ERROR],AL ; SAVE IT 6736 00002B7C B400 <1> MOV AH,0 6737 00002B7E 3C01 <1> CMP AL,1 ; CHECK FOR ALL OK 6738 00002B80 7402 <1> JE SHORT CD_EXIT 6739 00002B82 B420 <1> CD_ERR: MOV AH,BAD_CNTLR 6740 <1> CD_EXIT: 6741 00002B84 8825[3F6E0000] <1> MOV [DISK_STATUS1],AH 6742 00002B8A C3 <1> RETn 6743 <1> 6744 <1> ;---------------------------------------- 6745 <1> ; COMMANDI : 6746 <1> ; REPEATEDLY INPUTS DATA TILL : 6747 <1> ; NSECTOR RETURNS ZERO : 6748 <1> ;---------------------------------------- 6749 <1> COMMANDI: 6750 00002B8B E85A020000 <1> CALL CHECK_DMA ; CHECK 64K BOUNDARY ERROR 6751 00002B90 724D <1> JC short CMD_ABORT 6752 <1> ;MOV DI,BX 6753 00002B92 89DF <1> mov edi, ebx ; 21/02/2015 6754 00002B94 E8BE000000 <1> CALL COMMAND ; OUTPUT COMMAND 6755 00002B99 7544 <1> JNZ short CMD_ABORT 6756 <1> CMD_I1: 6757 00002B9B E830010000 <1> CALL _WAIT ; WAIT FOR DATA REQUEST INTERRUPT 6758 00002BA0 753D <1> JNZ short TM_OUT ; TIME OUT 6759 <1> ;MOV CX,256 ; SECTOR SIZE IN WORDS 6760 00002BA2 B900010000 <1> mov ecx, 256 ; 21/02/2015 6761 <1> ;MOV DX,HF_PORT 6762 00002BA7 668B15[94680000] <1> mov dx,[HF_PORT] 6763 00002BAE FA <1> CLI 6764 00002BAF FC <1> CLD 6765 00002BB0 F3666D <1> REP INSW ; GET THE SECTOR 6766 00002BB3 FB <1> STI 6767 00002BB4 F645FE02 <1> TEST byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT 6768 00002BB8 7419 <1> JZ CMD_I3 6769 00002BBA E87A010000 <1> CALL WAIT_DRQ ; WAIT FOR DATA REQUEST 6770 00002BBF 721E <1> JC short TM_OUT 6771 <1> ;MOV DX,HF_PORT 6772 00002BC1 668B15[94680000] <1> mov dx,[HF_PORT] 6773 <1> ;MOV CX,4 ; GET ECC BYTES 6774 00002BC8 B904000000 <1> mov ecx, 4 ; mov cx, 4 6775 00002BCD EC <1> CMD_I2: IN AL,DX 6776 <1> ;MOV [ES:DI],AL ; GO SLOW FOR BOARD 6777 00002BCE 8807 <1> mov [edi], al ; 21/02/2015 6778 00002BD0 47 <1> INC eDI 6779 00002BD1 E2FA <1> LOOP CMD_I2 6780 00002BD3 E88C010000 <1> CMD_I3: CALL CHECK_STATUS 6781 00002BD8 7505 <1> JNZ short CMD_ABORT ; ERROR RETURNED 6782 00002BDA FE4DF9 <1> DEC byte [CMD_BLOCK+1] ; CHECK FOR MORE 6783 00002BDD 75BC <1> JNZ SHORT CMD_I1 6784 <1> CMD_ABORT: 6785 00002BDF C3 <1> TM_OUT: RETn 6786 <1> 6787 <1> ;---------------------------------------- 6788 <1> ; COMMANDO : 6789 <1> ; REPEATEDLY OUTPUTS DATA TILL : 6790 <1> ; NSECTOR RETURNS ZERO : 6791 <1> ;---------------------------------------- 6792 <1> COMMANDO: 6793 00002BE0 E805020000 <1> CALL CHECK_DMA ; CHECK 64K BOUNDARY ERROR 6794 00002BE5 72F8 <1> JC short CMD_ABORT 6795 00002BE7 89DE <1> CMD_OF: MOV eSI,eBX ; 21/02/2015 6796 00002BE9 E869000000 <1> CALL COMMAND ; OUTPUT COMMAND 6797 00002BEE 75EF <1> JNZ short CMD_ABORT 6798 00002BF0 E844010000 <1> CALL WAIT_DRQ ; WAIT FOR DATA REQUEST 6799 00002BF5 72E8 <1> JC short TM_OUT ; TOO LONG 6800 <1> CMD_O1: ;PUSH DS 6801 <1> ;PUSH ES ; MOVE ES TO DS 6802 <1> ;POP DS 6803 <1> ;MOV CX,256 ; PUT THE DATA OUT TO THE CARD 6804 <1> ;MOV DX,HF_PORT 6805 <1> ; 01/02/2015 6806 00002BF7 668B15[94680000] <1> mov dx, [HF_PORT] 6807 <1> ;push es 6808 <1> ;pop ds 6809 <1> ;mov cx, 256 6810 00002BFE B900010000 <1> mov ecx, 256 ; 21/02/2015 6811 00002C03 FA <1> CLI 6812 00002C04 FC <1> CLD 6813 00002C05 F3666F <1> REP OUTSW 6814 00002C08 FB <1> STI 6815 <1> ;POP DS ; RESTORE DS 6816 00002C09 F645FE02 <1> TEST byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT 6817 00002C0D 7419 <1> JZ short CMD_O3 6818 00002C0F E825010000 <1> CALL WAIT_DRQ ; WAIT FOR DATA REQUEST 6819 00002C14 72C9 <1> JC short TM_OUT 6820 <1> ;MOV DX,HF_PORT 6821 00002C16 668B15[94680000] <1> mov dx, [HF_PORT] 6822 <1> ;MOV CX,4 ; OUTPUT THE ECC BYTES 6823 00002C1D B904000000 <1> mov ecx, 4 ; mov cx, 4 6824 <1> CMD_O2: ;MOV AL,[ES:SI] 6825 00002C22 8A06 <1> mov al, [esi] 6826 00002C24 EE <1> OUT DX,AL 6827 00002C25 46 <1> INC eSI 6828 00002C26 E2FA <1> LOOP CMD_O2 6829 <1> CMD_O3: 6830 00002C28 E8A3000000 <1> CALL _WAIT ; WAIT FOR SECTOR COMPLETE INTERRUPT 6831 00002C2D 75B0 <1> JNZ short TM_OUT ; ERROR RETURNED 6832 00002C2F E830010000 <1> CALL CHECK_STATUS 6833 00002C34 75A9 <1> JNZ short CMD_ABORT 6834 00002C36 F605[356E0000]08 <1> TEST byte [HF_STATUS],ST_DRQ ; CHECK FOR MORE 6835 00002C3D 75B8 <1> JNZ SHORT CMD_O1 6836 <1> ;MOV DX,HF_PORT+2 ; CHECK RESIDUAL SECTOR COUNT 6837 00002C3F 668B15[94680000] <1> mov dx, [HF_PORT] 6838 <1> ;add dl, 2 6839 00002C46 FEC2 <1> inc dl 6840 00002C48 FEC2 <1> inc dl 6841 00002C4A EC <1> IN AL,DX ; 6842 00002C4B A8FF <1> TEST AL,0FFH ; 6843 00002C4D 7407 <1> JZ short CMD_O4 ; COUNT = 0 OK 6844 00002C4F C605[3F6E0000]BB <1> MOV byte [DISK_STATUS1],UNDEF_ERR 6845 <1> ; OPERATION ABORTED - PARTIAL TRANSFER 6846 <1> CMD_O4: 6847 00002C56 C3 <1> RETn 6848 <1> 6849 <1> ;-------------------------------------------------------- 6850 <1> ; COMMAND : 6851 <1> ; THIS ROUTINE OUTPUTS THE COMMAND BLOCK : 6852 <1> ; OUTPUT : 6853 <1> ; BL = STATUS : 6854 <1> ; BH = ERROR REGISTER : 6855 <1> ;-------------------------------------------------------- 6856 <1> 6857 <1> COMMAND: 6858 00002C57 53 <1> PUSH eBX ; WAIT FOR SEEK COMPLETE AND READY 6859 <1> ;;MOV CX,DELAY_2 ; SET INITIAL DELAY BEFORE TEST 6860 <1> COMMAND1: 6861 <1> ;;PUSH CX ; SAVE LOOP COUNT 6862 00002C58 E87FFEFFFF <1> CALL TST_RDY ; CHECK DRIVE READY 6863 <1> ;;POP CX 6864 00002C5D 7419 <1> JZ short COMMAND2 ; DRIVE IS READY 6865 00002C5F 803D[3F6E0000]80 <1> CMP byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP 6866 <1> ;JZ short CMD_TIMEOUT 6867 <1> ;;LOOP COMMAND1 ; KEEP TRYING FOR A WHILE 6868 <1> ;JMP SHORT COMMAND4 ; ITS NOT GOING TO GET READY 6869 00002C66 7507 <1> jne short COMMAND4 6870 <1> CMD_TIMEOUT: 6871 00002C68 C605[3F6E0000]20 <1> MOV byte [DISK_STATUS1],BAD_CNTLR 6872 <1> COMMAND4: 6873 00002C6F 5B <1> POP eBX 6874 00002C70 803D[3F6E0000]00 <1> CMP byte [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 6875 00002C77 C3 <1> RETn 6876 <1> COMMAND2: 6877 00002C78 5B <1> POP eBX 6878 00002C79 57 <1> PUSH eDI 6879 00002C7A C605[376E0000]00 <1> MOV byte [HF_INT_FLAG],0 ; RESET INTERRUPT FLAG 6880 00002C81 FA <1> CLI ; INHIBIT INTERRUPTS WHILE CHANGING MASK 6881 00002C82 E4A1 <1> IN AL,INTB01 ; TURN ON SECOND INTERRUPT CHIP 6882 <1> ;AND AL,0BFH 6883 00002C84 243F <1> and al, 3Fh ; Enable IRQ 14 & 15 6884 <1> ;JMP $+2 6885 <1> IODELAY 2133 00002C86 EB00 <2> jmp short $+2 2134 00002C88 EB00 <2> jmp short $+2 6886 00002C8A E6A1 <1> OUT INTB01,AL 6887 00002C8C E421 <1> IN AL,INTA01 ; LET INTERRUPTS PASS THRU TO 6888 00002C8E 24FB <1> AND AL,0FBH ; SECOND CHIP 6889 <1> ;JMP $+2 6890 <1> IODELAY 2133 00002C90 EB00 <2> jmp short $+2 2134 00002C92 EB00 <2> jmp short $+2 6891 00002C94 E621 <1> OUT INTA01,AL 6892 00002C96 FB <1> STI 6893 00002C97 31FF <1> XOR eDI,eDI ; INDEX THE COMMAND TABLE 6894 <1> ;MOV DX,HF_PORT+1 ; DISK ADDRESS 6895 00002C99 668B15[94680000] <1> mov dx, [HF_PORT] 6896 00002CA0 FEC2 <1> inc dl 6897 00002CA2 F605[416E0000]C0 <1> TEST byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION 6898 00002CA9 7411 <1> JZ short COMMAND3 6899 00002CAB 8A45FE <1> MOV AL, [CMD_BLOCK+6] ; YES-GET OPERATION CODE 6900 00002CAE 24F0 <1> AND AL,0F0H ; GET RID OF MODIFIERS 6901 00002CB0 3C20 <1> CMP AL,20H ; 20H-40H IS READ, WRITE, VERIFY 6902 00002CB2 7208 <1> JB short COMMAND3 6903 00002CB4 3C40 <1> CMP AL,40H 6904 00002CB6 7704 <1> JA short COMMAND3 6905 00002CB8 804DFE01 <1> OR byte [CMD_BLOCK+6],NO_RETRIES 6906 <1> ; VALID OPERATION FOR RETRY SUPPRESS 6907 <1> COMMAND3: 6908 00002CBC 8A443DF8 <1> MOV AL,[CMD_BLOCK+eDI] ; GET THE COMMAND STRING BYTE 6909 00002CC0 EE <1> OUT DX,AL ; GIVE IT TO CONTROLLER 6910 <1> IODELAY 2133 00002CC1 EB00 <2> jmp short $+2 2134 00002CC3 EB00 <2> jmp short $+2 6911 00002CC5 47 <1> INC eDI ; NEXT BYTE IN COMMAND BLOCK 6912 00002CC6 6642 <1> INC DX ; NEXT DISK ADAPTER REGISTER 6913 00002CC8 6683FF07 <1> cmp di, 7 ; 1/1/2015 ; ALL DONE? 6914 00002CCC 75EE <1> JNZ short COMMAND3 ; NO--GO DO NEXT ONE 6915 00002CCE 5F <1> POP eDI 6916 00002CCF C3 <1> RETn ; ZERO FLAG IS SET 6917 <1> 6918 <1> ;CMD_TIMEOUT: 6919 <1> ; MOV byte [DISK_STATUS1],BAD_CNTLR 6920 <1> ;COMMAND4: 6921 <1> ; POP BX 6922 <1> ; CMP [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 6923 <1> ; RETn 6924 <1> 6925 <1> ;---------------------------------------- 6926 <1> ; WAIT FOR INTERRUPT : 6927 <1> ;---------------------------------------- 6928 <1> ;WAIT: 6929 <1> _WAIT: 6930 00002CD0 FB <1> STI ; MAKE SURE INTERRUPTS ARE ON 6931 <1> ;SUB CX,CX ; SET INITIAL DELAY BEFORE TEST 6932 <1> ;CLC 6933 <1> ;MOV AX,9000H ; DEVICE WAIT INTERRUPT 6934 <1> ;INT 15H 6935 <1> ;JC WT2 ; DEVICE TIMED OUT 6936 <1> ;MOV BL,DELAY_1 ; SET DELAY COUNT 6937 <1> 6938 <1> ;mov bl, WAIT_HDU_INT_HI 6939 <1> ;; 21/02/2015 6940 <1> ;;mov bl, WAIT_HDU_INT_HI + 1 6941 <1> ;;mov cx, WAIT_HDU_INT_LO 6942 00002CD1 B915160500 <1> mov ecx, WAIT_HDU_INT_LH 6943 <1> ; (AWARD BIOS -> WAIT_FOR_MEM) 6944 <1> ;----- WAIT LOOP 6945 <1> 6946 <1> WT1: 6947 <1> ;TEST byte [HF_INT_FLAG],80H ; TEST FOR INTERRUPT 6948 00002CD6 F605[376E0000]C0 <1> test byte [HF_INT_FLAG],0C0h 6949 <1> ;LOOPZ WT1 6950 00002CDD 7517 <1> JNZ short WT3 ; INTERRUPT--LETS GO 6951 <1> ;DEC BL 6952 <1> ;JNZ short WT1 ; KEEP TRYING FOR A WHILE 6953 <1> 6954 <1> WT1_hi: 6955 00002CDF E461 <1> in al, SYS1 ; 61h (PORT_B) ; wait for lo to hi 6956 00002CE1 A810 <1> test al, 10h ; transition on memory 6957 00002CE3 75FA <1> jnz short WT1_hi ; refresh. 6958 <1> WT1_lo: 6959 00002CE5 E461 <1> in al, SYS1 ; 061h (PORT_B) 6960 00002CE7 A810 <1> test al, 10h 6961 00002CE9 74FA <1> jz short WT1_lo 6962 00002CEB E2E9 <1> loop WT1 6963 <1> ;;or bl, bl 6964 <1> ;;jz short WT2 6965 <1> ;;dec bl 6966 <1> ;;jmp short WT1 6967 <1> ;dec bl 6968 <1> ;jnz short WT1 6969 <1> 6970 00002CED C605[3F6E0000]80 <1> WT2: MOV byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR 6971 00002CF4 EB0E <1> JMP SHORT WT4 6972 00002CF6 C605[3F6E0000]00 <1> WT3: MOV byte [DISK_STATUS1],0 6973 00002CFD C605[376E0000]00 <1> MOV byte [HF_INT_FLAG],0 6974 00002D04 803D[3F6E0000]00 <1> WT4: CMP byte [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 6975 00002D0B C3 <1> RETn 6976 <1> 6977 <1> ;---------------------------------------- 6978 <1> ; WAIT FOR CONTROLLER NOT BUSY : 6979 <1> ;---------------------------------------- 6980 <1> NOT_BUSY: 6981 00002D0C FB <1> STI ; MAKE SURE INTERRUPTS ARE ON 6982 <1> ;PUSH eBX 6983 <1> ;SUB CX,CX ; SET INITIAL DELAY BEFORE TEST 6984 00002D0D 668B15[94680000] <1> mov DX, [HF_PORT] 6985 00002D14 80C207 <1> add dl, 7 ; Status port (HF_PORT+7) 6986 <1> ;MOV BL,DELAY_1 6987 <1> ; wait for 10 seconds 6988 <1> ;mov cx, WAIT_HDU_INT_LO ; 1615h 6989 <1> ;;mov bl, WAIT_HDU_INT_HI ; 05h 6990 <1> ;mov bl, WAIT_HDU_INT_HI + 1 6991 00002D17 B915160500 <1> mov ecx, WAIT_HDU_INT_LH ; 21/02/2015 6992 <1> ; 6993 <1> ;; mov byte [wait_count], 0 ; Reset wait counter 6994 <1> NB1: 6995 00002D1C EC <1> IN AL,DX ; CHECK STATUS 6996 <1> ;TEST AL,ST_BUSY 6997 00002D1D 2480 <1> and al, ST_BUSY 6998 <1> ;LOOPNZ NB1 6999 00002D1F 7410 <1> JZ short NB2 ; NOT BUSY--LETS GO 7000 <1> ;DEC BL 7001 <1> ;JNZ short NB1 ; KEEP TRYING FOR A WHILE 7002 <1> 7003 00002D21 E461 <1> NB1_hi: IN AL,SYS1 ; wait for hi to lo 7004 00002D23 A810 <1> TEST AL,010H ; transition on memory 7005 00002D25 75FA <1> JNZ SHORT NB1_hi ; refresh. 7006 00002D27 E461 <1> NB1_lo: IN AL,SYS1 7007 00002D29 A810 <1> TEST AL,010H 7008 00002D2B 74FA <1> JZ short NB1_lo 7009 00002D2D E2ED <1> LOOP NB1 7010 <1> ;dec bl 7011 <1> ;jnz short NB1 7012 <1> ; 7013 <1> ;; cmp byte [wait_count], 182 ; 10 seconds (182 timer ticks) 7014 <1> ;; jb short NB1 7015 <1> ; 7016 <1> ;MOV [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR 7017 <1> ;JMP SHORT NB3 7018 00002D2F B080 <1> mov al, TIME_OUT 7019 <1> NB2: 7020 <1> ;MOV byte [DISK_STATUS1],0 7021 <1> ;NB3: 7022 <1> ;POP eBX 7023 00002D31 A2[3F6E0000] <1> mov [DISK_STATUS1], al ;;; will be set after return 7024 <1> ;CMP byte [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 7025 00002D36 08C0 <1> or al, al ; (zf = 0 --> timeout) 7026 00002D38 C3 <1> RETn 7027 <1> 7028 <1> ;---------------------------------------- 7029 <1> ; WAIT FOR DATA REQUEST : 7030 <1> ;---------------------------------------- 7031 <1> WAIT_DRQ: 7032 <1> ;MOV CX,DELAY_3 7033 <1> ;MOV DX,HF_PORT+7 7034 00002D39 668B15[94680000] <1> mov dx, [HF_PORT] 7035 00002D40 80C207 <1> add dl, 7 7036 <1> ;;MOV bl, WAIT_HDU_DRQ_HI ; 0 7037 <1> ;MOV cx, WAIT_HDU_DRQ_LO ; 1000 (30 milli seconds) 7038 <1> ; (but it is written as 2000 7039 <1> ; micro seconds in ATORGS.ASM file 7040 <1> ; of Award Bios - 1999, D1A0622) 7041 00002D43 B9E8030000 <1> mov ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 7042 00002D48 EC <1> WQ_1: IN AL,DX ; GET STATUS 7043 00002D49 A808 <1> TEST AL,ST_DRQ ; WAIT FOR DRQ 7044 00002D4B 7516 <1> JNZ short WQ_OK 7045 <1> ;LOOP WQ_1 ; KEEP TRYING FOR A SHORT WHILE 7046 <1> WQ_hi: 7047 00002D4D E461 <1> IN AL,SYS1 ; wait for hi to lo 7048 00002D4F A810 <1> TEST AL,010H ; transition on memory 7049 00002D51 75FA <1> JNZ SHORT WQ_hi ; refresh. 7050 00002D53 E461 <1> WQ_lo: IN AL,SYS1 7051 00002D55 A810 <1> TEST AL,010H 7052 00002D57 74FA <1> JZ SHORT WQ_lo 7053 00002D59 E2ED <1> LOOP WQ_1 7054 <1> 7055 00002D5B C605[3F6E0000]80 <1> MOV byte [DISK_STATUS1],TIME_OUT ; ERROR 7056 00002D62 F9 <1> STC 7057 <1> WQ_OK: 7058 00002D63 C3 <1> RETn 7059 <1> ;WQ_OK: ;CLC 7060 <1> ; RETn 7061 <1> 7062 <1> ;---------------------------------------- 7063 <1> ; CHECK FIXED DISK STATUS : 7064 <1> ;---------------------------------------- 7065 <1> CHECK_STATUS: 7066 00002D64 E813000000 <1> CALL CHECK_ST ; CHECK THE STATUS BYTE 7067 00002D69 7509 <1> JNZ short CHECK_S1 ; AN ERROR WAS FOUND 7068 00002D6B A801 <1> TEST AL,ST_ERROR ; WERE THERE ANY OTHER ERRORS 7069 00002D6D 7405 <1> JZ short CHECK_S1 ; NO ERROR REPORTED 7070 00002D6F E847000000 <1> CALL CHECK_ER ; ERROR REPORTED 7071 <1> CHECK_S1: 7072 00002D74 803D[3F6E0000]00 <1> CMP byte [DISK_STATUS1],0 ; SET STATUS FOR CALLER 7073 00002D7B C3 <1> RETn 7074 <1> 7075 <1> ;---------------------------------------- 7076 <1> ; CHECK FIXED DISK STATUS BYTE : 7077 <1> ;---------------------------------------- 7078 <1> CHECK_ST: 7079 <1> ;MOV DX,HF_PORT+7 ; GET THE STATUS 7080 00002D7C 668B15[94680000] <1> mov dx, [HF_PORT] 7081 00002D83 80C207 <1> add dl, 7 7082 00002D86 EC <1> IN AL,DX 7083 00002D87 A2[356E0000] <1> MOV [HF_STATUS],AL 7084 00002D8C B400 <1> MOV AH,0 7085 00002D8E A880 <1> TEST AL,ST_BUSY ; IF STILL BUSY 7086 00002D90 751A <1> JNZ short CKST_EXIT ; REPORT OK 7087 00002D92 B4CC <1> MOV AH,WRITE_FAULT 7088 00002D94 A820 <1> TEST AL,ST_WRT_FLT ; CHECK FOR WRITE FAULT 7089 00002D96 7514 <1> JNZ short CKST_EXIT 7090 00002D98 B4AA <1> MOV AH,NOT_RDY 7091 00002D9A A840 <1> TEST AL,ST_READY ; CHECK FOR NOT READY 7092 00002D9C 740E <1> JZ short CKST_EXIT 7093 00002D9E B440 <1> MOV AH,BAD_SEEK 7094 00002DA0 A810 <1> TEST AL,ST_SEEK_COMPL ; CHECK FOR SEEK NOT COMPLETE 7095 00002DA2 7408 <1> JZ short CKST_EXIT 7096 00002DA4 B411 <1> MOV AH,DATA_CORRECTED 7097 00002DA6 A804 <1> TEST AL,ST_CORRCTD ; CHECK FOR CORRECTED ECC 7098 00002DA8 7502 <1> JNZ short CKST_EXIT 7099 00002DAA B400 <1> MOV AH,0 7100 <1> CKST_EXIT: 7101 00002DAC 8825[3F6E0000] <1> MOV [DISK_STATUS1],AH ; SET ERROR FLAG 7102 00002DB2 80FC11 <1> CMP AH,DATA_CORRECTED ; KEEP GOING WITH DATA CORRECTED 7103 00002DB5 7403 <1> JZ short CKST_EX1 7104 00002DB7 80FC00 <1> CMP AH,0 7105 <1> CKST_EX1: 7106 00002DBA C3 <1> RETn 7107 <1> 7108 <1> ;---------------------------------------- 7109 <1> ; CHECK FIXED DISK ERROR REGISTER : 7110 <1> ;---------------------------------------- 7111 <1> CHECK_ER: 7112 <1> ;MOV DX, HF_PORT+1 ; GET THE ERROR REGISTER 7113 00002DBB 668B15[94680000] <1> mov dx, [HF_PORT] ; 7114 00002DC2 FEC2 <1> inc dl 7115 00002DC4 EC <1> IN AL,DX 7116 00002DC5 A2[366E0000] <1> MOV [HF_ERROR],AL 7117 00002DCA 53 <1> PUSH eBX ; 21/02/2015 7118 00002DCB B908000000 <1> MOV eCX,8 ; TEST ALL 8 BITS 7119 00002DD0 D0E0 <1> CK1: SHL AL,1 ; MOVE NEXT ERROR BIT TO CARRY 7120 00002DD2 7202 <1> JC short CK2 ; FOUND THE ERROR 7121 00002DD4 E2FA <1> LOOP CK1 ; KEEP TRYING 7122 00002DD6 BB[88680000] <1> CK2: MOV eBX, ERR_TBL ; COMPUTE ADDRESS OF 7123 00002DDB 01CB <1> ADD eBX,eCX ; ERROR CODE 7124 <1> ;;MOV AH,BYTE [CS:BX] ; GET ERROR CODE 7125 <1> ;mov ah, [bx] 7126 00002DDD 8A23 <1> mov ah, [ebx] ; 21/02/2015 7127 00002DDF 8825[3F6E0000] <1> CKEX: MOV [DISK_STATUS1],AH ; SAVE ERROR CODE 7128 00002DE5 5B <1> POP eBX 7129 00002DE6 80FC00 <1> CMP AH,0 7130 00002DE9 C3 <1> RETn 7131 <1> 7132 <1> ;-------------------------------------------------------- 7133 <1> ; CHECK_DMA : 7134 <1> ; -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL : 7135 <1> ; FIT WITHOUT SEGMENT OVERFLOW. : 7136 <1> ; -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X : 7137 <1> ; -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE) : 7138 <1> ; -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H) : 7139 <1> ; -ERROR OTHERWISE : 7140 <1> ;-------------------------------------------------------- 7141 <1> CHECK_DMA: 7142 <1> ;PUSH AX ; SAVE REGISTERS 7143 <1> ; 05/12/2021 7144 00002DEA 50 <1> push eax 7145 00002DEB 66B80080 <1> MOV AX,8000H ; AH = MAX # SECTORS AL = MAX OFFSET 7146 00002DEF F645FE02 <1> TEST byte [CMD_BLOCK+6],ECC_MODE 7147 00002DF3 7404 <1> JZ short CKD1 7148 00002DF5 66B8047F <1> MOV AX,7F04H ; ECC IS 4 MORE BYTES 7149 00002DF9 3A65F9 <1> CKD1: CMP AH, [CMD_BLOCK+1] ; NUMBER OF SECTORS 7150 00002DFC 7706 <1> JA short CKDOK ; IT WILL FIT 7151 00002DFE 7207 <1> JB short CKDERR ; TOO MANY 7152 00002E00 38D8 <1> CMP AL,BL ; CHECK OFFSET ON MAX SECTORS 7153 00002E02 7203 <1> JB short CKDERR ; ERROR 7154 00002E04 F8 <1> CKDOK: CLC ; CLEAR CARRY 7155 <1> ;POP AX 7156 <1> ; 05/12/2021 7157 00002E05 58 <1> pop eax 7158 00002E06 C3 <1> RETn ; NORMAL RETURN 7159 00002E07 F9 <1> CKDERR: STC ; INDICATE ERROR 7160 00002E08 C605[3F6E0000]09 <1> MOV byte [DISK_STATUS1],DMA_BOUNDARY 7161 <1> ;POP AX 7162 <1> ; 05/12/2021 7163 00002E0F 58 <1> pop eax 7164 00002E10 C3 <1> RETn 7165 <1> 7166 <1> ;---------------------------------------- 7167 <1> ; SET UP ES:BX-> DISK PARMS : 7168 <1> ;---------------------------------------- 7169 <1> 7170 <1> ; INPUT -> DL = 0 based drive number 7171 <1> ; OUTPUT -> ES:BX = disk parameter table address 7172 <1> 7173 <1> GET_VEC: 7174 <1> ;SUB AX,AX ; GET DISK PARAMETER ADDRESS 7175 <1> ;MOV ES,AX 7176 <1> ;TEST DL,1 7177 <1> ;JZ short GV_0 7178 <1> ; LES BX,[HF1_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 7179 <1> ; JMP SHORT GV_EXIT 7180 <1> ;GV_0: 7181 <1> ; LES BX,[HF_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 7182 <1> ; 7183 <1> ;xor bh, bh 7184 00002E11 31DB <1> xor ebx, ebx 7185 00002E13 88D3 <1> mov bl, dl 7186 <1> ;;02/01/2015 7187 <1> ;;shl bl, 1 ; port address offset 7188 <1> ;;mov ax, [bx+hd_ports] ; Base port address (1F0h, 170h) 7189 <1> ;;shl bl, 1 ; dpt pointer offset 7190 00002E15 C0E302 <1> shl bl, 2 ;; 7191 <1> ;add bx, HF_TBL_VEC ; Disk parameter table pointer 7192 00002E18 81C3[446E0000] <1> add ebx, HF_TBL_VEC ; 21/02/2015 7193 <1> ;push word [bx+2] ; dpt segment 7194 <1> ;pop es 7195 <1> ;mov bx, [bx] ; dpt offset 7196 00002E1E 8B1B <1> mov ebx, [ebx] 7197 <1> ;GV_EXIT: 7198 00002E20 C3 <1> RETn 7199 <1> 7200 <1> ; 05/12/2021 - Retro UNIX 386 v1.2 7201 <1> hdc1_int: ; 21/02/2015 7202 <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL 14 ) ---------------------- 7203 <1> ; : 7204 <1> ; FIXED DISK INTERRUPT ROUTINE : 7205 <1> ; : 7206 <1> ;---------------------------------------------------------------- 7207 <1> 7208 <1> ; 22/12/2014 7209 <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT) 7210 <1> ; '11/15/85' 7211 <1> ; AWARD BIOS 1999 (D1A0622) 7212 <1> ; Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1) 7213 <1> 7214 <1> ;int_76h: 7215 <1> HD_INT: 7216 <1> ;push ax 7217 <1> ; 05/12/2021 7218 00002E21 50 <1> push eax 7219 00002E22 1E <1> push ds 7220 <1> ;CALL DDS 7221 <1> ; 21/02/2015 (32 bit, 386 pm modification) 7222 00002E23 66B81000 <1> mov ax, KDATA 7223 00002E27 8ED8 <1> mov ds, ax 7224 <1> ; 7225 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 7226 <1> ;mov byte [CS:HF_INT_FLAG], 0FFh 7227 00002E29 C605[376E0000]FF <1> mov byte [HF_INT_FLAG], 0FFh 7228 <1> ; 7229 <1> ;push dx 7230 <1> ; 05/12/2021 7231 00002E30 52 <1> push edx 7232 00002E31 66BAF701 <1> mov dx, HDC1_BASEPORT+7 ; Status Register (1F7h) 7233 <1> ; Clear Controller 7234 <1> Clear_IRQ1415: ; (Award BIOS - 1999) 7235 00002E35 EC <1> in al, dx ; 7236 <1> ;pop dx 7237 <1> ; 05/12/2021 7238 00002E36 5A <1> pop edx 7239 <1> NEWIODELAY 2138 00002E37 E6EB <2> out 0EBh,al 7240 <1> ; 7241 00002E39 B020 <1> MOV AL,EOI ; NON-SPECIFIC END OF INTERRUPT 7242 00002E3B E6A0 <1> OUT INTB00,AL ; FOR CONTROLLER #2 7243 <1> ;JMP $+2 ; WAIT 7244 <1> NEWIODELAY 2138 00002E3D E6EB <2> out 0EBh,al 7245 00002E3F E620 <1> OUT INTA00,AL ; FOR CONTROLLER #1 7246 00002E41 1F <1> pop ds 7247 <1> ;STI ; RE-ENABLE INTERRUPTS 7248 <1> ;MOV AX,9100H ; DEVICE POST 7249 <1> ;INT 15H ; INTERRUPT 7250 <1> irq15_iret: ; 25/02/2015 7251 <1> ;pop ax 7252 <1> ; 05/12/2021 7253 00002E42 58 <1> pop eax 7254 00002E43 CF <1> iretd ; RETURN FROM INTERRUPT 7255 <1> 7256 <1> ; 05/12/2021 - Retro UNIX 386 v1.2 7257 <1> hdc2_int: ; 21/02/2015 7258 <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL 15 ) +++++++++++++++++++++ 7259 <1> ; : 7260 <1> ; FIXED DISK INTERRUPT ROUTINE : 7261 <1> ; : 7262 <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7263 <1> 7264 <1> ;int_77h: 7265 <1> HD1_INT: 7266 <1> ;push ax 7267 <1> ; 05/12/2021 7268 00002E44 50 <1> push eax 7269 <1> ; Check if that is a spurious IRQ (from slave PIC) 7270 <1> ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 7271 00002E45 B00B <1> mov al, 0Bh ; In-Service Register 7272 00002E47 E6A0 <1> out 0A0h, al 7273 00002E49 EB00 <1> jmp short $+2 7274 00002E4B EB00 <1> jmp short $+2 7275 00002E4D E4A0 <1> in al, 0A0h 7276 00002E4F 2480 <1> and al, 80h ; bit 7 (is it real IRQ 15 or fake?) 7277 00002E51 74EF <1> jz short irq15_iret ; Fake (spurious)IRQ, do not send EOI) 7278 <1> ; 7279 00002E53 1E <1> push ds 7280 <1> ;CALL DDS 7281 <1> ; 21/02/2015 (32 bit, 386 pm modification) 7282 00002E54 66B81000 <1> mov ax, KDATA 7283 00002E58 8ED8 <1> mov ds, ax 7284 <1> ; 7285 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 7286 <1> ;or byte [CS:HF_INT_FLAG],0C0h 7287 00002E5A 800D[376E0000]C0 <1> or byte [HF_INT_FLAG], 0C0h 7288 <1> ; 7289 <1> ;push dx 7290 <1> ; 05/12/2021 7291 00002E61 52 <1> push edx 7292 00002E62 66BA7701 <1> mov dx, HDC2_BASEPORT+7 ; Status Register (177h) 7293 <1> ; Clear Controller (Award BIOS 1999) 7294 00002E66 EBCD <1> jmp short Clear_IRQ1415 7295 <1> 7296 <1> ;%include 'diskdata.inc' ; 11/03/2015 7297 <1> ;%include 'diskbss.inc' ; 11/03/2015 7298 <1> 7299 <1> ;//////////////////////////////////////////////////////////////////// 7300 <1> ;; END OF DISK I/O SYTEM /// 2073 %include 'memory.s' ; 09/03/2015 2074 <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020 2075 <1> ; Last Modification: 31/12/2021 (Retro UNIX 386 v1.2) 2076 <1> ; ---------------------------------------------------------------------------- 2077 <1> ; 2078 <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) 2079 <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC 2080 <1> ; 18/10/2015 (!not completed!) 2081 <1> ; 2082 <1> ; Source code for NASM - Netwide Assembler (2.11) 2083 <1> 2084 <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) /////////////// 2085 <1> 2086 <1> ;;04/11/2014 (unix386.s) 2087 <1> ;PDE_A_PRESENT equ 1 ; Present flag for PDE 2088 <1> ;PDE_A_WRITE equ 2 ; Writable (write permission) flag 2089 <1> ;PDE_A_USER equ 4 ; User (non-system/kernel) page flag 2090 <1> ;; 2091 <1> ;PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 2092 <1> ;PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 2093 <1> ;PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 2094 <1> ;PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 2095 <1> 2096 <1> ; 27/04/2015 2097 <1> ; 09/03/2015 2098 <1> PAGE_SIZE equ 4096 ; page size in bytes 2099 <1> PAGE_SHIFT equ 12 ; page table shift count 2100 <1> PAGE_D_SHIFT equ 22 ; 12+10 ; page directory shift count 2101 <1> PAGE_OFF equ 0FFFh ; 12 bit byte offset in page frame 2102 <1> PTE_MASK equ 03FFh ; page table entry mask 2103 <1> PTE_DUPLICATED equ 200h ; duplicated page sign (AVL bit 0) 2104 <1> PDE_A_CLEAR equ 0F000h ; to clear PDE attribute bits 2105 <1> PTE_A_CLEAR equ 0F000h ; to clear PTE attribute bits 2106 <1> LOGIC_SECT_SIZE equ 512 ; logical sector size 2107 <1> ERR_MAJOR_PF equ 0E0h ; major error: page fault 2108 <1> ; 15/10/2016 (TRDOS 386 v2) 2109 <1> ERR_MINOR_IM equ 4 ;15/10/2016 (1->4); insufficient (out of) memory 2110 <1> ERR_MINOR_PV equ 6 ;15/10/2016 (3->6); protection violation 2111 <1> SWP_DISK_READ_ERR equ 40 2112 <1> SWP_DISK_NOT_PRESENT_ERR equ 41 2113 <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42 2114 <1> SWP_NO_FREE_SPACE_ERR equ 43 2115 <1> SWP_DISK_WRITE_ERR equ 44 2116 <1> SWP_NO_PAGE_TO_SWAP_ERR equ 45 2117 <1> PTE_A_ACCESS_BIT equ 5 ; Bit 5 (accessed flag) 2118 <1> SECTOR_SHIFT equ 3 ; sector shift (to convert page block number) 2119 <1> ; 10/06/2021 (Retro UNIX 386 v2) 2120 <1> ; 12/07/2016 (TRDOS 386 v2) 2121 <1> PTE_SHARED equ 400h ; AVL bit 1, direct memory access bit 2122 <1> ; (Indicates that the page is not allocated 2123 <1> ; for the process, it is a shared or system 2124 <1> ; page, it must not be deallocated!) 2125 <1> ; 14/12/2020 2126 <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.) 2127 <1> PDE_EXTERNAL equ 400h ; Page directory entry for external memory blocks 2128 <1> PTE_EXTERNAL equ 400h ; Allocated kernel pages for Linear Frame Buffer 2129 <1> ; (Out of memory allocation table) 2130 <1> ; 2131 <1> ;; Retro Unix 386 v1 - paging method/principles 2132 <1> ;; 2133 <1> ;; 10/10/2014 2134 <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES 2135 <1> ;; 2136 <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map 2137 <1> ;; (virtual address = physical address) 2138 <1> ;; KERNEL PAGE TABLES: 2139 <1> ;; Kernel page directory and all page tables are 2140 <1> ;; on memory as initialized, as equal to physical memory 2141 <1> ;; layout. Kernel pages can/must not be swapped out/in. 2142 <1> ;; 2143 <1> ;; what for: User pages may be swapped out, when accessing 2144 <1> ;; a page in kernel/system mode, if it would be swapped out, 2145 <1> ;; kernel would have to swap it in! But it is also may be 2146 <1> ;; in use by a user process. (In system/kernel mode 2147 <1> ;; kernel can access all memory pages even if they are 2148 <1> ;; reserved/allocated for user processes. Swap out/in would 2149 <1> ;; cause conflicts.) 2150 <1> ;; 2151 <1> ;; As result of these conditions, 2152 <1> ;; all kernel pages must be initialized as equal to 2153 <1> ;; physical layout for preventing page faults. 2154 <1> ;; Also, calling "allocate page" procedure after 2155 <1> ;; a page fault can cause another page fault (double fault) 2156 <1> ;; if all kernel page tables would not be initialized. 2157 <1> ;; 2158 <1> ;; [first_page] = Beginning of users space, as offset to 2159 <1> ;; memory allocation table. (double word aligned) 2160 <1> ;; 2161 <1> ;; [next_page] = first/next free space to be searched 2162 <1> ;; as offset to memory allocation table. (dw aligned) 2163 <1> ;; 2164 <1> ;; [last_page] = End of memory (users space), as offset 2165 <1> ;; to memory allocation table. (double word aligned) 2166 <1> ;; 2167 <1> ;; USER PAGE TABLES: 2168 <1> ;; Demand paging (& 'copy on write' allocation method) ... 2169 <1> ;; 'ready only' marked copies of the 2170 <1> ;; parent process's page table entries (for 2171 <1> ;; same physical memory). 2172 <1> ;; (A page will be copied to a new page after 2173 <1> ;; if it causes R/W page fault.) 2174 <1> ;; 2175 <1> ;; Every user process has own (different) 2176 <1> ;; page directory and page tables. 2177 <1> ;; 2178 <1> ;; Code starts at virtual address 0, always. 2179 <1> ;; (Initial value of EIP is 0 in user mode.) 2180 <1> ;; (Programs can be written/developed as simple 2181 <1> ;; flat memory programs.) 2182 <1> ;; 2183 <1> ;; MEMORY ALLOCATION STRATEGY: 2184 <1> ;; Memory page will be allocated by kernel only 2185 <1> ;; (in kernel/system mode only). 2186 <1> ;; * After a 2187 <1> ;; - 'not present' page fault 2188 <1> ;; - 'writing attempt on read only page' page fault 2189 <1> ;; * For loading (opening, reading) a file or disk/drive 2190 <1> ;; * As responce to 'allocate additional memory blocks' 2191 <1> ;; request by running process. 2192 <1> ;; * While creating a process, allocating a new buffer, 2193 <1> ;; new page tables etc. 2194 <1> ;; 2195 <1> ;; At first, 2196 <1> ;; - 'allocate page' procedure will be called; 2197 <1> ;, if it will return with a valid (>0) physical address 2198 <1> ;; (that means the relevant M.A.T. bit has been RESET) 2199 <1> ;; relevant memory page/block will be cleared (zeroed). 2200 <1> ;; - 'allocate page' will be called for allocating page 2201 <1> ;; directory, page table and running space (data/code). 2202 <1> ;; - every successful 'allocate page' call will decrease 2203 <1> ;; 'free_pages' count (pointer). 2204 <1> ;; - 'out of (insufficient) memory error' will be returned 2205 <1> ;; if 'free_pages' points to a ZERO. 2206 <1> ;; - swapping out and swapping in (if it is not a new page) 2207 <1> ;; procedures will be called as responce to 'out of memory' 2208 <1> ;; error except errors caused by attribute conflicts. 2209 <1> ;; (swapper functions) 2210 <1> ;; 2211 <1> ;; At second, 2212 <1> ;; - page directory entry will be updated then page table 2213 <1> ;; entry will be updated. 2214 <1> ;; 2215 <1> ;; MEMORY ALLOCATION TABLE FORMAT: 2216 <1> ;; - M.A.T. has a size according to available memory as 2217 <1> ;; follows: 2218 <1> ;; - 1 (allocation) bit per 1 page (4096 bytes) 2219 <1> ;; - a bit with value of 0 means allocated page 2220 <1> ;; - a bit with value of 1 means a free page 2221 <1> ;, - 'free_pages' pointer holds count of free pages 2222 <1> ;; depending on M.A.T. 2223 <1> ;; (NOTE: Free page count will not be checked 2224 <1> ;; again -on M.A.T.- after initialization. 2225 <1> ;; Kernel will trust on initial count.) 2226 <1> ;, - 'free_pages' count will be decreased by allocation 2227 <1> ;; and it will be increased by deallocation procedures. 2228 <1> ;; 2229 <1> ;; - Available memory will be calculated during 2230 <1> ;; the kernel's initialization stage (in real mode). 2231 <1> ;; Memory allocation table and kernel page tables 2232 <1> ;; will be formatted/sized as result of available 2233 <1> ;; memory calculation before paging is enabled. 2234 <1> ;; 2235 <1> ;; For 4GB Available/Present Memory: (max. possible memory size) 2236 <1> ;; - Memory Allocation Table size will be 128 KB. 2237 <1> ;; - Memory allocation for kernel page directory size 2238 <1> ;; is always 4 KB. (in addition to total allocation size 2239 <1> ;; for page tables) 2240 <1> ;; - Memory allocation for kernel page tables (1024 tables) 2241 <1> ;; is 4 MB (1024*4*1024 bytes). 2242 <1> ;; - User (available) space will be started 2243 <1> ;; at 6th MB of the memory (after 1MB+4MB). 2244 <1> ;; - The first 640 KB is for kernel's itself plus 2245 <1> ;; memory allocation table and kernel's page directory 2246 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 2247 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 2248 <1> ;; for buffers. 2249 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 2250 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 2251 <1> ;; - Kernel page tables start at 100000h (2nd MB) 2252 <1> ;; 2253 <1> ;; For 1GB Available Memory: 2254 <1> ;; - Memory Allocation Table size will be 32 KB. 2255 <1> ;; - Memory allocation for kernel page directory size 2256 <1> ;; is always 4 KB. (in addition to total allocation size 2257 <1> ;; for page tables) 2258 <1> ;; - Memory allocation for kernel page tables (256 tables) 2259 <1> ;; is 1 MB (256*4*1024 bytes). 2260 <1> ;; - User (available) space will be started 2261 <1> ;; at 3th MB of the memory (after 1MB+1MB). 2262 <1> ;; - The first 640 KB is for kernel's itself plus 2263 <1> ;; memory allocation table and kernel's page directory 2264 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 2265 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 2266 <1> ;; for buffers. 2267 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 2268 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 2269 <1> ;; - Kernel page tables start at 100000h (2nd MB). 2270 <1> ;; 2271 <1> ;; 2272 <1> 2273 <1> ;;************************************************************************************ 2274 <1> ;; 2275 <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle) 2276 <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015) 2277 <1> 2278 <1> ;; Main factor: "sys fork" system call 2279 <1> ;; 2280 <1> ;; FORK 2281 <1> ;; |----> parent - duplicated PTEs, read only pages 2282 <1> ;; writable pages ---->| 2283 <1> ;; |----> child - duplicated PTEs, read only pages 2284 <1> ;; 2285 <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 2286 <1> ;; 2287 <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set) 2288 <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9) 2289 <1> ;; -while R/W bit is 0-. 2290 <1> ;; 2291 <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process): 2292 <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 2293 <1> ;; as duplicated PTE bit -AVL bit 0, PTE bit 9- are reset/clear. 2294 <1> ;; # Then Parent's Page Table is copied to Child's Page Table. 2295 <1> ;; # Child's Page Table Entries are updated as duplicated child bit 2296 <1> ;; -AVL bit 0, PTE bit 9- is set. 2297 <1> ;; 2298 <1> ;; Duplicate page tables with read only pages (several sys fork system calls): 2299 <1> ;; # Parent's read only pages are copied to new child pages. 2300 <1> ;; Parent's PTE attributes are not changed. 2301 <1> ;; (Because, there is another parent-child fork before this fork! We must not 2302 <1> ;; destroy/mix previous fork result). 2303 <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 2304 <1> ;; read only pages) are set as writable (while duplicated PTE bit is clear). 2305 <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 2306 <1> ;; as read only, (while) duplicated PTE bit is reset (clear). 2307 <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 2308 <1> ;; as Child's Page Table Entries without copying actual page. 2309 <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 2310 <1> ;; pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set. 2311 <1> ;; 2312 <1> ;; !? WHAT FOR (duplication after duplication): 2313 <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init) 2314 <1> ;; program/executable code continues from specified location as child process, 2315 <1> ;; returns back previous code location as parent process, every child after 2316 <1> ;; every sys fork uses last image of code and data just prior the fork. 2317 <1> ;; Even if the parent code changes data, the child will not see the changed data 2318 <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB) 2319 <1> ;; was copied to child's process segment (all of code and data) according to 2320 <1> ;; original UNIX v1 which copies all of parent process code and data -core- 2321 <1> ;; to child space -core- but swaps that core image -of child- on to disk. 2322 <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core 2323 <1> ;; (complete running image of parent process) to the child process; 2324 <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 2325 <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork, 2326 <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes 2327 <1> ;; a new/fresh core -running space-, by clearing all code/data content). 2328 <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write 2329 <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 2330 <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and 2331 <1> ;; new/fresh pages will be used to load and run new executable/program. 2332 <1> ;; That is what for i have preferred "copy on write", "duplication" method 2333 <1> ;; for sharing same read only pages between parent and child processes. 2334 <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 2335 <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 2336 <1> ;; and it's child processes; otherwise parent process would destroy data belongs 2337 <1> ;; to its child or vice versa; or some pages would remain unclaimed 2338 <1> ;; -deallocation problem-. 2339 <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 2340 <1> ;; 2341 <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 2342 <1> ;; # Page fault handler will do those: 2343 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 2344 <1> ;; - If it is reset/clear, there is a child uses same page. 2345 <1> ;; - Parent's read only page -previous page- is copied to a new writable page. 2346 <1> ;; - Parent's PTE is updated as writable page, as unique page (AVL=0) 2347 <1> ;; - (Page fault handler whill check this PTE later, if child process causes to 2348 <1> ;; page fault due to write attempt on read only page. Of course, the previous 2349 <1> ;; read only page will be converted to writable and unique page which belongs 2350 <1> ;; to child process.) 2351 <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 2352 <1> ;; # Page fault handler will do those: 2353 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 2354 <1> ;; - If it is set, there is a parent uses -or was using- same page. 2355 <1> ;; - Same PTE address within parent's page table is checked if it has same page 2356 <1> ;; address or not. 2357 <1> ;; - If parent's PTE has same address, child will continue with a new writable page. 2358 <1> ;; Parent's PTE will point to same (previous) page as writable, unique (AVL=0). 2359 <1> ;; - If parent's PTE has different address, child will continue with it's 2360 <1> ;; own/same page but read only flag (0) will be changed to writable flag (1) and 2361 <1> ;; 'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 2362 <1> ;; 2363 <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables 2364 <1> ;; will be set as writable (and unique) in case of child process was using 2365 <1> ;; same pages with duplicated child PTE sign... Depending on sys fork and 2366 <1> ;; duplication method details, it is not possible multiple child processes 2367 <1> ;; were using same page with duplicated PTEs. 2368 <1> ;; 2369 <1> ;;************************************************************************************ 2370 <1> 2371 <1> ;; 08/10/2014 2372 <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft 2373 <1> ;; by Erdogan Tan (Based on KolibriOS 'memory.inc') 2374 <1> 2375 <1> ;; 'allocate_page' code is derived and modified from KolibriOS 2376 <1> ;; 'alloc_page' procedure in 'memory.inc' 2377 <1> ;; (25/08/2014, Revision: 5057) file 2378 <1> ;; by KolibriOS Team (2004-2012) 2379 <1> 2380 <1> allocate_page: 2381 <1> ; 17/04/2021 - Retro UNIX 386 v2 2382 <1> ; (temporary modifications) 2383 <1> ; 01/07/2015 2384 <1> ; 05/05/2015 2385 <1> ; 30/04/2015 2386 <1> ; 16/10/2014 2387 <1> ; 08/10/2014 2388 <1> ; 09/09/2014 (Retro UNIX 386 v1 - beginning) 2389 <1> ; 2390 <1> ; INPUT -> none 2391 <1> ; 2392 <1> ; OUTPUT -> 2393 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 2394 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is RESET) 2395 <1> ; 2396 <1> ; CF = 1 and EAX = 0 2397 <1> ; if there is not a free page to be allocated 2398 <1> ; 2399 <1> ; Modified Registers -> none (except EAX) 2400 <1> ; 2401 00002E68 A1[B06D0000] <1> mov eax, [free_pages] 2402 00002E6D 21C0 <1> and eax, eax 2403 00002E6F 7438 <1> jz short out_of_memory 2404 <1> ; 2405 00002E71 53 <1> push ebx 2406 00002E72 51 <1> push ecx 2407 <1> ; 2408 00002E73 BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table offset 2409 00002E78 89D9 <1> mov ecx, ebx 2410 <1> ; NOTE: 32 (first_page) is initial 2411 <1> ; value of [next_page]. 2412 <1> ; It points to the first available 2413 <1> ; page block for users (ring 3) ... 2414 <1> ; (MAT offset 32 = 1024/32) 2415 <1> ; (at the of the first 4 MB) 2416 00002E7A 031D[B46D0000] <1> add ebx, [next_page] ; Free page searching starts from here 2417 <1> ; next_free_page >> 5 2418 00002E80 030D[B86D0000] <1> add ecx, [last_page] ; Free page searching ends here 2419 <1> ; (total_pages - 1) >> 5 2420 <1> al_p_scan: 2421 00002E86 39CB <1> cmp ebx, ecx 2422 00002E88 770A <1> ja short al_p_notfound 2423 <1> ; 2424 <1> ; 01/07/2015 2425 <1> ; AMD64 Architecture Programmer’s Manual 2426 <1> ; Volume 3: 2427 <1> ; General-Purpose and System Instructions 2428 <1> ; 2429 <1> ; BSF - Bit Scan Forward 2430 <1> ; 2431 <1> ; Searches the value in a register or a memory location 2432 <1> ; (second operand) for the least-significant set bit. 2433 <1> ; If a set bit is found, the instruction clears the zero flag (ZF) 2434 <1> ; and stores the index of the least-significant set bit in a destination 2435 <1> ; register (first operand). If the second operand contains 0, 2436 <1> ; the instruction sets ZF to 1 and does not change the contents of the 2437 <1> ; destination register. The bit index is an unsigned offset from bit 0 2438 <1> ; of the searched value 2439 <1> ; 2440 00002E8A 0FBC03 <1> bsf eax, [ebx] ; Scans source operand for first bit set (1). 2441 <1> ; Clear ZF if a bit is found set (1) and 2442 <1> ; loads the destination with an index to 2443 <1> ; first set bit. (0 -> 31) 2444 <1> ; Sets ZF to 1 if no bits are found set. 2445 00002E8D 751C <1> jnz short al_p_found ; ZF = 0 -> a free page has been found 2446 <1> ; 2447 <1> ; NOTE: a Memory Allocation Table bit 2448 <1> ; with value of 1 means 2449 <1> ; the corresponding page is free 2450 <1> ; (Retro UNIX 386 v1 feature only!) 2451 00002E8F 83C304 <1> add ebx, 4 2452 <1> ; We return back for searching next page block 2453 <1> ; NOTE: [free_pages] is not ZERO; so, 2454 <1> ; we always will find at least 1 free page here. 2455 00002E92 EBF2 <1> jmp short al_p_scan 2456 <1> ; 2457 <1> al_p_notfound: 2458 00002E94 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 2459 00002E9A 890D[B46D0000] <1> mov [next_page], ecx ; next/first free page = last page 2460 <1> ; (deallocate_page procedure will change it) 2461 00002EA0 31C0 <1> xor eax, eax 2462 00002EA2 A3[B06D0000] <1> mov [free_pages], eax ; 0 2463 00002EA7 59 <1> pop ecx 2464 00002EA8 5B <1> pop ebx 2465 <1> ; 2466 <1> ; 17/04/2021 2467 <1> ; ('swap_out' procedure call is disabled as temporary) 2468 <1> 2469 <1> out_of_memory: 2470 <1> ; call swap_out 2471 <1> ; jnc short al_p_ok ; [free_pages] = 0, re-allocation by swap_out 2472 <1> ; ; 2473 <1> ; sub eax, eax ; 0 2474 00002EA9 F9 <1> stc 2475 00002EAA C3 <1> retn 2476 <1> 2477 <1> al_p_found: 2478 00002EAB 89D9 <1> mov ecx, ebx 2479 00002EAD 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 2480 00002EB3 890D[B46D0000] <1> mov [next_page], ecx ; Set first free page searching start 2481 <1> ; address/offset (to the next) 2482 00002EB9 FF0D[B06D0000] <1> dec dword [free_pages] ; 1 page has been allocated (X = X-1) 2483 <1> ; 2484 00002EBF 0FB303 <1> btr [ebx], eax ; The destination bit indexed by the source value 2485 <1> ; is copied into the Carry Flag and then cleared 2486 <1> ; in the destination. 2487 <1> ; 2488 <1> ; Reset the bit which is corresponding to the 2489 <1> ; (just) allocated page. 2490 <1> ; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages) 2491 00002EC2 C1E103 <1> shl ecx, 3 ; (page block offset * 32) + page index 2492 00002EC5 01C8 <1> add eax, ecx ; = page number 2493 00002EC7 C1E00C <1> shl eax, 12 ; physical address of the page (flat/real value) 2494 <1> ; EAX = physical address of memory page 2495 <1> ; 2496 <1> ; NOTE: The relevant page directory and page table entry will be updated 2497 <1> ; according to this EAX value... 2498 00002ECA 59 <1> pop ecx 2499 00002ECB 5B <1> pop ebx 2500 <1> al_p_ok: 2501 00002ECC C3 <1> retn 2502 <1> 2503 <1> make_page_dir: 2504 <1> ; 18/04/2015 2505 <1> ; 12/04/2015 2506 <1> ; 23/10/2014 2507 <1> ; 16/10/2014 2508 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2509 <1> ; 2510 <1> ; INPUT -> 2511 <1> ; none 2512 <1> ; OUTPUT -> 2513 <1> ; (EAX = 0) 2514 <1> ; cf = 1 -> insufficient (out of) memory error 2515 <1> ; cf = 0 -> 2516 <1> ; u.pgdir = page directory (physical) address of the current 2517 <1> ; process/user. 2518 <1> ; 2519 <1> ; Modified Registers -> EAX 2520 <1> ; 2521 00002ECD E896FFFFFF <1> call allocate_page 2522 00002ED2 7216 <1> jc short mkpd_error 2523 <1> ; 2524 00002ED4 A3[046F0000] <1> mov [u.pgdir], eax ; Page dir address for current user/process 2525 <1> ; (Physical address) 2526 <1> clear_page: 2527 <1> ; 18/04/2015 2528 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2529 <1> ; 2530 <1> ; INPUT -> 2531 <1> ; EAX = physical address of the page 2532 <1> ; OUTPUT -> 2533 <1> ; all bytes of the page will be cleared 2534 <1> ; 2535 <1> ; Modified Registers -> none 2536 <1> ; 2537 00002ED9 57 <1> push edi 2538 00002EDA 51 <1> push ecx 2539 00002EDB 50 <1> push eax 2540 00002EDC B900040000 <1> mov ecx, PAGE_SIZE / 4 2541 00002EE1 89C7 <1> mov edi, eax 2542 00002EE3 31C0 <1> xor eax, eax 2543 00002EE5 F3AB <1> rep stosd 2544 00002EE7 58 <1> pop eax 2545 00002EE8 59 <1> pop ecx 2546 00002EE9 5F <1> pop edi 2547 <1> mkpd_error: 2548 <1> mkpt_error: 2549 00002EEA C3 <1> retn 2550 <1> 2551 <1> make_page_table: 2552 <1> ; 23/06/2015 2553 <1> ; 18/04/2015 2554 <1> ; 12/04/2015 2555 <1> ; 16/10/2014 2556 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2557 <1> ; 2558 <1> ; INPUT -> 2559 <1> ; EBX = virtual (linear) address 2560 <1> ; ECX = page table attributes (lower 12 bits) 2561 <1> ; (higher 20 bits must be ZERO) 2562 <1> ; (bit 0 must be 1) 2563 <1> ; u.pgdir = page directory (physical) address 2564 <1> ; OUTPUT -> 2565 <1> ; EDX = Page directory entry address 2566 <1> ; EAX = Page table address 2567 <1> ; cf = 1 -> insufficient (out of) memory error 2568 <1> ; cf = 0 -> page table address in the PDE (EDX) 2569 <1> ; 2570 <1> ; Modified Registers -> EAX, EDX 2571 <1> ; 2572 00002EEB E878FFFFFF <1> call allocate_page 2573 00002EF0 72F8 <1> jc short mkpt_error 2574 00002EF2 E811000000 <1> call set_pde 2575 00002EF7 EBE0 <1> jmp short clear_page 2576 <1> 2577 <1> make_page: 2578 <1> ; 24/07/2015 2579 <1> ; 23/06/2015 ; (Retro UNIX 386 v1 - beginning) 2580 <1> ; 2581 <1> ; INPUT -> 2582 <1> ; EBX = virtual (linear) address 2583 <1> ; ECX = page attributes (lower 12 bits) 2584 <1> ; (higher 20 bits must be ZERO) 2585 <1> ; (bit 0 must be 1) 2586 <1> ; u.pgdir = page directory (physical) address 2587 <1> ; OUTPUT -> 2588 <1> ; EBX = Virtual address 2589 <1> ; (EDX = PTE value) 2590 <1> ; EAX = Physical address 2591 <1> ; cf = 1 -> insufficient (out of) memory error 2592 <1> ; 2593 <1> ; Modified Registers -> EAX, EDX 2594 <1> ; 2595 00002EF9 E86AFFFFFF <1> call allocate_page 2596 00002EFE 7207 <1> jc short mkp_err 2597 00002F00 E821000000 <1> call set_pte 2598 00002F05 73D2 <1> jnc short clear_page ; 18/04/2015 2599 <1> mkp_err: 2600 00002F07 C3 <1> retn 2601 <1> 2602 <1> set_pde: ; Set page directory entry (PDE) 2603 <1> ; 20/07/2015 2604 <1> ; 18/04/2015 2605 <1> ; 12/04/2015 2606 <1> ; 23/10/2014 2607 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2608 <1> ; 2609 <1> ; INPUT -> 2610 <1> ; EAX = physical address 2611 <1> ; (use present value if EAX = 0) 2612 <1> ; EBX = virtual (linear) address 2613 <1> ; ECX = page table attributes (lower 12 bits) 2614 <1> ; (higher 20 bits must be ZERO) 2615 <1> ; (bit 0 must be 1) 2616 <1> ; u.pgdir = page directory (physical) address 2617 <1> ; OUTPUT -> 2618 <1> ; EDX = PDE address 2619 <1> ; EAX = page table address (physical) 2620 <1> ; ;(CF=1 -> Invalid page address) 2621 <1> ; 2622 <1> ; Modified Registers -> EDX 2623 <1> ; 2624 00002F08 89DA <1> mov edx, ebx 2625 00002F0A C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 2626 00002F0D C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 2627 00002F10 0315[046F0000] <1> add edx, [u.pgdir] 2628 <1> ; 2629 00002F16 21C0 <1> and eax, eax 2630 00002F18 7506 <1> jnz short spde_1 2631 <1> ; 2632 00002F1A 8B02 <1> mov eax, [edx] ; old PDE value 2633 <1> ;test al, 1 2634 <1> ;jz short spde_2 2635 00002F1C 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2636 <1> spde_1: 2637 <1> ;and cx, 0FFFh 2638 00002F20 8902 <1> mov [edx], eax 2639 00002F22 66090A <1> or [edx], cx 2640 00002F25 C3 <1> retn 2641 <1> ;spde_2: ; error 2642 <1> ; stc 2643 <1> ; retn 2644 <1> 2645 <1> set_pte: ; Set page table entry (PTE) 2646 <1> ; 24/07/2015 2647 <1> ; 20/07/2015 2648 <1> ; 23/06/2015 2649 <1> ; 18/04/2015 2650 <1> ; 12/04/2015 2651 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2652 <1> ; 2653 <1> ; INPUT -> 2654 <1> ; EAX = physical page address 2655 <1> ; (use present value if EAX = 0) 2656 <1> ; EBX = virtual (linear) address 2657 <1> ; ECX = page attributes (lower 12 bits) 2658 <1> ; (higher 20 bits must be ZERO) 2659 <1> ; (bit 0 must be 1) 2660 <1> ; u.pgdir = page directory (physical) address 2661 <1> ; OUTPUT -> 2662 <1> ; EAX = physical page address 2663 <1> ; (EDX = PTE value) 2664 <1> ; EBX = virtual address 2665 <1> ; 2666 <1> ; CF = 1 -> error 2667 <1> ; 2668 <1> ; Modified Registers -> EAX, EDX 2669 <1> ; 2670 00002F26 50 <1> push eax 2671 00002F27 A1[046F0000] <1> mov eax, [u.pgdir] ; 20/07/2015 2672 00002F2C E837000000 <1> call get_pde 2673 <1> ; EDX = PDE address 2674 <1> ; EAX = PDE value 2675 00002F31 5A <1> pop edx ; physical page address 2676 00002F32 722A <1> jc short spte_err ; PDE not present 2677 <1> ; 2678 00002F34 53 <1> push ebx ; 24/07/2015 2679 00002F35 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2680 <1> ; EDX = PT address (physical) 2681 00002F39 C1EB0C <1> shr ebx, PAGE_SHIFT ; 12 2682 00002F3C 81E3FF030000 <1> and ebx, PTE_MASK ; 03FFh 2683 <1> ; clear higher 10 bits (PD bits) 2684 00002F42 C1E302 <1> shl ebx, 2 ; offset to page table (1024*4) 2685 00002F45 01C3 <1> add ebx, eax 2686 <1> ; 2687 00002F47 8B03 <1> mov eax, [ebx] ; Old PTE value 2688 00002F49 A801 <1> test al, 1 2689 00002F4B 740C <1> jz short spte_0 2690 00002F4D 09D2 <1> or edx, edx 2691 00002F4F 750F <1> jnz short spte_1 2692 00002F51 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits 2693 00002F55 89C2 <1> mov edx, eax 2694 00002F57 EB09 <1> jmp short spte_2 2695 <1> spte_0: 2696 <1> ; If this PTE contains a swap (disk) address, 2697 <1> ; it can be updated by using 'swap_in' procedure 2698 <1> ; only! 2699 00002F59 21C0 <1> and eax, eax 2700 00002F5B 7403 <1> jz short spte_1 2701 <1> ; 24/07/2015 2702 <1> ; swapped page ! (on disk) 2703 00002F5D 5B <1> pop ebx 2704 <1> spte_err: 2705 00002F5E F9 <1> stc 2706 00002F5F C3 <1> retn 2707 <1> spte_1: 2708 00002F60 89D0 <1> mov eax, edx 2709 <1> spte_2: 2710 00002F62 09CA <1> or edx, ecx 2711 <1> ; 23/06/2015 2712 00002F64 8913 <1> mov [ebx], edx ; PTE value in EDX 2713 <1> ; 24/07/2015 2714 00002F66 5B <1> pop ebx 2715 00002F67 C3 <1> retn 2716 <1> 2717 <1> get_pde: ; Get present value of the relevant PDE 2718 <1> ; 20/07/2015 2719 <1> ; 18/04/2015 2720 <1> ; 12/04/2015 2721 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2722 <1> ; 2723 <1> ; INPUT -> 2724 <1> ; EBX = virtual (linear) address 2725 <1> ; EAX = page directory (physical) address 2726 <1> ; OUTPUT -> 2727 <1> ; EDX = Page directory entry address 2728 <1> ; EAX = Page directory entry value 2729 <1> ; CF = 1 -> PDE not present or invalid ? 2730 <1> ; Modified Registers -> EDX, EAX 2731 <1> ; 2732 00002F68 89DA <1> mov edx, ebx 2733 00002F6A C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 (12+10) 2734 00002F6D C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 2735 00002F70 01C2 <1> add edx, eax ; page directory address (physical) 2736 00002F72 8B02 <1> mov eax, [edx] 2737 00002F74 A801 <1> test al, PDE_A_PRESENT ; page table is present or not ! 2738 00002F76 751F <1> jnz short gpte_retn 2739 00002F78 F9 <1> stc 2740 <1> gpde_retn: 2741 00002F79 C3 <1> retn 2742 <1> 2743 <1> get_pte: 2744 <1> ; Get present value of the relevant PTE 2745 <1> ; 29/07/2015 2746 <1> ; 20/07/2015 2747 <1> ; 18/04/2015 2748 <1> ; 12/04/2015 2749 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2750 <1> ; 2751 <1> ; INPUT -> 2752 <1> ; EBX = virtual (linear) address 2753 <1> ; EAX = page directory (physical) address 2754 <1> ; OUTPUT -> 2755 <1> ; EDX = Page table entry address (if CF=0) 2756 <1> ; Page directory entry address (if CF=1) 2757 <1> ; (Bit 0 value is 0 if PT is not present) 2758 <1> ; EAX = Page table entry value (page address) 2759 <1> ; CF = 1 -> PDE not present or invalid ? 2760 <1> ; Modified Registers -> EAX, EDX 2761 <1> ; 2762 00002F7A E8E9FFFFFF <1> call get_pde 2763 00002F7F 72F8 <1> jc short gpde_retn ; page table is not present 2764 <1> ;jnc short gpte_1 2765 <1> ;retn 2766 <1> ;gpte_1: 2767 00002F81 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2768 00002F85 89DA <1> mov edx, ebx 2769 00002F87 C1EA0C <1> shr edx, PAGE_SHIFT ; 12 2770 00002F8A 81E2FF030000 <1> and edx, PTE_MASK ; 03FFh 2771 <1> ; clear higher 10 bits (PD bits) 2772 00002F90 C1E202 <1> shl edx, 2 ; offset from start of page table (1024*4) 2773 00002F93 01C2 <1> add edx, eax 2774 00002F95 8B02 <1> mov eax, [edx] 2775 <1> gpte_retn: 2776 00002F97 C3 <1> retn 2777 <1> 2778 <1> deallocate_page_dir: 2779 <1> ; 15/09/2015 2780 <1> ; 05/08/2015 2781 <1> ; 30/04/2015 2782 <1> ; 28/04/2015 2783 <1> ; 17/10/2014 2784 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2785 <1> ; 2786 <1> ; INPUT -> 2787 <1> ; EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD) 2788 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 2789 <1> ; OUTPUT -> 2790 <1> ; All of page tables in the page directory 2791 <1> ; and page dir's itself will be deallocated 2792 <1> ; except 'read only' duplicated pages (will be converted 2793 <1> ; to writable pages). 2794 <1> ; 2795 <1> ; Modified Registers -> EAX 2796 <1> ; 2797 <1> ; 2798 00002F98 56 <1> push esi 2799 00002F99 51 <1> push ecx 2800 00002F9A 50 <1> push eax 2801 00002F9B 89C6 <1> mov esi, eax 2802 00002F9D 31C9 <1> xor ecx, ecx 2803 <1> ; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB), 2804 <1> ; it must not be deallocated 2805 00002F9F 890E <1> mov [esi], ecx ; 0 ; clear PDE 0 2806 <1> dapd_0: 2807 00002FA1 AD <1> lodsd 2808 00002FA2 A801 <1> test al, PDE_A_PRESENT ; bit 0, present flag (must be 1) 2809 00002FA4 7409 <1> jz short dapd_1 2810 00002FA6 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 2811 00002FAA E812000000 <1> call deallocate_page_table 2812 <1> dapd_1: 2813 00002FAF 41 <1> inc ecx ; page directory entry index 2814 00002FB0 81F900040000 <1> cmp ecx, PAGE_SIZE / 4 ; 1024 2815 00002FB6 72E9 <1> jb short dapd_0 2816 <1> dapd_2: 2817 00002FB8 58 <1> pop eax 2818 00002FB9 E872000000 <1> call deallocate_page ; deallocate the page dir's itself 2819 00002FBE 59 <1> pop ecx 2820 00002FBF 5E <1> pop esi 2821 00002FC0 C3 <1> retn 2822 <1> 2823 <1> deallocate_page_table: 2824 <1> ; 17/04/2021 - Retro UNIX 386 v2 2825 <1> ; (temporary modifications) 2826 <1> ; 12/07/2016 (TRDOS 386 v2) 2827 <1> ; 19/09/2015 2828 <1> ; 15/09/2015 2829 <1> ; 05/08/2015 2830 <1> ; 30/04/2015 2831 <1> ; 28/04/2015 2832 <1> ; 24/10/2014 2833 <1> ; 23/10/2014 2834 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2835 <1> ; 2836 <1> ; INPUT -> 2837 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE 2838 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 2839 <1> ; (ECX = page directory entry index) 2840 <1> ; OUTPUT -> 2841 <1> ; All of pages in the page table and page table's itself 2842 <1> ; will be deallocated except 'read only' duplicated pages 2843 <1> ; (will be converted to writable pages). 2844 <1> ; 2845 <1> ; Modified Registers -> EAX 2846 <1> ; 2847 00002FC1 56 <1> push esi 2848 00002FC2 57 <1> push edi 2849 00002FC3 52 <1> push edx 2850 00002FC4 50 <1> push eax ; * 2851 00002FC5 89C6 <1> mov esi, eax 2852 00002FC7 31FF <1> xor edi, edi ; 0 2853 <1> dapt_0: 2854 00002FC9 AD <1> lodsd 2855 00002FCA A801 <1> test al, PTE_A_PRESENT ; bit 0, present flag (must be 1) 2856 00002FCC 7455 <1> jz short dapt_1 2857 <1> ; 2858 00002FCE A802 <1> test al, PTE_A_WRITE ; bit 1, writable (r/w) flag 2859 <1> ; (must be 1) 2860 00002FD0 753F <1> jnz short dapt_3 2861 <1> ; Read only -duplicated- page (belongs to a parent or a child) 2862 00002FD2 66A90002 <1> test ax, PTE_DUPLICATED ; Was this page duplicated 2863 <1> ; as child's page ? 2864 00002FD6 7444 <1> jz short dapt_4 ; Clear PTE but don't deallocate the page! 2865 <1> ; check the parent's PTE value is read only & same page or not.. 2866 <1> ; ECX = page directory entry index (0-1023) 2867 00002FD8 53 <1> push ebx 2868 00002FD9 51 <1> push ecx 2869 00002FDA 66C1E102 <1> shl cx, 2 ; *4 2870 00002FDE 01CB <1> add ebx, ecx ; PDE offset (for the parent) 2871 00002FE0 8B0B <1> mov ecx, [ebx] 2872 00002FE2 F6C101 <1> test cl, PDE_A_PRESENT ; present (valid) or not ? 2873 00002FE5 7428 <1> jz short dapt_2 ; parent process does not use this page 2874 00002FE7 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 2875 <1> ; EDI = page table entry index (0-1023) 2876 00002FEC 89FA <1> mov edx, edi 2877 00002FEE 66C1E202 <1> shl dx, 2 ; *4 2878 00002FF2 01CA <1> add edx, ecx ; PTE offset (for the parent) 2879 00002FF4 8B1A <1> mov ebx, [edx] 2880 00002FF6 F6C301 <1> test bl, PTE_A_PRESENT ; present or not ? 2881 00002FF9 7414 <1> jz short dapt_2 ; parent process does not use this page 2882 00002FFB 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 2883 00002FFF 6681E300F0 <1> and bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 2884 00003004 39D8 <1> cmp eax, ebx ; parent's and child's pages are same ? 2885 00003006 7507 <1> jne short dapt_2 ; not same page 2886 <1> ; deallocate the child's page 2887 00003008 800A02 <1> or byte [edx], PTE_A_WRITE ; convert to writable page (parent) 2888 0000300B 59 <1> pop ecx 2889 0000300C 5B <1> pop ebx 2890 0000300D EB0D <1> jmp short dapt_4 2891 <1> 2892 <1> ; 17/04/2021 2893 <1> ; ('dapt_1' is disabled as temporary) 2894 <1> ; 2895 <1> ;dapt_1: 2896 <1> ; or eax, eax ; swapped page ? 2897 <1> ; jz short dapt_5 ; no 2898 <1> ; ; yes 2899 <1> ; shr eax, 1 2900 <1> ; call unlink_swap_block ; Deallocate swapped page block 2901 <1> ; ; on the swap disk (or in file) 2902 <1> ; jmp short dapt_5 2903 <1> dapt_2: 2904 0000300F 59 <1> pop ecx 2905 00003010 5B <1> pop ebx 2906 <1> dapt_3: 2907 <1> ; 12/07/2016 2908 00003011 66A90004 <1> test ax, PTE_SHARED ; shared or direct memory access indicator 2909 00003015 7505 <1> jnz short dapt_4 ; AVL bit 1 = 1, do not deallocate this page! 2910 <1> ; 2911 <1> ;and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 2912 00003017 E814000000 <1> call deallocate_page ; set the mem allocation bit of this page 2913 <1> dapt_4: 2914 0000301C C746FC00000000 <1> mov dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent) 2915 <1> dapt_1: ; 17/04/2021 (temporary) 2916 <1> dapt_5: 2917 00003023 47 <1> inc edi ; page table entry index 2918 00003024 81FF00040000 <1> cmp edi, PAGE_SIZE / 4 ; 1024 2919 0000302A 729D <1> jb short dapt_0 2920 <1> ; 2921 0000302C 58 <1> pop eax ; * 2922 0000302D 5A <1> pop edx 2923 0000302E 5F <1> pop edi 2924 0000302F 5E <1> pop esi 2925 <1> ; 2926 <1> ;call deallocate_page ; deallocate the page table's itself 2927 <1> ;retn 2928 <1> 2929 <1> deallocate_page: 2930 <1> ; 15/09/2015 2931 <1> ; 28/04/2015 2932 <1> ; 10/03/2015 2933 <1> ; 17/10/2014 2934 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2935 <1> ; 2936 <1> ; INPUT -> 2937 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 2938 <1> ; OUTPUT -> 2939 <1> ; [free_pages] is increased 2940 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is SET) 2941 <1> ; CF = 1 if the page is already deallocated 2942 <1> ; (or not allocated) before. 2943 <1> ; 2944 <1> ; Modified Registers -> EAX 2945 <1> ; 2946 00003030 53 <1> push ebx 2947 00003031 52 <1> push edx 2948 <1> ; 2949 00003032 C1E80C <1> shr eax, PAGE_SHIFT ; shift physical address to 2950 <1> ; 12 bits right 2951 <1> ; to get page number 2952 00003035 89C2 <1> mov edx, eax 2953 <1> ; 15/09/2015 2954 00003037 C1EA03 <1> shr edx, 3 ; to get offset to M.A.T. 2955 <1> ; (1 allocation bit = 1 page) 2956 <1> ; (1 allocation bytes = 8 pages) 2957 0000303A 80E2FC <1> and dl, 0FCh ; clear lower 2 bits 2958 <1> ; (to get 32 bit position) 2959 <1> ; 2960 0000303D BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table address 2961 00003042 01D3 <1> add ebx, edx 2962 00003044 83E01F <1> and eax, 1Fh ; lower 5 bits only 2963 <1> ; (allocation bit position) 2964 00003047 3B15[B46D0000] <1> cmp edx, [next_page] ; is the new free page address lower 2965 <1> ; than the address in 'next_page' ? 2966 <1> ; (next/first free page value) 2967 0000304D 7306 <1> jnb short dap_1 ; no 2968 0000304F 8915[B46D0000] <1> mov [next_page], edx ; yes 2969 <1> dap_1: 2970 00003055 0FAB03 <1> bts [ebx], eax ; unlink/release/deallocate page 2971 <1> ; set relevant bit to 1. 2972 <1> ; set CF to the previous bit value 2973 <1> ;cmc ; complement carry flag 2974 <1> ;jc short dap_2 ; do not increase free_pages count 2975 <1> ; if the page is already deallocated 2976 <1> ; before. 2977 00003058 FF05[B06D0000] <1> inc dword [free_pages] 2978 <1> dap_2: 2979 0000305E 5A <1> pop edx 2980 0000305F 5B <1> pop ebx 2981 00003060 C3 <1> retn 2982 <1> 2983 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2984 <1> ;; ;; 2985 <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; 2986 <1> ;; Distributed under terms of the GNU General Public License ;; 2987 <1> ;; ;; 2988 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2989 <1> 2990 <1> ;;$Revision: 5057 $ 2991 <1> 2992 <1> 2993 <1> ;;align 4 2994 <1> ;;proc alloc_page 2995 <1> 2996 <1> ;; pushfd 2997 <1> ;; cli 2998 <1> ;; push ebx 2999 <1> ;;;//- 3000 <1> ;; cmp [pg_data.pages_free], 1 3001 <1> ;; jle .out_of_memory 3002 <1> ;;;//- 3003 <1> ;; 3004 <1> ;; mov ebx, [page_start] 3005 <1> ;; mov ecx, [page_end] 3006 <1> ;;.l1: 3007 <1> ;; bsf eax, [ebx]; 3008 <1> ;; jnz .found 3009 <1> ;; add ebx, 4 3010 <1> ;; cmp ebx, ecx 3011 <1> ;; jb .l1 3012 <1> ;; pop ebx 3013 <1> ;; popfd 3014 <1> ;; xor eax, eax 3015 <1> ;; ret 3016 <1> ;;.found: 3017 <1> ;;;//- 3018 <1> ;; dec [pg_data.pages_free] 3019 <1> ;; jz .out_of_memory 3020 <1> ;;;//- 3021 <1> ;; btr [ebx], eax 3022 <1> ;; mov [page_start], ebx 3023 <1> ;; sub ebx, sys_pgmap 3024 <1> ;; lea eax, [eax+ebx*8] 3025 <1> ;; shl eax, 12 3026 <1> ;;;//- dec [pg_data.pages_free] 3027 <1> ;; pop ebx 3028 <1> ;; popfd 3029 <1> ;; ret 3030 <1> ;;;//- 3031 <1> ;;.out_of_memory: 3032 <1> ;; mov [pg_data.pages_free], 1 3033 <1> ;; xor eax, eax 3034 <1> ;; pop ebx 3035 <1> ;; popfd 3036 <1> ;; ret 3037 <1> ;;;//- 3038 <1> ;;endp 3039 <1> 3040 <1> duplicate_page_dir: 3041 <1> ; 21/09/2015 3042 <1> ; 31/08/2015 3043 <1> ; 20/07/2015 3044 <1> ; 28/04/2015 3045 <1> ; 27/04/2015 3046 <1> ; 18/04/2015 3047 <1> ; 12/04/2015 3048 <1> ; 18/10/2014 3049 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 3050 <1> ; 3051 <1> ; INPUT -> 3052 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 3053 <1> ; page directory. 3054 <1> ; OUTPUT -> 3055 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 3056 <1> ; page directory. 3057 <1> ; (New page directory with new page table entries.) 3058 <1> ; (New page tables with read only copies of the parent's 3059 <1> ; pages.) 3060 <1> ; EAX = 0 -> Error (CF = 1) 3061 <1> ; 3062 <1> ; Modified Registers -> none (except EAX) 3063 <1> ; 3064 00003061 E802FEFFFF <1> call allocate_page 3065 00003066 723E <1> jc short dpd_err 3066 <1> ; 3067 00003068 55 <1> push ebp ; 20/07/2015 3068 00003069 56 <1> push esi 3069 0000306A 57 <1> push edi 3070 0000306B 53 <1> push ebx 3071 0000306C 51 <1> push ecx 3072 0000306D 8B35[046F0000] <1> mov esi, [u.pgdir] 3073 00003073 89C7 <1> mov edi, eax 3074 00003075 50 <1> push eax ; save child's page directory address 3075 <1> ; 31/08/2015 3076 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 3077 <1> ; (use same system space for all user page tables) 3078 00003076 A5 <1> movsd 3079 00003077 BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 3080 0000307C B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 3081 <1> dpd_0: 3082 00003081 AD <1> lodsd 3083 <1> ;or eax, eax 3084 <1> ;jnz short dpd_1 3085 00003082 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 3086 00003084 7508 <1> jnz short dpd_1 3087 <1> ; 20/07/2015 (virtual address at the end of the page table) 3088 00003086 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 3089 0000308C EB0F <1> jmp short dpd_2 3090 <1> dpd_1: 3091 0000308E 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 3092 00003092 89C3 <1> mov ebx, eax 3093 <1> ; EBX = Parent's page table address 3094 00003094 E81F000000 <1> call duplicate_page_table 3095 00003099 720C <1> jc short dpd_p_err 3096 <1> ; EAX = Child's page table address 3097 0000309B 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 3098 <1> ; set bit 0, bit 1 and bit 2 to 1 3099 <1> ; (present, writable, user) 3100 <1> dpd_2: 3101 0000309D AB <1> stosd 3102 0000309E E2E1 <1> loop dpd_0 3103 <1> ; 3104 000030A0 58 <1> pop eax ; restore child's page directory address 3105 <1> dpd_3: 3106 000030A1 59 <1> pop ecx 3107 000030A2 5B <1> pop ebx 3108 000030A3 5F <1> pop edi 3109 000030A4 5E <1> pop esi 3110 000030A5 5D <1> pop ebp ; 20/07/2015 3111 <1> dpd_err: 3112 000030A6 C3 <1> retn 3113 <1> dpd_p_err: 3114 <1> ; release the allocated pages missing (recover free space) 3115 000030A7 58 <1> pop eax ; the new page directory address (physical) 3116 000030A8 8B1D[046F0000] <1> mov ebx, [u.pgdir] ; parent's page directory address 3117 000030AE E8E5FEFFFF <1> call deallocate_page_dir 3118 000030B3 29C0 <1> sub eax, eax ; 0 3119 000030B5 F9 <1> stc 3120 000030B6 EBE9 <1> jmp short dpd_3 3121 <1> 3122 <1> duplicate_page_table: 3123 <1> ; 31/12/2021 - Retro UNIX 386 v1.2 3124 <1> ; 17/04/2021 - Retro UNIX 386 v2 3125 <1> ; (temporary modifications) 3126 <1> ; 16/04/2021 (Retro UNIX 386 v2) 3127 <1> ; 20/02/2017 (TRDOS 386 v2) 3128 <1> ; 21/09/2015 3129 <1> ; 20/07/2015 3130 <1> ; 05/05/2015 3131 <1> ; 28/04/2015 3132 <1> ; 27/04/2015 3133 <1> ; 18/04/2015 3134 <1> ; 18/10/2014 3135 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 3136 <1> ; 3137 <1> ; INPUT -> 3138 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 3139 <1> ; 20/02/2017 3140 <1> ; EBP = Linear address of the page (from 'duplicate_page_dir') 3141 <1> ; (Linear address = CORE + user's virtual address) 3142 <1> ; OUTPUT -> 3143 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 3144 <1> ; (with 'read only' attribute of page table entries) 3145 <1> ; 20/02/2017 3146 <1> ; EBP = Next linear page address (for 'duplicate_page_dir') 3147 <1> ; 3148 <1> ; CF = 1 -> error 3149 <1> ; 3150 <1> ; Modified Registers -> EBP (except EAX) 3151 <1> ; 3152 000030B8 E8ABFDFFFF <1> call allocate_page 3153 000030BD 725B <1> jc short dpt_err 3154 <1> ; 3155 000030BF 50 <1> push eax ; * 3156 000030C0 56 <1> push esi 3157 000030C1 57 <1> push edi 3158 000030C2 52 <1> push edx 3159 000030C3 51 <1> push ecx 3160 <1> ; 3161 000030C4 89DE <1> mov esi, ebx 3162 000030C6 89C7 <1> mov edi, eax 3163 000030C8 89C2 <1> mov edx, eax 3164 000030CA 81C200100000 <1> add edx, PAGE_SIZE 3165 <1> dpt_0: 3166 000030D0 AD <1> lodsd 3167 000030D1 21C0 <1> and eax, eax 3168 000030D3 7435 <1> jz short dpt_3 3169 000030D5 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 3170 <1> ; 17/04/2021 (temporary) 3171 000030D7 7503 <1> jnz short dpt_1 3172 <1> ;jz short dpt_p_err 3173 <1> ; 31/12/2021 3174 000030D9 F9 <1> stc 3175 000030DA EB39 <1> jmp short dpt_p_err 3176 <1> 3177 <1> ; 17/04/2021 3178 <1> ; ('reload_page' procedure call is disabled as temporary) 3179 <1> ; 3180 <1> ; ; 20/07/2015 3181 <1> ; ; ebp = virtual (linear) address of the memory page 3182 <1> ; call reload_page ; 28/04/2015 3183 <1> ; jc short dpt_p_err 3184 <1> dpt_1: 3185 <1> ; 21/09/2015 3186 000030DC 89C1 <1> mov ecx, eax 3187 000030DE 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3188 000030E2 F6C102 <1> test cl, PTE_A_WRITE ; writable page ? 3189 000030E5 751A <1> jnz short dpt_2 3190 <1> ; Read only (parent) page 3191 <1> ; - there is a third process which uses this page - 3192 <1> ; Allocate a new page for the child process 3193 000030E7 E87CFDFFFF <1> call allocate_page 3194 000030EC 7227 <1> jc short dpt_p_err 3195 000030EE 57 <1> push edi 3196 000030EF 56 <1> push esi 3197 000030F0 89CE <1> mov esi, ecx 3198 000030F2 89C7 <1> mov edi, eax 3199 000030F4 B900040000 <1> mov ecx, PAGE_SIZE/4 3200 000030F9 F3A5 <1> rep movsd ; copy page (4096 bytes) 3201 000030FB 5E <1> pop esi 3202 000030FC 5F <1> pop edi 3203 <1> ; 3204 <1> 3205 <1> ; 17/04/2021 3206 <1> ; ('add_to_swap_queue' procedure call is disabled as temporary) 3207 <1> ; 3208 <1> ; push ebx 3209 <1> ; push eax 3210 <1> ; ; 20/07/2015 3211 <1> ; mov ebx, ebp 3212 <1> ; ; ebx = virtual (linear) address of the memory page 3213 <1> ; call add_to_swap_queue 3214 <1> ; pop eax 3215 <1> ; pop ebx 3216 <1> 3217 <1> ; 21/09/2015 3218 000030FD 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 3219 <1> ; user + writable + present page 3220 000030FF EB09 <1> jmp short dpt_3 3221 <1> dpt_2: 3222 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 3223 00003101 0C05 <1> or al, PTE_A_USER+PTE_A_PRESENT 3224 <1> ; (read only page!) 3225 00003103 8946FC <1> mov [esi-4], eax ; update parent's PTE 3226 00003106 660D0002 <1> or ax, PTE_DUPLICATED ; (read only page & duplicated PTE!) 3227 <1> dpt_3: 3228 0000310A AB <1> stosd ; EDI points to child's PTE 3229 <1> ; 3230 0000310B 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 3231 <1> ; 3232 00003111 39D7 <1> cmp edi, edx 3233 00003113 72BB <1> jb short dpt_0 3234 <1> dpt_p_err: 3235 00003115 59 <1> pop ecx 3236 00003116 5A <1> pop edx 3237 00003117 5F <1> pop edi 3238 00003118 5E <1> pop esi 3239 00003119 58 <1> pop eax ; * 3240 <1> dpt_err: 3241 0000311A C3 <1> retn 3242 <1> 3243 <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault ! 3244 <1> ; 31/12/2021 - Retro UNIX 386 v1.2 3245 <1> ; 17/04/2021 - Retro UNIX 386 v2 3246 <1> ; (temporary modifications) 3247 <1> ; 21/09/2015 3248 <1> ; 19/09/2015 3249 <1> ; 17/09/2015 3250 <1> ; 28/08/2015 3251 <1> ; 20/07/2015 3252 <1> ; 28/06/2015 3253 <1> ; 03/05/2015 3254 <1> ; 30/04/2015 3255 <1> ; 18/04/2015 3256 <1> ; 12/04/2015 3257 <1> ; 30/10/2014 3258 <1> ; 11/09/2014 3259 <1> ; 10/09/2014 (Retro UNIX 386 v1 - beginning) 3260 <1> ; 3261 <1> ; Note: This is not an interrupt/exception handler. 3262 <1> ; This is a 'page fault remedy' subroutine 3263 <1> ; which will be called by standard/uniform 3264 <1> ; exception handler. 3265 <1> ; 3266 <1> ; INPUT -> 3267 <1> ; [error_code] = 32 bit ERROR CODE (lower 5 bits are valid) 3268 <1> ; 3269 <1> ; cr2 = the virtual (linear) address 3270 <1> ; which has caused to page fault (19/09/2015) 3271 <1> ; 3272 <1> ; OUTPUT -> 3273 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3274 <1> ; EAX = 0 -> no error 3275 <1> ; EAX > 0 -> error code in EAX (also CF = 1) 3276 <1> ; 3277 <1> ; Modified Registers -> none (except EAX) 3278 <1> ; 3279 <1> ; 3280 <1> ; ERROR CODE: 3281 <1> ; 31 ..... 4 3 2 1 0 3282 <1> ; +---+-- --+---+---+---+---+---+---+ 3283 <1> ; | Reserved | I | R | U | W | P | 3284 <1> ; +---+-- --+---+---+---+---+---+---+ 3285 <1> ; 3286 <1> ; P : PRESENT - When set, the page fault was caused by 3287 <1> ; a page-protection violation. When not set, 3288 <1> ; it was caused by a non-present page. 3289 <1> ; W : WRITE - When set, the page fault was caused by 3290 <1> ; a page write. When not set, it was caused 3291 <1> ; by a page read. 3292 <1> ; U : USER - When set, the page fault was caused 3293 <1> ; while CPL = 3. 3294 <1> ; This does not necessarily mean that 3295 <1> ; the page fault was a privilege violation. 3296 <1> ; R : RESERVD - When set, the page fault was caused by 3297 <1> ; WRITE reading a 1 in a reserved field. 3298 <1> ; I : INSTRUC - When set, the page fault was caused by 3299 <1> ; FETCH an instruction fetch 3300 <1> ; 3301 <1> ;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION 3302 <1> ; 31 22 12 11 0 3303 <1> ; +-------------------+-------------------+-----------------------+ 3304 <1> ; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # | OFFSET | 3305 <1> ; +-------------------+-------------------+-----------------------+ 3306 <1> ; 3307 <1> 3308 <1> ;; CR3 REGISTER (Control Register 3) 3309 <1> ; 31 12 5 4 3 2 0 3310 <1> ; +---------------------------------------+-------------+---+-----+ 3311 <1> ; | | |P|P| | 3312 <1> ; | PAGE DIRECTORY TABLE BASE ADDRESS | reserved |C|W|rsvrd| 3313 <1> ; | | |D|T| | 3314 <1> ; +---------------------------------------+-------------+---+-----+ 3315 <1> ; 3316 <1> ; PWT - WRITE THROUGH 3317 <1> ; PCD - CACHE DISABLE 3318 <1> ; 3319 <1> ; 3320 <1> ;; x86 PAGE DIRECTORY ENTRY (4 KByte Page) 3321 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3322 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3323 <1> ; | | | | | | |P|P|U|R| | 3324 <1> ; | PAGE TABLE BASE ADDRESS 31..12 | AVL |G|0|D|A|C|W|/|/|P| 3325 <1> ; | | | | | | |D|T|S|W| | 3326 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3327 <1> ; 3328 <1> ; P - PRESENT 3329 <1> ; R/W - READ/WRITE 3330 <1> ; U/S - USER/SUPERVISOR 3331 <1> ; PWT - WRITE THROUGH 3332 <1> ; PCD - CACHE DISABLE 3333 <1> ; A - ACCESSED 3334 <1> ; D - DIRTY (IGNORED) 3335 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 3336 <1> ; G - GLOBAL (IGNORED) 3337 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3338 <1> ; 3339 <1> ; 3340 <1> ;; x86 PAGE TABLE ENTRY (4 KByte Page) 3341 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3342 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3343 <1> ; | | | |P| | |P|P|U|R| | 3344 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |G|A|D|A|C|W|/|/|P| 3345 <1> ; | | | |T| | |D|T|S|W| | 3346 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3347 <1> ; 3348 <1> ; P - PRESENT 3349 <1> ; R/W - READ/WRITE 3350 <1> ; U/S - USER/SUPERVISOR 3351 <1> ; PWT - WRITE THROUGH 3352 <1> ; PCD - CACHE DISABLE 3353 <1> ; A - ACCESSED 3354 <1> ; D - DIRTY 3355 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 3356 <1> ; G - GLOBAL 3357 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3358 <1> ; 3359 <1> ; 3360 <1> ;; 80386 PAGE TABLE ENTRY (4 KByte Page) 3361 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3362 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 3363 <1> ; | | | | | | | | |U|R| | 3364 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |0|0|D|A|0|0|/|/|P| 3365 <1> ; | | | | | | | | |S|W| | 3366 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 3367 <1> ; 3368 <1> ; P - PRESENT 3369 <1> ; R/W - READ/WRITE 3370 <1> ; U/S - USER/SUPERVISOR 3371 <1> ; D - DIRTY 3372 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3373 <1> ; 3374 <1> ; NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. 3375 <1> ; 3376 <1> ; 3377 <1> ;; Invalid Page Table Entry 3378 <1> ; 31 1 0 3379 <1> ; +-------------------------------------------------------------+-+ 3380 <1> ; | | | 3381 <1> ; | AVAILABLE |0| 3382 <1> ; | | | 3383 <1> ; +-------------------------------------------------------------+-+ 3384 <1> ; 3385 <1> 3386 0000311B 53 <1> push ebx 3387 0000311C 52 <1> push edx 3388 0000311D 51 <1> push ecx 3389 <1> ; 3390 <1> ; 21/09/2015 (debugging) 3391 0000311E FF05[1C6F0000] <1> inc dword [u.pfcount] ; page fault count for running process 3392 00003124 FF05[606E0000] <1> inc dword [PF_Count] ; total page fault count 3393 <1> ; 28/06/2015 3394 <1> ;mov edx, [error_code] ; Lower 5 bits are valid 3395 0000312A 8A15[586E0000] <1> mov dl, [error_code] 3396 <1> ; 3397 00003130 F6C201 <1> test dl, 1 ; page fault was caused by a non-present page 3398 <1> ; sign 3399 00003133 7416 <1> jz short pfh_alloc_np 3400 <1> ; 3401 <1> ; If it is not a 'write on read only page' type page fault 3402 <1> ; major page fault error with minor reason must be returned without 3403 <1> ; fixing the problem. 'sys_exit with error' will be needed 3404 <1> ; after return here! 3405 <1> ; Page fault will be remedied, by copying page contents 3406 <1> ; to newly allocated page with write permission; 3407 <1> ; sys_fork -> sys_exec -> copy on write, demand paging method is 3408 <1> ; used for working with minimum possible memory usage. 3409 <1> ; sys_fork will duplicate page directory and tables of parent 3410 <1> ; process with 'read only' flag. If the child process attempts to 3411 <1> ; write on these read only pages, page fault will be directed here 3412 <1> ; for allocating a new page with same data/content. 3413 <1> ; 3414 <1> ; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS) 3415 <1> ; will not force to separate CODE and DATA space 3416 <1> ; in a process/program... 3417 <1> ; CODE segment/section may contain DATA! 3418 <1> ; It is flat, smoth and simplest programming method already as in 3419 <1> ; Retro UNIX 8086 v1 and MS-DOS programs. 3420 <1> ; 3421 00003135 F6C202 <1> test dl, 2 ; page fault was caused by a page write 3422 <1> ; sign 3423 00003138 744F <1> jz short pfh_p_err 3424 <1> ; 31/08/2015 3425 0000313A F6C204 <1> test dl, 4 ; page fault was caused while CPL = 3 (user mode) 3426 <1> ; sign. (U+W+P = 4+2+1 = 7) 3427 0000313D 744A <1> jz short pfh_pv_err 3428 <1> ; 3429 <1> ; make a new page and copy the parent's page content 3430 <1> ; as the child's new page content 3431 <1> ; 3432 0000313F 0F20D3 <1> mov ebx, cr2 ; CR2 contains the linear address 3433 <1> ; which has caused to page fault 3434 00003142 E87C000000 <1> call copy_page 3435 00003147 7239 <1> jc short pfh_im_err ; insufficient memory 3436 <1> ; 3437 00003149 EB72 <1> jmp pfh_cpp_ok 3438 <1> ; 3439 <1> pfh_alloc_np: 3440 0000314B E818FDFFFF <1> call allocate_page ; (allocate a new page) 3441 00003150 7230 <1> jc short pfh_im_err ; 'insufficient memory' error 3442 <1> pfh_chk_cpl: 3443 <1> ; EAX = Physical (base) address of the allocated (new) page 3444 <1> ; (Lower 12 bits are ZERO, because 3445 <1> ; the address is on a page boundary) 3446 00003152 80E204 <1> and dl, 4 ; CPL = 3 ? 3447 00003155 7505 <1> jnz short pfh_um 3448 <1> ; Page fault handler for kernel/system mode (CPL=0) 3449 00003157 0F20DB <1> mov ebx, cr3 ; CR3 (Control Register 3) contains physical address 3450 <1> ; of the current/active page directory 3451 <1> ; (Always kernel/system mode page directory, here!) 3452 <1> ; Note: Lower 12 bits are 0. (page boundary) 3453 0000315A EB06 <1> jmp short pfh_get_pde 3454 <1> ; 3455 <1> pfh_um: ; Page fault handler for user/appl. mode (CPL=3) 3456 0000315C 8B1D[046F0000] <1> mov ebx, [u.pgdir] ; Page directory of current/active process 3457 <1> ; Physical address of the USER's page directory 3458 <1> ; Note: Lower 12 bits are 0. (page boundary) 3459 <1> pfh_get_pde: 3460 00003162 80CA03 <1> or dl, 3 ; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT 3461 00003165 0F20D1 <1> mov ecx, cr2 ; CR2 contains the virtual address 3462 <1> ; which has been caused to page fault 3463 <1> ; 3464 00003168 C1E914 <1> shr ecx, 20 ; shift 20 bits right 3465 0000316B 80E1FC <1> and cl, 0FCh ; mask lower 2 bits to get PDE offset 3466 <1> ; 3467 0000316E 01CB <1> add ebx, ecx ; now, EBX points to the relevant page dir entry 3468 00003170 8B0B <1> mov ecx, [ebx] ; physical (base) address of the page table 3469 00003172 F6C101 <1> test cl, 1 ; check bit 0 is set (1) or not (0). 3470 00003175 741A <1> jz short pfh_set_pde ; Page directory entry is not valid, 3471 <1> ; set/validate page directory entry 3472 00003177 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 3473 0000317C 89CB <1> mov ebx, ecx ; Physical address of the page table 3474 0000317E 89C1 <1> mov ecx, eax ; new page address (physical) 3475 00003180 EB25 <1> jmp short pfh_get_pte 3476 <1> 3477 <1> ; 31/12/2021 (short jump) 3478 <1> pfh_im_err: 3479 00003182 B8E4000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX 3480 <1> ; Major (Primary) Error: Page Fault 3481 <1> ; Minor (Secondary) Error: Insufficient Memory ! 3482 00003187 EB36 <1> jmp short pfh_err_retn 3483 <1> 3484 <1> ; 31/12/2021 3485 <1> pfh_p_err: ; 09/03/2015 3486 <1> pfh_pv_err: 3487 <1> ; Page fault was caused by a protection-violation 3488 00003189 B8E6000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX 3489 <1> ; Major (Primary) Error: Page Fault 3490 <1> ; Minor (Secondary) Error: Protection violation ! 3491 0000318E F9 <1> stc 3492 0000318F EB2E <1> jmp short pfh_err_retn 3493 <1> 3494 <1> pfh_set_pde: 3495 <1> ;; NOTE: Page directories and page tables never be swapped out! 3496 <1> ;; (So, we know this PDE is empty or invalid) 3497 <1> ; 3498 00003191 08D0 <1> or al, dl ; lower 3 bits are used as U/S, R/W, P flags 3499 00003193 8903 <1> mov [ebx], eax ; Let's put the new page directory entry here ! 3500 00003195 30C0 <1> xor al, al ; clear lower (3..8) bits 3501 00003197 89C3 <1> mov ebx, eax 3502 00003199 E8CAFCFFFF <1> call allocate_page ; (allocate a new page) 3503 0000319E 72E2 <1> jc short pfh_im_err ; 'insufficient memory' error 3504 <1> pfh_spde_1: 3505 <1> ; EAX = Physical (base) address of the allocated (new) page 3506 000031A0 89C1 <1> mov ecx, eax 3507 000031A2 E832FDFFFF <1> call clear_page ; Clear page content 3508 <1> pfh_get_pte: 3509 000031A7 0F20D0 <1> mov eax, cr2 ; virtual address 3510 <1> ; which has been caused to page fault 3511 000031AA 89C7 <1> mov edi, eax ; 20/07/2015 3512 000031AC C1E80C <1> shr eax, 12 ; shift 12 bit right to get 3513 <1> ; higher 20 bits of the page fault address 3514 000031AF 25FF030000 <1> and eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3515 000031B4 C1E002 <1> shl eax, 2 ; shift 2 bits left to get PTE offset 3516 000031B7 01C3 <1> add ebx, eax ; now, EBX points to the relevant page table entry 3517 <1> ; 17/04/2021 temporary 3518 <1> ; mov eax, [ebx] ; get previous value of pte 3519 <1> ; ; bit 0 of EAX is always 0 (otherwise we would not be here) 3520 <1> ; 17/04/2021 3521 <1> ; ('swap_in' procedure call has been disabled as temporary) 3522 <1> ; 3523 <1> ; and eax, eax 3524 <1> ; jz short pfh_gpte_1 3525 <1> ; ; 20/07/2015 3526 <1> ; xchg ebx, ecx ; new page address (physical) 3527 <1> ; push ebp ; 20/07/2015 3528 <1> ; mov ebp, cr2 3529 <1> ; ; ECX = physical address of the page table entry 3530 <1> ; ; EBX = Memory page address (physical!) 3531 <1> ; ; EAX = Swap disk (offset) address 3532 <1> ; ; EBP = virtual address (page fault address) 3533 <1> ; call swap_in 3534 <1> ; pop ebp 3535 <1> ; jc short pfh_err_retn 3536 <1> ; xchg ecx, ebx 3537 <1> ; ; EBX = physical address of the page table entry 3538 <1> ; ; ECX = new page 3539 <1> pfh_gpte_1: 3540 000031B9 08D1 <1> or cl, dl ; lower 3 bits are used as U/S, R/W, P flags 3541 000031BB 890B <1> mov [ebx], ecx ; Let's put the new page table entry here ! 3542 <1> pfh_cpp_ok: 3543 <1> ; 17/04/2021 3544 <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary) 3545 <1> ; 3546 <1> ; ; 20/07/2015 3547 <1> ; mov ebx, cr2 3548 <1> ; call add_to_swap_queue 3549 <1> ; 3550 <1> ; The new PTE (which contains the new page) will be added to 3551 <1> ; the swap queue, here. 3552 <1> ; (Later, if memory will become insufficient, 3553 <1> ; one page will be swapped out which is at the head of 3554 <1> ; the swap queue by using FIFO and access check methods.) 3555 <1> ; 3556 000031BD 31C0 <1> xor eax, eax ; 0 3557 <1> ; 3558 <1> pfh_err_retn: 3559 000031BF 59 <1> pop ecx 3560 000031C0 5A <1> pop edx 3561 000031C1 5B <1> pop ebx 3562 000031C2 C3 <1> retn 3563 <1> 3564 <1> copy_page: 3565 <1> ; 16/04/2021 3566 <1> ; 19/04/2020 - Retro UNIX 386 v2 3567 <1> ; 22/09/2015 3568 <1> ; 21/09/2015 3569 <1> ; 19/09/2015 3570 <1> ; 07/09/2015 3571 <1> ; 31/08/2015 3572 <1> ; 20/07/2015 3573 <1> ; 05/05/2015 3574 <1> ; 03/05/2015 3575 <1> ; 18/04/2015 3576 <1> ; 12/04/2015 3577 <1> ; 30/10/2014 3578 <1> ; 18/10/2014 (Retro UNIX 386 v1 - beginning) 3579 <1> ; 3580 <1> ; INPUT -> 3581 <1> ; EBX = Virtual (linear) address of source page 3582 <1> ; (Page fault address) 3583 <1> ; OUTPUT -> 3584 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 3585 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3586 <1> ; EAX = 0 (CF = 1) 3587 <1> ; if there is not a free page to be allocated 3588 <1> ; (page content of the source page will be copied 3589 <1> ; onto the target/new page) 3590 <1> ; 3591 <1> ; Modified Registers -> ecx, ebx (except EAX) 3592 <1> ; 3593 <1> 3594 <1> ; 19/04/2020 - Retro UNIX 386 v2 3595 <1> ; INPUT: 3596 <1> ; EBX = Virtual (linear) address of source page 3597 <1> ; (Page fault address) 3598 <1> ; OUTPUT: 3599 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 3600 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3601 <1> ; EAX = 0 (CF = 1) 3602 <1> ; if there is not a free page to be allocated 3603 <1> ; (page content of the source page will be copied 3604 <1> ; onto the target/new page) 3605 <1> ; 3606 <1> ; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021 3607 <1> 3608 000031C3 56 <1> push esi ; * 3609 000031C4 57 <1> push edi ; ** 3610 <1> ; 16/04/2021 3611 <1> ; 19/04/2020 - Retro UNIX 386 v2 3612 <1> ;push ebx ; *** 3613 <1> ;push ecx ; **** 3614 000031C5 31F6 <1> xor esi, esi 3615 000031C7 C1EB0C <1> shr ebx, 12 ; shift 12 bits right to get PDE & PTE numbers 3616 000031CA 89D9 <1> mov ecx, ebx ; save page fault address (as 12 bit shifted) 3617 000031CC C1EB08 <1> shr ebx, 8 ; shift 8 bits right and then 3618 000031CF 80E3FC <1> and bl, 0FCh ; mask lower 2 bits to get PDE offset 3619 000031D2 89DF <1> mov edi, ebx ; save it for the parent of current process 3620 000031D4 031D[046F0000] <1> add ebx, [u.pgdir] ; EBX points to the relevant page dir entry 3621 000031DA 8B03 <1> mov eax, [ebx] ; physical (base) address of the page table 3622 000031DC 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3623 000031E0 89CB <1> mov ebx, ecx ; (restore higher 20 bits of page fault address) 3624 000031E2 81E3FF030000 <1> and ebx, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3625 000031E8 66C1E302 <1> shl bx, 2 ; shift 2 bits left to get PTE offset 3626 000031EC 01C3 <1> add ebx, eax ; EBX points to the relevant page table entry 3627 <1> ; 07/09/2015 3628 000031EE 66F7030002 <1> test word [ebx], PTE_DUPLICATED ; (Does current process share this 3629 <1> ; read only page as a child process?) 3630 000031F3 7509 <1> jnz short cpp_0 ; yes 3631 000031F5 8B0B <1> mov ecx, [ebx] ; PTE value 3632 000031F7 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 3633 000031FC EB32 <1> jmp short cpp_1 3634 <1> cpp_0: 3635 000031FE 89FE <1> mov esi, edi 3636 00003200 0335[086F0000] <1> add esi, [u.ppgdir] ; the parent's page directory entry 3637 00003206 8B06 <1> mov eax, [esi] ; physical (base) address of the page table 3638 00003208 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3639 0000320C 89CE <1> mov esi, ecx ; (restore higher 20 bits of page fault address) 3640 0000320E 81E6FF030000 <1> and esi, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3641 00003214 66C1E602 <1> shl si, 2 ; shift 2 bits left to get PTE offset 3642 00003218 01C6 <1> add esi, eax ; EDX points to the relevant page table entry 3643 0000321A 8B0E <1> mov ecx, [esi] ; PTE value of the parent process 3644 <1> ; 21/09/2015 3645 0000321C 8B03 <1> mov eax, [ebx] ; PTE value of the child process 3646 0000321E 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear page attributes 3647 <1> ; 3648 00003222 F6C101 <1> test cl, PTE_A_PRESENT ; is it a present/valid page ? 3649 00003225 7424 <1> jz short cpp_3 ; the parent's page is not same page 3650 <1> ; 3651 00003227 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 3652 0000322C 39C8 <1> cmp eax, ecx ; Same page? 3653 0000322E 751B <1> jne short cpp_3 ; Parent page and child page are not same 3654 <1> ; Convert child's page to writable page 3655 <1> cpp_1: 3656 00003230 E833FCFFFF <1> call allocate_page 3657 00003235 721A <1> jc short cpp_4 ; 'insufficient memory' error 3658 00003237 21F6 <1> and esi, esi ; check ESI is valid or not 3659 00003239 7405 <1> jz short cpp_2 3660 <1> ; Convert read only page to writable page 3661 <1> ;(for the parent of the current process) 3662 <1> ;and word [esi], PTE_A_CLEAR ; 0F000h 3663 <1> ; 22/09/2015 3664 0000323B 890E <1> mov [esi], ecx 3665 0000323D 800E07 <1> or byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER 3666 <1> ; 1+2+4 = 7 3667 <1> cpp_2: 3668 00003240 89C7 <1> mov edi, eax ; new page address of the child process 3669 <1> ; 07/09/2015 3670 00003242 89CE <1> mov esi, ecx ; the page address of the parent process 3671 00003244 B900040000 <1> mov ecx, PAGE_SIZE / 4 3672 00003249 F3A5 <1> rep movsd ; 31/08/2015 3673 <1> cpp_3: 3674 0000324B 0C07 <1> or al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7 3675 0000324D 8903 <1> mov [ebx], eax ; Update PTE 3676 0000324F 28C0 <1> sub al, al ; clear attributes 3677 <1> cpp_4: 3678 <1> ; 16/04/2021 3679 <1> ; 19/04/2020 - Retro UNIX 386 v2 3680 <1> ;pop ecx ; **** 3681 <1> ;pop ebx ; *** 3682 00003251 5F <1> pop edi ; ** 3683 00003252 5E <1> pop esi ; * 3684 00003253 C3 <1> retn 3685 <1> 3686 <1> ;; 28/04/2015 3687 <1> ;; 24/10/2014 3688 <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning) 3689 <1> ;; SWAP_PAGE_QUEUE (4096 bytes) 3690 <1> ;; 3691 <1> ;; 0000 0001 0002 0003 .... 1020 1021 1022 1023 3692 <1> ;; +------+------+------+------+- -+------+------+------+------+ 3693 <1> ;; | pg1 | pg2 | pg3 | pg4 | .... |pg1021|pg1022|pg1023|pg1024| 3694 <1> ;; +------+------+------+------+- -+------+------+------+------+ 3695 <1> ;; 3696 <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue 3697 <1> ;; 3698 <1> ;; Method: 3699 <1> ;; Swap page queue is a list of allocated pages with physical 3700 <1> ;; addresses (system mode virtual adresses = physical addresses). 3701 <1> ;; It is used for 'swap_in' and 'swap_out' procedures. 3702 <1> ;; When a new page is being allocated, swap queue is updated 3703 <1> ;; by 'swap_queue_shift' procedure, header of the queue (offset 0) 3704 <1> ;; is checked for 'accessed' flag. If the 1st page on the queue 3705 <1> ;; is 'accessed' or 'read only', it is dropped from the list; 3706 <1> ;; other pages from the 2nd to the last (in [swpq_last]) shifted 3707 <1> ;; to head then the 2nd page becomes the 1st and '[swpq_last]' 3708 <1> ;; offset value becomes it's previous offset value - 4. 3709 <1> ;; If the 1st page of the swap page queue is not 'accessed' 3710 <1> ;; the queue/list is not shifted. 3711 <1> ;; After the queue/list shift, newly allocated page is added 3712 <1> ;; to the tail of the queue at the [swpq_count*4] position. 3713 <1> ;; But, if [swpq_count] > 1023, the newly allocated page 3714 <1> ;; will not be added to the tail of swap page queue. 3715 <1> ;; 3716 <1> ;; During 'swap_out' procedure, swap page queue is checked for 3717 <1> ;; the first non-accessed, writable page in the list, 3718 <1> ;; from the head to the tail. The list is shifted to left 3719 <1> ;; (to the head) till a non-accessed page will be found in the list. 3720 <1> ;; Then, this page is swapped out (to disk) and then it is dropped 3721 <1> ;; from the list by a final swap queue shift. [swpq_count] value 3722 <1> ;; is changed. If all pages on the queue' are 'accessed', 3723 <1> ;; 'insufficient memory' error will be returned ('swap_out' 3724 <1> ;; procedure will be failed)... 3725 <1> ;; 3726 <1> ;; Note: If the 1st page of the queue is an 'accessed' page, 3727 <1> ;; 'accessed' flag of the page will be reset (0) and that page 3728 <1> ;; (PTE) will be added to the tail of the queue after 3729 <1> ;; the check, if [swpq_count] < 1023. If [swpq_count] = 1024 3730 <1> ;; the queue will be rotated and the PTE in the head will be 3731 <1> ;; added to the tail after resetting 'accessed' bit. 3732 <1> ;; 3733 <1> ;; 3734 <1> ;; 3735 <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks) 3736 <1> ;; 3737 <1> ;; 00000000 00000004 00000008 0000000C ... size-8 size-4 3738 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 3739 <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) | 3740 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 3741 <1> ;; 3742 <1> ;; [swpd_next] = the first free block address in swapped page records 3743 <1> ;; for next free block search by 'swap_out' procedure. 3744 <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes) 3745 <1> ;; NOTE: max. possible swap disk size is 1024 GB 3746 <1> ;; (entire swap space must be accessed by using 3747 <1> ;; 31 bit offset address) 3748 <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space 3749 <1> ;; [swpd_start] = absolute/start address of the swap disk/file 3750 <1> ;; 0 for file, or beginning sector of the swap partition 3751 <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file 3752 <1> ;; 3753 <1> ;; 3754 <1> ;; Method: 3755 <1> ;; When the memory (ram) becomes insufficient, page allocation 3756 <1> ;; procedure swaps out a page from memory to the swap disk 3757 <1> ;; (partition) or swap file to get a new free page at the memory. 3758 <1> ;; Swapping out is performed by using swap page queue. 3759 <1> ;; 3760 <1> ;; Allocation block size of swap disk/file is equal to page size 3761 <1> ;; (4096 bytes). Swapping address (in sectors) is recorded 3762 <1> ;; into relevant page file entry as 31 bit physical (logical) 3763 <1> ;; offset address as 1 bit shifted to left for present flag (0). 3764 <1> ;; Swapped page address is between 1 and swap disk/file size - 4. 3765 <1> ;; Absolute physical (logical) address of the swapped page is 3766 <1> ;; calculated by adding offset value to the swap partition's 3767 <1> ;; start address. If the swap device (disk) is a virtual disk 3768 <1> ;; or it is a file, start address of the swap disk/volume is 0, 3769 <1> ;; and offset value is equal to absolute (physical or logical) 3770 <1> ;; address/position. (It has not to be ZERO if the swap partition 3771 <1> ;; is in a partitioned virtual hard disk.) 3772 <1> ;; 3773 <1> ;; Note: Swap addresses are always specified/declared in sectors, 3774 <1> ;; not in bytes or in blocks/zones/clusters (4096 bytes) as unit. 3775 <1> ;; 3776 <1> ;; Swap disk/file allocation is mapped via 'Swap Allocation Table' 3777 <1> ;; at memory as similar to 'Memory Allocation Table'. 3778 <1> ;; 3779 <1> ;; Every bit of Swap Allocation Table repsesents one swap block 3780 <1> ;; (equal to page size) respectively. Bit 0 of the S.A.T. byte 0 3781 <1> ;; is reserved for swap disk/file block 0 as descriptor block 3782 <1> ;; (also for compatibility with PTE). If bit value is ZERO, 3783 <1> ;; it means relevant (respective) block is in use, and, 3784 <1> ;; of course, if bit value is 1, it means relevant (respective) 3785 <1> ;; swap disk/file block is free. 3786 <1> ;; For example: bit 1 of the byte 128 repsesents block 1025 3787 <1> ;; (128*8+1) or sector (offset) 8200 on the swap disk or 3788 <1> ;; byte (offset/position) 4198400 in the swap file. 3789 <1> ;; 4GB swap space is represented via 128KB Swap Allocation Table. 3790 <1> ;; Initial layout of Swap Allocation Table is as follows: 3791 <1> ;; ------------------------------------------------------------ 3792 <1> ;; 0111111111111111111111111 .... 11111111111111111111111111111 3793 <1> ;; ------------------------------------------------------------ 3794 <1> ;; (0 is reserved block, 1s represent free blocks respectively.) 3795 <1> ;; (Note: Allocation cell/unit of the table is bit, not byte) 3796 <1> ;; 3797 <1> ;; .............................................................. 3798 <1> ;; 3799 <1> ;; 'swap_out' procedure checks 'free_swap_blocks' count at first, 3800 <1> ;; then it searches Swap Allocation Table if free count is not 3801 <1> ;; zero. From begining the [swpd_next] dword value, the first bit 3802 <1> ;; position with value of 1 on the table is converted to swap 3803 <1> ;; disk/file offset address, in sectors (not 4096 bytes block). 3804 <1> ;; 'ldrv_write' procedure is called with ldrv (logical drive 3805 <1> ;; number of physical swap disk or virtual swap disk) 3806 <1> ;; number, sector offset (not absolute sector -LBA- number), 3807 <1> ;; and sector count (8, 512*8 = 4096) and buffer adress 3808 <1> ;; (memory page). That will be a direct disk write procedure. 3809 <1> ;; (for preventing late memory allocation, significant waiting). 3810 <1> ;; If disk write procedure returns with error or free count of 3811 <1> ;; swap blocks is ZERO, 'swap_out' procedure will return with 3812 <1> ;; 'insufficient memory error' (cf=1). 3813 <1> ;; 3814 <1> ;; (Note: Even if free swap disk/file blocks was not zero, 3815 <1> ;; any disk write error will not be fixed by 'swap_out' procedure, 3816 <1> ;; in other words, 'swap_out' will not check the table for other 3817 <1> ;; free blocks after a disk write error. It will return to 3818 <1> ;; the caller with error (CF=1) which means swapping is failed. 3819 <1> ;; 3820 <1> ;; After writing the page on to swap disk/file address/sector, 3821 <1> ;; 'swap_out' procedure returns with that swap (offset) sector 3822 <1> ;; address (cf=0). 3823 <1> ;; 3824 <1> ;; .............................................................. 3825 <1> ;; 3826 <1> ;; 'swap_in' procedure loads addressed (relevant) swap disk or 3827 <1> ;; file sectors at specified memory page. Then page allocation 3828 <1> ;; procedure updates relevant page table entry with 'present' 3829 <1> ;; attribute. If swap disk or file reading fails there is nothing 3830 <1> ;; to do, except to terminate the process which is the owner of 3831 <1> ;; the swapped page. 3832 <1> ;; 3833 <1> ;; 'swap_in' procedure sets the relevant/respective bit value 3834 <1> ;; in the Swap Allocation Table (as free block). 'swap_in' also 3835 <1> ;; updates [swpd_first] pointer if it is required. 3836 <1> ;; 3837 <1> ;; .............................................................. 3838 <1> ;; 3839 <1> ;; Note: If [swap_enabled] value is ZERO, that means there is not 3840 <1> ;; a swap disk or swap file in use... 'swap_in' and 'swap_out' 3841 <1> ;; procedures ans 'swap page que' procedures will not be active... 3842 <1> ;; 'Insufficient memory' error will be returned by 'swap_out' 3843 <1> ;; and 'general protection fault' will be returned by 'swap_in' 3844 <1> ;; procedure, if it is called mistakenly (a wrong value in a PTE). 3845 <1> ;; 3846 <1> 3847 <1> ; 17/04/2021 3848 <1> ; ('swap_in' procedure call is disabled as temporary) 3849 <1> 3850 <1> ; 30/11/2021 - temporary ! 3851 <1> ;swap_in: 3852 <1> ; 31/08/2015 3853 <1> ; 20/07/2015 3854 <1> ; 28/04/2015 3855 <1> ; 18/04/2015 3856 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 3857 <1> ; 3858 <1> ; INPUT -> 3859 <1> ; EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE 3860 <1> ; EBP = VIRTUAL (LINEAR) ADDRESS (page fault address) 3861 <1> ; EAX = Offset Address for the swapped page on the 3862 <1> ; swap disk or in the swap file. 3863 <1> ; 3864 <1> ; OUTPUT -> 3865 <1> ; EAX = 0 if loading at memory has been successful 3866 <1> ; 3867 <1> ; CF = 1 -> swap disk reading error (disk/file not present 3868 <1> ; or sector not present or drive not ready 3869 <1> ; EAX = Error code 3870 <1> ; [u.error] = EAX 3871 <1> ; = The last error code for the process 3872 <1> ; (will be reset after returning to user) 3873 <1> ; 3874 <1> ; Modified Registers -> EAX 3875 <1> ; 3876 <1> 3877 <1> ; cmp dword [swp_drv], 0 3878 <1> ; jna short swpin_dnp_err 3879 <1> ; 3880 <1> ; cmp eax, [swpd_size] 3881 <1> ; jnb short swpin_snp_err 3882 <1> ; 3883 <1> ; push esi 3884 <1> ; push ebx 3885 <1> ; push ecx 3886 <1> ; mov esi, [swp_drv] 3887 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 3888 <1> ; ; Note: Even if corresponding physical disk's sector 3889 <1> ; ; size different than 512 bytes, logical disk sector 3890 <1> ; ; size is 512 bytes and disk reading procedure 3891 <1> ; ; will be performed for reading 4096 bytes 3892 <1> ; ; (2*2048, 8*512). 3893 <1> ; ; ESI = Logical disk description table address 3894 <1> ; ; EBX = Memory page (buffer) address (physical!) 3895 <1> ; ; EAX = Sector adress (offset address, logical sector number) 3896 <1> ; ; ECX = Sector count ; 8 sectors 3897 <1> ; push eax 3898 <1> ; call logical_disk_read 3899 <1> ; pop eax 3900 <1> ; jnc short swpin_read_ok 3901 <1> ; ; 3902 <1> ; mov eax, SWP_DISK_READ_ERR ; drive not ready or read error 3903 <1> ; mov [u.error], eax 3904 <1> ; jmp short swpin_retn 3905 <1> ; ; 3906 <1> ;swpin_read_ok: 3907 <1> ; ; EAX = Offset address (logical sector number) 3908 <1> ; call unlink_swap_block ; Deallocate swap block 3909 <1> ; ; 3910 <1> ; ; EBX = Memory page (buffer) address (physical!) 3911 <1> ; ; 20/07/2015 3912 <1> ; mov ebx, ebp ; virtual address (page fault address) 3913 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 3914 <1> ; mov bl, [u.uno] ; current process number 3915 <1> ; ; EBX = Virtual (Linear) address & process number combination 3916 <1> ; call swap_queue_shift 3917 <1> ; ; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0) 3918 <1> ; ;sub eax, eax ; 0 ; Error Code = 0 (no error) 3919 <1> ; ; zf = 1 3920 <1> ;swpin_retn: 3921 <1> ; pop ecx 3922 <1> ; pop ebx 3923 <1> ; pop esi 3924 <1> ; retn 3925 <1> ; 3926 <1> ;swpin_dnp_err: 3927 <1> ; mov eax, SWP_DISK_NOT_PRESENT_ERR 3928 <1> ;swpin_err_retn: 3929 <1> ; mov [u.error], eax 3930 <1> ; stc 3931 <1> ; retn 3932 <1> ; 3933 <1> ;swpin_snp_err: 3934 <1> ; mov eax, SWP_SECTOR_NOT_PRESENT_ERR 3935 <1> ; jmp short swpin_err_retn 3936 <1> 3937 <1> ; 17/04/2021 3938 <1> ; ('swap_out' procedure call is disabled as temporary) 3939 <1> 3940 <1> ; 30/11/2021 - temporary ! 3941 <1> ;swap_out: 3942 <1> ; 10/06/2016 3943 <1> ; 07/06/2016 3944 <1> ; 23/05/2016 3945 <1> ; 19/05/2016 - TRDOS 386 (TRDOS v2.0) 3946 <1> ; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1) 3947 <1> ; 3948 <1> ; INPUT -> 3949 <1> ; none 3950 <1> ; 3951 <1> ; OUTPUT -> 3952 <1> ; EAX = Physical page address (which is swapped out 3953 <1> ; for allocating a new page) 3954 <1> ; CF = 1 -> swap disk writing error (disk/file not present 3955 <1> ; or sector not present or drive not ready 3956 <1> ; EAX = Error code 3957 <1> ; [u.error] = EAX 3958 <1> ; = The last error code for the process 3959 <1> ; (will be reset after returning to user) 3960 <1> ; 3961 <1> ; Modified Registers -> none (except EAX) 3962 <1> ; 3963 <1> 3964 <1> ; cmp word [swpq_count], 1 3965 <1> ; jc swpout_im_err ; 'insufficient memory' 3966 <1> ; 3967 <1> ; ;cmp dword [swp_drv], 1 3968 <1> ; ;jc short swpout_dnp_err ; 'swap disk/file not present' 3969 <1> ; 3970 <1> ; cmp dword [swpd_free], 1 3971 <1> ; jc swpout_nfspc_err ; 'no free space on swap disk' 3972 <1> ; 3973 <1> ; push ebx ; * 3974 <1> ;swpout_1: 3975 <1> ; ; 10/06/2016 3976 <1> ; xor ebx, ebx ; shift the queue and return a PTE value 3977 <1> ; call swap_queue_shift 3978 <1> ; and eax, eax ; 0 = empty queue (improper entries) 3979 <1> ; jz swpout_npts_err ; There is not any proper PTE 3980 <1> ; ; pointer in the swap queue 3981 <1> ; ; EAX = PTE value of the page 3982 <1> ; ; EBX = PTE address of the page 3983 <1> ; and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3984 <1> ; ; 3985 <1> ; ; 07/06/2016 3986 <1> ; ; 19/05/2016 3987 <1> ; ; check this page is in timer events or not 3988 <1> ; 3989 <1> ;swpout_timer_page_0: 3990 <1> ; push edx ; ** 3991 <1> ; 3992 <1> ; ; 07/06/2016 3993 <1> ; cmp byte [timer_events], 0 3994 <1> ; jna short swpout_2 3995 <1> ; ; 3996 <1> ; mov dl, [timer_events] 3997 <1> ; 3998 <1> ; push ecx ; *** 3999 <1> ; push ebx ; **** 4000 <1> ; mov ebx, timer_set ; beginning address of timer event 4001 <1> ; ; structures 4002 <1> ;swpout_timer_page_1: 4003 <1> ; mov cl, [ebx] 4004 <1> ; or cl, cl ; 0 = free, >0 = process number 4005 <1> ; jz short swpout_timer_page_3 4006 <1> ; mov ecx, [ebx+12] ; response (signal return) address 4007 <1> ; and cx, PTE_A_CLEAR ; clear offset part (right 12 bits) 4008 <1> ; ; of the response byte address, to 4009 <1> ; ; get beginning of the page address) 4010 <1> ; cmp eax, ecx 4011 <1> ; jne short swpout_timer_page_2 ; not same page 4012 <1> ; 4013 <1> ; ; !same page! 4014 <1> ; ; 4015 <1> ; ; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! - 4016 <1> ; ; This page will be used by the kernel to put timer event 4017 <1> ; ; response (signal return) byte at the requested address; 4018 <1> ; ; in order to prevent a possible wrong write (while 4019 <1> ; ; this page is swapped out) on physical memory, 4020 <1> ; ; we must protect this page against to be swapped out! 4021 <1> ; ; 4022 <1> ; pop ebx ; **** 4023 <1> ; pop ecx ; *** 4024 <1> ; pop edx ; ** 4025 <1> ; jmp short swpout_1 ; do not swap out this page ! 4026 <1> ; 4027 <1> ;swpout_timer_page_2: 4028 <1> ; ; 07/06/2016 4029 <1> ; dec dl 4030 <1> ; jz short swpout_timer_page_4 4031 <1> ;swpout_timer_page_3: 4032 <1> ; ;cmp ebx, timer_set + 240 ; last timer event (15*16) 4033 <1> ; ;jnb short swpout_timer_page_4 4034 <1> ; add ebx, 16 4035 <1> ; jmp short swpout_timer_page_1 4036 <1> ; 4037 <1> ;swpout_timer_page_4: 4038 <1> ; pop ebx ; **** 4039 <1> ; pop ecx ; *** 4040 <1> ;swpout_2: 4041 <1> ; mov edx, ebx ; Page table entry address 4042 <1> ; mov ebx, eax ; Buffer (Page) Address 4043 <1> ; ; 4044 <1> ; call link_swap_block 4045 <1> ; jnc short swpout_3 ; It may not be needed here 4046 <1> ; ; because [swpd_free] value 4047 <1> ; ; was checked at the beginging. 4048 <1> ; pop edx ; ** 4049 <1> ; pop ebx ; * 4050 <1> ; jmp short swpout_nfspc_err 4051 <1> ;swpout_3: 4052 <1> ; test eax, 80000000h ; test bit 31 (this may not be needed!) 4053 <1> ; jnz short swpout_nfspc_err ; 10/06/2016 (bit 31 = 1 !) 4054 <1> ; ; 4055 <1> ; push esi ; ** 4056 <1> ; push ecx ; *** 4057 <1> ; push eax ; sector address ; (31 bit !, bit 31 = 0) 4058 <1> ; mov esi, [swp_drv] 4059 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 4060 <1> ; ; Note: Even if corresponding physical disk's sector 4061 <1> ; ; size different than 512 bytes, logical disk sector 4062 <1> ; ; size is 512 bytes and disk writing procedure 4063 <1> ; ; will be performed for writing 4096 bytes 4064 <1> ; ; (2*2048, 8*512). 4065 <1> ; ; ESI = Logical disk description table address 4066 <1> ; ; EBX = Buffer (Page) address 4067 <1> ; ; EAX = Sector adress (offset address, logical sector number) 4068 <1> ; ; ECX = Sector count ; 8 sectors 4069 <1> ; ; edx = PTE address 4070 <1> ; call logical_disk_write 4071 <1> ; ; edx = PTE address 4072 <1> ; pop ecx ; sector address 4073 <1> ; jnc short swpout_write_ok 4074 <1> ; ; 4075 <1> ; ;; call unlink_swap_block ; this block must be left as 'in use' 4076 <1> ;swpout_dw_err: 4077 <1> ; mov eax, SWP_DISK_WRITE_ERR ; drive not ready or write error 4078 <1> ; mov [u.error], eax 4079 <1> ; jmp short swpout_retn 4080 <1> ; ; 4081 <1> ;swpout_write_ok: 4082 <1> ; ; EBX = Buffer (page) address 4083 <1> ; ; EDX = Page Table Entry address 4084 <1> ; ; ECX = Swap disk sector (file block) address (31 bit) 4085 <1> ; shl ecx, 1 ; 31 bit sector address from bit 1 to bit 31 4086 <1> ; mov [edx], ecx 4087 <1> ; ; bit 0 = 0 (swapped page) 4088 <1> ; mov eax, ebx 4089 <1> ;swpout_retn: 4090 <1> ; pop ecx ; *** 4091 <1> ; pop esi ; ** 4092 <1> ; pop ebx ; * 4093 <1> ; retn 4094 <1> ; 4095 <1> ;;swpout_dnp_err: 4096 <1> ;; mov eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present 4097 <1> ;; jmp short swpout_err_retn 4098 <1> ;swpout_nfspc_err: 4099 <1> ; mov eax, SWP_NO_FREE_SPACE_ERR ; no free space 4100 <1> ;swpout_err_retn: 4101 <1> ; mov [u.error], eax 4102 <1> ; ;stc 4103 <1> ; retn 4104 <1> ;swpout_npts_err: 4105 <1> ; mov eax, SWP_NO_PAGE_TO_SWAP_ERR 4106 <1> ; pop ebx 4107 <1> ; jmp short swpout_err_retn 4108 <1> ;swpout_im_err: 4109 <1> ; mov eax, ERR_MINOR_IM ; insufficient (out of) memory 4110 <1> ; jmp short swpout_err_retn 4111 <1> 4112 <1> ; 17/04/2021 4113 <1> ; ('swap_queue_shift' procedure call is disabled as temporary) 4114 <1> 4115 <1> ; 30/11/2021 - temporary ! 4116 <1> ;swap_queue_shift: 4117 <1> ; 26/03/2017 4118 <1> ; 10/06/2016 4119 <1> ; 09/06/2016 - TRDOS 386 (TRDOS v2.0) 4120 <1> ; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1) 4121 <1> ; 4122 <1> ; INPUT -> 4123 <1> ; EBX = Virtual (linear) address (bit 12 to 31) 4124 <1> ; and process number combination (bit 0 to 11) 4125 <1> ; EBX = 0 -> shift/drop from the head (offset 0) 4126 <1> ; 4127 <1> ; OUTPUT -> 4128 <1> ; If EBX input > 0 4129 <1> ; the queue will be shifted 4 bytes (dword), 4130 <1> ; from the tail to the head, up to entry offset 4131 <1> ; which points to EBX input value or nothing 4132 <1> ; to do if EBX value is not found on the queue. 4133 <1> ; (The entry -with EBX value- will be removed 4134 <1> ; from the queue if it is found.) 4135 <1> ; 4136 <1> ; EAX = 0 4137 <1> ; 4138 <1> ; If EBX input = 0 4139 <1> ; the queue will be shifted 4 bytes (dword), 4140 <1> ; from the tail to the head, if the PTE address 4141 <1> ; which is pointed in head of the queue is marked 4142 <1> ; as "accessed" or it is marked as "non present". 4143 <1> ; (If "accessed" flag of the PTE -which is pointed 4144 <1> ; in the head- is set -to 1-, it will be reset 4145 <1> ; -to 0- and then, the queue will be rotated 4146 <1> ; -without dropping pointer of the PTE from 4147 <1> ; the queue- for 4 bytes on head to tail direction. 4148 <1> ; Pointer in the head will be moved into the tail, 4149 <1> ; other PTEs will be shifted on head direction.) 4150 <1> ; 4151 <1> ; Swap queue will be shifted up to the first 4152 <1> ; 'present' or 'non accessed' page will be found 4153 <1> ; (as pointed) on the queue head (then it will be 4154 <1> ; removed/dropped from the queue). 4155 <1> ; 4156 <1> ; EAX (> 0) = PTE value of the page which is 4157 <1> ; (it's pointer -virtual address-) dropped 4158 <1> ; (removed) from swap queue. 4159 <1> ; EBX = PTE address of the page (if EAX > 0) 4160 <1> ; which is (it's pointer -virtual address-) 4161 <1> ; dropped (removed) from swap queue. 4162 <1> ; 4163 <1> ; EAX = 0 -> empty swap queue ! 4164 <1> ; 4165 <1> ; Modified Registers -> EAX, EBX 4166 <1> ; 4167 <1> ; movzx eax, word [swpq_count] ; Max. 1024 4168 <1> ; and ax, ax 4169 <1> ; jz short swpqs_retn 4170 <1> ; push edi 4171 <1> ; push esi 4172 <1> ; push ecx 4173 <1> ; mov esi, swap_queue 4174 <1> ; mov ecx, eax 4175 <1> ; or ebx, ebx 4176 <1> ; jz short swpqs_7 4177 <1> ;swpqs_1: 4178 <1> ; lodsd 4179 <1> ; cmp eax, ebx 4180 <1> ; je short swpqs_2 4181 <1> ; loop swpqs_1 4182 <1> ; ; 10/06/2016 4183 <1> ; sub eax, eax 4184 <1> ; jmp short swpqs_6 4185 <1> ;swpqs_2: 4186 <1> ; mov edi, esi 4187 <1> ; sub edi, 4 4188 <1> ;swpqs_3: 4189 <1> ; dec word [swpq_count] 4190 <1> ; jz short swpqs_5 4191 <1> ;swpqs_4: 4192 <1> ; dec ecx 4193 <1> ; rep movsd ; shift up (to the head) 4194 <1> ;swpqs_5: 4195 <1> ; xor eax, eax 4196 <1> ; mov [edi], eax 4197 <1> ;swpqs_6: 4198 <1> ; pop ecx 4199 <1> ; pop esi 4200 <1> ; pop edi 4201 <1> ;swpqs_retn: 4202 <1> ; retn 4203 <1> ;swpqs_7: 4204 <1> ; mov edi, esi ; head 4205 <1> ; lodsd 4206 <1> ; ; 20/07/2015 4207 <1> ; mov ebx, eax 4208 <1> ; and ebx, ~PAGE_OFF ; ~0FFFh 4209 <1> ; ; ebx = virtual address (at page boundary) 4210 <1> ; and eax, PAGE_OFF ; 0FFFh 4211 <1> ; ; ax = process number (1 to 4095) 4212 <1> ; cmp al, [u.uno] 4213 <1> ; ; Max. 16 (nproc) processes for Retro UNIX 386 v1 4214 <1> ; jne short swpqs_8 4215 <1> ; mov eax, [u.pgdir] 4216 <1> ; jmp short swpqs_9 4217 <1> ;swpqs_8: 4218 <1> ; ; 09/06/2016 4219 <1> ; cmp byte [eax+p.stat-1], 0 4220 <1> ; jna short swpqs_3 ; free (or terminated) process 4221 <1> ; cmp byte [eax+p.stat-1], 2 ; waiting 4222 <1> ; ja short swpqs_3 ; zombie (3) or undefined ? 4223 <1> ; 4224 <1> ; ;shl ax, 2 4225 <1> ; shl al, 2 4226 <1> ; mov eax, [eax+p.upage-4] 4227 <1> ; or eax, eax 4228 <1> ; jz short swpqs_3 ; invalid upage 4229 <1> ; add eax, u.pgdir - user 4230 <1> ; ; u.pgdir value for the process 4231 <1> ; ; is in [eax] 4232 <1> ; mov eax, [eax] 4233 <1> ; and eax, eax 4234 <1> ; jz short swpqs_3 ; invalid page directory 4235 <1> ;swpqs_9: 4236 <1> ; push edx 4237 <1> ; ; eax = page directory 4238 <1> ; ; ebx = virtual address 4239 <1> ; call get_pte 4240 <1> ; mov ebx, edx ; PTE address 4241 <1> ; pop edx 4242 <1> ; ; 10/06/2016 4243 <1> ; jc short swpqs_13 ; empty PDE 4244 <1> ; ; EAX = PTE value 4245 <1> ; test al, PTE_A_PRESENT ; bit 0 = 1 4246 <1> ; jz short swpqs_13 ; Drop non-present page 4247 <1> ; ; from the queue (head) 4248 <1> ; test al, PTE_A_WRITE ; bit 1 = 0 (read only) 4249 <1> ; jz short swpqs_13 ; Drop read only page 4250 <1> ; ; from the queue (head) 4251 <1> ; ;test al, PTE_A_ACCESS ; bit 5 = 1 (Accessed) 4252 <1> ; ;jnz short swpqs_11 ; present 4253 <1> ; ; accessed page 4254 <1> ; btr eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit 4255 <1> ; jc short swpqs_11 ; accessed page 4256 <1> ; 4257 <1> ; dec ecx 4258 <1> ; mov [swpq_count], cx 4259 <1> ; jz short swpqs_10 4260 <1> ; ; esi = head + 4 4261 <1> ; ; edi = head 4262 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 4263 <1> ;swpqs_10: 4264 <1> ; mov [edi], ecx ; 0 4265 <1> ; jmp short swpqs_6 ; 26/03/2017 4266 <1> ; 4267 <1> ;swpqs_11: 4268 <1> ; mov [ebx], eax ; save changed attribute 4269 <1> ; ; Rotation (head -> tail) 4270 <1> ; dec ecx ; entry count -> last entry number 4271 <1> ; jz short swpqs_10 4272 <1> ; ; esi = head + 4 4273 <1> ; ; edi = head 4274 <1> ; mov eax, [edi] ; 20/07/2015 4275 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 4276 <1> ; mov [edi], eax ; head -> tail ; [k] = [1] 4277 <1> ; 4278 <1> ; mov cx, [swpq_count] 4279 <1> ; 4280 <1> ;swpqs_12: 4281 <1> ; mov esi, swap_queue ; head 4282 <1> ; jmp swpqs_7 4283 <1> ; 4284 <1> ;swpqs_13: 4285 <1> ; dec ecx 4286 <1> ; mov [swpq_count], cx 4287 <1> ; jz swpqs_5 4288 <1> ; jmp short swpqs_12 4289 <1> 4290 <1> ; 17/04/2021 4291 <1> ; ('add_to_swp_queue' procedure call is disabled as temporary) 4292 <1> 4293 <1> ; 30/11/2021 - temporary ! 4294 <1> ;add_to_swap_queue: 4295 <1> ; 20/02/2017 4296 <1> ; 20/07/2015 4297 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4298 <1> ; 4299 <1> ; Adds new page to swap queue 4300 <1> ; (page directories and page tables must not be added 4301 <1> ; to swap queue) 4302 <1> ; 4303 <1> ; INPUT -> 4304 <1> ; EBX = Linear (Virtual) addr for current process 4305 <1> ; [u.uno] 4306 <1> ; 20/02/2017 4307 <1> ; (Linear address = CORE + user's virtual address) 4308 <1> ; 4309 <1> ; OUTPUT -> 4310 <1> ; EAX = [swpq_count] 4311 <1> ; (after the PTE has been added) 4312 <1> ; EAX = 0 -> Swap queue is full, (1024 entries) 4313 <1> ; the PTE could not be added. 4314 <1> ; 4315 <1> ; Modified Registers -> EAX 4316 <1> ; 4317 <1> ; push ebx 4318 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 4319 <1> ; mov bl, [u.uno] ; current process number 4320 <1> ; call swap_queue_shift ; drop from the queue if 4321 <1> ; ; it is already on the queue 4322 <1> ; ; then add it to the tail of the queue 4323 <1> ; movzx eax, word [swpq_count] 4324 <1> ; cmp ax, 1024 4325 <1> ; jb short atsq_1 4326 <1> ; sub ax, ax 4327 <1> ; pop ebx 4328 <1> ; retn 4329 <1> ;atsq_1: 4330 <1> ; push esi 4331 <1> ; mov esi, swap_queue 4332 <1> ; and ax, ax 4333 <1> ; jz short atsq_2 4334 <1> ; shl ax, 2 ; convert to offset 4335 <1> ; add esi, eax 4336 <1> ; shr ax, 2 4337 <1> ;atsq_2: 4338 <1> ; inc ax 4339 <1> ; mov [esi], ebx ; Virtual address + [u.uno] combination 4340 <1> ; mov [swpq_count], ax 4341 <1> ; pop esi 4342 <1> ; pop ebx 4343 <1> ; retn 4344 <1> 4345 <1> ; 17/04/2021 4346 <1> ; ('unlink_swap_block' procedure call is disabled as temporary) 4347 <1> 4348 <1> ; 30/11/2021 - temporary ! 4349 <1> ;unlink_swap_block: 4350 <1> ; 15/09/2015 4351 <1> ; 30/04/2015 4352 <1> ; 18/04/2015 4353 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4354 <1> ; 4355 <1> ; INPUT -> 4356 <1> ; EAX = swap disk/file offset address 4357 <1> ; (bit 1 to bit 31) 4358 <1> ; OUTPUT -> 4359 <1> ; [swpd_free] is increased 4360 <1> ; (corresponding SWAP DISK ALLOC. TABLE bit is SET) 4361 <1> ; 4362 <1> ; Modified Registers -> EAX 4363 <1> ; 4364 <1> ; push ebx 4365 <1> ; push edx 4366 <1> ; ; 4367 <1> ; shr eax, SECTOR_SHIFT+1 ;3+1 ; shift sector address to 4368 <1> ; ; 3 bits right 4369 <1> ; ; to get swap block/page number 4370 <1> ; mov edx, eax 4371 <1> ; ; 15/09/2015 4372 <1> ; shr edx, 3 ; to get offset to S.A.T. 4373 <1> ; ; (1 allocation bit = 1 page) 4374 <1> ; ; (1 allocation bytes = 8 pages) 4375 <1> ; and dl, 0FCh ; clear lower 2 bits 4376 <1> ; ; (to get 32 bit position) 4377 <1> ; ; 4378 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table address 4379 <1> ; add ebx, edx 4380 <1> ; and eax, 1Fh ; lower 5 bits only 4381 <1> ; ; (allocation bit position) 4382 <1> ; cmp eax, [swpd_next] ; is the new free block addr. lower 4383 <1> ; ; than the address in 'swpd_next' ? 4384 <1> ; ; (next/first free block value) 4385 <1> ; jnb short uswpbl_1 ; no 4386 <1> ; mov [swpd_next], eax ; yes 4387 <1> ;uswpbl_1: 4388 <1> ; bts [ebx], eax ; unlink/release/deallocate block 4389 <1> ; ; set relevant bit to 1. 4390 <1> ; ; set CF to the previous bit value 4391 <1> ; cmc ; complement carry flag 4392 <1> ; jc short uswpbl_2 ; do not increase swfd_free count 4393 <1> ; ; if the block is already deallocated 4394 <1> ; ; before. 4395 <1> ; inc dword [swpd_free] 4396 <1> ;uswpbl_2: 4397 <1> ; pop edx 4398 <1> ; pop ebx 4399 <1> ; retn 4400 <1> 4401 <1> ; 17/04/2021 4402 <1> ; ('link_swap_block' procedure call is disabled as temporary) 4403 <1> 4404 <1> ; 30/11/2021 - temporary ! 4405 <1> ;link_swap_block: 4406 <1> ; 01/07/2015 4407 <1> ; 18/04/2015 4408 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4409 <1> ; 4410 <1> ; INPUT -> none 4411 <1> ; 4412 <1> ; OUTPUT -> 4413 <1> ; EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes) 4414 <1> ; in sectors (corresponding 4415 <1> ; SWAP DISK ALLOCATION TABLE bit is RESET) 4416 <1> ; 4417 <1> ; CF = 1 and EAX = 0 4418 <1> ; if there is not a free block to be allocated 4419 <1> ; 4420 <1> ; Modified Registers -> none (except EAX) 4421 <1> ; 4422 <1> 4423 <1> ; ;mov eax, [swpd_free] 4424 <1> ; ;and eax, eax 4425 <1> ; ;jz short out_of_swpspc 4426 <1> ; ; 4427 <1> ; push ebx 4428 <1> ; push ecx 4429 <1> ; ; 4430 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table offset 4431 <1> ; mov ecx, ebx 4432 <1> ; add ebx, [swpd_next] ; Free block searching starts from here 4433 <1> ; ; next_free_swap_block >> 5 4434 <1> ; add ecx, [swpd_last] ; Free block searching ends here 4435 <1> ; ; (total_swap_blocks - 1) >> 5 4436 <1> ;lswbl_scan: 4437 <1> ; cmp ebx, ecx 4438 <1> ; ja short lswbl_notfound 4439 <1> ; ; 4440 <1> ; bsf eax, [ebx] ; Scans source operand for first bit set (1). 4441 <1> ; ; Clears ZF if a bit is found set (1) and 4442 <1> ; ; loads the destination with an index to 4443 <1> ; ; first set bit. (0 -> 31) 4444 <1> ; ; Sets ZF to 1 if no bits are found set. 4445 <1> ; ; 01/07/2015 4446 <1> ; jnz short lswbl_found ; ZF = 0 -> a free block has been found 4447 <1> ; ; 4448 <1> ; ; NOTE: a Swap Disk Allocation Table bit 4449 <1> ; ; with value of 1 means 4450 <1> ; ; the corresponding page is free 4451 <1> ; ; (Retro UNIX 386 v1 feaure only!) 4452 <1> ; add ebx, 4 4453 <1> ; ; We return back for searching next page block 4454 <1> ; ; NOTE: [swpd_free] is not ZERO; so, 4455 <1> ; ; we always will find at least 1 free block here. 4456 <1> ; jmp short lswbl_scan 4457 <1> ; ; 4458 <1> ;lswbl_notfound: 4459 <1> ; sub ecx, swap_alloc_table 4460 <1> ; mov [swpd_next], ecx ; next/first free page = last page 4461 <1> ; ; (unlink_swap_block procedure will change it) 4462 <1> ; xor eax, eax 4463 <1> ; mov [swpd_free], eax 4464 <1> ; stc 4465 <1> ;lswbl_ok: 4466 <1> ; pop ecx 4467 <1> ; pop ebx 4468 <1> ; retn 4469 <1> ; ; 4470 <1> ;;out_of_swpspc: 4471 <1> ;; stc 4472 <1> ;; retn 4473 <1> ; 4474 <1> ;lswbl_found: 4475 <1> ; mov ecx, ebx 4476 <1> ; sub ecx, swap_alloc_table 4477 <1> ; mov [swpd_next], ecx ; Set first free block searching start 4478 <1> ; ; address/offset (to the next) 4479 <1> ; dec dword [swpd_free] ; 1 block has been allocated (X = X-1) 4480 <1> ; ; 4481 <1> ; btr [ebx], eax ; The destination bit indexed by the source value 4482 <1> ; ; is copied into the Carry Flag and then cleared 4483 <1> ; ; in the destination. 4484 <1> ; ; 4485 <1> ; ; Reset the bit which is corresponding to the 4486 <1> ; ; (just) allocated block. 4487 <1> ; shl ecx, 5 ; (block offset * 32) + block index 4488 <1> ; add eax, ecx ; = block number 4489 <1> ; shl eax, SECTOR_SHIFT ; 3, sector (offset) address of the block 4490 <1> ; ; 1 block = 8 sectors 4491 <1> ; ; 4492 <1> ; ; EAX = offset address of swap disk/file sector (beginning of the block) 4493 <1> ; ; 4494 <1> ; ; NOTE: The relevant page table entry will be updated 4495 <1> ; ; according to this EAX value... 4496 <1> ; ; 4497 <1> ; jmp short lswbl_ok 4498 <1> 4499 <1> ; 17/04/2021 4500 <1> ; ('logical_disk_read' procedure call is disabled as temporary) 4501 <1> 4502 <1> ; 30/11/2021 - temporary ! 4503 <1> ;logical_disk_read: 4504 <1> ; 20/07/2015 4505 <1> ; 09/03/2015 (temporary code here) 4506 <1> ; 4507 <1> ; INPUT -> 4508 <1> ; ESI = Logical disk description table address 4509 <1> ; EBX = Memory page (buffer) address (physical!) 4510 <1> ; EAX = Sector adress (offset address, logical sector number) 4511 <1> ; ECX = Sector count 4512 <1> ; 4513 <1> ; 4514 <1> ; retn 4515 <1> 4516 <1> ; 17/04/2021 4517 <1> ; ('logical_disk_write' procedure call is disabled as temporary) 4518 <1> 4519 <1> ; 30/11/2021 - temporary ! 4520 <1> ;logical_disk_write: 4521 <1> ; 20/07/2015 4522 <1> ; 09/03/2015 (temporary code here) 4523 <1> ; 4524 <1> ; INPUT -> 4525 <1> ; ESI = Logical disk description table address 4526 <1> ; EBX = Memory page (buffer) address (physical!) 4527 <1> ; EAX = Sector adress (offset address, logical sector number) 4528 <1> ; ECX = Sector count 4529 <1> ; 4530 <1> ; retn 4531 <1> 4532 <1> get_physical_addr: 4533 <1> ; 17/04/2021 - Retro UNIX 386 v2 4534 <1> ; (temporary modifications) 4535 <1> ; 19/04/2020 - Retro UNIX 386 v2 4536 <1> ; 18/10/2015 4537 <1> ; 29/07/2015 4538 <1> ; 20/07/2015 4539 <1> ; 04/06/2015 4540 <1> ; 20/05/2015 4541 <1> ; 28/04/2015 4542 <1> ; 18/04/2015 4543 <1> ; Get physical address 4544 <1> ; (allocates a new page for user if it is not present) 4545 <1> ; 4546 <1> ; (This subroutine is needed for mapping user's virtual 4547 <1> ; (buffer) address to physical address (of the buffer).) 4548 <1> ; ('sys write', 'sys read' system calls...) 4549 <1> ; 4550 <1> ; INPUT -> 4551 <1> ; EBX = virtual address 4552 <1> ; u.pgdir = page directory (physical) address 4553 <1> ; 4554 <1> ; OUTPUT -> 4555 <1> ; EAX = physical address 4556 <1> ; EBX = linear address 4557 <1> ; EDX = physical address of the page frame 4558 <1> ; (with attribute bits) 4559 <1> ; ECX = byte count within the page frame 4560 <1> ; 4561 <1> ; Modified Registers -> EAX, EBX, ECX, EDX 4562 <1> ; 4563 <1> 4564 <1> ; 19/04/2020 - Retro UNIX386 v2 4565 00003254 A1[046F0000] <1> mov eax, [u.pgdir] 4566 <1> 4567 <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2 4568 <1> 4569 00003259 81C300004000 <1> add ebx, CORE ; 18/10/2015 4570 <1> ; 4571 <1> ;mov eax, [u.pgdir] 4572 0000325F E816FDFFFF <1> call get_pte 4573 <1> ; EDX = Page table entry address (if CF=0) 4574 <1> ; Page directory entry address (if CF=1) 4575 <1> ; (Bit 0 value is 0 if PT is not present) 4576 <1> ; EAX = Page table entry value (page address) 4577 <1> ; CF = 1 -> PDE not present or invalid ? 4578 00003264 731C <1> jnc short gpa_1 4579 <1> ; 4580 00003266 E8FDFBFFFF <1> call allocate_page 4581 0000326B 724B <1> jc short gpa_im_err ; 'insufficient memory' error 4582 <1> gpa_0: 4583 0000326D E867FCFFFF <1> call clear_page 4584 <1> ; EAX = Physical (base) address of the allocated (new) page 4585 00003272 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7 4586 <1> ; lower 3 bits are used as U/S, R/W, P flags 4587 <1> ; (user, writable, present page) 4588 00003274 8902 <1> mov [edx], eax ; Let's put the new page directory entry here ! 4589 00003276 A1[046F0000] <1> mov eax, [u.pgdir] 4590 0000327B E8FAFCFFFF <1> call get_pte 4591 00003280 7236 <1> jc short gpa_im_err ; 'insufficient memory' error 4592 <1> gpa_1: 4593 <1> ; EAX = PTE value, EDX = PTE address 4594 00003282 A801 <1> test al, PTE_A_PRESENT 4595 00003284 750A <1> jnz short gpa_3 4596 00003286 09C0 <1> or eax, eax 4597 00003288 7420 <1> jz short gpa_4 ; Allocate a new page 4598 <1> 4599 <1> ; 17/04/2021 4600 <1> ; ('reload_page' procedure call is disabled as temporary) 4601 0000328A EB2C <1> jmp short gpa_im_err ; temporary ! 4602 <1> 4603 <1> ; 20/07/2015 4604 <1> ; push ebp 4605 <1> ; mov ebp, ebx ; virtual (linear) address 4606 <1> ; ; reload swapped page 4607 <1> ; call reload_page ; 28/04/2015 4608 <1> ; pop ebp 4609 <1> ; jc short gpa_retn 4610 <1> gpa_2: 4611 <1> ; 17/04/2021 4612 <1> ; ('add_to_swap_queue' procedure call is disabled as temporary) 4613 <1> 4614 <1> ; 20/07/2015 4615 <1> ; 20/05/2015 4616 <1> ; add this page to swap queue 4617 <1> ; push eax 4618 <1> ; ; EBX = Linear (CORE+virtual) address ; 20/02/2017 4619 <1> ; call add_to_swap_queue 4620 <1> ; pop eax 4621 <1> ; PTE address in EDX 4622 <1> ; virtual address in EBX 4623 <1> 4624 <1> ; EAX = memory page address 4625 0000328C 0C07 <1> or al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE 4626 <1> ; present flag, bit 0 = 1 4627 <1> ; user flag, bit 2 = 1 4628 <1> ; writable flag, bit 1 = 1 4629 0000328E 8902 <1> mov [edx], eax ; Update PTE value 4630 <1> gpa_3: 4631 <1> ; 18/10/2015 4632 00003290 89D9 <1> mov ecx, ebx 4633 00003292 81E1FF0F0000 <1> and ecx, PAGE_OFF 4634 00003298 89C2 <1> mov edx, eax 4635 0000329A 662500F0 <1> and ax, PTE_A_CLEAR 4636 0000329E 01C8 <1> add eax, ecx 4637 000032A0 F7D9 <1> neg ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095 4638 000032A2 81C100100000 <1> add ecx, PAGE_SIZE 4639 000032A8 F8 <1> clc 4640 <1> gpa_retn: 4641 000032A9 C3 <1> retn 4642 <1> gpa_4: 4643 000032AA E8B9FBFFFF <1> call allocate_page 4644 000032AF 7207 <1> jc short gpa_im_err ; 'insufficient memory' error 4645 000032B1 E823FCFFFF <1> call clear_page 4646 000032B6 EBD4 <1> jmp short gpa_2 4647 <1> 4648 <1> gpa_im_err: 4649 000032B8 B804000000 <1> mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 4650 <1> ; Major error = 0 (No protection fault) 4651 000032BD C3 <1> retn 4652 <1> 4653 <1> ; 17/04/2021 4654 <1> ; ('reload_page' procedure call is disabled as temporary) 4655 <1> 4656 <1> ; 30/11/2021 - temporary ! 4657 <1> ;reload_page: 4658 <1> ; 20/07/2015 4659 <1> ; 28/04/2015 (Retro UNIX 386 v1 - beginning) 4660 <1> ; 4661 <1> ; Reload (Restore) swapped page at memory 4662 <1> ; 4663 <1> ; INPUT -> 4664 <1> ; EBP = Virtual (linear) memory address 4665 <1> ; EAX = PTE value (swap disk sector address) 4666 <1> ; (Swap disk sector address = bit 1 to bit 31 of EAX) 4667 <1> ; OUTPUT -> 4668 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE 4669 <1> ; 4670 <1> ; CF = 1 and EAX = error code 4671 <1> ; 4672 <1> ; Modified Registers -> none (except EAX) 4673 <1> ; 4674 <1> ; shr eax, 1 ; Convert PTE value to swap disk address 4675 <1> ; push ebx ; 4676 <1> ; mov ebx, eax ; Swap disk (offset) address 4677 <1> ; call allocate_page 4678 <1> ; jc short rlp_im_err 4679 <1> ; xchg eax, ebx 4680 <1> ; ; EBX = Physical memory (page) address 4681 <1> ; ; EAX = Swap disk (offset) address 4682 <1> ; ; EBP = Virtual (linear) memory address 4683 <1> ; call swap_in 4684 <1> ; jc short rlp_swp_err ; (swap disk/file read error) 4685 <1> ; mov eax, ebx 4686 <1> ;rlp_retn: 4687 <1> ; pop ebx 4688 <1> ; retn 4689 <1> ; 4690 <1> ;rlp_im_err: 4691 <1> ; mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 4692 <1> ; ; Major error = 0 (No protection fault) 4693 <1> ; jmp short rlp_retn 4694 <1> ; 4695 <1> ;rlp_swp_err: 4696 <1> ; mov eax, SWP_DISK_READ_ERR ; Swap disk read error ! 4697 <1> ; jmp short rlp_retn 4698 <1> 4699 <1> copy_page_dir: 4700 <1> ; 17/04/2021 (temporary modifications) 4701 <1> ; 19/09/2015 4702 <1> ; temporary - 07/09/2015 4703 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 4704 <1> ; 4705 <1> ; INPUT -> 4706 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 4707 <1> ; page directory. 4708 <1> ; OUTPUT -> 4709 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 4710 <1> ; page directory. 4711 <1> ; (New page directory with new page table entries.) 4712 <1> ; (New page tables with read only copies of the parent's 4713 <1> ; pages.) 4714 <1> ; EAX = 0 -> Error (CF = 1) 4715 <1> ; 4716 <1> ; Modified Registers -> none (except EAX) 4717 <1> ; 4718 000032BE E8A5FBFFFF <1> call allocate_page 4719 000032C3 723E <1> jc short cpd_err 4720 <1> ; 4721 000032C5 55 <1> push ebp ; 20/07/2015 4722 000032C6 56 <1> push esi 4723 000032C7 57 <1> push edi 4724 000032C8 53 <1> push ebx 4725 000032C9 51 <1> push ecx 4726 000032CA 8B35[046F0000] <1> mov esi, [u.pgdir] 4727 000032D0 89C7 <1> mov edi, eax 4728 000032D2 50 <1> push eax ; save child's page directory address 4729 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 4730 <1> ; (use same system space for all user page tables) 4731 000032D3 A5 <1> movsd 4732 000032D4 BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 4733 000032D9 B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 4734 <1> cpd_0: 4735 000032DE AD <1> lodsd 4736 <1> ;or eax, eax 4737 <1> ;jnz short cpd_1 4738 000032DF A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 4739 000032E1 7508 <1> jnz short cpd_1 4740 <1> ; (virtual address at the end of the page table) 4741 000032E3 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 4742 000032E9 EB0F <1> jmp short cpd_2 4743 <1> cpd_1: 4744 000032EB 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 4745 000032EF 89C3 <1> mov ebx, eax 4746 <1> ; EBX = Parent's page table address 4747 000032F1 E81F000000 <1> call copy_page_table 4748 000032F6 720C <1> jc short cpd_p_err 4749 <1> ; EAX = Child's page table address 4750 000032F8 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 4751 <1> ; set bit 0, bit 1 and bit 2 to 1 4752 <1> ; (present, writable, user) 4753 <1> cpd_2: 4754 000032FA AB <1> stosd 4755 000032FB E2E1 <1> loop cpd_0 4756 <1> ; 4757 000032FD 58 <1> pop eax ; restore child's page directory address 4758 <1> cpd_3: 4759 000032FE 59 <1> pop ecx 4760 000032FF 5B <1> pop ebx 4761 00003300 5F <1> pop edi 4762 00003301 5E <1> pop esi 4763 00003302 5D <1> pop ebp 4764 <1> cpd_err: 4765 00003303 C3 <1> retn 4766 <1> cpd_p_err: 4767 <1> ; release the allocated pages missing (recover free space) 4768 00003304 58 <1> pop eax ; the new page directory address (physical) 4769 00003305 8B1D[046F0000] <1> mov ebx, [u.pgdir] ; parent's page directory address 4770 0000330B E888FCFFFF <1> call deallocate_page_dir 4771 00003310 29C0 <1> sub eax, eax ; 0 4772 00003312 F9 <1> stc 4773 00003313 EBE9 <1> jmp short cpd_3 4774 <1> 4775 <1> copy_page_table: 4776 <1> ; 17/04/2021 (temporary modifications) 4777 <1> ; 19/09/2015 4778 <1> ; temporary - 07/09/2015 4779 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 4780 <1> ; 4781 <1> ; INPUT -> 4782 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 4783 <1> ; EBP = page table entry index (from 'copy_page_dir') 4784 <1> ; OUTPUT -> 4785 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 4786 <1> ; EBP = (recent) page table index (for 'add_to_swap_queue') 4787 <1> ; CF = 1 -> error 4788 <1> ; 4789 <1> ; Modified Registers -> EBP (except EAX) 4790 <1> ; 4791 00003315 E84EFBFFFF <1> call allocate_page 4792 0000331A 7244 <1> jc short cpt_err 4793 <1> ; 4794 0000331C 50 <1> push eax ; * 4795 <1> ;push ebx 4796 0000331D 56 <1> push esi 4797 0000331E 57 <1> push edi 4798 0000331F 52 <1> push edx 4799 00003320 51 <1> push ecx 4800 <1> ; 4801 00003321 89DE <1> mov esi, ebx 4802 00003323 89C7 <1> mov edi, eax 4803 00003325 89C2 <1> mov edx, eax 4804 00003327 81C200100000 <1> add edx, PAGE_SIZE 4805 <1> cpt_0: 4806 0000332D AD <1> lodsd 4807 0000332E A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 4808 <1> ;jnz short cpt_1 (*) 4809 <1> ; 17/04/2021 (temporary (*) 4810 <1> ;and eax, eax (*) 4811 00003330 741E <1> jz short cpt_2 ; 17/04/2021 4812 <1> 4813 <1> ; 17/04/2021 4814 <1> ; ('reload_page' procedure call is disabled as temporary) 4815 <1> ; 4816 <1> ; ; ebp = virtual (linear) address of the memory page 4817 <1> ; call reload_page ; 28/04/2015 4818 <1> ; jc short cpt_p_err 4819 <1> cpt_1: 4820 00003332 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 4821 00003336 89C1 <1> mov ecx, eax 4822 <1> ; Allocate a new page for the child process 4823 00003338 E82BFBFFFF <1> call allocate_page 4824 0000333D 721C <1> jc short cpt_p_err 4825 0000333F 57 <1> push edi 4826 00003340 56 <1> push esi 4827 00003341 89CE <1> mov esi, ecx 4828 00003343 89C7 <1> mov edi, eax 4829 00003345 B900040000 <1> mov ecx, PAGE_SIZE/4 4830 0000334A F3A5 <1> rep movsd ; copy page (4096 bytes) 4831 0000334C 5E <1> pop esi 4832 0000334D 5F <1> pop edi 4833 <1> ; 4834 <1> ; 17/04/2021 4835 <1> ; ('add_to_swap_queue' procedure call is disabled as temporary) 4836 <1> ; 4837 <1> ; push ebx 4838 <1> ; push eax 4839 <1> ; mov ebx, ebp 4840 <1> ; ; ebx = virtual address of the memory page 4841 <1> ; call add_to_swap_queue 4842 <1> ; pop eax 4843 <1> ; pop ebx 4844 <1> ; 4845 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 4846 0000334E 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 4847 <1> cpt_2: 4848 00003350 AB <1> stosd ; EDI points to child's PTE 4849 <1> ; 4850 00003351 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 4851 <1> ; 4852 00003357 39D7 <1> cmp edi, edx 4853 00003359 72D2 <1> jb short cpt_0 4854 <1> cpt_p_err: 4855 0000335B 59 <1> pop ecx 4856 0000335C 5A <1> pop edx 4857 0000335D 5F <1> pop edi 4858 0000335E 5E <1> pop esi 4859 <1> ;pop ebx 4860 0000335F 58 <1> pop eax ; * 4861 <1> cpt_err: 4862 00003360 C3 <1> retn 4863 <1> 4864 <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS /// 4865 <1> 4866 <1> ;; Data: 4867 <1> 4868 <1> ; 09/03/2015 4869 <1> ;swpq_count: dw 0 ; count of pages on the swap que 4870 <1> ;swp_drv: dd 0 ; logical drive description table address of the swap drive/disk 4871 <1> ;swpd_size: dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 4872 <1> ;swpd_free: dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical) 4873 <1> ;swpd_next: dd 0 ; next free page block 4874 <1> ;swpd_last: dd 0 ; last swap page block 2074 %include 'sysdefs.s' ; 09/03/2015 2075 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2076 <1> ; (re-write kernel for test by using previous version without a major defect) 2077 <1> ; **************************************************************************** 2078 <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC 2079 <1> ; Last Modification: 10/01/2022 2080 <1> ; 2081 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 2082 <1> ; (Modified from 2083 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 2084 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 2085 <1> ; UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11) 2086 <1> ; ---------------------------------------------------------------------------- 2087 <1> ; 2088 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2089 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2090 <1> ; 2091 <1> ; 2092 <1> ; 2093 <1> ; **************************************************************************** 2094 <1> 2095 <1> nproc equ 16 ; number of processes 2096 <1> ntty equ 8 ; 8+1 -> 8 (10/05/2013) 2097 <1> nbuf equ 6 ; number of buffers (04/02/2016) 2098 <1> nfiles equ 50 ; NFILES equ 50 ; 02/01/2022 2099 <1> 2100 <1> ; 27/12/2021 2101 <1> ;NFILES equ 32 ; temporary ! ( 27/12/2021) 2102 <1> ; 02/01/2022 2103 <1> ;OPENFILES equ 10 ; open files (for user) ; 28/03/2020 2104 <1> 2105 <1> ;csgmnt equ 2000h ; 26/05/2013 (segment of process 1) 2106 <1> ;core equ 0 ; 19/04/2013 2107 <1> ;ecore equ 32768 - 64 ; 04/06/2013 (24/05/2013) 2108 <1> ; (if total size of argument list and arguments is 128 bytes) 2109 <1> ; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes 2110 <1> ; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570) 2111 <1> ; initial value of user's stack pointer = 32768-64-128-2 = 32574 2112 <1> ; (sp=32768-args_space-2 at the beginning of execution) 2113 <1> ; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes) 2114 <1> ; 'u' structure offset (for the '/core' dump file) = 32704 2115 <1> ; '/core' dump file size = 32768 bytes 2116 <1> 2117 <1> ; 08/03/2014 2118 <1> ;sdsegmnt equ 6C0h ; 256*16 bytes (swap data segment size for 16 processes) 2119 <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only ! 2120 <1> ;;sdsegmnt equ 740h ; swap data segment (for user structures and registers) 2121 <1> 2122 <1> ; 30/08/2013 2123 <1> time_count equ 4 ; 10 --> 4 01/02/2014 2124 <1> 2125 <1> ; 05/02/2014 2126 <1> ; process status 2127 <1> ;SFREE equ 0 2128 <1> ;SRUN equ 1 2129 <1> ;SWAIT equ 2 2130 <1> ;SZOMB equ 3 2131 <1> ;SSLEEP equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup) 2132 <1> 2133 <1> ; 09/03/2015 2134 <1> userdata equ 80000h ; user structure data address for current user ; temporary 2135 <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary 2136 <1> swap_alloc_table equ 0D0000h ; swap allocation table address ; temporary 2137 <1> 2138 <1> ; 17/09/2015 2139 <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return 2140 <1> 2141 <1> ; 21/09/2015 (36) 2142 <1> ; 01/07/2015 (35) 2143 <1> ; 14/07/2013 (0-34) 2144 <1> ; UNIX v1 system calls 2145 <1> _rele equ 0 2146 <1> _exit equ 1 2147 <1> _fork equ 2 2148 <1> _read equ 3 2149 <1> _write equ 4 2150 <1> _open equ 5 2151 <1> _close equ 6 2152 <1> _wait equ 7 2153 <1> _creat equ 8 2154 <1> _link equ 9 2155 <1> _unlink equ 10 2156 <1> _exec equ 11 2157 <1> _chdir equ 12 2158 <1> _time equ 13 2159 <1> _mkdir equ 14 2160 <1> _chmod equ 15 2161 <1> _chown equ 16 2162 <1> _break equ 17 2163 <1> _stat equ 18 2164 <1> _seek equ 19 2165 <1> _tell equ 20 2166 <1> _mount equ 21 2167 <1> _umount equ 22 2168 <1> _setuid equ 23 2169 <1> _getuid equ 24 2170 <1> _stime equ 25 2171 <1> _quit equ 26 2172 <1> _intr equ 27 2173 <1> _fstat equ 28 2174 <1> _emt equ 29 2175 <1> _mdate equ 30 2176 <1> _stty equ 31 2177 <1> _gtty equ 32 2178 <1> _ilgins equ 33 2179 <1> _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 2180 <1> _msg equ 35 ; Retro UNIX 386 v1 feature only ! 2181 <1> _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 2182 <1> 2183 <1> %macro sys 1-4 2184 <1> ; 13/04/2015 2185 <1> ; Retro UNIX 386 v1 system call. 2186 <1> mov eax, %1 2187 <1> %if %0 >= 2 2188 <1> mov ebx, %2 2189 <1> %if %0 >= 3 2190 <1> mov ecx, %3 2191 <1> %if %0 = 4 2192 <1> mov edx, %4 2193 <1> %endif 2194 <1> %endif 2195 <1> %endif 2196 <1> int 30h 2197 <1> %endmacro 2198 <1> 2199 <1> ; 13/05/2015 - ERROR CODES 2200 <1> ERR_FILE_NOT_OPEN equ 10 ; 'file not open !' error 2201 <1> ERR_FILE_ACCESS equ 11 ; 'permission denied !' error 2202 <1> ; 14/05/2015 2203 <1> ERR_DIR_ACCESS equ 11 ; 'permission denied !' error 2204 <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error 2205 <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error 2206 <1> ERR_DIR_EXISTS equ 14 ; 'directory already exists !' error 2207 <1> ; 16/05/2015 2208 <1> ERR_DRV_NOT_RDY equ 15 ; 'drive not ready !' error 2209 <1> ; 18/05/2015 2210 <1> ERR_DEV_NOT_RDY equ 15 ; 'device not ready !' error 2211 <1> ERR_DEV_ACCESS equ 11 ; 'permission denied !' error 2212 <1> ERR_DEV_NOT_OPEN equ 10 ; 'device not open !' error 2213 <1> ; 07/06/2015 2214 <1> ERR_FILE_EOF equ 16 ; 'end of file !' error 2215 <1> ERR_DEV_VOL_SIZE equ 16 ; 'out of volume' error 2216 <1> ; 09/06/2015 2217 <1> ERR_DRV_READ equ 17 ; 'disk read error !' 2218 <1> ERR_DRV_WRITE equ 18 ; 'disk write error !' 2219 <1> ; 16/06/2015 2220 <1> ERR_NOT_DIR equ 19 ; 'not a (valid) directory !' error 2221 <1> ERR_FILE_SIZE equ 20 ; 'file size error !' 2222 <1> ; 22/06/2015 2223 <1> ERR_NOT_SUPERUSER equ 11 ; 'permission denied !' error 2224 <1> ERR_NOT_OWNER equ 11 ; 'permission denied !' error 2225 <1> ERR_NOT_FILE equ 11 ; 'permission denied !' error 2226 <1> ; 23/06/2015 2227 <1> ERR_FILE_EXISTS equ 14 ; 'file already exists !' error 2228 <1> ERR_DRV_NOT_SAME equ 21 ; 'not same drive !' error 2229 <1> ERR_DIR_NOT_FOUND equ 12 ; 'directory not found !' error 2230 <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error 2231 <1> ; 27/06/2015 2232 <1> ERR_INV_PARAMETER equ 23 ; 'invalid parameter !' error 2233 <1> ERR_INV_DEV_NAME equ 24 ; 'invalid device name !' error 2234 <1> ; 29/06/2015 2235 <1> ERR_TIME_OUT equ 25 ; 'time out !' error 2236 <1> ERR_DEV_NOT_RESP equ 25 ; 'device not responding !' error 2237 <1> 2238 <1> ; 26/08/2015 2239 <1> ; 24/07/2015 2240 <1> ; 24/06/2015 2241 <1> MAX_ARG_LEN equ 256 ; max. length of sys exec arguments 2242 <1> ; 01/07/2015 2243 <1> MAX_MSG_LEN equ 255 ; max. msg length for 'sysmsg' 2244 <1> ; 2245 <1> ; 26/11/2021 ('no free blocks on disk !' error) 2246 <1> ERR_ALLOC equ 33 ; 'disk allocation error !' 2247 <1> ; 22/11/2021 2248 <1> ERR_READ_ONLY_FS equ 30 ; 'read only file system !' error 2249 <1> ; 28/11/2021 2250 <1> ERR_INV_FILE equ 255 ; 'invalid file (inode) !' error 2251 <1> ; 04/12/2021 2252 <1> ERR_PERM_DENIED equ 11 ; 'permission denied !' error 2253 <1> ; 11/12/2021 2254 <1> ERR_INV_FUNC equ 1 ; 'invalid system call !' error 2255 <1> ; 10/01/2022 2256 <1> ERR_INO_ALLOC equ 33 ; 'inode allocation error !' 2257 <1> ERR_NOT_REGULAR equ 255 ; 'not regular file directory !' error 2075 %include 'u0.s' ; 15/03/2015 2076 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2077 <1> ; (re-write kernel for test by using previous version without a major defect) 2078 <1> ; **************************************************************************** 2079 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS0.INC 2080 <1> ; Last Modification: 08/01/2022 2081 <1> ; ---------------------------------------------------------------------------- 2082 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2083 <1> ; (v0.1 - Beginning: 11/07/2012) 2084 <1> ; 2085 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2086 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2087 <1> ; 2088 <1> ; 2089 <1> ; 2090 <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s 2091 <1> ; 2092 <1> ; **************************************************************************** 2093 <1> 2094 <1> sys_init: 2095 <1> ; 08/01/2022 2096 <1> ; 01/01/2022 2097 <1> ; 26/12/2021 2098 <1> ; 27/11/2021 2099 <1> ; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification 2100 <1> ; 18/10/2015 2101 <1> ; 28/08/2015 2102 <1> ; 24/08/2015 2103 <1> ; 14/08/2015 2104 <1> ; 24/07/2015 2105 <1> ; 02/07/2015 2106 <1> ; 01/07/2015 2107 <1> ; 23/06/2015 2108 <1> ; 15/04/2015 2109 <1> ; 13/04/2015 2110 <1> ; 11/03/2015 (Retro UNIX 386 v1 - Beginning) 2111 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2112 <1> ; 2113 <1> ;call ldrv_init ; Logical drive description tables initialization 2114 <1> ; 2115 <1> ;; 14/02/2014 2116 <1> ;; 14/07/2013 2117 <1> ;mov ax, 41 2118 <1> ;mov [rootdir], ax 2119 <1> ;mov [u.cdir], ax 2120 <1> ;and al, 1 ; 15/04/2015 2121 <1> 2122 <1> ; 27/11/2021 2123 <1> ; 18/04/2021 - Retro UNIX 386 v2 2124 00003361 31C0 <1> xor eax, eax 2125 <1> ; 12/12/2021 - Temporary 2126 00003363 A2[E06B0000] <1> mov [p.ttyc], al ; 0 ; test !!! 2127 00003368 FEC0 <1> inc al ; eax = 1 (root directory inode) ; runix v2 fs 2128 0000336A A3[8C6E0000] <1> mov [rootdir], eax ; = 1 ; 28/10/2021 (32 bit) 2129 0000336F A3[A86E0000] <1> mov [u.cdir], eax ; 28/10/2021 (32 bit) 2130 <1> 2131 00003374 A2[F56E0000] <1> mov [u.uno], al ; = 1 2132 <1> ;mov [mpid], ax ; 1 2133 <1> ;mov [p.pid], ax ; 1 2134 <1> ; 01/01/2022 2135 00003379 A2[8A6E0000] <1> mov [mpid], al 2136 0000337E A2[806B0000] <1> mov [p.pid], al 2137 00003383 A2[106C0000] <1> mov [p.stat], al ; SRUN, 05/02/2014 2138 <1> ; 2139 00003388 B004 <1> mov al, time_count ; 30/08/2013 2140 0000338A A2[EC6E0000] <1> mov [u.quant], al ; 14/07/2013 2141 <1> ; 02/07/2015 2142 0000338F A1[A86D0000] <1> mov eax, [k_page_dir] 2143 00003394 A3[046F0000] <1> mov [u.pgdir], eax ; reset 2144 <1> ; 18/10/2015 2145 <1> ;sub eax, eax 2146 <1> ;mov [u.ppgdir], eax ; 0 2147 <1> ; 2148 00003399 E82B030000 <1> call epoch 2149 0000339E A3[486F0000] <1> mov [s.time], eax ; 13/03/2015 2150 <1> ; 17/07/2013 2151 000033A3 E883060000 <1> call bf_init ; buffer initialization 2152 <1> ; 23/06/2015 2153 000033A8 E8BBFAFFFF <1> call allocate_page 2154 <1> ;;jc error 2155 <1> ;jc panic ; jc short panic (01/07/2015) 2156 <1> ; 05/12/2021 2157 000033AD 7305 <1> jnc short sysinit_1 2158 000033AF E990000000 <1> jmp panic 2159 <1> sysinit_1: 2160 000033B4 A3[006F0000] <1> mov [u.upage], eax ; user structure page 2161 000033B9 A3[206C0000] <1> mov [p.upage], eax 2162 <1> ; 2163 000033BE E816FBFFFF <1> call clear_page 2164 <1> ; 2165 <1> ; 14/08/2015 2166 000033C3 FA <1> cli 2167 <1> ; 14/03/2015 2168 <1> ; 17/01/2014 2169 000033C4 E8CD010000 <1> call sp_init ; serial port initialization 2170 <1> ; 14/08/2015 2171 000033C9 FB <1> sti 2172 <1> ; 2173 <1> ; 30/06/2015 2174 <1> ;mov esi, kernel_init_ok_msg 2175 <1> ;call print_msg 2176 <1> ; 2177 000033CA 30DB <1> xor bl, bl ; video page 0 2178 <1> vp_clr_nxt: ; clear video pages (reset cursor positions) 2179 000033CC E8FF2F0000 <1> call vp_clr ; 17/07/2013 2180 000033D1 FEC3 <1> inc bl 2181 000033D3 80FB08 <1> cmp bl, 8 2182 000033D6 72F4 <1> jb short vp_clr_nxt 2183 <1> ; 2184 <1> ; 24/07/2015 2185 <1> ;push KDATA 2186 <1> ;push esp 2187 <1> ;mov [tss.esp0], esp 2188 <1> ;mov word [tss.ss0], KDATA 2189 <1> ; 2190 <1> ; 08/01/2022 2191 <1> ; 24/08/2015 2192 <1> ;; temporary (01/07/2015) 2193 <1> ;mov byte [u.quant], time_count ; 4 2194 <1> ; ; it is not needed here ! 2195 <1> ;;inc byte [u.kcall] ; 'the caller is kernel' sign 2196 000033D8 FE0D[9A6E0000] <1> dec byte [sysflg] ; FFh = ready for system call 2197 <1> ; 0 = executing a system call 2198 <1> ;;sys _msg, kernel_init_ok_msg, 255, 0 2199 <1> ; 2200 <1> ;;; 06/08/2015 2201 <1> ;;;call getch ; wait for a key stroke 2202 <1> ;;mov ecx, 0FFFFFFFh 2203 <1> ;;sys_init_msg_wait: 2204 <1> ;; push ecx 2205 <1> ;; mov al, 1 2206 <1> ;; mov ah, [ptty] ; active (current) video page 2207 <1> ;; call getc_n 2208 <1> ;; pop ecx 2209 <1> ;; jnz short sys_init_msg_ok 2210 <1> ;; loop sys_init_msg_wait 2211 <1> ; 2212 <1> ;;sys_init_msg_ok: 2213 <1> ; 28/08/2015 (initial settings for the 1st 'rswap') 2214 000033DE 6A10 <1> push KDATA ; ss 2215 000033E0 54 <1> push esp 2216 000033E1 9C <1> pushfd 2217 000033E2 6A08 <1> push KCODE ; cs 2218 000033E4 68[11340000] <1> push init_exec ; eip 2219 000033E9 8925[9C6E0000] <1> mov [u.sp], esp 2220 000033EF 1E <1> push ds 2221 000033F0 06 <1> push es 2222 000033F1 0FA0 <1> push fs 2223 000033F3 0FA8 <1> push gs 2224 000033F5 60 <1> pushad 2225 000033F6 8925[A06E0000] <1> mov [u.usp], esp 2226 000033FC E873190000 <1> call wswap ; save current user (u) structure, user registers 2227 <1> ; and interrupt return components (for IRET) 2228 00003401 61 <1> popad 2229 00003402 6658 <1> pop ax ; gs 2230 00003404 6658 <1> pop ax ; fs 2231 00003406 6658 <1> pop ax ; es 2232 00003408 6658 <1> pop ax ; ds 2233 0000340A 58 <1> pop eax ; eip (init_exec) 2234 0000340B 6658 <1> pop ax ; cs (KCODE) 2235 0000340D 58 <1> pop eax ; E-FLAGS 2236 0000340E 58 <1> pop eax ; esp 2237 0000340F 6658 <1> pop ax ; ss (KDATA) 2238 <1> ; 2239 <1> ; 26/12/2021 ([u.ppgdir] is zero already) 2240 <1> ;xor eax, eax ; 0 2241 <1> ;mov [u.ppgdir], eax ; reset (to zero) for '/etc/init' 2242 <1> ; 2243 <1> ; 02/07/2015 2244 <1> ; [u.pgdir ] = [k_page_dir] 2245 <1> ; [u.ppgdir] = 0 (page dir of the parent process) 2246 <1> ; (The caller is os kernel sign for 'sysexec') 2247 <1> init_exec: 2248 <1> 2249 <1> ; temporary - 27/12/2021 2250 <1> ; clear faulty areas 2251 <1> ;mov ecx, (NFILES*16)/4 2252 <1> ;mov edi, fsp 2253 00003411 31C0 <1> xor eax, eax 2254 <1> ;rep stosd 2255 <1> ;mov edi, u.fp 2256 <1> ;mov cl, 10 2257 <1> ;rep stosb 2258 00003413 A3[406B0000] <1> mov [fsp], eax 2259 <1> 2260 <1> ; 13/03/2013 2261 <1> ; 24/07/2013 2262 00003418 BB[3A340000] <1> mov ebx, init_file 2263 0000341D B9[32340000] <1> mov ecx, init_argp 2264 <1> ; EBX contains 'etc/init' asciiz file name address 2265 <1> ; ECX contains address of argument list pointer 2266 <1> ; 2267 <1> ;dec byte [sysflg] ; FFh = ready for system call 2268 <1> ; 0 = executing a system call 2269 <1> sys _exec ; execute file 2184 <2> 2185 <2> 2186 00003422 B80B000000 <2> mov eax, %1 2187 <2> %if %0 >= 2 2188 <2> mov ebx, %2 2189 <2> %if %0 >= 3 2190 <2> mov ecx, %3 2191 <2> %if %0 = 4 2192 <2> mov edx, %4 2193 <2> %endif 2194 <2> %endif 2195 <2> %endif 2196 00003427 CD30 <2> int 30h 2270 00003429 7319 <1> jnc short panic 2271 <1> ; 2272 0000342B BE[BC6A0000] <1> mov esi, etc_init_err_msg 2273 <1> ; 22/11/2021 2274 <1> ;call print_msg 2275 00003430 EB17 <1> jmp short key_to_reboot 2276 <1> 2277 <1> ;align 4 2278 <1> init_argp: 2279 00003432 [3A340000]00000000 <1> dd init_file, 0 ; 23/06/2015 (dw -> dd) 2280 <1> init_file: 2281 <1> ; 24/08/2015 2282 0000343A 2F6574632F696E6974- <1> db '/etc/init', 0 2282 00003443 00 <1> 2283 <1> panic: 2284 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2285 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 2286 00003444 BE[A16A0000] <1> mov esi, panic_msg 2287 <1> key_to_reboot: ; 22/11/2021 2288 00003449 E819000000 <1> call print_msg 2289 <1> ;key_to_reboot: 2290 <1> ; 15/11/2015 2291 0000344E E8C92D0000 <1> call getch 2292 <1> ; wait for a character from the current tty 2293 <1> ; 2294 00003453 B00A <1> mov al, 0Ah 2295 00003455 8A1D[D66D0000] <1> mov bl, [ptty] ; [active_page] 2296 0000345B B407 <1> mov ah, 07h ; Black background, 2297 <1> ; light gray forecolor 2298 0000345D E85ADFFFFF <1> call write_tty 2299 00003462 E9F5DBFFFF <1> jmp cpu_reset 2300 <1> 2301 <1> print_msg: 2302 <1> ; 01/07/2015 2303 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2304 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 2305 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 2306 <1> ; 2307 <1> ; 2308 00003467 AC <1> lodsb 2309 <1> pmsg1: 2310 00003468 56 <1> push esi 2311 00003469 0FB61D[D66D0000] <1> movzx ebx, byte [ptty] 2312 00003470 B407 <1> mov ah, 07h ; Black background, light gray forecolor 2313 00003472 E845DFFFFF <1> call write_tty 2314 00003477 5E <1> pop esi 2315 00003478 AC <1> lodsb 2316 00003479 20C0 <1> and al, al 2317 0000347B 75EB <1> jnz short pmsg1 2318 0000347D C3 <1> retn 2319 <1> 2320 <1> ctrlbrk: 2321 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 2322 <1> ; 12/11/2015 2323 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2324 <1> ; 06/12/2013 (Retro UNIX 8086 v1) 2325 <1> ; 2326 <1> ; INT 1Bh (control+break) handler 2327 <1> ; 2328 <1> ; Retro Unix 8086 v1 feature only! 2329 <1> ; 2330 0000347E 66833D[F06E0000]00 <1> cmp word [u.intr], 0 2331 00003486 7641 <1> jna short cbrk4 2332 <1> cbrk0: 2333 <1> ; 12/11/2015 2334 <1> ; 06/12/2013 2335 00003488 66833D[F26E0000]00 <1> cmp word [u.quit], 0 2336 00003490 7437 <1> jz short cbrk4 2337 <1> ; 2338 <1> ; 20/09/2013 2339 <1> ;push ax 2340 <1> ; 04/12/2021 2341 00003492 50 <1> push eax 2342 00003493 A0[D66D0000] <1> mov al, [ptty] 2343 <1> ; 2344 <1> ; 12/11/2015 2345 <1> ; 2346 <1> ; ctrl+break (EOT, CTRL+D) from serial port 2347 <1> ; or ctrl+break from console (pseudo) tty 2348 <1> ; (!redirection!) 2349 <1> ; 2350 00003498 3C08 <1> cmp al, 8 ; serial port tty nums > 7 2351 0000349A 7211 <1> jb short cbrk1 ; console (pseudo) tty 2352 <1> ; 2353 <1> ; Serial port interrupt handler sets [ptty] 2354 <1> ; to the port's tty number (as temporary). 2355 <1> ; 2356 <1> ; If active process is using a stdin or 2357 <1> ; stdout redirection (by the shell), 2358 <1> ; console tty keyboard must be available 2359 <1> ; to terminate running process, 2360 <1> ; in order to prevent a deadlock. 2361 <1> ; 2362 0000349C 52 <1> push edx 2363 0000349D 0FB615[F56E0000] <1> movzx edx, byte [u.uno] 2364 000034A4 3A82[DF6B0000] <1> cmp al, [edx+p.ttyc-1] ; console tty (rw) 2365 000034AA 5A <1> pop edx 2366 000034AB 7412 <1> je short cbrk2 2367 <1> cbrk1: 2368 000034AD FEC0 <1> inc al ; [u.ttyp] : 1 based tty number 2369 <1> ; 06/12/2013 2370 000034AF 3A05[DA6E0000] <1> cmp al, [u.ttyp] ; recent open tty (r) 2371 000034B5 7408 <1> je short cbrk2 2372 000034B7 3A05[DB6E0000] <1> cmp al, [u.ttyp+1] ; recent open tty (w) 2373 000034BD 7509 <1> jne short cbrk3 2374 <1> cbrk2: 2375 <1> ;; 06/12/2013 2376 <1> ;mov ax, [u.quit] 2377 <1> ;and ax, ax 2378 <1> ;jz short cbrk3 2379 <1> ; 2380 <1> ;xor ax, ax ; 0 2381 <1> ;dec ax 2382 <1> ; 04/12/2021 2383 000034BF 31C0 <1> xor eax, eax ; 0 2384 000034C1 48 <1> dec eax ; 0FFFFFFFFh 2385 <1> ; 0FFFFh = 'ctrl+brk' keystroke 2386 000034C2 66A3[F26E0000] <1> mov [u.quit], ax 2387 <1> cbrk3: 2388 <1> ;pop ax 2389 <1> ; 04/12/2021 2390 000034C8 58 <1> pop eax 2391 <1> cbrk4: 2392 000034C9 C3 <1> retn 2393 <1> 2394 <1> com2_int: 2395 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 2396 <1> ; 07/11/2015 2397 <1> ; 24/10/2015 2398 <1> ; 23/10/2015 2399 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 2400 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2401 <1> ; < serial port 2 interrupt handler > 2402 <1> ; 2403 000034CA 890424 <1> mov [esp], eax ; overwrite call return address 2404 <1> ;;push eax 2405 <1> ; 08/01/2022 2406 000034CD 29C0 <1> sub eax, eax 2407 000034CF B009 <1> mov al, 9 2408 <1> ;mov ax, 9 2409 000034D1 EB07 <1> jmp short comm_int 2410 <1> com1_int: 2411 <1> ; 07/11/2015 2412 <1> ; 24/10/2015 2413 000034D3 890424 <1> mov [esp], eax ; overwrite call return address 2414 <1> ; 23/10/2015 2415 <1> ;push eax 2416 <1> ; 08/01/2022 2417 000034D6 29C0 <1> sub eax, eax 2418 000034D8 B008 <1> mov al, 8 2419 <1> ;mov ax, 8 2420 <1> comm_int: 2421 <1> ; 08/01/2022 2422 <1> ; 20/11/2015 2423 <1> ; 18/11/2015 2424 <1> ; 17/11/2015 2425 <1> ; 16/11/2015 2426 <1> ; 09/11/2015 2427 <1> ; 08/11/2015 2428 <1> ; 07/11/2015 2429 <1> ; 06/11/2015 (serial4.asm, 'serial') 2430 <1> ; 01/11/2015 2431 <1> ; 26/10/2015 2432 <1> ; 23/10/2015 2433 000034DA 53 <1> push ebx 2434 000034DB 56 <1> push esi 2435 000034DC 57 <1> push edi 2436 000034DD 1E <1> push ds 2437 000034DE 06 <1> push es 2438 <1> ; 18/11/2015 2439 000034DF 0F20DB <1> mov ebx, cr3 2440 000034E2 53 <1> push ebx ; **** 2441 <1> ; 2442 000034E3 51 <1> push ecx ; *** 2443 000034E4 52 <1> push edx ; ** 2444 <1> ; 2445 000034E5 BB10000000 <1> mov ebx, KDATA 2446 000034EA 8EDB <1> mov ds, bx 2447 000034EC 8EC3 <1> mov es, bx 2448 <1> ; 2449 000034EE 8B0D[A86D0000] <1> mov ecx, [k_page_dir] 2450 000034F4 0F22D9 <1> mov cr3, ecx 2451 <1> ; 20/11/2015 2452 <1> ; Interrupt identification register 2453 000034F7 66BAFA02 <1> mov dx, 2FAh ; COM2 2454 <1> ; 2455 000034FB 3C08 <1> cmp al, 8 2456 000034FD 7702 <1> ja short com_i0 2457 <1> ; 2458 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 2459 <1> ; 20/11/2015 2460 <1> ; 17/11/2015 2461 <1> ; 16/11/2015 2462 <1> ; 15/11/2015 2463 <1> ; 24/10/2015 2464 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 2465 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2466 <1> ; < serial port 1 interrupt handler > 2467 <1> ; 2468 000034FF FEC6 <1> inc dh ; 3FAh ; COM1 Interrupt id. register 2469 <1> com_i0: 2470 <1> ;push eax ; * 2471 <1> ; 07/11/2015 2472 00003501 A2[166E0000] <1> mov byte [ccomport], al 2473 <1> ; 09/11/2015 2474 <1> ;movzx ebx, ax ; 8 or 9 2475 <1> ; 08/01/2022 2476 00003506 89C3 <1> mov ebx, eax ; 8 or 9 2477 <1> ; 17/11/2015 2478 <1> ; reset request for response status 2479 00003508 88A3[0C6E0000] <1> mov [ebx+req_resp-8], ah ; 0 2480 <1> ; 2481 <1> ; 20/11/2015 2482 0000350E EC <1> in al, dx ; read interrupt id. register 2483 0000350F EB00 <1> JMP $+2 ; I/O DELAY 2484 00003511 2404 <1> and al, 4 ; received data available? 2485 00003513 7470 <1> jz short com_eoi ; (transmit. holding reg. empty) 2486 <1> ; 2487 <1> ; 20/11/2015 2488 00003515 80EA02 <1> sub dl, 3FAh-3F8h ; data register (3F8h, 2F8h) 2489 00003518 EC <1> in al, dx ; read character 2490 <1> ;JMP $+2 ; I/O DELAY 2491 <1> ; 08/11/2015 2492 <1> ; 07/11/2015 2493 00003519 89DE <1> mov esi, ebx 2494 0000351B 89DF <1> mov edi, ebx 2495 0000351D 81C6[106E0000] <1> add esi, rchar - 8 ; points to last received char 2496 00003523 81C7[126E0000] <1> add edi, schar - 8 ; points to last sent char 2497 00003529 8806 <1> mov [esi], al ; received char (current char) 2498 <1> ; query 2499 0000352B 20C0 <1> and al, al 2500 0000352D 7527 <1> jnz short com_i2 2501 <1> ; response 2502 <1> ; 17/11/2015 2503 <1> ; set request for response status 2504 0000352F FE83[0C6E0000] <1> inc byte [ebx+req_resp-8] ; 1 2505 <1> ; 2506 00003535 6683C205 <1> add dx, 3FDh-3F8h ; (3FDh, 2FDh) 2507 00003539 EC <1> in al, dx ; read line status register 2508 0000353A EB00 <1> JMP $+2 ; I/O DELAY 2509 0000353C 2420 <1> and al, 20h ; transmitter holding reg. empty? 2510 0000353E 7445 <1> jz short com_eoi ; no 2511 00003540 B0FF <1> mov al, 0FFh ; response 2512 00003542 6683EA05 <1> sub dx, 3FDh-3F8h ; data port (3F8h, 2F8h) 2513 00003546 EE <1> out dx, al ; send on serial port 2514 <1> ; 17/11/2015 2515 00003547 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 2516 0000354A 7502 <1> jne short com_i1 ; no 2517 0000354C 8807 <1> mov [edi], al ; 0FFh (responded) 2518 <1> com_i1: 2519 <1> ; 17/11/2015 2520 <1> ; reset request for response status (again) 2521 0000354E FE8B[0C6E0000] <1> dec byte [ebx+req_resp-8] ; 0 2522 00003554 EB2F <1> jmp short com_eoi 2523 <1> com_i2: 2524 <1> ; 08/11/2015 2525 00003556 3CFF <1> cmp al, 0FFh ; (response ?) 2526 00003558 7417 <1> je short com_i3 ; (check for response signal) 2527 <1> ; 07/11/2015 2528 0000355A 3C04 <1> cmp al, 04h ; EOT 2529 0000355C 751C <1> jne short com_i4 2530 <1> ; EOT = 04h (End of Transmit) - 'CTRL + D' 2531 <1> ;(an EOT char is supposed as a ctrl+brk from the terminal) 2532 <1> ; 08/11/2015 2533 <1> ; ptty -> tty 0 to 7 (pseudo screens) 2534 0000355E 861D[D66D0000] <1> xchg bl, [ptty] ; tty number (8 or 9) 2535 00003564 E815FFFFFF <1> call ctrlbrk 2536 00003569 861D[D66D0000] <1> xchg [ptty], bl ; (restore ptty value and BL value) 2537 <1> ;mov al, 04h ; EOT 2538 <1> ; 08/11/2015 2539 0000356F EB09 <1> jmp short com_i4 2540 <1> com_i3: 2541 <1> ; 08/11/2015 2542 <1> ; If 0FFh has been received just after a query 2543 <1> ; (schar, ZERO), it is a response signal. 2544 <1> ; 17/11/2015 2545 00003571 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 2546 00003574 7704 <1> ja short com_i4 ; no 2547 <1> ; reset query status (schar) 2548 00003576 8807 <1> mov [edi], al ; 0FFh 2549 00003578 FEC0 <1> inc al ; 0 2550 <1> com_i4: 2551 <1> ; 27/07/2014 2552 <1> ; 09/07/2014 2553 0000357A D0E3 <1> shl bl, 1 2554 0000357C 81C3[D86D0000] <1> add ebx, ttychr 2555 <1> ; 23/07/2014 (always overwrite) 2556 <1> ;;cmp word [ebx], 0 2557 <1> ;;ja short com_eoi 2558 <1> ; 2559 00003582 668903 <1> mov [ebx], ax ; Save ascii code 2560 <1> ; scan code = 0 2561 <1> com_eoi: 2562 <1> ;mov al, 20h 2563 <1> ;out 20h, al ; end of interrupt 2564 <1> ; 2565 <1> ; 07/11/2015 2566 <1> ;pop eax ; * 2567 00003585 A0[166E0000] <1> mov al, byte [ccomport] ; current COM port 2568 <1> ; al = tty number (8 or 9) 2569 0000358A E8BF180000 <1> call wakeup 2570 <1> com_iret: 2571 <1> ; 23/10/2015 2572 0000358F 5A <1> pop edx ; ** 2573 00003590 59 <1> pop ecx ; *** 2574 <1> ; 18/11/2015 2575 <1> ;pop eax ; **** 2576 <1> ;mov cr3, eax 2577 <1> ;jmp iiret 2578 00003591 E909D4FFFF <1> jmp iiretp 2579 <1> 2580 <1> ;iiretp: ; 01/09/2015 2581 <1> ; ; 28/08/2015 2582 <1> ; pop eax ; (*) page directory 2583 <1> ; mov cr3, eax 2584 <1> ;iiret: 2585 <1> ; ; 22/08/2014 2586 <1> ; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 2587 <1> ; out 20h, al ; 8259 PORT 2588 <1> ; ; 2589 <1> ; pop es 2590 <1> ; pop ds 2591 <1> ; pop edi 2592 <1> ; pop esi 2593 <1> ; pop ebx ; 29/08/2014 2594 <1> ; pop eax 2595 <1> ; iretd 2596 <1> 2597 <1> sp_init: 2598 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 2599 <1> ; 07/11/2015 2600 <1> ; 29/10/2015 2601 <1> ; 26/10/2015 2602 <1> ; 23/10/2015 2603 <1> ; 29/06/2015 2604 <1> ; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud) 2605 <1> ; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud) 2606 <1> ; Initialization of Serial Port Communication Parameters 2607 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 2608 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 2609 <1> ; 2610 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 2611 <1> ; 2612 <1> ; INPUT: (29/06/2015) 2613 <1> ; AL = 0 for COM1 2614 <1> ; 1 for COM2 2615 <1> ; AH = Communication parameters 2616 <1> ; 2617 <1> ; (*) Communication parameters (except BAUD RATE): 2618 <1> ; Bit 4 3 2 1 0 2619 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 2620 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 2621 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 2622 <1> ; 11 = even 2623 <1> ; Baud rate setting bits: (29/06/2015) 2624 <1> ; Retro UNIX 386 v1 feature only ! 2625 <1> ; Bit 7 6 5 | Baud rate 2626 <1> ; ------------------------ 2627 <1> ; value 0 0 0 | Default (Divisor = 1) 2628 <1> ; 0 0 1 | 9600 (12) 2629 <1> ; 0 1 0 | 19200 (6) 2630 <1> ; 0 1 1 | 38400 (3) 2631 <1> ; 1 0 0 | 14400 (8) 2632 <1> ; 1 0 1 | 28800 (4) 2633 <1> ; 1 1 0 | 57600 (2) 2634 <1> ; 1 1 1 | 115200 (1) 2635 <1> 2636 <1> ; References: 2637 <1> ; (1) IBM PC-XT Model 286 BIOS Source Code 2638 <1> ; RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232) 2639 <1> ; (2) Award BIOS 1999 - ATORGS.ASM 2640 <1> ; (3) http://wiki.osdev.org/Serial_Ports 2641 <1> ; 2642 <1> ; Set communication parameters for COM1 (= 03h) 2643 <1> ; 2644 00003596 BB[126E0000] <1> mov ebx, com1p ; COM1 parameters 2645 0000359B 66BAF803 <1> mov dx, 3F8h ; COM1 2646 <1> ; 29/10/2015 2647 0000359F 66B90103 <1> mov cx, 301h ; divisor = 1 (115200 baud) 2648 000035A3 E84F000000 <1> call sp_i3 ; call A4 2649 000035A8 A880 <1> test al, 80h 2650 000035AA 740E <1> jz short sp_i0 ; OK.. 2651 <1> ; Error ! 2652 <1> ;mov dx, 3F8h 2653 000035AC 80EA05 <1> sub dl, 5 ; 3FDh -> 3F8h 2654 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 2655 <1> ; 08/01/2022 2656 000035AF B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 2657 000035B1 E841000000 <1> call sp_i3 ; call A4 2658 000035B6 A880 <1> test al, 80h 2659 000035B8 7508 <1> jnz short sp_i1 2660 <1> sp_i0: 2661 <1> ; (Note: Serial port interrupts will be disabled here...) 2662 <1> ; (INT 14h initialization code disables interrupts.) 2663 <1> ; 2664 000035BA C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 2665 000035BD E8BF000000 <1> call sp_i5 ; 29/06/2015 2666 <1> sp_i1: 2667 000035C2 43 <1> inc ebx 2668 000035C3 66BAF802 <1> mov dx, 2F8h ; COM2 2669 <1> ; 29/10/2015 2670 <1> ;mov cx, 301h ; divisor = 1 (115200 baud) 2671 <1> ; 08/01/2022 2672 000035C7 B101 <1> mov cl, 01h ; cx = 301h, divisor = 1 (115200 baud) 2673 000035C9 E829000000 <1> call sp_i3 ; call A4 2674 000035CE A880 <1> test al, 80h 2675 000035D0 740E <1> jz short sp_i2 ; OK.. 2676 <1> ; Error ! 2677 <1> ;mov dx, 2F8h 2678 000035D2 80EA05 <1> sub dl, 5 ; 2FDh -> 2F8h 2679 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 2680 <1> ; 08/01/2022 2681 000035D5 B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 2682 000035D7 E81B000000 <1> call sp_i3 ; call A4 2683 000035DC A880 <1> test al, 80h 2684 000035DE 7516 <1> jnz short sp_i7 2685 <1> sp_i2: 2686 000035E0 C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 2687 <1> sp_i6: 2688 <1> ;; COM2 - enabling IRQ 3 2689 <1> ; 08/01/2022 2690 000035E3 B4F7 <1> mov ah, 0F7h ; enable IRQ 3 (COM2) 2691 <1> ; 07/11/2015 2692 <1> ; 26/10/2015 2693 <1> ;pushf 2694 <1> ;cli 2695 <1> ;; 2696 <1> ;;mov dx, 2FCh ; modem control register 2697 <1> ;mov dl, 0FCh ; 08/01/2022 2698 <1> ;in al, dx ; read register 2699 <1> ;JMP $+2 ; I/O DELAY 2700 <1> ;or al, 8 ; enable bit 3 (OUT2) 2701 <1> ;out dx, al ; write back to register 2702 <1> ;JMP $+2 ; I/O DELAY 2703 <1> ;;mov dx, 2F9h ; interrupt enable register 2704 <1> ;mov dl, 0F9h ; 08/01/2022 2705 <1> ;in al, dx ; read register 2706 <1> ;JMP $+2 ; I/O DELAY 2707 <1> ;;or al, 1 ; receiver data interrupt enable and 2708 <1> ;or al, 3 ; transmitter empty interrupt enable 2709 <1> ;out dx, al ; write back to register 2710 <1> ;JMP $+2 ; I/O DELAY 2711 <1> ;in al, 21h ; read interrupt mask register 2712 <1> ;JMP $+2 ; I/O DELAY 2713 <1> ;and al, 0F7h ; enable IRQ 3 (COM2) 2714 <1> ;out 21h, al ; write back to register 2715 <1> ; 2716 <1> ; 08/01/2022 2717 000035E5 9C <1> pushf 2718 000035E6 E8AA000000 <1> call sp_i8 2719 <1> ; 23/10/2015 2720 000035EB B8[CA340000] <1> mov eax, com2_int 2721 000035F0 A3[A33A0000] <1> mov [com2_irq3], eax 2722 <1> ; 26/10/2015 2723 000035F5 9D <1> popf 2724 <1> sp_i7: 2725 000035F6 C3 <1> retn 2726 <1> 2727 <1> sp_i3: 2728 <1> ;A4: ;----- INITIALIZE THE COMMUNICATIONS PORT 2729 <1> ; 28/10/2015 2730 000035F7 FEC2 <1> inc dl ; 3F9h (2F9h) ; 3F9h, COM1 Interrupt enable register 2731 000035F9 B000 <1> mov al, 0 2732 000035FB EE <1> out dx, al ; disable serial port interrupt 2733 000035FC EB00 <1> JMP $+2 ; I/O DELAY 2734 000035FE 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; COM1 Line control register (3FBh) 2735 00003601 B080 <1> mov al, 80h 2736 00003603 EE <1> out dx, al ; SET DLAB=1 ; divisor latch access bit 2737 <1> ;----- SET BAUD RATE DIVISOR 2738 <1> ; 26/10/2015 2739 00003604 80EA03 <1> sub dl, 3 ; 3F8h (2F8h) ; register for least significant byte 2740 <1> ; of the divisor value 2741 00003607 88C8 <1> mov al, cl ; 1 2742 00003609 EE <1> out dx, al ; 1 = 115200 baud (Retro UNIX 386 v1) 2743 <1> ; 2 = 57600 baud 2744 <1> ; 3 = 38400 baud 2745 <1> ; 6 = 19200 baud 2746 <1> ; 12 = 9600 baud (Retro UNIX 8086 v1) 2747 0000360A EB00 <1> JMP $+2 ; I/O DELAY 2748 0000360C 28C0 <1> sub al, al 2749 0000360E FEC2 <1> inc dl ; 3F9h (2F9h) ; register for most significant byte 2750 <1> ; of the divisor value 2751 00003610 EE <1> out dx, al ; 0 2752 00003611 EB00 <1> JMP $+2 ; I/O DELAY 2753 <1> ; 2754 00003613 88E8 <1> mov al, ch ; 3 ; 8 data bits, 1 stop bit, no parity 2755 <1> ;and al, 1Fh ; Bits 0,1,2,3,4 2756 00003615 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; Line control register 2757 00003618 EE <1> out dx, al 2758 00003619 EB00 <1> JMP $+2 ; I/O DELAY 2759 <1> ; 29/10/2015 2760 0000361B FECA <1> dec dl ; 3FAh (2FAh) ; FIFO Control register (16550/16750) 2761 0000361D 30C0 <1> xor al, al ; 0 2762 0000361F EE <1> out dx, al ; Disable FIFOs (reset to 8250 mode) 2763 00003620 EB00 <1> JMP $+2 2764 <1> sp_i4: 2765 <1> ;A18: ;----- COMM PORT STATUS ROUTINE 2766 <1> ; 29/06/2015 (line status after modem status) 2767 00003622 80C204 <1> add dl, 4 ; 3FEh (2FEh) ; Modem status register 2768 <1> sp_i4s: 2769 00003625 EC <1> in al, dx ; GET MODEM CONTROL STATUS 2770 00003626 EB00 <1> JMP $+2 ; I/O DELAY 2771 00003628 88C4 <1> mov ah, al ; PUT IN (AH) FOR RETURN 2772 0000362A FECA <1> dec dl ; 3FDh (2FDh) ; POINT TO LINE STATUS REGISTER 2773 <1> ; dx = 3FDh for COM1, 2FDh for COM2 2774 0000362C EC <1> in al, dx ; GET LINE CONTROL STATUS 2775 <1> ; AL = Line status, AH = Modem status 2776 0000362D C3 <1> retn 2777 <1> 2778 <1> sp_status: 2779 <1> ; 29/06/2015 2780 <1> ; 27/06/2015 (Retro UNIX 386 v1) 2781 <1> ; Get serial port status 2782 0000362E 66BAFE03 <1> mov dx, 3FEh ; Modem status register (COM1) 2783 00003632 28C6 <1> sub dh, al ; dh = 2 for COM2 (al = 1) 2784 <1> ; dx = 2FEh for COM2 2785 00003634 EBEF <1> jmp short sp_i4s 2786 <1> 2787 <1> sp_setp: ; Set serial port communication parameters 2788 <1> ; 08/01/2022 2789 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 2790 <1> ; 07/11/2015 2791 <1> ; 29/10/2015 2792 <1> ; 29/06/2015 2793 <1> ; Retro UNIX 386 v1 feature only ! 2794 <1> ; 2795 <1> ; INPUT: 2796 <1> ; AL = 0 for COM1 2797 <1> ; 1 for COM2 2798 <1> ; AH = Communication parameters (*) 2799 <1> ; OUTPUT: 2800 <1> ; CL = Line status 2801 <1> ; CH = Modem status 2802 <1> ; If cf = 1 -> Error code in [u.error] 2803 <1> ; 'invalid parameter !' 2804 <1> ; or 2805 <1> ; 'device not ready !' error 2806 <1> ; 2807 <1> ; (*) Communication parameters (except BAUD RATE): 2808 <1> ; Bit 4 3 2 1 0 2809 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 2810 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 2811 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 2812 <1> ; 11 = even 2813 <1> ; Baud rate setting bits: (29/06/2015) 2814 <1> ; Retro UNIX 386 v1 feature only ! 2815 <1> ; Bit 7 6 5 | Baud rate 2816 <1> ; ------------------------ 2817 <1> ; value 0 0 0 | Default (Divisor = 1) 2818 <1> ; 0 0 1 | 9600 (12) 2819 <1> ; 0 1 0 | 19200 (6) 2820 <1> ; 0 1 1 | 38400 (3) 2821 <1> ; 1 0 0 | 14400 (8) 2822 <1> ; 1 0 1 | 28800 (4) 2823 <1> ; 1 1 0 | 57600 (2) 2824 <1> ; 1 1 1 | 115200 (1) 2825 <1> ; 2826 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 2827 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 2828 <1> ; 2829 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 2830 <1> ; 2831 00003636 66BAF803 <1> mov dx, 3F8h 2832 0000363A BB[126E0000] <1> mov ebx, com1p ; COM1 control byte offset 2833 0000363F 3C01 <1> cmp al, 1 2834 00003641 7770 <1> ja short sp_invp_err 2835 00003643 7203 <1> jb short sp_setp1 ; COM1 (AL = 0) 2836 00003645 FECE <1> dec dh ; 2F8h 2837 00003647 43 <1> inc ebx ; COM2 control byte offset 2838 <1> sp_setp1: 2839 <1> ; 29/10/2015 2840 00003648 8823 <1> mov [ebx], ah 2841 0000364A 0FB6CC <1> movzx ecx, ah 2842 0000364D C0E905 <1> shr cl, 5 ; -> baud rate index 2843 00003650 80E41F <1> and ah, 1Fh ; communication parameters except baud rate 2844 00003653 8A81[C2360000] <1> mov al, [ecx+b_div_tbl] 2845 00003659 6689C1 <1> mov cx, ax 2846 0000365C E896FFFFFF <1> call sp_i3 2847 00003661 6689C1 <1> mov cx, ax ; CL = Line status, CH = Modem status 2848 00003664 A880 <1> test al, 80h 2849 00003666 740F <1> jz short sp_setp2 2850 00003668 C603E3 <1> mov byte [ebx], 0E3h ; Reset to initial value (11100011b) 2851 <1> stp_dnr_err: 2852 0000366B C705[186F0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !' 2852 00003673 0000 <1> 2853 <1> ; CL = Line status, CH = Modem status 2854 00003675 F9 <1> stc 2855 00003676 C3 <1> retn 2856 <1> sp_setp2: 2857 00003677 80FE02 <1> cmp dh, 2 ; COM2 (2F?h) 2858 <1> ;jna sp_i6 2859 <1> ; COM1 (3F?h) 2860 <1> ; 24/12/2021 2861 0000367A 7705 <1> ja short sp_i5 2862 0000367C E962FFFFFF <1> jmp sp_i6 2863 <1> sp_i5: 2864 <1> ; 08/01/2022 2865 00003681 B4EF <1> mov ah, 0EFh ; enable IRQ 4 (COM1) 2866 <1> ; 07/11/2015 2867 <1> ; 26/10/2015 2868 <1> ; 29/06/2015 2869 <1> ; 2870 <1> ;; COM1 - enabling IRQ 4 2871 <1> ;pushf 2872 <1> ;cli 2873 <1> ;;mov dx, 3FCh ; modem control register 2874 <1> ;mov dl, 0FCh ; 08/01/2022 2875 <1> ;in al, dx ; read register 2876 <1> ;JMP $+2 ; I/O DELAY 2877 <1> ;or al, 8 ; enable bit 3 (OUT2) 2878 <1> ;out dx, al ; write back to register 2879 <1> ;JMP $+2 ; I/O DELAY 2880 <1> ;;mov dx, 3F9h ; interrupt enable register 2881 <1> ;mov dl, 0F9h ; 08/01/2022 2882 <1> ;in al, dx ; read register 2883 <1> ;JMP $+2 ; I/O DELAY 2884 <1> ;;or al, 1 ; receiver data interrupt enable and 2885 <1> ;or al, 3 ; transmitter empty interrupt enable 2886 <1> ;out dx, al ; write back to register 2887 <1> ;JMP $+2 ; I/O DELAY 2888 <1> ;in al, 21h ; read interrupt mask register 2889 <1> ;JMP $+2 ; I/O DELAY 2890 <1> ;and al, 0EFh ; enable IRQ 4 (COM1) 2891 <1> ;out 21h, al ; write back to register 2892 <1> ; 2893 <1> ; 08/01/2022 2894 00003683 9C <1> pushf 2895 00003684 E80C000000 <1> call sp_i8 2896 <1> ; 23/10/2015 2897 00003689 B8[D3340000] <1> mov eax, com1_int 2898 0000368E A3[9F3A0000] <1> mov [com1_irq4], eax 2899 <1> ; 26/10/2015 2900 00003693 9D <1> popf 2901 00003694 C3 <1> retn 2902 <1> 2903 <1> sp_i8: 2904 <1> ; 08/01/2022 2905 <1> ;pushf 2906 00003695 FA <1> cli 2907 <1> ; 2908 <1> ;mov dx, 2FCh ; 3FCh ; modem control register 2909 00003696 B2FC <1> mov dl, 0FCh 2910 00003698 EC <1> in al, dx ; read register 2911 00003699 EB00 <1> JMP $+2 ; I/O DELAY 2912 0000369B 0C08 <1> or al, 8 ; enable bit 3 (OUT2) 2913 0000369D EE <1> out dx, al ; write back to register 2914 0000369E EB00 <1> JMP $+2 ; I/O DELAY 2915 <1> ;mov dx, 2F9h ; 3F9h ; interrupt enable register 2916 000036A0 B2F9 <1> mov dl, 0F9h 2917 000036A2 EC <1> in al, dx ; read register 2918 000036A3 EB00 <1> JMP $+2 ; I/O DELAY 2919 <1> ;or al, 1 ; receiver data interrupt enable and 2920 000036A5 0C03 <1> or al, 3 ; transmitter empty interrupt enable 2921 000036A7 EE <1> out dx, al ; write back to register 2922 000036A8 EB00 <1> JMP $+2 ; I/O DELAY 2923 000036AA E421 <1> in al, 21h ; read interrupt mask register 2924 000036AC EB00 <1> JMP $+2 ; I/O DELAY 2925 <1> ;and al, 0F7h ; 0EFh ; enable IRQ 3 (COM2) 2926 000036AE 20E0 <1> and al, ah ; 0F7h or 0EFh 2927 000036B0 E621 <1> out 21h, al ; write back to register 2928 <1> ; 2929 <1> ;popf 2930 000036B2 C3 <1> retn 2931 <1> 2932 <1> sp_invp_err: 2933 000036B3 C705[186F0000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 2933 000036BB 0000 <1> 2934 000036BD 31C9 <1> xor ecx, ecx 2935 000036BF 49 <1> dec ecx ; 0FFFFh 2936 000036C0 F9 <1> stc 2937 000036C1 C3 <1> retn 2938 <1> 2939 <1> ; 29/10/2015 2940 <1> b_div_tbl: ; Baud rate divisor table (115200/divisor) 2941 000036C2 010C0603080401 <1> db 1, 12, 6, 3, 8, 4, 1 2942 <1> 2943 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 2944 <1> epoch: 2945 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 2946 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 2947 <1> ; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM) 2948 <1> ; 'epoch' procedure prototype: 2949 <1> ; UNIXCOPY.ASM, 10/03/2013 2950 <1> ; 14/11/2012 2951 <1> ; unixboot.asm (boot file configuration) 2952 <1> ; version of "epoch" procedure in "unixproc.asm" 2953 <1> ; 21/7/2012 2954 <1> ; 15/7/2012 2955 <1> ; 14/7/2012 2956 <1> ; Erdogan Tan - RETRO UNIX v0.1 2957 <1> ; compute current date and time as UNIX Epoch/Time 2958 <1> ; UNIX Epoch: seconds since 1/1/1970 00:00:00 2959 <1> ; 2960 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 2961 <1> ; 2962 000036C9 E81B010000 <1> call get_rtc_time ; Return Current Time 2963 000036CE 86E9 <1> xchg ch,cl 2964 000036D0 66890D[166B0000] <1> mov [hour], cx 2965 000036D7 86F2 <1> xchg dh,dl 2966 000036D9 668915[1A6B0000] <1> mov [second], dx 2967 <1> ; 2968 000036E0 E835010000 <1> call get_rtc_date ; Return Current Date 2969 000036E5 86E9 <1> xchg ch,cl 2970 000036E7 66890D[106B0000] <1> mov [year], cx 2971 000036EE 86F2 <1> xchg dh,dl 2972 000036F0 668915[126B0000] <1> mov [month], dx 2973 <1> ; 2974 000036F7 66B93030 <1> mov cx, 3030h 2975 <1> ; 2976 000036FB A0[166B0000] <1> mov al, [hour] ; Hour 2977 <1> ; AL <= BCD number) 2978 00003700 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2979 <1> ; AH = AL / 10h 2980 <1> ; AL = AL MOD 10h 2981 00003702 D50A <1> aad ; AX= AH*10+AL 2982 00003704 A2[166B0000] <1> mov [hour], al 2983 00003709 A0[176B0000] <1> mov al, [hour+1] ; Minute 2984 <1> ; AL <= BCD number) 2985 0000370E D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2986 <1> ; AH = AL / 10h 2987 <1> ; AL = AL MOD 10h 2988 00003710 D50A <1> aad ; AX= AH*10+AL 2989 00003712 A2[186B0000] <1> mov [minute], al 2990 00003717 A0[1A6B0000] <1> mov al, [second] ; Second 2991 <1> ; AL <= BCD number) 2992 0000371C D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2993 <1> ; AH = AL / 10h 2994 <1> ; AL = AL MOD 10h 2995 0000371E D50A <1> aad ; AX= AH*10+AL 2996 00003720 A2[1A6B0000] <1> mov [second], al 2997 00003725 66A1[106B0000] <1> mov ax, [year] ; Year (century) 2998 <1> ;push ax 2999 <1> ; 04/12/2021 3000 0000372B 50 <1> push eax 3001 <1> ; AL <= BCD number) 3002 0000372C D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3003 <1> ; AH = AL / 10h 3004 <1> ; AL = AL MOD 10h 3005 0000372E D50A <1> aad ; AX= AH*10+AL 3006 00003730 B464 <1> mov ah, 100 3007 00003732 F6E4 <1> mul ah 3008 00003734 66A3[106B0000] <1> mov [year], ax 3009 <1> ;pop ax 3010 <1> ; 04/12/2021 3011 0000373A 58 <1> pop eax 3012 0000373B 88E0 <1> mov al, ah 3013 <1> ; AL <= BCD number) 3014 0000373D D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3015 <1> ; AH = AL / 10h 3016 <1> ; AL = AL MOD 10h 3017 0000373F D50A <1> aad ; AX= AH*10+AL 3018 00003741 660105[106B0000] <1> add [year], ax 3019 00003748 A0[126B0000] <1> mov al, [month] ; Month 3020 <1> ; AL <= BCD number) 3021 0000374D D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3022 <1> ; AH = AL / 10h 3023 <1> ; AL = AL MOD 10h 3024 0000374F D50A <1> aad ; AX= AH*10+AL 3025 00003751 A2[126B0000] <1> mov [month], al 3026 00003756 A0[136B0000] <1> mov al, [month+1] ; Day 3027 <1> ; AL <= BCD number) 3028 0000375B D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3029 <1> ; AH = AL / 10h 3030 <1> ; AL = AL MOD 10h 3031 0000375D D50A <1> aad ; AX= AH*10+AL 3032 0000375F A2[146B0000] <1> mov [day], al 3033 <1> 3034 <1> convert_to_epoch: 3035 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification) 3036 <1> ; 09/04/2013 (Retro UNIX 8086 v1) 3037 <1> ; 3038 <1> ; ((Modified registers: EAX, EDX, EBX)) 3039 <1> ; 3040 <1> ; Derived from DALLAS Semiconductor 3041 <1> ; Application Note 31 (DS1602/DS1603) 3042 <1> ; 6 May 1998 3043 00003764 29C0 <1> sub eax, eax 3044 00003766 66A1[106B0000] <1> mov ax, [year] 3045 0000376C 662DB207 <1> sub ax, 1970 3046 00003770 BA6D010000 <1> mov edx, 365 3047 00003775 F7E2 <1> mul edx 3048 00003777 31DB <1> xor ebx, ebx 3049 00003779 8A1D[126B0000] <1> mov bl, [month] 3050 0000377F FECB <1> dec bl 3051 00003781 D0E3 <1> shl bl, 1 3052 <1> ;sub edx, edx 3053 00003783 668B93[1C6B0000] <1> mov dx, [EBX+DMonth] 3054 0000378A 8A1D[146B0000] <1> mov bl, [day] 3055 00003790 FECB <1> dec bl 3056 00003792 01D0 <1> add eax, edx 3057 00003794 01D8 <1> add eax, ebx 3058 <1> ; EAX = days since 1/1/1970 3059 00003796 668B15[106B0000] <1> mov dx, [year] 3060 0000379D 6681EAB107 <1> sub dx, 1969 3061 000037A2 66D1EA <1> shr dx, 1 3062 000037A5 66D1EA <1> shr dx, 1 3063 <1> ; (year-1969)/4 3064 000037A8 01D0 <1> add eax, edx 3065 <1> ; + leap days since 1/1/1970 3066 000037AA 803D[126B0000]02 <1> cmp byte [month], 2 ; if past february 3067 000037B1 7610 <1> jna short cte1 3068 000037B3 668B15[106B0000] <1> mov dx, [year] 3069 000037BA 6683E203 <1> and dx, 3 ; year mod 4 3070 000037BE 7503 <1> jnz short cte1 3071 <1> ; and if leap year 3072 000037C0 83C001 <1> add eax, 1 ; add this year's leap day (february 29) 3073 <1> cte1: ; compute seconds since 1/1/1970 3074 000037C3 BA18000000 <1> mov edx, 24 3075 000037C8 F7E2 <1> mul edx 3076 000037CA 8A15[166B0000] <1> mov dl, [hour] 3077 000037D0 01D0 <1> add eax, edx 3078 <1> ; EAX = hours since 1/1/1970 00:00:00 3079 <1> ;mov ebx, 60 3080 000037D2 B33C <1> mov bl, 60 3081 000037D4 F7E3 <1> mul ebx 3082 000037D6 8A15[186B0000] <1> mov dl, [minute] 3083 000037DC 01D0 <1> add eax, edx 3084 <1> ; EAX = minutes since 1/1/1970 00:00:00 3085 <1> ;mov ebx, 60 3086 000037DE F7E3 <1> mul ebx 3087 000037E0 8A15[1A6B0000] <1> mov dl, [second] 3088 000037E6 01D0 <1> add eax, edx 3089 <1> ; EAX -> seconds since 1/1/1970 00:00:00 3090 000037E8 C3 <1> retn 3091 <1> 3092 <1> get_rtc_time: 3093 <1> ; 15/03/2015 3094 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3095 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3096 <1> ; INT 1Ah 3097 <1> ; (AH) = 02H READ THE REAL TIME CLOCK AND RETURN WITH, : 3098 <1> ; (CH) = HOURS IN BCD (00-23) : 3099 <1> ; (CL) = MINUTES IN BCD (00-59) : 3100 <1> ; (DH) = SECONDS IN BCD (00-59) : 3101 <1> ; (DL) = DAYLIGHT SAVINGS ENABLE (00-01). : 3102 <1> ; 3103 <1> RTC_20: ; GET RTC TIME 3104 000037E9 FA <1> cli 3105 000037EA E845D3FFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3106 000037EF 7227 <1> JC short RTC_29 ; EXIT IF ERROR (CY= 1) 3107 <1> 3108 000037F1 B000 <1> MOV AL, CMOS_SECONDS ; SET ADDRESS OF SECONDS 3109 000037F3 E826D3FFFF <1> CALL CMOS_READ ; GET SECONDS 3110 000037F8 88C6 <1> MOV DH, AL ; SAVE 3111 000037FA B00B <1> MOV AL, CMOS_REG_B ; ADDRESS ALARM REGISTER 3112 000037FC E81DD3FFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 3113 00003801 2401 <1> AND AL, 00000001B ; MASK FOR VALID DSE BIT 3114 00003803 88C2 <1> MOV DL, AL ; SET [DL] TO ZERO FOR NO DSE BIT 3115 00003805 B002 <1> MOV AL, CMOS_MINUTES ; SET ADDRESS OF MINUTES 3116 00003807 E812D3FFFF <1> CALL CMOS_READ ; GET MINUTES 3117 0000380C 88C1 <1> MOV CL, AL ; SAVE 3118 0000380E B004 <1> MOV AL, CMOS_HOURS ; SET ADDRESS OF HOURS 3119 00003810 E809D3FFFF <1> CALL CMOS_READ ; GET HOURS 3120 00003815 88C5 <1> MOV CH, AL ; SAVE 3121 00003817 F8 <1> CLC ; SET CY= 0 3122 <1> RTC_29: 3123 00003818 FB <1> sti 3124 00003819 C3 <1> RETn ; RETURN WITH RESULT IN CARRY FLAG 3125 <1> 3126 <1> get_rtc_date: 3127 <1> ; 15/03/2015 3128 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3129 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3130 <1> ; INT 1Ah 3131 <1> ; (AH) = 04H READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,: 3132 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 3133 <1> ; (CL) = YEAR IN BCD (00-99) : 3134 <1> ; (DH) = MONTH IN BCD (01-12) : 3135 <1> ; (DL) = DAY IN BCD (01-31). 3136 <1> ; 3137 <1> RTC_40: ; GET RTC DATE 3138 0000381A FA <1> cli 3139 0000381B E814D3FFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3140 00003820 7225 <1> JC short RTC_49 ; EXIT IF ERROR (CY= 1) 3141 <1> 3142 00003822 B007 <1> MOV AL, CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH 3143 00003824 E8F5D2FFFF <1> CALL CMOS_READ ; READ DAY OF MONTH 3144 00003829 88C2 <1> MOV DL, AL ; SAVE 3145 0000382B B008 <1> MOV AL, CMOS_MONTH ; ADDRESS MONTH 3146 0000382D E8ECD2FFFF <1> CALL CMOS_READ ; READ MONTH 3147 00003832 88C6 <1> MOV DH, AL ; SAVE 3148 00003834 B009 <1> MOV AL, CMOS_YEAR ; ADDRESS YEAR 3149 00003836 E8E3D2FFFF <1> CALL CMOS_READ ; READ YEAR 3150 0000383B 88C1 <1> MOV CL, AL ; SAVE 3151 0000383D B032 <1> MOV AL, CMOS_CENTURY ; ADDRESS CENTURY LOCATION 3152 0000383F E8DAD2FFFF <1> CALL CMOS_READ ; GET CENTURY BYTE 3153 00003844 88C5 <1> MOV CH, AL ; SAVE 3154 00003846 F8 <1> CLC ; SET CY=0 3155 <1> RTC_49: 3156 00003847 FB <1> sti 3157 00003848 C3 <1> RETn ; RETURN WITH RESULTS IN CARRY FLAG 3158 <1> 3159 <1> set_date_time: 3160 <1> convert_from_epoch: 3161 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 3162 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 3163 <1> ; 'convert_from_epoch' procedure prototype: 3164 <1> ; UNIXCOPY.ASM, 10/03/2013 3165 <1> ; 3166 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 3167 <1> ; 3168 <1> ; Derived from DALLAS Semiconductor 3169 <1> ; Application Note 31 (DS1602/DS1603) 3170 <1> ; 6 May 1998 3171 <1> ; 3172 <1> ; INPUT: 3173 <1> ; EAX = Unix (Epoch) Time 3174 <1> ; 3175 00003849 31D2 <1> xor edx, edx 3176 0000384B B93C000000 <1> mov ecx, 60 3177 00003850 F7F1 <1> div ecx 3178 <1> ;mov [imin], eax ; whole minutes 3179 <1> ; since 1/1/1970 3180 00003852 668915[1A6B0000] <1> mov [second], dx ; leftover seconds 3181 00003859 29D2 <1> sub edx, edx 3182 0000385B F7F1 <1> div ecx 3183 <1> ;mov [ihrs], eax ; whole hours 3184 <1> ; ; since 1/1/1970 3185 0000385D 668915[186B0000] <1> mov [minute], dx ; leftover minutes 3186 00003864 31D2 <1> xor edx, edx 3187 <1> ;mov cx, 24 3188 00003866 B118 <1> mov cl, 24 3189 00003868 F7F1 <1> div ecx 3190 <1> ;mov [iday], ax ; whole days 3191 <1> ; since 1/1/1970 3192 0000386A 668915[166B0000] <1> mov [hour], dx ; leftover hours 3193 00003871 05DB020000 <1> add eax, 365+366 ; whole day since 3194 <1> ; 1/1/1968 3195 <1> ;mov [iday], ax 3196 00003876 50 <1> push eax 3197 00003877 29D2 <1> sub edx, edx 3198 00003879 B9B5050000 <1> mov ecx, (4*365)+1 ; 4 years = 1461 days 3199 0000387E F7F1 <1> div ecx 3200 00003880 59 <1> pop ecx 3201 <1> ;mov [lday], ax ; count of quadyrs (4 years) 3202 00003881 6652 <1> push dx 3203 <1> ;mov [qday], dx ; days since quadyr began 3204 00003883 6683FA3C <1> cmp dx, 31 + 29 ; if past feb 29 then 3205 00003887 F5 <1> cmc ; add this quadyr's leap day 3206 00003888 83D000 <1> adc eax, 0 ; to # of qadyrs (leap days) 3207 <1> ;mov [lday], ax ; since 1968 3208 <1> ;mov cx, [iday] 3209 0000388B 91 <1> xchg ecx, eax ; ECX = lday, EAX = iday 3210 0000388C 29C8 <1> sub eax, ecx ; iday - lday 3211 0000388E B96D010000 <1> mov ecx, 365 3212 00003893 31D2 <1> xor edx, edx 3213 <1> ; EAX = iday-lday, EDX = 0 3214 00003895 F7F1 <1> div ecx 3215 <1> ;mov [iyrs], ax ; whole years since 1968 3216 <1> ;jday = iday - (iyrs*365) - lday 3217 <1> ;mov [jday], dx ; days since 1/1 of current year 3218 <1> ;add eax, 1968 3219 00003897 6605B007 <1> add ax, 1968 ; compute year 3220 0000389B 66A3[106B0000] <1> mov [year], ax 3221 000038A1 6689D1 <1> mov cx, dx 3222 <1> ;mov dx, [qday] 3223 000038A4 665A <1> pop dx 3224 000038A6 6681FA6D01 <1> cmp dx, 365 ; if qday <= 365 and qday >= 60 3225 000038AB 7709 <1> ja short cfe1 ; jday = jday +1 3226 000038AD 6683FA3C <1> cmp dx, 60 ; if past 2/29 and leap year then 3227 000038B1 F5 <1> cmc ; add a leap day to the # of whole 3228 000038B2 6683D100 <1> adc cx, 0 ; days since 1/1 of current year 3229 <1> cfe1: 3230 <1> ;mov [jday], cx 3231 000038B6 66BB0C00 <1> mov bx, 12 ; estimate month 3232 000038BA 66BA6E01 <1> mov dx, 366 ; mday, max. days since 1/1 is 365 3233 000038BE 6683E003 <1> and ax, 11b ; year mod 4 (and dx, 3) 3234 <1> cfe2: ; Month calculation ; 0 to 11 (11 to 0) 3235 000038C2 6639D1 <1> cmp cx, dx ; mday = # of days passed from 1/1 3236 000038C5 731D <1> jnb short cfe3 3237 000038C7 664B <1> dec bx ; month = month - 1 3238 000038C9 66D1E3 <1> shl bx, 1 3239 000038CC 668B93[1C6B0000] <1> mov dx, [EBX+DMonth] ; # elapsed days at 1st of month 3240 000038D3 66D1EB <1> shr bx, 1 ; bx = month - 1 (0 to 11) 3241 000038D6 6683FB01 <1> cmp bx, 1 ; if month > 2 and year mod 4 = 0 3242 000038DA 76E6 <1> jna short cfe2 ; then mday = mday + 1 3243 000038DC 08C0 <1> or al, al ; if past 2/29 and leap year then 3244 000038DE 75E2 <1> jnz short cfe2 ; add leap day (to mday) 3245 000038E0 6642 <1> inc dx ; mday = mday + 1 3246 000038E2 EBDE <1> jmp short cfe2 3247 <1> cfe3: 3248 000038E4 6643 <1> inc bx ; -> bx = month, 1 to 12 3249 000038E6 66891D[126B0000] <1> mov [month], bx 3250 000038ED 6629D1 <1> sub cx, dx ; day = jday - mday + 1 3251 000038F0 6641 <1> inc cx 3252 000038F2 66890D[146B0000] <1> mov [day], cx 3253 <1> 3254 <1> ; eax, ebx, ecx, edx is changed at return 3255 <1> ; output -> 3256 <1> ; [year], [month], [day], [hour], [minute], [second] 3257 <1> 3258 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 3259 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 3260 <1> set_date: 3261 000038F9 A0[116B0000] <1> mov al, [year+1] 3262 000038FE D40A <1> aam ; ah = al / 10, al = al mod 10 3263 00003900 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3264 <1> ; AL = AH * 10h + AL 3265 00003902 88C5 <1> mov ch, al ; century (BCD) 3266 00003904 A0[106B0000] <1> mov al, [year] 3267 00003909 D40A <1> aam ; ah = al / 10, al = al mod 10 3268 0000390B D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3269 <1> ; AL = AH * 10h + AL 3270 0000390D 88C1 <1> mov cl, al ; year (BCD) 3271 0000390F A0[126B0000] <1> mov al, [month] 3272 00003914 D40A <1> aam ; ah = al / 10, al = al mod 10 3273 00003916 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3274 <1> ; AL = AH * 10h + AL 3275 00003918 88C6 <1> mov dh, al ; month (BCD) 3276 0000391A A0[146B0000] <1> mov al, [day] 3277 0000391F D40A <1> aam ; ah = al / 10, al = al mod 10 3278 00003921 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3279 <1> ; AL = AH * 10h + AL 3280 00003923 88C6 <1> mov dh, al ; day (BCD) 3281 <1> ; Set real-time clock date 3282 00003925 E879000000 <1> call set_rtc_date 3283 <1> set_time: 3284 <1> ; Read real-time clock time 3285 <1> ; (get day light saving time bit status) 3286 0000392A FA <1> cli 3287 0000392B E804D2FFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3288 <1> ; cf = 1 -> al = 0 3289 00003930 7207 <1> jc short stime1 3290 00003932 B00B <1> MOV AL, CMOS_REG_B ; ADDRESS ALARM REGISTER 3291 00003934 E8E5D1FFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 3292 <1> stime1: 3293 00003939 FB <1> sti 3294 0000393A 2401 <1> AND AL, 00000001B ; MASK FOR VALID DSE BIT 3295 0000393C 88C2 <1> MOV DL, AL ; SET [DL] TO ZERO FOR NO DSE BIT 3296 <1> ; DL = 1 or 0 (day light saving time) 3297 <1> ; 3298 0000393E A0[166B0000] <1> mov al, [hour] 3299 00003943 D40A <1> aam ; ah = al / 10, al = al mod 10 3300 00003945 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3301 <1> ; AL = AH * 10h + AL 3302 00003947 88C5 <1> mov ch, al ; hour (BCD) 3303 00003949 A0[186B0000] <1> mov al, [minute] 3304 0000394E D40A <1> aam ; ah = al / 10, al = al mod 10 3305 00003950 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3306 <1> ; AL = AH * 10h + AL 3307 00003952 88C1 <1> mov cl, al ; minute (BCD) 3308 00003954 A0[1A6B0000] <1> mov al, [second] 3309 00003959 D40A <1> aam ; ah = al / 10, al = al mod 10 3310 0000395B D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3311 <1> ; AL = AH * 10h + AL 3312 0000395D 88C6 <1> mov dh, al ; second (BCD) 3313 <1> ; Set real-time clock time 3314 <1> ; call set_rtc_time 3315 <1> set_rtc_time: 3316 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 3317 <1> ; 15/03/2015 3318 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3319 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3320 <1> ; INT 1Ah 3321 <1> ; (AH) = 03H SET THE REAL TIME CLOCK USING, : 3322 <1> ; (CH) = HOURS IN BCD (00-23) : 3323 <1> ; (CL) = MINUTES IN BCD (00-59) : 3324 <1> ; (DH) = SECONDS IN BCD (00-59) : 3325 <1> ; (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00. : 3326 <1> ; : 3327 <1> ; NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. : 3328 <1> ; (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN : 3329 <1> ; APRIL (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN : 3330 <1> ; OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME. : 3331 <1> ; 3332 <1> RTC_30: ; SET RTC TIME 3333 0000395F FA <1> cli 3334 00003960 E8CFD1FFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3335 00003965 7305 <1> JNC short RTC_35 ; GO AROUND IF CLOCK OPERATING 3336 00003967 E886000000 <1> CALL RTC_STA ; ELSE TRY INITIALIZING CLOCK 3337 <1> RTC_35: 3338 0000396C 88F4 <1> MOV AH, DH ; GET TIME BYTE - SECONDS 3339 0000396E B000 <1> MOV AL, CMOS_SECONDS ; ADDRESS SECONDS 3340 00003970 E89E000000 <1> CALL CMOS_WRITE ; UPDATE SECONDS 3341 00003975 88CC <1> MOV AH, CL ; GET TIME BYTE - MINUTES 3342 00003977 B002 <1> MOV AL, CMOS_MINUTES ; ADDRESS MINUTES 3343 00003979 E895000000 <1> CALL CMOS_WRITE ; UPDATE MINUTES 3344 0000397E 88EC <1> MOV AH, CH ; GET TIME BYTE - HOURS 3345 00003980 B004 <1> MOV AL, CMOS_HOURS ; ADDRESS HOURS 3346 00003982 E88C000000 <1> CALL CMOS_WRITE ; UPDATE ADDRESS 3347 <1> ;MOV AX, X*CMOS_REG_B ; ADDRESS ALARM REGISTER 3348 00003987 66B80B0B <1> MOV AX, 257*CMOS_REG_B ; 3349 0000398B E88ED1FFFF <1> CALL CMOS_READ ; READ CURRENT TIME 3350 00003990 2462 <1> AND AL, 01100010B ; MASK FOR VALID BIT POSITIONS 3351 00003992 0C02 <1> OR AL, 00000010B ; TURN ON 24 HOUR MODE 3352 00003994 80E201 <1> AND DL, 00000001B ; USE ONLY THE DSE BIT 3353 00003997 08D0 <1> OR AL, DL ; GET DAY LIGHT SAVINGS TIME BIT (OSE) 3354 00003999 86E0 <1> XCHG AH, AL ; PLACE IN WORK REGISTER AND GET ADDRESS 3355 0000399B E873000000 <1> CALL CMOS_WRITE ; SET NEW ALARM BITS 3356 000039A0 F8 <1> CLC ; SET CY= 0 3357 000039A1 FB <1> sti 3358 000039A2 C3 <1> RETn ; RETURN WITH CY= 0 3359 <1> 3360 <1> set_rtc_date: 3361 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 3362 <1> ; 15/03/2015 3363 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3364 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3365 <1> ; INT 1Ah 3366 <1> ; (AH) = 05H SET THE DATE INTO THE REAL TIME CLOCK USING, : 3367 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 3368 <1> ; (CL) = YEAR IN BCD (00-99) : 3369 <1> ; (DH) = MONTH IN BCD (01-12) : 3370 <1> ; (DL) = DAY IN BCD (01-31). 3371 <1> ; 3372 <1> RTC_50: ; SET RTC DATE 3373 000039A3 FA <1> cli 3374 000039A4 E88BD1FFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3375 000039A9 7305 <1> JNC short RTC_55 ; GO AROUND IF NO ERROR 3376 000039AB E842000000 <1> CALL RTC_STA ; ELSE INITIALIZE CLOCK 3377 <1> RTC_55: 3378 000039B0 66B80600 <1> MOV AX, CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE 3379 000039B4 E85A000000 <1> CALL CMOS_WRITE ; LOAD ZEROS TO DAY OF WEEK 3380 000039B9 88D4 <1> MOV AH, DL ; GET DAY OF MONTH BYTE 3381 000039BB B007 <1> MOV AL, CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE 3382 000039BD E851000000 <1> CALL CMOS_WRITE ; WRITE OF DAY OF MONTH REGISTER 3383 000039C2 88F4 <1> MOV AH, DH ; GET MONTH 3384 000039C4 B008 <1> MOV AL, CMOS_MONTH ; ADDRESS MONTH BYTE 3385 000039C6 E848000000 <1> CALL CMOS_WRITE ; WRITE MONTH REGISTER 3386 000039CB 88CC <1> MOV AH, CL ; GET YEAR BYTE 3387 000039CD B009 <1> MOV AL, CMOS_YEAR ; ADDRESS YEAR REGISTER 3388 000039CF E83F000000 <1> CALL CMOS_WRITE ; WRITE YEAR REGISTER 3389 000039D4 88EC <1> MOV AH, CH ; GET CENTURY BYTE 3390 000039D6 B032 <1> MOV AL, CMOS_CENTURY ; ADDRESS CENTURY BYTE 3391 000039D8 E836000000 <1> CALL CMOS_WRITE ; WRITE CENTURY LOCATION 3392 <1> ;MOV AX, X*CMOS_REG_B ; ADDRESS ALARM REGISTER 3393 000039DD 66B80B0B <1> MOV AX, 257*CMOS_REG_B ; 3394 000039E1 E838D1FFFF <1> CALL CMOS_READ ; READ CURRENT SETTINGS 3395 000039E6 247F <1> AND AL, 07FH ; CLEAR 'SET BIT' 3396 000039E8 86E0 <1> XCHG AH, AL ; MOVE TO WORK REGISTER 3397 000039EA E824000000 <1> CALL CMOS_WRITE ; AND START CLOCK UPDATING 3398 000039EF F8 <1> CLC ; SET CY= 0 3399 000039F0 FB <1> sti 3400 000039F1 C3 <1> RETn ; RETURN CY=0 3401 <1> 3402 <1> ; 15/03/2015 3403 <1> RTC_STA: ; INITIALIZE REAL TIME CLOCK 3404 000039F2 B426 <1> mov ah, 26h 3405 000039F4 B00A <1> mov al, CMOS_REG_A ; ADDRESS REGISTER A AND LOAD DATA MASK 3406 000039F6 E818000000 <1> CALL CMOS_WRITE ; INITIALIZE STATUS REGISTER A 3407 000039FB B482 <1> mov ah, 82h 3408 000039FD B00B <1> mov al, CMOS_REG_B ; SET "SET BIT" FOR CLOCK INITIALIZATION 3409 000039FF E80F000000 <1> CALL CMOS_WRITE ; AND 24 HOUR MODE TO REGISTER B 3410 00003A04 B00C <1> MOV AL, CMOS_REG_C ; ADDRESS REGISTER C 3411 00003A06 E813D1FFFF <1> CALL CMOS_READ ; READ REGISTER C TO INITIALIZE 3412 00003A0B B00D <1> MOV AL, CMOS_REG_D ; ADDRESS REGISTER D 3413 00003A0D E80CD1FFFF <1> CALL CMOS_READ ; READ REGISTER D TO INITIALIZE 3414 00003A12 C3 <1> RETn 3415 <1> 3416 <1> ; 15/03/2015 3417 <1> ; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm) 3418 <1> CMOS_WRITE: ; WRITE (AH) TO LOCATION (AL) 3419 00003A13 9C <1> pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 3420 <1> ;push ax ; SAVE WORK REGISTER VALUES 3421 00003A14 D0C0 <1> rol al, 1 ; MOVE NMI BIT TO LOW POSITION 3422 00003A16 F9 <1> stc ; FORCE NMI BIT ON IN CARRY FLAG 3423 00003A17 D0D8 <1> rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 3424 00003A19 FA <1> cli ; DISABLE INTERRUPTS 3425 00003A1A E670 <1> out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 3426 00003A1C 88E0 <1> mov al, ah ; GET THE DATA BYTE TO WRITE 3427 00003A1E E671 <1> out CMOS_DATA, al ; PLACE IN REQUESTED CMOS LOCATION 3428 00003A20 B01E <1> mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 3429 00003A22 D0D8 <1> rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 3430 00003A24 E670 <1> out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 3431 00003A26 90 <1> nop ; I/O DELAY 3432 00003A27 E471 <1> in al, CMOS_DATA ; OPEN STANDBY LATCH 3433 <1> ;pop ax ; RESTORE WORK REGISTERS 3434 00003A29 9D <1> popf 3435 00003A2A C3 <1> RETn 3436 <1> 3437 <1> bf_init: 3438 <1> ; 28/11/2021 3439 <1> ; 14/08/2015 3440 <1> ; 02/07/2015 3441 <1> ; 01/07/2015 3442 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 3443 <1> ; Buffer (pointer) initialization ! 3444 <1> ; 3445 <1> ; 17/07/2013 - 24/07/2013 3446 <1> ; Retro UNIX 8086 v1 (U9.ASM) 3447 <1> ; (Retro UNIX 8086 v1 feature only !) 3448 <1> ; 3449 00003A2B BF[606E0000] <1> mov edi, bufp 3450 00003A30 B8[8C830000] <1> mov eax, buffer + (nbuf*520) 3451 00003A35 29D2 <1> sub edx, edx 3452 00003A37 FECA <1> dec dl 3453 00003A39 31C9 <1> xor ecx, ecx 3454 00003A3B 49 <1> dec ecx 3455 <1> bi0: 3456 00003A3C 2D08020000 <1> sub eax, 520 ; 8 header + 512 data 3457 00003A41 AB <1> stosd 3458 00003A42 89C6 <1> mov esi, eax 3459 00003A44 8916 <1> mov [esi], edx ; 000000FFh 3460 <1> ; Not a valid device sign 3461 00003A46 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 3462 <1> ; Not a valid block number sign 3463 00003A49 3D[5C770000] <1> cmp eax, buffer 3464 00003A4E 77EC <1> ja short bi0 3465 00003A50 B8[4C6F0000] <1> mov eax, sb0 3466 00003A55 AB <1> stosd 3467 00003A56 B8[54710000] <1> mov eax, sb1 3468 00003A5B AB <1> stosd 3469 00003A5C 89C6 <1> mov esi, eax ; offset sb1 3470 00003A5E 8916 <1> mov [esi], edx ; 000000FFh 3471 <1> ; Not a valid device sign 3472 00003A60 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 3473 <1> ; Not a valid block number sign 3474 <1> ; 14/08/2015 3475 <1> ;call rdev_init 3476 <1> ;retn 3477 <1> 3478 <1> ; 28/11/2021 3479 <1> rdev_init: ; root device, super block buffer initialization 3480 <1> ; 14/08/2015 3481 <1> ; Retro UNIX 386 v1 feature only ! 3482 <1> ; 3483 <1> ; NOTE: Disk partitions (file systems), logical 3484 <1> ; drive initialization, partition's start sector etc. 3485 <1> ; will be coded here, later in 'ldrv_init' 3486 <1> 3487 00003A63 0FB605[9A680000] <1> movzx eax, byte [boot_drv] 3488 <1> rdi_0: 3489 00003A6A 3C80 <1> cmp al, 80h 3490 00003A6C 7202 <1> jb short rdi_1 3491 00003A6E 2C7E <1> sub al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1) 3492 <1> rdi_1: 3493 <1> ; temporary - 05/12/2021 3494 00003A70 20C0 <1> and al, al 3495 00003A72 7515 <1> jnz short rdi_2 3496 00003A74 C605[C0680000]12 <1> mov byte [drv.spt], 18 3497 00003A7B C605[B2680000]02 <1> mov byte [drv.heads], 2 3498 00003A82 C605[A4680000]50 <1> mov byte [drv.cylinders], 80 3499 <1> rdi_2: 3500 00003A89 A2[866E0000] <1> mov [rdev], al 3501 00003A8E BB[4C6F0000] <1> mov ebx, sb0 ; super block buffer 3502 00003A93 8903 <1> mov [ebx], eax 3503 00003A95 B001 <1> mov al, 1 ; eax = 1 3504 00003A97 894304 <1> mov [ebx+4], eax ; super block address on disk 3505 <1> ;call diskio 3506 <1> ;retn 3507 <1> ; 28/11/2021 3508 00003A9A E941260000 <1> jmp diskio 3509 <1> 3510 <1> ; 23/10/2015 3511 <1> com1_irq4: 3512 00003A9F [A73A0000] <1> dd dummy_retn 3513 <1> com2_irq3: 3514 00003AA3 [A73A0000] <1> dd dummy_retn 3515 <1> 3516 <1> dummy_retn: 3517 00003AA7 C3 <1> retn 2076 %include 'u1.s' ; 10/05/2015 2077 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2078 <1> ; (re-write kernel for test by using previous version without a major defect) 2079 <1> ; **************************************************************************** 2080 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC 2081 <1> ; Last Modification: 09/01/2022 2082 <1> ; ---------------------------------------------------------------------------- 2083 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2084 <1> ; (v0.1 - Beginning: 11/07/2012) 2085 <1> ; 2086 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2087 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2088 <1> ; 2089 <1> ; 2090 <1> ; 2091 <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s 2092 <1> ; 2093 <1> ; **************************************************************************** 2094 <1> 2095 <1> unkni: ; / used for all system calls 2096 <1> sysent: ; < enter to system call > 2097 <1> ; 25/12/2021 (Retro UNIX 386 v1.2) 2098 <1> ; 19/10/2015 2099 <1> ; 21/09/2015 2100 <1> ; 01/07/2015 2101 <1> ; 19/05/2015 2102 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2103 <1> ; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2104 <1> ; 2105 <1> ; 'unkni' or 'sysent' is sytem entry from various traps. 2106 <1> ; The trap type is determined and an indirect jump is made to 2107 <1> ; the appropriate system call handler. If there is a trap inside 2108 <1> ; the system a jump to panic is made. All user registers are saved 2109 <1> ; and u.sp points to the end of the users stack. The sys (trap) 2110 <1> ; instructor is decoded to get the the system code part (see 2111 <1> ; trap instruction in the PDP-11 handbook) and from this 2112 <1> ; the indirect jump address is calculated. If a bad system call is 2113 <1> ; made, i.e., the limits of the jump table are exceeded, 'badsys' 2114 <1> ; is called. If the call is legitimate control passes to the 2115 <1> ; appropriate system routine. 2116 <1> ; 2117 <1> ; Calling sequence: 2118 <1> ; Through a trap caused by any sys call outside the system. 2119 <1> ; Arguments: 2120 <1> ; Arguments of particular system call. 2121 <1> ; ............................................................... 2122 <1> ; 2123 <1> ; Retro UNIX 8086 v1 modification: 2124 <1> ; System call number is in EAX register. 2125 <1> ; 2126 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 2127 <1> ; registers depending of function details. 2128 <1> ; 2129 <1> ; 16/04/2015 2130 00003AA8 368925[9C6E0000] <1> mov [ss:u.sp], esp ; Kernel stack points to return address 2131 <1> ; save user registers 2132 00003AAF 1E <1> push ds 2133 00003AB0 06 <1> push es 2134 00003AB1 0FA0 <1> push fs 2135 00003AB3 0FA8 <1> push gs 2136 00003AB5 60 <1> pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 2137 <1> ; 2138 <1> ; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015 2139 <1> ; (ESPACE is size of space in kernel stack 2140 <1> ; for saving/restoring user registers.) 2141 <1> ; 2142 00003AB6 50 <1> push eax ; 01/07/2015 2143 00003AB7 66B81000 <1> mov ax, KDATA 2144 00003ABB 8ED8 <1> mov ds, ax 2145 00003ABD 8EC0 <1> mov es, ax 2146 00003ABF 8EE0 <1> mov fs, ax 2147 00003AC1 8EE8 <1> mov gs, ax 2148 00003AC3 A1[A86D0000] <1> mov eax, [k_page_dir] 2149 00003AC8 0F22D8 <1> mov cr3, eax 2150 00003ACB 58 <1> pop eax ; 01/07/2015 2151 <1> ; 19/10/2015 2152 00003ACC FC <1> cld 2153 <1> ; 2154 00003ACD FE05[9A6E0000] <1> inc byte [sysflg] 2155 <1> ; incb sysflg / indicate a system routine is in progress 2156 00003AD3 FB <1> sti ; 18/01/2014 2157 <1> ;jnz panic ; 24/05/2013 2158 <1> ; 04/12/2021 2159 00003AD4 7405 <1> jz short _1 2160 00003AD6 E969F9FFFF <1> jmp panic 2161 <1> ; beq 1f 2162 <1> ; jmp panic ; / called if trap inside system 2163 <1> ;1: 2164 <1> _1: ; 04/12/2021 2165 <1> ; 16/04/2015 2166 00003ADB A3[A46E0000] <1> mov [u.r0], eax 2167 00003AE0 8925[A06E0000] <1> mov [u.usp], esp ; kernel stack points to user's registers 2168 <1> ; 2169 <1> ; mov $s.syst+2,clockp 2170 <1> ; mov r0,-(sp) / save user registers 2171 <1> ; mov sp,u.r0 / pointer to bottom of users stack 2172 <1> ; / in u.r0 2173 <1> ; mov r1,-(sp) 2174 <1> ; mov r2,-(sp) 2175 <1> ; mov r3,-(sp) 2176 <1> ; mov r4,-(sp) 2177 <1> ; mov r5,-(sp) 2178 <1> ; mov ac,-(sp) / "accumulator" register for extended 2179 <1> ; / arithmetic unit 2180 <1> ; mov mq,-(sp) / "multiplier quotient" register for the 2181 <1> ; / extended arithmetic unit 2182 <1> ; mov sc,-(sp) / "step count" register for the extended 2183 <1> ; / arithmetic unit 2184 <1> ; mov sp,u.sp / u.sp points to top of users stack 2185 <1> ; mov 18.(sp),r0 / store pc in r0 2186 <1> ; mov -(r0),r0 / sys inst in r0 10400xxx 2187 <1> ; sub $sys,r0 / get xxx code 2188 00003AE6 C1E002 <1> shl eax, 2 2189 <1> ; asl r0 / multiply by 2 to jump indirect in bytes 2190 00003AE9 3DA0000000 <1> cmp eax, end_of_syscalls - syscalls 2191 <1> ; cmp r0,$2f-1f / limit of table (35) exceeded 2192 <1> ;jnb short badsys 2193 <1> ; bhis badsys / yes, bad system call 2194 <1> ; 25/12/2021 2195 00003AEE 7205 <1> jb short _2 2196 00003AF0 E969010000 <1> jmp badsys 2197 <1> _2: 2198 <1> ; 25/12/2021 2199 <1> ;cmc 2200 <1> ;pushf 2201 <1> ;push eax 2202 00003AF5 8B2D[9C6E0000] <1> mov ebp, [u.sp] ; Kernel stack at the beginning of sys call 2203 <1> ;mov al, 0FEh ; 11111110b 2204 <1> ;;adc al, 0 ; al = al + cf 2205 <1> ;and [ebp+8], al ; flags (reset carry flag) 2206 00003AFB 806508FE <1> and byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021 2207 <1> ; bic $341,20.(sp) / set users processor priority to 0 2208 <1> ; / and clear carry bit 2209 <1> ;pop ebp ; eax 2210 00003AFF 89C5 <1> mov ebp, eax ; 25/12/2021 2211 <1> ;popf 2212 <1> ;;jc badsys 2213 <1> ;; 04/12/2021 2214 <1> ;jnc short _3 2215 <1> ;jmp badsys 2216 <1> ;_3: 2217 00003B01 A1[A46E0000] <1> mov eax, [u.r0] 2218 <1> ; system call registers: EAX, EDX, ECX, EBX, ESI, EDI 2219 00003B06 FFA5[0C3B0000] <1> jmp dword [ebp+syscalls] 2220 <1> ; jmp *1f(r0) / jump indirect thru table of addresses 2221 <1> ; / to proper system routine. 2222 <1> 2223 <1> ; 09/01/2022 2224 <1> ; 01/01/2022 (/etc/init error, BugFix efforts, test) 2225 <1> syscalls: ; 1: 2226 <1> ; 21/09/2015 2227 <1> ; 01/07/2015 2228 <1> ; 16/04/2015 (32 bit address modification) 2229 00003B0C [283C0000] <1> dd sysrele ; / 0 2230 00003B10 [E33C0000] <1> dd sysexit ; / 1 2231 00003B14 [113E0000] <1> dd sysfork ; / 2 2232 00003B18 [173F0000] <1> dd sysread ; / 3 2233 00003B1C [4B3F0000] <1> dd syswrite ; / 4 2234 00003B20 [E73F0000] <1> dd sysopen ; / 5 2235 00003B24 [E6400000] <1> dd sysclose ; / 6 2236 00003B28 [943D0000] <1> dd syswait ; / 7 2237 <1> 2238 <1> ; temporary - 'syscreat, syslink, sysunlink' system calls are disabled 2239 <1> ; for 32KB limit test ; 01/01/2022 2240 <1> ;dd syscreat ; / 8 2241 <1> ;dd syslink ; / 9 2242 <1> ;dd sysunlink ; / 10 2243 00003B2C [5E3C0000] <1> dd badsys 2244 00003B30 [5E3C0000] <1> dd badsys 2245 00003B34 [5E3C0000] <1> dd badsys 2246 <1> 2247 00003B38 [F9430000] <1> dd sysexec ; / 11 2248 00003B3C [4F4A0000] <1> dd syschdir ; / 12 2249 00003B40 [734B0000] <1> dd systime ; / 13 2250 <1> 2251 <1> ; temporary - 'sysmkdir' is disabled for 32KB limit test ; 01/01/2022 2252 <1> ;dd sysmkdir ; / 14 2253 00003B44 [5E3C0000] <1> dd badsys 2254 <1> 2255 00003B48 [AA4A0000] <1> dd syschmod ; / 15 2256 00003B4C [D94A0000] <1> dd syschown ; / 16 2257 <1> 2258 <1> ; temporary - 'sysbreak' is disabled for 32KB limit test ; 01/01/2022 2259 <1> ;dd sysbreak ; / 17 2260 00003B50 [5E3C0000] <1> dd badsys 2261 <1> 2262 00003B54 [96470000] <1> dd sysstat ; / 18 2263 00003B58 [A74B0000] <1> dd sysseek ; / 19 2264 00003B5C [B94B0000] <1> dd systell ; / 20 2265 00003B60 [8E5A0000] <1> dd sysmount ; / 21 2266 00003B64 [405B0000] <1> dd sysumount ; / 22 2267 00003B68 [2C4C0000] <1> dd syssetuid ; / 23 2268 00003B6C [614C0000] <1> dd sysgetuid ; / 24 2269 00003B70 [824B0000] <1> dd sysstime ; / 25 2270 00003B74 [204C0000] <1> dd sysquit ; / 26 2271 00003B78 [144C0000] <1> dd sysintr ; / 27 2272 00003B7C [7C470000] <1> dd sysfstat ; / 28 2273 00003B80 [01410000] <1> dd sysemt ; / 29 2274 00003B84 [2F410000] <1> dd sysmdate ; / 30 2275 00003B88 [7E410000] <1> dd sysstty ; / 31 2276 00003B8C [EC420000] <1> dd sysgtty ; / 32 2277 00003B90 [2A410000] <1> dd sysilgins ; / 33 2278 00003B94 [B9630000] <1> dd syssleep ; 34 ; Retro UNIX 8086 v1 feature only ! 2279 <1> ; 11/06/2014 2280 00003B98 [E6630000] <1> dd sysmsg ; 35 ; Retro UNIX 386 v1 feature only ! 2281 <1> ; 01/07/2015 2282 00003B9C [BE640000] <1> dd sysgeterr ; 36 ; Retro UNIX 386 v1 feature only ! 2283 <1> ; 21/09/2015 - get last error number 2284 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 2285 <1> ; 27/03/2021 - Retro UNIX 386 v2 2286 00003BA0 [714C0000] <1> dd syssetgid ; 37 2287 00003BA4 [944C0000] <1> dd sysgetgid ; 38 2288 <1> ; 18/06/2021 - Retro UNIX 386 v2 (ref: TRDOS 386 v2) 2289 00003BA8 [AC4C0000] <1> dd sysver ; 39 ; (get) Retro Unix 386 version 2290 <1> 2291 <1> end_of_syscalls: 2292 <1> 2293 <1> error: 2294 <1> ; 11/12/2021 (Retro UNIX 386 v1.2) 2295 <1> ; 17/09/2015 2296 <1> ; 03/09/2015 2297 <1> ; 01/09/2015 2298 <1> ; 09/06/2015 2299 <1> ; 13/05/2015 2300 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2301 <1> ; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 2302 <1> ; 2303 <1> ; 'error' merely sets the error bit off the processor status (c-bit) 2304 <1> ; then falls right into the 'sysret', 'sysrele' return sequence. 2305 <1> ; 2306 <1> ; INPUTS -> none 2307 <1> ; OUTPUTS -> 2308 <1> ; processor status - carry (c) bit is set (means error) 2309 <1> ; 2310 <1> ; 26/05/2013 (Stack pointer must be reset here! 2311 <1> ; Because, jumps to error procedure 2312 <1> ; disrupts push-pop nesting balance) 2313 <1> ; 2314 00003BAC 8B2D[9C6E0000] <1> mov ebp, [u.sp] ; interrupt (system call) return (iretd) address 2315 00003BB2 804D0801 <1> or byte [ebp+8], 1 ; set carry bit of flags register 2316 <1> ; (system call will return with cf = 1) 2317 <1> ; bis $1,20.(r1) / set c bit in processor status word below 2318 <1> ; / users stack 2319 <1> ; 17/09/2015 2320 00003BB6 83ED30 <1> sub ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc') 2321 <1> ; for saving/restoring user registers 2322 <1> ;cmp ebp, [u.usp] 2323 <1> ;je short err0 2324 00003BB9 892D[A06E0000] <1> mov [u.usp], ebp 2325 <1> ;err0: 2326 <1> ; 01/09/2015 2327 00003BBF 8B25[A06E0000] <1> mov esp, [u.usp] ; Retro Unix 8086 v1 modification! 2328 <1> ; 10/04/2013 2329 <1> ; (If an I/O error occurs during disk I/O, 2330 <1> ; related procedures will jump to 'error' 2331 <1> ; procedure directly without returning to 2332 <1> ; the caller procedure. So, stack pointer 2333 <1> ; must be restored here.) 2334 <1> ; 13/05/2015 2335 <1> ; NOTE: (The last) error code is in 'u.error', it can be retrieved by 2336 <1> ; 'get last error' system call later. 2337 <1> 2338 <1> ; 03/09/2015 - 09/06/2015 - 07/08/2013 2339 00003BC5 C605[166F0000]00 <1> mov byte [u.kcall], 0 ; namei_r, mkdir_w reset 2340 <1> 2341 <1> sysret: ; < return from system call> 2342 <1> ; 11/12/2021 2343 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 2344 <1> ; 30/11/2021 2345 <1> ; 10/09/2015 2346 <1> ; 29/07/2015 2347 <1> ; 25/06/2015 2348 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2349 <1> ; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 2350 <1> ; 2351 <1> ; 'sysret' first checks to see if process is about to be 2352 <1> ; terminated (u.bsys). If it is, 'sysexit' is called. 2353 <1> ; If not, following happens: 2354 <1> ; 1) The user's stack pointer is restored. 2355 <1> ; 2) r1=0 and 'iget' is called to see if last mentioned 2356 <1> ; i-node has been modified. If it has, it is written out 2357 <1> ; via 'ppoke'. 2358 <1> ; 3) If the super block has been modified, it is written out 2359 <1> ; via 'ppoke'. 2360 <1> ; 4) If the dismountable file system's super block has been 2361 <1> ; modified, it is written out to the specified device 2362 <1> ; via 'ppoke'. 2363 <1> ; 5) A check is made if user's time quantum (uquant) ran out 2364 <1> ; during his execution. If so, 'tswap' is called to give 2365 <1> ; another user a chance to run. 2366 <1> ; 6) 'sysret' now goes into 'sysrele'. 2367 <1> ; (See 'sysrele' for conclusion.) 2368 <1> ; 2369 <1> ; Calling sequence: 2370 <1> ; jump table or 'br sysret' 2371 <1> ; Arguments: 2372 <1> ; - 2373 <1> ; ............................................................... 2374 <1> ; 2375 <1> ; ((AX=r1 for 'iget' input)) 2376 <1> ; 2377 <1> ;xor ax, ax ; 04/05/2013 2378 <1> ; 30/11/2021 2379 00003BCC 31C0 <1> xor eax, eax 2380 <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec) 2381 00003BCE FEC0 <1> inc al ; 04/05/2013 2382 00003BD0 3805[F46E0000] <1> cmp [u.bsys], al ; 1 2383 <1> ; tstb u.bsys / is a process about to be terminated because 2384 <1> ;jnb sysexit ; 04/05/2013 2385 <1> ; ; bne sysexit / of an error? yes, go to sysexit 2386 <1> ; 04/12/2021 2387 00003BD6 720F <1> jb short _3 2388 <1> ; 11/12/2021 2389 00003BD8 C705[186F0000]0100- <1> mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 2389 00003BE0 0000 <1> 2390 00003BE2 E9FC000000 <1> jmp sysexit 2391 <1> _3: 2392 <1> ;mov esp, [u.usp] ; 24/05/2013 (that is not needed here) 2393 <1> ; mov u.sp,sp / no point stack to users stack 2394 00003BE7 FEC8 <1> dec al ; mov ax, 0 2395 <1> ; clr r1 / zero r1 to check last mentioned i-node 2396 00003BE9 E882160000 <1> call iget 2397 <1> ; jsr r0,iget / if last mentioned i-node has been modified 2398 <1> ; / it is written out 2399 <1> ;xor ax, ax ; 0 2400 <1> ; 30/11/2021 2401 00003BEE 31C0 <1> xor eax, eax 2402 00003BF0 3805[986E0000] <1> cmp [smod], al ; 0 2403 <1> ; tstb smod / has the super block been modified 2404 00003BF6 7614 <1> jna short sysret1 2405 <1> ; beq 1f / no, 1f 2406 00003BF8 A2[986E0000] <1> mov [smod], al ; 0 2407 <1> ; clrb smod / yes, clear smod 2408 00003BFD BB[4C6F0000] <1> mov ebx, sb0 ;; 07/08//2013 2409 00003C02 66810B0002 <1> or word [ebx], 200h ;; 2410 <1> ;or word [sb0], 200h ; write bit, bit 9 2411 <1> ; bis $1000,sb0 / set write bit in I/O queue for super block 2412 <1> ; / output 2413 <1> ; AX = 0 2414 00003C07 E8B3230000 <1> call poke ; 07/08/2013 2415 <1> ;call ppoke 2416 <1> ; AX = 0 2417 <1> ; jsr r0,ppoke / write out modified super block to disk 2418 <1> sysret1: ;1: 2419 00003C0C 3805[996E0000] <1> cmp [mmod], al ; 0 2420 <1> ; tstb mmod / has the super block for the dismountable file 2421 <1> ; / system 2422 00003C12 7614 <1> jna short sysrel0 2423 <1> ; beq 1f / been modified? no, 1f 2424 00003C14 A2[996E0000] <1> mov [mmod], al ; 0 2425 <1> ; clrb mmod / yes, clear mmod 2426 <1> ;mov ax, [mntd] 2427 <1> ;;mov al, [mdev] ; 26/04/2013 2428 00003C19 BB[54710000] <1> mov ebx, sb1 ;; 07/08//2013 2429 <1> ;;mov [ebx], al 2430 <1> ;mov [sb1], al 2431 <1> ; movb mntd,sb1 / set the I/O queue 2432 00003C1E 66810B0002 <1> or word [ebx], 200h 2433 <1> ;or word [sb1], 200h ; write bit, bit 9 2434 <1> ; bis $1000,sb1 / set write bit in I/O queue for detached sb 2435 00003C23 E897230000 <1> call poke ; 07/08/2013 2436 <1> ;call ppoke 2437 <1> ; jsr r0,ppoke / write it out to its device 2438 <1> ;xor al, al ; 26/04/2013 2439 <1> ;1: 2440 <1> ; tstb uquant / is the time quantum 0? 2441 <1> ; bne 1f / no, don't swap it out 2442 <1> 2443 <1> sysrele: ; < release > 2444 <1> ; 14/10/2015 2445 <1> ; 01/09/2015 2446 <1> ; 24/07/2015 2447 <1> ; 14/05/2015 2448 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2449 <1> ; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1) 2450 <1> ; 2451 <1> ; 'sysrele' first calls 'tswap' if the time quantum for a user is 2452 <1> ; zero (see 'sysret'). It then restores the user's registers and 2453 <1> ; turns off the system flag. It then checked to see if there is 2454 <1> ; an interrupt from the user by calling 'isintr'. If there is, 2455 <1> ; the output gets flashed (see isintr) and interrupt action is 2456 <1> ; taken by a branch to 'intract'. If there is no interrupt from 2457 <1> ; the user, a rti is made. 2458 <1> ; 2459 <1> ; Calling sequence: 2460 <1> ; Fall through a 'bne' in 'sysret' & ? 2461 <1> ; Arguments: 2462 <1> ; - 2463 <1> ; ............................................................... 2464 <1> ; 2465 <1> ; 23/02/2014 (swapret) 2466 <1> ; 22/09/2013 2467 <1> sysrel0: ;1: 2468 00003C28 803D[EC6E0000]00 <1> cmp byte [u.quant], 0 ; 16/05/2013 2469 <1> ; tstb uquant / is the time quantum 0? 2470 00003C2F 7705 <1> ja short swapret 2471 <1> ; bne 1f / no, don't swap it out 2472 <1> sysrelease: ; 07/12/2013 (jump from 'clock') 2473 00003C31 E8BD100000 <1> call tswap 2474 <1> ; jsr r0,tswap / yes, swap it out 2475 <1> ; 2476 <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address. 2477 <1> swapret: ;1: 2478 <1> ; 10/09/2015 2479 <1> ; 01/09/2015 2480 <1> ; 14/05/2015 2481 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications) 2482 <1> ; 26/05/2013 (Retro UNIX 8086 v1) 2483 <1> ; cli 2484 <1> ; 24/07/2015 2485 <1> ; 2486 <1> ;; 'esp' must be already equal to '[u.usp]' here ! 2487 <1> ;; mov esp, [u.usp] 2488 <1> 2489 <1> ; 22/09/2013 2490 00003C36 E89D120000 <1> call isintr 2491 <1> ; 20/10/2013 2492 00003C3B 7405 <1> jz short sysrel1 2493 00003C3D E88A000000 <1> call intract 2494 <1> ; jsr r0,isintr / is there an interrupt from the user 2495 <1> ; br intract / yes, output gets flushed, take interrupt 2496 <1> ; / action 2497 <1> sysrel1: 2498 00003C42 FA <1> cli ; 14/10/2015 2499 00003C43 FE0D[9A6E0000] <1> dec byte [sysflg] 2500 <1> ; decb sysflg / turn system flag off 2501 00003C49 A1[046F0000] <1> mov eax, [u.pgdir] 2502 00003C4E 0F22D8 <1> mov cr3, eax ; 1st PDE points to Kernel Page Table 0 (1st 4 MB) 2503 <1> ; (others are different than kernel page tables) 2504 <1> ; 10/09/2015 2505 00003C51 61 <1> popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax 2506 <1> ; mov (sp)+,sc / restore user registers 2507 <1> ; mov (sp)+,mq 2508 <1> ; mov (sp)+,ac 2509 <1> ; mov (sp)+,r5 2510 <1> ; mov (sp)+,r4 2511 <1> ; mov (sp)+,r3 2512 <1> ; mov (sp)+,r2 2513 <1> ; 2514 00003C52 A1[A46E0000] <1> mov eax, [u.r0] ; ((return value in EAX)) 2515 00003C57 0FA9 <1> pop gs 2516 00003C59 0FA1 <1> pop fs 2517 00003C5B 07 <1> pop es 2518 00003C5C 1F <1> pop ds 2519 00003C5D CF <1> iretd 2520 <1> ; rti / no, return from interrupt 2521 <1> 2522 <1> badsys: 2523 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2524 <1> ; (Major Modification: 'core' dumping procedure in 2525 <1> ; original UNIX v1 and Retro UNIX 8086 v1 2526 <1> ; has been changed to print 'Invalid System Call !' 2527 <1> ; message on the user's console tty.) 2528 <1> ; (EIP, EAX values will be shown on screen with error message) 2529 <1> ; (EIP = Return address just after the system call -INT 30h-) 2530 <1> ; (EAX = Function number) 2531 <1> ; 2532 00003C5E FE05[F46E0000] <1> inc byte [u.bsys] 2533 <1> ; 2534 00003C64 8B1D[9C6E0000] <1> mov ebx, [u.sp] ; esp at the beginning of 'sysent' 2535 00003C6A 8B03 <1> mov eax, [ebx] ; EIP (return address, not 'INT 30h' address) 2536 00003C6C E839DBFFFF <1> call dwordtohex 2537 00003C71 8915[046B0000] <1> mov [bsys_msg_eip], edx 2538 00003C77 A3[086B0000] <1> mov [bsys_msg_eip+4], eax 2539 00003C7C A1[A46E0000] <1> mov eax, [u.r0] 2540 00003C81 E824DBFFFF <1> call dwordtohex 2541 00003C86 8915[F46A0000] <1> mov [bsys_msg_eax], edx 2542 00003C8C A3[F86A0000] <1> mov [bsys_msg_eax+4], eax 2543 <1> ; 11/12/2021 2544 <1> ;xor eax, eax 2545 <1> ;mov dword [u.base], badsys_msg ; "Invalid System Call !" 2546 <1> ;mov ebx, [u.fofp] 2547 <1> ;mov [ebx], eax 2548 <1> ;;mov eax, 1 ; inode number of console tty (for user) 2549 <1> ;inc eax 2550 <1> ; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 2551 <1> ; (Retro UNIX 386 v1.2) 2552 <1> ;mov al, 8 ; /dev/tty inode number (runix v2 fs) 2553 <1> ;; eax = 8 ; inode number of console tty (for user) 2554 <1> ;mov dword [u.count], BSYS_M_SIZE 2555 <1> ; writei 2556 <1> ; INPUTS -> 2557 <1> ; r1 - inode number 2558 <1> ; u.count - byte count to be written 2559 <1> ; u.base - points to user buffer 2560 <1> ; u.fofp - points to word with current file offset 2561 <1> ; OUTPUTS -> 2562 <1> ; u.count - cleared 2563 <1> ; u.nread - accumulates total bytes passed back 2564 <1> ; 2565 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 2566 <1> ;call writei 2567 <1> ;;mov eax, 1 2568 <1> ;jmp sysexit 2569 <1> 2570 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 2571 00003C91 BE[D56A0000] <1> mov esi, badsys_msg ; "Invalid System Call !" 2572 00003C96 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 2573 <1> ; temporary - 12/12/2021 2574 <1> ;mov bl, 1 2575 00003C9D 8A83[DF6B0000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2576 <1> ;mov al, 0 2577 00003CA3 C605[D76D0000]0F <1> mov byte [ccolor], 0Fh ; white (message) color 2578 00003CAA A2[D96E0000] <1> mov [u.ttyn], al ; current (active) tty (for user) 2579 00003CAF E8EF270000 <1> call print_cmsg 2580 <1> ;mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 2581 <1> 2582 <1> ; temporary - 11/12/2021 2583 00003CB4 C70500800B00324E32- <1> mov dword [0B8000h], 4E324E32h 2583 00003CBD 4E <1> 2584 00003CBE B9FFFF0000 <1> mov ecx, 0FFFFh 2585 <1> abovexfx: 2586 00003CC3 4A <1> dec edx 2587 00003CC4 42 <1> inc edx 2588 00003CC5 E2FC <1> loop abovexfx 2589 <1> 2590 00003CC7 E9E0FEFFFF <1> jmp error 2591 <1> 2592 <1> ; incb u.bsys / turn on the user's bad-system flag 2593 <1> ; mov $3f,u.namep / point u.namep to "core\0\0" 2594 <1> ; jsr r0,namei / get the i-number for the core image file 2595 <1> ; br 1f / error 2596 <1> ; neg r1 / negate the i-number to open the core image file 2597 <1> ; / for writing 2598 <1> ; jsr r0,iopen / open the core image file 2599 <1> ; jsr r0,itrunc / free all associated blocks 2600 <1> ; br 2f 2601 <1> ;1: 2602 <1> ; mov $17,r1 / put i-node mode (17) in r1 2603 <1> ; jsr r0,maknod / make an i-node 2604 <1> ; mov u.dirbuf,r1 / put i-node number in r1 2605 <1> ;2: 2606 <1> ; mov $core,u.base / move address core to u.base 2607 <1> ; mov $ecore-core,u.count / put the byte count in u.count 2608 <1> ; mov $u.off,u.fofp / more user offset to u.fofp 2609 <1> ; clr u.off / clear user offset 2610 <1> ; jsr r0,writei / write out the core image to the user 2611 <1> ; mov $user,u.base / pt. u.base to user 2612 <1> ; mov $64.,u.count / u.count = 64 2613 <1> ; jsr r0,writei / write out all the user parameters 2614 <1> ; neg r1 / make i-number positive 2615 <1> ; jsr r0,iclose / close the core image file 2616 <1> ; br sysexit / 2617 <1> ;3: 2618 <1> ; 2619 <1> 2620 <1> intract: ; / interrupt action 2621 <1> ; 14/10/2015 2622 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2623 <1> ; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1) 2624 <1> ; 2625 <1> ; Retro UNIX 8086 v1 modification ! 2626 <1> ; (Process/task switching and quit routine by using 2627 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2628 <1> ; 2629 <1> ; input -> 'u.quit' (also value of 'u.intr' > 0) 2630 <1> ; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign) 2631 <1> ; 'intract' will jump to 'sysexit'. 2632 <1> ; Intract will return to the caller 2633 <1> ; if value of 'u.quit' <> FFFFh. 2634 <1> ; 14/10/2015 2635 00003CCC FB <1> sti 2636 <1> ; 07/12/2013 2637 00003CCD 66FF05[F26E0000] <1> inc word [u.quit] 2638 00003CD4 7408 <1> jz short intrct0 ; FFFFh -> 0 2639 00003CD6 66FF0D[F26E0000] <1> dec word [u.quit] 2640 <1> ; 16/04/2015 2641 00003CDD C3 <1> retn 2642 <1> intrct0: 2643 00003CDE 58 <1> pop eax ; call intract -> retn 2644 <1> ; 2645 00003CDF 31C0 <1> xor eax, eax 2646 00003CE1 FEC0 <1> inc al ; mov ax, 1 2647 <1> ;;; 2648 <1> ; UNIX v1 original 'intract' routine... 2649 <1> ; / interrupt action 2650 <1> ;cmp *(sp),$rti / are you in a clock interrupt? 2651 <1> ; bne 1f / no, 1f 2652 <1> ; cmp (sp)+,(sp)+ / pop clock pointer 2653 <1> ; 1: / now in user area 2654 <1> ; mov r1,-(sp) / save r1 2655 <1> ; mov u.ttyp,r1 2656 <1> ; / pointer to tty buffer in control-to r1 2657 <1> ; cmpb 6(r1),$177 2658 <1> ; / is the interrupt char equal to "del" 2659 <1> ; beq 1f / yes, 1f 2660 <1> ; clrb 6(r1) 2661 <1> ; / no, clear the byte 2662 <1> ; / (must be a quit character) 2663 <1> ; mov (sp)+,r1 / restore r1 2664 <1> ; clr u.quit / clear quit flag 2665 <1> ; bis $20,2(sp) 2666 <1> ; / set trace for quit (sets t bit of 2667 <1> ; / ps-trace trap) 2668 <1> ; rti ; / return from interrupt 2669 <1> ; 1: / interrupt char = del 2670 <1> ; clrb 6(r1) / clear the interrupt byte 2671 <1> ; / in the buffer 2672 <1> ; mov (sp)+,r1 / restore r1 2673 <1> ; cmp u.intr,$core / should control be 2674 <1> ; / transferred to loc core? 2675 <1> ; blo 1f 2676 <1> ; jmp *u.intr / user to do rti yes, 2677 <1> ; / transfer to loc core 2678 <1> ; 1: 2679 <1> ; sys 1 / exit 2680 <1> 2681 <1> sysexit: ; 2682 <1> ; 30/11/2021 - etro UNIX 386 v1.2 2683 <1> ; 01/09/2015 2684 <1> ; 31/08/2015 2685 <1> ; 14/05/2015 2686 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2687 <1> ; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2688 <1> ; 2689 <1> ; 'sysexit' terminates a process. First each file that 2690 <1> ; the process has opened is closed by 'flose'. The process 2691 <1> ; status is then set to unused. The 'p.pid' table is then 2692 <1> ; searched to find children of the dying process. If any of 2693 <1> ; children are zombies (died by not waited for), they are 2694 <1> ; set free. The 'p.pid' table is then searched to find the 2695 <1> ; dying process's parent. When the parent is found, it is 2696 <1> ; checked to see if it is free or it is a zombie. If it is 2697 <1> ; one of these, the dying process just dies. If it is waiting 2698 <1> ; for a child process to die, it notified that it doesn't 2699 <1> ; have to wait anymore by setting it's status from 2 to 1 2700 <1> ; (waiting to active). It is awakened and put on runq by 2701 <1> ; 'putlu'. The dying process enters a zombie state in which 2702 <1> ; it will never be run again but stays around until a 'wait' 2703 <1> ; is completed by it's parent process. If the parent is not 2704 <1> ; found, process just dies. This means 'swap' is called with 2705 <1> ; 'u.uno=0'. What this does is the 'wswap' is not called 2706 <1> ; to write out the process and 'rswap' reads the new process 2707 <1> ; over the one that dies..i.e., the dying process is 2708 <1> ; overwritten and destroyed. 2709 <1> ; 2710 <1> ; Calling sequence: 2711 <1> ; sysexit or conditional branch. 2712 <1> ; Arguments: 2713 <1> ; - 2714 <1> ; ............................................................... 2715 <1> ; 2716 <1> ; Retro UNIX 8086 v1 modification: 2717 <1> ; System call number (=1) is in EAX register. 2718 <1> ; 2719 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 2720 <1> ; registers depending of function details. 2721 <1> ; 2722 <1> ; ('swap' procedure is mostly different than original UNIX v1.) 2723 <1> ; 2724 <1> ; / terminate process 2725 <1> ; AX = 1 2726 <1> ;dec ax ; 0 2727 <1> ; 30/11/2021 2728 00003CE3 48 <1> dec eax ; 0 2729 00003CE4 66A3[F06E0000] <1> mov [u.intr], ax ; 0 2730 <1> ; clr u.intr / clear interrupt control word 2731 <1> ; clr r1 / clear r1 2732 <1> 2733 <1> ; temporary - 26/12/2021 2734 00003CEA B9FFFF0000 <1> mov ecx, 0FFFFh 2735 <1> fcloop: 2736 00003CEF 48 <1> dec eax 2737 00003CF0 40 <1> inc eax 2738 00003CF1 4A <1> dec edx 2739 00003CF2 42 <1> inc edx 2740 00003CF3 E2FA <1> loop fcloop 2741 <1> 2742 <1> ; AX = 0 2743 <1> sysexit_1: ; 1: 2744 <1> ; AX = File descriptor 2745 <1> ; / r1 has file descriptor (index to u.fp list) 2746 <1> ; / Search the whole list 2747 00003CF5 E82F0B0000 <1> call fclose 2748 <1> ; jsr r0,fclose / close all files the process opened 2749 <1> ;; ignore error return 2750 <1> ; br .+2 / ignore error return 2751 <1> ;inc ax 2752 00003CFA FEC0 <1> inc al 2753 <1> ; inc r1 / increment file descriptor 2754 <1> ;cmp ax, 10 2755 00003CFC 3C0A <1> cmp al, 10 2756 <1> ; cmp r1,$10. / end of u.fp list? 2757 00003CFE 72F5 <1> jb short sysexit_1 2758 <1> ; blt 1b / no, go back 2759 00003D00 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 2760 <1> ; movb u.uno,r1 / yes, move dying process's number to r1 2761 00003D07 88A3[0F6C0000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 2762 <1> ; clrb p.stat-1(r1) / free the process 2763 <1> ;shl bx, 1 2764 00003D0D D0E3 <1> shl bl, 1 2765 <1> ; asl r1 / use r1 for index into the below tables 2766 00003D0F 668B8B[7E6B0000] <1> mov cx, [ebx+p.pid-2] 2767 <1> ; mov p.pid-2(r1),r3 / move dying process's name to r3 2768 00003D16 668B93[9E6B0000] <1> mov dx, [ebx+p.ppid-2] 2769 <1> ; mov p.ppid-2(r1),r4 / move its parents name to r4 2770 <1> ; xor bx, bx ; 0 2771 00003D1D 30DB <1> xor bl, bl ; 0 2772 <1> ; clr r2 2773 00003D1F 31F6 <1> xor esi, esi ; 0 2774 <1> ; clr r5 / initialize reg 2775 <1> sysexit_2: ; 1: 2776 <1> ; / find children of this dying process, 2777 <1> ; / if they are zombies, free them 2778 <1> ;add bx, 2 2779 00003D21 80C302 <1> add bl, 2 2780 <1> ; add $2,r2 / search parent process table 2781 <1> ; / for dying process's name 2782 00003D24 66398B[9E6B0000] <1> cmp [ebx+p.ppid-2], cx 2783 <1> ; cmp p.ppid-2(r2),r3 / found it? 2784 00003D2B 7513 <1> jne short sysexit_4 2785 <1> ; bne 3f / no 2786 <1> ;shr bx, 1 2787 00003D2D D0EB <1> shr bl, 1 2788 <1> ; asr r2 / yes, it is a parent 2789 00003D2F 80BB[0F6C0000]03 <1> cmp byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 2790 <1> ; cmpb p.stat-1(r2),$3 / is the child of this 2791 <1> ; / dying process a zombie 2792 00003D36 7506 <1> jne short sysexit_3 2793 <1> ; bne 2f / no 2794 00003D38 88A3[0F6C0000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 2795 <1> ; clrb p.stat-1(r2) / yes, free the child process 2796 <1> sysexit_3: ; 2: 2797 <1> ;shr bx, 1 2798 00003D3E D0E3 <1> shl bl, 1 2799 <1> ; asl r2 2800 <1> sysexit_4: ; 3: 2801 <1> ; / search the process name table 2802 <1> ; / for the dying process's parent 2803 00003D40 663993[7E6B0000] <1> cmp [ebx+p.pid-2], dx ; 17/09/2013 2804 <1> ; cmp p.pid-2(r2),r4 / found it? 2805 00003D47 7502 <1> jne short sysexit_5 2806 <1> ; bne 3f / no 2807 00003D49 89DE <1> mov esi, ebx 2808 <1> ; mov r2,r5 / yes, put index to p.pid table (parents 2809 <1> ; / process # x2) in r5 2810 <1> sysexit_5: ; 3: 2811 <1> ;cmp bx, nproc + nproc 2812 00003D4B 80FB20 <1> cmp bl, nproc + nproc 2813 <1> ; cmp r2,$nproc+nproc / has whole table been searched? 2814 00003D4E 72D1 <1> jb short sysexit_2 2815 <1> ; blt 1b / no, go back 2816 <1> ; mov r5,r1 / yes, r1 now has parents process # x2 2817 00003D50 21F6 <1> and esi, esi ; r5=r1 2818 00003D52 7431 <1> jz short sysexit_6 2819 <1> ; beq 2f / no parent has been found. 2820 <1> ; / The process just dies 2821 00003D54 66D1EE <1> shr si, 1 2822 <1> ; asr r1 / set up index to p.stat 2823 00003D57 8A86[0F6C0000] <1> mov al, [esi+p.stat-1] 2824 <1> ; movb p.stat-1(r1),r2 / move status of parent to r2 2825 00003D5D 20C0 <1> and al, al 2826 00003D5F 7424 <1> jz short sysexit_6 2827 <1> ; beq 2f / if its been freed, 2f 2828 00003D61 3C03 <1> cmp al, 3 2829 <1> ; cmp r2,$3 / is parent a zombie? 2830 00003D63 7420 <1> je short sysexit_6 2831 <1> ; beq 2f / yes, 2f 2832 <1> ; BH = 0 2833 00003D65 8A1D[F56E0000] <1> mov bl, [u.uno] 2834 <1> ; movb u.uno,r3 / move dying process's number to r3 2835 00003D6B C683[0F6C0000]03 <1> mov byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 2836 <1> ; movb $3,p.stat-1(r3) / make the process a zombie 2837 <1> ; 05/02/2014 2838 00003D72 3C01 <1> cmp al, 1 ; SRUN 2839 00003D74 740F <1> je short sysexit_6 2840 <1> ;cmp al, 2 2841 <1> ; cmp r2,$2 / is the parent waiting for 2842 <1> ; / this child to die 2843 <1> ;jne short sysexit_6 2844 <1> ; bne 2f / yes, notify parent not to wait any more 2845 <1> ; 05/02/2014 2846 <1> ; p.stat = 2 --> waiting 2847 <1> ; p.stat = 4 --> sleeping 2848 00003D76 C686[0F6C0000]01 <1> mov byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014 2849 <1> ;dec byte [esi+p.stat-1] 2850 <1> ; decb p.stat-1(r1) / awaken it by putting it (parent) 2851 00003D7D 6689F0 <1> mov ax, si ; r1 (process number in AL) 2852 <1> ; 2853 <1> ;mov ebx, runq + 4 2854 <1> ; mov $runq+4,r2 / on the runq 2855 00003D80 E845100000 <1> call putlu 2856 <1> ; jsr r0, putlu 2857 <1> sysexit_6: ; 2: 2858 <1> ; 31/08/2015 2859 <1> ; / the process dies 2860 00003D85 C605[F56E0000]00 <1> mov byte [u.uno], 0 2861 <1> ; clrb u.uno / put zero as the process number, 2862 <1> ; / so "swap" will 2863 00003D8C E86C0F0000 <1> call swap 2864 <1> ; jsr r0,swap / overwrite process with another process 2865 <1> hlt_sys: 2866 <1> ;sti ; 18/01/2014 2867 <1> hlts0: 2868 00003D91 F4 <1> hlt 2869 00003D92 EBFD <1> jmp short hlts0 2870 <1> ; 0 / and thereby kill it; halt? 2871 <1> 2872 <1> 2873 <1> syswait: ; < wait for a processs to die > 2874 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 2875 <1> ; 17/09/2015 2876 <1> ; 02/09/2015 2877 <1> ; 01/09/2015 2878 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2879 <1> ; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1) 2880 <1> ; 2881 <1> ; 'syswait' waits for a process die. 2882 <1> ; It works in following way: 2883 <1> ; 1) From the parent process number, the parent's 2884 <1> ; process name is found. The p.ppid table of parent 2885 <1> ; names is then searched for this process name. 2886 <1> ; If a match occurs, r2 contains child's process 2887 <1> ; number. The child status is checked to see if it is 2888 <1> ; a zombie, i.e; dead but not waited for (p.stat=3) 2889 <1> ; If it is, the child process is freed and it's name 2890 <1> ; is put in (u.r0). A return is then made via 'sysret'. 2891 <1> ; If the child is not a zombie, nothing happens and 2892 <1> ; the search goes on through the p.ppid table until 2893 <1> ; all processes are checked or a zombie is found. 2894 <1> ; 2) If no zombies are found, a check is made to see if 2895 <1> ; there are any children at all. If there are none, 2896 <1> ; an error return is made. If there are, the parent's 2897 <1> ; status is set to 2 (waiting for child to die), 2898 <1> ; the parent is swapped out, and a branch to 'syswait' 2899 <1> ; is made to wait on the next process. 2900 <1> ; 2901 <1> ; Calling sequence: 2902 <1> ; ? 2903 <1> ; Arguments: 2904 <1> ; - 2905 <1> ; Inputs: - 2906 <1> ; Outputs: if zombie found, it's name put in u.r0. 2907 <1> ; ............................................................... 2908 <1> ; 2909 <1> 2910 <1> ; / wait for a process to die 2911 <1> 2912 <1> syswait_0: 2913 00003D94 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 2914 <1> ; movb u.uno,r1 / put parents process number in r1 2915 00003D9B D0E3 <1> shl bl, 1 2916 <1> ;shl bx, 1 2917 <1> ; asl r1 / x2 to get index into p.pid table 2918 00003D9D 668B83[7E6B0000] <1> mov ax, [ebx+p.pid-2] 2919 <1> ; mov p.pid-2(r1),r1 / get the name of this process 2920 00003DA4 31F6 <1> xor esi, esi 2921 <1> ; clr r2 2922 00003DA6 31C9 <1> xor ecx, ecx ; 30/10/2013 2923 <1> ;xor cl, cl 2924 <1> ; clr r3 / initialize reg 3 2925 <1> syswait_1: ; 1: 2926 00003DA8 6683C602 <1> add si, 2 2927 <1> ; add $2,r2 / use r2 for index into p.ppid table 2928 <1> ; / search table of parent processes 2929 <1> ; / for this process name 2930 00003DAC 663B86[9E6B0000] <1> cmp ax, [esi+p.ppid-2] 2931 <1> ; cmp p.ppid-2(r2),r1 / r2 will contain the childs 2932 <1> ; / process number 2933 00003DB3 7534 <1> jne short syswait_3 2934 <1> ;bne 3f / branch if no match of parent process name 2935 <1> ;inc cx 2936 00003DB5 FEC1 <1> inc cl 2937 <1> ;inc r3 / yes, a match, r3 indicates number of children 2938 00003DB7 66D1EE <1> shr si, 1 2939 <1> ; asr r2 / r2/2 to get index to p.stat table 2940 <1> ; The possible states ('p.stat' values) of a process are: 2941 <1> ; 0 = free or unused 2942 <1> ; 1 = active 2943 <1> ; 2 = waiting for a child process to die 2944 <1> ; 3 = terminated, but not yet waited for (zombie). 2945 00003DBA 80BE[0F6C0000]03 <1> cmp byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014 2946 <1> ; cmpb p.stat-1(r2),$3 / is the child process a zombie? 2947 00003DC1 7523 <1> jne short syswait_2 2948 <1> ; bne 2f / no, skip it 2949 00003DC3 88BE[0F6C0000] <1> mov [esi+p.stat-1], bh ; 0 2950 <1> ; clrb p.stat-1(r2) / yes, free it 2951 00003DC9 66D1E6 <1> shl si, 1 2952 <1> ; asl r2 / r2x2 to get index into p.pid table 2953 00003DCC 0FB786[7E6B0000] <1> movzx eax, word [esi+p.pid-2] 2954 00003DD3 A3[A46E0000] <1> mov [u.r0], eax 2955 <1> ; mov p.pid-2(r2),*u.r0 2956 <1> ; / put childs process name in (u.r0) 2957 <1> ; 2958 <1> ; Retro UNIX 386 v1 modification ! (17/09/2015) 2959 <1> ; 2960 <1> ; Parent process ID -p.ppid- field (of the child process) 2961 <1> ; must be cleared in order to prevent infinitive 'syswait' 2962 <1> ; system call loop from the application/program if it calls 2963 <1> ; 'syswait' again (mistakenly) while there is not a zombie 2964 <1> ; or running child process to wait. ('forktest.s', 17/09/2015) 2965 <1> ; 2966 <1> ; Note: syswait will return with error if there is not a 2967 <1> ; zombie or running process to wait. 2968 <1> ; 2969 <1> ;sub ax, ax 2970 <1> ; 08/01/2022 2971 00003DD8 29C0 <1> sub eax, eax 2972 00003DDA 668986[9E6B0000] <1> mov [esi+p.ppid-2], ax ; 0 ; 17/09/2015 2973 00003DE1 E9E8FDFFFF <1> jmp sysret0 ; ax = 0 2974 <1> ; 2975 <1> ;jmp sysret 2976 <1> ; br sysret1 / return cause child is dead 2977 <1> syswait_2: ; 2: 2978 00003DE6 66D1E6 <1> shl si, 1 2979 <1> ; asl r2 / r2x2 to get index into p.ppid table 2980 <1> syswait_3: ; 3: 2981 00003DE9 6683FE20 <1> cmp si, nproc+nproc 2982 <1> ; cmp r2,$nproc+nproc / have all processes been checked? 2983 00003DED 72B9 <1> jb short syswait_1 2984 <1> ; blt 1b / no, continue search 2985 <1> ;and cx, cx 2986 00003DEF 20C9 <1> and cl, cl 2987 <1> ; tst r3 / one gets here if there are no children 2988 <1> ; / or children that are still active 2989 <1> ; 30/10/2013 2990 00003DF1 750B <1> jnz short syswait_4 2991 <1> ;jz error 2992 <1> ; beq error1 / there are no children, error 2993 00003DF3 890D[A46E0000] <1> mov [u.r0], ecx ; 0 2994 00003DF9 E9AEFDFFFF <1> jmp error 2995 <1> syswait_4: 2996 00003DFE 8A1D[F56E0000] <1> mov bl, [u.uno] 2997 <1> ; movb u.uno,r1 / there are children so put 2998 <1> ; / parent process number in r1 2999 00003E04 FE83[0F6C0000] <1> inc byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014 3000 <1> ; incb p.stat-1(r1) / it is waiting for 3001 <1> ; / other children to die 3002 <1> ; 04/11/2013 3003 00003E0A E8EE0E0000 <1> call swap 3004 <1> ; jsr r0,swap / swap it out, because it's waiting 3005 00003E0F EB83 <1> jmp syswait_0 3006 <1> ; br syswait / wait on next process 3007 <1> 3008 <1> sysfork: ; < create a new process > 3009 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 3010 <1> ; 18/09/2015 3011 <1> ; 04/09/2015 3012 <1> ; 02/09/2015 3013 <1> ; 01/09/2015 3014 <1> ; 28/08/2015 3015 <1> ; 14/05/2015 3016 <1> ; 10/05/2015 3017 <1> ; 09/05/2015 3018 <1> ; 06/05/2015 (Retro UNIX 386 v1 - Beginning) 3019 <1> ; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1) 3020 <1> ; 3021 <1> ; 'sysfork' creates a new process. This process is referred 3022 <1> ; to as the child process. This new process core image is 3023 <1> ; a copy of that of the caller of 'sysfork'. The only 3024 <1> ; distinction is the return location and the fact that (u.r0) 3025 <1> ; in the old process (parent) contains the process id (p.pid) 3026 <1> ; of the new process (child). This id is used by 'syswait'. 3027 <1> ; 'sysfork' works in the following manner: 3028 <1> ; 1) The process status table (p.stat) is searched to find 3029 <1> ; a process number that is unused. If none are found 3030 <1> ; an error occurs. 3031 <1> ; 2) when one is found, it becomes the child process number 3032 <1> ; and it's status (p.stat) is set to active. 3033 <1> ; 3) If the parent had a control tty, the interrupt 3034 <1> ; character in that tty buffer is cleared. 3035 <1> ; 4) The child process is put on the lowest priority run 3036 <1> ; queue via 'putlu'. 3037 <1> ; 5) A new process name is gotten from 'mpid' (actually 3038 <1> ; it is a unique number) and is put in the child's unique 3039 <1> ; identifier; process id (p.pid). 3040 <1> ; 6) The process name of the parent is then obtained and 3041 <1> ; placed in the unique identifier of the parent process 3042 <1> ; name is then put in 'u.r0'. 3043 <1> ; 7) The child process is then written out on disk by 3044 <1> ; 'wswap',i.e., the parent process is copied onto disk 3045 <1> ; and the child is born. (The child process is written 3046 <1> ; out on disk/drum with 'u.uno' being the child process 3047 <1> ; number.) 3048 <1> ; 8) The parent process number is then restored to 'u.uno'. 3049 <1> ; 9) The child process name is put in 'u.r0'. 3050 <1> ; 10) The pc on the stack sp + 18 is incremented by 2 to 3051 <1> ; create the return address for the parent process. 3052 <1> ; 11) The 'u.fp' list as then searched to see what files 3053 <1> ; the parent has opened. For each file the parent has 3054 <1> ; opened, the corresponding 'fsp' entry must be updated 3055 <1> ; to indicate that the child process also has opened 3056 <1> ; the file. A branch to 'sysret' is then made. 3057 <1> ; 3058 <1> ; Calling sequence: 3059 <1> ; from shell ? 3060 <1> ; Arguments: 3061 <1> ; - 3062 <1> ; Inputs: - 3063 <1> ; Outputs: *u.r0 - child process name 3064 <1> ; ............................................................... 3065 <1> ; 3066 <1> ; Retro UNIX 8086 v1 modification: 3067 <1> ; AX = r0 = PID (>0) (at the return of 'sysfork') 3068 <1> ; = process id of child a parent process returns 3069 <1> ; = process id of parent when a child process returns 3070 <1> ; 3071 <1> ; In original UNIX v1, sysfork is called and returns as 3072 <1> ; in following manner: (with an example: c library, fork) 3073 <1> ; 3074 <1> ; 1: 3075 <1> ; sys fork 3076 <1> ; br 1f / child process returns here 3077 <1> ; bes 2f / parent process returns here 3078 <1> ; / pid of new process in r0 3079 <1> ; rts pc 3080 <1> ; 2: / parent process condionally branches here 3081 <1> ; mov $-1,r0 / pid = -1 means error return 3082 <1> ; rts pc 3083 <1> ; 3084 <1> ; 1: / child process brances here 3085 <1> ; clr r0 / pid = 0 in child process 3086 <1> ; rts pc 3087 <1> ; 3088 <1> ; In UNIX v7x86 (386) by Robert Nordier (1999) 3089 <1> ; // pid = fork(); 3090 <1> ; // 3091 <1> ; // pid == 0 in child process; 3092 <1> ; // pid == -1 means error return 3093 <1> ; // in child, 3094 <1> ; // parents id is in par_uid if needed 3095 <1> ; 3096 <1> ; _fork: 3097 <1> ; mov $.fork,eax 3098 <1> ; int $0x30 3099 <1> ; jmp 1f 3100 <1> ; jnc 2f 3101 <1> ; jmp cerror 3102 <1> ; 1: 3103 <1> ; mov eax,_par_uid 3104 <1> ; xor eax,eax 3105 <1> ; 2: 3106 <1> ; ret 3107 <1> ; 3108 <1> ; In Retro UNIX 8086 v1, 3109 <1> ; 'sysfork' returns in following manner: 3110 <1> ; 3111 <1> ; mov ax, sys_fork 3112 <1> ; mov bx, offset @f ; routine for child 3113 <1> ; int 20h 3114 <1> ; jc error 3115 <1> ; 3116 <1> ; ; Routine for parent process here (just after 'jc') 3117 <1> ; mov word ptr [pid_of_child], ax 3118 <1> ; jmp next_routine_for_parent 3119 <1> ; 3120 <1> ; @@: ; routine for child process here 3121 <1> ; .... 3122 <1> ; NOTE: 'sysfork' returns to specified offset 3123 <1> ; for child process by using BX input. 3124 <1> ; (at first, parent process will return then 3125 <1> ; child process will return -after swapped in- 3126 <1> ; 'syswait' is needed in parent process 3127 <1> ; if return from child process will be waited for.) 3128 <1> ; 3129 <1> 3130 <1> ; / create a new process 3131 <1> ; EBX = return address for child process 3132 <1> ; (Retro UNIX 8086 v1 modification !) 3133 00003E11 31F6 <1> xor esi, esi 3134 <1> ; clr r1 3135 <1> sysfork_1: ; 1: / search p.stat table for unused process number 3136 00003E13 46 <1> inc esi 3137 <1> ; inc r1 3138 00003E14 80BE[0F6C0000]00 <1> cmp byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014 3139 <1> ; tstb p.stat-1(r1) / is process active, unused, dead 3140 00003E1B 760B <1> jna short sysfork_2 3141 <1> ; beq 1f / it's unused so branch 3142 00003E1D 6683FE10 <1> cmp si, nproc 3143 <1> ; cmp r1,$nproc / all processes checked 3144 00003E21 72F0 <1> jb short sysfork_1 3145 <1> ; blt 1b / no, branch back 3146 <1> ; 3147 <1> ; Retro UNIX 8086 v1. modification: 3148 <1> ; Parent process returns from 'sysfork' to address 3149 <1> ; which is just after 'sysfork' system call in parent 3150 <1> ; process. Child process returns to address which is put 3151 <1> ; in BX register by parent process for 'sysfork'. 3152 <1> ; 3153 <1> ;add $2,18.(sp) / add 2 to pc when trap occured, points 3154 <1> ; / to old process return 3155 <1> ; br error1 / no room for a new process 3156 <1> sysfork_0: 3157 00003E23 E984FDFFFF <1> jmp error 3158 <1> sysfork_2: ; 1: 3159 00003E28 E83BF0FFFF <1> call allocate_page 3160 <1> ;jc error 3161 <1> ; 08/01/2022 3162 00003E2D 72F4 <1> jc short sysfork_0 3163 <1> 3164 00003E2F 50 <1> push eax ; UPAGE (user structure page) address 3165 <1> ; Retro UNIX 386 v1 modification! 3166 00003E30 E82CF2FFFF <1> call duplicate_page_dir 3167 <1> ; EAX = New page directory 3168 00003E35 7308 <1> jnc short sysfork_3 3169 00003E37 58 <1> pop eax ; UPAGE (user structure page) address 3170 00003E38 E8F3F1FFFF <1> call deallocate_page 3171 <1> ;jmp error 3172 <1> ; 08/01/2022 3173 00003E3D EBE4 <1> jmp short sysfork_0 ; error 3174 <1> sysfork_3: 3175 <1> ; Retro UNIX 386 v1 modification ! 3176 00003E3F 56 <1> push esi 3177 00003E40 E82F0F0000 <1> call wswap ; save current user (u) structure, user registers 3178 <1> ; and interrupt return components (for IRET) 3179 00003E45 8705[046F0000] <1> xchg eax, [u.pgdir] ; page directory of the child process 3180 00003E4B A3[086F0000] <1> mov [u.ppgdir], eax ; page directory of the parent process 3181 00003E50 5E <1> pop esi 3182 00003E51 58 <1> pop eax ; UPAGE (user structure page) address 3183 <1> ; [u.usp] = esp 3184 00003E52 89F7 <1> mov edi, esi 3185 <1> ;shl di, 2 3186 <1> ; 08/01/2022 3187 00003E54 C1E702 <1> shl edi, 2 3188 00003E57 8987[1C6C0000] <1> mov [edi+p.upage-4], eax ; memory page for 'user' struct 3189 00003E5D A3[006F0000] <1> mov [u.upage], eax ; memory page for 'user' struct (child) 3190 <1> ; 28/08/2015 3191 00003E62 0FB605[F56E0000] <1> movzx eax, byte [u.uno] ; parent process number 3192 <1> ; movb u.uno,-(sp) / save parent process number 3193 00003E69 89C7 <1> mov edi, eax 3194 00003E6B 50 <1> push eax ; ** 3195 00003E6C 8A87[DF6B0000] <1> mov al, [edi+p.ttyc-1] ; console tty (parent) 3196 <1> ; 18/09/2015 3197 <1> ;mov [esi+p.ttyc-1], al ; set child's console tty 3198 <1> ;mov [esi+p.waitc-1], ah ; 0 ; reset child's wait channel 3199 00003E72 668986[DF6B0000] <1> mov [esi+p.ttyc-1], ax ; al - set child's console tty 3200 <1> ; ah - reset child's wait channel 3201 00003E79 89F0 <1> mov eax, esi 3202 00003E7B A2[F56E0000] <1> mov [u.uno], al ; child process number 3203 <1> ;movb r1,u.uno / set child process number to r1 3204 00003E80 FE86[0F6C0000] <1> inc byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014 3205 <1> ; incb p.stat-1(r1) / set p.stat entry for child 3206 <1> ; / process to active status 3207 <1> ; mov u.ttyp,r2 / put pointer to parent process' 3208 <1> ; / control tty buffer in r2 3209 <1> ; beq 2f / branch, if no such tty assigned 3210 <1> ; clrb 6(r2) / clear interrupt character in tty buffer 3211 <1> ; 2: 3212 00003E86 53 <1> push ebx ; * return address for the child process 3213 <1> ; * Retro UNIX 8086 v1 feature only ! 3214 <1> ; (Retro UNIX 8086 v1 modification!) 3215 <1> ; mov $runq+4,r2 3216 00003E87 E83E0F0000 <1> call putlu 3217 <1> ; jsr r0,putlu / put child process on lowest priority 3218 <1> ; / run queue 3219 <1> ; 08/01/2022 3220 00003E8C D1E6 <1> shl esi, 1 3221 <1> ;shl si, 1 3222 <1> ; asl r1 / multiply r1 by 2 to get index 3223 <1> ; / into p.pid table 3224 00003E8E 66FF05[8A6E0000] <1> inc word [mpid] 3225 <1> ; inc mpid / increment m.pid; get a new process name 3226 00003E95 66A1[8A6E0000] <1> mov ax, [mpid] 3227 00003E9B 668986[7E6B0000] <1> mov [esi+p.pid-2], ax 3228 <1> ;mov mpid,p.pid-2(r1) / put new process name 3229 <1> ; / in child process' name slot 3230 00003EA2 5A <1> pop edx ; * return address for the child process 3231 <1> ; * Retro UNIX 8086 v1 feature only ! 3232 00003EA3 5B <1> pop ebx ; ** 3233 <1> ;mov ebx, [esp] ; ** parent process number 3234 <1> ; movb (sp),r2 / put parent process number in r2 3235 <1> ; 08/01/2022 3236 00003EA4 D1E3 <1> shl ebx, 1 3237 <1> ;shl bx, 1 3238 <1> ; asl r2 / multiply by 2 to get index into below tables 3239 <1> ;movzx eax, word [ebx+p.pid-2] 3240 00003EA6 668B83[7E6B0000] <1> mov ax, [ebx+p.pid-2] 3241 <1> ; mov p.pid-2(r2),r2 / get process name of parent 3242 <1> ; / process 3243 00003EAD 668986[9E6B0000] <1> mov [esi+p.ppid-2], ax 3244 <1> ; mov r2,p.ppid-2(r1) / put parent process name 3245 <1> ; / in parent process slot for child 3246 00003EB4 A3[A46E0000] <1> mov [u.r0], eax 3247 <1> ; mov r2,*u.r0 / put parent process name on stack 3248 <1> ; / at location where r0 was saved 3249 00003EB9 8B2D[9C6E0000] <1> mov ebp, [u.sp] ; points to return address (EIP for IRET) 3250 00003EBF 895500 <1> mov [ebp], edx ; *, CS:EIP -> EIP 3251 <1> ; * return address for the child process 3252 <1> ; mov $sysret1,-(sp) / 3253 <1> ; mov sp,u.usp / contents of sp at the time when 3254 <1> ; / user is swapped out 3255 <1> ; mov $sstack,sp / point sp to swapping stack space 3256 <1> ; 04/09/2015 - 01/09/2015 3257 <1> ; [u.usp] = esp 3258 00003EC2 68[CC3B0000] <1> push sysret ; *** 3259 00003EC7 8925[A06E0000] <1> mov [u.usp], esp ; points to 'sysret' address (***) 3260 <1> ; (for child process) 3261 00003ECD 31C0 <1> xor eax, eax 3262 00003ECF 66A3[DA6E0000] <1> mov [u.ttyp], ax ; 0 3263 <1> ; 3264 00003ED5 E89A0E0000 <1> call wswap ; Retro UNIX 8086 v1 modification ! 3265 <1> ;jsr r0,wswap / put child process out on drum 3266 <1> ;jsr r0,unpack / unpack user stack 3267 <1> ;mov u.usp,sp / restore user stack pointer 3268 <1> ; tst (sp)+ / bump stack pointer 3269 <1> ; Retro UNIX 386 v1 modification ! 3270 00003EDA 58 <1> pop eax ; *** 3271 <1> ; 08/01/2022 3272 00003EDB D1E3 <1> shl ebx, 1 3273 <1> ;shl bx, 1 3274 00003EDD 8B83[1C6C0000] <1> mov eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015 3275 00003EE3 E8B50E0000 <1> call rswap ; restore parent process 'u' structure, 3276 <1> ; registers and return address (for IRET) 3277 <1> ;movb (sp)+,u.uno / put parent process number in u.uno 3278 00003EE8 0FB705[8A6E0000] <1> movzx eax, word [mpid] 3279 00003EEF A3[A46E0000] <1> mov [u.r0], eax 3280 <1> ; mov mpid,*u.r0 / put child process name on stack 3281 <1> ; / where r0 was saved 3282 <1> ; add $2,18.(sp) / add 2 to pc on stack; gives parent 3283 <1> ; / process return 3284 <1> ;xor ebx, ebx 3285 00003EF4 31F6 <1> xor esi, esi 3286 <1> ;clr r1 3287 <1> sysfork_4: ; 1: / search u.fp list to find the files 3288 <1> ; / opened by the parent process 3289 <1> ; 08/01/2022 3290 <1> ; 01/09/2015 3291 00003EF6 30FF <1> xor bh, bh 3292 00003EF8 8A9E[AE6E0000] <1> mov bl, [esi+u.fp] 3293 <1> ; 08/01/2022 3294 <1> ;mov al, [esi+u.fp] 3295 <1> ; movb u.fp(r1),r2 / get an open file for this process 3296 00003EFE 08DB <1> or bl, bl 3297 <1> ; 08/01/2022 3298 <1> ;or al, al 3299 00003F00 7409 <1> jz short sysfork_5 3300 <1> ; beq 2f / file has not been opened by parent, 3301 <1> ; / so branch 3302 <1> ;mov ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes 3303 <1> ; 08/01/2022 3304 <1> ;mov ah, 16 ; Retro UNIX 386 v2 fsp structure size = 16 bytes 3305 <1> ;mul ah 3306 <1> ;;movzx ebx, ax 3307 <1> ;mov bx, ax 3308 <1> ;mov ebx, eax ; 08/01/2022 3309 <1> ;shl bx, 3 3310 <1> ; asl r2 / multiply by 8 3311 <1> ; asl r2 / to get index into fsp table 3312 <1> ; asl r2 3313 <1> ; 08/01/2022 3314 00003F02 C1E304 <1> shl ebx, 4 ; multiply by 16 3315 <1> ; 08/01/2022 3316 00003F05 FE83[366B0000] <1> inc byte [ebx+fsp-10] ; Retro UNIX 386 v2 fs fsp structure 3317 <1> ;inc byte [ebx+fsp-2] 3318 <1> ; incb fsp-2(r2) / increment number of processes 3319 <1> ; / using file, because child will now be 3320 <1> ; / using this file 3321 <1> sysfork_5: ; 2: 3322 00003F0B 46 <1> inc esi 3323 <1> ; inc r1 / get next open file 3324 00003F0C 6683FE0A <1> cmp si, 10 3325 <1> ; cmp r1,$10. / 10. files is the maximum number which 3326 <1> ; / can be opened 3327 00003F10 72E4 <1> jb short sysfork_4 3328 <1> ; blt 1b / check next entry 3329 00003F12 E9B5FCFFFF <1> jmp sysret 3330 <1> ; br sysret1 3331 <1> 3332 <1> sysread: ; < read from file > 3333 <1> ; 24/12/2021 3334 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 3335 <1> ; 27/03/2020 3336 <1> ; 26/03/2020 - Retro UNIX 386 v2 3337 <1> ; 13/05/2015 3338 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3339 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 3340 <1> ; 3341 <1> ; 'sysread' is given a buffer to read into and the number of 3342 <1> ; characters to be read. If finds the file from the file 3343 <1> ; descriptor located in *u.r0 (r0). This file descriptor 3344 <1> ; is returned from a successful open call (sysopen). 3345 <1> ; The i-number of file is obtained via 'rw1' and the data 3346 <1> ; is read into core via 'readi'. 3347 <1> ; 3348 <1> ; Calling sequence: 3349 <1> ; sysread; buffer; nchars 3350 <1> ; Arguments: 3351 <1> ; buffer - location of contiguous bytes where 3352 <1> ; input will be placed. 3353 <1> ; nchars - number of bytes or characters to be read. 3354 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 3355 <1> ; Outputs: *u.r0 - number of bytes read. 3356 <1> ; ............................................................... 3357 <1> ; 3358 <1> ; Retro UNIX 8086 v1 modification: 3359 <1> ; 'sysread' system call has three arguments; so, 3360 <1> ; * 1st argument, file descriptor is in BX register 3361 <1> ; * 2nd argument, buffer address/offset in CX register 3362 <1> ; * 3rd argument, number of bytes is in DX register 3363 <1> ; 3364 <1> ; AX register (will be restored via 'u.r0') will return 3365 <1> ; to the user with number of bytes read. 3366 <1> ; 3367 <1> 3368 <1> ; temporary ! - 26/12/2021 3369 00003F17 C605[6F3F0000]52 <1> mov byte [srwtype], 'R' 3370 <1> 3371 00003F1E E859000000 <1> call rw1 3372 <1> ;jc error ; 13/05/2015, ax < 1 3373 <1> ; ; jsr r0,rw1 / get i-number of file to be read into r1 3374 <1> ; 04/12/2021 3375 00003F23 7221 <1> jc short sysread_err 3376 00003F25 7549 <1> jnz short rw3 ; error ! (permission denied) 3377 <1> ; ; read a file while it is open for write! 3378 <1> 3379 <1> ; eax = inode number 3380 <1> 3381 <1> ; 04/12/2021 3382 <1> ;((Retro Unix 386 v1 code)) (old code below) 3383 <1> ;test ah, 80h 3384 <1> ; ; tst r1 / negative i-number? 3385 <1> ;;jnz error 3386 <1> ;; ; ble error1 / yes, error 1 to read 3387 <1> ;; ; / it should be positive 3388 <1> ;; 04/12/2021 3389 <1> ;jnz short sysread_err 3390 <1> 3391 <1> ; temporary - 26/12/2021 3392 00003F27 53 <1> push ebx 3393 00003F28 50 <1> push eax 3394 00003F29 B058 <1> mov al, 'X' 3395 00003F2B B44E <1> mov ah, 4Eh 3396 00003F2D 8B1D[E1400000] <1> mov ebx, [openaddr] 3397 00003F33 8005[E1400000]02 <1> add byte [openaddr], 2 3398 00003F3A 668903 <1> mov word [ebx], ax 3399 00003F3D 58 <1> pop eax 3400 00003F3E 5B <1> pop ebx 3401 <1> 3402 00003F3F E87B160000 <1> call readi 3403 <1> ; jsr r0,readi / read data into core 3404 00003F44 EB1A <1> jmp short rw0 3405 <1> ; br 1f 3406 <1> sysread_err: 3407 <1> syswrite_err: 3408 <1> ; 04/12/2021 3409 00003F46 E961FCFFFF <1> jmp error 3410 <1> 3411 <1> syswrite: ; < write to file > 3412 <1> ; 24/12/2021 3413 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 3414 <1> ; 27/03/2020 3415 <1> ; 26/03/2020 - Retro UNIX 386 v2 3416 <1> ; 13/05/2015 3417 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3418 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 3419 <1> ; 3420 <1> ; 'syswrite' is given a buffer to write onto an output file 3421 <1> ; and the number of characters to write. If finds the file 3422 <1> ; from the file descriptor located in *u.r0 (r0). This file 3423 <1> ; descriptor is returned from a successful open or create call 3424 <1> ; (sysopen or syscreat). The i-number of file is obtained via 3425 <1> ; 'rw1' and buffer is written on the output file via 'write'. 3426 <1> ; 3427 <1> ; Calling sequence: 3428 <1> ; syswrite; buffer; nchars 3429 <1> ; Arguments: 3430 <1> ; buffer - location of contiguous bytes to be writtten. 3431 <1> ; nchars - number of characters to be written. 3432 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 3433 <1> ; Outputs: *u.r0 - number of bytes written. 3434 <1> ; ............................................................... 3435 <1> ; 3436 <1> ; Retro UNIX 8086 v1 modification: 3437 <1> ; 'syswrite' system call has three arguments; so, 3438 <1> ; * 1st argument, file descriptor is in BX register 3439 <1> ; * 2nd argument, buffer address/offset in CX register 3440 <1> ; * 3rd argument, number of bytes is in DX register 3441 <1> ; 3442 <1> ; AX register (will be restored via 'u.r0') will return 3443 <1> ; to the user with number of bytes written. 3444 <1> ; 3445 <1> 3446 <1> ; temporary ! - 26/12/2021 3447 00003F4B C605[6F3F0000]56 <1> mov byte [srwtype], 'V' 3448 <1> 3449 00003F52 E825000000 <1> call rw1 3450 <1> ;jc error ; 13/05/2015, ax < 1 3451 <1> ; ; jsr r0,rw1 / get i-number in r1 of file to write 3452 <1> ; 04/12/2021 3453 00003F57 72ED <1> jc short syswrite_err 3454 00003F59 7415 <1> jz short rw3 ; error ! (permission denied) 3455 <1> ; write to a file while it is open for read 3456 <1> ; eax = inode number 3457 <1> 3458 <1> ; 04/12/2021 3459 <1> ;((Retro Unix 386 v1 code)) (old code below) 3460 <1> ;test ah, 80h 3461 <1> ; ; tst r1 / positive i-number ? 3462 <1> ;jz short rw3 ; 13/05/2015 3463 <1> ;;jz error 3464 <1> ; ; bge error1 / yes, error 1 3465 <1> ; ; / negative i-number means write 3466 <1> ;neg ax 3467 <1> ; ; neg r1 / make it positive 3468 <1> 3469 00003F5B E870180000 <1> call writei 3470 <1> ; jsr r0,writei / write data 3471 <1> rw0: ; 1: 3472 00003F60 A1[D06E0000] <1> mov eax, [u.nread] 3473 00003F65 A3[A46E0000] <1> mov [u.r0], eax 3474 <1> ; mov u.nread,*u.r0 / put no. of bytes transferred 3475 <1> ; / into (u.r0) 3476 00003F6A E95DFCFFFF <1> jmp sysret 3477 <1> ; br sysret1 3478 <1> 3479 <1> ; temporary - 26/12/2021 3480 00003F6F 00 <1> srwtype: db 0 3481 <1> 3482 <1> rw3: 3483 <1> ; temporary - 26/12/2021 3484 <1> ;mov dword [0B8000h], 4E354E35h 3485 <1> ;mov ecx, 0FFFFh 3486 <1> ;aboveysx: 3487 <1> ;dec edx 3488 <1> ;inc edx 3489 <1> ;loop aboveysx 3490 <1> ;stc 3491 <1> ;rw4: 3492 <1> ; 13/05/2015 3493 00003F70 C705[186F0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 3493 00003F78 0000 <1> 3494 <1> ;stc 3495 <1> ;retn 3496 <1> ; 24/12/2021 - Retro UNIX 386 v1.2 3497 00003F7A EBCA <1> jmp short syswrite_err 3498 <1> 3499 <1> rw1: 3500 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3501 <1> ; 27/03/2020 3502 <1> ; 26/03/2020 - Retro UNIX 386 v2 3503 <1> ; 14/05/2015 3504 <1> ; 13/05/2015 3505 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3506 <1> ; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1) 3507 <1> ; System call registers: bx, cx, dx (through 'sysenter') 3508 <1> ; 3509 <1> ;mov [u.base], ecx ; buffer address/offset 3510 <1> ;(in the user's virtual memory space) 3511 <1> ;mov [u.count], edx 3512 <1> ; jsr r0,arg; u.base / get buffer pointer 3513 <1> ; jsr r0,arg; u.count / get no. of characters 3514 <1> ;;mov eax, ebx ; file descriptor 3515 <1> ; mov *u.r0,r1 / put file descriptor 3516 <1> ; / (index to u.fp table) in r1 3517 <1> ; 13/05/2015 3518 00003F7C C705[A46E0000]0000- <1> mov dword [u.r0], 0 ; r/w transfer count = 0 (reset) 3518 00003F84 0000 <1> 3519 <1> ; 3520 <1> ;; call getf 3521 <1> ; ebx = File descriptor 3522 00003F86 E8EA080000 <1> call getf1 ; calling point in 'getf' from 'rw1' 3523 <1> ; jsr r0,getf / get i-number of the file in r1 3524 <1> ; AX = I-number of the file ; negative i-number means write 3525 <1> 3526 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3527 <1> ; 26/03/2020 - Retro UNIX 386 v2 3528 <1> ; BL = open mode & status flag (0 = read, 1 = write) 3529 <1> ; eax = inode number (ax) 3530 <1> ; 27/03/2020 3531 <1> ; [cdev] = logical drive number 3532 <1> 3533 <1> ; 13/05/2015 3534 00003F8B 6683F801 <1> cmp ax, 1 3535 00003F8F 7237 <1> jb short rw2 3536 <1> ; 3537 00003F91 890D[C86E0000] <1> mov [u.base], ecx ; buffer address/offset 3538 <1> ;(in the user's virtual memory space) 3539 00003F97 8915[CC6E0000] <1> mov [u.count], edx 3540 <1> ; 14/05/2015 3541 00003F9D C705[186F0000]0000- <1> mov dword [u.error], 0 ; reset the last error code 3541 00003FA5 0000 <1> 3542 <1> 3543 <1> 3544 <1> ; temporary - 27/12/2021 3545 00003FA7 08DB <1> or bl, bl 3546 00003FA9 7519 <1> jnz short ghi 3547 00003FAB 50 <1> push eax 3548 00003FAC B44E <1> mov ah, 4Eh 3549 00003FAE B052 <1> mov al, 'R' 3550 00003FB0 66A304800B00 <1> mov word [0B8004h], ax 3551 00003FB6 A0[E5400000] <1> mov al, [bytype] 3552 00003FBB 0430 <1> add al, '0' 3553 00003FBD 66A306800B00 <1> mov word [0B8006h], ax 3554 00003FC3 58 <1> pop eax 3555 <1> ghi: 3556 <1> 3557 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3558 <1> ; 27/03/2020 - Retro UNIX 386 v2 3559 00003FC4 80E301 <1> and bl, 1 3560 <1> ; zf = 0 -> open for write 3561 <1> ; zf = 1 -> open for read 3562 <1> ; 3563 00003FC7 C3 <1> retn 3564 <1> ; rts r0 3565 <1> rw2: 3566 <1> ; temporary - 25/12/2021 3567 00003FC8 C70500800B00344E34- <1> mov dword [0B8000h], 4E344E34h 3567 00003FD1 4E <1> 3568 00003FD2 B9FFFF0000 <1> mov ecx, 0FFFFh 3569 <1> abovexsx: 3570 00003FD7 4A <1> dec edx 3571 00003FD8 42 <1> inc edx 3572 00003FD9 E2FC <1> loop abovexsx 3573 00003FDB F9 <1> stc 3574 <1> ; 13/05/2015 3575 00003FDC C705[186F0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 3575 00003FE4 0000 <1> 3576 00003FE6 C3 <1> retn 3577 <1> 3578 <1> ; 08/01/2022 3579 <1> ; 02/01/2022 3580 <1> ; 01/01/2022 3581 <1> ; 27/12/2021 3582 <1> ; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code 3583 <1> sysopen: ; 3584 <1> ; 04/12/2021 3585 <1> ; 07/08/2020 (Retro UNIX 386 v2) 3586 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3587 <1> ; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1) 3588 <1> ; 3589 <1> ; 'sysopen' opens a file in following manner: 3590 <1> ; 1) The second argument in a sysopen says whether to 3591 <1> ; open the file ro read (0) or write (>0). 3592 <1> ; 2) I-node of the particular file is obtained via 'namei'. 3593 <1> ; 3) The file is opened by 'iopen'. 3594 <1> ; 4) Next housekeeping is performed on the fsp table 3595 <1> ; and the user's open file list - u.fp. 3596 <1> ; a) u.fp and fsp are scanned for the next available slot. 3597 <1> ; b) An entry for the file is created in the fsp table. 3598 <1> ; c) The number of this entry is put on u.fp list. 3599 <1> ; d) The file descriptor index to u.fp list is pointed 3600 <1> ; to by u.r0. 3601 <1> ; 3602 <1> ; Calling sequence: 3603 <1> ; sysopen; name; mode 3604 <1> ; Arguments: 3605 <1> ; name - file name or path name 3606 <1> ; mode - 0 to open for reading 3607 <1> ; 1 to open for writing 3608 <1> ; Inputs: (arguments) 3609 <1> ; Outputs: *u.r0 - index to u.fp list (the file descriptor) 3610 <1> ; is put into r0's location on the stack. 3611 <1> ; ............................................................... 3612 <1> ; 3613 <1> ; Retro UNIX 8086 v1 modification: 3614 <1> ; 'sysopen' system call has two arguments; so, 3615 <1> ; * 1st argument, name is pointed to by BX register 3616 <1> ; * 2nd argument, mode is in CX register 3617 <1> ; 3618 <1> ; AX register (will be restored via 'u.r0') will return 3619 <1> ; to the user with the file descriptor/number 3620 <1> ; (index to u.fp list). 3621 <1> ; 3622 <1> ;call arg2 3623 <1> ; * name - 'u.namep' points to address of file/path name 3624 <1> ; in the user's program segment ('u.segmnt') 3625 <1> ; with offset in BX register (as sysopen argument 1). 3626 <1> ; * mode - sysopen argument 2 is in CX register 3627 <1> ; which is on top of stack. 3628 <1> ; 3629 <1> ; jsr r0,arg2 / get sys args into u.namep and on stack 3630 <1> ; 3631 <1> ; system call registers: ebx, ecx (through 'sysenter') 3632 <1> 3633 00003FE7 891D[C06E0000] <1> mov [u.namep], ebx 3634 00003FED 51 <1> push ecx ; * ; 04/12/2021 (cx -> ecx) 3635 00003FEE E8EF080000 <1> call namei 3636 <1> ; jsr r0,namei / i-number of file in r1 3637 <1> ;and ax, ax 3638 <1> ;jz error ; File not found 3639 00003FF3 722B <1> jc short fnotfound ; 14/05/2015 3640 <1> ;jc error ; 27/05/2013 3641 <1> ; br error2 / file not found 3642 <1> ;pop edx ; * ; mode ; 04/12/2021 3643 <1> ;push edx ; * 3644 <1> ;;or dx, dx 3645 <1> ;or dl, dl 3646 <1> ; ; tst (sp) / is mode = 0 (2nd arg of call; 3647 <1> ; ; / 0 means, open for read) 3648 <1> ;;jz short sysopen_0 3649 <1> ;; ; beq 1f / yes, leave i-number positive 3650 <1> 3651 00003FF5 8B1424 <1> mov edx, [esp] ; * 3652 <1> ; edx = open mode (0 or 1) 3653 <1> 3654 <1> ;syscreat_0: ;op0: ; 27/12/2015 3655 <1> ; neg ax 3656 <1> ; ; neg r1 / open for writing so make i-number negative 3657 <1> 3658 <1> sysopen_0: ;1: 3659 00003FF8 E89E1B0000 <1> call iopen 3660 <1> ; jsr r0,iopen / open file whose i-number is in r1 3661 00003FFD 5A <1> pop edx ; * ; mode ; 04/12/2021 3662 <1> ;;and dx, dx 3663 <1> ;and dl, dl 3664 <1> ; ; tst (sp)+ / pop the stack and test the mode 3665 <1> ;jz short sysopen_2 3666 <1> ; ; beq op1 / is open for read op1 3667 <1> ;sysopen_1: ;op0: 3668 <1> ;neg ax 3669 <1> ; ; neg r1 3670 <1> ; ;/ make i-number positive if open for writing [???] 3671 <1> 3672 <1> ;; NOTE: iopen always make i-number positive. 3673 <1> ;; Here i-number becomes negative again. [22/05/2013] 3674 <1> sysopen_1: ; 04/12/2021 3675 <1> sysopen_2: ;op1: 3676 00003FFE 31F6 <1> xor esi, esi 3677 <1> ; clr r2 / clear registers 3678 00004000 31DB <1> xor ebx, ebx 3679 <1> ; clr r3 3680 <1> sysopen_3: ;1: / scan the list of entries in fsp table 3681 00004002 389E[AE6E0000] <1> cmp [esi+u.fp], bl ; 0 3682 <1> ; tstb u.fp(r2) / test the entry in the u.fp list 3683 00004008 7625 <1> jna short sysopen_4_temp ; temporary - 26/12/2021 3684 <1> ;jna short sysopen_4 3685 <1> ; beq 1f / if byte in list is 0 branch 3686 0000400A 46 <1> inc esi 3687 <1> ; inc r2 / bump r2 so next byte can be checked 3688 <1> ; 02/01/2022 3689 <1> ;cmp si, OPENFILES ; 04/12/2021 3690 0000400B 6683FE0A <1> cmp si, 10 3691 <1> ; cmp r2,$10. / reached end of list? 3692 0000400F 72F1 <1> jb short sysopen_3 3693 <1> ; blt 1b / no, go back 3694 <1> toomanyf: 3695 <1> ; 14/05/2015 3696 00004011 C705[186F0000]0D00- <1> mov dword [u.error], ERR_TOO_MANY_FILES ; too many open files ! 3696 00004019 0000 <1> 3697 0000401B E98CFBFFFF <1> jmp error 3698 <1> ; br error2 / yes, error (no files open) 3699 <1> fnotfound: 3700 <1> ; 14/05/2015 3701 00004020 C705[186F0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; file not found ! 3701 00004028 0000 <1> 3702 0000402A E97DFBFFFF <1> jmp error 3703 <1> 3704 <1> ; temporary - 26/12/2021 3705 <1> sysopen_4_temp: 3706 0000402F 89F3 <1> mov ebx, esi 3707 00004031 881D[E5400000] <1> mov [bytype], bl 3708 00004037 31DB <1> xor ebx, ebx 3709 <1> 3710 <1> sysopen_4: ; 1: 3711 00004039 6683BB[406B0000]00 <1> cmp word [ebx+fsp], 0 3712 <1> ; tst fsp(r3) / scan fsp entries 3713 00004041 760D <1> jna short sysopen_5 3714 <1> ; beq 1f / if 0 branch 3715 <1> ;; 14/05/2015 - Retro UNIX 386 v1 modification ! 3716 <1> ;add bx, 10 ; fsp structure size = 10 bytes/entry 3717 <1> ; add $8.,r3 / add 8 to r3 3718 <1> ; / to bump it to next entry mfsp table 3719 <1> ; 01/01/2022 3720 <1> ; 07/08/2020 - Retro UNIX 386 v2 3721 00004043 6683C310 <1> add bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2 3722 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 3723 <1> ;add bx, fp.size 3724 <1> 3725 <1> ; 22/11/2021 3726 <1> ;cmp bx, NFILES*fp.size ; NFILES*16 3727 <1> ; 02/01/2022 3728 00004047 6681FB2003 <1> cmp bx, nfiles*16 3729 <1> ; 01/01/2022 3730 <1> ;cmp bx, NFILES*16 ; NFILES*fp.size 3731 <1> ;;cmp bx, nfiles*10 3732 <1> ; cmp r3,$[nfiles*8.] / done scanning 3733 0000404C 72EB <1> jb short sysopen_4 3734 <1> ; blt 1b / no, back 3735 <1> ;jmp error 3736 <1> ; ; br error2 / yes, error 3737 <1> ; 04/12/2021 3738 <1> ; 07/08/2020 3739 0000404E EBC1 <1> jmp short toomanyf 3740 <1> 3741 <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table 3742 00004050 668983[406B0000] <1> mov [ebx+fsp], ax 3743 <1> ; mov r1,fsp(r3) / put i-number of open file 3744 <1> ; / into next available entry in fsp table, 3745 <1> ;mov di, [cdev] ; word ? byte ? 3746 <1> ;mov [ebx+fsp+2], di ; device number 3747 <1> ; ; mov cdev,fsp+2(r3) / put # of device in next word 3748 <1> 3749 <1> ; temporary - 01/01/2022 3750 00004057 53 <1> push ebx 3751 00004058 B44E <1> mov ah, 4Eh 3752 0000405A B057 <1> mov al, 'W' 3753 0000405C 08D2 <1> or dl, dl 3754 0000405E 7502 <1> jnz short tyu 3755 00004060 B052 <1> mov al, 'R' 3756 <1> tyu: 3757 00004062 8B1D[E1400000] <1> mov ebx, [openaddr] 3758 00004068 8005[E1400000]02 <1> add byte [openaddr], 2 3759 0000406F 668903 <1> mov word [ebx], ax 3760 00004072 8B1D[E1400000] <1> mov ebx, [openaddr] 3761 00004078 8005[E1400000]02 <1> add byte [openaddr], 2 3762 0000407F A0[E5400000] <1> mov al, [bytype] 3763 00004084 0430 <1> add al, '0' 3764 00004086 668903 <1> mov word [ebx], ax 3765 00004089 8B1C24 <1> mov ebx, [esp] 3766 0000408C C1EB04 <1> shr ebx, 4 3767 0000408F 88D8 <1> mov al, bl 3768 00004091 0430 <1> add al, '0' 3769 00004093 8B1D[E1400000] <1> mov ebx, [openaddr] 3770 00004099 8005[E1400000]02 <1> add byte [openaddr], 2 3771 000040A0 668903 <1> mov [ebx], ax 3772 000040A3 51 <1> push ecx 3773 000040A4 B9FFFFFF00 <1> mov ecx, 0FFFFFFh 3774 <1> gjl: 3775 000040A9 48 <1> dec eax 3776 000040AA 40 <1> inc eax 3777 000040AB E2FC <1> loop gjl 3778 000040AD 59 <1> pop ecx 3779 000040AE 5B <1> pop ebx 3780 <1> 3781 <1> ; 04/12/2021 3782 000040AF A0[856E0000] <1> mov al, [cdev] 3783 000040B4 88D4 <1> mov ah, dl ; open mode, 0 = read, 1 = write 3784 000040B6 668983[446B0000] <1> mov [ebx+fsp+4], ax ; device number & open mode 3785 <1> 3786 <1> ;xor edi, edi 3787 <1> ;mov [ebx+fsp+4], edi ; offset pointer (0) 3788 <1> ; ; clr fsp+4(r3) 3789 <1> ;mov [ebx+fsp+8], di ; open count (0), deleted flag (0) 3790 <1> ; ; clr fsp+6(r3) / clear the next two words 3791 <1> 3792 <1> ; 04/12/2021 3793 000040BD 31C0 <1> xor eax, eax 3794 000040BF 8983[486B0000] <1> mov [ebx+fsp+8], eax ; offset pointer = 0 3795 <1> ;inc word [ebx+fsp+6] 3796 000040C5 FE83[466B0000] <1> inc byte [ebx+fsp+6] ; open count = open count + 1 3797 <1> 3798 <1> ;mov eax, ebx 3799 <1> ;mov bl, 10 3800 <1> ;div bl 3801 <1> ; ; asr r3 3802 <1> ; ; asr r3 / divide by 8 3803 <1> ; ; asr r3 ; / to get number of the fsp entry-1 3804 <1> ;inc al 3805 <1> ; ; inc r3 / add 1 to get fsp entry number 3806 <1> ;mov [esi+u.fp], al 3807 <1> ; ; movb r3,u.fp(r2) / move entry number into 3808 <1> ; / next available slot in u.fp list 3809 <1> ; 04/12/2021 3810 000040CB C1EB04 <1> shr ebx, 4 ; / 16 3811 <1> ;shr bx, 4 ; bx = fsp entry number (index) 3812 <1> ; bx <= 49 for current runix 386 version 3813 000040CE FEC3 <1> inc bl ; bl = 1 to 50 3814 000040D0 889E[AE6E0000] <1> mov [esi+u.fp], bl 3815 <1> 3816 000040D6 8935[A46E0000] <1> mov [u.r0], esi 3817 <1> ; mov r2,*u.r0 / move index to u.fp list 3818 <1> ; / into r0 loc on stack 3819 000040DC E9EBFAFFFF <1> jmp sysret 3820 <1> ; br sysret2 3821 <1> 3822 <1> ; temporary - 01/01/2022 3823 000040E1 00800B00 <1> openaddr: dd 0B8000h 3824 000040E5 00 <1> bytype: db 0 3825 <1> 3826 <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 3827 <1> ; 3828 <1> ; 15 7 0 3829 <1> ; 1 |-------------------------------------------| 3830 <1> ; | i-number of open file | 3831 <1> ; |-------------------------------------------| 3832 <1> ; | high word of 32 bit i-number | 3833 <1> ; |-------------------------------------------| 3834 <1> ; | open mode & status | device number | 3835 <1> ; |-------------------------------------------| 3836 <1> ; | reserved byte | open count | 3837 <1> ; |-------------------------------------------| 3838 <1> ; | offset pointer, i.e., r/w pointer to file | 3839 <1> ; |-------------------------------------------| 3840 <1> ; | 64 bit file offset pointer (bit 16-31) | 3841 <1> ; |-------------------------------------------| 3842 <1> ; | 64 bit file offset pointer (bit 32-47) | 3843 <1> ; |-------------------------------------------| 3844 <1> ; | 64 bit file offset pointer (bit 48-63) | 3845 <1> ; |-------------------------------------------| 3846 <1> ; 2 | | 3847 <1> ; |-------------------------------------------| 3848 <1> ; | | 3849 <1> ; |-------------------------------------------| 3850 <1> ; | | 3851 <1> ; |-------------------------------------------| 3852 <1> ; | | 3853 <1> ; |-------------------------------------------| 3854 <1> ; | | 3855 <1> 3856 <1> ; 3857 <1> ; 'fsp' table (10 bytes/entry) 3858 <1> ; bit 15 bit 0 3859 <1> ; ---|------------------------------------------- 3860 <1> ; r/w| i-number of open file 3861 <1> ; ---|------------------------------------------- 3862 <1> ; device number 3863 <1> ; ----------------------------------------------- 3864 <1> ; offset pointer, r/w pointer to file (bit 0-15) 3865 <1> ; ----------------------------------------------- 3866 <1> ; offset pointer, r/w pointer to file (bit 16-31) 3867 <1> ; ----------------------|------------------------ 3868 <1> ; flag that says file | number of processes 3869 <1> ; has been deleted | that have file open 3870 <1> ; ----------------------|------------------------ 3871 <1> ; 3872 <1> 3873 <1> ; temporary - 01/01/2022 3874 <1> %if 0 3875 <1> 3876 <1> ; 01/01/2022 3877 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 3878 <1> syscreat: ; < create file > 3879 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 3880 <1> ; 04/04/2021 3881 <1> ; 27/03/2021 (Retro UNIX 386 v2 - Beginning) 3882 <1> ; 27/12/2015 (Retro UNIX 386 v1.1) 3883 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3884 <1> ; 27/05/2013 (Retro UNIX 8086 v1) 3885 <1> ; 3886 <1> ; 'syscreat' called with two arguments; name and mode. 3887 <1> ; u.namep points to name of the file and mode is put 3888 <1> ; on the stack. 'namei' is called to get i-number of the file. 3889 <1> ; If the file aready exists, it's mode and owner remain 3890 <1> ; unchanged, but it is truncated to zero length. If the file 3891 <1> ; did not exist, an i-node is created with the new mode via 3892 <1> ; 'maknod' whether or not the file already existed, it is 3893 <1> ; open for writing. The fsp table is then searched for a free 3894 <1> ; entry. When a free entry is found, proper data is placed 3895 <1> ; in it and the number of this entry is put in the u.fp list. 3896 <1> ; The index to the u.fp (also know as the file descriptor) 3897 <1> ; is put in the user's r0. 3898 <1> ; 3899 <1> ; Calling sequence: 3900 <1> ; syscreate; name; mode 3901 <1> ; Arguments: 3902 <1> ; name - name of the file to be created 3903 <1> ; mode - mode of the file to be created 3904 <1> ; Inputs: (arguments) 3905 <1> ; Outputs: *u.r0 - index to u.fp list 3906 <1> ; (the file descriptor of new file) 3907 <1> ; ............................................................... 3908 <1> ; 3909 <1> ; Retro UNIX 8086 v1 modification: 3910 <1> ; 'syscreate' system call has two arguments; so, 3911 <1> ; * 1st argument, name is pointed to by BX register 3912 <1> ; * 2nd argument, mode is in CX register 3913 <1> ; 3914 <1> ; AX register (will be restored via 'u.r0') will return 3915 <1> ; to the user with the file descriptor/number 3916 <1> ; (index to u.fp list). 3917 <1> ; 3918 <1> ;call arg2 3919 <1> ; * name - 'u.namep' points to address of file/path name 3920 <1> ; in the user's program segment ('u.segmnt') 3921 <1> ; with offset in BX register (as sysopen argument 1). 3922 <1> ; * mode - sysopen argument 2 is in CX register 3923 <1> ; which is on top of stack. 3924 <1> ; 3925 <1> ; jsr r0,arg2 / put file name in u.namep put mode 3926 <1> ; / on stack 3927 <1> mov [u.namep], ebx ; file name address 3928 <1> ;push cx ; mode 3929 <1> ; 04/12/2021 3930 <1> push ecx ; cx = mode (permission flags) 3931 <1> call namei 3932 <1> ; jsr r0,namei / get the i-number 3933 <1> ;and ax, ax 3934 <1> ;jz short syscreat_1 3935 <1> jc short syscreat_1 3936 <1> ; br 2f / if file doesn't exist 2f 3937 <1> ; 27/12/2015 3938 <1> ;cmp ax, 41 ; device inode ? 3939 <1> ;jb syscreat_0 ; yes 3940 <1> ; 3941 <1> ;neg ax 3942 <1> ; ; neg r1 / if file already exists make i-number 3943 <1> ; / negative (open for writing) 3944 <1> ; 01/01/2021 3945 <1> ; 27/03/2021 3946 <1> test byte [i.flgs+1], 80h ; regular file 3947 <1> jz short f_create_error ; device inode !!! 3948 <1> test byte [i.flgs+1], 40h ; directory 3949 <1> jnz short f_create_error ; directory inode !!! 3950 <1> 3951 <1> ; Truncate existing file 3952 <1> ;syscreate_2: 3953 <1> ; 27/03/2021 3954 <1> ;xor edx, edx ; 0 3955 <1> ;inc dl ; DL = 1 ; create/truncate (open for write) 3956 <1> mov dl, 1 3957 <1> ; 3958 <1> call iopen 3959 <1> ; jsr r0,iopen / 3960 <1> call itrunc 3961 <1> ; jsr r0,itrunc / truncate to 0 length 3962 <1> ;pop cx ; pop mode (did not exist in original Unix v1 !?) 3963 <1> ; 04/12/2021 3964 <1> pop ecx 3965 <1> syscreat_2: 3966 <1> mov dl, 1 ; open for writing 3967 <1> jmp sysopen_1 3968 <1> ; br op0 3969 <1> syscreat_1: ; 2: / file doesn't exist 3970 <1> ;pop ax 3971 <1> ; ; mov (sp)+,r1 / put the mode in r1 3972 <1> ; 27/03/2021 3973 <1> pop eax ; ax = mode (permission flags) 3974 <1> ;xor ah, ah 3975 <1> ; ; bic $!377,r1 / clear upper byte 3976 <1> ; 27/03/2021 3977 <1> ;(ref: Retro UNIX 386 v2 inode flags,'ux.s') 3978 <1> ; clear bits 15,14,13,12,9 of mode (input from user) 3979 <1> and ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h) 3980 <1> or ah, 8Dh ; IFREG (8000h) ; Regular file 3981 <1> call maknod 3982 <1> ; jsr r0,maknod / make an i-node for this file 3983 <1> ;sub eax, eax ; 04/12/2021 3984 <1> mov ax, [u.dirbuf] 3985 <1> ; mov u.dirbuf,r1 / put i-number 3986 <1> ; / for this new file in r1 3987 <1> ; 04/04/2021 3988 <1> ;mov dl, 1 ; open for writing 3989 <1> ; 3990 <1> ;jmp sysopen_1 3991 <1> ; ; br op0 / open the file 3992 <1> ; 04/04/2021 3993 <1> jmp short syscreat_2 3994 <1> 3995 <1> ; 04/12/2021 3996 <1> dir_access_err: 3997 <1> ; 14/05/2015 3998 <1> ;mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 3999 <1> f_create_error: 4000 <1> ; 27/03/2021 4001 <1> mov dword [u.error], ERR_PERM_DENIED ; permission denided ! 4002 <1> jmp error 4003 <1> 4004 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 4005 <1> sysmkdir: ; < make directory > 4006 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 4007 <1> ; 02/04/2021 4008 <1> ; 27/03/2021 (Retro UNIX 386 v2 - Beginning) 4009 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 4010 <1> ; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4011 <1> ; 4012 <1> ; 'sysmkdir' creates an empty directory whose name is 4013 <1> ; pointed to by arg 1. The mode of the directory is arg 2. 4014 <1> ; The special entries '.' and '..' are not present. 4015 <1> ; Errors are indicated if the directory already exists or 4016 <1> ; user is not the super user. 4017 <1> ; 4018 <1> ; Calling sequence: 4019 <1> ; sysmkdir; name; mode 4020 <1> ; Arguments: 4021 <1> ; name - points to the name of the directory 4022 <1> ; mode - mode of the directory 4023 <1> ; Inputs: (arguments) 4024 <1> ; Outputs: - 4025 <1> ; (sets 'directory' flag to 1; 4026 <1> ; 'set user id on execution' and 'executable' flags to 0) 4027 <1> ; ............................................................... 4028 <1> ; 4029 <1> ; Retro UNIX 8086 v1 modification: 4030 <1> ; 'sysmkdir' system call has two arguments; so, 4031 <1> ; * 1st argument, name is pointed to by BX register 4032 <1> ; * 2nd argument, mode is in CX register 4033 <1> ; 4034 <1> 4035 <1> ; / make a directory 4036 <1> 4037 <1> ;call arg2 4038 <1> ; * name - 'u.namep' points to address of file/path name 4039 <1> ; in the user's program segment ('u.segmnt') 4040 <1> ; with offset in BX register (as sysopen argument 1). 4041 <1> ; * mode - sysopen argument 2 is in CX register 4042 <1> ; which is on top of stack. 4043 <1> 4044 <1> ; jsr r0,arg2 / put file name in u.namep put mode 4045 <1> ; / on stack 4046 <1> mov [u.namep], ebx 4047 <1> ;push cx ; mode 4048 <1> ; 27/03/2021 4049 <1> push ecx ; cx = mode 4050 <1> call namei 4051 <1> ; jsr r0,namei / get the i-number 4052 <1> ; br .+4 / if file not found branch around error 4053 <1> ;xor ax, ax 4054 <1> ;jnz error 4055 <1> jnc short dir_exists ; 14/05/2015 4056 <1> ;jnc error 4057 <1> ; br error2 / directory already exists (error) 4058 <1> 4059 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 4060 <1> ; ;tstb u.uid / is user the super user 4061 <1> ;jna short dir_access_err ; 14/05/2015 4062 <1> ;;jna error 4063 <1> ; ;bne error2 / no, not allowed 4064 <1> ;pop ax 4065 <1> ; ;mov (sp)+,r1 / put the mode in r1 4066 <1> ;and ax, 0FFCFh ; 1111111111001111b 4067 <1> ; ;bic $!317,r1 / all but su and ex 4068 <1> ;;or ax, 4000h ; 1011111111111111b 4069 <1> ;or ah, 40h ; Set bit 14 to 1 4070 <1> ; ;bis $40000,r1 / directory flag 4071 <1> 4072 <1> ; 02/04/2021 4073 <1> ;cmp word [u.uid], 0 4074 <1> ;ja error 4075 <1> 4076 <1> ; 02/04/2021 4077 <1> ; ('mkdir' procedure will be called from 'maknod' 4078 <1> ; and then 'mkdir' will check write access permission) 4079 <1> ; ((so, 'access_w' call is not needed here.)) 4080 <1> 4081 <1> ;; 02/04/2021 4082 <1> ;; ('make directory' user permission check) 4083 <1> ;; ((current directory's write permission flags 4084 <1> ;; will be checked against user's 'uid' & gid')) 4085 <1> ;mov dx, 80h ; IWRITE 4086 <1> ;call access_w ; (in 'access', 'u5.s') 4087 <1> ;; (If cpu will return here, the user has write permission) 4088 <1> 4089 <1> ; 27/03/2021 4090 <1> pop eax ; ax = mode 4091 <1> ; [ii] = current directory's inode number 4092 <1> 4093 <1> ; 27/03/2021 4094 <1> ;(ref: Retro UNIX 386 v2 inode flags,'ux.s') 4095 <1> ; clear bits 13,12,11,10,9,6,3,0 of mode (input from user) 4096 <1> ;and ax, 0C1B6h ; bits 15,14,8,7,5,4,2,1 4097 <1> and ax, 01B6h 4098 <1> or ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 4099 <1> ; Directory 4100 <1> call maknod 4101 <1> ;jsr r0,maknod / make the i-node for the directory 4102 <1> jmp sysret 4103 <1> ;br sysret2 / 4104 <1> dir_exists: 4105 <1> ; 27/03/2021 4106 <1> ; (same error number for files and directories) 4107 <1> ; Error Number: 14 (ERR_DIR_EXISTS) 4108 <1> mov dword [u.error], ERR_FILE_EXISTS 4109 <1> ; 'file already exists !' error 4110 <1> ; 04/12/2021 4111 <1> jmp error 4112 <1> ;dir_access_err: 4113 <1> ; ; 14/05/2015 4114 <1> ; mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 4115 <1> ; jmp error 4116 <1> 4117 <1> %endif 4118 <1> 4119 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 4120 <1> sysclose: ; 4121 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 4122 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 4123 <1> ; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1) 4124 <1> ; 4125 <1> ; 'sysclose', given a file descriptor in 'u.r0', closes the 4126 <1> ; associated file. The file descriptor (index to 'u.fp' list) 4127 <1> ; is put in r1 and 'fclose' is called. 4128 <1> ; 4129 <1> ; Calling sequence: 4130 <1> ; sysclose 4131 <1> ; Arguments: 4132 <1> ; - 4133 <1> ; Inputs: *u.r0 - file descriptor 4134 <1> ; Outputs: - 4135 <1> ; ............................................................... 4136 <1> ; 4137 <1> ; Retro UNIX 8086 v1 modification: 4138 <1> ; The user/application program puts file descriptor 4139 <1> ; in BX register as 'sysclose' system call argument. 4140 <1> ; (argument transfer method 1) 4141 <1> 4142 <1> ; / close the file 4143 <1> 4144 <1> ;mov eax, ebx 4145 <1> ; 04/12/2021 4146 <1> ; ebx = file descriptor/number 4147 000040E6 E83E070000 <1> call fclose 4148 <1> ; mov *u.r0,r1 / move index to u.fp list into r1 4149 <1> ; jsr r0,fclose / close the file 4150 <1> ; br error2 / unknown file descriptor 4151 <1> ; br sysret2 4152 <1> ;; 14/05/2015 4153 <1> ;jnc sysret 4154 <1> ; 04/12/2021 4155 000040EB 7205 <1> jc short sysclose_1 4156 000040ED E9DAFAFFFF <1> jmp sysret 4157 <1> sysclose_1: 4158 000040F2 C705[186F0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 4158 000040FA 0000 <1> 4159 000040FC E9ABFAFFFF <1> jmp error 4160 <1> 4161 <1> ; 19/12/2021 4162 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 4163 <1> sysemt: 4164 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 4165 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 4166 <1> ; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1) 4167 <1> ; 4168 <1> ; Retro UNIX 8086 v1 modification: 4169 <1> ; 'Enable Multi Tasking' system call instead 4170 <1> ; of 'Emulator Trap' in original UNIX v1 for PDP-11. 4171 <1> ; 4172 <1> ; Retro UNIX 8086 v1 feature only! 4173 <1> ; Using purpose: Kernel will start without time-out 4174 <1> ; (internal clock/timer) functionality. 4175 <1> ; Then etc/init will enable clock/timer for 4176 <1> ; multi tasking. (Then it will not be disabled again 4177 <1> ; except hardware reset/restart.) 4178 <1> ; 4179 <1> 4180 <1> ;cmp byte [u.uid], 0 ; root ? 4181 <1> ;;ja error 4182 <1> ;ja badsys ; 14/05/2015 4183 <1> ; 04/12/2021 4184 00004101 66833D[F66E0000]00 <1> cmp word [u.uid], 0 ; root ? 4185 00004109 7605 <1> jna short emt_0 4186 0000410B E94EFBFFFF <1> jmp badsys 4187 <1> emt_0: 4188 <1> ; 19/12/2021 4189 <1> ;cli 4190 00004110 21DB <1> and ebx, ebx 4191 00004112 740F <1> jz short emt_2 4192 <1> ; Enable multi tasking -time sharing- 4193 00004114 B8[124E0000] <1> mov eax, clock 4194 <1> emt_1: 4195 00004119 A3[0F070000] <1> mov [x_timer], eax 4196 <1> ;sti 4197 0000411E E9A9FAFFFF <1> jmp sysret 4198 <1> emt_2: 4199 <1> ; Disable multi tasking -time sharing- 4200 00004123 B8[17070000] <1> mov eax, u_timer 4201 00004128 EBEF <1> jmp short emt_1 4202 <1> 4203 <1> ; Original UNIX v1 'sysemt' routine 4204 <1> ;sysemt: 4205 <1> ; 4206 <1> ;jsr r0,arg; 30 / put the argument of the sysemt call 4207 <1> ; / in loc 30 4208 <1> ;cmp 30,$core / was the argument a lower address 4209 <1> ; / than core 4210 <1> ;blo 1f / yes, rtssym 4211 <1> ;cmp 30,$ecore / no, was it higher than "core" 4212 <1> ; / and less than "ecore" 4213 <1> ;blo 2f / yes, sysret2 4214 <1> ;1: 4215 <1> ;mov $rtssym,30 4216 <1> ;2: 4217 <1> ;br sysret2 4218 <1> 4219 <1> sysilgins: 4220 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 4221 <1> ; 03/06/2013 4222 <1> ; Retro UNIX 8086 v1 modification: 4223 <1> ; not a valid system call ! (not in use) 4224 <1> ; 4225 0000412A E92FFBFFFF <1> jmp badsys 4226 <1> ;jmp error 4227 <1> ;;jmp sysret 4228 <1> 4229 <1> ; Original UNIX v1 'sysemt' routine 4230 <1> ;sysilgins: / calculate proper illegal instruction trap address 4231 <1> ;jsr r0,arg; 10 / take address from sysilgins call 4232 <1> ;/ put it in loc 8., 4233 <1> ;cmp 10,$core / making it the illegal instruction 4234 <1> ; / trap address 4235 <1> ;blo 1f / is the address a user core address? 4236 <1> ; / yes, go to 2f 4237 <1> ;cmp 10,$ecore 4238 <1> ;blo 2f 4239 <1> ;1: 4240 <1> ;mov $fpsym,10 / no, make 'fpsum' the illegal 4241 <1> ; / instruction trap address for the system 4242 <1> ;2: 4243 <1> ;br sysret2 / return to the caller via 'sysret' 4244 <1> 4245 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 4246 <1> sysmdate: ; < change the modification time of a file > 4247 <1> ; 24/12/2021 4248 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 4249 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 4250 <1> ; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4251 <1> ; 4252 <1> ; 'sysmdate' is given a file name. It gets inode of this 4253 <1> ; file into core. The user is checked if he is the owner 4254 <1> ; or super user. If he is neither an error occurs. 4255 <1> ; 'setimod' is then called to set the i-node modification 4256 <1> ; byte and the modification time, but the modification time 4257 <1> ; is overwritten by whatever get put on the stack during 4258 <1> ; a 'systime' system call. This calls are restricted to 4259 <1> ; the super user. 4260 <1> ; 4261 <1> ; Calling sequence: 4262 <1> ; sysmdate; name 4263 <1> ; Arguments: 4264 <1> ; name - points to the name of file 4265 <1> ; Inputs: (arguments) 4266 <1> ; Outputs: - 4267 <1> ; ............................................................... 4268 <1> ; 4269 <1> ; Retro UNIX 8086 v1 modification: 4270 <1> ; The user/application program puts address 4271 <1> ; of the file name in BX register 4272 <1> ; as 'sysmdate' system call argument. 4273 <1> ; 4274 <1> ; / change the modification time of a file 4275 <1> ; jsr r0,arg; u.namep / point u.namep to the file name 4276 0000412F 891D[C06E0000] <1> mov [u.namep], ebx 4277 00004135 E8A8070000 <1> call namei 4278 <1> ; jsr r0,namei / get its i-number 4279 <1> ;;jc error 4280 <1> ; ; br error2 / no, such file 4281 <1> ;jc fnotfound ; file not found ! 4282 <1> ; 24/12/2021 4283 0000413A 7305 <1> jnc short mdate_0 4284 0000413C E9DFFEFFFF <1> jmp fnotfound 4285 <1> mdate_0: 4286 00004141 E82A110000 <1> call iget 4287 <1> ; jsr r0,iget / get i-node into core 4288 <1> ;mov al, [u.uid] 4289 <1> ;cmp al, [i.uid] 4290 <1> ; ; cmpb u.uid,i.uid / is user same as owner 4291 <1> ;je short mdate_1 4292 <1> ; ; beq 1f / yes 4293 <1> ;and al, al 4294 <1> ; ; tstb u.uid / no, is user the super user 4295 <1> ;;jnz error 4296 <1> ; ; bne error2 / no, error 4297 <1> ;jz short mdate_1 4298 <1> ; 04/12/2021 4299 00004146 66A1[F66E0000] <1> mov ax, [u.uid] 4300 0000414C 663B05[446B0000] <1> cmp ax, [i.uid] 4301 00004153 7414 <1> je short mdate_1 4302 00004155 6621C0 <1> and ax, ax 4303 00004158 740F <1> jz short mdate_1 4304 <1> 4305 0000415A C705[186F0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 4305 00004162 0000 <1> 4306 00004164 E943FAFFFF <1> jmp error 4307 <1> mdate_1: ;1: 4308 00004169 E8A1120000 <1> call setimod 4309 <1> ; jsr r0,setimod / fill in modification data, 4310 <1> ; / time etc. 4311 0000416E BE[F06D0000] <1> mov esi, p_time 4312 00004173 BF[786B0000] <1> mov edi, i.mtim 4313 00004178 A5 <1> movsd 4314 <1> ; mov 4(sp),i.mtim / move present time to 4315 <1> ; mov 2(sp),i.mtim+2 / modification time 4316 00004179 E94EFAFFFF <1> jmp sysret 4317 <1> ; br sysret2 4318 <1> 4319 <1> sysstty: ; < set tty status and mode > 4320 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4321 <1> ; ((32 bit reg push/pop)) 4322 <1> ; 17/11/2015 4323 <1> ; 12/11/2015 4324 <1> ; 29/10/2015 4325 <1> ; 17/10/2015 4326 <1> ; 13/10/2015 4327 <1> ; 29/06/2015 4328 <1> ; 27/06/2015 (Retro UNIX 386 v1 - Beginning) 4329 <1> ; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1) 4330 <1> ; 4331 <1> ; 'sysstty' sets the status and mode of the typewriter 4332 <1> ; whose file descriptor is in (u.r0). 4333 <1> ; 4334 <1> ; Calling sequence: 4335 <1> ; sysstty; arg 4336 <1> ; Arguments: 4337 <1> ; arg - address of 3 consequitive words that contain 4338 <1> ; the source of status data 4339 <1> ; Inputs: ((*u.r0 - file descriptor & argument)) 4340 <1> ; Outputs: ((status in address which is pointed to by arg)) 4341 <1> ; ............................................................... 4342 <1> ; 4343 <1> ; Retro UNIX 8086 v1 modification: 4344 <1> ; 'sysstty' system call will set the tty 4345 <1> ; (clear keyboard buffer and set cursor position) 4346 <1> ; in following manner: 4347 <1> ; NOTE: All of tty setting functions are here (16/01/2014) 4348 <1> ; 4349 <1> ; Inputs: 4350 <1> ; BX = 0 --> means 4351 <1> ; If CL = FFh 4352 <1> ; set cursor position for console tty, only 4353 <1> ; CH will be ignored (char. will not be written) 4354 <1> ; If CH = 0 (CL < FFh) 4355 <1> ; set console tty for (current) process 4356 <1> ; CL = tty number (0 to 9) 4357 <1> ; (If CH = 0, character will not be written) 4358 <1> ; If CH > 0 (CL < FFh) 4359 <1> ; CL = tty number (0 to 9) 4360 <1> ; CH = character will be written 4361 <1> ; at requested cursor position (in DX) 4362 <1> ; DX = cursor position for tty number 0 to 7. 4363 <1> ; (only tty number 0 to 7) 4364 <1> ; DL = communication parameters (for serial ports) 4365 <1> ; (only for COM1 and COM2 serial ports) 4366 <1> ; DH < 0FFh -> DL is valid, initialize serial port 4367 <1> ; or set cursor position 4368 <1> ; DH = 0FFh -> DL is not valid 4369 <1> ; do not set serial port parameters 4370 <1> ; or do not set cursor position 4371 <1> ; 4372 <1> ; BX > 0 --> points to name of tty 4373 <1> ; CH > 0 --> 4374 <1> ; CH = character will be written in current 4375 <1> ; cursor position (for tty number from 0 to 7) 4376 <1> ; or character will be sent to serial port 4377 <1> ; (for tty number 8 or 9) 4378 <1> ; CL = color of the character if tty number < 8. 4379 <1> ; CH = 0 --> Do not write a character, 4380 <1> ; set mode (tty 8 to 9) or 4381 <1> ; set current cursor positions (tty 0 to 7) only. 4382 <1> ; DX = cursor position for tty number 0 to 7. 4383 <1> ; DH = FFh --> Do not set cursor pos (or comm. params.) 4384 <1> ; (DL is not valid) 4385 <1> ; DL = communication parameters 4386 <1> ; for tty number 8 or 9 (COM1 or COM2). 4387 <1> ; Outputs: 4388 <1> ; cf = 0 -> OK 4389 <1> ; AL = tty number (0 to 9) 4390 <1> ; AH = line status if tty number is 8 or 9 4391 <1> ; AH = process number (of the caller) 4392 <1> ; cf = 1 means error (requested tty is not ready) 4393 <1> ; AH = FFh if the tty is locked 4394 <1> ; (owned by another process) 4395 <1> ; = process number (of the caller) 4396 <1> ; (if < FFh and tty number < 8) 4397 <1> ; AL = tty number (0FFh if it does not exist) 4398 <1> ; AH = line status if tty number is 8 or 9 4399 <1> ; NOTE: Video page will be cleared if cf = 0. 4400 <1> ; 4401 <1> ; 27/06/2015 (32 bit modifications) 4402 <1> ; 14/01/2014 4403 0000417E 31C0 <1> xor eax, eax 4404 00004180 6648 <1> dec ax ; 17/10/2015 4405 00004182 A3[A46E0000] <1> mov [u.r0], eax ; 0FFFFh 4406 00004187 21DB <1> and ebx, ebx 4407 <1> ;jnz sysstty_6 4408 <1> ; 24/12/2021 4409 00004189 7405 <1> jz short sysstty_14 4410 0000418B E9C7000000 <1> jmp sysstty_6 4411 <1> sysstty_14: 4412 <1> ; set console tty 4413 <1> ; 29/10/2015 4414 <1> ; 17/01/2014 4415 00004190 80F909 <1> cmp cl, 9 4416 00004193 7613 <1> jna short sysstty_0 4417 <1> ; 17/11/2015 4418 00004195 80F9FF <1> cmp cl, 0FFh 4419 00004198 7202 <1> jb short sysstty_13 4420 0000419A 88CD <1> mov ch, cl ; force CH value to FFh 4421 <1> sysstty_13: 4422 0000419C 8A1D[F56E0000] <1> mov bl, [u.uno] ; process number 4423 000041A2 8A8B[DF6B0000] <1> mov cl, [ebx+p.ttyc-1] ; current/console tty 4424 <1> sysstty_0: 4425 <1> ; 29/06/2015 4426 000041A8 52 <1> push edx ; 24/12/2021 4427 000041A9 51 <1> push ecx 4428 000041AA 30D2 <1> xor dl, dl ; sysstty call sign 4429 000041AC 88C8 <1> mov al, cl 4430 000041AE A2[A46E0000] <1> mov [u.r0], al ; tyy number (0 to 9) 4431 000041B3 E8A81A0000 <1> call ottyp 4432 000041B8 59 <1> pop ecx 4433 000041B9 5A <1> pop edx 4434 <1> ; 4435 000041BA 7256 <1> jc short sysstty_pd_err 4436 <1> ; 4437 000041BC 80F908 <1> cmp cl, 8 4438 000041BF 7220 <1> jb short sysstty_2 4439 <1> ; 4440 000041C1 80FEFF <1> cmp dh, 0FFh 4441 000041C4 741B <1> je short sysstty_2 4442 <1> ; set communication parameters for serial ports 4443 <1> ; 29/10/2015 4444 000041C6 88D4 <1> mov ah, dl ; communication parameters 4445 <1> ; ah = 0E3h = 11100011b = 115200 baud, 4446 <1> ; THRE int + RDA int 4447 <1> ; ah = 23h = 00100011b = 9600 baud, 4448 <1> ; THRE int + RDA int 4449 000041C8 28C0 <1> sub al, al ; 0 4450 <1> ; 12/07/2014 4451 000041CA 80F909 <1> cmp cl, 9 4452 000041CD 7202 <1> jb short sysstty_1 4453 000041CF FEC0 <1> inc al 4454 <1> sysstty_1: 4455 000041D1 51 <1> push ecx ; 24/12/2021 4456 <1> ; 29/06/2015 4457 000041D2 E85FF4FFFF <1> call sp_setp ; Set serial port communication parameters 4458 000041D7 66890D[A56E0000] <1> mov [u.r0+1], cx ; Line status (ah) 4459 <1> ; Modem status (EAX bits 16 to 23) 4460 000041DE 59 <1> pop ecx 4461 000041DF 7267 <1> jc short sysstty_tmout_err ; 29/10/2015 4462 <1> sysstty_2: 4463 <1> ; 17/01/2014 4464 000041E1 20ED <1> and ch, ch ; set cursor position 4465 <1> ; or comm. parameters ONLY 4466 000041E3 750D <1> jnz short sysstty_3 4467 000041E5 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 4468 000041EC 888B[DF6B0000] <1> mov [ebx+p.ttyc-1], cl ; console tty 4469 <1> sysstty_3: 4470 <1> ; 16/01/2014 4471 000041F2 88E8 <1> mov al, ch ; character ; 0 to FFh 4472 <1> ; 17/11/2015 4473 000041F4 B507 <1> mov ch, 7 ; Default color (light gray) 4474 000041F6 38E9 <1> cmp cl, ch ; 7 (tty number) 4475 <1> ;jna sysstty_9 4476 <1> ; 24/12/2021 4477 000041F8 7705 <1> ja short sysstty_12 4478 000041FA E9BE000000 <1> jmp sysstty_9 4479 <1> sysstty_12: 4480 <1> ;; BX = 0, CL = 8 or CL = 9 4481 <1> ; (Set specified serial port as console tty port) 4482 <1> ; CH = character to be written 4483 <1> ; 15/04/2014 4484 <1> ; CH = 0 --> initialization only 4485 <1> ; AL = character 4486 <1> ; 26/06/2014 4487 000041FF 880D[D96E0000] <1> mov [u.ttyn], cl 4488 <1> ; 12/07/2014 4489 00004205 88CC <1> mov ah, cl ; tty number (8 or 9) 4490 00004207 20C0 <1> and al, al 4491 00004209 7416 <1> jz short sysstty_4 ; al = ch = 0 4492 <1> ; 04/07/2014 4493 0000420B E893200000 <1> call sndc 4494 <1> ; 12/07/2014 4495 00004210 EB1B <1> jmp short sysstty_5 4496 <1> sysstty_pd_err: ; 29/06/2015 4497 <1> ; 'permission denied !' error 4498 00004212 C705[186F0000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER 4498 0000421A 0000 <1> 4499 0000421C E98BF9FFFF <1> jmp error 4500 <1> sysstty_4: 4501 <1> ; 12/07/2014 4502 <1> ;xchg ah, al ; al = 0 -> al = ah, ah = 0 4503 00004221 88E0 <1> mov al, ah ; 29/06/2015 4504 00004223 2C08 <1> sub al, 8 4505 <1> ; 27/06/2015 4506 00004225 E804F4FFFF <1> call sp_status ; get serial port status 4507 <1> ; AL = Line status, AH = Modem status 4508 <1> ; 12/11/2015 4509 0000422A 3C80 <1> cmp al, 80h 4510 0000422C F5 <1> cmc 4511 <1> sysstty_5: 4512 0000422D 66A3[A56E0000] <1> mov [u.r0+1], ax ; ah = line status 4513 <1> ; EAX bits 16-23 = modem status 4514 00004233 9C <1> pushf 4515 00004234 30D2 <1> xor dl, dl ; sysstty call sign 4516 00004236 A0[D96E0000] <1> mov al, [u.ttyn] ; 26/06/2014 4517 0000423B E8421B0000 <1> call cttyp 4518 00004240 9D <1> popf 4519 <1> ;jnc sysret 4520 <1> ; 24/12/2021 4521 00004241 7205 <1> jc short sysstty_tmout_err 4522 00004243 E984F9FFFF <1> jmp sysret 4523 <1> ; time out error 4524 <1> sysstty_tmout_err: 4525 00004248 C705[186F0000]1900- <1> mov dword [u.error], ERR_TIME_OUT 4525 00004250 0000 <1> 4526 00004252 E955F9FFFF <1> jmp error 4527 <1> sysstty_6: 4528 00004257 52 <1> push edx ; 24/12/2021 4529 00004258 51 <1> push ecx 4530 00004259 891D[C06E0000] <1> mov [u.namep], ebx 4531 0000425F E87E060000 <1> call namei 4532 00004264 59 <1> pop ecx 4533 00004265 5A <1> pop edx 4534 00004266 720E <1> jc short sysstty_inv_dn 4535 <1> ; 4536 00004268 6683F813 <1> cmp ax, 19 ; inode number of /dev/COM2 4537 0000426C 7708 <1> ja short sysstty_inv_dn ; 27/06/2015 4538 <1> ; 4539 0000426E 3C0A <1> cmp al, 10 ; /dev/tty0 .. /dev/tty7 4540 <1> ; /dev/COM1, /dev/COM2 4541 00004270 7213 <1> jb short sysstty_7 4542 00004272 2C0A <1> sub al, 10 4543 00004274 EB20 <1> jmp short sysstty_8 4544 <1> sysstty_inv_dn: 4545 <1> ; 27/06/2015 4546 <1> ; Invalid device name (not a tty) ! error 4547 <1> ; (Device is not a tty or device name not found) 4548 00004276 C705[186F0000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 4548 0000427E 0000 <1> 4549 00004280 E927F9FFFF <1> jmp error 4550 <1> sysstty_7: 4551 00004285 3C01 <1> cmp al, 1 ; /dev/tty 4552 00004287 75ED <1> jne short sysstty_inv_dn ; 27/06/2015 4553 00004289 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 4554 00004290 8A83[DF6B0000] <1> mov al, [ebx+p.ttyc-1] ; console tty 4555 <1> sysstty_8: 4556 00004296 A2[A46E0000] <1> mov [u.r0], al 4557 0000429B 52 <1> push edx ; 24/12/2021 4558 0000429C 50 <1> push eax 4559 0000429D 51 <1> push ecx 4560 0000429E E8BD190000 <1> call ottyp 4561 000042A3 59 <1> pop ecx 4562 000042A4 58 <1> pop eax 4563 000042A5 5A <1> pop edx 4564 <1> ;jc sysstty_pd_err ; 'permission denied !' 4565 <1> ; 24/12/2021 4566 000042A6 7305 <1> jnc short sysstty_15 4567 <1> ; 'permission denied !' 4568 000042A8 E965FFFFFF <1> jmp sysstty_pd_err 4569 <1> sysstty_15: 4570 <1> ; 29/10/2015 4571 000042AD 86E9 <1> xchg ch, cl 4572 <1> ; cl = character, ch = color code 4573 000042AF 86C1 <1> xchg al, cl 4574 <1> ; al = character, cl = tty number 4575 000042B1 80F907 <1> cmp cl, 7 4576 <1> ;ja sysstty_12 4577 <1> ; 24/12/2021 4578 000042B4 7605 <1> jna short sysstty_16 4579 000042B6 E944FFFFFF <1> jmp sysstty_12 4580 <1> sysstty_16: 4581 <1> ; 16/01/2014 4582 000042BB 30FF <1> xor bh, bh 4583 <1> ; 4584 <1> sysstty_9: ; tty 0 to tty 7 4585 <1> ; al = character 4586 000042BD 80FEFF <1> cmp dh, 0FFh ; Do not set cursor position 4587 000042C0 740B <1> je short sysstty_10 4588 000042C2 51 <1> push ecx ; 24/12/2021 4589 000042C3 50 <1> push eax 4590 <1> ;movzx, ebx, cl 4591 000042C4 88CB <1> mov bl, cl ; (tty number = video page number) 4592 000042C6 E813D2FFFF <1> call set_cpos 4593 000042CB 58 <1> pop eax 4594 000042CC 59 <1> pop ecx 4595 <1> sysstty_10: 4596 <1> ; 29/10/2015 4597 000042CD 08C0 <1> or al, al ; character 4598 000042CF 740D <1> jz short sysstty_11 ; al = 0 4599 <1> ; 17/11/2015 4600 000042D1 3CFF <1> cmp al, 0FFh 4601 000042D3 7309 <1> jnb short sysstty_11 4602 <1> ; ch > 0 and ch < FFh 4603 <1> ; write a character at current cursor position 4604 000042D5 88EC <1> mov ah, ch ; color/attribute 4605 <1> ; 12/07/2014 4606 000042D7 51 <1> push ecx ; 24/12/2021 4607 000042D8 E83FD3FFFF <1> call write_c_current 4608 000042DD 59 <1> pop ecx 4609 <1> sysstty_11: 4610 <1> ; 14/01/2014 4611 000042DE 30D2 <1> xor dl, dl ; sysstty call sign 4612 <1> ; 18/01/2014 4613 <1> ;movzx eax, cl ; 27/06/2015 4614 000042E0 88C8 <1> mov al, cl 4615 000042E2 E89B1A0000 <1> call cttyp 4616 000042E7 E9E0F8FFFF <1> jmp sysret 4617 <1> 4618 <1> ; Original UNIX v1 'sysstty' routine: 4619 <1> ; gtty: 4620 <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments 4621 <1> ;jsr r0,gtty / r1 will have offset to tty block, 4622 <1> ; / r2 has source 4623 <1> ;mov r2,-(sp) 4624 <1> ;mov r1,-(sp) / put r1 and r2 on the stack 4625 <1> ;1: / flush the clist wait till typewriter is quiescent 4626 <1> ;mov (sp),r1 / restore r1 to tty block offset 4627 <1> ;movb tty+3(r1),0f / put cc offset into getc argument 4628 <1> ;mov $240,*$ps / set processor priority to 5 4629 <1> ;jsr r0,getc; 0:../ put character from clist in r1 4630 <1> ; br .+4 / list empty, skip branch 4631 <1> ;br 1b / get another character until list is empty 4632 <1> ;mov 0b,r1 / move cc offset to r1 4633 <1> ;inc r1 / bump it for output clist 4634 <1> ;tstb cc(r1) / is it 0 4635 <1> ;beq 1f / yes, no characters to output 4636 <1> ;mov r1,0f / no, put offset in sleep arg 4637 <1> ;jsr r0,sleep; 0:.. / put tty output process to sleep 4638 <1> ;br 1b / try to calm it down again 4639 <1> ;1: 4640 <1> ;mov (sp)+,r1 4641 <1> ;mov (sp)+,r2 / restore registers 4642 <1> ;mov (r2)+,r3 / put reader control status in r3 4643 <1> ;beq 1f / if 0, 1f 4644 <1> ;mov r3,rcsr(r1) / move r.c. status to reader 4645 <1> ; / control status register 4646 <1> ;1: 4647 <1> ;mov (r2)+,r3 / move pointer control status to r3 4648 <1> ;beq 1f / if 0 1f 4649 <1> ;mov r3,tcsr(r1) / move p.c. status to printer 4650 <1> ; / control status reg 4651 <1> ;1: 4652 <1> ;mov (r2)+,tty+4(r1) / move to flag byte of tty block 4653 <1> ;jmp sysret2 / return to user 4654 <1> 4655 <1> sysgtty: ; < get tty status > 4656 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4657 <1> ; ((32 bit reg push/pop)) 4658 <1> ; 23/11/2015 4659 <1> ; 29/10/2015 4660 <1> ; 17/10/2015 4661 <1> ; 28/06/2015 (Retro UNIX 386 v1 - Beginning) 4662 <1> ; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1) 4663 <1> ; 4664 <1> ; 'sysgtty' gets the status of tty in question. 4665 <1> ; It stores in the three words addressed by it's argument 4666 <1> ; the status of the typewriter whose file descriptor 4667 <1> ; in (u.r0). 4668 <1> ; 4669 <1> ; Calling sequence: 4670 <1> ; sysgtty; arg 4671 <1> ; Arguments: 4672 <1> ; arg - address of 3 words destination of the status 4673 <1> ; Inputs: ((*u.r0 - file descriptor)) 4674 <1> ; Outputs: ((status in address which is pointed to by arg)) 4675 <1> ; ............................................................... 4676 <1> ; 4677 <1> ; Retro UNIX 8086 v1 modification: 4678 <1> ; 'sysgtty' system call will return status of tty 4679 <1> ; (keyboard, serial port and video page status) 4680 <1> ; in following manner: 4681 <1> ; 4682 <1> ; Inputs: 4683 <1> ; BX = 0 --> means 4684 <1> ; CH = 0 --> 'return status of the console tty' 4685 <1> ; for (current) process 4686 <1> ; CL = 0 --> return keyboard status (tty 0 to 9) 4687 <1> ; CL = 1 --> return video page status (tty 0 to 7) 4688 <1> ; CL = 1 --> return serial port status (tty 8 & 9) 4689 <1> ; CH > 0 --> tty number + 1 4690 <1> ; 4691 <1> ; BX > 0 --> points to name of tty 4692 <1> ; CL = 0 --> return keyboard status 4693 <1> ; CL = 1 --> return video page status 4694 <1> ; CH = undefined 4695 <1> ; 4696 <1> ; Outputs: 4697 <1> ; cf = 0 -> 4698 <1> ; 4699 <1> ; AL = tty number from 0 to 9 4700 <1> ; (0 to 7 is also the video page of the tty) 4701 <1> ; AH = 0 if the tty is free/unused 4702 <1> ; AH = the process number of the caller 4703 <1> ; AH = FFh if the tty is locked by another process 4704 <1> ; 4705 <1> ; (if calling is for serial port status) 4706 <1> ; BX = serial port status if tty number is 8 or 9 4707 <1> ; (BH = modem status, BL = Line status) 4708 <1> ; CX = 0FFFFh (if data is ready) 4709 <1> ; CX = 0 (if data is not ready or undefined) 4710 <1> ; 4711 <1> ; (if calling is for keyboard status) 4712 <1> ; BX = current character in tty/keyboard buffer 4713 <1> ; (BH = scan code, BL = ascii code) 4714 <1> ; (BX=0 if there is not a waiting character) 4715 <1> ; CX is undefined 4716 <1> ; 4717 <1> ; (if calling is for video page status) 4718 <1> ; BX = cursor position on the video page 4719 <1> ; if tty number < 8 4720 <1> ; (BH = row, BL = column) 4721 <1> ; CX = current character (in cursor position) 4722 <1> ; on the video page of the tty 4723 <1> ; if tty number < 8 4724 <1> ; (CH = color, CL = character) 4725 <1> ; 4726 <1> ; cf = 1 means error (requested tty is not ready) 4727 <1> ; 4728 <1> ; AH = FFh if the caller is not owner of 4729 <1> ; specified tty or console tty 4730 <1> ; AL = tty number (0FFh if it does not exist) 4731 <1> ; BX, CX are undefined if cf = 1 4732 <1> ; 4733 <1> ; (If tty number is 8 or 9) 4734 <1> ; AL = tty number 4735 <1> ; AH = the process number of the caller 4736 <1> ; BX = serial port status 4737 <1> ; (BH = modem status, BL = Line status) 4738 <1> ; CX = 0 4739 <1> ; 4740 <1> 4741 <1> gtty: ; get (requested) tty number 4742 <1> ; 17/10/2015 4743 <1> ; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications) 4744 <1> ; 30/05/2013 - 12/07/2014 4745 <1> ; Retro UNIX 8086 v1 modification ! 4746 <1> ; 4747 <1> ; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP)) 4748 <1> ; 4749 <1> ; 28/06/2015 (32 bit modifications) 4750 <1> ; 16/01/2014 4751 000042EC 31C0 <1> xor eax, eax 4752 000042EE 6648 <1> dec ax ; 17/10/2015 4753 000042F0 A3[A46E0000] <1> mov [u.r0], eax ; 0FFFFh 4754 000042F5 80F901 <1> cmp cl, 1 4755 000042F8 760F <1> jna short sysgtty_0 4756 <1> sysgtty_invp: 4757 <1> ; 28/06/2015 4758 000042FA C705[186F0000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 4758 00004302 0000 <1> 4759 00004304 E9A3F8FFFF <1> jmp error 4760 <1> sysgtty_0: 4761 00004309 21DB <1> and ebx, ebx 4762 0000430B 742E <1> jz short sysgtty_1 4763 <1> ; 4764 0000430D 891D[C06E0000] <1> mov [u.namep], ebx 4765 <1> ;push cx ; 23/11/2015 4766 00004313 51 <1> push ecx ; 24/12/2021 4767 00004314 E8C9050000 <1> call namei 4768 00004319 59 <1> pop ecx 4769 <1> ;pop cx ; 23/11/2015 4770 0000431A 7210 <1> jc short sysgtty_inv_dn ; 28/06/2015 4771 <1> ; 4772 0000431C 6683F801 <1> cmp ax, 1 4773 00004320 7622 <1> jna short sysgtty_2 4774 00004322 6683E80A <1> sub ax, 10 4775 00004326 6683F809 <1> cmp ax, 9 4776 <1> ;ja short sysgtty_inv_dn 4777 <1> ;mov ch, al 4778 <1> ;jmp short sysgtty_4 4779 <1> ; 23/11/2015 4780 0000432A 7629 <1> jna short sysgtty_4 4781 <1> sysgtty_inv_dn: 4782 <1> ; 28/06/2015 4783 <1> ; Invalid device name (not a tty) ! error 4784 <1> ; (Device is not a tty or device name not found) 4785 0000432C C705[186F0000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 4785 00004334 0000 <1> 4786 00004336 E971F8FFFF <1> jmp error 4787 <1> sysgtty_1: 4788 <1> ; 16/01/2014 4789 0000433B 80FD0A <1> cmp ch, 10 4790 0000433E 77BA <1> ja short sysgtty_invp ; 28/06/2015 4791 00004340 FECD <1> dec ch ; 0 -> FFh (negative) 4792 00004342 790F <1> jns short sysgtty_3 ; not negative 4793 <1> ; 4794 <1> sysgtty_2: 4795 <1> ; get tty number of console tty 4796 00004344 8A25[F56E0000] <1> mov ah, [u.uno] 4797 <1> ; 28/06/2015 4798 0000434A 0FB6DC <1> movzx ebx, ah 4799 0000434D 8AAB[DF6B0000] <1> mov ch, [ebx+p.ttyc-1] 4800 <1> sysgtty_3: 4801 00004353 88E8 <1> mov al, ch 4802 <1> sysgtty_4: 4803 00004355 A2[A46E0000] <1> mov [u.r0], al 4804 <1> ; 28/06/2015 4805 <1> ;cmp al, 9 4806 <1> ;ja short sysgtty_invp 4807 0000435A 8B2D[A06E0000] <1> mov ebp, [u.usp] 4808 <1> ; 23/11/2015 4809 00004360 20C9 <1> and cl, cl 4810 00004362 7432 <1> jz short sysgtty_6 ; keyboard status 4811 00004364 3C08 <1> cmp al, 8 ; cmp ch, 8 4812 00004366 722E <1> jb short sysgtty_6 ; video page status 4813 <1> ; serial port status 4814 <1> ; 12/07/2014 4815 <1> ;mov dx, 0 4816 <1> ;je short sysgtty_5 4817 <1> ;inc dl 4818 <1> ;sysgtty_5: 4819 <1> ; 28/06/2015 4820 00004368 2C08 <1> sub al, 8 4821 0000436A E8BFF2FFFF <1> call sp_status ; serial (COM) port (line) status 4822 <1> ; AL = Line status, AH = Modem status 4823 0000436F 66894510 <1> mov [ebp+16], ax ; serial port status (in EBX) 4824 00004373 8A25[F56E0000] <1> mov ah, [u.uno] 4825 00004379 8825[A56E0000] <1> mov [u.r0+1], ah 4826 <1> ; 24/12/2021 4827 0000437F 66C745180000 <1> mov word [ebp+24], 0 ; data status (0 = not ready) 4828 <1> ; (in ECX) 4829 00004385 A880 <1> test al, 80h 4830 00004387 7561 <1> jnz short sysgtty_dnr_err ; 29/06/2015 4831 00004389 A801 <1> test al, 1 4832 <1> ;jz sysret 4833 0000438B 7404 <1> jz short sysgtty_10 4834 0000438D 66FF4D18 <1> dec word [ebp+24] ; data status (FFFFh = ready) 4835 <1> sysgtty_10: 4836 00004391 E936F8FFFF <1> jmp sysret 4837 <1> sysgtty_6: 4838 00004396 A2[D96E0000] <1> mov [u.ttyn], al ; tty number 4839 <1> ;movzx ebx, al 4840 0000439B 88C3 <1> mov bl, al ; tty number (0 to 9) 4841 0000439D D0E3 <1> shl bl, 1 ; aligned to word 4842 <1> ; 22/04/2014 - 29/06/2015 4843 0000439F 81C3[F46D0000] <1> add ebx, ttyl 4844 000043A5 8A23 <1> mov ah, [ebx] 4845 000043A7 3A25[F56E0000] <1> cmp ah, [u.uno] 4846 000043AD 7404 <1> je short sysgtty_7 4847 000043AF 20E4 <1> and ah, ah 4848 <1> ;jz short sysgtty_7 4849 000043B1 7506 <1> jnz short sysgtty_8 4850 <1> ;mov ah, 0FFh 4851 <1> sysgtty_7: 4852 000043B3 8825[A56E0000] <1> mov [u.r0+1], ah 4853 <1> sysgtty_8: 4854 000043B9 08C9 <1> or cl, cl 4855 000043BB 7510 <1> jnz short sysgtty_9 4856 000043BD B001 <1> mov al, 1 ; test a key is available 4857 000043BF E8621E0000 <1> call getc 4858 000043C4 66894510 <1> mov [ebp+16], ax ; bx, character 4859 000043C8 E9FFF7FFFF <1> jmp sysret 4860 <1> sysgtty_9: 4861 000043CD 8A1D[D96E0000] <1> mov bl, [u.ttyn] 4862 <1> ; bl = video page number 4863 000043D3 E8C11F0000 <1> call get_cpos 4864 <1> ; dx = cursor position 4865 000043D8 66895510 <1> mov [ebp+16], dx ; bx 4866 <1> ;mov bl, [u.ttyn] 4867 <1> ; bl = video page number 4868 000043DC E8C91F0000 <1> call read_ac_current 4869 <1> ; ax = character and attribute/color 4870 000043E1 66894518 <1> mov [ebp+24], ax ; cx 4871 000043E5 E9E2F7FFFF <1> jmp sysret 4872 <1> sysgtty_dnr_err: 4873 <1> ; 'device not responding !' error 4874 <1> ;mov dword [u.error], ERR_TIME_OUT ; 25 4875 000043EA C705[186F0000]1900- <1> mov dword [u.error], ERR_DEV_NOT_RESP ; 25 4875 000043F2 0000 <1> 4876 000043F4 E9B3F7FFFF <1> jmp error 4877 <1> 4878 <1> ; Original UNIX v1 'sysgtty' routine: 4879 <1> ; sysgtty: 4880 <1> ;jsr r0,gtty / r1 will have offset to tty block, 4881 <1> ; / r2 has destination 4882 <1> ;mov rcsr(r1),(r2)+ / put reader control status 4883 <1> ; / in 1st word of dest 4884 <1> ;mov tcsr(r1),(r2)+ / put printer control status 4885 <1> ; / in 2nd word of dest 4886 <1> ;mov tty+4(r1),(r2)+ / put mode in 3rd word 4887 <1> ;jmp sysret2 / return to user 4888 <1> 4889 <1> ; Original UNIX v1 'gtty' routine: 4890 <1> ; gtty: 4891 <1> ;jsr r0,arg; u.off / put first arg in u.off 4892 <1> ;mov *u.r0,r1 / put file descriptor in r1 4893 <1> ;jsr r0,getf / get the i-number of the file 4894 <1> ;tst r1 / is it open for reading 4895 <1> ;bgt 1f / yes 4896 <1> ;neg r1 / no, i-number is negative, 4897 <1> ; / so make it positive 4898 <1> ;1: 4899 <1> ;sub $14.,r1 / get i-number of tty0 4900 <1> ;cmp r1,$ntty-1 / is there such a typewriter 4901 <1> ;bhis error9 / no, error 4902 <1> ;asl r1 / 0%2 4903 <1> ;asl r1 / 0%4 / yes 4904 <1> ;asl r1 / 0%8 / multiply by 8 so r1 points to 4905 <1> ; ; / tty block 4906 <1> ;mov u.off,r2 / put argument in r2 4907 <1> ;rts r0 / return 2077 %include 'u2.s' ; 11/05/2015 2078 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2079 <1> ; (re-write kernel for test by using previous version without a major defect) 2080 <1> ; **************************************************************************** 2081 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC 2082 <1> ; Last Modification: 10/01/2022 2083 <1> ; ---------------------------------------------------------------------------- 2084 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2085 <1> ; (v0.1 - Beginning: 11/07/2012) 2086 <1> ; 2087 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2088 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2089 <1> ; 2090 <1> ; 2091 <1> ; 2092 <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s 2093 <1> ; 2094 <1> ; **************************************************************************** 2095 <1> 2096 <1> ; temporary - 01/01/2022 2097 <1> %if 0 2098 <1> 2099 <1> syslink: 2100 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2101 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2102 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 2103 <1> ; 2104 <1> ; 'syslink' is given two arguments, name 1 and name 2. 2105 <1> ; name 1 is a file that already exists. name 2 is the name 2106 <1> ; given to the entry that will go in the current directory. 2107 <1> ; name2 will then be a link to the name 1 file. The i-number 2108 <1> ; in the name 2 entry of current directory is the same 2109 <1> ; i-number for the name 1 file. 2110 <1> ; 2111 <1> ; Calling sequence: 2112 <1> ; syslink; name 1; name 2 2113 <1> ; Arguments: 2114 <1> ; name 1 - file name to which link will be created. 2115 <1> ; name 2 - name of entry in current directory that 2116 <1> ; links to name 1. 2117 <1> ; Inputs: - 2118 <1> ; Outputs: - 2119 <1> ; ............................................................... 2120 <1> ; 2121 <1> ; Retro UNIX 8086 v1 modification: 2122 <1> ; 'syslink' system call has two arguments; so, 2123 <1> ; * 1st argument, name 1 is pointed to by BX register 2124 <1> ; * 2nd argument, name 2 is pointed to by CX register 2125 <1> ; 2126 <1> ; / name1, name2 2127 <1> ;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd 2128 <1> mov [u.namep], ebx 2129 <1> push ecx 2130 <1> call namei 2131 <1> ; jsr r0,namei / find the i-number associated with 2132 <1> ; / the 1st path name 2133 <1> ;;and ax, ax 2134 <1> ;;jz error ; File not found 2135 <1> ;jc error 2136 <1> ; br error9 / cannot be found 2137 <1> jnc short syslink0 2138 <1> ;pop ecx 2139 <1> ; 'file not found !' error 2140 <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 2141 <1> jmp error 2142 <1> syslink0: 2143 <1> call iget 2144 <1> ; jsr r0,iget / get the i-node into core 2145 <1> pop dword [u.namep] ; ecx 2146 <1> ; mov (sp)+,u.namep / u.namep points to 2nd name 2147 <1> ; 24/12/2021 2148 <1> push eax ; * 2149 <1> ;push ax 2150 <1> ; mov r1,-(sp) / put i-number of name1 on the stack 2151 <1> ; / (a link to this file is to be created) 2152 <1> ; 24/12/2021 2153 <1> mov cl, [cdev] 2154 <1> push ecx ; ** 2155 <1> ;push word [cdev] 2156 <1> ; mov cdev,-(sp) / put i-nodes device on the stack 2157 <1> call isdir 2158 <1> ; jsr r0,isdir / is it a directory 2159 <1> call namei 2160 <1> ; jsr r0,namei / no, get i-number of name2 2161 <1> ;jnc error 2162 <1> ; br .+4 / not found 2163 <1> ; / so r1 = i-number of current directory 2164 <1> ; / ii = i-number of current directory 2165 <1> ; br error9 / file already exists., error 2166 <1> jc short syslink1 2167 <1> ; pop eax ; 24/12/2021 2168 <1> ; pop eax 2169 <1> ; 'file exists !' error 2170 <1> mov dword [u.error], ERR_FILE_EXISTS ; 14 2171 <1> jmp error 2172 <1> syslink1: 2173 <1> ;pop cx 2174 <1> ; 24/12/2021 2175 <1> pop ecx ; ** 2176 <1> ;cmp cx, [cdev] 2177 <1> cmp cl, [cdev] 2178 <1> ;jne error 2179 <1> ; cmp (sp)+,cdev / u.dirp now points to 2180 <1> ; / end of current directory 2181 <1> ; bne error9 2182 <1> je short syslink2 2183 <1> ; 'not same drive !' error 2184 <1> mov dword [u.error], ERR_DRV_NOT_SAME ; 21 2185 <1> jmp error 2186 <1> syslink2: 2187 <1> ;pop eax ; 24/12/2021 2188 <1> ;push eax 2189 <1> ; 24/12/2021 2190 <1> mov eax, [esp] ; * 2191 <1> mov [u.dirbuf], ax 2192 <1> ; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf 2193 <1> call mkdir 2194 <1> ; jsr r0,mkdir / make directory entry for name2 2195 <1> ; / in current directory 2196 <1> ; 24/12/2021 2197 <1> pop eax ; * 2198 <1> ;pop ax 2199 <1> ; mov (sp)+,r1 / r1 has i-number of name1 2200 <1> call iget 2201 <1> ; jsr r0,iget / get i-node into core 2202 <1> inc byte [i.nlks] 2203 <1> ; incb i.nlks / add 1 to its number of links 2204 <1> call setimod 2205 <1> ; jsr r0,setimod / set the i-node modified flag 2206 <1> jmp sysret 2207 <1> 2208 <1> isdir: 2209 <1> ; 08/01/2022 2210 <1> ; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode) 2211 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 2212 <1> ; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 2213 <1> ; 2214 <1> ; 'isdir' check to see if the i-node whose i-number is in r1 2215 <1> ; is a directory. If it is, an error occurs, because 'isdir' 2216 <1> ; called by syslink and sysunlink to make sure directories 2217 <1> ; are not linked. If the user is the super user (u.uid=0), 2218 <1> ; 'isdir' does not bother checking. The current i-node 2219 <1> ; is not disturbed. 2220 <1> ; 2221 <1> ; INPUTS -> 2222 <1> ; r1 - contains the i-number whose i-node is being checked. 2223 <1> ; u.uid - user id 2224 <1> ; OUTPUTS -> 2225 <1> ; r1 - contains current i-number upon exit 2226 <1> ; (current i-node back in core) 2227 <1> ; 2228 <1> ; ((AX = R1)) 2229 <1> ; 2230 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 2231 <1> ; 2232 <1> 2233 <1> ; / if the i-node whose i-number is in r1 is a directory 2234 <1> ; / there is an error unless super user made the call 2235 <1> 2236 <1> ; 01/01/2022 2237 <1> cmp word [u.uid], 0 ; 16 bit uid (runix v2 fs inode) 2238 <1> ;cmp byte [u.uid], 0 2239 <1> ; tstb u.uid / super user 2240 <1> jna short isdir1 2241 <1> ; beq 1f / yes, don't care 2242 <1> ; 08/01/2022 2243 <1> push dword [ii] 2244 <1> ;push word [ii] 2245 <1> ; mov ii,-(sp) / put current i-number on stack 2246 <1> call iget 2247 <1> ; jsr r0,iget / get i-node into core (i-number in r1) 2248 <1> ; 01/01/2022 (runix v2 fs inode flag) 2249 <1> test byte [i.flgs+1], 80h ; regular file ? 2250 <1> jz short isdir2 ; no, error! 2251 <1> test byte [i.flgs+1], 40h ; directory flag 2252 <1> ;test word [i.flgs], 4000h ; Bit 14 : Directory flag 2253 <1> ; bit $40000,i.flgs / is it a directory 2254 <1> ;jnz error 2255 <1> ; bne error9 / yes, error 2256 <1> jz short isdir0 2257 <1> isdir2: 2258 <1> mov dword [u.error], ERR_NOT_FILE ; 11 ; ERR_DIR_ACCESS 2259 <1> ; 'permission denied !' error 2260 <1> ;pop ax 2261 <1> jmp error 2262 <1> isdir0: 2263 <1> ; 08/01/2022 2264 <1> pop eax 2265 <1> ;pop ax 2266 <1> ; mov (sp)+,r1 / no, put current i-number in r1 (ii) 2267 <1> call iget 2268 <1> ; jsr r0,iget / get it back in 2269 <1> isdir1: ; 1: 2270 <1> retn 2271 <1> ; rts r0 2272 <1> 2273 <1> sysunlink: 2274 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 2275 <1> ; 04/12/2015 (14 byte file names) 2276 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2277 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 2278 <1> ; 2279 <1> ; 'sysunlink' removes the entry for the file pointed to by 2280 <1> ; name from its directory. If this entry was the last link 2281 <1> ; to the file, the contents of the file are freed and the 2282 <1> ; file is destroyed. If, however, the file was open in any 2283 <1> ; process, the actual destruction is delayed until it is 2284 <1> ; closed, even though the directory entry has disappeared. 2285 <1> ; 2286 <1> ; The error bit (e-bit) is set to indicate that the file 2287 <1> ; does not exist or that its directory can not be written. 2288 <1> ; Write permission is not required on the file itself. 2289 <1> ; It is also illegal to unlink a directory (except for 2290 <1> ; the superuser). 2291 <1> ; 2292 <1> ; Calling sequence: 2293 <1> ; sysunlink; name 2294 <1> ; Arguments: 2295 <1> ; name - name of directory entry to be removed 2296 <1> ; Inputs: - 2297 <1> ; Outputs: - 2298 <1> ; ............................................................... 2299 <1> ; 2300 <1> ; Retro UNIX 8086 v1 modification: 2301 <1> ; The user/application program puts address of the name 2302 <1> ; in BX register as 'sysunlink' system call argument. 2303 <1> 2304 <1> ; / name - remove link name 2305 <1> mov [u.namep], ebx 2306 <1> ;jsr r0,arg; u.namep / u.namep points to name 2307 <1> call namei 2308 <1> ; jsr r0,namei / find the i-number associated 2309 <1> ; / with the path name 2310 <1> ;jc error 2311 <1> ; br error9 / not found 2312 <1> jnc short sysunlink1 2313 <1> ; 'file not found !' error 2314 <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 2315 <1> jmp error 2316 <1> sysunlink1: 2317 <1> push eax ; 24/12/2021 2318 <1> ;push ax 2319 <1> ; mov r1,-(sp) / put its i-number on the stack 2320 <1> call isdir 2321 <1> ; jsr r0,isdir / is it a directory 2322 <1> ;xor ax, ax 2323 <1> ; 24/12/2021 2324 <1> xor eax, eax 2325 <1> mov [u.dirbuf], ax ; 0 2326 <1> ; clr u.dirbuf / no, clear the location that will 2327 <1> ; / get written into the i-number portion 2328 <1> ; / of the entry 2329 <1> sub dword [u.off], 16 ; 04/12/2015 (10 -> 16) 2330 <1> ; sub $10.,u.off / move u.off back 1 directory entry 2331 <1> call wdir 2332 <1> ; jsr r0,wdir / free the directory entry 2333 <1> pop eax ; 24/12/2021 2334 <1> ;pop ax 2335 <1> ; mov (sp)+,r1 / get i-number back 2336 <1> call iget 2337 <1> ; jsr r0,iget / get i-node 2338 <1> call setimod 2339 <1> ; jsr r0,setimod / set modified flag 2340 <1> dec byte [i.nlks] 2341 <1> ; decb i.nlks / decrement the number of links 2342 <1> ; 24/12/2021 2343 <1> jnz short sysunlink_2 2344 <1> ;jnz sysret 2345 <1> ; bgt sysret9 / if this was not the last link 2346 <1> ; / to file return 2347 <1> ; AX = r1 = i-number 2348 <1> call anyi 2349 <1> ; jsr r0,anyi / if it was, see if anyone has it open. 2350 <1> ; / Then free contents of file and destroy it. 2351 <1> sysunlink_2: 2352 <1> jmp sysret 2353 <1> ; br sysret9 2354 <1> 2355 <1> mkdir: 2356 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 2357 <1> ; 04/12/2015 (14 byte directory names) 2358 <1> ; 12/10/2015 2359 <1> ; 17/06/2015 (Retro UNIX 386 v1 - Beginning) 2360 <1> ; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2361 <1> ; 2362 <1> ; 'mkdir' makes a directory entry from the name pointed to 2363 <1> ; by u.namep into the current directory. 2364 <1> ; 2365 <1> ; INPUTS -> 2366 <1> ; u.namep - points to a file name 2367 <1> ; that is about to be a directory entry. 2368 <1> ; ii - current directory's i-number. 2369 <1> ; OUTPUTS -> 2370 <1> ; u.dirbuf+2 - u.dirbuf+10 - contains file name. 2371 <1> ; u.off - points to entry to be filled 2372 <1> ; in the current directory 2373 <1> ; u.base - points to start of u.dirbuf. 2374 <1> ; r1 - contains i-number of current directory 2375 <1> ; 2376 <1> ; ((AX = R1)) output 2377 <1> ; 2378 <1> ; (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM) 2379 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 2380 <1> ; 2381 <1> 2382 <1> ; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 2383 <1> xor eax, eax 2384 <1> mov edi, u.dirbuf+2 2385 <1> mov esi, edi 2386 <1> stosd 2387 <1> stosd 2388 <1> ; 04/12/2015 (14 byte directory names) 2389 <1> stosd 2390 <1> stosw 2391 <1> ; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this 2392 <1> mov edi, esi ; offset to u.dirbuf 2393 <1> ; 12/10/2015 ([u.namep] -> ebp) 2394 <1> ;mov ebp, [u.namep] 2395 <1> call trans_addr_nmbp ; convert virtual address to physical 2396 <1> ; esi = physical address (page start + offset) 2397 <1> ; ecx = byte count in the page (1 - 4096) 2398 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 2399 <1> ; mov u.namep,r2 / r2 points to name of directory entry 2400 <1> ; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 2401 <1> mkdir_1: ; 1: 2402 <1> inc ebp ; 12/10/2015 2403 <1> ; 2404 <1> ; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 2405 <1> ; 01/08/2013 2406 <1> lodsb 2407 <1> ; movb (r2)+,r1 / move character in name to r1 2408 <1> and al, al 2409 <1> jz short mkdir_3 2410 <1> ; beq 1f / if null, done 2411 <1> cmp al, '/' 2412 <1> ; cmp r1,$'/ / is it a "/"? 2413 <1> je short mkdir_err 2414 <1> ;je error 2415 <1> ; beq error9 / yes, error 2416 <1> ; 12/10/2015 2417 <1> ;dec cx 2418 <1> dec ecx ; 24/12/2021 2419 <1> jnz short mkdir_2 2420 <1> ; 12/10/2015 ([u.namep] -> ebp) 2421 <1> call trans_addr_nm ; convert virtual address to physical 2422 <1> ; esi = physical address (page start + offset) 2423 <1> ; ecx = byte count in the page 2424 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 2425 <1> mkdir_2: 2426 <1> cmp edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 2427 <1> ; cmp r3,$u.dirbuf+10. / have we reached the last slot for 2428 <1> ; / a char? 2429 <1> je short mkdir_1 2430 <1> ; beq 1b / yes, go back 2431 <1> stosb 2432 <1> ; movb r1,(r3)+ / no, put the char in the u.dirbuf 2433 <1> jmp short mkdir_1 2434 <1> ; br 1b / get next char 2435 <1> mkdir_err: 2436 <1> ; 17/06/2015 2437 <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 2438 <1> jmp error 2439 <1> 2440 <1> mkdir_3: ; 1: 2441 <1> mov eax, [u.dirp] 2442 <1> mov [u.off], eax 2443 <1> ; mov u.dirp,u.off / pointer to empty current directory 2444 <1> ; / slot to u.off 2445 <1> ; 08/01/2022 2446 <1> wdir: ; 24/12/2021 (Retro UNIX 386 v1.2) 2447 <1> ; 29/04/2013 2448 <1> mov dword [u.base], u.dirbuf 2449 <1> ; mov $u.dirbuf,u.base / u.base points to created file name 2450 <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 2451 <1> ; mov $10.,u.count / u.count = 10 2452 <1> ; 08/01/2022 2453 <1> mov eax, [ii] 2454 <1> ;mov ax, [ii] 2455 <1> ; mov ii,r1 / r1 has i-number of current directory 2456 <1> ;mov dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification ! 2457 <1> ; 08/01/2022 (Retro UNIX 386 v2 file system inode) 2458 <1> mov dx, 80h ; mov dx, IWRITE 2459 <1> call access 2460 <1> ; jsr r0,access; 1 / get i-node and set its file up 2461 <1> ; / for writing 2462 <1> ; AX = i-number of current directory 2463 <1> ; 01/08/2013 2464 <1> inc byte [u.kcall] ; the caller is 'mkdir' sign 2465 <1> ;call writei 2466 <1> ; ; jsr r0,writei / write into directory 2467 <1> ;retn 2468 <1> ; ; rts r0 2469 <1> ; 24/12/2021 2470 <1> jmp writei 2471 <1> 2472 <1> %endif 2473 <1> 2474 <1> ; 01/01/2022 2475 <1> ; 24/12/2021 2476 <1> ; 11/12/2021 2477 <1> ; 04/12/2021 2478 <1> ; 30/11/2021 2479 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2480 <1> sysexec: 2481 <1> ; 02/05/2021 2482 <1> ; 27/03/2021 2483 <1> ; 26/03/2021 2484 <1> ; 25/03/2021 (Retro UNIX 386 v2 - Beginning) 2485 <1> ; 23/10/2015 2486 <1> ; 10/10/2015, 18/10/2015, 19/10/2015 2487 <1> ; 29/07/2015, 05/08/2015, 05/08/2015 2488 <1> ; 21/07/2015, 24/07/2015, 25/07/2015 2489 <1> ; 01/07/2015, 02/07/2015, 20/07,2015 2490 <1> ; 24/06/2015, 25/06/2021 2491 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2492 <1> ; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2493 <1> ; 2494 <1> ; 'sysexec' initiates execution of a file whose path name if 2495 <1> ; pointed to by 'name' in the sysexec call. 2496 <1> ; 'sysexec' performs the following operations: 2497 <1> ; 1. obtains i-number of file to be executed via 'namei'. 2498 <1> ; 2. obtains i-node of file to be executed via 'iget'. 2499 <1> ; 3. sets trap vectors to system routines. 2500 <1> ; 4. loads arguments to be passed to executing file into 2501 <1> ; highest locations of user's core 2502 <1> ; 5. puts pointers to arguments in locations immediately 2503 <1> ; following arguments. 2504 <1> ; 6. saves number of arguments in next location. 2505 <1> ; 7. initializes user's stack area so that all registers 2506 <1> ; will be zeroed and the PS is cleared and the PC set 2507 <1> ; to core when 'sysret' restores registers 2508 <1> ; and does an rti. 2509 <1> ; 8. inializes u.r0 and u.sp 2510 <1> ; 9. zeros user's core down to u.r0 2511 <1> ; 10. reads executable file from storage device into core 2512 <1> ; starting at location 'core'. 2513 <1> ; 11. sets u.break to point to end of user's code with 2514 <1> ; data area appended. 2515 <1> ; 12. calls 'sysret' which returns control at location 2516 <1> ; 'core' via 'rti' instruction. 2517 <1> ; 2518 <1> ; Calling sequence: 2519 <1> ; sysexec; namep; argp 2520 <1> ; Arguments: 2521 <1> ; namep - points to pathname of file to be executed 2522 <1> ; argp - address of table of argument pointers 2523 <1> ; argp1... argpn - table of argument pointers 2524 <1> ; argp1:<...0> ... argpn:<...0> - argument strings 2525 <1> ; Inputs: (arguments) 2526 <1> ; Outputs: - 2527 <1> ; ............................................................... 2528 <1> ; 2529 <1> ; Retro UNIX 386 v1 modification: 2530 <1> ; User application runs in it's own virtual space 2531 <1> ; which is izolated from kernel memory (and other 2532 <1> ; memory pages) via 80386 paging in ring 3 2533 <1> ; privilige mode. Virtual start address is always 0. 2534 <1> ; User's core memory starts at linear address 400000h 2535 <1> ; (the end of the 1st 4MB). 2536 <1> ; 2537 <1> ; Retro UNIX 8086 v1 modification: 2538 <1> ; user/application segment and system/kernel segment 2539 <1> ; are different and sysenter/sysret/sysrele routines 2540 <1> ; are different (user's registers are saved to 2541 <1> ; and then restored from system's stack.) 2542 <1> ; 2543 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 2544 <1> ; arguments which were in these registers; 2545 <1> ; but, it returns by putting the 1st argument 2546 <1> ; in 'u.namep' and the 2nd argument 2547 <1> ; on top of stack. (1st argument is offset of the 2548 <1> ; file/path name in the user's program segment.) 2549 <1> 2550 <1> ;call arg2 2551 <1> ; * name - 'u.namep' points to address of file/path name 2552 <1> ; in the user's program segment ('u.segmnt') 2553 <1> ; with offset in BX register (as sysopen argument 1). 2554 <1> ; * argp - sysexec argument 2 is in CX register 2555 <1> ; which is on top of stack. 2556 <1> ; 2557 <1> ; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack 2558 <1> 2559 <1> ; 23/06/2015 (32 bit modifications) 2560 <1> 2561 000043F9 891D[C06E0000] <1> mov [u.namep], ebx ; argument 1 2562 <1> ; 18/10/2015 2563 000043FF 890D[346F0000] <1> mov [argv], ecx ; * ; argument 2 2564 00004405 E8D8040000 <1> call namei 2565 <1> ; jsr r0,namei / namei returns i-number of file 2566 <1> ; / named in sysexec call in r1 2567 <1> ;jc error 2568 <1> ; br error9 2569 0000440A 730F <1> jnc short sysexec_0 2570 <1> ; 2571 <1> ; 'file not found !' error 2572 0000440C C705[186F0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND 2572 00004414 0000 <1> 2573 00004416 E991F7FFFF <1> jmp error 2574 <1> 2575 <1> ; 26/03/2021 - Retro UNIX 386 v2 2576 <1> ; (executable file flag is checked in 'access') 2577 <1> ; (following error message is in 'access' subroutine) 2578 <1> ;sysexec_not_exf: 2579 <1> ;; 'not executable file !' error 2580 <1> ;mov dword [u.error], ERR_NOT_EXECUTABLE 2581 <1> ;jmp error 2582 <1> sysexec_0: 2583 <1> ; 26/03/2021 ('iget' will be called in 'access') 2584 <1> ;call iget 2585 <1> ; ; jsr r0,iget / get i-node for file to be executed 2586 <1> ; 2587 <1> ;test byte [i.flgs], 10h 2588 <1> ;;test word [i.flgs], 10h 2589 <1> ; ; bit $20,i.flgs / is file executable 2590 <1> ;jz short sysexec_not_exf 2591 <1> ;;jz error 2592 <1> ; ; beq error9 2593 <1> ; 26/03/2021 2594 0000441B 66BA4000 <1> mov dx, 40h ; IEXEC - execute, owner 2595 0000441F E8360F0000 <1> call access 2596 <1> ; ! we are here because there is execute permission ! 2597 <1> ; ('iopen' is not needed for regular files, from now on) 2598 <1> 2599 <1> ; 26/03/2021 2600 <1> ;; 25/03/2021 2601 <1> ;; (ref: Retro UNIX 386 v2, 'ux.s') 2602 <1> ;mov dx, 40h ; IEXEC - execute, owner 2603 <1> ;; 2604 <1> ;call iopen 2605 <1> ; ; jsr r0,iopen / gets i-node for file with i-number 2606 <1> ; ; / given in r1 (opens file) 2607 <1> 2608 <1> ; 26/03/2021 2609 <1> ; AX = i-number of the file 2610 <1> ;test byte [i.flgs], 20h 2611 <1> ;;test word [i.flgs], 20h 2612 <1> ; ; bit $40,i.flgs / test user id on execution bit 2613 <1> ;jz short sysexec_1 2614 <1> ; ; beq 1f 2615 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 2616 <1> ; ; tstb u.uid / test user id 2617 <1> ;jna short sysexec_1 2618 <1> ; ; beq 1f / super user 2619 <1> 2620 <1> ;mov cl, [i.uid] 2621 <1> ;mov [u.uid], cl ; 02/08/2013 2622 <1> ; ; movb i.uid,u.uid / put user id of owner of file 2623 <1> ; / as process user id 2624 <1> ; 26/03/2021 - Retro UNIX 386 v2 2625 <1> ;mov al, [i.flgs+1] 2626 00004424 66833D[F66E0000]00 <1> cmp word [u.uid], 0 ; super user (root) ? 2627 <1> ;jna short sysexec_19 ; yes, super user 2628 <1> ;; 02/05/2021 2629 0000442C 7625 <1> jna short sysexec_1 ; don't set UID or GID 2630 <1> 2631 <1> ; 01/01/2022 - Retro UNIX 386 v1.2 2632 0000442E A0[416B0000] <1> mov al, [i.flgs+1] 2633 <1> 2634 <1> ; test set user id on execution bit 2635 00004433 A808 <1> test al, 08h ; ISUID flag (800h) 2636 <1> ;jz short sysexec_19 2637 <1> ; 02/05/2021 2638 00004435 741C <1> jz short sysexec_1 ; do not set group ID 2639 <1> ; (if user ID will not be set) 2640 <1> ; (02/05/2021) 2641 <1> ; set user id on exec (800h) 2642 <1> ; 26/03/2021 2643 <1> sysexec_setuid: 2644 <1> ;; 27/03/2021 2645 <1> ;cmp word [u.uid], 0 2646 <1> ;;jna short sysexec_19 ; super user 2647 <1> ;; 02/05/2021 2648 <1> ;jna short sysexec_1 ; do not set group ID 2649 <1> ; ; (if user ID will not be set) 2650 <1> ; ; (02/05/2021) 2651 00004437 668B0D[446B0000] <1> mov cx, [i.uid] 2652 0000443E 66890D[F66E0000] <1> mov [u.uid], cx 2653 <1> sysexec_19: 2654 <1> ; test set group id on execution bit 2655 00004445 A804 <1> test al, 04h ; ISGID flag (400h) 2656 00004447 740A <1> jz short sysexec_1 2657 <1> sysexec_setgid: 2658 <1> ; set group id on exec (400h) 2659 00004449 A0[466B0000] <1> mov al, [i.gid] 2660 0000444E A2[FA6E0000] <1> mov [u.gid], al 2661 <1> ; 2662 <1> sysexec_1: 2663 <1> ; 24/12/2021 2664 <1> ; 11/12/2021 2665 <1> ; 04/12/2021 2666 <1> ; 18/10/2015 2667 <1> ; 10/10/2015 2668 <1> ; 24/07/2015 2669 <1> ; 21/07/2015 2670 <1> ; 25/06/2015 2671 <1> ; 24/06/2015 2672 <1> ; Moving arguments to the end of [u.upage] 2673 <1> ; (by regarding page borders in user's memory space) 2674 <1> ; 2675 <1> ; 10/10/2015 2676 <1> ; 21/07/2015 2677 00004453 89E5 <1> mov ebp, esp ; (**) 2678 <1> ; 18/10/2015 2679 00004455 89EF <1> mov edi, ebp 2680 00004457 B900010000 <1> mov ecx, MAX_ARG_LEN ; 256 2681 <1> ;sub edi, MAX_ARG_LEN ; 256 2682 0000445C 29CF <1> sub edi, ecx 2683 0000445E 89FC <1> mov esp, edi 2684 00004460 31C0 <1> xor eax, eax 2685 00004462 A3[D06E0000] <1> mov [u.nread], eax ; 0 2686 00004467 49 <1> dec ecx ; 256 - 1 2687 00004468 890D[CC6E0000] <1> mov [u.count], ecx ; MAX_ARG_LEN - 1 ; 255 2688 <1> ;mov dword [u.count], MAX_ARG_LEN - 1 ; 255 2689 <1> ; 24/12/2021 2690 <1> sysexec_2: 2691 0000446E 8B35[346F0000] <1> mov esi, [argv] ; 18/10/2015 2692 00004474 E85A020000 <1> call get_argp 2693 00004479 B904000000 <1> mov ecx, 4 ; mov ecx, 4 2694 <1> sysexec_3: 2695 0000447E 21C0 <1> and eax, eax 2696 00004480 7454 <1> jz short sysexec_6 2697 <1> ; 18/10/2015 2698 00004482 010D[346F0000] <1> add [argv], ecx ; 4 2699 <1> ;inc word [argc] 2700 <1> ; 11/12/2021 2701 00004488 FF05[306F0000] <1> inc dword [argc] 2702 <1> ; 2703 0000448E A3[C86E0000] <1> mov [u.base], eax 2704 <1> ; 23/10/2015 2705 00004493 66C705[106F0000]00- <1> mov word [u.pcount], 0 2705 0000449B 00 <1> 2706 <1> sysexec_4: 2707 0000449C E8EA140000 <1> call cpass ; get a character from user's core memory 2708 000044A1 750B <1> jnz short sysexec_5 2709 <1> ; (max. 255 chars + null) 2710 <1> ; 18/10/2015 2711 000044A3 28C0 <1> sub al, al 2712 000044A5 AA <1> stosb 2713 000044A6 FF05[D06E0000] <1> inc dword [u.nread] 2714 000044AC EB28 <1> jmp short sysexec_6 2715 <1> sysexec_5: 2716 000044AE AA <1> stosb 2717 000044AF 20C0 <1> and al, al 2718 000044B1 75E9 <1> jnz short sysexec_4 2719 000044B3 B904000000 <1> mov ecx, 4 2720 000044B8 390D[2C6F0000] <1> cmp [ncount], ecx ; 4 2721 000044BE 72AE <1> jb short sysexec_2 2722 000044C0 8B35[286F0000] <1> mov esi, [nbase] 2723 000044C6 010D[286F0000] <1> add [nbase], ecx ; 4 2724 <1> ;sub [ncount], cx 2725 <1> ; 11/12/2021 2726 000044CC 290D[2C6F0000] <1> sub [ncount], ecx 2727 000044D2 8B06 <1> mov eax, [esi] 2728 000044D4 EBA8 <1> jmp short sysexec_3 2729 <1> sysexec_6: 2730 <1> ; 24/12/2021 2731 <1> ; 18/10/2015 2732 <1> ; argument list transfer from user's core memory to 2733 <1> ; kernel stack frame is OK here. 2734 <1> ; [u.nread] = ; argument list length 2735 <1> ;mov [argv], esp ; start address of argument list 2736 <1> ; 2737 <1> ; 18/10/2015 2738 <1> ; 24/07/2015 2739 <1> ; 21/07/2015 2740 <1> ; 02/07/2015 2741 <1> ; 25/06/2015 2742 <1> ; 24/06/2015 2743 <1> ; 23/06/2015 2744 <1> ; 2745 000044D6 8B1D[086F0000] <1> mov ebx, [u.ppgdir] ; parent's page directory 2746 000044DC 21DB <1> and ebx, ebx ; /etc/init ? (u.ppgdir = 0) 2747 000044DE 740A <1> jz short sysexec_7 2748 000044E0 A1[046F0000] <1> mov eax, [u.pgdir] ; physical address of page directory 2749 000044E5 E8AEEAFFFF <1> call deallocate_page_dir 2750 <1> sysexec_7: 2751 000044EA E8DEE9FFFF <1> call make_page_dir 2752 <1> ;jc short sysexec_14 2753 <1> ;jc panic ; allocation error 2754 <1> ; ; after a deallocation would be nonsence !? 2755 <1> ; 26/03/2021 2756 000044EF 7243 <1> jc short sysexec_panic 2757 <1> 2758 <1> ; 24/07/2015 2759 <1> ; map kernel pages (1st 4MB) to PDE 0 2760 <1> ; of the user's page directory 2761 <1> ; (It is needed for interrupts!) 2762 <1> ; 18/10/2015 2763 000044F1 8B15[A86D0000] <1> mov edx, [k_page_dir] ; Kernel's page directory 2764 000044F7 8B02 <1> mov eax, [edx] ; physical address of 2765 <1> ; kernel's first page table (1st 4 MB) 2766 <1> ; (PDE 0 of kernel's page directory) 2767 000044F9 8B15[046F0000] <1> mov edx, [u.pgdir] 2768 000044FF 8902 <1> mov [edx], eax ; PDE 0 (1st 4MB) 2769 <1> ; 2770 <1> ; 20/07/2015 2771 00004501 BB00004000 <1> mov ebx, CORE ; start address = 0 (virtual) + CORE 2772 <1> ; 18/10/2015 2773 00004506 BE[206F0000] <1> mov esi, pcore ; physical start address 2774 <1> sysexec_8: 2775 0000450B B907000000 <1> mov ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT 2776 00004510 E8D6E9FFFF <1> call make_page_table 2777 <1> ;jc panic 2778 <1> ; 26/03/2021 2779 00004515 721D <1> jc short sysexec_panic 2780 <1> ; 2781 <1> ;mov ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT 2782 00004517 E8DDE9FFFF <1> call make_page ; make new page, clear and set the pte 2783 <1> ;jc panic 2784 <1> ; 26/03/2021 2785 0000451C 7216 <1> jc short sysexec_panic 2786 <1> ; 2787 0000451E 8906 <1> mov [esi], eax ; 24/06/2015 2788 <1> ; ebx = virtual address (24/07/2015) 2789 <1> ; 30/11/2021 2790 <1> ;call add_to_swap_queue 2791 <1> ; 18/10/2015 2792 00004520 81FE[246F0000] <1> cmp esi, ecore ; user's stack (last) page ? 2793 00004526 7411 <1> je short sysexec_9 ; yes 2794 00004528 BE[246F0000] <1> mov esi, ecore ; physical address of the last page 2795 <1> ; 20/07/2015 2796 0000452D BB00F0FFFF <1> mov ebx, (ECORE - PAGE_SIZE) + CORE 2797 <1> ; ebx = virtual end address + segment base address - 4K 2798 00004532 EBD7 <1> jmp short sysexec_8 2799 <1> sysexec_panic: 2800 <1> ; 26/03/2021 2801 00004534 E90BEFFFFF <1> jmp panic 2802 <1> 2803 <1> sysexec_9: 2804 <1> ; 11/12/2021 2805 <1> ; 18/10/2015 2806 <1> ; 26/08/2015 2807 <1> ; 25/06/2015 2808 <1> ; move arguments from kernel stack to [ecore] 2809 <1> ; (argument list/line will be copied from kernel stack 2810 <1> ; frame to the last (stack) page of user's core memory) 2811 <1> ; 18/10/2015 2812 00004539 8B3D[246F0000] <1> mov edi, [ecore] 2813 0000453F 81C700100000 <1> add edi, PAGE_SIZE 2814 <1> ;movzx eax, word [argc] 2815 <1> ; 11/12/2021 2816 00004545 A1[306F0000] <1> mov eax, [argc] 2817 0000454A 09C0 <1> or eax, eax 2818 0000454C 7509 <1> jnz short sysexec_10 2819 0000454E 89FB <1> mov ebx, edi 2820 00004550 83EB04 <1> sub ebx, 4 2821 00004553 8903 <1> mov [ebx], eax ; 0 2822 00004555 EB40 <1> jmp short sysexec_13 2823 <1> sysexec_10: 2824 00004557 8B0D[D06E0000] <1> mov ecx, [u.nread] 2825 <1> ;mov esi, [argv] 2826 0000455D 89E6 <1> mov esi, esp ; start address of argument list 2827 0000455F 29CF <1> sub edi, ecx ; page end address - argument list length 2828 00004561 89C2 <1> mov edx, eax 2829 00004563 FEC2 <1> inc dl ; argument count + 1 for argc value 2830 00004565 C0E202 <1> shl dl, 2 ; 4 * (argument count + 1) 2831 00004568 89FB <1> mov ebx, edi 2832 0000456A 80E3FC <1> and bl, 0FCh ; 32 bit (dword) alignment 2833 0000456D 29D3 <1> sub ebx, edx 2834 0000456F 89FA <1> mov edx, edi 2835 00004571 F3A4 <1> rep movsb 2836 00004573 89D6 <1> mov esi, edx 2837 00004575 89DF <1> mov edi, ebx 2838 00004577 BA00F0BFFF <1> mov edx, ECORE - PAGE_SIZE ; virtual addr. of the last page 2839 0000457C 2B15[246F0000] <1> sub edx, [ecore] ; difference (virtual - physical) 2840 00004582 AB <1> stosd ; eax = argument count 2841 <1> sysexec_11: 2842 00004583 89F0 <1> mov eax, esi 2843 00004585 01D0 <1> add eax, edx 2844 00004587 AB <1> stosd ; eax = virtual address 2845 00004588 FE0D[306F0000] <1> dec byte [argc] 2846 0000458E 7407 <1> jz short sysexec_13 2847 <1> sysexec_12: 2848 00004590 AC <1> lodsb 2849 00004591 20C0 <1> and al, al 2850 00004593 75FB <1> jnz short sysexec_12 2851 00004595 EBEC <1> jmp short sysexec_11 2852 <1> ; 2853 <1> ; 1: 2854 <1> ; mov (sp)+,r5 / r5 now contains address of list of 2855 <1> ; / pointers to arguments to be passed 2856 <1> ; mov $1,u.quit / u.quit determines handling of quits; 2857 <1> ; / u.quit = 1 take quit 2858 <1> ; mov $1,u.intr / u.intr determines handling of 2859 <1> ; / interrupts; u.intr = 1 take interrupt 2860 <1> ; mov $rtssym,30 / emt trap vector set to take 2861 <1> ; / system routine 2862 <1> ; mov $fpsym,*10 / reserved instruction trap vector 2863 <1> ; / set to take system routine 2864 <1> ; mov $sstack,sp / stack space used during swapping 2865 <1> ; mov r5,-(sp) / save arguments pointer on stack 2866 <1> ; mov $ecore,r5 / r5 has end of core 2867 <1> ; mov $core,r4 / r4 has start of users core 2868 <1> ; mov r4,u.base / u.base has start of users core 2869 <1> ; mov (sp),r2 / move arguments list pointer into r2 2870 <1> ; 1: 2871 <1> ; tst (r2)+ / argument char = "nul" 2872 <1> ; bne 1b 2873 <1> ; tst -(r2) / decrement r2 by 2; r2 has addr of 2874 <1> ; / end of argument pointer list 2875 <1> ; 1: 2876 <1> ; / move arguments to bottom of users core 2877 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 2878 <1> ; cmp r2,(sp) / is r2 = beginning of argument 2879 <1> ; / ptr list 2880 <1> ; blo 1f / branch to 1f when all arguments 2881 <1> ; / are moved 2882 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 2883 <1> ; 2: 2884 <1> ; tstb (r3)+ 2885 <1> ; bne 2b / scan argument for \0 (nul) 2886 <1> 2887 <1> ; 2: 2888 <1> ; movb -(r3),-(r5) / move argument char 2889 <1> ; / by char starting at "ecore" 2890 <1> ; cmp r3,(r2) / moved all characters in 2891 <1> ; / this argument 2892 <1> ; bhi 2b / branch 2b if not 2893 <1> ; mov r5,(r4)+ / move r5 into top of users core; 2894 <1> ; / r5 has pointer to nth arg 2895 <1> ; br 1b / string 2896 <1> ; 1: 2897 <1> ; clrb -(r5) 2898 <1> ; bic $1,r5 / make r5 even, r5 points to 2899 <1> ; / last word of argument strings 2900 <1> ; mov $core,r2 2901 <1> 2902 <1> ; 1: / move argument pointers into core following 2903 <1> ; / argument strings 2904 <1> ; cmp r2,r4 2905 <1> ; bhis 1f / branch to 1f when all pointers 2906 <1> ; / are moved 2907 <1> ; mov (r2)+,-(r5) 2908 <1> ; br 1b 2909 <1> ; 1: 2910 <1> ; sub $core,r4 / gives number of arguments *2 2911 <1> ; asr r4 / divide r4 by 2 to calculate 2912 <1> ; / the number of args stored 2913 <1> ; mov r4,-(r5) / save number of arguments ahead 2914 <1> ; / of the argument pointers 2915 <1> sysexec_13: 2916 <1> ; 30/11/2021 2917 <1> ; 28/11/2021 2918 <1> ; 19/10/2015 2919 <1> ; 18/10/2015 2920 <1> ; 29/07/2015 2921 <1> ; 25/07/2015 2922 <1> ; 24/07/2015 2923 <1> ; 20/07/2015 2924 <1> ; 25/06/2015 2925 <1> ; 24/06/2015 2926 <1> ; 23/06/2015 2927 <1> ; 2928 <1> ; moving arguments to [ecore] is OK here.. 2929 <1> ; 18/10/2015 2930 00004597 89EC <1> mov esp, ebp ; (**) restore kernel stack pointer 2931 <1> ; ebx = beginning address of argument list pointers 2932 <1> ; in user's stack 2933 <1> ; 19/10/2015 2934 00004599 2B1D[246F0000] <1> sub ebx, [ecore] 2935 0000459F 81C300F0BFFF <1> add ebx, (ECORE - PAGE_SIZE) 2936 <1> ; end of core - 4096 (last page) 2937 <1> ; (virtual address) 2938 000045A5 891D[346F0000] <1> mov [argv], ebx 2939 000045AB 891D[D46E0000] <1> mov [u.break], ebx ; available user memory 2940 <1> ; 2941 000045B1 29C0 <1> sub eax, eax 2942 000045B3 C705[CC6E0000]2000- <1> mov dword [u.count], 32 ; Executable file header size 2942 000045BB 0000 <1> 2943 <1> ; mov $14,u.count 2944 000045BD C705[B86E0000]- <1> mov dword [u.fofp], u.off 2944 000045C3 [C46E0000] <1> 2945 <1> ; mov $u.off,u.fofp 2946 000045C7 A3[C46E0000] <1> mov [u.off], eax ; 0 2947 <1> ; clr u.off / set offset in file to be read to zero 2948 <1> ; 25/07/2015 2949 000045CC A3[C86E0000] <1> mov [u.base], eax ; 0, start of user's core (virtual) 2950 <1> ; 25/06/2015 2951 000045D1 A1[806E0000] <1> mov eax, [ii] ; 28/11/2021 (32 bit inode number) 2952 <1> ; AX = i-number of the executable file 2953 000045D6 E8E40F0000 <1> call readi 2954 <1> ; jsr r0,readi / read in first six words of 2955 <1> ; / user's file, starting at $core 2956 <1> ; mov sp,r5 / put users stack address in r5 2957 <1> ; sub $core+40.,r5 / subtract $core +40, 2958 <1> ; / from r5 (leaves number of words 2959 <1> ; / less 26 available for 2960 <1> ; / program in user core 2961 <1> ; mov r5,u.count / 2962 <1> ; 25/06/2015 2963 000045DB 8B0D[D46E0000] <1> mov ecx, [u.break] ; top of user's stack (physical addr.) 2964 000045E1 890D[CC6E0000] <1> mov [u.count], ecx ; save for overrun check 2965 <1> ; 2966 000045E7 8B0D[D06E0000] <1> mov ecx, [u.nread] 2967 000045ED 890D[D46E0000] <1> mov [u.break], ecx ; virtual address (offset from start) 2968 000045F3 80F920 <1> cmp cl, 32 2969 000045F6 7540 <1> jne short sysexec_15 2970 <1> ;: 2971 <1> ; 25/06/2015 2972 <1> ; Retro UNIX 386 v1 (32 bit) executable file header format 2973 <1> ; 18/10/2015 2974 000045F8 8B35[206F0000] <1> mov esi, [pcore] ; start address of user's core memory 2975 <1> ; (phys. start addr. of the exec. file) 2976 000045FE AD <1> lodsd 2977 000045FF 663DEB1E <1> cmp ax, 1EEBh ; EBh, 1Eh -> jump to +32 2978 00004603 7533 <1> jne short sysexec_15 2979 <1> ; cmp core,$405 / br .+14 is first instruction 2980 <1> ; / if file is standard a.out format 2981 <1> ; bne 1f / branch, if not standard format 2982 00004605 AD <1> lodsd 2983 00004606 89C1 <1> mov ecx, eax ; text (code) section size 2984 00004608 AD <1> lodsd 2985 00004609 01C1 <1> add ecx, eax ; + data section size (initialized data) 2986 <1> ; mov core+2,r5 / put 2nd word of users program in r5; 2987 <1> ; / number of bytes in program text 2988 <1> ; sub $14,r5 / subtract 12 2989 0000460B 89CB <1> mov ebx, ecx 2990 <1> ; 2991 <1> ; 25/06/2015 2992 <1> ; NOTE: These are for next versions of Retro UNIX 386 2993 <1> ; and SINGLIX operating systems (as code template). 2994 <1> ; Current Retro UNIX 386 v1 files can be max. 64KB 2995 <1> ; due to RUFS (floppy disk file system) restriction... 2996 <1> ; Overrun is not possible for current version. 2997 <1> ; 2998 0000460D AD <1> lodsd 2999 0000460E 01C3 <1> add ebx, eax ; + bss section size (for overrun checking) 3000 00004610 3B1D[CC6E0000] <1> cmp ebx, [u.count] 3001 00004616 7711 <1> ja short sysexec_14 ; program overruns stack ! 3002 <1> ; 3003 <1> ; 24/07/2015 3004 <1> ; add bss section size to [u.break] 3005 00004618 0105[D46E0000] <1> add [u.break], eax 3006 <1> ; 3007 0000461E 83E920 <1> sub ecx, 32 ; header size (already loaded) 3008 <1> ;cmp ecx, [u.count] 3009 <1> ;jnb short sysexec_16 3010 <1> ; cmp r5,u.count / 3011 <1> ; bgt 1f / branch if r5 greater than u.count 3012 00004621 890D[CC6E0000] <1> mov [u.count], ecx ; required read count 3013 <1> ; mov r5,u.count 3014 <1> ; 3015 00004627 EB29 <1> jmp short sysexec_16 3016 <1> ; 3017 <1> sysexec_14: 3018 <1> ; 23/06/2015 3019 <1> ; insufficient (out of) memory 3020 00004629 C705[186F0000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; 1 3020 00004631 0000 <1> 3021 00004633 E974F5FFFF <1> jmp error 3022 <1> ; 3023 <1> sysexec_15: 3024 <1> ; 25/06/2015 3025 <1> ;movzx edx, word [i.size] ; file size 3026 <1> ; 30/11/2021 3027 00004638 8B15[486B0000] <1> mov edx, [i.size] ; file size 3028 0000463E 29CA <1> sub edx, ecx ; file size - loaded bytes 3029 00004640 7626 <1> jna short sysexec_17 ; no need to next read 3030 00004642 01D1 <1> add ecx, edx ; [i.size] 3031 00004644 3B0D[CC6E0000] <1> cmp ecx, [u.count] ; overrun check (!) 3032 0000464A 77DD <1> ja short sysexec_14 3033 0000464C 8915[CC6E0000] <1> mov [u.count], edx 3034 <1> sysexec_16: 3035 <1> ;mov ax, [ii] ; i-number 3036 <1> ; 28/11/2021 3037 00004652 A1[806E0000] <1> mov eax, [ii] ; 32 bit inode number 3038 00004657 E8630F0000 <1> call readi 3039 <1> ; add core+10,u.nread / add size of user data area 3040 <1> ; / to u.nread 3041 <1> ; br 2f 3042 <1> ; 1: 3043 <1> ; jsr r0,readi / read in rest of file 3044 <1> ; 2: 3045 0000465C 8B0D[D06E0000] <1> mov ecx, [u.nread] 3046 00004662 010D[D46E0000] <1> add [u.break], ecx 3047 <1> ; mov u.nread,u.break / set users program break to end of 3048 <1> ; / user code 3049 <1> ; add $core+14,u.break / plus data area 3050 <1> ; 20/07/2015 3051 <1> sysexec_17: 3052 <1> ; 26/03/2021 - Retro UNIX 386 v2 3053 <1> ; ('iclose' is not needed for regular files, from now on) 3054 <1> ;;mov ax, [ii] ; i-number 3055 <1> ;call iclose 3056 <1> ; ; jsr r0,iclose / does nothing 3057 00004668 31C0 <1> xor eax, eax 3058 0000466A FEC0 <1> inc al 3059 0000466C 66A3[F06E0000] <1> mov [u.intr], ax ; 1 (interrupt/time-out is enabled) 3060 00004672 66A3[F26E0000] <1> mov [u.quit], ax ; 1 ('crtl+brk' signal is enabled) 3061 <1> ; 30/11/2021 3062 00004678 FEC8 <1> dec al ; eax = 0 3063 <1> ; 02/07/2015 3064 <1> ;cmp dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ? 3065 0000467A 3905[086F0000] <1> cmp [u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ? 3066 00004680 770C <1> ja short sysexec_18 ; no, the caller is user process 3067 <1> ; If the caller is kernel (sys_init), 'sysexec' will come here 3068 00004682 8B15[A86D0000] <1> mov edx, [k_page_dir] ; kernel's page directory 3069 00004688 8915[086F0000] <1> mov [u.ppgdir], edx ; next time 'sysexec' must not come here 3070 <1> sysexec_18: 3071 <1> ; 18/10/2015 3072 <1> ; 05/08/2015 3073 <1> ; 29/07/2015 3074 0000468E 8B2D[346F0000] <1> mov ebp, [argv] ; user's stack pointer must points to argument 3075 <1> ; list pointers (argument count) 3076 00004694 FA <1> cli 3077 00004695 8B25[446D0000] <1> mov esp, [tss.esp0] ; ring 0 (kernel) stack pointer 3078 <1> ;mov esp, [u.sp] ; Restore Kernel stack 3079 <1> ; for this process 3080 <1> ;add esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS 3081 <1> ;;xor eax, eax ; 0 3082 <1> ;dec al ; eax = 0 3083 <1> ; eax = 0 ; 30/11/2021 3084 0000469B 66BA2300 <1> mov dx, UDATA 3085 0000469F 6652 <1> push dx ; user's stack segment 3086 000046A1 55 <1> push ebp ; user's stack pointer 3087 <1> ; (points to number of arguments) 3088 000046A2 FB <1> sti 3089 000046A3 9C <1> pushfd ; EFLAGS 3090 <1> ; Set IF for enabling interrupts in user mode 3091 <1> ;or dword [esp], 200h 3092 <1> ; 3093 <1> ;mov bx, UCODE 3094 <1> ;push bx ; user's code segment 3095 000046A4 6A1B <1> push UCODE 3096 <1> ;push 0 3097 000046A6 50 <1> push eax ; EIP (=0) - start address - 3098 <1> ; clr -(r5) / popped into ps when rti in 3099 <1> ; / sysrele is executed 3100 <1> ; mov $core,-(r5) / popped into pc when rti 3101 <1> ; / in sysrele is executed 3102 <1> ;mov r5,0f / load second copyz argument 3103 <1> ;tst -(r5) / decrement r5 3104 000046A7 8925[9C6E0000] <1> mov [u.sp], esp ; 29/07/2015 3105 <1> ; 05/08/2015 3106 <1> ; Remedy of a General Protection Fault during 'iretd' is here ! 3107 <1> ; ('push dx' would cause to general protection fault, 3108 <1> ; after 'pop ds' etc.) 3109 <1> ; 3110 <1> ;; push dx ; ds (UDATA) 3111 <1> ;; push dx ; es (UDATA) 3112 <1> ;; push dx ; fs (UDATA) 3113 <1> ;; push dx ; gs (UDATA) 3114 <1> ; 3115 <1> ; This is a trick to prevent general protection fault 3116 <1> ; during 'iretd' intruction at the end of 'sysrele' (in u1.s): 3117 000046AD 8EC2 <1> mov es, dx ; UDATA 3118 000046AF 06 <1> push es ; ds (UDATA) 3119 000046B0 06 <1> push es ; es (UDATA) 3120 000046B1 06 <1> push es ; fs (UDATA) 3121 000046B2 06 <1> push es ; gs (UDATA) 3122 000046B3 66BA1000 <1> mov dx, KDATA 3123 000046B7 8EC2 <1> mov es, dx 3124 <1> ; 3125 <1> ;; pushad simulation 3126 000046B9 89E5 <1> mov ebp, esp ; esp before pushad 3127 000046BB 50 <1> push eax ; eax (0) 3128 000046BC 50 <1> push eax ; ecx (0) 3129 000046BD 50 <1> push eax ; edx (0) 3130 000046BE 50 <1> push eax ; ebx (0) 3131 000046BF 55 <1> push ebp ; esp before pushad 3132 000046C0 50 <1> push eax ; ebp (0) 3133 000046C1 50 <1> push eax ; esi (0) 3134 000046C2 50 <1> push eax ; edi (0) 3135 <1> ; 3136 000046C3 A3[A46E0000] <1> mov [u.r0], eax ; eax = 0 3137 000046C8 8925[A06E0000] <1> mov [u.usp], esp 3138 <1> ; mov r5,u.r0 / 3139 <1> ; sub $16.,r5 / skip 8 words 3140 <1> ; mov r5,u.sp / assign user stack pointer value, 3141 <1> ; / effectively zeroes all regs 3142 <1> ; / when sysrele is executed 3143 <1> ; jsr r0,copyz; core; 0:0 / zero user's core 3144 <1> ; clr u.break 3145 <1> ; mov r5,sp / point sp to user's stack 3146 <1> ; 3147 000046CE E9FBF4FFFF <1> jmp sysret0 3148 <1> ;jmp sysret 3149 <1> ; br sysret3 / return to core image at $core 3150 <1> 3151 <1> get_argp: 3152 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 3153 <1> ; 18/10/2015 (nbase, ncount) 3154 <1> ; 21/07/2015 3155 <1> ; 24/06/2015 (Retro UNIX 386 v1) 3156 <1> ; Get (virtual) address of argument from user's core memory 3157 <1> ; 3158 <1> ; INPUT: 3159 <1> ; esi = virtual address of argument pointer 3160 <1> ; OUTPUT: 3161 <1> ; eax = virtual address of argument 3162 <1> ; 3163 <1> ; Modified registers: EAX, EBX, ECX, EDX, ESI 3164 <1> ; 3165 000046D3 833D[086F0000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? 3166 <1> ; (the caller is kernel) 3167 000046DA 767C <1> jna short get_argpk 3168 <1> ; 3169 000046DC 89F3 <1> mov ebx, esi 3170 000046DE E871EBFFFF <1> call get_physical_addr ; get physical address 3171 000046E3 7254 <1> jc short get_argp_err ; 11/12/2021 3172 000046E5 A3[286F0000] <1> mov [nbase], eax ; physical address 3173 <1> ;mov [ncount], cx ; remain byte count in page (1-4096) 3174 <1> ; 11/12/2021 3175 000046EA 890D[2C6F0000] <1> mov [ncount], ecx 3176 000046F0 B804000000 <1> mov eax, 4 ; 21/07/2015 3177 <1> ;cmp cx, ax ; 4 3178 <1> ; 11/12/2021 3179 000046F5 39C1 <1> cmp ecx, eax ; 4 3180 000046F7 734A <1> jnb short get_argp2 3181 000046F9 89F3 <1> mov ebx, esi 3182 000046FB 01CB <1> add ebx, ecx 3183 000046FD E852EBFFFF <1> call get_physical_addr ; get physical address 3184 00004702 7235 <1> jc short get_argp_err 3185 <1> ;push esi 3186 00004704 89C6 <1> mov esi, eax 3187 <1> ;xchg cx, [ncount] 3188 <1> ; 11/12/2021 3189 00004706 870D[2C6F0000] <1> xchg ecx, [ncount] 3190 0000470C 8735[286F0000] <1> xchg esi, [nbase] 3191 00004712 B504 <1> mov ch, 4 3192 00004714 28CD <1> sub ch, cl 3193 <1> get_argp0: 3194 00004716 AC <1> lodsb 3195 <1> ;push ax 3196 <1> ; 11/12/2021 3197 00004717 50 <1> push eax 3198 00004718 FEC9 <1> dec cl 3199 0000471A 75FA <1> jnz short get_argp0 3200 0000471C 8B35[286F0000] <1> mov esi, [nbase] 3201 <1> ; 21/07/2015 3202 00004722 0FB6C5 <1> movzx eax, ch 3203 00004725 0105[286F0000] <1> add [nbase], eax 3204 <1> ;sub [ncount], ax 3205 <1> ; 11/12/2021 3206 0000472B 2905[2C6F0000] <1> sub [ncount], eax 3207 <1> get_argp1: 3208 00004731 AC <1> lodsb 3209 00004732 FECD <1> dec ch 3210 00004734 743B <1> jz short get_argp3 3211 <1> ;push ax 3212 <1> ; 11/12/2021 3213 00004736 50 <1> push eax 3214 00004737 EBF8 <1> jmp short get_argp1 3215 <1> get_argp_err: 3216 00004739 A3[186F0000] <1> mov [u.error], eax 3217 0000473E E969F4FFFF <1> jmp error 3218 <1> get_argp2: 3219 <1> ; 21/07/2015 3220 <1> ;mov eax, 4 3221 00004743 8B15[286F0000] <1> mov edx, [nbase] ; 18/10/2015 3222 00004749 0105[286F0000] <1> add [nbase], eax 3223 <1> ;sub [ncount], ax 3224 <1> ; 11/12/2021 3225 0000474F 2905[2C6F0000] <1> sub [ncount], eax 3226 <1> ; 3227 00004755 8B02 <1> mov eax, [edx] 3228 00004757 C3 <1> retn 3229 <1> get_argpk: 3230 <1> ; Argument is in kernel's memory space 3231 00004758 66C705[2C6F0000]00- <1> mov word [ncount], PAGE_SIZE ; 4096 3231 00004760 10 <1> 3232 00004761 8935[286F0000] <1> mov [nbase], esi 3233 00004767 8305[286F0000]04 <1> add dword [nbase], 4 3234 0000476E 8B06 <1> mov eax, [esi] ; virtual addr. = physical addr. 3235 00004770 C3 <1> retn 3236 <1> get_argp3: 3237 00004771 B103 <1> mov cl, 3 3238 <1> get_argp4: 3239 00004773 C1E008 <1> shl eax, 8 3240 <1> ;pop dx 3241 <1> ; 11/12/2021 3242 00004776 5A <1> pop edx 3243 00004777 88D0 <1> mov al, dl 3244 00004779 E2F8 <1> loop get_argp4 3245 <1> ;pop esi 3246 0000477B C3 <1> retn 3247 <1> 3248 <1> sysfstat: 3249 <1> ; 08/01/2022 3250 <1> ; 26/12/2021 (Retro UNIX 386 v1.2) 3251 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3252 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3253 <1> ; 3254 <1> ; 'sysfstat' is identical to 'sysstat' except that it operates 3255 <1> ; on open files instead of files given by name. It puts the 3256 <1> ; buffer address on the stack, gets the i-number and 3257 <1> ; checks to see if the file is open for reading or writing. 3258 <1> ; If the file is open for writing (i-number is negative) 3259 <1> ; the i-number is set positive and a branch into 'sysstat' 3260 <1> ; is made. 3261 <1> ; 3262 <1> ; Calling sequence: 3263 <1> ; sysfstat; buf 3264 <1> ; Arguments: 3265 <1> ; buf - buffer address 3266 <1> ; 3267 <1> ; Inputs: *u.r0 - file descriptor 3268 <1> ; Outputs: buffer is loaded with file information 3269 <1> ; ............................................................... 3270 <1> ; 3271 <1> ; Retro UNIX 8086 v1 modification: 3272 <1> ; 'sysfstat' system call has two arguments; so, 3273 <1> ; * 1st argument, file descriptor is in BX register 3274 <1> ; * 2nd argument, buf is pointed to by CX register 3275 <1> 3276 <1> ; / set status of open file 3277 <1> ; jsr r0,arg; u.off / put buffer address in u.off 3278 0000477C 51 <1> push ecx ; * 3279 <1> ; mov u.off,-(sp) / put buffer address on the stack 3280 <1> ; mov *u.r0,r1 / put file descriptor in r1 3281 <1> ; jsr r0,getf / get the files i-number 3282 <1> ; BX = file descriptor (file number) 3283 0000477D E8F3000000 <1> call getf1 3284 00004782 6621C0 <1> and ax, ax ; i-number of the file 3285 <1> ; tst r1 / is it 0? 3286 <1> ;jz error 3287 <1> ; beq error3 / yes, error 3288 <1> ;jnz short sysfstat1 3289 <1> ; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system) 3290 00004785 752D <1> jnz short sysstat1 3291 00004787 C705[186F0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 3291 0000478F 0000 <1> 3292 00004791 E916F4FFFF <1> jmp error 3293 <1> ; 26/12/2021 3294 <1> ;sysfstat1: 3295 <1> ;cmp ah, 80h 3296 <1> ;jb short sysstat1 3297 <1> ; ; bgt 1f / if i-number is negative (open for writing) 3298 <1> ;neg ax 3299 <1> ; ; neg r1 / make it positive, then branch 3300 <1> ; 08/01/2022 3301 <1> ;jmp short sysstat1 3302 <1> ; br 1f / to 1f 3303 <1> sysstat: 3304 <1> ; 26/12/2021 (Retro UNIX 386 v1.2) 3305 <1> ; 18/10/2015 3306 <1> ; 07/10/2015 3307 <1> ; 02/09/2015 3308 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3309 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3310 <1> ; 3311 <1> ; 'sysstat' gets the status of a file. Its arguments are the 3312 <1> ; name of the file and buffer address. The buffer is 34 bytes 3313 <1> ; long and information about the file placed in it. 3314 <1> ; sysstat calls 'namei' to get the i-number of the file. 3315 <1> ; Then 'iget' is called to get i-node in core. The buffer 3316 <1> ; is then loaded and the results are given in the UNIX 3317 <1> ; Programmers Manual sysstat (II). 3318 <1> ; 3319 <1> ; Calling sequence: 3320 <1> ; sysstat; name; buf 3321 <1> ; Arguments: 3322 <1> ; name - points to the name of the file 3323 <1> ; buf - address of a 34 bytes buffer 3324 <1> ; Inputs: - 3325 <1> ; Outputs: buffer is loaded with file information 3326 <1> ; ............................................................... 3327 <1> ; 3328 <1> ; Retro UNIX 8086 v1 modification: 3329 <1> ; 'sysstat' system call has two arguments; so, 3330 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 3331 <1> ; to get sysstat system call arguments from the user; 3332 <1> ; * 1st argument, name is pointed to by BX register 3333 <1> ; * 2nd argument, buf is pointed to by CX register 3334 <1> ; 3335 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 3336 <1> ; arguments which were in these registers; 3337 <1> ; but, it returns by putting the 1st argument 3338 <1> ; in 'u.namep' and the 2nd argument 3339 <1> ; on top of stack. (1st argument is offset of the 3340 <1> ; file/path name in the user's program segment.) 3341 <1> 3342 <1> ; / ; name of file; buffer - get files status 3343 <1> ; jsr r0,arg2 / get the 2 arguments 3344 00004796 891D[C06E0000] <1> mov [u.namep], ebx 3345 0000479C 51 <1> push ecx ; * 3346 0000479D E840010000 <1> call namei 3347 <1> ; jsr r0,namei / get the i-number for the file 3348 <1> ;jc error 3349 <1> ; br error3 / no such file, error 3350 000047A2 7310 <1> jnc short sysstat1 3351 <1> ; pop ecx 3352 <1> sysstat_err0: 3353 <1> ; 'file not found !' error 3354 000047A4 C705[186F0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 3354 000047AC 0000 <1> 3355 000047AE E9F9F3FFFF <1> jmp error 3356 <1> 3357 000047B3 00 <1> statx: db 0 3358 <1> 3359 <1> sysstat1: ; 1: 3360 000047B4 E8B70A0000 <1> call iget 3361 <1> ; jsr r0,iget / get the i-node into core 3362 <1> ; 07/10/2015 (ax = [ii], inode number) 3363 <1> ; 02/09/2015 3364 000047B9 8F05[C86E0000] <1> pop dword [u.base] ; * 3365 <1> ; mov (sp)+,r3 / move u.off to r3 (points to buffer) 3366 000047BF E855000000 <1> call sysstat_gpa ; get physical address 3367 000047C4 730A <1> jnc short sysstat2 3368 <1> sysstat_err1: 3369 000047C6 A3[186F0000] <1> mov dword [u.error], eax ; error code 3370 000047CB E9DCF3FFFF <1> jmp error 3371 <1> sysstat2: 3372 000047D0 A0[806E0000] <1> mov al, [ii] ; 07/10/2015 (result of 'iget' call, above) 3373 000047D5 AA <1> stosb 3374 000047D6 FF05[C86E0000] <1> inc dword [u.base] 3375 <1> ;dec cx 3376 000047DC 49 <1> dec ecx ; 26/12/2021 3377 000047DD 7505 <1> jnz short sysstat3 3378 000047DF E835000000 <1> call sysstat_gpa 3379 <1> ;jc short sysstat_err1 3380 <1> sysstat3: 3381 000047E4 A0[816E0000] <1> mov al, [ii+1] ; 07/10/2015 (result of 'iget' call, above) 3382 000047E9 AA <1> stosb 3383 <1> ; mov r1,(r3)+ / put i-number in 1st word of buffer 3384 000047EA FF05[C86E0000] <1> inc dword [u.base] 3385 <1> ;;dec word [u.pcount] 3386 <1> ;dec cx 3387 000047F0 49 <1> dec ecx ; 26/12/2021 3388 000047F1 7505 <1> jnz short sysstat4 3389 000047F3 E821000000 <1> call sysstat_gpa 3390 <1> ;jc short sysstat_err1 3391 <1> sysstat4: 3392 000047F8 BE[406B0000] <1> mov esi, inode 3393 <1> ; mov $inode,r2 / r2 points to i-node 3394 <1> sysstat5: ; 1: 3395 000047FD A4 <1> movsb 3396 <1> ; mov (r2)+,(r3)+ / move rest of i-node to buffer 3397 000047FE FF05[C86E0000] <1> inc dword [u.base] 3398 <1> ;;dec word [u.pcount] 3399 <1> ;dec cx 3400 00004804 49 <1> dec ecx ; 26/12/2021 3401 00004805 7505 <1> jnz short sysstat6 3402 00004807 E80D000000 <1> call sysstat_gpa 3403 <1> ;jc short sysstat_err1 3404 <1> sysstat6: 3405 <1> ; 26/12/2021 - Retro UNIX 386 v1.2 3406 0000480C 81FE[806B0000] <1> cmp esi, inode + 64 ; Retro UNIX v2 inode 3407 <1> ;cmp esi, inode + 32 3408 <1> ; cmp r2,$inode+32 / done? 3409 00004812 75E9 <1> jne short sysstat5 3410 <1> ; bne 1b / no, go back 3411 00004814 E9B3F3FFFF <1> jmp sysret 3412 <1> ; br sysret3 / return through sysret 3413 <1> ; 3414 <1> sysstat_gpa: ; get physical address of file status buffer 3415 <1> ; 02/09/2015 3416 00004819 8B1D[C86E0000] <1> mov ebx, [u.base] 3417 <1> ; 07/10/2015 3418 0000481F E830EAFFFF <1> call get_physical_addr ; get physical address 3419 <1> ;jc short sysstat_gpa1 3420 00004824 72A0 <1> jc short sysstat_err1 3421 <1> ; 18/10/2015 3422 00004826 89C7 <1> mov edi, eax ; physical address 3423 <1> ;mov [u.pcount], cx ; remain bytes in page 3424 <1> ;sysstat_gpa1: 3425 00004828 C3 <1> retn 3426 <1> 3427 <1> fclose: 3428 <1> ; 08/01/2022 3429 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3430 <1> ; 08/04/2021 3431 <1> ; 04/04/2021 3432 <1> ; 18/08/2020 - Retro UNIX 386 v2 3433 <1> ; 18/06/2015 (Retro UNIX 386 v1 - Beginning) 3434 <1> ; (32 bit offset pointer modification) 3435 <1> ; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1) 3436 <1> ; 3437 <1> ; Given the file descriptor (index to the u.fp list) 3438 <1> ; 'fclose' first gets the i-number of the file via 'getf'. 3439 <1> ; If i-node is active (i-number > 0) the entry in 3440 <1> ; u.fp list is cleared. If all the processes that opened 3441 <1> ; that file close it, then fsp etry is freed and the file 3442 <1> ; is closed. If not a return is taken. 3443 <1> ; If the file has been deleted while open, 'anyi' is called 3444 <1> ; to see anyone else has it open, i.e., see if it is appears 3445 <1> ; in another entry in the fsp table. Upon return from 'anyi' 3446 <1> ; a check is made to see if the file is special. 3447 <1> ; 3448 <1> ; INPUTS -> 3449 <1> ; r1 - contains the file descriptor (value=0,1,2...) 3450 <1> ; u.fp - list of entries in the fsp table 3451 <1> ; fsp - table of entries (4 words/entry) of open files. 3452 <1> ; OUTPUTS -> 3453 <1> ; r1 - contains the same file descriptor 3454 <1> ; r2 - contains i-number 3455 <1> ; 3456 <1> ; ((AX = R1)) 3457 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 3458 <1> ; 3459 <1> ; Retro UNIX 8086 v1 modification : CF = 1 3460 <1> ; if i-number of the file is 0. (error) 3461 <1> 3462 <1> ; 08/04/2021 3463 <1> ; INPUT: 3464 <1> ; eax = file descriptor 3465 <1> ; OUTPUT: 3466 <1> ; cf = 0 -> eax = file descriptor 3467 <1> ; cf = 1 -> eax = error code 3468 <1> ; (al = 0 -> file not open) 3469 <1> 3470 <1> ; 18/08/2020 3471 <1> ;movzx edx, ax ; ** 3472 00004829 89C3 <1> mov ebx, eax 3473 <1> 3474 <1> ; 18/08/2020 3475 <1> _fclose: 3476 0000482B 53 <1> push ebx ; *** ; file descriptor (index to u.fp) 3477 <1> 3478 <1> ;push ax ; *** 3479 <1> ; mov r1,-(sp) / put r1 on the stack (it contains 3480 <1> ; / the index to u.fp list) 3481 <1> ; ebx = file descriptor/number 3482 0000482C E844000000 <1> call getf 3483 <1> ; jsr r0,getf / r1 contains i-number, 3484 <1> ; / cdev has device =, u.fofp 3485 <1> ; / points to 3rd word of fsp entry 3486 <1> ;cmp eax, 1 ; 18/08/2020 3487 00004831 6683F801 <1> cmp ax, 1 ; r1 3488 <1> ; tst r1 / is i-number 0? 3489 00004835 723C <1> jb short fclose_2 3490 <1> ; beq 1f / yes, i-node not active so return 3491 <1> ; tst (r0)+ / no, jump over error return 3492 <1> 3493 <1> ;mov ebx, edx ; ** 3494 <1> ; 18/08/2020 3495 00004837 8B1C24 <1> mov ebx, [esp] 3496 <1> ;mov edx, eax 3497 <1> ;;mov dx, ax ; * 3498 <1> ; mov r1,r2 / move i-number to r2 ;* 3499 <1> ; mov (sp),r1 / restore value of r1 from the stack 3500 <1> ; / which is index to u.fp ; ** 3501 0000483A C683[AE6E0000]00 <1> mov byte [ebx+u.fp], 0 3502 <1> ; clrb u.fp(r1) / clear that entry in the u.fp list 3503 00004841 8B1D[B86E0000] <1> mov ebx, [u.fofp] 3504 <1> ; mov u.fofp,r1 / r1 points to 3rd word in fsp entry 3505 <1> 3506 <1> ; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure) 3507 <1> ; ebx = 5th word of fsp entry (64 bit file offset) 3508 <1> fclose_0: 3509 <1> ; 08/01/2022 3510 00004847 FE4BFE <1> dec byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2 3511 <1> ;dec byte [ebx+4] ; 18/06/2015 3512 <1> ; decb 2(r1) / decrement the number of processes 3513 <1> ; / that have opened the file 3514 0000484A 7927 <1> jns short fclose_2 ; jump if not negative (jump if bit 7 is 0) 3515 <1> ; bge 1f / if all processes haven't closed the file, return 3516 <1> ; 3517 <1> ;push dx ; * 3518 <1> ; mov r2,-(sp) / put r2 on the stack (i-number) 3519 <1> ;;xor ax, ax ; 0 3520 <1> ;xor eax, eax ; 18/08/2020 3521 <1> ; clear 1st word of fsp entry 3522 <1> ;mov [ebx-8], ax ; 0 ; 18/08/2020 3523 <1> ; 18/08/2020 - Retro UNIX 386 v2 3524 0000484C 66C743F80000 <1> mov word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number 3525 <1> ; Note: 32 bit i-node number field is ready but 3526 <1> ; it is not used in current runix version. 3527 <1> 3528 <1> ;;mov [ebx-4], ax ; 0 3529 <1> ; clr -4(r1) / clear 1st word of fsp entry 3530 <1> ;mov al, [ebx+5] ; 18/06/2015 3531 <1> ; ; tstb 3(r1) / has this file been deleted 3532 <1> ;and al, al 3533 <1> ;jz short fclose_1 3534 <1> ; ; beq 2f / no, branch 3535 <1> 3536 <1> ;push edx ; * ; 18/08/2020 3537 <1> ;mov eax, edx ; * ; 18/08/2020 3538 <1> 3539 <1> ;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure) 3540 <1> ;;test byte [ebx-3], 80h ; open mode & status flags 3541 <1> ; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure) 3542 <1> ;test byte [ebx-4], 80h ; open mode & status flags 3543 <1> ;jz short fclose_1 ; deleted file flag (bit 7) 3544 <1> 3545 <1> ; 04/04/2021 3546 00004852 31D2 <1> xor edx, edx 3547 <1> ; 08/01/2022 3548 00004854 8A53FD <1> mov dl, [ebx-3] ; open mode & status flags 3549 00004857 F6C280 <1> test dl, 80h ; deleted file flag (bit 7) 3550 0000485A 7409 <1> jz short fclose_1 ; (not deleted -while open-) 3551 0000485C 52 <1> push edx 3552 <1> 3553 <1> ; deleted file ! 3554 <1> 3555 <1> ;mov ax, dx ; * 3556 <1> ; mov r2,r1 / yes, put i-number back into r1 3557 <1> ; AX = inode number 3558 0000485D E859040000 <1> call anyi 3559 <1> ; jsr r0,anyi / free all blocks related to i-number 3560 <1> ; / check if file appears in fsp again 3561 <1> ; 04/04/2021 3562 00004862 5A <1> pop edx 3563 <1> ; 08/04/2021 3564 00004863 720C <1> jc short fclose_3 ; error code in eax 3565 <1> ; 18/08/2020 3566 <1> ; jmp short fclose_2 3567 <1> 3568 <1> ; ax = inode number 3569 <1> fclose_1: ; 2: 3570 <1> ; 04/04/2021 3571 00004865 80E201 <1> and dl, 1 3572 00004868 FEC2 <1> inc dl ; 0 -> 1 (open for read), 1 -> 2 (open for write) 3573 <1> 3574 <1> ;pop eax ; * ; 18/08/2020 3575 <1> ;;pop ax ; * 3576 <1> ; mov (sp)+,r1 / put i-number back into r1 3577 0000486A E883140000 <1> call iclose ; close if it is special file 3578 <1> ; jsr r0,iclose / check to see if it is a special file 3579 <1> ; 08/04/2021 3580 0000486F 7302 <1> jnc short fclose_2 3581 <1> fclose_3: 3582 00004871 5B <1> pop ebx ; *** ; file descriptor 3583 <1> ; eax = error code 3584 00004872 C3 <1> retn 3585 <1> fclose_2: ; 1: 3586 00004873 58 <1> pop eax ; *** ; 18/08/2020 3587 <1> ;pop ax ; *** 3588 <1> ; mov (sp)+,r1 / put index to u.fp back into r1 3589 00004874 C3 <1> retn 3590 <1> ; rts r0 3591 <1> 3592 <1> ; 08/01/2022 3593 <1> ; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code 3594 <1> getf: ; / get the device number and the i-number of an open file 3595 <1> ; 13/05/2015 3596 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3597 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 3598 <1> 3599 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3600 <1> ; 3601 <1> ; 16/05/2021 3602 <1> ; 27/03/2020 - Retro UNIX 386 v2 3603 <1> ; (new open files -fsp- structure) 3604 <1> ; 13/05/2015 3605 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3606 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 3607 <1> 3608 <1> ; INPUT: 3609 <1> ; ;eax = file descriptor/number 3610 <1> ; ebx = file descriptor/number ; 18/08/2020 3611 <1> ; OUTPUT: 3612 <1> ; bl = open mode & status flag ; 27/03/2020 3613 <1> ; (bit 0 open mode flag, 0 = read, 1 = write) 3614 <1> ; eax = inode number (in AX) 3615 <1> ; If eax = 0 -> file not open 3616 <1> ; byte [cdev] = logical drive number (of inode in eax) 3617 <1> ; 3618 <1> ; Modified registers: eax, ebx 3619 <1> 3620 <1> ; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c') 3621 <1> ; /* 3622 <1> ; * Convert a user supplied 3623 <1> ; * file descriptor into a pointer 3624 <1> ; * to a file structure. 3625 <1> ; * Only task is to check range 3626 <1> ; * of the descriptor. 3627 <1> ; */ 3628 <1> ; struct file * 3629 <1> ; getf(f) 3630 <1> ; 3631 <1> ; 18/08/2020 3632 <1> ; ebx = file descriptor/number 3633 <1> 3634 <1> ; 16/05/2021 3635 <1> ;NOFILE equ 10 ; 08/01/2022 3636 <1> 3637 <1> ; 18/08/2020 3638 <1> ;mov ebx, eax 3639 <1> getf1: ;; Calling point from 'rw1' (23/05/2013) 3640 <1> 3641 <1> ; ebx = file descriptor/number 3642 <1> 3643 <1> ; 18/08/2020 3644 00004875 29C0 <1> sub eax, eax ; eax = 0 3645 <1> 3646 00004877 83FB0A <1> cmp ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021 3647 <1> ; cmp r1,$10. / user limited to 10 open files 3648 0000487A 7365 <1> jnb short getf2 ; 13/05/2015 3649 <1> ;jnb error 3650 <1> ; bhis error3 / u.fp is table of users open files, 3651 <1> ; / index in fsp table 3652 <1> ; 08/01/2022 3653 0000487C 8A83[AE6E0000] <1> mov al, [ebx+u.fp] 3654 <1> ;mov bl, [ebx+u.fp] 3655 <1> ; movb u.fp(r1),r1 / r1 contains number of entry 3656 <1> ; / in fsp table 3657 00004882 08C0 <1> or al, al ; 08/01/2022 3658 <1> ;or bl, bl 3659 <1> ;jnz short getf3 3660 00004884 745B <1> jz short getf2 ; 18/08/2020 3661 <1> ;;jz short getf4 3662 <1> ; beq 1f / if its zero return 3663 <1> ;getf2: 3664 <1> ; ; 'File not open !' error (ax=0) 3665 <1> ; ;sub eax, eax ; 18/08/2020 3666 <1> ; retn 3667 <1> ;getf3: 3668 <1> ; Retro UNIX 386 v1 modification ! (11/05/2015) 3669 <1> ; 3670 <1> ; 'fsp' table (10 bytes/entry) 3671 <1> ; bit 15 bit 0 3672 <1> ; ---|------------------------------------------- 3673 <1> ; r/w| i-number of open file 3674 <1> ; ---|------------------------------------------- 3675 <1> ; device number 3676 <1> ; ----------------------------------------------- 3677 <1> ; offset pointer, r/w pointer to file (bit 0-15) 3678 <1> ; ----------------------------------------------- 3679 <1> ; offset pointer, r/w pointer to file (bit 16-31) 3680 <1> ; ----------------------|------------------------ 3681 <1> ; flag that says file | number of processes 3682 <1> ; has been deleted | that have file open 3683 <1> ; ----------------------|------------------------ 3684 <1> 3685 <1> ; Retro UNIX 386 v2 modification ! (27/03/2020) 3686 <1> 3687 <1> ; bit 15 bit 0 3688 <1> ; ----------------------------------------------- byte 0 3689 <1> ; i-number of open file 3690 <1> ; ----------------------------------------------- byte 2 3691 <1> ; high word of 32 bit i-number 3692 <1> ; ----------------------------------------------- byte 4 3693 <1> ; open mode & status | device number 3694 <1> ; ----------------------------------------------- byte 6 3695 <1> ; reserved byte | open count 3696 <1> ; ----------------------------------------------- byte 8 3697 <1> ; offset pointer, i.e., r/w pointer to file 3698 <1> ; ----------------------------------------------- byte 10 3699 <1> ; 64 bit file offset pointer (bit 16-31) 3700 <1> ; ----------------------------------------------- byte 12 3701 <1> ; 64 bit file offset pointer (bit 32-47) 3702 <1> ; ----------------------------------------------- byte 14 3703 <1> ; 64 bit file offset pointer (bit 48-63) 3704 <1> ; ----------------------------------------------- byte 16 3705 <1> 3706 <1> ; 11/05/2015 - Retro UNIX 386 v1 3707 <1> ;mov eax, 10 3708 <1> 3709 <1> ; 27/03/2020 - Retro UNIX 386 v2 3710 <1> ;mov eax, opfls.size ; mov eax, 16 3711 <1> 3712 <1> ;sub eax, eax ; 18/08/2020 ; eax = 0 3713 <1> 3714 <1> ;mov al, opfls.size ; mov al, 16 3715 <1> ; 3716 <1> ;mul bl 3717 <1> ;;mov ebx, fsp-6 ; the 3rd word in the fsp entry 3718 <1> ;; 27/03/2020 3719 <1> ;mov ebx, fsp-(opfls.size-opfls.offset) ; fsp-8 3720 <1> 3721 <1> ;add ebx, eax 3722 <1> ; asl r1 3723 <1> ; asl r1 / multiply by 8 to get index into 3724 <1> ; / fsp table entry 3725 <1> ; asl r1 3726 <1> ; add $fsp-4,r1 / r1 is pointing at the 3rd word 3727 <1> ; / in the fsp entry 3728 <1> ; 08/01/2022 3729 00004886 88C3 <1> mov bl, al 3730 <1> ; 18/08/2020 3731 00004888 FECB <1> dec bl ; zero based fsp table entry number 3732 <1> 3733 <1> ; temporary - 26/12/2021 3734 0000488A 881D[E5400000] <1> mov [bytype], bl 3735 <1> 3736 <1> ;shl bl, 4 ; * 16 ; opfls.size 3737 <1> ; 08/01/2022 3738 00004890 C1E304 <1> shl ebx, 4 ; * 16 ; opfls.size 3739 00004893 81C3[486B0000] <1> add ebx, fsp+8 ; opfls.offset 3740 <1> ; ebx = address of the file offset pointer 3741 <1> ; (not file offset! not fsp entry address !) 3742 <1> 3743 00004899 891D[B86E0000] <1> mov [u.fofp], ebx 3744 <1> ; mov r1,u.fofp / save address of 3rd word 3745 <1> ; / in fsp entry in u.fofp 3746 <1> ; 18/08/2020 3747 0000489F 8A43FD <1> mov al, [ebx-3] ; open mode & status flags 3748 <1> 3749 000048A2 50 <1> push eax 3750 <1> 3751 <1> ;mov ax, [ebx] 3752 <1> ;;mov [cdev], al ; ;;Retro UNIX 8086 v1 ! 3753 <1> ;mov [cdev], ax ; ;;in fact (!) 3754 <1> ;;dev number is in 1 byte 3755 <1> ; mov -(r1),cdev / remove the device number cdev 3756 <1> 3757 <1> ; temporary - 26/12/2021 3758 000048A3 53 <1> push ebx 3759 000048A4 0205[6F3F0000] <1> add al, [srwtype] 3760 000048AA 8B1D[E1400000] <1> mov ebx, [openaddr] 3761 000048B0 8005[E1400000]02 <1> add byte [openaddr], 2 3762 000048B7 B44E <1> mov ah, 4Eh 3763 000048B9 668903 <1> mov word [ebx], ax 3764 000048BC 8B1D[E1400000] <1> mov ebx, [openaddr] 3765 000048C2 8005[E1400000]02 <1> add byte [openaddr], 2 3766 000048C9 A0[E5400000] <1> mov al, [bytype] 3767 000048CE 0430 <1> add al, '0' 3768 000048D0 668903 <1> mov word [ebx], ax 3769 000048D3 5B <1> pop ebx 3770 <1> 3771 <1> ; 18/08/2020 3772 000048D4 8A43FC <1> mov al, [ebx-4] ; logical drive number 3773 <1> 3774 000048D7 A2[856E0000] <1> mov [cdev], al 3775 <1> 3776 <1> ;dec ebx 3777 <1> ;dec ebx 3778 <1> ; 18/08/2020 3779 000048DC 668B43F8 <1> mov ax, [ebx-8] 3780 <1> ; mov -(r1),r1 / and the i-number r1 3781 <1> 3782 000048E0 5B <1> pop ebx ; ebx = bl = open mode and status flag 3783 <1> ; (bit 0 is open mode flag, 0 = read, 1 = write) 3784 <1> ; eax = inode number (in ax) 3785 <1> 3786 <1> getf2: ; 18/08/2020 3787 <1> getf4: ; 1: ; 08/01/2022 3788 000048E1 C3 <1> retn 3789 <1> ; rts r0 3790 <1> 3791 <1> ; 08/01/2022 3792 <1> ; 19/12/2021 3793 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 3794 <1> namei: 3795 <1> ; 18/10/2021 3796 <1> ; 12/06/2021 3797 <1> ; 01/05/2021 3798 <1> ; 26/03/2021 3799 <1> ; 25/03/2021 (Retro UNIX 386 v2 - Beginning) 3800 <1> ; 04/12/2015 (14 byte file names) 3801 <1> ; 18/10/2015 (nbase, ncount) 3802 <1> ; 12/10/2015 3803 <1> ; 21/08/2015 3804 <1> ; 18/07/2015 3805 <1> ; 02/07/2015 3806 <1> ; 17/06/2015 3807 <1> ; 16/06/2015 (Retro UNIX 386 v1 - Beginning) 3808 <1> ; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 3809 <1> ; 3810 <1> ; 'namei' takes a file path name and returns i-number of 3811 <1> ; the file in the current directory or the root directory 3812 <1> ; (if the first character of the pathname is '/'). 3813 <1> ; 3814 <1> ; INPUTS -> 3815 <1> ; u.namep - points to a file path name 3816 <1> ; u.cdir - i-number of users directory 3817 <1> ; u.cdev - device number on which user directory resides 3818 <1> ; OUTPUTS -> 3819 <1> ; r1 - i-number of file 3820 <1> ; cdev 3821 <1> ; u.dirbuf - points to directory entry where a match 3822 <1> ; occurs in the search for file path name. 3823 <1> ; If no match u.dirb points to the end of 3824 <1> ; the directory and r1 = i-number of the current 3825 <1> ; directory. 3826 <1> ; ((AX = R1)) 3827 <1> ; 3828 <1> ; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM) 3829 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 3830 <1> ; 3831 <1> 3832 <1> ;mov ax, [u.cdir] 3833 <1> ; mov u.cdir,r1 / put the i-number of current directory 3834 <1> ; / in r1 3835 <1> ; 01/05/2021 3836 000048E2 A1[A86E0000] <1> mov eax, [u.cdir] 3837 000048E7 8A15[AC6E0000] <1> mov dl, [u.cdrv] 3838 000048ED 8815[856E0000] <1> mov [cdev], dl 3839 <1> ;mov dx, [u.cdrv] 3840 <1> ;mov [cdev], dx ; NOTE: Retro UNIX 8086 v1 3841 <1> ; device/drive number is in 1 byte, 3842 <1> ; not in 1 word! 3843 <1> ; mov u.cdev,cdev / device number for users directory 3844 <1> ; / into cdev 3845 <1> ; 12/10/2015 3846 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 3847 <1> ; convert virtual (pathname) addr to physical address 3848 000048F3 E808010000 <1> call trans_addr_nmbp ; 12/10/2015 3849 <1> ; esi = physical address of [u.namep] 3850 <1> ; ecx = byte count in the page 3851 000048F8 803E2F <1> cmp byte [esi], '/' 3852 <1> ; cmpb *u.namep,$'/ / is first char in file name a / 3853 000048FB 751C <1> jne short namei_1 3854 <1> ; bne 1f 3855 000048FD FF05[C06E0000] <1> inc dword [u.namep] 3856 <1> ; inc u.namep / go to next char 3857 <1> ;dec cx ; remain byte count in the page 3858 00004903 49 <1> dec ecx ; 18/10/2021 3859 00004904 7506 <1> jnz short namei_0 3860 <1> ; 12/10/2015 3861 00004906 E8F5000000 <1> call trans_addr_nmbp ; convert virtual address to physical 3862 <1> ; esi = physical address (page start + offset) 3863 <1> ; ecx = byte count in the page 3864 0000490B 4E <1> dec esi 3865 <1> namei_0: 3866 0000490C 46 <1> inc esi ; go to next char 3867 <1> ;mov ax, [rootdir] ; 09/07/2013 3868 <1> ; 18/10/2021 3869 0000490D A1[8C6E0000] <1> mov eax, [rootdir] 3870 <1> ; mov rootdir,r1 / put i-number of rootdirectory in r1 3871 00004912 C605[856E0000]00 <1> mov byte [cdev], 0 3872 <1> ; clr cdev / clear device number 3873 <1> namei_1: ; 1: 3874 00004919 F606FF <1> test byte [esi], 0FFh 3875 <1> ;jz short getf4 3876 <1> ; 26/03/2021 3877 <1> ;jz short getf2 ; retn 3878 <1> ;;jz nig 3879 <1> ; tstb *u.namep / is the character in file name a nul 3880 <1> ; beq nig / yes, end of file name reached; 3881 <1> ; / branch to "nig" 3882 <1> ; 19/12/2021 3883 <1> namei_9: 3884 <1> ; 12/06/2021 3885 <1> ;jnz short namei_2 3886 <1> ;retn 3887 <1> ; 08/01/2022 3888 0000491C 74C3 <1> jz short getf4 3889 <1> namei_2: ; 1: 3890 <1> ; 18/10/2015 3891 0000491E 8935[286F0000] <1> mov [nbase], esi 3892 <1> ;mov [ncount], cx 3893 <1> ; 18/10/2021 3894 00004924 890D[2C6F0000] <1> mov [ncount], ecx 3895 <1> ; 3896 <1> ;;mov dx, 2 3897 <1> ;mov dl, 2 ; user flag (read, non-owner) 3898 <1> ; 25/03/2021 3899 <1> ;mov dx, 100h ; IREAD - read, owner 3900 <1> ; 18/10/2021 3901 0000492A 29D2 <1> sub edx, edx 3902 0000492C FEC6 <1> inc dh ; dx = 100h ; IREAD - read, owner 3903 0000492E E8270A0000 <1> call access 3904 <1> ; jsr r0,access; 2 / get i-node with i-number r1 3905 <1> ; 'access' will not return here if user has not "r" permission ! 3906 <1> 3907 <1> ;test word [i.flgs], 4000h 3908 <1> ; ; bit $40000,i.flgs / directory i-node? 3909 <1> ;jz short namei_err 3910 <1> ; beq error3 / no, got an error 3911 <1> ; 26/03/2021 3912 <1> ; mov al, [i.flgs+1] 3913 <1> ; ;test al, 80h ; IFREG ; 80h 3914 <1> ; ;jz short namei_err ; not a regular file ! (device!?) 3915 <1> ; ;and al, 40h ; IFDIR ; 40h 3916 <1> ; ;jz short namei_err ; not a sub directory ! 3917 <1> ; shl al, 1 ; 80h (IFREG flag) -> cf = 1 3918 <1> ; jnc short namei_err ; not a regular file ! (device!?) 3919 <1> ; shl al, 1 ; 80h (IFDIR flag) -> cf = 1 3920 <1> ; jnc short namei_err ; not a sub directory ! 3921 <1> 3922 <1> ; 27/03/2021 3923 00004933 E8F9000000 <1> call chk_dir ; check for directory, jump to 'error' if not 3924 <1> ; CPU will be here if the inode is a (valid) directory inode 3925 <1> 3926 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 3927 <1> ;xor eax, eax 3928 <1> ;mov [u.off], eax ; 0 3929 <1> ; 01/05/2021 - Retro UNIX 386 v2 inode structure 3930 00004938 A1[486B0000] <1> mov eax, [i.size] 3931 <1> ;mov ax, [i.size] 3932 0000493D A3[BC6E0000] <1> mov [u.dirp], eax 3933 <1> ; mov i.size,u.dirp / put size of directory in u.dirp 3934 <1> ; clr u.off / u.off is file offset used by user 3935 <1> ; 18/10/2021 3936 00004942 31C0 <1> xor eax, eax 3937 <1> ;mov [u.off], eax ; 0 3938 00004944 BB[C46E0000] <1> mov ebx, u.off 3939 00004949 8903 <1> mov [ebx], eax ; mov dword [u.off], 0 3940 <1> ; 3941 0000494B 891D[B86E0000] <1> mov [u.fofp], ebx ; u.off ; 18/10/2021 3942 <1> ;mov dword [u.fofp], u.off 3943 <1> ; mov $u.off,u.fofp / u.fofp is a pointer to 3944 <1> ; / the offset portion of fsp entry 3945 <1> namei_3: ; 2: 3946 00004951 C705[C86E0000]- <1> mov dword [u.base], u.dirbuf 3946 00004957 [DC6E0000] <1> 3947 <1> ; mov $u.dirbuf,u.base / u.dirbuf holds a file name 3948 <1> ; / copied from a directory 3949 0000495B C705[CC6E0000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 3949 00004963 0000 <1> 3950 <1> ; mov $10.,u.count / u.count is byte count 3951 <1> ; / for reads and writes 3952 <1> ;mov ax, [ii] 3953 <1> ; 18/10/2021 3954 00004965 A1[806E0000] <1> mov eax, [ii] ; (32 bit inode number) 3955 <1> ; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall') 3956 0000496A FE05[166F0000] <1> inc byte [u.kcall] ; the caller is 'namei' sign 3957 00004970 E84A0C0000 <1> call readi 3958 <1> ; jsr r0,readi / read 10. bytes of file 3959 <1> ; with i-number (r1); i.e. read a directory entry 3960 <1> 3961 00004975 8B0D[D06E0000] <1> mov ecx, [u.nread] 3962 0000497B 09C9 <1> or ecx, ecx 3963 <1> ; tst u.nread 3964 0000497D 741A <1> jz short nib 3965 <1> ; ble nib / gives error return 3966 <1> ; 3967 <1> ;mov bx, [u.dirbuf] 3968 <1> ;and bx, bx 3969 <1> ; 18/10/2021 3970 0000497F 66F705[DC6E0000]FF- <1> test word [u.dirbuf], 0FFFFh 3970 00004987 FF <1> 3971 <1> ; tst u.dirbuf / 3972 00004988 7513 <1> jnz short namei_4 3973 <1> ; bne 3f / branch when active directory entry 3974 <1> ; / (i-node word in entry non zero) 3975 0000498A A1[C46E0000] <1> mov eax, [u.off] 3976 0000498F 83E810 <1> sub eax, 16 ; 04/12/2015 (10 -> 16) 3977 00004992 A3[BC6E0000] <1> mov [u.dirp], eax 3978 <1> ; mov u.off,u.dirp 3979 <1> ; sub $10.,u.dirp 3980 00004997 EBB8 <1> jmp short namei_3 3981 <1> ; br 2b 3982 <1> 3983 <1> ; 18/07/2013 3984 <1> nib: 3985 00004999 31C0 <1> xor eax, eax ; xor ax, ax ; ax = 0 -> file not found 3986 0000499B F9 <1> stc 3987 <1> nig: 3988 0000499C C3 <1> retn 3989 <1> 3990 <1> ; 27/03/2021 3991 <1> ;namei_err: 3992 <1> ; 16/06/2015 3993 <1> ; mov dword [u.error], ERR_NOT_DIR ; 'not a directory !' error 3994 <1> ; jmp error 3995 <1> 3996 <1> namei_4: ; 3: 3997 <1> ; 18/10/2015 3998 <1> ; 12/10/2015 3999 <1> ; 21/08/2015 4000 <1> ; 18/07/2015 4001 0000499D 8B2D[C06E0000] <1> mov ebp, [u.namep] 4002 <1> ; mov u.namep,r2 / u.namep points into a file name string 4003 000049A3 BF[DE6E0000] <1> mov edi, u.dirbuf + 2 4004 <1> ; mov $u.dirbuf+2,r3 / points to file name of directory entry 4005 <1> ; 18/10/2015 4006 000049A8 8B35[286F0000] <1> mov esi, [nbase] 4007 <1> ;mov cx, [ncount] 4008 <1> ;and cx, cx 4009 <1> ; 18/10/2021 4010 000049AE 8B0D[2C6F0000] <1> mov ecx, [ncount] 4011 000049B4 21C9 <1> and ecx, ecx 4012 000049B6 7505 <1> jnz short namei_5 4013 <1> ; 4014 000049B8 E849000000 <1> call trans_addr_nm ; convert virtual address to physical 4015 <1> ; esi = physical address (page start + offset) 4016 <1> ; ecx = byte count in the page 4017 <1> namei_5: ; 3: 4018 000049BD 45 <1> inc ebp ; 18/07/2015 4019 000049BE AC <1> lodsb ; mov al, [esi] ; inc esi (al = r4) 4020 <1> ; movb (r2)+,r4 / move a character from u.namep string into r4 4021 000049BF 08C0 <1> or al, al 4022 000049C1 741C <1> jz short namei_7 4023 <1> ; beq 3f / if char is nul, then the last char in string 4024 <1> ; / has been moved 4025 000049C3 3C2F <1> cmp al, '/' 4026 <1> ; cmp r4,$'/ / is char a 4027 000049C5 7418 <1> je short namei_7 4028 <1> ; beq 3f 4029 <1> ; 12/10/2015 4030 <1> ;dec cx ; remain byte count in the page 4031 000049C7 49 <1> dec ecx ; 18/10/2021 4032 000049C8 7505 <1> jnz short namei_6 4033 000049CA E837000000 <1> call trans_addr_nm ; convert virtual address to physical 4034 <1> ; esi = physical address (page start + offset) 4035 <1> ; ecx = byte count in the page 4036 <1> namei_6: 4037 000049CF 81FF[EC6E0000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 4038 <1> ; cmp r3,$u.dirbuf+10. / have I checked 4039 <1> ; / all 8 bytes of file name 4040 000049D5 74E6 <1> je short namei_5 4041 <1> ; beq 3b 4042 000049D7 AE <1> scasb 4043 <1> ; cmpb (r3)+,r4 / compare char in u.namep string to file name 4044 <1> ; / char read from directory 4045 000049D8 74E3 <1> je short namei_5 4046 <1> ; beq 3b / branch if chars match 4047 <1> namei_10: 4048 000049DA E972FFFFFF <1> jmp namei_3 ; 2b 4049 <1> ; br 2b / file names do not match go to next directory entry 4050 <1> namei_7: ; 3: 4051 000049DF 81FF[EC6E0000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 4052 <1> ; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched 4053 000049E5 7405 <1> je short namei_8 4054 <1> ; beq 3f 4055 <1> ;mov ah, [edi] 4056 <1> ;;inc edi 4057 <1> ;and ah, ah 4058 <1> ; ; tstb (r3)+ / 4059 <1> ; 18/10/2021 4060 000049E7 F607FF <1> test byte [edi], 0FFh 4061 <1> ; 08/01/2021 4062 000049EA 75EE <1> jnz short namei_10 4063 <1> ;jnz namei_3 4064 <1> ; bne 2b 4065 <1> namei_8: ; 3 4066 000049EC 892D[C06E0000] <1> mov [u.namep], ebp ; 18/07/2015 4067 <1> ; mov r2,u.namep / u.namep points to char 4068 <1> ; / following a / or nul 4069 <1> ;mov bx, [u.dirbuf] 4070 <1> ; mov u.dirbuf,r1 / move i-node number in directory 4071 <1> ; / entry to r1 4072 000049F2 20C0 <1> and al, al 4073 <1> ; tst r4 / if r4 = 0 the end of file name reached, 4074 <1> ; / if r4 = then go to next directory 4075 <1> ;mov ax, bx 4076 <1> ;mov ax, [u.dirbuf] ; 17/06/2015 4077 <1> ; 18/10/2021 (16 bit inode number in 32 bit register) 4078 000049F4 0FB705[DC6E0000] <1> movzx eax, word [u.dirbuf] 4079 <1> ; 19/12/2021 4080 000049FB E91CFFFFFF <1> jmp namei_9 ; eax = inode number 4081 <1> ; jnz namei_2 4082 <1> ; ; bne 1b 4083 <1> ; ; AX = i-number of the file 4084 <1> ;;;nig: 4085 <1> ; retn 4086 <1> ; tst (r0)+ / gives non-error return 4087 <1> ;;nib: 4088 <1> ;; xor ax, ax ; Retro UNIX 8086 v1 modification ! 4089 <1> ; ax = 0 -> file not found 4090 <1> ;; stc ; 27/05/2013 4091 <1> ;; retn 4092 <1> ; rts r0 4093 <1> 4094 <1> trans_addr_nmbp: 4095 <1> ; 18/10/2021 - Retro UNIX 386 v2 4096 <1> ; 18/10/2015 4097 <1> ; 12/10/2015 4098 00004A00 8B2D[C06E0000] <1> mov ebp, [u.namep] 4099 <1> trans_addr_nm: 4100 <1> ; 18/10/2021 - Retro UNIX 386 v2 4101 <1> ; Convert virtual (pathname) address to physical address 4102 <1> ; (Retro UNIX 386 v1 feature only !) 4103 <1> ; 18/10/2015 4104 <1> ; 12/10/2015 (u.pnbase & u.pncount has been removed from code) 4105 <1> ; 02/07/2015 4106 <1> ; 17/06/2015 4107 <1> ; 16/06/2015 4108 <1> ; 4109 <1> ; INPUTS: 4110 <1> ; ebp = pathname address (virtual) ; [u.namep] 4111 <1> ; [u.pgdir] = user's page directory 4112 <1> ; OUTPUT: 4113 <1> ; esi = physical address of the pathname 4114 <1> ; ecx = remain byte count in the page 4115 <1> ; 4116 <1> ; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021 4117 <1> ; 4118 <1> 4119 <1> ; 18/10/2021 4120 00004A06 29C9 <1> sub ecx, ecx 4121 <1> ; 4122 <1> ;cmp dword [u.ppgdir], 0 ; /etc/init ? (sysexec) 4123 00004A08 390D[086F0000] <1> cmp [u.ppgdir], ecx ; 0 ; 18/10/2021 4124 00004A0E 7618 <1> jna short trans_addr_nmk ; the caller is os kernel; 4125 <1> ; it is already physical address 4126 00004A10 50 <1> push eax 4127 00004A11 89EB <1> mov ebx, ebp ; [u.namep] ; pathname address (virtual) 4128 00004A13 E83CE8FFFF <1> call get_physical_addr ; get physical address 4129 00004A18 7204 <1> jc short tr_addr_nm_err 4130 <1> ; 18/10/2015 4131 <1> ; eax = physical address 4132 <1> ; ecx = remain byte count in page (1-4096) ; 18/10/2021 4133 <1> ; 12/10/2015 (cx = [u.pncount]) 4134 00004A1A 89C6 <1> mov esi, eax ; 12/10/2015 (esi=[u.pnbase]) 4135 00004A1C 58 <1> pop eax 4136 00004A1D C3 <1> retn 4137 <1> 4138 <1> tr_addr_nm_err: 4139 00004A1E A3[186F0000] <1> mov [u.error], eax 4140 <1> ;pop eax 4141 00004A23 E984F1FFFF <1> jmp error 4142 <1> 4143 <1> trans_addr_nmk: 4144 <1> ; 12/10/2015 4145 <1> ; 02/07/2015 4146 00004A28 8B35[C06E0000] <1> mov esi, [u.namep] ; [u.pnbase] 4147 <1> ;mov cx, PAGE_SIZE ; 4096 ; [u.pncount] 4148 <1> ; 18/10/2021 4149 00004A2E B510 <1> mov ch, PAGE_SIZE/256 4150 00004A30 C3 <1> retn 4151 <1> 4152 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 4153 <1> chk_dir: 4154 <1> ; 12/06/2021 4155 <1> ; 27/03/2021 (Retro UNIX 386 v2) 4156 <1> ; Check for directory inode 4157 <1> 4158 00004A31 8A0D[416B0000] <1> mov cl, [i.flgs+1] 4159 <1> ;test cl, 80h ; IFREG ; 80h 4160 <1> ;jz short chk_dir_err ; not a regular file ! (device!?) 4161 <1> ;and cl, 40h ; IFDIR ; 40h 4162 <1> ;jz short chk_dir_err ; not a sub directory ! 4163 00004A37 D0E1 <1> shl cl, 1 ; 80h (IFREG flag) -> cf = 1 4164 00004A39 7305 <1> jnc short chk_dir_err ; not a regular file ! (device!?) 4165 00004A3B D0E1 <1> shl cl, 1 ; 40h (IFDIR flag) -> cf = 1 4166 00004A3D 7301 <1> jnc short chk_dir_err ; not a sub directory ! 4167 <1> ; 12/06/2021 4168 00004A3F C3 <1> retn 4169 <1> chk_dir_err: 4170 00004A40 C705[186F0000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 4170 00004A48 0000 <1> 4171 00004A4A E95DF1FFFF <1> jmp error 4172 <1> 4173 <1> ; 08/01/2022 4174 <1> ; 01/01/2022 - Retro UNIX 386 v1.2 (runix v2 fs inode) 4175 <1> syschdir: 4176 <1> ; / makes the directory specified in the argument 4177 <1> ; / the current directory 4178 <1> ; 4179 <1> ; 08/01/2022 (Retro UNIX 386 v1.2) 4180 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4181 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 4182 <1> ; 4183 <1> ; 'syschdir' makes the directory specified in its argument 4184 <1> ; the current working directory. 4185 <1> ; 4186 <1> ; Calling sequence: 4187 <1> ; syschdir; name 4188 <1> ; Arguments: 4189 <1> ; name - address of the path name of a directory 4190 <1> ; terminated by nul byte. 4191 <1> ; Inputs: - 4192 <1> ; Outputs: - 4193 <1> ; ............................................................... 4194 <1> ; 4195 <1> ; Retro UNIX 8086 v1 modification: 4196 <1> ; The user/application program puts address of 4197 <1> ; the path name in BX register as 'syschdir' 4198 <1> ; system call argument. 4199 <1> 4200 00004A4F 891D[C06E0000] <1> mov [u.namep], ebx 4201 <1> ;jsr r0,arg; u.namep / u.namep points to path name 4202 00004A55 E888FEFFFF <1> call namei 4203 <1> ; jsr r0,namei / find its i-number 4204 <1> ;jc error 4205 <1> ; br error3 4206 00004A5A 730F <1> jnc short syschdir0 4207 <1> ; 'directory not found !' error 4208 00004A5C C705[186F0000]0C00- <1> mov dword [u.error], ERR_DIR_NOT_FOUND ; 12 4208 00004A64 0000 <1> 4209 00004A66 E941F1FFFF <1> jmp error 4210 <1> syschdir0: 4211 <1> ; 08/01/2022 4212 00004A6B 66BA0001 <1> mov dx, 100h ; read access ; IREAD (100h) 4213 00004A6F E8E6080000 <1> call access 4214 <1> ; jsr r0,access; 2 / get i-node into core 4215 <1> 4216 <1> ; 01/01/2022 (runix v2 fs inode flag) 4217 00004A74 F605[416B0000]80 <1> test byte [i.flgs+1], 80h ; regular file ? 4218 00004A7B 7409 <1> jz short syschdir2 ; no, error! 4219 00004A7D F605[416B0000]40 <1> test byte [i.flgs+1], 40h ; directory flag ? 4220 <1> ;test word [i.flgs], 4000h 4221 <1> ; bit $40000,i.flgs / is it a directory? 4222 <1> ;jz error 4223 <1> ; beq error3 / no error 4224 00004A84 750F <1> jnz short syschdir1 4225 <1> syschdir2: 4226 00004A86 C705[186F0000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 4226 00004A8E 0000 <1> 4227 00004A90 E917F1FFFF <1> jmp error 4228 <1> syschdir1: 4229 00004A95 66A3[A86E0000] <1> mov [u.cdir], ax 4230 <1> ; mov r1,u.cdir / move i-number to users 4231 <1> ; / current directory 4232 <1> ;mov ax, [cdev] 4233 <1> ;mov [u.cdrv], ax 4234 <1> ; 08/01/2022 4235 00004A9B A0[856E0000] <1> mov al, [cdev] 4236 00004AA0 A2[AC6E0000] <1> mov [u.cdrv], al 4237 <1> ; mov cdev,u.cdev / move its device to users 4238 <1> ; / current device 4239 00004AA5 E922F1FFFF <1> jmp sysret 4240 <1> ; br sysret3 4241 <1> 4242 <1> syschmod: ; < change mode of file > 4243 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 4244 <1> ; 01/05/2021 4245 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 4246 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4247 <1> ; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1) 4248 <1> ; 4249 <1> ; 'syschmod' changes mode of the file whose name is given as 4250 <1> ; null terminated string pointed to by 'name' has it's mode 4251 <1> ; changed to 'mode'. 4252 <1> ; 4253 <1> ; Calling sequence: 4254 <1> ; syschmod; name; mode 4255 <1> ; Arguments: 4256 <1> ; name - address of the file name 4257 <1> ; terminated by null byte. 4258 <1> ; mode - (new) mode/flags < attributes > 4259 <1> ; 4260 <1> ; Inputs: - 4261 <1> ; Outputs: - 4262 <1> ; ............................................................... 4263 <1> ; 4264 <1> ; Retro UNIX 8086 v1 modification: 4265 <1> ; 'syschmod' system call has two arguments; so, 4266 <1> ; * 1st argument, name is pointed to by BX register 4267 <1> ; * 2nd argument, mode is in CX register 4268 <1> ; 4269 <1> ; Mode bits (Flags): 4270 <1> ; bit 15 - 'i-node is allocated' flag (8000h) 4271 <1> ; bit 14 - directory flag (4000h) 4272 <1> ; bit 13 - file has modified flag (always on) (2000h) 4273 <1> ; bit 12 - large file flag (1000h) 4274 <1> ; bit 6,7,8,9,10,11 are not used (undefined) 4275 <1> ; bit 5 - set user ID on execution flag (20h) 4276 <1> ; bit 4 - executable flag (10h) 4277 <1> ; bit 3 - read permission for owner (08h) 4278 <1> ; bit 2 - write permission for owner (04h) 4279 <1> ; bit 1 - read permission for non-owner (02h) 4280 <1> ; bit 0 - write permission for non-owner (01h) 4281 <1> 4282 <1> ; 01/05/2021 (07/02/2020) 4283 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files 4284 <1> ; bit 15 - IFREG - regular file (8000h) 4285 <1> ; bit 14 - IFDIR - directory (4000h) 4286 <1> ; bit 13 - IRSVD - 0 - reserved/mounted bit (2000h) 4287 <1> ; bit 12 - ILARG - large file addressing bit (1000h) 4288 <1> ; bit 11 - ISUID - set user id on exec (800h) 4289 <1> ; bit 10 - ISGID - set group id on exec (400h) 4290 <1> ; bit 9 - IEXTT - 0 - use extents (200h) 4291 <1> ; bit 8 - IREAD - read, owner (100h) 4292 <1> ; bit 7 - IWRITE - write, owner (80h) 4293 <1> ; bit 6 - IEXEC - execute, owner (40h) 4294 <1> ; bit 5 - read, group (20h) 4295 <1> ; bit 4 - write, group (10h) 4296 <1> ; bit 3 - execute, group (08h) 4297 <1> ; bit 2 - read, others (04h) 4298 <1> ; bit 1 - write, others (02h) 4299 <1> ; bit 0 - execute, others (01h) 4300 <1> ; 4301 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices 4302 <1> ; bit 15 - IFREG - 0 - device file (8000h) 4303 <1> ; bit 14 - IFBLK - block device (4000h) 4304 <1> ; bit 13 - IFCHR - 1 - character special (2000h) 4305 <1> ; bit 12 - IFIFO - fifo special (1000h) 4306 <1> ; bit 11 - IPIPE - pipe special (800h) 4307 <1> ; bit 10 - IREDIR - redirected (400h) 4308 <1> ; bit 9 - IEXTR - external device driver (200h) 4309 <1> ; bit 8 - IREAD - read, owner (100h) 4310 <1> ; bit 7 - IWRITE - write, owner (80h) 4311 <1> ; bit 6 - IEXEC - execute, owner (40h) 4312 <1> ; bit 5 - read, group (20h) 4313 <1> ; bit 4 - write, group (10h) 4314 <1> ; bit 3 - execute, group (08h) 4315 <1> ; bit 2 - read, others (04h) 4316 <1> ; bit 1 - write, others (02h) 4317 <1> ; bit 0 - execute, others (01h) 4318 <1> 4319 <1> ; / name; mode 4320 00004AAA E870000000 <1> call isown 4321 <1> ;jsr r0,isown / get the i-node and check user status 4322 <1> 4323 <1> ; 25/05/2020 4324 <1> ; AL = new mode (return form 'isown', ecx -> eax) 4325 <1> 4326 <1> ;test word [i.flgs], 4000h 4327 <1> ; ; bit $40000,i.flgs / directory? 4328 <1> ;jz short syschmod1 4329 <1> ; ; beq 2f / no 4330 <1> ;; AL = (new) mode 4331 <1> ;and al, 0CFh ; 11001111b (clears bit 4 & 5) 4332 <1> ; ; bic $60,r2 / su & ex / yes, clear set user id and 4333 <1> ; ; / executable modes 4334 <1> 4335 <1> ; 01/05/2021 4336 <1> ; AX = new mode (9 bits for devices or 12 bits files) 4337 00004AAF 8A15[416B0000] <1> mov dl, [i.flgs+1] 4338 <1> ; 09/01/2022 4339 00004AB5 F6C280 <1> test dl, 80h ; regular file 4340 00004AB8 7416 <1> jz short syschmod1 ; device file 4341 00004ABA F6C240 <1> test dl, 40h ; directory 4342 00004ABD 7511 <1> jnz short syschmod1 4343 <1> ; regular file 4344 00004ABF 6625FF0D <1> and ax, 0DFFh ; clear bit 9, 12-15 (of new mode) 4345 <1> ; clear bit 8,10,11 of current mode/flags 4346 00004AC3 80E2F2 <1> and dl, 0F2h ; and dl, 11110010b 4347 <1> syschmod0: 4348 00004AC6 08D4 <1> or ah, dl 4349 00004AC8 66A3[406B0000] <1> mov [i.flgs], ax 4350 00004ACE EB3E <1> jmp short syschmod2 4351 <1> syschmod1: 4352 <1> ; device or directory 4353 00004AD0 6625B601 <1> and ax, 1B6h ; clear bit 9-15 & bit 0,3,6 (EXEC bits) 4354 <1> ; clear bit 8 (IREAD) of current mode/flags 4355 <1> ; (dl contains flag bits 8-15) 4356 00004AD4 80E2FE <1> and dl, ~1 ; and dl, 11111110b 4357 00004AD7 EBED <1> jmp short syschmod0 4358 <1> 4359 <1> ;syschmod1: ; 2: 4360 <1> ;mov [i.flgs], al 4361 <1> ; ; movb r2,i.flgs / move remaining mode to i.flgs 4362 <1> 4363 <1> ; 25/05/2020 - Retro UNIX 386 v2 4364 <1> ;mov byte [imodx], 1 ; (flag means file data is same 4365 <1> ; ; but inode's itself has been modified) 4366 <1> ;call setimod 4367 <1> ;jmp sysret 4368 <1> 4369 <1> ; 25/05/2020 4370 <1> ;jmp short syschmod2 4371 <1> 4372 <1> syschown: ; < change owner of file > 4373 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 4374 <1> ; 01/05/2021 4375 <1> ; (change owner and group ID of file) 4376 <1> ; 02/04/2021 4377 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 4378 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4379 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4380 <1> ; 4381 <1> ; 'syschown' changes the owner of the file whose name is given 4382 <1> ; as null terminated string pointed to by 'name' has it's owner 4383 <1> ; changed to 'owner' 4384 <1> ; 4385 <1> ; Calling sequence: 4386 <1> ; syschown; name; owner 4387 <1> ; Arguments: 4388 <1> ; name - address of the file name 4389 <1> ; terminated by null byte. 4390 <1> ; owner - (new) owner (number/ID) 4391 <1> ; 4392 <1> ; Inputs: - 4393 <1> ; Outputs: - 4394 <1> ; ............................................................... 4395 <1> ; 4396 <1> ; Retro UNIX 8086 v1 modification: 4397 <1> ; 'syschown' system call has two arguments; so, 4398 <1> ; * 1st argument, name is pointed to by BX register 4399 <1> ; * 2nd argument, owner number is in CX register 4400 <1> ; 4401 <1> ; / name; owner 4402 00004AD9 E841000000 <1> call isown 4403 <1> ; jsr r0,isown / get the i-node and check user status 4404 <1> 4405 <1> ; 25/05/2020 4406 <1> ; AL = owner number (return form 'isown', ecx -> eax) 4407 <1> ; 02/04/2021 4408 <1> ; AX = owner number 4409 <1> ; 01/05/2021 4410 <1> ; byte 2 of EAX is group number 4411 <1> 4412 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 4413 <1> ; ; tstb u.uid / super user 4414 <1> ;jz short syschown1 4415 <1> ; ; beq 2f / yes, 2f 4416 00004ADE 66833D[F66E0000]00 <1> cmp word [u.uid], 0 4417 00004AE6 7418 <1> jz short syschown1 4418 <1> 4419 <1> ;test byte [i.flgs], 20h ; 32 4420 <1> ; ; bit $40,i.flgs / no, set userid on execution? 4421 <1> ;;jnz error 4422 <1> ; ; bne 3f / yes error, could create Trojan Horses 4423 <1> ;jz short syschown1 4424 <1> ; 01/05/2021 4425 <1> ; check set user id on execution flag 4426 <1> ; (protection against Trojan Horses) 4427 <1> 4428 <1> ; ((Note: UNIX v7 x86 'chown' source code in 'sys4.c' 4429 <1> ; does not contain this protection)) 4430 <1> 4431 <1> ; 09/01/2022 4432 00004AE8 F605[416B0000]08 <1> test byte [i.flgs+1], 08h ; ISUID ; RUNIX v2 inode flags 4433 00004AEF 740F <1> jz short syschown1 4434 <1> 4435 <1> ; 'permission denied !' 4436 00004AF1 C705[186F0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; 11 4436 00004AF9 0000 <1> 4437 00004AFB E9ACF0FFFF <1> jmp error 4438 <1> syschown1: ; 2: 4439 <1> ;; AL = owner (number/ID) 4440 <1> ;mov [i.uid], al ; 23/06/2015 4441 <1> ; ; movb r2,i.uid / no, put the new owners id 4442 <1> ; ; / in the i-node 4443 <1> ; 02/04/2021 (Retro UNIX 386 v2) 4444 <1> ; AX = owner number 4445 00004B00 66A3[446B0000] <1> mov [i.uid], ax ; owner 4446 <1> ; 01/05/2021 (Retro UNIX 386 v2) 4447 00004B06 C1E810 <1> shr eax, 16 4448 00004B09 A2[466B0000] <1> mov [i.gid], al ; group 4449 <1> syschown2: 4450 <1> ; 25/05/2020 - Retro UNIX 386 v2 4451 <1> syschmod2: 4452 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 4453 00004B0E C605[976E0000]01 <1> mov byte [imodx], 1 ; (flag means file data is same 4454 <1> ; but inode's itself has been modified) 4455 00004B15 E8F5080000 <1> call setimod ; 25/05/2020 4456 <1> 4457 00004B1A E9ADF0FFFF <1> jmp sysret 4458 <1> 4459 <1> ; 1: 4460 <1> ; jmp sysret4 4461 <1> ; 3: 4462 <1> ; jmp error 4463 <1> 4464 <1> isown: 4465 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 4466 <1> ; 06/11/2021 4467 <1> ; 12/06/2021 4468 <1> ; 01/05/2021 4469 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 4470 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4471 <1> ; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1) 4472 <1> ; 4473 <1> ; 'isown' is given a file name (the 1st argument). 4474 <1> ; It find the i-number of that file via 'namei' 4475 <1> ; then gets the i-node into core via 'iget'. 4476 <1> ; It then tests to see if the user is super user. 4477 <1> ; If not, it checks to see if the user is owner of 4478 <1> ; the file. If he is not an error occurs. 4479 <1> ; If user is the owner 'setimod' is called to indicate 4480 <1> ; the inode has been modified and the 2nd argument of 4481 <1> ; the call is put in r2. 4482 <1> ; 4483 <1> ; INPUTS -> 4484 <1> ; arguments of syschmod and syschown calls 4485 <1> ; OUTPUTS -> 4486 <1> ; u.uid - id of user 4487 <1> ; imod - set to a 1 4488 <1> ; r2 - contains second argument of the system call 4489 <1> ; 4490 <1> ; ((AX=R2) output as 2nd argument) 4491 <1> ; 4492 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 4493 <1> ; 4494 <1> ; jsr r0,arg2 / u.namep points to file name 4495 <1> ;; ! 2nd argument on top of stack ! 4496 <1> ;; 22/06/2015 - 32 bit modifications 4497 <1> ;; 07/07/2013 4498 00004B1F 891D[C06E0000] <1> mov [u.namep], ebx ;; 1st argument 4499 00004B25 51 <1> push ecx ;* ; 2nd argument 4500 <1> ;; 4501 00004B26 E8B7FDFFFF <1> call namei 4502 <1> ; jsr r0,namei / get its i-number 4503 <1> ; Retro UNIX 8086 v1 modification ! 4504 <1> ; ax = 0 -> file not found 4505 <1> ;and ax, ax 4506 <1> ;jz error 4507 <1> ;jc error ; 27/05/2013 4508 <1> ; br error3 4509 00004B2B 730F <1> jnc short isown1 ; 25/05/2020 (isown0 -> isown1) 4510 <1> ; 'file not found !' error 4511 00004B2D C705[186F0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 4511 00004B35 0000 <1> 4512 00004B37 E970F0FFFF <1> jmp error 4513 <1> isown1: 4514 00004B3C E82F070000 <1> call iget 4515 <1> ; jsr r0,iget / get i-node into core 4516 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 4517 <1> ;; 06/11/2021 4518 <1> ;jnc short isown3 4519 <1> ;mov [u.error], eax 4520 <1> ;jmp error 4521 <1> ;isown3: 4522 <1> ; check if it is super user ID 4523 <1> ; 09/01/2022 (Retro UNIX 386 v2 fs inode structure) 4524 00004B41 66A1[F66E0000] <1> mov ax, [u.uid] 4525 00004B47 6609C0 <1> or ax, ax 4526 <1> ;mov al, [u.uid] ; 02/08/2013 4527 <1> ;or al, al 4528 <1> ; tstb u.uid / super user? 4529 <1> ; 12/06/2021 4530 00004B4A 7425 <1> jz short isown2 ; 25/05/2020 (isown1 -> isown2) 4531 <1> ; beq 1f / yes, branch 4532 <1> 4533 <1> ; check user ID (if same with file's owner) 4534 00004B4C 663B05[446B0000] <1> cmp ax, [i.uid] ; 09/01/2022 4535 <1> ;cmp al, [i.uid] 4536 <1> ; cmpb i.uid,u.uid / no, is this the owner of 4537 <1> ; / the file 4538 <1> ;jne error 4539 <1> ; beq 1f / yes 4540 <1> ; jmp error3 / no, error 4541 <1> ;je short isown2 ; 25/05/2020 4542 <1> ; 01/05/2021 4543 00004B53 750D <1> jne short isown_err 4544 <1> 4545 <1> ; 01/05/2021 4546 <1> ;mov ax, [u.uid] 4547 <1> ;or ax, ax 4548 <1> ;jz short isown2 4549 <1> ;cmp ax, [i.uid] 4550 <1> ;;je short isown2 4551 <1> ;jne short isown_err 4552 <1> 4553 <1> ; 01/05/2021 4554 <1> ; ((Note: UNIX v7 x86 'chown', 'chmod' procedures 4555 <1> ; and their sub procedures do not check group ID)) 4556 <1> ; (('sys4.c', 'fio.c')) 4557 <1> 4558 <1> ; 01/05/2021 4559 <1> ; check group ID (if same with group of file's owner) 4560 00004B55 A0[FA6E0000] <1> mov al, [u.gid] 4561 00004B5A 3A05[466B0000] <1> cmp al, [i.gid] 4562 00004B60 740F <1> je short isown2 4563 <1> isown_err: 4564 00004B62 C705[186F0000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER ; 11 4564 00004B6A 0000 <1> 4565 <1> ; 'permission denied !' error 4566 00004B6C E93BF0FFFF <1> jmp error 4567 <1> 4568 <1> ; 25/05/2020 4569 <1> ;isown2: ; 1: 4570 <1> ; call setimod 4571 <1> ; ; jsr r0,setimod / indicates 4572 <1> ; ; ; / i-node has been modified 4573 <1> isown2: 4574 <1> ; 25/05/2020 4575 00004B71 58 <1> pop eax ;* ; 2nd argument 4576 <1> ; mov (sp)+,r2 / mode is put in r2 4577 <1> ; / (u.off put on stack with 2nd arg) 4578 00004B72 C3 <1> retn 4579 <1> 4580 <1> ;;arg: ; < get system call arguments > 4581 <1> ; 'arg' extracts an argument for a routine whose call is 4582 <1> ; of form: 4583 <1> ; sys 'routine' ; arg1 4584 <1> ; or 4585 <1> ; sys 'routine' ; arg1 ; arg2 4586 <1> ; or 4587 <1> ; sys 'routine' ; arg1;...;arg10 (sys exec) 4588 <1> ; 4589 <1> ; INPUTS -> 4590 <1> ; u.sp+18 - contains a pointer to one of arg1..argn 4591 <1> ; This pointers's value is actually the value of 4592 <1> ; update pc at the the trap to sysent (unkni) is 4593 <1> ; made to process the sys instruction 4594 <1> ; r0 - contains the return address for the routine 4595 <1> ; that called arg. The data in the word pointer 4596 <1> ; to by the return address is used as address 4597 <1> ; in which the extracted argument is stored 4598 <1> ; 4599 <1> ; OUTPUTS -> 4600 <1> ; 'address' - contains the extracted argument 4601 <1> ; u.sp+18 - is incremented by 2 4602 <1> ; r1 - contains the extracted argument 4603 <1> ; r0 - points to the next instruction to be 4604 <1> ; executed in the calling routine. 4605 <1> ; 4606 <1> 4607 <1> ; mov u.sp,r1 4608 <1> ; mov *18.(r1),*(r0)+ / put argument of system call 4609 <1> ; / into argument of arg2 4610 <1> ; add $2,18.(r1) / point pc on stack 4611 <1> ; / to next system argument 4612 <1> ; rts r0 4613 <1> 4614 <1> ;;arg2: ; < get system calls arguments - with file name pointer> 4615 <1> ; 'arg2' takes first argument in system call 4616 <1> ; (pointer to name of the file) and puts it in location 4617 <1> ; u.namep; takes second argument and puts it in u.off 4618 <1> ; and on top of the stack 4619 <1> ; 4620 <1> ; INPUTS -> 4621 <1> ; u.sp, r0 4622 <1> ; 4623 <1> ; OUTPUTS -> 4624 <1> ; u.namep 4625 <1> ; u.off 4626 <1> ; u.off pushed on stack 4627 <1> ; r1 4628 <1> ; 4629 <1> 4630 <1> ; jsr r0,arg; u.namep / u.namep contains value of 4631 <1> ; / first arg in sys call 4632 <1> ; jsr r0,arg; u.off / u.off contains value of 4633 <1> ; / second arg in sys call 4634 <1> ; mov r0,r1 / r0 points to calling routine 4635 <1> ; mov (sp),r0 / put operation code back in r0 4636 <1> ; mov u.off,(sp) / put pointer to second argument 4637 <1> ; / on stack 4638 <1> ; jmp (r1) / return to calling routine 4639 <1> 4640 <1> systime: ; / get time of year 4641 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4642 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 4643 <1> ; 4644 <1> ; 20/06/2013 4645 <1> ; 'systime' gets the time of the year. 4646 <1> ; The present time is put on the stack. 4647 <1> ; 4648 <1> ; Calling sequence: 4649 <1> ; systime 4650 <1> ; Arguments: - 4651 <1> ; 4652 <1> ; Inputs: - 4653 <1> ; Outputs: sp+2, sp+4 - present time 4654 <1> ; ............................................................... 4655 <1> ; 4656 <1> ; Retro UNIX 8086 v1 modification: 4657 <1> ; 'systime' system call will return to the user 4658 <1> ; with unix time (epoch) in DX:AX register pair 4659 <1> ; 4660 <1> ; !! Major modification on original Unix v1 'systime' 4661 <1> ; system call for PC compatibility !! 4662 <1> 4663 00004B73 E851EBFFFF <1> call epoch 4664 00004B78 A3[A46E0000] <1> mov [u.r0], eax 4665 <1> ; mov s.time,4(sp) 4666 <1> ; mov s.time+2,2(sp) / put the present time 4667 <1> ; / on the stack 4668 <1> ; br sysret4 4669 00004B7D E94AF0FFFF <1> jmp sysret 4670 <1> 4671 <1> sysstime: ; / set time 4672 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 4673 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4674 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4675 <1> ; 4676 <1> ; 'sysstime' sets the time. Only super user can use this call. 4677 <1> ; 4678 <1> ; Calling sequence: 4679 <1> ; sysstime 4680 <1> ; Arguments: - 4681 <1> ; 4682 <1> ; Inputs: sp+2, sp+4 - time system is to be set to. 4683 <1> ; Outputs: - 4684 <1> ; ............................................................... 4685 <1> ; 4686 <1> ; Retro UNIX 8086 v1 modification: 4687 <1> ; the user calls 'sysstime' with unix (epoch) time 4688 <1> ; (to be set) is in CX:BX register pair as two arguments. 4689 <1> ; 4690 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 4691 <1> ; to get sysstime system call arguments from the user; 4692 <1> ; * 1st argument, lowword of unix time is in BX register 4693 <1> ; * 2nd argument, highword of unix time is in CX register 4694 <1> ; 4695 <1> ; !! Major modification on original Unix v1 'sysstime' 4696 <1> ; system call for PC compatibility !! 4697 <1> 4698 <1> ; 09/01/2022 (Retro UNIX 386 v2 fs inode structure) 4699 00004B82 66833D[F66E0000]00 <1> cmp word [u.uid], 0 ; 16 bit user ID 4700 <1> ;cmp byte [u.uid], 0 4701 <1> ; tstb u.uid / is user the super user 4702 <1> ;ja error 4703 <1> ; bne error4 / no, error 4704 00004B8A 760F <1> jna short systime1 4705 <1> ; 'permission denied !' 4706 00004B8C C705[186F0000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 4706 00004B94 0000 <1> 4707 00004B96 E911F0FFFF <1> jmp error 4708 <1> systime1: 4709 <1> ; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version) 4710 <1> ; EBX = unix (epoch) time (from user) 4711 00004B9B 89D8 <1> mov eax, ebx 4712 00004B9D E8A7ECFFFF <1> call set_date_time 4713 <1> ; mov 4(sp),s.time 4714 <1> ; mov 2(sp),s.time+2 / set the system time 4715 00004BA2 E925F0FFFF <1> jmp sysret 4716 <1> ; br sysret4 4717 <1> 4718 <1> 4719 <1> ; temporary - 01/01/2022 4720 <1> %if 0 4721 <1> 4722 <1> sysbreak: 4723 <1> ; 18/10/2015 4724 <1> ; 07/10/2015 4725 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4726 <1> ; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1) 4727 <1> ; 4728 <1> ; 'sysbreak' sets the programs break points. 4729 <1> ; It checks the current break point (u.break) to see if it is 4730 <1> ; between "core" and the stack (sp). If it is, it is made an 4731 <1> ; even address (if it was odd) and the area between u.break 4732 <1> ; and the stack is cleared. The new breakpoint is then put 4733 <1> ; in u.break and control is passed to 'sysret'. 4734 <1> ; 4735 <1> ; Calling sequence: 4736 <1> ; sysbreak; addr 4737 <1> ; Arguments: - 4738 <1> ; 4739 <1> ; Inputs: u.break - current breakpoint 4740 <1> ; Outputs: u.break - new breakpoint 4741 <1> ; area between old u.break and the stack (sp) is cleared. 4742 <1> ; ............................................................... 4743 <1> ; 4744 <1> ; Retro UNIX 8086 v1 modification: 4745 <1> ; The user/application program puts breakpoint address 4746 <1> ; in BX register as 'sysbreak' system call argument. 4747 <1> ; (argument transfer method 1) 4748 <1> ; 4749 <1> ; NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 ! 4750 <1> ; ((!'sysbreak' is not needed in Retro UNIX 8086 v1!)) 4751 <1> ; NOTE: 4752 <1> ; 'sysbreak' clears extended part (beyond of previous 4753 <1> ; 'u.break' address) of user's memory for original unix's 4754 <1> ; 'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013) 4755 <1> 4756 <1> ; mov u.break,r1 / move users break point to r1 4757 <1> ; cmp r1,$core / is it the same or lower than core? 4758 <1> ; blos 1f / yes, 1f 4759 <1> ; 23/06/2015 4760 <1> mov ebp, [u.break] ; virtual address (offset) 4761 <1> ;and ebp, ebp 4762 <1> ;jz short sysbreak_3 4763 <1> ; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!! 4764 <1> ; (Even break point address is not needed for Retro UNIX 386 v1) 4765 <1> mov edx, [u.sp] ; kernel stack at the beginning of sys call 4766 <1> add edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 4767 <1> ; 07/10/2015 4768 <1> mov [u.break], ebx ; virtual address !!! 4769 <1> ; 4770 <1> cmp ebx, [edx] ; compare new break point with 4771 <1> ; with top of user's stack (virtual!) 4772 <1> jnb short sysbreak_3 4773 <1> ; cmp r1,sp / is it the same or higher 4774 <1> ; / than the stack? 4775 <1> ; bhis 1f / yes, 1f 4776 <1> mov esi, ebx 4777 <1> sub esi, ebp ; new break point - old break point 4778 <1> jna short sysbreak_3 4779 <1> ;push ebx 4780 <1> sysbreak_1: 4781 <1> mov ebx, ebp 4782 <1> call get_physical_addr ; get physical address 4783 <1> jc tr_addr_nm_err 4784 <1> ; 18/10/2015 4785 <1> mov edi, eax 4786 <1> sub eax, eax ; 0 4787 <1> ; ECX = remain byte count in page (1-4096) 4788 <1> cmp esi, ecx 4789 <1> jnb short sysbreak_2 4790 <1> mov ecx, esi 4791 <1> sysbreak_2: 4792 <1> sub esi, ecx 4793 <1> add ebp, ecx 4794 <1> rep stosb 4795 <1> or esi, esi 4796 <1> jnz short sysbreak_1 4797 <1> ; 4798 <1> ; bit $1,r1 / is it an odd address 4799 <1> ; beq 2f / no, its even 4800 <1> ; clrb (r1)+ / yes, make it even 4801 <1> ; 2: / clear area between the break point and the stack 4802 <1> ; cmp r1,sp / is it higher or same than the stack 4803 <1> ; bhis 1f / yes, quit 4804 <1> ; clr (r1)+ / clear word 4805 <1> ; br 2b / go back 4806 <1> ;pop ebx 4807 <1> sysbreak_3: ; 1: 4808 <1> ;mov [u.break], ebx ; virtual address !!! 4809 <1> ; jsr r0,arg; u.break / put the "address" 4810 <1> ; / in u.break (set new break point) 4811 <1> ; br sysret4 / br sysret 4812 <1> jmp sysret 4813 <1> 4814 <1> maknod: 4815 <1> ; 10/01/2022 4816 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 4817 <1> ; 06/11/2021 (Retro UNIX 386 v2) 4818 <1> ; 15/08/2021 4819 <1> ; 06/05/2021 4820 <1> ; 02/05/2021 4821 <1> ; 01/04/2021 4822 <1> ; 27/03/2021 4823 <1> ; 25/03/2021 (Retro UNIX 386 v2 - Beginning) 4824 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4825 <1> ; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4826 <1> ; 4827 <1> ; 'maknod' creates an i-node and makes a directory entry 4828 <1> ; for this i-node in the current directory. 4829 <1> ; 4830 <1> ; INPUTS -> 4831 <1> ; r1 - contains mode 4832 <1> ; ii - current directory's i-number 4833 <1> ; 4834 <1> ; OUTPUTS -> 4835 <1> ; u.dirbuf - contains i-number of free i-node 4836 <1> ; i.flgs - flags in new i-node 4837 <1> ; i.uid - filled with u.uid 4838 <1> ; i.nlks - 1 is put in the number of links 4839 <1> ; i.ctim - creation time 4840 <1> ; i.ctim+2 - modification time 4841 <1> ; imod - set via call to setimod 4842 <1> ; 4843 <1> ; ((AX = R1)) input 4844 <1> ; 4845 <1> ; (Retro UNIX Prototype : 4846 <1> ; 30/10/2012 - 01/03/2013, UNIXCOPY.ASM) 4847 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 4848 <1> 4849 <1> ; 27/03/2021 4850 <1> ; INPUT: 4851 <1> ; AX = mode 4852 <1> ; 4853 <1> ; ('maknod' is called by 'syscreat' and 'sysmkdir') 4854 <1> ; (('syscreat' and 'sysmkdir' will set AX input)) 4855 <1> 4856 <1> ; 27/03/2021 4857 <1> ; Retro UNIX 386 v2 inode mode flags (ref: 'ux.s') 4858 <1> ; for File Inode: (high byte) 4859 <1> ; IFREG - 1 = regular file (8000h) 4860 <1> ; IFDIR - 1 = directory (4000h) 4861 <1> ; IRSVD - 0 = reserved bit (2000h) ; Mounted flag for dirs 4862 <1> ; ILARG - large file addressing bit (1000h) 4863 <1> ; ISUID - set user id on exec (800h) 4864 <1> ; ISGID - set group id on exec (400h) 4865 <1> ; IEXTT - 1 = use extents (200h) 4866 <1> ; IREAD - read, owner (100h) 4867 <1> ; for Device Inode: (high byte) 4868 <1> ; IFREG - 0 = device file (8000h) 4869 <1> ; IFBLK - 1 = block device (4000h) 4870 <1> ; IFCHR - character special (2000h) -always 1- 4871 <1> ; IFIFO - fifo special (1000h) 4872 <1> ; IPIPE - pipe special (800h) ; 07/02/2020 4873 <1> ; IREDIR - redirected (400h) ; 07/02/2020 4874 <1> ; IEXTR - 1 = external device driver (200h) 4875 <1> ; IREAD - read, owner (100h) 4876 <1> 4877 <1> ;; / r1 contains the mode 4878 <1> ;or ah, 80h ; 10000000b 4879 <1> ; ; bis $100000,r1 / allocate flag set 4880 <1> 4881 <1> ; high 3 bit will be checked here 4882 <1> ; (ref: unix v7 x86 source, iget.c) 4883 <1> 4884 <1> ; ; 27/03/2021 4885 <1> ; test ah, 0E0h ; 80h+40h+20h 4886 <1> ; jnz short maknod0 4887 <1> ; 4888 <1> ; ; ('syscreat' clears ILARG & IEXTT bits) 4889 <1> ; ;and ah, ~0Ch ; clear ILARG & IEXTT bits 4890 <1> ; ; ; user can set ISUID & ISGID bits 4891 <1> ; 4892 <1> ; or ah, 80h ; IFREG 4893 <1> ;maknod0: 4894 <1> push eax ; ***** ; 27/03/2021 (32 bit push, pop) 4895 <1> ; mov r1,-(sp) / put mode on stack 4896 <1> ; 31/07/2013 4897 <1> ;mov ax, [ii] ; move current i-number to AX/r1 4898 <1> ; ; mov ii,r1 / move current i-number to r1 4899 <1> ;mov dl, 1 ; owner flag mask 4900 <1> ; 15/08/2021 4901 <1> ;movzx eax, word [ii] ; move current i-number to EAX 4902 <1> ; 09/01/2022 4903 <1> mov eax, [ii] ; move current i-number to EAX 4904 <1> ; 25/03/2021 4905 <1> mov dx, 80h ; IWRITE - write,owner 4906 <1> call access 4907 <1> ; jsr r0,access; 1 / get its i-node into core 4908 <1> ; 15/08/2021 4909 <1> ; NOTE: cpu will not return here if there is a permission error 4910 <1> ; (it will jump to 'error' address from/in 'access') 4911 <1> 4912 <1> push eax ; **** ; 27/03/2021 (32 bit push, pop) 4913 <1> ; mov r1,-(sp) / put i-number on stack 4914 <1> ;mov ax, 40 4915 <1> ; ; mov $40.,r1 / r1 = 40 4916 <1> ; 27/03/2021 4917 <1> xor eax, eax 4918 <1> ;;dec ax ; 0FFFFh 4919 <1> ; 15/08/2021 4920 <1> ;dec eax ; 0FFFFFFFFh 4921 <1> ; 01/04/2021 4922 <1> ;maknod1: ; 1: / scan for a free i-node (next 4 instructions) 4923 <1> ;;inc ax 4924 <1> ; ; inc r1 / r1 = r1 + 1 4925 <1> ; 15/08/2021 4926 <1> ;inc eax 4927 <1> ; 27/03/2021 - Retro UNIX 386 v2 4928 <1> ; eax = 0 -> start from first free inode 4929 <1> ; eax > 0 -> locate this inode on the inode map buffer 4930 <1> ; NOTE: 4931 <1> ; Retro UNIX 386 v2 'imap' is mostly different than v1 'imap' 4932 <1> ; ('imap' will not check inode table) 4933 <1> call imap 4934 <1> ; jsr r0,imap / get byte address and bit position in 4935 <1> ; / inode map in r2 & m 4936 <1> ; 09/01/2022 4937 <1> ; (cpu will not return here if there would be an eror in imap) 4938 <1> ; 15/08/2021 4939 <1> ;jc short maknod_err 4940 <1> 4941 <1> ; DX (MQ) has a 1 in the calculated bit position 4942 <1> ; eBX (R2) has byte address of the byte with allocation bit 4943 <1> 4944 <1> ; 06/11/2021 4945 <1> ; ebp = superblock buffer address 4946 <1> ; eax = inode number 4947 <1> ; 10/01/2022 4948 <1> ; [ebp+SB.IMapBuffer] = physical block/sector number 4949 <1> ; of current IMAP sector 4950 <1> 4951 <1> ; 27/03/2021 4952 <1> ; If cpu is here, there is not an error 4953 <1> ; and EBX points to inode map buffer 4954 <1> ; DL has 1 at bit position which is for free inode 4955 <1> ; (E)AX = inode number 4956 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 4957 <1> ; ECX = byte offset from the (start of) inode map buffer 4958 <1> 4959 <1> ; 15/08/2021 4960 <1> maknod1: 4961 <1> ; 22/06/2015 - NOTE for next Retro UNIX version: 4962 <1> ; Inode count must be checked here 4963 <1> ; (Original UNIX v1 did not check inode count here !?) 4964 <1> test [ebx], dl 4965 <1> ; bitb mq,(r2) / is the i-node active 4966 <1> ;jnz short maknod1 4967 <1> ; ; bne 1b / yes, try the next one 4968 <1> ; 15/08/2021 4969 <1> jz short maknod3 ; free inode (inactive inode) 4970 <1> maknod2: 4971 <1> inc eax 4972 <1> call imap_x ; next call to imap (bypass 1st call code) 4973 <1> ; 10/01/2022 4974 <1> ; (cpu will/would not return here 4975 <1> ; if there is/was an error in 'imap_x') 4976 <1> ;jnc short maknod1 4977 <1> jmp short maknod1 4978 <1> maknod_err: 4979 <1> ; 15/08/2021 4980 <1> ;pop edx ; two pops for stack alignment 4981 <1> ;pop edx ; (may not be needed while jumping to 'error') 4982 <1> mov [u.error], eax 4983 <1> jmp error 4984 <1> maknod3: 4985 <1> ; 10/01/2022 4986 <1> ; ebp = superblock buffer address 4987 <1> ; eax = (free) inode number 4988 <1> ; [ebp+SB.IMapBuffer] = physical block/sector number 4989 <1> ; of current IMAP sector 4990 <1> ; EBX = buffer address/offset for relevant alloc byte 4991 <1> ; DL has 1 at bit position which is for free inode 4992 <1> ; 4993 <1> ; ECX = byte offset from the (start of) inode map buffer 4994 <1> 4995 <1> ;mov [ebp+SB.LastInode], eax ; (free) inode number 4996 <1> 4997 <1> push eax ; *** 4998 <1> push ecx ; ** 4999 <1> push edx ; * 5000 <1> 5001 <1> mov eax, [ebp+SB.ImapBuffer] 5002 <1> 5003 <1> call wslot 5004 <1> ; ebx = buffer data address (write operation bit is set) 5005 <1> ; eax = physical sector number 5006 <1> ; Note: ebx contains addr of the 1st buffer in the buffer 5007 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 5008 <1> 5009 <1> ;mov [ebp+SB.ImapBuffer], ebx 5010 <1> ; save inode map buffer address 5011 <1> pop edx ; * 5012 <1> pop ecx ; ** 5013 <1> add ebx, ecx ; + byte offset (for allocation bit pos) 5014 <1> 5015 <1> ; set allocation bit (for this new inode) ; 10/01/2022 5016 <1> or [ebx], dl 5017 <1> ; bisb mq,(r2) / no, make it active 5018 <1> ; / (put a 1 in the bit map) 5019 <1> ;push ebp ; @ 5020 <1> call dskwr ; writes the 1st buffer to sector 5021 <1> ; (at the beginning/head of the buffer chain) 5022 <1> ;pop ebp ; @ 5023 <1> 5024 <1> ; if we are here, buffer has been written to disk successfully 5025 <1> ; (otherwise cpu would jump to 'error' address) 5026 <1> 5027 <1> ; set superblock modified flag 5028 <1> mov edx, smod 5029 <1> test byte [cdev], 1 ; mounted device ? 5030 <1> jz short maknod4 ; no, root device 5031 <1> ; yes, mounted device 5032 <1> ;mov edx, mmod 5033 <1> inc edx ; edx = offset mmod 5034 <1> maknod4: 5035 <1> inc byte [edx] ; superblock modified ! 5036 <1> 5037 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 5038 <1> ;; 5039 <1> ;; 27/03/2021 5040 <1> ;; (ref: 'UNIXHDCP.ASM', 'mak_nod', 18/01/2020) 5041 <1> ;or byte [smod], 2 ; inode map modified 5042 <1> ;; 01/04/2021 5043 <1> ;;or byte [imapbuf_hdr+bufhdr.status], 2 5044 <1> ;or byte [imapbuf_hdr], 2 ; set modified flag bit 5045 <1> ; 02/05/2021 5046 <1> ;or byte [esi+ldrv.b_status], 2 ; inode map modified 5047 <1> ; 15/08/2021 5048 <1> ; 06/05/2021 5049 <1> ;or byte [esi+ldrv.status], 2 ; inode map modified 5050 <1> ;;or byte [sysbuf_hdr], 2 ; set modified flag bit 5051 <1> 5052 <1> ;mov eax, [ebp+SB.LastInode] ; (free) inode number 5053 <1> ;push eax ; *** 5054 <1> mov eax, [esp] ; *** 5055 <1> inc eax ; next inode number 5056 <1> ; (free inode search start value) 5057 <1> mov [ebp+SB.FirstFreeIno], eax 5058 <1> call get_system_time 5059 <1> ; eax = current time (as unix epoch time) 5060 <1> mov [ebp+SB.ModifTime], eax 5061 <1> pop eax ; *** ; inode number 5062 <1> ;; 5063 <1> call iget 5064 <1> ; jsr r0,iget / get i-node into core 5065 <1> ; 09/01/2022 5066 <1> ; (If cpu is here, there was/is not an error!) 5067 <1> ; 06/11/2021 5068 <1> ;jc short maknod_err 5069 <1> 5070 <1> ;test word [i.flgs], 8000h 5071 <1> ; ; tst i.flgs / is i-node already allocated 5072 <1> ;jnz short maknod1 5073 <1> ; ; blt 1b / yes, look for another one 5074 <1> ; 27/03/2021 5075 <1> ; (Retro UNIX 386 v2 inode flags) 5076 <1> test byte [i.flgs+1], 0E0h ; 80h+40h+20h 5077 <1> ;jnz short maknod1 ; i-node already allocated 5078 <1> ; ; (as it is in inode table) 5079 <1> ; 15/08/2021 5080 <1> jnz short maknod2 ; defective inode map !? 5081 <1> 5082 <1> ; AX = free inode number 5083 <1> mov [u.dirbuf], ax 5084 <1> ; mov r1,u.dirbuf / no, put i-number in u.dirbuf 5085 <1> pop eax ; **** ; 27/03/2021 (32 bit push, pop) 5086 <1> ; mov (sp)+,r1 / get current i-number back 5087 <1> call iget 5088 <1> ; jsr r0,iget / get i-node in core 5089 <1> ; 09/01/2022 5090 <1> ; 06/11/2021 5091 <1> ;jc short maknod_err 5092 <1> 5093 <1> call mkdir 5094 <1> ; jsr r0,mkdir / make a directory entry 5095 <1> ; / in current directory 5096 <1> ; 09/01/2022 5097 <1> ; (If cpu is here, there was/is not an error in 'mkdir'!) 5098 <1> ; 06/11/2021 5099 <1> ;jc short maknod_err 5100 <1> 5101 <1> ; (eax = 0) 5102 <1> ;movzx eax, [u.difbuf] ; 06/11/2021 5103 <1> mov ax, [u.dirbuf] 5104 <1> ; mov u.dirbuf,r1 / r1 = new inode number 5105 <1> call iget 5106 <1> ; jsr r0,iget / get it into core 5107 <1> ; jsr r0,copyz; inode; inode+32. / 0 it out 5108 <1> ; 09/01/2022 5109 <1> ; 06/11/2021 5110 <1> ;jc short maknod_err 5111 <1> 5112 <1> ;mov ecx, 8 5113 <1> ; 27/03/2021 5114 <1> xor ecx, ecx 5115 <1> mov cl, 16 ; 64 bit inodes 5116 <1> xor eax, eax ; 0 5117 <1> mov edi, inode 5118 <1> rep stosd 5119 <1> ; 5120 <1> ;pop word [i.flgs] 5121 <1> ; ; mov (sp)+,i.flgs / fill flags 5122 <1> ; 27/03/2021 (32 bit push, pop) 5123 <1> pop eax ; ***** 5124 <1> mov [i.flgs], ax 5125 <1> 5126 <1> ;mov cl, [u.uid] ; 02/08/2013 5127 <1> ;mov [i.uid], cl 5128 <1> ; ; movb u.uid,i.uid / user id 5129 <1> ; 15/08/2021 5130 <1> ; 27/03/2021 5131 <1> mov cl, [u.gid] ; 8 bit group ID ; 15/08/2021 5132 <1> mov [i.gid], cl 5133 <1> mov cx, [u.uid] ; 16 bit user ID 5134 <1> mov [i.uid], cx 5135 <1> 5136 <1> mov byte [i.nlks], 1 5137 <1> ; movb $1,i.nlks / 1 link 5138 <1> ;call epoch ; Retro UNIX 8086 v1 modification ! 5139 <1> ;mov eax, [s.time] 5140 <1> ;mov [i.ctim], eax 5141 <1> ; mov s.time,i.ctim / time created 5142 <1> ; mov s.time+2,i.ctim+2 / time modified 5143 <1> ; Retro UNIX 8086 v1 modification ! 5144 <1> ; i.ctime=0, i.ctime+2=0 and 5145 <1> ; 'setimod' will set ctime of file via 'epoch' 5146 <1> ;call setimod 5147 <1> ; ; jsr r0,setimod / set modified flag 5148 <1> ;retn 5149 <1> ; ; rts r0 / return 5150 <1> ; 27/03/2021 5151 <1> jmp setimod 5152 <1> 5153 <1> %endif 5154 <1> 5155 <1> sysseek: ; / moves read write pointer in an fsp entry 5156 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5157 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 5158 <1> ; 5159 <1> ; 'sysseek' changes the r/w pointer of (3rd word of in an 5160 <1> ; fsp entry) of an open file whose file descriptor is in u.r0. 5161 <1> ; The file descriptor refers to a file open for reading or 5162 <1> ; writing. The read (or write) pointer is set as follows: 5163 <1> ; * if 'ptrname' is 0, the pointer is set to offset. 5164 <1> ; * if 'ptrname' is 1, the pointer is set to its 5165 <1> ; current location plus offset. 5166 <1> ; * if 'ptrname' is 2, the pointer is set to the 5167 <1> ; size of file plus offset. 5168 <1> ; The error bit (e-bit) is set for an undefined descriptor. 5169 <1> ; 5170 <1> ; Calling sequence: 5171 <1> ; sysseek; offset; ptrname 5172 <1> ; Arguments: 5173 <1> ; offset - number of bytes desired to move 5174 <1> ; the r/w pointer 5175 <1> ; ptrname - a switch indicated above 5176 <1> ; 5177 <1> ; Inputs: r0 - file descriptor 5178 <1> ; Outputs: - 5179 <1> ; ............................................................... 5180 <1> ; 5181 <1> ; Retro UNIX 8086 v1 modification: 5182 <1> ; 'sysseek' system call has three arguments; so, 5183 <1> ; * 1st argument, file descriptor is in BX (BL) register 5184 <1> ; * 2nd argument, offset is in CX register 5185 <1> ; * 3rd argument, ptrname/switch is in DX (DL) register 5186 <1> ; 5187 <1> 5188 00004BA7 E822000000 <1> call seektell 5189 <1> ; AX = u.count 5190 <1> ; BX = *u.fofp 5191 <1> ; jsr r0,seektell / get proper value in u.count 5192 <1> ; add u.base,u.count / add u.base to it 5193 00004BAC 0305[C86E0000] <1> add eax, [u.base] ; add offset (u.base) to base 5194 00004BB2 8903 <1> mov [ebx], eax 5195 <1> ; mov u.count,*u.fofp / put result into r/w pointer 5196 00004BB4 E913F0FFFF <1> jmp sysret 5197 <1> ; br sysret4 5198 <1> 5199 <1> systell: ; / get the r/w pointer 5200 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 5201 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5202 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 5203 <1> ; 5204 <1> ; Retro UNIX 8086 v1 modification: 5205 <1> ; ! 'systell' does not work in original UNIX v1, 5206 <1> ; it returns with error ! 5207 <1> ; Inputs: r0 - file descriptor 5208 <1> ; Outputs: r0 - file r/w pointer 5209 <1> 5210 <1> ;xor ecx, ecx ; 0 5211 <1> ;mov edx, 1 ; 05/08/2013 5212 <1> ; 09/01/2022 5213 00004BB9 29D2 <1> sub edx, edx 5214 00004BBB FEC2 <1> inc dl 5215 <1> ; edx = 1 5216 <1> ;call seektell 5217 00004BBD E812000000 <1> call seektell0 ; 05/08/2013 5218 <1> ;mov ebx, [u.fofp] 5219 00004BC2 8B03 <1> mov eax, [ebx] 5220 00004BC4 A3[A46E0000] <1> mov [u.r0], eax 5221 00004BC9 E9FEEFFFFF <1> jmp sysret 5222 <1> 5223 <1> ; Original unix v1 'systell' system call: 5224 <1> ; jsr r0,seektell 5225 <1> ; br error4 5226 <1> 5227 <1> seektell: 5228 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 5229 <1> ; 06/11/2021 5230 <1> ; 12/06/2021 5231 <1> ; 06/05/2021 (Retro UNIX 386 v2) 5232 <1> ; 03/01/2016 5233 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5234 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 5235 <1> ; 5236 <1> ; 'seektell' puts the arguments from sysseek and systell 5237 <1> ; call in u.base and u.count. It then gets the i-number of 5238 <1> ; the file from the file descriptor in u.r0 and by calling 5239 <1> ; getf. The i-node is brought into core and then u.count 5240 <1> ; is checked to see it is a 0, 1, or 2. 5241 <1> ; If it is 0 - u.count stays the same 5242 <1> ; 1 - u.count = offset (u.fofp) 5243 <1> ; 2 - u.count = i.size (size of file) 5244 <1> ; 5245 <1> ; !! Retro UNIX 8086 v1 modification: 5246 <1> ; Argument 1, file descriptor is in BX; 5247 <1> ; Argument 2, offset is in CX; 5248 <1> ; Argument 3, ptrname/switch is in DX register. 5249 <1> ; 5250 <1> ; mov ax, 3 ; Argument transfer method 3 (three arguments) 5251 <1> ; call arg 5252 <1> ; 5253 <1> ; ((Return -> ax = base for offset (position= base+offset)) 5254 <1> ; 5255 00004BCE 890D[C86E0000] <1> mov [u.base], ecx ; offset 5256 <1> ; jsr r0,arg; u.base / puts offset in u.base 5257 <1> ; 09/01/2022 5258 <1> ; ebx = file descriptor (0 to 9) 5259 <1> seektell0: 5260 00004BD4 8915[CC6E0000] <1> mov [u.count], edx 5261 <1> ; jsr r0,arg; u.count / put ptr name in u.count 5262 <1> ;mov ax, bx 5263 <1> ; mov *u.r0,r1 / file descriptor in r1 5264 <1> ; / (index in u.fp list) 5265 <1> ; 12/06/2021 5266 <1> ; BX = file descriptor (file number) 5267 00004BDA E896FCFFFF <1> call getf 5268 <1> ; jsr r0,getf / u.fofp points to 3rd word in fsp entry 5269 <1> ; 09/01/2022 5270 00004BDF 09C0 <1> or eax, eax 5271 <1> ;or ax, ax ; i-number of the file 5272 <1> ; mov r1,-(sp) / r1 has i-number of file, 5273 <1> ; / put it on the stack 5274 <1> ;jz error 5275 <1> ; beq error4 / if i-number is 0, not active so error 5276 00004BE1 750F <1> jnz short seektell1 5277 00004BE3 C705[186F0000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 5277 00004BEB 0000 <1> 5278 00004BED E9BAEFFFFF <1> jmp error 5279 <1> seektell1: 5280 <1> ; 06/05/2021 5281 <1> ;push eax 5282 <1> ;cmp ah, 80h 5283 <1> ;jb short seektell2 5284 <1> ; ; bgt .+4 / if its positive jump 5285 <1> ;neg ax 5286 <1> ; ; neg r1 / if not make it positive 5287 <1> seektell2: 5288 00004BF2 E879060000 <1> call iget 5289 <1> ; jsr r0,iget / get its i-node into core 5290 <1> ; 09/01/2022 5291 <1> ; (if there is/was an error in 'iget', cpu will not come here) 5292 <1> ;; 06/11/2021 5293 <1> ;jnc short seektell6 5294 <1> ;mov [u.error], eax 5295 <1> ;jmp error 5296 <1> seektell6: 5297 00004BF7 8B1D[B86E0000] <1> mov ebx, [u.fofp] ; 05/08/2013 5298 00004BFD 803D[CC6E0000]01 <1> cmp byte [u.count], 1 5299 <1> ; cmp u.count,$1 / is ptr name =1 5300 00004C04 7705 <1> ja short seektell3 5301 <1> ; blt 2f / no its zero 5302 00004C06 7409 <1> je short seektell4 5303 <1> ; beq 1f / yes its 1 5304 00004C08 31C0 <1> xor eax, eax 5305 <1> ;jmp short seektell5 5306 00004C0A C3 <1> retn 5307 <1> seektell3: 5308 <1> ; 03/01/2016 5309 <1> ;;movzx eax, word [i.size] 5310 <1> ;mov ax, [i.size] 5311 <1> ; ; mov i.size,u.count / put number of bytes 5312 <1> ; ; / in file in u.count 5313 <1> ;;jmp short seektell5 5314 <1> ; ; br 2f 5315 <1> ; 06/05/2021 - Retro UNIX 386 v2 5316 00004C0B A1[486B0000] <1> mov eax, [i.size] 5317 00004C10 C3 <1> retn 5318 <1> seektell4: ; 1: / ptrname =1 5319 <1> ;mov ebx, [u.fofp] 5320 00004C11 8B03 <1> mov eax, [ebx] 5321 <1> ; mov *u.fofp,u.count / put offset in u.count 5322 <1> ;seektell5: ; 2: / ptrname =0 5323 <1> ;mov [u.count], eax 5324 <1> ;pop eax 5325 <1> ; mov (sp)+,r1 / i-number on stack r1 5326 00004C13 C3 <1> retn 5327 <1> ; rts r0 5328 <1> 5329 <1> sysintr: ; / set interrupt handling 5330 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5331 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 5332 <1> ; 5333 <1> ; 'sysintr' sets the interrupt handling value. It puts 5334 <1> ; argument of its call in u.intr then branches into 'sysquit' 5335 <1> ; routine. u.tty is checked if to see if a control tty exists. 5336 <1> ; If one does the interrupt character in the tty buffer is 5337 <1> ; cleared and 'sysret'is called. If one does not exits 5338 <1> ; 'sysret' is just called. 5339 <1> ; 5340 <1> ; Calling sequence: 5341 <1> ; sysintr; arg 5342 <1> ; Argument: 5343 <1> ; arg - if 0, interrupts (ASCII DELETE) are ignored. 5344 <1> ; - if 1, intterupts cause their normal result 5345 <1> ; i.e force an exit. 5346 <1> ; - if arg is a location within the program, 5347 <1> ; control is passed to that location when 5348 <1> ; an interrupt occurs. 5349 <1> ; Inputs: - 5350 <1> ; Outputs: - 5351 <1> ; ............................................................... 5352 <1> ; 5353 <1> ; Retro UNIX 8086 v1 modification: 5354 <1> ; 'sysintr' system call sets u.intr to value of BX 5355 <1> ; then branches into sysquit. 5356 <1> ; 5357 00004C14 66891D[F06E0000] <1> mov [u.intr], bx 5358 <1> ; jsr r0,arg; u.intr / put the argument in u.intr 5359 <1> ; br 1f / go into quit routine 5360 00004C1B E9ACEFFFFF <1> jmp sysret 5361 <1> 5362 <1> sysquit: 5363 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5364 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 5365 <1> ; 5366 <1> ; 'sysquit' turns off the quit signal. it puts the argument of 5367 <1> ; the call in u.quit. u.tty is checked if to see if a control 5368 <1> ; tty exists. If one does the interrupt character in the tty 5369 <1> ; buffer is cleared and 'sysret'is called. If one does not exits 5370 <1> ; 'sysret' is just called. 5371 <1> ; 5372 <1> ; Calling sequence: 5373 <1> ; sysquit; arg 5374 <1> ; Argument: 5375 <1> ; arg - if 0, this call diables quit signals from the 5376 <1> ; typewriter (ASCII FS) 5377 <1> ; - if 1, quits are re-enabled and cause execution to 5378 <1> ; cease and a core image to be produced. 5379 <1> ; i.e force an exit. 5380 <1> ; - if arg is an addres in the program, 5381 <1> ; a quit causes control to sent to that 5382 <1> ; location. 5383 <1> ; Inputs: - 5384 <1> ; Outputs: - 5385 <1> ; ............................................................... 5386 <1> ; 5387 <1> ; Retro UNIX 8086 v1 modification: 5388 <1> ; 'sysquit' system call sets u.quit to value of BX 5389 <1> ; then branches into 'sysret'. 5390 <1> ; 5391 00004C20 66891D[F26E0000] <1> mov [u.quit], bx 5392 00004C27 E9A0EFFFFF <1> jmp sysret 5393 <1> ; jsr r0,arg; u.quit / put argument in u.quit 5394 <1> ;1: 5395 <1> ; mov u.ttyp,r1 / move pointer to control tty buffer 5396 <1> ; / to r1 5397 <1> ; beq sysret4 / return to user 5398 <1> ; clrb 6(r1) / clear the interrupt character 5399 <1> ; / in the tty buffer 5400 <1> ; br sysret4 / return to user 5401 <1> 5402 <1> syssetuid: ; / set process id 5403 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 5404 <1> ; 27/03/2021 - Retro UNIX 386 v2 5405 <1> ; (16 bit uid) 5406 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5407 <1> ; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1) 5408 <1> ; 5409 <1> ; 'syssetuid' sets the user id (u.uid) of the current process 5410 <1> ; to the process id in (u.r0). Both the effective user u.uid 5411 <1> ; and the real user u.ruid are set to this. 5412 <1> ; Only the super user can make this call. 5413 <1> ; 5414 <1> ; Calling sequence: 5415 <1> ; syssetuid 5416 <1> ; Arguments: - 5417 <1> ; 5418 <1> ; Inputs: (u.r0) - contains the process id. 5419 <1> ; Outputs: - 5420 <1> ; ............................................................... 5421 <1> ; 5422 <1> ; Retro UNIX 8086 v1 modification: 5423 <1> ; BL contains the (new) user ID of the current process 5424 <1> 5425 <1> ; 27/03/2021 5426 <1> ; INPUT: 5427 <1> ; BX = (new) user ID 5428 <1> 5429 <1> ; movb *u.r0,r1 / move process id (number) to r1 5430 <1> ;cmp bl, [u.ruid] 5431 <1> ; ; cmpb r1,u.ruid / is it equal to the real user 5432 <1> ; / id number 5433 <1> ; 27/03/2021 5434 00004C2C 663B1D[F86E0000] <1> cmp bx, [u.ruid] 5435 00004C33 7420 <1> je short setuid1 5436 <1> ; beq 1f / yes 5437 <1> ;cmp byte [u.uid], 0 ; 02/08/2013 5438 <1> ; ; tstb u.uid / no, is current user the super user? 5439 <1> ;;ja error 5440 <1> ; ; bne error4 / no, error 5441 <1> ; 27/03/2021 5442 00004C35 66833D[F66E0000]00 <1> cmp word [u.uid], 0 5443 00004C3D 760F <1> jna short setuid0 5444 <1> setuid_err: 5445 <1> setgid_err: 5446 00004C3F C705[186F0000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 5446 00004C47 0000 <1> 5447 <1> ; 'permission denied !' error 5448 00004C49 E95EEFFFFF <1> jmp error 5449 <1> setuid0: 5450 <1> ;mov [u.ruid], bl 5451 <1> ; 27/03/2021 5452 00004C4E 66891D[F86E0000] <1> mov [u.ruid], bx 5453 <1> setuid1: ; 1: 5454 <1> ;mov [u.uid], bl ; 02/08/2013 5455 <1> ; ; movb r1,u.uid / put process id in u.uid 5456 <1> ; ; movb r1,u.ruid / put process id in u.ruid 5457 <1> ; 27/03/2021 5458 00004C55 66891D[F66E0000] <1> mov [u.uid], bx 5459 00004C5C E96BEFFFFF <1> jmp sysret 5460 <1> ; br sysret4 / system return 5461 <1> 5462 <1> sysgetuid: ; < get user id > 5463 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 5464 <1> ; 27/03/2021 - Retro UNIX 386 v2 5465 <1> ; (16 bit uid) 5466 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5467 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 5468 <1> ; 5469 <1> ; 'sysgetuid' returns the real user ID of the current process. 5470 <1> ; The real user ID identifies the person who is logged in, 5471 <1> ; in contradistinction to the effective user ID, which 5472 <1> ; determines his access permission at each moment. It is thus 5473 <1> ; useful to programs which operate using the 'set user ID' 5474 <1> ; mode, to find out who invoked them. 5475 <1> ; 5476 <1> ; Calling sequence: 5477 <1> ; syssetuid 5478 <1> ; Arguments: - 5479 <1> ; 5480 <1> ; Inputs: - 5481 <1> ; Outputs: (u.r0) - contains the real user's id. 5482 <1> ; ............................................................... 5483 <1> ; 5484 <1> ; Retro UNIX 8086 v1 modification: 5485 <1> ; AL contains the real user ID at return. 5486 <1> ; 5487 <1> ;;movzx eax, byte [u.ruid] 5488 <1> ; 27/03/2021 5489 <1> ;movzx eax, word [u.ruid] 5490 <1> ; 09/01/2022 5491 00004C61 66A1[F86E0000] <1> mov ax, [u.ruid] 5492 00004C67 A3[A46E0000] <1> mov [u.r0], eax 5493 <1> ; movb u.ruid,*u.r0 / move the real user id to (u.r0) 5494 00004C6C E95BEFFFFF <1> jmp sysret 5495 <1> ; br sysret4 / systerm return, sysret 5496 <1> 5497 <1> syssetgid: ; set group id 5498 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 5499 <1> ; 02/04/2021 5500 <1> ; 27/03/2021 - Retro UNIX 386 v2 5501 <1> ; 5502 <1> ; 'syssetgid' sets the user's group id (u.gid) 5503 <1> ; of the current process to the process id in (u.r0). 5504 <1> ; Both the effective user u.gid and the real user 5505 <1> ; u.rgid are set to this. 5506 <1> ; Only the super user can make this call. 5507 <1> 5508 <1> ; INPUT: 5509 <1> ; BL = (new) group ID 5510 <1> ; OUTPUT: 5511 <1> ; - 5512 <1> 5513 00004C71 3A1D[FB6E0000] <1> cmp bl, [u.rgid] 5514 00004C77 7410 <1> je short setgid1 5515 <1> 5516 <1> ;cmp byte [u.uid], 0 5517 <1> ; 02/04/2021 5518 00004C79 66833D[F66E0000]00 <1> cmp word [u.uid], 0 5519 00004C81 77BC <1> ja short setgid_err 5520 <1> setgid0: 5521 00004C83 881D[FB6E0000] <1> mov [u.rgid], bl 5522 <1> setgid1: ; 1: 5523 00004C89 881D[FA6E0000] <1> mov [u.gid], bl 5524 00004C8F E938EFFFFF <1> jmp sysret 5525 <1> 5526 <1> sysgetgid: ; < get group id > (& user ID) 5527 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 5528 <1> ; 27/03/2021 - Retro UNIX 386 v2 5529 <1> ; 5530 <1> ; 'sysgetgid' returns the real group ID of the current process. 5531 <1> ; The real group ID identifies the group of the person 5532 <1> ; who is logged in, in contradistinction to the effective 5533 <1> ; group ID, which determines his access permission at each moment. 5534 <1> ; It is thus useful to programs which operate using 5535 <1> ; the 'set group ID' mode, to find out the group of the user 5536 <1> ; who invoked them. 5537 <1> 5538 <1> ;movzx eax, word [u.ruid] 5539 <1> ; 09/01/2022 5540 00004C94 66A1[F86E0000] <1> mov ax, [u.ruid] 5541 00004C9A C1E008 <1> shl eax, 8 5542 <1> ; user ID in byte 1 and byte 2 5543 00004C9D A0[FB6E0000] <1> mov al, [u.rgid] ; group ID in byte 0 5544 00004CA2 A3[A46E0000] <1> mov [u.r0], eax 5545 00004CA7 E920EFFFFF <1> jmp sysret 5546 <1> 5547 <1> sysver: ; get operating system version 5548 <1> ; 09/01/2022 - Retro UNIX 386 v1.2 5549 <1> ; 18/06/2021 - Retro UNIX 386 v2 5550 <1> 5551 <1> ;VMAJOR equ 2 ; Retro UNIX 386 v2 5552 <1> ;VMINOR equ 0 ; Retro UNIX 386 v2.0 (v2.0.0) 5553 <1> ;CURRENT_VERSION equ (VMAJOR*256)+VMINOR 5554 <1> 5555 <1> ; 09/01/2022 5556 <1> VMAJOR equ 1 ; Retro UNIX 386 v1 5557 <1> VMINOR equ 2 ; Retro UNIX 386 v1.2 (v1.2.0) 5558 <1> CURRENT_VERSION equ (VMAJOR*256)+VMINOR 5559 <1> 5560 <1> ; 29/04/2016 - TRDOS 386 v2.0 5561 <1> ;mov dword [u.r0], 200h ; AH = major version, AL = minor version 5562 <1> ; 18/06/2021 5563 00004CAC C705[A46E0000]0201- <1> mov dword [u.r0], CURRENT_VERSION ; (ah = 2, al = 0) 5563 00004CB4 0000 <1> 5564 00004CB6 E911EFFFFF <1> jmp sysret 5565 <1> 5566 <1> anyi: 5567 <1> ; 09/01/2022 5568 <1> ; 02/01/2022 5569 <1> ; 01/01/2022 5570 <1> ; 27/12/2021 (Retro UNIX 386 v1.2) 5571 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 5572 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 5573 <1> ; 25/04/2013 (Retro UNIX 8086 v1) 5574 <1> ; 5575 <1> ; 'anyi' is called if a file deleted while open. 5576 <1> ; "anyi" checks to see if someone else has opened this file. 5577 <1> ; 5578 <1> ; INPUTS -> 5579 <1> ; r1 - contains an i-number 5580 <1> ; fsp - start of table containing open files 5581 <1> ; 5582 <1> ; OUTPUTS -> 5583 <1> ; "deleted" flag set in fsp entry of another occurrence of 5584 <1> ; this file and r2 points 1st word of this fsp entry. 5585 <1> ; if file not found - bit in i-node map is cleared 5586 <1> ; (i-node is freed) 5587 <1> ; all blocks related to i-node are freed 5588 <1> ; all flags in i-node are cleared 5589 <1> ; ((AX = R1)) input 5590 <1> ; 5591 <1> ; (Retro UNIX Prototype: 02/12/2012, UNIXCOPY.ASM) 5592 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 5593 <1> ; 5594 <1> ; / r1 contains an i-number 5595 00004CBB BB[406B0000] <1> mov ebx, fsp 5596 <1> ; mov $fsp,r2 / move start of fsp table to r2 5597 <1> anyi_1: ; 1: 5598 <1> ;cmp eax, [ebx] ; 09/01/2022 (32 bit inode number) 5599 00004CC0 663B03 <1> cmp ax, [ebx] 5600 <1> ; cmp r1,(r2) / do i-numbers match? 5601 00004CC3 7423 <1> je short anyi_3 5602 <1> ; beq 1f / yes, 1f 5603 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 5604 <1> ;neg ax 5605 <1> ; ; neg r1 / no complement r1 5606 <1> ;cmp ax, [ebx] 5607 <1> ; ; cmp r1,(r2) / do they match now? 5608 <1> ;je short anyi_3 5609 <1> ; beq 1f / yes, transfer 5610 <1> ; / i-numbers do not match 5611 <1> anyi_0: 5612 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 5613 <1> ;add ebx, fp.size ; runix v2 fsp table size is 16 bytes 5614 <1> ; 01/01/2022 5615 00004CC5 83C310 <1> add ebx, 16 ; runix v2 fsp table size is 16 bytes 5616 <1> ;;add ebx, 10 ; fsp table size is 10 bytes 5617 <1> ; in Retro UNIX 386 v1 (22/06/2015) 5618 <1> ; add $8,r2 / no, bump to next entry in fsp table 5619 <1> ; 22/11/2021 5620 <1> ;cmp ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16) 5621 <1> ; 02/01/2022 5622 00004CC8 81FB[606E0000] <1> cmp ebx, fsp + (nfiles*16) 5623 <1> ; 01/01/2022 5624 <1> ;cmp ebx, fsp + (NFILES*16) ; fsp+(NFILES*fp.size) 5625 <1> ;;cmp ebx, fsp + (nfiles*10) ; 22/06/2015 5626 <1> ; cmp r2,$fsp+[nfiles*8] 5627 <1> ; / are we at last entry in the table 5628 00004CCE 72F0 <1> jb short anyi_1 5629 <1> ; blt 1b / no, check next entries i-number 5630 <1> ; 27/12/2021 5631 <1> ;;cmp ax, 32768 5632 <1> ;cmp ah, 80h ; negative number check 5633 <1> ; ; tst r1 / yes, no match 5634 <1> ; ; bge .+4 5635 <1> ;jb short anyi_2 5636 <1> ;neg ax 5637 <1> ; ; neg r1 / make i-number positive 5638 <1> ;anyi_2: 5639 00004CD0 E85B080000 <1> call imap 5640 <1> ; jsr r0,imap / get address of allocation bit 5641 <1> ; / in the i-map in r2 5642 <1> ;; DL/DX (MQ) has a 1 in the calculated bit position 5643 <1> ;; eBX (R2) has address of the byte with allocation bit 5644 <1> ; not dx 5645 00004CD5 F6D2 <1> not dl ;; 0 at calculated bit position, other bits are 1 5646 <1> ;and [ebx], dx 5647 00004CD7 2013 <1> and [ebx], dl 5648 <1> ; bicb mq,(r2) / clear bit for i-node in the imap 5649 00004CD9 E853070000 <1> call itrunc 5650 <1> ; jsr r0,itrunc / free all blocks related to i-node 5651 00004CDE 66C705[406B0000]00- <1> mov word [i.flgs], 0 5651 00004CE6 00 <1> 5652 <1> ; clr i.flgs / clear all flags in the i-node 5653 00004CE7 C3 <1> retn 5654 <1> ;rts r0 / return 5655 <1> anyi_3: ; 1: / i-numbers match 5656 <1> ; 09/01/2022 5657 00004CE8 F6430501 <1> test byte [ebx+5], 1 ; open for writing flag 5658 00004CEC 74D7 <1> jz short anyi_0 5659 <1> 5660 <1> ; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs) 5661 00004CEE 804B0580 <1> or byte [ebx+5], 80h ; set deleted file flag (bit 7) 5662 <1> ; 22/06/2015 5663 <1> ;inc byte [ebx+9] 5664 <1> ;incb 7(r2) / increment upper byte of the 4th word 5665 <1> ; / in that fsp entry (deleted flag of fsp entry) 5666 00004CF2 C3 <1> retn 5667 <1> ; rts r0 2078 %include 'u3.s' ; 10/05/2015 2079 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2080 <1> ; (re-write kernel for test by using previous version without a major defect) 2081 <1> ; **************************************************************************** 2082 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC 2083 <1> ; Last Modification: 24/12/2021 2084 <1> ; ---------------------------------------------------------------------------- 2085 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2086 <1> ; (v0.1 - Beginning: 11/07/2012) 2087 <1> ; 2088 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2089 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2090 <1> ; 2091 <1> ; 2092 <1> ; 2093 <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s 2094 <1> ; 2095 <1> ; **************************************************************************** 2096 <1> 2097 <1> tswitch: ; Retro UNIX 386 v1 2098 <1> tswap: 2099 <1> ; 01/09/2015 2100 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2101 <1> ; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2102 <1> ; time out swap, called when a user times out. 2103 <1> ; the user is put on the low priority queue. 2104 <1> ; This is done by making a link from the last user 2105 <1> ; on the low priority queue to him via a call to 'putlu'. 2106 <1> ; then he is swapped out. 2107 <1> ; 2108 <1> ; Retro UNIX 386 v1 modification -> 2109 <1> ; swap (software task switch) is performed by changing 2110 <1> ; user's page directory (u.pgdir) instead of segment change 2111 <1> ; as in Retro UNIX 8086 v1. 2112 <1> ; 2113 <1> ; RETRO UNIX 8086 v1 modification -> 2114 <1> ; 'swap to disk' is replaced with 'change running segment' 2115 <1> ; according to 8086 cpu (x86 real mode) architecture. 2116 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2117 <1> ; compatibles was using 1MB segmented memory 2118 <1> ; in 8086/8088 times. 2119 <1> ; 2120 <1> ; INPUTS -> 2121 <1> ; u.uno - users process number 2122 <1> ; runq+4 - lowest priority queue 2123 <1> ; OUTPUTS -> 2124 <1> ; r0 - users process number 2125 <1> ; r2 - lowest priority queue address 2126 <1> ; 2127 <1> ; ((AX = R0, BX = R2)) output 2128 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) 2129 <1> ; 2130 00004CF3 A0[F56E0000] <1> mov al, [u.uno] 2131 <1> ; movb u.uno,r1 / move users process number to r1 2132 <1> ; mov $runq+4,r2 2133 <1> ; / move lowest priority queue address to r2 2134 00004CF8 E8CD000000 <1> call putlu 2135 <1> ; jsr r0,putlu / create link from last user on Q to 2136 <1> ; / u.uno's user 2137 <1> 2138 <1> switch: ; Retro UNIX 386 v1 2139 <1> swap: 2140 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 2141 <1> ; 02/09/2015 2142 <1> ; 01/09/2015 2143 <1> ; 31/08/2015 2144 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2145 <1> ; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2146 <1> ; 'swap' is routine that controls the swapping of processes 2147 <1> ; in and out of core. 2148 <1> ; 2149 <1> ; Retro UNIX 386 v1 modification -> 2150 <1> ; swap (software task switch) is performed by changing 2151 <1> ; user's page directory (u.pgdir) instead of segment change 2152 <1> ; as in Retro UNIX 8086 v1. 2153 <1> ; 2154 <1> ; RETRO UNIX 8086 v1 modification -> 2155 <1> ; 'swap to disk' is replaced with 'change running segment' 2156 <1> ; according to 8086 cpu (x86 real mode) architecture. 2157 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2158 <1> ; compatibles was using 1MB segmented memory 2159 <1> ; in 8086/8088 times. 2160 <1> ; 2161 <1> ; INPUTS -> 2162 <1> ; runq table - contains processes to run. 2163 <1> ; p.link - contains next process in line to be run. 2164 <1> ; u.uno - process number of process in core 2165 <1> ; s.stack - swap stack used as an internal stack for swapping. 2166 <1> ; OUTPUTS -> 2167 <1> ; (original unix v1 -> present process to its disk block) 2168 <1> ; (original unix v1 -> new process into core -> 2169 <1> ; Retro Unix 8086 v1 -> segment registers changed 2170 <1> ; for new process) 2171 <1> ; u.quant = 3 (Time quantum for a process) 2172 <1> ; ((INT 1Ch count down speed -> 18.2 times per second) 2173 <1> ; RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second) 2174 <1> ; for now, it will swap the process if there is not 2175 <1> ; a keyboard event (keystroke) (Int 15h, function 4Fh) 2176 <1> ; or will count down from 3 to 0 even if there is a 2177 <1> ; keyboard event locking due to repetitive key strokes. 2178 <1> ; u.quant will be reset to 3 for RETRO UNIX 8086 v1. 2179 <1> ; 2180 <1> ; u.pri -points to highest priority run Q. 2181 <1> ; r2 - points to the run queue. 2182 <1> ; r1 - contains new process number 2183 <1> ; r0 - points to place in routine or process that called 2184 <1> ; swap all user parameters 2185 <1> ; 2186 <1> ; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI)) 2187 <1> ; 2188 <1> swap_0: 2189 <1> ;mov $300,*$ps / processor priority = 6 2190 00004CFD BE[946E0000] <1> mov esi, runq 2191 <1> ; mov $runq,r2 / r2 points to runq table 2192 <1> swap_1: ; 1: / search runq table for highest priority process 2193 00004D02 668B06 <1> mov ax, [esi] 2194 00004D05 6621C0 <1> and ax, ax 2195 <1> ; tst (r2)+ / are there any processes to run 2196 <1> ; / in this Q entry 2197 00004D08 7507 <1> jnz short swap_2 2198 <1> ; bne 1f / yes, process 1f 2199 <1> ; cmp r2,$runq+6 / if zero compare address 2200 <1> ; / to end of table 2201 <1> ; bne 1b / if not at end, go back 2202 00004D0A E8E0000000 <1> call idle 2203 <1> ; jsr r0,idle; s.idlet+2 / wait for interrupt; 2204 <1> ; / all queues are empty 2205 00004D0F EBF1 <1> jmp short swap_1 2206 <1> ; br swap 2207 <1> swap_2: ; 1: 2208 00004D11 0FB6D8 <1> movzx ebx, al ; 02/09/2015 2209 <1> ; tst -(r2) / restore pointer to right Q entry 2210 <1> ; mov r2,u.pri / set present user to this run queue 2211 <1> ; movb (r2)+,r1 / move 1st process in queue to r1 2212 00004D14 38E0 <1> cmp al, ah 2213 <1> ; cmpb r1,(r2)+ / is there only 1 process 2214 <1> ; / in this Q to be run 2215 00004D16 740A <1> je short swap_3 2216 <1> ; beq 1f / yes 2217 <1> ; tst -(r2) / no, pt r2 back to this Q entry 2218 <1> ;movzx ebx, al 2219 00004D18 8AA3[FF6B0000] <1> mov ah, [ebx+p.link-1] 2220 00004D1E 8826 <1> mov [esi], ah 2221 <1> ; movb p.link-1(r1),(r2) / move next process 2222 <1> ; / in line into run queue 2223 00004D20 EB05 <1> jmp short swap_4 2224 <1> ; br 2f 2225 <1> swap_3: ; 1: 2226 <1> ;xor dx, dx 2227 <1> ; 24/12/2021 2228 00004D22 31D2 <1> xor edx, edx 2229 00004D24 668916 <1> mov [esi], dx 2230 <1> ; clr -(r2) / zero the entry; no processes on the Q 2231 <1> swap_4: ; / write out core to appropriate disk area and read 2232 <1> ; / in new process if required 2233 <1> ; clr *$ps / clear processor status 2234 00004D27 8A25[F56E0000] <1> mov ah, [u.uno] 2235 00004D2D 38C4 <1> cmp ah, al 2236 <1> ; cmpb r1,u.uno / is this process the same as 2237 <1> ; / the process in core? 2238 00004D2F 743B <1> je short swap_8 2239 <1> ; beq 2f / yes, don't have to swap 2240 <1> ; mov r0,-(sp) / no, write out core; save r0 2241 <1> ; / (address in routine that called swap) 2242 <1> ; mov r1,-(sp) / put r1 (new process #) on the stack 2243 <1> ; 01/09/2015 2244 <1> ;mov [u.usp], esp 2245 <1> ; mov sp,u.usp / save stack pointer 2246 <1> ; mov $sstack,sp / move swap stack pointer 2247 <1> ; / to the stack pointer 2248 00004D31 08E4 <1> or ah, ah 2249 <1> ; tstb u.uno / is the process # = 0 2250 00004D33 740D <1> jz short swap_6 ; 'sysexit' 2251 <1> ; beq 1f / yes, kill process by overwriting 2252 <1> ; 02/09/2015 2253 00004D35 8925[A06E0000] <1> mov [u.usp], esp ; return address for 'syswait' & 'sleep' 2254 <1> ; 2255 00004D3B E834000000 <1> call wswap 2256 <1> ;jsr r0,wswap / write out core to disk 2257 <1> ; 31/08/2015 2258 <1> ;movzx ebx, al ; New (running) process number 2259 00004D40 EB1C <1> jmp short swap_7 2260 <1> swap_6: 2261 <1> ; 31/08/2015 2262 <1> ; Deallocate memory pages belong to the process 2263 <1> ; which is being terminated 2264 <1> ; 14/05/2015 ('sysexit') 2265 <1> ; Deallocate memory pages of the process 2266 <1> ; (Retro UNIX 386 v1 modification !) 2267 <1> ; 2268 <1> ; movzx ebx, al 2269 00004D42 53 <1> push ebx 2270 00004D43 A1[046F0000] <1> mov eax, [u.pgdir] ; page directory of the process 2271 00004D48 8B1D[086F0000] <1> mov ebx, [u.ppgdir] ; page directory of the parent process 2272 00004D4E E845E2FFFF <1> call deallocate_page_dir 2273 00004D53 A1[006F0000] <1> mov eax, [u.upage] ; 'user' structure page of the process 2274 00004D58 E8D3E2FFFF <1> call deallocate_page 2275 00004D5D 5B <1> pop ebx 2276 <1> swap_7: ;1: 2277 <1> ; 02/09/2015 2278 <1> ; 31/08/2015 2279 <1> ; 14/05/2015 2280 00004D5E C0E302 <1> shl bl, 2 ; * 4 2281 00004D61 8B83[1C6C0000] <1> mov eax, [ebx+p.upage-4] ; the 'u' page of the new process 2282 <1> ;cli 2283 00004D67 E831000000 <1> call rswap 2284 <1> ; mov (sp)+,r1 / restore r1 to new process number 2285 <1> ; jsr r0,rswap / read new process into core 2286 <1> ; jsr r0,unpack / unpack the users stack from next 2287 <1> ; / to his program to its normal 2288 <1> ; 01/09/2015 2289 <1> ;mov esp, [u.usp] 2290 <1> ; mov u.usp,sp / location; restore stack pointer to 2291 <1> ; / new process stack 2292 <1> ; mov (sp)+,r0 / put address of where the process 2293 <1> ; / that just got swapped in, left off., 2294 <1> ; / i.e., transfer control to new process 2295 <1> ;sti 2296 <1> swap_8: ;2: 2297 <1> ; RETRO UNIX 8086 v1 modification ! 2298 00004D6C C605[EC6E0000]04 <1> mov byte [u.quant], time_count 2299 <1> ; movb $30.,uquant / initialize process time quantum 2300 00004D73 C3 <1> retn 2301 <1> ; rts r0 / return 2302 <1> 2303 <1> wswap: ; < swap out, swap to disk > 2304 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 2305 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2306 <1> ; 'wswap' writes out the process that is in core onto its 2307 <1> ; appropriate disk area. 2308 <1> ; 2309 <1> ; Retro UNIX 386 v1 modification -> 2310 <1> ; User (u) structure content and the user's register content 2311 <1> ; will be copied to the process's/user's UPAGE (a page for 2312 <1> ; saving 'u' structure and user registers for task switching). 2313 <1> ; u.usp - points to kernel stack address which contains 2314 <1> ; user's registers while entering system call. 2315 <1> ; u.sp - points to kernel stack address 2316 <1> ; to return from system call -for IRET-. 2317 <1> ; [u.usp]+32+16 = [u.sp] 2318 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 2319 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 2320 <1> ; 2321 <1> ; Retro UNIX 8086 v1 modification -> 2322 <1> ; 'swap to disk' is replaced with 'change running segment' 2323 <1> ; according to 8086 cpu (x86 real mode) architecture. 2324 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2325 <1> ; compatibles was using 1MB segmented memory 2326 <1> ; in 8086/8088 times. 2327 <1> ; 2328 <1> ; INPUTS -> 2329 <1> ; u.break - points to end of program 2330 <1> ; u.usp - stack pointer at the moment of swap 2331 <1> ; core - beginning of process program 2332 <1> ; ecore - end of core 2333 <1> ; user - start of user parameter area 2334 <1> ; u.uno - user process number 2335 <1> ; p.dska - holds block number of process 2336 <1> ; OUTPUTS -> 2337 <1> ; swp I/O queue 2338 <1> ; p.break - negative word count of process 2339 <1> ; r1 - process disk address 2340 <1> ; r2 - negative word count 2341 <1> ; 2342 <1> ; RETRO UNIX 8086 v1 input/output: 2343 <1> ; 2344 <1> ; INPUTS -> 2345 <1> ; u.uno - process number (to be swapped out) 2346 <1> ; OUTPUTS -> 2347 <1> ; none 2348 <1> ; 2349 <1> ; ((Modified registers: ECX, ESI, EDI)) 2350 <1> ; 2351 00004D74 8B3D[006F0000] <1> mov edi, [u.upage] ; process's user (u) structure page addr 2352 00004D7A B921000000 <1> mov ecx, (U_SIZE + 3) / 4 2353 00004D7F BE[9C6E0000] <1> mov esi, user ; active user (u) structure 2354 00004D84 F3A5 <1> rep movsd 2355 <1> ; 2356 00004D86 8B35[A06E0000] <1> mov esi, [u.usp] ; esp (system stack pointer, 2357 <1> ; points to user registers) 2358 00004D8C 8B0D[9C6E0000] <1> mov ecx, [u.sp] ; return address from the system call 2359 <1> ; (for IRET) 2360 <1> ; [u.sp] -> EIP (user) 2361 <1> ; [u.sp+4]-> CS (user) 2362 <1> ; [u.sp+8] -> EFLAGS (user) 2363 <1> ; [u.sp+12] -> ESP (user) 2364 <1> ; [u.sp+16] -> SS (user) 2365 00004D92 29F1 <1> sub ecx, esi ; required space for user registers 2366 00004D94 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 2367 <1> ; (for IRET) 2368 00004D97 C1E902 <1> shr ecx, 2 2369 00004D9A F3A5 <1> rep movsd 2370 00004D9C C3 <1> retn 2371 <1> 2372 <1> ; Original UNIX v1 'wswap' routine: 2373 <1> ; wswap: 2374 <1> ; mov *$30,u.emt / determines handling of emts 2375 <1> ; mov *$10,u.ilgins / determines handling of 2376 <1> ; / illegal instructions 2377 <1> ; mov u.break,r2 / put process program break address in r2 2378 <1> ; inc r2 / add 1 to it 2379 <1> ; bic $1,r2 / make it even 2380 <1> ; mov r2,u.break / set break to an even location 2381 <1> ; mov u.usp,r3 / put users stack pointer 2382 <1> ; / at moment of swap in r3 2383 <1> ; cmp r2,$core / is u.break less than $core 2384 <1> ; blos 2f / yes 2385 <1> ; cmp r2,r3 / no, is (u.break) greater than stack ptr. 2386 <1> ; bhis 2f / yes 2387 <1> ; 1: 2388 <1> ; mov (r3)+,(r2)+ / no, pack stack next to users program 2389 <1> ; cmp r3,$ecore / has stack reached end of core 2390 <1> ; bne 1b / no, keep packing 2391 <1> ; br 1f / yes 2392 <1> ; 2: 2393 <1> ; mov $ecore,r2 / put end of core in r2 2394 <1> ; 1: 2395 <1> ; sub $user,r2 / get number of bytes to write out 2396 <1> ; / (user up to end of stack gets written out) 2397 <1> ; neg r2 / make it negative 2398 <1> ; asr r2 / change bytes to words (divide by 2) 2399 <1> ; mov r2,swp+4 / word count 2400 <1> ; movb u.uno,r1 / move user process number to r1 2401 <1> ; asl r1 / x2 for index 2402 <1> ; mov r2,p.break-2(r1) / put negative of word count 2403 <1> ; / into the p.break table 2404 <1> ; mov p.dska-2(r1),r1 / move disk address of swap area 2405 <1> ; / for process to r1 2406 <1> ; mov r1,swp+2 / put processes dska address in swp+2 2407 <1> ; / (block number) 2408 <1> ; bis $1000,swp / set it up to write (set bit 9) 2409 <1> ; jsr r0,ppoke / write process out on swap area of disk 2410 <1> ; 1: 2411 <1> ; tstb swp+1 / is lt done writing? 2412 <1> ; bne 1b / no, wait 2413 <1> ; rts r0 / yes, return to swap 2414 <1> 2415 <1> rswap: ; < swap in, swap from disk > 2416 <1> ; 15/09/2015 2417 <1> ; 28/08/2015 2418 <1> ; 14/05/2015 2419 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 2420 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2421 <1> ; 'rswap' reads a process whose number is in r1, 2422 <1> ; from disk into core. 2423 <1> ; 2424 <1> ; Retro UNIX 386 v1 modification -> 2425 <1> ; User (u) structure content and the user's register content 2426 <1> ; will be restored from process's/user's UPAGE (a page for 2427 <1> ; saving 'u' structure and user registers for task switching). 2428 <1> ; u.usp - points to kernel stack address which contains 2429 <1> ; user's registers while entering system call. 2430 <1> ; u.sp - points to kernel stack address 2431 <1> ; to return from system call -for IRET-. 2432 <1> ; [u.usp]+32+16 = [u.sp] 2433 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 2434 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 2435 <1> ; 2436 <1> ; RETRO UNIX 8086 v1 modification -> 2437 <1> ; 'swap to disk' is replaced with 'change running segment' 2438 <1> ; according to 8086 cpu (x86 real mode) architecture. 2439 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2440 <1> ; compatibles was using 1MB segmented memory 2441 <1> ; in 8086/8088 times. 2442 <1> ; 2443 <1> ; INPUTS -> 2444 <1> ; r1 - process number of process to be read in 2445 <1> ; p.break - negative of word count of process 2446 <1> ; p.dska - disk address of the process 2447 <1> ; u.emt - determines handling of emt's 2448 <1> ; u.ilgins - determines handling of illegal instructions 2449 <1> ; OUTPUTS -> 2450 <1> ; 8 = (u.ilgins) 2451 <1> ; 24 = (u.emt) 2452 <1> ; swp - bit 10 is set to indicate read 2453 <1> ; (bit 15=0 when reading is done) 2454 <1> ; swp+2 - disk block address 2455 <1> ; swp+4 - negative word count 2456 <1> ; ((swp+6 - address of user structure)) 2457 <1> ; 2458 <1> ; RETRO UNIX 8086 v1 input/output: 2459 <1> ; 2460 <1> ; INPUTS -> 2461 <1> ; AL - new process number (to be swapped in) 2462 <1> ; OUTPUTS -> 2463 <1> ; none 2464 <1> ; 2465 <1> ; ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 2466 <1> ; 2467 <1> ; Retro UNIX 386 v1 - modification ! 14/05/2015 2468 00004D9D 89C6 <1> mov esi, eax ; process's user (u) structure page addr 2469 00004D9F B921000000 <1> mov ecx, (U_SIZE + 3) / 4 2470 00004DA4 BF[9C6E0000] <1> mov edi, user ; active user (u) structure 2471 00004DA9 F3A5 <1> rep movsd 2472 00004DAB 58 <1> pop eax ; 15/09/2015, 'rswap' return address 2473 00004DAC 8B3D[A06E0000] <1> mov edi, [u.usp] ; esp (system stack pointer, 2474 <1> ; points to user registers) 2475 00004DB2 8B0D[9C6E0000] <1> mov ecx, [u.sp] ; return address from the system call 2476 <1> ; (for IRET) 2477 <1> ; [u.sp] -> EIP (user) 2478 <1> ; [u.sp+4]-> CS (user) 2479 <1> ; [u.sp+8] -> EFLAGS (user) 2480 <1> ; [u.sp+12] -> ESP (user) 2481 <1> ; [u.sp+16] -> SS (user) 2482 <1> ; 28/08/2015 2483 00004DB8 29F9 <1> sub ecx, edi ; required space for user registers 2484 00004DBA 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 2485 <1> ; (for IRET) 2486 00004DBD C1E902 <1> shr ecx, 2 2487 00004DC0 F3A5 <1> rep movsd 2488 00004DC2 8B25[A06E0000] <1> mov esp, [u.usp] ; 15/09/2015 2489 00004DC8 50 <1> push eax ; 15/09/2015 'rswap' return address 2490 00004DC9 C3 <1> retn 2491 <1> 2492 <1> ; Original UNIX v1 'rswap' and 'unpack' routines: 2493 <1> ;rswap: 2494 <1> ; asl r1 / process number x2 for index 2495 <1> ; mov p.break-2(r1), swp+4 / word count 2496 <1> ; mov p.dska-2(r1),swp+2 / disk address 2497 <1> ; bis $2000,swp / read 2498 <1> ; jsr r0,ppoke / read it in 2499 <1> ; 1: 2500 <1> ; tstb swp+1 / done 2501 <1> ; bne 1b / no, wait for bit 15 to clear (inhibit bit) 2502 <1> ; mov u.emt,*$30 / yes move these 2503 <1> ; mov u.ilgins,*$10 / back 2504 <1> ; rts r0 / return 2505 <1> 2506 <1> ;unpack: ; / move stack back to its normal place 2507 <1> ; mov u.break,r2 / r2 points to end of user program 2508 <1> ; cmp r2,$core / at beginning of user program yet? 2509 <1> ; blos 2f / yes, return 2510 <1> ; cmp r2,u.usp / is break_above the stack pointer 2511 <1> ; / before swapping 2512 <1> ; bhis 2f / yes, return 2513 <1> ; mov $ecore,r3 / r3 points to end of core 2514 <1> ; add r3,r2 2515 <1> ; sub u.usp,r2 / end of users stack is in r2 2516 <1> ; 1: 2517 <1> ; mov -(r2),-(r3) / move stack back to its normal place 2518 <1> ; cmp r2,u.break / in core 2519 <1> ; bne 1b 2520 <1> ; 2: 2521 <1> ; rts r0 2522 <1> 2523 <1> putlu: 2524 <1> ; 12/09/2015 2525 <1> ; 02/09/2015 2526 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2527 <1> ; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 2528 <1> ; 'putlu' is called with a process number in r1 and a pointer 2529 <1> ; to lowest priority Q (runq+4) in r2. A link is created from 2530 <1> ; the last process on the queue to process in r1 by putting 2531 <1> ; the process number in r1 into the last process's link. 2532 <1> ; 2533 <1> ; INPUTS -> 2534 <1> ; r1 - user process number 2535 <1> ; r2 - points to lowest priority queue 2536 <1> ; p.dska - disk address of the process 2537 <1> ; u.emt - determines handling of emt's 2538 <1> ; u.ilgins - determines handling of illegal instructions 2539 <1> ; OUTPUTS -> 2540 <1> ; r3 - process number of last process on the queue upon 2541 <1> ; entering putlu 2542 <1> ; p.link-1 + r3 - process number in r1 2543 <1> ; r2 - points to lowest priority queue 2544 <1> ; 2545 <1> ; ((Modified registers: EDX, EBX)) 2546 <1> ; 2547 <1> ; / r1 = user process no.; r2 points to lowest priority queue 2548 <1> 2549 <1> ; eBX = r2 2550 <1> ; eAX = r1 (AL=r1b) 2551 <1> 2552 00004DCA BB[946E0000] <1> mov ebx, runq 2553 00004DCF 0FB613 <1> movzx edx, byte [ebx] 2554 00004DD2 43 <1> inc ebx 2555 00004DD3 20D2 <1> and dl, dl 2556 <1> ; tstb (r2)+ / is queue empty? 2557 00004DD5 740A <1> jz short putlu_1 2558 <1> ; beq 1f / yes, branch 2559 00004DD7 8A13 <1> mov dl, [ebx] ; 12/09/2015 2560 <1> ; movb (r2),r3 / no, save the "last user" process number 2561 <1> ; / in r3 2562 00004DD9 8882[FF6B0000] <1> mov [edx+p.link-1], al 2563 <1> ; movb r1,p.link-1(r3) / put pointer to user on 2564 <1> ; / "last users" link 2565 00004DDF EB03 <1> jmp short putlu_2 2566 <1> ; br 2f / 2567 <1> putlu_1: ; 1: 2568 00004DE1 8843FF <1> mov [ebx-1], al 2569 <1> ; movb r1,-1(r2) / user is only user; 2570 <1> ; / put process no. at beginning and at end 2571 <1> putlu_2: ; 2: 2572 00004DE4 8803 <1> mov [ebx], al 2573 <1> ; movb r1,(r2) / user process in r1 is now the last entry 2574 <1> ; / on the queue 2575 00004DE6 88C2 <1> mov dl, al 2576 00004DE8 88B2[FF6B0000] <1> mov [edx+p.link-1], dh ; 0 2577 <1> ; dec r2 / restore r2 2578 00004DEE C3 <1> retn 2579 <1> ; rts r0 2580 <1> 2581 <1> ;copyz: 2582 <1> ; mov r1,-(sp) / put r1 on stack 2583 <1> ; mov r2,-(sp) / put r2 on stack 2584 <1> ; mov (r0)+,r1 2585 <1> ; mov (r0)+,r2 2586 <1> ;1: 2587 <1> ; clr (r1)+ / clear all locations between r1 and r2 2588 <1> ; cmp r1,r2 2589 <1> ; blo 1b 2590 <1> ; mov (sp)+,r2 / restore r2 2591 <1> ; mov (sp)+,r1 / restore r1 2592 <1> ; rts r0 2593 <1> 2594 <1> idle: 2595 <1> ; 01/09/2015 2596 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2597 <1> ; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1) 2598 <1> ; (idle & wait loop) 2599 <1> ; Retro Unix 8086 v1 modification on original UNIX v1 2600 <1> ; idle procedure! 2601 <1> ; 2602 <1> ; 01/09/2015 2603 00004DEF FB <1> sti 2604 <1> ; 29/07/2013 2605 00004DF0 F4 <1> hlt 2606 00004DF1 90 <1> nop ; 10/10/2013 2607 00004DF2 90 <1> nop 2608 00004DF3 90 <1> nop 2609 <1> ; 23/10/2013 2610 00004DF4 90 <1> nop 2611 00004DF5 90 <1> nop 2612 00004DF6 90 <1> nop 2613 00004DF7 90 <1> nop 2614 00004DF8 C3 <1> retn 2615 <1> 2616 <1> ;mov *$ps,-(sp) / save ps on stack 2617 <1> ;clr *$ps / clear ps 2618 <1> ;mov clockp,-(sp) / save clockp on stack 2619 <1> ;mov (r0)+,clockp / arg to idle in clockp 2620 <1> ;1 / wait for interrupt 2621 <1> ;mov (sp)+,clockp / restore clockp, ps 2622 <1> ;mov (sp)+,*$ps 2623 <1> ;rts r0 2624 <1> 2625 <1> clear: 2626 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2627 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2628 <1> ; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2629 <1> ; 'clear' zero's out of a block (whose block number is in r1) 2630 <1> ; on the current device (cdev) 2631 <1> ; 2632 <1> ; INPUTS -> 2633 <1> ; r1 - block number of block to be zeroed 2634 <1> ; cdev - current device number 2635 <1> ; OUTPUTS -> 2636 <1> ; a zeroed I/O buffer onto the current device 2637 <1> ; r1 - points to last entry in the I/O buffer 2638 <1> ; 2639 <1> ; ((AX = R1)) input/output 2640 <1> ; (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM) 2641 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP)) 2642 <1> 2643 00004DF9 E883110000 <1> call wslot 2644 <1> ; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first 2645 <1> ; / word of I/O queue r5 points to first data word in buffer 2646 00004DFE 89DF <1> mov edi, ebx ; r5 2647 00004E00 89C2 <1> mov edx, eax 2648 00004E02 B980000000 <1> mov ecx, 128 2649 <1> ; mov $256.,r3 2650 00004E07 31C0 <1> xor eax, eax 2651 00004E09 F3AB <1> rep stosd 2652 00004E0B 89D0 <1> mov eax, edx 2653 <1> ; 1: 2654 <1> ; clr (r5)+ / zero data word in buffer 2655 <1> ; dec r3 2656 <1> ; bgt 1b / branch until all data words in buffer are zero 2657 <1> ;call dskwr 2658 <1> ; jsr r0,dskwr / write zeroed buffer area out onto physical 2659 <1> ; / block specified in r1 2660 <1> ; eAX (r1) = block number 2661 <1> ;retn 2662 <1> ; rts r0 2663 <1> ; 24/12/2021 2664 00004E0D E98B110000 <1> jmp dskwr 2079 %include 'u4.s' ; 15/04/2015 2080 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2081 <1> ; (re-write kernel for test by using previous version without a major defect) 2082 <1> ; **************************************************************************** 2083 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC 2084 <1> ; Last Modification: 05/12/2021 2085 <1> ; ---------------------------------------------------------------------------- 2086 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2087 <1> ; (v0.1 - Beginning: 11/07/2012) 2088 <1> ; 2089 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2090 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2091 <1> ; 2092 <1> ; 2093 <1> ; 2094 <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s 2095 <1> ; 2096 <1> ; **************************************************************************** 2097 <1> 2098 <1> ;setisp: 2099 <1> ;mov r1,-(sp) 2100 <1> ;mov r2,-(sp) 2101 <1> ;mov r3,-(sp) 2102 <1> ;mov clockp,-(sp) 2103 <1> ;mov $s.syst+2,clockp 2104 <1> ;jmp (r0) 2105 <1> 2106 <1> clock: ; / interrupt from 60 cycle clock 2107 <1> 2108 <1> ; 14/10/2015 2109 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 2110 <1> ; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1) 2111 <1> 2112 <1> ;mov r0,-(sp) / save r0 2113 <1> ;tst *$lks / restart clock? 2114 <1> ;mov $s.time+2,r0 / increment the time of day 2115 <1> ;inc (r0) 2116 <1> ;bne 1f 2117 <1> ;inc -(r0) 2118 <1> ;1: 2119 <1> ;mov clockp,r0 / increment appropriate time category 2120 <1> ;inc (r0) 2121 <1> ;bne 1f 2122 <1> ;inc -(r0) 2123 <1> ;1: 2124 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2125 <1> 2126 00004E12 803D[EC6E0000]00 <1> cmp byte [u.quant], 0 2127 00004E19 772C <1> ja short clk_1 2128 <1> ; 2129 00004E1B 803D[9A6E0000]FF <1> cmp byte [sysflg], 0FFh ; user or system space ? 2130 00004E22 7529 <1> jne short clk_2 ; system space (sysflg <> 0FFh) 2131 00004E24 803D[F56E0000]01 <1> cmp byte [u.uno], 1 ; /etc/init ? 2132 00004E2B 761A <1> jna short clk_1 ; yes, do not swap out 2133 00004E2D 66833D[F06E0000]00 <1> cmp word [u.intr], 0 2134 00004E35 7616 <1> jna short clk_2 2135 <1> clk_0: 2136 <1> ; 14/10/2015 2137 00004E37 FE05[9A6E0000] <1> inc byte [sysflg] ; Now, we are in system space 2138 00004E3D 58 <1> pop eax ; return address to the timer interrupt 2139 <1> ; 2140 00004E3E B020 <1> MOV AL,EOI ; GET END OF INTERRUPT MASK 2141 <1> ;CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 2142 00004E40 E620 <1> OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 2143 <1> ; 2144 00004E42 E9EAEDFFFF <1> jmp sysrelease ; 'sys release' by clock/timer 2145 <1> clk_1: 2146 00004E47 FE0D[EC6E0000] <1> dec byte [u.quant] 2147 <1> clk_2: 2148 00004E4D C3 <1> retn ; return to (hardware) timer interrupt routine 2149 <1> 2150 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2151 <1> 2152 <1> ;mov $uquant,r0 / decrement user time quantum 2153 <1> ;decb (r0) 2154 <1> ;bge 1f / if less than 0 2155 <1> ;clrb (r0) / make it 0 2156 <1> ;1: / decrement time out counts return now if priority was not 0 2157 <1> ;cmp 4(sp),$200 / ps greater than or equal to 200 2158 <1> ;bge 2f / yes, check time outs 2159 <1> ;tstb (r0) / no, user timed out? 2160 <1> ;bne 1f / no 2161 <1> ;cmpb sysflg,$-1 / yes, are we outside the system? 2162 <1> ;bne 1f / no, 1f 2163 <1> ;mov (sp)+,r0 / yes, put users r0 in r0 2164 <1> ;sys 0 / sysrele 2165 <1> ;rti 2166 <1> ;2: / priority is high so just decrement time out counts 2167 <1> ;mov $toutt,r0 / r0 points to beginning of time out table 2168 <1> ;2: 2169 <1> ;tstb (r0) / is the time out? 2170 <1> ;beq 3f / yes, 3f (get next entry) 2171 <1> ;decb (r0) / no, decrement the time 2172 <1> ;bne 3f / isit zero now? 2173 <1> ;incb (r0) / yes, increment the time 2174 <1> ;3: 2175 <1> ;inc r0 / next entry 2176 <1> ;cmp r0,$touts / end of toutt table? 2177 <1> ;blo 2b / no, check this entry 2178 <1> ;mov (sp)+,r0 / yes, restore r0 2179 <1> ;rti / return from interrupt 2180 <1> ;1: / decrement time out counts; if 0 call subroutine 2181 <1> ;mov (sp)+,r0 / restore r0 2182 <1> ;mov $240,*$ps / set processor priority to 5 2183 <1> ;jsr r0,setisp / save registers 2184 <1> ;mov $touts-toutt-1,r0 / set up r0 as index to decrement thru 2185 <1> ; / the table 2186 <1> ;1: 2187 <1> ;tstb toutt(r0) / is the time out for this entry 2188 <1> ;beq 2f / yes 2189 <1> ;decb toutt(r0) / no, decrement the time 2190 <1> ;bne 2f / is the time 0, now 2191 <1> ;asl r0 / yes, 2 x r0 to get word index for tout entry 2192 <1> ;jsr r0,*touts(r0) / go to appropriate routine specified in this 2193 <1> ;asr r0 / touts entry; set r0 back to toutt index 2194 <1> ;2: 2195 <1> ;dec r0 / set up r0 for next entry 2196 <1> ;bge 1b / finished? , no, go back 2197 <1> ;br retisp / yes, restore registers and do a rti 2198 <1> 2199 <1> ;retisp: 2200 <1> ;mov (sp)+,clockp / pop values before interrupt off the stack 2201 <1> ;mov (sp)+,r3 2202 <1> ;mov (sp)+,r2 2203 <1> ;mov (sp)+,r1 2204 <1> ;mov (sp)+,r0 2205 <1> ;rti / return from interrupt 2206 <1> 2207 <1> 2208 <1> wakeup: ; / wakeup processes waiting for an event 2209 <1> ; / by linking them to the queue 2210 <1> ; 2211 <1> ; 15/09/2015 2212 <1> ; 29/06/2015 2213 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 2214 <1> ; 2215 <1> ; 15/05/2013 - 02/06/2014 2216 <1> ; Retro UNIX 8086 v1 modification ! 2217 <1> ; (Process/task switching routine by using 2218 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.) 2219 <1> ; 2220 <1> ; In original UNIX v1, 'wakeup' is called to wake the process 2221 <1> ; sleeping in the specified wait channel by creating a link 2222 <1> ; to it from the last user process on the run queue. 2223 <1> ; If there is no process to wake up, nothing happens. 2224 <1> ; 2225 <1> ; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set 2226 <1> ; 'switching' status of the current process (owns current tty) 2227 <1> ; (via alt + function keys) to a process which has highest 2228 <1> ; priority (on run queue) on the requested tty (0 to 7, except 2229 <1> ; 8 and 9 which are tty identifiers of COM1, COM2 serial ports) 2230 <1> ; as it's console tty. (NOTE: 'p.ttyc' is used to set console 2231 <1> ; tty for tty switching by keyboard.) 2232 <1> ; 2233 <1> ; INPUT -> 2234 <1> ; AL = wait channel (r3) ('tty number' for now) 2235 <1> ; ;;EBX = Run queue (r2) offset 2236 <1> ; 2237 <1> ; ((modified registers: EAX, EBX)) 2238 <1> ; 2239 00004E4E 0FB6D8 <1> movzx ebx, al ; 29/06/2015 2240 00004E51 81C3[086E0000] <1> add ebx, wlist 2241 00004E57 8A03 <1> mov al, [ebx] ; waiting list (waiting process number) 2242 00004E59 20C0 <1> and al, al 2243 00004E5B 7424 <1> jz short wa0 ; nothing to wakeup 2244 <1> ; 2245 00004E5D 30E4 <1> xor ah, ah 2246 00004E5F 8825[EC6E0000] <1> mov [u.quant], ah ; 0 ; time quantum = 0 2247 00004E65 8823 <1> mov [ebx], ah ; 0 ; zero wait channel entry 2248 <1> ; 15/09/2015 2249 00004E67 0FB6D8 <1> movzx ebx, al 2250 00004E6A 88A3[EF6B0000] <1> mov [ebx+p.waitc-1], ah ; 0 2251 00004E70 FEC4 <1> inc ah 2252 00004E72 88A3[0F6C0000] <1> mov byte [ebx+p.stat-1], ah ; 1 ; SRUN 2253 <1> ; 2254 00004E78 57 <1> push edi 2255 00004E79 52 <1> push edx 2256 00004E7A E84BFFFFFF <1> call putlu 2257 00004E7F 5A <1> pop edx 2258 00004E80 5F <1> pop edi 2259 <1> wa0: 2260 00004E81 C3 <1> retn 2261 <1> 2262 <1> ; 05/12/2021 2263 <1> ; 30/11/2021 - Retro UNIX 386 v1.2 2264 <1> sleep: 2265 <1> ; 15/09/2015 2266 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2267 <1> ; 2268 <1> ; 09/05/2013 - 20/03/2014 2269 <1> ; 2270 <1> ; Retro UNIX 8086 v1 modification ! 2271 <1> ; (Process/task switching and quit routine by using 2272 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2273 <1> ; 2274 <1> ; In original UNIX v1, 'sleep' is called to wait for 2275 <1> ; tty and tape output or input becomes available 2276 <1> ; and process is put on waiting channel and swapped out, 2277 <1> ; then -when the tty or tape is ready to write or read- 2278 <1> ; 'wakeup' gets process back to active swapped-in status.) 2279 <1> ; 2280 <1> ; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and 2281 <1> ; Int 09h keyboard interrupt will set 'quit' or 'switching' 2282 <1> ; status of the current process also INT 1Ch will count down 2283 <1> ; 'uquant' value and INT 09h will redirect scancode of keystroke 2284 <1> ; to tty buffer of the current process and kernel will get 2285 <1> ; user input by using tty buffer of the current process 2286 <1> ; (instead of standard INT 16h interrupt). 2287 <1> ; TTY output will be redirected to related video page of text mode 2288 <1> ; (INT 10h will be called with different video page depending 2289 <1> ; on tty assignment of the active process: 0 to 7 for 2290 <1> ; pseudo screens.) 2291 <1> ; 2292 <1> ; In Retro UNIX 8086 v1, 'sleep' will be called to wait for 2293 <1> ; a keystroke from keyboard or wait for reading or writing 2294 <1> ; characters/data on serial port(s). 2295 <1> ; 2296 <1> ; Character/Terminal input/output through COM1 and COM2 will be 2297 <1> ; performed by related routines in addition to pseudo TTY routines. 2298 <1> ; 2299 <1> ; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013) 2300 <1> ; 2301 <1> ;; 05/10/2013 2302 <1> ;10/12/2013 2303 <1> ;cmp byte [u.uno], 1 2304 <1> ;ja short sleep0 2305 <1> ;retn 2306 <1> 2307 <1> ; 20/03/2014 2308 <1> ;mov bx, [runq] 2309 <1> ;cmp bl, bh 2310 <1> ;jne short sleep0 2311 <1> ; 25/02/2014 2312 <1> ;cmp word ptr [runq], 0 2313 <1> ;ja short sleep0 2314 <1> ;retn 2315 <1> sleep0: 2316 <1> ; 2317 00004E82 E851000000 <1> call isintr 2318 <1> ;jnz sysret 2319 <1> ; / wait for event 2320 <1> ; jsr r0,isintr / check to see if interrupt 2321 <1> ; / or quit from user 2322 <1> ; br 2f / something happened 2323 <1> ; / yes, his interrupt so return 2324 <1> ; / to user 2325 <1> ; 05/12/2021 2326 00004E87 7405 <1> jz short sleep_2 2327 <1> sleep_3: 2328 00004E89 E93EEDFFFF <1> jmp sysret 2329 <1> sleep_2: 2330 <1> ; 30/06/2015 2331 00004E8E 0FB6DC <1> movzx ebx, ah ; 30/06/2015 2332 00004E91 81C3[086E0000] <1> add ebx, wlist 2333 00004E97 8A03 <1> mov al, [ebx] 2334 00004E99 20C0 <1> and al, al 2335 00004E9B 7407 <1> jz short sleep1 2336 00004E9D 53 <1> push ebx 2337 00004E9E E827FFFFFF <1> call putlu 2338 00004EA3 5B <1> pop ebx 2339 <1> sleep1: 2340 00004EA4 A0[F56E0000] <1> mov al, [u.uno] 2341 00004EA9 8803 <1> mov [ebx], al ; put the process number 2342 <1> ; in the wait channel 2343 <1> ; mov (r0)+,r1 / put number of wait channel in r1 2344 <1> ; movb wlist(r1),-(sp) / put old process number in there, 2345 <1> ; / on the stack 2346 <1> ; movb u.uno,wlist(r1) / put process number of process 2347 <1> ; / to put to sleep in there 2348 <1> ; 30/11/2021 2349 00004EAB 31DB <1> xor ebx, ebx 2350 00004EAD 8A1D[856E0000] <1> mov bl, [cdev] 2351 00004EB3 53 <1> push ebx 2352 <1> ; 15/09/2015 2353 <1> ;movzx ebx, al 2354 00004EB4 88C3 <1> mov bl, al 2355 00004EB6 C683[0F6C0000]04 <1> mov byte [ebx+p.stat-1], 4 ; SSLEEP 2356 00004EBD FEC4 <1> inc ah 2357 00004EBF 88A3[EF6B0000] <1> mov [ebx+p.waitc-1], ah ; wait channel + 1 2358 <1> ; 2359 <1> ;push word [cdev] 2360 <1> ; ; mov cdev,-(sp) / nothing happened in isintr so 2361 00004EC5 E833FEFFFF <1> call swap 2362 <1> ; jsr r0,swap / swap out process that needs to sleep 2363 <1> ;pop word [cdev] 2364 <1> ; ; mov (sp)+,cdev / restore device 2365 <1> ; 30/11/2021 2366 00004ECA 58 <1> pop eax 2367 00004ECB A2[856E0000] <1> mov [cdev], al 2368 00004ED0 E803000000 <1> call isintr 2369 <1> ; 22/09/2013 2370 <1> ;jnz sysret 2371 <1> ; jsr r0,isintr / check for interrupt of new process 2372 <1> ; br 2f / yes, return to new user 2373 <1> ; movb (sp)+,r1 / no, r1 = old process number that was 2374 <1> ; / originally on the wait channel 2375 <1> ; beq 1f / if 0 branch 2376 <1> ; mov $runq+4,r2 / r2 points to lowest priority queue 2377 <1> ; mov $300,*$ps / processor priority = 6 2378 <1> ; jsr r0,putlu / create link to old process number 2379 <1> ; clr *$ps / clear the status; process priority = 0 2380 <1> ; 05/12/2021 2381 00004ED5 75B2 <1> jnz short sleep_3 ; jump to sysret 2382 <1> ;1: 2383 00004ED7 C3 <1> retn 2384 <1> ; rts r0 / return 2385 <1> ;2: 2386 <1> ;;jmp sysret 2387 <1> ; jmp sysret / return to user 2388 <1> 2389 <1> isintr: 2390 <1> ; 30/11/2021 2391 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2392 <1> ; 2393 <1> ; 09/05/2013 - 30/05/2014 2394 <1> ; 2395 <1> ; Retro UNIX 8086 v1 modification ! 2396 <1> ; (Process/task switching and quit routine by using 2397 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2398 <1> ; 2399 <1> ; Retro UNIX 8086 v1 modification: 2400 <1> ; 'isintr' checks if user interrupt request is enabled 2401 <1> ; and there is a 'quit' request by user; 2402 <1> ; otherwise, 'isintr' will return with zf=1 that means 2403 <1> ; "nothing to do". (20/10/2013) 2404 <1> ; 2405 <1> ; 20/10/2013 2406 00004ED8 66833D[DA6E0000]00 <1> cmp word [u.ttyp], 0 ; has process got a tty ? 2407 00004EE0 761F <1> jna short isintr2 ; retn 2408 <1> ; 03/09/2013 2409 <1> ; (nothing to do) 2410 <1> ;retn 2411 <1> ; 22/09/2013 2412 00004EE2 66833D[F06E0000]00 <1> cmp word [u.intr], 0 2413 00004EEA 7615 <1> jna short isintr2 ; retn 2414 <1> ; 30/05/2014 2415 <1> ;push ax 2416 00004EEC 50 <1> push eax ; 30/11/2021 2417 00004EED 66A1[F26E0000] <1> mov ax, [u.quit] 2418 00004EF3 6609C0 <1> or ax, ax ; 0 ? 2419 00004EF6 7408 <1> jz short isintr1 ; zf = 1 2420 00004EF8 6683F8FE <1> cmp ax, 0FFFEh ; 'ctrl + brk' check 2421 00004EFC 7702 <1> ja short isintr1 ; 0FFFFh, zf = 0 2422 <1> ;xor ax, ax ; zf = 1 2423 <1> ; 30/11/2021 2424 00004EFE 31C0 <1> xor eax, eax 2425 <1> isintr1: 2426 <1> ;pop ax 2427 <1> ; 30/11/2021 2428 00004F00 58 <1> pop eax 2429 <1> isintr2: ; 22/09/2013 2430 <1> ; zf=1 -> nothing to do 2431 00004F01 C3 <1> retn 2432 <1> 2433 <1> ; UNIX v1 original 'isintr' routine... 2434 <1> ;mov r1,-(sp) / put number of wait channel on the stack 2435 <1> ;mov r2,-(sp) / save r2 2436 <1> ;mov u.ttyp,r1 / r1 = pointer to buffer of process control 2437 <1> ; / typewriter 2438 <1> ;beq 1f / if 0, do nothing except skip return 2439 <1> ;movb 6(r1),r1 / put interrupt char in the tty buffer in r1 2440 <1> ;beq 1f / if its 0 do nothing except skip return 2441 <1> ;cmp r1,$177 / is interrupt char = delete? 2442 <1> ;bne 3f / no, so it must be a quit (fs) 2443 <1> ;tst u.intr / yes, value of u.intr determines handling 2444 <1> ; / of interrupts 2445 <1> ;bne 2f / if not 0, 2f. If zero do nothing. 2446 <1> ;1: 2447 <1> ;tst (r0)+ / bump r0 past system return (skip) 2448 <1> ;4: 2449 <1> ;mov (sp)+,r2 / restore r1 and r2 2450 <1> ;mov (sp)+,r1 2451 <1> ;rts r0 2452 <1> ;3: / interrupt char = quit (fs) 2453 <1> ;tst u.quit / value of u.quit determines handling of quits 2454 <1> ;beq 1b / u.quit = 0 means do nothing 2455 <1> ;2: / get here because either u.intr <> 0 or u.qult <> O 2456 <1> ;mov $tty+6,r1 / move pointer to tty block into r1 2457 <1> ;1: / find process control tty entry in tty block 2458 <1> ;cmp (r1),u.ttyp / is this the process control tty buffer? 2459 <1> ;beq 1f / block found go to 1f 2460 <1> ;add $8,r1 / look at next tty block 2461 <1> ;cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks 2462 <1> ;blo 1b / no 2463 <1> ;br 4b / no process control tty found so go to 4b 2464 <1> ;1: 2465 <1> ;mov $240,*$ps / set processor priority to 5 2466 <1> ;movb -3(r1),0f / load getc call argument; character llst 2467 <1> ; / identifier 2468 <1> ;inc 0f / increment 2469 <1> ;1: 2470 <1> ;jsr r0,getc; 0:.. / erase output char list for control 2471 <1> ; br 4b / process tty. This prevents a line of stuff 2472 <1> ; / being typed out after you hit the interrupt 2473 <1> ; / key 2474 <1> ;br 1b 2080 %include 'u5.s' ; 03/06/2015 2081 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2082 <1> ; (re-write kernel for test by using previous version without a major defect) 2083 <1> ; **************************************************************************** 2084 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC 2085 <1> ; Last Modification: 10/01/2022 2086 <1> ; ---------------------------------------------------------------------------- 2087 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2088 <1> ; (v0.1 - Beginning: 11/07/2012) 2089 <1> ; 2090 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2091 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2092 <1> ; 2093 <1> ; 2094 <1> ; 2095 <1> ; Retro UNIX 8086 v1 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s 2096 <1> ; 2097 <1> ; **************************************************************************** 2098 <1> 2099 <1> ; 09/01/2022 2100 <1> ; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2101 <1> mget_w: 2102 <1> ; 28/10/2021 2103 <1> ; 22/08/2021 2104 <1> ; 20/08/2021 2105 <1> ; 25/05/2020 2106 <1> ; 24/05/2020 - Retro UNIX 386 v2 2107 00004F02 C605[3A6F0000]01 <1> mov byte [mget_rw], 1 ; write access 2108 00004F09 EB07 <1> jmp short mget 2109 <1> mget_r: 2110 <1> ; 28/10/2021 2111 <1> ; 22/08/2021 2112 <1> ; 25/05/2020 2113 <1> ; 24/05/2020 - Retro UNIX 386 v2 2114 00004F0B C605[3A6F0000]00 <1> mov byte [mget_rw], 0 ; read access 2115 <1> mget: 2116 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 2117 <1> ; 28/11/2021 2118 <1> ; 22/11/2021 2119 <1> ; 28/10/2021 - temporary (simplified code) 2120 <1> ; 22/08/2021 2121 <1> ; 20/08/2021 2122 <1> ; 25/05/2020 2123 <1> ; 24/05/2020 2124 <1> ; 05/05/2020 2125 <1> ; 02/05/2020, 03/05/2020 2126 <1> ; 29/04/2020 - Retro UNIX 386 v2 2127 <1> ; New inode model/format (Modified UNIX v7 inode model) 2128 <1> ; 2129 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2130 <1> ; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2131 <1> ; 2132 <1> ; Get existing or (allocate) a new disk block for file 2133 <1> ; 2134 <1> ; INPUTS -> 2135 <1> ; u.fofp (file offset pointer) 2136 <1> ; inode 2137 <1> ; u.off (file offset) 2138 <1> ; OUTPUTS -> 2139 <1> ; r1 (physical block number) 2140 <1> ; r2, r3, r5 (internal) 2141 <1> ; 2142 <1> ; ((AX = R1)) output 2143 <1> ; (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM) 2144 <1> ; 2145 <1> ; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp 2146 <1> 2147 <1> ; Retro UNIX 386 v2 'mget' procedure 2148 <1> ; source code reference: 2149 <1> ; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan 2150 <1> 2151 <1> ; Get sector/block address for current file pointer 2152 <1> ; (If file pointer points to a number greater than current file 2153 <1> ; size, a new -empty- sector/block will be created/written.) 2154 <1> 2155 <1> ; Note: 'mget' procedure will be used for only RUNIX v2 FS. 2156 <1> ; (installable file system drivers will not use 'mget') 2157 <1> ; !!! 512 bytes per sector !!! ; 02/05/2020 2158 <1> 2159 <1> ; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit 2160 <1> ; file offset for regular files and directories. 2161 <1> ; ('mget' procedure will be called for regular files & directories) 2162 <1> 2163 <1> ; 28/10/2021 2164 <1> ; Note: 'mget' uses only current inode ([ii], 'inode:') 2165 <1> ; (inode must be loaded at 'inode:' addr by 'iget' before 'mget') 2166 <1> 2167 <1> ; mov *u.fofp,mq / file offset in mq 2168 <1> ; clr ac / later to be high sig 2169 <1> ; mov $-8,lsh / divide ac/mq by 256. 2170 <1> ; mov mq,r2 2171 <1> ; bit $10000,i.flgs / lg/sm is this a large or small file 2172 <1> ; bne 4f / branch for large file 2173 <1> 2174 <1> ; 09/01/2022 2175 <1> ; Return: eax = physical block/sector number 2176 <1> mget_0: 2177 00004F12 8B35[B86E0000] <1> mov esi, [u.fofp] 2178 00004F18 8B1E <1> mov ebx, [esi] 2179 <1> ; ebx = file offset 2180 <1> 2181 <1> ; 20/08/2021 2182 00004F1A C1EB09 <1> shr ebx, 9 ; / 512 (to convert byte offset to sector offset) 2183 <1> 2184 00004F1D F605[416B0000]10 <1> test byte [i.flgs+1], 10h ; is this a large or small file addr? 2185 00004F24 7405 <1> jz short mget_1 ; small file addressing 2186 00004F26 E986000000 <1> jmp mget_5 ; large file addressing 2187 <1> mget_1: 2188 <1> ; If large file flag is clear -not set- RUNIX v2 FS inode 2189 <1> ; will contain 10 direct disk block/sector dword pointers. 2190 <1> 2191 <1> ; 05/05/2020 2192 <1> ;shr ebx, 9 ; / 512 (to convert byte offset to sector offset) 2193 <1> 2194 00004F2B 83FB0A <1> cmp ebx, 10 ; block 10 2195 00004F2E 733A <1> jnb short mget_3 ; file offset >= 5120 2196 <1> 2197 <1> ; 05/05/2020 2198 <1> ;cmp ebx, 5120 2199 <1> ;jnb short mget_3 ; file offset >= 5120 2200 <1> 2201 <1> ;mov bl, bh 2202 <1> ;and bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18 2203 <1> ; ; max. value = 12h = 10010b = 18 (because ebx <= 5119) 2204 <1> ;shl bl, 1 ; * 2 ; max. value = 24h = 100100b = 36 2205 <1> ;xor bh, bh ; clear bh 2206 <1> ; RUNIX v2 (RUFS 2) file system bytes per sector value 2207 <1> ; is always 512. 2208 <1> ; ebx = 4*(ebx/512) = 0 to 36 2209 <1> 2210 <1> ; 05/05/2020 2211 00004F30 C0E302 <1> shl bl, 2 ; * 4 2212 <1> ; ebx = 0 to 36 2213 <1> 2214 00004F33 8B83[4C6B0000] <1> mov eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file 2215 <1> ; 22/08/2021 2216 00004F39 89DE <1> mov esi, ebx 2217 <1> ;xor ebx, ebx ; 0 2218 <1> ; 09/01/2022 2219 00004F3B 30DB <1> xor bl, bl 2220 <1> 2221 00004F3D 09C0 <1> or eax, eax 2222 00004F3F 7512 <1> jnz short mget_2 ; existing block/sector (logical) 2223 <1> 2224 00004F41 56 <1> push esi ; * ; 22/08/2021 2225 00004F42 E877010000 <1> call alloc_m ; 24/05/2020 2226 <1> ;call alloc ; allocate a new sector/block for this file 2227 <1> ; eax = sector/block number 2228 <1> ; ebx = buffer header address 2229 00004F47 5E <1> pop esi ; * ; 22/08/2021 2230 <1> ; 28/11/2021 2231 <1> ;jc short mget_2 2232 <1> ; cf = 1 -> eax = 'no free block' error 2233 <1> ; 22/08/2021 2234 00004F48 8986[4C6B0000] <1> mov [esi+i.dskp], eax ; logical sector/block address 2235 <1> 2236 <1> ; 09/01/2022 2237 00004F4E E8BC040000 <1> call setimod ; set inode modification flag 2238 <1> ; and set modification time 2239 <1> 2240 <1> ; eax = logical sector/block number 2241 <1> ; ([idev] = logical drive number) 2242 <1> ; 28/10/2021 2243 <1> ; [cdev] = logical drive number (0 or 1) 2244 <1> ; (0 = root fs, 1 = mounted fs) 2245 <1> mget_2: 2246 <1> ; 09/01/2022 2247 <1> ; eax = logical sector/block number 2248 00004F53 F605[856E0000]01 <1> test byte [cdev], 1 2249 00004F5A 7507 <1> jnz short mget_14 2250 <1> ; convert to physical sector/block number 2251 00004F5C 0305[586F0000] <1> add eax, [systm+SB.BootSectAddr] 2252 00004F62 C3 <1> retn 2253 <1> ; 09/01/2022 2254 <1> mget_14: 2255 <1> ; convert to physical sector/block number 2256 00004F63 0305[60710000] <1> add eax, [mount+SB.BootSectAddr] 2257 00004F69 C3 <1> retn 2258 <1> 2259 <1> ; rts r0 2260 <1> mget_3: ; 3: / adding on block which changes small file to a large file 2261 <1> ; 22/11/2021 2262 00004F6A E84F010000 <1> call alloc_m ; 24/05/2020 2263 <1> ;call alloc ; allocate a new sector/block for this file 2264 <1> ; eax = sector/block number 2265 <1> ; ebx = buffer header ; 24/05/2020 2266 <1> ; 28/11/2021 2267 <1> ;jc short mget_2 ; error code in eax 2268 <1> 2269 <1> ; 09/01/2022 2270 <1> ; convert to physical block/sector number 2271 00004F6F 50 <1> push eax ; *!* ; logical sector/block number 2272 00004F70 E8DEFFFFFF <1> call mget_2 2273 <1> 2274 <1> ; EAX (r1) = Physical block (sector) number 2275 00004F75 E807100000 <1> call wslot 2276 <1> ; jsr r0,wslot / set up I/O buffer for write, r5 points to 2277 <1> ; / first data word in buffer 2278 <1> ; EAX (r1) = Physical block number 2279 <1> ; 28/11/2021 2280 <1> ; ebx = buffer (data) address 2281 <1> ; 22/11/2021 2282 00004F7A 31C9 <1> xor ecx, ecx 2283 00004F7C B10A <1> mov cl, 10 ; r3, transfer old physical block pointers 2284 <1> ; into new indirect block area for the new 2285 <1> ; large file 2286 00004F7E 89DF <1> mov edi, ebx ; r5 2287 00004F80 BE[4C6B0000] <1> mov esi, i.dskp ; current inode's direct disk addr ptrs 2288 00004F85 89C2 <1> mov edx, eax 2289 00004F87 31C0 <1> xor eax, eax 2290 <1> mget_4: 2291 00004F89 A5 <1> movsd 2292 00004F8A 8946FC <1> mov [esi-4], eax ; 0 2293 00004F8D E2FA <1> loop mget_4 2294 <1> 2295 <1> ; 22/11/2021 2296 00004F8F B176 <1> mov cl, 128-10 ; clear rest of data buffer 2297 <1> ;mget_4: ; 1 2298 00004F91 F3AB <1> rep stosd 2299 <1> ; clr (r5)+ 2300 <1> ; dec r3 2301 <1> ; bgt 1b 2302 00004F93 89D0 <1> mov eax, edx 2303 <1> ; EAX (r1) = Physical block number 2304 00004F95 E803100000 <1> call dskwr 2305 <1> ; jsr r0,dskwr / write new indirect block on disk 2306 <1> 2307 <1> ;; EAX (r1) = Physical block number 2308 <1> 2309 <1> ; 09/01/2022 2310 00004F9A 8F05[4C6B0000] <1> pop dword [i.dskp] ; *!* ; logical sector/block number 2311 <1> 2312 <1> ; eax = logical disk sector/block number/addr ; 09/01/2022 2313 <1> ;mov [i.dskp], eax ; 22/11/2021 2314 <1> ; mov r1,i.dskp / put pointer to indirect block in i-node 2315 <1> 2316 00004FA0 800D[416B0000]10 <1> or byte [i.flgs+1], 10000b ; 10h ; 16 ; large file flag 2317 <1> ; bis $10000,i.flgs / set large file bit 2318 <1> ; / in i.flgs word of i-node 2319 00004FA7 E863040000 <1> call setimod 2320 <1> ; jsr r0,setimod / set i-node modified flag 2321 <1> 2322 00004FAC E961FFFFFF <1> jmp mget_0 ; 09/01/2022 2323 <1> ; br mget 2324 <1> 2325 <1> mget_5: ; 4 ; large file 2326 <1> ; 13/11/2019 (UNIXHDCP.ASM) 2327 <1> ; 2328 <1> ; Retro UNIX 386 v2 disk inode contains.. 2329 <1> ; (if large file flag is set) 2330 <1> ; 8 indirect disk block/sector dword pointers 2331 <1> ; +1 double indirect disk block/sector dword pointers 2332 <1> ; +1 triple indirect disk block/sector dword pointers 2333 <1> 2334 <1> ; check indirect pointers limit (as file offset) 2335 <1> ; 8*128 = 1024 blocks (or sectors) or 512 KB 2336 <1> ; check dx (file offset hw) value 2337 <1> 2338 <1> ; 03/05/2020 2339 <1> ;cmp ebx, 524288 ; is file offset >= 524288 ? 2340 <1> ;jnb short mget_6 ; yes, check double indirect limit 2341 <1> 2342 <1> ; 05/05/2020 2343 00004FB1 81FB00040000 <1> cmp ebx, 1024 ; block 1024 (byte 524288) 2344 00004FB7 7321 <1> jnb short mget_6 ; check double indirect limit 2345 <1> 2346 00004FB9 C605[3C6F0000]01 <1> mov byte [level], 1 ; levels, 1 = indirect blocks 2347 <1> 2348 <1> ; 05/05/2020 2349 <1> ;shr ebx, 9 ; ebx = sector offset (flat) 2350 <1> 2351 00004FC0 88D9 <1> mov cl, bl 2352 00004FC2 80E17F <1> and cl, 127 2353 00004FC5 880D[3D6F0000] <1> mov [level+1], cl ; level 1, direct block ptr index (0 to 127) 2354 00004FCB 66C1EB07 <1> shr bx, 7 ; bl = level 0, indirect block pointer index (0 to 7) 2355 <1> ;mov [level+2], bl 2356 <1> 2357 00004FCF C0E302 <1> shl bl, 2 ; * 4 to convert index number to offset 2358 <1> 2359 <1> ;mov esi, i.dskp 2360 <1> ;add esi, ebx 2361 <1> 2362 00004FD2 8DB3[4C6B0000] <1> lea esi, [ebx+i.dskp] 2363 <1> 2364 00004FD8 EB66 <1> jmp short mget_8 2365 <1> 2366 <1> mget_6: 2367 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 2368 <1> ; 03/05/2020 2369 <1> ; 13/11/2019 (UNIXHDCP.ASM) 2370 <1> ; check double indirect pointer limit (as file offset) 2371 <1> ; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB 2372 <1> ; check dx (file offset hw) value 2373 <1> 2374 <1> ;cmp ebx, 8912896 ; >= 17408 sectors (16384+1024) ? 2375 <1> ;jnb short mget_7 ; yes, use triple indirect pointer (block) 2376 <1> 2377 <1> ; 05/05/2020 2378 00004FDA 81FB00440000 <1> cmp ebx, 17408 ; block 17408 (byte 8912896) 2379 00004FE0 7329 <1> jnb short mget_7 ; use triple indirect pointer (block) 2380 <1> 2381 00004FE2 C605[3C6F0000]02 <1> mov byte [level], 2 ; levels, 2 = double indirect blocks 2382 <1> 2383 <1> ;sub ebx, 524288 ; 1024 sectors 2384 <1> ;shr ebx, 9 ; ebx = sector offset (flat) 2385 <1> ; (from sector 1024) 2386 <1> ; 05/05/2020 2387 00004FE9 81EB00040000 <1> sub ebx, 1024 ; offset from sector 1024 2388 <1> 2389 00004FEF 88D9 <1> mov cl, bl 2390 00004FF1 80E17F <1> and cl, 127 2391 00004FF4 880D[3D6F0000] <1> mov [level+1], cl 2392 <1> ; level 2, direct block ptr index (0 to 127) 2393 00004FFA 66C1EB07 <1> shr bx, 7 2394 00004FFE 881D[3E6F0000] <1> mov [level+2], bl 2395 <1> ; level 1, indirect block ptr index (0 to 127) 2396 <1> 2397 00005004 BE[6C6B0000] <1> mov esi, i.dskp + 32 ; 8*4 2398 <1> ; level 0, double indirect block pointer 2399 00005009 EB35 <1> jmp short mget_8 2400 <1> 2401 <1> mget_7: 2402 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 2403 <1> ; 03/05/2020 2404 <1> ; 13/11/2019 (UNIXHDCP.ASM) 2405 <1> ; triple indirect pointer ; 8912896 to 1082654720 bytes 2406 <1> ;mov esi, i.dskp + 36 ; 9*4 2407 <1> 2408 0000500B C605[3C6F0000]03 <1> mov byte [level], 3 ; levels, 3 = triple indirect blocks 2409 <1> 2410 <1> ;sub ebx, 8912896 ; 17408 sectors (16384+1024) 2411 <1> ;shr ebx, 9 ; ebx = sector offset (flat) 2412 <1> ; (from sector 17408) 2413 <1> ; 05/05/2020 2414 00005012 81EB00440000 <1> sub ebx, 17408 ; offset from sector 17408 2415 <1> 2416 00005018 88D9 <1> mov cl, bl 2417 0000501A 80E17F <1> and cl, 127 2418 0000501D 880D[3D6F0000] <1> mov [level+1], cl 2419 <1> ; level 3, direct block ptr index (0 to 127) 2420 00005023 C1EB07 <1> shr ebx, 7 2421 00005026 88D9 <1> mov cl, bl 2422 00005028 80E17F <1> and cl, 127 2423 0000502B 880D[3E6F0000] <1> mov [level+2], cl 2424 <1> ; level 2, indirect block ptr index (0 to 127) 2425 00005031 66C1EB07 <1> shr bx, 7 2426 00005035 881D[3F6F0000] <1> mov [level+3], bl 2427 <1> ; level 1, double indir blk ptr index (0 to 127) 2428 <1> 2429 0000503B BE[706B0000] <1> mov esi, i.dskp + 36 ; 9*4 2430 <1> ; level 0, triple indirect block pointer 2431 <1> mget_8: 2432 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibiliy modification 2433 00005040 8B06 <1> mov eax, [esi] 2434 00005042 09C0 <1> or eax, eax ; R1 2435 00005044 751A <1> jnz short mget_10 ; 2f 2436 <1> ; bne 2f / if no indirect block exists 2437 00005046 56 <1> push esi ; * ; 24/05/2020 2438 <1> 2439 00005047 E872000000 <1> call alloc_m ; 24/05/2020 2440 <1> ;call alloc ; allocate a new block for this file 2441 <1> ; eax = block number 2442 <1> ; ebx = buffer header address 2443 <1> ; [pdn] = physical drive number ; 25/05/2020 2444 <1> ;jc mget_2 ; cf -> 1 & eax = 0 -> no free block 2445 <1> 2446 0000504C 5E <1> pop esi ; * ; 24/05/2020 2447 <1> ;jc short mget_9 2448 <1> 2449 <1> ; 09/01/2022 2450 <1> ; eax = logical sector/block number 2451 <1> 2452 0000504D 8906 <1> mov [esi], eax ; record sector/block address on i.dskp area 2453 <1> 2454 0000504F E8BB030000 <1> call setimod 2455 <1> ; jsr r0,setimod / set i-node modified byte 2456 <1> ; EAX = new block number (logical) 2457 <1> 2458 <1> ; 09/01/2022 2459 <1> ; convert to physical block/sector number 2460 00005054 E8FAFEFFFF <1> call mget_2 2461 <1> ; 2462 00005059 E89BFDFFFF <1> call clear 2463 <1> ; jsr r0,clear / clear new block 2464 <1> ; 22/11/2021 2465 0000505E EB0A <1> jmp short mget_11 2466 <1> ;mget_9: 2467 <1> ; pop edx ; * ; 09/01/2022 2468 <1> ; retn 2469 <1> mget_10: ;2 2470 <1> ; 09/01/2022 2471 <1> ; eax = logical sector/block number/address 2472 <1> ; convert to physical sector/block number/address 2473 00005060 E8EEFEFFFF <1> call mget_2 2474 <1> ; 05/03/2013 2475 <1> ; EAX = r1, physical block number (of indirect block) 2476 00005065 E8B70E0000 <1> call dskrd ; read indirect block 2477 <1> ; jsr r0,dskrd / read in indirect block 2478 <1> ;jc short mget_9 2479 <1> mget_11: 2480 <1> ; 22/11/2021 2481 <1> ; eax = physical block/sector address 2482 <1> ; ebx = buffer address 2483 <1> 2484 0000506A 89C2 <1> mov edx, eax ; * ; save physical sector number in edx 2485 <1> 2486 0000506C 0FB605[3C6F0000] <1> movzx eax, byte [level] 2487 00005073 8A80[3C6F0000] <1> mov al, [eax+level] ; get sector pointer offset 2488 00005079 C1E002 <1> shl eax, 2 ; * 4 ; 09/01/2022 2489 <1> ;shl ax, 2 ; * 4 2490 <1> 2491 0000507C 01C3 <1> add ebx, eax 2492 <1> 2493 0000507E 8B03 <1> mov eax, [ebx] ; put logical block no of block 2494 <1> ; in file sought in R1 (EAX) 2495 <1> ; mov (r2),r1 / put physical block no of block in file 2496 <1> ; / sought in r1 2497 <1> 2498 00005080 21C0 <1> and eax, eax ; if logical sector/block number is zero 2499 <1> ; then we need a new block for file 2500 00005082 740F <1> jz short mget_12 2501 <1> 2502 00005084 FE0D[3C6F0000] <1> dec byte [level] 2503 0000508A 75D4 <1> jnz short mget_10 2504 <1> 2505 0000508C 29DB <1> sub ebx, ebx ; ebx = 0 ; existing sector 2506 <1> 2507 <1> ;retn 2508 <1> ; 09/01/2022 2509 <1> ; eax = logical block/sector number 2510 0000508E E9C0FEFFFF <1> jmp mget_2 2511 <1> 2512 <1> mget_12: 2513 <1> ; 22/11/2021 2514 00005093 52 <1> push edx ; * 2515 00005094 53 <1> push ebx ; ** ; buffer data position 2516 00005095 E824000000 <1> call alloc_m 2517 <1> ;call alloc ; allocate a new block for this file 2518 <1> ; eax = block number (logical) 2519 <1> ; ebx = buffer header address 2520 0000509A 5E <1> pop esi ; ** 2521 <1> ; 09/01/2022 2522 <1> ;pop edx ; * 2523 <1> ;jc short mget_9 ; cf -> 1 & eax = 0 -> no free block 2524 <1> 2525 0000509B 8906 <1> mov [esi], eax ; record/save block number (logical) 2526 <1> 2527 <1> ; 22/11/2021 2528 0000509D 870424 <1> xchg eax, [esp] ; * 2529 <1> 2530 <1> ; eax (r1) = physical block number (of indirect block) 2531 000050A0 E8DC0E0000 <1> call wslot 2532 <1> ; jsr r0,wslot 2533 <1> ; eax (r1) = physical block number 2534 <1> ; ebx (r5) = pointer to buffer (indirect block) 2535 000050A5 E8F30E0000 <1> call dskwr 2536 <1> ; eax = r1 = physical block number (of indirect block) 2537 <1> ; jsr r0,dskwr / write newly modified indirect block 2538 <1> ; / back out on disk 2539 000050AA 58 <1> pop eax ; * ; 31/07/2013 2540 <1> ; mov (sp),r1 / restore block number of new block 2541 <1> 2542 <1> ; 09/01/2022 2543 <1> ; eax = logical sector/block number/address of new block 2544 <1> ; convert to physical sector/block number/address 2545 000050AB E8A3FEFFFF <1> call mget_2 2546 <1> 2547 000050B0 E844FDFFFF <1> call clear 2548 <1> ; jsr r0,clear / clear new block 2549 <1> 2550 000050B5 FE0D[3C6F0000] <1> dec byte [level] 2551 000050BB 75AD <1> jnz short mget_11 2552 <1> 2553 <1> ; 09/01/2022 2554 <1> ; eax = physical sector/block number/address of new block 2555 <1> 2556 <1> ; 22/11/2021 2557 <1> ; ebx = buffer address 2558 <1> mget_13: ; 2 2559 <1> ; eax (r1) = Block number of new block 2560 000050BD C3 <1> retn 2561 <1> ; rts r0 2562 <1> 2563 <1> ; 09/01/2022 2564 <1> ; 26/11/2021 2565 <1> ; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2566 <1> alloc_m: 2567 <1> ; 27/11/2021 2568 <1> ; 28/10/2021 2569 <1> ; 07/05/2021 2570 <1> ; 26/05/2020 2571 <1> ; 25/05/2020 2572 <1> ; 24/05/2020 - Retro UNIX 386 v2 2573 <1> ; 'alloc' call in 'mget' 2574 <1> ; 2575 <1> ; (('mget_r' will be returned with error)) 2576 <1> ; (('mget_w' will continue to 'alloc')) 2577 <1> 2578 <1> ; Note: 'sysread' will return with cf = 0, eax = 0 2579 <1> ; if [fofp] >= file size (eax = 0 --> EOF) 2580 <1> ; So, if we are here, that means [fofp] < file size 2581 <1> ; but disk address is 0. 2582 <1> 2583 000050BE 803D[3A6F0000]01 <1> cmp byte [mget_rw], 1 ; write access ? (mget_w) 2584 000050C5 730F <1> jnb short alloc ; yes (this is a call from 'mget_w') 2585 <1> ; ((cf = 1)) 2586 <1> ; no (this is a call from 'mget_r') ! 2587 <1> ;mov eax, ERR_FILE_SIZE ; file size error (inode error!) 2588 <1> ; [User may change this empty/invalid inode (disk) sector 2589 <1> ; pointer with a new valid inode (disk) sector pointer 2590 <1> ; by writing new clear (zero) sector to same file position 2591 <1> ; in order to correct file size -inode parm/content- error. 2592 <1> ; It may be useful for recovering lost data if other sector 2593 <1> ; pointers are not empty.] 2594 <1> ;retn 2595 <1> ; 27/11/2021 2596 000050C7 C705[186F0000]1400- <1> mov dword [u.error], ERR_FILE_SIZE 2596 000050CF 0000 <1> 2597 <1> ; file size error (inode error!) 2598 000050D1 E9D6EAFFFF <1> jmp error 2599 <1> alloc: 2600 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 2601 <1> ; 27/11/2021 2602 <1> ; 26/11/2021 - Major modification for Runix v2 file system 2603 <1> ; (I have called this kernel version as v1.2, it is a 2604 <1> ; debug/test version just before Retro UNIX 386 v2 kernel) 2605 <1> ; ((there were running problems on new version, 2606 <1> ; so i am developing an intermediate version with minimum 2607 <1> ; modification on v1.1 code which is successfuly running)) 2608 <1> ; ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 2609 <1> ; 2610 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2611 <1> ; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2612 <1> ; 2613 <1> ; get a free block and 2614 <1> ; set the corresponding bit in the free storage map 2615 <1> ; 2616 <1> ; INPUTS -> 2617 <1> ; cdev (current device) 2618 <1> ; r2 2619 <1> ; r3 2620 <1> ; OUTPUTS -> 2621 <1> ; r1 (physical block number of block assigned) 2622 <1> ; smod, mmod, systm (super block), mount (mountable super block) 2623 <1> ; 2624 <1> ; ((AX = R1)) output 2625 <1> ; (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM) 2626 <1> ; ((Modified registers: edx, ecx)) 2627 <1> 2628 <1> ; 26/11/2021 2629 <1> ; INPUT: 2630 <1> ; [cdev] = current device (root = 0, mounted = 1) 2631 <1> ; OUTPUT: 2632 <1> ; eax = disk block/sector number/address (physical) 2633 <1> ; (ebx = disk buffer address for sector/block in eax) 2634 <1> ; 2635 <1> ; Note: 2636 <1> ; Free blocks map will be modified and written to it's disk. 2637 <1> ; Superblock (buffer) of [cdev] will be modified and it's 2638 <1> ; modification flag will be set; but the superblock 2639 <1> ; will not be written to it's disk in this 'alloc' procedure) 2640 <1> ; 2641 <1> ; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp 2642 <1> 2643 <1> ; 09/01/2022 2644 <1> ; Return: eax = logical block/sector number 2645 <1> 2646 <1> ; 26/11/2021 2647 000050D6 BB[546F0000] <1> mov ebx, systm ; (SuperBlock of root file system) 2648 <1> ; mov $systm,r2 / start of inode and free storage map for drum 2649 000050DB F605[856E0000]01 <1> test byte [cdev], 1 2650 <1> ; tst cdev 2651 000050E2 7405 <1> jz short alloc_1 2652 <1> ; beq 1f / drum is device 2653 000050E4 BB[5C710000] <1> mov ebx, mount ; (SuperBlock of mounted file system) 2654 <1> ; mov $mount,r2 / disk or tape is device, start of inode and 2655 <1> ; / free storage map 2656 <1> alloc_1: ; 1 2657 <1> ; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code 2658 <1> ;test byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs 2659 <1> ;jnz short alloc_2 ; 'read only file system' error 2660 <1> ; 2661 000050E9 8B4B38 <1> mov ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors 2662 000050EC 21C9 <1> and ecx, ecx 2663 000050EE 750F <1> jnz short alloc_3 2664 <1> alloc_2: 2665 <1> ; 'no free blocks on disk !' error 2666 000050F0 C705[186F0000]2100- <1> mov dword [u.error], ERR_ALLOC 2666 000050F8 0000 <1> 2667 000050FA E9ADEAFFFF <1> jmp error 2668 <1> alloc_3: 2669 <1> ; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code 2670 000050FF 31C0 <1> xor eax, eax 2671 <1> ; 23/07/2021 2672 00005101 8B4B3C <1> mov ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number 2673 <1> ; (as logical sector number) 2674 00005104 09C9 <1> or ecx, ecx 2675 00005106 7415 <1> jz short alloc_5 ; 0 = initial/reset value or 'not valid' 2676 00005108 41 <1> inc ecx ; 0FFFFFFFFh -> 0 2677 00005109 7412 <1> jz short alloc_5 ; 'not valid' or 'not calculated' 2678 0000510B 49 <1> dec ecx ; restore first free block value 2679 0000510C 89C8 <1> mov eax, ecx 2680 <1> ; 1 allocation byte (in fbm) is for 8 sectors 2681 0000510E C1E903 <1> shr ecx, 3 ; first free block number / 8 2682 00005111 80E1FC <1> and cl, ~3 ; dword alignment (to backward) 2683 <1> ; 27/11/2021 2684 00005114 890D[3C6F0000] <1> mov [free_map_offset], ecx ; byte position on fbm 2685 <1> alloc_4: 2686 0000511A C1E80C <1> shr eax, 12 ; 1 fbm sector for 4096 sectors 2687 <1> alloc_5: 2688 <1> ; 26/11/2021 2689 0000511D 53 <1> push ebx ; ** ; superblock buffer address 2690 <1> ; eax = fbm sector index 2691 0000511E A3[406F0000] <1> mov [free_map_index], eax 2692 00005123 034318 <1> add eax, [ebx+SB.FreeMapAddr] 2693 <1> ; free blocks map start sector addr 2694 <1> ; 09/01/2022 2695 00005126 034304 <1> add eax, [ebx+SB.BootSectAddr] 2696 <1> ; + Hidden Sectors 2697 <1> ; 2698 <1> ; eax = physical sector number 2699 00005129 E8F30D0000 <1> call dskrd 2700 <1> ; cpu returns here if there is/was not an error in 'dskrd' 2701 <1> ; eax = physical sector number 2702 <1> ; ebx = buffer data address 2703 <1> ; 27/11/2021 2704 0000512E 8B15[3C6F0000] <1> mov edx, [free_map_offset] ; byte position on fbm 2705 00005134 A3[446F0000] <1> mov [free_map_sector], eax ; physical sector number 2706 00005139 B9FF010000 <1> mov ecx, 511 2707 <1> ;and edx, 511 2708 0000513E 21CA <1> and edx, ecx ; fbm byte offset in fbm buffer 2709 00005140 41 <1> inc ecx ; 512 2710 00005141 01D9 <1> add ecx, ebx 2711 00005143 01DA <1> add edx, ebx ; + buffer address 2712 00005145 5B <1> pop ebx ; ** ; superblock buffer address 2713 <1> ; 2714 <1> ; ebx = superblock buffer address 2715 <1> ; edx = superblock buffer address + byte offset (dword aligned) 2716 <1> ; ecx = superblock buffer address + 512 2717 <1> alloc_6: 2718 <1> ; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code 2719 <1> ; for Retro UNIX 386 v1.2 2720 <1> ; 25/05/2020 - Retro UNIX 386 v2 code 2721 <1> ; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors)) 2722 <1> ; ((Note: Logical drive size must be multiplies of 32 sectors)) 2723 <1> ; 19/05/2020 2724 <1> ; edx = free blocks map byte address 2725 00005146 0FBC02 <1> bsf eax, [edx] ; Scans source operand for first bit set (1). 2726 <1> ; Clear ZF if a bit is found set (1) and 2727 <1> ; loads the destination with an index to 2728 <1> ; first set bit. (0 -> 31) 2729 <1> ; Sets ZF to 1 if no bits are found set. 2730 00005149 752A <1> jnz short alloc_8 ; ZF = 0 -> a free block has been found 2731 <1> 2732 0000514B A1[3C6F0000] <1> mov eax, [free_map_offset] ; byte offset from start of fbm 2733 00005150 83C004 <1> add eax, 4 ; next dword 2734 00005153 3B431C <1> cmp eax, [ebx+SB.FreeMapSize] ; fbm size in bytes 2735 00005156 7209 <1> jb short alloc_7 2736 <1> ; invalidate superblock's first free block field 2737 00005158 C7433CFFFFFFFF <1> mov dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh 2738 <1> ; 'no free blocks on disk !' error 2739 0000515F EB8F <1> jmp alloc_2 2740 <1> alloc_7: 2741 <1> ; 26/05/2020 2742 <1> ; NOTE: If ldrv size is not multiplies of 32 sectors, 2743 <1> ; mod (ldrv size / 32) sectors (at the end of ldrv) 2744 <1> ; can not be allocated (for regular files or dirs)! 2745 <1> ; (Kernel or runix fs installation program can use 2746 <1> ; this fact to save/duplicate critical sectors/data 2747 <1> ; onto end sectors of that logical drive's runix fs.) 2748 <1> 2749 <1> ; 26/11/2021 2750 00005161 A3[3C6F0000] <1> mov [free_map_offset], eax 2751 <1> ; 28/07/2021 2752 <1> ; set next first free block value for search 2753 00005166 C1E003 <1> shl eax, 3 ; * 8 ; first free block 2754 <1> ; 26/11/2021 2755 00005169 89433C <1> mov [ebx+SB.FirstFreeBlk], eax 2756 <1> ; search (scan) for next free block map dword (in buffer) 2757 0000516C 83C204 <1> add edx, 4 ; next dword 2758 0000516F 39CA <1> cmp edx, ecx 2759 00005171 72D3 <1> jb short alloc_6 2760 <1> ; 27/11/2021 2761 00005173 EBA5 <1> jmp short alloc_4 2762 <1> 2763 <1> alloc_8: 2764 <1> ; 26/11/2021 2765 <1> ; convert bit index to xor value 2766 <1> ; and then set allocated flag for corresponding fbm bit 2767 00005175 89C1 <1> mov ecx, eax 2768 <1> ;mov cl, al 2769 <1> ;sub eax, eax 2770 <1> ;inc al ; eax = 1 2771 00005177 B001 <1> mov al, 1 2772 00005179 D3E0 <1> shl eax, cl 2773 0000517B 3102 <1> xor [edx], eax ; clear allocated block's bit in the fbm 2774 <1> ; zero bit means allocated disk block (1 means free disk block) 2775 <1> 2776 0000517D A1[3C6F0000] <1> mov eax, [free_map_offset] ; byte offset from start of fbm 2777 <1> ; note: eax is dword aligned (0,4,8,12..) ! 2778 00005182 C1E003 <1> shl eax, 3 ; * 8 ; free block number base 2779 00005185 01C8 <1> add eax, ecx ; add allocation bit index (0 to 31) 2780 00005187 89433C <1> mov [ebx+SB.FirstFreeBlk], eax ; current free block 2781 <1> ; (which is being allocated here) 2782 <1> 2783 <1> ;mov eax, [ebx+SB.FreeMapAddr] 2784 <1> ; ; free blocks map start sector addr 2785 <1> ;add eax, [free_map_index] 2786 <1> 2787 <1> ;;add eax, [ebx+SB.BootSectAddr] 2788 <1> ; ; + Hidden Sectors 2789 <1> ; eax = physical sector number 2790 <1> 2791 <1> ; 27/11/2021 2792 0000518A A1[446F0000] <1> mov eax, [free_map_sector] ; physical sector number 2793 <1> 2794 0000518F E8ED0D0000 <1> call wslot 2795 <1> ; ebx = buffer data address (write operation bit is set) 2796 <1> ; eax = physical sector number 2797 <1> ; Note: ebx contains addr of the 1st buffer in the buffer 2798 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 2799 <1> 2800 <1> ; 27/11/2021 2801 <1> ;mov [free_map_buffer], ebx ; save free map buffer address 2802 <1> 2803 00005194 E8040E0000 <1> call dskwr ; writes the 1st buffer to sector 2804 <1> ; (at the beginning/head of the buffer chain) 2805 <1> 2806 <1> ; if we are here, buffer has been written to disk successfully 2807 <1> ; (otherwise cpu would jump to 'error' address) 2808 <1> 2809 <1> ; set superblock modified flag 2810 00005199 BA[986E0000] <1> mov edx, smod 2811 0000519E BB[546F0000] <1> mov ebx, systm 2812 000051A3 F605[856E0000]01 <1> test byte [cdev], 1 ; mounted device ? 2813 000051AA 7406 <1> jz short alloc_9 ; no, root device 2814 <1> ; yes, mounted device 2815 000051AC BB[5C710000] <1> mov ebx, mount 2816 <1> ;mov edx, mmod 2817 000051B1 42 <1> inc edx ; edx = offset mmod 2818 <1> alloc_9: 2819 000051B2 FE02 <1> inc byte [edx] ; superblock modified ! 2820 <1> 2821 <1> ; Allocating a new sector/block (for file) has been completed here. 2822 000051B4 8B4338 <1> mov eax, [ebx+SB.FreeBlocks] 2823 000051B7 40 <1> inc eax ; 0FFFFFFFFh -> 0 2824 000051B8 7405 <1> jz short alloc_10 ; not valid (not set) 2825 000051BA 48 <1> dec eax ; Free Blocks 2826 000051BB 48 <1> dec eax ; Free Blocks = Free Blocks - 1 2827 000051BC 894338 <1> mov [ebx+SB.FreeBlocks], eax 2828 <1> alloc_10: 2829 000051BF E8900E0000 <1> call get_system_time 2830 <1> ; eax = current time (as unix epoch time) 2831 <1> ; 30/07/2021 2832 000051C4 89435C <1> mov [ebx+SB.ModifTime], eax 2833 <1> 2834 000051C7 8B433C <1> mov eax, [ebx+SB.FirstFreeBlk] ; allocated block address 2835 000051CA FF433C <1> inc dword [ebx+SB.FirstFreeBlk] 2836 <1> ; +1, new value of first free block 2837 <1> ; (new search will be started from here) 2838 <1> ; ((it may not be free, no problem)) 2839 <1> 2840 <1> ; put free map buffer address in ebx 2841 <1> ; 27/11/2021 2842 <1> ;mov ebx, [free_map_buffer] 2843 <1> 2844 000051CD C3 <1> retn 2845 <1> 2846 <1> ; 09/01/2022 2847 <1> ; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2848 <1> free: 2849 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 2850 <1> ; 05/11/2021 2851 <1> ; 29/10/2021 - temporary (simplified code) 2852 <1> ; 14/08/2021 2853 <1> ; 12/06/2021 2854 <1> ; 07/06/2020 2855 <1> ; 25/05/2020 (Retro UNIX 386 v2 - Beginning) 2856 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2857 <1> ; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2858 <1> ; 2859 <1> ; calculates byte address and bit position for given block number 2860 <1> ; then sets the corresponding bit in the free storage map 2861 <1> ; 2862 <1> ; INPUTS -> 2863 <1> ; r1 - block number for a block structured device 2864 <1> ; cdev - current device 2865 <1> ; OUTPUTS -> 2866 <1> ; free storage map is updated 2867 <1> ; smod is incremented if cdev is root device (fixed disk) 2868 <1> ; mmod is incremented if cdev is a removable disk 2869 <1> ; 2870 <1> ; (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM) 2871 <1> ; ((Modified registers: DX, CX)) 2872 <1> 2873 <1> ; 27/11/2021 2874 <1> ; INPUT: 2875 <1> ; [cdev] = current device (root = 0, mounted = 1) 2876 <1> ; eax = disk block/sector number/address (logical) 2877 <1> ; OUTPUT: 2878 <1> ; ebx = superblock buffer address 2879 <1> ; 2880 <1> ; Note: 2881 <1> ; Free blocks map will be modified and written to it's disk. 2882 <1> ; Superblock (buffer) of [cdev] will be modified and it's 2883 <1> ; modification flag will be set; but the superblock 2884 <1> ; will not be written to it's disk in this 'free' procedure) 2885 <1> ; 2886 <1> ; Modified registers: ebx, ecx, edx, esi, edi, ebp 2887 <1> 2888 <1> ; 27/11/2021 2889 000051CE BB[546F0000] <1> mov ebx, systm ; (SuperBlock of root file system) 2890 000051D3 F605[856E0000]01 <1> test byte [cdev], 1 2891 000051DA 7405 <1> jz short free_1 2892 000051DC BB[5C710000] <1> mov ebx, mount ; (SuperBlock of mounted file system) 2893 <1> free_1: ; 1 2894 <1> ; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code 2895 <1> ;test byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs 2896 <1> ;jz short free_2 2897 <1> ; 'read only file system' error 2898 000051E1 C705[186F0000]1E00- <1> mov dword [u.error], ERR_READ_ONLY_FS 2898 000051E9 0000 <1> 2899 000051EB E9BCE9FFFF <1> jmp error 2900 <1> free_2: 2901 000051F0 89C1 <1> mov ecx, eax ; logical sector/block number 2902 000051F2 A3[446F0000] <1> mov [free_map_sector], eax 2903 000051F7 C1E903 <1> shr ecx, 3 ; convert to fbmap byte offset 2904 000051FA C1E80C <1> shr eax, 12 ; convert to fbmap sector index 2905 <1> ; (1 fb sector for 4096 sectors) 2906 <1> ;and cl, ~3 ; dword alignment (to backward) 2907 000051FD 890D[3C6F0000] <1> mov [free_map_offset], ecx ; byte position on fbm 2908 <1> ; 27/11/2021 2909 <1> ; eax = fbm sector index 2910 00005203 034318 <1> add eax, [ebx+SB.FreeMapAddr] 2911 <1> ; free blocks map start sector address 2912 <1> ; 09/01/2022 2913 00005206 034304 <1> add eax, [ebx+SB.BootSectAddr] 2914 <1> ; + Hidden Sectors 2915 <1> ; ebx = superblock address 2916 <1> ; eax = physical sector number 2917 00005209 E8130D0000 <1> call dskrd 2918 <1> ; cpu returns here if there is/was not an error in 'dskrd' 2919 <1> ; eax = physical sector number 2920 <1> ; ebx = buffer data address 2921 <1> ; 27/11/2021 2922 0000520E A3[406F0000] <1> mov [free_map_index], eax ; save physical sector address 2923 00005213 8B15[3C6F0000] <1> mov edx, [free_map_offset] ; byte position on fbm 2924 <1> ; 2925 00005219 29C0 <1> sub eax, eax 2926 0000521B A0[446F0000] <1> mov al, [free_map_sector] ; logical sector number 2927 00005220 2407 <1> and al, 7 2928 <1> 2929 <1> ; al = bit offset in fbm allocation byte 2930 <1> ; edx = buffer address (start+offset) 2931 <1> ; [free_map_offset] = byte position on fbm 2932 <1> ; 27/11/2021 2933 00005222 0FAB02 <1> bts [edx], eax ; copy value of bit position in eax to cf 2934 <1> ; then set same bit position at [edx] 2935 00005225 7305 <1> jnc short free_3 ; it was allocated sector 2936 <1> 2937 <1> ; already free sector !? 2938 <1> ; (nonsence or defective fs) 2939 <1> 2940 00005227 30C0 <1> xor al, al ; 0 ; eax = 0 2941 00005229 48 <1> dec eax ; 0FFFFFFFFh 2942 <1> ;mov [ebx+SB.FreeBlocks], eax 2943 <1> ; invalidate free blocks count 2944 0000522A EB18 <1> jmp short free_5 2945 <1> free_3: 2946 <1> ; 27/11/2021 2947 0000522C 8B4338 <1> mov eax, [ebx+SB.FreeBlocks] 2948 0000522F 40 <1> inc eax 2949 00005230 7401 <1> jz short free_4 ; 0FFFFFFFFh -> 0 (invalid!) 2950 00005232 48 <1> dec eax ; 0 -> 0FFFFFFFFh (invalid!) 2951 <1> free_4: 2952 00005233 50 <1> push eax ; * ; number of free blocks 2953 <1> ;mov eax, [free_map_index] ; fbm sector index 2954 <1> ;add eax, [ebx+SB.FreeMapAddr] 2955 <1> ; free blocks map start sector address 2956 <1> ;add eax, [ebx+SB.BootSectAddr] 2957 <1> ; ; + Hidden Sectors 2958 00005234 A1[406F0000] <1> mov eax, [free_map_index] ; restore physical sector address 2959 <1> ; eax = physical sector number 2960 00005239 E8430D0000 <1> call wslot 2961 <1> ; ebx = buffer data address (write operation bit is set) 2962 <1> ; eax = physical sector number 2963 <1> ; Note: ebx contains addr of the 1st buffer in the buffer 2964 <1> ; (the last allocated buffer becomes the 1st in buffer chain) 2965 <1> 2966 0000523E E85A0D0000 <1> call dskwr ; writes the 1st buffer to sector 2967 <1> ; (at the beginning/head of the buffer chain) 2968 <1> 2969 <1> ; if we are here, buffer has been written to disk successfully 2970 <1> ; (otherwise cpu would jump to 'error' address) 2971 00005243 58 <1> pop eax ; * ; number of free blocks 2972 <1> free_5: 2973 <1> ; eax = number of free blocks 2974 <1> ; 2975 <1> ; set superblock modified flag 2976 00005244 BA[986E0000] <1> mov edx, smod 2977 00005249 BB[546F0000] <1> mov ebx, systm 2978 0000524E F605[856E0000]01 <1> test byte [cdev], 1 ; mounted device ? 2979 00005255 7406 <1> jz short free_6 ; no, root device 2980 <1> ; yes, mounted device 2981 00005257 BB[5C710000] <1> mov ebx, mount 2982 <1> ;mov edx, mmod 2983 0000525C 42 <1> inc edx ; edx = offset mmod 2984 <1> free_6: 2985 0000525D 894338 <1> mov [ebx+SB.FreeBlocks], eax 2986 <1> 2987 00005260 A1[446F0000] <1> mov eax, [free_map_sector] ; logical sector number 2988 00005265 3B433C <1> cmp eax, [ebx+SB.FirstFreeBlk] 2989 00005268 7303 <1> jnb short free_7 2990 0000526A 89433C <1> mov [ebx+SB.FirstFreeBlk], eax 2991 <1> free_7: 2992 0000526D FE02 <1> inc byte [edx] ; superblock modified ! 2993 0000526F C3 <1> retn 2994 <1> 2995 <1> iget: 2996 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 2997 <1> ; 30/11/2021 2998 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 2999 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3000 <1> ; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 3001 <1> ; 3002 <1> ; get a new i-node whose i-number in r1 and whose device is in cdev 3003 <1> ; 3004 <1> ; ('iget' returns current i-number in r1, if input value of r1 is 0) 3005 <1> ; 3006 <1> ; INPUTS -> 3007 <1> ; ii - current i-number, rootdir 3008 <1> ; cdev - new i-node device 3009 <1> ; idev - current i-node device 3010 <1> ; imod - current i-node modified flag 3011 <1> ; mnti - cross device file i-number 3012 <1> ; r1 - i-numbe rof new i-node 3013 <1> ; mntd - mountable device number 3014 <1> ; 3015 <1> ; OUTPUTS -> 3016 <1> ; cdev, idev, imod, ii, r1 3017 <1> ; 3018 <1> ; ((AX = R1)) input/output 3019 <1> ; 3020 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 3021 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 3022 <1> 3023 <1> ; 22/11/2021 3024 <1> ;;mov dl, [cdev] ; 18/07/2013 3025 <1> ;;mov dh, [idev] ; 07/08/2013 3026 <1> ; 26/05/2020 - Retro UNIX 386 v2 3027 <1> ;mov dh, [cdev] 3028 <1> ;mov dl, [idev] 3029 00005270 668B15[846E0000] <1> mov dx, [idev] ; [idev] in dl, [cdev] in dh 3030 <1> ; 3031 <1> ; 22/11/2021 3032 00005277 25FFFF0000 <1> and eax, 0FFFFh 3033 0000527C 3B05[806E0000] <1> cmp eax, [ii] 3034 <1> ; cmp r1,ii / r1 = i-number of current file 3035 00005282 7504 <1> jne short iget_1 3036 <1> ; bne 1f 3037 00005284 38F2 <1> cmp dl, dh 3038 <1> ; cmp idev,cdev 3039 <1> ; / is device number of i-node = current device 3040 00005286 746C <1> je short iget_5 3041 <1> ; ; beq 2f 3042 <1> ; 14/08/2021 3043 <1> iget_1: ; 1: 3044 00005288 30DB <1> xor bl, bl 3045 0000528A 381D[966E0000] <1> cmp [imod], bl ; 0 3046 <1> ; tstb imod / has i-node of current file 3047 <1> ; / been modified i.e., imod set 3048 00005290 7628 <1> jna short iget_2 3049 <1> ; beq 1f 3050 00005292 881D[966E0000] <1> mov [imod], bl ; 0 3051 <1> ; clrb imod / if it has, 3052 <1> ; / we must write the new i-node out on disk 3053 <1> ; 22/11/2021 (32 bit push-pop) 3054 00005298 50 <1> push eax ; * 3055 <1> ; mov r1,-(sp) 3056 00005299 52 <1> push edx ; ** 3057 <1> ; mov cdev,-(sp) 3058 0000529A A1[806E0000] <1> mov eax, [ii] 3059 <1> ; mov ii,r1 3060 <1> ;mov dh, [idev] 3061 <1> ;mov [cdev], dh 3062 <1> ; 09/01/2022 3063 0000529F 8815[856E0000] <1> mov [cdev], dl ; dl = [idev] 3064 <1> ; mov idev,cdev 3065 000052A5 FEC3 <1> inc bl ; 1 3066 <1> ; 31/07/2013 3067 000052A7 881D[386F0000] <1> mov [rw], bl ; 1 == write 3068 <1> ;;28/07/2013 rw -> u.rw 3069 <1> ;;mov [u.rw], bl ; 1 == write 3070 000052AD E843000000 <1> call icalc 3071 <1> ; jsr r0,icalc; 1 3072 000052B2 5A <1> pop edx ; ** 3073 000052B3 8835[856E0000] <1> mov [cdev], dh ; 22/11/2021 3074 <1> ; mov (sp)+,cdev 3075 000052B9 58 <1> pop eax ; * 3076 <1> ; mov (sp)+,r1 3077 <1> iget_2: ; 1: 3078 <1> ;and ax, ax 3079 000052BA 21C0 <1> and eax, eax ; 22/11/2021 (32 bit inode number) 3080 <1> ; tst r1 / is new i-number non zero 3081 000052BC 7431 <1> jz short iget_4 ; 2f 3082 <1> ; beq 2f / branch if r1=0 3083 <1> 3084 <1> ;mov dh, [cdev] 3085 000052BE 08F6 <1> or dh, dh ; 22/11/2021 3086 <1> ; tst cdev / is the current device number non zero 3087 <1> ; / (i.e., device =/ drum) 3088 000052C0 7515 <1> jnz short iget_3 ; 1f 3089 <1> ; bne 1f / branch 1f cdev =/ 0 ;; (cdev != 0) 3090 <1> ; 22/11/2021 3091 000052C2 3B05[906E0000] <1> cmp eax, [mnti] 3092 <1> ;cmp ax, [mnti] 3093 <1> ; cmp r1,mnti / mnti is the i-number of the cross device 3094 <1> ; / file (root directory of mounted device) 3095 000052C8 750D <1> jne short iget_3 ; 1f 3096 <1> ; bne 1f 3097 <1> ;mov bl, [mntd] 3098 000052CA FEC6 <1> inc dh ; mov dh, 1 ; 22/11/2021 3099 000052CC 8835[856E0000] <1> mov [cdev], dh ; 22/11/2021 3100 <1> ; mov mntd,cdev / make mounted device the current device 3101 <1> ; 22/11/2021 3102 000052D2 A1[8C6E0000] <1> mov eax, [rootdir] ; rootdir = 1 (for runix v2 file system) 3103 <1> ;mov ax, [rootdir] 3104 <1> ; mov rootdir,r1 3105 <1> iget_3: ; 1: 3106 <1> ; 22/11/2021 3107 000052D7 A3[806E0000] <1> mov [ii], eax ; 32 bit inode number 3108 <1> ;mov [ii], ax 3109 <1> ; mov r1,ii 3110 <1> ; 30/11/2021 3111 000052DC 8835[846E0000] <1> mov [idev], dh ; cdev 3112 <1> ;mov [idev], dl ; cdev 3113 <1> ; mov cdev,idev 3114 000052E2 30DB <1> xor bl, bl 3115 <1> ; 31/07/2013 3116 000052E4 881D[386F0000] <1> mov [rw], bl ; 0 == read 3117 <1> ;;28/07/2013 rw -> u.rw 3118 <1> ;;mov [u.rw], bl ; 0 = read 3119 000052EA E806000000 <1> call icalc 3120 <1> ; jsr r0,icalc; 0 / read in i-node ii 3121 <1> iget_4: ; 2: 3122 <1> ; 22/11/2021 3123 000052EF A1[806E0000] <1> mov eax, [ii] 3124 <1> ;mov ax, [ii] 3125 <1> ; mov ii,r1 3126 <1> iget_5: 3127 000052F4 C3 <1> retn 3128 <1> ; rts r0 3129 <1> 3130 <1> icalc: 3131 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 3132 <1> ; 28/11/2021 3133 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 3134 <1> ; 02/07/2015 3135 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3136 <1> ; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 3137 <1> ; 3138 <1> ; calculate physical block number from i-number then 3139 <1> ; read or write that block 3140 <1> ; 3141 <1> ; 'icalc' is called from 'iget' 3142 <1> ; 3143 <1> ; for original unix v1: 3144 <1> ; / i-node i is located in block (i+31.)/16. and begins 32.* 3145 <1> ; / (i+31.) mod 16. bytes from its start 3146 <1> ; 3147 <1> ; for retro unix 8086 v1: 3148 <1> ; i-node is located in block (i+47)/16 and 3149 <1> ; begins 32*(i+47) mod 16 bytes from its start 3150 <1> ; 3151 <1> ; INPUTS -> 3152 <1> ; r1 - i-number of i-node 3153 <1> ; 3154 <1> ; OUTPUTS -> 3155 <1> ; inode r/w 3156 <1> ; 3157 <1> ; ((AX = R1)) input 3158 <1> ; 3159 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 3160 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 3161 <1> ; 3162 <1> 3163 <1> ; 28/11/2021 3164 <1> ;cmp byte [idev], 0 ; [cdev] = [idev] 3165 000052F5 803D[856E0000]00 <1> cmp byte [cdev], 0 3166 000052FC 7607 <1> jna short icalc_0r 3167 000052FE BD[5C710000] <1> mov ebp, mount ; mounted file system's superblock 3168 00005303 EB05 <1> jmp short icalc_0m 3169 <1> icalc_0r: 3170 <1> ; 28/11/2021 3171 00005305 BD[546F0000] <1> mov ebp, systm ; root file system's superblock 3172 <1> icalc_0m: 3173 <1> ; 22/11/2021 3174 <1> ;mov edx, eax 3175 0000530A 8B15[806E0000] <1> mov edx, [ii] ; 32 bit inode number 3176 00005310 8B4528 <1> mov eax, [ebp+SB.InodeTblAddr] ; inode table base address 3177 <1> ; 3178 00005313 4A <1> dec edx ; 0 based inode number 3179 <1> ; (inode index in inode table) 3180 00005314 52 <1> push edx ; * 3181 00005315 C1EA03 <1> shr edx, 3 3182 00005318 7402 <1> jz short icalc_0t ; 0 for inodes 1 to 8 3183 0000531A 01D0 <1> add eax, edx 3184 <1> icalc_0t: 3185 <1> ; 09/01/2022 3186 <1> ; eax = locical block/sector number 3187 0000531C 034504 <1> add eax, [ebp+SB.BootSectAddr] 3188 <1> ; eax = physical block/sector number 3189 0000531F E8FD0B0000 <1> call dskrd 3190 <1> ; jsr r0,dskrd / read in block containing i-node i. 3191 <1> ; 31/07/2013 3192 00005324 803D[386F0000]00 <1> cmp byte [rw], 0 ; Retro Unix 8086 v1 feature ! 3193 <1> ;; 28/07/2013 rw -> u.rw 3194 <1> ;;cmp byte [u.rw], 0 ; Retro Unix 8086 v1 feature ! 3195 <1> ; tst (r0) 3196 0000532B 7605 <1> jna short icalc_1 3197 <1> ; beq 1f / branch to wslot when argument 3198 <1> ; / in icalc call = 1 3199 <1> ; eAX = r1 = block number 3200 0000532D E84F0C0000 <1> call wslot 3201 <1> ; jsr r0,wslot / set up data buffer for write 3202 <1> ; / (will be same buffer as dskrd got) 3203 <1> ; EBX = r5 points to first word in data area for this block 3204 <1> icalc_1: ; 1: 3205 00005332 5A <1> pop edx ; * 3206 <1> ; 22/11/2021 3207 00005333 83E207 <1> and edx, 07h ; 8 inodes per inode table sector 3208 00005336 C1E206 <1> shl edx, 6 ; * 64 (inode size) 3209 <1> ; edx = 64 * (mod(inodenumber-1)/8) 3210 00005339 89DE <1> mov esi, ebx ; ebx points to 1st word of the buffer 3211 0000533B 01D6 <1> add esi, edx ; edx is inode offset in the buffer 3212 <1> ; eSI (r5) points to first word in i-node i. 3213 <1> ; mov (sp)+,mq / calculate offset in data buffer; 3214 <1> ; / 32.*(i+31.)mod16 3215 <1> ; mov $5,lsh / for i-node i. 3216 <1> ; add mq,r5 / r5 points to first word in i-node i. 3217 0000533D BF[406B0000] <1> mov edi, inode 3218 <1> ; mov $inode,r1 / inode is address of first word 3219 <1> ; / of current i-node 3220 <1> ;mov ecx, 8 ; 02/07/2015 (32 bit modification) 3221 <1> ; ; mov $16.,r3 3222 <1> ; 28/11/2021 3223 00005342 29C9 <1> sub ecx, ecx 3224 00005344 B110 <1> mov cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes 3225 <1> ; 31/07/2013 3226 00005346 382D[386F0000] <1> cmp [rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 3227 <1> ;;28/07/2013 rw -> u.rw 3228 <1> ;;cmp [u.rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 3229 <1> ; tst (r0)+ / branch to 2f when argument in icalc call = 0 3230 0000534C 7609 <1> jna short icalc_3 3231 <1> ; beq 2f / r0 now contains proper return address 3232 <1> ; / for rts r0 3233 <1> icalc_2: ; 1: 3234 0000534E 87F7 <1> xchg esi, edi 3235 <1> ; overwrite old i-node (in buffer to be written) 3236 00005350 F3A5 <1> rep movsd 3237 <1> ; mov (r1)+,(r5)+ / over write old i-node 3238 <1> ; dec r3 3239 <1> ; bgt 1b 3240 <1> ;call dskwr 3241 <1> ; ; jsr r0,dskwr / write inode out on device 3242 <1> ;retn 3243 <1> ; ; rts r0 3244 <1> ; 28/11/2021 3245 00005352 E9460C0000 <1> jmp dskwr 3246 <1> icalc_3: ; 2: 3247 <1> ; copy new i-node into inode area of (core) memory 3248 00005357 F3A5 <1> rep movsd 3249 <1> ; mov (r5)+,(r1)+ / read new i-node into 3250 <1> ; / "inode" area of core 3251 <1> ; dec r3 3252 <1> ; bgt 2b 3253 00005359 C3 <1> retn 3254 <1> ; rts r0 3255 <1> 3256 <1> access: 3257 <1> ; 25/12/2021 3258 <1> ; 19/12/2021 3259 <1> ; 28/11/2021 3260 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 3261 <1> ; 31/10/2021 - temporary (simplified code) 3262 <1> ; 14/06/2021 3263 <1> ; 02/05/2021 3264 <1> ; 27/03/2021 3265 <1> ; 26/03/2021 3266 <1> ; 25/03/2021 3267 <1> ; 23/03/2021 (Retro UNIX 386 v2 - Beginning) 3268 <1> ; ((ref: unix v7 source - fio.c)) 3269 <1> ; ref: INODE STRUCTURE of Retro UNIX v2 file system 3270 <1> ; 07/02/2020, 'RETRO UNIX v2 Inodes.pdf' 3271 <1> ; 3272 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3273 <1> ; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1) 3274 <1> ; 3275 <1> ; check whether user is owner of file or user has read or write 3276 <1> ; permission (based on i.flgs). 3277 <1> ; 3278 <1> ; INPUTS -> 3279 <1> ; r1 - i-number of file 3280 <1> ; u.uid 3281 <1> ; arg0 -> (owner flag mask) 3282 <1> ; Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 3283 <1> ; OUTPUTS -> 3284 <1> ; inode (or jump to error) 3285 <1> ; 3286 <1> ; ((AX = R1)) input/output 3287 <1> ; 3288 <1> ; ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP)) 3289 <1> 3290 <1> ; 26/03/2021 3291 <1> ; INPUT: 3292 <1> ; eax = inode number (ax) 3293 <1> ; dx = mode (IEXEC, IREAD or IWRITE) 3294 <1> ; [cdev] = logical drive number ; 31/10/2021 3295 <1> ; 3296 <1> ; OUTPUT: 3297 <1> ; inode (or jump to error) 3298 <1> ; eax (ax) = [ii] = inode number 3299 <1> ; [cdev] = logical drive number ; 31/10/2021 3300 <1> ; 3301 <1> ; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp 3302 <1> ; 3303 <1> ; IREAD equ 100h ; read permission flag, owner 3304 <1> ; IWRITE equ 80h ; write permission flag, owner 3305 <1> ; IEXEC equ 40h ; execute permission flag, owner 3306 <1> 3307 <1> ; 23/03/2021 3308 0000535A 52 <1> push edx ; save flag (DX) 3309 <1> ;push dx ; save flag (DL) 3310 0000535B E810FFFFFF <1> call iget 3311 <1> ; jsr r0,iget / read in i-node for current directory 3312 <1> ; / (i-number passed in r1) 3313 <1> ;;mov cl, [i.flgs] 3314 <1> ;; ; mov i.flgs,r2 3315 <1> ; 23/03/2021 3316 <1> ;mov cx, [i.iflgs] 3317 <1> 3318 <1> ;;pop dx ; restore flag (DL) 3319 <1> ; 23/03/2021 3320 00005360 5A <1> pop edx ; restore flag (DX) 3321 <1> 3322 <1> ; 28/11/2021 (iget will not return here if there is an error) 3323 <1> ; 31/10/2021 3324 <1> ;jc short access_5 3325 <1> 3326 <1> ; 31/10/2021 3327 <1> ; Note: If eax input is same with [mnti], 'iget' will change 3328 <1> ; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 3329 <1> 3330 <1> ; 27/03/2021 3331 <1> ; 23/03/2021 3332 <1> ; (check if it is write permission flag) 3333 00005361 6681FA8000 <1> cmp dx, 80h ; IWRITE 3334 00005366 775E <1> ja short access_r ; IREAD = 100h (owner) 3335 00005368 722B <1> jb short access_x ; IEXEC = 40h (owner) 3336 <1> ; IWRITE (80h) 3337 <1> access_w: 3338 <1> ; 23/03/2021 3339 <1> ; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure)) 3340 <1> ;mov bl, [idev] 3341 <1> ;call getfs 3342 <1> ;movzx ebx, byte [idev] ; logical drive number 3343 <1> ;shl bx, 6 ; * 64 ; of current inode 3344 <1> ;add ebx, ldrvtable 3345 <1> ;;test byte [ebx+ldrv.pflags], 01h ; read only fs flag 3346 <1> ;;jz short access_0 3347 <1> ;; 14/06/2021 3348 <1> ; 14/06/2021 3349 <1> ; check block device (fs) if it is read only fs or not ? 3350 <1> ;mov edi, [ebx+ldrv.superblk] 3351 <1> ;test byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ? 3352 <1> ;jz short access_0 3353 <1> ; 31/10/2021 3354 0000536A 803D[856E0000]01 <1> cmp byte [cdev], 1 3355 00005371 7207 <1> jb short access_7 ; [cdev] = 0 3356 <1> ; [cdev] = 1 3357 <1> ; 28/11/2021 3358 00005373 BF[5C710000] <1> mov edi, mount ; mounted file system's superblock buffer 3359 00005378 EB05 <1> jmp short access_8 3360 <1> access_7: 3361 <1> ; 28/11/2021 3362 0000537A BF[546F0000] <1> mov edi, systm ; root file system's superblock buffer 3363 <1> access_8: 3364 0000537F F6476A01 <1> test byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ? 3365 00005383 7441 <1> jz short access_0 3366 <1> 3367 <1> ; 23/03/2021 3368 <1> ;mov dword [u.error], ERR_READ_ONLY_FS 3369 <1> ; ; 'read only file system !' error 3370 <1> ;jmp error 3371 <1> 3372 <1> ; 19/12/2021 3373 00005385 F605[416B0000]80 <1> test byte [i.flgs+1], 80h ; regular file ? 3374 0000538C 7438 <1> jz short access_0 ; no, device file 3375 <1> 3376 <1> ; 31/10/2021 3377 0000538E B81E000000 <1> mov eax, ERR_READ_ONLY_FS 3378 <1> ; 'read only file system !' error 3379 <1> ; 27/03/2021 3380 00005393 EB27 <1> jmp short access_5 3381 <1> 3382 <1> ; check block device (fs) if it is read only fs or not ? 3383 <1> 3384 <1> ;mov dh, [u.uid] 3385 <1> ;cmp dh, [i.uid] 3386 <1> ; ; cmpb i.uid,u.uid / is user same as owner of file 3387 <1> ;jne short access_1 3388 <1> ; bne 1f / no, then branch 3389 <1> access_x: 3390 <1> ; IEXEC (40h) 3391 <1> ; 27/03/2021 3392 00005395 668B1D[406B0000] <1> mov bx, [i.flgs] 3393 0000539C F6C780 <1> test bh, 80h ; regular file ? 3394 0000539F 7416 <1> jz short access_4 ; not executable file ! 3395 000053A1 F6C740 <1> test bh, 40h ; directory ? 3396 000053A4 7511 <1> jnz short access_4 ; not executable file ! 3397 000053A6 668B0D[F66E0000] <1> mov cx, [u.uid] 3398 000053AD 6609C9 <1> or cx, cx 3399 000053B0 7520 <1> jnz short access_3 ; (restricted user) 3400 <1> ; (super user) 3401 <1> ;test [i.flgs], dl ; execute permission for owner 3402 <1> ;test byte [i.flgs], 49h ; for owner, group, others 3403 000053B2 F6C349 <1> test bl, 49h ; exec perm for owner, group, others 3404 000053B5 7557 <1> jnz short access_2 3405 <1> access_4: 3406 <1> ; 31/10/2021 3407 000053B7 B816000000 <1> mov eax, ERR_NOT_EXECUTABLE 3408 <1> ; 'not executable file !' error 3409 <1> ; 26/03/2021 3410 <1> ;;sysexec_not_exf: 3411 <1> ; mov dword [u.error], ERR_NOT_EXECUTABLE 3412 <1> ; ; 'not executable file !' error 3413 <1> ;access_5: 3414 <1> ; jmp error 3415 <1> 3416 <1> ; 31/10/2021 3417 <1> access_5: 3418 000053BC A3[186F0000] <1> mov [u.error], eax 3419 000053C1 E9E6E7FFFF <1> jmp error 3420 <1> 3421 <1> access_r: 3422 <1> ; 27/03/2021 3423 <1> access_0: 3424 <1> ; 23/03/2021 3425 000053C6 668B0D[F66E0000] <1> mov cx, [u.uid] 3426 000053CD 6609C9 <1> or cx, cx ; 0 ; root ? 3427 <1> ;jz short access_2 ; yes 3428 <1> ; 25/12/2021 3429 000053D0 742C <1> jz short access_1 ; yes 3430 <1> access_3: 3431 <1> ; owner ? 3432 000053D2 8A1D[466B0000] <1> mov bl, [i.gid] 3433 000053D8 663B0D[446B0000] <1> cmp cx, [i.uid] 3434 <1> ;je short access_1 3435 <1> ; 02/05/2021 3436 000053DF 750E <1> jne short access_6 3437 <1> ; check owner's group number/ID 3438 000053E1 3A1D[FA6E0000] <1> cmp bl, [u.gid] ; same group number/ID ? 3439 000053E7 7415 <1> je short access_1 ; yes, owner 3440 <1> ; one of others 3441 000053E9 66C1EA06 <1> shr dx, 6 3442 000053ED EB0F <1> jmp short access_1 ; others 3443 <1> access_6: 3444 <1> ;shr cl, 2 3445 <1> ; ; asrb r2 / shift owner read write bits into non owner 3446 <1> ; ; ; / read/write bits 3447 <1> ; ; asrb r2 3448 <1> 3449 <1> ; 23/03/2021 3450 <1> ; same group ? 3451 000053EF 66C1EA03 <1> shr dx, 3 3452 <1> ;mov cl, [u.gid] 3453 <1> ;cmp cl, [i.gid] 3454 <1> ;je short access_1 3455 <1> ; 02/05/2021 3456 000053F3 3A1D[FA6E0000] <1> cmp bl, [u.gid] 3457 000053F9 7403 <1> je short access_1 ; same group, different owner 3458 <1> 3459 <1> ; others 3460 <1> ;shr dx, 3 3461 000053FB C0EA03 <1> shr dl, 3 3462 <1> ;jmp short access_1 3463 <1> 3464 <1> ;access_1: ; 1: 3465 <1> ;and cl, dl 3466 <1> ; ; bit r2,(r0)+ / test read-write flags against argument 3467 <1> ; ; / in access call 3468 <1> ;jnz short access_2 3469 <1> ; ; bne 1f 3470 <1> 3471 <1> ;or dh, dh ; super user (root) ? 3472 <1> ; ; tstb u.uid 3473 <1> ;jz short access_2 ; yes, super user 3474 <1> ;;jnz error 3475 <1> ; ; beq 1f 3476 <1> ; ; jmp error 3477 <1> 3478 <1> ;mov dword [u.error], ERR_FILE_ACCESS 3479 <1> ; ; 'permission denied !' error 3480 <1> ;jmp error 3481 <1> 3482 <1> access_1: 3483 <1> ; 23/03/2021 3484 000053FE 668515[406B0000] <1> test dx, [i.flgs] 3485 00005405 7507 <1> jnz short access_2 3486 <1> 3487 <1> ;; r/w permission error 3488 <1> ;mov dword [u.error], ERR_FILE_ACCESS 3489 <1> ; ; 'permission denied !' error 3490 <1> ;;jmp error 3491 <1> 3492 <1> ; 31/10/2021 3493 00005407 B80B000000 <1> mov eax, ERR_FILE_ACCESS 3494 <1> ; 'permission denied !' error 3495 <1> ; 27/03/2021 3496 0000540C EBAE <1> jmp short access_5 3497 <1> 3498 <1> access_2: ; 1: 3499 <1> ;; DL = flags 3500 <1> ;retn 3501 <1> ; ; rts r0 3502 <1> ; 27/03/2021 3503 <1> ; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h) 3504 0000540E C3 <1> retn 3505 <1> 3506 <1> setimod: 3507 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3508 <1> ; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 3509 <1> ; 3510 <1> ; 'setimod' sets byte at location 'imod' to 1; thus indicating that 3511 <1> ; the inode has been modified. Also puts the time of modification 3512 <1> ; into the inode. 3513 <1> ; 3514 <1> ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) 3515 <1> ; ((Modified registers: eDX, eCX, eBX)) 3516 <1> ; 3517 <1> 3518 <1> ; push edx 3519 0000540F 50 <1> push eax 3520 <1> 3521 00005410 C605[966E0000]01 <1> mov byte [imod], 1 3522 <1> ; movb $1,imod / set current i-node modified bytes 3523 <1> ; Erdogan Tan 14-7-2012 3524 00005417 E8ADE2FFFF <1> call epoch 3525 <1> ; mov s.time,i.mtim 3526 <1> ; / put present time into file modified time 3527 <1> ; mov s.time+2,i.mtim+2 3528 <1> 3529 0000541C A3[786B0000] <1> mov [i.mtim], eax 3530 <1> 3531 <1> ; Retro UNIX 386 v1 modification ! (cmp) 3532 <1> ; Retro UNIX 8086 v1 modification ! (test) 3533 00005421 833D[7C6B0000]00 <1> cmp dword [i.ctim], 0 3534 00005428 7505 <1> jnz short setimod_ok 3535 <1> 3536 0000542A A3[7C6B0000] <1> mov [i.ctim], eax 3537 <1> 3538 <1> setimod_ok: ; 31/07/2013 3539 0000542F 58 <1> pop eax 3540 <1> ;pop edx 3541 <1> 3542 00005430 C3 <1> retn 3543 <1> ; rts r0 3544 <1> 3545 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 3546 <1> %if 0 3547 <1> ; Retro UNIX 386 v1.1 'itrunc' code 3548 <1> itrunc: 3549 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3550 <1> ; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 3551 <1> ; 3552 <1> ; 'itrunc' truncates a file whose i-number is given in r1 3553 <1> ; to zero length. 3554 <1> ; 3555 <1> ; INPUTS -> 3556 <1> ; r1 - i-number of i-node 3557 <1> ; i.dskp - pointer to contents or indirect block in an i-node 3558 <1> ; i.flgs - large file flag 3559 <1> ; i.size - size of file 3560 <1> ; 3561 <1> ; OUTPUTS -> 3562 <1> ; i.flgs - large file flag is cleared 3563 <1> ; i.size - set to 0 3564 <1> ; i.dskp .. i.dskp+16 - entire list is cleared 3565 <1> ; setimod - set to indicate i-node has been modified 3566 <1> ; r1 - i-number of i-node 3567 <1> ; 3568 <1> ; ((AX = R1)) input/output 3569 <1> ; 3570 <1> ; (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM) 3571 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 3572 <1> 3573 <1> call iget 3574 <1> ; jsr r0,iget 3575 <1> mov esi, i.dskp 3576 <1> ; mov $i.dskp,r2 / address of block pointers in r2 3577 <1> xor eax, eax 3578 <1> itrunc_1: ; 1: 3579 <1> lodsw 3580 <1> ; mov (r2)+,r1 / move physical block number into r1 3581 <1> or ax, ax 3582 <1> jz short itrunc_5 3583 <1> ; beq 5f 3584 <1> push esi 3585 <1> ; mov r2,-(sp) 3586 <1> test word [i.flgs], 1000h 3587 <1> ; bit $10000,i.flgs / test large file bit? 3588 <1> jz short itrunc_4 3589 <1> ; beq 4f / if clear, branch 3590 <1> push eax 3591 <1> ; mov r1,-(sp) / save block number of indirect block 3592 <1> call dskrd 3593 <1> ; jsr r0,dskrd / read in block, 1st data word 3594 <1> ; / pointed to by r5 3595 <1> ; eBX = r5 = Buffer data address (the 1st word) 3596 <1> mov ecx, 256 3597 <1> ; mov $256.,r3 / move word count into r3 3598 <1> mov esi, ebx 3599 <1> itrunc_2: ; 2: 3600 <1> lodsw 3601 <1> ; mov (r5)+,r1 / put 1st data word in r1; 3602 <1> ; / physical block number 3603 <1> and ax, ax 3604 <1> jz short itrunc_3 3605 <1> ; beq 3f / branch if zero 3606 <1> ;push ecx 3607 <1> push cx 3608 <1> ; mov r3,-(sp) / save r3, r5 on stack 3609 <1> ;push esi 3610 <1> ; mov r5,-(sp) 3611 <1> call free 3612 <1> ; jsr r0,free / free block in free storage map 3613 <1> ;pop esi 3614 <1> ; mov(sp)+,r5 3615 <1> pop cx 3616 <1> ;pop ecx 3617 <1> ; mov (sp)+,r3 3618 <1> itrunc_3: ; 3: 3619 <1> loop itrunc_2 3620 <1> ; dec r3 / decrement word count 3621 <1> ; bgt 2b / branch if positive 3622 <1> pop eax 3623 <1> ; mov (sp)+,r1 / put physical block number of 3624 <1> ; / indirect block 3625 <1> ; 01/08/2013 3626 <1> and word [i.flgs], 0EFFFh ; 1110111111111111b 3627 <1> itrunc_4: ; 4: 3628 <1> call free 3629 <1> ; jsr r0,free / free indirect block 3630 <1> pop esi 3631 <1> ; mov (sp)+,r2 3632 <1> itrunc_5: ; 5: 3633 <1> cmp esi, i.dskp+16 3634 <1> ; cmp r2,$i.dskp+16. 3635 <1> jb short itrunc_1 3636 <1> ; bne 1b / branch until all i.dskp entries check 3637 <1> ; 01/08/2013 3638 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 3639 <1> ; bic $10000,i.flgs / clear large file bit 3640 <1> mov edi, i.dskp 3641 <1> mov cx, 8 3642 <1> xor ax, ax 3643 <1> mov [i.size], ax ; 0 3644 <1> ; clr i.size / zero file size 3645 <1> rep stosw 3646 <1> ; jsr r0,copyz; i.dskp; i.dskp+16. 3647 <1> ; / zero block pointers 3648 <1> call setimod 3649 <1> ; jsr r0,setimod / set i-node modified flag 3650 <1> mov ax, [ii] 3651 <1> ; mov ii,r1 3652 <1> retn 3653 <1> ; rts r0 3654 <1> 3655 <1> ; Retro UNIX 386 v1.1 'imap' code 3656 <1> imap: 3657 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3658 <1> ; 26/04/2013 (Retro UNIX 8086 v1) 3659 <1> ; 3660 <1> ; 'imap' finds the byte in core (superblock) containing 3661 <1> ; allocation bit for an i-node whose number in r1. 3662 <1> ; 3663 <1> ; INPUTS -> 3664 <1> ; r1 - contains an i-number 3665 <1> ; fsp - start of table containing open files 3666 <1> ; 3667 <1> ; OUTPUTS -> 3668 <1> ; r2 - byte address of byte with the allocation bit 3669 <1> ; mq - a mask to locate the bit position. 3670 <1> ; (a 1 is in calculated bit posisiton) 3671 <1> ; 3672 <1> ; ((AX = R1)) input/output 3673 <1> ; ((DL/DX = MQ)) output 3674 <1> ; ((BX = R2)) output 3675 <1> ; 3676 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 3677 <1> ; ((Modified registers: eDX, eCX, eBX, eSI)) 3678 <1> ; 3679 <1> ; / get the byte that has the allocation bit for 3680 <1> ; / the i-number contained in r1 3681 <1> ;mov dx, 1 3682 <1> mov dl, 1 3683 <1> ; mov $1,mq / put 1 in the mq 3684 <1> movzx ebx, ax 3685 <1> ; mov r1,r2 / r2 now has i-number whose byte 3686 <1> ; / in the map we must find 3687 <1> sub bx, 41 3688 <1> ; sub $41.,r2 / r2 has i-41 3689 <1> mov cl, bl 3690 <1> ; mov r2,r3 / r3 has i-41 3691 <1> and cl, 7 3692 <1> ; bic $!7,r3 / r3 has (i-41) mod 8 to get 3693 <1> ; / the bit position 3694 <1> jz short imap1 3695 <1> ;shl dx, cl 3696 <1> shl dl, cl 3697 <1> ; mov r3,lsh / move the 1 over (i-41) mod 8 positions 3698 <1> imap1: ; / to the left to mask the correct bit 3699 <1> shr bx, 3 3700 <1> ; asr r2 3701 <1> ; asr r2 3702 <1> ; asr r2 / r2 has (i-41) base 8 of the byte number 3703 <1> ; / from the start of the map 3704 <1> ; mov r2,-(sp) / put (i-41) base 8 on the stack 3705 <1> mov esi, systm 3706 <1> ; mov $systm,r2 / r2 points to the in-core image of 3707 <1> ; / the super block for drum 3708 <1> ;cmp word [cdev], 0 3709 <1> cmp byte [cdev], 0 3710 <1> ; tst cdev / is the device the disk 3711 <1> jna short imap2 3712 <1> ; beq 1f / yes 3713 <1> add esi, mount - systm 3714 <1> ; add $mount-systm,r2 / for mounted device, 3715 <1> ; / r2 points to 1st word of its super block 3716 <1> imap2: ; 1: 3717 <1> add bx, [esi] ;; add free map size to si 3718 <1> ; add (r2)+,(sp) / get byte address of allocation bit 3719 <1> add bx, 4 3720 <1> add ebx, esi 3721 <1> ; add (sp)+,r2 / ? 3722 <1> ;add ebx, 4 ;; inode map offset in superblock 3723 <1> ;; (2 + free map size + 2) 3724 <1> ; add $2,r2 / ? 3725 <1> ; DL/DX (MQ) has a 1 in the calculated bit position 3726 <1> ; BX (R2) has byte address of the byte with allocation bit 3727 <1> retn 3728 <1> ; rts r0 3729 <1> %endif 3730 <1> 3731 <1> ; Retro UNIX 386 v2.0 'itrunc' code 3732 <1> itrunc: 3733 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 3734 <1> ; 07/06/2020 3735 <1> ; 02/06/2020 3736 <1> ; 26/05/2020 - Retro UNIX 386 v2 3737 <1> ; 3738 <1> ; 'itrunc' truncates a file whose i-number is given in r1 3739 <1> ; to zero length. 3740 <1> ; 07/06/2020 3741 <1> ; 02/06/2020 3742 <1> ; 26/05/2020 - Retro UNIX 386 v2 3743 <1> ; 3744 <1> ; 'itrunc' truncates a file whose i-number is given 3745 <1> ; in ax to zero length. 3746 <1> ; 3747 <1> 3748 <1> ; Reference: 3749 <1> ; Retro UNIX 386 v2 FS installation utility 3750 <1> ; 17/01/2020 - 'UNIXHDCP.ASM', 'itrunc' procedure 3751 <1> 3752 <1> ; * Free all the disk blocks associated 3753 <1> ; * with the specified inode structure. 3754 <1> 3755 <1> ; INPUT: 3756 <1> ; ax = inode number 3757 <1> ; OUTPUT: 3758 <1> ; inode will be modified (file size = 0) 3759 <1> 3760 <1> ; (Modified registers: eax, edx, ecx, ebx, esi, edi, ebp) 3761 <1> 3762 <1> ; 07/06/2020 3763 <1> 3764 <1> ; [cdev] = current logical drive number 3765 <1> ; eax = inode number (for [cdev]) 3766 <1> 3767 00005431 E83AFEFFFF <1> call iget 3768 <1> ; 10/01/2022 3769 <1> ;jc short itrunc_0 ; error code in eax (al) 3770 <1> 3771 <1> ; eax = inode number, [ii] 3772 <1> ; [cdev] = current logical drive number (same with input) 3773 <1> ; [idev] = logical drive number of current inode, [ii] 3774 <1> ; [ii] = current inode ([ii] = ax input, if ax was not zero) 3775 <1> ; [imod] = 0 3776 <1> ; ([imodx] = 0) 3777 <1> 3778 00005436 F605[416B0000]80 <1> test byte [i.flgs+1], 80h ; regular file or directory 3779 0000543D 750F <1> jnz short itrunc_1 3780 <1> 3781 <1> ; 10/01/2022 3782 0000543F C705[186F0000]FF00- <1> mov dword [u.error], ERR_NOT_REGULAR ; 255 3782 00005447 0000 <1> 3783 <1> ; 'not a regular file (or directory) !' error 3784 <1> itrunc_0: 3785 00005449 E95EE7FFFF <1> jmp error 3786 <1> itrunc_1: 3787 0000544E F605[416B0000]10 <1> test byte [i.flgs+1], 10h ; large file (indirect blocks) 3788 00005455 7525 <1> jnz short itrunc_5 ; large file 3789 00005457 BE[4C6B0000] <1> mov esi, i.dskp ; disk address pointer 0 3790 <1> itrunc_2: 3791 0000545C AD <1> lodsd 3792 0000545D 21C0 <1> and eax, eax 3793 0000545F 740C <1> jz short itrunc_3 ; empty ! (no more sectors/blocks) 3794 <1> ; eax = block address to be released 3795 00005461 56 <1> push esi ; * ; 10/01/2022 3796 00005462 E867FDFFFF <1> call free 3797 <1> ; modified registers: ebx, ecx, edx, esi, edi, ebp 3798 <1> ; 10/01/2022 3799 <1> ;jc short itrunc_0 ; error code in eax 3800 00005467 5E <1> pop esi ; * ; 10/01/2022 3801 00005468 31C0 <1> xor eax, eax ; 0 3802 0000546A 8946FC <1> mov [esi-4], eax ; 0 3803 <1> itrunc_3: 3804 0000546D 81FE[746B0000] <1> cmp esi, i.dskp+40 3805 00005473 72E7 <1> jb short itrunc_2 ; next disk address ptr 3806 <1> itrunc_4: 3807 00005475 A3[486B0000] <1> mov [i.size], eax ; 0 3808 <1> ;mov [i.size_h], al ; 0 3809 <1> 3810 <1> ; clear large file flag 3811 <1> ;and byte [i.flgs+1], 0EFh ; 11101111b ; not 10h 3812 <1> 3813 <1> ;call setimod 3814 <1> ;retn 3815 0000547A EB93 <1> jmp setimod 3816 <1> 3817 <1> itrunc_5: 3818 <1> ; free disk blocks by using triple indirect blocks at first 3819 0000547C BE[706B0000] <1> mov esi, i.dskp+36 3820 00005481 8B06 <1> mov eax, [esi] 3821 00005483 09C0 <1> or eax, eax 3822 00005485 740C <1> jz short itrunc_6 3823 <1> 3824 00005487 BA02000000 <1> mov edx, 2 ; Triple indirect sign (level = 2) 3825 0000548C E835000000 <1> call tloop 3826 <1> ; 10/01/2022 3827 <1> ;jc short itrunc_0 3828 <1> ; eax = 0 3829 00005491 8906 <1> mov [esi], eax ; 0 3830 <1> itrunc_6: 3831 <1> ; free disk blocks by using double indirect blocks at second 3832 00005493 BE[6C6B0000] <1> mov esi, i.dskp+32 3833 00005498 8B06 <1> mov eax, [esi] 3834 0000549A 21C0 <1> and eax, eax 3835 0000549C 740C <1> jz short itrunc_7 3836 <1> 3837 0000549E BA01000000 <1> mov edx, 1 ; Double indirect sign (level = 1) 3838 000054A3 E81E000000 <1> call tloop 3839 <1> ; 10/01/2022 3840 <1> ;jc short itrunc_0 3841 <1> ; eax = 0 3842 000054A8 8906 <1> mov [esi], eax ; 0 3843 <1> ;esi = i.dskp+32 3844 <1> itrunc_7: 3845 <1> ; free disk blocks by using single indirect blocks at third 3846 000054AA 83EE04 <1> sub esi, 4 3847 000054AD 8B06 <1> mov eax, [esi] 3848 000054AF 09C0 <1> or eax, eax 3849 000054B1 7409 <1> jz short itrunc_8 3850 <1> 3851 000054B3 29D2 <1> sub edx, edx ; 0 ; Single indirect sign (level = 0) 3852 000054B5 E80C000000 <1> call tloop 3853 <1> ; 10/01/2022 3854 <1> ;jc short itrunc_0 3855 <1> ; eax = 0 3856 000054BA 8906 <1> mov [esi], eax ; 0 3857 <1> itrunc_8: 3858 000054BC 81FE[4C6B0000] <1> cmp esi, i.dskp 3859 000054C2 77E6 <1> ja short itrunc_7 3860 000054C4 EBAF <1> jmp short itrunc_4 3861 <1> 3862 <1> tloop: 3863 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 3864 <1> ; 07/06/2020 3865 <1> ; 03/06/2020 3866 <1> ; 02/06/2020 3867 <1> ; 26/05/2020 - Retro UNIX 386 v2 by Erdogan Tan 3868 <1> ; 3869 <1> ; * Free all the disk blocks associated 3870 <1> ; * with the specified inode structure. 3871 <1> 3872 <1> ; Reference: 3873 <1> ; Retro UNIX 386 v2 FS installation utility 3874 <1> ; 17/01/2020 - 'UNIXHDCP.ASM', 'tloop' procedure 3875 <1> 3876 <1> ; INPUT: 3877 <1> ; 03/06/2020 3878 <1> ; eax = indirect block number/address (logical) 3879 <1> ; edx = level (in dl) 3880 <1> ; (0 = indirect, 1 = double indr. 2 = triple indr.) 3881 <1> ; 3882 <1> ; OUTPUT: 3883 <1> ; indirect blocks will be released 3884 <1> ; 3885 <1> ; Modified registers: eax, ebx, ecx, edx 3886 <1> 3887 <1> ; 03/06/2020 3888 <1> 3889 000054C6 57 <1> push edi ; * 3890 000054C7 56 <1> push esi ; ** 3891 <1> 3892 000054C8 50 <1> push eax ; *** 3893 <1> 3894 000054C9 52 <1> push edx ; **** level 3895 <1> 3896 <1> ; [ii] = current inode number 3897 <1> ; [idev] = logical drive number of current inode, [ii] 3898 <1> ; eax = logical sector/block number 3899 <1> 3900 <1> ; 10/01/2022 3901 <1> ; convert to physical sector/block number/address 3902 000054CA E884FAFFFF <1> call mget_2 3903 <1> 3904 000054CF E84D0A0000 <1> call dskrd ; read disk sector 3905 <1> 3906 <1> ;; ebx = buffer header address 3907 <1> ;; eax = physical sector/block number 3908 <1> ;; [pdn] = phsysical drive (index) number 3909 <1> 3910 <1> ;; Modified registers: eax, edx, ecx, esi, edi 3911 <1> ;; If cf = 1 --> eax = error code (al) 3912 <1> 3913 <1> ; 10/01/2022 3914 <1> ; Return from 'dskrd': (Retro UNIX 386 v1.2) 3915 <1> ; eax = physical block/sector number 3916 <1> ; ebx = buffer data address 3917 <1> ; Modified registers: edx, ecx, ebx, esi, edi, ebp 3918 <1> 3919 000054D4 5A <1> pop edx ; **** ; level in dl 3920 <1> ; 10/01/2022 3921 <1> ;jc short tloop_5 3922 <1> 3923 <1> ;mov esi, [ebx+bufhdr.address] ; buffer address 3924 <1> ; 10/01/2022 3925 000054D5 89DE <1> mov esi, ebx ; buffer data address 3926 <1> 3927 <1> ; 07/06/2020 3928 000054D7 B980000000 <1> mov ecx, 512/4 ; 128 dwords 3929 <1> 3930 000054DC 80FA01 <1> cmp dl, 1 ; - 3931 000054DF 722A <1> jb short tloop_7 3932 000054E1 7407 <1> je short tloop_1 3933 000054E3 BF[5C750000] <1> mov edi, trpi_buf ; triple indirect buffer address 3934 000054E8 EB05 <1> jmp short tloop_2 3935 <1> tloop_1: 3936 000054EA BF[5C730000] <1> mov edi, dbli_buf ; double indirect buffer address 3937 <1> tloop_2: 3938 <1> ; copy disk r/w buffer content to indirect block buffer 3939 <1> ;mov ecx, 512/4 ; 128 dwords 3940 000054EF F3A5 <1> rep movsd 3941 <1> 3942 000054F1 FECA <1> dec dl ; - 3943 <1> ; next indirect block level, 2 -> 1, 1 -> 0 3944 000054F3 89FE <1> mov esi, edi ; (dbli, trpi) indirect buffer + 512 3945 000054F5 B180 <1> mov cl, 128 ; 128 dwords 3946 <1> tloop_3: 3947 000054F7 83EE04 <1> sub esi, 4 ; previous pointer 3948 <1> 3949 000054FA 8B06 <1> mov eax, [esi] 3950 <1> 3951 000054FC 09C0 <1> or eax, eax ; 0 3952 000054FE 7407 <1> jz short tloop_4 3953 <1> 3954 <1> ; 03/06/2020 3955 00005500 51 <1> push ecx ; @ 3956 00005501 E8C0FFFFFF <1> call tloop 3957 00005506 59 <1> pop ecx ; @ 3958 <1> ; 10/01/2022 3959 <1> ;jc short tloop_5 3960 <1> tloop_4: 3961 00005507 E2EE <1> loop tloop_3 3962 <1> 3963 00005509 EB1A <1> jmp short tloop_10 3964 <1> 3965 <1> ; 10/01/2022 3966 <1> ;tloop_5: 3967 <1> ; pop edx ; *** ; discard eax 3968 <1> ; ; error code in eax 3969 <1> ;tloop_6: 3970 <1> ; pop esi ; ** 3971 <1> ; pop edi ; * 3972 <1> ; retn 3973 <1> 3974 <1> ; free blocks in current indirect block 3975 <1> tloop_7: 3976 <1> ;mov ecx, 512/4 ; 128 dwords 3977 0000550B 81C6FC010000 <1> add esi, 508 3978 <1> tloop_8: 3979 00005511 8B06 <1> mov eax, [esi] 3980 00005513 21C0 <1> and eax, eax ; 0 ? 3981 00005515 7409 <1> jz short tloop_9 3982 <1> 3983 00005517 56 <1> push esi ; **** ; 10/01/2022 3984 00005518 51 <1> push ecx ; ***** 3985 00005519 E8B0FCFFFF <1> call free 3986 <1> ; if cf = 0 -> eax = 0 3987 <1> ; if cf = 1 -> eax = error code (in al) 3988 0000551E 59 <1> pop ecx ; ***** 3989 0000551F 5E <1> pop esi ; **** ; 10/01/2022 3990 <1> ; 10/01/2022 3991 <1> ;; 07/06/2020 3992 <1> ;jc short tloop_6 3993 <1> tloop_9: 3994 00005520 83EE04 <1> sub esi, 4 3995 00005523 E2EC <1> loop tloop_8 3996 <1> tloop_10: 3997 00005525 58 <1> pop eax ; *** ; free indirect block's itself 3998 00005526 E8A3FCFFFF <1> call free 3999 <1> ;; if cf = 0 -> eax = 0 4000 <1> ;; if cf = 1 -> eax = error code (in al) 4001 <1> ; 10/01/2022 4002 <1> ; (if we are here, there is not an error, cf=0) 4003 <1> ;jmp short tloop_6 4004 <1> 4005 <1> ; 10/02/2022 4006 0000552B 31C0 <1> xor eax, eax ; 0 4007 0000552D 5E <1> pop esi ; ** 4008 0000552E 5F <1> pop edi ; * 4009 0000552F C3 <1> retn 4010 <1> 4011 <1> ; Retro UNIX 386 v2.0 'imap' code 4012 <1> ; (runix v2 fs inode map) 4013 <1> imap: 4014 <1> ; 10/01/2022 - Retro UNIX 386 v1.2 4015 <1> ; (major modification) 4016 <1> ; 05/11/2021 - temporary (simplified code) 4017 <1> ; 21/08/2021 4018 <1> ; 15/08/2021 4019 <1> ; 14/06/2021 4020 <1> ; 02/05/2021 4021 <1> ; 01/04/2021, 08/04/2021, 24/04/2021 4022 <1> ; 29/03/2021 4023 <1> ; 28/03/2021 - Retro UNIX 386 v2 (beginning) 4024 <1> ; 4025 <1> ; 'imap' finds the byte in inode map containing 4026 <1> ; allocation bit for an i-node whose number in (E)AX 4027 <1> ; 4028 <1> ; (ref: 'UNIXHDCP.ASM', imap', 22/01/2020) 4029 <1> ; 4030 <1> ; ((Retro UNIX 386 v2 'imap' code is mostly different 4031 <1> ; than Retro UNIX 386 v1.1 'imap' code.)) 4032 <1> ; 4033 <1> ; INPUTS -> 4034 <1> ; EAX = inode number 4035 <1> ; 0 = first free inode 4036 <1> ; >0 = requested inode 4037 <1> ; [cdev] = current (logical) drive/device 4038 <1> ; 4039 <1> ; OUTPUTS -> 4040 <1> ; EBX = address of the byte contains allocation bit 4041 <1> ; DX has 1 at calculated bit position 4042 <1> ; ; 05/11/2021 4043 <1> ; EBP = superblock buffer address 4044 <1> ; (EAX = inode number) 4045 <1> ; ; 08/04/2021 4046 <1> ; If cf=1 -> error code in eax (al) 4047 <1> ; 4048 <1> ; Modified registers: ebx, ecx, edx, esi, edi, ebp 4049 <1> 4050 <1> ; 05/11/2021 4051 00005530 803D[856E0000]00 <1> cmp byte [cdev], 0 4052 00005537 7616 <1> jna short imap_0 4053 <1> ; 10/01/2022 4054 00005539 BD[5C710000] <1> mov ebp, mount ; mounted fs superblock buffer 4055 0000553E EB14 <1> jmp short imap_1 4056 <1> 4057 <1> imap_ialloc_err: 4058 <1> ; 10/01/2022 4059 00005540 C705[186F0000]2100- <1> mov dword [u.error], ERR_INO_ALLOC ; 33 4059 00005548 0000 <1> 4060 <1> ; 'inode allocation error !' 4061 0000554A E95DE6FFFF <1> jmp error 4062 <1> 4063 <1> imap_0: 4064 <1> ; 10/01/2022 4065 0000554F BD[546F0000] <1> mov ebp, systm ; root fs superblock buffer 4066 <1> imap_1: 4067 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 4068 <1> imap_x: 4069 <1> ; 05/11/2021 4070 <1> ; 21/08/2021 4071 <1> ; 15/08/2021 (Retro UNIX 386 v2) 4072 <1> ; call from 'maknod2' ; 10/01/2022 4073 <1> ; 4074 <1> ; eax = inode number 4075 <1> ; [cdev] = device number for inode in eax 4076 <1> ; ebp = superblock buffer address 4077 <1> 4078 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 4079 <1> ; 'imap' and 'imap_x' will return with.. 4080 <1> ; ECX = byte offset from inode map buff (imap_x) 4081 <1> ; EBX = byte addr of the byte with allocation bit 4082 <1> ; EDX (DL) has a 1 in the calculated bit position 4083 <1> 4084 <1> ; 02/05/2021 4085 <1> ; convert inode number to first free inode if it is 0 4086 00005554 E83D000000 <1> call imap_3 ; 10/01/2022 4087 00005559 72E5 <1> jc short imap_ialloc_err 4088 <1> ; eax = inode number > 1 (1 = root directory inode) 4089 <1> 4090 0000555B 898584000000 <1> mov [ebp+SB.LastInode], eax 4091 <1> 4092 00005561 50 <1> push eax ; * ; save inode number 4093 <1> 4094 <1> ; convert inode number to inode map sector index 4095 00005562 E847000000 <1> call imap_8 ; 10/01/2022 4096 00005567 50 <1> push eax ; ** ; byte offset in inode map buffer 4097 <1> 4098 <1> ; edx = inode map buffer sector index number (< 16) 4099 <1> ; eax = byte offset in inode map buffer (< 512) 4100 <1> 4101 <1> ; 15/08/2021 4102 00005568 89958C000000 <1> mov [ebp+SB.ImapIndex], edx 4103 0000556E 8B4520 <1> mov eax, [ebp+SB.InodeMapAddr] 4104 00005571 01D0 <1> add eax, edx 4105 00005573 034504 <1> add eax, [ebp+SB.BootSectAddr] 4106 <1> ; eax = physical sector number 4107 <1> ; [cdev] = current device/disk number 4108 <1> 4109 <1> ; 10/01/2022 (Retro UNIX 386 v1.2) 4110 00005576 55 <1> push ebp ; *** 4111 00005577 E8A5090000 <1> call dskrd 4112 0000557C 5D <1> pop ebp ; *** 4113 <1> ; cpu returns here if there is/was not an error in 'dskrd' 4114 <1> ; eax = physical sector number 4115 <1> ; ebx = buffer data address 4116 <1> 4117 <1> ; 10/01/2022 4118 0000557D 8A4C2404 <1> mov cl, [esp+4] ; * ; inode number 4119 <1> ;dec cl 4120 00005581 31D2 <1> xor edx, edx 4121 <1> ;mov dl, 1 4122 00005583 FEC2 <1> inc dl ; dl = 1 4123 <1> ;and ecx, 7 4124 <1> ; 02/05/2021 4125 00005585 FEC9 <1> dec cl 4126 00005587 7405 <1> jz short imap_2 ; 15/08/2021 4127 00005589 80E107 <1> and cl, 7 ; 1 imap bytes is for 8 inodes 4128 0000558C D2E2 <1> shl dl, cl 4129 <1> imap_2: 4130 <1> ; 10/01/2022 4131 <1> ; save physical sector number of imap sector in the SB 4132 0000558E 89457C <1> mov [ebp+SB.ImapBuffer], eax ; ! sector addr ! 4133 <1> ; 4134 00005591 59 <1> pop ecx ; ** ; byte offset in inode map buffer 4135 00005592 01CB <1> add ebx, ecx ; + byte position 4136 00005594 58 <1> pop eax ; * ; inode number 4137 <1> 4138 <1> ; 10/01/2022 4139 <1> ; ECX contains byte offset from inode map buff (imap_x) 4140 <1> ; EDX (DL) has a 1 in the calculated bit position 4141 <1> ; EBX has byte address of the byte with allocation bit 4142 <1> 4143 00005595 C3 <1> retn 4144 <1> 4145 <1> imap_3: 4146 <1> ; 10/01/2022 4147 <1> ; 15/08/2021 4148 <1> ; 02/05/2021 4149 <1> ; 28/03/2021 4150 <1> ; get first free inode number (from superblock) 4151 <1> ; and check inode number against inode count 4152 <1> ; 4153 <1> ; INPUT: 4154 <1> ; eax = 0 -> get first free inode number 4155 <1> ; (eax > 0 -> check inode number) 4156 <1> ; ebp = superblock address ; 15/08/2021 4157 <1> ; OUTPUT: 4158 <1> ; eax = inode number 4159 <1> ; (eax will be 2 when SB.FirstFreeIno is invalid) 4160 <1> ; cf = 1 -> inode allocation error/problem 4161 <1> 4162 00005596 21C0 <1> and eax, eax 4163 00005598 750E <1> jnz short imap_5 4164 <1> 4165 <1> ; get first free inode 4166 <1> ;mov eax, [ebp+SB.FreeInodes] 4167 <1> ;and eax, eax 4168 <1> ;jz short imap_6 4169 <1> ; 10/01/2022 4170 0000559A 394530 <1> cmp [ebp+SB.FreeInodes], eax ; 0 4171 0000559D 760D <1> jna short imap_6 4172 0000559F 8B4534 <1> mov eax, [ebp+SB.FirstFreeIno] ; 1 based inode num 4173 000055A2 40 <1> inc eax 4174 000055A3 7502 <1> jnz short imap_4 ; 0FFFFFFFFh -> 0 4175 <1> ; invalid first free inode value (not initialized) 4176 000055A5 B003 <1> mov al, 3 ; first free inode to be searched + 1 4177 <1> imap_4: 4178 000055A7 48 <1> dec eax 4179 <1> imap_5: 4180 <1> ; 15/08/2021 4181 <1> ; check inode number against inode count of the fs 4182 000055A8 394514 <1> cmp [ebp+SB.InodeCount], eax 4183 000055AB C3 <1> retn ; if cf = 1 --> inode number > inode count 4184 <1> imap_6: 4185 <1> ; 'imap' inode allocation error ! 4186 000055AC F9 <1> stc 4187 <1> imap_7: 4188 000055AD C3 <1> retn 4189 <1> 4190 <1> imap_8: 4191 <1> ; 10/01/2022 4192 <1> ; 15/08/2021 4193 <1> ; 02/05/2021 4194 <1> ; 28/03/2021 4195 <1> ; convert inode count to inode map sector index 4196 <1> ; 4197 <1> ; INPUT: 4198 <1> ; eax = inode number 4199 <1> ; OUTPUT: 4200 <1> ; edx = inode map sector offset/index number 4201 <1> ; eax = byte offset from start of imapbuf 4202 <1> 4203 000055AE 31D2 <1> xor edx, edx 4204 000055B0 48 <1> dec eax ; zero based inode number 4205 000055B1 74FA <1> jz short imap_7 4206 <1> 4207 000055B3 C1E803 <1> shr eax, 3 ; 8 inodes per inode map byte 4208 <1> ; eax = byte offset from start of inode map 4209 000055B6 88E2 <1> mov dl, ah ; ah <= 31 (1Fh) for Retro UNIX 386 v2 4210 000055B8 D0EA <1> shr dl, 1 4211 <1> ; edx = inode map sector offset/index number 4212 <1> ;and eax, 511 4213 000055BA 6625FF01 <1> and ax, 511 4214 <1> ; eax = byte offset from start of imapbuf 4215 000055BE C3 <1> retn 2081 %include 'u6.s' ; 31/05/2015 2082 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2083 <1> ; (re-write kernel for test by using previous version without a major defect) 2084 <1> ; **************************************************************************** 2085 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC 2086 <1> ; Last Modification: 31/12/2021 2087 <1> ; ---------------------------------------------------------------------------- 2088 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2089 <1> ; (v0.1 - Beginning: 11/07/2012) 2090 <1> ; 2091 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2092 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2093 <1> ; 2094 <1> ; 2095 <1> ; 2096 <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s 2097 <1> ; 2098 <1> ; **************************************************************************** 2099 <1> 2100 <1> ; 25/12/2021 2101 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2102 <1> readi: 2103 <1> ; 20/05/2015 2104 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2105 <1> ; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2106 <1> ; 2107 <1> ; Reads from an inode whose number in R1 2108 <1> ; 2109 <1> ; INPUTS -> 2110 <1> ; r1 - inode number 2111 <1> ; u.count - byte count user desires 2112 <1> ; u.base - points to user buffer 2113 <1> ; u.fofp - points to word with current file offset 2114 <1> ; OUTPUTS -> 2115 <1> ; u.count - cleared 2116 <1> ; u.nread - accumulates total bytes passed back 2117 <1> ; 2118 <1> ; ((AX = R1)) input/output 2119 <1> ; (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM) 2120 <1> ; ((Modified registers: edx, ebx, ecx, esi, esi, ebp)) 2121 <1> 2122 000055BF 31D2 <1> xor edx, edx ; 0 2123 000055C1 8915[D06E0000] <1> mov [u.nread], edx ; 0 2124 <1> ; clr u.nread / accumulates number of bytes transmitted 2125 000055C7 668915[106F0000] <1> mov [u.pcount], dx ; 19/05/2015 2126 000055CE 3915[CC6E0000] <1> cmp [u.count], edx ; 0 2127 <1> ; tst u.count / is number of bytes to be read greater than 0 2128 000055D4 7701 <1> ja short readi_1 ; 1f 2129 <1> ; bgt 1f / yes, branch 2130 000055D6 C3 <1> retn 2131 <1> ; rts r0 / no, nothing to read; return to caller 2132 <1> readi_1: ; 1: 2133 <1> ; ; mov r1,-(sp) / save i-number on stack 2134 <1> ;cmp ax, 40 2135 <1> ; ; cmp r1,$40. / want to read a special file 2136 <1> ; ; / (i-nodes 1,...,40 are for special files) 2137 <1> ;ja dskr 2138 <1> ; ; ble 1f / yes, branch 2139 <1> ; ; jmp dskr / no, jmp to dskr; 2140 <1> ; ; / read file with i-node number (r1) 2141 <1> ; ; / starting at byte ((u.fofp)), read in u.count bytes 2142 <1> 2143 <1> ; 28/11/2021 2144 000055D7 F605[166F0000]FF <1> test byte [u.kcall], 0FFh 2145 000055DE 7505 <1> jnz short readi_2 ; 'readi' called by 'namei' 2146 <1> 2147 <1> ; eax = inode number 2148 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 2149 000055E0 E88BFCFFFF <1> call iget 2150 <1> readi_2: 2151 <1> ; 28/11/2021 2152 <1> ; eax = inode number 2153 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 2154 000055E5 E882040000 <1> call is_regular_file 2155 <1> ;jz dskr ; regular file 2156 <1> ; 25/12/2021 2157 000055EA 7505 <1> jnz short readi_5 ; device file 2158 <1> ; regular file 2159 000055EC E9E4000000 <1> jmp dskr 2160 <1> readi_5: 2161 <1> ; (20/05/2015) 2162 000055F1 50 <1> push eax ; because subroutines will jump to 'ret_' 2163 <1> 2164 <1> ; 28/11/2021 2165 <1> ; device file 2166 000055F2 BB[0C560000] <1> mov ebx, readi_4 2167 000055F7 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 2168 000055FA 720E <1> jb short readi_3 2169 000055FC 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 2170 000055FF 7709 <1> ja short readi_3 2171 <1> 2172 <1> ; convert v2 inode number to v1 device inode number 2173 00005601 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 2174 00005603 89C1 <1> mov ecx, eax 2175 00005605 C0E102 <1> shl cl, 2 ; * 4 2176 00005608 01CB <1> add ebx, ecx 2177 <1> readi_3: 2178 0000560A FF23 <1> jmp dword [ebx] 2179 <1> ; jmp *1f-2(r1) 2180 <1> readi_4: ; 1: 2181 0000560C [5C560000] <1> dd null ; 28/11/2021 2182 00005610 [60560000] <1> dd rtty ; tty, AX = 1 (runix) 2183 <1> ;rtty / tty; r1=2 2184 <1> ;rppt / ppt; r1=4 2185 00005614 [B1560000] <1> dd rmem ; mem, AX = 2 (runix) 2186 <1> ;rmem / mem; r1=6 2187 <1> ;rrf0 / rf0 2188 <1> ;rrk0 / rk0 2189 <1> ;rtap / tap0 2190 <1> ;rtap / tap1 2191 <1> ;rtap / tap2 2192 <1> ;rtap / tap3 2193 <1> ;rtap / tap4 2194 <1> ;rtap / tap5 2195 <1> ;rtap / tap6 2196 <1> ;rtap / tap7 2197 00005618 [C75D0000] <1> dd rfd ; fd0, AX = 3 (runix only) 2198 0000561C [C75D0000] <1> dd rfd ; fd1, AX = 4 (runix only) 2199 00005620 [C75D0000] <1> dd rhd ; hd0, AX = 5 (runix only) 2200 00005624 [C75D0000] <1> dd rhd ; hd1, AX = 6 (runix only) 2201 00005628 [C75D0000] <1> dd rhd ; hd2, AX = 7 (runix only) 2202 0000562C [C75D0000] <1> dd rhd ; hd3, AX = 8 (runix only) 2203 00005630 [C6560000] <1> dd rlpr ; lpr, AX = 9 (invalid, write only device !?) 2204 00005634 [AD560000] <1> dd rcvt ; tty0, AX = 10 (runix) 2205 <1> ;rcvt / tty0 2206 00005638 [AD560000] <1> dd rcvt ; tty1, AX = 11 (runix) 2207 <1> ;rcvt / tty1 2208 0000563C [AD560000] <1> dd rcvt ; tty2, AX = 12 (runix) 2209 <1> ;rcvt / tty2 2210 00005640 [AD560000] <1> dd rcvt ; tty3, AX = 13 (runix) 2211 <1> ;rcvt / tty3 2212 00005644 [AD560000] <1> dd rcvt ; tty4, AX = 14 (runix) 2213 <1> ;rcvt / tty4 2214 00005648 [AD560000] <1> dd rcvt ; tty5, AX = 15 (runix) 2215 <1> ;rcvt / tty5 2216 0000564C [AD560000] <1> dd rcvt ; tty6, AX = 16 (runix) 2217 <1> ;rcvt / tty6 2218 00005650 [AD560000] <1> dd rcvt ; tty7, AX = 17 (runix) 2219 <1> ;rcvt / tty7 2220 00005654 [AD560000] <1> dd rcvt ; COM1, AX = 18 (runix only) 2221 <1> ;rcrd / crd 2222 00005658 [AD560000] <1> dd rcvt ; COM2, AX = 19 (runix only) 2223 <1> 2224 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2225 <1> null: 2226 0000565C 31C0 <1> xor eax, eax 2227 0000565E 58 <1> pop eax 2228 0000565F C3 <1> retn 2229 <1> 2230 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 2231 <1> rtty: ; / read from console tty 2232 <1> ; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1) 2233 <1> ; (Only 1 byte is read, by ignoring byte count!) 2234 <1> ; WHAT FOR: Every character from Keyboard input 2235 <1> ; must be written immediate on video page (screen) 2236 <1> ; when it is required. 2237 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2238 <1> ; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1) 2239 <1> ; 2240 <1> ; Console tty buffer is PC keyboard buffer 2241 <1> ; and keyboard-keystroke handling is different than original 2242 <1> ; unix (PDP-11) here. TTY/Keyboard procedures here are changed 2243 <1> ; according to IBM PC compatible ROM BIOS keyboard functions. 2244 <1> ; 2245 <1> ; 06/12/2013 2246 00005660 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 2247 00005667 8A83[DF6B0000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2248 <1> rttys: 2249 <1> ; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of 2250 <1> ; / of the control and status block 2251 <1> ; tst 2(r5) / for the console tty; this word points to the console 2252 <1> ; / tty buffer 2253 <1> ; 28/07/2013 2254 0000566D A2[D96E0000] <1> mov [u.ttyn], al 2255 <1> ; 13/01/2014 2256 00005672 FEC0 <1> inc al 2257 00005674 A2[DA6E0000] <1> mov [u.ttyp], al ; tty number + 1 2258 <1> rtty_nc: ; 01/02/2014 2259 <1> ; 29/09/2013 2260 00005679 B90A000000 <1> mov ecx, 10 2261 <1> rtty_1: ; 01/02/2014 2262 <1> ;push cx ; 29/09/2013 2263 <1> ; 11/12/2021 2264 0000567E 51 <1> push ecx 2265 <1> ; byte [u.ttyn] = tty number (0 to 9) 2266 0000567F B001 <1> mov al, 1 2267 00005681 E8A00B0000 <1> call getc 2268 <1> ;pop cx ; 29/09/2013 2269 <1> ; 11/12/2021 2270 00005686 59 <1> pop ecx 2271 00005687 7516 <1> jnz short rtty_2 2272 <1> ; bne 1f / 2nd word of console tty buffer contains number 2273 <1> ; / of chars. Is this number non-zero? 2274 00005689 E20D <1> loop rtty_idle ; 01/02/2014 2275 <1> ; 05/10/2013 2276 0000568B 8A25[D96E0000] <1> mov ah, [u.ttyn] 2277 <1> ; 29/09/2013 2278 00005691 E8ECF7FFFF <1> call sleep 2279 <1> ; jsr r0,canon; ttych / if 0, call 'canon' to get a line 2280 <1> ; / (120 chars.) 2281 <1> ; byte [u.ttyn] = tty number (0 to 9) 2282 00005696 EBE1 <1> jmp short rtty_nc ; 01/02/2014 2283 <1> 2284 <1> rtty_idle: 2285 <1> ; 29/07/2013 2286 00005698 E852F7FFFF <1> call idle 2287 0000569D EBDF <1> jmp short rtty_1 ; 01/02/2014 2288 <1> ;1: 2289 <1> ; tst 2(r5) / is the number of characters zero 2290 <1> ; beq ret1 / yes, return to caller via 'ret1' 2291 <1> ; movb *4(r5),r1 / no, put character in r1 2292 <1> ; inc 4(r5) / 3rd word of console tty buffer points to byte which 2293 <1> ; / contains the next char. 2294 <1> ; dec 2(r5) / decrement the character count 2295 <1> rtty_2: 2296 0000569F 30C0 <1> xor al, al 2297 000056A1 E8800B0000 <1> call getc 2298 000056A6 E891000000 <1> call passc 2299 <1> ; jsr r0,passc / move the character to core (user) 2300 <1> ;; 17/10/2015 - 16/07/2015 2301 <1> ; 19/06/2014 2302 <1> ;;jnz short rtty_nc 2303 000056AB 58 <1> pop eax ; (20/05/2015) 2304 000056AC C3 <1> retn 2305 <1> ;ret1: 2306 <1> ; jmp ret / return to caller via 'ret' 2307 <1> 2308 <1> rcvt: ; < receive/read character from tty > 2309 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2310 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2311 <1> ; 2312 <1> ; Retro UNIX 8086 v1 modification ! 2313 <1> ; 2314 <1> ; In original UNIX v1, 'rcvt' routine 2315 <1> ; (exactly different than this one) 2316 <1> ; was in 'u9.s' file. 2317 <1> ; 2318 000056AD 2C0A <1> sub al, 10 2319 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 2320 <1> ; 16/07/2013 2321 <1> ; 21/05/2013 2322 000056AF EBBC <1> jmp short rttys 2323 <1> 2324 <1> ;rppt: / read paper tape 2325 <1> ; jsr r0,pptic / gets next character in clist for ppt input and 2326 <1> ; / places 2327 <1> ; br ret / it in r1; if there 1s no problem with reader, it 2328 <1> ; / also enables read bit in prs 2329 <1> ; jsr r0,passc / place character in users buffer area 2330 <1> ; br rppt 2331 <1> 2332 <1> rmem: ; / transfer characters from memory to a user area of core 2333 <1> ; 17/10/2015 2334 <1> ; 11/06/2015 2335 <1> ; 24/05/2015 2336 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2337 <1> ; 2338 000056B1 8B35[B86E0000] <1> mov esi, [u.fofp] 2339 <1> rmem_1: 2340 000056B7 8B1E <1> mov ebx, [esi] 2341 <1> ; mov *u.fofp,r1 / save file offset which points to the char 2342 <1> ; / to be transferred to user 2343 000056B9 FF06 <1> inc dword [esi] ; 17/10/2015 2344 <1> ; inc *u.fofp / increment file offset to point to 'next' 2345 <1> ; / char in memory file 2346 000056BB 8A03 <1> mov al, [ebx] 2347 <1> ; movb (r1),r1 / get character from memory file, 2348 <1> ; / put it in r1 2349 000056BD E87A000000 <1> call passc ; jsr r0,passc / move this character to 2350 <1> ; / the next byte of the users core area 2351 <1> ; br rmem / continue 2352 000056C2 75F3 <1> jnz short rmem_1 2353 <1> ret_: 2354 000056C4 58 <1> pop eax ; 09/06/2015 2355 000056C5 C3 <1> retn 2356 <1> 2357 <1> rlpr: 2358 <1> ;1: 2359 <1> ;rcrd: 2360 000056C6 C705[186F0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 2360 000056CE 0000 <1> 2361 000056D0 E9D7E4FFFF <1> jmp error 2362 <1> ;jmp error / see 'error' routine 2363 <1> 2364 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2365 <1> dskr: 2366 <1> ; 12/10/2015 2367 <1> ; 21/08/2015 2368 <1> ; 25/07/2015 2369 <1> ; 10/07/2015 2370 <1> ; 16/06/2015 2371 <1> ; 31/05/2015 2372 <1> ; 24/05/2015 (Retro UNIX 386 v1 - Beginning) 2373 <1> ; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2374 <1> dskr_0: 2375 000056D5 50 <1> push eax 2376 <1> ; mov (sp),r1 / i-number in r1 2377 <1> ; AX = i-number 2378 000056D6 E895FBFFFF <1> call iget 2379 <1> ; jsr r0,iget / get i-node (r1) into i-node section of core 2380 <1> ;movzx edx, word [i.size] ; 16/06/2015 2381 <1> ; ; mov i.size,r2 / file size in bytes in r2 2382 <1> ; 28/11/2021 2383 000056DB 8B15[486B0000] <1> mov edx, [i.size] ; 32 bit file size (runix v2 inode) 2384 <1> ; 2385 000056E1 8B1D[B86E0000] <1> mov ebx, [u.fofp] 2386 000056E7 2B13 <1> sub edx, [ebx] 2387 <1> ; sub *u.fofp,r2 / subtract file offset 2388 <1> ; 12/10/2015 2389 <1> ; jna short ret_ 2390 <1> ; blos ret 2391 000056E9 7709 <1> ja short dskr_1 2392 <1> ; 2393 <1> dskr_retn: ; 12/10/2015 2394 000056EB 58 <1> pop eax 2395 000056EC C605[166F0000]00 <1> mov byte [u.kcall], 0 2396 000056F3 C3 <1> retn 2397 <1> dskr_1: 2398 000056F4 3B15[CC6E0000] <1> cmp edx, [u.count] 2399 <1> ; cmp r2,u.count / are enough bytes left in file 2400 <1> ; / to carry out read 2401 000056FA 7306 <1> jnb short dskr_2 2402 <1> ; bhis 1f 2403 000056FC 8915[CC6E0000] <1> mov [u.count], edx 2404 <1> ; mov r2,u.count / no, just read to end of file 2405 <1> dskr_2: ; 1: 2406 <1> ; (E)AX = i-number ; 28/11/2021 (32 bit inode number) 2407 <1> ;call mget 2408 <1> ; jsr r0,mget / returns physical block number of block 2409 <1> ; / in file where offset points 2410 <1> ; 28/11/2021 2411 00005702 E804F8FFFF <1> call mget_r 2412 <1> 2413 <1> ; eax = physical block number 2414 <1> ; [cdev] = current device number 2415 00005707 E815080000 <1> call dskrd 2416 <1> ; jsr r0,dskrd / read in block, r5 points to 2417 <1> ; / 1st word of data in buffer 2418 <1> ; 09/06/2015 2419 0000570C 803D[166F0000]00 <1> cmp byte [u.kcall], 0 ; the caller is 'namei' sign (=1) 2420 00005713 770F <1> ja short dskr_4 ; zf=0 -> the caller is 'namei' 2421 00005715 66833D[106F0000]00 <1> cmp word [u.pcount], 0 2422 0000571D 7705 <1> ja short dskr_4 2423 <1> dskr_3: 2424 <1> ; [u.base] = virtual address to transfer (as destination address) 2425 0000571F E853000000 <1> call trans_addr_w ; translate virtual address to physical (w) 2426 <1> dskr_4: 2427 <1> ; EBX (r5) = system (I/O) buffer address -physical- 2428 00005724 E8C2020000 <1> call sioreg 2429 <1> ; jsr r0,sioreg 2430 00005729 87F7 <1> xchg esi, edi 2431 <1> ; edi = file (user data) offset 2432 <1> ; edi = sector (I/O) buffer offset 2433 <1> ; ecx = byte count 2434 0000572B F3A4 <1> rep movsb 2435 <1> ; movb (r2)+,(r1)+ / move data from buffer into working core 2436 <1> ; / starting at u.base 2437 <1> ; dec r3 2438 <1> ; bne 2b / branch until proper number of bytes are transferred 2439 <1> ; 25/07/2015 2440 <1> ; eax = remain bytes in buffer 2441 <1> ; (check if remain bytes in the buffer > [u.pcount]) 2442 0000572D 09C0 <1> or eax, eax 2443 0000572F 75EE <1> jnz short dskr_3 ; (page end before system buffer end!) 2444 <1> ; 03/08/2013 2445 <1> ;pop eax 2446 00005731 390D[CC6E0000] <1> cmp [u.count], ecx ; 0 2447 <1> ; tst u.count / all bytes read off disk 2448 <1> ; bne dskr 2449 <1> ; br ret 2450 <1> ;ja short dskr_0 2451 <1> ;mov [u.kcall], cl ; 0 ; 09/06/2015 2452 <1> ;retn 2453 <1> ; 12/10/2015 2454 00005737 76B2 <1> jna short dskr_retn 2455 00005739 58 <1> pop eax ; (i-node number) 2456 0000573A EB99 <1> jmp short dskr_0 2457 <1> 2458 <1> passc: 2459 <1> ; 18/10/2015 2460 <1> ; 10/07/2015 2461 <1> ; 01/07/2015 2462 <1> ; 08/06/2015 2463 <1> ; 04/06/2015 2464 <1> ; 20/05/2015 2465 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2466 <1> ; 2467 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 2468 <1> ; to physical address 2469 0000573C 66833D[106F0000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 2470 <1> ; 1-4095 --> use previous physical base address 2471 <1> ; in [u.pbase] 2472 00005744 7705 <1> ja short passc_3 2473 <1> ; 08/06/2015 - 10/07/2015 2474 00005746 E82C000000 <1> call trans_addr_w 2475 <1> passc_3: 2476 <1> ; 19/05/2015 2477 0000574B 66FF0D[106F0000] <1> dec word [u.pcount] 2478 <1> ; 2479 00005752 8B1D[0C6F0000] <1> mov ebx, [u.pbase] 2480 00005758 8803 <1> mov [ebx], al 2481 <1> ; movb r1,*u.base / move a character to the next byte of the 2482 <1> ; / users buffer 2483 0000575A FF05[C86E0000] <1> inc dword [u.base] 2484 <1> ; inc u.base / increment the pointer to point to 2485 <1> ; / the next byte in users buffer 2486 00005760 FF05[0C6F0000] <1> inc dword [u.pbase] ; 04/06/2015 2487 00005766 FF05[D06E0000] <1> inc dword [u.nread] 2488 <1> ; inc u.nread / increment the number of bytes read 2489 0000576C FF0D[CC6E0000] <1> dec dword [u.count] 2490 <1> ; dec u.count / decrement the number of bytes to be read 2491 <1> ; bne 1f / any more bytes to read? ; yes, branch 2492 00005772 C3 <1> retn 2493 <1> ; mov (sp)+,r0 / no, do a non-local return to the caller of 2494 <1> ; / 'readi' by: 2495 <1> ;/ (1) pop the return address off the stack into r0 2496 <1> ; mov (sp)+,r1 / (2) pop the i-number off the stack into r1 2497 <1> ;1: 2498 <1> ; clr *$ps / clear processor status 2499 <1> ; rts r0 / return to address currently on top of stack 2500 <1> 2501 <1> trans_addr_r: 2502 <1> ; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2) 2503 <1> ; -'add_to_swap_queue' call is diasbled as temporary- 2504 <1> ; Translate virtual address to physical address 2505 <1> ; for reading from user's memory space 2506 <1> ; (Retro UNIX 386 v1 feature only !) 2507 <1> ; 18/10/2015 2508 <1> ; 10/07/2015 2509 <1> ; 09/06/2015 2510 <1> ; 08/06/2015 2511 <1> ; 04/06/2015 2512 <1> ; 2513 <1> ; 18/10/2015 2514 00005773 31D2 <1> xor edx, edx ; 0 (read access sign) 2515 00005775 EB04 <1> jmp short trans_addr_rw 2516 <1> 2517 <1> ;push eax 2518 <1> ;push ebx 2519 <1> ;mov ebx, [u.base] 2520 <1> ;call get_physical_addr ; get physical address 2521 <1> ;;jnc short cpass_0 2522 <1> ;jnc short passc_1 2523 <1> ;mov [u.error], eax 2524 <1> ;;pop ebx 2525 <1> ;;pop eax 2526 <1> ;jmp error 2527 <1> ;cpass_0: 2528 <1> ; 18/10/2015 2529 <1> ; 20/05/2015 2530 <1> ;mov [u.pbase], eax ; physical address 2531 <1> ;mov [u.pcount], cx ; remain byte count in page (1-4096) 2532 <1> ;pop ebx 2533 <1> ;pop eax 2534 <1> ;retn ; 08/06/2015 2535 <1> 2536 <1> trans_addr_w: 2537 <1> ; 31/12/2021 2538 <1> ; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2) 2539 <1> ; -'add_to_swap_queue' call is disabled as temporary- 2540 <1> ; Translate virtual address to physical address 2541 <1> ; for writing to user's memory space 2542 <1> ; (Retro UNIX 386 v1 feature only !) 2543 <1> ; 18/10/2015 2544 <1> ; 29/07/2015 2545 <1> ; 10/07/2015 2546 <1> ; 09/06/2015 2547 <1> ; 08/06/2015 2548 <1> ; 04/06/2015 (passc) 2549 <1> ; 2550 <1> ; 18/10/2015 2551 00005777 29D2 <1> sub edx, edx 2552 00005779 FEC2 <1> inc dl ; 1 (write access sign) 2553 <1> trans_addr_rw: 2554 0000577B 50 <1> push eax 2555 0000577C 53 <1> push ebx 2556 <1> ; 18/10/2015 2557 0000577D 52 <1> push edx ; r/w sign (in DL) 2558 <1> ; 2559 0000577E 8B1D[C86E0000] <1> mov ebx, [u.base] 2560 00005784 E8CBDAFFFF <1> call get_physical_addr ; get physical address 2561 00005789 730A <1> jnc short passc_0 2562 0000578B A3[186F0000] <1> mov [u.error], eax 2563 <1> ;pop edx 2564 <1> ;pop ebx 2565 <1> ;pop eax 2566 00005790 E917E4FFFF <1> jmp error 2567 <1> passc_0: 2568 00005795 F6C202 <1> test dl, PTE_A_WRITE ; writable page ; 18/10/2015 2569 00005798 5A <1> pop edx ; 18/10/2015 2570 00005799 7517 <1> jnz short passc_1 2571 <1> ; 18/10/2015 2572 0000579B 20D2 <1> and dl, dl 2573 0000579D 7413 <1> jz short passc_1 2574 <1> ; 20/05/2015 2575 <1> ; read only (duplicated) page -must be copied to a new page- 2576 <1> ; EBX = linear address 2577 0000579F 51 <1> push ecx 2578 <1> ; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix) 2579 000057A0 53 <1> push ebx ;* ; BugFix ; 31/12/2021 2580 000057A1 E81DDAFFFF <1> call copy_page 2581 000057A6 5B <1> pop ebx ;* ; BugFix ; 31/12/2021 2582 000057A7 59 <1> pop ecx 2583 000057A8 7217 <1> jc short passc_2 2584 <1> ; 30/11/2021 2585 <1> ;push eax ; physical address of the new/allocated page 2586 <1> ;call add_to_swap_queue 2587 <1> ;pop eax 2588 <1> ; 18/10/2015 2589 000057AA 81E3FF0F0000 <1> and ebx, PAGE_OFF ; 0FFFh 2590 <1> ;mov ecx, PAGE_SIZE 2591 <1> ;sub ecx, ebx 2592 000057B0 01D8 <1> add eax, ebx 2593 <1> passc_1: 2594 <1> ; 18/10/2015 2595 <1> ; 20/05/2015 2596 000057B2 A3[0C6F0000] <1> mov [u.pbase], eax ; physical address 2597 000057B7 66890D[106F0000] <1> mov [u.pcount], cx ; remain byte count in page (1-4096) 2598 000057BE 5B <1> pop ebx 2599 000057BF 58 <1> pop eax 2600 000057C0 C3 <1> retn ; 08/06/2015 2601 <1> passc_2: 2602 000057C1 C705[186F0000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error 2602 000057C9 0000 <1> 2603 <1> ;pop ebx 2604 <1> ;pop eax 2605 000057CB E9DCE3FFFF <1> jmp error 2606 <1> 2607 <1> ; 25/12/2021 2608 <1> ; 11/12/2021 2609 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2610 <1> writei: 2611 <1> ; 20/05/2015 2612 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2613 <1> ; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2614 <1> ; 2615 <1> ; Write data to file with inode number in R1 2616 <1> ; 2617 <1> ; INPUTS -> 2618 <1> ; r1 - inode number 2619 <1> ; u.count - byte count to be written 2620 <1> ; u.base - points to user buffer 2621 <1> ; u.fofp - points to word with current file offset 2622 <1> ; OUTPUTS -> 2623 <1> ; u.count - cleared 2624 <1> ; u.nread - accumulates total bytes passed back 2625 <1> ; ((AX = R1)) 2626 <1> ; (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM) 2627 <1> ; ((Modified registers: DX, BX, CX, SI, DI, BP)) 2628 <1> 2629 000057D0 31C9 <1> xor ecx, ecx 2630 000057D2 890D[D06E0000] <1> mov [u.nread], ecx ; 0 2631 <1> ; clr u.nread / clear the number of bytes transmitted during 2632 <1> ; / read or write calls 2633 000057D8 66890D[106F0000] <1> mov [u.pcount], cx ; 19/05/2015 2634 000057DF 390D[CC6E0000] <1> cmp [u.count], ecx 2635 <1> ; ; tst u.count / test the byte count specified by the user 2636 000057E5 7701 <1> ja short writei_1 ; 1f 2637 <1> ; bgt 1f / any bytes to output; yes, branch 2638 000057E7 C3 <1> retn 2639 <1> ; ; rts r0 / no, return - no writing to do 2640 <1> writei_1: ;1: 2641 <1> ; ; mov r1 ,-(sp) / save the i-node number on the stack 2642 <1> ;cmp ax, 40 2643 <1> ; ; cmp r1,$40. 2644 <1> ; ; / does the i-node number indicate a special file? 2645 <1> ;ja dskw 2646 <1> ; ; bgt dskw / no, branch to standard file output 2647 <1> 2648 <1> ; 28/11/2021 2649 000057E8 F605[166F0000]FF <1> test byte [u.kcall], 0FFh 2650 000057EF 7505 <1> jnz short writei_2 ; 'writei' called by 'mkdir' 2651 <1> 2652 <1> ; eax = inode number 2653 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 2654 000057F1 E87AFAFFFF <1> call iget 2655 <1> writei_2: 2656 <1> ; 28/11/2021 2657 <1> ; eax = inode number 2658 <1> ; [cdev] = device number (0 = root fs, 1 = mounted fs) 2659 000057F6 E871020000 <1> call is_regular_file 2660 <1> ;jz dskw ; regular file 2661 <1> ; 25/12/2021 2662 000057FB 7505 <1> jnz short writei_5 ; device file 2663 <1> ; regular file 2664 000057FD E9FD000000 <1> jmp dskw 2665 <1> writei_5: 2666 <1> ; (20/05/2015) 2667 00005802 50 <1> push eax ; because subroutines will jump to 'ret_' 2668 <1> 2669 <1> ; 28/11/2021 2670 <1> ; device file 2671 00005803 BB[1D580000] <1> mov ebx, writei_4 2672 00005808 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 2673 0000580B 720E <1> jb short writei_3 2674 0000580D 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 2675 00005810 7709 <1> ja short writei_3 ; 11/12/2021 2676 <1> 2677 <1> ; convert v2 inode number to v1 device inode number 2678 00005812 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 2679 00005814 89C1 <1> mov ecx, eax 2680 00005816 C0E102 <1> shl cl, 2 ; * 4 2681 00005819 01CB <1> add ebx, ecx 2682 <1> writei_3: 2683 0000581B FF23 <1> jmp dword [ebx] 2684 <1> ; jmp *1f-2(r1) 2685 <1> ; / jump table and jump to the appropriate routine 2686 <1> writei_4: ;1: 2687 0000581D [5C560000] <1> dd null ; 28/11/2021 2688 00005821 [6D580000] <1> dd wtty ; tty, AX = 1 (runix) 2689 <1> ;wtty / tty; r1=2 2690 <1> ;wppt / ppt; r1=4 2691 00005825 [CF580000] <1> dd wmem ; mem, AX = 2 (runix) 2692 <1> ;wmem / mem; r1=6 2693 <1> ;wrf0 / rf0 2694 <1> ;wrk0 / rk0 2695 <1> ;wtap / tap0 2696 <1> ;wtap / tap1 2697 <1> ;wtap / tap2 2698 <1> ;wtap / tap3 2699 <1> ;wtap / tap4 2700 <1> ;wtap / tap5 2701 <1> ;wtap / tap6 2702 <1> ;wtap / tap7 2703 00005829 [495E0000] <1> dd wfd ; fd0, AX = 3 (runix only) 2704 0000582D [495E0000] <1> dd wfd ; fd1, AX = 4 (runix only) 2705 00005831 [495E0000] <1> dd whd ; hd0, AX = 5 (runix only) 2706 00005835 [495E0000] <1> dd whd ; hd1, AX = 6 (runix only) 2707 00005839 [495E0000] <1> dd whd ; hd2, AX = 7 (runix only) 2708 0000583D [495E0000] <1> dd whd ; hd3, AX = 8 (runix only) 2709 00005841 [C0580000] <1> dd wlpr ; lpr, AX = 9 (runix) 2710 00005845 [BA580000] <1> dd xmtt ; tty0, AX = 10 (runix) 2711 <1> ;xmtt / tty0 2712 00005849 [BA580000] <1> dd xmtt ; tty1, AX = 11 (runix) 2713 <1> ;xmtt / tty1 2714 0000584D [BA580000] <1> dd xmtt ; tty2, AX = 12 (runix) 2715 <1> ;xmtt / tty2 2716 00005851 [BA580000] <1> dd xmtt ; tty3, AX = 13 (runix) 2717 <1> ;xmtt / tty3 2718 00005855 [BA580000] <1> dd xmtt ; tty4, AX = 14 (runix) 2719 <1> ;xmtt / tty4 2720 00005859 [BA580000] <1> dd xmtt ; tty5, AX = 15 (runix) 2721 <1> ;xmtt / tty5 2722 0000585D [BA580000] <1> dd xmtt ; tty6, AX = 16 (runix) 2723 <1> ;xmtt / tty6 2724 00005861 [BA580000] <1> dd xmtt ; tty7, AX = 17 (runix) 2725 <1> ;xmtt / tty7 2726 00005865 [BA580000] <1> dd xmtt ; COM1, AX = 18 (runix only) 2727 <1> ; / wlpr / lpr 2728 00005869 [BA580000] <1> dd xmtt ; COM2, AX = 19 (runix only) 2729 <1> 2730 <1> ; ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2731 <1> ;null: 2732 <1> ; xor eax, eax 2733 <1> ; pop eax 2734 <1> ; retn 2735 <1> 2736 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 2737 <1> wtty: ; write to console tty (write to screen) 2738 <1> ; 18/11/2015 2739 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2740 <1> ; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1) 2741 <1> ; 2742 <1> ; Console tty output is on current video page 2743 <1> ; Console tty character output procedure is changed here 2744 <1> ; acconding to IBM PC compatible ROM BIOS video (text mode) functions. 2745 <1> ; 2746 0000586D 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 2747 00005874 8AA3[DF6B0000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 2748 0000587A 88E0 <1> mov al, ah ; 07/07/2014 2749 <1> wttys: 2750 <1> ; 10/10/2013 2751 0000587C 8825[D96E0000] <1> mov [u.ttyn], ah 2752 <1> ; 13/01/2014 2753 00005882 FEC0 <1> inc al 2754 00005884 A2[DB6E0000] <1> mov [u.ttyp+1], al ; tty number + 1 2755 <1> wtty_nc: ; 15/05/2013 2756 <1> ; AH = [u.ttyn] = tty number ; 28/07/2013 2757 00005889 E8FD000000 <1> call cpass 2758 <1> ; jsr r0,cpass / get next character from user buffer area; if 2759 <1> ; / none go to return address in syswrite 2760 <1> ; tst r1 / is character = null 2761 <1> ; beq wtty / yes, get next character 2762 <1> ; 10/10/2013 2763 0000588E 7428 <1> jz short wret 2764 <1> ;1 : 2765 <1> ;mov $240,*$ps / no, set processor priority to five 2766 <1> ;cmpb cc+1,$20. / is character count for console tty greater 2767 <1> ; / than 20 2768 <1> ;bhis 2f / yes; branch to put process to sleep 2769 <1> ; 27/06/2014 2770 <1> wtty_1: 2771 <1> ; AH = tty number 2772 <1> ; AL = ASCII code of the character 2773 <1> ; 15/04/2014 2774 <1> ;push ax 2775 <1> ; 11/12/2021 2776 00005890 50 <1> push eax 2777 00005891 E8FE090000 <1> call putc ; 14/05/2013 2778 00005896 731D <1> jnc short wtty_2 2779 <1> ; 18/11/2015 2780 00005898 E852F5FFFF <1> call idle 2781 <1> ;mov ax, [esp] 2782 <1> ; 11/12/2021 2783 0000589D 8B0424 <1> mov eax, [esp] 2784 000058A0 E8EF090000 <1> call putc 2785 000058A5 730E <1> jnc short wtty_2 2786 <1> ; 02/06/2014 2787 000058A7 8A25[D96E0000] <1> mov ah, [u.ttyn] 2788 000058AD E8D0F5FFFF <1> call sleep 2789 <1> ;pop ax 2790 <1> ; 11/12/2021 2791 000058B2 58 <1> pop eax 2792 000058B3 EBDB <1> jmp short wtty_1 2793 <1> ; jc error ; 15/05/2013 (COM1 or COM2 serial port error) 2794 <1> ; jsr r0,putc; 1 / find place in freelist to assign to 2795 <1> ; / console tty and 2796 <1> ; br 2f / place character in list; if none available 2797 <1> ; / branch to put process to sleep 2798 <1> ; jsr r0,startty / attempt to output character on tty 2799 <1> wtty_2: 2800 <1> ; 15/04/2014 2801 <1> ;pop ax 2802 <1> ; 11/12/2021 2803 000058B5 58 <1> pop eax 2804 000058B6 EBD1 <1> jmp short wtty_nc 2805 <1> ; br wtty 2806 <1> wret: ; 10/10/2013 (20/05/2015) 2807 000058B8 58 <1> pop eax 2808 000058B9 C3 <1> retn 2809 <1> ;2: 2810 <1> ;mov r1,-(sp) / place character on stack 2811 <1> ;jsr r0,sleep; 1 / put process to sleep 2812 <1> ;mov (sp)+,r1 / remove character from stack 2813 <1> ;br 1b / try again to place character in clist and output 2814 <1> 2815 <1> xmtt: ; < send/write character to tty > 2816 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2817 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2818 <1> ; 2819 <1> ; Retro UNIX 8086 v1 modification ! 2820 <1> ; 2821 <1> ; In original UNIX v1, 'xmtt' routine 2822 <1> ; (exactly different than this one) 2823 <1> ; was in 'u9.s' file. 2824 <1> ; 2825 000058BA 2C0A <1> sub al, 10 2826 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 2827 <1> ; 10/10/2013 2828 000058BC 88C4 <1> mov ah, al 2829 <1> ; 28/07/2013 2830 000058BE EBBC <1> jmp short wttys 2831 <1> 2832 <1> ;wppt: 2833 <1> ; jsr r0,cpass / get next character from user buffer area, 2834 <1> ; / if none return to writei's calling routine 2835 <1> ; jsr r0,pptoc / output character on ppt 2836 <1> ; br wppt 2837 <1> wlpr: 2838 000058C0 C705[186F0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 2838 000058C8 0000 <1> 2839 000058CA E9DDE2FFFF <1> jmp error ; ... Printing procedure will be located here ... 2840 <1> ;/ jsr r0,cpass 2841 <1> ;/ cmp r0,$'a 2842 <1> ;/ blo 1f 2843 <1> ;/ cmp r1,$'z 2844 <1> ;/ bhi 1f 2845 <1> ;/ sub $40,r1 2846 <1> ;/1: 2847 <1> ;/ jsr r0,lptoc 2848 <1> ;/ br wlpr 2849 <1> ; br rmem / continue 2850 <1> 2851 <1> wmem: ; / transfer characters from a user area of core to memory file 2852 <1> ; 17/10/2015 2853 <1> ; 11/06/2015 2854 <1> ; 24/05/2015 2855 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2856 <1> ; 2857 000058CF 813D[0F070000]- <1> cmp dword [x_timer], clock ; multi tasking clock/timer 2857 000058D5 [124E0000] <1> 2858 000058D9 7415 <1> je short wmem_acc_err 2859 <1> ; 2860 000058DB 8B35[B86E0000] <1> mov esi, [u.fofp] 2861 <1> wmem_1: 2862 000058E1 E8A5000000 <1> call cpass 2863 <1> ; jsr r0,cpass / get next character from users area of 2864 <1> ; / core and put it in r1 2865 <1> ; mov r1,-(sp) / put character on the stack 2866 <1> ; 20/09/2013 2867 000058E6 74D0 <1> jz short wret ; wmem_2 2868 000058E8 8B1E <1> mov ebx, [esi] 2869 <1> ; mov *u.fofp,r1 / save file offset in r1 2870 000058EA FF06 <1> inc dword [esi] ; 17/10/2015 2871 <1> ; inc *u.fofp / increment file offset to point to next 2872 <1> ; / available location in file 2873 000058EC 8803 <1> mov [ebx], al 2874 <1> ; movb (sp)+,(r1) / pop char off stack, put in memory loc 2875 <1> ; / assigned to it 2876 000058EE EBF1 <1> jmp short wmem_1 2877 <1> ; br wmem / continue 2878 <1> ;1: 2879 <1> ;jmp error / ? 2880 <1> ;wmem_2: 2881 <1> ; ; 20/09/2013 2882 <1> ; pop ax 2883 <1> ; retn 2884 <1> 2885 <1> wmem_acc_err: 2886 000058F0 C705[186F0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2886 000058F8 0000 <1> 2887 000058FA E9ADE2FFFF <1> jmp error 2888 <1> 2889 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 2890 <1> 2891 <1> dskw: ; / write routine for non-special files 2892 <1> ; 2893 <1> ; 28/11/2021 2894 <1> ; 25/07/2015 2895 <1> ; 16/06/2015 2896 <1> ; 09/06/2015 2897 <1> ; 31/05/2015 (Retro UNIX 386 v1 - Beginning) 2898 <1> ; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1) 2899 <1> 2900 <1> ; 01/08/2013 (mkdir_w check) 2901 <1> ;push ax ; 26/04/2013 2902 <1> ; ; mov (sp),r1 / get an i-node number from the stack into r1 2903 <1> ; 28/11/2021 2904 000058FF 50 <1> push eax 2905 <1> ; AX = inode number 2906 00005900 E86BF9FFFF <1> call iget 2907 <1> ; jsr r0,iget / write i-node out (if modified), 2908 <1> ; / read i-node 'r1' into i-node area of core 2909 00005905 8B1D[B86E0000] <1> mov ebx, [u.fofp] 2910 0000590B 8B13 <1> mov edx, [ebx] 2911 <1> ; mov *u.fofp,r2 / put the file offset [(u.off) or the offset 2912 <1> ; / in the fsp entry for this file] in r2 2913 0000590D 0315[CC6E0000] <1> add edx, [u.count] 2914 <1> ; add u.count,r2 / no. of bytes to be written 2915 <1> ; / + file offset is put in r2 2916 <1> ;; 16/06/2015 2917 <1> ;cmp edx, 65535 ; file size limit (for UNIX v1 file system) 2918 <1> ;jna short dskw_0 2919 <1> ;mov dword [u.error], ERR_FILE_SIZE ; 'file size error !' 2920 <1> ;jmp error 2921 <1> dskw_0: 2922 <1> ; 28/11/2021 2923 00005913 3B15[486B0000] <1> cmp edx, [i.size] ; 32 bit file size (runix v2 inode) 2924 <1> ;cmp dx, [i.size] 2925 <1> ; ; cmp r2,i.size / is this greater than the present size of 2926 <1> ; / the file? 2927 00005919 760B <1> jna short dskw_1 2928 <1> ; blos 1f / no, branch 2929 0000591B 8915[486B0000] <1> mov [i.size], edx ; 32 bit file size (runix v2 inode) 2930 <1> ;mov [i.size], dx 2931 <1> ; mov r2,i.size / yes, increase the file size to 2932 <1> ; / file offset + no. of data bytes 2933 00005921 E8E9FAFFFF <1> call setimod 2934 <1> ; jsr r0,setimod / set imod=1 (i.e., core inode has been 2935 <1> ; / modified), stuff time of modification into 2936 <1> ; / core image of i-node 2937 <1> dskw_1: ; 1: 2938 <1> ; 28/11/2021 2939 <1> ;call mget 2940 00005926 E8D7F5FFFF <1> call mget_w 2941 <1> ; jsr r0,mget / get the block no. in which to write 2942 <1> ; / the next data byte 2943 <1> ; eax = physical block/sector number 2944 0000592B 8B1D[B86E0000] <1> mov ebx, [u.fofp] 2945 00005931 8B13 <1> mov edx, [ebx] 2946 00005933 81E2FF010000 <1> and edx, 1FFh 2947 <1> ; bit *u.fofp,$777 / test the lower 9 bits of the file offset 2948 00005939 750C <1> jnz short dskw_2 2949 <1> ; bne 2f / if its non-zero, branch; if zero, file offset = 0, 2950 <1> ; / 512, 1024,...(i.e., start of new block) 2951 0000593B 813D[CC6E0000]0002- <1> cmp dword [u.count], 512 2951 00005943 0000 <1> 2952 <1> ; cmp u.count,$512. / if zero, is there enough data to fill 2953 <1> ; / an entire block? (i.e., no. of 2954 00005945 7305 <1> jnb short dskw_3 2955 <1> ; bhis 3f / bytes to be written greater than 512.? 2956 <1> ; / Yes, branch. Don't have to read block 2957 <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be 2958 <1> ; / overwritten). 2959 00005947 E8D5050000 <1> call dskrd 2960 <1> ; jsr r0,dskrd / no, must retain old info.. 2961 <1> ; / Hence, read block 'r1' into an I/O buffer 2962 <1> dskw_3: ; 3: 2963 <1> ; EAX (r1) = block/sector number 2964 0000594C E830060000 <1> call wslot 2965 <1> ; jsr r0,wslot / set write and inhibit bits in I/O queue, 2966 <1> ; / proc. status=0, r5 points to 1st word of data 2967 00005951 803D[166F0000]00 <1> cmp byte [u.kcall], 0 2968 00005958 770F <1> ja short dskw_5 ; zf=0 -> the caller is 'mkdir' 2969 <1> ; 2970 0000595A 66833D[106F0000]00 <1> cmp word [u.pcount], 0 2971 00005962 7705 <1> ja short dskw_5 2972 <1> dskw_4: 2973 <1> ; [u.base] = virtual address to transfer (as source address) 2974 00005964 E80AFEFFFF <1> call trans_addr_r ; translate virtual address to physical (r) 2975 <1> dskw_5: 2976 <1> ; eBX (r5) = system (I/O) buffer address 2977 00005969 E87D000000 <1> call sioreg 2978 <1> ; jsr r0,sioreg / r3 = no. of bytes of data, 2979 <1> ; / r1 = address of data, r2 points to location 2980 <1> ; / in buffer in which to start writing data 2981 <1> ; eSI = file (user data) offset 2982 <1> ; eDI = sector (I/O) buffer offset 2983 <1> ; eCX = byte count 2984 <1> ; 2985 0000596E F3A4 <1> rep movsb 2986 <1> ; movb (r1 )+,(r2)+ 2987 <1> ; / transfer a byte of data to the I/O buffer 2988 <1> ; dec r3 / decrement no. of bytes to be written 2989 <1> ; bne 2b / have all bytes been transferred? No, branch 2990 <1> ; 25/07/2015 2991 <1> ; eax = remain bytes in buffer 2992 <1> ; (check if remain bytes in the buffer > [u.pcount]) 2993 00005970 09C0 <1> or eax, eax 2994 00005972 75F0 <1> jnz short dskw_4 ; (page end before system buffer end!) 2995 <1> dskw_6: 2996 00005974 E824060000 <1> call dskwr 2997 <1> ; jsr r0,dskwr / yes, write the block and the i-node 2998 00005979 833D[CC6E0000]00 <1> cmp dword [u.count], 0 2999 <1> ; tst u.count / any more data to write? 3000 00005980 77A4 <1> ja short dskw_1 3001 <1> ; bne 1b / yes, branch 3002 <1> ; 03/08/2013 3003 00005982 C605[166F0000]00 <1> mov byte [u.kcall], 0 3004 <1> ; 20/09/2013 (;;) 3005 <1> ;pop ax 3006 <1> ; 28/11/2021 3007 00005989 58 <1> pop eax 3008 0000598A C3 <1> retn 3009 <1> ;;jmp short dskw_ret 3010 <1> ; jmp ret / no, return to the caller via 'ret' 3011 <1> 3012 <1> ; 24/12/2021 3013 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3014 <1> cpass: ; / get next character from user area of core and put it in r1 3015 <1> ; 18/10/2015 3016 <1> ; 10/10/2015 3017 <1> ; 10/07/2015 3018 <1> ; 02/07/2015 3019 <1> ; 01/07/2015 3020 <1> ; 24/06/2015 3021 <1> ; 08/06/2015 3022 <1> ; 04/06/2015 3023 <1> ; 20/05/2015 3024 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 3025 <1> ; 3026 <1> ; INPUTS -> 3027 <1> ; [u.base] = virtual address in user area 3028 <1> ; [u.count] = byte count (max.) 3029 <1> ; [u.pcount] = byte count in page (0 = reset) 3030 <1> ; OUTPUTS -> 3031 <1> ; AL = the character which is pointed by [u.base] 3032 <1> ; zf = 1 -> transfer count has been completed 3033 <1> ; 3034 <1> ; ((Modified registers: EAX, EDX, ECX)) 3035 <1> ; 3036 <1> ; 3037 0000598B 833D[CC6E0000]00 <1> cmp dword [u.count], 0 ; 14/08/2013 3038 <1> ; tst u.count / have all the characters been transferred 3039 <1> ; / (i.e., u.count, # of chars. left 3040 00005992 763F <1> jna short cpass_3 3041 <1> ; beq 1f / to be transferred = 0?) yes, branch 3042 00005994 FF0D[CC6E0000] <1> dec dword [u.count] 3043 <1> ; dec u.count / no, decrement u.count 3044 <1> ; 19/05/2015 3045 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 3046 <1> ; to physical address 3047 0000599A 66833D[106F0000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 3048 <1> ; 1-4095 --> use previous physical base address 3049 <1> ; in [u.pbase] 3050 000059A2 770E <1> ja short cpass_1 3051 <1> ; 02/07/2015 3052 000059A4 833D[086F0000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller os kernel 3053 000059AB 7427 <1> je short cpass_k ; (sysexec, '/etc/init') ? 3054 <1> ; 08/06/2015 - 10/07/2015 3055 000059AD E8C1FDFFFF <1> call trans_addr_r 3056 <1> cpass_1: 3057 <1> ; 02/07/2015 3058 <1> ; 24/06/2015 3059 000059B2 66FF0D[106F0000] <1> dec word [u.pcount] 3060 <1> cpass_2: 3061 <1> ; 10/10/2015 3062 <1> ; 02/07/2015 3063 000059B9 8B15[0C6F0000] <1> mov edx, [u.pbase] 3064 000059BF 8A02 <1> mov al, [edx] ; 10/10/2015 3065 <1> ; movb *u.base,r1 / take the character pointed to 3066 <1> ; / by u.base and put it in r1 3067 000059C1 FF05[D06E0000] <1> inc dword [u.nread] 3068 <1> ; inc u.nread / increment no. of bytes transferred 3069 000059C7 FF05[C86E0000] <1> inc dword [u.base] 3070 <1> ; inc u.base / increment the buffer address to point to the 3071 <1> ; / next byte 3072 000059CD FF05[0C6F0000] <1> inc dword [u.pbase] ; 04/06/2015 3073 <1> cpass_3: 3074 000059D3 C3 <1> retn 3075 <1> ; rts r0 / next byte 3076 <1> ; 1: 3077 <1> ; mov (sp)+,r0 3078 <1> ; / put return address of calling routine into r0 3079 <1> ; mov (sp)+,r1 / i-number in r1 3080 <1> ; rts r0 / non-local return 3081 <1> cpass_k: 3082 <1> ; 02/07/2015 3083 <1> ; The caller is os kernel 3084 <1> ; (get sysexec arguments from kernel's memory space) 3085 <1> ; 3086 000059D4 8B1D[C86E0000] <1> mov ebx, [u.base] 3087 000059DA 66C705[106F0000]00- <1> mov word [u.pcount], PAGE_SIZE ; 4096 3087 000059E2 10 <1> 3088 000059E3 891D[0C6F0000] <1> mov [u.pbase], ebx 3089 000059E9 EBCE <1> jmp short cpass_2 3090 <1> 3091 <1> sioreg: 3092 <1> ; 25/07/2015 3093 <1> ; 18/07/2015 3094 <1> ; 02/07/2015 3095 <1> ; 17/06/2015 3096 <1> ; 09/06/2015 3097 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 3098 <1> ; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1) 3099 <1> ; 3100 <1> ; INPUTS -> 3101 <1> ; eBX = system buffer (data) address (r5) 3102 <1> ; [u.fofp] = pointer to file offset pointer 3103 <1> ; [u.base] = virtual address of the user buffer 3104 <1> ; [u.pbase] = physical address of the user buffer 3105 <1> ; [u.count] = byte count 3106 <1> ; [u.pcount] = byte count within page frame 3107 <1> ; OUTPUTS -> 3108 <1> ; eSI = user data offset (r1) 3109 <1> ; eDI = system (I/O) buffer offset (r2) 3110 <1> ; eCX = byte count (r3) 3111 <1> ; EAX = remain bytes after byte count within page frame 3112 <1> ; (If EAX > 0, transfer will continue from the next page) 3113 <1> ; 3114 <1> ; ((Modified registers: EDX)) 3115 <1> 3116 000059EB 8B35[B86E0000] <1> mov esi, [u.fofp] 3117 000059F1 8B3E <1> mov edi, [esi] 3118 <1> ; mov *u.fofp,r2 / file offset (in bytes) is moved to r2 3119 000059F3 89F9 <1> mov ecx, edi 3120 <1> ; mov r2,r3 / and also to r3 3121 000059F5 81C900FEFFFF <1> or ecx, 0FFFFFE00h 3122 <1> ; bis $177000,r3 / set bits 9,...,15 of file offset in r3 3123 000059FB 81E7FF010000 <1> and edi, 1FFh 3124 <1> ; bic $!777,r2 / calculate file offset mod 512. 3125 00005A01 01DF <1> add edi, ebx ; EBX = system buffer (data) address 3126 <1> ; add r5,r2 / r2 now points to 1st byte in system buffer 3127 <1> ; / where data is to be placed 3128 <1> ; mov u.base,r1 / address of data is in r1 3129 00005A03 F7D9 <1> neg ecx 3130 <1> ; neg r3 / 512 - file offset (mod512.) in r3 3131 <1> ; / (i.e., the no. of free bytes in the file block) 3132 00005A05 3B0D[CC6E0000] <1> cmp ecx, [u.count] 3133 <1> ; cmp r3,u.count / compare this with the no. of data bytes 3134 <1> ; / to be written to the file 3135 00005A0B 7606 <1> jna short sioreg_0 3136 <1> ; blos 2f / if less than branch. Use the no. of free bytes 3137 <1> ; / in the file block as the number to be written 3138 00005A0D 8B0D[CC6E0000] <1> mov ecx, [u.count] 3139 <1> ; mov u.count,r3 / if greater than, use the no. of data 3140 <1> ; / bytes as the number to be written 3141 <1> sioreg_0: 3142 <1> ; 17/06/2015 3143 00005A13 803D[166F0000]00 <1> cmp byte [u.kcall], 0 3144 00005A1A 7613 <1> jna short sioreg_1 3145 <1> ; 25/07/2015 3146 <1> ; the caller is 'mkdir' or 'namei' 3147 00005A1C A1[C86E0000] <1> mov eax, [u.base] ; 25/07/2015 3148 00005A21 A3[0C6F0000] <1> mov [u.pbase], eax ; physical address = virtual address 3149 00005A26 66890D[106F0000] <1> mov word [u.pcount], cx ; remain bytes in buffer (1 sector) 3150 00005A2D EB0B <1> jmp short sioreg_2 3151 <1> sioreg_1: 3152 <1> ; 25/07/2015 3153 <1> ; 18/07/2015 3154 <1> ; 09/06/2015 3155 00005A2F 0FB715[106F0000] <1> movzx edx, word [u.pcount] 3156 <1> ; ecx and [u.pcount] are always > 0, here 3157 00005A36 39D1 <1> cmp ecx, edx 3158 00005A38 772A <1> ja short sioreg_4 ; transfer count > [u.pcount] 3159 <1> sioreg_2: ; 2: 3160 00005A3A 31C0 <1> xor eax, eax ; 25/07/2015 3161 <1> sioreg_3: 3162 00005A3C 010D[D06E0000] <1> add [u.nread], ecx 3163 <1> ; add r3,u.nread / r3 + number of bytes xmitted 3164 <1> ; / during write is put into u.nread 3165 00005A42 290D[CC6E0000] <1> sub [u.count], ecx 3166 <1> ; sub r3,u.count / u.count = no. of bytes that still 3167 <1> ; / must be written or read 3168 00005A48 010D[C86E0000] <1> add [u.base], ecx 3169 <1> ; add r3,u.base / u.base points to the 1st of the remaining 3170 <1> ; / data bytes 3171 00005A4E 010E <1> add [esi], ecx 3172 <1> ; add r3,*u.fofp / new file offset = number of bytes done 3173 <1> ; / + old file offset 3174 <1> ; 25/07/2015 3175 00005A50 8B35[0C6F0000] <1> mov esi, [u.pbase] 3176 00005A56 66290D[106F0000] <1> sub [u.pcount], cx 3177 00005A5D 010D[0C6F0000] <1> add [u.pbase], ecx 3178 00005A63 C3 <1> retn 3179 <1> ; rts r0 3180 <1> ; transfer count > [u.pcount] 3181 <1> sioreg_4: 3182 <1> ; 25/07/2015 3183 <1> ; transfer count > [u.pcount] 3184 <1> ; (ecx > edx) 3185 00005A64 89C8 <1> mov eax, ecx 3186 00005A66 29D0 <1> sub eax, edx ; remain bytes for 1 sector (block) transfer 3187 00005A68 89D1 <1> mov ecx, edx ; current transfer count = [u.pcount] 3188 00005A6A EBD0 <1> jmp short sioreg_3 3189 <1> 3190 <1> ; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification 3191 <1> is_regular_file: 3192 <1> ; check if it is a regular file or device file inode 3193 <1> ; 3194 <1> ; INPUT: 3195 <1> ; current inode 3196 <1> ; OUTPUT: 3197 <1> ; cf = 0 and zf = 1 -> regular file 3198 <1> ; cf = 0 and zf = 0 -> device file 3199 <1> ; cf = 1 -> invalid file (jump to 'error') 3200 <1> ; 3201 <1> ; Modified registers: ecx (cl) 3202 <1> 3203 <1> ; 28/11/2021 3204 00005A6C 8A0D[416B0000] <1> mov cl, [i.flgs+1] 3205 00005A72 F6C180 <1> test cl, 80h ; regular file ? 3206 00005A75 7514 <1> jnz short isregf_1 ; yes 3207 00005A77 80E120 <1> and cl, 20h ; device file ? 3208 00005A7A 7511 <1> jnz short isregf_2 ; yes 3209 <1> 3210 <1> ; 28/11/2021 3211 <1> ; invalid inode/file type ! 3212 00005A7C C705[186F0000]FF00- <1> mov dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file 3212 00005A84 0000 <1> 3213 <1> ;stc 3214 <1> ;retn 3215 00005A86 E921E1FFFF <1> jmp error 3216 <1> isregf_1: 3217 00005A8B 30C9 <1> xor cl, cl ; cl = 0 3218 <1> ; zf = 1 3219 <1> ;retn 3220 <1> isregf_2: 3221 <1> ; zf = 0 3222 <1> ; cl = 20h 3223 00005A8D C3 <1> retn 2082 %include 'u7.s' ; 18/04/2015 2083 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2084 <1> ; (re-write kernel for test by using previous version without a major defect) 2085 <1> ; **************************************************************************** 2086 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC 2087 <1> ; Last Modification: 08/01/2022 2088 <1> ; ---------------------------------------------------------------------------- 2089 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2090 <1> ; (v0.1 - Beginning: 11/07/2012) 2091 <1> ; 2092 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2093 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2094 <1> ; 2095 <1> ; 2096 <1> ; 2097 <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s 2098 <1> ; 2099 <1> ; **************************************************************************** 2100 <1> 2101 <1> sysmount: ; / mount file system; args special; name 2102 <1> ; 14/11/2015 2103 <1> ; 24/10/2015 2104 <1> ; 13/10/2015 2105 <1> ; 10/07/2015 2106 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 2107 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 2108 <1> ; 2109 <1> ; 'sysmount' anounces to the system that a removable 2110 <1> ; file system has been mounted on a special file. 2111 <1> ; The device number of the special file is obtained via 2112 <1> ; a call to 'getspl'. It is put in the I/O queue entry for 2113 <1> ; dismountable file system (sb1) and the I/O queue entry is 2114 <1> ; set up to read (bit 10 is set). 'ppoke' is then called to 2115 <1> ; to read file system into core, i.e. the first block on the 2116 <1> ; mountable file system is read in. This block is super block 2117 <1> ; for the file system. This call is super user restricted. 2118 <1> ; 2119 <1> ; Calling sequence: 2120 <1> ; sysmount; special; name 2121 <1> ; Arguments: 2122 <1> ; special - pointer to name of special file (device) 2123 <1> ; name - pointer to name of the root directory of the 2124 <1> ; newly mounted file system. 'name' should 2125 <1> ; always be a directory. 2126 <1> ; Inputs: - 2127 <1> ; Outputs: - 2128 <1> ; ............................................................... 2129 <1> ; 2130 <1> ; Retro UNIX 8086 v1 modification: 2131 <1> ; 'sysmount' system call has two arguments; so, 2132 <1> ; * 1st argument, special is pointed to by BX register 2133 <1> ; * 2nd argument, name is in CX register 2134 <1> ; 2135 <1> ; NOTE: Device numbers, names and related procedures are 2136 <1> ; already modified for IBM PC compatibility and 2137 <1> ; Retro UNIX 8086 v1 device configuration. 2138 <1> 2139 <1> ;call arg2 2140 <1> ; jsr r0,arg2 / get arguments special and name 2141 00005A8E 891D[C06E0000] <1> mov [u.namep], ebx 2142 00005A94 51 <1> push ecx ; directory name 2143 00005A95 66833D[906E0000]00 <1> cmp word [mnti], 0 2144 <1> ; tst mnti / is the i-number of the cross device file 2145 <1> ; / zero? 2146 <1> ;ja error 2147 <1> ; bne errora / no, error 2148 00005A9D 0F87E9000000 <1> ja sysmnt_err0 2149 <1> ; 2150 00005AA3 E8CC000000 <1> call getspl 2151 <1> ; jsr r0,getspl / get special files device number in r1 2152 <1> ; 13/10/2015 2153 00005AA8 0FB7D8 <1> movzx ebx, ax ; ; Retro UNIX 8086 v1 device number (0 to 5) 2154 00005AAB F683[EA680000]80 <1> test byte [ebx+drv.status], 80h ; 24/10/2015 2155 00005AB2 750F <1> jnz short sysmnt_1 2156 <1> sysmnt_err1: 2157 00005AB4 C705[186F0000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY ; drive not ready ! 2157 00005ABC 0000 <1> 2158 00005ABE E9E9E0FFFF <1> jmp error 2159 <1> sysmnt_1: 2160 00005AC3 8F05[C06E0000] <1> pop dword [u.namep] 2161 <1> ; mov (sp)+,u.namep / put the name of file to be placed 2162 <1> ; / on the device 2163 <1> ; 14/11/2015 2164 00005AC9 53 <1> push ebx ; 13/10/2015 2165 <1> ; mov r1,-(sp) / save the device number 2166 <1> ; 2167 00005ACA E813EEFFFF <1> call namei 2168 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 2169 <1> ; ax = 0 -> file not found 2170 <1> ;jz error 2171 <1> ;jc error 2172 <1> ; jsr r0,namei / get the i-number of the file 2173 <1> ; br errora 2174 00005ACF 730F <1> jnc short sysmnt_2 2175 <1> sysmnt_err2: 2176 00005AD1 C705[186F0000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready ! 2176 00005AD9 0000 <1> 2177 00005ADB E9CCE0FFFF <1> jmp error 2178 <1> sysmnt_2: 2179 00005AE0 66A3[906E0000] <1> mov [mnti], ax 2180 <1> ; mov r1,mnti / put it in mnti 2181 <1> ; mov ebx, sb1 ; super block buffer (of mounted disk) 2182 <1> sysmnt_3: ;1: 2183 <1> ;cmp byte [ebx+1], 0 2184 <1> ; tstb sb1+1 / is 15th bit of I/O queue entry for 2185 <1> ; / dismountable device set? 2186 <1> ;jna short sysmnt_4 2187 <1> ; bne 1b / (inhibit bit) yes, skip writing 2188 <1> ;call idle ; (wait for hardware interrupt) 2189 <1> ;jmp short sysmnt_3 2190 <1> sysmnt_4: 2191 00005AE6 58 <1> pop eax ; Retro UNIX 8086 v1 device number/ID (0 to 5) 2192 00005AE7 A2[876E0000] <1> mov [mdev], al 2193 <1> ; mov (sp),mntd / no, put the device number in mntd 2194 00005AEC 8803 <1> mov [ebx], al 2195 <1> ; movb (sp),sb1 / put the device number in the lower byte 2196 <1> ; / of the I/O queue entry 2197 <1> ;mov byte [cdev], 1 ; mounted device/drive 2198 <1> ; mov (sp)+,cdev / put device number in cdev 2199 00005AEE 66810B0004 <1> or word [ebx], 400h ; Bit 10, 'read' flag/bit 2200 <1> ; bis $2000,sb1 / set the read bit 2201 <1> ; Retro UNIX 386 v1 modification : 2202 <1> ; 32 bit block number at buffer header offset 4 2203 00005AF3 C7430401000000 <1> mov dword [ebx+4], 1 ; physical block number = 1 2204 00005AFA E8E1050000 <1> call diskio 2205 00005AFF 731C <1> jnc short sysmnt_5 2206 00005B01 31C0 <1> xor eax, eax 2207 00005B03 66A3[906E0000] <1> mov [mnti], ax ; 0 2208 00005B09 A2[876E0000] <1> mov [mdev], al ; 0 2209 <1> ;mov [cdev], al ; 0 2210 <1> sysmnt_invd: 2211 <1> ; 14/11/2015 2212 00005B0E FEC8 <1> dec al 2213 00005B10 8903 <1> mov [ebx], eax ; 000000FFh 2214 00005B12 FEC0 <1> inc al 2215 00005B14 48 <1> dec eax 2216 00005B15 894304 <1> mov [ebx+4], eax ; 0FFFFFFFFh 2217 00005B18 E98FE0FFFF <1> jmp error 2218 <1> sysmnt_5: 2219 <1> ; 14/11/2015 (Retro UNIX 386 v1 modification) 2220 <1> ; (Following check is needed to prevent mounting an 2221 <1> ; in valid valid file system (in valid super block). 2222 <1> ; 2223 00005B1D 0FB603 <1> movzx eax, byte [ebx] ; device number 2224 00005B20 C0E002 <1> shl al, 2 ; 4*index 2225 00005B23 8B88[CE680000] <1> mov ecx, [eax+drv.size] ; volume (fs) size 2226 00005B29 C1E103 <1> shl ecx, 3 2227 00005B2C 0FB715[58710000] <1> movzx edx, word [sb1+4] ; the 1st data word 2228 00005B33 39D1 <1> cmp ecx, edx ; compare free map bits and volume size 2229 <1> ; (in sectors), if they are not equal 2230 <1> ; the disk to be mounted is an... 2231 00005B35 75D7 <1> jne short sysmnt_invd ; invalid disk ! 2232 <1> ; (which has not got a valid super block) 2233 <1> ; 2234 00005B37 C6430100 <1> mov byte [ebx+1], 0 2235 <1> ; jsr r0,ppoke / read in entire file system 2236 <1> ;sysmnt_6: ;1: 2237 <1> ;;cmp byte [sb1+1], 0 2238 <1> ; tstb sb1+1 / done reading? 2239 <1> ;;jna sysret 2240 <1> ;;call idle ; (wait for hardware interrupt) 2241 <1> ;;jmp short sysmnt_6 2242 <1> ;bne 1b / no, wait 2243 <1> ;br sysreta / yes 2244 00005B3B E98CE0FFFF <1> jmp sysret 2245 <1> 2246 <1> sysumount: ; / special dismount file system 2247 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 2248 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 2249 <1> ; 2250 <1> ; 04/11/2013 2251 <1> ; 09/07/2013 2252 <1> ; 'sysumount' anounces to the system that the special file, 2253 <1> ; indicated as an argument is no longer contain a removable 2254 <1> ; file system. 'getspl' gets the device number of the special 2255 <1> ; file. If no file system was mounted on that device an error 2256 <1> ; occurs. 'mntd' and 'mnti' are cleared and control is passed 2257 <1> ; to 'sysret'. 2258 <1> ; 2259 <1> ; Calling sequence: 2260 <1> ; sysmount; special 2261 <1> ; Arguments: 2262 <1> ; special - special file to dismount (device) 2263 <1> ; 2264 <1> ; Inputs: - 2265 <1> ; Outputs: - 2266 <1> ; ............................................................... 2267 <1> ; 2268 <1> ; Retro UNIX 8086 v1 modification: 2269 <1> ; 'sysumount' system call has one argument; so, 2270 <1> ; * Single argument, special is pointed to by BX register 2271 <1> ; 2272 <1> 2273 <1> ;mov ax, 1 ; one/single argument, put argument in BX 2274 <1> ;call arg 2275 <1> ; jsr r0,arg; u.namep / point u.namep to special 2276 00005B40 891D[C06E0000] <1> mov [u.namep], ebx 2277 00005B46 E829000000 <1> call getspl 2278 <1> ; jsr r0,getspl / get the device number in r1 2279 00005B4B 3A05[876E0000] <1> cmp al, [mdev] 2280 <1> ; cmp r1,mntd / is it equal to the last device mounted? 2281 00005B51 7539 <1> jne short sysmnt_err0 ; 'permission denied !' error 2282 <1> ;jne error 2283 <1> ; bne errora / no error 2284 00005B53 30C0 <1> xor al, al ; ah = 0 2285 <1> sysumnt_0: ;1: 2286 00005B55 3805[55710000] <1> cmp [sb1+1], al ; 0 2287 <1> ; tstb sb1+1 / yes, is the device still doing I/O 2288 <1> ; / (inhibit bit set)? 2289 00005B5B 7607 <1> jna short sysumnt_1 2290 <1> ; bne 1b / yes, wait 2291 00005B5D E88DF2FFFF <1> call idle ; (wait for hardware interrupt) 2292 00005B62 EBF1 <1> jmp short sysumnt_0 2293 <1> sysumnt_1: 2294 00005B64 A2[876E0000] <1> mov [mdev], al 2295 <1> ; clr mntd / no, clear these 2296 00005B69 66A3[906E0000] <1> mov [mnti], ax 2297 <1> ; clr mnti 2298 00005B6F E958E0FFFF <1> jmp sysret 2299 <1> ; br sysreta / return 2300 <1> 2301 <1> getspl: ; / get device number from a special file name 2302 00005B74 E869EDFFFF <1> call namei 2303 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 2304 <1> ; ax = 0 -> file not found 2305 00005B79 0F8252FFFFFF <1> jc sysmnt_err2 ; 'file not found !' error 2306 <1> ;jz error 2307 <1> ;jc error 2308 <1> ; jsr r0,namei / get the i-number of the special file 2309 <1> ; br errora / no such file 2310 00005B7F 6683E803 <1> sub ax, 3 ; Retro UNIX 8086 v1 modification ! 2311 <1> ; i-number-3, 0 = fd0, 5 = hd3 2312 <1> ; sub $4,r1 / i-number-4 rk=1,tap=2+n 2313 00005B83 7207 <1> jc short sysmnt_err0 ; 'permission denied !' error 2314 <1> ;jc error 2315 <1> ; ble errora / less than 0? yes, error 2316 00005B85 6683F805 <1> cmp ax, 5 ; 2317 <1> ; cmp r1,$9. / greater than 9 tap 7 2318 00005B89 7701 <1> ja short sysmnt_err0 ; 'permission denied !' error 2319 <1> ;ja error 2320 <1> ; bgt errora / yes, error 2321 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 2322 <1> iopen_retn: 2323 00005B8B C3 <1> retn 2324 <1> ; rts r0 / return with device number in r1 2325 <1> sysmnt_err0: 2326 00005B8C C705[186F0000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2326 00005B94 0000 <1> 2327 00005B96 E911E0FFFF <1> jmp error 2328 <1> 2329 <1> ; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification 2330 <1> iopen: 2331 <1> ; 05/12/2021 - Retro UNIX 386 v1.2 2332 <1> ; 27/03/2021 (Retro UNIX 386 v2) 2333 <1> ; 19/05/2015 2334 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2335 <1> ; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1) 2336 <1> ; 2337 <1> ; open file whose i-number is in r1 2338 <1> ; 2339 <1> ; INPUTS -> 2340 <1> ; r1 - inode number 2341 <1> ; OUTPUTS -> 2342 <1> ; file's inode in core 2343 <1> ; r1 - inode number (positive) 2344 <1> ; 2345 <1> ; ((AX = R1)) 2346 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 2347 <1> ; 2348 <1> ; / open file whose i-number is in r1 2349 <1> ; test ah, 80h ; Bit 15 of AX 2350 <1> ; ;tst r1 / write or read access? 2351 <1> ; jnz short iopen_2 2352 <1> ; ;blt 2f / write, go to 2f 2353 <1> ; mov dl, 2 ; read access 2354 <1> ; call access 2355 <1> ; ;jsr r0,access; 2 2356 <1> ; ; / get inode into core with read access 2357 <1> ; ; DL=2 2358 <1> ;iopen_0: 2359 <1> ; cmp ax, 40 2360 <1> ; ; cmp r1,$40. / is it a special file 2361 <1> ; ja short iopen_retn 2362 <1> ; ;bgt 3f / no. 3f 2363 <1> 2364 <1> ; 05/12/2021 2365 <1> ; DL = 0 -> open for read 2366 <1> ; DL = 1 -> open for write 2367 <1> 2368 00005B9B 52 <1> push edx ; * 2369 <1> 2370 <1> ; set permission/mode flag for 'access' 2371 <1> ; (DX = 100h -> IREAD, DX = 80h -> IWRITE) 2372 <1> 2373 00005B9C B601 <1> mov dh, 1 2374 00005B9E 08D2 <1> or dl, dl ; dl = 0, open for read 2375 00005BA0 7404 <1> jz short iopen_0 ; DX = IREAD (100h) 2376 <1> ; dl = 1, open for write 2377 00005BA2 FECE <1> dec dh 2378 00005BA4 B280 <1> mov dl, 80h 2379 <1> ; DX = IWRITE (80h) 2380 <1> iopen_0: 2381 <1> ; 27/03/2021 2382 <1> ; EAX = inode number (in AX) 2383 <1> ; DX = access mode, 100h = read, 80h = write 2384 <1> 2385 <1> ; 24/06/2020 - Retro UNIX 386 v2 2386 00005BA6 E8AFF7FFFF <1> call access 2387 <1> ;jsr r0,access; 1 / get inode in core 2388 <1> 2389 <1> ; 27/03/2021 2390 <1> ; DX return value from 'access' subroutine 2391 <1> ; may be 100h, 20h, 04h for DX = 100h (IREAD) input 2392 <1> ; 80h, 10h, 02h for DX = 80h (IWRITE) input 2393 <1> 2394 <1> ; 05/12/2021 2395 00005BAB 5A <1> pop edx ; * ; dl = 0 -> open for read 2396 <1> ; dl = 1 -> open for write 2397 <1> ; 24/06/2020 2398 00005BAC 8A0D[416B0000] <1> mov cl, [i.flgs+1] 2399 <1> 2400 00005BB2 F6C180 <1> test cl, 80h ; regular file ? 2401 00005BB5 7514 <1> jnz short iopen_1 ; yes ; 05/12/2021 2402 00005BB7 F6C120 <1> test cl, 20h ; device file ? 2403 00005BBA 7524 <1> jnz short iopen_2 ; yes 2404 <1> 2405 <1> ; no !?, error. 2406 <1> 2407 00005BBC C705[186F0000]FF00- <1> mov dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file 2407 00005BC4 0000 <1> 2408 <1> iopen_err: 2409 00005BC6 E9E1DFFFFF <1> jmp error 2410 <1> 2411 <1> iopen_1: 2412 <1> ; 05/12/2021 2413 <1> ; (If open mode is 'write' and the file/inode is a directory, 2414 <1> ; open request will/must be rejected.) 2415 <1> ; 2416 <1> ; (If inode is a regular file and it is not a directory, 2417 <1> ; there is nothing to do here, we need to return to 'sysopen' 2418 <1> ; for completing the rest of file opening procedure.) 2419 <1> 2420 00005BCB F6C140 <1> test cl, 40h ; directory ? 2421 00005BCE 74BB <1> jz short iopen_retn ; no 2422 <1> 2423 00005BD0 20D2 <1> and dl, dl ; open mode is 1 (write) ? 2424 00005BD2 74B7 <1> jz short iopen_retn ; no 2425 <1> 2426 <1> ; !!! 2427 <1> ; 'sysopen' for writing 2428 <1> ; is not applicable for directories 2429 <1> ; (Directory entries must be created or deleted by 2430 <1> ; relevant system calls.) 2431 <1> 2432 <1> ;mov dword [u.error], ERR_DIR_ACCESS ; 11 2433 00005BD4 C705[186F0000]0B00- <1> mov dword [u.error], ERR_PERM_DENIED ; 11 2433 00005BDC 0000 <1> 2434 <1> ; 'permission denied !' error 2435 <1> ;jmp error 2436 00005BDE EBE6 <1> jmp short iopen_err 2437 <1> 2438 <1> ;iopen_retn: 2439 <1> ; retn 2440 <1> 2441 <1> iopen_2: 2442 <1> ;push ax 2443 <1> ; ; mov r1,-(sp) / yes, figure out 2444 <1> ;movzx ebx, al 2445 <1> ;shl bx, 2 2446 <1> ; ; asl r1 2447 <1> ;add ebx, iopen_1 - 4 2448 <1> ;jmp dword [ebx] 2449 <1> ; ; jmp *1f-2(r1) / which one and transfer to it 2450 <1> 2451 <1> ; 05/12/2021 2452 00005BE0 50 <1> push eax ; save inode number 2453 <1> ; device file 2454 00005BE1 BB[FD5B0000] <1> mov ebx, iopen_4 2455 00005BE6 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 2456 00005BE9 720E <1> jb short iopen_3 2457 00005BEB 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 2458 00005BEE 7709 <1> ja short iopen_3 2459 <1> ; convert v2 inode number to v1 device inode number 2460 00005BF0 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 2461 00005BF2 89C1 <1> mov ecx, eax 2462 00005BF4 C0E102 <1> shl cl, 2 ; * 4 2463 00005BF7 01CB <1> add ebx, ecx 2464 <1> iopen_3: 2465 00005BF9 FEC2 <1> inc dl ; 1 = read, 2 = write 2466 00005BFB FF23 <1> jmp dword [ebx] 2467 <1> ; jmp *1f-2(r1) 2468 <1> ;iopen_1: ; 1: 2469 <1> iopen_4: 2470 00005BFD [5C560000] <1> dd null ; 05/12/2021 2471 00005C01 [4D5C0000] <1> dd otty ; tty, AX = 1 (runix) 2472 <1> ;otty / tty ; r1=2 2473 <1> ;oppt / ppt ; r1=4 2474 00005C05 [EC5C0000] <1> dd sret ; mem, AX = 2 (runix) 2475 <1> ;sret / mem ; r1=6 2476 <1> ;sret / rf0 2477 <1> ;sret / rk0 2478 <1> ;sret / tap0 2479 <1> ;sret / tap1 2480 <1> ;sret / tap2 2481 <1> ;sret / tap3 2482 <1> ;sret / tap4 2483 <1> ;sret / tap5 2484 <1> ;sret / tap6 2485 <1> ;sret / tap7 2486 00005C09 [EC5C0000] <1> dd sret ; fd0, AX = 3 (runix only) 2487 00005C0D [EC5C0000] <1> dd sret ; fd1, AX = 4 (runix only) 2488 00005C11 [EC5C0000] <1> dd sret ; hd0, AX = 5 (runix only) 2489 00005C15 [EC5C0000] <1> dd sret ; hd1, AX = 6 (runix only) 2490 00005C19 [EC5C0000] <1> dd sret ; hd2, AX = 7 (runix only) 2491 00005C1D [EC5C0000] <1> dd sret ; hd3, AX = 8 (runix only) 2492 <1> ;dd error ; lpr, AX = 9 (error !) 2493 00005C21 [EC5C0000] <1> dd sret ; lpr, AX = 9 (runix) 2494 00005C25 [5C5C0000] <1> dd ocvt ; tty0, AX = 10 (runix) 2495 <1> ;ocvt / tty0 2496 00005C29 [5C5C0000] <1> dd ocvt ; tty1, AX = 11 (runix) 2497 <1> ;ocvt / tty1 2498 00005C2D [5C5C0000] <1> dd ocvt ; tty2, AX = 12 (runix) 2499 <1> ;ocvt / tty2 2500 00005C31 [5C5C0000] <1> dd ocvt ; tty3, AX = 13 (runix) 2501 <1> ;ocvt / tty3 2502 00005C35 [5C5C0000] <1> dd ocvt ; tty4, AX = 14 (runix) 2503 <1> ;ocvt / tty4 2504 00005C39 [5C5C0000] <1> dd ocvt ; tty5, AX = 15 (runix) 2505 <1> ;ocvt / tty5 2506 00005C3D [5C5C0000] <1> dd ocvt ; tty6, AX = 16 (runix) 2507 <1> ;ocvt / tty6 2508 00005C41 [5C5C0000] <1> dd ocvt ; tty7, AX = 17 (runix) 2509 <1> ;ocvt / tty7 2510 00005C45 [5C5C0000] <1> dd ocvt ; COM1, AX = 18 (runix only) 2511 <1> ;error / crd 2512 00005C49 [5C5C0000] <1> dd ocvt ; COM2, AX = 19 (runix only) 2513 <1> 2514 <1> ;iopen_2: ; 2: / check open write access 2515 <1> ; neg ax 2516 <1> ; ;neg r1 / make inode number positive 2517 <1> ; mov dl, 1 ; write access 2518 <1> ; call access 2519 <1> ; ;jsr r0,access; 1 / get inode in core 2520 <1> ; ; DL=1 2521 <1> ; test word [i.flgs], 4000h ; Bit 14 : Directory flag 2522 <1> ; ;bit $40000,i.flgs / is it a directory? 2523 <1> ; jz short iopen_0 2524 <1> ; ;mov [u.error], ERR_DIR_ACCESS 2525 <1> ; ;jmp error ; permission denied ! 2526 <1> ; jmp sysmnt_err0 2527 <1> ; ;;jnz error 2528 <1> ; ; bne 2f / yes, transfer (error) 2529 <1> ; ;;jmp short iopen_0 2530 <1> ; ;cmp ax, 40 2531 <1> ; ; cmp r1,$40. / no, is it a special file? 2532 <1> ; ;ja short iopen_2 2533 <1> ; ;bgt 3f / no, return 2534 <1> ; ;push ax 2535 <1> ; ;mov r1,-(sp) / yes 2536 <1> ; ;movzx ebx, al 2537 <1> ; ;shl bx, 1 2538 <1> ; ; asl r1 2539 <1> ; ;add ebx, ipen_3 - 2 2540 <1> ; ;jmp dword [ebx] 2541 <1> ; ; jmp *1f-2(r1) / figure out 2542 <1> ; ; / which special file it is and transfer 2543 <1> ;iopen_3: ; 1: 2544 <1> ; dd otty ; tty, AX = 1 (runix) 2545 <1> ; ;otty / tty ; r1=2 2546 <1> ; ;leadr / ppt ; r1=4 2547 <1> ; dd sret ; mem, AX = 2 (runix) 2548 <1> ; ;sret / mem ; r1=6 2549 <1> ; ;sret / rf0 2550 <1> ; ;sret / rk0 2551 <1> ; ;sret / tap0 2552 <1> ; ;sret / tap1 2553 <1> ; ;sret / tap2 2554 <1> ; ;sret / tap3 2555 <1> ; ;sret / tap4 2556 <1> ; ;sret / tap5 2557 <1> ; ;sret / tap6 2558 <1> ; ;sret / tap7 2559 <1> ; dd sret ; fd0, AX = 3 (runix only) 2560 <1> ; dd sret ; fd1, AX = 4 (runix only) 2561 <1> ; dd sret ; hd0, AX = 5 (runix only) 2562 <1> ; dd sret ; hd1, AX = 6 (runix only) 2563 <1> ; dd sret ; hd2, AX = 7 (runix only) 2564 <1> ; dd sret ; hd3, AX = 8 (runix only) 2565 <1> ; dd sret ; lpr, AX = 9 (runix) 2566 <1> ; ;dd ejec ; lpr, AX = 9 (runix) 2567 <1> ; dd sret ; tty0, AX = 10 (runix) 2568 <1> ; ;ocvt / tty0 2569 <1> ; dd sret ; tty1, AX = 11 (runix) 2570 <1> ; ;ocvt / tty1 2571 <1> ; dd sret ; tty2, AX = 12 (runix) 2572 <1> ; ;ocvt / tty2 2573 <1> ; dd sret ; tty3, AX = 13 (runix) 2574 <1> ; ;ocvt / tty3 2575 <1> ; dd sret ; tty4, AX = 14 (runix) 2576 <1> ; ;ocvt / tty4 2577 <1> ; dd sret ; tty5, AX = 15 (runix) 2578 <1> ; ;ocvt / tty5 2579 <1> ; dd sret ; tty6, AX = 16 (runix) 2580 <1> ; ;ocvt / tty6 2581 <1> ; dd sret ; tty7, AX = 17 (runix) 2582 <1> ; ;ocvt / tty7 2583 <1> ; dd ocvt ; COM1, AX = 18 (runix only) 2584 <1> ; ;/ ejec / lpr 2585 <1> ; dd ocvt ; COM2, AX = 19 (runix only) 2586 <1> 2587 <1> otty: ;/ open console tty for reading or writing 2588 <1> ; 08/01/2022 2589 <1> ; 01/01/2022 2590 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2591 <1> ; 16/11/2015 2592 <1> ; 12/11/2015 2593 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2594 <1> ; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1) 2595 <1> ; 16/07/2013 2596 <1> ; Retro UNIX 8086 v1 modification: 2597 <1> ; If a tty is open for read or write by 2598 <1> ; a process (u.uno), only same process can open 2599 <1> ; same tty to write or read (R->R&W or W->W&R). 2600 <1> ; 2601 <1> ; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty) 2602 <1> ; 2603 00005C4D 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 2604 00005C54 8A83[DF6B0000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2605 <1> ; 13/01/2014 2606 00005C5A EB04 <1> jmp short ottyp 2607 <1> ocvt: 2608 00005C5C 2C0A <1> sub al, 10 2609 <1> ; 08/01/2022 2610 00005C5E 31DB <1> xor ebx, ebx 2611 <1> ottyp: 2612 <1> ; 08/01/2022 2613 <1> ; 01/01/2022 2614 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2615 <1> ; 16/11/2015 2616 <1> ; 12/11/2015 2617 <1> ; 18/05/2015 (32 bit modifications) 2618 <1> ; 06/12/2013 - 13/07/2014 2619 00005C60 88C6 <1> mov dh, al ; tty number 2620 <1> ;movzx ebx, al ; AL = tty number (0 to 9), AH = 0 2621 <1> ; 08/01/2022 2622 00005C62 88C3 <1> mov bl, al 2623 00005C64 D0E3 <1> shl bl, 1 ; aligned to word 2624 <1> ; 26/01/2014 2625 00005C66 81C3[F46D0000] <1> add ebx, ttyl 2626 00005C6C 668B0B <1> mov cx, [ebx] 2627 <1> ; CL = lock value (0 or process number) 2628 <1> ; CH = open count 2629 00005C6F 20C9 <1> and cl, cl 2630 <1> ; 13/01/2014 2631 <1> ;jz short otty_ret 2632 <1> ; 05/12/2021 2633 00005C71 743A <1> jz short ottys_0 2634 <1> ; 2635 <1> ; 16/11/2015 2636 00005C73 3A0D[F56E0000] <1> cmp cl, [u.uno] 2637 00005C79 745D <1> je short ottys_3 2638 <1> ; 2639 00005C7B 0FB6D9 <1> movzx ebx, cl ; the process which has locked the tty 2640 00005C7E D0E3 <1> shl bl, 1 2641 00005C80 668B83[7E6B0000] <1> mov ax, [ebx+p.pid-2] 2642 <1> ;movzx ebx, byte [u.uno] 2643 00005C87 8A1D[F56E0000] <1> mov bl, [u.uno] 2644 00005C8D D0E3 <1> shl bl, 1 2645 00005C8F 663B83[9E6B0000] <1> cmp ax, [ebx+p.ppid-2] 2646 00005C96 7440 <1> je short ottys_3 ; 16/11/2015 2647 <1> ; 2648 <1> ; the tty is locked by another process 2649 <1> ; except the parent process (p.ppid) 2650 <1> ; 2651 00005C98 C705[186F0000]0B00- <1> mov dword [u.error], ERR_DEV_ACCESS 2651 00005CA0 0000 <1> 2652 <1> ; permission denied ! error 2653 <1> otty_err: ; 13/01/2014 2654 00005CA2 08D2 <1> or dl, dl ; DL = 0 -> called by sysstty 2655 <1> ;jnz error 2656 <1> ; 05/12/2021 2657 00005CA4 7405 <1> jz short otty_stc_retn 2658 00005CA6 E901DFFFFF <1> jmp error 2659 <1> otty_stc_retn: 2660 00005CAB F9 <1> stc 2661 00005CAC C3 <1> retn 2662 <1> ottys_0: 2663 <1> ; 05/12/2021 2664 <1> otty_ret: 2665 <1> ; 13/01/2014 2666 00005CAD 80FE07 <1> cmp dh, 7 2667 00005CB0 761C <1> jna short ottys_2 2668 <1> ; 16/11/2015 2669 <1> com_port_check: 2670 00005CB2 BE[126E0000] <1> mov esi, com1p 2671 00005CB7 80FE08 <1> cmp dh, 8 ; COM1 (tty8) ? 2672 00005CBA 7601 <1> jna short ottys_1 ; yes, it is COM1 2673 00005CBC 46 <1> inc esi ; no, it is COM2 (tty9) 2674 <1> ottys_1: 2675 <1> ; 12/11/2015 2676 00005CBD 803E00 <1> cmp byte [esi], 0 ; E3h (or 23h) 2677 00005CC0 770C <1> ja short com_port_ready 2678 <1> ; 2679 00005CC2 C705[186F0000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY 2679 00005CCA 0000 <1> 2680 <1> ; device not ready ! error 2681 00005CCC EBD4 <1> jmp short otty_err 2682 <1> com_port_ready: 2683 <1> ottys_2: 2684 00005CCE 08C9 <1> or cl, cl ; cl = lock/owner, ch = open count 2685 00005CD0 7506 <1> jnz short ottys_3 2686 00005CD2 8A0D[F56E0000] <1> mov cl, [u.uno] 2687 <1> ottys_3: 2688 00005CD8 FEC5 <1> inc ch 2689 00005CDA 66890B <1> mov [ebx], cx ; set tty lock again 2690 <1> ; 06/12/2013 2691 00005CDD FEC6 <1> inc dh ; tty number + 1 2692 00005CDF BB[DA6E0000] <1> mov ebx, u.ttyp 2693 <1> ; 13/01/2014 2694 <1> ;test dl, 2 ; open for read sign 2695 <1> ;jnz short ottys_4 2696 <1> ; 05/12/2021 2697 <1> ;test dl, 2 2698 <1> ;jz short ottys_4 ; open for read 2699 <1> ; 01/01/2022 2700 00005CE4 F6C201 <1> test dl, 1 2701 00005CE7 7501 <1> jnz short ottys_4 ; open for read 2702 <1> ; dl = 2 (open for write) or dl = 0 (sysstty) 2703 00005CE9 43 <1> inc ebx 2704 <1> ottys_4: 2705 <1> ; Set 'u.ttyp' ('the recent TTY') value 2706 00005CEA 8833 <1> mov [ebx], dh ; tty number + 1 2707 <1> sret: 2708 00005CEC 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 2709 00005CEE 7401 <1> jz short iclose_retn 2710 <1> ;pop ax 2711 <1> ; 05/12/2021 2712 00005CF0 58 <1> pop eax 2713 <1> iclose_retn: 2714 00005CF1 C3 <1> retn 2715 <1> 2716 <1> ; 2717 <1> ; Original UNIX v1 'otty' routine: 2718 <1> ; 2719 <1> ;mov $100,*$tks / set interrupt enable bit (zero others) in 2720 <1> ; / reader status reg 2721 <1> ;mov $100,*$tps / set interrupt enable bit (zero others) in 2722 <1> ; / punch status reg 2723 <1> ;mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the 2724 <1> ; / console tty buffer 2725 <1> ;incb (r5) / increment the count of processes that opened the 2726 <1> ; / console tty 2727 <1> ;tst u.ttyp / is there a process control tty (i.e., has a tty 2728 <1> ; / buffer header 2729 <1> ;bne sret / address been loaded into u.ttyp yet)? yes, branch 2730 <1> ;mov r5,u.ttyp / no, make the console tty the process control 2731 <1> ; / tty 2732 <1> ;br sret / ? 2733 <1> ;sret: 2734 <1> ;clr *$ps / set processor priority to zero 2735 <1> ; pop ax 2736 <1> ;mov (sp)+,r1 / pop stack to r1 2737 <1> ;3: 2738 <1> ; retn 2739 <1> ;rts r0 2740 <1> 2741 <1> ;ocvt: ; < open tty > 2742 <1> ; 13/01/2014 2743 <1> ; 06/12/2013 (major modification: p.ttyc, u.ttyp) 2744 <1> ; 24/09/2013 consistency check -> ok 2745 <1> ; 16/09/2013 2746 <1> ; 03/09/2013 2747 <1> ; 27/08/2013 2748 <1> ; 16/08/2013 2749 <1> ; 16/07/2013 2750 <1> ; 27/05/2013 2751 <1> ; 21/05/2013 2752 <1> ; 2753 <1> ; Retro UNIX 8086 v1 modification ! 2754 <1> ; 2755 <1> ; In original UNIX v1, 'ocvt' routine 2756 <1> ; (exactly different than this one) 2757 <1> ; was in 'u9.s' file. 2758 <1> ; 2759 <1> ; 16/07/2013 2760 <1> ; Retro UNIX 8086 v1 modification: 2761 <1> ; If a tty is open for read or write by 2762 <1> ; a process (u.uno), only same process can open 2763 <1> ; same tty to write or read (R->R&W or W->W&R). 2764 <1> ; 2765 <1> ; INPUT: DL=2 for Read DL=1 for Write 2766 <1> 2767 <1> ; 16/09/2013 2768 <1> ; sub al, 10 2769 <1> 2770 <1> ; 06/12/2013 2771 <1> ;cmp al, 7 2772 <1> ;jna short ottyp 2773 <1> ; 13/01/2014 2774 <1> ;jmp short ottyp 2775 <1> 2776 <1> ;oppt: / open paper tape for reading or writing 2777 <1> ; mov $100,*$prs / set reader interrupt enable bit 2778 <1> ; tstb pptiflg / is file already open 2779 <1> ; bne 2f / yes, branch 2780 <1> ;1: 2781 <1> ; mov $240,*$ps / no, set processor priority to 5 2782 <1> ; jsr r0,getc; 2 / remove all entries in clist 2783 <1> ; br .+4 / for paper tape input and place in free list 2784 <1> ; br 1b 2785 <1> ; movb $2,pptiflg / set pptiflg to indicate file just open 2786 <1> ; movb $10.,toutt+1 / place 10 in paper tape input tout entry 2787 <1> ; br sret 2788 <1> ;2: 2789 <1> ; jmp error / file already open 2790 <1> 2791 <1> ; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification 2792 <1> iclose: 2793 <1> ; 05/12/2021 - Retro UNIX 386 v1.2 2794 <1> ; 10/04/2021 2795 <1> ; 08/04/2021 2796 <1> ; 04/04/2021 - Retro UNIX 386 v2 2797 <1> ; 19/05/2015 2798 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2799 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 2800 <1> ; 2801 <1> ; close file whose i-number is in r1 2802 <1> ; 2803 <1> ; INPUTS -> 2804 <1> ; r1 - inode number 2805 <1> ; OUTPUTS -> 2806 <1> ; file's inode in core 2807 <1> ; r1 - inode number (positive) 2808 <1> ; 2809 <1> ; ((AX = R1)) 2810 <1> ; ((Modified registers: -ebx-, edx)) 2811 <1> ; 2812 <1> ;;/ close file whose i-number is in r1 2813 <1> ; mov dl, 2 ; 12/01/2014 2814 <1> ; test ah, 80h ; Bit 15 of AX 2815 <1> ; ;tst r1 / test i-number 2816 <1> ; ;jnz short iclose_2 2817 <1> ; ;blt 2f / if neg., branch 2818 <1> ; jz short iclose_0 ; 30/07/2013 2819 <1> ; ; 16/07/2013 2820 <1> ; neg ax ; make it positive 2821 <1> ; ; 12/01/2014 2822 <1> ; dec dl ; dl = 1 (open for write) 2823 <1> ;iclose_0: 2824 <1> ; cmp ax, 40 2825 <1> ; ;cmp r1,$40. / is it a special file 2826 <1> ; ja short iclose_retn ; 13/01/2014 2827 <1> ; ;bgt 3b / no, return 2828 <1> ; ; 12/01/2014 2829 <1> ; ; DL=2 -> special file was opened for reading 2830 <1> ; ; DL=1 -> special file was opened for writing 2831 <1> 2832 <1> ; 04/04/2021 2833 <1> ; INPUT: 2834 <1> ; (e)ax = inode number 2835 <1> ; dl = open mode 2836 <1> ; 0 = control mode 2837 <1> ; 1 = read 2838 <1> ; 2 = write 2839 <1> ; OUTPUT: 2840 <1> ; none 2841 <1> ; (if cf=1 -> eax = error code) 2842 <1> ; (if cf=0 -> ax = inode number) 2843 <1> 2844 <1> ; 10/04/2021 2845 <1> ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 2846 <1> 2847 <1> ; 05/12/2021 2848 <1> ; 08/04/2021 2849 <1> 2850 00005CF2 52 <1> push edx 2851 00005CF3 E878F5FFFF <1> call iget 2852 00005CF8 5A <1> pop edx 2853 <1> 2854 00005CF9 8A0D[416B0000] <1> mov cl, [i.flgs+1] 2855 <1> 2856 <1> ; if i.flgs bit 15 is 1, it is regular file 2857 <1> ;test byte [i.flgs+1], 80h ; is it a special file? 2858 00005CFF F6C180 <1> test cl, 80h ; is it a special file? 2859 00005D02 75ED <1> jnz short iclose_retn ; no 2860 <1> 2861 <1> ;; inode flags - bit 13 must be 1 2862 <1> ;test cl, 20h ; is it a valid device inode 2863 <1> ;jnz short iclose_retn ; no 2864 <1> 2865 <1> ;push ax 2866 <1> ; ;mov r1,-(sp) / yes, save r1 on stack 2867 <1> ;movzx ebx, al 2868 <1> ;shl bx, 2 2869 <1> ; ; asl r1 2870 <1> ;add ebx, iclose_1 - 4 2871 <1> ;jmp dword [ebx] 2872 <1> ; ; jmp *1f-2(r1) / compute jump address and transfer 2873 <1> 2874 <1> ; 05/12/2021 2875 00005D04 50 <1> push eax ; save inode number 2876 <1> ; device file 2877 00005D05 BB[1F5D0000] <1> mov ebx, iclose_1 2878 00005D0A 83F808 <1> cmp eax, 8 ; /dev/tty inode number is 8 2879 00005D0D 720E <1> jb short iclose_0 2880 00005D0F 83F81A <1> cmp eax, 26 ; /dev/tty9 (/dev/com2) inode number is 26 2881 00005D12 7709 <1> ja short iclose_0 2882 <1> ; convert v2 inode number to v1 device inode number 2883 00005D14 2C07 <1> sub al, 7 ; 8 -> 1, 26 -> 19 2884 00005D16 89C1 <1> mov ecx, eax 2885 00005D18 C0E102 <1> shl cl, 2 ; * 4 2886 00005D1B 01CB <1> add ebx, ecx 2887 <1> iclose_0: 2888 00005D1D FF23 <1> jmp dword [ebx] 2889 <1> ; jmp *1f-2(r1) 2890 <1> iclose_1: ; 1: 2891 00005D1F [5C560000] <1> dd null ; 05/12/2021 2892 00005D23 [6F5D0000] <1> dd ctty ; tty, AX = 1 (runix) 2893 00005D27 [C15D0000] <1> dd cret ; mem, AX = 2 (runix) 2894 00005D2B [C15D0000] <1> dd cret ; fd0, AX = 3 (runix only) 2895 00005D2F [C15D0000] <1> dd cret ; fd1, AX = 4 (runix only) 2896 00005D33 [C15D0000] <1> dd cret ; hd0, AX = 5 (runix only) 2897 00005D37 [C15D0000] <1> dd cret ; hd1, AX = 6 (runix only) 2898 00005D3B [C15D0000] <1> dd cret ; hd2, AX = 7 (runix only) 2899 00005D3F [C15D0000] <1> dd cret ; hd3, AX = 8 (runix only) 2900 00005D43 [C15D0000] <1> dd cret ; lpr, AX = 9 (runix) 2901 <1> ;dd error; lpr, AX = 9 (error!) 2902 <1> ;;dd offset ejec ;;lpr, AX = 9 2903 00005D47 [7E5D0000] <1> dd ccvt ; tty0, AX = 10 (runix) 2904 00005D4B [7E5D0000] <1> dd ccvt ; tty1, AX = 11 (runix) 2905 00005D4F [7E5D0000] <1> dd ccvt ; tty2, AX = 12 (runix) 2906 00005D53 [7E5D0000] <1> dd ccvt ; tty3, AX = 13 (runix) 2907 00005D57 [7E5D0000] <1> dd ccvt ; tty4, AX = 14 (runix) 2908 00005D5B [7E5D0000] <1> dd ccvt ; tty5, AX = 15 (runix) 2909 00005D5F [7E5D0000] <1> dd ccvt ; tty6, AX = 16 (runix) 2910 00005D63 [7E5D0000] <1> dd ccvt ; tty7, AX = 17 (runix) 2911 00005D67 [7E5D0000] <1> dd ccvt ; COM1, AX = 18 (runix only) 2912 00005D6B [7E5D0000] <1> dd ccvt ; COM2, AX = 19 (runix only) 2913 <1> 2914 <1> ; 1: 2915 <1> ; ctty / tty 2916 <1> ; cppt / ppt 2917 <1> ; sret / mem 2918 <1> ; sret / rf0 2919 <1> ; sret / rk0 2920 <1> ; sret / tap0 2921 <1> ; sret / tap1 2922 <1> ; sret / tap2 2923 <1> ; sret / tap3 2924 <1> ; sret / tap4 2925 <1> ; sret / tap5 2926 <1> ; sret / tap6 2927 <1> ; sret / tap7 2928 <1> ; ccvt / tty0 2929 <1> ; ccvt / tty1 2930 <1> ; ccvt / tty2 2931 <1> ; ccvt / tty3 2932 <1> ; ccvt / tty4 2933 <1> ; ccvt / tty5 2934 <1> ; ccvt / tty6 2935 <1> ; ccvt / tty7 2936 <1> ; error / crd 2937 <1> 2938 <1> ;iclose_2: ; 2: / negative i-number 2939 <1> ;neg ax 2940 <1> ;neg r1 / make it positive 2941 <1> ;cmp ax, 40 2942 <1> ;cmp r1,$40. / is it a special file? 2943 <1> ;ja short @b 2944 <1> ;bgt 3b / no. return 2945 <1> ;push ax 2946 <1> ;mov r1,-(sp) 2947 <1> ;movzx ebx, al 2948 <1> ;shl bx, 1 2949 <1> ;asl r1 / yes. compute jump address and transfer 2950 <1> ;add ebx, iclose_3 - 2 2951 <1> ;jmp dword [ebx] 2952 <1> ;jmp *1f-2(r1) / figure out 2953 <1> ;iclose_3: 2954 <1> ;dd ctty ; tty, AX = 1 (runix) 2955 <1> ;dd sret ; mem, AX = 2 (runix) 2956 <1> ;dd sret ; fd0, AX = 3 (runix only) 2957 <1> ;dd sret ; fd1, AX = 4 (runix only) 2958 <1> ;dd sret ; hd0, AX = 5 (runix only) 2959 <1> ;dd sret ; hd1, AX = 6 (runix only) 2960 <1> ;dd sret ; hd2, AX = 7 (runix only) 2961 <1> ;dd sret ; hd3, AX = 8 (runix only) 2962 <1> ;;dd sret ; lpr, AX = 9 2963 <1> ;dd ejec ; lpr, AX = 9 (runix) 2964 <1> ;dd ccvt ; tty0, AX = 10 (runix) 2965 <1> ;dd ccvt ; tty1, AX = 11 (runix) 2966 <1> ;dd ccvt ; tty2, AX = 12 (runix) 2967 <1> ;dd ccvt ; tty3, AX = 13 (runix) 2968 <1> ;dd ccvt ; tty4, AX = 14 (runix) 2969 <1> ;dd ccvt ; tty5, AX = 15 (runix) 2970 <1> ;dd ccvt ; tty6, AX = 16 (runix) 2971 <1> ;dd ccvt ; tty7, AX = 17 (runix) 2972 <1> ;dd ccvt ; COM1, AX = 18 (runix only) 2973 <1> ;dd ccvt ; COM2, AX = 19 (runix only) 2974 <1> 2975 <1> ;1: 2976 <1> ; ctty / tty 2977 <1> ; leadr / ppt 2978 <1> ; sret / mem 2979 <1> ; sret / rf0 2980 <1> ; sret / rk0 2981 <1> ; sret / tap0 2982 <1> ; sret / tap1 2983 <1> ; sret / tap2 2984 <1> ; sret / tap3 2985 <1> ; sret / tap4 2986 <1> ; sret / tap5 2987 <1> ; sret / tap6 2988 <1> ; sret / tap7 2989 <1> ; ccvt / tty0 2990 <1> ; ccvt / tty1 2991 <1> ; ccvt / tty2 2992 <1> ; ccvt / tty3 2993 <1> ; ccvt / tty4 2994 <1> ; ccvt / tty5 2995 <1> ; ccvt / tty6 2996 <1> ; ccvt / tty7 2997 <1> ;/ ejec / lpr 2998 <1> 2999 <1> ctty: ; / close console tty 3000 <1> ; 08/01/2022 3001 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 3002 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 3003 <1> ; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1) 3004 <1> ; 3005 <1> ; Retro UNIX 8086 v1 modification ! 3006 <1> ; (DL = 2 -> it is open for reading) 3007 <1> ; (DL = 1 -> it is open for writing) 3008 <1> ; (DL = 0 -> it is open for sysstty system call) 3009 <1> ; 3010 <1> ; 06/12/2013 3011 00005D6F 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 3012 00005D76 8A83[DF6B0000] <1> mov al, [ebx+p.ttyc-1] 3013 <1> ; 13/01/2014 3014 00005D7C EB04 <1> jmp short cttyp 3015 <1> ccvt: 3016 00005D7E 2C0A <1> sub al, 10 3017 <1> ; 08/01/2022 3018 00005D80 31DB <1> xor ebx, ebx 3019 <1> cttyp: 3020 <1> ; 08/01/2022 3021 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 3022 <1> ; 18/05/2015 (32 bit modifications) 3023 <1> ; 16/08/2013 - 26/01/2014 3024 <1> ;movzx ebx, al ; tty number (0 to 9) 3025 <1> ; 08/01/2022 3026 00005D82 88C3 <1> mov bl, al 3027 00005D84 D0E3 <1> shl bl, 1 ; aligned to word 3028 <1> ; 26/01/2014 3029 00005D86 81C3[F46D0000] <1> add ebx, ttyl 3030 00005D8C 88C6 <1> mov dh, al ; tty number 3031 00005D8E 668B03 <1> mov ax, [ebx] 3032 <1> ; AL = lock value (0 or process number) 3033 <1> ; AH = open count 3034 00005D91 20E4 <1> and ah, ah 3035 00005D93 750F <1> jnz short ctty_ret 3036 00005D95 C705[186F0000]0A00- <1> mov dword [u.error], ERR_DEV_NOT_OPEN 3036 00005D9D 0000 <1> 3037 <1> ; device not open ! error 3038 <1> ;jmp short ctty_err ; open count = 0, it is not open ! 3039 00005D9F E908DEFFFF <1> jmp error 3040 <1> ; 26/01/2014 3041 <1> ctty_ret: 3042 00005DA4 FECC <1> dec ah ; decrease open count 3043 00005DA6 7502 <1> jnz short ctty_1 3044 00005DA8 30C0 <1> xor al, al ; unlock/free tty 3045 <1> ctty_1: 3046 00005DAA 668903 <1> mov [ebx], ax ; close tty instance 3047 <1> ; 3048 00005DAD BB[DA6E0000] <1> mov ebx, u.ttyp 3049 <1> ;test dl, 1 ; open for write sign 3050 <1> ;jz short ctty_2 3051 <1> ; 05/12/2021 3052 00005DB2 F6C202 <1> test dl, 2 ; open for write sign 3053 00005DB5 7401 <1> jz short ctty_2 3054 00005DB7 43 <1> inc ebx 3055 <1> ctty_2: 3056 00005DB8 FEC6 <1> inc dh ; tty number + 1 3057 00005DBA 3A33 <1> cmp dh, [ebx] 3058 00005DBC 7503 <1> jne short cret 3059 <1> ; Reset/Clear 'u.ttyp' ('the recent TTY') value 3060 00005DBE C60300 <1> mov byte [ebx], 0 3061 <1> cret: 3062 00005DC1 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 3063 00005DC3 7401 <1> jz short ctty_3 3064 <1> ;pop ax 3065 <1> ; 05/12/2021 3066 00005DC5 58 <1> pop eax 3067 <1> ctty_3: 3068 00005DC6 C3 <1> retn 3069 <1> 3070 <1> ;ctty_err: ; 13/01/2014 3071 <1> ; or dl, dl ; DL = 0 -> called by sysstty 3072 <1> ; jnz error 3073 <1> ; stc 3074 <1> ; retn 3075 <1> 3076 <1> ; Original UNIX v1 'ctty' routine: 3077 <1> ; 3078 <1> ;mov tty+[ntty*8]-8+6,r5 3079 <1> ; ;/ point r5 to the console tty buffer 3080 <1> ;decb (r5) / dec number of processes using console tty 3081 <1> ;br sret / return via sret 3082 <1> 3083 <1> ;ccvt: ; < close tty > 3084 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 3085 <1> ; 3086 <1> ; Retro UNIX 8086 v1 modification ! 3087 <1> ; 3088 <1> ; In original UNIX v1, 'ccvt' routine 3089 <1> ; (exactly different than this one) 3090 <1> ; was in 'u9.s' file. 3091 <1> ; 3092 <1> ; DL = 2 -> it is open for reading 3093 <1> ; DL = 1 -> it is open for writing 3094 <1> ; 3095 <1> ; 17/09/2013 3096 <1> ;sub al, 10 3097 <1> ;cmp al, 7 3098 <1> ;jna short cttyp 3099 <1> ; 13/01/2014 3100 <1> ;jmp short cttyp 3101 <1> 3102 <1> ;cppt: / close paper tape 3103 <1> ; clrb pptiflg / set pptiflg to indicate file not open 3104 <1> ;1: 3105 <1> ; mov $240,*$ps /set process or priority to 5 3106 <1> ; jsr r0,getc; 2 / remove all ppt input entries from clist 3107 <1> ; / and assign to free list 3108 <1> ; br sret 3109 <1> ; br 1b 3110 <1> 3111 <1> ;ejec: 3112 <1> ; jmp error 3113 <1> ;/ejec: 3114 <1> ;/ mov $100,*$lps / set line printer interrupt enable bit 3115 <1> ;/ mov $14,r1 / 'form feed' character in r1 (new page). 3116 <1> ;/ jsr r0,lptoc / space the printer to a new page 3117 <1> ;/ br sret / return to caller via 'sret' 2083 %include 'u8.s' ; 11/06/2015 2084 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2085 <1> ; (re-write kernel for test by using previous version without a major defect) 2086 <1> ; **************************************************************************** 2087 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC 2088 <1> ; Last Modification: 09/01/2022 2089 <1> ; ---------------------------------------------------------------------------- 2090 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2091 <1> ; (v0.1 - Beginning: 11/07/2012) 2092 <1> ; 2093 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2094 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2095 <1> ; 2096 <1> ; 2097 <1> ; 2098 <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s 2099 <1> ; 2100 <1> ; **************************************************************************** 2101 <1> 2102 <1> ;; I/O Buffer - Retro UNIX 386 v1 modification 2103 <1> ;; (8+512 bytes, 8 bytes header, 512 bytes data) 2104 <1> ;; Word 1, byte 0 = device id 2105 <1> ;; Word 1, byte 1 = status bits (bits 8 to 15) 2106 <1> ;; bit 9 = write bit 2107 <1> ;; bit 10 = read bit 2108 <1> ;; bit 12 = waiting to write bit 2109 <1> ;; bit 13 = waiting to read bit 2110 <1> ;; bit 15 = inhibit bit 2111 <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015) 2112 <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 2113 <1> ;; (In fact, it is 32 bit LBA for Retro UNIX 386 v1) 2114 <1> ;; 2115 <1> ;; I/O Buffer ((8+512 bytes in original Unix v1)) 2116 <1> ;; ((4+512 bytes in Retro UNIX 8086 v1)) 2117 <1> ;; 2118 <1> ;; I/O Queue Entry (of original UNIX operating system v1) 2119 <1> ;; Word 1, Byte 0 = device id 2120 <1> ;; Word 1, Byte 1 = (bits 8 to 15) 2121 <1> ;; bit 9 = write bit 2122 <1> ;; bit 10 = read bit 2123 <1> ;; bit 12 = waiting to write bit 2124 <1> ;; bit 13 = waiting to read bit 2125 <1> ;; bit 15 = inhibit bit 2126 <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) 2127 <1> ;; 2128 <1> ;; Original UNIX v1 -> 2129 <1> ;; Word 3 = number of words in buffer (=256) 2130 <1> ;; Original UNIX v1 -> 2131 <1> ;; Word 4 = bus address (addr of first word of data buffer) 2132 <1> ;; 2133 <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! 2134 <1> ;; 2135 <1> ;; Device IDs (of Retro Unix 8086 v1) 2136 <1> ;; 0 = fd0 2137 <1> ;; 1 = fd1 2138 <1> ;; 2 = hd0 2139 <1> ;; 3 = hd1 2140 <1> ;; 4 = hd2 2141 <1> ;; 5 = hd3 2142 <1> 2143 <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015 2144 <1> 2145 <1> rfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2146 <1> ; 26/04/2013 2147 <1> ; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2148 <1> ;sub ax, 3 ; zero based device number (Floppy disk) 2149 <1> ;jmp short bread ; **** returns to routine that called readi 2150 <1> 2151 <1> rhd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2152 <1> ; 26/04/2013 2153 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2154 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2155 <1> ;jmp short bread ; **** returns to routine that called readi 2156 <1> 2157 <1> bread: 2158 <1> ; 14/07/2015 2159 <1> ; 10/07/2015 2160 <1> ; 09/06/2015 2161 <1> ; 07/06/2015 (Retro UNIX 386 v1 - Beginning) 2162 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2163 <1> ; 2164 <1> ; / read a block from a block structured device 2165 <1> ; 2166 <1> ; INPUTS -> 2167 <1> ; [u.fopf] points to the block number 2168 <1> ; CX = maximum block number allowed on device 2169 <1> ; ; that was an arg to bread, in original Unix v1, but 2170 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 2171 <1> ; [u.count] number of bytes to read in 2172 <1> ; OUTPUTS -> 2173 <1> ; [u.base] starting address of data block or blocks in user area 2174 <1> ; [u.fopf] points to next consecutive block to be read 2175 <1> ; 2176 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 2177 <1> ; 2178 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if read 2179 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 2180 <1> ; is increased by 1. For example: If user/program request 2181 <1> ; to read 16 bytes in current block, 'sys read' increases 2182 <1> ; the next block number just as 512 byte reading is done. 2183 <1> ; This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 2184 <1> ; for user (u) structure compatibility (because 16 bit is not 2185 <1> ; enough to keep byte position/offset of the disk), this 2186 <1> ; defect will not be corrected, user/program must request 2187 <1> ; 512 byte read per every 'sys read' call to block devices 2188 <1> ; for achieving correct result. In future version(s), 2189 <1> ; this defect will be corrected by using different 2190 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 2191 <1> 2192 <1> ; jsr r0,tstdeve / error on special file I/O 2193 <1> ; / (only works on tape) 2194 <1> ; mov *u.fofp,r1 / move block number to r1 2195 <1> ; mov $2.-cold,-(sp) / "2-cold" to stack 2196 <1> ;1: 2197 <1> ; cmp r1,(r0) / is this block # greater than or equal to 2198 <1> ; / maximum block # allowed on device 2199 <1> ; jnb short @f 2200 <1> ; bhis 1f / yes, 1f (error) 2201 <1> ; mov r1,-(sp) / no, put block # on stack 2202 <1> ; jsr r0,preread / read in the block into an I/O buffer 2203 <1> ; mov (sp)+,r1 / return block # to r1 2204 <1> ; inc r1 / bump block # to next consecutive block 2205 <1> ; dec (sp) / "2-1-cold" on stack 2206 <1> ; bgt 1b / 2-1-cold = 0? No, go back and read in next block 2207 <1> ;1: 2208 <1> ; tst (sp)+ / yes, pop stack to clear off cold calculation 2209 <1> ;push ecx ; ** 2210 <1> ;26/04/2013 2211 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 2212 00005DC7 2C03 <1> sub al, 3 2213 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 2214 00005DC9 A2[176F0000] <1> mov [u.brwdev], al 2215 <1> ; 09/06/2015 2216 00005DCE 0FB6D8 <1> movzx ebx, al 2217 00005DD1 8B8B[CE680000] <1> mov ecx, [ebx+drv.size] ; disk size (in sectors) 2218 <1> bread_0: 2219 00005DD7 51 <1> push ecx ; ** ; 09/06/2015 2220 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 2221 <1> ; [u.fopf] points to byte position in disk, not sector/block ! 2222 00005DD8 8B1D[B86E0000] <1> mov ebx, [u.fofp] 2223 00005DDE 8B03 <1> mov eax, [ebx] 2224 00005DE0 C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 2225 <1> ; mov *u.fofp,r1 / restore r1 to initial value of the 2226 <1> ; / block # 2227 00005DE3 39C8 <1> cmp eax, ecx 2228 <1> ; cmp r1,(r0)+ / block # greater than or equal to maximum 2229 <1> ; / block number allowed 2230 <1> ;jnb error ; 18/04/2013 2231 <1> ; bhis error10 / yes, error 2232 00005DE5 720F <1> jb short bread_1 2233 00005DE7 C705[186F0000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2233 00005DEF 0000 <1> 2234 00005DF1 E9B6DDFFFF <1> jmp error 2235 <1> bread_1: 2236 <1> ; inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 2237 <1> ; inc *u.fofp / no, *u.fofp has next block number 2238 <1> ; eAX = Block number (zero based) 2239 <1> ;;jsr r0,preread / read in the block whose number is in r1 2240 <1> preread: ;; call preread 2241 00005DF6 BF[176F0000] <1> mov edi, u.brwdev ; block device number for direct I/O 2242 00005DFB E86A020000 <1> call bufaloc_0 ; 26/04/2013 2243 <1> ;; jc error 2244 <1> ; eBX = Buffer (Header) Address -Physical- 2245 <1> ; eAX = Block/Sector number (r1) 2246 <1> ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number) 2247 <1> ; 14/03/2013 2248 00005E00 740A <1> jz short bread_2 ; Retro UNIX 8086 v1 modification 2249 <1> ; br 1f / branch if block already in a I/O buffer 2250 00005E02 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 2251 <1> ; bis $2000,(r5) / set read bit (bit 10 in I/O buffer) 2252 00005E07 E8B3010000 <1> call poke 2253 <1> ; jsr r0,poke / perform the read 2254 <1> ;;jc error ;2 0/07/2013 2255 <1> ; 1: 2256 <1> ; clr *$ps / ps = 0 2257 <1> ; rts r0 2258 <1> ;; return from preread 2259 <1> bread_2: 2260 00005E0C 66810B0040 <1> or word [ebx], 4000h 2261 <1> ; bis $40000,(r5) 2262 <1> ; / set bit 14 of the 1st word of the I/O buffer 2263 <1> bread_3: ; 1: 2264 00005E11 66F7030024 <1> test word [ebx], 2400h 2265 <1> ; bit $22000,(r5) / are 10th and 13th bits set (read bits) 2266 00005E16 7407 <1> jz short bread_4 2267 <1> ; beq 1f / no 2268 <1> ; cmp cdev,$1 / disk or drum? 2269 <1> ; ble 2f / yes 2270 <1> ; tstb uquant / is the time quantum = 0? 2271 <1> ; bne 2f / no, 2f 2272 <1> ; mov r5,-(sp) / yes, save r5 (buffer address) 2273 <1> ; jsr r0,sleep; 31. 2274 <1> ; / put process to sleep in channel 31 (tape) 2275 <1> ; mov (sp)+,r5 / restore r5 2276 <1> ; br 1b / go back 2277 <1> ; 2: / drum or disk 2278 <1> ;; mov cx, [s.wait_]+2 ;; 29/07/2013 2279 00005E18 E8D2EFFFFF <1> call idle 2280 <1> ; jsr r0,idle; s.wait+2 / wait 2281 00005E1D EBF2 <1> jmp short bread_3 2282 <1> ; br 1b 2283 <1> bread_4: ; 1: / 10th and 13th bits not set 2284 00005E1F 668123FFBF <1> and word [ebx], 0BFFFh ; 1011111111111111b 2285 <1> ; bic $40000,(r5) / clear bit 14 2286 <1> ; jsr r0,tstdeve / test device for error (tape) 2287 00005E24 83C308 <1> add ebx, 8 2288 <1> ; add $8,r5 / r5 points to data in I/O buffer 2289 <1> ; 09/06/2015 2290 00005E27 66833D[106F0000]00 <1> cmp word [u.pcount], 0 2291 00005E2F 7705 <1> ja short bread_5 2292 00005E31 E841F9FFFF <1> call trans_addr_w ; translate virtual address to physical (w) 2293 <1> bread_5: 2294 <1> ; eBX = system (I/O) buffer address 2295 00005E36 E870000000 <1> call dioreg 2296 <1> ; jsr r0,dioreg / do bookkeeping on u.count etc. 2297 <1> ; esi = start address of the transfer (in the buffer) 2298 <1> ; edi = [u.pbase], destination address in user's memory space 2299 <1> ; ecx = transfer count (in bytes) 2300 <1> ; 2301 <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning 2302 <1> ; / of users data 2303 00005E3B F3A4 <1> rep movsb 2304 <1> ; movb (r5)+,(r2)+ / move data from the I/O buffer 2305 <1> ; dec r3 / to the user's area in core starting at u.base 2306 <1> ; bne 1b 2307 00005E3D 59 <1> pop ecx ; ** 2308 00005E3E 833D[CC6E0000]00 <1> cmp dword [u.count], 0 2309 <1> ; tst u.count / done 2310 00005E45 7790 <1> ja short bread_0 ; 09/06/2015 2311 <1> ; beq 1f / yes, return 2312 <1> ; tst -(r0) / no, point r0 to the argument again 2313 <1> ; br bread / read some more 2314 <1> ; 1: 2315 00005E47 58 <1> pop eax ; **** 2316 <1> ; mov (sp)+,r0 2317 00005E48 C3 <1> retn ; 09/06/2015 2318 <1> ;jmp ret_ 2319 <1> ;jmp ret / jump to routine that called readi 2320 <1> 2321 <1> wfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2322 <1> ; 26/04/2013 2323 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2324 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2325 <1> ;jmp short bwrite ; **** returns to routine that called writei 2326 <1> 2327 <1> whd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2328 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2329 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2330 <1> ;jmp short bwrite ; **** returns to routine that called writei ('jmp ret') 2331 <1> 2332 <1> bwrite: 2333 <1> ; 14/07/2015 2334 <1> ; 10/07/2015 2335 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2336 <1> ; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1) 2337 <1> ; 2338 <1> ;; / write on block structured device 2339 <1> ; 2340 <1> ; INPUTS -> 2341 <1> ; [u.fopf] points to the block number 2342 <1> ; CX = maximum block number allowed on device 2343 <1> ; ; that was an arg to bwrite, in original Unix v1, but 2344 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 2345 <1> ; [u.count] number of bytes to user desires to write 2346 <1> ; OUTPUTS -> 2347 <1> ; [u.fopf] points to next consecutive block to be written into 2348 <1> ; 2349 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2350 <1> ; 2351 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if write 2352 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 2353 <1> ; is increased by 1. For example: If user/program request 2354 <1> ; to write 16 bytes in current block, 'sys write' increases 2355 <1> ; the next block number just as 512 byte writing is done. 2356 <1> ; This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 2357 <1> ; for user (u) structure compatibility (because 16 bit is not 2358 <1> ; enough to keep byte position/offset of the disk), this 2359 <1> ; defect will not be corrected, user/program must request 2360 <1> ; 512 byte write per every 'sys write' call to block devices 2361 <1> ; for achieving correct result. In future version(s), 2362 <1> ; this defect will be corrected by using different 2363 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 2364 <1> 2365 <1> ; jsr r0,tstdeve / test the device for an error 2366 <1> ;push ecx ; ** 2367 <1> ;26/04/2013 2368 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 2369 00005E49 2C03 <1> sub al, 3 2370 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 2371 00005E4B A2[176F0000] <1> mov [u.brwdev], al 2372 <1> ; 09/06/2015 2373 00005E50 0FB6D8 <1> movzx ebx, al 2374 00005E53 8B8B[CE680000] <1> mov ecx, [ebx+drv.size] ; disk size (in sectors) 2375 <1> bwrite_0: 2376 00005E59 51 <1> push ecx ; ** ; 09/06/2015 2377 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 2378 <1> ; [u.fopf] points to byte position in disk, not sector/block ! 2379 00005E5A 8B1D[B86E0000] <1> mov ebx, [u.fofp] 2380 00005E60 8B03 <1> mov eax, [ebx] 2381 00005E62 C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 2382 <1> ; mov *u.fofp,r1 / put the block number in r1 2383 00005E65 39C8 <1> cmp eax, ecx 2384 <1> ; cmp r1,(r0)+ / does block number exceed maximum allowable # 2385 <1> ; / block number allowed 2386 <1> ;jnb error ; 18/04/2013 2387 <1> ; bhis error10 / yes, error 2388 00005E67 720F <1> jb short bwrite_1 2389 00005E69 C705[186F0000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2389 00005E71 0000 <1> 2390 00005E73 E934DDFFFF <1> jmp error 2391 <1> bwrite_1: 2392 <1> ; inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 2393 <1> ; inc *u.fofp / no, increment block number 2394 <1> ; 09/06/2015 - 10/07/2015 2395 00005E78 66833D[106F0000]00 <1> cmp word [u.pcount], 0 2396 00005E80 7705 <1> ja short bwrite_2 2397 00005E82 E8ECF8FFFF <1> call trans_addr_r ; translate virtual address to physical (r) 2398 <1> bwrite_2: 2399 00005E87 BF[176F0000] <1> mov edi, u.brwdev ; block device number for direct I/O 2400 00005E8C E8C4000000 <1> call bwslot ; 26/04/2013 (wslot -> bwslot) 2401 <1> ; jsr r0,wslot / get an I/O buffer to write into 2402 <1> ; add $8,r5 / r5 points to data in I/O buffer 2403 00005E91 E815000000 <1> call dioreg 2404 <1> ; jsr r0,dioreg / do the necessary bookkeeping 2405 <1> ; esi = destination address (in the buffer) 2406 <1> ; edi = [u.pbase], start address of transfer in user's memory space 2407 <1> ; ecx = transfer count (in bytes) 2408 <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area 2409 00005E96 87F7 <1> xchg esi, edi ; 14/07/2015 2410 00005E98 F3A4 <1> rep movsb 2411 <1> ; movb (r2)+,(r5)+ / ; r3, has the byte count 2412 <1> ; dec r3 / area to the I/O buffer 2413 <1> ; bne 1b 2414 00005E9A E8FE000000 <1> call dskwr 2415 <1> ; jsr r0,dskwr / write it out on the device 2416 00005E9F 59 <1> pop ecx ; ** 2417 00005EA0 833D[CC6E0000]00 <1> cmp dword [u.count], 0 2418 <1> ; tst u.count / done 2419 00005EA7 77B0 <1> ja short bwrite_0 ; 09/06/2015 2420 <1> ; beq 1f / yes, 1f 2421 <1> ; tst -(r0) / no, point r0 to the argument of the call 2422 <1> ; br bwrite / go back and write next block 2423 <1> ; 1: 2424 00005EA9 58 <1> pop eax ; **** 2425 <1> ; mov (sp)+,r0 2426 00005EAA C3 <1> retn ; 09/06/2015 2427 <1> ;jmp ret_ 2428 <1> ; jmp ret / return to routine that called writei 2429 <1> ;error10: 2430 <1> ; jmp error ; / see 'error' routine 2431 <1> 2432 <1> dioreg: 2433 <1> ; 14/07/2015 2434 <1> ; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block) 2435 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2436 <1> ; 14/03/2013 (Retro UNIX 8086 v1) 2437 <1> ; 2438 <1> ; bookkeeping on block transfers of data 2439 <1> ; 2440 <1> ; * returns value of u.pbase before it gets updated, in EDI 2441 <1> ; * returns byte count (to transfer) in ECX (<=512) 2442 <1> ; 10/07/2015 2443 <1> ; * returns byte offset from beginning of current sector buffer 2444 <1> ; (beginning of data) in ESI 2445 <1> ; 2446 00005EAB 8B0D[CC6E0000] <1> mov ecx, [u.count] 2447 <1> ; mov u.count,r3 / move char count to r3 2448 00005EB1 81F900020000 <1> cmp ecx, 512 2449 <1> ; cmp r3,$512. / more than 512. char? 2450 00005EB7 7605 <1> jna short dioreg_0 2451 <1> ; blos 1f / no, branch 2452 00005EB9 B900020000 <1> mov ecx, 512 2453 <1> ; mov $512.,r3 / yes, just take 512. 2454 <1> dioreg_0: 2455 <1> ; 09/06/2015 2456 00005EBE 663B0D[106F0000] <1> cmp cx, [u.pcount] 2457 00005EC5 7607 <1> jna short dioreg_1 2458 00005EC7 668B0D[106F0000] <1> mov cx, [u.pcount] 2459 <1> dioreg_1: 2460 <1> ; 1: 2461 00005ECE 8B15[C86E0000] <1> mov edx, [u.base] ; 09/06/2015 (eax -> edx) 2462 <1> ; mov u.base,r2 / put users base in r2 2463 00005ED4 010D[D06E0000] <1> add [u.nread], ecx 2464 <1> ; add r3,u.nread / add the number to be read to u.nread 2465 00005EDA 290D[CC6E0000] <1> sub [u.count], ecx 2466 <1> ; sub r3,u.count / update count 2467 00005EE0 010D[C86E0000] <1> add [u.base], ecx 2468 <1> ; add r3,u.base / update base 2469 <1> ; 10/07/2015 2470 <1> ; Retro UNIX 386 v1 - modification ! 2471 <1> ; (File pointer points to byte position, not block/sector no.) 2472 <1> ; (It will point to next byte position instead of next block no.) 2473 00005EE6 8B35[B86E0000] <1> mov esi, [u.fofp] ; u.fopf points to byte position pointer 2474 00005EEC 8B06 <1> mov eax, [esi] ; esi points to current byte pos. on the disk 2475 00005EEE 010E <1> add [esi], ecx ; ecx is added to set the next byte position 2476 00005EF0 25FF010000 <1> and eax, 1FFh ; get offset from beginning of current block 2477 00005EF5 89DE <1> mov esi, ebx ; beginning of data in sector/block buffer 2478 00005EF7 01C6 <1> add esi, eax ; esi contains start address of the transfer 2479 <1> ; 09/06/2015 - 10/07/2015 2480 00005EF9 66290D[106F0000] <1> sub [u.pcount], cx 2481 00005F00 81E2FF0F0000 <1> and edx, PAGE_OFF ; 0FFFh 2482 00005F06 8B3D[0C6F0000] <1> mov edi, [u.pbase] 2483 00005F0C 81E700F0FFFF <1> and edi, ~PAGE_OFF 2484 00005F12 01D7 <1> add edi, edx 2485 00005F14 893D[0C6F0000] <1> mov [u.pbase], edi 2486 00005F1A 010D[0C6F0000] <1> add [u.pbase], ecx ; 14/07/2015 2487 00005F20 C3 <1> retn 2488 <1> ; rts r0 / return 2489 <1> 2490 <1> dskrd: 2491 <1> ; 18/08/2015 2492 <1> ; 02/07/2015 2493 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2494 <1> ; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2495 <1> ; 2496 <1> ; 'dskrd' acquires an I/O buffer, puts in the proper 2497 <1> ; I/O queue entries (via bufaloc) then reads a block 2498 <1> ; (number specified in r1) in the acquired buffer.) 2499 <1> ; If the device is busy at the time dskrd is called, 2500 <1> ; dskrd calls idle. 2501 <1> ; 2502 <1> ; INPUTS -> 2503 <1> ; r1 - block number 2504 <1> ; cdev - current device number 2505 <1> ; OUTPUTS -> 2506 <1> ; r5 - points to first data word in I/O buffer 2507 <1> ; 2508 <1> ; ((AX = R1)) input/output 2509 <1> ; ((BX = R5)) output 2510 <1> ; 2511 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2512 <1> ; 2513 00005F21 E837010000 <1> call bufaloc 2514 <1> ; jsr r0,bufaloc / shuffle off to bufaloc; 2515 <1> ; / get a free I/O buffer 2516 <1> ;;jc error ; 20/07/2013 2517 00005F26 741B <1> jz short dskrd_1 ; Retro UNIX 8086 v1 modification 2518 <1> ; br 1f / branch if block already in a I/O buffer 2519 <1> dskrd_0: ; 10/07/2015 (wslot) 2520 00005F28 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 2521 <1> ; bis $2000,(r5) / set bit 10 of word 1 of 2522 <1> ; / I/O queue entry for buffer 2523 00005F2D E88D000000 <1> call poke 2524 <1> ; jsr r0,poke / just assigned in bufaloc, 2525 <1> ; / bit 10=1 says read 2526 <1> ; 09/06/2015 2527 00005F32 730F <1> jnc short dskrd_1 2528 <1> ; 2529 00005F34 C705[186F0000]1100- <1> mov dword [u.error], ERR_DRV_READ ; disk read error ! 2529 00005F3C 0000 <1> 2530 00005F3E E969DCFFFF <1> jmp error 2531 <1> dskrd_1: ; 1: 2532 <1> ;clr *$ps 2533 00005F43 66F7030024 <1> test word [ebx], 2400h 2534 <1> ; bit $22000,(r5) / if either bits 10, or 13 are 1; 2535 <1> ; / jump to idle 2536 00005F48 7407 <1> jz short dskrd_2 2537 <1> ; beq 1f 2538 <1> ;;mov ecx, [s.wait_] 2539 00005F4A E8A0EEFFFF <1> call idle 2540 <1> ; jsr r0,idle; s.wait+2 2541 00005F4F EBF2 <1> jmp short dskrd_1 2542 <1> ; br 1b 2543 <1> dskrd_2: ; 1: 2544 00005F51 83C308 <1> add ebx, 8 2545 <1> ; add $8,r5 / r5 points to first word of data in block 2546 <1> ; / just read in 2547 00005F54 C3 <1> retn 2548 <1> ; rts r0 2549 <1> 2550 <1> bwslot: 2551 <1> ; 10/07/2015 2552 <1> ; If the block/sector is not placed in a buffer 2553 <1> ; before 'wslot', it must be read before 2554 <1> ; it is written! (Otherwise transfer counts less 2555 <1> ; than 512 bytes will be able to destroy existing 2556 <1> ; data on disk.) 2557 <1> ; 2558 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2559 <1> ; 26/04/2013(Retro UNIX 8086 v1) 2560 <1> ; Retro UNIX 8086 v1 modification ! 2561 <1> ; ('bwslot' will be called from 'bwrite' only!) 2562 <1> ; INPUT -> eDI - points to device id (in u.brwdev) 2563 <1> ; -> eAX = block number 2564 <1> ; 2565 00005F55 E810010000 <1> call bufaloc_0 2566 00005F5A 742A <1> jz short wslot_0 ; block/sector already is in the buffer 2567 <1> bwslot_0: 2568 <1> ; 10/07/2015 2569 00005F5C 8B35[B86E0000] <1> mov esi, [u.fofp] 2570 00005F62 8B06 <1> mov eax, [esi] 2571 00005F64 25FF010000 <1> and eax, 1FFh ; offset from beginning of the sector/block 2572 00005F69 750C <1> jnz short bwslot_1 ; it is not a full sector write 2573 <1> ; recent disk data must be placed in the buffer 2574 00005F6B 813D[CC6E0000]0002- <1> cmp dword [u.count], 512 2574 00005F73 0000 <1> 2575 00005F75 730F <1> jnb short wslot_0 2576 <1> bwslot_1: 2577 00005F77 E8ACFFFFFF <1> call dskrd_0 2578 00005F7C 83EB08 <1> sub ebx, 8 ; set ebx to the buffer header address again 2579 00005F7F EB05 <1> jmp short wslot_0 2580 <1> 2581 <1> wslot: 2582 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2583 <1> ; (32 bit modifications) 2584 <1> ; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1) 2585 <1> ; 2586 <1> ; 'wslot' calls 'bufaloc' and obtains as a result, a pointer 2587 <1> ; to the I/O queue of an I/O buffer for a block structured 2588 <1> ; device. It then checks the first word of I/O queue entry. 2589 <1> ; If bits 10 and/or 13 (read bit, waiting to read bit) are set, 2590 <1> ; wslot calls 'idle'. When 'idle' returns, or if bits 10 2591 <1> ; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first 2592 <1> ; word of the I/O queue entry (write bit, inhibit bit). 2593 <1> ; 2594 <1> ; INPUTS -> 2595 <1> ; r1 - block number 2596 <1> ; cdev - current (block/disk) device number 2597 <1> ; 2598 <1> ; OUTPUTS -> 2599 <1> ; bufp - bits 9 and 15 are set, 2600 <1> ; the remainder of the word left unchanged 2601 <1> ; r5 - points to first data word in I/O buffer 2602 <1> ; 2603 <1> ; ((AX = R1)) input/output 2604 <1> ; ((BX = R5)) output 2605 <1> ; 2606 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2607 <1> 2608 00005F81 E8D7000000 <1> call bufaloc 2609 <1> ; 10/07/2015 2610 <1> ; jsr r0,bufaloc / get a free I/O buffer; pointer to first 2611 <1> ; br 1f / word in buffer in r5 2612 <1> ; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) 2613 <1> ; eAX = Block/Sector number (r1) 2614 <1> wslot_0: ;1: 2615 00005F86 66F7030024 <1> test word [ebx], 2400h 2616 <1> ; bit $22000,(r5) / check bits 10, 13 (read, waiting to read) 2617 <1> ; / of I/O queue entry 2618 00005F8B 7407 <1> jz short wslot_1 2619 <1> ; beq 1f / branch if 10, 13 zero (i.e., not reading, 2620 <1> ; / or not waiting to read) 2621 <1> 2622 <1> ;; mov ecx, [s.wait_] ; 29/07/2013 2623 00005F8D E85DEEFFFF <1> call idle 2624 <1> ; jsr r0,idle; / if buffer is reading or writing to read, 2625 <1> ; / idle 2626 00005F92 EBF2 <1> jmp short wslot_0 2627 <1> ; br 1b / till finished 2628 <1> wslot_1: ;1: 2629 00005F94 66810B0082 <1> or word [ebx], 8200h 2630 <1> ; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue 2631 <1> ; / (write, inhibit bits) 2632 <1> ; clr *$ps / clear processor status 2633 00005F99 83C308 <1> add ebx, 8 ; 11/06/2015 2634 <1> ; add $8,r5 / r5 points to first word in data area 2635 <1> ; / for this block 2636 00005F9C C3 <1> retn 2637 <1> ; rts r0 2638 <1> dskwr: 2639 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2640 <1> ; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2641 <1> ; 2642 <1> ; 'dskwr' writes a block out on disk, via ppoke. The only 2643 <1> ; thing dskwr does is clear bit 15 in the first word of I/O queue 2644 <1> ; entry pointed by 'bufp'. 'wslot' which must have been called 2645 <1> ; previously has supplied all the information required in the 2646 <1> ; I/O queue entry. 2647 <1> ; 2648 <1> ; (Modified registers: eCX, eDX, eBX, eSI, eDI) 2649 <1> ; 2650 <1> ; 2651 00005F9D 8B1D[606E0000] <1> mov ebx, [bufp] 2652 00005FA3 668123FF7F <1> and word [ebx], 7FFFh ; 0111111111111111b 2653 <1> ; bic $100000,*bufp / clear bit 15 of I/O queue entry at 2654 <1> ; / bottom of queue 2655 00005FA8 E812000000 <1> call poke 2656 <1> ; 09/06/2015 2657 00005FAD 730F <1> jnc short dskwr_1 2658 00005FAF C705[186F0000]1200- <1> mov dword [u.error], ERR_DRV_WRITE ; disk write error ! 2658 00005FB7 0000 <1> 2659 00005FB9 E9EEDBFFFF <1> jmp error 2660 <1> dskwr_1: 2661 00005FBE C3 <1> retn 2662 <1> 2663 <1> ;ppoke: 2664 <1> ; mov $340,*$ps 2665 <1> ; jsr r0,poke 2666 <1> ; clr *$ps 2667 <1> ; rts r0 2668 <1> poke: 2669 <1> ; 29/11/2021 (32 bit reg push-pop) 2670 <1> ; 24/10/2015 2671 <1> ; 20/08/2015 2672 <1> ; 18/08/2015 2673 <1> ; 02/07/2015 2674 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2675 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2676 <1> ; 2677 <1> ; (NOTE: There are some disk I/O code modifications & extensions 2678 <1> ; & exclusions on original 'poke' & other device I/O procedures of 2679 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 2680 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 2681 <1> ; 2682 <1> ; Basic I/O functions for all block structured devices 2683 <1> ; 2684 <1> ; (Modified registers: eCX, eDX, eSI, eDI) 2685 <1> ; 2686 <1> ; 20/07/2013 modifications 2687 <1> ; (Retro UNIX 8086 v1 features only !) 2688 <1> ; INPUTS -> 2689 <1> ; (EBX = buffer header address) 2690 <1> ; OUTPUTS -> 2691 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 2692 <1> ; cf=1 -> error, word [eBX] = 0FFFFh 2693 <1> ; (drive not ready or r/w error!) 2694 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 2695 <1> ; (dword [EBx+4] = 0FFFFFFFFh means RW/IO error) 2696 <1> ; (also it indicates invalid buffer data) 2697 <1> ; 2698 00005FBF 53 <1> push ebx 2699 <1> ; mov r1,-(sp) 2700 <1> ; mov r2,-(sp) 2701 <1> ; mov r3,-(sp) 2702 00005FC0 50 <1> push eax ; Physical Block Number (r1) (mget) 2703 <1> ; 2704 <1> ; 09/06/2015 2705 <1> ; (permit read/write after a disk R/W error) 2706 00005FC1 8A0B <1> mov cl, [ebx] ; device id (0 to 5) 2707 00005FC3 B001 <1> mov al, 1 2708 00005FC5 D2E0 <1> shl al, cl 2709 00005FC7 8405[886E0000] <1> test al, [active] ; busy ? (error) 2710 00005FCD 7408 <1> jz short poke_0 2711 00005FCF F6D0 <1> not al 2712 00005FD1 2005[886E0000] <1> and [active], al ; reset busy bit for this device only 2713 <1> poke_0: 2714 00005FD7 BE[806E0000] <1> mov esi, bufp + (4*(nbuf+2)) 2715 <1> ; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority 2716 <1> ; / I/O queue pointer 2717 <1> poke_1: ; 1: 2718 00005FDC 83EE04 <1> sub esi, 4 2719 00005FDF 8B1E <1> mov ebx, [esi] 2720 <1> ; mov -(r2),r1 / r1 points to an I/O queue entry 2721 00005FE1 668B03 <1> mov ax, [ebx] ; 17/07/2013 2722 00005FE4 F6C406 <1> test ah, 06h 2723 <1> ;test word [ebx], 600h ; 0000011000000000b 2724 <1> ; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 2725 <1> ; / queue entry 2726 00005FE7 745C <1> jz short poke_5 2727 <1> ; beq 2f / branch to 2f if both are clear 2728 <1> ; 31/07/2013 2729 <1> ;test ah, 0B0h ; (*) 2730 <1> ;;test word [ebx], 0B000h ; 1011000000000000b 2731 <1> ; bit $130000,(r1) / test bits 12, 13, and 15 2732 <1> ;jnz short poke_5 ; 31/07/2013 (*) 2733 <1> ; bne 2f / branch if any are set 2734 <1> ;movzx ecx, byte [ebx] ; 09/06/2015 ; Device Id 2735 <1> ; movb (r1),r3 / get device id 2736 00005FE9 0FB6C8 <1> movzx ecx, al ; 18/08/2015 2737 <1> ;mov edi, ecx ; 26/04/2013 2738 00005FEC 31C0 <1> xor eax, eax ; 0 2739 <1> ;cmp [edi+drv.error], al ; 0 2740 <1> ; tstb deverr(r3) / test for errors on this device 2741 <1> ;jna short poke_2 2742 <1> ; beq 3f / branch if no errors 2743 <1> ; 02/07/2015 2744 <1> ;dec eax 2745 <1> ;mov [ebx+4], ax ; 0FFFFFFFFh ; -1 2746 <1> ; mov $-1,2(r1) / destroy associativity 2747 <1> ;shr eax, 24 2748 <1> ;mov [ebx], eax ; 000000FFh, reset 2749 <1> ; clrb 1(r1) / do not do I/O 2750 <1> ;jmp short poke_5 2751 <1> ; ; br 2f 2752 <1> ; rts r0 2753 <1> poke_2: ; 3: 2754 <1> ; 02/07/2015 2755 00005FEE FEC1 <1> inc cl ; 0FFh -> 0 2756 00005FF0 7453 <1> jz short poke_5 2757 00005FF2 FEC0 <1> inc al ; mov ax, 1 2758 00005FF4 FEC9 <1> dec cl 2759 00005FF6 7402 <1> jz short poke_3 2760 <1> ; 26/04/2013 Modification 2761 <1> ;inc al ; mov ax, 1 2762 <1> ;or cl, cl ; Retro UNIX 8086 v1 device id. 2763 <1> ;jz short poke_3 ; cl = 0 2764 00005FF8 D2E0 <1> shl al, cl ; shl ax, cl 2765 <1> poke_3: 2766 <1> ;test [active], ax 2767 00005FFA 8405[886E0000] <1> test [active], al 2768 <1> ; bit $2,active / test disk busy bit 2769 00006000 7543 <1> jnz short poke_5 2770 <1> ; bne 2f / branch if bit is set 2771 <1> ;or [active], ax 2772 00006002 0805[886E0000] <1> or [active], al 2773 <1> ; bis $2,active / set disk busy bit 2774 00006008 50 <1> push eax ; 29/11/2021 2775 00006009 E8D2000000 <1> call diskio ; Retro UNIX 8086 v1 Only ! 2776 <1> ;mov [edi+drv.error], ah 2777 0000600E 58 <1> pop eax 2778 0000600F 730E <1> jnc short poke_4 ; 20/07/2013 2779 <1> ;cmp [edi+drv.error], al ; 0 2780 <1> ;jna short poke_4 2781 <1> ; tstb deverr(r3) / test for errors on this device 2782 <1> ; beq 3f / branch if no errors 2783 <1> ; 02/07/2015 (32 bit modification) 2784 <1> ; 20/07/2013 2785 00006011 C74304FFFFFFFF <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 2786 <1> ; mov $-1,2(r1) / destroy associativity 2787 00006018 66C703FF00 <1> mov word [ebx], 0FFh ; 20/08/2015 2788 <1> ; clrb 1(r1) / do not do I/O 2789 0000601D EB26 <1> jmp short poke_5 2790 <1> poke_4: ; 20/07/2013 2791 <1> ; 17/07/2013 2792 0000601F F6D0 <1> not al 2793 00006021 2005[886E0000] <1> and [active], al ; reset, not busy 2794 <1> ; eBX = system I/O buffer header (queue entry) address 2795 <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits. 2796 00006027 668B03 <1> mov ax, [ebx] 2797 <1> ; mov (r1),r3 / move word 1 of I/O queue entry into r3 2798 0000602A 66250006 <1> and ax, 600h 2799 <1> ; bic $!3000,r3 / clear all bits except 9 and 10 2800 0000602E 668123FFF9 <1> and word [ebx], 0F9FFh 2801 <1> ; bic $3000,(r1) / clear only bits 9 and 10 2802 00006033 C0E403 <1> shl ah, 3 2803 <1> ; rol r3 2804 <1> ; rol r3 2805 <1> ; rol r3 2806 00006036 660903 <1> or [ebx], ax 2807 <1> ; bis r3,(r1) / or old value of bits 9 and 10 with 2808 <1> ; bits 12 and 13 2809 00006039 E8B1EDFFFF <1> call idle ; 18/01/2014 2810 <1> ;; sti 2811 <1> ;hlt ; wait for a hardware interrupt 2812 <1> ;; cli 2813 <1> ; NOTE: In fact, disk controller's 'disk I/O completed' 2814 <1> ; interrupt would be used to reset busy bits, but INT 13h 2815 <1> ; returns when disk I/O is completed. So, here, as temporary 2816 <1> ; method, this procedure will wait for a time according to 2817 <1> ; multi tasking and time sharing concept. 2818 <1> ; 2819 <1> ; 24/10/2015 2820 <1> ;not ax 2821 0000603E 66B8FF00 <1> mov ax, 0FFh ; 24/10/2015 (temporary) 2822 00006042 662103 <1> and [ebx], ax ; clear bits 12 and 13 2823 <1> poke_5: ;2: 2824 00006045 81FE[606E0000] <1> cmp esi, bufp 2825 <1> ; cmp r2,$bufp / test to see if entire I/O queue 2826 <1> ; / has been scanned 2827 0000604B 778F <1> ja short poke_1 2828 <1> ; bhi 1b 2829 <1> ; 24/03/2013 2830 <1> ; mov (sp)+,r3 2831 <1> ; mov (sp)+,r2 2832 <1> ; mov (sp)+,r1 2833 0000604D 58 <1> pop eax ; Physical Block Number (r1) (mget) 2834 0000604E 5B <1> pop ebx 2835 <1> ; 02/07/2015 (32 bit modification) 2836 <1> ; 20/07/2013 2837 <1> ;cmp dword [ebx+4], 0FFFFFFFFh 2838 0000604F 803BFF <1> cmp byte [ebx], 0FFh ; 20/08/2015 2839 <1> ; 2840 <1> ; 'poke' returns with cf=0 if the requested buffer is read 2841 <1> ; or written succesfully; even if an error occurs while 2842 <1> ; reading to or writing from other buffers. 20/07/2013 2843 <1> ; 2844 <1> ; 09/06/2015 2845 00006052 F5 <1> cmc 2846 00006053 C3 <1> retn 2847 <1> ; rts r0 2848 <1> 2849 <1> ; 27/11/2021 - Retro UNIX 386 v2 compatibility code 2850 <1> get_system_time: 2851 <1> ; 27/10/2021 2852 <1> ; 21/02/2020 - Retro UNIX 386 v2 2853 <1> ; get system time 2854 <1> ; (from recent value which is saved in RTC interrupt) 2855 <1> ; Input: 2856 <1> ; none 2857 <1> ; Return: 2858 <1> ; eax = system time in unix epoch format 2859 <1> ; 2860 <1> ; Modified registers: eax, ecx, edx 2861 <1> 2862 <1> ; 27/11/2021 2863 00006054 53 <1> push ebx 2864 00006055 E86FD6FFFF <1> call epoch 2865 0000605A 5B <1> pop ebx 2866 0000605B C3 <1> retn 2867 <1> 2868 <1> get_serial_number: 2869 <1> ; temporary - 21/02/2020 2870 <1> ; 26/04/2020 (esi) 2871 <1> ; 25/04/2020 2872 <1> ; (Possible) Modified registers: eax, ecx, edx 2873 <1> ; (edi, ebx & esi registers must be preserved) 2874 <1> ; Return: 2875 <1> ; eax = 32 bit serial number 2876 <1> ; (edx = high 32 bit of 64 bit serial number) 2877 <1> ; -64 bit serial numbers will not be used in RUNIX 386 v2- 2878 0000605C C3 <1> retn 2879 <1> 2880 <1> bufaloc: 2881 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 2882 <1> ; 20/08/2015 2883 <1> ; 19/08/2015 2884 <1> ; 02/07/2015 2885 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2886 <1> ; (32 bit modifications) 2887 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2888 <1> ; 2889 <1> ; bufaloc - Block device I/O buffer allocation 2890 <1> ; 2891 <1> ; INPUTS -> 2892 <1> ; r1 - block number 2893 <1> ; cdev - current (block/disk) device number 2894 <1> ; bufp+(2*n)-2 --- n = 1 ... nbuff 2895 <1> ; OUTPUTS -> 2896 <1> ; r5 - pointer to buffer allocated 2897 <1> ; bufp ... bufp+12 --- (bufp), (bufp)+2 2898 <1> ; 2899 <1> ; ((AX = R1)) input/output 2900 <1> ; ((BX = R5)) output 2901 <1> ; ((Modified registers: DX, CX, BX, SI, DI, BP)) 2902 <1> ; zf=1 -> block already in a I/O buffer 2903 <1> ; zf=0 -> a new I/O buffer has been allocated 2904 <1> ; ((DL = Device ID)) 2905 <1> ; (((DH = 0 or 1))) 2906 <1> ; (((CX = previous value of word ptr [bufp]))) 2907 <1> ; ((CX and DH will not be used after return))) 2908 <1> 2909 <1> ;;push esi ; *** 2910 <1> ; mov r2,-(sp) / save r2 on stack 2911 <1> ; mov $340,*$ps / set processor priority to 7 2912 <1> ; 20/07/2013 2913 <1> ; 26/04/2013 2914 <1> ;movzx ebx, byte [cdev] ; 0 or 1 2915 <1> ;mov edi, rdev ; offset mdev = offset rdev + 1 2916 <1> ;add edi, ebx 2917 <1> ; 09/01/2022 2918 0000605D 0FB63D[856E0000] <1> movzx edi, byte [cdev] ; 0 or 1 2919 00006064 81C7[866E0000] <1> add edi, rdev 2920 <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !! 2921 <1> ;; eDI points to device id. 2922 0000606A 0FB61F <1> movzx ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev 2923 <1> ; 11/06/2021 2924 0000606D 80BB[EA680000]F0 <1> cmp byte [ebx+drv.status], 0F0h ; Drive not ready ! 2925 00006074 720F <1> jb short bufaloc_9 2926 00006076 C705[186F0000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 2926 0000607E 0000 <1> 2927 00006080 E927DBFFFF <1> jmp error 2928 <1> bufaloc_9: 2929 00006085 89DA <1> mov edx, ebx ; dh = 0, dl = device number (0 to 5) 2930 <1> bufaloc_10: ; 02/07/2015 2931 00006087 31ED <1> xor ebp, ebp ; 0 2932 00006089 55 <1> push ebp ; 0 2933 0000608A 89E5 <1> mov ebp, esp 2934 <1> ; 2935 <1> bufaloc_1: ;1: 2936 <1> ; clr -(sp) / vacant buffer 2937 0000608C BE[606E0000] <1> mov esi, bufp 2938 <1> ; mov $bufp,r2 / bufp contains pointers to I/O queue 2939 <1> ; / entrys in buffer area 2940 <1> bufaloc_2: ;2: 2941 00006091 8B1E <1> mov ebx, [esi] 2942 <1> ; mov (r2)+,r5 / move pointer to word 1 of an I/O 2943 <1> ; queue entry into r5 2944 00006093 66F70300F6 <1> test word [ebx], 0F600h 2945 <1> ; bit $173000,(r5) / lock+keep+active+outstanding 2946 00006098 7503 <1> jnz short bufaloc_3 2947 <1> ; bne 3f / branch when 2948 <1> ; / any of bits 9,10,12,13,14,15 are set 2949 <1> ; / (i.e., buffer busy) 2950 0000609A 897500 <1> mov [ebp], esi ; pointer to I/0 queue entry 2951 <1> ; mov r2,(sp) ;/ save pointer to last non-busy buffer 2952 <1> ; / found points to word 2 of I/O queue entry) 2953 <1> bufaloc_3: ;3: 2954 <1> ;mov dl, [edi] ; 26/04/2013 2955 <1> ; 2956 0000609D 3813 <1> cmp [ebx], dl 2957 <1> ; cmpb (r5),cdev / is device in I/O queue entry same 2958 <1> ; / as current device 2959 0000609F 7508 <1> jne short bufaloc_4 2960 <1> ; bne 3f 2961 000060A1 394304 <1> cmp [ebx+4], eax 2962 <1> ; cmp 2(r5),r1 / is block number in I/O queue entry, 2963 <1> ; / same as current block number 2964 000060A4 7503 <1> jne short bufaloc_4 2965 <1> ; bne 3f 2966 <1> ;add esp, 4 2967 000060A6 59 <1> pop ecx 2968 <1> ; tst (sp)+ / bump stack pointer 2969 000060A7 EB20 <1> jmp short bufaloc_7 ; Retro Unix 8086 v1 modification 2970 <1> ; jump to bufaloc_6 in original Unix v1 2971 <1> ; br 1f / use this buffer 2972 <1> bufaloc_4: ;3: 2973 000060A9 83C604 <1> add esi, 4 ; 20/08/2015 2974 <1> ; 2975 000060AC 81FE[786E0000] <1> cmp esi, bufp + (nbuf*4) 2976 <1> ; cmp r2,$bufp+nbuf+nbuf 2977 000060B2 72DD <1> jb short bufaloc_2 2978 <1> ; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all 2979 <1> ; / buffers not checked) 2980 000060B4 5E <1> pop esi 2981 <1> ; mov (sp)+,r2 / once all bufs are examined move pointer 2982 <1> ; / to last free block 2983 000060B5 09F6 <1> or esi, esi 2984 000060B7 7507 <1> jnz short bufaloc_5 2985 <1> ; bne 2f / if (sp) is non zero, i.e., 2986 <1> ; / if a free buffer is found branch to 2f 2987 <1> ;; mov ecx, [s.wait_] 2988 000060B9 E831EDFFFF <1> call idle 2989 <1> ; jsr r0,idle; s.wait+2 / idle if no free buffers 2990 000060BE EBC7 <1> jmp short bufaloc_10 ; 02/07/2015 2991 <1> ; br 1b 2992 <1> bufaloc_5: ;2: 2993 <1> ; tst (r0)+ / skip if warmed over buffer 2994 000060C0 FEC6 <1> inc dh ; Retro UNIX 8086 v1 modification 2995 <1> bufaloc_6: ;1: 2996 000060C2 8B1E <1> mov ebx, [esi] 2997 <1> ; mov -(r2),r5 / put pointer to word 1 of I/O queue 2998 <1> ; / entry in r5 2999 <1> ;; 26/04/2013 3000 <1> ;mov dl, [edi] ; byte [rdev] or byte [mdev] 3001 000060C4 8813 <1> mov [ebx], dl 3002 <1> ; movb cdev,(r5) / put current device number 3003 <1> ; / in I/O queue entry 3004 000060C6 894304 <1> mov [ebx+4], eax 3005 <1> ; mov r1,2(r5) / move block number into word 2 3006 <1> ; / of I/O queue entry 3007 <1> bufaloc_7: ;1: 3008 000060C9 81FE[606E0000] <1> cmp esi, bufp 3009 <1> ; cmp r2,$bufp / bump all entrys in bufp 3010 <1> ; / and put latest assigned 3011 000060CF 760A <1> jna short bufaloc_8 3012 <1> ; blos 1f / buffer on the top 3013 <1> ; / (this makes if the lowest priority) 3014 000060D1 83EE04 <1> sub esi, 4 3015 000060D4 8B0E <1> mov ecx, [esi] 3016 000060D6 894E04 <1> mov [esi+4], ecx 3017 <1> ; mov -(r2),2(r2) / job for a particular device 3018 000060D9 EBEE <1> jmp short bufaloc_7 3019 <1> ; br 1b 3020 <1> bufaloc_8: ;1: 3021 000060DB 891E <1> mov [esi], ebx 3022 <1> ; mov r5,(r2) 3023 <1> ;;pop esi ; *** 3024 <1> ; mov (sp)+,r2 / restore r2 3025 000060DD 08F6 <1> or dh, dh ; 0 or 1 ? 3026 <1> ; Retro UNIX 8086 v1 modification 3027 <1> ; zf=1 --> block already is in an I/O buffer 3028 <1> ; zf=0 --> a new I/O buffer has been allocated 3029 000060DF C3 <1> retn 3030 <1> ; rts r0 3031 <1> 3032 <1> diskio: 3033 <1> ; 09/01/2022 (Retro UNIX 386 v1.2) 3034 <1> ; 28/11/2021 3035 <1> ; 10/07/2015 3036 <1> ; 02/07/2015 3037 <1> ; 16/06/2015 3038 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 3039 <1> ; (80386 protected mode modifications) 3040 <1> ; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1) 3041 <1> ; 3042 <1> ; Retro UNIX 8086 v1 feature only ! 3043 <1> ; 3044 <1> ; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011) 3045 <1> ; 04/07/2009 - 20/07/2011 3046 <1> ; 3047 <1> ; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes) 3048 <1> ; 3049 <1> ; INPUTS -> 3050 <1> ; ebx = System I/O Buffer header address 3051 <1> ; 3052 <1> ; OUTPUTS -> cf=0 --> done 3053 <1> ; cf=1 ---> error code in AH 3054 <1> ; 3055 <1> ; (Modified registers: eax, ecx, edx) 3056 <1> 3057 <1> ;rw_disk_sector: 3058 <1> ; 28/11/2021 3059 <1> ; 10/07/2015 3060 <1> ; 02/07/2015 3061 <1> ; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 3062 <1> ; 21/02/2015 ('dsectpm.s', 'read_disk_sector') 3063 <1> ; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s') 3064 <1> ; 01/12/2014 - 18/01/2015 ('dsectrm2.s') 3065 <1> ; 3066 <1> ;mov dx, 0201h ; Read 1 sector/block 3067 000060E0 B602 <1> mov dh, 2 3068 <1> ;mov ax, [ebx] 3069 <1> ; 28/11/2021 3070 000060E2 8B03 <1> mov eax, [ebx] 3071 <1> ; 3072 000060E4 56 <1> push esi ; **** 3073 000060E5 53 <1> push ebx ; *** 3074 <1> ; 3075 000060E6 0FB6C8 <1> movzx ecx, al 3076 <1> ; 28/11/2021 3077 <1> ;mov ecx, eax 3078 000060E9 89CE <1> mov esi, ecx 3079 <1> ; 3080 000060EB 38F1 <1> cmp cl, dh ; 2 3081 000060ED 7202 <1> jb short rwdsk0 3082 000060EF 047E <1> add al, 7Eh ; 80h, 81h, 82h, 83h 3083 <1> rwdsk0: 3084 000060F1 A2[9B680000] <1> mov [drv], al 3085 000060F6 81C6[EA680000] <1> add esi, drv.status 3086 <1> ; 11/06/2015 3087 000060FC 803EF0 <1> cmp byte [esi], 0F0h 3088 000060FF 720F <1> jb short rwdsk1 3089 <1> ; 'drive not ready' error 3090 00006101 C705[186F0000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 3090 00006109 0000 <1> 3091 0000610B E99CDAFFFF <1> jmp error 3092 <1> rwdsk1: 3093 00006110 F6C402 <1> test ah, 2 3094 <1> ;test ax, 200h ; Bit 9 of word 0 (status word) 3095 <1> ; write bit 3096 00006113 7402 <1> jz short rwdsk2 3097 <1> ;test ah, 4 3098 <1> ;;test ax, 400h ; Bit 10 of word 0 (status word) 3099 <1> ; ; read bit 3100 <1> ;jz short diskio_ret 3101 00006115 FEC6 <1> inc dh ; 03h = write 3102 <1> rwdsk2: 3103 00006117 88C2 <1> mov dl, al 3104 00006119 83C304 <1> add ebx, 4 ; sector/block address/number pointer 3105 0000611C 8B03 <1> mov eax, [ebx] ; sector/block number (LBA) 3106 0000611E C0E102 <1> shl cl, 2 3107 00006121 81C1[CE680000] <1> add ecx, drv.size ; disk size 3108 00006127 3B01 <1> cmp eax, [ecx] ; Last sector + 1 (number of secs.) 3109 00006129 720F <1> jb short rwdsk3 3110 <1> ; 'out of volume' error 3111 0000612B C705[186F0000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE 3111 00006133 0000 <1> 3112 00006135 E972DAFFFF <1> jmp error 3113 <1> rwdsk3: 3114 <1> ; 11/06/2015 3115 0000613A 83C304 <1> add ebx, 4 ; buffer address 3116 0000613D C605[3B6F0000]04 <1> mov byte [retry_count], 4 3117 00006144 F60601 <1> test byte [esi], 1 ; LBA ready ? 3118 00006147 7432 <1> jz short rwdsk_chs 3119 <1> rwdsk_lba: 3120 <1> ; LBA read/write (with private LBA function) 3121 <1> ;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan)) 3122 00006149 83C607 <1> add esi, drv.error - drv.status ; 10/07/2015 3123 0000614C 89C1 <1> mov ecx, eax ; sector number 3124 <1> ; ebx = buffer (data) address 3125 <1> ; dl = physical drive number (0,1, 80h, 81h, 82h, 83h) 3126 <1> rwdsk_lba_retry: 3127 <1> ;mov dl, [drv] 3128 <1> ; Function 1Bh = LBA read, 1Ch = LBA write 3129 0000614E B419 <1> mov ah, 1Ch - 03h ; LBA write function number - 3 3130 00006150 00F4 <1> add ah, dh 3131 00006152 B001 <1> mov al, 1 3132 <1> ;int 13h 3133 00006154 E8F5C4FFFF <1> call int13h 3134 00006159 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3135 0000615B 730E <1> jnc short rwdsk_lba_ok 3136 0000615D 80FC80 <1> cmp ah, 80h ; time out ? 3137 00006160 7408 <1> je short rwdsk_lba_fails 3138 00006162 FE0D[3B6F0000] <1> dec byte [retry_count] 3139 00006168 7504 <1> jnz short rwdsk_lba_reset ; 10/07/2015 3140 <1> rwdsk_lba_fails: 3141 0000616A F9 <1> stc 3142 <1> rwdsk_lba_ok: 3143 0000616B 5B <1> pop ebx ; *** 3144 0000616C 5E <1> pop esi ; **** 3145 0000616D C3 <1> retn 3146 <1> rwdsk_lba_reset: 3147 0000616E B40D <1> mov ah, 0Dh ; Alternate reset 3148 <1> ;int 13h 3149 00006170 E8D9C4FFFF <1> call int13h 3150 00006175 73D7 <1> jnc short rwdsk_lba_retry 3151 00006177 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3152 00006179 EBF0 <1> jmp short rwdsk_lba_ok 3153 <1> ; 3154 <1> ; CHS read (convert LBA address to CHS values) 3155 <1> rwdsk_chs: 3156 <1> ; 10/07/2015 3157 0000617B 81EE[EA680000] <1> sub esi, drv.status 3158 00006181 89F1 <1> mov ecx, esi 3159 00006183 81C6[F1680000] <1> add esi, drv.error 3160 <1> ; 02/07/2015 3161 <1> ; 16/06/2015 3162 <1> ; 11/06/2015 3163 00006189 53 <1> push ebx ; ** ; buffer 3164 0000618A D1E1 <1> shl ecx, 1 3165 0000618C 51 <1> push ecx ; * 3166 <1> ; 3167 0000618D 89CB <1> mov ebx, ecx 3168 0000618F 8835[396F0000] <1> mov [rwdsk], dh ; 02/07/2015 3169 00006195 31D2 <1> xor edx, edx ; 0 3170 <1> ; 09/01/2022 3171 <1> ;sub ecx, ecx 3172 00006197 81C3[C0680000] <1> add ebx, drv.spt 3173 0000619D 668B0B <1> mov cx, [ebx] ; sector per track 3174 <1> ; EDX:EAX = LBA 3175 <1> ; 28/11/2021 - temporary 3176 000061A0 09C9 <1> or ecx, ecx 3177 000061A2 7515 <1> jnz short bunugec1 3178 000061A4 50 <1> push eax 3179 000061A5 B44E <1> mov ah, 4Eh 3180 000061A7 B021 <1> mov al, '!' 3181 000061A9 66A300800B00 <1> mov [0B8000h], ax 3182 000061AF B9FFFFFF0F <1> mov ecx, 0FFFFFFFh 3183 <1> above4: 3184 000061B4 4A <1> dec edx 3185 000061B5 42 <1> inc edx 3186 000061B6 E2FC <1> loop above4 3187 000061B8 58 <1> pop eax 3188 <1> 3189 <1> bunugec1: 3190 <1> 3191 000061B9 F7F1 <1> div ecx 3192 000061BB 88D1 <1> mov cl, dl ; sector number - 1 3193 000061BD FEC1 <1> inc cl ; sector number (1 based) 3194 000061BF 5B <1> pop ebx ; * ; 11/06/2015 3195 <1> ;push cx 3196 000061C0 51 <1> push ecx ; 28/11/2021 3197 000061C1 81C3[B2680000] <1> add ebx, drv.heads 3198 000061C7 668B0B <1> mov cx, [ebx] ; heads 3199 000061CA 31D2 <1> xor edx, edx 3200 <1> ; EAX = cylinders * heads + head 3201 000061CC F7F1 <1> div ecx 3202 <1> ;pop cx ; sector number 3203 000061CE 59 <1> pop ecx ; 28/11/2021 3204 000061CF 88D6 <1> mov dh, dl ; head number 3205 000061D1 8A15[9B680000] <1> mov dl, [drv] 3206 000061D7 88C5 <1> mov ch, al ; cylinder (bits 0-7) 3207 000061D9 C0E406 <1> shl ah, 6 3208 000061DC 08E1 <1> or cl, ah ; cylinder (bits 8-9) 3209 <1> ; sector (bits 0-7) 3210 000061DE 5B <1> pop ebx ; ** ; buffer ; 11/06/2015 3211 <1> ; CL = sector (bits 0-5) 3212 <1> ; cylinder (bits 8-9 -> bits 6-7) 3213 <1> ; CH = cylinder (bits 0-7) 3214 <1> ; DH = head 3215 <1> ; DL = drive 3216 <1> ; 3217 000061DF C605[3B6F0000]04 <1> mov byte [retry_count], 4 3218 <1> rwdsk_retry: 3219 000061E6 8A25[396F0000] <1> mov ah, [rwdsk] ; 02h = read, 03h = write 3220 000061EC B001 <1> mov al, 1 ; sector count 3221 <1> ;int 13h 3222 000061EE E85BC4FFFF <1> call int13h 3223 000061F3 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3224 000061F5 730E <1> jnc short rwdsk_ok ; ah = 0 3225 000061F7 80FC80 <1> cmp ah, 80h ; time out ? 3226 000061FA 7408 <1> je short rwdsk_fails 3227 000061FC FE0D[3B6F0000] <1> dec byte [retry_count] 3228 00006202 7504 <1> jnz short rwdsk_reset 3229 <1> rwdsk_fails: 3230 00006204 F9 <1> stc 3231 <1> rwdsk_ok: 3232 00006205 5B <1> pop ebx ; *** 3233 00006206 5E <1> pop esi ; **** 3234 00006207 C3 <1> retn 3235 <1> rwdsk_reset: 3236 <1> ; 02/02/2015 3237 00006208 28E4 <1> sub ah, ah 3238 0000620A 80FA80 <1> cmp dl, 80h 3239 0000620D 7202 <1> jb short rwdsk_fd_reset 3240 0000620F B40D <1> mov ah, 0Dh ; Alternate reset 3241 <1> rwdsk_fd_reset: 3242 <1> ;int 13h 3243 00006211 E838C4FFFF <1> call int13h 3244 00006216 73CE <1> jnc short rwdsk_retry 3245 00006218 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3246 0000621A EBE9 <1> jmp short rwdsk_ok 3247 <1> 3248 <1> ; Original UNIX v1 - drum (& disk) interrupt routine 3249 <1> ; (Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts) 3250 <1> ; 3251 <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now. 3252 <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 3253 <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h 3254 <1> ; that uses hardware -transfer has been completed- interrupt inside it. 3255 <1> ; In a next Retro UNIX 386 version, these interrupts 3256 <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine 3257 <1> ; as in original unix v1. 3258 <1> ; I am not removing IBM BIOS source code derivatives -compatible code- 3259 <1> ; for now, regarding the new/next 32 bit TRDOS project by me 3260 <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.) 3261 <1> ; 3262 <1> ; Erdogan tan (10/07/2015) 3263 <1> 3264 <1> ;drum: / interrupt handler 3265 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 3266 <1> ; jsr r0,trapt; dcs; rfap; 1 / check for stray interrupt or 3267 <1> ; / error 3268 <1> ; br 3f / no, error 3269 <1> ; br 2f / error 3270 <1> ; 3271 <1> ;disk: 3272 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 3273 <1> ; jmp *$0f 3274 <1> ;0: 3275 <1> ; jsr r0,trapt; rkcs; rkap; 2 3276 <1> ; br 3f / no, errors 3277 <1> ; mov $115,(r2) / drive reset, errbit was set 3278 <1> ; mov $1f,0b-2 / next time jmp *$0f is executed jmp will be 3279 <1> ; / to 1f 3280 <1> ; br 4f 3281 <1> ;1: 3282 <1> ; bit $20000,rkcs 3283 <1> ; beq 4f / wait for seek complete 3284 <1> ; mov $0b,0b-2 3285 <1> ; mov rkap,r1 3286 <1> ;2: 3287 <1> ; bit $3000,(r1) / are bits 9 or 10 set in the 1st word of 3288 <1> ; / the disk buffer 3289 <1> ; bne 3f / no, branch ignore error if outstanding 3290 <1> ; inc r1 3291 <1> ; asr (r1) 3292 <1> ; asr (r1) 3293 <1> ; asr (r1) / reissue request 3294 <1> ; dec r1 3295 <1> ;3: 3296 <1> ; bic $30000,(r1) / clear bits 12 and 13 in 1st word of buffer 3297 <1> ; mov ac,-(sp) 3298 <1> ; mov mq,-(sp) / put these on the stack 3299 <1> ; mov sc,-(sp) 3300 <1> ; jsr r0,poke 3301 <1> ; mov (sp)+,sc 3302 <1> ; mov (sp)+,mq / pop them off stack 3303 <1> ; mov (sp)+,ac 3304 <1> ;4: 3305 <1> ; jmp retisp / u4-3 3306 <1> ; 3307 <1> ;trapt: / r2 points to the 3308 <1> ; mov (r0)+,r2 / device control register 3309 <1> ; mov *(r0)+,r1 / transaction pointer points to buffer 3310 <1> ; tst (sp)+ 3311 <1> ; tstb (r2) / is ready bit of dcs set? 3312 <1> ; bge 4b / device still active so branch 3313 <1> ; bit (r0),active / was device busy? 3314 <1> ; beq 4b / no, stray interrupt 3315 <1> ; bic (r0)+,active / yes, set active to zero 3316 <1> ; tst (r2) / test the err(bit is) of dcs 3317 <1> ; bge 2f / if no error jump to 2f 3318 <1> ; tst (r0)+ / skip on error 3319 <1> ; 2: 3320 <1> ; jmp (r0) 2084 %include 'u9.s' ; 29/06/2015 2085 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2086 <1> ; (re-write kernel for test by using previous version without a major defect) 2087 <1> ; **************************************************************************** 2088 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS9.INC 2089 <1> ; Last Modification: 24/12/2021 2090 <1> ; ---------------------------------------------------------------------------- 2091 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2092 <1> ; (v0.1 - Beginning: 11/07/2012) 2093 <1> ; 2094 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2095 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2096 <1> ; 2097 <1> ; 2098 <1> ; 2099 <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s 2100 <1> ; 2101 <1> ; **************************************************************************** 2102 <1> 2103 <1> getch: 2104 <1> ; 30/06/2015 2105 <1> ; 18/02/2015 - Retro UNIX 386 v1 - feature only! 2106 0000621C 28C0 <1> sub al, al ; 0 2107 <1> getch_q: ; 06/08/2015 2108 0000621E 8A25[D66D0000] <1> mov ah, [ptty] ; active (current) video page 2109 00006224 EB06 <1> jmp short getc_n 2110 <1> 2111 <1> getc: 2112 <1> ; 12/11/2015 2113 <1> ; 15/09/2015 2114 <1> ; 01/07/2015 2115 <1> ; 30/06/2015 2116 <1> ; 18/02/2015 (Retro UNIX 386 v1 - Beginning) 2117 <1> ; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1) 2118 <1> ; 2119 <1> ; Retro UNIX 8086 v1 modification ! 2120 <1> ; 2121 <1> ; 'getc' gets (next) character 2122 <1> ; from requested TTY (keyboard) buffer 2123 <1> ; INPUTS -> 2124 <1> ; [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2) 2125 <1> ; AL=0 -> Get (next) character from requested TTY buffer 2126 <1> ; (Keyboard buffer will point to 2127 <1> ; next character at next call) 2128 <1> ; AL=1 -> Test a key is available in requested TTY buffer 2129 <1> ; (Keyboard buffer will point to 2130 <1> ; current character at next call) 2131 <1> ; OUTPUTS -> 2132 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 2133 <1> ; ZF=0 -> AX has (current) character 2134 <1> ; AL = ascii code 2135 <1> ; AH = scan code (AH = line status for COM1 or COM2) 2136 <1> ; (cf=1 -> error code/flags in AH) 2137 <1> ; Original UNIX V1 'getc': 2138 <1> ; get a character off character list 2139 <1> ; 2140 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2141 <1> ; 2142 <1> ; 30/06/20045 (32 bit modifications) 2143 <1> ; 16/07/2013 2144 <1> ; mov [getctty], ah 2145 <1> ; 2146 <1> 2147 00006226 8A25[D96E0000] <1> mov ah, [u.ttyn] ; 28/07/2013 2148 <1> getc_n: 2149 <1> ; 30/06/2015 2150 0000622C 08E4 <1> or ah, ah 2151 0000622E 740D <1> jz short getc0 2152 00006230 D0E4 <1> shl ah, 1 2153 00006232 0FB6DC <1> movzx ebx, ah 2154 00006235 81C3[D86D0000] <1> add ebx, ttychr 2155 0000623B EB05 <1> jmp short getc1 2156 <1> getc0: 2157 0000623D BB[D86D0000] <1> mov ebx, ttychr 2158 <1> getc1: 2159 00006242 668B0B <1> mov cx, [ebx] ; ascii & scan code 2160 <1> ; (by kb_int) 2161 00006245 6609C9 <1> or cx, cx 2162 00006248 7507 <1> jnz short getc2 2163 0000624A 20C0 <1> and al, al 2164 0000624C 7415 <1> jz short getc_s 2165 <1> ;xor ax, ax 2166 <1> ; 30/11/2021 2167 0000624E 31C0 <1> xor eax, eax 2168 00006250 C3 <1> retn 2169 <1> getc2: 2170 00006251 20C0 <1> and al, al 2171 00006253 6689C8 <1> mov ax, cx 2172 00006256 66B90000 <1> mov cx, 0 2173 0000625A 7506 <1> jnz short getc3 2174 <1> getc_sn: 2175 0000625C 66890B <1> mov [ebx], cx ; 0, reset 2176 0000625F 6639C8 <1> cmp ax, cx ; zf = 0 2177 <1> getc3: 2178 00006262 C3 <1> retn 2179 <1> getc_s: 2180 <1> ; 12/11/2015 2181 <1> ; 15/09/2015 2182 <1> ; 01/07/2015 2183 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2184 <1> ; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2185 <1> ; 2186 <1> ; tty of the current process is not 2187 <1> ; current tty (ptty); so, current process only 2188 <1> ; can use keyboard input when its tty becomes 2189 <1> ; current tty (ptty). 2190 <1> ; 'sleep' is for preventing an endless lock 2191 <1> ; during this tty input request. 2192 <1> ; (Because, the user is not looking at the video page 2193 <1> ; of the process to undersand there is a keyboard 2194 <1> ; input request.) 2195 <1> ; 2196 <1> ;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2197 <1> ; 2198 <1> ; 05/10/2013 2199 <1> ; ah = byte ptr [u.ttyn] ; (tty number) 2200 <1> ; 2201 <1> ; 10/10/2013 2202 <1> gcw0: 2203 00006263 B10A <1> mov cl, 10 ; ch = 0 2204 <1> gcw1: 2205 <1> ; 12/11/2015 2206 00006265 E862DAFFFF <1> call intract ; jumps to 'sysexit' if [u.quit] = FFFFh 2207 <1> ; 10/10/2013 2208 0000626A E880EBFFFF <1> call idle 2209 0000626F 668B03 <1> mov ax, [ebx] ; ascii & scan code 2210 <1> ; (by kb_int) 2211 00006272 6609C0 <1> or ax, ax 2212 <1> ; jnz short gcw3 2213 00006275 7519 <1> jnz short gcw2 ; 15/09/2015 2214 <1> ; 30/06/2015 2215 00006277 FEC9 <1> dec cl 2216 00006279 75EA <1> jnz short gcw1 2217 <1> ; 2218 0000627B 8A25[D96E0000] <1> mov ah, [u.ttyn] ; 20/10/2013 2219 <1> ; ; 10/12/2013 2220 <1> ; cmp ah, [ptty] 2221 <1> ; jne short gcw2 2222 <1> ; ; 14/02/2014 2223 <1> ; cmp byte [u.uno], 1 2224 <1> ; jna short gcw0 2225 <1> ;gcw2: 2226 00006281 E8FCEBFFFF <1> call sleep 2227 <1> ; 2228 <1> ; 20/09/2013 2229 00006286 8A25[D96E0000] <1> mov ah, [u.ttyn] 2230 0000628C 30C0 <1> xor al, al 2231 0000628E EB9C <1> jmp short getc_n 2232 <1> ;gcw3: 2233 <1> gcw2: ; 15/09/2015 2234 <1> ; 10/10/2013 2235 00006290 30C9 <1> xor cl, cl 2236 00006292 EBC8 <1> jmp short getc_sn 2237 <1> 2238 <1> putc: 2239 <1> ; 05/12/2021 (Retro UNIX 386 v1.2) 2240 <1> ; 13/08/2015 2241 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2242 <1> ; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1) 2243 <1> ; 2244 <1> ; Retro UNIX 8086 v1 modification ! 2245 <1> ; 2246 <1> ; 'putc' puts a character 2247 <1> ; onto requested (tty) video page or 2248 <1> ; serial port 2249 <1> ; INPUTS -> 2250 <1> ; AL = ascii code of the character 2251 <1> ; AH = video page (tty) number (0 to 7) 2252 <1> ; (8 is COM1, 9 is COM2) 2253 <1> ; OUTPUTS -> 2254 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 2255 <1> ; ZF=0 -> AX has (current) character 2256 <1> ; cf=0 and AH = 0 -> no error 2257 <1> ; cf=1 and AH > 0 -> error (only for COM1 and COM2) 2258 <1> ; 2259 <1> ; Original UNIX V1 'putc': 2260 <1> ; put a character at the end of character list 2261 <1> ; 2262 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2263 <1> ; 2264 00006294 80FC07 <1> cmp ah, 7 2265 00006297 770A <1> ja short sndc ; 05/12/2021 2266 <1> ; 30/06/2015 2267 00006299 0FB6DC <1> movzx ebx, ah 2268 <1> ; 13/08/2015 2269 0000629C B407 <1> mov ah, 07h ; black background, light gray character color 2270 0000629E E919B1FFFF <1> jmp write_tty ; 'video.inc' 2271 <1> 2272 <1> sndc: ; 2273 <1> ; 2274 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 2275 <1> ; 17/11/2015 2276 <1> ; 16/11/2015 2277 <1> ; 11/11/2015 2278 <1> ; 10/11/2015 2279 <1> ; 09/11/2015 2280 <1> ; 08/11/2015 2281 <1> ; 07/11/2015 2282 <1> ; 06/11/2015 (serial4.asm, 'sendchr') 2283 <1> ; 29/10/2015 2284 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2285 <1> ; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1) 2286 <1> ; 2287 <1> ; Retro UNIX 8086 v1 feature only ! 2288 <1> ; 2289 <1> ; ah = [u.ttyn] 2290 <1> ; 2291 <1> ; 30/06/2015 2292 000062A3 80EC08 <1> sub ah, 8 ; ; 0 = tty8 or 1 = tty9 2293 <1> ; 07/11/2015 2294 000062A6 0FB6DC <1> movzx ebx, ah ; serial port index (0 or 1) 2295 <1> sndc0: 2296 <1> ; 07/11/2015 2297 000062A9 E82AECFFFF <1> call isintr ; quit (ctrl+break) check 2298 000062AE 7405 <1> jz short sndc1 2299 000062B0 E817DAFFFF <1> call intract ; quit (ctrl+break) check 2300 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 2301 <1> sndc1: 2302 <1> ; 16/11/2015 2303 <1> ;mov cx, ax ; *** al = character (to be sent) 2304 <1> ; 24/12/2021 2305 000062B5 89C1 <1> mov ecx, eax ; *** al = character (to be sent) 2306 <1> sndcx: 2307 000062B7 8A83[1A6E0000] <1> mov al, [ebx+schar] ; last sent character 2308 000062BD 8AA3[186E0000] <1> mov ah, [ebx+rchar] ; last received character 2309 <1> ; 2310 <1> ; 17/11/2015 2311 <1> ; check 'request for response' status 2312 000062C3 80BB[146E0000]00 <1> cmp byte [ebx+req_resp], 0 2313 000062CA 740A <1> jz short query 2314 <1> response: 2315 000062CC FE05[176E0000] <1> inc byte [comqr] ; query or response status 2316 000062D2 B0FF <1> mov al, 0FFh 2317 000062D4 EB14 <1> jmp short sndc3 2318 <1> query: 2319 000062D6 08C0 <1> or al, al ; 0 = query (also end of text) 2320 000062D8 750E <1> jnz short sndc2 ; normal character 2321 <1> ;cmp ah, 0FFh ; is it responded by terminal ? 2322 <1> ;je short sndc2 ; yes, already responded 2323 <1> ; 16/11/2015 2324 <1> ; query: request for response (again) 2325 000062DA 8883[186E0000] <1> mov [ebx+rchar], al ; 0 ; reset 2326 000062E0 FE05[176E0000] <1> inc byte [comqr] ; query or response status 2327 000062E6 EB02 <1> jmp short sndc3 2328 <1> sndc2: 2329 000062E8 88C8 <1> mov al, cl ; *** character (to be sent) 2330 <1> sndc3: 2331 000062EA 8883[1A6E0000] <1> mov [ebx+schar], al ; current character (to be sent) 2332 000062F0 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 2333 <1> ; 30/06/2015 2334 000062F2 E837D3FFFF <1> call sp_status ; get serial port status 2335 <1> ; AL = Line status, AH = Modem status 2336 <1> ; 07/11/2015 2337 000062F7 A880 <1> test al, 80h 2338 000062F9 7504 <1> jnz short sndc4 2339 000062FB A820 <1> test al, 20h ; Transmitter holding register empty ? 2340 000062FD 751B <1> jnz short sndc5 2341 <1> sndc4: ; Check line status again 2342 <1> ; 16/11/2015 2343 <1> ;push cx 2344 <1> ; 24/12/2021 2345 000062FF 51 <1> push ecx 2346 00006300 B906000000 <1> mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 2347 00006305 E8C1B1FFFF <1> call WAITF 2348 <1> ;pop cx 2349 <1> ; 24/12/1021 2350 0000630A 59 <1> pop ecx 2351 <1> ; 2352 0000630B 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 2353 0000630D E81CD3FFFF <1> call sp_status ; get serial port status 2354 <1> ; 16/11/2015 2355 <1> ; 09/11/2015 2356 <1> ; 08/11/2015 2357 00006312 A880 <1> test al, 80h ; time out error 2358 00006314 7566 <1> jnz short sndc7 2359 00006316 A820 <1> test al, 20h ; Transmitter holding register empty ? 2360 00006318 7462 <1> jz short sndc7 2361 <1> sndc5: 2362 0000631A 8A83[1A6E0000] <1> mov al, [ebx+schar] ; character (to be sent) 2363 00006320 66BAF803 <1> mov dx, 3F8h ; data port (COM2) 2364 00006324 28DE <1> sub dh, bl 2365 00006326 EE <1> out dx, al ; send on serial port 2366 <1> ; 10/11/2015 2367 <1> ; delay for 3*30 (3*(15..80)) micro seconds 2368 <1> ; (to improve text flow to the terminal) 2369 <1> ; ('diskette.inc': 'WAITF') 2370 <1> ; Uses port 61h, bit 4 to have CPU speed independent waiting. 2371 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2372 <1> ;push cx 2373 <1> ; 24/12/2021 2374 00006327 51 <1> push ecx 2375 00006328 B906000000 <1> mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 2376 0000632D E899B1FFFF <1> call WAITF 2377 <1> ;pop cx 2378 <1> ; 24/12/1021 2379 00006332 59 <1> pop ecx 2380 <1> ; 2381 <1> ; 07/11/2015 2382 00006333 88D8 <1> mov al, bl ; al = 0 (tty8) or 1 (tty9) 2383 <1> ; 2384 00006335 E8F4D2FFFF <1> call sp_status ; get serial port status 2385 <1> ; AL = Line status, AH = Modem status 2386 <1> ; 2387 0000633A E899EBFFFF <1> call isintr ; quit (ctrl+break) check 2388 0000633F 7405 <1> jz short sndc6 2389 00006341 E886D9FFFF <1> call intract ; quit (ctrl+break) check 2390 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 2391 <1> sndc6: 2392 00006346 3C80 <1> cmp al, 80h 2393 00006348 7332 <1> jnb short sndc7 2394 <1> ; 2395 0000634A 803D[176E0000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 2396 00006351 7244 <1> jb short sndc8 ; no, normal character 2397 00006353 883D[176E0000] <1> mov byte [comqr], bh ; 0 ; reset 2398 <1> ; 17/11/2015 2399 00006359 E891EAFFFF <1> call idle 2400 <1> ; 2401 0000635E 38BB[1A6E0000] <1> cmp [ebx+schar], bh ; 0 ; query ? 2402 <1> ;ja sndc2 ; response (will be followed by 2403 <1> ; a normal character) 2404 <1> ; 24/12/2021 2405 00006364 7602 <1> jna short sndc_10 2406 00006366 EB80 <1> jmp sndc2 2407 <1> sndc_10: 2408 <1> ; Query request must be responded by the terminal 2409 <1> ; before sending a normal character ! 2410 00006368 53 <1> push ebx 2411 <1> ;push cx ; *** cl = character (to be sent) 2412 <1> ; 24/12/2021 2413 00006369 51 <1> push ecx ; *** cl = character (to be sent) 2414 0000636A 8A25[D96E0000] <1> mov ah, [u.ttyn] 2415 00006370 E80DEBFFFF <1> call sleep ; this process will be awakened by 2416 <1> ; received data available interrupt 2417 <1> ;pop cx ; *** cl = character (to be sent) 2418 <1> ; 24/12/2021 2419 00006375 59 <1> pop ecx ; *** cl = character (to be sent) 2420 00006376 5B <1> pop ebx 2421 00006377 E93BFFFFFF <1> jmp sndcx 2422 <1> sndc7: 2423 <1> ; 16/11/2015 2424 0000637C 803D[176E0000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 2425 00006383 7213 <1> jb short sndc9 ; no 2426 <1> ; 2427 00006385 88BB[186E0000] <1> mov [ebx+rchar], bh ; 0 ; reset 2428 0000638B 88BB[1A6E0000] <1> mov [ebx+schar], bh ; 0 ; reset 2429 <1> ; 2430 00006391 883D[176E0000] <1> mov byte [comqr], bh ; 0 ; reset 2431 <1> sndc8: 2432 00006397 F5 <1> cmc ; jnc -> jc, jb -> jnb 2433 <1> sndc9: 2434 <1> ; AL = Line status, AH = Modem status 2435 00006398 C3 <1> retn 2436 <1> 2437 <1> get_cpos: 2438 <1> ; 29/06/2015 (Retro UNIX 386 v1) 2439 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 2440 <1> ; 2441 <1> ; INPUT -> bl = video page number 2442 <1> ; RETURN -> dx = cursor position 2443 <1> 2444 00006399 53 <1> push ebx 2445 0000639A 83E30F <1> and ebx, 0Fh ; 07h ; tty0 to tty7 2446 0000639D D0E3 <1> shl bl, 1 2447 0000639F 81C3[C66D0000] <1> add ebx, cursor_posn 2448 000063A5 668B13 <1> mov dx, [ebx] 2449 000063A8 5B <1> pop ebx 2450 000063A9 C3 <1> retn 2451 <1> 2452 <1> read_ac_current: 2453 <1> ; 29/06/2015 (Retro UNIX 386 v1) 2454 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 2455 <1> ; 2456 <1> ; INPUT -> bl = video page number 2457 <1> ; RETURN -> ax = character (al) and attribute (ah) 2458 <1> 2459 000063AA E88BB1FFFF <1> call find_position ; 'video.inc' 2460 <1> ; dx = status port 2461 <1> ; esi = cursor location/address 2462 000063AF 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 2463 000063B5 668B06 <1> mov ax, [esi] ; get the character and attribute 2464 000063B8 C3 <1> retn 2465 <1> 2466 <1> syssleep: 2467 <1> ; 29/06/2015 - (Retro UNIX 386 v1) 2468 <1> ; 11/06/2014 - (Retro UNIX 8086 v1) 2469 <1> ; 2470 <1> ; Retro UNIX 8086 v1 feature only 2471 <1> ; (INPUT -> none) 2472 <1> ; 2473 000063B9 0FB61D[F56E0000] <1> movzx ebx, byte [u.uno] ; process number 2474 000063C0 8AA3[DF6B0000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 2475 000063C6 E8B7EAFFFF <1> call sleep 2476 000063CB E9FCD7FFFF <1> jmp sysret 2477 <1> 2478 <1> vp_clr: 2479 <1> ; Reset/Clear Video Page 2480 <1> ; 2481 <1> ; 05/12/2021 - (Retro UNIX 386 v1.2) 2482 <1> ; 30/06/2015 - (Retro UNIX 386 v1) 2483 <1> ; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM) 2484 <1> ; 2485 <1> ; Retro UNIX 8086 v1 feature only ! 2486 <1> ; 2487 <1> ; INPUTS -> 2488 <1> ; BL = video page number 2489 <1> ; 2490 <1> ; OUTPUT -> 2491 <1> ; none 2492 <1> ; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI)) 2493 <1> ; 2494 <1> ; 04/12/2013 2495 000063D0 28C0 <1> sub al, al 2496 <1> ; al = 0 (clear video page) 2497 <1> ; bl = video page 2498 000063D2 B407 <1> mov ah, 07h 2499 <1> ; ah = 7 (attribute/color) 2500 <1> ;xor cx, cx ; 0, left upper column (cl) & row (cl) 2501 <1> ; 05/12/2021 2502 000063D4 31C9 <1> xor ecx, ecx 2503 000063D6 66BA4F18 <1> mov dx, 184Fh ; right lower column & row (dl=24, dh=79) 2504 000063DA E885B1FFFF <1> call scroll_up 2505 <1> ; bl = video page 2506 <1> ;xor dx, dx ; 0 (cursor position) 2507 <1> ; 05/12/2021 2508 000063DF 31D2 <1> xor edx, edx 2509 000063E1 E9F8B0FFFF <1> jmp set_cpos 2510 <1> 2511 <1> sysmsg: 2512 <1> ; 11/12/2021 2513 <1> ; 04/12/2021 (Retro UNIX 386 v1.2) 2514 <1> ; 11/11/2015 2515 <1> ; 01/07/2015 - (Retro UNIX 386 v1 feature only!) 2516 <1> ; Print user-application message on user's console tty 2517 <1> ; 2518 <1> ; Input -> EBX = Message address 2519 <1> ; ECX = Message length (max. 255) 2520 <1> ; DL = Color (IBM PC Rombios color attributes) 2521 <1> ; 2522 000063E6 81F9FF000000 <1> cmp ecx, MAX_MSG_LEN ; 255 2523 <1> ;ja sysret ; nothing to do with big message size 2524 000063EC 7779 <1> ja short sysmsg8 ; 11/12/2021 2525 000063EE 08C9 <1> or cl, cl 2526 <1> ;jz sysret 2527 000063F0 7475 <1> jz short sysmsg8 ; 11/12/2021 2528 000063F2 20D2 <1> and dl, dl 2529 000063F4 7502 <1> jnz short sysmsg0 2530 000063F6 B207 <1> mov dl, 07h ; default color 2531 <1> ; (black background, light gray character) 2532 <1> sysmsg0: 2533 000063F8 891D[C86E0000] <1> mov [u.base], ebx 2534 000063FE 8815[D76D0000] <1> mov [ccolor], dl ; color attributes 2535 00006404 89E5 <1> mov ebp, esp 2536 00006406 31DB <1> xor ebx, ebx ; 0 2537 00006408 891D[D06E0000] <1> mov [u.nread], ebx ; 0 2538 <1> ; 2539 0000640E 381D[166F0000] <1> cmp [u.kcall], bl ; 0 2540 00006414 7772 <1> ja short sysmsgk ; Temporary (01/07/2015) 2541 <1> ; 2542 00006416 890D[CC6E0000] <1> mov [u.count], ecx 2543 0000641C 41 <1> inc ecx ; + 00h ; ASCIIZ ; 04/12/2021 2544 <1> ; 04/12/2021 2545 <1> ; (dword alignment for esp) 2546 0000641D F6C103 <1> test cl, 3 2547 00006420 7404 <1> jz short sysmsg_7 2548 00006422 80C903 <1> or cl, 3 2549 00006425 41 <1> inc ecx 2550 <1> sysmsg_7: 2551 00006426 29CC <1> sub esp, ecx 2552 00006428 89E7 <1> mov edi, esp 2553 0000642A 89E6 <1> mov esi, esp 2554 0000642C 66891D[106F0000] <1> mov [u.pcount], bx ; reset page (phy. addr.) counter 2555 <1> ; 11/11/2015 2556 00006433 8A25[DA6E0000] <1> mov ah, [u.ttyp] ; recent open tty 2557 <1> ; 0 = none 2558 00006439 FECC <1> dec ah 2559 0000643B 790C <1> jns short sysmsg1 2560 0000643D 8A1D[F56E0000] <1> mov bl, [u.uno] ; process number 2561 00006443 8AA3[DF6B0000] <1> mov ah, [ebx+p.ttyc-1] ; user's (process's) console tty 2562 <1> sysmsg1: 2563 00006449 8825[D96E0000] <1> mov [u.ttyn], ah 2564 <1> sysmsg2: 2565 0000644F E837F5FFFF <1> call cpass 2566 00006454 7416 <1> jz short sysmsg5 2567 00006456 AA <1> stosb 2568 00006457 20C0 <1> and al, al 2569 00006459 75F4 <1> jnz short sysmsg2 2570 <1> sysmsg3: 2571 0000645B 80FC07 <1> cmp ah, 7 ; tty number 2572 0000645E 7711 <1> ja short sysmsg6 ; serial port 2573 00006460 E83E000000 <1> call print_cmsg 2574 <1> sysmsg4: 2575 00006465 89EC <1> mov esp, ebp 2576 <1> sysmsg8: ; 11/12/2021 2577 00006467 E960D7FFFF <1> jmp sysret 2578 <1> sysmsg5: 2579 0000646C C60700 <1> mov byte [edi], 0 2580 0000646F EBEA <1> jmp short sysmsg3 2581 <1> sysmsg6: 2582 00006471 8A06 <1> mov al, [esi] 2583 00006473 E82BFEFFFF <1> call sndc 2584 00006478 72EB <1> jc short sysmsg4 2585 0000647A 803E00 <1> cmp byte [esi], 0 ; 0 is stop character 2586 0000647D 76E6 <1> jna short sysmsg4 2587 0000647F 46 <1> inc esi 2588 00006480 8A25[D96E0000] <1> mov ah, [u.ttyn] 2589 00006486 EBE9 <1> jmp short sysmsg6 2590 <1> 2591 <1> sysmsgk: ; Temporary (01/07/2015) 2592 <1> ; The message has been sent by Kernel (ASCIIZ string) 2593 <1> ; (ECX -character count- will not be considered) 2594 00006488 8B35[C86E0000] <1> mov esi, [u.base] 2595 0000648E 8A25[D66D0000] <1> mov ah, [ptty] ; present/current screen (video page) 2596 00006494 8825[D96E0000] <1> mov [u.ttyn], ah 2597 0000649A C605[166F0000]00 <1> mov byte [u.kcall], 0 2598 000064A1 EBB8 <1> jmp short sysmsg3 2599 <1> 2600 <1> print_cmsg: 2601 <1> ; 01/07/2015 (retro UNIX 386 v1 feature only !) 2602 <1> ; 2603 <1> ; print message (on user's console tty) 2604 <1> ; with requested color 2605 <1> ; 2606 <1> ; INPUTS: 2607 <1> ; esi = message address 2608 <1> ; [u.ttyn] = tty number (0 to 7) 2609 <1> ; [ccolor] = color attributes (IBM PC BIOS colors) 2610 <1> ; 2611 000064A3 AC <1> lodsb 2612 <1> pcmsg1: 2613 000064A4 56 <1> push esi 2614 000064A5 0FB61D[D96E0000] <1> movzx ebx, byte [u.ttyn] 2615 000064AC 8A25[D76D0000] <1> mov ah, [ccolor] 2616 000064B2 E805AFFFFF <1> call write_tty 2617 000064B7 5E <1> pop esi 2618 000064B8 AC <1> lodsb 2619 000064B9 20C0 <1> and al, al ; 0 2620 000064BB 75E7 <1> jnz short pcmsg1 2621 000064BD C3 <1> retn 2622 <1> 2623 <1> sysgeterr: 2624 <1> ; 09/12/2015 2625 <1> ; 21/09/2015 - (Retro UNIX 386 v1 feature only!) 2626 <1> ; Get last error number or page fault count 2627 <1> ; (for debugging) 2628 <1> ; 2629 <1> ; Input -> EBX = return type 2630 <1> ; 0 = last error code (which is in 'u.error') 2631 <1> ; FFFFFFFFh = page fault count for running process 2632 <1> ; FFFFFFFEh = total page fault count 2633 <1> ; 1 .. FFFFFFFDh = undefined 2634 <1> ; 2635 <1> ; Output -> EAX = last error number or page fault count 2636 <1> ; (depending on EBX input) 2637 <1> ; 2638 000064BE 21DB <1> and ebx, ebx 2639 000064C0 750B <1> jnz short glerr_2 2640 <1> glerr_0: 2641 000064C2 A1[186F0000] <1> mov eax, [u.error] 2642 <1> glerr_1: 2643 000064C7 A3[A46E0000] <1> mov [u.r0], eax 2644 000064CC C3 <1> retn 2645 <1> glerr_2: 2646 000064CD 43 <1> inc ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh 2647 000064CE 74FD <1> jz short glerr_2 ; page fault count for process 2648 000064D0 43 <1> inc ebx ; FFFFFFFFh -> 0 2649 000064D1 75EF <1> jnz short glerr_0 2650 000064D3 A1[606E0000] <1> mov eax, [PF_Count] ; total page fault count 2651 000064D8 EBED <1> jmp short glerr_1 2652 <1> glerr_3: 2653 000064DA A1[1C6F0000] <1> mov eax, [u.pfcount] 2654 000064DF EBE6 <1> jmp short glerr_1 2085 2086 ; 07/03/2015 2087 ; Temporary Code 2088 display_disks: 2089 000064E1 803D[9E680000]00 cmp byte [fd0_type], 0 2090 000064E8 7605 jna short ddsks1 2091 000064EA E87D000000 call pdskm 2092 ddsks1: 2093 000064EF 803D[9F680000]00 cmp byte [fd1_type], 0 2094 000064F6 760C jna short ddsks2 2095 000064F8 C605[8F6A0000]31 mov byte [dskx], '1' 2096 000064FF E868000000 call pdskm 2097 ddsks2: 2098 00006504 803D[A0680000]00 cmp byte [hd0_type], 0 2099 0000650B 7654 jna short ddsk6 2100 0000650D 66C705[8D6A0000]68- mov word [dsktype], 'hd' 2100 00006515 64 2101 00006516 C605[8F6A0000]30 mov byte [dskx], '0' 2102 0000651D E84A000000 call pdskm 2103 ddsks3: 2104 00006522 803D[A1680000]00 cmp byte [hd1_type], 0 2105 00006529 7636 jna short ddsk6 2106 0000652B C605[8F6A0000]31 mov byte [dskx], '1' 2107 00006532 E835000000 call pdskm 2108 ddsks4: 2109 00006537 803D[A2680000]00 cmp byte [hd2_type], 0 2110 0000653E 7621 jna short ddsk6 2111 00006540 C605[8F6A0000]32 mov byte [dskx], '2' 2112 00006547 E820000000 call pdskm 2113 ddsks5: 2114 0000654C 803D[A3680000]00 cmp byte [hd3_type], 0 2115 00006553 760C jna short ddsk6 2116 00006555 C605[8F6A0000]33 mov byte [dskx], '3' 2117 0000655C E80B000000 call pdskm 2118 ddsk6: 2119 00006561 BE[9E6A0000] mov esi, nextline 2120 00006566 E806000000 call pdskml 2121 pdskm_ok: 2122 0000656B C3 retn 2123 pdskm: 2124 0000656C BE[8B6A0000] mov esi, dsk_ready_msg 2125 pdskml: 2126 00006571 AC lodsb 2127 00006572 08C0 or al, al 2128 00006574 74F5 jz short pdskm_ok 2129 00006576 56 push esi 2130 00006577 31DB xor ebx, ebx ; 0 2131 ; Video page 0 (bl=0) 2132 00006579 B407 mov ah, 07h ; Black background, 2133 ; light gray forecolor 2134 0000657B E83CAEFFFF call write_tty 2135 00006580 5E pop esi 2136 00006581 EBEE jmp short pdskml 2137 2138 00006583 90 align 16 2139 2140 gdt: ; Global Descriptor Table 2141 ; (30/07/2015, conforming cs) 2142 ; (26/03/2015) 2143 ; (24/03/2015, tss) 2144 ; (19/03/2015) 2145 ; (29/12/2013) 2146 ; 2147 00006590 0000000000000000 dw 0, 0, 0, 0 ; NULL descriptor 2148 ; 18/08/2014 2149 ; 8h kernel code segment, base = 00000000h 2150 00006598 FFFF0000009ACF00 dw 0FFFFh, 0, 9A00h, 00CFh ; KCODE 2151 ; 10h kernel data segment, base = 00000000h 2152 000065A0 FFFF00000092CF00 dw 0FFFFh, 0, 9200h, 00CFh ; KDATA 2153 ; 1Bh user code segment, base address = 400000h ; CORE 2154 000065A8 FFFB000040FACF00 dw 0FBFFh, 0, 0FA40h, 00CFh ; UCODE 2155 ; 23h user data segment, base address = 400000h ; CORE 2156 000065B0 FFFB000040F2CF00 dw 0FBFFh, 0, 0F240h, 00CFh ; UDATA 2157 ; Task State Segment 2158 000065B8 6700 dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 2159 ; no IO permission in ring 3) 2160 gdt_tss0: 2161 000065BA 0000 dw 0 ; TSS base address, bits 0-15 2162 gdt_tss1: 2163 000065BC 00 db 0 ; TSS base address, bits 16-23 2164 ; 49h 2165 000065BD E9 db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1) 2166 000065BE 00 db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte) 2167 gdt_tss2: 2168 000065BF 00 db 0 ; TSS base address, bits 24-31 2169 2170 gdt_end: 2171 ;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 2172 ;; Type= 1 (code)/C=0/R=1/A=0 2173 ; P= Present, DPL=0=ring 0, 1= user (0= system) 2174 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 2175 2176 ;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 2177 ;; Type= 0 (data)/E=0/W=1/A=0 2178 ; P= Present, DPL=0=ring 0, 1= user (0= system) 2179 ; 0= Data E= Expansion direction (1= down, 0= up) 2180 ; W= Writeable, A= Accessed 2181 2182 ;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 2183 ;; Type= 1 (code)/C=0/R=1/A=0 2184 ; P= Present, DPL=3=ring 3, 1= user (0= system) 2185 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 2186 2187 ;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 2188 ;; Type= 0 (data)/E=0/W=1/A=0 2189 ; P= Present, DPL=3=ring 3, 1= user (0= system) 2190 ; 0= Data E= Expansion direction (1= down, 0= up) 2191 2192 ;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3) 2193 2194 ;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 // 2195 ; = 100000h * 1000h (G=1) = 4GB 2196 ;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 // 2197 ; = FFC00h * 1000h (G=1) = 4GB - 4MB 2198 ; G= Granularity (1= 4KB), B= Big (32 bit), 2199 ; AVL= Available to programmers 2200 2201 gdtd: 2202 000065C0 2F00 dw gdt_end - gdt - 1 ; Limit (size) 2203 000065C2 [90650000] dd gdt ; Address of the GDT 2204 2205 ; 20/08/2014 2206 idtd: 2207 000065C6 FF01 dw idt_end - idt - 1 ; Limit (size) 2208 000065C8 [406B0000] dd idt ; Address of the IDT 2209 2210 Align 4 2211 2212 ; 21/08/2014 2213 ilist: 2214 ;times 32 dd cpu_except ; INT 0 to INT 1Fh 2215 ; 2216 ; Exception list 2217 ; 25/08/2014 2218 000065CC [20080000] dd exc0 ; 0h, Divide-by-zero Error 2219 000065D0 [27080000] dd exc1 2220 000065D4 [2E080000] dd exc2 2221 000065D8 [35080000] dd exc3 2222 000065DC [39080000] dd exc4 2223 000065E0 [3D080000] dd exc5 2224 000065E4 [41080000] dd exc6 ; 06h, Invalid Opcode 2225 000065E8 [45080000] dd exc7 2226 000065EC [49080000] dd exc8 2227 000065F0 [4D080000] dd exc9 2228 000065F4 [51080000] dd exc10 2229 000065F8 [55080000] dd exc11 2230 000065FC [59080000] dd exc12 2231 00006600 [5D080000] dd exc13 ; 0Dh, General Protection Fault 2232 00006604 [61080000] dd exc14 ; 0Eh, Page Fault 2233 00006608 [65080000] dd exc15 2234 0000660C [69080000] dd exc16 2235 00006610 [6D080000] dd exc17 2236 00006614 [71080000] dd exc18 2237 00006618 [75080000] dd exc19 2238 0000661C [79080000] dd exc20 2239 00006620 [7D080000] dd exc21 2240 00006624 [81080000] dd exc22 2241 00006628 [85080000] dd exc23 2242 0000662C [89080000] dd exc24 2243 00006630 [8D080000] dd exc25 2244 00006634 [91080000] dd exc26 2245 00006638 [95080000] dd exc27 2246 0000663C [99080000] dd exc28 2247 00006640 [9D080000] dd exc29 2248 00006644 [A1080000] dd exc30 2249 00006648 [A5080000] dd exc31 2250 ; Interrupt list 2251 0000664C [5E060000] dd timer_int ; INT 20h 2252 ;dd irq0 2253 00006650 [580B0000] dd keyb_int ; 27/08/2014 2254 ;dd irq1 2255 00006654 [7A070000] dd irq2 2256 ; COM2 int 2257 00006658 [7E070000] dd irq3 2258 ; COM1 int 2259 0000665C [89070000] dd irq4 2260 00006660 [94070000] dd irq5 2261 ;DISKETTE_INT: ;06/02/2015 2262 00006664 [FB250000] dd fdc_int ; 16/02/2015, IRQ 6 handler 2263 ;dd irq6 2264 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 2265 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 2266 00006668 [090B0000] dd default_irq7 ; 25/02/2015 2267 ;dd irq7 2268 ; Real Time Clock Interrupt 2269 0000666C [AE090000] dd rtc_int ; 23/02/2015, IRQ 8 handler 2270 ;dd irq8 ; INT 28h 2271 00006670 [A4070000] dd irq9 2272 00006674 [A8070000] dd irq10 2273 00006678 [AC070000] dd irq11 2274 0000667C [B0070000] dd irq12 2275 00006680 [B4070000] dd irq13 2276 ;HDISK_INT1: ;06/02/2015 2277 00006684 [212E0000] dd hdc1_int ; 21/02/2015, IRQ 14 handler 2278 ;dd irq14 2279 ;HDISK_INT2: ;06/02/2015 2280 00006688 [442E0000] dd hdc2_int ; 21/02/2015, IRQ 15 handler 2281 ;dd irq15 ; INT 2Fh 2282 ; 14/08/2015 2283 0000668C [A83A0000] dd sysent ; INT 30h (system calls) 2284 2285 ;dd ignore_int 2286 00006690 00000000 dd 0 2287 2288 ;;; 2289 ;;; 11/03/2015 2290 %include 'kybdata.s' ; KEYBOARD (BIOS) DATA 2291 <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC 2292 <1> ; Last Modification: 11/03/2015 2293 <1> ; (Data Section for 'KEYBOARD.INC') 2294 <1> ; 2295 <1> ; ///////// KEYBOARD DATA /////////////// 2296 <1> 2297 <1> ; 05/12/2014 2298 <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 2299 <1> ; 03/06/86 KEYBOARD BIOS 2300 <1> 2301 <1> ;--------------------------------------------------------------------------------- 2302 <1> ; KEY IDENTIFICATION SCAN TABLES 2303 <1> ;--------------------------------------------------------------------------------- 2304 <1> 2305 <1> ;----- TABLES FOR ALT CASE ------------ 2306 <1> ;----- ALT-INPUT-TABLE 2307 00006694 524F50514B <1> K30: db 82,79,80,81,75 2308 00006699 4C4D474849 <1> db 76,77,71,72,73 ; 10 NUMBER ON KEYPAD 2309 <1> ;----- SUPER-SHIFT-TABLE 2310 0000669E 101112131415 <1> db 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS 2311 000066A4 161718191E1F <1> db 22,23,24,25,30,31 2312 000066AA 202122232425 <1> db 32,33,34,35,36,37 2313 000066B0 262C2D2E2F30 <1> db 38,44,45,46,47,48 2314 000066B6 3132 <1> db 49,50 2315 <1> 2316 <1> ;----- TABLE OF SHIFT KEYS AND MASK VALUES 2317 <1> ;----- KEY_TABLE 2318 000066B8 52 <1> _K6: db INS_KEY ; INSERT KEY 2319 000066B9 3A4546381D <1> db CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY 2320 000066BE 2A36 <1> db LEFT_KEY,RIGHT_KEY 2321 <1> _K6L equ $-_K6 2322 <1> 2323 <1> ;----- MASK_TABLE 2324 000066C0 80 <1> _K7: db INS_SHIFT ; INSERT MODE SHIFT 2325 000066C1 4020100804 <1> db CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT 2326 000066C6 0201 <1> db LEFT_SHIFT,RIGHT_SHIFT 2327 <1> 2328 <1> ;----- TABLES FOR CTRL CASE ;---- CHARACTERS ------ 2329 000066C8 1BFF00FFFFFF <1> _K8: db 27,-1,0,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5 2330 000066CE 1EFFFFFFFF1F <1> db 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, - 2331 000066D4 FF7FFF111705 <1> db -1,127,-1,17,23,5 ; =, Bksp, Tab, Q, W, E 2332 000066DA 12141915090F <1> db 18,20,25,21,9,15 ; R, T, Y, U, I, O 2333 000066E0 101B1D0AFF01 <1> db 16,27,29,10,-1,1 ; P, [, ], Enter, Ctrl, A 2334 000066E6 13040607080A <1> db 19,4,6,7,8,10 ; S, D, F, G, H, J 2335 000066EC 0B0CFFFFFFFF <1> db 11,12,-1,-1,-1,-1 ; K, L, :, ', `, LShift 2336 000066F2 1C1A18031602 <1> db 28,26,24,3,22,2 ; Bkslash, Z, X, C, V, B 2337 000066F8 0E0DFFFFFFFF <1> db 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift 2338 000066FE 96FF20FF <1> db 150,-1,' ',-1 ; *, ALT, Spc, CL 2339 <1> ; ;----- FUNCTIONS ------ 2340 00006702 5E5F60616263 <1> db 94,95,96,97,98,99 ; F1 - F6 2341 00006708 64656667FFFF <1> db 100,101,102,103,-1,-1 ; F7 - F10, NL, SL 2342 0000670E 778D848E738F <1> db 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5 2343 00006714 749075917692 <1> db 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins 2344 0000671A 93FFFFFF898A <1> db 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12 2345 <1> 2346 <1> ;----- TABLES FOR LOWER CASE ---------- 2347 00006720 1B3132333435363738- <1> K10: db 27,'1234567890-=',8,9 2347 00006729 39302D3D0809 <1> 2348 0000672F 71776572747975696F- <1> db 'qwertyuiop[]',13,-1,'asdfghjkl;',39 2348 00006738 705B5D0DFF61736466- <1> 2348 00006741 67686A6B6C3B27 <1> 2349 00006748 60FF5C7A786376626E- <1> db 96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1 2349 00006751 6D2C2E2FFF2AFF20FF <1> 2350 <1> ;----- LC TABLE SCAN 2351 0000675A 3B3C3D3E3F <1> db 59,60,61,62,63 ; BASE STATE OF F1 - F10 2352 0000675F 4041424344 <1> db 64,65,66,67,68 2353 00006764 FFFF <1> db -1,-1 ; NL, SL 2354 <1> 2355 <1> ;----- KEYPAD TABLE 2356 00006766 474849FF4BFF <1> K15: db 71,72,73,-1,75,-1 ; BASE STATE OF KEYPAD KEYS 2357 0000676C 4DFF4F50515253 <1> db 77,-1,79,80,81,82,83 2358 00006773 FFFF5C8586 <1> db -1,-1,92,133,134 ; SysRq, Undef, WT, F11, F12 2359 <1> 2360 <1> ;----- TABLES FOR UPPER CASE ---------- 2361 00006778 1B21402324255E262A- <1> K11: db 27,'!@#$%',94,'&*()_+',8,0 2361 00006781 28295F2B0800 <1> 2362 00006787 51574552545955494F- <1> db 'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"' 2362 00006790 507B7D0DFF41534446- <1> 2362 00006799 47484A4B4C3A22 <1> 2363 000067A0 7EFF7C5A584356424E- <1> db 126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1 2363 000067A9 4D3C3E3FFF2AFF20FF <1> 2364 <1> ;----- UC TABLE SCAN 2365 000067B2 5455565758 <1> K12: db 84,85,86,87,88 ; SHIFTED STATE OF F1 - F10 2366 000067B7 595A5B5C5D <1> db 89,90,91,92,93 2367 000067BC FFFF <1> db -1,-1 ; NL, SL 2368 <1> 2369 <1> ;----- NUM STATE TABLE 2370 000067BE 3738392D3435362B31- <1> K14: db '789-456+1230.' ; NUMLOCK STATE OF KEYPAD KEYS 2370 000067C7 3233302E <1> 2371 <1> ; 2372 000067CB FFFF7C8788 <1> db -1,-1,124,135,136 ; SysRq, Undef, WT, F11, F12 2373 <1> 2374 <1> Align 4 2375 <1> ;---------------------------------------- 2376 <1> ; VIDEO DISPLAY DATA AREA ; 2377 <1> ;---------------------------------------- 2378 000067D0 03 <1> CRT_MODE db 3 ; CURRENT DISPLAY MODE (TYPE) 2379 000067D1 29 <1> CRT_MODE_SET db 29h ; CURRENT SETTING OF THE 3X8 REGISTER 2380 <1> ; (29h default setting for video mode 3) 2381 <1> ; Mode Select register Bits 2382 <1> ; BIT 0 - 80x25 (1), 40x25 (0) 2383 <1> ; BIT 1 - ALPHA (0), 320x200 GRAPHICS (1) 2384 <1> ; BIT 2 - COLOR (0), BW (1) 2385 <1> ; BIT 3 - Video Sig. ENABLE (1), DISABLE (0) 2386 <1> ; BIT 4 - 640x200 B&W Graphics Mode (1) 2387 <1> ; BIT 5 - ALPHA mode BLINKING (1) 2388 <1> ; BIT 6, 7 - Not Used 2389 <1> 2390 <1> ; Mode 0 - 2Ch = 101100b ; 40x25 text, 16 gray colors 2391 <1> ; Mode 1 - 28h = 101000b ; 40x25 text, 16 fore colors, 8 back colors 2392 <1> ; Mode 2 - 2Dh = 101101b ; 80x25 text, 16 gray colors 2393 <1> ; MODE 3 - 29h = 101001b ; 80x25 text, 16 fore color, 8 back color 2394 <1> ; Mode 4 - 2Ah = 101010b ; 320x200 graphics, 4 colors 2395 <1> ; Mode 5 - 2Eh = 101110b ; 320x200 graphics, 4 gray colors 2396 <1> ; Mode 6 - 1Eh = 011110b ; 640x200 graphics, 2 colors 2397 <1> ; Mode 7 - 29h = 101001b ; 80x25 text, black & white colors 2398 <1> ; Mode & 37h = Video signal OFF 2399 <1> 2400 <1> 2401 <1> ; 26/08/2014 2402 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014) 2403 <1> ; Derived from IBM "pc-at" 2404 <1> ; rombios source code (06/10/1985) 2405 <1> ; 'dseg.inc' 2406 <1> 2407 <1> ;---------------------------------------; 2408 <1> ; SYSTEM DATA AREA ; 2409 <1> ;---------------------------------------- 2410 000067D2 00 <1> BIOS_BREAK db 0 ; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED 2411 <1> 2412 <1> ;---------------------------------------- 2413 <1> ; KEYBOARD DATA AREAS ; 2414 <1> ;---------------------------------------- 2415 <1> 2416 000067D3 00 <1> KB_FLAG db 0 ; KEYBOARD SHIFT STATE AND STATUS FLAGS 2417 000067D4 00 <1> KB_FLAG_1 db 0 ; SECOND BYTE OF KEYBOARD STATUS 2418 000067D5 00 <1> KB_FLAG_2 db 0 ; KEYBOARD LED FLAGS 2419 000067D6 00 <1> KB_FLAG_3 db 0 ; KEYBOARD MODE STATE AND TYPE FLAGS 2420 000067D7 00 <1> ALT_INPUT db 0 ; STORAGE FOR ALTERNATE KEY PAD ENTRY 2421 000067D8 [E8670000] <1> BUFFER_START dd KB_BUFFER ; OFFSET OF KEYBOARD BUFFER START 2422 000067DC [08680000] <1> BUFFER_END dd KB_BUFFER + 32 ; OFFSET OF END OF BUFFER 2423 000067E0 [E8670000] <1> BUFFER_HEAD dd KB_BUFFER ; POINTER TO HEAD OF KEYBOARD BUFFER 2424 000067E4 [E8670000] <1> BUFFER_TAIL dd KB_BUFFER ; POINTER TO TAIL OF KEYBOARD BUFFER 2425 <1> ; ------ HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY 2426 000067E8 0000 <1> KB_BUFFER times 16 dw 0 ; ROOM FOR 16 SCAN CODE ENTRIES 2427 <1> 2428 <1> ; /// End Of KEYBOARD DATA /// 2291 %include 'vidata.s' ; VIDEO (BIOS) DATA 2292 <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC 2293 <1> ; Last Modification: 11/03/2015 2294 <1> ; (Data section for 'VIDEO.INC') 2295 <1> ; 2296 <1> ; ///////// VIDEO DATA /////////////// 2297 <1> 2298 <1> video_params: 2299 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2300 <1> ;ORGS.ASM ----- 06/10/85 COMPATIBILITY MODULE 2301 <1> ; VIDEO MODE 3 2302 00006808 71505A0A1F0619 <1> db 71h,50h,5Ah,0Ah,1Fh,6,19h ; SET UP FOR 80X25 2303 0000680F 1C02070607 <1> db 1Ch,2,7,6,7 ; cursor start = 6, cursor stop = 7 2304 00006814 00000000 <1> db 0,0,0,0 2305 <1> 2306 <1> ; /// End Of VIDEO DATA /// 2292 %include 'diskdata.s' ; DISK (BIOS) DATA (initialized) 2293 <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC 2294 <1> ; Last Modification: 11/03/2015 2295 <1> ; (Initialized Disk Parameters Data section for 'DISKIO.INC') 2296 <1> ; 2297 <1> ; ***************************************************************************** 2298 <1> 2299 <1> ;---------------------------------------- 2300 <1> ; 80286 INTERRUPT LOCATIONS : 2301 <1> ; REFERENCED BY POST & BIOS : 2302 <1> ;---------------------------------------- 2303 <1> 2304 00006818 [7B680000] <1> DISK_POINTER: dd MD_TBL6 ; Pointer to Diskette Parameter Table 2305 <1> 2306 <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014 2307 <1> ;---------------------------------------------------------------- 2308 <1> ; DISK_BASE : 2309 <1> ; THIS IS THE SET OF PARAMETERS REQUIRED FOR : 2310 <1> ; DISKETTE OPERATION. THEY ARE POINTED AT BY THE : 2311 <1> ; DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS, : 2312 <1> ; BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT : 2313 <1> ;---------------------------------------------------------------- 2314 <1> 2315 <1> ;DISK_BASE: 2316 <1> ; DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2317 <1> ; DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2318 <1> ; DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2319 <1> ; DB 2 ; 512 BYTES/SECTOR 2320 <1> ; ;DB 15 ; EOT (LAST SECTOR ON TRACK) 2321 <1> ; db 18 ; (EOT for 1.44MB diskette) 2322 <1> ; DB 01BH ; GAP LENGTH 2323 <1> ; DB 0FFH ; DTL 2324 <1> ; ;DB 054H ; GAP LENGTH FOR FORMAT 2325 <1> ; db 06ch ; (for 1.44MB dsikette) 2326 <1> ; DB 0F6H ; FILL BYTE FOR FORMAT 2327 <1> ; DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2328 <1> ; DB 8 ; MOTOR START TIME (1/8 SECONDS) 2329 <1> 2330 <1> ;---------------------------------------- 2331 <1> ; ROM BIOS DATA AREAS : 2332 <1> ;---------------------------------------- 2333 <1> 2334 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 2335 <1> 2336 <1> ;@EQUIP_FLAG DW ? ; INSTALLED HARDWARE FLAGS 2337 <1> 2338 <1> ;---------------------------------------- 2339 <1> ; DISKETTE DATA AREAS : 2340 <1> ;---------------------------------------- 2341 <1> 2342 <1> ;@SEEK_STATUS DB ? ; DRIVE RECALIBRATION STATUS 2343 <1> ; ; BIT 3-0 = DRIVE 3-0 RECALIBRATION 2344 <1> ; ; BEFORE NEXT SEEK IF BIT IS = 0 2345 <1> ;@MOTOR_STATUS DB ? ; MOTOR STATUS 2346 <1> ; ; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING 2347 <1> ; ; BIT 7 = CURRENT OPERATION IS A WRITE 2348 <1> ;@MOTOR_COUNT DB ? ; TIME OUT COUNTER FOR MOTOR(S) TURN OFF 2349 <1> ;@DSKETTE_STATUS DB ? ; RETURN CODE STATUS BYTE 2350 <1> ; ; CMD_BLOCK IN STACK FOR DISK OPERATION 2351 <1> ;@NEC_STATUS DB 7 DUP(?) ; STATUS BYTES FROM DISKETTE OPERATION 2352 <1> 2353 <1> ;---------------------------------------- 2354 <1> ; POST AND BIOS WORK DATA AREA : 2355 <1> ;---------------------------------------- 2356 <1> 2357 <1> ;@INTR_FLAG DB ? ; FLAG INDICATING AN INTERRUPT HAPPENED 2358 <1> 2359 <1> ;---------------------------------------- 2360 <1> ; TIMER DATA AREA : 2361 <1> ;---------------------------------------- 2362 <1> 2363 <1> ; 17/12/2014 (IRQ 0 - INT 08H) 2364 <1> ;TIMER_LOW equ 46Ch ; Timer ticks (counter) @ 40h:006Ch 2365 <1> ;TIMER_HIGH equ 46Eh ; (18.2 timer ticks per second) 2366 <1> ;TIMER_OFL equ 470h ; Timer - 24 hours flag @ 40h:0070h 2367 <1> 2368 <1> ;---------------------------------------- 2369 <1> ; ADDITIONAL MEDIA DATA : 2370 <1> ;---------------------------------------- 2371 <1> 2372 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 2373 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 2374 <1> ; DB ? ; DRIVE 1 MEDIA STATE 2375 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 2376 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 2377 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 2378 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 2379 <1> 2380 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 2381 <1> 2382 <1> ;-------------------------------------------------------- 2383 <1> ; DRIVE TYPE TABLE : 2384 <1> ;-------------------------------------------------------- 2385 <1> ; 16/02/2015 (unix386.s, 32 bit modifications) 2386 <1> DR_TYPE: 2387 0000681C 01 <1> DB 01 ;DRIVE TYPE, MEDIA TABLE 2388 <1> ;DW MD_TBL1 2389 0000681D [3A680000] <1> dd MD_TBL1 2390 00006821 82 <1> DB 02+BIT7ON 2391 <1> ;DW MD_TBL2 2392 00006822 [47680000] <1> dd MD_TBL2 2393 00006826 02 <1> DR_DEFAULT: DB 02 2394 <1> ;DW MD_TBL3 2395 00006827 [54680000] <1> dd MD_TBL3 2396 0000682B 03 <1> DB 03 2397 <1> ;DW MD_TBL4 2398 0000682C [61680000] <1> dd MD_TBL4 2399 00006830 84 <1> DB 04+BIT7ON 2400 <1> ;DW MD_TBL5 2401 00006831 [6E680000] <1> dd MD_TBL5 2402 00006835 04 <1> DB 04 2403 <1> ;DW MD_TBL6 2404 00006836 [7B680000] <1> dd MD_TBL6 2405 <1> DR_TYPE_E equ $ ; END OF TABLE 2406 <1> ;DR_CNT EQU (DR_TYPE_E-DR_TYPE)/3 2407 <1> DR_CNT equ (DR_TYPE_E-DR_TYPE)/5 2408 <1> ;-------------------------------------------------------- 2409 <1> ; MEDIA/DRIVE PARAMETER TABLES : 2410 <1> ;-------------------------------------------------------- 2411 <1> ;-------------------------------------------------------- 2412 <1> ; 360 KB MEDIA IN 360 KB DRIVE : 2413 <1> ;-------------------------------------------------------- 2414 <1> MD_TBL1: 2415 0000683A DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2416 0000683B 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2417 0000683C 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2418 0000683D 02 <1> DB 2 ; 512 BYTES/SECTOR 2419 0000683E 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2420 0000683F 2A <1> DB 02AH ; GAP LENGTH 2421 00006840 FF <1> DB 0FFH ; DTL 2422 00006841 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2423 00006842 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2424 00006843 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2425 00006844 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2426 00006845 27 <1> DB 39 ; MAX. TRACK NUMBER 2427 00006846 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2428 <1> ;-------------------------------------------------------- 2429 <1> ; 360 KB MEDIA IN 1.2 MB DRIVE : 2430 <1> ;-------------------------------------------------------- 2431 <1> MD_TBL2: 2432 00006847 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2433 00006848 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2434 00006849 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2435 0000684A 02 <1> DB 2 ; 512 BYTES/SECTOR 2436 0000684B 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2437 0000684C 2A <1> DB 02AH ; GAP LENGTH 2438 0000684D FF <1> DB 0FFH ; DTL 2439 0000684E 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2440 0000684F F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2441 00006850 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2442 00006851 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2443 00006852 27 <1> DB 39 ; MAX. TRACK NUMBER 2444 00006853 40 <1> DB RATE_300 ; DATA TRANSFER RATE 2445 <1> ;-------------------------------------------------------- 2446 <1> ; 1.2 MB MEDIA IN 1.2 MB DRIVE : 2447 <1> ;-------------------------------------------------------- 2448 <1> MD_TBL3: 2449 00006854 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2450 00006855 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2451 00006856 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2452 00006857 02 <1> DB 2 ; 512 BYTES/SECTOR 2453 00006858 0F <1> DB 15 ; EOT (LAST SECTOR ON TRACK) 2454 00006859 1B <1> DB 01BH ; GAP LENGTH 2455 0000685A FF <1> DB 0FFH ; DTL 2456 0000685B 54 <1> DB 054H ; GAP LENGTH FOR FORMAT 2457 0000685C F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2458 0000685D 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2459 0000685E 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2460 0000685F 4F <1> DB 79 ; MAX. TRACK NUMBER 2461 00006860 00 <1> DB RATE_500 ; DATA TRANSFER RATE 2462 <1> ;-------------------------------------------------------- 2463 <1> ; 720 KB MEDIA IN 720 KB DRIVE : 2464 <1> ;-------------------------------------------------------- 2465 <1> MD_TBL4: 2466 00006861 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2467 00006862 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2468 00006863 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2469 00006864 02 <1> DB 2 ; 512 BYTES/SECTOR 2470 00006865 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2471 00006866 2A <1> DB 02AH ; GAP LENGTH 2472 00006867 FF <1> DB 0FFH ; DTL 2473 00006868 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2474 00006869 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2475 0000686A 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2476 0000686B 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2477 0000686C 4F <1> DB 79 ; MAX. TRACK NUMBER 2478 0000686D 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2479 <1> ;-------------------------------------------------------- 2480 <1> ; 720 KB MEDIA IN 1.44 MB DRIVE : 2481 <1> ;-------------------------------------------------------- 2482 <1> MD_TBL5: 2483 0000686E DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2484 0000686F 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2485 00006870 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2486 00006871 02 <1> DB 2 ; 512 BYTES/SECTOR 2487 00006872 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2488 00006873 2A <1> DB 02AH ; GAP LENGTH 2489 00006874 FF <1> DB 0FFH ; DTL 2490 00006875 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2491 00006876 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2492 00006877 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2493 00006878 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2494 00006879 4F <1> DB 79 ; MAX. TRACK NUMBER 2495 0000687A 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2496 <1> ;-------------------------------------------------------- 2497 <1> ; 1.44 MB MEDIA IN 1.44 MB DRIVE : 2498 <1> ;-------------------------------------------------------- 2499 <1> MD_TBL6: 2500 0000687B AF <1> DB 10101111B ; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE 2501 0000687C 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2502 0000687D 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2503 0000687E 02 <1> DB 2 ; 512 BYTES/SECTOR 2504 0000687F 12 <1> DB 18 ; EOT (LAST SECTOR ON TRACK) 2505 00006880 1B <1> DB 01BH ; GAP LENGTH 2506 00006881 FF <1> DB 0FFH ; DTL 2507 00006882 6C <1> DB 06CH ; GAP LENGTH FOR FORMAT 2508 00006883 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2509 00006884 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2510 00006885 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2511 00006886 4F <1> DB 79 ; MAX. TRACK NUMBER 2512 00006887 00 <1> DB RATE_500 ; DATA TRANSFER RATE 2513 <1> 2514 <1> 2515 <1> ; << diskette.inc >> 2516 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2517 <1> ; 2518 <1> ;---------------------------------------- 2519 <1> ; ROM BIOS DATA AREAS : 2520 <1> ;---------------------------------------- 2521 <1> 2522 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 2523 <1> 2524 <1> ;---------------------------------------- 2525 <1> ; FIXED DISK DATA AREAS : 2526 <1> ;---------------------------------------- 2527 <1> 2528 <1> ;DISK_STATUS1: DB 0 ; FIXED DISK STATUS 2529 <1> ;HF_NUM: DB 0 ; COUNT OF FIXED DISK DRIVES 2530 <1> ;CONTROL_BYTE: DB 0 ; HEAD CONTROL BYTE 2531 <1> ;@PORT_OFF DB ? ; RESERVED (PORT OFFSET) 2532 <1> 2533 <1> ;---------------------------------------- 2534 <1> ; ADDITIONAL MEDIA DATA : 2535 <1> ;---------------------------------------- 2536 <1> 2537 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 2538 <1> ;HF_STATUS DB 0 ; STATUS REGISTER 2539 <1> ;HF_ERROR DB 0 ; ERROR REGISTER 2540 <1> ;HF_INT_FLAG DB 0 ; FIXED DISK INTERRUPT FLAG 2541 <1> ;HF_CNTRL DB 0 ; COMBO FIXED DISK/DISKETTE CARD BIT 0=1 2542 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 2543 <1> ; DB ? ; DRIVE 1 MEDIA STATE 2544 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 2545 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 2546 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 2547 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 2548 <1> 2549 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 2550 <1> ; 2551 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2552 <1> 2553 <1> ERR_TBL: 2554 00006888 E0 <1> db NO_ERR 2555 00006889 024001BB <1> db BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR 2556 0000688D 04BB100A <1> db RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR 2557 <1> 2558 <1> ; 17/12/2014 (mov ax, [cfd]) 2559 <1> ; 11/12/2014 2560 00006891 00 <1> cfd: db 0 ; current floppy drive (for GET_PARM) 2561 <1> ; 17/12/2014 ; instead of 'DISK_POINTER' 2562 00006892 01 <1> pfd: db 1 ; previous floppy drive (for GET_PARM) 2563 <1> ; (initial value of 'pfd 2564 <1> ; must be different then 'cfd' value 2565 <1> ; to force updating/initializing 2566 <1> ; current drive parameters) 2567 00006893 90 <1> align 2 2568 <1> 2569 00006894 F001 <1> HF_PORT: dw 1F0h ; Default = 1F0h 2570 <1> ; (170h) 2571 00006896 F603 <1> HF_REG_PORT: dw 3F6h ; HF_PORT + 206h 2572 <1> 2573 <1> ; 05/01/2015 2574 00006898 00 <1> hf_m_s: db 0 ; (0 = Master, 1 = Slave) 2575 <1> 2576 <1> ; ***************************************************************************** 2293 ;;; 2294 2295 00006899 90 Align 2 2296 2297 ; 12/11/2014 (Retro UNIX 386 v1) 2298 0000689A 00 boot_drv: db 0 ; boot drive number (physical) 2299 ; 24/11/2014 2300 0000689B 00 drv: db 0 2301 0000689C 00 last_drv: db 0 ; last hdd 2302 0000689D 00 hdc: db 0 ; number of hard disk drives 2303 ; (present/detected) 2304 ; 2305 ; 24/11/2014 (Retro UNIX 386 v1) 2306 ; Physical drive type & flags 2307 0000689E 00 fd0_type: db 0 ; floppy drive type 2308 0000689F 00 fd1_type: db 0 ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt) 2309 ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt) 2310 ; 3 = 720 Kb, 80 track, 3.5" (9 spt) 2311 ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt) 2312 ; 1 = 360 Kb, 40 track, 5.25" (9 spt) 2313 000068A0 00 hd0_type: db 0 ; EDD status for hd0 (bit 7 = present flag) 2314 000068A1 00 hd1_type: db 0 ; EDD status for hd1 (bit 7 = present flag) 2315 000068A2 00 hd2_type: db 0 ; EDD status for hd2 (bit 7 = present flag) 2316 000068A3 00 hd3_type: db 0 ; EDD status for hd3 (bit 7 = present flag) 2317 ; bit 0 - Fixed disk access subset supported 2318 ; bit 1 - Drive locking and ejecting 2319 ; bit 2 - Enhanced disk drive support 2320 ; bit 3 = Reserved (64 bit EDD support) 2321 ; (If bit 0 is '1' Retro UNIX 386 v1 2322 ; will interpret it as 'LBA ready'!) 2323 2324 ; 11/03/2015 - 10/07/2015 2325 000068A4 000000000000000000- drv.cylinders: dw 0,0,0,0,0,0,0 2325 000068AD 0000000000 2326 000068B2 000000000000000000- drv.heads: dw 0,0,0,0,0,0,0 2326 000068BB 0000000000 2327 000068C0 000000000000000000- drv.spt: dw 0,0,0,0,0,0,0 2327 000068C9 0000000000 2328 000068CE 000000000000000000- drv.size: dd 0,0,0,0,0,0,0 2328 000068D7 000000000000000000- 2328 000068E0 000000000000000000- 2328 000068E9 00 2329 000068EA 00000000000000 drv.status: db 0,0,0,0,0,0,0 2330 000068F1 00000000000000 drv.error: db 0,0,0,0,0,0,0 2331 ; 2332 2333 ; 27/08/2014 2334 scr_row: 2335 000068F8 E0810B00 dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3 2336 scr_col: 2337 000068FC 00000000 dd 0 2338 2339 ;; 14/08/2015 2340 ;;msgPM: 2341 ;; db "Protected mode and paging are ENABLED ... ", 0 2342 msgKVER: 2343 00006900 526574726F20554E49- db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [10/01/2022]", 0 2343 00006909 58203338362076312E- 2343 00006912 32202D204B65726E65- 2343 0000691B 6C2076302E322E322E- 2343 00006924 30205B31302F30312F- 2343 0000692D 323032325D00 2344 2345 00006933 90 Align 2 2346 2347 ; 20/08/2014 2348 ; /* This is the default interrupt "handler" :-) */ 2349 ; Linux v0.12 (head.s) 2350 int_msg: 2351 00006934 556E6B6E6F776E2069- db "Unknown interrupt ! ", 0 2351 0000693D 6E7465727275707420- 2351 00006946 212000 2352 2353 00006949 90 Align 2 2354 2355 ; 21/08/2014 2356 timer_msg: 2357 0000694A 49525120302028494E- db "IRQ 0 (INT 20h) ! Timer Interrupt : " 2357 00006953 542032306829202120- 2357 0000695C 54696D657220496E74- 2357 00006965 657272757074203A20 2358 tcountstr: 2359 0000696E 303030303020 db "00000 " 2360 00006974 00 db 0 2361 2362 00006975 90 Align 2 2363 ; 21/08/2014 2364 exc_msg: 2365 00006976 435055206578636570- db "CPU exception ! " 2365 0000697F 74696F6E202120 2366 excnstr: ; 25/08/2014 2367 00006986 3F3F68202045495020- db "??h", " EIP : " 2367 0000698F 3A20 2368 EIPstr: ; 29/08/2014 2369 00006991 00 times 12 db 0 2370 rtc_msg: 2371 0000699D 5265616C2054696D65- db "Real Time Clock - " 2371 000069A6 20436C6F636B202D20 2372 datestr: 2373 000069AF 30302F30302F303030- db "00/00/0000" 2373 000069B8 30 2374 000069B9 20 db " " 2375 daystr: 2376 000069BA 44415920 db "DAY " 2377 timestr: 2378 000069BE 30303A30303A3030 db "00:00:00" 2379 000069C6 20 db " " 2380 000069C7 00 db 0 2381 2382 daytmp: 2383 ; 28/02/2015 2384 000069C8 3F3F3F2053554E204D- db "??? SUN MON TUE WED THU FRI SAT " 2384 000069D1 4F4E20545545205745- 2384 000069DA 442054485520465249- 2384 000069E3 2053415420 2385 2386 000069E8 FF ptime_seconds: db 0FFh 2387 2388 ; 23/02/2015 2389 ; 25/08/2014 2390 ;scounter: 2391 ; db 5 2392 ; db 19 2393 2394 ; 28/11/2021 2395 ;; 05/11/2014 2396 ;msg_out_of_memory: 2397 ; db 07h, 0Dh, 0Ah 2398 ; db 'Insufficient memory ! (Minimum 2 MB memory is needed.)' 2399 ; db 0Dh, 0Ah, 0 2400 ; 2401 setup_error_msg: 2402 000069E9 0D0A db 0Dh, 0Ah 2403 000069EB 4469736B2053657475- db 'Disk Setup Error!' 2403 000069F4 70204572726F7221 2404 000069FC 0D0A00 db 0Dh, 0Ah,0 2405 2406 ; 02/09/2014 (Retro UNIX 386 v1) 2407 ;crt_ulc: db 0 ; upper left column (for scroll) 2408 ; db 0 ; upper left row (for scroll) 2409 2410 ;crt_lrc: db 79 ; lower right column (for scroll) 2411 ; db 24 ; lower right row (for scroll) 2412 2413 ; 06/11/2014 (Temporary Data) 2414 ; Memory Information message 2415 ; 14/08/2015 2416 msg_memory_info: 2417 000069FF 07 db 07h 2418 00006A00 0D0A db 0Dh, 0Ah 2419 ;db "MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah 2420 00006A02 546F74616C206D656D- db "Total memory : " 2420 00006A0B 6F7279203A20 2421 mem_total_b_str: ; 10 digits 2422 00006A11 303030303030303030- db "0000000000 bytes", 0Dh, 0Ah 2422 00006A1A 302062797465730D0A 2423 00006A23 202020202020202020- db " ", 20h, 20h, 20h 2423 00006A2C 202020202020202020 2424 mem_total_p_str: ; 7 digits 2425 00006A35 303030303030302070- db "0000000 pages", 0Dh, 0Ah 2425 00006A3E 616765730D0A 2426 00006A44 0D0A db 0Dh, 0Ah 2427 00006A46 46726565206D656D6F- db "Free memory : " 2427 00006A4F 727920203A20 2428 free_mem_b_str: ; 10 digits 2429 00006A55 3F3F3F3F3F3F3F3F3F- db "?????????? bytes", 0Dh, 0Ah 2429 00006A5E 3F2062797465730D0A 2430 00006A67 202020202020202020- db " ", 20h, 20h, 20h 2430 00006A70 202020202020202020 2431 free_mem_p_str: ; 7 digits 2432 00006A79 3F3F3F3F3F3F3F2070- db "??????? pages", 0Dh, 0Ah 2432 00006A82 616765730D0A 2433 00006A88 0D0A00 db 0Dh, 0Ah, 0 2434 2435 dsk_ready_msg: 2436 00006A8B 0D0A db 0Dh, 0Ah 2437 dsktype: 2438 00006A8D 6664 db 'fd' 2439 dskx: 2440 00006A8F 30 db '0' 2441 00006A90 20 db 20h 2442 00006A91 697320524541445920- db 'is READY ...' 2442 00006A9A 2E2E2E 2443 00006A9D 00 db 0 2444 nextline: 2445 00006A9E 0D0A00 db 0Dh, 0Ah, 0 2446 2447 ; KERNEL - SYSINIT Messages 2448 ; 24/08/2015 2449 ; 13/04/2015 - (Retro UNIX 386 v1 Beginning) 2450 ; 14/07/2013 2451 ;kernel_init_err_msg: 2452 ; db 0Dh, 0Ah 2453 ; db 07h 2454 ; db 'Kernel initialization ERROR !' 2455 ; db 0Dh, 0Ah, 0 2456 ; 24/08/2015 2457 ;;; (temporary kernel init message has been removed 2458 ;;; from 'sys_init' code) 2459 ;kernel_init_ok_msg: 2460 ; db 0Dh, 0Ah 2461 ; db 07h 2462 ; db 'Welcome to Retro UNIX 386 v1.1 Operating System !' 2463 ; db 0Dh, 0Ah 2464 ; db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)' 2465 ; db 0Dh, 0Ah, 0 2466 panic_msg: 2467 00006AA1 0D0A07 db 0Dh, 0Ah, 07h 2468 00006AA4 4552524F523A204B65- db 'ERROR: Kernel Panic !' 2468 00006AAD 726E656C2050616E69- 2468 00006AB6 632021 2469 00006AB9 0D0A00 db 0Dh, 0Ah, 0 2470 etc_init_err_msg: 2471 00006ABC 0D0A db 0Dh, 0Ah 2472 00006ABE 07 db 07h 2473 00006ABF 4552524F523A202F65- db 'ERROR: /etc/init !?' 2473 00006AC8 74632F696E69742021- 2473 00006AD1 3F 2474 00006AD2 0D0A00 db 0Dh, 0Ah, 0 2475 2476 ; 10/05/2015 2477 badsys_msg: 2478 00006AD5 0D0A db 0Dh, 0Ah 2479 00006AD7 07 db 07h 2480 00006AD8 496E76616C69642053- db 'Invalid System Call !' 2480 00006AE1 797374656D2043616C- 2480 00006AEA 6C2021 2481 00006AED 0D0A db 0Dh, 0Ah 2482 00006AEF 4541583A20 db 'EAX: ' 2483 bsys_msg_eax: 2484 00006AF4 303030303030303068 db '00000000h' 2485 00006AFD 0D0A db 0Dh, 0Ah 2486 00006AFF 4549503A20 db 'EIP: ' 2487 bsys_msg_eip: 2488 00006B04 303030303030303068 db '00000000h' 2489 00006B0D 0D0A00 db 0Dh, 0Ah, 0 2490 2491 BSYS_M_SIZE equ $ - badsys_msg 2492 2493 align 2 2494 2495 ; EPOCH Variables 2496 ; 13/04/2015 - Retro UNIX 386 v1 Beginning 2497 ; 09/04/2013 epoch variables 2498 ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013 2499 ; 2500 00006B10 B207 year: dw 1970 2501 00006B12 0100 month: dw 1 2502 00006B14 0100 day: dw 1 2503 00006B16 0000 hour: dw 0 2504 00006B18 0000 minute: dw 0 2505 00006B1A 0000 second: dw 0 2506 2507 DMonth: 2508 00006B1C 0000 dw 0 2509 00006B1E 1F00 dw 31 2510 00006B20 3B00 dw 59 2511 00006B22 5A00 dw 90 2512 00006B24 7800 dw 120 2513 00006B26 9700 dw 151 2514 00006B28 B500 dw 181 2515 00006B2A D400 dw 212 2516 00006B2C F300 dw 243 2517 00006B2E 1101 dw 273 2518 00006B30 3001 dw 304 2519 00006B32 4E01 dw 334 2520 2521 ; 02/01/2022 (Retro UNIX 386 v1.2) 2522 ; 04/11/2014 (Retro UNIX 386 v1) 2523 00006B34 0000 mem_1m_1k: dw 0 ; Number of contiguous KB between 2524 ; 1 and 16 MB, max. 3C00h = 15 MB. 2525 00006B36 0000 dw 0 ; 02/01/2022 (Retro UNIX 386 v1.2) 2526 00006B38 0000 mem_16m_64k: dw 0 ; Number of contiguous 64 KB blocks 2527 ; between 16 MB and 4 GB. 2528 00006B3A 0000 dw 0 ; 02/01/2022 (Retro UNIX 386 v1.2) 2529 2530 ; 01/01/2022 2531 KEND: 2532 2533 00006B3C 90 align 16 2534 2535 bss_start: 2536 2537 ABSOLUTE bss_start 2538 2539 ; 11/03/2015 2540 ; Interrupt Descriptor Table (20/08/2014) 2541 idt: 2542 00006B40 resb 64*8 ; INT 0 to INT 3Fh 2543 idt_end: 2544 2545 ;alignb 4 2546 2547 task_state_segment: 2548 ; 24/03/2015 2549 00006D40 ???? tss.link: resw 1 2550 00006D42 ???? resw 1 2551 ; tss offset 4 2552 00006D44 ???????? tss.esp0: resd 1 2553 00006D48 ???? tss.ss0: resw 1 2554 00006D4A ???? resw 1 2555 00006D4C ???????? tss.esp1: resd 1 2556 00006D50 ???? tss.ss1: resw 1 2557 00006D52 ???? resw 1 2558 00006D54 ???????? tss.esp2: resd 1 2559 00006D58 ???? tss.ss2: resw 1 2560 00006D5A ???? resw 1 2561 ; tss offset 28 2562 00006D5C ???????? tss.CR3: resd 1 2563 00006D60 ???????? tss.eip: resd 1 2564 00006D64 ???????? tss.eflags: resd 1 2565 ; tss offset 40 2566 00006D68 ???????? tss.eax: resd 1 2567 00006D6C ???????? tss.ecx: resd 1 2568 00006D70 ???????? tss.edx: resd 1 2569 00006D74 ???????? tss.ebx: resd 1 2570 00006D78 ???????? tss.esp: resd 1 2571 00006D7C ???????? tss.ebp: resd 1 2572 00006D80 ???????? tss.esi: resd 1 2573 00006D84 ???????? tss.edi: resd 1 2574 ; tss offset 72 2575 00006D88 ???? tss.ES: resw 1 2576 00006D8A ???? resw 1 2577 00006D8C ???? tss.CS: resw 1 2578 00006D8E ???? resw 1 2579 00006D90 ???? tss.SS: resw 1 2580 00006D92 ???? resw 1 2581 00006D94 ???? tss.DS: resw 1 2582 00006D96 ???? resw 1 2583 00006D98 ???? tss.FS: resw 1 2584 00006D9A ???? resw 1 2585 00006D9C ???? tss.GS: resw 1 2586 00006D9E ???? resw 1 2587 00006DA0 ???? tss.LDTR: resw 1 2588 00006DA2 ???? resw 1 2589 ; tss offset 100 2590 00006DA4 ???? resw 1 2591 00006DA6 ???? tss.IOPB: resw 1 2592 ; tss offset 104 2593 tss_end: 2594 2595 00006DA8 ???????? k_page_dir: resd 1 ; Kernel's (System) Page Directory address 2596 ; (Physical address = Virtual address) 2597 00006DAC ???????? memory_size: resd 1 ; memory size in pages 2598 00006DB0 ???????? free_pages: resd 1 ; number of free pages 2599 00006DB4 ???????? next_page: resd 1 ; offset value in M.A.T. for 2600 ; first free page search 2601 00006DB8 ???????? last_page: resd 1 ; offset value in M.A.T. which 2602 ; next free page search will be 2603 ; stopped after it. (end of M.A.T.) 2604 00006DBC ???????? first_page: resd 1 ; offset value in M.A.T. which 2605 ; first free page search 2606 ; will be started on it. (for user) 2607 00006DC0 ???????? mat_size: resd 1 ; Memory Allocation Table size in pages 2608 2609 ;;; 2610 ; 02/09/2014 (Retro UNIX 386 v1) 2611 ; 04/12/2013 (Retro UNIX 8086 v1) 2612 00006DC4 ???? CRT_START: resw 1 ; starting address in regen buffer 2613 ; NOTE: active page only 2614 00006DC6 cursor_posn: resw 8 ; cursor positions for video pages 2615 active_page: 2616 00006DD6 ?? ptty: resb 1 ; current tty 2617 ; 01/07/2015 2618 00006DD7 ?? ccolor: resb 1 ; current color attributes ('sysmsg') 2619 ; 26/10/2015 2620 ; 07/09/2014 2621 00006DD8 ttychr: resw ntty+2 ; Character buffer (multiscreen) 2622 2623 ; 21/08/2014 2624 00006DEC ???????? tcount: resd 1 2625 2626 ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!) 2627 00006DF0 ???????? p_time: resd 1 ; present time (for systime & sysmdate) 2628 2629 ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !) 2630 ; (open mode locks for pseudo TTYs) 2631 ; [ major tty locks (return error in any conflicts) ] 2632 00006DF4 ttyl: resw ntty+2 ; opening locks for TTYs. 2633 2634 ; 15/04/2015 (Retro UNIX 386 v1) 2635 ; 22/09/2013 (Retro UNIX 8086 v1) 2636 00006E08 wlist: resb ntty+2 ; wait channel list (0 to 9 for TTYs) 2637 ; 15/04/2015 (Retro UNIX 386 v1) 2638 ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h 2639 ;; 0 means serial port is not available 2640 ;;comprm: ; 25/06/2014 2641 00006E12 ?? com1p: resb 1 ;;0E3h 2642 00006E13 ?? com2p: resb 1 ;;0E3h 2643 2644 ; 17/11/2015 2645 ; request for response (from the terminal) 2646 00006E14 ???? req_resp: resw 1 2647 ; 07/11/2015 2648 00006E16 ?? ccomport: resb 1 ; current COM (serial) port 2649 ; (0= COM1, 1= COM2) 2650 ; 09/11/2015 2651 00006E17 ?? comqr: resb 1 ; 'query or response' sign (u9.s, 'sndc') 2652 ; 07/11/2015 2653 00006E18 ???? rchar: resw 1 ; last received char for COM 1 and COM 2 2654 00006E1A ???? schar: resw 1 ; last sent char for COM 1 and COM 2 2655 2656 ; 23/10/2015 2657 ; SERIAL PORTS - COMMUNICATION MODES 2658 ; (Retro UNIX 386 v1 feature only!) 2659 ; 0 - command mode (default/initial mode) 2660 ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars) 2661 ;;; communication modes for futre versions: 2662 ; // 2 - keyboard mode (ascii+scancode input) 2663 ; // 3 - mouse mode 2664 ; // 4 - device control (output) mode 2665 ; VALID COMMANDS for current version: 2666 ; 'LOGIN' 2667 ; Login request: db 0FFh, 'LOGIN', 0 2668 ; ("Retro UNIX 386 v1 terminal requests login") 2669 ; Login response: db 0FFh, 'login', 0 2670 ; ("login request accepted, wait for login prompt") 2671 ; When a login requests is received and acknowledged (by 2672 ; serial port interrupt handler (communication procedure), 2673 ; Retro UNIX 386 v1 operating system will start terminal mode 2674 ; (login procedure) by changing comm. mode to 1 (terminal mode) 2675 ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2) 2676 ; 2677 ; 'sys connect' system call is used to change communication mode 2678 ; except 'LOGIN' command which is used to start terminal mode 2679 ; by using (COM port) terminal. 2680 2681 ;com1own: resb 1 ; COM1 owner (u.uno) 2682 ;com2own: resb 1 ; COM2 owner (u.uno) 2683 ;com1mode: resb 1 ; communication mode for COM1 2684 ;com1com: resb 1 ; communication command for COM1 2685 ;com2mode: resb 1 ; communication mode for COM1 2686 ;com2com resb 1 ; communication command for COM1 2687 ;com1cbufp: resb 8 ; COM1 command buffer char pointer 2688 ;com2cbufp: resb 8 ; COM2 command buffer char pointer 2689 ;com1cbuf: resb 8 ; COM2 command buffer 2690 ;com2cbuf: resb 8 ; COM2 command buffer 2691 2692 ; 22/08/2014 (RTC) 2693 ; (Packed BCD) 2694 00006E1C ?? time_seconds: resb 1 2695 00006E1D ?? time_minutes: resb 1 2696 00006E1E ?? time_hours: resb 1 2697 00006E1F ?? date_wday: resb 1 2698 00006E20 ?? date_day: resb 1 2699 00006E21 ?? date_month: resb 1 2700 00006E22 ?? date_year: resb 1 2701 00006E23 ?? date_century: resb 1 2702 2703 %include 'diskbss.s' ; UNINITIALIZED DISK (BIOS) DATA 2704 <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC 2705 <1> ; Last Modification: 10/07/2015 2706 <1> ; (Unitialized Disk Parameters Data section for 'DISKIO.INC') 2707 <1> ; 2708 <1> ; ***************************************************************************** 2709 <1> 2710 <1> alignb 2 2711 <1> 2712 <1> ;---------------------------------------- 2713 <1> ; TIMER DATA AREA : 2714 <1> ;---------------------------------------- 2715 <1> 2716 <1> TIMER_LH: ; 16/02/2015 2717 00006E24 ???? <1> TIMER_LOW: resw 1 ; LOW WORD OF TIMER COUNT 2718 00006E26 ???? <1> TIMER_HIGH: resw 1 ; HIGH WORD OF TIMER COUNT 2719 00006E28 ?? <1> TIMER_OFL: resb 1 ; TIMER HAS ROLLED OVER SINCE LAST READ 2720 <1> 2721 <1> ;---------------------------------------- 2722 <1> ; DISKETTE DATA AREAS : 2723 <1> ;---------------------------------------- 2724 <1> 2725 00006E29 ?? <1> SEEK_STATUS: resb 1 2726 00006E2A ?? <1> MOTOR_STATUS: resb 1 2727 00006E2B ?? <1> MOTOR_COUNT: resb 1 2728 00006E2C ?? <1> DSKETTE_STATUS: resb 1 2729 00006E2D ?????????????? <1> NEC_STATUS: resb 7 2730 <1> 2731 <1> ;---------------------------------------- 2732 <1> ; ADDITIONAL MEDIA DATA : 2733 <1> ;---------------------------------------- 2734 <1> 2735 00006E34 ?? <1> LASTRATE: resb 1 2736 00006E35 ?? <1> HF_STATUS: resb 1 2737 00006E36 ?? <1> HF_ERROR: resb 1 2738 00006E37 ?? <1> HF_INT_FLAG: resb 1 2739 00006E38 ?? <1> HF_CNTRL: resb 1 2740 00006E39 ???????? <1> DSK_STATE: resb 4 2741 00006E3D ???? <1> DSK_TRK: resb 2 2742 <1> 2743 <1> ;---------------------------------------- 2744 <1> ; FIXED DISK DATA AREAS : 2745 <1> ;---------------------------------------- 2746 <1> 2747 00006E3F ?? <1> DISK_STATUS1: resb 1 ; FIXED DISK STATUS 2748 00006E40 ?? <1> HF_NUM: resb 1 ; COUNT OF FIXED DISK DRIVES 2749 00006E41 ?? <1> CONTROL_BYTE: resb 1 ; HEAD CONTROL BYTE 2750 <1> ;@PORT_OFF resb 1 ; RESERVED (PORT OFFSET) 2751 <1> ;port1_off resb 1 ; Hard disk controller 1 - port offset 2752 <1> ;port2_off resb 1 ; Hard idsk controller 2 - port offset 2753 <1> 2754 00006E42 ???? <1> alignb 4 2755 <1> 2756 <1> ;HF_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 2757 <1> ;HF1_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 2758 <1> HF_TBL_VEC: ; 22/12/2014 2759 00006E44 ???????? <1> HDPM_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 2760 00006E48 ???????? <1> HDPS_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 2761 00006E4C ???????? <1> HDSM_TBL_VEC: resd 1 ; Secondary master disk param. tbl. pointer 2762 00006E50 ???????? <1> HDSS_TBL_VEC: resd 1 ; Secondary slave disk param. tbl. pointer 2763 <1> 2764 <1> ; 03/01/2015 2765 00006E54 ?? <1> LBAMode: resb 1 2766 <1> 2767 <1> ; ***************************************************************************** 2704 2705 ;;; Real Mode Data (10/07/2015 - BSS) 2706 2707 ;alignb 2 2708 2709 ; 02/01/2022 2710 ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data) 2711 2712 ; 17/04/2021 2713 ; (memory page swap parameters are disabled as temporary) 2714 ; 2715 ;; Memory (swap) Data (11/03/2015) 2716 ; 09/03/2015 2717 ;swpq_count: resw 1 ; count of pages on the swap que 2718 ;swp_drv: resd 1 ; logical drive description table address of the swap drive/disk 2719 ;swpd_size: resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 2720 ;swpd_free: resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical) 2721 ;swpd_next: resd 1 ; next free page block 2722 ;swpd_last: resd 1 ; last swap page block 2723 2724 00006E55 ?????? alignb 4 2725 2726 ; 10/07/2015 2727 ; 28/08/2014 2728 00006E58 ???????? error_code: resd 1 2729 ; 29/08/2014 2730 00006E5C ???????? FaultOffset: resd 1 2731 ; 21/09/2015 2732 00006E60 ???????? PF_Count: resd 1 ; total page fault count 2733 ; (for debugging - page fault analyze) 2734 ; 'page _fault_handler' (memory.s) 2735 ; 'sysgeterr' (u9.s) 2736 ;; 21/08/2015 2737 ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s 2738 2739 ; 02/01/2022 2740 %include 'ux.s' ; 12/04/2015 (unix system/user/process data) 2741 <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021 2742 <1> ; (re-write kernel for test by using previous version without a major defect) 2743 <1> ; **************************************************************************** 2744 <1> ; Retro UNIX 386 v1.2 Kernel - ux.s 2745 <1> ; Last Modification: 10/01/2022 2746 <1> ; 2747 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 2748 <1> ; (Modified from 2749 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 2750 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 2751 <1> ; ---------------------------------------------------------------------------- 2752 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2753 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2754 <1> ; 2755 <1> ; 2756 <1> ; (Section E10 (17/3/1972) - ux.s) 2757 <1> ; **************************************************************************** 2758 <1> 2759 <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility) 2760 <1> ; 18/07/2021 2761 <1> ; 15/07/2021 2762 <1> ; 12/05/2021 2763 <1> ; 09/05/2021 2764 <1> ; 06/05/2021 2765 <1> ; 02/05/2021 2766 <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM) 2767 <1> 2768 <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM) 2769 <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM) 2770 <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock 2771 <1> 2772 <1> ; 14/01/2020 - Super Block modification: 2773 <1> ; - Extended sections/divisions (consequental sectors) 2774 <1> ; - (for swapping, configuration, boot space etc.) 2775 <1> 2776 <1> struc SB ; SuperBlock 2777 <1> 2778 00000000 ???????? <1> .Header: resd 1 2779 <1> ;.HiddenSects: 2780 00000004 ???????? <1> .BootSectAddr: resd 1 ; Hidden Sectors 2781 <1> ;.TotalSects: 2782 00000008 ???????? <1> .VolumeSize: resd 1 ; Entire Volume/Partition Size (includes ext. volume) 2783 0000000C ???????? <1> .Version: resd 1 2784 00000010 ???????? <1> .BlockSize: resd 1 2785 00000014 ???????? <1> .InodeCount: resd 1 2786 00000018 ???????? <1> .FreeMapAddr: resd 1 2787 0000001C ???????? <1> .FreeMapSize: resd 1 2788 00000020 ???????? <1> .InodeMapAddr: resd 1 2789 00000024 ???????? <1> .InodeMapSize: resd 1 2790 00000028 ???????? <1> .InodeTblAddr: resd 1 2791 0000002C ???????? <1> .InodeTblSize: resd 1 2792 00000030 ???????? <1> .FreeInodes: resd 1 2793 00000034 ???????? <1> .FirstFreeIno: resd 1 2794 00000038 ???????? <1> .FreeBlocks: resd 1 2795 0000003C ???????? <1> .FirstFreeBlk: resd 1 2796 00000040 <1> .BootSecParms: resb 19 ; v1 2797 00000053 ?????????? <1> .BSExtension: resb 5 ; v2 HDFS 2798 00000058 ?? <1> .Status: resb 1 ; 12/05/2021 (system modification status) (*) 2799 00000059 ?? <1> .Pdrv: resb 1 ; Physical disk number (index) ; 12/05/2021 (*) 2800 0000005A ???? <1> .Uno: resw 1 ; user/process number ; 12/05/2021 (*) 2801 0000005C ???????? <1> .ModifTime: resd 1 ; (last) modification time (*) 2802 00000060 ???????? <1> .ExtdVolTbl: resd 1 ; Extended Volume Start/Table Address 2803 00000064 ???????? <1> .ExtdVolSize: resd 1 ; Extended Volume (swap section etc.) Size 2804 00000068 ?? <1> .LBA_rw: resb 1 2805 00000069 ?? <1> .ClusterSize: resb 1 2806 0000006A ?? <1> .ReadOnly: resb 1 ; (SB will not be written to disk if bit 0 is 1) 2807 0000006B ?? <1> .Mounted: resb 1 2808 0000006C ???????? <1> .MountInode: resd 1 ; double word 2809 00000070 ?? <1> .DevMajor: resb 1 2810 00000071 ?? <1> .DevMinor: resb 1 2811 00000072 ?? <1> .LongName: resb 1 2812 00000073 ?? <1> .Direntry32: resb 1 2813 <1> ; 18/07/2021 2814 00000074 ???????? <1> .FileBuffer: resd 1 2815 00000078 ???????? <1> .ItabBuffer: resd 1 2816 0000007C ???????? <1> .ImapBuffer: resd 1 2817 00000080 ???????? <1> .FmapBuffer: resd 1 2818 <1> ; 15/07/2021 2819 00000084 ???????? <1> .LastInode: resd 1 2820 <1> ; 02/05/2021 2821 00000088 ???????? <1> .FmapIndex: resd 1 2822 0000008C ???????? <1> .ImapIndex: resd 1 2823 00000090 ???????? <1> .ItableIndex: resd 1 2824 00000094 <1> .Reserved: resb 508-148 ; 18/07/2021 2825 000001FC ???????? <1> .Footer: resd 1 2826 <1> 2827 <1> endstruc 2828 <1> 2829 <1> ; 26/01/2020 (unix386.s, ux.s) 2830 <1> ; 14/01/2020 2831 <1> SB.HiddenSects equ SB.BootSectAddr 2832 <1> SB.TotalSects equ SB.VolumeSize 2833 <1> 2834 <1> ; 11/05/2021 (Retro UNIX 386 v2) 2835 <1> ; Super block status byte (byte 0 of SB.status dword) 2836 <1> ; bit 0 - superblock modified flag 2837 <1> ; bit 1 - inode map modified flag 2838 <1> ; bit 2 - free blocks map modified flag 2839 <1> ; bit 3 - inode table modified flag 2840 <1> ;; bit 4 - boot sector modified flag ; 17/08/2021 2841 <1> ; 17/08/2021 2842 <1> ; bit 4 - file data write error (for SB.LastInode) 2843 <1> ; bit 5 - inode table write error (for SB.LastInode) 2844 <1> ; bit 6 - inode map write error (for SB.LastInode) 2845 <1> ; bit 7 - free blocks map write error (for SB.LastInode) 2846 <1> 2847 <1> ; 21/12/2019 2848 <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 2849 <1> ; (UNIXHDFS.ASM) 2850 <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1) 2851 <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0) 2852 <1> 2853 <1> bsFSystemID equ 2 ; db 'RUFS' 2854 <1> bsVolumeSerial equ 6 ; dd 0 ; (4 bytes) 2855 <1> bsFDSign equ 10 ; db 'fd' 2856 <1> bsDriveNumber equ 12 ; db 0 ; fd0 or fd1 (0 or 1) 2857 <1> bsReserved equ 13 ; db 0 ; (512 bytes per sector) 2858 <1> bsSecPerTrack equ 14 ; db 18 ; (9 or 15) 2859 <1> bsHeads equ 15 ; db ; 2 2860 <1> bsTracks equ 16 ; dw 80 ; bsCylinders 2861 <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number 2862 <1> bsInfoEndsign equ 20 ; db '@' 2863 <1> ; 21/12/2019 2864 <1> bsMagic equ 20 ; db '@' 2865 <1> bsPartitionID equ 21 ; db 0 ; db 71h 2866 <1> bsHiddenSects equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA) 2867 <1> 2868 <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags 2869 <1> ; ------------------------------------------------------------------ 2870 <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020 2871 <1> ; ------------------------------------------------------------------ 2872 <1> 2873 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files 2874 <1> ; 1000000000000000b IFREG - 1 = regular file (8000h) 2875 <1> ; 0100000000000000b IFDIR - 1 = directory (4000h) 2876 <1> ; 0010000000000000b IRSVD - 0 = reserved bit (2000h) ; Mounted flag 2877 <1> ; 0001000000000000b ILARG - large file addressing bit (1000h) 2878 <1> ; 0000100000000000b ISUID - set user id on exec (800h) 2879 <1> ; 0000010000000000b ISGID - set group id on exec (400h) 2880 <1> ; 0000001000000000b IEXTT - 1 = use extents (200h) 2881 <1> ; 0000000100000000b IREAD - read, owner (100h) 2882 <1> ; 0000000010000000b IWRITE - write, owner (80h) 2883 <1> ; 0000000001000000b IEXEC - execute, owner (40h) 2884 <1> ; 0000000000100000b read, group (20h) 2885 <1> ; 0000000000010000b write, group (10h) 2886 <1> ; 0000000000001000b execute, group (08h) 2887 <1> ; 0000000000000100b read, others (04h) 2888 <1> ; 0000000000000010b write, others (02h) 2889 <1> ; 0000000000000001b execute, others (01h) 2890 <1> 2891 <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices 2892 <1> ; 1000000000000000b IFREG - 0 = device file (8000h) 2893 <1> ; 0100000000000000b IFBLK - 1 = block device (4000h) 2894 <1> ; 0010000000000000b IFCHR - character special (2000h) -always 1- 2895 <1> ; 0001000000000000b IFIFO - fifo special (1000h) 2896 <1> ; 0000100000000000b IPIPE - pipe special (800h) ; 07/02/2020 2897 <1> ; 0000010000000000b IREDIR - redirected (400h) ; 07/02/2020 2898 <1> ; 0000001000000000b IEXTR - 1 = external device driver (200h) 2899 <1> ; 0000000100000000b IREAD - read, owner (100h) 2900 <1> ; 0000000010000000b IWRITE - write, owner (80h) 2901 <1> ; 0000000001000000b IEXEC - execute, owner (40h) 2902 <1> ; 0000000000100000b read, group (20h) 2903 <1> ; 0000000000010000b write, group (10h) 2904 <1> ; 0000000000001000b execute, group (08h) 2905 <1> ; 0000000000000100b read, others (04h) 2906 <1> ; 0000000000000010b write, others (02h) 2907 <1> ; 0000000000000001b execute, others (01h) 2908 <1> 2909 <1> alignb 2 2910 <1> 2911 <1> inode: 2912 <1> ;; 11/03/2013. 2913 <1> ;;Derived from UNIX v1 source code 'inode' structure (ux). 2914 <1> ;;i. 2915 <1> ; 2916 <1> ;i.flgs: resw 1 2917 <1> ;i.nlks: resb 1 2918 <1> ;i.uid: resb 1 2919 <1> ;i.size: resw 1 ; size 2920 <1> ;i.dskp: resw 8 ; 16 bytes 2921 <1> ;i.ctim: resd 1 2922 <1> ;i.mtim: resd 1 2923 <1> ;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1) 2924 <1> 2925 <1> ; 26/01/2020 2926 <1> ; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model 2927 <1> ; (15/09/2029 .. 18/12/2019) 2928 <1> 2929 00006B40 ???? <1> i.flgs: resw 1 ; /* mode and type of file */ 2930 00006B42 ???? <1> i.nlks: resw 1 ; /* number of links to file */ 2931 00006B44 ???? <1> i.uid: resw 1 ; /* owner's user id */ - 0 to 655535 - 2932 00006B46 ?? <1> i.gid: resb 1 ; /* owner's group id */ - o to 255 - 2933 00006B47 ?? <1> i.size_h: resb 1 ; /* number of bytes in file */ ; byte 5 2934 00006B48 ???????? <1> i.size: resd 1 ; size ; /* number of bytes in file */ 2935 00006B4C <1> i.dskp: resd 10 ; 40 bytes ; /* disk block addresses */ 2936 00006B74 ???????? <1> i.atim: resd 1 ; /* time last accessed */ 2937 00006B78 ???????? <1> i.mtim: resd 1 ; /* time last modified */ 2938 00006B7C ???????? <1> i.ctim: resd 1 ; /* time created */ 2939 <1> 2940 <1> I_SIZE equ $ - inode 2941 <1> 2942 <1> process: 2943 <1> ; 06/05/2015 2944 <1> ; 11/03/2013 - 05/02/2014 2945 <1> ;Derived from UNIX v1 source code 'proc' structure (ux). 2946 <1> ;p. 2947 <1> 2948 00006B80 <1> p.pid: resw nproc 2949 00006BA0 <1> p.ppid: resw nproc 2950 00006BC0 <1> p.break: resw nproc 2951 00006BE0 <1> p.ttyc: resb nproc ; console tty in Retro UNIX 8086 v1. 2952 00006BF0 <1> p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1. 2953 00006C00 <1> p.link: resb nproc 2954 00006C10 <1> p.stat: resb nproc 2955 <1> 2956 <1> ; 06/05/2015 (Retro UNIX 386 v1 feature only !) 2957 00006C20 <1> p.upage: resd nproc ; Physical address of the process's 2958 <1> ; 'user' structure 2959 <1> 2960 <1> P_SIZE equ $ - process 2961 <1> 2962 <1> ; fsp table (original UNIX v1) 2963 <1> ; 2964 <1> ;Entry 2965 <1> ; 15 0 2966 <1> ; 1 |---|---------------------------------------| 2967 <1> ; |r/w| i-number of open file | 2968 <1> ; |---|---------------------------------------| 2969 <1> ; | device number | 2970 <1> ; |-------------------------------------------| 2971 <1> ; (*) | offset pointer, i.e., r/w pointer to file | 2972 <1> ; |-------------------------------------------| 2973 <1> ; | flag that says | number of processes | 2974 <1> ; | file deleted | that have file open | 2975 <1> ; |-------------------------------------------| 2976 <1> ; 2 | | 2977 <1> ; |-------------------------------------------| 2978 <1> ; | | 2979 <1> ; |-------------------------------------------| 2980 <1> ; | | 2981 <1> ; |-------------------------------------------| 2982 <1> ; | | 2983 <1> ; |-------------------------------------------| 2984 <1> ; 3 | | 2985 <1> ; | | 2986 <1> ; 2987 <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 2988 <1> 2989 <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 2990 <1> 2991 <1> ;Entry 2992 <1> ; 15 7 0 2993 <1> ; 1 |-------------------------------------------| 2994 <1> ; | i-number of open file | 2995 <1> ; |-------------------------------------------| 2996 <1> ; | high word of 32 bit i-number | 2997 <1> ; |-------------------------------------------| 2998 <1> ; | open mode & status | device number | 2999 <1> ; |-------------------------------------------| 3000 <1> ; | reserved byte | open count | 3001 <1> ; |-------------------------------------------| 3002 <1> ; | offset pointer, i.e., r/w pointer to file | 3003 <1> ; |-------------------------------------------| 3004 <1> ; | 64 bit file offset pointer (bit 16-31) | 3005 <1> ; |-------------------------------------------| 3006 <1> ; | 64 bit file offset pointer (bit 32-47) | 3007 <1> ; |-------------------------------------------| 3008 <1> ; | 64 bit file offset pointer (bit 48-63) | 3009 <1> ; |-------------------------------------------| 3010 <1> ; 2 | | 3011 <1> ; |-------------------------------------------| 3012 <1> ; | | 3013 <1> ; |-------------------------------------------| 3014 <1> ; | | 3015 <1> ; |-------------------------------------------| 3016 <1> ; | | 3017 <1> ; |-------------------------------------------| 3018 <1> ; | | 3019 <1> 3020 <1> ; 22/11/2021 3021 <1> ; 21/07/2021 - Retro UNIX 386 v2 open file structure revision 3022 <1> 3023 <1> struc file ; open files (fsp) structure 3024 00000000 ???? <1> .inode: resw 1 ; inode number of open file (32 bit) 3025 00000002 ???? <1> .i32: resw 1 ; higher word of inode number (reserved) 3026 00000004 ?? <1> .drive: resb 1 ; logical drive (disk) number 3027 00000005 ?? <1> .flags: resb 1 ; open mode and status 3028 00000006 ?? <1> .count: resb 1 ; number of processes that have file open 3029 <1> ;.rsvd: resb 1 ; reserved byte (for next versions) 3030 00000007 ?? <1> .mnt: resb 1 ; mnttab index+1 (0 = not mounted) 3031 00000008 ???????? <1> .offset: resd 1 ; file offset/pointer (64 bit) 3032 0000000C ???????? <1> .o64: resd 1 ; higher 32 bit of file offset 3033 <1> .size: ; = 16 3034 <1> endstruc 3035 <1> 3036 <1> ; 01/01/2022 3037 <1> ; 22/11/2021 3038 <1> ;fp.size equ file.size 3039 <1> 3040 <1> ; 02/01/2022 3041 00006B40 <1> fsp: resb nfiles*16 ; (NFILES*fp.size) 3042 <1> ; 01/01/2022 3043 <1> ; 22/11/2021 (16/05/2021) 3044 <1> ;fsp: resb NFILES*16 ; (NFILES*fp.size) 3045 <1> ; 15/04/2015 3046 <1> ;fsp: resb nfiles*10 ; 11/05/2015 (8 -> 10) 3047 <1> 3048 00006E60 <1> bufp: resd (nbuf+2) ; will be initialized 3049 00006E80 ???????? <1> ii: resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0) 3050 <1> ; 22/11/2021 3051 00006E84 ?? <1> idev: resb 1 ; logical drive number of current inode, [ii] 3052 00006E85 ?? <1> cdev: resb 1 ; current logical drive number for current user 3053 <1> 3054 <1> ; 18/05/2015 3055 <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!) 3056 <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv') 3057 <1> ; 0 -> root device (which has Retro UNIX 8086 v1 file system) 3058 <1> ; 1 -> mounted device (which has Retro UNIX 8086 v1 file system) 3059 <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures) 3060 <1> ; 0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0 3061 <1> ; 1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1 3062 <1> ; 2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h 3063 <1> ; 3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h 3064 <1> ; 4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h 3065 <1> ; 5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h 3066 00006E86 ?? <1> rdev: resb 1 ; root device number ; Retro UNIX 8086 v1 feature only! 3067 <1> ; as above, for physical drives numbers in following table 3068 00006E87 ?? <1> mdev: resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only! 3069 <1> ; 15/04/2015 3070 00006E88 ?? <1> active: resb 1 3071 00006E89 ?? <1> resb 1 ; 09/06/2015 3072 00006E8A ???? <1> mpid: resw 1 3073 <1> ; 22/11/2021 (32 bit inode numbers) 3074 00006E8C ???????? <1> rootdir: resd 1 3075 00006E90 ???????? <1> mnti: resd 1 3076 <1> 3077 <1> ; 14/02/2014 3078 <1> ; Major Modification: Retro UNIX 8086 v1 feature only! 3079 <1> ; Single level run queue 3080 <1> ; (in order to solve sleep/wakeup lock) 3081 00006E94 ???? <1> runq: resw 1 3082 00006E96 ?? <1> imod: resb 1 3083 00006E97 ?? <1> imodx: resb 1 ; 09/01/2022 - Retro UNIX 386 v1.2 3084 00006E98 ?? <1> smod: resb 1 3085 00006E99 ?? <1> mmod: resb 1 3086 <1> ; resb 1 ; 09/01/2022 3087 00006E9A ?? <1> sysflg: resb 1 3088 <1> 3089 00006E9B ?? <1> alignb 4 3090 <1> 3091 <1> user: 3092 <1> ; 01/01/2022 3093 <1> ; 04/12/2021 - Retro UNIX 386 v1.2 3094 <1> ; 24/10/2021 3095 <1> ; 18/10/2021 3096 <1> ; 10/06/2021 3097 <1> ; 30/05/2021 3098 <1> ; 29/05/2021 3099 <1> ; 21/05/2021 3100 <1> ; 20/05/2021 3101 <1> ; 16/05/2021 3102 <1> ; 01/05/2021 3103 <1> ; 27/03/2021 3104 <1> ; 17/04/2020, 28/04/2020 3105 <1> ; 25/03/2020, 28/03/2020 3106 <1> ; 20/03/2020, 22/03/2020, 23/03/2020 3107 <1> ; 05/03/2020, 08/03/2020, 14/03/2020 3108 <1> ; 07/02/2020 - Retro UNIX 386 v2 3109 <1> ; 3110 <1> ; 27/02/2017 - TRDOS 386 3111 <1> ; 13/01/2017 - TRDOS 386 3112 <1> ; 10/01/2017 - TRDOS 386 3113 <1> ; 19/12/2016 - TRDOS 386 3114 <1> ; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 3115 <1> ; [u.pri] usage method modification 3116 <1> ; 3117 <1> ; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names) 3118 <1> ; 18/10/2015 3119 <1> ; 12/10/2015 3120 <1> ; 21/09/2015 3121 <1> ; 24/07/2015 3122 <1> ; 16/06/2015 3123 <1> ; 09/06/2015 3124 <1> ; 11/05/2015 3125 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications) 3126 <1> ; 10/10/2013 3127 <1> ; 11/03/2013. 3128 <1> ;Derived from UNIX v1 source code 'user' structure (ux). 3129 <1> ;u. 3130 <1> 3131 00006E9C ???????? <1> u.sp: resd 1 ; esp (kernel stack at the beginning of 'sysent') 3132 00006EA0 ???????? <1> u.usp: resd 1 ; esp (kernel stack points to user's registers) 3133 00006EA4 ???????? <1> u.r0: resd 1 ; eax 3134 00006EA8 ???? <1> u.cdir: resw 1 3135 00006EAA ???? <1> resw 1 ; 28/03/2020 - reserved for 32 bit inode number 3136 <1> ;u.cdrv: resw 1 ; 17/04/2020 (dword alignment) 3137 00006EAC ?? <1> u.cdrv: resb 1 ; 01/05/2021 3138 00006EAD ?? <1> resb 1 ; 01/05/2021 (dword alignment) 3139 00006EAE <1> u.fp: resb 10 ; Retro UNIX 386 v1 3140 <1> ;u.fp: resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 3141 <1> u.fsp: ; 16/05/2021 3142 00006EB8 ???????? <1> u.fofp: resd 1 ; 16/05/2021 (pointer to fsp entry) 3143 00006EBC ???????? <1> u.dirp: resd 1 3144 00006EC0 ???????? <1> u.namep: resd 1 3145 00006EC4 ???????? <1> u.off: resd 1 3146 <1> ; resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr 3147 00006EC8 ???????? <1> u.base: resd 1 3148 00006ECC ???????? <1> u.count: resd 1 3149 00006ED0 ???????? <1> u.nread: resd 1 3150 00006ED4 ???????? <1> u.break: resd 1 ; break 3151 <1> ; 16/05/2021 (Retro UNIX 386 v2) 3152 00006ED8 ?? <1> u.mode: resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode) 3153 <1> ; 10/01/2017 (TRDOS 386, relocation and dword alignment) 3154 <1> ; tty number (rtty, rcvt, wtty) 3155 00006ED9 ?? <1> u.ttyn: resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only ! 3156 00006EDA ???? <1> u.ttyp: resw 1 3157 00006EDC <1> u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 3158 <1> ;u.pri: resw 1 ; 14/02/2014 3159 00006EEC ?? <1> u.quant: resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant) 3160 00006EED ?? <1> resb 1 ; 17/04/2020 3161 00006EEE ?? <1> u.pri: resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2) 3162 00006EEF ?? <1> resb 1 ; 17/04/2020 3163 <1> ; 10/06/2021 3164 <1> ;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2 3165 <1> ; resw 1 ; reserved ; 21/05/2021 3166 00006EF0 ???? <1> u.intr: resw 1 3167 00006EF2 ???? <1> u.quit: resw 1 3168 <1> ;u.emt: resw 1 ; 10/10/2013 3169 <1> ;u.ilgins: resw 1 ; 10/01/2017 3170 <1> ;u.cdrv: resw 1 ; cdev ; 17/04/2020 (moved to up) 3171 <1> ;u.uid: resb 1 ; uid 3172 <1> ;u.ruid: resb 1 3173 00006EF4 ?? <1> u.bsys: resb 1 3174 00006EF5 ?? <1> u.uno: resb 1 3175 00006EF6 ???? <1> u.uid: resw 1 ; uid ; 27/03/2021 - Retro UNIX 386 v2 3176 00006EF8 ???? <1> u.ruid: resw 1 ; 16 bit uid 3177 00006EFA ?? <1> u.gid: resb 1 ; gid ; 27/03/2021 - Retro UNIX 386 v2 3178 00006EFB ?? <1> u.rgid: resb 1 3179 <1> ; 20/05/2021 - Retro UNIX 386 v2 3180 00006EFC ???????? <1> u.procp: resd 1 ; /* pointer to proc structure */ 3181 00006F00 ???????? <1> u.upage: resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only ! 3182 00006F04 ???????? <1> u.pgdir: resd 1 ; 09/03/2015 (page dir addr of process) 3183 00006F08 ???????? <1> u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process) 3184 00006F0C ???????? <1> u.pbase: resd 1 ; 20/05/2015 (physical base/transfer address) 3185 <1> ; 24/10/2021 (32 bit value for Retro UNIX 386 v2) 3186 00006F10 ???????? <1> u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page) 3187 <1> ;u.pncount: resw 1 3188 <1> ; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir') 3189 <1> ;u.pnbase: resd 1 3190 <1> ; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir') 3191 00006F14 ???? <1> u.rsvd: resw 1 ; 04/12/2021 (dword alignment) 3192 <1> ; 09/06/2015 3193 00006F16 ?? <1> u.kcall: resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign 3194 <1> ; 08/03/2020 (block device read/write flag for 'sioreg') 3195 00006F17 ?? <1> u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite) 3196 <1> ; 24/07/2015 - 24/06/2015 3197 <1> ;u.args: resd 1 ; arguments list (line) offset from start of [u.upage] 3198 <1> ; (arg list/line is from offset [u.args] to 4096 in [u.upage]) 3199 <1> ; ([u.args] points to argument count -argc- address offset) 3200 <1> ; 24/06/2015 3201 <1> ;u.core: resd 1 ; physical start address of user's memory space (for sys exec) 3202 <1> ;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec) 3203 <1> ; last error number 3204 00006F18 ???????? <1> u.error: resd 1 ; 28/07/2013 - 09/03/2015 3205 <1> ; Retro UNIX 8086/386 v1 feature only! 3206 <1> ; 21/09/2015 (debugging - page fault analyze) 3207 00006F1C ???????? <1> u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr) 3208 <1> ; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig) 3209 <1> ; u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits 3210 <1> ; u.srb: resb 1 ; signal handling/responding method 3211 <1> ; u.snum: resb 1 ; signal number (last signal number) 3212 <1> ; u.exit: resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2 3213 <1> ; u.s_lock: resb 1 ; signal handling (phase) lock 3214 <1> ; u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address 3215 <1> ; u.s_time: resd 1 ; signal time in unix epoch format 3216 <1> ; 19/12/2016 (TRDOS 386) 3217 <1> ; u.tcb: resd 1 ; Timer callback address/flag which will be used by timer int 3218 <1> ; 13/01/2017 (TRDOS 386) 3219 <1> ; u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele') 3220 <1> ; u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user) 3221 <1> ; 26/02/2017 (TRDOS 386) 3222 <1> ; u.irqc: resb 1 ; Count of IRQ callback services (IRQs in use) 3223 <1> ; 28/02/2017 (TRDOS 386) 3224 <1> ; u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0) 3225 <1> ; u.r_lock: resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock) 3226 <1> ; u.r_mode: resb 1 ; running mode during hardware interrupt 3227 <1> ; 07/02/2020 - Retro UNIX 386 v2 3228 <1> ; u.redir: resb 1 ; device func redirection permitted by user (if u.redir > 0) 3229 <1> ; 26/02/2020 - Retro UNIX 386 v2 3230 <1> ; u.rwm: resb 1 ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 3231 <1> ; 24/02/2020 - Retro UNIX 386 v2 3232 <1> ; 24/10/2021 (32 bit value) 3233 <1> ; u.scount: resd 1 ; sub byte count ; 22/03/2020 3234 <1> ; 07/03/2020 - Retro UNIX 386 v2 3235 <1> ; u.bps: resw 1 ; u.bps = bytes per sector, for readi and writei 3236 <1> ; resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers) 3237 <1> ; 23/03/2020 - Retro UNIX 386 v2 3238 <1> ; u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'- 3239 <1> ; 28/04/2020 - Retro UNIX 386 v2 3240 <1> ; u.lock: resb 1 ; Device lock flag (bit 0 is for device/disk read/write) 3241 <1> ; 24/04/2020 3242 <1> ; 17/04/2020 - Retro UNIX 386 v2 3243 <1> ; u.ifs: resb 1 ; (current) installable file system driver index number 3244 <1> ; 25/03/2020 3245 <1> ; 20/03/2020 3246 <1> ;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count) 3247 <1> 3248 <1> ; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi') 3249 <1> ;u.limit: resd 1 ; disk/file size limit for block device read/write ('sioreg') 3250 <1> ; resd 1 ; 08/03/2020 - 64 bit limit (disk size in bytes) 3251 <1> ; ; 26/02/2020 - Retro UNIX 386 v2 3252 <1> ;u.sector: resd 1 ; current sector (for readi and writei, device r/w) 3253 <1> ;u.buffer: resd 1 ; current buffer (for readi and writei, device r/w) 3254 <1> ; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup) 3255 <1> ;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers 3256 <1> ;u.zero: resw 1 ; 14/03/2020 - Must be ZERO for current version 3257 <1> ; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup) 3258 <1> ; u.device: resd 1 ; (blk, chr) device description table (entry) address 3259 <1> ; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup) 3260 <1> ; u.function: resd 1 ; device function (read, write) 3261 <1> ; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei) 3262 <1> ; u.buffer: resd 1 ; for saving buffer header address for 'poke' 3263 <1> ; u.inode: resw 1 ; for saving inode number of current (device) inode 3264 <1> ; resw 1 ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number 3265 <1> ; u.idev: resb 1 ; for saving logical drv number of current (dev) inode 3266 <1> ; 04/12/2021 3267 <1> ; u.rsvd2: resw 1 ; (for dword alignment) 3268 <1> ; 27/02/2017 (TRDOS 386) 3269 <1> ;; 31/12/2021 - temporary ! 3270 <1> ; u.fpsave: resb 1 ; TRDOS 386, 'save/restore FPU registers' flag 3271 <1> alignb 4 3272 <1> ; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 3273 <1> ;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers 3274 <1> ; 30/05/2021 - Retro UNIX 386 v2 3275 <1> ; u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers 3276 <1> alignb 4 3277 <1> 3278 <1> U_SIZE equ $ - user 3279 <1> 3280 <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec') 3281 00006F20 ???????? <1> pcore: resd 1 ; physical start address of user's memory space (for sys exec) 3282 00006F24 ???????? <1> ecore: resd 1 ; physical start address of user's memory space (for sys exec) 3283 00006F28 ???????? <1> nbase: resd 1 ; physical base address for 'namei' & 'sysexec' 3284 <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec' 3285 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount') 3286 00006F2C ???????? <1> ncount: resd 1 ; remain byte count in page for 'namei' & 'sysexec' 3287 <1> ;argc: resw 1 ; argument count for 'sysexec' 3288 <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc') 3289 00006F30 ???????? <1> argc: resd 1 ; argument count for 'sysexec' 3290 00006F34 ???????? <1> argv: resd 1 ; argument list (recent) address for 'sysexec' 3291 <1> 3292 <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning 3293 <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1 3294 00006F38 ?? <1> rw: resb 1 ;; Read/Write sign (iget) 3295 00006F39 ?? <1> rwdsk: resb 1 ;; Read/Write function number (diskio) - 16/06/2015 3296 00006F3A ?? <1> mget_rw: resb 1 ; 22/11/2021 3297 00006F3B ?? <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015 3298 <1> 3299 <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility 3300 <1> level: resd 0 ; level, level+1, level+2, level+3 ; for 'mget' procedure 3301 <1> 3302 <1> ; (02/01/2022) 3303 <1> ; 27/11/2021 3304 <1> ; these are will be used for disk block allocation ('alloc' proc) 3305 <1> free_map_offset: 3306 00006F3C ???????? <1> resd 1 3307 00006F40 ???????? <1> free_map_index: resd 1 3308 <1> free_map_sector: 3309 00006F44 ???????? <1> resd 1 3310 <1> ;free_map_buffer: 3311 <1> ; resd 1 3312 <1> 3313 <1> ; 27/11/2021 - temporary ! 3314 00006F48 ???????? <1> s.time: resd 1 3315 <1> 3316 <1> ;alignb 4 3317 <1> 3318 <1> ; (02/01/2022) 3319 <1> ; 22/08/2015 3320 <1> ;buffer: resb nbuf * 520 3321 <1> 3322 00006F4C ???????????????? <1> sb0: resd 2 3323 <1> ;s: 3324 <1> ; (root disk) super block buffer 3325 <1> systm: 3326 <1> ; 27/11/2021 - Retro UNIX 386 v2 compatible super block 3327 <1> ; 13/11/2015 (Retro UNIX 386 v1) 3328 <1> ; 11/03/2013. 3329 <1> ;Derived from UNIX v1 source code 'systm' structure (ux). 3330 <1> ;s. 3331 <1> 3332 <1> ;resw 1 3333 <1> ;resb 360 ; 2880 sectors ; original UNIX v1 value: 128 3334 <1> ;resw 1 3335 <1> ;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64 3336 <1> ;s.time: resd 1 3337 <1> ;s.syst: resd 1 3338 <1> ;s.wait_: resd 1 ; wait 3339 <1> ;s.idlet: resd 1 3340 <1> ;s.chrgt: resd 1 3341 <1> ;s.drerr: resw 1 3342 <1> 3343 <1> ; 27/11/2021 3344 00006F54 <1> resb 512 3345 <1> 3346 <1> ;S_SIZE equ $ - systm 3347 <1> 3348 <1> ;resb 512-S_SIZE ; 03/06/2015 3349 <1> 3350 00007154 ???????????????? <1> sb1: resd 2 3351 <1> ; (mounted disk) super block buffer 3352 <1> mount: 3353 0000715C <1> resb 512 ; 03/06/2015 3354 <1> 3355 <1> ; 10/01/2022 3356 0000735C <1> dbli_buf: resb 512 ; double indir ptr buff for 'itrunc', 'tloop' 3357 0000755C <1> trpi_buf: resb 512 ; triple indir ptr buff for 'itrunc', 'tloop' 3358 <1> 3359 <1> ;/ ux -- unix 3360 <1> ; 3361 <1> ;systm: 3362 <1> ; 3363 <1> ; .=.+2 3364 <1> ; .=.+128. 3365 <1> ; .=.+2 3366 <1> ; .=.+64. 3367 <1> ; s.time: .=.+4 3368 <1> ; s.syst: .=.+4 3369 <1> ; s.wait: .=.+4 3370 <1> ; s.idlet:.=.+4 3371 <1> ; s.chrgt:.=.+4 3372 <1> ; s.drerr:.=.+2 3373 <1> ;inode: 3374 <1> ; i.flgs: .=.+2 3375 <1> ; i.nlks: .=.+1 3376 <1> ; i.uid: .=.+1 3377 <1> ; i.size: .=.+2 3378 <1> ; i.dskp: .=.+16. 3379 <1> ; i.ctim: .=.+4 3380 <1> ; i.mtim: .=.+4 3381 <1> ; . = inode+32. 3382 <1> ;mount: .=.+1024. 3383 <1> ;proc: 3384 <1> ; p.pid: .=.+[2*nproc] 3385 <1> ; p.dska: .=.+[2*nproc] 3386 <1> ; p.ppid: .=.+[2*nproc] 3387 <1> ; p.break:.=.+[2*nproc] 3388 <1> ; p.link: .=.+nproc 3389 <1> ; p.stat: .=.+nproc 3390 <1> ;tty: 3391 <1> ; . = .+[ntty*8.] 3392 <1> ;fsp: .=.+[nfiles*8.] 3393 <1> ;bufp: .=.+[nbuf*2]+6 3394 <1> ;sb0: .=.+8 3395 <1> ;sb1: .=.+8 3396 <1> ;swp: .=.+8 3397 <1> ;ii: .=.+2 3398 <1> ;idev: .=.+2 3399 <1> ;cdev: .=.+2 3400 <1> ;deverr: .=.+12. 3401 <1> ;active: .=.+2 3402 <1> ;rfap: .=.+2 3403 <1> ;rkap: .=.+2 3404 <1> ;tcap: .=.+2 3405 <1> ;tcstate:.=.+2 3406 <1> ;tcerrc: .=.+2 3407 <1> ;mnti: .=.+2 3408 <1> ;mntd: .=.+2 3409 <1> ;mpid: .=.+2 3410 <1> ;clockp: .=.+2 3411 <1> ;rootdir:.=.+2 3412 <1> ;toutt: .=.+16. 3413 <1> ;touts: .=.+32. 3414 <1> ;runq: .=.+6 3415 <1> ; 3416 <1> ;wlist: .=.+40. 3417 <1> ;cc: .=.+30. 3418 <1> ;cf: .=.+31. 3419 <1> ;cl: .=.+31. 3420 <1> ;clist: .=.+510. 3421 <1> ;imod: .=.+1 3422 <1> ;smod: .=.+1 3423 <1> ;mmod: .=.+1 3424 <1> ;uquant: .=.+1 3425 <1> ;sysflg: .=.+1 3426 <1> ;pptiflg:.=.+1 3427 <1> ;ttyoch: .=.+1 3428 <1> ; .even 3429 <1> ; .=.+100.; sstack: 3430 <1> ;buffer: .=.+[ntty*140.] 3431 <1> ; .=.+[nbuf*520.] 3432 <1> ; 3433 <1> ; . = core-64. 3434 <1> ;user: 3435 <1> ; u.sp: .=.+2 3436 <1> ; u.usp: .=.+2 3437 <1> ; u.r0: .=.+2 3438 <1> ; u.cdir: .=.+2 3439 <1> ; u.fp: .=.+10. 3440 <1> ; u.fofp: .=.+2 3441 <1> ; u.dirp: .=.+2 3442 <1> ; u.namep: .=.+2 3443 <1> ; u.off: .=.+2 3444 <1> ; u.base: .=.+2 3445 <1> ; u.count: .=.+2 3446 <1> ; u.nread: .=.+2 3447 <1> ; u.break: .=.+2 3448 <1> ; u.ttyp: .=.+2 3449 <1> ; u.dirbuf:.=.+10. 3450 <1> ; u.pri: .=.+2 3451 <1> ; u.intr: .=.+2 3452 <1> ; u.quit: .=.+2 3453 <1> ; u.emt: .=.+2 3454 <1> ; u.ilgins:.=.+2 3455 <1> ; u.cdev: .=.+2 3456 <1> ; u.uid: .=.+1 3457 <1> ; u.ruid: .=.+1 3458 <1> ; u.bsys: .=.+1 3459 <1> ; u.uno: .=.+1 3460 <1> ;. = core 2741 2742 ; 27/12/2021 2743 0000775C buffer: resb (nbuf*520) 2744 2745 bss_end: 2746 2747 ; 12/12/2021 2748 BSS_SIZE equ bss_end - bss_start 2749 2750 ; 27/12/2013 2751 _end: ; end of kernel code (and read only data, just before bss)