1 ; **************************************************************************** 2 ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.22 3 ; ---------------------------------------------------------------------------- 4 ; NASM version 2.15 (unix386.s) 5 ; 6 ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix) 7 ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013) 8 ; 9 ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 10 ; (v0.1 - Beginning: 11/07/2012) 11 ; 12 ; [ Last Modification: 24/07/2022 ] ; 2022 modification (previous: 12/7/2022) 13 ; 14 ; Derived from UNIX Operating System (v1.0 for PDP-11) 15 ; (Original) Source Code by Ken Thompson (1971-1972) 16 ; 17 ; 18 ; 19 ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999) 20 ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details. 21 ; 22 ; **************************************************************************** 23 ; 14/07/2022 - 24/07/2022 (v0.2.0.22) 24 ; 12/07/2022 (v0.2.0.21) 25 ; 15/05/2022 - 14/06/2022 (v0.2.0.20) 26 ; 04/02/2016 (v0.2.0.17) - 29/04/2022 (v0.2.0.18) - 09/05/2022 (v0.2.0.19) 27 28 ; Assembler: NASM 2.15 29 ; nasm unix386.s -l unix386.lst -o unix386 -Z error.txt 30 31 ; 24/12/2013 32 33 ; Entering protected mode: 34 ; Derived from 'simple_asm.txt' source code file and 35 ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003) 36 ; (gregor.brunmar@home.se) 37 ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode 38 ; 39 40 ; "The Real, Protected, Long mode assembly tutorial for PCs" 41 ; by Michael Chourdakis (2009) 42 ; http://www.codeproject.com/Articles/45788/ 43 ; http://www.michaelchourdakis.com 44 ; 45 46 ; Global Descriptor Table: 47 ; Derived from 'head.s" source code of Linux v1.0 kernel 48 ; by Linus Torvalds (1991-1992) 49 ; 50 51 KLOAD equ 10000h ; Kernel loading address 52 ; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 53 KCODE equ 08h ; Code segment descriptor (ring 0) 54 KDATA equ 10h ; Data segment descriptor (ring 0) 55 ; 19/03/2015 56 UCODE equ 1Bh ; 18h + 3h (ring 3) 57 UDATA equ 23h ; 20h + 3h (ring 3) 58 ; 24/03/2015 59 TSS equ 28h ; Task state segment descriptor (ring 0) 60 ; 19/03/2015 61 CORE equ 400000h ; Start of USER's virtual/linear address space 62 ; (at the end of the 1st 4MB) 63 ECORE equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB) 64 ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT) 65 66 ; 27/12/2013 67 KEND equ KLOAD + 65536 ; (28/12/2013) (end of kernel space) 68 69 ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc) 70 ;--------- CMOS TABLE LOCATION ADDRESS'S ------------------------------------- 71 CMOS_SECONDS EQU 00H ; SECONDS (BCD) 72 CMOS_MINUTES EQU 02H ; MINUTES (BCD) 73 CMOS_HOURS EQU 04H ; HOURS (BCD) 74 CMOS_DAY_WEEK EQU 06H ; DAY OF THE WEEK (BCD) 75 CMOS_DAY_MONTH EQU 07H ; DAY OF THE MONTH (BCD) 76 CMOS_MONTH EQU 08H ; MONTH (BCD) 77 CMOS_YEAR EQU 09H ; YEAR (TWO DIGITS) (BCD) 78 CMOS_CENTURY EQU 32H ; DATE CENTURY BYTE (BCD) 79 CMOS_REG_A EQU 0AH ; STATUS REGISTER A 80 CMOS_REG_B EQU 00BH ; STATUS REGISTER B ALARM 81 CMOS_REG_C EQU 00CH ; STATUS REGISTER C FLAGS 82 CMOS_REG_D EQU 0DH ; STATUS REGISTER D BATTERY 83 CMOS_SHUT_DOWN EQU 0FH ; SHUTDOWN STATUS COMMAND BYTE 84 ;---------------------------------------- 85 ; CMOS EQUATES FOR THIS SYSTEM ; 86 ;----------------------------------------------------------------------------- 87 CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 88 CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 89 NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 90 ; HIGH BIT OF CMOS LOCATION ADDRESS 91 92 ; Memory Allocation Table Address 93 ; 05/11/2014 94 ; 31/10/2014 95 MEM_ALLOC_TBL equ 100000h ; Memory Allocation Table at the end of 96 ; the 1st 1 MB memory space. 97 ; (This address must be aligned 98 ; on 128 KB boundary, if it will be 99 ; changed later.) 100 ; ((lower 17 bits of 32 bit M.A.T. 101 ; address must be ZERO)). 102 ; ((((Reason: 32 bit allocation 103 ; instructions, dword steps))) 104 ; (((byte >> 12 --> page >> 5))) 105 ;04/11/2014 106 PDE_A_PRESENT equ 1 ; Present flag for PDE 107 PDE_A_WRITE equ 2 ; Writable (write permission) flag 108 PDE_A_USER equ 4 ; User (non-system/kernel) page flag 109 ; 110 PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 111 PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 112 PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 113 PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 114 115 ; 17/02/2015 (unix386.s) 116 ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s) 117 DPT_SEGM equ 09000h ; FDPT segment (EDD v1.1, EDD v3) 118 ; 119 HD0_DPT equ 0 ; Disk parameter table address for hd0 120 HD1_DPT equ 32 ; Disk parameter table address for hd1 121 HD2_DPT equ 64 ; Disk parameter table address for hd2 122 HD3_DPT equ 96 ; Disk parameter table address for hd3 123 124 125 ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0) 126 ; (HDPT: Programmer's Guide to the AMIBIOS, 1993) 127 ; 128 FDPT_CYLS equ 0 ; 1 word, number of cylinders 129 FDPT_HDS equ 2 ; 1 byte, number of heads 130 FDPT_TT equ 3 ; 1 byte, A0h = translated FDPT with logical values 131 ; otherwise it is standard FDPT with physical values 132 FDPT_PCMP equ 5 ; 1 word, starting write precompensation cylinder 133 ; (obsolete for IDE/ATA drives) 134 FDPT_CB equ 8 ; 1 byte, drive control byte 135 ; Bits 7-6 : Enable or disable retries (00h = enable) 136 ; Bit 5 : 1 = Defect map is located at last cyl. + 1 137 ; Bit 4 : Reserved. Always 0 138 ; Bit 3 : Set to 1 if more than 8 heads 139 ; Bit 2-0 : Reserved. Alsways 0 140 FDPT_LZ equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives) 141 FDPT_SPT equ 14 ; 1 byte, sectors per track 142 143 ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993) 144 ; (11 bytes long) will be used by diskette handler/bios 145 ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986). 146 147 [BITS 16] ; We need 16-bit intructions for Real mode 148 149 [ORG 0] 150 ; 12/11/2014 151 ; Save boot drive number (that is default root drive) 152 00000000 8816[585C] mov [boot_drv], dl ; physical drv number 153 154 ; Determine installed memory 155 ; 31/10/2014 156 ; 157 00000004 B801E8 mov ax, 0E801h ; Get memory size 158 00000007 CD15 int 15h ; for large configurations 159 00000009 7308 jnc short chk_ms 160 0000000B B488 mov ah, 88h ; Get extended memory size 161 0000000D CD15 int 15h 162 ; 163 ;mov al, 17h ; Extended memory (1K blocks) low byte 164 ;out 70h, al ; select CMOS register 165 ;in al, 71h ; read data (1 byte) 166 ;mov cl, al 167 ;mov al, 18h ; Extended memory (1K blocks) high byte 168 ;out 70h, al ; select CMOS register 169 ;in al, 71h ; read data (1 byte) 170 ;mov ch, al 171 ; 172 0000000F 89C1 mov cx, ax 173 00000011 31D2 xor dx, dx 174 chk_ms: 175 00000013 890E[C25E] mov [mem_1m_1k], cx 176 00000017 8916[C45E] mov [mem_16m_64k], dx 177 ; 05/11/2014 178 ;and dx, dx 179 ;jz short L2 180 0000001B 81F90004 cmp cx, 1024 181 0000001F 7351 jnb short L0 182 ; insufficient memory_error 183 ; Minimum 2 MB memory is needed... 184 ; 05/11/2014 185 ; (real mode error printing) 186 00000021 FB sti 187 00000022 BE[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 ; 04/02/2022 201 ; 05/11/2014 202 msg_out_of_memory: 203 00000036 070D0A db 07h, 0Dh, 0Ah 204 00000039 496E73756666696369- db 'Insufficient memory !' 204 00000042 656E74206D656D6F72- 204 0000004B 792021 205 0000004E 0D0A db 0Dh, 0Ah 206 _int13h_48h_buffer: 207 ; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc') 208 00000050 284D696E696D756D20- db '(Minimum 2MB memory is needed.)' 208 00000059 324D42206D656D6F72- 208 00000062 79206973206E656564- 208 0000006B 65642E29 209 0000006F 0D0A00 db 0Dh, 0Ah, 0 210 211 L0: 212 %include 'diskinit.inc' ; 07/03/2015 213 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKINIT.INC 214 <1> ; Last Modification: 12/07/2022 215 <1> ; ************************************************************************ 216 <1> ; Ref: Retro UNIX 386 v1.1 'diskinit.inc' modification: 12/07/2022 217 <1> 218 <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project) 219 <1> 220 <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION /////////////// 221 <1> 222 <1> ; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18) 223 <1> ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2) 224 <1> ; 10/12/2014 - 02/02/2015 - dsectrm2.s 225 <1> ;L0: 226 <1> ; 12/11/2014 (Retro UNIX 386 v1 - beginning) 227 <1> ; Detecting disk drives... (by help of ROM-BIOS) 228 00000072 BA7F00 <1> mov dx, 7Fh 229 <1> L1: 230 00000075 FEC2 <1> inc dl 231 00000077 B441 <1> mov ah, 41h ; Check extensions present 232 <1> ; Phoenix EDD v1.1 - EDD v3 233 00000079 BBAA55 <1> mov bx, 55AAh 234 0000007C CD13 <1> int 13h 235 0000007E 721A <1> jc short L2 236 <1> 237 00000080 81FB55AA <1> cmp bx, 0AA55h 238 00000084 7514 <1> jne short L2 239 00000086 FE06[5B5C] <1> inc byte [hdc] ; count of hard disks (EDD present) 240 0000008A 8816[5A5C] <1> mov [last_drv], dl ; last hard disk number 241 0000008E BB[DE5B] <1> mov bx, hd0_type - 80h 242 00000091 01D3 <1> add bx, dx 243 00000093 880F <1> mov [bx], cl ; Interface support bit map in CX 244 <1> ; Bit 0 - 1, Fixed disk access subset ready 245 <1> ; Bit 1 - 1, Drv locking and ejecting ready 246 <1> ; Bit 2 - 1, Enhanced Disk Drive Support 247 <1> ; (EDD) ready (DPTE ready) 248 <1> ; Bit 3 - 1, 64bit extensions are present 249 <1> ; (EDD-3) 250 <1> ; Bit 4 to 15 - 0, Reserved 251 00000095 80FA83 <1> cmp dl, 83h ; drive number < 83h 252 00000098 72DB <1> jb short L1 253 <1> L2: 254 <1> ; 23/11/2014 255 <1> ; 19/11/2014 256 0000009A 30D2 <1> xor dl, dl ; 0 257 <1> ; 04/02/2016 (esi -> si) 258 0000009C BE[5C5C] <1> mov si, fd0_type 259 <1> L3: 260 <1> ; 14/01/2015 261 0000009F 8816[595C] <1> mov [drv], dl 262 <1> ; 263 000000A3 B408 <1> mov ah, 08h ; Return drive parameters 264 000000A5 CD13 <1> int 13h 265 000000A7 7210 <1> jc short L4 266 <1> ; BL = drive type (for floppy drives) 267 <1> ; DL = number of floppy drives 268 <1> ; 269 <1> ; ES:DI = Address of DPT from BIOS 270 <1> ; 271 000000A9 881C <1> mov [si], bl ; Drive type 272 <1> ; 4 = 1.44 MB, 80 track, 3 1/2" 273 <1> ; 14/01/2015 274 000000AB E8BB01 <1> call set_disk_parms 275 <1> ; 10/12/2014 276 000000AE 81FE[5C5C] <1> cmp si, fd0_type 277 000000B2 7705 <1> ja short L4 278 000000B4 46 <1> inc si ; fd1_type 279 000000B5 B201 <1> mov dl, 1 280 000000B7 EBE6 <1> jmp short L3 281 <1> L4: 282 <1> ; Older BIOS (INT 13h, AH = 48h is not available) 283 000000B9 B27F <1> mov dl, 7Fh 284 <1> ; 24/12/2014 (Temporary) 285 000000BB 803E[5B5C]00 <1> cmp byte [hdc], 0 ; EDD present or not ? 286 <1> ;ja L10 ; yes, all fixed disk operations 287 <1> ; will be performed according to 288 <1> ; present EDD specification 289 <1> ; 02/01/2022 290 000000C0 7603 <1> jna short L5 291 000000C2 E99100 <1> jmp L10 292 <1> L5: 293 000000C5 FEC2 <1> inc dl 294 000000C7 8816[595C] <1> mov [drv], dl 295 000000CB 8816[5A5C] <1> mov [last_drv], dl ; 14/01/2015 296 000000CF B408 <1> mov ah, 08h ; Return drive parameters 297 000000D1 CD13 <1> int 13h ; (conventional function) 298 <1> ;jc L13 ; fixed disk drive not ready 299 <1> ; 02/01/2022 300 000000D3 7303 <1> jnc short L6 301 000000D5 E98301 <1> jmp L13 302 <1> L6: 303 000000D8 8816[5B5C] <1> mov [hdc], dl ; number of drives 304 <1> ;; 14/01/2013 305 <1> ;;push cx 306 000000DC E88A01 <1> call set_disk_parms 307 <1> ;;pop cx 308 <1> ; 309 <1> ;;and cl, 3Fh ; sectors per track (bits 0-6) 310 000000DF 8A16[595C] <1> mov dl, [drv] 311 000000E3 BB0401 <1> mov bx, 65*4 ; hd0 parameters table (INT 41h) 312 000000E6 80FA80 <1> cmp dl, 80h 313 000000E9 7603 <1> jna short L7 314 000000EB 83C314 <1> add bx, 5*4 ; hd1 parameters table (INT 46h) 315 <1> L7: 316 000000EE 31C0 <1> xor ax, ax 317 000000F0 8ED8 <1> mov ds, ax 318 000000F2 8B37 <1> mov si, [bx] 319 000000F4 8B4702 <1> mov ax, [bx+2] 320 000000F7 8ED8 <1> mov ds, ax 321 000000F9 3A4C0E <1> cmp cl, [si+FDPT_SPT] ; sectors per track 322 <1> ;jne L12 ; invalid FDPT 323 <1> ; 02/01/2022 324 000000FC 7403 <1> je short L7_8 325 000000FE E95601 <1> jmp L12 326 <1> L7_8: 327 00000101 BF0000 <1> mov di, HD0_DPT 328 00000104 80FA80 <1> cmp dl, 80h 329 00000107 7603 <1> jna short L8 330 00000109 BF2000 <1> mov di, HD1_DPT 331 <1> L8: 332 <1> ; 30/12/2014 333 0000010C B80090 <1> mov ax, DPT_SEGM 334 0000010F 8EC0 <1> mov es, ax 335 <1> ; 24/12/2014 336 00000111 B90800 <1> mov cx, 8 337 00000114 F3A5 <1> rep movsw ; copy 16 bytes to the kernel's DPT location 338 00000116 8CC8 <1> mov ax, cs 339 00000118 8ED8 <1> mov ds, ax 340 <1> ; 02/02/2015 341 0000011A 8A0E[595C] <1> mov cl, [drv] 342 0000011E 88CB <1> mov bl, cl 343 00000120 B8F001 <1> mov ax, 1F0h 344 00000123 80E301 <1> and bl, 1 345 00000126 7406 <1> jz short L9 346 00000128 C0E304 <1> shl bl, 4 347 0000012B 2D8000 <1> sub ax, 1F0h-170h 348 <1> L9: 349 0000012E AB <1> stosw ; I/O PORT Base Address (1F0h, 170h) 350 0000012F 050602 <1> add ax, 206h 351 00000132 AB <1> stosw ; CONTROL PORT Address (3F6h, 376h) 352 00000133 88D8 <1> mov al, bl 353 00000135 04A0 <1> add al, 0A0h 354 00000137 AA <1> stosb ; Device/Head Register upper nibble 355 <1> ; 356 00000138 FE06[595C] <1> inc byte [drv] 357 0000013C BB[DE5B] <1> mov bx, hd0_type - 80h 358 0000013F 01CB <1> add bx, cx 359 00000141 800F80 <1> or byte [bx], 80h ; present sign (when lower nibble is 0) 360 00000144 A0[5B5C] <1> mov al, [hdc] 361 00000147 FEC8 <1> dec al 362 <1> ;jz L13 363 <1> ; 02/01/2022 364 00000149 7408 <1> jz short L9_10 365 0000014B 80FA80 <1> cmp dl, 80h 366 <1> ;jna L5 367 <1> ;jmp L13 368 <1> ; 02/01/2022 369 0000014E 7703 <1> ja short L9_10 370 00000150 E972FF <1> jmp L5 371 <1> L9_10: 372 00000153 E90501 <1> jmp L13 373 <1> L10: 374 00000156 FEC2 <1> inc dl 375 <1> ; 25/12/2014 376 00000158 8816[595C] <1> mov [drv], dl 377 0000015C B408 <1> mov ah, 08h ; Return drive parameters 378 0000015E CD13 <1> int 13h ; (conventional function) 379 <1> ;jc L13 380 <1> ; 02/01/2022 381 00000160 72F1 <1> jc short L9_10 382 <1> ; 14/01/2015 383 00000162 8A16[595C] <1> mov dl, [drv] 384 00000166 52 <1> push dx 385 00000167 51 <1> push cx 386 00000168 E8FE00 <1> call set_disk_parms 387 0000016B 59 <1> pop cx 388 0000016C 5A <1> pop dx 389 <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2) 390 <1> ; 04/02/2016 (esi -> si) 391 <1> ;mov si, _end ; 30 byte temporary buffer address 392 <1> ; ; at the '_end' of kernel. 393 <1> ;mov word [si], 30 394 <1> ; 06/07/2016 395 0000016D BE[5000] <1> mov si, _int13h_48h_buffer 396 <1> ; 09/07/2016 397 00000170 B81E00 <1> mov ax, 001Eh 398 00000173 8824 <1> mov [si], ah ; 0 399 00000175 46 <1> inc si 400 00000176 8904 <1> mov word [si], ax 401 <1> ; word [si] = 30 402 <1> ; 403 00000178 B448 <1> mov ah, 48h ; Get drive parameters (EDD function) 404 0000017A CD13 <1> int 13h 405 <1> ;jc L13 406 <1> ; 02/01/2022 407 0000017C 72D5 <1> jc short L9_10 408 <1> ; 04/02/2016 (ebx -> bx) 409 <1> ; 14/01/2015 410 <1> ;sub bx, bx 411 0000017E 28FF <1> sub bh, bh ; 02/01/2022 412 00000180 88D3 <1> mov bl, dl 413 00000182 80EB80 <1> sub bl, 80h 414 00000185 81C3[5E5C] <1> add bx, hd0_type 415 00000189 8A07 <1> mov al, [bx] 416 0000018B 0C80 <1> or al, 80h 417 0000018D 8807 <1> mov [bx], al 418 0000018F 81EB[5C5C] <1> sub bx, hd0_type - 2 ; 15/01/2015 419 00000193 81C3[7E5C] <1> add bx, drv.status 420 00000197 8807 <1> mov [bx], al 421 <1> ; 04/02/2016 (eax -> ax) 422 00000199 8B4410 <1> mov ax, [si+16] 423 0000019C 854412 <1> test ax, [si+18] 424 0000019F 7413 <1> jz short L10_A0h 425 <1> ; 'CHS only' disks on EDD system 426 <1> ; are reported with ZERO disk size 427 000001A1 81EB[7E5C] <1> sub bx, drv.status 428 000001A5 C1E302 <1> shl bx, 2 429 000001A8 81C3[625C] <1> add bx, drv.size ; disk size (in sectors) 430 000001AC 8907 <1> mov [bx], ax 431 000001AE 8B4412 <1> mov ax, [si+18] 432 <1> ;mov [bx], ax 433 <1> ; 02/01/2022 (BugFix) 434 000001B1 894702 <1> mov [bx+2], ax 435 <1> 436 <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 437 <1> ; for CHS disks (28/02/2015) 438 <1> ; 30/12/2014 439 000001B4 BF0000 <1> mov di, HD0_DPT 440 000001B7 88D0 <1> mov al, dl 441 000001B9 83E003 <1> and ax, 3 442 000001BC C0E005 <1> shl al, 5 ; *32 443 000001BF 01C7 <1> add di, ax 444 000001C1 B80090 <1> mov ax, DPT_SEGM 445 000001C4 8EC0 <1> mov es, ax 446 <1> ; 447 000001C6 88E8 <1> mov al, ch ; max. cylinder number (bits 0-7) 448 000001C8 88CC <1> mov ah, cl 449 000001CA C0EC06 <1> shr ah, 6 ; max. cylinder number (bits 8-9) 450 000001CD 40 <1> inc ax ; logical cylinders (limit 1024) 451 000001CE AB <1> stosw 452 000001CF 88F0 <1> mov al, dh ; max. head number 453 000001D1 FEC0 <1> inc al 454 000001D3 AA <1> stosb ; logical heads (limits 256) 455 000001D4 B0A0 <1> mov al, 0A0h ; Indicates translated table 456 000001D6 AA <1> stosb 457 000001D7 8A440C <1> mov al, [si+12] 458 000001DA AA <1> stosb ; physical sectors per track 459 000001DB 31C0 <1> xor ax, ax 460 <1> ;dec ax ; 02/01/2015 461 000001DD AB <1> stosw ; precompensation (obsolete) 462 <1> ;xor al, al ; 02/01/2015 463 000001DE AA <1> stosb ; reserved 464 000001DF B008 <1> mov al, 8 ; drive control byte 465 <1> ; (do not disable retries, 466 <1> ; more than 8 heads) 467 000001E1 AA <1> stosb 468 000001E2 8B4404 <1> mov ax, [si+4] 469 000001E5 AB <1> stosw ; physical number of cylinders 470 <1> ;push ax ; 02/01/2015 471 000001E6 8A4408 <1> mov al, [si+8] 472 000001E9 AA <1> stosb ; physical num. of heads (limit 16) 473 000001EA 29C0 <1> sub ax, ax 474 <1> ;pop ax ; 02/01/2015 475 000001EC AB <1> stosw ; landing zone (obsolete) 476 000001ED 88C8 <1> mov al, cl ; logical sectors per track (limit 63) 477 000001EF 243F <1> and al, 3Fh 478 000001F1 AA <1> stosb 479 <1> ;sub al, al ; checksum 480 <1> ;stosb 481 <1> ; 482 000001F2 83C61A <1> add si, 26 ; (BIOS) DPTE address pointer 483 000001F5 AD <1> lodsw 484 000001F6 50 <1> push ax ; (BIOS) DPTE offset 485 000001F7 AD <1> lodsw 486 000001F8 50 <1> push ax ; (BIOS) DPTE segment 487 <1> ; 488 <1> ; checksum calculation 489 000001F9 89FE <1> mov si, di 490 000001FB 06 <1> push es 491 000001FC 1F <1> pop ds 492 <1> ;mov cx, 16 493 000001FD B90F00 <1> mov cx, 15 494 00000200 29CE <1> sub si, cx 495 00000202 30E4 <1> xor ah, ah 496 <1> ;del cl 497 <1> L11: 498 00000204 AC <1> lodsb 499 00000205 00C4 <1> add ah, al 500 00000207 E2FB <1> loop L11 501 <1> ; 502 00000209 88E0 <1> mov al, ah 503 0000020B F6D8 <1> neg al ; -x+x = 0 504 0000020D AA <1> stosb ; put checksum in byte 15 of the tbl 505 <1> ; 506 0000020E 1F <1> pop ds ; (BIOS) DPTE segment 507 0000020F 5E <1> pop si ; (BIOS) DPTE offset 508 <1> ; 509 <1> ; 23/02/2015 510 00000210 57 <1> push di 511 <1> ; ES:DI points to DPTE (FDPTE) location 512 <1> ;mov cx, 8 513 00000211 B108 <1> mov cl, 8 514 00000213 F3A5 <1> rep movsw 515 <1> ; 516 <1> ; 23/02/2015 517 <1> ; (P)ATA drive and LBA validation 518 <1> ; (invalidating SATA drives and setting 519 <1> ; CHS type I/O for old type fixed disks) 520 00000215 5B <1> pop bx 521 00000216 8CC8 <1> mov ax, cs 522 00000218 8ED8 <1> mov ds, ax 523 0000021A 268B07 <1> mov ax, [es:bx] 524 0000021D 3DF001 <1> cmp ax, 1F0h 525 00000220 7418 <1> je short L11a 526 00000222 3D7001 <1> cmp ax, 170h 527 00000225 7413 <1> je short L11a 528 <1> ; invalidation 529 <1> ; (because base port address is not 1F0h or 170h) 530 00000227 30FF <1> xor bh, bh 531 00000229 88D3 <1> mov bl, dl 532 0000022B 80EB80 <1> sub bl, 80h 533 0000022E C687[5E5C]00 <1> mov byte [bx+hd0_type], 0 ; not a valid disk drive ! 534 00000233 808F[805C]F0 <1> or byte [bx+drv.status+2], 0F0h ; (failure sign) 535 00000238 EB14 <1> jmp short L11b 536 <1> L11a: 537 <1> ; LBA validation 538 0000023A 268A4704 <1> mov al, [es:bx+4] ; Head register upper nibble 539 0000023E A840 <1> test al, 40h ; LBA bit (bit 6) 540 00000240 750C <1> jnz short L11b ; LBA type I/O is OK! (E0h or F0h) 541 <1> ; force CHS type I/O for this drive (A0h or B0h) 542 00000242 28FF <1> sub bh, bh 543 00000244 88D3 <1> mov bl, dl 544 00000246 80EB80 <1> sub bl, 80h ; 26/02/2015 545 00000249 80A7[805C]FE <1> and byte [bx+drv.status+2], 0FEh ; clear bit 0 546 <1> ; bit 0 = LBA ready bit 547 <1> ; 'diskio' procedure will check this bit ! 548 <1> L11b: 549 0000024E 3A16[5A5C] <1> cmp dl, [last_drv] ; 25/12/2014 550 00000252 7307 <1> jnb short L13 551 00000254 E9FFFE <1> jmp L10 552 <1> L12: 553 <1> ; Restore data registers 554 00000257 8CC8 <1> mov ax, cs 555 00000259 8ED8 <1> mov ds, ax 556 <1> L13: 557 <1> ; 13/12/2014 558 0000025B 0E <1> push cs 559 0000025C 07 <1> pop es 560 <1> L14: 561 0000025D B411 <1> mov ah, 11h 562 0000025F CD16 <1> int 16h 563 <1> ;jz short L15 ; no keys in keyboard buffer 564 <1> ; 02/01/2022 565 00000261 7447 <1> jz short L16 566 00000263 B010 <1> mov al, 10h 567 00000265 CD16 <1> int 16h 568 00000267 EBF4 <1> jmp short L14 569 <1> L15: 570 <1> 571 <1> ; ////// 572 <1> 573 <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2) 574 <1> %if 0 575 <1> ; 24/11/2014 576 <1> ; 19/11/2014 577 <1> ; 14/11/2014 578 <1> ; Temporary code for disk searching code check 579 <1> ; 580 <1> ; This code will show existing (usable) drives and also 581 <1> ; will show EDD interface support status for hard disks 582 <1> ; (If status bit 7 is 1, Identify Device info is ready, 583 <1> ; no need to get it again in protected mode...) 584 <1> ; 585 <1> ; 13/11/2014 586 <1> mov bx, 7 587 <1> mov ah, 0Eh 588 <1> mov al, [fd0_type] 589 <1> and al, al 590 <1> jz short L15a 591 <1> mov dl, al 592 <1> mov al, 'F' 593 <1> int 10h 594 <1> mov al, 'D' 595 <1> int 10h 596 <1> mov al, '0' 597 <1> int 10h 598 <1> mov al, ' ' 599 <1> int 10h 600 <1> call L15c 601 <1> mov al, ' ' 602 <1> int 10h 603 <1> ; 604 <1> mov al, [fd1_type] 605 <1> and al, al 606 <1> jz short L15a 607 <1> mov dl, al 608 <1> mov al, 'F' 609 <1> int 10h 610 <1> mov al, 'D' 611 <1> int 10h 612 <1> mov al, '1' 613 <1> int 10h 614 <1> mov al, ' ' 615 <1> int 10h 616 <1> call L15c 617 <1> mov al, ' ' 618 <1> int 10h 619 <1> mov al, ' ' 620 <1> int 10h 621 <1> L15a: 622 <1> mov al, [hd0_type] 623 <1> and al, al 624 <1> jz short L15b 625 <1> mov dl, al 626 <1> mov al, 'H' 627 <1> int 10h 628 <1> mov al, 'D' 629 <1> int 10h 630 <1> mov al, '0' 631 <1> int 10h 632 <1> mov al, ' ' 633 <1> int 10h 634 <1> call L15c 635 <1> mov al, ' ' 636 <1> int 10h 637 <1> ; 638 <1> mov al, [hd1_type] 639 <1> and al, al 640 <1> jz short L15b 641 <1> mov dl, al 642 <1> mov al, 'H' 643 <1> int 10h 644 <1> mov al, 'D' 645 <1> int 10h 646 <1> mov al, '1' 647 <1> int 10h 648 <1> mov al, ' ' 649 <1> int 10h 650 <1> call L15c 651 <1> mov al, ' ' 652 <1> int 10h 653 <1> ; 654 <1> mov al, [hd2_type] 655 <1> and al, al 656 <1> jz short L15b 657 <1> mov dl, al 658 <1> mov al, 'H' 659 <1> int 10h 660 <1> mov al, 'D' 661 <1> int 10h 662 <1> mov al, '2' 663 <1> int 10h 664 <1> mov al, ' ' 665 <1> int 10h 666 <1> call L15c 667 <1> mov al, ' ' 668 <1> int 10h 669 <1> ; 670 <1> mov al, [hd3_type] 671 <1> and al, al 672 <1> jz short L15b 673 <1> mov dl, al 674 <1> mov al, 'H' 675 <1> int 10h 676 <1> mov al, 'D' 677 <1> int 10h 678 <1> mov al, '3' 679 <1> int 10h 680 <1> mov al, ' ' 681 <1> int 10h 682 <1> call L15c 683 <1> mov al, ' ' 684 <1> int 10h 685 <1> ; 686 <1> L15b: 687 <1> mov al, 0Dh 688 <1> int 10h 689 <1> mov al, 0Ah 690 <1> int 10h 691 <1> ;;xor ah, ah 692 <1> ;;int 16h 693 <1> ; 694 <1> ;jmp L16 ; jmp short L16 695 <1> ; 02/01/2022 696 <1> jmp short L16 697 <1> ; 698 <1> L15c: 699 <1> mov dh, dl 700 <1> shr dh, 4 701 <1> add dh, 30h 702 <1> and dl, 15 703 <1> add dl, 30h 704 <1> mov al, dh 705 <1> int 10h 706 <1> mov al, dl 707 <1> int 10h 708 <1> retn 709 <1> ; 710 <1> ; end of temporary code for disk searching code check 711 <1> 712 <1> %endif 713 <1> 714 <1> ; ////// 715 <1> 716 <1> set_disk_parms: 717 <1> ; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 718 <1> ; 09/05/2022 719 <1> ; disksize = cylinders*spt*heads (*) 720 <1> ; (fd0&fd1 drv.size is calculated with total cylinders) 721 <1> ; 722 <1> ; 04/02/2016 (ebx -> bx) 723 <1> ; 10/07/2015 724 <1> ; 14/01/2015 725 <1> ;push bx 726 00000269 28FF <1> sub bh, bh 727 0000026B 8A1E[595C] <1> mov bl, [drv] 728 0000026F 80FB80 <1> cmp bl, 80h 729 00000272 7203 <1> jb short sdp0 730 00000274 80EB7E <1> sub bl, 7Eh 731 <1> sdp0: 732 00000277 81C3[7E5C] <1> add bx, drv.status 733 0000027B C60780 <1> mov byte [bx], 80h ; 'Present' flag 734 <1> ; 735 0000027E 88E8 <1> mov al, ch ; last cylinder (bits 0-7) 736 00000280 88CC <1> mov ah, cl ; 737 00000282 C0EC06 <1> shr ah, 6 ; last cylinder (bits 8-9) 738 00000285 81EB[7E5C] <1> sub bx, drv.status 739 00000289 D0E3 <1> shl bl, 1 740 <1> ; 12/07/2022 741 <1> ;add bx, drv.cylinders 742 0000028B 40 <1> inc ax ; convert max. cyl number to cyl count 743 <1> ;mov [bx], ax 744 0000028C 50 <1> push ax ; ** cylinders 745 <1> ;sub bx, drv.cylinders 746 <1> ;add bx, drv.heads 747 0000028D 30E4 <1> xor ah, ah 748 0000028F 88F0 <1> mov al, dh ; heads 749 00000291 40 <1> inc ax 750 <1> ;mov [bx], ax 751 <1> ;sub bx, drv.heads 752 <1> ;add bx, drv.spt 753 00000292 30ED <1> xor ch, ch 754 00000294 80E13F <1> and cl, 3Fh ; sectors (bits 0-6) 755 <1> ;mov [bx], cx 756 <1> ;sub bx, drv.spt 757 00000297 D1E3 <1> shl bx, 1 758 00000299 81C3[625C] <1> add bx, drv.size ; disk size (in sectors) 759 <1> ; LBA size = cylinders * heads * secpertrack 760 0000029D F7E1 <1> mul cx 761 0000029F 89C2 <1> mov dx, ax ; heads*spt 762 000002A1 58 <1> pop ax ; ** cylinders 763 <1> ; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads) 764 <1> ;dec ax ; 1 cylinder reserved (!?) ; (*) 765 000002A2 F7E2 <1> mul dx ; cylinders * (heads*spt) 766 000002A4 8907 <1> mov [bx], ax 767 000002A6 895702 <1> mov [bx+2], dx 768 <1> ; 769 <1> ;pop bx 770 000002A9 C3 <1> retn 771 <1> 772 <1> ;align 2 773 <1> 774 <1> ;cylinders : dw 0, 0, 0, 0, 0, 0 775 <1> ;heads : dw 0, 0, 0, 0, 0, 0 776 <1> ;spt : dw 0, 0, 0, 0, 0, 0 777 <1> ;disk_size : dd 0, 0, 0, 0, 0, 0 778 <1> 779 <1> ;last_drv: 780 <1> ; db 0 781 <1> ;drv_status: 782 <1> ; db 0,0,0,0,0,0 783 <1> ; db 0 784 <1> 785 <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015 786 <1> 787 <1> L16: 213 214 ; 10/11/2014 215 000002AA FA cli ; Disable interrupts (clear interrupt flag) 216 ; Reset Interrupt MASK Registers (Master&Slave) 217 ;mov al, 0FFh ; mask off all interrupts 218 ;out 21h, al ; on master PIC (8259) 219 ;jmp $+2 ; (delay) 220 ;out 0A1h, al ; on slave PIC (8259) 221 ; 222 ; Disable NMI 223 000002AB B080 mov al, 80h 224 000002AD E670 out 70h, al ; set bit 7 to 1 for disabling NMI 225 ; 23/02/2015 226 000002AF 90 nop ; 227 ;in al, 71h ; read in 71h just after writing out to 70h 228 ; for preventing unknown state (!?) 229 ; 230 ; 20/08/2014 231 ; Moving the kernel 64 KB back (to physical address 0) 232 ; DS = CS = 1000h 233 ; 05/11/2014 234 000002B0 31C0 xor ax, ax 235 000002B2 8EC0 mov es, ax ; ES = 0 236 ; 237 000002B4 B90040 mov cx, (KEND - KLOAD)/4 238 000002B7 31F6 xor si, si 239 000002B9 31FF xor di, di 240 000002BB F366A5 rep movsd 241 ; 242 000002BE 06 push es ; 0 243 000002BF 68[C302] push L17 244 000002C2 CB retf 245 ; 246 L17: 247 ; Turn off the floppy drive motor 248 000002C3 BAF203 mov dx, 3F2h 249 000002C6 EE out dx, al ; 0 ; 31/12/2013 250 251 ; Enable access to memory above one megabyte 252 L18: 253 000002C7 E464 in al, 64h 254 000002C9 A802 test al, 2 255 000002CB 75FA jnz short L18 256 000002CD B0D1 mov al, 0D1h ; Write output port 257 000002CF E664 out 64h, al 258 L19: 259 000002D1 E464 in al, 64h 260 000002D3 A802 test al, 2 261 000002D5 75FA jnz short L19 262 000002D7 B0DF mov al, 0DFh ; Enable A20 line 263 000002D9 E660 out 60h, al 264 ;L20: 265 ; 266 ; Load global descriptor table register 267 268 ;mov ax, cs 269 ;mov ds, ax 270 271 000002DB 2E0F0116[8059] lgdt [cs:gdtd] 272 273 000002E1 0F20C0 mov eax, cr0 274 ; or eax, 1 275 000002E4 40 inc ax 276 000002E5 0F22C0 mov cr0, eax 277 278 ; Jump to 32 bit code 279 280 000002E8 66 db 66h ; Prefix for 32-bit 281 000002E9 EA db 0EAh ; Opcode for far jump 282 000002EA [F0020000] dd StartPM ; Offset to start, 32-bit 283 ; (1000h:StartPM = StartPM + 10000h) 284 000002EE 0800 dw KCODE ; This is the selector for CODE32_DESCRIPTOR, 285 ; assuming that StartPM resides in code32 286 287 [BITS 32] 288 289 StartPM: 290 ; Kernel Base Address = 0 ; 30/12/2013 291 000002F0 66B81000 mov ax, KDATA ; Save data segment identifier 292 000002F4 8ED8 mov ds, ax ; Move a valid data segment into DS register 293 000002F6 8EC0 mov es, ax ; Move data segment into ES register 294 000002F8 8EE0 mov fs, ax ; Move data segment into FS register 295 000002FA 8EE8 mov gs, ax ; Move data segment into GS register 296 000002FC 8ED0 mov ss, ax ; Move data segment into SS register 297 000002FE BC00000900 mov esp, 90000h ; Move the stack pointer to 090000h 298 299 clear_bss: ; Clear uninitialized data area 300 ; 11/03/2015 301 00000303 31C0 xor eax, eax ; 0 302 ;mov ecx, (bss_end - bss_start)/4 303 ;;shr ecx, 2 ; bss section is already aligned for double words 304 ; 27/02/2022 305 00000305 B9C0060000 mov ecx, BSS_SIZE/4 306 0000030A BF[D05E0000] mov edi, bss_start 307 0000030F F3AB rep stosd 308 309 memory_init: 310 ; Initialize memory allocation table and page tables 311 ; 16/11/2014 312 ; 15/11/2014 313 ; 07/11/2014 314 ; 06/11/2014 315 ; 05/11/2014 316 ; 04/11/2014 317 ; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 318 ; 319 ; xor eax, eax 320 ; xor ecx, ecx 321 00000311 B108 mov cl, 8 322 00000313 BF00001000 mov edi, MEM_ALLOC_TBL 323 00000318 F3AB rep stosd ; clear Memory Allocation Table 324 ; for the first 1 MB memory 325 ; 326 0000031A 668B0D[C25E0000] mov cx, [mem_1m_1k] ; Number of contiguous KB between 327 ; 1 and 16 MB, max. 3C00h = 15 MB. 328 00000321 66C1E902 shr cx, 2 ; convert 1 KB count to 4 KB count 329 00000325 890D[40610000] mov [free_pages], ecx 330 0000032B 668B15[C45E0000] mov dx, [mem_16m_64k] ; Number of contiguous 64 KB blocks 331 ; between 16 MB and 4 GB. 332 00000332 6609D2 or dx, dx 333 00000335 7413 jz short mi_0 334 ; 335 00000337 6689D0 mov ax, dx 336 0000033A C1E004 shl eax, 4 ; 64 KB -> 4 KB (page count) 337 0000033D 0105[40610000] add [free_pages], eax 338 00000343 0500100000 add eax, 4096 ; 16 MB = 4096 pages 339 00000348 EB07 jmp short mi_1 340 mi_0: 341 0000034A 6689C8 mov ax, cx 342 0000034D 66050001 add ax, 256 ; add 256 pages for the first 1 MB 343 mi_1: 344 00000351 A3[3C610000] mov [memory_size], eax ; Total available memory in pages 345 ; 1 alloc. tbl. bit = 1 memory page 346 ; 32 allocation bits = 32 mem. pages 347 ; 348 00000356 05FF7F0000 add eax, 32767 ; 32768 memory pages per 1 M.A.T. page 349 0000035B C1E80F shr eax, 15 ; ((32768 * x) + y) pages (y < 32768) 350 ; --> x + 1 M.A.T. pages, if y > 0 351 ; --> x M.A.T. pages, if y = 0 352 0000035E 66A3[50610000] mov [mat_size], ax ; Memory Alloc. Table Size in pages 353 00000364 C1E00C shl eax, 12 ; 1 M.A.T. page = 4096 bytes 354 ; ; Max. 32 M.A.T. pages (4 GB memory) 355 00000367 89C3 mov ebx, eax ; M.A.T. size in bytes 356 ; Set/Calculate Kernel's Page Directory Address 357 00000369 81C300001000 add ebx, MEM_ALLOC_TBL 358 0000036F 891D[38610000] mov [k_page_dir], ebx ; Kernel's Page Directory address 359 ; just after the last M.A.T. page 360 ; 361 00000375 83E804 sub eax, 4 ; convert M.A.T. size to offset value 362 00000378 A3[48610000] mov [last_page], eax ; last page ofset in the M.A.T. 363 ; ; (allocation status search must be 364 ; stopped after here) 365 0000037D 31C0 xor eax, eax 366 0000037F 48 dec eax ; FFFFFFFFh (set all bits to 1) 367 00000380 6651 push cx 368 00000382 C1E905 shr ecx, 5 ; convert 1 - 16 MB page count to 369 ; count of 32 allocation bits 370 00000385 F3AB rep stosd 371 00000387 6659 pop cx 372 00000389 40 inc eax ; 0 373 0000038A 80E11F and cl, 31 ; remain bits 374 0000038D 7412 jz short mi_4 375 0000038F 8907 mov [edi], eax ; reset 376 mi_2: 377 00000391 0FAB07 bts [edi], eax ; 06/11/2014 378 00000394 FEC9 dec cl 379 00000396 7404 jz short mi_3 380 00000398 FEC0 inc al 381 0000039A EBF5 jmp short mi_2 382 mi_3: 383 0000039C 28C0 sub al, al ; 0 384 0000039E 83C704 add edi, 4 ; 15/11/2014 385 mi_4: 386 000003A1 6609D2 or dx, dx ; check 16M to 4G memory space 387 000003A4 7421 jz short mi_6 ; max. 16 MB memory, no more... 388 ; 389 000003A6 B900021000 mov ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory 390 ; 391 000003AB 29F9 sub ecx, edi ; displacement (to end of 16 MB) 392 000003AD 7406 jz short mi_5 ; jump if EDI points to 393 ; end of first 16 MB 394 000003AF D1E9 shr ecx, 1 ; convert to dword count 395 000003B1 D1E9 shr ecx, 1 ; (shift 2 bits right) 396 000003B3 F3AB rep stosd ; reset all bits for reserved pages 397 ; (memory hole under 16 MB) 398 mi_5: 399 000003B5 6689D1 mov cx, dx ; count of 64 KB memory blocks 400 000003B8 D1E9 shr ecx, 1 ; 1 alloc. dword per 128 KB memory 401 000003BA 9C pushf ; 16/11/2014 402 000003BB 48 dec eax ; FFFFFFFFh (set all bits to 1) 403 000003BC F3AB rep stosd 404 000003BE 40 inc eax ; 0 405 000003BF 9D popf ; 16/11/2014 406 000003C0 7305 jnc short mi_6 407 000003C2 6648 dec ax ; eax = 0000FFFFh 408 000003C4 AB stosd 409 000003C5 6640 inc ax ; 0 410 mi_6: 411 000003C7 39DF cmp edi, ebx ; check if EDI points to 412 000003C9 730A jnb short mi_7 ; end of memory allocation table 413 ; ; (>= MEM_ALLOC_TBL + 4906) 414 000003CB 89D9 mov ecx, ebx ; end of memory allocation table 415 000003CD 29F9 sub ecx, edi ; convert displacement/offset 416 000003CF D1E9 shr ecx, 1 ; to dword count 417 000003D1 D1E9 shr ecx, 1 ; (shift 2 bits right) 418 000003D3 F3AB rep stosd ; reset all remain M.A.T. bits 419 mi_7: 420 ; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages) 421 000003D5 BA00001000 mov edx, MEM_ALLOC_TBL 422 ;sub ebx, edx ; Mem. Alloc. Tbl. size in bytes 423 ;shr ebx, 12 ; Mem. Alloc. Tbl. size in pages 424 000003DA 668B0D[50610000] mov cx, [mat_size] ; Mem. Alloc. Tbl. size in pages 425 000003E1 89D7 mov edi, edx 426 000003E3 C1EF0F shr edi, 15 ; convert M.A.T. address to 427 ; byte offset in M.A.T. 428 ; (1 M.A.T. byte points to 429 ; 32768 bytes) 430 ; Note: MEM_ALLOC_TBL address 431 ; must be aligned on 128 KB 432 ; boundary! 433 000003E6 01D7 add edi, edx ; points to M.A.T.'s itself 434 ; eax = 0 435 000003E8 290D[40610000] sub [free_pages], ecx ; 07/11/2014 436 mi_8: 437 000003EE 0FB307 btr [edi], eax ; clear bit 0 to bit x (1 to 31) 438 ;dec bl 439 000003F1 FEC9 dec cl 440 000003F3 7404 jz short mi_9 441 000003F5 FEC0 inc al 442 000003F7 EBF5 jmp short mi_8 443 mi_9: 444 ; 445 ; Reset Kernel's Page Dir. and Page Table bits in M.A.T. 446 ; (allocate pages for system page tables) 447 448 ; edx = MEM_ALLOC_TBL 449 000003F9 8B0D[3C610000] mov ecx, [memory_size] ; memory size in pages (PTEs) 450 000003FF 81C1FF030000 add ecx, 1023 ; round up (1024 PTEs per table) 451 00000405 C1E90A shr ecx, 10 ; convert memory page count to 452 ; page table count (PDE count) 453 ; 454 00000408 51 push ecx ; (**) PDE count (<= 1024) 455 ; 456 00000409 41 inc ecx ; +1 for kernel page directory 457 ; 458 0000040A 290D[40610000] sub [free_pages], ecx ; 07/11/2014 459 ; 460 00000410 8B35[38610000] mov esi, [k_page_dir] ; Kernel's Page Directory address 461 00000416 C1EE0C shr esi, 12 ; convert to page number 462 mi_10: 463 00000419 89F0 mov eax, esi ; allocation bit offset 464 0000041B 89C3 mov ebx, eax 465 0000041D C1EB03 shr ebx, 3 ; convert to alloc. byte offset 466 00000420 80E3FC and bl, 0FCh ; clear bit 0 and bit 1 467 ; to align on dword boundary 468 00000423 83E01F and eax, 31 ; set allocation bit position 469 ; (bit 0 to bit 31) 470 ; 471 00000426 01D3 add ebx, edx ; offset in M.A.T. + M.A.T. address 472 ; 473 00000428 0FB303 btr [ebx], eax ; reset relevant bit (0 to 31) 474 ; 475 0000042B 46 inc esi ; next page table 476 0000042C E2EB loop mi_10 ; allocate next kernel page table 477 ; (ecx = page table count + 1) 478 ; 479 0000042E 59 pop ecx ; (**) PDE count (= pg. tbl. count) 480 ; 481 ; Initialize Kernel Page Directory and Kernel Page Tables 482 ; 483 ; Initialize Kernel's Page Directory 484 0000042F 8B3D[38610000] mov edi, [k_page_dir] 485 00000435 89F8 mov eax, edi 486 00000437 0C03 or al, PDE_A_PRESENT + PDE_A_WRITE 487 ; supervisor + read&write + present 488 00000439 89CA mov edx, ecx ; (**) PDE count (= pg. tbl. count) 489 mi_11: 490 0000043B 0500100000 add eax, 4096 ; Add page size (PGSZ) 491 ; EAX points to next page table 492 00000440 AB stosd 493 00000441 E2F8 loop mi_11 494 00000443 29C0 sub eax, eax ; Empty PDE 495 00000445 66B90004 mov cx, 1024 ; Entry count (PGSZ/4) 496 00000449 29D1 sub ecx, edx 497 0000044B 7402 jz short mi_12 498 0000044D F3AB rep stosd ; clear remain (empty) PDEs 499 ; 500 ; Initialization of Kernel's Page Directory is OK, here. 501 mi_12: 502 ; Initialize Kernel's Page Tables 503 ; 504 ; (EDI points to address of page table 0) 505 ; eax = 0 506 0000044F 8B0D[3C610000] mov ecx, [memory_size] ; memory size in pages 507 00000455 89CA mov edx, ecx ; (***) 508 00000457 B003 mov al, PTE_A_PRESENT + PTE_A_WRITE 509 ; supervisor + read&write + present 510 mi_13: 511 00000459 AB stosd 512 0000045A 0500100000 add eax, 4096 513 0000045F E2F8 loop mi_13 514 00000461 6681E2FF03 and dx, 1023 ; (***) 515 00000466 740B jz short mi_14 516 00000468 66B90004 mov cx, 1024 517 0000046C 6629D1 sub cx, dx ; from dx (<= 1023) to 1024 518 0000046F 31C0 xor eax, eax 519 00000471 F3AB rep stosd ; clear remain (empty) PTEs 520 ; of the last page table 521 mi_14: 522 ; Initialization of Kernel's Page Tables is OK, here. 523 ; 524 00000473 89F8 mov eax, edi ; end of the last page table page 525 ; (beginging of user space pages) 526 00000475 C1E80F shr eax, 15 ; convert to M.A.T. byte offset 527 00000478 24FC and al, 0FCh ; clear bit 0 and bit 1 for 528 ; aligning on dword boundary 529 530 0000047A A3[4C610000] mov [first_page], eax 531 0000047F A3[44610000] mov [next_page], eax ; The first free page pointer 532 ; for user programs 533 ; (Offset in Mem. Alloc. Tbl.) 534 ; 535 ; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here. 536 ; 537 538 ; Enable paging 539 ; 540 00000484 A1[38610000] mov eax, [k_page_dir] 541 00000489 0F22D8 mov cr3, eax 542 0000048C 0F20C0 mov eax, cr0 543 0000048F 0D00000080 or eax, 80000000h ; set paging bit (bit 31) 544 00000494 0F22C0 mov cr0, eax 545 ;jmp KCODE:StartPMP 546 547 00000497 EA db 0EAh ; Opcode for far jump 548 00000498 [9E040000] dd StartPMP ; 32 bit offset 549 0000049C 0800 dw KCODE ; kernel code segment descriptor 550 551 552 StartPMP: 553 ; 06/11//2014 554 ; Clear video page 0 555 ; 556 ; Temporary Code 557 ; 558 0000049E B9E8030000 mov ecx, 80*25/2 559 000004A3 BF00800B00 mov edi, 0B8000h 560 000004A8 31C0 xor eax, eax ; black background, black fore color 561 000004AA F3AB rep stosd 562 563 ; 19/08/2014 564 ; Kernel Base Address = 0 565 ; It is mapped to (physically) 0 in the page table. 566 ; So, here is exactly 'StartPMP' address. 567 ; 568 ;;mov ah, 4Eh ; Red background, yellow forecolor 569 ;;mov esi, msgPM 570 ;; 14/08/2015 (kernel version message will appear 571 ;; when protected mode and paging is enabled) 572 000004AC B40B mov ah, 0Bh ; Black background, light cyan forecolor 573 000004AE BE[945C0000] mov esi, msgKVER 574 000004B3 BF00800B00 mov edi, 0B8000h ; 27/08/2014 575 ; 20/08/2014 576 000004B8 E891010000 call printk 577 578 ; 'UNIX v7/x86' source code by Robert Nordier (1999) 579 ; // Set IRQ offsets 580 ; 581 ; Linux (v0.12) source code by Linus Torvalds (1991) 582 ; 583 ;; ICW1 584 000004BD B011 mov al, 11h ; Initialization sequence 585 000004BF E620 out 20h, al ; 8259A-1 586 ; jmp $+2 587 000004C1 E6A0 out 0A0h, al ; 8259A-2 588 ;; ICW2 589 000004C3 B020 mov al, 20h ; Start of hardware ints (20h) 590 000004C5 E621 out 21h, al ; for 8259A-1 591 ; jmp $+2 592 000004C7 B028 mov al, 28h ; Start of hardware ints (28h) 593 000004C9 E6A1 out 0A1h, al ; for 8259A-2 594 ; 595 000004CB B004 mov al, 04h ;; ICW3 596 000004CD E621 out 21h, al ; IRQ2 of 8259A-1 (master) 597 ; jmp $+2 598 000004CF B002 mov al, 02h ; is 8259A-2 (slave) 599 000004D1 E6A1 out 0A1h, al ; 600 ;; ICW4 601 000004D3 B001 mov al, 01h ; 602 000004D5 E621 out 21h, al ; 8086 mode, normal EOI 603 ; jmp $+2 604 000004D7 E6A1 out 0A1h, al ; for both chips. 605 606 ;mov al, 0FFh ; mask off all interrupts for now 607 ;out 21h, al 608 ;; jmp $+2 609 ;out 0A1h, al 610 611 ; 02/04/2015 612 ; 26/03/2015 System call (INT 30h) modification 613 ; DPL = 3 (Interrupt service routine can be called from user mode) 614 ; 615 ;; Linux (v0.12) source code by Linus Torvalds (1991) 616 ; setup_idt: 617 ; 618 ;; 16/02/2015 619 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 620 ; 21/08/2014 (timer_int) 621 000004D9 BE[8C590000] mov esi, ilist 622 000004DE 8D3D[D05E0000] lea edi, [idt] 623 ; 26/03/2015 624 000004E4 B930000000 mov ecx, 48 ; 48 hardware interrupts (INT 0 to INT 2Fh) 625 ; 02/04/2015 626 000004E9 BB00000800 mov ebx, 80000h 627 rp_sidt1: 628 000004EE AD lodsd 629 000004EF 89C2 mov edx, eax 630 000004F1 66BA008E mov dx, 8E00h 631 000004F5 6689C3 mov bx, ax 632 000004F8 89D8 mov eax, ebx ; /* selector = 0x0008 = cs */ 633 ; /* interrupt gate - dpl=0, present */ 634 000004FA AB stosd ; selector & offset bits 0-15 635 000004FB 89D0 mov eax, edx 636 000004FD AB stosd ; attributes & offset bits 16-23 637 000004FE E2EE loop rp_sidt1 638 00000500 B110 mov cl, 16 ; 16 software interrupts (INT 30h to INT 3Fh) 639 rp_sidt2: 640 00000502 AD lodsd 641 00000503 21C0 and eax, eax 642 00000505 7413 jz short rp_sidt3 643 00000507 89C2 mov edx, eax 644 00000509 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 645 0000050D 6689C3 mov bx, ax 646 00000510 89D8 mov eax, ebx ; selector & offset bits 0-15 647 00000512 AB stosd 648 00000513 89D0 mov eax, edx 649 00000515 AB stosd 650 00000516 E2EA loop rp_sidt2 651 00000518 EB16 jmp short sidt_OK 652 rp_sidt3: 653 0000051A B8[71090000] mov eax, ignore_int 654 0000051F 89C2 mov edx, eax 655 00000521 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 656 00000525 6689C3 mov bx, ax 657 00000528 89D8 mov eax, ebx ; selector & offset bits 0-15 658 rp_sidt4: 659 0000052A AB stosd 660 0000052B 92 xchg eax, edx 661 0000052C AB stosd 662 0000052D 92 xchg edx, eax 663 0000052E E2FA loop rp_sidt4 664 sidt_OK: 665 00000530 0F011D[86590000] lidt [idtd] 666 ; 667 ; TSS descriptor setup ; 24/03/2015 668 00000537 B8[D0600000] mov eax, task_state_segment 669 0000053C 66A3[7A590000] mov [gdt_tss0], ax 670 00000542 C1C010 rol eax, 16 671 00000545 A2[7C590000] mov [gdt_tss1], al 672 0000054A 8825[7F590000] mov [gdt_tss2], ah 673 00000550 66C705[36610000]68- mov word [tss.IOPB], tss_end - task_state_segment 673 00000558 00 674 ; 675 ; IO Map Base address (When this address points 676 ; to end of the TSS, CPU does not use IO port 677 ; permission bit map for RING 3 IO permissions, 678 ; access to any IO ports in ring 3 will be forbidden.) 679 ; 680 ;mov [tss.esp0], esp ; TSS offset 4 681 ;mov word [tss.ss0], KDATA ; TSS offset 8 (SS) 682 00000559 66B82800 mov ax, TSS ; It is needed when an interrupt 683 ; occurs (or a system call -software INT- is requested) 684 ; while cpu running in ring 3 (in user mode). 685 ; (Kernel stack pointer and segment will be loaded 686 ; from offset 4 and 8 of the TSS, by the CPU.) 687 0000055D 0F00D8 ltr ax ; Load task register 688 ; 689 esp0_set0: 690 ; 30/07/2015 691 00000560 8B0D[3C610000] mov ecx, [memory_size] ; memory size in pages 692 00000566 C1E10C shl ecx, 12 ; convert page count to byte count 693 00000569 81F900004000 cmp ecx, CORE ; beginning of user's memory space (400000h) 694 ; (kernel mode virtual address) 695 0000056F 7605 jna short esp0_set1 696 ; 697 ; If available memory > CORE (end of the 1st 4 MB) 698 ; set stack pointer to CORE 699 ;(Because, PDE 0 is reserved for kernel space in user's page directory) 700 ;(PDE 0 points to page table of the 1st 4 MB virtual address space) 701 00000571 B900004000 mov ecx, CORE 702 esp0_set1: 703 00000576 89CC mov esp, ecx ; top of kernel stack (**tss.esp0**) 704 esp0_set_ok: 705 ; 30/07/2015 (**tss.esp0**) 706 00000578 8925[D4600000] mov [tss.esp0], esp 707 0000057E 66C705[D8600000]10- mov word [tss.ss0], KDATA 707 00000586 00 708 ; 14/08/2015 709 ; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan) 710 ; 711 ;cli ; Disable interrupts (for CPU) 712 ; (CPU will not handle hardware interrupts, except NMI!) 713 ; 714 00000587 30C0 xor al, al ; Enable all hardware interrupts! 715 00000589 E621 out 21h, al ; (IBM PC-AT compatibility) 716 0000058B EB00 jmp $+2 ; (All conventional PC-AT hardware 717 0000058D E6A1 out 0A1h, al ; interrupts will be in use.) 718 ; (Even if related hardware component 719 ; does not exist!) 720 ; Enable NMI 721 0000058F B07F mov al, 7Fh ; Clear bit 7 to enable NMI (again) 722 00000591 E670 out 70h, al 723 ; 23/02/2015 724 00000593 90 nop 725 00000594 E471 in al, 71h ; read in 71h just after writing out to 70h 726 ; for preventing unknown state (!?) 727 ; 728 ; Only a NMI can occur here... (Before a 'STI' instruction) 729 ; 730 ; 02/09/2014 731 ;xor bx, bx 732 ;mov dx, 0200h ; Row 2, column 0 ; 07/03/2015 733 ; 27/02/2022 734 00000596 31DB xor ebx, ebx 735 00000598 31D2 xor edx, edx 736 0000059A B602 mov dh, 2 737 0000059C E81E0E0000 call set_cpos 738 ; 739 ; 06/11/2014 740 ; Temporary Code 741 ; 742 000005A1 E8930F0000 call memory_info 743 ; 14/08/2015 744 ;call getch ; 28/02/2015 745 drv_init: 746 000005A6 FB sti ; Enable Interrupts 747 ; 06/02/2015 748 000005A7 8B15[5E5C0000] mov edx, [hd0_type] ; hd0, hd1, hd2, hd3 749 000005AD 668B1D[5C5C0000] mov bx, [fd0_type] ; fd0, fd1 750 ; 22/02/2015 751 000005B4 6621DB and bx, bx 752 000005B7 751B jnz short di1 753 ; 754 000005B9 09D2 or edx, edx 755 000005BB 7529 jnz short di2 756 ; 757 setup_error: 758 000005BD BE[7B5D0000] mov esi, setup_error_msg 759 psem: 760 000005C2 AC lodsb 761 000005C3 08C0 or al, al 762 ;jz short haltx ; 22/02/2015 763 000005C5 7426 jz short di3 764 000005C7 56 push esi 765 000005C8 31DB xor ebx, ebx ; 0 766 ; Video page 0 (bl=0) 767 000005CA B407 mov ah, 07h ; Black background, 768 ; light gray forecolor 769 000005CC E8E40C0000 call write_tty 770 000005D1 5E pop esi 771 000005D2 EBEE jmp short psem 772 773 di1: 774 ; supress 'jmp short T6' 775 ; (activate fdc motor control code) 776 000005D4 66C705[CF060000]90- mov word [T5], 9090h ; nop 776 000005DC 90 777 ; 778 ;mov ax, int_0Eh ; IRQ 6 handler 779 ;mov di, 0Eh*4 ; IRQ 6 vector 780 ;stosw 781 ;mov ax, cs 782 ;stosw 783 ;; 16/02/2015 784 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 785 ; 786 000005DD E804190000 CALL DSKETTE_SETUP ; Initialize Floppy Disks 787 ; 788 000005E2 09D2 or edx, edx 789 000005E4 7407 jz short di3 790 di2: 791 000005E6 E82D190000 call DISK_SETUP ; Initialize Fixed Disks 792 000005EB 72D0 jc short setup_error 793 di3: 794 000005ED E81B0F0000 call setup_rtc_int ; 22/05/2015 (dsectrpm.s) 795 ; 796 000005F2 E8B1520000 call display_disks ; 07/03/2015 (Temporary) 797 ;haltx: 798 ; 14/08/2015 799 ;call getch ; 22/02/2015 800 000005F7 FB sti ; Enable interrupts (for CPU) 801 ; 14/08/2015 802 ;mov ecx, 0FFFFFFFh 803 ; 16/02/2022 804 000005F8 B9FFFF4F00 mov ecx, 04FFFFFh 805 md_info_msg_wait: 806 000005FD 51 push ecx 807 000005FE B001 mov al, 1 808 00000600 8A25[66610000] mov ah, [ptty] ; active (current) video page 809 00000606 E8884F0000 call getc_n 810 0000060B 59 pop ecx 811 0000060C 7502 jnz short md_info_msg_ok 812 0000060E E2ED loop md_info_msg_wait 813 md_info_msg_ok: 814 ; 30/06/2015 815 00000610 E8C1220000 call sys_init 816 ; 817 ;jmp cpu_reset ; 22/02/2015 818 hang: 819 ; 27/02/2022 820 00000615 29C0 sub eax, eax 821 _hang: 822 ; 23/02/2015 823 ;sti ; Enable interrupts 824 00000617 F4 hlt 825 ; 826 ;nop 827 ;; 03/12/2014 828 ;; 28/08/2014 829 ;mov ah, 11h 830 ;call getc 831 ;jz _c8 832 ; 833 ; 23/02/2015 834 ; 06/02/2015 835 ; 07/09/2014 836 00000618 31DB xor ebx, ebx 837 0000061A 8A1D[66610000] mov bl, [ptty] ; active_page 838 00000620 89DE mov esi, ebx 839 ;shl si, 1 840 ; 17/07/2022 841 00000622 D1E6 shl esi, 1 842 00000624 81C6[68610000] add esi, ttychr 843 0000062A 668B06 mov ax, [esi] 844 ;and ax, ax 845 ;;jz short _c8 846 ;jz short hang 847 ; 27/02/2022 848 0000062D 21C0 and eax, eax 849 0000062F 74E6 jz short _hang 850 00000631 66C7060000 mov word [esi], 0 851 00000636 80FB03 cmp bl, 3 ; Video page 3 852 ;jb short _c8 853 00000639 72DA jb short hang 854 ; 855 ; 02/09/2014 856 0000063B B40E mov ah, 0Eh ; Yellow character 857 ; on black background 858 ; 27/02/2022 (32 bit reg push-pop) 859 ; 07/09/2014 860 nxtl: 861 ;push bx 862 0000063D 53 push ebx 863 ; 864 ;xor ebx, ebx ; bl = 0 (video page 0) 865 ; bh = 0 (video mode) 866 ; Retro UNIX 386 v1 - Video Mode 0 867 ; (PC/AT Video Mode 3 - 80x25 Alpha.) 868 0000063E 50 push eax 869 0000063F E8710C0000 call write_tty 870 00000644 58 pop eax 871 ;pop bx 872 00000645 5B pop ebx 873 00000646 3C0D cmp al, 0Dh ; carriage return (enter) 874 ;jne short _c8 875 00000648 75CB jne short hang 876 0000064A B00A mov al, 0Ah ; next line 877 0000064C EBEF jmp short nxtl 878 879 ;_c8: 880 ; ; 25/08/2014 881 ; cli ; Disable interrupts 882 ; mov al, [scounter + 1] 883 ; and al, al 884 ; jnz hang 885 ; call rtc_p 886 ; jmp hang 887 888 889 ; 27/08/2014 890 ; 20/08/2014 891 printk: 892 ;mov edi, [scr_row] 893 pkl: 894 0000064E AC lodsb 895 0000064F 08C0 or al, al 896 00000651 7404 jz short pkr 897 00000653 66AB stosw 898 00000655 EBF7 jmp short pkl 899 pkr: 900 00000657 C3 retn 901 902 ; 25/07/2015 903 ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer) 904 ; 17/02/2015 905 ; 06/02/2015 (unix386.s) 906 ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 907 ; 908 ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85) 909 ; 910 ;-- HARDWARE INT 08 H - ( IRQ LEVEL 0 ) --------------------------------------- 911 ; THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF : 912 ; THE 8254 TIMER. INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR : 913 ; IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND. : 914 ; : 915 ; THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE : 916 ; POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY. : 917 ; THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40) : 918 ; OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE : 919 ; DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS. : 920 ; THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH : 921 ; INTERRUPT 1CH AT EVERY TIME TICK. THE USER MUST CODE A : 922 ; ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE. : 923 ;------------------------------------------------------------------------------- 924 ; 925 926 timer_int: ; IRQ 0 927 ;int_08h: ; Timer 928 ; 14/10/2015 929 ; Here, we are simulating system call entry (for task switch) 930 ; (If multitasking is enabled, 931 ; 'clock' procedure may jump to 'sysrelease') 932 00000658 1E push ds 933 00000659 06 push es 934 0000065A 0FA0 push fs 935 0000065C 0FA8 push gs 936 0000065E 60 pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 937 0000065F 66B91000 mov cx, KDATA 938 00000663 8ED9 mov ds, cx 939 00000665 8EC1 mov es, cx 940 00000667 8EE1 mov fs, cx 941 00000669 8EE9 mov gs, cx 942 ; 943 0000066B 0F20D9 mov ecx, cr3 944 0000066E 890D[11070000] mov [cr3reg], ecx ; save current cr3 register value/content 945 ; 946 00000674 3B0D[38610000] cmp ecx, [k_page_dir] 947 0000067A 741F je short T3 948 ; 949 ; timer interrupt has been occurred while OS is in user mode 950 0000067C A3[00650000] mov [u.r0], eax 951 00000681 89E1 mov ecx, esp 952 00000683 83C130 add ecx, ESPACE ; 4 * 12 (stack frame) 953 00000686 890D[F8640000] mov [u.sp], ecx ; kernel stack pointer at the start of interrupt 954 0000068C 8925[FC640000] mov [u.usp], esp ; kernel stack points to user's registers 955 ; 956 00000692 8B0D[38610000] mov ecx, [k_page_dir] 957 00000698 0F22D9 mov cr3, ecx 958 T3: 959 0000069B FB sti ; INTERRUPTS BACK ON 960 0000069C 66FF05[B4610000] INC word [TIMER_LOW] ; INCREMENT TIME 961 000006A3 7507 JNZ short T4 ; GO TO TEST_DAY 962 000006A5 66FF05[B6610000] INC word [TIMER_HIGH] ; INCREMENT HIGH WORD OF TIME 963 T4: ; TEST_DAY 964 000006AC 66833D[B6610000]18 CMP word [TIMER_HIGH],018H ; TEST FOR COUNT EQUALING 24 HOURS 965 000006B4 7519 JNZ short T5 ; GO TO DISKETTE_CTL 966 000006B6 66813D[B4610000]B0- CMP word [TIMER_LOW],0B0H 966 000006BE 00 967 000006BF 750E JNZ short T5 ; GO TO DISKETTE_CTL 968 969 ;----- TIMER HAS GONE 24 HOURS 970 ;;SUB AX,AX 971 ;MOV [TIMER_HIGH],AX 972 ;MOV [TIMER_LOW],AX 973 000006C1 29C0 sub eax, eax 974 000006C3 A3[B4610000] mov [TIMER_LH], eax 975 ; 976 000006C8 C605[B8610000]01 MOV byte [TIMER_OFL],1 977 978 ;----- TEST FOR DISKETTE TIME OUT 979 980 T5: 981 ; 23/12/2014 982 000006CF EB1D jmp short T6 ; will be replaced with nop, nop 983 ; (9090h) if a floppy disk 984 ; is detected. 985 ;mov al,[CS:MOTOR_COUNT] 986 000006D1 A0[BB610000] mov al, [MOTOR_COUNT] 987 000006D6 FEC8 dec al 988 ;mov [CS:MOTOR_COUNT], al ; DECREMENT DISKETTE MOTOR CONTROL 989 000006D8 A2[BB610000] mov [MOTOR_COUNT], al 990 ;mov [ORG_MOTOR_COUNT], al 991 000006DD 750F JNZ short T6 ; RETURN IF COUNT NOT OUT 992 000006DF B0F0 mov al,0F0h 993 ;AND [CS:MOTOR_STATUS],al ; TURN OFF MOTOR RUNNING BITS 994 000006E1 2005[BA610000] and [MOTOR_STATUS], al 995 ;and [ORG_MOTOR_STATUS], al 996 000006E7 B00C MOV AL,0CH ; bit 3 = enable IRQ & DMA, 997 ; bit 2 = enable controller 998 ; 1 = normal operation 999 ; 0 = reset 1000 ; bit 0, 1 = drive select 1001 ; bit 4-7 = motor running bits 1002 000006E9 66BAF203 MOV DX,03F2H ; FDC CTL PORT 1003 000006ED EE OUT DX,AL ; TURN OFF THE MOTOR 1004 T6: 1005 ;inc word [CS:wait_count] ; 22/12/2014 (byte -> word) 1006 ; TIMER TICK INTERRUPT 1007 ;;inc word [wait_count] ;;27/02/2015 1008 ;INT 1CH ; TRANSFER CONTROL TO A USER ROUTINE 1009 ;;;;cli 1010 ;call u_timer ; TRANSFER CONTROL TO A USER ROUTINE 1011 000006EE FF15[09070000] call [x_timer] ; 14/05/2015 1012 T7: 1013 ; 14/10/2015 1014 000006F4 B020 MOV AL,EOI ; GET END OF INTERRUPT MASK 1015 000006F6 FA CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 1016 000006F7 E620 OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 1017 ; 1018 000006F9 A1[11070000] mov eax, [cr3reg] ; previous value/content of cr3 register 1019 000006FE 0F22D8 mov cr3, eax ; restore cr3 register content 1020 ; 1021 00000701 61 popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 1022 ; 1023 00000702 0FA9 pop gs 1024 00000704 0FA1 pop fs 1025 00000706 07 pop es 1026 00000707 1F pop ds 1027 00000708 CF iretd ; return from interrupt 1028 1029 1030 ; //////////////// 1031 1032 ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt) 1033 x_timer: 1034 00000709 [15070000] dd u_timer ; (temporary demo code) ; 14/05/2015 1035 ;dd clock 1036 1037 ; 23/02/2022 - Real time clock (digital) output demo (sys emt) 1038 x_rtci: 1039 0000070D [4A0A0000] dd rtc_p ; (temporary demo code) ; 23/02/2022 1040 1041 ; 14/10/2015 1042 00000711 00000000 cr3reg: dd 0 1043 1044 ; 06/02/2015 1045 ; 07/09/2014 1046 ; 21/08/2014 1047 u_timer: 1048 ; 27/02/2022 1049 ; 12/02/2022 1050 ;timer_int: ; IRQ 0 1051 ; 06/02/2015 1052 ;push eax 1053 ;push edx 1054 ;push ecx 1055 ;push ebx 1056 ;push ds 1057 ;push es 1058 ;mov eax, KDATA 1059 ;mov ds, ax 1060 ;mov es, ax 1061 00000715 FF05[7C610000] inc dword [tcount] 1062 0000071B BB[045D0000] mov ebx, tcountstr + 4 1063 ;mov ax, [tcount] 1064 ; 27/02/2022 1065 00000720 A1[7C610000] mov eax, [tcount] 1066 ;mov ecx, 10 1067 00000725 31C9 xor ecx, ecx 1068 00000727 B10A mov cl, 10 1069 rp_divtcnt: 1070 00000729 31D2 xor edx, edx 1071 0000072B F7F1 div ecx 1072 0000072D 80C230 add dl, 30h 1073 00000730 8813 mov [ebx], dl 1074 ;or ax, ax 1075 ; 27/02/2022 1076 00000732 09C0 or eax, eax 1077 00000734 7403 jz short print_lzero 1078 00000736 4B dec ebx 1079 00000737 EBF0 jmp short rp_divtcnt 1080 print_lzero: 1081 00000739 81FB[005D0000] cmp ebx, tcountstr 1082 0000073F 7606 jna short print_tcount 1083 00000741 4B dec ebx 1084 00000742 C60330 mov byte [ebx], 30h 1085 00000745 EBF2 jmp short print_lzero 1086 print_tcount: 1087 00000747 56 push esi 1088 00000748 57 push edi 1089 00000749 BE[DC5C0000] mov esi, timer_msg ; Timer interrupt message 1090 ;; 07/09/2014 1091 ;mov bx, 1 ; Video page 1 1092 ; 12/02/2022 1093 ;mov bx, 6 ; Video page 6 1094 ; 27/02/2022 1095 0000074E 29DB sub ebx, ebx 1096 00000750 B306 mov bl, 6 ; Video page 6 1097 ptmsg: 1098 00000752 AC lodsb 1099 00000753 08C0 or al, al 1100 00000755 740D jz short ptmsg_ok 1101 00000757 56 push esi 1102 ;push bx 1103 ; 27/02/2022 1104 00000758 53 push ebx 1105 00000759 B42F mov ah, 2Fh ; Green background, white forecolor 1106 0000075B E8550B0000 call write_tty 1107 ;pop bx 1108 ; 27/02/2022 1109 00000760 5B pop ebx 1110 00000761 5E pop esi 1111 00000762 EBEE jmp short ptmsg 1112 ;; 27/08/2014 1113 ;mov edi, 0B8000h + 0A0h ; Row 1 1114 ;call printk 1115 ; 1116 ptmsg_ok: 1117 ; 07/09/2014 1118 ;xor dx, dx ; column 0, row 0 1119 ; 27/02/2022 1120 00000764 31D2 xor edx, edx 1121 00000766 E8540C0000 call set_cpos ; set cursor position to 0,0 1122 ; 23/02/2015 1123 ; 25/08/2014 1124 ;mov ebx, scounter ; (seconds counter) 1125 ;dec byte [ebx+1] ; (for reading real time clock) 1126 ; dec byte [scounter+1] 1127 ;; jns short timer_eoi ; 0 -> 0FFh ? 1128 ; jns short u_timer_retn 1129 ; 26/02/2015 1130 ; call rtc_p 1131 ; mov ebx, scounter ; (seconds counter) 1132 ; mov byte [ebx+1], 18 ; (18.2 timer ticks per second) 1133 ; dec byte [ebx] ; 19+18+18+18+18 (5) 1134 ; jnz short timer_eoi ; (109 timer ticks in 5 seconds) 1135 ; jnz short u_timer_retn ; 06/02/2015 1136 ; mov byte [ebx], 5 1137 ; inc byte [ebx+1] ; 19 1138 ;;timer_eoi: 1139 ;; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1140 ;; out 20h, al ; 8259 PORT 1141 ; 1142 ;u_timer_retn: ; 06/02/2015 1143 0000076B 5F pop edi 1144 0000076C 5E pop esi 1145 ;pop es 1146 ;pop ds 1147 ;pop ebx 1148 ;pop ecx 1149 ;pop edx 1150 ;pop eax 1151 ;iret 1152 0000076D C3 retn ; 06/02/2015 1153 1154 ; 28/08/2014 1155 irq0: 1156 0000076E 6A00 push dword 0 1157 00000770 EB48 jmp short which_irq 1158 irq1: 1159 00000772 6A01 push dword 1 1160 00000774 EB44 jmp short which_irq 1161 irq2: 1162 00000776 6A02 push dword 2 1163 00000778 EB40 jmp short which_irq 1164 irq3: 1165 ; 20/11/2015 1166 ; 24/10/2015 1167 0000077A 2EFF15[E42F0000] call dword [cs:com2_irq3] 1168 00000781 6A03 push dword 3 1169 00000783 EB35 jmp short which_irq 1170 irq4: 1171 ; 20/11/2015 1172 ; 24/10/2015 1173 00000785 2EFF15[E02F0000] call dword [cs:com1_irq4] 1174 0000078C 6A04 push dword 4 1175 0000078E EB2A jmp short which_irq 1176 irq5: 1177 00000790 6A05 push dword 5 1178 00000792 EB26 jmp short which_irq 1179 irq6: 1180 00000794 6A06 push dword 6 1181 00000796 EB22 jmp short which_irq 1182 irq7: 1183 00000798 6A07 push dword 7 1184 0000079A EB1E jmp short which_irq 1185 irq8: 1186 0000079C 6A08 push dword 8 1187 0000079E EB1A jmp short which_irq 1188 irq9: 1189 000007A0 6A09 push dword 9 1190 000007A2 EB16 jmp short which_irq 1191 irq10: 1192 000007A4 6A0A push dword 10 1193 000007A6 EB12 jmp short which_irq 1194 irq11: 1195 000007A8 6A0B push dword 11 1196 000007AA EB0E jmp short which_irq 1197 irq12: 1198 000007AC 6A0C push dword 12 1199 000007AE EB0A jmp short which_irq 1200 irq13: 1201 000007B0 6A0D push dword 13 1202 000007B2 EB06 jmp short which_irq 1203 irq14: 1204 000007B4 6A0E push dword 14 1205 000007B6 EB02 jmp short which_irq 1206 irq15: 1207 000007B8 6A0F push dword 15 1208 ;jmp short which_irq 1209 1210 ; 27/02/2022 1211 ; 19/10/2015 1212 ; 29/08/2014 1213 ; 21/08/2014 1214 which_irq: 1215 000007BA 870424 xchg eax, [esp] ; 28/08/2014 1216 000007BD 53 push ebx 1217 000007BE 56 push esi 1218 000007BF 57 push edi 1219 000007C0 1E push ds 1220 000007C1 06 push es 1221 ; 1222 000007C2 88C3 mov bl, al 1223 ; 1224 000007C4 B810000000 mov eax, KDATA 1225 000007C9 8ED8 mov ds, ax 1226 000007CB 8EC0 mov es, ax 1227 ; 19/10/2015 1228 000007CD FC cld 1229 ; 27/08/2014 1230 000007CE 8105[8C5C0000]A000- add dword [scr_row], 0A0h 1230 000007D6 0000 1231 ; 1232 000007D8 B417 mov ah, 17h ; blue (1) background, 1233 ; light gray (7) forecolor 1234 000007DA 8B3D[8C5C0000] mov edi, [scr_row] 1235 000007E0 B049 mov al, 'I' 1236 000007E2 66AB stosw 1237 000007E4 B052 mov al, 'R' 1238 000007E6 66AB stosw 1239 000007E8 B051 mov al, 'Q' 1240 000007EA 66AB stosw 1241 000007EC B020 mov al, ' ' 1242 000007EE 66AB stosw 1243 000007F0 88D8 mov al, bl 1244 000007F2 3C0A cmp al, 10 1245 000007F4 7208 jb short iix 1246 000007F6 B031 mov al, '1' 1247 000007F8 66AB stosw 1248 000007FA 88D8 mov al, bl 1249 000007FC 2C0A sub al, 10 1250 iix: 1251 000007FE 0430 add al, '0' 1252 00000800 66AB stosw 1253 00000802 B020 mov al, ' ' 1254 00000804 66AB stosw 1255 00000806 B021 mov al, '!' 1256 00000808 66AB stosw 1257 0000080A B020 mov al, ' ' 1258 0000080C 66AB stosw 1259 ; 23/02/2015 1260 0000080E 80FB07 cmp bl, 7 ; check for IRQ 8 to IRQ 15 1261 ;jna iiret 1262 ; 27/02/2022 1263 00000811 7604 jna short iiz 1264 iiy: 1265 00000813 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1266 00000815 E6A0 out 0A0h, al ; the 2nd 8259 1267 iiz: 1268 00000817 E983010000 jmp iiret 1269 ; 1270 ; 22/08/2014 1271 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1272 ;out 20h, al ; 8259 PORT 1273 ; 1274 ;pop es 1275 ;pop ds 1276 ;pop edi 1277 ;pop esi 1278 ;pop ebx 1279 ;pop eax 1280 ;iret 1281 1282 ; 02/04/2015 1283 ; 25/08/2014 1284 exc0: 1285 0000081C 6A00 push dword 0 1286 0000081E E990000000 jmp cpu_except 1287 exc1: 1288 00000823 6A01 push dword 1 1289 00000825 E989000000 jmp cpu_except 1290 exc2: 1291 0000082A 6A02 push dword 2 1292 0000082C E982000000 jmp cpu_except 1293 exc3: 1294 00000831 6A03 push dword 3 1295 00000833 EB7E jmp cpu_except 1296 exc4: 1297 00000835 6A04 push dword 4 1298 00000837 EB7A jmp cpu_except 1299 exc5: 1300 00000839 6A05 push dword 5 1301 0000083B EB76 jmp cpu_except 1302 exc6: 1303 0000083D 6A06 push dword 6 1304 0000083F EB72 jmp cpu_except 1305 exc7: 1306 00000841 6A07 push dword 7 1307 00000843 EB6E jmp cpu_except 1308 exc8: 1309 ; [esp] = Error code 1310 00000845 6A08 push dword 8 1311 00000847 EB5C jmp cpu_except_en 1312 exc9: 1313 00000849 6A09 push dword 9 1314 0000084B EB66 jmp cpu_except 1315 exc10: 1316 ; [esp] = Error code 1317 0000084D 6A0A push dword 10 1318 0000084F EB54 jmp cpu_except_en 1319 exc11: 1320 ; [esp] = Error code 1321 00000851 6A0B push dword 11 1322 00000853 EB50 jmp cpu_except_en 1323 exc12: 1324 ; [esp] = Error code 1325 00000855 6A0C push dword 12 1326 00000857 EB4C jmp cpu_except_en 1327 exc13: 1328 ; [esp] = Error code 1329 00000859 6A0D push dword 13 1330 0000085B EB48 jmp cpu_except_en 1331 exc14: 1332 ; [esp] = Error code 1333 0000085D 6A0E push dword 14 1334 0000085F EB44 jmp short cpu_except_en 1335 exc15: 1336 00000861 6A0F push dword 15 1337 00000863 EB4E jmp cpu_except 1338 exc16: 1339 00000865 6A10 push dword 16 1340 00000867 EB4A jmp cpu_except 1341 exc17: 1342 ; [esp] = Error code 1343 00000869 6A11 push dword 17 1344 0000086B EB38 jmp short cpu_except_en 1345 exc18: 1346 0000086D 6A12 push dword 18 1347 0000086F EB42 jmp short cpu_except 1348 exc19: 1349 00000871 6A13 push dword 19 1350 00000873 EB3E jmp short cpu_except 1351 exc20: 1352 00000875 6A14 push dword 20 1353 00000877 EB3A jmp short cpu_except 1354 exc21: 1355 00000879 6A15 push dword 21 1356 0000087B EB36 jmp short cpu_except 1357 exc22: 1358 0000087D 6A16 push dword 22 1359 0000087F EB32 jmp short cpu_except 1360 exc23: 1361 00000881 6A17 push dword 23 1362 00000883 EB2E jmp short cpu_except 1363 exc24: 1364 00000885 6A18 push dword 24 1365 00000887 EB2A jmp short cpu_except 1366 exc25: 1367 00000889 6A19 push dword 25 1368 0000088B EB26 jmp short cpu_except 1369 exc26: 1370 0000088D 6A1A push dword 26 1371 0000088F EB22 jmp short cpu_except 1372 exc27: 1373 00000891 6A1B push dword 27 1374 00000893 EB1E jmp short cpu_except 1375 exc28: 1376 00000895 6A1C push dword 28 1377 00000897 EB1A jmp short cpu_except 1378 exc29: 1379 00000899 6A1D push dword 29 1380 0000089B EB16 jmp short cpu_except 1381 exc30: 1382 0000089D 6A1E push dword 30 1383 0000089F EB04 jmp short cpu_except_en 1384 exc31: 1385 000008A1 6A1F push dword 31 1386 000008A3 EB0E jmp short cpu_except 1387 1388 ; 27/02/2022 1389 ; 19/10/2015 1390 ; 19/09/2015 1391 ; 01/09/2015 1392 ; 28/08/2015 1393 ; 28/08/2014 1394 cpu_except_en: 1395 000008A5 87442404 xchg eax, [esp+4] ; Error code 1396 000008A9 36A3[E4610000] mov [ss:error_code], eax 1397 000008AF 58 pop eax ; Exception number 1398 000008B0 870424 xchg eax, [esp] 1399 ; eax = eax before exception 1400 ; [esp] -> exception number 1401 ; [esp+4] -> EIP to return 1402 ; 19/10/2015 1403 ; 19/09/2015 1404 ; 01/09/2015 1405 ; 28/08/2015 1406 ; 29/08/2014 1407 ; 28/08/2014 1408 ; 25/08/2014 1409 ; 21/08/2014 1410 cpu_except: ; CPU Exceptions 1411 000008B3 FC cld 1412 000008B4 870424 xchg eax, [esp] 1413 ; eax = Exception number 1414 ; [esp] = eax (before exception) 1415 000008B7 53 push ebx 1416 000008B8 56 push esi 1417 000008B9 57 push edi 1418 000008BA 1E push ds 1419 000008BB 06 push es 1420 ; 28/08/2015 1421 000008BC 66BB1000 mov bx, KDATA 1422 000008C0 8EDB mov ds, bx 1423 000008C2 8EC3 mov es, bx 1424 000008C4 0F20DB mov ebx, cr3 1425 000008C7 53 push ebx ; (*) page directory 1426 ; 19/10/2015 1427 000008C8 FC cld 1428 ; 25/03/2015 1429 000008C9 8B1D[38610000] mov ebx, [k_page_dir] 1430 000008CF 0F22DB mov cr3, ebx 1431 ; 28/08/2015 1432 000008D2 83F80E cmp eax, 0Eh ; 14, PAGE FAULT 1433 000008D5 7513 jne short cpu_except_nfp 1434 000008D7 E8B61D0000 call page_fault_handler 1435 000008DC 21C0 and eax, eax 1436 ;jz iiretp ; 01/09/2015 1437 ; 27/02/2022 1438 000008DE 7505 jnz short cpu_except_pf 1439 000008E0 E9B6000000 jmp iiretp 1440 cpu_except_pf: 1441 000008E5 B80E000000 mov eax, 0Eh ; 14 1442 cpu_except_nfp: 1443 ; 02/04/2015 1444 000008EA BB[15060000] mov ebx, hang 1445 000008EF 875C241C xchg ebx, [esp+28] 1446 ; EIP (points to instruction which faults) 1447 ; New EIP (hang) 1448 000008F3 891D[E8610000] mov [FaultOffset], ebx 1449 000008F9 C744242008000000 mov dword [esp+32], KCODE ; kernel's code segment 1450 00000901 814C242400020000 or dword [esp+36], 200h ; enable interrupts (set IF) 1451 ; 1452 00000909 88C4 mov ah, al 1453 0000090B 240F and al, 0Fh 1454 0000090D 3C09 cmp al, 9 1455 0000090F 7602 jna short h1ok 1456 00000911 0407 add al, 'A'-':' 1457 h1ok: 1458 00000913 D0EC shr ah, 1 1459 00000915 D0EC shr ah, 1 1460 00000917 D0EC shr ah, 1 1461 00000919 D0EC shr ah, 1 1462 0000091B 80FC09 cmp ah, 9 1463 0000091E 7603 jna short h2ok 1464 00000920 80C407 add ah, 'A'-':' 1465 h2ok: 1466 00000923 86E0 xchg ah, al 1467 00000925 66053030 add ax, '00' 1468 00000929 66A3[185D0000] mov [excnstr], ax 1469 ; 1470 ; 29/08/2014 1471 0000092F A1[E8610000] mov eax, [FaultOffset] 1472 00000934 51 push ecx 1473 00000935 52 push edx 1474 00000936 89E3 mov ebx, esp 1475 ; 28/08/2015 1476 00000938 B910000000 mov ecx, 16 ; divisor value to convert binary number 1477 ; to hexadecimal string 1478 ;mov ecx, 10 ; divisor to convert 1479 ; binary number to decimal string 1480 b2d1: 1481 0000093D 31D2 xor edx, edx 1482 0000093F F7F1 div ecx 1483 ;push dx 1484 ; 27/02/2022 1485 00000941 52 push edx 1486 00000942 39C8 cmp eax, ecx 1487 00000944 73F7 jnb short b2d1 1488 00000946 BF[235D0000] mov edi, EIPstr ; EIP value 1489 ; points to instruction which faults 1490 ; 28/08/2015 1491 0000094B 89C2 mov edx, eax 1492 b2d2: 1493 ;add al, '0' 1494 0000094D 8A82[F5150000] mov al, [edx+hexchrs] 1495 00000953 AA stosb ; write hexadecimal digit to its place 1496 00000954 39E3 cmp ebx, esp 1497 00000956 7605 jna short b2d3 1498 ; 27/02/2022 1499 00000958 58 pop eax 1500 ;pop ax 1501 00000959 88C2 mov dl, al 1502 0000095B EBF0 jmp short b2d2 1503 b2d3: 1504 0000095D B068 mov al, 'h' ; 28/08/2015 1505 0000095F AA stosb 1506 00000960 B020 mov al, 20h ; space 1507 00000962 AA stosb 1508 00000963 30C0 xor al, al ; to do it an ASCIIZ string 1509 00000965 AA stosb 1510 ; 1511 00000966 5A pop edx 1512 00000967 59 pop ecx 1513 ; 1514 00000968 B44F mov ah, 4Fh ; red (4) background, 1515 ; white (F) forecolor 1516 0000096A BE[085D0000] mov esi, exc_msg ; message offset 1517 ; 1518 0000096F EB11 jmp short piemsg 1519 ; 1520 ;add dword [scr_row], 0A0h 1521 ;mov edi, [scr_row] 1522 ; 1523 ;call printk 1524 ; 1525 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1526 ;out 20h, al ; 8259 PORT 1527 ; 1528 ;pop es 1529 ;pop ds 1530 ;pop edi 1531 ;pop esi 1532 ;pop eax 1533 ;iret 1534 1535 ; 28/08/2015 1536 ; 23/02/2015 1537 ; 20/08/2014 1538 ignore_int: 1539 00000971 50 push eax 1540 00000972 53 push ebx ; 23/02/2015 1541 00000973 56 push esi 1542 00000974 57 push edi 1543 00000975 1E push ds 1544 00000976 06 push es 1545 ; 28/08/2015 1546 00000977 0F20D8 mov eax, cr3 1547 0000097A 50 push eax ; (*) page directory 1548 ; 1549 0000097B B467 mov ah, 67h ; brown (6) background, 1550 ; light gray (7) forecolor 1551 0000097D BE[C65C0000] mov esi, int_msg ; message offset 1552 piemsg: 1553 ; 27/08/2014 1554 00000982 8105[8C5C0000]A000- add dword [scr_row], 0A0h 1554 0000098A 0000 1555 0000098C 8B3D[8C5C0000] mov edi, [scr_row] 1556 ; 1557 00000992 E8B7FCFFFF call printk 1558 ; 1559 ; 23/02/2015 1560 00000997 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1561 00000999 E6A0 out 0A0h, al ; the 2nd 8259 1562 iiretp: ; 01/09/2015 1563 ; 28/08/2015 1564 0000099B 58 pop eax ; (*) page directory 1565 0000099C 0F22D8 mov cr3, eax 1566 ; 1567 iiret: 1568 ; 22/08/2014 1569 0000099F B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1570 000009A1 E620 out 20h, al ; 8259 PORT 1571 ; 1572 000009A3 07 pop es 1573 000009A4 1F pop ds 1574 000009A5 5F pop edi 1575 000009A6 5E pop esi 1576 000009A7 5B pop ebx ; 29/08/2014 1577 000009A8 58 pop eax 1578 000009A9 CF iretd 1579 1580 ; 23/02/2022 1581 ; 26/02/2015 1582 ; 07/09/2014 1583 ; 25/08/2014 1584 rtc_int: ; Real Time Clock Interrupt (IRQ 8) 1585 ; 22/08/2014 1586 000009AA 50 push eax 1587 000009AB 53 push ebx ; 29/08/2014 1588 000009AC 56 push esi 1589 000009AD 57 push edi 1590 000009AE 1E push ds 1591 000009AF 06 push es 1592 ; 1593 000009B0 B810000000 mov eax, KDATA 1594 000009B5 8ED8 mov ds, ax 1595 000009B7 8EC0 mov es, ax 1596 ; 1597 ; 25/08/2014 1598 ;call rtc_p 1599 ; 23/02/2022 1600 000009B9 FF15[0D070000] call [x_rtci] 1601 ; 1602 ; 22/02/2015 - dsectpm.s 1603 ; [ source: http://wiki.osdev.org/RTC ] 1604 ; read status register C to complete procedure 1605 ;(it is needed to get a next IRQ 8) 1606 000009BF B00C mov al, 0Ch ; 1607 000009C1 E670 out 70h, al ; select register C 1608 000009C3 90 nop 1609 000009C4 E471 in al, 71h ; just throw away contents 1610 ; 22/02/2015 1611 000009C6 B020 MOV AL,EOI ; END OF INTERRUPT 1612 000009C8 E6A0 OUT INTB00,AL ; FOR CONTROLLER #2 1613 ; 1614 000009CA EBD3 jmp short iiret 1615 1616 ; 22/08/2014 1617 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm) 1618 ; (INT 1Ah) 1619 ;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991) 1620 time_of_day: 1621 000009CC E868010000 call UPD_IPR ; WAIT TILL UPDATE NOT IN PROGRESS 1622 000009D1 726F jc short rtc_retn 1623 000009D3 B000 mov al, CMOS_SECONDS 1624 000009D5 E847010000 call CMOS_READ 1625 000009DA A2[AC610000] mov [time_seconds], al 1626 000009DF B002 mov al, CMOS_MINUTES 1627 000009E1 E83B010000 call CMOS_READ 1628 000009E6 A2[AD610000] mov [time_minutes], al 1629 000009EB B004 mov al, CMOS_HOURS 1630 000009ED E82F010000 call CMOS_READ 1631 000009F2 A2[AE610000] mov [time_hours], al 1632 000009F7 B006 mov al, CMOS_DAY_WEEK 1633 000009F9 E823010000 call CMOS_READ 1634 000009FE A2[AF610000] mov [date_wday], al 1635 00000A03 B007 mov al, CMOS_DAY_MONTH 1636 00000A05 E817010000 call CMOS_READ 1637 00000A0A A2[B0610000] mov [date_day], al 1638 00000A0F B008 mov al, CMOS_MONTH 1639 00000A11 E80B010000 call CMOS_READ 1640 00000A16 A2[B1610000] mov [date_month], al 1641 00000A1B B009 mov al, CMOS_YEAR 1642 00000A1D E8FF000000 call CMOS_READ 1643 00000A22 A2[B2610000] mov [date_year], al 1644 00000A27 B032 mov al, CMOS_CENTURY 1645 00000A29 E8F3000000 call CMOS_READ 1646 00000A2E A2[B3610000] mov [date_century], al 1647 ; 1648 00000A33 B000 mov al, CMOS_SECONDS 1649 00000A35 E8E7000000 call CMOS_READ 1650 00000A3A 3A05[AC610000] cmp al, [time_seconds] 1651 00000A40 758A jne short time_of_day 1652 1653 rtc_retn: 1654 00000A42 C3 retn 1655 1656 rtci_default: 1657 ; 23/02/2022 (Temporary!) 1658 ; (default real time clock handler in multitasking mode) 1659 ; ((2 rtc ticks per second after 'setup_rtc_int')) 1660 00000A43 FF05[F0610000] inc dword [rtc_ticks] ; real time clock counter 1661 ; (not used in anywhere of kernel for now!) 1662 00000A49 C3 retn 1663 1664 rtc_p: 1665 ; 27/02/2022 1666 ; 12/02/2022 1667 ; 07/09/2014 1668 ; 29/08/2014 1669 ; 27/08/2014 1670 ; 25/08/2014 1671 ; Print Real Time Clock content 1672 ; 1673 ; 1674 00000A4A E87DFFFFFF call time_of_day 1675 00000A4F 72F1 jc short rtc_retn 1676 ; 1677 00000A51 3A05[7A5D0000] cmp al, [ptime_seconds] 1678 00000A57 74E9 je short rtc_retn ; 29/08/2014 1679 ; 1680 00000A59 A2[7A5D0000] mov [ptime_seconds], al 1681 ; 1682 00000A5E A0[B3610000] mov al, [date_century] 1683 00000A63 E8EC000000 call bcd_to_ascii 1684 00000A68 66A3[475D0000] mov [datestr+6], ax 1685 00000A6E A0[B2610000] mov al, [date_year] 1686 00000A73 E8DC000000 call bcd_to_ascii 1687 00000A78 66A3[495D0000] mov [datestr+8], ax 1688 00000A7E A0[B1610000] mov al, [date_month] 1689 00000A83 E8CC000000 call bcd_to_ascii 1690 00000A88 66A3[445D0000] mov [datestr+3], ax 1691 00000A8E A0[B0610000] mov al, [date_day] 1692 00000A93 E8BC000000 call bcd_to_ascii 1693 00000A98 66A3[415D0000] mov [datestr], ax 1694 ; 1695 00000A9E 0FB61D[AF610000] movzx ebx, byte [date_wday] 1696 00000AA5 C0E302 shl bl, 2 1697 00000AA8 81C3[5A5D0000] add ebx, daytmp 1698 00000AAE 8B03 mov eax, [ebx] 1699 00000AB0 A3[4C5D0000] mov [daystr], eax 1700 ; 1701 00000AB5 A0[AE610000] mov al, [time_hours] 1702 00000ABA E895000000 call bcd_to_ascii 1703 00000ABF 66A3[505D0000] mov [timestr], ax 1704 00000AC5 A0[AD610000] mov al, [time_minutes] 1705 00000ACA E885000000 call bcd_to_ascii 1706 00000ACF 66A3[535D0000] mov [timestr+3], ax 1707 00000AD5 A0[AC610000] mov al, [time_seconds] 1708 00000ADA E875000000 call bcd_to_ascii 1709 00000ADF 66A3[565D0000] mov [timestr+6], ax 1710 ; 1711 00000AE5 BE[2F5D0000] mov esi, rtc_msg ; message offset 1712 ; 23/02/2015 1713 00000AEA 52 push edx 1714 00000AEB 51 push ecx 1715 ; 07/09/2014 1716 ;mov bx, 2 ; Video page 2 1717 ; 27/02/2022 1718 00000AEC 29DB sub ebx, ebx 1719 00000AEE B307 mov bl, 7 ; Video page 7 1720 prtmsg: 1721 00000AF0 AC lodsb 1722 00000AF1 08C0 or al, al 1723 00000AF3 740D jz short prtmsg_ok 1724 00000AF5 56 push esi 1725 ; 27/02/2022 1726 00000AF6 53 push ebx 1727 ;push bx 1728 00000AF7 B43F mov ah, 3Fh ; cyan (6) background, 1729 ; white (F) forecolor 1730 00000AF9 E8B7070000 call write_tty 1731 ;pop bx 1732 ; 27/02/2022 1733 00000AFE 5B pop ebx 1734 00000AFF 5E pop esi 1735 00000B00 EBEE jmp short prtmsg 1736 ; 1737 ;mov edi, 0B8000h+0A0h+0A0h ; Row 2 1738 ;call printk 1739 prtmsg_ok: 1740 ; 07/09/2014 1741 ;xor dx, dx ; column 0, row 0 1742 ; 27/02/2022 1743 00000B02 31D2 xor edx, edx 1744 00000B04 E8B6080000 call set_cpos ; set cursor position to 0,0 1745 ; 23/02/2015 1746 00000B09 59 pop ecx 1747 00000B0A 5A pop edx 1748 00000B0B C3 retn 1749 1750 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 1751 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 1752 default_irq7: 1753 ; 27/02/2022 1754 ;push ax 1755 00000B0C 50 push eax 1756 00000B0D B00B mov al, 0Bh ; In-Service register 1757 00000B0F E620 out 20h, al 1758 00000B11 EB00 jmp short $+2 1759 00000B13 EB00 jmp short $+2 1760 00000B15 E420 in al, 20h 1761 00000B17 2480 and al, 80h ; bit 7 (is it real IRQ 7 or fake?) 1762 00000B19 7404 jz short irq7_iret ; Fake (spurious) IRQ, do not send EOI 1763 00000B1B B020 mov al, 20h ; EOI 1764 00000B1D E620 out 20h, al 1765 irq7_iret: 1766 ;pop ax 1767 ; 27/02/2022 1768 00000B1F 58 pop eax 1769 00000B20 CF iretd 1770 1771 ; 22/08/2014 1772 ; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm) 1773 CMOS_READ: 1774 00000B21 9C pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 1775 00000B22 D0C0 rol al, 1 ; MOVE NMI BIT TO LOW POSITION 1776 00000B24 F9 stc ; FORCE NMI BIT ON IN CARRY FLAG 1777 00000B25 D0D8 rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 1778 00000B27 FA cli ; DISABLE INTERRUPTS 1779 00000B28 E670 out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 1780 00000B2A 90 nop ; I/O DELAY 1781 00000B2B E471 in al, CMOS_DATA ; READ THE REQUESTED CMOS LOCATION 1782 00000B2D 6650 push ax ; SAVE (AH) REGISTER VALUE AND CMOS BYTE 1783 ; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 1784 ; ----- 10/06/85 (test4.asm) 1785 00000B2F B01E mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 1786 ;mov al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION 1787 00000B31 D0D8 rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 1788 00000B33 E670 out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 1789 00000B35 6658 pop ax ; RESTORE (AH) AND (AL), CMOS BYTE 1790 00000B37 9D popf 1791 00000B38 C3 retn ; RETURN WITH FLAGS RESTORED 1792 1793 ; 22/08/2014 1794 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm) 1795 UPD_IPR: ; WAIT TILL UPDATE NOT IN PROGRESS 1796 00000B39 51 push ecx 1797 00000B3A B9FFFF0000 mov ecx, 65535 ; SET TIMEOUT LOOP COUNT (= 800) 1798 ; mov cx, 800 1799 UPD_10: 1800 00000B3F B00A mov al, CMOS_REG_A ; ADDRESS STATUS REGISTER A 1801 00000B41 FA cli ; NO TIMER INTERRUPTS DURING UPDATES 1802 00000B42 E8DAFFFFFF call CMOS_READ ; READ UPDATE IN PROCESS FLAG 1803 00000B47 A880 test al, 80h ; IF UIP BIT IS ON ( CANNOT READ TIME ) 1804 00000B49 7406 jz short UPD_90 ; EXIT WITH CY= 0 IF CAN READ CLOCK NOW 1805 00000B4B FB sti ; ALLOW INTERRUPTS WHILE WAITING 1806 00000B4C E2F1 loop UPD_10 ; LOOP TILL READY OR TIMEOUT 1807 00000B4E 31C0 xor eax, eax ; CLEAR RESULTS IF ERROR 1808 ; xor ax, ax 1809 00000B50 F9 stc ; SET CARRY FOR ERROR 1810 UPD_90: 1811 00000B51 59 pop ecx ; RESTORE CALLERS REGISTER 1812 00000B52 FA cli ; INTERRUPTS OFF DURING SET 1813 00000B53 C3 retn ; RETURN WITH CY FLAG SET 1814 1815 bcd_to_ascii: 1816 ; 25/08/2014 1817 ; INPUT -> 1818 ; al = Packed BCD number 1819 ; OUTPUT -> 1820 ; ax = ASCII word/number 1821 ; 1822 ; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011) 1823 ; 1824 00000B54 D410 db 0D4h,10h ; Undocumented inst. AAM 1825 ; AH = AL / 10h 1826 ; AL = AL MOD 10h 1827 00000B56 660D3030 or ax,'00' ; Make it ASCII based 1828 1829 00000B5A 86E0 xchg ah, al 1830 1831 00000B5C C3 retn 1832 1833 %include 'keyboard.inc' ; 07/03/2015 1834 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - KEYBOARD.INC 1835 <1> ; Last Modification: 24/07/2022 1836 <1> ; (Keyboard Data is in 'KYBDATA.INC') 1837 <1> ; 1838 <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) /////////////// 1839 <1> 1840 <1> ; 24/07/2022 (Retro UNIX 386 v1, Kernel v0.2.0.22) 1841 <1> ; 13/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20) 1842 <1> ; 23/02/2022 1843 <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 1844 <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 1845 <1> ; 30/06/2015 1846 <1> ; 11/03/2015 1847 <1> ; 28/02/2015 1848 <1> ; 25/02/2015 1849 <1> ; 20/02/2015 1850 <1> ; 18/02/2015 1851 <1> ; 03/12/2014 1852 <1> ; 07/09/2014 1853 <1> ; KEYBOARD INTERRUPT HANDLER 1854 <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014) 1855 <1> 1856 <1> ;getch: 1857 <1> ; ; 18/02/2015 1858 <1> ; ; This routine will be replaced with Retro UNIX 386 1859 <1> ; ; version of Retro UNIX 8086 getch (tty input) 1860 <1> ; ; routine, later... (multi tasking ability) 1861 <1> ; ; 28/02/2015 1862 <1> ; sti ; enable interrupts 1863 <1> ; ; 1864 <1> ; ;push esi 1865 <1> ; ;push ebx 1866 <1> ; ;xor ebx, ebx 1867 <1> ; ;mov bl, [ptty] ; active_page 1868 <1> ; ;mov esi, ebx 1869 <1> ; ;shl si, 1 1870 <1> ; ;add esi, ttychr 1871 <1> ;getch_1: 1872 <1> ; ;mov ax, [esi] 1873 <1> ; mov ax, [ttychr] ; video page 0 (tty0) 1874 <1> ; and ax, ax 1875 <1> ; jz short getch_2 1876 <1> ; mov word [ttychr], 0 1877 <1> ; ;mov word [esi], 0 1878 <1> ; ;pop ebx 1879 <1> ; ;pop esi 1880 <1> ; retn 1881 <1> ;getch_2: 1882 <1> ; hlt ; not proper for multi tasking! 1883 <1> ; ; (temporary halt for now) 1884 <1> ; ; 'sleep' on tty 1885 <1> ; ; will (must) be located here 1886 <1> ; nop 1887 <1> ; jmp short getch_1 1888 <1> 1889 <1> keyb_int: 1890 <1> ; 24/07/2022 1891 <1> ; 23/02/2022 1892 <1> ; 30/06/2015 1893 <1> ; 25/02/2015 1894 <1> ; 20/02/2015 1895 <1> ; 03/12/2014 (getc_int - INT 16h modifications) 1896 <1> ; 07/09/2014 - Retro UNIX 386 v1 1897 <1> ; 30/06/2014 1898 <1> ; 10/05/2013 1899 <1> ; Retro Unix 8086 v1 feature only! 1900 <1> ; 03/03/2014 1901 <1> 1902 00000B5D 1E <1> push ds 1903 00000B5E 53 <1> push ebx 1904 00000B5F 50 <1> push eax 1905 <1> ; 1906 <1> ; 23/02/2022 1907 00000B60 9C <1> pushfd 1908 00000B61 0E <1> push cs 1909 <1> ;mov ax, KDATA 1910 00000B62 31C0 <1> xor eax, eax 1911 00000B64 B010 <1> mov al, KDATA 1912 00000B66 8ED8 <1> mov ds, ax 1913 <1> ; 1914 <1> ;pushfd 1915 <1> ;push cs 1916 00000B68 E80A010000 <1> call kb_int ; int_09h 1917 <1> ; 1918 <1> ;mov ah, 11h ; 03/12/2014 1919 00000B6D B401 <1> mov ah, 1 ; 24/07/2022 1920 <1> ;call getc 1921 00000B6F E854000000 <1> call int_16h ; 30/06/2015 1922 00000B74 744E <1> jz short keyb_int4 1923 <1> ; 1924 <1> ;mov ah, 10h ; 03/12/2014 1925 00000B76 B400 <1> mov ah, 0 ; 24/07/2022 1926 <1> ;call getc 1927 00000B78 E84B000000 <1> call int_16h ; 30/06/2015 1928 <1> ; 1929 <1> ; 20/02/2015 1930 00000B7D 0FB61D[66610000] <1> movzx ebx, byte [ptty] ; active_page 1931 <1> ; 1932 00000B84 20C0 <1> and al, al 1933 00000B86 751D <1> jnz short keyb_int1 1934 <1> ; 1935 00000B88 80FC68 <1> cmp ah, 68h ; ALT + F1 key 1936 00000B8B 7218 <1> jb short keyb_int1 1937 00000B8D 80FC6F <1> cmp ah, 6Fh ; ALT + F8 key 1938 00000B90 7713 <1> ja short keyb_int1 1939 <1> ; 1940 00000B92 88D8 <1> mov al, bl 1941 00000B94 0468 <1> add al, 68h 1942 00000B96 38E0 <1> cmp al, ah 1943 00000B98 7409 <1> je short keyb_int0 1944 00000B9A 88E0 <1> mov al, ah 1945 00000B9C 2C68 <1> sub al, 68h 1946 00000B9E E831090000 <1> call tty_sw 1947 <1> ;movzx ebx, [ptty] ; active_page 1948 <1> keyb_int0: ; 30/06/2015 1949 <1> ;xor ax, ax 1950 <1> ; 23/02/2022 1951 00000BA3 31C0 <1> xor eax, eax 1952 <1> keyb_int1: 1953 00000BA5 D0E3 <1> shl bl, 1 1954 00000BA7 81C3[68610000] <1> add ebx, ttychr 1955 <1> ; 1956 <1> ;23/02/2022 1957 00000BAD 09C0 <1> or eax, eax 1958 <1> ;or ax, ax 1959 00000BAF 7406 <1> jz short keyb_int2 1960 <1> ; 1961 00000BB1 66833B00 <1> cmp word [ebx], 0 1962 00000BB5 7703 <1> ja short keyb_int3 1963 <1> keyb_int2: 1964 00000BB7 668903 <1> mov [ebx], ax ; Save ascii code 1965 <1> ; and scan code of the character 1966 <1> ; for current tty (or last tty 1967 <1> ; just before tty switch). 1968 <1> keyb_int3: 1969 00000BBA A0[66610000] <1> mov al, [ptty] 1970 00000BBF E8233A0000 <1> call wakeup 1971 <1> ; 1972 <1> keyb_int4: 1973 00000BC4 58 <1> pop eax 1974 00000BC5 5B <1> pop ebx 1975 00000BC6 1F <1> pop ds 1976 00000BC7 CF <1> iret 1977 <1> 1978 <1> ; 18/02/2015 1979 <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc. 1980 <1> ; 'keyb_int' always handles 'getc' at 1st and puts the 1981 <1> ; scancode and ascii code of the character 1982 <1> ; in the tty input (ttychr) buffer. 1983 <1> ; Test procedures must call 'getch' for tty input 1984 <1> ; otherwise, 'getc' will not be able to return to the caller 1985 <1> ; due to infinite (key press) waiting loop. 1986 <1> ; 1987 <1> ; 03/12/2014 1988 <1> ; 26/08/2014 1989 <1> ; KEYBOARD I/O 1990 <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014) 1991 <1> 1992 <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers. 1993 <1> ; (The reason of using '_k' labels!!!) (27/08/2014) 1994 <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM. 1995 <1> ; ('NOT LC_HC' --> '~LC_HC') (bit reversing operator) 1996 <1> 1997 <1> 1998 <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 1999 <1> ;int_16h: ; 30/06/2015 2000 <1> ;;getc: 2001 <1> ; pushfd ; 28/08/2014 2002 <1> ; push cs 2003 <1> ; call getc_int 2004 <1> ; retn 2005 <1> 2006 <1> ; 24/07/2022 2007 <1> %if 0 2008 <1> ; 24/12/2021 2009 <1> 2010 <1> ;----- SHIFT STATUS 2011 <1> _K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2012 <1> mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2013 <1> and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2014 <1> ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2015 <1> ;shl ah, cl ; BIT 7 POSITION 2016 <1> shl ah, 5 2017 <1> mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2018 <1> and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2019 <1> or ah, al ; MERGE REMAINING BITS INTO AH 2020 <1> mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2021 <1> and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2022 <1> or ah, al ; OR THE SHIFT FLAGS TOGETHER 2023 <1> _K3: 2024 <1> mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2025 <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2026 <1> 2027 <1> %endif 2028 <1> 2029 <1> int_16h: 2030 <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2031 <1> ; 24/07/2022 - (near call return instead of interrupt return) 2032 <1> 2033 <1> ; INPUT: 2034 <1> ; AH = Function (0 or 1) 2035 <1> ; 0 = Read Character 2036 <1> ; 1 = Get Keyboard Buffer Status 2037 <1> ; OUTPUT: 2038 <1> ; Function 0 - AX = ASCII (AL) and SCAN CODE (AH) 2039 <1> ; of the character (enterrd from the keyboard) 2040 <1> ; Function 1 - If ZF = 0 2041 <1> ; AX = ASCII (AL) and SCAN CODE (AH) of the character 2042 <1> ; (which is waiting in keyboard buffer) 2043 <1> ; If ZF = 1 2044 <1> ; there is not a character in the keyboard buffer 2045 <1> ; 2046 <1> ; Modified registers: eax, ebx 2047 <1> 2048 <1> getc_int: 2049 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2050 <1> ; 28/02/2015 2051 <1> ; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2052 <1> ; instead of pc-at bios - 1985-) 2053 <1> ; 28/08/2014 (_k1d) 2054 <1> ; 30/06/2014 2055 <1> ; 03/03/2014 2056 <1> ; 28/02/2014 2057 <1> ; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 2058 <1> ; rombios source code (21/04/1986) 2059 <1> ; 'keybd.asm', INT 16H, KEYBOARD_IO 2060 <1> ; 2061 <1> ; KYBD --- 03/06/86 KEYBOARD BIOS 2062 <1> ; 2063 <1> ;--- INT 16 H ----------------------------------------------------------------- 2064 <1> ; KEYBOARD I/O : 2065 <1> ; THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT : 2066 <1> ; INPUT : 2067 <1> ; (AH)= 00H READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD, : 2068 <1> ; RETURN THE RESULT IN (AL), SCAN CODE IN (AH). : 2069 <1> ; THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE : 2070 <1> ; STANDARD PC OR PCAT KEYBOARD : 2071 <1> ;-----------------------------------------------------------------------------: 2072 <1> ; (AH)= 01H SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS : 2073 <1> ; AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER. : 2074 <1> ; (ZF)= 1 -- NO CODE AVAILABLE : 2075 <1> ; (ZF)= 0 -- CODE IS AVAILABLE (AX)= CHARACTER : 2076 <1> ; IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS : 2077 <1> ; IN (AX), AND THE ENTRY REMAINS IN THE BUFFER. : 2078 <1> ; THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES : 2079 <1> ;-----------------------------------------------------------------------------: 2080 <1> ; (AH)= 02H RETURN THE CURRENT SHIFT STATUS IN AL REGISTER : 2081 <1> ; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE : 2082 <1> ; EQUATES FOR @KB_FLAG : 2083 <1> ;-----------------------------------------------------------------------------: 2084 <1> ; (AH)= 03H SET TYPAMATIC RATE AND DELAY : 2085 <1> ; (AL) = 05H : 2086 <1> ; (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0) : 2087 <1> ; : 2088 <1> ; REGISTER RATE REGISTER RATE : 2089 <1> ; VALUE SELECTED VALUE SELECTED : 2090 <1> ; -------------------------------------------- : 2091 <1> ; 00H 30.0 10H 7.5 : 2092 <1> ; 01H 26.7 11H 6.7 : 2093 <1> ; 02H 24.0 12H 6.0 : 2094 <1> ; 03H 21.8 13H 5.5 : 2095 <1> ; 04H 20.0 14H 5.0 : 2096 <1> ; 05H 18.5 15H 4.6 : 2097 <1> ; 06H 17.1 16H 4.3 : 2098 <1> ; 07H 16.0 17H 4.0 : 2099 <1> ; 08H 15.0 18H 3.7 : 2100 <1> ; 09H 13.3 19H 3.3 : 2101 <1> ; 0AH 12.0 1AH 3.0 : 2102 <1> ; 0BH 10.9 1BH 2.7 : 2103 <1> ; 0CH 10.0 1CH 2.5 : 2104 <1> ; 0DH 9.2 1DH 2.3 : 2105 <1> ; 0EH 8.6 1EH 2.1 : 2106 <1> ; 0FH 8.0 1FH 2.0 : 2107 <1> ; : 2108 <1> ; (BH) = TYPAMATIC DELAY (BITS 2 - 7 MUST BE RESET TO 0) : 2109 <1> ; : 2110 <1> ; REGISTER DELAY : 2111 <1> ; VALUE VALUE : 2112 <1> ; ------------------ : 2113 <1> ; 00H 250 ms : 2114 <1> ; 01H 500 ms : 2115 <1> ; 02H 750 ms : 2116 <1> ; 03H 1000 ms : 2117 <1> ;-----------------------------------------------------------------------------: 2118 <1> ; (AH)= 05H PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD : 2119 <1> ; BUFFER AS IF STRUCK FROM KEYBOARD : 2120 <1> ; ENTRY: (CL) = ASCII CHARACTER : 2121 <1> ; (CH) = SCAN CODE : 2122 <1> ; EXIT: (AH) = 00H = SUCCESSFUL OPERATION : 2123 <1> ; (AL) = 01H = UNSUCCESSFUL - BUFFER FULL : 2124 <1> ; FLAGS: CARRY IF ERROR : 2125 <1> ;-----------------------------------------------------------------------------: 2126 <1> ; (AH)= 10H EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD, : 2127 <1> ; OTHERWISE SAME AS FUNCTION AH=0 : 2128 <1> ;-----------------------------------------------------------------------------: 2129 <1> ; (AH)= 11H EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD, : 2130 <1> ; OTHERWISE SAME AS FUNCTION AH=1 : 2131 <1> ;-----------------------------------------------------------------------------: 2132 <1> ; (AH)= 12H RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER : 2133 <1> ; AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT : 2134 <1> ; CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3 : 2135 <1> ; OUTPUT : 2136 <1> ; AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED : 2137 <1> ; ALL REGISTERS RETAINED : 2138 <1> ;------------------------------------------------------------------------------ 2139 <1> 2140 00000BC8 FB <1> sti ; INTERRUPTS BACK ON 2141 <1> 2142 <1> ; 24/07/2022 2143 <1> ;push ds ; SAVE CURRENT DS 2144 <1> ;push ebx ; SAVE BX TEMPORARILY 2145 <1> ;push ecx ; SAVE CX TEMPORARILY 2146 <1> ;mov bx, KDATA 2147 <1> ;mov ds, bx ; PUT SEGMENT VALUE OF DATA AREA INTO DS 2148 <1> 2149 <1> ;or ah, ah ; CHECK FOR (AH)= 00H 2150 <1> ;jz short _K1 ; ASCII_READ 2151 <1> ;dec ah ; CHECK FOR (AH)= 01H 2152 <1> ;jz short _K2 ; ASCII_STATUS 2153 <1> ;dec ah ; CHECK FOR (AH)= 02H 2154 <1> ;jz short _K3 ; SHIFT STATUS 2155 <1> ;dec ah ; CHECK FOR (AH)= 03H 2156 <1> ;jz short _K300 ; SET TYPAMATIC RATE/DELAY 2157 <1> ;sub ah, 2 ; CHECK FOR (AH)= 05H 2158 <1> ;jz short _K500 ; KEYBOARD WRITE 2159 <1> ;_KIO1: 2160 <1> ;sub ah, 11 ; AH = 10H 2161 <1> ;jz short _K1E ; EXTENDED ASCII READ 2162 <1> ;dec ah ; CHECK FOR (AH)= 11H 2163 <1> ;jz short _K2E ; EXTENDED_ASCII_STATUS 2164 <1> ;dec ah ; CHECK FOR (AH)= 12H 2165 <1> ;jz short _K3E ; EXTENDED_SHIFT_STATUS 2166 <1> 2167 <1> ;_KIO_EXIT: 2168 <1> ;pop ecx ; RECOVER REGISTER 2169 <1> ;pop ebx ; RECOVER REGISTER 2170 <1> ; 24/07/2022 2171 <1> ;retn 2172 <1> ;pop ds ; RECOVER SEGMENT 2173 <1> ;iretd ; INVALID COMMAND, EXIT 2174 <1> 2175 00000BC9 08E4 <1> or ah, ah 2176 00000BCB 7507 <1> jnz short _K2 2177 <1> 2178 <1> ;----- ASCII CHARACTER 2179 <1> _K1: 2180 <1> _K1E: 2181 00000BCD E81C000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER (EXTENDED) 2182 <1> ;call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2183 <1> ;;jmp short _KIO_EXIT ; GIVE IT TO THE CALLER 2184 <1> ; 24/07/2022 2185 <1> ;retn 2186 00000BD2 EB0F <1> jmp short _KIO_E_XLAT 2187 <1> ;_K1: 2188 <1> ;call _K1S ; GET A CHARACTER FROM THE BUFFER 2189 <1> ;call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2190 <1> ;jc short _K1 ; CARRY SET MEANS TROW CODE AWAY 2191 <1> ;_K1A: 2192 <1> ;jmp short _KIO_EXIT ; RETURN TO CALLER 2193 <1> ; 24/07/2022 2194 <1> ;retn 2195 <1> 2196 <1> ;----- ASCII STATUS 2197 <1> _K2: 2198 <1> _K2E: 2199 00000BD4 E860000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER (EXTENDED) 2200 00000BD9 7407 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2201 00000BDB 9C <1> pushf ; SAVE ZF FROM TEST 2202 00000BDC E802000000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2203 <1> ;jmp short _K2A ; GIVE IT TO THE CALLER 2204 <1> ; 24/07/2022 2205 00000BE1 9D <1> popf 2206 <1> _K2B: 2207 00000BE2 C3 <1> retn 2208 <1> ;_K2: 2209 <1> ;call _K2S ; TEST FOR CHARACTER IN BUFFER 2210 <1> ;jz short _K2B ; RETURN IF BUFFER EMPTY 2211 <1> ;pushf ; SAVE ZF FROM TEST 2212 <1> ;call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2213 <1> ;jnc short _K2A ; CARRY CLEAR MEANS PASS VALID CODE 2214 <1> ;popf ; INVALID CODE FOR THIS TYPE OF CALL 2215 <1> ;call _K1S ; THROW THE CHARACTER AWAY 2216 <1> ;jmp short _K2 ; GO LOOK FOR NEXT CHAR, IF ANY 2217 <1> ;_K2A: 2218 <1> ;popf ; RESTORE ZF FROM TEST 2219 <1> ;_K2B: 2220 <1> ;;pop ecx ; RECOVER REGISTER 2221 <1> ;pop ebx ; RECOVER REGISTER 2222 <1> ;pop ds ; RECOVER SEGMENT 2223 <1> ;retf 4 ; THROW AWAY (E)FLAGS 2224 <1> 2225 <1> ; 24/12/2021 2226 <1> ; ;----- SHIFT STATUS 2227 <1> ;_K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2228 <1> ; mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2229 <1> ; and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2230 <1> ; ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2231 <1> ; ;shl ah, cl ; BIT 7 POSITION 2232 <1> ; shl ah, 5 2233 <1> ; mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2234 <1> ; and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2235 <1> ; or ah, al ; MERGE REMAINING BITS INTO AH 2236 <1> ; mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2237 <1> ; and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2238 <1> ; or ah, al ; OR THE SHIFT FLAGS TOGETHER 2239 <1> ;_K3: 2240 <1> ; mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2241 <1> ; jmp short _KIO_EXIT ; RETURN TO CALLER 2242 <1> 2243 <1> ; 24/07/2022 2244 <1> %if 0 2245 <1> ;----- SET TYPAMATIC RATE AND DELAY 2246 <1> _K300: 2247 <1> cmp al, 5 ; CORRECT FUNCTION CALL? 2248 <1> jne short _KIO_EXIT ; NO, RETURN 2249 <1> test bl, 0E0h ; TEST FOR OUT-OF-RANGE RATE 2250 <1> jnz short _KIO_EXIT ; RETURN IF SO 2251 <1> test BH, 0FCh ; TEST FOR OUT-OF-RANGE DELAY 2252 <1> jnz short _KIO_EXIT ; RETURN IF SO 2253 <1> mov al, KB_TYPA_RD ; COMMAND FOR TYPAMATIC RATE/DELAY 2254 <1> call SND_DATA ; SEND TO KEYBOARD 2255 <1> ;mov cx, 5 ; SHIFT COUNT 2256 <1> ;shl bh, cl ; SHIFT DELAY OVER 2257 <1> shl bh, 5 2258 <1> mov al, bl ; PUT IN RATE 2259 <1> or al, bh ; AND DELAY 2260 <1> call SND_DATA ; SEND TO KEYBOARD 2261 <1> jmp _KIO_EXIT ; RETURN TO CALLER 2262 <1> 2263 <1> ;----- WRITE TO KEYBOARD BUFFER 2264 <1> _K500: 2265 <1> push esi ; SAVE SI (esi) 2266 <1> cli ; 2267 <1> mov ebx, [BUFFER_TAIL] ; GET THE 'IN TO' POINTER TO THE BUFFER 2268 <1> mov esi, ebx ; SAVE A COPY IN CASE BUFFER NOT FULL 2269 <1> call _K4 ; BUMP THE POINTER TO SEE IF BUFFER IS FULL 2270 <1> cmp ebx, [BUFFER_HEAD] ; WILL THE BUFFER OVERRUN IF WE STORE THIS? 2271 <1> je short _K502 ; YES - INFORM CALLER OF ERROR 2272 <1> mov [esi], cx ; NO - PUT ASCII/SCAN CODE INTO BUFFER 2273 <1> mov [BUFFER_TAIL], ebx ; ADJUST 'IN TO' POINTER TO REFLECT CHANGE 2274 <1> sub al, al ; TELL CALLER THAT OPERATION WAS SUCCESSFUL 2275 <1> jmp short _K504 ; SUB INSTRUCTION ALSO RESETS CARRY FLAG 2276 <1> _K502: 2277 <1> mov al, 01h ; BUFFER FULL INDICATION 2278 <1> _K504: 2279 <1> sti 2280 <1> pop esi ; RECOVER SI (esi) 2281 <1> jmp _KIO_EXIT ; RETURN TO CALLER WITH STATUS IN AL 2282 <1> %endif 2283 <1> 2284 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS ----- 2285 <1> _KIO_E_XLAT: 2286 00000BE3 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2287 00000BE5 7506 <1> jne short _KIO_E_RET ; NO, PASS IT ON 2288 00000BE7 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2289 00000BE9 7402 <1> jz short _KIO_E_RET ; PASS THIS ON UNCHANGED 2290 00000BEB 30C0 <1> xor al, al ; OTHERWISE SET AL = 0 2291 <1> _KIO_E_RET: 2292 00000BED C3 <1> retn ; GO BACK 2293 <1> 2294 <1> ;----- READ THE KEY TO FIGURE OUT WHAT TO DO ----- 2295 <1> _K1S: 2296 00000BEE FA <1> cli ; 03/12/2014 2297 00000BEF 8B1D[A05B0000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2298 00000BF5 3B1D[A45B0000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2299 <1> ;jne short _K1U ; IF ANYTHING IN BUFFER SKIP INTERRUPT 2300 00000BFB 750F <1> jne short _k1x ; 03/12/2014 2301 <1> ; 2302 <1> ; 03/12/2014 2303 <1> ; 28/08/2014 2304 <1> ; PERFORM OTHER FUNCTION ?? here ! 2305 <1> ;;mov ax, 9002h ; MOVE IN WAIT CODE & TYPE 2306 <1> ;;int 15h ; PERFORM OTHER FUNCTION 2307 <1> _K1T: ; ASCII READ 2308 00000BFD FB <1> sti ; INTERRUPTS BACK ON DURING LOOP 2309 00000BFE 90 <1> nop ; ALLOW AN INTERRUPT TO OCCUR 2310 <1> _K1U: 2311 00000BFF FA <1> cli ; INTERRUPTS BACK OFF 2312 00000C00 8B1D[A05B0000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2313 00000C06 3B1D[A45B0000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2314 <1> _k1x: 2315 00000C0C 53 <1> push ebx ; SAVE ADDRESS 2316 00000C0D 9C <1> pushf ; SAVE FLAGS 2317 00000C0E E895060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2318 00000C13 8A1D[955B0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2319 00000C19 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2320 00000C1B 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2321 00000C1E 7406 <1> jz short _K1V ; IF NO CHANGE BYPASS UPDATE 2322 00000C20 E82F060000 <1> call SND_LED1 2323 00000C25 FA <1> cli ; DISABLE INTERRUPTS 2324 <1> _K1V: 2325 00000C26 9D <1> popf ; RESTORE FLAGS 2326 00000C27 5B <1> pop ebx ; RESTORE ADDRESS 2327 00000C28 74D3 <1> je short _K1T ; LOOP UNTIL SOMETHING IN BUFFER 2328 <1> ; 2329 00000C2A 668B03 <1> mov ax, [ebx] ; GET SCAN CODE AND ASCII CODE 2330 00000C2D E834000000 <1> call _K4 ; MOVE POINTER TO NEXT POSITION 2331 00000C32 891D[A05B0000] <1> mov [BUFFER_HEAD], ebx ; STORE VALUE IN VARIABLE 2332 00000C38 C3 <1> retn ; RETURN 2333 <1> 2334 <1> ;----- READ THE KEY TO SEE IF ONE IS PRESENT ----- 2335 <1> _K2S: 2336 00000C39 FA <1> cli ; INTERRUPTS OFF 2337 00000C3A 8B1D[A05B0000] <1> mov ebx, [BUFFER_HEAD] ; GET HEAD POINTER 2338 00000C40 3B1D[A45B0000] <1> cmp ebx, [BUFFER_TAIL] ; IF EQUAL (Z=1) THEN NOTHING THERE 2339 00000C46 668B03 <1> mov ax, [ebx] 2340 00000C49 9C <1> pushf ; SAVE FLAGS 2341 <1> ;push ax ; SAVE CODE 2342 <1> ; 24/12/2021 2343 00000C4A 50 <1> push eax 2344 00000C4B E858060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2345 00000C50 8A1D[955B0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2346 00000C56 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2347 00000C58 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2348 00000C5B 7405 <1> jz short _K2T ; IF NO CHANGE BYPASS UPDATE 2349 00000C5D E8DB050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2350 <1> _K2T: 2351 <1> ;pop ax ; RESTORE CODE 2352 <1> ; 24/12/2021 2353 00000C62 58 <1> pop eax 2354 00000C63 9D <1> popf ; RESTORE FLAGS 2355 00000C64 FB <1> sti ; INTERRUPTS BACK ON 2356 00000C65 C3 <1> retn ; RETURN 2357 <1> 2358 <1> ; 24/07/2022 2359 <1> %if 0 2360 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS ----- 2361 <1> _KIO_S_XLAT: 2362 <1> cmp ah, 0E0h ; IS IT KEYPAD ENTER OR / ? 2363 <1> jne short _KIO_S2 ; NO, CONTINUE 2364 <1> cmp al, 0Dh ; KEYPAD ENTER CODE? 2365 <1> je short _KIO_S1 ; YES, MASSAGE A BIT 2366 <1> cmp al, 0Ah ; CTRL KEYPAD ENTER CODE? 2367 <1> je short _KIO_S1 ; YES, MASSAGE THE SAME 2368 <1> mov ah, 35h ; NO, MUST BE KEYPAD / 2369 <1> _kio_ret: ; 03/12/2014 2370 <1> clc 2371 <1> retn 2372 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2373 <1> _KIO_S1: 2374 <1> mov ah, 1Ch ; CONVERT TO COMPATIBLE OUTPUT 2375 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2376 <1> retn 2377 <1> _KIO_S2: 2378 <1> cmp ah, 84h ; IS IT ONE OF EXTENDED ONES? 2379 <1> ja short _KIO_DIS ; YES, THROW AWAY AND GET ANOTHER CHAR 2380 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2381 <1> jne short _KIO_S3 ; NO, TRY LAST TEST 2382 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2383 <1> jz short _KIO_USE ; PASS THIS ON UNCHANGED 2384 <1> jmp short _KIO_DIS ; THROW AWAY THE REST 2385 <1> _KIO_S3: 2386 <1> cmp al, 0E0h ; IS IT AN EXTENSION OF A PREVIOUS ONE? 2387 <1> ;jne short _KIO_USE ; NO, MUST BE A STANDARD CODE 2388 <1> jne short _kio_ret 2389 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2390 <1> jz short _KIO_USE ; JUMP IF AH = 0 2391 <1> xor al, al ; CONVERT TO COMPATIBLE OUTPUT 2392 <1> ;jmp short _KIO_USE ; PASS IT ON TO CALLER 2393 <1> _KIO_USE: 2394 <1> ;clc ; CLEAR CARRY TO INDICATE GOOD CODE 2395 <1> retn ; RETURN 2396 <1> _KIO_DIS: 2397 <1> stc ; SET CARRY TO INDICATE DISCARD CODE 2398 <1> retn ; RETURN 2399 <1> 2400 <1> %endif 2401 <1> 2402 <1> ;----- INCREMENT BUFFER POINTER ROUTINE ----- 2403 <1> _K4: 2404 00000C66 43 <1> inc ebx 2405 00000C67 43 <1> inc ebx ; MOVE TO NEXT WORD IN LIST 2406 00000C68 3B1D[9C5B0000] <1> cmp ebx, [BUFFER_END] ; AT END OF BUFFER? 2407 <1> ;jne short _K5 ; NO, CONTINUE 2408 00000C6E 7206 <1> jb short _K5 2409 00000C70 8B1D[985B0000] <1> mov ebx, [BUFFER_START] ; YES, RESET TO BUFFER BEGINNING 2410 <1> _K5: 2411 00000C76 C3 <1> retn 2412 <1> 2413 <1> ; 20/02/2015 2414 <1> ; 05/12/2014 2415 <1> ; 26/08/2014 2416 <1> ; KEYBOARD (HARDWARE) INTERRUPT - IRQ LEVEL 1 2417 <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014) 2418 <1> ; 2419 <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 2420 <1> ; rombios source code (06/10/1985) 2421 <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1) 2422 <1> 2423 <1> ;--------- 8042 COMMANDS ------------------------------------------------------- 2424 <1> ENA_KBD equ 0AEh ; ENABLE KEYBOARD COMMAND 2425 <1> DIS_KBD equ 0ADh ; DISABLE KEYBOARD COMMAND 2426 <1> SHUT_CMD equ 0FEh ; CAUSE A SHUTDOWN COMMAND 2427 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2428 <1> STATUS_PORT equ 064h ; 8042 STATUS PORT 2429 <1> INPT_BUF_FULL equ 00000010b ; 1 = +INPUT BUFFER FULL 2430 <1> PORT_A equ 060h ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2431 <1> ;---------- 8042 KEYBOARD RESPONSE --------------------------------------------- 2432 <1> KB_ACK equ 0FAh ; ACKNOWLEDGE PROM TRANSMISSION 2433 <1> KB_RESEND equ 0FEh ; RESEND REQUEST 2434 <1> KB_OVER_RUN equ 0FFh ; OVER RUN SCAN CODE 2435 <1> ;---------- KEYBOARD/LED COMMANDS ---------------------------------------------- 2436 <1> KB_ENABLE equ 0F4h ; KEYBOARD ENABLE 2437 <1> LED_CMD equ 0EDh ; LED WRITE COMMAND 2438 <1> KB_TYPA_RD equ 0F3h ; TYPAMATIC RATE/DELAY COMMAND 2439 <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------ 2440 <1> NUM_KEY equ 69 ; SCAN CODE FOR NUMBER LOCK KEY 2441 <1> SCROLL_KEY equ 70 ; SCAN CODE FOR SCROLL LOCK KEY 2442 <1> ALT_KEY equ 56 ; SCAN CODE FOR ALTERNATE SHIFT KEY 2443 <1> CTL_KEY equ 29 ; SCAN CODE FOR CONTROL KEY 2444 <1> CAPS_KEY equ 58 ; SCAN CODE FOR SHIFT LOCK KEY 2445 <1> DEL_KEY equ 83 ; SCAN CODE FOR DELETE KEY 2446 <1> INS_KEY equ 82 ; SCAN CODE FOR INSERT KEY 2447 <1> LEFT_KEY equ 42 ; SCAN CODE FOR LEFT SHIFT 2448 <1> RIGHT_KEY equ 54 ; SCAN CODE FOR RIGHT SHIFT 2449 <1> SYS_KEY equ 84 ; SCAN CODE FOR SYSTEM KEY 2450 <1> ;---------- ENHANCED KEYBOARD SCAN CODES --------------------------------------- 2451 <1> ID_1 equ 0ABh ; 1ST ID CHARACTER FOR KBX 2452 <1> ID_2 equ 041h ; 2ND ID CHARACTER FOR KBX 2453 <1> ID_2A equ 054h ; ALTERNATE 2ND ID CHARACTER FOR KBX 2454 <1> F11_M equ 87 ; F11 KEY MAKE 2455 <1> F12_M equ 88 ; F12 KEY MAKE 2456 <1> MC_E0 equ 224 ; GENERAL MARKER CODE 2457 <1> MC_E1 equ 225 ; PAUSE KEY MARKER CODE 2458 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG---------------------------------------- 2459 <1> RIGHT_SHIFT equ 00000001b ; RIGHT SHIFT KEY DEPRESSED 2460 <1> LEFT_SHIFT equ 00000010b ; LEFT SHIFT KEY DEPRESSED 2461 <1> CTL_SHIFT equ 00000100b ; CONTROL SHIFT KEY DEPRESSED 2462 <1> ALT_SHIFT equ 00001000b ; ALTERNATE SHIFT KEY DEPRESSED 2463 <1> SCROLL_STATE equ 00010000b ; SCROLL LOCK STATE IS ACTIVE 2464 <1> NUM_STATE equ 00100000b ; NUM LOCK STATE IS ACTIVE 2465 <1> CAPS_STATE equ 01000000b ; CAPS LOCK STATE IS ACTIVE 2466 <1> INS_STATE equ 10000000b ; INSERT STATE IS ACTIVE 2467 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG_1 ------------------------------------- 2468 <1> L_CTL_SHIFT equ 00000001b ; LEFT CTL KEY DOWN 2469 <1> L_ALT_SHIFT equ 00000010b ; LEFT ALT KEY DOWN 2470 <1> SYS_SHIFT equ 00000100b ; SYSTEM KEY DEPRESSED AND HELD 2471 <1> HOLD_STATE equ 00001000b ; SUSPEND KEY HAS BEEN TOGGLED 2472 <1> SCROLL_SHIFT equ 00010000b ; SCROLL LOCK KEY IS DEPRESSED 2473 <1> NUM_SHIFT equ 00100000b ; NUM LOCK KEY IS DEPRESSED 2474 <1> CAPS_SHIFT equ 01000000b ; CAPS LOCK KEY IS DEPRE55ED 2475 <1> INS_SHIFT equ 10000000b ; INSERT KEY IS DEPRESSED 2476 <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 ----------------------------------- 2477 <1> KB_LEDS equ 00000111b ; KEYBOARD LED STATE BITS 2478 <1> ; equ 00000001b ; SCROLL LOCK INDICATOR 2479 <1> ; equ 00000010b ; NUM LOCK INDICATOR 2480 <1> ; equ 00000100b ; CAPS LOCK INDICATOR 2481 <1> ; equ 00001000b ; RESERVED (MUST BE ZERO) 2482 <1> KB_FA equ 00010000b ; ACKNOWLEDGMENT RECEIVED 2483 <1> KB_FE equ 00100000b ; RESEND RECEIVED FLAG 2484 <1> KB_PR_LED equ 01000000b ; MODE INDICATOR UPDATE 2485 <1> KB_ERR equ 10000000b ; KEYBOARD TRANSMIT ERROR FLAG 2486 <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 ----------------------------------- 2487 <1> LC_E1 equ 00000001b ; LAST CODE WAS THE E1 HIDDEN CODE 2488 <1> LC_E0 equ 00000010b ; LAST CODE WAS THE E0 HIDDEN CODE 2489 <1> R_CTL_SHIFT equ 00000100b ; RIGHT CTL KEY DOWN 2490 <1> R_ALT_SHIFT equ 00001000b ; RIGHT ALT KEY DOWN 2491 <1> GRAPH_ON equ 00001000b ; ALT GRAPHICS KEY DOWN (WT ONLY) 2492 <1> KBX equ 00010000b ; ENHANCED KEYBOARD INSTALLED 2493 <1> SET_NUM_LK equ 00100000b ; FORCE NUM LOCK IF READ ID AND KBX 2494 <1> LC_AB equ 01000000b ; LAST CHARACTER WAS FIRST ID CHARACTER 2495 <1> RD_ID equ 10000000b ; DOING A READ ID (MUST BE BIT0) 2496 <1> ; 2497 <1> ;----------- INTERRUPT EQUATES ------------------------------------------------- 2498 <1> EOI equ 020h ; END OF INTERRUPT COMMAND TO 8259 2499 <1> INTA00 equ 020h ; 8259 PORT 2500 <1> 2501 <1> kb_int: 2502 <1> 2503 <1> ; 13/06/2022 2504 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2505 <1> ; 17/10/2015 ('ctrlbrk') 2506 <1> ; 05/12/2014 2507 <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2508 <1> ; instead of pc-at bios - 1985-) 2509 <1> ; 26/08/2014 2510 <1> ; 2511 <1> ; 03/06/86 KEYBOARD BIOS 2512 <1> ; 2513 <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------ 2514 <1> ; ; 2515 <1> ; KEYBOARD INTERRUPT ROUTINE ; 2516 <1> ; ; 2517 <1> ;-------------------------------------------------------------------------------- 2518 <1> 2519 <1> KB_INT_1: 2520 00000C77 FB <1> sti ; ENABLE INTERRUPTS 2521 <1> ;push ebp 2522 00000C78 50 <1> push eax 2523 00000C79 53 <1> push ebx 2524 00000C7A 51 <1> push ecx 2525 00000C7B 52 <1> push edx 2526 00000C7C 56 <1> push esi 2527 00000C7D 57 <1> push edi 2528 00000C7E 1E <1> push ds 2529 00000C7F 06 <1> push es 2530 00000C80 FC <1> cld ; FORWARD DIRECTION 2531 00000C81 66B81000 <1> mov ax, KDATA 2532 00000C85 8ED8 <1> mov ds, ax 2533 00000C87 8EC0 <1> mov es, ax 2534 <1> ; 2535 <1> ;----- WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED 2536 00000C89 B0AD <1> mov al, DIS_KBD ; DISABLE THE KEYBOARD COMMAND 2537 00000C8B E852050000 <1> call SHIP_IT ; EXECUTE DISABLE 2538 00000C90 FA <1> cli ; DISABLE INTERRUPTS 2539 00000C91 B900000100 <1> mov ecx, 10000h ; SET MAXIMUM TIMEOUT 2540 <1> KB_INT_01: 2541 00000C96 E464 <1> in al, STATUS_PORT ; READ ADAPTER STATUS 2542 00000C98 A802 <1> test al, INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT 2543 00000C9A E0FA <1> loopnz KB_INT_01 ; WAIT FOR COMMAND TO BE ACCEPTED 2544 <1> ; 2545 <1> ;----- READ CHARACTER FROM KEYBOARD INTERFACE 2546 00000C9C E460 <1> in al, PORT_A ; READ IN THE CHARACTER 2547 <1> ; 2548 <1> ;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 2549 <1> ;mov ah, 04Fh ; SYSTEM INTERCEPT - KEY CODE FUNCTION 2550 <1> ;stc ; SET CY=1 (IN CASE OF IRET) 2551 <1> ;int 15h ; CASETTE CALL (AL)=KEY SCAN CODE 2552 <1> ; ; RETURNS CY=1 FOR INVALID FUNCTION 2553 <1> ;jc KB_INT_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) 2554 <1> ;jmp K26 ; EXIT IF SYSTEM HANDLES SCAN CODE 2555 <1> ; ; EXÝT HANDLES HARDWARE EOI AND ENABLE 2556 <1> ; 2557 <1> ;----- CHECK FOR A RESEND COMMAND TO KEYBOARD 2558 <1> KB_INT_02: ; (AL)= SCAN CODE 2559 00000C9E FB <1> sti ; ENABLE INTERRUPTS AGAIN 2560 00000C9F 3CFE <1> cmp al, KB_RESEND ; IS THE INPUT A RESEND 2561 00000CA1 7411 <1> je short KB_INT_4 ; GO IF RESEND 2562 <1> ; 2563 <1> ;----- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD 2564 00000CA3 3CFA <1> cmp al, KB_ACK ; IS THE INPUT AN ACKNOWLEDGE 2565 00000CA5 751A <1> jne short KB_INT_2 ; GO IF NOT 2566 <1> ; 2567 <1> ;----- A COMMAND TO THE KEYBOARD WAS ISSUED 2568 00000CA7 FA <1> cli ; DISABLE INTERRUPTS 2569 00000CA8 800D[955B0000]10 <1> or byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED 2570 00000CAF E963020000 <1> jmp K26 ; RETURN IF NOT (ACK RETURNED FOR DATA) 2571 <1> ; 2572 <1> ;----- RESEND THE LAST BYTE 2573 <1> KB_INT_4: 2574 00000CB4 FA <1> cli ; DISABLE INTERRUPTS 2575 00000CB5 800D[955B0000]20 <1> or byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED 2576 00000CBC E956020000 <1> jmp K26 ; RETURN IF NOT ACK RETURNED FOR DATA) 2577 <1> ; 2578 <1> ;----- UPDATE MODE INDICATORS IF CHANGE IN STATE 2579 <1> KB_INT_2: 2580 <1> ;push ax ; SAVE DATA IN 2581 <1> ; 24/12/2021 2582 00000CC1 50 <1> push eax 2583 00000CC2 E8E1050000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2584 00000CC7 8A1D[955B0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2585 00000CCD 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2586 00000CCF 80E307 <1> and bl, KB_LEDS ; ISOLATE INDICATOR BITS 2587 00000CD2 7405 <1> jz short UP0 ; IF NO CHANGE BYPASS UPDATE 2588 00000CD4 E864050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2589 <1> UP0: 2590 <1> ;pop ax ; RESTORE DATA IN 2591 <1> ; 24/12/2021 2592 00000CD9 58 <1> pop eax 2593 <1> ;------------------------------------------------------------------------ 2594 <1> ; START OF KEY PROCESSING ; 2595 <1> ;------------------------------------------------------------------------ 2596 00000CDA 88C4 <1> mov ah, al ; SAVE SCAN CODE IN AH ALSO 2597 <1> ; 2598 <1> ;----- TEST FOR OVERRUN SCAN CODE FROM KEYBOARD 2599 00000CDC 3CFF <1> cmp al, KB_OVER_RUN ; IS THIS AN OVERRUN CHAR 2600 <1> ;je K62 ; BUFFER_FULL_BEEP 2601 <1> ; 24/12/2021 2602 00000CDE 7505 <1> jne short K16 2603 00000CE0 E9E9040000 <1> jmp K62 2604 <1> K16: 2605 00000CE5 8A3D[965B0000] <1> mov bh, [KB_FLAG_3] ; LOAD FLAGS FOR TESTING 2606 <1> ; 2607 <1> ;----- TEST TO SEE IF A READ_ID IS IN PROGRESS 2608 00000CEB F6C7C0 <1> test bh, RD_ID+LC_AB ; ARE WE DOING A READ ID? 2609 00000CEE 7442 <1> jz short NOT_ID ; CONTINUE IF NOT 2610 00000CF0 7914 <1> jns short TST_ID_2 ; IS THE RD_ID FLAG ON? 2611 00000CF2 3CAB <1> cmp al, ID_1 ; IS THIS THE 1ST ID CHARACTER? 2612 00000CF4 7507 <1> jne short RST_RD_ID 2613 00000CF6 800D[965B0000]40 <1> or byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK 2614 <1> RST_RD_ID: 2615 00000CFD 8025[965B0000]7F <1> and byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG 2616 00000D04 EB27 <1> jmp short ID_EX ; AND EXIT 2617 <1> ; 24/12/2021 2618 <1> ;jmp K26 2619 <1> ; 2620 <1> TST_ID_2: 2621 00000D06 8025[965B0000]BF <1> and byte [KB_FLAG_3], ~LC_AB ; RESET FLAG 2622 00000D0D 3C54 <1> cmp al, ID_2A ; IS THIS THE 2ND ID CHARACTER? 2623 00000D0F 7415 <1> je short KX_BIT ; JUMP IF SO 2624 00000D11 3C41 <1> cmp al, ID_2 ; IS THIS THE 2ND ID CHARACTER? 2625 00000D13 7518 <1> jne short ID_EX ; LEAVE IF NOT 2626 <1> ; 24/12/2021 2627 <1> ;jne K26 2628 <1> ; 2629 <1> ;----- A READ ID SAID THAT IT WAS ENHANCED KEYBOARD 2630 00000D15 F6C720 <1> test bh, SET_NUM_LK ; SHOULD WE SET NUM LOCK? 2631 00000D18 740C <1> jz short KX_BIT ; EXIT IF NOT 2632 00000D1A 800D[935B0000]20 <1> or byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON 2633 00000D21 E817050000 <1> call SND_LED ; GO SET THE NUM LOCK INDICATOR 2634 <1> KX_BIT: 2635 00000D26 800D[965B0000]10 <1> or byte [KB_FLAG_3], KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND 2636 00000D2D E9E5010000 <1> ID_EX: jmp K26 ; EXIT 2637 <1> ; 2638 <1> NOT_ID: 2639 00000D32 3CE0 <1> cmp al, MC_E0 ; IS THIS THE GENERAL MARKER CODE? 2640 00000D34 750E <1> jne short TEST_E1 2641 00000D36 800D[965B0000]12 <1> or byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND 2642 00000D3D EB10 <1> jmp short EXIT ; THROW AWAY THIS CODE 2643 <1> ; 24/12/2021 2644 00000D3F E9DA010000 <1> jmp K26A 2645 <1> TEST_E1: 2646 00000D44 3CE1 <1> cmp al, MC_E1 ; IS THIS THE PAUSE KEY? 2647 00000D46 750C <1> jne short NOT_HC 2648 00000D48 800D[965B0000]11 <1> or byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND 2649 00000D4F E9CA010000 <1> EXIT: jmp K26A ; THROW AWAY THIS CODE 2650 <1> ; 2651 <1> NOT_HC: 2652 00000D54 247F <1> and al, 07Fh ; TURN OFF THE BREAK BIT 2653 00000D56 F6C702 <1> test bh, LC_E0 ; LAST CODE THE E0 MARKER CODE 2654 00000D59 740D <1> jz short NOT_LC_E0 ; JUMP IF NOT 2655 <1> ; 2656 00000D5B BF[7E5A0000] <1> mov edi, _K6+6 ; IS THIS A SHIFT KEY? 2657 00000D60 AE <1> scasb 2658 <1> ;je K26 ; K16B ; YES, THROW AWAY & RESET FLAG 2659 <1> ; 24/12/2021 2660 00000D61 7458 <1> je short K16B 2661 00000D63 AE <1> scasb 2662 00000D64 756A <1> jne short K16A ; NO, CONTINUE KEY PROCESSING 2663 00000D66 EB53 <1> jmp short K16B ; YES, THROW AWAY & RESET FLAG 2664 <1> ; 24/12/2021 2665 <1> ;jmp K26 2666 <1> ; 2667 <1> NOT_LC_E0: 2668 00000D68 F6C701 <1> test bh, LC_E1 ; LAST CODE THE E1 MARKER CODE? 2669 00000D6B 7425 <1> jz short T_SYS_KEY ; JUMP IF NOT 2670 00000D6D B904000000 <1> mov ecx, 4 ; LENGHT OF SEARCH 2671 00000D72 BF[7C5A0000] <1> mov edi, _K6+4 ; IS THIS AN ALT, CTL, OR SHIFT? 2672 00000D77 F2AE <1> repne scasb ; CHECK IT 2673 00000D79 74D4 <1> je short EXIT ; THROW AWAY IF SO 2674 <1> ; 24/12/2021 2675 <1> ;je K26A 2676 <1> ; 2677 00000D7B 3C45 <1> cmp al, NUM_KEY ; IS IT THE PAUSE KEY? 2678 00000D7D 753C <1> jne short K16B ; NO, THROW AWAY & RESET FLAG 2679 <1> ; 24/12/2021 2680 <1> ;jne K26 2681 00000D7F F6C480 <1> test ah, 80h ; YES, IS IT THE BREAK OF THE KEY? 2682 00000D82 7537 <1> jnz short K16B ; YES, THROW THIS AWAY, TOO 2683 <1> ; 24/12/2021 2684 <1> ;jnz K26 2685 <1> ; 20/02/2015 2686 00000D84 F605[945B0000]08 <1> test byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY? 2687 00000D8B 752E <1> jnz short K16B ; YES, THROW AWAY 2688 <1> ; 24/12/2021 2689 <1> ;jnz K26 2690 00000D8D E9D2020000 <1> jmp K39P ; NO, THIS IS THE REAL PAUSE STATE 2691 <1> ; 2692 <1> ;----- TEST FOR SYSTEM KEY 2693 <1> T_SYS_KEY: 2694 00000D92 3C54 <1> cmp al, SYS_KEY ; IS IT THE SYSTEM KEY? 2695 00000D94 753A <1> jnz short K16A ; CONTINUE IF NOT 2696 <1> ; 2697 00000D96 F6C480 <1> test ah, 80h ; CHECK IF THIS A BREAK CODE 2698 00000D99 7525 <1> jnz short K16C ; DO NOT TOUCH SYSTEM INDICATOR IF TRUE 2699 <1> ; 2700 00000D9B F605[945B0000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 2701 00000DA2 7517 <1> jnz short K16B ; IF YES, DO NOT PROCESS SYSTEM INDICATOR 2702 <1> ;jnz K26 2703 <1> ; 2704 00000DA4 800D[945B0000]04 <1> or byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED 2705 00000DAB B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2706 00000DAD E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2707 <1> ; INTERRUPT-RETURN-NO-EOI 2708 00000DAF B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2709 00000DB1 E82C040000 <1> call SHIP_IT ; EXECUTE ENABLE 2710 <1> ; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!! 2711 <1> ;mov al, 8500h ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY 2712 <1> ;sti ; MAKE SURE INTERRUPTS ENABLED 2713 <1> ;int 15h ; USER INTERRUPT 2714 00000DB6 E96F010000 <1> jmp K27A ; END PROCESSING 2715 <1> ; 2716 00000DBB E957010000 <1> K16B: jmp K26 ; IGNORE SYSTEM KEY 2717 <1> ; 2718 <1> K16C: 2719 00000DC0 8025[945B0000]FB <1> and byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN 2720 00000DC7 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2721 00000DC9 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2722 <1> ; INTERRUPT-RETURN-NO-EOI 2723 <1> ;mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2724 <1> ;call SHIP_IT ; EXECUTE ENABLE 2725 <1> ; 2726 <1> ;mov ax, 8501h ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY 2727 <1> ;sti ; MAKE SURE INTERRUPTS ENABLED 2728 <1> ;int 15h ; USER INTERRUPT 2729 <1> ;jmp K27A ; INGONRE SYSTEM KEY 2730 <1> ; 2731 00000DCB E953010000 <1> jmp K27 ; IGNORE SYSTEM KEY 2732 <1> ; 2733 <1> ;----- TEST FOR SHIFT KEYS 2734 <1> K16A: 2735 00000DD0 8A1D[935B0000] <1> mov bl, [KB_FLAG] ; PUT STATE FLAGS IN BL 2736 00000DD6 BF[785A0000] <1> mov edi, _K6 ; SHIFT KEY TABLE offset 2737 00000DDB B908000000 <1> mov ecx, _K6L ; LENGTH 2738 00000DE0 F2AE <1> repne scasb ; LOOK THROUGH THE TABLE FOR A MATCH 2739 00000DE2 88E0 <1> mov al, ah ; RECOVER SCAN CODE 2740 <1> ;jne K25 ; IF NO MATCH, THEN SHIFT NOT FOUND 2741 <1> ; 24/12/2021 2742 00000DE4 7405 <1> je short K17 2743 00000DE6 E914010000 <1> jmp K25 2744 <1> ; 2745 <1> ;------ SHIFT KEY FOUND 2746 <1> K17: 2747 00000DEB 81EF[795A0000] <1> sub edi, _K6+1 ; ADJUST PTR TO SCAN CODE MATCH 2748 00000DF1 8AA7[805A0000] <1> mov ah, [edi+_K7] ; GET MASK INTO AH 2749 00000DF7 B102 <1> mov cl, 2 ; SETUP COUNT FOR FLAG SHIFTS 2750 00000DF9 A880 <1> test al, 80h ; TEST FOR BREAK KEY 2751 <1> ;jnz K23 ; JUMP OF BREAK 2752 <1> ; 24/12/2021 2753 00000DFB 7405 <1> jz short K17C 2754 00000DFD E999000000 <1> jmp K23 2755 <1> ; 2756 <1> ;----- SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE 2757 <1> K17C: 2758 00000E02 80FC10 <1> cmp ah, SCROLL_SHIFT 2759 00000E05 732C <1> jae short K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY 2760 <1> ; 2761 <1> ;----- PLAIN SHIFT KEY, SET SHIFT ON 2762 00000E07 0825[935B0000] <1> or [KB_FLAG], ah ; TURN ON SHIFT BIT 2763 00000E0D A80C <1> test al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL? 2764 00000E0F 7505 <1> jnz short K17D ; YES, MORE FLAGS TO SET 2765 <1> ;jz K26 ; NO, INTERRUPT RETURN 2766 <1> ; 24/12/2021 2767 00000E11 E901010000 <1> jmp K26 2768 <1> K17D: 2769 00000E16 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF NEW KEYS? 2770 00000E19 740B <1> jz short K17E ; NO, JUMP 2771 00000E1B 0825[965B0000] <1> or [KB_FLAG_3], ah ; SET BITS FOR RIGHT CTRL, ALT 2772 00000E21 E9F1000000 <1> jmp K26 ; INTERRUPT RETURN 2773 <1> K17E: 2774 00000E26 D2EC <1> shr ah, cl ; MOVE FLAG BITS TWO POSITIONS 2775 00000E28 0825[945B0000] <1> or [KB_FLAG_1], ah ; SET BITS FOR LEFT CTRL, ALT 2776 00000E2E E9E4000000 <1> jmp K26 2777 <1> ; 2778 <1> ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT 2779 <1> K18: ; SHIFT-TOGGLE 2780 00000E33 F6C304 <1> test bl, CTL_SHIFT ; CHECK CTL SHIFT STATE 2781 00000E36 7405 <1> jz short K18A ; JUMP IF NOT CTL STATE 2782 <1> ;jnz K25 ; JUMP IF CTL STATE 2783 <1> ; 24/12/2021 2784 00000E38 E9C2000000 <1> jmp K25 2785 <1> K18A: 2786 00000E3D 3C52 <1> cmp al, INS_KEY ; CHECK FOR INSERT KEY 2787 00000E3F 7525 <1> jne short K22 ; JUMP IF NOT INSERT KEY 2788 00000E41 F6C308 <1> test bl, ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT 2789 00000E44 7405 <1> jz short K18B ; JUMP IF NOT ALTERNATE SHIFT 2790 <1> ;jnz K25 ; JUMP IF ALTERNATE SHIFT 2791 <1> ; 24/12/2021 2792 00000E46 E9B4000000 <1> jmp K25 2793 <1> K18B: 2794 00000E4B F6C702 <1> test bh, LC_E0 ;20/02/2015 ; IS THIS NEW INSERT KEY? 2795 00000E4E 7516 <1> jnz short K22 ; YES, THIS ONE'S NEVER A '0' 2796 <1> K19: 2797 00000E50 F6C320 <1> test bl, NUM_STATE ; CHECK FOR BASE STATE 2798 00000E53 750C <1> jnz short K21 ; JUMP IF NUM LOCK IS ON 2799 00000E55 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE 2800 00000E58 740C <1> jz short K22 ; JUMP IF BASE STATE 2801 <1> K20: ; NUMERIC ZERO, NOT INSERT KEY 2802 00000E5A 88C4 <1> mov ah, al ; PUT SCAN CODE BACK IN AH 2803 00000E5C E99E000000 <1> jmp K25 ; NUMERAL '0', STNDRD. PROCESSING 2804 <1> K21: ; MIGHT BE NUMERIC 2805 00000E61 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 2806 00000E64 74F4 <1> jz short K20 ; IS NUMERIC, STD. PROC. 2807 <1> ; 2808 <1> K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT 2809 00000E66 8425[945B0000] <1> test ah, [KB_FLAG_1] ; IS KEY ALREADY DEPRESSED 2810 <1> ;jnz K26 2811 <1> ; 24/12/2021 2812 00000E6C 7405 <1> jz short K22A 2813 00000E6E E9A4000000 <1> jmp K26 ; JUMP IF KEY ALREADY DEPRESSED 2814 <1> K22A: 2815 00000E73 0825[945B0000] <1> or [KB_FLAG_1], ah ; INDICATE THAT THE KEY IS DEPRESSED 2816 00000E79 3025[935B0000] <1> xor [KB_FLAG], ah ; TOGGLE THE SHIFT STATE 2817 <1> ; 2818 <1> ;----- TOGGLE LED IF CAPS, NUM OR SCROLL KEY DEPRESSED 2819 00000E7F F6C470 <1> test ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? 2820 00000E82 7407 <1> jz short K22B ; GO IF NOT 2821 <1> ; 2822 <1> ; 24/12/2021 2823 <1> ;push ax ; SAVE SCAN CODE AND SHIFT MASK 2824 00000E84 50 <1> push eax 2825 00000E85 E8B3030000 <1> call SND_LED ; GO TURN MODE INDICATORS ON 2826 <1> ;pop ax ; RESTORE SCAN CODE 2827 00000E8A 58 <1> pop eax 2828 <1> K22B: 2829 00000E8B 3C52 <1> cmp al, INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY 2830 <1> ;jne K26 ; JUMP IF NOT INSERT KEY 2831 <1> ; 24/12/2021 2832 00000E8D 7405 <1> je short K22C 2833 00000E8F E983000000 <1> jmp K26 ; JUMP IF NOT INSERT KEY 2834 <1> K22C: 2835 00000E94 88C4 <1> mov ah, al ; SCAN CODE IN BOTH HALVES OF AX 2836 00000E96 E999000000 <1> jmp K28 ; FLAGS UPDATED, PROC. FOR BUFFER 2837 <1> ; 2838 <1> ;----- BREAK SHIFT FOUND 2839 <1> K23: ; BREAK-SHIFT-FOUND 2840 00000E9B 80FC10 <1> cmp ah, SCROLL_SHIFT ; IS THIS A TOGGLE KEY 2841 00000E9E F6D4 <1> not ah ; INVERT MASK 2842 00000EA0 7355 <1> jae short K24 ; YES, HANDLE BREAK TOGGLE 2843 00000EA2 2025[935B0000] <1> and [KB_FLAG], ah ; TURN OFF SHIFT BIT 2844 00000EA8 80FCFB <1> cmp ah, ~CTL_SHIFT ; IS THIS ALT OR CTL? 2845 00000EAB 7730 <1> ja short K23D ; NO, ALL DONE 2846 <1> ; 2847 00000EAD F6C702 <1> test bh, LC_E0 ; 2ND ALT OR CTL? 2848 00000EB0 7408 <1> jz short K23A ; NO, HANSLE NORMALLY 2849 00000EB2 2025[965B0000] <1> and [KB_FLAG_3], ah ; RESET BIT FOR RIGHT ALT OR CTL 2850 00000EB8 EB08 <1> jmp short K23B ; CONTINUE 2851 <1> K23A: 2852 00000EBA D2FC <1> sar ah, cl ; MOVE THE MASK BIT TWO POSITIONS 2853 00000EBC 2025[945B0000] <1> and [KB_FLAG_1], ah ; RESET BIT FOR LEFT ALT AND CTL 2854 <1> K23B: 2855 00000EC2 88C4 <1> mov ah, al ; SAVE SCAN CODE 2856 00000EC4 A0[965B0000] <1> mov al, [KB_FLAG_3] ; GET RIGHT ALT & CTRL FLAGS 2857 00000EC9 D2E8 <1> shr al, cl ; MOVE TO BITS 1 & 0 2858 00000ECB 0A05[945B0000] <1> or al, [KB_FLAG_1] ; PUT IN LEFT ALÞT & CTL FLAGS 2859 00000ED1 D2E0 <1> shl al, cl ; MOVE BACK TO BITS 3 & 2 2860 00000ED3 240C <1> and al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE 2861 00000ED5 0805[935B0000] <1> or [KB_FLAG], al ; PUT RESULT IN THE REAL FLAGS 2862 00000EDB 88E0 <1> mov al, ah 2863 <1> K23D: 2864 00000EDD 3CB8 <1> cmp al, ALT_KEY+80h ; IS THIS ALTERNATE SHIFT RELEASE 2865 00000EDF 7536 <1> jne short K26 ; INTERRUPT RETURN 2866 <1> ; 2867 <1> ;----- ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER 2868 00000EE1 A0[975B0000] <1> mov al, [ALT_INPUT] 2869 00000EE6 B400 <1> mov ah, 0 ; SCAN CODE OF 0 2870 00000EE8 8825[975B0000] <1> mov [ALT_INPUT], ah ; ZERO OUT THE FIELD 2871 00000EEE 3C00 <1> cmp al, 0 ; WAS THE INPUT = 0? 2872 00000EF0 7425 <1> je short K26 ; INTERRUPT_RETURN 2873 00000EF2 E9B4020000 <1> jmp K61 ; IT WASN'T, SO PUT IN BUFFER 2874 <1> ; 2875 <1> K24: ; BREAK-TOGGLE 2876 00000EF7 2025[945B0000] <1> and [KB_FLAG_1], ah ; INDICATE NO LONGER DEPRESSED 2877 00000EFD EB18 <1> jmp short K26 ; INTERRUPT_RETURN 2878 <1> ; 2879 <1> ;----- TEST FOR HOLD STATE 2880 <1> ; AL, AH = SCAN CODE 2881 <1> K25: ; NO-SHIFT-FOUND 2882 00000EFF 3C80 <1> cmp al, 80h ; TEST FOR BREAK KEY 2883 00000F01 7314 <1> jae short K26 ; NOTHING FOR BREAK CHARS FROM HERE ON 2884 00000F03 F605[945B0000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE 2885 00000F0A 7428 <1> jz short K28 ; BRANCH AROUND TEST IF NOT 2886 00000F0C 3C45 <1> cmp al, NUM_KEY 2887 00000F0E 7407 <1> je short K26 ; CAN'T END HOLD ON NUM_LOCK 2888 00000F10 8025[945B0000]F7 <1> and byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT 2889 <1> ; 2890 <1> K26: 2891 00000F17 8025[965B0000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 2892 <1> K26A: ; INTERRUPT-RETURN 2893 00000F1E FA <1> cli ; TURN OFF INTERRUPTS 2894 00000F1F B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2895 00000F21 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2896 <1> K27: ; INTERRUPT-RETURN-NO-EOI 2897 00000F23 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2898 00000F25 E8B8020000 <1> call SHIP_IT ; EXECUTE ENABLE 2899 <1> K27A: 2900 00000F2A FA <1> cli ; DISABLE INTERRUPTS 2901 00000F2B 07 <1> pop es ; RESTORE REGISTERS 2902 00000F2C 1F <1> pop ds 2903 00000F2D 5F <1> pop edi 2904 00000F2E 5E <1> pop esi 2905 00000F2F 5A <1> pop edx 2906 00000F30 59 <1> pop ecx 2907 00000F31 5B <1> pop ebx 2908 00000F32 58 <1> pop eax 2909 <1> ;pop ebp 2910 00000F33 CF <1> iret ; RETURN 2911 <1> 2912 <1> ;----- NOT IN HOLD STATE 2913 <1> K28: ; NO-HOLD-STATE 2914 00000F34 3C58 <1> cmp al, 88 ; TEST FOR OUT-OF-RANGE SCAN CODES 2915 00000F36 77DF <1> ja short K26 ; IGNORE IF OUT-OF-RANGE 2916 <1> ; 2917 00000F38 F6C308 <1> test bl, ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT 2918 00000F3B 740E <1> jz short K28A ; IF NOT ALTERNATE 2919 <1> ; 24/12/2021 2920 <1> ;jz K38 2921 <1> ; 2922 00000F3D F6C710 <1> test bh, KBX ; IS THIS THE ENCHANCED KEYBOARD? 2923 00000F40 740E <1> jz short K29 ; NO, ALT STATE IS REAL 2924 <1> ; 28/02/2015 2925 00000F42 F605[945B0000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN? 2926 00000F49 7405 <1> jz short K29 ; NO, ALT STATE IS REAL 2927 <1> ; 24/12/2021 2928 <1> ;jnz K38 ; YES, THIS IS PHONY ALT STATE 2929 <1> ; ; DUE TO PRESSING SYSREQ 2930 00000F4B E9CD000000 <1> K28A: jmp K38 2931 <1> ; 2932 <1> ;----- TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) 2933 <1> K29: ; TEST-RESET 2934 00000F50 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO? 2935 00000F53 740B <1> jz short K31 ; NO_RESET 2936 00000F55 3C53 <1> cmp al, DEL_KEY ; CTL-ALT STATE, TEST FOR DELETE KEY 2937 00000F57 7507 <1> jne short K31 ; NO_RESET, IGNORE 2938 <1> ; 2939 <1> ;----- CTL-ALT-DEL HAS BEEN FOUND 2940 <1> ; 26/08/2014 2941 <1> cpu_reset: 2942 <1> ; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN) 2943 <1> ; Send FEh (system reset command) to the keyboard controller. 2944 00000F59 B0FE <1> mov al, SHUT_CMD ; SHUTDOWN COMMAND 2945 00000F5B E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROL PORT 2946 <1> khere: 2947 00000F5D F4 <1> hlt ; WAIT FOR 80286 RESET 2948 00000F5E EBFD <1> jmp short khere ; INSURE HALT 2949 <1> 2950 <1> ; 2951 <1> ;----- IN ALTERNATE SHIFT, RESET NOT FOUND 2952 <1> K31: ; NO-RESET 2953 00000F60 3C39 <1> cmp al, 57 ; TEST FOR SPACE KEY 2954 00000F62 7507 <1> jne short K311 ; NOT THERE 2955 00000F64 B020 <1> mov al, ' ' ; SET SPACE CHAR 2956 00000F66 E932020000 <1> jmp K57 ; BUFFER_FILL 2957 <1> K311: 2958 00000F6B 3C0F <1> cmp al, 15 ; TEST FOR TAB KEY 2959 00000F6D 7509 <1> jne short K312 ; NOT THERE 2960 00000F6F 66B800A5 <1> mov ax, 0A500h ; SET SPECIAL CODE FOR ALT-TAB 2961 00000F73 E925020000 <1> jmp K57 ; BUFFER_FILL 2962 <1> K312: 2963 00000F78 3C4A <1> cmp al, 74 ; TEST FOR KEY PAD - 2964 00000F7A 7471 <1> je short K37B ; GO PROCESS 2965 00000F7C 3C4E <1> cmp al, 78 ; TEST FOR KEY PAD + 2966 00000F7E 746D <1> je short K37B ; GO PROCESS 2967 <1> ; 2968 <1> ;----- LOOK FOR KEY PAD ENTRY 2969 <1> K32: ; ALT-KEY-PAD 2970 00000F80 BF[545A0000] <1> mov edi, K30 ; ALT-INPUT-TABLE offset 2971 00000F85 B90A000000 <1> mov ecx, 10 ; LOOK FOR ENTRY USING KEYPAD 2972 00000F8A F2AE <1> repne scasb ; LOOK FOR MATCH 2973 00000F8C 7523 <1> jne short K33 ; NO_ALT_KEYPAD 2974 00000F8E F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF THE NEW KEYS? 2975 <1> ;jnz short K37C ; YES, JUMP, NOT NUMPAD KEY 2976 <1> ; 24/12/2021 2977 00000F91 751C <1> jnz short K32B 2978 00000F93 81EF[555A0000] <1> sub edi, K30+1 ; DI NOW HAS ENTRY VALUE 2979 00000F99 A0[975B0000] <1> mov al, [ALT_INPUT] ; GET THE CURRENT BYTE 2980 00000F9E B40A <1> mov ah, 10 ; MULTIPLY BY 10 2981 00000FA0 F6E4 <1> mul ah 2982 00000FA2 6601F8 <1> add ax, di ; ADD IN THE LATEST ENTRY 2983 00000FA5 A2[975B0000] <1> mov [ALT_INPUT], al ; STORE IT AWAY 2984 <1> K32A: 2985 00000FAA E968FFFFFF <1> jmp K26 ; THROW AWAY THAT KEYSTROKE 2986 <1> K32B: 2987 <1> ; 24/12/2021 2988 00000FAF EB66 <1> jmp K37C 2989 <1> ; 2990 <1> ;----- LOOK FOR SUPERSHIFT ENTRY 2991 <1> K33: ; NO-ALT-KEYPAD 2992 00000FB1 C605[975B0000]00 <1> mov byte [ALT_INPUT], 0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT 2993 00000FB8 B91A000000 <1> mov ecx, 26 ; (DI),(ES) ALREADY POINTING 2994 00000FBD F2AE <1> repne scasb ; LOOK FOR MATCH IN ALPHABET 2995 00000FBF 744F <1> je short K37A ; MATCH FOUND, GO FILLL THE BUFFER 2996 <1> ; 2997 <1> ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT 2998 <1> K34: ; ALT-TOP-ROW 2999 00000FC1 3C02 <1> cmp al, 2 ; KEY WITH '1' ON IT 3000 00000FC3 7228 <1> jb short K37B ; MUST BE ESCAPE 3001 00000FC5 3C0D <1> cmp al, 13 ; IS IT IN THE REGION 3002 00000FC7 7705 <1> ja short K35 ; NO, ALT SOMETHING ELSE 3003 00000FC9 80C476 <1> add ah, 118 ; CONVERT PSEUDO SCAN CODE TO RANGE 3004 00000FCC EB42 <1> jmp short K37A ; GO FILL THE BUFFER 3005 <1> ; 3006 <1> ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES 3007 <1> K35: ; ALT-FUNCTION 3008 00000FCE 3C57 <1> cmp al, F11_M ; IS IT F11? 3009 00000FD0 7209 <1> jb short K35A ; 20/02/2015 ; NO, BRANCH 3010 00000FD2 3C58 <1> cmp al, F12_M ; IS IT F12? 3011 00000FD4 7705 <1> ja short K35A ; 20/02/2015 ; NO, BRANCH 3012 00000FD6 80C434 <1> add ah, 52 ; CONVERT TO PSEUDO SCAN CODE 3013 00000FD9 EB35 <1> jmp short K37A ; GO FILL THE BUFFER 3014 <1> K35A: 3015 00000FDB F6C702 <1> test bh, LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS? 3016 00000FDE 7425 <1> jz short K37 ; NO, JUMP 3017 00000FE0 3C1C <1> cmp al, 28 ; TEST FOR KEYPAD ENTER 3018 00000FE2 7510 <1> jne short K35B ; NOT THERE 3019 00000FE4 66B800A6 <1> mov ax, 0A600h ; SPECIAL CODE 3020 00000FE8 E9B0010000 <1> jmp K57 ; BUFFER FILL 3021 <1> K37B: 3022 00000FED B0F0 <1> mov al, 0F0h ; USE SPECIAL ASCII CODE 3023 00000FEF E9A9010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3024 <1> K35B: 3025 00000FF4 3C53 <1> cmp al, 83 ; TEST FOR DELETE KEY 3026 00000FF6 741F <1> je short K37C ; HANDLE WITH OTHER EDIT KEYS 3027 00000FF8 3C35 <1> cmp al, 53 ; TEST FOR KEYPAD / 3028 00000FFA 75AE <1> jne short K32A ; NOT THERE, NO OTHER E0 SPECIALS 3029 <1> ; 24/12/2021 3030 <1> ;jne K26 3031 00000FFC 66B800A4 <1> mov ax, 0A400h ; SPECIAL CODE 3032 00001000 E998010000 <1> jmp K57 ; BUFFER FILL 3033 <1> K37: 3034 00001005 3C3B <1> cmp al, 59 ; TEST FOR FUNCTION KEYS (F1) 3035 00001007 72E4 <1> jb short K37B ; NO FN, HANDLE W/OTHER EXTENDED 3036 00001009 3C44 <1> cmp al, 68 ; IN KEYPAD REGION? 3037 0000100B 779D <1> ja short K32A ; IF SO, IGNORE 3038 <1> ; 13/06/2022 3039 <1> ;ja K26 3040 0000100D 80C42D <1> add ah, 45 ; CONVERT TO PSEUDO SCAN CODE 3041 <1> K37A: 3042 00001010 B000 <1> mov al, 0 ; ASCII CODE OF ZERO 3043 00001012 E986010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3044 <1> K37C: 3045 00001017 0450 <1> add al, 80 ; CONVERT SCAN CODE (EDIT KEYS) 3046 00001019 88C4 <1> mov ah, al ; (SCAN CODE NOT IN AH FOR INSERT) 3047 0000101B EBF3 <1> jmp short K37A ; PUT IT IN THE BUFFER 3048 <1> ; 3049 <1> ;----- NOT IN ALTERNATE SHIFT 3050 <1> K38: ; NOT-ALT-SHIFT 3051 <1> ; BL STILL HAS SHIFT FLAGS 3052 0000101D F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT? 3053 00001020 7505 <1> jnz short K38A ; YES, START PROCESSING 3054 <1> ;jz K44 ; NOT-CTL-SHIFT 3055 <1> ; 24/12/2021 3056 00001022 E9AB000000 <1> jmp K44 3057 <1> ; 3058 <1> ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS 3059 <1> ;----- TEST FOR BREAK 3060 <1> K38A: 3061 00001027 3C46 <1> cmp al, SCROLL_KEY ; TEST FOR BREAK 3062 00001029 7530 <1> jne short K39 ; JUMP, NO-BREAK 3063 0000102B F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3064 0000102E 7405 <1> jz short K38B ; NO, BREAK IS VALID 3065 00001030 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3066 00001033 7426 <1> jz short K39 ; NO-BREAK, TEST FOR PAUSE 3067 <1> K38B: 3068 00001035 8B1D[A05B0000] <1> mov ebx, [BUFFER_HEAD] ; RESET BUFFER TO EMPTY 3069 0000103B 891D[A45B0000] <1> mov [BUFFER_TAIL], ebx 3070 00001041 C605[925B0000]80 <1> mov byte [BIOS_BREAK], 80h ; TURN ON BIOS_BREAK BIT 3071 <1> ; 3072 <1> ;----- ENABLE KEYBOARD 3073 00001048 B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3074 0000104A E893010000 <1> call SHIP_IT ; EXECUTE ENABLE 3075 <1> ; 3076 <1> ; CTRL+BREAK code here !!! 3077 <1> ;int 1Bh ; BREAK INTERRUPT VECTOR 3078 <1> ; 17/10/2015 3079 0000104F E889190000 <1> call ctrlbrk ; control+break subroutine 3080 <1> ; 3081 <1> ;sub ax, ax ; PUT OUT DUMMY CHARACTER 3082 <1> ; 24/12/2021 3083 00001054 29C0 <1> sub eax, eax 3084 00001056 E942010000 <1> jmp K57 ; BUFFER_FILL 3085 <1> ; 3086 <1> ;----- TEST FOR PAUSE 3087 <1> K39: ; NO_BREAK 3088 0000105B F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3089 0000105E 7537 <1> jnz short K41 ; YES, THEN THIS CAN'T BE PAUSE 3090 00001060 3C45 <1> cmp al, NUM_KEY ; LOOK FOR PAUSE KEY 3091 00001062 7533 <1> jne short K41 ; NO-PAUSE 3092 <1> K39P: 3093 00001064 800D[945B0000]08 <1> or byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG 3094 <1> ; 3095 <1> ;----- ENABLE KEYBOARD 3096 0000106B B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3097 0000106D E870010000 <1> call SHIP_IT ; EXECUTE ENABLE 3098 <1> K39A: 3099 00001072 B020 <1> mov al, EOI ; END OF INTERRUPT TO CONTROL PORT 3100 00001074 E620 <1> out 20h, al ;out INTA00, al ; ALLOW FURTHER KEYSTROKE INTERRUPTS 3101 <1> ; 3102 <1> ;----- DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON 3103 00001076 803D[905B0000]07 <1> cmp byte [CRT_MODE], 7 ; IS THIS BLACK AND WHITE CARD 3104 0000107D 740A <1> je short K40 ; YES, NOTHING TO DO 3105 0000107F 66BAD803 <1> mov dx, 03D8h ; PORT FOR COLOR CARD 3106 00001083 A0[915B0000] <1> mov al, [CRT_MODE_SET] ; GET THE VALUE OF THE CURRENT MODE 3107 00001088 EE <1> out dx, al ; SET THE CRT MODE, SO THAT CRT IS ON 3108 <1> ; 3109 <1> K40: ; PAUSE-LOOP 3110 00001089 F605[945B0000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG 3111 00001090 75F7 <1> jnz short K40 ; LOOP UNTIL FLAG TURNED OFF 3112 <1> ; 3113 00001092 E98CFEFFFF <1> jmp K27 ; INTERRUPT_RETURN_NO_EOI 3114 <1> ; 3115 <1> ;----- TEST SPECIAL CASE KEY 55 3116 <1> K41: ; NO-PAUSE 3117 00001097 3C37 <1> cmp al, 55 ; TEST FOR */PRTSC KEY 3118 00001099 7513 <1> jne short K42 ; NOT-KEY-55 3119 0000109B F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3120 0000109E 7405 <1> jz short K41A ; NO, CTL-PRTSC IS VALID 3121 000010A0 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3122 000010A3 7421 <1> jz short K42B ; NO, TRANSLATE TO A FUNCTION 3123 <1> K41A: 3124 000010A5 66B80072 <1> mov ax, 114*256 ; START/STOP PRINTING SWITCH 3125 000010A9 E9EF000000 <1> jmp K57 ; BUFFER_FILL 3126 <1> ; 3127 <1> ;----- SET UP TO TRANSLATE CONTROL SHIFT 3128 <1> K42: ; NOT-KEY-55 3129 000010AE 3C0F <1> cmp al, 15 ; IS IT THE TAB KEY? 3130 000010B0 7414 <1> je short K42B ; YES, XLATE TO FUNCTION CODE 3131 000010B2 3C35 <1> cmp al, 53 ; IS IT THE / KEY? 3132 000010B4 750E <1> jne short K42A ; NO, NO MORE SPECIAL CASES 3133 000010B6 F6C702 <1> test bh, LC_E0 ; YES, IS IT FROM THE KEY PAD? 3134 000010B9 7409 <1> jz short K42A ; NO, JUST TRANSLATE 3135 000010BB 66B80095 <1> mov ax, 9500h ; YES, SPECIAL CODE FOR THIS ONE 3136 000010BF E9D9000000 <1> jmp K57 ; BUFFER FILL 3137 <1> K42A: 3138 <1> ;mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3139 000010C4 3C3B <1> cmp al, 59 ; IS IT IN CHARACTER TABLE? 3140 <1> ;jb short K45F ; YES, GO TRANSLATE CHAR 3141 <1> ;;jb K56 ; 20/02/2015 3142 <1> ;;jmp K64 ; 20/02/2015 3143 <1> K42B: 3144 000010C6 BB[885A0000] <1> mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3145 <1> ;;jmp K64 3146 <1> ;jb K56 ;; 20/02/2015 3147 <1> ; 24/12/2021 3148 000010CB 7267 <1> jb short K45F 3149 000010CD E9B9000000 <1> jmp K64 3150 <1> ; 3151 <1> ;----- NOT IN CONTROL SHIFT 3152 <1> K44: ; NOT-CTL-SHIFT 3153 000010D2 3C37 <1> cmp al, 55 ; PRINT SCREEN KEY? 3154 000010D4 7528 <1> jne short K45 ; NOT PRINT SCREEN 3155 000010D6 F6C710 <1> test bh, KBX ; IS THIS ENHANCED KEYBOARD? 3156 000010D9 7407 <1> jz short K44A ; NO, TEST FOR SHIFT STATE 3157 000010DB F6C702 <1> test bh, LC_E0 ; YES, LAST CODE A MARKER? 3158 000010DE 7507 <1> jnz short K44B ; YES, IS PRINT SCREEN 3159 000010E0 EB41 <1> jmp short K45C ; NO, TRANSLATE TO '*' CHARACTER 3160 <1> K44A: 3161 000010E2 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN? 3162 000010E5 743C <1> jz short K45C ; NO, TRANSLATE TO '*' CHARACTER 3163 <1> ; 3164 <1> ;----- ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION 3165 <1> K44B: 3166 000010E7 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3167 000010E9 E8F4000000 <1> call SHIP_IT ; EXECUTE ENABLE 3168 000010EE B020 <1> mov al, EOI ; END OF CURRENT INTERRUPT 3169 000010F0 E620 <1> out 20h, al ;out INTA00, al ; SO FURTHER THINGS CAN HAPPEN 3170 <1> ; Print Screen !!! ; ISSUE PRINT SCREEN INTERRUPT (INT 05h) 3171 <1> ;push bp ; SAVE POINTER 3172 <1> ;int 05h ; ISSUE PRINT SCREEN INTERRUPT 3173 <1> ;pop bp ; RESTORE POINTER 3174 000010F2 8025[965B0000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS 3175 000010F9 E925FEFFFF <1> jmp K27 ; GO BACK WITHOUT EOI OCCURRING 3176 <1> ; 3177 <1> ;----- HANDLE IN-CORE KEYS 3178 <1> K45: ; NOT-PRINT-SCREEN 3179 000010FE 3C3A <1> cmp al, 58 ; TEST FOR IN-CORE AREA 3180 00001100 7734 <1> ja short K46 ; JUMP IF NOT 3181 00001102 3C35 <1> cmp al, 53 ; IS THIS THE '/' KEY? 3182 00001104 7505 <1> jne short K45A ; NO, JUMP 3183 00001106 F6C702 <1> test bh, LC_E0 ; WAS THE LAST CODE THE MARKER? 3184 00001109 7518 <1> jnz short K45C ; YES, TRANSLATE TO CHARACTER 3185 <1> K45A: 3186 0000110B B91A000000 <1> mov ecx, 26 ; LENGHT OF SEARCH 3187 00001110 BF[5E5A0000] <1> mov edi, K30+10 ; POINT TO TABLE OF A-Z CHARS 3188 00001115 F2AE <1> repne scasb ; IS THIS A LETTER KEY? 3189 <1> ; 20/02/2015 3190 00001117 7505 <1> jne short K45B ; NO, SYMBOL KEY 3191 <1> ; 3192 00001119 F6C340 <1> test bl, CAPS_STATE ; ARE WE IN CAPS_LOCK? 3193 0000111C 750C <1> jnz short K45D ; TEST FOR SURE 3194 <1> K45B: 3195 0000111E F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3196 00001121 750C <1> jnz short K45E ; YES, UPPERCASE 3197 <1> ; NO, LOWERCASE 3198 <1> K45C: 3199 00001123 BB[E05A0000] <1> mov ebx, K10 ; TRANSLATE TO LOWERCASE LETTERS 3200 00001128 EB51 <1> jmp short K56 3201 <1> K45D: ; ALMOST-CAPS-STATE 3202 0000112A F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO? 3203 0000112D 75F4 <1> jnz short K45C ; SHIFTED TEMP OUT OF CAPS STATE 3204 <1> K45E: 3205 0000112F BB[385B0000] <1> mov ebx, K11 ; TRANSLATE TO UPPER CASE LETTERS 3206 00001134 EB45 <1> K45F: jmp short K56 3207 <1> ; 3208 <1> ;----- TEST FOR KEYS F1 - F10 3209 <1> K46: ; NOT IN-CORE AREA 3210 00001136 3C44 <1> cmp al, 68 ; TEST FOR F1 - F10 3211 <1> ;ja short K47 ; JUMP IF NOT 3212 <1> ;jmp short K53 ; YES, GO DO FN KEY PROCESS 3213 00001138 7635 <1> jna short K53 3214 <1> ; 3215 <1> ;----- HANDLE THE NUMERIC PAD KEYS 3216 <1> K47: ; NOT F1 - F10 3217 0000113A 3C53 <1> cmp al, 83 ; TEST NUMPAD KEYS 3218 0000113C 772D <1> ja short K52 ; JUMP IF NOT 3219 <1> ; 3220 <1> ;----- KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION 3221 <1> K48: 3222 0000113E 3C4A <1> cmp al, 74 ; SPECIAL CASE FOR MINUS 3223 00001140 74ED <1> je short K45E ; GO TRANSLATE 3224 00001142 3C4E <1> cmp al, 78 ; SPECIAL CASE FOR PLUS 3225 00001144 74E9 <1> je short K45E ; GO TRANSLATE 3226 00001146 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OFTHE NEW KEYS? 3227 00001149 750A <1> jnz short K49 ; YES, TRANSLATE TO BASE STATE 3228 <1> ; 3229 0000114B F6C320 <1> test bl, NUM_STATE ; ARE WE IN NUM LOCK 3230 0000114E 7514 <1> jnz short K50 ; TEST FOR SURE 3231 00001150 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3232 <1> ;jnz short K51 ; IF SHIFTED, REALLY NUM STATE 3233 00001153 75DA <1> jnz short K45E 3234 <1> ; 3235 <1> ;----- BASE CASE FOR KEYPAD 3236 <1> K49: 3237 00001155 3C4C <1> cmp al, 76 ; SPECIAL CASE FOR BASE STATE 5 3238 00001157 7504 <1> jne short K49A ; CONTINUE IF NOT KEYPAD 5 3239 00001159 B0F0 <1> mov al, 0F0h ; SPECIAL ASCII CODE 3240 0000115B EB40 <1> jmp short K57 ; BUFFER FILL 3241 <1> K49A: 3242 0000115D BB[E05A0000] <1> mov ebx, K10 ; BASE CASE TABLE 3243 00001162 EB27 <1> jmp short K64 ; CONVERT TO PSEUDO SCAN 3244 <1> ; 3245 <1> ;----- MIGHT BE NUM LOCK, TEST SHIFT STATUS 3246 <1> K50: ; ALMOST-NUM-STATE 3247 00001164 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3248 00001167 75EC <1> jnz short K49 ; SHIFTED TEMP OUT OF NUM STATE 3249 00001169 EBC4 <1> K51: jmp short K45E ; REALLY NUM STATE 3250 <1> ; 3251 <1> ;----- TEST FOR THE NEW KEYS ON WT KEYBOARDS 3252 <1> K52: ; NOT A NUMPAD KEY 3253 0000116B 3C56 <1> cmp al, 86 ; IS IT THE NEW WT KEY? 3254 <1> ;jne short K53 ; JUMP IF NOT 3255 <1> ;jmp short K45B ; HANDLE WITH REST OF LETTER KEYS 3256 0000116D 74AF <1> je short K45B 3257 <1> ; 3258 <1> ;----- MUST BE F11 OR F12 3259 <1> K53: ; F1 - F10 COME HERE, TOO 3260 0000116F F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE 3261 00001172 74E1 <1> jz short K49 ; JUMP, LOWER CASE PSEUDO SC'S 3262 <1> ; 20/02/2015 3263 00001174 BB[385B0000] <1> mov ebx, K11 ; UPPER CASE PSEUDO SCAN CODES 3264 00001179 EB10 <1> jmp short K64 ; TRANSLATE SCAN 3265 <1> ; 3266 <1> ;----- TRANSLATE THE CHARACTER 3267 <1> K56: ; TRANSLATE-CHAR 3268 0000117B FEC8 <1> dec al ; CONVERT ORIGIN 3269 0000117D D7 <1> xlat ; CONVERT THE SCAN CODE TO ASCII 3270 0000117E F605[965B0000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3271 00001185 7416 <1> jz short K57 ; NO, GO FILL BUFFER 3272 00001187 B4E0 <1> mov ah, MC_E0 ; YES, PUT SPECIAL MARKER IN AH 3273 00001189 EB12 <1> jmp short K57 ; PUT IT INTO THE BUFFER 3274 <1> ; 3275 <1> ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES 3276 <1> K64: ; TRANSLATE-SCAN-ORGD 3277 0000118B FEC8 <1> dec al ; CONVERT ORIGIN 3278 0000118D D7 <1> xlat ; CTL TABLE SCAN 3279 0000118E 88C4 <1> mov ah, al ; PUT VALUE INTO AH 3280 00001190 B000 <1> mov al, 0 ; ZERO ASCII CODE 3281 00001192 F605[965B0000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3282 00001199 7402 <1> jz short K57 ; NO, GO FILL BUFFER 3283 0000119B B0E0 <1> mov al, MC_E0 ; YES, PUT SPECIAL MARKER IN AL 3284 <1> ; 3285 <1> ;----- PUT CHARACTER INTO BUFFER 3286 <1> K57: ; BUFFER_FILL 3287 0000119D 3CFF <1> cmp al, -1 ; IS THIS AN IGNORE CHAR 3288 0000119F 7405 <1> je short K59 ; YES, DO NOTHING WITH IT 3289 <1> ; 24/12/2021 3290 <1> ;je K26 ; YES, DO NOTHING WITH IT 3291 000011A1 80FCFF <1> cmp ah, -1 ; LOOK FOR -1 PSEUDO SCAN 3292 <1> ; 24/12/2021 3293 000011A4 7505 <1> jne short K61 ; NEAR_INTERRUPT_RETURN 3294 <1> ;je K26 ; INTERRUPT_RETURN 3295 <1> K59: ; NEAR_INTERRUPT_RETURN 3296 000011A6 E96CFDFFFF <1> jmp K26 ; INTERRUPT_RETURN 3297 <1> K61: ; NOT-CAPS-STATE 3298 000011AB 8B1D[A45B0000] <1> mov ebx, [BUFFER_TAIL] ; GET THE END POINTER TO THE BUFFER 3299 000011B1 89DE <1> mov esi, ebx ; SAVE THE VALUE 3300 000011B3 E8AEFAFFFF <1> call _K4 ; ADVANCE THE TAIL 3301 000011B8 3B1D[A05B0000] <1> cmp ebx, [BUFFER_HEAD] ; HAS THE BUFFER WRAPPED AROUND 3302 000011BE 740E <1> je short K62 ; BUFFER_FULL_BEEP 3303 000011C0 668906 <1> mov [esi], ax ; STORE THE VALUE 3304 000011C3 891D[A45B0000] <1> mov [BUFFER_TAIL], ebx ; MOVE THE POINTER UP 3305 000011C9 E949FDFFFF <1> jmp K26 3306 <1> ;;cli ; TURN OFF INTERRUPTS 3307 <1> ;;mov al, EOI ; END OF INTERRUPT COMMAND 3308 <1> ;;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3309 <1> ;mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3310 <1> ;call SHIP_IT ; EXECUTE ENABLE 3311 <1> ;mov ax, 9102h ; MOVE IN POST CODE & TYPE 3312 <1> ;int 15h ; PERFORM OTHER FUNCTION 3313 <1> ;;and byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3314 <1> ;jmp K27A ; INTERRUPT_RETURN 3315 <1> ;;jmp K27 3316 <1> ; 3317 <1> ;----- BUFFER IS FULL SOUND THE BEEPER 3318 <1> K62: 3319 000011CE B020 <1> mov al, EOI ; ENABLE INTERRUPT CONTROLLER CHIP 3320 000011D0 E620 <1> out INTA00, al 3321 000011D2 66B9A602 <1> mov cx, 678 ; DIVISOR FOR 1760 HZ 3322 000011D6 B304 <1> mov bl, 4 ; SHORT BEEP COUNT (1/16 + 1/64 DELAY) 3323 000011D8 E883010000 <1> call beep ; GO TO COMMON BEEP HANDLER 3324 000011DD E941FDFFFF <1> jmp K27 ; EXIT 3325 <1> 3326 <1> SHIP_IT: 3327 <1> ;--------------------------------------------------------------------------------- 3328 <1> ; SHIP_IT 3329 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3330 <1> ; TO THE KEYBOARD CONTROLLER. 3331 <1> ;--------------------------------------------------------------------------------- 3332 <1> ; 3333 <1> ;push ax ; SAVE DATA TO SEND 3334 <1> ; 24/12/2021 3335 000011E2 50 <1> push eax 3336 <1> ;----- WAIT FOR COMMAND TO ACCEPTED 3337 000011E3 FA <1> cli ; DISABLE INTERRUPTS TILL DATA SENT 3338 <1> ; xor ecx, ecx ; CLEAR TIMEOUT COUNTER 3339 000011E4 B900000100 <1> mov ecx, 10000h 3340 <1> S10: 3341 000011E9 E464 <1> in al, STATUS_PORT ; READ KEYBOARD CONTROLLER STATUS 3342 000011EB A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ITS INPUT BUFFER BUSY 3343 000011ED E0FA <1> loopnz S10 ; WAIT FOR COMMAND TO BE ACCEPTED 3344 <1> 3345 <1> ;pop ax ; GET DATA TO SEND 3346 <1> ; 24/12/2021 3347 000011EF 58 <1> pop eax 3348 000011F0 E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROLLER 3349 000011F2 FB <1> sti ; ENABLE INTERRUPTS AGAIN 3350 000011F3 C3 <1> retn ; RETURN TO CALLER 3351 <1> 3352 <1> SND_DATA: 3353 <1> ; --------------------------------------------------------------------------------- 3354 <1> ; SND_DATA 3355 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3356 <1> ; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO 3357 <1> ; HANDLES ANY RETRIES IF REQUIRED 3358 <1> ; --------------------------------------------------------------------------------- 3359 <1> ; 3360 <1> ;push ax ; SAVE REGISTERS 3361 <1> ;push bx 3362 <1> ; 24/12/2021 3363 000011F4 50 <1> push eax 3364 000011F5 53 <1> push ebx 3365 000011F6 51 <1> push ecx 3366 000011F7 88C7 <1> mov bh, al ; SAVE TRANSMITTED BYTE FOR RETRIES 3367 000011F9 B303 <1> mov bl, 3 ; LOAD RETRY COUNT 3368 <1> SD0: 3369 000011FB FA <1> cli ; DISABLE INTERRUPTS 3370 000011FC 8025[955B0000]CF <1> and byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS 3371 <1> ; 3372 <1> ;----- WAIT FOR COMMAND TO BE ACCEPTED 3373 00001203 B900000100 <1> mov ecx, 10000h ; MAXIMUM WAIT COUNT 3374 <1> SD5: 3375 00001208 E464 <1> in al, STATUS_PORT ; READ KEYBOARD PROCESSOR STATUS PORT 3376 0000120A A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ANY PENDING COMMAND 3377 0000120C E0FA <1> loopnz SD5 ; WAIT FOR COMMAND TO BE ACCEPTED 3378 <1> ; 3379 0000120E 88F8 <1> mov al, bh ; REESTABLISH BYTE TO TRANSMIT 3380 00001210 E660 <1> out PORT_A, al ; SEND BYTE 3381 00001212 FB <1> sti ; ENABLE INTERRUPTS 3382 <1> ;mov cx, 01A00h ; LOAD COUNT FOR 10 ms+ 3383 00001213 B9FFFF0000 <1> mov ecx, 0FFFFh 3384 <1> SD1: 3385 00001218 F605[955B0000]30 <1> test byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET 3386 0000121F 750F <1> jnz short SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS 3387 00001221 E2F5 <1> loop SD1 ; OTHERWISE WAIT 3388 <1> SD2: 3389 00001223 FECB <1> dec bl ; DECREMENT RETRY COUNT 3390 00001225 75D4 <1> jnz short SD0 ; RETRY TRANSMISSION 3391 00001227 800D[955B0000]80 <1> or byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG 3392 0000122E EB09 <1> jmp short SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION 3393 <1> SD3: 3394 00001230 F605[955B0000]10 <1> test byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE 3395 00001237 74EA <1> jz short SD2 ; IF NOT, GO RESEND 3396 <1> SD4: 3397 00001239 59 <1> pop ecx ; RESTORE REGISTERS 3398 <1> ;pop bx 3399 <1> ;pop ax 3400 <1> ; 24/12/2021 3401 0000123A 5B <1> pop ebx 3402 0000123B 58 <1> pop eax 3403 0000123C C3 <1> retn ; RETURN, GOOD TRANSMISSION 3404 <1> 3405 <1> SND_LED: 3406 <1> ; --------------------------------------------------------------------------------- 3407 <1> ; SND_LED 3408 <1> ; THIS ROUTINES TURNS ON THE MODE INDICATORS. 3409 <1> ; 3410 <1> ;---------------------------------------------------------------------------------- 3411 <1> ; 3412 0000123D FA <1> cli ; TURN OFF INTERRUPTS 3413 0000123E F605[955B0000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3414 00001245 755F <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3415 <1> ; 3416 00001247 800D[955B0000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3417 0000124E B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3418 00001250 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3419 00001252 EB11 <1> jmp short SL0 ; GO SEND MODE INDICATOR COMMAND 3420 <1> SND_LED1: 3421 00001254 FA <1> cli ; TURN OFF INTERRUPTS 3422 00001255 F605[955B0000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3423 0000125C 7548 <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3424 <1> ; 3425 0000125E 800D[955B0000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3426 <1> SL0: 3427 00001265 B0ED <1> mov al, LED_CMD ; LED CMD BYTE 3428 00001267 E888FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3429 0000126C FA <1> cli 3430 0000126D E836000000 <1> call MAKE_LED ; GO FORM INDICATOR DATA BYTE 3431 00001272 8025[955B0000]F8 <1> and byte [KB_FLAG_2], 0F8h ; ~KB_LEDS ; CLEAR MODE INDICATOR BITS 3432 00001279 0805[955B0000] <1> or [KB_FLAG_2], al ; SAVE PRESENT INDICATORS FOR NEXT TIME 3433 0000127F F605[955B0000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3434 00001286 750F <1> jnz short SL2 ; IF SO, BYPASS SECOND BYTE TRANSMISSION 3435 <1> ; 3436 00001288 E867FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3437 0000128D FA <1> cli ; TURN OFF INTERRUPTS 3438 0000128E F605[955B0000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3439 00001295 7408 <1> jz short SL3 ; IF NOT, DON'T SEND AN ENABLE COMMAND 3440 <1> SL2: 3441 00001297 B0F4 <1> mov al, KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND 3442 00001299 E856FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3443 0000129E FA <1> cli ; TURN OFF INTERRUPTS 3444 <1> SL3: 3445 0000129F 8025[955B0000]3F <1> and byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR 3446 <1> SL1: ; UPDATE AND TRANSMIT ERROR FLAG 3447 000012A6 FB <1> sti ; ENABLE INTERRUPTS 3448 000012A7 C3 <1> retn ; RETURN TO CALLER 3449 <1> 3450 <1> MAKE_LED: 3451 <1> ;--------------------------------------------------------------------------------- 3452 <1> ; MAKE_LED 3453 <1> ; THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF 3454 <1> ; THE MODE INDICATORS. 3455 <1> ;--------------------------------------------------------------------------------- 3456 <1> ; 3457 <1> ;push cx ; SAVE CX 3458 000012A8 A0[935B0000] <1> mov al, [KB_FLAG] ; GET CAPS & NUM LOCK INDICATORS 3459 000012AD 2470 <1> and al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS 3460 <1> ;mov cl, 4 ; SHIFT COUNT 3461 <1> ;rol al, cl ; SHIFT BITS OVER TO TURN ON INDICATORS 3462 000012AF C0C004 <1> rol al, 4 ; 20/02/2015 3463 000012B2 2407 <1> and al, 07h ; MAKE SURE ONLY MODE BITS ON 3464 <1> ;pop cx 3465 000012B4 C3 <1> retn ; RETURN TO CALLER 3466 <1> 3467 <1> ; % include 'kybdata.inc' ; KEYBOARD DATA ; 11/03/2015 3468 <1> 3469 <1> ; /// End Of KEYBOARD FUNCTIONS /// 1834 1835 %include 'video.inc' ; 07/03/2015 1836 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - VIDEO.INC 1837 <1> ; Last Modification: 14/06/2022 1838 <1> ; (Video Data is in 'VIDATA.INC') 1839 <1> ; 1840 <1> ; ///////// VIDEO (CGA) FUNCTIONS /////////////// 1841 <1> 1842 <1> ; 14/06/2022 1843 <1> ; 25/02/2022 1844 <1> ; 02/02/2022 (simplified scroll up) 1845 <1> ; 16/01/2016 1846 <1> ; 30/06/2015 1847 <1> ; 27/06/2015 1848 <1> ; 11/03/2015 1849 <1> ; 02/09/2014 1850 <1> ; 30/08/2014 1851 <1> ; VIDEO FUNCTIONS 1852 <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014) 1853 <1> 1854 <1> write_tty: 1855 <1> ; 02/02/2022 1856 <1> ; 13/08/2015 1857 <1> ; 02/09/2014 1858 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 1859 <1> ; 01/02/2014 (Retro UNIX 8086 v1 - last update) 1860 <1> ; 03/12/2013 (Retro UNIX 8086 v1 - beginning) 1861 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 1862 <1> ; 1863 <1> ; INPUT -> AH = Color (Forecolor, Backcolor) 1864 <1> ; AL = Character to be written 1865 <1> ; EBX = Video Page (0 to 7) 1866 <1> ; (BH = 0 --> Video Mode 3) 1867 <1> 1868 <1> RVRT equ 00001000b ; VIDEO VERTICAL RETRACE BIT 1869 <1> RHRZ equ 00000001b ; VIDEO HORIZONTAL RETRACE BIT 1870 <1> 1871 <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code 1872 <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO 1873 <1> ; 1874 <1> ; 06/10/85 VIDEO DISPLAY BIOS 1875 <1> ; 1876 <1> ;--- WRITE_TTY ------------------------------------------------------------------ 1877 <1> ; : 1878 <1> ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE : 1879 <1> ; VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT : 1880 <1> ; CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. : 1881 <1> ; IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN : 1882 <1> ; IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW : 1883 <1> ; ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, : 1884 <1> ; FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. : 1885 <1> ; WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE : 1886 <1> ; NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : 1887 <1> ; LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE, : 1888 <1> ; THE 0 COLOR IS USED. : 1889 <1> ; ENTRY -- : 1890 <1> ; (AH) = CURRENT CRT MODE : 1891 <1> ; (AL) = CHARACTER TO BE WRITTEN : 1892 <1> ; NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE : 1893 <1> ; HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS : 1894 <1> ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE : 1895 <1> ; EXIT -- : 1896 <1> ; ALL REGISTERS SAVED : 1897 <1> ;-------------------------------------------------------------------------------- 1898 <1> 1899 000012B5 FA <1> cli 1900 <1> ; 1901 <1> ; READ CURSOR (04/12/2013) 1902 <1> ; Retro UNIX 386 v1 Modifications: 30/08/2014 1903 000012B6 08FF <1> or bh, bh 1904 <1> ;jnz beeper 1905 <1> ; 02/02/2022 1906 000012B8 7405 <1> jz short u14 1907 000012BA E992000000 <1> jmp beeper 1908 <1> u14: 1909 <1> ; 02/02/2022 1910 <1> ;; 01/09/2014 1911 <1> ;cmp byte [CRT_MODE], 3 1912 <1> ;je short m3 1913 <1> ;; 1914 <1> ;call set_mode 1915 <1> m3: 1916 000012BF 89DE <1> mov esi, ebx ; 13/08/2015 (0 to 7) 1917 <1> ;shl si, 1 1918 <1> ; 02/02/2022 1919 000012C1 D1E6 <1> shl esi, 1 1920 000012C3 81C6[56610000] <1> add esi, cursor_posn 1921 000012C9 668B16 <1> mov dx, [esi] 1922 <1> ; 1923 <1> ; dx now has the current cursor position 1924 <1> ; 1925 000012CC 3C0D <1> cmp al, 0Dh ; is it carriage return or control character 1926 000012CE 7647 <1> jbe short u8 1927 <1> ; 1928 <1> ; write the char to the screen 1929 <1> u0: 1930 <1> ; ah = attribute/color 1931 <1> ; al = character 1932 <1> ; bl = video page number (0 to 7) 1933 <1> ; bh = 0 1934 <1> ; 1935 000012D0 E8D2010000 <1> call write_c_current 1936 <1> ; 1937 <1> ; position the cursor for next char 1938 000012D5 FEC2 <1> inc dl ; next column 1939 <1> ;cmp dl, [CRT_COLS] 1940 000012D7 80FA50 <1> cmp dl, 80 ; test for column overflow 1941 <1> ;jne set_cpos 1942 <1> ; 02/02/2022 1943 000012DA 7405 <1> je short u13 1944 000012DC E9DE000000 <1> jmp set_cpos 1945 <1> u13: 1946 000012E1 B200 <1> mov dl, 0 ; column = 0 1947 <1> u10: ; (line feed found) 1948 000012E3 80FE18 <1> cmp dh, 25-1 ; check for last row 1949 000012E6 7228 <1> jb short u6 1950 <1> ; 1951 <1> ; scroll required 1952 <1> u1: 1953 <1> ; SET CURSOR POSITION (04/12/2013) 1954 000012E8 E8D2000000 <1> call set_cpos 1955 <1> ; 1956 <1> ; determine value to fill with during scroll 1957 <1> u2: 1958 <1> ; READ_AC_CURRENT : 1959 <1> ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER 1960 <1> ; AT THE CURRENT CURSOR POSITION 1961 <1> ; 1962 <1> ; INPUT 1963 <1> ; (AH) = CURRENT CRT MODE 1964 <1> ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) 1965 <1> ; (DS) = DATA SEGMENT 1966 <1> ; (ES) = REGEN SEGMENT 1967 <1> ; OUTPUT 1968 <1> ; (AL) = CHARACTER READ 1969 <1> ; (AH) = ATTRIBUTE READ 1970 <1> ; 1971 <1> ; mov ah, [CRT_MODE] ; move current mode into ah 1972 <1> ; 1973 <1> ; bl = video page number 1974 <1> ; 1975 000012ED E829010000 <1> call find_position ; get regen location and port address 1976 <1> ; dx = status port 1977 <1> ; esi = cursor location/address 1978 <1> p11: 1979 000012F2 FB <1> sti ; enable interrupts 1980 000012F3 90 <1> nop ; allow for small interupts window 1981 000012F4 FA <1> cli ; blocks interrupts for single loop 1982 000012F5 EC <1> in al, dx ; get status from adapter 1983 000012F6 A801 <1> test al, RHRZ ; is horizontal retrace low 1984 000012F8 75F8 <1> jnz short p11 ; wait until it is 1985 <1> p12: ; now wait for either retrace high 1986 000012FA EC <1> in al, dx ; get status 1987 000012FB A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 1988 000012FD 74FB <1> jz short p12 ; wait until either is active 1989 <1> p13: 1990 000012FF 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 1991 00001305 668B06 <1> mov ax, [esi] ; get the character and attribute 1992 <1> ; 1993 <1> ; al = character, ah = attribute 1994 <1> ; 1995 00001308 FB <1> sti 1996 <1> ; bl = video page number 1997 <1> u3: 1998 <1> ;;mov ax, 0601h ; scroll one line 1999 <1> ;;sub cx, cx ; upper left corner 2000 <1> ;;mov dh, 25-1 ; lower right row 2001 <1> ;;;mov dl, [CRT_COLS] 2002 <1> ;mov dl, 80 ; lower right column 2003 <1> ;;dec dl 2004 <1> ;;mov dl, 79 2005 <1> 2006 <1> ;;call scroll_up ; 04/12/2013 2007 <1> ;;; 11/03/2015 2008 <1> ; 02/09/2014 2009 <1> ;;;mov cx, [crt_ulc] ; Upper left corner (0000h) 2010 <1> ;;;mov dx, [crt_lrc] ; Lower right corner (184Fh) 2011 <1> ; 11/03/2015 2012 <1> ;sub cx, cx 2013 <1> ;mov dx, 184Fh ; dl= 79 (column), dh = 24 (row) 2014 <1> ; 2015 <1> ; 02/02/2022 (simplied scroll up) 2016 <1> ; ((retro unix 8086 v1 'scroll_up' in 'u9.s')) 2017 <1> ; 2018 00001309 B001 <1> mov al, 1 ; scroll 1 line up 2019 <1> ; ah = attribute 2020 0000130B E935010000 <1> jmp scroll_up 2021 <1> ;u4: 2022 <1> ;;int 10h ; video-call return 2023 <1> ; scroll up the screen 2024 <1> ; tty return 2025 <1> ;u5: 2026 <1> ;retn ; return to the caller 2027 <1> 2028 <1> u6: ; set-cursor-inc 2029 00001310 FEC6 <1> inc dh ; next row 2030 <1> ; set cursor 2031 <1> ;u7: 2032 <1> ;;mov ah, 02h 2033 <1> ;;jmp short u4 ; establish the new cursor 2034 <1> ;call set_cpos 2035 <1> ;jmp short u5 2036 00001312 E9A8000000 <1> jmp set_cpos 2037 <1> 2038 <1> ; check for control characters 2039 <1> u8: 2040 00001317 7434 <1> je short u9 2041 00001319 3C0A <1> cmp al, 0Ah ; is it a line feed (0Ah) 2042 0000131B 74C6 <1> je short u10 2043 0000131D 3C07 <1> cmp al, 07h ; is it a bell 2044 0000131F 7430 <1> je short u11 2045 00001321 3C08 <1> cmp al, 08h ; is it a backspace 2046 <1> ;jne short u0 2047 00001323 7420 <1> je short bs ; 12/12/2013 2048 <1> ; 12/12/2013 (tab stop) 2049 00001325 3C09 <1> cmp al, 09h ; is it a tab stop 2050 00001327 75A7 <1> jne short u0 2051 00001329 88D0 <1> mov al, dl 2052 0000132B 6698 <1> cbw 2053 0000132D B108 <1> mov cl, 8 2054 0000132F F6F1 <1> div cl 2055 00001331 28E1 <1> sub cl, ah 2056 <1> ts: 2057 <1> ; 02/09/2014 2058 <1> ; 01/09/2014 2059 00001333 B020 <1> mov al, 20h 2060 <1> tsloop: 2061 <1> ;push cx 2062 <1> ;push ax 2063 <1> ; 02/02/2022 2064 00001335 51 <1> push ecx 2065 00001336 50 <1> push eax 2066 00001337 30FF <1> xor bh, bh 2067 <1> ;mov bl, [active_page] 2068 00001339 E881FFFFFF <1> call m3 2069 <1> ; 02/02/2022 2070 0000133E 58 <1> pop eax 2071 0000133F 59 <1> pop ecx 2072 <1> ;pop ax ; ah = attribute/color 2073 <1> ;pop cx 2074 00001340 FEC9 <1> dec cl 2075 00001342 75F1 <1> jnz short tsloop 2076 00001344 C3 <1> retn 2077 <1> bs: 2078 <1> ; back space found 2079 00001345 08D2 <1> or dl, dl ; is it already at start of line 2080 <1> ;je short u7 ; set_cursor 2081 00001347 7476 <1> jz short set_cpos 2082 <1> ;dec dx ; no -- just move it back 2083 <1> ; 02/02/2022 2084 00001349 FECA <1> dec dl 2085 <1> ;jmp short u7 2086 0000134B EB72 <1> jmp short set_cpos 2087 <1> 2088 <1> ; carriage return found 2089 <1> u9: 2090 0000134D B200 <1> mov dl, 0 ; move to first column 2091 <1> ;jmp short u7 2092 0000134F EB6E <1> jmp short set_cpos 2093 <1> 2094 <1> ; line feed found 2095 <1> ;u10: 2096 <1> ; cmp dh, 25-1 ; bottom of screen 2097 <1> ; jne short u6 ; no, just set the cursor 2098 <1> ; jmp u1 ; yes, scroll the screen 2099 <1> 2100 <1> beeper: 2101 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2102 <1> ; 18/01/2014 2103 <1> ; 03/12/2013 2104 <1> ; bell found 2105 <1> u11: 2106 00001351 FB <1> sti 2107 00001352 3A1D[66610000] <1> cmp bl, [active_page] 2108 00001358 7551 <1> jne short u12 ; Do not sound the beep 2109 <1> ; if it is not written on the active page 2110 0000135A 66B93305 <1> mov cx, 1331 ; divisor for 896 hz tone 2111 0000135E B31F <1> mov bl, 31 ; set count for 31/64 second for beep 2112 <1> ;call beep ; sound the pod bell 2113 <1> ;jmp short u5 ; tty_return 2114 <1> ;retn 2115 <1> 2116 <1> TIMER equ 040h ; 8254 TIMER - BASE ADDRESS 2117 <1> PORT_B equ 061h ; PORT B READ/WRITE DIAGNOSTIC REGISTER 2118 <1> GATE2 equ 00000001b ; TIMER 2 INPUT CATE CLOCK BIT 2119 <1> SPK2 equ 00000010b ; SPEAKER OUTPUT DATA ENABLE BIT 2120 <1> 2121 <1> beep: 2122 <1> ; 07/02/2015 2123 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2124 <1> ; 18/01/2014 2125 <1> ; 03/12/2013 2126 <1> ; 2127 <1> ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES 2128 <1> ; 2129 <1> ; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE 2130 <1> ; 2131 <1> ; ENTRY: 2132 <1> ; (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND ) 2133 <1> ; (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ) 2134 <1> ; EXIT: : 2135 <1> ; (AX),(BL),(CX) MODIFIED. 2136 <1> 2137 00001360 9C <1> pushf ; 18/01/2014 ; save interrupt status 2138 00001361 FA <1> cli ; block interrupts during update 2139 00001362 B0B6 <1> mov al, 10110110b ; select timer 2, lsb, msb binary 2140 00001364 E643 <1> out TIMER+3, al ; write timer mode register 2141 00001366 EB00 <1> jmp $+2 ; I/O delay 2142 00001368 88C8 <1> mov al, cl ; divisor for hz (low) 2143 0000136A E642 <1> out TIMER+2,AL ; write timer 2 count - lsb 2144 0000136C EB00 <1> jmp $+2 ; I/O delay 2145 0000136E 88E8 <1> mov al, ch ; divisor for hz (high) 2146 00001370 E642 <1> out TIMER+2, al ; write timer 2 count - msb 2147 00001372 E461 <1> in al, PORT_B ; get current setting of port 2148 00001374 88C4 <1> mov ah, al ; save that setting 2149 00001376 0C03 <1> or al, GATE2+SPK2 ; gate timer 2 and turn speaker on 2150 00001378 E661 <1> out PORT_B, al ; and restore interrupt status 2151 <1> ;popf ; 18/01/2014 2152 0000137A FB <1> sti 2153 <1> g7: ; 1/64 second per count (bl) 2154 0000137B B90B040000 <1> mov ecx, 1035 ; delay count for 1/64 of a second 2155 00001380 E827000000 <1> call waitf ; go to beep delay 1/64 count 2156 00001385 FECB <1> dec bl ; (bl) length count expired? 2157 00001387 75F2 <1> jnz short g7 ; no - continue beeping speaker 2158 <1> ; 2159 <1> ;pushf ; save interrupt status 2160 00001389 FA <1> cli ; 18/01/2014 ; block interrupts during update 2161 0000138A E461 <1> in al, PORT_B ; get current port value 2162 <1> ;or al, not (GATE2+SPK2) ; isolate current speaker bits in case 2163 0000138C 0CFC <1> or al, ~(GATE2+SPK2) 2164 0000138E 20C4 <1> and ah, al ; someone turned them off during beep 2165 00001390 88E0 <1> mov al, ah ; recover value of port 2166 <1> ;or al, not (GATE2+SPK2) ; force speaker data off 2167 00001392 0CFC <1> or al, ~(GATE2+SPK2) ; isolate current speaker bits in case 2168 00001394 E661 <1> out PORT_B, al ; and stop speaker timer 2169 <1> ;popf ; restore interrupt flag state 2170 00001396 FB <1> sti 2171 00001397 B90B040000 <1> mov ecx, 1035 ; force 1/64 second delay (short) 2172 0000139C E80B000000 <1> call waitf ; minimum delay between all beeps 2173 <1> ;pushf ; save interrupt status 2174 000013A1 FA <1> cli ; block interrupts during update 2175 000013A2 E461 <1> in al, PORT_B ; get current port value in case 2176 000013A4 2403 <1> and al, GATE2+SPK2 ; someone turned them on 2177 000013A6 08E0 <1> or al, ah ; recover value of port_b 2178 000013A8 E661 <1> out PORT_B, al ; restore speaker status 2179 000013AA 9D <1> popf ; restore interrupt flag state 2180 <1> u12: 2181 000013AB C3 <1> retn 2182 <1> 2183 <1> REFRESH_BIT equ 00010000b ; REFRESH TEST BIT 2184 <1> 2185 <1> WAITF: 2186 <1> waitf: 2187 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2188 <1> ; 03/12/2013 2189 <1> ; 2190 <1> ; push ax ; save work register (ah) 2191 <1> ;waitf1: 2192 <1> ; use timer 1 output bits 2193 <1> ; in al, PORT_B ; read current counter output status 2194 <1> ; and al, REFRESH_BIT ; mask for refresh determine bit 2195 <1> ; cmp al, ah ; did it just change 2196 <1> ; je short waitf1 ; wait for a change in output line 2197 <1> ; ; 2198 <1> ; mov ah, al ; save new lflag state 2199 <1> ; loop waitf1 ; decrement half cycles till count end 2200 <1> ; ; 2201 <1> ; pop ax ; restore (ah) 2202 <1> ; retn ; return (cx)=0 2203 <1> 2204 <1> ; 02/02/2022 2205 <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s) 2206 <1> ; 17/12/2014 (dsectrm2.s) 2207 <1> ; WAITF 2208 <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 /// 2209 <1> ; 2210 <1> ;---WAITF----------------------------------------------------------------------- 2211 <1> ; FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR) 2212 <1> ; ENTRY: 2213 <1> ; (CX) = COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT 2214 <1> ; MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE 2215 <1> ; EXIT: 2216 <1> ; AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS) 2217 <1> ; (CX) = 0 2218 <1> ;------------------------------------------------------------------------------- 2219 <1> 2220 <1> ; Refresh period: 30 micro seconds (15-80 us) 2221 <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH) 2222 <1> 2223 <1> ;WAITF: ; DELAY FOR (CX)*15.085737 US 2224 000013AC 50 <1> push eax ; 02/02/2022 ; SAVE WORK REGISTER (AH) 2225 <1> ;push ax 2226 <1> ; 16/12/2014 2227 <1> ;shr cx, 1 ; convert to count of 30 micro seconds 2228 000013AD D1E9 <1> shr ecx, 1 ; 21/02/2015 2229 <1> ;17/12/2014 2230 <1> ;WAITF1: 2231 <1> ; IN AL, PORT_B ;061h ; READ CURRENT COUNTER OUTPUT STATUS 2232 <1> ; AND AL, REFRESH_BIT ;00010000b ; MASK FOR REFRESH DETERMINE BIT 2233 <1> ; CMP AL, AH ; DID IT JUST CHANGE 2234 <1> ; JE short WAITF1 ; WAIT FOR A CHANGE IN OUTPUT LINE 2235 <1> ; MOV AH, AL ; SAVE NEW FLAG STATE 2236 <1> ; LOOP WAITF1 ; DECREMENT HALF CYCLES TILL COUNT END 2237 <1> ; 2238 <1> ; 17/12/2014 2239 <1> ; 2240 <1> ; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999 2241 <1> ; 2242 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 2243 <1> ; INPUT: CX = number of refresh periods to wait 2244 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2245 <1> WR_STATE_0: 2246 000013AF E461 <1> IN AL,PORT_B ; IN AL,SYS1 2247 000013B1 A810 <1> TEST AL,010H 2248 000013B3 74FA <1> JZ SHORT WR_STATE_0 2249 <1> WR_STATE_1: 2250 000013B5 E461 <1> IN AL,PORT_B ; IN AL,SYS1 2251 000013B7 A810 <1> TEST AL,010H 2252 000013B9 75FA <1> JNZ SHORT WR_STATE_1 2253 000013BB E2F2 <1> LOOP WR_STATE_0 2254 <1> ; 2255 <1> ;pop ax 2256 000013BD 58 <1> pop eax ; 02/02/2022 ; RESTORE (AH) 2257 000013BE C3 <1> RETn ; (CX) = 0 2258 <1> 2259 <1> set_cpos: 2260 <1> ; 14/06/2022 (Retro UNIX 386 v1, Kernel v0.2.0.20) 2261 <1> ; 25/02/2022 2262 <1> ; 23/02/2022 2263 <1> ; 02/02/2022 2264 <1> ; 27/06/2015 2265 <1> ; 01/09/2014 2266 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 2267 <1> ; 2268 <1> ; 12/12/2013 (Retro UNIX 8086 v1 - last update) 2269 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - beginning) 2270 <1> ; 2271 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2272 <1> ; 2273 <1> ; SET_CPOS 2274 <1> ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE 2275 <1> ; NEW X-Y VALUES PASSED 2276 <1> ; INPUT 2277 <1> ; DX - ROW,COLUMN OF NEW CURSOR 2278 <1> ; BH - DISPLAY PAGE OF CURSOR 2279 <1> ; OUTPUT 2280 <1> ; CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY 2281 <1> ; 2282 000013BF 0FB6C3 <1> movzx eax, bl ; BL = video page number ; 27/06/2015 (movzx) 2283 000013C2 D0E0 <1> shl al, 1 ; word offset 2284 000013C4 BE[56610000] <1> mov esi, cursor_posn 2285 000013C9 01C6 <1> add esi, eax 2286 000013CB 668916 <1> mov [esi], dx ; save the pointer 2287 000013CE 381D[66610000] <1> cmp [active_page], bl 2288 000013D4 7531 <1> jne short m17 2289 <1> 2290 <1> ; 14/06/2022 2291 <1> ;cli ; 25/02/2022 2292 <1> 2293 <1> ;call m18 ;h CURSOR SET 2294 <1> ;m17: ; SET_CPOS_RETURN 2295 <1> ; 01/09/2014 2296 <1> ;retn 2297 <1> ; DX = row/column 2298 <1> m18: 2299 000013D6 E832000000 <1> call position ; determine location in regen buffer 2300 <1> ;mov cx, [CRT_START] 2301 <1> ; 23/02/2022 2302 000013DB 0FB70D[54610000] <1> movzx ecx, word [CRT_START] 2303 000013E2 01C1 <1> add ecx, eax 2304 <1> ;add cx, ax ; add char position in regen buffer 2305 <1> ; to the start address (offset) for this page 2306 <1> ;shr cx, 1 ; divide by 2 for char only count 2307 <1> ; 23/02/2022 2308 000013E4 D1E9 <1> shr ecx, 1 2309 000013E6 B40E <1> mov ah, 14 ; register number for cursor 2310 <1> 2311 <1> ; 14/06/2022 2312 <1> ;call m16 ; output value to the 6845 2313 <1> ;sti ; 25/02/2022 2314 <1> ;retn 2315 <1> 2316 <1> ; 14/06/2022 2317 <1> ; 25/02/2022 2318 <1> ; 02/02/2022 2319 <1> ;----- THIS ROUTINE OUTPUTS THE CX REGISTER 2320 <1> ; TO THE 6845 REGISTERS NAMED IN (AH) 2321 <1> m16: 2322 <1> ; 14/06/2022 2323 000013E8 FA <1> cli ; 25/02/2022 2324 <1> ;mov dx, [addr_6845] ; address register 2325 000013E9 66BAD403 <1> mov dx, 03D4h ; I/O address of color card 2326 000013ED 88E0 <1> mov al, ah ; get value 2327 000013EF EE <1> out dx, al ; register set 2328 <1> ;inc dx ; data register 2329 <1> ; 02/02/2022 2330 000013F0 FEC2 <1> inc dl 2331 000013F2 EB00 <1> jmp $+2 ; i/o delay 2332 000013F4 88E8 <1> mov al, ch ; data 2333 000013F6 EE <1> out dx, al 2334 <1> ;dec dx 2335 <1> ; 02/02/2022 2336 000013F7 FECA <1> dec dl 2337 000013F9 88E0 <1> mov al, ah 2338 000013FB FEC0 <1> inc al ; point to other data register 2339 000013FD EE <1> out dx, al ; set for second register 2340 <1> ;inc dx 2341 <1> ; 02/02/2022 2342 000013FE FEC2 <1> inc dl 2343 00001400 EB00 <1> jmp $+2 ; i/o delay 2344 00001402 88C8 <1> mov al, cl ; second data value 2345 00001404 EE <1> out dx, al 2346 <1> ; 14/06/2022 2347 00001405 FB <1> sti ; 25/02/2022 2348 <1> ;m17: 2349 00001406 C3 <1> retn 2350 <1> m17: 2351 <1> ; 14/06/2022 2352 <1> ; ('write_tty' must not return to 'putc' with cf) 2353 00001407 F8 <1> clc 2354 00001408 C3 <1> retn 2355 <1> 2356 <1> set_ctype: 2357 <1> ; 07/02/2022 2358 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2359 <1> ; 2360 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2361 <1> 2362 <1> ; CH) = BITS 4-0 = START LINE FOR CURSOR 2363 <1> ; ** HARDWARE WILL ALWAYS CAUSE BLINK 2364 <1> ; ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING 2365 <1> ; OR NO CURSOR AT ALL 2366 <1> ; (CL) = BITS 4-0 = END LINE FOR CURSOR 2367 <1> 2368 <1> ;------------------------------------------------ 2369 <1> ; SET_CTYPE 2370 <1> ; THIS ROUTINE SETS THE CURSOR VALUE 2371 <1> ; INPUT 2372 <1> ; (CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE 2373 <1> ; OUTPUT 2374 <1> ; NONE 2375 <1> ;------------------------------------------------ 2376 <1> 2377 00001409 B40A <1> mov ah, 10 ; 6845 register for cursor set 2378 <1> ;mov [CURSOR_MODE], cx ; save in data area 2379 <1> ;call m16 ; output cx register 2380 <1> ;retn 2381 <1> ; 07/02/2022 2382 0000140B EBDB <1> jmp short m16 2383 <1> 2384 <1> position: 2385 <1> ; 23/02/2022 2386 <1> ; 02/02/2022 2387 <1> ; 27/06/2015 2388 <1> ; 02/09/2014 2389 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2390 <1> ; 04/12/2013 (Retro UNIX 8086 v1) 2391 <1> ; 2392 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2393 <1> ; 2394 <1> ; POSITION 2395 <1> ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS 2396 <1> ; OF A CHARACTER IN THE ALPHA MODE 2397 <1> ; INPUT 2398 <1> ; AX = ROW, COLUMN POSITION 2399 <1> ; OUTPUT 2400 <1> ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 2401 <1> 2402 <1> ; DX = ROW, COLUMN POSITION 2403 <1> ;movzx eax, byte [CRT_COLS] ; 27/06/2015 2404 0000140D 31C0 <1> xor eax, eax ; 02/09/2014 2405 0000140F B050 <1> mov al, 80 ; determine bytes to row 2406 00001411 F6E6 <1> mul dh ; row value 2407 <1> ;xor dh, dh ; 0 2408 <1> ;add ax, dx ; add column value to the result 2409 <1> ; 23/02/2022 2410 00001413 00D0 <1> add al, dl 2411 00001415 80D400 <1> adc ah, 0 2412 <1> ;shl ax, 1 ; * 2 for attribute bytes 2413 <1> ; 02/02/2022 2414 00001418 D1E0 <1> shl eax, 1 2415 <1> ; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 2416 0000141A C3 <1> retn 2417 <1> 2418 <1> find_position: 2419 <1> ; 02/02/2022 2420 <1> ; 27/06/2015 2421 <1> ; 07/09/2014 2422 <1> ; 02/09/2014 2423 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2424 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2425 0000141B 0FB6CB <1> movzx ecx, bl ; video page number ; 27/06/2015 (movzx) 2426 0000141E 89CE <1> mov esi, ecx 2427 <1> ;shl si, 1 2428 <1> ; 02/02/2022 2429 00001420 D1E6 <1> shl esi, 1 2430 00001422 668B96[56610000] <1> mov dx, [esi+cursor_posn] 2431 00001429 7409 <1> jz short p21 2432 <1> ;xor si, si 2433 <1> ; 02/02/2022 2434 0000142B 31F6 <1> xor esi, esi 2435 <1> p20: 2436 <1> ;add si, [CRT_LEN] 2437 0000142D 6681C6A00F <1> add si, 80*25*2 ; add length of buffer for one page 2438 00001432 E2F9 <1> loop p20 2439 <1> p21: 2440 00001434 6621D2 <1> and dx, dx 2441 00001437 7407 <1> jz short p22 2442 00001439 E8CFFFFFFF <1> call position ; determine location in regen in page 2443 0000143E 01C6 <1> add esi, eax ; add location to start of regen page 2444 <1> p22: 2445 <1> ;mov dx, [addr_6845] ; get base address of active display 2446 <1> ;mov dx, 03D4h ; I/O address of color card 2447 <1> ;add dx, 6 ; point at status port 2448 00001440 66BADA03 <1> mov dx, 03DAh ; status port 2449 <1> ; cx = 0 2450 00001444 C3 <1> retn 2451 <1> 2452 <1> scroll_up: 2453 <1> ; 02/02/2022 (simplified scroll up) 2454 <1> ; ((retro unix 8086 v1 'scroll_up' in 'u9.s')) 2455 <1> ; 16/01/2016 2456 <1> ; 07/09/2014 2457 <1> ; 02/09/2014 2458 <1> ; 01/09/2014 (Retro UNIX 386 v1 - beginning) 2459 <1> ; 04/04/2014 2460 <1> ; 04/12/2013 2461 <1> ; 2462 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2463 <1> ; 2464 <1> ; SCROLL UP 2465 <1> ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP 2466 <1> ; ON THE SCREEN 2467 <1> ; INPUT 2468 <1> ; (AH) = CURRENT CRT MODE 2469 <1> ; (AL) = NUMBER OF ROWS TO SCROLL 2470 <1> ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER 2471 <1> ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER 2472 <1> ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE 2473 <1> ; (DS) = DATA SEGMENT 2474 <1> ; (ES) = REGEN BUFFER SEGMENT 2475 <1> ; OUTPUT 2476 <1> ; NONE -- THE REGEN BUFFER IS MODIFIED 2477 <1> ; 2478 <1> ; bh = 0 (02/09/2014) 2479 <1> ; 2480 <1> ; ((ah = 3)) 2481 <1> ; cl = left upper column 2482 <1> ; ch = left upper row 2483 <1> ; dl = right lower column 2484 <1> ; dh = right lower row 2485 <1> ; 2486 <1> ; al = line count 2487 <1> ; ah = attribute to be used on blanked line 2488 <1> ; bl = video page number (0 to 7) 2489 <1> ; 2490 <1> 2491 <1> ; 02/02/2022 'scroll_up' code 2492 <1> ; ------------------------------------------------------ 2493 <1> ; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm') 2494 <1> 2495 <1> ; INPUT: 2496 <1> ; 2497 <1> ; al = line count 2498 <1> ; (0 or 1) .. 0 -> clear video page 2499 <1> ; ah = attribute to be used on blanked line 2500 <1> ; bl = video page number (0 to 7) 2501 <1> 2502 <1> ;cli 2503 00001445 31C9 <1> xor ecx, ecx 2504 00001447 88C1 <1> mov cl, al ; line count (cl) 2505 00001449 BE00800B00 <1> mov esi, 0B8000h 2506 0000144E 3A1D[66610000] <1> cmp bl, [active_page] 2507 00001454 7411 <1> je short n1 2508 00001456 20DB <1> and bl, bl 2509 00001458 7422 <1> jz short n3 2510 0000145A 88DD <1> mov ch, bl ; video page number 2511 <1> n0: 2512 0000145C 6681C6A00F <1> add si, 25*80*2 2513 00001461 FECD <1> dec ch 2514 00001463 75F7 <1> jnz short n0 2515 00001465 EB15 <1> jmp short n3 2516 <1> n1: 2517 00001467 660335[54610000] <1> add si, [CRT_START] 2518 <1> ; 2519 0000146E 66BADA03 <1> mov dx, 3DAh ; guaranteed to be color card here 2520 <1> n2: ; wait_display_enable 2521 00001472 EC <1> in al, dx ; get port 2522 00001473 A808 <1> test al, RVRT ; wait for vertical retrace 2523 00001475 74FB <1> jz short n2 ; wait_display_enable 2524 00001477 B025 <1> mov al, 25h 2525 00001479 B2D8 <1> mov dl, 0D8h ; address control port 2526 0000147B EE <1> out dx, al ; turn off video during vertical retrace 2527 <1> n3: 2528 <1> ; cl = line count 2529 <1> ; ah = attribute/color 2530 0000147C 89F7 <1> mov edi, esi 2531 0000147E 20C9 <1> and cl, cl 2532 00001480 741F <1> jz short n6 2533 00001482 6681C6A000 <1> add si, 80*2 ; + 160 bytes 2534 00001487 66B98007 <1> mov cx, 24*80 ; 24 rows/lines 2535 0000148B F366A5 <1> rep movsw 2536 0000148E B150 <1> mov cl, 80 ; 1 row (will be cleared) 2537 <1> n4: 2538 <1> ; ah = character attribute/cocor 2539 00001490 B020 <1> mov al, 20h ; fill with blanks 2540 00001492 F366AB <1> rep stosw 2541 <1> 2542 00001495 3A1D[66610000] <1> cmp bl, [active_page] 2543 0000149B 7503 <1> jne short n5 2544 <1> 2545 <1> ;mov al, [crt_mode_set] ; get the value of mode set 2546 0000149D B029 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 2547 <1> ;mov dx, 03D8h ; always set color card port 2548 0000149F EE <1> out dx, al 2549 <1> n5: 2550 000014A0 C3 <1> retn 2551 <1> n6: 2552 <1> ; clear video page 2553 000014A1 66B9D007 <1> mov cx, 25*80 ; 25 rows/lines 2554 000014A5 EBE9 <1> jmp short n4 2555 <1> 2556 <1> ; 23/02/2022 2557 <1> %if 0 ; 16/01/2016 'scroll_up' code 2558 <1> ; ------------------------------------------------------ 2559 <1> 2560 <1> ; Test Line Count 2561 <1> or al, al 2562 <1> jz short al_set 2563 <1> mov bh, dh ; subtract lower row from upper row 2564 <1> sub bh, ch 2565 <1> inc bh ; adjust difference by 1 2566 <1> cmp bh, al ; line count = amount of rows in window? 2567 <1> jne short al_set ; if not the we're all set 2568 <1> xor al, al ; otherwise set al to zero 2569 <1> al_set: 2570 <1> xor bh, bh ; 0 2571 <1> ;push ax 2572 <1> push eax ; 23/02/2022 2573 <1> ;mov esi, [crt_base] 2574 <1> mov esi, 0B8000h 2575 <1> cmp bl, [active_page] 2576 <1> jne short n0 2577 <1> ; 2578 <1> mov ax, [CRT_START] 2579 <1> add si, ax 2580 <1> jmp short n1 2581 <1> n0: 2582 <1> and bl, bl 2583 <1> jz short n1 2584 <1> mov al, bl 2585 <1> n0x: 2586 <1> ;add si, [CRT_LEN] 2587 <1> ;add esi, 80*25*2 2588 <1> add si, 80*25*2 2589 <1> dec al 2590 <1> jnz short n0x 2591 <1> n1: 2592 <1> ; Scroll position 2593 <1> ;push dx ; 23/02/2022 2594 <1> mov dx, cx ; now, upper left position in DX 2595 <1> call position 2596 <1> add esi, eax 2597 <1> mov edi, esi 2598 <1> ;pop dx ; lower right position in DX 2599 <1> sub dx, cx 2600 <1> inc dh ; dh = #rows 2601 <1> inc dl ; dl = #cols in block 2602 <1> ;pop ax ; al = line count, ah = attribute 2603 <1> pop eax ; 23/02/2022 2604 <1> xor ecx, ecx 2605 <1> mov cx, ax 2606 <1> ;mov ah, [CRT_COLS] 2607 <1> mov ah, 80 2608 <1> mul ah ; determine offset to from address 2609 <1> add ax, ax ; *2 for attribute byte 2610 <1> ; 2611 <1> ;push ax ; offset 2612 <1> ;push dx 2613 <1> ; 23/02/2022 2614 <1> push eax 2615 <1> push edx 2616 <1> ; 2617 <1> ; 04/04/2014 2618 <1> mov dx, 3DAh ; guaranteed to be color card here 2619 <1> n8: ; wait_display_enable 2620 <1> in al, dx ; get port 2621 <1> test al, RVRT ; wait for vertical retrace 2622 <1> jz short n8 ; wait_display_enable 2623 <1> mov al, 25h 2624 <1> mov dl, 0D8h ; address control port 2625 <1> out dx, al ; turn off video during vertical retrace 2626 <1> ;pop dx ; #rows, #cols 2627 <1> ;pop ax ; offset 2628 <1> ; 23/02/2022 2629 <1> pop edx 2630 <1> pop eax 2631 <1> xchg ax, cx ; 2632 <1> ; ecx = offset, al = line count, ah = attribute 2633 <1> ;n9: 2634 <1> or al, al 2635 <1> jz short n3 2636 <1> add esi, ecx ; from address for scroll 2637 <1> mov bh, dh ; #rows in block 2638 <1> sub bh, al ; #rows to be moved 2639 <1> n2: 2640 <1> ; Move rows 2641 <1> mov cl, dl ; get # of cols to move 2642 <1> push esi 2643 <1> push edi ; save start address 2644 <1> n10: 2645 <1> movsw ; move that line on screen 2646 <1> dec cl 2647 <1> jnz short n10 2648 <1> pop edi 2649 <1> pop esi ; recover addresses 2650 <1> ;mov cl, [CRT_COLS] 2651 <1> ;add cl, cl 2652 <1> ;mov ecx, 80*2 2653 <1> mov cx, 80*2 2654 <1> add esi, ecx ; next line 2655 <1> add edi, ecx 2656 <1> dec bh ; count of lines to move 2657 <1> jnz short n2 ; row loop 2658 <1> ; bh = 0 2659 <1> mov dh, al ; #rows 2660 <1> n3: 2661 <1> ; attribute in ah 2662 <1> mov al, ' ' ; fill with blanks 2663 <1> n3x: 2664 <1> ; Clear rows 2665 <1> ; dh = #rows 2666 <1> mov cl, dl ; get # of cols to clear 2667 <1> push edi ; save address 2668 <1> n11: 2669 <1> stosw ; store fill character 2670 <1> dec cl 2671 <1> jnz short n11 2672 <1> pop edi ; recover address 2673 <1> ;mov cl, [CRT_COLS] 2674 <1> ;add cl, cl 2675 <1> ;mov ecx, 80*2 2676 <1> mov cl, 80*2 2677 <1> add edi, ecx 2678 <1> dec dh 2679 <1> jnz short n3x ; 16/01/2016 2680 <1> ; 2681 <1> cmp bl, [active_page] 2682 <1> jne short n6 2683 <1> ;mov al, [CRT_MODE_SET] ; get the value of mode set 2684 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 2685 <1> mov dx, 03D8h ; always set color card port 2686 <1> out dx, al 2687 <1> n6: 2688 <1> retn 2689 <1> 2690 <1> %endif 2691 <1> 2692 <1> write_c_current: 2693 <1> ; 02/02/2022 2694 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2695 <1> ; 18/01/2014 2696 <1> ; 04/12/2013 2697 <1> ; 2698 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2699 <1> ; 2700 <1> ; WRITE_C_CURRENT 2701 <1> ; THIS ROUTINE WRITES THE CHARACTER AT 2702 <1> ; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED 2703 <1> ; INPUT 2704 <1> ; (AH) = CURRENT CRT MODE 2705 <1> ; (BH) = DISPLAY PAGE 2706 <1> ; (CX) = COUNT OF CHARACTERS TO WRITE 2707 <1> ; (AL) = CHAR TO WRITE 2708 <1> ; (DS) = DATA SEGMENT 2709 <1> ; (ES) = REGEN SEGMENT 2710 <1> ; OUTPUT 2711 <1> ; DISPLAY REGEN BUFFER UPDATED 2712 <1> 2713 000014A7 FA <1> cli 2714 <1> ; bl = video page 2715 <1> ; al = character 2716 <1> ; ah = color/attribute 2717 <1> ;push dx 2718 <1> ;push ax ; save character & attribute/color 2719 <1> ; 02/02/2022 2720 000014A8 52 <1> push edx 2721 000014A9 50 <1> push eax 2722 000014AA E86CFFFFFF <1> call find_position ; get regen location and port address 2723 <1> ; esi = regen location 2724 <1> ; dx = status port 2725 <1> ; 2726 <1> ; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE 2727 <1> ; 2728 <1> p41: ; wait for horizontal retrace is low or vertical 2729 000014AF FB <1> sti ; enable interrupts first 2730 000014B0 3A1D[66610000] <1> cmp bl, [active_page] 2731 000014B6 7510 <1> jne short p44 2732 000014B8 FA <1> cli ; block interrupts for single loop 2733 000014B9 EC <1> in al, dx ; get status from the adapter 2734 000014BA A808 <1> test al, RVRT ; check for vertical retrace first 2735 000014BC 7509 <1> jnz short p43 ; Do fast write now if vertical retrace 2736 000014BE A801 <1> test al, RHRZ ; is horizontal retrace low 2737 000014C0 75ED <1> jnz short p41 ; wait until it is 2738 <1> p42: ; wait for either retrace high 2739 000014C2 EC <1> in al, dx ; get status again 2740 000014C3 A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 2741 000014C5 74FB <1> jz short p42 ; wait until either retrace active 2742 <1> p43: 2743 000014C7 FB <1> sti 2744 <1> p44: 2745 <1> ;pop ax ; restore the character (al) & attribute (ah) 2746 <1> ; 02/02/2022 2747 000014C8 58 <1> pop eax 2748 000014C9 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (crt_base) 2749 <1> ; Retro UNIX 386 v1 feature only! 2750 000014CF 668906 <1> mov [esi], ax 2751 <1> ;pop dx 2752 <1> ; 02/02/2022 2753 000014D2 5A <1> pop edx 2754 000014D3 C3 <1> retn 2755 <1> 2756 <1> %if 0 ; 02/02/2022 2757 <1> 2758 <1> set_mode: 2759 <1> ; 02/02/2022 2760 <1> ; 16/01/2016 2761 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2762 <1> ; 2763 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2764 <1> 2765 <1> ;------------------------------------------------------ 2766 <1> ; SET MODE : 2767 <1> ; THIS ROUTINE INITIALIZES THE ATTACHMENT TO : 2768 <1> ; THE SELECTED MODE, THE SCREEN IS BLANKED. : 2769 <1> ; INPUT : 2770 <1> ; (AL) - MODE SELECTED (RANGE 0-7) : 2771 <1> ; OUTPUT : 2772 <1> ; NONE : 2773 <1> ;------------------------------------------------------ 2774 <1> 2775 <1> push edi ; 16/01/2016 2776 <1> push ebx 2777 <1> push edx 2778 <1> push ecx ; 16/01/2016 2779 <1> push eax 2780 <1> 2781 <1> ;mov dx, 03D4h ; address or color card 2782 <1> mov al, 3 2783 <1> ;M8: 2784 <1> mov [CRT_MODE], al ; save mode in global variable 2785 <1> mov al, 29h 2786 <1> ;mov [CRT_MODE_SET], al ; save the mode set value 2787 <1> and al, 037h ; video off, save high resolution bit 2788 <1> ;push dx ; save port value 2789 <1> ;add dx, 4 ; point to control register 2790 <1> mov dx, 3D8h 2791 <1> out dx, al ; reset video to off to suppress rolling 2792 <1> ;pop dx 2793 <1> ;M9: 2794 <1> mov ebx, video_params ; initialization table 2795 <1> ;mov ax, [ebx+10] ; get the cursor mode from the table 2796 <1> ;xchg ah, al 2797 <1> ;mov [CURSOR_MODE], ax ; save cursor mode 2798 <1> xor ah, ah ; ah is register number during loop 2799 <1> 2800 <1> ;----- LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE 2801 <1> ; 02/02/2022 2802 <1> ; dx = 3D8h 2803 <1> xor ecx, ecx 2804 <1> mov cl, 16 2805 <1> ;mov ecx, 16 ; 16/01/2016 2806 <1> M10: ; initialization loop 2807 <1> mov al, ah ; get 6845 register number 2808 <1> out dx, al 2809 <1> ;inc dx ; point to data port 2810 <1> ; 02/02/2022 2811 <1> inc dl ; 3D9h 2812 <1> inc ah ; next register value 2813 <1> mov al, [ebx] ; get table value 2814 <1> out dx, al ; out to chip 2815 <1> inc ebx ; next in table 2816 <1> ;dec dx ; back to pointer register 2817 <1> ; 02/02/2022 2818 <1> dec dl ; 3D8h 2819 <1> loop M10 ; do the whole table 2820 <1> 2821 <1> ;----- FILL REGEN AREA WITH BLANK 2822 <1> ;xor ax, ax 2823 <1> ;mov [CRT_START], ax ; start address saved in global 2824 <1> ;mov [ACTIVE_PAGE], al ; 0 ; (re)set page value 2825 <1> ;mov ecx, 8192 ; number of words in color card 2826 <1> ; black background, light gray characeter color, space character 2827 <1> ;mov ax, 0720h ; fill char for alpha - attribute 2828 <1> ;M13: ; clear buffer 2829 <1> ;add edi, 0B8000h ; [crt_base] 2830 <1> ;rep stosw ; FILL THE REGEN BUFFER WITH BLANKS 2831 <1> 2832 <1> ;----- ENABLE VIDEO AND CORRECT PORT SETTING 2833 <1> ;mov dx, 3D4h ; mov dx, word [ADDR_6845] 2834 <1> ; prepare to output to video enable port 2835 <1> ;;add dx, 4 ; point to the mode control gerister 2836 <1> ; 02/02/2022 2837 <1> ;mov dx, 3D8h 2838 <1> ; 2839 <1> ;mov al, [CRT_MODE_SET] ; get the mode set value 2840 <1> mov al, 29h 2841 <1> out dx, al ; set video enable port 2842 <1> 2843 <1> ;----- DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY 2844 <1> ;----- AND THE NUMBER TO BE USED FOR TTY INTERFACE 2845 <1> ; 2846 <1> ;mov byte [CRT_COLS], 80h ; initialize number of columns count 2847 <1> ; 2848 <1> ;----- SET CURSOR POSITIONS 2849 <1> ;push edi 2850 <1> ;mov word [CRT_LEN], 80*25*2 2851 <1> mov edi, cursor_posn 2852 <1> mov ecx, 4 ; clear all cursor positions (16 bytes) 2853 <1> xor eax, eax 2854 <1> rep stosd ; fill with zeroes 2855 <1> ;pop edi 2856 <1> 2857 <1> ;----- SET UP OVERSCAN REGISTER 2858 <1> inc dx ; set overscan port to a default 2859 <1> mov al, 30h ; 30H valuye for all modes except 640X200 bw 2860 <1> ;M14: 2861 <1> out dx, al ; output the correct value to 3D9 port 2862 <1> ;mov [CRT_PALETTE], al ; save the value for future use 2863 <1> 2864 <1> ;----- NORMAL RETURN FROM ALL VIDEO RETURNS 2865 <1> ; 2866 <1> pop eax 2867 <1> pop ecx ; 16/01/2016 2868 <1> pop edx 2869 <1> pop ebx 2870 <1> pop edi ; 16/01/2016 2871 <1> retn 2872 <1> 2873 <1> %endif 2874 <1> 2875 <1> tty_sw: 2876 <1> ; 02/02/2022 2877 <1> ; 30/06/2015 2878 <1> ; 27/06/2015 2879 <1> ; 07/09/2014 2880 <1> ; 02/09/2014 (Retro UNIX 386 v1 - beginning) 2881 <1> ; 2882 <1> ; (Modified registers : EAX) 2883 <1> ; 2884 <1> ;mov byte [u.quant], 0 ; 04/03/2014 2885 <1> ; 2886 <1> ;act_disp_page: 2887 <1> ; 30/06/2015 2888 <1> ; 04/03/2014 (act_disp_page --> tty_sw) 2889 <1> ; 10/12/2013 2890 <1> ; 04/12/2013 2891 <1> ; 2892 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2893 <1> ; 2894 <1> ; ACT_DISP_PAGE 2895 <1> ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING 2896 <1> ; THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT 2897 <1> ; INPUT 2898 <1> ; AL HAS THE NEW ACTIVE DISPLAY PAGE 2899 <1> ; OUTPUT 2900 <1> ; THE 6845 IS RESET TO DISPLAY THAT PAGE 2901 <1> 2902 <1> ;cli 2903 <1> 2904 000014D4 53 <1> push ebx 2905 <1> ;push cx 2906 <1> ;push dx 2907 <1> ; 02/02/2022 2908 000014D5 51 <1> push ecx 2909 000014D6 52 <1> push edx 2910 <1> ; 2911 000014D7 A2[66610000] <1> mov [active_page], al ; save active page value ; [ptty] 2912 <1> ;;mov cx, [CRT_LEN] ; get saved length of regen buffer 2913 <1> ;mov cx, 25*80*2 2914 <1> ; 02/02/2022 2915 000014DC B9A00F0000 <1> mov ecx, 25*80*2 2916 <1> ; 27/06/2015 2917 000014E1 0FB6D8 <1> movzx ebx, al 2918 <1> ; 02/02/2022 2919 000014E4 89D8 <1> mov eax, ebx 2920 <1> ; 2921 <1> ;cbw ; 07/09/2014 (ah=0) 2922 <1> ;mul cx ; display page times regen length 2923 <1> ; 02/02/2022 2924 000014E6 F7E1 <1> mul ecx 2925 <1> ; 10/12/2013 2926 000014E8 66A3[54610000] <1> mov [CRT_START], ax ; save start address for later 2927 <1> ;mov cx, ax ; start address to cx 2928 <1> ; 02/02/2022 2929 000014EE 89C1 <1> mov ecx, eax 2930 <1> ;sar cx, 1 2931 <1> ;shr cx, 1 ; divide by 2 for 6845 handling 2932 <1> ; 02/02/2022 2933 000014F0 D1E9 <1> shr ecx, 1 2934 000014F2 B40C <1> mov ah, 12 ; 6845 register for start address 2935 000014F4 E8EFFEFFFF <1> call m16 2936 <1> ;sal bx, 1 2937 <1> ; 01/09/2014 2938 000014F9 D0E3 <1> shl bl, 1 ; * 2 for word offset 2939 000014FB 81C3[56610000] <1> add ebx, cursor_posn 2940 00001501 668B13 <1> mov dx, [ebx] ; get cursor for this page 2941 00001504 E8CDFEFFFF <1> call m18 2942 <1> ; 2943 <1> ;pop dx 2944 <1> ;pop cx 2945 <1> ; 02/02/2022 2946 00001509 5A <1> pop edx 2947 0000150A 59 <1> pop ecx 2948 0000150B 5B <1> pop ebx 2949 <1> ; 2950 <1> ;sti 2951 <1> ; 2952 0000150C C3 <1> retn 2953 <1> 2954 <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015 2955 <1> 2956 <1> ; /// End Of VIDEO FUNCTIONS /// 1836 1837 setup_rtc_int: 1838 ; source: http://wiki.osdev.org/RTC 1839 0000150D FA cli ; disable interrupts 1840 ; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6) 1841 ; in order to change this ... 1842 ; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024 1843 ; (rate must be above 2 and not over 15) 1844 ; new rate = 15 --> 32768 >> (15-1) = 2 Hz 1845 0000150E B08A mov al, 8Ah 1846 00001510 E670 out 70h, al ; set index to register A, disable NMI 1847 00001512 90 nop 1848 00001513 E471 in al, 71h ; get initial value of register A 1849 00001515 88C4 mov ah, al 1850 00001517 80E4F0 and ah, 0F0h 1851 0000151A B08A mov al, 8Ah 1852 0000151C E670 out 70h, al ; reset index to register A 1853 0000151E 88E0 mov al, ah 1854 00001520 0C0F or al, 0Fh ; new rate (0Fh -> 15) 1855 00001522 E671 out 71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 1856 ; enable RTC interrupt 1857 00001524 B08B mov al, 8Bh ; 1858 00001526 E670 out 70h, al ; select register B and disable NMI 1859 00001528 90 nop 1860 00001529 E471 in al, 71h ; read the current value of register B 1861 0000152B 88C4 mov ah, al ; 1862 0000152D B08B mov al, 8Bh ; 1863 0000152F E670 out 70h, al ; set the index again (a read will reset the index to register B) 1864 00001531 88E0 mov al, ah ; 1865 00001533 0C40 or al, 40h ; 1866 00001535 E671 out 71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B 1867 00001537 FB sti 1868 00001538 C3 retn 1869 1870 ; Write memory information 1871 ; Temporary Code 1872 ; 06/11/2014 1873 ; 14/08/2015 1874 memory_info: 1875 00001539 A1[3C610000] mov eax, [memory_size] ; in pages 1876 0000153E 50 push eax 1877 0000153F C1E00C shl eax, 12 ; in bytes 1878 00001542 BB0A000000 mov ebx, 10 1879 00001547 89D9 mov ecx, ebx ; 10 1880 00001549 BE[A35D0000] mov esi, mem_total_b_str 1881 0000154E E8B2000000 call bintdstr 1882 00001553 58 pop eax 1883 00001554 B107 mov cl, 7 1884 00001556 BE[C75D0000] mov esi, mem_total_p_str 1885 0000155B E8A5000000 call bintdstr 1886 ; 14/08/2015 1887 00001560 E8BD000000 call calc_free_mem 1888 ; edx = calculated free pages 1889 ; ecx = 0 1890 00001565 A1[40610000] mov eax, [free_pages] 1891 0000156A 39D0 cmp eax, edx ; calculated free mem value 1892 ; and initial free mem value are same or not? 1893 0000156C 751D jne short pmim ; print mem info with '?' if not 1894 0000156E 52 push edx ; free memory in pages 1895 ;mov eax, edx 1896 0000156F C1E00C shl eax, 12 ; convert page count 1897 ; to byte count 1898 00001572 B10A mov cl, 10 1899 00001574 BE[E75D0000] mov esi, free_mem_b_str 1900 00001579 E887000000 call bintdstr 1901 0000157E 58 pop eax 1902 0000157F B107 mov cl, 7 1903 00001581 BE[0B5E0000] mov esi, free_mem_p_str 1904 00001586 E87A000000 call bintdstr 1905 pmim: 1906 0000158B BE[915D0000] mov esi, msg_memory_info 1907 pmim_nb: 1908 00001590 AC lodsb 1909 00001591 08C0 or al, al 1910 00001593 740D jz short pmim_ok 1911 00001595 56 push esi 1912 00001596 31DB xor ebx, ebx ; 0 1913 ; Video page 0 (bl=0) 1914 00001598 B407 mov ah, 07h ; Black background, 1915 ; light gray forecolor 1916 0000159A E816FDFFFF call write_tty 1917 0000159F 5E pop esi 1918 000015A0 EBEE jmp short pmim_nb 1919 pmim_ok: 1920 000015A2 C3 retn 1921 1922 ; Convert binary number to hexadecimal string 1923 ; 10/05/2015 1924 ; dsectpm.s (28/02/2015) 1925 ; Retro UNIX 386 v1 - Kernel v0.2.0.6 1926 ; 01/12/2014 1927 ; 25/11/2014 1928 ; 1929 bytetohex: 1930 ; INPUT -> 1931 ; AL = byte (binary number) 1932 ; OUTPUT -> 1933 ; AX = hexadecimal string 1934 ; 1935 000015A3 53 push ebx 1936 000015A4 31DB xor ebx, ebx 1937 000015A6 88C3 mov bl, al 1938 000015A8 C0EB04 shr bl, 4 1939 000015AB 8A9B[F5150000] mov bl, [ebx+hexchrs] 1940 000015B1 86D8 xchg bl, al 1941 000015B3 80E30F and bl, 0Fh 1942 000015B6 8AA3[F5150000] mov ah, [ebx+hexchrs] 1943 000015BC 5B pop ebx 1944 000015BD C3 retn 1945 1946 wordtohex: 1947 ; INPUT -> 1948 ; AX = word (binary number) 1949 ; OUTPUT -> 1950 ; EAX = hexadecimal string 1951 ; 1952 000015BE 53 push ebx 1953 000015BF 31DB xor ebx, ebx 1954 000015C1 86E0 xchg ah, al 1955 000015C3 6650 push ax 1956 000015C5 88E3 mov bl, ah 1957 000015C7 C0EB04 shr bl, 4 1958 000015CA 8A83[F5150000] mov al, [ebx+hexchrs] 1959 000015D0 88E3 mov bl, ah 1960 000015D2 80E30F and bl, 0Fh 1961 000015D5 8AA3[F5150000] mov ah, [ebx+hexchrs] 1962 000015DB C1E010 shl eax, 16 1963 000015DE 6658 pop ax 1964 000015E0 5B pop ebx 1965 000015E1 EBC0 jmp short bytetohex 1966 ;mov bl, al 1967 ;shr bl, 4 1968 ;mov bl, [ebx+hexchrs] 1969 ;xchg bl, al 1970 ;and bl, 0Fh 1971 ;mov ah, [ebx+hexchrs] 1972 ;pop ebx 1973 ;retn 1974 1975 dwordtohex: 1976 ; INPUT -> 1977 ; EAX = dword (binary number) 1978 ; OUTPUT -> 1979 ; EDX:EAX = hexadecimal string 1980 ; 1981 000015E3 50 push eax 1982 000015E4 C1E810 shr eax, 16 1983 000015E7 E8D2FFFFFF call wordtohex 1984 000015EC 89C2 mov edx, eax 1985 000015EE 58 pop eax 1986 000015EF E8CAFFFFFF call wordtohex 1987 000015F4 C3 retn 1988 1989 ; 10/05/2015 1990 hex_digits: 1991 hexchrs: 1992 000015F5 303132333435363738- db '0123456789ABCDEF' 1992 000015FE 39414243444546 1993 1994 ; Convert binary number to decimal/numeric string 1995 ; 06/11/2014 1996 ; Temporary Code 1997 ; 1998 1999 bintdstr: 2000 ; EAX = binary number 2001 ; ESI = decimal/numeric string address 2002 ; EBX = divisor (10) 2003 ; ECX = string length (<=10) 2004 00001605 01CE add esi, ecx 2005 btdstr0: 2006 00001607 4E dec esi 2007 00001608 31D2 xor edx, edx 2008 0000160A F7F3 div ebx 2009 0000160C 80C230 add dl, 30h 2010 0000160F 8816 mov [esi], dl 2011 00001611 FEC9 dec cl 2012 00001613 740C jz btdstr2 2013 00001615 09C0 or eax, eax 2014 00001617 75EE jnz short btdstr0 2015 btdstr1: 2016 00001619 4E dec esi 2017 0000161A C60620 mov byte [esi], 20h ; blank space 2018 0000161D FEC9 dec cl 2019 0000161F 75F8 jnz short btdstr1 2020 btdstr2: 2021 00001621 C3 retn 2022 2023 ; Calculate free memory pages on M.A.T. 2024 ; 06/11/2014 2025 ; Temporary Code 2026 ; 2027 2028 calc_free_mem: 2029 00001622 31D2 xor edx, edx 2030 ;xor ecx, ecx 2031 00001624 668B0D[50610000] mov cx, [mat_size] ; in pages 2032 0000162B C1E10A shl ecx, 10 ; 1024 dwords per page 2033 0000162E BE00001000 mov esi, MEM_ALLOC_TBL 2034 cfm0: 2035 00001633 AD lodsd 2036 00001634 51 push ecx 2037 00001635 B920000000 mov ecx, 32 2038 cfm1: 2039 0000163A D1E8 shr eax, 1 2040 0000163C 7301 jnc short cfm2 2041 0000163E 42 inc edx 2042 cfm2: 2043 0000163F E2F9 loop cfm1 2044 00001641 59 pop ecx 2045 00001642 E2EF loop cfm0 2046 00001644 C3 retn 2047 2048 %include 'diskio.inc' ; 07/03/2015 2049 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - DISKIO.INC 2050 <1> ; Last Modification: 18/07/2022 2051 <1> ; (Initialized Disk Parameters Data is in 'DISKDATA.INC') 2052 <1> ; (Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 2053 <1> ; ************************************************************************ 2054 <1> ; Ref: Retro UNIX 386 v1.1 'diskio.inc' modification: 12/07/2022 2055 <1> 2056 <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project) 2057 <1> ; ///////// DISK I/O SYSTEM /////////////// 2058 <1> 2059 <1> ; 15/07/2022 2060 <1> ;; 06/02/2015 2061 <1> ;diskette_io: 2062 <1> ; pushfd 2063 <1> ; push cs 2064 <1> ; call DISKETTE_IO_1 2065 <1> ; retn 2066 <1> 2067 <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;; 2068 <1> ;////////////////////////////////////////////////////// 2069 <1> 2070 <1> ; 11/07/2022 - (direct call instead of int 13h simulation) 2071 <1> ; Function in AL 2072 <1> ; 0 = reset 2073 <1> ; 1 = read 2074 <1> ; 2 = write 2075 <1> ; Disk drive number in DL 2076 <1> ; 0 & 1 = floppy disks 2077 <1> ; 80h .. 83h = hard disks 2078 <1> ; Sector address (LBA) in ECX 2079 <1> ; Buffer address in EBX 2080 <1> ; R/W sector count is (always) 1 2081 <1> ; 2082 <1> ; Return: 2083 <1> ; Status in AH (>0 = error code) 2084 <1> ; if CF = 1 -> error code in AH 2085 <1> ; if CF = 0 -> successful 2086 <1> ; AL = undefined 2087 <1> ; 2088 <1> ; Modified registers: (only) EAX 2089 <1> 2090 <1> ; 10/07/2022 2091 <1> ; 08/07/2022 - (diskio code has been simplified/shortened 2092 <1> ; by removing unused IBM PC-AT disk functions) 2093 <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project) 2094 <1> ; 20/02/2015 2095 <1> ; 06/02/2015 (unix386.s) 2096 <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s) 2097 <1> ; 2098 <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC) 2099 <1> ; 2100 <1> ; ADISK.EQU 2101 <1> 2102 <1> ;----- Wait control constants 2103 <1> 2104 <1> ;amount of time to wait while RESET is active. 2105 <1> 2106 <1> WAITCPU_RESET_ON EQU 21 ;Reset on must last at least 14us 2107 <1> ;at 250 KBS xfer rate. 2108 <1> ;see INTEL MCS, 1985, pg. 5-456 2109 <1> 2110 <1> WAITCPU_FOR_STATUS EQU 100 ;allow 30 microseconds for 2111 <1> ;status register to become valid 2112 <1> ;before re-reading. 2113 <1> 2114 <1> ;After sending a byte to NEC, status register may remain 2115 <1> ;incorrectly set for 24 us. 2116 <1> 2117 <1> WAITCPU_RQM_LOW EQU 24 ;number of loops to check for 2118 <1> ;RQM low. 2119 <1> 2120 <1> ; COMMON.MAC 2121 <1> ; 2122 <1> ; Timing macros 2123 <1> ; 2124 <1> 2125 <1> %macro SIODELAY 0 ; SHORT IODELAY 2126 <1> jmp short $+2 2127 <1> %endmacro 2128 <1> 2129 <1> %macro IODELAY 0 ; NORMAL IODELAY 2130 <1> jmp short $+2 2131 <1> jmp short $+2 2132 <1> %endmacro 2133 <1> 2134 <1> %macro NEWIODELAY 0 2135 <1> out 0EBh,al 2136 <1> %endmacro 2137 <1> 2138 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 2139 <1> ;;; WAIT_FOR_MEM 2140 <1> ;WAIT_FDU_INT_LO equ 017798 ; 2.5 secs in 30 micro units. 2141 <1> ;WAIT_FDU_INT_HI equ 1 2142 <1> WAIT_FDU_INT_LH equ 83334 ; 27/02/2015 (2.5 seconds waiting) 2143 <1> ;;; WAIT_FOR_PORT 2144 <1> ;WAIT_FDU_SEND_LO equ 16667 ; .5 secons in 30 us units. 2145 <1> ;WAIT_FDU_SEND_HI equ 0 2146 <1> WAIT_FDU_SEND_LH equ 16667 ; 27/02/2015 2147 <1> ;Time to wait while waiting for each byte of NEC results = .5 2148 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 2149 <1> ;WAIT_FDU_RESULTS_LO equ 16667 ; .5 seconds in 30 micro units. 2150 <1> ;WAIT_FDU_RESULTS_HI equ 0 2151 <1> WAIT_FDU_RESULTS_LH equ 16667 ; 27/02/2015 2152 <1> ;;; WAIT_REFRESH 2153 <1> ;amount of time to wait for head settle, per unit in parameter 2154 <1> ;table = 1 ms. 2155 <1> WAIT_FDU_HEAD_SETTLE equ 33 ; 1 ms in 30 micro units. 2156 <1> 2157 <1> 2158 <1> ; //////////////// DISKETTE I/O //////////////// 2159 <1> 2160 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC) 2161 <1> 2162 <1> ;---------------------------------------- 2163 <1> ; EQUATES USED BY POST AND BIOS : 2164 <1> ;---------------------------------------- 2165 <1> 2166 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2167 <1> ;PORT_A EQU 060H ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2168 <1> ;PORT_B EQU 061H ; PORT B READ/WRITE DIAGNOSTIC REGISTER 2169 <1> ;REFRESH_BIT EQU 00010000B ; REFRESH TEST BIT 2170 <1> 2171 <1> ;---------------------------------------- 2172 <1> ; CMOS EQUATES FOR THIS SYSTEM : 2173 <1> ;------------------------------------------------------------------------------- 2174 <1> ;CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 2175 <1> ;CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 2176 <1> ;NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 2177 <1> ; HIGH BIT OF CMOS LOCATION ADDRESS 2178 <1> 2179 <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- 2180 <1> CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; 2181 <1> ; EQU 011H ; - RESERVED ;C 2182 <1> CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H 2183 <1> ; EQU 013H ; - RESERVED ;E 2184 <1> CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C 2185 <1> 2186 <1> ;---------- DISKETTE EQUATES --------------------------------------------------- 2187 <1> INT_FLAG EQU 10000000B ; INTERRUPT OCCURRENCE FLAG 2188 <1> DSK_CHG EQU 10000000B ; DISKETTE CHANGE FLAG MASK BIT 2189 <1> DETERMINED EQU 00010000B ; SET STATE DETERMINED IN STATE BITS 2190 <1> HOME EQU 00010000B ; TRACK 0 MASK 2191 <1> SENSE_DRV_ST EQU 00000100B ; SENSE DRIVE STATUS COMMAND 2192 <1> TRK_SLAP EQU 030H ; CRASH STOP (48 TPI DRIVES) 2193 <1> QUIET_SEEK EQU 00AH ; SEEK TO TRACK 10 2194 <1> ;MAX_DRV EQU 2 ; MAX NUMBER OF DRIVES 2195 <1> HD12_SETTLE EQU 15 ; 1.2 M HEAD SETTLE TIME 2196 <1> HD320_SETTLE EQU 20 ; 320 K HEAD SETTLE TIME 2197 <1> MOTOR_WAIT EQU 37 ; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF 2198 <1> 2199 <1> ;---------- DISKETTE ERRORS ---------------------------------------------------- 2200 <1> ;TIME_OUT EQU 080H ; ATTACHMENT FAILED TO RESPOND 2201 <1> ;BAD_SEEK EQU 040H ; SEEK OPERATION FAILED 2202 <1> BAD_NEC EQU 020H ; DISKETTE CONTROLLER HAS FAILED 2203 <1> BAD_CRC EQU 010H ; BAD CRC ON DISKETTE READ 2204 <1> MED_NOT_FND EQU 00CH ; MEDIA TYPE NOT FOUND 2205 <1> DMA_BOUNDARY EQU 009H ; ATTEMPT TO DMA ACROSS 64K BOUNDARY 2206 <1> BAD_DMA EQU 008H ; DMA OVERRUN ON OPERATION 2207 <1> MEDIA_CHANGE EQU 006H ; MEDIA REMOVED ON DUAL ATTACH CARD 2208 <1> RECORD_NOT_FND EQU 004H ; REQUESTED SECTOR NOT FOUND 2209 <1> WRITE_PROTECT EQU 003H ; WRITE ATTEMPTED ON WRITE PROTECT DISK 2210 <1> BAD_ADDR_MARK EQU 002H ; ADDRESS MARK NOT FOUND 2211 <1> BAD_CMD EQU 001H ; BAD COMMAND PASSED TO DISKETTE I/O 2212 <1> 2213 <1> ;---------- DISK CHANGE LINE EQUATES ------------------------------------------- 2214 <1> NOCHGLN EQU 001H ; NO DISK CHANGE LINE AVAILABLE 2215 <1> CHGLN EQU 002H ; DISK CHANGE LINE AVAILABLE 2216 <1> 2217 <1> ;---------- MEDIA/DRIVE STATE INDICATORS --------------------------------------- 2218 <1> TRK_CAPA EQU 00000001B ; 80 TRACK CAPABILITY 2219 <1> FMT_CAPA EQU 00000010B ; MULTIPLE FORMAT CAPABILITY (1.2M) 2220 <1> DRV_DET EQU 00000100B ; DRIVE DETERMINED 2221 <1> MED_DET EQU 00010000B ; MEDIA DETERMINED BIT 2222 <1> DBL_STEP EQU 00100000B ; DOUBLE STEP BIT 2223 <1> RATE_MSK EQU 11000000B ; MASK FOR CLEARING ALL BUT RATE 2224 <1> RATE_500 EQU 00000000B ; 500 KBS DATA RATE 2225 <1> RATE_300 EQU 01000000B ; 300 KBS DATA RATE 2226 <1> RATE_250 EQU 10000000B ; 250 KBS DATA RATE 2227 <1> STRT_MSK EQU 00001100B ; OPERATION START RATE MASK 2228 <1> SEND_MSK EQU 11000000B ; MASK FOR SEND RATE BITS 2229 <1> 2230 <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY ------------------------- 2231 <1> M3D3U EQU 00000000B ; 360 MEDIA/DRIVE NOT ESTABLISHED 2232 <1> M3D1U EQU 00000001B ; 360 MEDIA,1.2DRIVE NOT ESTABLISHED 2233 <1> M1D1U EQU 00000010B ; 1.2 MEDIA/DRIVE NOT ESTABLISHED 2234 <1> MED_UNK EQU 00000111B ; NONE OF THE ABOVE 2235 <1> 2236 <1> ;---------- INTERRUPT EQUATES -------------------------------------------------- 2237 <1> ;EOI EQU 020H ; END OF INTERRUPT COMMAND TO 8259 2238 <1> ;INTA00 EQU 020H ; 8259 PORT 2239 <1> INTA01 EQU 021H ; 8259 PORT 2240 <1> INTB00 EQU 0A0H ; 2ND 8259 2241 <1> INTB01 EQU 0A1H ; 2242 <1> 2243 <1> ;------------------------------------------------------------------------------- 2244 <1> DMA08 EQU 008H ; DMA STATUS REGISTER PORT ADDRESS 2245 <1> DMA EQU 000H ; DMA CH.0 ADDRESS REGISTER PORT ADDRESS 2246 <1> DMA18 EQU 0D0H ; 2ND DMA STATUS PORT ADDRESS 2247 <1> DMA1 EQU 0C0H ; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS 2248 <1> ;------------------------------------------------------------------------------- 2249 <1> ;TIMER EQU 040H ; 8254 TIMER - BASE ADDRESS 2250 <1> 2251 <1> ;------------------------------------------------------------------------------- 2252 <1> DMA_PAGE EQU 081H ; START OF DMA PAGE REGISTERS 2253 <1> 2254 <1> ; 10/07/2022 2255 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2256 <1> ; 06/02/2015 (unix386.s, protected mode modifications) 2257 <1> ; (unix386.s <-- dsectrm2.s) 2258 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC) 2259 <1> 2260 <1> ; 10/12/2014 2261 <1> ; 2262 <1> ;int40h: 2263 <1> ; pushf 2264 <1> ; push cs 2265 <1> ; ;cli 2266 <1> ; call DISKETTE_IO_1 2267 <1> ; retn 2268 <1> 2269 <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS 2270 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 2271 <1> ; 2272 <1> 2273 <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022------------------------- 2274 <1> ; DISKETTE I/O 2275 <1> ; THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB, 2276 <1> ; 1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES. 2277 <1> ; INPUT 2278 <1> ; (AH)= 00H RESET DISKETTE SYSTEM 2279 <1> ; HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED 2280 <1> ; ON ALL DRIVES 2281 <1> ;------------------------------------------------------------------------------- 2282 <1> ; (AH)= 01H READ THE DESIRED SECTORS INTO MEMORY 2283 <1> ;------------------------------------------------------------------------------- 2284 <1> ; (AH)= 02H WRITE THE DESIRED SECTORS FROM MEMORY 2285 <1> ;------------------------------------------------------------------------------- 2286 <1> ; 2287 <1> ; REGISTERS FOR READ/WRITE 2288 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 2289 <1> ; (DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED) 2290 <1> ; (CH) - TRACK NUMBER (NOT VALUE CHECKED) 2291 <1> ; MEDIA DRIVE TRACK NUMBER 2292 <1> ; 320/360 320/360 0-39 2293 <1> ; 320/360 1.2M 0-39 2294 <1> ; 1.2M 1.2M 0-79 2295 <1> ; 720K 720K 0-79 2296 <1> ; 1.44M 1.44M 0-79 2297 <1> ; (CL) - SECTOR NUMBER (NOT VALUE CHECKED) 2298 <1> ; MEDIA DRIVE SECTOR NUMBER 2299 <1> ; 320/360 320/360 1-8/9 2300 <1> ; 320/360 1.2M 1-8/9 2301 <1> ; 1.2M 1.2M 1-15 2302 <1> ; 720K 720K 1-9 2303 <1> ; 1.44M 1.44M 1-18 2304 <1> ; (AL) NUMBER OF SECTORS (NOT VALUE CHECKED) 2305 <1> ; MEDIA DRIVE MAX NUMBER OF SECTORS 2306 <1> ; 320/360 320/360 8/9 2307 <1> ; 320/360 1.2M 8/9 2308 <1> ; 1.2M 1.2M 15 2309 <1> ; 720K 720K 9 2310 <1> ; 1.44M 1.44M 18 2311 <1> ; 2312 <1> ; (EBX) - ADDRESS OF BUFFER 2313 <1> ; 2314 <1> ;------------------------------------------------------------------------------- 2315 <1> ; OUTPUT FOR ALL FUNCTIONS 2316 <1> ; AH = STATUS OF OPERATION 2317 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS 2318 <1> ; VARIABLE IN THE DATA SEGMENT OF THIS MODULE 2319 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) 2320 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) 2321 <1> ; FOR READ/WRITE/VERIFY 2322 <1> ; DS,BX,DX,CX PRESERVED 2323 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 2324 <1> ; ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION. 2325 <1> ; ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 2326 <1> ; THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 2327 <1> ; PROBLEM IS NOT DUE TO MOTOR START-UP. 2328 <1> ;------------------------------------------------------------------------------- 2329 <1> ; 2330 <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B) 2331 <1> ; 2332 <1> ; ----------------------------------------------------------------- 2333 <1> ; | | | | | | | | | 2334 <1> ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 2335 <1> ; | | | | | | | | | 2336 <1> ; ----------------------------------------------------------------- 2337 <1> ; | | | | | | | | 2338 <1> ; | | | | | ----------------- 2339 <1> ; | | | | | | 2340 <1> ; | | | | RESERVED | 2341 <1> ; | | | | PRESENT STATE 2342 <1> ; | | | | 000: 360K IN 360K DRIVE UNESTABLISHED 2343 <1> ; | | | | 001: 360K IN 1.2M DRIVE UNESTABLISHED 2344 <1> ; | | | | 010: 1.2M IN 1.2M DRIVE UNESTABLISHED 2345 <1> ; | | | | 011: 360K IN 360K DRIVE ESTABLISHED 2346 <1> ; | | | | 100: 360K IN 1.2M DRIVE ESTABLISHED 2347 <1> ; | | | | 101: 1.2M IN 1.2M DRIVE ESTABLISHED 2348 <1> ; | | | | 110: RESERVED 2349 <1> ; | | | | 111: NONE OF THE ABOVE 2350 <1> ; | | | | 2351 <1> ; | | | ------> MEDIA/DRIVE ESTABLISHED 2352 <1> ; | | | 2353 <1> ; | | --------------> DOUBLE STEPPING REQUIRED 2354 <1> ; | | (360K IN 1.2M DRIVE) 2355 <1> ; | | 2356 <1> ; ------------------------------> DATA TRANSFER RATE FOR THIS DRIVE: 2357 <1> ; 2358 <1> ; 00: 500 KBS 2359 <1> ; 01: 300 KBS 2360 <1> ; 10: 250 KBS 2361 <1> ; 11: RESERVED 2362 <1> ; 2363 <1> ; 2364 <1> 2365 <1> struc MD 2366 00000000 ?? <1> .SPEC1: resb 1 ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2367 00000001 ?? <1> .SPEC2: resb 1 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2368 00000002 ?? <1> .OFF_TIM: resb 1 ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2369 00000003 ?? <1> .BYT_SEC: resb 1 ; 512 BYTES/SECTOR 2370 00000004 ?? <1> .SEC_TRK: resb 1 ; EOT (LAST SECTOR ON TRACK) 2371 00000005 ?? <1> .GAP: resb 1 ; GAP LENGTH 2372 00000006 ?? <1> .DTL: resb 1 ; DTL 2373 00000007 ?? <1> .GAP3: resb 1 ; GAP LENGTH FOR FORMAT 2374 00000008 ?? <1> .FIL_BYT: resb 1 ; FILL BYTE FOR FORMAT 2375 00000009 ?? <1> .HD_TIM: resb 1 ; HEAD SETTLE TIME (MILLISECONDS) 2376 0000000A ?? <1> .STR_TIM: resb 1 ; MOTOR START TIME (1/8 SECONDS) 2377 0000000B ?? <1> .MAX_TRK: resb 1 ; MAX. TRACK NUMBER 2378 0000000C ?? <1> .RATE: resb 1 ; DATA TRANSFER RATE 2379 <1> endstruc 2380 <1> 2381 <1> BIT7OFF EQU 7FH 2382 <1> BIT7ON EQU 80H 2383 <1> 2384 <1> ; 11/07/2022 - (direct call instead of int 13h simulation) 2385 <1> ; Function in AL 2386 <1> ; 0 = reset 2387 <1> ; 1 = read 2388 <1> ; 2 = write 2389 <1> ; Disk drive number in DL 2390 <1> ; 0 & 1 = floppy disks 2391 <1> ; 80h .. 83h = hard disks 2392 <1> ; Sector address (LBA) in ECX 2393 <1> ; Buffer address in EBX 2394 <1> ; R/W sector count is (always) 1 2395 <1> ; 2396 <1> ; Return: 2397 <1> ; Status in AH (>0 = error code) 2398 <1> ; if CF = 1 -> error code in AH 2399 <1> ; if CF = 0 -> successful 2400 <1> ; AL = undefined 2401 <1> ; 2402 <1> ; Modified registers: (only) EAX 2403 <1> 2404 <1> ; 11/07/2022 2405 <1> ;;int13h: ; 16/02/2015 2406 <1> ;; 16/02/2015 - 21/02/2015 2407 <1> ;int40h: 2408 <1> ; pushfd 2409 <1> ; push cs 2410 <1> ; call DISKETTE_IO_1 2411 <1> ; retn 2412 <1> 2413 <1> DISKETTE_IO_1: 2414 <1> 2415 <1> ;sti ; INTERRUPTS BACK ON 2416 <1> ; 11/07/2022 2417 <1> ; save registers 2418 00001645 55 <1> push ebp ; ANY 2419 <1> 2420 <1> ; 11/07/2022 2421 <1> ;push edi ; ANY 2422 <1> ;push edx ; DRIVE NUMBER (DL) 2423 <1> ;push ebx ; BUFFER ADDRESS 2424 <1> ;push ecx ; SECTOR ADDRESS (LBA) 2425 <1> ;push esi ; ANY 2426 <1> 2427 <1> ; 11/07/2022 2428 00001646 89DD <1> mov ebp, ebx ; buffer address 2429 00001648 C605[BC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS 2430 0000164F 0FB6FA <1> movzx edi, dl ; drive number (0 or 1) 2431 <1> 2432 00001652 08C0 <1> or al, al ; RESET ? 2433 00001654 7507 <1> jnz short DISKETTE_RW_1 ; NO 2434 <1> 2435 00001656 E84D010000 <1> call DSK_RESET 2436 <1> 2437 0000165B EB37 <1> jmp short DISKETTE_RW_2 2438 <1> 2439 <1> DISKETTE_RW_1: 2440 <1> ; 12/07/2022 2441 <1> ; 11/07/2022 2442 <1> ; ecx = sector address (LBA, < 2880) 2443 <1> ; ebp = buffer address 2444 <1> ; edi = drive number (0 or 1) 2445 <1> ; al = function (read = 1 or write = 2) 2446 <1> 2447 0000165D 88C2 <1> mov dl, al ; * 2448 <1> convert_to_chs: 2449 <1> ;;; 2450 0000165F B004 <1> mov al, 4 ; MD.SEC_TRK ; sector per track (drv.spt) 2451 00001661 E8DB050000 <1> call GET_PARM 2452 <1> ; 12/07/2022 2453 00001666 88E6 <1> mov dh, ah ; spt 2454 00001668 89C8 <1> mov eax, ecx ; sector address (LBA) 2455 0000166A F6F6 <1> div dh ; AX/DH 2456 0000166C 88E1 <1> mov cl, ah ; sector number - 1 2457 0000166E FEC1 <1> inc cl ; sector number (1 based) 2458 00001670 28ED <1> sub ch, ch ; head = 0 2459 <1> ; heads = 2 2460 00001672 D0E8 <1> shr al, 1 ; al = al/2 2461 00001674 80D500 <1> adc ch, 0 ; head = 1 or head = 0 2462 00001677 C1E110 <1> shl ecx, 16 2463 0000167A 88C1 <1> mov cl, al ; track (cylinder) 2464 0000167C 88D5 <1> mov ch, dl ; function number 2465 0000167E 89CE <1> mov esi, ecx ; byte 0 = track, byte 1 = function 2466 <1> ; byte 2 = sector, byte 3 = head 2467 00001680 C1C610 <1> rol esi, 16 2468 <1> ; byte 0 = sector, byte 1 = head 2469 <1> ; byte 2 = track, byte 3 = function 2470 <1> ;;; 2471 00001683 80FA02 <1> cmp dl, 2 ; * 2472 00001686 7407 <1> je short DISKETTE_W 2473 <1> DISKETTE_R: 2474 <1> ; dl = 1 ; * 2475 00001688 E809000000 <1> call DSK_READ 2476 0000168D EB05 <1> jmp short DISKETTE_RW_2 2477 <1> DISKETTE_W: 2478 0000168F E80F000000 <1> call DSK_WRITE 2479 <1> DISKETTE_RW_2: 2480 <1> ; 11/07/2022 2481 <1> ; Restore registers 2482 <1> ;pop esi 2483 <1> ;pop ecx 2484 <1> ;pop ebx 2485 <1> ;pop edx 2486 <1> ;pop edi 2487 <1> 2488 <1> ; 11/07/2022 2489 00001694 5D <1> pop ebp 2490 00001695 C3 <1> retn 2491 <1> 2492 <1> ;------------------------------------------------------------------------------- 2493 <1> ; DISK_READ (AH = 01H) ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2494 <1> ; DISKETTE READ. 2495 <1> ; 2496 <1> ; ON ENTRY: EDI : DRIVE # 2497 <1> ; SI-HI : HEAD # 2498 <1> ; SI-LOW : # OF SECTORS 2499 <1> ; ES : BUFFER SEGMENT 2500 <1> ; [BP] : SECTOR # 2501 <1> ; [BP+1] : TRACK # 2502 <1> ; [BP+2] : BUFFER OFFSET 2503 <1> ; 2504 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2505 <1> ;------------------------------------------------------------------------------- 2506 <1> 2507 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2508 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 2509 <1> 2510 <1> DSK_READ: 2511 00001696 8025[BA610000]7F <1> and byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION 2512 0000169D 66B846E6 <1> mov ax, 0E646h ; AX = NEC COMMAND, DMA COMMAND 2513 <1> ;call RD_WR_VF ; COMMON READ/WRITE/VERIFY 2514 <1> ;retn 2515 000016A1 EB0B <1> jmp short RD_WR_VF 2516 <1> 2517 <1> ;------------------------------------------------------------------------------- 2518 <1> ; DISK_WRITE (AH = 02H) 2519 <1> ; DISKETTE WRITE. 2520 <1> ; 2521 <1> ; ON ENTRY: EDI : DRIVE # 2522 <1> ; SI-HI : HEAD # 2523 <1> ; SI-LOW : # OF SECTORS 2524 <1> ; ES : BUFFER SEGMENT 2525 <1> ; [BP] : SECTOR # 2526 <1> ; [BP+1] : TRACK # 2527 <1> ; [BP+2] : BUFFER OFFSET 2528 <1> ; 2529 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2530 <1> ;------------------------------------------------------------------------------- 2531 <1> 2532 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2533 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 2534 <1> 2535 <1> DSK_WRITE: 2536 000016A3 66B84AC5 <1> mov ax, 0C54Ah ; AX = NEC COMMAND, DMA COMMAND 2537 000016A7 800D[BA610000]80 <1> or byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION 2538 <1> ;;call RD_WR_VF ; COMMON READ/WRITE/VERIFY 2539 <1> ;;retn 2540 <1> ;jmp short RD_WR_VF 2541 <1> 2542 <1> ;------------------------------------------------------------------------------- 2543 <1> ; RD_WR_VF 2544 <1> ; COMMON READ, WRITE 2545 <1> ; MAIN LOOP FOR STATE RETRIES. 2546 <1> ; 2547 <1> ; ON ENTRY: AH = READ/WRITE NEC PARAMETER 2548 <1> ; AL = READ/WRITE DMA PARAMETER 2549 <1> ; 2550 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2551 <1> ;------------------------------------------------------------------------------- 2552 <1> 2553 <1> RD_WR_VF: 2554 <1> ; 18/07/2022 2555 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2556 000016AE 50 <1> push eax ; 24/12/2021 ; SAVE DMA, NEC PARAMETERS 2557 000016AF E8CB010000 <1> call XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 2558 000016B4 E82D020000 <1> call SETUP_STATE ; INITIALIZE START AND END RATE 2559 000016B9 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 2560 <1> DO_AGAIN: 2561 000016BA 50 <1> push eax ; 24/12/2021 ; SAVE READ/WRITE PARAMETER 2562 000016BB E867020000 <1> call MED_CHANGE ; MEDIA CHANGE AND RESET IF CHANGED 2563 000016C0 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 2564 <1> ; 24/12/2021 2565 000016C1 7305 <1> jnc short RWV 2566 000016C3 E9B6000000 <1> jmp RWV_END ; MEDIA CHANGE ERROR OR TIME-OUT 2567 <1> RWV: 2568 000016C8 50 <1> push eax ; 24/12/2021 ; SAVE READ/WRITE/VERIFY PARAMETER 2569 000016C9 8AB7[C7610000] <1> mov dh, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 2570 000016CF 80E6C0 <1> and dh, RATE_MSK ; KEEP ONLY RATE 2571 000016D2 E861050000 <1> call CMOS_TYPE ; RETURN DRIVE TYPE IN AL 2572 <1> ; 20/02/2015 2573 000016D7 7445 <1> jz short RWV_ASSUME ; ERROR IN CMOS 2574 000016D9 3C01 <1> cmp al, 1 ; 40 TRACK DRIVE? 2575 000016DB 750D <1> jne short RWV_1 ; NO, BYPASS CMOS VALIDITY CHECK 2576 000016DD F687[C7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE 2577 000016E4 740F <1> jz short RWV_2 ; YES, CMOS IS CORRECT 2578 <1> ;mov al, 2 ; CHANGE TO 1.2M 2579 <1> ; 12/07/2022 2580 000016E6 FEC0 <1> inc al ; al = 2 2581 000016E8 EB0B <1> jmp short RWV_2 2582 <1> RWV_1: 2583 <1> ; 12/07/2022 2584 <1> ;jb short RWV_2 ; NO DRIVE SPECIFIED, CONTINUE 2585 000016EA F687[C7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK? 2586 000016F1 7502 <1> jnz short RWV_2 ; NO, 80 TRACK 2587 000016F3 B001 <1> mov al, 1 ; IT IS 40 TRACK, FIX CMOS VALUE 2588 <1> ; 12/07/2022 2589 <1> ;jmp short RWV_3 2590 <1> RWV_2: 2591 <1> ; 12/07/2022 2592 <1> ;or al, al ; TEST FOR NO DRIVE 2593 <1> ;jz short RWV_ASSUME ; ASSUME TYPE, USE MAX TRACK 2594 <1> RWV_3: 2595 <1> ; 12/07/2022 2596 <1> ;mov dl, al ; 11/07/2022 2597 000016F5 E81F010000 <1> call DR_TYPE_CHECK ; RTN EBX = MEDIA/DRIVE PARAM TBL. 2598 000016FA 7222 <1> jc short RWV_ASSUME ; TYPE NOT IN TABLE (BAD CMOS) 2599 <1> 2600 <1> ;----- SEARCH FOR MEDIA/DRIVE PARAMETER TABLE 2601 <1> 2602 000016FC 57 <1> push edi ; SAVE DRIVE # 2603 <1> ;xor ebx, ebx ; EBX = INDEX TO DR_TYPE TABLE 2604 000016FD BB[DC5B0000] <1> mov ebx, DR_TYPE 2605 <1> ;mov ecx, DR_CNT ; ECX = LOOP COUNT 2606 00001702 B106 <1> mov cl, DR_CNT 2607 <1> RWV_DR_SEARCH: 2608 <1> ;mov ah, [DR_TYPE+ebx] ; GET DRIVE TYPE 2609 00001704 8A23 <1> mov ah, [ebx] 2610 00001706 80E47F <1> and ah, BIT7OFF ; MASK OUT MSB 2611 00001709 38E0 <1> cmp al, ah ; DRIVE TYPE MATCH? 2612 <1> ; 12/07/2022 2613 <1> ;cmp dl, ah ; 11/07/2022 2614 0000170B 7509 <1> jne short RWV_NXT_MD ; NO, CHECK NEXT DRIVE TYPE 2615 <1> RWV_DR_FND: 2616 <1> ;mov edi, [DR_TYPE+ebx+1] ; EDI = MEDIA/DRIVE PARAMETER TABLE 2617 0000170D 43 <1> inc ebx 2618 0000170E 8B3B <1> mov edi, [ebx] 2619 00001710 4B <1> dec ebx 2620 <1> RWV_MD_SEARH: 2621 00001711 3A770C <1> cmp dh, [edi+MD.RATE] ; MATCH? 2622 00001714 741D <1> je short RWV_MD_FND ; YES, GO GET 1ST SPECIFY BYTE 2623 <1> RWV_NXT_MD: 2624 00001716 83C305 <1> add ebx, 5 ; CHECK NEXT DRIVE TYPE 2625 <1> ;loop RWV_DR_SEARCH 2626 00001719 FEC9 <1> dec cl 2627 0000171B 75E7 <1> jnz short RWV_DR_SEARCH 2628 0000171D 5F <1> pop edi ; RESTORE DRIVE # 2629 <1> 2630 <1> ;----- ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED 2631 <1> 2632 <1> RWV_ASSUME: 2633 0000171E BB[FA5B0000] <1> mov ebx, MD_TBL1 ; POINT TO 40 TRACK 250 KBS 2634 00001723 F687[C7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK 2635 0000172A 740A <1> jz short RWV_MD_FND1 ; MUST BE 40 TRACK 2636 0000172C BB[145C0000] <1> mov ebx, MD_TBL3 ; POINT TO 80 TRACK 500 KBS 2637 00001731 EB03 <1> jmp short RWV_MD_FND1 ; GO SPECIFY PARAMTERS 2638 <1> 2639 <1> ;----- EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE 2640 <1> 2641 <1> RWV_MD_FND: 2642 00001733 89FB <1> mov ebx, edi ; EBX = MEDIA/DRIVE PARAMETER TABLE 2643 00001735 5F <1> pop edi ; RESTORE DRIVE # 2644 <1> 2645 <1> ;----- SEND THE SPECIFY COMMAND TO THE CONTROLLER 2646 <1> 2647 <1> RWV_MD_FND1: 2648 00001736 E824010000 <1> call SEND_SPEC_MD 2649 0000173B E853020000 <1> call CHK_LASTRATE ; ZF=1 ATTEMP RATE IS SAME AS LAST RATE 2650 00001740 7405 <1> jz short RWV_DBL ; YES,SKIP SEND RATE COMMAND 2651 00001742 E82E020000 <1> call SEND_RATE ; SEND DATA RATE TO NEC 2652 <1> RWV_DBL: 2653 00001747 53 <1> push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 2654 00001748 E849040000 <1> call SETUP_DBL ; CHECK FOR DOUBLE STEP 2655 0000174D 5B <1> pop ebx ; RESTORE ADDRESS 2656 0000174E 7221 <1> jc short CHK_RET ; ERROR FROM READ ID, POSSIBLE RETRY 2657 <1> ;pop eax ; 24/12/2021 ; RESTORE NEC COMMAND 2658 <1> ;push eax ; 24/12/2021 ; SAVE NEC COMMAND 2659 <1> ; 08/07/2022 2660 00001750 8B0424 <1> mov eax, [esp] 2661 <1> ; 18/07/2022 2662 <1> ;push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 2663 00001753 E84E020000 <1> call DMA_SETUP ; SET UP THE DMA 2664 <1> ;pop ebx 2665 00001758 58 <1> pop eax ; 24/12/2021 ; RESTORE NEC COMMAND 2666 00001759 722D <1> jc short RWV_BAC ; CHECK FOR DMA BOUNDARY ERROR 2667 0000175B 50 <1> push eax ; 24/12/2021 ; SAVE NEC COMMAND 2668 0000175C 53 <1> push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 2669 0000175D E88E020000 <1> call NEC_INIT ; INITIALIZE NEC 2670 00001762 5B <1> pop ebx ; RESTORE ADDRESS 2671 00001763 720C <1> jc short CHK_RET ; ERROR - EXIT 2672 00001765 E8B7020000 <1> call RWV_COM ; OP CODE COMMON TO READ/WRITE 2673 0000176A 7205 <1> jc short CHK_RET ; ERROR - EXIT 2674 0000176C E8FE020000 <1> call NEC_TERM ; TERMINATE, GET STATUS, ETC. 2675 <1> CHK_RET: 2676 00001771 E89D030000 <1> call RETRY ; CHECK FOR, SETUP RETRY 2677 00001776 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 2678 00001777 7305 <1> jnc short RWV_END ; CY = 0 NO RETRY 2679 00001779 E93CFFFFFF <1> jmp DO_AGAIN ; CY = 1 MEANS RETRY 2680 <1> RWV_END: 2681 0000177E E848030000 <1> call DSTATE ; ESTABLISH STATE IF SUCCESSFUL 2682 00001783 E8D9030000 <1> call NUM_TRANS ; AL = NUMBER TRANSFERRED 2683 <1> RWV_BAC: 2684 <1> ; 08/07/2022 ; BAD DMA ERROR ENTRY 2685 <1> ;push eax ; 24/12/2021 ; SAVE NUMBER TRANSFERRED 2686 <1> ;CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 2687 <1> ;pop eax ; 24/12/2021 ; RESTORE NUMBER TRANSFERRED 2688 <1> ;;call SETUP_END ; VARIOUS CLEANUPS 2689 <1> ;;retn 2690 <1> ;jmp SETUP_END 2691 <1> 2692 <1> ;------------------------------------------------------------------------------- 2693 <1> ; SETUP_END 2694 <1> ; RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 2695 <1> ; AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY. 2696 <1> ; 2697 <1> ; ON EXIT: 2698 <1> ; AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2699 <1> ;------------------------------------------------------------------------------- 2700 <1> SETUP_END: 2701 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2702 <1> ;mov dl, 2 ; GET THE MOTOR WAIT PARAMETER 2703 <1> ;push ax ; SAVE NUMBER TRANSFERRED 2704 00001788 50 <1> push eax ; 24/12/2021 2705 00001789 B002 <1> mov al, 2 ; 08/07/2022 2706 0000178B E8B1040000 <1> call GET_PARM 2707 00001790 8825[BB610000] <1> mov [MOTOR_COUNT], ah ; STORE UPON RETURN 2708 <1> ;pop ax ; RESTORE NUMBER TRANSFERRED 2709 00001796 58 <1> pop eax ; 24/12/2021 2710 00001797 8A25[BC610000] <1> mov ah, [DSKETTE_STATUS] ; GET STATUS OF OPERATION 2711 0000179D 08E4 <1> or ah, ah ; CHECK FOR ERROR 2712 0000179F 7406 <1> jz short NUN_ERR ; NO ERROR 2713 000017A1 30C0 <1> xor al, al ; CLEAR NUMBER RETURNED 2714 <1> ;NUN_ERR: 2715 000017A3 80FC01 <1> cmp ah, 1 ; SET THE CARRY FLAG TO INDICATE 2716 000017A6 F5 <1> cmc ; SUCCESS OR FAILURE 2717 <1> NUN_ERR: 2718 000017A7 C3 <1> retn 2719 <1> 2720 <1> ;------------------------------------------------------------------------------- 2721 <1> ; DISK_RESET (AH = 00H) 2722 <1> ; RESET THE DISKETTE SYSTEM. 2723 <1> ; 2724 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2725 <1> ;------------------------------------------------------------------------------- 2726 <1> DSK_RESET: 2727 <1> ; 17/07/2022 2728 <1> ; 12/07/2022 2729 <1> ; 11/07/2022 2730 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2731 000017A8 66BAF203 <1> mov dx, 03F2h ; ADAPTER CONTROL PORT 2732 000017AC FA <1> cli ; NO INTERRUPTS 2733 000017AD A0[BA610000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 2734 000017B2 243F <1> and al, 00111111b ; KEEP SELECTED AND MOTOR ON BITS 2735 000017B4 C0C004 <1> rol al, 4 ; MOTOR VALUE TO HIGH NIBBLE 2736 <1> ; DRIVE SELECT TO LOW NIBBLE 2737 000017B7 0C08 <1> or al, 00001000b ; TURN ON INTERRUPT ENABLE 2738 000017B9 EE <1> out dx, al ; RESET THE ADAPTER 2739 000017BA C605[B9610000]00 <1> mov byte [SEEK_STATUS], 0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 2740 <1> ;JMP $+2 ; WAIT FOR I/O 2741 <1> ;JMP $+2 ; WAIT FOR I/O (TO INSURE MINIMUM 2742 <1> ; PULSE WIDTH) 2743 <1> ; 19/12/2014 2744 <1> NEWIODELAY 2135 000017C1 E6EB <2> out 0EBh,al 2745 <1> 2746 <1> ; 17/12/2014 2747 <1> ; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM) 2748 000017C3 B915000000 <1> mov ecx, WAITCPU_RESET_ON ; cx = 21 -- Min. 14 micro seconds !? 2749 <1> wdw1: 2750 <1> NEWIODELAY ; 27/02/2015 2135 000017C8 E6EB <2> out 0EBh,al 2751 000017CA E2FC <1> loop wdw1 2752 <1> ; 2753 000017CC 0C04 <1> or al, 00000100b ; TURN OFF RESET BIT 2754 000017CE EE <1> out dx, al ; RESET THE ADAPTER 2755 <1> ; 16/12/2014 2756 <1> IODELAY 2130 000017CF EB00 <2> jmp short $+2 2131 000017D1 EB00 <2> jmp short $+2 2757 <1> ; 2758 <1> ;sti ; ENABLE THE INTERRUPTS 2759 000017D3 E864060000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 2760 000017D8 7236 <1> jc short DR_ERR ; IF ERROR, RETURN IT 2761 <1> ;mov cx, 11000000b ; CL = EXPECTED @NEC_STATUS 2762 <1> ; 12/07/2022 2763 <1> ;xor ecx, ecx 2764 <1> ; 17/07/2022 2765 <1> ;xor ch, ch 2766 000017DA B1C0 <1> mov cl, 11000000b 2767 <1> NXT_DRV: 2768 <1> ; 24/12/2021 2769 000017DC 51 <1> push ecx ; SAVE FOR CALL 2770 000017DD B8[0F180000] <1> mov eax, DR_POP_ERR ; LOAD NEC_OUTPUT ERROR ADDRESS 2771 000017E2 50 <1> push eax ; 2772 000017E3 B408 <1> mov ah, 08h ; SENSE INTERRUPT STATUS COMMAND 2773 000017E5 E848050000 <1> call NEC_OUTPUT 2774 000017EA 58 <1> pop eax ; THROW AWAY ERROR RETURN 2775 000017EB E87B060000 <1> call RESULTS ; READ IN THE RESULTS 2776 <1> ; 24/12/2021 2777 000017F0 59 <1> pop ecx ; RESTORE AFTER CALL 2778 000017F1 721D <1> jc short DR_ERR ; ERROR RETURN 2779 000017F3 3A0D[BD610000] <1> cmp cl, [NEC_STATUS] ; TEST FOR DRIVE READY TRANSITION 2780 000017F9 7515 <1> jnz short DR_ERR ; EVERYTHING OK 2781 000017FB FEC1 <1> inc cl ; NEXT EXPECTED @NEC_STATUS 2782 000017FD 80F9C3 <1> cmp cl, 11000011b ; ALL POSSIBLE DRIVES CLEARED 2783 00001800 76DA <1> jbe short NXT_DRV ; FALL THRU IF 11000100B OR > 2784 <1> ; 2785 00001802 E82F000000 <1> call SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 2786 <1> RESBAC: 2787 00001807 E87CFFFFFF <1> call SETUP_END ; VARIOUS CLEANUPS 2788 <1> 2789 <1> ; 11/07/2022 2790 <1> ; CF = 1 -> error (error code in AH) 2791 <1> ; CF = 0 -> OK 2792 <1> 2793 <1> ;; 24/12/2021 2794 <1> ;mov ebx, esi ; GET SAVED AL TO BL 2795 <1> ;; 11/07/2022 2796 <1> ;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 2797 <1> ;rol ebx, 8 2798 <1> ; bl = function (reset = 0) 2799 <1> ; 2800 <1> ;mov al, bl ; PUT BACK FOR RETURN 2801 <1> 2802 <1> ; 11/07/2022 2803 0000180C B000 <1> mov al, 0 ; (reset function = 0) 2804 <1> 2805 0000180E C3 <1> retn 2806 <1> 2807 <1> DR_POP_ERR: 2808 <1> ; 24/12/2021 2809 0000180F 59 <1> pop ecx ; CLEAR STACK 2810 <1> DR_ERR: 2811 00001810 800D[BC610000]20 <1> or byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE 2812 00001817 EBEE <1> jmp short RESBAC ; RETURN FROM RESET 2813 <1> 2814 <1> ;------------------------------------------------------------------------------- 2815 <1> ; FNC_ERR 2816 <1> ; INVALID FUNCTION REQUESTED OR INVALID DRIVE: 2817 <1> ; SET BAD COMMAND IN STATUS. 2818 <1> ; 2819 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2820 <1> ;------------------------------------------------------------------------------- 2821 <1> 2822 <1> ; 11/07/2022 - not needed (because diskio is used by kernel only) 2823 <1> 2824 <1> ;FNC_ERR: ; INVALID FUNCTION REQUEST 2825 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2826 <1> ; ; 24/12/2021 2827 <1> ; mov eax, esi ; RESTORE AL 2828 <1> ; mov ah, BAD_CMD ; SET BAD COMMAND ERROR 2829 <1> ; mov [DSKETTE_STATUS], ah ; STORE IN DATA AREA 2830 <1> ; stc ; SET CARRY INDICATING ERROR 2831 <1> ; retn 2832 <1> 2833 <1> 2834 <1> ;---------------------------------------------------------------- 2835 <1> ; DR_TYPE_CHECK : 2836 <1> ; CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL) : 2837 <1> ; IS SUPPORTED IN BIOS DRIVE TYPE TABLE : 2838 <1> ; ON ENTRY: : 2839 <1> ; AL = DRIVE TYPE : 2840 <1> ; ON EXIT: : 2841 <1> ; CY = 0 DRIVE TYPE SUPPORTED : 2842 <1> ; EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE : 2843 <1> ; CY = 1 DRIVE TYPE NOT SUPPORTED : 2844 <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 : 2845 <1> ;---------------------------------------------------------------- 2846 <1> DR_TYPE_CHECK: 2847 <1> ; 12/07/2022 2848 <1> ; 11/07/2022 2849 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2850 <1> ; 24/12/2021 2851 <1> ;push eax ; 11/07/2022 2852 <1> ;push ecx ; 08/07/2022 2853 <1> ;xor ebx,ebx ; EBX = INDEX TO DR_TYPE TABLE 2854 00001819 BB[DC5B0000] <1> mov ebx, DR_TYPE 2855 <1> ;;mov ecx, DR_CNT ; ECX = LOOP COUNT 2856 <1> ;mov cl, DR_CNT 2857 0000181E B406 <1> mov ah, DR_CNT ; 11/07/2022 2858 <1> TYPE_CHK: 2859 <1> ;;mov ah, [DR_TYPE+ebx] ; GET DRIVE TYPE 2860 <1> ;mov ah, [ebx] 2861 <1> ;cmp al, ah ; DRIVE TYPE MATCH? 2862 00001820 3A03 <1> cmp al, [ebx] ; 11/07/2022 2863 00001822 740E <1> je short DR_TYPE_VALID ; YES, RETURN WITH CARRY RESET 2864 <1> ; 16/02/2015 (32 bit address modification) 2865 00001824 83C305 <1> add ebx, 5 ; CHECK NEXT DRIVE TYPE 2866 <1> ;loop TYPE_CHK 2867 <1> ;dec cl 2868 00001827 FECC <1> dec ah ; 11/07/2022 2869 00001829 75F5 <1> jnz short TYPE_CHK 2870 <1> ; 2871 0000182B BB[3B5C0000] <1> mov ebx, MD_TBL6 ; 1.44MB fd parameter table 2872 <1> ; Default for GET_PARM (11/12/2014) 2873 <1> ; 2874 00001830 F9 <1> stc ; DRIVE TYPE NOT FOUND IN TABLE 2875 <1> ;jmp short TYPE_RTN 2876 <1> ; 12/07/2022 2877 00001831 C3 <1> retn 2878 <1> DR_TYPE_VALID: 2879 <1> ;mov ebx, [DR_TYPE+ebx+1] ; EBX = MEDIA TABLE 2880 00001832 43 <1> inc ebx 2881 00001833 8B1B <1> mov ebx, [ebx] 2882 <1> TYPE_RTN: 2883 <1> ;pop ecx ; 08/07/2022 2884 <1> ; 24/12/2021 2885 <1> ;pop eax ; 11/07/2022 2886 00001835 C3 <1> retn 2887 <1> 2888 <1> ;---------------------------------------------------------------- 2889 <1> ; SEND_SPEC : 2890 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 2891 <1> ; THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER : 2892 <1> ; ON ENTRY: @DISK_POINTER = DRIVE PARAMETER TABLE : 2893 <1> ; ON EXIT: NONE : 2894 <1> ; REGISTERS ALTERED: ECX, EDX : 2895 <1> ;---------------------------------------------------------------- 2896 <1> SEND_SPEC: 2897 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2898 00001836 50 <1> push eax ; SAVE EAX 2899 00001837 B8[5D180000] <1> mov eax, SPECBAC ; LOAD ERROR ADDRESS 2900 0000183C 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 2901 0000183D B403 <1> mov ah, 03h ; SPECIFY COMMAND 2902 0000183F E8EE040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2903 <1> ;sub dl, dl ; FIRST SPECIFY BYTE 2904 00001844 28C0 <1> sub al, al ; 08/07/2022 2905 00001846 E8F6030000 <1> call GET_PARM ; GET PARAMETER TO AH 2906 0000184B E8E2040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2907 <1> ;mov dl, 1 ; SECOND SPECIFY BYTE 2908 00001850 B001 <1> mov al, 1 ; 08/07/2022 2909 00001852 E8EA030000 <1> call GET_PARM ; GET PARAMETER TO AH 2910 00001857 E8D6040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2911 0000185C 58 <1> pop eax ; POP ERROR RETURN 2912 <1> SPECBAC: 2913 0000185D 58 <1> pop eax ; RESTORE ORIGINAL EAX VALUE 2914 0000185E C3 <1> retn 2915 <1> 2916 <1> ;---------------------------------------------------------------- 2917 <1> ; SEND_SPEC_MD : 2918 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 2919 <1> ; THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX) : 2920 <1> ; ON ENTRY: CS:BX = MEDIA/DRIVE PARAMETER TABLE : 2921 <1> ; ON EXIT: NONE : 2922 <1> ; REGISTERS ALTERED: AX : 2923 <1> ;---------------------------------------------------------------- 2924 <1> SEND_SPEC_MD: 2925 0000185F 50 <1> PUSH eAX ; SAVE RATE DATA 2926 00001860 B8[7D180000] <1> MOV eAX, SPEC_ESBAC ; LOAD ERROR ADDRESS 2927 00001865 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 2928 00001866 B403 <1> MOV AH,03H ; SPECIFY COMMAND 2929 00001868 E8C5040000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 2930 0000186D 8A23 <1> MOV AH, [eBX+MD.SPEC1] ; GET 1ST SPECIFY BYTE 2931 0000186F E8BE040000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 2932 00001874 8A6301 <1> MOV AH, [eBX+MD.SPEC2] ; GET SECOND SPECIFY BYTE 2933 00001877 E8B6040000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 2934 0000187C 58 <1> POP eAX ; POP ERROR RETURN 2935 <1> SPEC_ESBAC: 2936 0000187D 58 <1> POP eAX ; RESTORE ORIGINAL AX VALUE 2937 0000187E C3 <1> RETn 2938 <1> 2939 <1> ;------------------------------------------------------------------------------- 2940 <1> ; XLAT_NEW 2941 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE 2942 <1> ; MODE TO NEW ARCHITECTURE. 2943 <1> ; 2944 <1> ; ON ENTRY: EDI = DRIVE # 2945 <1> ;------------------------------------------------------------------------------- 2946 <1> XLAT_NEW: 2947 <1> ; 11/07/2022 2948 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2949 <1> ;cmp edi, 1 ; VALID DRIVE 2950 <1> ;ja short XN_OUT ; IF INVALID BACK 2951 <1> ; 2952 0000187F 80BF[C7610000]00 <1> cmp byte [DSK_STATE+edi], 0 ; NO DRIVE ? 2953 00001886 7401 <1> jz short DO_DET ; IF NO DRIVE ATTEMPT DETERMINE 2954 <1> ; 2955 <1> ;mov al, [HF_CNTRL] ; DRIVE INFORMATION 2956 <1> ;mov ecx, edi ; ECX = DRIVE NUMBER 2957 <1> ;or cl, cl 2958 <1> ;jz short XN_0 ; 08/07/2022 2959 <1> ;shl cl, 2 ; CL = SHIFT COUNT, A=0, B=4 2960 <1> ;;mov al, [HF_CNTRL] ; DRIVE INFORMATION 2961 <1> ;ror al, cl ; TO LOW NIBBLE 2962 <1> ;XN_0: 2963 <1> ;and al, DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 2964 <1> ;and byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA) 2965 <1> ;or [DSK_STATE+edi], al ; UPDATE DRIVE STATE 2966 <1> XN_OUT: 2967 00001888 C3 <1> retn 2968 <1> DO_DET: 2969 <1> ;;call DRIVE_DET ; TRY TO DETERMINE 2970 <1> ;;retn 2971 <1> ;jmp DRIVE_DET 2972 <1> 2973 <1> ;------------------------------------------------------------------------------- 2974 <1> ; DRIVE_DET 2975 <1> ; DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND 2976 <1> ; UPDATES STATE INFORMATION ACCORDINGLY. 2977 <1> ; ON ENTRY: EDI = DRIVE # 2978 <1> ;------------------------------------------------------------------------------- 2979 <1> DRIVE_DET: 2980 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2981 00001889 E8EE030000 <1> call MOTOR_ON ; TURN ON MOTOR IF NOT ALREADY ON 2982 0000188E E857050000 <1> call RECAL ; RECALIBRATE DRIVE 2983 00001893 724E <1> jc short DD_BAC ; ASSUME NO DRIVE PRESENT 2984 00001895 B530 <1> mov ch, TRK_SLAP ; SEEK TO TRACK 48 2985 00001897 E8CF040000 <1> call SEEK 2986 0000189C 7245 <1> jc short DD_BAC ; ERROR NO DRIVE 2987 0000189E B50B <1> mov ch, QUIET_SEEK+1 ; SEEK TO TRACK 10 2988 <1> SK_GIN: 2989 000018A0 FECD <1> dec ch ; DECREMENT TO NEXT TRACK 2990 <1> ;push cx 2991 <1> ; 24/12/2021 2992 000018A2 51 <1> push ecx ; SAVE TRACK 2993 000018A3 E8C3040000 <1> call SEEK 2994 000018A8 723A <1> jc short POP_BAC ; POP AND RETURN 2995 000018AA B8[E4180000] <1> mov eax, POP_BAC ; LOAD NEC OUTPUT ERROR ADDRESS 2996 000018AF 50 <1> push eax 2997 000018B0 B404 <1> mov ah, SENSE_DRV_ST ; SENSE DRIVE STATUS COMMAND BYTE 2998 000018B2 E87B040000 <1> call NEC_OUTPUT ; OUTPUT TO NEC 2999 <1> ; 08/07/2022 3000 000018B7 89F8 <1> mov eax, edi ; AL = DRIVE 3001 000018B9 88C4 <1> mov ah, al ; AH = DRIVE 3002 000018BB E872040000 <1> call NEC_OUTPUT ; OUTPUT TO NEC 3003 000018C0 E8A6050000 <1> call RESULTS ; GO GET STATUS 3004 000018C5 58 <1> pop eax ; THROW AWAY ERROR ADDRESS 3005 <1> ;pop cx ; RESTORE TRACK 3006 <1> ; 24/12/2021 3007 000018C6 59 <1> pop ecx 3008 000018C7 F605[BD610000]10 <1> test byte [NEC_STATUS], HOME ; TRACK 0 ? 3009 000018CE 74D0 <1> jz short SK_GIN ; GO TILL TRACK 0 3010 000018D0 08ED <1> or ch, ch ; IS HOME AT TRACK 0 3011 000018D2 7408 <1> jz short IS_80 ; MUST BE 80 TRACK DRIVE 3012 <1> 3013 <1> ; DRIVE IS A 360; SET DRIVE TO DETERMINED; 3014 <1> ; SET MEDIA TO DETERMINED AT RATE 250. 3015 <1> 3016 000018D4 808F[C7610000]94 <1> or byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250 3017 000018DB C3 <1> retn ; ALL INFORMATION SET 3018 <1> IS_80: 3019 000018DC 808F[C7610000]01 <1> or byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY 3020 <1> DD_BAC: 3021 000018E3 C3 <1> retn 3022 <1> POP_BAC: 3023 <1> ;pop cx ; THROW AWAY 3024 <1> ; 24/12/2021 3025 000018E4 59 <1> pop ecx 3026 000018E5 C3 <1> retn 3027 <1> 3028 <1> ;------------------------------------------------------------------------------- 3029 <1> ; SETUP_STATE: INITIALIZES START AND END RATES. 3030 <1> ;------------------------------------------------------------------------------- 3031 <1> SETUP_STATE: 3032 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3033 000018E6 F687[C7610000]10 <1> test byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ? 3034 000018ED 7537 <1> jnz short J1C ; NO STATES IF DETERMINED 3035 000018EF 66B84000 <1> mov ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE 3036 000018F3 F687[C7610000]04 <1> test byte [DSK_STATE+edi], DRV_DET ; DRIVE ? 3037 000018FA 740D <1> jz short AX_SET ; DO NOT KNOW DRIVE 3038 000018FC F687[C7610000]02 <1> test byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE? 3039 00001903 7504 <1> jnz short AX_SET ; JUMP IF YES 3040 00001905 66B88080 <1> mov ax, RATE_250*257 ; START A END RATE 250 FOR 360 DRIVE 3041 <1> AX_SET: 3042 00001909 80A7[C7610000]1F <1> and byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE 3043 00001910 08A7[C7610000] <1> or [DSK_STATE+edi], ah ; RATE FIRST TO TRY 3044 00001916 8025[C4610000]F3 <1> and byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS 3045 0000191D C0C804 <1> ror al, 4 ; TO OPERATION LAST RATE LOCATION 3046 00001920 0805[C4610000] <1> or [LASTRATE], al ; LAST RATE 3047 <1> J1C: 3048 00001926 C3 <1> retn 3049 <1> 3050 <1> ;------------------------------------------------------------------------------- 3051 <1> ; MED_CHANGE 3052 <1> ; CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 3053 <1> ; CHECKS MEDIA CHANGE AGAIN. 3054 <1> ; 3055 <1> ; ON EXIT: CY = 1 MEANS MEDIA CHANGE OR TIMEOUT 3056 <1> ; @DSKETTE_STATUS = ERROR CODE 3057 <1> ;------------------------------------------------------------------------------- 3058 <1> MED_CHANGE: 3059 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3060 00001927 E897050000 <1> call READ_DSKCHNG ; READ DISK CHANCE LINE STATE 3061 0000192C 7446 <1> jz short MC_OUT ; BYPASS HANDLING DISK CHANGE LINE 3062 0000192E 80A7[C7610000]EF <1> and byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE 3063 <1> 3064 <1> ; THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT 3065 <1> ; ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL 3066 <1> ; BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING). 3067 <1> 3068 00001935 89F9 <1> mov ecx, edi ; CL = DRIVE # 3069 00001937 B001 <1> mov al, 1 ; MOTOR ON BIT MASK 3070 00001939 D2E0 <1> shl al, cl ; TO APPROPRIATE POSITION 3071 0000193B F6D0 <1> not al ; KEEP ALL BUT MOTOR ON 3072 0000193D FA <1> cli ; NO INTERRUPTS 3073 0000193E 2005[BA610000] <1> and [MOTOR_STATUS], al ; TURN MOTOR OFF INDICATOR 3074 00001944 FB <1> sti ; INTERRUPTS ENABLED 3075 00001945 E832030000 <1> call MOTOR_ON ; TURN MOTOR ON 3076 <1> 3077 <1> ;----- THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL 3078 <1> 3079 0000194A E859FEFFFF <1> call DSK_RESET ; RESET NEC 3080 0000194F B501 <1> mov ch, 1 ; MOVE TO CYLINDER 1 3081 00001951 E815040000 <1> call SEEK ; ISSUE SEEK 3082 00001956 30ED <1> xor ch, ch ; MOVE TO CYLINDER 0 3083 00001958 E80E040000 <1> call SEEK ; ISSUE SEEK 3084 0000195D C605[BC610000]06 <1> mov byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS 3085 <1> OK1: 3086 00001964 E85A050000 <1> call READ_DSKCHNG ; CHECK MEDIA CHANGED AGAIN 3087 00001969 7407 <1> jz short OK2 ; IF ACTIVE, NO DISKETTE, TIMEOUT 3088 <1> OK4: 3089 0000196B C605[BC610000]80 <1> mov byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY 3090 <1> OK2: 3091 00001972 F9 <1> stc ; MEDIA CHANGED, SET CY 3092 00001973 C3 <1> retn 3093 <1> MC_OUT: 3094 <1> ;clc ; 08/07/2022 ; NO MEDIA CHANGED, CLEAR CY 3095 00001974 C3 <1> retn 3096 <1> 3097 <1> ;------------------------------------------------------------------------------- 3098 <1> ; SEND_RATE 3099 <1> ; SENDS DATA RATE COMMAND TO NEC 3100 <1> ; ON ENTRY: EDI = DRIVE # 3101 <1> ; ON EXIT: NONE 3102 <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022 3103 <1> ;------------------------------------------------------------------------------- 3104 <1> SEND_RATE: 3105 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5 3106 <1> ;push ax ; SAVE REG. 3107 <1> ; 24/12/2021 3108 <1> ;push eax ; 11/07/2022 3109 00001975 8025[C4610000]3F <1> and byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED 3110 0000197C 8A87[C7610000] <1> mov al, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 3111 00001982 24C0 <1> and al, SEND_MSK ; KEEP ONLY RATE BITS 3112 00001984 0805[C4610000] <1> or [LASTRATE], al ; SAVE NEW RATE FOR NEXT CHECK 3113 0000198A C0C002 <1> rol al, 2 ; MOVE TO BIT OUTPUT POSITIONS 3114 0000198D 66BAF703 <1> mov dx, 03F7h ; OUTPUT NEW DATA RATE 3115 00001991 EE <1> out dx, al 3116 <1> ;pop ax ; RESTORE REG. 3117 <1> ; 24/12/2021 3118 <1> ;pop eax ; 11/07/2022 3119 00001992 C3 <1> retn 3120 <1> 3121 <1> ;------------------------------------------------------------------------------- 3122 <1> ; CHK_LASTRATE 3123 <1> ; CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER. 3124 <1> ; ON ENTRY: 3125 <1> ; EDI = DRIVE # 3126 <1> ; ON EXIT: 3127 <1> ; ZF = 1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC 3128 <1> ; ZF = 0 DATA RATE IS DIFFERENT FROM LAST RATE 3129 <1> ; REGISTERS ALTERED: EAX ; 11/07/2022 3130 <1> ;------------------------------------------------------------------------------- 3131 <1> CHK_LASTRATE: 3132 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3133 <1> ;push ax ; SAVE REG. 3134 <1> ; 24/12/2021 3135 <1> ;push eax ; 11/07/2022 3136 00001993 8A25[C4610000] <1> mov ah, [LASTRATE] ; 08/07/2022 (BugFix) 3137 <1> ; GET LAST DATA RATE SELECTED 3138 00001999 8A87[C7610000] <1> mov al, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 3139 0000199F 6625C0C0 <1> and ax, SEND_MSK*257 ; KEEP ONLY RATE BITS OF BOTH 3140 000019A3 38E0 <1> cmp al, ah ; COMPARE TO PREVIOUSLY TRIED 3141 <1> ; ZF = 1 RATE IS THE SAME 3142 <1> ;pop ax ; RESTORE REG. 3143 <1> ; 24/12/2021 3144 <1> ;pop eax ; 11/07/2022 3145 000019A5 C3 <1> retn 3146 <1> 3147 <1> ;------------------------------------------------------------------------------- 3148 <1> ; DMA_SETUP 3149 <1> ; THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS. 3150 <1> ; 3151 <1> ; ON ENTRY: AL = DMA COMMAND 3152 <1> ; 3153 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3154 <1> ;------------------------------------------------------------------------------- 3155 <1> 3156 <1> ; SI = Head #, # of Sectors or DASD Type 3157 <1> 3158 <1> ; 22/08/2015 3159 <1> ; 08/02/2015 - Protected Mode Modification 3160 <1> ; 06/02/2015 - 07/02/2015 3161 <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit). 3162 <1> ; (DMA Addres = Physical Address) 3163 <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address) 3164 <1> ; 3165 <1> ; 04/02/2016 (clc) 3166 <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP) 3167 <1> ; 16/12/2014 (IODELAY) 3168 <1> 3169 <1> DMA_SETUP: 3170 <1> ; 18/07/2022 3171 <1> ; 11/07/2022 3172 <1> ; ebp = buffer address 3173 <1> 3174 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3175 <1> ;; 20/02/2015 3176 <1> ;mov edx, [ebp+4] ; 11/07/2022 ; Buffer address 3177 <1> ; 08/07/2022 - not needed for Retro UNIX 386 v1.1 3178 <1> ;test edx, 0FF000000h ; 16 MB limit (22/08/2015, bugfix) 3179 <1> ;jnz short dma_bnd_err_stc 3180 <1> 3181 <1> ; al = dma command 3182 <1> 3183 <1> ; ; 18/07/2022 3184 <1> ; ; (512 bytes/sector only!) 3185 <1> ; ; 24/12/2021 3186 <1> ; push eax ; DMA command 3187 <1> ; ;push edx ; 11/07/2022 ; * 3188 <1> ; ;mov dl, 3 ; GET BYTES/SECTOR PARAMETER 3189 <1> ; mov al, 3 ; 08/07/2022 3190 <1> ; call GET_PARM ; 3191 <1> ; mov cl, ah ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 3192 <1> ; ;mov ax, si ; Sector count 3193 <1> ; ;mov ah, al ; AH = # OF SECTORS 3194 <1> ; ;sub al, al ; AL = 0, AX = # SECTORS * 256 3195 <1> ; ;shr ax, 1 ; AX = # SECTORS * 128 3196 <1> ; ;shl ax, cl ; SHIFT BY PARAMETER VALUE 3197 <1> ; ; 08/07/2022 3198 <1> ; ; 24/12/2021 3199 <1> ; ;mov edx, esi 3200 <1> ; sub eax, eax 3201 <1> ; ;mov ah, dl 3202 <1> ; ;shr eax, 1 3203 <1> ; mov al, 128 3204 <1> ; shl eax, cl 3205 <1> ; ; 3206 <1> ; dec eax ; -1 FOR DMA VALUE 3207 <1> ; mov ecx, eax 3208 <1> ; ;pop edx ; 11/07/2022 ; * 3209 <1> ; ; 24/12/2021 3210 <1> ; pop eax 3211 <1> 3212 <1> ; 08/07/2022 3213 <1> ;cmp al, 42h 3214 <1> ;jne short NOT_VERF 3215 <1> ;mov edx, 0FF0000h 3216 <1> ;jmp short J33 3217 <1> ;NOT_VERF: 3218 <1> ; 11/07/2022 3219 000019A6 89EA <1> mov edx, ebp 3220 <1> ; 3221 <1> ;add dx, cx ; check for (64K) overflow 3222 <1> ; 18/07/2022 3223 <1> ; (512 bytes/sector) 3224 000019A8 6681C2FF01 <1> add dx, 511 3225 000019AD 7239 <1> jc short dma_bnd_err 3226 <1> ; 3227 <1> ;sub dx, cx ; 11/07/2022 ; Restore start address 3228 <1> J33: 3229 <1> ; 08/07/2022 3230 000019AF FA <1> cli ; DISABLE INTERRUPTS DURING DMA SET-UP 3231 000019B0 E60C <1> out DMA+12, al ; SET THE FIRST/LAST F/F 3232 <1> IODELAY ; WAIT FOR I/O 2130 000019B2 EB00 <2> jmp short $+2 2131 000019B4 EB00 <2> jmp short $+2 3233 000019B6 E60B <1> out DMA+11, al ; OUTPUT THE MODE BYTE 3234 <1> ;mov eax, edx ; Buffer address 3235 <1> ; 11/07/2022 3236 000019B8 89E8 <1> mov eax, ebp ; buffer address 3237 000019BA E604 <1> out DMA+4, al ; OUTPUT LOW ADDRESS 3238 <1> IODELAY ; WAIT FOR I/O 2130 000019BC EB00 <2> jmp short $+2 2131 000019BE EB00 <2> jmp short $+2 3239 000019C0 88E0 <1> mov al, ah 3240 000019C2 E604 <1> out DMA+4, al ; OUTPUT HIGH ADDRESS 3241 000019C4 C1E810 <1> shr eax, 16 3242 <1> IODELAY ; I/O WAIT STATE 2130 000019C7 EB00 <2> jmp short $+2 2131 000019C9 EB00 <2> jmp short $+2 3243 000019CB E681 <1> out 081h, al ; OUTPUT highest BITS TO PAGE REGISTER 3244 <1> IODELAY 2130 000019CD EB00 <2> jmp short $+2 2131 000019CF EB00 <2> jmp short $+2 3245 <1> ;;mov ax, cx ; Byte count - 1 3246 <1> ;mov al, cl 3247 <1> ; 18/07/2022 3248 <1> ; (Byte count - 1 = 511) 3249 000019D1 B0FF <1> mov al, 0FFh ; 511-256 3250 000019D3 E605 <1> out DMA+5, al ; LOW BYTE OF COUNT 3251 <1> IODELAY ; WAIT FOR I/O 2130 000019D5 EB00 <2> jmp short $+2 2131 000019D7 EB00 <2> jmp short $+2 3252 <1> ;;mov al, ah 3253 <1> ;mov al, ch 3254 <1> ; 18/07/2022 3255 000019D9 B001 <1> mov al, 1 ; 256 3256 000019DB E605 <1> out DMA+5, al ; HIGH BYTE OF COUNT 3257 <1> IODELAY 2130 000019DD EB00 <2> jmp short $+2 2131 000019DF EB00 <2> jmp short $+2 3258 000019E1 FB <1> sti ; RE-ENABLE INTERRUPTS 3259 000019E2 B002 <1> mov al, 2 ; MODE FOR 8237 3260 000019E4 E60A <1> out DMA+10, al ; INITIALIZE THE DISKETTE CHANNEL 3261 <1> 3262 000019E6 F8 <1> clc ; 04/02/2016 3263 <1> 3264 000019E7 C3 <1> retn 3265 <1> 3266 <1> ; 18/07/2022 3267 <1> ;dma_bnd_err_stc: 3268 <1> ; stc 3269 <1> 3270 <1> dma_bnd_err: 3271 000019E8 C605[BC610000]09 <1> mov byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 3272 000019EF C3 <1> retn ; CY SET BY ABOVE IF ERROR 3273 <1> 3274 <1> ;------------------------------------------------------------------------------- 3275 <1> ; NEC_INIT 3276 <1> ; THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES 3277 <1> ; THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION. 3278 <1> ; 3279 <1> ; ON ENTRY: AH = NEC COMMAND TO BE PERFORMED 3280 <1> ; 3281 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3282 <1> ;------------------------------------------------------------------------------- 3283 <1> NEC_INIT: 3284 <1> ; 11/07/2022 3285 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3286 <1> ;push ax ; SAVE NEC COMMAND 3287 <1> ; 24/12/2021 3288 000019F0 50 <1> push eax 3289 000019F1 E886020000 <1> call MOTOR_ON ; TURN MOTOR ON FOR SPECIFIC DRIVE 3290 <1> 3291 <1> ;----- DO THE SEEK OPERATION 3292 <1> 3293 <1> ;mov ch, [ebp+1] ; CH = TRACK # 3294 <1> ; 11/07/2022 3295 000019F6 89F1 <1> mov ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector 3296 000019F8 C1E908 <1> shr ecx, 8 3297 <1> ; ch = track # 3298 <1> 3299 000019FB E86B030000 <1> call SEEK ; MOVE TO CORRECT TRACK 3300 <1> ;pop ax ; RECOVER COMMAND 3301 <1> ; 24/12/2021 3302 00001A00 58 <1> pop eax 3303 00001A01 721D <1> jc short ER_1 ; ERROR ON SEEK 3304 00001A03 BB[201A0000] <1> mov ebx, ER_1 ; LOAD ERROR ADDRESS 3305 00001A08 53 <1> push ebx ; PUSH NEC_OUT ERROR RETURN 3306 <1> 3307 <1> ;----- SEND OUT THE PARAMETERS TO THE CONTROLLER 3308 <1> 3309 00001A09 E824030000 <1> call NEC_OUTPUT ; OUTPUT THE OPERATION COMMAND 3310 00001A0E 89F0 <1> mov eax, esi ; AH = HEAD # 3311 00001A10 89FB <1> mov ebx, edi ; BL = DRIVE # 3312 00001A12 C0E402 <1> sal ah, 2 ; MOVE IT TO BIT 2 3313 00001A15 80E404 <1> and ah, 00000100b ; ISOLATE THAT BIT 3314 00001A18 08DC <1> or ah, bl ; OR IN THE DRIVE NUMBER 3315 00001A1A E813030000 <1> call NEC_OUTPUT ; FALL THRU CY SET IF ERROR 3316 00001A1F 5B <1> pop ebx ; THROW AWAY ERROR RETURN 3317 <1> ER_1: 3318 00001A20 C3 <1> retn 3319 <1> 3320 <1> ;------------------------------------------------------------------------------- 3321 <1> ; RWV_COM 3322 <1> ; THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 3323 <1> ; READ/WRITE/VERIFY OPERATIONS. 3324 <1> ; 3325 <1> ; ON ENTRY: EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE 3326 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3327 <1> ;------------------------------------------------------------------------------- 3328 <1> RWV_COM: 3329 <1> ; 11/07/2022 3330 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3331 00001A21 B8[6E1A0000] <1> mov eax, ER_2 ; LOAD ERROR ADDRESS 3332 00001A26 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 3333 <1> ;mov ah, [ebp+1] ; OUTPUT TRACK # 3334 <1> ; 11/07/2022 3335 00001A27 89F0 <1> mov eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track 3336 00001A29 C1E808 <1> shr eax, 8 3337 <1> ; ah = track # 3338 00001A2C E801030000 <1> call NEC_OUTPUT 3339 00001A31 89F0 <1> mov eax, esi ; OUTPUT HEAD # 3340 <1> ; ah = head # 3341 00001A33 E8FA020000 <1> call NEC_OUTPUT 3342 <1> ;mov ah, [ebp] ; OUTPUT SECTOR # 3343 00001A38 89F0 <1> mov eax, esi 3344 00001A3A 88C4 <1> mov ah, al 3345 <1> ; ah = sector # 3346 00001A3C E8F1020000 <1> CALL NEC_OUTPUT 3347 <1> ;mov dl, 3 ; BYTES/SECTOR PARAMETER FROM BLOCK 3348 00001A41 B003 <1> mov al, 3 ; 08/07/2022 3349 00001A43 E8F9010000 <1> call GET_PARM ; .. TO THE NEC 3350 00001A48 E8E5020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 3351 <1> ;mov dl, 4 ; EOT PARAMETER FROM BLOCK 3352 00001A4D B004 <1> mov al, 4 ; 08/07/2022 3353 00001A4F E8ED010000 <1> call GET_PARM ; .. TO THE NEC 3354 00001A54 E8D9020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 3355 00001A59 8A6305 <1> mov ah, [ebx+MD.GAP] ; GET GAP LENGTH 3356 <1> _R15: 3357 00001A5C E8D1020000 <1> call NEC_OUTPUT 3358 <1> ;mov dl, 6 ; DTL PARAMETER PROM BLOCK 3359 00001A61 B006 <1> mov al, 6 ; 08/07/2022 3360 00001A63 E8D9010000 <1> call GET_PARM ; .. TO THE NEC 3361 00001A68 E8C5020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 3362 00001A6D 58 <1> pop eax ; THROW AWAY ERROR EXIT 3363 <1> ER_2: 3364 00001A6E C3 <1> retn 3365 <1> 3366 <1> ;------------------------------------------------------------------------------- 3367 <1> ; NEC_TERM 3368 <1> ; THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 3369 <1> ; FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION. 3370 <1> ; 3371 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3372 <1> ;------------------------------------------------------------------------------- 3373 <1> 3374 <1> NEC_TERM: 3375 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3376 <1> 3377 <1> ;----- LET THE OPERATION HAPPEN 3378 <1> 3379 00001A6F 56 <1> push esi ; SAVE HEAD #, # OF SECTORS 3380 00001A70 E8C7030000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 3381 00001A75 9C <1> pushfd ; 24/12/2021 3382 00001A76 E8F0030000 <1> call RESULTS ; GET THE NEC STATUS 3383 00001A7B 724B <1> jc short SET_END_POP 3384 00001A7D 9D <1> popfd ; 24/12/2021 3385 00001A7E 723E <1> jc short SET_END ; LOOK FOR ERROR 3386 <1> 3387 <1> ;----- CHECK THE RESULTS RETURNED BY THE CONTROLLER 3388 <1> 3389 00001A80 FC <1> cld ; SET THE CORRECT DIRECTION 3390 00001A81 BE[BD610000] <1> mov esi, NEC_STATUS ; POINT TO STATUS FIELD 3391 00001A86 AC <1> lodsb ; GET ST0 3392 00001A87 24C0 <1> and al, 11000000b ; TEST FOR NORMAL TERMINATION 3393 00001A89 7433 <1> jz short SET_END 3394 00001A8B 3C40 <1> cmp al, 01000000b ; TEST FOR ABNORMAL TERMINATION 3395 00001A8D 7527 <1> jnz short J18 ; NOT ABNORMAL, BAD NEC 3396 <1> 3397 <1> ;----- ABNORMAL TERMINATION, FIND OUT WHY 3398 <1> 3399 00001A8F AC <1> lodsb ; GET ST1 3400 00001A90 D0E0 <1> sal al, 1 ; TEST FOR EDT FOUND 3401 00001A92 B404 <1> mov ah, RECORD_NOT_FND 3402 00001A94 7222 <1> jc short J19 3403 00001A96 C0E002 <1> sal al, 2 3404 00001A99 B410 <1> mov ah, BAD_CRC 3405 00001A9B 721B <1> jc short J19 3406 00001A9D D0E0 <1> sal al, 1 ; TEST FOR DMA OVERRUN 3407 00001A9F B408 <1> mov ah, BAD_DMA 3408 00001AA1 7215 <1> jc short J19 3409 00001AA3 C0E002 <1> sal al, 2 ; TEST FOR RECORD NOT FOUND 3410 00001AA6 B404 <1> mov ah, RECORD_NOT_FND 3411 00001AA8 720E <1> jc short J19 3412 00001AAA D0E0 <1> sal al, 1 3413 00001AAC B403 <1> mov ah, WRITE_PROTECT ; TEST FOR WRITE_PROTECT 3414 00001AAE 7208 <1> jc short J19 3415 00001AB0 D0E0 <1> sal al, 1 ; TEST MISSING ADDRESS MARK 3416 00001AB2 B402 <1> mov ah, BAD_ADDR_MARK 3417 00001AB4 7202 <1> jc short J19 3418 <1> 3419 <1> ;----- NEC MUST HAVE FAILED 3420 <1> J18: 3421 00001AB6 B420 <1> mov ah, BAD_NEC 3422 <1> J19: 3423 00001AB8 0825[BC610000] <1> or [DSKETTE_STATUS], ah 3424 <1> SET_END: 3425 00001ABE 803D[BC610000]01 <1> cmp byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION 3426 00001AC5 F5 <1> cmc 3427 00001AC6 5E <1> pop esi 3428 00001AC7 C3 <1> retn ; RESTORE HEAD #, # OF SECTORS 3429 <1> 3430 <1> SET_END_POP: 3431 00001AC8 9D <1> popfd ; 24/12/2021 3432 00001AC9 EBF3 <1> jmp short SET_END 3433 <1> 3434 <1> ;------------------------------------------------------------------------------- 3435 <1> ; DSTATE: ESTABLISH STATE UPON SUCCESSFUL OPERATION. 3436 <1> ;------------------------------------------------------------------------------- 3437 <1> DSTATE: 3438 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3439 00001ACB 803D[BC610000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR 3440 00001AD2 753E <1> jne short SETBAC ; IF ERROR JUMP 3441 00001AD4 808F[C7610000]10 <1> or byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED 3442 00001ADB F687[C7610000]04 <1> test byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ? 3443 00001AE2 752E <1> jnz short SETBAC ; IF DETERMINED NO TRY TO DETERMINE 3444 00001AE4 8A87[C7610000] <1> mov al, [DSK_STATE+edi] ; LOAD STATE 3445 00001AEA 24C0 <1> and al, RATE_MSK ; KEEP ONLY RATE 3446 00001AEC 3C80 <1> cmp al, RATE_250 ; RATE 250 ? 3447 00001AEE 751B <1> jne short M_12 ; NO, MUST BE 1.2M OR 1.44M DRIVE 3448 <1> 3449 <1> ;----- CHECK IF IT IS 1.44M 3450 <1> 3451 00001AF0 E843010000 <1> call CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 3452 <1> ;;20/02/2015 3453 <1> ;;jc short M_12 ; CMOS BAD 3454 00001AF5 7414 <1> jz short M_12 ;; 20/02/2015 3455 00001AF7 3C04 <1> cmp al, 4 ; 1.44MB DRIVE ? 3456 00001AF9 7410 <1> je short M_12 ; YES 3457 <1> M_720: 3458 00001AFB 80A7[C7610000]FD <1> and byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY 3459 00001B02 808F[C7610000]04 <1> or byte [DSK_STATE+edi], DRV_DET ; MARK DRIVE DETERMINED 3460 00001B09 EB07 <1> jmp short SETBAC ; BACK 3461 <1> M_12: 3462 00001B0B 808F[C7610000]06 <1> or byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 3463 <1> ; TURN ON DETERMINED & FMT CAPA 3464 <1> SETBAC: 3465 00001B12 C3 <1> retn 3466 <1> 3467 <1> ;------------------------------------------------------------------------------- 3468 <1> ; RETRY 3469 <1> ; DETERMINES WHETHER A RETRY IS NECESSARY. 3470 <1> ; IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY. 3471 <1> ; 3472 <1> ; ON EXIT: CY = 1 FOR RETRY, CY = 0 FOR NO RETRY 3473 <1> ;------------------------------------------------------------------------------- 3474 <1> RETRY: 3475 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3476 00001B13 803D[BC610000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION 3477 00001B1A 7444 <1> je short NO_RETRY ; SUCCESSFUL OPERATION 3478 00001B1C 803D[BC610000]80 <1> cmp byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY 3479 00001B23 743B <1> je short NO_RETRY 3480 00001B25 8AA7[C7610000] <1> mov ah, [DSK_STATE+edi] ; GET MEDIA STATE OF DRIVE 3481 00001B2B F6C410 <1> test ah, MED_DET ; ESTABLISHED/DETERMINED ? 3482 00001B2E 7530 <1> jnz short NO_RETRY ; IF ESTABLISHED STATE THEN TRUE ERROR 3483 00001B30 80E4C0 <1> and ah, RATE_MSK ; ISOLATE RATE 3484 00001B33 8A2D[C4610000] <1> mov ch, [LASTRATE] ; GET START OPERATION STATE 3485 00001B39 C0C504 <1> rol ch, 4 ; TO CORRESPONDING BITS 3486 00001B3C 80E5C0 <1> and ch, RATE_MSK ; ISOLATE RATE BITS 3487 00001B3F 38E5 <1> cmp ch, ah ; ALL RATES TRIED 3488 00001B41 741D <1> je short NO_RETRY ; IF YES, THEN TRUE ERROR 3489 <1> 3490 <1> ; SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE 3491 <1> ; 00000000B (500) -> 10000000B (250) 3492 <1> ; 10000000B (250) -> 01000000B (300) 3493 <1> ; 01000000B (300) -> 00000000B (500) 3494 <1> 3495 00001B43 80FC01 <1> cmp ah, RATE_500+1 ; SET CY FOR RATE 500 3496 00001B46 D0DC <1> rcr ah, 1 ; TO NEXT STATE 3497 00001B48 80E4C0 <1> and ah, RATE_MSK ; KEEP ONLY RATE BITS 3498 00001B4B 80A7[C7610000]1F <1> and byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) 3499 <1> ; RATE, DBL STEP OFF 3500 00001B52 08A7[C7610000] <1> or [DSK_STATE+edi], ah ; TURN ON NEW RATE 3501 00001B58 C605[BC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY 3502 00001B5F F9 <1> stc ; SET CARRY FOR RETRY 3503 <1> NO_RETRY: ; 08/07/2022 3504 00001B60 C3 <1> retn ; RETRY RETURN 3505 <1> 3506 <1> ;NO_RETRY: 3507 <1> ;clc ; CLEAR CARRY NO RETRY 3508 <1> ;RETn ; NO RETRY RETURN 3509 <1> 3510 <1> ;------------------------------------------------------------------------------- 3511 <1> ; NUM_TRANS 3512 <1> ; THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE 3513 <1> ; ACTUALLY TRANSFERRED TO/FROM THE DISKETTE. 3514 <1> ; 3515 <1> ; ON ENTRY: [BP+1] = TRACK 3516 <1> ; SI-HI = HEAD 3517 <1> ; [BP] = START SECTOR 3518 <1> ; 3519 <1> ; ON EXIT: AL = NUMBER ACTUALLY TRANSFERRED 3520 <1> ;------------------------------------------------------------------------------- 3521 <1> NUM_TRANS: 3522 <1> ; 11/07/2022 3523 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3524 00001B61 30C0 <1> xor al, al ; CLEAR FOR ERROR 3525 00001B63 803D[BC610000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR 3526 <1> ; 24/12/2021 3527 00001B6A 7529 <1> jne short NT_OUT ; IF ERROR 0 TRANSFERRED 3528 <1> ;mov dl, 4 ; SECTORS/TRACK OFFSET TO DL 3529 00001B6C B004 <1> mov al, 4 ; 08/07/2022 3530 00001B6E E8CE000000 <1> call GET_PARM ; AH = SECTORS/TRACK 3531 <1> ;mov bl, [NEC_STATUS+5] ; GET ENDING SECTOR 3532 00001B73 A0[C2610000] <1> mov al, [NEC_STATUS+5] 3533 00001B78 89F1 <1> mov ecx, esi ; CH = HEAD # STARTED 3534 00001B7A 88CB <1> mov bl, cl ; 11/07/2022 ; sector # 3535 00001B7C 3A2D[C1610000] <1> cmp ch, [NEC_STATUS+4] ; GET HEAD ENDED UP ON 3536 00001B82 750D <1> jne short DIF_HD ; IF ON SAME HEAD, THEN NO ADJUST 3537 <1> ; 11/07/2022 3538 <1> ;mov ch, [NEC_STATUS+3] ; GET TRACK ENDED UP ON 3539 <1> ;cmp ch, [ebp+1] ; IS IT ASKED FOR TRACK 3540 <1> ;jz short SAME_TR ; IF SAME TRACK NO INCREASE 3541 00001B84 C1E908 <1> shr ecx, 8 ; byte 3 = track # --> byte 2 3542 00001B87 3A2D[C0610000] <1> cmp ch, [NEC_STATUS+3] 3543 00001B8D 7404 <1> je short SAME_TRK 3544 <1> ; 11/07/2022 3545 <1> ;add bl, ah ; ADD SECTORS/TRACK 3546 00001B8F 00E0 <1> add al, ah 3547 <1> DIF_HD: 3548 <1> ;add bl, ah ; ADD SECTORS/TRACK 3549 00001B91 00E0 <1> add al, ah 3550 <1> SAME_TRK: 3551 <1> ;sub bl, [ebp] ; SUBTRACT START FROM END 3552 <1> ;mov al, bl ; TO AL 3553 00001B93 28D8 <1> sub al, bl 3554 <1> NT_OUT: 3555 00001B95 C3 <1> retn 3556 <1> 3557 <1> ;------------------------------------------------------------------------------- 3558 <1> ; SETUP_DBL 3559 <1> ; CHECK DOUBLE STEP. 3560 <1> ; 3561 <1> ; ON ENTRY : EDI = DRIVE # 3562 <1> ; 3563 <1> ; ON EXIT : CY = 1 MEANS ERROR 3564 <1> ;------------------------------------------------------------------------------- 3565 <1> SETUP_DBL: 3566 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3567 00001B96 8AA7[C7610000] <1> mov ah, [DSK_STATE+edi] ; ACCESS STATE 3568 00001B9C F6C410 <1> test ah, MED_DET ; ESTABLISHED STATE ? 3569 00001B9F 7578 <1> jnz short NO_DBL ; IF ESTABLISHED THEN DOUBLE DONE 3570 <1> 3571 <1> ;----- CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE 3572 <1> 3573 00001BA1 C605[B9610000]00 <1> mov byte [SEEK_STATUS], 0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 3574 00001BA8 E8CF000000 <1> call MOTOR_ON ; ENSURE MOTOR STAY ON 3575 00001BAD B500 <1> mov ch, 0 ; LOAD TRACK 0 3576 00001BAF E8B7010000 <1> call SEEK ; SEEK TO TRACK 0 3577 00001BB4 E862000000 <1> call READ_ID ; READ ID FUNCTION 3578 00001BB9 7243 <1> jc short SD_ERR ; IF ERROR NO TRACK 0 3579 <1> 3580 <1> ;----- INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS) 3581 <1> 3582 00001BBB 66B95004 <1> mov cx, 0450h ; START, MAX TRACKS 3583 00001BBF F687[C7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY 3584 00001BC6 7402 <1> jz short CNT_OK ; IF NOT COUNT IS SETUP 3585 00001BC8 B1A0 <1> mov cl, 0A0h ; MAXIMUM TRACK 1.2 MB 3586 <1> 3587 <1> ; ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS, 3588 <1> ; MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT 3589 <1> ; THEN SET DOUBLE STEP ON. 3590 <1> 3591 <1> CNT_OK: 3592 00001BCA C605[BB610000]FF <1> mov byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 3593 <1> ; 24/12/2021 3594 00001BD1 51 <1> push ecx ; SAVE TRACK, COUNT 3595 00001BD2 C605[BC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS 3596 00001BD9 31C0 <1> xor eax, eax ; CLEAR EAX 3597 00001BDB D0ED <1> shr ch, 1 ; HALVE TRACK, CY = HEAD 3598 00001BDD C0D003 <1> rcl al, 3 ; AX = HEAD IN CORRECT BIT 3599 <1> ; 24/12/2021 3600 00001BE0 50 <1> push eax ; SAVE HEAD 3601 00001BE1 E885010000 <1> call SEEK ; SEEK TO TRACK 3602 <1> ; 24/12/2021 3603 00001BE6 58 <1> pop eax ; RESTORE HEAD 3604 00001BE7 09C7 <1> or edi, eax ; DI = HEAD OR'ED DRIVE 3605 00001BE9 E82D000000 <1> call READ_ID ; READ ID HEAD 0 3606 00001BEE 9C <1> pushf ; SAVE RETURN FROM READ_ID 3607 00001BEF 6681E7FB00 <1> and di, 11111011b ; TURN OFF HEAD 1 BIT 3608 00001BF4 9D <1> popf ; RESTORE ERROR RETURN 3609 <1> ; 24/12/2021 3610 00001BF5 59 <1> pop ecx ; RESTORE COUNT 3611 00001BF6 7308 <1> jnc short DO_CHK ; IF OK, ASKED = RETURNED TRACK ? 3612 00001BF8 FEC5 <1> inc ch ; INC FOR NEXT TRACK 3613 00001BFA 38CD <1> cmp ch, cl ; REACHED MAXIMUM YET 3614 00001BFC 75CC <1> jnz short CNT_OK ; CONTINUE TILL ALL TRIED 3615 <1> 3616 <1> ;----- FALL THRU, READ ID FAILED FOR ALL TRACKS 3617 <1> 3618 <1> SD_ERR: 3619 00001BFE F9 <1> stc ; SET CARRY FOR ERROR 3620 00001BFF C3 <1> retn ; SETUP_DBL ERROR EXIT 3621 <1> 3622 <1> DO_CHK: 3623 00001C00 8A0D[C0610000] <1> mov cl, [NEC_STATUS+3] ; LOAD RETURNED TRACK 3624 00001C06 888F[C9610000] <1> mov [DSK_TRK+edi], cl ; STORE TRACK NUMBER 3625 00001C0C D0ED <1> shr ch, 1 ; HALVE TRACK 3626 00001C0E 38CD <1> cmp ch, cl ; IS IT THE SAME AS ASKED FOR TRACK 3627 00001C10 7407 <1> jz short NO_DBL ; IF SAME THEN NO DOUBLE STEP 3628 00001C12 808F[C7610000]20 <1> or byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED 3629 <1> NO_DBL: 3630 00001C19 F8 <1> clc ; CLEAR ERROR FLAG 3631 00001C1A C3 <1> retn 3632 <1> 3633 <1> ;------------------------------------------------------------------------------- 3634 <1> ; READ_ID 3635 <1> ; READ ID FUNCTION. 3636 <1> ; 3637 <1> ; ON ENTRY: EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE 3638 <1> ; 3639 <1> ; ON EXIT: EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE 3640 <1> ; @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3641 <1> ;------------------------------------------------------------------------------- 3642 <1> READ_ID: 3643 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3644 00001C1B B8[371C0000] <1> mov eax, ER_3 ; MOVE NEC OUTPUT ERROR ADDRESS 3645 00001C20 50 <1> push eax 3646 00001C21 B44A <1> mov ah, 4Ah ; READ ID COMMAND 3647 00001C23 E80A010000 <1> call NEC_OUTPUT ; TO CONTROLLER 3648 00001C28 89F8 <1> mov eax, edi ; DRIVE # TO AH, HEAD 0 3649 00001C2A 88C4 <1> mov ah, al 3650 00001C2C E801010000 <1> call NEC_OUTPUT ; TO CONTROLLER 3651 00001C31 E839FEFFFF <1> call NEC_TERM ; WAIT FOR OPERATION, GET STATUS 3652 00001C36 58 <1> pop eax ; THROW AWAY ERROR ADDRESS 3653 <1> ER_3: 3654 00001C37 C3 <1> retn 3655 <1> 3656 <1> ;------------------------------------------------------------------------------- 3657 <1> ; CMOS_TYPE 3658 <1> ; RETURNS CMOS DISKETTE TYPE 3659 <1> ; 3660 <1> ; ON ENTRY: EDI = DRIVE # 3661 <1> ; 3662 <1> ; ON EXIT: AL = TYPE; CY REFLECTS STATUS 3663 <1> ;------------------------------------------------------------------------------- 3664 <1> 3665 <1> CMOS_TYPE: ; 11/12/2014 3666 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3667 00001C38 8A87[5C5C0000] <1> mov al, [edi+fd0_type] ; diskette type 3668 00001C3E 20C0 <1> and al, al ; 18/12/2014 3669 00001C40 C3 <1> retn 3670 <1> 3671 <1> ;------------------------------------------------------------------------------- 3672 <1> ; GET_PARM 3673 <1> ; THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE 3674 <1> ; BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM 3675 <1> ; THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING 3676 <1> ; THE PARAMETER IN DL. 3677 <1> ; 3678 <1> ; ON ENTRY: AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022 3679 <1> ; 3680 <1> ; ON EXIT: AH = THAT BYTE FROM BLOCK 3681 <1> ; AL DESTROYED 3682 <1> ;------------------------------------------------------------------------------- 3683 <1> GET_PARM: 3684 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3685 <1> ; ENTRY: 3686 <1> ; AL = INDEX 3687 <1> ; EDI = DRIVE # 3688 <1> ; RETURN: 3689 <1> ; AH = REQUESTED PARAMETER 3690 <1> ; AL DESTROYED 3691 <1> 3692 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3693 <1> ; 08/02/2015 (protected mode modifications, bx -> ebx) 3694 <1> ;push esi ; 11/07/2022 3695 00001C41 53 <1> push ebx ; SAVE EBX 3696 00001C42 0FB6D8 <1> movzx ebx, al ; EBX = INDEX 3697 <1> ; 17/12/2014 3698 <1> ;mov ax, [cfd] ; current (AL) and previous fd (AH) 3699 <1> ; 11/07/2022 3700 <1> ;cmp al, ah 3701 <1> ;je short gpndc 3702 <1> 3703 <1> ; 11/07/2022 3704 00001C45 89F8 <1> mov eax, edi 3705 00001C47 3A05[515C0000] <1> cmp al, [pfd] ; is same with previous drive # ? 3706 00001C4D 7423 <1> je short gpndc 3707 <1> 3708 00001C4F A2[515C0000] <1> mov [pfd], al ; current drive -> previous drive 3709 <1> 3710 00001C54 53 <1> push ebx ; 08/02/2015 3711 <1> 3712 <1> ;mov bl, al 3713 <1> ; 11/12/2014 3714 <1> ;mov al, [ebx+fd0_type] ; Drive type (0,1,2,3,4) 3715 <1> ; 11/07/2022 3716 00001C55 8A87[5C5C0000] <1> mov al, [edi+fd0_type] ; Drive type (0,1,2,3,4) 3717 <1> ; 18/12/2014 3718 00001C5B 20C0 <1> and al, al 3719 00001C5D 7507 <1> jnz short gpdtc 3720 00001C5F BB[3B5C0000] <1> mov ebx, MD_TBL6 ; 1.44 MB param. tbl. (default) 3721 00001C64 EB05 <1> jmp short gpdpu 3722 <1> gpdtc: 3723 00001C66 E8AEFBFFFF <1> call DR_TYPE_CHECK 3724 <1> ; cf = 1 -> EBX points to 1.44MB fd parameter table (default) 3725 <1> gpdpu: 3726 00001C6B 891D[D85B0000] <1> mov [DISK_POINTER], ebx 3727 00001C71 5B <1> pop ebx 3728 <1> gpndc: 3729 <1> ;mov esi, [DISK_POINTER] ; 08/02/2015, si -> esi 3730 <1> ;mov ah, [esi+ebx] ; GET THE WORD 3731 <1> ; 11/07/2022 3732 00001C72 031D[D85B0000] <1> add ebx, [DISK_POINTER] 3733 00001C78 8A23 <1> mov ah, [ebx] 3734 00001C7A 5B <1> pop ebx ; RESTORE EBX 3735 <1> ;pop esi ; 11/07/2022 3736 00001C7B C3 <1> retn 3737 <1> 3738 <1> ;------------------------------------------------------------------------------- 3739 <1> ; MOTOR_ON 3740 <1> ; TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT 3741 <1> ; IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE 3742 <1> ; THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE 3743 <1> ; MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION 3744 <1> ; (AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM 3745 <1> ; THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS 3746 <1> ; FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT 3747 <1> ; HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE 3748 <1> ; THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID 3749 <1> ; NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE 3750 <1> ; PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN, 3751 <1> ; IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE 3752 <1> ; WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT. 3753 <1> ; 3754 <1> ; ON ENTRY: EDI = DRIVE # 3755 <1> ; ON EXIT: EAX, ECX, EDX DESTROYED 3756 <1> ;------------------------------------------------------------------------------- 3757 <1> MOTOR_ON: 3758 <1> ; 12/07/2022 3759 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3760 00001C7C 53 <1> push ebx ; SAVE REG. 3761 00001C7D E820000000 <1> call TURN_ON ; TURN ON MOTOR 3762 00001C82 721C <1> jc short MOT_IS_ON ; IF CY=1 NO WAIT 3763 <1> ;call XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3764 <1> ; 08/07/2022 3765 <1> ;call XLAT_NEW ; 12/07/2022 ; TRANSLATE STATE TO PRESENT ARCH, 3766 <1> ;call TURN_ON ; CHECK AGAIN IF MOTOR ON 3767 <1> ;jc short MOT_IS_ON ; IF NO WAIT MEANS IT IS ON 3768 <1> M_WAIT: 3769 <1> ;mov dl,10 ; GET THE MOTOR WAIT PARAMETER 3770 00001C84 B00A <1> mov al, 10 ; 08/07/2022 3771 00001C86 E8B6FFFFFF <1> call GET_PARM 3772 <1> ; 08/07/2022 ; AH = MOTOR WAIT PARAMETER 3773 00001C8B 80FC08 <1> cmp ah, 8 ; SEE IF AT LEAST A SECOND IS SPECIFIED 3774 <1> ;jae short GP2 ; IF YES, CONTINUE 3775 00001C8E 7302 <1> jae short J13 3776 00001C90 B408 <1> mov ah, 8 ; ONE SECOND WAIT FOR MOTOR START UP 3777 <1> 3778 <1> ;----- AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT 3779 <1> GP2: 3780 <1> ;----- FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE 3781 <1> J13: ; WAIT FOR 1/8 SECOND PER (AL) 3782 00001C92 B95E200000 <1> mov ecx, 8286 ; COUNT FOR 1/8 SECOND AT 15.085737 US 3783 00001C97 E810F7FFFF <1> call WAITF ; GO TO FIXED WAIT ROUTINE 3784 <1> ;dec al ; DECREMENT TIME VALUE 3785 00001C9C FECC <1> dec ah 3786 00001C9E 75F2 <1> jnz short J13 ; ARE WE DONE YET 3787 <1> MOT_IS_ON: 3788 00001CA0 5B <1> pop ebx ; RESTORE REG. 3789 00001CA1 C3 <1> retn 3790 <1> 3791 <1> ;------------------------------------------------------------------------------- 3792 <1> ; TURN_ON 3793 <1> ; TURN MOTOR ON AND RETURN WAIT STATE. 3794 <1> ; 3795 <1> ; ON ENTRY: EDI = DRIVE # 3796 <1> ; 3797 <1> ; ON EXIT: CY = 0 MEANS WAIT REQUIRED 3798 <1> ; CY = 1 MEANS NO WAIT REQUIRED 3799 <1> ; EAX, EBX, ECX, EDX DESTROYED 3800 <1> ;------------------------------------------------------------------------------- 3801 <1> TURN_ON: 3802 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3803 00001CA2 89FB <1> mov ebx, edi ; EBX = DRIVE # 3804 00001CA4 88D9 <1> mov cl, bl ; CL = DRIVE # 3805 00001CA6 C0C304 <1> rol bl, 4 ; BL = DRIVE SELECT 3806 00001CA9 FA <1> cli ; NO INTERRUPTS WHILE DETERMINING STATUS 3807 00001CAA C605[BB610000]FF <1> mov byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 3808 00001CB1 A0[BA610000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 3809 00001CB6 2430 <1> and al, 00110000b ; KEEP ONLY DRIVE SELECT BITS 3810 00001CB8 B401 <1> mov ah, 1 ; MASK FOR DETERMINING MOTOR BIT 3811 00001CBA D2E4 <1> shl ah, cl ; AH = MOTOR ON, A=00000001, B=00000010 3812 <1> 3813 <1> ; AL = DRIVE SELECT FROM @MOTOR_STATUS 3814 <1> ; BL = DRIVE SELECT DESIRED 3815 <1> ; AH = MOTOR ON MASK DESIRED 3816 <1> 3817 00001CBC 38D8 <1> cmp al, bl ; REQUESTED DRIVE ALREADY SELECTED ? 3818 00001CBE 7508 <1> jne short TURN_IT_ON ; IF NOT SELECTED JUMP 3819 00001CC0 8425[BA610000] <1> test ah, [MOTOR_STATUS] ; TEST MOTOR ON BIT 3820 00001CC6 7535 <1> jnz short NO_MOT_WAIT ; JUMP IF MOTOR ON AND SELECTED 3821 <1> 3822 <1> TURN_IT_ON: 3823 00001CC8 08DC <1> or ah, bl ; AH = DRIVE SELECT AND MOTOR ON 3824 00001CCA 8A3D[BA610000] <1> mov bh, [MOTOR_STATUS] ; SAVE COPY OF @MOTOR_STATUS BEFORE 3825 00001CD0 80E70F <1> and bh, 00001111b ; KEEP ONLY MOTOR BITS 3826 00001CD3 8025[BA610000]CF <1> and byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT 3827 00001CDA 0825[BA610000] <1> or [MOTOR_STATUS], ah ; OR IN DRIVE SELECTED AND MOTOR ON 3828 00001CE0 A0[BA610000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 3829 00001CE5 88C3 <1> mov bl, al ; BL=@MOTOR_STATUS AFTER, BH=BEFORE 3830 00001CE7 80E30F <1> and bl, 00001111b ; KEEP ONLY MOTOR BITS 3831 00001CEA FB <1> sti ; ENABLE INTERRUPTS AGAIN 3832 00001CEB 243F <1> and al, 00111111b ; STRIP AWAY UNWANTED BITS 3833 00001CED C0C004 <1> rol al, 4 ; PUT BITS IN DESIRED POSITIONS 3834 00001CF0 0C0C <1> or al, 00001100b ; NO RESET, ENABLE DMA/INTERRUPT 3835 00001CF2 66BAF203 <1> mov dx, 03F2h ; SELECT DRIVE AND TURN ON MOTOR 3836 00001CF6 EE <1> out dx, al 3837 00001CF7 38FB <1> cmp bl, bh ; NEW MOTOR TURNED ON ? 3838 <1> ;je short NO_MOT_WAIT ; NO WAIT REQUIRED IF JUST SELECT 3839 00001CF9 7403 <1> je short no_mot_w1 ; 27/02/2015 3840 00001CFB F8 <1> clc ; RESET CARRY MEANING WAIT 3841 00001CFC C3 <1> retn 3842 <1> 3843 <1> NO_MOT_WAIT: 3844 00001CFD FB <1> sti 3845 <1> no_mot_w1: ; 27/02/2015 3846 00001CFE F9 <1> stc ; SET NO WAIT REQUIRED 3847 <1> ;sti ; INTERRUPTS BACK ON 3848 00001CFF C3 <1> retn 3849 <1> 3850 <1> ;------------------------------------------------------------------------------- 3851 <1> ; HD_WAIT 3852 <1> ; WAIT FOR HEAD SETTLE TIME. 3853 <1> ; 3854 <1> ; ON ENTRY: DI = DRIVE # 3855 <1> ; 3856 <1> ; ON EXIT: AX,BX,CX,DX DESTROYED 3857 <1> ;------------------------------------------------------------------------------- 3858 <1> HD_WAIT: 3859 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3860 <1> ;mov dl, 9 ; GET HEAD SETTLE PARAMETER 3861 00001D00 B009 <1> mov al, 9 ; 08/07/2022 3862 00001D02 E83AFFFFFF <1> CALL GET_PARM 3863 00001D07 08E4 <1> or ah, ah ; 17/12/2014 ; CHECK FOR ANY WAIT? 3864 00001D09 7519 <1> jnz short DO_WAT ; IF THERE DO NOT ENFORCE 3865 00001D0B F605[BA610000]80 <1> test byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION 3866 <1> ;jz short ISNT_WRITE ; IF NOT, DO NOT ENFORCE ANY VALUES 3867 <1> ;or ah, ah ; CHECK FOR ANY WAIT? 3868 <1> ;jnz short DO_WAT ; IF THERE DO NOT ENFORCE 3869 00001D12 741D <1> jz short HW_DONE 3870 00001D14 B40F <1> mov ah, HD12_SETTLE ; LOAD 1.2M HEAD SETTLE MINIMUM 3871 00001D16 8A87[C7610000] <1> mov al, [DSK_STATE+edi] ; LOAD STATE 3872 00001D1C 24C0 <1> and al, RATE_MSK ; KEEP ONLY RATE 3873 00001D1E 3C80 <1> cmp al, RATE_250 ; 1.2 M DRIVE ? 3874 00001D20 7502 <1> jnz short DO_WAT ; DEFAULT HEAD SETTLE LOADED 3875 <1> ;GP3: 3876 00001D22 B414 <1> mov ah, HD320_SETTLE ; USE 320/360 HEAD SETTLE 3877 <1> ; jmp short DO_WAT 3878 <1> 3879 <1> ;ISNT_WRITE: 3880 <1> ; or ah, ah ; CHECK FOR NO WAIT 3881 <1> ; jz short HW_DONE ; IF NOT WRITE AND 0 ITS OK 3882 <1> 3883 <1> ;----- AH CONTAINS NUMBER OF MILLISECONDS TO WAIT 3884 <1> DO_WAT: 3885 <1> ; mov al, ah ; AL = # MILLISECONDS 3886 <1> ; ;xor ah, ah ; AX = # MILLISECONDS 3887 <1> J29: ; 1 MILLISECOND LOOP 3888 <1> ;mov cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units. 3889 <1> ;mov ecx, 66 ; COUNT AT 15.085737 US PER COUNT 3890 <1> ; 08/07/2022 3891 00001D24 29C9 <1> sub ecx, ecx 3892 00001D26 B142 <1> mov cl, 66 3893 00001D28 E87FF6FFFF <1> call WAITF ; DELAY FOR 1 MILLISECOND 3894 <1> ;dec al ; DECREMENT THE COUNT 3895 00001D2D FECC <1> dec ah 3896 00001D2F 75F3 <1> jnz short J29 ; DO AL MILLISECOND # OF TIMES 3897 <1> HW_DONE: 3898 00001D31 C3 <1> retn 3899 <1> 3900 <1> ;------------------------------------------------------------------------------- 3901 <1> ; NEC_OUTPUT 3902 <1> ; THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING 3903 <1> ; FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL 3904 <1> ; TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT 3905 <1> ; OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION. 3906 <1> ; 3907 <1> ; ON ENTRY: AH = BYTE TO BE OUTPUT 3908 <1> ; 3909 <1> ; ON EXIT: CY = 0 SUCCESS 3910 <1> ; CY = 1 FAILURE -- DISKETTE STATUS UPDATED 3911 <1> ; IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL 3912 <1> ; HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE 3913 <1> ; REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT. 3914 <1> ; 3915 <1> ; EAX, ECX, EDX DESTROYED 3916 <1> ;------------------------------------------------------------------------------- 3917 <1> 3918 <1> ; 09/12/2014 [Erdogan Tan] 3919 <1> ; (from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.) 3920 <1> ; Diskette Drive Controller Status Register (3F4h) 3921 <1> ; This read only register facilitates the transfer of data between 3922 <1> ; the system microprocessor and the controller. 3923 <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 3924 <1> ; with the system micrprocessor. 3925 <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0, 3926 <1> ; the transfer is to the controller. 3927 <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode. 3928 <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed. 3929 <1> ; Bit 3 - Reserved. 3930 <1> ; Bit 2 - Reserved. 3931 <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode. 3932 <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode. 3933 <1> 3934 <1> ; Data Register (3F5h) 3935 <1> ; This read/write register passes data, commands and parameters, and provides 3936 <1> ; diskette status information. 3937 <1> 3938 <1> NEC_OUTPUT: 3939 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3940 <1> ;push ebx ; SAVE REG. 3941 00001D32 BAF4030000 <1> mov edx, 03F4h ; STATUS PORT 3942 <1> ;xor ecx, ecx ; COUNT FOR TIME OUT 3943 <1> ; 16/12/2014 3944 <1> ; waiting for (max.) 0.5 seconds 3945 <1> ;;mov byte [wait_count], 0 ;; 27/02/2015 3946 <1> ; 3947 <1> ; 17/12/2014 3948 <1> ; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND 3949 <1> ; 3950 <1> ;WAIT_FOR_PORT: Waits for a bit at a port pointed to by DX to 3951 <1> ; go on. 3952 <1> ;INPUT: 3953 <1> ; AH=Mask for isolation bits. 3954 <1> ; AL=pattern to look for. 3955 <1> ; DX=Port to test for 3956 <1> ; ECX=Number of memory refresh periods to delay. 3957 <1> ; (normally 30 microseconds per period.) 3958 <1> ; 3959 <1> ;WFP_SHORT: 3960 <1> ; Wait for port if refresh cycle is short (15-80 Us range). 3961 <1> ; 3962 <1> 3963 00001D37 B91B410000 <1> mov ecx, WAIT_FDU_SEND_LH ; 16667 (27/02/2015) 3964 <1> ; 3965 <1> ;WFPS_OUTER_LP: 3966 <1> ; ; 3967 <1> ;WFPS_CHECK_PORT: 3968 <1> J23: 3969 00001D3C EC <1> in al, dx ; GET STATUS 3970 00001D3D 24C0 <1> and al, 11000000b ; KEEP STATUS AND DIRECTION 3971 00001D3F 3C80 <1> cmp al, 10000000b ; STATUS 1 AND DIRECTION 0 ? 3972 00001D41 7418 <1> jz short J27 ; STATUS AND DIRECTION OK 3973 <1> WFPS_HI: 3974 00001D43 E461 <1> in al, PORT_B ; 061h ; SYS1 ; wait for hi to lo 3975 00001D45 A810 <1> test al, 010h ; transition on memory 3976 00001D47 75FA <1> jnz short WFPS_HI ; refresh. 3977 <1> WFPS_LO: 3978 00001D49 E461 <1> in al, PORT_B ; SYS1 3979 00001D4B A810 <1> test al, 010h 3980 00001D4D 74FA <1> jz short WFPS_LO 3981 <1> ;loop short WFPS_CHECK_PORT 3982 00001D4F E2EB <1> loop J23 ; 27/02/2015 ; REPEAT TILL DELAY FINISHED 3983 <1> 3984 <1> ; fail 3985 <1> 3986 <1> ;WFPS_TIMEOUT: 3987 <1> 3988 <1> ;----- FALL THRU TO ERROR RETURN 3989 <1> 3990 00001D51 800D[BC610000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT 3991 <1> ;pop ebx ; RESTORE REG. 3992 00001D58 58 <1> pop eax ; 08/02/2015 ; DISCARD THE RETURN ADDRESS 3993 00001D59 F9 <1> stc ; INDICATE ERROR TO CALLER 3994 00001D5A C3 <1> retn 3995 <1> 3996 <1> ;----- DIRECTION AND STATUS OK; OUTPUT BYTE 3997 <1> 3998 <1> J27: 3999 00001D5B 88E0 <1> mov al, ah ; GET BYTE TO OUTPUT 4000 00001D5D 42 <1> inc edx ; DATA PORT = STATUS PORT + 1 4001 00001D5E EE <1> out dx, al ; OUTPUT THE BYTE 4002 <1> ;;NEWIODELAY ;; 27/02/2015 4003 <1> ; 27/02/2015 4004 00001D5F 9C <1> pushfd ; 24/12/2021 ; SAVE FLAGS 4005 <1> ;mov ecx, 3 ; 30 TO 45 MICROSECONDS WAIT FOR 4006 00001D60 29C9 <1> sub ecx, ecx 4007 00001D62 B103 <1> mov cl, 3 ; 24/12/2021 4008 00001D64 E843F6FFFF <1> call WAITF ; NEC FLAGS UPDATE CYCLE 4009 00001D69 9D <1> popfd ; 24/12/2021 ; RESTORE FLAGS FOR EXIT 4010 <1> ;pop ebx ; RESTORE REG 4011 00001D6A C3 <1> retn ; CY = 0 FROM TEST INSTRUCTION 4012 <1> 4013 <1> ;------------------------------------------------------------------------------- 4014 <1> ; SEEK 4015 <1> ; THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED 4016 <1> ; TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE 4017 <1> ; RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED. 4018 <1> ; 4019 <1> ; ON ENTRY: EDI = DRIVE # 4020 <1> ; CH = TRACK # 4021 <1> ; 4022 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4023 <1> ; EAX, EBX, ECX, EDX DESTROYED 4024 <1> ;------------------------------------------------------------------------------- 4025 <1> SEEK: 4026 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4027 00001D6B 89FB <1> mov ebx, edi ; EBX = DRIVE # 4028 00001D6D B001 <1> mov al, 1 ; ESTABLISH MASK FOR RECALIBRATE TEST 4029 00001D6F 86CB <1> xchg cl, bl ; SET DRIVE VALUE INTO CL 4030 00001D71 D2C0 <1> rol al, cl ; SHIFT MASK BY THE DRIVE VALUE 4031 00001D73 86CB <1> xchg cl, bl ; RECOVER DRIVE VALUE 4032 00001D75 8405[B9610000] <1> test al, [SEEK_STATUS] ; TEST FOR RECALIBRATE REQUIRED 4033 00001D7B 7526 <1> jnz short J28A ; JUMP IF RECALIBRATE NOT REQUIRED 4034 <1> 4035 00001D7D 0805[B9610000] <1> or [SEEK_STATUS], al ; TURN ON THE NO RECALIBRATE BIT IN FLAG 4036 00001D83 E862000000 <1> call RECAL ; RECALIBRATE DRIVE 4037 00001D88 730E <1> jnc short AFT_RECAL ; RECALIBRATE DONE 4038 <1> 4039 <1> ;----- ISSUE RECALIBRATE FOR 80 TRACK DISKETTES 4040 <1> 4041 00001D8A C605[BC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS 4042 00001D91 E854000000 <1> call RECAL ; RECALIBRATE DRIVE 4043 00001D96 7251 <1> jc short RB ; IF RECALIBRATE FAILS TWICE THEN ERROR 4044 <1> 4045 <1> AFT_RECAL: 4046 00001D98 C687[C9610000]00 <1> mov byte [DSK_TRK+edi], 0 ; SAVE NEW CYLINDER AS PRESENT POSITION 4047 00001D9F 08ED <1> or ch, ch ; CHECK FOR SEEK TO TRACK 0 4048 00001DA1 743F <1> jz short DO_WAIT ; HEAD SETTLE, CY = 0 IF JUMP 4049 <1> 4050 <1> ;----- DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK 4051 <1> 4052 00001DA3 F687[C7610000]20 <1> J28A: test byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED 4053 00001DAA 7402 <1> jz short _R7 ; SINGLE STEP REQUIRED BYPASS DOUBLE 4054 00001DAC D0E5 <1> shl ch, 1 ; DOUBLE NUMBER OF STEP TO TAKE 4055 <1> 4056 00001DAE 3AAF[C9610000] <1> _R7: cmp ch, [DSK_TRK+edi] ; SEE IF ALREADY AT THE DESIRED TRACK 4057 00001DB4 7433 <1> je short RB ; IF YES, DO NOT NEED TO SEEK 4058 <1> 4059 00001DB6 BA[E91D0000] <1> mov edx, NEC_ERR ; LOAD RETURN ADDRESS 4060 00001DBB 52 <1> push edx ; (*) ; ON STACK FOR NEC OUTPUT ERROR 4061 00001DBC 88AF[C9610000] <1> mov [DSK_TRK+edi], ch ; SAVE NEW CYLINDER AS PRESENT POSITION 4062 00001DC2 B40F <1> mov ah, 0Fh ; SEEK COMMAND TO NEC 4063 00001DC4 E869FFFFFF <1> call NEC_OUTPUT 4064 00001DC9 89FB <1> mov ebx, edi ; EBX = DRIVE # 4065 00001DCB 88DC <1> mov ah, bl ; OUTPUT DRIVE NUMBER 4066 00001DCD E860FFFFFF <1> call NEC_OUTPUT 4067 00001DD2 8AA7[C9610000] <1> mov ah, [DSK_TRK+edi] ; GET CYLINDER NUMBER 4068 00001DD8 E855FFFFFF <1> call NEC_OUTPUT 4069 00001DDD E827000000 <1> call CHK_STAT_2 ; ENDING INTERRUPT AND SENSE STATUS 4070 <1> 4071 <1> ;----- WAIT FOR HEAD SETTLE 4072 <1> 4073 <1> DO_WAIT: 4074 00001DE2 9C <1> pushfd ; 24/12/2021 ; SAVE STATUS 4075 00001DE3 E818FFFFFF <1> call HD_WAIT ; WAIT FOR HEAD SETTLE TIME 4076 00001DE8 9D <1> popfd ; 24/12/2021 ; RESTORE STATUS 4077 <1> RB: 4078 <1> NEC_ERR: 4079 <1> ; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM) 4080 <1> ; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn 4081 00001DE9 C3 <1> retn ; RETURN TO CALLER 4082 <1> 4083 <1> ;------------------------------------------------------------------------------- 4084 <1> ; RECAL 4085 <1> ; RECALIBRATE DRIVE 4086 <1> ; 4087 <1> ; ON ENTRY: EDI = DRIVE # 4088 <1> ; 4089 <1> ; ON EXIT: CY REFLECTS STATUS OF OPERATION. 4090 <1> ;------------------------------------------------------------------------------- 4091 <1> RECAL: 4092 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4093 <1> ;push cx 4094 <1> ; 24/12/2021 4095 00001DEA 51 <1> push ecx 4096 00001DEB B8[071E0000] <1> mov eax, RC_BACK ; LOAD NEC_OUTPUT ERROR 4097 00001DF0 50 <1> push eax 4098 00001DF1 B407 <1> mov ah, 07h ; RECALIBRATE COMMAND 4099 00001DF3 E83AFFFFFF <1> call NEC_OUTPUT 4100 00001DF8 89FB <1> mov ebx, edi ; EBX = DRIVE # 4101 00001DFA 88DC <1> mov ah, bl 4102 00001DFC E831FFFFFF <1> call NEC_OUTPUT ; OUTPUT THE DRIVE NUMBER 4103 00001E01 E803000000 <1> call CHK_STAT_2 ; GET THE INTERRUPT AND SENSE INT STATUS 4104 00001E06 58 <1> pop eax ; THROW AWAY ERROR 4105 <1> RC_BACK: 4106 <1> ;pop cx 4107 <1> ; 24/12/2021 4108 00001E07 59 <1> pop ecx 4109 00001E08 C3 <1> RETn 4110 <1> 4111 <1> ;------------------------------------------------------------------------------- 4112 <1> ; CHK_STAT_2 4113 <1> ; THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE, 4114 <1> ; OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE 4115 <1> ; INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER. 4116 <1> ; 4117 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4118 <1> ;------------------------------------------------------------------------------- 4119 <1> CHK_STAT_2: 4120 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4121 00001E09 B8[311E0000] <1> mov eax, CS_BACK ; LOAD NEC_OUTPUT ERROR ADDRESS 4122 00001E0E 50 <1> push eax 4123 00001E0F E828000000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 4124 00001E14 721A <1> jc short J34 ; IF ERROR, RETURN IT 4125 00001E16 B408 <1> mov ah, 08h ; SENSE INTERRUPT STATUS COMMAND 4126 00001E18 E815FFFFFF <1> call NEC_OUTPUT 4127 00001E1D E849000000 <1> call RESULTS ; READ IN THE RESULTS 4128 00001E22 720C <1> jc short J34 4129 00001E24 A0[BD610000] <1> mov al, [NEC_STATUS] ; GET THE FIRST STATUS BYTE 4130 00001E29 2460 <1> and al, 01100000b ; ISOLATE THE BITS 4131 00001E2B 3C60 <1> cmp al, 01100000b ; TEST FOR CORRECT VALUE 4132 00001E2D 7403 <1> jz short J35 ; IF ERROR, GO MARK IT 4133 00001E2F F8 <1> clc ; GOOD RETURN 4134 <1> J34: 4135 00001E30 58 <1> pop eax ; THROW AWAY ERROR RETURN 4136 <1> CS_BACK: 4137 00001E31 C3 <1> retn 4138 <1> J35: 4139 00001E32 800D[BC610000]40 <1> or byte [DSKETTE_STATUS], BAD_SEEK 4140 00001E39 F9 <1> stc ; ERROR RETURN CODE 4141 00001E3A EBF4 <1> jmp short J34 4142 <1> 4143 <1> ;------------------------------------------------------------------------------- 4144 <1> ; WAIT_INT 4145 <1> ; THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE 4146 <1> ; TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED 4147 <1> ; IF THE DRIVE IS NOT READY. 4148 <1> ; 4149 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4150 <1> ;------------------------------------------------------------------------------- 4151 <1> 4152 <1> ; 17/12/2014 4153 <1> ; 2.5 seconds waiting ! 4154 <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI) 4155 <1> ; amount of time to wait for completion interrupt from NEC. 4156 <1> 4157 <1> WAIT_INT: 4158 <1> ; 12/07/2022 4159 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4160 00001E3C FB <1> sti ; TURN ON INTERRUPTS, JUST IN CASE 4161 <1> ; 12/07/2022 4162 <1> ;clc ; CLEAR TIMEOUT INDICATOR 4163 <1> ;mov bl, 10 ; CLEAR THE COUNTERS 4164 <1> ;xor cx, cx ; FOR 2 SECOND WAIT 4165 <1> 4166 <1> ; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT 4167 <1> ; 4168 <1> ;WAIT_FOR_MEM: 4169 <1> ; Waits for a bit at a specified memory location pointed 4170 <1> ; to by ES:[DI] to become set. 4171 <1> ;INPUT: 4172 <1> ; AH=Mask to test with. 4173 <1> ; ES:[DI] = memory location to watch. 4174 <1> ; BH:CX=Number of memory refresh periods to delay. 4175 <1> ; (normally 30 microseconds per period.) 4176 <1> 4177 <1> ; waiting for (max.) 2.5 secs in 30 micro units. 4178 <1> ; mov cx, WAIT_FDU_INT_LO ; 017798 4179 <1> ;; mov bl, WAIT_FDU_INT_HI 4180 <1> ; mov bl, WAIT_FDU_INT_HI + 1 4181 <1> ; 27/02/2015 4182 00001E3D B986450100 <1> mov ecx, WAIT_FDU_INT_LH ; 83334 (2.5 seconds) 4183 <1> WFMS_CHECK_MEM: 4184 00001E42 F605[B9610000]80 <1> test byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING 4185 00001E49 7516 <1> jnz short J37 4186 <1> WFMS_HI: 4187 00001E4B E461 <1> in al, PORT_B ; 061h ; SYS1, wait for lo to hi 4188 00001E4D A810 <1> test al, 010h ; transition on memory 4189 00001E4F 75FA <1> jnz short WFMS_HI ; refresh. 4190 <1> WFMS_LO: 4191 00001E51 E461 <1> in al, PORT_B ; SYS1 4192 00001E53 A810 <1> test al, 010h 4193 00001E55 74FA <1> jz short WFMS_LO 4194 00001E57 E2E9 <1> loop WFMS_CHECK_MEM 4195 <1> ;WFMS_OUTER_LP: 4196 <1> ;; or bl, bl ; check outer counter 4197 <1> ;; jz short J36A ; WFMS_TIMEOUT 4198 <1> ; dec bl 4199 <1> ; jz short J36A 4200 <1> ; jmp short WFMS_CHECK_MEM 4201 <1> 4202 <1> ;17/12/2014 4203 <1> ;16/12/2014 4204 <1> ; mov byte [wait_count], 0 ; Reset (INT 08H) counter 4205 <1> ;J36: 4206 <1> ; test byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING 4207 <1> ; jnz short J37 4208 <1> ;16/12/2014 4209 <1> ;loop J36 ; COUNT DOWN WHILE WAITING 4210 <1> ;dec bl ; SECOND LEVEL COUNTER 4211 <1> ;jnz short J36 4212 <1> ; cmp byte [wait_count], 46 ; (46/18.2 seconds) 4213 <1> ; jb short J36 4214 <1> 4215 <1> ;WFMS_TIMEOUT: 4216 <1> ;J36A: 4217 00001E59 800D[BC610000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED 4218 00001E60 F9 <1> stc ; ERROR RETURN 4219 <1> J37: 4220 00001E61 9C <1> pushf ; SAVE CURRENT CARRY 4221 00001E62 8025[B9610000]7F <1> and byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG 4222 00001E69 9D <1> popf ; RECOVER CARRY 4223 00001E6A C3 <1> retn ; GOOD RETURN CODE 4224 <1> 4225 <1> ;------------------------------------------------------------------------------- 4226 <1> ; RESULTS 4227 <1> ; THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 4228 <1> ; FOLLOWING AN INTERRUPT. 4229 <1> ; 4230 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4231 <1> ; EAX, EBX, ECX, EDX DESTROYED 4232 <1> ;------------------------------------------------------------------------------- 4233 <1> RESULTS: 4234 <1> ; 12/07/2022 4235 <1> ; 11/07/2022 4236 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4237 00001E6B 57 <1> push edi 4238 00001E6C BF[BD610000] <1> mov edi, NEC_STATUS ; POINTER TO DATA AREA 4239 00001E71 B307 <1> mov bl, 7 ; MAX STATUS BYTES 4240 00001E73 66BAF403 <1> mov dx, 03F4h ; STATUS PORT 4241 <1> 4242 <1> ;----- WAIT FOR REQUEST FOR MASTER 4243 <1> 4244 <1> _R10: 4245 <1> ; 16/12/2014 4246 <1> ; wait for (max) 0.5 seconds 4247 <1> ;mov bh, 2 ; HIGH ORDER COUNTER 4248 <1> ;xor cx, cx ; COUNTER 4249 <1> 4250 <1> ;Time to wait while waiting for each byte of NEC results = .5 4251 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 4252 <1> ; 27/02/2015 4253 <1> 4254 00001E77 B91B410000 <1> mov ecx, WAIT_FDU_RESULTS_LH ; 16667 4255 <1> ;mov cx, WAIT_FDU_RESULTS_LO ; 16667 4256 <1> ;mov bh, WAIT_FDU_RESULTS_HI+1 ; 0+1 4257 <1> 4258 <1> WFPSR_OUTER_LP: 4259 <1> ; 4260 <1> WFPSR_CHECK_PORT: 4261 <1> J39: ; WAIT FOR MASTER 4262 00001E7C EC <1> in al, dx ; GET STATUS 4263 00001E7D 24C0 <1> and al, 11000000b ; KEEP ONLY STATUS AND DIRECTION 4264 00001E7F 3CC0 <1> cmp al, 11000000b ; STATUS 1 AND DIRECTION 1 ? 4265 00001E81 7418 <1> jz short J42 ; STATUS AND DIRECTION OK 4266 <1> WFPSR_HI: 4267 00001E83 E461 <1> in al, PORT_B ;061h ; SYS1 ; wait for hi to lo 4268 00001E85 A810 <1> test al, 010h ; transition on memory 4269 00001E87 75FA <1> jnz short WFPSR_HI ; refresh. 4270 <1> WFPSR_LO: 4271 00001E89 E461 <1> in al, PORT_B ; SYS1 4272 00001E8B A810 <1> test al, 010h 4273 00001E8D 74FA <1> jz short WFPSR_LO 4274 00001E8F E2EB <1> loop WFPSR_CHECK_PORT 4275 <1> 4276 <1> ;; 27/02/2015 4277 <1> ;;dec bh 4278 <1> ;;jnz short WFPSR_OUTER_LP 4279 <1> ;jmp short WFPSR_TIMEOUT ; fail 4280 <1> 4281 <1> ;;mov byte [wait_count], 0 4282 <1> ;J39: ; WAIT FOR MASTER 4283 <1> ; in al, dx ; GET STATUS 4284 <1> ; and al, 11000000b ; KEEP ONLY STATUS AND DIRECTION 4285 <1> ; cmp al, 11000000b ; STATUS 1 AND DIRECTION 1 ? 4286 <1> ; jz short J42 ; STATUS AND DIRECTION OK 4287 <1> ;loop J39 ; LOOP TILL TIMEOUT 4288 <1> ;dec bh ; DECREMENT HIGH ORDER COUNTER 4289 <1> ;jnz short J39 ; REPEAT TILL DELAY DONE 4290 <1> ; 4291 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 4292 <1> ;;jb short J39 4293 <1> 4294 <1> ;WFPSR_TIMEOUT: 4295 00001E91 800D[BC610000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT 4296 00001E98 F9 <1> stc ; SET ERROR RETURN 4297 00001E99 EB26 <1> jmp short POPRES ; POP REGISTERS AND RETURN 4298 <1> 4299 <1> ;----- READ IN THE STATUS 4300 <1> 4301 <1> J42: 4302 00001E9B EB00 <1> JMP $+2 ; I/O DELAY 4303 <1> ;inc dx ; POINT AT DATA PORT 4304 00001E9D FEC2 <1> inc dl 4305 00001E9F EC <1> in al, dx ; GET THE DATA 4306 <1> ; 16/12/2014 4307 <1> NEWIODELAY 2135 00001EA0 E6EB <2> out 0EBh,al 4308 <1> 4309 <1> ;mov [edi], al ; STORE THE BYTE 4310 <1> ;inc edi ; INCREMENT THE POINTER 4311 <1> ; 11/07/2022 4312 00001EA2 AA <1> stosb 4313 <1> 4314 <1> ; 16/12/2014 4315 <1> ; push cx 4316 <1> ; mov cx, 30 4317 <1> ;wdw2: 4318 <1> ; NEWIODELAY 4319 <1> ; loop wdw2 4320 <1> ; pop cx 4321 <1> 4322 <1> ;mov ecx,3 ; MINIMUM 24 MICROSECONDS FOR NEC 4323 <1> ; 12/07/2022 4324 00001EA3 29C9 <1> sub ecx, ecx 4325 00001EA5 B103 <1> mov cl, 3 4326 00001EA7 E800F5FFFF <1> call WAITF ; WAIT 30 TO 45 MICROSECONDS 4327 <1> ;dec dx ; POINT AT STATUS PORT 4328 00001EAC FECA <1> dec dl 4329 00001EAE EC <1> in al, dx ; GET STATUS 4330 <1> ; 16/12/2014 4331 <1> NEWIODELAY 2135 00001EAF E6EB <2> out 0EBh,al 4332 <1> ; 4333 00001EB1 A810 <1> test al, 00010000b ; TEST FOR NEC STILL BUSY 4334 00001EB3 740C <1> jz short POPRES ; RESULTS DONE ? 4335 <1> 4336 00001EB5 FECB <1> dec bl ; DECREMENT THE STATUS COUNTER 4337 00001EB7 75BE <1> jnz short _R10 ; GO BACK FOR MORE 4338 00001EB9 800D[BC610000]20 <1> or byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES 4339 00001EC0 F9 <1> stc ; SET ERROR FLAG 4340 <1> 4341 <1> ;----- RESULT OPERATION IS DONE 4342 <1> POPRES: 4343 00001EC1 5F <1> pop edi 4344 00001EC2 C3 <1> retn ; RETURN WITH CARRY SET 4345 <1> 4346 <1> ;------------------------------------------------------------------------------- 4347 <1> ; READ_DSKCHNG 4348 <1> ; READS THE STATE OF THE DISK CHANGE LINE. 4349 <1> ; 4350 <1> ; ON ENTRY: EDI = DRIVE # 4351 <1> ; 4352 <1> ; ON EXIT: EDI = DRIVE # 4353 <1> ; ZF = 0 : DISK CHANGE LINE INACTIVE 4354 <1> ; ZF = 1 : DISK CHANGE LINE ACTIVE 4355 <1> ; EAX, ECX, EDX DESTROYED 4356 <1> ;------------------------------------------------------------------------------- 4357 <1> READ_DSKCHNG: 4358 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4359 00001EC3 E8B4FDFFFF <1> call MOTOR_ON ; TURN ON THE MOTOR IF OFF 4360 00001EC8 66BAF703 <1> mov dx, 03F7h ; ADDRESS DIGITAL INPUT REGISTER 4361 00001ECC EC <1> in al, dx ; INPUT DIGITAL INPUT REGISTER 4362 00001ECD A880 <1> test al, DSK_CHG ; CHECK FOR DISK CHANGE LINE ACTIVE 4363 00001ECF C3 <1> retn ; RETURN TO CALLER WITH ZERO FLAG SET 4364 <1> 4365 <1> fdc_int: 4366 <1> ; 30/07/2015 4367 <1> ; 16/02/2015 4368 <1> ;int_0Eh: ; 11/12/2014 4369 <1> 4370 <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL 6 ) -------------------------------------- 4371 <1> ; DISK_INT 4372 <1> ; THIS ROUTINE HANDLES THE DISKETTE INTERRUPT. 4373 <1> ; 4374 <1> ; ON EXIT: THE INTERRUPT FLAG IS SET IN @SEEK_STATUS. 4375 <1> ;------------------------------------------------------------------------------- 4376 <1> DISK_INT_1: 4377 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4378 <1> ;push eax ; SAVE WORK REGISTER 4379 <1> ; 24/12/2021 4380 00001ED0 50 <1> push eax 4381 00001ED1 1E <1> push ds 4382 00001ED2 66B81000 <1> mov ax, KDATA 4383 00001ED6 8ED8 <1> mov ds, ax 4384 00001ED8 800D[B9610000]80 <1> or byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED 4385 00001EDF B020 <1> mov al, EOI ; END OF INTERRUPT MARKER 4386 00001EE1 E620 <1> out INTA00, al ; INTERRUPT CONTROL PORT 4387 00001EE3 1F <1> pop ds 4388 <1> ;pop ax ; RECOVER REGISTER 4389 <1> ; 24/12/2021 4390 00001EE4 58 <1> pop eax 4391 00001EE5 CF <1> iretd ; RETURN FROM INTERRUPT 4392 <1> 4393 <1> ;------------------------------------------------------------------------------- 4394 <1> ; DSKETTE_SETUP 4395 <1> ; THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF 4396 <1> ; DISKETTE DRIVES ARE ATTACH TO THE SYSTEM. 4397 <1> ;------------------------------------------------------------------------------- 4398 <1> DSKETTE_SETUP: 4399 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4400 <1> ;push eax ; SAVE REGISTERS 4401 <1> ;push ebx 4402 <1> ;push ecx 4403 00001EE6 52 <1> push edx 4404 <1> ;push edi 4405 <1> ; 14/12/2014 4406 <1> ;mov dword [DISK_POINTER], MD_TBL6 4407 <1> ; 4408 <1> ;or byte [RTC_WAIT_FLAG], 1 ; NO RTC WAIT, FORCE USE OF LOOP 4409 <1> 4410 00001EE7 31FF <1> xor edi, edi ; INITIALIZE DRIVE POINTER 4411 00001EE9 29C9 <1> sub ecx, ecx 4412 00001EEB 66890D[C7610000] <1> mov [DSK_STATE], cx ; 0 ; INITIALIZE STATES 4413 <1> ; 08/07/2022 4414 <1> ;and byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND 4415 00001EF2 800D[C4610000]C0 <1> or byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE 4416 00001EF9 880D[B9610000] <1> mov [SEEK_STATUS], cl ; 0 ; INDICATE RECALIBRATE NEEDED 4417 00001EFF 880D[BB610000] <1> mov [MOTOR_COUNT], cl ; 0 ; INITIALIZE MOTOR COUNT 4418 00001F05 880D[BA610000] <1> mov [MOTOR_STATUS], cl ; 0 ; INITIALIZE DRIVES TO OFF STATE 4419 00001F0B 880D[BC610000] <1> mov [DSKETTE_STATUS], cl ; 0 ; NO ERRORS 4420 <1> ; 4421 <1> ; 28/02/2015 4422 <1> ;mov word [cfd], 100h 4423 00001F11 E892F8FFFF <1> call DSK_RESET 4424 00001F16 5A <1> pop edx 4425 00001F17 C3 <1> retn 4426 <1> 4427 <1> ;////////////////////////////////////////////////////// 4428 <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4429 <1> ; 4430 <1> 4431 <1> ; 12/07/2022 4432 <1> ;int13h: ; 21/02/2015 4433 <1> ; pushfd 4434 <1> ; push cs 4435 <1> ; call DISK_IO 4436 <1> ; retn 4437 <1> 4438 <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;; 4439 <1> ;///////////////////////////////////////////////////////////////////// 4440 <1> 4441 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4442 <1> ; ((Direct call instead of int 13h simulation)) 4443 <1> ; 4444 <1> ; Function in AL 4445 <1> ; 0 = reset 4446 <1> ; 1 = read 4447 <1> ; 2 = write 4448 <1> ; Disk drive number in DL 4449 <1> ; 0 & 1 = floppy disks 4450 <1> ; 80h .. 83h = hard disks 4451 <1> ; Sector address (LBA) in ECX 4452 <1> ; Buffer address in EBX 4453 <1> ; R/W sector count is (always) 1 4454 <1> ; 4455 <1> ; Return: 4456 <1> ; Status in AH (>0 = error code) 4457 <1> ; if CF = 1 -> error code in AH 4458 <1> ; if CF = 0 -> successful 4459 <1> ; AL = undefined 4460 <1> ; 4461 <1> ; Modified registers: (only) EAX 4462 <1> 4463 <1> ; 10/07/2022 4464 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4465 <1> 4466 <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project) 4467 <1> ; 23/02/2015 4468 <1> ; 21/02/2015 (unix386.s) 4469 <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s) 4470 <1> ; 4471 <1> ; Original Source Code: 4472 <1> ; DISK ----- 09/25/85 FIXED DISK BIOS 4473 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 4474 <1> ; 4475 <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 4476 <1> ; Source Code - ATORGS.ASM, AHDSK.ASM 4477 <1> ; 4478 <1> 4479 <1> ;The wait for controller to be not busy is 10 seconds. 4480 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 4481 <1> ;;WAIT_HDU_CTLR_BUSY_LO equ 1615h 4482 <1> ;;WAIT_HDU_CTLR_BUSY_HI equ 05h 4483 <1> WAIT_HDU_CTRL_BUSY_LH equ 51615h ;21/02/2015 4484 <1> 4485 <1> ;The wait for controller to issue completion interrupt is 10 seconds. 4486 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 4487 <1> ;;WAIT_HDU_INT_LO equ 1615h 4488 <1> ;;WAIT_HDU_INT_HI equ 05h 4489 <1> WAIT_HDU_INT_LH equ 51615h ; 21/02/2015 4490 <1> 4491 <1> ;The wait for Data request on read and write longs is 4492 <1> ;2000 us. (?) 4493 <1> ;;WAIT_HDU_DRQ_LO equ 1000 ; 03E8h 4494 <1> ;;WAIT_HDU_DRQ_HI equ 0 4495 <1> WAIT_HDU_DRQ_LH equ 1000 ; 21/02/2015 4496 <1> 4497 <1> ; Port 61h (PORT_B) 4498 <1> SYS1 equ 61h ; PORT_B (diskette.inc) 4499 <1> 4500 <1> ; 23/12/2014 4501 <1> %define CMD_BLOCK ebp-8 ; 21/02/2015 4502 <1> 4503 <1> ; 11/07/2022 4504 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4505 <1> 4506 <1> ;--- INT 13H ------------------------------------------------------------------- 4507 <1> ; : 4508 <1> ; FIXED DISK I/O INTERFACE : 4509 <1> ; : 4510 <1> ; THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH : 4511 <1> ; THE IBM FIXED DISK CONTROLLER. : 4512 <1> ; : 4513 <1> ; THE BIOS ROUTINES ARE MEANT TO BE ACCESSED THROUGH : 4514 <1> ; SOFTWARE INTERRUPTS ONLY. ANY ADDRESSES PRESENT IN : 4515 <1> ; THESE LISTINGS ARE INCLUDED ONLY FOR COMPLETENESS, : 4516 <1> ; NOT FOR REFERENCE. APPLICATIONS WHICH REFERENCE ANY : 4517 <1> ; ABSOLUTE ADDRESSES WITHIN THE CODE SEGMENTS OF BIOS : 4518 <1> ; VIOLATE THE STRUCTURE AND DESIGN OF BIOS. : 4519 <1> ; : 4520 <1> ;------------------------------------------------------------------------------: 4521 <1> ; : 4522 <1> ; INPUT (AH)= HEX COMMAND VALUE : 4523 <1> ; : 4524 <1> ; (AH)= 00H RESET DISK (DL = 80H,81H) / DISKETTE : 4525 <1> ; (AH)= 01H READ THE DESIRED SECTORS INTO MEMORY : 4526 <1> ; (AH)= 02H WRITE THE DESIRED SECTORS FROM MEMORY : 4527 <1> ; : 4528 <1> ;------------------------------------------------------------------------------: 4529 <1> ; : 4530 <1> ; REGISTERS USED FOR FIXED DISK OPERATIONS : 4531 <1> ; : 4532 <1> ; (DL) - DRIVE NUMBER (80H-81H FOR DISK. VALUE CHECKED) : 4533 <1> ; (DH) - HEAD NUMBER (0-15 ALLOWED, NOT VALUE CHECKED) : 4534 <1> ; (CH) - CYLINDER NUMBER (0-1023, NOT VALUE CHECKED)(SEE CL): 4535 <1> ; (CL) - SECTOR NUMBER (1-17, NOT VALUE CHECKED) : 4536 <1> ; : 4537 <1> ; NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED : 4538 <1> ; IN THE HIGH 2 BITS OF THE CL REGISTER : 4539 <1> ; (10 BITS TOTAL) : 4540 <1> ; : 4541 <1> ; (AL) - NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H, : 4542 <1> ; FOR READ/WRITE LONG 1-79H) : 4543 <1> ; : 4544 <1> ; (EBX) - ADDRESS OF BUFFER FOR READS AND WRITES, : 4545 <1> ; (NOT REQUIRED FOR VERIFY) : 4546 <1> ; : 4547 <1> ;------------------------------------------------------------------------------: 4548 <1> ; OUTPUT : 4549 <1> ; AH = STATUS OF CURRENT OPERATION : 4550 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES BELOW : 4551 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) : 4552 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) : 4553 <1> ; : 4554 <1> ; NOTE: ERROR 11H INDICATES THAT THE DATA READ HAD A RECOVERABLE : 4555 <1> ; ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM. THE DATA : 4556 <1> ; IS PROBABLY GOOD, HOWEVER THE BIOS ROUTINE INDICATES AN : 4557 <1> ; ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE : 4558 <1> ; FOR ITSELF. THE ERROR MAY NOT RECUR IF THE DATA IS : 4559 <1> ; REWRITTEN. : 4560 <1> ; : 4561 <1> ; IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), : 4562 <1> ; INPUT: : 4563 <1> ; (DL) = DRIVE NUMBER : 4564 <1> ; OUTPUT: : 4565 <1> ; (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2) : 4566 <1> ; (CONTROLLER CARD ZERO TALLY ONLY) : 4567 <1> ; (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER : 4568 <1> ; (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER : 4569 <1> ; (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER : 4570 <1> ; AND CYLINDER NUMBER HIGH BITS : 4571 <1> ; : 4572 <1> ; REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN : 4573 <1> ; INFORMATION. : 4574 <1> ; : 4575 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE : 4576 <1> ; ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION. : 4577 <1> ; : 4578 <1> ;------------------------------------------------------------------------------- 4579 <1> 4580 <1> SENSE_FAIL EQU 0FFH ; NOT IMPLEMENTED 4581 <1> NO_ERR EQU 0E0H ; STATUS ERROR/ERROR REGISTER=0 4582 <1> WRITE_FAULT EQU 0CCH ; WRITE FAULT ON SELECTED DRIVE 4583 <1> UNDEF_ERR EQU 0BBH ; UNDEFINED ERROR OCCURRED 4584 <1> NOT_RDY EQU 0AAH ; DRIVE NOT READY 4585 <1> TIME_OUT EQU 80H ; ATTACHMENT FAILED TO RESPOND 4586 <1> BAD_SEEK EQU 40H ; SEEK OPERATION FAILED 4587 <1> BAD_CNTLR EQU 20H ; CONTROLLER HAS FAILED 4588 <1> DATA_CORRECTED EQU 11H ; ECC CORRECTED DATA ERROR 4589 <1> BAD_ECC EQU 10H ; BAD ECC ON DISK READ 4590 <1> BAD_TRACK EQU 0BH ; NOT IMPLEMENTED 4591 <1> BAD_SECTOR EQU 0AH ; BAD SECTOR FLAG DETECTED 4592 <1> ;DMA_BOUNDARY EQU 09H ; DATA EXTENDS TOO FAR 4593 <1> INIT_FAIL EQU 07H ; DRIVE PARAMETER ACTIVITY FAILED 4594 <1> BAD_RESET EQU 05H ; RESET FAILED 4595 <1> ;RECORD_NOT_FND EQU 04H ; REQUESTED SECTOR NOT FOUND 4596 <1> ;BAD_ADDR_MARK EQU 02H ; ADDRESS MARK NOT FOUND 4597 <1> ;BAD_CMD EQU 01H ; BAD COMMAND PASSED TO DISK I/O 4598 <1> 4599 <1> ;-------------------------------------------------------- 4600 <1> ; : 4601 <1> ; FIXED DISK PARAMETER TABLE : 4602 <1> ; - THE TABLE IS COMPOSED OF A BLOCK DEFINED AS: : 4603 <1> ; : 4604 <1> ; +0 (1 WORD) - MAXIMUM NUMBER OF CYLINDERS : 4605 <1> ; +2 (1 BYTE) - MAXIMUM NUMBER OF HEADS : 4606 <1> ; +3 (1 WORD) - NOT USED/SEE PC-XT : 4607 <1> ; +5 (1 WORD) - STARTING WRITE PRECOMPENSATION CYL : 4608 <1> ; +7 (1 BYTE) - MAXIMUM ECC DATA BURST LENGTH : 4609 <1> ; +8 (1 BYTE) - CONTROL BYTE : 4610 <1> ; BIT 7 DISABLE RETRIES -OR- : 4611 <1> ; BIT 6 DISABLE RETRIES : 4612 <1> ; BIT 3 MORE THAN 8 HEADS : 4613 <1> ; +9 (3 BYTES)- NOT USED/SEE PC-XT : 4614 <1> ; +12 (1 WORD) - LANDING ZONE : 4615 <1> ; +14 (1 BYTE) - NUMBER OF SECTORS/TRACK : 4616 <1> ; +15 (1 BYTE) - RESERVED FOR FUTURE USE : 4617 <1> ; : 4618 <1> ; - TO DYNAMICALLY DEFINE A SET OF PARAMETERS : 4619 <1> ; BUILD A TABLE FOR UP TO 15 TYPES AND PLACE : 4620 <1> ; THE CORRESPONDING VECTOR INTO INTERRUPT 41 : 4621 <1> ; FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1. : 4622 <1> ; : 4623 <1> ;-------------------------------------------------------- 4624 <1> 4625 <1> ;-------------------------------------------------------- 4626 <1> ; : 4627 <1> ; HARDWARE SPECIFIC VALUES : 4628 <1> ; : 4629 <1> ; - CONTROLLER I/O PORT : 4630 <1> ; : 4631 <1> ; > WHEN READ FROM: : 4632 <1> ; HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU) : 4633 <1> ; HF_PORT+1 - GET ERROR REGISTER : 4634 <1> ; HF_PORT+2 - GET SECTOR COUNT : 4635 <1> ; HF_PORT+3 - GET SECTOR NUMBER : 4636 <1> ; HF_PORT+4 - GET CYLINDER LOW : 4637 <1> ; HF_PORT+5 - GET CYLINDER HIGH (2 BITS) : 4638 <1> ; HF_PORT+6 - GET SIZE/DRIVE/HEAD : 4639 <1> ; HF_PORT+7 - GET STATUS REGISTER : 4640 <1> ; : 4641 <1> ; > WHEN WRITTEN TO: : 4642 <1> ; HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) : 4643 <1> ; HF_PORT+1 - SET PRECOMPENSATION CYLINDER : 4644 <1> ; HF_PORT+2 - SET SECTOR COUNT : 4645 <1> ; HF_PORT+3 - SET SECTOR NUMBER : 4646 <1> ; HF_PORT+4 - SET CYLINDER LOW : 4647 <1> ; HF_PORT+5 - SET CYLINDER HIGH (2 BITS) : 4648 <1> ; HF_PORT+6 - SET SIZE/DRIVE/HEAD : 4649 <1> ; HF_PORT+7 - SET COMMAND REGISTER : 4650 <1> ; : 4651 <1> ;-------------------------------------------------------- 4652 <1> 4653 <1> ;HF_PORT EQU 01F0H ; DISK PORT 4654 <1> ;HF1_PORT equ 0170h 4655 <1> ;HF_REG_PORT EQU 03F6H 4656 <1> ;HF1_REG_PORT equ 0376h 4657 <1> 4658 <1> HDC1_BASEPORT equ 1F0h 4659 <1> HDC2_BASEPORT equ 170h 4660 <1> 4661 <1> align 2 4662 <1> 4663 <1> ;----- STATUS REGISTER 4664 <1> 4665 <1> ST_ERROR EQU 00000001B ; 4666 <1> ST_INDEX EQU 00000010B ; 4667 <1> ST_CORRCTD EQU 00000100B ; ECC CORRECTION SUCCESSFUL 4668 <1> ST_DRQ EQU 00001000B ; 4669 <1> ST_SEEK_COMPL EQU 00010000B ; SEEK COMPLETE 4670 <1> ST_WRT_FLT EQU 00100000B ; WRITE FAULT 4671 <1> ST_READY EQU 01000000B ; 4672 <1> ST_BUSY EQU 10000000B ; 4673 <1> 4674 <1> ;----- ERROR REGISTER 4675 <1> 4676 <1> ERR_DAM EQU 00000001B ; DATA ADDRESS MARK NOT FOUND 4677 <1> ERR_TRK_0 EQU 00000010B ; TRACK 0 NOT FOUND ON RECAL 4678 <1> ERR_ABORT EQU 00000100B ; ABORTED COMMAND 4679 <1> ; EQU 00001000B ; NOT USED 4680 <1> ERR_ID EQU 00010000B ; ID NOT FOUND 4681 <1> ; EQU 00100000B ; NOT USED 4682 <1> ERR_DATA_ECC EQU 01000000B 4683 <1> ERR_BAD_BLOCK EQU 10000000B 4684 <1> 4685 <1> 4686 <1> RECAL_CMD EQU 00010000B ; DRIVE RECAL (10H) 4687 <1> READ_CMD EQU 00100000B ; READ (20H) 4688 <1> WRITE_CMD EQU 00110000B ; WRITE (30H) 4689 <1> VERIFY_CMD EQU 01000000B ; VERIFY (40H) 4690 <1> FMTTRK_CMD EQU 01010000B ; FORMAT TRACK (50H) 4691 <1> INIT_CMD EQU 01100000B ; INITIALIZE (60H) 4692 <1> SEEK_CMD EQU 01110000B ; SEEK (70H) 4693 <1> DIAG_CMD EQU 10010000B ; DIAGNOSTIC (90H) 4694 <1> SET_PARM_CMD EQU 10010001B ; DRIVE PARMS (91H) 4695 <1> NO_RETRIES EQU 00000001B ; CHD MODIFIER (01H) 4696 <1> ECC_MODE EQU 00000010B ; CMD MODIFIER (02H) 4697 <1> BUFFER_MODE EQU 00001000B ; CMD MODIFIER (08H) 4698 <1> 4699 <1> ;MAX_FILE EQU 2 4700 <1> ;S_MAX_FILE EQU 2 4701 <1> MAX_FILE equ 4 ; 22/12/2014 4702 <1> S_MAX_FILE equ 4 ; 22/12/2014 4703 <1> 4704 <1> DELAY_1 EQU 25H ; DELAY FOR OPERATION COMPLETE 4705 <1> DELAY_2 EQU 0600H ; DELAY FOR READY 4706 <1> DELAY_3 EQU 0100H ; DELAY FOR DATA REQUEST 4707 <1> 4708 <1> HF_FAIL EQU 08H ; CMOS FLAG IN BYTE 0EH 4709 <1> 4710 <1> ;----- COMMAND BLOCK REFERENCE 4711 <1> 4712 <1> ;CMD_BLOCK EQU BP-8 ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS 4713 <1> ; (BP) POINTS TO COMMAND BLOCK TAIL 4714 <1> ; AS DEFINED BY THE "ENTER" PARMS 4715 <1> ; 19/12/2014 4716 <1> ORG_VECTOR equ 4*13h ; INT 13h vector 4717 <1> DISK_VECTOR equ 4*40h ; INT 40h vector (for floppy disks) 4718 <1> ;HDISK_INT equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 4719 <1> ;HDISK_INT1 equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 4720 <1> ;HDISK_INT2 equ 4*77h ; Secondary HDC - Hardware interrupt (IRQ15) 4721 <1> ;HF_TBL_VEC equ 4*41h ; Pointer to 1st fixed disk parameter table 4722 <1> ;HF1_TBL_VEC equ 4*46h ; Pointer to 2nd fixed disk parameter table 4723 <1> 4724 <1> align 2 4725 <1> 4726 <1> ;---------------------------------------------------------------- 4727 <1> ; FIXED DISK I/O SETUP : 4728 <1> ; : 4729 <1> ; - ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK : 4730 <1> ; - PERFORM POWER ON DIAGNOSTICS : 4731 <1> ; SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED : 4732 <1> ; : 4733 <1> ;---------------------------------------------------------------- 4734 <1> 4735 <1> ; 12/07/2022 4736 <1> ; 11/07/2022 4737 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4738 <1> 4739 <1> DISK_SETUP: 4740 <1> ;cli 4741 <1> ;;mov ax, ABS0 ; GET ABSOLUTE SEGMENT 4742 <1> ;xor ax, ax 4743 <1> ;mov ds, ax ; SET SEGMENT REGISTER 4744 <1> ;mov ax, [ORG_VECTOR] ; GET DISKETTE VECTOR 4745 <1> ;mov [DISK_VECTOR], ax ; INTO INT 40H 4746 <1> ;mov ax, [ORG_VECTOR+2] 4747 <1> ;mov [DISK_VECTOR+2], ax 4748 <1> ;mov word [ORG_VECTOR], DISK_IO ; FIXED DISK HANDLER 4749 <1> ;mov [ORG_VECTOR+2], cs 4750 <1> ; 1st controller (primary master, slave) - IRQ 14 4751 <1> ;;mov word [HDISK_INT], HD_INT ; FIXED DISK INTERRUPT 4752 <1> ;mov word [HDISK_INT1], HD_INT ; 4753 <1> ;;mov [HDISK_INT+2], cs 4754 <1> ;mov [HDISK_INT1+2], cs 4755 <1> ; 2nd controller (secondary master, slave) - IRQ 15 4756 <1> ;mov word [HDISK_INT2], HD1_INT ; 4757 <1> ;mov [HDISK_INT2+2], cs 4758 <1> ; 4759 <1> ;;mov word [HF_TBL_VEC], HD0_DPT ; PARM TABLE DRIVE 80 4760 <1> ;;mov word [HF_TBL_VEC+2], DPT_SEGM 4761 <1> ;;mov word [HF1_TBL_VEC], HD1_DPT ; PARM TABLE DRIVE 81 4762 <1> ;;mov word [HF1_TBL_VEC+2], DPT_SEGM 4763 <1> ;push cs 4764 <1> ;pop ds 4765 <1> ;mov word [HDPM_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80h 4766 <1> ;mov word [HDPM_TBL_VEC+2],DPT_SEGM 4767 00001F18 C705[D0610000]0000- <1> mov dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT 4767 00001F20 0900 <1> 4768 <1> ;mov word [HDPS_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81h 4769 <1> ;mov word [HDPS_TBL_VEC+2],DPT_SEGM 4770 00001F22 C705[D4610000]2000- <1> mov dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT 4770 00001F2A 0900 <1> 4771 <1> ;mov word [HDSM_TBL_VEC],HD2_DPT ; PARM TABLE DRIVE 82h 4772 <1> ;mov word [HDSM_TBL_VEC+2],DPT_SEGM 4773 00001F2C C705[D8610000]4000- <1> mov dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT 4773 00001F34 0900 <1> 4774 <1> ;mov word [HDSS_TBL_VEC],HD3_DPT ; PARM TABLE DRIVE 83h 4775 <1> ;mov word [HDSS_TBL_VEC+2],DPT_SEGM 4776 00001F36 C705[DC610000]6000- <1> mov dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT 4776 00001F3E 0900 <1> 4777 <1> ; 4778 <1> ;;in al, INTB01 ; TURN ON SECOND INTERRUPT CHIP 4779 <1> ;;;and al, 0BFh 4780 <1> ;;and al, 3Fh ; enable IRQ 14 and IRQ 15 4781 <1> ;;;JMP $+2 4782 <1> ;;IODELAY 4783 <1> ;;out INTB01, al 4784 <1> ;;IODELAY 4785 <1> ;;in al, INTA01 ; LET INTERRUPTS PASS THRU TO 4786 <1> ;;and al, 0FBh ; SECOND CHIP 4787 <1> ;;;JMP $+2 4788 <1> ;;IODELAY 4789 <1> ;;out INTA01, al 4790 <1> ; 4791 <1> ;sti 4792 <1> ;;push ds ; MOVE ABS0 POINTER TO 4793 <1> ;;pop es ; EXTRA SEGMENT POINTER 4794 <1> ;;;call DDS ; ESTABLISH DATA SEGMENT 4795 <1> ;;mov byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 4796 <1> ;;mov byte [HF_NUM],0 ; ZERO NUMBER OF FIXED DISKS 4797 <1> ;;mov byte [CONTROL_BYTE],0 4798 <1> ;;mov byte [PORT_OFF],0 ; ZERO CARD OFFSET 4799 <1> ; 20/12/2014 - private code by Erdogan Tan 4800 <1> ; (out of original PC-AT, PC-XT BIOS code) 4801 <1> ;mov si, hd0_type 4802 00001F40 BE[5E5C0000] <1> mov esi, hd0_type 4803 <1> ;;mov cx, 4 4804 <1> ;mov ecx, 4 4805 <1> ; 11/07/2022 4806 00001F45 29C9 <1> sub ecx, ecx 4807 00001F47 B104 <1> mov cl, 4 4808 <1> hde_l: 4809 00001F49 AC <1> lodsb 4810 00001F4A 3C80 <1> cmp al, 80h ; 8?h = existing 4811 00001F4C 7206 <1> jb short _L4 4812 00001F4E FE05[CC610000] <1> inc byte [HF_NUM] ; + 1 hard (fixed) disk drives 4813 <1> _L4: ; 26/02/2015 4814 00001F54 E2F3 <1> loop hde_l 4815 <1> ;_L4: ; 0 <= [HF_NUM] =< 4 4816 <1> ;L4: 4817 <1> ; 4818 <1> ;; 31/12/2014 - cancel controller diagnostics here 4819 <1> ;;;mov cx, 3 ; 26/12/2014 (Award BIOS 1999) 4820 <1> ;;mov cl, 3 4821 <1> ;; 4822 <1> ;;mov dl, 80h ; CHECK THE CONTROLLER 4823 <1> ;;hdc_dl: 4824 <1> ;;mov ah, 14h ; USE CONTROLLER DIAGNOSTIC COMMAND 4825 <1> ;;int 13h ; CALL BIOS WITH DIAGNOSTIC COMMAND 4826 <1> ;;;jc short CTL_ERRX ; DISPLAY ERROR MESSAGE IF BAD RETURN 4827 <1> ;;;jc short POD_DONE ;22/12/2014 4828 <1> ;;jnc short hdc_reset0 4829 <1> ;;loop hdc_dl 4830 <1> ;;; 27/12/2014 4831 <1> ;;stc 4832 <1> ;;retn 4833 <1> ; 4834 <1> ;;hdc_reset0: 4835 <1> ; 18/01/2015 4836 00001F56 8A0D[CC610000] <1> mov cl, [HF_NUM] 4837 00001F5C 20C9 <1> and cl, cl 4838 00001F5E 740D <1> jz short POD_DONE 4839 <1> ; 4840 00001F60 B27F <1> mov dl, 7Fh 4841 <1> hdc_reset1: 4842 00001F62 FEC2 <1> inc dl 4843 <1> ;; 31/12/2015 4844 <1> ;;push dx 4845 <1> ;;push cx 4846 <1> ;;push ds 4847 <1> ;;sub ax, ax 4848 <1> ;;mov ds, ax 4849 <1> ;;mov ax, [TIMER_LOW] ; GET START TIMER COUNTS 4850 <1> ;;pop ds 4851 <1> ;;mov bx, ax 4852 <1> ;;add ax, 6*182 ; 60 SECONDS* 18.2 4853 <1> ;;mov cx, ax 4854 <1> ;;mov word [wait_count], 0 ; 22/12/2014 (reset wait counter) 4855 <1> ;; 4856 <1> ;; 31/12/2014 - cancel HD_RESET_1 4857 <1> ;;call HD_RESET_1 ; SET UP DRIVE 0, (1,2,3) 4858 <1> ;;pop cx 4859 <1> ;;pop dx 4860 <1> ;; 4861 <1> ; 18/01/2015 4862 <1> ;mov ah, 0Dh ; ALTERNATE RESET 4863 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4864 <1> ;mov ah, 5 ; ALTERNATE RESET 4865 <1> ;;int 13h 4866 <1> ;call int13h 4867 <1> ; 12/07/2022 4868 00001F64 30C0 <1> xor al, al ; reset 4869 00001F66 E803000000 <1> call DISK_IO 4870 <1> ; 4871 00001F6B E2F5 <1> loop hdc_reset1 4872 <1> POD_DONE: 4873 00001F6D C3 <1> retn 4874 <1> 4875 <1> ;---------------------------------------- 4876 <1> ; FIXED DISK BIOS ENTRY POINT : 4877 <1> ;---------------------------------------- 4878 <1> 4879 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4880 <1> ; ((Direct call instead of int 13h simulation)) 4881 <1> ; 4882 <1> ; Function in AL 4883 <1> ; 0 = reset 4884 <1> ; 1 = read 4885 <1> ; 2 = write 4886 <1> ; Disk drive number in DL 4887 <1> ; 0 & 1 = floppy disks 4888 <1> ; 80h .. 83h = hard disks 4889 <1> ; Sector address (LBA) in ECX 4890 <1> ; Buffer address in EBX 4891 <1> ; R/W sector count is (always) 1 4892 <1> ; 4893 <1> ; Return: 4894 <1> ; Status in AH (>0 = error code) 4895 <1> ; if CF = 1 -> error code in AH 4896 <1> ; if CF = 0 -> successful 4897 <1> ; AL = undefined 4898 <1> ; 4899 <1> ; Modified registers: (only) EAX 4900 <1> 4901 <1> 4902 <1> ; 11/07/2022 4903 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4904 <1> 4905 <1> DISK_IO: 4906 <1> ; 11/07/2022 4907 <1> ; save registers 4908 00001F6E 57 <1> push edi ; ANY 4909 00001F6F 56 <1> push esi ; ANY 4910 00001F70 53 <1> push ebx ; BUFFER ADDRESS 4911 00001F71 51 <1> push ecx ; SECTOR ADDRESS (LBA) 4912 00001F72 52 <1> push edx ; DRIVE NUMBER (DL) 4913 <1> 4914 <1> ;cmp dl, 80h ; TEST FOR FIXED DISK DRIVE 4915 <1> ;;jae short A1 ; YES, HANDLE HERE 4916 <1> ;;;;int 40H ; DISKETTE HANDLER 4917 <1> ;;;call int40h 4918 <1> ;;jb DISKETTE_IO_1 4919 <1> ;; 24/12/2021 4920 <1> ;jnb short A1 4921 <1> ;jmp DISKETTE_IO_1 4922 <1> 4923 <1> ; 11/07/2022 4924 00001F73 80FA80 <1> cmp dl, 80h 4925 00001F76 730B <1> jae short A1 4926 <1> 4927 00001F78 E8C8F6FFFF <1> call DISKETTE_IO_1 4928 <1> 4929 <1> DISK_IO_RTN: 4930 <1> ; restore registers 4931 00001F7D 5A <1> pop edx 4932 00001F7E 59 <1> pop ecx 4933 00001F7F 5B <1> pop ebx 4934 00001F80 5E <1> pop esi 4935 00001F81 5F <1> pop edi 4936 00001F82 C3 <1> retn 4937 <1> 4938 <1> ;RET_2: 4939 <1> ; retf 4 ; BACK TO CALLER 4940 <1> 4941 <1> A1: 4942 <1> ; 11/07/2022 4943 <1> ;sti ; ENABLE INTERRUPTS 4944 <1> ;cmp dl, (80h + S_MAX_FILE - 1) 4945 <1> ;ja short RET_2 4946 <1> 4947 <1> ; 18/01/2015 4948 <1> ;;or ah, ah 4949 <1> ;or al, al ; 11/07/2022 (reset function) 4950 <1> ;jz short A3 ; 08/07/2022 4951 <1> 4952 <1> ;;cmp ah, 5 ; Alternate reset 4953 <1> ;cmp al, 5 ; 11/07/2022 4954 <1> ;je short A2 4955 <1> 4956 <1> ; 11/07/2022 - no need to check 4957 <1> ; (only kernel calls diskio functions) 4958 <1> ;;cmp ah, M1L/4 ; cmp ah, 6 4959 <1> ;jb short A3 4960 <1> ;; BAD COMMAND 4961 <1> ;mov byte [DISK_STATUS1], BAD_CMD 4962 <1> ;RET_2: 4963 <1> ;retf 4 4964 <1> 4965 <1> ; 11/07/2022 4966 <1> ;stc 4967 <1> ;retn 4968 <1> A2: 4969 <1> ;sub ah, ah ; Reset 4970 <1> ; 11/07/2022 4971 <1> ;sub al, al 4972 <1> A3: 4973 <1> ; SAVE REGISTERS DURING OPERATION 4974 00001F83 C8080000 <1> enter 8,0 ; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK 4975 <1> 4976 <1> ; 11/07/2022 4977 <1> ; 08/07/2022 4978 <1> ;push ebx ; IN THE STACK, THE COMMAND BLOCK IS: 4979 <1> ;push ecx ; @CMD_BLOCK == BYTE PTR [EBP]-8 4980 <1> ;push edx 4981 <1> ;push esi 4982 <1> ;push edi 4983 <1> 4984 00001F87 E80D000000 <1> call DISK_IO_CONT ; PERFORM THE OPERATION 4985 <1> 4986 00001F8C C9 <1> leave ; 11/07/2022 4987 <1> 4988 00001F8D 8A25[CB610000] <1> mov ah, [DISK_STATUS1] ; GET STATUS FROM OPERATION 4989 00001F93 80FC01 <1> cmp ah, 1 ; SET THE CARRY FLAG TO INDICATE 4990 00001F96 F5 <1> cmc ; SUCCESS OR FAILURE 4991 <1> 4992 <1> ;pop edi ; RESTORE REGISTERS 4993 <1> ;pop esi 4994 <1> ;pop edx 4995 <1> ;pop ecx 4996 <1> ;pop ebx 4997 <1> 4998 <1> ;leave ; ADJUST (ESP) AND RESTORE (EBP) 4999 <1> 5000 <1> ; 11/07/2022 5001 <1> ;retf 4 ; THROW AWAY SAVED FLAGS 5002 <1> 5003 00001F97 EBE4 <1> jmp short DISK_IO_RTN 5004 <1> 5005 <1> DISK_IO_CONT: 5006 <1> ; 17/07/2022 5007 <1> ; 11/07/2022 5008 <1> ; INPUT: 5009 <1> ; AL = 0 : reset 5010 <1> ; AL = 1 : read 5011 <1> ; Al = 2 : write 5012 <1> ; 5013 <1> ; 10/07/2022 5014 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5015 <1> SU0: 5016 00001F99 C605[CB610000]00 <1> mov byte [DISK_STATUS1], 0 ; RESET THE STATUS INDICATOR 5017 <1> ; 10/07/2022 5018 00001FA0 89DE <1> mov esi, ebx ; 21/02/2015 ; DATA (BUFFER) ADDRESS 5019 <1> 5020 00001FA2 8A1D[CC610000] <1> mov bl, [HF_NUM] ; GET NUMBER OF DRIVES 5021 00001FA8 80E27F <1> and dl, 7Fh ; GET DRIVE AS 0 OR 1 5022 <1> ; (get drive number as 0 to 3) 5023 00001FAB 38D3 <1> cmp bl, dl 5024 <1> ;;jbe BAD_COMMAND_POP ; INVALID DRIVE 5025 <1> ;jbe BAD_COMMAND ;; 14/02/2015 5026 <1> ; 24/12/2021 5027 00001FAD 7705 <1> ja short su0_su1 5028 00001FAF E98D000000 <1> jmp BAD_COMMAND 5029 <1> su0_su1: 5030 <1> ;;03/01/2015 5031 00001FB4 29DB <1> sub ebx, ebx 5032 00001FB6 88D3 <1> mov bl, dl 5033 00001FB8 883D[E0610000] <1> mov [LBAMode], bh ; 0 5034 <1> ;test byte [ebx+hd0_type], 1 ; LBA ready ? 5035 <1> ;jz short su1 ; no 5036 <1> ;inc byte [LBAMode] 5037 <1> ;su1: 5038 <1> ; 21/02/2015 (32 bit modification) 5039 <1> ; 04/01/2015 5040 <1> ;push ax ; *** 5041 <1> ; 24/12/2021 5042 00001FBE 50 <1> push eax ; *** ; function (in AL) ; 11/07/2022 5043 <1> ; 24/12/2021 5044 00001FBF 52 <1> push edx ; * 5045 00001FC0 50 <1> push eax ; function (in AL) ; 11/07/2022 5046 00001FC1 E8C4030000 <1> CALL GET_VEC ; GET DISK PARAMETERS 5047 <1> ; 02/02/2015 5048 00001FC6 668B4310 <1> mov ax, [ebx+16] ; I/O port base address (1F0h, 170h) 5049 00001FCA 66A3[525C0000] <1> mov [HF_PORT], ax 5050 00001FD0 668B5312 <1> mov dx, [ebx+18] ; control port address (3F6h, 376h) 5051 00001FD4 668915[545C0000] <1> mov [HF_REG_PORT], dx 5052 00001FDB 8A4314 <1> mov al, [ebx+20] ; head register upper nibble (A0h,B0h,E0h,F0h) 5053 <1> ; 23/02/2015 5054 00001FDE A840 <1> test al, 40h ; LBA bit (bit 6) 5055 00001FE0 7406 <1> jz short su1 5056 00001FE2 FE05[E0610000] <1> inc byte [LBAMode] ; 1 5057 <1> su1: 5058 00001FE8 C0E804 <1> shr al, 4 5059 00001FEB 2401 <1> and al, 1 5060 00001FED A2[565C0000] <1> mov [hf_m_s], al 5061 <1> ; 5062 <1> ; 03/01/2015 5063 00001FF2 8A4308 <1> mov al, [ebx+8] ; GET CONTROL BYTE MODIFIER 5064 <1> ;mov dx, [HF_REG_PORT] ; Device Control register 5065 00001FF5 EE <1> out dx, al ; SET EXTRA HEAD OPTION 5066 <1> ; Control Byte: (= 08h, here) 5067 <1> ; bit 0 - 0 5068 <1> ; bit 1 - nIEN (1 = disable irq) 5069 <1> ; bit 2 - SRST (software RESET) 5070 <1> ; bit 3 - use extra heads (8 to 15) 5071 <1> ; -always set to 1- 5072 <1> ; (bits 3 to 7 are reserved 5073 <1> ; for ATA devices) 5074 00001FF6 8A25[CD610000] <1> mov ah, [CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 5075 00001FFC 80E4C0 <1> and ah, 0C0h ; CONTROL BYTE 5076 00001FFF 08C4 <1> or ah, al 5077 00002001 8825[CD610000] <1> mov [CONTROL_BYTE], ah 5078 <1> ; 04/01/2015 5079 <1> ;pop ax 5080 <1> ; 24/12/2021 5081 00002007 58 <1> pop eax ; function (in AL) ; 11/07/2022 5082 <1> ;pop dx ; * ;; 14/02/2015 5083 <1> ; 24/12/2021 5084 00002008 5A <1> pop edx ; * 5085 <1> ;and ah, ah ; Reset function ? 5086 00002009 20C0 <1> and al, al ; 11/07/2022 5087 0000200B 7506 <1> jnz short su2 5088 <1> ;pop ax ; *** 5089 <1> ; 24/12/2021 5090 0000200D 58 <1> pop eax ; *** 5091 <1> ;;pop bx 5092 0000200E E9E4000000 <1> jmp DISK_RESET 5093 <1> su2: 5094 <1> ; 11/07/2022 5095 <1> ; ecx = sector address (lba) 5096 <1> ; dl = hard disk drive number (80h, 81h .. 83h) 5097 <1> ; al = function (0 = read, 1 = write) 5098 <1> 5099 00002013 803D[E0610000]00 <1> cmp byte [LBAMode], 0 5100 0000201A 7620 <1> jna short su3 ; convert LBA address to CHS parameters 5101 <1> 5102 <1> ; ; 02/02/2015 (LBA read/write function calls) 5103 <1> ; ;cmp ah, 1Bh 5104 <1> ; cmp ah, 3 ; 08/07/2022 5105 <1> ; jb short lbarw1 5106 <1> ; ;;cmp ah, 1Ch 5107 <1> ; ;cmp ah, 4 ; 08/07/2022 5108 <1> ; ;ja short invldfnc 5109 <1> ; ;;pop dx ; * ; 14/02/2015 5110 <1> ; ;mov ax, cx ; Lower word of LBA address (bits 0-15) 5111 <1> 5112 0000201C 89C8 <1> mov eax, ecx ; LBA address (21/02/2015) 5113 <1> 5114 <1> ; 11/07/2022 5115 <1> ;; 14/02/2015 5116 <1> ;mov cl, dl ; 14/02/2015 5117 <1> 5118 <1> ;;mov dx, bx 5119 <1> ;mov dx, si ; higher word of LBA address (bits 16-23) 5120 <1> ;;mov bx, di 5121 <1> ;mov si, di ; Buffer offset 5122 <1> 5123 <1> ; 11/07/2022 5124 <1> ;jmp short lbarw2 5125 <1> 5126 <1> ;lbarw1: 5127 <1> ; ; convert CHS to LBA 5128 <1> ; ; 5129 <1> ; ; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM 5130 <1> ; ; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track 5131 <1> ; ; + Sector - 1 5132 <1> ; ;push dx ; * ;; 14/02/2015 5133 <1> ; ; 24/12/2021 5134 <1> ; push edx ; * 5135 <1> ; ;xor dh, dh 5136 <1> ; xor edx, edx 5137 <1> ; mov dl, [ebx+14] ; sectors per track (logical) 5138 <1> ; ;xor ah, ah 5139 <1> ; xor eax, eax 5140 <1> ; mov al, [ebx+2] ; heads (logical) 5141 <1> ; dec al 5142 <1> ; ;inc ax ; 0 = 256 5143 <1> ; inc eax ; 24/12/2021 5144 <1> ; mul dx 5145 <1> ; ; AX = # of Heads * Sectors/Track 5146 <1> ; mov dx, cx 5147 <1> ; ;and cx, 3Fh ; sector (1 to 63) 5148 <1> ; and ecx, 3fh 5149 <1> ; xchg dl, dh 5150 <1> ; shr dh, 6 5151 <1> ; ; DX = cylinder (0 to 1023) 5152 <1> ; ;mul dx 5153 <1> ; ; DX:AX = # of Heads * Sectors/Track * Cylinder 5154 <1> ; mul edx 5155 <1> ; dec cl ; sector - 1 5156 <1> ; ;add ax, cx 5157 <1> ; ;adc dx, 0 5158 <1> ; ; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1 5159 <1> ; add eax, ecx 5160 <1> ; ;pop cx ; * ; ch = head, cl = drive number (zero based) 5161 <1> ; ; 24/12/2021 5162 <1> ; pop ecx ; * ; ch = head, cl = drive number (zero based) 5163 <1> ; ;push dx 5164 <1> ; ;push ax 5165 <1> ; push eax 5166 <1> ; mov al, [ebx+14] ; sectors per track (logical) 5167 <1> ; mul ch 5168 <1> ; ; AX = Head * Sectors/Track 5169 <1> ; cwd 5170 <1> ; ;pop dx 5171 <1> ; pop edx 5172 <1> ; ;add ax, dx 5173 <1> ; ;pop dx 5174 <1> ; ;adc dx, 0 ; add carry bit 5175 <1> ; add eax, edx 5176 <1> ; 5177 <1> ;lbarw2: 5178 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5179 <1> 5180 0000201E 29D2 <1> sub edx, edx ; 21/02/2015 5181 <1> 5182 <1> ; 11/07/2022 5183 <1> ;mov dl, cl ; 21/02/2015 5184 <1> 5185 00002020 C645F800 <1> mov byte [CMD_BLOCK], 0 ; Features Register 5186 <1> ; NOTE: Features register (1F1h, 171h) 5187 <1> ; is not used for ATA device R/W functions. 5188 <1> ; It is old/obsolete 'write precompensation' 5189 <1> ; register and error register 5190 <1> ; for old ATA/IDE devices. 5191 <1> ; 18/01/2014 5192 <1> ;mov ch, [hf_m_s] ; Drive 0 (master) or 1 (slave) 5193 00002024 8A0D[565C0000] <1> mov cl, [hf_m_s] 5194 <1> ;shl ch, 4 ; bit 4 (drive bit) 5195 <1> ;or ch, 0E0h ; bit 5 = 1 5196 <1> ; bit 6 = 1 = LBA mode 5197 <1> ; bit 7 = 1 5198 0000202A 80C90E <1> or cl, 0Eh ; 1110b 5199 <1> ;and dh, 0Fh ; LBA byte 4 (bits 24 to 27) 5200 0000202D 25FFFFFF0F <1> and eax, 0FFFFFFFh 5201 00002032 C1E11C <1> shl ecx, 28 ; 21/02/2015 5202 <1> ;or dh, ch 5203 00002035 09C8 <1> or eax, ecx 5204 <1> ;;mov [CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7) 5205 <1> ; (Sector Number Register) 5206 <1> ;;mov [CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15) 5207 <1> ; (Cylinder Low Register) 5208 <1> ;mov [CMD_BLOCK+2], ax ; LBA byte 1, 2 5209 <1> ;mov [CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23) 5210 <1> ; (Cylinder High Register) 5211 <1> ;;mov [CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27) 5212 <1> ; (Drive/Head Register) 5213 <1> 5214 <1> ;mov [CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits 5215 00002037 8945FA <1> mov [CMD_BLOCK+2], eax ; 21/02/2015 5216 <1> ;14/02/2015 5217 <1> ;mov dl, cl ; Drive number (INIT_DRV) 5218 0000203A EB3D <1> jmp short su4 5219 <1> su3: 5220 <1> ; 02/02/2015 5221 <1> ; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 5222 <1> ;cmp ah, 14h 5223 <1> ;jna short chsfnc 5224 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5225 <1> ;cmp ah, 2 5226 <1> ;jna short chsfnc 5227 <1> ; 11/07/2022 5228 <1> ; (al = function, read = 1 or write = 2) 5229 0000203C 3C02 <1> cmp al, 2 5230 0000203E 760B <1> jna short chsfnc 5231 <1> invldfnc: 5232 <1> ; 14/02/2015 5233 <1> ;pop es ; ** 5234 <1> ;pop ax ; *** 5235 <1> ; 24/12/2021 5236 00002040 58 <1> pop eax ; *** 5237 <1> ;;jmp short BAD_COMMAND_POP 5238 <1> ; 11/07/2022 5239 <1> ;jmp short BAD_COMMAND 5240 <1> 5241 <1> ; 11/07/2022 5242 <1> BAD_COMMAND: 5243 00002041 C605[CB610000]01 <1> mov byte [DISK_STATUS1], BAD_CMD ; COMMAND ERROR 5244 <1> ;mov al, 0 5245 00002048 28C0 <1> sub al, al ; 0 5246 0000204A C3 <1> retn 5247 <1> 5248 <1> chsfnc: 5249 0000204B 668B4305 <1> mov ax, [ebx+5] ; GET WRITE PRE-COMPENSATION CYLINDER 5250 <1> ;shr ax, 2 5251 <1> ; 17/07/2022 5252 0000204F C1E802 <1> shr eax, 2 5253 00002052 8845F8 <1> mov [CMD_BLOCK], al 5254 <1> ; 5255 <1> ;;mov al, [ebx+8] ; GET CONTROL BYTE MODIFIER 5256 <1> ;;push edx ; * 5257 <1> ;;mov dx, [HF_REG_PORT] 5258 <1> ;;out dx, al ; SET EXTRA HEAD OPTION 5259 <1> ;;pop edx ; * 5260 <1> ;;mov ah, [CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 5261 <1> ;;and ah, 0C0h ; CONTROL BYTE 5262 <1> ;;or ah, al 5263 <1> ;;mov [CONTROL_BYTE], ah 5264 <1> ; 5265 00002055 88C8 <1> mov al, cl ; GET SECTOR NUMBER 5266 00002057 243F <1> and al, 3Fh 5267 00002059 8845FA <1> mov [CMD_BLOCK+2], al 5268 0000205C 886DFB <1> mov [CMD_BLOCK+3], ch ; GET CYLINDER NUMBER 5269 0000205F 88C8 <1> mov al, cl 5270 00002061 C0E806 <1> shr al, 6 5271 00002064 8845FC <1> mov [CMD_BLOCK+4], al ; CYLINDER HIGH ORDER 2 BITS 5272 <1> ;;05/01/2015 5273 <1> ;;mov al, dl ; DRIVE NUMBER 5274 00002067 A0[565C0000] <1> mov al, [hf_m_s] 5275 0000206C C0E004 <1> shl al, 4 5276 0000206F 80E60F <1> and dh, 0Fh ; HEAD NUMBER 5277 00002072 08F0 <1> or al, dh 5278 00002074 0CA0 <1> or al, 80h+20h ; ECC AND 512 BYTE SECTORS 5279 00002076 8845FD <1> mov [CMD_BLOCK+5], al ; ECC/SIZE/DRIVE/HEAD 5280 <1> su4: 5281 <1> ;; 14/02/2015 5282 <1> ;;pop ax 5283 <1> ;;mov [CMD_BLOCK+1], AL ; SECTOR COUNT 5284 <1> ;;push ax 5285 <1> ;;mov al, ah ; GET INTO LOW BYTE 5286 <1> ;;xor ah, ah ; ZERO HIGH BYTE 5287 <1> ;;sal ax, 1 ; *2 FOR TABLE LOOKUP 5288 <1> ;pop ax ; *** 5289 <1> ; 24/12/2021 5290 00002079 58 <1> pop eax ; *** ; function (in AL) ; 11/07/2022 5291 <1> 5292 <1> ;mov [CMD_BLOCK+1], al 5293 0000207A C645F901 <1> mov byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w) 5294 <1> 5295 <1> ; 11/07/2022 5296 <1> ;mov ebx, esi 5297 <1> ; (esi = buffer address) 5298 <1> 5299 0000207E 3C02 <1> cmp al, 2 5300 00002080 742D <1> je short DISK_WRITE 5301 <1> 5302 <1> ;jmp short DISK_READ 5303 <1> 5304 <1> ; ;xor ebx, ebx 5305 <1> ; ;mov bl, ah 5306 <1> ; 5307 <1> ; ;xor bh, bh 5308 <1> ; ;sal bx, 1 5309 <1> ; sal bx, 2 ; 32 bit offset (21/02/2015) 5310 <1> ; ;;mov si, ax ; PUT INTO SI FOR BRANCH 5311 <1> ; ;;cmp ax, M1L ; TEST WITHIN RANGE 5312 <1> ; ;;jnb short BAD_COMMAND_POP 5313 <1> ; ; 08/07/2022 5314 <1> ; ;cmp ebx, M1L 5315 <1> ; ;jnb short BAD_COMMAND 5316 <1> ; 5317 <1> ; xchg ebx, esi 5318 <1> ; 5319 <1> ; ;;;pop ax ; RESTORE AX 5320 <1> ; ;;;pop bx ; AND DATA ADDRESS 5321 <1> ; 5322 <1> ; ;;push cx 5323 <1> ; ;;push ax ; ADJUST ES:BX 5324 <1> ; ;mov cx, bx ; GET 3 HIGH ORDER NIBBLES OF BX 5325 <1> ; ;shr cx, 4 5326 <1> ; ;mov ax, es 5327 <1> ; ;add ax, cx 5328 <1> ; ;mov es, ax 5329 <1> ; ;and bx, 000Fh ; ES:BX CHANGED TO ES:000X 5330 <1> ; ;;pop ax 5331 <1> ; ;;pop cx 5332 <1> ; 5333 <1> ; jmp dword [esi+M1] 5334 <1> 5335 <1> ;;BAD_COMMAND_POP: 5336 <1> ;; pop ax 5337 <1> ;; pop bx 5338 <1> ; 5339 <1> ; ; 11/07/2022 5340 <1> ;BAD_COMMAND: 5341 <1> ; mov byte [DISK_STATUS1], BAD_CMD ; COMMAND ERROR 5342 <1> ; ;mov al, 0 5343 <1> ; sub al, al ; 0 5344 <1> ; retn 5345 <1> 5346 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5347 <1> 5348 <1> ;---------------------------------------- 5349 <1> ; DISK READ ROUTINE (AH = 01H) : 5350 <1> ;---------------------------------------- 5351 <1> ; 5352 <1> DISK_READ: 5353 00002082 C645FE20 <1> mov byte [CMD_BLOCK+6], READ_CMD 5354 <1> ;jmp COMMANDI 5355 <1> 5356 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5357 <1> 5358 <1> ;---------------------------------------- 5359 <1> ; COMMANDI : 5360 <1> ; REPEATEDLY INPUTS DATA TILL : 5361 <1> ; NSECTOR RETURNS ZERO : 5362 <1> ;---------------------------------------- 5363 <1> COMMANDI: 5364 <1> ; 11/07/2022 5365 <1> ; (check 64K boundary is not needed) 5366 <1> ;call CHECK_DMA ; CHECK 64K BOUNDARY ERROR 5367 <1> ;jc short CMD_ABORT 5368 <1> 5369 <1> ;mov di, bx 5370 <1> ; 11/07/2022 5371 <1> ; (esi = buffer address) 5372 <1> ;mov edi, ebx ; 21/02/2015 5373 00002086 89F7 <1> mov edi, esi ; 11/07/2022 5374 <1> 5375 00002088 E8A8010000 <1> call COMMAND ; OUTPUT COMMAND 5376 0000208D 751F <1> jnz short CMD_ABORT 5377 <1> CMD_I1: 5378 0000208F E813020000 <1> call _WAIT ; WAIT FOR DATA REQUEST INTERRUPT 5379 00002094 7518 <1> jnz short TM_OUT ; TIME OUT 5380 <1> ;;mov cx,256 ; SECTOR SIZE IN WORDS 5381 <1> ;mov ecx, 256 ; 21/02/2015 5382 00002096 29C9 <1> sub ecx, ecx 5383 00002098 FEC5 <1> inc ch 5384 <1> ; ecx = 256 5385 <1> ;mov dx, HF_PORT 5386 0000209A 668B15[525C0000] <1> mov dx, [HF_PORT] 5387 000020A1 FA <1> cli 5388 000020A2 FC <1> cld 5389 000020A3 F3666D <1> rep insw ; GET THE SECTOR 5390 000020A6 FB <1> sti 5391 <1> 5392 <1> ;test byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT 5393 <1> ;jz short CMD_I3 5394 <1> ;call WAIT_DRQ ; WAIT FOR DATA REQUEST 5395 <1> ;jc short TM_OUT 5396 <1> ;;mov dx, HF_PORT 5397 <1> ;mov dx,[HF_PORT] 5398 <1> ;xor ecx, ecx 5399 <1> ;;mov ecx, 4 ; mov cx, 4 ; OUTPUT THE ECC BYTES 5400 <1> ;mov cl, 4 5401 <1> ;CMD_I2: 5402 <1> ;inc al, dx 5403 <1> ;mov [edi], al ; 21/02/2015 5404 <1> ;inc edi 5405 <1> ;loop CMD_I2 5406 <1> CMD_I3: 5407 000020A7 E817010000 <1> call CHECK_STATUS 5408 000020AC 7500 <1> jnz short CMD_ABORT ; ERROR RETURNED 5409 <1> ; 11/07/2022 5410 <1> ; (sector count = 1) 5411 <1> ;dec byte [CMD_BLOCK+1] ; CHECK FOR MORE 5412 <1> ;jnz SHORT CMD_I1 5413 <1> CMD_ABORT: 5414 <1> TM_OUT: 5415 000020AE C3 <1> retn 5416 <1> 5417 <1> ;--------------------------------------------------- 5418 <1> 5419 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5420 <1> 5421 <1> ;---------------------------------------- 5422 <1> ; DISK WRITE ROUTINE (AH = 02H) : 5423 <1> ;---------------------------------------- 5424 <1> 5425 <1> DISK_WRITE: 5426 000020AF C645FE30 <1> mov byte [CMD_BLOCK+6], WRITE_CMD 5427 <1> ;JMP COMMANDO 5428 <1> 5429 <1> ; 16/07/2022 5430 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5431 <1> 5432 <1> ;---------------------------------------- 5433 <1> ; COMMANDO : 5434 <1> ; REPEATEDLY OUTPUTS DATA TILL : 5435 <1> ; NSECTOR RETURNS ZERO : 5436 <1> ;---------------------------------------- 5437 <1> COMMANDO: 5438 <1> ; 11/07/2022 5439 <1> ; (check 64K boundary is not needed) 5440 <1> ;call CHECK_DMA ; CHECK 64K BOUNDARY ERROR 5441 <1> ;jc short CMD_ABORT 5442 <1> CMD_OF: 5443 <1> ; 11/07/2022 5444 <1> ; (esi = ebx = buffer address) 5445 <1> ;mov esi, ebx ; 21/02/2015 5446 000020B3 E87D010000 <1> call COMMAND ; OUTPUT COMMAND 5447 000020B8 75F4 <1> jnz short CMD_ABORT 5448 000020BA E83F020000 <1> call WAIT_DRQ ; WAIT FOR DATA REQUEST 5449 000020BF 72ED <1> jc short TM_OUT ; TOO LONG 5450 <1> CMD_O1: 5451 <1> ; 16/07/2022 5452 000020C1 668B15[525C0000] <1> mov dx, [HF_PORT] 5453 <1> 5454 <1> ; 10/07/2022 5455 <1> ;mov ecx, 256 ; 21/02/2015 5456 000020C8 31C9 <1> xor ecx, ecx 5457 000020CA FEC5 <1> inc ch 5458 <1> ; ecx = 256 5459 000020CC FA <1> cli 5460 000020CD FC <1> cld 5461 000020CE F3666F <1> rep outsw 5462 000020D1 FB <1> sti 5463 <1> 5464 <1> ; 10/07/2022 5465 <1> ;test byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT 5466 <1> ;jz short CMD_O3 5467 <1> ; 5468 <1> ;call WAIT_DRQ ; WAIT FOR DATA REQUEST 5469 <1> ;jc short TM_OUT 5470 <1> ;;mov dx, HF_PORT 5471 <1> ;mov dx, [HF_PORT] 5472 <1> ;sub ecx, ecx 5473 <1> ;;mov ecx, 4 ; mov cx, 4 ; OUTPUT THE ECC BYTES 5474 <1> ;mov cl, 4 5475 <1> ;CMD_O2: 5476 <1> ;;lodsb 5477 <1> ;mov al, [esi] 5478 <1> ;out dx, al 5479 <1> ;inc esi 5480 <1> ;loop CMD_O2 5481 <1> 5482 <1> CMD_O3: 5483 000020D2 E8D0010000 <1> call _WAIT ; WAIT FOR SECTOR COMPLETE INTERRUPT 5484 000020D7 75D5 <1> jnz short TM_OUT ; ERROR RETURNED 5485 000020D9 E8E5000000 <1> call CHECK_STATUS 5486 000020DE 75CE <1> jnz short CMD_ABORT 5487 <1> 5488 <1> ; 11/07/2022 5489 <1> ; (sector count = 1) 5490 <1> ;test byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE 5491 <1> ;jnz short CMD_O1 5492 <1> 5493 <1> ;mov dx, HF_PORT+2 ; CHECK RESIDUAL SECTOR COUNT 5494 000020E0 668B15[525C0000] <1> mov dx, [HF_PORT] 5495 000020E7 80C202 <1> add dl, 2 5496 <1> ;inc dl 5497 <1> ;inc dl 5498 000020EA EC <1> in al, dx ; 5499 000020EB A8FF <1> test al, 0FFh ; 5500 000020ED 7407 <1> jz short CMD_O4 ; COUNT = 0 OK 5501 000020EF C605[CB610000]BB <1> mov byte [DISK_STATUS1], UNDEF_ERR 5502 <1> ; OPERATION ABORTED - PARTIAL TRANSFER 5503 <1> CMD_O4: 5504 000020F6 C3 <1> retn 5505 <1> 5506 <1> ; 10/07/2022 5507 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5508 <1> 5509 <1> ;---------------------------------------- 5510 <1> ; RESET THE DISK SYSTEM (AH=00H) : 5511 <1> ;---------------------------------------- 5512 <1> 5513 <1> ; 18-1-2015 : one controller reset (not other one) 5514 <1> 5515 <1> DISK_RESET: 5516 000020F7 FA <1> cli 5517 000020F8 E4A1 <1> in al, INTB01 ; GET THE MASK REGISTER 5518 <1> ;JMP $+2 5519 <1> IODELAY 2130 000020FA EB00 <2> jmp short $+2 2131 000020FC EB00 <2> jmp short $+2 5520 <1> ;and al, 0BFh ; ENABLE FIXED DISK INTERRUPT 5521 000020FE 243F <1> and al, 3Fh ; 22/12/2014 (IRQ 14 & IRQ 15) 5522 00002100 E6A1 <1> out INTB01, al 5523 00002102 FB <1> sti ; START INTERRUPTS 5524 <1> ; 14/02/2015 5525 <1> ;mov di, dx 5526 <1> ; 24/12/2021 5527 00002103 89D7 <1> mov edi, edx 5528 <1> ; 04/01/2015 5529 <1> ;xor di,di 5530 <1> drst0: 5531 00002105 B004 <1> mov al, 04h ; bit 2 - SRST 5532 <1> ;mov dx, HF_REG_PORT 5533 00002107 668B15[545C0000] <1> mov dx, [HF_REG_PORT] 5534 0000210E EE <1> out dx, al ; RESET 5535 <1> ; mov cx, 10 ; DELAY COUNT 5536 <1> ;DRD: dec cx 5537 <1> ; jnz short DRD ; WAIT 4.8 MICRO-SEC 5538 <1> ;mov cx, 2 ; wait for 30 micro seconds 5539 <1> ;mov ecx, 2 ; 21/02/2015 5540 <1> ; 10/07/2022 5541 0000210F 29C9 <1> sub ecx, ecx 5542 00002111 B102 <1> mov cl, 2 5543 00002113 E894F2FFFF <1> call WAITF ; (Award Bios 1999 - WAIT_REFRESH, 5544 <1> ; 40 micro seconds) 5545 00002118 A0[CD610000] <1> mov al, [CONTROL_BYTE] 5546 0000211D 240F <1> and al, 0Fh ; SET HEAD OPTION 5547 0000211F EE <1> out dx, al ; TURN RESET OFF 5548 00002120 E8B2010000 <1> call NOT_BUSY 5549 00002125 7514 <1> jnz short DRERR ; TIME OUT ON RESET 5550 00002127 668B15[525C0000] <1> mov dx, [HF_PORT] 5551 0000212E FEC2 <1> inc dl ; HF_PORT+1 5552 <1> ; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM 5553 <1> ;mov cl, 10 5554 <1> ;mov ecx, 10 ; 21/02/2015 5555 <1> ; 10/07/2022 5556 <1> ;xor ecx, ecx 5557 00002130 B10A <1> mov cl, 10 5558 <1> drst1: 5559 00002132 EC <1> in al, dx ; GET RESET STATUS 5560 00002133 3C01 <1> cmp al, 1 5561 <1> ; 04/01/2015 5562 00002135 740C <1> jz short drst2 5563 <1> ;jnz short DRERR ; BAD RESET STATUS 5564 <1> ; Drive/Head Register - bit 4 5565 <1> ;loop drst1 5566 <1> ; 10/07/2022 5567 00002137 FEC9 <1> dec cl 5568 00002139 75F7 <1> jnz short drst1 5569 <1> DRERR: 5570 0000213B C605[CB610000]05 <1> mov byte [DISK_STATUS1], BAD_RESET ; CARD FAILED 5571 00002142 C3 <1> retn 5572 <1> drst2: 5573 <1> ; 14/02/2015 5574 <1> ;mov dx, di 5575 <1> ; 24/12/2021 5576 00002143 89FA <1> mov edx, edi 5577 <1> ;drst3: 5578 <1> ; ; 05/01/2015 5579 <1> ; shl di, 1 5580 <1> ; ; 04/01/2015 5581 <1> ; mov ax, [di+hd_cports] 5582 <1> ; cmp ax, [HF_REG_PORT] 5583 <1> ; je short drst4 5584 <1> ; mov [HF_REG_PORT], ax 5585 <1> ; ; 03/01/2015 5586 <1> ; mov ax, [di+hd_ports] 5587 <1> ; mov [HF_PORT], ax 5588 <1> ; ; 05/01/2014 5589 <1> ; shr di, 1 5590 <1> ; ; 04/01/2015 5591 <1> ; jmp short drst0 ; reset other controller 5592 <1> ;drst4: 5593 <1> ; ; 05/01/2015 5594 <1> ; shr di, 1 5595 <1> ; mov al, [di+hd_dregs] 5596 <1> ; and al, 10h ; bit 4 only 5597 <1> ; shr al, 4 ; bit 4 -> bit 0 5598 <1> ; mov [hf_m_s], al ; (0 = master, 1 = slave) 5599 <1> ; 5600 00002145 A0[565C0000] <1> mov al, [hf_m_s] ; 18/01/2015 5601 0000214A A801 <1> test al, 1 5602 <1> ;jnz short drst6 5603 0000214C 7516 <1> jnz short drst4 5604 0000214E 8065FDEF <1> and byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0 5605 <1> ;drst5: 5606 <1> drst3: 5607 00002152 E813000000 <1> call INIT_DRV ; SET MAX HEADS 5608 <1> ;mov dx, di 5609 00002157 E8A3000000 <1> call HDISK_RECAL ; RECAL TO RESET SEEK SPEED 5610 <1> ; 04/01/2014 5611 <1> ; inc di 5612 <1> ; mov dx, di 5613 <1> ; cmp dl, [HF_NUM] 5614 <1> ; jb short drst3 5615 <1> ;DRE: 5616 0000215C C605[CB610000]00 <1> mov byte [DISK_STATUS1], 0 ; IGNORE ANY SET UP ERRORS 5617 00002163 C3 <1> retn 5618 <1> ;drst6: 5619 <1> drst4: ; Drive/Head Register - bit 4 5620 00002164 804DFD10 <1> or byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1 5621 <1> ;jmp short drst5 5622 00002168 EBE8 <1> jmp short drst3 5623 <1> 5624 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5625 <1> 5626 <1> ;---------------------------------------- 5627 <1> ; INITIALIZE DRIVE (AH = 09H) : 5628 <1> ;---------------------------------------- 5629 <1> ; 03/01/2015 5630 <1> ; According to ATA-ATAPI specification v2.0 to v5.0 5631 <1> ; logical sector per logical track 5632 <1> ; and logical heads - 1 would be set but 5633 <1> ; it is seen as it will be good 5634 <1> ; if physical parameters will be set here 5635 <1> ; because, number of heads <= 16. 5636 <1> ; (logical heads usually more than 16) 5637 <1> ; NOTE: ATA logical parameters (software C, H, S) 5638 <1> ; == INT 13h physical parameters 5639 <1> 5640 <1> ;INIT_DRV: 5641 <1> ; mov byte [CMD_BLOCK+6], SET_PARM_CMD 5642 <1> ; call GET_VEC ; ES:BX -> PARAMETER BLOCK 5643 <1> ; mov al, [es:bx+2] ; GET NUMBER OF HEADS 5644 <1> ; dec al ; CONVERT TO 0-INDEX 5645 <1> ; mov ah, [CMD_BLOCK+5] ; GET SDH REGISTER 5646 <1> ; and ah, 0F0h ; CHANGE HEAD NUMBER 5647 <1> ; or ah, al ; TO MAX HEAD 5648 <1> ; mov [CMD_BLOCK+5], ah 5649 <1> ; mov al, [es:bx+14] ; MAX SECTOR NUMBER 5650 <1> ; mov [CMD_BLOCK+1], al 5651 <1> ; sub ax, ax 5652 <1> ; mov [CMD_BLOCK+3], al ; ZERO FLAGS 5653 <1> ; call COMMAND ; TELL CONTROLLER 5654 <1> ; jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 5655 <1> ; call NOT_BUSY ; WAIT FOR IT TO BE DONE 5656 <1> ; jnz short INIT_EXIT ; TIME OUT 5657 <1> ; call CHECK_STATUS 5658 <1> ;INIT_EXIT: 5659 <1> ; retn 5660 <1> 5661 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5662 <1> 5663 <1> ; 04/01/2015 5664 <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999 5665 <1> ; AHDSK.ASM - INIT_DRIVE 5666 <1> INIT_DRV: 5667 <1> ;xor ah, ah 5668 0000216A 31C0 <1> xor eax, eax ; 21/02/2015 5669 0000216C B00B <1> mov al, 11 ; Physical heads from translated HDPT 5670 0000216E 3825[E0610000] <1> cmp [LBAMode], ah ; 0 5671 00002174 7702 <1> ja short idrv0 5672 00002176 B002 <1> mov al, 2 ; Physical heads from standard HDPT 5673 <1> idrv0: 5674 <1> ; DL = drive number (0 based) 5675 00002178 E80D020000 <1> call GET_VEC 5676 <1> ;push bx 5677 0000217D 53 <1> push ebx ; 21/02/2015 5678 <1> ;add bx, ax 5679 0000217E 01C3 <1> add ebx, eax 5680 <1> ;; 05/01/2015 5681 00002180 8A25[565C0000] <1> mov ah, [hf_m_s] ; drive number (0= master, 1= slave) 5682 <1> ;;and ah, 1 5683 00002186 C0E404 <1> shl ah, 4 5684 00002189 80CCA0 <1> or ah, 0A0h ; Drive/Head register - 10100000b (A0h) 5685 <1> ;mov al, [es:bx] 5686 0000218C 8A03 <1> mov al, [ebx] ; 21/02/2015 5687 0000218E FEC8 <1> dec al ; last head number 5688 <1> ;and al, 0Fh 5689 00002190 08E0 <1> or al, ah ; lower 4 bits for head number 5690 <1> ; 5691 00002192 C645FE91 <1> mov byte [CMD_BLOCK+6], SET_PARM_CMD 5692 00002196 8845FD <1> mov [CMD_BLOCK+5], al 5693 <1> ;pop bx 5694 00002199 5B <1> pop ebx 5695 0000219A 29C0 <1> sub eax, eax ; 21/02/2015 5696 0000219C B004 <1> mov al, 4 ; Physical sec per track from translated HDPT 5697 0000219E 803D[E0610000]00 <1> cmp byte [LBAMode], 0 5698 000021A5 7702 <1> ja short idrv1 5699 000021A7 B00E <1> mov al, 14 ; Physical sec per track from standard HDPT 5700 <1> idrv1: 5701 <1> ;xor ah, ah 5702 <1> ;add bx, ax 5703 000021A9 01C3 <1> add ebx, eax ; 21/02/2015 5704 <1> ;mov al, [es:bx] 5705 <1> ; sector number 5706 000021AB 8A03 <1> mov al, [ebx] 5707 000021AD 8845F9 <1> mov [CMD_BLOCK+1], al 5708 000021B0 28C0 <1> sub al, al 5709 000021B2 8845FB <1> mov [CMD_BLOCK+3], al ; ZERO FLAGS 5710 000021B5 E87B000000 <1> call COMMAND ; TELL CONTROLLER 5711 000021BA 751E <1> jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 5712 000021BC E816010000 <1> call NOT_BUSY ; WAIT FOR IT TO BE DONE 5713 000021C1 7517 <1> jnz short INIT_EXIT ; TIME OUT 5714 <1> ;call CHECK_STATUS 5715 <1> ;jmp short CHECK_STATUS 5716 <1> ;INIT_EXIT: 5717 <1> ;retn 5718 <1> 5719 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5720 <1> 5721 <1> ;---------------------------------------- 5722 <1> ; CHECK FIXED DISK STATUS : 5723 <1> ;---------------------------------------- 5724 <1> CHECK_STATUS: 5725 000021C3 E861010000 <1> call CHECK_ST ; CHECK THE STATUS BYTE 5726 <1> ;jnz short CHECK_S1 ; AN ERROR WAS FOUND 5727 <1> ; 10/07/2022 5728 000021C8 7510 <1> jnz short CHECK_S2 5729 000021CA A801 <1> test al, ST_ERROR ; WERE THERE ANY OTHER ERRORS 5730 000021CC 7405 <1> jz short CHECK_S1 ; NO ERROR REPORTED 5731 000021CE E894010000 <1> call CHECK_ER ; ERROR REPORTED 5732 <1> CHECK_S1: 5733 000021D3 803D[CB610000]00 <1> cmp byte [DISK_STATUS1], 0 ; SET STATUS FOR CALLER 5734 <1> CHECK_S2: 5735 <1> INIT_EXIT: ; 10/07/2022 5736 000021DA C3 <1> retn 5737 <1> 5738 <1> ;---------------------------------------- 5739 <1> ; TEST DISK READY (AH = 10H) : 5740 <1> ;---------------------------------------- 5741 <1> 5742 <1> TST_RDY: ; WAIT FOR CONTROLLER 5743 000021DB E8F7000000 <1> call NOT_BUSY 5744 000021E0 751C <1> jnz short TR_EX 5745 000021E2 8A45FD <1> mov al, [CMD_BLOCK+5] ; SELECT DRIVE 5746 000021E5 668B15[525C0000] <1> mov dx, [HF_PORT] 5747 000021EC 80C206 <1> add dl,6 5748 000021EF EE <1> out dx, al 5749 000021F0 E834010000 <1> call CHECK_ST ; CHECK STATUS ONLY 5750 000021F5 7507 <1> jnz short TR_EX 5751 000021F7 C605[CB610000]00 <1> mov byte [DISK_STATUS1], 0 ; WIPE OUT DATA CORRECTED ERROR 5752 <1> TR_EX: 5753 000021FE C3 <1> retn 5754 <1> 5755 <1> ;---------------------------------------- 5756 <1> ; RECALIBRATE (AH = 11H) : 5757 <1> ;---------------------------------------- 5758 <1> 5759 <1> HDISK_RECAL: 5760 000021FF C645FE10 <1> mov byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16 5761 00002203 E82D000000 <1> call COMMAND ; START THE OPERATION 5762 00002208 7523 <1> jnz short RECAL_EXIT ; ERROR 5763 0000220A E898000000 <1> call _WAIT ; WAIT FOR COMPLETION 5764 0000220F 7407 <1> jz short RECAL_X ; TIME OUT ONE OK ? 5765 00002211 E891000000 <1> call _WAIT ; WAIT FOR COMPLETION LONGER 5766 00002216 7515 <1> jnz short RECAL_EXIT ; TIME OUT TWO TIMES IS ERROR 5767 <1> RECAL_X: 5768 00002218 E8A6FFFFFF <1> call CHECK_STATUS 5769 0000221D 803D[CB610000]40 <1> cmp byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE 5770 00002224 7507 <1> jne short RECAL_EXIT ; IS OK 5771 00002226 C605[CB610000]00 <1> mov byte [DISK_STATUS1], 0 5772 <1> RECAL_EXIT: 5773 0000222D 803D[CB610000]00 <1> cmp byte [DISK_STATUS1], 0 5774 00002234 C3 <1> retn 5775 <1> 5776 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5777 <1> 5778 <1> ;-------------------------------------------------------- 5779 <1> ; COMMAND : 5780 <1> ; THIS ROUTINE OUTPUTS THE COMMAND BLOCK : 5781 <1> ; OUTPUT : 5782 <1> ; BL = STATUS : 5783 <1> ; BH = ERROR REGISTER : 5784 <1> ;-------------------------------------------------------- 5785 <1> 5786 <1> COMMAND: 5787 <1> ;push ebx ; 10/07/2022 ; WAIT FOR SEEK COMPLETE AND READY 5788 <1> ;;mov ecx, DELAY_2 ; SET INITIAL DELAY BEFORE TEST 5789 <1> COMMAND1: 5790 <1> ;;push ecx ; SAVE LOOP COUNT 5791 00002235 E8A1FFFFFF <1> call TST_RDY ; CHECK DRIVE READY 5792 <1> ;;pop ecx 5793 <1> ;pop ebx ; 10/07/2022 5794 0000223A 7418 <1> jz short COMMAND2 ; DRIVE IS READY 5795 0000223C 803D[CB610000]80 <1> cmp byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP 5796 <1> ;jz short CMD_TIMEOUT 5797 <1> ;;loop COMMAND1 ; KEEP TRYING FOR A WHILE 5798 <1> ;jmp short COMMAND4 ; ITS NOT GOING TO GET READY 5799 00002243 7507 <1> jne short COMMAND4 5800 <1> CMD_TIMEOUT: 5801 00002245 C605[CB610000]20 <1> mov byte [DISK_STATUS1], BAD_CNTLR 5802 <1> COMMAND4: 5803 <1> ;;pop ebx ; 10/07/2022 5804 0000224C 803D[CB610000]00 <1> cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5805 00002253 C3 <1> retn 5806 <1> COMMAND2: 5807 <1> ;;pop ebx ; 10/07/2022 5808 <1> ;push edi ; 10/07/2022 5809 00002254 C605[C6610000]00 <1> mov byte [HF_INT_FLAG], 0 ; RESET INTERRUPT FLAG 5810 0000225B FA <1> cli ; INHIBIT INTERRUPTS WHILE CHANGING MASK 5811 0000225C E4A1 <1> in al, INTB01 ; TURN ON SECOND INTERRUPT CHIP 5812 <1> ;and al, 0BFh 5813 0000225E 243F <1> and al, 3Fh ; Enable IRQ 14 & 15 5814 <1> ;JMP $+2 5815 <1> IODELAY 2130 00002260 EB00 <2> jmp short $+2 2131 00002262 EB00 <2> jmp short $+2 5816 00002264 E6A1 <1> out INTB01, al 5817 00002266 E421 <1> in al, INTA01 ; LET INTERRUPTS PASS THRU TO 5818 00002268 24FB <1> and al, 0FBh ; SECOND CHIP 5819 <1> ;JMP $+2 5820 <1> IODELAY 2130 0000226A EB00 <2> jmp short $+2 2131 0000226C EB00 <2> jmp short $+2 5821 0000226E E621 <1> out INTA01, al 5822 00002270 FB <1> sti 5823 <1> ;xor edi, edi ; INDEX THE COMMAND TABLE 5824 <1> ; 10/07/2022 5825 00002271 31C9 <1> xor ecx, ecx 5826 <1> ;mov dx, HF_PORT+1 ; DISK ADDRESS 5827 00002273 668B15[525C0000] <1> mov dx, [HF_PORT] 5828 0000227A FEC2 <1> inc dl 5829 0000227C F605[CD610000]C0 <1> test byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION 5830 00002283 7411 <1> jz short COMMAND3 5831 00002285 8A45FE <1> mov al, [CMD_BLOCK+6] ; YES-GET OPERATION CODE 5832 00002288 24F0 <1> and al, 0F0h ; GET RID OF MODIFIERS 5833 0000228A 3C20 <1> cmp al, 20h ; 20H-40H IS READ, WRITE, VERIFY 5834 0000228C 7208 <1> jb short COMMAND3 5835 0000228E 3C40 <1> cmp al, 40h 5836 00002290 7704 <1> ja short COMMAND3 5837 00002292 804DFE01 <1> or byte [CMD_BLOCK+6], NO_RETRIES 5838 <1> ; VALID OPERATION FOR RETRY SUPPRESS 5839 <1> COMMAND3: 5840 <1> ;mov al, [CMD_BLOCK+edi] ; GET THE COMMAND STRING BYTE 5841 <1> ; 10/07/2022 5842 00002296 8A440DF8 <1> mov al, [CMD_BLOCK+ecx] 5843 0000229A EE <1> out dx, al ; GIVE IT TO CONTROLLER 5844 <1> IODELAY 2130 0000229B EB00 <2> jmp short $+2 2131 0000229D EB00 <2> jmp short $+2 5845 <1> ;inc edi ; NEXT BYTE IN COMMAND BLOCK 5846 <1> ; 10/07/2022 5847 0000229F 41 <1> inc ecx 5848 <1> ;inc dx ; NEXT DISK ADAPTER REGISTER 5849 000022A0 42 <1> inc edx ; 10/07/2022 5850 <1> ;cmp di, 7 ; 01/01/2015 ; ALL DONE? 5851 <1> ;jne short COMMAND3 ; NO--GO DO NEXT ONE 5852 000022A1 80F907 <1> cmp cl, 7 ; 10/07/2022 5853 000022A4 72F0 <1> jb short COMMAND3 5854 <1> ;pop edi ; 10/07/2022 5855 000022A6 C3 <1> retn ; ZERO FLAG IS SET 5856 <1> 5857 <1> ;CMD_TIMEOUT: 5858 <1> ; mov byte [DISK_STATUS1], BAD_CNTLR 5859 <1> ;COMMAND4: 5860 <1> ; pop ebx 5861 <1> ; cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5862 <1> ; retn 5863 <1> 5864 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5865 <1> 5866 <1> ;---------------------------------------- 5867 <1> ; WAIT FOR INTERRUPT : 5868 <1> ;---------------------------------------- 5869 <1> ;WAIT: 5870 <1> _WAIT: 5871 000022A7 FB <1> sti ; MAKE SURE INTERRUPTS ARE ON 5872 <1> ;sub cx, cx ; SET INITIAL DELAY BEFORE TEST 5873 <1> ;clc 5874 <1> ;mov ax, 9000h ; DEVICE WAIT INTERRUPT 5875 <1> ;int 15h 5876 <1> ;jc short WT2 ; DEVICE TIMED OUT 5877 <1> ;mov bl, DELAY_1 ; SET DELAY COUNT 5878 <1> 5879 <1> ;mov bl, WAIT_HDU_INT_HI 5880 <1> ;; 21/02/2015 5881 <1> ;;mov bl, WAIT_HDU_INT_HI + 1 5882 <1> ;;mov cx, WAIT_HDU_INT_LO 5883 000022A8 B915160500 <1> mov ecx, WAIT_HDU_INT_LH 5884 <1> ; (AWARD BIOS -> WAIT_FOR_MEM) 5885 <1> ;----- WAIT LOOP 5886 <1> 5887 <1> WT1: 5888 <1> ;test byte [HF_INT_FLAG], 80h ; TEST FOR INTERRUPT 5889 000022AD F605[C6610000]C0 <1> test byte [HF_INT_FLAG], 0C0h 5890 <1> ;loopz WT1 5891 000022B4 7512 <1> jnz short WT3 ; INTERRUPT--LETS GO 5892 <1> ;dec bl 5893 <1> ;jnz short WT1 ; KEEP TRYING FOR A WHILE 5894 <1> 5895 <1> WT1_hi: 5896 000022B6 E461 <1> in al, SYS1 ; 61h (PORT_B) ; wait for lo to hi 5897 000022B8 A810 <1> test al, 10h ; transition on memory 5898 000022BA 75FA <1> jnz short WT1_hi ; refresh. 5899 <1> WT1_lo: 5900 000022BC E461 <1> in al, SYS1 ; 061h (PORT_B) 5901 000022BE A810 <1> test al, 10h 5902 000022C0 74FA <1> jz short WT1_lo 5903 000022C2 E2E9 <1> loop WT1 5904 <1> ;;or bl, bl 5905 <1> ;;jz short WT2 5906 <1> ;;dec bl 5907 <1> ;;jmp short WT1 5908 <1> ;dec bl 5909 <1> ;jnz short WT1 5910 <1> WT2: 5911 <1> ; 10/07/2022 5912 <1> ;mov byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR 5913 000022C4 B080 <1> mov al, TIME_OUT 5914 000022C6 EB07 <1> jmp short WT4 5915 <1> WT3: 5916 <1> ;mov byte [DISK_STATUS1], 0 5917 <1> ;mov byte [HF_INT_FLAG], 0 5918 000022C8 28C0 <1> sub al, al ; 0 5919 000022CA A2[C6610000] <1> mov byte [HF_INT_FLAG], al 5920 <1> WT4: 5921 <1> NB2: 5922 000022CF A2[CB610000] <1> mov byte [DISK_STATUS1], al 5923 <1> 5924 <1> ;cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5925 000022D4 20C0 <1> and al, al 5926 <1> ; zf = 0 -> time out, zf = 1 -> ok 5927 000022D6 C3 <1> retn 5928 <1> 5929 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5930 <1> 5931 <1> ;---------------------------------------- 5932 <1> ; WAIT FOR CONTROLLER NOT BUSY : 5933 <1> ;---------------------------------------- 5934 <1> NOT_BUSY: 5935 000022D7 FB <1> sti ; MAKE SURE INTERRUPTS ARE ON 5936 <1> ;push ebx 5937 <1> ;sub cx, cx ; SET INITIAL DELAY BEFORE TEST 5938 000022D8 668B15[525C0000] <1> mov dx, [HF_PORT] 5939 000022DF 80C207 <1> add dl, 7 ; Status port (HF_PORT+7) 5940 <1> ;mov bl, DELAY_1 5941 <1> ; wait for 10 seconds 5942 <1> ;mov cx, WAIT_HDU_INT_LO ; 1615h 5943 <1> ;;mov bl, WAIT_HDU_INT_HI ; 05h 5944 <1> ;mov bl, WAIT_HDU_INT_HI + 1 5945 000022E2 B915160500 <1> mov ecx, WAIT_HDU_INT_LH ; 21/02/2015 5946 <1> ; 5947 <1> ;;mov byte [wait_count], 0 ; Reset wait counter 5948 <1> NB1: 5949 000022E7 EC <1> in al, dx ; CHECK STATUS 5950 <1> ;test al, ST_BUSY 5951 000022E8 2480 <1> and al, ST_BUSY 5952 <1> ;loopnz NB1 5953 000022EA 74E3 <1> jz short NB2 ; al = 0 ; NOT BUSY--LETS GO 5954 <1> ;dec bl 5955 <1> ;jnz short NB1 ; KEEP TRYING FOR A WHILE 5956 <1> 5957 <1> NB1_hi: 5958 000022EC E461 <1> in al, SYS1 ; wait for hi to lo 5959 000022EE A810 <1> test al, 010h ; transition on memory 5960 000022F0 75FA <1> jnz short NB1_hi ; refresh. 5961 <1> NB1_lo: 5962 000022F2 E461 <1> in al, SYS1 5963 000022F4 A810 <1> test al, 010h 5964 000022F6 74FA <1> jz short NB1_lo 5965 000022F8 E2ED <1> loop NB1 5966 <1> ;dec bl 5967 <1> ;jnz short NB1 5968 <1> ; 5969 <1> ;;cmp byte [wait_count], 182 ; 10 seconds (182 timer ticks) 5970 <1> ;;jb short NB1 5971 <1> ; 5972 <1> ;mov byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR 5973 <1> ;jmp short NB3 5974 000022FA B080 <1> mov al, TIME_OUT 5975 <1> ;NB2: 5976 000022FC EBD1 <1> jmp short NB2 ; 10/07/2022 5977 <1> 5978 <1> ; ;mov byte [DISK_STATUS1], 0 5979 <1> ;;NB3: 5980 <1> ; ;pop ebx 5981 <1> ; mov [DISK_STATUS1], al ;;; will be set after return 5982 <1> ; ;cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5983 <1> ; or al, al ; (zf = 0 --> timeout) 5984 <1> ; retn 5985 <1> 5986 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5987 <1> 5988 <1> ;---------------------------------------- 5989 <1> ; WAIT FOR DATA REQUEST : 5990 <1> ;---------------------------------------- 5991 <1> WAIT_DRQ: 5992 <1> ;mov cx, DELAY_3 5993 <1> ;mov dx, HF_PORT+7 5994 000022FE 668B15[525C0000] <1> mov dx, [HF_PORT] 5995 00002305 80C207 <1> add dl, 7 5996 <1> ;;mov bl, WAIT_HDU_DRQ_HI ; 0 5997 <1> ;mov cx, WAIT_HDU_DRQ_LO ; 1000 (30 milli seconds) 5998 <1> ; (but it is written as 2000 5999 <1> ; micro seconds in ATORGS.ASM file 6000 <1> ; of Award Bios - 1999, D1A0622) 6001 00002308 B9E8030000 <1> mov ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 6002 <1> WQ_1: 6003 0000230D EC <1> in al, dx ; GET STATUS 6004 0000230E A808 <1> test al, ST_DRQ ; WAIT FOR DRQ 6005 00002310 7516 <1> jnz short WQ_OK 6006 <1> ;loop WQ_1 ; KEEP TRYING FOR A SHORT WHILE 6007 <1> WQ_hi: 6008 00002312 E461 <1> in al, SYS1 ; wait for hi to lo 6009 00002314 A810 <1> test al, 010h ; transition on memory 6010 00002316 75FA <1> jnz short WQ_hi ; refresh. 6011 <1> WQ_lo: 6012 00002318 E461 <1> in al, SYS1 6013 0000231A A810 <1> test al, 010h 6014 0000231C 74FA <1> jz short WQ_lo 6015 0000231E E2ED <1> loop WQ_1 6016 <1> 6017 00002320 C605[CB610000]80 <1> mov byte [DISK_STATUS1], TIME_OUT ; ERROR 6018 00002327 F9 <1> stc 6019 <1> WQ_OK: 6020 00002328 C3 <1> retn 6021 <1> ;WQ_OK: 6022 <1> ;clc 6023 <1> ;retn 6024 <1> 6025 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6026 <1> 6027 <1> ;---------------------------------------- 6028 <1> ; CHECK FIXED DISK STATUS BYTE : 6029 <1> ;---------------------------------------- 6030 <1> CHECK_ST: 6031 <1> ;mov dx, HF_PORT+7 ; GET THE STATUS 6032 00002329 668B15[525C0000] <1> mov dx, [HF_PORT] 6033 00002330 80C207 <1> add dl, 7 6034 00002333 EC <1> in al, dx 6035 00002334 A2[C5610000] <1> mov [HF_STATUS], al 6036 <1> ;mov ah, 0 6037 00002339 28E4 <1> sub ah, ah ; 0 6038 0000233B A880 <1> test al, ST_BUSY ; IF STILL BUSY 6039 0000233D 751A <1> jnz short CKST_EXIT ; REPORT OK 6040 0000233F B4CC <1> mov ah, WRITE_FAULT 6041 00002341 A820 <1> test al, ST_WRT_FLT ; CHECK FOR WRITE FAULT 6042 00002343 7514 <1> jnz short CKST_EXIT 6043 00002345 B4AA <1> mov ah, NOT_RDY 6044 00002347 A840 <1> test al, ST_READY ; CHECK FOR NOT READY 6045 00002349 740E <1> jz short CKST_EXIT 6046 0000234B B440 <1> mov ah, BAD_SEEK 6047 0000234D A810 <1> test al, ST_SEEK_COMPL ; CHECK FOR SEEK NOT COMPLETE 6048 0000234F 7408 <1> jz short CKST_EXIT 6049 00002351 B411 <1> mov ah, DATA_CORRECTED 6050 00002353 A804 <1> test al, ST_CORRCTD ; CHECK FOR CORRECTED ECC 6051 00002355 7502 <1> jnz short CKST_EXIT 6052 <1> ;mov ah, 0 6053 00002357 30E4 <1> xor ah, ah ; 0 6054 <1> CKST_EXIT: 6055 00002359 8825[CB610000] <1> mov [DISK_STATUS1], ah ; SET ERROR FLAG 6056 0000235F 80FC11 <1> cmp ah, DATA_CORRECTED ; KEEP GOING WITH DATA CORRECTED 6057 00002362 7402 <1> je short CKST_EX1 6058 <1> ;cmp ah, 0 6059 00002364 20E4 <1> and ah, ah 6060 <1> CKST_EX1: 6061 00002366 C3 <1> retn 6062 <1> 6063 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6064 <1> 6065 <1> ;---------------------------------------- 6066 <1> ; CHECK FIXED DISK ERROR REGISTER : 6067 <1> ;---------------------------------------- 6068 <1> CHECK_ER: 6069 <1> ;mov dx, HF_PORT+1 ; GET THE ERROR REGISTER 6070 00002367 668B15[525C0000] <1> mov dx, [HF_PORT] ; 6071 0000236E FEC2 <1> inc dl 6072 00002370 EC <1> in al, dx 6073 <1> ; 10/07/2022 6074 <1> ;mov [HF_ERROR], al 6075 <1> ;push ebx ; 21/02/2015 6076 00002371 29C9 <1> sub ecx, ecx 6077 <1> ;mov ecx, 8 ; TEST ALL 8 BITS 6078 00002373 B108 <1> mov cl, 8 6079 <1> CK1: 6080 00002375 D0E0 <1> shl al, 1 ; MOVE NEXT ERROR BIT TO CARRY 6081 00002377 7202 <1> jc short CK2 ; FOUND THE ERROR 6082 00002379 E2FA <1> loop CK1 ; KEEP TRYING 6083 <1> CK2: 6084 <1> ;mov ebx, ERR_TBL ; COMPUTE ADDRESS OF 6085 <1> ;add ebx, ecx ; ERROR CODE 6086 0000237B 81C1[485C0000] <1> add ecx, ERR_TBL ; 10/07/2022 6087 <1> 6088 <1> ;;;mov ah, byte [cs:bx] ; GET ERROR CODE 6089 <1> ;;mov ah, [bx] 6090 <1> ;mov ah, [ebx] ; 21/02/2015 6091 00002381 8A21 <1> mov ah, [ecx] 6092 <1> CKEX: 6093 00002383 8825[CB610000] <1> mov [DISK_STATUS1], ah ; SAVE ERROR CODE 6094 <1> ; 10/07/2022 6095 <1> ;pop ebx 6096 <1> ;;cmp ah, 0 6097 <1> ;and ah, ah 6098 00002389 C3 <1> retn 6099 <1> 6100 <1> ;-------------------------------------------------------- 6101 <1> ; CHECK_DMA : 6102 <1> ; -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL : 6103 <1> ; FIT WITHOUT SEGMENT OVERFLOW. : 6104 <1> ; -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X : 6105 <1> ; -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE) : 6106 <1> ; -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H) : 6107 <1> ; -ERROR OTHERWISE : 6108 <1> ;-------------------------------------------------------- 6109 <1> 6110 <1> ; 11/07/2022 6111 <1> ; (not needed for hard disks and 32 bit OS) 6112 <1> ; 6113 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6114 <1> ;CHECK_DMA: 6115 <1> ; ;;push ax ; SAVE REGISTERS 6116 <1> ; ;; 24/12/2021 6117 <1> ; ;;push eax 6118 <1> ; ;mov ax, 8000h ; AH = MAX # SECTORS 6119 <1> ; ; AL = MAX OFFSET 6120 <1> ; ; 10/07/2022 6121 <1> ; ;test byte [CMD_BLOCK+6], ECC_MODE 6122 <1> ; ;jz short CKD1 6123 <1> ; ;mov ax, 7F04h ; ECC IS 4 MORE BYTES 6124 <1> ;CKD1: 6125 <1> ; ;cmp ah, [CMD_BLOCK+1] ; NUMBER OF SECTORS 6126 <1> ; ;ja short CKDOK ; IT WILL FIT 6127 <1> ; ;jb short CKDERR ; TOO MANY 6128 <1> ; 6129 <1> ; cmp byte [CMD_BLOCK+1], 80h 6130 <1> ; jb short CKDOK 6131 <1> ; ja short CKDERR 6132 <1> ; ;cmp al, bl ; CHECK OFFSET ON MAX SECTORS 6133 <1> ; ;jb short CKDERR ; ERROR 6134 <1> ;CKD2: 6135 <1> ; or bl, bl 6136 <1> ; jz short CKDR 6137 <1> ; 6138 <1> ;;CKDOK: 6139 <1> ; ;clc ; CLEAR CARRY 6140 <1> ; ;;pop ax 6141 <1> ; ;; 24/12/2021 6142 <1> ; ;pop eax 6143 <1> ; ;retn ; NORMAL RETURN 6144 <1> ;CKDERR: 6145 <1> ; stc ; INDICATE ERROR 6146 <1> ; mov byte [DISK_STATUS1], DMA_BOUNDARY 6147 <1> ; ;;pop ax 6148 <1> ; ;; 24/12/2021 6149 <1> ; ;pop eax 6150 <1> ; retn 6151 <1> ; 6152 <1> ; ; 10/07/2022 6153 <1> ;CKDOK: 6154 <1> ; clc 6155 <1> ;CKDR: 6156 <1> ; retn 6157 <1> 6158 <1> ;---------------------------------------- 6159 <1> ; SET UP EBX-> DISK PARMS : 6160 <1> ;---------------------------------------- 6161 <1> 6162 <1> ; INPUT -> DL = 0 based drive number 6163 <1> ; OUTPUT -> EBX = disk parameter table address 6164 <1> 6165 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6166 <1> 6167 <1> GET_VEC: 6168 <1> ;sub ax, ax ; GET DISK PARAMETER ADDRESS 6169 <1> ;mov es, ax 6170 <1> ;test dl, 1 6171 <1> ;jz short GV_0 6172 <1> ; les bx, [HF1_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 6173 <1> ; jmp short GV_EXIT 6174 <1> ;GV_0: 6175 <1> ; les bx,[HF_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 6176 <1> ; 6177 0000238A 31DB <1> xor ebx, ebx 6178 0000238C 88D3 <1> mov bl, dl 6179 <1> ;02/01/2015 6180 <1> ;xor bh, bh 6181 <1> ;shl bl, 1 ; port address offset 6182 <1> ;mov ax, [bx+hd_ports] ; Base port address (1F0h, 170h) 6183 <1> ;shl bl, 1 ; dpt pointer offset 6184 0000238E C0E302 <1> shl bl, 2 6185 <1> ;add bx, HF_TBL_VEC ; Disk parameter table pointer 6186 00002391 81C3[D0610000] <1> add ebx, HF_TBL_VEC ; 21/02/2015 6187 <1> ;push word [bx+2] ; dpt segment 6188 <1> ;pop es 6189 <1> ;mov bx, [bx] ; dpt offset 6190 00002397 8B1B <1> mov ebx, [ebx] 6191 <1> ;GV_EXIT: 6192 00002399 C3 <1> retn 6193 <1> 6194 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 6195 <1> hdc1_int: ; 21/02/2015 6196 <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL 14 ) ---------------------- 6197 <1> ; : 6198 <1> ; FIXED DISK INTERRUPT ROUTINE : 6199 <1> ; : 6200 <1> ;---------------------------------------------------------------- 6201 <1> 6202 <1> ; 22/12/2014 6203 <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT) 6204 <1> ; '11/15/85' 6205 <1> ; AWARD BIOS 1999 (D1A0622) 6206 <1> ; Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1) 6207 <1> 6208 <1> ;int_76h: 6209 <1> HD_INT: 6210 <1> ;push ax 6211 <1> ; 24/12/2021 6212 0000239A 50 <1> push eax 6213 0000239B 1E <1> push ds 6214 <1> ;CALL DDS 6215 <1> ; 21/02/2015 (32 bit, 386 pm modification) 6216 0000239C 66B81000 <1> mov ax, KDATA 6217 000023A0 8ED8 <1> mov ds, ax 6218 <1> ; 6219 <1> ;;MOV @HF_INT_FLAG, 0FFH ; ALL DONE 6220 <1> ;mov byte [CS:HF_INT_FLAG], 0FFh 6221 000023A2 C605[C6610000]FF <1> mov byte [HF_INT_FLAG], 0FFh 6222 <1> ; 6223 <1> ;push dx 6224 <1> ; 24/12/2021 6225 000023A9 52 <1> push edx 6226 000023AA 66BAF701 <1> mov dx, HDC1_BASEPORT+7 ; Status Register (1F7h) 6227 <1> ; Clear Controller 6228 <1> Clear_IRQ1415: ; (Award BIOS - 1999) 6229 000023AE EC <1> in al, dx ; 6230 <1> ;pop dx 6231 <1> ; 24/12/2021 6232 000023AF 5A <1> pop edx 6233 <1> NEWIODELAY 2135 000023B0 E6EB <2> out 0EBh,al 6234 <1> ; 6235 000023B2 B020 <1> mov al, EOI ; NON-SPECIFIC END OF INTERRUPT 6236 000023B4 E6A0 <1> out INTB00, al ; FOR CONTROLLER #2 6237 <1> ;JMP $+2 ; WAIT 6238 <1> NEWIODELAY 2135 000023B6 E6EB <2> out 0EBh,al 6239 000023B8 E620 <1> out INTA00, al ; FOR CONTROLLER #1 6240 000023BA 1F <1> pop ds 6241 <1> ;sti ; RE-ENABLE INTERRUPTS 6242 <1> ;mov ax, 9100h ; DEVICE POST 6243 <1> ;int 15h ; INTERRUPT 6244 <1> irq15_iret: ; 25/02/2015 6245 <1> ;pop ax 6246 <1> ; 24/12/2021 6247 000023BB 58 <1> pop eax 6248 000023BC CF <1> iretd ; RETURN FROM INTERRUPT 6249 <1> 6250 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 6251 <1> hdc2_int: ; 21/02/2015 6252 <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL 15 ) ---------------------- 6253 <1> ; : 6254 <1> ; FIXED DISK INTERRUPT ROUTINE : 6255 <1> ; : 6256 <1> ;---------------------------------------------------------------- 6257 <1> 6258 <1> ;int_77h: 6259 <1> HD1_INT: 6260 <1> ;push ax 6261 <1> ; 24/12/2021 6262 000023BD 50 <1> push eax 6263 <1> ; Check if that is a spurious IRQ (from slave PIC) 6264 <1> ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 6265 000023BE B00B <1> mov al, 0Bh ; In-Service Register 6266 000023C0 E6A0 <1> out 0A0h, al 6267 000023C2 EB00 <1> jmp short $+2 6268 000023C4 EB00 <1> jmp short $+2 6269 000023C6 E4A0 <1> in al, 0A0h 6270 000023C8 2480 <1> and al, 80h ; bit 7 (is it real IRQ 15 or fake?) 6271 000023CA 74EF <1> jz short irq15_iret ; Fake (spurious)IRQ, do not send EOI) 6272 <1> ; 6273 000023CC 1E <1> push ds 6274 <1> ;CALL DDS 6275 <1> ; 21/02/2015 (32 bit, 386 pm modification) 6276 000023CD 66B81000 <1> mov ax, KDATA 6277 000023D1 8ED8 <1> mov ds, ax 6278 <1> ; 6279 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 6280 <1> ;or byte [CS:HF_INT_FLAG], 0C0h 6281 000023D3 800D[C6610000]C0 <1> or byte [HF_INT_FLAG], 0C0h 6282 <1> ; 6283 <1> ;push dx 6284 <1> ; 24/12/2021 6285 000023DA 52 <1> push edx 6286 000023DB 66BA7701 <1> mov dx, HDC2_BASEPORT+7 ; Status Register (177h) 6287 <1> ; Clear Controller (Award BIOS 1999) 6288 000023DF EBCD <1> jmp short Clear_IRQ1415 6289 <1> 6290 <1> ;%include 'diskdata.inc' ; 11/03/2015 6291 <1> ;%include 'diskbss.inc' ; 11/03/2015 6292 <1> 6293 <1> ;//////////////////////////////////////////////////////////////////// 6294 <1> ;; END OF DISK I/O SYTEM /// 2049 %include 'memory.inc' ; 09/03/2015 2050 <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) 2051 <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.22) - MEMORY.INC 2052 <1> ; Last Modification: 17/07/2022 2053 <1> ; 2054 <1> ; Source code for NASM - Netwide Assembler (2.15) 2055 <1> 2056 <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.6 - MEMORY.INC (17/07/2022) 2057 <1> 2058 <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) /////////////// 2059 <1> 2060 <1> ;;04/11/2014 (unix386.s) 2061 <1> ;PDE_A_PRESENT equ 1 ; Present flag for PDE 2062 <1> ;PDE_A_WRITE equ 2 ; Writable (write permission) flag 2063 <1> ;PDE_A_USER equ 4 ; User (non-system/kernel) page flag 2064 <1> ;; 2065 <1> ;PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 2066 <1> ;PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 2067 <1> ;PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 2068 <1> ;PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 2069 <1> 2070 <1> ; 27/04/2015 2071 <1> ; 09/03/2015 2072 <1> PAGE_SIZE equ 4096 ; page size in bytes 2073 <1> PAGE_SHIFT equ 12 ; page table shift count 2074 <1> PAGE_D_SHIFT equ 22 ; 12+10 ; page directory shift count 2075 <1> PAGE_OFF equ 0FFFh ; 12 bit byte offset in page frame 2076 <1> PTE_MASK equ 03FFh ; page table entry mask 2077 <1> PTE_DUPLICATED equ 200h ; duplicated page sign (AVL bit 0) 2078 <1> PDE_A_CLEAR equ 0F000h ; to clear PDE attribute bits 2079 <1> PTE_A_CLEAR equ 0F000h ; to clear PTE attribute bits 2080 <1> LOGIC_SECT_SIZE equ 512 ; logical sector size 2081 <1> ERR_MAJOR_PF equ 0E0h ; major error: page fault 2082 <1> ; 15/10/2016 (TRDOS 386 v2) 2083 <1> ERR_MINOR_IM equ 4 ;15/10/2016 (1->4); insufficient (out of) memory 2084 <1> ERR_MINOR_PV equ 6 ;15/10/2016 (3->6); protection violation 2085 <1> SWP_DISK_READ_ERR equ 40 2086 <1> SWP_DISK_NOT_PRESENT_ERR equ 41 2087 <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42 2088 <1> SWP_NO_FREE_SPACE_ERR equ 43 2089 <1> SWP_DISK_WRITE_ERR equ 44 2090 <1> SWP_NO_PAGE_TO_SWAP_ERR equ 45 2091 <1> PTE_A_ACCESS_BIT equ 5 ; Bit 5 (accessed flag) 2092 <1> SECTOR_SHIFT equ 3 ; sector shift (to convert page block number) 2093 <1> ; 10/06/2021 (Retro UNIX 386 v2) 2094 <1> ; 12/07/2016 (TRDOS 386 v2) 2095 <1> PTE_SHARED equ 400h ; AVL bit 1, direct memory access bit 2096 <1> ; (Indicates that the page is not allocated 2097 <1> ; for the process, it is a shared or system 2098 <1> ; page, it must not be deallocated!) 2099 <1> ; 14/12/2020 2100 <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.) 2101 <1> PDE_EXTERNAL equ 400h ; Page directory entry for external memory blocks 2102 <1> PTE_EXTERNAL equ 400h ; Allocated kernel pages for Linear Frame Buffer 2103 <1> ; (Out of memory allocation table) 2104 <1> ; 2105 <1> ;; Retro Unix 386 v1 - paging method/principles 2106 <1> ;; 2107 <1> ;; 10/10/2014 2108 <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES 2109 <1> ;; 2110 <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map 2111 <1> ;; (virtual address = physical address) 2112 <1> ;; KERNEL PAGE TABLES: 2113 <1> ;; Kernel page directory and all page tables are 2114 <1> ;; on memory as initialized, as equal to physical memory 2115 <1> ;; layout. Kernel pages can/must not be swapped out/in. 2116 <1> ;; 2117 <1> ;; what for: User pages may be swapped out, when accessing 2118 <1> ;; a page in kernel/system mode, if it would be swapped out, 2119 <1> ;; kernel would have to swap it in! But it is also may be 2120 <1> ;; in use by a user process. (In system/kernel mode 2121 <1> ;; kernel can access all memory pages even if they are 2122 <1> ;; reserved/allocated for user processes. Swap out/in would 2123 <1> ;; cause conflicts.) 2124 <1> ;; 2125 <1> ;; As result of these conditions, 2126 <1> ;; all kernel pages must be initialized as equal to 2127 <1> ;; physical layout for preventing page faults. 2128 <1> ;; Also, calling "allocate page" procedure after 2129 <1> ;; a page fault can cause another page fault (double fault) 2130 <1> ;; if all kernel page tables would not be initialized. 2131 <1> ;; 2132 <1> ;; [first_page] = Beginning of users space, as offset to 2133 <1> ;; memory allocation table. (double word aligned) 2134 <1> ;; 2135 <1> ;; [next_page] = first/next free space to be searched 2136 <1> ;; as offset to memory allocation table. (dw aligned) 2137 <1> ;; 2138 <1> ;; [last_page] = End of memory (users space), as offset 2139 <1> ;; to memory allocation table. (double word aligned) 2140 <1> ;; 2141 <1> ;; USER PAGE TABLES: 2142 <1> ;; Demand paging (& 'copy on write' allocation method) ... 2143 <1> ;; 'ready only' marked copies of the 2144 <1> ;; parent process's page table entries (for 2145 <1> ;; same physical memory). 2146 <1> ;; (A page will be copied to a new page after 2147 <1> ;; if it causes R/W page fault.) 2148 <1> ;; 2149 <1> ;; Every user process has own (different) 2150 <1> ;; page directory and page tables. 2151 <1> ;; 2152 <1> ;; Code starts at virtual address 0, always. 2153 <1> ;; (Initial value of EIP is 0 in user mode.) 2154 <1> ;; (Programs can be written/developed as simple 2155 <1> ;; flat memory programs.) 2156 <1> ;; 2157 <1> ;; MEMORY ALLOCATION STRATEGY: 2158 <1> ;; Memory page will be allocated by kernel only 2159 <1> ;; (in kernel/system mode only). 2160 <1> ;; * After a 2161 <1> ;; - 'not present' page fault 2162 <1> ;; - 'writing attempt on read only page' page fault 2163 <1> ;; * For loading (opening, reading) a file or disk/drive 2164 <1> ;; * As responce to 'allocate additional memory blocks' 2165 <1> ;; request by running process. 2166 <1> ;; * While creating a process, allocating a new buffer, 2167 <1> ;; new page tables etc. 2168 <1> ;; 2169 <1> ;; At first, 2170 <1> ;; - 'allocate page' procedure will be called; 2171 <1> ;, if it will return with a valid (>0) physical address 2172 <1> ;; (that means the relevant M.A.T. bit has been RESET) 2173 <1> ;; relevant memory page/block will be cleared (zeroed). 2174 <1> ;; - 'allocate page' will be called for allocating page 2175 <1> ;; directory, page table and running space (data/code). 2176 <1> ;; - every successful 'allocate page' call will decrease 2177 <1> ;; 'free_pages' count (pointer). 2178 <1> ;; - 'out of (insufficient) memory error' will be returned 2179 <1> ;; if 'free_pages' points to a ZERO. 2180 <1> ;; - swapping out and swapping in (if it is not a new page) 2181 <1> ;; procedures will be called as responce to 'out of memory' 2182 <1> ;; error except errors caused by attribute conflicts. 2183 <1> ;; (swapper functions) 2184 <1> ;; 2185 <1> ;; At second, 2186 <1> ;; - page directory entry will be updated then page table 2187 <1> ;; entry will be updated. 2188 <1> ;; 2189 <1> ;; MEMORY ALLOCATION TABLE FORMAT: 2190 <1> ;; - M.A.T. has a size according to available memory as 2191 <1> ;; follows: 2192 <1> ;; - 1 (allocation) bit per 1 page (4096 bytes) 2193 <1> ;; - a bit with value of 0 means allocated page 2194 <1> ;; - a bit with value of 1 means a free page 2195 <1> ;, - 'free_pages' pointer holds count of free pages 2196 <1> ;; depending on M.A.T. 2197 <1> ;; (NOTE: Free page count will not be checked 2198 <1> ;; again -on M.A.T.- after initialization. 2199 <1> ;; Kernel will trust on initial count.) 2200 <1> ;, - 'free_pages' count will be decreased by allocation 2201 <1> ;; and it will be increased by deallocation procedures. 2202 <1> ;; 2203 <1> ;; - Available memory will be calculated during 2204 <1> ;; the kernel's initialization stage (in real mode). 2205 <1> ;; Memory allocation table and kernel page tables 2206 <1> ;; will be formatted/sized as result of available 2207 <1> ;; memory calculation before paging is enabled. 2208 <1> ;; 2209 <1> ;; For 4GB Available/Present Memory: (max. possible memory size) 2210 <1> ;; - Memory Allocation Table size will be 128 KB. 2211 <1> ;; - Memory allocation for kernel page directory size 2212 <1> ;; is always 4 KB. (in addition to total allocation size 2213 <1> ;; for page tables) 2214 <1> ;; - Memory allocation for kernel page tables (1024 tables) 2215 <1> ;; is 4 MB (1024*4*1024 bytes). 2216 <1> ;; - User (available) space will be started 2217 <1> ;; at 6th MB of the memory (after 1MB+4MB). 2218 <1> ;; - The first 640 KB is for kernel's itself plus 2219 <1> ;; memory allocation table and kernel's page directory 2220 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 2221 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 2222 <1> ;; for buffers. 2223 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 2224 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 2225 <1> ;; - Kernel page tables start at 100000h (2nd MB) 2226 <1> ;; 2227 <1> ;; For 1GB Available Memory: 2228 <1> ;; - Memory Allocation Table size will be 32 KB. 2229 <1> ;; - Memory allocation for kernel page directory size 2230 <1> ;; is always 4 KB. (in addition to total allocation size 2231 <1> ;; for page tables) 2232 <1> ;; - Memory allocation for kernel page tables (256 tables) 2233 <1> ;; is 1 MB (256*4*1024 bytes). 2234 <1> ;; - User (available) space will be started 2235 <1> ;; at 3th MB of the memory (after 1MB+1MB). 2236 <1> ;; - The first 640 KB is for kernel's itself plus 2237 <1> ;; memory allocation table and kernel's page directory 2238 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 2239 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 2240 <1> ;; for buffers. 2241 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 2242 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 2243 <1> ;; - Kernel page tables start at 100000h (2nd MB). 2244 <1> ;; 2245 <1> ;; 2246 <1> 2247 <1> ;;************************************************************************************ 2248 <1> ;; 2249 <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle) 2250 <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015) 2251 <1> 2252 <1> ;; Main factor: "sys fork" system call 2253 <1> ;; 2254 <1> ;; FORK 2255 <1> ;; |----> parent - duplicated PTEs, read only pages 2256 <1> ;; writable pages ---->| 2257 <1> ;; |----> child - duplicated PTEs, read only pages 2258 <1> ;; 2259 <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 2260 <1> ;; 2261 <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set) 2262 <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9) 2263 <1> ;; -while R/W bit is 0-. 2264 <1> ;; 2265 <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process): 2266 <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 2267 <1> ;; as duplicated PTE bit -AVL bit 0, PTE bit 9- are reset/clear. 2268 <1> ;; # Then Parent's Page Table is copied to Child's Page Table. 2269 <1> ;; # Child's Page Table Entries are updated as duplicated child bit 2270 <1> ;; -AVL bit 0, PTE bit 9- is set. 2271 <1> ;; 2272 <1> ;; Duplicate page tables with read only pages (several sys fork system calls): 2273 <1> ;; # Parent's read only pages are copied to new child pages. 2274 <1> ;; Parent's PTE attributes are not changed. 2275 <1> ;; (Because, there is another parent-child fork before this fork! We must not 2276 <1> ;; destroy/mix previous fork result). 2277 <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 2278 <1> ;; read only pages) are set as writable (while duplicated PTE bit is clear). 2279 <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 2280 <1> ;; as read only, (while) duplicated PTE bit is reset (clear). 2281 <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 2282 <1> ;; as Child's Page Table Entries without copying actual page. 2283 <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 2284 <1> ;; pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set. 2285 <1> ;; 2286 <1> ;; !? WHAT FOR (duplication after duplication): 2287 <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init) 2288 <1> ;; program/executable code continues from specified location as child process, 2289 <1> ;; returns back previous code location as parent process, every child after 2290 <1> ;; every sys fork uses last image of code and data just prior the fork. 2291 <1> ;; Even if the parent code changes data, the child will not see the changed data 2292 <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB) 2293 <1> ;; was copied to child's process segment (all of code and data) according to 2294 <1> ;; original UNIX v1 which copies all of parent process code and data -core- 2295 <1> ;; to child space -core- but swaps that core image -of child- on to disk. 2296 <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core 2297 <1> ;; (complete running image of parent process) to the child process; 2298 <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 2299 <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork, 2300 <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes 2301 <1> ;; a new/fresh core -running space-, by clearing all code/data content). 2302 <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write 2303 <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 2304 <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and 2305 <1> ;; new/fresh pages will be used to load and run new executable/program. 2306 <1> ;; That is what for i have preferred "copy on write", "duplication" method 2307 <1> ;; for sharing same read only pages between parent and child processes. 2308 <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 2309 <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 2310 <1> ;; and it's child processes; otherwise parent process would destroy data belongs 2311 <1> ;; to its child or vice versa; or some pages would remain unclaimed 2312 <1> ;; -deallocation problem-. 2313 <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 2314 <1> ;; 2315 <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 2316 <1> ;; # Page fault handler will do those: 2317 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 2318 <1> ;; - If it is reset/clear, there is a child uses same page. 2319 <1> ;; - Parent's read only page -previous page- is copied to a new writable page. 2320 <1> ;; - Parent's PTE is updated as writable page, as unique page (AVL=0) 2321 <1> ;; - (Page fault handler whill check this PTE later, if child process causes to 2322 <1> ;; page fault due to write attempt on read only page. Of course, the previous 2323 <1> ;; read only page will be converted to writable and unique page which belongs 2324 <1> ;; to child process.) 2325 <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 2326 <1> ;; # Page fault handler will do those: 2327 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 2328 <1> ;; - If it is set, there is a parent uses -or was using- same page. 2329 <1> ;; - Same PTE address within parent's page table is checked if it has same page 2330 <1> ;; address or not. 2331 <1> ;; - If parent's PTE has same address, child will continue with a new writable page. 2332 <1> ;; Parent's PTE will point to same (previous) page as writable, unique (AVL=0). 2333 <1> ;; - If parent's PTE has different address, child will continue with it's 2334 <1> ;; own/same page but read only flag (0) will be changed to writable flag (1) and 2335 <1> ;; 'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 2336 <1> ;; 2337 <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables 2338 <1> ;; will be set as writable (and unique) in case of child process was using 2339 <1> ;; same pages with duplicated child PTE sign... Depending on sys fork and 2340 <1> ;; duplication method details, it is not possible multiple child processes 2341 <1> ;; were using same page with duplicated PTEs. 2342 <1> ;; 2343 <1> ;;************************************************************************************ 2344 <1> 2345 <1> ;; 08/10/2014 2346 <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft 2347 <1> ;; by Erdogan Tan (Based on KolibriOS 'memory.inc') 2348 <1> 2349 <1> ;; 'allocate_page' code is derived and modified from KolibriOS 2350 <1> ;; 'alloc_page' procedure in 'memory.inc' 2351 <1> ;; (25/08/2014, Revision: 5057) file 2352 <1> ;; by KolibriOS Team (2004-2012) 2353 <1> 2354 <1> allocate_page: 2355 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2356 <1> ; 01/07/2015 2357 <1> ; 05/05/2015 2358 <1> ; 30/04/2015 2359 <1> ; 16/10/2014 2360 <1> ; 08/10/2014 2361 <1> ; 09/09/2014 (Retro UNIX 386 v1 - beginning) 2362 <1> ; 2363 <1> ; INPUT -> none 2364 <1> ; 2365 <1> ; OUTPUT -> 2366 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 2367 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is RESET) 2368 <1> ; 2369 <1> ; CF = 1 and EAX = 0 2370 <1> ; if there is not a free page to be allocated 2371 <1> ; 2372 <1> ; Modified Registers -> none (except EAX) 2373 <1> ; 2374 000023E1 A1[40610000] <1> mov eax, [free_pages] 2375 000023E6 21C0 <1> and eax, eax 2376 000023E8 7438 <1> jz short out_of_memory 2377 <1> ; 2378 000023EA 53 <1> push ebx 2379 000023EB 51 <1> push ecx 2380 <1> ; 2381 000023EC BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table offset 2382 000023F1 89D9 <1> mov ecx, ebx 2383 <1> ; NOTE: 32 (first_page) is initial 2384 <1> ; value of [next_page]. 2385 <1> ; It points to the first available 2386 <1> ; page block for users (ring 3) ... 2387 <1> ; (MAT offset 32 = 1024/32) 2388 <1> ; (at the of the first 4 MB) 2389 000023F3 031D[44610000] <1> add ebx, [next_page] ; Free page searching starts from here 2390 <1> ; next_free_page >> 5 2391 000023F9 030D[48610000] <1> add ecx, [last_page] ; Free page searching ends here 2392 <1> ; (total_pages - 1) >> 5 2393 <1> al_p_scan: 2394 000023FF 39CB <1> cmp ebx, ecx 2395 00002401 770A <1> ja short al_p_notfound 2396 <1> ; 2397 <1> ; 01/07/2015 2398 <1> ; AMD64 Architecture Programmer’s Manual 2399 <1> ; Volume 3: 2400 <1> ; General-Purpose and System Instructions 2401 <1> ; 2402 <1> ; BSF - Bit Scan Forward 2403 <1> ; 2404 <1> ; Searches the value in a register or a memory location 2405 <1> ; (second operand) for the least-significant set bit. 2406 <1> ; If a set bit is found, the instruction clears the zero flag (ZF) 2407 <1> ; and stores the index of the least-significant set bit in a destination 2408 <1> ; register (first operand). If the second operand contains 0, 2409 <1> ; the instruction sets ZF to 1 and does not change the contents of the 2410 <1> ; destination register. The bit index is an unsigned offset from bit 0 2411 <1> ; of the searched value 2412 <1> ; 2413 00002403 0FBC03 <1> bsf eax, [ebx] ; Scans source operand for first bit set (1). 2414 <1> ; Clear ZF if a bit is found set (1) and 2415 <1> ; loads the destination with an index to 2416 <1> ; first set bit. (0 -> 31) 2417 <1> ; Sets ZF to 1 if no bits are found set. 2418 00002406 751C <1> jnz short al_p_found ; ZF = 0 -> a free page has been found 2419 <1> ; 2420 <1> ; NOTE: a Memory Allocation Table bit 2421 <1> ; with value of 1 means 2422 <1> ; the corresponding page is free 2423 <1> ; (Retro UNIX 386 v1 feature only!) 2424 00002408 83C304 <1> add ebx, 4 2425 <1> ; We return back for searching next page block 2426 <1> ; NOTE: [free_pages] is not ZERO; so, 2427 <1> ; we always will find at least 1 free page here. 2428 0000240B EBF2 <1> jmp short al_p_scan 2429 <1> ; 2430 <1> al_p_notfound: 2431 0000240D 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 2432 00002413 890D[44610000] <1> mov [next_page], ecx ; next/first free page = last page 2433 <1> ; (deallocate_page procedure will change it) 2434 00002419 31C0 <1> xor eax, eax 2435 0000241B A3[40610000] <1> mov [free_pages], eax ; 0 2436 00002420 59 <1> pop ecx 2437 00002421 5B <1> pop ebx 2438 <1> ; 2439 <1> ; 24/12/2021 2440 <1> ; ('swap_out' procedure call is disabled) 2441 <1> 2442 <1> out_of_memory: 2443 <1> ; call swap_out 2444 <1> ; jnc short al_p_ok ; [free_pages] = 0, re-allocation by swap_out 2445 <1> ; ; 2446 <1> ; sub eax, eax ; 0 2447 00002422 F9 <1> stc 2448 00002423 C3 <1> retn 2449 <1> 2450 <1> al_p_found: 2451 00002424 89D9 <1> mov ecx, ebx 2452 00002426 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 2453 0000242C 890D[44610000] <1> mov [next_page], ecx ; Set first free page searching start 2454 <1> ; address/offset (to the next) 2455 00002432 FF0D[40610000] <1> dec dword [free_pages] ; 1 page has been allocated (X = X-1) 2456 <1> ; 2457 00002438 0FB303 <1> btr [ebx], eax ; The destination bit indexed by the source value 2458 <1> ; is copied into the Carry Flag and then cleared 2459 <1> ; in the destination. 2460 <1> ; 2461 <1> ; Reset the bit which is corresponding to the 2462 <1> ; (just) allocated page. 2463 <1> ; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages) 2464 0000243B C1E103 <1> shl ecx, 3 ; (page block offset * 32) + page index 2465 0000243E 01C8 <1> add eax, ecx ; = page number 2466 00002440 C1E00C <1> shl eax, 12 ; physical address of the page (flat/real value) 2467 <1> ; EAX = physical address of memory page 2468 <1> ; 2469 <1> ; NOTE: The relevant page directory and page table entry will be updated 2470 <1> ; according to this EAX value... 2471 00002443 59 <1> pop ecx 2472 00002444 5B <1> pop ebx 2473 <1> al_p_ok: 2474 00002445 C3 <1> retn 2475 <1> 2476 <1> make_page_dir: 2477 <1> ; 18/04/2015 2478 <1> ; 12/04/2015 2479 <1> ; 23/10/2014 2480 <1> ; 16/10/2014 2481 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2482 <1> ; 2483 <1> ; INPUT -> 2484 <1> ; none 2485 <1> ; OUTPUT -> 2486 <1> ; (EAX = 0) 2487 <1> ; cf = 1 -> insufficient (out of) memory error 2488 <1> ; cf = 0 -> 2489 <1> ; u.pgdir = page directory (physical) address of the current 2490 <1> ; process/user. 2491 <1> ; 2492 <1> ; Modified Registers -> EAX 2493 <1> ; 2494 00002446 E896FFFFFF <1> call allocate_page 2495 0000244B 7216 <1> jc short mkpd_error 2496 <1> ; 2497 0000244D A3[53650000] <1> mov [u.pgdir], eax ; Page dir address for current user/process 2498 <1> ; (Physical address) 2499 <1> clear_page: 2500 <1> ; 18/04/2015 2501 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2502 <1> ; 2503 <1> ; INPUT -> 2504 <1> ; EAX = physical address of the page 2505 <1> ; OUTPUT -> 2506 <1> ; all bytes of the page will be cleared 2507 <1> ; 2508 <1> ; Modified Registers -> none 2509 <1> ; 2510 00002452 57 <1> push edi 2511 00002453 51 <1> push ecx 2512 00002454 50 <1> push eax 2513 00002455 B900040000 <1> mov ecx, PAGE_SIZE / 4 2514 0000245A 89C7 <1> mov edi, eax 2515 0000245C 31C0 <1> xor eax, eax 2516 0000245E F3AB <1> rep stosd 2517 00002460 58 <1> pop eax 2518 00002461 59 <1> pop ecx 2519 00002462 5F <1> pop edi 2520 <1> mkpd_error: 2521 <1> mkpt_error: 2522 00002463 C3 <1> retn 2523 <1> 2524 <1> make_page_table: 2525 <1> ; 23/06/2015 2526 <1> ; 18/04/2015 2527 <1> ; 12/04/2015 2528 <1> ; 16/10/2014 2529 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2530 <1> ; 2531 <1> ; INPUT -> 2532 <1> ; EBX = virtual (linear) address 2533 <1> ; ECX = page table attributes (lower 12 bits) 2534 <1> ; (higher 20 bits must be ZERO) 2535 <1> ; (bit 0 must be 1) 2536 <1> ; u.pgdir = page directory (physical) address 2537 <1> ; OUTPUT -> 2538 <1> ; EDX = Page directory entry address 2539 <1> ; EAX = Page table address 2540 <1> ; cf = 1 -> insufficient (out of) memory error 2541 <1> ; cf = 0 -> page table address in the PDE (EDX) 2542 <1> ; 2543 <1> ; Modified Registers -> EAX, EDX 2544 <1> ; 2545 00002464 E878FFFFFF <1> call allocate_page 2546 00002469 72F8 <1> jc short mkpt_error 2547 0000246B E811000000 <1> call set_pde 2548 00002470 EBE0 <1> jmp short clear_page 2549 <1> 2550 <1> make_page: 2551 <1> ; 24/07/2015 2552 <1> ; 23/06/2015 ; (Retro UNIX 386 v1 - beginning) 2553 <1> ; 2554 <1> ; INPUT -> 2555 <1> ; EBX = virtual (linear) address 2556 <1> ; ECX = page attributes (lower 12 bits) 2557 <1> ; (higher 20 bits must be ZERO) 2558 <1> ; (bit 0 must be 1) 2559 <1> ; u.pgdir = page directory (physical) address 2560 <1> ; OUTPUT -> 2561 <1> ; EBX = Virtual address 2562 <1> ; (EDX = PTE value) 2563 <1> ; EAX = Physical address 2564 <1> ; cf = 1 -> insufficient (out of) memory error 2565 <1> ; 2566 <1> ; Modified Registers -> EAX, EDX 2567 <1> ; 2568 00002472 E86AFFFFFF <1> call allocate_page 2569 00002477 7207 <1> jc short mkp_err 2570 00002479 E821000000 <1> call set_pte 2571 0000247E 73D2 <1> jnc short clear_page ; 18/04/2015 2572 <1> mkp_err: 2573 00002480 C3 <1> retn 2574 <1> 2575 <1> set_pde: ; Set page directory entry (PDE) 2576 <1> ; 20/07/2015 2577 <1> ; 18/04/2015 2578 <1> ; 12/04/2015 2579 <1> ; 23/10/2014 2580 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2581 <1> ; 2582 <1> ; INPUT -> 2583 <1> ; EAX = physical address 2584 <1> ; (use present value if EAX = 0) 2585 <1> ; EBX = virtual (linear) address 2586 <1> ; ECX = page table attributes (lower 12 bits) 2587 <1> ; (higher 20 bits must be ZERO) 2588 <1> ; (bit 0 must be 1) 2589 <1> ; u.pgdir = page directory (physical) address 2590 <1> ; OUTPUT -> 2591 <1> ; EDX = PDE address 2592 <1> ; EAX = page table address (physical) 2593 <1> ; ;(CF=1 -> Invalid page address) 2594 <1> ; 2595 <1> ; Modified Registers -> EDX 2596 <1> ; 2597 00002481 89DA <1> mov edx, ebx 2598 00002483 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 2599 00002486 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 2600 00002489 0315[53650000] <1> add edx, [u.pgdir] 2601 <1> ; 2602 0000248F 21C0 <1> and eax, eax 2603 00002491 7506 <1> jnz short spde_1 2604 <1> ; 2605 00002493 8B02 <1> mov eax, [edx] ; old PDE value 2606 <1> ;test al, 1 2607 <1> ;jz short spde_2 2608 00002495 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2609 <1> spde_1: 2610 <1> ;and cx, 0FFFh 2611 00002499 8902 <1> mov [edx], eax 2612 0000249B 66090A <1> or [edx], cx 2613 0000249E C3 <1> retn 2614 <1> ;spde_2: ; error 2615 <1> ; stc 2616 <1> ; retn 2617 <1> 2618 <1> set_pte: ; Set page table entry (PTE) 2619 <1> ; 24/07/2015 2620 <1> ; 20/07/2015 2621 <1> ; 23/06/2015 2622 <1> ; 18/04/2015 2623 <1> ; 12/04/2015 2624 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2625 <1> ; 2626 <1> ; INPUT -> 2627 <1> ; EAX = physical page address 2628 <1> ; (use present value if EAX = 0) 2629 <1> ; EBX = virtual (linear) address 2630 <1> ; ECX = page attributes (lower 12 bits) 2631 <1> ; (higher 20 bits must be ZERO) 2632 <1> ; (bit 0 must be 1) 2633 <1> ; u.pgdir = page directory (physical) address 2634 <1> ; OUTPUT -> 2635 <1> ; EAX = physical page address 2636 <1> ; (EDX = PTE value) 2637 <1> ; EBX = virtual address 2638 <1> ; 2639 <1> ; CF = 1 -> error 2640 <1> ; 2641 <1> ; Modified Registers -> EAX, EDX 2642 <1> ; 2643 0000249F 50 <1> push eax 2644 000024A0 A1[53650000] <1> mov eax, [u.pgdir] ; 20/07/2015 2645 000024A5 E837000000 <1> call get_pde 2646 <1> ; EDX = PDE address 2647 <1> ; EAX = PDE value 2648 000024AA 5A <1> pop edx ; physical page address 2649 000024AB 722A <1> jc short spte_err ; PDE not present 2650 <1> ; 2651 000024AD 53 <1> push ebx ; 24/07/2015 2652 000024AE 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2653 <1> ; EDX = PT address (physical) 2654 000024B2 C1EB0C <1> shr ebx, PAGE_SHIFT ; 12 2655 000024B5 81E3FF030000 <1> and ebx, PTE_MASK ; 03FFh 2656 <1> ; clear higher 10 bits (PD bits) 2657 000024BB C1E302 <1> shl ebx, 2 ; offset to page table (1024*4) 2658 000024BE 01C3 <1> add ebx, eax 2659 <1> ; 2660 000024C0 8B03 <1> mov eax, [ebx] ; Old PTE value 2661 000024C2 A801 <1> test al, 1 2662 000024C4 740C <1> jz short spte_0 2663 000024C6 09D2 <1> or edx, edx 2664 000024C8 750F <1> jnz short spte_1 2665 000024CA 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits 2666 000024CE 89C2 <1> mov edx, eax 2667 000024D0 EB09 <1> jmp short spte_2 2668 <1> spte_0: 2669 <1> ; If this PTE contains a swap (disk) address, 2670 <1> ; it can be updated by using 'swap_in' procedure 2671 <1> ; only! 2672 000024D2 21C0 <1> and eax, eax 2673 000024D4 7403 <1> jz short spte_1 2674 <1> ; 24/07/2015 2675 <1> ; swapped page ! (on disk) 2676 000024D6 5B <1> pop ebx 2677 <1> spte_err: 2678 000024D7 F9 <1> stc 2679 000024D8 C3 <1> retn 2680 <1> spte_1: 2681 000024D9 89D0 <1> mov eax, edx 2682 <1> spte_2: 2683 000024DB 09CA <1> or edx, ecx 2684 <1> ; 23/06/2015 2685 000024DD 8913 <1> mov [ebx], edx ; PTE value in EDX 2686 <1> ; 24/07/2015 2687 000024DF 5B <1> pop ebx 2688 000024E0 C3 <1> retn 2689 <1> 2690 <1> get_pde: ; Get present value of the relevant PDE 2691 <1> ; 20/07/2015 2692 <1> ; 18/04/2015 2693 <1> ; 12/04/2015 2694 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2695 <1> ; 2696 <1> ; INPUT -> 2697 <1> ; EBX = virtual (linear) address 2698 <1> ; EAX = page directory (physical) address 2699 <1> ; OUTPUT -> 2700 <1> ; EDX = Page directory entry address 2701 <1> ; EAX = Page directory entry value 2702 <1> ; CF = 1 -> PDE not present or invalid ? 2703 <1> ; Modified Registers -> EDX, EAX 2704 <1> ; 2705 000024E1 89DA <1> mov edx, ebx 2706 000024E3 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 (12+10) 2707 000024E6 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 2708 000024E9 01C2 <1> add edx, eax ; page directory address (physical) 2709 000024EB 8B02 <1> mov eax, [edx] 2710 000024ED A801 <1> test al, PDE_A_PRESENT ; page table is present or not ! 2711 000024EF 751F <1> jnz short gpte_retn 2712 000024F1 F9 <1> stc 2713 <1> gpde_retn: 2714 000024F2 C3 <1> retn 2715 <1> 2716 <1> get_pte: 2717 <1> ; Get present value of the relevant PTE 2718 <1> ; 29/07/2015 2719 <1> ; 20/07/2015 2720 <1> ; 18/04/2015 2721 <1> ; 12/04/2015 2722 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2723 <1> ; 2724 <1> ; INPUT -> 2725 <1> ; EBX = virtual (linear) address 2726 <1> ; EAX = page directory (physical) address 2727 <1> ; OUTPUT -> 2728 <1> ; EDX = Page table entry address (if CF=0) 2729 <1> ; Page directory entry address (if CF=1) 2730 <1> ; (Bit 0 value is 0 if PT is not present) 2731 <1> ; EAX = Page table entry value (page address) 2732 <1> ; CF = 1 -> PDE not present or invalid ? 2733 <1> ; Modified Registers -> EAX, EDX 2734 <1> ; 2735 000024F3 E8E9FFFFFF <1> call get_pde 2736 000024F8 72F8 <1> jc short gpde_retn ; page table is not present 2737 <1> ;jnc short gpte_1 2738 <1> ;retn 2739 <1> ;gpte_1: 2740 000024FA 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2741 000024FE 89DA <1> mov edx, ebx 2742 00002500 C1EA0C <1> shr edx, PAGE_SHIFT ; 12 2743 00002503 81E2FF030000 <1> and edx, PTE_MASK ; 03FFh 2744 <1> ; clear higher 10 bits (PD bits) 2745 00002509 C1E202 <1> shl edx, 2 ; offset from start of page table (1024*4) 2746 0000250C 01C2 <1> add edx, eax 2747 0000250E 8B02 <1> mov eax, [edx] 2748 <1> gpte_retn: 2749 00002510 C3 <1> retn 2750 <1> 2751 <1> deallocate_page_dir: 2752 <1> ; 15/09/2015 2753 <1> ; 05/08/2015 2754 <1> ; 30/04/2015 2755 <1> ; 28/04/2015 2756 <1> ; 17/10/2014 2757 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2758 <1> ; 2759 <1> ; INPUT -> 2760 <1> ; EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD) 2761 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 2762 <1> ; OUTPUT -> 2763 <1> ; All of page tables in the page directory 2764 <1> ; and page dir's itself will be deallocated 2765 <1> ; except 'read only' duplicated pages (will be converted 2766 <1> ; to writable pages). 2767 <1> ; 2768 <1> ; Modified Registers -> EAX 2769 <1> ; 2770 <1> ; 2771 00002511 56 <1> push esi 2772 00002512 51 <1> push ecx 2773 00002513 50 <1> push eax 2774 00002514 89C6 <1> mov esi, eax 2775 00002516 31C9 <1> xor ecx, ecx 2776 <1> ; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB), 2777 <1> ; it must not be deallocated 2778 00002518 890E <1> mov [esi], ecx ; 0 ; clear PDE 0 2779 <1> dapd_0: 2780 0000251A AD <1> lodsd 2781 0000251B A801 <1> test al, PDE_A_PRESENT ; bit 0, present flag (must be 1) 2782 0000251D 7409 <1> jz short dapd_1 2783 0000251F 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 2784 00002523 E812000000 <1> call deallocate_page_table 2785 <1> dapd_1: 2786 00002528 41 <1> inc ecx ; page directory entry index 2787 00002529 81F900040000 <1> cmp ecx, PAGE_SIZE / 4 ; 1024 2788 0000252F 72E9 <1> jb short dapd_0 2789 <1> dapd_2: 2790 00002531 58 <1> pop eax 2791 00002532 E870000000 <1> call deallocate_page ; deallocate the page dir's itself 2792 00002537 59 <1> pop ecx 2793 00002538 5E <1> pop esi 2794 00002539 C3 <1> retn 2795 <1> 2796 <1> deallocate_page_table: 2797 <1> ; 17/07/2022 2798 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2799 <1> ; 12/07/2016 (TRDOS 386 v2) 2800 <1> ; 19/09/2015 2801 <1> ; 15/09/2015 2802 <1> ; 05/08/2015 2803 <1> ; 30/04/2015 2804 <1> ; 28/04/2015 2805 <1> ; 24/10/2014 2806 <1> ; 23/10/2014 2807 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2808 <1> ; 2809 <1> ; INPUT -> 2810 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE 2811 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 2812 <1> ; (ECX = page directory entry index) 2813 <1> ; OUTPUT -> 2814 <1> ; All of pages in the page table and page table's itself 2815 <1> ; will be deallocated except 'read only' duplicated pages 2816 <1> ; (will be converted to writable pages). 2817 <1> ; 2818 <1> ; Modified Registers -> EAX 2819 <1> ; 2820 0000253A 56 <1> push esi 2821 0000253B 57 <1> push edi 2822 0000253C 52 <1> push edx 2823 0000253D 50 <1> push eax ; * 2824 0000253E 89C6 <1> mov esi, eax 2825 00002540 31FF <1> xor edi, edi ; 0 2826 <1> dapt_0: 2827 00002542 AD <1> lodsd 2828 00002543 A801 <1> test al, PTE_A_PRESENT ; bit 0, present flag (must be 1) 2829 00002545 7453 <1> jz short dapt_1 2830 <1> ; 2831 00002547 A802 <1> test al, PTE_A_WRITE ; bit 1, writable (r/w) flag 2832 <1> ; (must be 1) 2833 00002549 753D <1> jnz short dapt_3 2834 <1> ; Read only -duplicated- page (belongs to a parent or a child) 2835 0000254B 66A90002 <1> test ax, PTE_DUPLICATED ; Was this page duplicated 2836 <1> ; as child's page ? 2837 0000254F 7442 <1> jz short dapt_4 ; Clear PTE but don't deallocate the page! 2838 <1> ; check the parent's PTE value is read only & same page or not.. 2839 <1> ; ECX = page directory entry index (0-1023) 2840 00002551 53 <1> push ebx 2841 00002552 51 <1> push ecx 2842 <1> ;shl cx, 2 ; *4 2843 <1> ; 17/07/2022 2844 00002553 C1E102 <1> shl ecx, 2 2845 00002556 01CB <1> add ebx, ecx ; PDE offset (for the parent) 2846 00002558 8B0B <1> mov ecx, [ebx] 2847 0000255A F6C101 <1> test cl, PDE_A_PRESENT ; present (valid) or not ? 2848 0000255D 7427 <1> jz short dapt_2 ; parent process does not use this page 2849 0000255F 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 2850 <1> ; EDI = page table entry index (0-1023) 2851 00002564 89FA <1> mov edx, edi 2852 <1> ;shl dx, 2 ; *4 2853 <1> ; 17/07/2022 2854 00002566 C1E202 <1> shl edx, 2 2855 00002569 01CA <1> add edx, ecx ; PTE offset (for the parent) 2856 0000256B 8B1A <1> mov ebx, [edx] 2857 0000256D F6C301 <1> test bl, PTE_A_PRESENT ; present or not ? 2858 00002570 7414 <1> jz short dapt_2 ; parent process does not use this page 2859 00002572 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 2860 00002576 6681E300F0 <1> and bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 2861 0000257B 39D8 <1> cmp eax, ebx ; parent's and child's pages are same ? 2862 0000257D 7507 <1> jne short dapt_2 ; not same page 2863 <1> ; deallocate the child's page 2864 0000257F 800A02 <1> or byte [edx], PTE_A_WRITE ; convert to writable page (parent) 2865 00002582 59 <1> pop ecx 2866 00002583 5B <1> pop ebx 2867 00002584 EB0D <1> jmp short dapt_4 2868 <1> 2869 <1> ; 24/12/2021 2870 <1> ; ('dapt_1' is disabled) 2871 <1> ; 2872 <1> ;dapt_1: 2873 <1> ; or eax, eax ; swapped page ? 2874 <1> ; jz short dapt_5 ; no 2875 <1> ; ; yes 2876 <1> ; shr eax, 1 2877 <1> ; call unlink_swap_block ; Deallocate swapped page block 2878 <1> ; ; on the swap disk (or in file) 2879 <1> ; jmp short dapt_5 2880 <1> dapt_2: 2881 00002586 59 <1> pop ecx 2882 00002587 5B <1> pop ebx 2883 <1> dapt_3: 2884 <1> ; 12/07/2016 2885 00002588 66A90004 <1> test ax, PTE_SHARED ; shared or direct memory access indicator 2886 0000258C 7505 <1> jnz short dapt_4 ; AVL bit 1 = 1, do not deallocate this page! 2887 <1> ; 2888 <1> ;and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 2889 0000258E E814000000 <1> call deallocate_page ; set the mem allocation bit of this page 2890 <1> dapt_4: 2891 00002593 C746FC00000000 <1> mov dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent) 2892 <1> dapt_1: ; 24/12/2021 2893 <1> dapt_5: 2894 0000259A 47 <1> inc edi ; page table entry index 2895 0000259B 81FF00040000 <1> cmp edi, PAGE_SIZE / 4 ; 1024 2896 000025A1 729F <1> jb short dapt_0 2897 <1> ; 2898 000025A3 58 <1> pop eax ; * 2899 000025A4 5A <1> pop edx 2900 000025A5 5F <1> pop edi 2901 000025A6 5E <1> pop esi 2902 <1> ; 2903 <1> ;call deallocate_page ; deallocate the page table's itself 2904 <1> ;retn 2905 <1> 2906 <1> deallocate_page: 2907 <1> ; 15/09/2015 2908 <1> ; 28/04/2015 2909 <1> ; 10/03/2015 2910 <1> ; 17/10/2014 2911 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2912 <1> ; 2913 <1> ; INPUT -> 2914 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 2915 <1> ; OUTPUT -> 2916 <1> ; [free_pages] is increased 2917 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is SET) 2918 <1> ; CF = 1 if the page is already deallocated 2919 <1> ; (or not allocated) before. 2920 <1> ; 2921 <1> ; Modified Registers -> EAX 2922 <1> ; 2923 000025A7 53 <1> push ebx 2924 000025A8 52 <1> push edx 2925 <1> ; 2926 000025A9 C1E80C <1> shr eax, PAGE_SHIFT ; shift physical address to 2927 <1> ; 12 bits right 2928 <1> ; to get page number 2929 000025AC 89C2 <1> mov edx, eax 2930 <1> ; 15/09/2015 2931 000025AE C1EA03 <1> shr edx, 3 ; to get offset to M.A.T. 2932 <1> ; (1 allocation bit = 1 page) 2933 <1> ; (1 allocation bytes = 8 pages) 2934 000025B1 80E2FC <1> and dl, 0FCh ; clear lower 2 bits 2935 <1> ; (to get 32 bit position) 2936 <1> ; 2937 000025B4 BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table address 2938 000025B9 01D3 <1> add ebx, edx 2939 000025BB 83E01F <1> and eax, 1Fh ; lower 5 bits only 2940 <1> ; (allocation bit position) 2941 000025BE 3B15[44610000] <1> cmp edx, [next_page] ; is the new free page address lower 2942 <1> ; than the address in 'next_page' ? 2943 <1> ; (next/first free page value) 2944 000025C4 7306 <1> jnb short dap_1 ; no 2945 000025C6 8915[44610000] <1> mov [next_page], edx ; yes 2946 <1> dap_1: 2947 000025CC 0FAB03 <1> bts [ebx], eax ; unlink/release/deallocate page 2948 <1> ; set relevant bit to 1. 2949 <1> ; set CF to the previous bit value 2950 <1> ;cmc ; complement carry flag 2951 <1> ;jc short dap_2 ; do not increase free_pages count 2952 <1> ; if the page is already deallocated 2953 <1> ; before. 2954 000025CF FF05[40610000] <1> inc dword [free_pages] 2955 <1> dap_2: 2956 000025D5 5A <1> pop edx 2957 000025D6 5B <1> pop ebx 2958 000025D7 C3 <1> retn 2959 <1> 2960 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2961 <1> ;; ;; 2962 <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; 2963 <1> ;; Distributed under terms of the GNU General Public License ;; 2964 <1> ;; ;; 2965 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2966 <1> 2967 <1> ;;$Revision: 5057 $ 2968 <1> 2969 <1> 2970 <1> ;;align 4 2971 <1> ;;proc alloc_page 2972 <1> 2973 <1> ;; pushfd 2974 <1> ;; cli 2975 <1> ;; push ebx 2976 <1> ;;;//- 2977 <1> ;; cmp [pg_data.pages_free], 1 2978 <1> ;; jle .out_of_memory 2979 <1> ;;;//- 2980 <1> ;; 2981 <1> ;; mov ebx, [page_start] 2982 <1> ;; mov ecx, [page_end] 2983 <1> ;;.l1: 2984 <1> ;; bsf eax, [ebx]; 2985 <1> ;; jnz .found 2986 <1> ;; add ebx, 4 2987 <1> ;; cmp ebx, ecx 2988 <1> ;; jb .l1 2989 <1> ;; pop ebx 2990 <1> ;; popfd 2991 <1> ;; xor eax, eax 2992 <1> ;; ret 2993 <1> ;;.found: 2994 <1> ;;;//- 2995 <1> ;; dec [pg_data.pages_free] 2996 <1> ;; jz .out_of_memory 2997 <1> ;;;//- 2998 <1> ;; btr [ebx], eax 2999 <1> ;; mov [page_start], ebx 3000 <1> ;; sub ebx, sys_pgmap 3001 <1> ;; lea eax, [eax+ebx*8] 3002 <1> ;; shl eax, 12 3003 <1> ;;;//- dec [pg_data.pages_free] 3004 <1> ;; pop ebx 3005 <1> ;; popfd 3006 <1> ;; ret 3007 <1> ;;;//- 3008 <1> ;;.out_of_memory: 3009 <1> ;; mov [pg_data.pages_free], 1 3010 <1> ;; xor eax, eax 3011 <1> ;; pop ebx 3012 <1> ;; popfd 3013 <1> ;; ret 3014 <1> ;;;//- 3015 <1> ;;endp 3016 <1> 3017 <1> duplicate_page_dir: 3018 <1> ; 21/09/2015 3019 <1> ; 31/08/2015 3020 <1> ; 20/07/2015 3021 <1> ; 28/04/2015 3022 <1> ; 27/04/2015 3023 <1> ; 18/04/2015 3024 <1> ; 12/04/2015 3025 <1> ; 18/10/2014 3026 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 3027 <1> ; 3028 <1> ; INPUT -> 3029 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 3030 <1> ; page directory. 3031 <1> ; OUTPUT -> 3032 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 3033 <1> ; page directory. 3034 <1> ; (New page directory with new page table entries.) 3035 <1> ; (New page tables with read only copies of the parent's 3036 <1> ; pages.) 3037 <1> ; EAX = 0 -> Error (CF = 1) 3038 <1> ; 3039 <1> ; Modified Registers -> none (except EAX) 3040 <1> ; 3041 000025D8 E804FEFFFF <1> call allocate_page 3042 000025DD 723E <1> jc short dpd_err 3043 <1> ; 3044 000025DF 55 <1> push ebp ; 20/07/2015 3045 000025E0 56 <1> push esi 3046 000025E1 57 <1> push edi 3047 000025E2 53 <1> push ebx 3048 000025E3 51 <1> push ecx 3049 000025E4 8B35[53650000] <1> mov esi, [u.pgdir] 3050 000025EA 89C7 <1> mov edi, eax 3051 000025EC 50 <1> push eax ; save child's page directory address 3052 <1> ; 31/08/2015 3053 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 3054 <1> ; (use same system space for all user page tables) 3055 000025ED A5 <1> movsd 3056 000025EE BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 3057 000025F3 B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 3058 <1> dpd_0: 3059 000025F8 AD <1> lodsd 3060 <1> ;or eax, eax 3061 <1> ;jnz short dpd_1 3062 000025F9 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 3063 000025FB 7508 <1> jnz short dpd_1 3064 <1> ; 20/07/2015 (virtual address at the end of the page table) 3065 000025FD 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 3066 00002603 EB0F <1> jmp short dpd_2 3067 <1> dpd_1: 3068 00002605 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 3069 00002609 89C3 <1> mov ebx, eax 3070 <1> ; EBX = Parent's page table address 3071 0000260B E81F000000 <1> call duplicate_page_table 3072 00002610 720C <1> jc short dpd_p_err 3073 <1> ; EAX = Child's page table address 3074 00002612 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 3075 <1> ; set bit 0, bit 1 and bit 2 to 1 3076 <1> ; (present, writable, user) 3077 <1> dpd_2: 3078 00002614 AB <1> stosd 3079 00002615 E2E1 <1> loop dpd_0 3080 <1> ; 3081 00002617 58 <1> pop eax ; restore child's page directory address 3082 <1> dpd_3: 3083 00002618 59 <1> pop ecx 3084 00002619 5B <1> pop ebx 3085 0000261A 5F <1> pop edi 3086 0000261B 5E <1> pop esi 3087 0000261C 5D <1> pop ebp ; 20/07/2015 3088 <1> dpd_err: 3089 0000261D C3 <1> retn 3090 <1> dpd_p_err: 3091 <1> ; release the allocated pages missing (recover free space) 3092 0000261E 58 <1> pop eax ; the new page directory address (physical) 3093 0000261F 8B1D[53650000] <1> mov ebx, [u.pgdir] ; parent's page directory address 3094 00002625 E8E7FEFFFF <1> call deallocate_page_dir 3095 0000262A 29C0 <1> sub eax, eax ; 0 3096 0000262C F9 <1> stc 3097 0000262D EBE9 <1> jmp short dpd_3 3098 <1> 3099 <1> duplicate_page_table: 3100 <1> ; 31/12/2021 3101 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3102 <1> ; 20/02/2017 (TRDOS 386 v2) 3103 <1> ; 21/09/2015 3104 <1> ; 20/07/2015 3105 <1> ; 05/05/2015 3106 <1> ; 28/04/2015 3107 <1> ; 27/04/2015 3108 <1> ; 18/04/2015 3109 <1> ; 18/10/2014 3110 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 3111 <1> ; 3112 <1> ; INPUT -> 3113 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 3114 <1> ; 20/02/2017 3115 <1> ; EBP = Linear address of the page (from 'duplicate_page_dir') 3116 <1> ; (Linear address = CORE + user's virtual address) 3117 <1> ; OUTPUT -> 3118 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 3119 <1> ; (with 'read only' attribute of page table entries) 3120 <1> ; 20/02/2017 3121 <1> ; EBP = Next linear page address (for 'duplicate_page_dir') 3122 <1> ; 3123 <1> ; CF = 1 -> error 3124 <1> ; 3125 <1> ; Modified Registers -> EBP (except EAX) 3126 <1> ; 3127 0000262F E8ADFDFFFF <1> call allocate_page 3128 00002634 725B <1> jc short dpt_err 3129 <1> ; 3130 00002636 50 <1> push eax ; * 3131 00002637 56 <1> push esi 3132 00002638 57 <1> push edi 3133 00002639 52 <1> push edx 3134 0000263A 51 <1> push ecx 3135 <1> ; 3136 0000263B 89DE <1> mov esi, ebx 3137 0000263D 89C7 <1> mov edi, eax 3138 0000263F 89C2 <1> mov edx, eax 3139 00002641 81C200100000 <1> add edx, PAGE_SIZE 3140 <1> dpt_0: 3141 00002647 AD <1> lodsd 3142 00002648 21C0 <1> and eax, eax 3143 0000264A 7435 <1> jz short dpt_3 3144 0000264C A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 3145 <1> ; 24/12/2021 3146 0000264E 7503 <1> jnz short dpt_1 3147 <1> ;jz short dpt_p_err 3148 <1> ; 31/12/2021 3149 00002650 F9 <1> stc 3150 00002651 EB39 <1> jmp short dpt_p_err 3151 <1> 3152 <1> ; 24/12/2021 3153 <1> ; ('reload_page' procedure call is disabled) 3154 <1> ; 3155 <1> ; ; 20/07/2015 3156 <1> ; ; ebp = virtual (linear) address of the memory page 3157 <1> ; call reload_page ; 28/04/2015 3158 <1> ; jc short dpt_p_err 3159 <1> dpt_1: 3160 <1> ; 21/09/2015 3161 00002653 89C1 <1> mov ecx, eax 3162 00002655 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3163 00002659 F6C102 <1> test cl, PTE_A_WRITE ; writable page ? 3164 0000265C 751A <1> jnz short dpt_2 3165 <1> ; Read only (parent) page 3166 <1> ; - there is a third process which uses this page - 3167 <1> ; Allocate a new page for the child process 3168 0000265E E87EFDFFFF <1> call allocate_page 3169 00002663 7227 <1> jc short dpt_p_err 3170 00002665 57 <1> push edi 3171 00002666 56 <1> push esi 3172 00002667 89CE <1> mov esi, ecx 3173 00002669 89C7 <1> mov edi, eax 3174 0000266B B900040000 <1> mov ecx, PAGE_SIZE/4 3175 00002670 F3A5 <1> rep movsd ; copy page (4096 bytes) 3176 00002672 5E <1> pop esi 3177 00002673 5F <1> pop edi 3178 <1> ; 3179 <1> 3180 <1> ; 24/12/2021 3181 <1> ; ('add_to_swap_queue' procedure call is disabled) 3182 <1> ; 3183 <1> ; push ebx 3184 <1> ; push eax 3185 <1> ; ; 20/07/2015 3186 <1> ; mov ebx, ebp 3187 <1> ; ; ebx = virtual (linear) address of the memory page 3188 <1> ; call add_to_swap_queue 3189 <1> ; pop eax 3190 <1> ; pop ebx 3191 <1> 3192 <1> ; 21/09/2015 3193 00002674 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 3194 <1> ; user + writable + present page 3195 00002676 EB09 <1> jmp short dpt_3 3196 <1> dpt_2: 3197 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 3198 00002678 0C05 <1> or al, PTE_A_USER+PTE_A_PRESENT 3199 <1> ; (read only page!) 3200 0000267A 8946FC <1> mov [esi-4], eax ; update parent's PTE 3201 0000267D 660D0002 <1> or ax, PTE_DUPLICATED ; (read only page & duplicated PTE!) 3202 <1> dpt_3: 3203 00002681 AB <1> stosd ; EDI points to child's PTE 3204 <1> ; 3205 00002682 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 3206 <1> ; 3207 00002688 39D7 <1> cmp edi, edx 3208 0000268A 72BB <1> jb short dpt_0 3209 <1> dpt_p_err: 3210 0000268C 59 <1> pop ecx 3211 0000268D 5A <1> pop edx 3212 0000268E 5F <1> pop edi 3213 0000268F 5E <1> pop esi 3214 00002690 58 <1> pop eax ; * 3215 <1> dpt_err: 3216 00002691 C3 <1> retn 3217 <1> 3218 <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault ! 3219 <1> ; 31/12/2021 3220 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3221 <1> ; 21/09/2015 3222 <1> ; 19/09/2015 3223 <1> ; 17/09/2015 3224 <1> ; 28/08/2015 3225 <1> ; 20/07/2015 3226 <1> ; 28/06/2015 3227 <1> ; 03/05/2015 3228 <1> ; 30/04/2015 3229 <1> ; 18/04/2015 3230 <1> ; 12/04/2015 3231 <1> ; 30/10/2014 3232 <1> ; 11/09/2014 3233 <1> ; 10/09/2014 (Retro UNIX 386 v1 - beginning) 3234 <1> ; 3235 <1> ; Note: This is not an interrupt/exception handler. 3236 <1> ; This is a 'page fault remedy' subroutine 3237 <1> ; which will be called by standard/uniform 3238 <1> ; exception handler. 3239 <1> ; 3240 <1> ; INPUT -> 3241 <1> ; [error_code] = 32 bit ERROR CODE (lower 5 bits are valid) 3242 <1> ; 3243 <1> ; cr2 = the virtual (linear) address 3244 <1> ; which has caused to page fault (19/09/2015) 3245 <1> ; 3246 <1> ; OUTPUT -> 3247 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3248 <1> ; EAX = 0 -> no error 3249 <1> ; EAX > 0 -> error code in EAX (also CF = 1) 3250 <1> ; 3251 <1> ; Modified Registers -> none (except EAX) 3252 <1> ; 3253 <1> ; 3254 <1> ; ERROR CODE: 3255 <1> ; 31 ..... 4 3 2 1 0 3256 <1> ; +---+-- --+---+---+---+---+---+---+ 3257 <1> ; | Reserved | I | R | U | W | P | 3258 <1> ; +---+-- --+---+---+---+---+---+---+ 3259 <1> ; 3260 <1> ; P : PRESENT - When set, the page fault was caused by 3261 <1> ; a page-protection violation. When not set, 3262 <1> ; it was caused by a non-present page. 3263 <1> ; W : WRITE - When set, the page fault was caused by 3264 <1> ; a page write. When not set, it was caused 3265 <1> ; by a page read. 3266 <1> ; U : USER - When set, the page fault was caused 3267 <1> ; while CPL = 3. 3268 <1> ; This does not necessarily mean that 3269 <1> ; the page fault was a privilege violation. 3270 <1> ; R : RESERVD - When set, the page fault was caused by 3271 <1> ; WRITE reading a 1 in a reserved field. 3272 <1> ; I : INSTRUC - When set, the page fault was caused by 3273 <1> ; FETCH an instruction fetch 3274 <1> ; 3275 <1> ;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION 3276 <1> ; 31 22 12 11 0 3277 <1> ; +-------------------+-------------------+-----------------------+ 3278 <1> ; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # | OFFSET | 3279 <1> ; +-------------------+-------------------+-----------------------+ 3280 <1> ; 3281 <1> 3282 <1> ;; CR3 REGISTER (Control Register 3) 3283 <1> ; 31 12 5 4 3 2 0 3284 <1> ; +---------------------------------------+-------------+---+-----+ 3285 <1> ; | | |P|P| | 3286 <1> ; | PAGE DIRECTORY TABLE BASE ADDRESS | reserved |C|W|rsvrd| 3287 <1> ; | | |D|T| | 3288 <1> ; +---------------------------------------+-------------+---+-----+ 3289 <1> ; 3290 <1> ; PWT - WRITE THROUGH 3291 <1> ; PCD - CACHE DISABLE 3292 <1> ; 3293 <1> ; 3294 <1> ;; x86 PAGE DIRECTORY ENTRY (4 KByte Page) 3295 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3296 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3297 <1> ; | | | | | | |P|P|U|R| | 3298 <1> ; | PAGE TABLE BASE ADDRESS 31..12 | AVL |G|0|D|A|C|W|/|/|P| 3299 <1> ; | | | | | | |D|T|S|W| | 3300 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3301 <1> ; 3302 <1> ; P - PRESENT 3303 <1> ; R/W - READ/WRITE 3304 <1> ; U/S - USER/SUPERVISOR 3305 <1> ; PWT - WRITE THROUGH 3306 <1> ; PCD - CACHE DISABLE 3307 <1> ; A - ACCESSED 3308 <1> ; D - DIRTY (IGNORED) 3309 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 3310 <1> ; G - GLOBAL (IGNORED) 3311 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3312 <1> ; 3313 <1> ; 3314 <1> ;; x86 PAGE TABLE ENTRY (4 KByte Page) 3315 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3316 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3317 <1> ; | | | |P| | |P|P|U|R| | 3318 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |G|A|D|A|C|W|/|/|P| 3319 <1> ; | | | |T| | |D|T|S|W| | 3320 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3321 <1> ; 3322 <1> ; P - PRESENT 3323 <1> ; R/W - READ/WRITE 3324 <1> ; U/S - USER/SUPERVISOR 3325 <1> ; PWT - WRITE THROUGH 3326 <1> ; PCD - CACHE DISABLE 3327 <1> ; A - ACCESSED 3328 <1> ; D - DIRTY 3329 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 3330 <1> ; G - GLOBAL 3331 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3332 <1> ; 3333 <1> ; 3334 <1> ;; 80386 PAGE TABLE ENTRY (4 KByte Page) 3335 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3336 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 3337 <1> ; | | | | | | | | |U|R| | 3338 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |0|0|D|A|0|0|/|/|P| 3339 <1> ; | | | | | | | | |S|W| | 3340 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 3341 <1> ; 3342 <1> ; P - PRESENT 3343 <1> ; R/W - READ/WRITE 3344 <1> ; U/S - USER/SUPERVISOR 3345 <1> ; D - DIRTY 3346 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3347 <1> ; 3348 <1> ; NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. 3349 <1> ; 3350 <1> ; 3351 <1> ;; Invalid Page Table Entry 3352 <1> ; 31 1 0 3353 <1> ; +-------------------------------------------------------------+-+ 3354 <1> ; | | | 3355 <1> ; | AVAILABLE |0| 3356 <1> ; | | | 3357 <1> ; +-------------------------------------------------------------+-+ 3358 <1> ; 3359 <1> 3360 00002692 53 <1> push ebx 3361 00002693 52 <1> push edx 3362 00002694 51 <1> push ecx 3363 <1> ; 3364 <1> ; 21/09/2015 (debugging) 3365 00002695 FF05[63650000] <1> inc dword [u.pfcount] ; page fault count for running process 3366 0000269B FF05[EC610000] <1> inc dword [PF_Count] ; total page fault count 3367 <1> ; 28/06/2015 3368 <1> ;mov edx, [error_code] ; Lower 5 bits are valid 3369 000026A1 8A15[E4610000] <1> mov dl, [error_code] 3370 <1> ; 3371 000026A7 F6C201 <1> test dl, 1 ; page fault was caused by a non-present page 3372 <1> ; sign 3373 000026AA 7425 <1> jz short pfh_alloc_np 3374 <1> ; 3375 <1> ; If it is not a 'write on read only page' type page fault 3376 <1> ; major page fault error with minor reason must be returned without 3377 <1> ; fixing the problem. 'sys_exit with error' will be needed 3378 <1> ; after return here! 3379 <1> ; Page fault will be remedied, by copying page contents 3380 <1> ; to newly allocated page with write permission; 3381 <1> ; sys_fork -> sys_exec -> copy on write, demand paging method is 3382 <1> ; used for working with minimum possible memory usage. 3383 <1> ; sys_fork will duplicate page directory and tables of parent 3384 <1> ; process with 'read only' flag. If the child process attempts to 3385 <1> ; write on these read only pages, page fault will be directed here 3386 <1> ; for allocating a new page with same data/content. 3387 <1> ; 3388 <1> ; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS) 3389 <1> ; will not force to separate CODE and DATA space 3390 <1> ; in a process/program... 3391 <1> ; CODE segment/section may contain DATA! 3392 <1> ; It is flat, smoth and simplest programming method already as in 3393 <1> ; Retro UNIX 8086 v1 and MS-DOS programs. 3394 <1> ; 3395 000026AC F6C202 <1> test dl, 2 ; page fault was caused by a page write 3396 <1> ; sign 3397 000026AF 7418 <1> jz pfh_p_err 3398 <1> ; 31/08/2015 3399 000026B1 F6C204 <1> test dl, 4 ; page fault was caused while CPL = 3 (user mode) 3400 <1> ; sign. (U+W+P = 4+2+1 = 7) 3401 000026B4 7413 <1> jz short pfh_pv_err 3402 <1> ; 3403 <1> ; make a new page and copy the parent's page content 3404 <1> ; as the child's new page content 3405 <1> ; 3406 000026B6 0F20D3 <1> mov ebx, cr2 ; CR2 contains the linear address 3407 <1> ; which has caused to page fault 3408 000026B9 E87C000000 <1> call copy_page 3409 000026BE 7202 <1> jc short pfh_im_err ; insufficient memory 3410 <1> ; 3411 000026C0 EB72 <1> jmp pfh_cpp_ok 3412 <1> 3413 <1> ; 31/12/2021 (short jump) 3414 <1> pfh_im_err: 3415 000026C2 B8E4000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX 3416 <1> ; Major (Primary) Error: Page Fault 3417 <1> ; Minor (Secondary) Error: Insufficient Memory ! 3418 000026C7 EB6D <1> jmp short pfh_err_retn 3419 <1> 3420 <1> ; 31/12/2021 3421 <1> pfh_p_err: ; 09/03/2015 3422 <1> pfh_pv_err: 3423 <1> ; Page fault was caused by a protection-violation 3424 000026C9 B8E6000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX 3425 <1> ; Major (Primary) Error: Page Fault 3426 <1> ; Minor (Secondary) Error: Protection violation ! 3427 000026CE F9 <1> stc 3428 000026CF EB65 <1> jmp short pfh_err_retn 3429 <1> 3430 <1> pfh_alloc_np: 3431 000026D1 E80BFDFFFF <1> call allocate_page ; (allocate a new page) 3432 000026D6 72EA <1> jc short pfh_im_err ; 'insufficient memory' error 3433 <1> pfh_chk_cpl: 3434 <1> ; EAX = Physical (base) address of the allocated (new) page 3435 <1> ; (Lower 12 bits are ZERO, because 3436 <1> ; the address is on a page boundary) 3437 000026D8 80E204 <1> and dl, 4 ; CPL = 3 ? 3438 000026DB 7505 <1> jnz short pfh_um 3439 <1> ; Page fault handler for kernel/system mode (CPL=0) 3440 000026DD 0F20DB <1> mov ebx, cr3 ; CR3 (Control Register 3) contains physical address 3441 <1> ; of the current/active page directory 3442 <1> ; (Always kernel/system mode page directory, here!) 3443 <1> ; Note: Lower 12 bits are 0. (page boundary) 3444 000026E0 EB06 <1> jmp short pfh_get_pde 3445 <1> ; 3446 <1> pfh_um: ; Page fault handler for user/appl. mode (CPL=3) 3447 000026E2 8B1D[53650000] <1> mov ebx, [u.pgdir] ; Page directory of current/active process 3448 <1> ; Physical address of the USER's page directory 3449 <1> ; Note: Lower 12 bits are 0. (page boundary) 3450 <1> pfh_get_pde: 3451 000026E8 80CA03 <1> or dl, 3 ; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT 3452 000026EB 0F20D1 <1> mov ecx, cr2 ; CR2 contains the virtual address 3453 <1> ; which has been caused to page fault 3454 <1> ; 3455 000026EE C1E914 <1> shr ecx, 20 ; shift 20 bits right 3456 000026F1 80E1FC <1> and cl, 0FCh ; mask lower 2 bits to get PDE offset 3457 <1> ; 3458 000026F4 01CB <1> add ebx, ecx ; now, EBX points to the relevant page dir entry 3459 000026F6 8B0B <1> mov ecx, [ebx] ; physical (base) address of the page table 3460 000026F8 F6C101 <1> test cl, 1 ; check bit 0 is set (1) or not (0). 3461 000026FB 740B <1> jz short pfh_set_pde ; Page directory entry is not valid, 3462 <1> ; set/validate page directory entry 3463 000026FD 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 3464 00002702 89CB <1> mov ebx, ecx ; Physical address of the page table 3465 00002704 89C1 <1> mov ecx, eax ; new page address (physical) 3466 00002706 EB16 <1> jmp short pfh_get_pte 3467 <1> pfh_set_pde: 3468 <1> ;; NOTE: Page directories and page tables never be swapped out! 3469 <1> ;; (So, we know this PDE is empty or invalid) 3470 <1> ; 3471 00002708 08D0 <1> or al, dl ; lower 3 bits are used as U/S, R/W, P flags 3472 0000270A 8903 <1> mov [ebx], eax ; Let's put the new page directory entry here ! 3473 0000270C 30C0 <1> xor al, al ; clear lower (3..8) bits 3474 0000270E 89C3 <1> mov ebx, eax 3475 00002710 E8CCFCFFFF <1> call allocate_page ; (allocate a new page) 3476 00002715 72AB <1> jc short pfh_im_err ; 'insufficient memory' error 3477 <1> pfh_spde_1: 3478 <1> ; EAX = Physical (base) address of the allocated (new) page 3479 00002717 89C1 <1> mov ecx, eax 3480 00002719 E834FDFFFF <1> call clear_page ; Clear page content 3481 <1> pfh_get_pte: 3482 0000271E 0F20D0 <1> mov eax, cr2 ; virtual address 3483 <1> ; which has been caused to page fault 3484 00002721 89C7 <1> mov edi, eax ; 20/07/2015 3485 00002723 C1E80C <1> shr eax, 12 ; shift 12 bit right to get 3486 <1> ; higher 20 bits of the page fault address 3487 00002726 25FF030000 <1> and eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3488 0000272B C1E002 <1> shl eax, 2 ; shift 2 bits left to get PTE offset 3489 0000272E 01C3 <1> add ebx, eax ; now, EBX points to the relevant page table entry 3490 <1> ; 24/12/2021 3491 <1> ; mov eax, [ebx] ; get previous value of pte 3492 <1> ; ; bit 0 of EAX is always 0 (otherwise we would not be here) 3493 <1> ; 24/12/2021 3494 <1> ; ('swap_in' procedure call has been disabled) 3495 <1> ; 3496 <1> ; and eax, eax 3497 <1> ; jz short pfh_gpte_1 3498 <1> ; ; 20/07/2015 3499 <1> ; xchg ebx, ecx ; new page address (physical) 3500 <1> ; push ebp ; 20/07/2015 3501 <1> ; mov ebp, cr2 3502 <1> ; ; ECX = physical address of the page table entry 3503 <1> ; ; EBX = Memory page address (physical!) 3504 <1> ; ; EAX = Swap disk (offset) address 3505 <1> ; ; EBP = virtual address (page fault address) 3506 <1> ; call swap_in 3507 <1> ; pop ebp 3508 <1> ; jc short pfh_err_retn 3509 <1> ; xchg ecx, ebx 3510 <1> ; ; EBX = physical address of the page table entry 3511 <1> ; ; ECX = new page 3512 <1> pfh_gpte_1: 3513 00002730 08D1 <1> or cl, dl ; lower 3 bits are used as U/S, R/W, P flags 3514 00002732 890B <1> mov [ebx], ecx ; Let's put the new page table entry here ! 3515 <1> pfh_cpp_ok: 3516 <1> ; 24/12/2021 3517 <1> ; ('add_to_swap_queue' procedure call has been disabled) 3518 <1> ; 3519 <1> ; ; 20/07/2015 3520 <1> ; mov ebx, cr2 3521 <1> ; call add_to_swap_queue 3522 <1> ; 3523 <1> ; The new PTE (which contains the new page) will be added to 3524 <1> ; the swap queue, here. 3525 <1> ; (Later, if memory will become insufficient, 3526 <1> ; one page will be swapped out which is at the head of 3527 <1> ; the swap queue by using FIFO and access check methods.) 3528 <1> ; 3529 00002734 31C0 <1> xor eax, eax ; 0 3530 <1> ; 3531 <1> pfh_err_retn: 3532 00002736 59 <1> pop ecx 3533 00002737 5A <1> pop edx 3534 00002738 5B <1> pop ebx 3535 00002739 C3 <1> retn 3536 <1> 3537 <1> copy_page: 3538 <1> ; 17/07/2022 3539 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 3540 <1> ; 16/04/2021 3541 <1> ; 19/04/2020 - Retro UNIX 386 v2 3542 <1> ; 22/09/2015 3543 <1> ; 21/09/2015 3544 <1> ; 19/09/2015 3545 <1> ; 07/09/2015 3546 <1> ; 31/08/2015 3547 <1> ; 20/07/2015 3548 <1> ; 05/05/2015 3549 <1> ; 03/05/2015 3550 <1> ; 18/04/2015 3551 <1> ; 12/04/2015 3552 <1> ; 30/10/2014 3553 <1> ; 18/10/2014 (Retro UNIX 386 v1 - beginning) 3554 <1> ; 3555 <1> ; INPUT -> 3556 <1> ; EBX = Virtual (linear) address of source page 3557 <1> ; (Page fault address) 3558 <1> ; OUTPUT -> 3559 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 3560 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3561 <1> ; EAX = 0 (CF = 1) 3562 <1> ; if there is not a free page to be allocated 3563 <1> ; (page content of the source page will be copied 3564 <1> ; onto the target/new page) 3565 <1> ; 3566 <1> ; Modified Registers -> ecx, ebx (except EAX) 3567 <1> ; 3568 <1> 3569 <1> ; 19/04/2020 - Retro UNIX 386 v2 3570 <1> ; INPUT: 3571 <1> ; EBX = Virtual (linear) address of source page 3572 <1> ; (Page fault address) 3573 <1> ; OUTPUT: 3574 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 3575 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3576 <1> ; EAX = 0 (CF = 1) 3577 <1> ; if there is not a free page to be allocated 3578 <1> ; (page content of the source page will be copied 3579 <1> ; onto the target/new page) 3580 <1> ; 3581 <1> ; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021 3582 <1> 3583 0000273A 56 <1> push esi ; * 3584 0000273B 57 <1> push edi ; ** 3585 <1> ; 16/04/2021 3586 <1> ; 19/04/2020 - Retro UNIX 386 v2 3587 <1> ;push ebx ; *** 3588 <1> ;push ecx ; **** 3589 0000273C 31F6 <1> xor esi, esi 3590 0000273E C1EB0C <1> shr ebx, 12 ; shift 12 bits right to get PDE & PTE numbers 3591 00002741 89D9 <1> mov ecx, ebx ; save page fault address (as 12 bit shifted) 3592 00002743 C1EB08 <1> shr ebx, 8 ; shift 8 bits right and then 3593 00002746 80E3FC <1> and bl, 0FCh ; mask lower 2 bits to get PDE offset 3594 00002749 89DF <1> mov edi, ebx ; save it for the parent of current process 3595 0000274B 031D[53650000] <1> add ebx, [u.pgdir] ; EBX points to the relevant page dir entry 3596 00002751 8B03 <1> mov eax, [ebx] ; physical (base) address of the page table 3597 00002753 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3598 00002757 89CB <1> mov ebx, ecx ; (restore higher 20 bits of page fault address) 3599 00002759 81E3FF030000 <1> and ebx, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3600 <1> ;shl bx, 2 ; shift 2 bits left to get PTE offset 3601 <1> ; 17/07/2022 3602 0000275F C1E302 <1> shl ebx, 2 3603 00002762 01C3 <1> add ebx, eax ; EBX points to the relevant page table entry 3604 <1> ; 07/09/2015 3605 00002764 66F7030002 <1> test word [ebx], PTE_DUPLICATED ; (Does current process share this 3606 <1> ; read only page as a child process?) 3607 00002769 7509 <1> jnz short cpp_0 ; yes 3608 0000276B 8B0B <1> mov ecx, [ebx] ; PTE value 3609 0000276D 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 3610 00002772 EB31 <1> jmp short cpp_1 3611 <1> cpp_0: 3612 00002774 89FE <1> mov esi, edi 3613 00002776 0335[57650000] <1> add esi, [u.ppgdir] ; the parent's page directory entry 3614 0000277C 8B06 <1> mov eax, [esi] ; physical (base) address of the page table 3615 0000277E 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3616 00002782 89CE <1> mov esi, ecx ; (restore higher 20 bits of page fault address) 3617 00002784 81E6FF030000 <1> and esi, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3618 <1> ;shl si, 2 ; shift 2 bits left to get PTE offset 3619 <1> ; 17/07/2022 3620 0000278A C1E602 <1> shl esi, 2 3621 0000278D 01C6 <1> add esi, eax ; EDX points to the relevant page table entry 3622 0000278F 8B0E <1> mov ecx, [esi] ; PTE value of the parent process 3623 <1> ; 21/09/2015 3624 00002791 8B03 <1> mov eax, [ebx] ; PTE value of the child process 3625 00002793 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear page attributes 3626 <1> ; 3627 00002797 F6C101 <1> test cl, PTE_A_PRESENT ; is it a present/valid page ? 3628 0000279A 7424 <1> jz short cpp_3 ; the parent's page is not same page 3629 <1> ; 3630 0000279C 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 3631 000027A1 39C8 <1> cmp eax, ecx ; Same page? 3632 000027A3 751B <1> jne short cpp_3 ; Parent page and child page are not same 3633 <1> ; Convert child's page to writable page 3634 <1> cpp_1: 3635 000027A5 E837FCFFFF <1> call allocate_page 3636 000027AA 721A <1> jc short cpp_4 ; 'insufficient memory' error 3637 000027AC 21F6 <1> and esi, esi ; check ESI is valid or not 3638 000027AE 7405 <1> jz short cpp_2 3639 <1> ; Convert read only page to writable page 3640 <1> ;(for the parent of the current process) 3641 <1> ;and word [esi], PTE_A_CLEAR ; 0F000h 3642 <1> ; 22/09/2015 3643 000027B0 890E <1> mov [esi], ecx 3644 000027B2 800E07 <1> or byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER 3645 <1> ; 1+2+4 = 7 3646 <1> cpp_2: 3647 000027B5 89C7 <1> mov edi, eax ; new page address of the child process 3648 <1> ; 07/09/2015 3649 000027B7 89CE <1> mov esi, ecx ; the page address of the parent process 3650 000027B9 B900040000 <1> mov ecx, PAGE_SIZE / 4 3651 000027BE F3A5 <1> rep movsd ; 31/08/2015 3652 <1> cpp_3: 3653 000027C0 0C07 <1> or al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7 3654 000027C2 8903 <1> mov [ebx], eax ; Update PTE 3655 000027C4 28C0 <1> sub al, al ; clear attributes 3656 <1> cpp_4: 3657 <1> ; 16/04/2021 3658 <1> ; 19/04/2020 - Retro UNIX 386 v2 3659 <1> ;pop ecx ; **** 3660 <1> ;pop ebx ; *** 3661 000027C6 5F <1> pop edi ; ** 3662 000027C7 5E <1> pop esi ; * 3663 000027C8 C3 <1> retn 3664 <1> 3665 <1> ;; 28/04/2015 3666 <1> ;; 24/10/2014 3667 <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning) 3668 <1> ;; SWAP_PAGE_QUEUE (4096 bytes) 3669 <1> ;; 3670 <1> ;; 0000 0001 0002 0003 .... 1020 1021 1022 1023 3671 <1> ;; +------+------+------+------+- -+------+------+------+------+ 3672 <1> ;; | pg1 | pg2 | pg3 | pg4 | .... |pg1021|pg1022|pg1023|pg1024| 3673 <1> ;; +------+------+------+------+- -+------+------+------+------+ 3674 <1> ;; 3675 <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue 3676 <1> ;; 3677 <1> ;; Method: 3678 <1> ;; Swap page queue is a list of allocated pages with physical 3679 <1> ;; addresses (system mode virtual adresses = physical addresses). 3680 <1> ;; It is used for 'swap_in' and 'swap_out' procedures. 3681 <1> ;; When a new page is being allocated, swap queue is updated 3682 <1> ;; by 'swap_queue_shift' procedure, header of the queue (offset 0) 3683 <1> ;; is checked for 'accessed' flag. If the 1st page on the queue 3684 <1> ;; is 'accessed' or 'read only', it is dropped from the list; 3685 <1> ;; other pages from the 2nd to the last (in [swpq_last]) shifted 3686 <1> ;; to head then the 2nd page becomes the 1st and '[swpq_last]' 3687 <1> ;; offset value becomes it's previous offset value - 4. 3688 <1> ;; If the 1st page of the swap page queue is not 'accessed' 3689 <1> ;; the queue/list is not shifted. 3690 <1> ;; After the queue/list shift, newly allocated page is added 3691 <1> ;; to the tail of the queue at the [swpq_count*4] position. 3692 <1> ;; But, if [swpq_count] > 1023, the newly allocated page 3693 <1> ;; will not be added to the tail of swap page queue. 3694 <1> ;; 3695 <1> ;; During 'swap_out' procedure, swap page queue is checked for 3696 <1> ;; the first non-accessed, writable page in the list, 3697 <1> ;; from the head to the tail. The list is shifted to left 3698 <1> ;; (to the head) till a non-accessed page will be found in the list. 3699 <1> ;; Then, this page is swapped out (to disk) and then it is dropped 3700 <1> ;; from the list by a final swap queue shift. [swpq_count] value 3701 <1> ;; is changed. If all pages on the queue' are 'accessed', 3702 <1> ;; 'insufficient memory' error will be returned ('swap_out' 3703 <1> ;; procedure will be failed)... 3704 <1> ;; 3705 <1> ;; Note: If the 1st page of the queue is an 'accessed' page, 3706 <1> ;; 'accessed' flag of the page will be reset (0) and that page 3707 <1> ;; (PTE) will be added to the tail of the queue after 3708 <1> ;; the check, if [swpq_count] < 1023. If [swpq_count] = 1024 3709 <1> ;; the queue will be rotated and the PTE in the head will be 3710 <1> ;; added to the tail after resetting 'accessed' bit. 3711 <1> ;; 3712 <1> ;; 3713 <1> ;; 3714 <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks) 3715 <1> ;; 3716 <1> ;; 00000000 00000004 00000008 0000000C ... size-8 size-4 3717 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 3718 <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) | 3719 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 3720 <1> ;; 3721 <1> ;; [swpd_next] = the first free block address in swapped page records 3722 <1> ;; for next free block search by 'swap_out' procedure. 3723 <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes) 3724 <1> ;; NOTE: max. possible swap disk size is 1024 GB 3725 <1> ;; (entire swap space must be accessed by using 3726 <1> ;; 31 bit offset address) 3727 <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space 3728 <1> ;; [swpd_start] = absolute/start address of the swap disk/file 3729 <1> ;; 0 for file, or beginning sector of the swap partition 3730 <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file 3731 <1> ;; 3732 <1> ;; 3733 <1> ;; Method: 3734 <1> ;; When the memory (ram) becomes insufficient, page allocation 3735 <1> ;; procedure swaps out a page from memory to the swap disk 3736 <1> ;; (partition) or swap file to get a new free page at the memory. 3737 <1> ;; Swapping out is performed by using swap page queue. 3738 <1> ;; 3739 <1> ;; Allocation block size of swap disk/file is equal to page size 3740 <1> ;; (4096 bytes). Swapping address (in sectors) is recorded 3741 <1> ;; into relevant page file entry as 31 bit physical (logical) 3742 <1> ;; offset address as 1 bit shifted to left for present flag (0). 3743 <1> ;; Swapped page address is between 1 and swap disk/file size - 4. 3744 <1> ;; Absolute physical (logical) address of the swapped page is 3745 <1> ;; calculated by adding offset value to the swap partition's 3746 <1> ;; start address. If the swap device (disk) is a virtual disk 3747 <1> ;; or it is a file, start address of the swap disk/volume is 0, 3748 <1> ;; and offset value is equal to absolute (physical or logical) 3749 <1> ;; address/position. (It has not to be ZERO if the swap partition 3750 <1> ;; is in a partitioned virtual hard disk.) 3751 <1> ;; 3752 <1> ;; Note: Swap addresses are always specified/declared in sectors, 3753 <1> ;; not in bytes or in blocks/zones/clusters (4096 bytes) as unit. 3754 <1> ;; 3755 <1> ;; Swap disk/file allocation is mapped via 'Swap Allocation Table' 3756 <1> ;; at memory as similar to 'Memory Allocation Table'. 3757 <1> ;; 3758 <1> ;; Every bit of Swap Allocation Table repsesents one swap block 3759 <1> ;; (equal to page size) respectively. Bit 0 of the S.A.T. byte 0 3760 <1> ;; is reserved for swap disk/file block 0 as descriptor block 3761 <1> ;; (also for compatibility with PTE). If bit value is ZERO, 3762 <1> ;; it means relevant (respective) block is in use, and, 3763 <1> ;; of course, if bit value is 1, it means relevant (respective) 3764 <1> ;; swap disk/file block is free. 3765 <1> ;; For example: bit 1 of the byte 128 repsesents block 1025 3766 <1> ;; (128*8+1) or sector (offset) 8200 on the swap disk or 3767 <1> ;; byte (offset/position) 4198400 in the swap file. 3768 <1> ;; 4GB swap space is represented via 128KB Swap Allocation Table. 3769 <1> ;; Initial layout of Swap Allocation Table is as follows: 3770 <1> ;; ------------------------------------------------------------ 3771 <1> ;; 0111111111111111111111111 .... 11111111111111111111111111111 3772 <1> ;; ------------------------------------------------------------ 3773 <1> ;; (0 is reserved block, 1s represent free blocks respectively.) 3774 <1> ;; (Note: Allocation cell/unit of the table is bit, not byte) 3775 <1> ;; 3776 <1> ;; .............................................................. 3777 <1> ;; 3778 <1> ;; 'swap_out' procedure checks 'free_swap_blocks' count at first, 3779 <1> ;; then it searches Swap Allocation Table if free count is not 3780 <1> ;; zero. From begining the [swpd_next] dword value, the first bit 3781 <1> ;; position with value of 1 on the table is converted to swap 3782 <1> ;; disk/file offset address, in sectors (not 4096 bytes block). 3783 <1> ;; 'ldrv_write' procedure is called with ldrv (logical drive 3784 <1> ;; number of physical swap disk or virtual swap disk) 3785 <1> ;; number, sector offset (not absolute sector -LBA- number), 3786 <1> ;; and sector count (8, 512*8 = 4096) and buffer adress 3787 <1> ;; (memory page). That will be a direct disk write procedure. 3788 <1> ;; (for preventing late memory allocation, significant waiting). 3789 <1> ;; If disk write procedure returns with error or free count of 3790 <1> ;; swap blocks is ZERO, 'swap_out' procedure will return with 3791 <1> ;; 'insufficient memory error' (cf=1). 3792 <1> ;; 3793 <1> ;; (Note: Even if free swap disk/file blocks was not zero, 3794 <1> ;; any disk write error will not be fixed by 'swap_out' procedure, 3795 <1> ;; in other words, 'swap_out' will not check the table for other 3796 <1> ;; free blocks after a disk write error. It will return to 3797 <1> ;; the caller with error (CF=1) which means swapping is failed. 3798 <1> ;; 3799 <1> ;; After writing the page on to swap disk/file address/sector, 3800 <1> ;; 'swap_out' procedure returns with that swap (offset) sector 3801 <1> ;; address (cf=0). 3802 <1> ;; 3803 <1> ;; .............................................................. 3804 <1> ;; 3805 <1> ;; 'swap_in' procedure loads addressed (relevant) swap disk or 3806 <1> ;; file sectors at specified memory page. Then page allocation 3807 <1> ;; procedure updates relevant page table entry with 'present' 3808 <1> ;; attribute. If swap disk or file reading fails there is nothing 3809 <1> ;; to do, except to terminate the process which is the owner of 3810 <1> ;; the swapped page. 3811 <1> ;; 3812 <1> ;; 'swap_in' procedure sets the relevant/respective bit value 3813 <1> ;; in the Swap Allocation Table (as free block). 'swap_in' also 3814 <1> ;; updates [swpd_first] pointer if it is required. 3815 <1> ;; 3816 <1> ;; .............................................................. 3817 <1> ;; 3818 <1> ;; Note: If [swap_enabled] value is ZERO, that means there is not 3819 <1> ;; a swap disk or swap file in use... 'swap_in' and 'swap_out' 3820 <1> ;; procedures ans 'swap page que' procedures will not be active... 3821 <1> ;; 'Insufficient memory' error will be returned by 'swap_out' 3822 <1> ;; and 'general protection fault' will be returned by 'swap_in' 3823 <1> ;; procedure, if it is called mistakenly (a wrong value in a PTE). 3824 <1> ;; 3825 <1> 3826 <1> ; 24/12/2021 3827 <1> ; ('swap_in' procedure call is disabled) 3828 <1> 3829 <1> ;swap_in: 3830 <1> ; 31/08/2015 3831 <1> ; 20/07/2015 3832 <1> ; 28/04/2015 3833 <1> ; 18/04/2015 3834 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 3835 <1> ; 3836 <1> ; INPUT -> 3837 <1> ; EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE 3838 <1> ; EBP = VIRTUAL (LINEAR) ADDRESS (page fault address) 3839 <1> ; EAX = Offset Address for the swapped page on the 3840 <1> ; swap disk or in the swap file. 3841 <1> ; 3842 <1> ; OUTPUT -> 3843 <1> ; EAX = 0 if loading at memory has been successful 3844 <1> ; 3845 <1> ; CF = 1 -> swap disk reading error (disk/file not present 3846 <1> ; or sector not present or drive not ready 3847 <1> ; EAX = Error code 3848 <1> ; [u.error] = EAX 3849 <1> ; = The last error code for the process 3850 <1> ; (will be reset after returning to user) 3851 <1> ; 3852 <1> ; Modified Registers -> EAX 3853 <1> ; 3854 <1> 3855 <1> ; cmp dword [swp_drv], 0 3856 <1> ; jna short swpin_dnp_err 3857 <1> ; 3858 <1> ; cmp eax, [swpd_size] 3859 <1> ; jnb short swpin_snp_err 3860 <1> ; 3861 <1> ; push esi 3862 <1> ; push ebx 3863 <1> ; push ecx 3864 <1> ; mov esi, [swp_drv] 3865 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 3866 <1> ; ; Note: Even if corresponding physical disk's sector 3867 <1> ; ; size different than 512 bytes, logical disk sector 3868 <1> ; ; size is 512 bytes and disk reading procedure 3869 <1> ; ; will be performed for reading 4096 bytes 3870 <1> ; ; (2*2048, 8*512). 3871 <1> ; ; ESI = Logical disk description table address 3872 <1> ; ; EBX = Memory page (buffer) address (physical!) 3873 <1> ; ; EAX = Sector adress (offset address, logical sector number) 3874 <1> ; ; ECX = Sector count ; 8 sectors 3875 <1> ; push eax 3876 <1> ; call logical_disk_read 3877 <1> ; pop eax 3878 <1> ; jnc short swpin_read_ok 3879 <1> ; ; 3880 <1> ; mov eax, SWP_DISK_READ_ERR ; drive not ready or read error 3881 <1> ; mov [u.error], eax 3882 <1> ; jmp short swpin_retn 3883 <1> ; ; 3884 <1> ;swpin_read_ok: 3885 <1> ; ; EAX = Offset address (logical sector number) 3886 <1> ; call unlink_swap_block ; Deallocate swap block 3887 <1> ; ; 3888 <1> ; ; EBX = Memory page (buffer) address (physical!) 3889 <1> ; ; 20/07/2015 3890 <1> ; mov ebx, ebp ; virtual address (page fault address) 3891 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 3892 <1> ; mov bl, [u.uno] ; current process number 3893 <1> ; ; EBX = Virtual (Linear) address & process number combination 3894 <1> ; call swap_queue_shift 3895 <1> ; ; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0) 3896 <1> ; ;sub eax, eax ; 0 ; Error Code = 0 (no error) 3897 <1> ; ; zf = 1 3898 <1> ;swpin_retn: 3899 <1> ; pop ecx 3900 <1> ; pop ebx 3901 <1> ; pop esi 3902 <1> ; retn 3903 <1> ; 3904 <1> ;swpin_dnp_err: 3905 <1> ; mov eax, SWP_DISK_NOT_PRESENT_ERR 3906 <1> ;swpin_err_retn: 3907 <1> ; mov [u.error], eax 3908 <1> ; stc 3909 <1> ; retn 3910 <1> ; 3911 <1> ;swpin_snp_err: 3912 <1> ; mov eax, SWP_SECTOR_NOT_PRESENT_ERR 3913 <1> ; jmp short swpin_err_retn 3914 <1> 3915 <1> ; 24/12/2021 3916 <1> ; ('swap_out' procedure call is disabled) 3917 <1> 3918 <1> ;swap_out: 3919 <1> ; 10/06/2016 3920 <1> ; 07/06/2016 3921 <1> ; 23/05/2016 3922 <1> ; 19/05/2016 - TRDOS 386 (TRDOS v2.0) 3923 <1> ; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1) 3924 <1> ; 3925 <1> ; INPUT -> 3926 <1> ; none 3927 <1> ; 3928 <1> ; OUTPUT -> 3929 <1> ; EAX = Physical page address (which is swapped out 3930 <1> ; for allocating a new page) 3931 <1> ; CF = 1 -> swap disk writing error (disk/file not present 3932 <1> ; or sector not present or drive not ready 3933 <1> ; EAX = Error code 3934 <1> ; [u.error] = EAX 3935 <1> ; = The last error code for the process 3936 <1> ; (will be reset after returning to user) 3937 <1> ; 3938 <1> ; Modified Registers -> none (except EAX) 3939 <1> ; 3940 <1> 3941 <1> ; cmp word [swpq_count], 1 3942 <1> ; jc swpout_im_err ; 'insufficient memory' 3943 <1> ; 3944 <1> ; ;cmp dword [swp_drv], 1 3945 <1> ; ;jc short swpout_dnp_err ; 'swap disk/file not present' 3946 <1> ; 3947 <1> ; cmp dword [swpd_free], 1 3948 <1> ; jc swpout_nfspc_err ; 'no free space on swap disk' 3949 <1> ; 3950 <1> ; push ebx ; * 3951 <1> ;swpout_1: 3952 <1> ; ; 10/06/2016 3953 <1> ; xor ebx, ebx ; shift the queue and return a PTE value 3954 <1> ; call swap_queue_shift 3955 <1> ; and eax, eax ; 0 = empty queue (improper entries) 3956 <1> ; jz swpout_npts_err ; There is not any proper PTE 3957 <1> ; ; pointer in the swap queue 3958 <1> ; ; EAX = PTE value of the page 3959 <1> ; ; EBX = PTE address of the page 3960 <1> ; and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3961 <1> ; ; 3962 <1> ; ; 07/06/2016 3963 <1> ; ; 19/05/2016 3964 <1> ; ; check this page is in timer events or not 3965 <1> ; 3966 <1> ;swpout_timer_page_0: 3967 <1> ; push edx ; ** 3968 <1> ; 3969 <1> ; ; 07/06/2016 3970 <1> ; cmp byte [timer_events], 0 3971 <1> ; jna short swpout_2 3972 <1> ; ; 3973 <1> ; mov dl, [timer_events] 3974 <1> ; 3975 <1> ; push ecx ; *** 3976 <1> ; push ebx ; **** 3977 <1> ; mov ebx, timer_set ; beginning address of timer event 3978 <1> ; ; structures 3979 <1> ;swpout_timer_page_1: 3980 <1> ; mov cl, [ebx] 3981 <1> ; or cl, cl ; 0 = free, >0 = process number 3982 <1> ; jz short swpout_timer_page_3 3983 <1> ; mov ecx, [ebx+12] ; response (signal return) address 3984 <1> ; and cx, PTE_A_CLEAR ; clear offset part (right 12 bits) 3985 <1> ; ; of the response byte address, to 3986 <1> ; ; get beginning of the page address) 3987 <1> ; cmp eax, ecx 3988 <1> ; jne short swpout_timer_page_2 ; not same page 3989 <1> ; 3990 <1> ; ; !same page! 3991 <1> ; ; 3992 <1> ; ; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! - 3993 <1> ; ; This page will be used by the kernel to put timer event 3994 <1> ; ; response (signal return) byte at the requested address; 3995 <1> ; ; in order to prevent a possible wrong write (while 3996 <1> ; ; this page is swapped out) on physical memory, 3997 <1> ; ; we must protect this page against to be swapped out! 3998 <1> ; ; 3999 <1> ; pop ebx ; **** 4000 <1> ; pop ecx ; *** 4001 <1> ; pop edx ; ** 4002 <1> ; jmp short swpout_1 ; do not swap out this page ! 4003 <1> ; 4004 <1> ;swpout_timer_page_2: 4005 <1> ; ; 07/06/2016 4006 <1> ; dec dl 4007 <1> ; jz short swpout_timer_page_4 4008 <1> ;swpout_timer_page_3: 4009 <1> ; ;cmp ebx, timer_set + 240 ; last timer event (15*16) 4010 <1> ; ;jnb short swpout_timer_page_4 4011 <1> ; add ebx, 16 4012 <1> ; jmp short swpout_timer_page_1 4013 <1> ; 4014 <1> ;swpout_timer_page_4: 4015 <1> ; pop ebx ; **** 4016 <1> ; pop ecx ; *** 4017 <1> ;swpout_2: 4018 <1> ; mov edx, ebx ; Page table entry address 4019 <1> ; mov ebx, eax ; Buffer (Page) Address 4020 <1> ; ; 4021 <1> ; call link_swap_block 4022 <1> ; jnc short swpout_3 ; It may not be needed here 4023 <1> ; ; because [swpd_free] value 4024 <1> ; ; was checked at the beginging. 4025 <1> ; pop edx ; ** 4026 <1> ; pop ebx ; * 4027 <1> ; jmp short swpout_nfspc_err 4028 <1> ;swpout_3: 4029 <1> ; test eax, 80000000h ; test bit 31 (this may not be needed!) 4030 <1> ; jnz short swpout_nfspc_err ; 10/06/2016 (bit 31 = 1 !) 4031 <1> ; ; 4032 <1> ; push esi ; ** 4033 <1> ; push ecx ; *** 4034 <1> ; push eax ; sector address ; (31 bit !, bit 31 = 0) 4035 <1> ; mov esi, [swp_drv] 4036 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 4037 <1> ; ; Note: Even if corresponding physical disk's sector 4038 <1> ; ; size different than 512 bytes, logical disk sector 4039 <1> ; ; size is 512 bytes and disk writing procedure 4040 <1> ; ; will be performed for writing 4096 bytes 4041 <1> ; ; (2*2048, 8*512). 4042 <1> ; ; ESI = Logical disk description table address 4043 <1> ; ; EBX = Buffer (Page) address 4044 <1> ; ; EAX = Sector adress (offset address, logical sector number) 4045 <1> ; ; ECX = Sector count ; 8 sectors 4046 <1> ; ; edx = PTE address 4047 <1> ; call logical_disk_write 4048 <1> ; ; edx = PTE address 4049 <1> ; pop ecx ; sector address 4050 <1> ; jnc short swpout_write_ok 4051 <1> ; ; 4052 <1> ; ;; call unlink_swap_block ; this block must be left as 'in use' 4053 <1> ;swpout_dw_err: 4054 <1> ; mov eax, SWP_DISK_WRITE_ERR ; drive not ready or write error 4055 <1> ; mov [u.error], eax 4056 <1> ; jmp short swpout_retn 4057 <1> ; ; 4058 <1> ;swpout_write_ok: 4059 <1> ; ; EBX = Buffer (page) address 4060 <1> ; ; EDX = Page Table Entry address 4061 <1> ; ; ECX = Swap disk sector (file block) address (31 bit) 4062 <1> ; shl ecx, 1 ; 31 bit sector address from bit 1 to bit 31 4063 <1> ; mov [edx], ecx 4064 <1> ; ; bit 0 = 0 (swapped page) 4065 <1> ; mov eax, ebx 4066 <1> ;swpout_retn: 4067 <1> ; pop ecx ; *** 4068 <1> ; pop esi ; ** 4069 <1> ; pop ebx ; * 4070 <1> ; retn 4071 <1> ; 4072 <1> ;;swpout_dnp_err: 4073 <1> ;; mov eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present 4074 <1> ;; jmp short swpout_err_retn 4075 <1> ;swpout_nfspc_err: 4076 <1> ; mov eax, SWP_NO_FREE_SPACE_ERR ; no free space 4077 <1> ;swpout_err_retn: 4078 <1> ; mov [u.error], eax 4079 <1> ; ;stc 4080 <1> ; retn 4081 <1> ;swpout_npts_err: 4082 <1> ; mov eax, SWP_NO_PAGE_TO_SWAP_ERR 4083 <1> ; pop ebx 4084 <1> ; jmp short swpout_err_retn 4085 <1> ;swpout_im_err: 4086 <1> ; mov eax, ERR_MINOR_IM ; insufficient (out of) memory 4087 <1> ; jmp short swpout_err_retn 4088 <1> 4089 <1> ; 24/12/2021 4090 <1> ; ('swap_queue_shift' procedure call is disabled) 4091 <1> 4092 <1> ;swap_queue_shift: 4093 <1> ; 26/03/2017 4094 <1> ; 10/06/2016 4095 <1> ; 09/06/2016 - TRDOS 386 (TRDOS v2.0) 4096 <1> ; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1) 4097 <1> ; 4098 <1> ; INPUT -> 4099 <1> ; EBX = Virtual (linear) address (bit 12 to 31) 4100 <1> ; and process number combination (bit 0 to 11) 4101 <1> ; EBX = 0 -> shift/drop from the head (offset 0) 4102 <1> ; 4103 <1> ; OUTPUT -> 4104 <1> ; If EBX input > 0 4105 <1> ; the queue will be shifted 4 bytes (dword), 4106 <1> ; from the tail to the head, up to entry offset 4107 <1> ; which points to EBX input value or nothing 4108 <1> ; to do if EBX value is not found on the queue. 4109 <1> ; (The entry -with EBX value- will be removed 4110 <1> ; from the queue if it is found.) 4111 <1> ; 4112 <1> ; EAX = 0 4113 <1> ; 4114 <1> ; If EBX input = 0 4115 <1> ; the queue will be shifted 4 bytes (dword), 4116 <1> ; from the tail to the head, if the PTE address 4117 <1> ; which is pointed in head of the queue is marked 4118 <1> ; as "accessed" or it is marked as "non present". 4119 <1> ; (If "accessed" flag of the PTE -which is pointed 4120 <1> ; in the head- is set -to 1-, it will be reset 4121 <1> ; -to 0- and then, the queue will be rotated 4122 <1> ; -without dropping pointer of the PTE from 4123 <1> ; the queue- for 4 bytes on head to tail direction. 4124 <1> ; Pointer in the head will be moved into the tail, 4125 <1> ; other PTEs will be shifted on head direction.) 4126 <1> ; 4127 <1> ; Swap queue will be shifted up to the first 4128 <1> ; 'present' or 'non accessed' page will be found 4129 <1> ; (as pointed) on the queue head (then it will be 4130 <1> ; removed/dropped from the queue). 4131 <1> ; 4132 <1> ; EAX (> 0) = PTE value of the page which is 4133 <1> ; (it's pointer -virtual address-) dropped 4134 <1> ; (removed) from swap queue. 4135 <1> ; EBX = PTE address of the page (if EAX > 0) 4136 <1> ; which is (it's pointer -virtual address-) 4137 <1> ; dropped (removed) from swap queue. 4138 <1> ; 4139 <1> ; EAX = 0 -> empty swap queue ! 4140 <1> ; 4141 <1> ; Modified Registers -> EAX, EBX 4142 <1> ; 4143 <1> ; movzx eax, word [swpq_count] ; Max. 1024 4144 <1> ; and ax, ax 4145 <1> ; jz short swpqs_retn 4146 <1> ; push edi 4147 <1> ; push esi 4148 <1> ; push ecx 4149 <1> ; mov esi, swap_queue 4150 <1> ; mov ecx, eax 4151 <1> ; or ebx, ebx 4152 <1> ; jz short swpqs_7 4153 <1> ;swpqs_1: 4154 <1> ; lodsd 4155 <1> ; cmp eax, ebx 4156 <1> ; je short swpqs_2 4157 <1> ; loop swpqs_1 4158 <1> ; ; 10/06/2016 4159 <1> ; sub eax, eax 4160 <1> ; jmp short swpqs_6 4161 <1> ;swpqs_2: 4162 <1> ; mov edi, esi 4163 <1> ; sub edi, 4 4164 <1> ;swpqs_3: 4165 <1> ; dec word [swpq_count] 4166 <1> ; jz short swpqs_5 4167 <1> ;swpqs_4: 4168 <1> ; dec ecx 4169 <1> ; rep movsd ; shift up (to the head) 4170 <1> ;swpqs_5: 4171 <1> ; xor eax, eax 4172 <1> ; mov [edi], eax 4173 <1> ;swpqs_6: 4174 <1> ; pop ecx 4175 <1> ; pop esi 4176 <1> ; pop edi 4177 <1> ;swpqs_retn: 4178 <1> ; retn 4179 <1> ;swpqs_7: 4180 <1> ; mov edi, esi ; head 4181 <1> ; lodsd 4182 <1> ; ; 20/07/2015 4183 <1> ; mov ebx, eax 4184 <1> ; and ebx, ~PAGE_OFF ; ~0FFFh 4185 <1> ; ; ebx = virtual address (at page boundary) 4186 <1> ; and eax, PAGE_OFF ; 0FFFh 4187 <1> ; ; ax = process number (1 to 4095) 4188 <1> ; cmp al, [u.uno] 4189 <1> ; ; Max. 16 (nproc) processes for Retro UNIX 386 v1 4190 <1> ; jne short swpqs_8 4191 <1> ; mov eax, [u.pgdir] 4192 <1> ; jmp short swpqs_9 4193 <1> ;swpqs_8: 4194 <1> ; ; 09/06/2016 4195 <1> ; cmp byte [eax+p.stat-1], 0 4196 <1> ; jna short swpqs_3 ; free (or terminated) process 4197 <1> ; cmp byte [eax+p.stat-1], 2 ; waiting 4198 <1> ; ja short swpqs_3 ; zombie (3) or undefined ? 4199 <1> ; 4200 <1> ; ;shl ax, 2 4201 <1> ; shl al, 2 4202 <1> ; mov eax, [eax+p.upage-4] 4203 <1> ; or eax, eax 4204 <1> ; jz short swpqs_3 ; invalid upage 4205 <1> ; add eax, u.pgdir - user 4206 <1> ; ; u.pgdir value for the process 4207 <1> ; ; is in [eax] 4208 <1> ; mov eax, [eax] 4209 <1> ; and eax, eax 4210 <1> ; jz short swpqs_3 ; invalid page directory 4211 <1> ;swpqs_9: 4212 <1> ; push edx 4213 <1> ; ; eax = page directory 4214 <1> ; ; ebx = virtual address 4215 <1> ; call get_pte 4216 <1> ; mov ebx, edx ; PTE address 4217 <1> ; pop edx 4218 <1> ; ; 10/06/2016 4219 <1> ; jc short swpqs_13 ; empty PDE 4220 <1> ; ; EAX = PTE value 4221 <1> ; test al, PTE_A_PRESENT ; bit 0 = 1 4222 <1> ; jz short swpqs_13 ; Drop non-present page 4223 <1> ; ; from the queue (head) 4224 <1> ; test al, PTE_A_WRITE ; bit 1 = 0 (read only) 4225 <1> ; jz short swpqs_13 ; Drop read only page 4226 <1> ; ; from the queue (head) 4227 <1> ; ;test al, PTE_A_ACCESS ; bit 5 = 1 (Accessed) 4228 <1> ; ;jnz short swpqs_11 ; present 4229 <1> ; ; accessed page 4230 <1> ; btr eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit 4231 <1> ; jc short swpqs_11 ; accessed page 4232 <1> ; 4233 <1> ; dec ecx 4234 <1> ; mov [swpq_count], cx 4235 <1> ; jz short swpqs_10 4236 <1> ; ; esi = head + 4 4237 <1> ; ; edi = head 4238 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 4239 <1> ;swpqs_10: 4240 <1> ; mov [edi], ecx ; 0 4241 <1> ; jmp short swpqs_6 ; 26/03/2017 4242 <1> ; 4243 <1> ;swpqs_11: 4244 <1> ; mov [ebx], eax ; save changed attribute 4245 <1> ; ; Rotation (head -> tail) 4246 <1> ; dec ecx ; entry count -> last entry number 4247 <1> ; jz short swpqs_10 4248 <1> ; ; esi = head + 4 4249 <1> ; ; edi = head 4250 <1> ; mov eax, [edi] ; 20/07/2015 4251 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 4252 <1> ; mov [edi], eax ; head -> tail ; [k] = [1] 4253 <1> ; 4254 <1> ; mov cx, [swpq_count] 4255 <1> ; 4256 <1> ;swpqs_12: 4257 <1> ; mov esi, swap_queue ; head 4258 <1> ; jmp swpqs_7 4259 <1> ; 4260 <1> ;swpqs_13: 4261 <1> ; dec ecx 4262 <1> ; mov [swpq_count], cx 4263 <1> ; jz swpqs_5 4264 <1> ; jmp short swpqs_12 4265 <1> 4266 <1> ; 24/12/2021 4267 <1> ; ('add_to_swp_queue' procedure call is disabled) 4268 <1> 4269 <1> ;add_to_swap_queue: 4270 <1> ; 20/02/2017 4271 <1> ; 20/07/2015 4272 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4273 <1> ; 4274 <1> ; Adds new page to swap queue 4275 <1> ; (page directories and page tables must not be added 4276 <1> ; to swap queue) 4277 <1> ; 4278 <1> ; INPUT -> 4279 <1> ; EBX = Linear (Virtual) addr for current process 4280 <1> ; [u.uno] 4281 <1> ; 20/02/2017 4282 <1> ; (Linear address = CORE + user's virtual address) 4283 <1> ; 4284 <1> ; OUTPUT -> 4285 <1> ; EAX = [swpq_count] 4286 <1> ; (after the PTE has been added) 4287 <1> ; EAX = 0 -> Swap queue is full, (1024 entries) 4288 <1> ; the PTE could not be added. 4289 <1> ; 4290 <1> ; Modified Registers -> EAX 4291 <1> ; 4292 <1> ; push ebx 4293 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 4294 <1> ; mov bl, [u.uno] ; current process number 4295 <1> ; call swap_queue_shift ; drop from the queue if 4296 <1> ; ; it is already on the queue 4297 <1> ; ; then add it to the tail of the queue 4298 <1> ; movzx eax, word [swpq_count] 4299 <1> ; cmp ax, 1024 4300 <1> ; jb short atsq_1 4301 <1> ; sub ax, ax 4302 <1> ; pop ebx 4303 <1> ; retn 4304 <1> ;atsq_1: 4305 <1> ; push esi 4306 <1> ; mov esi, swap_queue 4307 <1> ; and ax, ax 4308 <1> ; jz short atsq_2 4309 <1> ; shl ax, 2 ; convert to offset 4310 <1> ; add esi, eax 4311 <1> ; shr ax, 2 4312 <1> ;atsq_2: 4313 <1> ; inc ax 4314 <1> ; mov [esi], ebx ; Virtual address + [u.uno] combination 4315 <1> ; mov [swpq_count], ax 4316 <1> ; pop esi 4317 <1> ; pop ebx 4318 <1> ; retn 4319 <1> 4320 <1> ; 24/12/2021 4321 <1> ; ('unlink_swap_block' procedure call is disabled) 4322 <1> 4323 <1> ;unlink_swap_block: 4324 <1> ; 15/09/2015 4325 <1> ; 30/04/2015 4326 <1> ; 18/04/2015 4327 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4328 <1> ; 4329 <1> ; INPUT -> 4330 <1> ; EAX = swap disk/file offset address 4331 <1> ; (bit 1 to bit 31) 4332 <1> ; OUTPUT -> 4333 <1> ; [swpd_free] is increased 4334 <1> ; (corresponding SWAP DISK ALLOC. TABLE bit is SET) 4335 <1> ; 4336 <1> ; Modified Registers -> EAX 4337 <1> ; 4338 <1> ; push ebx 4339 <1> ; push edx 4340 <1> ; ; 4341 <1> ; shr eax, SECTOR_SHIFT+1 ;3+1 ; shift sector address to 4342 <1> ; ; 3 bits right 4343 <1> ; ; to get swap block/page number 4344 <1> ; mov edx, eax 4345 <1> ; ; 15/09/2015 4346 <1> ; shr edx, 3 ; to get offset to S.A.T. 4347 <1> ; ; (1 allocation bit = 1 page) 4348 <1> ; ; (1 allocation bytes = 8 pages) 4349 <1> ; and dl, 0FCh ; clear lower 2 bits 4350 <1> ; ; (to get 32 bit position) 4351 <1> ; ; 4352 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table address 4353 <1> ; add ebx, edx 4354 <1> ; and eax, 1Fh ; lower 5 bits only 4355 <1> ; ; (allocation bit position) 4356 <1> ; cmp eax, [swpd_next] ; is the new free block addr. lower 4357 <1> ; ; than the address in 'swpd_next' ? 4358 <1> ; ; (next/first free block value) 4359 <1> ; jnb short uswpbl_1 ; no 4360 <1> ; mov [swpd_next], eax ; yes 4361 <1> ;uswpbl_1: 4362 <1> ; bts [ebx], eax ; unlink/release/deallocate block 4363 <1> ; ; set relevant bit to 1. 4364 <1> ; ; set CF to the previous bit value 4365 <1> ; cmc ; complement carry flag 4366 <1> ; jc short uswpbl_2 ; do not increase swfd_free count 4367 <1> ; ; if the block is already deallocated 4368 <1> ; ; before. 4369 <1> ; inc dword [swpd_free] 4370 <1> ;uswpbl_2: 4371 <1> ; pop edx 4372 <1> ; pop ebx 4373 <1> ; retn 4374 <1> 4375 <1> ; 24/12/2021 4376 <1> ; ('link_swap_block' procedure call is disabled) 4377 <1> 4378 <1> ;link_swap_block: 4379 <1> ; 01/07/2015 4380 <1> ; 18/04/2015 4381 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4382 <1> ; 4383 <1> ; INPUT -> none 4384 <1> ; 4385 <1> ; OUTPUT -> 4386 <1> ; EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes) 4387 <1> ; in sectors (corresponding 4388 <1> ; SWAP DISK ALLOCATION TABLE bit is RESET) 4389 <1> ; 4390 <1> ; CF = 1 and EAX = 0 4391 <1> ; if there is not a free block to be allocated 4392 <1> ; 4393 <1> ; Modified Registers -> none (except EAX) 4394 <1> ; 4395 <1> 4396 <1> ; ;mov eax, [swpd_free] 4397 <1> ; ;and eax, eax 4398 <1> ; ;jz short out_of_swpspc 4399 <1> ; ; 4400 <1> ; push ebx 4401 <1> ; push ecx 4402 <1> ; ; 4403 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table offset 4404 <1> ; mov ecx, ebx 4405 <1> ; add ebx, [swpd_next] ; Free block searching starts from here 4406 <1> ; ; next_free_swap_block >> 5 4407 <1> ; add ecx, [swpd_last] ; Free block searching ends here 4408 <1> ; ; (total_swap_blocks - 1) >> 5 4409 <1> ;lswbl_scan: 4410 <1> ; cmp ebx, ecx 4411 <1> ; ja short lswbl_notfound 4412 <1> ; ; 4413 <1> ; bsf eax, [ebx] ; Scans source operand for first bit set (1). 4414 <1> ; ; Clears ZF if a bit is found set (1) and 4415 <1> ; ; loads the destination with an index to 4416 <1> ; ; first set bit. (0 -> 31) 4417 <1> ; ; Sets ZF to 1 if no bits are found set. 4418 <1> ; ; 01/07/2015 4419 <1> ; jnz short lswbl_found ; ZF = 0 -> a free block has been found 4420 <1> ; ; 4421 <1> ; ; NOTE: a Swap Disk Allocation Table bit 4422 <1> ; ; with value of 1 means 4423 <1> ; ; the corresponding page is free 4424 <1> ; ; (Retro UNIX 386 v1 feaure only!) 4425 <1> ; add ebx, 4 4426 <1> ; ; We return back for searching next page block 4427 <1> ; ; NOTE: [swpd_free] is not ZERO; so, 4428 <1> ; ; we always will find at least 1 free block here. 4429 <1> ; jmp short lswbl_scan 4430 <1> ; ; 4431 <1> ;lswbl_notfound: 4432 <1> ; sub ecx, swap_alloc_table 4433 <1> ; mov [swpd_next], ecx ; next/first free page = last page 4434 <1> ; ; (unlink_swap_block procedure will change it) 4435 <1> ; xor eax, eax 4436 <1> ; mov [swpd_free], eax 4437 <1> ; stc 4438 <1> ;lswbl_ok: 4439 <1> ; pop ecx 4440 <1> ; pop ebx 4441 <1> ; retn 4442 <1> ; ; 4443 <1> ;;out_of_swpspc: 4444 <1> ;; stc 4445 <1> ;; retn 4446 <1> ; 4447 <1> ;lswbl_found: 4448 <1> ; mov ecx, ebx 4449 <1> ; sub ecx, swap_alloc_table 4450 <1> ; mov [swpd_next], ecx ; Set first free block searching start 4451 <1> ; ; address/offset (to the next) 4452 <1> ; dec dword [swpd_free] ; 1 block has been allocated (X = X-1) 4453 <1> ; ; 4454 <1> ; btr [ebx], eax ; The destination bit indexed by the source value 4455 <1> ; ; is copied into the Carry Flag and then cleared 4456 <1> ; ; in the destination. 4457 <1> ; ; 4458 <1> ; ; Reset the bit which is corresponding to the 4459 <1> ; ; (just) allocated block. 4460 <1> ; shl ecx, 5 ; (block offset * 32) + block index 4461 <1> ; add eax, ecx ; = block number 4462 <1> ; shl eax, SECTOR_SHIFT ; 3, sector (offset) address of the block 4463 <1> ; ; 1 block = 8 sectors 4464 <1> ; ; 4465 <1> ; ; EAX = offset address of swap disk/file sector (beginning of the block) 4466 <1> ; ; 4467 <1> ; ; NOTE: The relevant page table entry will be updated 4468 <1> ; ; according to this EAX value... 4469 <1> ; ; 4470 <1> ; jmp short lswbl_ok 4471 <1> 4472 <1> ; 24/12/2021 4473 <1> ; ('logical_disk_read' procedure call is disabled) 4474 <1> 4475 <1> ;logical_disk_read: 4476 <1> ; 20/07/2015 4477 <1> ; 09/03/2015 (temporary code here) 4478 <1> ; 4479 <1> ; INPUT -> 4480 <1> ; ESI = Logical disk description table address 4481 <1> ; EBX = Memory page (buffer) address (physical!) 4482 <1> ; EAX = Sector adress (offset address, logical sector number) 4483 <1> ; ECX = Sector count 4484 <1> ; 4485 <1> ; 4486 <1> ; retn 4487 <1> 4488 <1> ; 24/12/2021 4489 <1> ; ('logical_disk_write' procedure call is disabled) 4490 <1> 4491 <1> ;logical_disk_write: 4492 <1> ; 20/07/2015 4493 <1> ; 09/03/2015 (temporary code here) 4494 <1> ; 4495 <1> ; INPUT -> 4496 <1> ; ESI = Logical disk description table address 4497 <1> ; EBX = Memory page (buffer) address (physical!) 4498 <1> ; EAX = Sector adress (offset address, logical sector number) 4499 <1> ; ECX = Sector count 4500 <1> ; 4501 <1> ; retn 4502 <1> 4503 <1> get_physical_addr: 4504 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4505 <1> ; 19/04/2020 - Retro UNIX 386 v2 4506 <1> ; 18/10/2015 4507 <1> ; 29/07/2015 4508 <1> ; 20/07/2015 4509 <1> ; 04/06/2015 4510 <1> ; 20/05/2015 4511 <1> ; 28/04/2015 4512 <1> ; 18/04/2015 4513 <1> ; Get physical address 4514 <1> ; (allocates a new page for user if it is not present) 4515 <1> ; 4516 <1> ; (This subroutine is needed for mapping user's virtual 4517 <1> ; (buffer) address to physical address (of the buffer).) 4518 <1> ; ('sys write', 'sys read' system calls...) 4519 <1> ; 4520 <1> ; INPUT -> 4521 <1> ; EBX = virtual address 4522 <1> ; u.pgdir = page directory (physical) address 4523 <1> ; 4524 <1> ; OUTPUT -> 4525 <1> ; EAX = physical address 4526 <1> ; EBX = linear address 4527 <1> ; EDX = physical address of the page frame 4528 <1> ; (with attribute bits) 4529 <1> ; ECX = byte count within the page frame 4530 <1> ; 4531 <1> ; Modified Registers -> EAX, EBX, ECX, EDX 4532 <1> ; 4533 <1> 4534 <1> ; 19/04/2020 - Retro UNIX386 v2 4535 000027C9 A1[53650000] <1> mov eax, [u.pgdir] 4536 <1> 4537 <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2 4538 <1> 4539 000027CE 81C300004000 <1> add ebx, CORE ; 18/10/2015 4540 <1> ; 4541 <1> ;mov eax, [u.pgdir] 4542 000027D4 E81AFDFFFF <1> call get_pte 4543 <1> ; EDX = Page table entry address (if CF=0) 4544 <1> ; Page directory entry address (if CF=1) 4545 <1> ; (Bit 0 value is 0 if PT is not present) 4546 <1> ; EAX = Page table entry value (page address) 4547 <1> ; CF = 1 -> PDE not present or invalid ? 4548 000027D9 731C <1> jnc short gpa_1 4549 <1> ; 4550 000027DB E801FCFFFF <1> call allocate_page 4551 000027E0 724B <1> jc short gpa_im_err ; 'insufficient memory' error 4552 <1> gpa_0: 4553 000027E2 E86BFCFFFF <1> call clear_page 4554 <1> ; EAX = Physical (base) address of the allocated (new) page 4555 000027E7 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7 4556 <1> ; lower 3 bits are used as U/S, R/W, P flags 4557 <1> ; (user, writable, present page) 4558 000027E9 8902 <1> mov [edx], eax ; Let's put the new page directory entry here ! 4559 000027EB A1[53650000] <1> mov eax, [u.pgdir] 4560 000027F0 E8FEFCFFFF <1> call get_pte 4561 000027F5 7236 <1> jc short gpa_im_err ; 'insufficient memory' error 4562 <1> gpa_1: 4563 <1> ; EAX = PTE value, EDX = PTE address 4564 000027F7 A801 <1> test al, PTE_A_PRESENT 4565 000027F9 750A <1> jnz short gpa_3 4566 000027FB 09C0 <1> or eax, eax 4567 000027FD 7420 <1> jz short gpa_4 ; Allocate a new page 4568 <1> 4569 <1> ; 24/12/2021 4570 <1> ; ('reload_page' procedure call is disabled) 4571 000027FF EB2C <1> jmp short gpa_im_err 4572 <1> 4573 <1> ; 20/07/2015 4574 <1> ; push ebp 4575 <1> ; mov ebp, ebx ; virtual (linear) address 4576 <1> ; ; reload swapped page 4577 <1> ; call reload_page ; 28/04/2015 4578 <1> ; pop ebp 4579 <1> ; jc short gpa_retn 4580 <1> gpa_2: 4581 <1> ; 24/12/2021 4582 <1> ; ('add_to_swap_queue' procedure call is disabled) 4583 <1> 4584 <1> ; 20/07/2015 4585 <1> ; 20/05/2015 4586 <1> ; add this page to swap queue 4587 <1> ; push eax 4588 <1> ; ; EBX = Linear (CORE+virtual) address ; 20/02/2017 4589 <1> ; call add_to_swap_queue 4590 <1> ; pop eax 4591 <1> ; PTE address in EDX 4592 <1> ; virtual address in EBX 4593 <1> ; EAX = memory page address 4594 00002801 0C07 <1> or al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE 4595 <1> ; present flag, bit 0 = 1 4596 <1> ; user flag, bit 2 = 1 4597 <1> ; writable flag, bit 1 = 1 4598 00002803 8902 <1> mov [edx], eax ; Update PTE value 4599 <1> gpa_3: 4600 <1> ; 18/10/2015 4601 00002805 89D9 <1> mov ecx, ebx 4602 00002807 81E1FF0F0000 <1> and ecx, PAGE_OFF 4603 0000280D 89C2 <1> mov edx, eax 4604 0000280F 662500F0 <1> and ax, PTE_A_CLEAR 4605 00002813 01C8 <1> add eax, ecx 4606 00002815 F7D9 <1> neg ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095 4607 00002817 81C100100000 <1> add ecx, PAGE_SIZE 4608 0000281D F8 <1> clc 4609 <1> gpa_retn: 4610 0000281E C3 <1> retn 4611 <1> gpa_4: 4612 0000281F E8BDFBFFFF <1> call allocate_page 4613 00002824 7207 <1> jc short gpa_im_err ; 'insufficient memory' error 4614 00002826 E827FCFFFF <1> call clear_page 4615 0000282B EBD4 <1> jmp short gpa_2 4616 <1> 4617 <1> gpa_im_err: 4618 0000282D B804000000 <1> mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 4619 <1> ; Major error = 0 (No protection fault) 4620 00002832 C3 <1> retn 4621 <1> 4622 <1> ; 24/12/2021 4623 <1> ; ('reload_page' procedure call is disabled) 4624 <1> 4625 <1> ;reload_page: 4626 <1> ; 20/07/2015 4627 <1> ; 28/04/2015 (Retro UNIX 386 v1 - beginning) 4628 <1> ; 4629 <1> ; Reload (Restore) swapped page at memory 4630 <1> ; 4631 <1> ; INPUT -> 4632 <1> ; EBP = Virtual (linear) memory address 4633 <1> ; EAX = PTE value (swap disk sector address) 4634 <1> ; (Swap disk sector address = bit 1 to bit 31 of EAX) 4635 <1> ; OUTPUT -> 4636 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE 4637 <1> ; 4638 <1> ; CF = 1 and EAX = error code 4639 <1> ; 4640 <1> ; Modified Registers -> none (except EAX) 4641 <1> ; 4642 <1> ; shr eax, 1 ; Convert PTE value to swap disk address 4643 <1> ; push ebx ; 4644 <1> ; mov ebx, eax ; Swap disk (offset) address 4645 <1> ; call allocate_page 4646 <1> ; jc short rlp_im_err 4647 <1> ; xchg eax, ebx 4648 <1> ; ; EBX = Physical memory (page) address 4649 <1> ; ; EAX = Swap disk (offset) address 4650 <1> ; ; EBP = Virtual (linear) memory address 4651 <1> ; call swap_in 4652 <1> ; jc short rlp_swp_err ; (swap disk/file read error) 4653 <1> ; mov eax, ebx 4654 <1> ;rlp_retn: 4655 <1> ; pop ebx 4656 <1> ; retn 4657 <1> ; 4658 <1> ;rlp_im_err: 4659 <1> ; mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 4660 <1> ; ; Major error = 0 (No protection fault) 4661 <1> ; jmp short rlp_retn 4662 <1> ; 4663 <1> ;rlp_swp_err: 4664 <1> ; mov eax, SWP_DISK_READ_ERR ; Swap disk read error ! 4665 <1> ; jmp short rlp_retn 4666 <1> 4667 <1> copy_page_dir: 4668 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4669 <1> ; 19/09/2015 4670 <1> ; temporary - 07/09/2015 4671 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 4672 <1> ; 4673 <1> ; INPUT -> 4674 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 4675 <1> ; page directory. 4676 <1> ; OUTPUT -> 4677 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 4678 <1> ; page directory. 4679 <1> ; (New page directory with new page table entries.) 4680 <1> ; (New page tables with read only copies of the parent's 4681 <1> ; pages.) 4682 <1> ; EAX = 0 -> Error (CF = 1) 4683 <1> ; 4684 <1> ; Modified Registers -> none (except EAX) 4685 <1> ; 4686 00002833 E8A9FBFFFF <1> call allocate_page 4687 00002838 723E <1> jc short cpd_err 4688 <1> ; 4689 0000283A 55 <1> push ebp ; 20/07/2015 4690 0000283B 56 <1> push esi 4691 0000283C 57 <1> push edi 4692 0000283D 53 <1> push ebx 4693 0000283E 51 <1> push ecx 4694 0000283F 8B35[53650000] <1> mov esi, [u.pgdir] 4695 00002845 89C7 <1> mov edi, eax 4696 00002847 50 <1> push eax ; save child's page directory address 4697 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 4698 <1> ; (use same system space for all user page tables) 4699 00002848 A5 <1> movsd 4700 00002849 BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 4701 0000284E B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 4702 <1> cpd_0: 4703 00002853 AD <1> lodsd 4704 <1> ;or eax, eax 4705 <1> ;jnz short cpd_1 4706 00002854 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 4707 00002856 7508 <1> jnz short cpd_1 4708 <1> ; (virtual address at the end of the page table) 4709 00002858 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 4710 0000285E EB0F <1> jmp short cpd_2 4711 <1> cpd_1: 4712 00002860 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 4713 00002864 89C3 <1> mov ebx, eax 4714 <1> ; EBX = Parent's page table address 4715 00002866 E81F000000 <1> call copy_page_table 4716 0000286B 720C <1> jc short cpd_p_err 4717 <1> ; EAX = Child's page table address 4718 0000286D 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 4719 <1> ; set bit 0, bit 1 and bit 2 to 1 4720 <1> ; (present, writable, user) 4721 <1> cpd_2: 4722 0000286F AB <1> stosd 4723 00002870 E2E1 <1> loop cpd_0 4724 <1> ; 4725 00002872 58 <1> pop eax ; restore child's page directory address 4726 <1> cpd_3: 4727 00002873 59 <1> pop ecx 4728 00002874 5B <1> pop ebx 4729 00002875 5F <1> pop edi 4730 00002876 5E <1> pop esi 4731 00002877 5D <1> pop ebp 4732 <1> cpd_err: 4733 00002878 C3 <1> retn 4734 <1> cpd_p_err: 4735 <1> ; release the allocated pages missing (recover free space) 4736 00002879 58 <1> pop eax ; the new page directory address (physical) 4737 0000287A 8B1D[53650000] <1> mov ebx, [u.pgdir] ; parent's page directory address 4738 00002880 E88CFCFFFF <1> call deallocate_page_dir 4739 00002885 29C0 <1> sub eax, eax ; 0 4740 00002887 F9 <1> stc 4741 00002888 EBE9 <1> jmp short cpd_3 4742 <1> 4743 <1> copy_page_table: 4744 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4745 <1> ; 19/09/2015 4746 <1> ; temporary - 07/09/2015 4747 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 4748 <1> ; 4749 <1> ; INPUT -> 4750 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 4751 <1> ; EBP = page table entry index (from 'copy_page_dir') 4752 <1> ; OUTPUT -> 4753 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 4754 <1> ; EBP = (recent) page table index (for 'add_to_swap_queue') 4755 <1> ; CF = 1 -> error 4756 <1> ; 4757 <1> ; Modified Registers -> EBP (except EAX) 4758 <1> ; 4759 0000288A E852FBFFFF <1> call allocate_page 4760 0000288F 7244 <1> jc short cpt_err 4761 <1> ; 4762 00002891 50 <1> push eax ; * 4763 <1> ;push ebx 4764 00002892 56 <1> push esi 4765 00002893 57 <1> push edi 4766 00002894 52 <1> push edx 4767 00002895 51 <1> push ecx 4768 <1> ; 4769 00002896 89DE <1> mov esi, ebx 4770 00002898 89C7 <1> mov edi, eax 4771 0000289A 89C2 <1> mov edx, eax 4772 0000289C 81C200100000 <1> add edx, PAGE_SIZE 4773 <1> cpt_0: 4774 000028A2 AD <1> lodsd 4775 000028A3 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 4776 <1> ;jnz short cpt_1 (*) 4777 <1> ; 24/12/2021 4778 <1> ;and eax, eax (*) 4779 000028A5 741E <1> jz short cpt_2 ; 24/12/2021 4780 <1> 4781 <1> ; 24/12/2021 4782 <1> ; ('reload_page' procedure call is disabled) 4783 <1> ; 4784 <1> ; ; ebp = virtual (linear) address of the memory page 4785 <1> ; call reload_page ; 28/04/2015 4786 <1> ; jc short cpt_p_err 4787 <1> cpt_1: 4788 000028A7 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 4789 000028AB 89C1 <1> mov ecx, eax 4790 <1> ; Allocate a new page for the child process 4791 000028AD E82FFBFFFF <1> call allocate_page 4792 000028B2 721C <1> jc short cpt_p_err 4793 000028B4 57 <1> push edi 4794 000028B5 56 <1> push esi 4795 000028B6 89CE <1> mov esi, ecx 4796 000028B8 89C7 <1> mov edi, eax 4797 000028BA B900040000 <1> mov ecx, PAGE_SIZE/4 4798 000028BF F3A5 <1> rep movsd ; copy page (4096 bytes) 4799 000028C1 5E <1> pop esi 4800 000028C2 5F <1> pop edi 4801 <1> ; 4802 <1> ; 24/12/2021 4803 <1> ; ('add_to_swap_queue' procedure call is disabled) 4804 <1> ; 4805 <1> ; push ebx 4806 <1> ; push eax 4807 <1> ; mov ebx, ebp 4808 <1> ; ; ebx = virtual address of the memory page 4809 <1> ; call add_to_swap_queue 4810 <1> ; pop eax 4811 <1> ; pop ebx 4812 <1> ; 4813 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 4814 000028C3 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 4815 <1> cpt_2: 4816 000028C5 AB <1> stosd ; EDI points to child's PTE 4817 <1> ; 4818 000028C6 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 4819 <1> ; 4820 000028CC 39D7 <1> cmp edi, edx 4821 000028CE 72D2 <1> jb short cpt_0 4822 <1> cpt_p_err: 4823 000028D0 59 <1> pop ecx 4824 000028D1 5A <1> pop edx 4825 000028D2 5F <1> pop edi 4826 000028D3 5E <1> pop esi 4827 <1> ;pop ebx 4828 000028D4 58 <1> pop eax ; * 4829 <1> cpt_err: 4830 000028D5 C3 <1> retn 4831 <1> 4832 <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS /// 4833 <1> 4834 <1> ;; Data: 4835 <1> 4836 <1> ; 09/03/2015 4837 <1> ;swpq_count: dw 0 ; count of pages on the swap que 4838 <1> ;swp_drv: dd 0 ; logical drive description table address of the swap drive/disk 4839 <1> ;swpd_size: dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 4840 <1> ;swpd_free: dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical) 4841 <1> ;swpd_next: dd 0 ; next free page block 4842 <1> ;swpd_last: dd 0 ; last swap page block 2050 %include 'sysdefs.inc' ; 09/03/2015 2051 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYSDEFS.INC 2052 <1> ; Last Modification: 15/07/2022 2053 <1> ; 2054 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 2055 <1> ; (Modified from 2056 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 2057 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 2058 <1> ; UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11) 2059 <1> ; ---------------------------------------------------------------------------- 2060 <1> ; 2061 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2062 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2063 <1> ; 2064 <1> ; 2065 <1> ; 2066 <1> ; **************************************************************************** 2067 <1> 2068 <1> nproc equ 16 ; number of processes 2069 <1> nfiles equ 50 2070 <1> ntty equ 8 ; 8+1 -> 8 (10/05/2013) 2071 <1> ;nbuf equ 6 ; number of buffers (04/02/2016) 2072 <1> nbuf equ 8 ; 15/07/2022 2073 <1> 2074 <1> ;csgmnt equ 2000h ; 26/05/2013 (segment of process 1) 2075 <1> ;core equ 0 ; 19/04/2013 2076 <1> ;ecore equ 32768 - 64 ; 04/06/2013 (24/05/2013) 2077 <1> ; (if total size of argument list and arguments is 128 bytes) 2078 <1> ; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes 2079 <1> ; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570) 2080 <1> ; initial value of user's stack pointer = 32768-64-128-2 = 32574 2081 <1> ; (sp=32768-args_space-2 at the beginning of execution) 2082 <1> ; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes) 2083 <1> ; 'u' structure offset (for the '/core' dump file) = 32704 2084 <1> ; '/core' dump file size = 32768 bytes 2085 <1> 2086 <1> ; 08/03/2014 2087 <1> ;sdsegmnt equ 6C0h ; 256*16 bytes (swap data segment size for 16 processes) 2088 <1> ; 19/04/2013 Retro UNIX 8086 v1 feature only ! 2089 <1> ;;sdsegmnt equ 740h ; swap data segment (for user structures and registers) 2090 <1> 2091 <1> ; 30/08/2013 2092 <1> time_count equ 4 ; 10 --> 4 01/02/2014 2093 <1> 2094 <1> ; 05/02/2014 2095 <1> ; process status 2096 <1> ;SFREE equ 0 2097 <1> ;SRUN equ 1 2098 <1> ;SWAIT equ 2 2099 <1> ;SZOMB equ 3 2100 <1> ;SSLEEP equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup) 2101 <1> 2102 <1> ; 09/03/2015 2103 <1> userdata equ 80000h ; user structure data address for current user ; temporary 2104 <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary 2105 <1> swap_alloc_table equ 0D0000h ; swap allocation table address ; temporary 2106 <1> 2107 <1> ; 17/09/2015 2108 <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return 2109 <1> 2110 <1> ; 21/09/2015 (36) 2111 <1> ; 01/07/2015 (35) 2112 <1> ; 14/07/2013 (0-34) 2113 <1> ; UNIX v1 system calls 2114 <1> _rele equ 0 2115 <1> _exit equ 1 2116 <1> _fork equ 2 2117 <1> _read equ 3 2118 <1> _write equ 4 2119 <1> _open equ 5 2120 <1> _close equ 6 2121 <1> _wait equ 7 2122 <1> _creat equ 8 2123 <1> _link equ 9 2124 <1> _unlink equ 10 2125 <1> _exec equ 11 2126 <1> _chdir equ 12 2127 <1> _time equ 13 2128 <1> _mkdir equ 14 2129 <1> _chmod equ 15 2130 <1> _chown equ 16 2131 <1> _break equ 17 2132 <1> _stat equ 18 2133 <1> _seek equ 19 2134 <1> _tell equ 20 2135 <1> _mount equ 21 2136 <1> _umount equ 22 2137 <1> _setuid equ 23 2138 <1> _getuid equ 24 2139 <1> _stime equ 25 2140 <1> _quit equ 26 2141 <1> _intr equ 27 2142 <1> _fstat equ 28 2143 <1> _emt equ 29 2144 <1> _mdate equ 30 2145 <1> _stty equ 31 2146 <1> _gtty equ 32 2147 <1> _ilgins equ 33 2148 <1> _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 2149 <1> _msg equ 35 ; Retro UNIX 386 v1 feature only ! 2150 <1> _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 2151 <1> 2152 <1> %macro sys 1-4 2153 <1> ; 13/04/2015 2154 <1> ; Retro UNIX 386 v1 system call. 2155 <1> mov eax, %1 2156 <1> %if %0 >= 2 2157 <1> mov ebx, %2 2158 <1> %if %0 >= 3 2159 <1> mov ecx, %3 2160 <1> %if %0 = 4 2161 <1> mov edx, %4 2162 <1> %endif 2163 <1> %endif 2164 <1> %endif 2165 <1> int 30h 2166 <1> %endmacro 2167 <1> 2168 <1> ; 13/05/2015 - ERROR CODES 2169 <1> ERR_FILE_NOT_OPEN equ 10 ; 'file not open !' error 2170 <1> ERR_FILE_ACCESS equ 11 ; 'permission denied !' error 2171 <1> ; 14/05/2015 2172 <1> ERR_DIR_ACCESS equ 11 ; 'permission denied !' error 2173 <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error 2174 <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error 2175 <1> ERR_DIR_EXISTS equ 14 ; 'directory already exists !' error 2176 <1> ; 16/05/2015 2177 <1> ERR_DRV_NOT_RDY equ 15 ; 'drive not ready !' error 2178 <1> ; 18/05/2015 2179 <1> ERR_DEV_NOT_RDY equ 15 ; 'device not ready !' error 2180 <1> ERR_DEV_ACCESS equ 11 ; 'permission denied !' error 2181 <1> ERR_DEV_NOT_OPEN equ 10 ; 'device not open !' error 2182 <1> ; 07/06/2015 2183 <1> ERR_FILE_EOF equ 16 ; 'end of file !' error 2184 <1> ERR_DEV_VOL_SIZE equ 16 ; 'out of volume' error 2185 <1> ; 09/06/2015 2186 <1> ERR_DRV_READ equ 17 ; 'disk read error !' 2187 <1> ERR_DRV_WRITE equ 18 ; 'disk write error !' 2188 <1> ; 16/06/2015 2189 <1> ERR_NOT_DIR equ 19 ; 'not a (valid) directory !' error 2190 <1> ERR_FILE_SIZE equ 20 ; 'file size error !' 2191 <1> ; 22/06/2015 2192 <1> ERR_NOT_SUPERUSER equ 11 ; 'permission denied !' error 2193 <1> ERR_NOT_OWNER equ 11 ; 'permission denied !' error 2194 <1> ERR_NOT_FILE equ 11 ; 'permission denied !' error 2195 <1> ; 23/06/2015 2196 <1> ERR_FILE_EXISTS equ 14 ; 'file already exists !' error 2197 <1> ERR_DRV_NOT_SAME equ 21 ; 'not same drive !' error 2198 <1> ERR_DIR_NOT_FOUND equ 12 ; 'directory not found !' error 2199 <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error 2200 <1> ; 27/06/2015 2201 <1> ERR_INV_PARAMETER equ 23 ; 'invalid parameter !' error 2202 <1> ERR_INV_DEV_NAME equ 24 ; 'invalid device name !' error 2203 <1> ; 29/06/2015 2204 <1> ERR_TIME_OUT equ 25 ; 'time out !' error 2205 <1> ERR_DEV_NOT_RESP equ 25 ; 'device not responding !' error 2206 <1> ; 12/02/2022 2207 <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s') 2208 <1> ; 10/10/2016 2209 <1> ERR_INV_FILE_NAME equ 26 ; 'invalid file name !' error 2210 <1> ; 18/05/2016 2211 <1> ERR_MISC equ 27 ; miscellaneous/other errors 2212 <1> ; 15/10/2016 2213 <1> ERR_INV_FORMAT equ 28 ; 'invalid format !' error 2214 <1> ERR_INV_DATA equ 29 ; 'invalid data !' error 2215 <1> ; 16/10/2016 2216 <1> ERR_DISK_WRITE equ 30 ; 'disk write protected !' 2217 <1> ; 08/02/2022 2218 <1> ERR_INV_FS equ 28 ;'invalid fs/superblock !' error 2219 <1> 2220 <1> ; 13/06/2022 2221 <1> ; printer errors 2222 <1> ERR_PRN_NOT_RDY equ 15 ; 'device not ready !' error 2223 <1> ERR_PRN_TIMEOUT equ 25 ; 'time out !' error 2224 <1> ERR_PRN_PAPER equ 31 ; 'out of paper !' error 2225 <1> ERR_PRN_IO equ 32 ; 'io error !' error 2226 <1> ERR_PRN_BUSY equ 34 ; 'busy !' error 2227 <1> 2228 <1> ; 26/08/2015 2229 <1> ; 24/07/2015 2230 <1> ; 24/06/2015 2231 <1> MAX_ARG_LEN equ 256 ; max. length of sys exec arguments 2232 <1> ; 01/07/2015 2233 <1> MAX_MSG_LEN equ 255 ; max. msg length for 'sysmsg' 2234 <1> ; 2051 %include 'u0.s' ; 15/03/2015 2052 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS0.INC 2053 <1> ; Last Modification: 17/07/2022 2054 <1> ; ---------------------------------------------------------------------------- 2055 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2056 <1> ; (v0.1 - Beginning: 11/07/2012) 2057 <1> ; 2058 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2059 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2060 <1> ; 2061 <1> ; 2062 <1> ; 2063 <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s 2064 <1> ; 2065 <1> ; **************************************************************************** 2066 <1> ; 21/11/2015 2067 <1> 2068 <1> sys_init: 2069 <1> ; 27/02/2022 2070 <1> ; 23/02/2022 2071 <1> ; 04/02/2022 2072 <1> ; 18/10/2015 2073 <1> ; 28/08/2015 2074 <1> ; 24/08/2015 2075 <1> ; 14/08/2015 2076 <1> ; 24/07/2015 2077 <1> ; 02/07/2015 2078 <1> ; 01/07/2015 2079 <1> ; 23/06/2015 2080 <1> ; 15/04/2015 2081 <1> ; 13/04/2015 2082 <1> ; 11/03/2015 (Retro UNIX 386 v1 - Beginning) 2083 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2084 <1> ; 2085 <1> ;call ldrv_init ; Logical drive description tables initialization 2086 <1> ; 2087 <1> ; 14/02/2014 2088 <1> ; 14/07/2013 2089 <1> ;;mov ax, 41 2090 <1> ; 27/02/2022 2091 <1> ;xor eax, eax 2092 <1> ;mov al, 41 2093 <1> ;mov [rootdir], ax 2094 <1> ;mov [u.cdir], ax 2095 <1> ;;and al, 1 ; 15/04/2015 2096 <1> ;inc al ; ax = 1 2097 000028D6 B001 <1> mov al, 1 2098 000028D8 A2[49650000] <1> mov [u.uno], al 2099 <1> ;mov [mpid], ax 2100 <1> ;mov [p.pid], ax 2101 000028DD A2[EC640000] <1> mov [mpid], al 2102 000028E2 A2[14620000] <1> mov [p.pid], al 2103 000028E7 A2[74620000] <1> mov [p.stat], al ; SRUN, 05/02/2014 2104 <1> ; 27/02/2022 2105 000028EC B029 <1> mov al, 41 2106 <1> ;mov [rootdir], ax 2107 <1> ;mov [u.cdir], ax 2108 000028EE A2[EE640000] <1> mov [rootdir], al 2109 000028F3 A2[04650000] <1> mov [u.cdir], al 2110 <1> ; 2111 <1> ; 23/02/2022 2112 <1> ;call epoch 2113 <1> ;mov [s.time], eax ; 13/03/2015 2114 <1> ; 17/07/2013 2115 000028F8 E888060000 <1> call bf_init ; buffer initialization 2116 <1> ; 23/02/2022 2117 <1> ; (save sysinit time on sb0) 2118 000028FD E830030000 <1> call epoch 2119 00002902 A3[54770000] <1> mov [s.time], eax ; 13/03/2015 2120 <1> ; 23/06/2015 2121 00002907 E8D5FAFFFF <1> call allocate_page 2122 <1> ;;jc error 2123 <1> ;jc panic ; jc short panic (01/07/2015) 2124 <1> ; 04/02/2022 2125 0000290C 7305 <1> jnc short sysinit_1 2126 0000290E E990000000 <1> jmp panic 2127 <1> sysinit_1: 2128 00002913 A3[4A650000] <1> mov [u.upage], eax ; user structure page 2129 00002918 A3[84620000] <1> mov [p.upage], eax 2130 <1> ; 2131 0000291D E830FBFFFF <1> call clear_page 2132 <1> ; 2133 <1> ; 14/08/2015 2134 00002922 FA <1> cli 2135 <1> ; 14/03/2015 2136 <1> ; 17/01/2014 2137 00002923 E8D7010000 <1> call sp_init ; serial port initialization 2138 <1> ; 14/08/2015 2139 00002928 FB <1> sti 2140 <1> ; 2141 <1> ; 30/06/2015 2142 <1> ;mov esi, kernel_init_ok_msg 2143 <1> ;call print_msg 2144 <1> ; 2145 00002929 30DB <1> xor bl, bl ; video page 0 2146 <1> vp_clr_nxt: ; clear video pages (reset cursor positions) 2147 0000292B E83C0F0000 <1> call vp_clr ; 17/07/2013 2148 00002930 FEC3 <1> inc bl 2149 00002932 80FB08 <1> cmp bl, 8 2150 00002935 72F4 <1> jb short vp_clr_nxt 2151 <1> ; 2152 <1> ; 24/07/2015 2153 <1> ;push KDATA 2154 <1> ;push esp 2155 <1> ;mov [tss.esp0], esp 2156 <1> ;mov word [tss.ss0], KDATA 2157 <1> ; 2158 <1> ; 27/02/2022 2159 <1> ; 24/08/2015 2160 <1> ;; temporary (01/07/2015) 2161 <1> ;mov byte [u.quant], time_count ; 4 2162 <1> ; it is not needed here ! 2163 <1> ;;inc byte [u.kcall] ; 'the caller is kernel' sign 2164 00002937 FE0D[F5640000] <1> dec byte [sysflg] ; FFh = ready for system call 2165 <1> ; 0 = executing a system call 2166 <1> ;;sys _msg, kernel_init_ok_msg, 255, 0 2167 <1> ; 2168 <1> ;;; 06/08/2015 2169 <1> ;;;call getch ; wait for a key stroke 2170 <1> ;;mov ecx, 0FFFFFFFh 2171 <1> ;;sys_init_msg_wait: 2172 <1> ;; push ecx 2173 <1> ;; mov al, 1 2174 <1> ;; mov ah, [ptty] ; active (current) video page 2175 <1> ;; call getc_n 2176 <1> ;; pop ecx 2177 <1> ;; jnz short sys_init_msg_ok 2178 <1> ;; loop sys_init_msg_wait 2179 <1> ; 2180 <1> ;;sys_init_msg_ok: 2181 <1> ; 28/08/2015 (initial settings for the 1st 'rswap') 2182 0000293D 6A10 <1> push KDATA ; ss 2183 0000293F 54 <1> push esp 2184 00002940 9C <1> pushfd 2185 00002941 6A08 <1> push KCODE ; cs 2186 00002943 68[77290000] <1> push init_exec ; eip 2187 00002948 8925[F8640000] <1> mov [u.sp], esp 2188 0000294E 1E <1> push ds 2189 0000294F 06 <1> push es 2190 00002950 0FA0 <1> push fs 2191 00002952 0FA8 <1> push gs 2192 00002954 60 <1> pushad 2193 00002955 8925[FC640000] <1> mov [u.usp], esp 2194 0000295B E8AD1B0000 <1> call wswap ; save current user (u) structure, user registers 2195 <1> ; and interrupt return components (for IRET) 2196 00002960 61 <1> popad 2197 00002961 6658 <1> pop ax ; gs 2198 00002963 6658 <1> pop ax ; fs 2199 00002965 6658 <1> pop ax ; es 2200 00002967 6658 <1> pop ax ; ds 2201 00002969 58 <1> pop eax ; eip (init_exec) 2202 0000296A 6658 <1> pop ax ; cs (KCODE) 2203 0000296C 58 <1> pop eax ; E-FLAGS 2204 0000296D 58 <1> pop eax ; esp 2205 0000296E 6658 <1> pop ax ; ss (KDATA) 2206 <1> ; 2207 00002970 31C0 <1> xor eax, eax ; 0 2208 00002972 A3[57650000] <1> mov [u.ppgdir], eax ; reset (to zero) for '/etc/init' 2209 <1> ; 2210 <1> ; 02/07/2015 2211 <1> ; [u.pgdir ] = [k_page_dir] 2212 <1> ; [u.ppgdir] = 0 (page dir of the parent process) 2213 <1> ; (The caller is os kernel sign for 'sysexec') 2214 <1> init_exec: 2215 <1> ; 13/03/2013 2216 <1> ; 24/07/2013 2217 00002977 BB[99290000] <1> mov ebx, init_file 2218 0000297C B9[91290000] <1> mov ecx, init_argp 2219 <1> ; EBX contains 'etc/init' asciiz file name address 2220 <1> ; ECX contains address of argument list pointer 2221 <1> ; 2222 <1> ;dec byte [sysflg] ; FFh = ready for system call 2223 <1> ; 0 = executing a system call 2224 <1> sys _exec ; execute file 2153 <2> 2154 <2> 2155 00002981 B80B000000 <2> mov eax, %1 2156 <2> %if %0 >= 2 2157 <2> mov ebx, %2 2158 <2> %if %0 >= 3 2159 <2> mov ecx, %3 2160 <2> %if %0 = 4 2161 <2> mov edx, %4 2162 <2> %endif 2163 <2> %endif 2164 <2> %endif 2165 00002986 CD30 <2> int 30h 2225 00002988 7319 <1> jnc short panic 2226 <1> ; 2227 0000298A BE[4E5E0000] <1> mov esi, etc_init_err_msg 2228 <1> ; 27/02/2022 2229 <1> ;call print_msg 2230 0000298F EB17 <1> jmp short key_to_reboot 2231 <1> 2232 <1> ;align 4 2233 <1> init_argp: 2234 00002991 [99290000]00000000 <1> dd init_file, 0 ; 23/06/2015 (dw -> dd) 2235 <1> init_file: 2236 <1> ; 24/08/2015 2237 00002999 2F6574632F696E6974- <1> db '/etc/init', 0 2237 000029A2 00 <1> 2238 <1> panic: 2239 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2240 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 2241 000029A3 BE[335E0000] <1> mov esi, panic_msg 2242 <1> key_to_reboot: ; 27/02/2022 2243 000029A8 E819000000 <1> call print_msg 2244 <1> ;key_to_reboot: 2245 <1> ; 15/11/2015 2246 000029AD E8D12B0000 <1> call getch 2247 <1> ; wait for a character from the current tty 2248 <1> ; 2249 000029B2 B00A <1> mov al, 0Ah 2250 000029B4 8A1D[66610000] <1> mov bl, [ptty] ; [active_page] 2251 000029BA B407 <1> mov ah, 07h ; Black background, 2252 <1> ; light gray forecolor 2253 000029BC E8F4E8FFFF <1> call write_tty 2254 000029C1 E993E5FFFF <1> jmp cpu_reset 2255 <1> 2256 <1> print_msg: 2257 <1> ; 01/07/2015 2258 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2259 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 2260 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 2261 <1> ; 2262 <1> ; 2263 000029C6 AC <1> lodsb 2264 <1> pmsg1: 2265 000029C7 56 <1> push esi 2266 000029C8 0FB61D[66610000] <1> movzx ebx, byte [ptty] 2267 000029CF B407 <1> mov ah, 07h ; Black background, light gray forecolor 2268 000029D1 E8DFE8FFFF <1> call write_tty 2269 000029D6 5E <1> pop esi 2270 000029D7 AC <1> lodsb 2271 000029D8 20C0 <1> and al, al 2272 000029DA 75EB <1> jnz short pmsg1 2273 000029DC C3 <1> retn 2274 <1> 2275 <1> ctrlbrk: 2276 <1> ; 04/02/2022 2277 <1> ; 01/02/2022 2278 <1> ; 12/11/2015 2279 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2280 <1> ; 06/12/2013 (Retro UNIX 8086 v1) 2281 <1> ; 2282 <1> ; INT 1Bh (control+break) handler 2283 <1> ; 2284 <1> ; Retro Unix 8086 v1 feature only! 2285 <1> ; 2286 000029DD 66833D[3E650000]00 <1> cmp word [u.intr], 0 2287 000029E5 764B <1> jna short cbrk4 2288 <1> cbrk0: 2289 <1> ; 12/11/2015 2290 <1> ; 06/12/2013 2291 000029E7 66833D[40650000]00 <1> cmp word [u.quit], 0 2292 000029EF 7441 <1> jz short cbrk4 2293 <1> ; 2294 <1> ; 20/09/2013 2295 <1> ;push ax 2296 <1> ; 01/02/2022 2297 000029F1 50 <1> push eax 2298 <1> 2299 <1> ; 04/02/2022 2300 <1> ; (repetitive ctrl+brk check) 2301 000029F2 66A1[40650000] <1> mov ax, [u.quit] 2302 000029F8 6640 <1> inc ax ; 0FFFFh -> 0 2303 000029FA 7435 <1> jz short cbrk3 2304 <1> 2305 <1> ; 20/09/2013 2306 000029FC A0[66610000] <1> mov al, [ptty] 2307 <1> ; 2308 <1> ; 12/11/2015 2309 <1> ; 2310 <1> ; ctrl+break (EOT, CTRL+D) from serial port 2311 <1> ; or ctrl+break from console (pseudo) tty 2312 <1> ; (!redirection!) 2313 <1> ; 2314 00002A01 3C08 <1> cmp al, 8 ; serial port tty nums > 7 2315 00002A03 7211 <1> jb short cbrk1 ; console (pseudo) tty 2316 <1> ; 2317 <1> ; Serial port interrupt handler sets [ptty] 2318 <1> ; to the port's tty number (as temporary). 2319 <1> ; 2320 <1> ; If active process is using a stdin or 2321 <1> ; stdout redirection (by the shell), 2322 <1> ; console tty keyboard must be available 2323 <1> ; to terminate running process, 2324 <1> ; in order to prevent a deadlock. 2325 <1> ; 2326 00002A05 52 <1> push edx 2327 00002A06 0FB615[49650000] <1> movzx edx, byte [u.uno] 2328 00002A0D 3A82[53620000] <1> cmp al, [edx+p.ttyc-1] ; console tty (rw) 2329 00002A13 5A <1> pop edx 2330 00002A14 7412 <1> je short cbrk2 2331 <1> cbrk1: 2332 00002A16 FEC0 <1> inc al ; [u.ttyp] : 1 based tty number 2333 <1> ; 06/12/2013 2334 00002A18 3A05[30650000] <1> cmp al, [u.ttyp] ; recent open tty (r) 2335 00002A1E 7408 <1> je short cbrk2 2336 00002A20 3A05[31650000] <1> cmp al, [u.ttyp+1] ; recent open tty (w) 2337 00002A26 7509 <1> jne short cbrk3 2338 <1> cbrk2: 2339 <1> ;; 06/12/2013 2340 <1> ;mov ax, [u.quit] 2341 <1> ;and ax, ax 2342 <1> ;jz short cbrk3 2343 <1> ; 2344 <1> ;xor ax, ax ; 0 2345 <1> ;dec ax 2346 <1> ; 01/02/2022 2347 00002A28 31C0 <1> xor eax, eax ; 0 2348 00002A2A 48 <1> dec eax ; 0FFFFFFFFh 2349 <1> ; 0FFFFh = 'ctrl+brk' keystroke 2350 00002A2B 66A3[40650000] <1> mov [u.quit], ax 2351 <1> cbrk3: 2352 <1> ;pop ax 2353 <1> ; 01/02/2022 2354 00002A31 58 <1> pop eax 2355 <1> cbrk4: 2356 00002A32 C3 <1> retn 2357 <1> 2358 <1> com2_int: 2359 <1> ; 04/02/2022 (Retro UNIX 386 v1) 2360 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 2361 <1> ; 07/11/2015 2362 <1> ; 24/10/2015 2363 <1> ; 23/10/2015 2364 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 2365 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2366 <1> ; < serial port 2 interrupt handler > 2367 <1> ; 2368 00002A33 890424 <1> mov [esp], eax ; overwrite call return address 2369 <1> ;;push eax 2370 <1> ; 08/01/2022 2371 00002A36 29C0 <1> sub eax, eax 2372 00002A38 B009 <1> mov al, 9 2373 <1> ;mov ax, 9 2374 00002A3A EB07 <1> jmp short comm_int 2375 <1> com1_int: 2376 <1> ; 04/02/2022 (Retro UNIX 386 v1) 2377 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 2378 <1> ; 07/11/2015 2379 <1> ; 24/10/2015 2380 00002A3C 890424 <1> mov [esp], eax ; overwrite call return address 2381 <1> ; 23/10/2015 2382 <1> ;push eax 2383 <1> ; 08/01/2022 2384 00002A3F 29C0 <1> sub eax, eax 2385 00002A41 B008 <1> mov al, 8 2386 <1> ;mov ax, 8 2387 <1> comm_int: 2388 <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 2389 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2390 <1> ; 20/11/2015 2391 <1> ; 18/11/2015 2392 <1> ; 17/11/2015 2393 <1> ; 16/11/2015 2394 <1> ; 09/11/2015 2395 <1> ; 08/11/2015 2396 <1> ; 07/11/2015 2397 <1> ; 06/11/2015 (serial4.asm, 'serial') 2398 <1> ; 01/11/2015 2399 <1> ; 26/10/2015 2400 <1> ; 23/10/2015 2401 00002A43 53 <1> push ebx 2402 00002A44 56 <1> push esi 2403 00002A45 57 <1> push edi 2404 00002A46 1E <1> push ds 2405 00002A47 06 <1> push es 2406 <1> ; 18/11/2015 2407 00002A48 0F20DB <1> mov ebx, cr3 2408 00002A4B 53 <1> push ebx ; **** 2409 <1> ; 2410 00002A4C 51 <1> push ecx ; *** 2411 00002A4D 52 <1> push edx ; ** 2412 <1> ; 2413 00002A4E BB10000000 <1> mov ebx, KDATA 2414 00002A53 8EDB <1> mov ds, bx 2415 00002A55 8EC3 <1> mov es, bx 2416 <1> ; 2417 00002A57 8B0D[38610000] <1> mov ecx, [k_page_dir] 2418 00002A5D 0F22D9 <1> mov cr3, ecx 2419 <1> ; 20/11/2015 2420 <1> ; Interrupt identification register 2421 00002A60 66BAFA02 <1> mov dx, 2FAh ; COM2 2422 <1> ; 2423 00002A64 3C08 <1> cmp al, 8 2424 00002A66 7702 <1> ja short com_i0 2425 <1> ; 2426 <1> ; 04/02/2022 (Retro UNIX 386 v1) 2427 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 2428 <1> ; 20/11/2015 2429 <1> ; 17/11/2015 2430 <1> ; 16/11/2015 2431 <1> ; 15/11/2015 2432 <1> ; 24/10/2015 2433 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 2434 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2435 <1> ; < serial port 1 interrupt handler > 2436 <1> ; 2437 00002A68 FEC6 <1> inc dh ; 3FAh ; COM1 Interrupt id. register 2438 <1> com_i0: 2439 <1> ;push eax ; * 2440 <1> ; 07/11/2015 2441 00002A6A A2[A6610000] <1> mov byte [ccomport], al 2442 <1> ; 09/11/2015 2443 <1> ;movzx ebx, ax ; 8 or 9 2444 <1> ; 08/01/2022 2445 00002A6F 89C3 <1> mov ebx, eax ; 8 or 9 2446 <1> ; 17/11/2015 2447 <1> ; reset request for response status 2448 00002A71 88A3[9C610000] <1> mov [ebx+req_resp-8], ah ; 0 2449 <1> ; 2450 <1> ; 20/11/2015 2451 00002A77 EC <1> in al, dx ; read interrupt id. register 2452 00002A78 EB00 <1> JMP $+2 ; I/O DELAY 2453 00002A7A 2404 <1> and al, 4 ; received data available? 2454 00002A7C 7470 <1> jz short com_eoi ; (transmit. holding reg. empty) 2455 <1> ; 2456 <1> ; 20/11/2015 2457 00002A7E 80EA02 <1> sub dl, 3FAh-3F8h ; data register (3F8h, 2F8h) 2458 00002A81 EC <1> in al, dx ; read character 2459 <1> ;JMP $+2 ; I/O DELAY 2460 <1> ; 08/11/2015 2461 <1> ; 07/11/2015 2462 00002A82 89DE <1> mov esi, ebx 2463 00002A84 89DF <1> mov edi, ebx 2464 00002A86 81C6[A0610000] <1> add esi, rchar - 8 ; points to last received char 2465 00002A8C 81C7[A2610000] <1> add edi, schar - 8 ; points to last sent char 2466 00002A92 8806 <1> mov [esi], al ; received char (current char) 2467 <1> ; query 2468 00002A94 20C0 <1> and al, al 2469 00002A96 7527 <1> jnz short com_i2 2470 <1> ; response 2471 <1> ; 17/11/2015 2472 <1> ; set request for response status 2473 00002A98 FE83[9C610000] <1> inc byte [ebx+req_resp-8] ; 1 2474 <1> ; 2475 00002A9E 6683C205 <1> add dx, 3FDh-3F8h ; (3FDh, 2FDh) 2476 00002AA2 EC <1> in al, dx ; read line status register 2477 00002AA3 EB00 <1> JMP $+2 ; I/O DELAY 2478 00002AA5 2420 <1> and al, 20h ; transmitter holding reg. empty? 2479 00002AA7 7445 <1> jz short com_eoi ; no 2480 00002AA9 B0FF <1> mov al, 0FFh ; response 2481 00002AAB 6683EA05 <1> sub dx, 3FDh-3F8h ; data port (3F8h, 2F8h) 2482 00002AAF EE <1> out dx, al ; send on serial port 2483 <1> ; 17/11/2015 2484 00002AB0 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 2485 00002AB3 7502 <1> jne short com_i1 ; no 2486 00002AB5 8807 <1> mov [edi], al ; 0FFh (responded) 2487 <1> com_i1: 2488 <1> ; 17/11/2015 2489 <1> ; reset request for response status (again) 2490 00002AB7 FE8B[9C610000] <1> dec byte [ebx+req_resp-8] ; 0 2491 00002ABD EB2F <1> jmp short com_eoi 2492 <1> com_i2: 2493 <1> ; 08/11/2015 2494 00002ABF 3CFF <1> cmp al, 0FFh ; (response ?) 2495 00002AC1 7417 <1> je short com_i3 ; (check for response signal) 2496 <1> ; 07/11/2015 2497 00002AC3 3C04 <1> cmp al, 04h ; EOT 2498 00002AC5 751C <1> jne short com_i4 2499 <1> ; EOT = 04h (End of Transmit) - 'CTRL + D' 2500 <1> ;(an EOT char is supposed as a ctrl+brk from the terminal) 2501 <1> ; 08/11/2015 2502 <1> ; ptty -> tty 0 to 7 (pseudo screens) 2503 00002AC7 861D[66610000] <1> xchg bl, [ptty] ; tty number (8 or 9) 2504 00002ACD E80BFFFFFF <1> call ctrlbrk 2505 00002AD2 861D[66610000] <1> xchg [ptty], bl ; (restore ptty value and BL value) 2506 <1> ;mov al, 04h ; EOT 2507 <1> ; 08/11/2015 2508 00002AD8 EB09 <1> jmp short com_i4 2509 <1> com_i3: 2510 <1> ; 08/11/2015 2511 <1> ; If 0FFh has been received just after a query 2512 <1> ; (schar, ZERO), it is a response signal. 2513 <1> ; 17/11/2015 2514 00002ADA 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 2515 00002ADD 7704 <1> ja short com_i4 ; no 2516 <1> ; reset query status (schar) 2517 00002ADF 8807 <1> mov [edi], al ; 0FFh 2518 00002AE1 FEC0 <1> inc al ; 0 2519 <1> com_i4: 2520 <1> ; 27/07/2014 2521 <1> ; 09/07/2014 2522 00002AE3 D0E3 <1> shl bl, 1 2523 00002AE5 81C3[68610000] <1> add ebx, ttychr 2524 <1> ; 23/07/2014 (always overwrite) 2525 <1> ;;cmp word [ebx], 0 2526 <1> ;;ja short com_eoi 2527 <1> ; 2528 00002AEB 668903 <1> mov [ebx], ax ; Save ascii code 2529 <1> ; scan code = 0 2530 <1> com_eoi: 2531 <1> ;mov al, 20h 2532 <1> ;out 20h, al ; end of interrupt 2533 <1> ; 2534 <1> ; 07/11/2015 2535 <1> ;pop eax ; * 2536 00002AEE A0[A6610000] <1> mov al, byte [ccomport] ; current COM port 2537 <1> ; al = tty number (8 or 9) 2538 00002AF3 E8EF1A0000 <1> call wakeup 2539 <1> com_iret: 2540 <1> ; 23/10/2015 2541 00002AF8 5A <1> pop edx ; ** 2542 00002AF9 59 <1> pop ecx ; *** 2543 <1> ; 18/11/2015 2544 <1> ;pop eax ; **** 2545 <1> ;mov cr3, eax 2546 <1> ;jmp iiret 2547 00002AFA E99CDEFFFF <1> jmp iiretp 2548 <1> 2549 <1> ;hfgchr: 2550 <1> ; db '0123456789ABCDEF?*' 2551 <1> ; db 0 2552 <1> 2553 <1> ;iiretp: ; 01/09/2015 2554 <1> ; ; 28/08/2015 2555 <1> ; pop eax ; (*) page directory 2556 <1> ; mov cr3, eax 2557 <1> ;iiret: 2558 <1> ; ; 22/08/2014 2559 <1> ; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 2560 <1> ; out 20h, al ; 8259 PORT 2561 <1> ; ; 2562 <1> ; pop es 2563 <1> ; pop ds 2564 <1> ; pop edi 2565 <1> ; pop esi 2566 <1> ; pop ebx ; 29/08/2014 2567 <1> ; pop eax 2568 <1> ; iretd 2569 <1> 2570 <1> sp_init: 2571 <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 2572 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2573 <1> ; 07/11/2015 2574 <1> ; 29/10/2015 2575 <1> ; 26/10/2015 2576 <1> ; 23/10/2015 2577 <1> ; 29/06/2015 2578 <1> ; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud) 2579 <1> ; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud) 2580 <1> ; Initialization of Serial Port Communication Parameters 2581 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 2582 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 2583 <1> ; 2584 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 2585 <1> ; 2586 <1> ; INPUT: (29/06/2015) 2587 <1> ; AL = 0 for COM1 2588 <1> ; 1 for COM2 2589 <1> ; AH = Communication parameters 2590 <1> ; 2591 <1> ; (*) Communication parameters (except BAUD RATE): 2592 <1> ; Bit 4 3 2 1 0 2593 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 2594 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 2595 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 2596 <1> ; 11 = even 2597 <1> ; Baud rate setting bits: (29/06/2015) 2598 <1> ; Retro UNIX 386 v1 feature only ! 2599 <1> ; Bit 7 6 5 | Baud rate 2600 <1> ; ------------------------ 2601 <1> ; value 0 0 0 | Default (Divisor = 1) 2602 <1> ; 0 0 1 | 9600 (12) 2603 <1> ; 0 1 0 | 19200 (6) 2604 <1> ; 0 1 1 | 38400 (3) 2605 <1> ; 1 0 0 | 14400 (8) 2606 <1> ; 1 0 1 | 28800 (4) 2607 <1> ; 1 1 0 | 57600 (2) 2608 <1> ; 1 1 1 | 115200 (1) 2609 <1> 2610 <1> ; References: 2611 <1> ; (1) IBM PC-XT Model 286 BIOS Source Code 2612 <1> ; RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232) 2613 <1> ; (2) Award BIOS 1999 - ATORGS.ASM 2614 <1> ; (3) http://wiki.osdev.org/Serial_Ports 2615 <1> ; 2616 <1> ; Set communication parameters for COM1 (= 03h) 2617 <1> ; 2618 00002AFF BB[A2610000] <1> mov ebx, com1p ; COM1 parameters 2619 00002B04 66BAF803 <1> mov dx, 3F8h ; COM1 2620 <1> ; 29/10/2015 2621 00002B08 66B90103 <1> mov cx, 301h ; divisor = 1 (115200 baud) 2622 00002B0C E84F000000 <1> call sp_i3 ; call A4 2623 00002B11 A880 <1> test al, 80h 2624 00002B13 740E <1> jz short sp_i0 ; OK.. 2625 <1> ; Error ! 2626 <1> ;mov dx, 3F8h 2627 00002B15 80EA05 <1> sub dl, 5 ; 3FDh -> 3F8h 2628 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 2629 <1> ; 08/01/2022 2630 00002B18 B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 2631 00002B1A E841000000 <1> call sp_i3 ; call A4 2632 00002B1F A880 <1> test al, 80h 2633 00002B21 7508 <1> jnz short sp_i1 2634 <1> sp_i0: 2635 <1> ; (Note: Serial port interrupts will be disabled here...) 2636 <1> ; (INT 14h initialization code disables interrupts.) 2637 <1> ; 2638 00002B23 C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 2639 00002B26 E8BF000000 <1> call sp_i5 ; 29/06/2015 2640 <1> sp_i1: 2641 00002B2B 43 <1> inc ebx 2642 00002B2C 66BAF802 <1> mov dx, 2F8h ; COM2 2643 <1> ; 29/10/2015 2644 <1> ;mov cx, 301h ; divisor = 1 (115200 baud) 2645 <1> ; 08/01/2022 2646 00002B30 B101 <1> mov cl, 01h ; cx = 301h, divisor = 1 (115200 baud) 2647 00002B32 E829000000 <1> call sp_i3 ; call A4 2648 00002B37 A880 <1> test al, 80h 2649 00002B39 740E <1> jz short sp_i2 ; OK.. 2650 <1> ; Error ! 2651 <1> ;mov dx, 2F8h 2652 00002B3B 80EA05 <1> sub dl, 5 ; 2FDh -> 2F8h 2653 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 2654 <1> ; 08/01/2022 2655 00002B3E B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 2656 00002B40 E81B000000 <1> call sp_i3 ; call A4 2657 00002B45 A880 <1> test al, 80h 2658 00002B47 7516 <1> jnz short sp_i7 2659 <1> sp_i2: 2660 00002B49 C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 2661 <1> sp_i6: 2662 <1> ;; COM2 - enabling IRQ 3 2663 <1> ; 08/01/2022 2664 00002B4C B4F7 <1> mov ah, 0F7h ; enable IRQ 3 (COM2) 2665 <1> ; 07/11/2015 2666 <1> ; 26/10/2015 2667 <1> ;pushf 2668 <1> ;cli 2669 <1> ;; 2670 <1> ;;mov dx, 2FCh ; modem control register 2671 <1> ;mov dl, 0FCh ; 08/01/2022 2672 <1> ;in al, dx ; read register 2673 <1> ;JMP $+2 ; I/O DELAY 2674 <1> ;or al, 8 ; enable bit 3 (OUT2) 2675 <1> ;out dx, al ; write back to register 2676 <1> ;JMP $+2 ; I/O DELAY 2677 <1> ;;mov dx, 2F9h ; interrupt enable register 2678 <1> ;mov dl, 0F9h ; 08/01/2022 2679 <1> ;in al, dx ; read register 2680 <1> ;JMP $+2 ; I/O DELAY 2681 <1> ;;or al, 1 ; receiver data interrupt enable and 2682 <1> ;or al, 3 ; transmitter empty interrupt enable 2683 <1> ;out dx, al ; write back to register 2684 <1> ;JMP $+2 ; I/O DELAY 2685 <1> ;in al, 21h ; read interrupt mask register 2686 <1> ;JMP $+2 ; I/O DELAY 2687 <1> ;and al, 0F7h ; enable IRQ 3 (COM2) 2688 <1> ;out 21h, al ; write back to register 2689 <1> ; 2690 <1> ; 08/01/2022 2691 00002B4E 9C <1> pushf 2692 00002B4F E8AA000000 <1> call sp_i8 2693 <1> ; 23/10/2015 2694 00002B54 B8[332A0000] <1> mov eax, com2_int 2695 00002B59 A3[E42F0000] <1> mov [com2_irq3], eax 2696 <1> ; 26/10/2015 2697 00002B5E 9D <1> popf 2698 <1> sp_i7: 2699 00002B5F C3 <1> retn 2700 <1> 2701 <1> sp_i3: 2702 <1> ;A4: ;----- INITIALIZE THE COMMUNICATIONS PORT 2703 <1> ; 28/10/2015 2704 00002B60 FEC2 <1> inc dl ; 3F9h (2F9h) ; 3F9h, COM1 Interrupt enable register 2705 00002B62 B000 <1> mov al, 0 2706 00002B64 EE <1> out dx, al ; disable serial port interrupt 2707 00002B65 EB00 <1> JMP $+2 ; I/O DELAY 2708 00002B67 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; COM1 Line control register (3FBh) 2709 00002B6A B080 <1> mov al, 80h 2710 00002B6C EE <1> out dx, al ; SET DLAB=1 ; divisor latch access bit 2711 <1> ;----- SET BAUD RATE DIVISOR 2712 <1> ; 26/10/2015 2713 00002B6D 80EA03 <1> sub dl, 3 ; 3F8h (2F8h) ; register for least significant byte 2714 <1> ; of the divisor value 2715 00002B70 88C8 <1> mov al, cl ; 1 2716 00002B72 EE <1> out dx, al ; 1 = 115200 baud (Retro UNIX 386 v1) 2717 <1> ; 2 = 57600 baud 2718 <1> ; 3 = 38400 baud 2719 <1> ; 6 = 19200 baud 2720 <1> ; 12 = 9600 baud (Retro UNIX 8086 v1) 2721 00002B73 EB00 <1> JMP $+2 ; I/O DELAY 2722 00002B75 28C0 <1> sub al, al 2723 00002B77 FEC2 <1> inc dl ; 3F9h (2F9h) ; register for most significant byte 2724 <1> ; of the divisor value 2725 00002B79 EE <1> out dx, al ; 0 2726 00002B7A EB00 <1> JMP $+2 ; I/O DELAY 2727 <1> ; 2728 00002B7C 88E8 <1> mov al, ch ; 3 ; 8 data bits, 1 stop bit, no parity 2729 <1> ;and al, 1Fh ; Bits 0,1,2,3,4 2730 00002B7E 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; Line control register 2731 00002B81 EE <1> out dx, al 2732 00002B82 EB00 <1> JMP $+2 ; I/O DELAY 2733 <1> ; 29/10/2015 2734 00002B84 FECA <1> dec dl ; 3FAh (2FAh) ; FIFO Control register (16550/16750) 2735 00002B86 30C0 <1> xor al, al ; 0 2736 00002B88 EE <1> out dx, al ; Disable FIFOs (reset to 8250 mode) 2737 00002B89 EB00 <1> JMP $+2 2738 <1> sp_i4: 2739 <1> ;A18: ;----- COMM PORT STATUS ROUTINE 2740 <1> ; 29/06/2015 (line status after modem status) 2741 00002B8B 80C204 <1> add dl, 4 ; 3FEh (2FEh) ; Modem status register 2742 <1> sp_i4s: 2743 00002B8E EC <1> in al, dx ; GET MODEM CONTROL STATUS 2744 00002B8F EB00 <1> JMP $+2 ; I/O DELAY 2745 00002B91 88C4 <1> mov ah, al ; PUT IN (AH) FOR RETURN 2746 00002B93 FECA <1> dec dl ; 3FDh (2FDh) ; POINT TO LINE STATUS REGISTER 2747 <1> ; dx = 3FDh for COM1, 2FDh for COM2 2748 00002B95 EC <1> in al, dx ; GET LINE CONTROL STATUS 2749 <1> ; AL = Line status, AH = Modem status 2750 00002B96 C3 <1> retn 2751 <1> 2752 <1> sp_status: 2753 <1> ; 29/06/2015 2754 <1> ; 27/06/2015 (Retro UNIX 386 v1) 2755 <1> ; Get serial port status 2756 00002B97 66BAFE03 <1> mov dx, 3FEh ; Modem status register (COM1) 2757 00002B9B 28C6 <1> sub dh, al ; dh = 2 for COM2 (al = 1) 2758 <1> ; dx = 2FEh for COM2 2759 00002B9D EBEF <1> jmp short sp_i4s 2760 <1> 2761 <1> sp_setp: ; Set serial port communication parameters 2762 <1> ; 04/02/2022 2763 <1> ; (Retro UNIX 386 v1, Kernel v0.2.0.18) 2764 <1> ; 08/01/2022 2765 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2766 <1> ; 07/11/2015 2767 <1> ; 29/10/2015 2768 <1> ; 29/06/2015 2769 <1> ; Retro UNIX 386 v1 feature only ! 2770 <1> ; 2771 <1> ; INPUT: 2772 <1> ; AL = 0 for COM1 2773 <1> ; 1 for COM2 2774 <1> ; AH = Communication parameters (*) 2775 <1> ; OUTPUT: 2776 <1> ; CL = Line status 2777 <1> ; CH = Modem status 2778 <1> ; If cf = 1 -> Error code in [u.error] 2779 <1> ; 'invalid parameter !' 2780 <1> ; or 2781 <1> ; 'device not ready !' error 2782 <1> ; 2783 <1> ; (*) Communication parameters (except BAUD RATE): 2784 <1> ; Bit 4 3 2 1 0 2785 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 2786 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 2787 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 2788 <1> ; 11 = even 2789 <1> ; Baud rate setting bits: (29/06/2015) 2790 <1> ; Retro UNIX 386 v1 feature only ! 2791 <1> ; Bit 7 6 5 | Baud rate 2792 <1> ; ------------------------ 2793 <1> ; value 0 0 0 | Default (Divisor = 1) 2794 <1> ; 0 0 1 | 9600 (12) 2795 <1> ; 0 1 0 | 19200 (6) 2796 <1> ; 0 1 1 | 38400 (3) 2797 <1> ; 1 0 0 | 14400 (8) 2798 <1> ; 1 0 1 | 28800 (4) 2799 <1> ; 1 1 0 | 57600 (2) 2800 <1> ; 1 1 1 | 115200 (1) 2801 <1> ; 2802 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 2803 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 2804 <1> ; 2805 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 2806 <1> ; 2807 00002B9F 66BAF803 <1> mov dx, 3F8h 2808 00002BA3 BB[A2610000] <1> mov ebx, com1p ; COM1 control byte offset 2809 00002BA8 3C01 <1> cmp al, 1 2810 00002BAA 7770 <1> ja short sp_invp_err 2811 00002BAC 7203 <1> jb short sp_setp1 ; COM1 (AL = 0) 2812 00002BAE FECE <1> dec dh ; 2F8h 2813 00002BB0 43 <1> inc ebx ; COM2 control byte offset 2814 <1> sp_setp1: 2815 <1> ; 29/10/2015 2816 00002BB1 8823 <1> mov [ebx], ah 2817 00002BB3 0FB6CC <1> movzx ecx, ah 2818 00002BB6 C0E905 <1> shr cl, 5 ; -> baud rate index 2819 00002BB9 80E41F <1> and ah, 1Fh ; communication parameters except baud rate 2820 00002BBC 8A81[2B2C0000] <1> mov al, [ecx+b_div_tbl] 2821 00002BC2 6689C1 <1> mov cx, ax 2822 00002BC5 E896FFFFFF <1> call sp_i3 2823 00002BCA 6689C1 <1> mov cx, ax ; CL = Line status, CH = Modem status 2824 00002BCD A880 <1> test al, 80h 2825 00002BCF 740F <1> jz short sp_setp2 2826 00002BD1 C603E3 <1> mov byte [ebx], 0E3h ; Reset to initial value (11100011b) 2827 <1> stp_dnr_err: 2828 00002BD4 C705[4F650000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !' 2828 00002BDC 0000 <1> 2829 <1> ; CL = Line status, CH = Modem status 2830 00002BDE F9 <1> stc 2831 00002BDF C3 <1> retn 2832 <1> sp_setp2: 2833 00002BE0 80FE02 <1> cmp dh, 2 ; COM2 (2F?h) 2834 <1> ;jna sp_i6 2835 <1> ; COM1 (3F?h) 2836 <1> ; 24/12/2021 2837 00002BE3 7705 <1> ja short sp_i5 2838 00002BE5 E962FFFFFF <1> jmp sp_i6 2839 <1> sp_i5: 2840 <1> ; 08/01/2022 2841 00002BEA B4EF <1> mov ah, 0EFh ; enable IRQ 4 (COM1) 2842 <1> ; 07/11/2015 2843 <1> ; 26/10/2015 2844 <1> ; 29/06/2015 2845 <1> ; 2846 <1> ;; COM1 - enabling IRQ 4 2847 <1> ;pushf 2848 <1> ;cli 2849 <1> ;;mov dx, 3FCh ; modem control register 2850 <1> ;mov dl, 0FCh ; 08/01/2022 2851 <1> ;in al, dx ; read register 2852 <1> ;JMP $+2 ; I/O DELAY 2853 <1> ;or al, 8 ; enable bit 3 (OUT2) 2854 <1> ;out dx, al ; write back to register 2855 <1> ;JMP $+2 ; I/O DELAY 2856 <1> ;;mov dx, 3F9h ; interrupt enable register 2857 <1> ;mov dl, 0F9h ; 08/01/2022 2858 <1> ;in al, dx ; read register 2859 <1> ;JMP $+2 ; I/O DELAY 2860 <1> ;;or al, 1 ; receiver data interrupt enable and 2861 <1> ;or al, 3 ; transmitter empty interrupt enable 2862 <1> ;out dx, al ; write back to register 2863 <1> ;JMP $+2 ; I/O DELAY 2864 <1> ;in al, 21h ; read interrupt mask register 2865 <1> ;JMP $+2 ; I/O DELAY 2866 <1> ;and al, 0EFh ; enable IRQ 4 (COM1) 2867 <1> ;out 21h, al ; write back to register 2868 <1> ; 2869 <1> ; 08/01/2022 2870 00002BEC 9C <1> pushf 2871 00002BED E80C000000 <1> call sp_i8 2872 <1> ; 23/10/2015 2873 00002BF2 B8[3C2A0000] <1> mov eax, com1_int 2874 00002BF7 A3[E02F0000] <1> mov [com1_irq4], eax 2875 <1> ; 26/10/2015 2876 00002BFC 9D <1> popf 2877 00002BFD C3 <1> retn 2878 <1> 2879 <1> sp_i8: 2880 <1> ; 08/01/2022 2881 <1> ;pushf 2882 00002BFE FA <1> cli 2883 <1> ; 2884 <1> ;mov dx, 2FCh ; 3FCh ; modem control register 2885 00002BFF B2FC <1> mov dl, 0FCh 2886 00002C01 EC <1> in al, dx ; read register 2887 00002C02 EB00 <1> JMP $+2 ; I/O DELAY 2888 00002C04 0C08 <1> or al, 8 ; enable bit 3 (OUT2) 2889 00002C06 EE <1> out dx, al ; write back to register 2890 00002C07 EB00 <1> JMP $+2 ; I/O DELAY 2891 <1> ;mov dx, 2F9h ; 3F9h ; interrupt enable register 2892 00002C09 B2F9 <1> mov dl, 0F9h 2893 00002C0B EC <1> in al, dx ; read register 2894 00002C0C EB00 <1> JMP $+2 ; I/O DELAY 2895 <1> ;or al, 1 ; receiver data interrupt enable and 2896 00002C0E 0C03 <1> or al, 3 ; transmitter empty interrupt enable 2897 00002C10 EE <1> out dx, al ; write back to register 2898 00002C11 EB00 <1> JMP $+2 ; I/O DELAY 2899 00002C13 E421 <1> in al, 21h ; read interrupt mask register 2900 00002C15 EB00 <1> JMP $+2 ; I/O DELAY 2901 <1> ;and al, 0F7h ; 0EFh ; enable IRQ 3 (COM2) 2902 00002C17 20E0 <1> and al, ah ; 0F7h or 0EFh 2903 00002C19 E621 <1> out 21h, al ; write back to register 2904 <1> ; 2905 <1> ;popf 2906 00002C1B C3 <1> retn 2907 <1> 2908 <1> sp_invp_err: 2909 00002C1C C705[4F650000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 2909 00002C24 0000 <1> 2910 00002C26 31C9 <1> xor ecx, ecx 2911 00002C28 49 <1> dec ecx ; 0FFFFh 2912 00002C29 F9 <1> stc 2913 00002C2A C3 <1> retn 2914 <1> 2915 <1> ; 29/10/2015 2916 <1> b_div_tbl: ; Baud rate divisor table (115200/divisor) 2917 00002C2B 010C0603080401 <1> db 1, 12, 6, 3, 8, 4, 1 2918 <1> 2919 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 2920 <1> epoch: 2921 <1> ; 17/07/2022 2922 <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 2923 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2924 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 2925 <1> ; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM) 2926 <1> ; 'epoch' procedure prototype: 2927 <1> ; UNIXCOPY.ASM, 10/03/2013 2928 <1> ; 14/11/2012 2929 <1> ; unixboot.asm (boot file configuration) 2930 <1> ; version of "epoch" procedure in "unixproc.asm" 2931 <1> ; 21/7/2012 2932 <1> ; 15/7/2012 2933 <1> ; 14/7/2012 2934 <1> ; Erdogan Tan - RETRO UNIX v0.1 2935 <1> ; compute current date and time as UNIX Epoch/Time 2936 <1> ; UNIX Epoch: seconds since 1/1/1970 00:00:00 2937 <1> ; 2938 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 2939 <1> ; 2940 00002C32 E818010000 <1> call get_rtc_time ; Return Current Time 2941 00002C37 86E9 <1> xchg ch,cl 2942 00002C39 66890D[A65E0000] <1> mov [hour], cx 2943 00002C40 86F2 <1> xchg dh,dl 2944 00002C42 668915[A85E0000] <1> mov [second], dx 2945 <1> ; 2946 00002C49 E832010000 <1> call get_rtc_date ; Return Current Date 2947 00002C4E 86E9 <1> xchg ch,cl 2948 00002C50 66890D[A25E0000] <1> mov [year], cx 2949 00002C57 86F2 <1> xchg dh,dl 2950 00002C59 668915[A45E0000] <1> mov [month], dx 2951 <1> ; 2952 00002C60 66B93030 <1> mov cx, 3030h 2953 <1> ; 2954 00002C64 A0[A65E0000] <1> mov al, [hour] ; Hour 2955 <1> ; AL <= BCD number) 2956 00002C69 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2957 <1> ; AH = AL / 10h 2958 <1> ; AL = AL MOD 10h 2959 00002C6B D50A <1> aad ; AX= AH*10+AL 2960 00002C6D A2[A65E0000] <1> mov [hour], al 2961 00002C72 A0[A75E0000] <1> mov al, [hour+1] ; Minute 2962 <1> ; AL <= BCD number) 2963 00002C77 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2964 <1> ; AH = AL / 10h 2965 <1> ; AL = AL MOD 10h 2966 00002C79 D50A <1> aad ; AX= AH*10+AL 2967 00002C7B A2[A75E0000] <1> mov [minute], al 2968 00002C80 A0[A85E0000] <1> mov al, [second] ; Second 2969 <1> ; AL <= BCD number) 2970 00002C85 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2971 <1> ; AH = AL / 10h 2972 <1> ; AL = AL MOD 10h 2973 00002C87 D50A <1> aad ; AX= AH*10+AL 2974 00002C89 A2[A85E0000] <1> mov [second], al 2975 00002C8E 66A1[A25E0000] <1> mov ax, [year] ; Year (century) 2976 <1> ;push ax 2977 <1> ; 08/01/2022 2978 00002C94 50 <1> push eax 2979 <1> ; AL <= BCD number) 2980 00002C95 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2981 <1> ; AH = AL / 10h 2982 <1> ; AL = AL MOD 10h 2983 00002C97 D50A <1> aad ; AX= AH*10+AL 2984 00002C99 B464 <1> mov ah, 100 2985 00002C9B F6E4 <1> mul ah 2986 00002C9D 66A3[A25E0000] <1> mov [year], ax 2987 <1> ;pop ax 2988 <1> ; 08/01/2022 2989 00002CA3 58 <1> pop eax 2990 00002CA4 88E0 <1> mov al, ah 2991 <1> ; AL <= BCD number) 2992 00002CA6 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 2993 <1> ; AH = AL / 10h 2994 <1> ; AL = AL MOD 10h 2995 00002CA8 D50A <1> aad ; AX= AH*10+AL 2996 00002CAA 660105[A25E0000] <1> add [year], ax 2997 00002CB1 A0[A45E0000] <1> mov al, [month] ; Month 2998 <1> ; AL <= BCD number) 2999 00002CB6 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3000 <1> ; AH = AL / 10h 3001 <1> ; AL = AL MOD 10h 3002 00002CB8 D50A <1> aad ; AX= AH*10+AL 3003 00002CBA A2[A45E0000] <1> mov [month], al 3004 00002CBF A0[A55E0000] <1> mov al, [month+1] ; Day 3005 <1> ; AL <= BCD number) 3006 00002CC4 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3007 <1> ; AH = AL / 10h 3008 <1> ; AL = AL MOD 10h 3009 00002CC6 D50A <1> aad ; AX= AH*10+AL 3010 00002CC8 A2[A55E0000] <1> mov [day], al 3011 <1> 3012 <1> convert_to_epoch: 3013 <1> ; 17/07/2022 3014 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification) 3015 <1> ; 09/04/2013 (retro UNIX 8086 v1) 3016 <1> ; 3017 <1> ; ((Modified registers: EAX, EDX, EBX)) 3018 <1> ; 3019 <1> ; Derived from DALLAS Semiconductor 3020 <1> ; Application Note 31 (DS1602/DS1603) 3021 <1> ; 6 May 1998 3022 00002CCD 29C0 <1> sub eax, eax 3023 00002CCF 66A1[A25E0000] <1> mov ax, [year] 3024 00002CD5 662DB207 <1> sub ax, 1970 3025 00002CD9 BA6D010000 <1> mov edx, 365 3026 00002CDE F7E2 <1> mul edx 3027 00002CE0 31DB <1> xor ebx, ebx 3028 00002CE2 8A1D[A45E0000] <1> mov bl, [month] 3029 00002CE8 FECB <1> dec bl 3030 00002CEA D0E3 <1> shl bl, 1 3031 <1> ;sub edx, edx 3032 00002CEC 668B93[AA5E0000] <1> mov dx, [EBX+DMonth] 3033 00002CF3 8A1D[A55E0000] <1> mov bl, [day] 3034 00002CF9 FECB <1> dec bl 3035 00002CFB 01D0 <1> add eax, edx 3036 00002CFD 01D8 <1> add eax, ebx 3037 <1> ; EAX = days since 1/1/1970 3038 00002CFF 668B15[A25E0000] <1> mov dx, [year] 3039 00002D06 6681EAB107 <1> sub dx, 1969 3040 <1> ;shr dx, 1 3041 <1> ;shr dx, 1 3042 <1> ; 17/07/2022 3043 00002D0B C1EA02 <1> shr edx, 2 3044 <1> ; (year-1969)/4 3045 00002D0E 01D0 <1> add eax, edx 3046 <1> ; + leap days since 1/1/1970 3047 00002D10 803D[A45E0000]02 <1> cmp byte [month], 2 ; if past february 3048 00002D17 7610 <1> jna short cte1 3049 00002D19 668B15[A25E0000] <1> mov dx, [year] 3050 00002D20 6683E203 <1> and dx, 3 ; year mod 4 3051 00002D24 7503 <1> jnz short cte1 3052 <1> ; and if leap year 3053 00002D26 83C001 <1> add eax, 1 ; add this year's leap day (february 29) 3054 <1> cte1: ; compute seconds since 1/1/1970 3055 00002D29 BA18000000 <1> mov edx, 24 3056 00002D2E F7E2 <1> mul edx 3057 00002D30 8A15[A65E0000] <1> mov dl, [hour] 3058 00002D36 01D0 <1> add eax, edx 3059 <1> ; EAX = hours since 1/1/1970 00:00:00 3060 <1> ;mov ebx, 60 3061 00002D38 B33C <1> mov bl, 60 3062 00002D3A F7E3 <1> mul ebx 3063 00002D3C 8A15[A75E0000] <1> mov dl, [minute] 3064 00002D42 01D0 <1> add eax, edx 3065 <1> ; EAX = minutes since 1/1/1970 00:00:00 3066 <1> ;mov ebx, 60 3067 00002D44 F7E3 <1> mul ebx 3068 00002D46 8A15[A85E0000] <1> mov dl, [second] 3069 00002D4C 01D0 <1> add eax, edx 3070 <1> ; EAX -> seconds since 1/1/1970 00:00:00 3071 00002D4E C3 <1> retn 3072 <1> 3073 <1> get_rtc_time: 3074 <1> ; 15/03/2015 3075 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code : 3076 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES : 3077 <1> ; INT 1Ah : 3078 <1> ; (AH) = 02H READ THE REAL TIME CLOCK AND RETURN WITH, : 3079 <1> ; (CH) = HOURS IN BCD (00-23) : 3080 <1> ; (CL) = MINUTES IN BCD (00-59) : 3081 <1> ; (DH) = SECONDS IN BCD (00-59) : 3082 <1> ; (DL) = DAYLIGHT SAVINGS ENABLE (00-01). : 3083 <1> ; 3084 <1> RTC_20: ; GET RTC TIME 3085 00002D4F FA <1> cli 3086 00002D50 E8E4DDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3087 00002D55 7227 <1> JC short RTC_29 ; EXIT IF ERROR (CY= 1) 3088 <1> 3089 00002D57 B000 <1> MOV AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS 3090 00002D59 E8C3DDFFFF <1> CALL CMOS_READ ; GET SECONDS 3091 00002D5E 88C6 <1> MOV DH,AL ; SAVE 3092 00002D60 B00B <1> MOV AL,CMOS_REG_B ; ADDRESS ALARM REGISTER 3093 00002D62 E8BADDFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 3094 00002D67 2401 <1> AND AL,00000001B ; MASK FOR VALID DSE BIT 3095 00002D69 88C2 <1> MOV DL,AL ; SET [DL] TO ZERO FOR NO DSE BIT 3096 00002D6B B002 <1> MOV AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES 3097 00002D6D E8AFDDFFFF <1> CALL CMOS_READ ; GET MINUTES 3098 00002D72 88C1 <1> MOV CL,AL ; SAVE 3099 00002D74 B004 <1> MOV AL,CMOS_HOURS ; SET ADDRESS OF HOURS 3100 00002D76 E8A6DDFFFF <1> CALL CMOS_READ ; GET HOURS 3101 00002D7B 88C5 <1> MOV CH,AL ; SAVE 3102 00002D7D F8 <1> CLC ; SET CY= 0 3103 <1> RTC_29: 3104 00002D7E FB <1> sti 3105 00002D7F C3 <1> RETn ; RETURN WITH RESULT IN CARRY FLAG 3106 <1> 3107 <1> get_rtc_date: 3108 <1> ; 15/03/2015 3109 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code : 3110 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES : 3111 <1> ; INT 1Ah : 3112 <1> ; (AH) = 04H READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,: 3113 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 3114 <1> ; (CL) = YEAR IN BCD (00-99) : 3115 <1> ; (DH) = MONTH IN BCD (01-12) : 3116 <1> ; (DL) = DAY IN BCD (01-31). : 3117 <1> ; 3118 <1> RTC_40: ; GET RTC DATE 3119 00002D80 FA <1> cli 3120 00002D81 E8B3DDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3121 00002D86 7225 <1> JC short RTC_49 ; EXIT IF ERROR (CY= 1) 3122 <1> 3123 00002D88 B007 <1> MOV AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH 3124 00002D8A E892DDFFFF <1> CALL CMOS_READ ; READ DAY OF MONTH 3125 00002D8F 88C2 <1> MOV DL,AL ; SAVE 3126 00002D91 B008 <1> MOV AL,CMOS_MONTH ; ADDRESS MONTH 3127 00002D93 E889DDFFFF <1> CALL CMOS_READ ; READ MONTH 3128 00002D98 88C6 <1> MOV DH,AL ; SAVE 3129 00002D9A B009 <1> MOV AL,CMOS_YEAR ; ADDRESS YEAR 3130 00002D9C E880DDFFFF <1> CALL CMOS_READ ; READ YEAR 3131 00002DA1 88C1 <1> MOV CL,AL ; SAVE 3132 00002DA3 B032 <1> MOV AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION 3133 00002DA5 E877DDFFFF <1> CALL CMOS_READ ; GET CENTURY BYTE 3134 00002DAA 88C5 <1> MOV CH,AL ; SAVE 3135 00002DAC F8 <1> CLC ; SET CY=0 3136 <1> RTC_49: 3137 00002DAD FB <1> sti 3138 00002DAE C3 <1> RETn ; RETURN WITH RESULTS IN CARRY FLAG 3139 <1> 3140 <1> set_date_time: 3141 <1> convert_from_epoch: 3142 <1> ; 02/06/2022 3143 <1> ; 01/06/2022 (BugFix) 3144 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 3145 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 3146 <1> ; 'convert_from_epoch' procedure prototype: 3147 <1> ; UNIXCOPY.ASM, 10/03/2013 3148 <1> ; 3149 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 3150 <1> ; 3151 <1> ; Derived from DALLAS Semiconductor 3152 <1> ; Application Note 31 (DS1602/DS1603) 3153 <1> ; 6 May 1998 3154 <1> ; 3155 <1> ; INPUT: 3156 <1> ; EAX = Unix (Epoch) Time 3157 <1> ; 3158 00002DAF 31D2 <1> xor edx, edx 3159 <1> ; 02/06/2022 3160 00002DB1 31C9 <1> xor ecx, ecx 3161 00002DB3 31DB <1> xor ebx, ebx 3162 <1> ;mov ecx, 60 3163 00002DB5 B13C <1> mov cl, 60 3164 00002DB7 F7F1 <1> div ecx 3165 <1> ;mov [imin], eax ; whole minutes 3166 <1> ; since 1/1/1970 3167 <1> ;mov [second], dx ; leftover seconds 3168 00002DB9 8815[A85E0000] <1> mov [second], dl ; 02/06/2022 3169 00002DBF 29D2 <1> sub edx, edx 3170 00002DC1 F7F1 <1> div ecx 3171 <1> ;mov [ihrs], eax ; whole hours 3172 <1> ; ; since 1/1/1970 3173 <1> ;mov [minute], dx ; leftover minutes 3174 00002DC3 8815[A75E0000] <1> mov [minute], dl ; 02/06/2022 3175 00002DC9 31D2 <1> xor edx, edx 3176 <1> ;mov cx, 24 3177 00002DCB B118 <1> mov cl, 24 3178 00002DCD F7F1 <1> div ecx 3179 <1> ;mov [iday], ax ; whole days 3180 <1> ; since 1/1/1970 3181 <1> ;mov [hour], dx ; leftover hours 3182 00002DCF 8815[A65E0000] <1> mov [hour], dl ; 02/06/2022 3183 <1> 3184 00002DD5 05DB020000 <1> add eax, 365+366 ; whole day since 3185 <1> ; 1/1/1968 3186 <1> ;mov [iday], ax 3187 00002DDA 50 <1> push eax 3188 00002DDB 29D2 <1> sub edx, edx 3189 00002DDD B9B5050000 <1> mov ecx, (4*365)+1 ; 4 years = 1461 days 3190 00002DE2 F7F1 <1> div ecx 3191 00002DE4 59 <1> pop ecx 3192 <1> ;mov [lday], ax ; count of quadyrs (4 years) 3193 <1> ;push dx 3194 <1> ; 01/06/2022 3195 00002DE5 52 <1> push edx 3196 <1> ;mov [qday], dx ; days since quadyr began 3197 00002DE6 6683FA3C <1> cmp dx, 31+29 ; if past feb 29 then 3198 00002DEA F5 <1> cmc ; add this quadyr's leap day 3199 00002DEB 83D000 <1> adc eax, 0 ; to # of qadyrs (leap days) 3200 <1> ;mov [lday], ax ; since 1968 3201 <1> ;mov cx, [iday] 3202 00002DEE 91 <1> xchg ecx, eax ; ECX = lday, EAX = iday 3203 00002DEF 29C8 <1> sub eax, ecx ; iday - lday 3204 00002DF1 B96D010000 <1> mov ecx, 365 3205 00002DF6 31D2 <1> xor edx, edx 3206 <1> ; EAX = iday-lday, EDX = 0 3207 00002DF8 F7F1 <1> div ecx 3208 <1> ;mov [iyrs], ax ; whole years since 1968 3209 <1> ;jday = iday - (iyrs*365) - lday 3210 <1> ;mov [jday], dx ; days since 1/1 of current year 3211 <1> ;add eax, 1968 3212 00002DFA 6605B007 <1> add ax, 1968 ; compute year 3213 00002DFE 66A3[A25E0000] <1> mov [year], ax 3214 <1> ;mov cx, dx 3215 <1> ; 02/06/2022 3216 00002E04 89D1 <1> mov ecx, edx 3217 <1> ;mov dx, [qday] 3218 <1> ;pop dx 3219 <1> ; 01/06/2022 3220 00002E06 5A <1> pop edx 3221 00002E07 6681FA6D01 <1> cmp dx, 365 ; if qday <= 365 and qday >= 60 3222 00002E0C 7709 <1> ja short cfe1 ; jday = jday +1 3223 00002E0E 6683FA3C <1> cmp dx, 60 ; if past 2/29 and leap year then 3224 00002E12 F5 <1> cmc ; add a leap day to the # of whole 3225 00002E13 6683D100 <1> adc cx, 0 ; days since 1/1 of current year 3226 <1> cfe1: 3227 <1> ;mov [jday], cx 3228 <1> ;mov bx, 12 ; estimate month 3229 <1> ;sub ebx, ebx 3230 <1> ; 02/06/2022 3231 00002E17 B30C <1> mov bl, 12 3232 00002E19 66BA6E01 <1> mov dx, 366 ; mday, max. days since 1/1 is 365 3233 00002E1D 6683E003 <1> and ax, 11b ; year mod 4 (and dx, 3) 3234 <1> cfe2: ; Month calculation ; 0 to 11 (11 to 0) 3235 <1> ;cmp cx, dx ; mday = # of days passed from 1/1 3236 <1> ; 02/06/2022 3237 00002E21 39D1 <1> cmp ecx, edx 3238 00002E23 7319 <1> jnb short cfe3 3239 <1> ;dec bx ; month = month - 1 3240 00002E25 FECB <1> dec bl 3241 <1> ;shl bx, 1 3242 00002E27 D0E3 <1> shl bl, 1 3243 00002E29 668B93[AA5E0000] <1> mov dx, [ebx+DMonth] ; # elapsed days at 1st of month 3244 <1> ;shr bx, 1 ; bx = month - 1 (0 to 11) 3245 <1> ; 02/06/2022 3246 00002E30 D0EB <1> shr bl, 1 3247 00002E32 80FB01 <1> cmp bl, 1 3248 <1> ;cmp bx, 1 ; if month > 2 and year mod 4 = 0 3249 00002E35 76EA <1> jna short cfe2 ; then mday = mday + 1 3250 00002E37 08C0 <1> or al, al ; if past 2/29 and leap year then 3251 00002E39 75E6 <1> jnz short cfe2 ; add leap day (to mday) 3252 <1> ;inc dx ; mday = mday + 1 3253 00002E3B 42 <1> inc edx 3254 00002E3C EBE3 <1> jmp short cfe2 3255 <1> cfe3: 3256 <1> ;inc bx ; -> bx = month, 1 to 12 3257 <1> ; 02/06/2022 3258 00002E3E FEC3 <1> inc bl 3259 <1> ;mov [month], bx 3260 00002E40 881D[A45E0000] <1> mov [month], bl 3261 <1> ;sub cx, dx ; day = jday - mday + 1 3262 00002E46 29D1 <1> sub ecx, edx 3263 <1> ;inc cx 3264 00002E48 FEC1 <1> inc cl 3265 <1> ;mov [day], cx 3266 00002E4A 880D[A55E0000] <1> mov [day], cl ; 02/06/2022 3267 <1> 3268 <1> ; eax, ebx, ecx, edx is changed at return 3269 <1> ; output -> 3270 <1> ; [year], [month], [day], [hour], [minute], [second] 3271 <1> 3272 <1> ; 01/06/2022 (BugFix) 3273 <1> _set_date: 3274 00002E50 66A1[A25E0000] <1> mov ax, [year] 3275 00002E56 B520 <1> mov ch, 20h ; century (bcd) 3276 00002E58 662DD007 <1> sub ax, 2000 3277 00002E5C 7306 <1> jnc short set_date 3278 00002E5E B519 <1> mov ch, 19h ; century (bcd) 3279 00002E60 6683C064 <1> add ax, 100 3280 <1> ; 01/06/2022 3281 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 3282 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 3283 <1> set_date: 3284 <1> ;mov al, [year+1] 3285 <1> ;aam ; ah = al / 10, al = al mod 10 3286 <1> ;db 0D5h, 10h ; Undocumented inst. AAD 3287 <1> ; ; AL = AH * 10h + AL 3288 <1> ;mov ch, al ; century (BCD) 3289 <1> ;mov al, [year] 3290 <1> ; al = year (0-99) ; 01/06/2022 3291 00002E64 D40A <1> aam ; ah = al / 10, al = al mod 10 3292 00002E66 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3293 <1> ; AL = AH * 10h + AL 3294 00002E68 88C1 <1> mov cl, al ; year (BCD) 3295 00002E6A A0[A45E0000] <1> mov al, [month] 3296 00002E6F D40A <1> aam ; ah = al / 10, al = al mod 10 3297 00002E71 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3298 <1> ; AL = AH * 10h + AL 3299 00002E73 88C6 <1> mov dh, al ; month (BCD) 3300 00002E75 A0[A55E0000] <1> mov al, [day] 3301 00002E7A D40A <1> aam ; ah = al / 10, al = al mod 10 3302 00002E7C D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3303 <1> ; AL = AH * 10h + AL 3304 <1> ; 01/06/2022 (BugFix) 3305 00002E7E 88C2 <1> mov dl, al ; day (BCD) 3306 <1> 3307 <1> ; Set real-time clock date 3308 00002E80 E879000000 <1> call set_rtc_date 3309 <1> set_time: 3310 <1> ; Read real-time clock time 3311 <1> ; (get day light saving time bit status) 3312 00002E85 FA <1> cli 3313 00002E86 E8AEDCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3314 <1> ; cf = 1 -> al = 0 3315 00002E8B 7207 <1> jc short stime1 3316 00002E8D B00B <1> MOV AL,CMOS_REG_B ; ADDRESS ALARM REGISTER 3317 00002E8F E88DDCFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 3318 <1> stime1: 3319 00002E94 FB <1> sti 3320 00002E95 2401 <1> AND AL,00000001B ; MASK FOR VALID DSE BIT 3321 00002E97 88C2 <1> MOV DL,AL ; SET [DL] TO ZERO FOR NO DSE BIT 3322 <1> ; DL = 1 or 0 (day light saving time) 3323 <1> ; 3324 00002E99 A0[A65E0000] <1> mov al, [hour] 3325 00002E9E D40A <1> aam ; ah = al / 10, al = al mod 10 3326 00002EA0 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3327 <1> ; AL = AH * 10h + AL 3328 00002EA2 88C5 <1> mov ch, al ; hour (BCD) 3329 00002EA4 A0[A75E0000] <1> mov al, [minute] 3330 00002EA9 D40A <1> aam ; ah = al / 10, al = al mod 10 3331 00002EAB D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3332 <1> ; AL = AH * 10h + AL 3333 00002EAD 88C1 <1> mov cl, al ; minute (BCD) 3334 00002EAF A0[A85E0000] <1> mov al, [second] 3335 00002EB4 D40A <1> aam ; ah = al / 10, al = al mod 10 3336 00002EB6 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 3337 <1> ; AL = AH * 10h + AL 3338 00002EB8 88C6 <1> mov dh, al ; second (BCD) 3339 <1> 3340 <1> ; Set real-time clock time 3341 <1> ; call set_rtc_time 3342 <1> set_rtc_time: 3343 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) : 3344 <1> ; 15/03/2015 : 3345 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code : 3346 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES : 3347 <1> ; INT 1Ah : 3348 <1> ; (AH) = 03H SET THE REAL TIME CLOCK USING, : 3349 <1> ; (CH) = HOURS IN BCD (00-23) : 3350 <1> ; (CL) = MINUTES IN BCD (00-59) : 3351 <1> ; (DH) = SECONDS IN BCD (00-59) : 3352 <1> ; (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00. : 3353 <1> ; : 3354 <1> ; NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. : 3355 <1> ; (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN : 3356 <1> ; APRIL (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN : 3357 <1> ; OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME. : 3358 <1> ; : 3359 <1> RTC_30: ; SET RTC TIME 3360 00002EBA FA <1> cli 3361 00002EBB E879DCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3362 00002EC0 7305 <1> JNC short RTC_35 ; GO AROUND IF CLOCK OPERATING 3363 00002EC2 E886000000 <1> CALL RTC_STA ; ELSE TRY INITIALIZING CLOCK 3364 <1> RTC_35: 3365 00002EC7 88F4 <1> MOV AH,DH ; GET TIME BYTE - SECONDS 3366 00002EC9 B000 <1> MOV AL,CMOS_SECONDS ; ADDRESS SECONDS 3367 00002ECB E89D000000 <1> CALL CMOS_WRITE ; UPDATE SECONDS 3368 00002ED0 88CC <1> MOV AH,CL ; GET TIME BYTE - MINUTES 3369 00002ED2 B002 <1> MOV AL,CMOS_MINUTES ; ADDRESS MINUTES 3370 00002ED4 E894000000 <1> CALL CMOS_WRITE ; UPDATE MINUTES 3371 00002ED9 88EC <1> MOV AH,CH ; GET TIME BYTE - HOURS 3372 00002EDB B004 <1> MOV AL,CMOS_HOURS ; ADDRESS HOURS 3373 00002EDD E88B000000 <1> CALL CMOS_WRITE ; UPDATE ADDRESS 3374 <1> ;MOV AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER 3375 00002EE2 66B80B0B <1> MOV AX,257*CMOS_REG_B ; 3376 00002EE6 E836DCFFFF <1> CALL CMOS_READ ; READ CURRENT TIME 3377 00002EEB 2462 <1> AND AL,01100010B ; MASK FOR VALID BIT POSITIONS 3378 00002EED 0C02 <1> OR AL,00000010B ; TURN ON 24 HOUR MODE 3379 00002EEF 80E201 <1> AND DL,00000001B ; USE ONLY THE DSE BIT 3380 00002EF2 08D0 <1> OR AL,DL ; GET DAY LIGHT SAVINGS TIME BIT (OSE) 3381 00002EF4 86E0 <1> XCHG AH,AL ; PLACE IN WORK REGISTER AND GET ADDRESS 3382 00002EF6 E872000000 <1> CALL CMOS_WRITE ; SET NEW ALARM BITS 3383 00002EFB F8 <1> CLC ; SET CY= 0 3384 00002EFC FB <1> sti 3385 00002EFD C3 <1> RETn ; RETURN WITH CY= 0 3386 <1> 3387 <1> set_rtc_date: 3388 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) : 3389 <1> ; 15/03/2015 : 3390 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code : 3391 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES : 3392 <1> ; INT 1Ah : 3393 <1> ; (AH) = 05H SET THE DATE INTO THE REAL TIME CLOCK USING, : 3394 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 3395 <1> ; (CL) = YEAR IN BCD (00-99) : 3396 <1> ; (DH) = MONTH IN BCD (01-12) : 3397 <1> ; (DL) = DAY IN BCD (01-31). : 3398 <1> ; : 3399 <1> RTC_50: ; SET RTC DATE 3400 00002EFE FA <1> cli 3401 00002EFF E835DCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3402 00002F04 7305 <1> JNC short RTC_55 ; GO AROUND IF NO ERROR 3403 00002F06 E842000000 <1> CALL RTC_STA ; ELSE INITIALIZE CLOCK 3404 <1> RTC_55: 3405 00002F0B 66B80600 <1> MOV AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE 3406 00002F0F E859000000 <1> CALL CMOS_WRITE ; LOAD ZEROS TO DAY OF WEEK 3407 00002F14 88D4 <1> MOV AH,DL ; GET DAY OF MONTH BYTE 3408 00002F16 B007 <1> MOV AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE 3409 00002F18 E850000000 <1> CALL CMOS_WRITE ; WRITE OF DAY OF MONTH REGISTER 3410 00002F1D 88F4 <1> MOV AH,DH ; GET MONTH 3411 00002F1F B008 <1> MOV AL,CMOS_MONTH ; ADDRESS MONTH BYTE 3412 00002F21 E847000000 <1> CALL CMOS_WRITE ; WRITE MONTH REGISTER 3413 00002F26 88CC <1> MOV AH,CL ; GET YEAR BYTE 3414 00002F28 B009 <1> MOV AL,CMOS_YEAR ; ADDRESS YEAR REGISTER 3415 00002F2A E83E000000 <1> CALL CMOS_WRITE ; WRITE YEAR REGISTER 3416 00002F2F 88EC <1> MOV AH,CH ; GET CENTURY BYTE 3417 00002F31 B032 <1> MOV AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE 3418 00002F33 E835000000 <1> CALL CMOS_WRITE ; WRITE CENTURY LOCATION 3419 <1> ;MOV AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER 3420 00002F38 66B80B0B <1> MOV AX,257*CMOS_REG_B ; 3421 00002F3C E8E0DBFFFF <1> CALL CMOS_READ ; READ CURRENT SETTINGS 3422 00002F41 247F <1> AND AL,07FH ; CLEAR 'SET BIT' 3423 00002F43 86E0 <1> XCHG AH,AL ; MOVE TO WORK REGISTER 3424 00002F45 E823000000 <1> CALL CMOS_WRITE ; AND START CLOCK UPDATING 3425 00002F4A F8 <1> CLC ; SET CY= 0 3426 00002F4B FB <1> sti 3427 00002F4C C3 <1> RETn ; RETURN CY=0 3428 <1> 3429 <1> ; 15/03/2015 3430 <1> RTC_STA: ; INITIALIZE REAL TIME CLOCK 3431 00002F4D B426 <1> mov ah, 26h 3432 00002F4F B00A <1> mov al, CMOS_REG_A ; ADDRESS REGISTER A AND LOAD DATA MASK 3433 00002F51 E817000000 <1> CALL CMOS_WRITE ; INITIALIZE STATUS REGISTER A 3434 00002F56 B482 <1> mov ah, 82h 3435 00002F58 B00B <1> mov al, CMOS_REG_B ; SET "SET BIT" FOR CLOCK INITIALIZATION 3436 00002F5A E80E000000 <1> CALL CMOS_WRITE ; AND 24 HOUR MODE TO REGISTER B 3437 00002F5F B00C <1> MOV AL,CMOS_REG_C ; ADDRESS REGISTER C 3438 00002F61 E8BBDBFFFF <1> CALL CMOS_READ ; READ REGISTER C TO INITIALIZE 3439 00002F66 B00D <1> MOV AL,CMOS_REG_D ; ADDRESS REGISTER D 3440 <1> ;CALL CMOS_READ ; READ REGISTER D TO INITIALIZE 3441 <1> ;RETn 3442 <1> ; 12/02/2022 3443 00002F68 E9B4DBFFFF <1> jmp CMOS_READ 3444 <1> 3445 <1> ; 15/03/2015 3446 <1> ; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm) 3447 <1> CMOS_WRITE: ; WRITE (AH) TO LOCATION (AL) 3448 00002F6D 9C <1> pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 3449 <1> ;push ax ; SAVE WORK REGISTER VALUES 3450 00002F6E D0C0 <1> rol al, 1 ; MOVE NMI BIT TO LOW POSITION 3451 00002F70 F9 <1> stc ; FORCE NMI BIT ON IN CARRY FLAG 3452 00002F71 D0D8 <1> rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 3453 00002F73 FA <1> cli ; DISABLE INTERRUPTS 3454 00002F74 E670 <1> out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 3455 00002F76 88E0 <1> mov al, ah ; GET THE DATA BYTE TO WRITE 3456 00002F78 E671 <1> out CMOS_DATA, al ; PLACE IN REQUESTED CMOS LOCATION 3457 00002F7A B01E <1> mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 3458 00002F7C D0D8 <1> rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 3459 00002F7E E670 <1> out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 3460 00002F80 90 <1> nop ; I/O DELAY 3461 00002F81 E471 <1> in al, CMOS_DATA ; OPEN STANDBY LATCH 3462 <1> ;pop ax ; RESTORE WORK REGISTERS 3463 00002F83 9D <1> popf 3464 00002F84 C3 <1> RETn 3465 <1> 3466 <1> bf_init: 3467 <1> ; 14/08/2015 3468 <1> ; 02/07/2015 3469 <1> ; 01/07/2015 3470 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 3471 <1> ; Buffer (pointer) initialization ! 3472 <1> ; 3473 <1> ; 17/07/2013 - 24/07/2013 3474 <1> ; Retro UNIX 8086 v1 (U9.ASM) 3475 <1> ; (Retro UNIX 8086 v1 feature only !) 3476 <1> ; 3477 00002F85 BF[B8640000] <1> mov edi, bufp 3478 00002F8A B8[C0750000] <1> mov eax, buffer + (nbuf*520) 3479 00002F8F 29D2 <1> sub edx, edx 3480 00002F91 FECA <1> dec dl 3481 00002F93 31C9 <1> xor ecx, ecx 3482 00002F95 49 <1> dec ecx 3483 <1> bi0: 3484 00002F96 2D08020000 <1> sub eax, 520 ; 8 header + 512 data 3485 00002F9B AB <1> stosd 3486 00002F9C 89C6 <1> mov esi, eax 3487 00002F9E 8916 <1> mov [esi], edx ; 000000FFh 3488 <1> ; Not a valid device sign 3489 00002FA0 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 3490 <1> ; Not a valid block number sign 3491 00002FA3 3D[80650000] <1> cmp eax, buffer 3492 00002FA8 77EC <1> ja short bi0 3493 00002FAA B8[C0750000] <1> mov eax, sb0 3494 00002FAF AB <1> stosd 3495 00002FB0 B8[C8770000] <1> mov eax, sb1 3496 00002FB5 AB <1> stosd 3497 00002FB6 89C6 <1> mov esi, eax ; offset sb1 3498 00002FB8 8916 <1> mov [esi], edx ; 000000FFh 3499 <1> ; Not a valid device sign 3500 00002FBA 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 3501 <1> ; Not a valid block number sign 3502 <1> ; 14/08/2015 3503 <1> ;call rdev_init 3504 <1> ;retn 3505 <1> 3506 <1> rdev_init: ; root device, super block buffer initialization 3507 <1> ; 01/02/2022 3508 <1> ; 14/08/2015 3509 <1> ; Retro UNIX 386 v1 feature only ! 3510 <1> ; 3511 <1> ; NOTE: Disk partitions (file systems), logical 3512 <1> ; drive initialization, partition's start sector etc. 3513 <1> ; will be coded here, later in 'ldrv_init' 3514 <1> 3515 00002FBD 0FB605[585C0000] <1> movzx eax, byte [boot_drv] 3516 <1> rdi_0: 3517 00002FC4 3C80 <1> cmp al, 80h 3518 00002FC6 7202 <1> jb short rdi_1 3519 00002FC8 2C7E <1> sub al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1) 3520 <1> rdi_1: 3521 00002FCA A2[E6640000] <1> mov [rdev], al 3522 00002FCF BB[C0750000] <1> mov ebx, sb0 ; super block buffer 3523 00002FD4 8903 <1> mov [ebx], eax 3524 00002FD6 B001 <1> mov al, 1 ; eax = 1 3525 00002FD8 894304 <1> mov [ebx+4], eax ; super block address on disk 3526 <1> ;call diskio 3527 <1> ;retn 3528 <1> ; 01/02/2022 3529 00002FDB E91C250000 <1> jmp diskio 3530 <1> 3531 <1> ; 23/10/2015 3532 <1> com1_irq4: 3533 00002FE0 [E82F0000] <1> dd dummy_retn 3534 <1> com2_irq3: 3535 00002FE4 [E82F0000] <1> dd dummy_retn 3536 <1> 3537 <1> dummy_retn: 3538 00002FE8 C3 <1> retn 2052 %include 'u1.s' ; 10/05/2015 2053 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS1.INC 2054 <1> ; Last Modification: 17/07/2022 2055 <1> ; ---------------------------------------------------------------------------- 2056 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2057 <1> ; (v0.1 - Beginning: 11/07/2012) 2058 <1> ; 2059 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2060 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2061 <1> ; 2062 <1> ; 2063 <1> ; 2064 <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s 2065 <1> ; 2066 <1> ; **************************************************************************** 2067 <1> ; 23/11/2015 2068 <1> 2069 <1> unkni: ; / used for all system calls 2070 <1> sysent: ; < enter to system call > 2071 <1> ; 27/02/2022 2072 <1> ; 01/02/2022 2073 <1> ; 19/10/2015 2074 <1> ; 21/09/2015 2075 <1> ; 01/07/2015 2076 <1> ; 19/05/2015 2077 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2078 <1> ; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2079 <1> ; 2080 <1> ; 'unkni' or 'sysent' is sytem entry from various traps. 2081 <1> ; The trap type is determined and an indirect jump is made to 2082 <1> ; the appropriate system call handler. If there is a trap inside 2083 <1> ; the system a jump to panic is made. All user registers are saved 2084 <1> ; and u.sp points to the end of the users stack. The sys (trap) 2085 <1> ; instructor is decoded to get the the system code part (see 2086 <1> ; trap instruction in the PDP-11 handbook) and from this 2087 <1> ; the indirect jump address is calculated. If a bad system call is 2088 <1> ; made, i.e., the limits of the jump table are exceeded, 'badsys' 2089 <1> ; is called. If the call is legitimate control passes to the 2090 <1> ; appropriate system routine. 2091 <1> ; 2092 <1> ; Calling sequence: 2093 <1> ; Through a trap caused by any sys call outside the system. 2094 <1> ; Arguments: 2095 <1> ; Arguments of particular system call. 2096 <1> ; ............................................................... 2097 <1> ; 2098 <1> ; Retro UNIX 8086 v1 modification: 2099 <1> ; System call number is in EAX register. 2100 <1> ; 2101 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 2102 <1> ; registers depending of function details. 2103 <1> ; 2104 <1> ; 16/04/2015 2105 00002FE9 368925[F8640000] <1> mov [ss:u.sp], esp ; Kernel stack points to return address 2106 <1> ; save user registers 2107 00002FF0 1E <1> push ds 2108 00002FF1 06 <1> push es 2109 00002FF2 0FA0 <1> push fs 2110 00002FF4 0FA8 <1> push gs 2111 00002FF6 60 <1> pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 2112 <1> ; 2113 <1> ; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015 2114 <1> ; (ESPACE is size of space in kernel stack 2115 <1> ; for saving/restoring user registers.) 2116 <1> ; 2117 00002FF7 50 <1> push eax ; 01/07/2015 2118 00002FF8 66B81000 <1> mov ax, KDATA 2119 00002FFC 8ED8 <1> mov ds, ax 2120 00002FFE 8EC0 <1> mov es, ax 2121 00003000 8EE0 <1> mov fs, ax 2122 00003002 8EE8 <1> mov gs, ax 2123 00003004 A1[38610000] <1> mov eax, [k_page_dir] 2124 00003009 0F22D8 <1> mov cr3, eax 2125 0000300C 58 <1> pop eax ; 01/07/2015 2126 <1> ; 19/10/2015 2127 0000300D FC <1> cld 2128 <1> ; 2129 0000300E FE05[F5640000] <1> inc byte [sysflg] 2130 <1> ; incb sysflg / indicate a system routine is in progress 2131 00003014 FB <1> sti ; 18/01/2014 2132 <1> ;jnz panic ; 24/05/2013 2133 <1> ; beq 1f 2134 <1> ; jmp panic ; / called if trap inside system 2135 <1> ; 01/02/2022 2136 00003015 7405 <1> jz short sysent_1 2137 00003017 E987F9FFFF <1> jmp panic 2138 <1> sysent_1: 2139 <1> ;1: ; 16/04/2015 2140 0000301C A3[00650000] <1> mov [u.r0], eax 2141 00003021 8925[FC640000] <1> mov [u.usp], esp ; kernel stack points to user's registers 2142 <1> ; 2143 <1> ; mov $s.syst+2,clockp 2144 <1> ; mov r0,-(sp) / save user registers 2145 <1> ; mov sp,u.r0 / pointer to bottom of users stack 2146 <1> ; / in u.r0 2147 <1> ; mov r1,-(sp) 2148 <1> ; mov r2,-(sp) 2149 <1> ; mov r3,-(sp) 2150 <1> ; mov r4,-(sp) 2151 <1> ; mov r5,-(sp) 2152 <1> ; mov ac,-(sp) / "accumulator" register for extended 2153 <1> ; / arithmetic unit 2154 <1> ; mov mq,-(sp) / "multiplier quotient" register for the 2155 <1> ; / extended arithmetic unit 2156 <1> ; mov sc,-(sp) / "step count" register for the extended 2157 <1> ; / arithmetic unit 2158 <1> ; mov sp,u.sp / u.sp points to top of users stack 2159 <1> ; mov 18.(sp),r0 / store pc in r0 2160 <1> ; mov -(r0),r0 / sys inst in r0 10400xxx 2161 <1> ; sub $sys,r0 / get xxx code 2162 00003027 C1E002 <1> shl eax, 2 2163 <1> ; asl r0 / multiply by 2 to jump indirect in bytes 2164 0000302A 3D94000000 <1> cmp eax, end_of_syscalls - syscalls 2165 <1> ; cmp r0,$2f-1f / limit of table (35) exceeded 2166 <1> ;jnb short badsys 2167 <1> ; bhis badsys / yes, bad system call 2168 <1> ; 27/02/2022 2169 0000302F 7205 <1> jb short _2 2170 00003031 E954010000 <1> jmp badsys 2171 <1> _2: 2172 <1> ; 27/02/2022 2173 <1> ;cmc 2174 <1> ;pushf 2175 <1> ;push eax 2176 00003036 8B2D[F8640000] <1> mov ebp, [u.sp] ; Kernel stack at the beginning of sys call 2177 <1> ;mov al, 0FEh ; 11111110b 2178 <1> ;;adc al, 0 ; al = al + cf 2179 <1> ;and [ebp+8], al ; flags (reset carry flag) 2180 0000303C 806508FE <1> and byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021 2181 <1> ; bic $341,20.(sp) / set users processor priority to 0 2182 <1> ; / and clear carry bit 2183 <1> ;pop ebp ; eax 2184 00003040 89C5 <1> mov ebp, eax 2185 <1> ;popf 2186 <1> ;;jc badsys 2187 <1> ; 27/02/2022 2188 <1> ;jnc short _3 2189 <1> ;jmp badsys 2190 <1> ;_3: 2191 00003042 A1[00650000] <1> mov eax, [u.r0] 2192 <1> ; system call registers: EAX, EDX, ECX, EBX, ESI, EDI 2193 00003047 FFA5[4D300000] <1> jmp dword [ebp+syscalls] 2194 <1> ; jmp *1f(r0) / jump indirect thru table of addresses 2195 <1> ; / to proper system routine. 2196 <1> syscalls: ; 1: 2197 <1> ; 21/09/2015 2198 <1> ; 01/07/2015 2199 <1> ; 16/04/2015 (32 bit address modification) 2200 0000304D [54310000] <1> dd sysrele ; / 0 2201 00003051 [FC310000] <1> dd sysexit ; / 1 2202 00003055 [26330000] <1> dd sysfork ; / 2 2203 00003059 [2C340000] <1> dd sysread ; / 3 2204 0000305D [3F340000] <1> dd syswrite ; / 4 2205 00003061 [A8340000] <1> dd sysopen ; / 5 2206 00003065 [D7350000] <1> dd sysclose ; / 6 2207 00003069 [A1320000] <1> dd syswait ; / 7 2208 0000306D [54350000] <1> dd syscreat ; / 8 2209 00003071 [89390000] <1> dd syslink ; / 9 2210 00003075 [453A0000] <1> dd sysunlink ; / 10 2211 00003079 [0C3B0000] <1> dd sysexec ; / 11 2212 0000307D [95410000] <1> dd syschdir ; / 12 2213 00003081 [7A420000] <1> dd systime ; / 13 2214 00003085 [90350000] <1> dd sysmkdir ; / 14 2215 00003089 [E7410000] <1> dd syschmod ; / 15 2216 0000308D [4A420000] <1> dd syschown ; / 16 2217 00003091 [AD420000] <1> dd sysbreak ; / 17 2218 00003095 [CD3E0000] <1> dd sysstat ; / 18 2219 00003099 [7D430000] <1> dd sysseek ; / 19 2220 0000309D [8F430000] <1> dd systell ; / 20 2221 000030A1 [CD4E0000] <1> dd sysmount ; / 21 2222 000030A5 [B84F0000] <1> dd sysumount ; / 22 2223 000030A9 [0B440000] <1> dd syssetuid ; / 23 2224 000030AD [3C440000] <1> dd sysgetuid ; / 24 2225 000030B1 [89420000] <1> dd sysstime ; / 25 2226 000030B5 [FF430000] <1> dd sysquit ; / 26 2227 000030B9 [F3430000] <1> dd sysintr ; / 27 2228 000030BD [AA3E0000] <1> dd sysfstat ; / 28 2229 000030C1 [EF350000] <1> dd sysemt ; / 29 2230 000030C5 [37360000] <1> dd sysmdate ; / 30 2231 000030C9 [91360000] <1> dd sysstty ; / 31 2232 000030CD [7C380000] <1> dd sysgtty ; / 32 2233 000030D1 [32360000] <1> dd sysilgins ; / 33 2234 000030D5 [1E570000] <1> dd syssleep ; 34 ; Retro UNIX 8086 v1 feature only ! 2235 <1> ; 11/06/2014 2236 000030D9 [35570000] <1> dd sysmsg ; 35 ; Retro UNIX 386 v1 feature only ! 2237 <1> ; 01/07/2015 2238 000030DD [0D580000] <1> dd sysgeterr ; 36 ; Retro UNIX 386 v1 feature only ! 2239 <1> ; 21/09/2015 - get last error number 2240 <1> end_of_syscalls: 2241 <1> 2242 <1> error: 2243 <1> ; 17/09/2015 2244 <1> ; 03/09/2015 2245 <1> ; 01/09/2015 2246 <1> ; 09/06/2015 2247 <1> ; 13/05/2015 2248 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2249 <1> ; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 2250 <1> ; 2251 <1> ; 'error' merely sets the error bit off the processor status (c-bit) 2252 <1> ; then falls right into the 'sysret', 'sysrele' return sequence. 2253 <1> ; 2254 <1> ; INPUTS -> none 2255 <1> ; OUTPUTS -> 2256 <1> ; processor status - carry (c) bit is set (means error) 2257 <1> ; 2258 <1> ; 26/05/2013 (Stack pointer must be reset here! 2259 <1> ; Because, jumps to error procedure 2260 <1> ; disrupts push-pop nesting balance) 2261 <1> ; 2262 000030E1 8B2D[F8640000] <1> mov ebp, [u.sp] ; interrupt (system call) return (iretd) address 2263 000030E7 804D0801 <1> or byte [ebp+8], 1 ; set carry bit of flags register 2264 <1> ; (system call will return with cf = 1) 2265 <1> ; bis $1,20.(r1) / set c bit in processor status word below 2266 <1> ; / users stack 2267 <1> ; 17/09/2015 2268 000030EB 83ED30 <1> sub ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc') 2269 <1> ; for saving/restoring user registers 2270 <1> ;cmp ebp, [u.usp] 2271 <1> ;je short err0 2272 000030EE 892D[FC640000] <1> mov [u.usp], ebp 2273 <1> ;err0: 2274 <1> ; 01/09/2015 2275 000030F4 8B25[FC640000] <1> mov esp, [u.usp] ; Retro Unix 8086 v1 modification! 2276 <1> ; 10/04/2013 2277 <1> ; (If an I/O error occurs during disk I/O, 2278 <1> ; related procedures will jump to 'error' 2279 <1> ; procedure directly without returning to 2280 <1> ; the caller procedure. So, stack pointer 2281 <1> ; must be restored here.) 2282 <1> ; 13/05/2015 2283 <1> ; NOTE: (The last) error code is in 'u.error', it can be retrieved by 2284 <1> ; 'get last error' system call later. 2285 <1> 2286 <1> ; 03/09/2015 - 09/06/2015 - 07/08/2013 2287 000030FA C605[61650000]00 <1> mov byte [u.kcall], 0 ; namei_r, mkdir_w reset 2288 <1> 2289 <1> sysret: ; < return from system call> 2290 <1> ; 01/02/2022 2291 <1> ; 10/09/2015 2292 <1> ; 29/07/2015 2293 <1> ; 25/06/2015 2294 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2295 <1> ; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 2296 <1> ; 2297 <1> ; 'sysret' first checks to see if process is about to be 2298 <1> ; terminated (u.bsys). If it is, 'sysexit' is called. 2299 <1> ; If not, following happens: 2300 <1> ; 1) The user's stack pointer is restored. 2301 <1> ; 2) r1=0 and 'iget' is called to see if last mentioned 2302 <1> ; i-node has been modified. If it has, it is written out 2303 <1> ; via 'ppoke'. 2304 <1> ; 3) If the super block has been modified, it is written out 2305 <1> ; via 'ppoke'. 2306 <1> ; 4) If the dismountable file system's super block has been 2307 <1> ; modified, it is written out to the specified device 2308 <1> ; via 'ppoke'. 2309 <1> ; 5) A check is made if user's time quantum (uquant) ran out 2310 <1> ; during his execution. If so, 'tswap' is called to give 2311 <1> ; another user a chance to run. 2312 <1> ; 6) 'sysret' now goes into 'sysrele'. 2313 <1> ; (See 'sysrele' for conclusion.) 2314 <1> ; 2315 <1> ; Calling sequence: 2316 <1> ; jump table or 'br sysret' 2317 <1> ; Arguments: 2318 <1> ; - 2319 <1> ; ............................................................... 2320 <1> ; 2321 <1> ; ((AX=r1 for 'iget' input)) 2322 <1> ; 2323 <1> ;xor ax, ax ; 04/05/2013 2324 <1> ; 01/02/2022 2325 00003101 31C0 <1> xor eax, eax 2326 <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec) 2327 00003103 FEC0 <1> inc al ; 04/05/2013 2328 00003105 3805[48650000] <1> cmp [u.bsys], al ; 1 2329 <1> ; tstb u.bsys / is a process about to be terminated because 2330 <1> ;jnb sysexit ; 04/05/2013 2331 <1> ; bne sysexit / of an error? yes, go to sysexit 2332 <1> ; 01/02/2022 2333 0000310B 7205 <1> jb short sysret_2 2334 0000310D E9EA000000 <1> jmp sysexit 2335 <1> sysret_2: 2336 <1> ;mov esp, [u.usp] ; 24/05/2013 (that is not needed here) 2337 <1> ; mov u.sp,sp / no point stack to users stack 2338 00003112 FEC8 <1> dec al ; mov ax, 0 2339 <1> ; clr r1 / zero r1 to check last mentioned i-node 2340 00003114 E8DD160000 <1> call iget 2341 <1> ; jsr r0,iget / if last mentioned i-node has been modified 2342 <1> ; / it is written out 2343 00003119 6631C0 <1> xor ax, ax ; 0 2344 0000311C 3805[F3640000] <1> cmp [smod], al ; 0 2345 <1> ; tstb smod / has the super block been modified 2346 00003122 7614 <1> jna short sysret1 2347 <1> ; beq 1f / no, 1f 2348 00003124 A2[F3640000] <1> mov [smod], al ; 0 2349 <1> ; clrb smod / yes, clear smod 2350 00003129 BB[C0750000] <1> mov ebx, sb0 ;; 07/08//2013 2351 0000312E 66810B0002 <1> or word [ebx], 200h ;; 2352 <1> ;or word [sb0], 200h ; write bit, bit 9 2353 <1> ; bis $1000,sb0 / set write bit in I/O queue for super block 2354 <1> ; / output 2355 <1> ; AX = 0 2356 00003133 E828230000 <1> call poke ; 07/08/2013 2357 <1> ;call ppoke 2358 <1> ; AX = 0 2359 <1> ; jsr r0,ppoke / write out modified super block to disk 2360 <1> sysret1: ;1: 2361 00003138 3805[F4640000] <1> cmp [mmod], al ; 0 2362 <1> ; tstb mmod / has the super block for the dismountable file 2363 <1> ; / system 2364 0000313E 7614 <1> jna short sysrel0 2365 <1> ; beq 1f / been modified? no, 1f 2366 00003140 A2[F4640000] <1> mov [mmod], al ; 0 2367 <1> ; clrb mmod / yes, clear mmod 2368 <1> ;mov ax, [mntd] 2369 <1> ;;mov al, [mdev] ; 26/04/2013 2370 00003145 BB[C8770000] <1> mov ebx, sb1 ;; 07/08//2013 2371 <1> ;;mov [ebx], al 2372 <1> ;mov [sb1], al 2373 <1> ; movb mntd,sb1 / set the I/O queue 2374 0000314A 66810B0002 <1> or word [ebx], 200h 2375 <1> ;or word [sb1], 200h ; write bit, bit 9 2376 <1> ; bis $1000,sb1 / set write bit in I/O queue for detached sb 2377 0000314F E80C230000 <1> call poke ; 07/08/2013 2378 <1> ;call ppoke 2379 <1> ; jsr r0,ppoke / write it out to its device 2380 <1> ;xor al, al ; 26/04/2013 2381 <1> ;1: 2382 <1> ; tstb uquant / is the time quantum 0? 2383 <1> ; bne 1f / no, don't swap it out 2384 <1> 2385 <1> sysrele: ; < release > 2386 <1> ; 14/10/2015 2387 <1> ; 01/09/2015 2388 <1> ; 24/07/2015 2389 <1> ; 14/05/2015 2390 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2391 <1> ; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1) 2392 <1> ; 2393 <1> ; 'sysrele' first calls 'tswap' if the time quantum for a user is 2394 <1> ; zero (see 'sysret'). It then restores the user's registers and 2395 <1> ; turns off the system flag. It then checked to see if there is 2396 <1> ; an interrupt from the user by calling 'isintr'. If there is, 2397 <1> ; the output gets flashed (see isintr) and interrupt action is 2398 <1> ; taken by a branch to 'intract'. If there is no interrupt from 2399 <1> ; the user, a rti is made. 2400 <1> ; 2401 <1> ; Calling sequence: 2402 <1> ; Fall through a 'bne' in 'sysret' & ? 2403 <1> ; Arguments: 2404 <1> ; - 2405 <1> ; ............................................................... 2406 <1> ; 2407 <1> ; 23/02/2014 (swapret) 2408 <1> ; 22/09/2013 2409 <1> sysrel0: ;1: 2410 00003154 803D[3C650000]00 <1> cmp byte [u.quant], 0 ; 16/05/2013 2411 <1> ; tstb uquant / is the time quantum 0? 2412 0000315B 7705 <1> ja short swapret 2413 <1> ; bne 1f / no, don't swap it out 2414 <1> sysrelease: ; 07/12/2013 (jump from 'clock') 2415 0000315D E82A130000 <1> call tswap 2416 <1> ; jsr r0,tswap / yes, swap it out 2417 <1> ; 2418 <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address. 2419 <1> swapret: ;1: 2420 <1> ; 10/09/2015 2421 <1> ; 01/09/2015 2422 <1> ; 14/05/2015 2423 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications) 2424 <1> ; 26/05/2013 (Retro UNIX 8086 v1) 2425 <1> ; cli 2426 <1> ; 24/07/2015 2427 <1> ; 2428 <1> ;; 'esp' must be already equal to '[u.usp]' here ! 2429 <1> ;; mov esp, [u.usp] 2430 <1> 2431 <1> ; 22/09/2013 2432 00003162 E8FC140000 <1> call isintr 2433 <1> ; 20/10/2013 2434 00003167 7405 <1> jz short sysrel1 2435 00003169 E877000000 <1> call intract 2436 <1> ; jsr r0,isintr / is there an interrupt from the user 2437 <1> ; br intract / yes, output gets flushed, take interrupt 2438 <1> ; / action 2439 <1> sysrel1: 2440 0000316E FA <1> cli ; 14/10/2015 2441 0000316F FE0D[F5640000] <1> dec byte [sysflg] 2442 <1> ; decb sysflg / turn system flag off 2443 00003175 A1[53650000] <1> mov eax, [u.pgdir] 2444 0000317A 0F22D8 <1> mov cr3, eax ; 1st PDE points to Kernel Page Table 0 (1st 4 MB) 2445 <1> ; (others are different than kernel page tables) 2446 <1> ; 10/09/2015 2447 0000317D 61 <1> popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 2448 <1> ; mov (sp)+,sc / restore user registers 2449 <1> ; mov (sp)+,mq 2450 <1> ; mov (sp)+,ac 2451 <1> ; mov (sp)+,r5 2452 <1> ; mov (sp)+,r4 2453 <1> ; mov (sp)+,r3 2454 <1> ; mov (sp)+,r2 2455 <1> ; 2456 0000317E A1[00650000] <1> mov eax, [u.r0] ; ((return value in EAX)) 2457 00003183 0FA9 <1> pop gs 2458 00003185 0FA1 <1> pop fs 2459 00003187 07 <1> pop es 2460 00003188 1F <1> pop ds 2461 00003189 CF <1> iretd 2462 <1> ; rti / no, return from interrupt 2463 <1> 2464 <1> badsys: 2465 <1> ; 27/02/2022 2466 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2467 <1> ; (Major Modification: 'core' dumping procedure in 2468 <1> ; original UNIX v1 and Retro UNIX 8086 v1 2469 <1> ; has been changed to print 'Invalid System Call !' 2470 <1> ; message on the user's console tty.) 2471 <1> ; (EIP, EAX values will be shown on screen with error message) 2472 <1> ; (EIP = Return address just after the system call -INT 30h-) 2473 <1> ; (EAX = Function number) 2474 <1> ; 2475 0000318A FE05[48650000] <1> inc byte [u.bsys] 2476 <1> ; 2477 00003190 8B1D[F8640000] <1> mov ebx, [u.sp] ; esp at the beginning of 'sysent' 2478 00003196 8B03 <1> mov eax, [ebx] ; EIP (return address, not 'INT 30h' address) 2479 00003198 E846E4FFFF <1> call dwordtohex 2480 0000319D 8915[965E0000] <1> mov [bsys_msg_eip], edx 2481 000031A3 A3[9A5E0000] <1> mov [bsys_msg_eip+4], eax 2482 000031A8 A1[00650000] <1> mov eax, [u.r0] 2483 000031AD E831E4FFFF <1> call dwordtohex 2484 000031B2 8915[865E0000] <1> mov [bsys_msg_eax], edx 2485 000031B8 A3[8A5E0000] <1> mov [bsys_msg_eax+4], eax 2486 <1> ; 27/02/2022 2487 <1> ;xor eax, eax 2488 <1> ;mov dword [u.base], badsys_msg ; "Invalid System Call !" 2489 <1> ;mov ebx, [u.fofp] 2490 <1> ;mov [ebx], eax 2491 <1> ;;mov eax, 1 ; inode number of console tty (for user) 2492 <1> ;inc eax 2493 <1> ;mov dword [u.count], BSYS_M_SIZE 2494 <1> ; writei 2495 <1> ; INPUTS -> 2496 <1> ; r1 - inode number 2497 <1> ; u.count - byte count to be written 2498 <1> ; u.base - points to user buffer 2499 <1> ; u.fofp - points to word with current file offset 2500 <1> ; OUTPUTS -> 2501 <1> ; u.count - cleared 2502 <1> ; u.nread - accumulates total bytes passed back 2503 <1> ; 2504 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 2505 <1> ;call writei 2506 <1> ;;mov eax, 1 2507 <1> ;jmp sysexit 2508 <1> 2509 <1> ; 27/02/2022 2510 000031BD BE[675E0000] <1> mov esi, badsys_msg ; "Invalid System Call !" 2511 000031C2 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 2512 000031C9 8A83[53620000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2513 000031CF C605[67610000]0F <1> mov byte [ccolor], 0Fh ; white (message) color 2514 000031D6 A2[4E650000] <1> mov [u.ttyn], al ; current (active) tty (for user) 2515 000031DB E812260000 <1> call print_cmsg 2516 <1> ;mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 2517 000031E0 E9FCFEFFFF <1> jmp error 2518 <1> 2519 <1> ; incb u.bsys / turn on the user's bad-system flag 2520 <1> ; mov $3f,u.namep / point u.namep to "core\0\0" 2521 <1> ; jsr r0,namei / get the i-number for the core image file 2522 <1> ; br 1f / error 2523 <1> ; neg r1 / negate the i-number to open the core image file 2524 <1> ; / for writing 2525 <1> ; jsr r0,iopen / open the core image file 2526 <1> ; jsr r0,itrunc / free all associated blocks 2527 <1> ; br 2f 2528 <1> ;1: 2529 <1> ; mov $17,r1 / put i-node mode (17) in r1 2530 <1> ; jsr r0,maknod / make an i-node 2531 <1> ; mov u.dirbuf,r1 / put i-node number in r1 2532 <1> ;2: 2533 <1> ; mov $core,u.base / move address core to u.base 2534 <1> ; mov $ecore-core,u.count / put the byte count in u.count 2535 <1> ; mov $u.off,u.fofp / more user offset to u.fofp 2536 <1> ; clr u.off / clear user offset 2537 <1> ; jsr r0,writei / write out the core image to the user 2538 <1> ; mov $user,u.base / pt. u.base to user 2539 <1> ; mov $64.,u.count / u.count = 64 2540 <1> ; jsr r0,writei / write out all the user parameters 2541 <1> ; neg r1 / make i-number positive 2542 <1> ; jsr r0,iclose / close the core image file 2543 <1> ; br sysexit / 2544 <1> ;3: 2545 <1> ; 2546 <1> 2547 <1> intract: ; / interrupt action 2548 <1> ; 14/10/2015 2549 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2550 <1> ; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1) 2551 <1> ; 2552 <1> ; Retro UNIX 8086 v1 modification ! 2553 <1> ; (Process/task switching and quit routine by using 2554 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2555 <1> ; 2556 <1> ; input -> 'u.quit' (also value of 'u.intr' > 0) 2557 <1> ; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign) 2558 <1> ; 'intract' will jump to 'sysexit'. 2559 <1> ; Intract will return to the caller 2560 <1> ; if value of 'u.quit' <> FFFFh. 2561 <1> ; 14/10/2015 2562 000031E5 FB <1> sti 2563 <1> ; 07/12/2013 2564 000031E6 66FF05[40650000] <1> inc word [u.quit] 2565 000031ED 7408 <1> jz short intrct0 ; FFFFh -> 0 2566 000031EF 66FF0D[40650000] <1> dec word [u.quit] 2567 <1> ; 16/04/2015 2568 000031F6 C3 <1> retn 2569 <1> intrct0: 2570 000031F7 58 <1> pop eax ; call intract -> retn 2571 <1> ; 2572 000031F8 31C0 <1> xor eax, eax 2573 000031FA FEC0 <1> inc al ; mov ax, 1 2574 <1> ;;; 2575 <1> ; UNIX v1 original 'intract' routine... 2576 <1> ; / interrupt action 2577 <1> ;cmp *(sp),$rti / are you in a clock interrupt? 2578 <1> ; bne 1f / no, 1f 2579 <1> ; cmp (sp)+,(sp)+ / pop clock pointer 2580 <1> ; 1: / now in user area 2581 <1> ; mov r1,-(sp) / save r1 2582 <1> ; mov u.ttyp,r1 2583 <1> ; / pointer to tty buffer in control-to r1 2584 <1> ; cmpb 6(r1),$177 2585 <1> ; / is the interrupt char equal to "del" 2586 <1> ; beq 1f / yes, 1f 2587 <1> ; clrb 6(r1) 2588 <1> ; / no, clear the byte 2589 <1> ; / (must be a quit character) 2590 <1> ; mov (sp)+,r1 / restore r1 2591 <1> ; clr u.quit / clear quit flag 2592 <1> ; bis $20,2(sp) 2593 <1> ; / set trace for quit (sets t bit of 2594 <1> ; / ps-trace trap) 2595 <1> ; rti ; / return from interrupt 2596 <1> ; 1: / interrupt char = del 2597 <1> ; clrb 6(r1) / clear the interrupt byte 2598 <1> ; / in the buffer 2599 <1> ; mov (sp)+,r1 / restore r1 2600 <1> ; cmp u.intr,$core / should control be 2601 <1> ; / transferred to loc core? 2602 <1> ; blo 1f 2603 <1> ; jmp *u.intr / user to do rti yes, 2604 <1> ; / transfer to loc core 2605 <1> ; 1: 2606 <1> ; sys 1 / exit 2607 <1> 2608 <1> sysexit: ; 2609 <1> ; 17/07/2022 2610 <1> ; 01/02/2022 2611 <1> ; 01/09/2015 2612 <1> ; 31/08/2015 2613 <1> ; 14/05/2015 2614 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2615 <1> ; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2616 <1> ; 2617 <1> ; 'sysexit' terminates a process. First each file that 2618 <1> ; the process has opened is closed by 'flose'. The process 2619 <1> ; status is then set to unused. The 'p.pid' table is then 2620 <1> ; searched to find children of the dying process. If any of 2621 <1> ; children are zombies (died by not waited for), they are 2622 <1> ; set free. The 'p.pid' table is then searched to find the 2623 <1> ; dying process's parent. When the parent is found, it is 2624 <1> ; checked to see if it is free or it is a zombie. If it is 2625 <1> ; one of these, the dying process just dies. If it is waiting 2626 <1> ; for a child process to die, it notified that it doesn't 2627 <1> ; have to wait anymore by setting it's status from 2 to 1 2628 <1> ; (waiting to active). It is awakened and put on runq by 2629 <1> ; 'putlu'. The dying process enters a zombie state in which 2630 <1> ; it will never be run again but stays around until a 'wait' 2631 <1> ; is completed by it's parent process. If the parent is not 2632 <1> ; found, process just dies. This means 'swap' is called with 2633 <1> ; 'u.uno=0'. What this does is the 'wswap' is not called 2634 <1> ; to write out the process and 'rswap' reads the new process 2635 <1> ; over the one that dies..i.e., the dying process is 2636 <1> ; overwritten and destroyed. 2637 <1> ; 2638 <1> ; Calling sequence: 2639 <1> ; sysexit or conditional branch. 2640 <1> ; Arguments: 2641 <1> ; - 2642 <1> ; ............................................................... 2643 <1> ; 2644 <1> ; Retro UNIX 8086 v1 modification: 2645 <1> ; System call number (=1) is in EAX register. 2646 <1> ; 2647 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 2648 <1> ; registers depending of function details. 2649 <1> ; 2650 <1> ; ('swap' procedure is mostly different than original UNIX v1.) 2651 <1> ; 2652 <1> ; / terminate process 2653 <1> ; AX = 1 2654 <1> ;dec ax ; 0 2655 <1> ; 01/02/2022 2656 000031FC 48 <1> dec eax ; 0 2657 000031FD 66A3[3E650000] <1> mov [u.intr], ax ; 0 2658 <1> ; clr u.intr / clear interrupt control word 2659 <1> ; clr r1 / clear r1 2660 <1> ; AX = 0 2661 <1> sysexit_1: ; 1: 2662 <1> ; AX = File descriptor 2663 <1> ; / r1 has file descriptor (index to u.fp list) 2664 <1> ; / Search the whole list 2665 00003203 E8630D0000 <1> call fclose 2666 <1> ; jsr r0,fclose / close all files the process opened 2667 <1> ;; ignore error return 2668 <1> ; br .+2 / ignore error return 2669 <1> ;inc ax 2670 00003208 FEC0 <1> inc al 2671 <1> ; inc r1 / increment file descriptor 2672 <1> ;cmp ax, 10 2673 0000320A 3C0A <1> cmp al, 10 2674 <1> ; cmp r1,$10. / end of u.fp list? 2675 0000320C 72F5 <1> jb short sysexit_1 2676 <1> ; blt 1b / no, go back 2677 0000320E 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 2678 <1> ; movb u.uno,r1 / yes, move dying process's number to r1 2679 00003215 88A3[73620000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 2680 <1> ; clrb p.stat-1(r1) / free the process 2681 <1> ;shl bx, 1 2682 0000321B D0E3 <1> shl bl, 1 2683 <1> ; asl r1 / use r1 for index into the below tables 2684 0000321D 668B8B[12620000] <1> mov cx, [ebx+p.pid-2] 2685 <1> ; mov p.pid-2(r1),r3 / move dying process's name to r3 2686 00003224 668B93[32620000] <1> mov dx, [ebx+p.ppid-2] 2687 <1> ; mov p.ppid-2(r1),r4 / move its parents name to r4 2688 <1> ;xor bx, bx ; 0 2689 0000322B 30DB <1> xor bl, bl ; 0 2690 <1> ; clr r2 2691 0000322D 31F6 <1> xor esi, esi ; 0 2692 <1> ; clr r5 / initialize reg 2693 <1> sysexit_2: ; 1: 2694 <1> ; / find children of this dying process, 2695 <1> ; / if they are zombies, free them 2696 <1> ;add bx, 2 2697 0000322F 80C302 <1> add bl, 2 2698 <1> ; add $2,r2 / search parent process table 2699 <1> ; / for dying process's name 2700 00003232 66398B[32620000] <1> cmp [ebx+p.ppid-2], cx 2701 <1> ; cmp p.ppid-2(r2),r3 / found it? 2702 00003239 7513 <1> jne short sysexit_4 2703 <1> ; bne 3f / no 2704 <1> ;shr bx, 1 2705 0000323B D0EB <1> shr bl, 1 2706 <1> ; asr r2 / yes, it is a parent 2707 0000323D 80BB[73620000]03 <1> cmp byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 2708 <1> ; cmpb p.stat-1(r2),$3 / is the child of this 2709 <1> ; / dying process a zombie 2710 00003244 7506 <1> jne short sysexit_3 2711 <1> ; bne 2f / no 2712 00003246 88A3[73620000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 2713 <1> ; clrb p.stat-1(r2) / yes, free the child process 2714 <1> sysexit_3: ; 2: 2715 <1> ;shr bx, 1 2716 0000324C D0E3 <1> shl bl, 1 2717 <1> ; asl r2 2718 <1> sysexit_4: ; 3: 2719 <1> ; / search the process name table 2720 <1> ; / for the dying process's parent 2721 0000324E 663993[12620000] <1> cmp [ebx+p.pid-2], dx ; 17/09/2013 2722 <1> ; cmp p.pid-2(r2),r4 / found it? 2723 00003255 7502 <1> jne short sysexit_5 2724 <1> ; bne 3f / no 2725 00003257 89DE <1> mov esi, ebx 2726 <1> ; mov r2,r5 / yes, put index to p.pid table (parents 2727 <1> ; / process # x2) in r5 2728 <1> sysexit_5: ; 3: 2729 <1> ;cmp bx, nproc + nproc 2730 00003259 80FB20 <1> cmp bl, nproc + nproc 2731 <1> ; cmp r2,$nproc+nproc / has whole table been searched? 2732 0000325C 72D1 <1> jb short sysexit_2 2733 <1> ; blt 1b / no, go back 2734 <1> ; mov r5,r1 / yes, r1 now has parents process # x2 2735 0000325E 21F6 <1> and esi, esi ; r5=r1 2736 00003260 7430 <1> jz short sysexit_6 2737 <1> ; beq 2f / no parent has been found. 2738 <1> ; / The process just dies 2739 <1> ;shr si, 1 2740 <1> ; 17/07/2022 2741 00003262 D1EE <1> shr esi, 1 2742 <1> ; asr r1 / set up index to p.stat 2743 00003264 8A86[73620000] <1> mov al, [esi+p.stat-1] 2744 <1> ; movb p.stat-1(r1),r2 / move status of parent to r2 2745 0000326A 20C0 <1> and al, al 2746 0000326C 7424 <1> jz short sysexit_6 2747 <1> ; beq 2f / if its been freed, 2f 2748 0000326E 3C03 <1> cmp al, 3 2749 <1> ; cmp r2,$3 / is parent a zombie? 2750 00003270 7420 <1> je short sysexit_6 2751 <1> ; beq 2f / yes, 2f 2752 <1> ; BH = 0 2753 00003272 8A1D[49650000] <1> mov bl, [u.uno] 2754 <1> ; movb u.uno,r3 / move dying process's number to r3 2755 00003278 C683[73620000]03 <1> mov byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 2756 <1> ; movb $3,p.stat-1(r3) / make the process a zombie 2757 <1> ; 05/02/2014 2758 0000327F 3C01 <1> cmp al, 1 ; SRUN 2759 00003281 740F <1> je short sysexit_6 2760 <1> ;cmp al, 2 2761 <1> ; cmp r2,$2 / is the parent waiting for 2762 <1> ; / this child to die 2763 <1> ;jne short sysexit_6 2764 <1> ; bne 2f / yes, notify parent not to wait any more 2765 <1> ; 05/02/2014 2766 <1> ; p.stat = 2 --> waiting 2767 <1> ; p.stat = 4 --> sleeping 2768 00003283 C686[73620000]01 <1> mov byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014 2769 <1> ;dec byte [esi+p.stat-1] 2770 <1> ; decb p.stat-1(r1) / awaken it by putting it (parent) 2771 0000328A 6689F0 <1> mov ax, si ; r1 (process number in AL) 2772 <1> ; 2773 <1> ;mov ebx, runq + 4 2774 <1> ; mov $runq+4,r2 / on the runq 2775 0000328D E8D1120000 <1> call putlu 2776 <1> ; jsr r0, putlu 2777 <1> sysexit_6: ; 2: 2778 <1> ; 31/08/2015 2779 <1> ; / the process dies 2780 00003292 C605[49650000]00 <1> mov byte [u.uno], 0 2781 <1> ; clrb u.uno / put zero as the process number, 2782 <1> ; / so "swap" will 2783 00003299 E8F8110000 <1> call swap 2784 <1> ; jsr r0,swap / overwrite process with another process 2785 <1> hlt_sys: 2786 <1> ;sti ; 18/01/2014 2787 <1> hlts0: 2788 0000329E F4 <1> hlt 2789 0000329F EBFD <1> jmp short hlts0 2790 <1> ; 0 / and thereby kill it; halt? 2791 <1> 2792 <1> 2793 <1> syswait: ; < wait for a processs to die > 2794 <1> ; 12/02/2022 2795 <1> ; 01/02/2022 2796 <1> ; 17/09/2015 2797 <1> ; 02/09/2015 2798 <1> ; 01/09/2015 2799 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2800 <1> ; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1) 2801 <1> ; 2802 <1> ; 'syswait' waits for a process die. 2803 <1> ; It works in following way: 2804 <1> ; 1) From the parent process number, the parent's 2805 <1> ; process name is found. The p.ppid table of parent 2806 <1> ; names is then searched for this process name. 2807 <1> ; If a match occurs, r2 contains child's process 2808 <1> ; number. The child status is checked to see if it is 2809 <1> ; a zombie, i.e; dead but not waited for (p.stat=3) 2810 <1> ; If it is, the child process is freed and it's name 2811 <1> ; is put in (u.r0). A return is then made via 'sysret'. 2812 <1> ; If the child is not a zombie, nothing happens and 2813 <1> ; the search goes on through the p.ppid table until 2814 <1> ; all processes are checked or a zombie is found. 2815 <1> ; 2) If no zombies are found, a check is made to see if 2816 <1> ; there are any children at all. If there are none, 2817 <1> ; an error return is made. If there are, the parent's 2818 <1> ; status is set to 2 (waiting for child to die), 2819 <1> ; the parent is swapped out, and a branch to 'syswait' 2820 <1> ; is made to wait on the next process. 2821 <1> ; 2822 <1> ; Calling sequence: 2823 <1> ; ? 2824 <1> ; Arguments: 2825 <1> ; - 2826 <1> ; Inputs: - 2827 <1> ; Outputs: if zombie found, it's name put in u.r0. 2828 <1> ; ............................................................... 2829 <1> ; 2830 <1> 2831 <1> ; / wait for a process to die 2832 <1> 2833 <1> syswait_0: 2834 000032A1 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 2835 <1> ; movb u.uno,r1 / put parents process number in r1 2836 000032A8 D0E3 <1> shl bl, 1 2837 <1> ;shl bx, 1 2838 <1> ; asl r1 / x2 to get index into p.pid table 2839 000032AA 668B83[12620000] <1> mov ax, [ebx+p.pid-2] 2840 <1> ; mov p.pid-2(r1),r1 / get the name of this process 2841 000032B1 31F6 <1> xor esi, esi 2842 <1> ; clr r2 2843 000032B3 31C9 <1> xor ecx, ecx ; 30/10/2013 2844 <1> ;xor cl, cl 2845 <1> ; clr r3 / initialize reg 3 2846 <1> syswait_1: ; 1: 2847 <1> ; 12/02/2022 2848 000032B5 46 <1> inc esi 2849 000032B6 46 <1> inc esi 2850 <1> ;add si, 2 2851 <1> ; add $2,r2 / use r2 for index into p.ppid table 2852 <1> ; / search table of parent processes 2853 <1> ; / for this process name 2854 000032B7 663B86[32620000] <1> cmp ax, [esi+p.ppid-2] 2855 <1> ; cmp p.ppid-2(r2),r1 / r2 will contain the childs 2856 <1> ; / process number 2857 000032BE 7531 <1> jne short syswait_3 2858 <1> ; bne 3f / branch if no match of parent process name 2859 <1> ;inc cx 2860 000032C0 FEC1 <1> inc cl 2861 <1> ; inc r3 / yes, a match, r3 indicates number of children 2862 <1> ; 12/02/2022 2863 000032C2 D1EE <1> shr esi, 1 2864 <1> ;shr si, 1 2865 <1> ; asr r2 / r2/2 to get index to p.stat table 2866 <1> ; The possible states ('p.stat' values) of a process are: 2867 <1> ; 0 = free or unused 2868 <1> ; 1 = active 2869 <1> ; 2 = waiting for a child process to die 2870 <1> ; 3 = terminated, but not yet waited for (zombie). 2871 000032C4 80BE[73620000]03 <1> cmp byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014 2872 <1> ; cmpb p.stat-1(r2),$3 / is the child process a zombie? 2873 000032CB 7522 <1> jne short syswait_2 2874 <1> ; bne 2f / no, skip it 2875 000032CD 88BE[73620000] <1> mov [esi+p.stat-1], bh ; 0 2876 <1> ; clrb p.stat-1(r2) / yes, free it 2877 <1> ; 12/02/2022 2878 000032D3 D1E6 <1> shl esi, 1 2879 <1> ;shl si, 1 2880 <1> ; asl r2 / r2x2 to get index into p.pid table 2881 000032D5 0FB786[12620000] <1> movzx eax, word [esi+p.pid-2] 2882 000032DC A3[00650000] <1> mov [u.r0], eax 2883 <1> ; mov p.pid-2(r2),*u.r0 2884 <1> ; / put childs process name in (u.r0) 2885 <1> ; 2886 <1> ; Retro UNIX 386 v1 modification ! (17/09/2015) 2887 <1> ; 2888 <1> ; Parent process ID -p.ppid- field (of the child process) 2889 <1> ; must be cleared in order to prevent infinitive 'syswait' 2890 <1> ; system call loop from the application/program if it calls 2891 <1> ; 'syswait' again (mistakenly) while there is not a zombie 2892 <1> ; or running child process to wait. ('forktest.s', 17/09/2015) 2893 <1> ; 2894 <1> ; Note: syswait will return with error if there is not a 2895 <1> ; zombie or running process to wait. 2896 <1> ; 2897 <1> ;sub ax, ax 2898 <1> ; 01/02/2022 2899 000032E1 29C0 <1> sub eax, eax 2900 000032E3 668986[32620000] <1> mov [esi+p.ppid-2], ax ; 0 ; 17/09/2015 2901 000032EA E914FEFFFF <1> jmp sysret0 ; ax = 0 2902 <1> ; 2903 <1> ;jmp sysret 2904 <1> ; br sysret1 / return cause child is dead 2905 <1> syswait_2: ; 2: 2906 <1> ; 12/02/2022 2907 000032EF D1E6 <1> shl esi, 1 2908 <1> ;shl si, 1 2909 <1> ; asl r2 / r2x2 to get index into p.ppid table 2910 <1> syswait_3: ; 3: 2911 000032F1 6683FE20 <1> cmp si, nproc+nproc 2912 <1> ; cmp r2,$nproc+nproc / have all processes been checked? 2913 000032F5 72BE <1> jb short syswait_1 2914 <1> ; blt 1b / no, continue search 2915 <1> ;and cx, cx 2916 000032F7 20C9 <1> and cl, cl 2917 <1> ; tst r3 / one gets here if there are no children 2918 <1> ; / or children that are still active 2919 <1> ; 30/10/2013 2920 000032F9 7515 <1> jnz short syswait_4 2921 <1> ;jz error 2922 <1> ; beq error1 / there are no children, error 2923 000032FB 890D[00650000] <1> mov [u.r0], ecx ; 0 2924 <1> ; 12/02/2022 2925 00003301 C705[4F650000]1B00- <1> mov dword [u.error], ERR_MISC ; 27 2925 00003309 0000 <1> 2926 <1> ; miscellaneous/other errors 2927 0000330B E9D1FDFFFF <1> jmp error 2928 <1> syswait_4: 2929 00003310 8A1D[49650000] <1> mov bl, [u.uno] 2930 <1> ; movb u.uno,r1 / there are children so put 2931 <1> ; / parent process number in r1 2932 00003316 FE83[73620000] <1> inc byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014 2933 <1> ; incb p.stat-1(r1) / it is waiting for 2934 <1> ; / other children to die 2935 <1> ; 04/11/2013 2936 0000331C E875110000 <1> call swap 2937 <1> ; jsr r0,swap / swap it out, because it's waiting 2938 00003321 E97BFFFFFF <1> jmp syswait_0 2939 <1> ; br syswait / wait on next process 2940 <1> 2941 <1> sysfork: ; < create a new process > 2942 <1> ; 26/02/2022 2943 <1> ; 25/02/2022 2944 <1> ; 01/02/2022 2945 <1> ; 18/09/2015 2946 <1> ; 04/09/2015 2947 <1> ; 02/09/2015 2948 <1> ; 01/09/2015 2949 <1> ; 28/08/2015 2950 <1> ; 14/05/2015 2951 <1> ; 10/05/2015 2952 <1> ; 09/05/2015 2953 <1> ; 06/05/2015 (Retro UNIX 386 v1 - Beginning) 2954 <1> ; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2955 <1> ; 2956 <1> ; 'sysfork' creates a new process. This process is referred 2957 <1> ; to as the child process. This new process core image is 2958 <1> ; a copy of that of the caller of 'sysfork'. The only 2959 <1> ; distinction is the return location and the fact that (u.r0) 2960 <1> ; in the old process (parent) contains the process id (p.pid) 2961 <1> ; of the new process (child). This id is used by 'syswait'. 2962 <1> ; 'sysfork' works in the following manner: 2963 <1> ; 1) The process status table (p.stat) is searched to find 2964 <1> ; a process number that is unused. If none are found 2965 <1> ; an error occurs. 2966 <1> ; 2) when one is found, it becomes the child process number 2967 <1> ; and it's status (p.stat) is set to active. 2968 <1> ; 3) If the parent had a control tty, the interrupt 2969 <1> ; character in that tty buffer is cleared. 2970 <1> ; 4) The child process is put on the lowest priority run 2971 <1> ; queue via 'putlu'. 2972 <1> ; 5) A new process name is gotten from 'mpid' (actually 2973 <1> ; it is a unique number) and is put in the child's unique 2974 <1> ; identifier; process id (p.pid). 2975 <1> ; 6) The process name of the parent is then obtained and 2976 <1> ; placed in the unique identifier of the parent process 2977 <1> ; name is then put in 'u.r0'. 2978 <1> ; 7) The child process is then written out on disk by 2979 <1> ; 'wswap',i.e., the parent process is copied onto disk 2980 <1> ; and the child is born. (The child process is written 2981 <1> ; out on disk/drum with 'u.uno' being the child process 2982 <1> ; number.) 2983 <1> ; 8) The parent process number is then restored to 'u.uno'. 2984 <1> ; 9) The child process name is put in 'u.r0'. 2985 <1> ; 10) The pc on the stack sp + 18 is incremented by 2 to 2986 <1> ; create the return address for the parent process. 2987 <1> ; 11) The 'u.fp' list as then searched to see what files 2988 <1> ; the parent has opened. For each file the parent has 2989 <1> ; opened, the corresponding 'fsp' entry must be updated 2990 <1> ; to indicate that the child process also has opened 2991 <1> ; the file. A branch to 'sysret' is then made. 2992 <1> ; 2993 <1> ; Calling sequence: 2994 <1> ; from shell ? 2995 <1> ; Arguments: 2996 <1> ; - 2997 <1> ; Inputs: - 2998 <1> ; Outputs: *u.r0 - child process name 2999 <1> ; ............................................................... 3000 <1> ; 3001 <1> ; Retro UNIX 8086 v1 modification: 3002 <1> ; AX = r0 = PID (>0) (at the return of 'sysfork') 3003 <1> ; = process id of child a parent process returns 3004 <1> ; = process id of parent when a child process returns 3005 <1> ; 3006 <1> ; In original UNIX v1, sysfork is called and returns as 3007 <1> ; in following manner: (with an example: c library, fork) 3008 <1> ; 3009 <1> ; 1: 3010 <1> ; sys fork 3011 <1> ; br 1f / child process returns here 3012 <1> ; bes 2f / parent process returns here 3013 <1> ; / pid of new process in r0 3014 <1> ; rts pc 3015 <1> ; 2: / parent process condionally branches here 3016 <1> ; mov $-1,r0 / pid = -1 means error return 3017 <1> ; rts pc 3018 <1> ; 3019 <1> ; 1: / child process brances here 3020 <1> ; clr r0 / pid = 0 in child process 3021 <1> ; rts pc 3022 <1> ; 3023 <1> ; In UNIX v7x86 (386) by Robert Nordier (1999) 3024 <1> ; // pid = fork(); 3025 <1> ; // 3026 <1> ; // pid == 0 in child process; 3027 <1> ; // pid == -1 means error return 3028 <1> ; // in child, 3029 <1> ; // parents id is in par_uid if needed 3030 <1> ; 3031 <1> ; _fork: 3032 <1> ; mov $.fork,eax 3033 <1> ; int $0x30 3034 <1> ; jmp 1f 3035 <1> ; jnc 2f 3036 <1> ; jmp cerror 3037 <1> ; 1: 3038 <1> ; mov eax,_par_uid 3039 <1> ; xor eax,eax 3040 <1> ; 2: 3041 <1> ; ret 3042 <1> ; 3043 <1> ; In Retro UNIX 8086 v1, 3044 <1> ; 'sysfork' returns in following manner: 3045 <1> ; 3046 <1> ; mov ax, sys_fork 3047 <1> ; mov bx, offset @f ; routine for child 3048 <1> ; int 20h 3049 <1> ; jc error 3050 <1> ; 3051 <1> ; ; Routine for parent process here (just after 'jc') 3052 <1> ; mov word ptr [pid_of_child], ax 3053 <1> ; jmp next_routine_for_parent 3054 <1> ; 3055 <1> ; @@: ; routine for child process here 3056 <1> ; .... 3057 <1> ; NOTE: 'sysfork' returns to specified offset 3058 <1> ; for child process by using BX input. 3059 <1> ; (at first, parent process will return then 3060 <1> ; child process will return -after swapped in- 3061 <1> ; 'syswait' is needed in parent process 3062 <1> ; if return from child process will be waited for.) 3063 <1> ; 3064 <1> 3065 <1> ; / create a new process 3066 <1> ; EBX = return address for child process 3067 <1> ; (Retro UNIX 8086 v1 modification !) 3068 00003326 31F6 <1> xor esi, esi 3069 <1> ; clr r1 3070 <1> sysfork_1: ; 1: / search p.stat table for unused process number 3071 00003328 46 <1> inc esi 3072 <1> ; inc r1 3073 00003329 80BE[73620000]00 <1> cmp byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014 3074 <1> ; tstb p.stat-1(r1) / is process active, unused, dead 3075 00003330 760B <1> jna short sysfork_2 3076 <1> ; beq 1f / it's unused so branch 3077 00003332 6683FE10 <1> cmp si, nproc 3078 <1> ; cmp r1,$nproc / all processes checked 3079 00003336 72F0 <1> jb short sysfork_1 3080 <1> ; blt 1b / no, branch back 3081 <1> ; 3082 <1> ; Retro UNIX 8086 v1. modification: 3083 <1> ; Parent process returns from 'sysfork' to address 3084 <1> ; which is just after 'sysfork' system call in parent 3085 <1> ; process. Child process returns to address which is put 3086 <1> ; in BX register by parent process for 'sysfork'. 3087 <1> ; 3088 <1> ; add $2,18.(sp) / add 2 to pc when trap occured, points 3089 <1> ; / to old process return 3090 <1> ; br error1 / no room for a new process 3091 <1> sysfork_err: 3092 00003338 E9A4FDFFFF <1> jmp error 3093 <1> sysfork_2: ; 1: 3094 0000333D E89FF0FFFF <1> call allocate_page 3095 <1> ;jc error 3096 <1> ; 01/02/2022 3097 00003342 72F4 <1> jc short sysfork_err 3098 00003344 50 <1> push eax ; UPAGE (user structure page) address 3099 <1> ; Retro UNIX 386 v1 modification! 3100 00003345 E88EF2FFFF <1> call duplicate_page_dir 3101 <1> ; EAX = New page directory 3102 0000334A 7308 <1> jnc short sysfork_3 3103 0000334C 58 <1> pop eax ; UPAGE (user structure page) address 3104 0000334D E855F2FFFF <1> call deallocate_page 3105 <1> ;jmp error 3106 <1> ; 01/02/2022 3107 00003352 EBE4 <1> jmp short sysfork_err 3108 <1> sysfork_3: 3109 <1> ; Retro UNIX 386 v1 modification ! 3110 00003354 56 <1> push esi 3111 00003355 E8B3110000 <1> call wswap ; save current user (u) structure, user registers 3112 <1> ; and interrupt return components (for IRET) 3113 0000335A 8705[53650000] <1> xchg eax, [u.pgdir] ; page directory of the child process 3114 00003360 A3[57650000] <1> mov [u.ppgdir], eax ; page directory of the parent process 3115 00003365 5E <1> pop esi 3116 00003366 58 <1> pop eax ; UPAGE (user structure page) address 3117 <1> ; [u.usp] = esp 3118 00003367 89F7 <1> mov edi, esi 3119 <1> ;shl di, 2 3120 <1> ; 12/02/2022 3121 00003369 C1E702 <1> shl edi, 2 3122 0000336C 8987[80620000] <1> mov [edi+p.upage-4], eax ; memory page for 'user' struct 3123 00003372 A3[4A650000] <1> mov [u.upage], eax ; memory page for 'user' struct (child) 3124 <1> ; 28/08/2015 3125 00003377 0FB605[49650000] <1> movzx eax, byte [u.uno] ; parent process number 3126 <1> ; movb u.uno,-(sp) / save parent process number 3127 0000337E 89C7 <1> mov edi, eax 3128 00003380 50 <1> push eax ; ** 3129 00003381 8A87[53620000] <1> mov al, [edi+p.ttyc-1] ; console tty (parent) 3130 <1> ; 18/09/2015 3131 00003387 8886[53620000] <1> mov [esi+p.ttyc-1], al ; set child's console tty 3132 <1> ; 26/02/2022 (p.waitc is not used) 3133 <1> ;mov [esi+p.waitc-1], ah ; 0 ; reset child's wait channel 3134 <1> ; 25/02/2022 (BugFix) 3135 <1> ;mov [esi+p.ttyc-1], ax ; al - set child's console tty 3136 <1> ; ; ah - reset child's wait channel 3137 0000338D 89F0 <1> mov eax, esi 3138 0000338F A2[49650000] <1> mov [u.uno], al ; child process number 3139 <1> ;movb r1,u.uno / set child process number to r1 3140 00003394 FE86[73620000] <1> inc byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014 3141 <1> ; incb p.stat-1(r1) / set p.stat entry for child 3142 <1> ; / process to active status 3143 <1> ; mov u.ttyp,r2 / put pointer to parent process' 3144 <1> ; / control tty buffer in r2 3145 <1> ; beq 2f / branch, if no such tty assigned 3146 <1> ; clrb 6(r2) / clear interrupt character in tty buffer 3147 <1> ; 2: 3148 0000339A 53 <1> push ebx ; * return address for the child process 3149 <1> ; * Retro UNIX 8086 v1 feature only ! 3150 <1> ; (Retro UNIX 8086 v1 modification!) 3151 <1> ; mov $runq+4,r2 3152 0000339B E8C3110000 <1> call putlu 3153 <1> ; jsr r0,putlu / put child process on lowest priority 3154 <1> ; / run queue 3155 <1> ; 12/02/2022 3156 000033A0 D1E6 <1> shl esi, 1 3157 <1> ;shl si, 1 3158 <1> ; asl r1 / multiply r1 by 2 to get index 3159 <1> ; / into p.pid table 3160 000033A2 66FF05[EC640000] <1> inc word [mpid] 3161 <1> ; inc mpid / increment m.pid; get a new process name 3162 000033A9 66A1[EC640000] <1> mov ax, [mpid] 3163 000033AF 668986[12620000] <1> mov [esi+p.pid-2], ax 3164 <1> ;mov mpid,p.pid-2(r1) / put new process name 3165 <1> ; / in child process' name slot 3166 000033B6 5A <1> pop edx ; * return address for the child process 3167 <1> ; * Retro UNIX 8086 v1 feature only ! 3168 000033B7 5B <1> pop ebx ; ** 3169 <1> ;mov ebx, [esp] ; ** parent process number 3170 <1> ; movb (sp),r2 / put parent process number in r2 3171 <1> ; 01/02/2022 3172 000033B8 D0E3 <1> shl bl, 1 3173 <1> ;shl bx, 1 3174 <1> ; asl r2 / multiply by 2 to get index into below tables 3175 <1> ; ebx <= 32 3176 <1> ;movzx eax, word [ebx+p.pid-2] 3177 000033BA 668B83[12620000] <1> mov ax, [ebx+p.pid-2] 3178 <1> ; mov p.pid-2(r2),r2 / get process name of parent 3179 <1> ; / process 3180 000033C1 668986[32620000] <1> mov [esi+p.ppid-2], ax 3181 <1> ; mov r2,p.ppid-2(r1) / put parent process name 3182 <1> ; / in parent process slot for child 3183 000033C8 A3[00650000] <1> mov [u.r0], eax 3184 <1> ; mov r2,*u.r0 / put parent process name on stack 3185 <1> ; / at location where r0 was saved 3186 000033CD 8B2D[F8640000] <1> mov ebp, [u.sp] ; points to return address (EIP for IRET) 3187 000033D3 895500 <1> mov [ebp], edx ; *, CS:EIP -> EIP 3188 <1> ; * return address for the child process 3189 <1> ; mov $sysret1,-(sp) / 3190 <1> ; mov sp,u.usp / contents of sp at the time when 3191 <1> ; / user is swapped out 3192 <1> ; mov $sstack,sp / point sp to swapping stack space 3193 <1> ; 04/09/2015 - 01/09/2015 3194 <1> ; [u.usp] = esp 3195 000033D6 68[01310000] <1> push sysret ; *** 3196 000033DB 8925[FC640000] <1> mov [u.usp], esp ; points to 'sysret' address (***) 3197 <1> ; (for child process) 3198 000033E1 31C0 <1> xor eax, eax 3199 000033E3 66A3[30650000] <1> mov [u.ttyp], ax ; 0 3200 <1> ; 3201 000033E9 E81F110000 <1> call wswap ; Retro UNIX 8086 v1 modification ! 3202 <1> ;jsr r0,wswap / put child process out on drum 3203 <1> ;jsr r0,unpack / unpack user stack 3204 <1> ;mov u.usp,sp / restore user stack pointer 3205 <1> ; tst (sp)+ / bump stack pointer 3206 <1> ; Retro UNIX 386 v1 modification ! 3207 000033EE 58 <1> pop eax ; *** 3208 <1> ;shl bx, 1 3209 <1> ; 01/02/2022 3210 000033EF D0E3 <1> shl bl, 1 3211 <1> ; ebx <= 64 3212 000033F1 8B83[80620000] <1> mov eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015 3213 000033F7 E83A110000 <1> call rswap ; restore parent process 'u' structure, 3214 <1> ; registers and return address (for IRET) 3215 <1> ;movb (sp)+,u.uno / put parent process number in u.uno 3216 000033FC 0FB705[EC640000] <1> movzx eax, word [mpid] 3217 00003403 A3[00650000] <1> mov [u.r0], eax 3218 <1> ; mov mpid,*u.r0 / put child process name on stack 3219 <1> ; / where r0 was saved 3220 <1> ; add $2,18.(sp) / add 2 to pc on stack; gives parent 3221 <1> ; / process return 3222 <1> ;xor ebx, ebx 3223 00003408 31F6 <1> xor esi, esi 3224 <1> ;clr r1 3225 <1> sysfork_4: ; 1: / search u.fp list to find the files 3226 <1> ; / opened by the parent process 3227 <1> ; 01/09/2015 3228 <1> ;xor bh, bh 3229 <1> ;mov bl, [esi+u.fp] 3230 0000340A 8A86[06650000] <1> mov al, [esi+u.fp] 3231 <1> ; movb u.fp(r1),r2 / get an open file for this process 3232 <1> ;or bl, bl 3233 00003410 08C0 <1> or al, al 3234 00003412 740C <1> jz short sysfork_5 3235 <1> ; beq 2f / file has not been opened by parent, 3236 <1> ; / so branch 3237 00003414 B40A <1> mov ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes 3238 00003416 F6E4 <1> mul ah 3239 <1> ;;movzx ebx, ax 3240 <1> ;mov bx, ax 3241 00003418 89C3 <1> mov ebx, eax ; 12/02/2022 3242 <1> ;shl bx, 3 3243 <1> ; asl r2 / multiply by 8 3244 <1> ; asl r2 / to get index into fsp table 3245 <1> ; asl r2 3246 0000341A FE83[C2620000] <1> inc byte [ebx+fsp-2] 3247 <1> ; incb fsp-2(r2) / increment number of processes 3248 <1> ; / using file, because child will now be 3249 <1> ; / using this file 3250 <1> sysfork_5: ; 2: 3251 00003420 46 <1> inc esi 3252 <1> ; inc r1 / get next open file 3253 00003421 6683FE0A <1> cmp si, 10 3254 <1> ; cmp r1,$10. / 10. files is the maximum number which 3255 <1> ; / can be opened 3256 00003425 72E3 <1> jb short sysfork_4 3257 <1> ; blt 1b / check next entry 3258 00003427 E9D5FCFFFF <1> jmp sysret 3259 <1> ; br sysret1 3260 <1> 3261 <1> sysread: ; < read from file > 3262 <1> ; 27/02/2022 3263 <1> ; 01/02/2022 3264 <1> ; 13/05/2015 3265 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3266 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 3267 <1> ; 3268 <1> ; 'sysread' is given a buffer to read into and the number of 3269 <1> ; characters to be read. If finds the file from the file 3270 <1> ; descriptor located in *u.r0 (r0). This file descriptor 3271 <1> ; is returned from a successful open call (sysopen). 3272 <1> ; The i-number of file is obtained via 'rw1' and the data 3273 <1> ; is read into core via 'readi'. 3274 <1> ; 3275 <1> ; Calling sequence: 3276 <1> ; sysread; buffer; nchars 3277 <1> ; Arguments: 3278 <1> ; buffer - location of contiguous bytes where 3279 <1> ; input will be placed. 3280 <1> ; nchars - number of bytes or characters to be read. 3281 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 3282 <1> ; Outputs: *u.r0 - number of bytes read. 3283 <1> ; ............................................................... 3284 <1> ; 3285 <1> ; Retro UNIX 8086 v1 modification: 3286 <1> ; 'sysread' system call has three arguments; so, 3287 <1> ; * 1st argument, file descriptor is in BX register 3288 <1> ; * 2nd argument, buffer address/offset in CX register 3289 <1> ; * 3rd argument, number of bytes is in DX register 3290 <1> ; 3291 <1> ; AX register (will be restored via 'u.r0') will return 3292 <1> ; to the user with number of bytes read. 3293 <1> ; 3294 0000342C E840000000 <1> call rw1 3295 <1> ;jc error ; 13/05/2015, ax < 1 3296 <1> ; ; jsr r0,rw1 / get i-number in r1 of file to write 3297 <1> ; 27/02/2022 3298 00003431 7239 <1> jc short sysread_err 3299 00003433 F6C480 <1> test ah, 80h 3300 <1> ; tst r1 / negative i-number? 3301 <1> ;jnz error 3302 <1> ; ble error1 / yes, error 1 to read 3303 <1> ; / it should be positive 3304 <1> ; 01/02/2022 3305 <1> ;jnz short rw_error 3306 <1> ;27/02/2022 3307 00003436 752A <1> jnz short rw3 ; 24/12/2021 3308 <1> ; 3309 00003438 E88D150000 <1> call readi 3310 <1> ; jsr r0,readi / read data into core 3311 0000343D EB14 <1> jmp short rw0 3312 <1> ; br 1f 3313 <1> 3314 <1> syswrite: ; < write to file > 3315 <1> ; 27/02/2022 3316 <1> ; 01/02/2022 3317 <1> ; 13/05/2015 3318 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3319 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 3320 <1> ; 3321 <1> ; 'syswrite' is given a buffer to write onto an output file 3322 <1> ; and the number of characters to write. If finds the file 3323 <1> ; from the file descriptor located in *u.r0 (r0). This file 3324 <1> ; descriptor is returned from a successful open or create call 3325 <1> ; (sysopen or syscreat). The i-number of file is obtained via 3326 <1> ; 'rw1' and buffer is written on the output file via 'write'. 3327 <1> ; 3328 <1> ; Calling sequence: 3329 <1> ; syswrite; buffer; nchars 3330 <1> ; Arguments: 3331 <1> ; buffer - location of contiguous bytes to be writtten. 3332 <1> ; nchars - number of characters to be written. 3333 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 3334 <1> ; Outputs: *u.r0 - number of bytes written. 3335 <1> ; ............................................................... 3336 <1> ; 3337 <1> ; Retro UNIX 8086 v1 modification: 3338 <1> ; 'syswrite' system call has three arguments; so, 3339 <1> ; * 1st argument, file descriptor is in BX register 3340 <1> ; * 2nd argument, buffer address/offset in CX register 3341 <1> ; * 3rd argument, number of bytes is in DX register 3342 <1> ; 3343 <1> ; AX register (will be restored via 'u.r0') will return 3344 <1> ; to the user with number of bytes written. 3345 <1> ; 3346 0000343F E82D000000 <1> call rw1 3347 <1> ;jc error ; 13/05/2015, ax < 1 3348 <1> ; jsr r0,rw1 / get i-number in r1 of file to write 3349 <1> ; 01/02/2022 3350 <1> ;jnc short syswrite_1 3351 <1> ;rw_error: 3352 <1> ;jmp error 3353 <1> ; 27/02/2022 3354 00003444 7226 <1> jc short short syswrite_err 3355 <1> syswrite_1: 3356 00003446 F6C480 <1> test ah, 80h 3357 <1> ; tst r1 / positive i-number ? 3358 00003449 7417 <1> jz short rw3 ; 13/05/2015 3359 <1> ;jz error 3360 <1> ; bge error1 / yes, error 1 3361 <1> ; / negative i-number means write 3362 0000344B 66F7D8 <1> neg ax 3363 <1> ; neg r1 / make it positive 3364 0000344E E869170000 <1> call writei 3365 <1> ; jsr r0,writei / write data 3366 <1> rw0: ; 1: 3367 00003453 A1[28650000] <1> mov eax, [u.nread] 3368 00003458 A3[00650000] <1> mov [u.r0], eax 3369 <1> ; mov u.nread,*u.r0 / put no. of bytes transferred 3370 <1> ; / into (u.r0) 3371 0000345D E99FFCFFFF <1> jmp sysret 3372 <1> ; br sysret1 3373 <1> rw3: 3374 <1> ; 13/05/2015 3375 00003462 C705[4F650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 3375 0000346A 0000 <1> 3376 <1> ;stc 3377 <1> ;retn 3378 <1> ; 27/02/2022 (BugFix) 3379 <1> sysread_err: 3380 <1> syswrite_err: 3381 0000346C E970FCFFFF <1> jmp error 3382 <1> 3383 <1> rw1: 3384 <1> ; 14/05/2015 3385 <1> ; 13/05/2015 3386 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3387 <1> ; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1) 3388 <1> ; System call registers: bx, cx, dx (through 'sysenter') 3389 <1> ; 3390 <1> ;mov [u.base], ecx ; buffer address/offset 3391 <1> ;(in the user's virtual memory space) 3392 <1> ;mov [u.count], edx 3393 <1> ; jsr r0,arg; u.base / get buffer pointer 3394 <1> ; jsr r0,arg; u.count / get no. of characters 3395 <1> ;;mov eax, ebx ; file descriptor 3396 <1> ; mov *u.r0,r1 / put file descriptor 3397 <1> ; / (index to u.fp table) in r1 3398 <1> ; 13/05/2015 3399 00003471 C705[00650000]0000- <1> mov dword [u.r0], 0 ; r/w transfer count = 0 (reset) 3399 00003479 0000 <1> 3400 <1> ; 3401 <1> ;; call getf 3402 <1> ; eBX = File descriptor 3403 0000347B E82E0B0000 <1> call getf1 ; calling point in 'getf' from 'rw1' 3404 <1> ; jsr r0,getf / get i-number of the file in r1 3405 <1> ; AX = I-number of the file ; negative i-number means write 3406 <1> ; 13/05/2015 3407 00003480 6683F801 <1> cmp ax, 1 3408 00003484 7217 <1> jb short rw2 3409 <1> ; 3410 00003486 890D[20650000] <1> mov [u.base], ecx ; buffer address/offset 3411 <1> ;(in the user's virtual memory space) 3412 0000348C 8915[24650000] <1> mov [u.count], edx 3413 <1> ; 14/05/2015 3414 00003492 C705[4F650000]0000- <1> mov dword [u.error], 0 ; reset the last error code 3414 0000349A 0000 <1> 3415 0000349C C3 <1> retn 3416 <1> ; rts r0 3417 <1> rw2: 3418 <1> ; 13/05/2015 3419 0000349D C705[4F650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 3419 000034A5 0000 <1> 3420 000034A7 C3 <1> retn 3421 <1> 3422 <1> sysopen: ; 3423 <1> ; 12/02/2022 3424 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3425 <1> ; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1) 3426 <1> ; 3427 <1> ; 'sysopen' opens a file in following manner: 3428 <1> ; 1) The second argument in a sysopen says whether to 3429 <1> ; open the file ro read (0) or write (>0). 3430 <1> ; 2) I-node of the particular file is obtained via 'namei'. 3431 <1> ; 3) The file is opened by 'iopen'. 3432 <1> ; 4) Next housekeeping is performed on the fsp table 3433 <1> ; and the user's open file list - u.fp. 3434 <1> ; a) u.fp and fsp are scanned for the next available slot. 3435 <1> ; b) An entry for the file is created in the fsp table. 3436 <1> ; c) The number of this entry is put on u.fp list. 3437 <1> ; d) The file descriptor index to u.fp list is pointed 3438 <1> ; to by u.r0. 3439 <1> ; 3440 <1> ; Calling sequence: 3441 <1> ; sysopen; name; mode 3442 <1> ; Arguments: 3443 <1> ; name - file name or path name 3444 <1> ; mode - 0 to open for reading 3445 <1> ; 1 to open for writing 3446 <1> ; Inputs: (arguments) 3447 <1> ; Outputs: *u.r0 - index to u.fp list (the file descriptor) 3448 <1> ; is put into r0's location on the stack. 3449 <1> ; ............................................................... 3450 <1> ; 3451 <1> ; Retro UNIX 8086 v1 modification: 3452 <1> ; 'sysopen' system call has two arguments; so, 3453 <1> ; * 1st argument, name is pointed to by BX register 3454 <1> ; * 2nd argument, mode is in CX register 3455 <1> ; 3456 <1> ; AX register (will be restored via 'u.r0') will return 3457 <1> ; to the user with the file descriptor/number 3458 <1> ; (index to u.fp list). 3459 <1> ; 3460 <1> ;call arg2 3461 <1> ; * name - 'u.namep' points to address of file/path name 3462 <1> ; in the user's program segment ('u.segmnt') 3463 <1> ; with offset in BX register (as sysopen argument 1). 3464 <1> ; * mode - sysopen argument 2 is in CX register 3465 <1> ; which is on top of stack. 3466 <1> ; 3467 <1> ; jsr r0,arg2 / get sys args into u.namep and on stack 3468 <1> ; 3469 <1> ; system call registers: ebx, ecx (through 'sysenter') 3470 <1> 3471 000034A8 891D[18650000] <1> mov [u.namep], ebx 3472 <1> ;push cx 3473 000034AE 51 <1> push ecx ; 12/02/2022 3474 000034AF E82D0B0000 <1> call namei 3475 <1> ; jsr r0,namei / i-number of file in r1 3476 <1> ;and ax, ax 3477 <1> ;jz error ; File not found 3478 000034B4 7239 <1> jc short fnotfound ; 14/05/2015 3479 <1> ;jc error ; 27/05/2013 3480 <1> ; br error2 / file not found 3481 <1> ;pop dx ; mode 3482 <1> ;push dx 3483 <1> ; 12/02/2022 3484 <1> ;pop edx ; * ; mode 3485 <1> ;push edx ; * 3486 000034B6 8B1424 <1> mov edx, [esp] ; * 3487 <1> ; edx = open mode (0 or 1) 3488 <1> ;or dx, dx 3489 000034B9 08D2 <1> or dl, dl 3490 <1> ; tst (sp) / is mode = 0 (2nd arg of call; 3491 <1> ; / 0 means, open for read) 3492 000034BB 7403 <1> jz short sysopen_0 3493 <1> ; beq 1f / yes, leave i-number positive 3494 <1> syscreat_0: 3495 <1> ; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1) 3496 000034BD 66F7D8 <1> neg ax 3497 <1> ; neg r1 / open for writing so make i-number negative 3498 <1> sysopen_0: ;1: 3499 000034C0 E8951B0000 <1> call iopen 3500 <1> ; jsr r0,iopen / open file whose i-number is in r1 3501 000034C5 5A <1> pop edx ; * ; mode ; 12/02/2022 3502 <1> ;and dx, dx 3503 000034C6 20D2 <1> and dl, dl 3504 <1> ; tst (sp)+ / pop the stack and test the mode 3505 000034C8 7403 <1> jz short sysopen_2 3506 <1> ; beq op1 / is open for read op1 3507 <1> sysopen_1: ;op0: 3508 000034CA 66F7D8 <1> neg ax 3509 <1> ; neg r1 3510 <1> ;/ make i-number positive if open for writing [???] 3511 <1> ;; NOTE: iopen always make i-number positive. 3512 <1> ;; Here i-number becomes negative again. [22/05/2013] 3513 <1> sysopen_2: ;op1: 3514 000034CD 31F6 <1> xor esi, esi 3515 <1> ; clr r2 / clear registers 3516 000034CF 31DB <1> xor ebx, ebx 3517 <1> ; clr r3 3518 <1> sysopen_3: ;1: / scan the list of entries in fsp table 3519 000034D1 389E[06650000] <1> cmp [esi+u.fp], bl ; 0 3520 <1> ; tstb u.fp(r2) / test the entry in the u.fp list 3521 000034D7 7625 <1> jna short sysopen_4 3522 <1> ; beq 1f / if byte in list is 0 branch 3523 000034D9 46 <1> inc esi 3524 <1> ; inc r2 / bump r2 so next byte can be checked 3525 000034DA 6683FE0A <1> cmp si, 10 3526 <1> ; cmp r2,$10. / reached end of list? 3527 000034DE 72F1 <1> jb short sysopen_3 3528 <1> ; blt 1b / no, go back 3529 <1> toomanyf: 3530 <1> ; 14/05/2015 3531 000034E0 C705[4F650000]0D00- <1> mov dword [u.error], ERR_TOO_MANY_FILES ; too many open files ! 3531 000034E8 0000 <1> 3532 000034EA E9F2FBFFFF <1> jmp error 3533 <1> ; br error2 / yes, error (no files open) 3534 <1> fnotfound: 3535 <1> ; 14/05/2015 3536 000034EF C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; file not found ! 3536 000034F7 0000 <1> 3537 000034F9 E9E3FBFFFF <1> jmp error 3538 <1> 3539 <1> sysopen_4: ; 1: 3540 000034FE 6683BB[C4620000]00 <1> cmp word [ebx+fsp], 0 3541 <1> ; tst fsp(r3) / scan fsp entries 3542 00003506 7610 <1> jna short sysopen_5 3543 <1> ; beq 1f / if 0 branch 3544 <1> ; 14/05/2015 - Retro UNIX 386 v1 modification ! 3545 00003508 6683C30A <1> add bx, 10 ; fsp structure size = 10 bytes/entry 3546 <1> ; add $8.,r3 / add 8 to r3 3547 <1> ; / to bump it to next entry mfsp table 3548 0000350C 6681FBF401 <1> cmp bx, nfiles*10 3549 <1> ; cmp r3,$[nfiles*8.] / done scanning 3550 00003511 72EB <1> jb short sysopen_4 3551 <1> ; blt 1b / no, back 3552 00003513 E9C9FBFFFF <1> jmp error 3553 <1> ; br error2 / yes, error 3554 <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table 3555 00003518 668983[C4620000] <1> mov [ebx+fsp], ax 3556 <1> ; mov r1,fsp(r3) / put i-number of open file 3557 <1> ; / into next available entry in fsp table, 3558 <1> ; 12/02/2022 3559 <1> ;mov di, [cdev] ; word ? byte ? 3560 <1> ;mov [ebx+fsp+2], di ; device number 3561 <1> ; mov cdev,fsp+2(r3) / put # of device in next word 3562 <1> ;xor edi, edi 3563 <1> ;mov [ebx+fsp+4], edi ; offset pointer (0) 3564 <1> ; ; clr fsp+4(r3) 3565 <1> ;mov [ebx+fsp+8], di ; open count (0), deleted flag (0) 3566 <1> ; ; clr fsp+6(r3) / clear the next two words 3567 0000351F 31C0 <1> xor eax, eax 3568 00003521 8983[C8620000] <1> mov [ebx+fsp+4], eax ; offset pointer (0) 3569 00003527 668983[CC620000] <1> mov [ebx+fsp+8], ax ; open count (0), deleted flag (0) 3570 <1> 3571 0000352E 66A1[E4640000] <1> mov ax, [cdev] 3572 00003534 668983[C6620000] <1> mov [ebx+fsp+2], ax ; device number 3573 <1> 3574 0000353B 89D8 <1> mov eax, ebx 3575 0000353D B30A <1> mov bl, 10 3576 0000353F F6F3 <1> div bl 3577 <1> ; asr r3 3578 <1> ; asr r3 / divide by 8 3579 <1> ; asr r3 ; / to get number of the fsp entry-1 3580 00003541 FEC0 <1> inc al 3581 <1> ; inc r3 / add 1 to get fsp entry number 3582 00003543 8886[06650000] <1> mov [esi+u.fp], al 3583 <1> ; movb r3,u.fp(r2) / move entry number into 3584 <1> ; / next available slot in u.fp list 3585 00003549 8935[00650000] <1> mov [u.r0], esi 3586 <1> ; mov r2,*u.r0 / move index to u.fp list 3587 <1> ; / into r0 loc on stack 3588 0000354F E9ADFBFFFF <1> jmp sysret 3589 <1> ; br sysret2 3590 <1> 3591 <1> ; 3592 <1> ; 'fsp' table (10 bytes/entry) 3593 <1> ; bit 15 bit 0 3594 <1> ; ---|------------------------------------------- 3595 <1> ; r/w| i-number of open file 3596 <1> ; ---|------------------------------------------- 3597 <1> ; device number 3598 <1> ; ----------------------------------------------- 3599 <1> ; offset pointer, r/w pointer to file (bit 0-15) 3600 <1> ; ----------------------------------------------- 3601 <1> ; offset pointer, r/w pointer to file (bit 16-31) 3602 <1> ; ----------------------|------------------------ 3603 <1> ; flag that says file | number of processes 3604 <1> ; has been deleted | that have file open 3605 <1> ; ----------------------|------------------------ 3606 <1> ; 3607 <1> 3608 <1> syscreat: ; < create file > 3609 <1> ; 12/02/2022 3610 <1> ; 01/02/2022 3611 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3612 <1> ; 27/05/2013 (Retro UNIX 8086 v1) 3613 <1> ; 3614 <1> ; 'syscreat' called with two arguments; name and mode. 3615 <1> ; u.namep points to name of the file and mode is put 3616 <1> ; on the stack. 'namei' is called to get i-number of the file. 3617 <1> ; If the file aready exists, it's mode and owner remain 3618 <1> ; unchanged, but it is truncated to zero length. If the file 3619 <1> ; did not exist, an i-node is created with the new mode via 3620 <1> ; 'maknod' whether or not the file already existed, it is 3621 <1> ; open for writing. The fsp table is then searched for a free 3622 <1> ; entry. When a free entry is found, proper data is placed 3623 <1> ; in it and the number of this entry is put in the u.fp list. 3624 <1> ; The index to the u.fp (also know as the file descriptor) 3625 <1> ; is put in the user's r0. 3626 <1> ; 3627 <1> ; Calling sequence: 3628 <1> ; syscreate; name; mode 3629 <1> ; Arguments: 3630 <1> ; name - name of the file to be created 3631 <1> ; mode - mode of the file to be created 3632 <1> ; Inputs: (arguments) 3633 <1> ; Outputs: *u.r0 - index to u.fp list 3634 <1> ; (the file descriptor of new file) 3635 <1> ; ............................................................... 3636 <1> ; 3637 <1> ; Retro UNIX 8086 v1 modification: 3638 <1> ; 'syscreate' system call has two arguments; so, 3639 <1> ; * 1st argument, name is pointed to by BX register 3640 <1> ; * 2nd argument, mode is in CX register 3641 <1> ; 3642 <1> ; AX register (will be restored via 'u.r0') will return 3643 <1> ; to the user with the file descriptor/number 3644 <1> ; (index to u.fp list). 3645 <1> ; 3646 <1> ;call arg2 3647 <1> ; * name - 'u.namep' points to address of file/path name 3648 <1> ; in the user's program segment ('u.segmnt') 3649 <1> ; with offset in BX register (as sysopen argument 1). 3650 <1> ; * mode - sysopen argument 2 is in CX register 3651 <1> ; which is on top of stack. 3652 <1> ; 3653 <1> ; jsr r0,arg2 / put file name in u.namep put mode 3654 <1> ; / on stack 3655 00003554 891D[18650000] <1> mov [u.namep], ebx ; file name address 3656 <1> ;push cx ; mode 3657 <1> ; 01/02/2022 3658 0000355A 51 <1> push ecx ; mode 3659 0000355B E8810A0000 <1> call namei 3660 <1> ; jsr r0,namei / get the i-number 3661 <1> ;and ax, ax 3662 <1> ;jz short syscreat_2 3663 00003560 721B <1> jc short syscreat_2 3664 <1> ; br 2f / if file doesn't exist 2f 3665 <1> ; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022) 3666 <1> ; 27/12/2015 (Retro UNIX 386 v1.1) 3667 00003562 6683F829 <1> cmp ax, 41 ; device inode ? 3668 <1> ;jb syscreat_0 ; yes 3669 <1> ; 02/02/2022 3670 00003566 7305 <1> jnb short syscreat_1 3671 00003568 E950FFFFFF <1> jmp syscreat_0 3672 <1> syscreat_1: 3673 0000356D 66F7D8 <1> neg ax 3674 <1> ; neg r1 / if file already exists make i-number 3675 <1> ; / negative (open for writing) 3676 00003570 E8E51A0000 <1> call iopen 3677 <1> ; jsr r0,iopen / 3678 00003575 E8A8130000 <1> call itrunc 3679 <1> ; jsr r0,itrunc / truncate to 0 length 3680 <1> ;pop cx ; pop mode (did not exist in original Unix v1 !?) 3681 <1> ; 01/02/2022 3682 0000357A 59 <1> pop ecx ; mode 3683 <1> ; 12/02/2022 3684 0000357B EB0E <1> jmp short syscreat_3 3685 <1> ;jmp sysopen_1 3686 <1> ; br op0 3687 <1> syscreat_2: ; 2: / file doesn't exist 3688 <1> ; 01/02/2022 3689 0000357D 58 <1> pop eax ; mode 3690 <1> ;pop ax 3691 <1> ; mov (sp)+,r1 / put the mode in r1 3692 0000357E 30E4 <1> xor ah, ah 3693 <1> ; bic $!377,r1 / clear upper byte 3694 00003580 E86D0D0000 <1> call maknod 3695 <1> ; jsr r0,maknod / make an i-node for this file 3696 00003585 66A1[32650000] <1> mov ax, [u.dirbuf] 3697 <1> ; mov u.dirbuf,r1 / put i-number 3698 <1> ; / for this new file in r1 3699 <1> syscreat_3: 3700 0000358B E93AFFFFFF <1> jmp sysopen_1 3701 <1> ; br op0 / open the file 3702 <1> 3703 <1> sysmkdir: ; < make directory > 3704 <1> ; 01/02/2022 3705 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3706 <1> ; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 3707 <1> ; 3708 <1> ; 'sysmkdir' creates an empty directory whose name is 3709 <1> ; pointed to by arg 1. The mode of the directory is arg 2. 3710 <1> ; The special entries '.' and '..' are not present. 3711 <1> ; Errors are indicated if the directory already exists or 3712 <1> ; user is not the super user. 3713 <1> ; 3714 <1> ; Calling sequence: 3715 <1> ; sysmkdir; name; mode 3716 <1> ; Arguments: 3717 <1> ; name - points to the name of the directory 3718 <1> ; mode - mode of the directory 3719 <1> ; Inputs: (arguments) 3720 <1> ; Outputs: - 3721 <1> ; (sets 'directory' flag to 1; 3722 <1> ; 'set user id on execution' and 'executable' flags to 0) 3723 <1> ; ............................................................... 3724 <1> ; 3725 <1> ; Retro UNIX 8086 v1 modification: 3726 <1> ; 'sysmkdir' system call has two arguments; so, 3727 <1> ; * 1st argument, name is pointed to by BX register 3728 <1> ; * 2nd argument, mode is in CX register 3729 <1> 3730 <1> ; / make a directory 3731 <1> 3732 <1> ;call arg2 3733 <1> ; * name - 'u.namep' points to address of file/path name 3734 <1> ; in the user's program segment ('u.segmnt') 3735 <1> ; with offset in BX register (as sysopen argument 1). 3736 <1> ; * mode - sysopen argument 2 is in CX register 3737 <1> ; which is on top of stack. 3738 <1> 3739 <1> ; jsr r0,arg2 / put file name in u.namep put mode 3740 <1> ; / on stack 3741 00003590 891D[18650000] <1> mov [u.namep], ebx 3742 <1> ;push cx ; mode 3743 <1> ; 01/02/2022 3744 00003596 51 <1> push ecx ; mode 3745 00003597 E8450A0000 <1> call namei 3746 <1> ; jsr r0,namei / get the i-number 3747 <1> ; br .+4 / if file not found branch around error 3748 <1> ;xor ax, ax 3749 <1> ;jnz error 3750 0000359C 731B <1> jnc short dir_exists ; 14/05/2015 3751 <1> ;jnc error 3752 <1> ; br error2 / directory already exists (error) 3753 0000359E 803D[46650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 3754 <1> ;tstb u.uid / is user the super user 3755 <1> ;jna short dir_access_err ; 14/05/2015 3756 <1> ;;jna error 3757 <1> ; 01/02/2022 (BugFix) 3758 000035A5 7721 <1> ja short dir_access_err 3759 <1> ;bne error2 / no, not allowed 3760 <1> ;pop ax 3761 <1> ; 01/02/2022 3762 000035A7 58 <1> pop eax ; mode 3763 <1> ;mov (sp)+,r1 / put the mode in r1 3764 000035A8 6683E0CF <1> and ax, 0FFCFh ; 1111111111001111b 3765 <1> ;bic $!317,r1 / all but su and ex 3766 <1> ;or ax, 4000h ; 1011111111111111b 3767 000035AC 80CC40 <1> or ah, 40h ; Set bit 14 to 1 3768 <1> ;bis $40000,r1 / directory flag 3769 000035AF E83E0D0000 <1> call maknod 3770 <1> ;jsr r0,maknod / make the i-node for the directory 3771 <1> sysclose_sysret: ; 01/02/2022 3772 000035B4 E948FBFFFF <1> jmp sysret 3773 <1> ;br sysret2 / 3774 <1> dir_exists: 3775 <1> ; 14/05/2015 3776 000035B9 C705[4F650000]0E00- <1> mov dword [u.error], ERR_DIR_EXISTS ; dir. already exists ! 3776 000035C1 0000 <1> 3777 000035C3 E919FBFFFF <1> jmp error 3778 <1> dir_access_err: 3779 <1> ; 14/05/2015 3780 000035C8 C705[4F650000]0B00- <1> mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 3780 000035D0 0000 <1> 3781 000035D2 E90AFBFFFF <1> jmp error 3782 <1> 3783 <1> sysclose: ; 3784 <1> ; 01/02/2022 3785 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3786 <1> ; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1) 3787 <1> ; 3788 <1> ; 'sysclose', given a file descriptor in 'u.r0', closes the 3789 <1> ; associated file. The file descriptor (index to 'u.fp' list) 3790 <1> ; is put in r1 and 'fclose' is called. 3791 <1> ; 3792 <1> ; Calling sequence: 3793 <1> ; sysclose 3794 <1> ; Arguments: 3795 <1> ; - 3796 <1> ; Inputs: *u.r0 - file descriptor 3797 <1> ; Outputs: - 3798 <1> ; ............................................................... 3799 <1> ; 3800 <1> ; Retro UNIX 8086 v1 modification: 3801 <1> ; The user/application program puts file descriptor 3802 <1> ; in BX register as 'sysclose' system call argument. 3803 <1> ; (argument transfer method 1) 3804 <1> 3805 <1> ; / close the file 3806 <1> 3807 000035D7 89D8 <1> mov eax, ebx 3808 000035D9 E88D090000 <1> call fclose 3809 <1> ; mov *u.r0,r1 / move index to u.fp list into r1 3810 <1> ; jsr r0,fclose / close the file 3811 <1> ; br error2 / unknown file descriptor 3812 <1> ; br sysret2 3813 <1> ; 14/05/2015 3814 <1> ;jnc sysret 3815 <1> ; 01/02/2022 3816 000035DE 73D4 <1> jnc short sysclose_sysret 3817 000035E0 C705[4F650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 3817 000035E8 0000 <1> 3818 000035EA E9F2FAFFFF <1> jmp error 3819 <1> 3820 <1> sysemt: 3821 <1> ; 23/02/2022 3822 <1> ; 01/02/2022 3823 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3824 <1> ; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1) 3825 <1> ; 3826 <1> ; Retro UNIX 8086 v1 modification: 3827 <1> ; 'Enable Multi Tasking' system call instead 3828 <1> ; of 'Emulator Trap' in original UNIX v1 for PDP-11. 3829 <1> ; 3830 <1> ; Retro UNIX 8086 v1 feature only! 3831 <1> ; Using purpose: Kernel will start without time-out 3832 <1> ; (internal clock/timer) functionality. 3833 <1> ; Then etc/init will enable clock/timer for 3834 <1> ; multi tasking. (Then it will not be disabled again 3835 <1> ; except hardware reset/restart.) 3836 <1> 3837 000035EF 803D[46650000]00 <1> cmp byte [u.uid], 0 ; root ? 3838 <1> ;;ja error 3839 <1> ;ja badsys ; 14/05/2015 3840 <1> ; 01/02/2022 3841 <1> ;jna short emt_0 3842 <1> ;jmp badsys 3843 000035F6 773A <1> ja short sysilgins ; jmp badsys 3844 <1> emt_0: 3845 000035F8 FA <1> cli 3846 000035F9 21DB <1> and ebx, ebx 3847 000035FB 7429 <1> jz short emt_2 3848 <1> ; Enable multi tasking -time sharing- 3849 000035FD B8[AB450000] <1> mov eax, clock ; enable multi tasking clock/timer 3850 <1> ; 23/02/2022 3851 00003602 BA[430A0000] <1> mov edx, rtci_default ; disable rtc (digital) printing 3852 <1> emt_1: 3853 00003607 A3[09070000] <1> mov [x_timer], eax 3854 <1> ; 23/02/2022 (Temporary) 3855 0000360C 8915[0D070000] <1> mov [x_rtci], edx 3856 00003612 B306 <1> mov bl, 6 ; timer interrupt page, video page 6 3857 00003614 E853020000 <1> call wttyc ; clear video page 3858 00003619 B307 <1> mov bl, 7 ; rtc interrupt page, video page 7 3859 0000361B E84C020000 <1> call wttyc ; clear video page 3860 <1> ; 3861 00003620 FB <1> sti 3862 00003621 E9DBFAFFFF <1> jmp sysret 3863 <1> emt_2: 3864 <1> ; Disable multi tasking -time sharing- 3865 00003626 B8[15070000] <1> mov eax, u_timer ; enable timer tick printing 3866 <1> ; 23/02/2022 3867 0000362B BA[4A0A0000] <1> mov edx, rtc_p ; enable rtc (digital) printing 3868 <1> ; 3869 00003630 EBD5 <1> jmp short emt_1 3870 <1> 3871 <1> ; Original UNIX v1 'sysemt' routine 3872 <1> ;sysemt: 3873 <1> ; 3874 <1> ;jsr r0,arg; 30 / put the argument of the sysemt call 3875 <1> ; / in loc 30 3876 <1> ;cmp 30,$core / was the argument a lower address 3877 <1> ; / than core 3878 <1> ;blo 1f / yes, rtssym 3879 <1> ;cmp 30,$ecore / no, was it higher than "core" 3880 <1> ; / and less than "ecore" 3881 <1> ;blo 2f / yes, sysret2 3882 <1> ;1: 3883 <1> ;mov $rtssym,30 3884 <1> ;2: 3885 <1> ;br sysret2 3886 <1> 3887 <1> ; 01/02/2022 3888 <1> sysilgins: 3889 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3890 <1> ; 03/06/2013 3891 <1> ; Retro UNIX 8086 v1 modification: 3892 <1> ; not a valid system call ! (not in use) 3893 <1> ; 3894 00003632 E953FBFFFF <1> jmp badsys 3895 <1> ;jmp error 3896 <1> ;;jmp sysret 3897 <1> 3898 <1> ; Original UNIX v1 'sysemt' routine 3899 <1> ;sysilgins: / calculate proper illegal instruction trap address 3900 <1> ;jsr r0,arg; 10 / take address from sysilgins call 3901 <1> ;/ put it in loc 8., 3902 <1> ;cmp 10,$core / making it the illegal instruction 3903 <1> ; / trap address 3904 <1> ;blo 1f / is the address a user core address? 3905 <1> ; / yes, go to 2f 3906 <1> ;cmp 10,$ecore 3907 <1> ;blo 2f 3908 <1> ;1: 3909 <1> ;mov $fpsym,10 / no, make 'fpsum' the illegal 3910 <1> ; / instruction trap address for the system 3911 <1> ;2: 3912 <1> ;br sysret2 / return to the caller via 'sysret' 3913 <1> 3914 <1> sysmdate: ; < change the modification time of a file > 3915 <1> ; 23/02/2022 (Retro UNIX 386 v1 feature/modification) 3916 <1> ; (ECX input) 3917 <1> ; 01/02/2022 3918 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 3919 <1> ; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 3920 <1> ; 3921 <1> ; 'sysmdate' is given a file name. It gets inode of this 3922 <1> ; file into core. The user is checked if he is the owner 3923 <1> ; or super user. If he is neither an error occurs. 3924 <1> ; 'setimod' is then called to set the i-node modification 3925 <1> ; byte and the modification time, but the modification time 3926 <1> ; is overwritten by whatever get put on the stack during 3927 <1> ; a 'systime' system call. This calls are restricted to 3928 <1> ; the super user. 3929 <1> ; 3930 <1> ; Calling sequence: 3931 <1> ; sysmdate; name 3932 <1> ; Arguments: 3933 <1> ; name - points to the name of file 3934 <1> ; Inputs: (arguments) 3935 <1> ; Outputs: - 3936 <1> ; ............................................................... 3937 <1> ; 3938 <1> ; Retro UNIX 8086 v1 modification: 3939 <1> ; The user/application program puts address 3940 <1> ; of the file name in BX register 3941 <1> ; as 'sysmdate' system call argument. 3942 <1> ; 3943 <1> ; / change the modification time of a file 3944 <1> ; jsr r0,arg; u.namep / point u.namep to the file name 3945 00003637 891D[18650000] <1> mov [u.namep], ebx 3946 <1> ; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code) 3947 0000363D 890D[80610000] <1> mov [p_time], ecx ; save new modification time to be set 3948 00003643 E899090000 <1> call namei 3949 <1> ; jsr r0,namei / get its i-number 3950 <1> ;;jc error 3951 <1> ; br error2 / no, such file 3952 <1> ;jc fnotfound ; file not found ! 3953 <1> ; 01/02/2022 3954 00003648 7305 <1> jnc short mdate_0 3955 0000364A E9A0FEFFFF <1> jmp fnotfound 3956 <1> mdate_0: 3957 0000364F E8A2110000 <1> call iget 3958 <1> ; jsr r0,iget / get i-node into core 3959 00003654 A0[46650000] <1> mov al, [u.uid] 3960 00003659 3A05[F7610000] <1> cmp al, [i.uid] 3961 <1> ; cmpb u.uid,i.uid / is user same as owner 3962 0000365F 7413 <1> je short mdate_1 3963 <1> ; beq 1f / yes 3964 00003661 20C0 <1> and al, al 3965 <1> ; tstb u.uid / no, is user the super user 3966 <1> ;jnz error 3967 <1> ; bne error2 / no, error 3968 00003663 740F <1> jz short mdate_1 3969 00003665 C705[4F650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 3969 0000366D 0000 <1> 3970 <1> sysstty_err: ; 01/02/2022 3971 0000366F E96DFAFFFF <1> jmp error 3972 <1> mdate_1: ;1: 3973 00003674 E887120000 <1> call setimod 3974 <1> ; jsr r0,setimod / fill in modification data, 3975 <1> ; / time etc. 3976 00003679 BE[80610000] <1> mov esi, p_time 3977 0000367E BF[0E620000] <1> mov edi, i.mtim 3978 00003683 A5 <1> movsd 3979 <1> ; mov 4(sp),i.mtim / move present time to 3980 <1> ; mov 2(sp),i.mtim+2 / modification time 3981 00003684 E978FAFFFF <1> jmp sysret 3982 <1> ; br sysret2 3983 <1> 3984 <1> ; 01/02/2022 3985 <1> sysstty_err_s: 3986 00003689 880D[00650000] <1> mov byte [u.r0], cl ; serial port's tty number 3987 0000368F EBDE <1> jmp short sysstty_err 3988 <1> 3989 <1> sysstty: ; < set tty status and mode > 3990 <1> ; 23/02/2022 3991 <1> ; 22/02/2022 3992 <1> ; 02/02/2022 3993 <1> ; 01/02/2022 (clear screen) 3994 <1> ; 17/11/2015 3995 <1> ; 12/11/2015 3996 <1> ; 29/10/2015 3997 <1> ; 17/10/2015 3998 <1> ; 13/10/2015 3999 <1> ; 29/06/2015 4000 <1> ; 27/06/2015 (Retro UNIX 386 v1 - Beginning) 4001 <1> ; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1) 4002 <1> ; 4003 <1> ; 'sysstty' sets the status and mode of the typewriter 4004 <1> ; whose file descriptor is in (u.r0). 4005 <1> ; 4006 <1> ; Calling sequence: 4007 <1> ; sysstty; arg 4008 <1> ; Arguments: 4009 <1> ; arg - address of 3 consequitive words that contain 4010 <1> ; the source of status data 4011 <1> ; Inputs: ((*u.r0 - file descriptor & argument)) 4012 <1> ; Outputs: ((status in address which is pointed to by arg)) 4013 <1> ; ............................................................... 4014 <1> ; 4015 <1> ; Retro UNIX 8086 v1 modification: 4016 <1> ; 'sysstty' system call will set the tty 4017 <1> ; (clear keyboard buffer and set cursor position) 4018 <1> ; in following manner: 4019 <1> ; NOTE: All of tty setting functions are here (16/01/2014) 4020 <1> ; 4021 <1> ; Inputs: 4022 <1> ; BX = 0 --> means 4023 <1> ; If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022 4024 <1> ; set cursor position for console tty, only 4025 <1> ; CH will be ignored (char. will not be written) 4026 <1> ; If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222 4027 <1> ; set console tty for (current) process 4028 <1> ; CL = tty number (0 to 9) 4029 <1> ; (If CH = 0, character will not be written) 4030 <1> ; If CH > 0 (CL < FFh) 4031 <1> ; CL = tty number (0 to 9) 4032 <1> ; CH = character will be written 4033 <1> ; at requested cursor position (in DX) 4034 <1> ; DX = cursor position for tty number 0 to 7. 4035 <1> ; (only tty number 0 to 7) 4036 <1> ; DL = communication parameters (for serial ports) 4037 <1> ; (only for COM1 and COM2 serial ports) 4038 <1> ; DH < 0FFh -> DL is valid, initialize serial port 4039 <1> ; or set cursor position 4040 <1> ; DH = 0FFh -> DL is not valid 4041 <1> ; do not set serial port parameters 4042 <1> ; or do not set cursor position 4043 <1> ; 4044 <1> ; BX > 0 --> points to name of tty 4045 <1> ; CH > 0 --> 4046 <1> ; CH = character will be written in current 4047 <1> ; cursor position (for tty number from 0 to 7) 4048 <1> ; or character will be sent to serial port 4049 <1> ; (for tty number 8 or 9) 4050 <1> ; CL = color of the character if tty number < 8. 4051 <1> ; CH = 0 --> Do not write a character, 4052 <1> ; set mode (tty 8 to 9) or 4053 <1> ; set current cursor positions (tty 0 to 7) only. 4054 <1> ; DX = cursor position for tty number 0 to 7. 4055 <1> ; DH = FFh --> Do not set cursor pos (or comm. params.) 4056 <1> ; (DL is not valid) 4057 <1> ; DL = communication parameters 4058 <1> ; for tty number 8 or 9 (COM1 or COM2). 4059 <1> ; 4060 <1> ; 01/02/2022 - Retro UNIX 386 v1 - 2022 modification 4061 <1> ; (30/01/2022 - Retro UNIX 8086 - 2022 modification) 4062 <1> ; If CH = 0 & DX = 0FFFFh -> 4063 <1> ; clear screen (video page) & set cursor pos to 0,0. 4064 <1> ; (for tty number 0 to 7, CL <= 7) 4065 <1> ; (if CL = 0FFh -> clear console tty) 4066 <1> ; 4067 <1> ; Outputs: 4068 <1> ; cf = 0 -> OK 4069 <1> ; AL = tty number (0 to 9) 4070 <1> ; AH = line status if tty number is 8 or 9 4071 <1> ; AH = process number (of the caller) 4072 <1> ; cf = 1 means error (requested tty is not ready) 4073 <1> ; AH = FFh if the tty is locked 4074 <1> ; (owned by another process) 4075 <1> ; = process number (of the caller) 4076 <1> ; (if < FFh and tty number < 8) 4077 <1> ; AL = tty number (0FFh if it does not exist) 4078 <1> ; AH = line status if tty number is 8 or 9 4079 <1> ; NOTE: Video page will be cleared if cf = 0. 4080 <1> ; 4081 <1> 4082 <1> ; 27/06/2015 (32 bit modifications) 4083 <1> ; 14/01/2014 4084 00003691 31C0 <1> xor eax, eax 4085 00003693 6648 <1> dec ax ; 17/10/2015 4086 00003695 A3[00650000] <1> mov [u.r0], eax ; 0FFFFh 4087 <1> ;;; 4088 <1> ; 01/02/2022 4089 0000369A FEC1 <1> inc cl ; 0FFh -> 0, 7 -> 8 4090 0000369C 39C2 <1> cmp edx, eax 4091 <1> ;cmp dx, ax ; 0FFFFh 4092 0000369E 7521 <1> jne short sysstty_18 4093 <1> ; clear video page 4094 <1> ; (CH must be 0) 4095 000036A0 08ED <1> or ch, ch 4096 000036A2 75CB <1> jnz short sysstty_err ; invalid parameters 4097 000036A4 80F908 <1> cmp cl, 8 ; > tty7 (serial port?) 4098 000036A7 77C6 <1> ja short sysstty_err ; invalid parameters 4099 000036A9 20C9 <1> and cl, cl 4100 000036AB 7514 <1> jnz short sysstty_18 ; actual tty (video page) num + 1 4101 000036AD 0FB635[49650000] <1> movzx esi, byte [u.uno] 4102 000036B4 8A8E[53620000] <1> mov cl, byte [esi+p.ttyc-1] ; current/console tty 4103 000036BA 80F907 <1> cmp cl, 7 4104 000036BD 77CA <1> ja short sysstty_err_s ; serial port ! 4105 <1> ; here CL contains (actual) tty number (tty0 to tty7) 4106 000036BF FEC1 <1> inc cl ; 0 -> 1, 7 -> 8 4107 <1> sysstty_18: 4108 000036C1 FEC9 <1> dec cl ; 8 -> 7, 1 -> 0 4109 <1> ; cl = video page (tty) number 4110 <1> ;;; 4111 000036C3 21DB <1> and ebx, ebx 4112 <1> ;jnz sysstty_6 4113 <1> ; 01/02/2022 4114 000036C5 7405 <1> jz short sysstty_19 4115 000036C7 E9C2000000 <1> jmp sysstty_6 4116 <1> sysstty_19: 4117 <1> ; set console tty 4118 <1> ; 29/10/2015 4119 <1> ; 17/01/2014 4120 000036CC 80F909 <1> cmp cl, 9 4121 000036CF 7613 <1> jna short sysstty_0 4122 <1> ; 17/11/2015 4123 000036D1 80F9FF <1> cmp cl, 0FFh 4124 000036D4 7202 <1> jb short sysstty_13 4125 000036D6 88CD <1> mov ch, cl ; force CH value to FFh 4126 <1> sysstty_13: 4127 000036D8 8A1D[49650000] <1> mov bl, [u.uno] ; process number 4128 000036DE 8A8B[53620000] <1> mov cl, [ebx+p.ttyc-1] ; current/console tty 4129 <1> sysstty_0: 4130 <1> ; 29/06/2015 4131 <1> ;push dx 4132 <1> ;push cx 4133 <1> ; 01/02/2022 4134 000036E4 52 <1> push edx 4135 000036E5 51 <1> push ecx 4136 000036E6 30D2 <1> xor dl, dl ; sysstty call sign 4137 000036E8 88C8 <1> mov al, cl 4138 000036EA A2[00650000] <1> mov [u.r0], al ; tyy number (0 to 9) 4139 000036EF E8001A0000 <1> call ottyp 4140 <1> ; 01/02/2022 4141 000036F4 59 <1> pop ecx 4142 000036F5 5A <1> pop edx 4143 <1> ;pop cx 4144 <1> ;pop dx 4145 <1> ; 4146 000036F6 7220 <1> jc short sysstty_pd_err 4147 <1> ; 4148 <1> ; 22/02/2022 (Bug!, BugFix) 4149 <1> ; (ebx = ?, modified in ottyp, it may be > 255) 4150 <1> ; 4151 000036F8 80F908 <1> cmp cl, 8 4152 000036FB 720C <1> jb short sysstty_2 4153 <1> ; 4154 000036FD 80FEFF <1> cmp dh, 0FFh 4155 00003700 7407 <1> je short sysstty_2 4156 <1> ; set communication parameters for serial ports 4157 <1> 4158 <1> ; 01/02/2022 4159 <1> ; ; 29/10/2015 4160 <1> ; mov ah, dl ; communication parameters 4161 <1> ; ; ah = 0E3h = 11100011b = 115200 baud, 4162 <1> ; ; THRE int + RDA int 4163 <1> ; ; ah = 23h = 00100011b = 9600 baud, 4164 <1> ; ; THRE int + RDA int 4165 <1> ; sub al, al ; 0 4166 <1> ; ; 12/07/2014 4167 <1> ; cmp cl, 9 4168 <1> ; jb short sysstty_1 4169 <1> ; inc al 4170 <1> ;sysstty_1: 4171 <1> ; ; 01/02/2022 4172 <1> ; push ecx 4173 <1> ; ;push cx 4174 <1> ; ; 29/06/2015 4175 <1> ; call sp_setp ; Set serial port communication parameters 4176 <1> ; mov [u.r0+1], cx ; Line status (ah) 4177 <1> ; ; Modem status (EAX bits 16 to 23) 4178 <1> ; ; 01/02/2022 4179 <1> ; pop ecx 4180 <1> ; ;pop cx 4181 <1> ; jc short sysstty_tmout_err ; 29/10/2015 4182 <1> 4183 <1> ; 01/02/2022 4184 00003702 E832010000 <1> call sysstty_scp 4185 00003707 7276 <1> jc short sysstty_tmout_err ; 29/10/2015 4186 <1> 4187 <1> sysstty_2: 4188 <1> ; 17/01/2014 4189 00003709 20ED <1> and ch, ch ; set cursor position 4190 <1> ; or comm. parameters ONLY 4191 0000370B 7527 <1> jnz short sysstty_3 4192 <1> ; 01/02/2022 4193 0000370D 6683FAFF <1> cmp dx, 0FFFFh 4194 00003711 7214 <1> jb short sysstty_20 4195 <1> ; clear screen (video page) 4196 00003713 E93D010000 <1> jmp sysstty_14 4197 <1> 4198 <1> sysstty_pd_err: ; 29/06/2015 4199 <1> ; 'permission denied !' error 4200 00003718 C705[4F650000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER 4200 00003720 0000 <1> 4201 00003722 E9BAF9FFFF <1> jmp error 4202 <1> 4203 <1> sysstty_20: 4204 00003727 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 4205 0000372E 888B[53620000] <1> mov [ebx+p.ttyc-1], cl ; console tty 4206 <1> sysstty_3: 4207 <1> ; 16/01/2014 4208 00003734 88E8 <1> mov al, ch ; character ; 0 to FFh 4209 <1> ; 17/11/2015 4210 00003736 B507 <1> mov ch, 7 ; Default color (light gray) 4211 00003738 38E9 <1> cmp cl, ch ; 7 (tty number) 4212 <1> ;jna sysstty_9 4213 <1> ; 01/02/2022 4214 0000373A 7705 <1> ja short sysstty_12 4215 0000373C E9C7000000 <1> jmp sysstty_9 4216 <1> 4217 <1> sysstty_12: 4218 <1> ;; BX = 0, CL = 8 or CL = 9 4219 <1> ; (Set specified serial port as console tty port) 4220 <1> ; CH = character to be written 4221 <1> ; 15/04/2014 4222 <1> ; CH = 0 --> initialization only 4223 <1> ; AL = character 4224 <1> ; 26/06/2014 4225 00003741 880D[4E650000] <1> mov [u.ttyn], cl 4226 <1> ; 12/07/2014 4227 00003747 88CC <1> mov ah, cl ; tty number (8 or 9) 4228 <1> ; 02/02/2022 4229 00003749 FEC0 <1> inc al ; 0FFh -> 0, 0 -> 1 4230 0000374B 740B <1> jz short sysstty_4 ; al = ch = 0 4231 0000374D FEC8 <1> dec al ; 1 -> 0 4232 <1> ;and al, al 4233 0000374F 7407 <1> jz short sysstty_4 ; al = ch = 0 4234 <1> ; 04/07/2014 4235 00003751 E8B41E0000 <1> call sndc 4236 <1> ; 12/07/2014 4237 00003756 EB0C <1> jmp short sysstty_5 4238 <1> 4239 <1> sysstty_4: 4240 <1> ; 12/07/2014 4241 <1> ;xchg ah, al ; al = 0 -> al = ah, ah = 0 4242 00003758 88E0 <1> mov al, ah ; 29/06/2015 4243 0000375A 2C08 <1> sub al, 8 4244 <1> ; 27/06/2015 4245 0000375C E836F4FFFF <1> call sp_status ; get serial port status 4246 <1> ; AL = Line status, AH = Modem status 4247 <1> ; 12/11/2015 4248 00003761 3C80 <1> cmp al, 80h 4249 00003763 F5 <1> cmc 4250 <1> sysstty_5: 4251 00003764 66A3[01650000] <1> mov [u.r0+1], ax ; ah = line status 4252 <1> ; EAX bits 16-23 = modem status 4253 0000376A 9C <1> pushf 4254 0000376B 30D2 <1> xor dl, dl ; sysstty call sign 4255 0000376D A0[4E650000] <1> mov al, [u.ttyn] ; 26/06/2014 4256 00003772 E8A01A0000 <1> call cttyp 4257 00003777 9D <1> popf 4258 <1> ;jnc sysret ; time out error 4259 <1> ; 01/02/2022 4260 00003778 7205 <1> jc short sysstty_tmout_err 4261 0000377A E982F9FFFF <1> jmp sysret 4262 <1> 4263 <1> sysstty_tmout_err: 4264 0000377F C705[4F650000]1900- <1> mov dword [u.error], ERR_TIME_OUT 4264 00003787 0000 <1> 4265 00003789 E953F9FFFF <1> jmp error 4266 <1> 4267 <1> sysstty_6: 4268 <1> ;push dx 4269 <1> ;push cx 4270 <1> ; 01/02/2022 4271 0000378E 52 <1> push edx 4272 0000378F 51 <1> push ecx 4273 00003790 891D[18650000] <1> mov [u.namep], ebx 4274 00003796 E846080000 <1> call namei 4275 <1> ; 01/02/2022 4276 0000379B 59 <1> pop ecx 4277 0000379C 5A <1> pop edx 4278 <1> ;pop cx 4279 <1> ;pop dx 4280 0000379D 725A <1> jc short sysstty_inv_dn 4281 <1> ; 4282 0000379F 6683F813 <1> cmp ax, 19 ; inode number of /dev/COM2 4283 000037A3 7754 <1> ja short sysstty_inv_dn ; 27/06/2015 4284 <1> ; 4285 000037A5 3C0A <1> cmp al, 10 ; /dev/tty0 .. /dev/tty7 4286 <1> ; /dev/COM1, /dev/COM2 4287 000037A7 7206 <1> jb short sysstty_7 4288 000037A9 2C0A <1> sub al, 10 4289 <1> ; al = 0 to 9 4290 000037AB 29DB <1> sub ebx, ebx ; 22/02/2022 4291 000037AD EB11 <1> jmp short sysstty_8 4292 <1> 4293 <1> sysstty_7: 4294 000037AF 3C01 <1> cmp al, 1 ; /dev/tty 4295 000037B1 7546 <1> jne short sysstty_inv_dn ; 27/06/2015 4296 000037B3 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 4297 000037BA 8A83[53620000] <1> mov al, [ebx+p.ttyc-1] ; console tty 4298 <1> sysstty_8: 4299 <1> ; 22/02/2022 4300 <1> ; (ebx < 256) 4301 000037C0 A2[00650000] <1> mov [u.r0], al 4302 <1> ; 01/02/2022 4303 <1> ;push dx 4304 <1> ;push ax 4305 <1> ;push cx 4306 000037C5 52 <1> push edx 4307 000037C6 50 <1> push eax 4308 000037C7 51 <1> push ecx 4309 000037C8 E827190000 <1> call ottyp 4310 000037CD 59 <1> pop ecx 4311 000037CE 58 <1> pop eax 4312 000037CF 5A <1> pop edx 4313 <1> ;pop cx 4314 <1> ;pop ax 4315 <1> ;pop dx 4316 <1> ;jc sysstty_pd_err ; 'permission denied !' 4317 <1> ; 01/02/2022 4318 000037D0 7305 <1> jnc short sysstty_21 4319 000037D2 E941FFFFFF <1> jmp sysstty_pd_err ; 'permission denied !' 4320 <1> sysstty_21: 4321 <1> ; 29/10/2015 4322 000037D7 86E9 <1> xchg ch, cl 4323 <1> ; cl = character, ch = color code 4324 000037D9 86C1 <1> xchg al, cl 4325 <1> ; al = character, cl = tty number 4326 000037DB 80F907 <1> cmp cl, 7 4327 <1> ;ja sysstty_12 4328 <1> ; 01/02/2022 4329 000037DE 7628 <1> jna short sysstty_16 4330 <1> ;; 4331 000037E0 80FEFF <1> cmp dh, 0FFh 4332 000037E3 740B <1> je short sysstty_22 ; do not set comm. parameters 4333 <1> 4334 <1> ; 01/02/2022 4335 <1> ; ; 29/10/2015 4336 <1> ; mov ah, dl ; communication parameters 4337 <1> ; ; ah = 0E3h = 11100011b = 115200 baud, 4338 <1> ; ; THRE int + RDA int 4339 <1> ; ; ah = 23h = 00100011b = 9600 baud, 4340 <1> ; ; THRE int + RDA int 4341 <1> ; sub al, al ; 0 4342 <1> ; ; 12/07/2014 4343 <1> ; cmp cl, 9 4344 <1> ; jb short sysstty_1 4345 <1> ; inc al 4346 <1> ;sysstty_1: 4347 <1> ; ; 01/02/2022 4348 <1> ; push ecx 4349 <1> ; ;push cx 4350 <1> ; ; 29/06/2015 4351 <1> ; call sp_setp ; Set serial port communication parameters 4352 <1> ; mov [u.r0+1], cx ; Line status (ah) 4353 <1> ; ; Modem status (EAX bits 16 to 23) 4354 <1> ; ; 01/02/2022 4355 <1> ; pop ecx 4356 <1> ; ;pop cx 4357 <1> ; jc short sysstty_tmout_err ; 29/10/2015 4358 <1> 4359 <1> ; 02/02/2022 4360 000037E5 88C5 <1> mov ch, al ; save char 4361 <1> ; 01/02/2022 4362 000037E7 E84D000000 <1> call sysstty_scp 4363 000037EC 7291 <1> jc short sysstty_tmout_err ; 29/10/2015 4364 <1> ; 02/02/2022 4365 000037EE 88E8 <1> mov al, ch ; restore char 4366 <1> sysstty_22: 4367 <1> ; 01/02/2022 4368 000037F0 08ED <1> or ch, ch 4369 000037F2 7437 <1> jz short sysstty_11 ; do not send char to terminal 4370 <1> ; send char to (serial port) terminal 4371 <1> ; al = character 4372 <1> ; cl = tty number (8 or 9) 4373 000037F4 E948FFFFFF <1> jmp sysstty_12 ; (tty8 or tty9) 4374 <1> 4375 <1> sysstty_inv_dn: 4376 <1> ; 27/06/2015 4377 <1> ; Invalid device name (not a tty) ! error 4378 <1> ; (Device is not a tty or device name not found) 4379 000037F9 C705[4F650000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 4379 00003801 0000 <1> 4380 00003803 E9D9F8FFFF <1> jmp error 4381 <1> 4382 <1> sysstty_16: 4383 <1> ; 22/02/2022 4384 <1> ; 16/01/2014 4385 <1> ;xor bh, bh 4386 <1> sysstty_9: ; tty 0 to tty 7 4387 <1> ; al = character 4388 <1> ; ch = color/attribute ; 01/02/2022 4389 <1> ; 4390 <1> ; 22/02/2022 (BugFix) 4391 <1> ; (ebx may be > 255 here!? due to 'ottyp') 4392 00003808 29DB <1> sub ebx, ebx ; * 4393 0000380A 88CB <1> mov bl, cl ; (tty number = video page number) 4394 <1> ; 4395 0000380C 80FEFF <1> cmp dh, 0FFh ; Do not set cursor position 4396 0000380F 7409 <1> je short sysstty_10 4397 <1> ; 02/02/2022 4398 00003811 51 <1> push ecx 4399 00003812 50 <1> push eax 4400 <1> ;push cx 4401 <1> ;push ax 4402 <1> ; 22/02/2022 4403 <1> ;;movzx ebx, cl ; * 4404 <1> ;mov bl, cl ; (tty number = video page number) 4405 00003813 E8A7DBFFFF <1> call set_cpos 4406 <1> ;pop ax 4407 <1> ;pop cx 4408 <1> ; 02/02/2022 4409 00003818 58 <1> pop eax 4410 00003819 59 <1> pop ecx 4411 <1> sysstty_10: 4412 <1> ; 29/10/2015 4413 0000381A 08C0 <1> or al, al ; character 4414 0000381C 740D <1> jz short sysstty_11 ; al = 0 4415 <1> ; 17/11/2015 4416 0000381E 3CFF <1> cmp al, 0FFh 4417 00003820 7309 <1> jnb short sysstty_11 4418 <1> ; ch > 0 and ch < FFh 4419 <1> ; write a character at current cursor position 4420 00003822 88EC <1> mov ah, ch ; color/attribute 4421 <1> ; 12/07/2014 4422 <1> ;push cx 4423 <1> ; 02/02/2022 4424 00003824 51 <1> push ecx 4425 00003825 E87DDCFFFF <1> call write_c_current 4426 <1> ;pop cx 4427 <1> ; 02/02/2022 4428 0000382A 59 <1> pop ecx 4429 <1> sysstty_11: 4430 <1> ; 14/01/2014 4431 0000382B 30D2 <1> xor dl, dl ; sysstty call sign 4432 <1> ; 18/01/2014 4433 <1> ;movzx eax, cl ; 27/06/2015 4434 0000382D 88C8 <1> mov al, cl 4435 0000382F E8E3190000 <1> call cttyp 4436 00003834 E9C8F8FFFF <1> jmp sysret 4437 <1> 4438 <1> sysstty_scp: 4439 <1> ; 02/02/2022 4440 <1> ; set communication parameters (for COM1 or COM2) 4441 <1> ; 01/02/2022 4442 <1> ; 4443 <1> ; 29/10/2015 4444 00003839 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 0000383B 28C0 <1> sub al, al ; 0 4450 <1> ; 12/07/2014 4451 0000383D 80F909 <1> cmp cl, 9 4452 00003840 7202 <1> jb short sysstty_1 4453 00003842 FEC0 <1> inc al 4454 <1> sysstty_1: 4455 <1> ; 02/02/2022 4456 00003844 52 <1> push edx 4457 <1> ; 01/02/2022 4458 00003845 51 <1> push ecx 4459 <1> ;push cx 4460 <1> ; 29/06/2015 4461 00003846 E854F3FFFF <1> call sp_setp ; Set serial port communication parameters 4462 0000384B 66890D[01650000] <1> mov [u.r0+1], cx ; Line status (ah) 4463 <1> ; Modem status (EAX bits 16 to 23) 4464 <1> ; 01/02/2022 4465 00003852 59 <1> pop ecx 4466 <1> ;pop cx 4467 00003853 5A <1> pop edx ; 02/02/2022 4468 <1> ; 01/02/2022 4469 <1> ; if cf = 1 -> sysstty_tmout_err 4470 00003854 C3 <1> retn 4471 <1> 4472 <1> sysstty_14: 4473 <1> ; 23/02/2022 4474 <1> ; 02/02/2022 4475 <1> ; ch = 0 4476 <1> ; cl = video page 4477 <1> ; 4478 <1> ; dx = 0FFFFh 4479 <1> ; clear screen (video page) 4480 <1> ; 4481 <1> 4482 <1> ; 02/02/2022 4483 <1> ; clear screen 4484 <1> ; 4485 <1> ; (modified registers: eax, ebx, ecx, edx, esi, edi) 4486 <1> 4487 <1> ; 23/02/2022 4488 00003855 88CB <1> mov bl, cl ; CL = tty number (0 to 7) 4489 <1> 4490 <1> ; clear video page 4491 00003857 E810000000 <1> call wttyc ; 23/02/2022 4492 <1> 4493 <1> ; 23/02/2022 4494 0000385C 88D8 <1> mov al, bl 4495 0000385E 8A25[49650000] <1> mov ah, [u.uno] 4496 00003864 66A3[00650000] <1> mov [u.r0], ax 4497 0000386A EBBF <1> jmp short sysstty_11 4498 <1> 4499 <1> vp_clr: ; 27/02/2022 4500 <1> wttyc: 4501 <1> ; 23/02/2022 4502 <1> ; (clear video page) 4503 <1> ; INPUT: 4504 <1> ; bl = video page (0 to 7) 4505 <1> ; 4506 <1> ; Modified registers: eax, ecx, edx, esi, edi 4507 <1> 4508 <1> ;xor dx, dx ; column 0, row 0 4509 <1> ;;inc dx ; 0 ; 23/02/2022 4510 <1> ; 4511 <1> ; movzx ebx, cl 4512 <1> ; mov bl, cl ; CL = tty number (0 to 7) ; 23/02/2022 4513 <1> 4514 <1> ; shl bl, 1 4515 <1> ; mov al, byte ptr [ebx+ttyl] 4516 <1> ; ; AL = lock value (0 or process number) 4517 <1> ; or al, al 4518 <1> ; jz short @f 4519 <1> ; cmp al, byte ptr [u.uno] ; process number 4520 <1> ; jne short sysstty_15 4521 <1> ; ; only the owner can clear its video page 4522 <1> ; xor al, al ; 0 4523 <1> ;@@: 4524 <1> ; ;mov bl, cl 4525 <1> ; shr bl, 1 4526 <1> 4527 0000386C 30C0 <1> xor al, al ; 0 4528 0000386E B407 <1> mov ah, 07h ; attribute/color (default) 4529 <1> 4530 <1> ; scroll_up input: 4531 <1> ; 4532 <1> ; al = line count (0 or 1) ((0 == clear video page)) 4533 <1> ; ((al = 1 for write_tty (putc) procedure)) 4534 <1> ; ah = attribute to be used on blanked line 4535 <1> ; bl = video page number (0 to 7) 4536 <1> 4537 00003870 E8D0DBFFFF <1> call scroll_up ; clear video page (al=0) 4538 <1> 4539 <1> ; (modified registers: eax, ecx, edx, esi, edi) 4540 <1> 4541 <1> ; bl = video page number (0 to 7) 4542 <1> ;xor dx, dx ; column 0, row 0 4543 <1> ; 02/02/2022 4544 00003875 31D2 <1> xor edx, edx 4545 <1> ; 23/02/2022 4546 <1> ;call set_cpos 4547 <1> ;retn 4548 00003877 E943DBFFFF <1> jmp set_cpos 4549 <1> 4550 <1> ;mov al, bl 4551 <1> ;mov ah, [u.uno] 4552 <1> ;mov [u.r0], ax 4553 <1> ;jmp short sysstty_11 4554 <1> 4555 <1> ;sysstty_15: 4556 <1> ; ; 30/01/2022 4557 <1> ; ; permission (denied) error 4558 <1> ; ;xor dl, dl ; sysstty call sign 4559 <1> ; mov al, cl 4560 <1> ; sub ah, ah ; 0 4561 <1> ; call cttyp 4562 <1> ; jmp error 4563 <1> 4564 <1> ; Original UNIX v1 'sysstty' routine: 4565 <1> ; gtty: 4566 <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments 4567 <1> ;jsr r0,gtty / r1 will have offset to tty block, 4568 <1> ; / r2 has source 4569 <1> ;mov r2,-(sp) 4570 <1> ;mov r1,-(sp) / put r1 and r2 on the stack 4571 <1> ;1: / flush the clist wait till typewriter is quiescent 4572 <1> ;mov (sp),r1 / restore r1 to tty block offset 4573 <1> ;movb tty+3(r1),0f / put cc offset into getc argument 4574 <1> ;mov $240,*$ps / set processor priority to 5 4575 <1> ;jsr r0,getc; 0:../ put character from clist in r1 4576 <1> ; br .+4 / list empty, skip branch 4577 <1> ;br 1b / get another character until list is empty 4578 <1> ;mov 0b,r1 / move cc offset to r1 4579 <1> ;inc r1 / bump it for output clist 4580 <1> ;tstb cc(r1) / is it 0 4581 <1> ;beq 1f / yes, no characters to output 4582 <1> ;mov r1,0f / no, put offset in sleep arg 4583 <1> ;jsr r0,sleep; 0:.. / put tty output process to sleep 4584 <1> ;br 1b / try to calm it down again 4585 <1> ;1: 4586 <1> ;mov (sp)+,r1 4587 <1> ;mov (sp)+,r2 / restore registers 4588 <1> ;mov (r2)+,r3 / put reader control status in r3 4589 <1> ;beq 1f / if 0, 1f 4590 <1> ;mov r3,rcsr(r1) / move r.c. status to reader 4591 <1> ; / control status register 4592 <1> ;1: 4593 <1> ;mov (r2)+,r3 / move pointer control status to r3 4594 <1> ;beq 1f / if 0 1f 4595 <1> ;mov r3,tcsr(r1) / move p.c. status to printer 4596 <1> ; / control status reg 4597 <1> ;1: 4598 <1> ;mov (r2)+,tty+4(r1) / move to flag byte of tty block 4599 <1> ;jmp sysret2 / return to user 4600 <1> 4601 <1> sysgtty: ; < get tty status > 4602 <1> ; 22/02/2022 4603 <1> ; 01/02/2022 4604 <1> ; 23/11/2015 4605 <1> ; 29/10/2015 4606 <1> ; 17/10/2015 4607 <1> ; 28/06/2015 (Retro UNIX 386 v1 - Beginning) 4608 <1> ; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1) 4609 <1> ; 4610 <1> ; 'sysgtty' gets the status of tty in question. 4611 <1> ; It stores in the three words addressed by it's argument 4612 <1> ; the status of the typewriter whose file descriptor 4613 <1> ; in (u.r0). 4614 <1> ; 4615 <1> ; Calling sequence: 4616 <1> ; sysgtty; arg 4617 <1> ; Arguments: 4618 <1> ; arg - address of 3 words destination of the status 4619 <1> ; Inputs: ((*u.r0 - file descriptor)) 4620 <1> ; Outputs: ((status in address which is pointed to by arg)) 4621 <1> ; ............................................................... 4622 <1> ; 4623 <1> ; Retro UNIX 8086 v1 modification: 4624 <1> ; 'sysgtty' system call will return status of tty 4625 <1> ; (keyboard, serial port and video page status) 4626 <1> ; in following manner: 4627 <1> ; 4628 <1> ; Inputs: 4629 <1> ; BX = 0 --> means 4630 <1> ; CH = 0 --> 'return status of the console tty' 4631 <1> ; for (current) process 4632 <1> ; CL = 0 --> return keyboard status (tty 0 to 9) 4633 <1> ; CL = 1 --> return video page status (tty 0 to 7) 4634 <1> ; CL = 1 --> return serial port status (tty 8 & 9) 4635 <1> ; CH > 0 --> tty number + 1 4636 <1> ; 4637 <1> ; BX > 0 --> points to name of tty 4638 <1> ; CL = 0 --> return keyboard status 4639 <1> ; CL = 1 --> return video page status 4640 <1> ; CH = undefined 4641 <1> ; 4642 <1> ; Outputs: 4643 <1> ; cf = 0 -> 4644 <1> ; 4645 <1> ; AL = tty number from 0 to 9 4646 <1> ; (0 to 7 is also the video page of the tty) 4647 <1> ; AH = 0 if the tty is free/unused 4648 <1> ; AH = the process number of the caller 4649 <1> ; AH = FFh if the tty is locked by another process 4650 <1> ; 4651 <1> ; (if calling is for serial port status) 4652 <1> ; BX = serial port status if tty number is 8 or 9 4653 <1> ; (BH = modem status, BL = Line status) 4654 <1> ; CX = 0FFFFh (if data is ready) 4655 <1> ; CX = 0 (if data is not ready or undefined) 4656 <1> ; 4657 <1> ; (if calling is for keyboard status) 4658 <1> ; BX = current character in tty/keyboard buffer 4659 <1> ; (BH = scan code, BL = ascii code) 4660 <1> ; (BX=0 if there is not a waiting character) 4661 <1> ; CX is undefined 4662 <1> ; 4663 <1> ; (if calling is for video page status) 4664 <1> ; BX = cursor position on the video page 4665 <1> ; if tty number < 8 4666 <1> ; (BH = row, BL = column) 4667 <1> ; CX = current character (in cursor position) 4668 <1> ; on the video page of the tty 4669 <1> ; if tty number < 8 4670 <1> ; (CH = color, CL = character) 4671 <1> ; 4672 <1> ; cf = 1 means error (requested tty is not ready) 4673 <1> ; 4674 <1> ; AH = FFh if the caller is not owner of 4675 <1> ; specified tty or console tty 4676 <1> ; AL = tty number (0FFh if it does not exist) 4677 <1> ; BX, CX are undefined if cf = 1 4678 <1> ; 4679 <1> ; (If tty number is 8 or 9) 4680 <1> ; AL = tty number 4681 <1> ; AH = the process number of the caller 4682 <1> ; BX = serial port status 4683 <1> ; (BH = modem status, BL = Line status) 4684 <1> ; CX = 0 4685 <1> ; 4686 <1> 4687 <1> gtty: ; get (requested) tty number 4688 <1> ; 22/02/2022 4689 <1> ; 01/02/2022 4690 <1> ; 17/10/2015 4691 <1> ; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications) 4692 <1> ; 30/05/2013 - 12/07/2014 4693 <1> ; Retro UNIX 8086 v1 modification ! 4694 <1> ; 4695 <1> ; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP)) 4696 <1> ; 4697 <1> ; 28/06/2015 (32 bit modifications) 4698 <1> ; 16/01/2014 4699 0000387C 31C0 <1> xor eax, eax 4700 0000387E 6648 <1> dec ax ; 17/10/2015 4701 00003880 A3[00650000] <1> mov [u.r0], eax ; 0FFFFh 4702 00003885 80F901 <1> cmp cl, 1 4703 00003888 760F <1> jna short sysgtty_0 4704 <1> sysgtty_invp: 4705 <1> ; 28/06/2015 4706 0000388A C705[4F650000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 4706 00003892 0000 <1> 4707 00003894 E948F8FFFF <1> jmp error 4708 <1> sysgtty_0: 4709 00003899 21DB <1> and ebx, ebx 4710 0000389B 742E <1> jz short sysgtty_1 4711 <1> ; 4712 0000389D 891D[18650000] <1> mov [u.namep], ebx 4713 <1> ;push cx ; 23/11/2015 4714 <1> ; 01/02/2022 4715 000038A3 51 <1> push ecx 4716 000038A4 E838070000 <1> call namei 4717 <1> ; 01/02/2022 4718 000038A9 59 <1> pop ecx 4719 <1> ;pop cx ; 23/11/2015 4720 000038AA 7210 <1> jc short sysgtty_inv_dn ; 28/06/2015 4721 <1> ; 4722 000038AC 6683F801 <1> cmp ax, 1 4723 000038B0 7622 <1> jna short sysgtty_2 4724 <1> ; 01/02/2022 4725 000038B2 20E4 <1> and ah, ah 4726 000038B4 7506 <1> jnz short sysgtty_inv_dn 4727 <1> ;sub ax, 10 4728 000038B6 2C0A <1> sub al, 10 4729 000038B8 3C09 <1> cmp al, 9 4730 <1> ;cmp ax, 9 4731 <1> ;ja short sysgtty_inv_dn 4732 <1> ;mov ch, al 4733 <1> ;jmp short sysgtty_4 4734 <1> ; 23/11/2015 4735 000038BA 7629 <1> jna short sysgtty_4 4736 <1> sysgtty_inv_dn: 4737 <1> ; 28/06/2015 4738 <1> ; Invalid device name (not a tty) ! error 4739 <1> ; (Device is not a tty or device name not found) 4740 000038BC C705[4F650000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 4740 000038C4 0000 <1> 4741 000038C6 E916F8FFFF <1> jmp error 4742 <1> sysgtty_1: 4743 <1> ; 16/01/2014 4744 000038CB 80FD0A <1> cmp ch, 10 4745 000038CE 77BA <1> ja short sysgtty_invp ; 28/06/2015 4746 000038D0 FECD <1> dec ch ; 0 -> FFh (negative) 4747 000038D2 790F <1> jns short sysgtty_3 ; not negative 4748 <1> ; 4749 <1> sysgtty_2: 4750 <1> ; get tty number of console tty 4751 000038D4 8A25[49650000] <1> mov ah, [u.uno] 4752 <1> ; 28/06/2015 4753 000038DA 0FB6DC <1> movzx ebx, ah 4754 000038DD 8AAB[53620000] <1> mov ch, [ebx+p.ttyc-1] 4755 <1> sysgtty_3: 4756 000038E3 88E8 <1> mov al, ch 4757 <1> sysgtty_4: 4758 000038E5 A2[00650000] <1> mov [u.r0], al 4759 <1> ; 28/06/2015 4760 <1> ;cmp al, 9 4761 <1> ;ja short sysgtty_invp 4762 000038EA 8B2D[FC640000] <1> mov ebp, [u.usp] 4763 <1> ; 23/11/2015 4764 000038F0 20C9 <1> and cl, cl 4765 000038F2 7432 <1> jz short sysgtty_6 ; keyboard status 4766 000038F4 3C08 <1> cmp al, 8 ; cmp ch, 8 4767 000038F6 722E <1> jb short sysgtty_6 ; video page status 4768 <1> ; serial port status 4769 <1> ; 12/07/2014 4770 <1> ;mov dx, 0 4771 <1> ;je short sysgtty_5 4772 <1> ;inc dl 4773 <1> ;sysgtty_5: 4774 <1> ; 28/06/2015 4775 000038F8 2C08 <1> sub al, 8 4776 000038FA E898F2FFFF <1> call sp_status ; serial (COM) port (line) status 4777 <1> ; AL = Line status, AH = Modem status 4778 000038FF 66894510 <1> mov [ebp+16], ax ; serial port status (in EBX) 4779 00003903 8A25[49650000] <1> mov ah, [u.uno] 4780 00003909 8825[01650000] <1> mov [u.r0+1], ah 4781 0000390F 66C745180000 <1> mov word [ebp+24], 0 ; data status (0 = not ready) 4782 <1> ; (in ECX) 4783 00003915 A880 <1> test al, 80h 4784 00003917 7561 <1> jnz short sysgtty_dnr_err ; 29/06/2015 4785 00003919 A801 <1> test al, 1 4786 <1> ;jz sysret 4787 0000391B 7404 <1> jz short sysgtty_10 ; 22/02/2022 4788 0000391D 66FF4D18 <1> dec word [ebp+24] ; data status (FFFFh = ready) 4789 <1> sysgtty_10: 4790 00003921 E9DBF7FFFF <1> jmp sysret 4791 <1> sysgtty_6: 4792 00003926 A2[4E650000] <1> mov [u.ttyn], al ; tty number 4793 <1> ;movzx ebx, al 4794 0000392B 88C3 <1> mov bl, al ; tty number (0 to 9) 4795 0000392D D0E3 <1> shl bl, 1 ; aligned to word 4796 <1> ; 22/04/2014 - 29/06/2015 4797 0000392F 81C3[84610000] <1> add ebx, ttyl 4798 00003935 8A23 <1> mov ah, [ebx] 4799 00003937 3A25[49650000] <1> cmp ah, [u.uno] 4800 0000393D 7404 <1> je short sysgtty_7 4801 0000393F 20E4 <1> and ah, ah 4802 <1> ;jz short sysgtty_7 4803 00003941 7506 <1> jnz short sysgtty_8 4804 <1> ;mov ah, 0FFh 4805 <1> sysgtty_7: 4806 00003943 8825[01650000] <1> mov [u.r0+1], ah 4807 <1> sysgtty_8: 4808 00003949 08C9 <1> or cl, cl 4809 0000394B 7510 <1> jnz short sysgtty_9 4810 0000394D B001 <1> mov al, 1 ; test a key is available 4811 0000394F E8391C0000 <1> call getc 4812 00003954 66894510 <1> mov [ebp+16], ax ; bx, character 4813 00003958 E9A4F7FFFF <1> jmp sysret 4814 <1> sysgtty_9: 4815 0000395D 8A1D[4E650000] <1> mov bl, [u.ttyn] 4816 <1> ; bl = video page number 4817 00003963 E8961D0000 <1> call get_cpos 4818 <1> ; dx = cursor position 4819 00003968 66895510 <1> mov [ebp+16], dx ; bx 4820 <1> ;mov bl, [u.ttyn] 4821 <1> ; bl = video page number 4822 0000396C E89E1D0000 <1> call read_ac_current 4823 <1> ; ax = character and attribute/color 4824 00003971 66894518 <1> mov [ebp+24], ax ; cx 4825 00003975 E987F7FFFF <1> jmp sysret 4826 <1> sysgtty_dnr_err: 4827 <1> ; 'device not responding !' error 4828 <1> ;mov dword [u.error], ERR_TIME_OUT ; 25 4829 0000397A C705[4F650000]1900- <1> mov dword [u.error], ERR_DEV_NOT_RESP ; 25 4829 00003982 0000 <1> 4830 00003984 E958F7FFFF <1> jmp error 4831 <1> 4832 <1> ; Original UNIX v1 'sysgtty' routine: 4833 <1> ; sysgtty: 4834 <1> ;jsr r0,gtty / r1 will have offset to tty block, 4835 <1> ; / r2 has destination 4836 <1> ;mov rcsr(r1),(r2)+ / put reader control status 4837 <1> ; / in 1st word of dest 4838 <1> ;mov tcsr(r1),(r2)+ / put printer control status 4839 <1> ; / in 2nd word of dest 4840 <1> ;mov tty+4(r1),(r2)+ / put mode in 3rd word 4841 <1> ;jmp sysret2 / return to user 4842 <1> 4843 <1> ; Original UNIX v1 'gtty' routine: 4844 <1> ; gtty: 4845 <1> ;jsr r0,arg; u.off / put first arg in u.off 4846 <1> ;mov *u.r0,r1 / put file descriptor in r1 4847 <1> ;jsr r0,getf / get the i-number of the file 4848 <1> ;tst r1 / is it open for reading 4849 <1> ;bgt 1f / yes 4850 <1> ;neg r1 / no, i-number is negative, 4851 <1> ; / so make it positive 4852 <1> ;1: 4853 <1> ;sub $14.,r1 / get i-number of tty0 4854 <1> ;cmp r1,$ntty-1 / is there such a typewriter 4855 <1> ;bhis error9 / no, error 4856 <1> ;asl r1 / 0%2 4857 <1> ;asl r1 / 0%4 / yes 4858 <1> ;asl r1 / 0%8 / multiply by 8 so r1 points to 4859 <1> ; ; / tty block 4860 <1> ;mov u.off,r2 / put argument in r2 4861 <1> ;rts r0 / return 2053 %include 'u2.s' ; 11/05/2015 2054 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS2.INC 2055 <1> ; Last Modification: 15/05/2022 2056 <1> ; ---------------------------------------------------------------------------- 2057 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2058 <1> ; (v0.1 - Beginning: 11/07/2012) 2059 <1> ; 2060 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2061 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2062 <1> ; 2063 <1> ; 2064 <1> ; 2065 <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s 2066 <1> ; 2067 <1> ; **************************************************************************** 2068 <1> ; 03/01/2016 2069 <1> 2070 <1> syslink: 2071 <1> ; 03/02/2022 2072 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2073 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 2074 <1> ; 2075 <1> ; 'syslink' is given two arguments, name 1 and name 2. 2076 <1> ; name 1 is a file that already exists. name 2 is the name 2077 <1> ; given to the entry that will go in the current directory. 2078 <1> ; name2 will then be a link to the name 1 file. The i-number 2079 <1> ; in the name 2 entry of current directory is the same 2080 <1> ; i-number for the name 1 file. 2081 <1> ; 2082 <1> ; Calling sequence: 2083 <1> ; syslink; name 1; name 2 2084 <1> ; Arguments: 2085 <1> ; name 1 - file name to which link will be created. 2086 <1> ; name 2 - name of entry in current directory that 2087 <1> ; links to name 1. 2088 <1> ; Inputs: - 2089 <1> ; Outputs: - 2090 <1> ; ............................................................... 2091 <1> ; 2092 <1> ; Retro UNIX 8086 v1 modification: 2093 <1> ; 'syslink' system call has two arguments; so, 2094 <1> ; * 1st argument, name 1 is pointed to by BX register 2095 <1> ; * 2nd argument, name 2 is pointed to by CX register 2096 <1> ; 2097 <1> ; / name1, name2 2098 <1> ;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd 2099 00003989 891D[18650000] <1> mov [u.namep], ebx 2100 0000398F 51 <1> push ecx 2101 00003990 E84C060000 <1> call namei 2102 <1> ; jsr r0,namei / find the i-number associated with 2103 <1> ; / the 1st path name 2104 <1> ;;and ax, ax 2105 <1> ;;jz error ; File not found 2106 <1> ;jc error 2107 <1> ; br error9 / cannot be found 2108 00003995 730F <1> jnc short syslink0 2109 <1> ;pop ecx 2110 <1> ; 'file not found !' error 2111 00003997 C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 2111 0000399F 0000 <1> 2112 000039A1 E93BF7FFFF <1> jmp error 2113 <1> syslink0: 2114 000039A6 E84B0E0000 <1> call iget 2115 <1> ; jsr r0,iget / get the i-node into core 2116 000039AB 8F05[18650000] <1> pop dword [u.namep] ; ecx 2117 <1> ; mov (sp)+,u.namep / u.namep points to 2nd name 2118 <1> ; 03/02/2022 2119 000039B1 50 <1> push eax 2120 <1> ;push ax 2121 <1> ; mov r1,-(sp) / put i-number of name1 on the stack 2122 <1> ; / (a link to this file is to be created) 2123 000039B2 66FF35[E4640000] <1> push word [cdev] 2124 <1> ; mov cdev,-(sp) / put i-nodes device on the stack 2125 000039B9 E852000000 <1> call isdir 2126 <1> ; jsr r0,isdir / is it a directory 2127 000039BE E81E060000 <1> call namei 2128 <1> ; jsr r0,namei / no, get i-number of name2 2129 <1> ;jnc error 2130 <1> ; br .+4 / not found 2131 <1> ; / so r1 = i-number of current directory 2132 <1> ; / ii = i-number of current directory 2133 <1> ; br error9 / file already exists., error 2134 000039C3 720F <1> jc short syslink1 2135 <1> ; pop ax 2136 <1> ; pop ax 2137 <1> ; 'file exists !' error 2138 000039C5 C705[4F650000]0E00- <1> mov dword [u.error], ERR_FILE_EXISTS ; 14 2138 000039CD 0000 <1> 2139 000039CF E90DF7FFFF <1> jmp error 2140 <1> syslink1: 2141 000039D4 6659 <1> pop cx 2142 <1> ;cmp cx, [cdev] 2143 000039D6 3A0D[E4640000] <1> cmp cl, [cdev] 2144 <1> ;jne error 2145 <1> ; cmp (sp)+,cdev / u.dirp now points to 2146 <1> ; / end of current directory 2147 <1> ; bne error9 2148 000039DC 740F <1> je short syslink2 2149 <1> ; 'not same drive !' error 2150 000039DE C705[4F650000]1500- <1> mov dword [u.error], ERR_DRV_NOT_SAME ; 21 2150 000039E6 0000 <1> 2151 000039E8 E9F4F6FFFF <1> jmp error 2152 <1> syslink2: 2153 <1> ;pop ax 2154 <1> ;push ax 2155 <1> ; 03/02/2022 2156 <1> ;mov eax, [esp] 2157 000039ED 58 <1> pop eax 2158 000039EE 50 <1> push eax 2159 000039EF 66A3[32650000] <1> mov [u.dirbuf], ax 2160 <1> ; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf 2161 000039F5 E89E000000 <1> call mkdir 2162 <1> ; jsr r0,mkdir / make directory entry for name2 2163 <1> ; / in current directory 2164 <1> ; 03/02/2022 2165 000039FA 58 <1> pop eax 2166 <1> ;pop ax 2167 <1> ; mov (sp)+,r1 / r1 has i-number of name1 2168 000039FB E8F60D0000 <1> call iget 2169 <1> ; jsr r0,iget / get i-node into core 2170 00003A00 FE05[F6610000] <1> inc byte [i.nlks] 2171 <1> ; incb i.nlks / add 1 to its number of links 2172 00003A06 E8F50E0000 <1> call setimod 2173 <1> ; jsr r0,setimod / set the i-node modified flag 2174 00003A0B E9F1F6FFFF <1> jmp sysret 2175 <1> 2176 <1> isdir: 2177 <1> ; 03/02/2022 2178 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 2179 <1> ; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 2180 <1> ; 2181 <1> ; 'isdir' check to see if the i-node whose i-number is in r1 2182 <1> ; is a directory. If it is, an error occurs, because 'isdir' 2183 <1> ; called by syslink and sysunlink to make sure directories 2184 <1> ; are not linked. If the user is the super user (u.uid=0), 2185 <1> ; 'isdir' does not bother checking. The current i-node 2186 <1> ; is not disturbed. 2187 <1> ; 2188 <1> ; INPUTS -> 2189 <1> ; r1 - contains the i-number whose i-node is being checked. 2190 <1> ; u.uid - user id 2191 <1> ; OUTPUTS -> 2192 <1> ; r1 - contains current i-number upon exit 2193 <1> ; (current i-node back in core) 2194 <1> ; 2195 <1> ; ((AX = R1)) 2196 <1> ; 2197 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 2198 <1> ; 2199 <1> 2200 <1> ; / if the i-node whose i-number is in r1 is a directory 2201 <1> ; / there is an error unless super user made the call 2202 <1> 2203 00003A10 803D[46650000]00 <1> cmp byte [u.uid], 0 2204 <1> ; tstb u.uid / super user 2205 00003A17 762B <1> jna short isdir1 2206 <1> ; beq 1f / yes, don't care 2207 00003A19 66FF35[E0640000] <1> push word [ii] 2208 <1> ; mov ii,-(sp) / put current i-number on stack 2209 00003A20 E8D10D0000 <1> call iget 2210 <1> ; jsr r0,iget / get i-node into core (i-number in r1) 2211 <1> ; 03/02/2022 2212 00003A25 F605[F5610000]40 <1> test byte [i.flgs+1], 40h 2213 <1> ;test word [i.flgs], 4000h ; Bit 14 : Directory flag 2214 <1> ; bit $40000,i.flgs / is it a directory 2215 <1> ;jnz error 2216 <1> ; bne error9 / yes, error 2217 00003A2C 740F <1> jz short isdir0 2218 00003A2E C705[4F650000]0B00- <1> mov dword [u.error], ERR_NOT_FILE ; 11 ; ERR_DIR_ACCESS 2218 00003A36 0000 <1> 2219 <1> ; 'permission denied !' error 2220 <1> ;pop ax 2221 00003A38 E9A4F6FFFF <1> jmp error 2222 <1> isdir0: 2223 00003A3D 6658 <1> pop ax 2224 <1> ; mov (sp)+,r1 / no, put current i-number in r1 (ii) 2225 00003A3F E8B20D0000 <1> call iget 2226 <1> ; jsr r0,iget / get it back in 2227 <1> isdir1: ; 1: 2228 00003A44 C3 <1> retn 2229 <1> ; rts r0 2230 <1> 2231 <1> sysunlink: 2232 <1> ; 03/02/2022 2233 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2234 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 2235 <1> ; 2236 <1> ; 'sysunlink' removes the entry for the file pointed to by 2237 <1> ; name from its directory. If this entry was the last link 2238 <1> ; to the file, the contents of the file are freed and the 2239 <1> ; file is destroyed. If, however, the file was open in any 2240 <1> ; process, the actual destruction is delayed until it is 2241 <1> ; closed, even though the directory entry has disappeared. 2242 <1> ; 2243 <1> ; The error bit (e-bit) is set to indicate that the file 2244 <1> ; does not exist or that its directory can not be written. 2245 <1> ; Write permission is not required on the file itself. 2246 <1> ; It is also illegal to unlink a directory (except for 2247 <1> ; the superuser). 2248 <1> ; 2249 <1> ; Calling sequence: 2250 <1> ; sysunlink; name 2251 <1> ; Arguments: 2252 <1> ; name - name of directory entry to be removed 2253 <1> ; Inputs: - 2254 <1> ; Outputs: - 2255 <1> ; ............................................................... 2256 <1> ; 2257 <1> ; Retro UNIX 8086 v1 modification: 2258 <1> ; The user/application program puts address of the name 2259 <1> ; in BX register as 'sysunlink' system call argument. 2260 <1> 2261 <1> ; / name - remove link name 2262 00003A45 891D[18650000] <1> mov [u.namep], ebx 2263 <1> ;jsr r0,arg; u.namep / u.namep points to name 2264 00003A4B E891050000 <1> call namei 2265 <1> ; jsr r0,namei / find the i-number associated 2266 <1> ; / with the path name 2267 <1> ;jc error 2268 <1> ; br error9 / not found 2269 00003A50 730F <1> jnc short sysunlink1 2270 <1> ; 'file not found !' error 2271 00003A52 C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 2271 00003A5A 0000 <1> 2272 00003A5C E980F6FFFF <1> jmp error 2273 <1> sysunlink1: 2274 <1> ; 03/02/2022 2275 00003A61 50 <1> push eax 2276 <1> ;push ax 2277 <1> ; mov r1,-(sp) / put its i-number on the stack 2278 00003A62 E8A9FFFFFF <1> call isdir 2279 <1> ; jsr r0,isdir / is it a directory 2280 <1> ;xor ax, ax 2281 <1> ; 03/02/2022 2282 00003A67 31C0 <1> xor eax, eax 2283 00003A69 66A3[32650000] <1> mov [u.dirbuf], ax ; 0 2284 <1> ; clr u.dirbuf / no, clear the location that will 2285 <1> ; / get written into the i-number portion 2286 <1> ; / of the entry 2287 00003A6F 832D[1C650000]0A <1> sub dword [u.off], 10 2288 <1> ; sub $10.,u.off / move u.off back 1 directory entry 2289 00003A76 E865000000 <1> call wdir 2290 <1> ; jsr r0,wdir / free the directory entry 2291 <1> ; 03/02/2022 2292 00003A7B 58 <1> pop eax 2293 <1> ;pop ax 2294 <1> ; mov (sp)+,r1 / get i-number back 2295 00003A7C E8750D0000 <1> call iget 2296 <1> ; jsr r0,iget / get i-node 2297 00003A81 E87A0E0000 <1> call setimod 2298 <1> ; jsr r0,setimod / set modified flag 2299 00003A86 FE0D[F6610000] <1> dec byte [i.nlks] 2300 <1> ; decb i.nlks / decrement the number of links 2301 <1> ;jnz sysret 2302 <1> ; bgt sysret9 / if this was not the last link 2303 <1> ; / to file return 2304 <1> ; 03/02/2022 2305 00003A8C 7505 <1> jnz short sysunlink2 2306 <1> ; AX = r1 = i-number 2307 00003A8E E8B8090000 <1> call anyi 2308 <1> ; jsr r0,anyi / if it was, see if anyone has it open. 2309 <1> ; / Then free contents of file and destroy it. 2310 <1> sysunlink2: 2311 00003A93 E969F6FFFF <1> jmp sysret 2312 <1> ; br sysret9 2313 <1> 2314 <1> mkdir: 2315 <1> ; 03/02/2022 2316 <1> ; 12/10/2015 2317 <1> ; 17/06/2015 (Retro UNIX 386 v1 - Beginning) 2318 <1> ; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2319 <1> ; 2320 <1> ; 'mkdir' makes a directory entry from the name pointed to 2321 <1> ; by u.namep into the current directory. 2322 <1> ; 2323 <1> ; INPUTS -> 2324 <1> ; u.namep - points to a file name 2325 <1> ; that is about to be a directory entry. 2326 <1> ; ii - current directory's i-number. 2327 <1> ; OUTPUTS -> 2328 <1> ; u.dirbuf+2 - u.dirbuf+10 - contains file name. 2329 <1> ; u.off - points to entry to be filled 2330 <1> ; in the current directory 2331 <1> ; u.base - points to start of u.dirbuf. 2332 <1> ; r1 - contains i-number of current directory 2333 <1> ; 2334 <1> ; ((AX = R1)) output 2335 <1> ; 2336 <1> ; (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM) 2337 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 2338 <1> ; 2339 <1> 2340 <1> ; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 2341 00003A98 31C0 <1> xor eax, eax 2342 00003A9A BF[34650000] <1> mov edi, u.dirbuf+2 2343 00003A9F 89FE <1> mov esi, edi 2344 00003AA1 AB <1> stosd 2345 00003AA2 AB <1> stosd 2346 <1> ; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this 2347 00003AA3 89F7 <1> mov edi, esi ; offset to u.dirbuf 2348 <1> ; 12/10/2015 ([u.namep] -> ebp) 2349 <1> ;mov ebp, [u.namep] 2350 00003AA5 E8B9060000 <1> call trans_addr_nmbp ; convert virtual address to physical 2351 <1> ; esi = physical address (page start + offset) 2352 <1> ; ecx = byte count in the page (1 - 4096) 2353 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 2354 <1> ; mov u.namep,r2 / r2 points to name of directory entry 2355 <1> ; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 2356 <1> mkdir_1: ; 1: 2357 00003AAA 45 <1> inc ebp ; 12/10/2015 2358 <1> ; 2359 <1> ; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 2360 <1> ; 01/08/2013 2361 00003AAB AC <1> lodsb 2362 <1> ; movb (r2)+,r1 / move character in name to r1 2363 00003AAC 20C0 <1> and al, al 2364 00003AAE 7426 <1> jz short mkdir_3 2365 <1> ; beq 1f / if null, done 2366 00003AB0 3C2F <1> cmp al, '/' 2367 <1> ; cmp r1,$'/ / is it a "/"? 2368 00003AB2 7413 <1> je short mkdir_err 2369 <1> ;je error 2370 <1> ; beq error9 / yes, error 2371 <1> ; 03/02/2022 2372 00003AB4 49 <1> dec ecx 2373 <1> ; 12/10/2015 2374 <1> ;dec cx 2375 00003AB5 7505 <1> jnz short mkdir_2 2376 <1> ; 12/10/2015 ([u.namep] -> ebp) 2377 00003AB7 E8AD060000 <1> call trans_addr_nm ; convert virtual address to physical 2378 <1> ; esi = physical address (page start + offset) 2379 <1> ; ecx = byte count in the page 2380 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 2381 <1> mkdir_2: 2382 00003ABC 81FF[3C650000] <1> cmp edi, u.dirbuf+10 2383 <1> ; cmp r3,$u.dirbuf+10. / have we reached the last slot for 2384 <1> ; / a char? 2385 00003AC2 74E6 <1> je short mkdir_1 2386 <1> ; beq 1b / yes, go back 2387 00003AC4 AA <1> stosb 2388 <1> ; movb r1,(r3)+ / no, put the char in the u.dirbuf 2389 00003AC5 EBE3 <1> jmp short mkdir_1 2390 <1> ; br 1b / get next char 2391 <1> mkdir_err: 2392 <1> ; 17/06/2015 2393 00003AC7 C705[4F650000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 2393 00003ACF 0000 <1> 2394 00003AD1 E90BF6FFFF <1> jmp error 2395 <1> mkdir_3: ; 1: 2396 00003AD6 A1[14650000] <1> mov eax, [u.dirp] 2397 00003ADB A3[1C650000] <1> mov [u.off], eax 2398 <1> ; mov u.dirp,u.off / pointer to empty current directory 2399 <1> ; / slot to u.off 2400 <1> wdir: ; 03/02/2022 2401 <1> ; 29/04/2013 2402 00003AE0 C705[20650000]- <1> mov dword [u.base], u.dirbuf 2402 00003AE6 [32650000] <1> 2403 <1> ; mov $u.dirbuf,u.base / u.base points to created file name 2404 00003AEA C705[24650000]0A00- <1> mov dword [u.count], 10 2404 00003AF2 0000 <1> 2405 <1> ; mov $10.,u.count / u.count = 10 2406 00003AF4 66A1[E0640000] <1> mov ax, [ii] 2407 <1> ; mov ii,r1 / r1 has i-number of current directory 2408 00003AFA B201 <1> mov dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification ! 2409 00003AFC E8C90D0000 <1> call access 2410 <1> ; jsr r0,access; 1 / get i-node and set its file up 2411 <1> ; / for writing 2412 <1> ; AX = i-number of current directory 2413 <1> ; 01/08/2013 2414 00003B01 FE05[61650000] <1> inc byte [u.kcall] ; the caller is 'mkdir' sign 2415 <1> ;call writei 2416 <1> ; ; jsr r0,writei / write into directory 2417 <1> ;retn 2418 <1> ; ; rts r0 2419 <1> ; 03/02/2022 2420 00003B07 E9B0100000 <1> jmp writei 2421 <1> 2422 <1> sysexec: 2423 <1> ; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19) 2424 <1> ; 03/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18) 2425 <1> ; 23/10/2015 2426 <1> ; 19/10/2015 2427 <1> ; 10/10/2015, 18/10/2015 2428 <1> ; 29/07/2015, 05/08/2015, 26/08/2015 2429 <1> ; 21/07/2015, 24/07/2015, 25/07/2015 2430 <1> ; 01/07/2015, 02/07/2015, 20/07/2015 2431 <1> ; 24/06/2015, 25/06/2015 2432 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2433 <1> ; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2434 <1> ; 2435 <1> ; 'sysexec' initiates execution of a file whose path name if 2436 <1> ; pointed to by 'name' in the sysexec call. 2437 <1> ; 'sysexec' performs the following operations: 2438 <1> ; 1. obtains i-number of file to be executed via 'namei'. 2439 <1> ; 2. obtains i-node of file to be exceuted via 'iget'. 2440 <1> ; 3. sets trap vectors to system routines. 2441 <1> ; 4. loads arguments to be passed to executing file into 2442 <1> ; highest locations of user's core 2443 <1> ; 5. puts pointers to arguments in locations immediately 2444 <1> ; following arguments. 2445 <1> ; 6. saves number of arguments in next location. 2446 <1> ; 7. intializes user's stack area so that all registers 2447 <1> ; will be zeroed and the PS is cleared and the PC set 2448 <1> ; to core when 'sysret' restores registers 2449 <1> ; and does an rti. 2450 <1> ; 8. inializes u.r0 and u.sp 2451 <1> ; 9. zeros user's core down to u.r0 2452 <1> ; 10. reads executable file from storage device into core 2453 <1> ; starting at location 'core'. 2454 <1> ; 11. sets u.break to point to end of user's code with 2455 <1> ; data area appended. 2456 <1> ; 12. calls 'sysret' which returns control at location 2457 <1> ; 'core' via 'rti' instruction. 2458 <1> ; 2459 <1> ; Calling sequence: 2460 <1> ; sysexec; namep; argp 2461 <1> ; Arguments: 2462 <1> ; namep - points to pathname of file to be executed 2463 <1> ; argp - address of table of argument pointers 2464 <1> ; argp1... argpn - table of argument pointers 2465 <1> ; argp1:<...0> ... argpn:<...0> - argument strings 2466 <1> ; Inputs: (arguments) 2467 <1> ; Outputs: - 2468 <1> ; ............................................................... 2469 <1> ; 2470 <1> ; Retro UNIX 386 v1 modification: 2471 <1> ; User application runs in it's own virtual space 2472 <1> ; which is izolated from kernel memory (and other 2473 <1> ; memory pages) via 80386 paging in ring 3 2474 <1> ; privilige mode. Virtual start address is always 0. 2475 <1> ; User's core memory starts at linear address 400000h 2476 <1> ; (the end of the 1st 4MB). 2477 <1> ; 2478 <1> ; Retro UNIX 8086 v1 modification: 2479 <1> ; user/application segment and system/kernel segment 2480 <1> ; are different and sysenter/sysret/sysrele routines 2481 <1> ; are different (user's registers are saved to 2482 <1> ; and then restored from system's stack.) 2483 <1> ; 2484 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 2485 <1> ; arguments which were in these registers; 2486 <1> ; but, it returns by putting the 1st argument 2487 <1> ; in 'u.namep' and the 2nd argument 2488 <1> ; on top of stack. (1st argument is offset of the 2489 <1> ; file/path name in the user's program segment.) 2490 <1> 2491 <1> ;call arg2 2492 <1> ; * name - 'u.namep' points to address of file/path name 2493 <1> ; in the user's program segment ('u.segmnt') 2494 <1> ; with offset in BX register (as sysopen argument 1). 2495 <1> ; * argp - sysexec argument 2 is in CX register 2496 <1> ; which is on top of stack. 2497 <1> ; 2498 <1> ; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack 2499 <1> 2500 <1> ; 23/06/2015 (32 bit modifications) 2501 <1> 2502 00003B0C 891D[18650000] <1> mov [u.namep], ebx ; argument 1 2503 <1> ; 18/10/2015 2504 00003B12 890D[78650000] <1> mov [argv], ecx ; * ; argument 2 2505 00003B18 E8C4040000 <1> call namei 2506 <1> ; jsr r0,namei / namei returns i-number of file 2507 <1> ; / named in sysexec call in r1 2508 <1> ;jc error 2509 <1> ; br error9 2510 00003B1D 731E <1> jnc short sysexec_0 2511 <1> ; 2512 <1> ; 'file not found !' error 2513 00003B1F C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND 2513 00003B27 0000 <1> 2514 00003B29 E9B3F5FFFF <1> jmp error 2515 <1> sysexec_not_exf: 2516 <1> ; 'not executable file !' error 2517 00003B2E C705[4F650000]1600- <1> mov dword [u.error], ERR_NOT_EXECUTABLE 2517 00003B36 0000 <1> 2518 00003B38 E9A4F5FFFF <1> jmp error 2519 <1> sysexec_0: 2520 00003B3D E8B40C0000 <1> call iget 2521 <1> ; jsr r0,iget / get i-node for file to be executed 2522 <1> ; 03/02/2022 2523 00003B42 F605[F4610000]10 <1> test byte [i.flgs], 10h 2524 <1> ;test word [i.flgs], 10h 2525 <1> ; bit $20,i.flgs / is file executable 2526 00003B49 74E3 <1> jz short sysexec_not_exf 2527 <1> ;jz error 2528 <1> ; beq error9 2529 <1> ;; 2530 00003B4B E80A150000 <1> call iopen 2531 <1> ; jsr r0,iopen / gets i-node for file with i-number 2532 <1> ; / given in r1 (opens file) 2533 <1> ; AX = i-number of the file 2534 <1> ; 03/02/2022 2535 00003B50 F605[F4610000]20 <1> test byte [i.flgs], 20h 2536 <1> ;test word [i.flgs], 20h 2537 <1> ; bit $40,i.flgs / test user id on execution bit 2538 00003B57 7415 <1> jz short sysexec_1 2539 <1> ; beq 1f 2540 00003B59 803D[46650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 2541 <1> ; tstb u.uid / test user id 2542 00003B60 760C <1> jna short sysexec_1 2543 <1> ; beq 1f / super user 2544 00003B62 8A0D[F7610000] <1> mov cl, [i.uid] 2545 00003B68 880D[46650000] <1> mov [u.uid], cl ; 02/08/2013 2546 <1> ; movb i.uid,u.uid / put user id of owner of file 2547 <1> ; / as process user id 2548 <1> sysexec_1: 2549 <1> ; 03/02/2022 2550 <1> ; 18/10/2215 2551 <1> ; 10/10/2015 2552 <1> ; 21/07/2015, 24/07/2015 2553 <1> ; 24/06/2015, 25/06/2015 2554 <1> ; Moving arguments to the end of [u.upage] 2555 <1> ; (by regarding page borders in user's memory space) 2556 <1> ; 2557 <1> ; 10/10/2015 2558 <1> ; 21/07/2015 2559 00003B6E 89E5 <1> mov ebp, esp ; (**) 2560 <1> ; 18/10/2015 2561 00003B70 89EF <1> mov edi, ebp 2562 00003B72 B900010000 <1> mov ecx, MAX_ARG_LEN ; 256 2563 <1> ;sub edi, MAX_ARG_LEN ; 256 2564 00003B77 29CF <1> sub edi, ecx 2565 00003B79 89FC <1> mov esp, edi 2566 00003B7B 31C0 <1> xor eax, eax 2567 00003B7D A3[28650000] <1> mov [u.nread], eax ; 0 2568 <1> ; 03/02/2022 2569 <1> ; ([argc] must be cleared because previous 'sysexec' 2570 <1> ; may leave it with any value after an error)) 2571 <1> ;mov [argc], ax 2572 00003B82 A2[76650000] <1> mov [argc], al ; 0 2573 <1> ; 2574 00003B87 49 <1> dec ecx ; 256 - 1 2575 00003B88 890D[24650000] <1> mov [u.count], ecx ; MAX_ARG_LEN - 1 ; 255 2576 <1> ;mov dword [u.count], MAX_ARG_LEN - 1 ; 255 2577 <1> sysexec_2: 2578 00003B8E 8B35[78650000] <1> mov esi, [argv] ; 18/10/2015 2579 00003B94 E864020000 <1> call get_argp 2580 <1> ;mov ecx, 4 2581 <1> ; 03/02/2022 2582 00003B99 31C9 <1> xor ecx, ecx 2583 00003B9B B104 <1> mov cl, 4 2584 <1> sysexec_3: 2585 00003B9D 21C0 <1> and eax, eax 2586 00003B9F 7456 <1> jz short sysexec_6 2587 <1> ; 18/10/2015 2588 00003BA1 010D[78650000] <1> add [argv], ecx ; 4 2589 00003BA7 66FF05[76650000] <1> inc word [argc] 2590 <1> ; 2591 00003BAE A3[20650000] <1> mov [u.base], eax 2592 <1> ; 23/10/2015 2593 00003BB3 66C705[5F650000]00- <1> mov word [u.pcount], 0 2593 00003BBB 00 <1> 2594 <1> sysexec_4: 2595 00003BBC E82D120000 <1> call cpass ; get a character from user's core memory 2596 00003BC1 750B <1> jnz short sysexec_5 2597 <1> ; (max. 255 chars + null) 2598 <1> ; 18/10/2015 2599 00003BC3 28C0 <1> sub al, al 2600 00003BC5 AA <1> stosb 2601 00003BC6 FF05[28650000] <1> inc dword [u.nread] 2602 00003BCC EB29 <1> jmp short sysexec_6 2603 <1> sysexec_5: 2604 00003BCE AA <1> stosb 2605 00003BCF 20C0 <1> and al, al 2606 00003BD1 75E9 <1> jnz short sysexec_4 2607 <1> ;mov ecx, 4 2608 <1> ; 03/02/2022 2609 00003BD3 29C9 <1> sub ecx, ecx 2610 00003BD5 B104 <1> mov cl, 4 2611 <1> ;cmp [ncount], ecx ; 4 2612 <1> ; 03/02/2022 2613 00003BD7 66390D[74650000] <1> cmp [ncount], cx ; 4 2614 00003BDE 72AE <1> jb short sysexec_2 2615 00003BE0 8B35[70650000] <1> mov esi, [nbase] 2616 00003BE6 010D[70650000] <1> add [nbase], ecx ; 4 2617 00003BEC 66290D[74650000] <1> sub [ncount], cx 2618 00003BF3 8B06 <1> mov eax, [esi] 2619 00003BF5 EBA6 <1> jmp short sysexec_3 2620 <1> sysexec_6: 2621 <1> ; 18/10/2015 2622 <1> ; argument list transfer from user's core memory to 2623 <1> ; kernel stack frame is OK here. 2624 <1> ; [u.nread] = ; argument list length 2625 <1> ;mov [argv], esp ; start address of argument list 2626 <1> ; 2627 <1> ; 18/10/2015 2628 <1> ; 21/07/2015, 24/07/2015 2629 <1> ; 25/06/2015, 02/07/2015 2630 <1> ; 23/06/2015, 24/06/2015 2631 <1> ; 2632 00003BF7 8B1D[57650000] <1> mov ebx, [u.ppgdir] ; parent's page directory 2633 00003BFD 21DB <1> and ebx, ebx ; /etc/init ? (u.ppgdir = 0) 2634 00003BFF 740A <1> jz short sysexec_7 2635 00003C01 A1[53650000] <1> mov eax, [u.pgdir] ; physical address of page directory 2636 00003C06 E806E9FFFF <1> call deallocate_page_dir 2637 <1> sysexec_7: 2638 00003C0B E836E8FFFF <1> call make_page_dir 2639 <1> ;jc short sysexec_14 2640 <1> ;jc panic ; allocation error 2641 <1> ; after a deallocation would be nonsence !? 2642 <1> ; 03/02/2022 2643 00003C10 7243 <1> jc short sysexec_panic 2644 <1> 2645 <1> ; 24/07/2015 2646 <1> ; map kernel pages (1st 4MB) to PDE 0 2647 <1> ; of the user's page directory 2648 <1> ; (It is needed for interrupts!) 2649 <1> ; 18/10/2015 2650 00003C12 8B15[38610000] <1> mov edx, [k_page_dir] ; Kernel's page directory 2651 00003C18 8B02 <1> mov eax, [edx] ; physical address of 2652 <1> ; kernel's first page table (1st 4 MB) 2653 <1> ; (PDE 0 of kernel's page directory) 2654 00003C1A 8B15[53650000] <1> mov edx, [u.pgdir] 2655 00003C20 8902 <1> mov [edx], eax ; PDE 0 (1st 4MB) 2656 <1> ; 2657 <1> ; 20/07/2015 2658 00003C22 BB00004000 <1> mov ebx, CORE ; start address = 0 (virtual) + CORE 2659 <1> ; 18/10/2015 2660 00003C27 BE[68650000] <1> mov esi, pcore ; physical start address 2661 <1> sysexec_8: 2662 00003C2C B907000000 <1> mov ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT 2663 00003C31 E82EE8FFFF <1> call make_page_table 2664 <1> ;jc panic 2665 <1> ; 03/02/2022 2666 00003C36 721D <1> jc short sysexec_panic 2667 <1> ;mov ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT 2668 00003C38 E835E8FFFF <1> call make_page ; make new page, clear and set the pte 2669 <1> ;jc panic 2670 <1> ; 03/02/2022 2671 00003C3D 7216 <1> jc short sysexec_panic 2672 <1> ; 2673 00003C3F 8906 <1> mov [esi], eax ; 24/06/2015 2674 <1> ; ebx = virtual address (24/07/2015) 2675 <1> ; 03/02/2022 2676 <1> ;call add_to_swap_queue 2677 <1> ; 18/10/2015 2678 00003C41 81FE[6C650000] <1> cmp esi, ecore ; user's stack (last) page ? 2679 00003C47 7411 <1> je short sysexec_9 ; yes 2680 00003C49 BE[6C650000] <1> mov esi, ecore ; physical address of the last page 2681 <1> ; 20/07/2015 2682 00003C4E BB00F0FFFF <1> mov ebx, (ECORE - PAGE_SIZE) + CORE 2683 <1> ; ebx = virtual end address + segment base address - 4K 2684 00003C53 EBD7 <1> jmp short sysexec_8 2685 <1> 2686 <1> sysexec_panic: 2687 <1> ; 03/02/2022 2688 00003C55 E949EDFFFF <1> jmp panic 2689 <1> 2690 <1> sysexec_9: 2691 <1> ; 18/10/2015 2692 <1> ; 26/08/2015 2693 <1> ; 25/06/2015 2694 <1> ; move arguments from kernel stack to [ecore] 2695 <1> ; (argument list/line will be copied from kernel stack 2696 <1> ; frame to the last (stack) page of user's core memory) 2697 <1> ; 18/10/2015 2698 00003C5A 8B3D[6C650000] <1> mov edi, [ecore] 2699 00003C60 81C700100000 <1> add edi, PAGE_SIZE 2700 <1> ;movzx eax, word [argc] 2701 <1> ; 03/02/2022 2702 00003C66 31C0 <1> xor eax, eax 2703 00003C68 A0[76650000] <1> mov al, [argc] 2704 00003C6D 08C0 <1> or al, al 2705 <1> ;or eax, eax 2706 00003C6F 7509 <1> jnz short sysexec_10 2707 00003C71 89FB <1> mov ebx, edi 2708 00003C73 83EB04 <1> sub ebx, 4 2709 00003C76 8903 <1> mov [ebx], eax ; 0 2710 00003C78 EB43 <1> jmp short sysexec_13 2711 <1> sysexec_10: 2712 00003C7A 8B0D[28650000] <1> mov ecx, [u.nread] 2713 <1> ;mov esi, [argv] 2714 00003C80 89E6 <1> mov esi, esp ; start address of argument list 2715 00003C82 29CF <1> sub edi, ecx ; page end address - argument list length 2716 <1> 2717 <1> ;;;; 2718 <1> ; 09/05/2022 2719 <1> ; (move edi -backward- to dword boundary) 2720 <1> ; ((this will prevent 'general protection fault' error 2721 <1> ; as result of a lodsd or dword move instruction 2722 <1> ; at the end of argument list)) 2723 00003C84 83EF03 <1> sub edi, 3 2724 00003C87 83E7FC <1> and edi, ~3 ; (*) 2725 <1> ;;; 2726 <1> 2727 00003C8A 89C2 <1> mov edx, eax 2728 <1> ; 03/02/2022 ; ([argc] < 32) 2729 00003C8C FEC2 <1> inc dl ; argument count + 1 for argc value 2730 00003C8E C0E202 <1> shl dl, 2 ; 4 * (argument count + 1) 2731 <1> ; edx <= 128 2732 00003C91 89FB <1> mov ebx, edi 2733 <1> ; 09/05/2022 (*) - edi is already dword aligned - 2734 <1> ;and bl, 0FCh ; 32 bit (dword) alignment 2735 00003C93 29D3 <1> sub ebx, edx 2736 00003C95 89FA <1> mov edx, edi 2737 00003C97 F3A4 <1> rep movsb 2738 00003C99 89D6 <1> mov esi, edx 2739 00003C9B 89DF <1> mov edi, ebx 2740 00003C9D BA00F0BFFF <1> mov edx, ECORE - PAGE_SIZE ; virtual addr. of the last page 2741 00003CA2 2B15[6C650000] <1> sub edx, [ecore] ; difference (virtual - physical) 2742 00003CA8 AB <1> stosd ; eax = argument count 2743 <1> sysexec_11: 2744 00003CA9 89F0 <1> mov eax, esi 2745 00003CAB 01D0 <1> add eax, edx 2746 00003CAD AB <1> stosd ; eax = virtual address 2747 00003CAE FE0D[76650000] <1> dec byte [argc] 2748 00003CB4 7407 <1> jz short sysexec_13 2749 <1> sysexec_12: 2750 00003CB6 AC <1> lodsb 2751 00003CB7 20C0 <1> and al, al 2752 00003CB9 75FB <1> jnz short sysexec_12 2753 00003CBB EBEC <1> jmp short sysexec_11 2754 <1> ; 2755 <1> ; 1: 2756 <1> ; mov (sp)+,r5 / r5 now contains address of list of 2757 <1> ; / pointers to arguments to be passed 2758 <1> ; mov $1,u.quit / u.quit determines handling of quits; 2759 <1> ; / u.quit = 1 take quit 2760 <1> ; mov $1,u.intr / u.intr determines handling of 2761 <1> ; / interrupts; u.intr = 1 take interrupt 2762 <1> ; mov $rtssym,30 / emt trap vector set to take 2763 <1> ; / system routine 2764 <1> ; mov $fpsym,*10 / reserved instruction trap vector 2765 <1> ; / set to take system routine 2766 <1> ; mov $sstack,sp / stack space used during swapping 2767 <1> ; mov r5,-(sp) / save arguments pointer on stack 2768 <1> ; mov $ecore,r5 / r5 has end of core 2769 <1> ; mov $core,r4 / r4 has start of users core 2770 <1> ; mov r4,u.base / u.base has start of users core 2771 <1> ; mov (sp),r2 / move arguments list pointer into r2 2772 <1> ; 1: 2773 <1> ; tst (r2)+ / argument char = "nul" 2774 <1> ; bne 1b 2775 <1> ; tst -(r2) / decrement r2 by 2; r2 has addr of 2776 <1> ; / end of argument pointer list 2777 <1> ; 1: 2778 <1> ; / move arguments to bottom of users core 2779 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 2780 <1> ; cmp r2,(sp) / is r2 = beginning of argument 2781 <1> ; / ptr list 2782 <1> ; blo 1f / branch to 1f when all arguments 2783 <1> ; / are moved 2784 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 2785 <1> ; 2: 2786 <1> ; tstb (r3)+ 2787 <1> ; bne 2b / scan argument for \0 (nul) 2788 <1> 2789 <1> ; 2: 2790 <1> ; movb -(r3),-(r5) / move argument char 2791 <1> ; / by char starting at "ecore" 2792 <1> ; cmp r3,(r2) / moved all characters in 2793 <1> ; / this argument 2794 <1> ; bhi 2b / branch 2b if not 2795 <1> ; mov r5,(r4)+ / move r5 into top of users core; 2796 <1> ; / r5 has pointer to nth arg 2797 <1> ; br 1b / string 2798 <1> ; 1: 2799 <1> ; clrb -(r5) 2800 <1> ; bic $1,r5 / make r5 even, r5 points to 2801 <1> ; / last word of argument strings 2802 <1> ; mov $core,r2 2803 <1> 2804 <1> ; 1: / move argument pointers into core following 2805 <1> ; / argument strings 2806 <1> ; cmp r2,r4 2807 <1> ; bhis 1f / branch to 1f when all pointers 2808 <1> ; / are moved 2809 <1> ; mov (r2)+,-(r5) 2810 <1> ; br 1b 2811 <1> ; 1: 2812 <1> ; sub $core,r4 / gives number of arguments *2 2813 <1> ; asr r4 / divide r4 by 2 to calculate 2814 <1> ; / the number of args stored 2815 <1> ; mov r4,-(r5) / save number of arguments ahead 2816 <1> ; / of the argument pointers 2817 <1> sysexec_13: 2818 <1> ; 19/10/2015 2819 <1> ; 18/10/2015 2820 <1> ; 29/07/2015 2821 <1> ; 24/07/2015, 25/07/2015 2822 <1> ; 25/06/2015, 20/07/2015 2823 <1> ; 23/06/2015, 24/06/2015 2824 <1> ; 2825 <1> ; moving arguments to [ecore] is OK here.. 2826 <1> ; 18/10/2015 2827 00003CBD 89EC <1> mov esp, ebp ; (**) restore kernel stack pointer 2828 <1> ; ebx = beginning addres of argument list pointers 2829 <1> ; in user's stack 2830 <1> ; 19/10/2015 2831 00003CBF 2B1D[6C650000] <1> sub ebx, [ecore] 2832 00003CC5 81C300F0BFFF <1> add ebx, (ECORE - PAGE_SIZE) 2833 <1> ; end of core - 4096 (last page) 2834 <1> ; (virtual address) 2835 00003CCB 891D[78650000] <1> mov [argv], ebx 2836 00003CD1 891D[2C650000] <1> mov [u.break], ebx ; available user memory 2837 <1> ; 2838 00003CD7 29C0 <1> sub eax, eax 2839 00003CD9 C705[24650000]2000- <1> mov dword [u.count], 32 ; Executable file header size 2839 00003CE1 0000 <1> 2840 <1> ; mov $14,u.count 2841 00003CE3 C705[10650000]- <1> mov dword [u.fofp], u.off 2841 00003CE9 [1C650000] <1> 2842 <1> ; mov $u.off,u.fofp 2843 00003CED A3[1C650000] <1> mov [u.off], eax ; 0 2844 <1> ; clr u.off / set offset in file to be read to zero 2845 <1> ; 25/07/2015 2846 00003CF2 A3[20650000] <1> mov [u.base], eax ; 0, start of user's core (virtual) 2847 <1> ; 25/06/2015 2848 00003CF7 66A1[E0640000] <1> mov ax, [ii] 2849 <1> ; AX = i-number of the executable file 2850 00003CFD E8C80C0000 <1> call readi 2851 <1> ; jsr r0,readi / read in first six words of 2852 <1> ; / user's file, starting at $core 2853 <1> ; mov sp,r5 / put users stack address in r5 2854 <1> ; sub $core+40.,r5 / subtract $core +40, 2855 <1> ; / from r5 (leaves number of words 2856 <1> ; / less 26 available for 2857 <1> ; / program in user core 2858 <1> ; mov r5,u.count / 2859 <1> ; 25/06/2015 2860 00003D02 8B0D[2C650000] <1> mov ecx, [u.break] ; top of user's stack (physical addr.) 2861 00003D08 890D[24650000] <1> mov [u.count], ecx ; save for overrun check 2862 <1> ; 2863 00003D0E 8B0D[28650000] <1> mov ecx, [u.nread] 2864 00003D14 890D[2C650000] <1> mov [u.break], ecx ; virtual address (offset from start) 2865 00003D1A 80F920 <1> cmp cl, 32 2866 00003D1D 7540 <1> jne short sysexec_15 2867 <1> ;: 2868 <1> ; 25/06/2015 2869 <1> ; Retro UNIX 386 v1 (32 bit) executable file header format 2870 <1> ; 18/10/2015 2871 00003D1F 8B35[68650000] <1> mov esi, [pcore] ; start address of user's core memory 2872 <1> ; (phys. start addr. of the exec. file) 2873 00003D25 AD <1> lodsd 2874 00003D26 663DEB1E <1> cmp ax, 1EEBh ; EBh, 1Eh -> jump to +32 2875 00003D2A 7533 <1> jne short sysexec_15 2876 <1> ; cmp core,$405 / br .+14 is first instruction 2877 <1> ; / if file is standard a.out format 2878 <1> ; bne 1f / branch, if not standard format 2879 00003D2C AD <1> lodsd 2880 00003D2D 89C1 <1> mov ecx, eax ; text (code) section size 2881 00003D2F AD <1> lodsd 2882 00003D30 01C1 <1> add ecx, eax ; + data section size (initialized data) 2883 <1> ; mov core+2,r5 / put 2nd word of users program in r5; 2884 <1> ; / number of bytes in program text 2885 <1> ; sub $14,r5 / subtract 12 2886 00003D32 89CB <1> mov ebx, ecx 2887 <1> ; 2888 <1> ; 25/06/2015 2889 <1> ; NOTE: These are for next versions of Retro UNIX 386 2890 <1> ; and SINGLIX operating systems (as code template). 2891 <1> ; Current Retro UNIX 386 v1 files can be max. 64KB 2892 <1> ; due to RUFS (floppy disk file system) restriction... 2893 <1> ; Overrun is not possible for current version. 2894 <1> ; 2895 00003D34 AD <1> lodsd 2896 00003D35 01C3 <1> add ebx, eax ; + bss section size (for overrun checking) 2897 00003D37 3B1D[24650000] <1> cmp ebx, [u.count] 2898 00003D3D 7711 <1> ja short sysexec_14 ; program overruns stack ! 2899 <1> ; 2900 <1> ; 24/07/2015 2901 <1> ; add bss section size to [u.break] 2902 00003D3F 0105[2C650000] <1> add [u.break], eax 2903 <1> ; 2904 00003D45 83E920 <1> sub ecx, 32 ; header size (already loaded) 2905 <1> ;cmp ecx, [u.count] 2906 <1> ;jnb short sysexec_16 2907 <1> ; cmp r5,u.count / 2908 <1> ; bgt 1f / branch if r5 greater than u.count 2909 00003D48 890D[24650000] <1> mov [u.count], ecx ; required read count 2910 <1> ; mov r5,u.count 2911 <1> ; 2912 00003D4E EB2A <1> jmp short sysexec_16 2913 <1> ; 2914 <1> sysexec_14: 2915 <1> ; 23/06/2015 2916 <1> ; insufficient (out of) memory 2917 00003D50 C705[4F650000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; 1 2917 00003D58 0000 <1> 2918 00003D5A E982F3FFFF <1> jmp error 2919 <1> ; 2920 <1> sysexec_15: 2921 <1> ; 25/06/2015 2922 00003D5F 0FB715[F8610000] <1> movzx edx, word [i.size] ; file size 2923 00003D66 29CA <1> sub edx, ecx ; file size - loaded bytes 2924 00003D68 7627 <1> jna short sysexec_17 ; no need to next read 2925 00003D6A 01D1 <1> add ecx, edx ; [i.size] 2926 00003D6C 3B0D[24650000] <1> cmp ecx, [u.count] ; overrun check (!) 2927 00003D72 77DC <1> ja short sysexec_14 2928 00003D74 8915[24650000] <1> mov [u.count], edx 2929 <1> sysexec_16: 2930 00003D7A 66A1[E0640000] <1> mov ax, [ii] ; i-number 2931 00003D80 E8450C0000 <1> call readi 2932 <1> ; add core+10,u.nread / add size of user data area 2933 <1> ; / to u.nread 2934 <1> ; br 2f 2935 <1> ; 1: 2936 <1> ; jsr r0,readi / read in rest of file 2937 <1> ; 2: 2938 00003D85 8B0D[28650000] <1> mov ecx, [u.nread] 2939 00003D8B 010D[2C650000] <1> add [u.break], ecx 2940 <1> ; mov u.nread,u.break / set users program break to end of 2941 <1> ; / user code 2942 <1> ; add $core+14,u.break / plus data area 2943 <1> sysexec_17: ; 20/07/2015 2944 <1> ; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18) 2945 <1> ; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 2946 <1> ; ('iclose' is not needed for regular files, from now on) 2947 <1> ;;mov ax, [ii] ; i-number 2948 <1> ;call iclose 2949 <1> ; ; jsr r0,iclose / does nothing 2950 00003D91 31C0 <1> xor eax, eax 2951 00003D93 FEC0 <1> inc al 2952 00003D95 66A3[3E650000] <1> mov [u.intr], ax ; 1 (interrupt/time-out is enabled) 2953 00003D9B 66A3[40650000] <1> mov [u.quit], ax ; 1 ('crtl+brk' signal is enabled) 2954 <1> ; 02/07/2015 2955 00003DA1 833D[57650000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ? 2956 00003DA8 770C <1> ja short sysexec_18 ; no, the caller is user process 2957 <1> ; If the caller is kernel (sys_init), 'sysexec' will come here 2958 00003DAA 8B15[38610000] <1> mov edx, [k_page_dir] ; kernel's page directory 2959 00003DB0 8915[57650000] <1> mov [u.ppgdir], edx ; next time 'sysexec' must not come here 2960 <1> sysexec_18: 2961 <1> ; 18/10/2015 2962 <1> ; 05/08/2015 2963 <1> ; 29/07/2015 2964 00003DB6 8B2D[78650000] <1> mov ebp, [argv] ; user's stack pointer must point to argument 2965 <1> ; list pointers (argument count) 2966 00003DBC FA <1> cli 2967 00003DBD 8B25[D4600000] <1> mov esp, [tss.esp0] ; ring 0 (kernel) stack pointer 2968 <1> ;mov esp, [u.sp] ; Restore Kernel stack 2969 <1> ; for this process 2970 <1> ;add esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS 2971 <1> ;xor eax, eax ; 0 2972 00003DC3 FEC8 <1> dec al ; eax = 0 2973 00003DC5 66BA2300 <1> mov dx, UDATA 2974 00003DC9 6652 <1> push dx ; user's stack segment 2975 00003DCB 55 <1> push ebp ; user's stack pointer 2976 <1> ; (points to number of arguments) 2977 00003DCC FB <1> sti 2978 00003DCD 9C <1> pushfd ; EFLAGS 2979 <1> ; Set IF for enabling interrupts in user mode 2980 <1> ;or dword [esp], 200h 2981 <1> ; 2982 <1> ;mov bx, UCODE 2983 <1> ;push bx ; user's code segment 2984 00003DCE 6A1B <1> push UCODE 2985 <1> ;push 0 2986 00003DD0 50 <1> push eax ; EIP (=0) - start address - 2987 <1> ; clr -(r5) / popped into ps when rti in 2988 <1> ; / sysrele is executed 2989 <1> ; mov $core,-(r5) / popped into pc when rti 2990 <1> ; / in sysrele is executed 2991 <1> ;mov r5,0f / load second copyz argument 2992 <1> ;tst -(r5) / decrement r5 2993 00003DD1 8925[F8640000] <1> mov [u.sp], esp ; 29/07/2015 2994 <1> ; 05/08/2015 2995 <1> ; Remedy of a General Protection Fault during 'iretd' is here ! 2996 <1> ; ('push dx' would cause to general protection fault, 2997 <1> ; after 'pop ds' etc.) 2998 <1> ; 2999 <1> ;; push dx ; ds (UDATA) 3000 <1> ;; push dx ; es (UDATA) 3001 <1> ;; push dx ; fs (UDATA) 3002 <1> ;; push dx ; gs (UDATA) 3003 <1> ; 3004 <1> ; This is a trick to prevent general protection fault 3005 <1> ; during 'iretd' intruction at the end of 'sysrele' (in u1.s): 3006 00003DD7 8EC2 <1> mov es, dx ; UDATA 3007 00003DD9 06 <1> push es ; ds (UDATA) 3008 00003DDA 06 <1> push es ; es (UDATA) 3009 00003DDB 06 <1> push es ; fs (UDATA) 3010 00003DDC 06 <1> push es ; gs (UDATA) 3011 00003DDD 66BA1000 <1> mov dx, KDATA 3012 00003DE1 8EC2 <1> mov es, dx 3013 <1> ; 3014 <1> ;; pushad simulation 3015 00003DE3 89E5 <1> mov ebp, esp ; esp before pushad 3016 00003DE5 50 <1> push eax ; eax (0) 3017 00003DE6 50 <1> push eax ; ecx (0) 3018 00003DE7 50 <1> push eax ; edx (0) 3019 00003DE8 50 <1> push eax ; ebx (0) 3020 00003DE9 55 <1> push ebp ; esp before pushad 3021 00003DEA 50 <1> push eax ; ebp (0) 3022 00003DEB 50 <1> push eax ; esi (0) 3023 00003DEC 50 <1> push eax ; edi (0) 3024 <1> ; 3025 00003DED A3[00650000] <1> mov [u.r0], eax ; eax = 0 3026 00003DF2 8925[FC640000] <1> mov [u.usp], esp 3027 <1> ; mov r5,u.r0 / 3028 <1> ; sub $16.,r5 / skip 8 words 3029 <1> ; mov r5,u.sp / assign user stack pointer value, 3030 <1> ; / effectively zeroes all regs 3031 <1> ; / when sysrele is executed 3032 <1> ; jsr r0,copyz; core; 0:0 / zero user's core 3033 <1> ; clr u.break 3034 <1> ; mov r5,sp / point sp to user's stack 3035 <1> ; 3036 00003DF8 E906F3FFFF <1> jmp sysret0 3037 <1> ;jmp sysret 3038 <1> ; br sysret3 / return to core image at $core 3039 <1> 3040 <1> get_argp: 3041 <1> ; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 3042 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3043 <1> ; 18/10/2015 (nbase, ncount) 3044 <1> ; 21/07/2015 3045 <1> ; 24/06/2015 (Retro UNIX 386 v1) 3046 <1> ; Get (virtual) address of argument from user's core memory 3047 <1> ; 3048 <1> ; INPUT: 3049 <1> ; esi = virtual address of argument pointer 3050 <1> ; OUTPUT: 3051 <1> ; eax = virtual address of argument 3052 <1> ; 3053 <1> ; Modified registers: EAX, EBX, ECX, EDX, ESI 3054 <1> ; 3055 00003DFD 833D[57650000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? 3056 <1> ; (the caller is kernel) 3057 <1> ;jna short get_argpk 3058 <1> ; 03/02/2022 3059 00003E04 7719 <1> ja short get_argp5 3060 <1> get_argpk: 3061 <1> ; Argument is in kernel's memory space 3062 00003E06 66C705[74650000]00- <1> mov word [ncount], PAGE_SIZE ; 4096 3062 00003E0E 10 <1> 3063 00003E0F 8935[70650000] <1> mov [nbase], esi 3064 00003E15 8305[70650000]04 <1> add dword [nbase], 4 3065 00003E1C 8B06 <1> mov eax, [esi] ; virtual addr. = physcal addr. 3066 00003E1E C3 <1> retn 3067 <1> get_argp5: 3068 00003E1F 89F3 <1> mov ebx, esi 3069 00003E21 E8A3E9FFFF <1> call get_physical_addr ; get physical address 3070 00003E26 7257 <1> jc short get_argp_err ; 03/02/2022 (short jump) 3071 00003E28 A3[70650000] <1> mov [nbase], eax ; physical address 3072 00003E2D 66890D[74650000] <1> mov [ncount], cx ; remain byte count in page (1-4096) 3073 00003E34 B804000000 <1> mov eax, 4 ; 21/07/2015 3074 <1> ;cmp cx, ax ; 4 3075 <1> ; 03/02/2022 3076 00003E39 39C1 <1> cmp ecx, eax 3077 00003E3B 734C <1> jnb short get_argp2 3078 00003E3D 89F3 <1> mov ebx, esi 3079 00003E3F 01CB <1> add ebx, ecx 3080 00003E41 E883E9FFFF <1> call get_physical_addr ; get physical address 3081 00003E46 7237 <1> jc short get_argp_err 3082 <1> ;push esi 3083 00003E48 89C6 <1> mov esi, eax 3084 00003E4A 66870D[74650000] <1> xchg cx, [ncount] 3085 00003E51 8735[70650000] <1> xchg esi, [nbase] 3086 00003E57 B504 <1> mov ch, 4 3087 00003E59 28CD <1> sub ch, cl 3088 <1> get_argp0: 3089 00003E5B AC <1> lodsb 3090 <1> ;push ax 3091 <1> ; 03/02/2022 3092 00003E5C 50 <1> push eax 3093 00003E5D FEC9 <1> dec cl 3094 00003E5F 75FA <1> jnz short get_argp0 3095 00003E61 8B35[70650000] <1> mov esi, [nbase] 3096 <1> ; 21/07/2015 3097 00003E67 0FB6C5 <1> movzx eax, ch 3098 00003E6A 0105[70650000] <1> add [nbase], eax 3099 00003E70 662905[74650000] <1> sub [ncount], ax 3100 <1> get_argp1: 3101 00003E77 AC <1> lodsb 3102 00003E78 FECD <1> dec ch 3103 00003E7A 7423 <1> jz short get_argp3 3104 <1> ;push ax 3105 <1> ; 03/02/2022 3106 00003E7C 50 <1> push eax 3107 00003E7D EBF8 <1> jmp short get_argp1 3108 <1> get_argp_err: 3109 00003E7F A3[4F650000] <1> mov [u.error], eax 3110 00003E84 E958F2FFFF <1> jmp error 3111 <1> get_argp2: 3112 <1> ; 21/07/2015 3113 <1> ;mov eax, 4 3114 00003E89 8B15[70650000] <1> mov edx, [nbase] ; 18/10/2015 3115 00003E8F 0105[70650000] <1> add [nbase], eax 3116 00003E95 662905[74650000] <1> sub [ncount], ax 3117 <1> ; 3118 00003E9C 8B02 <1> mov eax, [edx] 3119 00003E9E C3 <1> retn 3120 <1> get_argp3: 3121 00003E9F B103 <1> mov cl, 3 3122 <1> get_argp4: 3123 00003EA1 C1E008 <1> shl eax, 8 3124 <1> ;pop dx 3125 <1> ; 03/02/2022 3126 00003EA4 5A <1> pop edx 3127 00003EA5 88D0 <1> mov al, dl 3128 00003EA7 E2F8 <1> loop get_argp4 3129 <1> ;pop esi 3130 00003EA9 C3 <1> retn 3131 <1> 3132 <1> sysfstat: 3133 <1> ; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19) 3134 <1> ; ([idev] return in eax) 3135 <1> ; 0 = root device 3136 <1> ; 1 = mounted device (>0) 3137 <1> ; 03/02/2022 3138 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3139 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3140 <1> ; 3141 <1> ; 'sysfstat' is identical to 'sysstat' except that it operates 3142 <1> ; on open files instead of files given by name. It puts the 3143 <1> ; buffer address on the stack, gets the i-number and 3144 <1> ; checks to see if the file is open for reading or writing. 3145 <1> ; If the file is open for writing (i-number is negative) 3146 <1> ; the i-number is set positive and a branch into 'sysstat' 3147 <1> ; is made. 3148 <1> ; 3149 <1> ; Calling sequence: 3150 <1> ; sysfstat; buf 3151 <1> ; Arguments: 3152 <1> ; buf - buffer address 3153 <1> ; 3154 <1> ; Inputs: *u.r0 - file descriptor 3155 <1> ; Outputs: buffer is loaded with file information 3156 <1> ; ............................................................... 3157 <1> ; 3158 <1> ; Retro UNIX 8086 v1 modification: 3159 <1> ; 'sysfstat' system call has two arguments; so, 3160 <1> ; * 1st argument, file descriptor is in BX register 3161 <1> ; * 2nd argument, buf is pointed to by CX register 3162 <1> 3163 <1> ; / set status of open file 3164 <1> ; jsr r0,arg; u.off / put buffer address in u.off 3165 00003EAA 51 <1> push ecx 3166 <1> ; mov u.off,-(sp) / put buffer address on the stack 3167 <1> ; mov *u.r0,r1 / put file descriptor in r1 3168 <1> ; jsr r0,getf / get the files i-number 3169 <1> ; BX = file descriptor (file number) 3170 00003EAB E8FE000000 <1> call getf1 3171 <1> ; 03/02/2022 3172 00003EB0 21C0 <1> and eax, eax 3173 <1> ;and ax, ax ; i-number of the file 3174 <1> ; tst r1 / is it 0? 3175 <1> ;jz error 3176 <1> ; beq error3 / yes, error 3177 00003EB2 750F <1> jnz short sysfstat1 3178 00003EB4 C705[4F650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 3178 00003EBC 0000 <1> 3179 00003EBE E91EF2FFFF <1> jmp error 3180 <1> sysfstat1: 3181 00003EC3 80FC80 <1> cmp ah, 80h 3182 00003EC6 7222 <1> jb short sysstat1 3183 <1> ; bgt 1f / if i-number is negative (open for writing) 3184 00003EC8 66F7D8 <1> neg ax 3185 <1> ; neg r1 / make it positive, then branch 3186 00003ECB EB1D <1> jmp short sysstat1 3187 <1> ; br 1f / to 1f 3188 <1> sysstat: 3189 <1> ; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19) 3190 <1> ; ([idev] return in eax) 3191 <1> ; 0 = root device 3192 <1> ; 1 = mounted device (>0) 3193 <1> ; 03/02/2022 3194 <1> ; 18/10/2015 3195 <1> ; 07/10/2015 3196 <1> ; 02/09/2015 3197 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3198 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3199 <1> ; 3200 <1> ; 'sysstat' gets the status of a file. Its arguments are the 3201 <1> ; name of the file and buffer address. The buffer is 34 bytes 3202 <1> ; long and information about the file placed in it. 3203 <1> ; sysstat calls 'namei' to get the i-number of the file. 3204 <1> ; Then 'iget' is called to get i-node in core. The buffer 3205 <1> ; is then loaded and the results are given in the UNIX 3206 <1> ; Programmers Manual sysstat (II). 3207 <1> ; 3208 <1> ; Calling sequence: 3209 <1> ; sysstat; name; buf 3210 <1> ; Arguments: 3211 <1> ; name - points to the name of the file 3212 <1> ; buf - address of a 34 bytes buffer 3213 <1> ; Inputs: - 3214 <1> ; Outputs: buffer is loaded with file information 3215 <1> ; ............................................................... 3216 <1> ; 3217 <1> ; Retro UNIX 8086 v1 modification: 3218 <1> ; 'sysstat' system call has two arguments; so, 3219 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 3220 <1> ; to get sysstat system call arguments from the user; 3221 <1> ; * 1st argument, name is pointed to by BX register 3222 <1> ; * 2nd argument, buf is pointed to by CX register 3223 <1> ; 3224 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 3225 <1> ; arguments which were in these registers; 3226 <1> ; but, it returns by putting the 1st argument 3227 <1> ; in 'u.namep' and the 2nd argument 3228 <1> ; on top of stack. (1st argument is offset of the 3229 <1> ; file/path name in the user's program segment.) 3230 <1> 3231 <1> ; / ; name of file; buffer - get files status 3232 <1> ; jsr r0,arg2 / get the 2 arguments 3233 00003ECD 891D[18650000] <1> mov [u.namep], ebx 3234 00003ED3 51 <1> push ecx 3235 00003ED4 E808010000 <1> call namei 3236 <1> ; jsr r0,namei / get the i-number for the file 3237 <1> ;jc error 3238 <1> ; br error3 / no such file, error 3239 00003ED9 730F <1> jnc short sysstat1 3240 <1> ; pop ecx 3241 <1> sysstat_err0: 3242 <1> ; 'file not found !' error 3243 00003EDB C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 3243 00003EE3 0000 <1> 3244 00003EE5 E9F7F1FFFF <1> jmp error 3245 <1> 3246 <1> ;statx: db 0 3247 <1> 3248 <1> sysstat1: ; 1: 3249 00003EEA E807090000 <1> call iget 3250 <1> ; jsr r0,iget / get the i-node into core 3251 <1> ; 07/10/2015 (ax = [ii], inode number) 3252 <1> ; 02/09/2015 3253 00003EEF 8F05[20650000] <1> pop dword [u.base] 3254 <1> ; mov (sp)+,r3 / move u.off to r3 (points to buffer) 3255 00003EF5 E861000000 <1> call sysstat_gpa ; get physical address 3256 00003EFA 730A <1> jnc short sysstat2 3257 <1> sysstat_err1: 3258 00003EFC A3[4F650000] <1> mov dword [u.error], eax ; error code 3259 00003F01 E9DBF1FFFF <1> jmp error 3260 <1> sysstat2: 3261 00003F06 A0[E0640000] <1> mov al, [ii] ; 07/10/2015 (result of 'iget' call, above) 3262 00003F0B AA <1> stosb 3263 00003F0C FF05[20650000] <1> inc dword [u.base] 3264 <1> ;dec cx 3265 <1> ; 03/02/2022 3266 00003F12 49 <1> dec ecx 3267 00003F13 7505 <1> jnz short sysstat3 3268 00003F15 E841000000 <1> call sysstat_gpa 3269 <1> ;jc short sysstat_err1 3270 <1> sysstat3: 3271 00003F1A A0[E1640000] <1> mov al, [ii+1] ; 07/10/2015 (result of 'iget' call, above) 3272 00003F1F AA <1> stosb 3273 <1> ; mov r1,(r3)+ / put i-number in 1st word of buffer 3274 00003F20 FF05[20650000] <1> inc dword [u.base] 3275 <1> ;;dec word [u.pcount] 3276 <1> ;dec cx 3277 <1> ; 03/02/2022 3278 00003F26 49 <1> dec ecx 3279 00003F27 7505 <1> jnz short sysstat4 3280 00003F29 E82D000000 <1> call sysstat_gpa 3281 <1> ;jc short sysstat_err1 3282 <1> sysstat4: 3283 00003F2E BE[F4610000] <1> mov esi, inode 3284 <1> ; mov $inode,r2 / r2 points to i-node 3285 <1> sysstat5: ; 1: 3286 00003F33 A4 <1> movsb 3287 <1> ; mov (r2)+,(r3)+ / move rest of i-node to buffer 3288 00003F34 FF05[20650000] <1> inc dword [u.base] 3289 <1> ;;dec word [u.pcount] 3290 <1> ;dec cx 3291 <1> ; 03/02/2022 3292 00003F3A 49 <1> dec ecx 3293 00003F3B 7505 <1> jnz short sysstat6 3294 00003F3D E819000000 <1> call sysstat_gpa 3295 <1> ;jc short sysstat_err1 3296 <1> sysstat6: 3297 00003F42 81FE[14620000] <1> cmp esi, inode + 32 3298 <1> ; cmp r2,$inode+32 / done? 3299 00003F48 75E9 <1> jne short sysstat5 3300 <1> ; bne 1b / no, go back 3301 <1> 3302 <1> ;;; 3303 <1> ; 09/05/2022 3304 <1> ;*** additional feature *** -retro unix only- 3305 <1> ; 3306 <1> ; !! return device number -of current inode- in eax !! 3307 <1> ; 3308 <1> ; (modification reason/purpose: 3309 <1> ; to improve 'pwd' command's pathname output/result 3310 <1> ; and to correct 'cp' command's 'can not copy file itself' 3311 <1> ; error due to same inode numbers in root file system 3312 <1> ; and mounted file system.) 3313 <1> ; 3314 00003F4A 29C0 <1> sub eax, eax 3315 00003F4C A0[E2640000] <1> mov al, [idev] ; [cdev] 3316 00003F51 A3[00650000] <1> mov [u.r0], eax 3317 <1> ;;; 3318 <1> 3319 00003F56 E9A6F1FFFF <1> jmp sysret 3320 <1> ; br sysret3 / return through sysret 3321 <1> ; 3322 <1> sysstat_gpa: ; get physical address of file status buffer 3323 <1> ; 02/09/2015 3324 00003F5B 8B1D[20650000] <1> mov ebx, [u.base] 3325 <1> ; 07/10/2015 3326 00003F61 E863E8FFFF <1> call get_physical_addr ; get physical address 3327 <1> ;jc short sysstat_gpa1 3328 00003F66 7294 <1> jc short sysstat_err1 3329 <1> ; 18/10/2015 3330 00003F68 89C7 <1> mov edi, eax ; physical address 3331 <1> ;mov [u.pcount], cx ; remain bytes in page 3332 <1> ;sysstat_gpa1: 3333 00003F6A C3 <1> retn 3334 <1> 3335 <1> fclose: 3336 <1> ; 03/02/2022 3337 <1> ; 18/06/2015 (Retro UNIX 386 v1 - Beginning) 3338 <1> ; (32 bit offset pointer modification) 3339 <1> ; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1) 3340 <1> ; 3341 <1> ; Given the file descriptor (index to the u.fp list) 3342 <1> ; 'fclose' first gets the i-number of the file via 'getf'. 3343 <1> ; If i-node is active (i-number > 0) the entry in 3344 <1> ; u.fp list is cleared. If all the processes that opened 3345 <1> ; that file close it, then fsp etry is freed and the file 3346 <1> ; is closed. If not a return is taken. 3347 <1> ; If the file has been deleted while open, 'anyi' is called 3348 <1> ; to see anyone else has it open, i.e., see if it is appears 3349 <1> ; in another entry in the fsp table. Upon return from 'anyi' 3350 <1> ; a check is made to see if the file is special. 3351 <1> ; 3352 <1> ; INPUTS -> 3353 <1> ; r1 - contains the file descriptor (value=0,1,2...) 3354 <1> ; u.fp - list of entries in the fsp table 3355 <1> ; fsp - table of entries (4 words/entry) of open files. 3356 <1> ; OUTPUTS -> 3357 <1> ; r1 - contains the same file descriptor 3358 <1> ; r2 - contains i-number 3359 <1> ; 3360 <1> ; ((AX = R1)) 3361 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 3362 <1> ; 3363 <1> ; Retro UNIX 8086 v1 modification : CF = 1 3364 <1> ; if i-number of the file is 0. (error) 3365 <1> 3366 <1> ;movzx edx, ax ; ** 3367 <1> ; 03/02/2022 3368 <1> ;movzx edx, al 3369 00003F6B 89C2 <1> mov edx, eax ; eax <= 10 ; 03/02/2022 3370 00003F6D 50 <1> push eax ; *** 3371 <1> ;push ax ; *** 3372 <1> ; mov r1,-(sp) / put r1 on the stack (it contains 3373 <1> ; / the index to u.fp list) 3374 00003F6E E839000000 <1> call getf 3375 <1> ; jsr r0,getf / r1 contains i-number, 3376 <1> ; / cdev has device =, u.fofp 3377 <1> ; / points to 3rd word of fsp entry 3378 00003F73 6683F801 <1> cmp ax, 1 ; r1 3379 <1> ; tst r1 / is i-number 0? 3380 00003F77 7231 <1> jb short fclose_2 3381 <1> ; beq 1f / yes, i-node not active so return 3382 <1> ; tst (r0)+ / no, jump over error return 3383 00003F79 89D3 <1> mov ebx, edx ; ** 3384 <1> ; 03/02/2022 3385 00003F7B 89C2 <1> mov edx, eax ; * 3386 <1> ;mov dx, ax ; * 3387 <1> ; mov r1,r2 / move i-number to r2 ;* 3388 <1> ; mov (sp),r1 / restore value of r1 from the stack 3389 <1> ; / which is index to u.fp ; ** 3390 00003F7D C683[06650000]00 <1> mov byte [ebx+u.fp], 0 3391 <1> ; clrb u.fp(r1) / clear that entry in the u.fp list 3392 00003F84 8B1D[10650000] <1> mov ebx, [u.fofp] 3393 <1> ; mov u.fofp,r1 / r1 points to 3rd word in fsp entry 3394 <1> fclose_0: 3395 00003F8A FE4B04 <1> dec byte [ebx+4] ; 18/06/2015 3396 <1> ; decb 2(r1) / decrement the number of processes 3397 <1> ; / that have opened the file 3398 00003F8D 791B <1> jns short fclose_2 ; jump if not negative (jump if bit 7 is 0) 3399 <1> ; bge 1f / if all processes haven't closed the file, return 3400 <1> ; 3401 <1> ; 03/02/2022 3402 00003F8F 52 <1> push edx ; * 3403 <1> ;push dx ; * 3404 <1> ; mov r2,-(sp) / put r2 on the stack (i-number) 3405 <1> ;xor ax, ax ; 0 3406 <1> ; 03/02/2022 3407 00003F90 31C0 <1> xor eax, eax 3408 00003F92 668943FC <1> mov [ebx-4], ax ; 0 3409 <1> ; clr -4(r1) / clear 1st word of fsp entry 3410 00003F96 8A4305 <1> mov al, [ebx+5] ; 18/06/2015 3411 <1> ; tstb 3(r1) / has this file been deleted 3412 00003F99 20C0 <1> and al, al 3413 00003F9B 7407 <1> jz short fclose_1 3414 <1> ; beq 2f / no, branch 3415 <1> ; 03/02/2022 3416 00003F9D 89D0 <1> mov eax, edx 3417 <1> ;mov ax, dx ; * 3418 <1> ; mov r2,r1 / yes, put i-number back into r1 3419 <1> ; AX = inode number 3420 00003F9F E8A7040000 <1> call anyi 3421 <1> ; jsr r0,anyi / free all blocks related to i-number 3422 <1> ; / check if file appears in fsp again 3423 <1> fclose_1: ; 2: 3424 <1> ; 03/02/2022 3425 00003FA4 58 <1> pop eax ; * 3426 <1> ;pop ax ; * 3427 <1> ; mov (sp)+,r1 / put i-number back into r1 3428 00003FA5 E8EF110000 <1> call iclose ; close if it is special file 3429 <1> ; jsr r0,iclose / check to see if its a special file 3430 <1> fclose_2: ; 1: 3431 <1> ; 03/02/2022 3432 00003FAA 58 <1> pop eax ; *** 3433 <1> ;pop ax ; *** 3434 <1> ; mov (sp)+,r1 / put index to u.fp back into r1 3435 00003FAB C3 <1> retn 3436 <1> ; rts r0 3437 <1> 3438 <1> getf: ; / get the device number and the i-number of an open file 3439 <1> ; 03/02/2022 3440 <1> ; 13/05/2015 3441 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3442 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 3443 <1> ; 3444 00003FAC 89C3 <1> mov ebx, eax 3445 <1> getf1: ;; Calling point from 'rw1' (23/05/2013) 3446 <1> ; 03/02/2022 3447 00003FAE 29C0 <1> sub eax, eax 3448 <1> ; 3449 00003FB0 83FB0A <1> cmp ebx, 10 3450 <1> ; cmp r1,$10. / user limited to 10 open files 3451 00003FB3 732B <1> jnb short getf2 ; 13/05/2015 3452 <1> ;jnb error 3453 <1> ; bhis error3 / u.fp is table of users open files, 3454 <1> ; / index in fsp table 3455 <1> ; 03/02/2022 3456 00003FB5 8A83[06650000] <1> mov al, [ebx+u.fp] 3457 <1> ;mov bl, [ebx+u.fp] 3458 <1> ; movb u.fp(r1),r1 / r1 contains number of entry 3459 <1> ; / in fsp table 3460 <1> ; 03/02/2022 3461 00003FBB 08C0 <1> or al, al 3462 00003FBD 7421 <1> jz short getf2 3463 <1> ;or bl, bl 3464 <1> ;jnz short getf3 3465 <1> ;;jz short getf4 3466 <1> ; beq 1f / if its zero return 3467 <1> ;getf2: 3468 <1> ; ; 'File not open !' error (ax=0) 3469 <1> ; sub eax, eax 3470 <1> ; retn 3471 <1> 3472 <1> getf3: 3473 <1> ; Retro UNIX 386 v1 modification ! (11/05/2015) 3474 <1> ; 3475 <1> ; 'fsp' table (10 bytes/entry) 3476 <1> ; bit 15 bit 0 3477 <1> ; ---|------------------------------------------- 3478 <1> ; r/w| i-number of open file 3479 <1> ; ---|------------------------------------------- 3480 <1> ; device number 3481 <1> ; ----------------------------------------------- 3482 <1> ; offset pointer, r/w pointer to file (bit 0-15) 3483 <1> ; ----------------------------------------------- 3484 <1> ; offset pointer, r/w pointer to file (bit 16-31) 3485 <1> ; ----------------------|------------------------ 3486 <1> ; flag that says file | number of processes 3487 <1> ; has been deleted | that have file open 3488 <1> ; ----------------------|------------------------ 3489 <1> ; 3490 <1> ;mov eax, 10 3491 <1> ; 03/02/2022 3492 00003FBF B30A <1> mov bl, 10 3493 00003FC1 F6E3 <1> mul bl 3494 00003FC3 BB[BE620000] <1> mov ebx, fsp-6 ; the 3rd word in the fsp entry 3495 00003FC8 01C3 <1> add ebx, eax 3496 <1> ; asl r1 3497 <1> ; asl r1 / multiply by 8 to get index into 3498 <1> ; / fsp table entry 3499 <1> ; asl r1 3500 <1> ; add $fsp-4,r1 / r1 is pointing at the 3rd word 3501 <1> ; / in the fsp entry 3502 00003FCA 891D[10650000] <1> mov [u.fofp], ebx 3503 <1> ; mov r1,u.fofp / save address of 3rd word 3504 <1> ; / in fsp entry in u.fofp 3505 00003FD0 4B <1> dec ebx 3506 00003FD1 4B <1> dec ebx 3507 <1> ;mov al, [ebx] 3508 00003FD2 668B03 <1> mov ax, [ebx] 3509 <1> ;mov [cdev], al ; ;;Retro UNIX 8086 v1 ! 3510 00003FD5 66A3[E4640000] <1> mov [cdev], ax ; ;;in fact (!) 3511 <1> ;;dev number is in 1 byte 3512 <1> ; mov -(r1),cdev / remove the device number cdev 3513 00003FDB 4B <1> dec ebx 3514 00003FDC 4B <1> dec ebx 3515 00003FDD 668B03 <1> mov ax, [ebx] 3516 <1> ; mov -(r1),r1 / and the i-number r1 3517 <1> getf2: ; 03/02/2022 3518 <1> getf4: ; 1: 3519 00003FE0 C3 <1> retn 3520 <1> ; rts r0 3521 <1> 3522 <1> namei: 3523 <1> ; 15/05/2022 3524 <1> ; 14/05/2022 (mounted directory path, '..' method) 3525 <1> ; 03/02/2022 3526 <1> ; 18/10/2015 (nbase, ncount) 3527 <1> ; 12/10/2015 3528 <1> ; 21/08/2015 3529 <1> ; 18/07/2015 3530 <1> ; 02/07/2015 3531 <1> ; 17/06/2015 3532 <1> ; 16/06/2015 (Retro UNIX 386 v1 - Beginning) 3533 <1> ; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 3534 <1> ; 3535 <1> ; 'namei' takes a file path name and returns i-number of 3536 <1> ; the file in the current directory or the root directory 3537 <1> ; (if the first character of the pathname is '/'). 3538 <1> ; 3539 <1> ; INPUTS -> 3540 <1> ; u.namep - points to a file path name 3541 <1> ; u.cdir - i-number of users directory 3542 <1> ; u.cdev - device number on which user directory resides 3543 <1> ; OUTPUTS -> 3544 <1> ; r1 - i-number of file 3545 <1> ; cdev 3546 <1> ; u.dirbuf - points to directory entry where a match 3547 <1> ; occurs in the search for file path name. 3548 <1> ; If no match u.dirb points to the end of 3549 <1> ; the directory and r1 = i-number of the current 3550 <1> ; directory. 3551 <1> ; ((AX = R1)) 3552 <1> ; 3553 <1> ; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM) 3554 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 3555 <1> ; 3556 <1> 3557 00003FE1 66A1[04650000] <1> mov ax, [u.cdir] 3558 <1> ; mov u.cdir,r1 / put the i-number of current directory 3559 <1> ; / in r1 3560 00003FE7 668B15[44650000] <1> mov dx, [u.cdrv] 3561 00003FEE 668915[E4640000] <1> mov [cdev], dx ; NOTE: Retro UNIX 8086 v1 3562 <1> ; device/drive number is in 1 byte, 3563 <1> ; not in 1 word! 3564 <1> ; mov u.cdev,cdev / device number for users directory 3565 <1> ; / into cdev 3566 <1> ; 12/10/2015 3567 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 3568 <1> ; convert virtual (pathname) addr to physical address 3569 00003FF5 E869010000 <1> call trans_addr_nmbp ; 12/10/2015 3570 <1> ; esi = physical address of [u.namep] 3571 <1> ; ecx = byte count in the page 3572 00003FFA 803E2F <1> cmp byte [esi], '/' 3573 <1> ; cmpb *u.namep,$'/ / is first char in file name a / 3574 00003FFD 751D <1> jne short namei_1 3575 <1> ; bne 1f 3576 00003FFF FF05[18650000] <1> inc dword [u.namep] 3577 <1> ; inc u.namep / go to next char 3578 <1> ; 03/02/2022 3579 00004005 49 <1> dec ecx 3580 <1> ;dec cx ; remain byte count in the page 3581 00004006 7506 <1> jnz short namei_0 3582 <1> ; 12/10/2015 3583 00004008 E856010000 <1> call trans_addr_nmbp ; convert virtual address to physical 3584 <1> ; esi = physical address (page start + offset) 3585 <1> ; ecx = byte count in the page 3586 0000400D 4E <1> dec esi 3587 <1> namei_0: 3588 0000400E 46 <1> inc esi ; go to next char 3589 0000400F 66A1[EE640000] <1> mov ax, [rootdir] ; 09/07/2013 3590 <1> ; mov rootdir,r1 / put i-number of rootdirectory in r1 3591 00004015 C605[E4640000]00 <1> mov byte [cdev], 0 3592 <1> ; clr cdev / clear device number 3593 <1> namei_1: ; 1: 3594 0000401C F606FF <1> test byte [esi], 0FFh 3595 <1> namei_10: ; 03/02/2022 (jump from namei_8) 3596 0000401F 74BF <1> jz short getf4 3597 <1> ;jz nig 3598 <1> ; tstb *u.namep / is the character in file name a nul 3599 <1> ; beq nig / yes, end of file name reached; 3600 <1> ; / branch to "nig" 3601 <1> namei_2: ; 1: 3602 <1> ; 18/10/2015 3603 00004021 8935[70650000] <1> mov [nbase], esi 3604 00004027 66890D[74650000] <1> mov [ncount], cx 3605 <1> ; 3606 <1> ;mov dx, 2 3607 0000402E B202 <1> mov dl, 2 ; user flag (read, non-owner) 3608 00004030 E895080000 <1> call access 3609 <1> ; jsr r0,access; 2 / get i-node with i-number r1 3610 <1> ; 'access' will not return here if user has not "r" permission ! 3611 <1> ; 03/02/2022 3612 00004035 F605[F5610000]40 <1> test byte [i.flgs+1], 40h 3613 <1> ;test word [i.flgs], 4000h 3614 <1> ; bit $40000,i.flgs / directory i-node? 3615 0000403C 746A <1> jz short namei_err 3616 <1> ; beq error3 / no, got an error 3617 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 3618 0000403E 31C0 <1> xor eax, eax 3619 00004040 A3[1C650000] <1> mov [u.off], eax ; 0 3620 00004045 66A1[F8610000] <1> mov ax, [i.size] 3621 0000404B A3[14650000] <1> mov [u.dirp], eax 3622 <1> ; mov i.size,u.dirp / put size of directory in u.dirp 3623 <1> ; clr u.off / u.off is file offset used by user 3624 00004050 C705[10650000]- <1> mov dword [u.fofp], u.off 3624 00004056 [1C650000] <1> 3625 <1> ; mov $u.off,u.fofp / u.fofp is a pointer to 3626 <1> ; / the offset portion of fsp entry 3627 <1> namei_3: ; 2: 3628 0000405A C705[20650000]- <1> mov dword [u.base], u.dirbuf 3628 00004060 [32650000] <1> 3629 <1> ; mov $u.dirbuf,u.base / u.dirbuf holds a file name 3630 <1> ; / copied from a directory 3631 00004064 C705[24650000]0A00- <1> mov dword [u.count], 10 3631 0000406C 0000 <1> 3632 <1> ; mov $10.,u.count / u.count is byte count 3633 <1> ; / for reads and writes 3634 0000406E 66A1[E0640000] <1> mov ax, [ii] 3635 <1> ; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall') 3636 00004074 FE05[61650000] <1> inc byte [u.kcall] ; the caller is 'namei' sign 3637 0000407A E84B090000 <1> call readi 3638 <1> ; jsr r0,readi / read 10. bytes of file 3639 <1> ; with i-number (r1); i.e. read a directory entry 3640 0000407F 8B0D[28650000] <1> mov ecx, [u.nread] 3641 00004085 09C9 <1> or ecx, ecx 3642 <1> ; tst u.nread 3643 00004087 741B <1> jz short nib 3644 <1> ; ble nib / gives error return 3645 <1> ; 3646 00004089 668B1D[32650000] <1> mov bx, [u.dirbuf] 3647 00004090 6621DB <1> and bx, bx 3648 <1> ; tst u.dirbuf / 3649 00004093 7522 <1> jnz short namei_4 3650 <1> ; bne 3f / branch when active directory entry 3651 <1> ; / (i-node word in entry non zero) 3652 00004095 A1[1C650000] <1> mov eax, [u.off] 3653 0000409A 83E80A <1> sub eax, 10 3654 0000409D A3[14650000] <1> mov [u.dirp], eax 3655 <1> ; mov u.off,u.dirp 3656 <1> ; sub $10.,u.dirp 3657 000040A2 EBB6 <1> jmp short namei_3 3658 <1> ; br 2b 3659 <1> 3660 <1> ; 18/07/2013 3661 <1> nib: 3662 000040A4 31C0 <1> xor eax, eax ; xor ax, ax ; ax = 0 -> file not found 3663 000040A6 F9 <1> stc 3664 <1> nig: 3665 000040A7 C3 <1> retn 3666 <1> 3667 <1> namei_err: 3668 <1> ; 16/06/2015 3669 000040A8 C705[4F650000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a directory !' error 3669 000040B0 0000 <1> 3670 000040B2 E92AF0FFFF <1> jmp error 3671 <1> 3672 <1> namei_4: ; 3: 3673 <1> ; 18/10/2015 3674 <1> ; 12/10/2015 3675 <1> ; 21/08/2015 3676 <1> ; 18/07/2015 3677 000040B7 8B2D[18650000] <1> mov ebp, [u.namep] 3678 <1> ; mov u.namep,r2 / u.namep points into a file name string 3679 000040BD BF[34650000] <1> mov edi, u.dirbuf + 2 3680 <1> ; mov $u.dirbuf+2,r3 / points to file name of directory entry 3681 <1> ; 18/10/2015 3682 000040C2 8B35[70650000] <1> mov esi, [nbase] 3683 000040C8 668B0D[74650000] <1> mov cx, [ncount] 3684 <1> ; 3685 000040CF 6621C9 <1> and cx, cx 3686 000040D2 7505 <1> jnz short namei_5 3687 <1> ; 3688 000040D4 E890000000 <1> call trans_addr_nm ; convert virtual address to physical 3689 <1> ; esi = physical address (page start + offset) 3690 <1> ; ecx = byte count in the page 3691 <1> namei_5: ; 3: 3692 000040D9 45 <1> inc ebp ; 18/07/2015 3693 000040DA AC <1> lodsb ; mov al, [esi] ; inc esi (al = r4) 3694 <1> ; movb (r2)+,r4 / move a character from u.namep string into r4 3695 000040DB 08C0 <1> or al, al 3696 000040DD 741C <1> jz short namei_7 3697 <1> ; beq 3f / if char is nul, then the last char in string 3698 <1> ; / has been moved 3699 000040DF 3C2F <1> cmp al, '/' 3700 <1> ; cmp r4,$'/ / is char a 3701 000040E1 7418 <1> je short namei_7 3702 <1> ; beq 3f 3703 <1> ; 03/02/2022 3704 000040E3 49 <1> dec ecx 3705 <1> ; 12/10/2015 3706 <1> ;dec cx ; remain byte count in the page 3707 000040E4 7505 <1> jnz short namei_6 3708 000040E6 E87E000000 <1> call trans_addr_nm ; convert virtual address to physical 3709 <1> ; esi = physical address (page start + offset) 3710 <1> ; ecx = byte count in the page 3711 <1> namei_6: 3712 000040EB 81FF[3C650000] <1> cmp edi, u.dirbuf + 10 3713 <1> ; cmp r3,$u.dirbuf+10. / have I checked 3714 <1> ; / all 8 bytes of file name 3715 000040F1 74E6 <1> je short namei_5 3716 <1> ; beq 3b 3717 000040F3 AE <1> scasb 3718 <1> ; cmpb (r3)+,r4 / compare char in u.namep string to file name 3719 <1> ; / char read from directory 3720 000040F4 74E3 <1> je short namei_5 3721 <1> ; beq 3b / branch if chars match 3722 <1> namei_9: 3723 000040F6 E95FFFFFFF <1> jmp namei_3 ; 2b 3724 <1> ; br 2b / file names do not match go to next directory entry 3725 <1> namei_7: ; 3: 3726 000040FB 81FF[3C650000] <1> cmp edi, u.dirbuf + 10 3727 <1> ; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched 3728 00004101 7406 <1> je short namei_8 3729 <1> ; beq 3f 3730 00004103 8A27 <1> mov ah, [edi] 3731 <1> ;inc edi 3732 00004105 20E4 <1> and ah, ah 3733 <1> ; tstb (r3)+ / 3734 <1> ;jnz namei_3 3735 <1> ; bne 2b 3736 <1> ; 03/02/2020 3737 00004107 75ED <1> jnz short namei_9 3738 <1> namei_8: ; 3 3739 00004109 892D[18650000] <1> mov [u.namep], ebp ; 18/07/2015 3740 <1> ; mov r2,u.namep / u.namep points to char 3741 <1> ; / following a / or nul 3742 <1> ;mov bx, [u.dirbuf] 3743 <1> ; mov u.dirbuf,r1 / move i-node number in directory 3744 <1> ; / entry to r1 3745 <1> ;;;; 3746 <1> ; 14/05/2022 - Retro UNIX (8086/386) feature only ! 3747 <1> ; ! 'pwd' utility modification ! 3748 <1> ; ((if directory entry name is a dotdot))) 3749 <1> ;; check if it is mounted device's root directory inode 3750 <1> ; and if so, replace it with parent dir inode number 3751 <1> ; of mounting directory in [mntp]. 3752 <1> 3753 0000410F 668B1D[32650000] <1> mov bx, [u.dirbuf] 3754 <1> 3755 00004116 6683FB29 <1> cmp bx, 41 ; root directory inode number 3756 0000411A 753C <1> jne short namei_11 3757 <1> 3758 0000411C 663B1D[E0640000] <1> cmp bx, [ii] ; for root dir, '.' & '..' is 41 3759 00004123 7533 <1> jne short namei_11 ; not root dir (of mounted dev) 3760 <1> 3761 <1> ;cmp [idev], bh ; 0 3762 00004125 383D[E4640000] <1> cmp [cdev], bh ; 0 3763 <1> ; 0 = root fs, dev num in [rdev] 3764 <1> ; 1 = mounted, dev num in [mdev] 3765 0000412B 762B <1> jna short namei_11 3766 <1> 3767 <1> ; dotdot (parent directory link) check 3768 0000412D 66813D[34650000]2E- <1> cmp word [u.dirbuf+2], '..' 3768 00004135 2E <1> 3769 00004136 7520 <1> jne short namei_11 3770 00004138 803D[36650000]00 <1> cmp byte [u.dirbuf+4], 0 3771 0000413F 7517 <1> jne short namei_11 3772 <1> 3773 <1> ; (This may not be necessary because [idev] = 1 3774 <1> ; and [mnti] is expected as a sub dir inode number) 3775 00004141 66391D[E8640000] <1> cmp [mnti], bx ; 41 3776 00004148 760E <1> jna short namei_11 3777 <1> 3778 <1> ; change inumber to parent dir inum of mount directory 3779 0000414A 668B1D[EA640000] <1> mov bx, [mntp] 3780 00004151 C605[E4640000]00 <1> mov byte [cdev], 0 ; root fs 3781 <1> namei_11: 3782 <1> ;;;; 3783 <1> 3784 00004158 20C0 <1> and al, al 3785 <1> ; tst r4 / if r4 = 0 the end of file name reached, 3786 <1> ; / if r4 = then go to next directory 3787 <1> ; 15/05/2022 3788 0000415A 6689D8 <1> mov ax, bx 3789 <1> ;mov ax, [u.dirbuf] ; 17/06/2015 3790 <1> ; 03/02/2022 3791 0000415D E9BDFEFFFF <1> jmp namei_10 ; (jnz short namei_2, retn) 3792 <1> ;jnz namei_2 3793 <1> ; bne 1b 3794 <1> ; AX = i-number of the file 3795 <1> ;;nig: 3796 00004162 C3 <1> retn 3797 <1> ; tst (r0)+ / gives non-error return 3798 <1> ;;nib: 3799 <1> ;; xor ax, ax ; Retro UNIX 8086 v1 modification ! 3800 <1> ; ax = 0 -> file not found 3801 <1> ;; stc ; 27/05/2013 3802 <1> ;; retn 3803 <1> ; rts r0 3804 <1> 3805 <1> trans_addr_nmbp: 3806 <1> ; 03/02/2022 3807 <1> ; 18/10/2015 3808 <1> ; 12/10/2015 3809 00004163 8B2D[18650000] <1> mov ebp, [u.namep] 3810 <1> trans_addr_nm: 3811 <1> ; 03/02/2022 3812 <1> ; Convert virtual (pathname) address to physical address 3813 <1> ; (Retro UNIX 386 v1 feature only !) 3814 <1> ; 18/10/2015 3815 <1> ; 12/10/2015 (u.pnbase & u.pncount has been removed from code) 3816 <1> ; 02/07/2015 3817 <1> ; 17/06/2015 3818 <1> ; 16/06/2015 3819 <1> ; 3820 <1> ; INPUTS: 3821 <1> ; ebp = pathname address (virtual) ; [u.namep] 3822 <1> ; [u.pgdir] = user's page directory 3823 <1> ; OUTPUT: 3824 <1> ; esi = physical address of the pathname 3825 <1> ; ecx = remain byte count in the page 3826 <1> ; 3827 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI) 3828 <1> ; 3829 <1> 3830 <1> ; 03/02/2022 3831 00004169 29C9 <1> sub ecx, ecx 3832 <1> 3833 0000416B 833D[57650000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? (sysexec) 3834 00004172 7618 <1> jna short trans_addr_nmk ; the caller is os kernel; 3835 <1> ; it is already physical address 3836 00004174 50 <1> push eax 3837 00004175 89EB <1> mov ebx, ebp ; [u.namep] ; pathname address (virtual) 3838 00004177 E84DE6FFFF <1> call get_physical_addr ; get physical address 3839 0000417C 7204 <1> jc short tr_addr_nm_err 3840 <1> ; 18/10/2015 3841 <1> ; eax = physical address 3842 <1> ; cx = remain byte count in page (1-4096) 3843 <1> ; 12/10/2015 (cx = [u.pncount]) 3844 0000417E 89C6 <1> mov esi, eax ; 12/10/2015 (esi=[u.pnbase]) 3845 00004180 58 <1> pop eax 3846 00004181 C3 <1> retn 3847 <1> 3848 <1> tr_addr_nm_err: 3849 00004182 A3[4F650000] <1> mov [u.error], eax 3850 <1> ;pop eax 3851 00004187 E955EFFFFF <1> jmp error 3852 <1> 3853 <1> trans_addr_nmk: 3854 <1> ; 12/10/2015 3855 <1> ; 02/07/2015 3856 0000418C 8B35[18650000] <1> mov esi, [u.namep] ; [u.pnbase] 3857 <1> ;mov cx, PAGE_SIZE ; 4096 ; [u.pncount] 3858 <1> ; 03/02/2022 3859 00004192 B510 <1> mov ch, PAGE_SIZE/256 3860 00004194 C3 <1> retn 3861 <1> 3862 <1> syschdir: 3863 <1> ; 03/02/2022 3864 <1> ; / makes the directory specified in the argument 3865 <1> ; / the current directory 3866 <1> ; 3867 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3868 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3869 <1> ; 3870 <1> ; 'syschdir' makes the directory specified in its argument 3871 <1> ; the current working directory. 3872 <1> ; 3873 <1> ; Calling sequence: 3874 <1> ; syschdir; name 3875 <1> ; Arguments: 3876 <1> ; name - address of the path name of a directory 3877 <1> ; terminated by nul byte. 3878 <1> ; Inputs: - 3879 <1> ; Outputs: - 3880 <1> ; ............................................................... 3881 <1> ; 3882 <1> ; Retro UNIX 8086 v1 modification: 3883 <1> ; The user/application program puts address of 3884 <1> ; the path name in BX register as 'syschdir' 3885 <1> ; system call argument. 3886 <1> 3887 00004195 891D[18650000] <1> mov [u.namep], ebx 3888 <1> ;jsr r0,arg; u.namep / u.namep points to path name 3889 0000419B E841FEFFFF <1> call namei 3890 <1> ; jsr r0,namei / find its i-number 3891 <1> ;jc error 3892 <1> ; br error3 3893 000041A0 730F <1> jnc short syschdir0 3894 <1> ; 'directory not found !' error 3895 000041A2 C705[4F650000]0C00- <1> mov dword [u.error], ERR_DIR_NOT_FOUND ; 12 3895 000041AA 0000 <1> 3896 000041AC E930EFFFFF <1> jmp error 3897 <1> syschdir0: 3898 <1> ; 03/02/2022 3899 000041B1 B202 <1> mov dl, 2 ; read access ; 03/02/2022 (BugFix) 3900 000041B3 E812070000 <1> call access 3901 <1> ; jsr r0,access; 2 / get i-node into core 3902 <1> ; 03/02/2022 3903 000041B8 F605[F5610000]40 <1> test byte [i.flgs+1], 40h 3904 <1> ;test word [i.flgs], 4000h 3905 <1> ; bit $40000,i.flgs / is it a directory? 3906 <1> ;jz error 3907 <1> ; beq error3 / no error 3908 000041BF 750F <1> jnz short syschdir1 3909 000041C1 C705[4F650000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 3909 000041C9 0000 <1> 3910 000041CB E911EFFFFF <1> jmp error 3911 <1> syschdir1: 3912 000041D0 66A3[04650000] <1> mov [u.cdir], ax 3913 <1> ; mov r1,u.cdir / move i-number to users 3914 <1> ; / current directory 3915 000041D6 66A1[E4640000] <1> mov ax, [cdev] 3916 000041DC 66A3[44650000] <1> mov [u.cdrv], ax 3917 <1> ; mov cdev,u.cdev / move its device to users 3918 <1> ; / current device 3919 000041E2 E91AEFFFFF <1> jmp sysret 3920 <1> ; br sysret3 3921 <1> 3922 <1> syschmod: ; < change mode of file > 3923 <1> ; 29/04/2022 (bugfix) 3924 <1> ; 03/02/2022 3925 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3926 <1> ; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1) 3927 <1> ; 3928 <1> ; 'syschmod' changes mode of the file whose name is given as 3929 <1> ; null terminated string pointed to by 'name' has it's mode 3930 <1> ; changed to 'mode'. 3931 <1> ; 3932 <1> ; Calling sequence: 3933 <1> ; syschmod; name; mode 3934 <1> ; Arguments: 3935 <1> ; name - address of the file name 3936 <1> ; terminated by null byte. 3937 <1> ; mode - (new) mode/flags < attributes > 3938 <1> ; 3939 <1> ; Inputs: - 3940 <1> ; Outputs: - 3941 <1> ; ............................................................... 3942 <1> ; 3943 <1> ; Retro UNIX 8086 v1 modification: 3944 <1> ; 'syschmod' system call has two arguments; so, 3945 <1> ; * 1st argument, name is pointed to by BX register 3946 <1> ; * 2nd argument, mode is in CX register 3947 <1> ; 3948 <1> ; Mode bits (Flags): 3949 <1> ; bit 0 - write permission for non-owner (1) 3950 <1> ; bit 1 - read permission for non-owner (2) 3951 <1> ; bit 2 - write permission for owner (4) 3952 <1> ; bit 3 - read permission for owner (8) 3953 <1> ; bit 4 - executable flag (16) 3954 <1> ; bit 5 - set user ID on execution flag (32) 3955 <1> ; bit 6,7,8,9,10,11 are not used (undefined) 3956 <1> ; bit 12 - large file flag (4096) 3957 <1> ; bit 13 - file has modified flag (always on) (8192) 3958 <1> ; bit 14 - directory flag (16384) 3959 <1> ; bit 15 - 'i-node is allocated' flag (32768) 3960 <1> 3961 <1> ; / name; mode 3962 000041E7 E815000000 <1> call isown 3963 <1> ;jsr r0,isown / get the i-node and check user status 3964 <1> ; 03/02/2022 3965 000041EC F605[F5610000]40 <1> test byte [i.flgs+1], 40h 3966 <1> ;test word [i.flgs], 4000h 3967 <1> ; bit $40000,i.flgs / directory? 3968 000041F3 7402 <1> jz short syschmod1 3969 <1> ; beq 2f / no 3970 <1> ; AL = (new) mode 3971 000041F5 24CF <1> and al, 0CFh ; 11001111b (clears bit 4 & 5) 3972 <1> ; bic $60,r2 / su & ex / yes, clear set user id and 3973 <1> ; / executable modes 3974 <1> syschmod1: ; 2: 3975 000041F7 A2[F4610000] <1> mov [i.flgs], al 3976 <1> ; movb r2,i.flgs / move remaining mode to i.flgs 3977 <1> ;jmp short isown1 3978 <1> ; ; br 1f ; (jmp sysret4) 3979 <1> ; 29/04/2022 3980 000041FC E900EFFFFF <1> jmp sysret 3981 <1> 3982 <1> isown: 3983 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 3984 <1> ; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1) 3985 <1> ; 3986 <1> ; 'isown' is given a file name (the 1st argument). 3987 <1> ; It find the i-number of that file via 'namei' 3988 <1> ; then gets the i-node into core via 'iget'. 3989 <1> ; It then tests to see if the user is super user. 3990 <1> ; If not, it cheks to see if the user is owner of 3991 <1> ; the file. If he is not an error occurs. 3992 <1> ; If user is the owner 'setimod' is called to indicate 3993 <1> ; the inode has been modificed and the 2nd argument of 3994 <1> ; the call is put in r2. 3995 <1> ; 3996 <1> ; INPUTS -> 3997 <1> ; arguments of syschmod and syschown calls 3998 <1> ; OUTPUTS -> 3999 <1> ; u.uid - id of user 4000 <1> ; imod - set to a 1 4001 <1> ; r2 - contains second argument of the system call 4002 <1> ; 4003 <1> ; ((AX=R2) output as 2nd argument) 4004 <1> ; 4005 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 4006 <1> ; 4007 <1> ; jsr r0,arg2 / u.namep points to file name 4008 <1> ;; ! 2nd argument on top of stack ! 4009 <1> ;; 22/06/2015 - 32 bit modifications 4010 <1> ;; 07/07/2013 4011 00004201 891D[18650000] <1> mov [u.namep], ebx ;; 1st argument 4012 00004207 51 <1> push ecx ;; 2nd argument 4013 <1> ;; 4014 00004208 E8D4FDFFFF <1> call namei 4015 <1> ; jsr r0,namei / get its i-number 4016 <1> ; Retro UNIX 8086 v1 modification ! 4017 <1> ; ax = 0 -> file not found 4018 <1> ;and ax, ax 4019 <1> ;jz error 4020 <1> ;jc error ; 27/05/2013 4021 <1> ; br error3 4022 0000420D 730F <1> jnc short isown0 4023 <1> ; 'file not found !' error 4024 0000420F C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 4024 00004217 0000 <1> 4025 00004219 E9C3EEFFFF <1> jmp error 4026 <1> isown0: 4027 0000421E E8D3050000 <1> call iget 4028 <1> ; jsr r0,iget / get i-node into core 4029 00004223 A0[46650000] <1> mov al, [u.uid] ; 02/08/2013 4030 00004228 08C0 <1> or al, al 4031 <1> ; tstb u.uid / super user? 4032 0000422A 7417 <1> jz short isown1 4033 <1> ; beq 1f / yes, branch 4034 0000422C 3A05[F7610000] <1> cmp al, [i.uid] 4035 <1> ; cmpb i.uid,u.uid / no, is this the owner of 4036 <1> ; / the file 4037 <1> ;jne error 4038 <1> ; beq 1f / yes 4039 <1> ; jmp error3 / no, error 4040 00004232 740F <1> je short isown1 4041 <1> 4042 00004234 C705[4F650000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER ; 11 4042 0000423C 0000 <1> 4043 <1> ; 'permission denied !' error 4044 0000423E E99EEEFFFF <1> jmp error 4045 <1> isown1: ; 1: 4046 00004243 E8B8060000 <1> call setimod 4047 <1> ; jsr r0,setimod / indicates 4048 <1> ; ; / i-node has been modified 4049 00004248 58 <1> pop eax ; 2nd argument 4050 <1> ; mov (sp)+,r2 / mode is put in r2 4051 <1> ; / (u.off put on stack with 2nd arg) 4052 00004249 C3 <1> retn 4053 <1> ; rts r0 4054 <1> 4055 <1> ;;arg: ; < get system call arguments > 4056 <1> ; 'arg' extracts an argument for a routine whose call is 4057 <1> ; of form: 4058 <1> ; sys 'routine' ; arg1 4059 <1> ; or 4060 <1> ; sys 'routine' ; arg1 ; arg2 4061 <1> ; or 4062 <1> ; sys 'routine' ; arg1;...;arg10 (sys exec) 4063 <1> ; 4064 <1> ; INPUTS -> 4065 <1> ; u.sp+18 - contains a pointer to one of arg1..argn 4066 <1> ; This pointers's value is actually the value of 4067 <1> ; update pc at the the trap to sysent (unkni) is 4068 <1> ; made to process the sys instruction 4069 <1> ; r0 - contains the return address for the routine 4070 <1> ; that called arg. The data in the word pointer 4071 <1> ; to by the return address is used as address 4072 <1> ; in which the extracted argument is stored 4073 <1> ; 4074 <1> ; OUTPUTS -> 4075 <1> ; 'address' - contains the extracted argument 4076 <1> ; u.sp+18 - is incremented by 2 4077 <1> ; r1 - contains the extracted argument 4078 <1> ; r0 - points to the next instruction to be 4079 <1> ; executed in the calling routine. 4080 <1> ; 4081 <1> 4082 <1> ; mov u.sp,r1 4083 <1> ; mov *18.(r1),*(r0)+ / put argument of system call 4084 <1> ; / into argument of arg2 4085 <1> ; add $2,18.(r1) / point pc on stack 4086 <1> ; / to next system argument 4087 <1> ; rts r0 4088 <1> 4089 <1> ;;arg2: ; < get system calls arguments - with file name pointer> 4090 <1> ; 'arg2' takes first argument in system call 4091 <1> ; (pointer to name of the file) and puts it in location 4092 <1> ; u.namep; takes second argument and puts it in u.off 4093 <1> ; and on top of the stack 4094 <1> ; 4095 <1> ; INPUTS -> 4096 <1> ; u.sp, r0 4097 <1> ; 4098 <1> ; OUTPUTS -> 4099 <1> ; u.namep 4100 <1> ; u.off 4101 <1> ; u.off pushed on stack 4102 <1> ; r1 4103 <1> ; 4104 <1> 4105 <1> ; jsr r0,arg; u.namep / u.namep contains value of 4106 <1> ; / first arg in sys call 4107 <1> ; jsr r0,arg; u.off / u.off contains value of 4108 <1> ; / second arg in sys call 4109 <1> ; mov r0,r1 / r0 points to calling routine 4110 <1> ; mov (sp),r0 / put operation code back in r0 4111 <1> ; mov u.off,(sp) / put pointer to second argument 4112 <1> ; / on stack 4113 <1> ; jmp (r1) / return to calling routine 4114 <1> 4115 <1> syschown: ; < change owner of file > 4116 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4117 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4118 <1> ; 4119 <1> ; 'syschown' changes the owner of the file whose name is given 4120 <1> ; as null terminated string pointed to by 'name' has it's owner 4121 <1> ; changed to 'owner' 4122 <1> ; 4123 <1> ; Calling sequence: 4124 <1> ; syschown; name; owner 4125 <1> ; Arguments: 4126 <1> ; name - address of the file name 4127 <1> ; terminated by null byte. 4128 <1> ; owner - (new) owner (number/ID) 4129 <1> ; 4130 <1> ; Inputs: - 4131 <1> ; Outputs: - 4132 <1> ; ............................................................... 4133 <1> ; 4134 <1> ; Retro UNIX 8086 v1 modification: 4135 <1> ; 'syschown' system call has two arguments; so, 4136 <1> ; * 1st argument, name is pointed to by BX register 4137 <1> ; * 2nd argument, owner number is in CX register 4138 <1> ; 4139 <1> ; / name; owner 4140 0000424A E8B2FFFFFF <1> call isown 4141 <1> ; jsr r0,isown / get the i-node and check user status 4142 0000424F 803D[46650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 4143 <1> ; tstb u.uid / super user 4144 00004256 7418 <1> jz short syschown1 4145 <1> ; beq 2f / yes, 2f 4146 00004258 F605[F4610000]20 <1> test byte [i.flgs], 20h ; 32 4147 <1> ; bit $40,i.flgs / no, set userid on execution? 4148 <1> ;jnz error 4149 <1> ; bne 3f / yes error, could create Trojan Horses 4150 0000425F 740F <1> jz short syschown1 4151 <1> ; 'permission denied !' 4152 00004261 C705[4F650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; 11 4152 00004269 0000 <1> 4153 0000426B E971EEFFFF <1> jmp error 4154 <1> syschown1: ; 2: 4155 <1> ; AL = owner (number/ID) 4156 00004270 A2[F7610000] <1> mov [i.uid], al ; 23/06/2015 4157 <1> ; movb r2,i.uid / no, put the new owners id 4158 <1> ; / in the i-node 4159 00004275 E987EEFFFF <1> jmp sysret 4160 <1> ; 1: 4161 <1> ; jmp sysret4 4162 <1> ; 3: 4163 <1> ; jmp error 4164 <1> 4165 <1> systime: ; / get time of year 4166 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4167 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 4168 <1> ; 4169 <1> ; 20/06/2013 4170 <1> ; 'systime' gets the time of the year. 4171 <1> ; The present time is put on the stack. 4172 <1> ; 4173 <1> ; Calling sequence: 4174 <1> ; systime 4175 <1> ; Arguments: - 4176 <1> ; 4177 <1> ; Inputs: - 4178 <1> ; Outputs: sp+2, sp+4 - present time 4179 <1> ; ............................................................... 4180 <1> ; 4181 <1> ; Retro UNIX 8086 v1 modification: 4182 <1> ; 'systime' system call will return to the user 4183 <1> ; with unix time (epoch) in DX:AX register pair 4184 <1> ; 4185 <1> ; !! Major modification on original Unix v1 'systime' 4186 <1> ; system call for PC compatibility !! 4187 <1> 4188 0000427A E8B3E9FFFF <1> call epoch 4189 0000427F A3[00650000] <1> mov [u.r0], eax 4190 <1> ; mov s.time,4(sp) 4191 <1> ; mov s.time+2,2(sp) / put the present time 4192 <1> ; / on the stack 4193 <1> ; br sysret4 4194 00004284 E978EEFFFF <1> jmp sysret 4195 <1> 4196 <1> sysstime: ; / set time 4197 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4198 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4199 <1> ; 4200 <1> ; 'sysstime' sets the time. Only super user can use this call. 4201 <1> ; 4202 <1> ; Calling sequence: 4203 <1> ; sysstime 4204 <1> ; Arguments: - 4205 <1> ; 4206 <1> ; Inputs: sp+2, sp+4 - time system is to be set to. 4207 <1> ; Outputs: - 4208 <1> ; ............................................................... 4209 <1> ; 4210 <1> ; Retro UNIX 8086 v1 modification: 4211 <1> ; the user calls 'sysstime' with unix (epoch) time 4212 <1> ; (to be set) is in CX:BX register pair as two arguments. 4213 <1> ; 4214 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 4215 <1> ; to get sysstime system call arguments from the user; 4216 <1> ; * 1st argument, lowword of unix time is in BX register 4217 <1> ; * 2nd argument, highword of unix time is in CX register 4218 <1> ; 4219 <1> ; !! Major modification on original Unix v1 'sysstime' 4220 <1> ; system call for PC compatibility !! 4221 <1> 4222 00004289 803D[46650000]00 <1> cmp byte [u.uid], 0 4223 <1> ; tstb u.uid / is user the super user 4224 <1> ;ja error 4225 <1> ; bne error4 / no, error 4226 00004290 760F <1> jna short systime1 4227 <1> ; 'permission denied !' 4228 00004292 C705[4F650000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 4228 0000429A 0000 <1> 4229 0000429C E940EEFFFF <1> jmp error 4230 <1> systime1: 4231 <1> ; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version) 4232 <1> ; EBX = unix (epoch) time (from user) 4233 000042A1 89D8 <1> mov eax, ebx 4234 000042A3 E807EBFFFF <1> call set_date_time 4235 <1> ; mov 4(sp),s.time 4236 <1> ; mov 2(sp),s.time+2 / set the system time 4237 000042A8 E954EEFFFF <1> jmp sysret 4238 <1> ; br sysret4 4239 <1> 4240 <1> sysbreak: 4241 <1> ; 18/10/2015 4242 <1> ; 07/10/2015 4243 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4244 <1> ; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1) 4245 <1> ; 4246 <1> ; 'sysbreak' sets the programs break points. 4247 <1> ; It checks the current break point (u.break) to see if it is 4248 <1> ; between "core" and the stack (sp). If it is, it is made an 4249 <1> ; even address (if it was odd) and the area between u.break 4250 <1> ; and the stack is cleared. The new breakpoint is then put 4251 <1> ; in u.break and control is passed to 'sysret'. 4252 <1> ; 4253 <1> ; Calling sequence: 4254 <1> ; sysbreak; addr 4255 <1> ; Arguments: - 4256 <1> ; 4257 <1> ; Inputs: u.break - current breakpoint 4258 <1> ; Outputs: u.break - new breakpoint 4259 <1> ; area between old u.break and the stack (sp) is cleared. 4260 <1> ; ............................................................... 4261 <1> ; 4262 <1> ; Retro UNIX 8086 v1 modification: 4263 <1> ; The user/application program puts breakpoint address 4264 <1> ; in BX register as 'sysbreak' system call argument. 4265 <1> ; (argument transfer method 1) 4266 <1> ; 4267 <1> ; NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 ! 4268 <1> ; ((!'sysbreak' is not needed in Retro UNIX 8086 v1!)) 4269 <1> ; NOTE: 4270 <1> ; 'sysbreak' clears extended part (beyond of previous 4271 <1> ; 'u.break' address) of user's memory for original unix's 4272 <1> ; 'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013) 4273 <1> 4274 <1> ; mov u.break,r1 / move users break point to r1 4275 <1> ; cmp r1,$core / is it the same or lower than core? 4276 <1> ; blos 1f / yes, 1f 4277 <1> ; 23/06/2015 4278 000042AD 8B2D[2C650000] <1> mov ebp, [u.break] ; virtual address (offset) 4279 <1> ;and ebp, ebp 4280 <1> ;jz short sysbreak_3 4281 <1> ; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!! 4282 <1> ; (Even break point address is not needed for Retro UNIX 386 v1) 4283 000042B3 8B15[F8640000] <1> mov edx, [u.sp] ; kernel stack at the beginning of sys call 4284 000042B9 83C20C <1> add edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 4285 <1> ; 07/10/2015 4286 000042BC 891D[2C650000] <1> mov [u.break], ebx ; virtual address !!! 4287 <1> ; 4288 000042C2 3B1A <1> cmp ebx, [edx] ; compare new break point with 4289 <1> ; with top of user's stack (virtual!) 4290 000042C4 7327 <1> jnb short sysbreak_3 4291 <1> ; cmp r1,sp / is it the same or higher 4292 <1> ; / than the stack? 4293 <1> ; bhis 1f / yes, 1f 4294 000042C6 89DE <1> mov esi, ebx 4295 000042C8 29EE <1> sub esi, ebp ; new break point - old break point 4296 000042CA 7621 <1> jna short sysbreak_3 4297 <1> ;push ebx 4298 <1> sysbreak_1: 4299 000042CC 89EB <1> mov ebx, ebp 4300 000042CE E8F6E4FFFF <1> call get_physical_addr ; get physical address 4301 000042D3 0F82A9FEFFFF <1> jc tr_addr_nm_err 4302 <1> ; 18/10/2015 4303 000042D9 89C7 <1> mov edi, eax 4304 000042DB 29C0 <1> sub eax, eax ; 0 4305 <1> ; ECX = remain byte count in page (1-4096) 4306 000042DD 39CE <1> cmp esi, ecx 4307 000042DF 7302 <1> jnb short sysbreak_2 4308 000042E1 89F1 <1> mov ecx, esi 4309 <1> sysbreak_2: 4310 000042E3 29CE <1> sub esi, ecx 4311 000042E5 01CD <1> add ebp, ecx 4312 000042E7 F3AA <1> rep stosb 4313 000042E9 09F6 <1> or esi, esi 4314 000042EB 75DF <1> jnz short sysbreak_1 4315 <1> ; 4316 <1> ; bit $1,r1 / is it an odd address 4317 <1> ; beq 2f / no, its even 4318 <1> ; clrb (r1)+ / yes, make it even 4319 <1> ; 2: / clear area between the break point and the stack 4320 <1> ; cmp r1,sp / is it higher or same than the stack 4321 <1> ; bhis 1f / yes, quit 4322 <1> ; clr (r1)+ / clear word 4323 <1> ; br 2b / go back 4324 <1> ;pop ebx 4325 <1> sysbreak_3: ; 1: 4326 <1> ;mov [u.break], ebx ; virtual address !!! 4327 <1> ; jsr r0,arg; u.break / put the "address" 4328 <1> ; / in u.break (set new break point) 4329 <1> ; br sysret4 / br sysret 4330 000042ED E90FEEFFFF <1> jmp sysret 4331 <1> 4332 <1> maknod: 4333 <1> ; 12/02/2022 4334 <1> ; 03/02/2022 4335 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4336 <1> ; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4337 <1> ; 4338 <1> ; 'maknod' creates an i-node and makes a directory entry 4339 <1> ; for this i-node in the current directory. 4340 <1> ; 4341 <1> ; INPUTS -> 4342 <1> ; r1 - contains mode 4343 <1> ; ii - current directory's i-number 4344 <1> ; 4345 <1> ; OUTPUTS -> 4346 <1> ; u.dirbuf - contains i-number of free i-node 4347 <1> ; i.flgs - flags in new i-node 4348 <1> ; i.uid - filled with u.uid 4349 <1> ; i.nlks - 1 is put in the number of links 4350 <1> ; i.ctim - creation time 4351 <1> ; i.ctim+2 - modification time 4352 <1> ; imod - set via call to setimod 4353 <1> ; 4354 <1> ; ((AX = R1)) input 4355 <1> ; 4356 <1> ; (Retro UNIX Prototype : 4357 <1> ; 30/10/2012 - 01/03/2013, UNIXCOPY.ASM) 4358 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 4359 <1> 4360 <1> ; / r1 contains the mode 4361 000042F2 80CC80 <1> or ah, 80h ; 10000000b 4362 <1> ; bis $100000,r1 / allocate flag set 4363 000042F5 6650 <1> push ax ; * 4364 <1> ; mov r1,-(sp) / put mode on stack 4365 <1> ; 31/07/2013 4366 000042F7 66A1[E0640000] <1> mov ax, [ii] ; move current i-number to AX/r1 4367 <1> ; mov ii,r1 / move current i-number to r1 4368 000042FD B201 <1> mov dl, 1 ; owner flag mask 4369 000042FF E8C6050000 <1> call access 4370 <1> ; jsr r0,access; 1 / get its i-node into core 4371 <1> ; 03/02/2022 4372 00004304 50 <1> push eax ; ** 4373 <1> ;push ax 4374 <1> ; mov r1,-(sp) / put i-number on stack 4375 00004305 66B82800 <1> mov ax, 40 4376 <1> ; mov $40.,r1 / r1 = 40 4377 <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions) 4378 00004309 6640 <1> inc ax 4379 <1> ; inc r1 / r1 = r1 + 1 4380 0000430B E87F060000 <1> call imap 4381 <1> ; jsr r0,imap / get byte address and bit position in 4382 <1> ; / inode map in r2 & m 4383 <1> 4384 <1> ; DX (MQ) has a 1 in the calculated bit position 4385 <1> ; eBX (R2) has byte address of the byte with allocation bit 4386 <1> 4387 <1> ; 22/06/2015 - NOTE for next Retro UNIX version: 4388 <1> ; Inode count must be checked here 4389 <1> ; (Original UNIX v1 did not check inode count here !?) 4390 <1> 4391 <1> ; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18) 4392 <1> ; (inode count check) 4393 <1> ; ((if cf=1 --> requested inode number > inode count)) 4394 <1> 4395 00004310 730F <1> jnc short maknod2 4396 <1> 4397 <1> ; no free inode in inode table ! 4398 00004312 C705[4F650000]1B00- <1> mov dword [u.error], ERR_MISC ; 27 4398 0000431A 0000 <1> 4399 <1> ; miscellaneous/other errors 4400 0000431C E9C0EDFFFF <1> jmp error 4401 <1> maknod2: 4402 00004321 8413 <1> test [ebx], dl 4403 <1> ; bitb mq,(r2) / is the i-node active 4404 00004323 75E4 <1> jnz short maknod1 4405 <1> ; bne 1b / yes, try the next one 4406 00004325 0813 <1> or [ebx], dl 4407 <1> ; bisb mq,(r2) / no, make it active 4408 <1> ; / (put a 1 in the bit map) 4409 00004327 E8CA040000 <1> call iget 4410 <1> ; jsr r0,iget / get i-node into core 4411 <1> ; 03/02/2022 4412 0000432C F605[F5610000]80 <1> test byte [i.flgs+1], 80h 4413 <1> ;test word [i.flgs], 8000h 4414 <1> ; tst i.flgs / is i-node already allocated 4415 00004333 75D4 <1> jnz short maknod1 4416 <1> ; blt 1b / yes, look for another one 4417 00004335 66A3[32650000] <1> mov [u.dirbuf], ax 4418 <1> ; mov r1,u.dirbuf / no, put i-number in u.dirbuf 4419 <1> ; 03/02/2022 4420 0000433B 58 <1> pop eax ; ** 4421 <1> ;pop ax 4422 <1> ; mov (sp)+,r1 / get current i-number back 4423 0000433C E8B5040000 <1> call iget 4424 <1> ; jsr r0,iget / get i-node in core 4425 00004341 E852F7FFFF <1> call mkdir 4426 <1> ; jsr r0,mkdir / make a directory entry 4427 <1> ; / in current directory 4428 00004346 66A1[32650000] <1> mov ax, [u.dirbuf] 4429 <1> ; mov u.dirbuf,r1 / r1 = new inode number 4430 0000434C E8A5040000 <1> call iget 4431 <1> ; jsr r0,iget / get it into core 4432 <1> ; jsr r0,copyz; inode; inode+32. / 0 it out 4433 <1> ;mov ecx, 8 4434 <1> ; 03/02/2022 4435 00004351 29C9 <1> sub ecx, ecx 4436 00004353 B108 <1> mov cl, 8 4437 00004355 31C0 <1> xor eax, eax ; 0 4438 00004357 BF[F4610000] <1> mov edi, inode 4439 0000435C F3AB <1> rep stosd 4440 <1> ; 4441 0000435E 668F05[F4610000] <1> pop word [i.flgs] ; * 4442 <1> ; mov (sp)+,i.flgs / fill flags 4443 00004365 8A0D[46650000] <1> mov cl, [u.uid] ; 02/08/2013 4444 0000436B 880D[F7610000] <1> mov [i.uid], cl 4445 <1> ; movb u.uid,i.uid / user id 4446 00004371 C605[F6610000]01 <1> mov byte [i.nlks], 1 4447 <1> ; movb $1,i.nlks / 1 link 4448 <1> ;call epoch ; Retro UNIX 8086 v1 modification ! 4449 <1> ;mov eax, [s.time] 4450 <1> ;mov [i.ctim], eax 4451 <1> ; mov s.time,i.ctim / time created 4452 <1> ; mov s.time+2,i.ctim+2 / time modified 4453 <1> ; Retro UNIX 8086 v1 modification ! 4454 <1> ; i.ctime=0, i.ctime+2=0 and 4455 <1> ; 'setimod' will set ctime of file via 'epoch' 4456 <1> ;call setimod 4457 <1> ; jsr r0,setimod / set modified flag 4458 <1> ;retn 4459 <1> ; rts r0 / return 4460 <1> ; 03/02/2022 4461 00004378 E983050000 <1> jmp setimod 4462 <1> 4463 <1> sysseek: ; / moves read write pointer in an fsp entry 4464 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4465 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 4466 <1> ; 4467 <1> ; 'sysseek' changes the r/w pointer of (3rd word of in an 4468 <1> ; fsp entry) of an open file whose file descriptor is in u.r0. 4469 <1> ; The file descriptor refers to a file open for reading or 4470 <1> ; writing. The read (or write) pointer is set as follows: 4471 <1> ; * if 'ptrname' is 0, the pointer is set to offset. 4472 <1> ; * if 'ptrname' is 1, the pointer is set to its 4473 <1> ; current location plus offset. 4474 <1> ; * if 'ptrname' is 2, the pointer is set to the 4475 <1> ; size of file plus offset. 4476 <1> ; The error bit (e-bit) is set for an undefined descriptor. 4477 <1> ; 4478 <1> ; Calling sequence: 4479 <1> ; sysseek; offset; ptrname 4480 <1> ; Arguments: 4481 <1> ; offset - number of bytes desired to move 4482 <1> ; the r/w pointer 4483 <1> ; ptrname - a switch indicated above 4484 <1> ; 4485 <1> ; Inputs: r0 - file descriptor 4486 <1> ; Outputs: - 4487 <1> ; ............................................................... 4488 <1> ; 4489 <1> ; Retro UNIX 8086 v1 modification: 4490 <1> ; 'sysseek' system call has three arguments; so, 4491 <1> ; * 1st argument, file descriptor is in BX (BL) register 4492 <1> ; * 2nd argument, offset is in CX register 4493 <1> ; * 3rd argument, ptrname/switch is in DX (DL) register 4494 <1> ; 4495 <1> 4496 0000437D E822000000 <1> call seektell 4497 <1> ; AX = u.count 4498 <1> ; BX = *u.fofp 4499 <1> ; jsr r0,seektell / get proper value in u.count 4500 <1> ; add u.base,u.count / add u.base to it 4501 00004382 0305[20650000] <1> add eax, [u.base] ; add offset (u.base) to base 4502 00004388 8903 <1> mov [ebx], eax 4503 <1> ; mov u.count,*u.fofp / put result into r/w pointer 4504 0000438A E972EDFFFF <1> jmp sysret 4505 <1> ; br sysret4 4506 <1> 4507 <1> systell: ; / get the r/w pointer 4508 <1> ; 03/02/2022 4509 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4510 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 4511 <1> ; 4512 <1> ; Retro UNIX 8086 v1 modification: 4513 <1> ; ! 'systell' does not work in original UNIX v1, 4514 <1> ; it returns with error ! 4515 <1> ; Inputs: r0 - file descriptor 4516 <1> ; Outputs: r0 - file r/w pointer 4517 <1> 4518 <1> ;xor ecx, ecx ; 0 4519 <1> ;mov edx, 1 ; 05/08/2013 4520 <1> ; 03/02/2022 4521 0000438F 29D2 <1> sub edx, edx 4522 00004391 FEC2 <1> inc dl 4523 <1> ; edx = 1 4524 <1> ;call seektell 4525 00004393 E812000000 <1> call seektell0 ; 05/08/2013 4526 <1> ;mov ebx, [u.fofp] 4527 00004398 8B03 <1> mov eax, [ebx] 4528 0000439A A3[00650000] <1> mov [u.r0], eax 4529 0000439F E95DEDFFFF <1> jmp sysret 4530 <1> 4531 <1> ; Original unix v1 'systell' system call: 4532 <1> ; jsr r0,seektell 4533 <1> ; br error4 4534 <1> 4535 <1> seektell: 4536 <1> ; 03/02/2022 4537 <1> ; 03/01/2016 4538 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4539 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 4540 <1> ; 4541 <1> ; 'seektell' puts the arguments from sysseek and systell 4542 <1> ; call in u.base and u.count. It then gets the i-number of 4543 <1> ; the file from the file descriptor in u.r0 and by calling 4544 <1> ; getf. The i-node is brought into core and then u.count 4545 <1> ; is checked to see it is a 0, 1, or 2. 4546 <1> ; If it is 0 - u.count stays the same 4547 <1> ; 1 - u.count = offset (u.fofp) 4548 <1> ; 2 - u.count = i.size (size of file) 4549 <1> ; 4550 <1> ; !! Retro UNIX 8086 v1 modification: 4551 <1> ; Argument 1, file descriptor is in BX; 4552 <1> ; Argument 2, offset is in CX; 4553 <1> ; Argument 3, ptrname/switch is in DX register. 4554 <1> ; 4555 <1> ; mov ax, 3 ; Argument transfer method 3 (three arguments) 4556 <1> ; call arg 4557 <1> ; 4558 <1> ; ((Return -> ax = base for offset (position= base+offset)) 4559 <1> ; 4560 000043A4 890D[20650000] <1> mov [u.base], ecx ; offset 4561 <1> ; jsr r0,arg; u.base / puts offset in u.base 4562 <1> seektell0: 4563 000043AA 8915[24650000] <1> mov [u.count], edx 4564 <1> ; jsr r0,arg; u.count / put ptr name in u.count 4565 <1> ; mov ax, bx 4566 <1> ; mov *u.r0,r1 / file descriptor in r1 4567 <1> ; / (index in u.fp list) 4568 <1> ; call getf 4569 <1> ; jsr r0,getf / u.fofp points to 3rd word in fsp entry 4570 <1> ; BX = file descriptor (file number) 4571 000043B0 E8F9FBFFFF <1> call getf1 4572 <1> ; 03/02/2022 4573 000043B5 09C0 <1> or eax, eax 4574 <1> ;or ax, ax ; i-number of the file 4575 <1> ; mov r1,-(sp) / r1 has i-number of file, 4576 <1> ; / put it on the stack 4577 <1> ;jz error 4578 <1> ; beq error4 / if i-number is 0, not active so error 4579 000043B7 750F <1> jnz short seektell1 4580 000043B9 C705[4F650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 4580 000043C1 0000 <1> 4581 000043C3 E919EDFFFF <1> jmp error 4582 <1> seektell1: 4583 <1> ;push eax 4584 000043C8 80FC80 <1> cmp ah, 80h 4585 000043CB 7203 <1> jb short seektell2 4586 <1> ; bgt .+4 / if its positive jump 4587 000043CD 66F7D8 <1> neg ax 4588 <1> ; neg r1 / if not make it positive 4589 <1> seektell2: 4590 000043D0 E821040000 <1> call iget 4591 <1> ; jsr r0,iget / get its i-node into core 4592 000043D5 8B1D[10650000] <1> mov ebx, [u.fofp] ; 05/08/2013 4593 000043DB 803D[24650000]01 <1> cmp byte [u.count], 1 4594 <1> ; cmp u.count,$1 / is ptr name =1 4595 000043E2 7705 <1> ja short seektell3 4596 <1> ; blt 2f / no its zero 4597 000043E4 740A <1> je short seektell_4 4598 <1> ; beq 1f / yes its 1 4599 000043E6 31C0 <1> xor eax, eax 4600 <1> ;jmp short seektell_5 4601 000043E8 C3 <1> retn 4602 <1> seektell3: 4603 <1> ; 03/01/2016 4604 <1> ;movzx eax, word [i.size] 4605 000043E9 66A1[F8610000] <1> mov ax, [i.size] 4606 <1> ; mov i.size,u.count / put number of bytes 4607 <1> ; / in file in u.count 4608 <1> ;jmp short seektell_5 4609 <1> ; br 2f 4610 000043EF C3 <1> retn 4611 <1> seektell_4: ; 1: / ptrname =1 4612 <1> ;mov ebx, [u.fofp] 4613 000043F0 8B03 <1> mov eax, [ebx] 4614 <1> ; mov *u.fofp,u.count / put offset in u.count 4615 <1> ;seektell_5: ; 2: / ptrname =0 4616 <1> ;mov [u.count], eax 4617 <1> ;pop eax 4618 <1> ; mov (sp)+,r1 / i-number on stack r1 4619 000043F2 C3 <1> retn 4620 <1> ; rts r0 4621 <1> 4622 <1> sysintr: ; / set interrupt handling 4623 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4624 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 4625 <1> ; 4626 <1> ; 'sysintr' sets the interrupt handling value. It puts 4627 <1> ; argument of its call in u.intr then branches into 'sysquit' 4628 <1> ; routine. u.tty is checked if to see if a control tty exists. 4629 <1> ; If one does the interrupt character in the tty buffer is 4630 <1> ; cleared and 'sysret'is called. If one does not exits 4631 <1> ; 'sysret' is just called. 4632 <1> ; 4633 <1> ; Calling sequence: 4634 <1> ; sysintr; arg 4635 <1> ; Argument: 4636 <1> ; arg - if 0, interrupts (ASCII DELETE) are ignored. 4637 <1> ; - if 1, intterupts cause their normal result 4638 <1> ; i.e force an exit. 4639 <1> ; - if arg is a location within the program, 4640 <1> ; control is passed to that location when 4641 <1> ; an interrupt occurs. 4642 <1> ; Inputs: - 4643 <1> ; Outputs: - 4644 <1> ; ............................................................... 4645 <1> ; 4646 <1> ; Retro UNIX 8086 v1 modification: 4647 <1> ; 'sysintr' system call sets u.intr to value of BX 4648 <1> ; then branches into sysquit. 4649 <1> ; 4650 000043F3 66891D[3E650000] <1> mov [u.intr], bx 4651 <1> ; jsr r0,arg; u.intr / put the argument in u.intr 4652 <1> ; br 1f / go into quit routine 4653 000043FA E902EDFFFF <1> jmp sysret 4654 <1> 4655 <1> sysquit: 4656 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4657 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 4658 <1> ; 4659 <1> ; 'sysquit' turns off the quit signal. it puts the argument of 4660 <1> ; the call in u.quit. u.tty is checked if to see if a control 4661 <1> ; tty exists. If one does the interrupt character in the tty 4662 <1> ; buffer is cleared and 'sysret'is called. If one does not exits 4663 <1> ; 'sysret' is just called. 4664 <1> ; 4665 <1> ; Calling sequence: 4666 <1> ; sysquit; arg 4667 <1> ; Argument: 4668 <1> ; arg - if 0, this call diables quit signals from the 4669 <1> ; typewriter (ASCII FS) 4670 <1> ; - if 1, quits are re-enabled and cause execution to 4671 <1> ; cease and a core image to be produced. 4672 <1> ; i.e force an exit. 4673 <1> ; - if arg is an addres in the program, 4674 <1> ; a quit causes control to sent to that 4675 <1> ; location. 4676 <1> ; Inputs: - 4677 <1> ; Outputs: - 4678 <1> ; ............................................................... 4679 <1> ; 4680 <1> ; Retro UNIX 8086 v1 modification: 4681 <1> ; 'sysquit' system call sets u.quit to value of BX 4682 <1> ; then branches into 'sysret'. 4683 <1> ; 4684 000043FF 66891D[40650000] <1> mov [u.quit], bx 4685 00004406 E9F6ECFFFF <1> jmp sysret 4686 <1> ; jsr r0,arg; u.quit / put argument in u.quit 4687 <1> ;1: 4688 <1> ; mov u.ttyp,r1 / move pointer to control tty buffer 4689 <1> ; / to r1 4690 <1> ; beq sysret4 / return to user 4691 <1> ; clrb 6(r1) / clear the interrupt character 4692 <1> ; / in the tty buffer 4693 <1> ; br sysret4 / return to user 4694 <1> 4695 <1> syssetuid: ; / set process id 4696 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4697 <1> ; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4698 <1> ; 4699 <1> ; 'syssetuid' sets the user id (u.uid) of the current process 4700 <1> ; to the process id in (u.r0). Both the effective user and 4701 <1> ; u.uid and the real user u.ruid are set to this. 4702 <1> ; Only the super user can make this call. 4703 <1> ; 4704 <1> ; Calling sequence: 4705 <1> ; syssetuid 4706 <1> ; Arguments: - 4707 <1> ; 4708 <1> ; Inputs: (u.r0) - contains the process id. 4709 <1> ; Outputs: - 4710 <1> ; ............................................................... 4711 <1> ; 4712 <1> ; Retro UNIX 8086 v1 modification: 4713 <1> ; BL contains the (new) user ID of the current process 4714 <1> 4715 <1> ; movb *u.r0,r1 / move process id (number) to r1 4716 0000440B 3A1D[47650000] <1> cmp bl, [u.ruid] 4717 <1> ; cmpb r1,u.ruid / is it equal to the real user 4718 <1> ; / id number 4719 00004411 741E <1> je short setuid1 4720 <1> ; beq 1f / yes 4721 00004413 803D[46650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 4722 <1> ; tstb u.uid / no, is current user the super user? 4723 <1> ;ja error 4724 <1> ; bne error4 / no, error 4725 0000441A 760F <1> jna short setuid0 4726 0000441C C705[4F650000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 4726 00004424 0000 <1> 4727 <1> ; 'permission denied !' error 4728 00004426 E9B6ECFFFF <1> jmp error 4729 <1> setuid0: 4730 0000442B 881D[47650000] <1> mov [u.ruid], bl 4731 <1> setuid1: ; 1: 4732 00004431 881D[46650000] <1> mov [u.uid], bl ; 02/08/2013 4733 <1> ; movb r1,u.uid / put process id in u.uid 4734 <1> ; movb r1,u.ruid / put process id in u.ruid 4735 00004437 E9C5ECFFFF <1> jmp sysret 4736 <1> ; br sysret4 / system return 4737 <1> 4738 <1> sysgetuid: ; < get user id > 4739 <1> ; 03/02/2022 4740 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4741 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 4742 <1> ; 4743 <1> ; 'sysgetuid' returns the real user ID of the current process. 4744 <1> ; The real user ID identifies the person who is logged in, 4745 <1> ; in contradistinction to the effective user ID, which 4746 <1> ; determines his access permission at each moment. It is thus 4747 <1> ; useful to programs which operate using the 'set user ID' 4748 <1> ; mode, to find out who invoked them. 4749 <1> ; 4750 <1> ; Calling sequence: 4751 <1> ; syssetuid 4752 <1> ; Arguments: - 4753 <1> ; 4754 <1> ; Inputs: - 4755 <1> ; Outputs: (u.r0) - contains the real user's id. 4756 <1> ; ............................................................... 4757 <1> ; 4758 <1> ; Retro UNIX 8086 v1 modification: 4759 <1> ; AL contains the real user ID at return. 4760 <1> ; 4761 <1> ;movzx eax, byte [u.ruid] 4762 <1> ; 03/03/2022 4763 0000443C A0[47650000] <1> mov al, [u.ruid] 4764 00004441 A3[00650000] <1> mov [u.r0], eax 4765 <1> ; movb u.ruid,*u.r0 / move the real user id to (u.r0) 4766 00004446 E9B6ECFFFF <1> jmp sysret 4767 <1> ; br sysret4 / systerm return, sysret 4768 <1> 4769 <1> anyi: 4770 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4771 <1> ; 25/04/2013 (Retro UNIX 8086 v1) 4772 <1> ; 4773 <1> ; 'anyi' is called if a file deleted while open. 4774 <1> ; "anyi" checks to see if someone else has opened this file. 4775 <1> ; 4776 <1> ; INPUTS -> 4777 <1> ; r1 - contains an i-number 4778 <1> ; fsp - start of table containing open files 4779 <1> ; 4780 <1> ; OUTPUTS -> 4781 <1> ; "deleted" flag set in fsp entry of another occurrence of 4782 <1> ; this file and r2 points 1st word of this fsp entry. 4783 <1> ; if file not found - bit in i-node map is cleared 4784 <1> ; (i-node is freed) 4785 <1> ; all blocks related to i-node are freed 4786 <1> ; all flags in i-node are cleared 4787 <1> ; ((AX = R1)) input 4788 <1> ; 4789 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 4790 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 4791 <1> ; 4792 <1> ; / r1 contains an i-number 4793 0000444B BB[C4620000] <1> mov ebx, fsp 4794 <1> ; mov $fsp,r2 / move start of fsp table to r2 4795 <1> anyi_1: ; 1: 4796 00004450 663B03 <1> cmp ax, [ebx] 4797 <1> ; cmp r1,(r2) / do i-numbers match? 4798 00004453 7433 <1> je short anyi_3 4799 <1> ; beq 1f / yes, 1f 4800 00004455 66F7D8 <1> neg ax 4801 <1> ; neg r1 / no complement r1 4802 00004458 663B03 <1> cmp ax, [ebx] 4803 <1> ; cmp r1,(r2) / do they match now? 4804 0000445B 742B <1> je short anyi_3 4805 <1> ; beq 1f / yes, transfer 4806 <1> ; / i-numbers do not match 4807 0000445D 83C30A <1> add ebx, 10 ; fsp table size is 10 bytes 4808 <1> ; in Retro UNIX 386 v1 (22/06/2015) 4809 <1> ; add $8,r2 / no, bump to next entry in fsp table 4810 00004460 81FB[B8640000] <1> cmp ebx, fsp + (nfiles*10) ; 22/06/2015 4811 <1> ; cmp r2,$fsp+[nfiles*8] 4812 <1> ; / are we at last entry in the table 4813 00004466 72E8 <1> jb short anyi_1 4814 <1> ; blt 1b / no, check next entries i-number 4815 <1> ;cmp ax, 32768 4816 00004468 80FC80 <1> cmp ah, 80h ; negative number check 4817 <1> ; tst r1 / yes, no match 4818 <1> ; bge .+4 4819 0000446B 7203 <1> jb short anyi_2 4820 0000446D 66F7D8 <1> neg ax 4821 <1> ; neg r1 / make i-number positive 4822 <1> anyi_2: 4823 00004470 E81A050000 <1> call imap 4824 <1> ; jsr r0,imap / get address of allocation bit 4825 <1> ; / in the i-map in r2 4826 <1> ;; DL/DX (MQ) has a 1 in the calculated bit position 4827 <1> ;; eBX (R2) has address of the byte with allocation bit 4828 <1> ; not dx 4829 00004475 F6D2 <1> not dl ;; 0 at calculated bit position, other bits are 1 4830 <1> ;and [ebx], dx 4831 00004477 2013 <1> and [ebx], dl 4832 <1> ; bicb mq,(r2) / clear bit for i-node in the imap 4833 00004479 E8A4040000 <1> call itrunc 4834 <1> ; jsr r0,itrunc / free all blocks related to i-node 4835 0000447E 66C705[F4610000]00- <1> mov word [i.flgs], 0 4835 00004486 00 <1> 4836 <1> ; clr i.flgs / clear all flags in the i-node 4837 00004487 C3 <1> retn 4838 <1> ;rts r0 / return 4839 <1> anyi_3: ; 1: / i-numbers match 4840 00004488 FE4309 <1> inc byte [ebx+9] ; 22/06/2015 4841 <1> ;incb 7(r2) / increment upper byte of the 4th word 4842 <1> ; / in that fsp entry (deleted flag of fsp entry) 4843 0000448B C3 <1> retn 4844 <1> ; rts r0 2054 %include 'u3.s' ; 10/05/2015 2055 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC 2056 <1> ; Last Modification: 03/02/2022 2057 <1> ; ---------------------------------------------------------------------------- 2058 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2059 <1> ; (v0.1 - Beginning: 11/07/2012) 2060 <1> ; 2061 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2062 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2063 <1> ; 2064 <1> ; 2065 <1> ; 2066 <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s 2067 <1> ; 2068 <1> ; **************************************************************************** 2069 <1> ; 15/09/2015 2070 <1> 2071 <1> tswitch: ; Retro UNIX 386 v1 2072 <1> tswap: 2073 <1> ; 01/09/2015 2074 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2075 <1> ; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2076 <1> ; time out swap, called when a user times out. 2077 <1> ; the user is put on the low priority queue. 2078 <1> ; This is done by making a link from the last user 2079 <1> ; on the low priority queue to him via a call to 'putlu'. 2080 <1> ; then he is swapped out. 2081 <1> ; 2082 <1> ; Retro UNIX 386 v1 modification -> 2083 <1> ; swap (software task switch) is performed by changing 2084 <1> ; user's page directory (u.pgdir) instead of segment change 2085 <1> ; as in Retro UNIX 8086 v1. 2086 <1> ; 2087 <1> ; RETRO UNIX 8086 v1 modification -> 2088 <1> ; 'swap to disk' is replaced with 'change running segment' 2089 <1> ; according to 8086 cpu (x86 real mode) architecture. 2090 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2091 <1> ; compatibles was using 1MB segmented memory 2092 <1> ; in 8086/8088 times. 2093 <1> ; 2094 <1> ; INPUTS -> 2095 <1> ; u.uno - users process number 2096 <1> ; runq+4 - lowest priority queue 2097 <1> ; OUTPUTS -> 2098 <1> ; r0 - users process number 2099 <1> ; r2 - lowest priority queue address 2100 <1> ; 2101 <1> ; ((AX = R0, BX = R2)) output 2102 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) 2103 <1> ; 2104 0000448C A0[49650000] <1> mov al, [u.uno] 2105 <1> ; movb u.uno,r1 / move users process number to r1 2106 <1> ; mov $runq+4,r2 2107 <1> ; / move lowest priority queue address to r2 2108 00004491 E8CD000000 <1> call putlu 2109 <1> ; jsr r0,putlu / create link from last user on Q to 2110 <1> ; / u.uno's user 2111 <1> 2112 <1> switch: ; Retro UNIX 386 v1 2113 <1> swap: 2114 <1> ; 03/02/2022 2115 <1> ; 02/09/2015 2116 <1> ; 01/09/2015 2117 <1> ; 31/08/2015 2118 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2119 <1> ; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2120 <1> ; 'swap' is routine that controls the swapping of processes 2121 <1> ; in and out of core. 2122 <1> ; 2123 <1> ; Retro UNIX 386 v1 modification -> 2124 <1> ; swap (software task switch) is performed by changing 2125 <1> ; user's page directory (u.pgdir) instead of segment change 2126 <1> ; as in Retro UNIX 8086 v1. 2127 <1> ; 2128 <1> ; RETRO UNIX 8086 v1 modification -> 2129 <1> ; 'swap to disk' is replaced with 'change running segment' 2130 <1> ; according to 8086 cpu (x86 real mode) architecture. 2131 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2132 <1> ; compatibles was using 1MB segmented memory 2133 <1> ; in 8086/8088 times. 2134 <1> ; 2135 <1> ; INPUTS -> 2136 <1> ; runq table - contains processes to run. 2137 <1> ; p.link - contains next process in line to be run. 2138 <1> ; u.uno - process number of process in core 2139 <1> ; s.stack - swap stack used as an internal stack for swapping. 2140 <1> ; OUTPUTS -> 2141 <1> ; (original unix v1 -> present process to its disk block) 2142 <1> ; (original unix v1 -> new process into core -> 2143 <1> ; Retro Unix 8086 v1 -> segment registers changed 2144 <1> ; for new process) 2145 <1> ; u.quant = 3 (Time quantum for a process) 2146 <1> ; ((INT 1Ch count down speed -> 18.2 times per second) 2147 <1> ; RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second) 2148 <1> ; for now, it will swap the process if there is not 2149 <1> ; a keyboard event (keystroke) (Int 15h, function 4Fh) 2150 <1> ; or will count down from 3 to 0 even if there is a 2151 <1> ; keyboard event locking due to repetitive key strokes. 2152 <1> ; u.quant will be reset to 3 for RETRO UNIX 8086 v1. 2153 <1> ; 2154 <1> ; u.pri -points to highest priority run Q. 2155 <1> ; r2 - points to the run queue. 2156 <1> ; r1 - contains new process number 2157 <1> ; r0 - points to place in routine or process that called 2158 <1> ; swap all user parameters 2159 <1> ; 2160 <1> ; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI)) 2161 <1> ; 2162 <1> swap_0: 2163 <1> ;mov $300,*$ps / processor priority = 6 2164 00004496 BE[F0640000] <1> mov esi, runq 2165 <1> ; mov $runq,r2 / r2 points to runq table 2166 <1> swap_1: ; 1: / search runq table for highest priority process 2167 0000449B 668B06 <1> mov ax, [esi] 2168 0000449E 6621C0 <1> and ax, ax 2169 <1> ; tst (r2)+ / are there any processes to run 2170 <1> ; / in this Q entry 2171 000044A1 7507 <1> jnz short swap_2 2172 <1> ; bne 1f / yes, process 1f 2173 <1> ; cmp r2,$runq+6 / if zero compare address 2174 <1> ; / to end of table 2175 <1> ; bne 1b / if not at end, go back 2176 000044A3 E8E0000000 <1> call idle 2177 <1> ; jsr r0,idle; s.idlet+2 / wait for interrupt; 2178 <1> ; / all queues are empty 2179 000044A8 EBF1 <1> jmp short swap_1 2180 <1> ; br swap 2181 <1> swap_2: ; 1: 2182 000044AA 0FB6D8 <1> movzx ebx, al ; 02/09/2015 2183 <1> ; tst -(r2) / restore pointer to right Q entry 2184 <1> ; mov r2,u.pri / set present user to this run queue 2185 <1> ; movb (r2)+,r1 / move 1st process in queue to r1 2186 000044AD 38E0 <1> cmp al, ah 2187 <1> ; cmpb r1,(r2)+ / is there only 1 process 2188 <1> ; / in this Q to be run 2189 000044AF 740A <1> je short swap_3 2190 <1> ; beq 1f / yes 2191 <1> ; tst -(r2) / no, pt r2 back to this Q entry 2192 <1> ;movzx ebx, al 2193 000044B1 8AA3[63620000] <1> mov ah, [ebx+p.link-1] 2194 000044B7 8826 <1> mov [esi], ah 2195 <1> ; movb p.link-1(r1),(r2) / move next process 2196 <1> ; / in line into run queue 2197 000044B9 EB05 <1> jmp short swap_4 2198 <1> ; br 2f 2199 <1> swap_3: ; 1: 2200 <1> ;xor dx, dx 2201 <1> ; 03/02/2022 2202 000044BB 31D2 <1> xor edx, edx 2203 000044BD 668916 <1> mov [esi], dx 2204 <1> ; clr -(r2) / zero the entry; no processes on the Q 2205 <1> swap_4: ; / write out core to appropriate disk area and read 2206 <1> ; / in new process if required 2207 <1> ; clr *$ps / clear processor status 2208 000044C0 8A25[49650000] <1> mov ah, [u.uno] 2209 000044C6 38C4 <1> cmp ah, al 2210 <1> ; cmpb r1,u.uno / is this process the same as 2211 <1> ; / the process in core? 2212 000044C8 743B <1> je short swap_8 2213 <1> ; beq 2f / yes, don't have to swap 2214 <1> ; mov r0,-(sp) / no, write out core; save r0 2215 <1> ; / (address in routine that called swap) 2216 <1> ; mov r1,-(sp) / put r1 (new process #) on the stack 2217 <1> ; 01/09/2015 2218 <1> ;mov [u.usp], esp 2219 <1> ; mov sp,u.usp / save stack pointer 2220 <1> ; mov $sstack,sp / move swap stack pointer 2221 <1> ; / to the stack pointer 2222 000044CA 08E4 <1> or ah, ah 2223 <1> ; tstb u.uno / is the process # = 0 2224 000044CC 740D <1> jz short swap_6 ; 'sysexit' 2225 <1> ; beq 1f / yes, kill process by overwriting 2226 <1> ; 02/09/2015 2227 000044CE 8925[FC640000] <1> mov [u.usp], esp ; return address for 'syswait' & 'sleep' 2228 <1> ; 2229 000044D4 E834000000 <1> call wswap 2230 <1> ;jsr r0,wswap / write out core to disk 2231 <1> ; 31/08/2015 2232 <1> ;movzx ebx, al ; New (running) process number 2233 000044D9 EB1C <1> jmp short swap_7 2234 <1> swap_6: 2235 <1> ; 31/08/2015 2236 <1> ; Deallocate memory pages belong to the process 2237 <1> ; which is being terminated 2238 <1> ; 14/05/2015 ('sysexit') 2239 <1> ; Deallocate memory pages of the process 2240 <1> ; (Retro UNIX 386 v1 modification !) 2241 <1> ; 2242 <1> ; movzx ebx, al 2243 000044DB 53 <1> push ebx 2244 000044DC A1[53650000] <1> mov eax, [u.pgdir] ; page directory of the process 2245 000044E1 8B1D[57650000] <1> mov ebx, [u.ppgdir] ; page directory of the parent process 2246 000044E7 E825E0FFFF <1> call deallocate_page_dir 2247 000044EC A1[4A650000] <1> mov eax, [u.upage] ; 'user' structure page of the process 2248 000044F1 E8B1E0FFFF <1> call deallocate_page 2249 000044F6 5B <1> pop ebx 2250 <1> swap_7: ;1: 2251 <1> ; 02/09/2015 2252 <1> ; 31/08/2015 2253 <1> ; 14/05/2015 2254 000044F7 C0E302 <1> shl bl, 2 ; * 4 2255 000044FA 8B83[80620000] <1> mov eax, [ebx+p.upage-4] ; the 'u' page of the new process 2256 <1> ;cli 2257 00004500 E831000000 <1> call rswap 2258 <1> ; mov (sp)+,r1 / restore r1 to new process number 2259 <1> ; jsr r0,rswap / read new process into core 2260 <1> ; jsr r0,unpack / unpack the users stack from next 2261 <1> ; / to his program to its normal 2262 <1> ; 01/09/2015 2263 <1> ;mov esp, [u.usp] 2264 <1> ; mov u.usp,sp / location; restore stack pointer to 2265 <1> ; / new process stack 2266 <1> ; mov (sp)+,r0 / put address of where the process 2267 <1> ; / that just got swapped in, left off., 2268 <1> ; / i.e., transfer control to new process 2269 <1> ;sti 2270 <1> swap_8: ;2: 2271 <1> ; RETRO UNIX 8086 v1 modification ! 2272 00004505 C605[3C650000]04 <1> mov byte [u.quant], time_count 2273 <1> ; movb $30.,uquant / initialize process time quantum 2274 0000450C C3 <1> retn 2275 <1> ; rts r0 / return 2276 <1> 2277 <1> wswap: ; < swap out, swap to disk > 2278 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 2279 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2280 <1> ; 'wswap' writes out the process that is in core onto its 2281 <1> ; appropriate disk area. 2282 <1> ; 2283 <1> ; Retro UNIX 386 v1 modification -> 2284 <1> ; User (u) structure content and the user's register content 2285 <1> ; will be copied to the process's/user's UPAGE (a page for 2286 <1> ; saving 'u' structure and user registers for task switching). 2287 <1> ; u.usp - points to kernel stack address which contains 2288 <1> ; user's registers while entering system call. 2289 <1> ; u.sp - points to kernel stack address 2290 <1> ; to return from system call -for IRET-. 2291 <1> ; [u.usp]+32+16 = [u.sp] 2292 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 2293 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 2294 <1> ; 2295 <1> ; Retro UNIX 8086 v1 modification -> 2296 <1> ; 'swap to disk' is replaced with 'change running segment' 2297 <1> ; according to 8086 cpu (x86 real mode) architecture. 2298 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2299 <1> ; compatibles was using 1MB segmented memory 2300 <1> ; in 8086/8088 times. 2301 <1> ; 2302 <1> ; INPUTS -> 2303 <1> ; u.break - points to end of program 2304 <1> ; u.usp - stack pointer at the moment of swap 2305 <1> ; core - beginning of process program 2306 <1> ; ecore - end of core 2307 <1> ; user - start of user parameter area 2308 <1> ; u.uno - user process number 2309 <1> ; p.dska - holds block number of process 2310 <1> ; OUTPUTS -> 2311 <1> ; swp I/O queue 2312 <1> ; p.break - negative word count of process 2313 <1> ; r1 - process disk address 2314 <1> ; r2 - negative word count 2315 <1> ; 2316 <1> ; RETRO UNIX 8086 v1 input/output: 2317 <1> ; 2318 <1> ; INPUTS -> 2319 <1> ; u.uno - process number (to be swapped out) 2320 <1> ; OUTPUTS -> 2321 <1> ; none 2322 <1> ; 2323 <1> ; ((Modified registers: ECX, ESI, EDI)) 2324 <1> ; 2325 0000450D 8B3D[4A650000] <1> mov edi, [u.upage] ; process's user (u) structure page addr 2326 00004513 B91C000000 <1> mov ecx, (U_SIZE + 3) / 4 2327 00004518 BE[F8640000] <1> mov esi, user ; active user (u) structure 2328 0000451D F3A5 <1> rep movsd 2329 <1> ; 2330 0000451F 8B35[FC640000] <1> mov esi, [u.usp] ; esp (system stack pointer, 2331 <1> ; points to user registers) 2332 00004525 8B0D[F8640000] <1> mov ecx, [u.sp] ; return address from the system call 2333 <1> ; (for IRET) 2334 <1> ; [u.sp] -> EIP (user) 2335 <1> ; [u.sp+4]-> CS (user) 2336 <1> ; [u.sp+8] -> EFLAGS (user) 2337 <1> ; [u.sp+12] -> ESP (user) 2338 <1> ; [u.sp+16] -> SS (user) 2339 0000452B 29F1 <1> sub ecx, esi ; required space for user registers 2340 0000452D 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 2341 <1> ; (for IRET) 2342 00004530 C1E902 <1> shr ecx, 2 2343 00004533 F3A5 <1> rep movsd 2344 00004535 C3 <1> retn 2345 <1> 2346 <1> ; Original UNIX v1 'wswap' routine: 2347 <1> ; wswap: 2348 <1> ; mov *$30,u.emt / determines handling of emts 2349 <1> ; mov *$10,u.ilgins / determines handling of 2350 <1> ; / illegal instructions 2351 <1> ; mov u.break,r2 / put process program break address in r2 2352 <1> ; inc r2 / add 1 to it 2353 <1> ; bic $1,r2 / make it even 2354 <1> ; mov r2,u.break / set break to an even location 2355 <1> ; mov u.usp,r3 / put users stack pointer 2356 <1> ; / at moment of swap in r3 2357 <1> ; cmp r2,$core / is u.break less than $core 2358 <1> ; blos 2f / yes 2359 <1> ; cmp r2,r3 / no, is (u.break) greater than stack ptr. 2360 <1> ; bhis 2f / yes 2361 <1> ; 1: 2362 <1> ; mov (r3)+,(r2)+ / no, pack stack next to users program 2363 <1> ; cmp r3,$ecore / has stack reached end of core 2364 <1> ; bne 1b / no, keep packing 2365 <1> ; br 1f / yes 2366 <1> ; 2: 2367 <1> ; mov $ecore,r2 / put end of core in r2 2368 <1> ; 1: 2369 <1> ; sub $user,r2 / get number of bytes to write out 2370 <1> ; / (user up to end of stack gets written out) 2371 <1> ; neg r2 / make it negative 2372 <1> ; asr r2 / change bytes to words (divide by 2) 2373 <1> ; mov r2,swp+4 / word count 2374 <1> ; movb u.uno,r1 / move user process number to r1 2375 <1> ; asl r1 / x2 for index 2376 <1> ; mov r2,p.break-2(r1) / put negative of word count 2377 <1> ; / into the p.break table 2378 <1> ; mov p.dska-2(r1),r1 / move disk address of swap area 2379 <1> ; / for process to r1 2380 <1> ; mov r1,swp+2 / put processes dska address in swp+2 2381 <1> ; / (block number) 2382 <1> ; bis $1000,swp / set it up to write (set bit 9) 2383 <1> ; jsr r0,ppoke / write process out on swap area of disk 2384 <1> ; 1: 2385 <1> ; tstb swp+1 / is lt done writing? 2386 <1> ; bne 1b / no, wait 2387 <1> ; rts r0 / yes, return to swap 2388 <1> 2389 <1> rswap: ; < swap in, swap from disk > 2390 <1> ; 15/09/2015 2391 <1> ; 28/08/2015 2392 <1> ; 14/05/2015 2393 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 2394 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2395 <1> ; 'rswap' reads a process whose number is in r1, 2396 <1> ; from disk into core. 2397 <1> ; 2398 <1> ; Retro UNIX 386 v1 modification -> 2399 <1> ; User (u) structure content and the user's register content 2400 <1> ; will be restored from process's/user's UPAGE (a page for 2401 <1> ; saving 'u' structure and user registers for task switching). 2402 <1> ; u.usp - points to kernel stack address which contains 2403 <1> ; user's registers while entering system call. 2404 <1> ; u.sp - points to kernel stack address 2405 <1> ; to return from system call -for IRET-. 2406 <1> ; [u.usp]+32+16 = [u.sp] 2407 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 2408 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 2409 <1> ; 2410 <1> ; RETRO UNIX 8086 v1 modification -> 2411 <1> ; 'swap to disk' is replaced with 'change running segment' 2412 <1> ; according to 8086 cpu (x86 real mode) architecture. 2413 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2414 <1> ; compatibles was using 1MB segmented memory 2415 <1> ; in 8086/8088 times. 2416 <1> ; 2417 <1> ; INPUTS -> 2418 <1> ; r1 - process number of process to be read in 2419 <1> ; p.break - negative of word count of process 2420 <1> ; p.dska - disk address of the process 2421 <1> ; u.emt - determines handling of emt's 2422 <1> ; u.ilgins - determines handling of illegal instructions 2423 <1> ; OUTPUTS -> 2424 <1> ; 8 = (u.ilgins) 2425 <1> ; 24 = (u.emt) 2426 <1> ; swp - bit 10 is set to indicate read 2427 <1> ; (bit 15=0 when reading is done) 2428 <1> ; swp+2 - disk block address 2429 <1> ; swp+4 - negative word count 2430 <1> ; ((swp+6 - address of user structure)) 2431 <1> ; 2432 <1> ; RETRO UNIX 8086 v1 input/output: 2433 <1> ; 2434 <1> ; INPUTS -> 2435 <1> ; AL - new process number (to be swapped in) 2436 <1> ; OUTPUTS -> 2437 <1> ; none 2438 <1> ; 2439 <1> ; ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 2440 <1> ; 2441 <1> ; Retro UNIX 386 v1 - modification ! 14/05/2015 2442 00004536 89C6 <1> mov esi, eax ; process's user (u) structure page addr 2443 00004538 B91C000000 <1> mov ecx, (U_SIZE + 3) / 4 2444 0000453D BF[F8640000] <1> mov edi, user ; active user (u) structure 2445 00004542 F3A5 <1> rep movsd 2446 00004544 58 <1> pop eax ; 15/09/2015, 'rswap' return address 2447 00004545 8B3D[FC640000] <1> mov edi, [u.usp] ; esp (system stack pointer, 2448 <1> ; points to user registers) 2449 0000454B 8B0D[F8640000] <1> mov ecx, [u.sp] ; return address from the system call 2450 <1> ; (for IRET) 2451 <1> ; [u.sp] -> EIP (user) 2452 <1> ; [u.sp+4]-> CS (user) 2453 <1> ; [u.sp+8] -> EFLAGS (user) 2454 <1> ; [u.sp+12] -> ESP (user) 2455 <1> ; [u.sp+16] -> SS (user) 2456 <1> ; 28/08/2015 2457 00004551 29F9 <1> sub ecx, edi ; required space for user registers 2458 00004553 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 2459 <1> ; (for IRET) 2460 00004556 C1E902 <1> shr ecx, 2 2461 00004559 F3A5 <1> rep movsd 2462 0000455B 8B25[FC640000] <1> mov esp, [u.usp] ; 15/09/2015 2463 00004561 50 <1> push eax ; 15/09/2015 'rswap' return address 2464 00004562 C3 <1> retn 2465 <1> 2466 <1> ; Original UNIX v1 'rswap' and 'unpack' routines: 2467 <1> ;rswap: 2468 <1> ; asl r1 / process number x2 for index 2469 <1> ; mov p.break-2(r1), swp+4 / word count 2470 <1> ; mov p.dska-2(r1),swp+2 / disk address 2471 <1> ; bis $2000,swp / read 2472 <1> ; jsr r0,ppoke / read it in 2473 <1> ; 1: 2474 <1> ; tstb swp+1 / done 2475 <1> ; bne 1b / no, wait for bit 15 to clear (inhibit bit) 2476 <1> ; mov u.emt,*$30 / yes move these 2477 <1> ; mov u.ilgins,*$10 / back 2478 <1> ; rts r0 / return 2479 <1> 2480 <1> ;unpack: ; / move stack back to its normal place 2481 <1> ; mov u.break,r2 / r2 points to end of user program 2482 <1> ; cmp r2,$core / at beginning of user program yet? 2483 <1> ; blos 2f / yes, return 2484 <1> ; cmp r2,u.usp / is break_above the stack pointer 2485 <1> ; / before swapping 2486 <1> ; bhis 2f / yes, return 2487 <1> ; mov $ecore,r3 / r3 points to end of core 2488 <1> ; add r3,r2 2489 <1> ; sub u.usp,r2 / end of users stack is in r2 2490 <1> ; 1: 2491 <1> ; mov -(r2),-(r3) / move stack back to its normal place 2492 <1> ; cmp r2,u.break / in core 2493 <1> ; bne 1b 2494 <1> ; 2: 2495 <1> ; rts r0 2496 <1> 2497 <1> putlu: 2498 <1> ; 12/09/2015 2499 <1> ; 02/09/2015 2500 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2501 <1> ; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 2502 <1> ; 'putlu' is called with a process number in r1 and a pointer 2503 <1> ; to lowest priority Q (runq+4) in r2. A link is created from 2504 <1> ; the last process on the queue to process in r1 by putting 2505 <1> ; the process number in r1 into the last process's link. 2506 <1> ; 2507 <1> ; INPUTS -> 2508 <1> ; r1 - user process number 2509 <1> ; r2 - points to lowest priority queue 2510 <1> ; p.dska - disk address of the process 2511 <1> ; u.emt - determines handling of emt's 2512 <1> ; u.ilgins - determines handling of illegal instructions 2513 <1> ; OUTPUTS -> 2514 <1> ; r3 - process number of last process on the queue upon 2515 <1> ; entering putlu 2516 <1> ; p.link-1 + r3 - process number in r1 2517 <1> ; r2 - points to lowest priority queue 2518 <1> ; 2519 <1> ; ((Modified registers: EDX, EBX)) 2520 <1> ; 2521 <1> ; / r1 = user process no.; r2 points to lowest priority queue 2522 <1> 2523 <1> ; eBX = r2 2524 <1> ; eAX = r1 (AL=r1b) 2525 <1> 2526 00004563 BB[F0640000] <1> mov ebx, runq 2527 00004568 0FB613 <1> movzx edx, byte [ebx] 2528 0000456B 43 <1> inc ebx 2529 0000456C 20D2 <1> and dl, dl 2530 <1> ; tstb (r2)+ / is queue empty? 2531 0000456E 740A <1> jz short putlu_1 2532 <1> ; beq 1f / yes, branch 2533 00004570 8A13 <1> mov dl, [ebx] ; 12/09/2015 2534 <1> ; movb (r2),r3 / no, save the "last user" process number 2535 <1> ; / in r3 2536 00004572 8882[63620000] <1> mov [edx+p.link-1], al 2537 <1> ; movb r1,p.link-1(r3) / put pointer to user on 2538 <1> ; / "last users" link 2539 00004578 EB03 <1> jmp short putlu_2 2540 <1> ; br 2f / 2541 <1> putlu_1: ; 1: 2542 0000457A 8843FF <1> mov [ebx-1], al 2543 <1> ; movb r1,-1(r2) / user is only user; 2544 <1> ; / put process no. at beginning and at end 2545 <1> putlu_2: ; 2: 2546 0000457D 8803 <1> mov [ebx], al 2547 <1> ; movb r1,(r2) / user process in r1 is now the last entry 2548 <1> ; / on the queue 2549 0000457F 88C2 <1> mov dl, al 2550 00004581 88B2[63620000] <1> mov [edx+p.link-1], dh ; 0 2551 <1> ; dec r2 / restore r2 2552 00004587 C3 <1> retn 2553 <1> ; rts r0 2554 <1> 2555 <1> ;copyz: 2556 <1> ; mov r1,-(sp) / put r1 on stack 2557 <1> ; mov r2,-(sp) / put r2 on stack 2558 <1> ; mov (r0)+,r1 2559 <1> ; mov (r0)+,r2 2560 <1> ;1: 2561 <1> ; clr (r1)+ / clear all locations between r1 and r2 2562 <1> ; cmp r1,r2 2563 <1> ; blo 1b 2564 <1> ; mov (sp)+,r2 / restore r2 2565 <1> ; mov (sp)+,r1 / restore r1 2566 <1> ; rts r0 2567 <1> 2568 <1> idle: 2569 <1> ; 01/09/2015 2570 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2571 <1> ; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1) 2572 <1> ; (idle & wait loop) 2573 <1> ; Retro Unix 8086 v1 modification on original UNIX v1 2574 <1> ; idle procedure! 2575 <1> ; 2576 <1> ; 01/09/2015 2577 00004588 FB <1> sti 2578 <1> ; 29/07/2013 2579 00004589 F4 <1> hlt 2580 0000458A 90 <1> nop ; 10/10/2013 2581 0000458B 90 <1> nop 2582 0000458C 90 <1> nop 2583 <1> ; 23/10/2013 2584 0000458D 90 <1> nop 2585 0000458E 90 <1> nop 2586 0000458F 90 <1> nop 2587 00004590 90 <1> nop 2588 00004591 C3 <1> retn 2589 <1> 2590 <1> ;mov *$ps,-(sp) / save ps on stack 2591 <1> ;clr *$ps / clear ps 2592 <1> ;mov clockp,-(sp) / save clockp on stack 2593 <1> ;mov (r0)+,clockp / arg to idle in clockp 2594 <1> ;1 / wait for interrupt 2595 <1> ;mov (sp)+,clockp / restore clockp, ps 2596 <1> ;mov (sp)+,*$ps 2597 <1> ;rts r0 2598 <1> 2599 <1> clear: 2600 <1> ; 03/02/2022 2601 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2602 <1> ; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2603 <1> ; 'clear' zero's out of a block (whose block number is in r1) 2604 <1> ; on the current device (cdev) 2605 <1> ; 2606 <1> ; INPUTS -> 2607 <1> ; r1 - block number of block to be zeroed 2608 <1> ; cdev - current device number 2609 <1> ; OUTPUTS -> 2610 <1> ; a zeroed I/O buffer onto the current device 2611 <1> ; r1 - points to last entry in the I/O buffer 2612 <1> ; 2613 <1> ; ((AX = R1)) input/output 2614 <1> ; (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM) 2615 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP)) 2616 <1> 2617 00004592 E88E0E0000 <1> call wslot 2618 <1> ; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first 2619 <1> ; / word of I/O queue r5 points to first data word in buffer 2620 00004597 89DF <1> mov edi, ebx ; r5 2621 00004599 89C2 <1> mov edx, eax 2622 0000459B B980000000 <1> mov ecx, 128 2623 <1> ; mov $256.,r3 2624 000045A0 31C0 <1> xor eax, eax 2625 000045A2 F3AB <1> rep stosd 2626 000045A4 89D0 <1> mov eax, edx 2627 <1> ; 1: 2628 <1> ; clr (r5)+ / zero data word in buffer 2629 <1> ; dec r3 2630 <1> ; bgt 1b / branch until all data words in buffer are zero 2631 <1> ;call dskwr 2632 <1> ; jsr r0,dskwr / write zeroed buffer area out onto physical 2633 <1> ; / block specified in r1 2634 <1> ; eAX (r1) = block number 2635 <1> ;retn 2636 <1> ; rts r0 2637 <1> ; 03/02/2022 2638 000045A6 E9870E0000 <1> jmp dskwr 2055 %include 'u4.s' ; 15/04/2015 2056 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC 2057 <1> ; Last Modification: 26/02/2022 2058 <1> ; ---------------------------------------------------------------------------- 2059 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2060 <1> ; (v0.1 - Beginning: 11/07/2012) 2061 <1> ; 2062 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2063 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2064 <1> ; 2065 <1> ; 2066 <1> ; 2067 <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s 2068 <1> ; 2069 <1> ; **************************************************************************** 2070 <1> ; 14/10/2015 2071 <1> 2072 <1> ;setisp: 2073 <1> ;mov r1,-(sp) 2074 <1> ;mov r2,-(sp) 2075 <1> ;mov r3,-(sp) 2076 <1> ;mov clockp,-(sp) 2077 <1> ;mov $s.syst+2,clockp 2078 <1> ;jmp (r0) 2079 <1> 2080 <1> clock: ; / interrupt from 60 cycle clock 2081 <1> 2082 <1> ; 14/10/2015 2083 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 2084 <1> ; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1) 2085 <1> 2086 <1> ;mov r0,-(sp) / save r0 2087 <1> ;tst *$lks / restart clock? 2088 <1> ;mov $s.time+2,r0 / increment the time of day 2089 <1> ;inc (r0) 2090 <1> ;bne 1f 2091 <1> ;inc -(r0) 2092 <1> ;1: 2093 <1> ;mov clockp,r0 / increment appropriate time category 2094 <1> ;inc (r0) 2095 <1> ;bne 1f 2096 <1> ;inc -(r0) 2097 <1> ;1: 2098 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2099 <1> 2100 000045AB 803D[3C650000]00 <1> cmp byte [u.quant], 0 2101 000045B2 772C <1> ja short clk_1 2102 <1> ; 2103 000045B4 803D[F5640000]FF <1> cmp byte [sysflg], 0FFh ; user or system space ? 2104 000045BB 7529 <1> jne short clk_2 ; system space (sysflg <> 0FFh) 2105 000045BD 803D[49650000]01 <1> cmp byte [u.uno], 1 ; /etc/init ? 2106 000045C4 761A <1> jna short clk_1 ; yes, do not swap out 2107 000045C6 66833D[3E650000]00 <1> cmp word [u.intr], 0 2108 000045CE 7616 <1> jna short clk_2 2109 <1> clk_0: 2110 <1> ; 14/10/2015 2111 000045D0 FE05[F5640000] <1> inc byte [sysflg] ; Now, we are in system space 2112 000045D6 58 <1> pop eax ; return address to the timer interrupt 2113 <1> ; 2114 000045D7 B020 <1> MOV AL,EOI ; GET END OF INTERRUPT MASK 2115 <1> ;CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 2116 000045D9 E620 <1> OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 2117 <1> ; 2118 000045DB E97DEBFFFF <1> jmp sysrelease ; 'sys release' by clock/timer 2119 <1> clk_1: 2120 000045E0 FE0D[3C650000] <1> dec byte [u.quant] 2121 <1> clk_2: 2122 000045E6 C3 <1> retn ; return to (hardware) timer interrupt routine 2123 <1> 2124 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2125 <1> 2126 <1> ;mov $uquant,r0 / decrement user time quantum 2127 <1> ;decb (r0) 2128 <1> ;bge 1f / if less than 0 2129 <1> ;clrb (r0) / make it 0 2130 <1> ;1: / decrement time out counts return now if priority was not 0 2131 <1> ;cmp 4(sp),$200 / ps greater than or equal to 200 2132 <1> ;bge 2f / yes, check time outs 2133 <1> ;tstb (r0) / no, user timed out? 2134 <1> ;bne 1f / no 2135 <1> ;cmpb sysflg,$-1 / yes, are we outside the system? 2136 <1> ;bne 1f / no, 1f 2137 <1> ;mov (sp)+,r0 / yes, put users r0 in r0 2138 <1> ;sys 0 / sysrele 2139 <1> ;rti 2140 <1> ;2: / priority is high so just decrement time out counts 2141 <1> ;mov $toutt,r0 / r0 points to beginning of time out table 2142 <1> ;2: 2143 <1> ;tstb (r0) / is the time out? 2144 <1> ;beq 3f / yes, 3f (get next entry) 2145 <1> ;decb (r0) / no, decrement the time 2146 <1> ;bne 3f / isit zero now? 2147 <1> ;incb (r0) / yes, increment the time 2148 <1> ;3: 2149 <1> ;inc r0 / next entry 2150 <1> ;cmp r0,$touts / end of toutt table? 2151 <1> ;blo 2b / no, check this entry 2152 <1> ;mov (sp)+,r0 / yes, restore r0 2153 <1> ;rti / return from interrupt 2154 <1> ;1: / decrement time out counts; if 0 call subroutine 2155 <1> ;mov (sp)+,r0 / restore r0 2156 <1> ;mov $240,*$ps / set processor priority to 5 2157 <1> ;jsr r0,setisp / save registers 2158 <1> ;mov $touts-toutt-1,r0 / set up r0 as index to decrement thru 2159 <1> ; / the table 2160 <1> ;1: 2161 <1> ;tstb toutt(r0) / is the time out for this entry 2162 <1> ;beq 2f / yes 2163 <1> ;decb toutt(r0) / no, decrement the time 2164 <1> ;bne 2f / is the time 0, now 2165 <1> ;asl r0 / yes, 2 x r0 to get word index for tout entry 2166 <1> ;jsr r0,*touts(r0) / go to appropriate routine specified in this 2167 <1> ;asr r0 / touts entry; set r0 back to toutt index 2168 <1> ;2: 2169 <1> ;dec r0 / set up r0 for next entry 2170 <1> ;bge 1b / finished? , no, go back 2171 <1> ;br retisp / yes, restore registers and do a rti 2172 <1> 2173 <1> ;retisp: 2174 <1> ;mov (sp)+,clockp / pop values before interrupt off the stack 2175 <1> ;mov (sp)+,r3 2176 <1> ;mov (sp)+,r2 2177 <1> ;mov (sp)+,r1 2178 <1> ;mov (sp)+,r0 2179 <1> ;rti / return from interrupt 2180 <1> 2181 <1> 2182 <1> wakeup: ; / wakeup processes waiting for an event 2183 <1> ; / by linking them to the queue 2184 <1> ; 2185 <1> ; 26/02/2022 2186 <1> ; 15/09/2015 2187 <1> ; 29/06/2015 2188 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 2189 <1> ; 2190 <1> ; 15/05/2013 - 02/06/2014 2191 <1> ; Retro UNIX 8086 v1 modification ! 2192 <1> ; (Process/task switching routine by using 2193 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.) 2194 <1> ; 2195 <1> ; In original UNIX v1, 'wakeup' is called to wake the process 2196 <1> ; sleeping in the specified wait channel by creating a link 2197 <1> ; to it from the last user process on the run queue. 2198 <1> ; If there is no process to wake up, nothing happens. 2199 <1> ; 2200 <1> ; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set 2201 <1> ; 'switching' status of the current process (owns current tty) 2202 <1> ; (via alt + function keys) to a process which has highest 2203 <1> ; priority (on run queue) on the requested tty (0 to 7, except 2204 <1> ; 8 and 9 which are tty identifiers of COM1, COM2 serial ports) 2205 <1> ; as it's console tty. (NOTE: 'p.ttyc' is used to set console 2206 <1> ; tty for tty switching by keyboard.) 2207 <1> ; 2208 <1> ; INPUT -> 2209 <1> ; AL = wait channel (r3) ('tty number' for now) 2210 <1> ; ;;EBX = Run queue (r2) offset 2211 <1> ; 2212 <1> ; ((modified registers: EAX, EBX)) 2213 <1> ; 2214 000045E7 0FB6D8 <1> movzx ebx, al ; 29/06/2015 2215 000045EA 81C3[98610000] <1> add ebx, wlist 2216 000045F0 8A03 <1> mov al, [ebx] ; waiting list (waiting process number) 2217 000045F2 20C0 <1> and al, al 2218 000045F4 741E <1> jz short wa0 ; nothing to wakeup 2219 <1> ; 2220 000045F6 30E4 <1> xor ah, ah 2221 000045F8 8825[3C650000] <1> mov [u.quant], ah ; 0 ; time quantum = 0 2222 000045FE 8823 <1> mov [ebx], ah ; 0 ; zero wait channel entry 2223 <1> ; 15/09/2015 2224 00004600 0FB6D8 <1> movzx ebx, al 2225 <1> ; 26/02/2022 (p.waitc is not used) 2226 <1> ;mov [ebx+p.waitc-1], ah ; 0 2227 00004603 FEC4 <1> inc ah 2228 00004605 88A3[73620000] <1> mov byte [ebx+p.stat-1], ah ; 1 ; SRUN 2229 <1> ; 2230 0000460B 57 <1> push edi 2231 0000460C 52 <1> push edx 2232 0000460D E851FFFFFF <1> call putlu 2233 00004612 5A <1> pop edx 2234 00004613 5F <1> pop edi 2235 <1> wa0: 2236 00004614 C3 <1> retn 2237 <1> 2238 <1> sleep: 2239 <1> ; 26/02/2022 2240 <1> ; 03/02/2022 2241 <1> ; 15/09/2015 2242 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2243 <1> ; 2244 <1> ; 09/05/2013 - 20/03/2014 2245 <1> ; 2246 <1> ; Retro UNIX 8086 v1 modification ! 2247 <1> ; (Process/task switching and quit routine by using 2248 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2249 <1> ; 2250 <1> ; In original UNIX v1, 'sleep' is called to wait for 2251 <1> ; tty and tape output or input becomes available 2252 <1> ; and process is put on waiting channel and swapped out, 2253 <1> ; then -when the tty or tape is ready to write or read- 2254 <1> ; 'wakeup' gets process back to active swapped-in status.) 2255 <1> ; 2256 <1> ; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and 2257 <1> ; Int 09h keyboard interrupt will set 'quit' or 'switching' 2258 <1> ; status of the current process also INT 1Ch will count down 2259 <1> ; 'uquant' value and INT 09h will redirect scancode of keystroke 2260 <1> ; to tty buffer of the current process and kernel will get 2261 <1> ; user input by using tty buffer of the current process 2262 <1> ; (instead of standard INT 16h interrupt). 2263 <1> ; TTY output will be redirected to related video page of text mode 2264 <1> ; (INT 10h will be called with different video page depending 2265 <1> ; on tty assignment of the active process: 0 to 7 for 2266 <1> ; pseudo screens.) 2267 <1> ; 2268 <1> ; In Retro UNIX 8086 v1, 'sleep' will be called to wait for 2269 <1> ; a keystroke from keyboard or wait for reading or writing 2270 <1> ; characters/data on serial port(s). 2271 <1> ; 2272 <1> ; Character/Terminal input/output through COM1 and COM2 will be 2273 <1> ; performed by related routines in addition to pseudo TTY routines. 2274 <1> ; 2275 <1> ; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013) 2276 <1> ; 2277 <1> ;; 05/10/2013 2278 <1> ;10/12/2013 2279 <1> ;cmp byte [u.uno], 1 2280 <1> ;ja short sleep0 2281 <1> ;retn 2282 <1> 2283 <1> ; 20/03/2014 2284 <1> ;mov bx, [runq] 2285 <1> ;cmp bl, bh 2286 <1> ;jne short sleep0 2287 <1> ; 25/02/2014 2288 <1> ;cmp word ptr [runq], 0 2289 <1> ;ja short sleep0 2290 <1> ;retn 2291 <1> sleep0: 2292 <1> ; 2293 00004615 E849000000 <1> call isintr 2294 <1> ;jnz sysret 2295 <1> ; / wait for event 2296 <1> ; jsr r0,isintr / check to see if interrupt 2297 <1> ; / or quit from user 2298 <1> ; br 2f / something happened 2299 <1> ; / yes, his interrupt so return 2300 <1> ; / to user 2301 <1> ; 03/02/2022 2302 0000461A 7405 <1> jz short sleep_2 2303 <1> sleep_3: 2304 0000461C E9E0EAFFFF <1> jmp sysret 2305 <1> sleep_2: 2306 <1> ; 30/06/2015 2307 00004621 0FB6DC <1> movzx ebx, ah ; 30/06/2015 2308 00004624 81C3[98610000] <1> add ebx, wlist 2309 0000462A 8A03 <1> mov al, [ebx] 2310 0000462C 20C0 <1> and al, al 2311 0000462E 7407 <1> jz short sleep1 2312 00004630 53 <1> push ebx 2313 00004631 E82DFFFFFF <1> call putlu 2314 00004636 5B <1> pop ebx 2315 <1> sleep1: 2316 00004637 A0[49650000] <1> mov al, [u.uno] 2317 0000463C 8803 <1> mov [ebx], al ; put the process number 2318 <1> ; in the wait channel 2319 <1> ; mov (r0)+,r1 / put number of wait channel in r1 2320 <1> ; movb wlist(r1),-(sp) / put old process number in there, 2321 <1> ; / on the stack 2322 <1> ; movb u.uno,wlist(r1) / put process number of process 2323 <1> ; / to put to sleep in there 2324 <1> ; 15/09/2015 2325 0000463E 0FB6D8 <1> movzx ebx, al 2326 00004641 C683[73620000]04 <1> mov byte [ebx+p.stat-1], 4 ; SSLEEP 2327 <1> ; 26/02/2022 (p.waitc is not used) 2328 <1> ;inc ah 2329 <1> ;mov [ebx+p.waitc-1], ah ; wait channel + 1 2330 <1> ; 2331 00004648 66FF35[E4640000] <1> push word [cdev] 2332 <1> ; mov cdev,-(sp) / nothing happened in isintr so 2333 0000464F E842FEFFFF <1> call swap 2334 <1> ; jsr r0,swap / swap out process that needs to sleep 2335 00004654 668F05[E4640000] <1> pop word [cdev] 2336 <1> ; mov (sp)+,cdev / restore device 2337 0000465B E803000000 <1> call isintr 2338 <1> ; 22/09/2013 2339 <1> ;jnz sysret 2340 <1> ; jsr r0,isintr / check for interrupt of new process 2341 <1> ; br 2f / yes, return to new user 2342 <1> ; movb (sp)+,r1 / no, r1 = old process number that was 2343 <1> ; / originally on the wait channel 2344 <1> ; beq 1f / if 0 branch 2345 <1> ; mov $runq+4,r2 / r2 points to lowest priority queue 2346 <1> ; mov $300,*$ps / processor priority = 6 2347 <1> ; jsr r0,putlu / create link to old process number 2348 <1> ; clr *$ps / clear the status; process priority = 0 2349 <1> ; 03/02/2022 2350 00004660 75BA <1> jnz short sleep_3 2351 <1> ;1: 2352 00004662 C3 <1> retn 2353 <1> ; rts r0 / return 2354 <1> ;2: 2355 <1> ;;jmp sysret 2356 <1> ; jmp sysret / return to user 2357 <1> 2358 <1> isintr: 2359 <1> ; 03/02/2022 2360 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2361 <1> ; 2362 <1> ; 09/05/2013 - 30/05/2014 2363 <1> ; 2364 <1> ; Retro UNIX 8086 v1 modification ! 2365 <1> ; (Process/task switching and quit routine by using 2366 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2367 <1> ; 2368 <1> ; Retro UNIX 8086 v1 modification: 2369 <1> ; 'isintr' checks if user interrupt request is enabled 2370 <1> ; and there is a 'quit' request by user; 2371 <1> ; otherwise, 'isintr' will return with zf=1 that means 2372 <1> ; "nothing to do". (20/10/2013) 2373 <1> ; 2374 <1> ; 20/10/2013 2375 00004663 66833D[30650000]00 <1> cmp word [u.ttyp], 0 ; has process got a tty ? 2376 0000466B 761F <1> jna short isintr2 ; retn 2377 <1> ; 03/09/2013 2378 <1> ; (nothing to do) 2379 <1> ;retn 2380 <1> ; 22/09/2013 2381 0000466D 66833D[3E650000]00 <1> cmp word [u.intr], 0 2382 00004675 7615 <1> jna short isintr2 ; retn 2383 <1> ; 30/05/2014 2384 <1> ;push ax 2385 <1> ; 03/02/2022 2386 00004677 50 <1> push eax 2387 00004678 66A1[40650000] <1> mov ax, [u.quit] 2388 0000467E 6609C0 <1> or ax, ax ; 0 ? 2389 00004681 7408 <1> jz short isintr1 ; zf = 1 2390 00004683 6683F8FE <1> cmp ax, 0FFFEh ; 'ctrl + brk' check 2391 00004687 7702 <1> ja short isintr1 ; 0FFFFh, zf = 0 2392 <1> ;xor ax, ax ; zf = 1 2393 <1> ; 03/02/2022 2394 00004689 31C0 <1> xor eax, eax ; zf = 1 2395 <1> isintr1: 2396 <1> ;pop ax 2397 <1> ; 03/02/2022 2398 0000468B 58 <1> pop eax 2399 <1> isintr2: ; 22/09/2013 2400 <1> ; zf=1 -> nothing to do 2401 0000468C C3 <1> retn 2402 <1> 2403 <1> ; UNIX v1 original 'isintr' routine... 2404 <1> ;mov r1,-(sp) / put number of wait channel on the stack 2405 <1> ;mov r2,-(sp) / save r2 2406 <1> ;mov u.ttyp,r1 / r1 = pointer to buffer of process control 2407 <1> ; / typewriter 2408 <1> ;beq 1f / if 0, do nothing except skip return 2409 <1> ;movb 6(r1),r1 / put interrupt char in the tty buffer in r1 2410 <1> ;beq 1f / if its 0 do nothing except skip return 2411 <1> ;cmp r1,$177 / is interrupt char = delete? 2412 <1> ;bne 3f / no, so it must be a quit (fs) 2413 <1> ;tst u.intr / yes, value of u.intr determines handling 2414 <1> ; / of interrupts 2415 <1> ;bne 2f / if not 0, 2f. If zero do nothing. 2416 <1> ;1: 2417 <1> ;tst (r0)+ / bump r0 past system return (skip) 2418 <1> ;4: 2419 <1> ;mov (sp)+,r2 / restore r1 and r2 2420 <1> ;mov (sp)+,r1 2421 <1> ;rts r0 2422 <1> ;3: / interrupt char = quit (fs) 2423 <1> ;tst u.quit / value of u.quit determines handling of quits 2424 <1> ;beq 1b / u.quit = 0 means do nothing 2425 <1> ;2: / get here because either u.intr <> 0 or u.qult <> O 2426 <1> ;mov $tty+6,r1 / move pointer to tty block into r1 2427 <1> ;1: / find process control tty entry in tty block 2428 <1> ;cmp (r1),u.ttyp / is this the process control tty buffer? 2429 <1> ;beq 1f / block found go to 1f 2430 <1> ;add $8,r1 / look at next tty block 2431 <1> ;cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks 2432 <1> ;blo 1b / no 2433 <1> ;br 4b / no process control tty found so go to 4b 2434 <1> ;1: 2435 <1> ;mov $240,*$ps / set processor priority to 5 2436 <1> ;movb -3(r1),0f / load getc call argument; character llst 2437 <1> ; / identifier 2438 <1> ;inc 0f / increment 2439 <1> ;1: 2440 <1> ;jsr r0,getc; 0:.. / erase output char list for control 2441 <1> ; br 4b / process tty. This prevents a line of stuff 2442 <1> ; / being typed out after you hit the interrupt 2443 <1> ; / key 2444 <1> ;br 1b 2056 %include 'u5.s' ; 03/06/2015 2057 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC 2058 <1> ; Last Modification: 22/04/2022 2059 <1> ; ---------------------------------------------------------------------------- 2060 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2061 <1> ; (v0.1 - Beginning: 11/07/2012) 2062 <1> ; 2063 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2064 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2065 <1> ; 2066 <1> ; 2067 <1> ; 2068 <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s 2069 <1> ; 2070 <1> ; **************************************************************************** 2071 <1> ; 14/11/2015 2072 <1> 2073 <1> mget: 2074 <1> ; 22/04/2022 2075 <1> ; 03/02/2022 2076 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2077 <1> ; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2078 <1> ; 2079 <1> ; Get existing or (allocate) a new disk block for file 2080 <1> ; 2081 <1> ; INPUTS -> 2082 <1> ; u.fofp (file offset pointer) 2083 <1> ; inode 2084 <1> ; u.off (file offset) 2085 <1> ; OUTPUTS -> 2086 <1> ; r1 (physical block number) 2087 <1> ; r2, r3, r5 (internal) 2088 <1> ; 2089 <1> ; ((AX = R1)) output 2090 <1> ; (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM) 2091 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 2092 <1> 2093 <1> ; mov *u.fofp,mq / file offset in mq 2094 <1> ; clr ac / later to be high sig 2095 <1> ; mov $-8,lsh / divide ac/mq by 256. 2096 <1> ; mov mq,r2 2097 <1> ; bit $10000,i.flgs / lg/sm is this a large or small file 2098 <1> ; bne 4f / branch for large file 2099 <1> mget_0: 2100 <1> ; 03/02/2022 2101 0000468D 29C0 <1> sub eax, eax 2102 0000468F 29D2 <1> sub edx, edx 2103 00004691 29C9 <1> sub ecx, ecx 2104 00004693 29DB <1> sub ebx, ebx 2105 <1> 2106 00004695 8B35[10650000] <1> mov esi, [u.fofp] 2107 <1> ;movzx ebx, byte [esi+1] 2108 <1> ; 03/02/2022 2109 0000469B 46 <1> inc esi 2110 0000469C 8A1E <1> mov bl, [esi] 2111 <1> 2112 <1> ; BX = r2 2113 <1> ; 03/02/2022 2114 0000469E F605[F5610000]10 <1> test byte [i.flgs+1], 10h 2115 <1> ;test word [i.flgs], 4096 ; 1000h 2116 <1> ; is this a large or small file 2117 000046A5 756C <1> jnz short mget_5 ; 4f ; large file 2118 <1> 2119 000046A7 F6C3F0 <1> test bl, 0F0h ; !0Fh 2120 <1> ; bit $!17,r2 2121 000046AA 7525 <1> jnz short mget_2 2122 <1> ; bne 3f / branch if r2 greater than or equal to 16 2123 000046AC 80E30E <1> and bl, 0Eh 2124 <1> ; bic $!16,r2 / clear all bits but bits 1,2,3 2125 <1> ; 03/02/2022 2126 000046AF 668B83[FA610000] <1> mov ax, [ebx+i.dskp] 2127 <1> ;movzx eax, word [ebx+i.dskp] ; AX = R1, physical block number 2128 <1> ; mov i.dskp(r2),r1 / r1 has physical block number 2129 <1> ; 03/02/2022 2130 000046B6 09C0 <1> or eax, eax 2131 <1> ;or ax, ax 2132 000046B8 7516 <1> jnz short mget_1 2133 <1> ; bne 2f / if physical block num is zero then need a new block 2134 <1> ; / for file 2135 000046BA E8A6000000 <1> call alloc 2136 <1> ; jsr r0,alloc / allocate a new block 2137 <1> ; eAX (r1) = Physical block number 2138 000046BF 668983[FA610000] <1> mov [ebx+i.dskp], ax 2139 <1> ; mov r1,i.dskp(r2) / physical block number stored in i-node 2140 000046C6 E835020000 <1> call setimod 2141 <1> ; jsr r0,setimod / set inode modified byte (imod) 2142 000046CB E8C2FEFFFF <1> call clear 2143 <1> ; jsr r0,clear / zero out disk/drum block just allocated 2144 <1> mget_1: ; 2: 2145 <1> ; eAX (r1) = Physical block number 2146 000046D0 C3 <1> retn 2147 <1> ; rts r0 2148 <1> mget_2: ; 3: / adding on block which changes small file to a large file 2149 000046D1 E88F000000 <1> call alloc 2150 <1> ; jsr r0,alloc / allocate a new block for this file; 2151 <1> ; / block number in r1 2152 <1> ; eAX (r1) = Physical block number 2153 000046D6 E84A0D0000 <1> call wslot 2154 <1> ; jsr r0,wslot / set up I/O buffer for write, r5 points to 2155 <1> ; / first data word in buffer 2156 <1> ; 03/02/2022 2157 000046DB 31C9 <1> xor ecx, ecx 2158 000046DD B108 <1> mov cl, 8 2159 <1> ;mov ecx, 8 ; R3, transfer old physical block pointers 2160 <1> ; into new indirect block area for the new 2161 <1> ; large file 2162 000046DF 89DF <1> mov edi, ebx ; r5 2163 000046E1 BE[FA610000] <1> mov esi, i.dskp 2164 <1> ; mov $8.,r3 / next 6 instructions transfer old physical 2165 <1> ; / block pointers 2166 <1> ; mov $i.dskp,r2 / into new indirect block for the new 2167 <1> ; / large file 2168 <1> ; 22/04/2022 2169 000046E6 50 <1> push eax ; * ; bugfix 2170 <1> 2171 <1> ;xor ax, ax ; mov ax, 0 2172 <1> ; 03/02/2022 2173 000046E7 31C0 <1> xor eax, eax 2174 <1> mget_3: ;1: 2175 000046E9 66A5 <1> movsw 2176 <1> ; mov (r2),(r5)+ 2177 000046EB 668946FE <1> mov [esi-2], ax 2178 <1> ; clr (r2)+ 2179 000046EF E2F8 <1> loop mget_3 ; 1b 2180 <1> ; dec r3 2181 <1> ; bgt 1b 2182 <1> 2183 000046F1 B1F8 <1> mov cl, 256-8 2184 <1> ; mov $256.-8.,r3 / clear rest of data buffer 2185 <1> mget_4: ; 1 2186 000046F3 F366AB <1> rep stosw 2187 <1> ; clr (r5)+ 2188 <1> ; dec r3 2189 <1> ; bgt 1b 2190 <1> 2191 <1> ; 22/04/2022 2192 <1> ;pop eax ; * ; bugfix 2193 <1> 2194 <1> ; 24/03/2013 2195 <1> ; AX (r1) = Physical block number 2196 000046F6 E8370D0000 <1> call dskwr 2197 <1> ; jsr r0,dskwr / write new indirect block on disk 2198 <1> 2199 <1> ; 22/04/2022 2200 000046FB 58 <1> pop eax ; * ; bugfix 2201 <1> 2202 <1> ; eAX (r1) = Physical block number 2203 000046FC 66A3[FA610000] <1> mov [i.dskp], ax 2204 <1> ; mov r1,i.dskp / put pointer to indirect block in i-node 2205 <1> ; 03/02/2022 2206 00004702 800D[F5610000]10 <1> or byte [i.flgs+1], 10h 2207 <1> ;or word [i.flgs], 4096 ; 1000h 2208 <1> ; bis $10000,i.flgs / set large file bit 2209 <1> ; / in i.flgs word of i-node 2210 00004709 E8F2010000 <1> call setimod 2211 <1> ; jsr r0,setimod / set i-node modified flag 2212 0000470E E97AFFFFFF <1> jmp mget_0 2213 <1> ; br mget 2214 <1> 2215 <1> mget_5: ; 4 ; large file 2216 <1> ; mov $-8,lsh / divide byte number by 256. 2217 <1> ; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset 2218 <1> ; / in indirect block 2219 <1> ; mov r2,-(sp) / save on stack (*) 2220 <1> ; mov mq,r2 / calculate offset in i-node for pointer to proper 2221 <1> ; / indirect block 2222 <1> ; bic $!16,r2 2223 00004713 80E3FE <1> and bl, 0FEh ; bh = 0 2224 00004716 53 <1> push ebx ; i-node pointer offset in indirect block (*) 2225 <1> ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512) 2226 <1> ; for this file system (offset 128 to 255 not in use) 2227 <1> ; There is always 1 indirect block for this file system 2228 <1> ; 03/02/2022 2229 00004717 66A1[FA610000] <1> mov ax, [i.dskp] 2230 <1> ;movzx eax, word [i.dskp] ; i.dskp[0] 2231 <1> ; mov i.dskp(r2),r1 2232 <1> ; 03/02/2022 2233 0000471D 09C0 <1> or eax, eax 2234 <1> ;or ax, ax ; R1 2235 0000471F 7515 <1> jnz short mget_6 ; 2f 2236 <1> ; bne 2f / if no indirect block exists 2237 00004721 E83F000000 <1> call alloc 2238 <1> ; jsr r0,alloc / allocate a new block 2239 00004726 66A3[FA610000] <1> mov [i.dskp], ax ; 03/03/2013 2240 <1> ; mov r1,i.dskp(r2) / put block number of new block in i-node 2241 0000472C E8CF010000 <1> call setimod 2242 <1> ; jsr r0,setimod / set i-node modified byte 2243 <1> ; eAX = new block number 2244 00004731 E85CFEFFFF <1> call clear 2245 <1> ; jsr r0,clear / clear new block 2246 <1> mget_6: ;2 2247 <1> ; 05/03/2013 2248 <1> ; eAX = r1, physical block number (of indirect block) 2249 00004736 E8860C0000 <1> call dskrd ; read indirect block 2250 <1> ; jsr r0,dskrd / read in indirect block 2251 0000473B 5A <1> pop edx ; R2, get offset (*) 2252 <1> ; mov (sp)+,r2 / get offset 2253 <1> ; eAX = r1, physical block number (of indirect block) 2254 0000473C 50 <1> push eax ; ** ; 24/03/2013 2255 <1> ; mov r1,-(sp) / save block number of indirect block on stack 2256 <1> ; eBX (r5) = pointer to buffer (indirect block) 2257 0000473D 01D3 <1> add ebx, edx ; / r5 points to first word in indirect block, r2 2258 <1> ; add r5,r2 / r5 points to first word in indirect block, r2 2259 <1> ; / points to location of inter 2260 <1> ; 03/02/2022 2261 0000473F 668B03 <1> mov ax, [ebx] 2262 <1> ;movzx eax, word [ebx] ; put physical block no of block 2263 <1> ; in file sought in R1 (AX) 2264 <1> ; mov (r2),r1 / put physical block no of block in file 2265 <1> ; / sought in r1 2266 <1> ; 03/02/2022 2267 00004742 09C0 <1> or eax, eax 2268 <1> ;or ax, ax 2269 00004744 751D <1> jnz short mget_7 ; 2f 2270 <1> ; bne 2f / if no block exists 2271 00004746 E81A000000 <1> call alloc 2272 <1> ; jsr r0,alloc / allocate a new block 2273 0000474B 668903 <1> mov [ebx], ax ; R1 2274 <1> ; mov r1,(r2) / put new block number into proper location in 2275 <1> ; / indirect block 2276 0000474E 5A <1> pop edx ; ** ; 24/03/2013 2277 <1> ; mov (sp)+,r1 / get block number of indirect block 2278 0000474F 52 <1> push edx ; ** ; 31/07/2013 2279 00004750 50 <1> push eax ; * ; 24/03/2013, 31/07/2013 (new block number) 2280 00004751 89D0 <1> mov eax, edx ; 24/03/2013 2281 <1> ; mov (r2),-(sp) / save block number of new block 2282 <1> ; eAX (r1) = physical block number (of indirect block) 2283 00004753 E8CD0C0000 <1> call wslot 2284 <1> ; jsr r0,wslot 2285 <1> ; eAX (r1) = physical block number 2286 <1> ; eBX (r5) = pointer to buffer (indirect block) 2287 00004758 E8D50C0000 <1> call dskwr 2288 <1> ; eAX = r1 = physical block number (of indirect block) 2289 <1> ; jsr r0,dskwr / write newly modified indirect block 2290 <1> ; / back out on disk 2291 0000475D 58 <1> pop eax ; * ; 31/07/2013 2292 <1> ; mov (sp),r1 / restore block number of new block 2293 <1> ; eAX (r1) = physical block number of new block 2294 0000475E E82FFEFFFF <1> call clear 2295 <1> ; jsr r0,clear / clear new block 2296 <1> mget_7: ; 2 2297 00004763 5A <1> pop edx ; ** 2298 <1> ; tst (sp)+ / bump stack pointer 2299 <1> ; eAX (r1) = Block number of new block 2300 00004764 C3 <1> retn 2301 <1> ; rts r0 2302 <1> 2303 <1> alloc: 2304 <1> ; 03/02/2022 2305 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2306 <1> ; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2307 <1> ; 2308 <1> ; get a free block and 2309 <1> ; set the corresponding bit in the free storage map 2310 <1> ; 2311 <1> ; INPUTS -> 2312 <1> ; cdev (current device) 2313 <1> ; r2 2314 <1> ; r3 2315 <1> ; OUTPUTS -> 2316 <1> ; r1 (physical block number of block assigned) 2317 <1> ; smod, mmod, systm (super block), mount (mountable super block) 2318 <1> ; 2319 <1> ; ((AX = R1)) output 2320 <1> ; (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM) 2321 <1> ; ((Modified registers: DX, CX)) 2322 <1> 2323 <1> ;mov r2,-(sp) / save r2, r3 on stack 2324 <1> ;mov r3,-(sp) 2325 <1> ;push ecx 2326 00004765 53 <1> push ebx ; R2 2327 <1> ;push edx ; R3 2328 00004766 BB[C8750000] <1> mov ebx, systm ; SuperBlock 2329 <1> ; mov $systm,r2 / start of inode and free storage map for drum 2330 0000476B 803D[E4640000]00 <1> cmp byte [cdev], 0 2331 <1> ; tst cdev 2332 00004772 7605 <1> jna short alloc_1 2333 <1> ; beq 1f / drum is device 2334 00004774 BB[D0770000] <1> mov ebx, mount 2335 <1> ; mov $mount,r2 / disk or tape is device, start of inode and 2336 <1> ; / free storage map 2337 <1> alloc_1: ; 1 2338 <1> ; 03/02/2022 2339 <1> ;sub ecx, ecx 2340 <1> ;sub edx, edx 2341 <1> ;sub eax, eax 2342 <1> 2343 00004779 668B0B <1> mov cx, [ebx] 2344 <1> ; mov (r2)+,r1 / first word contains number of bytes in free 2345 <1> ; / storage map 2346 <1> ; 03/02/2022 2347 0000477C C1E103 <1> shl ecx, 3 2348 <1> ;shl cx, 3 2349 <1> ; asl r1 / multiply r1 by eight gives 2350 <1> ; number of blocks in device 2351 <1> ; asl r1 2352 <1> ; asl r1 2353 <1> ;;push cx ;; 01/08/2013 2354 <1> ; mov r1,-(sp) / save # of blocks in device on stack 2355 0000477F 31C0 <1> xor eax, eax ; 0 2356 <1> ; clr r1 / r1 contains bit count of free storage map 2357 <1> alloc_2: ; 1 2358 00004781 43 <1> inc ebx ; 18/8/2012 2359 00004782 43 <1> inc ebx ; 2360 00004783 668B13 <1> mov dx, [ebx] 2361 <1> ; mov (r2)+,r3 / word of free storage map in r3 2362 <1> ; 03/02/2022 2363 00004786 09D2 <1> or edx, edx 2364 <1> ;or dx, dx 2365 00004788 750D <1> jnz short alloc_3 ; 1f 2366 <1> ; bne 1f / branch if any free blocks in this word 2367 0000478A 6683C010 <1> add ax, 16 2368 <1> ; add $16.,r1 2369 <1> ; 03/02/2022 2370 0000478E 39C8 <1> cmp eax, ecx 2371 <1> ;cmp ax, cx 2372 <1> ; cmp r1 ,(sp) / have we examined all free storage bytes 2373 00004790 72EF <1> jb short alloc_2 2374 <1> ; blo 1b 2375 <1> ; 14/11/2015 2376 <1> ; Note: If the super block buffer has wrong content (zero bytes) 2377 <1> ; because of a (DMA or another) r/w error, 2378 <1> ; we will be here, at 'jmp panic' code address, 2379 <1> ; even if the (disk) file system space is not full !!! 2380 <1> ; (cx = 0) 2381 <1> ; 2382 00004792 E90CE2FFFF <1> jmp panic 2383 <1> ; jmp panic / found no free storage 2384 <1> alloc_3: ; 1 2385 <1> ; 03/02/2022 2386 00004797 D1EA <1> shr edx, 1 2387 <1> ;shr dx, 1 2388 <1> ; asr r3 / find a free block 2389 00004799 7203 <1> jc short alloc_4 ; 1f 2390 <1> ; bcs 1f / branch when free block found; bit for block k 2391 <1> ; / is in byte k/8 / in bit k (mod 8) 2392 <1> ; 03/02/2022 2393 0000479B 40 <1> inc eax 2394 <1> ;inc ax 2395 <1> ; inc r1 / increment bit count in bit k (mod8) 2396 0000479C EBF9 <1> jmp short alloc_3 2397 <1> ; br 1b 2398 <1> alloc_4: ; 1: 2399 <1> ;; pop cx ;; 01/08/2013 2400 <1> ; tst (sp)+ / bump sp 2401 <1> ; 02/04/2013 2402 0000479E E829000000 <1> call free3 2403 <1> ; jsr r0,3f / have found a free block 2404 <1> ; 21/8/2012 2405 000047A3 66F7D2 <1> not dx ; masking bit is '0' and others are '1' 2406 000047A6 662113 <1> and [ebx], dx ;; 0 -> allocated 2407 <1> ; bic r3,(r2) / set bit for this block 2408 <1> ; / i.e. assign block 2409 <1> ; br 2f 2410 000047A9 EB09 <1> jmp short alloc_5 2411 <1> 2412 <1> free: 2413 <1> ; 03/02/2022 2414 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2415 <1> ; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2416 <1> ; 2417 <1> ; calculates byte address and bit position for given block number 2418 <1> ; then sets the corresponding bit in the free storage map 2419 <1> ; 2420 <1> ; INPUTS -> 2421 <1> ; r1 - block number for a block structured device 2422 <1> ; cdev - current device 2423 <1> ; OUTPUTS -> 2424 <1> ; free storage map is updated 2425 <1> ; smod is incremented if cdev is root device (fixed disk) 2426 <1> ; mmod is incremented if cdev is a removable disk 2427 <1> ; 2428 <1> ; (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM) 2429 <1> ; ((Modified registers: DX, CX)) 2430 <1> 2431 <1> ;mov r2,-(sp) / save r2, r3 2432 <1> ;mov r3,-(sp) 2433 <1> ;push ecx 2434 000047AB 53 <1> push ebx ; R2 2435 <1> ;push edx ; R3 2436 <1> 2437 000047AC E81B000000 <1> call free3 2438 <1> ; jsr r0,3f / set up bit mask and word no. 2439 <1> ; / in free storage map for block 2440 000047B1 660913 <1> or [ebx], dx 2441 <1> ; bis r3, (r2) / set free storage block bit; 2442 <1> ; / indicates free block 2443 <1> ; 0 -> allocated, 1 -> free 2444 <1> 2445 <1> alloc_5: 2446 <1> ; 07/04/2013 2447 <1> free_1: ; 2: 2448 <1> ;pop edx 2449 <1> ; mov (sp)+,r3 / restore r2, r3 2450 000047B4 5B <1> pop ebx 2451 <1> ; mov (sp)+,r2 2452 <1> ; pop ecx 2453 000047B5 803D[E4640000]00 <1> cmp byte [cdev], 0 2454 <1> ; tst cdev / cdev = 0, block structured, drum; 2455 <1> ; / cdev = 1, mountable device 2456 000047BC 7707 <1> ja short alloc_6 ; 1f 2457 <1> ; bne 1f 2458 <1> ;mov byte [smod], 1 2459 000047BE FE05[F3640000] <1> inc byte [smod] 2460 <1> ; incb smod / set super block modified for drum 2461 <1> ; eAX (r1) = block number 2462 000047C4 C3 <1> retn 2463 <1> ; rts r0 2464 <1> free_2: 2465 <1> alloc_6: ; 1: 2466 <1> ;mov byte [mmod], 1 2467 000047C5 FE05[F4640000] <1> inc byte [mmod] 2468 <1> ; incb mmod 2469 <1> ; / set super block modified for mountable device 2470 <1> ; eAX (r1) = block number 2471 000047CB C3 <1> retn 2472 <1> ; rts r0 2473 <1> free3: 2474 <1> ; 03/02/2022 2475 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2476 <1> ; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2477 <1> ; 2478 <1> ; free3 is called from 'alloc' and 'free' procedures 2479 <1> ; 2480 <1> alloc_free_3: ; 3 2481 <1> ;mov dx, 1 2482 <1> ; 03/02/2022 2483 000047CC 31D2 <1> xor edx, edx 2484 000047CE 42 <1> inc edx 2485 <1> ; edx = 1 2486 000047CF 88C1 <1> mov cl, al 2487 <1> ; mov r1,r2 / block number, k, = 1 2488 000047D1 80E10F <1> and cl, 0Fh ; 0Fh <-- (k) mod 16 2489 <1> ; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8) 2490 000047D4 7402 <1> jz short free4 2491 <1> ; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to 2492 <1> ; / (k) mod 8 2493 <1> ;shl dx, cl 2494 <1> ; 03/02/2022 2495 000047D6 D3E2 <1> shl edx, cl 2496 <1> free4: 2497 000047D8 0FB7D8 <1> movzx ebx, ax 2498 <1> ; mov r1,r2 / divide block number by 16 2499 <1> ; 03/02/2022 2500 000047DB C1EB04 <1> shr ebx, 4 2501 <1> ;shr bx, 4 2502 <1> ; asr r2 2503 <1> ; asr r2 2504 <1> ; asr r2 2505 <1> ; asr r2 2506 <1> ; bcc 1f / branch if bit 3 in r1 was 0 i.e., 2507 <1> ; / bit for block is in lower half of word 2508 <1> ; swab r3 / swap bytes in r3; bit in upper half of word in free 2509 <1> ; / storage map 2510 <1> alloc_free_4: ; 1 2511 <1> ; 03/02/2022 2512 000047DE D1E3 <1> shl ebx, 1 2513 <1> ;shl bx, 1 2514 <1> ; asl r2 / multiply block number by 2; r2 = k/8 2515 000047E0 81C3[CA750000] <1> add ebx, systm+2 ; SuperBlock+2 2516 <1> ; add $systm+2,r2 / address of word of free storage map for drum 2517 <1> ; / with block bit in it 2518 000047E6 803D[E4640000]00 <1> cmp byte [cdev], 0 2519 <1> ; tst cdev 2520 000047ED 7606 <1> jna short alloc_free_5 2521 <1> ; beq 1f / cdev = 0 indicates device is drum 2522 000047EF 81C308020000 <1> add ebx, mount - systm 2523 <1> ; add $mount-systm,r2 / address of word of free storage map for 2524 <1> ; / mountable device with bit of block to be 2525 <1> ; / freed 2526 <1> alloc_free_5: ; 1 2527 000047F5 C3 <1> retn 2528 <1> ; rts r0 / return to 'free' 2529 <1> ; 2 2530 <1> ; .byte 1,2,4,10,20,40,100,200 / masks for bits 0,...,7 2531 <1> 2532 <1> iget: 2533 <1> ; 03/02/2022 2534 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2535 <1> ; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 2536 <1> ; 2537 <1> ; get a new i-node whose i-number in r1 and whose device is in cdev 2538 <1> ; 2539 <1> ; ('iget' returns current i-number in r1, if input value of r1 is 0) 2540 <1> ; 2541 <1> ; INPUTS -> 2542 <1> ; ii - current i-number, rootdir 2543 <1> ; cdev - new i-node device 2544 <1> ; idev - current i-node device 2545 <1> ; imod - current i-node modified flag 2546 <1> ; mnti - cross device file i-number 2547 <1> ; r1 - i-numbe rof new i-node 2548 <1> ; mntd - mountable device number 2549 <1> ; 2550 <1> ; OUTPUTS -> 2551 <1> ; cdev, idev, imod, ii, r1 2552 <1> ; 2553 <1> ; ((AX = R1)) input/output 2554 <1> ; 2555 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 2556 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2557 <1> 2558 000047F6 8A15[E4640000] <1> mov dl, [cdev] ; 18/07/2013 2559 000047FC 8A35[E2640000] <1> mov dh, [idev] ; 07/08/2013 2560 <1> ; 2561 00004802 663B05[E0640000] <1> cmp ax, [ii] 2562 <1> ; cmp r1,ii / r1 = i-number of current file 2563 00004809 7504 <1> jne short iget_1 2564 <1> ; bne 1f 2565 0000480B 38F2 <1> cmp dl, dh 2566 <1> ; cmp idev,cdev 2567 <1> ; / is device number of i-node = current device 2568 0000480D 7472 <1> je short iget_5 2569 <1> ; beq 2f 2570 <1> iget_1: ; 1: 2571 0000480F 30DB <1> xor bl, bl 2572 00004811 381D[F2640000] <1> cmp [imod], bl ; 0 2573 <1> ; tstb imod / has i-node of current file 2574 <1> ; / been modified i.e., imod set 2575 00004817 7629 <1> jna short iget_2 2576 <1> ; beq 1f 2577 00004819 881D[F2640000] <1> mov [imod], bl ; 0 2578 <1> ; clrb imod / if it has, 2579 <1> ; / we must write the new i-node out on disk 2580 <1> ; 03/02/2022 2581 0000481F 50 <1> push eax ; * 2582 <1> ;push ax 2583 <1> ; mov r1,-(sp) 2584 <1> ;mov dl, [cdev] 2585 00004820 52 <1> push edx ; ** 2586 <1> ;push dx 2587 <1> ; mov cdev,-(sp) 2588 00004821 66A1[E0640000] <1> mov ax, [ii] 2589 <1> ; mov ii,r1 2590 <1> ;mov dh, [idev] 2591 00004827 8835[E4640000] <1> mov [cdev], dh 2592 <1> ; mov idev,cdev 2593 0000482D FEC3 <1> inc bl ; 1 2594 <1> ; 31/07/2013 2595 0000482F 881D[7C650000] <1> mov [rw], bl ; 1 == write 2596 <1> ;;28/07/2013 rw -> u.rw 2597 <1> ;;mov [u.rw], bl ; 1 == write 2598 00004835 E848000000 <1> call icalc 2599 <1> ; jsr r0,icalc; 1 2600 <1> ;pop dx 2601 <1> ; 03/02/2022 2602 0000483A 5A <1> pop edx ; ** 2603 0000483B 8815[E4640000] <1> mov [cdev], dl 2604 <1> ; mov (sp)+,cdev 2605 <1> ; 03/02/2022 2606 00004841 58 <1> pop eax ; * 2607 <1> ;pop ax 2608 <1> ; mov (sp)+,r1 2609 <1> iget_2: ; 1: 2610 00004842 6621C0 <1> and ax, ax 2611 <1> ; tst r1 / is new i-number non zero 2612 00004845 7434 <1> jz short iget_4 ; 2f 2613 <1> ; beq 2f / branch if r1=0 2614 <1> 2615 <1> ;mov dl, [cdev] 2616 00004847 08D2 <1> or dl, dl 2617 <1> ; tst cdev / is the current device number non zero 2618 <1> ; / (i.e., device =/ drum) 2619 00004849 7517 <1> jnz short iget_3 ; 1f 2620 <1> ; bne 1f / branch 1f cdev =/ 0 ;; (cdev != 0) 2621 0000484B 663B05[E8640000] <1> cmp ax, [mnti] 2622 <1> ; cmp r1,mnti / mnti is the i-number of the cross device 2623 <1> ; / file (root directory of mounted device) 2624 00004852 750E <1> jne short iget_3 ; 1f 2625 <1> ; bne 1f 2626 <1> ;mov bl, [mntd] 2627 00004854 FEC2 <1> inc dl ; mov dl, 1 ; 17/07/2013 2628 00004856 8815[E4640000] <1> mov [cdev], dl ; 17/07/2013 - 09/07/2013 2629 <1> ; mov mntd,cdev / make mounted device the current device 2630 0000485C 66A1[EE640000] <1> mov ax, [rootdir] 2631 <1> ; mov rootdir,r1 2632 <1> iget_3: ; 1: 2633 00004862 66A3[E0640000] <1> mov [ii], ax 2634 <1> ; mov r1,ii 2635 00004868 8815[E2640000] <1> mov [idev], dl ; cdev 2636 <1> ; mov cdev,idev 2637 0000486E 30DB <1> xor bl, bl 2638 <1> ; 31/07/2013 2639 00004870 881D[7C650000] <1> mov [rw], bl ; 0 == read 2640 <1> ;;28/07/2013 rw -> u.rw 2641 <1> ;;mov [u.rw], bl ; 0 = read 2642 00004876 E807000000 <1> call icalc 2643 <1> ; jsr r0,icalc; 0 / read in i-node ii 2644 <1> iget_4: ; 2: 2645 0000487B 66A1[E0640000] <1> mov ax, [ii] 2646 <1> ; mov ii,r1 2647 <1> iget_5: 2648 00004881 C3 <1> retn 2649 <1> ; rts r0 2650 <1> 2651 <1> icalc: 2652 <1> ; 04/04/2022 (47->31) 2653 <1> ; (Inode Table/List Address modification) 2654 <1> ; 03/02/2022 2655 <1> ; 02/07/2015 2656 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2657 <1> ; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2658 <1> ; 2659 <1> ; calculate physical block number from i-number then 2660 <1> ; read or write that block 2661 <1> ; 2662 <1> ; 'icalc' is called from 'iget' 2663 <1> ; 2664 <1> ; for original unix v1: 2665 <1> ; / i-node i is located in block (i+31.)/16. and begins 32.* 2666 <1> ; / (i+31.) mod 16. bytes from its start 2667 <1> ; 2668 <1> ; for retro unix 8086 v1: 2669 <1> ; i-node is located in block (i+47)/16 and 2670 <1> ; begins 32*(i+47) mod 16 bytes from its start 2671 <1> ; 2672 <1> ; INPUTS -> 2673 <1> ; r1 - i-number of i-node 2674 <1> ; 2675 <1> ; OUTPUTS -> 2676 <1> ; inode r/w 2677 <1> ; 2678 <1> ; ((AX = R1)) input 2679 <1> ; 2680 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 2681 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 2682 <1> ; 2683 00004882 0FB7D0 <1> movzx edx, ax 2684 <1> ;add dx, 47 2685 <1> ; 04/04/2022 2686 00004885 6683C21F <1> add dx, 31 2687 00004889 89D0 <1> mov eax, edx 2688 <1> ;;add ax, 47 ; add 47 to inode number 2689 <1> ;add ax, 31 2690 <1> ; add $31.,r1 / add 31. to i-number 2691 0000488B 50 <1> push eax 2692 <1> ; mov r1,-(sp) / save i+31. on stack 2693 <1> ; 03/02/2022 2694 0000488C C1E804 <1> shr eax, 4 2695 <1> ;shr ax, 4 2696 <1> ; asr r1 / divide by 16. 2697 <1> ; asr r1 2698 <1> ; asr r1 2699 <1> ; asr r1 / r1 contains block number of block 2700 <1> ; / in which i-node exists 2701 0000488F E82D0B0000 <1> call dskrd 2702 <1> ; jsr r0,dskrd / read in block containing i-node i. 2703 <1> ; 31/07/2013 2704 00004894 803D[7C650000]00 <1> cmp byte [rw], 0 ; Retro Unix 8086 v1 feature ! 2705 <1> ;; 28/07/2013 rw -> u.rw 2706 <1> ;;cmp byte [u.rw], 0 ; Retro Unix 8086 v1 feature ! 2707 <1> ; tst (r0) 2708 0000489B 7605 <1> jna short icalc_1 2709 <1> ; beq 1f / branch to wslot when argument 2710 <1> ; / in icalc call = 1 2711 <1> ; eAX = r1 = block number 2712 0000489D E8830B0000 <1> call wslot 2713 <1> ; jsr r0,wslot / set up data buffer for write 2714 <1> ; / (will be same buffer as dskrd got) 2715 <1> ; eBX = r5 points to first word in data area for this block 2716 <1> icalc_1: ; 1: 2717 000048A2 5A <1> pop edx 2718 000048A3 83E20F <1> and edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16 2719 <1> ; bic $!17,(sp) / zero all but last 4 bits; 2720 <1> ; / gives (i+31.) mod 16 2721 000048A6 C1E205 <1> shl edx, 5 2722 <1> ; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16) 2723 000048A9 89DE <1> mov esi, ebx ; ebx points 1st word of the buffer 2724 000048AB 01D6 <1> add esi, edx ; edx is inode offset in the buffer 2725 <1> ; eSI (r5) points to first word in i-node i. 2726 <1> ; mov (sp)+,mq / calculate offset in data buffer; 2727 <1> ; / 32.*(i+31.)mod16 2728 <1> ; mov $5,lsh / for i-node i. 2729 <1> ; add mq,r5 / r5 points to first word in i-node i. 2730 000048AD BF[F4610000] <1> mov edi, inode 2731 <1> ; mov $inode,r1 / inode is address of first word 2732 <1> ; / of current i-node 2733 <1> ; 03/02/2022 2734 000048B2 29C9 <1> sub ecx, ecx 2735 000048B4 B108 <1> mov cl, 8 2736 <1> ;mov ecx, 8 ; 02/07/2015(32 bit modification) 2737 <1> ; mov $16.,r3 2738 <1> ; 31/07/2013 2739 000048B6 382D[7C650000] <1> cmp [rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 2740 <1> ;;28/07/2013 rw -> u.rw 2741 <1> ;;cmp [u.rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 2742 <1> ; tst (r0)+ / branch to 2f when argument in icalc call = 0 2743 000048BC 7609 <1> jna short icalc_3 2744 <1> ; beq 2f / r0 now contains proper return address 2745 <1> ; / for rts r0 2746 <1> icalc_2: ; 1: 2747 000048BE 87F7 <1> xchg esi, edi 2748 <1> ; overwrite old i-node (in buffer to be written) 2749 000048C0 F3A5 <1> rep movsd 2750 <1> ; mov (r1)+,(r5)+ / over write old i-node 2751 <1> ; dec r3 2752 <1> ; bgt 1b 2753 <1> ;call dskwr 2754 <1> ; jsr r0,dskwr / write inode out on device 2755 <1> ;retn 2756 <1> ; rts r0 2757 <1> ; 03/02/2022 2758 000048C2 E96B0B0000 <1> jmp dskwr 2759 <1> icalc_3: ; 2: 2760 <1> ; copy new i-node into inode area of (core) memory 2761 000048C7 F3A5 <1> rep movsd 2762 <1> ; mov (r5)+,(r1)+ / read new i-node into 2763 <1> ; / "inode" area of core 2764 <1> ; dec r3 2765 <1> ; bgt 2b 2766 000048C9 C3 <1> retn 2767 <1> ; rts r0 2768 <1> 2769 <1> access: 2770 <1> ; 03/02/2022 2771 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2772 <1> ; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1) 2773 <1> ; 2774 <1> ; check whether user is owner of file or user has read or write 2775 <1> ; permission (based on i.flgs). 2776 <1> ; 2777 <1> ; INPUTS -> 2778 <1> ; r1 - i-number of file 2779 <1> ; u.uid 2780 <1> ; arg0 -> (owner flag mask) 2781 <1> ; Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 2782 <1> ; OUTPUTS -> 2783 <1> ; inode (or jump to error) 2784 <1> ; 2785 <1> ; ((AX = R1)) input/output 2786 <1> ; 2787 <1> ; ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP)) 2788 <1> ; 2789 <1> 2790 <1> ;push dx ; save flags (DL) 2791 <1> ; 03/02/2022 2792 000048CA 52 <1> push edx ; save flags (DL) 2793 000048CB E826FFFFFF <1> call iget 2794 <1> ; jsr r0,iget / read in i-node for current directory 2795 <1> ; / (i-number passed in r1) 2796 000048D0 8A0D[F4610000] <1> mov cl, [i.flgs] 2797 <1> ; mov i.flgs,r2 2798 <1> ; 03/02/2022 2799 000048D6 5A <1> pop edx ; restore flags (DL) 2800 <1> ;pop dx ; restore flags (DL) 2801 000048D7 8A35[46650000] <1> mov dh, [u.uid] 2802 000048DD 3A35[F7610000] <1> cmp dh, [i.uid] 2803 <1> ; cmpb i.uid,u.uid / is user same as owner of file 2804 000048E3 7503 <1> jne short access_1 2805 <1> ; bne 1f / no, then branch 2806 000048E5 C0E902 <1> shr cl, 2 2807 <1> ; asrb r2 / shift owner read write bits into non owner 2808 <1> ; / read/write bits 2809 <1> ; asrb r2 2810 <1> access_1: ; 1: 2811 000048E8 20D1 <1> and cl, dl 2812 <1> ; bit r2,(r0)+ / test read-write flags against argument 2813 <1> ; / in access call 2814 000048EA 7513 <1> jnz short access_2 2815 <1> ; bne 1f 2816 000048EC 08F6 <1> or dh, dh ; super user (root) ? 2817 <1> ; tstb u.uid 2818 000048EE 740F <1> jz short access_2 ; yes, super user 2819 <1> ;jnz error 2820 <1> ; beq 1f 2821 <1> ; jmp error 2822 000048F0 C705[4F650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS 2822 000048F8 0000 <1> 2823 <1> ; 'permission denied !' error 2824 000048FA E9E2E7FFFF <1> jmp error 2825 <1> 2826 <1> access_2: ; 1: 2827 <1> ; DL = flags 2828 000048FF C3 <1> retn 2829 <1> ; rts r0 2830 <1> 2831 <1> setimod: 2832 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2833 <1> ; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2834 <1> ; 2835 <1> ; 'setimod' sets byte at location 'imod' to 1; thus indicating that 2836 <1> ; the inode has been modified. Also puts the time of modification 2837 <1> ; into the inode. 2838 <1> ; 2839 <1> ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) 2840 <1> ; ((Modified registers: eDX, eCX, eBX)) 2841 <1> ; 2842 <1> 2843 <1> ; push edx 2844 00004900 50 <1> push eax 2845 <1> 2846 00004901 C605[F2640000]01 <1> mov byte [imod], 1 2847 <1> ; movb $1,imod / set current i-node modified bytes 2848 <1> ; Erdogan Tan 14-7-2012 2849 00004908 E825E3FFFF <1> call epoch 2850 <1> ; mov s.time,i.mtim 2851 <1> ; / put present time into file modified time 2852 <1> ; mov s.time+2,i.mtim+2 2853 <1> 2854 0000490D A3[0E620000] <1> mov [i.mtim], eax 2855 <1> 2856 <1> ; Retro UNIX 386 v1 modification ! (cmp) 2857 <1> ; Retro UNIX 8086 v1 modification ! (test) 2858 00004912 833D[0A620000]00 <1> cmp dword [i.ctim], 0 2859 00004919 7505 <1> jnz short setimod_ok 2860 <1> 2861 0000491B A3[0A620000] <1> mov [i.ctim], eax 2862 <1> 2863 <1> setimod_ok: ; 31/07/2013 2864 00004920 58 <1> pop eax 2865 <1> ;pop edx 2866 <1> 2867 00004921 C3 <1> retn 2868 <1> ; rts r0 2869 <1> 2870 <1> itrunc: 2871 <1> ; 03/02/2022 2872 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2873 <1> ; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2874 <1> ; 2875 <1> ; 'itrunc' truncates a file whose i-number is given in r1 2876 <1> ; to zero length. 2877 <1> ; 2878 <1> ; INPUTS -> 2879 <1> ; r1 - i-number of i-node 2880 <1> ; i.dskp - pointer to contents or indirect block in an i-node 2881 <1> ; i.flgs - large file flag 2882 <1> ; i.size - size of file 2883 <1> ; 2884 <1> ; OUTPUTS -> 2885 <1> ; i.flgs - large file flag is cleared 2886 <1> ; i.size - set to 0 2887 <1> ; i.dskp .. i.dskp+16 - entire list is cleared 2888 <1> ; setimod - set to indicate i-node has been modified 2889 <1> ; r1 - i-number of i-node 2890 <1> ; 2891 <1> ; ((AX = R1)) input/output 2892 <1> ; 2893 <1> ; (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM) 2894 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2895 <1> 2896 00004922 E8CFFEFFFF <1> call iget 2897 <1> ; jsr r0,iget 2898 00004927 BE[FA610000] <1> mov esi, i.dskp 2899 <1> ; mov $i.dskp,r2 / address of block pointers in r2 2900 0000492C 31C0 <1> xor eax, eax 2901 <1> itrunc_1: ; 1: 2902 0000492E 66AD <1> lodsw 2903 <1> ; mov (r2)+,r1 / move physical block number into r1 2904 <1> ; 03/02/2022 2905 00004930 09C0 <1> or eax, eax 2906 <1> ;or ax, ax 2907 00004932 7433 <1> jz short itrunc_5 2908 <1> ; beq 5f 2909 00004934 56 <1> push esi 2910 <1> ; mov r2,-(sp) 2911 <1> ; 03/02/2022 2912 00004935 F605[F5610000]10 <1> test byte [i.flgs+1], 10h 2913 <1> ;test word [i.flgs], 1000h 2914 <1> ; bit $10000,i.flgs / test large file bit? 2915 0000493C 7423 <1> jz short itrunc_4 2916 <1> ; beq 4f / if clear, branch 2917 0000493E 50 <1> push eax 2918 <1> ; mov r1,-(sp) / save block number of indirect block 2919 0000493F E87D0A0000 <1> call dskrd 2920 <1> ; jsr r0,dskrd / read in block, 1st data word 2921 <1> ; / pointed to by r5 2922 <1> ; eBX = r5 = Buffer data address (the 1st word) 2923 <1> ; 03/02/2022 2924 00004944 31C9 <1> xor ecx, ecx 2925 00004946 FEC5 <1> inc ch ; mov ch, 1 2926 <1> ; ecx = 256 2927 <1> ;mov ecx, 256 2928 <1> ; mov $256.,r3 / move word count into r3 2929 00004948 89DE <1> mov esi, ebx 2930 <1> itrunc_2: ; 2: 2931 0000494A 66AD <1> lodsw 2932 <1> ; mov (r5)+,r1 / put 1st data word in r1; 2933 <1> ; / physical block number 2934 <1> ; 03/02/2022 2935 0000494C 21C0 <1> and eax, eax 2936 <1> ;and ax, ax 2937 0000494E 7407 <1> jz short itrunc_3 2938 <1> ; beq 3f / branch if zero 2939 <1> ; 03/02/2022 2940 00004950 51 <1> push ecx 2941 <1> ;push cx 2942 <1> ; mov r3,-(sp) / save r3, r5 on stack 2943 <1> ;push esi 2944 <1> ; mov r5,-(sp) 2945 00004951 E855FEFFFF <1> call free 2946 <1> ; jsr r0,free / free block in free storage map 2947 <1> ;pop esi 2948 <1> ; mov(sp)+,r5 2949 <1> ;pop cx 2950 00004956 59 <1> pop ecx 2951 <1> ; mov (sp)+,r3 2952 <1> itrunc_3: ; 3: 2953 00004957 E2F1 <1> loop itrunc_2 2954 <1> ; dec r3 / decrement word count 2955 <1> ; bgt 2b / branch if positive 2956 00004959 58 <1> pop eax 2957 <1> ; mov (sp)+,r1 / put physical block number of 2958 <1> ; / indirect block 2959 <1> ; 01/08/2013 2960 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 2961 <1> ; 03/02/2022 2962 0000495A 8025[F5610000]EF <1> and byte [i.flgs+1], 0EFh 2963 <1> itrunc_4: ; 4: 2964 00004961 E845FEFFFF <1> call free 2965 <1> ; jsr r0,free / free indirect block 2966 00004966 5E <1> pop esi 2967 <1> ; mov (sp)+,r2 2968 <1> itrunc_5: ; 5: 2969 00004967 81FE[0A620000] <1> cmp esi, i.dskp+16 2970 <1> ; cmp r2,$i.dskp+16. 2971 0000496D 72BF <1> jb short itrunc_1 2972 <1> ; bne 1b / branch until all i.dskp entries check 2973 <1> ; 03/02/2022 2974 <1> ;and byte [i.flgs+1], 0EFh 2975 <1> ; 01/08/2013 2976 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 2977 <1> ; bic $10000,i.flgs / clear large file bit 2978 0000496F BF[FA610000] <1> mov edi, i.dskp 2979 <1> ;mov cx, 8 2980 <1> ;xor ax, ax 2981 <1> ; 03/02/2022 2982 00004974 29C9 <1> sub ecx, ecx 2983 00004976 B108 <1> mov cl, 8 2984 00004978 29C0 <1> sub eax, eax 2985 0000497A 66A3[F8610000] <1> mov [i.size], ax ; 0 2986 <1> ; clr i.size / zero file size 2987 00004980 F366AB <1> rep stosw 2988 <1> ; jsr r0,copyz; i.dskp; i.dskp+16. 2989 <1> ; / zero block pointers 2990 00004983 E878FFFFFF <1> call setimod 2991 <1> ; jsr r0,setimod / set i-node modified flag 2992 00004988 66A1[E0640000] <1> mov ax, [ii] 2993 <1> ; mov ii,r1 2994 0000498E C3 <1> retn 2995 <1> ; rts r0 2996 <1> 2997 <1> imap: 2998 <1> ; 12/02/2022 2999 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3000 <1> ; 26/04/2013 (Retro UNIX 8086 v1) 3001 <1> ; 3002 <1> ; 'imap' finds the byte in core (superblock) containing 3003 <1> ; allocation bit for an i-node whose number in r1. 3004 <1> ; 3005 <1> ; INPUTS -> 3006 <1> ; r1 - contains an i-number 3007 <1> ; fsp - start of table containing open files 3008 <1> ; 3009 <1> ; OUTPUTS -> 3010 <1> ; r2 - byte address of byte with the allocation bit 3011 <1> ; mq - a mask to locate the bit position. 3012 <1> ; (a 1 is in calculated bit posisiton) 3013 <1> ; 3014 <1> ; ((AX = R1)) input/output 3015 <1> ; ((DL/DX = MQ)) output 3016 <1> ; ((BX = R2)) output 3017 <1> ; 3018 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 3019 <1> ; ((Modified registers: eDX, eCX, eBX, eSI)) 3020 <1> ; 3021 <1> ; / get the byte that has the allocation bit for 3022 <1> ; / the i-number contained in r1 3023 <1> ;mov dx, 1 3024 0000498F B201 <1> mov dl, 1 3025 <1> ; mov $1,mq / put 1 in the mq 3026 00004991 0FB7D8 <1> movzx ebx, ax 3027 <1> ; mov r1,r2 / r2 now has i-number whose byte 3028 <1> ; / in the map we must find 3029 00004994 6683EB29 <1> sub bx, 41 3030 <1> ; sub $41.,r2 / r2 has i-41 3031 00004998 88D9 <1> mov cl, bl 3032 <1> ; mov r2,r3 / r3 has i-41 3033 0000499A 80E107 <1> and cl, 7 3034 <1> ; bic $!7,r3 / r3 has (i-41) mod 8 to get 3035 <1> ; / the bit position 3036 0000499D 7402 <1> jz short imap1 3037 <1> ;shl dx, cl 3038 0000499F D2E2 <1> shl dl, cl 3039 <1> ; mov r3,lsh / move the 1 over (i-41) mod 8 positions 3040 <1> imap1: ; / to the left to mask the correct bit 3041 <1> ; 03/02/2022 3042 000049A1 C1EB03 <1> shr ebx, 3 3043 <1> ;shr bx, 3 3044 <1> ; asr r2 3045 <1> ; asr r2 3046 <1> ; asr r2 / r2 has (i-41) base 8 of the byte number 3047 <1> ; / from the start of the map 3048 <1> ; mov r2,-(sp) / put (i-41) base 8 on the stack 3049 000049A4 BE[C8750000] <1> mov esi, systm 3050 <1> ; mov $systm,r2 / r2 points to the in-core image of 3051 <1> ; / the super block for drum 3052 <1> ;cmp word [cdev], 0 3053 000049A9 803D[E4640000]00 <1> cmp byte [cdev], 0 3054 <1> ; tst cdev / is the device the disk 3055 000049B0 7606 <1> jna short imap2 3056 <1> ; beq 1f / yes 3057 000049B2 81C608020000 <1> add esi, mount - systm 3058 <1> ; add $mount-systm,r2 / for mounted device, 3059 <1> ; / r2 points to 1st word of its super block 3060 <1> imap2: ; 1: 3061 000049B8 66031E <1> add bx, [esi] ;; add free map size to si 3062 <1> ; add (r2)+,(sp) / get byte address of allocation bit 3063 000049BB 6683C304 <1> add bx, 4 3064 000049BF 01F3 <1> add ebx, esi 3065 <1> ; add (sp)+,r2 / ? 3066 <1> ;add ebx, 4 ;; inode map offset in superblock 3067 <1> ;; (2 + free map size + 2) 3068 <1> ; add $2,r2 / ? 3069 <1> 3070 <1> ; 12/02/2022 3071 000049C1 81C68B010000 <1> add esi, eofitab-1 ; last byte of the inode table in sb 3072 000049C7 39DE <1> cmp esi, ebx ; cf will be 1 3073 <1> ; if inode num overs inode count 3074 <1> 3075 <1> ; DL/DX (MQ) has a 1 in the calculated bit position 3076 <1> ; BX (R2) has byte address of the byte with allocation bit 3077 <1> 3078 <1> ; 11/02/2022 3079 <1> ; if ebx > last byte of the inode table --> cf = 1 3080 <1> ; (number of requested inode > inode count) 3081 <1> 3082 000049C9 C3 <1> retn 3083 <1> ; rts r0 2057 %include 'u6.s' ; 31/05/2015 2058 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS6.INC 2059 <1> ; Last Modification: 19/07/2022 2060 <1> ; ---------------------------------------------------------------------------- 2061 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2062 <1> ; (v0.1 - Beginning: 11/07/2012) 2063 <1> ; 2064 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2065 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2066 <1> ; 2067 <1> ; 2068 <1> ; 2069 <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s 2070 <1> ; 2071 <1> ; **************************************************************************** 2072 <1> ; 18/11/2015 2073 <1> 2074 <1> readi: 2075 <1> ; 03/02/2022 2076 <1> ; 20/05/2015 2077 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2078 <1> ; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2079 <1> ; 2080 <1> ; Reads from an inode whose number in R1 2081 <1> ; 2082 <1> ; INPUTS -> 2083 <1> ; r1 - inode number 2084 <1> ; u.count - byte count user desires 2085 <1> ; u.base - points to user buffer 2086 <1> ; u.fofp - points to word with current file offset 2087 <1> ; OUTPUTS -> 2088 <1> ; u.count - cleared 2089 <1> ; u.nread - accumulates total bytes passed back 2090 <1> ; 2091 <1> ; ((AX = R1)) input/output 2092 <1> ; (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM) 2093 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -14/07/2022- 2094 <1> 2095 000049CA 31D2 <1> xor edx, edx ; 0 2096 000049CC 8915[28650000] <1> mov [u.nread], edx ; 0 2097 <1> ; clr u.nread / accumulates number of bytes transmitted 2098 000049D2 668915[5F650000] <1> mov [u.pcount], dx ; 19/05/2015 2099 000049D9 3915[24650000] <1> cmp [u.count], edx ; 0 2100 <1> ; tst u.count / is number of bytes to be read greater than 0 2101 000049DF 7701 <1> ja short readi_1 ; 1f 2102 <1> ; bgt 1f / yes, branch 2103 000049E1 C3 <1> retn 2104 <1> ; rts r0 / no, nothing to read; return to caller 2105 <1> readi_1: ; 1: 2106 <1> ; mov r1,-(sp) / save i-number on stack 2107 000049E2 6683F828 <1> cmp ax, 40 2108 <1> ; cmp r1,$40. / want to read a special file 2109 <1> ; / (i-nodes 1,...,40 are for special files) 2110 <1> ;ja dskr 2111 <1> ; ble 1f / yes, branch 2112 <1> ; jmp dskr / no, jmp to dskr; 2113 <1> ; / read file with i-node number (r1) 2114 <1> ; / starting at byte ((u.fofp)), read in u.count bytes 2115 <1> ; 03/02/2022 2116 000049E6 7605 <1> jna short readi_3 2117 000049E8 E9CF000000 <1> jmp dskr 2118 <1> readi_3: 2119 <1> ; (20/05/2015) 2120 000049ED 50 <1> push eax ; because subroutines will jump to 'ret_' 2121 <1> ; 1: 2122 000049EE 0FB6D8 <1> movzx ebx, al 2123 <1> ; 03/02/2022 2124 000049F1 C1E302 <1> shl ebx, 2 2125 <1> ;shl bx, 2 2126 <1> ; asl r1 / multiply inode number by 2 2127 000049F4 81C3[F8490000] <1> add ebx, readi_2 - 4 2128 000049FA FF23 <1> jmp dword [ebx] 2129 <1> ; jmp *1f-2(r1) 2130 <1> readi_2: ; 1: 2131 000049FC [484A0000] <1> dd rtty ; tty, AX = 1 (runix) 2132 <1> ;rtty / tty; r1=2 2133 <1> ;rppt / ppt; r1=4 2134 00004A00 [984A0000] <1> dd rmem ; mem, AX = 2 (runix) 2135 <1> ;rmem / mem; r1=6 2136 <1> ;rrf0 / rf0 2137 <1> ;rrk0 / rk0 2138 <1> ;rtap / tap0 2139 <1> ;rtap / tap1 2140 <1> ;rtap / tap2 2141 <1> ;rtap / tap3 2142 <1> ;rtap / tap4 2143 <1> ;rtap / tap5 2144 <1> ;rtap / tap6 2145 <1> ;rtap / tap7 2146 00004A04 [82520000] <1> dd rfd ; fd0, AX = 3 (runix only) 2147 00004A08 [82520000] <1> dd rfd ; fd1, AX = 4 (runix only) 2148 00004A0C [82520000] <1> dd rhd ; hd0, AX = 5 (runix only) 2149 00004A10 [82520000] <1> dd rhd ; hd1, AX = 6 (runix only) 2150 00004A14 [82520000] <1> dd rhd ; hd2, AX = 7 (runix only) 2151 00004A18 [82520000] <1> dd rhd ; hd3, AX = 8 (runix only) 2152 00004A1C [AD4A0000] <1> dd rlpr ; lpr, AX = 9 (invalid, write only device !?) 2153 00004A20 [944A0000] <1> dd rcvt ; tty0, AX = 10 (runix) 2154 <1> ;rcvt / tty0 2155 00004A24 [944A0000] <1> dd rcvt ; tty1, AX = 11 (runix) 2156 <1> ;rcvt / tty1 2157 00004A28 [944A0000] <1> dd rcvt ; tty2, AX = 12 (runix) 2158 <1> ;rcvt / tty2 2159 00004A2C [944A0000] <1> dd rcvt ; tty3, AX = 13 (runix) 2160 <1> ;rcvt / tty3 2161 00004A30 [944A0000] <1> dd rcvt ; tty4, AX = 14 (runix) 2162 <1> ;rcvt / tty4 2163 00004A34 [944A0000] <1> dd rcvt ; tty5, AX = 15 (runix) 2164 <1> ;rcvt / tty5 2165 00004A38 [944A0000] <1> dd rcvt ; tty6, AX = 16 (runix) 2166 <1> ;rcvt / tty6 2167 00004A3C [944A0000] <1> dd rcvt ; tty7, AX = 17 (runix) 2168 <1> ;rcvt / tty7 2169 00004A40 [944A0000] <1> dd rcvt ; COM1, AX = 18 (runix only) 2170 <1> ;rcrd / crd 2171 00004A44 [944A0000] <1> dd rcvt ; COM2, AX = 19 (runix only) 2172 <1> 2173 <1> rtty: ; / read from console tty 2174 <1> ; 03/02/2022 2175 <1> ; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1) 2176 <1> ; (Only 1 byte is read, by ignoring byte count!) 2177 <1> ; WHAT FOR: Every character from Keyboard input 2178 <1> ; must be written immediate on video page (screen) 2179 <1> ; when it is required. 2180 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2181 <1> ; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1) 2182 <1> ; 2183 <1> ; Console tty buffer is PC keyboard buffer 2184 <1> ; and keyboard-keystroke handling is different than original 2185 <1> ; unix (PDP-11) here. TTY/Keyboard procedures here are changed 2186 <1> ; according to IBM PC compatible ROM BIOS keyboard functions. 2187 <1> ; 2188 <1> ; 06/12/2013 2189 00004A48 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 2190 00004A4F 8A83[53620000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2191 <1> rttys: 2192 <1> ; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of 2193 <1> ; / of the control and status block 2194 <1> ; tst 2(r5) / for the console tty; this word points to the console 2195 <1> ; / tty buffer 2196 <1> ; 28/07/2013 2197 00004A55 A2[4E650000] <1> mov [u.ttyn], al 2198 <1> ; 13/01/2014 2199 00004A5A FEC0 <1> inc al 2200 00004A5C A2[30650000] <1> mov [u.ttyp], al ; tty number + 1 2201 <1> rtty_nc: ; 01/02/2014 2202 <1> ; 29/09/2013 2203 <1> ;mov ecx, 10 2204 <1> ; 03/02/2022 2205 00004A61 29C9 <1> sub ecx, ecx 2206 00004A63 B10A <1> mov cl, 10 2207 <1> rtty_1: ; 01/02/2014 2208 <1> ;push cx ; 29/09/2013 2209 <1> ; 03/02/2022 2210 00004A65 51 <1> push ecx 2211 <1> ; byte [u.ttyn] = tty number (0 to 9) 2212 00004A66 B001 <1> mov al, 1 2213 00004A68 E8200B0000 <1> call getc 2214 <1> ; 03/02/2022 2215 00004A6D 59 <1> pop ecx 2216 <1> ;pop cx ; 29/09/2013 2217 00004A6E 7516 <1> jnz short rtty_2 2218 <1> ; bne 1f / 2nd word of console tty buffer contains number 2219 <1> ; / of chars. Is this number non-zero? 2220 00004A70 E20D <1> loop rtty_idle ; 01/02/2014 2221 <1> ; 05/10/2013 2222 00004A72 8A25[4E650000] <1> mov ah, [u.ttyn] 2223 <1> ; 29/09/2013 2224 00004A78 E898FBFFFF <1> call sleep 2225 <1> ; jsr r0,canon; ttych / if 0, call 'canon' to get a line 2226 <1> ; / (120 chars.) 2227 <1> ;byte [u.ttyn] = tty number (0 to 9) 2228 00004A7D EBE2 <1> jmp short rtty_nc ; 01/02/2014 2229 <1> 2230 <1> rtty_idle: 2231 <1> ; 29/07/2013 2232 00004A7F E804FBFFFF <1> call idle 2233 00004A84 EBDF <1> jmp short rtty_1 ; 01/02/2014 2234 <1> ;1: 2235 <1> ; tst 2(r5) / is the number of characters zero 2236 <1> ; beq ret1 / yes, return to caller via 'ret1' 2237 <1> ; movb *4(r5),r1 / no, put character in r1 2238 <1> ; inc 4(r5) / 3rd word of console tty buffer points to byte which 2239 <1> ; / contains the next char. 2240 <1> ; dec 2(r5) / decrement the character count 2241 <1> rtty_2: 2242 00004A86 30C0 <1> xor al, al 2243 00004A88 E8000B0000 <1> call getc 2244 00004A8D E896000000 <1> call passc 2245 <1> ; jsr r0,passc / move the character to core (user) 2246 <1> ;; 17/10/2015 - 16/07/2015 2247 <1> ; 19/06/2014 2248 <1> ;;jnz short rtty_nc 2249 00004A92 58 <1> pop eax ; (20/05/2015) 2250 00004A93 C3 <1> retn 2251 <1> ;ret1: 2252 <1> ; jmp ret / return to caller via 'ret' 2253 <1> 2254 <1> rcvt: ; < receive/read character from tty > 2255 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2256 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2257 <1> ; 2258 <1> ; Retro UNIX 8086 v1 modification ! 2259 <1> ; 2260 <1> ; In original UNIX v1, 'rcvt' routine 2261 <1> ; (exactly different than this one) 2262 <1> ; was in 'u9.s' file. 2263 <1> ; 2264 00004A94 2C0A <1> sub al, 10 2265 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 2266 <1> ; 16/07/2013 2267 <1> ; 21/05/2013 2268 00004A96 EBBD <1> jmp short rttys 2269 <1> 2270 <1> ;rppt: / read paper tape 2271 <1> ; jsr r0,pptic / gets next character in clist for ppt input and 2272 <1> ; / places 2273 <1> ; br ret / it in r1; if there 1s no problem with reader, it 2274 <1> ; / also enables read bit in prs 2275 <1> ; jsr r0,passc / place character in users buffer area 2276 <1> ; br rppt 2277 <1> 2278 <1> rmem: ; / transfer characters from memory to a user area of core 2279 <1> ; 17/10/2015 2280 <1> ; 11/06/2015 2281 <1> ; 24/05/2015 2282 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2283 <1> ; 2284 00004A98 8B35[10650000] <1> mov esi, [u.fofp] 2285 <1> rmem_1: 2286 00004A9E 8B1E <1> mov ebx, [esi] 2287 <1> ; mov *u.fofp,r1 / save file offset which points to the char 2288 <1> ; / to be transferred to user 2289 00004AA0 FF06 <1> inc dword [esi] ; 17/10/2015 2290 <1> ; inc *u.fofp / increment file offset to point to 'next' 2291 <1> ; / char in memory file 2292 00004AA2 8A03 <1> mov al, [ebx] 2293 <1> ; movb (r1),r1 / get character from memory file, 2294 <1> ; / put it in r1 2295 00004AA4 E87F000000 <1> call passc ; jsr r0,passc / move this character to 2296 <1> ; / the next byte of the users core area 2297 <1> ; br rmem / continue 2298 00004AA9 75F3 <1> jnz short rmem_1 2299 <1> ret_: 2300 00004AAB 58 <1> pop eax ; 09/06/2015 2301 00004AAC C3 <1> retn 2302 <1> 2303 <1> rlpr: 2304 <1> ;1: 2305 <1> ;rcrd: 2306 00004AAD C705[4F650000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 2306 00004AB5 0000 <1> 2307 00004AB7 E925E6FFFF <1> jmp error 2308 <1> ;jmp error / see 'error' routine 2309 <1> 2310 <1> dskr: 2311 <1> ; 19/07/2022 2312 <1> ; 12/10/2015 2313 <1> ; 21/08/2015 2314 <1> ; 25/07/2015 2315 <1> ; 10/07/2015 2316 <1> ; 16/06/2015 2317 <1> ; 31/05/2015 2318 <1> ; 24/05/2015 (Retro UNIX 386 v1 - Beginning) 2319 <1> ; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2320 <1> dskr_0: 2321 00004ABC 50 <1> push eax 2322 <1> ; mov (sp),r1 / i-number in r1 2323 <1> ; AX = i-number 2324 00004ABD E834FDFFFF <1> call iget 2325 <1> ; jsr r0,iget / get i-node (r1) into i-node section of core 2326 00004AC2 0FB715[F8610000] <1> movzx edx, word [i.size] ; 16/06/2015 2327 <1> ; mov i.size,r2 / file size in bytes in r2 2328 00004AC9 8B1D[10650000] <1> mov ebx, [u.fofp] 2329 00004ACF 2B13 <1> sub edx, [ebx] 2330 <1> ; sub *u.fofp,r2 / subtract file offset 2331 <1> ; 12/10/2015 2332 <1> ; jna short ret_ 2333 <1> ; blos ret 2334 00004AD1 7709 <1> ja short dskr_1 2335 <1> ; 2336 <1> dskr_retn: ; 12/10/2015 2337 00004AD3 58 <1> pop eax 2338 00004AD4 C605[61650000]00 <1> mov byte [u.kcall], 0 2339 00004ADB C3 <1> retn 2340 <1> dskr_1: 2341 00004ADC 3B15[24650000] <1> cmp edx, [u.count] 2342 <1> ; cmp r2,u.count / are enough bytes left in file 2343 <1> ; / to carry out read 2344 00004AE2 7306 <1> jnb short dskr_2 2345 <1> ; bhis 1f 2346 00004AE4 8915[24650000] <1> mov [u.count], edx 2347 <1> ; mov r2,u.count / no, just read to end of file 2348 <1> dskr_2: ; 1: 2349 <1> ; AX = i-number 2350 00004AEA E89EFBFFFF <1> call mget 2351 <1> ; jsr r0,mget / returns physical block number of block 2352 <1> ; / in file where offset points 2353 <1> ; EAX = physical block number 2354 00004AEF E8CD080000 <1> call dskrd 2355 <1> ; jsr r0,dskrd / read in block, r5 points to 2356 <1> ; / 1st word of data in buffer 2357 <1> ; 09/06/2015 2358 00004AF4 803D[61650000]00 <1> cmp byte [u.kcall], 0 ; the caller is 'namei' sign (=1) 2359 00004AFB 770F <1> ja short dskr_4 ; zf=0 -> the caller is 'namei' 2360 00004AFD 66833D[5F650000]00 <1> cmp word [u.pcount], 0 2361 00004B05 7705 <1> ja short dskr_4 2362 <1> dskr_3: 2363 <1> ; [u.base] = virtual address to transfer (as destination address) 2364 00004B07 E857000000 <1> call trans_addr_w ; translate virtual address to physical (w) 2365 <1> dskr_4: 2366 <1> ; EBX (r5) = system (I/O) buffer address -physical- 2367 00004B0C E83D030000 <1> call sioreg 2368 <1> ; jsr r0,sioreg 2369 <1> 2370 <1> ; 19/07/2022 2371 <1> ;xchg esi, edi 2372 <1> 2373 <1> ; 19/07/2022 2374 <1> ; EDX = user data offset (previous value of [u.pbase]) 2375 <1> ; ESI = pointer to file offset 2376 <1> ; EDI = system (I/O) buffer offset 2377 <1> ; ECX = byte count 2378 <1> ; EBX = system buffer (data) address 2379 <1> ; EAX = remain bytes after byte count within page frame 2380 <1> 2381 00004B11 010E <1> add [esi], ecx 2382 <1> ; new file offset (old offset + byte count) 2383 <1> ; 2384 00004B13 89FE <1> mov esi, edi ; sector (I/O) buffer offset 2385 00004B15 89D7 <1> mov edi, edx 2386 <1> 2387 <1> ; EDI = file (user data) offset 2388 <1> ; ESI = sector (I/O) buffer offset 2389 <1> ; ECX = byte count 2390 00004B17 F3A4 <1> rep movsb 2391 <1> ; movb (r2)+,(r1)+ / move data from buffer into working core 2392 <1> ; / starting at u.base 2393 <1> ; dec r3 2394 <1> ; bne 2b / branch until proper number of bytes are transferred 2395 <1> ; 25/07/2015 2396 <1> ; eax = remain bytes in buffer 2397 <1> ; (check if remain bytes in the buffer > [u.pcount]) 2398 00004B19 09C0 <1> or eax, eax 2399 00004B1B 75EA <1> jnz short dskr_3 ; (page end before system buffer end!) 2400 <1> ; 03/08/2013 2401 <1> ;pop eax 2402 00004B1D 390D[24650000] <1> cmp [u.count], ecx ; 0 2403 <1> ; tst u.count / all bytes read off disk 2404 <1> ; bne dskr 2405 <1> ; br ret 2406 <1> ;ja short dskr_0 2407 <1> ;mov [u.kcall], cl ; 0 ; 09/06/2015 2408 <1> ;retn 2409 <1> ; 12/10/2015 2410 00004B23 76AE <1> jna short dskr_retn 2411 00004B25 58 <1> pop eax ; (i-node number) 2412 00004B26 EB94 <1> jmp short dskr_0 2413 <1> 2414 <1> passc: 2415 <1> ; 18/10/2015 2416 <1> ; 10/07/2015 2417 <1> ; 01/07/2015 2418 <1> ; 08/06/2015 2419 <1> ; 04/06/2015 2420 <1> ; 20/05/2015 2421 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2422 <1> ; 2423 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 2424 <1> ; to physical address 2425 00004B28 66833D[5F650000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 2426 <1> ; 1-4095 --> use previous physical base address 2427 <1> ; in [u.pbase] 2428 00004B30 7705 <1> ja short passc_3 2429 <1> ; 08/06/2015 - 10/07/2015 2430 00004B32 E82C000000 <1> call trans_addr_w 2431 <1> passc_3: 2432 <1> ; 19/05/2015 2433 00004B37 66FF0D[5F650000] <1> dec word [u.pcount] 2434 <1> ; 2435 00004B3E 8B1D[5B650000] <1> mov ebx, [u.pbase] 2436 00004B44 8803 <1> mov [ebx], al 2437 <1> ; movb r1,*u.base / move a character to the next byte of the 2438 <1> ; / users buffer 2439 00004B46 FF05[20650000] <1> inc dword [u.base] 2440 <1> ; inc u.base / increment the pointer to point to 2441 <1> ; / the next byte in users buffer 2442 00004B4C FF05[5B650000] <1> inc dword [u.pbase] ; 04/06/2015 2443 00004B52 FF05[28650000] <1> inc dword [u.nread] 2444 <1> ; inc u.nread / increment the number of bytes read 2445 00004B58 FF0D[24650000] <1> dec dword [u.count] 2446 <1> ; dec u.count / decrement the number of bytes to be read 2447 <1> ; bne 1f / any more bytes to read?; yes, branch 2448 00004B5E C3 <1> retn 2449 <1> ; mov (sp)+,r0 / no, do a non-local return to the caller of 2450 <1> ; / 'readi' by: 2451 <1> ;/ (1) pop the return address off the stack into r0 2452 <1> ; mov (sp)+,r1 / (2) pop the i-number off the stack into r1 2453 <1> ;1: 2454 <1> ; clr *$ps / clear processor status 2455 <1> ; rts r0 / return to address currently on top of stack 2456 <1> 2457 <1> trans_addr_r: 2458 <1> ; Translate virtual address to physical address 2459 <1> ; for reading from user's memory space 2460 <1> ; (Retro UNIX 386 v1 feature only !) 2461 <1> ; 18/10/2015 2462 <1> ; 10/07/2015 2463 <1> ; 09/06/2015 2464 <1> ; 08/06/2015 2465 <1> ; 04/06/2015 2466 <1> ; 2467 <1> ; 18/10/2015 2468 00004B5F 31D2 <1> xor edx, edx ; 0 (read access sign) 2469 00004B61 EB04 <1> jmp short trans_addr_rw 2470 <1> 2471 <1> ;push eax 2472 <1> ;push ebx 2473 <1> ;mov ebx, [u.base] 2474 <1> ;call get_physical_addr ; get physical address 2475 <1> ;;jnc short cpass_0 2476 <1> ;jnc short passc_1 2477 <1> ;mov [u.error], eax 2478 <1> ;;pop ebx 2479 <1> ;;pop eax 2480 <1> ;jmp error 2481 <1> ;cpass_0: 2482 <1> ; 18/10/2015 2483 <1> ; 20/05/2015 2484 <1> ;mov [u.pbase], eax ; physical address 2485 <1> ;mov [u.pcount], cx ; remain byte count in page (1-4096) 2486 <1> ;pop ebx 2487 <1> ;pop eax 2488 <1> ;retn ; 08/06/2015 2489 <1> 2490 <1> ; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 2491 <1> trans_addr_w: 2492 <1> ; Translate virtual address to physical address 2493 <1> ; for writing to user's memory space 2494 <1> ; (Retro UNIX 386 v1 feature only !) 2495 <1> ; 18/10/2015 2496 <1> ; 29/07/2015 2497 <1> ; 10/07/2015 2498 <1> ; 09/06/2015 2499 <1> ; 08/06/2015 2500 <1> ; 04/06/2015 (passc) 2501 <1> ; 2502 <1> ; 18/10/2015 2503 00004B63 29D2 <1> sub edx, edx 2504 00004B65 FEC2 <1> inc dl ; 1 (write access sign) 2505 <1> trans_addr_rw: 2506 00004B67 50 <1> push eax 2507 00004B68 53 <1> push ebx 2508 <1> ; 18/10/2015 2509 00004B69 52 <1> push edx ; r/w sign (in DL) 2510 <1> ; 2511 00004B6A 8B1D[20650000] <1> mov ebx, [u.base] 2512 00004B70 E854DCFFFF <1> call get_physical_addr ; get physical address 2513 00004B75 730A <1> jnc short passc_0 2514 00004B77 A3[4F650000] <1> mov [u.error], eax 2515 <1> ;pop edx 2516 <1> ;pop ebx 2517 <1> ;pop eax 2518 00004B7C E960E5FFFF <1> jmp error 2519 <1> passc_0: 2520 00004B81 F6C202 <1> test dl, PTE_A_WRITE ; writable page ; 18/10/2015 2521 00004B84 5A <1> pop edx ; 18/10/2015 2522 00004B85 7517 <1> jnz short passc_1 2523 <1> ; 18/10/2015 2524 00004B87 20D2 <1> and dl, dl 2525 00004B89 7413 <1> jz short passc_1 2526 <1> ; 20/05/2015 2527 <1> ; read only (duplicated) page -must be copied to a new page- 2528 <1> ; EBX = linear address 2529 00004B8B 51 <1> push ecx 2530 00004B8C 53 <1> push ebx ; * ; 03/02/2022 (BugFix) 2531 00004B8D E8A8DBFFFF <1> call copy_page 2532 00004B92 5B <1> pop ebx ; * ; 03/02/2022 (BugFix) 2533 00004B93 59 <1> pop ecx 2534 00004B94 7217 <1> jc short passc_2 2535 <1> ; 03/02/2022 2536 <1> ;push eax ; physical address of the new/allocated page 2537 <1> ;call add_to_swap_queue 2538 <1> ;pop eax 2539 <1> ; 18/10/2015 2540 00004B96 81E3FF0F0000 <1> and ebx, PAGE_OFF ; 0FFFh 2541 <1> ;mov ecx, PAGE_SIZE 2542 <1> ;sub ecx, ebx 2543 00004B9C 01D8 <1> add eax, ebx 2544 <1> passc_1: 2545 <1> ; 18/10/2015 2546 <1> ; 20/05/2015 2547 00004B9E A3[5B650000] <1> mov [u.pbase], eax ; physical address 2548 00004BA3 66890D[5F650000] <1> mov [u.pcount], cx ; remain byte count in page (1-4096) 2549 00004BAA 5B <1> pop ebx 2550 00004BAB 58 <1> pop eax 2551 00004BAC C3 <1> retn ; 08/06/2015 2552 <1> passc_2: 2553 00004BAD C705[4F650000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error 2553 00004BB5 0000 <1> 2554 <1> ;pop ebx 2555 <1> ;pop eax 2556 00004BB7 E925E5FFFF <1> jmp error 2557 <1> 2558 <1> writei: 2559 <1> ; 13/06/2022 2560 <1> ; 03/02/2022 2561 <1> ; 20/05/2015 2562 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2563 <1> ; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2564 <1> ; 2565 <1> ; Write data to file with inode number in R1 2566 <1> ; 2567 <1> ; INPUTS -> 2568 <1> ; r1 - inode number 2569 <1> ; u.count - byte count to be written 2570 <1> ; u.base - points to user buffer 2571 <1> ; u.fofp - points to word with current file offset 2572 <1> ; OUTPUTS -> 2573 <1> ; u.count - cleared 2574 <1> ; u.nread - accumulates total bytes passed back 2575 <1> ; ((AX = R1)) 2576 <1> ; (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM) 2577 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -14/07/2022- 2578 <1> 2579 00004BBC 31C9 <1> xor ecx, ecx 2580 00004BBE 890D[28650000] <1> mov [u.nread], ecx ; 0 2581 <1> ; clr u.nread / clear the number of bytes transmitted during 2582 <1> ; / read or write calls 2583 00004BC4 66890D[5F650000] <1> mov [u.pcount], cx ; 19/05/2015 2584 00004BCB 390D[24650000] <1> cmp [u.count], ecx 2585 <1> ; ; tst u.count / test the byte count specified by the user 2586 00004BD1 770B <1> ja short writei_1 ; 1f 2587 <1> ; bgt 1f / any bytes to output; yes, branch 2588 <1> 2589 <1> ; 13/06/2022 - ('get/read LPT printer status' modification) 2590 00004BD3 83F810 <1> cmp eax, 16 ; LPR_INODE ; lpt (parallel port printer) ? 2591 00004BD6 7505 <1> jne short writei_0 2592 00004BD8 E924010000 <1> jmp lpr_stat ; get/read line status 2593 <1> writei_0: 2594 00004BDD C3 <1> retn 2595 <1> ; ; rts r0 / no, return - no writing to do 2596 <1> writei_1: ;1: 2597 <1> ; mov r1 ,-(sp) / save the i-node number on the stack 2598 00004BDE 6683F828 <1> cmp ax, 40 2599 <1> ; cmp r1,$40. 2600 <1> ; / does the i-node number indicate a special file? 2601 <1> ;ja dskw 2602 <1> ; bgt dskw / no, branch to standard file output 2603 <1> ; 03/02/2022 2604 00004BE2 7605 <1> jna short writei_3 2605 00004BE4 E958010000 <1> jmp dskw 2606 <1> writei_3: 2607 <1> ; (20/05/2015) 2608 00004BE9 50 <1> push eax ; because subroutines will jump to 'ret_' 2609 00004BEA 0FB6D8 <1> movzx ebx, al 2610 <1> ; 03/02/2022 2611 00004BED C1E302 <1> shl ebx, 2 2612 <1> ;shl bx, 2 2613 <1> ; asl r1 / yes, calculate the index into the special file 2614 00004BF0 81C3[F44B0000] <1> add ebx, writei_2 - 4 2615 00004BF6 FF23 <1> jmp dword [ebx] 2616 <1> ; jmp *1f-2(r1) 2617 <1> ; / jump table and jump to the appropriate routine 2618 <1> writei_2: ;1: 2619 00004BF8 [444C0000] <1> dd wtty ; tty, AX = 1 (runix) 2620 <1> ;wtty / tty; r1=2 2621 <1> ;wppt / ppt; r1=4 2622 00004BFC [974C0000] <1> dd wmem ; mem, AX = 2 (runix) 2623 <1> ;wmem / mem; r1=6 2624 <1> ;wrf0 / rf0 2625 <1> ;wrk0 / rk0 2626 <1> ;wtap / tap0 2627 <1> ;wtap / tap1 2628 <1> ;wtap / tap2 2629 <1> ;wtap / tap3 2630 <1> ;wtap / tap4 2631 <1> ;wtap / tap5 2632 <1> ;wtap / tap6 2633 <1> ;wtap / tap7 2634 00004C00 [F7520000] <1> dd wfd ; fd0, AX = 3 (runix only) 2635 00004C04 [F7520000] <1> dd wfd ; fd1, AX = 4 (runix only) 2636 00004C08 [F7520000] <1> dd whd ; hd0, AX = 5 (runix only) 2637 00004C0C [F7520000] <1> dd whd ; hd1, AX = 6 (runix only) 2638 00004C10 [F7520000] <1> dd whd ; hd2, AX = 7 (runix only) 2639 00004C14 [F7520000] <1> dd whd ; hd3, AX = 8 (runix only) 2640 00004C18 [C74C0000] <1> dd wlpr ; lpr, AX = 9 (runix) 2641 00004C1C [914C0000] <1> dd xmtt ; tty0, AX = 10 (runix) 2642 <1> ;xmtt / tty0 2643 00004C20 [914C0000] <1> dd xmtt ; tty1, AX = 11 (runix) 2644 <1> ;xmtt / tty1 2645 00004C24 [914C0000] <1> dd xmtt ; tty2, AX = 12 (runix) 2646 <1> ;xmtt / tty2 2647 00004C28 [914C0000] <1> dd xmtt ; tty3, AX = 13 (runix) 2648 <1> ;xmtt / tty3 2649 00004C2C [914C0000] <1> dd xmtt ; tty4, AX = 14 (runix) 2650 <1> ;xmtt / tty4 2651 00004C30 [914C0000] <1> dd xmtt ; tty5, AX = 15 (runix) 2652 <1> ;xmtt / tty5 2653 00004C34 [914C0000] <1> dd xmtt ; tty6, AX = 16 (runix) 2654 <1> ;xmtt / tty6 2655 00004C38 [914C0000] <1> dd xmtt ; tty7, AX = 17 (runix) 2656 <1> ;xmtt / tty7 2657 00004C3C [914C0000] <1> dd xmtt ; COM1, AX = 18 (runix only) 2658 <1> ; / wlpr / lpr 2659 00004C40 [914C0000] <1> dd xmtt ; COM2, AX = 19 (runix only) 2660 <1> 2661 <1> wtty: ; write to console tty (write to screen) 2662 <1> ; 03/02/2022 2663 <1> ; 18/11/2015 2664 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2665 <1> ; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1) 2666 <1> ; 2667 <1> ; Console tty output is on current video page 2668 <1> ; Console tty character output procedure is changed here 2669 <1> ; acconding to IBM PC compatible ROM BIOS video (text mode) functions. 2670 <1> ; 2671 00004C44 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 2672 00004C4B 8AA3[53620000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 2673 00004C51 88E0 <1> mov al, ah ; 07/07/2014 2674 <1> wttys: 2675 <1> ; 10/10/2013 2676 00004C53 8825[4E650000] <1> mov [u.ttyn], ah 2677 <1> ; 13/01/2014 2678 00004C59 FEC0 <1> inc al 2679 00004C5B A2[31650000] <1> mov [u.ttyp+1], al ; tty number + 1 2680 <1> wtty_nc: ; 15/05/2013 2681 <1> ; AH = [u.ttyn] = tty number ; 28/07/2013 2682 00004C60 E889010000 <1> call cpass 2683 <1> ; jsr r0,cpass / get next character from user buffer area; if 2684 <1> ; / none go to return address in syswrite 2685 <1> ; tst r1 / is character = null 2686 <1> ; beq wtty / yes, get next character 2687 <1> ; 10/10/2013 2688 00004C65 7428 <1> jz short wret 2689 <1> ;1 : 2690 <1> ;mov $240,*$ps / no, set processor priority to five 2691 <1> ;cmpb cc+1,$20. / is character count for console tty greater 2692 <1> ; / than 20 2693 <1> ;bhis 2f / yes; branch to put process to sleep 2694 <1> ; 27/06/2014 2695 <1> wtty_1: 2696 <1> ; AH = tty number 2697 <1> ; AL = ASCII code of the character 2698 <1> ; 15/04/2014 2699 <1> ;push ax 2700 <1> ; 03/02/2022 2701 00004C67 50 <1> push eax 2702 00004C68 E88E090000 <1> call putc ; 14/05/2013 2703 00004C6D 731D <1> jnc short wtty_2 2704 <1> ; 18/11/2015 2705 00004C6F E814F9FFFF <1> call idle 2706 <1> ;mov ax, [esp] 2707 <1> ; 03/02/2022 2708 00004C74 8B0424 <1> mov eax, [esp] 2709 00004C77 E87F090000 <1> call putc 2710 00004C7C 730E <1> jnc short wtty_2 2711 <1> ; 02/06/2014 2712 00004C7E 8A25[4E650000] <1> mov ah, [u.ttyn] 2713 00004C84 E88CF9FFFF <1> call sleep 2714 <1> ; 03/02/2022 2715 00004C89 58 <1> pop eax 2716 <1> ;pop ax 2717 00004C8A EBDB <1> jmp short wtty_1 2718 <1> ; jc error ; 15/05/2013 (COM1 or COM2 serial port error) 2719 <1> ; jsr r0,putc; 1 / find place in freelist to assign to 2720 <1> ; / console tty and 2721 <1> ; br 2f / place character in list; if none available 2722 <1> ; / branch to put process to sleep 2723 <1> ; jsr r0,startty / attempt to output character on tty 2724 <1> wtty_2: 2725 <1> ; 15/04/2014 2726 <1> ;pop ax 2727 <1> ; 03/02/2022 2728 00004C8C 58 <1> pop eax 2729 00004C8D EBD1 <1> jmp short wtty_nc 2730 <1> ; br wtty 2731 <1> wret: ; 10/10/2013 (20/05/2015) 2732 00004C8F 58 <1> pop eax 2733 00004C90 C3 <1> retn 2734 <1> ;2: 2735 <1> ;mov r1,-(sp) / place character on stack 2736 <1> ;jsr r0,sleep; 1 / put process to sleep 2737 <1> ;mov (sp)+,r1 / remove character from stack 2738 <1> ;br 1b / try again to place character in clist and output 2739 <1> 2740 <1> xmtt: ; < send/write character to tty > 2741 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2742 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2743 <1> ; 2744 <1> ; Retro UNIX 8086 v1 modification ! 2745 <1> ; 2746 <1> ; In original UNIX v1, 'xmtt' routine 2747 <1> ; (exactly different than this one) 2748 <1> ; was in 'u9.s' file. 2749 <1> ; 2750 00004C91 2C0A <1> sub al, 10 2751 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 2752 <1> ; 10/10/2013 2753 00004C93 88C4 <1> mov ah, al 2754 <1> ; 28/07/2013 2755 00004C95 EBBC <1> jmp short wttys 2756 <1> 2757 <1> ;wppt: 2758 <1> ; jsr r0,cpass / get next character from user buffer area, 2759 <1> ; / if none return to writei's calling routine 2760 <1> ; jsr r0,pptoc / output character on ppt 2761 <1> ; br wppt 2762 <1> 2763 <1> wmem: ; / transfer characters from a user area of core to memory file 2764 <1> ; 17/10/2015 2765 <1> ; 11/06/2015 2766 <1> ; 24/05/2015 2767 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2768 <1> ; 2769 00004C97 813D[09070000]- <1> cmp dword [x_timer], clock ; multi tasking clock/timer 2769 00004C9D [AB450000] <1> 2770 00004CA1 7415 <1> je short wmem_acc_err 2771 <1> ; 2772 00004CA3 8B35[10650000] <1> mov esi, [u.fofp] 2773 <1> wmem_1: 2774 00004CA9 E840010000 <1> call cpass 2775 <1> ; jsr r0,cpass / get next character from users area of 2776 <1> ; / core and put it in r1 2777 <1> ; mov r1,-(sp) / put character on the stack 2778 <1> ; 20/09/2013 2779 00004CAE 74DF <1> jz short wret ; wmem_2 2780 00004CB0 8B1E <1> mov ebx, [esi] 2781 <1> ; mov *u.fofp,r1 / save file offset in r1 2782 00004CB2 FF06 <1> inc dword [esi] ; 17/10/2015 2783 <1> ; inc *u.fofp / increment file offset to point to next 2784 <1> ; / available location in file 2785 00004CB4 8803 <1> mov [ebx], al 2786 <1> ; movb (sp)+,(r1) / pop char off stack, put in memory loc 2787 <1> ; / assigned to it 2788 00004CB6 EBF1 <1> jmp short wmem_1 2789 <1> ; br wmem / continue 2790 <1> ;1: 2791 <1> ;jmp error / ? 2792 <1> ;wmem_2: 2793 <1> ; ; 20/09/2013 2794 <1> ; pop ax 2795 <1> ; retn 2796 <1> 2797 <1> wmem_acc_err: 2798 00004CB8 C705[4F650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2798 00004CC0 0000 <1> 2799 00004CC2 E91AE4FFFF <1> jmp error 2800 <1> 2801 <1> ;wlpr: 2802 <1> ; 13/06/2022 2803 <1> ;mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 2804 <1> ;jmp error ; ... Printing procedure will be located here ... 2805 <1> ;/ jsr r0,cpass 2806 <1> ;/ cmp r0,$'a 2807 <1> ;/ blo 1f 2808 <1> ;/ cmp r1,$'z 2809 <1> ;/ bhi 1f 2810 <1> ;/ sub $40,r1 2811 <1> ;/1: 2812 <1> ;/ jsr r0,lptoc 2813 <1> ;/ br wlpr 2814 <1> ; br rmem / continue 2815 <1> 2816 <1> ; 13/06/2022 - Retro UNIX 386 v1 - PRINTER BIOS (Functions) 2817 <1> 2818 <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM) 2819 <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987 2820 <1> ;; 23/03/2018 - Retro DOS v2.0 2821 <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2) 2822 <1> 2823 <1> ; IBM ROMBIOS (INT 17h) STATUS BITS 2824 <1> 2825 <1> NOTBUSYSTATUS equ 10000000b ; NOT BUSY 2826 <1> ACKSTATUS equ 01000000b ; ACKNOWLEDGE (FOR WHAT?) 2827 <1> NOPAPERSTATUS equ 00100000b ; NO MORE PAPER 2828 <1> SELECTEDSTATUS equ 00010000b ; THE PRINTER SAID IT WAS SELECTED 2829 <1> IOERRSTATUS equ 00001000b ; SOME KIND ERROR 2830 <1> RESERVED equ 00000110b ; NOPS 2831 <1> TIMEOUTSTATUS equ 00000001b ; TIME OUT. 2832 <1> 2833 <1> ;---------------------------------------------------------------- 2834 <1> ; : 2835 <1> ; WRITE TO PRINTER DEVICE : 2836 <1> ; : 2837 <1> ; CX has count of bytes to be printed : 2838 <1> ; ES:DI point to source buffer contains characters : 2839 <1> ; AuxNum (in msbio.asm) has printer number : 2840 <1> ; : 2841 <1> ;---------------------------------------------------------------- 2842 <1> 2843 <1> wlpr: 2844 <1> ; 14/07/2022 2845 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) 2846 <1> PRN$WRIT: 2847 <1> ; INPUT: 2848 <1> ; [u.count] = count of characters to be printed 2849 <1> ; [u.base] = buffer address in user's memory space 2850 <1> ; 2851 <1> ; (if ECX = 0, printer status will be returned) 2852 <1> 2853 <1> ;xor ebx, ebx 2854 <1> PRN$LOOP: 2855 00004CC7 E822010000 <1> call cpass ; Get a character into AL 2856 00004CCC 7431 <1> jz short pr_exit 2857 <1> ; 2858 00004CCE B302 <1> mov bl, 2 ; retry count 2859 <1> PRN$OUT: 2860 <1> ; al = character which will be printed 2861 00004CD0 30E4 <1> xor ah, ah ; 0 ; PRINT THE CHARACTER IN (AL) 2862 00004CD2 E850000000 <1> call PRNOP 2863 00004CD7 74EE <1> jz short PRN$LOOP ; if error, try to print again 2864 <1> PrRetry: 2865 <1> ; al = character 2866 00004CD9 FECB <1> dec bl 2867 00004CDB 75F3 <1> jnz short PRN$OUT 2868 <1> pr_err_exit: 2869 00004CDD 0FB6C0 <1> movzx eax, al 2870 00004CE0 A3[4F650000] <1> mov [u.error], eax 2871 00004CE5 A3[00650000] <1> mov [u.r0], eax ; error code in AL 2872 <1> ;mov ebp, [u.sp] 2873 00004CEA 8B1D[F8640000] <1> mov ebx, [u.sp] ; 14/07/2022 2874 <1> ; Kernel stack at the beginning of sys call 2875 00004CF0 8B15[28650000] <1> mov edx, [u.nread] 2876 00004CF6 4A <1> dec edx ; last char failed 2877 <1> ;mov [ebp+20], edx ; count of printed characters in edx 2878 00004CF7 895314 <1> mov [ebx+20], edx ; 14/07/2022 2879 00004CFA E9E2E3FFFF <1> jmp error 2880 <1> pr_exit: 2881 00004CFF 58 <1> pop eax ; inode number 2882 <1> 2883 <1> ;mov eax, [u.nread] 2884 <1> ;mov [u.r0], eax ; count of printed chacters 2885 <1> ;jmp sysret 2886 00004D00 C3 <1> retn ; return from writei to syswrite (rw0) 2887 <1> 2888 <1> ; 13/06/2022 2889 <1> 2890 <1> ;---------------------------------------------------------------- 2891 <1> ; : 2892 <1> ; PRINTER STATUS ROUTINE : 2893 <1> ; : 2894 <1> ;---------------------------------------------------------------- 2895 <1> ; 2896 <1> 2897 <1> lpr_stat: 2898 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) 2899 <1> PRN$STAT: 2900 00004D01 E81F000000 <1> call PRNSTAT ; get the status 2901 00004D06 750E <1> jnz short prn_stat_retn 2902 <1> ; if error jump to error routine 2903 <1> ;mov al, 9 ; AGAIN, ASSUME OUT OF PAPER... 2904 00004D08 B01F <1> mov al, ERR_PRN_PAPER 2905 00004D0A F6C420 <1> test ah, NOPAPERSTATUS 2906 00004D0D 7507 <1> jnz short prn_stat_retn 2907 00004D0F F6C480 <1> test ah, NOTBUSYSTATUS 2908 00004D12 750D <1> jnz short prn_stat_ok ; if not busy return (with cf=0) 2909 00004D14 B022 <1> mov al, ERR_PRN_BUSY ; else busy, return to busy exit 2910 <1> prn_stat_retn: 2911 <1> ; al = error code 2912 <1> ; ah = status flags 2913 00004D16 A3[00650000] <1> mov [u.r0], eax 2914 <1> ;movzx eax, al 2915 <1> ;mov [u.error], eax 2916 00004D1B 58 <1> pop eax ; discard return address to syswrite 2917 00004D1C E9E0E3FFFF <1> jmp sysret 2918 <1> prn_stat_ok: 2919 00004D21 30C0 <1> xor al, al ; 0 2920 00004D23 EBF1 <1> jmp short prn_stat_retn 2921 <1> 2922 <1> ; 2923 <1> ; PRNSTAT get printer status 2924 <1> ; PRNOP print a character 2925 <1> ; 2926 <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS 2927 <1> ; printer routines. The routines share code which calls on the bios and 2928 <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ 2929 <1> ; only by the value put into AH before the ROM-BIOS call. 2930 <1> ; 2931 <1> ; INPUT if PRNOP then character in AL 2932 <1> ; 2933 <1> ; OUTPUT - AL holds error code 2934 <1> ; - AH status byte from printer 2935 <1> ; - flag NZ if error 2936 <1> 2937 <1> PRNSTAT: 2938 00004D25 B402 <1> mov ah, 2 ; set command for get status 2939 <1> 2940 <1> PRNOP: 2941 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) 2942 <1> ; 2943 <1> ; Print character (on paper) 2944 <1> 2945 <1> ; INPUT: 2946 <1> ; al = character to be printed 2947 <1> ; OUTPUT: 2948 <1> ; zf = 1 -> ok 2949 <1> ; zf = 0 -> error code in AL 2950 <1> 2951 00004D27 E8080B0000 <1> call int17h ; call lpt bios 2952 <1> 2953 00004D2C F6C408 <1> test ah, IOERRSTATUS ; I/O ERROR? 2954 00004D2F 740A <1> jz short short prnop_chk_nrdy ; NO, TRY NOT READY 2955 <1> 2956 <1> ; AT THIS POINT, WE KNOW WE HAVE AN ERROR. 2957 <1> ; THE CONVERSE IS NOT TRUE. 2958 <1> 2959 <1> ;mov al, 9 ; FIRST, ASSUME OUT OF PAPER 2960 00004D31 B01F <1> mov al, ERR_PRN_PAPER 2961 00004D33 F6C420 <1> test ah, NOPAPERSTATUS ; OUT OF PAPER SET? 2962 00004D36 7502 <1> jnz short PRNOP1 ; YES, ERROR IS SET 2963 <1> ;mov al, ERR_PRN_IO 2964 00004D38 FEC0 <1> inc al ; INDICATE I/O ERROR 2965 <1> PRNOP1: 2966 <1> 2967 <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT) 2968 <1> 2969 00004D3A C3 <1> retn ; RETURN WITH ERROR 2970 <1> 2971 <1> ; THE BITS SAID NO ERROR. 2972 <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE. 2973 <1> 2974 <1> prnop_chk_nrdy: 2975 <1> ;mov al, 2 ; ASSUME NOT-READY 2976 00004D3B B019 <1> mov al, ERR_PRN_TIMEOUT ; ''time out !' error 2977 <1> 2978 00004D3D F6C401 <1> test ah, TIMEOUTSTATUS ; IS TIME-OUT SET? 2979 <1> ; IF NZ THEN ERROR, ELSE OK??? 2980 <1> PRNOP2: 2981 00004D40 C3 <1> retn 2982 <1> 2983 <1> 2984 <1> dskw: ; / write routine for non-special files 2985 <1> ; 2986 <1> ; 19/07/2022 2987 <1> ; (file offset bugfix for 'dskwr' error return situation) 2988 <1> ; 03/02/2022 2989 <1> ; 25/07/2015 2990 <1> ; 16/06/2015 2991 <1> ; 09/06/2015 2992 <1> ; 31/05/2015 (Retro UNIX 386 v1 - Beginning) 2993 <1> ; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1) 2994 <1> ; 2995 <1> ; 01/08/2013 (mkdir_w check) 2996 <1> 2997 <1> ;push ax ; 26/04/2013 2998 <1> ; mov (sp),r1 / get an i-node number from the stack into r1 2999 <1> ; 03/02/2022 3000 00004D41 50 <1> push eax 3001 <1> ; AX = inode number 3002 00004D42 E8AFFAFFFF <1> call iget 3003 <1> ; jsr r0,iget / write i-node out (if modified), 3004 <1> ; / read i-node 'r1' into i-node area of core 3005 00004D47 8B1D[10650000] <1> mov ebx, [u.fofp] 3006 00004D4D 8B13 <1> mov edx, [ebx] 3007 <1> ; mov *u.fofp,r2 / put the file offset [(u.off) or the offset 3008 <1> ; / in the fsp entry for this file] in r2 3009 00004D4F 0315[24650000] <1> add edx, [u.count] 3010 <1> ; add u.count,r2 / no. of bytes to be written 3011 <1> ; / + file offset is put in r2 3012 <1> ; 16/06/2015 3013 00004D55 81FAFFFF0000 <1> cmp edx, 65535 ; file size limit (for UNIX v1 file system) 3014 00004D5B 760F <1> jna short dskw_0 3015 00004D5D C705[4F650000]1400- <1> mov dword [u.error], ERR_FILE_SIZE ; 'file size error !' 3015 00004D65 0000 <1> 3016 00004D67 E975E3FFFF <1> jmp error 3017 <1> dskw_0: 3018 00004D6C 663B15[F8610000] <1> cmp dx, [i.size] 3019 <1> ; cmp r2,i.size / is this greater than the present size of 3020 <1> ; / the file? 3021 00004D73 760C <1> jna short dskw_1 3022 <1> ; blos 1f / no, branch 3023 00004D75 668915[F8610000] <1> mov [i.size], dx 3024 <1> ; mov r2,i.size / yes, increase the file size to 3025 <1> ; / file offset + no. of data bytes 3026 00004D7C E87FFBFFFF <1> call setimod 3027 <1> ; jsr r0,setimod / set imod=1 (i.e., core inode has been 3028 <1> ; / modified), stuff time of modification into 3029 <1> ; / core image of i-node 3030 <1> dskw_1: ; 1: 3031 00004D81 E807F9FFFF <1> call mget 3032 <1> ; EAX = Block number 3033 <1> ; jsr r0,mget / get the block no. in which to write 3034 <1> ; / the next data byte 3035 <1> ; eax = block number 3036 00004D86 8B1D[10650000] <1> mov ebx, [u.fofp] 3037 00004D8C 8B13 <1> mov edx, [ebx] 3038 00004D8E 81E2FF010000 <1> and edx, 1FFh 3039 <1> ; bit *u.fofp,$777 / test the lower 9 bits of the file offset 3040 00004D94 750C <1> jnz short dskw_2 3041 <1> ; bne 2f / if its non-zero, branch; if zero, file offset = 0, 3042 <1> ; / 512, 1024,...(i.e., start of new block) 3043 00004D96 813D[24650000]0002- <1> cmp dword [u.count], 512 3043 00004D9E 0000 <1> 3044 <1> ; cmp u.count,$512. / if zero, is there enough data to fill 3045 <1> ; / an entire block? (i.e., no. of 3046 00004DA0 7305 <1> jnb short dskw_3 3047 <1> ; bhis 3f / bytes to be written greater than 512.? 3048 <1> ; / Yes, branch. Don't have to read block 3049 <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be 3050 <1> ; / overwritten). 3051 00004DA2 E81A060000 <1> call dskrd 3052 <1> ; jsr r0,dskrd / no, must retain old info.. 3053 <1> ; / Hence, read block 'r1' into an I/O buffer 3054 <1> dskw_3: ; 3: 3055 <1> ; EAX (r1) = block/sector number 3056 00004DA7 E879060000 <1> call wslot 3057 <1> ; jsr r0,wslot / set write and inhibit bits in I/O queue, 3058 <1> ; / proc. status=0, r5 points to 1st word of data 3059 00004DAC 803D[61650000]00 <1> cmp byte [u.kcall], 0 3060 00004DB3 770F <1> ja short dskw_5 ; zf=0 -> the caller is 'mkdir' 3061 <1> ; 3062 00004DB5 66833D[5F650000]00 <1> cmp word [u.pcount], 0 3063 00004DBD 7705 <1> ja short dskw_5 3064 <1> dskw_4: 3065 <1> ; [u.base] = virtual address to transfer (as source address) 3066 00004DBF E89BFDFFFF <1> call trans_addr_r ; translate virtual address to physical (r) 3067 <1> dskw_5: 3068 <1> ; EBX (r5) = system (I/O) buffer address 3069 00004DC4 E885000000 <1> call sioreg 3070 <1> ; jsr r0,sioreg / r3 = no. of bytes of data, 3071 <1> ; / r1 = address of data, r2 points to location 3072 <1> ; / in buffer in which to start writing data 3073 <1> ; 19/07/2022 3074 <1> ; EDX = user data offset (previous value of [u.pbase]) 3075 <1> ; ESI = pointer to file offset 3076 <1> ; EDI = system (I/O) buffer offset 3077 <1> ; ECX = byte count 3078 <1> ; EBX = system buffer (data) address 3079 <1> ; EAX = remain bytes after byte count within page frame 3080 <1> 3081 <1> ; 19/07/2022 - Erdogan Tan 3082 <1> ; BugFix (Also original unix v1 kernel code has this bug!) 3083 <1> ; ((Against a possible disk write failure/error, 3084 <1> ; file offset must not be updated/increased before 'dskwr' 3085 <1> ; but it was updated in 'sioreg'. I have modified 'sioreg' 3086 <1> ; and 'dskw' procedures for that.)) 3087 <1> 3088 <1> ; 19/07/2022 3089 00004DC9 56 <1> push esi ; * ; save file offset (pointer) 3090 00004DCA 51 <1> push ecx ; ** ; save byte count 3091 00004DCB 89D6 <1> mov esi, edx 3092 <1> 3093 <1> ; ESI = file (user data) offset 3094 <1> ; EDI = sector (I/O) buffer offset 3095 <1> ; ECX = byte count 3096 <1> ; 3097 00004DCD F3A4 <1> rep movsb 3098 <1> ; movb (r1 )+,(r2)+ 3099 <1> ; / transfer a byte of data to the I/O buffer 3100 <1> ; dec r3 / decrement no. of bytes to be written 3101 <1> ; bne 2b / have all bytes been transferred? No, branch 3102 <1> ; 25/07/2015 3103 <1> ; eax = remain bytes in buffer 3104 <1> ; (check if remain bytes in the buffer > [u.pcount]) 3105 00004DCF 09C0 <1> or eax, eax 3106 00004DD1 75EC <1> jnz short dskw_4 ; (page end before system buffer end!) 3107 <1> dskw_6: 3108 00004DD3 E85A060000 <1> call dskwr 3109 <1> ; jsr r0,dskwr / yes, write the block and the i-node 3110 <1> 3111 <1> ; 19/07/2022 3112 <1> ; (there is not a disk write error, we can increase file offset) 3113 00004DD8 58 <1> pop eax ; ** ; byte count 3114 00004DD9 5F <1> pop edi ; * ; file offset (pointer) 3115 <1> ; 3116 00004DDA 0107 <1> add [edi], eax 3117 <1> ; new file offset (old offset + byte count) 3118 <1> 3119 00004DDC 833D[24650000]00 <1> cmp dword [u.count], 0 3120 <1> ; tst u.count / any more data to write? 3121 00004DE3 779C <1> ja short dskw_1 3122 <1> ; bne 1b / yes, branch 3123 <1> ; 03/08/2013 3124 00004DE5 C605[61650000]00 <1> mov byte [u.kcall], 0 3125 <1> ; 20/09/2013 (;;) 3126 <1> ;pop ax 3127 <1> ; 03/02/2022 3128 00004DEC 58 <1> pop eax 3129 00004DED C3 <1> retn 3130 <1> ;;jmp short dskw_ret 3131 <1> ; jmp ret / no, return to the caller via 'ret' 3132 <1> 3133 <1> cpass: ; / get next character from user area of core and put it in r1 3134 <1> ; 18/10/2015 3135 <1> ; 10/10/2015 3136 <1> ; 10/07/2015 3137 <1> ; 02/07/2015 3138 <1> ; 01/07/2015 3139 <1> ; 24/06/2015 3140 <1> ; 08/06/2015 3141 <1> ; 04/06/2015 3142 <1> ; 20/05/2015 3143 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 3144 <1> ; 3145 <1> ; INPUTS -> 3146 <1> ; [u.base] = virtual address in user area 3147 <1> ; [u.count] = byte count (max.) 3148 <1> ; [u.pcount] = byte count in page (0 = reset) 3149 <1> ; OUTPUTS -> 3150 <1> ; AL = the character which is pointed by [u.base] 3151 <1> ; zf = 1 -> transfer count has been completed 3152 <1> ; 3153 <1> ; ((Modified registers: EAX, EDX, ECX)) 3154 <1> ; 3155 <1> ; 3156 00004DEE 833D[24650000]00 <1> cmp dword [u.count], 0 ; 14/08/2013 3157 <1> ; tst u.count / have all the characters been transferred 3158 <1> ; / (i.e., u.count, # of chars. left 3159 00004DF5 763F <1> jna short cpass_3 3160 <1> ; beq 1f / to be transferred = 0?) yes, branch 3161 00004DF7 FF0D[24650000] <1> dec dword [u.count] 3162 <1> ; dec u.count / no, decrement u.count 3163 <1> ; 19/05/2015 3164 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 3165 <1> ; to physical address 3166 00004DFD 66833D[5F650000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 3167 <1> ; 1-4095 --> use previous physical base address 3168 <1> ; in [u.pbase] 3169 00004E05 770E <1> ja short cpass_1 3170 <1> ; 02/07/2015 3171 00004E07 833D[57650000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller os kernel 3172 00004E0E 7427 <1> je short cpass_k ; (sysexec, '/etc/init') ? 3173 <1> ; 08/06/2015 - 10/07/2015 3174 00004E10 E84AFDFFFF <1> call trans_addr_r 3175 <1> cpass_1: 3176 <1> ; 02/07/2015 3177 <1> ; 24/06/2015 3178 00004E15 66FF0D[5F650000] <1> dec word [u.pcount] 3179 <1> cpass_2: 3180 <1> ; 10/10/2015 3181 <1> ; 02/07/2015 3182 00004E1C 8B15[5B650000] <1> mov edx, [u.pbase] 3183 00004E22 8A02 <1> mov al, [edx] ; 10/10/2015 3184 <1> ; movb *u.base,r1 / take the character pointed to 3185 <1> ; / by u.base and put it in r1 3186 00004E24 FF05[28650000] <1> inc dword [u.nread] 3187 <1> ; inc u.nread / increment no. of bytes transferred 3188 00004E2A FF05[20650000] <1> inc dword [u.base] 3189 <1> ; inc u.base / increment the buffer address to point to the 3190 <1> ; / next byte 3191 00004E30 FF05[5B650000] <1> inc dword [u.pbase] ; 04/06/2015 3192 <1> cpass_3: 3193 00004E36 C3 <1> retn 3194 <1> ; rts r0 / next byte 3195 <1> ; 1: 3196 <1> ; mov (sp)+,r0 3197 <1> ; / put return address of calling routine into r0 3198 <1> ; mov (sp)+,r1 / i-number in r1 3199 <1> ; rts r0 / non-local return 3200 <1> cpass_k: 3201 <1> ; 02/07/2015 3202 <1> ; The caller is os kernel 3203 <1> ; (get sysexec arguments from kernel's memory space) 3204 <1> ; 3205 00004E37 8B1D[20650000] <1> mov ebx, [u.base] 3206 00004E3D 66C705[5F650000]00- <1> mov word [u.pcount], PAGE_SIZE ; 4096 3206 00004E45 10 <1> 3207 00004E46 891D[5B650000] <1> mov [u.pbase], ebx 3208 00004E4C EBCE <1> jmp short cpass_2 3209 <1> 3210 <1> sioreg: 3211 <1> ; 19/07/2022 3212 <1> ; (file offset bugfix for 'dskwr' error return situation) 3213 <1> ; 25/07/2015 3214 <1> ; 18/07/2015 3215 <1> ; 02/07/2015 3216 <1> ; 17/06/2015 3217 <1> ; 09/06/2015 3218 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 3219 <1> ; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1) 3220 <1> ; 3221 <1> ; INPUTS -> 3222 <1> ; EBX = system buffer (data) address (r5) 3223 <1> ; [u.fofp] = pointer to file offset pointer 3224 <1> ; [u.base] = virtual address of the user buffer 3225 <1> ; [u.pbase] = physical address of the user buffer 3226 <1> ; [u.count] = byte count 3227 <1> ; [u.pcount] = byte count within page frame 3228 <1> ; OUTPUTS -> 3229 <1> ; ESI = user data offset (r1) 3230 <1> ; EDI = system (I/O) buffer offset (r2) 3231 <1> ; ECX = byte count (r3) 3232 <1> ; EAX = remain bytes after byte count within page frame 3233 <1> ; (If EAX > 0, transfer will continue from the next page) 3234 <1> ; 3235 <1> ; ((Modified registers: EDX)) 3236 <1> 3237 <1> ; 19/07/2022 3238 <1> ; OUTPUTS -> 3239 <1> ; EDX = user data offset (previous value of [u.pbase]) 3240 <1> ; ESI = pointer to file offset 3241 <1> ; EDI = system (I/O) buffer offset 3242 <1> ; ECX = byte count 3243 <1> ; EBX = system buffer (data) address 3244 <1> ; EAX = remain bytes after byte count within page frame 3245 <1> 3246 00004E4E 8B35[10650000] <1> mov esi, [u.fofp] 3247 00004E54 8B3E <1> mov edi, [esi] 3248 <1> ; mov *u.fofp,r2 / file offset (in bytes) is moved to r2 3249 00004E56 89F9 <1> mov ecx, edi 3250 <1> ; mov r2,r3 / and also to r3 3251 00004E58 81C900FEFFFF <1> or ecx, 0FFFFFE00h 3252 <1> ; bis $177000,r3 / set bits 9,...,15 of file offset in r3 3253 00004E5E 81E7FF010000 <1> and edi, 1FFh 3254 <1> ; bic $!777,r2 / calculate file offset mod 512. 3255 00004E64 01DF <1> add edi, ebx ; EBX = system buffer (data) address 3256 <1> ; add r5,r2 / r2 now points to 1st byte in system buffer 3257 <1> ; / where data is to be placed 3258 <1> ; mov u.base,r1 / address of data is in r1 3259 00004E66 F7D9 <1> neg ecx 3260 <1> ; neg r3 / 512 - file offset (mod512.) in r3 3261 <1> ; / (i.e., the no. of free bytes in the file block) 3262 00004E68 3B0D[24650000] <1> cmp ecx, [u.count] 3263 <1> ; cmp r3,u.count / compare this with the no. of data bytes 3264 <1> ; / to be written to the file 3265 00004E6E 7606 <1> jna short sioreg_0 3266 <1> ; blos 2f / if less than branch. Use the no. of free bytes 3267 <1> ; / in the file block as the number to be written 3268 00004E70 8B0D[24650000] <1> mov ecx, [u.count] 3269 <1> ; mov u.count,r3 / if greater than, use the no. of data 3270 <1> ; / bytes as the number to be written 3271 <1> sioreg_0: 3272 <1> ; 17/06/2015 3273 00004E76 803D[61650000]00 <1> cmp byte [u.kcall], 0 3274 00004E7D 7613 <1> jna short sioreg_1 3275 <1> ; 25/07/2015 3276 <1> ; the caller is 'mkdir' or 'namei' 3277 00004E7F A1[20650000] <1> mov eax, [u.base] ; 25/07/2015 3278 00004E84 A3[5B650000] <1> mov [u.pbase], eax ; physical address = virtual address 3279 00004E89 66890D[5F650000] <1> mov word [u.pcount], cx ; remain bytes in buffer (1 sector) 3280 00004E90 EB0B <1> jmp short sioreg_2 3281 <1> sioreg_1: 3282 <1> ; 25/07/2015 3283 <1> ; 18/07/2015 3284 <1> ; 09/06/2015 3285 00004E92 0FB715[5F650000] <1> movzx edx, word [u.pcount] 3286 <1> ; ecx and [u.pcount] are always > 0, here 3287 00004E99 39D1 <1> cmp ecx, edx 3288 00004E9B 7728 <1> ja short sioreg_4 ; transfer count > [u.pcount] 3289 <1> sioreg_2: ; 2: 3290 00004E9D 31C0 <1> xor eax, eax ; 25/07/2015 3291 <1> sioreg_3: 3292 00004E9F 010D[28650000] <1> add [u.nread], ecx 3293 <1> ; add r3,u.nread / r3 + number of bytes xmitted 3294 <1> ; / during write is put into u.nread 3295 00004EA5 290D[24650000] <1> sub [u.count], ecx 3296 <1> ; sub r3,u.count / u.count = no. of bytes that still 3297 <1> ; / must be written or read 3298 00004EAB 010D[20650000] <1> add [u.base], ecx 3299 <1> ; add r3,u.base / u.base points to the 1st of the remaining 3300 <1> ; / data bytes 3301 <1> ; 19/07/2022 3302 <1> ;add [esi], ecx 3303 <1> ; ; add r3,*u.fofp / new file offset = number of bytes done 3304 <1> ; / + old file offset 3305 <1> ; 25/07/2015 3306 <1> ;mov esi, [u.pbase] 3307 <1> ; 19/07/2022 3308 00004EB1 8B15[5B650000] <1> mov edx, [u.pbase] 3309 <1> 3310 00004EB7 66290D[5F650000] <1> sub [u.pcount], cx 3311 00004EBE 010D[5B650000] <1> add [u.pbase], ecx 3312 00004EC4 C3 <1> retn 3313 <1> ; rts r0 3314 <1> ; transfer count > [u.pcount] 3315 <1> sioreg_4: 3316 <1> ; 25/07/2015 3317 <1> ; transfer count > [u.pcount] 3318 <1> ; (ecx > edx) 3319 00004EC5 89C8 <1> mov eax, ecx 3320 00004EC7 29D0 <1> sub eax, edx ; remain bytes for 1 sector (block) transfer 3321 00004EC9 89D1 <1> mov ecx, edx ; current transfer count = [u.pcount] 3322 00004ECB EBD2 <1> jmp short sioreg_3 2058 %include 'u7.s' ; 18/04/2015 2059 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS7.INC 2060 <1> ; Last Modification: 13/06/2022 2061 <1> ; ---------------------------------------------------------------------------- 2062 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2063 <1> ; (v0.1 - Beginning: 11/07/2012) 2064 <1> ; 2065 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2066 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2067 <1> ; 2068 <1> ; 2069 <1> ; 2070 <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s 2071 <1> ; 2072 <1> ; **************************************************************************** 2073 <1> ; 14/11/2015 2074 <1> 2075 <1> sysmount: ; / mount file system; args special; name 2076 <1> ; 14/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19) 2077 <1> ; 12/02/2022 2078 <1> ; 04/02/2022 2079 <1> ; 14/11/2015 2080 <1> ; 24/10/2015 2081 <1> ; 13/10/2015 2082 <1> ; 10/07/2015 2083 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 2084 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 2085 <1> ; 2086 <1> ; 'sysmount' anounces to the system that a removable 2087 <1> ; file system has been mounted on a special file. 2088 <1> ; The device number of the special file is obtained vihha 2089 <1> ; a call to 'getspl'. It is put in the I/O queue entry for 2090 <1> ; dismountable file system (sb1) and the I/O queue entry is 2091 <1> ; set up to read (bit 10 is set). 'ppoke' is then called to 2092 <1> ; to read file system into core, i.e. the first block on the 2093 <1> ; mountable file system is read in. This block is super block 2094 <1> ; for the file system. This call is super user restricted. 2095 <1> ; 2096 <1> ; Calling sequence: 2097 <1> ; sysmount; special; name 2098 <1> ; Arguments: 2099 <1> ; special - pointer to name of special file (device) 2100 <1> ; name - pointer to name of the root directory of the 2101 <1> ; newly mounted file system. 'name' should 2102 <1> ; always be a directory. 2103 <1> ; Inputs: - 2104 <1> ; Outputs: - 2105 <1> ; ............................................................... 2106 <1> ; 2107 <1> ; Retro UNIX 8086 v1 modification: 2108 <1> ; 'sysmount' system call has two arguments; so, 2109 <1> ; * 1st argument, special is pointed to by BX register 2110 <1> ; * 2nd argument, name is in CX register 2111 <1> ; 2112 <1> ; NOTE: Device numbers, names and related procedures are 2113 <1> ; already modified for IBM PC compatibility and 2114 <1> ; Retro UNIX 8086 v1 device configuration. 2115 <1> 2116 <1> ;call arg2 2117 <1> ; jsr r0,arg2 / get arguments special and name 2118 00004ECD 891D[18650000] <1> mov [u.namep], ebx 2119 <1> ; 12/02/2022 2120 <1> ;push ecx ; directory name 2121 00004ED3 66833D[E8640000]00 <1> cmp word [mnti], 0 2122 <1> ; tst mnti / is the i-number of the cross device file 2123 <1> ; / zero? 2124 <1> ;;ja error 2125 <1> ; bne errora / no, error 2126 <1> ;ja sysmnt_err0 2127 <1> ; 04/02/2022 2128 00004EDB 7605 <1> jna short sysmnt_0 2129 00004EDD E950010000 <1> jmp sysmnt_err0 2130 <1> sysmnt_0: 2131 <1> ; 12/02/2022 2132 00004EE2 51 <1> push ecx ; directory name 2133 00004EE3 E859010000 <1> call getspl 2134 <1> ; jsr r0,getspl / get special files device number in r1 2135 <1> ; 12/02/2022 2136 00004EE8 8F05[18650000] <1> pop dword [u.namep] ; directory name 2137 <1> ; 13/10/2015 2138 <1> ;movzx ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5) 2139 <1> ; 04/02/2022 2140 00004EEE 29DB <1> sub ebx, ebx 2141 00004EF0 88C3 <1> mov bl, al 2142 00004EF2 F683[7E5C0000]80 <1> test byte [ebx+drv.status], 80h ; 24/10/2015 2143 00004EF9 750F <1> jnz short sysmnt_1 2144 <1> sysmnt_err1: 2145 00004EFB C705[4F650000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY ; drive not ready ! 2145 00004F03 0000 <1> 2146 00004F05 E9D7E1FFFF <1> jmp error 2147 <1> sysmnt_1: 2148 <1> ; 12/02/2022 2149 <1> ;pop dword [u.namep] 2150 <1> ; mov (sp)+,u.namep / put the name of file to be placed 2151 <1> ; / on the device 2152 <1> ; 14/11/2015 2153 00004F0A 53 <1> push ebx ; 13/10/2015 2154 <1> ; mov r1,-(sp) / save the device number 2155 <1> ; 2156 00004F0B E8D1F0FFFF <1> call namei 2157 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 2158 <1> ; ax = 0 -> file not found 2159 <1> ;jz error 2160 <1> ;jc error 2161 <1> ; jsr r0,namei / get the i-number of the file 2162 <1> ; br errora 2163 00004F10 730F <1> jnc short sysmnt_2 2164 <1> sysmnt_err2: 2165 00004F12 C705[4F650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready ! 2165 00004F1A 0000 <1> 2166 00004F1C E9C0E1FFFF <1> jmp error 2167 <1> sysmnt_2: 2168 00004F21 66A3[E8640000] <1> mov [mnti], ax 2169 <1> ; mov r1,mnti / put it in mnti 2170 <1> 2171 <1> ; 14/05/2022 2172 <1> ; -Retro UNIX 8086/386 v1 feaure only- 2173 00004F27 66A1[E0640000] <1> mov ax, [ii] 2174 00004F2D 66A3[EA640000] <1> mov [mntp], ax ; parent dir inumber of [mnti] 2175 <1> 2176 <1> ; 04/02/2022 2177 00004F33 BB[C8770000] <1> mov ebx, sb1 ; super block buffer (of mounted disk) 2178 <1> sysmnt_3: ;1: 2179 <1> ;cmp byte [ebx+1], 0 2180 <1> ; tstb sb1+1 / is 15th bit of I/O queue entry for 2181 <1> ; / dismountable device set? 2182 <1> ;jna short sysmnt_4 2183 <1> ; bne 1b / (inhibit bit) yes, skip writing 2184 <1> ;call idle ; (wait for hardware interrupt) 2185 <1> ;jmp short sysmnt_3 2186 <1> sysmnt_4: 2187 00004F38 58 <1> pop eax ; Retro UNIX 8086 v1 device number/ID (0 to 5) 2188 00004F39 A2[E7640000] <1> mov [mdev], al 2189 <1> ; mov (sp),mntd / no, put the device number in mntd 2190 00004F3E 8803 <1> mov [ebx], al 2191 <1> ; movb (sp),sb1 / put the device number in the lower byte 2192 <1> ; / of the I/O queue entry 2193 <1> ;mov byte [cdev], 1 ; mounted device/drive 2194 <1> ; mov (sp)+,cdev / put device number in cdev 2195 00004F40 66810B0004 <1> or word [ebx], 400h ; Bit 10, 'read' flag/bit 2196 <1> ; bis $2000,sb1 / set the read bit 2197 <1> ; Retro UNIX 386 v1 modification : 2198 <1> ; 32 bit block number at buffer header offset 4 2199 00004F45 C7430401000000 <1> mov dword [ebx+4], 1 ; physical block number = 1 2200 00004F4C E8AB050000 <1> call diskio 2201 00004F51 7345 <1> jnc short sysmnt_5 2202 00004F53 31C0 <1> xor eax, eax 2203 00004F55 66A3[E8640000] <1> mov [mnti], ax ; 0 2204 00004F5B A2[E7640000] <1> mov [mdev], al ; 0 2205 <1> ;mov [cdev], al ; 0 2206 <1> ; 12/02/2022 2207 00004F60 803D[62650000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 2208 00004F67 7508 <1> jne short sysmnt_err3 2209 <1> ; yes, clear [u.brwdev] for next check 2210 <1> ; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 2211 00004F69 FE05[62650000] <1> inc byte [u.brwdev] ; 0, reset 2212 00004F6F EB0A <1> jmp short sysmnt_err4 2213 <1> sysmnt_err3: ; 12/02/2022 2214 <1> ; no, set [u.error] to disk read error 2215 00004F71 C705[4F650000]1100- <1> mov dword [u.error], ERR_DRV_READ ; 'disk read error !' 2215 00004F79 0000 <1> 2216 <1> sysmnt_err4: 2217 <1> ; 12/02/2022 2218 <1> ; 14/11/2015 2219 00004F7B FEC8 <1> dec al 2220 00004F7D 8903 <1> mov [ebx], eax ; 000000FFh 2221 00004F7F FEC0 <1> inc al 2222 00004F81 48 <1> dec eax 2223 00004F82 894304 <1> mov [ebx+4], eax ; 0FFFFFFFFh 2224 00004F85 E957E1FFFF <1> jmp error 2225 <1> sysmnt_invd: 2226 <1> ; 12/02/2022 2227 00004F8A C705[4F650000]1C00- <1> mov dword [u.error], ERR_INV_FS ; 28 2227 00004F92 0000 <1> 2228 <1> ;'invalid fs/superblock !' error 2229 00004F94 30C0 <1> xor al, al 2230 00004F96 EBE3 <1> jmp short sysmnt_err4 2231 <1> 2232 <1> sysmnt_5: 2233 <1> ; 04/02/2022 (BugFix) 2234 <1> ; 14/11/2015 (Retro UNIX 386 v1 modification) 2235 <1> ; (Following check is needed to prevent mounting an 2236 <1> ; invalid valid file system (invalid super block). 2237 <1> ; 2238 00004F98 0FB603 <1> movzx eax, byte [ebx] ; device number 2239 00004F9B C0E002 <1> shl al, 2 ; 4*index 2240 00004F9E 8B88[625C0000] <1> mov ecx, [eax+drv.size] ; volume (fs) size 2241 <1> ;;shl ecx, 3 ; !!! 2242 <1> ; 04/02/2022 2243 00004FA4 C1E903 <1> shr ecx, 3 ; (8 sectors per 1 fbm byte) 2244 <1> ; ecx = number of free map bytes (required) 2245 <1> ;movzx edx, word [sb1+8] ; the 1st data word ('mount:') 2246 00004FA7 0FB75308 <1> movzx edx, word [ebx+8] ; the 1st data word (of the buffer) 2247 <1> ; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) ! 2248 <1> ;;movzx edx, word [sb1+4] ; the 1st data word ; !!! 2249 00004FAB 39D1 <1> cmp ecx, edx ; compare free map bits and volume size 2250 <1> ; (in sectors), if they are not equal 2251 <1> ; the disk to be mounted is an... 2252 00004FAD 75DB <1> jne short sysmnt_invd ; invalid disk ! 2253 <1> ; (which has not got a valid super block) 2254 <1> ; 2255 00004FAF C6430100 <1> mov byte [ebx+1], 0 2256 <1> ; jsr r0,ppoke / read in entire file system 2257 <1> ;sysmnt_6: ;1: 2258 <1> ;;cmp byte [sb1+1], 0 2259 <1> ; tstb sb1+1 / done reading? 2260 <1> ;;jna sysret 2261 <1> ;;call idle ; (wait for hardware interrupt) 2262 <1> ;;jmp short sysmnt_6 2263 <1> ;bne 1b / no, wait 2264 <1> ;br sysreta / yes 2265 00004FB3 E949E1FFFF <1> jmp sysret 2266 <1> 2267 <1> sysumount: ; / special dismount file system, 2268 <1> ; 15/05/2022 2269 <1> ; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19) 2270 <1> ; 04/02/2022 2271 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 2272 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 2273 <1> ; 2274 <1> ; 04/11/2013 2275 <1> ; 09/07/2013 2276 <1> ; 'sysumount' anounces to the system that the special file, 2277 <1> ; indicated as an argument is no longer contain a removable 2278 <1> ; file system. 'getspl' gets the device number of the special 2279 <1> ; file. If no file system was mounted on that device an error 2280 <1> ; occurs. 'mntd' and 'mnti' are cleared and control is passed 2281 <1> ; to 'sysret'. 2282 <1> ; 2283 <1> ; Calling sequence: 2284 <1> ; sysmount; special 2285 <1> ; Arguments: 2286 <1> ; special - special file to dismount (device) 2287 <1> ; 2288 <1> ; Inputs: - 2289 <1> ; Outputs: - 2290 <1> ; ............................................................... 2291 <1> ; 2292 <1> ; Retro UNIX 8086 v1 modification: 2293 <1> ; 'sysumount' system call has one argument; so, 2294 <1> ; * Single argument, special is pointed to by BX register 2295 <1> ; 2296 <1> 2297 <1> ;mov ax, 1 ; one/single argument, put argument in BX 2298 <1> ;call arg 2299 <1> ; jsr r0,arg; u.namep / point u.namep to special 2300 00004FB8 891D[18650000] <1> mov [u.namep], ebx 2301 00004FBE E87E000000 <1> call getspl 2302 <1> ; jsr r0,getspl / get the device number in r1 2303 <1> ;;; 2304 <1> ; 09/05/2022 - Erdogan Tan 2305 <1> ; (I have added [mnti] check because 2306 <1> ; retro unix device number of /dev/fd0 is 0 2307 <1> ; .. so, 'cmp al, [mdev]' is not enough 2308 <1> ; for dismounting /dev/fd0. sysumount system call would give 2309 <1> ; wrong cf=0 result while /dev/fd0 is not mounted.) 2310 00004FC3 66833D[E8640000]00 <1> cmp word [mnti], 0 2311 00004FCB 7665 <1> jna short sysmnt_err0 ; there is not a mounted device ! 2312 <1> ;;; 2313 <1> 2314 00004FCD 3A05[E7640000] <1> cmp al, [mdev] 2315 <1> ; cmp r1,mntd / is it equal to the last device mounted? 2316 00004FD3 755D <1> jne short sysmnt_err0 ; 'permission denied !' error 2317 <1> ;jne error 2318 <1> ; bne errora / no error 2319 00004FD5 30C0 <1> xor al, al ; ah = 0 2320 <1> sysumnt_0: ;1: 2321 <1> ; 04/02/2022 2322 <1> ;cmp [sb1+1], al ; 0 2323 <1> ; ; tstb sb1+1 / yes, is the device still doing I/O 2324 <1> ; ; / (inhibit bit set)? 2325 <1> ;jna short sysumnt_1 2326 <1> ; ; bne 1b / yes, wait 2327 <1> ;call idle ; (wait for hardware interrupt) 2328 <1> ;jmp short sysumnt_0 2329 <1> sysumnt_1: 2330 <1> ; 15/05/2022 2331 <1> ; change user's current directory to mounting directory 2332 <1> ; if it is on the mounted device (chdir back to root fs) 2333 00004FD7 3805[44650000] <1> cmp byte [u.cdrv], al ; 0 2334 00004FDD 7643 <1> jna short sysumnt_4 2335 <1> ;;; 2336 <1> ; 15/05/2022 2337 <1> ; It is needed to change the parent process's current 2338 <1> ; directory because shell runs (/etc/umount) 2339 <1> ; as child process. 2340 00004FDF 31DB <1> xor ebx, ebx 2341 00004FE1 8A1D[49650000] <1> mov bl, [u.uno] 2342 00004FE7 D0E3 <1> shl bl, 1 ; >= 2 .. <= 32 2343 00004FE9 81C3[32620000] <1> add ebx, p.ppid-2 2344 00004FEF 668B13 <1> mov dx, [ebx] ; process id of the parent [p.ppid] 2345 00004FF2 BE[14620000] <1> mov esi, p.pid 2346 00004FF7 29C9 <1> sub ecx, ecx 2347 00004FF9 B110 <1> mov cl, nproc ; 16 2348 <1> sysumnt_2: 2349 00004FFB 66AD <1> lodsw 2350 00004FFD 6639D0 <1> cmp ax, dx 2351 00005000 7402 <1> je short sysumnt_3 2352 00005002 E2F7 <1> loop sysumnt_2 2353 <1> sysumnt_3: 2354 00005004 31C0 <1> xor eax, eax 2355 00005006 81EE[14620000] <1> sub esi, p.pid 2356 0000500C D1E6 <1> shl esi, 1 2357 0000500E 8B9E[80620000] <1> mov ebx, [esi+p.upage-4] ; the parent's upage 2358 <1> ; ebx points to user (u) structure in upage 2359 00005014 668B15[E8640000] <1> mov dx, [mnti] 2360 <1> ;mov [u.cdir], dx 2361 <1> ;mov [u.cdrv], al ; 0 2362 0000501B 6689530C <1> mov [ebx+u.cdir-user], dx 2363 0000501F 88434C <1> mov [ebx+u.cdrv-user], al ; 0 2364 <1> ;;; 2365 <1> sysumnt_4: 2366 00005022 A2[E7640000] <1> mov [mdev], al ; 0 2367 <1> ; clr mntd / no, clear these 2368 00005027 66A3[E8640000] <1> mov [mnti], ax ; 0 2369 <1> ; clr mnti 2370 <1> 2371 <1> ;; 15/05/2022 2372 <1> ;mov [cdev], al ; 0 ; [u.cdrv] = 0 2373 <1> ;mov ax, dx ; [u.cdir] 2374 <1> ;call iget 2375 <1> 2376 0000502D E9CFE0FFFF <1> jmp sysret 2377 <1> ; br sysreta / return 2378 <1> 2379 <1> sysmnt_err0: 2380 00005032 C705[4F650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2380 0000503A 0000 <1> 2381 0000503C E9A0E0FFFF <1> jmp error 2382 <1> 2383 <1> getspl: ; / get device number from a special file name 2384 00005041 E89BEFFFFF <1> call namei 2385 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 2386 <1> ; ax = 0 -> file not found 2387 <1> ;jc sysmnt_err2 ; 'file not found !' error 2388 <1> ; 04/02/2022 2389 00005046 7305 <1> jnc short getspl_0 2390 00005048 E9C5FEFFFF <1> jmp sysmnt_err2 2391 <1> getspl_0: 2392 <1> ;jz error 2393 <1> ;jc error 2394 <1> ; jsr r0,namei / get the i-number of the special file 2395 <1> ; br errora / no such file 2396 0000504D 6683E803 <1> sub ax, 3 ; Retro UNIX 8086 v1 modification ! 2397 <1> ; i-number-3, 0 = fd0, 5 = hd3 2398 <1> ; sub $4,r1 / i-number-4 rk=1,tap=2+n 2399 00005051 72DF <1> jc short sysmnt_err0 ; 'permission denied !' error 2400 <1> ;jc error 2401 <1> ; ble errora / less than 0? yes, error 2402 00005053 6683F805 <1> cmp ax, 5 ; 2403 <1> ; cmp r1,$9. / greater than 9 tap 7 2404 <1> ;ja short sysmnt_err0 ; 'permission denied !' error 2405 <1> ;;ja error 2406 <1> ; ; bgt errora / yes, error 2407 <1> ; 04/02/2022 2408 00005057 7600 <1> jna short getspl_retn 2409 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 2410 <1> ;iopen_retn: 2411 <1> ; retn 2412 <1> ; rts r0 / return with device number in r1 2413 <1> ;sysmnt_err0: 2414 <1> ; mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2415 <1> ; jmp error 2416 <1> 2417 <1> getspl_retn: 2418 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 2419 <1> ; 04/02/2022 2420 <1> iopen_retn: 2421 00005059 C3 <1> retn 2422 <1> 2423 <1> iopen: 2424 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) 2425 <1> ; (Printer initialization) 2426 <1> ; 04/02/2022 2427 <1> ; 19/05/2015 2428 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2429 <1> ; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1) 2430 <1> ; 2431 <1> ; open file whose i-number is in r1 2432 <1> ; 2433 <1> ; INPUTS -> 2434 <1> ; r1 - inode number 2435 <1> ; OUTPUTS -> 2436 <1> ; file's inode in core 2437 <1> ; r1 - inode number (positive) 2438 <1> ; 2439 <1> ; ((AX = R1)) 2440 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 2441 <1> ; 2442 <1> ; / open file whose i-number is in r1 2443 0000505A F6C480 <1> test ah, 80h ; Bit 15 of AX 2444 <1> ; tst r1 / write or read access? 2445 0000505D 7568 <1> jnz short iopen_2 2446 <1> ; blt 2f / write, go to 2f 2447 0000505F B202 <1> mov dl, 2 ; read access 2448 00005061 E864F8FFFF <1> call access 2449 <1> ; jsr r0,access; 2 2450 <1> ; / get inode into core with read access 2451 <1> ; DL=2 2452 <1> iopen_0: 2453 00005066 6683F828 <1> cmp ax, 40 2454 <1> ; cmp r1,$40. / is it a special file 2455 0000506A 77ED <1> ja short iopen_retn 2456 <1> ; bgt 3f / no. 3f 2457 <1> ; 04/02/2022 2458 0000506C 50 <1> push eax 2459 <1> ;push ax 2460 <1> ; mov r1,-(sp) / yes, figure out 2461 0000506D 0FB6D8 <1> movzx ebx, al 2462 00005070 C0E302 <1> shl bl, 2 ; * 4 ; 04/02/2022 2463 <1> ;shl bx, 2 2464 <1> ; asl r1 2465 00005073 81C3[77500000] <1> add ebx, iopen_1 - 4 2466 00005079 FF23 <1> jmp dword [ebx] 2467 <1> ; jmp *1f-2(r1) / which one and transfer to it 2468 <1> iopen_1: ; 1: 2469 0000507B [DF500000] <1> dd otty ; tty, AX = 1 (runix) 2470 <1> ;otty / tty ; r1=2 2471 <1> ;oppt / ppt ; r1=4 2472 0000507F [97510000] <1> dd sret ; mem, AX = 2 (runix) 2473 <1> ;sret / mem ; r1=6 2474 <1> ;sret / rf0 2475 <1> ;sret / rk0 2476 <1> ;sret / tap0 2477 <1> ;sret / tap1 2478 <1> ;sret / tap2 2479 <1> ;sret / tap3 2480 <1> ;sret / tap4 2481 <1> ;sret / tap5 2482 <1> ;sret / tap6 2483 <1> ;sret / tap7 2484 00005083 [97510000] <1> dd sret ; fd0, AX = 3 (runix only) 2485 00005087 [97510000] <1> dd sret ; fd1, AX = 4 (runix only) 2486 0000508B [97510000] <1> dd sret ; hd0, AX = 5 (runix only) 2487 0000508F [97510000] <1> dd sret ; hd1, AX = 6 (runix only) 2488 00005093 [97510000] <1> dd sret ; hd2, AX = 7 (runix only) 2489 00005097 [97510000] <1> dd sret ; hd3, AX = 8 (runix only) 2490 <1> ;;dd error ; lpr, AX = 9 (error !) 2491 <1> ;dd sret ; lpr, AX = 9 (runix) 2492 <1> ; 13/06/2022 - (lpt_init) 2493 0000509B [63520000] <1> dd ejec ; lpr, AX = 9 (runix) 2494 0000509F [F0500000] <1> dd ocvt ; tty0, AX = 10 (runix) 2495 <1> ;ocvt / tty0 2496 000050A3 [F0500000] <1> dd ocvt ; tty1, AX = 11 (runix) 2497 <1> ;ocvt / tty1 2498 000050A7 [F0500000] <1> dd ocvt ; tty2, AX = 12 (runix) 2499 <1> ;ocvt / tty2 2500 000050AB [F0500000] <1> dd ocvt ; tty3, AX = 13 (runix) 2501 <1> ;ocvt / tty3 2502 000050AF [F0500000] <1> dd ocvt ; tty4, AX = 14 (runix) 2503 <1> ;ocvt / tty4 2504 000050B3 [F0500000] <1> dd ocvt ; tty5, AX = 15 (runix) 2505 <1> ;ocvt / tty5 2506 000050B7 [F0500000] <1> dd ocvt ; tty6, AX = 16 (runix) 2507 <1> ;ocvt / tty6 2508 000050BB [F0500000] <1> dd ocvt ; tty7, AX = 17 (runix) 2509 <1> ;ocvt / tty7 2510 000050BF [F0500000] <1> dd ocvt ; COM1, AX = 18 (runix only) 2511 <1> ;error / crd 2512 000050C3 [F0500000] <1> dd ocvt ; COM2, AX = 19 (runix only) 2513 <1> 2514 <1> iopen_2: ; 2: / check open write access 2515 000050C7 66F7D8 <1> neg ax 2516 <1> ; neg r1 / make inode number positive 2517 000050CA B201 <1> mov dl, 1 ; write access 2518 000050CC E8F9F7FFFF <1> call access 2519 <1> ; jsr r0,access; 1 / get inode in core 2520 <1> ; DL=1 2521 <1> ; 04/02/2022 2522 000050D1 F605[F5610000]40 <1> test byte [i.flgs+1], 40h 2523 <1> ;test word [i.flgs], 4000h ; Bit 14 : Directory flag 2524 <1> ; bit $40000,i.flgs / is it a directory? 2525 000050D8 748C <1> jz short iopen_0 2526 <1> ;mov [u.error], ERR_DIR_ACCESS 2527 <1> ;jmp error ; permission denied ! 2528 000050DA E953FFFFFF <1> jmp sysmnt_err0 2529 <1> ;;jnz error 2530 <1> ; bne 2f / yes, transfer (error) 2531 <1> ;;jmp short iopen_0 2532 <1> ;cmp ax, 40 2533 <1> ; cmp r1,$40. / no, is it a special file? 2534 <1> ;ja short iopen_2 2535 <1> ; bgt 3f / no, return 2536 <1> ;push ax 2537 <1> ; mov r1,-(sp) / yes 2538 <1> ;movzx ebx, al 2539 <1> ;shl bx, 1 2540 <1> ; asl r1 2541 <1> ;add ebx, ipen_3 - 2 2542 <1> ;jmp dword [ebx] 2543 <1> ; jmp *1f-2(r1) / figure out 2544 <1> ; / which special file it is and transfer 2545 <1> ;iopen_3: ; 1: 2546 <1> ; dd otty ; tty, AX = 1 (runix) 2547 <1> ;otty / tty ; r1=2 2548 <1> ;leadr / ppt ; r1=4 2549 <1> ; dd sret ; mem, AX = 2 (runix) 2550 <1> ;sret / mem ; r1=6 2551 <1> ;sret / rf0 2552 <1> ;sret / rk0 2553 <1> ;sret / tap0 2554 <1> ;sret / tap1 2555 <1> ;sret / tap2 2556 <1> ;sret / tap3 2557 <1> ;sret / tap4 2558 <1> ;sret / tap5 2559 <1> ;sret / tap6 2560 <1> ;sret / tap7 2561 <1> ; dd sret ; fd0, AX = 3 (runix only) 2562 <1> ; dd sret ; fd1, AX = 4 (runix only) 2563 <1> ; dd sret ; hd0, AX = 5 (runix only) 2564 <1> ; dd sret ; hd1, AX = 6 (runix only) 2565 <1> ; dd sret ; hd2, AX = 7 (runix only) 2566 <1> ; dd sret ; hd3, AX = 8 (runix only) 2567 <1> ; dd sret ; lpr, AX = 9 (runix) 2568 <1> ;dd ejec ; lpr, AX = 9 (runix) 2569 <1> ; dd sret ; tty0, AX = 10 (runix) 2570 <1> ;ocvt / tty0 2571 <1> ; dd sret ; tty1, AX = 11 (runix) 2572 <1> ;ocvt / tty1 2573 <1> ; dd sret ; tty2, AX = 12 (runix) 2574 <1> ;ocvt / tty2 2575 <1> ; dd sret ; tty3, AX = 13 (runix) 2576 <1> ;ocvt / tty3 2577 <1> ; dd sret ; tty4, AX = 14 (runix) 2578 <1> ;ocvt / tty4 2579 <1> ; dd sret ; tty5, AX = 15 (runix) 2580 <1> ;ocvt / tty5 2581 <1> ; dd sret ; tty6, AX = 16 (runix) 2582 <1> ;ocvt / tty6 2583 <1> ; dd sret ; tty7, AX = 17 (runix) 2584 <1> ;ocvt / tty7 2585 <1> ; dd ocvt ; COM1, AX = 18 (runix only) 2586 <1> ;/ ejec / lpr 2587 <1> ; dd ocvt ; COM2, AX = 19 (runix only) 2588 <1> 2589 <1> otty: ;/ open console tty for reading or writing 2590 <1> ; 03/03/2022 2591 <1> ; 02/03/2022 2592 <1> ; 27/02/2022 2593 <1> ; 23/02/2022 2594 <1> ; 22/02/2022 2595 <1> ; 04/02/2022 2596 <1> ; 16/11/2015 2597 <1> ; 12/11/2015 2598 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2599 <1> ; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1) 2600 <1> ; 16/07/2013 2601 <1> ; Retro UNIX 8086 v1 modification: 2602 <1> ; If a tty is open for read or write by 2603 <1> ; a process (u.uno), only same process can open 2604 <1> ; same tty to write or read (R->R&W or W->W&R). 2605 <1> ; 2606 <1> ; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty) 2607 <1> ; 2608 000050DF 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 2609 000050E6 8A83[53620000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2610 <1> ; 13/01/2014 2611 <1> ;jmp short ottyp 2612 <1> ; 23/02/2022 2613 000050EC 88C4 <1> mov ah, al 2614 000050EE EB06 <1> jmp short ottypc ; ah = al = console tty number 2615 <1> ocvt: 2616 000050F0 2C0A <1> sub al, 10 2617 <1> ; 04/02/2022 2618 000050F2 31DB <1> xor ebx, ebx 2619 <1> ottyp: 2620 <1> ; 23/02/2022 2621 000050F4 B4FF <1> mov ah, 0FFh 2622 <1> ottypc: 2623 <1> ; 03/03/2022 2624 <1> ; 23/02/2022 2625 <1> ; 22/02/2022 2626 <1> ; 12/02/2022 2627 <1> ; 04/02/2022 2628 <1> ; 16/11/2015 2629 <1> ; 12/11/2015 2630 <1> ; 18/05/2015 (32 bit modifications) 2631 <1> ; 06/12/2013 - 13/07/2014 2632 000050F6 88C6 <1> mov dh, al ; tty number 2633 <1> ;movzx ebx, al ; AL = tty number (0 to 9), AH = 0 2634 <1> ; 04/02/2022 2635 000050F8 88C3 <1> mov bl, al 2636 000050FA D0E3 <1> shl bl, 1 ; aligned to word 2637 <1> ; 26/01/2014 2638 000050FC 81C3[84610000] <1> add ebx, ttyl 2639 00005102 668B0B <1> mov cx, [ebx] 2640 <1> ; CL = lock value (0 or process number) 2641 <1> ; CH = open count 2642 00005105 20C9 <1> and cl, cl 2643 <1> ; 13/01/2014 2644 <1> ;jz short otty_ret 2645 <1> ; 04/02/2022 2646 00005107 7447 <1> jz short ottys_0 2647 <1> ; 2648 <1> ; 16/11/2015 2649 00005109 3A0D[49650000] <1> cmp cl, [u.uno] 2650 0000510F 746E <1> je short ottys_3 2651 <1> ; 2652 <1> ; 23/02/2022 2653 <1> ; (is it the console tty of the current process?) 2654 <1> ; ((fast check/permit for console tty open function)) 2655 00005111 38E0 <1> cmp al, ah ; cmp dh, ah 2656 00005113 746A <1> je short ottys_3 ; bypass parent process check 2657 <1> ; 2658 <1> ; 22/02/2022 2659 <1> ;movzx ebx, cl ; the process which has locked the tty 2660 <1> ;shl bl, 1 2661 <1> ;mov ax, [ebx+p.pid-2] 2662 <1> ;;movzx ebx, byte [u.uno] 2663 <1> ;mov bl, [u.uno] 2664 <1> ;shl bl, 1 2665 <1> ;cmp ax, [ebx+p.ppid-2] 2666 <1> ;je short ottys_3 ; 16/11/2015 2667 <1> ; 22/02/2022 (BugFix) ; * 2668 00005115 0FB6F1 <1> movzx esi, cl ; the process which has locked the tty 2669 00005118 D1E6 <1> shl esi, 1 2670 0000511A 668B86[12620000] <1> mov ax, [esi+p.pid-2] 2671 00005121 96 <1> xchg esi, eax 2672 00005122 A0[49650000] <1> mov al, [u.uno] 2673 00005127 D0E0 <1> shl al, 1 2674 00005129 663BB0[32620000] <1> cmp si, [eax+p.ppid-2] 2675 00005130 744D <1> je short ottys_3 ; * 2676 <1> ; 23/02/2022 2677 <1> ; check console tty of the process 2678 <1> ; (open permission must be given if the -requested- tty is 2679 <1> ; console tty of current process) 2680 00005132 D0E8 <1> shr al, 1 2681 00005134 38B0[53620000] <1> cmp [eax+p.ttyc-1], dh ; console tty ? 2682 0000513A 7443 <1> je short ottys_3 2683 <1> ; 2684 <1> ; the tty is locked by another process 2685 <1> ; except the parent process (p.ppid) 2686 <1> ; 2687 <1> ; 09/02/2022 2688 <1> ;mov dword [u.error], ERR_DEV_ACCESS 2689 <1> ; ; permission denied ! error 2690 <1> otty_err: ; 13/01/2014 2691 <1> ;or dl, dl ; DL = 0 -> called by sysstty 2692 <1> ;;jnz error 2693 <1> ; 04/02/2022 2694 <1> ;jz short otty_stc_retn 2695 <1> ;jmp error 2696 <1> ; 12/02/2022 2697 0000513C 80FA01 <1> cmp dl, 1 ; dl = 0 ? 2698 0000513F 7257 <1> jb short otty_retn ; yes, cf=1, called by sysstty 2699 <1> ; iopen (dl=1 or dl=2) 2700 00005141 C705[4F650000]0B00- <1> mov dword [u.error], ERR_DEV_ACCESS 2700 00005149 0000 <1> 2701 <1> ; permission denied ! error 2702 0000514B E991DFFFFF <1> jmp error 2703 <1> ;otty_stc_retn: 2704 <1> ;stc 2705 <1> ;retn 2706 <1> ottys_0: 2707 <1> ; 04/02/2022 2708 <1> otty_ret: 2709 <1> ; 13/01/2014 2710 00005150 80FE07 <1> cmp dh, 7 2711 00005153 7624 <1> jna short ottys_2 2712 <1> ; 16/11/2015 2713 <1> com_port_check: 2714 00005155 BE[A2610000] <1> mov esi, com1p 2715 0000515A 80FE08 <1> cmp dh, 8 ; COM1 (tty8) ? 2716 0000515D 7601 <1> jna short ottys_1 ; yes, it is COM1 2717 0000515F 46 <1> inc esi ; no, it is COM2 (tty9) 2718 <1> ottys_1: 2719 <1> ; 12/11/2015 2720 00005160 803E00 <1> cmp byte [esi], 0 ; E3h (or 23h) 2721 00005163 7714 <1> ja short com_port_ready 2722 <1> ; 2723 <1> ; 12/02/2022 2724 00005165 80FA01 <1> cmp dl, 1 ; dl = 0 ? 2725 00005168 722E <1> jb short otty_retn ; yes, cf=1, called by sysstty 2726 0000516A C705[4F650000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY 2726 00005172 0000 <1> 2727 <1> ; device not ready ! error 2728 <1> ;jmp short otty_err 2729 00005174 E968DFFFFF <1> jmp error 2730 <1> com_port_ready: 2731 <1> ottys_2: 2732 <1> ; 02/03/2022 2733 <1> ;or cl, cl ; cl = lock/owner, ch = open count 2734 <1> ;jnz short ottys_3 2735 00005179 8A0D[49650000] <1> mov cl, [u.uno] 2736 <1> ottys_3: 2737 0000517F FEC5 <1> inc ch 2738 00005181 66890B <1> mov [ebx], cx ; set tty lock again 2739 <1> ; 06/12/2013 2740 00005184 FEC6 <1> inc dh ; tty number + 1 2741 00005186 BB[30650000] <1> mov ebx, u.ttyp 2742 <1> ; 13/01/2014 2743 0000518B F6C202 <1> test dl, 2 ; open for read sign 2744 0000518E 7501 <1> jnz short ottys_4 2745 00005190 43 <1> inc ebx 2746 <1> ottys_4: 2747 <1> ; Set 'u.ttyp' ('the recent TTY') value 2748 00005191 8833 <1> mov [ebx], dh ; tty number + 1 2749 <1> ; 27/02/2022 2750 00005193 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 2751 00005195 7401 <1> jz short otty_retn ; 03/03/2022 2752 <1> sret: 2753 <1> ;pop ax 2754 <1> ; 04/02/2022 2755 00005197 58 <1> pop eax 2756 <1> otty_retn: ; 12/02/2022 2757 <1> iclose_retn: 2758 00005198 C3 <1> retn 2759 <1> 2760 <1> ; 2761 <1> ; Original UNIX v1 'otty' routine: 2762 <1> ; 2763 <1> ;mov $100,*$tks / set interrupt enable bit (zero others) in 2764 <1> ; / reader status reg 2765 <1> ;mov $100,*$tps / set interrupt enable bit (zero others) in 2766 <1> ; / punch status reg 2767 <1> ;mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the 2768 <1> ; / console tty buffer 2769 <1> ;incb (r5) / increment the count of processes that opened the 2770 <1> ; / console tty 2771 <1> ;tst u.ttyp / is there a process control tty (i.e., has a tty 2772 <1> ; / buffer header 2773 <1> ;bne sret / address been loaded into u.ttyp yet)? yes, branch 2774 <1> ;mov r5,u.ttyp / no, make the console tty the process control 2775 <1> ; / tty 2776 <1> ;br sret / ? 2777 <1> ;sret: 2778 <1> ; clr *$ps / set processor priority to zero 2779 <1> ; pop ax 2780 <1> ; mov (sp)+,r1 / pop stack to r1 2781 <1> ;3: 2782 <1> ; retn 2783 <1> ; rts r0 2784 <1> 2785 <1> ;ocvt: ; < open tty > 2786 <1> ; 13/01/2014 2787 <1> ; 06/12/2013 (major modification: p.ttyc, u.ttyp) 2788 <1> ; 24/09/2013 consistency check -> ok 2789 <1> ; 16/09/2013 2790 <1> ; 03/09/2013 2791 <1> ; 27/08/2013 2792 <1> ; 16/08/2013 2793 <1> ; 16/07/2013 2794 <1> ; 27/05/2013 2795 <1> ; 21/05/2013 2796 <1> ; 2797 <1> ; Retro UNIX 8086 v1 modification ! 2798 <1> ; 2799 <1> ; In original UNIX v1, 'ocvt' routine 2800 <1> ; (exactly different than this one) 2801 <1> ; was in 'u9.s' file. 2802 <1> ; 2803 <1> ; 16/07/2013 2804 <1> ; Retro UNIX 8086 v1 modification: 2805 <1> ; If a tty is open for read or write by 2806 <1> ; a process (u.uno), only same process can open 2807 <1> ; same tty to write or read (R->R&W or W->W&R). 2808 <1> ; 2809 <1> ; INPUT: DL=2 for Read DL=1 for Write 2810 <1> 2811 <1> ; 16/09/2013 2812 <1> ; sub al, 10 2813 <1> 2814 <1> ; 06/12/2013 2815 <1> ;cmp al, 7 2816 <1> ;jna short ottyp 2817 <1> ; 13/01/2014 2818 <1> ;jmp short ottyp 2819 <1> 2820 <1> 2821 <1> ;oppt: / open paper tape for reading or writing 2822 <1> ; mov $100,*$prs / set reader interrupt enable bit 2823 <1> ; tstb pptiflg / is file already open 2824 <1> ; bne 2f / yes, branch 2825 <1> ;1: 2826 <1> ; mov $240,*$ps / no, set processor priority to 5 2827 <1> ; jsr r0,getc; 2 / remove all entries in clist 2828 <1> ; br .+4 / for paper tape input and place in free list 2829 <1> ; br 1b 2830 <1> ; movb $2,pptiflg / set pptiflg to indicate file just open 2831 <1> ; movb $10.,toutt+1 / place 10 in paper tape input tout entry 2832 <1> ; br sret 2833 <1> ;2: 2834 <1> ; jmp error / file already open 2835 <1> 2836 <1> iclose: 2837 <1> ; 04/02/2022 2838 <1> ; 19/05/2015 2839 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2840 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 2841 <1> ; 2842 <1> ; close file whose i-number is in r1 2843 <1> ; 2844 <1> ; INPUTS -> 2845 <1> ; r1 - inode number 2846 <1> ; OUTPUTS -> 2847 <1> ; file's inode in core 2848 <1> ; r1 - inode number (positive) 2849 <1> ; 2850 <1> ; ((AX = R1)) 2851 <1> ; ((Modified registers: -ebx-, edx)) 2852 <1> ; 2853 <1> ;/ close file whose i-number is in r1 2854 00005199 B202 <1> mov dl, 2 ; 12/01/2014 2855 0000519B F6C480 <1> test ah, 80h ; Bit 15 of AX 2856 <1> ; tst r1 / test i-number 2857 <1> ;jnz short iclose_2 2858 <1> ; blt 2f / if neg., branch 2859 0000519E 7405 <1> jz short iclose_0 ; 30/07/2013 2860 <1> ; 16/07/2013 2861 000051A0 66F7D8 <1> neg ax ; make it positive 2862 <1> ; 12/01/2014 2863 000051A3 FECA <1> dec dl ; dl = 1 (open for write) 2864 <1> iclose_0: 2865 000051A5 6683F828 <1> cmp ax, 40 2866 <1> ; cmp r1,$40. / is it a special file 2867 000051A9 77ED <1> ja short iclose_retn ; 13/01/2014 2868 <1> ; bgt 3b / no, return 2869 <1> ; 12/01/2014 2870 <1> ; DL=2 -> special file was opened for reading 2871 <1> ; DL=1 -> special file was opened for writing 2872 <1> ; 04/02/2022 2873 000051AB 50 <1> push eax 2874 <1> ;push ax 2875 <1> ; mov r1,-(sp) / yes, save r1 on stack 2876 000051AC 0FB6D8 <1> movzx ebx, al 2877 <1> ; 04/02/2022 2878 000051AF C0E302 <1> shl bl, 2 2879 <1> ;shl bx, 2 2880 <1> ; asl r1 2881 000051B2 81C3[B6510000] <1> add ebx, iclose_1 - 4 2882 000051B8 FF23 <1> jmp dword [ebx] 2883 <1> ; jmp *1f-2(r1) / compute jump address and transfer 2884 <1> iclose_1 : 2885 000051BA [06520000] <1> dd ctty ; tty, AX = 1 (runix) 2886 000051BE [61520000] <1> dd cret ; mem, AX = 2 (runix) 2887 000051C2 [61520000] <1> dd cret ; fd0, AX = 3 (runix only) 2888 000051C6 [61520000] <1> dd cret ; fd1, AX = 4 (runix only) 2889 000051CA [61520000] <1> dd cret ; hd0, AX = 5 (runix only) 2890 000051CE [61520000] <1> dd cret ; hd1, AX = 6 (runix only) 2891 000051D2 [61520000] <1> dd cret ; hd2, AX = 7 (runix only) 2892 000051D6 [61520000] <1> dd cret ; hd3, AX = 8 (runix only) 2893 000051DA [61520000] <1> dd cret ; lpr, AX = 9 (runix) 2894 <1> ;dd error; lpr, AX = 9 (error !) 2895 <1> ;;dd offset ejec ;;lpr, AX = 9 2896 000051DE [15520000] <1> dd ccvt ; tty0, AX = 10 (runix) 2897 000051E2 [15520000] <1> dd ccvt ; tty1, AX = 11 (runix) 2898 000051E6 [15520000] <1> dd ccvt ; tty2, AX = 12 (runix) 2899 000051EA [15520000] <1> dd ccvt ; tty3, AX = 13 (runix) 2900 000051EE [15520000] <1> dd ccvt ; tty4, AX = 14 (runix) 2901 000051F2 [15520000] <1> dd ccvt ; tty5, AX = 15 (runix) 2902 000051F6 [15520000] <1> dd ccvt ; tty6, AX = 16 (runix) 2903 000051FA [15520000] <1> dd ccvt ; tty7, AX = 17 (runix) 2904 000051FE [15520000] <1> dd ccvt ; COM1, AX = 18 (runix only) 2905 00005202 [15520000] <1> dd ccvt ; COM2, AX = 19 (runix only) 2906 <1> 2907 <1> ; 1: 2908 <1> ; ctty / tty 2909 <1> ; cppt / ppt 2910 <1> ; sret / mem 2911 <1> ; sret / rf0 2912 <1> ; sret / rk0 2913 <1> ; sret / tap0 2914 <1> ; sret / tap1 2915 <1> ; sret / tap2 2916 <1> ; sret / tap3 2917 <1> ; sret / tap4 2918 <1> ; sret / tap5 2919 <1> ; sret / tap6 2920 <1> ; sret / tap7 2921 <1> ; ccvt / tty0 2922 <1> ; ccvt / tty1 2923 <1> ; ccvt / tty2 2924 <1> ; ccvt / tty3 2925 <1> ; ccvt / tty4 2926 <1> ; ccvt / tty5 2927 <1> ; ccvt / tty6 2928 <1> ; ccvt / tty7 2929 <1> ; error / crd 2930 <1> 2931 <1> ;iclose_2: ; 2: / negative i-number 2932 <1> ;neg ax 2933 <1> ;neg r1 / make it positive 2934 <1> ;cmp ax, 40 2935 <1> ;cmp r1,$40. / is it a special file? 2936 <1> ;ja short @b 2937 <1> ;bgt 3b / no. return 2938 <1> ;push ax 2939 <1> ;mov r1,-(sp) 2940 <1> ;movzx ebx, al 2941 <1> ;shl bx, 1 2942 <1> ;asl r1 / yes. compute jump address and transfer 2943 <1> ;add ebx, iclose_3 - 2 2944 <1> ;jmp dword [ebx] 2945 <1> ;jmp *1f-2(r1) / figure out 2946 <1> ;iclose_3: 2947 <1> ;dd ctty ; tty, AX = 1 (runix) 2948 <1> ;dd sret ; mem, AX = 2 (runix) 2949 <1> ;dd sret ; fd0, AX = 3 (runix only) 2950 <1> ;dd sret ; fd1, AX = 4 (runix only) 2951 <1> ;dd sret ; hd0, AX = 5 (runix only) 2952 <1> ;dd sret ; hd1, AX = 6 (runix only) 2953 <1> ;dd sret ; hd2, AX = 7 (runix only) 2954 <1> ;dd sret ; hd3, AX = 8 (runix only) 2955 <1> ;dd sret ; lpr, AX = 9 2956 <1> ;dd ejec ; lpr, AX = 9 (runix) 2957 <1> ;dd ccvt ; tty0, AX = 10 (runix) 2958 <1> ;dd ccvt ; tty1, AX = 11 (runix) 2959 <1> ;dd ccvt ; tty2, AX = 12 (runix) 2960 <1> ;dd ccvt ; tty3, AX = 13 (runix) 2961 <1> ;dd ccvt ; tty4, AX = 14 (runix) 2962 <1> ;dd ccvt ; tty5, AX = 15 (runix) 2963 <1> ;dd ccvt ; tty6, AX = 16 (runix) 2964 <1> ;dd ccvt ; tty7, AX = 17 (runix) 2965 <1> ;dd ccvt ; COM1, AX = 18 (runix only) 2966 <1> ;dd ccvt ; COM2, AX = 19 (runix only) 2967 <1> 2968 <1> ;1: 2969 <1> ; ctty / tty 2970 <1> ; leadr / ppt 2971 <1> ; sret / mem 2972 <1> ; sret / rf0 2973 <1> ; sret / rk0 2974 <1> ; sret / tap0 2975 <1> ; sret / tap1 2976 <1> ; sret / tap2 2977 <1> ; sret / tap3 2978 <1> ; sret / tap4 2979 <1> ; sret / tap5 2980 <1> ; sret / tap6 2981 <1> ; sret / tap7 2982 <1> ; ccvt / tty0 2983 <1> ; ccvt / tty1 2984 <1> ; ccvt / tty2 2985 <1> ; ccvt / tty3 2986 <1> ; ccvt / tty4 2987 <1> ; ccvt / tty5 2988 <1> ; ccvt / tty6 2989 <1> ; ccvt / tty7 2990 <1> ;/ ejec / lpr 2991 <1> 2992 <1> ctty: ; / close console tty 2993 <1> ; 25/02/2022 2994 <1> ; 12/02/2022 2995 <1> ; 05/02/2022 2996 <1> ; 04/02/2022 2997 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2998 <1> ; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1) 2999 <1> ; 3000 <1> ; Retro UNIX 8086 v1 modification ! 3001 <1> ; (DL = 2 -> it is open for reading) 3002 <1> ; (DL = 1 -> it is open for writing) 3003 <1> ; (DL = 0 -> it is open for sysstty system call) 3004 <1> ; 3005 <1> ; 06/12/2013 3006 00005206 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 3007 0000520D 8A83[53620000] <1> mov al, [ebx+p.ttyc-1] 3008 <1> ; 13/01/2014 3009 <1> ;jmp short cttyp 3010 <1> ; 05/02/2022 3011 00005213 EB04 <1> jmp short ctty_0 3012 <1> ccvt: 3013 00005215 2C0A <1> sub al, 10 3014 <1> cttyp: ; (call from sysstty) 3015 <1> ; 08/01/2022 3016 00005217 31DB <1> xor ebx, ebx 3017 <1> ctty_0: 3018 <1> ; 18/05/2015 (32 bit modifications) 3019 <1> ; 16/08/2013 - 26/01/2014 3020 <1> ;movzx ebx, al ; tty number (0 to 9) 3021 <1> ; 04/02/2022 3022 00005219 88C3 <1> mov bl, al 3023 0000521B D0E3 <1> shl bl, 1 ; aligned to word 3024 <1> ; 26/01/2014 3025 0000521D 81C3[84610000] <1> add ebx, ttyl 3026 00005223 88C6 <1> mov dh, al ; tty number 3027 00005225 668B03 <1> mov ax, [ebx] 3028 <1> ; AL = lock value (0 or process number) 3029 <1> ; AH = open count 3030 00005228 20E4 <1> and ah, ah 3031 0000522A 7514 <1> jnz short ctty_ret 3032 <1> ; 12/02/2022 3033 0000522C 80FA01 <1> cmp dl, 1 ; DL = 0 -> called by sysstty 3034 0000522F 7231 <1> jb short ctty_stc_retn ; cf=1 3035 <1> ; iclose (dl=1 or dl=2) 3036 00005231 C705[4F650000]0A00- <1> mov dword [u.error], ERR_DEV_NOT_OPEN 3036 00005239 0000 <1> 3037 <1> ; device not open ! error 3038 <1> ;jmp short ctty_err ; open count = 0, it is not open ! 3039 0000523B E9A1DEFFFF <1> jmp error 3040 <1> ; 26/01/2014 3041 <1> ctty_ret: 3042 00005240 FECC <1> dec ah ; decrease open count 3043 00005242 7502 <1> jnz short ctty_1 3044 00005244 30C0 <1> xor al, al ; unlock/free tty 3045 <1> ctty_1: 3046 00005246 668903 <1> mov [ebx], ax ; close tty instance 3047 <1> ; 3048 00005249 BB[30650000] <1> mov ebx, u.ttyp 3049 <1> ;test dl, 1 ; open for write sign 3050 <1> ;jz short ctty_2 3051 <1> ; 25/02/2022 3052 0000524E F6C202 <1> test dl, 2 ; open for read sign 3053 00005251 7501 <1> jnz short ctty_2 3054 00005253 43 <1> inc ebx 3055 <1> ctty_2: 3056 00005254 FEC6 <1> inc dh ; tty number + 1 3057 00005256 3A33 <1> cmp dh, [ebx] 3058 <1> ;jne short cret 3059 00005258 7503 <1> jne short ctty_3 ; 12/02/2022 3060 <1> ; Reset/Clear 'u.ttyp' ('the recent TTY') value 3061 0000525A C60300 <1> mov byte [ebx], 0 3062 <1> ctty_3: 3063 <1> ; 12/02/2022 3064 0000525D 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 3065 0000525F 7401 <1> jz short ctty_4 3066 <1> cret: 3067 <1> ;pop ax 3068 <1> ; 05/02/2022 3069 00005261 58 <1> pop eax 3070 <1> ctty_stc_retn: ; 12/02/2022 3071 <1> ctty_4: 3072 00005262 C3 <1> retn 3073 <1> 3074 <1> ;ctty_err: ; 13/01/2014 3075 <1> ; or dl, dl ; DL = 0 -> called by sysstty 3076 <1> ; jnz error 3077 <1> ; stc 3078 <1> ; retn 3079 <1> 3080 <1> ; Original UNIX v1 'ctty' routine: 3081 <1> ; 3082 <1> ;mov tty+[ntty*8]-8+6,r5 3083 <1> ; ;/ point r5 to the console tty buffer 3084 <1> ;decb (r5) / dec number of processes using console tty 3085 <1> ;br sret / return via sret 3086 <1> 3087 <1> ;ccvt: ; < close tty > 3088 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 3089 <1> ; 3090 <1> ; Retro UNIX 8086 v1 modification ! 3091 <1> ; 3092 <1> ; In original UNIX v1, 'ccvt' routine 3093 <1> ; (exactly different than this one) 3094 <1> ; was in 'u9.s' file. 3095 <1> ; 3096 <1> ; DL = 2 -> it is open for reading 3097 <1> ; DL = 1 -> it is open for writing 3098 <1> ; 3099 <1> ; 17/09/2013 3100 <1> ;sub al, 10 3101 <1> ;cmp al, 7 3102 <1> ;jna short cttyp 3103 <1> ; 13/01/2014 3104 <1> ;jmp short cttyp 3105 <1> 3106 <1> ;cppt: / close paper tape 3107 <1> ; clrb pptiflg / set pptiflg to indicate file not open 3108 <1> ;1: 3109 <1> ; mov $240,*$ps /set process or priority to 5 3110 <1> ; jsr r0,getc; 2 / remove all ppt input entries from clist 3111 <1> ; / and assign to free list 3112 <1> ; br sret 3113 <1> ; br 1b 3114 <1> 3115 <1> ;ejec: 3116 <1> ; jmp error 3117 <1> ;/ejec: 3118 <1> ;/ mov $100,*$lps / set line printer interrupt enable bit 3119 <1> ;/ mov $14,r1 / 'form feed' character in r1 (new page). 3120 <1> ;/ jsr r0,lptoc / space the printer to a new page 3121 <1> ;/ br sret / return to caller via 'sret' 3122 <1> 3123 <1> ejec: 3124 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kewrnel v0.2.0.20) 3125 <1> ; - Printer Initialization 3126 <1> lpt_init: 3127 <1> ; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 3128 <1> ; 3129 <1> ; Default printer port: 378h ; LPT1 3130 <1> 3131 00005263 B401 <1> mov ah, 1 ; INITIALIZE THE PRINTER PORT 3132 <1> ;call int17h 3133 00005265 E8BDFAFFFF <1> call PRNOP 3134 0000526A 7414 <1> jz short lpt_init_ok 3135 <1> 3136 <1> ; replace error code with 'device not ready' error 3137 <1> ; (this may be better for 'sysopen') 3138 0000526C B80F000000 <1> mov eax, ERR_PRN_NOT_RDY 3139 00005271 A3[4F650000] <1> mov [u.error], eax 3140 <1> ;jmp sysret ; (may be) ? ([u.r0] = file descriptor) 3141 00005276 A3[00650000] <1> mov [u.r0], eax 3142 0000527B E961DEFFFF <1> jmp error ; (better) 3143 <1> 3144 <1> lpt_init_ok: 3145 <1> ;jmp short cret 3146 00005280 58 <1> pop eax ; inode number 3147 00005281 C3 <1> retn 3148 <1> 2059 %include 'u8.s' ; 11/06/2015 2060 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYS8.INC 2061 <1> ; Last Modification: 19/07/2022 2062 <1> ; ---------------------------------------------------------------------------- 2063 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2064 <1> ; (v0.1 - Beginning: 11/07/2012) 2065 <1> ; 2066 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2067 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2068 <1> ; 2069 <1> ; 2070 <1> ; 2071 <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s 2072 <1> ; 2073 <1> ; **************************************************************************** 2074 <1> ; 24/10/2015 2075 <1> 2076 <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2077 <1> ;--------------------------------------------------------------------- 2078 <1> ; Buffer Header: -8 bytes- 2079 <1> ; word 1 - byte 0 - device (disk index) number (0 to 5) 2080 <1> ; byte 1 - status bits 2081 <1> ; bit 0 - valid buffer bit (1 = valid, 0 = invalid, new) 2082 <1> ; bit 1 - write bit (also modified bit) 2083 <1> ; bit 2 - read bit 2084 <1> ; bit 3 to bit 7 are not used 2085 <1> ; word 2 - byte & byte 3 not used 2086 <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7: 2087 <1> ; physical block/sector address (32 bit LBA) 2088 <1> ;--------------------------------------------------------------------- 2089 <1> 2090 <1> ;; I/O Buffer - Retro UNIX 386 v1 modification 2091 <1> ;; (8+512 bytes, 8 bytes header, 512 bytes data) 2092 <1> ;; Word 1, byte 0 = device id 2093 <1> ;; Word 1, byte 1 = status bits (bits 8 to 15) 2094 <1> ;; bit 9 = write bit 2095 <1> ;; bit 10 = read bit 2096 <1> ;; bit 12 = waiting to write bit 2097 <1> ;; bit 13 = waiting to read bit 2098 <1> ;; bit 15 = inhibit bit 2099 <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015) 2100 <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 2101 <1> ;; (In fact, it is 32 bit LBA for Retro UNIX 386 v1) 2102 <1> ;; 2103 <1> ;; I/O Buffer ((8+512 bytes in original Unix v1)) 2104 <1> ;; ((4+512 bytes in Retro UNIX 8086 v1)) 2105 <1> ;; 2106 <1> ;; I/O Queue Entry (of original UNIX operating system v1) 2107 <1> ;; Word 1, Byte 0 = device id 2108 <1> ;; Word 1, Byte 1 = (bits 8 to 15) 2109 <1> ;; bit 9 = write bit 2110 <1> ;; bit 10 = read bit 2111 <1> ;; bit 12 = waiting to write bit 2112 <1> ;; bit 13 = waiting to read bit 2113 <1> ;; bit 15 = inhibit bit 2114 <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) 2115 <1> ;; 2116 <1> ;; Original UNIX v1 -> 2117 <1> ;; Word 3 = number of words in buffer (=256) 2118 <1> ;; Original UNIX v1 -> 2119 <1> ;; Word 4 = bus address (addr of first word of data buffer) 2120 <1> ;; 2121 <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! 2122 <1> ;; 2123 <1> ;; Device IDs (of Retro Unix 8086 v1) 2124 <1> ;; 0 = fd0 2125 <1> ;; 1 = fd1 2126 <1> ;; 2 = hd0 2127 <1> ;; 3 = hd1 2128 <1> ;; 4 = hd2 2129 <1> ;; 5 = hd3 2130 <1> 2131 <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015 2132 <1> 2133 <1> ; 04/02/2022 2134 <1> rfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2135 <1> ; 26/04/2013 2136 <1> ; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2137 <1> ;sub ax, 3 ; zero based device number (Floppy disk) 2138 <1> ;jmp short bread ; **** returns to routine that called readi 2139 <1> 2140 <1> ; 04/02/2022 2141 <1> rhd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2142 <1> ; 26/04/2013 2143 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2144 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2145 <1> ;jmp short bread ; **** returns to routine that called readi 2146 <1> 2147 <1> bread: 2148 <1> ; 19/07/2022 2149 <1> ; 14/07/2022 2150 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2151 <1> ; 12/02/2022 2152 <1> ; 04/02/2022 2153 <1> ; 14/07/2015 2154 <1> ; 10/07/2015 2155 <1> ; 09/06/2015 2156 <1> ; 07/06/2015 (Retro UNIX 386 v1 - Beginning) 2157 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2158 <1> ; 2159 <1> ; / read a block from a block structured device 2160 <1> ; 2161 <1> ; INPUTS -> 2162 <1> ; [u.fofp] points to the block number 2163 <1> ; ECX = maximum block number allowed on device 2164 <1> ; ; that was an arg to bread, in original Unix v1, but 2165 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 2166 <1> ; [u.count] number of bytes to read in 2167 <1> ; OUTPUTS -> 2168 <1> ; [u.base] starting address of data block or blocks in user area 2169 <1> ; [u.fofp] points to next consecutive block to be read 2170 <1> ; 2171 <1> ; ((Modified registers: EAX, EDX, ECX, EBX, ESI, EDI)) 2172 <1> ; 2173 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if read 2174 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 2175 <1> ; is increased by 1. For example: If user/program request 2176 <1> ; to read 16 bytes in current block, 'sys read' increases 2177 <1> ; the next block number just as 512 byte reading is done. 2178 <1> ; This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 2179 <1> ; for user (u) structure compatibility (because 16 bit is not 2180 <1> ; enough to keep byte position/offset of the disk), this 2181 <1> ; defect will not be corrected, user/program must request 2182 <1> ; 512 byte read per every 'sys read' call to block devices 2183 <1> ; for achieving correct result. In future version(s), 2184 <1> ; this defect will be corrected by using different 2185 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 2186 <1> 2187 <1> ; jsr r0,tstdeve / error on special file I/O 2188 <1> ; / (only works on tape) 2189 <1> ; mov *u.fofp,r1 / move block number to r1 2190 <1> ; mov $2.-cold,-(sp) / "2-cold" to stack 2191 <1> ;1: 2192 <1> ; cmp r1,(r0) / is this block # greater than or equal to 2193 <1> ; / maximum block # allowed on device 2194 <1> ; jnb short @f 2195 <1> ; bhis 1f / yes, 1f (error) 2196 <1> ; mov r1,-(sp) / no, put block # on stack 2197 <1> ; jsr r0,preread / read in the block into an I/O buffer 2198 <1> ; mov (sp)+,r1 / return block # to r1 2199 <1> ; inc r1 / bump block # to next consecutive block 2200 <1> ; dec (sp) / "2-1-cold" on stack 2201 <1> ; bgt 1b / 2-1-cold = 0? No, go back and read in next block 2202 <1> ;1: 2203 <1> ; tst (sp)+ / yes, pop stack to clear off cold calculation 2204 <1> ;push ecx ; ** 2205 <1> ;26/04/2013 2206 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 2207 00005282 2C03 <1> sub al, 3 2208 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 2209 00005284 A2[62650000] <1> mov [u.brwdev], al 2210 <1> ; 09/06/2015 2211 <1> ;movzx ebx, al 2212 <1> ;mov ecx, [ebx+drv.size] ; disk size (in sectors) 2213 <1> ; 04/02/2022 (BugFix) 2214 00005289 C0E002 <1> shl al, 2 ; * 4 2215 0000528C 8B88[625C0000] <1> mov ecx, [eax+drv.size] ; disk size (in sectors) 2216 <1> bread_0: 2217 00005292 51 <1> push ecx ; ** ; 09/06/2015 2218 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 2219 <1> ; [u.fofp] points to byte position in disk, not sector/block ! 2220 00005293 8B1D[10650000] <1> mov ebx, [u.fofp] 2221 00005299 8B03 <1> mov eax, [ebx] 2222 0000529B C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 2223 <1> ; mov *u.fofp,r1 / restore r1 to initial value of the 2224 <1> ; / block # 2225 0000529E 39C8 <1> cmp eax, ecx 2226 <1> ; cmp r1,(r0)+ / block # greater than or equal to maximum 2227 <1> ; / block number allowed 2228 <1> ;jnb error ; 18/04/2013 2229 <1> ; bhis error10 / yes, error 2230 <1> ; 12/02/2022 2231 <1> ;jb short bread_1 2232 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2233 <1> ;jmp error 2234 000052A0 7346 <1> jnb short brw_oov_err ; 'out of volume' 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 000052A2 BF[62650000] <1> mov edi, u.brwdev ; block device number for direct I/O 2242 000052A7 E8DC010000 <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 000052AC 7411 <1> jz short bread_2 ; Retro UNIX 8086 v1 modification 2249 <1> ; br 1f / branch if block already in a I/O buffer 2250 000052AE 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 000052B3 E8A8010000 <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> ; 12/02/2022 2259 000052B8 7305 <1> jnc short bread_2 2260 000052BA E919010000 <1> jmp dskrd_err 2261 <1> 2262 <1> ;; return from preread 2263 <1> bread_2: 2264 <1> ; 14/07/2022 2265 <1> ;or word [ebx], 4000h 2266 <1> ; ; bis $40000,(r5) 2267 <1> ; ; / set bit 14 of the 1st word of the I/O buffer 2268 <1> bread_3: ; 1: 2269 <1> ; 14/07/2022 2270 <1> ;test word [ebx], 2400h 2271 <1> ; ; bit $22000,(r5) / are 10th and 13th bits set (read bits) 2272 <1> ;jz short bread_4 2273 <1> ; ; beq 1f / no 2274 <1> ; ; cmp cdev,$1 / disk or drum? 2275 <1> ; ; ble 2f / yes 2276 <1> ; ; tstb uquant / is the time quantum = 0? 2277 <1> ; ; bne 2f / no, 2f 2278 <1> ; ; mov r5,-(sp) / yes, save r5 (buffer address) 2279 <1> ; ; jsr r0,sleep; 31. 2280 <1> ; ; / put process to sleep in channel 31 (tape) 2281 <1> ; ; mov (sp)+,r5 / restore r5 2282 <1> ; ; br 1b / go back 2283 <1> ; 2: / drum or disk 2284 <1> ;; mov cx, [s.wait_]+2 ;; 29/07/2013 2285 <1> ;call idle 2286 <1> ; ; jsr r0,idle; s.wait+2 / wait 2287 <1> ;jmp short bread_3 2288 <1> ; ; br 1b 2289 <1> bread_4: ; 1: / 10th and 13th bits not set 2290 <1> ;and word [ebx], 0BFFFh ; 1011111111111111b 2291 <1> ; ; bic $40000,(r5) / clear bit 14 2292 <1> ; ; jsr r0,tstdeve / test device for error (tape) 2293 <1> ; 14/07/2022 2294 000052BF 83C308 <1> add ebx, 8 2295 <1> ; add $8,r5 / r5 points to data in I/O buffer 2296 <1> ; 09/06/2015 2297 000052C2 66833D[5F650000]00 <1> cmp word [u.pcount], 0 2298 000052CA 7705 <1> ja short bread_5 2299 000052CC E892F8FFFF <1> call trans_addr_w ; translate virtual address to physical (w) 2300 <1> bread_5: 2301 <1> ; EBX = system (I/O) buffer address 2302 000052D1 E87C000000 <1> call dioreg 2303 <1> ; jsr r0,dioreg / do bookkeeping on u.count etc. 2304 <1> 2305 <1> ; 19/07/2022 2306 <1> ; EDI = user data offset (previous value of [u.pbase]) 2307 <1> ; ESI = pointer to file offset 2308 <1> ; EAX = system (I/O) buffer offset (>= EBX) 2309 <1> ; ECX = byte count 2310 <1> ; EBX = system buffer (data) address 2311 <1> 2312 <1> ; 19/07/2022 2313 000052D6 010E <1> add [esi], ecx ; new file (disk) offset 2314 000052D8 89C6 <1> mov esi, eax 2315 <1> 2316 <1> ; esi = start address of the transfer (in the buffer) 2317 <1> ; edi = [u.pbase], destination address in user's memory space 2318 <1> ; ecx = transfer count (in bytes) 2319 <1> ; 2320 <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning 2321 <1> ; / of users data 2322 000052DA F3A4 <1> rep movsb 2323 <1> ; movb (r5)+,(r2)+ / move data from the I/O buffer 2324 <1> ; dec r3 / to the user's area in core starting at u.base 2325 <1> ; bne 1b 2326 000052DC 59 <1> pop ecx ; ** 2327 000052DD 833D[24650000]00 <1> cmp dword [u.count], 0 2328 <1> ; tst u.count / done 2329 000052E4 77AC <1> ja short bread_0 ; 09/06/2015 2330 <1> ; beq 1f / yes, return 2331 <1> ; tst -(r0) / no, point r0 to the argument again 2332 <1> ; br bread / read some more 2333 <1> ; 1: 2334 000052E6 58 <1> pop eax ; **** 2335 <1> ; mov (sp)+,r0 2336 000052E7 C3 <1> retn ; 09/06/2015 2337 <1> ;jmp ret_ 2338 <1> ;jmp ret / jump to routine that called readi 2339 <1> 2340 <1> ; 08/02/2022 2341 <1> brw_oov_err: 2342 000052E8 C705[4F650000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2342 000052F0 0000 <1> 2343 000052F2 E9EADDFFFF <1> jmp error 2344 <1> 2345 <1> ; 12/02/2022 2346 <1> wfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2347 <1> ; 26/04/2013 2348 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2349 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2350 <1> ;jmp short bwrite ; **** returns to routine that called writei 2351 <1> 2352 <1> ; 12/02/2022 2353 <1> whd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2354 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2355 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2356 <1> ;jmp short bwrite ; **** returns to routine that called writei ('jmp ret') 2357 <1> 2358 <1> bwrite: 2359 <1> ; 19/07/2022 2360 <1> ; (file offset bugfix for 'dskwr' error return situation) 2361 <1> ; 14/07/2022 2362 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2363 <1> ; 12/02/2022 2364 <1> ; 04/02/2022 2365 <1> ; 14/07/2015 2366 <1> ; 10/07/2015 2367 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2368 <1> ; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1) 2369 <1> ; 2370 <1> ;; / write on block structured device 2371 <1> ; 2372 <1> ; INPUTS -> 2373 <1> ; [u.fofp] points to the block number 2374 <1> ; ECX = maximum block number allowed on device 2375 <1> ; ; that was an arg to bwrite, in original Unix v1, but 2376 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 2377 <1> ; [u.count] number of bytes to user desires to write 2378 <1> ; OUTPUTS -> 2379 <1> ; [u.fofp] points to next consecutive block to be written into 2380 <1> ; 2381 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 2382 <1> ; 2383 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if write 2384 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 2385 <1> ; is increased by 1. For example: If user/program request 2386 <1> ; to write 16 bytes in current block, 'sys write' increases 2387 <1> ; the next block number just as 512 byte writing is done. 2388 <1> ; This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 2389 <1> ; for user (u) structure compatibility (because 16 bit is not 2390 <1> ; enough to keep byte position/offset of the disk), this 2391 <1> ; defect will not be corrected, user/program must request 2392 <1> ; 512 byte write per every 'sys write' call to block devices 2393 <1> ; for achieving correct result. In future version(s), 2394 <1> ; this defect will be corrected by using different 2395 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 2396 <1> 2397 <1> ; jsr r0,tstdeve / test the device for an error 2398 <1> ;push ecx ; ** 2399 <1> ;26/04/2013 2400 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 2401 000052F7 2C03 <1> sub al, 3 2402 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 2403 000052F9 A2[62650000] <1> mov [u.brwdev], al 2404 <1> ; 09/06/2015 2405 <1> ;movzx ebx, al 2406 <1> ;mov ecx, [ebx+drv.size] ; disk size (in sectors) 2407 <1> ; 04/02/2022 (BugFix) 2408 000052FE C0E002 <1> shl al, 2 ; * 4 2409 00005301 8B88[625C0000] <1> mov ecx, [eax+drv.size] ; disk size (in sectors) 2410 <1> bwrite_0: 2411 00005307 51 <1> push ecx ; ** ; 09/06/2015 2412 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 2413 <1> ; [u.fofp] points to byte position in disk, not sector/block ! 2414 00005308 8B1D[10650000] <1> mov ebx, [u.fofp] 2415 0000530E 8B03 <1> mov eax, [ebx] 2416 00005310 C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 2417 <1> ; mov *u.fofp,r1 / put the block number in r1 2418 00005313 39C8 <1> cmp eax, ecx 2419 <1> ; cmp r1,(r0)+ / does block number exceed maximum allowable # 2420 <1> ; / block number allowed 2421 <1> ;jnb error ; 18/04/2013 2422 <1> ; bhis error10 / yes, error 2423 <1> ; 12/02/2022 2424 <1> ;jb short bwrite_1 2425 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2426 <1> ;jmp error 2427 00005315 73D1 <1> jnb short brw_oov_err ; 'out of volume' error 2428 <1> bwrite_1: 2429 <1> ;inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 2430 <1> ; inc *u.fofp / no, increment block number 2431 <1> ; 09/06/2015 - 10/07/2015 2432 00005317 66833D[5F650000]00 <1> cmp word [u.pcount], 0 2433 0000531F 7705 <1> ja short bwrite_2 2434 00005321 E839F8FFFF <1> call trans_addr_r ; translate virtual address to physical (r) 2435 <1> bwrite_2: 2436 00005326 BF[62650000] <1> mov edi, u.brwdev ; block device number for direct I/O 2437 0000532B E8C9000000 <1> call bwslot ; 26/04/2013 (wslot -> bwslot) 2438 <1> ; jsr r0,wslot / get an I/O buffer to write into 2439 <1> ; add $8,r5 / r5 points to data in I/O buffer 2440 00005330 E81D000000 <1> call dioreg 2441 <1> ; jsr r0,dioreg / do the necessary bookkeeping 2442 <1> 2443 <1> ; 19/07/2022 2444 <1> ; EDI = user data offset (previous value of [u.pbase]) 2445 <1> ; ESI = pointer to file offset 2446 <1> ; EAX = system (I/O) buffer offset (>= EBX) 2447 <1> ; ECX = byte count 2448 <1> ; EBX = system buffer (data) address 2449 <1> 2450 <1> ; 19/07/2022 - Erdogan Tan 2451 <1> ; ((Against a possible disk write failure/error, 2452 <1> ; file offset must not be updated/increased before 'dskwr' 2453 <1> ; but it was updated in 'dioreg'. I have modified 'dioreg' 2454 <1> ; and 'bwrite' procedures for that.)) 2455 <1> 2456 <1> ; 19/07/2022 2457 00005335 56 <1> push esi ; (!) ; save file offset (pointer) 2458 00005336 51 <1> push ecx ; (!!) ; save byte count 2459 <1> ;mov esi, eax 2460 <1> 2461 <1> ; esi = destination address (in the buffer) 2462 <1> ; edi = [u.pbase], start address of transfer in user's memory space 2463 <1> ; ecx = transfer count (in bytes) 2464 <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area 2465 <1> ;xchg esi, edi ; 14/07/2015 2466 <1> 2467 <1> ; 19/07/2022 2468 00005337 89FE <1> mov esi, edi 2469 00005339 89C7 <1> mov edi, eax 2470 <1> 2471 0000533B F3A4 <1> rep movsb 2472 <1> ; movb (r2)+,(r5)+ / ; r3, has the byte count 2473 <1> ; dec r3 / area to the I/O buffer 2474 <1> ; bne 1b 2475 <1> 2476 0000533D E8F0000000 <1> call dskwr 2477 <1> ; jsr r0,dskwr / write it out on the device 2478 <1> 2479 <1> ; 19/07/2022 2480 <1> ; (there is not a disk write error, we can increase file offset) 2481 00005342 58 <1> pop eax ; (!!) ; byte count 2482 00005343 5F <1> pop edi ; (!) ; file offset (pointer) 2483 <1> ; 2484 00005344 0107 <1> add [edi], eax ; new file offset (old offset + byte count) 2485 <1> 2486 00005346 59 <1> pop ecx ; ** 2487 <1> 2488 00005347 833D[24650000]00 <1> cmp dword [u.count], 0 2489 <1> ; tst u.count / done 2490 0000534E 77B7 <1> ja short bwrite_0 ; 09/06/2015 2491 <1> ; beq 1f / yes, 1f 2492 <1> ; tst -(r0) / no, point r0 to the argument of the call 2493 <1> ; br bwrite / go back and write next block 2494 <1> ; 1: 2495 00005350 58 <1> pop eax ; **** 2496 <1> ; mov (sp)+,r0 2497 00005351 C3 <1> retn ; 09/06/2015 2498 <1> ;jmp ret_ 2499 <1> ; jmp ret / return to routine that called writei 2500 <1> ;error10: 2501 <1> ; jmp error ; / see 'error' routine 2502 <1> 2503 <1> dioreg: 2504 <1> ; 19/07/2022 2505 <1> ; (file offset bugfix for 'dskwr' error return situation) 2506 <1> ; 04/02/2022 2507 <1> ; 14/07/2015 2508 <1> ; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block) 2509 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2510 <1> ; 14/03/2013 (Retro UNIX 8086 v1) 2511 <1> ; 2512 <1> ; bookkeeping on block transfers of data 2513 <1> ; 2514 <1> ; * returns value of u.pbase before it gets updated, in EDI 2515 <1> ; * returns byte count (to transfer) in ECX (<=512) 2516 <1> ; 10/07/2015 2517 <1> ; * returns byte offset from beginning of current sector buffer 2518 <1> ; (beginning of data) in ESI 2519 <1> 2520 <1> 2521 <1> ; 19/07/2022 2522 <1> ; OUTPUTS: 2523 <1> ; EDI = user data offset (previous value of [u.pbase]) 2524 <1> ; ESI = pointer to file offset 2525 <1> ; EAX = system (I/O) buffer offset 2526 <1> ; ECX = byte count 2527 <1> ; EBX = system buffer (data) address 2528 <1> 2529 00005352 8B0D[24650000] <1> mov ecx, [u.count] 2530 <1> ; mov u.count,r3 / move char count to r3 2531 <1> ; 04/02/2022 2532 00005358 31D2 <1> xor edx, edx 2533 0000535A B602 <1> mov dh, 2 2534 <1> ; edx = 512 2535 0000535C 39D1 <1> cmp ecx, edx ; 512 2536 <1> ;cmp ecx, 512 2537 <1> ; cmp r3,$512. / more than 512. char? 2538 0000535E 7602 <1> jna short dioreg_0 2539 <1> ; blos 1f / no, branch 2540 00005360 89D1 <1> mov ecx, edx ; 512 2541 <1> ;mov ecx, 512 2542 <1> ; mov $512.,r3 / yes, just take 512. 2543 <1> dioreg_0: 2544 <1> ; 09/06/2015 2545 00005362 663B0D[5F650000] <1> cmp cx, [u.pcount] 2546 00005369 7607 <1> jna short dioreg_1 2547 0000536B 668B0D[5F650000] <1> mov cx, [u.pcount] 2548 <1> dioreg_1: 2549 <1> ; 1: 2550 00005372 8B15[20650000] <1> mov edx, [u.base] ; 09/06/2015 (eax -> edx) 2551 <1> ; mov u.base,r2 / put users base in r2 2552 00005378 010D[28650000] <1> add [u.nread], ecx 2553 <1> ; add r3,u.nread / add the number to be read to u.nread 2554 0000537E 290D[24650000] <1> sub [u.count], ecx 2555 <1> ; sub r3,u.count / update count 2556 00005384 010D[20650000] <1> add [u.base], ecx 2557 <1> ; add r3,u.base / update base 2558 <1> ; 10/07/2015 2559 <1> ; Retro UNIX 386 v1 - modification ! 2560 <1> ; (File pointer points to byte position, not block/sector no.) 2561 <1> ; (It will point to next byte position instead of next block no.) 2562 0000538A 8B35[10650000] <1> mov esi, [u.fofp] ; u.fopf points to byte position pointer 2563 00005390 8B06 <1> mov eax, [esi] ; esi points to current byte pos. on the disk 2564 <1> ; 19/07/2022 2565 <1> ;add [esi], ecx ; ecx is added to set the next byte position 2566 00005392 25FF010000 <1> and eax, 1FFh ; get offset from beginning of current block 2567 <1> ;mov esi, ebx ; beginning of data in sector/block buffer 2568 <1> ;add esi, eax ; esi contains start address of the transfer 2569 <1> ; 19/07/2022 2570 00005397 01D8 <1> add eax, ebx ; eax contains start address of the transfer 2571 <1> ; 09/06/2015 - 10/07/2015 2572 00005399 66290D[5F650000] <1> sub [u.pcount], cx 2573 000053A0 81E2FF0F0000 <1> and edx, PAGE_OFF ; 0FFFh 2574 000053A6 8B3D[5B650000] <1> mov edi, [u.pbase] 2575 000053AC 81E700F0FFFF <1> and edi, ~PAGE_OFF 2576 000053B2 01D7 <1> add edi, edx 2577 000053B4 893D[5B650000] <1> mov [u.pbase], edi 2578 000053BA 010D[5B650000] <1> add [u.pbase], ecx ; 14/07/2015 2579 000053C0 C3 <1> retn 2580 <1> ; rts r0 / return 2581 <1> 2582 <1> dskrd: 2583 <1> ; 14/07/2022 2584 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2585 <1> ; 12/02/2022 2586 <1> ; 18/08/2015 2587 <1> ; 02/07/2015 2588 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2589 <1> ; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2590 <1> ; 2591 <1> ; 'dskrd' acquires an I/O buffer, puts in the proper 2592 <1> ; I/O queue entries (via bufaloc) then reads a block 2593 <1> ; (number specified in r1) in the acquired buffer. 2594 <1> ; If the device is busy at the time dskrd is called, 2595 <1> ; dskrd calls idle. 2596 <1> ; 2597 <1> ; INPUTS -> 2598 <1> ; r1 - block number 2599 <1> ; cdev - current device number 2600 <1> ; OUTPUTS -> 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)) 2607 <1> ; 2608 000053C1 E8B5000000 <1> call bufaloc 2609 <1> ; jsr r0,bufaloc / shuffle off to bufaloc; 2610 <1> ; / get a free I/O buffer 2611 <1> ;;jc error ; 20/07/2013 2612 000053C6 740C <1> jz short dskrd_1 ; Retro UNIX 8086 v1 modification 2613 <1> ; br 1f / branch if block already in a I/O buffer 2614 <1> 2615 <1> ; 14/07/2022 2616 <1> ; (buffer header byte 1, bit 2 is disk read bit/flag) 2617 <1> dskrd_0: ; 10/07/2015 (wslot) 2618 000053C8 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 2619 <1> ; ; bis $2000,(r5) / set bit 10 of word 1 of 2620 <1> ; ; / I/O queue entry for buffer 2621 000053CD E88E000000 <1> call poke 2622 <1> ; jsr r0,poke / just assigned in bufaloc, 2623 <1> ; / bit 10=1 says read 2624 <1> ; 09/06/2015 2625 <1> ;jnc short dskrd_1 2626 <1> ;mov dword [u.error], ERR_DRV_READ ; disk read error ! 2627 <1> ;jmp error 2628 <1> ; 08/02/2022 2629 000053D2 7204 <1> jc short dskrd_3 2630 <1> dskrd_1: ; 1: 2631 <1> ; 14/07/2022 2632 <1> ; 2633 <1> ; ;clr *$ps 2634 <1> ;test word [ebx], 2400h 2635 <1> ; ; bit $22000,(r5) / if either bits 10, or 13 are 1; 2636 <1> ; ; / jump to idle 2637 <1> ;jz short dskrd_2 2638 <1> ; ; beq 1f 2639 <1> ;;;mov ecx, [s.wait_] 2640 <1> ;call idle 2641 <1> ; ; jsr r0,idle; s.wait+2 2642 <1> ;jmp short dskrd_1 2643 <1> ; ; br 1b 2644 <1> dskrd_2: ; 1: 2645 000053D4 83C308 <1> add ebx, 8 2646 <1> ; add $8,r5 / r5 points to first word of data in block 2647 <1> ; / just read in 2648 000053D7 C3 <1> retn 2649 <1> ; rts r0 2650 <1> dskrd_err: 2651 <1> ; 08/02/2022 2652 <1> ; (jump from 'bread' error) 2653 <1> dskrd_3: 2654 <1> ; 08/02/2022 2655 000053D8 803D[62650000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 2656 000053DF 7509 <1> jne short dskrd_4 ; no 2657 <1> ; yes, clear [u.brwdev] for next check and jump to 'error' 2658 000053E1 C605[62650000]00 <1> mov byte [u.brwdev], 0 2659 000053E8 EB0A <1> jmp short dskrd_5 2660 <1> dskrd_4: 2661 000053EA C705[4F650000]1100- <1> mov dword [u.error], ERR_DRV_READ ; disk read error ! 2661 000053F2 0000 <1> 2662 <1> dskrd_5: 2663 000053F4 E9E8DCFFFF <1> jmp error 2664 <1> 2665 <1> bwslot: 2666 <1> ; 14/07/2022 2667 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2668 <1> ; 04/02/2022 2669 <1> ; 10/07/2015 2670 <1> ; If the block/sector is not placed in a buffer 2671 <1> ; before 'wslot', it must be read before 2672 <1> ; it is written! (Otherwise transfer counts less 2673 <1> ; than 512 bytes will be able to destroy existing 2674 <1> ; data on disk.) 2675 <1> ; 2676 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2677 <1> ; 26/04/2013(Retro UNIX 8086 v1) 2678 <1> ; Retro UNIX 8086 v1 modification ! 2679 <1> ; ('bwslot' will be called from 'bwrite' only!) 2680 <1> ; INPUT -> EDI - points to device id (in u.brwdev) 2681 <1> ; -> EAX = block number 2682 <1> ; 2683 000053F9 E88A000000 <1> call bufaloc_0 2684 000053FE 742A <1> jz short wslot_0 ; block/sector already is in the buffer 2685 <1> ; 04/02/2022 2686 <1> ; ebx = buffer header address 2687 <1> bwslot_0: 2688 <1> ; 10/07/2015 2689 00005400 8B35[10650000] <1> mov esi, [u.fofp] 2690 00005406 8B06 <1> mov eax, [esi] 2691 00005408 25FF010000 <1> and eax, 1FFh ; offset from beginning of the sector/block 2692 0000540D 750C <1> jnz short bwslot_1 ; it is not a full sector write 2693 <1> ; recent disk data must be placed in the buffer 2694 0000540F 813D[24650000]0002- <1> cmp dword [u.count], 512 2694 00005417 0000 <1> 2695 00005419 730F <1> jnb short wslot_0 2696 <1> bwslot_1: 2697 0000541B E8A8FFFFFF <1> call dskrd_0 2698 <1> ; 04/02/2022 2699 <1> ; ebx = buffer data address = buffer header address + 8 2700 00005420 83EB08 <1> sub ebx, 8 ; set ebx to the buffer header address again 2701 00005423 EB05 <1> jmp short wslot_0 2702 <1> 2703 <1> wslot: 2704 <1> ; 14/07/2022 2705 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2706 <1> ; 2707 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2708 <1> ; (32 bit modifications) 2709 <1> ; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1) 2710 <1> ; 2711 <1> ; 'wslot' calls 'bufaloc' and obtains as a result, a pointer 2712 <1> ; to the I/O queue of an I/O buffer for a block structured 2713 <1> ; device. It then checks the first word of I/O queue entry. 2714 <1> ; If bits 10 and/or 13 (read bit, waiting to read bit) are set, 2715 <1> ; wslot calls 'idle'. When 'idle' returns, or if bits 10 2716 <1> ; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first 2717 <1> ; word of the I/O queue entry (write bit, inhibit bit). 2718 <1> ; 2719 <1> ; INPUTS -> 2720 <1> ; r1 - block number 2721 <1> ; cdev - current (block/disk) device number 2722 <1> ; 2723 <1> ; OUTPUTS -> 2724 <1> ; bufp - bits 9 and 15 are set, 2725 <1> ; the remainder of the word left unchanged 2726 <1> ; r5 - points to first data word in I/O buffer 2727 <1> ; 2728 <1> ; ((AX = R1)) input/output 2729 <1> ; ((BX = R5)) output 2730 <1> ; 2731 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 2732 <1> 2733 00005425 E851000000 <1> call bufaloc 2734 <1> ; 10/07/2015 2735 <1> ; jsr r0,bufaloc / get a free I/O buffer; pointer to first 2736 <1> ; br 1f / word in buffer in r5 2737 <1> ; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) 2738 <1> ; EAX = Block/Sector number (r1) 2739 <1> wslot_0: ;1: 2740 <1> ; 14/07/2022 2741 <1> ; 2742 <1> ;test word [ebx], 2400h 2743 <1> ; ; bit $22000,(r5) / check bits 10, 13 (read, waiting to read) 2744 <1> ; ; / of I/O queue entry 2745 <1> ;jz short wslot_1 2746 <1> ; ; beq 1f / branch if 10, 13 zero (i.e., not reading, 2747 <1> ; ; / or not waiting to read) 2748 <1> ; 2749 <1> ;;mov ecx, [s.wait_] ; 29/07/2013 2750 <1> ;call idle 2751 <1> ; ; jsr r0,idle; / if buffer is reading or writing to read, 2752 <1> ; ; / idle 2753 <1> ;jmp short wslot_0 2754 <1> ; ; br 1b / till finished 2755 <1> wslot_1: ;1: 2756 <1> ;or word [ebx], 8200h 2757 <1> ; ; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue 2758 <1> ; ; / (write, inhibit bits) 2759 <1> ; ; clr *$ps / clear processor status 2760 <1> 2761 <1> ; 14/07/2022 2762 <1> ; (set disk write bit/flag) 2763 <1> ;or word [ebx], 200h 2764 0000542A 43 <1> inc ebx 2765 0000542B 800B02 <1> or byte [ebx], 2 2766 0000542E 83C307 <1> add ebx, 7 2767 <1> 2768 <1> ;add ebx, 8 ; 11/06/2015 2769 <1> ; add $8,r5 / r5 points to first word in data area 2770 <1> ; / for this block 2771 <1> dskwr_1: ; 08/02/2022 2772 00005431 C3 <1> retn 2773 <1> ; rts r0 2774 <1> dskwr: 2775 <1> ; 14/07/2022 2776 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2777 <1> ; 12/02/2022 2778 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2779 <1> ; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2780 <1> ; 2781 <1> ; 'dskwr' writes a block out on disk, via ppoke. The only 2782 <1> ; thing dskwr does is clear bit 15 in the first word of I/O queue 2783 <1> ; entry pointed by 'bufp'. 'wslot' which must have been called 2784 <1> ; previously has supplied all the information required in the 2785 <1> ; I/O queue entry. 2786 <1> ; 2787 <1> ; (Modified registers: ECX, EDX, EBX, ESI, EDI) 2788 <1> ; 2789 <1> ; 2790 00005432 8B1D[B8640000] <1> mov ebx, [bufp] 2791 <1> ; 14/07/2022 2792 <1> ;and word [ebx], 7FFFh ; 0111111111111111b 2793 <1> ; ; bic $100000,*bufp / clear bit 15 of I/O queue entry at 2794 <1> ; / bottom of queue 2795 <1> ; 14/07/2022 2796 <1> ; (set disk write bit) 2797 <1> ; ('wslot' already sets disk write bit/flag) 2798 <1> ;mov word [ebx], 200h 2799 <1> 2800 00005438 E823000000 <1> call poke 2801 <1> ; 09/06/2015 2802 0000543D 73F2 <1> jnc short dskwr_1 2803 <1> ; 12/02/2022 2804 0000543F 803D[62650000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 2805 00005446 7509 <1> jne short dskwr_0 ; no 2806 <1> ; yes, clear [u.brwdev] for next check and jump to 'error' 2807 00005448 C605[62650000]00 <1> mov byte [u.brwdev], 0 2808 0000544F EB0A <1> jmp short dskwr_2 2809 <1> dskwr_0: 2810 00005451 C705[4F650000]1200- <1> mov dword [u.error], ERR_DRV_WRITE ; disk write error ! 2810 00005459 0000 <1> 2811 <1> dskwr_2: 2812 0000545B E981DCFFFF <1> jmp error 2813 <1> ;dskwr_1: 2814 <1> ; retn 2815 <1> 2816 <1> ;ppoke: 2817 <1> ; mov $340,*$ps 2818 <1> ; jsr r0,poke 2819 <1> ; clr *$ps 2820 <1> ; rts r0 2821 <1> poke: 2822 <1> ; 14/07/2022 2823 <1> ; ! Major Modification ! 2824 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2825 <1> ; 2826 <1> ; 04/02/2022 (32 bit reg push pop) 2827 <1> ; 24/10/2015 2828 <1> ; 20/08/2015 2829 <1> ; 18/08/2015 2830 <1> ; 02/07/2015 2831 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2832 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2833 <1> ; 2834 <1> ; (NOTE: There are some disk I/O code modifications & extensions 2835 <1> ; & exclusions on original 'poke' & other device I/O procedures of 2836 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 2837 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 2838 <1> ; 2839 <1> ; Basic I/O functions for all block structured devices 2840 <1> ; 2841 <1> ; (Modified registers: ECX, EDX, ESI, EDI) 2842 <1> ; 2843 <1> ; 20/07/2013 modifications 2844 <1> ; (Retro UNIX 8086 v1 features only !) 2845 <1> ; INPUTS -> 2846 <1> ; EBX = buffer header address 2847 <1> ; OUTPUTS -> 2848 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 2849 <1> ; cf=1 -> error, word [EBX] = 0FFFFh 2850 <1> ; (drive not ready or r/w error!) 2851 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 2852 <1> ; (dword [EBX+4] = 0FFFFFFFFh means RW/IO error) 2853 <1> ; (also it indicates invalid buffer data) 2854 <1> 2855 <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2856 <1> ; Buffer header: 2857 <1> ; byte 0 - device/disk (index) number 2858 <1> ; byte 1 - status 2859 <1> ; before 'poke' 2860 <1> ; bit 0 - valid bit 2861 <1> ; (0 for new buffer) 2862 <1> ; (1 for existing buffer) 2863 <1> ; bit 1 - write (modified) bit, disk write flag 2864 <1> ; bit 2 - read bit, disk read flag 2865 <1> ; after 'poke' 2866 <1> ; if disk r/w is successed 2867 <1> ; bit 0 = 1 2868 <1> ; bit 1 = 0 2869 <1> ; bit 2 = 0 2870 <1> ; if disk r/w is failed 2871 <1> ; bit 0 = 0 (invalid buffer) 2872 <1> ; bit 1 = 0 (write bit) 2873 <1> ; bit 2 = 0 (read bit) 2874 <1> ; 2875 <1> ; byte 2 & byte 3 - not used 2876 <1> ; byte 4 to byte 7 - disk block/sector address 2877 <1> 2878 <1> ; 04/02/2022 2879 00005460 50 <1> push eax 2880 00005461 E896000000 <1> call diskio ; Retro UNIX 8086 v1 Only ! 2881 00005466 58 <1> pop eax 2882 00005467 730D <1> jnc short seta ; 14/07/2022 2883 <1> 2884 <1> ; 14/07/2022 2885 <1> ; (invalidate buffer) 2886 <1> 2887 <1> ; 02/07/2015 (32 bit modification) 2888 <1> ; 20/07/2013 2889 00005469 C74304FFFFFFFF <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 2890 <1> ; mov $-1,2(r1) / destroy associativity 2891 00005470 66C703FF00 <1> mov word [ebx], 0FFh ; 20/08/2015 2892 <1> ; clrb 1(r1) / do not do I/O 2893 <1> ;stc 2894 00005475 C3 <1> retn 2895 <1> ; rts r0 2896 <1> seta: 2897 00005476 C6430101 <1> mov byte [ebx+1], 1 ; clear write/read bits, set valid bit 2898 <1> ;clc 2899 0000547A C3 <1> retn 2900 <1> 2901 <1> %if 0 2902 <1> 2903 <1> poke: 2904 <1> ; 04/02/2022 (32 bit reg push pop) 2905 <1> ; 24/10/2015 2906 <1> ; 20/08/2015 2907 <1> ; 18/08/2015 2908 <1> ; 02/07/2015 2909 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2910 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2911 <1> ; 2912 <1> ; (NOTE: There are some disk I/O code modifications & extensions 2913 <1> ; & exclusions on original 'poke' & other device I/O procedures of 2914 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 2915 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 2916 <1> ; 2917 <1> ; Basic I/O functions for all block structured devices 2918 <1> ; 2919 <1> ; (Modified registers: ECX, EDX, ESI, EDI) 2920 <1> ; 2921 <1> ; 20/07/2013 modifications 2922 <1> ; (Retro UNIX 8086 v1 features only !) 2923 <1> ; INPUTS -> 2924 <1> ; (EBX = buffer header address) 2925 <1> ; OUTPUTS -> 2926 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 2927 <1> ; cf=1 -> error, word [EBX] = 0FFFFh 2928 <1> ; (drive not ready or r/w error!) 2929 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 2930 <1> ; (dword [EBX+4] = 0FFFFFFFFh means RW/IO error) 2931 <1> ; (also it indicates invalid buffer data) 2932 <1> ; 2933 <1> push ebx 2934 <1> ; mov r1,-(sp) 2935 <1> ; mov r2,-(sp) 2936 <1> ; mov r3,-(sp) 2937 <1> push eax ; Physical Block Number (r1) (mget) 2938 <1> ; 2939 <1> ; 09/06/2015 2940 <1> ; (permit read/write after a disk R/W error) 2941 <1> mov cl, [ebx] ; device id (0 to 5) 2942 <1> mov al, 1 2943 <1> shl al, cl 2944 <1> test al, [active] ; busy ? (error) 2945 <1> jz short poke_0 2946 <1> not al 2947 <1> and [active], al ; reset busy bit for this device only 2948 <1> poke_0: 2949 <1> mov esi, bufp + (4*(nbuf+2)) 2950 <1> ; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority 2951 <1> ; / I/O queue pointer 2952 <1> poke_1: ; 1: 2953 <1> sub esi, 4 2954 <1> mov ebx, [esi] 2955 <1> ; mov -(r2),r1 / r1 points to an I/O queue entry 2956 <1> mov ax, [ebx] ; 17/07/2013 2957 <1> test ah, 06h 2958 <1> ;test word [ebx], 600h ; 0000011000000000b 2959 <1> ; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 2960 <1> ; / queue entry 2961 <1> jz short poke_5 2962 <1> ; beq 2f / branch to 2f if both are clear 2963 <1> ; 31/07/2013 2964 <1> ;test ah, 0B0h ; (*) 2965 <1> ;;test word [ebx], 0B000h ; 1011000000000000b 2966 <1> ; bit $130000,(r1) / test bits 12, 13, and 15 2967 <1> ;jnz short poke_5 ; 31/07/2013 (*) 2968 <1> ; bne 2f / branch if any are set 2969 <1> ;movzx ecx, byte [ebx] ; 09/06/2015 ; Device Id 2970 <1> ; movb (r1),r3 / get device id 2971 <1> movzx ecx, al ; 18/08/2015 2972 <1> ;mov edi, ecx ; 26/04/2013 2973 <1> xor eax, eax ; 0 2974 <1> ;cmp [edi+drv.error], al ; 0 2975 <1> ; tstb deverr(r3) / test for errors on this device 2976 <1> ;jna short poke_2 2977 <1> ; beq 3f / branch if no errors 2978 <1> ; 02/07/2015 2979 <1> ;dec eax 2980 <1> ;mov [ebx+4], ax ; 0FFFFFFFFh ; -1 2981 <1> ; mov $-1,2(r1) / destroy associativity 2982 <1> ;shr eax, 24 2983 <1> ;mov [ebx], eax ; 000000FFh, reset 2984 <1> ; clrb 1(r1) / do not do I/O 2985 <1> ;jmp short poke_5 2986 <1> ; ; br 2f 2987 <1> ; rts r0 2988 <1> poke_2: ; 3: 2989 <1> ; 02/07/2015 2990 <1> inc cl ; 0FFh -> 0 2991 <1> jz short poke_5 2992 <1> inc al ; mov ax, 1 2993 <1> dec cl 2994 <1> jz short poke_3 2995 <1> ; 26/04/2013 Modification 2996 <1> ;inc al ; mov ax, 1 2997 <1> ;or cl, cl ; Retro UNIX 8086 v1 device id. 2998 <1> ;jz short poke_3 ; cl = 0 2999 <1> shl al, cl ; shl ax, cl 3000 <1> poke_3: 3001 <1> ;test [active], ax 3002 <1> test [active], al 3003 <1> ; bit $2,active / test disk busy bit 3004 <1> jnz short poke_5 3005 <1> ; bne 2f / branch if bit is set 3006 <1> ;or [active], ax 3007 <1> or [active], al 3008 <1> ; bis $2,active / set disk busy bit 3009 <1> ;push ax 3010 <1> ; 04/02/2022 3011 <1> push eax 3012 <1> call diskio ; Retro UNIX 8086 v1 Only ! 3013 <1> ;mov [edi+drv.error], ah 3014 <1> ; 04/02/2022 3015 <1> pop eax 3016 <1> ;pop ax 3017 <1> jnc short poke_4 ; 20/07/2013 3018 <1> ;cmp [edi+drv.error], al ; 0 3019 <1> ;jna short poke_4 3020 <1> ; tstb deverr(r3) / test for errors on this device 3021 <1> ; beq 3f / branch if no errors 3022 <1> ; 02/07/2015 (32 bit modification) 3023 <1> ; 20/07/2013 3024 <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 3025 <1> ; mov $-1,2(r1) / destroy associativity 3026 <1> mov word [ebx], 0FFh ; 20/08/2015 3027 <1> ; clrb 1(r1) / do not do I/O 3028 <1> jmp short poke_5 3029 <1> poke_4: ; 20/07/2013 3030 <1> ; 17/07/2013 3031 <1> not al 3032 <1> and [active], al ; reset, not busy 3033 <1> ; eBX = system I/O buffer header (queue entry) address 3034 <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits. 3035 <1> mov ax, [ebx] 3036 <1> ; mov (r1),r3 / move word 1 of I/O queue entry into r3 3037 <1> and ax, 600h 3038 <1> ; bic $!3000,r3 / clear all bits except 9 and 10 3039 <1> and word [ebx], 0F9FFh 3040 <1> ; bic $3000,(r1) / clear only bits 9 and 10 3041 <1> shl ah, 3 3042 <1> ; rol r3 3043 <1> ; rol r3 3044 <1> ; rol r3 3045 <1> or [ebx], ax 3046 <1> ; bis r3,(r1) / or old value of bits 9 and 10 with 3047 <1> ; bits 12 and 13 3048 <1> call idle ; 18/01/2014 3049 <1> ;; sti 3050 <1> ;hlt ; wait for a hardware interrupt 3051 <1> ;; cli 3052 <1> ; NOTE: In fact, disk controller's 'disk I/O completed' 3053 <1> ; interrupt would be used to reset busy bits, but INT 13h 3054 <1> ; returns when disk I/O is completed. So, here, as temporary 3055 <1> ; method, this procedure will wait for a time according to 3056 <1> ; multi tasking and time sharing concept. 3057 <1> ; 3058 <1> ; 24/10/2015 3059 <1> ;not ax 3060 <1> mov ax, 0FFh ; 24/10/2015 (temporary) 3061 <1> and [ebx], ax ; clear bits 12 and 13 3062 <1> poke_5: ;2: 3063 <1> cmp esi, bufp 3064 <1> ; cmp r2,$bufp / test to see if entire I/O queue 3065 <1> ; / has been scanned 3066 <1> ja short poke_1 3067 <1> ; bhi 1b 3068 <1> ; 24/03/2013 3069 <1> ; mov (sp)+,r3 3070 <1> ; mov (sp)+,r2 3071 <1> ; mov (sp)+,r1 3072 <1> pop eax ; Physical Block Number (r1) (mget) 3073 <1> pop ebx 3074 <1> ; 02/07/2015 (32 bit modification) 3075 <1> ; 20/07/2013 3076 <1> ;cmp dword [ebx+4], 0FFFFFFFFh 3077 <1> cmp byte [ebx], 0FFh ; 20/08/2015 3078 <1> ; 3079 <1> ; 'poke' returns with cf=0 if the requested buffer is read 3080 <1> ; or written succesfully; even if an error occurs while 3081 <1> ; reading to or writing from other buffers. 20/07/2013 3082 <1> ; 3083 <1> ; 09/06/2015 3084 <1> cmc 3085 <1> retn 3086 <1> ; rts r0 3087 <1> %endif 3088 <1> 3089 <1> bufaloc: 3090 <1> ; 15/07/2022 3091 <1> ; 14/07/2022 3092 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 3093 <1> ; 04/02/2022 3094 <1> ; 20/08/2015 3095 <1> ; 19/08/2015 3096 <1> ; 02/07/2015 3097 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 3098 <1> ; (32 bit modifications) 3099 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 3100 <1> ; 3101 <1> ; bufaloc - Block device I/O buffer allocation 3102 <1> ; 3103 <1> ; INPUTS -> 3104 <1> ; r1 - block number 3105 <1> ; cdev - current (block/disk) device number 3106 <1> ; bufp+(2*n)-2 --- n = 1 ... nbuff 3107 <1> ; OUTPUTS -> 3108 <1> ; r5 - pointer to buffer allocated 3109 <1> ; bufp ... bufp+12 --- (bufp), (bufp)+2 3110 <1> ; 3111 <1> ; ((AX = R1)) input/output 3112 <1> ; ((BX = R5)) output 3113 <1> ; ((Modified registers: DX, CX, BX, SI, DI, BP)) 3114 <1> ; zf=1 -> block already in a I/O buffer 3115 <1> ; zf=0 -> a new I/O buffer has been allocated 3116 <1> ; ((DL = Device ID)) 3117 <1> ; (((DH = 0 or 1))) 3118 <1> ; (((CX = previous value of word ptr [bufp]))) 3119 <1> ; ((CX and DH will not be used after return))) 3120 <1> 3121 <1> ; 14/07/2022 3122 <1> ; Modified registers: EBX, ECX, EDX, ESI, EDI 3123 <1> 3124 <1> ;;push esi ; *** 3125 <1> ; mov r2,-(sp) / save r2 on stack 3126 <1> ; mov $340,*$ps / set processor priority to 7 3127 <1> ; 20/07/2013 3128 <1> ; 26/04/2013 3129 <1> ;movzx ebx, byte [cdev] ; 0 or 1 3130 <1> ;mov edi, rdev ; offset mdev = offset rdev + 1 3131 <1> ;add edi, ebx 3132 <1> ; 09/01/2022 3133 0000547B 0FB63D[E4640000] <1> movzx edi, byte [cdev] ; 0 or 1 3134 00005482 81C7[E6640000] <1> add edi, rdev 3135 <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !! 3136 <1> ;; EDI points to device id. 3137 00005488 0FB61F <1> movzx ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev 3138 <1> ; 11/06/2015 3139 0000548B 80BB[7E5C0000]F0 <1> cmp byte [ebx+drv.status], 0F0h ; Drive not ready ! 3140 00005492 720F <1> jb short bufaloc_9 3141 00005494 C705[4F650000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 3141 0000549C 0000 <1> 3142 0000549E E93EDCFFFF <1> jmp error 3143 <1> bufaloc_9: 3144 000054A3 89DA <1> mov edx, ebx ; dh = 0, dl = device number (0 to 5) 3145 <1> bufaloc_10: ; 02/07/2015 3146 <1> ; 14/07/2022 3147 <1> ;xor ebp, ebp ; 0 3148 <1> ;push ebp ; 0 3149 <1> ;mov ebp, esp 3150 000054A5 31FF <1> xor edi, edi ; 0 3151 000054A7 57 <1> push edi 3152 <1> bufaloc_1: ;1: 3153 <1> ; clr -(sp) / vacant buffer 3154 000054A8 BE[B8640000] <1> mov esi, bufp 3155 <1> ; mov $bufp,r2 / bufp contains pointers to I/O queue 3156 <1> ; / entrys in buffer area 3157 <1> bufaloc_2: ;2: 3158 000054AD 8B1E <1> mov ebx, [esi] 3159 <1> ; mov (r2)+,r5 / move pointer to word 1 of an I/O 3160 <1> ; queue entry into r5 3161 <1> ; 14/07/2022 3162 000054AF 8B0B <1> mov ecx, [ebx] 3163 <1> ;test word [ebx], 0F600h 3164 <1> ; 15/07/2022 3165 000054B1 F6C501 <1> test ch, 1 ; valid buffer (content) ? 3166 <1> ; bit $173000,(r5) / lock+keep+active+outstanding 3167 000054B4 7505 <1> jnz short bufaloc_3 ; yes 3168 <1> ; bne 3f / branch when 3169 <1> ; / any of bits 9,10,12,13,14,15 are set 3170 <1> ; / (i.e., buffer busy) 3171 <1> ;mov [ebp], esi ; pointer to I/0 queue entry 3172 <1> ; 14/07/2022 3173 <1> ; save free buffer pointer 3174 000054B6 893424 <1> mov [esp], esi 3175 <1> ; mov r2,(sp) ;/ save pointer to last non-busy buffer 3176 <1> ; / found points to word 2 of I/O queue entry) 3177 <1> ; continue to see if requested sector/block buffer 3178 <1> ; already is one of existing (valid) buffers 3179 <1> ;jmp short bufaloc_4 3180 000054B9 EB0E <1> jmp short bufaloc_11 ; 14/07/2022 3181 <1> bufaloc_3: ;3: 3182 <1> ;mov dl, [edi] ; 26/04/2013 3183 <1> ; 3184 000054BB 38D1 <1> cmp cl, dl ; 14/07/2022 3185 <1> ;cmp [ebx], dl 3186 <1> ; cmpb (r5),cdev / is device in I/O queue entry same 3187 <1> ; / as current device 3188 000054BD 7508 <1> jne short bufaloc_4 3189 <1> ; bne 3f 3190 000054BF 394304 <1> cmp [ebx+4], eax 3191 <1> ; cmp 2(r5),r1 / is block number in I/O queue entry, 3192 <1> ; / same as current block number 3193 000054C2 7503 <1> jne short bufaloc_4 3194 <1> ; bne 3f 3195 <1> ;add esp, 4 3196 000054C4 59 <1> pop ecx 3197 <1> ; tst (sp)+ / bump stack pointer 3198 000054C5 EB1D <1> jmp short bufaloc_7 ; Retro Unix 8086 v1 modification 3199 <1> ; jump to bufaloc_6 in original Unix v1 3200 <1> ; br 1f / use this buffer 3201 <1> bufaloc_4: ;3: 3202 <1> ; 14/07/2022 3203 <1> ; save last valid buffer 3204 <1> ; (will be used if there is not a free buffer) 3205 000054C7 89F7 <1> mov edi, esi 3206 <1> bufaloc_11: 3207 000054C9 83C604 <1> add esi, 4 ; 20/08/2015 3208 <1> ; 3209 000054CC 81FE[D8640000] <1> cmp esi, bufp + (nbuf*4) 3210 <1> ; cmp r2,$bufp+nbuf+nbuf 3211 000054D2 72D9 <1> jb short bufaloc_2 3212 <1> ; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all 3213 <1> ; / buffers not checked) 3214 000054D4 5E <1> pop esi 3215 <1> ; mov (sp)+,r2 / once all bufs are examined move pointer 3216 <1> ; / to last free block 3217 000054D5 09F6 <1> or esi, esi 3218 000054D7 7502 <1> jnz short bufaloc_5 3219 <1> ; bne 2f / if (sp) is non zero, i.e., 3220 <1> ; / if a free buffer is found branch to 2f 3221 <1> 3222 <1> ; 14/07/2022 3223 <1> ; if there is not a free buffer 3224 <1> ; we can use last valid buffer (the oldest buffer) 3225 <1> ; ((ptr to new buffer is located at head of buff ptr chain)) 3226 000054D9 89FE <1> mov esi, edi 3227 <1> 3228 <1> ;;mov ecx, [s.wait_] 3229 <1> ;call idle 3230 <1> ; ; jsr r0,idle; s.wait+2 / idle if no free buffers 3231 <1> ;jmp short bufaloc_10 ; 02/07/2015 3232 <1> ; ; br 1b 3233 <1> bufaloc_5: ;2: 3234 <1> ; tst (r0)+ / skip if warmed over buffer 3235 <1> ; 14/07/2022 3236 <1> ;inc dh ; Retro UNIX 8086 v1 modification 3237 <1> bufaloc_6: ;1: 3238 000054DB 8B1E <1> mov ebx, [esi] 3239 <1> ; mov -(r2),r5 / put pointer to word 1 of I/O queue 3240 <1> ; / entry in r5 3241 <1> ;; 26/04/2013 3242 <1> ;;mov dl, [edi] ; byte [rdev] or byte [mdev] 3243 <1> ;mov [ebx], dl 3244 <1> ; movb cdev,(r5) / put current device number 3245 <1> ; / in I/O queue entry 3246 <1> ; 14/07/2022 3247 <1> ; invalidate buffer before r/w (new) disk sector/block 3248 <1> ;mov [ebx+1], dh ; 0 3249 <1> ; 14/07/2022 3250 000054DD 8913 <1> mov [ebx], edx ; dh = 0 3251 <1> 3252 000054DF 894304 <1> mov [ebx+4], eax 3253 <1> ; mov r1,2(r5) / move block number into word 2 3254 <1> ; / of I/O queue entry 3255 <1> ; 14/07/2022 3256 000054E2 FEC6 <1> inc dh ; dh = 1 3257 <1> bufaloc_7: ;1: 3258 000054E4 81FE[B8640000] <1> cmp esi, bufp 3259 <1> ; cmp r2,$bufp / bump all entrys in bufp 3260 <1> ; / and put latest assigned 3261 000054EA 760B <1> jna short bufaloc_8 3262 <1> ; blos 1f / buffer on the top 3263 <1> ; / (this makes if the lowest priority) 3264 <1> ; 14/07/2022 3265 000054EC 89F7 <1> mov edi, esi 3266 000054EE 83EE04 <1> sub esi, 4 3267 000054F1 8B0E <1> mov ecx, [esi] 3268 000054F3 890F <1> mov [edi], ecx ; 14/07/2022 3269 <1> ;mov [esi+4], ecx 3270 <1> ; mov -(r2),2(r2) / job for a particular device 3271 000054F5 EBED <1> jmp short bufaloc_7 3272 <1> ; br 1b 3273 <1> bufaloc_8: ;1: 3274 000054F7 891E <1> mov [esi], ebx 3275 <1> ; mov r5,(r2) 3276 <1> ;;pop esi ; *** 3277 <1> ; mov (sp)+,r2 / restore r2 3278 000054F9 08F6 <1> or dh, dh ; 0 or 1 ? 3279 <1> ; Retro UNIX 8086 v1 modification 3280 <1> ; zf=1 --> block already is in an I/O buffer 3281 <1> ; zf=0 --> a new I/O buffer has been allocated 3282 000054FB C3 <1> retn 3283 <1> ; rts r0 3284 <1> 3285 <1> diskio: 3286 <1> ; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21) 3287 <1> ; ((Ref: Retro UNIX 386 v1.1 'diskio' modification: 12/07/2022)) 3288 <1> ; 3289 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3290 <1> ; ((simplified and shortened 'diskio.s' code) 3291 <1> ; 3292 <1> ; 12/02/2022 3293 <1> ; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18) 3294 <1> ; 10/07/2015 3295 <1> ; 02/07/2015 3296 <1> ; 16/06/2015 3297 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 3298 <1> ; (80386 protected mode modifications) 3299 <1> ; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1) 3300 <1> ; 3301 <1> ; Retro UNIX 8086 v1 feature only ! 3302 <1> ; 3303 <1> ; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011) 3304 <1> ; 04/07/2009 - 20/07/2011 3305 <1> ; 3306 <1> ; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes) 3307 <1> ; 3308 <1> ; INPUTS -> 3309 <1> ; EBX = System I/O Buffer header address 3310 <1> ; 3311 <1> ; OUTPUTS -> cf=0 --> done 3312 <1> ; cf=1 --> error code in AH 3313 <1> ; 3314 <1> ; (Modified registers: EAX, ECX, EDX) 3315 <1> 3316 <1> ;rw_disk_sector: 3317 <1> ; 12/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.21) 3318 <1> ; 12/02/2022 3319 <1> ; 10/07/2015 3320 <1> ; 02/07/2015 3321 <1> ; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 3322 <1> ; 21/02/2015 ('dsectpm.s', 'read_disk_sector') 3323 <1> ; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s') 3324 <1> ; 01/12/2014 - 18/01/2015 ('dsectrm2.s') 3325 <1> ; 3326 <1> ;;mov dx, 0201h ; Read 1 sector/block 3327 <1> ;mov dh, 2 3328 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3329 000054FC B602 <1> mov dh, 2 ; Write 1 sector/block 3330 000054FE 668B03 <1> mov ax, [ebx] 3331 <1> ; 3332 00005501 56 <1> push esi ; **** 3333 00005502 53 <1> push ebx ; *** 3334 <1> ; 3335 00005503 0FB6C8 <1> movzx ecx, al 3336 00005506 89CE <1> mov esi, ecx 3337 <1> ; 3338 00005508 38F1 <1> cmp cl, dh ; 2 3339 0000550A 7202 <1> jb short rwdsk0 3340 0000550C 047E <1> add al, 7Eh ; 80h, 81h, 82h, 83h 3341 <1> rwdsk0: 3342 <1> ; 12/07/2022 3343 <1> ;mov [drv], al 3344 0000550E 81C6[7E5C0000] <1> add esi, drv.status 3345 <1> ; 11/06/2015 3346 00005514 803EF0 <1> cmp byte [esi], 0F0h 3347 00005517 7204 <1> jb short rwdsk1 3348 <1> ; 'drive not ready' error 3349 <1> ; 12/02/2022 3350 <1> ;mov byte [u.brwdev], 0FFh ; error code in [u.error] 3351 <1> ;mov dword [u.error], ERR_DRV_NOT_RDY 3352 <1> ;;jmp error 3353 <1> ;stc ; cf = 1 3354 <1> ;retn 3355 <1> ; 12/02/2022 3356 00005519 B10F <1> mov cl, ERR_DRV_NOT_RDY 3357 0000551B EB1F <1> jmp short rwdsk_err1 3358 <1> rwdsk1: 3359 <1> ;test ah, 2 3360 <1> ;;test ax, 200h ; Bit 9 of word 0 (status word) 3361 <1> ; ; write bit 3362 <1> ;jz short rwdsk2 3363 <1> 3364 <1> ;;test ah, 4 3365 <1> ;;;test ax, 400h ; Bit 10 of word 0 (status word) 3366 <1> ;; ; read bit 3367 <1> ;;jz short diskio_ret 3368 <1> 3369 <1> ;inc dh ; 03h = write 3370 <1> 3371 <1> ; 08/07/2022 3372 0000551D 84F4 <1> test ah, dh ; test ah, 2 3373 0000551F 7502 <1> jnz short rwdsk2 ; dh = 02h = write 3374 00005521 FECE <1> dec dh 3375 <1> ; dh = 01h = read 3376 <1> rwdsk2: 3377 00005523 88C2 <1> mov dl, al 3378 00005525 83C304 <1> add ebx, 4 ; sector/block address/number pointer 3379 00005528 8B03 <1> mov eax, [ebx] ; sector/block number (LBA) 3380 0000552A C0E102 <1> shl cl, 2 3381 0000552D 81C1[625C0000] <1> add ecx, drv.size ; disk size 3382 00005533 3B01 <1> cmp eax, [ecx] ; Last sector + 1 (number of secs.) 3383 00005535 7214 <1> jb short rwdsk3 3384 <1> ; 'out of volume' error 3385 <1> ; 12/02/2022 3386 <1> ;mov byte [u.brwdev], 0FFh ; error code in [u.error] 3387 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE 3388 <1> ;;jmp error 3389 <1> ;stc ; cf = 1 3390 <1> ;retn 3391 <1> ; 12/02/2022 3392 00005537 B910000000 <1> mov ecx, ERR_DEV_VOL_SIZE 3393 <1> rwdsk_err1: 3394 0000553C C605[62650000]FF <1> mov byte [u.brwdev], 0FFh 3395 00005543 890D[4F650000] <1> mov [u.error], ecx ; 12/02/2022 3396 00005549 EB27 <1> jmp short rwdsk_err2 3397 <1> rwdsk3: 3398 <1> ; 11/06/2015 3399 0000554B 83C304 <1> add ebx, 4 ; buffer address 3400 0000554E C605[7E650000]04 <1> mov byte [retry_count], 4 3401 <1> ; 12/07/2022 3402 <1> ;test byte [esi], 1 ; LBA ready ? 3403 <1> ;jz short rwdsk_chs 3404 <1> rwdsk_lba: 3405 <1> ; LBA read/write (with private LBA function) 3406 <1> ;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan)) 3407 00005555 83C607 <1> add esi, drv.error - drv.status ; 10/07/2015 3408 00005558 89C1 <1> mov ecx, eax ; sector number 3409 <1> ; ebx = buffer (data) address 3410 <1> ; dl = physical drive number (0,1, 80h, 81h, 82h, 83h) 3411 <1> rwdsk_lba_retry: 3412 <1> ;mov dl, [drv] 3413 <1> ; Function 1Bh = LBA read, 1Ch = LBA write 3414 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3415 <1> ;;mov ah, 1Ch - 03h ; LBA write function number - 3 3416 <1> ;mov ah, 2 ; LBA write function number - 2 3417 <1> ;add ah, dh 3418 <1> ;mov al, 1 3419 <1> ;int 13h 3420 <1> ;call int13h 3421 <1> ; 12/07/2022 3422 0000555A 88F0 <1> mov al, dh ; function (1 or 2) 3423 <1> ; (1 = read, 2 = write ) 3424 <1> ; ecx = disk sector address (LBA) 3425 <1> ; ebx = buffer address 3426 <1> ; dl = (physical) disk number 3427 <1> ; al = function (r/w) 3428 0000555C E80DCAFFFF <1> call DISK_IO 3429 <1> 3430 00005561 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3431 00005563 730E <1> jnc short rwdsk_lba_ok 3432 00005565 80FC80 <1> cmp ah, 80h ; time out ? 3433 00005568 7408 <1> je short rwdsk_lba_fails 3434 0000556A FE0D[7E650000] <1> dec byte [retry_count] 3435 00005570 7504 <1> jnz short rwdsk_lba_reset ; 10/07/2015 3436 <1> rwdsk_err2: ; 12/02/2022 3437 <1> rwdsk_lba_fails: 3438 00005572 F9 <1> stc 3439 <1> rwdsk_lba_ok: 3440 00005573 5B <1> pop ebx ; *** 3441 00005574 5E <1> pop esi ; **** 3442 00005575 C3 <1> retn 3443 <1> rwdsk_lba_reset: 3444 <1> ;mov ah, 0Dh ; Alternate reset 3445 <1> ;int 13h 3446 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3447 <1> ;mov ah, 5 ; Alternate reset 3448 <1> ;call int13h 3449 <1> ;jnc short rwdsk_lba_retry 3450 <1> ; 12/07/2022 3451 00005576 30C0 <1> xor al, al ; 0 ; reset 3452 00005578 E8F1C9FFFF <1> call DISK_IO 3453 0000557D 73DB <1> jnc short rwdsk_lba_retry 3454 <1> 3455 0000557F 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3456 00005581 EBF0 <1> jmp short rwdsk_lba_ok 3457 <1> 3458 <1> ; 12/07/2022 3459 <1> ; (CHS Read/Write setup is not needed here.) 3460 <1> ; (LBA address will be converted to CHS parameters 3461 <1> ; in 'DISK_IO' procedure when/if it is required.) 3462 <1> 3463 <1> ; ; CHS read (convert LBA address to CHS values) 3464 <1> ;rwdsk_chs: 3465 <1> ; ; 10/07/2015 3466 <1> ; sub esi, drv.status 3467 <1> ; mov ecx, esi 3468 <1> ; add esi, drv.error 3469 <1> ; ; 02/07/2015 3470 <1> ; ; 16/06/2015 3471 <1> ; ; 11/06/2015 3472 <1> ; push ebx ; ** ; buffer 3473 <1> ; shl ecx, 1 3474 <1> ; push ecx ; * 3475 <1> ; ; 3476 <1> ; mov ebx, ecx 3477 <1> ; mov [rwdsk], dh ; 02/07/2015 3478 <1> ; xor edx, edx ; 0 3479 <1> ; ; 04/02/2022 3480 <1> ; ;sub ecx, ecx 3481 <1> ; add ebx, drv.spt 3482 <1> ; mov cx, [ebx] ; sector per track 3483 <1> ; ; EDX:EAX = LBA 3484 <1> ; div ecx 3485 <1> ; mov cl, dl ; sector number - 1 3486 <1> ; inc cl ; sector number (1 based) 3487 <1> ; pop ebx ; * ; 11/06/2015 3488 <1> ; ;push cx 3489 <1> ; ; 04/02/2022 3490 <1> ; push ecx 3491 <1> ; add ebx, drv.heads 3492 <1> ; mov cx, [ebx] ; heads 3493 <1> ; xor edx, edx 3494 <1> ; ; EAX = cylinders * heads + head 3495 <1> ; div ecx 3496 <1> ; ;pop cx ; sector number 3497 <1> ; ; 04/02/2022 3498 <1> ; pop ecx 3499 <1> ; mov dh, dl ; head number 3500 <1> ; mov dl, [drv] 3501 <1> ; mov ch, al ; cylinder (bits 0-7) 3502 <1> ; shl ah, 6 3503 <1> ; or cl, ah ; cylinder (bits 8-9) 3504 <1> ; ; sector (bits 0-7) 3505 <1> ; pop ebx ; ** ; buffer ; 11/06/2015 3506 <1> ; ; CL = sector (bits 0-5) 3507 <1> ; ; cylinder (bits 8-9 -> bits 6-7) 3508 <1> ; ; CH = cylinder (bits 0-7) 3509 <1> ; ; DH = head 3510 <1> ; ; DL = drive 3511 <1> ; ; 3512 <1> ; mov byte [retry_count], 4 3513 <1> ;rwdsk_retry: 3514 <1> ; ;mov ah, [rwdsk] ; 02h = read, 03h = write 3515 <1> ; ; 08/07/2022 3516 <1> ; mov ah, [rwdsk] ; 01h = read, 02h = write 3517 <1> ; mov al, 1 ; sector count 3518 <1> ; ;int 13h 3519 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3520 <1> ; call int13h 3521 <1> ; mov [esi], ah ; error code ; 10/07/2015 3522 <1> ; jnc short rwdsk_ok ; ah = 0 3523 <1> ; cmp ah, 80h ; time out ? 3524 <1> ; je short rwdsk_fails 3525 <1> ; dec byte [retry_count] 3526 <1> ; jnz short rwdsk_reset 3527 <1> ;rwdsk_fails: 3528 <1> ; stc 3529 <1> ;rwdsk_ok: 3530 <1> ; pop ebx ; *** 3531 <1> ; pop esi ; **** 3532 <1> ; retn 3533 <1> ;rwdsk_reset: 3534 <1> ; ; 02/02/2015 3535 <1> ; sub ah, ah 3536 <1> ; cmp dl, 80h 3537 <1> ; jb short rwdsk_fd_reset 3538 <1> ; ;mov ah, 0Dh ; Alternate reset 3539 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3540 <1> ; mov ah, 5 ; Alternate reset 3541 <1> ;rwdsk_fd_reset: 3542 <1> ; ;int 13h 3543 <1> ; call int13h 3544 <1> ; jnc short rwdsk_retry 3545 <1> ; mov [esi], ah ; error code ; 10/07/2015 3546 <1> ; jmp short rwdsk_ok 3547 <1> 3548 <1> ; Original UNIX v1 - drum (& disk) interrupt routine 3549 <1> ; (Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts) 3550 <1> ; 3551 <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now. 3552 <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 3553 <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h 3554 <1> ; that uses hardware -transfer has been completed- interrupt inside it. 3555 <1> ; In a next Retro UNIX 386 version, these interrupts 3556 <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine 3557 <1> ; as in original unix v1. 3558 <1> ; I am not removing IBM BIOS source code derivatives -compatible code- 3559 <1> ; for now, regarding the new/next 32 bit TRDOS project by me 3560 <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.) 3561 <1> ; 3562 <1> ; Erdogan tan (10/07/2015) 3563 <1> 3564 <1> ;drum: / interrupt handler 3565 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 3566 <1> ; jsr r0,trapt; dcs; rfap; 1 / check for stray interrupt or 3567 <1> ; / error 3568 <1> ; br 3f / no, error 3569 <1> ; br 2f / error 3570 <1> ; 3571 <1> ;disk: 3572 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 3573 <1> ; jmp *$0f 3574 <1> ;0: 3575 <1> ; jsr r0,trapt; rkcs; rkap; 2 3576 <1> ; br 3f / no, errors 3577 <1> ; mov $115,(r2) / drive reset, errbit was set 3578 <1> ; mov $1f,0b-2 / next time jmp *$0f is executed jmp will be 3579 <1> ; / to 1f 3580 <1> ; br 4f 3581 <1> ;1: 3582 <1> ; bit $20000,rkcs 3583 <1> ; beq 4f / wait for seek complete 3584 <1> ; mov $0b,0b-2 3585 <1> ; mov rkap,r1 3586 <1> ;2: 3587 <1> ; bit $3000,(r1) / are bits 9 or 10 set in the 1st word of 3588 <1> ; / the disk buffer 3589 <1> ; bne 3f / no, branch ignore error if outstanding 3590 <1> ; inc r1 3591 <1> ; asr (r1) 3592 <1> ; asr (r1) 3593 <1> ; asr (r1) / reissue request 3594 <1> ; dec r1 3595 <1> ;3: 3596 <1> ; bic $30000,(r1) / clear bits 12 and 13 in 1st word of buffer 3597 <1> ; mov ac,-(sp) 3598 <1> ; mov mq,-(sp) / put these on the stack 3599 <1> ; mov sc,-(sp) 3600 <1> ; jsr r0,poke 3601 <1> ; mov (sp)+,sc 3602 <1> ; mov (sp)+,mq / pop them off stack 3603 <1> ; mov (sp)+,ac 3604 <1> ;4: 3605 <1> ; jmp retisp / u4-3 3606 <1> ; 3607 <1> ;trapt: / r2 points to the 3608 <1> ; mov (r0)+,r2 / device control register 3609 <1> ; mov *(r0)+,r1 / transaction pointer points to buffer 3610 <1> ; tst (sp)+ 3611 <1> ; tstb (r2) / is ready bit of dcs set? 3612 <1> ; bge 4b / device still active so branch 3613 <1> ; bit (r0),active / was device busy? 3614 <1> ; beq 4b / no, stray interrupt 3615 <1> ; bic (r0)+,active / yes, set active to zero 3616 <1> ; tst (r2) / test the err(bit is) of dcs 3617 <1> ; bge 2f / if no error jump to 2f 3618 <1> ; tst (r0)+ / skip on error 3619 <1> ; 2: 3620 <1> ; jmp (r0) 2060 %include 'u9.s' ; 29/06/2015 2061 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - SYS9.INC 2062 <1> ; Last Modification: 13/06/2022 2063 <1> ; ---------------------------------------------------------------------------- 2064 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2065 <1> ; (v0.1 - Beginning: 11/07/2012) 2066 <1> ; 2067 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2068 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2069 <1> ; 2070 <1> ; 2071 <1> ; 2072 <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s 2073 <1> ; 2074 <1> ; **************************************************************************** 2075 <1> ; 21/11/2015 2076 <1> 2077 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) - Printer BIOS (Functions) 2078 <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18) 2079 <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 2080 <1> 2081 <1> getch: 2082 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2083 <1> ; 30/06/2015 2084 <1> ; 18/02/2015 - Retro UNIX 386 v1 - feature only! 2085 00005583 28C0 <1> sub al, al ; 0 2086 <1> getch_q: ; 06/08/2015 2087 00005585 8A25[66610000] <1> mov ah, [ptty] ; active (current) video page 2088 0000558B EB06 <1> jmp short getc_n 2089 <1> 2090 <1> getc: 2091 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2092 <1> ; 12/11/2015 2093 <1> ; 15/09/2015 2094 <1> ; 01/07/2015 2095 <1> ; 30/06/2015 2096 <1> ; 18/02/2015 (Retro UNIX 386 v1 - Beginning) 2097 <1> ; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1) 2098 <1> ; 2099 <1> ; Retro UNIX 8086 v1 modification ! 2100 <1> ; 2101 <1> ; 'getc' gets (next) character 2102 <1> ; from requested TTY (keyboard) buffer 2103 <1> ; INPUTS -> 2104 <1> ; [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2) 2105 <1> ; AL=0 -> Get (next) character from requested TTY buffer 2106 <1> ; (Keyboard buffer will point to 2107 <1> ; next character at next call) 2108 <1> ; AL=1 -> Test a key is available in requested TTY buffer 2109 <1> ; (Keyboard buffer will point to 2110 <1> ; current character at next call) 2111 <1> ; OUTPUTS -> 2112 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 2113 <1> ; ZF=0 -> AX has (current) character 2114 <1> ; AL = ascii code 2115 <1> ; AH = scan code (AH = line status for COM1 or COM2) 2116 <1> ; (cf=1 -> error code/flags in AH) 2117 <1> ; Original UNIX V1 'getc': 2118 <1> ; get a character off character list 2119 <1> ; 2120 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2121 <1> ; 2122 <1> ; 30/06/2015 (32 bit modifications) 2123 <1> ; 16/07/2013 2124 <1> ; mov [getctty], ah 2125 <1> ; 2126 <1> 2127 0000558D 8A25[4E650000] <1> mov ah, [u.ttyn] ; 28/07/2013 2128 <1> getc_n: 2129 <1> ; 30/06/2015 2130 00005593 08E4 <1> or ah, ah 2131 00005595 740D <1> jz short getc0 2132 00005597 D0E4 <1> shl ah, 1 2133 00005599 0FB6DC <1> movzx ebx, ah 2134 0000559C 81C3[68610000] <1> add ebx, ttychr 2135 000055A2 EB05 <1> jmp short getc1 2136 <1> getc0: 2137 000055A4 BB[68610000] <1> mov ebx, ttychr 2138 <1> getc1: 2139 000055A9 668B0B <1> mov cx, [ebx] ; ascii & scan code 2140 <1> ; (by kb_int) 2141 000055AC 6609C9 <1> or cx, cx 2142 000055AF 7507 <1> jnz short getc2 2143 000055B1 20C0 <1> and al, al 2144 000055B3 7415 <1> jz short getc_s 2145 <1> ;xor ax, ax 2146 <1> ; 24/12/2021 2147 000055B5 31C0 <1> xor eax, eax 2148 000055B7 C3 <1> retn 2149 <1> getc2: 2150 000055B8 20C0 <1> and al, al 2151 000055BA 6689C8 <1> mov ax, cx 2152 000055BD 66B90000 <1> mov cx, 0 2153 000055C1 7506 <1> jnz short getc3 2154 <1> getc_sn: 2155 000055C3 66890B <1> mov [ebx], cx ; 0, reset 2156 000055C6 6639C8 <1> cmp ax, cx ; zf = 0 2157 <1> getc3: 2158 000055C9 C3 <1> retn 2159 <1> getc_s: 2160 <1> ; 12/11/2015 2161 <1> ; 15/09/2015 2162 <1> ; 01/07/2015 2163 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2164 <1> ; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2165 <1> ; 2166 <1> ; tty of the current process is not 2167 <1> ; current tty (ptty); so, current process only 2168 <1> ; can use keyboard input when its tty becomes 2169 <1> ; current tty (ptty). 2170 <1> ; 'sleep' is for preventing an endless lock 2171 <1> ; during this tty input request. 2172 <1> ; (Because, the user is not looking at the video page 2173 <1> ; of the process to undersand there is a keyboard 2174 <1> ; input request.) 2175 <1> ; 2176 <1> ;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2177 <1> ; 2178 <1> ; 05/10/2013 2179 <1> ; ah = byte ptr [u.ttyn] ; (tty number) 2180 <1> ; 2181 <1> ; 10/10/2013 2182 <1> gcw0: 2183 000055CA B10A <1> mov cl, 10 ; ch = 0 2184 <1> gcw1: 2185 <1> ; 12/11/2015 2186 000055CC E814DCFFFF <1> call intract ; jumps to 'sysexit' if [u.quit] = FFFFh 2187 <1> ; 10/10/2013 2188 000055D1 E8B2EFFFFF <1> call idle 2189 000055D6 668B03 <1> mov ax, [ebx] ; ascii & scan code 2190 <1> ; (by kb_int) 2191 000055D9 6609C0 <1> or ax, ax 2192 <1> ; jnz short gcw3 2193 000055DC 7519 <1> jnz short gcw2 ; 15/09/2015 2194 <1> ; 30/06/2015 2195 000055DE FEC9 <1> dec cl 2196 000055E0 75EA <1> jnz short gcw1 2197 <1> ; 2198 000055E2 8A25[4E650000] <1> mov ah, [u.ttyn] ; 20/10/2013 2199 <1> ; ; 10/12/2013 2200 <1> ; cmp ah, [ptty] 2201 <1> ; jne short gcw2 2202 <1> ; ; 14/02/2014 2203 <1> ; cmp byte [u.uno], 1 2204 <1> ; jna short gcw0 2205 <1> ;gcw2: 2206 000055E8 E828F0FFFF <1> call sleep 2207 <1> ; 2208 <1> ; 20/09/2013 2209 000055ED 8A25[4E650000] <1> mov ah, [u.ttyn] 2210 000055F3 30C0 <1> xor al, al 2211 000055F5 EB9C <1> jmp short getc_n 2212 <1> ;gcw3: 2213 <1> gcw2: ; 15/09/2015 2214 <1> ; 10/10/2013 2215 000055F7 30C9 <1> xor cl, cl 2216 000055F9 EBC8 <1> jmp short getc_sn 2217 <1> 2218 <1> putc: 2219 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2220 <1> ; 13/08/2015 2221 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2222 <1> ; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1) 2223 <1> ; 2224 <1> ; Retro UNIX 8086 v1 modification ! 2225 <1> ; 2226 <1> ; 'putc' puts a character 2227 <1> ; onto requested (tty) video page or 2228 <1> ; serial port 2229 <1> ; INPUTS -> 2230 <1> ; AL = ascii code of the character 2231 <1> ; AH = video page (tty) number (0 to 7) 2232 <1> ; (8 is COM1, 9 is COM2) 2233 <1> ; OUTPUTS -> 2234 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 2235 <1> ; ZF=0 -> AX has (current) character 2236 <1> ; cf=0 and AH = 0 -> no error 2237 <1> ; cf=1 and AH > 0 -> error (only for COM1 and COM2) 2238 <1> ; 2239 <1> ; Original UNIX V1 'putc': 2240 <1> ; put a character at the end of character list 2241 <1> ; 2242 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2243 <1> ; 2244 000055FB 80FC07 <1> cmp ah, 7 2245 <1> ;ja sndc 2246 000055FE 770A <1> ja short sndc ; 24/12/2024 2247 <1> ; 30/06/2015 2248 00005600 0FB6DC <1> movzx ebx, ah 2249 <1> ; 13/08/2015 2250 00005603 B407 <1> mov ah, 07h ; black background, light gray character color 2251 00005605 E9ABBCFFFF <1> jmp write_tty ; 'video.inc' 2252 <1> 2253 <1> sndc: ; 2254 <1> ; 2255 <1> ; 12/01/2022 2256 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2257 <1> ; 17/11/2015 2258 <1> ; 16/11/2015 2259 <1> ; 11/11/2015 2260 <1> ; 10/11/2015 2261 <1> ; 09/11/2015 2262 <1> ; 08/11/2015 2263 <1> ; 07/11/2015 2264 <1> ; 06/11/2015 (serial4.asm, 'sendchr') 2265 <1> ; 29/10/2015 2266 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2267 <1> ; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1) 2268 <1> ; 2269 <1> ; Retro UNIX 8086 v1 feature only ! 2270 <1> ; 2271 <1> ; ah = [u.ttyn] 2272 <1> ; 2273 <1> ; 30/06/2015 2274 0000560A 80EC08 <1> sub ah, 8 ; ; 0 = tty8 or 1 = tty9 2275 <1> ; 07/11/2015 2276 0000560D 0FB6DC <1> movzx ebx, ah ; serial port index (0 or 1) 2277 <1> sndc0: 2278 <1> ; 07/11/2015 2279 00005610 E84EF0FFFF <1> call isintr ; quit (ctrl+break) check 2280 00005615 7405 <1> jz short sndc1 2281 00005617 E8C9DBFFFF <1> call intract ; quit (ctrl+break) check 2282 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 2283 <1> sndc1: 2284 <1> ; 16/11/2015 2285 <1> ;mov cx, ax ; *** al = character (to be sent) 2286 <1> ; 24/12/2021 2287 0000561C 89C1 <1> mov ecx, eax ; *** al = character (to be sent) 2288 <1> sndcx: 2289 0000561E 8A83[AA610000] <1> mov al, [ebx+schar] ; last sent character 2290 00005624 8AA3[A8610000] <1> mov ah, [ebx+rchar] ; last received character 2291 <1> ; 2292 <1> ; 17/11/2015 2293 <1> ; check 'request for response' status 2294 0000562A 80BB[A4610000]00 <1> cmp byte [ebx+req_resp], 0 2295 00005631 740A <1> jz short query 2296 <1> response: 2297 00005633 FE05[A7610000] <1> inc byte [comqr] ; query or response status 2298 00005639 B0FF <1> mov al, 0FFh 2299 0000563B EB14 <1> jmp short sndc3 2300 <1> query: 2301 0000563D 08C0 <1> or al, al ; 0 = query (also end of text) 2302 0000563F 750E <1> jnz short sndc2 ; normal character 2303 <1> ;cmp ah, 0FFh ; is it responded by terminal ? 2304 <1> ;je short sndc2 ; yes, already responded 2305 <1> ; 16/11/2015 2306 <1> ; query: request for response (again) 2307 00005641 8883[A8610000] <1> mov [ebx+rchar], al ; 0 ; reset 2308 00005647 FE05[A7610000] <1> inc byte [comqr] ; query or response status 2309 0000564D EB02 <1> jmp short sndc3 2310 <1> sndc2: 2311 0000564F 88C8 <1> mov al, cl ; *** character (to be sent) 2312 <1> sndc3: 2313 00005651 8883[AA610000] <1> mov [ebx+schar], al ; current character (to be sent) 2314 00005657 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 2315 <1> ; 30/06/2015 2316 00005659 E839D5FFFF <1> call sp_status ; get serial port status 2317 <1> ; AL = Line status, AH = Modem status 2318 <1> ; 07/11/2015 2319 0000565E A880 <1> test al, 80h 2320 00005660 7504 <1> jnz short sndc4 2321 00005662 A820 <1> test al, 20h ; Transmitter holding register empty ? 2322 00005664 751A <1> jnz short sndc5 2323 <1> sndc4: ; Check line status again 2324 <1> ; 16/11/2015 2325 <1> ;push cx 2326 <1> ; 24/12/2021 2327 00005666 51 <1> push ecx 2328 <1> ;mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 2329 <1> ; 12/01/2022 2330 00005667 31C9 <1> xor ecx, ecx 2331 00005669 B106 <1> mov cl, 6 2332 0000566B E83CBDFFFF <1> call WAITF 2333 <1> ;pop cx 2334 <1> ; 24/12/1021 2335 00005670 59 <1> pop ecx 2336 <1> ; 2337 00005671 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 2338 00005673 E81FD5FFFF <1> call sp_status ; get serial port status 2339 <1> ; 16/11/2015 2340 <1> ; 09/11/2015 2341 <1> ; 08/11/2015 2342 00005678 A880 <1> test al, 80h ; time out error 2343 0000567A 7565 <1> jnz short sndc7 2344 0000567C A820 <1> test al, 20h ; Transmitter holding register empty ? 2345 0000567E 7461 <1> jz short sndc7 2346 <1> sndc5: 2347 00005680 8A83[AA610000] <1> mov al, [ebx+schar] ; character (to be sent) 2348 00005686 66BAF803 <1> mov dx, 3F8h ; data port (COM2) 2349 0000568A 28DE <1> sub dh, bl 2350 0000568C EE <1> out dx, al ; send on serial port 2351 <1> ; 10/11/2015 2352 <1> ; delay for 3*30 (3*(15..80)) micro seconds 2353 <1> ; (to improve text flow to the terminal) 2354 <1> ; ('diskette.inc': 'WAITF') 2355 <1> ; Uses port 61h, bit 4 to have CPU speed independent waiting. 2356 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2357 <1> ;push cx 2358 <1> ; 24/12/2021 2359 0000568D 51 <1> push ecx 2360 <1> ;mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 2361 <1> ; 12/01/2022 2362 0000568E 29C9 <1> sub ecx, ecx 2363 00005690 B106 <1> mov cl, 6 2364 00005692 E815BDFFFF <1> call WAITF 2365 <1> ;pop cx 2366 <1> ; 24/12/1021 2367 00005697 59 <1> pop ecx 2368 <1> ; 2369 <1> ; 07/11/2015 2370 00005698 88D8 <1> mov al, bl ; al = 0 (tty8) or 1 (tty9) 2371 <1> ; 2372 0000569A E8F8D4FFFF <1> call sp_status ; get serial port status 2373 <1> ; AL = Line status, AH = Modem status 2374 <1> ; 2375 0000569F E8BFEFFFFF <1> call isintr ; quit (ctrl+break) check 2376 000056A4 7405 <1> jz short sndc6 2377 000056A6 E83ADBFFFF <1> call intract ; quit (ctrl+break) check 2378 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 2379 <1> sndc6: 2380 000056AB 3C80 <1> cmp al, 80h 2381 000056AD 7332 <1> jnb short sndc7 2382 <1> ; 2383 000056AF 803D[A7610000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 2384 000056B6 7244 <1> jb short sndc8 ; no, normal character 2385 000056B8 883D[A7610000] <1> mov byte [comqr], bh ; 0 ; reset 2386 <1> ; 17/11/2015 2387 000056BE E8C5EEFFFF <1> call idle 2388 <1> ; 2389 000056C3 38BB[AA610000] <1> cmp [ebx+schar], bh ; 0 ; query ? 2390 <1> ;ja sndc2 ; response (will be followed by 2391 <1> ; a normal character) 2392 <1> ; 24/12/2021 2393 000056C9 7602 <1> jna short sndc_10 2394 000056CB EB82 <1> jmp sndc2 2395 <1> sndc_10: 2396 <1> ; Query request must be responded by the terminal 2397 <1> ; before sending a normal character ! 2398 000056CD 53 <1> push ebx 2399 <1> ;push cx ; *** cl = character (to be sent) 2400 <1> ; 24/12/2021 2401 000056CE 51 <1> push ecx ; *** cl = character (to be sent) 2402 000056CF 8A25[4E650000] <1> mov ah, [u.ttyn] 2403 000056D5 E83BEFFFFF <1> call sleep ; this process will be awakened by 2404 <1> ; received data available interrupt 2405 <1> ;pop cx ; *** cl = character (to be sent) 2406 <1> ; 24/12/2021 2407 000056DA 59 <1> pop ecx ; *** cl = character (to be sent) 2408 000056DB 5B <1> pop ebx 2409 000056DC E93DFFFFFF <1> jmp sndcx 2410 <1> sndc7: 2411 <1> ; 16/11/2015 2412 000056E1 803D[A7610000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 2413 000056E8 7213 <1> jb short sndc9 ; no 2414 <1> ; 2415 000056EA 88BB[A8610000] <1> mov [ebx+rchar], bh ; 0 ; reset 2416 000056F0 88BB[AA610000] <1> mov [ebx+schar], bh ; 0 ; reset 2417 <1> ; 2418 000056F6 883D[A7610000] <1> mov byte [comqr], bh ; 0 ; reset 2419 <1> sndc8: 2420 000056FC F5 <1> cmc ; jnc -> jc, jb -> jnb 2421 <1> sndc9: 2422 <1> ; AL = Line status, AH = Modem status 2423 000056FD C3 <1> retn 2424 <1> 2425 <1> get_cpos: 2426 <1> ; 29/06/2015 (Retro UNIX 386 v1) 2427 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 2428 <1> ; 2429 <1> ; INPUT -> bl = video page number 2430 <1> ; RETURN -> dx = cursor position 2431 <1> 2432 000056FE 53 <1> push ebx 2433 000056FF 83E30F <1> and ebx, 0Fh ; 07h ; tty0 to tty7 2434 00005702 D0E3 <1> shl bl, 1 2435 00005704 81C3[56610000] <1> add ebx, cursor_posn 2436 0000570A 668B13 <1> mov dx, [ebx] 2437 0000570D 5B <1> pop ebx 2438 0000570E C3 <1> retn 2439 <1> 2440 <1> read_ac_current: 2441 <1> ; 29/06/2015 (Retro UNIX 386 v1) 2442 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 2443 <1> ; 2444 <1> ; INPUT -> bl = video page number 2445 <1> ; RETURN -> ax = character (al) and attribute (ah) 2446 <1> 2447 0000570F E807BDFFFF <1> call find_position ; 'video.inc' 2448 <1> ; dx = status port 2449 <1> ; esi = cursor location/address 2450 00005714 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 2451 0000571A 668B06 <1> mov ax, [esi] ; get the character and attribute 2452 0000571D C3 <1> retn 2453 <1> 2454 <1> syssleep: 2455 <1> ; 29/06/2015 - (Retro UNIX 386 v1) 2456 <1> ; 11/06/2014 - (Retro UNIX 8086 v1) 2457 <1> ; 2458 <1> ; Retro UNIX 8086 v1 feature only 2459 <1> ; (INPUT -> none) 2460 <1> ; 2461 0000571E 0FB61D[49650000] <1> movzx ebx, byte [u.uno] ; process number 2462 00005725 8AA3[53620000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 2463 0000572B E8E5EEFFFF <1> call sleep 2464 00005730 E9CCD9FFFF <1> jmp sysret 2465 <1> 2466 <1> ; 27/02/2022 2467 <1> ; (u1.s, 'wttyc' & 'wpc_clr') 2468 <1> %if 0 2469 <1> 2470 <1> vp_clr: 2471 <1> ; Reset/Clear Video Page 2472 <1> ; 2473 <1> ; 24/12/2021 - (Retro UNIX 386 v1.1) 2474 <1> ; 30/06/2015 - (Retro UNIX 386 v1) 2475 <1> ; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM) 2476 <1> ; 2477 <1> ; Retro UNIX 8086 v1 feature only ! 2478 <1> ; 2479 <1> ; INPUTS -> 2480 <1> ; BL = video page number 2481 <1> ; 2482 <1> ; OUTPUT -> 2483 <1> ; none 2484 <1> ; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI)) 2485 <1> ; 2486 <1> ; 04/12/2013 2487 <1> sub al, al 2488 <1> ; al = 0 (clear video page) 2489 <1> ; bl = video page 2490 <1> mov ah, 07h 2491 <1> ; ah = 7 (attribute/color) 2492 <1> ;xor cx, cx ; 0, left upper column (cl) & row (cl) 2493 <1> ; 24/12/2021 2494 <1> xor ecx, ecx 2495 <1> mov dx, 184Fh ; right lower column & row (dl=24, dh=79) 2496 <1> call scroll_up 2497 <1> ; bl = video page 2498 <1> ;xor dx, dx ; 0 (cursor position) 2499 <1> ; 24/12/2021 2500 <1> xor edx, edx 2501 <1> jmp set_cpos 2502 <1> 2503 <1> %endif 2504 <1> 2505 <1> sysmsg: 2506 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2507 <1> ; 11/11/2015 2508 <1> ; 01/07/2015 - (Retro UNIX 386 v1 feature only!) 2509 <1> ; Print user-application message on user's console tty 2510 <1> ; 2511 <1> ; Input -> EBX = Message address 2512 <1> ; ECX = Message length (max. 255) 2513 <1> ; DL = Color (IBM PC Rombios color attributes) 2514 <1> ; 2515 00005735 81F9FF000000 <1> cmp ecx, MAX_MSG_LEN ; 255 2516 <1> ;ja sysret ; nothing to do with big message size 2517 0000573B 7779 <1> ja short sysmsg8 ; 24/12/2021 2518 0000573D 08C9 <1> or cl, cl 2519 <1> ;jz sysret 2520 0000573F 7475 <1> jz short sysmsg8 ; 24/12/2021 2521 00005741 20D2 <1> and dl, dl 2522 00005743 7502 <1> jnz short sysmsg0 2523 00005745 B207 <1> mov dl, 07h ; default color 2524 <1> ; (black background, light gray character) 2525 <1> sysmsg0: 2526 00005747 891D[20650000] <1> mov [u.base], ebx 2527 0000574D 8815[67610000] <1> mov [ccolor], dl ; color attributes 2528 00005753 89E5 <1> mov ebp, esp 2529 00005755 31DB <1> xor ebx, ebx ; 0 2530 00005757 891D[28650000] <1> mov [u.nread], ebx ; 0 2531 <1> ; 2532 0000575D 381D[61650000] <1> cmp [u.kcall], bl ; 0 2533 00005763 7772 <1> ja short sysmsgk ; Temporary (01/07/2015) 2534 <1> ; 2535 00005765 890D[24650000] <1> mov [u.count], ecx 2536 0000576B 41 <1> inc ecx ; + 00h ; ASCIIZ 2537 <1> ; 24/12/2021 2538 <1> ; (dword alignment for esp) 2539 0000576C F6C103 <1> test cl, 3 2540 0000576F 7404 <1> jz short sysmsg_7 2541 00005771 80C903 <1> or cl, 3 2542 00005774 41 <1> inc ecx 2543 <1> sysmsg_7: 2544 00005775 29CC <1> sub esp, ecx 2545 00005777 89E7 <1> mov edi, esp 2546 00005779 89E6 <1> mov esi, esp 2547 0000577B 66891D[5F650000] <1> mov [u.pcount], bx ; reset page (phy. addr.) counter 2548 <1> ; 11/11/2015 2549 00005782 8A25[30650000] <1> mov ah, [u.ttyp] ; recent open tty 2550 <1> ; 0 = none 2551 00005788 FECC <1> dec ah 2552 0000578A 790C <1> jns short sysmsg1 2553 0000578C 8A1D[49650000] <1> mov bl, [u.uno] ; process number 2554 00005792 8AA3[53620000] <1> mov ah, [ebx+p.ttyc-1] ; user's (process's) console tty 2555 <1> sysmsg1: 2556 00005798 8825[4E650000] <1> mov [u.ttyn], ah 2557 <1> sysmsg2: 2558 0000579E E84BF6FFFF <1> call cpass 2559 000057A3 7416 <1> jz short sysmsg5 2560 000057A5 AA <1> stosb 2561 000057A6 20C0 <1> and al, al 2562 000057A8 75F4 <1> jnz short sysmsg2 2563 <1> sysmsg3: 2564 000057AA 80FC07 <1> cmp ah, 7 ; tty number 2565 000057AD 7711 <1> ja short sysmsg6 ; serial port 2566 000057AF E83E000000 <1> call print_cmsg 2567 <1> sysmsg4: 2568 000057B4 89EC <1> mov esp, ebp 2569 <1> sysmsg8: ; 24/12/2021 2570 000057B6 E946D9FFFF <1> jmp sysret 2571 <1> sysmsg5: 2572 000057BB C60700 <1> mov byte [edi], 0 2573 000057BE EBEA <1> jmp short sysmsg3 2574 <1> sysmsg6: 2575 000057C0 8A06 <1> mov al, [esi] 2576 000057C2 E843FEFFFF <1> call sndc 2577 000057C7 72EB <1> jc short sysmsg4 2578 000057C9 803E00 <1> cmp byte [esi], 0 ; 0 is stop character 2579 000057CC 76E6 <1> jna short sysmsg4 2580 000057CE 46 <1> inc esi 2581 000057CF 8A25[4E650000] <1> mov ah, [u.ttyn] 2582 000057D5 EBE9 <1> jmp short sysmsg6 2583 <1> 2584 <1> sysmsgk: ; Temporary (01/07/2015) 2585 <1> ; The message has been sent by Kernel (ASCIIZ string) 2586 <1> ; (ECX -character count- will not be considered) 2587 000057D7 8B35[20650000] <1> mov esi, [u.base] 2588 000057DD 8A25[66610000] <1> mov ah, [ptty] ; present/current screen (video page) 2589 000057E3 8825[4E650000] <1> mov [u.ttyn], ah 2590 000057E9 C605[61650000]00 <1> mov byte [u.kcall], 0 2591 000057F0 EBB8 <1> jmp short sysmsg3 2592 <1> 2593 <1> print_cmsg: 2594 <1> ; 01/07/2015 (retro UNIX 386 v1 feature only !) 2595 <1> ; 2596 <1> ; print message (on user's console tty) 2597 <1> ; with requested color 2598 <1> ; 2599 <1> ; INPUTS: 2600 <1> ; esi = message address 2601 <1> ; [u.ttyn] = tty number (0 to 7) 2602 <1> ; [ccolor] = color attributes (IBM PC BIOS colors) 2603 <1> ; 2604 000057F2 AC <1> lodsb 2605 <1> pcmsg1: 2606 000057F3 56 <1> push esi 2607 000057F4 0FB61D[4E650000] <1> movzx ebx, byte [u.ttyn] 2608 000057FB 8A25[67610000] <1> mov ah, [ccolor] 2609 00005801 E8AFBAFFFF <1> call write_tty 2610 00005806 5E <1> pop esi 2611 00005807 AC <1> lodsb 2612 00005808 20C0 <1> and al, al ; 0 2613 0000580A 75E7 <1> jnz short pcmsg1 2614 0000580C C3 <1> retn 2615 <1> 2616 <1> sysgeterr: 2617 <1> ; 16/02/2022 2618 <1> ; 09/12/2015 2619 <1> ; 21/09/2015 - (Retro UNIX 386 v1 feature only!) 2620 <1> ; Get last error number or page fault count 2621 <1> ; (for debugging) 2622 <1> ; 2623 <1> ; Input -> EBX = return type 2624 <1> ; 0 = last error code (which is in 'u.error') 2625 <1> ; FFFFFFFFh = page fault count for running process 2626 <1> ; FFFFFFFEh = total page fault count 2627 <1> ; 1 .. FFFFFFFDh = undefined 2628 <1> ; 2629 <1> ; Output -> EAX = last error number or page fault count 2630 <1> ; (depending on EBX input) 2631 <1> ; 2632 0000580D 21DB <1> and ebx, ebx 2633 0000580F 750F <1> jnz short glerr_2 2634 <1> glerr_0: 2635 00005811 A1[4F650000] <1> mov eax, [u.error] 2636 <1> glerr_1: 2637 00005816 A3[00650000] <1> mov [u.r0], eax 2638 <1> ;retn 2639 <1> ; 16/02/2022 (BugFix) 2640 0000581B E9E1D8FFFF <1> jmp sysret 2641 <1> glerr_2: 2642 00005820 43 <1> inc ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh 2643 00005821 74FD <1> jz short glerr_2 ; page fault count for process 2644 00005823 43 <1> inc ebx ; FFFFFFFFh -> 0 2645 00005824 75EB <1> jnz short glerr_0 2646 00005826 A1[EC610000] <1> mov eax, [PF_Count] ; total page fault count 2647 0000582B EBE9 <1> jmp short glerr_1 2648 <1> glerr_3: 2649 0000582D A1[63650000] <1> mov eax, [u.pfcount] 2650 00005832 EBE2 <1> jmp short glerr_1 2651 <1> 2652 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) 2653 <1> ; - PRINTER BIOS (Functions) 2654 <1> 2655 <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 2656 <1> ; 2657 <1> ;--- INT 17 H ------------------------------------------------------------------ 2658 <1> ; PRINTER_IO : 2659 <1> ; THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER : 2660 <1> ; INPUT : 2661 <1> ; (AH)= 00H PRINT THE CHARACTER IN (AL) : 2662 <1> ; ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT) : 2663 <1> ; OTHER BITS SET AS ON NORMAL STATUS CALL : 2664 <1> ; (AH)= 01H INITIALIZE THE PRINTER PORT : 2665 <1> ; RETURNS WITH (AH) SET WITH PRINTER STATUS : 2666 <1> ; (AH)= 02H READ THE PRINTER STATUS INTO (AH) : 2667 <1> ; 7 6 5 4 3 2-1 0 : 2668 <1> ; | | | | | | |_TIME OUT : 2669 <1> ; | | | | | | : 2670 <1> ; | | | | | |_ UNUSED : 2671 <1> ; | | | | | : 2672 <1> ; | | | | |_ 1 = I/O ERROR : 2673 <1> ; | | | | : 2674 <1> ; | | | |_ 1 = SELECTED : 2675 <1> ; | | | : 2676 <1> ; | | |_ 1 = OUT OF PAPER : 2677 <1> ; | | : 2678 <1> ; | |_ 1 = ACKNOWLEDGE : 2679 <1> ; | : 2680 <1> ; |_ 1 = NOT BUSY : 2681 <1> ; : 2682 <1> ; (DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES : 2683 <1> ; IN @PRINTER_BASE AREA : 2684 <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S) : 2685 <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS) : 2686 <1> ; : 2687 <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT : 2688 <1> ; TIME OUT WAITS. DEFAULT=20 * 4 : 2689 <1> ; : 2690 <1> ; REGISTERS (AH) IS MODIFIED WITH STATUS INFORMATION : 2691 <1> ; ALL OTHERS UNCHANGED : 2692 <1> ;------------------------------------------------------------------------------- 2693 <1> 2694 <1> int17h: 2695 <1> ; 13/06/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.20) 2696 <1> ; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985) 2697 <1> ; 2698 <1> ; (Default printer port: 378h) ; LPT1 2699 <1> ; (Number of printers = 1) 2700 <1> 2701 <1> PRINTER_BASE equ 378h ; LPT1 2702 <1> ;PRINT_TIM_OUT equ 4*80*65536 2703 <1> ; (Ref: IBM PC-AT BIOS v2 PRT.ASM) 2704 <1> 2705 <1> PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY 2706 <1> ; (Ref: AWARD BIOS 1999 ATORGS.ASM) 2707 <1> 2708 <1> ; INPUT: 2709 <1> ; ah = 0 -> print the character in AL 2710 <1> ; (sys write with write count >0) 2711 <1> ; ah = 1 -> initialize printer port 2712 <1> ; (sys open) 2713 <1> ; ah = 2 -> read the printer status 2714 <1> ; (sys write with write count = 0) 2715 <1> ; OUTPUT: 2716 <1> ; ah = printer status 2717 <1> 2718 <1> ; Modified registers: eax, ecx, edx 2719 <1> 2720 <1> PRINTER_IO_1: 2721 00005834 08E4 <1> or ah, ah 2722 00005836 7417 <1> jz short _b20 2723 00005838 FECC <1> dec ah 2724 0000583A 7444 <1> jz short _b80 2725 <1> ;dec ah 2726 <1> ;jz short _b50 2727 <1> _b50: 2728 <1> ;----- PRINTER STATUS 2729 <1> B50: 2730 0000583C 50 <1> push eax ; SAVE (AL) REGISTER 2731 <1> B60: 2732 0000583D 66BA7903 <1> mov dx, PRINTER_BASE+1 2733 <1> ; GET PRINTER ATTACHMENT BASE ADDRESS 2734 <1> ; POINT TO CONTROL PORT 2735 00005841 EC <1> in al, dx ; PRE-CHARGE +BUSY LINE IF FLOATING 2736 00005842 EC <1> in al, dx ; GET PRINTER STATUS HARDWARE BITS 2737 00005843 88C4 <1> mov ah, al ; SAVE 2738 00005845 80E4F8 <1> and ah, 0F8h ; TURN OFF UNUSED BITS 2739 <1> B70: 2740 00005848 5A <1> pop edx ; RECOVER (AL) REGISTER 2741 00005849 88D0 <1> mov al, dl ; MOVE CHARACTER INTO (AL) 2742 0000584B 80F448 <1> xor ah, 48h ; FLIP A COUPLE OF BITS 2743 <1> B10: 2744 0000584E C3 <1> retn ; RETURN FROM ROUTINE WITH STATUS IN AH 2745 <1> _b20: 2746 <1> ;----- PRINT THE CHARACTER IN (AL) 2747 0000584F B9A08C0000 <1> mov ecx, PRINT_TIM_OUT ; (1 second) 2748 <1> B20: 2749 00005854 50 <1> push eax ; SAVE VALUE TO PRINT 2750 00005855 66BA7803 <1> mov dx, PRINTER_BASE 2751 00005859 EE <1> out dx, al ; OUTPUT CHARACTER TO DATA PORT 2752 0000585A FEC2 <1> inc dl ; POINT TO STATUS PORT 2753 <1> 2754 <1> ;----- CHECK FOR PRINTER BUSY 2755 <1> B25: 2756 <1> ;----- WAIT BUSY 2757 <1> B35: 2758 0000585C EC <1> in al, dx ; GET STATUS 2759 0000585D 88C4 <1> mov ah, al ; STATUS TO (AH) ALSO 2760 0000585F A880 <1> test al, 80h ; IS THE PRINTER CURRENTLY BUSY? (*) 2761 00005861 750F <1> jnz short B40 ; GO TO OUTPUT STROBE 2762 00005863 E831000000 <1> call WAIT_REFRESH ; (wait for 30 micro seconds) 2763 00005868 E2F2 <1> loop B35 ; LOOP IF YES (*) 2764 <1> 2765 0000586A 80CC01 <1> or ah, 1 ; SET ERROR FLAG 2766 0000586D 80E4F9 <1> and ah, 0F9h ; TURN OFF THE UNUSED BITS 2767 00005870 EBD6 <1> jmp short B70 ; RETURN WITH ERROR FLAG SET 2768 <1> 2769 <1> B40: ; SEND STROBE PULSE 2770 00005872 B00D <1> mov al, 0Dh ; SET THE STROBE LOW (BIT ON) 2771 00005874 6642 <1> inc dx ; OUTPUT STROBE TO CONTROL PORT 2772 00005876 FA <1> cli ; PREVENT INTERRUPT PULSE STRETCHING 2773 00005877 EE <1> out dx, al ; OUTPUT STROBE BIT > 1us < 5us 2774 <1> ; IODELAY 2775 <1> ;jmp short $+2 ; I/O DELAY TO ALLOW FOR LINE LOADING 2776 <1> ;jmp short $+2 ; AND FOR CORRECT PULSE WIDTH 2777 <1> ; NEWIODELAY 2778 00005878 E6EB <1> out 0EBh, al 2779 <1> 2780 0000587A B00C <1> mov al, 0Ch ; SET THE -STROBE HIGH 2781 0000587C EE <1> out dx, al 2782 0000587D FB <1> sti ; INTERRUPTS BACK ON 2783 <1> ;pop eax ; RECOVER THE OUTPUT CHAR 2784 <1> ;jmp short B50 2785 0000587E EBBD <1> jmp short B60 2786 <1> 2787 <1> _b80: 2788 <1> ;----- INITIALIZE THE PRINTER PORT 2789 <1> B80: 2790 00005880 50 <1> push eax ; SAVE (AL) 2791 00005881 66BA7A03 <1> mov dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT 2792 00005885 B008 <1> mov al, 8 ; SET INIT LINE LOW 2793 00005887 EE <1> out dx, al 2794 <1> ;mov eax, 1000*4 ; ADJUST FOR INITIALIZATION DELAY LOOP 2795 00005888 B989080000 <1> mov ecx, WAIT_PRN_INIT ; (65536 micro seconds) 2796 <1> B90: ; INIT_LOOP 2797 <1> ;dec eax ; LOOP FOR RESET TO TAKE 2798 <1> ;jnz short B90 ; INIT_LOOP 2799 0000588D E807000000 <1> call WAIT_REFRESH ; (wait for 30 micro seconds) 2800 00005892 E2F9 <1> loop B90 2801 00005894 B00C <1> mov al, 0Ch ; NO INTERRUPTS, NON AUTO LF, INIT HIGH 2802 00005896 EE <1> out dx, al 2803 00005897 EBA4 <1> jmp short B60 ; EXIT THROUGH STATUS ROUTINE 2804 <1> 2805 <1> 2806 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 2807 <1> ; ------------------------------------------------------------------- 2808 <1> ; 2809 <1> ;;Wait while printer initializes should be 65,536 microseconds. 2810 <1> ;;65536/30 = 2185 2811 <1> ; PUBLIC WAIT_PRN_INIT_LO 2812 <1> ;WAIT_PRN_INIT_LO DW 2185 2813 <1> ; PUBLIC WAIT_PRN_INIT_HI 2814 <1> ;WAIT_PRN_INIT_HI DW 0 2815 <1> ; 2816 <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022 2817 <1> ; 2818 <1> ;;Wait for printer not busy should be 1,080,000 microseconds. 2819 <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us. 2820 <1> ;;1,080,000 / 30 = 36,000 2821 <1> ; PUBLIC WAIT_PRN_NBUSY_LO 2822 <1> ;WAIT_PRN_NBUSY_LO DW 36000 2823 <1> ; PUBLIC WAIT_PRN_NBUSY_HI 2824 <1> ;WAIT_PRN_NBUSY_HI DB 0 2825 <1> ; 2826 <1> ;WAIT_PRN_NBUSY equ 36000 ; 12/06/2022 2827 <1> 2828 <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999) 2829 <1> ; ------------------------------------------ 2830 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 2831 <1> ; INPUT: BX:CX = number of refresh periods to wait 2832 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2833 <1> ; OUTPUT: BX:CX destroyed. 2834 <1> ; 2835 <1> ; SAVES: AX (except when NO STACK) 2836 <1> ; 2837 <1> ; NOTES: This routine can be (and is) used with no stack. When 2838 <1> ; used this way, AX is assumed to be destroyed. 2839 <1> 2840 <1> WAIT_REFRESH: 2841 <1> ; 13/06/2022 2842 <1> ; Modified for Retro UNIX 386 v1 2843 <1> 2844 <1> ; (wait for 30 micro seconds) 2845 <1> 2846 <1> SYS1 equ 61h ; PORT_B 2847 <1> 2848 <1> WR_SHORT: 2849 00005899 50 <1> push eax 2850 <1> WR_STAT_0: 2851 0000589A E461 <1> in al, SYS1 ; wait for high to low 2852 0000589C A810 <1> test al, 10h ; transition on memory 2853 0000589E 75FA <1> jnz short WR_STAT_0 2854 <1> WR_STAT_1: 2855 000058A0 E461 <1> in al, SYS1 2856 000058A2 A810 <1> test al, 10h 2857 000058A4 74FA <1> jz short WR_STAT_1 2858 000058A6 58 <1> pop eax 2859 000058A7 C3 <1> retn 2061 2062 ; 07/03/2015 2063 ; Temporary Code 2064 display_disks: 2065 000058A8 803D[5C5C0000]00 cmp byte [fd0_type], 0 2066 000058AF 7605 jna short ddsks1 2067 000058B1 E87D000000 call pdskm 2068 ddsks1: 2069 000058B6 803D[5D5C0000]00 cmp byte [fd1_type], 0 2070 000058BD 760C jna short ddsks2 2071 000058BF C605[215E0000]31 mov byte [dskx], '1' 2072 000058C6 E868000000 call pdskm 2073 ddsks2: 2074 000058CB 803D[5E5C0000]00 cmp byte [hd0_type], 0 2075 000058D2 7654 jna short ddsk6 2076 000058D4 66C705[1F5E0000]68- mov word [dsktype], 'hd' 2076 000058DC 64 2077 000058DD C605[215E0000]30 mov byte [dskx], '0' 2078 000058E4 E84A000000 call pdskm 2079 ddsks3: 2080 000058E9 803D[5F5C0000]00 cmp byte [hd1_type], 0 2081 000058F0 7636 jna short ddsk6 2082 000058F2 C605[215E0000]31 mov byte [dskx], '1' 2083 000058F9 E835000000 call pdskm 2084 ddsks4: 2085 000058FE 803D[605C0000]00 cmp byte [hd2_type], 0 2086 00005905 7621 jna short ddsk6 2087 00005907 C605[215E0000]32 mov byte [dskx], '2' 2088 0000590E E820000000 call pdskm 2089 ddsks5: 2090 00005913 803D[615C0000]00 cmp byte [hd3_type], 0 2091 0000591A 760C jna short ddsk6 2092 0000591C C605[215E0000]33 mov byte [dskx], '3' 2093 00005923 E80B000000 call pdskm 2094 ddsk6: 2095 00005928 BE[305E0000] mov esi, nextline 2096 0000592D E806000000 call pdskml 2097 pdskm_ok: 2098 00005932 C3 retn 2099 pdskm: 2100 00005933 BE[1D5E0000] mov esi, dsk_ready_msg 2101 pdskml: 2102 00005938 AC lodsb 2103 00005939 08C0 or al, al 2104 0000593B 74F5 jz short pdskm_ok 2105 0000593D 56 push esi 2106 0000593E 31DB xor ebx, ebx ; 0 2107 ; Video page 0 (bl=0) 2108 00005940 B407 mov ah, 07h ; Black background, 2109 ; light gray forecolor 2110 00005942 E86EB9FFFF call write_tty 2111 00005947 5E pop esi 2112 00005948 EBEE jmp short pdskml 2113 2114 0000594A 90 align 16 2115 2116 gdt: ; Global Descriptor Table 2117 ; (30/07/2015, conforming cs) 2118 ; (26/03/2015) 2119 ; (24/03/2015, tss) 2120 ; (19/03/2015) 2121 ; (29/12/2013) 2122 ; 2123 00005950 0000000000000000 dw 0, 0, 0, 0 ; NULL descriptor 2124 ; 18/08/2014 2125 ; 8h kernel code segment, base = 00000000h 2126 00005958 FFFF0000009ACF00 dw 0FFFFh, 0, 9A00h, 00CFh ; KCODE 2127 ; 10h kernel data segment, base = 00000000h 2128 00005960 FFFF00000092CF00 dw 0FFFFh, 0, 9200h, 00CFh ; KDATA 2129 ; 1Bh user code segment, base address = 400000h ; CORE 2130 00005968 FFFB000040FACF00 dw 0FBFFh, 0, 0FA40h, 00CFh ; UCODE 2131 ; 23h user data segment, base address = 400000h ; CORE 2132 00005970 FFFB000040F2CF00 dw 0FBFFh, 0, 0F240h, 00CFh ; UDATA 2133 ; Task State Segment 2134 00005978 6700 dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 2135 ; no IO permission in ring 3) 2136 gdt_tss0: 2137 0000597A 0000 dw 0 ; TSS base address, bits 0-15 2138 gdt_tss1: 2139 0000597C 00 db 0 ; TSS base address, bits 16-23 2140 ; 49h 2141 0000597D E9 db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1) 2142 0000597E 00 db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte) 2143 gdt_tss2: 2144 0000597F 00 db 0 ; TSS base address, bits 24-31 2145 2146 gdt_end: 2147 ;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 2148 ;; Type= 1 (code)/C=0/R=1/A=0 2149 ; P= Present, DPL=0=ring 0, 1= user (0= system) 2150 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 2151 2152 ;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 2153 ;; Type= 0 (data)/E=0/W=1/A=0 2154 ; P= Present, DPL=0=ring 0, 1= user (0= system) 2155 ; 0= Data E= Expansion direction (1= down, 0= up) 2156 ; W= Writeable, A= Accessed 2157 2158 ;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 2159 ;; Type= 1 (code)/C=0/R=1/A=0 2160 ; P= Present, DPL=3=ring 3, 1= user (0= system) 2161 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 2162 2163 ;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 2164 ;; Type= 0 (data)/E=0/W=1/A=0 2165 ; P= Present, DPL=3=ring 3, 1= user (0= system) 2166 ; 0= Data E= Expansion direction (1= down, 0= up) 2167 2168 ;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3) 2169 2170 ;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 // 2171 ; = 100000h * 1000h (G=1) = 4GB 2172 ;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 // 2173 ; = FFC00h * 1000h (G=1) = 4GB - 4MB 2174 ; G= Granularity (1= 4KB), B= Big (32 bit), 2175 ; AVL= Available to programmers 2176 2177 gdtd: 2178 00005980 2F00 dw gdt_end - gdt - 1 ; Limit (size) 2179 00005982 [50590000] dd gdt ; Address of the GDT 2180 2181 ; 20/08/2014 2182 idtd: 2183 00005986 FF01 dw idt_end - idt - 1 ; Limit (size) 2184 00005988 [D05E0000] dd idt ; Address of the IDT 2185 2186 Align 4 2187 2188 ; 21/08/2014 2189 ilist: 2190 ;times 32 dd cpu_except ; INT 0 to INT 1Fh 2191 ; 2192 ; Exception list 2193 ; 25/08/2014 2194 0000598C [1C080000] dd exc0 ; 0h, Divide-by-zero Error 2195 00005990 [23080000] dd exc1 2196 00005994 [2A080000] dd exc2 2197 00005998 [31080000] dd exc3 2198 0000599C [35080000] dd exc4 2199 000059A0 [39080000] dd exc5 2200 000059A4 [3D080000] dd exc6 ; 06h, Invalid Opcode 2201 000059A8 [41080000] dd exc7 2202 000059AC [45080000] dd exc8 2203 000059B0 [49080000] dd exc9 2204 000059B4 [4D080000] dd exc10 2205 000059B8 [51080000] dd exc11 2206 000059BC [55080000] dd exc12 2207 000059C0 [59080000] dd exc13 ; 0Dh, General Protection Fault 2208 000059C4 [5D080000] dd exc14 ; 0Eh, Page Fault 2209 000059C8 [61080000] dd exc15 2210 000059CC [65080000] dd exc16 2211 000059D0 [69080000] dd exc17 2212 000059D4 [6D080000] dd exc18 2213 000059D8 [71080000] dd exc19 2214 000059DC [75080000] dd exc20 2215 000059E0 [79080000] dd exc21 2216 000059E4 [7D080000] dd exc22 2217 000059E8 [81080000] dd exc23 2218 000059EC [85080000] dd exc24 2219 000059F0 [89080000] dd exc25 2220 000059F4 [8D080000] dd exc26 2221 000059F8 [91080000] dd exc27 2222 000059FC [95080000] dd exc28 2223 00005A00 [99080000] dd exc29 2224 00005A04 [9D080000] dd exc30 2225 00005A08 [A1080000] dd exc31 2226 ; Interrupt list 2227 00005A0C [58060000] dd timer_int ; INT 20h 2228 ;dd irq0 2229 00005A10 [5D0B0000] dd keyb_int ; 27/08/2014 2230 ;dd irq1 2231 00005A14 [76070000] dd irq2 2232 ; COM2 int 2233 00005A18 [7A070000] dd irq3 2234 ; COM1 int 2235 00005A1C [85070000] dd irq4 2236 00005A20 [90070000] dd irq5 2237 ;DISKETTE_INT: ;06/02/2015 2238 00005A24 [D01E0000] dd fdc_int ; 16/02/2015, IRQ 6 handler 2239 ;dd irq6 2240 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 2241 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 2242 00005A28 [0C0B0000] dd default_irq7 ; 25/02/2015 2243 ;dd irq7 2244 ; Real Time Clock Interrupt 2245 00005A2C [AA090000] dd rtc_int ; 23/02/2015, IRQ 8 handler 2246 ;dd irq8 ; INT 28h 2247 00005A30 [A0070000] dd irq9 2248 00005A34 [A4070000] dd irq10 2249 00005A38 [A8070000] dd irq11 2250 00005A3C [AC070000] dd irq12 2251 00005A40 [B0070000] dd irq13 2252 ;HDISK_INT1: ;06/02/2015 2253 00005A44 [9A230000] dd hdc1_int ; 21/02/2015, IRQ 14 handler 2254 ;dd irq14 2255 ;HDISK_INT2: ;06/02/2015 2256 00005A48 [BD230000] dd hdc2_int ; 21/02/2015, IRQ 15 handler 2257 ;dd irq15 ; INT 2Fh 2258 ; 14/08/2015 2259 00005A4C [E92F0000] dd sysent ; INT 30h (system calls) 2260 2261 ;dd ignore_int 2262 00005A50 00000000 dd 0 2263 2264 ;;; 2265 ;;; 11/03/2015 2266 %include 'kybdata.inc' ; KEYBOARD (BIOS) DATA 2267 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.20) - KYBDATA.INC 2268 <1> ; Last Modification: 13/06/2022 2269 <1> ; (Data Section for 'KEYBOARD.INC') 2270 <1> ; 2271 <1> ; ///////// KEYBOARD DATA /////////////// 2272 <1> 2273 <1> ; 11/03/2015 2274 <1> ; 05/12/2014 2275 <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 2276 <1> ; 03/06/86 KEYBOARD BIOS 2277 <1> 2278 <1> ;--------------------------------------------------------------------------------- 2279 <1> ; KEY IDENTIFICATION SCAN TABLES 2280 <1> ;--------------------------------------------------------------------------------- 2281 <1> 2282 <1> ;----- TABLES FOR ALT CASE ------------ 2283 <1> ;----- ALT-INPUT-TABLE 2284 00005A54 524F50514B <1> K30: db 82,79,80,81,75 2285 00005A59 4C4D474849 <1> db 76,77,71,72,73 ; 10 NUMBER ON KEYPAD 2286 <1> ;----- SUPER-SHIFT-TABLE 2287 00005A5E 101112131415 <1> db 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS 2288 00005A64 161718191E1F <1> db 22,23,24,25,30,31 2289 00005A6A 202122232425 <1> db 32,33,34,35,36,37 2290 00005A70 262C2D2E2F30 <1> db 38,44,45,46,47,48 2291 00005A76 3132 <1> db 49,50 2292 <1> 2293 <1> ;----- TABLE OF SHIFT KEYS AND MASK VALUES 2294 <1> ;----- KEY_TABLE 2295 00005A78 52 <1> _K6: db INS_KEY ; INSERT KEY 2296 00005A79 3A4546381D <1> db CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY 2297 00005A7E 2A36 <1> db LEFT_KEY,RIGHT_KEY 2298 <1> _K6L equ $-_K6 2299 <1> 2300 <1> ;----- MASK_TABLE 2301 00005A80 80 <1> _K7: db INS_SHIFT ; INSERT MODE SHIFT 2302 00005A81 4020100804 <1> db CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT 2303 00005A86 0201 <1> db LEFT_SHIFT,RIGHT_SHIFT 2304 <1> 2305 <1> ;----- TABLES FOR CTRL CASE ;---- CHARACTERS ------ 2306 00005A88 1BFF00FFFFFF <1> _K8: db 27,-1,0,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5 2307 00005A8E 1EFFFFFFFF1F <1> db 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, - 2308 <1> ;db -1,127,-1,17,23,5 ; =, Bksp, Tab, Q, W, E 2309 00005A94 FF7F94111705 <1> db -1,127,148,17,23,5 ; 13/06/2022 2310 00005A9A 12141915090F <1> db 18,20,25,21,9,15 ; R, T, Y, U, I, O 2311 00005AA0 101B1D0AFF01 <1> db 16,27,29,10,-1,1 ; P, [, ], Enter, Ctrl, A 2312 00005AA6 13040607080A <1> db 19,4,6,7,8,10 ; S, D, F, G, H, J 2313 00005AAC 0B0CFFFFFFFF <1> db 11,12,-1,-1,-1,-1 ; K, L, :, ', `, LShift 2314 00005AB2 1C1A18031602 <1> db 28,26,24,3,22,2 ; Bkslash, Z, X, C, V, B 2315 00005AB8 0E0DFFFFFFFF <1> db 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift 2316 00005ABE 96FF20FF <1> db 150,-1,' ',-1 ; *, ALT, Spc, CL 2317 <1> ; ;----- FUNCTIONS ------ 2318 00005AC2 5E5F60616263 <1> db 94,95,96,97,98,99 ; F1 - F6 2319 00005AC8 64656667FFFF <1> db 100,101,102,103,-1,-1 ; F7 - F10, NL, SL 2320 00005ACE 778D848E738F <1> db 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5 2321 00005AD4 749075917692 <1> db 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins 2322 00005ADA 93FFFFFF898A <1> db 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12 2323 <1> 2324 <1> ;----- TABLES FOR LOWER CASE ---------- 2325 00005AE0 1B3132333435363738- <1> K10: db 27,'1234567890-=',8,9 2325 00005AE9 39302D3D0809 <1> 2326 00005AEF 71776572747975696F- <1> db 'qwertyuiop[]',13,-1,'asdfghjkl;',39 2326 00005AF8 705B5D0DFF61736466- <1> 2326 00005B01 67686A6B6C3B27 <1> 2327 00005B08 60FF5C7A786376626E- <1> db 96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1 2327 00005B11 6D2C2E2FFF2AFF20FF <1> 2328 <1> ;----- LC TABLE SCAN 2329 00005B1A 3B3C3D3E3F <1> db 59,60,61,62,63 ; BASE STATE OF F1 - F10 2330 00005B1F 4041424344 <1> db 64,65,66,67,68 2331 00005B24 FFFF <1> db -1,-1 ; NL, SL 2332 <1> 2333 <1> ;----- KEYPAD TABLE 2334 00005B26 474849FF4BFF <1> K15: db 71,72,73,-1,75,-1 ; BASE STATE OF KEYPAD KEYS 2335 00005B2C 4DFF4F50515253 <1> db 77,-1,79,80,81,82,83 2336 00005B33 FFFF5C8586 <1> db -1,-1,92,133,134 ; SysRq, Undef, WT, F11, F12 2337 <1> 2338 <1> ;----- TABLES FOR UPPER CASE ---------- 2339 00005B38 1B21402324255E262A- <1> K11: db 27,'!@#$%',94,'&*()_+',8,0 2339 00005B41 28295F2B0800 <1> 2340 00005B47 51574552545955494F- <1> db 'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"' 2340 00005B50 507B7D0DFF41534446- <1> 2340 00005B59 47484A4B4C3A22 <1> 2341 00005B60 7EFF7C5A584356424E- <1> db 126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1 2341 00005B69 4D3C3E3FFF2AFF20FF <1> 2342 <1> ;----- UC TABLE SCAN 2343 00005B72 5455565758 <1> K12: db 84,85,86,87,88 ; SHIFTED STATE OF F1 - F10 2344 00005B77 595A5B5C5D <1> db 89,90,91,92,93 2345 00005B7C FFFF <1> db -1,-1 ; NL, SL 2346 <1> 2347 <1> ;----- NUM STATE TABLE 2348 00005B7E 3738392D3435362B31- <1> K14: db '789-456+1230.' ; NUMLOCK STATE OF KEYPAD KEYS 2348 00005B87 3233302E <1> 2349 <1> ; 2350 00005B8B FFFF7C8788 <1> db -1,-1,124,135,136 ; SysRq, Undef, WT, F11, F12 2351 <1> 2352 <1> Align 4 2353 <1> ;---------------------------------------- 2354 <1> ; VIDEO DISPLAY DATA AREA ; 2355 <1> ;---------------------------------------- 2356 00005B90 03 <1> CRT_MODE db 3 ; CURRENT DISPLAY MODE (TYPE) 2357 00005B91 29 <1> CRT_MODE_SET db 29h ; CURRENT SETTING OF THE 3X8 REGISTER 2358 <1> ; (29h default setting for video mode 3) 2359 <1> ; Mode Select register Bits 2360 <1> ; BIT 0 - 80x25 (1), 40x25 (0) 2361 <1> ; BIT 1 - ALPHA (0), 320x200 GRAPHICS (1) 2362 <1> ; BIT 2 - COLOR (0), BW (1) 2363 <1> ; BIT 3 - Video Sig. ENABLE (1), DISABLE (0) 2364 <1> ; BIT 4 - 640x200 B&W Graphics Mode (1) 2365 <1> ; BIT 5 - ALPHA mode BLINKING (1) 2366 <1> ; BIT 6, 7 - Not Used 2367 <1> 2368 <1> ; Mode 0 - 2Ch = 101100b ; 40x25 text, 16 gray colors 2369 <1> ; Mode 1 - 28h = 101000b ; 40x25 text, 16 fore colors, 8 back colors 2370 <1> ; Mode 2 - 2Dh = 101101b ; 80x25 text, 16 gray colors 2371 <1> ; MODE 3 - 29h = 101001b ; 80x25 text, 16 fore color, 8 back color 2372 <1> ; Mode 4 - 2Ah = 101010b ; 320x200 graphics, 4 colors 2373 <1> ; Mode 5 - 2Eh = 101110b ; 320x200 graphics, 4 gray colors 2374 <1> ; Mode 6 - 1Eh = 011110b ; 640x200 graphics, 2 colors 2375 <1> ; Mode 7 - 29h = 101001b ; 80x25 text, black & white colors 2376 <1> ; Mode & 37h = Video signal OFF 2377 <1> 2378 <1> 2379 <1> ; 26/08/2014 2380 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014) 2381 <1> ; Derived from IBM "pc-at" 2382 <1> ; rombios source code (06/10/1985) 2383 <1> ; 'dseg.inc' 2384 <1> 2385 <1> ;---------------------------------------; 2386 <1> ; SYSTEM DATA AREA ; 2387 <1> ;---------------------------------------- 2388 00005B92 00 <1> BIOS_BREAK db 0 ; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED 2389 <1> 2390 <1> ;---------------------------------------- 2391 <1> ; KEYBOARD DATA AREAS ; 2392 <1> ;---------------------------------------- 2393 <1> 2394 00005B93 00 <1> KB_FLAG db 0 ; KEYBOARD SHIFT STATE AND STATUS FLAGS 2395 00005B94 00 <1> KB_FLAG_1 db 0 ; SECOND BYTE OF KEYBOARD STATUS 2396 00005B95 00 <1> KB_FLAG_2 db 0 ; KEYBOARD LED FLAGS 2397 00005B96 00 <1> KB_FLAG_3 db 0 ; KEYBOARD MODE STATE AND TYPE FLAGS 2398 00005B97 00 <1> ALT_INPUT db 0 ; STORAGE FOR ALTERNATE KEY PAD ENTRY 2399 00005B98 [A85B0000] <1> BUFFER_START dd KB_BUFFER ; OFFSET OF KEYBOARD BUFFER START 2400 00005B9C [C85B0000] <1> BUFFER_END dd KB_BUFFER + 32 ; OFFSET OF END OF BUFFER 2401 00005BA0 [A85B0000] <1> BUFFER_HEAD dd KB_BUFFER ; POINTER TO HEAD OF KEYBOARD BUFFER 2402 00005BA4 [A85B0000] <1> BUFFER_TAIL dd KB_BUFFER ; POINTER TO TAIL OF KEYBOARD BUFFER 2403 <1> ; ------ HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY 2404 00005BA8 0000 <1> KB_BUFFER times 16 dw 0 ; ROOM FOR 16 SCAN CODE ENTRIES 2405 <1> 2406 <1> ; /// End Of KEYBOARD DATA /// 2267 %include 'vidata.inc' ; VIDEO (BIOS) DATA 2268 <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC 2269 <1> ; Last Modification: 11/03/2015 2270 <1> ; (Data section for 'VIDEO.INC') 2271 <1> ; 2272 <1> ; ///////// VIDEO DATA /////////////// 2273 <1> 2274 <1> video_params: 2275 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2276 <1> ;ORGS.ASM ----- 06/10/85 COMPATIBILITY MODULE 2277 <1> ; VIDEO MODE 3 2278 00005BC8 71505A0A1F0619 <1> db 71h,50h,5Ah,0Ah,1Fh,6,19h ; SET UP FOR 80X25 2279 00005BCF 1C02070607 <1> db 1Ch,2,7,6,7 ; cursor start = 6, cursor stop = 7 2280 00005BD4 00000000 <1> db 0,0,0,0 2281 <1> 2282 <1> ; /// End Of VIDEO DATA /// 2268 %include 'diskdata.inc' ; DISK (BIOS) DATA (initialized) 2269 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKDATA.INC 2270 <1> ; Last Modification: 12/07/2022 2271 <1> ; (Initialized Disk Parameters Data section for 'DISKIO.INC') 2272 <1> ; 2273 <1> ; ***************************************************************************** 2274 <1> ; Ref: Retro UNIX 386 v1.1 'diskdata.inc' modification: 11/07/2022 2275 <1> 2276 <1> ;---------------------------------------- 2277 <1> ; 80286 INTERRUPT LOCATIONS : 2278 <1> ; REFERENCED BY POST & BIOS : 2279 <1> ;---------------------------------------- 2280 <1> 2281 00005BD8 [3B5C0000] <1> DISK_POINTER: dd MD_TBL6 ; Pointer to Diskette Parameter Table 2282 <1> 2283 <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014 2284 <1> ;---------------------------------------------------------------- 2285 <1> ; DISK_BASE : 2286 <1> ; THIS IS THE SET OF PARAMETERS REQUIRED FOR : 2287 <1> ; DISKETTE OPERATION. THEY ARE POINTED AT BY THE : 2288 <1> ; DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS, : 2289 <1> ; BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT : 2290 <1> ;---------------------------------------------------------------- 2291 <1> 2292 <1> ;DISK_BASE: 2293 <1> ; DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2294 <1> ; DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2295 <1> ; DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2296 <1> ; DB 2 ; 512 BYTES/SECTOR 2297 <1> ; ;DB 15 ; EOT (LAST SECTOR ON TRACK) 2298 <1> ; db 18 ; (EOT for 1.44MB diskette) 2299 <1> ; DB 01BH ; GAP LENGTH 2300 <1> ; DB 0FFH ; DTL 2301 <1> ; ;DB 054H ; GAP LENGTH FOR FORMAT 2302 <1> ; db 06ch ; (for 1.44MB dsikette) 2303 <1> ; DB 0F6H ; FILL BYTE FOR FORMAT 2304 <1> ; DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2305 <1> ; DB 8 ; MOTOR START TIME (1/8 SECONDS) 2306 <1> 2307 <1> ;---------------------------------------- 2308 <1> ; ROM BIOS DATA AREAS : 2309 <1> ;---------------------------------------- 2310 <1> 2311 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 2312 <1> 2313 <1> ;@EQUIP_FLAG DW ? ; INSTALLED HARDWARE FLAGS 2314 <1> 2315 <1> ;---------------------------------------- 2316 <1> ; DISKETTE DATA AREAS : 2317 <1> ;---------------------------------------- 2318 <1> 2319 <1> ;@SEEK_STATUS DB ? ; DRIVE RECALIBRATION STATUS 2320 <1> ; ; BIT 3-0 = DRIVE 3-0 RECALIBRATION 2321 <1> ; ; BEFORE NEXT SEEK IF BIT IS = 0 2322 <1> ;@MOTOR_STATUS DB ? ; MOTOR STATUS 2323 <1> ; ; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING 2324 <1> ; ; BIT 7 = CURRENT OPERATION IS A WRITE 2325 <1> ;@MOTOR_COUNT DB ? ; TIME OUT COUNTER FOR MOTOR(S) TURN OFF 2326 <1> ;@DSKETTE_STATUS DB ? ; RETURN CODE STATUS BYTE 2327 <1> ; ; CMD_BLOCK IN STACK FOR DISK OPERATION 2328 <1> ;@NEC_STATUS DB 7 DUP(?) ; STATUS BYTES FROM DISKETTE OPERATION 2329 <1> 2330 <1> ;---------------------------------------- 2331 <1> ; POST AND BIOS WORK DATA AREA : 2332 <1> ;---------------------------------------- 2333 <1> 2334 <1> ;@INTR_FLAG DB ? ; FLAG INDICATING AN INTERRUPT HAPPENED 2335 <1> 2336 <1> ;---------------------------------------- 2337 <1> ; TIMER DATA AREA : 2338 <1> ;---------------------------------------- 2339 <1> 2340 <1> ; 17/12/2014 (IRQ 0 - INT 08H) 2341 <1> ;TIMER_LOW equ 46Ch ; Timer ticks (counter) @ 40h:006Ch 2342 <1> ;TIMER_HIGH equ 46Eh ; (18.2 timer ticks per second) 2343 <1> ;TIMER_OFL equ 470h ; Timer - 24 hours flag @ 40h:0070h 2344 <1> 2345 <1> ;---------------------------------------- 2346 <1> ; ADDITIONAL MEDIA DATA : 2347 <1> ;---------------------------------------- 2348 <1> 2349 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 2350 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 2351 <1> ; DB ? ; DRIVE 1 MEDIA STATE 2352 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 2353 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 2354 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 2355 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 2356 <1> 2357 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 2358 <1> 2359 <1> ;-------------------------------------------------------- 2360 <1> ; DRIVE TYPE TABLE : 2361 <1> ;-------------------------------------------------------- 2362 <1> ; 16/02/2015 (unix386.s, 32 bit modifications) 2363 <1> DR_TYPE: 2364 00005BDC 01 <1> DB 01 ;DRIVE TYPE, MEDIA TABLE 2365 <1> ;DW MD_TBL1 2366 00005BDD [FA5B0000] <1> dd MD_TBL1 2367 00005BE1 82 <1> DB 02+BIT7ON 2368 <1> ;DW MD_TBL2 2369 00005BE2 [075C0000] <1> dd MD_TBL2 2370 00005BE6 02 <1> DR_DEFAULT: DB 02 2371 <1> ;DW MD_TBL3 2372 00005BE7 [145C0000] <1> dd MD_TBL3 2373 00005BEB 03 <1> DB 03 2374 <1> ;DW MD_TBL4 2375 00005BEC [215C0000] <1> dd MD_TBL4 2376 00005BF0 84 <1> DB 04+BIT7ON 2377 <1> ;DW MD_TBL5 2378 00005BF1 [2E5C0000] <1> dd MD_TBL5 2379 00005BF5 04 <1> DB 04 2380 <1> ;DW MD_TBL6 2381 00005BF6 [3B5C0000] <1> dd MD_TBL6 2382 <1> DR_TYPE_E equ $ ; END OF TABLE 2383 <1> ;DR_CNT EQU (DR_TYPE_E-DR_TYPE)/3 2384 <1> DR_CNT equ (DR_TYPE_E-DR_TYPE)/5 2385 <1> ;-------------------------------------------------------- 2386 <1> ; MEDIA/DRIVE PARAMETER TABLES : 2387 <1> ;-------------------------------------------------------- 2388 <1> ;-------------------------------------------------------- 2389 <1> ; 360 KB MEDIA IN 360 KB DRIVE : 2390 <1> ;-------------------------------------------------------- 2391 <1> MD_TBL1: 2392 00005BFA DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2393 00005BFB 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2394 00005BFC 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2395 00005BFD 02 <1> DB 2 ; 512 BYTES/SECTOR 2396 00005BFE 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2397 00005BFF 2A <1> DB 02AH ; GAP LENGTH 2398 00005C00 FF <1> DB 0FFH ; DTL 2399 00005C01 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2400 00005C02 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2401 00005C03 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2402 00005C04 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2403 00005C05 27 <1> DB 39 ; MAX. TRACK NUMBER 2404 00005C06 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2405 <1> ;-------------------------------------------------------- 2406 <1> ; 360 KB MEDIA IN 1.2 MB DRIVE : 2407 <1> ;-------------------------------------------------------- 2408 <1> MD_TBL2: 2409 00005C07 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2410 00005C08 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2411 00005C09 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2412 00005C0A 02 <1> DB 2 ; 512 BYTES/SECTOR 2413 00005C0B 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2414 00005C0C 2A <1> DB 02AH ; GAP LENGTH 2415 00005C0D FF <1> DB 0FFH ; DTL 2416 00005C0E 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2417 00005C0F F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2418 00005C10 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2419 00005C11 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2420 00005C12 27 <1> DB 39 ; MAX. TRACK NUMBER 2421 00005C13 40 <1> DB RATE_300 ; DATA TRANSFER RATE 2422 <1> ;-------------------------------------------------------- 2423 <1> ; 1.2 MB MEDIA IN 1.2 MB DRIVE : 2424 <1> ;-------------------------------------------------------- 2425 <1> MD_TBL3: 2426 00005C14 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2427 00005C15 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2428 00005C16 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2429 00005C17 02 <1> DB 2 ; 512 BYTES/SECTOR 2430 00005C18 0F <1> DB 15 ; EOT (LAST SECTOR ON TRACK) 2431 00005C19 1B <1> DB 01BH ; GAP LENGTH 2432 00005C1A FF <1> DB 0FFH ; DTL 2433 00005C1B 54 <1> DB 054H ; GAP LENGTH FOR FORMAT 2434 00005C1C F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2435 00005C1D 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2436 00005C1E 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2437 00005C1F 4F <1> DB 79 ; MAX. TRACK NUMBER 2438 00005C20 00 <1> DB RATE_500 ; DATA TRANSFER RATE 2439 <1> ;-------------------------------------------------------- 2440 <1> ; 720 KB MEDIA IN 720 KB DRIVE : 2441 <1> ;-------------------------------------------------------- 2442 <1> MD_TBL4: 2443 00005C21 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2444 00005C22 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2445 00005C23 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2446 00005C24 02 <1> DB 2 ; 512 BYTES/SECTOR 2447 00005C25 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2448 00005C26 2A <1> DB 02AH ; GAP LENGTH 2449 00005C27 FF <1> DB 0FFH ; DTL 2450 00005C28 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2451 00005C29 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2452 00005C2A 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2453 00005C2B 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2454 00005C2C 4F <1> DB 79 ; MAX. TRACK NUMBER 2455 00005C2D 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2456 <1> ;-------------------------------------------------------- 2457 <1> ; 720 KB MEDIA IN 1.44 MB DRIVE : 2458 <1> ;-------------------------------------------------------- 2459 <1> MD_TBL5: 2460 00005C2E DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2461 00005C2F 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2462 00005C30 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2463 00005C31 02 <1> DB 2 ; 512 BYTES/SECTOR 2464 00005C32 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2465 00005C33 2A <1> DB 02AH ; GAP LENGTH 2466 00005C34 FF <1> DB 0FFH ; DTL 2467 00005C35 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2468 00005C36 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2469 00005C37 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2470 00005C38 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2471 00005C39 4F <1> DB 79 ; MAX. TRACK NUMBER 2472 00005C3A 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2473 <1> ;-------------------------------------------------------- 2474 <1> ; 1.44 MB MEDIA IN 1.44 MB DRIVE : 2475 <1> ;-------------------------------------------------------- 2476 <1> MD_TBL6: 2477 00005C3B AF <1> DB 10101111B ; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE 2478 00005C3C 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2479 00005C3D 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2480 00005C3E 02 <1> DB 2 ; 512 BYTES/SECTOR 2481 00005C3F 12 <1> DB 18 ; EOT (LAST SECTOR ON TRACK) 2482 00005C40 1B <1> DB 01BH ; GAP LENGTH 2483 00005C41 FF <1> DB 0FFH ; DTL 2484 00005C42 6C <1> DB 06CH ; GAP LENGTH FOR FORMAT 2485 00005C43 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2486 00005C44 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2487 00005C45 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2488 00005C46 4F <1> DB 79 ; MAX. TRACK NUMBER 2489 00005C47 00 <1> DB RATE_500 ; DATA TRANSFER RATE 2490 <1> 2491 <1> 2492 <1> ; << diskette.inc >> 2493 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2494 <1> ; 2495 <1> ;---------------------------------------- 2496 <1> ; ROM BIOS DATA AREAS : 2497 <1> ;---------------------------------------- 2498 <1> 2499 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 2500 <1> 2501 <1> ;---------------------------------------- 2502 <1> ; FIXED DISK DATA AREAS : 2503 <1> ;---------------------------------------- 2504 <1> 2505 <1> ;DISK_STATUS1: DB 0 ; FIXED DISK STATUS 2506 <1> ;HF_NUM: DB 0 ; COUNT OF FIXED DISK DRIVES 2507 <1> ;CONTROL_BYTE: DB 0 ; HEAD CONTROL BYTE 2508 <1> ;@PORT_OFF DB ? ; RESERVED (PORT OFFSET) 2509 <1> 2510 <1> ;---------------------------------------- 2511 <1> ; ADDITIONAL MEDIA DATA : 2512 <1> ;---------------------------------------- 2513 <1> 2514 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 2515 <1> ;HF_STATUS DB 0 ; STATUS REGISTER 2516 <1> ;HF_ERROR DB 0 ; ERROR REGISTER 2517 <1> ;HF_INT_FLAG DB 0 ; FIXED DISK INTERRUPT FLAG 2518 <1> ;HF_CNTRL DB 0 ; COMBO FIXED DISK/DISKETTE CARD BIT 0=1 2519 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 2520 <1> ; DB ? ; DRIVE 1 MEDIA STATE 2521 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 2522 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 2523 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 2524 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 2525 <1> 2526 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 2527 <1> ; 2528 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2529 <1> 2530 <1> ERR_TBL: 2531 00005C48 E0 <1> db NO_ERR 2532 00005C49 024001BB <1> db BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR 2533 00005C4D 04BB100A <1> db RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR 2534 <1> 2535 <1> ; 11/07/2022 2536 <1> ; 17/12/2014 (mov ax, [cfd]) 2537 <1> ; 11/12/2014 2538 <1> ;cfd: db 0 ; current floppy drive (for GET_PARM) 2539 <1> ; 17/12/2014 ; instead of 'DISK_POINTER' 2540 <1> ;pfd: db 1 ; previous floppy drive (for GET_PARM) 2541 <1> ; (initial value of 'pfd 2542 <1> ; must be different then 'cfd' value 2543 <1> ; to force updating/initializing 2544 <1> ; current drive parameters) 2545 <1> 2546 <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2547 00005C51 FF <1> pfd: db 0FFh 2548 <1> 2549 <1> align 2 2550 <1> 2551 00005C52 F001 <1> HF_PORT: dw 1F0h ; Default = 1F0h 2552 <1> ; (170h) 2553 00005C54 F603 <1> HF_REG_PORT: dw 3F6h ; HF_PORT + 206h 2554 <1> 2555 <1> ; 05/01/2015 2556 00005C56 00 <1> hf_m_s: db 0 ; (0 = Master, 1 = Slave) 2557 <1> 2558 <1> ; ***************************************************************************** 2269 ;;; 2270 2271 00005C57 90 Align 2 2272 2273 ; 12/11/2014 (Retro UNIX 386 v1) 2274 00005C58 00 boot_drv: db 0 ; boot drive number (physical) 2275 ; 24/11/2014 2276 00005C59 00 drv: db 0 2277 00005C5A 00 last_drv: db 0 ; last hdd 2278 00005C5B 00 hdc: db 0 ; number of hard disk drives 2279 ; (present/detected) 2280 ; 2281 ; 24/11/2014 (Retro UNIX 386 v1) 2282 ; Physical drive type & flags 2283 00005C5C 00 fd0_type: db 0 ; floppy drive type 2284 00005C5D 00 fd1_type: db 0 ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt) 2285 ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt) 2286 ; 3 = 720 Kb, 80 track, 3.5" (9 spt) 2287 ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt) 2288 ; 1 = 360 Kb, 40 track, 5.25" (9 spt) 2289 00005C5E 00 hd0_type: db 0 ; EDD status for hd0 (bit 7 = present flag) 2290 00005C5F 00 hd1_type: db 0 ; EDD status for hd1 (bit 7 = present flag) 2291 00005C60 00 hd2_type: db 0 ; EDD status for hd2 (bit 7 = present flag) 2292 00005C61 00 hd3_type: db 0 ; EDD status for hd3 (bit 7 = present flag) 2293 ; bit 0 - Fixed disk access subset supported 2294 ; bit 1 - Drive locking and ejecting 2295 ; bit 2 - Enhanced disk drive support 2296 ; bit 3 = Reserved (64 bit EDD support) 2297 ; (If bit 0 is '1' Retro UNIX 386 v1 2298 ; will interpret it as 'LBA ready'!) 2299 2300 ; 12/07/2022 2301 ; (drv.cylinders, drv.spt, drv.spt will not be used now on) 2302 ; ('diskio.inc') 2303 ; ((spt and heads and cylinder counts will be taken from DPT)) 2304 2305 ; 11/03/2015 - 10/07/2015 2306 ;drv.cylinders: dw 0,0,0,0,0,0,0 2307 ;drv.heads: dw 0,0,0,0,0,0,0 2308 ;drv.spt: dw 0,0,0,0,0,0,0 2309 ; 12/07/2022 - 11/03/2015 2310 00005C62 000000000000000000- drv.size: dd 0,0,0,0,0,0,0 2310 00005C6B 000000000000000000- 2310 00005C74 000000000000000000- 2310 00005C7D 00 2311 00005C7E 00000000000000 drv.status: db 0,0,0,0,0,0,0 2312 00005C85 00000000000000 drv.error: db 0,0,0,0,0,0,0 2313 ; 2314 2315 ; 27/08/2014 2316 scr_row: 2317 00005C8C E0810B00 dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3 2318 scr_col: 2319 00005C90 00000000 dd 0 2320 2321 ;; 14/08/2015 2322 ;;msgPM: 2323 ;; db "Protected mode and paging are ENABLED ... ", 0 2324 msgKVER: 2325 ;;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0 2326 ;;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [29/04/2022]", 0 2327 ;;;db "Retro UNIX 386 v1 - Kernel v0.2.0.19 [02/06/2022]", 0 2328 ;;db "Retro UNIX 386 v1 - Kernel v0.2.0.20 [14/06/2022]", 0 2329 ;db "Retro UNIX 386 v1 - Kernel v0.2.0.21 [12/07/2022]", 0 2330 00005C94 526574726F20554E49- db "Retro UNIX 386 v1 - Kernel v0.2.0.22 [24/07/2022]", 0 2330 00005C9D 582033383620763120- 2330 00005CA6 2D204B65726E656C20- 2330 00005CAF 76302E322E302E3232- 2330 00005CB8 205B32342F30372F32- 2330 00005CC1 3032325D00 2331 2332 Align 2 2333 2334 ; 20/08/2014 2335 ; /* This is the default interrupt "handler" :-) */ 2336 ; Linux v0.12 (head.s) 2337 int_msg: 2338 00005CC6 556E6B6E6F776E2069- db "Unknown interrupt ! ", 0 2338 00005CCF 6E7465727275707420- 2338 00005CD8 212000 2339 2340 00005CDB 90 Align 2 2341 2342 ; 21/08/2014 2343 timer_msg: 2344 00005CDC 49525120302028494E- db "IRQ 0 (INT 20h) ! Timer Interrupt : " 2344 00005CE5 542032306829202120- 2344 00005CEE 54696D657220496E74- 2344 00005CF7 657272757074203A20 2345 tcountstr: 2346 00005D00 303030303020 db "00000 " 2347 00005D06 00 db 0 2348 2349 00005D07 90 Align 2 2350 ; 21/08/2014 2351 exc_msg: 2352 00005D08 435055206578636570- db "CPU exception ! " 2352 00005D11 74696F6E202120 2353 excnstr: ; 25/08/2014 2354 00005D18 3F3F68202045495020- db "??h", " EIP : " 2354 00005D21 3A20 2355 EIPstr: ; 29/08/2014 2356 00005D23 00 times 12 db 0 2357 rtc_msg: 2358 00005D2F 5265616C2054696D65- db "Real Time Clock - " 2358 00005D38 20436C6F636B202D20 2359 datestr: 2360 00005D41 30302F30302F303030- db "00/00/0000" 2360 00005D4A 30 2361 00005D4B 20 db " " 2362 daystr: 2363 00005D4C 44415920 db "DAY " 2364 timestr: 2365 00005D50 30303A30303A3030 db "00:00:00" 2366 00005D58 20 db " " 2367 00005D59 00 db 0 2368 2369 daytmp: 2370 ; 28/02/2015 2371 00005D5A 3F3F3F2053554E204D- db "??? SUN MON TUE WED THU FRI SAT " 2371 00005D63 4F4E20545545205745- 2371 00005D6C 442054485520465249- 2371 00005D75 2053415420 2372 2373 00005D7A FF ptime_seconds: db 0FFh 2374 2375 ; 23/02/2015 2376 ; 25/08/2014 2377 ;scounter: 2378 ; db 5 2379 ; db 19 2380 2381 ;; 05/11/2014 2382 ;msg_out_of_memory: 2383 ; db 07h, 0Dh, 0Ah 2384 ; db 'Insufficient memory ! ' 2385 ; db '(Minimum 2 MB memory is needed.)' 2386 ; db 0Dh, 0Ah, 0 2387 ; 2388 setup_error_msg: 2389 00005D7B 0D0A db 0Dh, 0Ah 2390 00005D7D 4469736B2053657475- db 'Disk Setup Error!' 2390 00005D86 70204572726F7221 2391 00005D8E 0D0A00 db 0Dh, 0Ah,0 2392 2393 ; 02/09/2014 (Retro UNIX 386 v1) 2394 ;crt_ulc : db 0 ; upper left column (for scroll) 2395 ; db 0 ; upper left row (for scroll) 2396 2397 ;crt_lrc : db 79 ; lower right column (for scroll) 2398 ; db 24 ; lower right row (for scroll) 2399 2400 2401 ; 06/11/2014 (Temporary Data) 2402 ; Memory Information message 2403 ; 14/08/2015 2404 msg_memory_info: 2405 00005D91 07 db 07h 2406 00005D92 0D0A db 0Dh, 0Ah 2407 ;db "MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah 2408 00005D94 546F74616C206D656D- db "Total memory : " 2408 00005D9D 6F7279203A20 2409 mem_total_b_str: ; 10 digits 2410 00005DA3 303030303030303030- db "0000000000 bytes", 0Dh, 0Ah 2410 00005DAC 302062797465730D0A 2411 00005DB5 202020202020202020- db " ", 20h, 20h, 20h 2411 00005DBE 202020202020202020 2412 mem_total_p_str: ; 7 digits 2413 00005DC7 303030303030302070- db "0000000 pages", 0Dh, 0Ah 2413 00005DD0 616765730D0A 2414 00005DD6 0D0A db 0Dh, 0Ah 2415 00005DD8 46726565206D656D6F- db "Free memory : " 2415 00005DE1 727920203A20 2416 free_mem_b_str: ; 10 digits 2417 00005DE7 3F3F3F3F3F3F3F3F3F- db "?????????? bytes", 0Dh, 0Ah 2417 00005DF0 3F2062797465730D0A 2418 00005DF9 202020202020202020- db " ", 20h, 20h, 20h 2418 00005E02 202020202020202020 2419 free_mem_p_str: ; 7 digits 2420 00005E0B 3F3F3F3F3F3F3F2070- db "??????? pages", 0Dh, 0Ah 2420 00005E14 616765730D0A 2421 00005E1A 0D0A00 db 0Dh, 0Ah, 0 2422 2423 dsk_ready_msg: 2424 00005E1D 0D0A db 0Dh, 0Ah 2425 dsktype: 2426 00005E1F 6664 db 'fd' 2427 dskx: 2428 00005E21 30 db '0' 2429 00005E22 20 db 20h 2430 00005E23 697320524541445920- db 'is READY ...' 2430 00005E2C 2E2E2E 2431 00005E2F 00 db 0 2432 nextline: 2433 00005E30 0D0A00 db 0Dh, 0Ah, 0 2434 2435 ; KERNEL - SYSINIT Messages 2436 ; 24/08/2015 2437 ; 13/04/2015 - (Retro UNIX 386 v1 Beginning) 2438 ; 14/07/2013 2439 ;kernel_init_err_msg: 2440 ; db 0Dh, 0Ah 2441 ; db 07h 2442 ; db 'Kernel initialization ERROR !' 2443 ; db 0Dh, 0Ah, 0 2444 ; 24/08/2015 2445 ;;; (temporary kernel init message has been removed 2446 ;;; from 'sys_init' code) 2447 ;kernel_init_ok_msg: 2448 ; db 0Dh, 0Ah 2449 ; db 07h 2450 ; db 'Welcome to Retro UNIX 386 v1 Operating System !' 2451 ; db 0Dh, 0Ah 2452 ; db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)' 2453 ; db 0Dh, 0Ah, 0 2454 panic_msg: 2455 00005E33 0D0A07 db 0Dh, 0Ah, 07h 2456 00005E36 4552524F523A204B65- db 'ERROR: Kernel Panic !' 2456 00005E3F 726E656C2050616E69- 2456 00005E48 632021 2457 00005E4B 0D0A00 db 0Dh, 0Ah, 0 2458 etc_init_err_msg: 2459 00005E4E 0D0A db 0Dh, 0Ah 2460 00005E50 07 db 07h 2461 00005E51 4552524F523A202F65- db 'ERROR: /etc/init !?' 2461 00005E5A 74632F696E69742021- 2461 00005E63 3F 2462 00005E64 0D0A00 db 0Dh, 0Ah, 0 2463 2464 ; 10/05/2015 2465 badsys_msg: 2466 00005E67 0D0A db 0Dh, 0Ah 2467 00005E69 07 db 07h 2468 00005E6A 496E76616C69642053- db 'Invalid System Call !' 2468 00005E73 797374656D2043616C- 2468 00005E7C 6C2021 2469 00005E7F 0D0A db 0Dh, 0Ah 2470 00005E81 4541583A20 db 'EAX: ' 2471 bsys_msg_eax: 2472 00005E86 303030303030303068 db '00000000h' 2473 00005E8F 0D0A db 0Dh, 0Ah 2474 00005E91 4549503A20 db 'EIP: ' 2475 bsys_msg_eip: 2476 00005E96 303030303030303068 db '00000000h' 2477 00005E9F 0D0A00 db 0Dh, 0Ah, 0 2478 2479 BSYS_M_SIZE equ $ - badsys_msg 2480 2481 2482 align 2 2483 2484 ; EPOCH Variables 2485 ; 13/04/2015 - Retro UNIX 386 v1 Beginning 2486 ; 09/04/2013 epoch variables 2487 ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013 2488 ; 2489 00005EA2 B207 year: dw 1970 2490 ;month: dw 1 2491 ;day: dw 1 2492 ;hour: dw 0 2493 ;minute: dw 0 2494 ;second: dw 0 2495 ; 02/06/2022 2496 00005EA4 01 month: db 1 2497 00005EA5 01 day: db 1 2498 00005EA6 01 hour: db 1 2499 00005EA7 01 minute: db 1 2500 00005EA8 01 second: db 1 2501 00005EA9 01 db 1 2502 2503 DMonth: 2504 00005EAA 0000 dw 0 2505 00005EAC 1F00 dw 31 2506 00005EAE 3B00 dw 59 2507 00005EB0 5A00 dw 90 2508 00005EB2 7800 dw 120 2509 00005EB4 9700 dw 151 2510 00005EB6 B500 dw 181 2511 00005EB8 D400 dw 212 2512 00005EBA F300 dw 243 2513 00005EBC 1101 dw 273 2514 00005EBE 3001 dw 304 2515 00005EC0 4E01 dw 334 2516 2517 ; 04/11/2014 (Retro UNIX 386 v1) 2518 00005EC2 0000 mem_1m_1k: dw 0 ; Number of contiguous KB between 2519 ; 1 and 16 MB, max. 3C00h = 15 MB. 2520 00005EC4 0000 mem_16m_64k: dw 0 ; Number of contiguous 64 KB blocks 2521 ; between 16 MB and 4 GB. 2522 2523 00005EC6 90 align 16 2524 2525 bss_start: 2526 2527 ABSOLUTE bss_start 2528 2529 ; 11/03/2015 2530 ; Interrupt Descriptor Table (20/08/2014) 2531 idt: 2532 00005ED0 resb 64*8 ; INT 0 to INT 3Fh 2533 idt_end: 2534 2535 ;alignb 4 2536 2537 task_state_segment: 2538 ; 24/03/2015 2539 000060D0 ???? tss.link: resw 1 2540 000060D2 ???? resw 1 2541 ; tss offset 4 2542 000060D4 ???????? tss.esp0: resd 1 2543 000060D8 ???? tss.ss0: resw 1 2544 000060DA ???? resw 1 2545 000060DC ???????? tss.esp1: resd 1 2546 000060E0 ???? tss.ss1: resw 1 2547 000060E2 ???? resw 1 2548 000060E4 ???????? tss.esp2: resd 1 2549 000060E8 ???? tss.ss2: resw 1 2550 000060EA ???? resw 1 2551 ; tss offset 28 2552 000060EC ???????? tss.CR3: resd 1 2553 000060F0 ???????? tss.eip: resd 1 2554 000060F4 ???????? tss.eflags: resd 1 2555 ; tss offset 40 2556 000060F8 ???????? tss.eax: resd 1 2557 000060FC ???????? tss.ecx: resd 1 2558 00006100 ???????? tss.edx: resd 1 2559 00006104 ???????? tss.ebx: resd 1 2560 00006108 ???????? tss.esp: resd 1 2561 0000610C ???????? tss.ebp: resd 1 2562 00006110 ???????? tss.esi: resd 1 2563 00006114 ???????? tss.edi: resd 1 2564 ; tss offset 72 2565 00006118 ???? tss.ES: resw 1 2566 0000611A ???? resw 1 2567 0000611C ???? tss.CS: resw 1 2568 0000611E ???? resw 1 2569 00006120 ???? tss.SS: resw 1 2570 00006122 ???? resw 1 2571 00006124 ???? tss.DS: resw 1 2572 00006126 ???? resw 1 2573 00006128 ???? tss.FS: resw 1 2574 0000612A ???? resw 1 2575 0000612C ???? tss.GS: resw 1 2576 0000612E ???? resw 1 2577 00006130 ???? tss.LDTR: resw 1 2578 00006132 ???? resw 1 2579 ; tss offset 100 2580 00006134 ???? resw 1 2581 00006136 ???? tss.IOPB: resw 1 2582 ; tss offset 104 2583 tss_end: 2584 2585 00006138 ???????? k_page_dir: resd 1 ; Kernel's (System) Page Directory address 2586 ; (Physical address = Virtual address) 2587 0000613C ???????? memory_size: resd 1 ; memory size in pages 2588 00006140 ???????? free_pages: resd 1 ; number of free pages 2589 00006144 ???????? next_page: resd 1 ; offset value in M.A.T. for 2590 ; first free page search 2591 00006148 ???????? last_page: resd 1 ; offset value in M.A.T. which 2592 ; next free page search will be 2593 ; stopped after it. (end of M.A.T.) 2594 0000614C ???????? first_page: resd 1 ; offset value in M.A.T. which 2595 ; first free page search 2596 ; will be started on it. (for user) 2597 00006150 ???????? mat_size: resd 1 ; Memory Allocation Table size in pages 2598 2599 ;;; 2600 ; 02/09/2014 (Retro UNIX 386 v1) 2601 ; 04/12/2013 (Retro UNIX 8086 v1) 2602 00006154 ???? CRT_START: resw 1 ; starting address in regen buffer 2603 ; NOTE: active page only 2604 00006156 cursor_posn: resw 8 ; cursor positions for video pages 2605 active_page: 2606 00006166 ?? ptty: resb 1 ; current tty 2607 ; 01/07/2015 2608 00006167 ?? ccolor: resb 1 ; current color attributes ('sysmsg') 2609 ; 26/10/2015 2610 ; 07/09/2014 2611 00006168 ttychr: resw ntty+2 ; Character buffer (multiscreen) 2612 2613 ; 21/08/2014 2614 0000617C ???????? tcount: resd 1 2615 2616 ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!) 2617 00006180 ???????? p_time: resd 1 ; present time (for systime & sysmdate) 2618 2619 ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !) 2620 ; (open mode locks for pseudo TTYs) 2621 ; [ major tty locks (return error in any conflicts) ] 2622 00006184 ttyl: resw ntty+2 ; opening locks for TTYs. 2623 2624 ; 15/04/2015 (Retro UNIX 386 v1) 2625 ; 22/09/2013 (Retro UNIX 8086 v1) 2626 00006198 wlist: resb ntty+2 ; wait channel list (0 to 9 for TTYs) 2627 ; 15/04/2015 (Retro UNIX 386 v1) 2628 ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h 2629 ;; 0 means serial port is not available 2630 ;;comprm: ; 25/06/2014 2631 000061A2 ?? com1p: resb 1 ;;0E3h 2632 000061A3 ?? com2p: resb 1 ;;0E3h 2633 2634 ; 17/11/2015 2635 ; request for response (from the terminal) 2636 000061A4 ???? req_resp: resw 1 2637 ; 07/11/2015 2638 000061A6 ?? ccomport: resb 1 ; current COM (serial) port 2639 ; (0= COM1, 1= COM2) 2640 ; 09/11/2015 2641 000061A7 ?? comqr: resb 1 ; 'query or response' sign (u9.s, 'sndc') 2642 ; 07/11/2015 2643 000061A8 ???? rchar: resw 1 ; last received char for COM 1 and COM 2 2644 000061AA ???? schar: resw 1 ; last sent char for COM 1 and COM 2 2645 2646 ; 23/10/2015 2647 ; SERIAL PORTS - COMMUNICATION MODES 2648 ; (Retro UNIX 386 v1 feature only!) 2649 ; 0 - command mode (default/initial mode) 2650 ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars) 2651 ;;; communication modes for future versions: 2652 ; // 2 - keyboard mode (ascii+scancode input) 2653 ; // 3 - mouse mode 2654 ; // 4 - device control (output) mode 2655 ; VALID COMMANDS for current version: 2656 ; 'LOGIN' 2657 ; Login request: db 0FFh, 'LOGIN', 0 2658 ; ("Retro UNIX 386 v1 terminal requests login") 2659 ; Login response: db 0FFh, 'login', 0 2660 ; ("login request accepted, wait for login prompt") 2661 ; When a login requests is received and acknowledged (by 2662 ; serial port interrupt handler (communication procedure), 2663 ; Retro UNIX 386 v1 operating system will start terminal mode 2664 ; (login procedure) by changing comm. mode to 1 (terminal mode) 2665 ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2) 2666 ; 2667 ; 'sys connect' system call is used to change communication mode 2668 ; except 'LOGIN' command which is used to start terminal mode 2669 ; by using (COM port) terminal. 2670 2671 ;com1own: resb 1 ; COM1 owner (u.uno) 2672 ;com2own: resb 1 ; COM2 owner (u.uno) 2673 ;com1mode: resb 1 ; communication mode for COM1 2674 ;com1com: resb 1 ; communication command for COM1 2675 ;com2mode: resb 1 ; communication mode for COM1 2676 ;com2com resb 1 ; communication command for COM1 2677 ;com1cbufp: resb 8 ; COM1 command buffer char pointer 2678 ;com2cbufp: resb 8 ; COM2 command buffer char pointer 2679 ;com1cbuf: resb 8 ; COM2 command buffer 2680 ;com2cbuf: resb 8 ; COM2 command buffer 2681 2682 ; 22/08/2014 (RTC) 2683 ; (Packed BCD) 2684 000061AC ?? time_seconds: resb 1 2685 000061AD ?? time_minutes: resb 1 2686 000061AE ?? time_hours: resb 1 2687 000061AF ?? date_wday: resb 1 2688 000061B0 ?? date_day: resb 1 2689 000061B1 ?? date_month: resb 1 2690 000061B2 ?? date_year: resb 1 2691 000061B3 ?? date_century: resb 1 2692 2693 %include 'diskbss.inc' ; UNINITIALIZED DISK (BIOS) DATA 2694 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.21) - DISKBSS.INC 2695 <1> ; Last Modification: 12/07/2022 2696 <1> ; (Uninitialized Disk Parameters Data section for 'DISKIO.INC') 2697 <1> ; 2698 <1> ; ***************************************************************************** 2699 <1> ; Ref: Retro UNIX 386 v1.1 'disbss.inc' modification: 10/07/2022 2700 <1> 2701 <1> 2702 <1> alignb 2 2703 <1> 2704 <1> ;---------------------------------------- 2705 <1> ; TIMER DATA AREA : 2706 <1> ;---------------------------------------- 2707 <1> 2708 <1> TIMER_LH: ; 16/02/205 2709 000061B4 ???? <1> TIMER_LOW: resw 1 ; LOW WORD OF TIMER COUNT 2710 000061B6 ???? <1> TIMER_HIGH: resw 1 ; HIGH WORD OF TIMER COUNT 2711 000061B8 ?? <1> TIMER_OFL: resb 1 ; TIMER HAS ROLLED OVER SINCE LAST READ 2712 <1> 2713 <1> ;---------------------------------------- 2714 <1> ; DISKETTE DATA AREAS : 2715 <1> ;---------------------------------------- 2716 <1> 2717 000061B9 ?? <1> SEEK_STATUS: resb 1 2718 000061BA ?? <1> MOTOR_STATUS: resb 1 2719 000061BB ?? <1> MOTOR_COUNT: resb 1 2720 000061BC ?? <1> DSKETTE_STATUS: resb 1 2721 000061BD ?????????????? <1> NEC_STATUS: resb 7 2722 <1> 2723 <1> ;---------------------------------------- 2724 <1> ; ADDITIONAL MEDIA DATA : 2725 <1> ;---------------------------------------- 2726 <1> 2727 000061C4 ?? <1> LASTRATE: resb 1 2728 000061C5 ?? <1> HF_STATUS: resb 1 2729 <1> ;HF_ERROR: resb 1 ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2730 000061C6 ?? <1> HF_INT_FLAG: resb 1 2731 <1> ;HF_CNTRL: resb 1 ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2732 <1> ;DSK_STATE: resb 4 2733 000061C7 ???? <1> DSK_STATE: resb 2 ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2734 000061C9 ???? <1> DSK_TRK: resb 2 2735 <1> 2736 <1> ;---------------------------------------- 2737 <1> ; FIXED DISK DATA AREAS : 2738 <1> ;---------------------------------------- 2739 <1> 2740 000061CB ?? <1> DISK_STATUS1: resb 1 ; FIXED DISK STATUS 2741 000061CC ?? <1> HF_NUM: resb 1 ; COUNT OF FIXED DISK DRIVES 2742 000061CD ?? <1> CONTROL_BYTE: resb 1 ; HEAD CONTROL BYTE 2743 <1> ;@PORT_OFF resb 1 ; RESERVED (PORT OFFSET) 2744 <1> ;port1_off resb 1 ; Hard disk controller 1 - port offset 2745 <1> ;port2_off resb 1 ; Hard idsk controller 2 - port offset 2746 <1> 2747 000061CE ???? <1> alignb 4 2748 <1> 2749 <1> ;HF_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 2750 <1> ;HF1_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 2751 <1> HF_TBL_VEC: ; 22/12/2014 2752 000061D0 ???????? <1> HDPM_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 2753 000061D4 ???????? <1> HDPS_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 2754 000061D8 ???????? <1> HDSM_TBL_VEC: resd 1 ; Secondary master disk param. tbl. pointer 2755 000061DC ???????? <1> HDSS_TBL_VEC: resd 1 ; Secondary slave disk param. tbl. pointer 2756 <1> 2757 <1> ; 03/01/2015 2758 000061E0 ?? <1> LBAMode: resb 1 2759 <1> 2760 <1> ; ***************************************************************************** 2694 2695 ;;; Real Mode Data (10/07/2015 - BSS) 2696 2697 ;alignb 2 2698 2699 ; 27/02/2022 2700 ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data) 2701 2702 ; 23/02/2022 2703 ;; Memory (swap) Data (11/03/2015) 2704 ; 09/03/2015 2705 ;swpq_count: resw 1 ; count of pages on the swap que 2706 ;swp_drv: resd 1 ; logical drive description table address of the swap drive/disk 2707 ;swpd_size: resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 2708 ;swpd_free: resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical) 2709 ;swpd_next: resd 1 ; next free page block 2710 ;swpd_last: resd 1 ; last swap page block 2711 2712 000061E1 ?????? alignb 4 2713 2714 ; 10/07/2015 2715 ; 28/08/2014 2716 000061E4 ???????? error_code: resd 1 2717 ; 29/08/2014 2718 000061E8 ???????? FaultOffset: resd 1 2719 ; 21/09/2015 2720 000061EC ???????? PF_Count: resd 1 ; total page fault count 2721 ; (for debugging - page fault analyze) 2722 ; 'page _fault_handler' (memory.inc) 2723 ; 'sysgeterr' (u9.s) 2724 ; 23/02/2022 2725 000061F0 ???????? rtc_ticks: resd 1 ; (temporary! this rtc counter value may be used 2726 ; for a system call in next retro unix 386 version) 2727 ; -2 ticks per second- 2728 ;; 21/08/2015 2729 ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s 2730 2731 ; 27/02/2022 2732 %include 'ux.s' ; 12/04/2015 (unix system/user/process data) 2733 <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.22) - SYSX.INC (ux.s) 2734 <1> ; Last Modification: 15/07/2022 2735 <1> ; 2736 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 2737 <1> ; (Modified from 2738 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 2739 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 2740 <1> ; ---------------------------------------------------------------------------- 2741 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2742 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2743 <1> ; 2744 <1> ; 2745 <1> ; (Section E10 (17/3/1972) - ux.s) 2746 <1> ; **************************************************************************** 2747 <1> ; 13/11/2015 2748 <1> 2749 <1> alignb 2 2750 <1> 2751 <1> inode: 2752 <1> ; 11/03/2013. 2753 <1> ;Derived from UNIX v1 source code 'inode' structure (ux). 2754 <1> ;i. 2755 <1> 2756 000061F4 ???? <1> i.flgs: resw 1 2757 000061F6 ?? <1> i.nlks: resb 1 2758 000061F7 ?? <1> i.uid: resb 1 2759 000061F8 ???? <1> i.size: resw 1 ; size 2760 000061FA <1> i.dskp: resw 8 ; 16 bytes 2761 0000620A ???????? <1> i.ctim: resd 1 2762 0000620E ???????? <1> i.mtim: resd 1 2763 00006212 ???? <1> i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.) 2764 <1> 2765 <1> I_SIZE equ $ - inode 2766 <1> 2767 <1> process: 2768 <1> ; 26/02/2022 2769 <1> ; 04/02/2022 2770 <1> ; 06/05/2015 2771 <1> ; 11/03/2013 - 05/02/2014 2772 <1> ;Derived from UNIX v1 source code 'proc' structure (ux). 2773 <1> ;p. 2774 <1> 2775 00006214 <1> p.pid: resw nproc 2776 00006234 <1> p.ppid: resw nproc 2777 <1> ;p.break: resw nproc ; 04/02/2022 (p.break is not used) 2778 00006254 <1> p.ttyc: resb nproc ; console tty in Retro UNIX 8086 v1. 2779 <1> ; 26/02/2022 (p.waitc is not used) 2780 <1> ;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1. 2781 00006264 <1> p.link: resb nproc 2782 00006274 <1> p.stat: resb nproc 2783 <1> 2784 <1> ; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 2785 00006284 <1> p.upage: resd nproc ; Physical address of the process's 2786 <1> ; 'user' structure 2787 <1> 2788 <1> 2789 <1> P_SIZE equ $ - process 2790 <1> 2791 <1> 2792 <1> ; fsp table (original UNIX v1) 2793 <1> ; 2794 <1> ;Entry 2795 <1> ; 15 0 2796 <1> ; 1 |---|---------------------------------------| 2797 <1> ; |r/w| i-number of open file | 2798 <1> ; |---|---------------------------------------| 2799 <1> ; | device number | 2800 <1> ; |-------------------------------------------| 2801 <1> ; (*) | offset pointer, i.e., r/w pointer to file | 2802 <1> ; |-------------------------------------------| 2803 <1> ; | flag that says | number of processes | 2804 <1> ; | file deleted | that have file open | 2805 <1> ; |-------------------------------------------| 2806 <1> ; 2 | | 2807 <1> ; |-------------------------------------------| 2808 <1> ; | | 2809 <1> ; |-------------------------------------------| 2810 <1> ; | | 2811 <1> ; |-------------------------------------------| 2812 <1> ; | | 2813 <1> ; |-------------------------------------------| 2814 <1> ; 3 | | 2815 <1> ; | | 2816 <1> ; 2817 <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 2818 <1> 2819 <1> 2820 <1> ; 15/04/2015 2821 000062C4 <1> fsp: resb nfiles * 10 ; 11/05/2015 (8 -> 10) 2822 000064B8 <1> bufp: resd (nbuf+2) ; will be initialized 2823 000064E0 ???? <1> ii: resw 1 2824 000064E2 ???? <1> idev: resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 ! 2825 000064E4 ???? <1> cdev: resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 ! 2826 <1> ; 18/05/2015 2827 <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!) 2828 <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv') 2829 <1> ; 0 -> root device (which has Retro UNIX 8086 v1 file system) 2830 <1> ; 1 -> mounted device (which has Retro UNIX 8086 v1 file system) 2831 <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures) 2832 <1> ; 0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0 2833 <1> ; 1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1 2834 <1> ; 2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h 2835 <1> ; 3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h 2836 <1> ; 4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h 2837 <1> ; 5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h 2838 000064E6 ?? <1> rdev: resb 1 ; root device number ; Retro UNIX 8086 v1 feature only! 2839 <1> ; as above, for physical drives numbers in following table 2840 000064E7 ?? <1> mdev: resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only! 2841 <1> ; 15/04/2015 2842 <1> ;active: resb 1 ; 15/07/2022 2843 <1> ; resb 1 ; 09/06/2015 2844 000064E8 ???? <1> mnti: resw 1 2845 000064EA ???? <1> mntp: resw 1 ; 14/05/2022 ; (parent dir inumber of [mnti]) 2846 000064EC ???? <1> mpid: resw 1 2847 000064EE ???? <1> rootdir: resw 1 2848 <1> ; 14/02/2014 2849 <1> ; Major Modification: Retro UNIX 8086 v1 feature only! 2850 <1> ; Single level run queue 2851 <1> ; (in order to solve sleep/wakeup lock) 2852 000064F0 ???? <1> runq: resw 1 2853 000064F2 ?? <1> imod: resb 1 2854 000064F3 ?? <1> smod: resb 1 2855 000064F4 ?? <1> mmod: resb 1 2856 000064F5 ?? <1> sysflg: resb 1 2857 <1> 2858 000064F6 ???? <1> alignb 4 2859 <1> 2860 <1> user: 2861 <1> ; 18/10/2015 2862 <1> ; 12/10/2015 2863 <1> ; 21/09/2015 2864 <1> ; 24/07/2015 2865 <1> ; 16/06/2015 2866 <1> ; 09/06/2015 2867 <1> ; 11/05/2015 2868 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications) 2869 <1> ; 10/10/2013 2870 <1> ; 11/03/2013. 2871 <1> ;Derived from UNIX v1 source code 'user' structure (ux). 2872 <1> ;u. 2873 <1> 2874 000064F8 ???????? <1> u.sp: resd 1 ; esp (kernel stack at the beginning of 'sysent') 2875 000064FC ???????? <1> u.usp: resd 1 ; esp (kernel stack points to user's registers) 2876 00006500 ???????? <1> u.r0: resd 1 ; eax 2877 00006504 ???? <1> u.cdir: resw 1 2878 00006506 <1> u.fp: resb 10 2879 00006510 ???????? <1> u.fofp: resd 1 2880 00006514 ???????? <1> u.dirp: resd 1 2881 00006518 ???????? <1> u.namep: resd 1 2882 0000651C ???????? <1> u.off: resd 1 2883 00006520 ???????? <1> u.base: resd 1 2884 00006524 ???????? <1> u.count: resd 1 2885 00006528 ???????? <1> u.nread: resd 1 2886 0000652C ???????? <1> u.break: resd 1 ; break 2887 00006530 ???? <1> u.ttyp: resw 1 2888 00006532 <1> u.dirbuf: resb 10 2889 <1> ;u.pri: resw 1 ; 14/02/2014 2890 0000653C ?? <1> u.quant: resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant) 2891 0000653D ?? <1> u.pri: resb 1 ; 2892 0000653E ???? <1> u.intr: resw 1 2893 00006540 ???? <1> u.quit: resw 1 2894 <1> ;u.emt: resw 1 ; 10/10/2013 2895 00006542 ???? <1> u.ilgins: resw 1 2896 00006544 ???? <1> u.cdrv: resw 1 ; cdev 2897 00006546 ?? <1> u.uid: resb 1 ; uid 2898 00006547 ?? <1> u.ruid: resb 1 2899 00006548 ?? <1> u.bsys: resb 1 2900 00006549 ?? <1> u.uno: resb 1 2901 0000654A ???????? <1> u.upage: resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only ! 2902 <1> ; tty number (rtty, rcvt, wtty) 2903 0000654E ?? <1> u.ttyn: resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only ! 2904 <1> ; last error number 2905 0000654F ???????? <1> u.error: resd 1 ; 28/07/2013 - 09/03/2015 2906 <1> ; Retro UNIX 8086/386 v1 feature only! 2907 00006553 ???????? <1> u.pgdir: resd 1 ; 09/03/2015 (page dir addr of process) 2908 00006557 ???????? <1> u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process) 2909 0000655B ???????? <1> u.pbase: resd 1 ; 20/05/2015 (physical base/transfer address) 2910 0000655F ???? <1> u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page) 2911 <1> ;u.pncount: resw 1 2912 <1> ; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir') 2913 <1> ;u.pnbase: resd 1 2914 <1> ; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir') 2915 <1> ; 09/06/2015 2916 00006561 ?? <1> u.kcall: resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign 2917 00006562 ?? <1> u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite) 2918 <1> ; 24/07/2015 - 24/06/2015 2919 <1> ;u.args: resd 1 ; arguments list (line) offset from start of [u.upage] 2920 <1> ; (arg list/line is from offset [u.args] to 4096 in [u.upage]) 2921 <1> ; ([u.args] points to argument count -argc- address offset) 2922 <1> ; 24/06/2015 2923 <1> ;u.core: resd 1 ; physical start address of user's memory space (for sys exec) 2924 <1> ;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec) 2925 <1> ; 21/09/2015 (debugging - page fault analyze) 2926 00006563 ???????? <1> u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr) 2927 <1> 2928 00006567 ?? <1> alignb 4 2929 <1> 2930 <1> U_SIZE equ $ - user 2931 <1> 2932 <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec') 2933 00006568 ???????? <1> pcore: resd 1 ; physical start address of user's memory space (for sys exec) 2934 0000656C ???????? <1> ecore: resd 1 ; physical start address of user's memory space (for sys exec) 2935 00006570 ???????? <1> nbase: resd 1 ; physical base address for 'namei' & 'sysexec' 2936 00006574 ???? <1> ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec' 2937 00006576 ???? <1> argc: resw 1 ; argument count for 'sysexec' 2938 00006578 ???????? <1> argv: resd 1 ; argument list (recent) address for 'sysexec' 2939 <1> 2940 <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning 2941 <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1 2942 0000657C ?? <1> rw: resb 1 ;; Read/Write sign (iget) 2943 0000657D ?? <1> rwdsk: resb 1 ;; Read/Write function number (diskio) - 16/06/2015 2944 0000657E ?? <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015 2945 0000657F ?? <1> resb 1 ;; Reserved (16/06/2015) 2946 <1> 2947 <1> ;alignb 4 2948 <1> 2949 <1> ; 22/08/2015 2950 00006580 <1> buffer: resb nbuf * 520 2951 <1> 2952 000075C0 ???????????????? <1> sb0: resd 2 2953 <1> ;s: 2954 <1> ; (root disk) super block buffer 2955 <1> systm: 2956 <1> ; 13/11/2015 (Retro UNIX 386 v1) 2957 <1> ; 11/03/2013. 2958 <1> ;Derived from UNIX v1 source code 'systm' structure (ux). 2959 <1> ;s. 2960 <1> 2961 000075C8 ???? <1> resw 1 2962 000075CA <1> resb 360 ; 2880 sectors ; original UNIX v1 value: 128 2963 00007732 ???? <1> resw 1 2964 00007734 <1> resb 32 ; 256+40 inodes ; original UNIX v1 value: 64 2965 <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table) 2966 00007754 ???????? <1> s.time: resd 1 2967 00007758 ???????? <1> s.syst: resd 1 2968 0000775C ???????? <1> s.wait_: resd 1 ; wait 2969 00007760 ???????? <1> s.idlet: resd 1 2970 00007764 ???????? <1> s.chrgt: resd 1 2971 00007768 ???? <1> s.drerr: resw 1 2972 <1> 2973 <1> S_SIZE equ $ - systm 2974 <1> 2975 0000776A <1> resb 512-S_SIZE ; 03/06/2015 2976 <1> 2977 000077C8 ???????????????? <1> sb1: resd 2 2978 <1> ; (mounted disk) super block buffer 2979 <1> mount: 2980 000077D0 <1> resb 512 ; 03/06/2015 2981 <1> 2982 <1> ;/ ux -- unix 2983 <1> ; 2984 <1> ;systm: 2985 <1> ; 2986 <1> ; .=.+2 2987 <1> ; .=.+128. 2988 <1> ; .=.+2 2989 <1> ; .=.+64. 2990 <1> ; s.time: .=.+4 2991 <1> ; s.syst: .=.+4 2992 <1> ; s.wait: .=.+4 2993 <1> ; s.idlet:.=.+4 2994 <1> ; s.chrgt:.=.+4 2995 <1> ; s.drerr:.=.+2 2996 <1> ;inode: 2997 <1> ; i.flgs: .=.+2 2998 <1> ; i.nlks: .=.+1 2999 <1> ; i.uid: .=.+1 3000 <1> ; i.size: .=.+2 3001 <1> ; i.dskp: .=.+16. 3002 <1> ; i.ctim: .=.+4 3003 <1> ; i.mtim: .=.+4 3004 <1> ; . = inode+32. 3005 <1> ;mount: .=.+1024. 3006 <1> ;proc: 3007 <1> ; p.pid: .=.+[2*nproc] 3008 <1> ; p.dska: .=.+[2*nproc] 3009 <1> ; p.ppid: .=.+[2*nproc] 3010 <1> ; p.break:.=.+[2*nproc] 3011 <1> ; p.link: .=.+nproc 3012 <1> ; p.stat: .=.+nproc 3013 <1> ;tty: 3014 <1> ; . = .+[ntty*8.] 3015 <1> ;fsp: .=.+[nfiles*8.] 3016 <1> ;bufp: .=.+[nbuf*2]+6 3017 <1> ;sb0: .=.+8 3018 <1> ;sb1: .=.+8 3019 <1> ;swp: .=.+8 3020 <1> ;ii: .=.+2 3021 <1> ;idev: .=.+2 3022 <1> ;cdev: .=.+2 3023 <1> ;deverr: .=.+12. 3024 <1> ;active: .=.+2 3025 <1> ;rfap: .=.+2 3026 <1> ;rkap: .=.+2 3027 <1> ;tcap: .=.+2 3028 <1> ;tcstate:.=.+2 3029 <1> ;tcerrc: .=.+2 3030 <1> ;mnti: .=.+2 3031 <1> ;mntd: .=.+2 3032 <1> ;mpid: .=.+2 3033 <1> ;clockp: .=.+2 3034 <1> ;rootdir:.=.+2 3035 <1> ;toutt: .=.+16. 3036 <1> ;touts: .=.+32. 3037 <1> ;runq: .=.+6 3038 <1> ; 3039 <1> ;wlist: .=.+40. 3040 <1> ;cc: .=.+30. 3041 <1> ;cf: .=.+31. 3042 <1> ;cl: .=.+31. 3043 <1> ;clist: .=.+510. 3044 <1> ;imod: .=.+1 3045 <1> ;smod: .=.+1 3046 <1> ;mmod: .=.+1 3047 <1> ;uquant: .=.+1 3048 <1> ;sysflg: .=.+1 3049 <1> ;pptiflg:.=.+1 3050 <1> ;ttyoch: .=.+1 3051 <1> ; .even 3052 <1> ; .=.+100.; sstack: 3053 <1> ;buffer: .=.+[ntty*140.] 3054 <1> ; .=.+[nbuf*520.] 3055 <1> ; 3056 <1> ; . = core-64. 3057 <1> ;user: 3058 <1> ; u.sp: .=.+2 3059 <1> ; u.usp: .=.+2 3060 <1> ; u.r0: .=.+2 3061 <1> ; u.cdir: .=.+2 3062 <1> ; u.fp: .=.+10. 3063 <1> ; u.fofp: .=.+2 3064 <1> ; u.dirp: .=.+2 3065 <1> ; u.namep: .=.+2 3066 <1> ; u.off: .=.+2 3067 <1> ; u.base: .=.+2 3068 <1> ; u.count: .=.+2 3069 <1> ; u.nread: .=.+2 3070 <1> ; u.break: .=.+2 3071 <1> ; u.ttyp: .=.+2 3072 <1> ; u.dirbuf:.=.+10. 3073 <1> ; u.pri: .=.+2 3074 <1> ; u.intr: .=.+2 3075 <1> ; u.quit: .=.+2 3076 <1> ; u.emt: .=.+2 3077 <1> ; u.ilgins:.=.+2 3078 <1> ; u.cdev: .=.+2 3079 <1> ; u.uid: .=.+1 3080 <1> ; u.ruid: .=.+1 3081 <1> ; u.bsys: .=.+1 3082 <1> ; u.uno: .=.+1 3083 <1> ;. = core 2733 2734 bss_end: 2735 2736 ; 27/02/2022 2737 BSS_SIZE equ bss_end - bss_start 2738 2739 ; 27/12/2013 2740 _end: ; end of kernel code (and read only data, just before bss)