1 ; **************************************************************************** 2 ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.6 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 (v0.2.1.6) ] 13 ; 04/02/2016 - Retro UNIX 386 v1.1 (Retro UNIX Kernel v0.2.1.0) 14 ; 31/12/2021 - BugFix and Code Optimization (v0.2.1.1) 15 ; 03/03/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022 16 ; 04/04/2022 - Inode Table/List Address Modification (v0.2.1.2) -u5.s- 17 ; 22/04/2022 - BugFix ('mget' -u5.s-) 18 ; 29/04/2022 - BugFix ('syschmod' -u2.s-) (v0.2.1.2) 19 ; ; (v0.2.1.3) 20 ; 09/05/2022 - u2.s (sysstat), u7.s (sysumount), diskinit.inc 21 ; 15/05/2022 - u2.s (namei), u7.s (sysumount) 22 ; 01/06/2022 - BugFix ('set_date_time' -u0.s-) (v0.2.1.3) 23 ; ; (v0.2.1.4) 24 ; 13/06/2022 - LPT1 (/dev/lpr) printing modification (v0.2.1.4) 25 ; 14/06/2022 - BugFix (video.inc,'set_cpos' <- u9.s 'putc' carry flg) 26 ; ; (v0.2.1.5) 27 ; 08/07/2022 - diskio.s (diskio simplified by removing the unused code) 28 ; ; (v0.2.1.6) 29 ; 15/07/2022 - Simplified and Improved Buffer Handling -u8.s- 30 ; 16/07/2022 - Code Optimization 31 ; 17/07/2022 - Code Optimization 32 ; 18/07/2022 - Code Optimization 33 ; 19/07/2022 - BugFix (File Offset after disk write error, u6.s, u8.s) 34 ; 24/07/2022 - keyboard.s (simplified & optimized 'getc_int') 35 ; 36 ; Derived from UNIX Operating System (v1.0 for PDP-11) 37 ; (Original) Source Code by Ken Thompson (1971-1972) 38 ; 39 ; 40 ; 41 ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999) 42 ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details. 43 ; 44 ; **************************************************************************** 45 ; 31/12/2021 - 15/07/2022 46 ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt 47 ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk) 48 49 ; 02/01/2022 - Code Optimization 50 ; Runix Kernel v0.2.1.2 51 ; 24/12/2021 - BugFix and Code Optimization 52 ; Runix Kernel v0.2.1.1 53 54 ; 24/12/2013 55 56 ; Entering protected mode: 57 ; Derived from 'simple_asm.txt' source code file and 58 ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003) 59 ; (gregor.brunmar@home.se) 60 ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode 61 ; 62 63 ; "The Real, Protected, Long mode assembly tutorial for PCs" 64 ; by Michael Chourdakis (2009) 65 ; http://www.codeproject.com/Articles/45788/ 66 ; http://www.michaelchourdakis.com 67 ; 68 69 ; Global Descriptor Table: 70 ; Derived from 'head.s" source code of Linux v1.0 kernel 71 ; by Linus Torvalds (1991-1992) 72 ; 73 74 KLOAD equ 10000h ; Kernel loading address 75 ; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 76 KCODE equ 08h ; Code segment descriptor (ring 0) 77 KDATA equ 10h ; Data segment descriptor (ring 0) 78 ; 19/03/2015 79 UCODE equ 1Bh ; 18h + 3h (ring 3) 80 UDATA equ 23h ; 20h + 3h (ring 3) 81 ; 24/03/2015 82 TSS equ 28h ; Task state segment descriptor (ring 0) 83 ; 19/03/2015 84 CORE equ 400000h ; Start of USER's virtual/linear address space 85 ; (at the end of the 1st 4MB) 86 ECORE equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB) 87 ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT) 88 89 ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2) 90 ;; 27/12/2013 91 ;KEND equ KLOAD + 65536 ; (28/12/2013) (end of kernel space) 92 93 ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc) 94 ;--------- CMOS TABLE LOCATION ADDRESS'S ------------------------------------- 95 CMOS_SECONDS EQU 00H ; SECONDS (BCD) 96 CMOS_MINUTES EQU 02H ; MINUTES (BCD) 97 CMOS_HOURS EQU 04H ; HOURS (BCD) 98 CMOS_DAY_WEEK EQU 06H ; DAY OF THE WEEK (BCD) 99 CMOS_DAY_MONTH EQU 07H ; DAY OF THE MONTH (BCD) 100 CMOS_MONTH EQU 08H ; MONTH (BCD) 101 CMOS_YEAR EQU 09H ; YEAR (TWO DIGITS) (BCD) 102 CMOS_CENTURY EQU 32H ; DATE CENTURY BYTE (BCD) 103 CMOS_REG_A EQU 0AH ; STATUS REGISTER A 104 CMOS_REG_B EQU 00BH ; STATUS REGISTER B ALARM 105 CMOS_REG_C EQU 00CH ; STATUS REGISTER C FLAGS 106 CMOS_REG_D EQU 0DH ; STATUS REGISTER D BATTERY 107 CMOS_SHUT_DOWN EQU 0FH ; SHUTDOWN STATUS COMMAND BYTE 108 ;---------------------------------------- 109 ; CMOS EQUATES FOR THIS SYSTEM ; 110 ;----------------------------------------------------------------------------- 111 CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 112 CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 113 NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 114 ; HIGH BIT OF CMOS LOCATION ADDRESS 115 116 ; Memory Allocation Table Address 117 ; 05/11/2014 118 ; 31/10/2014 119 MEM_ALLOC_TBL equ 100000h ; Memory Allocation Table at the end of 120 ; the 1st 1 MB memory space. 121 ; (This address must be aligned 122 ; on 128 KB boundary, if it will be 123 ; changed later.) 124 ; ((lower 17 bits of 32 bit M.A.T. 125 ; address must be ZERO)). 126 ; ((((Reason: 32 bit allocation 127 ; instructions, dword steps))) 128 ; (((byte >> 12 --> page >> 5))) 129 ;04/11/2014 130 PDE_A_PRESENT equ 1 ; Present flag for PDE 131 PDE_A_WRITE equ 2 ; Writable (write permission) flag 132 PDE_A_USER equ 4 ; User (non-system/kernel) page flag 133 ; 134 PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 135 PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 136 PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 137 PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 138 139 ; 17/02/2015 (unix386.s) 140 ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s) 141 DPT_SEGM equ 09000h ; FDPT segment (EDD v1.1, EDD v3) 142 ; 143 HD0_DPT equ 0 ; Disk parameter table address for hd0 144 HD1_DPT equ 32 ; Disk parameter table address for hd1 145 HD2_DPT equ 64 ; Disk parameter table address for hd2 146 HD3_DPT equ 96 ; Disk parameter table address for hd3 147 148 149 ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0) 150 ; (HDPT: Programmer's Guide to the AMIBIOS, 1993) 151 ; 152 FDPT_CYLS equ 0 ; 1 word, number of cylinders 153 FDPT_HDS equ 2 ; 1 byte, number of heads 154 FDPT_TT equ 3 ; 1 byte, A0h = translated FDPT with logical values 155 ; otherwise it is standard FDPT with physical values 156 FDPT_PCMP equ 5 ; 1 word, starting write precompensation cylinder 157 ; (obsolete for IDE/ATA drives) 158 FDPT_CB equ 8 ; 1 byte, drive control byte 159 ; Bits 7-6 : Enable or disable retries (00h = enable) 160 ; Bit 5 : 1 = Defect map is located at last cyl. + 1 161 ; Bit 4 : Reserved. Always 0 162 ; Bit 3 : Set to 1 if more than 8 heads 163 ; Bit 2-0 : Reserved. Alsways 0 164 FDPT_LZ equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives) 165 FDPT_SPT equ 14 ; 1 byte, sectors per track 166 167 ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993) 168 ; (11 bytes long) will be used by diskette handler/bios 169 ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986). 170 171 [BITS 16] ; We need 16-bit intructions for Real mode 172 173 [ORG 0] 174 175 KSTART: ; 01/01/2022 176 177 ; 12/11/2014 178 ; Save boot drive number (that is default root drive) 179 00000000 8816[485C] mov [boot_drv], dl ; physical drv number 180 181 ; Determine installed memory 182 ; 31/10/2014 183 ; 184 00000004 B801E8 mov ax, 0E801h ; Get memory size 185 00000007 CD15 int 15h ; for large configurations 186 00000009 7308 jnc short chk_ms 187 0000000B B488 mov ah, 88h ; Get extended memory size 188 0000000D CD15 int 15h 189 ; 190 ;mov al, 17h ; Extended memory (1K blocks) low byte 191 ;out 70h, al ; select CMOS register 192 ;in al, 71h ; read data (1 byte) 193 ;mov cl, al 194 ;mov al, 18h ; Extended memory (1K blocks) high byte 195 ;out 70h, al ; select CMOS register 196 ;in al, 71h ; read data (1 byte) 197 ;mov ch, al 198 ; 199 0000000F 89C1 mov cx, ax 200 00000011 31D2 xor dx, dx 201 chk_ms: 202 00000013 890E[B45E] mov [mem_1m_1k], cx 203 00000017 8916[B85E] mov [mem_16m_64k], dx 204 ; 05/11/2014 205 ;and dx, dx 206 ;jz short L2 207 0000001B 81F90004 cmp cx, 1024 208 0000001F 7351 jnb short L0 209 ; insufficient memory_error 210 ; Minimum 2 MB memory is needed... 211 ; 05/11/2014 212 ; (real mode error printing) 213 00000021 FB sti 214 00000022 BE[3600] mov si, msg_out_of_memory 215 00000025 BB0700 mov bx, 7 216 00000028 B40E mov ah, 0Eh ; write tty 217 oom_1: 218 0000002A AC lodsb 219 0000002B 08C0 or al, al 220 0000002D 7404 jz short oom_2 221 0000002F CD10 int 10h 222 00000031 EBF7 jmp short oom_1 223 oom_2: 224 00000033 F4 hlt 225 00000034 EBFD jmp short oom_2 226 227 ; 02/01/2022 228 ; 05/11/2014 229 msg_out_of_memory: 230 00000036 070D0A db 07h, 0Dh, 0Ah 231 00000039 496E73756666696369- db 'Insufficient memory !' 231 00000042 656E74206D656D6F72- 231 0000004B 792021 232 0000004E 0D0A db 0Dh, 0Ah 233 _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc') 234 00000050 284D696E696D756D20- db '(Minimum 2MB memory is needed.)' 234 00000059 324D42206D656D6F72- 234 00000062 79206973206E656564- 234 0000006B 65642E29 235 0000006F 0D0A00 db 0Dh, 0Ah, 0 236 237 L0: 238 %include 'diskinit.inc' ; 07/03/2015 239 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKINIT.INC 240 <1> ; Last Modification: 12/07/2022 241 <1> 242 <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project) 243 <1> 244 <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION /////////////// 245 <1> 246 <1> ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2) 247 <1> ; 10/12/2014 - 02/02/2015 - dsectrm2.s 248 <1> ;L0: 249 <1> ; 12/11/2014 (Retro UNIX 386 v1 - beginning) 250 <1> ; Detecting disk drives... (by help of ROM-BIOS) 251 00000072 BA7F00 <1> mov dx, 7Fh 252 <1> L1: 253 00000075 FEC2 <1> inc dl 254 00000077 B441 <1> mov ah, 41h ; Check extensions present 255 <1> ; Phoenix EDD v1.1 - EDD v3 256 00000079 BBAA55 <1> mov bx, 55AAh 257 0000007C CD13 <1> int 13h 258 0000007E 721A <1> jc short L2 259 <1> 260 00000080 81FB55AA <1> cmp bx, 0AA55h 261 00000084 7514 <1> jne short L2 262 00000086 FE06[4B5C] <1> inc byte [hdc] ; count of hard disks (EDD present) 263 0000008A 8816[4A5C] <1> mov [last_drv], dl ; last hard disk number 264 0000008E BB[CE5B] <1> mov bx, hd0_type - 80h 265 00000091 01D3 <1> add bx, dx 266 00000093 880F <1> mov [bx], cl ; Interface support bit map in CX 267 <1> ; Bit 0 - 1, Fixed disk access subset ready 268 <1> ; Bit 1 - 1, Drv locking and ejecting ready 269 <1> ; Bit 2 - 1, Enhanced Disk Drive Support 270 <1> ; (EDD) ready (DPTE ready) 271 <1> ; Bit 3 - 1, 64bit extensions are present 272 <1> ; (EDD-3) 273 <1> ; Bit 4 to 15 - 0, Reserved 274 00000095 80FA83 <1> cmp dl, 83h ; drive number < 83h 275 00000098 72DB <1> jb short L1 276 <1> L2: 277 <1> ; 23/11/2014 278 <1> ; 19/11/2014 279 0000009A 30D2 <1> xor dl, dl ; 0 280 <1> ; 04/02/2016 (esi -> si) 281 0000009C BE[4C5C] <1> mov si, fd0_type 282 <1> L3: 283 <1> ; 14/01/2015 284 0000009F 8816[495C] <1> mov [drv], dl 285 <1> ; 286 000000A3 B408 <1> mov ah, 08h ; Return drive parameters 287 000000A5 CD13 <1> int 13h 288 000000A7 7210 <1> jc short L4 289 <1> ; BL = drive type (for floppy drives) 290 <1> ; DL = number of floppy drives 291 <1> ; 292 <1> ; ES:DI = Address of DPT from BIOS 293 <1> ; 294 000000A9 881C <1> mov [si], bl ; Drive type 295 <1> ; 4 = 1.44 MB, 80 track, 3 1/2" 296 <1> ; 14/01/2015 297 000000AB E8BB01 <1> call set_disk_parms 298 <1> ; 10/12/2014 299 000000AE 81FE[4C5C] <1> cmp si, fd0_type 300 000000B2 7705 <1> ja short L4 301 000000B4 46 <1> inc si ; fd1_type 302 000000B5 B201 <1> mov dl, 1 303 000000B7 EBE6 <1> jmp short L3 304 <1> L4: 305 <1> ; Older BIOS (INT 13h, AH = 48h is not available) 306 000000B9 B27F <1> mov dl, 7Fh 307 <1> ; 24/12/2014 (Temporary) 308 000000BB 803E[4B5C]00 <1> cmp byte [hdc], 0 ; EDD present or not ? 309 <1> ;ja L10 ; yes, all fixed disk operations 310 <1> ; will be performed according to 311 <1> ; present EDD specification 312 <1> ; 02/01/2022 313 000000C0 7603 <1> jna short L5 314 000000C2 E99100 <1> jmp L10 315 <1> L5: 316 000000C5 FEC2 <1> inc dl 317 000000C7 8816[495C] <1> mov [drv], dl 318 000000CB 8816[4A5C] <1> mov [last_drv], dl ; 14/01/2015 319 000000CF B408 <1> mov ah, 08h ; Return drive parameters 320 000000D1 CD13 <1> int 13h ; (conventional function) 321 <1> ;jc L13 ; fixed disk drive not ready 322 <1> ; 02/01/2022 323 000000D3 7303 <1> jnc short L6 324 000000D5 E98301 <1> jmp L13 325 <1> L6: 326 000000D8 8816[4B5C] <1> mov [hdc], dl ; number of drives 327 <1> ;; 14/01/2013 328 <1> ;;push cx 329 000000DC E88A01 <1> call set_disk_parms 330 <1> ;;pop cx 331 <1> ; 332 <1> ;;and cl, 3Fh ; sectors per track (bits 0-6) 333 000000DF 8A16[495C] <1> mov dl, [drv] 334 000000E3 BB0401 <1> mov bx, 65*4 ; hd0 parameters table (INT 41h) 335 000000E6 80FA80 <1> cmp dl, 80h 336 000000E9 7603 <1> jna short L7 337 000000EB 83C314 <1> add bx, 5*4 ; hd1 parameters table (INT 46h) 338 <1> L7: 339 000000EE 31C0 <1> xor ax, ax 340 000000F0 8ED8 <1> mov ds, ax 341 000000F2 8B37 <1> mov si, [bx] 342 000000F4 8B4702 <1> mov ax, [bx+2] 343 000000F7 8ED8 <1> mov ds, ax 344 000000F9 3A4C0E <1> cmp cl, [si+FDPT_SPT] ; sectors per track 345 <1> ;jne L12 ; invalid FDPT 346 <1> ; 02/01/2022 347 000000FC 7403 <1> je short L7_8 348 000000FE E95601 <1> jmp L12 349 <1> L7_8: 350 00000101 BF0000 <1> mov di, HD0_DPT 351 00000104 80FA80 <1> cmp dl, 80h 352 00000107 7603 <1> jna short L8 353 00000109 BF2000 <1> mov di, HD1_DPT 354 <1> L8: 355 <1> ; 30/12/2014 356 0000010C B80090 <1> mov ax, DPT_SEGM 357 0000010F 8EC0 <1> mov es, ax 358 <1> ; 24/12/2014 359 00000111 B90800 <1> mov cx, 8 360 00000114 F3A5 <1> rep movsw ; copy 16 bytes to the kernel's DPT location 361 00000116 8CC8 <1> mov ax, cs 362 00000118 8ED8 <1> mov ds, ax 363 <1> ; 02/02/2015 364 0000011A 8A0E[495C] <1> mov cl, [drv] 365 0000011E 88CB <1> mov bl, cl 366 00000120 B8F001 <1> mov ax, 1F0h 367 00000123 80E301 <1> and bl, 1 368 00000126 7406 <1> jz short L9 369 00000128 C0E304 <1> shl bl, 4 370 0000012B 2D8000 <1> sub ax, 1F0h-170h 371 <1> L9: 372 0000012E AB <1> stosw ; I/O PORT Base Address (1F0h, 170h) 373 0000012F 050602 <1> add ax, 206h 374 00000132 AB <1> stosw ; CONTROL PORT Address (3F6h, 376h) 375 00000133 88D8 <1> mov al, bl 376 00000135 04A0 <1> add al, 0A0h 377 00000137 AA <1> stosb ; Device/Head Register upper nibble 378 <1> ; 379 00000138 FE06[495C] <1> inc byte [drv] 380 0000013C BB[CE5B] <1> mov bx, hd0_type - 80h 381 0000013F 01CB <1> add bx, cx 382 00000141 800F80 <1> or byte [bx], 80h ; present sign (when lower nibble is 0) 383 00000144 A0[4B5C] <1> mov al, [hdc] 384 00000147 FEC8 <1> dec al 385 <1> ;jz L13 386 <1> ; 02/01/2022 387 00000149 7408 <1> jz short L9_10 388 0000014B 80FA80 <1> cmp dl, 80h 389 <1> ;jna L5 390 <1> ;jmp L13 391 <1> ; 02/01/2022 392 0000014E 7703 <1> ja short L9_10 393 00000150 E972FF <1> jmp L5 394 <1> L9_10: 395 00000153 E90501 <1> jmp L13 396 <1> L10: 397 00000156 FEC2 <1> inc dl 398 <1> ; 25/12/2014 399 00000158 8816[495C] <1> mov [drv], dl 400 0000015C B408 <1> mov ah, 08h ; Return drive parameters 401 0000015E CD13 <1> int 13h ; (conventional function) 402 <1> ;jc L13 403 <1> ; 02/01/2022 404 00000160 72F1 <1> jc short L9_10 405 <1> ; 14/01/2015 406 00000162 8A16[495C] <1> mov dl, [drv] 407 00000166 52 <1> push dx 408 00000167 51 <1> push cx 409 00000168 E8FE00 <1> call set_disk_parms 410 0000016B 59 <1> pop cx 411 0000016C 5A <1> pop dx 412 <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2) 413 <1> ; 04/02/2016 (esi -> si) 414 <1> ;mov si, _end ; 30 byte temporary buffer address 415 <1> ; ; at the '_end' of kernel. 416 <1> ;mov word [si], 30 417 <1> ; 06/07/2016 418 0000016D BE[5000] <1> mov si, _int13h_48h_buffer 419 <1> ; 09/07/2016 420 00000170 B81E00 <1> mov ax, 001Eh 421 00000173 8824 <1> mov [si], ah ; 0 422 00000175 46 <1> inc si 423 00000176 8904 <1> mov word [si], ax 424 <1> ; word [si] = 30 425 <1> ; 426 00000178 B448 <1> mov ah, 48h ; Get drive parameters (EDD function) 427 0000017A CD13 <1> int 13h 428 <1> ;jc L13 429 <1> ; 02/01/2022 430 0000017C 72D5 <1> jc short L9_10 431 <1> ; 04/02/2016 (ebx -> bx) 432 <1> ; 14/01/2015 433 <1> ;sub bx, bx 434 0000017E 28FF <1> sub bh, bh ; 02/01/2022 435 00000180 88D3 <1> mov bl, dl 436 00000182 80EB80 <1> sub bl, 80h 437 00000185 81C3[4E5C] <1> add bx, hd0_type 438 00000189 8A07 <1> mov al, [bx] 439 0000018B 0C80 <1> or al, 80h 440 0000018D 8807 <1> mov [bx], al 441 0000018F 81EB[4C5C] <1> sub bx, hd0_type - 2 ; 15/01/2015 442 00000193 81C3[6E5C] <1> add bx, drv.status 443 00000197 8807 <1> mov [bx], al 444 <1> ; 04/02/2016 (eax -> ax) 445 00000199 8B4410 <1> mov ax, [si+16] 446 0000019C 854412 <1> test ax, [si+18] 447 0000019F 7413 <1> jz short L10_A0h 448 <1> ; 'CHS only' disks on EDD system 449 <1> ; are reported with ZERO disk size 450 000001A1 81EB[6E5C] <1> sub bx, drv.status 451 000001A5 C1E302 <1> shl bx, 2 452 000001A8 81C3[525C] <1> add bx, drv.size ; disk size (in sectors) 453 000001AC 8907 <1> mov [bx], ax 454 000001AE 8B4412 <1> mov ax, [si+18] 455 <1> ;mov [bx], ax 456 <1> ; 02/01/2022 (BugFix) 457 000001B1 894702 <1> mov [bx+2], ax 458 <1> 459 <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 460 <1> ; for CHS disks (28/02/2015) 461 <1> ; 30/12/2014 462 000001B4 BF0000 <1> mov di, HD0_DPT 463 000001B7 88D0 <1> mov al, dl 464 000001B9 83E003 <1> and ax, 3 465 000001BC C0E005 <1> shl al, 5 ; *32 466 000001BF 01C7 <1> add di, ax 467 000001C1 B80090 <1> mov ax, DPT_SEGM 468 000001C4 8EC0 <1> mov es, ax 469 <1> ; 470 000001C6 88E8 <1> mov al, ch ; max. cylinder number (bits 0-7) 471 000001C8 88CC <1> mov ah, cl 472 000001CA C0EC06 <1> shr ah, 6 ; max. cylinder number (bits 8-9) 473 000001CD 40 <1> inc ax ; logical cylinders (limit 1024) 474 000001CE AB <1> stosw 475 000001CF 88F0 <1> mov al, dh ; max. head number 476 000001D1 FEC0 <1> inc al 477 000001D3 AA <1> stosb ; logical heads (limits 256) 478 000001D4 B0A0 <1> mov al, 0A0h ; Indicates translated table 479 000001D6 AA <1> stosb 480 000001D7 8A440C <1> mov al, [si+12] 481 000001DA AA <1> stosb ; physical sectors per track 482 000001DB 31C0 <1> xor ax, ax 483 <1> ;dec ax ; 02/01/2015 484 000001DD AB <1> stosw ; precompensation (obsolete) 485 <1> ;xor al, al ; 02/01/2015 486 000001DE AA <1> stosb ; reserved 487 000001DF B008 <1> mov al, 8 ; drive control byte 488 <1> ; (do not disable retries, 489 <1> ; more than 8 heads) 490 000001E1 AA <1> stosb 491 000001E2 8B4404 <1> mov ax, [si+4] 492 000001E5 AB <1> stosw ; physical number of cylinders 493 <1> ;push ax ; 02/01/2015 494 000001E6 8A4408 <1> mov al, [si+8] 495 000001E9 AA <1> stosb ; physical num. of heads (limit 16) 496 000001EA 29C0 <1> sub ax, ax 497 <1> ;pop ax ; 02/01/2015 498 000001EC AB <1> stosw ; landing zone (obsolete) 499 000001ED 88C8 <1> mov al, cl ; logical sectors per track (limit 63) 500 000001EF 243F <1> and al, 3Fh 501 000001F1 AA <1> stosb 502 <1> ;sub al, al ; checksum 503 <1> ;stosb 504 <1> ; 505 000001F2 83C61A <1> add si, 26 ; (BIOS) DPTE address pointer 506 000001F5 AD <1> lodsw 507 000001F6 50 <1> push ax ; (BIOS) DPTE offset 508 000001F7 AD <1> lodsw 509 000001F8 50 <1> push ax ; (BIOS) DPTE segment 510 <1> ; 511 <1> ; checksum calculation 512 000001F9 89FE <1> mov si, di 513 000001FB 06 <1> push es 514 000001FC 1F <1> pop ds 515 <1> ;mov cx, 16 516 000001FD B90F00 <1> mov cx, 15 517 00000200 29CE <1> sub si, cx 518 00000202 30E4 <1> xor ah, ah 519 <1> ;del cl 520 <1> L11: 521 00000204 AC <1> lodsb 522 00000205 00C4 <1> add ah, al 523 00000207 E2FB <1> loop L11 524 <1> ; 525 00000209 88E0 <1> mov al, ah 526 0000020B F6D8 <1> neg al ; -x+x = 0 527 0000020D AA <1> stosb ; put checksum in byte 15 of the tbl 528 <1> ; 529 0000020E 1F <1> pop ds ; (BIOS) DPTE segment 530 0000020F 5E <1> pop si ; (BIOS) DPTE offset 531 <1> ; 532 <1> ; 23/02/2015 533 00000210 57 <1> push di 534 <1> ; ES:DI points to DPTE (FDPTE) location 535 <1> ;mov cx, 8 536 00000211 B108 <1> mov cl, 8 537 00000213 F3A5 <1> rep movsw 538 <1> ; 539 <1> ; 23/02/2015 540 <1> ; (P)ATA drive and LBA validation 541 <1> ; (invalidating SATA drives and setting 542 <1> ; CHS type I/O for old type fixed disks) 543 00000215 5B <1> pop bx 544 00000216 8CC8 <1> mov ax, cs 545 00000218 8ED8 <1> mov ds, ax 546 0000021A 268B07 <1> mov ax, [es:bx] 547 0000021D 3DF001 <1> cmp ax, 1F0h 548 00000220 7418 <1> je short L11a 549 00000222 3D7001 <1> cmp ax, 170h 550 00000225 7413 <1> je short L11a 551 <1> ; invalidation 552 <1> ; (because base port address is not 1F0h or 170h) 553 00000227 30FF <1> xor bh, bh 554 00000229 88D3 <1> mov bl, dl 555 0000022B 80EB80 <1> sub bl, 80h 556 0000022E C687[4E5C]00 <1> mov byte [bx+hd0_type], 0 ; not a valid disk drive ! 557 00000233 808F[705C]F0 <1> or byte [bx+drv.status+2], 0F0h ; (failure sign) 558 00000238 EB14 <1> jmp short L11b 559 <1> L11a: 560 <1> ; LBA validation 561 0000023A 268A4704 <1> mov al, [es:bx+4] ; Head register upper nibble 562 0000023E A840 <1> test al, 40h ; LBA bit (bit 6) 563 00000240 750C <1> jnz short L11b ; LBA type I/O is OK! (E0h or F0h) 564 <1> ; force CHS type I/O for this drive (A0h or B0h) 565 00000242 28FF <1> sub bh, bh 566 00000244 88D3 <1> mov bl, dl 567 00000246 80EB80 <1> sub bl, 80h ; 26/02/2015 568 00000249 80A7[705C]FE <1> and byte [bx+drv.status+2], 0FEh ; clear bit 0 569 <1> ; bit 0 = LBA ready bit 570 <1> ; 'diskio' procedure will check this bit ! 571 <1> L11b: 572 0000024E 3A16[4A5C] <1> cmp dl, [last_drv] ; 25/12/2014 573 00000252 7307 <1> jnb short L13 574 00000254 E9FFFE <1> jmp L10 575 <1> L12: 576 <1> ; Restore data registers 577 00000257 8CC8 <1> mov ax, cs 578 00000259 8ED8 <1> mov ds, ax 579 <1> L13: 580 <1> ; 13/12/2014 581 0000025B 0E <1> push cs 582 0000025C 07 <1> pop es 583 <1> L14: 584 0000025D B411 <1> mov ah, 11h 585 0000025F CD16 <1> int 16h 586 <1> ;jz short L15 ; no keys in keyboard buffer 587 <1> ; 02/01/2022 588 00000261 7447 <1> jz short L16 589 00000263 B010 <1> mov al, 10h 590 00000265 CD16 <1> int 16h 591 00000267 EBF4 <1> jmp short L14 592 <1> L15: 593 <1> 594 <1> ; ////// 595 <1> 596 <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2) 597 <1> %if 0 598 <1> ; 24/11/2014 599 <1> ; 19/11/2014 600 <1> ; 14/11/2014 601 <1> ; Temporary code for disk searching code check 602 <1> ; 603 <1> ; This code will show existing (usable) drives and also 604 <1> ; will show EDD interface support status for hard disks 605 <1> ; (If status bit 7 is 1, Identify Device info is ready, 606 <1> ; no need to get it again in protected mode...) 607 <1> ; 608 <1> ; 13/11/2014 609 <1> mov bx, 7 610 <1> mov ah, 0Eh 611 <1> mov al, [fd0_type] 612 <1> and al, al 613 <1> jz short L15a 614 <1> mov dl, al 615 <1> mov al, 'F' 616 <1> int 10h 617 <1> mov al, 'D' 618 <1> int 10h 619 <1> mov al, '0' 620 <1> int 10h 621 <1> mov al, ' ' 622 <1> int 10h 623 <1> call L15c 624 <1> mov al, ' ' 625 <1> int 10h 626 <1> ; 627 <1> mov al, [fd1_type] 628 <1> and al, al 629 <1> jz short L15a 630 <1> mov dl, al 631 <1> mov al, 'F' 632 <1> int 10h 633 <1> mov al, 'D' 634 <1> int 10h 635 <1> mov al, '1' 636 <1> int 10h 637 <1> mov al, ' ' 638 <1> int 10h 639 <1> call L15c 640 <1> mov al, ' ' 641 <1> int 10h 642 <1> mov al, ' ' 643 <1> int 10h 644 <1> L15a: 645 <1> mov al, [hd0_type] 646 <1> and al, al 647 <1> jz short L15b 648 <1> mov dl, al 649 <1> mov al, 'H' 650 <1> int 10h 651 <1> mov al, 'D' 652 <1> int 10h 653 <1> mov al, '0' 654 <1> int 10h 655 <1> mov al, ' ' 656 <1> int 10h 657 <1> call L15c 658 <1> mov al, ' ' 659 <1> int 10h 660 <1> ; 661 <1> mov al, [hd1_type] 662 <1> and al, al 663 <1> jz short L15b 664 <1> mov dl, al 665 <1> mov al, 'H' 666 <1> int 10h 667 <1> mov al, 'D' 668 <1> int 10h 669 <1> mov al, '1' 670 <1> int 10h 671 <1> mov al, ' ' 672 <1> int 10h 673 <1> call L15c 674 <1> mov al, ' ' 675 <1> int 10h 676 <1> ; 677 <1> mov al, [hd2_type] 678 <1> and al, al 679 <1> jz short L15b 680 <1> mov dl, al 681 <1> mov al, 'H' 682 <1> int 10h 683 <1> mov al, 'D' 684 <1> int 10h 685 <1> mov al, '2' 686 <1> int 10h 687 <1> mov al, ' ' 688 <1> int 10h 689 <1> call L15c 690 <1> mov al, ' ' 691 <1> int 10h 692 <1> ; 693 <1> mov al, [hd3_type] 694 <1> and al, al 695 <1> jz short L15b 696 <1> mov dl, al 697 <1> mov al, 'H' 698 <1> int 10h 699 <1> mov al, 'D' 700 <1> int 10h 701 <1> mov al, '3' 702 <1> int 10h 703 <1> mov al, ' ' 704 <1> int 10h 705 <1> call L15c 706 <1> mov al, ' ' 707 <1> int 10h 708 <1> ; 709 <1> L15b: 710 <1> mov al, 0Dh 711 <1> int 10h 712 <1> mov al, 0Ah 713 <1> int 10h 714 <1> ;;xor ah, ah 715 <1> ;;int 16h 716 <1> ; 717 <1> ;jmp L16 ; jmp short L16 718 <1> ; 02/01/2022 719 <1> jmp short L16 720 <1> ; 721 <1> L15c: 722 <1> mov dh, dl 723 <1> shr dh, 4 724 <1> add dh, 30h 725 <1> and dl, 15 726 <1> add dl, 30h 727 <1> mov al, dh 728 <1> int 10h 729 <1> mov al, dl 730 <1> int 10h 731 <1> retn 732 <1> ; 733 <1> ; end of temporary code for disk searching code check 734 <1> 735 <1> %endif 736 <1> 737 <1> ; ////// 738 <1> 739 <1> set_disk_parms: 740 <1> ; 12/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 741 <1> ; 09/05/2022 742 <1> ; disksize = cylinders*spt*heads (*) 743 <1> ; (fd0&fd1 drv.size is calculated with total cylinders) 744 <1> ; 745 <1> ; 04/02/2016 (ebx -> bx) 746 <1> ; 10/07/2015 747 <1> ; 14/01/2015 748 <1> ;push bx 749 00000269 28FF <1> sub bh, bh 750 0000026B 8A1E[495C] <1> mov bl, [drv] 751 0000026F 80FB80 <1> cmp bl, 80h 752 00000272 7203 <1> jb short sdp0 753 00000274 80EB7E <1> sub bl, 7Eh 754 <1> sdp0: 755 00000277 81C3[6E5C] <1> add bx, drv.status 756 0000027B C60780 <1> mov byte [bx], 80h ; 'Present' flag 757 <1> ; 758 0000027E 88E8 <1> mov al, ch ; last cylinder (bits 0-7) 759 00000280 88CC <1> mov ah, cl ; 760 00000282 C0EC06 <1> shr ah, 6 ; last cylinder (bits 8-9) 761 00000285 81EB[6E5C] <1> sub bx, drv.status 762 00000289 D0E3 <1> shl bl, 1 763 <1> ; 12/07/2022 764 <1> ;add bx, drv.cylinders 765 0000028B 40 <1> inc ax ; convert max. cyl number to cyl count 766 <1> ;mov [bx], ax 767 0000028C 50 <1> push ax ; ** cylinders 768 <1> ;sub bx, drv.cylinders 769 <1> ;add bx, drv.heads 770 0000028D 30E4 <1> xor ah, ah 771 0000028F 88F0 <1> mov al, dh ; heads 772 00000291 40 <1> inc ax 773 <1> ;mov [bx], ax 774 <1> ;sub bx, drv.heads 775 <1> ;add bx, drv.spt 776 00000292 30ED <1> xor ch, ch 777 00000294 80E13F <1> and cl, 3Fh ; sectors (bits 0-6) 778 <1> ;mov [bx], cx 779 <1> ;sub bx, drv.spt 780 00000297 D1E3 <1> shl bx, 1 781 00000299 81C3[525C] <1> add bx, drv.size ; disk size (in sectors) 782 <1> ; LBA size = cylinders * heads * secpertrack 783 0000029D F7E1 <1> mul cx 784 0000029F 89C2 <1> mov dx, ax ; heads*spt 785 000002A1 58 <1> pop ax ; ** cylinders 786 <1> ; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads) 787 <1> ;dec ax ; 1 cylinder reserved (!?) ; (*) 788 000002A2 F7E2 <1> mul dx ; cylinders * (heads*spt) 789 000002A4 8907 <1> mov [bx], ax 790 000002A6 895702 <1> mov [bx+2], dx 791 <1> ; 792 <1> ;pop bx 793 000002A9 C3 <1> retn 794 <1> 795 <1> ;align 2 796 <1> 797 <1> ;cylinders : dw 0, 0, 0, 0, 0, 0 798 <1> ;heads : dw 0, 0, 0, 0, 0, 0 799 <1> ;spt : dw 0, 0, 0, 0, 0, 0 800 <1> ;disk_size : dd 0, 0, 0, 0, 0, 0 801 <1> 802 <1> ;last_drv: 803 <1> ; db 0 804 <1> ;drv_status: 805 <1> ; db 0,0,0,0,0,0 806 <1> ; db 0 807 <1> 808 <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015 809 <1> 810 <1> L16: 239 240 ; 10/11/2014 241 000002AA FA cli ; Disable interrupts (clear interrupt flag) 242 ; Reset Interrupt MASK Registers (Master&Slave) 243 ;mov al, 0FFh ; mask off all interrupts 244 ;out 21h, al ; on master PIC (8259) 245 ;jmp $+2 ; (delay) 246 ;out 0A1h, al ; on slave PIC (8259) 247 ; 248 ; Disable NMI 249 000002AB B080 mov al, 80h 250 000002AD E670 out 70h, al ; set bit 7 to 1 for disabling NMI 251 ;23/02/2015 252 000002AF 90 nop ; 253 ;in al, 71h ; read in 71h just after writing out to 70h 254 ; for preventing unknown state (!?) 255 256 ; 02/01/2022 257 %define KERNELFSIZE KEND-KSTART 258 ; 259 ; 20/08/2014 260 ; Moving the kernel 64 KB back (to physical address 0) 261 ; DS = CS = 1000h 262 ; 05/11/2014 263 000002B0 31C0 xor ax, ax 264 000002B2 8EC0 mov es, ax ; ES = 0 265 ; 266 ;;mov cx, (KEND - KLOAD)/4 267 ;mov cx, (KERNELFSIZE+3)/4 ; 02/01/2022 268 000002B4 B95E2F mov cx, (KERNELFSIZE+1)/2 ; 02/01/2022 269 000002B7 31F6 xor si, si 270 000002B9 31FF xor di, di 271 ;rep movsd 272 000002BB F3A5 rep movsw ; 02/01/2022 273 ; 274 000002BD 06 push es ; 0 275 000002BE 68[C202] push L17 276 000002C1 CB retf 277 ; 278 L17: 279 ; Turn off the floppy drive motor 280 000002C2 BAF203 mov dx, 3F2h 281 000002C5 EE out dx, al ; 0 ; 31/12/2013 282 283 ; Enable access to memory above one megabyte 284 L18: 285 000002C6 E464 in al, 64h 286 000002C8 A802 test al, 2 287 000002CA 75FA jnz short L18 288 000002CC B0D1 mov al, 0D1h ; Write output port 289 000002CE E664 out 64h, al 290 L19: 291 000002D0 E464 in al, 64h 292 000002D2 A802 test al, 2 293 000002D4 75FA jnz short L19 294 000002D6 B0DF mov al, 0DFh ; Enable A20 line 295 000002D8 E660 out 60h, al 296 ;L20: 297 ; 298 ; Load global descriptor table register 299 300 ;mov ax, cs 301 ;mov ds, ax 302 303 000002DA 2E0F0116[7059] lgdt [cs:gdtd] 304 305 000002E0 0F20C0 mov eax, cr0 306 ; or eax, 1 307 000002E3 40 inc ax 308 000002E4 0F22C0 mov cr0, eax 309 310 ; Jump to 32 bit code 311 312 000002E7 66 db 66h ; Prefix for 32-bit 313 000002E8 EA db 0EAh ; Opcode for far jump 314 000002E9 [EF020000] dd StartPM ; Offset to start, 32-bit 315 ; (1000h:StartPM = StartPM + 10000h) 316 000002ED 0800 dw KCODE ; This is the selector for CODE32_DESCRIPTOR, 317 ; assuming that StartPM resides in code32 318 319 [BITS 32] 320 321 StartPM: 322 ; Kernel Base Address = 0 ; 30/12/2013 323 000002EF 66B81000 mov ax, KDATA ; Save data segment identifier 324 000002F3 8ED8 mov ds, ax ; Move a valid data segment into DS register 325 000002F5 8EC0 mov es, ax ; Move data segment into ES register 326 000002F7 8EE0 mov fs, ax ; Move data segment into FS register 327 000002F9 8EE8 mov gs, ax ; Move data segment into GS register 328 000002FB 8ED0 mov ss, ax ; Move data segment into SS register 329 000002FD BC00000900 mov esp, 90000h ; Move the stack pointer to 090000h 330 331 clear_bss: ; Clear uninitialized data area 332 ; 11/03/2015 333 00000302 31C0 xor eax, eax ; 0 334 ;mov ecx, (bss_end - bss_start)/4 335 ;;shr ecx, 2 ; bss section is already aligned for double words 336 ; 02/01/2022 337 00000304 B9C1060000 mov ecx, BSS_SIZE/4 338 00000309 BF[C05E0000] mov edi, bss_start 339 0000030E F3AB rep stosd 340 341 memory_init: 342 ; Initialize memory allocation table and page tables 343 ; 344 ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2) 345 ; 16/11/2014 346 ; 15/11/2014 347 ; 07/11/2014 348 ; 06/11/2014 349 ; 05/11/2014 350 ; 04/11/2014 351 ; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 352 ; 353 ; xor eax, eax 354 ; xor ecx, ecx 355 00000310 B108 mov cl, 8 356 00000312 BF00001000 mov edi, MEM_ALLOC_TBL 357 00000317 F3AB rep stosd ; clear Memory Allocation Table 358 ; for the first 1 MB memory 359 ; 360 00000319 8B0D[B45E0000] mov ecx, [mem_1m_1k] ; 02/01/2022 361 ;mov cx, [mem_1m_1k] ; Number of contiguous KB between 362 ; 1 and 16 MB, max. 3C00h = 15 MB. 363 ;shr cx, 2 ; convert 1 KB count to 4 KB count 364 0000031F C1E902 shr ecx, 2 ; 02/01/2022 365 00000322 890D[30610000] mov [free_pages], ecx 366 00000328 8B15[B85E0000] mov edx, [mem_16m_64k] ; 02/01/2022 367 ;mov dx, [mem_16m_64k] ; Number of contiguous 64 KB blocks 368 ; between 16 MB and 4 GB. 369 ;or dx, dx 370 0000032E 09D2 or edx, edx ; 02/01/2022 371 00000330 7412 jz short mi_0 372 ; 373 ;mov ax, dx 374 00000332 89D0 mov eax, edx ; 02/01/2022 375 00000334 C1E004 shl eax, 4 ; 64 KB -> 4 KB (page count) 376 00000337 0105[30610000] add [free_pages], eax 377 0000033D 0500100000 add eax, 4096 ; 16 MB = 4096 pages 378 00000342 EB06 jmp short mi_1 379 mi_0: 380 ;mov ax, cx 381 00000344 89C8 mov eax, ecx ; 02/01/2022 382 00000346 66050001 add ax, 256 ; add 256 pages for the first 1 MB 383 mi_1: 384 0000034A A3[2C610000] mov [memory_size], eax ; Total available memory in pages 385 ; 1 alloc. tbl. bit = 1 memory page 386 ; 32 allocation bits = 32 mem. pages 387 ; 388 0000034F 05FF7F0000 add eax, 32767 ; 32768 memory pages per 1 M.A.T. page 389 00000354 C1E80F shr eax, 15 ; ((32768 * x) + y) pages (y < 32768) 390 ; --> x + 1 M.A.T. pages, if y > 0 391 ; --> x M.A.T. pages, if y = 0 392 ;mov [mat_size], ax ; Memory Alloc. Table Size in pages 393 00000357 A3[40610000] mov [mat_size], eax ; 02/01/2022 394 0000035C C1E00C shl eax, 12 ; 1 M.A.T. page = 4096 bytes 395 ; ; Max. 32 M.A.T. pages (4 GB memory) 396 0000035F 89C3 mov ebx, eax ; M.A.T. size in bytes 397 ; Set/Calculate Kernel's Page Directory Address 398 00000361 81C300001000 add ebx, MEM_ALLOC_TBL 399 00000367 891D[28610000] mov [k_page_dir], ebx ; Kernel's Page Directory address 400 ; just after the last M.A.T. page 401 ; 402 0000036D 83E804 sub eax, 4 ; convert M.A.T. size to offset value 403 00000370 A3[38610000] mov [last_page], eax ; last page ofset in the M.A.T. 404 ; ; (allocation status search must be 405 ; stopped after here) 406 00000375 31C0 xor eax, eax 407 00000377 48 dec eax ; FFFFFFFFh (set all bits to 1) 408 ;push cx 409 00000378 51 push ecx ; 02/01/2022 410 00000379 C1E905 shr ecx, 5 ; convert 1 - 16 MB page count to 411 ; count of 32 allocation bits 412 0000037C F3AB rep stosd 413 ;pop cx 414 0000037E 59 pop ecx ; 02/01/2022 415 0000037F 40 inc eax ; 0 416 00000380 80E11F and cl, 31 ; remain bits 417 00000383 7412 jz short mi_4 418 00000385 8907 mov [edi], eax ; reset 419 mi_2: 420 00000387 0FAB07 bts [edi], eax ; 06/11/2014 421 0000038A FEC9 dec cl 422 0000038C 7404 jz short mi_3 423 0000038E FEC0 inc al 424 00000390 EBF5 jmp short mi_2 425 mi_3: 426 00000392 28C0 sub al, al ; 0 427 00000394 83C704 add edi, 4 ; 15/11/2014 428 mi_4: 429 00000397 09D2 or edx, edx ; 02/01/2022 430 ;or dx, dx ; check 16M to 4G memory space 431 00000399 741F jz short mi_6 ; max. 16 MB memory, no more... 432 ; 433 0000039B B900021000 mov ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory 434 ; 435 000003A0 29F9 sub ecx, edi ; displacement (to end of 16 MB) 436 000003A2 7405 jz short mi_5 ; jump if EDI points to 437 ; end of first 16 MB 438 ;shr ecx, 1 ; convert to dword count 439 ;shr ecx, 1 ; (shift 2 bits right) 440 000003A4 C1E902 shr ecx, 2 ; 02/01/2022 441 000003A7 F3AB rep stosd ; reset all bits for reserved pages 442 ; (memory hole under 16 MB) 443 mi_5: 444 000003A9 89D1 mov ecx, edx ; 02/01/2022 445 ;mov cx, dx ; count of 64 KB memory blocks 446 000003AB D1E9 shr ecx, 1 ; 1 alloc. dword per 128 KB memory 447 000003AD 9C pushf ; 16/11/2014 448 000003AE 48 dec eax ; FFFFFFFFh (set all bits to 1) 449 000003AF F3AB rep stosd 450 000003B1 40 inc eax ; 0 451 000003B2 9D popf ; 16/11/2014 452 000003B3 7305 jnc short mi_6 453 000003B5 6648 dec ax ; eax = 0000FFFFh 454 000003B7 AB stosd 455 000003B8 6640 inc ax ; 0 456 mi_6: 457 000003BA 39DF cmp edi, ebx ; check if EDI points to 458 000003BC 7309 jnb short mi_7 ; end of memory allocation table 459 ; ; (>= MEM_ALLOC_TBL + 4906) 460 000003BE 89D9 mov ecx, ebx ; end of memory allocation table 461 000003C0 29F9 sub ecx, edi ; convert displacement/offset 462 ;shr ecx, 1 ; to dword count 463 ;shr ecx, 1 ; (shift 2 bits right) 464 000003C2 C1E902 shr ecx, 2 ; 02/01/2022 465 000003C5 F3AB rep stosd ; reset all remain M.A.T. bits 466 mi_7: 467 ; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages) 468 000003C7 BA00001000 mov edx, MEM_ALLOC_TBL 469 ;sub ebx, edx ; Mem. Alloc. Tbl. size in bytes 470 ;shr ebx, 12 ; Mem. Alloc. Tbl. size in pages 471 000003CC 8B0D[40610000] mov ecx, [mat_size] ; 02/01/2022 472 ;mov cx, [mat_size] ; Mem. Alloc. Tbl. size in pages 473 000003D2 89D7 mov edi, edx 474 000003D4 C1EF0F shr edi, 15 ; convert M.A.T. address to 475 ; byte offset in M.A.T. 476 ; (1 M.A.T. byte points to 477 ; 32768 bytes) 478 ; Note: MEM_ALLOC_TBL address 479 ; must be aligned on 128 KB 480 ; boundary! 481 000003D7 01D7 add edi, edx ; points to M.A.T.'s itself 482 ; eax = 0 483 000003D9 290D[30610000] sub [free_pages], ecx ; 07/11/2014 484 mi_8: 485 000003DF 0FB307 btr [edi], eax ; clear bit 0 to bit x (1 to 31) 486 ;dec bl 487 000003E2 FEC9 dec cl 488 000003E4 7404 jz short mi_9 489 000003E6 FEC0 inc al 490 000003E8 EBF5 jmp short mi_8 491 mi_9: 492 ; 493 ; Reset Kernel's Page Dir. and Page Table bits in M.A.T. 494 ; (allocate pages for system page tables) 495 496 ; edx = MEM_ALLOC_TBL 497 000003EA 8B0D[2C610000] mov ecx, [memory_size] ; memory size in pages (PTEs) 498 000003F0 81C1FF030000 add ecx, 1023 ; round up (1024 PTEs per table) 499 000003F6 C1E90A shr ecx, 10 ; convert memory page count to 500 ; page table count (PDE count) 501 ; 502 000003F9 51 push ecx ; (**) PDE count (<= 1024) 503 ; 504 000003FA 41 inc ecx ; +1 for kernel page directory 505 ; 506 000003FB 290D[30610000] sub [free_pages], ecx ; 07/11/2014 507 ; 508 00000401 8B35[28610000] mov esi, [k_page_dir] ; Kernel's Page Directory address 509 00000407 C1EE0C shr esi, 12 ; convert to page number 510 mi_10: 511 0000040A 89F0 mov eax, esi ; allocation bit offset 512 0000040C 89C3 mov ebx, eax 513 0000040E C1EB03 shr ebx, 3 ; convert to alloc. byte offset 514 00000411 80E3FC and bl, 0FCh ; clear bit 0 and bit 1 515 ; to align on dword boundary 516 00000414 83E01F and eax, 31 ; set allocation bit position 517 ; (bit 0 to bit 31) 518 ; 519 00000417 01D3 add ebx, edx ; offset in M.A.T. + M.A.T. address 520 ; 521 00000419 0FB303 btr [ebx], eax ; reset relevant bit (0 to 31) 522 ; 523 0000041C 46 inc esi ; next page table 524 0000041D E2EB loop mi_10 ; allocate next kernel page table 525 ; (ecx = page table count + 1) 526 ; 527 0000041F 59 pop ecx ; (**) PDE count (= pg. tbl. count) 528 ; 529 ; Initialize Kernel Page Directory and Kernel Page Tables 530 ; 531 ; Initialize Kernel's Page Directory 532 00000420 8B3D[28610000] mov edi, [k_page_dir] 533 00000426 89F8 mov eax, edi 534 00000428 0C03 or al, PDE_A_PRESENT + PDE_A_WRITE 535 ; supervisor + read&write + present 536 0000042A 89CA mov edx, ecx ; (**) PDE count (= pg. tbl. count) 537 mi_11: 538 0000042C 0500100000 add eax, 4096 ; Add page size (PGSZ) 539 ; EAX points to next page table 540 00000431 AB stosd 541 00000432 E2F8 loop mi_11 542 00000434 29C0 sub eax, eax ; Empty PDE 543 ;mov cx, 1024 ; Entry count (PGSZ/4) 544 ; 02/01/2022 545 00000436 B504 mov ch, 4 ; cx = 4*256 = 1024 546 00000438 29D1 sub ecx, edx 547 0000043A 7402 jz short mi_12 548 0000043C F3AB rep stosd ; clear remain (empty) PDEs 549 ; 550 ; Initialization of Kernel's Page Directory is OK, here. 551 mi_12: 552 ; Initialize Kernel's Page Tables 553 ; 554 ; (EDI points to address of page table 0) 555 ; eax = 0 556 0000043E 8B0D[2C610000] mov ecx, [memory_size] ; memory size in pages 557 00000444 89CA mov edx, ecx ; (***) 558 00000446 B003 mov al, PTE_A_PRESENT + PTE_A_WRITE 559 ; supervisor + read&write + present 560 mi_13: 561 00000448 AB stosd 562 00000449 0500100000 add eax, 4096 563 0000044E E2F8 loop mi_13 564 ; 02/01/2022 565 00000450 66B9FF03 mov cx, 1023 566 00000454 21CA and edx, ecx 567 ;and dx, 1023 ; (***) 568 00000456 7407 jz short mi_14 569 ;mov cx, 1024 570 ; 02/01/2022 571 ;mov ch, 4 ; cx = 4*256 = 1024 572 00000458 41 inc ecx ; ecx = 1024 573 00000459 29D1 sub ecx, edx 574 ;sub cx, dx ; from dx (<= 1023) to 1024 575 0000045B 31C0 xor eax, eax 576 0000045D F3AB rep stosd ; clear remain (empty) PTEs 577 ; of the last page table 578 mi_14: 579 ; Initialization of Kernel's Page Tables is OK, here. 580 ; 581 0000045F 89F8 mov eax, edi ; end of the last page table page 582 ; (beginging of user space pages) 583 00000461 C1E80F shr eax, 15 ; convert to M.A.T. byte offset 584 00000464 24FC and al, 0FCh ; clear bit 0 and bit 1 for 585 ; aligning on dword boundary 586 587 00000466 A3[3C610000] mov [first_page], eax 588 0000046B A3[34610000] mov [next_page], eax ; The first free page pointer 589 ; for user programs 590 ; (Offset in Mem. Alloc. Tbl.) 591 ; 592 ; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here. 593 ; 594 595 ; Enable paging 596 ; 597 00000470 A1[28610000] mov eax, [k_page_dir] 598 00000475 0F22D8 mov cr3, eax 599 00000478 0F20C0 mov eax, cr0 600 0000047B 0D00000080 or eax, 80000000h ; set paging bit (bit 31) 601 00000480 0F22C0 mov cr0, eax 602 ;jmp KCODE:StartPMP 603 604 00000483 EA db 0EAh ; Opcode for far jump 605 00000484 [8A040000] dd StartPMP ; 32 bit offset 606 00000488 0800 dw KCODE ; kernel code segment descriptor 607 608 StartPMP: 609 ; 06/11//2014 610 ; Clear video page 0 611 ; 612 ; Temporary Code 613 ; 614 ;mov ecx, 80*25/2 615 0000048A 66B9E803 mov cx, (80*25)/2 ; 02/01/2022 616 0000048E BF00800B00 mov edi, 0B8000h 617 00000493 57 push edi ; * ; 02/01/2022 618 00000494 31C0 xor eax, eax ; black background, black fore color 619 00000496 F3AB rep stosd 620 621 ; 19/08/2014 622 ; Kernel Base Address = 0 623 ; It is mapped to (physically) 0 in the page table. 624 ; So, here is exactly 'StartPMP' address. 625 ; 626 ;;mov ah, 4Eh ; Red background, yellow forecolor 627 ;;mov esi, msgPM 628 ;; 14/08/2015 (kernel version message will appear 629 ;; when protected mode and paging is enabled) 630 00000498 B40B mov ah, 0Bh ; Black background, light cyan forecolor 631 0000049A BE[845C0000] mov esi, msgKVER 632 0000049F 5F pop edi ; * ; 02/01/2022 633 ;mov edi, 0B8000h ; 27/08/2014 634 ; 20/08/2014 635 000004A0 E891010000 call printk 636 637 ; 'UNIX v7/x86' source code by Robert Nordier (1999) 638 ; // Set IRQ offsets 639 ; 640 ; Linux (v0.12) source code by Linus Torvalds (1991) 641 ; 642 ;; ICW1 643 000004A5 B011 mov al, 11h ; Initialization sequence 644 000004A7 E620 out 20h, al ; 8259A-1 645 ; jmp $+2 646 000004A9 E6A0 out 0A0h, al ; 8259A-2 647 ;; ICW2 648 000004AB B020 mov al, 20h ; Start of hardware ints (20h) 649 000004AD E621 out 21h, al ; for 8259A-1 650 ; jmp $+2 651 000004AF B028 mov al, 28h ; Start of hardware ints (28h) 652 000004B1 E6A1 out 0A1h, al ; for 8259A-2 653 ; 654 000004B3 B004 mov al, 04h ;; ICW3 655 000004B5 E621 out 21h, al ; IRQ2 of 8259A-1 (master) 656 ; jmp $+2 657 000004B7 B002 mov al, 02h ; is 8259A-2 (slave) 658 000004B9 E6A1 out 0A1h, al ; 659 ;; ICW4 660 000004BB B001 mov al, 01h ; 661 000004BD E621 out 21h, al ; 8086 mode, normal EOI 662 ; jmp $+2 663 000004BF E6A1 out 0A1h, al ; for both chips. 664 665 ;mov al, 0FFh ; mask off all interrupts for now 666 ;out 21h, al 667 ;; jmp $+2 668 ;out 0A1h, al 669 670 ; 02/04/2015 671 ; 26/03/2015 System call (INT 30h) modification 672 ; DPL = 3 (Interrupt service routine can be called from user mode) 673 ; 674 ;; Linux (v0.12) source code by Linus Torvalds (1991) 675 ; setup_idt: 676 ; 677 ;; 16/02/2015 678 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 679 ; 21/08/2014 (timer_int) 680 000004C1 BE[7C590000] mov esi, ilist 681 000004C6 8D3D[C05E0000] lea edi, [idt] 682 ; 26/03/2015 683 000004CC B930000000 mov ecx, 48 ; 48 hardware interrupts (INT 0 to INT 2Fh) 684 ; 02/04/2015 685 000004D1 BB00000800 mov ebx, 80000h 686 rp_sidt1: 687 000004D6 AD lodsd 688 000004D7 89C2 mov edx, eax 689 000004D9 66BA008E mov dx, 8E00h 690 000004DD 6689C3 mov bx, ax 691 000004E0 89D8 mov eax, ebx ; /* selector = 0x0008 = cs */ 692 ; /* interrupt gate - dpl=0, present */ 693 000004E2 AB stosd ; selector & offset bits 0-15 694 000004E3 89D0 mov eax, edx 695 000004E5 AB stosd ; attributes & offset bits 16-23 696 000004E6 E2EE loop rp_sidt1 697 000004E8 B110 mov cl, 16 ; 16 software interrupts (INT 30h to INT 3Fh) 698 rp_sidt2: 699 000004EA AD lodsd 700 000004EB 21C0 and eax, eax 701 000004ED 7413 jz short rp_sidt3 702 000004EF 89C2 mov edx, eax 703 000004F1 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 704 000004F5 6689C3 mov bx, ax 705 000004F8 89D8 mov eax, ebx ; selector & offset bits 0-15 706 000004FA AB stosd 707 000004FB 89D0 mov eax, edx 708 000004FD AB stosd 709 000004FE E2EA loop rp_sidt2 710 00000500 EB16 jmp short sidt_OK 711 rp_sidt3: 712 00000502 B8[5A090000] mov eax, ignore_int 713 00000507 89C2 mov edx, eax 714 00000509 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 715 0000050D 6689C3 mov bx, ax 716 00000510 89D8 mov eax, ebx ; selector & offset bits 0-15 717 rp_sidt4: 718 00000512 AB stosd 719 00000513 92 xchg eax, edx 720 00000514 AB stosd 721 00000515 92 xchg edx, eax 722 00000516 E2FA loop rp_sidt4 723 sidt_OK: 724 00000518 0F011D[76590000] lidt [idtd] 725 ; 726 ; TSS descriptor setup ; 24/03/2015 727 0000051F B8[C0600000] mov eax, task_state_segment 728 00000524 66A3[6A590000] mov [gdt_tss0], ax 729 0000052A C1C010 rol eax, 16 730 0000052D A2[6C590000] mov [gdt_tss1], al 731 00000532 8825[6F590000] mov [gdt_tss2], ah 732 00000538 66C705[26610000]68- mov word [tss.IOPB], tss_end - task_state_segment 732 00000540 00 733 ; 734 ; IO Map Base address (When this address points 735 ; to end of the TSS, CPU does not use IO port 736 ; permission bit map for RING 3 IO permissions, 737 ; access to any IO ports in ring 3 will be forbidden.) 738 ; 739 ;mov [tss.esp0], esp ; TSS offset 4 740 ;mov word [tss.ss0], KDATA ; TSS offset 8 (SS) 741 00000541 66B82800 mov ax, TSS ; It is needed when an interrupt 742 ; occurs (or a system call -software INT- is requested) 743 ; while cpu running in ring 3 (in user mode). 744 ; (Kernel stack pointer and segment will be loaded 745 ; from offset 4 and 8 of the TSS, by the CPU.) 746 00000545 0F00D8 ltr ax ; Load task register 747 ; 748 esp0_set0: 749 ; 30/07/2015 750 00000548 8B0D[2C610000] mov ecx, [memory_size] ; memory size in pages 751 0000054E C1E10C shl ecx, 12 ; convert page count to byte count 752 00000551 81F900004000 cmp ecx, CORE ; beginning of user's memory space (400000h) 753 ; (kernel mode virtual address) 754 00000557 7605 jna short esp0_set1 755 ; 756 ; If available memory > CORE (end of the 1st 4 MB) 757 ; set stack pointer to CORE 758 ;(Because, PDE 0 is reserved for kernel space in user's page directory) 759 ;(PDE 0 points to page table of the 1st 4 MB virtual address space) 760 00000559 B900004000 mov ecx, CORE 761 esp0_set1: 762 0000055E 89CC mov esp, ecx ; top of kernel stack (**tss.esp0**) 763 esp0_set_ok: 764 ; 30/07/2015 (**tss.esp0**) 765 00000560 8925[C4600000] mov [tss.esp0], esp 766 00000566 66C705[C8600000]10- mov word [tss.ss0], KDATA 766 0000056E 00 767 ; 14/08/2015 768 ; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan) 769 ; 770 ;cli ; Disable interrupts (for CPU) 771 ; (CPU will not handle hardware interrupts, except NMI!) 772 ; 773 0000056F 30C0 xor al, al ; Enable all hardware interrupts! 774 00000571 E621 out 21h, al ; (IBM PC-AT compatibility) 775 00000573 EB00 jmp $+2 ; (All conventional PC-AT hardware 776 00000575 E6A1 out 0A1h, al ; interrupts will be in use.) 777 ; (Even if related hardware component 778 ; does not exist!) 779 ; Enable NMI 780 00000577 B07F mov al, 7Fh ; Clear bit 7 to enable NMI (again) 781 00000579 E670 out 70h, al 782 ; 23/02/2015 783 0000057B 90 nop 784 0000057C E471 in al, 71h ; read in 71h just after writing out to 70h 785 ; for preventing unknown state (!?) 786 ; 787 ; Only a NMI can occur here... (Before a 'STI' instruction) 788 ; 789 ; 02/09/2014 790 ;xor bx, bx 791 ;mov dx, 0200h ; Row 2, column 0 ; 07/03/2015 792 ; 27/02/2022 793 0000057E 31DB xor ebx, ebx 794 00000580 31D2 xor edx, edx 795 00000582 B602 mov dh, 2 796 00000584 E81D0E0000 call set_cpos 797 ; 798 ; 06/11/2014 799 ; Temporary Code 800 ; 801 00000589 E8920F0000 call memory_info 802 ; 14/08/2015 803 ;call getch ; 28/02/2015 804 drv_init: 805 0000058E FB sti ; Enable Interrupts 806 ; 06/02/2015 807 0000058F 8B15[4E5C0000] mov edx, [hd0_type] ; hd0, hd1, hd2, hd3 808 00000595 668B1D[4C5C0000] mov bx, [fd0_type] ; fd0, fd1 809 ; 22/02/2015 810 0000059C 6621DB and bx, bx 811 0000059F 751B jnz short di1 812 ; 813 000005A1 09D2 or edx, edx 814 000005A3 7529 jnz short di2 815 ; 816 setup_error: 817 000005A5 BE[6D5D0000] mov esi, setup_error_msg 818 psem: 819 000005AA AC lodsb 820 000005AB 08C0 or al, al 821 ;jz short haltx ; 22/02/2015 822 000005AD 7426 jz short di3 823 000005AF 56 push esi 824 000005B0 31DB xor ebx, ebx ; 0 825 ; Video page 0 (bl=0) 826 000005B2 B407 mov ah, 07h ; Black background, 827 ; light gray forecolor 828 000005B4 E8E30C0000 call write_tty 829 000005B9 5E pop esi 830 000005BA EBEE jmp short psem 831 832 di1: 833 ; supress 'jmp short T6' 834 ; (activate fdc motor control code) 835 000005BC 66C705[B7060000]90- mov word [T5], 9090h ; nop 835 000005C4 90 836 ; 837 ;mov ax, int_0Eh ; IRQ 6 handler 838 ;mov di, 0Eh*4 ; IRQ 6 vector 839 ;stosw 840 ;mov ax, cs 841 ;stosw 842 ;; 16/02/2015 843 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 844 ; 845 000005C5 E8FC180000 CALL DSKETTE_SETUP ; Initialize Floppy Disks 846 ; 847 000005CA 09D2 or edx, edx 848 000005CC 7407 jz short di3 849 di2: 850 000005CE E825190000 call DISK_SETUP ; Initialize Fixed Disks 851 000005D3 72D0 jc short setup_error 852 di3: 853 000005D5 E81A0F0000 call setup_rtc_int ; 22/05/2015 (dsectrpm.s) 854 ; 855 000005DA E8BA520000 call display_disks ; 07/03/2015 (Temporary) 856 ;haltx: 857 ; 14/08/2015 858 ;call getch ; 22/02/2015 859 000005DF FB sti ; Enable interrupts (for CPU) 860 ; 14/08/2015 861 ;mov ecx, 0FFFFFFFh 862 ; 24/12/2021 863 000005E0 B9FFFF2F00 mov ecx, 02FFFFFh 864 md_info_msg_wait: 865 000005E5 51 push ecx 866 000005E6 B001 mov al, 1 867 000005E8 8A25[56610000] mov ah, [ptty] ; active (current) video page 868 000005EE E8914F0000 call getc_n 869 000005F3 59 pop ecx 870 000005F4 7502 jnz short md_info_msg_ok 871 000005F6 E2ED loop md_info_msg_wait 872 md_info_msg_ok: 873 ; 30/06/2015 874 000005F8 E8B9220000 call sys_init 875 ; 876 ;jmp cpu_reset ; 22/02/2015 877 hang: 878 ; 24/12/2021 879 000005FD 29C0 sub eax, eax 880 _hang: 881 ; 23/02/2015 882 ;sti ; Enable interrupts 883 000005FF F4 hlt 884 ; 885 ;nop 886 ;; 03/12/2014 887 ;; 28/08/2014 888 ;mov ah, 11h 889 ;call getc 890 ;jz _c8 891 ; 892 ; 23/02/2015 893 ; 06/02/2015 894 ; 07/09/2014 895 00000600 31DB xor ebx, ebx 896 00000602 8A1D[56610000] mov bl, [ptty] ; active_page 897 00000608 89DE mov esi, ebx 898 ;shl si, 1 899 ; 17/07/2022 900 0000060A D1E6 shl esi, 1 901 0000060C 81C6[58610000] add esi, ttychr 902 00000612 668B06 mov ax, [esi] 903 ;and ax, ax 904 ;;jz short _c8 905 ;jz short hang 906 ; 24/12/2021 907 00000615 21C0 and eax, eax 908 00000617 74E6 jz short _hang 909 00000619 66C7060000 mov word [esi], 0 910 0000061E 80FB03 cmp bl, 3 ; Video page 3 911 ;jb short _c8 912 00000621 72DA jb short hang 913 ; 914 ; 02/09/2014 915 00000623 B40E mov ah, 0Eh ; Yellow character 916 ; on black background 917 ; 24/12/2021 (32 bit reg push-pop) 918 ; 07/09/2014 919 nxtl: 920 00000625 53 push ebx 921 ; 922 ;xor ebx, ebx ; bl = 0 (video page 0) 923 ; bh = 0 (video mode) 924 ; Retro UNIX 386 v1 - Video Mode 0 925 ; (PC/AT Video Mode 3 - 80x25 Alpha.) 926 00000626 50 push eax 927 00000627 E8700C0000 call write_tty 928 0000062C 58 pop eax 929 ;pop bx 930 0000062D 5B pop ebx 931 0000062E 3C0D cmp al, 0Dh ; carriage return (enter) 932 ;jne short _c8 933 00000630 75CB jne short hang 934 00000632 B00A mov al, 0Ah ; next line 935 00000634 EBEF jmp short nxtl 936 937 ;_c8: 938 ; ; 25/08/2014 939 ; cli ; Disable interrupts 940 ; mov al, [scounter + 1] 941 ; and al, al 942 ; jnz hang 943 ; call rtc_p 944 ; jmp hang 945 946 947 ; 27/08/2014 948 ; 20/08/2014 949 printk: 950 ;mov edi, [scr_row] 951 pkl: 952 00000636 AC lodsb 953 00000637 08C0 or al, al 954 00000639 7404 jz short pkr 955 0000063B 66AB stosw 956 0000063D EBF7 jmp short pkl 957 pkr: 958 0000063F C3 retn 959 960 ; 25/07/2015 961 ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer) 962 ; 17/02/2015 963 ; 06/02/2015 (unix386.s) 964 ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 965 ; 966 ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85) 967 ; 968 ;-- HARDWARE INT 08 H - ( IRQ LEVEL 0 ) --------------------------------------- 969 ; THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF : 970 ; THE 8254 TIMER. INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR : 971 ; IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND. : 972 ; : 973 ; THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE : 974 ; POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY. : 975 ; THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40) : 976 ; OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE : 977 ; DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS. : 978 ; THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH : 979 ; INTERRUPT 1CH AT EVERY TIME TICK. THE USER MUST CODE A : 980 ; ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE. : 981 ;------------------------------------------------------------------------------- 982 ; 983 984 timer_int: ; IRQ 0 985 ;int_08h: ; Timer 986 ; 14/10/2015 987 ; Here, we are simulating system call entry (for task switch) 988 ; (If multitasking is enabled, 989 ; 'clock' procedure may jump to 'sysrelease') 990 00000640 1E push ds 991 00000641 06 push es 992 00000642 0FA0 push fs 993 00000644 0FA8 push gs 994 00000646 60 pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 995 00000647 66B91000 mov cx, KDATA 996 0000064B 8ED9 mov ds, cx 997 0000064D 8EC1 mov es, cx 998 0000064F 8EE1 mov fs, cx 999 00000651 8EE9 mov gs, cx 1000 ; 1001 00000653 0F20D9 mov ecx, cr3 1002 00000656 890D[F9060000] mov [cr3reg], ecx ; save current cr3 register value/content 1003 ; 1004 0000065C 3B0D[28610000] cmp ecx, [k_page_dir] 1005 00000662 741F je short T3 1006 ; 1007 ; timer interrupt has been occurred while OS is in user mode 1008 00000664 A3[EC640000] mov [u.r0], eax 1009 00000669 89E1 mov ecx, esp 1010 0000066B 83C130 add ecx, ESPACE ; 4 * 12 (stack frame) 1011 0000066E 890D[E4640000] mov [u.sp], ecx ; kernel stack pointer at the start of interrupt 1012 00000674 8925[E8640000] mov [u.usp], esp ; kernel stack points to user's registers 1013 ; 1014 0000067A 8B0D[28610000] mov ecx, [k_page_dir] 1015 00000680 0F22D9 mov cr3, ecx 1016 T3: 1017 00000683 FB sti ; INTERRUPTS BACK ON 1018 00000684 66FF05[A4610000] INC word [TIMER_LOW] ; INCREMENT TIME 1019 0000068B 7507 JNZ short T4 ; GO TO TEST_DAY 1020 0000068D 66FF05[A6610000] INC word [TIMER_HIGH] ; INCREMENT HIGH WORD OF TIME 1021 T4: ; TEST_DAY 1022 00000694 66833D[A6610000]18 CMP word [TIMER_HIGH],018H ; TEST FOR COUNT EQUALING 24 HOURS 1023 0000069C 7519 JNZ short T5 ; GO TO DISKETTE_CTL 1024 0000069E 66813D[A4610000]B0- CMP word [TIMER_LOW],0B0H 1024 000006A6 00 1025 000006A7 750E JNZ short T5 ; GO TO DISKETTE_CTL 1026 1027 ;----- TIMER HAS GONE 24 HOURS 1028 ;;SUB AX,AX 1029 ;MOV [TIMER_HIGH],AX 1030 ;MOV [TIMER_LOW],AX 1031 000006A9 29C0 sub eax, eax 1032 000006AB A3[A4610000] mov [TIMER_LH], eax 1033 ; 1034 000006B0 C605[A8610000]01 MOV byte [TIMER_OFL],1 1035 1036 ;----- TEST FOR DISKETTE TIME OUT 1037 1038 T5: 1039 ; 23/12/2014 1040 000006B7 EB1D jmp short T6 ; will be replaced with nop, nop 1041 ; (9090h) if a floppy disk 1042 ; is detected. 1043 ;mov al,[CS:MOTOR_COUNT] 1044 000006B9 A0[AB610000] mov al, [MOTOR_COUNT] 1045 000006BE FEC8 dec al 1046 ;mov [CS:MOTOR_COUNT], al ; DECREMENT DISKETTE MOTOR CONTROL 1047 000006C0 A2[AB610000] mov [MOTOR_COUNT], al 1048 ;mov [ORG_MOTOR_COUNT], al 1049 000006C5 750F JNZ short T6 ; RETURN IF COUNT NOT OUT 1050 000006C7 B0F0 mov al,0F0h 1051 ;AND [CS:MOTOR_STATUS],al ; TURN OFF MOTOR RUNNING BITS 1052 000006C9 2005[AA610000] and [MOTOR_STATUS], al 1053 ;and [ORG_MOTOR_STATUS], al 1054 000006CF B00C MOV AL,0CH ; bit 3 = enable IRQ & DMA, 1055 ; bit 2 = enable controller 1056 ; 1 = normal operation 1057 ; 0 = reset 1058 ; bit 0, 1 = drive select 1059 ; bit 4-7 = motor running bits 1060 000006D1 66BAF203 MOV DX,03F2H ; FDC CTL PORT 1061 000006D5 EE OUT DX,AL ; TURN OFF THE MOTOR 1062 T6: 1063 ;inc word [CS:wait_count] ; 22/12/2014 (byte -> word) 1064 ; TIMER TICK INTERRUPT 1065 ;;inc word [wait_count] ;;27/02/2015 1066 ;INT 1CH ; TRANSFER CONTROL TO A USER ROUTINE 1067 ;;;;cli 1068 ;call u_timer ; TRANSFER CONTROL TO A USER ROUTINE 1069 000006D6 FF15[F1060000] call [x_timer] ; 14/05/2015 1070 T7: 1071 ; 14/10/2015 1072 000006DC B020 MOV AL,EOI ; GET END OF INTERRUPT MASK 1073 000006DE FA CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 1074 000006DF E620 OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 1075 ; 1076 000006E1 A1[F9060000] mov eax, [cr3reg] ; previous value/content of cr3 register 1077 000006E6 0F22D8 mov cr3, eax ; restore cr3 register content 1078 ; 1079 000006E9 61 popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 1080 ; 1081 000006EA 0FA9 pop gs 1082 000006EC 0FA1 pop fs 1083 000006EE 07 pop es 1084 000006EF 1F pop ds 1085 000006F0 CF iretd ; return from interrupt 1086 1087 1088 ; //////////////// 1089 1090 ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt) 1091 x_timer: 1092 000006F1 [FD060000] dd u_timer ; 14/05/2015 1093 ;dd clock 1094 1095 ; 26/02/2022 - Real time clock (digital) output demo (sys emt) 1096 x_rtci: 1097 000006F5 [330A0000] dd rtc_p ; (temporary demo code) ; 26/02/2022 1098 1099 ; 14/10/2015 1100 000006F9 00000000 cr3reg: dd 0 1101 1102 ; 24/12/2021 - Retro UNIX 386 v1.1 1103 ; 06/02/2015 1104 ; 07/09/2014 1105 ; 21/08/2014 1106 u_timer: 1107 ;timer_int: ; IRQ 0 1108 ; 06/02/2015 1109 ;push eax 1110 ;push edx 1111 ;push ecx 1112 ;push ebx 1113 ;push ds 1114 ;push es 1115 ;mov eax, KDATA 1116 ;mov ds, ax 1117 ;mov es, ax 1118 000006FD FF05[6C610000] inc dword [tcount] 1119 00000703 BB[F65C0000] mov ebx, tcountstr + 4 1120 ;mov ax, [tcount] 1121 ; 24/12/2021 1122 00000708 A1[6C610000] mov eax, [tcount] 1123 0000070D B90A000000 mov ecx, 10 1124 rp_divtcnt: 1125 00000712 31D2 xor edx, edx 1126 00000714 F7F1 div ecx 1127 00000716 80C230 add dl, 30h 1128 00000719 8813 mov [ebx], dl 1129 ;or ax, ax 1130 ; 24/12/2021 1131 0000071B 09C0 or eax, eax 1132 0000071D 7403 jz short print_lzero 1133 0000071F 4B dec ebx 1134 00000720 EBF0 jmp short rp_divtcnt 1135 print_lzero: 1136 00000722 81FB[F25C0000] cmp ebx, tcountstr 1137 00000728 7606 jna short print_tcount 1138 0000072A 4B dec ebx 1139 0000072B C60330 mov byte [ebx], 30h 1140 0000072E EBF2 jmp short print_lzero 1141 print_tcount: 1142 00000730 56 push esi 1143 00000731 57 push edi 1144 00000732 BE[CE5C0000] mov esi, timer_msg ; Timer interrupt message 1145 ; 07/09/2014 1146 ;mov bx, 1 ; Video page 1 1147 ; 24/12/2021 1148 00000737 29DB sub ebx, ebx 1149 ;inc bl ; ebx = 1 1150 ; 02/01/2022 1151 00000739 B306 mov bl, 6 ; Video page 6 1152 ptmsg: 1153 0000073B AC lodsb 1154 0000073C 08C0 or al, al 1155 0000073E 740D jz short ptmsg_ok 1156 00000740 56 push esi 1157 ;push bx 1158 ; 24/12/2021 1159 00000741 53 push ebx 1160 00000742 B42F mov ah, 2Fh ; Green background, white forecolor 1161 00000744 E8530B0000 call write_tty 1162 ;pop bx 1163 ; 24/12/2021 1164 00000749 5B pop ebx 1165 0000074A 5E pop esi 1166 0000074B EBEE jmp short ptmsg 1167 ;; 27/08/2014 1168 ;mov edi, 0B8000h + 0A0h ; Row 1 1169 ;call printk 1170 ; 1171 ptmsg_ok: 1172 ; 07/09/2014 1173 ;xor dx, dx ; column 0, row 0 1174 ; 24/12/2021 1175 0000074D 31D2 xor edx, edx 1176 0000074F E8520C0000 call set_cpos ; set cursor position to 0,0 1177 ; 23/02/2015 1178 ; 25/08/2014 1179 ;mov ebx, scounter ; (seconds counter) 1180 ;dec byte [ebx+1] ; (for reading real time clock) 1181 ; dec byte [scounter+1] 1182 ;; jns short timer_eoi ; 0 -> 0FFh ? 1183 ; jns short u_timer_retn 1184 ; 26/02/2015 1185 ; call rtc_p 1186 ; mov ebx, scounter ; (seconds counter) 1187 ; mov byte [ebx+1], 18 ; (18.2 timer ticks per second) 1188 ; dec byte [ebx] ; 19+18+18+18+18 (5) 1189 ; jnz short timer_eoi ; (109 timer ticks in 5 seconds) 1190 ; jnz short u_timer_retn ; 06/02/2015 1191 ; mov byte [ebx], 5 1192 ; inc byte [ebx+1] ; 19 1193 ;;timer_eoi: 1194 ;; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1195 ;; out 20h, al ; 8259 PORT 1196 ; 1197 ;u_timer_retn: ; 06/02/2015 1198 00000754 5F pop edi 1199 00000755 5E pop esi 1200 ;pop es 1201 ;pop ds 1202 ;pop ebx 1203 ;pop ecx 1204 ;pop edx 1205 ;pop eax 1206 ;iret 1207 00000756 C3 retn ; 06/02/2015 1208 1209 ; 28/08/2014 1210 irq0: 1211 00000757 6A00 push dword 0 1212 00000759 EB48 jmp short which_irq 1213 irq1: 1214 0000075B 6A01 push dword 1 1215 0000075D EB44 jmp short which_irq 1216 irq2: 1217 0000075F 6A02 push dword 2 1218 00000761 EB40 jmp short which_irq 1219 irq3: 1220 ; 20/11/2015 1221 ; 24/10/2015 1222 00000763 2EFF15[CE2F0000] call dword [cs:com2_irq3] 1223 0000076A 6A03 push dword 3 1224 0000076C EB35 jmp short which_irq 1225 irq4: 1226 ; 20/11/2015 1227 ; 24/10/2015 1228 0000076E 2EFF15[CA2F0000] call dword [cs:com1_irq4] 1229 00000775 6A04 push dword 4 1230 00000777 EB2A jmp short which_irq 1231 irq5: 1232 00000779 6A05 push dword 5 1233 0000077B EB26 jmp short which_irq 1234 irq6: 1235 0000077D 6A06 push dword 6 1236 0000077F EB22 jmp short which_irq 1237 irq7: 1238 00000781 6A07 push dword 7 1239 00000783 EB1E jmp short which_irq 1240 irq8: 1241 00000785 6A08 push dword 8 1242 00000787 EB1A jmp short which_irq 1243 irq9: 1244 00000789 6A09 push dword 9 1245 0000078B EB16 jmp short which_irq 1246 irq10: 1247 0000078D 6A0A push dword 10 1248 0000078F EB12 jmp short which_irq 1249 irq11: 1250 00000791 6A0B push dword 11 1251 00000793 EB0E jmp short which_irq 1252 irq12: 1253 00000795 6A0C push dword 12 1254 00000797 EB0A jmp short which_irq 1255 irq13: 1256 00000799 6A0D push dword 13 1257 0000079B EB06 jmp short which_irq 1258 irq14: 1259 0000079D 6A0E push dword 14 1260 0000079F EB02 jmp short which_irq 1261 irq15: 1262 000007A1 6A0F push dword 15 1263 ;jmp short which_irq 1264 1265 ; 19/10/2015 1266 ; 29/08/2014 1267 ; 21/08/2014 1268 which_irq: 1269 000007A3 870424 xchg eax, [esp] ; 28/08/2014 1270 000007A6 53 push ebx 1271 000007A7 56 push esi 1272 000007A8 57 push edi 1273 000007A9 1E push ds 1274 000007AA 06 push es 1275 ; 1276 000007AB 88C3 mov bl, al 1277 ; 1278 000007AD B810000000 mov eax, KDATA 1279 000007B2 8ED8 mov ds, ax 1280 000007B4 8EC0 mov es, ax 1281 ; 19/10/2015 1282 000007B6 FC cld 1283 ; 27/08/2014 1284 000007B7 8105[7C5C0000]A000- add dword [scr_row], 0A0h 1284 000007BF 0000 1285 ; 1286 000007C1 B417 mov ah, 17h ; blue (1) background, 1287 ; light gray (7) forecolor 1288 000007C3 8B3D[7C5C0000] mov edi, [scr_row] 1289 000007C9 B049 mov al, 'I' 1290 000007CB 66AB stosw 1291 000007CD B052 mov al, 'R' 1292 000007CF 66AB stosw 1293 000007D1 B051 mov al, 'Q' 1294 000007D3 66AB stosw 1295 000007D5 B020 mov al, ' ' 1296 000007D7 66AB stosw 1297 000007D9 88D8 mov al, bl 1298 000007DB 3C0A cmp al, 10 1299 000007DD 7208 jb short iix 1300 000007DF B031 mov al, '1' 1301 000007E1 66AB stosw 1302 000007E3 88D8 mov al, bl 1303 000007E5 2C0A sub al, 10 1304 iix: 1305 000007E7 0430 add al, '0' 1306 000007E9 66AB stosw 1307 000007EB B020 mov al, ' ' 1308 000007ED 66AB stosw 1309 000007EF B021 mov al, '!' 1310 000007F1 66AB stosw 1311 000007F3 B020 mov al, ' ' 1312 000007F5 66AB stosw 1313 ; 23/02/2015 1314 000007F7 80FB07 cmp bl, 7 ; check for IRQ 8 to IRQ 15 1315 ;jna iiret 1316 ; 02/01/2022 1317 000007FA 7604 jna short iiz 1318 iiy: 1319 000007FC B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1320 000007FE E6A0 out 0A0h, al ; the 2nd 8259 1321 iiz: 1322 00000800 E983010000 jmp iiret 1323 ; 1324 ; 22/08/2014 1325 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1326 ;out 20h, al ; 8259 PORT 1327 ; 1328 ;pop es 1329 ;pop ds 1330 ;pop edi 1331 ;pop esi 1332 ;pop ebx 1333 ;pop eax 1334 ;iret 1335 1336 ; 02/04/2015 1337 ; 25/08/2014 1338 exc0: 1339 00000805 6A00 push dword 0 1340 00000807 E990000000 jmp cpu_except 1341 exc1: 1342 0000080C 6A01 push dword 1 1343 0000080E E989000000 jmp cpu_except 1344 exc2: 1345 00000813 6A02 push dword 2 1346 00000815 E982000000 jmp cpu_except 1347 exc3: 1348 0000081A 6A03 push dword 3 1349 0000081C EB7E jmp cpu_except 1350 exc4: 1351 0000081E 6A04 push dword 4 1352 00000820 EB7A jmp cpu_except 1353 exc5: 1354 00000822 6A05 push dword 5 1355 00000824 EB76 jmp cpu_except 1356 exc6: 1357 00000826 6A06 push dword 6 1358 00000828 EB72 jmp cpu_except 1359 exc7: 1360 0000082A 6A07 push dword 7 1361 0000082C EB6E jmp cpu_except 1362 exc8: 1363 ; [esp] = Error code 1364 0000082E 6A08 push dword 8 1365 00000830 EB5C jmp cpu_except_en 1366 exc9: 1367 00000832 6A09 push dword 9 1368 00000834 EB66 jmp cpu_except 1369 exc10: 1370 ; [esp] = Error code 1371 00000836 6A0A push dword 10 1372 00000838 EB54 jmp cpu_except_en 1373 exc11: 1374 ; [esp] = Error code 1375 0000083A 6A0B push dword 11 1376 0000083C EB50 jmp cpu_except_en 1377 exc12: 1378 ; [esp] = Error code 1379 0000083E 6A0C push dword 12 1380 00000840 EB4C jmp cpu_except_en 1381 exc13: 1382 ; [esp] = Error code 1383 00000842 6A0D push dword 13 1384 00000844 EB48 jmp cpu_except_en 1385 exc14: 1386 ; [esp] = Error code 1387 00000846 6A0E push dword 14 1388 00000848 EB44 jmp short cpu_except_en 1389 exc15: 1390 0000084A 6A0F push dword 15 1391 0000084C EB4E jmp cpu_except 1392 exc16: 1393 0000084E 6A10 push dword 16 1394 00000850 EB4A jmp cpu_except 1395 exc17: 1396 ; [esp] = Error code 1397 00000852 6A11 push dword 17 1398 00000854 EB38 jmp short cpu_except_en 1399 exc18: 1400 00000856 6A12 push dword 18 1401 00000858 EB42 jmp short cpu_except 1402 exc19: 1403 0000085A 6A13 push dword 19 1404 0000085C EB3E jmp short cpu_except 1405 exc20: 1406 0000085E 6A14 push dword 20 1407 00000860 EB3A jmp short cpu_except 1408 exc21: 1409 00000862 6A15 push dword 21 1410 00000864 EB36 jmp short cpu_except 1411 exc22: 1412 00000866 6A16 push dword 22 1413 00000868 EB32 jmp short cpu_except 1414 exc23: 1415 0000086A 6A17 push dword 23 1416 0000086C EB2E jmp short cpu_except 1417 exc24: 1418 0000086E 6A18 push dword 24 1419 00000870 EB2A jmp short cpu_except 1420 exc25: 1421 00000872 6A19 push dword 25 1422 00000874 EB26 jmp short cpu_except 1423 exc26: 1424 00000876 6A1A push dword 26 1425 00000878 EB22 jmp short cpu_except 1426 exc27: 1427 0000087A 6A1B push dword 27 1428 0000087C EB1E jmp short cpu_except 1429 exc28: 1430 0000087E 6A1C push dword 28 1431 00000880 EB1A jmp short cpu_except 1432 exc29: 1433 00000882 6A1D push dword 29 1434 00000884 EB16 jmp short cpu_except 1435 exc30: 1436 00000886 6A1E push dword 30 1437 00000888 EB04 jmp short cpu_except_en 1438 exc31: 1439 0000088A 6A1F push dword 31 1440 0000088C EB0E jmp short cpu_except 1441 1442 ; 02/01/2022 1443 ; 19/10/2015 1444 ; 19/09/2015 1445 ; 01/09/2015 1446 ; 28/08/2015 1447 ; 28/08/2014 1448 cpu_except_en: 1449 0000088E 87442404 xchg eax, [esp+4] ; Error code 1450 00000892 36A3[D4610000] mov [ss:error_code], eax 1451 00000898 58 pop eax ; Exception number 1452 00000899 870424 xchg eax, [esp] 1453 ; eax = eax before exception 1454 ; [esp] -> exception number 1455 ; [esp+4] -> EIP to return 1456 ; 19/10/2015 1457 ; 19/09/2015 1458 ; 01/09/2015 1459 ; 28/08/2015 1460 ; 29/08/2014 1461 ; 28/08/2014 1462 ; 25/08/2014 1463 ; 21/08/2014 1464 cpu_except: ; CPU Exceptions 1465 0000089C FC cld 1466 0000089D 870424 xchg eax, [esp] 1467 ; eax = Exception number 1468 ; [esp] = eax (before exception) 1469 000008A0 53 push ebx 1470 000008A1 56 push esi 1471 000008A2 57 push edi 1472 000008A3 1E push ds 1473 000008A4 06 push es 1474 ; 28/08/2015 1475 000008A5 66BB1000 mov bx, KDATA 1476 000008A9 8EDB mov ds, bx 1477 000008AB 8EC3 mov es, bx 1478 000008AD 0F20DB mov ebx, cr3 1479 000008B0 53 push ebx ; (*) page directory 1480 ; 19/10/2015 1481 000008B1 FC cld 1482 ; 25/03/2015 1483 000008B2 8B1D[28610000] mov ebx, [k_page_dir] 1484 000008B8 0F22DB mov cr3, ebx 1485 ; 28/08/2015 1486 000008BB 83F80E cmp eax, 0Eh ; 14, PAGE FAULT 1487 000008BE 7513 jne short cpu_except_nfp 1488 000008C0 E8AD1D0000 call page_fault_handler 1489 000008C5 21C0 and eax, eax 1490 ;jz iiretp ; 01/09/2015 1491 ; 02/01/2022 1492 000008C7 7505 jnz short cpu_except_pf 1493 000008C9 E9B6000000 jmp iiretp 1494 cpu_except_pf: 1495 000008CE B80E000000 mov eax, 0Eh ; 14 1496 cpu_except_nfp: 1497 ; 02/04/2015 1498 000008D3 BB[FD050000] mov ebx, hang 1499 000008D8 875C241C xchg ebx, [esp+28] 1500 ; EIP (points to instruction which faults) 1501 ; New EIP (hang) 1502 000008DC 891D[D8610000] mov [FaultOffset], ebx 1503 000008E2 C744242008000000 mov dword [esp+32], KCODE ; kernel's code segment 1504 000008EA 814C242400020000 or dword [esp+36], 200h ; enable interrupts (set IF) 1505 ; 1506 000008F2 88C4 mov ah, al 1507 000008F4 240F and al, 0Fh 1508 000008F6 3C09 cmp al, 9 1509 000008F8 7602 jna short h1ok 1510 000008FA 0407 add al, 'A'-':' 1511 h1ok: 1512 000008FC D0EC shr ah, 1 1513 000008FE D0EC shr ah, 1 1514 00000900 D0EC shr ah, 1 1515 00000902 D0EC shr ah, 1 1516 00000904 80FC09 cmp ah, 9 1517 00000907 7603 jna short h2ok 1518 00000909 80C407 add ah, 'A'-':' 1519 h2ok: 1520 0000090C 86E0 xchg ah, al 1521 0000090E 66053030 add ax, '00' 1522 00000912 66A3[0A5D0000] mov [excnstr], ax 1523 ; 1524 ; 29/08/2014 1525 00000918 A1[D8610000] mov eax, [FaultOffset] 1526 0000091D 51 push ecx 1527 0000091E 52 push edx 1528 0000091F 89E3 mov ebx, esp 1529 ; 28/08/2015 1530 00000921 B910000000 mov ecx, 16 ; divisor value to convert binary number 1531 ; to hexadecimal string 1532 ;mov ecx, 10 ; divisor to convert 1533 ; binary number to decimal string 1534 b2d1: 1535 00000926 31D2 xor edx, edx 1536 00000928 F7F1 div ecx 1537 ;push dx 1538 ; 02/01/2022 1539 0000092A 52 push edx 1540 0000092B 39C8 cmp eax, ecx 1541 0000092D 73F7 jnb short b2d1 1542 0000092F BF[155D0000] mov edi, EIPstr ; EIP value 1543 ; points to instruction which faults 1544 ; 28/08/2015 1545 00000934 89C2 mov edx, eax 1546 b2d2: 1547 ;add al, '0' 1548 00000936 8A82[D8150000] mov al, [edx+hexchrs] 1549 0000093C AA stosb ; write hexadecimal digit to its place 1550 0000093D 39E3 cmp ebx, esp 1551 0000093F 7605 jna short b2d3 1552 ; 02/01/2022 1553 00000941 58 pop eax 1554 ;pop ax 1555 00000942 88C2 mov dl, al 1556 00000944 EBF0 jmp short b2d2 1557 b2d3: 1558 00000946 B068 mov al, 'h' ; 28/08/2015 1559 00000948 AA stosb 1560 00000949 B020 mov al, 20h ; space 1561 0000094B AA stosb 1562 0000094C 30C0 xor al, al ; to do it an ASCIIZ string 1563 0000094E AA stosb 1564 ; 1565 0000094F 5A pop edx 1566 00000950 59 pop ecx 1567 ; 1568 00000951 B44F mov ah, 4Fh ; red (4) background, 1569 ; white (F) forecolor 1570 00000953 BE[FA5C0000] mov esi, exc_msg ; message offset 1571 ; 1572 00000958 EB11 jmp short piemsg 1573 ; 1574 ;add dword [scr_row], 0A0h 1575 ;mov edi, [scr_row] 1576 ; 1577 ;call printk 1578 ; 1579 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1580 ;out 20h, al ; 8259 PORT 1581 ; 1582 ;pop es 1583 ;pop ds 1584 ;pop edi 1585 ;pop esi 1586 ;pop eax 1587 ;iret 1588 1589 ; 28/08/2015 1590 ; 23/02/2015 1591 ; 20/08/2014 1592 ignore_int: 1593 0000095A 50 push eax 1594 0000095B 53 push ebx ; 23/02/2015 1595 0000095C 56 push esi 1596 0000095D 57 push edi 1597 0000095E 1E push ds 1598 0000095F 06 push es 1599 ; 28/08/2015 1600 00000960 0F20D8 mov eax, cr3 1601 00000963 50 push eax ; (*) page directory 1602 ; 1603 00000964 B467 mov ah, 67h ; brown (6) background, 1604 ; light gray (7) forecolor 1605 00000966 BE[B85C0000] mov esi, int_msg ; message offset 1606 piemsg: 1607 ; 27/08/2014 1608 0000096B 8105[7C5C0000]A000- add dword [scr_row], 0A0h 1608 00000973 0000 1609 00000975 8B3D[7C5C0000] mov edi, [scr_row] 1610 ; 1611 0000097B E8B6FCFFFF call printk 1612 ; 1613 ; 23/02/2015 1614 00000980 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1615 00000982 E6A0 out 0A0h, al ; the 2nd 8259 1616 iiretp: ; 01/09/2015 1617 ; 28/08/2015 1618 00000984 58 pop eax ; (*) page directory 1619 00000985 0F22D8 mov cr3, eax 1620 ; 1621 iiret: 1622 ; 22/08/2014 1623 00000988 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1624 0000098A E620 out 20h, al ; 8259 PORT 1625 ; 1626 0000098C 07 pop es 1627 0000098D 1F pop ds 1628 0000098E 5F pop edi 1629 0000098F 5E pop esi 1630 00000990 5B pop ebx ; 29/08/2014 1631 00000991 58 pop eax 1632 00000992 CF iretd 1633 1634 ; 26/02/2022 1635 ; 26/02/2015 1636 ; 07/09/2014 1637 ; 25/08/2014 1638 rtc_int: ; Real Time Clock Interrupt (IRQ 8) 1639 ; 22/08/2014 1640 00000993 50 push eax 1641 00000994 53 push ebx ; 29/08/2014 1642 00000995 56 push esi 1643 00000996 57 push edi 1644 00000997 1E push ds 1645 00000998 06 push es 1646 ; 1647 00000999 B810000000 mov eax, KDATA 1648 0000099E 8ED8 mov ds, ax 1649 000009A0 8EC0 mov es, ax 1650 ; 1651 ; 25/08/2014 1652 ;call rtc_p 1653 ; 26/02/2022 1654 000009A2 FF15[F5060000] call [x_rtci] 1655 ; 1656 ; 22/02/2015 - dsectpm.s 1657 ; [ source: http://wiki.osdev.org/RTC ] 1658 ; read status register C to complete procedure 1659 ;(it is needed to get a next IRQ 8) 1660 000009A8 B00C mov al, 0Ch ; 1661 000009AA E670 out 70h, al ; select register C 1662 000009AC 90 nop 1663 000009AD E471 in al, 71h ; just throw away contents 1664 ; 22/02/2015 1665 000009AF B020 MOV AL,EOI ; END OF INTERRUPT 1666 000009B1 E6A0 OUT INTB00,AL ; FOR CONTROLLER #2 1667 ; 1668 000009B3 EBD3 jmp short iiret 1669 1670 ; 22/08/2014 1671 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm) 1672 ; (INT 1Ah) 1673 ;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991) 1674 time_of_day: 1675 000009B5 E866010000 call UPD_IPR ; WAIT TILL UPDATE NOT IN PROGRESS 1676 000009BA 726F jc short rtc_retn 1677 000009BC B000 mov al, CMOS_SECONDS 1678 000009BE E847010000 call CMOS_READ 1679 000009C3 A2[9C610000] mov [time_seconds], al 1680 000009C8 B002 mov al, CMOS_MINUTES 1681 000009CA E83B010000 call CMOS_READ 1682 000009CF A2[9D610000] mov [time_minutes], al 1683 000009D4 B004 mov al, CMOS_HOURS 1684 000009D6 E82F010000 call CMOS_READ 1685 000009DB A2[9E610000] mov [time_hours], al 1686 000009E0 B006 mov al, CMOS_DAY_WEEK 1687 000009E2 E823010000 call CMOS_READ 1688 000009E7 A2[9F610000] mov [date_wday], al 1689 000009EC B007 mov al, CMOS_DAY_MONTH 1690 000009EE E817010000 call CMOS_READ 1691 000009F3 A2[A0610000] mov [date_day], al 1692 000009F8 B008 mov al, CMOS_MONTH 1693 000009FA E80B010000 call CMOS_READ 1694 000009FF A2[A1610000] mov [date_month], al 1695 00000A04 B009 mov al, CMOS_YEAR 1696 00000A06 E8FF000000 call CMOS_READ 1697 00000A0B A2[A2610000] mov [date_year], al 1698 00000A10 B032 mov al, CMOS_CENTURY 1699 00000A12 E8F3000000 call CMOS_READ 1700 00000A17 A2[A3610000] mov [date_century], al 1701 ; 1702 00000A1C B000 mov al, CMOS_SECONDS 1703 00000A1E E8E7000000 call CMOS_READ 1704 00000A23 3A05[9C610000] cmp al, [time_seconds] 1705 00000A29 758A jne short time_of_day 1706 1707 rtc_retn: 1708 00000A2B C3 retn 1709 1710 rtci_default: 1711 ; 26/02/2022 (Temporary!) 1712 ; (default real time clock handler in multitasking mode) 1713 ; ((2 rtc ticks per second after 'setup_rtc_int')) 1714 00000A2C FF05[E0610000] inc dword [rtc_ticks] ; real time clock counter 1715 ; (not used in anywhere of kernel for now!) 1716 00000A32 C3 retn 1717 1718 rtc_p: 1719 ; 07/09/2014 1720 ; 29/08/2014 1721 ; 27/08/2014 1722 ; 25/08/2014 1723 ; Print Real Time Clock content 1724 ; 1725 ; 1726 00000A33 E87DFFFFFF call time_of_day 1727 00000A38 72F1 jc short rtc_retn 1728 ; 1729 00000A3A 3A05[6C5D0000] cmp al, [ptime_seconds] 1730 00000A40 74E9 je short rtc_retn ; 29/08/2014 1731 ; 1732 00000A42 A2[6C5D0000] mov [ptime_seconds], al 1733 ; 1734 00000A47 A0[A3610000] mov al, [date_century] 1735 00000A4C E8EA000000 call bcd_to_ascii 1736 00000A51 66A3[395D0000] mov [datestr+6], ax 1737 00000A57 A0[A2610000] mov al, [date_year] 1738 00000A5C E8DA000000 call bcd_to_ascii 1739 00000A61 66A3[3B5D0000] mov [datestr+8], ax 1740 00000A67 A0[A1610000] mov al, [date_month] 1741 00000A6C E8CA000000 call bcd_to_ascii 1742 00000A71 66A3[365D0000] mov [datestr+3], ax 1743 00000A77 A0[A0610000] mov al, [date_day] 1744 00000A7C E8BA000000 call bcd_to_ascii 1745 00000A81 66A3[335D0000] mov [datestr], ax 1746 ; 1747 00000A87 0FB61D[9F610000] movzx ebx, byte [date_wday] 1748 00000A8E C0E302 shl bl, 2 1749 00000A91 81C3[4C5D0000] add ebx, daytmp 1750 00000A97 8B03 mov eax, [ebx] 1751 00000A99 A3[3E5D0000] mov [daystr], eax 1752 ; 1753 00000A9E A0[9E610000] mov al, [time_hours] 1754 00000AA3 E893000000 call bcd_to_ascii 1755 00000AA8 66A3[425D0000] mov [timestr], ax 1756 00000AAE A0[9D610000] mov al, [time_minutes] 1757 00000AB3 E883000000 call bcd_to_ascii 1758 00000AB8 66A3[455D0000] mov [timestr+3], ax 1759 00000ABE A0[9C610000] mov al, [time_seconds] 1760 00000AC3 E873000000 call bcd_to_ascii 1761 00000AC8 66A3[485D0000] mov [timestr+6], ax 1762 ; 1763 00000ACE BE[215D0000] mov esi, rtc_msg ; message offset 1764 ; 23/02/2015 1765 00000AD3 52 push edx 1766 00000AD4 51 push ecx 1767 ; 07/09/2014 1768 ;mov bx, 2 ; Video page 2 1769 ; 02/01/2022 1770 00000AD5 29DB sub ebx, ebx 1771 00000AD7 B307 mov bl, 7 ; Video page 7 1772 prtmsg: 1773 00000AD9 AC lodsb 1774 00000ADA 08C0 or al, al 1775 00000ADC 740D jz short prtmsg_ok 1776 00000ADE 56 push esi 1777 ; 02/01/2022 1778 00000ADF 53 push ebx 1779 ;push bx 1780 00000AE0 B43F mov ah, 3Fh ; cyan (6) background, 1781 ; white (F) forecolor 1782 00000AE2 E8B5070000 call write_tty 1783 ;pop bx 1784 ; 02/01/2022 1785 00000AE7 5B pop ebx 1786 00000AE8 5E pop esi 1787 00000AE9 EBEE jmp short prtmsg 1788 ; 1789 ;mov edi, 0B8000h+0A0h+0A0h ; Row 2 1790 ;call printk 1791 prtmsg_ok: 1792 ; 07/09/2014 1793 ;xor dx, dx ; column 0, row 0 1794 ; 02/01/2022 1795 00000AEB 31D2 xor edx, edx 1796 00000AED E8B4080000 call set_cpos ; set curspor position to 0,0 1797 ; 23/02/2015 1798 00000AF2 59 pop ecx 1799 00000AF3 5A pop edx 1800 00000AF4 C3 retn 1801 1802 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 1803 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 1804 default_irq7: 1805 ; 24/12/2021 1806 ;push ax 1807 00000AF5 50 push eax 1808 00000AF6 B00B mov al, 0Bh ; In-Service register 1809 00000AF8 E620 out 20h, al 1810 00000AFA EB00 jmp short $+2 1811 00000AFC EB00 jmp short $+2 1812 00000AFE E420 in al, 20h 1813 00000B00 2480 and al, 80h ; bit 7 (is it real IRQ 7 or fake?) 1814 00000B02 7404 jz short irq7_iret ; Fake (spurious) IRQ, do not send EOI 1815 00000B04 B020 mov al, 20h ; EOI 1816 00000B06 E620 out 20h, al 1817 irq7_iret: 1818 ;pop ax 1819 ; 24/12/2021 1820 00000B08 58 pop eax 1821 00000B09 CF iretd 1822 1823 ; 24/12/2021 1824 ; 22/08/2014 1825 ; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm) 1826 CMOS_READ: 1827 00000B0A 9C pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 1828 00000B0B D0C0 rol al, 1 ; MOVE NMI BIT TO LOW POSITION 1829 00000B0D F9 stc ; FORCE NMI BIT ON IN CARRY FLAG 1830 00000B0E D0D8 rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 1831 00000B10 FA cli ; DISABLE INTERRUPTS 1832 00000B11 E670 out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 1833 00000B13 90 nop ; I/O DELAY 1834 00000B14 E471 in al, CMOS_DATA ; READ THE REQUESTED CMOS LOCATION 1835 ;push ax ; SAVE (AH) REGISTER VALUE AND CMOS BYTE 1836 ; 24/12/2021 1837 00000B16 50 push eax 1838 ; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 1839 ; ----- 10/06/85 (test4.asm) 1840 00000B17 B01E mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 1841 ;mov al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION 1842 00000B19 D0D8 rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 1843 00000B1B E670 out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 1844 ;pop ax ; RESTORE (AH) AND (AL), CMOS BYTE 1845 ; 24/12/2021 1846 00000B1D 58 pop eax 1847 00000B1E 9D popf 1848 00000B1F C3 retn ; RETURN WITH FLAGS RESTORED 1849 1850 ; 22/08/2014 1851 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm) 1852 UPD_IPR: ; WAIT TILL UPDATE NOT IN PROGRESS 1853 00000B20 51 push ecx 1854 00000B21 B9FFFF0000 mov ecx, 65535 ; SET TIMEOUT LOOP COUNT (= 800) 1855 ; mov cx, 800 1856 UPD_10: 1857 00000B26 B00A mov al, CMOS_REG_A ; ADDRESS STATUS REGISTER A 1858 00000B28 FA cli ; NO TIMER INTERRUPTS DURING UPDATES 1859 00000B29 E8DCFFFFFF call CMOS_READ ; READ UPDATE IN PROCESS FLAG 1860 00000B2E A880 test al, 80h ; IF UIP BIT IS ON ( CANNOT READ TIME ) 1861 00000B30 7406 jz short UPD_90 ; EXIT WITH CY= 0 IF CAN READ CLOCK NOW 1862 00000B32 FB sti ; ALLOW INTERRUPTS WHILE WAITING 1863 00000B33 E2F1 loop UPD_10 ; LOOP TILL READY OR TIMEOUT 1864 00000B35 31C0 xor eax, eax ; CLEAR RESULTS IF ERROR 1865 ; xor ax, ax 1866 00000B37 F9 stc ; SET CARRY FOR ERROR 1867 UPD_90: 1868 00000B38 59 pop ecx ; RESTORE CALLERS REGISTER 1869 00000B39 FA cli ; INTERRUPTS OFF DURING SET 1870 00000B3A C3 retn ; RETURN WITH CY FLAG SET 1871 1872 bcd_to_ascii: 1873 ; 25/08/2014 1874 ; INPUT -> 1875 ; al = Packed BCD number 1876 ; OUTPUT -> 1877 ; ax = ASCII word/number 1878 ; 1879 ; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011) 1880 ; 1881 00000B3B D410 db 0D4h,10h ; Undocumented inst. AAM 1882 ; AH = AL / 10h 1883 ; AL = AL MOD 10h 1884 00000B3D 660D3030 or ax,'00' ; Make it ASCII based 1885 1886 00000B41 86E0 xchg ah, al 1887 1888 00000B43 C3 retn 1889 1890 1891 %include 'keyboard.inc' ; 07/03/2015 1892 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - KEYBOARD.INC 1893 <1> ; Last Modification: 24/07/2022 1894 <1> ; (Keyboard Data is in 'KYBDATA.INC') 1895 <1> ; 1896 <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) /////////////// 1897 <1> 1898 <1> ; 24/07/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.6) 1899 <1> ; 24/07/2022 (Retro UNIX 386 v1, Kernel v0.2.0.22) 1900 <1> ; 23/02/2022 1901 <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 1902 <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 1903 <1> ; 30/06/2015 1904 <1> ; 11/03/2015 1905 <1> ; 28/02/2015 1906 <1> ; 25/02/2015 1907 <1> ; 20/02/2015 1908 <1> ; 18/02/2015 1909 <1> ; 03/12/2014 1910 <1> ; 07/09/2014 1911 <1> ; KEYBOARD INTERRUPT HANDLER 1912 <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014) 1913 <1> 1914 <1> ;getch: 1915 <1> ; ; 18/02/2015 1916 <1> ; ; This routine will be replaced with Retro UNIX 386 1917 <1> ; ; version of Retro UNIX 8086 getch (tty input) 1918 <1> ; ; routine, later... (multi tasking ability) 1919 <1> ; ; 28/02/2015 1920 <1> ; sti ; enable interrupts 1921 <1> ; ; 1922 <1> ; ;push esi 1923 <1> ; ;push ebx 1924 <1> ; ;xor ebx, ebx 1925 <1> ; ;mov bl, [ptty] ; active_page 1926 <1> ; ;mov esi, ebx 1927 <1> ; ;shl si, 1 1928 <1> ; ;add esi, ttychr 1929 <1> ;getch_1: 1930 <1> ; ;mov ax, [esi] 1931 <1> ; mov ax, [ttychr] ; video page 0 (tty0) 1932 <1> ; and ax, ax 1933 <1> ; jz short getch_2 1934 <1> ; mov word [ttychr], 0 1935 <1> ; ;mov word [esi], 0 1936 <1> ; ;pop ebx 1937 <1> ; ;pop esi 1938 <1> ; retn 1939 <1> ;getch_2: 1940 <1> ; hlt ; not proper for multi tasking! 1941 <1> ; ; (temporary halt for now) 1942 <1> ; ; 'sleep' on tty 1943 <1> ; ; will (must) be located here 1944 <1> ; nop 1945 <1> ; jmp short getch_1 1946 <1> 1947 <1> keyb_int: 1948 <1> ; 24/07/2022 1949 <1> ; 23/02/2022 1950 <1> ; 30/06/2015 1951 <1> ; 25/02/2015 1952 <1> ; 20/02/2015 1953 <1> ; 03/12/2014 (getc_int - INT 16h modifications) 1954 <1> ; 07/09/2014 - Retro UNIX 386 v1 1955 <1> ; 30/06/2014 1956 <1> ; 10/05/2013 1957 <1> ; Retro Unix 8086 v1 feature only! 1958 <1> ; 03/03/2014 1959 <1> 1960 00000B44 1E <1> push ds 1961 00000B45 53 <1> push ebx 1962 00000B46 50 <1> push eax 1963 <1> ; 1964 <1> ; 23/02/2022 1965 00000B47 9C <1> pushfd 1966 00000B48 0E <1> push cs 1967 <1> ;mov ax, KDATA 1968 00000B49 31C0 <1> xor eax, eax 1969 00000B4B B010 <1> mov al, KDATA 1970 00000B4D 8ED8 <1> mov ds, ax 1971 <1> ; 1972 <1> ;pushfd 1973 <1> ;push cs 1974 00000B4F E80A010000 <1> call kb_int ; int_09h 1975 <1> ; 1976 <1> ;mov ah, 11h ; 03/12/2014 1977 00000B54 B401 <1> mov ah, 1 ; 24/07/2022 1978 <1> ;call getc 1979 00000B56 E854000000 <1> call int_16h ; 30/06/2015 1980 00000B5B 744E <1> jz short keyb_int4 1981 <1> ; 1982 <1> ;mov ah, 10h ; 03/12/2014 1983 00000B5D B400 <1> mov ah, 0 ; 24/07/2022 1984 <1> ;call getc 1985 00000B5F E84B000000 <1> call int_16h ; 30/06/2015 1986 <1> ; 1987 <1> ; 20/02/2015 1988 00000B64 0FB61D[56610000] <1> movzx ebx, byte [ptty] ; active_page 1989 <1> ; 1990 00000B6B 20C0 <1> and al, al 1991 00000B6D 751D <1> jnz short keyb_int1 1992 <1> ; 1993 00000B6F 80FC68 <1> cmp ah, 68h ; ALT + F1 key 1994 00000B72 7218 <1> jb short keyb_int1 1995 00000B74 80FC6F <1> cmp ah, 6Fh ; ALT + F8 key 1996 00000B77 7713 <1> ja short keyb_int1 1997 <1> ; 1998 00000B79 88D8 <1> mov al, bl 1999 00000B7B 0468 <1> add al, 68h 2000 00000B7D 38E0 <1> cmp al, ah 2001 00000B7F 7409 <1> je short keyb_int0 2002 00000B81 88E0 <1> mov al, ah 2003 00000B83 2C68 <1> sub al, 68h 2004 00000B85 E831090000 <1> call tty_sw 2005 <1> ;movzx ebx, [ptty] ; active_page 2006 <1> keyb_int0: ; 30/06/2015 2007 <1> ;xor ax, ax 2008 <1> ; 23/02/2022 2009 00000B8A 31C0 <1> xor eax, eax 2010 <1> keyb_int1: 2011 00000B8C D0E3 <1> shl bl, 1 2012 00000B8E 81C3[58610000] <1> add ebx, ttychr 2013 <1> ; 2014 <1> ;23/02/2022 2015 00000B94 09C0 <1> or eax, eax 2016 <1> ;or ax, ax 2017 00000B96 7406 <1> jz short keyb_int2 2018 <1> ; 2019 00000B98 66833B00 <1> cmp word [ebx], 0 2020 00000B9C 7703 <1> ja short keyb_int3 2021 <1> keyb_int2: 2022 00000B9E 668903 <1> mov [ebx], ax ; Save ascii code 2023 <1> ; and scan code of the character 2024 <1> ; for current tty (or last tty 2025 <1> ; just before tty switch). 2026 <1> keyb_int3: 2027 00000BA1 A0[56610000] <1> mov al, [ptty] 2028 00000BA6 E82D3A0000 <1> call wakeup 2029 <1> ; 2030 <1> keyb_int4: 2031 00000BAB 58 <1> pop eax 2032 00000BAC 5B <1> pop ebx 2033 00000BAD 1F <1> pop ds 2034 00000BAE CF <1> iret 2035 <1> 2036 <1> ; 18/02/2015 2037 <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc. 2038 <1> ; 'keyb_int' always handles 'getc' at 1st and puts the 2039 <1> ; scancode and ascii code of the character 2040 <1> ; in the tty input (ttychr) buffer. 2041 <1> ; Test procedures must call 'getch' for tty input 2042 <1> ; otherwise, 'getc' will not be able to return to the caller 2043 <1> ; due to infinite (key press) waiting loop. 2044 <1> ; 2045 <1> ; 03/12/2014 2046 <1> ; 26/08/2014 2047 <1> ; KEYBOARD I/O 2048 <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014) 2049 <1> 2050 <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers. 2051 <1> ; (The reason of using '_k' labels!!!) (27/08/2014) 2052 <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM. 2053 <1> ; ('NOT LC_HC' --> '~LC_HC') (bit reversing operator) 2054 <1> 2055 <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2056 <1> ;int_16h: ; 30/06/2015 2057 <1> ;;getc: 2058 <1> ; pushfd ; 28/08/2014 2059 <1> ; push cs 2060 <1> ; call getc_int 2061 <1> ; retn 2062 <1> 2063 <1> ; 24/07/2022 2064 <1> %if 0 2065 <1> ; 24/12/2021 2066 <1> 2067 <1> ;----- SHIFT STATUS 2068 <1> _K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2069 <1> mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2070 <1> and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2071 <1> ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2072 <1> ;shl ah, cl ; BIT 7 POSITION 2073 <1> shl ah, 5 2074 <1> mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2075 <1> and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2076 <1> or ah, al ; MERGE REMAINING BITS INTO AH 2077 <1> mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2078 <1> and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2079 <1> or ah, al ; OR THE SHIFT FLAGS TOGETHER 2080 <1> _K3: 2081 <1> mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2082 <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2083 <1> 2084 <1> %endif 2085 <1> 2086 <1> int_16h: 2087 <1> ; 24/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2088 <1> ; 24/07/2022 - (near call return instead of interrupt return) 2089 <1> 2090 <1> ; INPUT: 2091 <1> ; AL = Function (0 or 1) 2092 <1> ; 0 = Read Character 2093 <1> ; 1 = Get Keyboard Buffer Status 2094 <1> ; OUTPUT: 2095 <1> ; Function 0 - AX = ASCII (AL) and SCAN CODE (AH) 2096 <1> ; of the character (enterrd from the keyboard) 2097 <1> ; Function 1 - If ZF = 0 2098 <1> ; AX = ASCII (AL) and SCAN CODE (AH) of the character 2099 <1> ; (which is waiting in keyboard buffer) 2100 <1> ; If ZF = 1 2101 <1> ; there is not a character in the keyboard buffer 2102 <1> ; 2103 <1> ; Modified registers: eax, ebx 2104 <1> 2105 <1> getc_int: 2106 <1> ; 24/07/2022 (Retro UNIX 386 v1.1 - Kernel v0.2.1.6) 2107 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2108 <1> ; 28/02/2015 2109 <1> ; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2110 <1> ; instead of pc-at bios - 1985-) 2111 <1> ; 28/08/2014 (_k1d) 2112 <1> ; 30/06/2014 2113 <1> ; 03/03/2014 2114 <1> ; 28/02/2014 2115 <1> ; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 2116 <1> ; rombios source code (21/04/1986) 2117 <1> ; 'keybd.asm', INT 16H, KEYBOARD_IO 2118 <1> ; 2119 <1> ; KYBD --- 03/06/86 KEYBOARD BIOS 2120 <1> ; 2121 <1> ;--- INT 16 H ----------------------------------------------------------------- 2122 <1> ; KEYBOARD I/O : 2123 <1> ; THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT : 2124 <1> ; INPUT : 2125 <1> ; (AH)= 00H READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD, : 2126 <1> ; RETURN THE RESULT IN (AL), SCAN CODE IN (AH). : 2127 <1> ; THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE : 2128 <1> ; STANDARD PC OR PCAT KEYBOARD : 2129 <1> ;-----------------------------------------------------------------------------: 2130 <1> ; (AH)= 01H SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS : 2131 <1> ; AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER. : 2132 <1> ; (ZF)= 1 -- NO CODE AVAILABLE : 2133 <1> ; (ZF)= 0 -- CODE IS AVAILABLE (AX)= CHARACTER : 2134 <1> ; IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS : 2135 <1> ; IN (AX), AND THE ENTRY REMAINS IN THE BUFFER. : 2136 <1> ; THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES : 2137 <1> ;-----------------------------------------------------------------------------: 2138 <1> ; (AH)= 02H RETURN THE CURRENT SHIFT STATUS IN AL REGISTER : 2139 <1> ; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE : 2140 <1> ; EQUATES FOR @KB_FLAG : 2141 <1> ;-----------------------------------------------------------------------------: 2142 <1> ; (AH)= 03H SET TYPAMATIC RATE AND DELAY : 2143 <1> ; (AL) = 05H : 2144 <1> ; (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0) : 2145 <1> ; : 2146 <1> ; REGISTER RATE REGISTER RATE : 2147 <1> ; VALUE SELECTED VALUE SELECTED : 2148 <1> ; -------------------------------------------- : 2149 <1> ; 00H 30.0 10H 7.5 : 2150 <1> ; 01H 26.7 11H 6.7 : 2151 <1> ; 02H 24.0 12H 6.0 : 2152 <1> ; 03H 21.8 13H 5.5 : 2153 <1> ; 04H 20.0 14H 5.0 : 2154 <1> ; 05H 18.5 15H 4.6 : 2155 <1> ; 06H 17.1 16H 4.3 : 2156 <1> ; 07H 16.0 17H 4.0 : 2157 <1> ; 08H 15.0 18H 3.7 : 2158 <1> ; 09H 13.3 19H 3.3 : 2159 <1> ; 0AH 12.0 1AH 3.0 : 2160 <1> ; 0BH 10.9 1BH 2.7 : 2161 <1> ; 0CH 10.0 1CH 2.5 : 2162 <1> ; 0DH 9.2 1DH 2.3 : 2163 <1> ; 0EH 8.6 1EH 2.1 : 2164 <1> ; 0FH 8.0 1FH 2.0 : 2165 <1> ; : 2166 <1> ; (BH) = TYPAMATIC DELAY (BITS 2 - 7 MUST BE RESET TO 0) : 2167 <1> ; : 2168 <1> ; REGISTER DELAY : 2169 <1> ; VALUE VALUE : 2170 <1> ; ------------------ : 2171 <1> ; 00H 250 ms : 2172 <1> ; 01H 500 ms : 2173 <1> ; 02H 750 ms : 2174 <1> ; 03H 1000 ms : 2175 <1> ;-----------------------------------------------------------------------------: 2176 <1> ; (AH)= 05H PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD : 2177 <1> ; BUFFER AS IF STRUCK FROM KEYBOARD : 2178 <1> ; ENTRY: (CL) = ASCII CHARACTER : 2179 <1> ; (CH) = SCAN CODE : 2180 <1> ; EXIT: (AH) = 00H = SUCCESSFUL OPERATION : 2181 <1> ; (AL) = 01H = UNSUCCESSFUL - BUFFER FULL : 2182 <1> ; FLAGS: CARRY IF ERROR : 2183 <1> ;-----------------------------------------------------------------------------: 2184 <1> ; (AH)= 10H EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD, : 2185 <1> ; OTHERWISE SAME AS FUNCTION AH=0 : 2186 <1> ;-----------------------------------------------------------------------------: 2187 <1> ; (AH)= 11H EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD, : 2188 <1> ; OTHERWISE SAME AS FUNCTION AH=1 : 2189 <1> ;-----------------------------------------------------------------------------: 2190 <1> ; (AH)= 12H RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER : 2191 <1> ; AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT : 2192 <1> ; CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3 : 2193 <1> ; OUTPUT : 2194 <1> ; AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED : 2195 <1> ; ALL REGISTERS RETAINED : 2196 <1> ;------------------------------------------------------------------------------ 2197 <1> 2198 00000BAF FB <1> sti ; INTERRUPTS BACK ON 2199 <1> 2200 <1> ; 24/07/2022 2201 <1> ;push ds ; SAVE CURRENT DS 2202 <1> ;push ebx ; SAVE BX TEMPORARILY 2203 <1> ;push ecx ; SAVE CX TEMPORARILY 2204 <1> ;mov bx, KDATA 2205 <1> ;mov ds, bx ; PUT SEGMENT VALUE OF DATA AREA INTO DS 2206 <1> 2207 <1> ;or ah, ah ; CHECK FOR (AH)= 00H 2208 <1> ;jz short _K1 ; ASCII_READ 2209 <1> ;dec ah ; CHECK FOR (AH)= 01H 2210 <1> ;jz short _K2 ; ASCII_STATUS 2211 <1> ;dec ah ; CHECK FOR (AH)= 02H 2212 <1> ;jz short _K3 ; SHIFT STATUS 2213 <1> ;dec ah ; CHECK FOR (AH)= 03H 2214 <1> ;jz short _K300 ; SET TYPAMATIC RATE/DELAY 2215 <1> ;sub ah, 2 ; CHECK FOR (AH)= 05H 2216 <1> ;jz short _K500 ; KEYBOARD WRITE 2217 <1> ;_KIO1: 2218 <1> ;sub ah, 11 ; AH = 10H 2219 <1> ;jz short _K1E ; EXTENDED ASCII READ 2220 <1> ;dec ah ; CHECK FOR (AH)= 11H 2221 <1> ;jz short _K2E ; EXTENDED_ASCII_STATUS 2222 <1> ;dec ah ; CHECK FOR (AH)= 12H 2223 <1> ;jz short _K3E ; EXTENDED_SHIFT_STATUS 2224 <1> 2225 <1> ;_KIO_EXIT: 2226 <1> ;pop ecx ; RECOVER REGISTER 2227 <1> ;pop ebx ; RECOVER REGISTER 2228 <1> ; 24/07/2022 2229 <1> ;retn 2230 <1> ;pop ds ; RECOVER SEGMENT 2231 <1> ;iretd ; INVALID COMMAND, EXIT 2232 <1> 2233 00000BB0 08E4 <1> or ah, ah 2234 00000BB2 7507 <1> jnz short _K2 2235 <1> 2236 <1> ;----- ASCII CHARACTER 2237 <1> _K1: 2238 <1> _K1E: 2239 00000BB4 E81C000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER (EXTENDED) 2240 <1> ;call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2241 <1> ;;jmp short _KIO_EXIT ; GIVE IT TO THE CALLER 2242 <1> ; 24/07/2022 2243 <1> ;retn 2244 00000BB9 EB0F <1> jmp short _KIO_E_XLAT 2245 <1> ;_K1: 2246 <1> ;call _K1S ; GET A CHARACTER FROM THE BUFFER 2247 <1> ;call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2248 <1> ;jc short _K1 ; CARRY SET MEANS TROW CODE AWAY 2249 <1> ;_K1A: 2250 <1> ;jmp short _KIO_EXIT ; RETURN TO CALLER 2251 <1> ; 24/07/2022 2252 <1> ;retn 2253 <1> 2254 <1> ;----- ASCII STATUS 2255 <1> _K2: 2256 <1> _K2E: 2257 00000BBB E860000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER (EXTENDED) 2258 00000BC0 7407 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2259 00000BC2 9C <1> pushf ; SAVE ZF FROM TEST 2260 00000BC3 E802000000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2261 <1> ;jmp short _K2A ; GIVE IT TO THE CALLER 2262 <1> ; 24/07/2022 2263 00000BC8 9D <1> popf 2264 <1> _K2B: 2265 00000BC9 C3 <1> retn 2266 <1> ;_K2: 2267 <1> ;call _K2S ; TEST FOR CHARACTER IN BUFFER 2268 <1> ;jz short _K2B ; RETURN IF BUFFER EMPTY 2269 <1> ;pushf ; SAVE ZF FROM TEST 2270 <1> ;call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2271 <1> ;jnc short _K2A ; CARRY CLEAR MEANS PASS VALID CODE 2272 <1> ;popf ; INVALID CODE FOR THIS TYPE OF CALL 2273 <1> ;call _K1S ; THROW THE CHARACTER AWAY 2274 <1> ;jmp short _K2 ; GO LOOK FOR NEXT CHAR, IF ANY 2275 <1> ;_K2A: 2276 <1> ;popf ; RESTORE ZF FROM TEST 2277 <1> ;_K2B: 2278 <1> ;;pop ecx ; RECOVER REGISTER 2279 <1> ;pop ebx ; RECOVER REGISTER 2280 <1> ;pop ds ; RECOVER SEGMENT 2281 <1> ;retf 4 ; THROW AWAY (E)FLAGS 2282 <1> 2283 <1> ; 24/12/2021 2284 <1> ; ;----- SHIFT STATUS 2285 <1> ;_K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2286 <1> ; mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2287 <1> ; and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2288 <1> ; ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2289 <1> ; ;shl ah, cl ; BIT 7 POSITION 2290 <1> ; shl ah, 5 2291 <1> ; mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2292 <1> ; and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2293 <1> ; or ah, al ; MERGE REMAINING BITS INTO AH 2294 <1> ; mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2295 <1> ; and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2296 <1> ; or ah, al ; OR THE SHIFT FLAGS TOGETHER 2297 <1> ;_K3: 2298 <1> ; mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2299 <1> ; jmp short _KIO_EXIT ; RETURN TO CALLER 2300 <1> 2301 <1> ; 24/07/2022 2302 <1> %if 0 2303 <1> ;----- SET TYPAMATIC RATE AND DELAY 2304 <1> _K300: 2305 <1> cmp al, 5 ; CORRECT FUNCTION CALL? 2306 <1> jne short _KIO_EXIT ; NO, RETURN 2307 <1> test bl, 0E0h ; TEST FOR OUT-OF-RANGE RATE 2308 <1> jnz short _KIO_EXIT ; RETURN IF SO 2309 <1> test BH, 0FCh ; TEST FOR OUT-OF-RANGE DELAY 2310 <1> jnz short _KIO_EXIT ; RETURN IF SO 2311 <1> mov al, KB_TYPA_RD ; COMMAND FOR TYPAMATIC RATE/DELAY 2312 <1> call SND_DATA ; SEND TO KEYBOARD 2313 <1> ;mov cx, 5 ; SHIFT COUNT 2314 <1> ;shl bh, cl ; SHIFT DELAY OVER 2315 <1> shl bh, 5 2316 <1> mov al, bl ; PUT IN RATE 2317 <1> or al, bh ; AND DELAY 2318 <1> call SND_DATA ; SEND TO KEYBOARD 2319 <1> jmp _KIO_EXIT ; RETURN TO CALLER 2320 <1> 2321 <1> ;----- WRITE TO KEYBOARD BUFFER 2322 <1> _K500: 2323 <1> push esi ; SAVE SI (esi) 2324 <1> cli ; 2325 <1> mov ebx, [BUFFER_TAIL] ; GET THE 'IN TO' POINTER TO THE BUFFER 2326 <1> mov esi, ebx ; SAVE A COPY IN CASE BUFFER NOT FULL 2327 <1> call _K4 ; BUMP THE POINTER TO SEE IF BUFFER IS FULL 2328 <1> cmp ebx, [BUFFER_HEAD] ; WILL THE BUFFER OVERRUN IF WE STORE THIS? 2329 <1> je short _K502 ; YES - INFORM CALLER OF ERROR 2330 <1> mov [esi], cx ; NO - PUT ASCII/SCAN CODE INTO BUFFER 2331 <1> mov [BUFFER_TAIL], ebx ; ADJUST 'IN TO' POINTER TO REFLECT CHANGE 2332 <1> sub al, al ; TELL CALLER THAT OPERATION WAS SUCCESSFUL 2333 <1> jmp short _K504 ; SUB INSTRUCTION ALSO RESETS CARRY FLAG 2334 <1> _K502: 2335 <1> mov al, 01h ; BUFFER FULL INDICATION 2336 <1> _K504: 2337 <1> sti 2338 <1> pop esi ; RECOVER SI (esi) 2339 <1> jmp _KIO_EXIT ; RETURN TO CALLER WITH STATUS IN AL 2340 <1> %endif 2341 <1> 2342 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS ----- 2343 <1> _KIO_E_XLAT: 2344 00000BCA 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2345 00000BCC 7506 <1> jne short _KIO_E_RET ; NO, PASS IT ON 2346 00000BCE 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2347 00000BD0 7402 <1> jz short _KIO_E_RET ; PASS THIS ON UNCHANGED 2348 00000BD2 30C0 <1> xor al, al ; OTHERWISE SET AL = 0 2349 <1> _KIO_E_RET: 2350 00000BD4 C3 <1> retn ; GO BACK 2351 <1> 2352 <1> ;----- READ THE KEY TO FIGURE OUT WHAT TO DO ----- 2353 <1> _K1S: 2354 00000BD5 FA <1> cli ; 03/12/2014 2355 00000BD6 8B1D[905B0000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2356 00000BDC 3B1D[945B0000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2357 <1> ;jne short _K1U ; IF ANYTHING IN BUFFER SKIP INTERRUPT 2358 00000BE2 750F <1> jne short _k1x ; 03/12/2014 2359 <1> ; 2360 <1> ; 03/12/2014 2361 <1> ; 28/08/2014 2362 <1> ; PERFORM OTHER FUNCTION ?? here ! 2363 <1> ;;mov ax, 9002h ; MOVE IN WAIT CODE & TYPE 2364 <1> ;;int 15h ; PERFORM OTHER FUNCTION 2365 <1> _K1T: ; ASCII READ 2366 00000BE4 FB <1> sti ; INTERRUPTS BACK ON DURING LOOP 2367 00000BE5 90 <1> nop ; ALLOW AN INTERRUPT TO OCCUR 2368 <1> _K1U: 2369 00000BE6 FA <1> cli ; INTERRUPTS BACK OFF 2370 00000BE7 8B1D[905B0000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2371 00000BED 3B1D[945B0000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2372 <1> _k1x: 2373 00000BF3 53 <1> push ebx ; SAVE ADDRESS 2374 00000BF4 9C <1> pushf ; SAVE FLAGS 2375 00000BF5 E895060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2376 00000BFA 8A1D[855B0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2377 00000C00 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2378 00000C02 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2379 00000C05 7406 <1> jz short _K1V ; IF NO CHANGE BYPASS UPDATE 2380 00000C07 E82F060000 <1> call SND_LED1 2381 00000C0C FA <1> cli ; DISABLE INTERRUPTS 2382 <1> _K1V: 2383 00000C0D 9D <1> popf ; RESTORE FLAGS 2384 00000C0E 5B <1> pop ebx ; RESTORE ADDRESS 2385 00000C0F 74D3 <1> je short _K1T ; LOOP UNTIL SOMETHING IN BUFFER 2386 <1> ; 2387 00000C11 668B03 <1> mov ax, [ebx] ; GET SCAN CODE AND ASCII CODE 2388 00000C14 E834000000 <1> call _K4 ; MOVE POINTER TO NEXT POSITION 2389 00000C19 891D[905B0000] <1> mov [BUFFER_HEAD], ebx ; STORE VALUE IN VARIABLE 2390 00000C1F C3 <1> retn ; RETURN 2391 <1> 2392 <1> ;----- READ THE KEY TO SEE IF ONE IS PRESENT ----- 2393 <1> _K2S: 2394 00000C20 FA <1> cli ; INTERRUPTS OFF 2395 00000C21 8B1D[905B0000] <1> mov ebx, [BUFFER_HEAD] ; GET HEAD POINTER 2396 00000C27 3B1D[945B0000] <1> cmp ebx, [BUFFER_TAIL] ; IF EQUAL (Z=1) THEN NOTHING THERE 2397 00000C2D 668B03 <1> mov ax, [ebx] 2398 00000C30 9C <1> pushf ; SAVE FLAGS 2399 <1> ;push ax ; SAVE CODE 2400 <1> ; 24/12/2021 2401 00000C31 50 <1> push eax 2402 00000C32 E858060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2403 00000C37 8A1D[855B0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2404 00000C3D 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2405 00000C3F 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2406 00000C42 7405 <1> jz short _K2T ; IF NO CHANGE BYPASS UPDATE 2407 00000C44 E8DB050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2408 <1> _K2T: 2409 <1> ;pop ax ; RESTORE CODE 2410 <1> ; 24/12/2021 2411 00000C49 58 <1> pop eax 2412 00000C4A 9D <1> popf ; RESTORE FLAGS 2413 00000C4B FB <1> sti ; INTERRUPTS BACK ON 2414 00000C4C C3 <1> retn ; RETURN 2415 <1> 2416 <1> ; 24/07/2022 2417 <1> %if 0 2418 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS ----- 2419 <1> _KIO_S_XLAT: 2420 <1> cmp ah, 0E0h ; IS IT KEYPAD ENTER OR / ? 2421 <1> jne short _KIO_S2 ; NO, CONTINUE 2422 <1> cmp al, 0Dh ; KEYPAD ENTER CODE? 2423 <1> je short _KIO_S1 ; YES, MASSAGE A BIT 2424 <1> cmp al, 0Ah ; CTRL KEYPAD ENTER CODE? 2425 <1> je short _KIO_S1 ; YES, MASSAGE THE SAME 2426 <1> mov ah, 35h ; NO, MUST BE KEYPAD / 2427 <1> _kio_ret: ; 03/12/2014 2428 <1> clc 2429 <1> retn 2430 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2431 <1> _KIO_S1: 2432 <1> mov ah, 1Ch ; CONVERT TO COMPATIBLE OUTPUT 2433 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2434 <1> retn 2435 <1> _KIO_S2: 2436 <1> cmp ah, 84h ; IS IT ONE OF EXTENDED ONES? 2437 <1> ja short _KIO_DIS ; YES, THROW AWAY AND GET ANOTHER CHAR 2438 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2439 <1> jne short _KIO_S3 ; NO, TRY LAST TEST 2440 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2441 <1> jz short _KIO_USE ; PASS THIS ON UNCHANGED 2442 <1> jmp short _KIO_DIS ; THROW AWAY THE REST 2443 <1> _KIO_S3: 2444 <1> cmp al, 0E0h ; IS IT AN EXTENSION OF A PREVIOUS ONE? 2445 <1> ;jne short _KIO_USE ; NO, MUST BE A STANDARD CODE 2446 <1> jne short _kio_ret 2447 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2448 <1> jz short _KIO_USE ; JUMP IF AH = 0 2449 <1> xor al, al ; CONVERT TO COMPATIBLE OUTPUT 2450 <1> ;jmp short _KIO_USE ; PASS IT ON TO CALLER 2451 <1> _KIO_USE: 2452 <1> ;clc ; CLEAR CARRY TO INDICATE GOOD CODE 2453 <1> retn ; RETURN 2454 <1> _KIO_DIS: 2455 <1> stc ; SET CARRY TO INDICATE DISCARD CODE 2456 <1> retn ; RETURN 2457 <1> 2458 <1> %endif 2459 <1> 2460 <1> ;----- INCREMENT BUFFER POINTER ROUTINE ----- 2461 <1> _K4: 2462 00000C4D 43 <1> inc ebx 2463 00000C4E 43 <1> inc ebx ; MOVE TO NEXT WORD IN LIST 2464 00000C4F 3B1D[8C5B0000] <1> cmp ebx, [BUFFER_END] ; AT END OF BUFFER? 2465 <1> ;jne short _K5 ; NO, CONTINUE 2466 00000C55 7206 <1> jb short _K5 2467 00000C57 8B1D[885B0000] <1> mov ebx, [BUFFER_START] ; YES, RESET TO BUFFER BEGINNING 2468 <1> _K5: 2469 00000C5D C3 <1> retn 2470 <1> 2471 <1> ; 20/02/2015 2472 <1> ; 05/12/2014 2473 <1> ; 26/08/2014 2474 <1> ; KEYBOARD (HARDWARE) INTERRUPT - IRQ LEVEL 1 2475 <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014) 2476 <1> ; 2477 <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 2478 <1> ; rombios source code (06/10/1985) 2479 <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1) 2480 <1> 2481 <1> ;--------- 8042 COMMANDS ------------------------------------------------------- 2482 <1> ENA_KBD equ 0AEh ; ENABLE KEYBOARD COMMAND 2483 <1> DIS_KBD equ 0ADh ; DISABLE KEYBOARD COMMAND 2484 <1> SHUT_CMD equ 0FEh ; CAUSE A SHUTDOWN COMMAND 2485 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2486 <1> STATUS_PORT equ 064h ; 8042 STATUS PORT 2487 <1> INPT_BUF_FULL equ 00000010b ; 1 = +INPUT BUFFER FULL 2488 <1> PORT_A equ 060h ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2489 <1> ;---------- 8042 KEYBOARD RESPONSE --------------------------------------------- 2490 <1> KB_ACK equ 0FAh ; ACKNOWLEDGE PROM TRANSMISSION 2491 <1> KB_RESEND equ 0FEh ; RESEND REQUEST 2492 <1> KB_OVER_RUN equ 0FFh ; OVER RUN SCAN CODE 2493 <1> ;---------- KEYBOARD/LED COMMANDS ---------------------------------------------- 2494 <1> KB_ENABLE equ 0F4h ; KEYBOARD ENABLE 2495 <1> LED_CMD equ 0EDh ; LED WRITE COMMAND 2496 <1> KB_TYPA_RD equ 0F3h ; TYPAMATIC RATE/DELAY COMMAND 2497 <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------ 2498 <1> NUM_KEY equ 69 ; SCAN CODE FOR NUMBER LOCK KEY 2499 <1> SCROLL_KEY equ 70 ; SCAN CODE FOR SCROLL LOCK KEY 2500 <1> ALT_KEY equ 56 ; SCAN CODE FOR ALTERNATE SHIFT KEY 2501 <1> CTL_KEY equ 29 ; SCAN CODE FOR CONTROL KEY 2502 <1> CAPS_KEY equ 58 ; SCAN CODE FOR SHIFT LOCK KEY 2503 <1> DEL_KEY equ 83 ; SCAN CODE FOR DELETE KEY 2504 <1> INS_KEY equ 82 ; SCAN CODE FOR INSERT KEY 2505 <1> LEFT_KEY equ 42 ; SCAN CODE FOR LEFT SHIFT 2506 <1> RIGHT_KEY equ 54 ; SCAN CODE FOR RIGHT SHIFT 2507 <1> SYS_KEY equ 84 ; SCAN CODE FOR SYSTEM KEY 2508 <1> ;---------- ENHANCED KEYBOARD SCAN CODES --------------------------------------- 2509 <1> ID_1 equ 0ABh ; 1ST ID CHARACTER FOR KBX 2510 <1> ID_2 equ 041h ; 2ND ID CHARACTER FOR KBX 2511 <1> ID_2A equ 054h ; ALTERNATE 2ND ID CHARACTER FOR KBX 2512 <1> F11_M equ 87 ; F11 KEY MAKE 2513 <1> F12_M equ 88 ; F12 KEY MAKE 2514 <1> MC_E0 equ 224 ; GENERAL MARKER CODE 2515 <1> MC_E1 equ 225 ; PAUSE KEY MARKER CODE 2516 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG---------------------------------------- 2517 <1> RIGHT_SHIFT equ 00000001b ; RIGHT SHIFT KEY DEPRESSED 2518 <1> LEFT_SHIFT equ 00000010b ; LEFT SHIFT KEY DEPRESSED 2519 <1> CTL_SHIFT equ 00000100b ; CONTROL SHIFT KEY DEPRESSED 2520 <1> ALT_SHIFT equ 00001000b ; ALTERNATE SHIFT KEY DEPRESSED 2521 <1> SCROLL_STATE equ 00010000b ; SCROLL LOCK STATE IS ACTIVE 2522 <1> NUM_STATE equ 00100000b ; NUM LOCK STATE IS ACTIVE 2523 <1> CAPS_STATE equ 01000000b ; CAPS LOCK STATE IS ACTIVE 2524 <1> INS_STATE equ 10000000b ; INSERT STATE IS ACTIVE 2525 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG_1 ------------------------------------- 2526 <1> L_CTL_SHIFT equ 00000001b ; LEFT CTL KEY DOWN 2527 <1> L_ALT_SHIFT equ 00000010b ; LEFT ALT KEY DOWN 2528 <1> SYS_SHIFT equ 00000100b ; SYSTEM KEY DEPRESSED AND HELD 2529 <1> HOLD_STATE equ 00001000b ; SUSPEND KEY HAS BEEN TOGGLED 2530 <1> SCROLL_SHIFT equ 00010000b ; SCROLL LOCK KEY IS DEPRESSED 2531 <1> NUM_SHIFT equ 00100000b ; NUM LOCK KEY IS DEPRESSED 2532 <1> CAPS_SHIFT equ 01000000b ; CAPS LOCK KEY IS DEPRE55ED 2533 <1> INS_SHIFT equ 10000000b ; INSERT KEY IS DEPRESSED 2534 <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 ----------------------------------- 2535 <1> KB_LEDS equ 00000111b ; KEYBOARD LED STATE BITS 2536 <1> ; equ 00000001b ; SCROLL LOCK INDICATOR 2537 <1> ; equ 00000010b ; NUM LOCK INDICATOR 2538 <1> ; equ 00000100b ; CAPS LOCK INDICATOR 2539 <1> ; equ 00001000b ; RESERVED (MUST BE ZERO) 2540 <1> KB_FA equ 00010000b ; ACKNOWLEDGMENT RECEIVED 2541 <1> KB_FE equ 00100000b ; RESEND RECEIVED FLAG 2542 <1> KB_PR_LED equ 01000000b ; MODE INDICATOR UPDATE 2543 <1> KB_ERR equ 10000000b ; KEYBOARD TRANSMIT ERROR FLAG 2544 <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 ----------------------------------- 2545 <1> LC_E1 equ 00000001b ; LAST CODE WAS THE E1 HIDDEN CODE 2546 <1> LC_E0 equ 00000010b ; LAST CODE WAS THE E0 HIDDEN CODE 2547 <1> R_CTL_SHIFT equ 00000100b ; RIGHT CTL KEY DOWN 2548 <1> R_ALT_SHIFT equ 00001000b ; RIGHT ALT KEY DOWN 2549 <1> GRAPH_ON equ 00001000b ; ALT GRAPHICS KEY DOWN (WT ONLY) 2550 <1> KBX equ 00010000b ; ENHANCED KEYBOARD INSTALLED 2551 <1> SET_NUM_LK equ 00100000b ; FORCE NUM LOCK IF READ ID AND KBX 2552 <1> LC_AB equ 01000000b ; LAST CHARACTER WAS FIRST ID CHARACTER 2553 <1> RD_ID equ 10000000b ; DOING A READ ID (MUST BE BIT0) 2554 <1> ; 2555 <1> ;----------- INTERRUPT EQUATES ------------------------------------------------- 2556 <1> EOI equ 020h ; END OF INTERRUPT COMMAND TO 8259 2557 <1> INTA00 equ 020h ; 8259 PORT 2558 <1> 2559 <1> kb_int: 2560 <1> 2561 <1> ; 13/06/2022 2562 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2563 <1> ; 17/10/2015 ('ctrlbrk') 2564 <1> ; 05/12/2014 2565 <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2566 <1> ; instead of pc-at bios - 1985-) 2567 <1> ; 26/08/2014 2568 <1> ; 2569 <1> ; 03/06/86 KEYBOARD BIOS 2570 <1> ; 2571 <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------ 2572 <1> ; ; 2573 <1> ; KEYBOARD INTERRUPT ROUTINE ; 2574 <1> ; ; 2575 <1> ;-------------------------------------------------------------------------------- 2576 <1> 2577 <1> KB_INT_1: 2578 00000C5E FB <1> sti ; ENABLE INTERRUPTS 2579 <1> ;push ebp 2580 00000C5F 50 <1> push eax 2581 00000C60 53 <1> push ebx 2582 00000C61 51 <1> push ecx 2583 00000C62 52 <1> push edx 2584 00000C63 56 <1> push esi 2585 00000C64 57 <1> push edi 2586 00000C65 1E <1> push ds 2587 00000C66 06 <1> push es 2588 00000C67 FC <1> cld ; FORWARD DIRECTION 2589 00000C68 66B81000 <1> mov ax, KDATA 2590 00000C6C 8ED8 <1> mov ds, ax 2591 00000C6E 8EC0 <1> mov es, ax 2592 <1> ; 2593 <1> ;----- WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED 2594 00000C70 B0AD <1> mov al, DIS_KBD ; DISABLE THE KEYBOARD COMMAND 2595 00000C72 E852050000 <1> call SHIP_IT ; EXECUTE DISABLE 2596 00000C77 FA <1> cli ; DISABLE INTERRUPTS 2597 00000C78 B900000100 <1> mov ecx, 10000h ; SET MAXIMUM TIMEOUT 2598 <1> KB_INT_01: 2599 00000C7D E464 <1> in al, STATUS_PORT ; READ ADAPTER STATUS 2600 00000C7F A802 <1> test al, INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT 2601 00000C81 E0FA <1> loopnz KB_INT_01 ; WAIT FOR COMMAND TO BE ACCEPTED 2602 <1> ; 2603 <1> ;----- READ CHARACTER FROM KEYBOARD INTERFACE 2604 00000C83 E460 <1> in al, PORT_A ; READ IN THE CHARACTER 2605 <1> ; 2606 <1> ;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 2607 <1> ;mov ah, 04Fh ; SYSTEM INTERCEPT - KEY CODE FUNCTION 2608 <1> ;stc ; SET CY=1 (IN CASE OF IRET) 2609 <1> ;int 15h ; CASETTE CALL (AL)=KEY SCAN CODE 2610 <1> ; ; RETURNS CY=1 FOR INVALID FUNCTION 2611 <1> ;jc KB_INT_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) 2612 <1> ;jmp K26 ; EXIT IF SYSTEM HANDLES SCAN CODE 2613 <1> ; ; EXIT HANDLES HARDWARE EOI AND ENABLE 2614 <1> ; 2615 <1> ;----- CHECK FOR A RESEND COMMAND TO KEYBOARD 2616 <1> KB_INT_02: ; (AL)= SCAN CODE 2617 00000C85 FB <1> sti ; ENABLE INTERRUPTS AGAIN 2618 00000C86 3CFE <1> cmp al, KB_RESEND ; IS THE INPUT A RESEND 2619 00000C88 7411 <1> je short KB_INT_4 ; GO IF RESEND 2620 <1> ; 2621 <1> ;----- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD 2622 00000C8A 3CFA <1> cmp al, KB_ACK ; IS THE INPUT AN ACKNOWLEDGE 2623 00000C8C 751A <1> jne short KB_INT_2 ; GO IF NOT 2624 <1> ; 2625 <1> ;----- A COMMAND TO THE KEYBOARD WAS ISSUED 2626 00000C8E FA <1> cli ; DISABLE INTERRUPTS 2627 00000C8F 800D[855B0000]10 <1> or byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED 2628 00000C96 E963020000 <1> jmp K26 ; RETURN IF NOT (ACK RETURNED FOR DATA) 2629 <1> ; 2630 <1> ;----- RESEND THE LAST BYTE 2631 <1> KB_INT_4: 2632 00000C9B FA <1> cli ; DISABLE INTERRUPTS 2633 00000C9C 800D[855B0000]20 <1> or byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED 2634 00000CA3 E956020000 <1> jmp K26 ; RETURN IF NOT ACK RETURNED FOR DATA) 2635 <1> ; 2636 <1> ;----- UPDATE MODE INDICATORS IF CHANGE IN STATE 2637 <1> KB_INT_2: 2638 <1> ;push ax ; SAVE DATA IN 2639 <1> ; 24/12/2021 2640 00000CA8 50 <1> push eax 2641 00000CA9 E8E1050000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2642 00000CAE 8A1D[855B0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2643 00000CB4 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2644 00000CB6 80E307 <1> and bl, KB_LEDS ; ISOLATE INDICATOR BITS 2645 00000CB9 7405 <1> jz short UP0 ; IF NO CHANGE BYPASS UPDATE 2646 00000CBB E864050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2647 <1> UP0: 2648 <1> ;pop ax ; RESTORE DATA IN 2649 <1> ; 24/12/2021 2650 00000CC0 58 <1> pop eax 2651 <1> ;------------------------------------------------------------------------ 2652 <1> ; START OF KEY PROCESSING ; 2653 <1> ;------------------------------------------------------------------------ 2654 00000CC1 88C4 <1> mov ah, al ; SAVE SCAN CODE IN AH ALSO 2655 <1> ; 2656 <1> ;----- TEST FOR OVERRUN SCAN CODE FROM KEYBOARD 2657 00000CC3 3CFF <1> cmp al, KB_OVER_RUN ; IS THIS AN OVERRUN CHAR 2658 <1> ;je K62 ; BUFFER_FULL_BEEP 2659 <1> ; 24/12/2021 2660 00000CC5 7505 <1> jne short K16 2661 00000CC7 E9E9040000 <1> jmp K62 2662 <1> K16: 2663 00000CCC 8A3D[865B0000] <1> mov bh, [KB_FLAG_3] ; LOAD FLAGS FOR TESTING 2664 <1> ; 2665 <1> ;----- TEST TO SEE IF A READ_ID IS IN PROGRESS 2666 00000CD2 F6C7C0 <1> test bh, RD_ID+LC_AB ; ARE WE DOING A READ ID? 2667 00000CD5 7442 <1> jz short NOT_ID ; CONTINUE IF NOT 2668 00000CD7 7914 <1> jns short TST_ID_2 ; IS THE RD_ID FLAG ON? 2669 00000CD9 3CAB <1> cmp al, ID_1 ; IS THIS THE 1ST ID CHARACTER? 2670 00000CDB 7507 <1> jne short RST_RD_ID 2671 00000CDD 800D[865B0000]40 <1> or byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK 2672 <1> RST_RD_ID: 2673 00000CE4 8025[865B0000]7F <1> and byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG 2674 00000CEB EB27 <1> jmp short ID_EX ; AND EXIT 2675 <1> ; 24/12/2021 2676 <1> ;jmp K26 2677 <1> ; 2678 <1> TST_ID_2: 2679 00000CED 8025[865B0000]BF <1> and byte [KB_FLAG_3], ~LC_AB ; RESET FLAG 2680 00000CF4 3C54 <1> cmp al, ID_2A ; IS THIS THE 2ND ID CHARACTER? 2681 00000CF6 7415 <1> je short KX_BIT ; JUMP IF SO 2682 00000CF8 3C41 <1> cmp al, ID_2 ; IS THIS THE 2ND ID CHARACTER? 2683 00000CFA 7518 <1> jne short ID_EX ; LEAVE IF NOT 2684 <1> ; 24/12/2021 2685 <1> ;jne K26 2686 <1> ; 2687 <1> ;----- A READ ID SAID THAT IT WAS ENHANCED KEYBOARD 2688 00000CFC F6C720 <1> test bh, SET_NUM_LK ; SHOULD WE SET NUM LOCK? 2689 00000CFF 740C <1> jz short KX_BIT ; EXIT IF NOT 2690 00000D01 800D[835B0000]20 <1> or byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON 2691 00000D08 E817050000 <1> call SND_LED ; GO SET THE NUM LOCK INDICATOR 2692 <1> KX_BIT: 2693 00000D0D 800D[865B0000]10 <1> or byte [KB_FLAG_3], KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND 2694 00000D14 E9E5010000 <1> ID_EX: jmp K26 ; EXIT 2695 <1> ; 2696 <1> NOT_ID: 2697 00000D19 3CE0 <1> cmp al, MC_E0 ; IS THIS THE GENERAL MARKER CODE? 2698 00000D1B 750E <1> jne short TEST_E1 2699 00000D1D 800D[865B0000]12 <1> or byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND 2700 00000D24 EB10 <1> jmp short EXIT ; THROW AWAY THIS CODE 2701 <1> ; 24/12/2021 2702 00000D26 E9DA010000 <1> jmp K26A 2703 <1> TEST_E1: 2704 00000D2B 3CE1 <1> cmp al, MC_E1 ; IS THIS THE PAUSE KEY? 2705 00000D2D 750C <1> jne short NOT_HC 2706 00000D2F 800D[865B0000]11 <1> or byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND 2707 00000D36 E9CA010000 <1> EXIT: jmp K26A ; THROW AWAY THIS CODE 2708 <1> ; 2709 <1> NOT_HC: 2710 00000D3B 247F <1> and al, 07Fh ; TURN OFF THE BREAK BIT 2711 00000D3D F6C702 <1> test bh, LC_E0 ; LAST CODE THE E0 MARKER CODE 2712 00000D40 740D <1> jz short NOT_LC_E0 ; JUMP IF NOT 2713 <1> ; 2714 00000D42 BF[6E5A0000] <1> mov edi, _K6+6 ; IS THIS A SHIFT KEY? 2715 00000D47 AE <1> scasb 2716 <1> ;je K26 ; K16B ; YES, THROW AWAY & RESET FLAG 2717 <1> ; 24/12/2021 2718 00000D48 7458 <1> je short K16B 2719 00000D4A AE <1> scasb 2720 00000D4B 756A <1> jne short K16A ; NO, CONTINUE KEY PROCESSING 2721 00000D4D EB53 <1> jmp short K16B ; YES, THROW AWAY & RESET FLAG 2722 <1> ; 24/12/2021 2723 <1> ;jmp K26 2724 <1> ; 2725 <1> NOT_LC_E0: 2726 00000D4F F6C701 <1> test bh, LC_E1 ; LAST CODE THE E1 MARKER CODE? 2727 00000D52 7425 <1> jz short T_SYS_KEY ; JUMP IF NOT 2728 00000D54 B904000000 <1> mov ecx, 4 ; LENGHT OF SEARCH 2729 00000D59 BF[6C5A0000] <1> mov edi, _K6+4 ; IS THIS AN ALT, CTL, OR SHIFT? 2730 00000D5E F2AE <1> repne scasb ; CHECK IT 2731 00000D60 74D4 <1> je short EXIT ; THROW AWAY IF SO 2732 <1> ; 24/12/2021 2733 <1> ;je K26A 2734 <1> ; 2735 00000D62 3C45 <1> cmp al, NUM_KEY ; IS IT THE PAUSE KEY? 2736 00000D64 753C <1> jne short K16B ; NO, THROW AWAY & RESET FLAG 2737 <1> ; 24/12/2021 2738 <1> ;jne K26 2739 00000D66 F6C480 <1> test ah, 80h ; YES, IS IT THE BREAK OF THE KEY? 2740 00000D69 7537 <1> jnz short K16B ; YES, THROW THIS AWAY, TOO 2741 <1> ; 24/12/2021 2742 <1> ;jnz K26 2743 <1> ; 20/02/2015 2744 00000D6B F605[845B0000]08 <1> test byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY? 2745 00000D72 752E <1> jnz short K16B ; YES, THROW AWAY 2746 <1> ; 24/12/2021 2747 <1> ;jnz K26 2748 00000D74 E9D2020000 <1> jmp K39P ; NO, THIS IS THE REAL PAUSE STATE 2749 <1> ; 2750 <1> ;----- TEST FOR SYSTEM KEY 2751 <1> T_SYS_KEY: 2752 00000D79 3C54 <1> cmp al, SYS_KEY ; IS IT THE SYSTEM KEY? 2753 00000D7B 753A <1> jnz short K16A ; CONTINUE IF NOT 2754 <1> ; 2755 00000D7D F6C480 <1> test ah, 80h ; CHECK IF THIS A BREAK CODE 2756 00000D80 7525 <1> jnz short K16C ; DO NOT TOUCH SYSTEM INDICATOR IF TRUE 2757 <1> ; 2758 00000D82 F605[845B0000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 2759 00000D89 7517 <1> jnz short K16B ; IF YES, DO NOT PROCESS SYSTEM INDICATOR 2760 <1> ;jnz K26 2761 <1> ; 2762 00000D8B 800D[845B0000]04 <1> or byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED 2763 00000D92 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2764 00000D94 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2765 <1> ; INTERRUPT-RETURN-NO-EOI 2766 00000D96 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2767 00000D98 E82C040000 <1> call SHIP_IT ; EXECUTE ENABLE 2768 <1> ; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!! 2769 <1> ;mov al, 8500h ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY 2770 <1> ;sti ; MAKE SURE INTERRUPTS ENABLED 2771 <1> ;int 15h ; USER INTERRUPT 2772 00000D9D E96F010000 <1> jmp K27A ; END PROCESSING 2773 <1> ; 2774 00000DA2 E957010000 <1> K16B: jmp K26 ; IGNORE SYSTEM KEY 2775 <1> ; 2776 <1> K16C: 2777 00000DA7 8025[845B0000]FB <1> and byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN 2778 00000DAE B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2779 00000DB0 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2780 <1> ; INTERRUPT-RETURN-NO-EOI 2781 <1> ;mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2782 <1> ;call SHIP_IT ; EXECUTE ENABLE 2783 <1> ; 2784 <1> ;mov ax, 8501h ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY 2785 <1> ;sti ; MAKE SURE INTERRUPTS ENABLED 2786 <1> ;int 15h ; USER INTERRUPT 2787 <1> ;jmp K27A ; IGNORE SYSTEM KEY 2788 <1> ; 2789 00000DB2 E953010000 <1> jmp K27 ; IGNORE SYSTEM KEY 2790 <1> ; 2791 <1> ;----- TEST FOR SHIFT KEYS 2792 <1> K16A: 2793 00000DB7 8A1D[835B0000] <1> mov bl, [KB_FLAG] ; PUT STATE FLAGS IN BL 2794 00000DBD BF[685A0000] <1> mov edi, _K6 ; SHIFT KEY TABLE offset 2795 00000DC2 B908000000 <1> mov ecx, _K6L ; LENGTH 2796 00000DC7 F2AE <1> repne scasb ; LOOK THROUGH THE TABLE FOR A MATCH 2797 00000DC9 88E0 <1> mov al, ah ; RECOVER SCAN CODE 2798 <1> ;jne K25 ; IF NO MATCH, THEN SHIFT NOT FOUND 2799 <1> ; 24/12/2021 2800 00000DCB 7405 <1> je short K17 2801 00000DCD E914010000 <1> jmp K25 2802 <1> ; 2803 <1> ;------ SHIFT KEY FOUND 2804 <1> K17: 2805 00000DD2 81EF[695A0000] <1> sub edi, _K6+1 ; ADJUST PTR TO SCAN CODE MATCH 2806 00000DD8 8AA7[705A0000] <1> mov ah, [edi+_K7] ; GET MASK INTO AH 2807 00000DDE B102 <1> mov cl, 2 ; SETUP COUNT FOR FLAG SHIFTS 2808 00000DE0 A880 <1> test al, 80h ; TEST FOR BREAK KEY 2809 <1> ;jnz K23 ; JUMP OF BREAK 2810 <1> ; 24/12/2021 2811 00000DE2 7405 <1> jz short K17C 2812 00000DE4 E999000000 <1> jmp K23 2813 <1> ; 2814 <1> ;----- SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE 2815 <1> K17C: 2816 00000DE9 80FC10 <1> cmp ah, SCROLL_SHIFT 2817 00000DEC 732C <1> jae short K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY 2818 <1> ; 2819 <1> ;----- PLAIN SHIFT KEY, SET SHIFT ON 2820 00000DEE 0825[835B0000] <1> or [KB_FLAG], ah ; TURN ON SHIFT BIT 2821 00000DF4 A80C <1> test al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL? 2822 00000DF6 7505 <1> jnz short K17D ; YES, MORE FLAGS TO SET 2823 <1> ;jz K26 ; NO, INTERRUPT RETURN 2824 <1> ; 24/12/2021 2825 00000DF8 E901010000 <1> jmp K26 2826 <1> K17D: 2827 00000DFD F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF NEW KEYS? 2828 00000E00 740B <1> jz short K17E ; NO, JUMP 2829 00000E02 0825[865B0000] <1> or [KB_FLAG_3], ah ; SET BITS FOR RIGHT CTRL, ALT 2830 00000E08 E9F1000000 <1> jmp K26 ; INTERRUPT RETURN 2831 <1> K17E: 2832 00000E0D D2EC <1> shr ah, cl ; MOVE FLAG BITS TWO POSITIONS 2833 00000E0F 0825[845B0000] <1> or [KB_FLAG_1], ah ; SET BITS FOR LEFT CTRL, ALT 2834 00000E15 E9E4000000 <1> jmp K26 2835 <1> ; 2836 <1> ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT 2837 <1> K18: ; SHIFT-TOGGLE 2838 00000E1A F6C304 <1> test bl, CTL_SHIFT ; CHECK CTL SHIFT STATE 2839 00000E1D 7405 <1> jz short K18A ; JUMP IF NOT CTL STATE 2840 <1> ;jnz K25 ; JUMP IF CTL STATE 2841 <1> ; 24/12/2021 2842 00000E1F E9C2000000 <1> jmp K25 2843 <1> K18A: 2844 00000E24 3C52 <1> cmp al, INS_KEY ; CHECK FOR INSERT KEY 2845 00000E26 7525 <1> jne short K22 ; JUMP IF NOT INSERT KEY 2846 00000E28 F6C308 <1> test bl, ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT 2847 00000E2B 7405 <1> jz short K18B ; JUMP IF NOT ALTERNATE SHIFT 2848 <1> ;jnz K25 ; JUMP IF ALTERNATE SHIFT 2849 <1> ; 24/12/2021 2850 00000E2D E9B4000000 <1> jmp K25 2851 <1> K18B: 2852 00000E32 F6C702 <1> test bh, LC_E0 ;20/02/2015 ; IS THIS NEW INSERT KEY? 2853 00000E35 7516 <1> jnz short K22 ; YES, THIS ONE'S NEVER A '0' 2854 <1> K19: 2855 00000E37 F6C320 <1> test bl, NUM_STATE ; CHECK FOR BASE STATE 2856 00000E3A 750C <1> jnz short K21 ; JUMP IF NUM LOCK IS ON 2857 00000E3C F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE 2858 00000E3F 740C <1> jz short K22 ; JUMP IF BASE STATE 2859 <1> K20: ; NUMERIC ZERO, NOT INSERT KEY 2860 00000E41 88C4 <1> mov ah, al ; PUT SCAN CODE BACK IN AH 2861 00000E43 E99E000000 <1> jmp K25 ; NUMERAL '0', STNDRD. PROCESSING 2862 <1> K21: ; MIGHT BE NUMERIC 2863 00000E48 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 2864 00000E4B 74F4 <1> jz short K20 ; IS NUMERIC, STD. PROC. 2865 <1> ; 2866 <1> K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT 2867 00000E4D 8425[845B0000] <1> test ah, [KB_FLAG_1] ; IS KEY ALREADY DEPRESSED 2868 <1> ;jnz K26 2869 <1> ; 24/12/2021 2870 00000E53 7405 <1> jz short K22A 2871 00000E55 E9A4000000 <1> jmp K26 ; JUMP IF KEY ALREADY DEPRESSED 2872 <1> K22A: 2873 00000E5A 0825[845B0000] <1> or [KB_FLAG_1], ah ; INDICATE THAT THE KEY IS DEPRESSED 2874 00000E60 3025[835B0000] <1> xor [KB_FLAG], ah ; TOGGLE THE SHIFT STATE 2875 <1> ; 2876 <1> ;----- TOGGLE LED IF CAPS, NUM OR SCROLL KEY DEPRESSED 2877 00000E66 F6C470 <1> test ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? 2878 00000E69 7407 <1> jz short K22B ; GO IF NOT 2879 <1> ; 2880 <1> ; 24/12/2021 2881 <1> ;push ax ; SAVE SCAN CODE AND SHIFT MASK 2882 00000E6B 50 <1> push eax 2883 00000E6C E8B3030000 <1> call SND_LED ; GO TURN MODE INDICATORS ON 2884 <1> ;pop ax ; RESTORE SCAN CODE 2885 00000E71 58 <1> pop eax 2886 <1> K22B: 2887 00000E72 3C52 <1> cmp al, INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY 2888 <1> ;jne K26 ; JUMP IF NOT INSERT KEY 2889 <1> ; 24/12/2021 2890 00000E74 7405 <1> je short K22C 2891 00000E76 E983000000 <1> jmp K26 ; JUMP IF NOT INSERT KEY 2892 <1> K22C: 2893 00000E7B 88C4 <1> mov ah, al ; SCAN CODE IN BOTH HALVES OF AX 2894 00000E7D E999000000 <1> jmp K28 ; FLAGS UPDATED, PROC. FOR BUFFER 2895 <1> ; 2896 <1> ;----- BREAK SHIFT FOUND 2897 <1> K23: ; BREAK-SHIFT-FOUND 2898 00000E82 80FC10 <1> cmp ah, SCROLL_SHIFT ; IS THIS A TOGGLE KEY 2899 00000E85 F6D4 <1> not ah ; INVERT MASK 2900 00000E87 7355 <1> jae short K24 ; YES, HANDLE BREAK TOGGLE 2901 00000E89 2025[835B0000] <1> and [KB_FLAG], ah ; TURN OFF SHIFT BIT 2902 00000E8F 80FCFB <1> cmp ah, ~CTL_SHIFT ; IS THIS ALT OR CTL? 2903 00000E92 7730 <1> ja short K23D ; NO, ALL DONE 2904 <1> ; 2905 00000E94 F6C702 <1> test bh, LC_E0 ; 2ND ALT OR CTL? 2906 00000E97 7408 <1> jz short K23A ; NO, HANSLE NORMALLY 2907 00000E99 2025[865B0000] <1> and [KB_FLAG_3], ah ; RESET BIT FOR RIGHT ALT OR CTL 2908 00000E9F EB08 <1> jmp short K23B ; CONTINUE 2909 <1> K23A: 2910 00000EA1 D2FC <1> sar ah, cl ; MOVE THE MASK BIT TWO POSITIONS 2911 00000EA3 2025[845B0000] <1> and [KB_FLAG_1], ah ; RESET BIT FOR LEFT ALT AND CTL 2912 <1> K23B: 2913 00000EA9 88C4 <1> mov ah, al ; SAVE SCAN CODE 2914 00000EAB A0[865B0000] <1> mov al, [KB_FLAG_3] ; GET RIGHT ALT & CTRL FLAGS 2915 00000EB0 D2E8 <1> shr al, cl ; MOVE TO BITS 1 & 0 2916 00000EB2 0A05[845B0000] <1> or al, [KB_FLAG_1] ; PUT IN LEFT ALÞT & CTL FLAGS 2917 00000EB8 D2E0 <1> shl al, cl ; MOVE BACK TO BITS 3 & 2 2918 00000EBA 240C <1> and al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE 2919 00000EBC 0805[835B0000] <1> or [KB_FLAG], al ; PUT RESULT IN THE REAL FLAGS 2920 00000EC2 88E0 <1> mov al, ah 2921 <1> K23D: 2922 00000EC4 3CB8 <1> cmp al, ALT_KEY+80h ; IS THIS ALTERNATE SHIFT RELEASE 2923 00000EC6 7536 <1> jne short K26 ; INTERRUPT RETURN 2924 <1> ; 2925 <1> ;----- ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER 2926 00000EC8 A0[875B0000] <1> mov al, [ALT_INPUT] 2927 00000ECD B400 <1> mov ah, 0 ; SCAN CODE OF 0 2928 00000ECF 8825[875B0000] <1> mov [ALT_INPUT], ah ; ZERO OUT THE FIELD 2929 00000ED5 3C00 <1> cmp al, 0 ; WAS THE INPUT = 0? 2930 00000ED7 7425 <1> je short K26 ; INTERRUPT_RETURN 2931 00000ED9 E9B4020000 <1> jmp K61 ; IT WASN'T, SO PUT IN BUFFER 2932 <1> ; 2933 <1> K24: ; BREAK-TOGGLE 2934 00000EDE 2025[845B0000] <1> and [KB_FLAG_1], ah ; INDICATE NO LONGER DEPRESSED 2935 00000EE4 EB18 <1> jmp short K26 ; INTERRUPT_RETURN 2936 <1> ; 2937 <1> ;----- TEST FOR HOLD STATE 2938 <1> ; AL, AH = SCAN CODE 2939 <1> K25: ; NO-SHIFT-FOUND 2940 00000EE6 3C80 <1> cmp al, 80h ; TEST FOR BREAK KEY 2941 00000EE8 7314 <1> jae short K26 ; NOTHING FOR BREAK CHARS FROM HERE ON 2942 00000EEA F605[845B0000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE 2943 00000EF1 7428 <1> jz short K28 ; BRANCH AROUND TEST IF NOT 2944 00000EF3 3C45 <1> cmp al, NUM_KEY 2945 00000EF5 7407 <1> je short K26 ; CAN'T END HOLD ON NUM_LOCK 2946 00000EF7 8025[845B0000]F7 <1> and byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT 2947 <1> ; 2948 <1> K26: 2949 00000EFE 8025[865B0000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 2950 <1> K26A: ; INTERRUPT-RETURN 2951 00000F05 FA <1> cli ; TURN OFF INTERRUPTS 2952 00000F06 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 2953 00000F08 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 2954 <1> K27: ; INTERRUPT-RETURN-NO-EOI 2955 00000F0A B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 2956 00000F0C E8B8020000 <1> call SHIP_IT ; EXECUTE ENABLE 2957 <1> K27A: 2958 00000F11 FA <1> cli ; DISABLE INTERRUPTS 2959 00000F12 07 <1> pop es ; RESTORE REGISTERS 2960 00000F13 1F <1> pop ds 2961 00000F14 5F <1> pop edi 2962 00000F15 5E <1> pop esi 2963 00000F16 5A <1> pop edx 2964 00000F17 59 <1> pop ecx 2965 00000F18 5B <1> pop ebx 2966 00000F19 58 <1> pop eax 2967 <1> ;pop ebp 2968 00000F1A CF <1> iret ; RETURN 2969 <1> 2970 <1> ;----- NOT IN HOLD STATE 2971 <1> K28: ; NO-HOLD-STATE 2972 00000F1B 3C58 <1> cmp al, 88 ; TEST FOR OUT-OF-RANGE SCAN CODES 2973 00000F1D 77DF <1> ja short K26 ; IGNORE IF OUT-OF-RANGE 2974 <1> ; 2975 00000F1F F6C308 <1> test bl, ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT 2976 00000F22 740E <1> jz short K28A ; IF NOT ALTERNATE 2977 <1> ; 24/12/2021 2978 <1> ;jz K38 2979 <1> ; 2980 00000F24 F6C710 <1> test bh, KBX ; IS THIS THE ENCHANCED KEYBOARD? 2981 00000F27 740E <1> jz short K29 ; NO, ALT STATE IS REAL 2982 <1> ; 28/02/2015 2983 00000F29 F605[845B0000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN? 2984 00000F30 7405 <1> jz short K29 ; NO, ALT STATE IS REAL 2985 <1> ; 24/12/2021 2986 <1> ;jnz K38 ; YES, THIS IS PHONY ALT STATE 2987 <1> ; ; DUE TO PRESSING SYSREQ 2988 00000F32 E9CD000000 <1> K28A: jmp K38 2989 <1> ; 2990 <1> ;----- TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) 2991 <1> K29: ; TEST-RESET 2992 00000F37 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO? 2993 00000F3A 740B <1> jz short K31 ; NO_RESET 2994 00000F3C 3C53 <1> cmp al, DEL_KEY ; CTL-ALT STATE, TEST FOR DELETE KEY 2995 00000F3E 7507 <1> jne short K31 ; NO_RESET, IGNORE 2996 <1> ; 2997 <1> ;----- CTL-ALT-DEL HAS BEEN FOUND 2998 <1> ; 26/08/2014 2999 <1> cpu_reset: 3000 <1> ; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN) 3001 <1> ; Send FEh (system reset command) to the keyboard controller. 3002 00000F40 B0FE <1> mov al, SHUT_CMD ; SHUTDOWN COMMAND 3003 00000F42 E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROL PORT 3004 <1> khere: 3005 00000F44 F4 <1> hlt ; WAIT FOR 80286 RESET 3006 00000F45 EBFD <1> jmp short khere ; INSURE HALT 3007 <1> 3008 <1> ; 3009 <1> ;----- IN ALTERNATE SHIFT, RESET NOT FOUND 3010 <1> K31: ; NO-RESET 3011 00000F47 3C39 <1> cmp al, 57 ; TEST FOR SPACE KEY 3012 00000F49 7507 <1> jne short K311 ; NOT THERE 3013 00000F4B B020 <1> mov al, ' ' ; SET SPACE CHAR 3014 00000F4D E932020000 <1> jmp K57 ; BUFFER_FILL 3015 <1> K311: 3016 00000F52 3C0F <1> cmp al, 15 ; TEST FOR TAB KEY 3017 00000F54 7509 <1> jne short K312 ; NOT THERE 3018 00000F56 66B800A5 <1> mov ax, 0A500h ; SET SPECIAL CODE FOR ALT-TAB 3019 00000F5A E925020000 <1> jmp K57 ; BUFFER_FILL 3020 <1> K312: 3021 00000F5F 3C4A <1> cmp al, 74 ; TEST FOR KEY PAD - 3022 00000F61 7471 <1> je short K37B ; GO PROCESS 3023 00000F63 3C4E <1> cmp al, 78 ; TEST FOR KEY PAD + 3024 00000F65 746D <1> je short K37B ; GO PROCESS 3025 <1> ; 3026 <1> ;----- LOOK FOR KEY PAD ENTRY 3027 <1> K32: ; ALT-KEY-PAD 3028 00000F67 BF[445A0000] <1> mov edi, K30 ; ALT-INPUT-TABLE offset 3029 00000F6C B90A000000 <1> mov ecx, 10 ; LOOK FOR ENTRY USING KEYPAD 3030 00000F71 F2AE <1> repne scasb ; LOOK FOR MATCH 3031 00000F73 7523 <1> jne short K33 ; NO_ALT_KEYPAD 3032 00000F75 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF THE NEW KEYS? 3033 <1> ;jnz short K37C ; YES, JUMP, NOT NUMPAD KEY 3034 <1> ; 24/12/2021 3035 00000F78 751C <1> jnz short K32B 3036 00000F7A 81EF[455A0000] <1> sub edi, K30+1 ; DI NOW HAS ENTRY VALUE 3037 00000F80 A0[875B0000] <1> mov al, [ALT_INPUT] ; GET THE CURRENT BYTE 3038 00000F85 B40A <1> mov ah, 10 ; MULTIPLY BY 10 3039 00000F87 F6E4 <1> mul ah 3040 00000F89 6601F8 <1> add ax, di ; ADD IN THE LATEST ENTRY 3041 00000F8C A2[875B0000] <1> mov [ALT_INPUT], al ; STORE IT AWAY 3042 <1> K32A: 3043 00000F91 E968FFFFFF <1> jmp K26 ; THROW AWAY THAT KEYSTROKE 3044 <1> K32B: 3045 <1> ; 24/12/2021 3046 00000F96 EB66 <1> jmp K37C 3047 <1> ; 3048 <1> ;----- LOOK FOR SUPERSHIFT ENTRY 3049 <1> K33: ; NO-ALT-KEYPAD 3050 00000F98 C605[875B0000]00 <1> mov byte [ALT_INPUT], 0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT 3051 00000F9F B91A000000 <1> mov ecx, 26 ; (DI),(ES) ALREADY POINTING 3052 00000FA4 F2AE <1> repne scasb ; LOOK FOR MATCH IN ALPHABET 3053 00000FA6 744F <1> je short K37A ; MATCH FOUND, GO FILLL THE BUFFER 3054 <1> ; 3055 <1> ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT 3056 <1> K34: ; ALT-TOP-ROW 3057 00000FA8 3C02 <1> cmp al, 2 ; KEY WITH '1' ON IT 3058 00000FAA 7228 <1> jb short K37B ; MUST BE ESCAPE 3059 00000FAC 3C0D <1> cmp al, 13 ; IS IT IN THE REGION 3060 00000FAE 7705 <1> ja short K35 ; NO, ALT SOMETHING ELSE 3061 00000FB0 80C476 <1> add ah, 118 ; CONVERT PSEUDO SCAN CODE TO RANGE 3062 00000FB3 EB42 <1> jmp short K37A ; GO FILL THE BUFFER 3063 <1> ; 3064 <1> ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES 3065 <1> K35: ; ALT-FUNCTION 3066 00000FB5 3C57 <1> cmp al, F11_M ; IS IT F11? 3067 00000FB7 7209 <1> jb short K35A ; 20/02/2015 ; NO, BRANCH 3068 00000FB9 3C58 <1> cmp al, F12_M ; IS IT F12? 3069 00000FBB 7705 <1> ja short K35A ; 20/02/2015 ; NO, BRANCH 3070 00000FBD 80C434 <1> add ah, 52 ; CONVERT TO PSEUDO SCAN CODE 3071 00000FC0 EB35 <1> jmp short K37A ; GO FILL THE BUFFER 3072 <1> K35A: 3073 00000FC2 F6C702 <1> test bh, LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS? 3074 00000FC5 7425 <1> jz short K37 ; NO, JUMP 3075 00000FC7 3C1C <1> cmp al, 28 ; TEST FOR KEYPAD ENTER 3076 00000FC9 7510 <1> jne short K35B ; NOT THERE 3077 00000FCB 66B800A6 <1> mov ax, 0A600h ; SPECIAL CODE 3078 00000FCF E9B0010000 <1> jmp K57 ; BUFFER FILL 3079 <1> K37B: 3080 00000FD4 B0F0 <1> mov al, 0F0h ; USE SPECIAL ASCII CODE 3081 00000FD6 E9A9010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3082 <1> K35B: 3083 00000FDB 3C53 <1> cmp al, 83 ; TEST FOR DELETE KEY 3084 00000FDD 741F <1> je short K37C ; HANDLE WITH OTHER EDIT KEYS 3085 00000FDF 3C35 <1> cmp al, 53 ; TEST FOR KEYPAD / 3086 00000FE1 75AE <1> jne short K32A ; NOT THERE, NO OTHER E0 SPECIALS 3087 <1> ; 24/12/2021 3088 <1> ;jne K26 3089 00000FE3 66B800A4 <1> mov ax, 0A400h ; SPECIAL CODE 3090 00000FE7 E998010000 <1> jmp K57 ; BUFFER FILL 3091 <1> K37: 3092 00000FEC 3C3B <1> cmp al, 59 ; TEST FOR FUNCTION KEYS (F1) 3093 00000FEE 72E4 <1> jb short K37B ; NO FN, HANDLE W/OTHER EXTENDED 3094 00000FF0 3C44 <1> cmp al, 68 ; IN KEYPAD REGION? 3095 00000FF2 779D <1> ja short K32A ; IF SO, IGNORE 3096 <1> ; 13/06/2022 3097 <1> ;ja K26 3098 00000FF4 80C42D <1> add ah, 45 ; CONVERT TO PSEUDO SCAN CODE 3099 <1> K37A: 3100 00000FF7 B000 <1> mov al, 0 ; ASCII CODE OF ZERO 3101 00000FF9 E986010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3102 <1> K37C: 3103 00000FFE 0450 <1> add al, 80 ; CONVERT SCAN CODE (EDIT KEYS) 3104 00001000 88C4 <1> mov ah, al ; (SCAN CODE NOT IN AH FOR INSERT) 3105 00001002 EBF3 <1> jmp short K37A ; PUT IT IN THE BUFFER 3106 <1> ; 3107 <1> ;----- NOT IN ALTERNATE SHIFT 3108 <1> K38: ; NOT-ALT-SHIFT 3109 <1> ; BL STILL HAS SHIFT FLAGS 3110 00001004 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT? 3111 00001007 7505 <1> jnz short K38A ; YES, START PROCESSING 3112 <1> ;jz K44 ; NOT-CTL-SHIFT 3113 <1> ; 24/12/2021 3114 00001009 E9AB000000 <1> jmp K44 3115 <1> ; 3116 <1> ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS 3117 <1> ;----- TEST FOR BREAK 3118 <1> K38A: 3119 0000100E 3C46 <1> cmp al, SCROLL_KEY ; TEST FOR BREAK 3120 00001010 7530 <1> jne short K39 ; JUMP, NO-BREAK 3121 00001012 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3122 00001015 7405 <1> jz short K38B ; NO, BREAK IS VALID 3123 00001017 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3124 0000101A 7426 <1> jz short K39 ; NO-BREAK, TEST FOR PAUSE 3125 <1> K38B: 3126 0000101C 8B1D[905B0000] <1> mov ebx, [BUFFER_HEAD] ; RESET BUFFER TO EMPTY 3127 00001022 891D[945B0000] <1> mov [BUFFER_TAIL], ebx 3128 00001028 C605[825B0000]80 <1> mov byte [BIOS_BREAK], 80h ; TURN ON BIOS_BREAK BIT 3129 <1> ; 3130 <1> ;----- ENABLE KEYBOARD 3131 0000102F B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3132 00001031 E893010000 <1> call SHIP_IT ; EXECUTE ENABLE 3133 <1> ; 3134 <1> ; CTRL+BREAK code here !!! 3135 <1> ;int 1Bh ; BREAK INTERRUPT VECTOR 3136 <1> ; 17/10/2015 3137 00001036 E88C190000 <1> call ctrlbrk ; control+break subroutine 3138 <1> ; 3139 <1> ;sub ax, ax ; PUT OUT DUMMY CHARACTER 3140 <1> ; 24/12/2021 3141 0000103B 29C0 <1> sub eax, eax 3142 0000103D E942010000 <1> jmp K57 ; BUFFER_FILL 3143 <1> ; 3144 <1> ;----- TEST FOR PAUSE 3145 <1> K39: ; NO_BREAK 3146 00001042 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3147 00001045 7537 <1> jnz short K41 ; YES, THEN THIS CAN'T BE PAUSE 3148 00001047 3C45 <1> cmp al, NUM_KEY ; LOOK FOR PAUSE KEY 3149 00001049 7533 <1> jne short K41 ; NO-PAUSE 3150 <1> K39P: 3151 0000104B 800D[845B0000]08 <1> or byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG 3152 <1> ; 3153 <1> ;----- ENABLE KEYBOARD 3154 00001052 B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3155 00001054 E870010000 <1> call SHIP_IT ; EXECUTE ENABLE 3156 <1> K39A: 3157 00001059 B020 <1> mov al, EOI ; END OF INTERRUPT TO CONTROL PORT 3158 0000105B E620 <1> out 20h, al ;out INTA00, al ; ALLOW FURTHER KEYSTROKE INTERRUPTS 3159 <1> ; 3160 <1> ;----- DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON 3161 0000105D 803D[805B0000]07 <1> cmp byte [CRT_MODE], 7 ; IS THIS BLACK AND WHITE CARD 3162 00001064 740A <1> je short K40 ; YES, NOTHING TO DO 3163 00001066 66BAD803 <1> mov dx, 03D8h ; PORT FOR COLOR CARD 3164 0000106A A0[815B0000] <1> mov al, [CRT_MODE_SET] ; GET THE VALUE OF THE CURRENT MODE 3165 0000106F EE <1> out dx, al ; SET THE CRT MODE, SO THAT CRT IS ON 3166 <1> ; 3167 <1> K40: ; PAUSE-LOOP 3168 00001070 F605[845B0000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG 3169 00001077 75F7 <1> jnz short K40 ; LOOP UNTIL FLAG TURNED OFF 3170 <1> ; 3171 00001079 E98CFEFFFF <1> jmp K27 ; INTERRUPT_RETURN_NO_EOI 3172 <1> ; 3173 <1> ;----- TEST SPECIAL CASE KEY 55 3174 <1> K41: ; NO-PAUSE 3175 0000107E 3C37 <1> cmp al, 55 ; TEST FOR */PRTSC KEY 3176 00001080 7513 <1> jne short K42 ; NOT-KEY-55 3177 00001082 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3178 00001085 7405 <1> jz short K41A ; NO, CTL-PRTSC IS VALID 3179 00001087 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3180 0000108A 7421 <1> jz short K42B ; NO, TRANSLATE TO A FUNCTION 3181 <1> K41A: 3182 0000108C 66B80072 <1> mov ax, 114*256 ; START/STOP PRINTING SWITCH 3183 00001090 E9EF000000 <1> jmp K57 ; BUFFER_FILL 3184 <1> ; 3185 <1> ;----- SET UP TO TRANSLATE CONTROL SHIFT 3186 <1> K42: ; NOT-KEY-55 3187 00001095 3C0F <1> cmp al, 15 ; IS IT THE TAB KEY? 3188 00001097 7414 <1> je short K42B ; YES, XLATE TO FUNCTION CODE 3189 00001099 3C35 <1> cmp al, 53 ; IS IT THE / KEY? 3190 0000109B 750E <1> jne short K42A ; NO, NO MORE SPECIAL CASES 3191 0000109D F6C702 <1> test bh, LC_E0 ; YES, IS IT FROM THE KEY PAD? 3192 000010A0 7409 <1> jz short K42A ; NO, JUST TRANSLATE 3193 000010A2 66B80095 <1> mov ax, 9500h ; YES, SPECIAL CODE FOR THIS ONE 3194 000010A6 E9D9000000 <1> jmp K57 ; BUFFER FILL 3195 <1> K42A: 3196 <1> ;mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3197 000010AB 3C3B <1> cmp al, 59 ; IS IT IN CHARACTER TABLE? 3198 <1> ;jb short K45F ; YES, GO TRANSLATE CHAR 3199 <1> ;;jb K56 ; 20/02/2015 3200 <1> ;;jmp K64 ; 20/02/2015 3201 <1> K42B: 3202 000010AD BB[785A0000] <1> mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3203 <1> ;;jmp K64 3204 <1> ;jb K56 ;; 20/02/2015 3205 <1> ; 24/12/2021 3206 000010B2 7267 <1> jb short K45F 3207 000010B4 E9B9000000 <1> jmp K64 3208 <1> ; 3209 <1> ;----- NOT IN CONTROL SHIFT 3210 <1> K44: ; NOT-CTL-SHIFT 3211 000010B9 3C37 <1> cmp al, 55 ; PRINT SCREEN KEY? 3212 000010BB 7528 <1> jne short K45 ; NOT PRINT SCREEN 3213 000010BD F6C710 <1> test bh, KBX ; IS THIS ENHANCED KEYBOARD? 3214 000010C0 7407 <1> jz short K44A ; NO, TEST FOR SHIFT STATE 3215 000010C2 F6C702 <1> test bh, LC_E0 ; YES, LAST CODE A MARKER? 3216 000010C5 7507 <1> jnz short K44B ; YES, IS PRINT SCREEN 3217 000010C7 EB41 <1> jmp short K45C ; NO, TRANSLATE TO '*' CHARACTER 3218 <1> K44A: 3219 000010C9 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN? 3220 000010CC 743C <1> jz short K45C ; NO, TRANSLATE TO '*' CHARACTER 3221 <1> ; 3222 <1> ;----- ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION 3223 <1> K44B: 3224 000010CE B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3225 000010D0 E8F4000000 <1> call SHIP_IT ; EXECUTE ENABLE 3226 000010D5 B020 <1> mov al, EOI ; END OF CURRENT INTERRUPT 3227 000010D7 E620 <1> out 20h, al ;out INTA00, al ; SO FURTHER THINGS CAN HAPPEN 3228 <1> ; Print Screen !!! ; ISSUE PRINT SCREEN INTERRUPT (INT 05h) 3229 <1> ;push bp ; SAVE POINTER 3230 <1> ;int 05h ; ISSUE PRINT SCREEN INTERRUPT 3231 <1> ;pop bp ; RESTORE POINTER 3232 000010D9 8025[865B0000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS 3233 000010E0 E925FEFFFF <1> jmp K27 ; GO BACK WITHOUT EOI OCCURRING 3234 <1> ; 3235 <1> ;----- HANDLE IN-CORE KEYS 3236 <1> K45: ; NOT-PRINT-SCREEN 3237 000010E5 3C3A <1> cmp al, 58 ; TEST FOR IN-CORE AREA 3238 000010E7 7734 <1> ja short K46 ; JUMP IF NOT 3239 000010E9 3C35 <1> cmp al, 53 ; IS THIS THE '/' KEY? 3240 000010EB 7505 <1> jne short K45A ; NO, JUMP 3241 000010ED F6C702 <1> test bh, LC_E0 ; WAS THE LAST CODE THE MARKER? 3242 000010F0 7518 <1> jnz short K45C ; YES, TRANSLATE TO CHARACTER 3243 <1> K45A: 3244 000010F2 B91A000000 <1> mov ecx, 26 ; LENGHT OF SEARCH 3245 000010F7 BF[4E5A0000] <1> mov edi, K30+10 ; POINT TO TABLE OF A-Z CHARS 3246 000010FC F2AE <1> repne scasb ; IS THIS A LETTER KEY? 3247 <1> ; 20/02/2015 3248 000010FE 7505 <1> jne short K45B ; NO, SYMBOL KEY 3249 <1> ; 3250 00001100 F6C340 <1> test bl, CAPS_STATE ; ARE WE IN CAPS_LOCK? 3251 00001103 750C <1> jnz short K45D ; TEST FOR SURE 3252 <1> K45B: 3253 00001105 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3254 00001108 750C <1> jnz short K45E ; YES, UPPERCASE 3255 <1> ; NO, LOWERCASE 3256 <1> K45C: 3257 0000110A BB[D05A0000] <1> mov ebx, K10 ; TRANSLATE TO LOWERCASE LETTERS 3258 0000110F EB51 <1> jmp short K56 3259 <1> K45D: ; ALMOST-CAPS-STATE 3260 00001111 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO? 3261 00001114 75F4 <1> jnz short K45C ; SHIFTED TEMP OUT OF CAPS STATE 3262 <1> K45E: 3263 00001116 BB[285B0000] <1> mov ebx, K11 ; TRANSLATE TO UPPER CASE LETTERS 3264 0000111B EB45 <1> K45F: jmp short K56 3265 <1> ; 3266 <1> ;----- TEST FOR KEYS F1 - F10 3267 <1> K46: ; NOT IN-CORE AREA 3268 0000111D 3C44 <1> cmp al, 68 ; TEST FOR F1 - F10 3269 <1> ;ja short K47 ; JUMP IF NOT 3270 <1> ;jmp short K53 ; YES, GO DO FN KEY PROCESS 3271 0000111F 7635 <1> jna short K53 3272 <1> ; 3273 <1> ;----- HANDLE THE NUMERIC PAD KEYS 3274 <1> K47: ; NOT F1 - F10 3275 00001121 3C53 <1> cmp al, 83 ; TEST NUMPAD KEYS 3276 00001123 772D <1> ja short K52 ; JUMP IF NOT 3277 <1> ; 3278 <1> ;----- KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION 3279 <1> K48: 3280 00001125 3C4A <1> cmp al, 74 ; SPECIAL CASE FOR MINUS 3281 00001127 74ED <1> je short K45E ; GO TRANSLATE 3282 00001129 3C4E <1> cmp al, 78 ; SPECIAL CASE FOR PLUS 3283 0000112B 74E9 <1> je short K45E ; GO TRANSLATE 3284 0000112D F6C702 <1> test bh, LC_E0 ; IS THIS ONE OFTHE NEW KEYS? 3285 00001130 750A <1> jnz short K49 ; YES, TRANSLATE TO BASE STATE 3286 <1> ; 3287 00001132 F6C320 <1> test bl, NUM_STATE ; ARE WE IN NUM LOCK 3288 00001135 7514 <1> jnz short K50 ; TEST FOR SURE 3289 00001137 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3290 <1> ;jnz short K51 ; IF SHIFTED, REALLY NUM STATE 3291 0000113A 75DA <1> jnz short K45E 3292 <1> ; 3293 <1> ;----- BASE CASE FOR KEYPAD 3294 <1> K49: 3295 0000113C 3C4C <1> cmp al, 76 ; SPECIAL CASE FOR BASE STATE 5 3296 0000113E 7504 <1> jne short K49A ; CONTINUE IF NOT KEYPAD 5 3297 00001140 B0F0 <1> mov al, 0F0h ; SPECIAL ASCII CODE 3298 00001142 EB40 <1> jmp short K57 ; BUFFER FILL 3299 <1> K49A: 3300 00001144 BB[D05A0000] <1> mov ebx, K10 ; BASE CASE TABLE 3301 00001149 EB27 <1> jmp short K64 ; CONVERT TO PSEUDO SCAN 3302 <1> ; 3303 <1> ;----- MIGHT BE NUM LOCK, TEST SHIFT STATUS 3304 <1> K50: ; ALMOST-NUM-STATE 3305 0000114B F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3306 0000114E 75EC <1> jnz short K49 ; SHIFTED TEMP OUT OF NUM STATE 3307 00001150 EBC4 <1> K51: jmp short K45E ; REALLY NUM STATE 3308 <1> ; 3309 <1> ;----- TEST FOR THE NEW KEYS ON WT KEYBOARDS 3310 <1> K52: ; NOT A NUMPAD KEY 3311 00001152 3C56 <1> cmp al, 86 ; IS IT THE NEW WT KEY? 3312 <1> ;jne short K53 ; JUMP IF NOT 3313 <1> ;jmp short K45B ; HANDLE WITH REST OF LETTER KEYS 3314 00001154 74AF <1> je short K45B 3315 <1> ; 3316 <1> ;----- MUST BE F11 OR F12 3317 <1> K53: ; F1 - F10 COME HERE, TOO 3318 00001156 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE 3319 00001159 74E1 <1> jz short K49 ; JUMP, LOWER CASE PSEUDO SC'S 3320 <1> ; 20/02/2015 3321 0000115B BB[285B0000] <1> mov ebx, K11 ; UPPER CASE PSEUDO SCAN CODES 3322 00001160 EB10 <1> jmp short K64 ; TRANSLATE SCAN 3323 <1> ; 3324 <1> ;----- TRANSLATE THE CHARACTER 3325 <1> K56: ; TRANSLATE-CHAR 3326 00001162 FEC8 <1> dec al ; CONVERT ORIGIN 3327 00001164 D7 <1> xlat ; CONVERT THE SCAN CODE TO ASCII 3328 00001165 F605[865B0000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3329 0000116C 7416 <1> jz short K57 ; NO, GO FILL BUFFER 3330 0000116E B4E0 <1> mov ah, MC_E0 ; YES, PUT SPECIAL MARKER IN AH 3331 00001170 EB12 <1> jmp short K57 ; PUT IT INTO THE BUFFER 3332 <1> ; 3333 <1> ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES 3334 <1> K64: ; TRANSLATE-SCAN-ORGD 3335 00001172 FEC8 <1> dec al ; CONVERT ORIGIN 3336 00001174 D7 <1> xlat ; CTL TABLE SCAN 3337 00001175 88C4 <1> mov ah, al ; PUT VALUE INTO AH 3338 00001177 B000 <1> mov al, 0 ; ZERO ASCII CODE 3339 00001179 F605[865B0000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3340 00001180 7402 <1> jz short K57 ; NO, GO FILL BUFFER 3341 00001182 B0E0 <1> mov al, MC_E0 ; YES, PUT SPECIAL MARKER IN AL 3342 <1> ; 3343 <1> ;----- PUT CHARACTER INTO BUFFER 3344 <1> K57: ; BUFFER_FILL 3345 00001184 3CFF <1> cmp al, -1 ; IS THIS AN IGNORE CHAR 3346 00001186 7405 <1> je short K59 ; YES, DO NOTHING WITH IT 3347 <1> ; 24/12/2021 3348 <1> ;je K26 ; YES, DO NOTHING WITH IT 3349 00001188 80FCFF <1> cmp ah, -1 ; LOOK FOR -1 PSEUDO SCAN 3350 <1> ; 24/12/2021 3351 0000118B 7505 <1> jne short K61 ; NEAR_INTERRUPT_RETURN 3352 <1> ;je K26 ; INTERRUPT_RETURN 3353 <1> K59: ; NEAR_INTERRUPT_RETURN 3354 0000118D E96CFDFFFF <1> jmp K26 ; INTERRUPT_RETURN 3355 <1> K61: ; NOT-CAPS-STATE 3356 00001192 8B1D[945B0000] <1> mov ebx, [BUFFER_TAIL] ; GET THE END POINTER TO THE BUFFER 3357 00001198 89DE <1> mov esi, ebx ; SAVE THE VALUE 3358 0000119A E8AEFAFFFF <1> call _K4 ; ADVANCE THE TAIL 3359 0000119F 3B1D[905B0000] <1> cmp ebx, [BUFFER_HEAD] ; HAS THE BUFFER WRAPPED AROUND 3360 000011A5 740E <1> je short K62 ; BUFFER_FULL_BEEP 3361 000011A7 668906 <1> mov [esi], ax ; STORE THE VALUE 3362 000011AA 891D[945B0000] <1> mov [BUFFER_TAIL], ebx ; MOVE THE POINTER UP 3363 000011B0 E949FDFFFF <1> jmp K26 3364 <1> ;;cli ; TURN OFF INTERRUPTS 3365 <1> ;;mov al, EOI ; END OF INTERRUPT COMMAND 3366 <1> ;;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3367 <1> ;mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3368 <1> ;call SHIP_IT ; EXECUTE ENABLE 3369 <1> ;mov ax, 9102h ; MOVE IN POST CODE & TYPE 3370 <1> ;int 15h ; PERFORM OTHER FUNCTION 3371 <1> ;;and byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3372 <1> ;jmp K27A ; INTERRUPT_RETURN 3373 <1> ;;jmp K27 3374 <1> ; 3375 <1> ;----- BUFFER IS FULL SOUND THE BEEPER 3376 <1> K62: 3377 000011B5 B020 <1> mov al, EOI ; ENABLE INTERRUPT CONTROLLER CHIP 3378 000011B7 E620 <1> out INTA00, al 3379 000011B9 66B9A602 <1> mov cx, 678 ; DIVISOR FOR 1760 HZ 3380 000011BD B304 <1> mov bl, 4 ; SHORT BEEP COUNT (1/16 + 1/64 DELAY) 3381 000011BF E883010000 <1> call beep ; GO TO COMMON BEEP HANDLER 3382 000011C4 E941FDFFFF <1> jmp K27 ; EXIT 3383 <1> 3384 <1> SHIP_IT: 3385 <1> ;--------------------------------------------------------------------------------- 3386 <1> ; SHIP_IT 3387 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3388 <1> ; TO THE KEYBOARD CONTROLLER. 3389 <1> ;--------------------------------------------------------------------------------- 3390 <1> ; 3391 <1> ;push ax ; SAVE DATA TO SEND 3392 <1> ; 24/12/2021 3393 000011C9 50 <1> push eax 3394 <1> ;----- WAIT FOR COMMAND TO ACCEPTED 3395 000011CA FA <1> cli ; DISABLE INTERRUPTS TILL DATA SENT 3396 <1> ; xor ecx, ecx ; CLEAR TIMEOUT COUNTER 3397 000011CB B900000100 <1> mov ecx, 10000h 3398 <1> S10: 3399 000011D0 E464 <1> in al, STATUS_PORT ; READ KEYBOARD CONTROLLER STATUS 3400 000011D2 A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ITS INPUT BUFFER BUSY 3401 000011D4 E0FA <1> loopnz S10 ; WAIT FOR COMMAND TO BE ACCEPTED 3402 <1> 3403 <1> ;pop ax ; GET DATA TO SEND 3404 <1> ; 24/12/2021 3405 000011D6 58 <1> pop eax 3406 000011D7 E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROLLER 3407 000011D9 FB <1> sti ; ENABLE INTERRUPTS AGAIN 3408 000011DA C3 <1> retn ; RETURN TO CALLER 3409 <1> 3410 <1> SND_DATA: 3411 <1> ; --------------------------------------------------------------------------------- 3412 <1> ; SND_DATA 3413 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3414 <1> ; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO 3415 <1> ; HANDLES ANY RETRIES IF REQUIRED 3416 <1> ; --------------------------------------------------------------------------------- 3417 <1> ; 3418 <1> ;push ax ; SAVE REGISTERS 3419 <1> ;push bx 3420 <1> ; 24/12/2021 3421 000011DB 50 <1> push eax 3422 000011DC 53 <1> push ebx 3423 000011DD 51 <1> push ecx 3424 000011DE 88C7 <1> mov bh, al ; SAVE TRANSMITTED BYTE FOR RETRIES 3425 000011E0 B303 <1> mov bl, 3 ; LOAD RETRY COUNT 3426 <1> SD0: 3427 000011E2 FA <1> cli ; DISABLE INTERRUPTS 3428 000011E3 8025[855B0000]CF <1> and byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS 3429 <1> ; 3430 <1> ;----- WAIT FOR COMMAND TO BE ACCEPTED 3431 000011EA B900000100 <1> mov ecx, 10000h ; MAXIMUM WAIT COUNT 3432 <1> SD5: 3433 000011EF E464 <1> in al, STATUS_PORT ; READ KEYBOARD PROCESSOR STATUS PORT 3434 000011F1 A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ANY PENDING COMMAND 3435 000011F3 E0FA <1> loopnz SD5 ; WAIT FOR COMMAND TO BE ACCEPTED 3436 <1> ; 3437 000011F5 88F8 <1> mov al, bh ; REESTABLISH BYTE TO TRANSMIT 3438 000011F7 E660 <1> out PORT_A, al ; SEND BYTE 3439 000011F9 FB <1> sti ; ENABLE INTERRUPTS 3440 <1> ;mov cx, 01A00h ; LOAD COUNT FOR 10 ms+ 3441 000011FA B9FFFF0000 <1> mov ecx, 0FFFFh 3442 <1> SD1: 3443 000011FF F605[855B0000]30 <1> test byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET 3444 00001206 750F <1> jnz short SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS 3445 00001208 E2F5 <1> loop SD1 ; OTHERWISE WAIT 3446 <1> SD2: 3447 0000120A FECB <1> dec bl ; DECREMENT RETRY COUNT 3448 0000120C 75D4 <1> jnz short SD0 ; RETRY TRANSMISSION 3449 0000120E 800D[855B0000]80 <1> or byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG 3450 00001215 EB09 <1> jmp short SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION 3451 <1> SD3: 3452 00001217 F605[855B0000]10 <1> test byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE 3453 0000121E 74EA <1> jz short SD2 ; IF NOT, GO RESEND 3454 <1> SD4: 3455 00001220 59 <1> pop ecx ; RESTORE REGISTERS 3456 <1> ;pop bx 3457 <1> ;pop ax 3458 <1> ; 24/12/2021 3459 00001221 5B <1> pop ebx 3460 00001222 58 <1> pop eax 3461 00001223 C3 <1> retn ; RETURN, GOOD TRANSMISSION 3462 <1> 3463 <1> SND_LED: 3464 <1> ; --------------------------------------------------------------------------------- 3465 <1> ; SND_LED 3466 <1> ; THIS ROUTINES TURNS ON THE MODE INDICATORS. 3467 <1> ; 3468 <1> ;---------------------------------------------------------------------------------- 3469 <1> ; 3470 00001224 FA <1> cli ; TURN OFF INTERRUPTS 3471 00001225 F605[855B0000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3472 0000122C 755F <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3473 <1> ; 3474 0000122E 800D[855B0000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3475 00001235 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3476 00001237 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3477 00001239 EB11 <1> jmp short SL0 ; GO SEND MODE INDICATOR COMMAND 3478 <1> SND_LED1: 3479 0000123B FA <1> cli ; TURN OFF INTERRUPTS 3480 0000123C F605[855B0000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3481 00001243 7548 <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3482 <1> ; 3483 00001245 800D[855B0000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3484 <1> SL0: 3485 0000124C B0ED <1> mov al, LED_CMD ; LED CMD BYTE 3486 0000124E E888FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3487 00001253 FA <1> cli 3488 00001254 E836000000 <1> call MAKE_LED ; GO FORM INDICATOR DATA BYTE 3489 00001259 8025[855B0000]F8 <1> and byte [KB_FLAG_2], 0F8h ; ~KB_LEDS ; CLEAR MODE INDICATOR BITS 3490 00001260 0805[855B0000] <1> or [KB_FLAG_2], al ; SAVE PRESENT INDICATORS FOR NEXT TIME 3491 00001266 F605[855B0000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3492 0000126D 750F <1> jnz short SL2 ; IF SO, BYPASS SECOND BYTE TRANSMISSION 3493 <1> ; 3494 0000126F E867FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3495 00001274 FA <1> cli ; TURN OFF INTERRUPTS 3496 00001275 F605[855B0000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3497 0000127C 7408 <1> jz short SL3 ; IF NOT, DON'T SEND AN ENABLE COMMAND 3498 <1> SL2: 3499 0000127E B0F4 <1> mov al, KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND 3500 00001280 E856FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3501 00001285 FA <1> cli ; TURN OFF INTERRUPTS 3502 <1> SL3: 3503 00001286 8025[855B0000]3F <1> and byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR 3504 <1> SL1: ; UPDATE AND TRANSMIT ERROR FLAG 3505 0000128D FB <1> sti ; ENABLE INTERRUPTS 3506 0000128E C3 <1> retn ; RETURN TO CALLER 3507 <1> 3508 <1> MAKE_LED: 3509 <1> ;--------------------------------------------------------------------------------- 3510 <1> ; MAKE_LED 3511 <1> ; THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF 3512 <1> ; THE MODE INDICATORS. 3513 <1> ;--------------------------------------------------------------------------------- 3514 <1> ; 3515 <1> ;push cx ; SAVE CX 3516 0000128F A0[835B0000] <1> mov al, [KB_FLAG] ; GET CAPS & NUM LOCK INDICATORS 3517 00001294 2470 <1> and al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS 3518 <1> ;mov cl, 4 ; SHIFT COUNT 3519 <1> ;rol al, cl ; SHIFT BITS OVER TO TURN ON INDICATORS 3520 00001296 C0C004 <1> rol al, 4 ; 20/02/2015 3521 00001299 2407 <1> and al, 07h ; MAKE SURE ONLY MODE BITS ON 3522 <1> ;pop cx 3523 0000129B C3 <1> retn ; RETURN TO CALLER 3524 <1> 3525 <1> ; % include 'kybdata.inc' ; KEYBOARD DATA ; 11/03/2015 3526 <1> 3527 <1> ; /// End Of KEYBOARD FUNCTIONS /// 1892 1893 %include 'video.inc' ; 07/03/2015 1894 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - VIDEO.INC 1895 <1> ; Last Modification: 14/06/2022 1896 <1> ; (Video Data is in 'VIDATA.INC') 1897 <1> ; 1898 <1> ; ///////// VIDEO (CGA) FUNCTIONS /////////////// 1899 <1> 1900 <1> ; 14/06/2022 1901 <1> ; 26/02/2022 1902 <1> ; 07/02/2022 1903 <1> ; 02/02/2022 (simplified scroll up) 1904 <1> ; 16/01/2016 1905 <1> ; 30/06/2015 1906 <1> ; 27/06/2015 1907 <1> ; 11/03/2015 1908 <1> ; 02/09/2014 1909 <1> ; 30/08/2014 1910 <1> ; VIDEO FUNCTIONS 1911 <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014) 1912 <1> 1913 <1> write_tty: 1914 <1> ; 02/02/2022 1915 <1> ; 13/08/2015 1916 <1> ; 02/09/2014 1917 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 1918 <1> ; 01/02/2014 (Retro UNIX 8086 v1 - last update) 1919 <1> ; 03/12/2013 (Retro UNIX 8086 v1 - beginning) 1920 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 1921 <1> ; 1922 <1> ; INPUT -> AH = Color (Forecolor, Backcolor) 1923 <1> ; AL = Character to be written 1924 <1> ; EBX = Video Page (0 to 7) 1925 <1> ; (BH = 0 --> Video Mode 3) 1926 <1> 1927 <1> RVRT equ 00001000b ; VIDEO VERTICAL RETRACE BIT 1928 <1> RHRZ equ 00000001b ; VIDEO HORIZONTAL RETRACE BIT 1929 <1> 1930 <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code 1931 <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO 1932 <1> ; 1933 <1> ; 06/10/85 VIDEO DISPLAY BIOS 1934 <1> ; 1935 <1> ;--- WRITE_TTY ------------------------------------------------------------------ 1936 <1> ; : 1937 <1> ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE : 1938 <1> ; VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT : 1939 <1> ; CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. : 1940 <1> ; IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN : 1941 <1> ; IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW : 1942 <1> ; ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, : 1943 <1> ; FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. : 1944 <1> ; WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE : 1945 <1> ; NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : 1946 <1> ; LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE, : 1947 <1> ; THE 0 COLOR IS USED. : 1948 <1> ; ENTRY -- : 1949 <1> ; (AH) = CURRENT CRT MODE : 1950 <1> ; (AL) = CHARACTER TO BE WRITTEN : 1951 <1> ; NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE : 1952 <1> ; HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS : 1953 <1> ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE : 1954 <1> ; EXIT -- : 1955 <1> ; ALL REGISTERS SAVED : 1956 <1> ;-------------------------------------------------------------------------------- 1957 <1> 1958 0000129C FA <1> cli 1959 <1> ; 1960 <1> ; READ CURSOR (04/12/2013) 1961 <1> ; Retro UNIX 386 v1 Modifications: 30/08/2014 1962 0000129D 08FF <1> or bh, bh 1963 <1> ;jnz beeper 1964 <1> ; 02/02/2022 1965 0000129F 7405 <1> jz short u14 1966 000012A1 E992000000 <1> jmp beeper 1967 <1> u14: 1968 <1> ; 02/02/2022 1969 <1> ;; 01/09/2014 1970 <1> ;cmp byte [CRT_MODE], 3 1971 <1> ;je short m3 1972 <1> ;; 1973 <1> ;call set_mode 1974 <1> m3: 1975 000012A6 89DE <1> mov esi, ebx ; 13/08/2015 (0 to 7) 1976 <1> ;shl si, 1 1977 <1> ; 02/02/2022 1978 000012A8 D1E6 <1> shl esi, 1 1979 000012AA 81C6[46610000] <1> add esi, cursor_posn 1980 000012B0 668B16 <1> mov dx, [esi] 1981 <1> ; 1982 <1> ; dx now has the current cursor position 1983 <1> ; 1984 000012B3 3C0D <1> cmp al, 0Dh ; is it carriage return or control character 1985 000012B5 7647 <1> jbe short u8 1986 <1> ; 1987 <1> ; write the char to the screen 1988 <1> u0: 1989 <1> ; ah = attribute/color 1990 <1> ; al = character 1991 <1> ; bl = video page number (0 to 7) 1992 <1> ; bh = 0 1993 <1> ; 1994 000012B7 E8D2010000 <1> call write_c_current 1995 <1> ; 1996 <1> ; position the cursor for next char 1997 000012BC FEC2 <1> inc dl ; next column 1998 <1> ;cmp dl, [CRT_COLS] 1999 000012BE 80FA50 <1> cmp dl, 80 ; test for column overflow 2000 <1> ;jne set_cpos 2001 <1> ; 02/02/2022 2002 000012C1 7405 <1> je short u13 2003 000012C3 E9DE000000 <1> jmp set_cpos 2004 <1> u13: 2005 000012C8 B200 <1> mov dl, 0 ; column = 0 2006 <1> u10: ; (line feed found) 2007 000012CA 80FE18 <1> cmp dh, 25-1 ; check for last row 2008 000012CD 7228 <1> jb short u6 2009 <1> ; 2010 <1> ; scroll required 2011 <1> u1: 2012 <1> ; SET CURSOR POSITION (04/12/2013) 2013 000012CF E8D2000000 <1> call set_cpos 2014 <1> ; 2015 <1> ; determine value to fill with during scroll 2016 <1> u2: 2017 <1> ; READ_AC_CURRENT : 2018 <1> ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER 2019 <1> ; AT THE CURRENT CURSOR POSITION 2020 <1> ; 2021 <1> ; INPUT 2022 <1> ; (AH) = CURRENT CRT MODE 2023 <1> ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) 2024 <1> ; (DS) = DATA SEGMENT 2025 <1> ; (ES) = REGEN SEGMENT 2026 <1> ; OUTPUT 2027 <1> ; (AL) = CHARACTER READ 2028 <1> ; (AH) = ATTRIBUTE READ 2029 <1> ; 2030 <1> ; mov ah, [CRT_MODE] ; move current mode into ah 2031 <1> ; 2032 <1> ; bl = video page number 2033 <1> ; 2034 000012D4 E829010000 <1> call find_position ; get regen location and port address 2035 <1> ; dx = status port 2036 <1> ; esi = cursor location/address 2037 <1> p11: 2038 000012D9 FB <1> sti ; enable interrupts 2039 000012DA 90 <1> nop ; allow for small interupts window 2040 000012DB FA <1> cli ; blocks interrupts for single loop 2041 000012DC EC <1> in al, dx ; get status from adapter 2042 000012DD A801 <1> test al, RHRZ ; is horizontal retrace low 2043 000012DF 75F8 <1> jnz short p11 ; wait until it is 2044 <1> p12: ; now wait for either retrace high 2045 000012E1 EC <1> in al, dx ; get status 2046 000012E2 A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 2047 000012E4 74FB <1> jz short p12 ; wait until either is active 2048 <1> p13: 2049 000012E6 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 2050 000012EC 668B06 <1> mov ax, [esi] ; get the character and attribute 2051 <1> ; 2052 <1> ; al = character, ah = attribute 2053 <1> ; 2054 000012EF FB <1> sti 2055 <1> ; bl = video page number 2056 <1> u3: 2057 <1> ;;mov ax, 0601h ; scroll one line 2058 <1> ;;sub cx, cx ; upper left corner 2059 <1> ;;mov dh, 25-1 ; lower right row 2060 <1> ;;;mov dl, [CRT_COLS] 2061 <1> ;mov dl, 80 ; lower right column 2062 <1> ;;dec dl 2063 <1> ;;mov dl, 79 2064 <1> 2065 <1> ;;call scroll_up ; 04/12/2013 2066 <1> ;;; 11/03/2015 2067 <1> ; 02/09/2014 2068 <1> ;;;mov cx, [crt_ulc] ; Upper left corner (0000h) 2069 <1> ;;;mov dx, [crt_lrc] ; Lower right corner (184Fh) 2070 <1> ; 11/03/2015 2071 <1> ;sub cx, cx 2072 <1> ;mov dx, 184Fh ; dl= 79 (column), dh = 24 (row) 2073 <1> ; 2074 <1> ; 02/02/2022 (simplied scroll up) 2075 <1> ; ((retro unix 8086 v1 'scroll_up' in 'u9.s')) 2076 <1> ; 2077 000012F0 B001 <1> mov al, 1 ; scroll 1 line up 2078 <1> ; ah = attribute 2079 000012F2 E935010000 <1> jmp scroll_up 2080 <1> ;u4: 2081 <1> ;;int 10h ; video-call return 2082 <1> ; scroll up the screen 2083 <1> ; tty return 2084 <1> ;u5: 2085 <1> ;retn ; return to the caller 2086 <1> 2087 <1> u6: ; set-cursor-inc 2088 000012F7 FEC6 <1> inc dh ; next row 2089 <1> ; set cursor 2090 <1> ;u7: 2091 <1> ;;mov ah, 02h 2092 <1> ;;jmp short u4 ; establish the new cursor 2093 <1> ;call set_cpos 2094 <1> ;jmp short u5 2095 000012F9 E9A8000000 <1> jmp set_cpos 2096 <1> 2097 <1> ; check for control characters 2098 <1> u8: 2099 000012FE 7434 <1> je short u9 2100 00001300 3C0A <1> cmp al, 0Ah ; is it a line feed (0Ah) 2101 00001302 74C6 <1> je short u10 2102 00001304 3C07 <1> cmp al, 07h ; is it a bell 2103 00001306 7430 <1> je short u11 2104 00001308 3C08 <1> cmp al, 08h ; is it a backspace 2105 <1> ;jne short u0 2106 0000130A 7420 <1> je short bs ; 12/12/2013 2107 <1> ; 12/12/2013 (tab stop) 2108 0000130C 3C09 <1> cmp al, 09h ; is it a tab stop 2109 0000130E 75A7 <1> jne short u0 2110 00001310 88D0 <1> mov al, dl 2111 00001312 6698 <1> cbw 2112 00001314 B108 <1> mov cl, 8 2113 00001316 F6F1 <1> div cl 2114 00001318 28E1 <1> sub cl, ah 2115 <1> ts: 2116 <1> ; 02/09/2014 2117 <1> ; 01/09/2014 2118 0000131A B020 <1> mov al, 20h 2119 <1> tsloop: 2120 <1> ;push cx 2121 <1> ;push ax 2122 <1> ; 02/02/2022 2123 0000131C 51 <1> push ecx 2124 0000131D 50 <1> push eax 2125 0000131E 30FF <1> xor bh, bh 2126 <1> ;mov bl, [active_page] 2127 00001320 E881FFFFFF <1> call m3 2128 <1> ; 02/02/2022 2129 00001325 58 <1> pop eax 2130 00001326 59 <1> pop ecx 2131 <1> ;pop ax ; ah = attribute/color 2132 <1> ;pop cx 2133 00001327 FEC9 <1> dec cl 2134 00001329 75F1 <1> jnz short tsloop 2135 0000132B C3 <1> retn 2136 <1> bs: 2137 <1> ; back space found 2138 0000132C 08D2 <1> or dl, dl ; is it already at start of line 2139 <1> ;je short u7 ; set_cursor 2140 0000132E 7476 <1> jz short set_cpos 2141 <1> ;dec dx ; no -- just move it back 2142 <1> ; 02/02/2022 2143 00001330 FECA <1> dec dl 2144 <1> ;jmp short u7 2145 00001332 EB72 <1> jmp short set_cpos 2146 <1> 2147 <1> ; carriage return found 2148 <1> u9: 2149 00001334 B200 <1> mov dl, 0 ; move to first column 2150 <1> ;jmp short u7 2151 00001336 EB6E <1> jmp short set_cpos 2152 <1> 2153 <1> ; line feed found 2154 <1> ;u10: 2155 <1> ; cmp dh, 25-1 ; bottom of screen 2156 <1> ; jne short u6 ; no, just set the cursor 2157 <1> ; jmp u1 ; yes, scroll the screen 2158 <1> 2159 <1> beeper: 2160 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2161 <1> ; 18/01/2014 2162 <1> ; 03/12/2013 2163 <1> ; bell found 2164 <1> u11: 2165 00001338 FB <1> sti 2166 00001339 3A1D[56610000] <1> cmp bl, [active_page] 2167 0000133F 7551 <1> jne short u12 ; Do not sound the beep 2168 <1> ; if it is not written on the active page 2169 00001341 66B93305 <1> mov cx, 1331 ; divisor for 896 hz tone 2170 00001345 B31F <1> mov bl, 31 ; set count for 31/64 second for beep 2171 <1> ;call beep ; sound the pod bell 2172 <1> ;jmp short u5 ; tty_return 2173 <1> ;retn 2174 <1> 2175 <1> TIMER equ 040h ; 8254 TIMER - BASE ADDRESS 2176 <1> PORT_B equ 061h ; PORT B READ/WRITE DIAGNOSTIC REGISTER 2177 <1> GATE2 equ 00000001b ; TIMER 2 INPUT CATE CLOCK BIT 2178 <1> SPK2 equ 00000010b ; SPEAKER OUTPUT DATA ENABLE BIT 2179 <1> 2180 <1> beep: 2181 <1> ; 07/02/2015 2182 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2183 <1> ; 18/01/2014 2184 <1> ; 03/12/2013 2185 <1> ; 2186 <1> ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES 2187 <1> ; 2188 <1> ; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE 2189 <1> ; 2190 <1> ; ENTRY: 2191 <1> ; (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND ) 2192 <1> ; (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ) 2193 <1> ; EXIT: : 2194 <1> ; (AX),(BL),(CX) MODIFIED. 2195 <1> 2196 00001347 9C <1> pushf ; 18/01/2014 ; save interrupt status 2197 00001348 FA <1> cli ; block interrupts during update 2198 00001349 B0B6 <1> mov al, 10110110b ; select timer 2, lsb, msb binary 2199 0000134B E643 <1> out TIMER+3, al ; write timer mode register 2200 0000134D EB00 <1> jmp $+2 ; I/O delay 2201 0000134F 88C8 <1> mov al, cl ; divisor for hz (low) 2202 00001351 E642 <1> out TIMER+2,AL ; write timer 2 count - lsb 2203 00001353 EB00 <1> jmp $+2 ; I/O delay 2204 00001355 88E8 <1> mov al, ch ; divisor for hz (high) 2205 00001357 E642 <1> out TIMER+2, al ; write timer 2 count - msb 2206 00001359 E461 <1> in al, PORT_B ; get current setting of port 2207 0000135B 88C4 <1> mov ah, al ; save that setting 2208 0000135D 0C03 <1> or al, GATE2+SPK2 ; gate timer 2 and turn speaker on 2209 0000135F E661 <1> out PORT_B, al ; and restore interrupt status 2210 <1> ;popf ; 18/01/2014 2211 00001361 FB <1> sti 2212 <1> g7: ; 1/64 second per count (bl) 2213 00001362 B90B040000 <1> mov ecx, 1035 ; delay count for 1/64 of a second 2214 00001367 E827000000 <1> call waitf ; go to beep delay 1/64 count 2215 0000136C FECB <1> dec bl ; (bl) length count expired? 2216 0000136E 75F2 <1> jnz short g7 ; no - continue beeping speaker 2217 <1> ; 2218 <1> ;pushf ; save interrupt status 2219 00001370 FA <1> cli ; 18/01/2014 ; block interrupts during update 2220 00001371 E461 <1> in al, PORT_B ; get current port value 2221 <1> ;or al, not (GATE2+SPK2) ; isolate current speaker bits in case 2222 00001373 0CFC <1> or al, ~(GATE2+SPK2) 2223 00001375 20C4 <1> and ah, al ; someone turned them off during beep 2224 00001377 88E0 <1> mov al, ah ; recover value of port 2225 <1> ;or al, not (GATE2+SPK2) ; force speaker data off 2226 00001379 0CFC <1> or al, ~(GATE2+SPK2) ; isolate current speaker bits in case 2227 0000137B E661 <1> out PORT_B, al ; and stop speaker timer 2228 <1> ;popf ; restore interrupt flag state 2229 0000137D FB <1> sti 2230 0000137E B90B040000 <1> mov ecx, 1035 ; force 1/64 second delay (short) 2231 00001383 E80B000000 <1> call waitf ; minimum delay between all beeps 2232 <1> ;pushf ; save interrupt status 2233 00001388 FA <1> cli ; block interrupts during update 2234 00001389 E461 <1> in al, PORT_B ; get current port value in case 2235 0000138B 2403 <1> and al, GATE2+SPK2 ; someone turned them on 2236 0000138D 08E0 <1> or al, ah ; recover value of port_b 2237 0000138F E661 <1> out PORT_B, al ; restore speaker status 2238 00001391 9D <1> popf ; restore interrupt flag state 2239 <1> u12: 2240 00001392 C3 <1> retn 2241 <1> 2242 <1> REFRESH_BIT equ 00010000b ; REFRESH TEST BIT 2243 <1> 2244 <1> WAITF: 2245 <1> waitf: 2246 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2247 <1> ; 03/12/2013 2248 <1> ; 2249 <1> ; push ax ; save work register (ah) 2250 <1> ;waitf1: 2251 <1> ; use timer 1 output bits 2252 <1> ; in al, PORT_B ; read current counter output status 2253 <1> ; and al, REFRESH_BIT ; mask for refresh determine bit 2254 <1> ; cmp al, ah ; did it just change 2255 <1> ; je short waitf1 ; wait for a change in output line 2256 <1> ; ; 2257 <1> ; mov ah, al ; save new lflag state 2258 <1> ; loop waitf1 ; decrement half cycles till count end 2259 <1> ; ; 2260 <1> ; pop ax ; restore (ah) 2261 <1> ; retn ; return (cx)=0 2262 <1> 2263 <1> ; 02/02/2022 2264 <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s) 2265 <1> ; 17/12/2014 (dsectrm2.s) 2266 <1> ; WAITF 2267 <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 /// 2268 <1> ; 2269 <1> ;---WAITF----------------------------------------------------------------------- 2270 <1> ; FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR) 2271 <1> ; ENTRY: 2272 <1> ; (CX) = COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT 2273 <1> ; MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE 2274 <1> ; EXIT: 2275 <1> ; AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS) 2276 <1> ; (CX) = 0 2277 <1> ;------------------------------------------------------------------------------- 2278 <1> 2279 <1> ; Refresh period: 30 micro seconds (15-80 us) 2280 <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH) 2281 <1> 2282 <1> ;WAITF: ; DELAY FOR (CX)*15.085737 US 2283 00001393 50 <1> push eax ; 02/02/2022 ; SAVE WORK REGISTER (AH) 2284 <1> ;push ax 2285 <1> ; 16/12/2014 2286 <1> ;shr cx, 1 ; convert to count of 30 micro seconds 2287 00001394 D1E9 <1> shr ecx, 1 ; 21/02/2015 2288 <1> ;17/12/2014 2289 <1> ;WAITF1: 2290 <1> ; IN AL, PORT_B ;061h ; READ CURRENT COUNTER OUTPUT STATUS 2291 <1> ; AND AL, REFRESH_BIT ;00010000b ; MASK FOR REFRESH DETERMINE BIT 2292 <1> ; CMP AL, AH ; DID IT JUST CHANGE 2293 <1> ; JE short WAITF1 ; WAIT FOR A CHANGE IN OUTPUT LINE 2294 <1> ; MOV AH, AL ; SAVE NEW FLAG STATE 2295 <1> ; LOOP WAITF1 ; DECREMENT HALF CYCLES TILL COUNT END 2296 <1> ; 2297 <1> ; 17/12/2014 2298 <1> ; 2299 <1> ; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999 2300 <1> ; 2301 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 2302 <1> ; INPUT: CX = number of refresh periods to wait 2303 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2304 <1> WR_STATE_0: 2305 00001396 E461 <1> IN AL,PORT_B ; IN AL,SYS1 2306 00001398 A810 <1> TEST AL,010H 2307 0000139A 74FA <1> JZ SHORT WR_STATE_0 2308 <1> WR_STATE_1: 2309 0000139C E461 <1> IN AL,PORT_B ; IN AL,SYS1 2310 0000139E A810 <1> TEST AL,010H 2311 000013A0 75FA <1> JNZ SHORT WR_STATE_1 2312 000013A2 E2F2 <1> LOOP WR_STATE_0 2313 <1> ; 2314 <1> ;pop ax 2315 000013A4 58 <1> pop eax ; 02/02/2022 ; RESTORE (AH) 2316 000013A5 C3 <1> RETn ; (CX) = 0 2317 <1> 2318 <1> set_cpos: 2319 <1> ; 14/06/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.4) 2320 <1> ; 26/02/2022 2321 <1> ; 02/02/2022 2322 <1> ; 27/06/2015 2323 <1> ; 01/09/2014 2324 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 2325 <1> ; 2326 <1> ; 12/12/2013 (Retro UNIX 8086 v1 - last update) 2327 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - beginning) 2328 <1> ; 2329 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2330 <1> ; 2331 <1> ; SET_CPOS 2332 <1> ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE 2333 <1> ; NEW X-Y VALUES PASSED 2334 <1> ; INPUT 2335 <1> ; DX - ROW,COLUMN OF NEW CURSOR 2336 <1> ; BH - DISPLAY PAGE OF CURSOR 2337 <1> ; OUTPUT 2338 <1> ; CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY 2339 <1> ; 2340 000013A6 0FB6C3 <1> movzx eax, bl ; BL = video page number ; 27/06/2015 (movzx) 2341 000013A9 D0E0 <1> shl al, 1 ; word offset 2342 000013AB BE[46610000] <1> mov esi, cursor_posn 2343 000013B0 01C6 <1> add esi, eax 2344 000013B2 668916 <1> mov [esi], dx ; save the pointer 2345 000013B5 381D[56610000] <1> cmp [active_page], bl 2346 000013BB 7531 <1> jne short m17 2347 <1> 2348 <1> ; 14/06/2022 2349 <1> ;cli ; 26/02/2022 2350 <1> 2351 <1> ;call m18 ;h CURSOR SET 2352 <1> ;m17: ; SET_CPOS_RETURN 2353 <1> ; 01/09/2014 2354 <1> ;retn 2355 <1> ; DX = row/column 2356 <1> m18: 2357 000013BD E832000000 <1> call position ; determine location in regen buffer 2358 <1> ;mov cx, [CRT_START] 2359 <1> ; 26/02/2022 2360 000013C2 0FB70D[44610000] <1> movzx ecx, word [CRT_START] 2361 000013C9 01C1 <1> add ecx, eax 2362 <1> ;add cx, ax ; add char position in regen buffer 2363 <1> ; to the start address (offset) for this page 2364 <1> ;shr cx, 1 ; divide by 2 for char only count 2365 <1> ; 26/02/2022 2366 000013CB D1E9 <1> shr ecx, 1 2367 000013CD B40E <1> mov ah, 14 ; register number for cursor 2368 <1> 2369 <1> ; 14/06/2022 2370 <1> ;call m16 ; output value to the 6845 2371 <1> ;sti ; 26/02/2022 2372 <1> ;retn 2373 <1> 2374 <1> ; 14/06/2022 2375 <1> ; 26/02/2022 2376 <1> ; 02/02/2022 2377 <1> ;----- THIS ROUTINE OUTPUTS THE CX REGISTER 2378 <1> ; TO THE 6845 REGISTERS NAMED IN (AH) 2379 <1> m16: 2380 <1> ; 14/06/2022 2381 000013CF FA <1> cli ; 26/02/2022 2382 <1> ;mov dx, [addr_6845] ; address register 2383 000013D0 66BAD403 <1> mov dx, 03D4h ; I/O address of color card 2384 000013D4 88E0 <1> mov al, ah ; get value 2385 000013D6 EE <1> out dx, al ; register set 2386 <1> ;inc dx ; data register 2387 <1> ; 02/02/2022 2388 000013D7 FEC2 <1> inc dl 2389 000013D9 EB00 <1> jmp $+2 ; i/o delay 2390 000013DB 88E8 <1> mov al, ch ; data 2391 000013DD EE <1> out dx, al 2392 <1> ;dec dx 2393 <1> ; 02/02/2022 2394 000013DE FECA <1> dec dl 2395 000013E0 88E0 <1> mov al, ah 2396 000013E2 FEC0 <1> inc al ; point to other data register 2397 000013E4 EE <1> out dx, al ; set for second register 2398 <1> ;inc dx 2399 <1> ; 02/02/2022 2400 000013E5 FEC2 <1> inc dl 2401 000013E7 EB00 <1> jmp $+2 ; i/o delay 2402 000013E9 88C8 <1> mov al, cl ; second data value 2403 000013EB EE <1> out dx, al 2404 <1> ; 14/06/2022 2405 000013EC FB <1> sti ; 26/02/2022 2406 <1> ;m17: 2407 000013ED C3 <1> retn 2408 <1> m17: 2409 <1> ; 14/06/2022 2410 <1> ; ('write_tty' must not return to 'putc'/'wtty' with cf) 2411 000013EE F8 <1> clc 2412 000013EF C3 <1> retn 2413 <1> 2414 <1> set_ctype: 2415 <1> ; 07/02/2022 2416 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2417 <1> ; 2418 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2419 <1> 2420 <1> ; CH) = BITS 4-0 = START LINE FOR CURSOR 2421 <1> ; ** HARDWARE WILL ALWAYS CAUSE BLINK 2422 <1> ; ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING 2423 <1> ; OR NO CURSOR AT ALL 2424 <1> ; (CL) = BITS 4-0 = END LINE FOR CURSOR 2425 <1> 2426 <1> ;------------------------------------------------ 2427 <1> ; SET_CTYPE 2428 <1> ; THIS ROUTINE SETS THE CURSOR VALUE 2429 <1> ; INPUT 2430 <1> ; (CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE 2431 <1> ; OUTPUT 2432 <1> ; NONE 2433 <1> ;------------------------------------------------ 2434 <1> 2435 000013F0 B40A <1> mov ah, 10 ; 6845 register for cursor set 2436 <1> ;mov [CURSOR_MODE], cx ; save in data area 2437 <1> ;call m16 ; output cx register 2438 <1> ;retn 2439 <1> ; 07/02/2022 2440 000013F2 EBDB <1> jmp short m16 2441 <1> 2442 <1> position: 2443 <1> ; 26/02/2022 2444 <1> ; 02/02/2022 2445 <1> ; 27/06/2015 2446 <1> ; 02/09/2014 2447 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2448 <1> ; 04/12/2013 (Retro UNIX 8086 v1) 2449 <1> ; 2450 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2451 <1> ; 2452 <1> ; POSITION 2453 <1> ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS 2454 <1> ; OF A CHARACTER IN THE ALPHA MODE 2455 <1> ; INPUT 2456 <1> ; AX = ROW, COLUMN POSITION 2457 <1> ; OUTPUT 2458 <1> ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 2459 <1> 2460 <1> ; DX = ROW, COLUMN POSITION 2461 <1> ;movzx eax, byte [CRT_COLS] ; 27/06/2015 2462 000013F4 31C0 <1> xor eax, eax ; 02/09/2014 2463 000013F6 B050 <1> mov al, 80 ; determine bytes to row 2464 000013F8 F6E6 <1> mul dh ; row value 2465 <1> ;xor dh, dh ; 0 2466 <1> ;add ax, dx ; add column value to the result 2467 <1> ; 26/02/2022 2468 000013FA 00D0 <1> add al, dl 2469 000013FC 80D400 <1> adc ah, 0 2470 <1> ;shl ax, 1 ; * 2 for attribute bytes 2471 <1> ; 02/02/2022 2472 000013FF D1E0 <1> shl eax, 1 2473 <1> ; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 2474 00001401 C3 <1> retn 2475 <1> 2476 <1> find_position: 2477 <1> ; 02/02/2022 2478 <1> ; 27/06/2015 2479 <1> ; 07/09/2014 2480 <1> ; 02/09/2014 2481 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2482 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2483 00001402 0FB6CB <1> movzx ecx, bl ; video page number ; 27/06/2015 (movzx) 2484 00001405 89CE <1> mov esi, ecx 2485 <1> ;shl si, 1 2486 <1> ; 02/02/2022 2487 00001407 D1E6 <1> shl esi, 1 2488 00001409 668B96[46610000] <1> mov dx, [esi+cursor_posn] 2489 00001410 7409 <1> jz short p21 2490 <1> ;xor si, si 2491 <1> ; 02/02/2022 2492 00001412 31F6 <1> xor esi, esi 2493 <1> p20: 2494 <1> ;add si, [CRT_LEN] 2495 00001414 6681C6A00F <1> add si, 80*25*2 ; add length of buffer for one page 2496 00001419 E2F9 <1> loop p20 2497 <1> p21: 2498 0000141B 6621D2 <1> and dx, dx 2499 0000141E 7407 <1> jz short p22 2500 00001420 E8CFFFFFFF <1> call position ; determine location in regen in page 2501 00001425 01C6 <1> add esi, eax ; add location to start of regen page 2502 <1> p22: 2503 <1> ;mov dx, [addr_6845] ; get base address of active display 2504 <1> ;mov dx, 03D4h ; I/O address of color card 2505 <1> ;add dx, 6 ; point at status port 2506 00001427 66BADA03 <1> mov dx, 03DAh ; status port 2507 <1> ; cx = 0 2508 0000142B C3 <1> retn 2509 <1> 2510 <1> scroll_up: 2511 <1> ; 02/02/2022 (simplified scroll up) 2512 <1> ; ((retro unix 8086 v1 'scroll_up' in 'u9.s')) 2513 <1> ; 16/01/2016 2514 <1> ; 07/09/2014 2515 <1> ; 02/09/2014 2516 <1> ; 01/09/2014 (Retro UNIX 386 v1 - beginning) 2517 <1> ; 04/04/2014 2518 <1> ; 04/12/2013 2519 <1> ; 2520 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2521 <1> ; 2522 <1> ; SCROLL UP 2523 <1> ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP 2524 <1> ; ON THE SCREEN 2525 <1> ; INPUT 2526 <1> ; (AH) = CURRENT CRT MODE 2527 <1> ; (AL) = NUMBER OF ROWS TO SCROLL 2528 <1> ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER 2529 <1> ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER 2530 <1> ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE 2531 <1> ; (DS) = DATA SEGMENT 2532 <1> ; (ES) = REGEN BUFFER SEGMENT 2533 <1> ; OUTPUT 2534 <1> ; NONE -- THE REGEN BUFFER IS MODIFIED 2535 <1> ; 2536 <1> ; bh = 0 (02/09/2014) 2537 <1> ; 2538 <1> ; ((ah = 3)) 2539 <1> ; cl = left upper column 2540 <1> ; ch = left upper row 2541 <1> ; dl = right lower column 2542 <1> ; dh = right lower row 2543 <1> ; 2544 <1> ; al = line count 2545 <1> ; ah = attribute to be used on blanked line 2546 <1> ; bl = video page number (0 to 7) 2547 <1> ; 2548 <1> 2549 <1> ; 02/02/2022 'scroll_up' code 2550 <1> ; ------------------------------------------------------ 2551 <1> ; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm') 2552 <1> 2553 <1> ; INPUT: 2554 <1> ; 2555 <1> ; al = line count 2556 <1> ; (0 or 1) .. 0 -> clear video page 2557 <1> ; ah = attribute to be used on blanked line 2558 <1> ; bl = video page number (0 to 7) 2559 <1> 2560 <1> ;cli 2561 0000142C 31C9 <1> xor ecx, ecx 2562 0000142E 88C1 <1> mov cl, al ; line count (cl) 2563 00001430 BE00800B00 <1> mov esi, 0B8000h 2564 00001435 3A1D[56610000] <1> cmp bl, [active_page] 2565 0000143B 7411 <1> je short n1 2566 0000143D 20DB <1> and bl, bl 2567 0000143F 7422 <1> jz short n3 2568 00001441 88DD <1> mov ch, bl ; video page number 2569 <1> n0: 2570 00001443 6681C6A00F <1> add si, 25*80*2 2571 00001448 FECD <1> dec ch 2572 0000144A 75F7 <1> jnz short n0 2573 0000144C EB15 <1> jmp short n3 2574 <1> n1: 2575 0000144E 660335[44610000] <1> add si, [CRT_START] 2576 <1> ; 2577 00001455 66BADA03 <1> mov dx, 3DAh ; guaranteed to be color card here 2578 <1> n2: ; wait_display_enable 2579 00001459 EC <1> in al, dx ; get port 2580 0000145A A808 <1> test al, RVRT ; wait for vertical retrace 2581 0000145C 74FB <1> jz short n2 ; wait_display_enable 2582 0000145E B025 <1> mov al, 25h 2583 00001460 B2D8 <1> mov dl, 0D8h ; address control port 2584 00001462 EE <1> out dx, al ; turn off video during vertical retrace 2585 <1> n3: 2586 <1> ; cl = line count 2587 <1> ; ah = attribute/color 2588 00001463 89F7 <1> mov edi, esi 2589 00001465 20C9 <1> and cl, cl 2590 00001467 741F <1> jz short n6 2591 00001469 6681C6A000 <1> add si, 80*2 ; + 160 bytes 2592 0000146E 66B98007 <1> mov cx, 24*80 ; 24 rows/lines 2593 00001472 F366A5 <1> rep movsw 2594 00001475 B150 <1> mov cl, 80 ; 1 row (will be cleared) 2595 <1> n4: 2596 <1> ; ah = character attribute/cocor 2597 00001477 B020 <1> mov al, 20h ; fill with blanks 2598 00001479 F366AB <1> rep stosw 2599 <1> 2600 0000147C 3A1D[56610000] <1> cmp bl, [active_page] 2601 00001482 7503 <1> jne short n5 2602 <1> 2603 <1> ;mov al, [crt_mode_set] ; get the value of mode set 2604 00001484 B029 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 2605 <1> ;mov dx, 03D8h ; always set color card port 2606 00001486 EE <1> out dx, al 2607 <1> n5: 2608 00001487 C3 <1> retn 2609 <1> n6: 2610 <1> ; clear video page 2611 00001488 66B9D007 <1> mov cx, 25*80 ; 25 rows/lines 2612 0000148C EBE9 <1> jmp short n4 2613 <1> 2614 <1> ; 26/02/2022 2615 <1> %if 0 ; 16/01/2016 'scroll_up' code 2616 <1> ; ------------------------------------------------------ 2617 <1> 2618 <1> ; Test Line Count 2619 <1> or al, al 2620 <1> jz short al_set 2621 <1> mov bh, dh ; subtract lower row from upper row 2622 <1> sub bh, ch 2623 <1> inc bh ; adjust difference by 1 2624 <1> cmp bh, al ; line count = amount of rows in window? 2625 <1> jne short al_set ; if not the we're all set 2626 <1> xor al, al ; otherwise set al to zero 2627 <1> al_set: 2628 <1> xor bh, bh ; 0 2629 <1> ;push ax 2630 <1> push eax ; 26/02/2022 2631 <1> ;mov esi, [crt_base] 2632 <1> mov esi, 0B8000h 2633 <1> cmp bl, [active_page] 2634 <1> jne short n0 2635 <1> ; 2636 <1> mov ax, [CRT_START] 2637 <1> add si, ax 2638 <1> jmp short n1 2639 <1> n0: 2640 <1> and bl, bl 2641 <1> jz short n1 2642 <1> mov al, bl 2643 <1> n0x: 2644 <1> ;add si, [CRT_LEN] 2645 <1> ;add esi, 80*25*2 2646 <1> add si, 80*25*2 2647 <1> dec al 2648 <1> jnz short n0x 2649 <1> n1: 2650 <1> ; Scroll position 2651 <1> ;push dx ; 26/02/2022 2652 <1> mov dx, cx ; now, upper left position in DX 2653 <1> call position 2654 <1> add esi, eax 2655 <1> mov edi, esi 2656 <1> ;pop dx ; lower right position in DX 2657 <1> sub dx, cx 2658 <1> inc dh ; dh = #rows 2659 <1> inc dl ; dl = #cols in block 2660 <1> ;pop ax ; al = line count, ah = attribute 2661 <1> pop eax ; 26/02/2022 2662 <1> xor ecx, ecx 2663 <1> mov cx, ax 2664 <1> ;mov ah, [CRT_COLS] 2665 <1> mov ah, 80 2666 <1> mul ah ; determine offset to from address 2667 <1> add ax, ax ; *2 for attribute byte 2668 <1> ; 2669 <1> ;push ax ; offset 2670 <1> ;push dx 2671 <1> ; 26/02/2022 2672 <1> push eax 2673 <1> push edx 2674 <1> ; 2675 <1> ; 04/04/2014 2676 <1> mov dx, 3DAh ; guaranteed to be color card here 2677 <1> n8: ; wait_display_enable 2678 <1> in al, dx ; get port 2679 <1> test al, RVRT ; wait for vertical retrace 2680 <1> jz short n8 ; wait_display_enable 2681 <1> mov al, 25h 2682 <1> mov dl, 0D8h ; address control port 2683 <1> out dx, al ; turn off video during vertical retrace 2684 <1> ;pop dx ; #rows, #cols 2685 <1> ;pop ax ; offset 2686 <1> ; 26/02/2022 2687 <1> pop edx 2688 <1> pop eax 2689 <1> xchg ax, cx ; 2690 <1> ; ecx = offset, al = line count, ah = attribute 2691 <1> ;n9: 2692 <1> or al, al 2693 <1> jz short n3 2694 <1> add esi, ecx ; from address for scroll 2695 <1> mov bh, dh ; #rows in block 2696 <1> sub bh, al ; #rows to be moved 2697 <1> n2: 2698 <1> ; Move rows 2699 <1> mov cl, dl ; get # of cols to move 2700 <1> push esi 2701 <1> push edi ; save start address 2702 <1> n10: 2703 <1> movsw ; move that line on screen 2704 <1> dec cl 2705 <1> jnz short n10 2706 <1> pop edi 2707 <1> pop esi ; recover addresses 2708 <1> ;mov cl, [CRT_COLS] 2709 <1> ;add cl, cl 2710 <1> ;mov ecx, 80*2 2711 <1> mov cx, 80*2 2712 <1> add esi, ecx ; next line 2713 <1> add edi, ecx 2714 <1> dec bh ; count of lines to move 2715 <1> jnz short n2 ; row loop 2716 <1> ; bh = 0 2717 <1> mov dh, al ; #rows 2718 <1> n3: 2719 <1> ; attribute in ah 2720 <1> mov al, ' ' ; fill with blanks 2721 <1> n3x: 2722 <1> ; Clear rows 2723 <1> ; dh = #rows 2724 <1> mov cl, dl ; get # of cols to clear 2725 <1> push edi ; save address 2726 <1> n11: 2727 <1> stosw ; store fill character 2728 <1> dec cl 2729 <1> jnz short n11 2730 <1> pop edi ; recover address 2731 <1> ;mov cl, [CRT_COLS] 2732 <1> ;add cl, cl 2733 <1> ;mov ecx, 80*2 2734 <1> mov cl, 80*2 2735 <1> add edi, ecx 2736 <1> dec dh 2737 <1> jnz short n3x ; 16/01/2016 2738 <1> ; 2739 <1> cmp bl, [active_page] 2740 <1> jne short n6 2741 <1> ;mov al, [CRT_MODE_SET] ; get the value of mode set 2742 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 2743 <1> mov dx, 03D8h ; always set color card port 2744 <1> out dx, al 2745 <1> n6: 2746 <1> retn 2747 <1> 2748 <1> %endif 2749 <1> 2750 <1> write_c_current: 2751 <1> ; 02/02/2022 2752 <1> ; 30/08/2014 (Retro UNIX 386 v1) 2753 <1> ; 18/01/2014 2754 <1> ; 04/12/2013 2755 <1> ; 2756 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2757 <1> ; 2758 <1> ; WRITE_C_CURRENT 2759 <1> ; THIS ROUTINE WRITES THE CHARACTER AT 2760 <1> ; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED 2761 <1> ; INPUT 2762 <1> ; (AH) = CURRENT CRT MODE 2763 <1> ; (BH) = DISPLAY PAGE 2764 <1> ; (CX) = COUNT OF CHARACTERS TO WRITE 2765 <1> ; (AL) = CHAR TO WRITE 2766 <1> ; (DS) = DATA SEGMENT 2767 <1> ; (ES) = REGEN SEGMENT 2768 <1> ; OUTPUT 2769 <1> ; DISPLAY REGEN BUFFER UPDATED 2770 <1> 2771 0000148E FA <1> cli 2772 <1> ; bl = video page 2773 <1> ; al = character 2774 <1> ; ah = color/attribute 2775 <1> ;push dx 2776 <1> ;push ax ; save character & attribute/color 2777 <1> ; 02/02/2022 2778 0000148F 52 <1> push edx 2779 00001490 50 <1> push eax 2780 00001491 E86CFFFFFF <1> call find_position ; get regen location and port address 2781 <1> ; esi = regen location 2782 <1> ; dx = status port 2783 <1> ; 2784 <1> ; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE 2785 <1> ; 2786 <1> p41: ; wait for horizontal retrace is low or vertical 2787 00001496 FB <1> sti ; enable interrupts first 2788 00001497 3A1D[56610000] <1> cmp bl, [active_page] 2789 0000149D 7510 <1> jne short p44 2790 0000149F FA <1> cli ; block interrupts for single loop 2791 000014A0 EC <1> in al, dx ; get status from the adapter 2792 000014A1 A808 <1> test al, RVRT ; check for vertical retrace first 2793 000014A3 7509 <1> jnz short p43 ; Do fast write now if vertical retrace 2794 000014A5 A801 <1> test al, RHRZ ; is horizontal retrace low 2795 000014A7 75ED <1> jnz short p41 ; wait until it is 2796 <1> p42: ; wait for either retrace high 2797 000014A9 EC <1> in al, dx ; get status again 2798 000014AA A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 2799 000014AC 74FB <1> jz short p42 ; wait until either retrace active 2800 <1> p43: 2801 000014AE FB <1> sti 2802 <1> p44: 2803 <1> ;pop ax ; restore the character (al) & attribute (ah) 2804 <1> ; 02/02/2022 2805 000014AF 58 <1> pop eax 2806 000014B0 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (crt_base) 2807 <1> ; Retro UNIX 386 v1 feature only! 2808 000014B6 668906 <1> mov [esi], ax 2809 <1> ;pop dx 2810 <1> ; 02/02/2022 2811 000014B9 5A <1> pop edx 2812 000014BA C3 <1> retn 2813 <1> 2814 <1> %if 0 ; 02/02/2022 2815 <1> 2816 <1> set_mode: 2817 <1> ; 02/02/2022 2818 <1> ; 16/01/2016 2819 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2820 <1> ; 2821 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2822 <1> 2823 <1> ;------------------------------------------------------ 2824 <1> ; SET MODE : 2825 <1> ; THIS ROUTINE INITIALIZES THE ATTACHMENT TO : 2826 <1> ; THE SELECTED MODE, THE SCREEN IS BLANKED. : 2827 <1> ; INPUT : 2828 <1> ; (AL) - MODE SELECTED (RANGE 0-7) : 2829 <1> ; OUTPUT : 2830 <1> ; NONE : 2831 <1> ;------------------------------------------------------ 2832 <1> 2833 <1> push edi ; 16/01/2016 2834 <1> push ebx 2835 <1> push edx 2836 <1> push ecx ; 16/01/2016 2837 <1> push eax 2838 <1> 2839 <1> ;mov dx, 03D4h ; address or color card 2840 <1> mov al, 3 2841 <1> ;M8: 2842 <1> mov [CRT_MODE], al ; save mode in global variable 2843 <1> mov al, 29h 2844 <1> ;mov [CRT_MODE_SET], al ; save the mode set value 2845 <1> and al, 037h ; video off, save high resolution bit 2846 <1> ;push dx ; save port value 2847 <1> ;add dx, 4 ; point to control register 2848 <1> mov dx, 3D8h 2849 <1> out dx, al ; reset video to off to suppress rolling 2850 <1> ;pop dx 2851 <1> ;M9: 2852 <1> mov ebx, video_params ; initialization table 2853 <1> ;mov ax, [ebx+10] ; get the cursor mode from the table 2854 <1> ;xchg ah, al 2855 <1> ;mov [CURSOR_MODE], ax ; save cursor mode 2856 <1> xor ah, ah ; ah is register number during loop 2857 <1> 2858 <1> ;----- LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE 2859 <1> ; 02/02/2022 2860 <1> ; dx = 3D8h 2861 <1> xor ecx, ecx 2862 <1> mov cl, 16 2863 <1> ;mov ecx, 16 ; 16/01/2016 2864 <1> M10: ; initialization loop 2865 <1> mov al, ah ; get 6845 register number 2866 <1> out dx, al 2867 <1> ;inc dx ; point to data port 2868 <1> ; 02/02/2022 2869 <1> inc dl ; 3D9h 2870 <1> inc ah ; next register value 2871 <1> mov al, [ebx] ; get table value 2872 <1> out dx, al ; out to chip 2873 <1> inc ebx ; next in table 2874 <1> ;dec dx ; back to pointer register 2875 <1> ; 02/02/2022 2876 <1> dec dl ; 3D8h 2877 <1> loop M10 ; do the whole table 2878 <1> 2879 <1> ;----- FILL REGEN AREA WITH BLANK 2880 <1> ;xor ax, ax 2881 <1> ;mov [CRT_START], ax ; start address saved in global 2882 <1> ;mov [ACTIVE_PAGE], al ; 0 ; (re)set page value 2883 <1> ;mov ecx, 8192 ; number of words in color card 2884 <1> ; black background, light gray characeter color, space character 2885 <1> ;mov ax, 0720h ; fill char for alpha - attribute 2886 <1> ;M13: ; clear buffer 2887 <1> ;add edi, 0B8000h ; [crt_base] 2888 <1> ;rep stosw ; FILL THE REGEN BUFFER WITH BLANKS 2889 <1> 2890 <1> ;----- ENABLE VIDEO AND CORRECT PORT SETTING 2891 <1> ;mov dx, 3D4h ; mov dx, word [ADDR_6845] 2892 <1> ; prepare to output to video enable port 2893 <1> ;;add dx, 4 ; point to the mode control gerister 2894 <1> ; 02/02/2022 2895 <1> ;mov dx, 3D8h 2896 <1> ; 2897 <1> ;mov al, [CRT_MODE_SET] ; get the mode set value 2898 <1> mov al, 29h 2899 <1> out dx, al ; set video enable port 2900 <1> 2901 <1> ;----- DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY 2902 <1> ;----- AND THE NUMBER TO BE USED FOR TTY INTERFACE 2903 <1> ; 2904 <1> ;mov byte [CRT_COLS], 80h ; initialize number of columns count 2905 <1> ; 2906 <1> ;----- SET CURSOR POSITIONS 2907 <1> ;push edi 2908 <1> ;mov word [CRT_LEN], 80*25*2 2909 <1> mov edi, cursor_posn 2910 <1> mov ecx, 4 ; clear all cursor positions (16 bytes) 2911 <1> xor eax, eax 2912 <1> rep stosd ; fill with zeroes 2913 <1> ;pop edi 2914 <1> 2915 <1> ;----- SET UP OVERSCAN REGISTER 2916 <1> inc dx ; set overscan port to a default 2917 <1> mov al, 30h ; 30H valuye for all modes except 640X200 bw 2918 <1> ;M14: 2919 <1> out dx, al ; output the correct value to 3D9 port 2920 <1> ;mov [CRT_PALETTE], al ; save the value for future use 2921 <1> 2922 <1> ;----- NORMAL RETURN FROM ALL VIDEO RETURNS 2923 <1> ; 2924 <1> pop eax 2925 <1> pop ecx ; 16/01/2016 2926 <1> pop edx 2927 <1> pop ebx 2928 <1> pop edi ; 16/01/2016 2929 <1> retn 2930 <1> 2931 <1> %endif 2932 <1> 2933 <1> tty_sw: 2934 <1> ; 02/02/2022 2935 <1> ; 30/06/2015 2936 <1> ; 27/06/2015 2937 <1> ; 07/09/2014 2938 <1> ; 02/09/2014 (Retro UNIX 386 v1 - beginning) 2939 <1> ; 2940 <1> ; (Modified registers : EAX) 2941 <1> ; 2942 <1> ;mov byte [u.quant], 0 ; 04/03/2014 2943 <1> ; 2944 <1> ;act_disp_page: 2945 <1> ; 30/06/2015 2946 <1> ; 04/03/2014 (act_disp_page --> tty_sw) 2947 <1> ; 10/12/2013 2948 <1> ; 04/12/2013 2949 <1> ; 2950 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 2951 <1> ; 2952 <1> ; ACT_DISP_PAGE 2953 <1> ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING 2954 <1> ; THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT 2955 <1> ; INPUT 2956 <1> ; AL HAS THE NEW ACTIVE DISPLAY PAGE 2957 <1> ; OUTPUT 2958 <1> ; THE 6845 IS RESET TO DISPLAY THAT PAGE 2959 <1> 2960 <1> ;cli 2961 <1> 2962 000014BB 53 <1> push ebx 2963 <1> ;push cx 2964 <1> ;push dx 2965 <1> ; 02/02/2022 2966 000014BC 51 <1> push ecx 2967 000014BD 52 <1> push edx 2968 <1> ; 2969 000014BE A2[56610000] <1> mov [active_page], al ; save active page value ; [ptty] 2970 <1> ;;mov cx, [CRT_LEN] ; get saved length of regen buffer 2971 <1> ;mov cx, 25*80*2 2972 <1> ; 02/02/2022 2973 000014C3 B9A00F0000 <1> mov ecx, 25*80*2 2974 <1> ; 27/06/2015 2975 000014C8 0FB6D8 <1> movzx ebx, al 2976 <1> ; 02/02/2022 2977 000014CB 89D8 <1> mov eax, ebx 2978 <1> ; 2979 <1> ;cbw ; 07/09/2014 (ah=0) 2980 <1> ;mul cx ; display page times regen length 2981 <1> ; 02/02/2022 2982 000014CD F7E1 <1> mul ecx 2983 <1> ; 10/12/2013 2984 000014CF 66A3[44610000] <1> mov [CRT_START], ax ; save start address for later 2985 <1> ;mov cx, ax ; start address to cx 2986 <1> ; 02/02/2022 2987 000014D5 89C1 <1> mov ecx, eax 2988 <1> ;sar cx, 1 2989 <1> ;shr cx, 1 ; divide by 2 for 6845 handling 2990 <1> ; 02/02/2022 2991 000014D7 D1E9 <1> shr ecx, 1 2992 000014D9 B40C <1> mov ah, 12 ; 6845 register for start address 2993 000014DB E8EFFEFFFF <1> call m16 2994 <1> ;sal bx, 1 2995 <1> ; 01/09/2014 2996 000014E0 D0E3 <1> shl bl, 1 ; * 2 for word offset 2997 000014E2 81C3[46610000] <1> add ebx, cursor_posn 2998 000014E8 668B13 <1> mov dx, [ebx] ; get cursor for this page 2999 000014EB E8CDFEFFFF <1> call m18 3000 <1> ; 3001 <1> ;pop dx 3002 <1> ;pop cx 3003 <1> ; 02/02/2022 3004 000014F0 5A <1> pop edx 3005 000014F1 59 <1> pop ecx 3006 000014F2 5B <1> pop ebx 3007 <1> ; 3008 <1> ;sti 3009 <1> ; 3010 000014F3 C3 <1> retn 3011 <1> 3012 <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015 3013 <1> 3014 <1> ; /// End Of VIDEO FUNCTIONS /// 1894 1895 setup_rtc_int: 1896 ; source: http://wiki.osdev.org/RTC 1897 000014F4 FA cli ; disable interrupts 1898 ; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6) 1899 ; in order to change this ... 1900 ; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024 1901 ; (rate must be above 2 and not over 15) 1902 ; new rate = 15 --> 32768 >> (15-1) = 2 Hz 1903 000014F5 B08A mov al, 8Ah 1904 000014F7 E670 out 70h, al ; set index to register A, disable NMI 1905 000014F9 90 nop 1906 000014FA E471 in al, 71h ; get initial value of register A 1907 000014FC 88C4 mov ah, al 1908 000014FE 80E4F0 and ah, 0F0h 1909 00001501 B08A mov al, 8Ah 1910 00001503 E670 out 70h, al ; reset index to register A 1911 00001505 88E0 mov al, ah 1912 00001507 0C0F or al, 0Fh ; new rate (0Fh -> 15) 1913 00001509 E671 out 71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 1914 ; enable RTC interrupt 1915 0000150B B08B mov al, 8Bh ; 1916 0000150D E670 out 70h, al ; select register B and disable NMI 1917 0000150F 90 nop 1918 00001510 E471 in al, 71h ; read the current value of register B 1919 00001512 88C4 mov ah, al ; 1920 00001514 B08B mov al, 8Bh ; 1921 00001516 E670 out 70h, al ; set the index again (a read will reset the index to register B) 1922 00001518 88E0 mov al, ah ; 1923 0000151A 0C40 or al, 40h ; 1924 0000151C E671 out 71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B 1925 0000151E FB sti 1926 0000151F C3 retn 1927 1928 ; Write memory information 1929 ; Temporary Code 1930 ; 06/11/2014 1931 ; 14/08/2015 1932 memory_info: 1933 00001520 A1[2C610000] mov eax, [memory_size] ; in pages 1934 00001525 50 push eax 1935 00001526 C1E00C shl eax, 12 ; in bytes 1936 00001529 BB0A000000 mov ebx, 10 1937 0000152E 89D9 mov ecx, ebx ; 10 1938 00001530 BE[955D0000] mov esi, mem_total_b_str 1939 00001535 E8AE000000 call bintdstr 1940 0000153A 58 pop eax 1941 0000153B B107 mov cl, 7 1942 0000153D BE[B95D0000] mov esi, mem_total_p_str 1943 00001542 E8A1000000 call bintdstr 1944 ; 14/08/2015 1945 00001547 E8B9000000 call calc_free_mem 1946 ; edx = calculated free pages 1947 ; ecx = 0 1948 0000154C A1[30610000] mov eax, [free_pages] 1949 00001551 39D0 cmp eax, edx ; calculated free mem value 1950 ; and initial free mem value are same or not? 1951 00001553 751D jne short pmim ; print mem info with '?' if not 1952 00001555 52 push edx ; free memory in pages 1953 ;mov eax, edx 1954 00001556 C1E00C shl eax, 12 ; convert page count 1955 ; to byte count 1956 00001559 B10A mov cl, 10 1957 0000155B BE[D95D0000] mov esi, free_mem_b_str 1958 00001560 E883000000 call bintdstr 1959 00001565 58 pop eax 1960 00001566 B107 mov cl, 7 1961 00001568 BE[FD5D0000] mov esi, free_mem_p_str 1962 0000156D E876000000 call bintdstr 1963 pmim: 1964 00001572 BE[835D0000] mov esi, msg_memory_info 1965 pmim_nb: 1966 00001577 AC lodsb 1967 00001578 08C0 or al, al 1968 0000157A 740D jz short pmim_ok 1969 0000157C 56 push esi 1970 0000157D 31DB xor ebx, ebx ; 0 1971 ; Video page 0 (bl=0) 1972 0000157F B407 mov ah, 07h ; Black background, 1973 ; light gray forecolor 1974 00001581 E816FDFFFF call write_tty 1975 00001586 5E pop esi 1976 00001587 EBEE jmp short pmim_nb 1977 pmim_ok: 1978 00001589 C3 retn 1979 1980 ; Convert binary number to hexadecimal string 1981 ; 10/05/2015 1982 ; dsectpm.s (28/02/2015) 1983 ; Retro UNIX 386 v1 - Kernel v0.2.0.6 1984 ; 01/12/2014 1985 ; 25/11/2014 1986 ; 1987 bytetohex: 1988 ; INPUT -> 1989 ; AL = byte (binary number) 1990 ; OUTPUT -> 1991 ; AX = hexadecimal string 1992 ; 1993 0000158A 53 push ebx 1994 0000158B 31DB xor ebx, ebx 1995 0000158D 88C3 mov bl, al 1996 0000158F C0EB04 shr bl, 4 1997 00001592 8A9B[D8150000] mov bl, [ebx+hexchrs] 1998 00001598 86D8 xchg bl, al 1999 0000159A 80E30F and bl, 0Fh 2000 0000159D 8AA3[D8150000] mov ah, [ebx+hexchrs] 2001 000015A3 5B pop ebx 2002 000015A4 C3 retn 2003 2004 wordtohex: 2005 ; INPUT -> 2006 ; AX = word (binary number) 2007 ; OUTPUT -> 2008 ; EAX = hexadecimal string 2009 ; 2010 000015A5 53 push ebx 2011 000015A6 31DB xor ebx, ebx 2012 000015A8 86E0 xchg ah, al 2013 000015AA 6650 push ax 2014 000015AC 88E3 mov bl, ah 2015 000015AE C0EB04 shr bl, 4 2016 000015B1 8A83[D8150000] mov al, [ebx+hexchrs] 2017 000015B7 88E3 mov bl, ah 2018 000015B9 80E30F and bl, 0Fh 2019 000015BC 8AA3[D8150000] mov ah, [ebx+hexchrs] 2020 000015C2 C1E010 shl eax, 16 2021 000015C5 6658 pop ax 2022 000015C7 5B pop ebx 2023 000015C8 EBC0 jmp short bytetohex 2024 ;mov bl, al 2025 ;shr bl, 4 2026 ;mov bl, [ebx+hexchrs] 2027 ;xchg bl, al 2028 ;and bl, 0Fh 2029 ;mov ah, [ebx+hexchrs] 2030 ;pop ebx 2031 ;retn 2032 2033 dwordtohex: 2034 ; INPUT -> 2035 ; EAX = dword (binary number) 2036 ; OUTPUT -> 2037 ; EDX:EAX = hexadecimal string 2038 ; 2039 000015CA 50 push eax 2040 000015CB C1E810 shr eax, 16 2041 000015CE E8D2FFFFFF call wordtohex 2042 000015D3 89C2 mov edx, eax 2043 000015D5 58 pop eax 2044 ;call wordtohex 2045 ;retn 2046 ; 02/01/2022 2047 000015D6 EBCD jmp short wordtohex 2048 2049 ; 10/05/2015 2050 hex_digits: 2051 hexchrs: 2052 000015D8 303132333435363738- db '0123456789ABCDEF' 2052 000015E1 39414243444546 2053 2054 ; Convert binary number to decimal/numeric string 2055 ; 06/11/2014 2056 ; Temporary Code 2057 ; 2058 2059 bintdstr: 2060 ; EAX = binary number 2061 ; ESI = decimal/numeric string address 2062 ; EBX = divisor (10) 2063 ; ECX = string length (<=10) 2064 000015E8 01CE add esi, ecx 2065 btdstr0: 2066 000015EA 4E dec esi 2067 000015EB 31D2 xor edx, edx 2068 000015ED F7F3 div ebx 2069 000015EF 80C230 add dl, 30h 2070 000015F2 8816 mov [esi], dl 2071 000015F4 FEC9 dec cl 2072 000015F6 740C jz short btdstr2 ; 02/01/2022 (short jump) 2073 000015F8 09C0 or eax, eax 2074 000015FA 75EE jnz short btdstr0 2075 btdstr1: 2076 000015FC 4E dec esi 2077 000015FD C60620 mov byte [esi], 20h ; blank space 2078 00001600 FEC9 dec cl 2079 00001602 75F8 jnz short btdstr1 2080 btdstr2: 2081 00001604 C3 ret 2082 2083 ; Calculate free memory pages on M.A.T. 2084 ; 06/11/2014 2085 ; Temporary Code 2086 ; 2087 2088 calc_free_mem: 2089 00001605 31D2 xor edx, edx 2090 ;xor ecx, ecx 2091 ;mov cx, [mat_size] ; in pages 2092 ; 02/01/2022 2093 00001607 8B0D[40610000] mov ecx, [mat_size] ; in pages 2094 0000160D C1E10A shl ecx, 10 ; 1024 dwords per page 2095 00001610 BE00001000 mov esi, MEM_ALLOC_TBL 2096 cfm0: 2097 00001615 AD lodsd 2098 00001616 51 push ecx 2099 00001617 B920000000 mov ecx, 32 2100 cfm1: 2101 0000161C D1E8 shr eax, 1 2102 0000161E 7301 jnc short cfm2 2103 00001620 42 inc edx 2104 cfm2: 2105 00001621 E2F9 loop cfm1 2106 00001623 59 pop ecx 2107 00001624 E2EF loop cfm0 2108 00001626 C3 ret 2109 2110 %include 'diskio.inc' ; 07/03/2015 2111 <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.6) - DISKIO.INC 2112 <1> ; Last Modification: 18/07/2022 2113 <1> ; (Initialized Disk Parameters Data is in 'DISKDATA.INC') 2114 <1> ; (Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 2115 <1> 2116 <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project) 2117 <1> 2118 <1> ; ///////// DISK I/O SYSTEM /////////////// 2119 <1> 2120 <1> ; 11/07/2022 2121 <1> ;; 06/02/2015 2122 <1> ;diskette_io: 2123 <1> ; pushfd 2124 <1> ; push cs 2125 <1> ; call DISKETTE_IO_1 2126 <1> ; retn 2127 <1> 2128 <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;; 2129 <1> ;////////////////////////////////////////////////////// 2130 <1> 2131 <1> ; 11/07/2022 - (direct call instead of int 13h simulation) 2132 <1> ; Function in AL 2133 <1> ; 0 = reset 2134 <1> ; 1 = read 2135 <1> ; 2 = write 2136 <1> ; Disk drive number in DL 2137 <1> ; 0 & 1 = floppy disks 2138 <1> ; 80h .. 83h = hard disks 2139 <1> ; Sector address (LBA) in ECX 2140 <1> ; Buffer address in EBX 2141 <1> ; R/W sector count is (always) 1 2142 <1> ; 2143 <1> ; Return: 2144 <1> ; Status in AH (>0 = error code) 2145 <1> ; if CF = 1 -> error code in AH 2146 <1> ; if CF = 0 -> successful 2147 <1> ; AL = undefined 2148 <1> ; 2149 <1> ; Modified registers: (only) EAX 2150 <1> 2151 <1> ; 10/07/2022 2152 <1> ; 08/07/2022 - (diskio code has been simplified/shortened 2153 <1> ; by removing unused IBM PC-AT disk functions) 2154 <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project) 2155 <1> ; 20/02/2015 2156 <1> ; 06/02/2015 (unix386.s) 2157 <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s) 2158 <1> ; 2159 <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC) 2160 <1> ; 2161 <1> ; ADISK.EQU 2162 <1> 2163 <1> ;----- Wait control constants 2164 <1> 2165 <1> ;amount of time to wait while RESET is active. 2166 <1> 2167 <1> WAITCPU_RESET_ON EQU 21 ;Reset on must last at least 14us 2168 <1> ;at 250 KBS xfer rate. 2169 <1> ;see INTEL MCS, 1985, pg. 5-456 2170 <1> 2171 <1> WAITCPU_FOR_STATUS EQU 100 ;allow 30 microseconds for 2172 <1> ;status register to become valid 2173 <1> ;before re-reading. 2174 <1> 2175 <1> ;After sending a byte to NEC, status register may remain 2176 <1> ;incorrectly set for 24 us. 2177 <1> 2178 <1> WAITCPU_RQM_LOW EQU 24 ;number of loops to check for 2179 <1> ;RQM low. 2180 <1> 2181 <1> ; COMMON.MAC 2182 <1> ; 2183 <1> ; Timing macros 2184 <1> ; 2185 <1> 2186 <1> %macro SIODELAY 0 ; SHORT IODELAY 2187 <1> jmp short $+2 2188 <1> %endmacro 2189 <1> 2190 <1> %macro IODELAY 0 ; NORMAL IODELAY 2191 <1> jmp short $+2 2192 <1> jmp short $+2 2193 <1> %endmacro 2194 <1> 2195 <1> %macro NEWIODELAY 0 2196 <1> out 0EBh,al 2197 <1> %endmacro 2198 <1> 2199 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 2200 <1> ;;; WAIT_FOR_MEM 2201 <1> ;WAIT_FDU_INT_LO equ 017798 ; 2.5 secs in 30 micro units. 2202 <1> ;WAIT_FDU_INT_HI equ 1 2203 <1> WAIT_FDU_INT_LH equ 83334 ; 27/02/2015 (2.5 seconds waiting) 2204 <1> ;;; WAIT_FOR_PORT 2205 <1> ;WAIT_FDU_SEND_LO equ 16667 ; .5 secons in 30 us units. 2206 <1> ;WAIT_FDU_SEND_HI equ 0 2207 <1> WAIT_FDU_SEND_LH equ 16667 ; 27/02/2015 2208 <1> ;Time to wait while waiting for each byte of NEC results = .5 2209 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 2210 <1> ;WAIT_FDU_RESULTS_LO equ 16667 ; .5 seconds in 30 micro units. 2211 <1> ;WAIT_FDU_RESULTS_HI equ 0 2212 <1> WAIT_FDU_RESULTS_LH equ 16667 ; 27/02/2015 2213 <1> ;;; WAIT_REFRESH 2214 <1> ;amount of time to wait for head settle, per unit in parameter 2215 <1> ;table = 1 ms. 2216 <1> WAIT_FDU_HEAD_SETTLE equ 33 ; 1 ms in 30 micro units. 2217 <1> 2218 <1> 2219 <1> ; //////////////// DISKETTE I/O //////////////// 2220 <1> 2221 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC) 2222 <1> 2223 <1> ;---------------------------------------- 2224 <1> ; EQUATES USED BY POST AND BIOS : 2225 <1> ;---------------------------------------- 2226 <1> 2227 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2228 <1> ;PORT_A EQU 060H ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2229 <1> ;PORT_B EQU 061H ; PORT B READ/WRITE DIAGNOSTIC REGISTER 2230 <1> ;REFRESH_BIT EQU 00010000B ; REFRESH TEST BIT 2231 <1> 2232 <1> ;---------------------------------------- 2233 <1> ; CMOS EQUATES FOR THIS SYSTEM : 2234 <1> ;------------------------------------------------------------------------------- 2235 <1> ;CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 2236 <1> ;CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 2237 <1> ;NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 2238 <1> ; HIGH BIT OF CMOS LOCATION ADDRESS 2239 <1> 2240 <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- 2241 <1> CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; 2242 <1> ; EQU 011H ; - RESERVED ;C 2243 <1> CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H 2244 <1> ; EQU 013H ; - RESERVED ;E 2245 <1> CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C 2246 <1> 2247 <1> ;---------- DISKETTE EQUATES --------------------------------------------------- 2248 <1> INT_FLAG EQU 10000000B ; INTERRUPT OCCURRENCE FLAG 2249 <1> DSK_CHG EQU 10000000B ; DISKETTE CHANGE FLAG MASK BIT 2250 <1> DETERMINED EQU 00010000B ; SET STATE DETERMINED IN STATE BITS 2251 <1> HOME EQU 00010000B ; TRACK 0 MASK 2252 <1> SENSE_DRV_ST EQU 00000100B ; SENSE DRIVE STATUS COMMAND 2253 <1> TRK_SLAP EQU 030H ; CRASH STOP (48 TPI DRIVES) 2254 <1> QUIET_SEEK EQU 00AH ; SEEK TO TRACK 10 2255 <1> ;MAX_DRV EQU 2 ; MAX NUMBER OF DRIVES 2256 <1> HD12_SETTLE EQU 15 ; 1.2 M HEAD SETTLE TIME 2257 <1> HD320_SETTLE EQU 20 ; 320 K HEAD SETTLE TIME 2258 <1> MOTOR_WAIT EQU 37 ; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF 2259 <1> 2260 <1> ;---------- DISKETTE ERRORS ---------------------------------------------------- 2261 <1> ;TIME_OUT EQU 080H ; ATTACHMENT FAILED TO RESPOND 2262 <1> ;BAD_SEEK EQU 040H ; SEEK OPERATION FAILED 2263 <1> BAD_NEC EQU 020H ; DISKETTE CONTROLLER HAS FAILED 2264 <1> BAD_CRC EQU 010H ; BAD CRC ON DISKETTE READ 2265 <1> MED_NOT_FND EQU 00CH ; MEDIA TYPE NOT FOUND 2266 <1> DMA_BOUNDARY EQU 009H ; ATTEMPT TO DMA ACROSS 64K BOUNDARY 2267 <1> BAD_DMA EQU 008H ; DMA OVERRUN ON OPERATION 2268 <1> MEDIA_CHANGE EQU 006H ; MEDIA REMOVED ON DUAL ATTACH CARD 2269 <1> RECORD_NOT_FND EQU 004H ; REQUESTED SECTOR NOT FOUND 2270 <1> WRITE_PROTECT EQU 003H ; WRITE ATTEMPTED ON WRITE PROTECT DISK 2271 <1> BAD_ADDR_MARK EQU 002H ; ADDRESS MARK NOT FOUND 2272 <1> BAD_CMD EQU 001H ; BAD COMMAND PASSED TO DISKETTE I/O 2273 <1> 2274 <1> ;---------- DISK CHANGE LINE EQUATES ------------------------------------------- 2275 <1> NOCHGLN EQU 001H ; NO DISK CHANGE LINE AVAILABLE 2276 <1> CHGLN EQU 002H ; DISK CHANGE LINE AVAILABLE 2277 <1> 2278 <1> ;---------- MEDIA/DRIVE STATE INDICATORS --------------------------------------- 2279 <1> TRK_CAPA EQU 00000001B ; 80 TRACK CAPABILITY 2280 <1> FMT_CAPA EQU 00000010B ; MULTIPLE FORMAT CAPABILITY (1.2M) 2281 <1> DRV_DET EQU 00000100B ; DRIVE DETERMINED 2282 <1> MED_DET EQU 00010000B ; MEDIA DETERMINED BIT 2283 <1> DBL_STEP EQU 00100000B ; DOUBLE STEP BIT 2284 <1> RATE_MSK EQU 11000000B ; MASK FOR CLEARING ALL BUT RATE 2285 <1> RATE_500 EQU 00000000B ; 500 KBS DATA RATE 2286 <1> RATE_300 EQU 01000000B ; 300 KBS DATA RATE 2287 <1> RATE_250 EQU 10000000B ; 250 KBS DATA RATE 2288 <1> STRT_MSK EQU 00001100B ; OPERATION START RATE MASK 2289 <1> SEND_MSK EQU 11000000B ; MASK FOR SEND RATE BITS 2290 <1> 2291 <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY ------------------------- 2292 <1> M3D3U EQU 00000000B ; 360 MEDIA/DRIVE NOT ESTABLISHED 2293 <1> M3D1U EQU 00000001B ; 360 MEDIA,1.2DRIVE NOT ESTABLISHED 2294 <1> M1D1U EQU 00000010B ; 1.2 MEDIA/DRIVE NOT ESTABLISHED 2295 <1> MED_UNK EQU 00000111B ; NONE OF THE ABOVE 2296 <1> 2297 <1> ;---------- INTERRUPT EQUATES -------------------------------------------------- 2298 <1> ;EOI EQU 020H ; END OF INTERRUPT COMMAND TO 8259 2299 <1> ;INTA00 EQU 020H ; 8259 PORT 2300 <1> INTA01 EQU 021H ; 8259 PORT 2301 <1> INTB00 EQU 0A0H ; 2ND 8259 2302 <1> INTB01 EQU 0A1H ; 2303 <1> 2304 <1> ;------------------------------------------------------------------------------- 2305 <1> DMA08 EQU 008H ; DMA STATUS REGISTER PORT ADDRESS 2306 <1> DMA EQU 000H ; DMA CH.0 ADDRESS REGISTER PORT ADDRESS 2307 <1> DMA18 EQU 0D0H ; 2ND DMA STATUS PORT ADDRESS 2308 <1> DMA1 EQU 0C0H ; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS 2309 <1> ;------------------------------------------------------------------------------- 2310 <1> ;TIMER EQU 040H ; 8254 TIMER - BASE ADDRESS 2311 <1> 2312 <1> ;------------------------------------------------------------------------------- 2313 <1> DMA_PAGE EQU 081H ; START OF DMA PAGE REGISTERS 2314 <1> 2315 <1> ; 10/07/2022 2316 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2317 <1> ; 06/02/2015 (unix386.s, protected mode modifications) 2318 <1> ; (unix386.s <-- dsectrm2.s) 2319 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC) 2320 <1> 2321 <1> ; 10/12/2014 2322 <1> ; 2323 <1> ;int40h: 2324 <1> ; pushf 2325 <1> ; push cs 2326 <1> ; ;cli 2327 <1> ; call DISKETTE_IO_1 2328 <1> ; retn 2329 <1> 2330 <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS 2331 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 2332 <1> ; 2333 <1> 2334 <1> ;-- Retro UNIX 386 v1.1 (Kernel v0.2.1.5) ---08/07/2022------------------------- 2335 <1> ; DISKETTE I/O 2336 <1> ; THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB, 2337 <1> ; 1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES. 2338 <1> ; INPUT 2339 <1> ; (AH)= 00H RESET DISKETTE SYSTEM 2340 <1> ; HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED 2341 <1> ; ON ALL DRIVES 2342 <1> ;------------------------------------------------------------------------------- 2343 <1> ; (AH)= 01H READ THE DESIRED SECTORS INTO MEMORY 2344 <1> ;------------------------------------------------------------------------------- 2345 <1> ; (AH)= 02H WRITE THE DESIRED SECTORS FROM MEMORY 2346 <1> ;------------------------------------------------------------------------------- 2347 <1> ; 2348 <1> ; REGISTERS FOR READ/WRITE 2349 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 2350 <1> ; (DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED) 2351 <1> ; (CH) - TRACK NUMBER (NOT VALUE CHECKED) 2352 <1> ; MEDIA DRIVE TRACK NUMBER 2353 <1> ; 320/360 320/360 0-39 2354 <1> ; 320/360 1.2M 0-39 2355 <1> ; 1.2M 1.2M 0-79 2356 <1> ; 720K 720K 0-79 2357 <1> ; 1.44M 1.44M 0-79 2358 <1> ; (CL) - SECTOR NUMBER (NOT VALUE CHECKED) 2359 <1> ; MEDIA DRIVE SECTOR NUMBER 2360 <1> ; 320/360 320/360 1-8/9 2361 <1> ; 320/360 1.2M 1-8/9 2362 <1> ; 1.2M 1.2M 1-15 2363 <1> ; 720K 720K 1-9 2364 <1> ; 1.44M 1.44M 1-18 2365 <1> ; (AL) NUMBER OF SECTORS (NOT VALUE CHECKED) 2366 <1> ; MEDIA DRIVE MAX NUMBER OF SECTORS 2367 <1> ; 320/360 320/360 8/9 2368 <1> ; 320/360 1.2M 8/9 2369 <1> ; 1.2M 1.2M 15 2370 <1> ; 720K 720K 9 2371 <1> ; 1.44M 1.44M 18 2372 <1> ; 2373 <1> ; (EBX) - ADDRESS OF BUFFER 2374 <1> ; 2375 <1> ;------------------------------------------------------------------------------- 2376 <1> ; OUTPUT FOR ALL FUNCTIONS 2377 <1> ; AH = STATUS OF OPERATION 2378 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS 2379 <1> ; VARIABLE IN THE DATA SEGMENT OF THIS MODULE 2380 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) 2381 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) 2382 <1> ; FOR READ/WRITE/VERIFY 2383 <1> ; DS,BX,DX,CX PRESERVED 2384 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 2385 <1> ; ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION. 2386 <1> ; ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 2387 <1> ; THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 2388 <1> ; PROBLEM IS NOT DUE TO MOTOR START-UP. 2389 <1> ;------------------------------------------------------------------------------- 2390 <1> ; 2391 <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B) 2392 <1> ; 2393 <1> ; ----------------------------------------------------------------- 2394 <1> ; | | | | | | | | | 2395 <1> ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 2396 <1> ; | | | | | | | | | 2397 <1> ; ----------------------------------------------------------------- 2398 <1> ; | | | | | | | | 2399 <1> ; | | | | | ----------------- 2400 <1> ; | | | | | | 2401 <1> ; | | | | RESERVED | 2402 <1> ; | | | | PRESENT STATE 2403 <1> ; | | | | 000: 360K IN 360K DRIVE UNESTABLISHED 2404 <1> ; | | | | 001: 360K IN 1.2M DRIVE UNESTABLISHED 2405 <1> ; | | | | 010: 1.2M IN 1.2M DRIVE UNESTABLISHED 2406 <1> ; | | | | 011: 360K IN 360K DRIVE ESTABLISHED 2407 <1> ; | | | | 100: 360K IN 1.2M DRIVE ESTABLISHED 2408 <1> ; | | | | 101: 1.2M IN 1.2M DRIVE ESTABLISHED 2409 <1> ; | | | | 110: RESERVED 2410 <1> ; | | | | 111: NONE OF THE ABOVE 2411 <1> ; | | | | 2412 <1> ; | | | ------> MEDIA/DRIVE ESTABLISHED 2413 <1> ; | | | 2414 <1> ; | | --------------> DOUBLE STEPPING REQUIRED 2415 <1> ; | | (360K IN 1.2M DRIVE) 2416 <1> ; | | 2417 <1> ; ------------------------------> DATA TRANSFER RATE FOR THIS DRIVE: 2418 <1> ; 2419 <1> ; 00: 500 KBS 2420 <1> ; 01: 300 KBS 2421 <1> ; 10: 250 KBS 2422 <1> ; 11: RESERVED 2423 <1> ; 2424 <1> ; 2425 <1> 2426 <1> struc MD 2427 00000000 ?? <1> .SPEC1: resb 1 ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2428 00000001 ?? <1> .SPEC2: resb 1 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2429 00000002 ?? <1> .OFF_TIM: resb 1 ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2430 00000003 ?? <1> .BYT_SEC: resb 1 ; 512 BYTES/SECTOR 2431 00000004 ?? <1> .SEC_TRK: resb 1 ; EOT (LAST SECTOR ON TRACK) 2432 00000005 ?? <1> .GAP: resb 1 ; GAP LENGTH 2433 00000006 ?? <1> .DTL: resb 1 ; DTL 2434 00000007 ?? <1> .GAP3: resb 1 ; GAP LENGTH FOR FORMAT 2435 00000008 ?? <1> .FIL_BYT: resb 1 ; FILL BYTE FOR FORMAT 2436 00000009 ?? <1> .HD_TIM: resb 1 ; HEAD SETTLE TIME (MILLISECONDS) 2437 0000000A ?? <1> .STR_TIM: resb 1 ; MOTOR START TIME (1/8 SECONDS) 2438 0000000B ?? <1> .MAX_TRK: resb 1 ; MAX. TRACK NUMBER 2439 0000000C ?? <1> .RATE: resb 1 ; DATA TRANSFER RATE 2440 <1> endstruc 2441 <1> 2442 <1> BIT7OFF EQU 7FH 2443 <1> BIT7ON EQU 80H 2444 <1> 2445 <1> ; 11/07/2022 - (direct call instead of int 13h simulation) 2446 <1> ; Function in AL 2447 <1> ; 0 = reset 2448 <1> ; 1 = read 2449 <1> ; 2 = write 2450 <1> ; Disk drive number in DL 2451 <1> ; 0 & 1 = floppy disks 2452 <1> ; 80h .. 83h = hard disks 2453 <1> ; Sector address (LBA) in ECX 2454 <1> ; Buffer address in EBX 2455 <1> ; R/W sector count is (always) 1 2456 <1> ; 2457 <1> ; Return: 2458 <1> ; Status in AH (>0 = error code) 2459 <1> ; if CF = 1 -> error code in AH 2460 <1> ; if CF = 0 -> successful 2461 <1> ; AL = undefined 2462 <1> ; 2463 <1> ; Modified registers: (only) EAX 2464 <1> 2465 <1> ; 11/07/2022 2466 <1> ;;int13h: ; 16/02/2015 2467 <1> ;; 16/02/2015 - 21/02/2015 2468 <1> ;int40h: 2469 <1> ; pushfd 2470 <1> ; push cs 2471 <1> ; call DISKETTE_IO_1 2472 <1> ; retn 2473 <1> 2474 <1> DISKETTE_IO_1: 2475 <1> 2476 <1> ;sti ; INTERRUPTS BACK ON 2477 <1> ; 11/07/2022 2478 <1> ; save registers 2479 00001627 55 <1> push ebp ; ANY 2480 <1> 2481 <1> ; 11/07/2022 2482 <1> ;push edi ; ANY 2483 <1> ;push edx ; DRIVE NUMBER (DL) 2484 <1> ;push ebx ; BUFFER ADDRESS 2485 <1> ;push ecx ; SECTOR ADDRESS (LBA) 2486 <1> ;push esi ; ANY 2487 <1> 2488 <1> ; 11/07/2022 2489 00001628 89DD <1> mov ebp, ebx ; buffer address 2490 0000162A C605[AC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; RESET DISKETTE STATUS 2491 00001631 0FB6FA <1> movzx edi, dl ; drive number (0 or 1) 2492 <1> 2493 00001634 08C0 <1> or al, al ; RESET ? 2494 00001636 7507 <1> jnz short DISKETTE_RW_1 ; NO 2495 <1> 2496 00001638 E84D010000 <1> call DSK_RESET 2497 <1> 2498 0000163D EB37 <1> jmp short DISKETTE_RW_2 2499 <1> 2500 <1> DISKETTE_RW_1: 2501 <1> ; 12/07/2022 2502 <1> ; 11/07/2022 2503 <1> ; ecx = sector address (LBA, < 2880) 2504 <1> ; ebp = buffer address 2505 <1> ; edi = drive number (0 or 1) 2506 <1> ; al = function (read = 1 or write = 2) 2507 <1> 2508 0000163F 88C2 <1> mov dl, al ; * 2509 <1> convert_to_chs: 2510 <1> ;;; 2511 00001641 B004 <1> mov al, 4 ; MD.SEC_TRK ; sector per track (drv.spt) 2512 00001643 E8D9050000 <1> call GET_PARM 2513 <1> ; 12/07/2022 2514 00001648 88E6 <1> mov dh, ah ; spt 2515 0000164A 89C8 <1> mov eax, ecx ; sector address (LBA) 2516 0000164C F6F6 <1> div dh ; AX/DH 2517 0000164E 88E1 <1> mov cl, ah ; sector number - 1 2518 00001650 FEC1 <1> inc cl ; sector number (1 based) 2519 00001652 28ED <1> sub ch, ch ; head = 0 2520 <1> ; heads = 2 2521 00001654 D0E8 <1> shr al, 1 ; al = al/2 2522 00001656 80D500 <1> adc ch, 0 ; head = 1 or head = 0 2523 00001659 C1E110 <1> shl ecx, 16 2524 0000165C 88C1 <1> mov cl, al ; track (cylinder) 2525 0000165E 88D5 <1> mov ch, dl ; function number 2526 00001660 89CE <1> mov esi, ecx ; byte 0 = track, byte 1 = function 2527 <1> ; byte 2 = sector, byte 3 = head 2528 00001662 C1C610 <1> rol esi, 16 2529 <1> ; byte 0 = sector, byte 1 = head 2530 <1> ; byte 2 = track, byte 3 = function 2531 <1> ;;; 2532 00001665 80FA02 <1> cmp dl, 2 ; * 2533 00001668 7407 <1> je short DISKETTE_W 2534 <1> DISKETTE_R: 2535 <1> ; dl = 1 ; * 2536 0000166A E809000000 <1> call DSK_READ 2537 0000166F EB05 <1> jmp short DISKETTE_RW_2 2538 <1> DISKETTE_W: 2539 00001671 E80F000000 <1> call DSK_WRITE 2540 <1> DISKETTE_RW_2: 2541 <1> ; 11/07/2022 2542 <1> ; Restore registers 2543 <1> ;pop esi 2544 <1> ;pop ecx 2545 <1> ;pop ebx 2546 <1> ;pop edx 2547 <1> ;pop edi 2548 <1> 2549 <1> ; 11/07/2022 2550 00001676 5D <1> pop ebp 2551 00001677 C3 <1> retn 2552 <1> 2553 <1> ;------------------------------------------------------------------------------- 2554 <1> ; DISK_READ (AH = 01H) ; Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2555 <1> ; DISKETTE READ. 2556 <1> ; 2557 <1> ; ON ENTRY: EDI : DRIVE # 2558 <1> ; SI-HI : HEAD # 2559 <1> ; SI-LOW : # OF SECTORS 2560 <1> ; ES : BUFFER SEGMENT 2561 <1> ; [BP] : SECTOR # 2562 <1> ; [BP+1] : TRACK # 2563 <1> ; [BP+2] : BUFFER OFFSET 2564 <1> ; 2565 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2566 <1> ;------------------------------------------------------------------------------- 2567 <1> 2568 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2569 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 2570 <1> 2571 <1> DSK_READ: 2572 00001678 8025[AA610000]7F <1> and byte [MOTOR_STATUS], 01111111b ; INDICATE A READ OPERATION 2573 0000167F 66B846E6 <1> mov ax, 0E646h ; AX = NEC COMMAND, DMA COMMAND 2574 <1> ;call RD_WR_VF ; COMMON READ/WRITE/VERIFY 2575 <1> ;retn 2576 00001683 EB0B <1> jmp short RD_WR_VF 2577 <1> 2578 <1> ;------------------------------------------------------------------------------- 2579 <1> ; DISK_WRITE (AH = 02H) 2580 <1> ; DISKETTE WRITE. 2581 <1> ; 2582 <1> ; ON ENTRY: EDI : DRIVE # 2583 <1> ; SI-HI : HEAD # 2584 <1> ; SI-LOW : # OF SECTORS 2585 <1> ; ES : BUFFER SEGMENT 2586 <1> ; [BP] : SECTOR # 2587 <1> ; [BP+1] : TRACK # 2588 <1> ; [BP+2] : BUFFER OFFSET 2589 <1> ; 2590 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2591 <1> ;------------------------------------------------------------------------------- 2592 <1> 2593 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2594 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 2595 <1> 2596 <1> DSK_WRITE: 2597 00001685 66B84AC5 <1> mov ax, 0C54Ah ; AX = NEC COMMAND, DMA COMMAND 2598 00001689 800D[AA610000]80 <1> or byte [MOTOR_STATUS], 10000000b ; INDICATE WRITE OPERATION 2599 <1> ;;call RD_WR_VF ; COMMON READ/WRITE/VERIFY 2600 <1> ;;retn 2601 <1> ;jmp short RD_WR_VF 2602 <1> 2603 <1> ;------------------------------------------------------------------------------- 2604 <1> ; RD_WR_VF 2605 <1> ; COMMON READ, WRITE 2606 <1> ; MAIN LOOP FOR STATE RETRIES. 2607 <1> ; 2608 <1> ; ON ENTRY: AH = READ/WRITE NEC PARAMETER 2609 <1> ; AL = READ/WRITE DMA PARAMETER 2610 <1> ; 2611 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2612 <1> ;------------------------------------------------------------------------------- 2613 <1> 2614 <1> RD_WR_VF: 2615 <1> ; 18/07/2022 2616 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2617 00001690 50 <1> push eax ; 24/12/2021 ; SAVE DMA, NEC PARAMETERS 2618 00001691 E8C9010000 <1> call XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 2619 00001696 E82B020000 <1> call SETUP_STATE ; INITIALIZE START AND END RATE 2620 0000169B 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 2621 <1> DO_AGAIN: 2622 0000169C 50 <1> push eax ; 24/12/2021 ; SAVE READ/WRITE PARAMETER 2623 0000169D E865020000 <1> call MED_CHANGE ; MEDIA CHANGE AND RESET IF CHANGED 2624 000016A2 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 2625 <1> ; 24/12/2021 2626 000016A3 7305 <1> jnc short RWV 2627 000016A5 E9B6000000 <1> jmp RWV_END ; MEDIA CHANGE ERROR OR TIME-OUT 2628 <1> RWV: 2629 000016AA 50 <1> push eax ; 24/12/2021 ; SAVE READ/WRITE/VERIFY PARAMETER 2630 000016AB 8AB7[B7610000] <1> mov dh, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 2631 000016B1 80E6C0 <1> and dh, RATE_MSK ; KEEP ONLY RATE 2632 000016B4 E85F050000 <1> call CMOS_TYPE ; RETURN DRIVE TYPE IN AL 2633 <1> ; 20/02/2015 2634 000016B9 7445 <1> jz short RWV_ASSUME ; ERROR IN CMOS 2635 000016BB 3C01 <1> cmp al, 1 ; 40 TRACK DRIVE? 2636 000016BD 750D <1> jne short RWV_1 ; NO, BYPASS CMOS VALIDITY CHECK 2637 000016BF F687[B7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE 2638 000016C6 740F <1> jz short RWV_2 ; YES, CMOS IS CORRECT 2639 <1> ;mov al, 2 ; CHANGE TO 1.2M 2640 <1> ; 12/07/2022 2641 000016C8 FEC0 <1> inc al ; al = 2 2642 000016CA EB0B <1> jmp short RWV_2 2643 <1> RWV_1: 2644 <1> ; 12/07/2022 2645 <1> ;jb short RWV_2 ; NO DRIVE SPECIFIED, CONTINUE 2646 000016CC F687[B7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; IS IT REALLY 40 TRACK? 2647 000016D3 7502 <1> jnz short RWV_2 ; NO, 80 TRACK 2648 000016D5 B001 <1> mov al, 1 ; IT IS 40 TRACK, FIX CMOS VALUE 2649 <1> ; 12/07/2022 2650 <1> ;jmp short RWV_3 2651 <1> RWV_2: 2652 <1> ; 12/07/2022 2653 <1> ;or al, al ; TEST FOR NO DRIVE 2654 <1> ;jz short RWV_ASSUME ; ASSUME TYPE, USE MAX TRACK 2655 <1> RWV_3: 2656 <1> ; 12/07/2022 2657 <1> ;mov dl, al ; 11/07/2022 2658 000016D7 E81F010000 <1> call DR_TYPE_CHECK ; RTN EBX = MEDIA/DRIVE PARAM TBL. 2659 000016DC 7222 <1> jc short RWV_ASSUME ; TYPE NOT IN TABLE (BAD CMOS) 2660 <1> 2661 <1> ;----- SEARCH FOR MEDIA/DRIVE PARAMETER TABLE 2662 <1> 2663 000016DE 57 <1> push edi ; SAVE DRIVE # 2664 <1> ;xor ebx, ebx ; EBX = INDEX TO DR_TYPE TABLE 2665 000016DF BB[CC5B0000] <1> mov ebx, DR_TYPE 2666 <1> ;mov ecx, DR_CNT ; ECX = LOOP COUNT 2667 000016E4 B106 <1> mov cl, DR_CNT 2668 <1> RWV_DR_SEARCH: 2669 <1> ;mov ah, [DR_TYPE+ebx] ; GET DRIVE TYPE 2670 000016E6 8A23 <1> mov ah, [ebx] 2671 000016E8 80E47F <1> and ah, BIT7OFF ; MASK OUT MSB 2672 000016EB 38E0 <1> cmp al, ah ; DRIVE TYPE MATCH? 2673 <1> ; 12/07/2022 2674 <1> ;cmp dl, ah ; 11/07/2022 2675 000016ED 7509 <1> jne short RWV_NXT_MD ; NO, CHECK NEXT DRIVE TYPE 2676 <1> RWV_DR_FND: 2677 <1> ;mov edi, [DR_TYPE+ebx+1] ; EDI = MEDIA/DRIVE PARAMETER TABLE 2678 000016EF 43 <1> inc ebx 2679 000016F0 8B3B <1> mov edi, [ebx] 2680 000016F2 4B <1> dec ebx 2681 <1> RWV_MD_SEARH: 2682 000016F3 3A770C <1> cmp dh, [edi+MD.RATE] ; MATCH? 2683 000016F6 741D <1> je short RWV_MD_FND ; YES, GO GET 1ST SPECIFY BYTE 2684 <1> RWV_NXT_MD: 2685 000016F8 83C305 <1> add ebx, 5 ; CHECK NEXT DRIVE TYPE 2686 <1> ;loop RWV_DR_SEARCH 2687 000016FB FEC9 <1> dec cl 2688 000016FD 75E7 <1> jnz short RWV_DR_SEARCH 2689 000016FF 5F <1> pop edi ; RESTORE DRIVE # 2690 <1> 2691 <1> ;----- ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED 2692 <1> 2693 <1> RWV_ASSUME: 2694 00001700 BB[EA5B0000] <1> mov ebx, MD_TBL1 ; POINT TO 40 TRACK 250 KBS 2695 00001705 F687[B7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK 2696 0000170C 740A <1> jz short RWV_MD_FND1 ; MUST BE 40 TRACK 2697 0000170E BB[045C0000] <1> mov ebx, MD_TBL3 ; POINT TO 80 TRACK 500 KBS 2698 00001713 EB03 <1> jmp short RWV_MD_FND1 ; GO SPECIFY PARAMTERS 2699 <1> 2700 <1> ;----- EBX POINTS TO MEDIA/DRIVE PARAMETER TABLE 2701 <1> 2702 <1> RWV_MD_FND: 2703 00001715 89FB <1> mov ebx, edi ; EBX = MEDIA/DRIVE PARAMETER TABLE 2704 00001717 5F <1> pop edi ; RESTORE DRIVE # 2705 <1> 2706 <1> ;----- SEND THE SPECIFY COMMAND TO THE CONTROLLER 2707 <1> 2708 <1> RWV_MD_FND1: 2709 00001718 E824010000 <1> call SEND_SPEC_MD 2710 0000171D E851020000 <1> call CHK_LASTRATE ; ZF=1 ATTEMP RATE IS SAME AS LAST RATE 2711 00001722 7405 <1> jz short RWV_DBL ; YES,SKIP SEND RATE COMMAND 2712 00001724 E82C020000 <1> call SEND_RATE ; SEND DATA RATE TO NEC 2713 <1> RWV_DBL: 2714 00001729 53 <1> push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 2715 0000172A E847040000 <1> call SETUP_DBL ; CHECK FOR DOUBLE STEP 2716 0000172F 5B <1> pop ebx ; RESTORE ADDRESS 2717 00001730 7221 <1> jc short CHK_RET ; ERROR FROM READ ID, POSSIBLE RETRY 2718 <1> ;pop eax ; 24/12/2021 ; RESTORE NEC COMMAND 2719 <1> ;push eax ; 24/12/2021 ; SAVE NEC COMMAND 2720 <1> ; 08/07/2022 2721 00001732 8B0424 <1> mov eax, [esp] 2722 <1> ; 18/07/2022 2723 <1> ;push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 2724 00001735 E84C020000 <1> call DMA_SETUP ; SET UP THE DMA 2725 <1> ;pop ebx 2726 0000173A 58 <1> pop eax ; 24/12/2021 ; RESTORE NEC COMMAND 2727 0000173B 722D <1> jc short RWV_BAC ; CHECK FOR DMA BOUNDARY ERROR 2728 0000173D 50 <1> push eax ; 24/12/2021 ; SAVE NEC COMMAND 2729 0000173E 53 <1> push ebx ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 2730 0000173F E88C020000 <1> call NEC_INIT ; INITIALIZE NEC 2731 00001744 5B <1> pop ebx ; RESTORE ADDRESS 2732 00001745 720C <1> jc short CHK_RET ; ERROR - EXIT 2733 00001747 E8B5020000 <1> call RWV_COM ; OP CODE COMMON TO READ/WRITE 2734 0000174C 7205 <1> jc short CHK_RET ; ERROR - EXIT 2735 0000174E E8FC020000 <1> call NEC_TERM ; TERMINATE, GET STATUS, ETC. 2736 <1> CHK_RET: 2737 00001753 E89B030000 <1> call RETRY ; CHECK FOR, SETUP RETRY 2738 00001758 58 <1> pop eax ; 24/12/2021 ; RESTORE READ/WRITE PARAMETER 2739 00001759 7305 <1> jnc short RWV_END ; CY = 0 NO RETRY 2740 0000175B E93CFFFFFF <1> jmp DO_AGAIN ; CY = 1 MEANS RETRY 2741 <1> RWV_END: 2742 00001760 E846030000 <1> call DSTATE ; ESTABLISH STATE IF SUCCESSFUL 2743 00001765 E8D7030000 <1> call NUM_TRANS ; AL = NUMBER TRANSFERRED 2744 <1> RWV_BAC: 2745 <1> ; 08/07/2022 ; BAD DMA ERROR ENTRY 2746 <1> ;push eax ; 24/12/2021 ; SAVE NUMBER TRANSFERRED 2747 <1> ;CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 2748 <1> ;pop eax ; 24/12/2021 ; RESTORE NUMBER TRANSFERRED 2749 <1> ;;call SETUP_END ; VARIOUS CLEANUPS 2750 <1> ;;retn 2751 <1> ;jmp SETUP_END 2752 <1> 2753 <1> ;------------------------------------------------------------------------------- 2754 <1> ; SETUP_END 2755 <1> ; RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 2756 <1> ; AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY. 2757 <1> ; 2758 <1> ; ON EXIT: 2759 <1> ; AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2760 <1> ;------------------------------------------------------------------------------- 2761 <1> SETUP_END: 2762 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2763 <1> ;mov dl, 2 ; GET THE MOTOR WAIT PARAMETER 2764 <1> ;push ax ; SAVE NUMBER TRANSFERRED 2765 0000176A 50 <1> push eax ; 24/12/2021 2766 0000176B B002 <1> mov al, 2 ; 08/07/2022 2767 0000176D E8AF040000 <1> call GET_PARM 2768 00001772 8825[AB610000] <1> mov [MOTOR_COUNT], ah ; STORE UPON RETURN 2769 <1> ;pop ax ; RESTORE NUMBER TRANSFERRED 2770 00001778 58 <1> pop eax ; 24/12/2021 2771 00001779 8A25[AC610000] <1> mov ah, [DSKETTE_STATUS] ; GET STATUS OF OPERATION 2772 0000177F 08E4 <1> or ah, ah ; CHECK FOR ERROR 2773 00001781 7406 <1> jz short NUN_ERR ; NO ERROR 2774 00001783 30C0 <1> xor al, al ; CLEAR NUMBER RETURNED 2775 <1> ;NUN_ERR: 2776 00001785 80FC01 <1> cmp ah, 1 ; SET THE CARRY FLAG TO INDICATE 2777 00001788 F5 <1> cmc ; SUCCESS OR FAILURE 2778 <1> NUN_ERR: 2779 00001789 C3 <1> retn 2780 <1> 2781 <1> ;------------------------------------------------------------------------------- 2782 <1> ; DISK_RESET (AH = 00H) 2783 <1> ; RESET THE DISKETTE SYSTEM. 2784 <1> ; 2785 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2786 <1> ;------------------------------------------------------------------------------- 2787 <1> DSK_RESET: 2788 <1> ; 17/07/2022 2789 <1> ; 12/07/2022 2790 <1> ; 11/07/2022 2791 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2792 0000178A 66BAF203 <1> mov dx, 03F2h ; ADAPTER CONTROL PORT 2793 0000178E FA <1> cli ; NO INTERRUPTS 2794 0000178F A0[AA610000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 2795 00001794 243F <1> and al, 00111111b ; KEEP SELECTED AND MOTOR ON BITS 2796 00001796 C0C004 <1> rol al, 4 ; MOTOR VALUE TO HIGH NIBBLE 2797 <1> ; DRIVE SELECT TO LOW NIBBLE 2798 00001799 0C08 <1> or al, 00001000b ; TURN ON INTERRUPT ENABLE 2799 0000179B EE <1> out dx, al ; RESET THE ADAPTER 2800 0000179C C605[A9610000]00 <1> mov byte [SEEK_STATUS], 0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 2801 <1> ;JMP $+2 ; WAIT FOR I/O 2802 <1> ;JMP $+2 ; WAIT FOR I/O (TO INSURE MINIMUM 2803 <1> ; PULSE WIDTH) 2804 <1> ; 19/12/2014 2805 <1> NEWIODELAY 2196 000017A3 E6EB <2> out 0EBh,al 2806 <1> 2807 <1> ; 17/12/2014 2808 <1> ; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM) 2809 000017A5 B915000000 <1> mov ecx, WAITCPU_RESET_ON ; cx = 21 -- Min. 14 micro seconds !? 2810 <1> wdw1: 2811 <1> NEWIODELAY ; 27/02/2015 2196 000017AA E6EB <2> out 0EBh,al 2812 000017AC E2FC <1> loop wdw1 2813 <1> ; 2814 000017AE 0C04 <1> or al, 00000100b ; TURN OFF RESET BIT 2815 000017B0 EE <1> out dx, al ; RESET THE ADAPTER 2816 <1> ; 16/12/2014 2817 <1> IODELAY 2191 000017B1 EB00 <2> jmp short $+2 2192 000017B3 EB00 <2> jmp short $+2 2818 <1> ; 2819 <1> ;sti ; ENABLE THE INTERRUPTS 2820 000017B5 E862060000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 2821 000017BA 7236 <1> jc short DR_ERR ; IF ERROR, RETURN IT 2822 <1> ;mov cx, 11000000b ; CL = EXPECTED @NEC_STATUS 2823 <1> ; 12/07/2022 2824 <1> ;xor ecx, ecx 2825 <1> ; 17/07/2022 2826 <1> ;xor ch, ch 2827 000017BC B1C0 <1> mov cl, 11000000b 2828 <1> NXT_DRV: 2829 <1> ; 24/12/2021 2830 000017BE 51 <1> push ecx ; SAVE FOR CALL 2831 000017BF B8[F1170000] <1> mov eax, DR_POP_ERR ; LOAD NEC_OUTPUT ERROR ADDRESS 2832 000017C4 50 <1> push eax ; 2833 000017C5 B408 <1> mov ah, 08h ; SENSE INTERRUPT STATUS COMMAND 2834 000017C7 E846050000 <1> call NEC_OUTPUT 2835 000017CC 58 <1> pop eax ; THROW AWAY ERROR RETURN 2836 000017CD E879060000 <1> call RESULTS ; READ IN THE RESULTS 2837 <1> ; 24/12/2021 2838 000017D2 59 <1> pop ecx ; RESTORE AFTER CALL 2839 000017D3 721D <1> jc short DR_ERR ; ERROR RETURN 2840 000017D5 3A0D[AD610000] <1> cmp cl, [NEC_STATUS] ; TEST FOR DRIVE READY TRANSITION 2841 000017DB 7515 <1> jnz short DR_ERR ; EVERYTHING OK 2842 000017DD FEC1 <1> inc cl ; NEXT EXPECTED @NEC_STATUS 2843 000017DF 80F9C3 <1> cmp cl, 11000011b ; ALL POSSIBLE DRIVES CLEARED 2844 000017E2 76DA <1> jbe short NXT_DRV ; FALL THRU IF 11000100B OR > 2845 <1> ; 2846 000017E4 E82F000000 <1> call SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 2847 <1> RESBAC: 2848 000017E9 E87CFFFFFF <1> call SETUP_END ; VARIOUS CLEANUPS 2849 <1> 2850 <1> ; 11/07/2022 2851 <1> ; CF = 1 -> error (error code in AH) 2852 <1> ; CF = 0 -> OK 2853 <1> 2854 <1> ;; 24/12/2021 2855 <1> ;mov ebx, esi ; GET SAVED AL TO BL 2856 <1> ;; 11/07/2022 2857 <1> ;; byte 0 = sector, byte 1 = head, byte 2 = track, byte 3 = function 2858 <1> ;rol ebx, 8 2859 <1> ; bl = function (reset = 0) 2860 <1> ; 2861 <1> ;mov al, bl ; PUT BACK FOR RETURN 2862 <1> 2863 <1> ; 11/07/2022 2864 000017EE B000 <1> mov al, 0 ; (reset function = 0) 2865 <1> 2866 000017F0 C3 <1> retn 2867 <1> 2868 <1> DR_POP_ERR: 2869 <1> ; 24/12/2021 2870 000017F1 59 <1> pop ecx ; CLEAR STACK 2871 <1> DR_ERR: 2872 000017F2 800D[AC610000]20 <1> or byte [DSKETTE_STATUS], BAD_NEC ; SET ERROR CODE 2873 000017F9 EBEE <1> jmp short RESBAC ; RETURN FROM RESET 2874 <1> 2875 <1> ;------------------------------------------------------------------------------- 2876 <1> ; FNC_ERR 2877 <1> ; INVALID FUNCTION REQUESTED OR INVALID DRIVE: 2878 <1> ; SET BAD COMMAND IN STATUS. 2879 <1> ; 2880 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 2881 <1> ;------------------------------------------------------------------------------- 2882 <1> 2883 <1> ; 11/07/2022 - not needed (because diskio is used by kernel only) 2884 <1> 2885 <1> ;FNC_ERR: ; INVALID FUNCTION REQUEST 2886 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2887 <1> ; ; 24/12/2021 2888 <1> ; mov eax, esi ; RESTORE AL 2889 <1> ; mov ah, BAD_CMD ; SET BAD COMMAND ERROR 2890 <1> ; mov [DSKETTE_STATUS], ah ; STORE IN DATA AREA 2891 <1> ; stc ; SET CARRY INDICATING ERROR 2892 <1> ; retn 2893 <1> 2894 <1> ;---------------------------------------------------------------- 2895 <1> ; DR_TYPE_CHECK : 2896 <1> ; CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL) : 2897 <1> ; IS SUPPORTED IN BIOS DRIVE TYPE TABLE : 2898 <1> ; ON ENTRY: : 2899 <1> ; AL = DRIVE TYPE : 2900 <1> ; ON EXIT: : 2901 <1> ; CY = 0 DRIVE TYPE SUPPORTED : 2902 <1> ; EBX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE : 2903 <1> ; CY = 1 DRIVE TYPE NOT SUPPORTED : 2904 <1> ; REGISTERS ALTERED: EBX, AH ; 11/07/2022 : 2905 <1> ;---------------------------------------------------------------- 2906 <1> DR_TYPE_CHECK: 2907 <1> ; 12/07/2022 2908 <1> ; 11/07/2022 2909 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2910 <1> ; 24/12/2021 2911 <1> ;push eax ; 11/07/2022 2912 <1> ;push ecx ; 08/07/2022 2913 <1> ;xor ebx,ebx ; EBX = INDEX TO DR_TYPE TABLE 2914 000017FB BB[CC5B0000] <1> mov ebx, DR_TYPE 2915 <1> ;;mov ecx, DR_CNT ; ECX = LOOP COUNT 2916 <1> ;mov cl, DR_CNT 2917 00001800 B406 <1> mov ah, DR_CNT ; 11/07/2022 2918 <1> TYPE_CHK: 2919 <1> ;;mov ah, [DR_TYPE+ebx] ; GET DRIVE TYPE 2920 <1> ;mov ah, [ebx] 2921 <1> ;cmp al, ah ; DRIVE TYPE MATCH? 2922 00001802 3A03 <1> cmp al, [ebx] ; 11/07/2022 2923 00001804 740E <1> je short DR_TYPE_VALID ; YES, RETURN WITH CARRY RESET 2924 <1> ; 16/02/2015 (32 bit address modification) 2925 00001806 83C305 <1> add ebx, 5 ; CHECK NEXT DRIVE TYPE 2926 <1> ;loop TYPE_CHK 2927 <1> ;dec cl 2928 00001809 FECC <1> dec ah ; 11/07/2022 2929 0000180B 75F5 <1> jnz short TYPE_CHK 2930 <1> ; 2931 0000180D BB[2B5C0000] <1> mov ebx, MD_TBL6 ; 1.44MB fd parameter table 2932 <1> ; Default for GET_PARM (11/12/2014) 2933 <1> ; 2934 00001812 F9 <1> stc ; DRIVE TYPE NOT FOUND IN TABLE 2935 <1> ;jmp short TYPE_RTN 2936 <1> ; 12/07/2022 2937 00001813 C3 <1> retn 2938 <1> DR_TYPE_VALID: 2939 <1> ;mov ebx, [DR_TYPE+ebx+1] ; EBX = MEDIA TABLE 2940 00001814 43 <1> inc ebx 2941 00001815 8B1B <1> mov ebx, [ebx] 2942 <1> TYPE_RTN: 2943 <1> ;pop ecx ; 08/07/2022 2944 <1> ; 24/12/2021 2945 <1> ;pop eax ; 11/07/2022 2946 00001817 C3 <1> retn 2947 <1> 2948 <1> ;---------------------------------------------------------------- 2949 <1> ; SEND_SPEC : 2950 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 2951 <1> ; THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER : 2952 <1> ; ON ENTRY: @DISK_POINTER = DRIVE PARAMETER TABLE : 2953 <1> ; ON EXIT: NONE : 2954 <1> ; REGISTERS ALTERED: ECX, EDX : 2955 <1> ;---------------------------------------------------------------- 2956 <1> SEND_SPEC: 2957 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2958 00001818 50 <1> push eax ; SAVE EAX 2959 00001819 B8[3F180000] <1> mov eax, SPECBAC ; LOAD ERROR ADDRESS 2960 0000181E 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 2961 0000181F B403 <1> mov ah, 03h ; SPECIFY COMMAND 2962 00001821 E8EC040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2963 <1> ;sub dl, dl ; FIRST SPECIFY BYTE 2964 00001826 28C0 <1> sub al, al ; 08/07/2022 2965 00001828 E8F4030000 <1> call GET_PARM ; GET PARAMETER TO AH 2966 0000182D E8E0040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2967 <1> ;mov dl, 1 ; SECOND SPECIFY BYTE 2968 00001832 B001 <1> mov al, 1 ; 08/07/2022 2969 00001834 E8E8030000 <1> call GET_PARM ; GET PARAMETER TO AH 2970 00001839 E8D4040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2971 0000183E 58 <1> pop eax ; POP ERROR RETURN 2972 <1> SPECBAC: 2973 0000183F 58 <1> pop eax ; RESTORE ORIGINAL EAX VALUE 2974 00001840 C3 <1> retn 2975 <1> 2976 <1> ;---------------------------------------------------------------- 2977 <1> ; SEND_SPEC_MD : 2978 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 2979 <1> ; THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (EBX) : 2980 <1> ; ON ENTRY: EBX = MEDIA/DRIVE PARAMETER TABLE : 2981 <1> ; ON EXIT: NONE : 2982 <1> ; REGISTERS ALTERED: EAX ; 11/07/2022 : 2983 <1> ;---------------------------------------------------------------- 2984 <1> SEND_SPEC_MD: 2985 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2986 <1> ;push eax ; 11/07/2022 ; SAVE RATE DATA 2987 00001841 B8[5E180000] <1> mov eax, SPEC_ESBAC ; LOAD ERROR ADDRESS 2988 00001846 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 2989 00001847 B403 <1> mov ah, 03h ; SPECIFY COMMAND 2990 00001849 E8C4040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2991 0000184E 8A23 <1> mov ah, [ebx+MD.SPEC1] ; GET 1ST SPECIFY BYTE 2992 00001850 E8BD040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2993 00001855 8A6301 <1> mov ah, [ebx+MD.SPEC2] ; GET SECOND SPECIFY BYTE 2994 00001858 E8B5040000 <1> call NEC_OUTPUT ; OUTPUT THE COMMAND 2995 0000185D 58 <1> pop eax ; POP ERROR RETURN 2996 <1> SPEC_ESBAC: 2997 <1> ;pop eax ; 11/07/2022 ; RESTORE ORIGINAL EAX VALUE 2998 0000185E C3 <1> retn 2999 <1> 3000 <1> ;------------------------------------------------------------------------------- 3001 <1> ; XLAT_NEW 3002 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE 3003 <1> ; MODE TO NEW ARCHITECTURE. 3004 <1> ; 3005 <1> ; ON ENTRY: EDI = DRIVE # 3006 <1> ;------------------------------------------------------------------------------- 3007 <1> XLAT_NEW: 3008 <1> ; 11/07/2022 3009 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3010 <1> ;cmp edi, 1 ; VALID DRIVE 3011 <1> ;ja short XN_OUT ; IF INVALID BACK 3012 <1> ; 3013 0000185F 80BF[B7610000]00 <1> cmp byte [DSK_STATE+edi], 0 ; NO DRIVE ? 3014 00001866 7401 <1> jz short DO_DET ; IF NO DRIVE ATTEMPT DETERMINE 3015 <1> ; 3016 <1> ;mov al, [HF_CNTRL] ; DRIVE INFORMATION 3017 <1> ;mov ecx, edi ; ECX = DRIVE NUMBER 3018 <1> ;or cl, cl 3019 <1> ;jz short XN_0 ; 08/07/2022 3020 <1> ;shl cl, 2 ; CL = SHIFT COUNT, A=0, B=4 3021 <1> ;;mov al, [HF_CNTRL] ; DRIVE INFORMATION 3022 <1> ;ror al, cl ; TO LOW NIBBLE 3023 <1> ;XN_0: 3024 <1> ;and al, DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 3025 <1> ;and byte [DSK_STATE+edi], ~(DRV_DET+FMT_CAPA+TRK_CAPA) 3026 <1> ;or [DSK_STATE+edi], al ; UPDATE DRIVE STATE 3027 <1> XN_OUT: 3028 00001868 C3 <1> retn 3029 <1> DO_DET: 3030 <1> ;;call DRIVE_DET ; TRY TO DETERMINE 3031 <1> ;;retn 3032 <1> ;jmp DRIVE_DET 3033 <1> 3034 <1> ;------------------------------------------------------------------------------- 3035 <1> ; DRIVE_DET 3036 <1> ; DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND 3037 <1> ; UPDATES STATE INFORMATION ACCORDINGLY. 3038 <1> ; ON ENTRY: EDI = DRIVE # 3039 <1> ;------------------------------------------------------------------------------- 3040 <1> DRIVE_DET: 3041 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3042 00001869 E8EE030000 <1> call MOTOR_ON ; TURN ON MOTOR IF NOT ALREADY ON 3043 0000186E E857050000 <1> call RECAL ; RECALIBRATE DRIVE 3044 00001873 724E <1> jc short DD_BAC ; ASSUME NO DRIVE PRESENT 3045 00001875 B530 <1> mov ch, TRK_SLAP ; SEEK TO TRACK 48 3046 00001877 E8CF040000 <1> call SEEK 3047 0000187C 7245 <1> jc short DD_BAC ; ERROR NO DRIVE 3048 0000187E B50B <1> mov ch, QUIET_SEEK+1 ; SEEK TO TRACK 10 3049 <1> SK_GIN: 3050 00001880 FECD <1> dec ch ; DECREMENT TO NEXT TRACK 3051 <1> ;push cx 3052 <1> ; 24/12/2021 3053 00001882 51 <1> push ecx ; SAVE TRACK 3054 00001883 E8C3040000 <1> call SEEK 3055 00001888 723A <1> jc short POP_BAC ; POP AND RETURN 3056 0000188A B8[C4180000] <1> mov eax, POP_BAC ; LOAD NEC OUTPUT ERROR ADDRESS 3057 0000188F 50 <1> push eax 3058 00001890 B404 <1> mov ah, SENSE_DRV_ST ; SENSE DRIVE STATUS COMMAND BYTE 3059 00001892 E87B040000 <1> call NEC_OUTPUT ; OUTPUT TO NEC 3060 <1> ; 08/07/2022 3061 00001897 89F8 <1> mov eax, edi ; AL = DRIVE 3062 00001899 88C4 <1> mov ah, al ; AH = DRIVE 3063 0000189B E872040000 <1> call NEC_OUTPUT ; OUTPUT TO NEC 3064 000018A0 E8A6050000 <1> call RESULTS ; GO GET STATUS 3065 000018A5 58 <1> pop eax ; THROW AWAY ERROR ADDRESS 3066 <1> ;pop cx ; RESTORE TRACK 3067 <1> ; 24/12/2021 3068 000018A6 59 <1> pop ecx 3069 000018A7 F605[AD610000]10 <1> test byte [NEC_STATUS], HOME ; TRACK 0 ? 3070 000018AE 74D0 <1> jz short SK_GIN ; GO TILL TRACK 0 3071 000018B0 08ED <1> or ch, ch ; IS HOME AT TRACK 0 3072 000018B2 7408 <1> jz short IS_80 ; MUST BE 80 TRACK DRIVE 3073 <1> 3074 <1> ; DRIVE IS A 360; SET DRIVE TO DETERMINED; 3075 <1> ; SET MEDIA TO DETERMINED AT RATE 250. 3076 <1> 3077 000018B4 808F[B7610000]94 <1> or byte [DSK_STATE+edi], DRV_DET+MED_DET+RATE_250 3078 000018BB C3 <1> retn ; ALL INFORMATION SET 3079 <1> IS_80: 3080 000018BC 808F[B7610000]01 <1> or byte [DSK_STATE+edi], TRK_CAPA ; SETUP 80 TRACK CAPABILITY 3081 <1> DD_BAC: 3082 000018C3 C3 <1> retn 3083 <1> POP_BAC: 3084 <1> ;pop cx ; THROW AWAY 3085 <1> ; 24/12/2021 3086 000018C4 59 <1> pop ecx 3087 000018C5 C3 <1> retn 3088 <1> 3089 <1> ;------------------------------------------------------------------------------- 3090 <1> ; SETUP_STATE: INITIALIZES START AND END RATES. 3091 <1> ;------------------------------------------------------------------------------- 3092 <1> SETUP_STATE: 3093 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3094 000018C6 F687[B7610000]10 <1> test byte [DSK_STATE+edi], MED_DET ; MEDIA DETERMINED ? 3095 000018CD 7537 <1> jnz short J1C ; NO STATES IF DETERMINED 3096 000018CF 66B84000 <1> mov ax, (RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE 3097 000018D3 F687[B7610000]04 <1> test byte [DSK_STATE+edi], DRV_DET ; DRIVE ? 3098 000018DA 740D <1> jz short AX_SET ; DO NOT KNOW DRIVE 3099 000018DC F687[B7610000]02 <1> test byte [DSK_STATE+edi], FMT_CAPA ; MULTI-RATE? 3100 000018E3 7504 <1> jnz short AX_SET ; JUMP IF YES 3101 000018E5 66B88080 <1> mov ax, RATE_250*257 ; START A END RATE 250 FOR 360 DRIVE 3102 <1> AX_SET: 3103 000018E9 80A7[B7610000]1F <1> and byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE 3104 000018F0 08A7[B7610000] <1> or [DSK_STATE+edi], ah ; RATE FIRST TO TRY 3105 000018F6 8025[B4610000]F3 <1> and byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS 3106 000018FD C0C804 <1> ror al, 4 ; TO OPERATION LAST RATE LOCATION 3107 00001900 0805[B4610000] <1> or [LASTRATE], al ; LAST RATE 3108 <1> J1C: 3109 00001906 C3 <1> retn 3110 <1> 3111 <1> ;------------------------------------------------------------------------------- 3112 <1> ; MED_CHANGE 3113 <1> ; CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 3114 <1> ; CHECKS MEDIA CHANGE AGAIN. 3115 <1> ; 3116 <1> ; ON EXIT: CY = 1 MEANS MEDIA CHANGE OR TIMEOUT 3117 <1> ; @DSKETTE_STATUS = ERROR CODE 3118 <1> ;------------------------------------------------------------------------------- 3119 <1> MED_CHANGE: 3120 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3121 00001907 E897050000 <1> call READ_DSKCHNG ; READ DISK CHANCE LINE STATE 3122 0000190C 7446 <1> jz short MC_OUT ; BYPASS HANDLING DISK CHANGE LINE 3123 0000190E 80A7[B7610000]EF <1> and byte [DSK_STATE+edi], ~MED_DET ; CLEAR STATE FOR THIS DRIVE 3124 <1> 3125 <1> ; THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT 3126 <1> ; ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL 3127 <1> ; BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING). 3128 <1> 3129 00001915 89F9 <1> mov ecx, edi ; CL = DRIVE # 3130 00001917 B001 <1> mov al, 1 ; MOTOR ON BIT MASK 3131 00001919 D2E0 <1> shl al, cl ; TO APPROPRIATE POSITION 3132 0000191B F6D0 <1> not al ; KEEP ALL BUT MOTOR ON 3133 0000191D FA <1> cli ; NO INTERRUPTS 3134 0000191E 2005[AA610000] <1> and [MOTOR_STATUS], al ; TURN MOTOR OFF INDICATOR 3135 00001924 FB <1> sti ; INTERRUPTS ENABLED 3136 00001925 E832030000 <1> call MOTOR_ON ; TURN MOTOR ON 3137 <1> 3138 <1> ;----- THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL 3139 <1> 3140 0000192A E85BFEFFFF <1> call DSK_RESET ; RESET NEC 3141 0000192F B501 <1> mov ch, 1 ; MOVE TO CYLINDER 1 3142 00001931 E815040000 <1> call SEEK ; ISSUE SEEK 3143 00001936 30ED <1> xor ch, ch ; MOVE TO CYLINDER 0 3144 00001938 E80E040000 <1> call SEEK ; ISSUE SEEK 3145 0000193D C605[AC610000]06 <1> mov byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS 3146 <1> OK1: 3147 00001944 E85A050000 <1> call READ_DSKCHNG ; CHECK MEDIA CHANGED AGAIN 3148 00001949 7407 <1> jz short OK2 ; IF ACTIVE, NO DISKETTE, TIMEOUT 3149 <1> OK4: 3150 0000194B C605[AC610000]80 <1> mov byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY 3151 <1> OK2: 3152 00001952 F9 <1> stc ; MEDIA CHANGED, SET CY 3153 00001953 C3 <1> retn 3154 <1> MC_OUT: 3155 <1> ;clc ; 08/07/2022 ; NO MEDIA CHANGED, CLEAR CY 3156 00001954 C3 <1> retn 3157 <1> 3158 <1> ;------------------------------------------------------------------------------- 3159 <1> ; SEND_RATE 3160 <1> ; SENDS DATA RATE COMMAND TO NEC 3161 <1> ; ON ENTRY: EDI = DRIVE # 3162 <1> ; ON EXIT: NONE 3163 <1> ; REGISTERS ALTERED: EDX, EAX ; 11/07/2022 3164 <1> ;------------------------------------------------------------------------------- 3165 <1> SEND_RATE: 3166 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3167 <1> ;push ax ; SAVE REG. 3168 <1> ; 24/12/2021 3169 <1> ;push eax ; 11/07/2022 3170 00001955 8025[B4610000]3F <1> and byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED 3171 0000195C 8A87[B7610000] <1> mov al, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 3172 00001962 24C0 <1> and al, SEND_MSK ; KEEP ONLY RATE BITS 3173 00001964 0805[B4610000] <1> or [LASTRATE], al ; SAVE NEW RATE FOR NEXT CHECK 3174 0000196A C0C002 <1> rol al, 2 ; MOVE TO BIT OUTPUT POSITIONS 3175 0000196D 66BAF703 <1> mov dx, 03F7h ; OUTPUT NEW DATA RATE 3176 00001971 EE <1> out dx, al 3177 <1> ;pop ax ; RESTORE REG. 3178 <1> ; 24/12/2021 3179 <1> ;pop eax ; 11/07/2022 3180 00001972 C3 <1> retn 3181 <1> 3182 <1> ;------------------------------------------------------------------------------- 3183 <1> ; CHK_LASTRATE 3184 <1> ; CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER. 3185 <1> ; ON ENTRY: 3186 <1> ; EDI = DRIVE # 3187 <1> ; ON EXIT: 3188 <1> ; ZF = 1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC 3189 <1> ; ZF = 0 DATA RATE IS DIFFERENT FROM LAST RATE 3190 <1> ; REGISTERS ALTERED: EAX ; 11/07/2022 3191 <1> ;------------------------------------------------------------------------------- 3192 <1> CHK_LASTRATE: 3193 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3194 <1> ;push ax ; SAVE REG. 3195 <1> ; 24/12/2021 3196 <1> ;push eax ; 11/07/2022 3197 00001973 8A25[B4610000] <1> mov ah, [LASTRATE] ; 08/07/2022 (BugFix) 3198 <1> ; GET LAST DATA RATE SELECTED 3199 00001979 8A87[B7610000] <1> mov al, [DSK_STATE+edi] ; GET RATE STATE OF THIS DRIVE 3200 0000197F 6625C0C0 <1> and ax, SEND_MSK*257 ; KEEP ONLY RATE BITS OF BOTH 3201 00001983 38E0 <1> cmp al, ah ; COMPARE TO PREVIOUSLY TRIED 3202 <1> ; ZF = 1 RATE IS THE SAME 3203 <1> ;pop ax ; RESTORE REG. 3204 <1> ; 24/12/2021 3205 <1> ;pop eax ; 11/07/2022 3206 00001985 C3 <1> retn 3207 <1> 3208 <1> ;------------------------------------------------------------------------------- 3209 <1> ; DMA_SETUP 3210 <1> ; THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS. 3211 <1> ; 3212 <1> ; ON ENTRY: AL = DMA COMMAND 3213 <1> ; 3214 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3215 <1> ;------------------------------------------------------------------------------- 3216 <1> 3217 <1> ; SI = Head #, # of Sectors or DASD Type 3218 <1> 3219 <1> ; 22/08/2015 3220 <1> ; 08/02/2015 - Protected Mode Modification 3221 <1> ; 06/02/2015 - 07/02/2015 3222 <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit). 3223 <1> ; (DMA Addres = Physical Address) 3224 <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address) 3225 <1> ; 3226 <1> ; 04/02/2016 (clc) 3227 <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP) 3228 <1> ; 16/12/2014 (IODELAY) 3229 <1> 3230 <1> DMA_SETUP: 3231 <1> ; 18/07/2022 3232 <1> ; 11/07/2022 3233 <1> ; ebp = buffer address 3234 <1> 3235 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3236 <1> ;; 20/02/2015 3237 <1> ;mov edx, [ebp+4] ; 11/07/2022 ; Buffer address 3238 <1> ; 08/07/2022 - not needed for Retro UNIX 386 v1.1 3239 <1> ;test edx, 0FF000000h ; 16 MB limit (22/08/2015, bugfix) 3240 <1> ;jnz short dma_bnd_err_stc 3241 <1> 3242 <1> ; al = dma command 3243 <1> 3244 <1> ; ; 18/07/2022 3245 <1> ; ; (512 bytes/sector only!) 3246 <1> ; ; 24/12/2021 3247 <1> ; push eax ; DMA command 3248 <1> ; ;push edx ; 11/07/2022 ; * 3249 <1> ; ;mov dl, 3 ; GET BYTES/SECTOR PARAMETER 3250 <1> ; mov al, 3 ; 08/07/2022 3251 <1> ; call GET_PARM ; 3252 <1> ; mov cl, ah ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 3253 <1> ; ;mov ax, si ; Sector count 3254 <1> ; ;mov ah, al ; AH = # OF SECTORS 3255 <1> ; ;sub al, al ; AL = 0, AX = # SECTORS * 256 3256 <1> ; ;shr ax, 1 ; AX = # SECTORS * 128 3257 <1> ; ;shl ax, cl ; SHIFT BY PARAMETER VALUE 3258 <1> ; ; 08/07/2022 3259 <1> ; ; 24/12/2021 3260 <1> ; ;mov edx, esi 3261 <1> ; sub eax, eax 3262 <1> ; ;mov ah, dl 3263 <1> ; ;shr eax, 1 3264 <1> ; mov al, 128 3265 <1> ; shl eax, cl 3266 <1> ; ; 3267 <1> ; dec eax ; -1 FOR DMA VALUE 3268 <1> ; mov ecx, eax 3269 <1> ; ;pop edx ; 11/07/2022 ; * 3270 <1> ; ; 24/12/2021 3271 <1> ; pop eax 3272 <1> 3273 <1> ; 08/07/2022 3274 <1> ;cmp al, 42h 3275 <1> ;jne short NOT_VERF 3276 <1> ;mov edx, 0FF0000h 3277 <1> ;jmp short J33 3278 <1> ;NOT_VERF: 3279 <1> ; 11/07/2022 3280 00001986 89EA <1> mov edx, ebp 3281 <1> ; 3282 <1> ;add dx, cx ; check for (64K) overflow 3283 <1> ; 18/07/2022 3284 <1> ; (512 bytes/sector) 3285 00001988 6681C2FF01 <1> add dx, 511 3286 0000198D 7239 <1> jc short dma_bnd_err 3287 <1> ; 3288 <1> ;sub dx, cx ; 11/07/2022 ; Restore start address 3289 <1> J33: 3290 <1> ; 08/07/2022 3291 0000198F FA <1> cli ; DISABLE INTERRUPTS DURING DMA SET-UP 3292 00001990 E60C <1> out DMA+12, al ; SET THE FIRST/LAST F/F 3293 <1> IODELAY ; WAIT FOR I/O 2191 00001992 EB00 <2> jmp short $+2 2192 00001994 EB00 <2> jmp short $+2 3294 00001996 E60B <1> out DMA+11, al ; OUTPUT THE MODE BYTE 3295 <1> ;mov eax, edx ; Buffer address 3296 <1> ; 11/07/2022 3297 00001998 89E8 <1> mov eax, ebp ; buffer address 3298 0000199A E604 <1> out DMA+4, al ; OUTPUT LOW ADDRESS 3299 <1> IODELAY ; WAIT FOR I/O 2191 0000199C EB00 <2> jmp short $+2 2192 0000199E EB00 <2> jmp short $+2 3300 000019A0 88E0 <1> mov al, ah 3301 000019A2 E604 <1> out DMA+4, al ; OUTPUT HIGH ADDRESS 3302 000019A4 C1E810 <1> shr eax, 16 3303 <1> IODELAY ; I/O WAIT STATE 2191 000019A7 EB00 <2> jmp short $+2 2192 000019A9 EB00 <2> jmp short $+2 3304 000019AB E681 <1> out 081h, al ; OUTPUT highest BITS TO PAGE REGISTER 3305 <1> IODELAY 2191 000019AD EB00 <2> jmp short $+2 2192 000019AF EB00 <2> jmp short $+2 3306 <1> ;;mov ax, cx ; Byte count - 1 3307 <1> ;mov al, cl 3308 <1> ; 18/07/2022 3309 <1> ; (Byte count - 1 = 511) 3310 000019B1 B0FF <1> mov al, 0FFh ; 511-256 3311 000019B3 E605 <1> out DMA+5, al ; LOW BYTE OF COUNT 3312 <1> IODELAY ; WAIT FOR I/O 2191 000019B5 EB00 <2> jmp short $+2 2192 000019B7 EB00 <2> jmp short $+2 3313 <1> ;;mov al, ah 3314 <1> ;mov al, ch 3315 <1> ; 18/07/2022 3316 000019B9 B001 <1> mov al, 1 ; 256 3317 000019BB E605 <1> out DMA+5, al ; HIGH BYTE OF COUNT 3318 <1> IODELAY 2191 000019BD EB00 <2> jmp short $+2 2192 000019BF EB00 <2> jmp short $+2 3319 000019C1 FB <1> sti ; RE-ENABLE INTERRUPTS 3320 000019C2 B002 <1> mov al, 2 ; MODE FOR 8237 3321 000019C4 E60A <1> out DMA+10, al ; INITIALIZE THE DISKETTE CHANNEL 3322 <1> 3323 000019C6 F8 <1> clc ; 04/02/2016 3324 <1> 3325 000019C7 C3 <1> retn 3326 <1> 3327 <1> ; 18/07/2022 3328 <1> ;dma_bnd_err_stc: 3329 <1> ; stc 3330 <1> 3331 <1> dma_bnd_err: 3332 000019C8 C605[AC610000]09 <1> mov byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 3333 000019CF C3 <1> retn ; CY SET BY ABOVE IF ERROR 3334 <1> 3335 <1> ;------------------------------------------------------------------------------- 3336 <1> ; NEC_INIT 3337 <1> ; THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES 3338 <1> ; THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION. 3339 <1> ; 3340 <1> ; ON ENTRY: AH = NEC COMMAND TO BE PERFORMED 3341 <1> ; 3342 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3343 <1> ;------------------------------------------------------------------------------- 3344 <1> NEC_INIT: 3345 <1> ; 11/07/2022 3346 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3347 <1> ;push ax ; SAVE NEC COMMAND 3348 <1> ; 24/12/2021 3349 000019D0 50 <1> push eax 3350 000019D1 E886020000 <1> call MOTOR_ON ; TURN MOTOR ON FOR SPECIFIC DRIVE 3351 <1> 3352 <1> ;----- DO THE SEEK OPERATION 3353 <1> 3354 <1> ;mov ch, [ebp+1] ; CH = TRACK # 3355 <1> ; 11/07/2022 3356 000019D6 89F1 <1> mov ecx, esi ; byte 2 = track, byte = 1 head, byte 0 = sector 3357 000019D8 C1E908 <1> shr ecx, 8 3358 <1> ; ch = track # 3359 <1> 3360 000019DB E86B030000 <1> call SEEK ; MOVE TO CORRECT TRACK 3361 <1> ;pop ax ; RECOVER COMMAND 3362 <1> ; 24/12/2021 3363 000019E0 58 <1> pop eax 3364 000019E1 721D <1> jc short ER_1 ; ERROR ON SEEK 3365 000019E3 BB[001A0000] <1> mov ebx, ER_1 ; LOAD ERROR ADDRESS 3366 000019E8 53 <1> push ebx ; PUSH NEC_OUT ERROR RETURN 3367 <1> 3368 <1> ;----- SEND OUT THE PARAMETERS TO THE CONTROLLER 3369 <1> 3370 000019E9 E824030000 <1> call NEC_OUTPUT ; OUTPUT THE OPERATION COMMAND 3371 000019EE 89F0 <1> mov eax, esi ; AH = HEAD # 3372 000019F0 89FB <1> mov ebx, edi ; BL = DRIVE # 3373 000019F2 C0E402 <1> sal ah, 2 ; MOVE IT TO BIT 2 3374 000019F5 80E404 <1> and ah, 00000100b ; ISOLATE THAT BIT 3375 000019F8 08DC <1> or ah, bl ; OR IN THE DRIVE NUMBER 3376 000019FA E813030000 <1> call NEC_OUTPUT ; FALL THRU CY SET IF ERROR 3377 000019FF 5B <1> pop ebx ; THROW AWAY ERROR RETURN 3378 <1> ER_1: 3379 00001A00 C3 <1> retn 3380 <1> 3381 <1> ;------------------------------------------------------------------------------- 3382 <1> ; RWV_COM 3383 <1> ; THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 3384 <1> ; READ/WRITE/VERIFY OPERATIONS. 3385 <1> ; 3386 <1> ; ON ENTRY: EBX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE 3387 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3388 <1> ;------------------------------------------------------------------------------- 3389 <1> RWV_COM: 3390 <1> ; 11/07/2022 3391 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3392 00001A01 B8[4E1A0000] <1> mov eax, ER_2 ; LOAD ERROR ADDRESS 3393 00001A06 50 <1> push eax ; PUSH NEC_OUT ERROR RETURN 3394 <1> ;mov ah, [ebp+1] ; OUTPUT TRACK # 3395 <1> ; 11/07/2022 3396 00001A07 89F0 <1> mov eax, esi ; byte 0 = sector, byte 1 = head, byte 2 = track 3397 00001A09 C1E808 <1> shr eax, 8 3398 <1> ; ah = track # 3399 00001A0C E801030000 <1> call NEC_OUTPUT 3400 00001A11 89F0 <1> mov eax, esi ; OUTPUT HEAD # 3401 <1> ; ah = head # 3402 00001A13 E8FA020000 <1> call NEC_OUTPUT 3403 <1> ;mov ah, [ebp] ; OUTPUT SECTOR # 3404 00001A18 89F0 <1> mov eax, esi 3405 00001A1A 88C4 <1> mov ah, al 3406 <1> ; ah = sector # 3407 00001A1C E8F1020000 <1> CALL NEC_OUTPUT 3408 <1> ;mov dl, 3 ; BYTES/SECTOR PARAMETER FROM BLOCK 3409 00001A21 B003 <1> mov al, 3 ; 08/07/2022 3410 00001A23 E8F9010000 <1> call GET_PARM ; .. TO THE NEC 3411 00001A28 E8E5020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 3412 <1> ;mov dl, 4 ; EOT PARAMETER FROM BLOCK 3413 00001A2D B004 <1> mov al, 4 ; 08/07/2022 3414 00001A2F E8ED010000 <1> call GET_PARM ; .. TO THE NEC 3415 00001A34 E8D9020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 3416 00001A39 8A6305 <1> mov ah, [ebx+MD.GAP] ; GET GAP LENGTH 3417 <1> _R15: 3418 00001A3C E8D1020000 <1> call NEC_OUTPUT 3419 <1> ;mov dl, 6 ; DTL PARAMETER PROM BLOCK 3420 00001A41 B006 <1> mov al, 6 ; 08/07/2022 3421 00001A43 E8D9010000 <1> call GET_PARM ; .. TO THE NEC 3422 00001A48 E8C5020000 <1> call NEC_OUTPUT ; OUTPUT TO CONTROLLER 3423 00001A4D 58 <1> pop eax ; THROW AWAY ERROR EXIT 3424 <1> ER_2: 3425 00001A4E C3 <1> retn 3426 <1> 3427 <1> ;------------------------------------------------------------------------------- 3428 <1> ; NEC_TERM 3429 <1> ; THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 3430 <1> ; FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION. 3431 <1> ; 3432 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3433 <1> ;------------------------------------------------------------------------------- 3434 <1> 3435 <1> NEC_TERM: 3436 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3437 <1> 3438 <1> ;----- LET THE OPERATION HAPPEN 3439 <1> 3440 00001A4F 56 <1> push esi ; SAVE HEAD #, # OF SECTORS 3441 00001A50 E8C7030000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 3442 00001A55 9C <1> pushfd ; 24/12/2021 3443 00001A56 E8F0030000 <1> call RESULTS ; GET THE NEC STATUS 3444 00001A5B 724B <1> jc short SET_END_POP 3445 00001A5D 9D <1> popfd ; 24/12/2021 3446 00001A5E 723E <1> jc short SET_END ; LOOK FOR ERROR 3447 <1> 3448 <1> ;----- CHECK THE RESULTS RETURNED BY THE CONTROLLER 3449 <1> 3450 00001A60 FC <1> cld ; SET THE CORRECT DIRECTION 3451 00001A61 BE[AD610000] <1> mov esi, NEC_STATUS ; POINT TO STATUS FIELD 3452 00001A66 AC <1> lodsb ; GET ST0 3453 00001A67 24C0 <1> and al, 11000000b ; TEST FOR NORMAL TERMINATION 3454 00001A69 7433 <1> jz short SET_END 3455 00001A6B 3C40 <1> cmp al, 01000000b ; TEST FOR ABNORMAL TERMINATION 3456 00001A6D 7527 <1> jnz short J18 ; NOT ABNORMAL, BAD NEC 3457 <1> 3458 <1> ;----- ABNORMAL TERMINATION, FIND OUT WHY 3459 <1> 3460 00001A6F AC <1> lodsb ; GET ST1 3461 00001A70 D0E0 <1> sal al, 1 ; TEST FOR EDT FOUND 3462 00001A72 B404 <1> mov ah, RECORD_NOT_FND 3463 00001A74 7222 <1> jc short J19 3464 00001A76 C0E002 <1> sal al, 2 3465 00001A79 B410 <1> mov ah, BAD_CRC 3466 00001A7B 721B <1> jc short J19 3467 00001A7D D0E0 <1> sal al, 1 ; TEST FOR DMA OVERRUN 3468 00001A7F B408 <1> mov ah, BAD_DMA 3469 00001A81 7215 <1> jc short J19 3470 00001A83 C0E002 <1> sal al, 2 ; TEST FOR RECORD NOT FOUND 3471 00001A86 B404 <1> mov ah, RECORD_NOT_FND 3472 00001A88 720E <1> jc short J19 3473 00001A8A D0E0 <1> sal al, 1 3474 00001A8C B403 <1> mov ah, WRITE_PROTECT ; TEST FOR WRITE_PROTECT 3475 00001A8E 7208 <1> jc short J19 3476 00001A90 D0E0 <1> sal al, 1 ; TEST MISSING ADDRESS MARK 3477 00001A92 B402 <1> mov ah, BAD_ADDR_MARK 3478 00001A94 7202 <1> jc short J19 3479 <1> 3480 <1> ;----- NEC MUST HAVE FAILED 3481 <1> J18: 3482 00001A96 B420 <1> mov ah, BAD_NEC 3483 <1> J19: 3484 00001A98 0825[AC610000] <1> or [DSKETTE_STATUS], ah 3485 <1> SET_END: 3486 00001A9E 803D[AC610000]01 <1> cmp byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION 3487 00001AA5 F5 <1> cmc 3488 00001AA6 5E <1> pop esi 3489 00001AA7 C3 <1> retn ; RESTORE HEAD #, # OF SECTORS 3490 <1> 3491 <1> SET_END_POP: 3492 00001AA8 9D <1> popfd ; 24/12/2021 3493 00001AA9 EBF3 <1> jmp short SET_END 3494 <1> 3495 <1> ;------------------------------------------------------------------------------- 3496 <1> ; DSTATE: ESTABLISH STATE UPON SUCCESSFUL OPERATION. 3497 <1> ;------------------------------------------------------------------------------- 3498 <1> DSTATE: 3499 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3500 00001AAB 803D[AC610000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR 3501 00001AB2 753E <1> jne short SETBAC ; IF ERROR JUMP 3502 00001AB4 808F[B7610000]10 <1> or byte [DSK_STATE+edi], MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED 3503 00001ABB F687[B7610000]04 <1> test byte [DSK_STATE+edi], DRV_DET ; DRIVE DETERMINED ? 3504 00001AC2 752E <1> jnz short SETBAC ; IF DETERMINED NO TRY TO DETERMINE 3505 00001AC4 8A87[B7610000] <1> mov al, [DSK_STATE+edi] ; LOAD STATE 3506 00001ACA 24C0 <1> and al, RATE_MSK ; KEEP ONLY RATE 3507 00001ACC 3C80 <1> cmp al, RATE_250 ; RATE 250 ? 3508 00001ACE 751B <1> jne short M_12 ; NO, MUST BE 1.2M OR 1.44M DRIVE 3509 <1> 3510 <1> ;----- CHECK IF IT IS 1.44M 3511 <1> 3512 00001AD0 E843010000 <1> call CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 3513 <1> ;;20/02/2015 3514 <1> ;;jc short M_12 ; CMOS BAD 3515 00001AD5 7414 <1> jz short M_12 ;; 20/02/2015 3516 00001AD7 3C04 <1> cmp al, 4 ; 1.44MB DRIVE ? 3517 00001AD9 7410 <1> je short M_12 ; YES 3518 <1> M_720: 3519 00001ADB 80A7[B7610000]FD <1> and byte [DSK_STATE+edi], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY 3520 00001AE2 808F[B7610000]04 <1> or byte [DSK_STATE+edi], DRV_DET ; MARK DRIVE DETERMINED 3521 00001AE9 EB07 <1> jmp short SETBAC ; BACK 3522 <1> M_12: 3523 00001AEB 808F[B7610000]06 <1> or byte [DSK_STATE+edi], DRV_DET+FMT_CAPA 3524 <1> ; TURN ON DETERMINED & FMT CAPA 3525 <1> SETBAC: 3526 00001AF2 C3 <1> retn 3527 <1> 3528 <1> ;------------------------------------------------------------------------------- 3529 <1> ; RETRY 3530 <1> ; DETERMINES WHETHER A RETRY IS NECESSARY. 3531 <1> ; IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY. 3532 <1> ; 3533 <1> ; ON EXIT: CY = 1 FOR RETRY, CY = 0 FOR NO RETRY 3534 <1> ;------------------------------------------------------------------------------- 3535 <1> RETRY: 3536 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3537 00001AF3 803D[AC610000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; GET STATUS OF OPERATION 3538 00001AFA 7444 <1> je short NO_RETRY ; SUCCESSFUL OPERATION 3539 00001AFC 803D[AC610000]80 <1> cmp byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT NO RETRY 3540 00001B03 743B <1> je short NO_RETRY 3541 00001B05 8AA7[B7610000] <1> mov ah, [DSK_STATE+edi] ; GET MEDIA STATE OF DRIVE 3542 00001B0B F6C410 <1> test ah, MED_DET ; ESTABLISHED/DETERMINED ? 3543 00001B0E 7530 <1> jnz short NO_RETRY ; IF ESTABLISHED STATE THEN TRUE ERROR 3544 00001B10 80E4C0 <1> and ah, RATE_MSK ; ISOLATE RATE 3545 00001B13 8A2D[B4610000] <1> mov ch, [LASTRATE] ; GET START OPERATION STATE 3546 00001B19 C0C504 <1> rol ch, 4 ; TO CORRESPONDING BITS 3547 00001B1C 80E5C0 <1> and ch, RATE_MSK ; ISOLATE RATE BITS 3548 00001B1F 38E5 <1> cmp ch, ah ; ALL RATES TRIED 3549 00001B21 741D <1> je short NO_RETRY ; IF YES, THEN TRUE ERROR 3550 <1> 3551 <1> ; SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE 3552 <1> ; 00000000B (500) -> 10000000B (250) 3553 <1> ; 10000000B (250) -> 01000000B (300) 3554 <1> ; 01000000B (300) -> 00000000B (500) 3555 <1> 3556 00001B23 80FC01 <1> cmp ah, RATE_500+1 ; SET CY FOR RATE 500 3557 00001B26 D0DC <1> rcr ah, 1 ; TO NEXT STATE 3558 00001B28 80E4C0 <1> and ah, RATE_MSK ; KEEP ONLY RATE BITS 3559 00001B2B 80A7[B7610000]1F <1> and byte [DSK_STATE+edi], ~(RATE_MSK+DBL_STEP) 3560 <1> ; RATE, DBL STEP OFF 3561 00001B32 08A7[B7610000] <1> or [DSK_STATE+edi], ah ; TURN ON NEW RATE 3562 00001B38 C605[AC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; RESET STATUS FOR RETRY 3563 00001B3F F9 <1> stc ; SET CARRY FOR RETRY 3564 <1> NO_RETRY: ; 08/07/2022 3565 00001B40 C3 <1> retn ; RETRY RETURN 3566 <1> 3567 <1> ;NO_RETRY: 3568 <1> ;clc ; CLEAR CARRY NO RETRY 3569 <1> ;RETn ; NO RETRY RETURN 3570 <1> 3571 <1> ;------------------------------------------------------------------------------- 3572 <1> ; NUM_TRANS 3573 <1> ; THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE 3574 <1> ; ACTUALLY TRANSFERRED TO/FROM THE DISKETTE. 3575 <1> ; 3576 <1> ; ON ENTRY: [BP+1] = TRACK 3577 <1> ; SI-HI = HEAD 3578 <1> ; [BP] = START SECTOR 3579 <1> ; 3580 <1> ; ON EXIT: AL = NUMBER ACTUALLY TRANSFERRED 3581 <1> ;------------------------------------------------------------------------------- 3582 <1> NUM_TRANS: 3583 <1> ; 11/07/2022 3584 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3585 00001B41 30C0 <1> xor al, al ; CLEAR FOR ERROR 3586 00001B43 803D[AC610000]00 <1> cmp byte [DSKETTE_STATUS], 0 ; CHECK FOR ERROR 3587 <1> ; 24/12/2021 3588 00001B4A 7529 <1> jne short NT_OUT ; IF ERROR 0 TRANSFERRED 3589 <1> ;mov dl, 4 ; SECTORS/TRACK OFFSET TO DL 3590 00001B4C B004 <1> mov al, 4 ; 08/07/2022 3591 00001B4E E8CE000000 <1> call GET_PARM ; AH = SECTORS/TRACK 3592 <1> ;mov bl, [NEC_STATUS+5] ; GET ENDING SECTOR 3593 00001B53 A0[B2610000] <1> mov al, [NEC_STATUS+5] 3594 00001B58 89F1 <1> mov ecx, esi ; CH = HEAD # STARTED 3595 00001B5A 88CB <1> mov bl, cl ; 11/07/2022 ; sector # 3596 00001B5C 3A2D[B1610000] <1> cmp ch, [NEC_STATUS+4] ; GET HEAD ENDED UP ON 3597 00001B62 750D <1> jne short DIF_HD ; IF ON SAME HEAD, THEN NO ADJUST 3598 <1> ; 11/07/2022 3599 <1> ;mov ch, [NEC_STATUS+3] ; GET TRACK ENDED UP ON 3600 <1> ;cmp ch, [ebp+1] ; IS IT ASKED FOR TRACK 3601 <1> ;jz short SAME_TR ; IF SAME TRACK NO INCREASE 3602 00001B64 C1E908 <1> shr ecx, 8 ; byte 3 = track # --> byte 2 3603 00001B67 3A2D[B0610000] <1> cmp ch, [NEC_STATUS+3] 3604 00001B6D 7404 <1> je short SAME_TRK 3605 <1> ; 11/07/2022 3606 <1> ;add bl, ah ; ADD SECTORS/TRACK 3607 00001B6F 00E0 <1> add al, ah 3608 <1> DIF_HD: 3609 <1> ;add bl, ah ; ADD SECTORS/TRACK 3610 00001B71 00E0 <1> add al, ah 3611 <1> SAME_TRK: 3612 <1> ;sub bl, [ebp] ; SUBTRACT START FROM END 3613 <1> ;mov al, bl ; TO AL 3614 00001B73 28D8 <1> sub al, bl 3615 <1> NT_OUT: 3616 00001B75 C3 <1> retn 3617 <1> 3618 <1> ;------------------------------------------------------------------------------- 3619 <1> ; SETUP_DBL 3620 <1> ; CHECK DOUBLE STEP. 3621 <1> ; 3622 <1> ; ON ENTRY : EDI = DRIVE # 3623 <1> ; 3624 <1> ; ON EXIT : CY = 1 MEANS ERROR 3625 <1> ;------------------------------------------------------------------------------- 3626 <1> SETUP_DBL: 3627 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3628 00001B76 8AA7[B7610000] <1> mov ah, [DSK_STATE+edi] ; ACCESS STATE 3629 00001B7C F6C410 <1> test ah, MED_DET ; ESTABLISHED STATE ? 3630 00001B7F 7578 <1> jnz short NO_DBL ; IF ESTABLISHED THEN DOUBLE DONE 3631 <1> 3632 <1> ;----- CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE 3633 <1> 3634 00001B81 C605[A9610000]00 <1> mov byte [SEEK_STATUS], 0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 3635 00001B88 E8CF000000 <1> call MOTOR_ON ; ENSURE MOTOR STAY ON 3636 00001B8D B500 <1> mov ch, 0 ; LOAD TRACK 0 3637 00001B8F E8B7010000 <1> call SEEK ; SEEK TO TRACK 0 3638 00001B94 E862000000 <1> call READ_ID ; READ ID FUNCTION 3639 00001B99 7243 <1> jc short SD_ERR ; IF ERROR NO TRACK 0 3640 <1> 3641 <1> ;----- INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS) 3642 <1> 3643 00001B9B 66B95004 <1> mov cx, 0450h ; START, MAX TRACKS 3644 00001B9F F687[B7610000]01 <1> test byte [DSK_STATE+edi], TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY 3645 00001BA6 7402 <1> jz short CNT_OK ; IF NOT COUNT IS SETUP 3646 00001BA8 B1A0 <1> mov cl, 0A0h ; MAXIMUM TRACK 1.2 MB 3647 <1> 3648 <1> ; ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS, 3649 <1> ; MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT 3650 <1> ; THEN SET DOUBLE STEP ON. 3651 <1> 3652 <1> CNT_OK: 3653 00001BAA C605[AB610000]FF <1> mov byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 3654 <1> ; 24/12/2021 3655 00001BB1 51 <1> push ecx ; SAVE TRACK, COUNT 3656 00001BB2 C605[AC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; CLEAR STATUS, EXPECT ERRORS 3657 00001BB9 31C0 <1> xor eax, eax ; CLEAR EAX 3658 00001BBB D0ED <1> shr ch, 1 ; HALVE TRACK, CY = HEAD 3659 00001BBD C0D003 <1> rcl al, 3 ; AX = HEAD IN CORRECT BIT 3660 <1> ; 24/12/2021 3661 00001BC0 50 <1> push eax ; SAVE HEAD 3662 00001BC1 E885010000 <1> call SEEK ; SEEK TO TRACK 3663 <1> ; 24/12/2021 3664 00001BC6 58 <1> pop eax ; RESTORE HEAD 3665 00001BC7 09C7 <1> or edi, eax ; DI = HEAD OR'ED DRIVE 3666 00001BC9 E82D000000 <1> call READ_ID ; READ ID HEAD 0 3667 00001BCE 9C <1> pushf ; SAVE RETURN FROM READ_ID 3668 00001BCF 6681E7FB00 <1> and di, 11111011b ; TURN OFF HEAD 1 BIT 3669 00001BD4 9D <1> popf ; RESTORE ERROR RETURN 3670 <1> ; 24/12/2021 3671 00001BD5 59 <1> pop ecx ; RESTORE COUNT 3672 00001BD6 7308 <1> jnc short DO_CHK ; IF OK, ASKED = RETURNED TRACK ? 3673 00001BD8 FEC5 <1> inc ch ; INC FOR NEXT TRACK 3674 00001BDA 38CD <1> cmp ch, cl ; REACHED MAXIMUM YET 3675 00001BDC 75CC <1> jnz short CNT_OK ; CONTINUE TILL ALL TRIED 3676 <1> 3677 <1> ;----- FALL THRU, READ ID FAILED FOR ALL TRACKS 3678 <1> 3679 <1> SD_ERR: 3680 00001BDE F9 <1> stc ; SET CARRY FOR ERROR 3681 00001BDF C3 <1> retn ; SETUP_DBL ERROR EXIT 3682 <1> 3683 <1> DO_CHK: 3684 00001BE0 8A0D[B0610000] <1> mov cl, [NEC_STATUS+3] ; LOAD RETURNED TRACK 3685 00001BE6 888F[B9610000] <1> mov [DSK_TRK+edi], cl ; STORE TRACK NUMBER 3686 00001BEC D0ED <1> shr ch, 1 ; HALVE TRACK 3687 00001BEE 38CD <1> cmp ch, cl ; IS IT THE SAME AS ASKED FOR TRACK 3688 00001BF0 7407 <1> jz short NO_DBL ; IF SAME THEN NO DOUBLE STEP 3689 00001BF2 808F[B7610000]20 <1> or byte [DSK_STATE+edi], DBL_STEP ; TURN ON DOUBLE STEP REQUIRED 3690 <1> NO_DBL: 3691 00001BF9 F8 <1> clc ; CLEAR ERROR FLAG 3692 00001BFA C3 <1> retn 3693 <1> 3694 <1> ;------------------------------------------------------------------------------- 3695 <1> ; READ_ID 3696 <1> ; READ ID FUNCTION. 3697 <1> ; 3698 <1> ; ON ENTRY: EDI : BIT 2 = HEAD; BITS 1,0 = DRIVE 3699 <1> ; 3700 <1> ; ON EXIT: EDI : BIT 2 IS RESET, BITS 1,0 = DRIVE 3701 <1> ; @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 3702 <1> ;------------------------------------------------------------------------------- 3703 <1> READ_ID: 3704 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3705 00001BFB B8[171C0000] <1> mov eax, ER_3 ; MOVE NEC OUTPUT ERROR ADDRESS 3706 00001C00 50 <1> push eax 3707 00001C01 B44A <1> mov ah, 4Ah ; READ ID COMMAND 3708 00001C03 E80A010000 <1> call NEC_OUTPUT ; TO CONTROLLER 3709 00001C08 89F8 <1> mov eax, edi ; DRIVE # TO AH, HEAD 0 3710 00001C0A 88C4 <1> mov ah, al 3711 00001C0C E801010000 <1> call NEC_OUTPUT ; TO CONTROLLER 3712 00001C11 E839FEFFFF <1> call NEC_TERM ; WAIT FOR OPERATION, GET STATUS 3713 00001C16 58 <1> pop eax ; THROW AWAY ERROR ADDRESS 3714 <1> ER_3: 3715 00001C17 C3 <1> retn 3716 <1> 3717 <1> ;------------------------------------------------------------------------------- 3718 <1> ; CMOS_TYPE 3719 <1> ; RETURNS CMOS DISKETTE TYPE 3720 <1> ; 3721 <1> ; ON ENTRY: EDI = DRIVE # 3722 <1> ; 3723 <1> ; ON EXIT: AL = TYPE; CY REFLECTS STATUS 3724 <1> ;------------------------------------------------------------------------------- 3725 <1> 3726 <1> CMOS_TYPE: ; 11/12/2014 3727 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3728 00001C18 8A87[4C5C0000] <1> mov al, [edi+fd0_type] ; diskette type 3729 00001C1E 20C0 <1> and al, al ; 18/12/2014 3730 00001C20 C3 <1> retn 3731 <1> 3732 <1> ;------------------------------------------------------------------------------- 3733 <1> ; GET_PARM 3734 <1> ; THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE 3735 <1> ; BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM 3736 <1> ; THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING 3737 <1> ; THE PARAMETER IN DL. 3738 <1> ; 3739 <1> ; ON ENTRY: AL = INDEX OF BYTE TO BE FETCHED ; 08/07/2022 3740 <1> ; 3741 <1> ; ON EXIT: AH = THAT BYTE FROM BLOCK 3742 <1> ; AL DESTROYED 3743 <1> ;------------------------------------------------------------------------------- 3744 <1> GET_PARM: 3745 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3746 <1> ; ENTRY: 3747 <1> ; AL = INDEX 3748 <1> ; EDI = DRIVE # 3749 <1> ; RETURN: 3750 <1> ; AH = REQUESTED PARAMETER 3751 <1> ; AL DESTROYED 3752 <1> 3753 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3754 <1> ; 08/02/2015 (protected mode modifications, bx -> ebx) 3755 <1> ;push esi ; 11/07/2022 3756 00001C21 53 <1> push ebx ; SAVE EBX 3757 00001C22 0FB6D8 <1> movzx ebx, al ; EBX = INDEX 3758 <1> ; 17/12/2014 3759 <1> ;mov ax, [cfd] ; current (AL) and previous fd (AH) 3760 <1> ; 11/07/2022 3761 <1> ;cmp al, ah 3762 <1> ;je short gpndc 3763 <1> 3764 <1> ; 11/07/2022 3765 00001C25 89F8 <1> mov eax, edi 3766 00001C27 3A05[415C0000] <1> cmp al, [pfd] ; is same with previous drive # ? 3767 00001C2D 7423 <1> je short gpndc 3768 <1> 3769 00001C2F A2[415C0000] <1> mov [pfd], al ; current drive -> previous drive 3770 <1> 3771 00001C34 53 <1> push ebx ; 08/02/2015 3772 <1> 3773 <1> ;mov bl, al 3774 <1> ; 11/12/2014 3775 <1> ;mov al, [ebx+fd0_type] ; Drive type (0,1,2,3,4) 3776 <1> ; 11/07/2022 3777 00001C35 8A87[4C5C0000] <1> mov al, [edi+fd0_type] ; Drive type (0,1,2,3,4) 3778 <1> ; 18/12/2014 3779 00001C3B 20C0 <1> and al, al 3780 00001C3D 7507 <1> jnz short gpdtc 3781 00001C3F BB[2B5C0000] <1> mov ebx, MD_TBL6 ; 1.44 MB param. tbl. (default) 3782 00001C44 EB05 <1> jmp short gpdpu 3783 <1> gpdtc: 3784 00001C46 E8B0FBFFFF <1> call DR_TYPE_CHECK 3785 <1> ; cf = 1 -> EBX points to 1.44MB fd parameter table (default) 3786 <1> gpdpu: 3787 00001C4B 891D[C85B0000] <1> mov [DISK_POINTER], ebx 3788 00001C51 5B <1> pop ebx 3789 <1> gpndc: 3790 <1> ;mov esi, [DISK_POINTER] ; 08/02/2015, si -> esi 3791 <1> ;mov ah, [esi+ebx] ; GET THE WORD 3792 <1> ; 11/07/2022 3793 00001C52 031D[C85B0000] <1> add ebx, [DISK_POINTER] 3794 00001C58 8A23 <1> mov ah, [ebx] 3795 00001C5A 5B <1> pop ebx ; RESTORE EBX 3796 <1> ;pop esi ; 11/07/2022 3797 00001C5B C3 <1> retn 3798 <1> 3799 <1> ;------------------------------------------------------------------------------- 3800 <1> ; MOTOR_ON 3801 <1> ; TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT 3802 <1> ; IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE 3803 <1> ; THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE 3804 <1> ; MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION 3805 <1> ; (AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM 3806 <1> ; THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS 3807 <1> ; FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT 3808 <1> ; HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE 3809 <1> ; THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID 3810 <1> ; NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE 3811 <1> ; PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN, 3812 <1> ; IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE 3813 <1> ; WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT. 3814 <1> ; 3815 <1> ; ON ENTRY: EDI = DRIVE # 3816 <1> ; ON EXIT: EAX, ECX, EDX DESTROYED 3817 <1> ;------------------------------------------------------------------------------- 3818 <1> MOTOR_ON: 3819 <1> ; 12/07/2022 3820 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3821 00001C5C 53 <1> push ebx ; SAVE REG. 3822 00001C5D E820000000 <1> call TURN_ON ; TURN ON MOTOR 3823 00001C62 721C <1> jc short MOT_IS_ON ; IF CY=1 NO WAIT 3824 <1> ;call XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 3825 <1> ; 08/07/2022 3826 <1> ;call XLAT_NEW ; 12/07/2022 ; TRANSLATE STATE TO PRESENT ARCH, 3827 <1> ;call TURN_ON ; CHECK AGAIN IF MOTOR ON 3828 <1> ;jc short MOT_IS_ON ; IF NO WAIT MEANS IT IS ON 3829 <1> M_WAIT: 3830 <1> ;mov dl,10 ; GET THE MOTOR WAIT PARAMETER 3831 00001C64 B00A <1> mov al, 10 ; 08/07/2022 3832 00001C66 E8B6FFFFFF <1> call GET_PARM 3833 <1> ; 08/07/2022 ; AH = MOTOR WAIT PARAMETER 3834 00001C6B 80FC08 <1> cmp ah, 8 ; SEE IF AT LEAST A SECOND IS SPECIFIED 3835 <1> ;jae short GP2 ; IF YES, CONTINUE 3836 00001C6E 7302 <1> jae short J13 3837 00001C70 B408 <1> mov ah, 8 ; ONE SECOND WAIT FOR MOTOR START UP 3838 <1> 3839 <1> ;----- AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT 3840 <1> GP2: 3841 <1> ;----- FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE 3842 <1> J13: ; WAIT FOR 1/8 SECOND PER (AL) 3843 00001C72 B95E200000 <1> mov ecx, 8286 ; COUNT FOR 1/8 SECOND AT 15.085737 US 3844 00001C77 E817F7FFFF <1> call WAITF ; GO TO FIXED WAIT ROUTINE 3845 <1> ;dec al ; DECREMENT TIME VALUE 3846 00001C7C FECC <1> dec ah 3847 00001C7E 75F2 <1> jnz short J13 ; ARE WE DONE YET 3848 <1> MOT_IS_ON: 3849 00001C80 5B <1> pop ebx ; RESTORE REG. 3850 00001C81 C3 <1> retn 3851 <1> 3852 <1> ;------------------------------------------------------------------------------- 3853 <1> ; TURN_ON 3854 <1> ; TURN MOTOR ON AND RETURN WAIT STATE. 3855 <1> ; 3856 <1> ; ON ENTRY: EDI = DRIVE # 3857 <1> ; 3858 <1> ; ON EXIT: CY = 0 MEANS WAIT REQUIRED 3859 <1> ; CY = 1 MEANS NO WAIT REQUIRED 3860 <1> ; EAX, EBX, ECX, EDX DESTROYED 3861 <1> ;------------------------------------------------------------------------------- 3862 <1> TURN_ON: 3863 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3864 00001C82 89FB <1> mov ebx, edi ; EBX = DRIVE # 3865 00001C84 88D9 <1> mov cl, bl ; CL = DRIVE # 3866 00001C86 C0C304 <1> rol bl, 4 ; BL = DRIVE SELECT 3867 00001C89 FA <1> cli ; NO INTERRUPTS WHILE DETERMINING STATUS 3868 00001C8A C605[AB610000]FF <1> mov byte [MOTOR_COUNT], 0FFh ; ENSURE MOTOR STAYS ON FOR OPERATION 3869 00001C91 A0[AA610000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 3870 00001C96 2430 <1> and al, 00110000b ; KEEP ONLY DRIVE SELECT BITS 3871 00001C98 B401 <1> mov ah, 1 ; MASK FOR DETERMINING MOTOR BIT 3872 00001C9A D2E4 <1> shl ah, cl ; AH = MOTOR ON, A=00000001, B=00000010 3873 <1> 3874 <1> ; AL = DRIVE SELECT FROM @MOTOR_STATUS 3875 <1> ; BL = DRIVE SELECT DESIRED 3876 <1> ; AH = MOTOR ON MASK DESIRED 3877 <1> 3878 00001C9C 38D8 <1> cmp al, bl ; REQUESTED DRIVE ALREADY SELECTED ? 3879 00001C9E 7508 <1> jne short TURN_IT_ON ; IF NOT SELECTED JUMP 3880 00001CA0 8425[AA610000] <1> test ah, [MOTOR_STATUS] ; TEST MOTOR ON BIT 3881 00001CA6 7535 <1> jnz short NO_MOT_WAIT ; JUMP IF MOTOR ON AND SELECTED 3882 <1> 3883 <1> TURN_IT_ON: 3884 00001CA8 08DC <1> or ah, bl ; AH = DRIVE SELECT AND MOTOR ON 3885 00001CAA 8A3D[AA610000] <1> mov bh, [MOTOR_STATUS] ; SAVE COPY OF @MOTOR_STATUS BEFORE 3886 00001CB0 80E70F <1> and bh, 00001111b ; KEEP ONLY MOTOR BITS 3887 00001CB3 8025[AA610000]CF <1> and byte [MOTOR_STATUS], 11001111b ; CLEAR OUT DRIVE SELECT 3888 00001CBA 0825[AA610000] <1> or [MOTOR_STATUS], ah ; OR IN DRIVE SELECTED AND MOTOR ON 3889 00001CC0 A0[AA610000] <1> mov al, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 3890 00001CC5 88C3 <1> mov bl, al ; BL=@MOTOR_STATUS AFTER, BH=BEFORE 3891 00001CC7 80E30F <1> and bl, 00001111b ; KEEP ONLY MOTOR BITS 3892 00001CCA FB <1> sti ; ENABLE INTERRUPTS AGAIN 3893 00001CCB 243F <1> and al, 00111111b ; STRIP AWAY UNWANTED BITS 3894 00001CCD C0C004 <1> rol al, 4 ; PUT BITS IN DESIRED POSITIONS 3895 00001CD0 0C0C <1> or al, 00001100b ; NO RESET, ENABLE DMA/INTERRUPT 3896 00001CD2 66BAF203 <1> mov dx, 03F2h ; SELECT DRIVE AND TURN ON MOTOR 3897 00001CD6 EE <1> out dx, al 3898 00001CD7 38FB <1> cmp bl, bh ; NEW MOTOR TURNED ON ? 3899 <1> ;je short NO_MOT_WAIT ; NO WAIT REQUIRED IF JUST SELECT 3900 00001CD9 7403 <1> je short no_mot_w1 ; 27/02/2015 3901 00001CDB F8 <1> clc ; RESET CARRY MEANING WAIT 3902 00001CDC C3 <1> retn 3903 <1> 3904 <1> NO_MOT_WAIT: 3905 00001CDD FB <1> sti 3906 <1> no_mot_w1: ; 27/02/2015 3907 00001CDE F9 <1> stc ; SET NO WAIT REQUIRED 3908 <1> ;sti ; INTERRUPTS BACK ON 3909 00001CDF C3 <1> retn 3910 <1> 3911 <1> ;------------------------------------------------------------------------------- 3912 <1> ; HD_WAIT 3913 <1> ; WAIT FOR HEAD SETTLE TIME. 3914 <1> ; 3915 <1> ; ON ENTRY: DI = DRIVE # 3916 <1> ; 3917 <1> ; ON EXIT: EAX, EBX, ECX, EDX DESTROYED 3918 <1> ;------------------------------------------------------------------------------- 3919 <1> HD_WAIT: 3920 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3921 <1> ;mov dl, 9 ; GET HEAD SETTLE PARAMETER 3922 00001CE0 B009 <1> mov al, 9 ; 08/07/2022 3923 00001CE2 E83AFFFFFF <1> CALL GET_PARM 3924 00001CE7 08E4 <1> or ah, ah ; 17/12/2014 ; CHECK FOR ANY WAIT? 3925 00001CE9 7519 <1> jnz short DO_WAT ; IF THERE DO NOT ENFORCE 3926 00001CEB F605[AA610000]80 <1> test byte [MOTOR_STATUS], 10000000b ; SEE IF A WRITE OPERATION 3927 <1> ;jz short ISNT_WRITE ; IF NOT, DO NOT ENFORCE ANY VALUES 3928 <1> ;or ah, ah ; CHECK FOR ANY WAIT? 3929 <1> ;jnz short DO_WAT ; IF THERE DO NOT ENFORCE 3930 00001CF2 741D <1> jz short HW_DONE 3931 00001CF4 B40F <1> mov ah, HD12_SETTLE ; LOAD 1.2M HEAD SETTLE MINIMUM 3932 00001CF6 8A87[B7610000] <1> mov al, [DSK_STATE+edi] ; LOAD STATE 3933 00001CFC 24C0 <1> and al, RATE_MSK ; KEEP ONLY RATE 3934 00001CFE 3C80 <1> cmp al, RATE_250 ; 1.2 M DRIVE ? 3935 00001D00 7502 <1> jnz short DO_WAT ; DEFAULT HEAD SETTLE LOADED 3936 <1> ;GP3: 3937 00001D02 B414 <1> mov ah, HD320_SETTLE ; USE 320/360 HEAD SETTLE 3938 <1> ; jmp short DO_WAT 3939 <1> 3940 <1> ;ISNT_WRITE: 3941 <1> ; or ah, ah ; CHECK FOR NO WAIT 3942 <1> ; jz short HW_DONE ; IF NOT WRITE AND 0 ITS OK 3943 <1> 3944 <1> ;----- AH CONTAINS NUMBER OF MILLISECONDS TO WAIT 3945 <1> DO_WAT: 3946 <1> ; mov al, ah ; AL = # MILLISECONDS 3947 <1> ; ;xor ah, ah ; AX = # MILLISECONDS 3948 <1> J29: ; 1 MILLISECOND LOOP 3949 <1> ;mov cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units. 3950 <1> ;mov ecx, 66 ; COUNT AT 15.085737 US PER COUNT 3951 <1> ; 08/07/2022 3952 00001D04 29C9 <1> sub ecx, ecx 3953 00001D06 B142 <1> mov cl, 66 3954 00001D08 E886F6FFFF <1> call WAITF ; DELAY FOR 1 MILLISECOND 3955 <1> ;dec al ; DECREMENT THE COUNT 3956 00001D0D FECC <1> dec ah 3957 00001D0F 75F3 <1> jnz short J29 ; DO AL MILLISECOND # OF TIMES 3958 <1> HW_DONE: 3959 00001D11 C3 <1> retn 3960 <1> 3961 <1> ;------------------------------------------------------------------------------- 3962 <1> ; NEC_OUTPUT 3963 <1> ; THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING 3964 <1> ; FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL 3965 <1> ; TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT 3966 <1> ; OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION. 3967 <1> ; 3968 <1> ; ON ENTRY: AH = BYTE TO BE OUTPUT 3969 <1> ; 3970 <1> ; ON EXIT: CY = 0 SUCCESS 3971 <1> ; CY = 1 FAILURE -- DISKETTE STATUS UPDATED 3972 <1> ; IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL 3973 <1> ; HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE 3974 <1> ; REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT. 3975 <1> ; 3976 <1> ; EAX, ECX, EDX DESTROYED 3977 <1> ;------------------------------------------------------------------------------- 3978 <1> 3979 <1> ; 09/12/2014 [Erdogan Tan] 3980 <1> ; (from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.) 3981 <1> ; Diskette Drive Controller Status Register (3F4h) 3982 <1> ; This read only register facilitates the transfer of data between 3983 <1> ; the system microprocessor and the controller. 3984 <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 3985 <1> ; with the system micrprocessor. 3986 <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0, 3987 <1> ; the transfer is to the controller. 3988 <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode. 3989 <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed. 3990 <1> ; Bit 3 - Reserved. 3991 <1> ; Bit 2 - Reserved. 3992 <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode. 3993 <1> ; Bit 0 - When this bit is set to 1, dskette drive 0 is in the seek mode. 3994 <1> 3995 <1> ; Data Register (3F5h) 3996 <1> ; This read/write register passes data, commands and parameters, and provides 3997 <1> ; diskette status information. 3998 <1> 3999 <1> NEC_OUTPUT: 4000 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4001 <1> ;push ebx ; SAVE REG. 4002 00001D12 BAF4030000 <1> mov edx, 03F4h ; STATUS PORT 4003 <1> ;xor ecx, ecx ; COUNT FOR TIME OUT 4004 <1> ; 16/12/2014 4005 <1> ; waiting for (max.) 0.5 seconds 4006 <1> ;;mov byte [wait_count], 0 ;; 27/02/2015 4007 <1> ; 4008 <1> ; 17/12/2014 4009 <1> ; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND 4010 <1> ; 4011 <1> ;WAIT_FOR_PORT: Waits for a bit at a port pointed to by DX to 4012 <1> ; go on. 4013 <1> ;INPUT: 4014 <1> ; AH=Mask for isolation bits. 4015 <1> ; AL=pattern to look for. 4016 <1> ; DX=Port to test for 4017 <1> ; ECX=Number of memory refresh periods to delay. 4018 <1> ; (normally 30 microseconds per period.) 4019 <1> ; 4020 <1> ;WFP_SHORT: 4021 <1> ; Wait for port if refresh cycle is short (15-80 Us range). 4022 <1> ; 4023 <1> 4024 00001D17 B91B410000 <1> mov ecx, WAIT_FDU_SEND_LH ; 16667 (27/02/2015) 4025 <1> ; 4026 <1> ;WFPS_OUTER_LP: 4027 <1> ; ; 4028 <1> ;WFPS_CHECK_PORT: 4029 <1> J23: 4030 00001D1C EC <1> in al, dx ; GET STATUS 4031 00001D1D 24C0 <1> and al, 11000000b ; KEEP STATUS AND DIRECTION 4032 00001D1F 3C80 <1> cmp al, 10000000b ; STATUS 1 AND DIRECTION 0 ? 4033 00001D21 7418 <1> jz short J27 ; STATUS AND DIRECTION OK 4034 <1> WFPS_HI: 4035 00001D23 E461 <1> in al, PORT_B ; 061h ; SYS1 ; wait for hi to lo 4036 00001D25 A810 <1> test al, 010h ; transition on memory 4037 00001D27 75FA <1> jnz short WFPS_HI ; refresh. 4038 <1> WFPS_LO: 4039 00001D29 E461 <1> in al, PORT_B ; SYS1 4040 00001D2B A810 <1> test al, 010h 4041 00001D2D 74FA <1> jz short WFPS_LO 4042 <1> ;loop short WFPS_CHECK_PORT 4043 00001D2F E2EB <1> loop J23 ; 27/02/2015 ; REPEAT TILL DELAY FINISHED 4044 <1> 4045 <1> ; fail 4046 <1> 4047 <1> ;WFPS_TIMEOUT: 4048 <1> 4049 <1> ;----- FALL THRU TO ERROR RETURN 4050 <1> 4051 00001D31 800D[AC610000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT 4052 <1> ;pop ebx ; RESTORE REG. 4053 00001D38 58 <1> pop eax ; 08/02/2015 ; DISCARD THE RETURN ADDRESS 4054 00001D39 F9 <1> stc ; INDICATE ERROR TO CALLER 4055 00001D3A C3 <1> retn 4056 <1> 4057 <1> ;----- DIRECTION AND STATUS OK; OUTPUT BYTE 4058 <1> 4059 <1> J27: 4060 00001D3B 88E0 <1> mov al, ah ; GET BYTE TO OUTPUT 4061 00001D3D 42 <1> inc edx ; DATA PORT = STATUS PORT + 1 4062 00001D3E EE <1> out dx, al ; OUTPUT THE BYTE 4063 <1> ;;NEWIODELAY ;; 27/02/2015 4064 <1> ; 27/02/2015 4065 00001D3F 9C <1> pushfd ; 24/12/2021 ; SAVE FLAGS 4066 <1> ;mov ecx, 3 ; 30 TO 45 MICROSECONDS WAIT FOR 4067 00001D40 29C9 <1> sub ecx, ecx 4068 00001D42 B103 <1> mov cl, 3 ; 24/12/2021 4069 00001D44 E84AF6FFFF <1> call WAITF ; NEC FLAGS UPDATE CYCLE 4070 00001D49 9D <1> popfd ; 24/12/2021 ; RESTORE FLAGS FOR EXIT 4071 <1> ;pop ebx ; RESTORE REG 4072 00001D4A C3 <1> retn ; CY = 0 FROM TEST INSTRUCTION 4073 <1> 4074 <1> ;------------------------------------------------------------------------------- 4075 <1> ; SEEK 4076 <1> ; THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED 4077 <1> ; TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE 4078 <1> ; RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED. 4079 <1> ; 4080 <1> ; ON ENTRY: EDI = DRIVE # 4081 <1> ; CH = TRACK # 4082 <1> ; 4083 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4084 <1> ; EAX, EBX, ECX, EDX DESTROYED 4085 <1> ;------------------------------------------------------------------------------- 4086 <1> SEEK: 4087 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4088 00001D4B 89FB <1> mov ebx, edi ; EBX = DRIVE # 4089 00001D4D B001 <1> mov al, 1 ; ESTABLISH MASK FOR RECALIBRATE TEST 4090 00001D4F 86CB <1> xchg cl, bl ; SET DRIVE VALUE INTO CL 4091 00001D51 D2C0 <1> rol al, cl ; SHIFT MASK BY THE DRIVE VALUE 4092 00001D53 86CB <1> xchg cl, bl ; RECOVER DRIVE VALUE 4093 00001D55 8405[A9610000] <1> test al, [SEEK_STATUS] ; TEST FOR RECALIBRATE REQUIRED 4094 00001D5B 7526 <1> jnz short J28A ; JUMP IF RECALIBRATE NOT REQUIRED 4095 <1> 4096 00001D5D 0805[A9610000] <1> or [SEEK_STATUS], al ; TURN ON THE NO RECALIBRATE BIT IN FLAG 4097 00001D63 E862000000 <1> call RECAL ; RECALIBRATE DRIVE 4098 00001D68 730E <1> jnc short AFT_RECAL ; RECALIBRATE DONE 4099 <1> 4100 <1> ;----- ISSUE RECALIBRATE FOR 80 TRACK DISKETTES 4101 <1> 4102 00001D6A C605[AC610000]00 <1> mov byte [DSKETTE_STATUS], 0 ; CLEAR OUT INVALID STATUS 4103 00001D71 E854000000 <1> call RECAL ; RECALIBRATE DRIVE 4104 00001D76 7251 <1> jc short RB ; IF RECALIBRATE FAILS TWICE THEN ERROR 4105 <1> 4106 <1> AFT_RECAL: 4107 00001D78 C687[B9610000]00 <1> mov byte [DSK_TRK+edi], 0 ; SAVE NEW CYLINDER AS PRESENT POSITION 4108 00001D7F 08ED <1> or ch, ch ; CHECK FOR SEEK TO TRACK 0 4109 00001D81 743F <1> jz short DO_WAIT ; HEAD SETTLE, CY = 0 IF JUMP 4110 <1> 4111 <1> ;----- DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK 4112 <1> 4113 00001D83 F687[B7610000]20 <1> J28A: test byte [DSK_STATE+edi], DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED 4114 00001D8A 7402 <1> jz short _R7 ; SINGLE STEP REQUIRED BYPASS DOUBLE 4115 00001D8C D0E5 <1> shl ch, 1 ; DOUBLE NUMBER OF STEP TO TAKE 4116 <1> 4117 00001D8E 3AAF[B9610000] <1> _R7: cmp ch, [DSK_TRK+edi] ; SEE IF ALREADY AT THE DESIRED TRACK 4118 00001D94 7433 <1> je short RB ; IF YES, DO NOT NEED TO SEEK 4119 <1> 4120 00001D96 BA[C91D0000] <1> mov edx, NEC_ERR ; LOAD RETURN ADDRESS 4121 00001D9B 52 <1> push edx ; (*) ; ON STACK FOR NEC OUTPUT ERROR 4122 00001D9C 88AF[B9610000] <1> mov [DSK_TRK+edi], ch ; SAVE NEW CYLINDER AS PRESENT POSITION 4123 00001DA2 B40F <1> mov ah, 0Fh ; SEEK COMMAND TO NEC 4124 00001DA4 E869FFFFFF <1> call NEC_OUTPUT 4125 00001DA9 89FB <1> mov ebx, edi ; EBX = DRIVE # 4126 00001DAB 88DC <1> mov ah, bl ; OUTPUT DRIVE NUMBER 4127 00001DAD E860FFFFFF <1> call NEC_OUTPUT 4128 00001DB2 8AA7[B9610000] <1> mov ah, [DSK_TRK+edi] ; GET CYLINDER NUMBER 4129 00001DB8 E855FFFFFF <1> call NEC_OUTPUT 4130 00001DBD E827000000 <1> call CHK_STAT_2 ; ENDING INTERRUPT AND SENSE STATUS 4131 <1> 4132 <1> ;----- WAIT FOR HEAD SETTLE 4133 <1> 4134 <1> DO_WAIT: 4135 00001DC2 9C <1> pushfd ; 24/12/2021 ; SAVE STATUS 4136 00001DC3 E818FFFFFF <1> call HD_WAIT ; WAIT FOR HEAD SETTLE TIME 4137 00001DC8 9D <1> popfd ; 24/12/2021 ; RESTORE STATUS 4138 <1> RB: 4139 <1> NEC_ERR: 4140 <1> ; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM) 4141 <1> ; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn 4142 00001DC9 C3 <1> retn ; RETURN TO CALLER 4143 <1> 4144 <1> ;------------------------------------------------------------------------------- 4145 <1> ; RECAL 4146 <1> ; RECALIBRATE DRIVE 4147 <1> ; 4148 <1> ; ON ENTRY: EDI = DRIVE # 4149 <1> ; 4150 <1> ; ON EXIT: CY REFLECTS STATUS OF OPERATION. 4151 <1> ;------------------------------------------------------------------------------- 4152 <1> RECAL: 4153 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4154 <1> ;push cx 4155 <1> ; 24/12/2021 4156 00001DCA 51 <1> push ecx 4157 00001DCB B8[E71D0000] <1> mov eax, RC_BACK ; LOAD NEC_OUTPUT ERROR 4158 00001DD0 50 <1> push eax 4159 00001DD1 B407 <1> mov ah, 07h ; RECALIBRATE COMMAND 4160 00001DD3 E83AFFFFFF <1> call NEC_OUTPUT 4161 00001DD8 89FB <1> mov ebx, edi ; EBX = DRIVE # 4162 00001DDA 88DC <1> mov ah, bl 4163 00001DDC E831FFFFFF <1> call NEC_OUTPUT ; OUTPUT THE DRIVE NUMBER 4164 00001DE1 E803000000 <1> call CHK_STAT_2 ; GET THE INTERRUPT AND SENSE INT STATUS 4165 00001DE6 58 <1> pop eax ; THROW AWAY ERROR 4166 <1> RC_BACK: 4167 <1> ;pop cx 4168 <1> ; 24/12/2021 4169 00001DE7 59 <1> pop ecx 4170 00001DE8 C3 <1> RETn 4171 <1> 4172 <1> ;------------------------------------------------------------------------------- 4173 <1> ; CHK_STAT_2 4174 <1> ; THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE, 4175 <1> ; OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE 4176 <1> ; INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER. 4177 <1> ; 4178 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4179 <1> ;------------------------------------------------------------------------------- 4180 <1> CHK_STAT_2: 4181 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4182 00001DE9 B8[111E0000] <1> mov eax, CS_BACK ; LOAD NEC_OUTPUT ERROR ADDRESS 4183 00001DEE 50 <1> push eax 4184 00001DEF E828000000 <1> call WAIT_INT ; WAIT FOR THE INTERRUPT 4185 00001DF4 721A <1> jc short J34 ; IF ERROR, RETURN IT 4186 00001DF6 B408 <1> mov ah, 08h ; SENSE INTERRUPT STATUS COMMAND 4187 00001DF8 E815FFFFFF <1> call NEC_OUTPUT 4188 00001DFD E849000000 <1> call RESULTS ; READ IN THE RESULTS 4189 00001E02 720C <1> jc short J34 4190 00001E04 A0[AD610000] <1> mov al, [NEC_STATUS] ; GET THE FIRST STATUS BYTE 4191 00001E09 2460 <1> and al, 01100000b ; ISOLATE THE BITS 4192 00001E0B 3C60 <1> cmp al, 01100000b ; TEST FOR CORRECT VALUE 4193 00001E0D 7403 <1> jz short J35 ; IF ERROR, GO MARK IT 4194 00001E0F F8 <1> clc ; GOOD RETURN 4195 <1> J34: 4196 00001E10 58 <1> pop eax ; THROW AWAY ERROR RETURN 4197 <1> CS_BACK: 4198 00001E11 C3 <1> retn 4199 <1> J35: 4200 00001E12 800D[AC610000]40 <1> or byte [DSKETTE_STATUS], BAD_SEEK 4201 00001E19 F9 <1> stc ; ERROR RETURN CODE 4202 00001E1A EBF4 <1> jmp short J34 4203 <1> 4204 <1> ;------------------------------------------------------------------------------- 4205 <1> ; WAIT_INT 4206 <1> ; THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE 4207 <1> ; TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED 4208 <1> ; IF THE DRIVE IS NOT READY. 4209 <1> ; 4210 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4211 <1> ;------------------------------------------------------------------------------- 4212 <1> 4213 <1> ; 17/12/2014 4214 <1> ; 2.5 seconds waiting ! 4215 <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI) 4216 <1> ; amount of time to wait for completion interrupt from NEC. 4217 <1> 4218 <1> WAIT_INT: 4219 <1> ; 12/07/2022 4220 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4221 00001E1C FB <1> sti ; TURN ON INTERRUPTS, JUST IN CASE 4222 <1> ; 12/07/2022 4223 <1> ;clc ; CLEAR TIMEOUT INDICATOR 4224 <1> ;mov bl, 10 ; CLEAR THE COUNTERS 4225 <1> ;xor cx, cx ; FOR 2 SECOND WAIT 4226 <1> 4227 <1> ; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT 4228 <1> ; 4229 <1> ;WAIT_FOR_MEM: 4230 <1> ; Waits for a bit at a specified memory location pointed 4231 <1> ; to by ES:[DI] to become set. 4232 <1> ;INPUT: 4233 <1> ; AH=Mask to test with. 4234 <1> ; ES:[DI] = memory location to watch. 4235 <1> ; BH:CX=Number of memory refresh periods to delay. 4236 <1> ; (normally 30 microseconds per period.) 4237 <1> 4238 <1> ; waiting for (max.) 2.5 secs in 30 micro units. 4239 <1> ; mov cx, WAIT_FDU_INT_LO ; 017798 4240 <1> ;; mov bl, WAIT_FDU_INT_HI 4241 <1> ; mov bl, WAIT_FDU_INT_HI + 1 4242 <1> ; 27/02/2015 4243 00001E1D B986450100 <1> mov ecx, WAIT_FDU_INT_LH ; 83334 (2.5 seconds) 4244 <1> WFMS_CHECK_MEM: 4245 00001E22 F605[A9610000]80 <1> test byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING 4246 00001E29 7516 <1> jnz short J37 4247 <1> WFMS_HI: 4248 00001E2B E461 <1> in al, PORT_B ; 061h ; SYS1, wait for lo to hi 4249 00001E2D A810 <1> test al, 010h ; transition on memory 4250 00001E2F 75FA <1> jnz short WFMS_HI ; refresh. 4251 <1> WFMS_LO: 4252 00001E31 E461 <1> in al, PORT_B ; SYS1 4253 00001E33 A810 <1> test al, 010h 4254 00001E35 74FA <1> jz short WFMS_LO 4255 00001E37 E2E9 <1> loop WFMS_CHECK_MEM 4256 <1> ;WFMS_OUTER_LP: 4257 <1> ;; or bl, bl ; check outer counter 4258 <1> ;; jz short J36A ; WFMS_TIMEOUT 4259 <1> ; dec bl 4260 <1> ; jz short J36A 4261 <1> ; jmp short WFMS_CHECK_MEM 4262 <1> 4263 <1> ;17/12/2014 4264 <1> ;16/12/2014 4265 <1> ; mov byte [wait_count], 0 ; Reset (INT 08H) counter 4266 <1> ;J36: 4267 <1> ; test byte [SEEK_STATUS], INT_FLAG ; TEST FOR INTERRUPT OCCURRING 4268 <1> ; jnz short J37 4269 <1> ;16/12/2014 4270 <1> ;loop J36 ; COUNT DOWN WHILE WAITING 4271 <1> ;dec bl ; SECOND LEVEL COUNTER 4272 <1> ;jnz short J36 4273 <1> ; cmp byte [wait_count], 46 ; (46/18.2 seconds) 4274 <1> ; jb short J36 4275 <1> 4276 <1> ;WFMS_TIMEOUT: 4277 <1> ;J36A: 4278 00001E39 800D[AC610000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED 4279 00001E40 F9 <1> stc ; ERROR RETURN 4280 <1> J37: 4281 00001E41 9C <1> pushf ; SAVE CURRENT CARRY 4282 00001E42 8025[A9610000]7F <1> and byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG 4283 00001E49 9D <1> popf ; RECOVER CARRY 4284 00001E4A C3 <1> retn ; GOOD RETURN CODE 4285 <1> 4286 <1> ;------------------------------------------------------------------------------- 4287 <1> ; RESULTS 4288 <1> ; THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 4289 <1> ; FOLLOWING AN INTERRUPT. 4290 <1> ; 4291 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 4292 <1> ; EAX, EBX, ECX, EDX DESTROYED 4293 <1> ;------------------------------------------------------------------------------- 4294 <1> RESULTS: 4295 <1> ; 12/07/2022 4296 <1> ; 11/07/2022 4297 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4298 00001E4B 57 <1> push edi 4299 00001E4C BF[AD610000] <1> mov edi, NEC_STATUS ; POINTER TO DATA AREA 4300 00001E51 B307 <1> mov bl, 7 ; MAX STATUS BYTES 4301 00001E53 66BAF403 <1> mov dx, 03F4h ; STATUS PORT 4302 <1> 4303 <1> ;----- WAIT FOR REQUEST FOR MASTER 4304 <1> 4305 <1> _R10: 4306 <1> ; 16/12/2014 4307 <1> ; wait for (max) 0.5 seconds 4308 <1> ;mov bh, 2 ; HIGH ORDER COUNTER 4309 <1> ;xor cx, cx ; COUNTER 4310 <1> 4311 <1> ;Time to wait while waiting for each byte of NEC results = .5 4312 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 4313 <1> ; 27/02/2015 4314 <1> 4315 00001E57 B91B410000 <1> mov ecx, WAIT_FDU_RESULTS_LH ; 16667 4316 <1> ;mov cx, WAIT_FDU_RESULTS_LO ; 16667 4317 <1> ;mov bh, WAIT_FDU_RESULTS_HI+1 ; 0+1 4318 <1> 4319 <1> WFPSR_OUTER_LP: 4320 <1> ; 4321 <1> WFPSR_CHECK_PORT: 4322 <1> J39: ; WAIT FOR MASTER 4323 00001E5C EC <1> in al, dx ; GET STATUS 4324 00001E5D 24C0 <1> and al, 11000000b ; KEEP ONLY STATUS AND DIRECTION 4325 00001E5F 3CC0 <1> cmp al, 11000000b ; STATUS 1 AND DIRECTION 1 ? 4326 00001E61 7418 <1> jz short J42 ; STATUS AND DIRECTION OK 4327 <1> WFPSR_HI: 4328 00001E63 E461 <1> in al, PORT_B ;061h ; SYS1 ; wait for hi to lo 4329 00001E65 A810 <1> test al, 010h ; transition on memory 4330 00001E67 75FA <1> jnz short WFPSR_HI ; refresh. 4331 <1> WFPSR_LO: 4332 00001E69 E461 <1> in al, PORT_B ; SYS1 4333 00001E6B A810 <1> test al, 010h 4334 00001E6D 74FA <1> jz short WFPSR_LO 4335 00001E6F E2EB <1> loop WFPSR_CHECK_PORT 4336 <1> 4337 <1> ;; 27/02/2015 4338 <1> ;;dec bh 4339 <1> ;;jnz short WFPSR_OUTER_LP 4340 <1> ;jmp short WFPSR_TIMEOUT ; fail 4341 <1> 4342 <1> ;;mov byte [wait_count], 0 4343 <1> ;J39: ; WAIT FOR MASTER 4344 <1> ; in al, dx ; GET STATUS 4345 <1> ; and al, 11000000b ; KEEP ONLY STATUS AND DIRECTION 4346 <1> ; cmp al, 11000000b ; STATUS 1 AND DIRECTION 1 ? 4347 <1> ; jz short J42 ; STATUS AND DIRECTION OK 4348 <1> ;loop J39 ; LOOP TILL TIMEOUT 4349 <1> ;dec bh ; DECREMENT HIGH ORDER COUNTER 4350 <1> ;jnz short J39 ; REPEAT TILL DELAY DONE 4351 <1> ; 4352 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 4353 <1> ;;jb short J39 4354 <1> 4355 <1> ;WFPSR_TIMEOUT: 4356 00001E71 800D[AC610000]80 <1> or byte [DSKETTE_STATUS], TIME_OUT 4357 00001E78 F9 <1> stc ; SET ERROR RETURN 4358 00001E79 EB26 <1> jmp short POPRES ; POP REGISTERS AND RETURN 4359 <1> 4360 <1> ;----- READ IN THE STATUS 4361 <1> 4362 <1> J42: 4363 00001E7B EB00 <1> JMP $+2 ; I/O DELAY 4364 <1> ;inc dx ; POINT AT DATA PORT 4365 00001E7D FEC2 <1> inc dl 4366 00001E7F EC <1> in al, dx ; GET THE DATA 4367 <1> ; 16/12/2014 4368 <1> NEWIODELAY 2196 00001E80 E6EB <2> out 0EBh,al 4369 <1> 4370 <1> ;mov [edi], al ; STORE THE BYTE 4371 <1> ;inc edi ; INCREMENT THE POINTER 4372 <1> ; 11/07/2022 4373 00001E82 AA <1> stosb 4374 <1> 4375 <1> ; 16/12/2014 4376 <1> ; push cx 4377 <1> ; mov cx, 30 4378 <1> ;wdw2: 4379 <1> ; NEWIODELAY 4380 <1> ; loop wdw2 4381 <1> ; pop cx 4382 <1> 4383 <1> ;mov ecx,3 ; MINIMUM 24 MICROSECONDS FOR NEC 4384 <1> ; 12/07/2022 4385 00001E83 29C9 <1> sub ecx, ecx 4386 00001E85 B103 <1> mov cl, 3 4387 00001E87 E807F5FFFF <1> call WAITF ; WAIT 30 TO 45 MICROSECONDS 4388 <1> ;dec dx ; POINT AT STATUS PORT 4389 00001E8C FECA <1> dec dl 4390 00001E8E EC <1> in al, dx ; GET STATUS 4391 <1> ; 16/12/2014 4392 <1> NEWIODELAY 2196 00001E8F E6EB <2> out 0EBh,al 4393 <1> ; 4394 00001E91 A810 <1> test al, 00010000b ; TEST FOR NEC STILL BUSY 4395 00001E93 740C <1> jz short POPRES ; RESULTS DONE ? 4396 <1> 4397 00001E95 FECB <1> dec bl ; DECREMENT THE STATUS COUNTER 4398 00001E97 75BE <1> jnz short _R10 ; GO BACK FOR MORE 4399 00001E99 800D[AC610000]20 <1> or byte [DSKETTE_STATUS], BAD_NEC ; TOO MANY STATUS BYTES 4400 00001EA0 F9 <1> stc ; SET ERROR FLAG 4401 <1> 4402 <1> ;----- RESULT OPERATION IS DONE 4403 <1> POPRES: 4404 00001EA1 5F <1> pop edi 4405 00001EA2 C3 <1> retn ; RETURN WITH CARRY SET 4406 <1> 4407 <1> ;------------------------------------------------------------------------------- 4408 <1> ; READ_DSKCHNG 4409 <1> ; READS THE STATE OF THE DISK CHANGE LINE. 4410 <1> ; 4411 <1> ; ON ENTRY: EDI = DRIVE # 4412 <1> ; 4413 <1> ; ON EXIT: EDI = DRIVE # 4414 <1> ; ZF = 0 : DISK CHANGE LINE INACTIVE 4415 <1> ; ZF = 1 : DISK CHANGE LINE ACTIVE 4416 <1> ; EAX, ECX, EDX DESTROYED 4417 <1> ;------------------------------------------------------------------------------- 4418 <1> READ_DSKCHNG: 4419 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4420 00001EA3 E8B4FDFFFF <1> call MOTOR_ON ; TURN ON THE MOTOR IF OFF 4421 00001EA8 66BAF703 <1> mov dx, 03F7h ; ADDRESS DIGITAL INPUT REGISTER 4422 00001EAC EC <1> in al, dx ; INPUT DIGITAL INPUT REGISTER 4423 00001EAD A880 <1> test al, DSK_CHG ; CHECK FOR DISK CHANGE LINE ACTIVE 4424 00001EAF C3 <1> retn ; RETURN TO CALLER WITH ZERO FLAG SET 4425 <1> 4426 <1> fdc_int: 4427 <1> ; 30/07/2015 4428 <1> ; 16/02/2015 4429 <1> ;int_0Eh: ; 11/12/2014 4430 <1> 4431 <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL 6 ) -------------------------------------- 4432 <1> ; DISK_INT 4433 <1> ; THIS ROUTINE HANDLES THE DISKETTE INTERRUPT. 4434 <1> ; 4435 <1> ; ON EXIT: THE INTERRUPT FLAG IS SET IN @SEEK_STATUS. 4436 <1> ;------------------------------------------------------------------------------- 4437 <1> DISK_INT_1: 4438 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4439 <1> ;push eax ; SAVE WORK REGISTER 4440 <1> ; 24/12/2021 4441 00001EB0 50 <1> push eax 4442 00001EB1 1E <1> push ds 4443 00001EB2 66B81000 <1> mov ax, KDATA 4444 00001EB6 8ED8 <1> mov ds, ax 4445 00001EB8 800D[A9610000]80 <1> or byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED 4446 00001EBF B020 <1> mov al, EOI ; END OF INTERRUPT MARKER 4447 00001EC1 E620 <1> out INTA00, al ; INTERRUPT CONTROL PORT 4448 00001EC3 1F <1> pop ds 4449 <1> ;pop ax ; RECOVER REGISTER 4450 <1> ; 24/12/2021 4451 00001EC4 58 <1> pop eax 4452 00001EC5 CF <1> iretd ; RETURN FROM INTERRUPT 4453 <1> 4454 <1> ;------------------------------------------------------------------------------- 4455 <1> ; DSKETTE_SETUP 4456 <1> ; THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF 4457 <1> ; DISKETTE DRIVES ARE ATTACH TO THE SYSTEM. 4458 <1> ;------------------------------------------------------------------------------- 4459 <1> DSKETTE_SETUP: 4460 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4461 <1> ;push eax ; SAVE REGISTERS 4462 <1> ;push ebx 4463 <1> ;push ecx 4464 00001EC6 52 <1> push edx 4465 <1> ;push edi 4466 <1> ; 14/12/2014 4467 <1> ;mov dword [DISK_POINTER], MD_TBL6 4468 <1> ; 4469 <1> ;or byte [RTC_WAIT_FLAG], 1 ; NO RTC WAIT, FORCE USE OF LOOP 4470 <1> 4471 00001EC7 31FF <1> xor edi, edi ; INITIALIZE DRIVE POINTER 4472 00001EC9 29C9 <1> sub ecx, ecx 4473 00001ECB 66890D[B7610000] <1> mov [DSK_STATE], cx ; 0 ; INITIALIZE STATES 4474 <1> ; 08/07/2022 4475 <1> ;and byte [LASTRATE], ~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND 4476 00001ED2 800D[B4610000]C0 <1> or byte [LASTRATE], SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE 4477 00001ED9 880D[A9610000] <1> mov [SEEK_STATUS], cl ; 0 ; INDICATE RECALIBRATE NEEDED 4478 00001EDF 880D[AB610000] <1> mov [MOTOR_COUNT], cl ; 0 ; INITIALIZE MOTOR COUNT 4479 00001EE5 880D[AA610000] <1> mov [MOTOR_STATUS], cl ; 0 ; INITIALIZE DRIVES TO OFF STATE 4480 00001EEB 880D[AC610000] <1> mov [DSKETTE_STATUS], cl ; 0 ; NO ERRORS 4481 <1> ; 4482 <1> ; 28/02/2015 4483 <1> ;mov word [cfd], 100h 4484 00001EF1 E894F8FFFF <1> call DSK_RESET 4485 00001EF6 5A <1> pop edx 4486 00001EF7 C3 <1> retn 4487 <1> 4488 <1> ;////////////////////////////////////////////////////// 4489 <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 4490 <1> ; 4491 <1> 4492 <1> ; 12/07/2022 4493 <1> ;int13h: ; 21/02/2015 4494 <1> ; pushfd 4495 <1> ; push cs 4496 <1> ; call DISK_IO 4497 <1> ; retn 4498 <1> 4499 <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;; 4500 <1> ;///////////////////////////////////////////////////////////////////// 4501 <1> 4502 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4503 <1> ; ((Direct call instead of int 13h simulation)) 4504 <1> ; 4505 <1> ; Function in AL 4506 <1> ; 0 = reset 4507 <1> ; 1 = read 4508 <1> ; 2 = write 4509 <1> ; Disk drive number in DL 4510 <1> ; 0 & 1 = floppy disks 4511 <1> ; 80h .. 83h = hard disks 4512 <1> ; Sector address (LBA) in ECX 4513 <1> ; Buffer address in EBX 4514 <1> ; R/W sector count is (always) 1 4515 <1> ; 4516 <1> ; Return: 4517 <1> ; Status in AH (>0 = error code) 4518 <1> ; if CF = 1 -> error code in AH 4519 <1> ; if CF = 0 -> successful 4520 <1> ; AL = undefined 4521 <1> ; 4522 <1> ; Modified registers: (only) EAX 4523 <1> 4524 <1> ; 10/07/2022 4525 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4526 <1> 4527 <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project) 4528 <1> ; 23/02/2015 4529 <1> ; 21/02/2015 (unix386.s) 4530 <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s) 4531 <1> ; 4532 <1> ; Original Source Code: 4533 <1> ; DISK ----- 09/25/85 FIXED DISK BIOS 4534 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 4535 <1> ; 4536 <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 4537 <1> ; Source Code - ATORGS.ASM, AHDSK.ASM 4538 <1> ; 4539 <1> 4540 <1> ;The wait for controller to be not busy is 10 seconds. 4541 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 4542 <1> ;;WAIT_HDU_CTLR_BUSY_LO equ 1615h 4543 <1> ;;WAIT_HDU_CTLR_BUSY_HI equ 05h 4544 <1> WAIT_HDU_CTRL_BUSY_LH equ 51615h ;21/02/2015 4545 <1> 4546 <1> ;The wait for controller to issue completion interrupt is 10 seconds. 4547 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 4548 <1> ;;WAIT_HDU_INT_LO equ 1615h 4549 <1> ;;WAIT_HDU_INT_HI equ 05h 4550 <1> WAIT_HDU_INT_LH equ 51615h ; 21/02/2015 4551 <1> 4552 <1> ;The wait for Data request on read and write longs is 4553 <1> ;2000 us. (?) 4554 <1> ;;WAIT_HDU_DRQ_LO equ 1000 ; 03E8h 4555 <1> ;;WAIT_HDU_DRQ_HI equ 0 4556 <1> WAIT_HDU_DRQ_LH equ 1000 ; 21/02/2015 4557 <1> 4558 <1> ; Port 61h (PORT_B) 4559 <1> SYS1 equ 61h ; PORT_B (diskette.inc) 4560 <1> 4561 <1> ; 23/12/2014 4562 <1> %define CMD_BLOCK ebp-8 ; 21/02/2015 4563 <1> 4564 <1> ; 11/07/2022 4565 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4566 <1> 4567 <1> ;--- INT 13H ------------------------------------------------------------------- 4568 <1> ; : 4569 <1> ; FIXED DISK I/O INTERFACE : 4570 <1> ; : 4571 <1> ; THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH : 4572 <1> ; THE IBM FIXED DISK CONTROLLER. : 4573 <1> ; : 4574 <1> ; THE BIOS ROUTINES ARE MEANT TO BE ACCESSED THROUGH : 4575 <1> ; SOFTWARE INTERRUPTS ONLY. ANY ADDRESSES PRESENT IN : 4576 <1> ; THESE LISTINGS ARE INCLUDED ONLY FOR COMPLETENESS, : 4577 <1> ; NOT FOR REFERENCE. APPLICATIONS WHICH REFERENCE ANY : 4578 <1> ; ABSOLUTE ADDRESSES WITHIN THE CODE SEGMENTS OF BIOS : 4579 <1> ; VIOLATE THE STRUCTURE AND DESIGN OF BIOS. : 4580 <1> ; : 4581 <1> ;------------------------------------------------------------------------------: 4582 <1> ; : 4583 <1> ; INPUT (AH)= HEX COMMAND VALUE : 4584 <1> ; : 4585 <1> ; (AH)= 00H RESET DISK (DL = 80H,81H) / DISKETTE : 4586 <1> ; (AH)= 01H READ THE DESIRED SECTORS INTO MEMORY : 4587 <1> ; (AH)= 02H WRITE THE DESIRED SECTORS FROM MEMORY : 4588 <1> ; : 4589 <1> ;------------------------------------------------------------------------------: 4590 <1> ; : 4591 <1> ; REGISTERS USED FOR FIXED DISK OPERATIONS : 4592 <1> ; : 4593 <1> ; (DL) - DRIVE NUMBER (80H-81H FOR DISK. VALUE CHECKED) : 4594 <1> ; (DH) - HEAD NUMBER (0-15 ALLOWED, NOT VALUE CHECKED) : 4595 <1> ; (CH) - CYLINDER NUMBER (0-1023, NOT VALUE CHECKED)(SEE CL): 4596 <1> ; (CL) - SECTOR NUMBER (1-17, NOT VALUE CHECKED) : 4597 <1> ; : 4598 <1> ; NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED : 4599 <1> ; IN THE HIGH 2 BITS OF THE CL REGISTER : 4600 <1> ; (10 BITS TOTAL) : 4601 <1> ; : 4602 <1> ; (AL) - NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H, : 4603 <1> ; FOR READ/WRITE LONG 1-79H) : 4604 <1> ; : 4605 <1> ; (EBX) - ADDRESS OF BUFFER FOR READS AND WRITES, : 4606 <1> ; (NOT REQUIRED FOR VERIFY) : 4607 <1> ; : 4608 <1> ;------------------------------------------------------------------------------: 4609 <1> ; OUTPUT : 4610 <1> ; AH = STATUS OF CURRENT OPERATION : 4611 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES BELOW : 4612 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) : 4613 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) : 4614 <1> ; : 4615 <1> ; NOTE: ERROR 11H INDICATES THAT THE DATA READ HAD A RECOVERABLE : 4616 <1> ; ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM. THE DATA : 4617 <1> ; IS PROBABLY GOOD, HOWEVER THE BIOS ROUTINE INDICATES AN : 4618 <1> ; ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE : 4619 <1> ; FOR ITSELF. THE ERROR MAY NOT RECUR IF THE DATA IS : 4620 <1> ; REWRITTEN. : 4621 <1> ; : 4622 <1> ; IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), : 4623 <1> ; INPUT: : 4624 <1> ; (DL) = DRIVE NUMBER : 4625 <1> ; OUTPUT: : 4626 <1> ; (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2) : 4627 <1> ; (CONTROLLER CARD ZERO TALLY ONLY) : 4628 <1> ; (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER : 4629 <1> ; (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER : 4630 <1> ; (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER : 4631 <1> ; AND CYLINDER NUMBER HIGH BITS : 4632 <1> ; : 4633 <1> ; REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN : 4634 <1> ; INFORMATION. : 4635 <1> ; : 4636 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE : 4637 <1> ; ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION. : 4638 <1> ; : 4639 <1> ;------------------------------------------------------------------------------- 4640 <1> 4641 <1> SENSE_FAIL EQU 0FFH ; NOT IMPLEMENTED 4642 <1> NO_ERR EQU 0E0H ; STATUS ERROR/ERROR REGISTER=0 4643 <1> WRITE_FAULT EQU 0CCH ; WRITE FAULT ON SELECTED DRIVE 4644 <1> UNDEF_ERR EQU 0BBH ; UNDEFINED ERROR OCCURRED 4645 <1> NOT_RDY EQU 0AAH ; DRIVE NOT READY 4646 <1> TIME_OUT EQU 80H ; ATTACHMENT FAILED TO RESPOND 4647 <1> BAD_SEEK EQU 40H ; SEEK OPERATION FAILED 4648 <1> BAD_CNTLR EQU 20H ; CONTROLLER HAS FAILED 4649 <1> DATA_CORRECTED EQU 11H ; ECC CORRECTED DATA ERROR 4650 <1> BAD_ECC EQU 10H ; BAD ECC ON DISK READ 4651 <1> BAD_TRACK EQU 0BH ; NOT IMPLEMENTED 4652 <1> BAD_SECTOR EQU 0AH ; BAD SECTOR FLAG DETECTED 4653 <1> ;DMA_BOUNDARY EQU 09H ; DATA EXTENDS TOO FAR 4654 <1> INIT_FAIL EQU 07H ; DRIVE PARAMETER ACTIVITY FAILED 4655 <1> BAD_RESET EQU 05H ; RESET FAILED 4656 <1> ;RECORD_NOT_FND EQU 04H ; REQUESTED SECTOR NOT FOUND 4657 <1> ;BAD_ADDR_MARK EQU 02H ; ADDRESS MARK NOT FOUND 4658 <1> ;BAD_CMD EQU 01H ; BAD COMMAND PASSED TO DISK I/O 4659 <1> 4660 <1> ;-------------------------------------------------------- 4661 <1> ; : 4662 <1> ; FIXED DISK PARAMETER TABLE : 4663 <1> ; - THE TABLE IS COMPOSED OF A BLOCK DEFINED AS: : 4664 <1> ; : 4665 <1> ; +0 (1 WORD) - MAXIMUM NUMBER OF CYLINDERS : 4666 <1> ; +2 (1 BYTE) - MAXIMUM NUMBER OF HEADS : 4667 <1> ; +3 (1 WORD) - NOT USED/SEE PC-XT : 4668 <1> ; +5 (1 WORD) - STARTING WRITE PRECOMPENSATION CYL : 4669 <1> ; +7 (1 BYTE) - MAXIMUM ECC DATA BURST LENGTH : 4670 <1> ; +8 (1 BYTE) - CONTROL BYTE : 4671 <1> ; BIT 7 DISABLE RETRIES -OR- : 4672 <1> ; BIT 6 DISABLE RETRIES : 4673 <1> ; BIT 3 MORE THAN 8 HEADS : 4674 <1> ; +9 (3 BYTES)- NOT USED/SEE PC-XT : 4675 <1> ; +12 (1 WORD) - LANDING ZONE : 4676 <1> ; +14 (1 BYTE) - NUMBER OF SECTORS/TRACK : 4677 <1> ; +15 (1 BYTE) - RESERVED FOR FUTURE USE : 4678 <1> ; : 4679 <1> ; - TO DYNAMICALLY DEFINE A SET OF PARAMETERS : 4680 <1> ; BUILD A TABLE FOR UP TO 15 TYPES AND PLACE : 4681 <1> ; THE CORRESPONDING VECTOR INTO INTERRUPT 41 : 4682 <1> ; FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1. : 4683 <1> ; : 4684 <1> ;-------------------------------------------------------- 4685 <1> 4686 <1> ;-------------------------------------------------------- 4687 <1> ; : 4688 <1> ; HARDWARE SPECIFIC VALUES : 4689 <1> ; : 4690 <1> ; - CONTROLLER I/O PORT : 4691 <1> ; : 4692 <1> ; > WHEN READ FROM: : 4693 <1> ; HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU) : 4694 <1> ; HF_PORT+1 - GET ERROR REGISTER : 4695 <1> ; HF_PORT+2 - GET SECTOR COUNT : 4696 <1> ; HF_PORT+3 - GET SECTOR NUMBER : 4697 <1> ; HF_PORT+4 - GET CYLINDER LOW : 4698 <1> ; HF_PORT+5 - GET CYLINDER HIGH (2 BITS) : 4699 <1> ; HF_PORT+6 - GET SIZE/DRIVE/HEAD : 4700 <1> ; HF_PORT+7 - GET STATUS REGISTER : 4701 <1> ; : 4702 <1> ; > WHEN WRITTEN TO: : 4703 <1> ; HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) : 4704 <1> ; HF_PORT+1 - SET PRECOMPENSATION CYLINDER : 4705 <1> ; HF_PORT+2 - SET SECTOR COUNT : 4706 <1> ; HF_PORT+3 - SET SECTOR NUMBER : 4707 <1> ; HF_PORT+4 - SET CYLINDER LOW : 4708 <1> ; HF_PORT+5 - SET CYLINDER HIGH (2 BITS) : 4709 <1> ; HF_PORT+6 - SET SIZE/DRIVE/HEAD : 4710 <1> ; HF_PORT+7 - SET COMMAND REGISTER : 4711 <1> ; : 4712 <1> ;-------------------------------------------------------- 4713 <1> 4714 <1> ;HF_PORT EQU 01F0H ; DISK PORT 4715 <1> ;HF1_PORT equ 0170h 4716 <1> ;HF_REG_PORT EQU 03F6H 4717 <1> ;HF1_REG_PORT equ 0376h 4718 <1> 4719 <1> HDC1_BASEPORT equ 1F0h 4720 <1> HDC2_BASEPORT equ 170h 4721 <1> 4722 <1> align 2 4723 <1> 4724 <1> ;----- STATUS REGISTER 4725 <1> 4726 <1> ST_ERROR EQU 00000001B ; 4727 <1> ST_INDEX EQU 00000010B ; 4728 <1> ST_CORRCTD EQU 00000100B ; ECC CORRECTION SUCCESSFUL 4729 <1> ST_DRQ EQU 00001000B ; 4730 <1> ST_SEEK_COMPL EQU 00010000B ; SEEK COMPLETE 4731 <1> ST_WRT_FLT EQU 00100000B ; WRITE FAULT 4732 <1> ST_READY EQU 01000000B ; 4733 <1> ST_BUSY EQU 10000000B ; 4734 <1> 4735 <1> ;----- ERROR REGISTER 4736 <1> 4737 <1> ERR_DAM EQU 00000001B ; DATA ADDRESS MARK NOT FOUND 4738 <1> ERR_TRK_0 EQU 00000010B ; TRACK 0 NOT FOUND ON RECAL 4739 <1> ERR_ABORT EQU 00000100B ; ABORTED COMMAND 4740 <1> ; EQU 00001000B ; NOT USED 4741 <1> ERR_ID EQU 00010000B ; ID NOT FOUND 4742 <1> ; EQU 00100000B ; NOT USED 4743 <1> ERR_DATA_ECC EQU 01000000B 4744 <1> ERR_BAD_BLOCK EQU 10000000B 4745 <1> 4746 <1> 4747 <1> RECAL_CMD EQU 00010000B ; DRIVE RECAL (10H) 4748 <1> READ_CMD EQU 00100000B ; READ (20H) 4749 <1> WRITE_CMD EQU 00110000B ; WRITE (30H) 4750 <1> VERIFY_CMD EQU 01000000B ; VERIFY (40H) 4751 <1> FMTTRK_CMD EQU 01010000B ; FORMAT TRACK (50H) 4752 <1> INIT_CMD EQU 01100000B ; INITIALIZE (60H) 4753 <1> SEEK_CMD EQU 01110000B ; SEEK (70H) 4754 <1> DIAG_CMD EQU 10010000B ; DIAGNOSTIC (90H) 4755 <1> SET_PARM_CMD EQU 10010001B ; DRIVE PARMS (91H) 4756 <1> NO_RETRIES EQU 00000001B ; CHD MODIFIER (01H) 4757 <1> ECC_MODE EQU 00000010B ; CMD MODIFIER (02H) 4758 <1> BUFFER_MODE EQU 00001000B ; CMD MODIFIER (08H) 4759 <1> 4760 <1> ;MAX_FILE EQU 2 4761 <1> ;S_MAX_FILE EQU 2 4762 <1> MAX_FILE equ 4 ; 22/12/2014 4763 <1> S_MAX_FILE equ 4 ; 22/12/2014 4764 <1> 4765 <1> DELAY_1 EQU 25H ; DELAY FOR OPERATION COMPLETE 4766 <1> DELAY_2 EQU 0600H ; DELAY FOR READY 4767 <1> DELAY_3 EQU 0100H ; DELAY FOR DATA REQUEST 4768 <1> 4769 <1> HF_FAIL EQU 08H ; CMOS FLAG IN BYTE 0EH 4770 <1> 4771 <1> ;----- COMMAND BLOCK REFERENCE 4772 <1> 4773 <1> ;CMD_BLOCK EQU BP-8 ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS 4774 <1> ; (BP) POINTS TO COMMAND BLOCK TAIL 4775 <1> ; AS DEFINED BY THE "ENTER" PARMS 4776 <1> ; 19/12/2014 4777 <1> ORG_VECTOR equ 4*13h ; INT 13h vector 4778 <1> DISK_VECTOR equ 4*40h ; INT 40h vector (for floppy disks) 4779 <1> ;HDISK_INT equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 4780 <1> ;HDISK_INT1 equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 4781 <1> ;HDISK_INT2 equ 4*77h ; Secondary HDC - Hardware interrupt (IRQ15) 4782 <1> ;HF_TBL_VEC equ 4*41h ; Pointer to 1st fixed disk parameter table 4783 <1> ;HF1_TBL_VEC equ 4*46h ; Pointer to 2nd fixed disk parameter table 4784 <1> 4785 <1> align 2 4786 <1> 4787 <1> ;---------------------------------------------------------------- 4788 <1> ; FIXED DISK I/O SETUP : 4789 <1> ; : 4790 <1> ; - ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK : 4791 <1> ; - PERFORM POWER ON DIAGNOSTICS : 4792 <1> ; SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED : 4793 <1> ; : 4794 <1> ;---------------------------------------------------------------- 4795 <1> 4796 <1> ; 12/07/2022 4797 <1> ; 11/07/2022 4798 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4799 <1> 4800 <1> DISK_SETUP: 4801 <1> ;cli 4802 <1> ;;mov ax, ABS0 ; GET ABSOLUTE SEGMENT 4803 <1> ;xor ax, ax 4804 <1> ;mov ds, ax ; SET SEGMENT REGISTER 4805 <1> ;mov ax, [ORG_VECTOR] ; GET DISKETTE VECTOR 4806 <1> ;mov [DISK_VECTOR], ax ; INTO INT 40H 4807 <1> ;mov ax, [ORG_VECTOR+2] 4808 <1> ;mov [DISK_VECTOR+2], ax 4809 <1> ;mov word [ORG_VECTOR], DISK_IO ; FIXED DISK HANDLER 4810 <1> ;mov [ORG_VECTOR+2], cs 4811 <1> ; 1st controller (primary master, slave) - IRQ 14 4812 <1> ;;mov word [HDISK_INT], HD_INT ; FIXED DISK INTERRUPT 4813 <1> ;mov word [HDISK_INT1], HD_INT ; 4814 <1> ;;mov [HDISK_INT+2], cs 4815 <1> ;mov [HDISK_INT1+2], cs 4816 <1> ; 2nd controller (secondary master, slave) - IRQ 15 4817 <1> ;mov word [HDISK_INT2], HD1_INT ; 4818 <1> ;mov [HDISK_INT2+2], cs 4819 <1> ; 4820 <1> ;;mov word [HF_TBL_VEC], HD0_DPT ; PARM TABLE DRIVE 80 4821 <1> ;;mov word [HF_TBL_VEC+2], DPT_SEGM 4822 <1> ;;mov word [HF1_TBL_VEC], HD1_DPT ; PARM TABLE DRIVE 81 4823 <1> ;;mov word [HF1_TBL_VEC+2], DPT_SEGM 4824 <1> ;push cs 4825 <1> ;pop ds 4826 <1> ;mov word [HDPM_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80h 4827 <1> ;mov word [HDPM_TBL_VEC+2],DPT_SEGM 4828 00001EF8 C705[C0610000]0000- <1> mov dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT 4828 00001F00 0900 <1> 4829 <1> ;mov word [HDPS_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81h 4830 <1> ;mov word [HDPS_TBL_VEC+2],DPT_SEGM 4831 00001F02 C705[C4610000]2000- <1> mov dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT 4831 00001F0A 0900 <1> 4832 <1> ;mov word [HDSM_TBL_VEC],HD2_DPT ; PARM TABLE DRIVE 82h 4833 <1> ;mov word [HDSM_TBL_VEC+2],DPT_SEGM 4834 00001F0C C705[C8610000]4000- <1> mov dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT 4834 00001F14 0900 <1> 4835 <1> ;mov word [HDSS_TBL_VEC],HD3_DPT ; PARM TABLE DRIVE 83h 4836 <1> ;mov word [HDSS_TBL_VEC+2],DPT_SEGM 4837 00001F16 C705[CC610000]6000- <1> mov dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT 4837 00001F1E 0900 <1> 4838 <1> ; 4839 <1> ;;in al, INTB01 ; TURN ON SECOND INTERRUPT CHIP 4840 <1> ;;;and al, 0BFh 4841 <1> ;;and al, 3Fh ; enable IRQ 14 and IRQ 15 4842 <1> ;;;JMP $+2 4843 <1> ;;IODELAY 4844 <1> ;;out INTB01, al 4845 <1> ;;IODELAY 4846 <1> ;;in al, INTA01 ; LET INTERRUPTS PASS THRU TO 4847 <1> ;;and al, 0FBh ; SECOND CHIP 4848 <1> ;;;JMP $+2 4849 <1> ;;IODELAY 4850 <1> ;;out INTA01, al 4851 <1> ; 4852 <1> ;sti 4853 <1> ;;push ds ; MOVE ABS0 POINTER TO 4854 <1> ;;pop es ; EXTRA SEGMENT POINTER 4855 <1> ;;;call DDS ; ESTABLISH DATA SEGMENT 4856 <1> ;;mov byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 4857 <1> ;;mov byte [HF_NUM],0 ; ZERO NUMBER OF FIXED DISKS 4858 <1> ;;mov byte [CONTROL_BYTE],0 4859 <1> ;;mov byte [PORT_OFF],0 ; ZERO CARD OFFSET 4860 <1> ; 20/12/2014 - private code by Erdogan Tan 4861 <1> ; (out of original PC-AT, PC-XT BIOS code) 4862 <1> ;mov si, hd0_type 4863 00001F20 BE[4E5C0000] <1> mov esi, hd0_type 4864 <1> ;;mov cx, 4 4865 <1> ;mov ecx, 4 4866 <1> ; 11/07/2022 4867 00001F25 29C9 <1> sub ecx, ecx 4868 00001F27 B104 <1> mov cl, 4 4869 <1> hde_l: 4870 00001F29 AC <1> lodsb 4871 00001F2A 3C80 <1> cmp al, 80h ; 8?h = existing 4872 00001F2C 7206 <1> jb short _L4 4873 00001F2E FE05[BC610000] <1> inc byte [HF_NUM] ; + 1 hard (fixed) disk drives 4874 <1> _L4: ; 26/02/2015 4875 00001F34 E2F3 <1> loop hde_l 4876 <1> ;_L4: ; 0 <= [HF_NUM] =< 4 4877 <1> ;L4: 4878 <1> ; 4879 <1> ;; 31/12/2014 - cancel controller diagnostics here 4880 <1> ;;;mov cx, 3 ; 26/12/2014 (Award BIOS 1999) 4881 <1> ;;mov cl, 3 4882 <1> ;; 4883 <1> ;;mov dl, 80h ; CHECK THE CONTROLLER 4884 <1> ;;hdc_dl: 4885 <1> ;;mov ah, 14h ; USE CONTROLLER DIAGNOSTIC COMMAND 4886 <1> ;;int 13h ; CALL BIOS WITH DIAGNOSTIC COMMAND 4887 <1> ;;;jc short CTL_ERRX ; DISPLAY ERROR MESSAGE IF BAD RETURN 4888 <1> ;;;jc short POD_DONE ;22/12/2014 4889 <1> ;;jnc short hdc_reset0 4890 <1> ;;loop hdc_dl 4891 <1> ;;; 27/12/2014 4892 <1> ;;stc 4893 <1> ;;retn 4894 <1> ; 4895 <1> ;;hdc_reset0: 4896 <1> ; 18/01/2015 4897 00001F36 8A0D[BC610000] <1> mov cl, [HF_NUM] 4898 00001F3C 20C9 <1> and cl, cl 4899 00001F3E 740D <1> jz short POD_DONE 4900 <1> ; 4901 00001F40 B27F <1> mov dl, 7Fh 4902 <1> hdc_reset1: 4903 00001F42 FEC2 <1> inc dl 4904 <1> ;; 31/12/2015 4905 <1> ;;push dx 4906 <1> ;;push cx 4907 <1> ;;push ds 4908 <1> ;;sub ax, ax 4909 <1> ;;mov ds, ax 4910 <1> ;;mov ax, [TIMER_LOW] ; GET START TIMER COUNTS 4911 <1> ;;pop ds 4912 <1> ;;mov bx, ax 4913 <1> ;;add ax, 6*182 ; 60 SECONDS* 18.2 4914 <1> ;;mov cx, ax 4915 <1> ;;mov word [wait_count], 0 ; 22/12/2014 (reset wait counter) 4916 <1> ;; 4917 <1> ;; 31/12/2014 - cancel HD_RESET_1 4918 <1> ;;call HD_RESET_1 ; SET UP DRIVE 0, (1,2,3) 4919 <1> ;;pop cx 4920 <1> ;;pop dx 4921 <1> ;; 4922 <1> ; 18/01/2015 4923 <1> ;mov ah, 0Dh ; ALTERNATE RESET 4924 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4925 <1> ;mov ah, 5 ; ALTERNATE RESET 4926 <1> ;;int 13h 4927 <1> ;call int13h 4928 <1> ; 12/07/2022 4929 00001F44 30C0 <1> xor al, al ; reset 4930 00001F46 E803000000 <1> call DISK_IO 4931 <1> ; 4932 00001F4B E2F5 <1> loop hdc_reset1 4933 <1> POD_DONE: 4934 00001F4D C3 <1> retn 4935 <1> 4936 <1> ;---------------------------------------- 4937 <1> ; FIXED DISK BIOS ENTRY POINT : 4938 <1> ;---------------------------------------- 4939 <1> 4940 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4941 <1> ; ((Direct call instead of int 13h simulation)) 4942 <1> ; 4943 <1> ; Function in AL 4944 <1> ; 0 = reset 4945 <1> ; 1 = read 4946 <1> ; 2 = write 4947 <1> ; Disk drive number in DL 4948 <1> ; 0 & 1 = floppy disks 4949 <1> ; 80h .. 83h = hard disks 4950 <1> ; Sector address (LBA) in ECX 4951 <1> ; Buffer address in EBX 4952 <1> ; R/W sector count is (always) 1 4953 <1> ; 4954 <1> ; Return: 4955 <1> ; Status in AH (>0 = error code) 4956 <1> ; if CF = 1 -> error code in AH 4957 <1> ; if CF = 0 -> successful 4958 <1> ; AL = undefined 4959 <1> ; 4960 <1> ; Modified registers: (only) EAX 4961 <1> 4962 <1> 4963 <1> ; 11/07/2022 4964 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 4965 <1> 4966 <1> DISK_IO: 4967 <1> ; 11/07/2022 4968 <1> ; save registers 4969 00001F4E 57 <1> push edi ; ANY 4970 00001F4F 56 <1> push esi ; ANY 4971 00001F50 53 <1> push ebx ; BUFFER ADDRESS 4972 00001F51 51 <1> push ecx ; SECTOR ADDRESS (LBA) 4973 00001F52 52 <1> push edx ; DRIVE NUMBER (DL) 4974 <1> 4975 <1> ;cmp dl, 80h ; TEST FOR FIXED DISK DRIVE 4976 <1> ;;jae short A1 ; YES, HANDLE HERE 4977 <1> ;;;;int 40H ; DISKETTE HANDLER 4978 <1> ;;;call int40h 4979 <1> ;;jb DISKETTE_IO_1 4980 <1> ;; 24/12/2021 4981 <1> ;jnb short A1 4982 <1> ;jmp DISKETTE_IO_1 4983 <1> 4984 <1> ; 11/07/2022 4985 00001F53 80FA80 <1> cmp dl, 80h 4986 00001F56 730B <1> jae short A1 4987 <1> 4988 00001F58 E8CAF6FFFF <1> call DISKETTE_IO_1 4989 <1> 4990 <1> DISK_IO_RTN: 4991 <1> ; restore registers 4992 00001F5D 5A <1> pop edx 4993 00001F5E 59 <1> pop ecx 4994 00001F5F 5B <1> pop ebx 4995 00001F60 5E <1> pop esi 4996 00001F61 5F <1> pop edi 4997 00001F62 C3 <1> retn 4998 <1> 4999 <1> ;RET_2: 5000 <1> ; retf 4 ; BACK TO CALLER 5001 <1> 5002 <1> A1: 5003 <1> ; 11/07/2022 5004 <1> ;sti ; ENABLE INTERRUPTS 5005 <1> ;cmp dl, (80h + S_MAX_FILE - 1) 5006 <1> ;ja short RET_2 5007 <1> 5008 <1> ; 18/01/2015 5009 <1> ;;or ah, ah 5010 <1> ;or al, al ; 11/07/2022 (reset function) 5011 <1> ;jz short A3 ; 08/07/2022 5012 <1> 5013 <1> ;;cmp ah, 5 ; Alternate reset 5014 <1> ;cmp al, 5 ; 11/07/2022 5015 <1> ;je short A2 5016 <1> 5017 <1> ; 11/07/2022 - no need to check 5018 <1> ; (only kernel calls diskio functions) 5019 <1> ;;cmp ah, M1L/4 ; cmp ah, 6 5020 <1> ;jb short A3 5021 <1> ;; BAD COMMAND 5022 <1> ;mov byte [DISK_STATUS1], BAD_CMD 5023 <1> ;RET_2: 5024 <1> ;retf 4 5025 <1> 5026 <1> ; 11/07/2022 5027 <1> ;stc 5028 <1> ;retn 5029 <1> A2: 5030 <1> ;sub ah, ah ; Reset 5031 <1> ; 11/07/2022 5032 <1> ;sub al, al 5033 <1> A3: 5034 <1> ; SAVE REGISTERS DURING OPERATION 5035 00001F63 C8080000 <1> enter 8,0 ; SAVE (EBP) AND MAKE ROOM FOR @CMD_BLOCK 5036 <1> 5037 <1> ; 11/07/2022 5038 <1> ; 08/07/2022 5039 <1> ;push ebx ; IN THE STACK, THE COMMAND BLOCK IS: 5040 <1> ;push ecx ; @CMD_BLOCK == BYTE PTR [EBP]-8 5041 <1> ;push edx 5042 <1> ;push esi 5043 <1> ;push edi 5044 <1> 5045 00001F67 E80D000000 <1> call DISK_IO_CONT ; PERFORM THE OPERATION 5046 <1> 5047 00001F6C C9 <1> leave ; 11/07/2022 5048 <1> 5049 00001F6D 8A25[BB610000] <1> mov ah, [DISK_STATUS1] ; GET STATUS FROM OPERATION 5050 00001F73 80FC01 <1> cmp ah, 1 ; SET THE CARRY FLAG TO INDICATE 5051 00001F76 F5 <1> cmc ; SUCCESS OR FAILURE 5052 <1> 5053 <1> ;pop edi ; RESTORE REGISTERS 5054 <1> ;pop esi 5055 <1> ;pop edx 5056 <1> ;pop ecx 5057 <1> ;pop ebx 5058 <1> 5059 <1> ;leave ; ADJUST (ESP) AND RESTORE (EBP) 5060 <1> 5061 <1> ; 11/07/2022 5062 <1> ;retf 4 ; THROW AWAY SAVED FLAGS 5063 <1> 5064 00001F77 EBE4 <1> jmp short DISK_IO_RTN 5065 <1> 5066 <1> DISK_IO_CONT: 5067 <1> ; 17/07/2022 5068 <1> ; 11/07/2022 5069 <1> ; INPUT: 5070 <1> ; AL = 0 : reset 5071 <1> ; AL = 1 : read 5072 <1> ; Al = 2 : write 5073 <1> ; 5074 <1> ; 10/07/2022 5075 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5076 <1> SU0: 5077 00001F79 C605[BB610000]00 <1> mov byte [DISK_STATUS1], 0 ; RESET THE STATUS INDICATOR 5078 <1> ; 10/07/2022 5079 00001F80 89DE <1> mov esi, ebx ; 21/02/2015 ; DATA (BUFFER) ADDRESS 5080 <1> 5081 00001F82 8A1D[BC610000] <1> mov bl, [HF_NUM] ; GET NUMBER OF DRIVES 5082 00001F88 80E27F <1> and dl, 7Fh ; GET DRIVE AS 0 OR 1 5083 <1> ; (get drive number as 0 to 3) 5084 00001F8B 38D3 <1> cmp bl, dl 5085 <1> ;;jbe BAD_COMMAND_POP ; INVALID DRIVE 5086 <1> ;jbe BAD_COMMAND ;; 14/02/2015 5087 <1> ; 24/12/2021 5088 00001F8D 7705 <1> ja short su0_su1 5089 00001F8F E98D000000 <1> jmp BAD_COMMAND 5090 <1> su0_su1: 5091 <1> ;;03/01/2015 5092 00001F94 29DB <1> sub ebx, ebx 5093 00001F96 88D3 <1> mov bl, dl 5094 00001F98 883D[D0610000] <1> mov [LBAMode], bh ; 0 5095 <1> ;test byte [ebx+hd0_type], 1 ; LBA ready ? 5096 <1> ;jz short su1 ; no 5097 <1> ;inc byte [LBAMode] 5098 <1> ;su1: 5099 <1> ; 21/02/2015 (32 bit modification) 5100 <1> ; 04/01/2015 5101 <1> ;push ax ; *** 5102 <1> ; 24/12/2021 5103 00001F9E 50 <1> push eax ; *** ; function (in AL) ; 11/07/2022 5104 <1> ; 24/12/2021 5105 00001F9F 52 <1> push edx ; * 5106 00001FA0 50 <1> push eax ; function (in AL) ; 11/07/2022 5107 00001FA1 E8C4030000 <1> CALL GET_VEC ; GET DISK PARAMETERS 5108 <1> ; 02/02/2015 5109 00001FA6 668B4310 <1> mov ax, [ebx+16] ; I/O port base address (1F0h, 170h) 5110 00001FAA 66A3[425C0000] <1> mov [HF_PORT], ax 5111 00001FB0 668B5312 <1> mov dx, [ebx+18] ; control port address (3F6h, 376h) 5112 00001FB4 668915[445C0000] <1> mov [HF_REG_PORT], dx 5113 00001FBB 8A4314 <1> mov al, [ebx+20] ; head register upper nibble (A0h,B0h,E0h,F0h) 5114 <1> ; 23/02/2015 5115 00001FBE A840 <1> test al, 40h ; LBA bit (bit 6) 5116 00001FC0 7406 <1> jz short su1 5117 00001FC2 FE05[D0610000] <1> inc byte [LBAMode] ; 1 5118 <1> su1: 5119 00001FC8 C0E804 <1> shr al, 4 5120 00001FCB 2401 <1> and al, 1 5121 00001FCD A2[465C0000] <1> mov [hf_m_s], al 5122 <1> ; 5123 <1> ; 03/01/2015 5124 00001FD2 8A4308 <1> mov al, [ebx+8] ; GET CONTROL BYTE MODIFIER 5125 <1> ;mov dx, [HF_REG_PORT] ; Device Control register 5126 00001FD5 EE <1> out dx, al ; SET EXTRA HEAD OPTION 5127 <1> ; Control Byte: (= 08h, here) 5128 <1> ; bit 0 - 0 5129 <1> ; bit 1 - nIEN (1 = disable irq) 5130 <1> ; bit 2 - SRST (software RESET) 5131 <1> ; bit 3 - use extra heads (8 to 15) 5132 <1> ; -always set to 1- 5133 <1> ; (bits 3 to 7 are reserved 5134 <1> ; for ATA devices) 5135 00001FD6 8A25[BD610000] <1> mov ah, [CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 5136 00001FDC 80E4C0 <1> and ah, 0C0h ; CONTROL BYTE 5137 00001FDF 08C4 <1> or ah, al 5138 00001FE1 8825[BD610000] <1> mov [CONTROL_BYTE], ah 5139 <1> ; 04/01/2015 5140 <1> ;pop ax 5141 <1> ; 24/12/2021 5142 00001FE7 58 <1> pop eax ; function (in AL) ; 11/07/2022 5143 <1> ;pop dx ; * ;; 14/02/2015 5144 <1> ; 24/12/2021 5145 00001FE8 5A <1> pop edx ; * 5146 <1> ;and ah, ah ; Reset function ? 5147 00001FE9 20C0 <1> and al, al ; 11/07/2022 5148 00001FEB 7506 <1> jnz short su2 5149 <1> ;pop ax ; *** 5150 <1> ; 24/12/2021 5151 00001FED 58 <1> pop eax ; *** 5152 <1> ;;pop bx 5153 00001FEE E9E4000000 <1> jmp DISK_RESET 5154 <1> su2: 5155 <1> ; 11/07/2022 5156 <1> ; ecx = sector address (lba) 5157 <1> ; dl = hard disk drive number (80h, 81h .. 83h) 5158 <1> ; al = function (0 = read, 1 = write) 5159 <1> 5160 00001FF3 803D[D0610000]00 <1> cmp byte [LBAMode], 0 5161 00001FFA 7620 <1> jna short su3 ; convert LBA address to CHS parameters 5162 <1> 5163 <1> ; ; 02/02/2015 (LBA read/write function calls) 5164 <1> ; ;cmp ah, 1Bh 5165 <1> ; cmp ah, 3 ; 08/07/2022 5166 <1> ; jb short lbarw1 5167 <1> ; ;;cmp ah, 1Ch 5168 <1> ; ;cmp ah, 4 ; 08/07/2022 5169 <1> ; ;ja short invldfnc 5170 <1> ; ;;pop dx ; * ; 14/02/2015 5171 <1> ; ;mov ax, cx ; Lower word of LBA address (bits 0-15) 5172 <1> 5173 00001FFC 89C8 <1> mov eax, ecx ; LBA address (21/02/2015) 5174 <1> 5175 <1> ; 11/07/2022 5176 <1> ;; 14/02/2015 5177 <1> ;mov cl, dl ; 14/02/2015 5178 <1> 5179 <1> ;;mov dx, bx 5180 <1> ;mov dx, si ; higher word of LBA address (bits 16-23) 5181 <1> ;;mov bx, di 5182 <1> ;mov si, di ; Buffer offset 5183 <1> 5184 <1> ; 11/07/2022 5185 <1> ;jmp short lbarw2 5186 <1> 5187 <1> ;lbarw1: 5188 <1> ; ; convert CHS to LBA 5189 <1> ; ; 5190 <1> ; ; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM 5191 <1> ; ; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track 5192 <1> ; ; + Sector - 1 5193 <1> ; ;push dx ; * ;; 14/02/2015 5194 <1> ; ; 24/12/2021 5195 <1> ; push edx ; * 5196 <1> ; ;xor dh, dh 5197 <1> ; xor edx, edx 5198 <1> ; mov dl, [ebx+14] ; sectors per track (logical) 5199 <1> ; ;xor ah, ah 5200 <1> ; xor eax, eax 5201 <1> ; mov al, [ebx+2] ; heads (logical) 5202 <1> ; dec al 5203 <1> ; ;inc ax ; 0 = 256 5204 <1> ; inc eax ; 24/12/2021 5205 <1> ; mul dx 5206 <1> ; ; AX = # of Heads * Sectors/Track 5207 <1> ; mov dx, cx 5208 <1> ; ;and cx, 3Fh ; sector (1 to 63) 5209 <1> ; and ecx, 3fh 5210 <1> ; xchg dl, dh 5211 <1> ; shr dh, 6 5212 <1> ; ; DX = cylinder (0 to 1023) 5213 <1> ; ;mul dx 5214 <1> ; ; DX:AX = # of Heads * Sectors/Track * Cylinder 5215 <1> ; mul edx 5216 <1> ; dec cl ; sector - 1 5217 <1> ; ;add ax, cx 5218 <1> ; ;adc dx, 0 5219 <1> ; ; DX:AX = # of Heads * Sectors/Track * Cylinder + Sector -1 5220 <1> ; add eax, ecx 5221 <1> ; ;pop cx ; * ; ch = head, cl = drive number (zero based) 5222 <1> ; ; 24/12/2021 5223 <1> ; pop ecx ; * ; ch = head, cl = drive number (zero based) 5224 <1> ; ;push dx 5225 <1> ; ;push ax 5226 <1> ; push eax 5227 <1> ; mov al, [ebx+14] ; sectors per track (logical) 5228 <1> ; mul ch 5229 <1> ; ; AX = Head * Sectors/Track 5230 <1> ; cwd 5231 <1> ; ;pop dx 5232 <1> ; pop edx 5233 <1> ; ;add ax, dx 5234 <1> ; ;pop dx 5235 <1> ; ;adc dx, 0 ; add carry bit 5236 <1> ; add eax, edx 5237 <1> ; 5238 <1> ;lbarw2: 5239 <1> ; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5240 <1> 5241 00001FFE 29D2 <1> sub edx, edx ; 21/02/2015 5242 <1> 5243 <1> ; 11/07/2022 5244 <1> ;mov dl, cl ; 21/02/2015 5245 <1> 5246 00002000 C645F800 <1> mov byte [CMD_BLOCK], 0 ; Features Register 5247 <1> ; NOTE: Features register (1F1h, 171h) 5248 <1> ; is not used for ATA device R/W functions. 5249 <1> ; It is old/obsolete 'write precompensation' 5250 <1> ; register and error register 5251 <1> ; for old ATA/IDE devices. 5252 <1> ; 18/01/2014 5253 <1> ;mov ch, [hf_m_s] ; Drive 0 (master) or 1 (slave) 5254 00002004 8A0D[465C0000] <1> mov cl, [hf_m_s] 5255 <1> ;shl ch, 4 ; bit 4 (drive bit) 5256 <1> ;or ch, 0E0h ; bit 5 = 1 5257 <1> ; bit 6 = 1 = LBA mode 5258 <1> ; bit 7 = 1 5259 0000200A 80C90E <1> or cl, 0Eh ; 1110b 5260 <1> ;and dh, 0Fh ; LBA byte 4 (bits 24 to 27) 5261 0000200D 25FFFFFF0F <1> and eax, 0FFFFFFFh 5262 00002012 C1E11C <1> shl ecx, 28 ; 21/02/2015 5263 <1> ;or dh, ch 5264 00002015 09C8 <1> or eax, ecx 5265 <1> ;;mov [CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7) 5266 <1> ; (Sector Number Register) 5267 <1> ;;mov [CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15) 5268 <1> ; (Cylinder Low Register) 5269 <1> ;mov [CMD_BLOCK+2], ax ; LBA byte 1, 2 5270 <1> ;mov [CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23) 5271 <1> ; (Cylinder High Register) 5272 <1> ;;mov [CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27) 5273 <1> ; (Drive/Head Register) 5274 <1> 5275 <1> ;mov [CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits 5276 00002017 8945FA <1> mov [CMD_BLOCK+2], eax ; 21/02/2015 5277 <1> ;14/02/2015 5278 <1> ;mov dl, cl ; Drive number (INIT_DRV) 5279 0000201A EB3D <1> jmp short su4 5280 <1> su3: 5281 <1> ; 02/02/2015 5282 <1> ; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 5283 <1> ;cmp ah, 14h 5284 <1> ;jna short chsfnc 5285 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5286 <1> ;cmp ah, 2 5287 <1> ;jna short chsfnc 5288 <1> ; 11/07/2022 5289 <1> ; (al = function, read = 1 or write = 2) 5290 0000201C 3C02 <1> cmp al, 2 5291 0000201E 760B <1> jna short chsfnc 5292 <1> invldfnc: 5293 <1> ; 14/02/2015 5294 <1> ;pop es ; ** 5295 <1> ;pop ax ; *** 5296 <1> ; 24/12/2021 5297 00002020 58 <1> pop eax ; *** 5298 <1> ;;jmp short BAD_COMMAND_POP 5299 <1> ; 11/07/2022 5300 <1> ;jmp short BAD_COMMAND 5301 <1> 5302 <1> ; 11/07/2022 5303 <1> BAD_COMMAND: 5304 00002021 C605[BB610000]01 <1> mov byte [DISK_STATUS1], BAD_CMD ; COMMAND ERROR 5305 <1> ;mov al, 0 5306 00002028 28C0 <1> sub al, al ; 0 5307 0000202A C3 <1> retn 5308 <1> 5309 <1> chsfnc: 5310 0000202B 668B4305 <1> mov ax, [ebx+5] ; GET WRITE PRE-COMPENSATION CYLINDER 5311 <1> ;shr ax, 2 5312 <1> ; 17/07/2022 5313 0000202F C1E802 <1> shr eax, 2 5314 00002032 8845F8 <1> mov [CMD_BLOCK], al 5315 <1> ; 5316 <1> ;;mov al, [ebx+8] ; GET CONTROL BYTE MODIFIER 5317 <1> ;;push edx ; * 5318 <1> ;;mov dx, [HF_REG_PORT] 5319 <1> ;;out dx, al ; SET EXTRA HEAD OPTION 5320 <1> ;;pop edx ; * 5321 <1> ;;mov ah, [CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 5322 <1> ;;and ah, 0C0h ; CONTROL BYTE 5323 <1> ;;or ah, al 5324 <1> ;;mov [CONTROL_BYTE], ah 5325 <1> ; 5326 00002035 88C8 <1> mov al, cl ; GET SECTOR NUMBER 5327 00002037 243F <1> and al, 3Fh 5328 00002039 8845FA <1> mov [CMD_BLOCK+2], al 5329 0000203C 886DFB <1> mov [CMD_BLOCK+3], ch ; GET CYLINDER NUMBER 5330 0000203F 88C8 <1> mov al, cl 5331 00002041 C0E806 <1> shr al, 6 5332 00002044 8845FC <1> mov [CMD_BLOCK+4], al ; CYLINDER HIGH ORDER 2 BITS 5333 <1> ;;05/01/2015 5334 <1> ;;mov al, dl ; DRIVE NUMBER 5335 00002047 A0[465C0000] <1> mov al, [hf_m_s] 5336 0000204C C0E004 <1> shl al, 4 5337 0000204F 80E60F <1> and dh, 0Fh ; HEAD NUMBER 5338 00002052 08F0 <1> or al, dh 5339 00002054 0CA0 <1> or al, 80h+20h ; ECC AND 512 BYTE SECTORS 5340 00002056 8845FD <1> mov [CMD_BLOCK+5], al ; ECC/SIZE/DRIVE/HEAD 5341 <1> su4: 5342 <1> ;; 14/02/2015 5343 <1> ;;pop ax 5344 <1> ;;mov [CMD_BLOCK+1], AL ; SECTOR COUNT 5345 <1> ;;push ax 5346 <1> ;;mov al, ah ; GET INTO LOW BYTE 5347 <1> ;;xor ah, ah ; ZERO HIGH BYTE 5348 <1> ;;sal ax, 1 ; *2 FOR TABLE LOOKUP 5349 <1> ;pop ax ; *** 5350 <1> ; 24/12/2021 5351 00002059 58 <1> pop eax ; *** ; function (in AL) ; 11/07/2022 5352 <1> 5353 <1> ;mov [CMD_BLOCK+1], al 5354 0000205A C645F901 <1> mov byte [CMD_BLOCK+1], 1 ; (always 1 sector r/w) 5355 <1> 5356 <1> ; 11/07/2022 5357 <1> ;mov ebx, esi 5358 <1> ; (esi = buffer address) 5359 <1> 5360 0000205E 3C02 <1> cmp al, 2 5361 00002060 742D <1> je short DISK_WRITE 5362 <1> 5363 <1> ;jmp short DISK_READ 5364 <1> 5365 <1> ; ;xor ebx, ebx 5366 <1> ; ;mov bl, ah 5367 <1> ; 5368 <1> ; ;xor bh, bh 5369 <1> ; ;sal bx, 1 5370 <1> ; sal bx, 2 ; 32 bit offset (21/02/2015) 5371 <1> ; ;;mov si, ax ; PUT INTO SI FOR BRANCH 5372 <1> ; ;;cmp ax, M1L ; TEST WITHIN RANGE 5373 <1> ; ;;jnb short BAD_COMMAND_POP 5374 <1> ; ; 08/07/2022 5375 <1> ; ;cmp ebx, M1L 5376 <1> ; ;jnb short BAD_COMMAND 5377 <1> ; 5378 <1> ; xchg ebx, esi 5379 <1> ; 5380 <1> ; ;;;pop ax ; RESTORE AX 5381 <1> ; ;;;pop bx ; AND DATA ADDRESS 5382 <1> ; 5383 <1> ; ;;push cx 5384 <1> ; ;;push ax ; ADJUST ES:BX 5385 <1> ; ;mov cx, bx ; GET 3 HIGH ORDER NIBBLES OF BX 5386 <1> ; ;shr cx, 4 5387 <1> ; ;mov ax, es 5388 <1> ; ;add ax, cx 5389 <1> ; ;mov es, ax 5390 <1> ; ;and bx, 000Fh ; ES:BX CHANGED TO ES:000X 5391 <1> ; ;;pop ax 5392 <1> ; ;;pop cx 5393 <1> ; 5394 <1> ; jmp dword [esi+M1] 5395 <1> 5396 <1> ;;BAD_COMMAND_POP: 5397 <1> ;; pop ax 5398 <1> ;; pop bx 5399 <1> ; 5400 <1> ; ; 11/07/2022 5401 <1> ;BAD_COMMAND: 5402 <1> ; mov byte [DISK_STATUS1], BAD_CMD ; COMMAND ERROR 5403 <1> ; ;mov al, 0 5404 <1> ; sub al, al ; 0 5405 <1> ; retn 5406 <1> 5407 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5408 <1> 5409 <1> ;---------------------------------------- 5410 <1> ; DISK READ ROUTINE (AH = 01H) : 5411 <1> ;---------------------------------------- 5412 <1> ; 5413 <1> DISK_READ: 5414 00002062 C645FE20 <1> mov byte [CMD_BLOCK+6], READ_CMD 5415 <1> ;jmp COMMANDI 5416 <1> 5417 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5418 <1> 5419 <1> ;---------------------------------------- 5420 <1> ; COMMANDI : 5421 <1> ; REPEATEDLY INPUTS DATA TILL : 5422 <1> ; NSECTOR RETURNS ZERO : 5423 <1> ;---------------------------------------- 5424 <1> COMMANDI: 5425 <1> ; 11/07/2022 5426 <1> ; (check 64K boundary is not needed) 5427 <1> ;call CHECK_DMA ; CHECK 64K BOUNDARY ERROR 5428 <1> ;jc short CMD_ABORT 5429 <1> 5430 <1> ;mov di, bx 5431 <1> ; 11/07/2022 5432 <1> ; (esi = buffer address) 5433 <1> ;mov edi, ebx ; 21/02/2015 5434 00002066 89F7 <1> mov edi, esi ; 11/07/2022 5435 <1> 5436 00002068 E8A8010000 <1> call COMMAND ; OUTPUT COMMAND 5437 0000206D 751F <1> jnz short CMD_ABORT 5438 <1> CMD_I1: 5439 0000206F E813020000 <1> call _WAIT ; WAIT FOR DATA REQUEST INTERRUPT 5440 00002074 7518 <1> jnz short TM_OUT ; TIME OUT 5441 <1> ;;mov cx,256 ; SECTOR SIZE IN WORDS 5442 <1> ;mov ecx, 256 ; 21/02/2015 5443 00002076 29C9 <1> sub ecx, ecx 5444 00002078 FEC5 <1> inc ch 5445 <1> ; ecx = 256 5446 <1> ;mov dx, HF_PORT 5447 0000207A 668B15[425C0000] <1> mov dx, [HF_PORT] 5448 00002081 FA <1> cli 5449 00002082 FC <1> cld 5450 00002083 F3666D <1> rep insw ; GET THE SECTOR 5451 00002086 FB <1> sti 5452 <1> 5453 <1> ;test byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL INPUT 5454 <1> ;jz short CMD_I3 5455 <1> ;call WAIT_DRQ ; WAIT FOR DATA REQUEST 5456 <1> ;jc short TM_OUT 5457 <1> ;;mov dx, HF_PORT 5458 <1> ;mov dx,[HF_PORT] 5459 <1> ;xor ecx, ecx 5460 <1> ;;mov ecx, 4 ; mov cx, 4 ; OUTPUT THE ECC BYTES 5461 <1> ;mov cl, 4 5462 <1> ;CMD_I2: 5463 <1> ;inc al, dx 5464 <1> ;mov [edi], al ; 21/02/2015 5465 <1> ;inc edi 5466 <1> ;loop CMD_I2 5467 <1> CMD_I3: 5468 00002087 E817010000 <1> call CHECK_STATUS 5469 0000208C 7500 <1> jnz short CMD_ABORT ; ERROR RETURNED 5470 <1> ; 11/07/2022 5471 <1> ; (sector count = 1) 5472 <1> ;dec byte [CMD_BLOCK+1] ; CHECK FOR MORE 5473 <1> ;jnz SHORT CMD_I1 5474 <1> CMD_ABORT: 5475 <1> TM_OUT: 5476 0000208E C3 <1> retn 5477 <1> 5478 <1> ;--------------------------------------------------- 5479 <1> 5480 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5481 <1> 5482 <1> ;---------------------------------------- 5483 <1> ; DISK WRITE ROUTINE (AH = 02H) : 5484 <1> ;---------------------------------------- 5485 <1> 5486 <1> DISK_WRITE: 5487 0000208F C645FE30 <1> mov byte [CMD_BLOCK+6], WRITE_CMD 5488 <1> ;JMP COMMANDO 5489 <1> 5490 <1> ; 16/07/2022 5491 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5492 <1> 5493 <1> ;---------------------------------------- 5494 <1> ; COMMANDO : 5495 <1> ; REPEATEDLY OUTPUTS DATA TILL : 5496 <1> ; NSECTOR RETURNS ZERO : 5497 <1> ;---------------------------------------- 5498 <1> COMMANDO: 5499 <1> ; 11/07/2022 5500 <1> ; (check 64K boundary is not needed) 5501 <1> ;call CHECK_DMA ; CHECK 64K BOUNDARY ERROR 5502 <1> ;jc short CMD_ABORT 5503 <1> CMD_OF: 5504 <1> ; 11/07/2022 5505 <1> ; (esi = ebx = buffer address) 5506 <1> ;mov esi, ebx ; 21/02/2015 5507 00002093 E87D010000 <1> call COMMAND ; OUTPUT COMMAND 5508 00002098 75F4 <1> jnz short CMD_ABORT 5509 0000209A E83F020000 <1> call WAIT_DRQ ; WAIT FOR DATA REQUEST 5510 0000209F 72ED <1> jc short TM_OUT ; TOO LONG 5511 <1> CMD_O1: 5512 <1> ; 16/07/2022 5513 000020A1 668B15[425C0000] <1> mov dx, [HF_PORT] 5514 <1> 5515 <1> ; 10/07/2022 5516 <1> ;mov ecx, 256 ; 21/02/2015 5517 000020A8 31C9 <1> xor ecx, ecx 5518 000020AA FEC5 <1> inc ch 5519 <1> ; ecx = 256 5520 000020AC FA <1> cli 5521 000020AD FC <1> cld 5522 000020AE F3666F <1> rep outsw 5523 000020B1 FB <1> sti 5524 <1> 5525 <1> ; 10/07/2022 5526 <1> ;test byte [CMD_BLOCK+6], ECC_MODE ; CHECK FOR NORMAL OUTPUT 5527 <1> ;jz short CMD_O3 5528 <1> ; 5529 <1> ;call WAIT_DRQ ; WAIT FOR DATA REQUEST 5530 <1> ;jc short TM_OUT 5531 <1> ;;mov dx, HF_PORT 5532 <1> ;mov dx, [HF_PORT] 5533 <1> ;sub ecx, ecx 5534 <1> ;;mov ecx, 4 ; mov cx, 4 ; OUTPUT THE ECC BYTES 5535 <1> ;mov cl, 4 5536 <1> ;CMD_O2: 5537 <1> ;;lodsb 5538 <1> ;mov al, [esi] 5539 <1> ;out dx, al 5540 <1> ;inc esi 5541 <1> ;loop CMD_O2 5542 <1> 5543 <1> CMD_O3: 5544 000020B2 E8D0010000 <1> call _WAIT ; WAIT FOR SECTOR COMPLETE INTERRUPT 5545 000020B7 75D5 <1> jnz short TM_OUT ; ERROR RETURNED 5546 000020B9 E8E5000000 <1> call CHECK_STATUS 5547 000020BE 75CE <1> jnz short CMD_ABORT 5548 <1> 5549 <1> ; 11/07/2022 5550 <1> ; (sector count = 1) 5551 <1> ;test byte [HF_STATUS], ST_DRQ ; CHECK FOR MORE 5552 <1> ;jnz short CMD_O1 5553 <1> 5554 <1> ;mov dx, HF_PORT+2 ; CHECK RESIDUAL SECTOR COUNT 5555 000020C0 668B15[425C0000] <1> mov dx, [HF_PORT] 5556 000020C7 80C202 <1> add dl, 2 5557 <1> ;inc dl 5558 <1> ;inc dl 5559 000020CA EC <1> in al, dx ; 5560 000020CB A8FF <1> test al, 0FFh ; 5561 000020CD 7407 <1> jz short CMD_O4 ; COUNT = 0 OK 5562 000020CF C605[BB610000]BB <1> mov byte [DISK_STATUS1], UNDEF_ERR 5563 <1> ; OPERATION ABORTED - PARTIAL TRANSFER 5564 <1> CMD_O4: 5565 000020D6 C3 <1> retn 5566 <1> 5567 <1> ; 10/07/2022 5568 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5569 <1> 5570 <1> ;---------------------------------------- 5571 <1> ; RESET THE DISK SYSTEM (AH=00H) : 5572 <1> ;---------------------------------------- 5573 <1> 5574 <1> ; 18-1-2015 : one controller reset (not other one) 5575 <1> 5576 <1> DISK_RESET: 5577 000020D7 FA <1> cli 5578 000020D8 E4A1 <1> in al, INTB01 ; GET THE MASK REGISTER 5579 <1> ;JMP $+2 5580 <1> IODELAY 2191 000020DA EB00 <2> jmp short $+2 2192 000020DC EB00 <2> jmp short $+2 5581 <1> ;and al, 0BFh ; ENABLE FIXED DISK INTERRUPT 5582 000020DE 243F <1> and al, 3Fh ; 22/12/2014 (IRQ 14 & IRQ 15) 5583 000020E0 E6A1 <1> out INTB01, al 5584 000020E2 FB <1> sti ; START INTERRUPTS 5585 <1> ; 14/02/2015 5586 <1> ;mov di, dx 5587 <1> ; 24/12/2021 5588 000020E3 89D7 <1> mov edi, edx 5589 <1> ; 04/01/2015 5590 <1> ;xor di,di 5591 <1> drst0: 5592 000020E5 B004 <1> mov al, 04h ; bit 2 - SRST 5593 <1> ;mov dx, HF_REG_PORT 5594 000020E7 668B15[445C0000] <1> mov dx, [HF_REG_PORT] 5595 000020EE EE <1> out dx, al ; RESET 5596 <1> ; mov cx, 10 ; DELAY COUNT 5597 <1> ;DRD: dec cx 5598 <1> ; jnz short DRD ; WAIT 4.8 MICRO-SEC 5599 <1> ;mov cx, 2 ; wait for 30 micro seconds 5600 <1> ;mov ecx, 2 ; 21/02/2015 5601 <1> ; 10/07/2022 5602 000020EF 29C9 <1> sub ecx, ecx 5603 000020F1 B102 <1> mov cl, 2 5604 000020F3 E89BF2FFFF <1> call WAITF ; (Award Bios 1999 - WAIT_REFRESH, 5605 <1> ; 40 micro seconds) 5606 000020F8 A0[BD610000] <1> mov al, [CONTROL_BYTE] 5607 000020FD 240F <1> and al, 0Fh ; SET HEAD OPTION 5608 000020FF EE <1> out dx, al ; TURN RESET OFF 5609 00002100 E8B2010000 <1> call NOT_BUSY 5610 00002105 7514 <1> jnz short DRERR ; TIME OUT ON RESET 5611 00002107 668B15[425C0000] <1> mov dx, [HF_PORT] 5612 0000210E FEC2 <1> inc dl ; HF_PORT+1 5613 <1> ; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM 5614 <1> ;mov cl, 10 5615 <1> ;mov ecx, 10 ; 21/02/2015 5616 <1> ; 10/07/2022 5617 <1> ;xor ecx, ecx 5618 00002110 B10A <1> mov cl, 10 5619 <1> drst1: 5620 00002112 EC <1> in al, dx ; GET RESET STATUS 5621 00002113 3C01 <1> cmp al, 1 5622 <1> ; 04/01/2015 5623 00002115 740C <1> jz short drst2 5624 <1> ;jnz short DRERR ; BAD RESET STATUS 5625 <1> ; Drive/Head Register - bit 4 5626 <1> ;loop drst1 5627 <1> ; 10/07/2022 5628 00002117 FEC9 <1> dec cl 5629 00002119 75F7 <1> jnz short drst1 5630 <1> DRERR: 5631 0000211B C605[BB610000]05 <1> mov byte [DISK_STATUS1], BAD_RESET ; CARD FAILED 5632 00002122 C3 <1> retn 5633 <1> drst2: 5634 <1> ; 14/02/2015 5635 <1> ;mov dx, di 5636 <1> ; 24/12/2021 5637 00002123 89FA <1> mov edx, edi 5638 <1> ;drst3: 5639 <1> ; ; 05/01/2015 5640 <1> ; shl di, 1 5641 <1> ; ; 04/01/2015 5642 <1> ; mov ax, [di+hd_cports] 5643 <1> ; cmp ax, [HF_REG_PORT] 5644 <1> ; je short drst4 5645 <1> ; mov [HF_REG_PORT], ax 5646 <1> ; ; 03/01/2015 5647 <1> ; mov ax, [di+hd_ports] 5648 <1> ; mov [HF_PORT], ax 5649 <1> ; ; 05/01/2014 5650 <1> ; shr di, 1 5651 <1> ; ; 04/01/2015 5652 <1> ; jmp short drst0 ; reset other controller 5653 <1> ;drst4: 5654 <1> ; ; 05/01/2015 5655 <1> ; shr di, 1 5656 <1> ; mov al, [di+hd_dregs] 5657 <1> ; and al, 10h ; bit 4 only 5658 <1> ; shr al, 4 ; bit 4 -> bit 0 5659 <1> ; mov [hf_m_s], al ; (0 = master, 1 = slave) 5660 <1> ; 5661 00002125 A0[465C0000] <1> mov al, [hf_m_s] ; 18/01/2015 5662 0000212A A801 <1> test al, 1 5663 <1> ;jnz short drst6 5664 0000212C 7516 <1> jnz short drst4 5665 0000212E 8065FDEF <1> and byte [CMD_BLOCK+5], 0EFh ; SET TO DRIVE 0 5666 <1> ;drst5: 5667 <1> drst3: 5668 00002132 E813000000 <1> call INIT_DRV ; SET MAX HEADS 5669 <1> ;mov dx, di 5670 00002137 E8A3000000 <1> call HDISK_RECAL ; RECAL TO RESET SEEK SPEED 5671 <1> ; 04/01/2014 5672 <1> ; inc di 5673 <1> ; mov dx, di 5674 <1> ; cmp dl, [HF_NUM] 5675 <1> ; jb short drst3 5676 <1> ;DRE: 5677 0000213C C605[BB610000]00 <1> mov byte [DISK_STATUS1], 0 ; IGNORE ANY SET UP ERRORS 5678 00002143 C3 <1> retn 5679 <1> ;drst6: 5680 <1> drst4: ; Drive/Head Register - bit 4 5681 00002144 804DFD10 <1> or byte [CMD_BLOCK+5], 010h ; SET TO DRIVE 1 5682 <1> ;jmp short drst5 5683 00002148 EBE8 <1> jmp short drst3 5684 <1> 5685 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5686 <1> 5687 <1> ;---------------------------------------- 5688 <1> ; INITIALIZE DRIVE (AH = 09H) : 5689 <1> ;---------------------------------------- 5690 <1> ; 03/01/2015 5691 <1> ; According to ATA-ATAPI specification v2.0 to v5.0 5692 <1> ; logical sector per logical track 5693 <1> ; and logical heads - 1 would be set but 5694 <1> ; it is seen as it will be good 5695 <1> ; if physical parameters will be set here 5696 <1> ; because, number of heads <= 16. 5697 <1> ; (logical heads usually more than 16) 5698 <1> ; NOTE: ATA logical parameters (software C, H, S) 5699 <1> ; == INT 13h physical parameters 5700 <1> 5701 <1> ;INIT_DRV: 5702 <1> ; mov byte [CMD_BLOCK+6], SET_PARM_CMD 5703 <1> ; call GET_VEC ; ES:BX -> PARAMETER BLOCK 5704 <1> ; mov al, [es:bx+2] ; GET NUMBER OF HEADS 5705 <1> ; dec al ; CONVERT TO 0-INDEX 5706 <1> ; mov ah, [CMD_BLOCK+5] ; GET SDH REGISTER 5707 <1> ; and ah, 0F0h ; CHANGE HEAD NUMBER 5708 <1> ; or ah, al ; TO MAX HEAD 5709 <1> ; mov [CMD_BLOCK+5], ah 5710 <1> ; mov al, [es:bx+14] ; MAX SECTOR NUMBER 5711 <1> ; mov [CMD_BLOCK+1], al 5712 <1> ; sub ax, ax 5713 <1> ; mov [CMD_BLOCK+3], al ; ZERO FLAGS 5714 <1> ; call COMMAND ; TELL CONTROLLER 5715 <1> ; jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 5716 <1> ; call NOT_BUSY ; WAIT FOR IT TO BE DONE 5717 <1> ; jnz short INIT_EXIT ; TIME OUT 5718 <1> ; call CHECK_STATUS 5719 <1> ;INIT_EXIT: 5720 <1> ; retn 5721 <1> 5722 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5723 <1> 5724 <1> ; 04/01/2015 5725 <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999 5726 <1> ; AHDSK.ASM - INIT_DRIVE 5727 <1> INIT_DRV: 5728 <1> ;xor ah, ah 5729 0000214A 31C0 <1> xor eax, eax ; 21/02/2015 5730 0000214C B00B <1> mov al, 11 ; Physical heads from translated HDPT 5731 0000214E 3825[D0610000] <1> cmp [LBAMode], ah ; 0 5732 00002154 7702 <1> ja short idrv0 5733 00002156 B002 <1> mov al, 2 ; Physical heads from standard HDPT 5734 <1> idrv0: 5735 <1> ; DL = drive number (0 based) 5736 00002158 E80D020000 <1> call GET_VEC 5737 <1> ;push bx 5738 0000215D 53 <1> push ebx ; 21/02/2015 5739 <1> ;add bx, ax 5740 0000215E 01C3 <1> add ebx, eax 5741 <1> ;; 05/01/2015 5742 00002160 8A25[465C0000] <1> mov ah, [hf_m_s] ; drive number (0= master, 1= slave) 5743 <1> ;;and ah, 1 5744 00002166 C0E404 <1> shl ah, 4 5745 00002169 80CCA0 <1> or ah, 0A0h ; Drive/Head register - 10100000b (A0h) 5746 <1> ;mov al, [es:bx] 5747 0000216C 8A03 <1> mov al, [ebx] ; 21/02/2015 5748 0000216E FEC8 <1> dec al ; last head number 5749 <1> ;and al, 0Fh 5750 00002170 08E0 <1> or al, ah ; lower 4 bits for head number 5751 <1> ; 5752 00002172 C645FE91 <1> mov byte [CMD_BLOCK+6], SET_PARM_CMD 5753 00002176 8845FD <1> mov [CMD_BLOCK+5], al 5754 <1> ;pop bx 5755 00002179 5B <1> pop ebx 5756 0000217A 29C0 <1> sub eax, eax ; 21/02/2015 5757 0000217C B004 <1> mov al, 4 ; Physical sec per track from translated HDPT 5758 0000217E 803D[D0610000]00 <1> cmp byte [LBAMode], 0 5759 00002185 7702 <1> ja short idrv1 5760 00002187 B00E <1> mov al, 14 ; Physical sec per track from standard HDPT 5761 <1> idrv1: 5762 <1> ;xor ah, ah 5763 <1> ;add bx, ax 5764 00002189 01C3 <1> add ebx, eax ; 21/02/2015 5765 <1> ;mov al, [es:bx] 5766 <1> ; sector number 5767 0000218B 8A03 <1> mov al, [ebx] 5768 0000218D 8845F9 <1> mov [CMD_BLOCK+1], al 5769 00002190 28C0 <1> sub al, al 5770 00002192 8845FB <1> mov [CMD_BLOCK+3], al ; ZERO FLAGS 5771 00002195 E87B000000 <1> call COMMAND ; TELL CONTROLLER 5772 0000219A 751E <1> jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 5773 0000219C E816010000 <1> call NOT_BUSY ; WAIT FOR IT TO BE DONE 5774 000021A1 7517 <1> jnz short INIT_EXIT ; TIME OUT 5775 <1> ;call CHECK_STATUS 5776 <1> ;jmp short CHECK_STATUS 5777 <1> ;INIT_EXIT: 5778 <1> ;retn 5779 <1> 5780 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5781 <1> 5782 <1> ;---------------------------------------- 5783 <1> ; CHECK FIXED DISK STATUS : 5784 <1> ;---------------------------------------- 5785 <1> CHECK_STATUS: 5786 000021A3 E861010000 <1> call CHECK_ST ; CHECK THE STATUS BYTE 5787 <1> ;jnz short CHECK_S1 ; AN ERROR WAS FOUND 5788 <1> ; 10/07/2022 5789 000021A8 7510 <1> jnz short CHECK_S2 5790 000021AA A801 <1> test al, ST_ERROR ; WERE THERE ANY OTHER ERRORS 5791 000021AC 7405 <1> jz short CHECK_S1 ; NO ERROR REPORTED 5792 000021AE E894010000 <1> call CHECK_ER ; ERROR REPORTED 5793 <1> CHECK_S1: 5794 000021B3 803D[BB610000]00 <1> cmp byte [DISK_STATUS1], 0 ; SET STATUS FOR CALLER 5795 <1> CHECK_S2: 5796 <1> INIT_EXIT: ; 10/07/2022 5797 000021BA C3 <1> retn 5798 <1> 5799 <1> ;---------------------------------------- 5800 <1> ; TEST DISK READY (AH = 10H) : 5801 <1> ;---------------------------------------- 5802 <1> 5803 <1> TST_RDY: ; WAIT FOR CONTROLLER 5804 000021BB E8F7000000 <1> call NOT_BUSY 5805 000021C0 751C <1> jnz short TR_EX 5806 000021C2 8A45FD <1> mov al, [CMD_BLOCK+5] ; SELECT DRIVE 5807 000021C5 668B15[425C0000] <1> mov dx, [HF_PORT] 5808 000021CC 80C206 <1> add dl,6 5809 000021CF EE <1> out dx, al 5810 000021D0 E834010000 <1> call CHECK_ST ; CHECK STATUS ONLY 5811 000021D5 7507 <1> jnz short TR_EX 5812 000021D7 C605[BB610000]00 <1> mov byte [DISK_STATUS1], 0 ; WIPE OUT DATA CORRECTED ERROR 5813 <1> TR_EX: 5814 000021DE C3 <1> retn 5815 <1> 5816 <1> ;---------------------------------------- 5817 <1> ; RECALIBRATE (AH = 11H) : 5818 <1> ;---------------------------------------- 5819 <1> 5820 <1> HDISK_RECAL: 5821 000021DF C645FE10 <1> mov byte [CMD_BLOCK+6], RECAL_CMD ; 10h, 16 5822 000021E3 E82D000000 <1> call COMMAND ; START THE OPERATION 5823 000021E8 7523 <1> jnz short RECAL_EXIT ; ERROR 5824 000021EA E898000000 <1> call _WAIT ; WAIT FOR COMPLETION 5825 000021EF 7407 <1> jz short RECAL_X ; TIME OUT ONE OK ? 5826 000021F1 E891000000 <1> call _WAIT ; WAIT FOR COMPLETION LONGER 5827 000021F6 7515 <1> jnz short RECAL_EXIT ; TIME OUT TWO TIMES IS ERROR 5828 <1> RECAL_X: 5829 000021F8 E8A6FFFFFF <1> call CHECK_STATUS 5830 000021FD 803D[BB610000]40 <1> cmp byte [DISK_STATUS1], BAD_SEEK ; SEEK NOT COMPLETE 5831 00002204 7507 <1> jne short RECAL_EXIT ; IS OK 5832 00002206 C605[BB610000]00 <1> mov byte [DISK_STATUS1], 0 5833 <1> RECAL_EXIT: 5834 0000220D 803D[BB610000]00 <1> cmp byte [DISK_STATUS1], 0 5835 00002214 C3 <1> retn 5836 <1> 5837 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5838 <1> 5839 <1> ;-------------------------------------------------------- 5840 <1> ; COMMAND : 5841 <1> ; THIS ROUTINE OUTPUTS THE COMMAND BLOCK : 5842 <1> ; OUTPUT : 5843 <1> ; BL = STATUS : 5844 <1> ; BH = ERROR REGISTER : 5845 <1> ;-------------------------------------------------------- 5846 <1> 5847 <1> COMMAND: 5848 <1> ;push ebx ; 10/07/2022 ; WAIT FOR SEEK COMPLETE AND READY 5849 <1> ;;mov ecx, DELAY_2 ; SET INITIAL DELAY BEFORE TEST 5850 <1> COMMAND1: 5851 <1> ;;push ecx ; SAVE LOOP COUNT 5852 00002215 E8A1FFFFFF <1> call TST_RDY ; CHECK DRIVE READY 5853 <1> ;;pop ecx 5854 <1> ;pop ebx ; 10/07/2022 5855 0000221A 7418 <1> jz short COMMAND2 ; DRIVE IS READY 5856 0000221C 803D[BB610000]80 <1> cmp byte [DISK_STATUS1], TIME_OUT ; TST_RDY TIMED OUT--GIVE UP 5857 <1> ;jz short CMD_TIMEOUT 5858 <1> ;;loop COMMAND1 ; KEEP TRYING FOR A WHILE 5859 <1> ;jmp short COMMAND4 ; ITS NOT GOING TO GET READY 5860 00002223 7507 <1> jne short COMMAND4 5861 <1> CMD_TIMEOUT: 5862 00002225 C605[BB610000]20 <1> mov byte [DISK_STATUS1], BAD_CNTLR 5863 <1> COMMAND4: 5864 <1> ;;pop ebx ; 10/07/2022 5865 0000222C 803D[BB610000]00 <1> cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5866 00002233 C3 <1> retn 5867 <1> COMMAND2: 5868 <1> ;;pop ebx ; 10/07/2022 5869 <1> ;push edi ; 10/07/2022 5870 00002234 C605[B6610000]00 <1> mov byte [HF_INT_FLAG], 0 ; RESET INTERRUPT FLAG 5871 0000223B FA <1> cli ; INHIBIT INTERRUPTS WHILE CHANGING MASK 5872 0000223C E4A1 <1> in al, INTB01 ; TURN ON SECOND INTERRUPT CHIP 5873 <1> ;and al, 0BFh 5874 0000223E 243F <1> and al, 3Fh ; Enable IRQ 14 & 15 5875 <1> ;JMP $+2 5876 <1> IODELAY 2191 00002240 EB00 <2> jmp short $+2 2192 00002242 EB00 <2> jmp short $+2 5877 00002244 E6A1 <1> out INTB01, al 5878 00002246 E421 <1> in al, INTA01 ; LET INTERRUPTS PASS THRU TO 5879 00002248 24FB <1> and al, 0FBh ; SECOND CHIP 5880 <1> ;JMP $+2 5881 <1> IODELAY 2191 0000224A EB00 <2> jmp short $+2 2192 0000224C EB00 <2> jmp short $+2 5882 0000224E E621 <1> out INTA01, al 5883 00002250 FB <1> sti 5884 <1> ;xor edi, edi ; INDEX THE COMMAND TABLE 5885 <1> ; 10/07/2022 5886 00002251 31C9 <1> xor ecx, ecx 5887 <1> ;mov dx, HF_PORT+1 ; DISK ADDRESS 5888 00002253 668B15[425C0000] <1> mov dx, [HF_PORT] 5889 0000225A FEC2 <1> inc dl 5890 0000225C F605[BD610000]C0 <1> test byte [CONTROL_BYTE], 0C0h ; CHECK FOR RETRY SUPPRESSION 5891 00002263 7411 <1> jz short COMMAND3 5892 00002265 8A45FE <1> mov al, [CMD_BLOCK+6] ; YES-GET OPERATION CODE 5893 00002268 24F0 <1> and al, 0F0h ; GET RID OF MODIFIERS 5894 0000226A 3C20 <1> cmp al, 20h ; 20H-40H IS READ, WRITE, VERIFY 5895 0000226C 7208 <1> jb short COMMAND3 5896 0000226E 3C40 <1> cmp al, 40h 5897 00002270 7704 <1> ja short COMMAND3 5898 00002272 804DFE01 <1> or byte [CMD_BLOCK+6], NO_RETRIES 5899 <1> ; VALID OPERATION FOR RETRY SUPPRESS 5900 <1> COMMAND3: 5901 <1> ;mov al, [CMD_BLOCK+edi] ; GET THE COMMAND STRING BYTE 5902 <1> ; 10/07/2022 5903 00002276 8A440DF8 <1> mov al, [CMD_BLOCK+ecx] 5904 0000227A EE <1> out dx, al ; GIVE IT TO CONTROLLER 5905 <1> IODELAY 2191 0000227B EB00 <2> jmp short $+2 2192 0000227D EB00 <2> jmp short $+2 5906 <1> ;inc edi ; NEXT BYTE IN COMMAND BLOCK 5907 <1> ; 10/07/2022 5908 0000227F 41 <1> inc ecx 5909 <1> ;inc dx ; NEXT DISK ADAPTER REGISTER 5910 00002280 42 <1> inc edx ; 10/07/2022 5911 <1> ;cmp di, 7 ; 01/01/2015 ; ALL DONE? 5912 <1> ;jne short COMMAND3 ; NO--GO DO NEXT ONE 5913 00002281 80F907 <1> cmp cl, 7 ; 10/07/2022 5914 00002284 72F0 <1> jb short COMMAND3 5915 <1> ;pop edi ; 10/07/2022 5916 00002286 C3 <1> retn ; ZERO FLAG IS SET 5917 <1> 5918 <1> ;CMD_TIMEOUT: 5919 <1> ; mov byte [DISK_STATUS1], BAD_CNTLR 5920 <1> ;COMMAND4: 5921 <1> ; pop ebx 5922 <1> ; cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5923 <1> ; retn 5924 <1> 5925 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5926 <1> 5927 <1> ;---------------------------------------- 5928 <1> ; WAIT FOR INTERRUPT : 5929 <1> ;---------------------------------------- 5930 <1> ;WAIT: 5931 <1> _WAIT: 5932 00002287 FB <1> sti ; MAKE SURE INTERRUPTS ARE ON 5933 <1> ;sub cx, cx ; SET INITIAL DELAY BEFORE TEST 5934 <1> ;clc 5935 <1> ;mov ax, 9000h ; DEVICE WAIT INTERRUPT 5936 <1> ;int 15h 5937 <1> ;jc short WT2 ; DEVICE TIMED OUT 5938 <1> ;mov bl, DELAY_1 ; SET DELAY COUNT 5939 <1> 5940 <1> ;mov bl, WAIT_HDU_INT_HI 5941 <1> ;; 21/02/2015 5942 <1> ;;mov bl, WAIT_HDU_INT_HI + 1 5943 <1> ;;mov cx, WAIT_HDU_INT_LO 5944 00002288 B915160500 <1> mov ecx, WAIT_HDU_INT_LH 5945 <1> ; (AWARD BIOS -> WAIT_FOR_MEM) 5946 <1> ;----- WAIT LOOP 5947 <1> 5948 <1> WT1: 5949 <1> ;test byte [HF_INT_FLAG], 80h ; TEST FOR INTERRUPT 5950 0000228D F605[B6610000]C0 <1> test byte [HF_INT_FLAG], 0C0h 5951 <1> ;loopz WT1 5952 00002294 7512 <1> jnz short WT3 ; INTERRUPT--LETS GO 5953 <1> ;dec bl 5954 <1> ;jnz short WT1 ; KEEP TRYING FOR A WHILE 5955 <1> 5956 <1> WT1_hi: 5957 00002296 E461 <1> in al, SYS1 ; 61h (PORT_B) ; wait for lo to hi 5958 00002298 A810 <1> test al, 10h ; transition on memory 5959 0000229A 75FA <1> jnz short WT1_hi ; refresh. 5960 <1> WT1_lo: 5961 0000229C E461 <1> in al, SYS1 ; 061h (PORT_B) 5962 0000229E A810 <1> test al, 10h 5963 000022A0 74FA <1> jz short WT1_lo 5964 000022A2 E2E9 <1> loop WT1 5965 <1> ;;or bl, bl 5966 <1> ;;jz short WT2 5967 <1> ;;dec bl 5968 <1> ;;jmp short WT1 5969 <1> ;dec bl 5970 <1> ;jnz short WT1 5971 <1> WT2: 5972 <1> ; 10/07/2022 5973 <1> ;mov byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR 5974 000022A4 B080 <1> mov al, TIME_OUT 5975 000022A6 EB07 <1> jmp short WT4 5976 <1> WT3: 5977 <1> ;mov byte [DISK_STATUS1], 0 5978 <1> ;mov byte [HF_INT_FLAG], 0 5979 000022A8 28C0 <1> sub al, al ; 0 5980 000022AA A2[B6610000] <1> mov byte [HF_INT_FLAG], al 5981 <1> WT4: 5982 <1> NB2: 5983 000022AF A2[BB610000] <1> mov byte [DISK_STATUS1], al 5984 <1> 5985 <1> ;cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 5986 000022B4 20C0 <1> and al, al 5987 <1> ; zf = 0 -> time out, zf = 1 -> ok 5988 000022B6 C3 <1> retn 5989 <1> 5990 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 5991 <1> 5992 <1> ;---------------------------------------- 5993 <1> ; WAIT FOR CONTROLLER NOT BUSY : 5994 <1> ;---------------------------------------- 5995 <1> NOT_BUSY: 5996 000022B7 FB <1> sti ; MAKE SURE INTERRUPTS ARE ON 5997 <1> ;push ebx 5998 <1> ;sub cx, cx ; SET INITIAL DELAY BEFORE TEST 5999 000022B8 668B15[425C0000] <1> mov dx, [HF_PORT] 6000 000022BF 80C207 <1> add dl, 7 ; Status port (HF_PORT+7) 6001 <1> ;mov bl, DELAY_1 6002 <1> ; wait for 10 seconds 6003 <1> ;mov cx, WAIT_HDU_INT_LO ; 1615h 6004 <1> ;;mov bl, WAIT_HDU_INT_HI ; 05h 6005 <1> ;mov bl, WAIT_HDU_INT_HI + 1 6006 000022C2 B915160500 <1> mov ecx, WAIT_HDU_INT_LH ; 21/02/2015 6007 <1> ; 6008 <1> ;;mov byte [wait_count], 0 ; Reset wait counter 6009 <1> NB1: 6010 000022C7 EC <1> in al, dx ; CHECK STATUS 6011 <1> ;test al, ST_BUSY 6012 000022C8 2480 <1> and al, ST_BUSY 6013 <1> ;loopnz NB1 6014 000022CA 74E3 <1> jz short NB2 ; al = 0 ; NOT BUSY--LETS GO 6015 <1> ;dec bl 6016 <1> ;jnz short NB1 ; KEEP TRYING FOR A WHILE 6017 <1> 6018 <1> NB1_hi: 6019 000022CC E461 <1> in al, SYS1 ; wait for hi to lo 6020 000022CE A810 <1> test al, 010h ; transition on memory 6021 000022D0 75FA <1> jnz short NB1_hi ; refresh. 6022 <1> NB1_lo: 6023 000022D2 E461 <1> in al, SYS1 6024 000022D4 A810 <1> test al, 010h 6025 000022D6 74FA <1> jz short NB1_lo 6026 000022D8 E2ED <1> loop NB1 6027 <1> ;dec bl 6028 <1> ;jnz short NB1 6029 <1> ; 6030 <1> ;;cmp byte [wait_count], 182 ; 10 seconds (182 timer ticks) 6031 <1> ;;jb short NB1 6032 <1> ; 6033 <1> ;mov byte [DISK_STATUS1], TIME_OUT ; REPORT TIME OUT ERROR 6034 <1> ;jmp short NB3 6035 000022DA B080 <1> mov al, TIME_OUT 6036 <1> ;NB2: 6037 000022DC EBD1 <1> jmp short NB2 ; 10/07/2022 6038 <1> 6039 <1> ; ;mov byte [DISK_STATUS1], 0 6040 <1> ;;NB3: 6041 <1> ; ;pop ebx 6042 <1> ; mov [DISK_STATUS1], al ;;; will be set after return 6043 <1> ; ;cmp byte [DISK_STATUS1], 0 ; SET CONDITION CODE FOR CALLER 6044 <1> ; or al, al ; (zf = 0 --> timeout) 6045 <1> ; retn 6046 <1> 6047 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6048 <1> 6049 <1> ;---------------------------------------- 6050 <1> ; WAIT FOR DATA REQUEST : 6051 <1> ;---------------------------------------- 6052 <1> WAIT_DRQ: 6053 <1> ;mov cx, DELAY_3 6054 <1> ;mov dx, HF_PORT+7 6055 000022DE 668B15[425C0000] <1> mov dx, [HF_PORT] 6056 000022E5 80C207 <1> add dl, 7 6057 <1> ;;mov bl, WAIT_HDU_DRQ_HI ; 0 6058 <1> ;mov cx, WAIT_HDU_DRQ_LO ; 1000 (30 milli seconds) 6059 <1> ; (but it is written as 2000 6060 <1> ; micro seconds in ATORGS.ASM file 6061 <1> ; of Award Bios - 1999, D1A0622) 6062 000022E8 B9E8030000 <1> mov ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 6063 <1> WQ_1: 6064 000022ED EC <1> in al, dx ; GET STATUS 6065 000022EE A808 <1> test al, ST_DRQ ; WAIT FOR DRQ 6066 000022F0 7516 <1> jnz short WQ_OK 6067 <1> ;loop WQ_1 ; KEEP TRYING FOR A SHORT WHILE 6068 <1> WQ_hi: 6069 000022F2 E461 <1> in al, SYS1 ; wait for hi to lo 6070 000022F4 A810 <1> test al, 010h ; transition on memory 6071 000022F6 75FA <1> jnz short WQ_hi ; refresh. 6072 <1> WQ_lo: 6073 000022F8 E461 <1> in al, SYS1 6074 000022FA A810 <1> test al, 010h 6075 000022FC 74FA <1> jz short WQ_lo 6076 000022FE E2ED <1> loop WQ_1 6077 <1> 6078 00002300 C605[BB610000]80 <1> mov byte [DISK_STATUS1], TIME_OUT ; ERROR 6079 00002307 F9 <1> stc 6080 <1> WQ_OK: 6081 00002308 C3 <1> retn 6082 <1> ;WQ_OK: 6083 <1> ;clc 6084 <1> ;retn 6085 <1> 6086 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6087 <1> 6088 <1> ;---------------------------------------- 6089 <1> ; CHECK FIXED DISK STATUS BYTE : 6090 <1> ;---------------------------------------- 6091 <1> CHECK_ST: 6092 <1> ;mov dx, HF_PORT+7 ; GET THE STATUS 6093 00002309 668B15[425C0000] <1> mov dx, [HF_PORT] 6094 00002310 80C207 <1> add dl, 7 6095 00002313 EC <1> in al, dx 6096 00002314 A2[B5610000] <1> mov [HF_STATUS], al 6097 <1> ;mov ah, 0 6098 00002319 28E4 <1> sub ah, ah ; 0 6099 0000231B A880 <1> test al, ST_BUSY ; IF STILL BUSY 6100 0000231D 751A <1> jnz short CKST_EXIT ; REPORT OK 6101 0000231F B4CC <1> mov ah, WRITE_FAULT 6102 00002321 A820 <1> test al, ST_WRT_FLT ; CHECK FOR WRITE FAULT 6103 00002323 7514 <1> jnz short CKST_EXIT 6104 00002325 B4AA <1> mov ah, NOT_RDY 6105 00002327 A840 <1> test al, ST_READY ; CHECK FOR NOT READY 6106 00002329 740E <1> jz short CKST_EXIT 6107 0000232B B440 <1> mov ah, BAD_SEEK 6108 0000232D A810 <1> test al, ST_SEEK_COMPL ; CHECK FOR SEEK NOT COMPLETE 6109 0000232F 7408 <1> jz short CKST_EXIT 6110 00002331 B411 <1> mov ah, DATA_CORRECTED 6111 00002333 A804 <1> test al, ST_CORRCTD ; CHECK FOR CORRECTED ECC 6112 00002335 7502 <1> jnz short CKST_EXIT 6113 <1> ;mov ah, 0 6114 00002337 30E4 <1> xor ah, ah ; 0 6115 <1> CKST_EXIT: 6116 00002339 8825[BB610000] <1> mov [DISK_STATUS1], ah ; SET ERROR FLAG 6117 0000233F 80FC11 <1> cmp ah, DATA_CORRECTED ; KEEP GOING WITH DATA CORRECTED 6118 00002342 7402 <1> je short CKST_EX1 6119 <1> ;cmp ah, 0 6120 00002344 20E4 <1> and ah, ah 6121 <1> CKST_EX1: 6122 00002346 C3 <1> retn 6123 <1> 6124 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6125 <1> 6126 <1> ;---------------------------------------- 6127 <1> ; CHECK FIXED DISK ERROR REGISTER : 6128 <1> ;---------------------------------------- 6129 <1> CHECK_ER: 6130 <1> ;mov dx, HF_PORT+1 ; GET THE ERROR REGISTER 6131 00002347 668B15[425C0000] <1> mov dx, [HF_PORT] ; 6132 0000234E FEC2 <1> inc dl 6133 00002350 EC <1> in al, dx 6134 <1> ; 10/07/2022 6135 <1> ;mov [HF_ERROR], al 6136 <1> ;push ebx ; 21/02/2015 6137 00002351 29C9 <1> sub ecx, ecx 6138 <1> ;mov ecx, 8 ; TEST ALL 8 BITS 6139 00002353 B108 <1> mov cl, 8 6140 <1> CK1: 6141 00002355 D0E0 <1> shl al, 1 ; MOVE NEXT ERROR BIT TO CARRY 6142 00002357 7202 <1> jc short CK2 ; FOUND THE ERROR 6143 00002359 E2FA <1> loop CK1 ; KEEP TRYING 6144 <1> CK2: 6145 <1> ;mov ebx, ERR_TBL ; COMPUTE ADDRESS OF 6146 <1> ;add ebx, ecx ; ERROR CODE 6147 0000235B 81C1[385C0000] <1> add ecx, ERR_TBL ; 10/07/2022 6148 <1> 6149 <1> ;;;mov ah, byte [cs:bx] ; GET ERROR CODE 6150 <1> ;;mov ah, [bx] 6151 <1> ;mov ah, [ebx] ; 21/02/2015 6152 00002361 8A21 <1> mov ah, [ecx] 6153 <1> CKEX: 6154 00002363 8825[BB610000] <1> mov [DISK_STATUS1], ah ; SAVE ERROR CODE 6155 <1> ; 10/07/2022 6156 <1> ;pop ebx 6157 <1> ;;cmp ah, 0 6158 <1> ;and ah, ah 6159 00002369 C3 <1> retn 6160 <1> 6161 <1> ;-------------------------------------------------------- 6162 <1> ; CHECK_DMA : 6163 <1> ; -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL : 6164 <1> ; FIT WITHOUT SEGMENT OVERFLOW. : 6165 <1> ; -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X : 6166 <1> ; -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE) : 6167 <1> ; -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H) : 6168 <1> ; -ERROR OTHERWISE : 6169 <1> ;-------------------------------------------------------- 6170 <1> 6171 <1> ; 11/07/2022 6172 <1> ; (not needed for hard disks and 32 bit OS) 6173 <1> ; 6174 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6175 <1> ;CHECK_DMA: 6176 <1> ; ;;push ax ; SAVE REGISTERS 6177 <1> ; ;; 24/12/2021 6178 <1> ; ;;push eax 6179 <1> ; ;mov ax, 8000h ; AH = MAX # SECTORS 6180 <1> ; ; AL = MAX OFFSET 6181 <1> ; ; 10/07/2022 6182 <1> ; ;test byte [CMD_BLOCK+6], ECC_MODE 6183 <1> ; ;jz short CKD1 6184 <1> ; ;mov ax, 7F04h ; ECC IS 4 MORE BYTES 6185 <1> ;CKD1: 6186 <1> ; ;cmp ah, [CMD_BLOCK+1] ; NUMBER OF SECTORS 6187 <1> ; ;ja short CKDOK ; IT WILL FIT 6188 <1> ; ;jb short CKDERR ; TOO MANY 6189 <1> ; 6190 <1> ; cmp byte [CMD_BLOCK+1], 80h 6191 <1> ; jb short CKDOK 6192 <1> ; ja short CKDERR 6193 <1> ; ;cmp al, bl ; CHECK OFFSET ON MAX SECTORS 6194 <1> ; ;jb short CKDERR ; ERROR 6195 <1> ;CKD2: 6196 <1> ; or bl, bl 6197 <1> ; jz short CKDR 6198 <1> ; 6199 <1> ;;CKDOK: 6200 <1> ; ;clc ; CLEAR CARRY 6201 <1> ; ;;pop ax 6202 <1> ; ;; 24/12/2021 6203 <1> ; ;pop eax 6204 <1> ; ;retn ; NORMAL RETURN 6205 <1> ;CKDERR: 6206 <1> ; stc ; INDICATE ERROR 6207 <1> ; mov byte [DISK_STATUS1], DMA_BOUNDARY 6208 <1> ; ;;pop ax 6209 <1> ; ;; 24/12/2021 6210 <1> ; ;pop eax 6211 <1> ; retn 6212 <1> ; 6213 <1> ; ; 10/07/2022 6214 <1> ;CKDOK: 6215 <1> ; clc 6216 <1> ;CKDR: 6217 <1> ; retn 6218 <1> 6219 <1> ;---------------------------------------- 6220 <1> ; SET UP EBX-> DISK PARMS : 6221 <1> ;---------------------------------------- 6222 <1> 6223 <1> ; INPUT -> DL = 0 based drive number 6224 <1> ; OUTPUT -> EBX = disk parameter table address 6225 <1> 6226 <1> ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 6227 <1> 6228 <1> GET_VEC: 6229 <1> ;sub ax, ax ; GET DISK PARAMETER ADDRESS 6230 <1> ;mov es, ax 6231 <1> ;test dl, 1 6232 <1> ;jz short GV_0 6233 <1> ; les bx, [HF1_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 6234 <1> ; jmp short GV_EXIT 6235 <1> ;GV_0: 6236 <1> ; les bx,[HF_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 6237 <1> ; 6238 0000236A 31DB <1> xor ebx, ebx 6239 0000236C 88D3 <1> mov bl, dl 6240 <1> ;02/01/2015 6241 <1> ;xor bh, bh 6242 <1> ;shl bl, 1 ; port address offset 6243 <1> ;mov ax, [bx+hd_ports] ; Base port address (1F0h, 170h) 6244 <1> ;shl bl, 1 ; dpt pointer offset 6245 0000236E C0E302 <1> shl bl, 2 6246 <1> ;add bx, HF_TBL_VEC ; Disk parameter table pointer 6247 00002371 81C3[C0610000] <1> add ebx, HF_TBL_VEC ; 21/02/2015 6248 <1> ;push word [bx+2] ; dpt segment 6249 <1> ;pop es 6250 <1> ;mov bx, [bx] ; dpt offset 6251 00002377 8B1B <1> mov ebx, [ebx] 6252 <1> ;GV_EXIT: 6253 00002379 C3 <1> retn 6254 <1> 6255 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 6256 <1> hdc1_int: ; 21/02/2015 6257 <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL 14 ) ---------------------- 6258 <1> ; : 6259 <1> ; FIXED DISK INTERRUPT ROUTINE : 6260 <1> ; : 6261 <1> ;---------------------------------------------------------------- 6262 <1> 6263 <1> ; 22/12/2014 6264 <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT) 6265 <1> ; '11/15/85' 6266 <1> ; AWARD BIOS 1999 (D1A0622) 6267 <1> ; Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1) 6268 <1> 6269 <1> ;int_76h: 6270 <1> HD_INT: 6271 <1> ;push ax 6272 <1> ; 24/12/2021 6273 0000237A 50 <1> push eax 6274 0000237B 1E <1> push ds 6275 <1> ;CALL DDS 6276 <1> ; 21/02/2015 (32 bit, 386 pm modification) 6277 0000237C 66B81000 <1> mov ax, KDATA 6278 00002380 8ED8 <1> mov ds, ax 6279 <1> ; 6280 <1> ;;MOV @HF_INT_FLAG, 0FFH ; ALL DONE 6281 <1> ;mov byte [CS:HF_INT_FLAG], 0FFh 6282 00002382 C605[B6610000]FF <1> mov byte [HF_INT_FLAG], 0FFh 6283 <1> ; 6284 <1> ;push dx 6285 <1> ; 24/12/2021 6286 00002389 52 <1> push edx 6287 0000238A 66BAF701 <1> mov dx, HDC1_BASEPORT+7 ; Status Register (1F7h) 6288 <1> ; Clear Controller 6289 <1> Clear_IRQ1415: ; (Award BIOS - 1999) 6290 0000238E EC <1> in al, dx ; 6291 <1> ;pop dx 6292 <1> ; 24/12/2021 6293 0000238F 5A <1> pop edx 6294 <1> NEWIODELAY 2196 00002390 E6EB <2> out 0EBh,al 6295 <1> ; 6296 00002392 B020 <1> mov al, EOI ; NON-SPECIFIC END OF INTERRUPT 6297 00002394 E6A0 <1> out INTB00, al ; FOR CONTROLLER #2 6298 <1> ;JMP $+2 ; WAIT 6299 <1> NEWIODELAY 2196 00002396 E6EB <2> out 0EBh,al 6300 00002398 E620 <1> out INTA00, al ; FOR CONTROLLER #1 6301 0000239A 1F <1> pop ds 6302 <1> ;sti ; RE-ENABLE INTERRUPTS 6303 <1> ;mov ax, 9100h ; DEVICE POST 6304 <1> ;int 15h ; INTERRUPT 6305 <1> irq15_iret: ; 25/02/2015 6306 <1> ;pop ax 6307 <1> ; 24/12/2021 6308 0000239B 58 <1> pop eax 6309 0000239C CF <1> iretd ; RETURN FROM INTERRUPT 6310 <1> 6311 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 6312 <1> hdc2_int: ; 21/02/2015 6313 <1> ;--- HARDWARE INT 77H ++ ( IRQ LEVEL 15 ) ---------------------- 6314 <1> ; : 6315 <1> ; FIXED DISK INTERRUPT ROUTINE : 6316 <1> ; : 6317 <1> ;---------------------------------------------------------------- 6318 <1> 6319 <1> ;int_77h: 6320 <1> HD1_INT: 6321 <1> ;push ax 6322 <1> ; 24/12/2021 6323 0000239D 50 <1> push eax 6324 <1> ; Check if that is a spurious IRQ (from slave PIC) 6325 <1> ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 6326 0000239E B00B <1> mov al, 0Bh ; In-Service Register 6327 000023A0 E6A0 <1> out 0A0h, al 6328 000023A2 EB00 <1> jmp short $+2 6329 000023A4 EB00 <1> jmp short $+2 6330 000023A6 E4A0 <1> in al, 0A0h 6331 000023A8 2480 <1> and al, 80h ; bit 7 (is it real IRQ 15 or fake?) 6332 000023AA 74EF <1> jz short irq15_iret ; Fake (spurious)IRQ, do not send EOI) 6333 <1> ; 6334 000023AC 1E <1> push ds 6335 <1> ;CALL DDS 6336 <1> ; 21/02/2015 (32 bit, 386 pm modification) 6337 000023AD 66B81000 <1> mov ax, KDATA 6338 000023B1 8ED8 <1> mov ds, ax 6339 <1> ; 6340 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 6341 <1> ;or byte [CS:HF_INT_FLAG], 0C0h 6342 000023B3 800D[B6610000]C0 <1> or byte [HF_INT_FLAG], 0C0h 6343 <1> ; 6344 <1> ;push dx 6345 <1> ; 24/12/2021 6346 000023BA 52 <1> push edx 6347 000023BB 66BA7701 <1> mov dx, HDC2_BASEPORT+7 ; Status Register (177h) 6348 <1> ; Clear Controller (Award BIOS 1999) 6349 000023BF EBCD <1> jmp short Clear_IRQ1415 6350 <1> 6351 <1> ;%include 'diskdata.inc' ; 11/03/2015 6352 <1> ;%include 'diskbss.inc' ; 11/03/2015 6353 <1> 6354 <1> ;//////////////////////////////////////////////////////////////////// 6355 <1> ;; END OF DISK I/O SYTEM /// 2111 %include 'memory.inc' ; 09/03/2015 2112 <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) 2113 <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.6) - MEMORY.INC 2114 <1> ; Last Modification: 17/07/2022 2115 <1> ; 2116 <1> ; Source code for NASM - Netwide Assembler (2.15) 2117 <1> 2118 <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) /////////////// 2119 <1> 2120 <1> ;;04/11/2014 (unix386.s) 2121 <1> ;PDE_A_PRESENT equ 1 ; Present flag for PDE 2122 <1> ;PDE_A_WRITE equ 2 ; Writable (write permission) flag 2123 <1> ;PDE_A_USER equ 4 ; User (non-system/kernel) page flag 2124 <1> ;; 2125 <1> ;PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 2126 <1> ;PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 2127 <1> ;PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 2128 <1> ;PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 2129 <1> 2130 <1> ; 27/04/2015 2131 <1> ; 09/03/2015 2132 <1> PAGE_SIZE equ 4096 ; page size in bytes 2133 <1> PAGE_SHIFT equ 12 ; page table shift count 2134 <1> PAGE_D_SHIFT equ 22 ; 12+10 ; page directory shift count 2135 <1> PAGE_OFF equ 0FFFh ; 12 bit byte offset in page frame 2136 <1> PTE_MASK equ 03FFh ; page table entry mask 2137 <1> PTE_DUPLICATED equ 200h ; duplicated page sign (AVL bit 0) 2138 <1> PDE_A_CLEAR equ 0F000h ; to clear PDE attribute bits 2139 <1> PTE_A_CLEAR equ 0F000h ; to clear PTE attribute bits 2140 <1> LOGIC_SECT_SIZE equ 512 ; logical sector size 2141 <1> ERR_MAJOR_PF equ 0E0h ; major error: page fault 2142 <1> ; 15/10/2016 (TRDOS 386 v2) 2143 <1> ERR_MINOR_IM equ 4 ;15/10/2016 (1->4); insufficient (out of) memory 2144 <1> ERR_MINOR_PV equ 6 ;15/10/2016 (3->6); protection violation 2145 <1> SWP_DISK_READ_ERR equ 40 2146 <1> SWP_DISK_NOT_PRESENT_ERR equ 41 2147 <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42 2148 <1> SWP_NO_FREE_SPACE_ERR equ 43 2149 <1> SWP_DISK_WRITE_ERR equ 44 2150 <1> SWP_NO_PAGE_TO_SWAP_ERR equ 45 2151 <1> PTE_A_ACCESS_BIT equ 5 ; Bit 5 (accessed flag) 2152 <1> SECTOR_SHIFT equ 3 ; sector shift (to convert page block number) 2153 <1> ; 10/06/2021 (Retro UNIX 386 v2) 2154 <1> ; 12/07/2016 (TRDOS 386 v2) 2155 <1> PTE_SHARED equ 400h ; AVL bit 1, direct memory access bit 2156 <1> ; (Indicates that the page is not allocated 2157 <1> ; for the process, it is a shared or system 2158 <1> ; page, it must not be deallocated!) 2159 <1> ; 14/12/2020 2160 <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.) 2161 <1> PDE_EXTERNAL equ 400h ; Page directory entry for external memory blocks 2162 <1> PTE_EXTERNAL equ 400h ; Allocated kernel pages for Linear Frame Buffer 2163 <1> ; (Out of memory allocation table) 2164 <1> ; 2165 <1> ;; Retro Unix 386 v1 - paging method/principles 2166 <1> ;; 2167 <1> ;; 10/10/2014 2168 <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES 2169 <1> ;; 2170 <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map 2171 <1> ;; (virtual address = physical address) 2172 <1> ;; KERNEL PAGE TABLES: 2173 <1> ;; Kernel page directory and all page tables are 2174 <1> ;; on memory as initialized, as equal to physical memory 2175 <1> ;; layout. Kernel pages can/must not be swapped out/in. 2176 <1> ;; 2177 <1> ;; what for: User pages may be swapped out, when accessing 2178 <1> ;; a page in kernel/system mode, if it would be swapped out, 2179 <1> ;; kernel would have to swap it in! But it is also may be 2180 <1> ;; in use by a user process. (In system/kernel mode 2181 <1> ;; kernel can access all memory pages even if they are 2182 <1> ;; reserved/allocated for user processes. Swap out/in would 2183 <1> ;; cause conflicts.) 2184 <1> ;; 2185 <1> ;; As result of these conditions, 2186 <1> ;; all kernel pages must be initialized as equal to 2187 <1> ;; physical layout for preventing page faults. 2188 <1> ;; Also, calling "allocate page" procedure after 2189 <1> ;; a page fault can cause another page fault (double fault) 2190 <1> ;; if all kernel page tables would not be initialized. 2191 <1> ;; 2192 <1> ;; [first_page] = Beginning of users space, as offset to 2193 <1> ;; memory allocation table. (double word aligned) 2194 <1> ;; 2195 <1> ;; [next_page] = first/next free space to be searched 2196 <1> ;; as offset to memory allocation table. (dw aligned) 2197 <1> ;; 2198 <1> ;; [last_page] = End of memory (users space), as offset 2199 <1> ;; to memory allocation table. (double word aligned) 2200 <1> ;; 2201 <1> ;; USER PAGE TABLES: 2202 <1> ;; Demand paging (& 'copy on write' allocation method) ... 2203 <1> ;; 'ready only' marked copies of the 2204 <1> ;; parent process's page table entries (for 2205 <1> ;; same physical memory). 2206 <1> ;; (A page will be copied to a new page after 2207 <1> ;; if it causes R/W page fault.) 2208 <1> ;; 2209 <1> ;; Every user process has own (different) 2210 <1> ;; page directory and page tables. 2211 <1> ;; 2212 <1> ;; Code starts at virtual address 0, always. 2213 <1> ;; (Initial value of EIP is 0 in user mode.) 2214 <1> ;; (Programs can be written/developed as simple 2215 <1> ;; flat memory programs.) 2216 <1> ;; 2217 <1> ;; MEMORY ALLOCATION STRATEGY: 2218 <1> ;; Memory page will be allocated by kernel only 2219 <1> ;; (in kernel/system mode only). 2220 <1> ;; * After a 2221 <1> ;; - 'not present' page fault 2222 <1> ;; - 'writing attempt on read only page' page fault 2223 <1> ;; * For loading (opening, reading) a file or disk/drive 2224 <1> ;; * As responce to 'allocate additional memory blocks' 2225 <1> ;; request by running process. 2226 <1> ;; * While creating a process, allocating a new buffer, 2227 <1> ;; new page tables etc. 2228 <1> ;; 2229 <1> ;; At first, 2230 <1> ;; - 'allocate page' procedure will be called; 2231 <1> ;, if it will return with a valid (>0) physical address 2232 <1> ;; (that means the relevant M.A.T. bit has been RESET) 2233 <1> ;; relevant memory page/block will be cleared (zeroed). 2234 <1> ;; - 'allocate page' will be called for allocating page 2235 <1> ;; directory, page table and running space (data/code). 2236 <1> ;; - every successful 'allocate page' call will decrease 2237 <1> ;; 'free_pages' count (pointer). 2238 <1> ;; - 'out of (insufficient) memory error' will be returned 2239 <1> ;; if 'free_pages' points to a ZERO. 2240 <1> ;; - swapping out and swapping in (if it is not a new page) 2241 <1> ;; procedures will be called as responce to 'out of memory' 2242 <1> ;; error except errors caused by attribute conflicts. 2243 <1> ;; (swapper functions) 2244 <1> ;; 2245 <1> ;; At second, 2246 <1> ;; - page directory entry will be updated then page table 2247 <1> ;; entry will be updated. 2248 <1> ;; 2249 <1> ;; MEMORY ALLOCATION TABLE FORMAT: 2250 <1> ;; - M.A.T. has a size according to available memory as 2251 <1> ;; follows: 2252 <1> ;; - 1 (allocation) bit per 1 page (4096 bytes) 2253 <1> ;; - a bit with value of 0 means allocated page 2254 <1> ;; - a bit with value of 1 means a free page 2255 <1> ;, - 'free_pages' pointer holds count of free pages 2256 <1> ;; depending on M.A.T. 2257 <1> ;; (NOTE: Free page count will not be checked 2258 <1> ;; again -on M.A.T.- after initialization. 2259 <1> ;; Kernel will trust on initial count.) 2260 <1> ;, - 'free_pages' count will be decreased by allocation 2261 <1> ;; and it will be increased by deallocation procedures. 2262 <1> ;; 2263 <1> ;; - Available memory will be calculated during 2264 <1> ;; the kernel's initialization stage (in real mode). 2265 <1> ;; Memory allocation table and kernel page tables 2266 <1> ;; will be formatted/sized as result of available 2267 <1> ;; memory calculation before paging is enabled. 2268 <1> ;; 2269 <1> ;; For 4GB Available/Present Memory: (max. possible memory size) 2270 <1> ;; - Memory Allocation Table size will be 128 KB. 2271 <1> ;; - Memory allocation for kernel page directory size 2272 <1> ;; is always 4 KB. (in addition to total allocation size 2273 <1> ;; for page tables) 2274 <1> ;; - Memory allocation for kernel page tables (1024 tables) 2275 <1> ;; is 4 MB (1024*4*1024 bytes). 2276 <1> ;; - User (available) space will be started 2277 <1> ;; at 6th MB of the memory (after 1MB+4MB). 2278 <1> ;; - The first 640 KB is for kernel's itself plus 2279 <1> ;; memory allocation table and kernel's page directory 2280 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 2281 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 2282 <1> ;; for buffers. 2283 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 2284 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 2285 <1> ;; - Kernel page tables start at 100000h (2nd MB) 2286 <1> ;; 2287 <1> ;; For 1GB Available Memory: 2288 <1> ;; - Memory Allocation Table size will be 32 KB. 2289 <1> ;; - Memory allocation for kernel page directory size 2290 <1> ;; is always 4 KB. (in addition to total allocation size 2291 <1> ;; for page tables) 2292 <1> ;; - Memory allocation for kernel page tables (256 tables) 2293 <1> ;; is 1 MB (256*4*1024 bytes). 2294 <1> ;; - User (available) space will be started 2295 <1> ;; at 3th MB of the memory (after 1MB+1MB). 2296 <1> ;; - The first 640 KB is for kernel's itself plus 2297 <1> ;; memory allocation table and kernel's page directory 2298 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 2299 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 2300 <1> ;; for buffers. 2301 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 2302 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 2303 <1> ;; - Kernel page tables start at 100000h (2nd MB). 2304 <1> ;; 2305 <1> ;; 2306 <1> 2307 <1> ;;************************************************************************************ 2308 <1> ;; 2309 <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle) 2310 <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015) 2311 <1> 2312 <1> ;; Main factor: "sys fork" system call 2313 <1> ;; 2314 <1> ;; FORK 2315 <1> ;; |----> parent - duplicated PTEs, read only pages 2316 <1> ;; writable pages ---->| 2317 <1> ;; |----> child - duplicated PTEs, read only pages 2318 <1> ;; 2319 <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 2320 <1> ;; 2321 <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set) 2322 <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9) 2323 <1> ;; -while R/W bit is 0-. 2324 <1> ;; 2325 <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process): 2326 <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 2327 <1> ;; as duplicated PTE bit -AVL bit 0, PTE bit 9- are reset/clear. 2328 <1> ;; # Then Parent's Page Table is copied to Child's Page Table. 2329 <1> ;; # Child's Page Table Entries are updated as duplicated child bit 2330 <1> ;; -AVL bit 0, PTE bit 9- is set. 2331 <1> ;; 2332 <1> ;; Duplicate page tables with read only pages (several sys fork system calls): 2333 <1> ;; # Parent's read only pages are copied to new child pages. 2334 <1> ;; Parent's PTE attributes are not changed. 2335 <1> ;; (Because, there is another parent-child fork before this fork! We must not 2336 <1> ;; destroy/mix previous fork result). 2337 <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 2338 <1> ;; read only pages) are set as writable (while duplicated PTE bit is clear). 2339 <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 2340 <1> ;; as read only, (while) duplicated PTE bit is reset (clear). 2341 <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 2342 <1> ;; as Child's Page Table Entries without copying actual page. 2343 <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 2344 <1> ;; pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set. 2345 <1> ;; 2346 <1> ;; !? WHAT FOR (duplication after duplication): 2347 <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init) 2348 <1> ;; program/executable code continues from specified location as child process, 2349 <1> ;; returns back previous code location as parent process, every child after 2350 <1> ;; every sys fork uses last image of code and data just prior the fork. 2351 <1> ;; Even if the parent code changes data, the child will not see the changed data 2352 <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB) 2353 <1> ;; was copied to child's process segment (all of code and data) according to 2354 <1> ;; original UNIX v1 which copies all of parent process code and data -core- 2355 <1> ;; to child space -core- but swaps that core image -of child- on to disk. 2356 <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core 2357 <1> ;; (complete running image of parent process) to the child process; 2358 <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 2359 <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork, 2360 <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes 2361 <1> ;; a new/fresh core -running space-, by clearing all code/data content). 2362 <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write 2363 <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 2364 <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and 2365 <1> ;; new/fresh pages will be used to load and run new executable/program. 2366 <1> ;; That is what for i have preferred "copy on write", "duplication" method 2367 <1> ;; for sharing same read only pages between parent and child processes. 2368 <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 2369 <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 2370 <1> ;; and it's child processes; otherwise parent process would destroy data belongs 2371 <1> ;; to its child or vice versa; or some pages would remain unclaimed 2372 <1> ;; -deallocation problem-. 2373 <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 2374 <1> ;; 2375 <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 2376 <1> ;; # Page fault handler will do those: 2377 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 2378 <1> ;; - If it is reset/clear, there is a child uses same page. 2379 <1> ;; - Parent's read only page -previous page- is copied to a new writable page. 2380 <1> ;; - Parent's PTE is updated as writable page, as unique page (AVL=0) 2381 <1> ;; - (Page fault handler whill check this PTE later, if child process causes to 2382 <1> ;; page fault due to write attempt on read only page. Of course, the previous 2383 <1> ;; read only page will be converted to writable and unique page which belongs 2384 <1> ;; to child process.) 2385 <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 2386 <1> ;; # Page fault handler will do those: 2387 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 2388 <1> ;; - If it is set, there is a parent uses -or was using- same page. 2389 <1> ;; - Same PTE address within parent's page table is checked if it has same page 2390 <1> ;; address or not. 2391 <1> ;; - If parent's PTE has same address, child will continue with a new writable page. 2392 <1> ;; Parent's PTE will point to same (previous) page as writable, unique (AVL=0). 2393 <1> ;; - If parent's PTE has different address, child will continue with it's 2394 <1> ;; own/same page but read only flag (0) will be changed to writable flag (1) and 2395 <1> ;; 'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 2396 <1> ;; 2397 <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables 2398 <1> ;; will be set as writable (and unique) in case of child process was using 2399 <1> ;; same pages with duplicated child PTE sign... Depending on sys fork and 2400 <1> ;; duplication method details, it is not possible multiple child processes 2401 <1> ;; were using same page with duplicated PTEs. 2402 <1> ;; 2403 <1> ;;************************************************************************************ 2404 <1> 2405 <1> ;; 08/10/2014 2406 <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft 2407 <1> ;; by Erdogan Tan (Based on KolibriOS 'memory.inc') 2408 <1> 2409 <1> ;; 'allocate_page' code is derived and modified from KolibriOS 2410 <1> ;; 'alloc_page' procedure in 'memory.inc' 2411 <1> ;; (25/08/2014, Revision: 5057) file 2412 <1> ;; by KolibriOS Team (2004-2012) 2413 <1> 2414 <1> allocate_page: 2415 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2416 <1> ; 01/07/2015 2417 <1> ; 05/05/2015 2418 <1> ; 30/04/2015 2419 <1> ; 16/10/2014 2420 <1> ; 08/10/2014 2421 <1> ; 09/09/2014 (Retro UNIX 386 v1 - beginning) 2422 <1> ; 2423 <1> ; INPUT -> none 2424 <1> ; 2425 <1> ; OUTPUT -> 2426 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 2427 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is RESET) 2428 <1> ; 2429 <1> ; CF = 1 and EAX = 0 2430 <1> ; if there is not a free page to be allocated 2431 <1> ; 2432 <1> ; Modified Registers -> none (except EAX) 2433 <1> ; 2434 000023C1 A1[30610000] <1> mov eax, [free_pages] 2435 000023C6 21C0 <1> and eax, eax 2436 000023C8 7438 <1> jz short out_of_memory 2437 <1> ; 2438 000023CA 53 <1> push ebx 2439 000023CB 51 <1> push ecx 2440 <1> ; 2441 000023CC BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table offset 2442 000023D1 89D9 <1> mov ecx, ebx 2443 <1> ; NOTE: 32 (first_page) is initial 2444 <1> ; value of [next_page]. 2445 <1> ; It points to the first available 2446 <1> ; page block for users (ring 3) ... 2447 <1> ; (MAT offset 32 = 1024/32) 2448 <1> ; (at the of the first 4 MB) 2449 000023D3 031D[34610000] <1> add ebx, [next_page] ; Free page searching starts from here 2450 <1> ; next_free_page >> 5 2451 000023D9 030D[38610000] <1> add ecx, [last_page] ; Free page searching ends here 2452 <1> ; (total_pages - 1) >> 5 2453 <1> al_p_scan: 2454 000023DF 39CB <1> cmp ebx, ecx 2455 000023E1 770A <1> ja short al_p_notfound 2456 <1> ; 2457 <1> ; 01/07/2015 2458 <1> ; AMD64 Architecture Programmer’s Manual 2459 <1> ; Volume 3: 2460 <1> ; General-Purpose and System Instructions 2461 <1> ; 2462 <1> ; BSF - Bit Scan Forward 2463 <1> ; 2464 <1> ; Searches the value in a register or a memory location 2465 <1> ; (second operand) for the least-significant set bit. 2466 <1> ; If a set bit is found, the instruction clears the zero flag (ZF) 2467 <1> ; and stores the index of the least-significant set bit in a destination 2468 <1> ; register (first operand). If the second operand contains 0, 2469 <1> ; the instruction sets ZF to 1 and does not change the contents of the 2470 <1> ; destination register. The bit index is an unsigned offset from bit 0 2471 <1> ; of the searched value 2472 <1> ; 2473 000023E3 0FBC03 <1> bsf eax, [ebx] ; Scans source operand for first bit set (1). 2474 <1> ; Clear ZF if a bit is found set (1) and 2475 <1> ; loads the destination with an index to 2476 <1> ; first set bit. (0 -> 31) 2477 <1> ; Sets ZF to 1 if no bits are found set. 2478 000023E6 751C <1> jnz short al_p_found ; ZF = 0 -> a free page has been found 2479 <1> ; 2480 <1> ; NOTE: a Memory Allocation Table bit 2481 <1> ; with value of 1 means 2482 <1> ; the corresponding page is free 2483 <1> ; (Retro UNIX 386 v1 feature only!) 2484 000023E8 83C304 <1> add ebx, 4 2485 <1> ; We return back for searching next page block 2486 <1> ; NOTE: [free_pages] is not ZERO; so, 2487 <1> ; we always will find at least 1 free page here. 2488 000023EB EBF2 <1> jmp short al_p_scan 2489 <1> ; 2490 <1> al_p_notfound: 2491 000023ED 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 2492 000023F3 890D[34610000] <1> mov [next_page], ecx ; next/first free page = last page 2493 <1> ; (deallocate_page procedure will change it) 2494 000023F9 31C0 <1> xor eax, eax 2495 000023FB A3[30610000] <1> mov [free_pages], eax ; 0 2496 00002400 59 <1> pop ecx 2497 00002401 5B <1> pop ebx 2498 <1> ; 2499 <1> ; 24/12/2021 2500 <1> ; ('swap_out' procedure call is disabled) 2501 <1> 2502 <1> out_of_memory: 2503 <1> ; call swap_out 2504 <1> ; jnc short al_p_ok ; [free_pages] = 0, re-allocation by swap_out 2505 <1> ; ; 2506 <1> ; sub eax, eax ; 0 2507 00002402 F9 <1> stc 2508 00002403 C3 <1> retn 2509 <1> 2510 <1> al_p_found: 2511 00002404 89D9 <1> mov ecx, ebx 2512 00002406 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 2513 0000240C 890D[34610000] <1> mov [next_page], ecx ; Set first free page searching start 2514 <1> ; address/offset (to the next) 2515 00002412 FF0D[30610000] <1> dec dword [free_pages] ; 1 page has been allocated (X = X-1) 2516 <1> ; 2517 00002418 0FB303 <1> btr [ebx], eax ; The destination bit indexed by the source value 2518 <1> ; is copied into the Carry Flag and then cleared 2519 <1> ; in the destination. 2520 <1> ; 2521 <1> ; Reset the bit which is corresponding to the 2522 <1> ; (just) allocated page. 2523 <1> ; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages) 2524 0000241B C1E103 <1> shl ecx, 3 ; (page block offset * 32) + page index 2525 0000241E 01C8 <1> add eax, ecx ; = page number 2526 00002420 C1E00C <1> shl eax, 12 ; physical address of the page (flat/real value) 2527 <1> ; EAX = physical address of memory page 2528 <1> ; 2529 <1> ; NOTE: The relevant page directory and page table entry will be updated 2530 <1> ; according to this EAX value... 2531 00002423 59 <1> pop ecx 2532 00002424 5B <1> pop ebx 2533 <1> al_p_ok: 2534 00002425 C3 <1> retn 2535 <1> 2536 <1> make_page_dir: 2537 <1> ; 18/04/2015 2538 <1> ; 12/04/2015 2539 <1> ; 23/10/2014 2540 <1> ; 16/10/2014 2541 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2542 <1> ; 2543 <1> ; INPUT -> 2544 <1> ; none 2545 <1> ; OUTPUT -> 2546 <1> ; (EAX = 0) 2547 <1> ; cf = 1 -> insufficient (out of) memory error 2548 <1> ; cf = 0 -> 2549 <1> ; u.pgdir = page directory (physical) address of the current 2550 <1> ; process/user. 2551 <1> ; 2552 <1> ; Modified Registers -> EAX 2553 <1> ; 2554 00002426 E896FFFFFF <1> call allocate_page 2555 0000242B 7216 <1> jc short mkpd_error 2556 <1> ; 2557 0000242D A3[45650000] <1> mov [u.pgdir], eax ; Page dir address for current user/process 2558 <1> ; (Physical address) 2559 <1> clear_page: 2560 <1> ; 18/04/2015 2561 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2562 <1> ; 2563 <1> ; INPUT -> 2564 <1> ; EAX = physical address of the page 2565 <1> ; OUTPUT -> 2566 <1> ; all bytes of the page will be cleared 2567 <1> ; 2568 <1> ; Modified Registers -> none 2569 <1> ; 2570 00002432 57 <1> push edi 2571 00002433 51 <1> push ecx 2572 00002434 50 <1> push eax 2573 00002435 B900040000 <1> mov ecx, PAGE_SIZE / 4 2574 0000243A 89C7 <1> mov edi, eax 2575 0000243C 31C0 <1> xor eax, eax 2576 0000243E F3AB <1> rep stosd 2577 00002440 58 <1> pop eax 2578 00002441 59 <1> pop ecx 2579 00002442 5F <1> pop edi 2580 <1> mkpd_error: 2581 <1> mkpt_error: 2582 00002443 C3 <1> retn 2583 <1> 2584 <1> make_page_table: 2585 <1> ; 23/06/2015 2586 <1> ; 18/04/2015 2587 <1> ; 12/04/2015 2588 <1> ; 16/10/2014 2589 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 2590 <1> ; 2591 <1> ; INPUT -> 2592 <1> ; EBX = virtual (linear) address 2593 <1> ; ECX = page table attributes (lower 12 bits) 2594 <1> ; (higher 20 bits must be ZERO) 2595 <1> ; (bit 0 must be 1) 2596 <1> ; u.pgdir = page directory (physical) address 2597 <1> ; OUTPUT -> 2598 <1> ; EDX = Page directory entry address 2599 <1> ; EAX = Page table address 2600 <1> ; cf = 1 -> insufficient (out of) memory error 2601 <1> ; cf = 0 -> page table address in the PDE (EDX) 2602 <1> ; 2603 <1> ; Modified Registers -> EAX, EDX 2604 <1> ; 2605 00002444 E878FFFFFF <1> call allocate_page 2606 00002449 72F8 <1> jc short mkpt_error 2607 0000244B E811000000 <1> call set_pde 2608 00002450 EBE0 <1> jmp short clear_page 2609 <1> 2610 <1> make_page: 2611 <1> ; 24/07/2015 2612 <1> ; 23/06/2015 ; (Retro UNIX 386 v1 - beginning) 2613 <1> ; 2614 <1> ; INPUT -> 2615 <1> ; EBX = virtual (linear) address 2616 <1> ; ECX = page attributes (lower 12 bits) 2617 <1> ; (higher 20 bits must be ZERO) 2618 <1> ; (bit 0 must be 1) 2619 <1> ; u.pgdir = page directory (physical) address 2620 <1> ; OUTPUT -> 2621 <1> ; EBX = Virtual address 2622 <1> ; (EDX = PTE value) 2623 <1> ; EAX = Physical address 2624 <1> ; cf = 1 -> insufficient (out of) memory error 2625 <1> ; 2626 <1> ; Modified Registers -> EAX, EDX 2627 <1> ; 2628 00002452 E86AFFFFFF <1> call allocate_page 2629 00002457 7207 <1> jc short mkp_err 2630 00002459 E821000000 <1> call set_pte 2631 0000245E 73D2 <1> jnc short clear_page ; 18/04/2015 2632 <1> mkp_err: 2633 00002460 C3 <1> retn 2634 <1> 2635 <1> set_pde: ; Set page directory entry (PDE) 2636 <1> ; 20/07/2015 2637 <1> ; 18/04/2015 2638 <1> ; 12/04/2015 2639 <1> ; 23/10/2014 2640 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2641 <1> ; 2642 <1> ; INPUT -> 2643 <1> ; EAX = physical address 2644 <1> ; (use present value if EAX = 0) 2645 <1> ; EBX = virtual (linear) address 2646 <1> ; ECX = page table attributes (lower 12 bits) 2647 <1> ; (higher 20 bits must be ZERO) 2648 <1> ; (bit 0 must be 1) 2649 <1> ; u.pgdir = page directory (physical) address 2650 <1> ; OUTPUT -> 2651 <1> ; EDX = PDE address 2652 <1> ; EAX = page table address (physical) 2653 <1> ; ;(CF=1 -> Invalid page address) 2654 <1> ; 2655 <1> ; Modified Registers -> EDX 2656 <1> ; 2657 00002461 89DA <1> mov edx, ebx 2658 00002463 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 2659 00002466 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 2660 00002469 0315[45650000] <1> add edx, [u.pgdir] 2661 <1> ; 2662 0000246F 21C0 <1> and eax, eax 2663 00002471 7506 <1> jnz short spde_1 2664 <1> ; 2665 00002473 8B02 <1> mov eax, [edx] ; old PDE value 2666 <1> ;test al, 1 2667 <1> ;jz short spde_2 2668 00002475 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2669 <1> spde_1: 2670 <1> ;and cx, 0FFFh 2671 00002479 8902 <1> mov [edx], eax 2672 0000247B 66090A <1> or [edx], cx 2673 0000247E C3 <1> retn 2674 <1> ;spde_2: ; error 2675 <1> ; stc 2676 <1> ; retn 2677 <1> 2678 <1> set_pte: ; Set page table entry (PTE) 2679 <1> ; 24/07/2015 2680 <1> ; 20/07/2015 2681 <1> ; 23/06/2015 2682 <1> ; 18/04/2015 2683 <1> ; 12/04/2015 2684 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2685 <1> ; 2686 <1> ; INPUT -> 2687 <1> ; EAX = physical page address 2688 <1> ; (use present value if EAX = 0) 2689 <1> ; EBX = virtual (linear) address 2690 <1> ; ECX = page attributes (lower 12 bits) 2691 <1> ; (higher 20 bits must be ZERO) 2692 <1> ; (bit 0 must be 1) 2693 <1> ; u.pgdir = page directory (physical) address 2694 <1> ; OUTPUT -> 2695 <1> ; EAX = physical page address 2696 <1> ; (EDX = PTE value) 2697 <1> ; EBX = virtual address 2698 <1> ; 2699 <1> ; CF = 1 -> error 2700 <1> ; 2701 <1> ; Modified Registers -> EAX, EDX 2702 <1> ; 2703 0000247F 50 <1> push eax 2704 00002480 A1[45650000] <1> mov eax, [u.pgdir] ; 20/07/2015 2705 00002485 E837000000 <1> call get_pde 2706 <1> ; EDX = PDE address 2707 <1> ; EAX = PDE value 2708 0000248A 5A <1> pop edx ; physical page address 2709 0000248B 722A <1> jc short spte_err ; PDE not present 2710 <1> ; 2711 0000248D 53 <1> push ebx ; 24/07/2015 2712 0000248E 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2713 <1> ; EDX = PT address (physical) 2714 00002492 C1EB0C <1> shr ebx, PAGE_SHIFT ; 12 2715 00002495 81E3FF030000 <1> and ebx, PTE_MASK ; 03FFh 2716 <1> ; clear higher 10 bits (PD bits) 2717 0000249B C1E302 <1> shl ebx, 2 ; offset to page table (1024*4) 2718 0000249E 01C3 <1> add ebx, eax 2719 <1> ; 2720 000024A0 8B03 <1> mov eax, [ebx] ; Old PTE value 2721 000024A2 A801 <1> test al, 1 2722 000024A4 740C <1> jz short spte_0 2723 000024A6 09D2 <1> or edx, edx 2724 000024A8 750F <1> jnz short spte_1 2725 000024AA 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits 2726 000024AE 89C2 <1> mov edx, eax 2727 000024B0 EB09 <1> jmp short spte_2 2728 <1> spte_0: 2729 <1> ; If this PTE contains a swap (disk) address, 2730 <1> ; it can be updated by using 'swap_in' procedure 2731 <1> ; only! 2732 000024B2 21C0 <1> and eax, eax 2733 000024B4 7403 <1> jz short spte_1 2734 <1> ; 24/07/2015 2735 <1> ; swapped page ! (on disk) 2736 000024B6 5B <1> pop ebx 2737 <1> spte_err: 2738 000024B7 F9 <1> stc 2739 000024B8 C3 <1> retn 2740 <1> spte_1: 2741 000024B9 89D0 <1> mov eax, edx 2742 <1> spte_2: 2743 000024BB 09CA <1> or edx, ecx 2744 <1> ; 23/06/2015 2745 000024BD 8913 <1> mov [ebx], edx ; PTE value in EDX 2746 <1> ; 24/07/2015 2747 000024BF 5B <1> pop ebx 2748 000024C0 C3 <1> retn 2749 <1> 2750 <1> get_pde: ; Get present value of the relevant PDE 2751 <1> ; 20/07/2015 2752 <1> ; 18/04/2015 2753 <1> ; 12/04/2015 2754 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2755 <1> ; 2756 <1> ; INPUT -> 2757 <1> ; EBX = virtual (linear) address 2758 <1> ; EAX = page directory (physical) address 2759 <1> ; OUTPUT -> 2760 <1> ; EDX = Page directory entry address 2761 <1> ; EAX = Page directory entry value 2762 <1> ; CF = 1 -> PDE not present or invalid ? 2763 <1> ; Modified Registers -> EDX, EAX 2764 <1> ; 2765 000024C1 89DA <1> mov edx, ebx 2766 000024C3 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 (12+10) 2767 000024C6 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 2768 000024C9 01C2 <1> add edx, eax ; page directory address (physical) 2769 000024CB 8B02 <1> mov eax, [edx] 2770 000024CD A801 <1> test al, PDE_A_PRESENT ; page table is present or not ! 2771 000024CF 751F <1> jnz short gpte_retn 2772 000024D1 F9 <1> stc 2773 <1> gpde_retn: 2774 000024D2 C3 <1> retn 2775 <1> 2776 <1> get_pte: 2777 <1> ; Get present value of the relevant PTE 2778 <1> ; 29/07/2015 2779 <1> ; 20/07/2015 2780 <1> ; 18/04/2015 2781 <1> ; 12/04/2015 2782 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 2783 <1> ; 2784 <1> ; INPUT -> 2785 <1> ; EBX = virtual (linear) address 2786 <1> ; EAX = page directory (physical) address 2787 <1> ; OUTPUT -> 2788 <1> ; EDX = Page table entry address (if CF=0) 2789 <1> ; Page directory entry address (if CF=1) 2790 <1> ; (Bit 0 value is 0 if PT is not present) 2791 <1> ; EAX = Page table entry value (page address) 2792 <1> ; CF = 1 -> PDE not present or invalid ? 2793 <1> ; Modified Registers -> EAX, EDX 2794 <1> ; 2795 000024D3 E8E9FFFFFF <1> call get_pde 2796 000024D8 72F8 <1> jc short gpde_retn ; page table is not present 2797 <1> ;jnc short gpte_1 2798 <1> ;retn 2799 <1> ;gpte_1: 2800 000024DA 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 2801 000024DE 89DA <1> mov edx, ebx 2802 000024E0 C1EA0C <1> shr edx, PAGE_SHIFT ; 12 2803 000024E3 81E2FF030000 <1> and edx, PTE_MASK ; 03FFh 2804 <1> ; clear higher 10 bits (PD bits) 2805 000024E9 C1E202 <1> shl edx, 2 ; offset from start of page table (1024*4) 2806 000024EC 01C2 <1> add edx, eax 2807 000024EE 8B02 <1> mov eax, [edx] 2808 <1> gpte_retn: 2809 000024F0 C3 <1> retn 2810 <1> 2811 <1> deallocate_page_dir: 2812 <1> ; 15/09/2015 2813 <1> ; 05/08/2015 2814 <1> ; 30/04/2015 2815 <1> ; 28/04/2015 2816 <1> ; 17/10/2014 2817 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2818 <1> ; 2819 <1> ; INPUT -> 2820 <1> ; EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD) 2821 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 2822 <1> ; OUTPUT -> 2823 <1> ; All of page tables in the page directory 2824 <1> ; and page dir's itself will be deallocated 2825 <1> ; except 'read only' duplicated pages (will be converted 2826 <1> ; to writable pages). 2827 <1> ; 2828 <1> ; Modified Registers -> EAX 2829 <1> ; 2830 <1> ; 2831 000024F1 56 <1> push esi 2832 000024F2 51 <1> push ecx 2833 000024F3 50 <1> push eax 2834 000024F4 89C6 <1> mov esi, eax 2835 000024F6 31C9 <1> xor ecx, ecx 2836 <1> ; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB), 2837 <1> ; it must not be deallocated 2838 000024F8 890E <1> mov [esi], ecx ; 0 ; clear PDE 0 2839 <1> dapd_0: 2840 000024FA AD <1> lodsd 2841 000024FB A801 <1> test al, PDE_A_PRESENT ; bit 0, present flag (must be 1) 2842 000024FD 7409 <1> jz short dapd_1 2843 000024FF 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 2844 00002503 E812000000 <1> call deallocate_page_table 2845 <1> dapd_1: 2846 00002508 41 <1> inc ecx ; page directory entry index 2847 00002509 81F900040000 <1> cmp ecx, PAGE_SIZE / 4 ; 1024 2848 0000250F 72E9 <1> jb short dapd_0 2849 <1> dapd_2: 2850 00002511 58 <1> pop eax 2851 00002512 E870000000 <1> call deallocate_page ; deallocate the page dir's itself 2852 00002517 59 <1> pop ecx 2853 00002518 5E <1> pop esi 2854 00002519 C3 <1> retn 2855 <1> 2856 <1> deallocate_page_table: 2857 <1> ; 17/07/2022 2858 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2859 <1> ; 12/07/2016 (TRDOS 386 v2) 2860 <1> ; 19/09/2015 2861 <1> ; 15/09/2015 2862 <1> ; 05/08/2015 2863 <1> ; 30/04/2015 2864 <1> ; 28/04/2015 2865 <1> ; 24/10/2014 2866 <1> ; 23/10/2014 2867 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2868 <1> ; 2869 <1> ; INPUT -> 2870 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE 2871 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 2872 <1> ; (ECX = page directory entry index) 2873 <1> ; OUTPUT -> 2874 <1> ; All of pages in the page table and page table's itself 2875 <1> ; will be deallocated except 'read only' duplicated pages 2876 <1> ; (will be converted to writable pages). 2877 <1> ; 2878 <1> ; Modified Registers -> EAX 2879 <1> ; 2880 0000251A 56 <1> push esi 2881 0000251B 57 <1> push edi 2882 0000251C 52 <1> push edx 2883 0000251D 50 <1> push eax ; * 2884 0000251E 89C6 <1> mov esi, eax 2885 00002520 31FF <1> xor edi, edi ; 0 2886 <1> dapt_0: 2887 00002522 AD <1> lodsd 2888 00002523 A801 <1> test al, PTE_A_PRESENT ; bit 0, present flag (must be 1) 2889 00002525 7453 <1> jz short dapt_1 2890 <1> ; 2891 00002527 A802 <1> test al, PTE_A_WRITE ; bit 1, writable (r/w) flag 2892 <1> ; (must be 1) 2893 00002529 753D <1> jnz short dapt_3 2894 <1> ; Read only -duplicated- page (belongs to a parent or a child) 2895 0000252B 66A90002 <1> test ax, PTE_DUPLICATED ; Was this page duplicated 2896 <1> ; as child's page ? 2897 0000252F 7442 <1> jz short dapt_4 ; Clear PTE but don't deallocate the page! 2898 <1> ; check the parent's PTE value is read only & same page or not.. 2899 <1> ; ECX = page directory entry index (0-1023) 2900 00002531 53 <1> push ebx 2901 00002532 51 <1> push ecx 2902 <1> ;shl cx, 2 ; *4 2903 <1> ; 17/07/2022 2904 00002533 C1E102 <1> shl ecx, 2 2905 00002536 01CB <1> add ebx, ecx ; PDE offset (for the parent) 2906 00002538 8B0B <1> mov ecx, [ebx] 2907 0000253A F6C101 <1> test cl, PDE_A_PRESENT ; present (valid) or not ? 2908 0000253D 7427 <1> jz short dapt_2 ; parent process does not use this page 2909 0000253F 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 2910 <1> ; EDI = page table entry index (0-1023) 2911 00002544 89FA <1> mov edx, edi 2912 <1> ;shl dx, 2 ; *4 2913 <1> ; 17/07/2022 2914 00002546 C1E202 <1> shl edx, 2 2915 00002549 01CA <1> add edx, ecx ; PTE offset (for the parent) 2916 0000254B 8B1A <1> mov ebx, [edx] 2917 0000254D F6C301 <1> test bl, PTE_A_PRESENT ; present or not ? 2918 00002550 7414 <1> jz short dapt_2 ; parent process does not use this page 2919 00002552 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 2920 00002556 6681E300F0 <1> and bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 2921 0000255B 39D8 <1> cmp eax, ebx ; parent's and child's pages are same ? 2922 0000255D 7507 <1> jne short dapt_2 ; not same page 2923 <1> ; deallocate the child's page 2924 0000255F 800A02 <1> or byte [edx], PTE_A_WRITE ; convert to writable page (parent) 2925 00002562 59 <1> pop ecx 2926 00002563 5B <1> pop ebx 2927 00002564 EB0D <1> jmp short dapt_4 2928 <1> 2929 <1> ; 24/12/2021 2930 <1> ; ('dapt_1' is disabled) 2931 <1> ; 2932 <1> ;dapt_1: 2933 <1> ; or eax, eax ; swapped page ? 2934 <1> ; jz short dapt_5 ; no 2935 <1> ; ; yes 2936 <1> ; shr eax, 1 2937 <1> ; call unlink_swap_block ; Deallocate swapped page block 2938 <1> ; ; on the swap disk (or in file) 2939 <1> ; jmp short dapt_5 2940 <1> dapt_2: 2941 00002566 59 <1> pop ecx 2942 00002567 5B <1> pop ebx 2943 <1> dapt_3: 2944 <1> ; 12/07/2016 2945 00002568 66A90004 <1> test ax, PTE_SHARED ; shared or direct memory access indicator 2946 0000256C 7505 <1> jnz short dapt_4 ; AVL bit 1 = 1, do not deallocate this page! 2947 <1> ; 2948 <1> ;and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 2949 0000256E E814000000 <1> call deallocate_page ; set the mem allocation bit of this page 2950 <1> dapt_4: 2951 00002573 C746FC00000000 <1> mov dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent) 2952 <1> dapt_1: ; 24/12/2021 2953 <1> dapt_5: 2954 0000257A 47 <1> inc edi ; page table entry index 2955 0000257B 81FF00040000 <1> cmp edi, PAGE_SIZE / 4 ; 1024 2956 00002581 729F <1> jb short dapt_0 2957 <1> ; 2958 00002583 58 <1> pop eax ; * 2959 00002584 5A <1> pop edx 2960 00002585 5F <1> pop edi 2961 00002586 5E <1> pop esi 2962 <1> ; 2963 <1> ;call deallocate_page ; deallocate the page table's itself 2964 <1> ;retn 2965 <1> 2966 <1> deallocate_page: 2967 <1> ; 15/09/2015 2968 <1> ; 28/04/2015 2969 <1> ; 10/03/2015 2970 <1> ; 17/10/2014 2971 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 2972 <1> ; 2973 <1> ; INPUT -> 2974 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 2975 <1> ; OUTPUT -> 2976 <1> ; [free_pages] is increased 2977 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is SET) 2978 <1> ; CF = 1 if the page is already deallocated 2979 <1> ; (or not allocated) before. 2980 <1> ; 2981 <1> ; Modified Registers -> EAX 2982 <1> ; 2983 00002587 53 <1> push ebx 2984 00002588 52 <1> push edx 2985 <1> ; 2986 00002589 C1E80C <1> shr eax, PAGE_SHIFT ; shift physical address to 2987 <1> ; 12 bits right 2988 <1> ; to get page number 2989 0000258C 89C2 <1> mov edx, eax 2990 <1> ; 15/09/2015 2991 0000258E C1EA03 <1> shr edx, 3 ; to get offset to M.A.T. 2992 <1> ; (1 allocation bit = 1 page) 2993 <1> ; (1 allocation bytes = 8 pages) 2994 00002591 80E2FC <1> and dl, 0FCh ; clear lower 2 bits 2995 <1> ; (to get 32 bit position) 2996 <1> ; 2997 00002594 BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table address 2998 00002599 01D3 <1> add ebx, edx 2999 0000259B 83E01F <1> and eax, 1Fh ; lower 5 bits only 3000 <1> ; (allocation bit position) 3001 0000259E 3B15[34610000] <1> cmp edx, [next_page] ; is the new free page address lower 3002 <1> ; than the address in 'next_page' ? 3003 <1> ; (next/first free page value) 3004 000025A4 7306 <1> jnb short dap_1 ; no 3005 000025A6 8915[34610000] <1> mov [next_page], edx ; yes 3006 <1> dap_1: 3007 000025AC 0FAB03 <1> bts [ebx], eax ; unlink/release/deallocate page 3008 <1> ; set relevant bit to 1. 3009 <1> ; set CF to the previous bit value 3010 <1> ;cmc ; complement carry flag 3011 <1> ;jc short dap_2 ; do not increase free_pages count 3012 <1> ; if the page is already deallocated 3013 <1> ; before. 3014 000025AF FF05[30610000] <1> inc dword [free_pages] 3015 <1> dap_2: 3016 000025B5 5A <1> pop edx 3017 000025B6 5B <1> pop ebx 3018 000025B7 C3 <1> retn 3019 <1> 3020 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3021 <1> ;; ;; 3022 <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; 3023 <1> ;; Distributed under terms of the GNU General Public License ;; 3024 <1> ;; ;; 3025 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 3026 <1> 3027 <1> ;;$Revision: 5057 $ 3028 <1> 3029 <1> 3030 <1> ;;align 4 3031 <1> ;;proc alloc_page 3032 <1> 3033 <1> ;; pushfd 3034 <1> ;; cli 3035 <1> ;; push ebx 3036 <1> ;;;//- 3037 <1> ;; cmp [pg_data.pages_free], 1 3038 <1> ;; jle .out_of_memory 3039 <1> ;;;//- 3040 <1> ;; 3041 <1> ;; mov ebx, [page_start] 3042 <1> ;; mov ecx, [page_end] 3043 <1> ;;.l1: 3044 <1> ;; bsf eax, [ebx]; 3045 <1> ;; jnz .found 3046 <1> ;; add ebx, 4 3047 <1> ;; cmp ebx, ecx 3048 <1> ;; jb .l1 3049 <1> ;; pop ebx 3050 <1> ;; popfd 3051 <1> ;; xor eax, eax 3052 <1> ;; ret 3053 <1> ;;.found: 3054 <1> ;;;//- 3055 <1> ;; dec [pg_data.pages_free] 3056 <1> ;; jz .out_of_memory 3057 <1> ;;;//- 3058 <1> ;; btr [ebx], eax 3059 <1> ;; mov [page_start], ebx 3060 <1> ;; sub ebx, sys_pgmap 3061 <1> ;; lea eax, [eax+ebx*8] 3062 <1> ;; shl eax, 12 3063 <1> ;;;//- dec [pg_data.pages_free] 3064 <1> ;; pop ebx 3065 <1> ;; popfd 3066 <1> ;; ret 3067 <1> ;;;//- 3068 <1> ;;.out_of_memory: 3069 <1> ;; mov [pg_data.pages_free], 1 3070 <1> ;; xor eax, eax 3071 <1> ;; pop ebx 3072 <1> ;; popfd 3073 <1> ;; ret 3074 <1> ;;;//- 3075 <1> ;;endp 3076 <1> 3077 <1> duplicate_page_dir: 3078 <1> ; 21/09/2015 3079 <1> ; 31/08/2015 3080 <1> ; 20/07/2015 3081 <1> ; 28/04/2015 3082 <1> ; 27/04/2015 3083 <1> ; 18/04/2015 3084 <1> ; 12/04/2015 3085 <1> ; 18/10/2014 3086 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 3087 <1> ; 3088 <1> ; INPUT -> 3089 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 3090 <1> ; page directory. 3091 <1> ; OUTPUT -> 3092 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 3093 <1> ; page directory. 3094 <1> ; (New page directory with new page table entries.) 3095 <1> ; (New page tables with read only copies of the parent's 3096 <1> ; pages.) 3097 <1> ; EAX = 0 -> Error (CF = 1) 3098 <1> ; 3099 <1> ; Modified Registers -> none (except EAX) 3100 <1> ; 3101 000025B8 E804FEFFFF <1> call allocate_page 3102 000025BD 723E <1> jc short dpd_err 3103 <1> ; 3104 000025BF 55 <1> push ebp ; 20/07/2015 3105 000025C0 56 <1> push esi 3106 000025C1 57 <1> push edi 3107 000025C2 53 <1> push ebx 3108 000025C3 51 <1> push ecx 3109 000025C4 8B35[45650000] <1> mov esi, [u.pgdir] 3110 000025CA 89C7 <1> mov edi, eax 3111 000025CC 50 <1> push eax ; save child's page directory address 3112 <1> ; 31/08/2015 3113 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 3114 <1> ; (use same system space for all user page tables) 3115 000025CD A5 <1> movsd 3116 000025CE BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 3117 000025D3 B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 3118 <1> dpd_0: 3119 000025D8 AD <1> lodsd 3120 <1> ;or eax, eax 3121 <1> ;jnz short dpd_1 3122 000025D9 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 3123 000025DB 7508 <1> jnz short dpd_1 3124 <1> ; 20/07/2015 (virtual address at the end of the page table) 3125 000025DD 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 3126 000025E3 EB0F <1> jmp short dpd_2 3127 <1> dpd_1: 3128 000025E5 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 3129 000025E9 89C3 <1> mov ebx, eax 3130 <1> ; EBX = Parent's page table address 3131 000025EB E81F000000 <1> call duplicate_page_table 3132 000025F0 720C <1> jc short dpd_p_err 3133 <1> ; EAX = Child's page table address 3134 000025F2 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 3135 <1> ; set bit 0, bit 1 and bit 2 to 1 3136 <1> ; (present, writable, user) 3137 <1> dpd_2: 3138 000025F4 AB <1> stosd 3139 000025F5 E2E1 <1> loop dpd_0 3140 <1> ; 3141 000025F7 58 <1> pop eax ; restore child's page directory address 3142 <1> dpd_3: 3143 000025F8 59 <1> pop ecx 3144 000025F9 5B <1> pop ebx 3145 000025FA 5F <1> pop edi 3146 000025FB 5E <1> pop esi 3147 000025FC 5D <1> pop ebp ; 20/07/2015 3148 <1> dpd_err: 3149 000025FD C3 <1> retn 3150 <1> dpd_p_err: 3151 <1> ; release the allocated pages missing (recover free space) 3152 000025FE 58 <1> pop eax ; the new page directory address (physical) 3153 000025FF 8B1D[45650000] <1> mov ebx, [u.pgdir] ; parent's page directory address 3154 00002605 E8E7FEFFFF <1> call deallocate_page_dir 3155 0000260A 29C0 <1> sub eax, eax ; 0 3156 0000260C F9 <1> stc 3157 0000260D EBE9 <1> jmp short dpd_3 3158 <1> 3159 <1> duplicate_page_table: 3160 <1> ; 31/12/2021 3161 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3162 <1> ; 20/02/2017 (TRDOS 386 v2) 3163 <1> ; 21/09/2015 3164 <1> ; 20/07/2015 3165 <1> ; 05/05/2015 3166 <1> ; 28/04/2015 3167 <1> ; 27/04/2015 3168 <1> ; 18/04/2015 3169 <1> ; 18/10/2014 3170 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 3171 <1> ; 3172 <1> ; INPUT -> 3173 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 3174 <1> ; 20/02/2017 3175 <1> ; EBP = Linear address of the page (from 'duplicate_page_dir') 3176 <1> ; (Linear address = CORE + user's virtual address) 3177 <1> ; OUTPUT -> 3178 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 3179 <1> ; (with 'read only' attribute of page table entries) 3180 <1> ; 20/02/2017 3181 <1> ; EBP = Next linear page address (for 'duplicate_page_dir') 3182 <1> ; 3183 <1> ; CF = 1 -> error 3184 <1> ; 3185 <1> ; Modified Registers -> EBP (except EAX) 3186 <1> ; 3187 0000260F E8ADFDFFFF <1> call allocate_page 3188 00002614 725B <1> jc short dpt_err 3189 <1> ; 3190 00002616 50 <1> push eax ; * 3191 00002617 56 <1> push esi 3192 00002618 57 <1> push edi 3193 00002619 52 <1> push edx 3194 0000261A 51 <1> push ecx 3195 <1> ; 3196 0000261B 89DE <1> mov esi, ebx 3197 0000261D 89C7 <1> mov edi, eax 3198 0000261F 89C2 <1> mov edx, eax 3199 00002621 81C200100000 <1> add edx, PAGE_SIZE 3200 <1> dpt_0: 3201 00002627 AD <1> lodsd 3202 00002628 21C0 <1> and eax, eax 3203 0000262A 7435 <1> jz short dpt_3 3204 0000262C A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 3205 <1> ; 24/12/2021 3206 0000262E 7503 <1> jnz short dpt_1 3207 <1> ;jz short dpt_p_err 3208 <1> ; 31/12/2021 3209 00002630 F9 <1> stc 3210 00002631 EB39 <1> jmp short dpt_p_err 3211 <1> 3212 <1> ; 24/12/2021 3213 <1> ; ('reload_page' procedure call is disabled) 3214 <1> ; 3215 <1> ; ; 20/07/2015 3216 <1> ; ; ebp = virtual (linear) address of the memory page 3217 <1> ; call reload_page ; 28/04/2015 3218 <1> ; jc short dpt_p_err 3219 <1> dpt_1: 3220 <1> ; 21/09/2015 3221 00002633 89C1 <1> mov ecx, eax 3222 00002635 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3223 00002639 F6C102 <1> test cl, PTE_A_WRITE ; writable page ? 3224 0000263C 751A <1> jnz short dpt_2 3225 <1> ; Read only (parent) page 3226 <1> ; - there is a third process which uses this page - 3227 <1> ; Allocate a new page for the child process 3228 0000263E E87EFDFFFF <1> call allocate_page 3229 00002643 7227 <1> jc short dpt_p_err 3230 00002645 57 <1> push edi 3231 00002646 56 <1> push esi 3232 00002647 89CE <1> mov esi, ecx 3233 00002649 89C7 <1> mov edi, eax 3234 0000264B B900040000 <1> mov ecx, PAGE_SIZE/4 3235 00002650 F3A5 <1> rep movsd ; copy page (4096 bytes) 3236 00002652 5E <1> pop esi 3237 00002653 5F <1> pop edi 3238 <1> ; 3239 <1> 3240 <1> ; 24/12/2021 3241 <1> ; ('add_to_swap_queue' procedure call is disabled) 3242 <1> ; 3243 <1> ; push ebx 3244 <1> ; push eax 3245 <1> ; ; 20/07/2015 3246 <1> ; mov ebx, ebp 3247 <1> ; ; ebx = virtual (linear) address of the memory page 3248 <1> ; call add_to_swap_queue 3249 <1> ; pop eax 3250 <1> ; pop ebx 3251 <1> 3252 <1> ; 21/09/2015 3253 00002654 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 3254 <1> ; user + writable + present page 3255 00002656 EB09 <1> jmp short dpt_3 3256 <1> dpt_2: 3257 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 3258 00002658 0C05 <1> or al, PTE_A_USER+PTE_A_PRESENT 3259 <1> ; (read only page!) 3260 0000265A 8946FC <1> mov [esi-4], eax ; update parent's PTE 3261 0000265D 660D0002 <1> or ax, PTE_DUPLICATED ; (read only page & duplicated PTE!) 3262 <1> dpt_3: 3263 00002661 AB <1> stosd ; EDI points to child's PTE 3264 <1> ; 3265 00002662 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 3266 <1> ; 3267 00002668 39D7 <1> cmp edi, edx 3268 0000266A 72BB <1> jb short dpt_0 3269 <1> dpt_p_err: 3270 0000266C 59 <1> pop ecx 3271 0000266D 5A <1> pop edx 3272 0000266E 5F <1> pop edi 3273 0000266F 5E <1> pop esi 3274 00002670 58 <1> pop eax ; * 3275 <1> dpt_err: 3276 00002671 C3 <1> retn 3277 <1> 3278 <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault ! 3279 <1> ; 31/12/2021 3280 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3281 <1> ; 21/09/2015 3282 <1> ; 19/09/2015 3283 <1> ; 17/09/2015 3284 <1> ; 28/08/2015 3285 <1> ; 20/07/2015 3286 <1> ; 28/06/2015 3287 <1> ; 03/05/2015 3288 <1> ; 30/04/2015 3289 <1> ; 18/04/2015 3290 <1> ; 12/04/2015 3291 <1> ; 30/10/2014 3292 <1> ; 11/09/2014 3293 <1> ; 10/09/2014 (Retro UNIX 386 v1 - beginning) 3294 <1> ; 3295 <1> ; Note: This is not an interrupt/exception handler. 3296 <1> ; This is a 'page fault remedy' subroutine 3297 <1> ; which will be called by standard/uniform 3298 <1> ; exception handler. 3299 <1> ; 3300 <1> ; INPUT -> 3301 <1> ; [error_code] = 32 bit ERROR CODE (lower 5 bits are valid) 3302 <1> ; 3303 <1> ; cr2 = the virtual (linear) address 3304 <1> ; which has caused to page fault (19/09/2015) 3305 <1> ; 3306 <1> ; OUTPUT -> 3307 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3308 <1> ; EAX = 0 -> no error 3309 <1> ; EAX > 0 -> error code in EAX (also CF = 1) 3310 <1> ; 3311 <1> ; Modified Registers -> none (except EAX) 3312 <1> ; 3313 <1> ; 3314 <1> ; ERROR CODE: 3315 <1> ; 31 ..... 4 3 2 1 0 3316 <1> ; +---+-- --+---+---+---+---+---+---+ 3317 <1> ; | Reserved | I | R | U | W | P | 3318 <1> ; +---+-- --+---+---+---+---+---+---+ 3319 <1> ; 3320 <1> ; P : PRESENT - When set, the page fault was caused by 3321 <1> ; a page-protection violation. When not set, 3322 <1> ; it was caused by a non-present page. 3323 <1> ; W : WRITE - When set, the page fault was caused by 3324 <1> ; a page write. When not set, it was caused 3325 <1> ; by a page read. 3326 <1> ; U : USER - When set, the page fault was caused 3327 <1> ; while CPL = 3. 3328 <1> ; This does not necessarily mean that 3329 <1> ; the page fault was a privilege violation. 3330 <1> ; R : RESERVD - When set, the page fault was caused by 3331 <1> ; WRITE reading a 1 in a reserved field. 3332 <1> ; I : INSTRUC - When set, the page fault was caused by 3333 <1> ; FETCH an instruction fetch 3334 <1> ; 3335 <1> ;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION 3336 <1> ; 31 22 12 11 0 3337 <1> ; +-------------------+-------------------+-----------------------+ 3338 <1> ; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # | OFFSET | 3339 <1> ; +-------------------+-------------------+-----------------------+ 3340 <1> ; 3341 <1> 3342 <1> ;; CR3 REGISTER (Control Register 3) 3343 <1> ; 31 12 5 4 3 2 0 3344 <1> ; +---------------------------------------+-------------+---+-----+ 3345 <1> ; | | |P|P| | 3346 <1> ; | PAGE DIRECTORY TABLE BASE ADDRESS | reserved |C|W|rsvrd| 3347 <1> ; | | |D|T| | 3348 <1> ; +---------------------------------------+-------------+---+-----+ 3349 <1> ; 3350 <1> ; PWT - WRITE THROUGH 3351 <1> ; PCD - CACHE DISABLE 3352 <1> ; 3353 <1> ; 3354 <1> ;; x86 PAGE DIRECTORY ENTRY (4 KByte Page) 3355 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3356 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3357 <1> ; | | | | | | |P|P|U|R| | 3358 <1> ; | PAGE TABLE BASE ADDRESS 31..12 | AVL |G|0|D|A|C|W|/|/|P| 3359 <1> ; | | | | | | |D|T|S|W| | 3360 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3361 <1> ; 3362 <1> ; P - PRESENT 3363 <1> ; R/W - READ/WRITE 3364 <1> ; U/S - USER/SUPERVISOR 3365 <1> ; PWT - WRITE THROUGH 3366 <1> ; PCD - CACHE DISABLE 3367 <1> ; A - ACCESSED 3368 <1> ; D - DIRTY (IGNORED) 3369 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 3370 <1> ; G - GLOBAL (IGNORED) 3371 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3372 <1> ; 3373 <1> ; 3374 <1> ;; x86 PAGE TABLE ENTRY (4 KByte Page) 3375 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3376 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3377 <1> ; | | | |P| | |P|P|U|R| | 3378 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |G|A|D|A|C|W|/|/|P| 3379 <1> ; | | | |T| | |D|T|S|W| | 3380 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 3381 <1> ; 3382 <1> ; P - PRESENT 3383 <1> ; R/W - READ/WRITE 3384 <1> ; U/S - USER/SUPERVISOR 3385 <1> ; PWT - WRITE THROUGH 3386 <1> ; PCD - CACHE DISABLE 3387 <1> ; A - ACCESSED 3388 <1> ; D - DIRTY 3389 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 3390 <1> ; G - GLOBAL 3391 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3392 <1> ; 3393 <1> ; 3394 <1> ;; 80386 PAGE TABLE ENTRY (4 KByte Page) 3395 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 3396 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 3397 <1> ; | | | | | | | | |U|R| | 3398 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |0|0|D|A|0|0|/|/|P| 3399 <1> ; | | | | | | | | |S|W| | 3400 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 3401 <1> ; 3402 <1> ; P - PRESENT 3403 <1> ; R/W - READ/WRITE 3404 <1> ; U/S - USER/SUPERVISOR 3405 <1> ; D - DIRTY 3406 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 3407 <1> ; 3408 <1> ; NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. 3409 <1> ; 3410 <1> ; 3411 <1> ;; Invalid Page Table Entry 3412 <1> ; 31 1 0 3413 <1> ; +-------------------------------------------------------------+-+ 3414 <1> ; | | | 3415 <1> ; | AVAILABLE |0| 3416 <1> ; | | | 3417 <1> ; +-------------------------------------------------------------+-+ 3418 <1> ; 3419 <1> 3420 00002672 53 <1> push ebx 3421 00002673 52 <1> push edx 3422 00002674 51 <1> push ecx 3423 <1> ; 3424 <1> ; 21/09/2015 (debugging) 3425 00002675 FF05[55650000] <1> inc dword [u.pfcount] ; page fault count for running process 3426 0000267B FF05[DC610000] <1> inc dword [PF_Count] ; total page fault count 3427 <1> ; 28/06/2015 3428 <1> ;mov edx, [error_code] ; Lower 5 bits are valid 3429 00002681 8A15[D4610000] <1> mov dl, [error_code] 3430 <1> ; 3431 00002687 F6C201 <1> test dl, 1 ; page fault was caused by a non-present page 3432 <1> ; sign 3433 0000268A 7425 <1> jz short pfh_alloc_np 3434 <1> ; 3435 <1> ; If it is not a 'write on read only page' type page fault 3436 <1> ; major page fault error with minor reason must be returned without 3437 <1> ; fixing the problem. 'sys_exit with error' will be needed 3438 <1> ; after return here! 3439 <1> ; Page fault will be remedied, by copying page contents 3440 <1> ; to newly allocated page with write permission; 3441 <1> ; sys_fork -> sys_exec -> copy on write, demand paging method is 3442 <1> ; used for working with minimum possible memory usage. 3443 <1> ; sys_fork will duplicate page directory and tables of parent 3444 <1> ; process with 'read only' flag. If the child process attempts to 3445 <1> ; write on these read only pages, page fault will be directed here 3446 <1> ; for allocating a new page with same data/content. 3447 <1> ; 3448 <1> ; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS) 3449 <1> ; will not force to separate CODE and DATA space 3450 <1> ; in a process/program... 3451 <1> ; CODE segment/section may contain DATA! 3452 <1> ; It is flat, smoth and simplest programming method already as in 3453 <1> ; Retro UNIX 8086 v1 and MS-DOS programs. 3454 <1> ; 3455 0000268C F6C202 <1> test dl, 2 ; page fault was caused by a page write 3456 <1> ; sign 3457 0000268F 7418 <1> jz pfh_p_err 3458 <1> ; 31/08/2015 3459 00002691 F6C204 <1> test dl, 4 ; page fault was caused while CPL = 3 (user mode) 3460 <1> ; sign. (U+W+P = 4+2+1 = 7) 3461 00002694 7413 <1> jz short pfh_pv_err 3462 <1> ; 3463 <1> ; make a new page and copy the parent's page content 3464 <1> ; as the child's new page content 3465 <1> ; 3466 00002696 0F20D3 <1> mov ebx, cr2 ; CR2 contains the linear address 3467 <1> ; which has caused to page fault 3468 00002699 E87C000000 <1> call copy_page 3469 0000269E 7202 <1> jc short pfh_im_err ; insufficient memory 3470 <1> ; 3471 000026A0 EB72 <1> jmp pfh_cpp_ok 3472 <1> 3473 <1> ; 31/12/2021 (short jump) 3474 <1> pfh_im_err: 3475 000026A2 B8E4000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX 3476 <1> ; Major (Primary) Error: Page Fault 3477 <1> ; Minor (Secondary) Error: Insufficient Memory ! 3478 000026A7 EB6D <1> jmp short pfh_err_retn 3479 <1> 3480 <1> ; 31/12/2021 3481 <1> pfh_p_err: ; 09/03/2015 3482 <1> pfh_pv_err: 3483 <1> ; Page fault was caused by a protection-violation 3484 000026A9 B8E6000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX 3485 <1> ; Major (Primary) Error: Page Fault 3486 <1> ; Minor (Secondary) Error: Protection violation ! 3487 000026AE F9 <1> stc 3488 000026AF EB65 <1> jmp short pfh_err_retn 3489 <1> 3490 <1> pfh_alloc_np: 3491 000026B1 E80BFDFFFF <1> call allocate_page ; (allocate a new page) 3492 000026B6 72EA <1> jc short pfh_im_err ; 'insufficient memory' error 3493 <1> pfh_chk_cpl: 3494 <1> ; EAX = Physical (base) address of the allocated (new) page 3495 <1> ; (Lower 12 bits are ZERO, because 3496 <1> ; the address is on a page boundary) 3497 000026B8 80E204 <1> and dl, 4 ; CPL = 3 ? 3498 000026BB 7505 <1> jnz short pfh_um 3499 <1> ; Page fault handler for kernel/system mode (CPL=0) 3500 000026BD 0F20DB <1> mov ebx, cr3 ; CR3 (Control Register 3) contains physical address 3501 <1> ; of the current/active page directory 3502 <1> ; (Always kernel/system mode page directory, here!) 3503 <1> ; Note: Lower 12 bits are 0. (page boundary) 3504 000026C0 EB06 <1> jmp short pfh_get_pde 3505 <1> ; 3506 <1> pfh_um: ; Page fault handler for user/appl. mode (CPL=3) 3507 000026C2 8B1D[45650000] <1> mov ebx, [u.pgdir] ; Page directory of current/active process 3508 <1> ; Physical address of the USER's page directory 3509 <1> ; Note: Lower 12 bits are 0. (page boundary) 3510 <1> pfh_get_pde: 3511 000026C8 80CA03 <1> or dl, 3 ; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT 3512 000026CB 0F20D1 <1> mov ecx, cr2 ; CR2 contains the virtual address 3513 <1> ; which has been caused to page fault 3514 <1> ; 3515 000026CE C1E914 <1> shr ecx, 20 ; shift 20 bits right 3516 000026D1 80E1FC <1> and cl, 0FCh ; mask lower 2 bits to get PDE offset 3517 <1> ; 3518 000026D4 01CB <1> add ebx, ecx ; now, EBX points to the relevant page dir entry 3519 000026D6 8B0B <1> mov ecx, [ebx] ; physical (base) address of the page table 3520 000026D8 F6C101 <1> test cl, 1 ; check bit 0 is set (1) or not (0). 3521 000026DB 740B <1> jz short pfh_set_pde ; Page directory entry is not valid, 3522 <1> ; set/validate page directory entry 3523 000026DD 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 3524 000026E2 89CB <1> mov ebx, ecx ; Physical address of the page table 3525 000026E4 89C1 <1> mov ecx, eax ; new page address (physical) 3526 000026E6 EB16 <1> jmp short pfh_get_pte 3527 <1> pfh_set_pde: 3528 <1> ;; NOTE: Page directories and page tables never be swapped out! 3529 <1> ;; (So, we know this PDE is empty or invalid) 3530 <1> ; 3531 000026E8 08D0 <1> or al, dl ; lower 3 bits are used as U/S, R/W, P flags 3532 000026EA 8903 <1> mov [ebx], eax ; Let's put the new page directory entry here ! 3533 000026EC 30C0 <1> xor al, al ; clear lower (3..8) bits 3534 000026EE 89C3 <1> mov ebx, eax 3535 000026F0 E8CCFCFFFF <1> call allocate_page ; (allocate a new page) 3536 000026F5 72AB <1> jc short pfh_im_err ; 'insufficient memory' error 3537 <1> pfh_spde_1: 3538 <1> ; EAX = Physical (base) address of the allocated (new) page 3539 000026F7 89C1 <1> mov ecx, eax 3540 000026F9 E834FDFFFF <1> call clear_page ; Clear page content 3541 <1> pfh_get_pte: 3542 000026FE 0F20D0 <1> mov eax, cr2 ; virtual address 3543 <1> ; which has been caused to page fault 3544 00002701 89C7 <1> mov edi, eax ; 20/07/2015 3545 00002703 C1E80C <1> shr eax, 12 ; shift 12 bit right to get 3546 <1> ; higher 20 bits of the page fault address 3547 00002706 25FF030000 <1> and eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3548 0000270B C1E002 <1> shl eax, 2 ; shift 2 bits left to get PTE offset 3549 0000270E 01C3 <1> add ebx, eax ; now, EBX points to the relevant page table entry 3550 <1> ; 24/12/2021 3551 <1> ; mov eax, [ebx] ; get previous value of pte 3552 <1> ; ; bit 0 of EAX is always 0 (otherwise we would not be here) 3553 <1> ; 24/12/2021 3554 <1> ; ('swap_in' procedure call has been disabled) 3555 <1> ; 3556 <1> ; and eax, eax 3557 <1> ; jz short pfh_gpte_1 3558 <1> ; ; 20/07/2015 3559 <1> ; xchg ebx, ecx ; new page address (physical) 3560 <1> ; push ebp ; 20/07/2015 3561 <1> ; mov ebp, cr2 3562 <1> ; ; ECX = physical address of the page table entry 3563 <1> ; ; EBX = Memory page address (physical!) 3564 <1> ; ; EAX = Swap disk (offset) address 3565 <1> ; ; EBP = virtual address (page fault address) 3566 <1> ; call swap_in 3567 <1> ; pop ebp 3568 <1> ; jc short pfh_err_retn 3569 <1> ; xchg ecx, ebx 3570 <1> ; ; EBX = physical address of the page table entry 3571 <1> ; ; ECX = new page 3572 <1> pfh_gpte_1: 3573 00002710 08D1 <1> or cl, dl ; lower 3 bits are used as U/S, R/W, P flags 3574 00002712 890B <1> mov [ebx], ecx ; Let's put the new page table entry here ! 3575 <1> pfh_cpp_ok: 3576 <1> ; 24/12/2021 3577 <1> ; ('add_to_swap_queue' procedure call has been disabled) 3578 <1> ; 3579 <1> ; ; 20/07/2015 3580 <1> ; mov ebx, cr2 3581 <1> ; call add_to_swap_queue 3582 <1> ; 3583 <1> ; The new PTE (which contains the new page) will be added to 3584 <1> ; the swap queue, here. 3585 <1> ; (Later, if memory will become insufficient, 3586 <1> ; one page will be swapped out which is at the head of 3587 <1> ; the swap queue by using FIFO and access check methods.) 3588 <1> ; 3589 00002714 31C0 <1> xor eax, eax ; 0 3590 <1> ; 3591 <1> pfh_err_retn: 3592 00002716 59 <1> pop ecx 3593 00002717 5A <1> pop edx 3594 00002718 5B <1> pop ebx 3595 00002719 C3 <1> retn 3596 <1> 3597 <1> copy_page: 3598 <1> ; 17/07/2022 3599 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 3600 <1> ; 16/04/2021 3601 <1> ; 19/04/2020 - Retro UNIX 386 v2 3602 <1> ; 22/09/2015 3603 <1> ; 21/09/2015 3604 <1> ; 19/09/2015 3605 <1> ; 07/09/2015 3606 <1> ; 31/08/2015 3607 <1> ; 20/07/2015 3608 <1> ; 05/05/2015 3609 <1> ; 03/05/2015 3610 <1> ; 18/04/2015 3611 <1> ; 12/04/2015 3612 <1> ; 30/10/2014 3613 <1> ; 18/10/2014 (Retro UNIX 386 v1 - beginning) 3614 <1> ; 3615 <1> ; INPUT -> 3616 <1> ; EBX = Virtual (linear) address of source page 3617 <1> ; (Page fault address) 3618 <1> ; OUTPUT -> 3619 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 3620 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3621 <1> ; EAX = 0 (CF = 1) 3622 <1> ; if there is not a free page to be allocated 3623 <1> ; (page content of the source page will be copied 3624 <1> ; onto the target/new page) 3625 <1> ; 3626 <1> ; Modified Registers -> ecx, ebx (except EAX) 3627 <1> ; 3628 <1> 3629 <1> ; 19/04/2020 - Retro UNIX 386 v2 3630 <1> ; INPUT: 3631 <1> ; EBX = Virtual (linear) address of source page 3632 <1> ; (Page fault address) 3633 <1> ; OUTPUT: 3634 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 3635 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 3636 <1> ; EAX = 0 (CF = 1) 3637 <1> ; if there is not a free page to be allocated 3638 <1> ; (page content of the source page will be copied 3639 <1> ; onto the target/new page) 3640 <1> ; 3641 <1> ; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021 3642 <1> 3643 0000271A 56 <1> push esi ; * 3644 0000271B 57 <1> push edi ; ** 3645 <1> ; 16/04/2021 3646 <1> ; 19/04/2020 - Retro UNIX 386 v2 3647 <1> ;push ebx ; *** 3648 <1> ;push ecx ; **** 3649 0000271C 31F6 <1> xor esi, esi 3650 0000271E C1EB0C <1> shr ebx, 12 ; shift 12 bits right to get PDE & PTE numbers 3651 00002721 89D9 <1> mov ecx, ebx ; save page fault address (as 12 bit shifted) 3652 00002723 C1EB08 <1> shr ebx, 8 ; shift 8 bits right and then 3653 00002726 80E3FC <1> and bl, 0FCh ; mask lower 2 bits to get PDE offset 3654 00002729 89DF <1> mov edi, ebx ; save it for the parent of current process 3655 0000272B 031D[45650000] <1> add ebx, [u.pgdir] ; EBX points to the relevant page dir entry 3656 00002731 8B03 <1> mov eax, [ebx] ; physical (base) address of the page table 3657 00002733 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3658 00002737 89CB <1> mov ebx, ecx ; (restore higher 20 bits of page fault address) 3659 00002739 81E3FF030000 <1> and ebx, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3660 <1> ;shl bx, 2 ; shift 2 bits left to get PTE offset 3661 <1> ; 17/07/2022 3662 0000273F C1E302 <1> shl ebx, 2 3663 00002742 01C3 <1> add ebx, eax ; EBX points to the relevant page table entry 3664 <1> ; 07/09/2015 3665 00002744 66F7030002 <1> test word [ebx], PTE_DUPLICATED ; (Does current process share this 3666 <1> ; read only page as a child process?) 3667 00002749 7509 <1> jnz short cpp_0 ; yes 3668 0000274B 8B0B <1> mov ecx, [ebx] ; PTE value 3669 0000274D 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 3670 00002752 EB31 <1> jmp short cpp_1 3671 <1> cpp_0: 3672 00002754 89FE <1> mov esi, edi 3673 00002756 0335[49650000] <1> add esi, [u.ppgdir] ; the parent's page directory entry 3674 0000275C 8B06 <1> mov eax, [esi] ; physical (base) address of the page table 3675 0000275E 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 3676 00002762 89CE <1> mov esi, ecx ; (restore higher 20 bits of page fault address) 3677 00002764 81E6FF030000 <1> and esi, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 3678 <1> ;shl si, 2 ; shift 2 bits left to get PTE offset 3679 <1> ; 17/07/2022 3680 0000276A C1E602 <1> shl esi, 2 3681 0000276D 01C6 <1> add esi, eax ; EDX points to the relevant page table entry 3682 0000276F 8B0E <1> mov ecx, [esi] ; PTE value of the parent process 3683 <1> ; 21/09/2015 3684 00002771 8B03 <1> mov eax, [ebx] ; PTE value of the child process 3685 00002773 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear page attributes 3686 <1> ; 3687 00002777 F6C101 <1> test cl, PTE_A_PRESENT ; is it a present/valid page ? 3688 0000277A 7424 <1> jz short cpp_3 ; the parent's page is not same page 3689 <1> ; 3690 0000277C 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 3691 00002781 39C8 <1> cmp eax, ecx ; Same page? 3692 00002783 751B <1> jne short cpp_3 ; Parent page and child page are not same 3693 <1> ; Convert child's page to writable page 3694 <1> cpp_1: 3695 00002785 E837FCFFFF <1> call allocate_page 3696 0000278A 721A <1> jc short cpp_4 ; 'insufficient memory' error 3697 0000278C 21F6 <1> and esi, esi ; check ESI is valid or not 3698 0000278E 7405 <1> jz short cpp_2 3699 <1> ; Convert read only page to writable page 3700 <1> ;(for the parent of the current process) 3701 <1> ;and word [esi], PTE_A_CLEAR ; 0F000h 3702 <1> ; 22/09/2015 3703 00002790 890E <1> mov [esi], ecx 3704 00002792 800E07 <1> or byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER 3705 <1> ; 1+2+4 = 7 3706 <1> cpp_2: 3707 00002795 89C7 <1> mov edi, eax ; new page address of the child process 3708 <1> ; 07/09/2015 3709 00002797 89CE <1> mov esi, ecx ; the page address of the parent process 3710 00002799 B900040000 <1> mov ecx, PAGE_SIZE / 4 3711 0000279E F3A5 <1> rep movsd ; 31/08/2015 3712 <1> cpp_3: 3713 000027A0 0C07 <1> or al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7 3714 000027A2 8903 <1> mov [ebx], eax ; Update PTE 3715 000027A4 28C0 <1> sub al, al ; clear attributes 3716 <1> cpp_4: 3717 <1> ; 16/04/2021 3718 <1> ; 19/04/2020 - Retro UNIX 386 v2 3719 <1> ;pop ecx ; **** 3720 <1> ;pop ebx ; *** 3721 000027A6 5F <1> pop edi ; ** 3722 000027A7 5E <1> pop esi ; * 3723 000027A8 C3 <1> retn 3724 <1> 3725 <1> ;; 28/04/2015 3726 <1> ;; 24/10/2014 3727 <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning) 3728 <1> ;; SWAP_PAGE_QUEUE (4096 bytes) 3729 <1> ;; 3730 <1> ;; 0000 0001 0002 0003 .... 1020 1021 1022 1023 3731 <1> ;; +------+------+------+------+- -+------+------+------+------+ 3732 <1> ;; | pg1 | pg2 | pg3 | pg4 | .... |pg1021|pg1022|pg1023|pg1024| 3733 <1> ;; +------+------+------+------+- -+------+------+------+------+ 3734 <1> ;; 3735 <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue 3736 <1> ;; 3737 <1> ;; Method: 3738 <1> ;; Swap page queue is a list of allocated pages with physical 3739 <1> ;; addresses (system mode virtual adresses = physical addresses). 3740 <1> ;; It is used for 'swap_in' and 'swap_out' procedures. 3741 <1> ;; When a new page is being allocated, swap queue is updated 3742 <1> ;; by 'swap_queue_shift' procedure, header of the queue (offset 0) 3743 <1> ;; is checked for 'accessed' flag. If the 1st page on the queue 3744 <1> ;; is 'accessed' or 'read only', it is dropped from the list; 3745 <1> ;; other pages from the 2nd to the last (in [swpq_last]) shifted 3746 <1> ;; to head then the 2nd page becomes the 1st and '[swpq_last]' 3747 <1> ;; offset value becomes it's previous offset value - 4. 3748 <1> ;; If the 1st page of the swap page queue is not 'accessed' 3749 <1> ;; the queue/list is not shifted. 3750 <1> ;; After the queue/list shift, newly allocated page is added 3751 <1> ;; to the tail of the queue at the [swpq_count*4] position. 3752 <1> ;; But, if [swpq_count] > 1023, the newly allocated page 3753 <1> ;; will not be added to the tail of swap page queue. 3754 <1> ;; 3755 <1> ;; During 'swap_out' procedure, swap page queue is checked for 3756 <1> ;; the first non-accessed, writable page in the list, 3757 <1> ;; from the head to the tail. The list is shifted to left 3758 <1> ;; (to the head) till a non-accessed page will be found in the list. 3759 <1> ;; Then, this page is swapped out (to disk) and then it is dropped 3760 <1> ;; from the list by a final swap queue shift. [swpq_count] value 3761 <1> ;; is changed. If all pages on the queue' are 'accessed', 3762 <1> ;; 'insufficient memory' error will be returned ('swap_out' 3763 <1> ;; procedure will be failed)... 3764 <1> ;; 3765 <1> ;; Note: If the 1st page of the queue is an 'accessed' page, 3766 <1> ;; 'accessed' flag of the page will be reset (0) and that page 3767 <1> ;; (PTE) will be added to the tail of the queue after 3768 <1> ;; the check, if [swpq_count] < 1023. If [swpq_count] = 1024 3769 <1> ;; the queue will be rotated and the PTE in the head will be 3770 <1> ;; added to the tail after resetting 'accessed' bit. 3771 <1> ;; 3772 <1> ;; 3773 <1> ;; 3774 <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks) 3775 <1> ;; 3776 <1> ;; 00000000 00000004 00000008 0000000C ... size-8 size-4 3777 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 3778 <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) | 3779 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 3780 <1> ;; 3781 <1> ;; [swpd_next] = the first free block address in swapped page records 3782 <1> ;; for next free block search by 'swap_out' procedure. 3783 <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes) 3784 <1> ;; NOTE: max. possible swap disk size is 1024 GB 3785 <1> ;; (entire swap space must be accessed by using 3786 <1> ;; 31 bit offset address) 3787 <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space 3788 <1> ;; [swpd_start] = absolute/start address of the swap disk/file 3789 <1> ;; 0 for file, or beginning sector of the swap partition 3790 <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file 3791 <1> ;; 3792 <1> ;; 3793 <1> ;; Method: 3794 <1> ;; When the memory (ram) becomes insufficient, page allocation 3795 <1> ;; procedure swaps out a page from memory to the swap disk 3796 <1> ;; (partition) or swap file to get a new free page at the memory. 3797 <1> ;; Swapping out is performed by using swap page queue. 3798 <1> ;; 3799 <1> ;; Allocation block size of swap disk/file is equal to page size 3800 <1> ;; (4096 bytes). Swapping address (in sectors) is recorded 3801 <1> ;; into relevant page file entry as 31 bit physical (logical) 3802 <1> ;; offset address as 1 bit shifted to left for present flag (0). 3803 <1> ;; Swapped page address is between 1 and swap disk/file size - 4. 3804 <1> ;; Absolute physical (logical) address of the swapped page is 3805 <1> ;; calculated by adding offset value to the swap partition's 3806 <1> ;; start address. If the swap device (disk) is a virtual disk 3807 <1> ;; or it is a file, start address of the swap disk/volume is 0, 3808 <1> ;; and offset value is equal to absolute (physical or logical) 3809 <1> ;; address/position. (It has not to be ZERO if the swap partition 3810 <1> ;; is in a partitioned virtual hard disk.) 3811 <1> ;; 3812 <1> ;; Note: Swap addresses are always specified/declared in sectors, 3813 <1> ;; not in bytes or in blocks/zones/clusters (4096 bytes) as unit. 3814 <1> ;; 3815 <1> ;; Swap disk/file allocation is mapped via 'Swap Allocation Table' 3816 <1> ;; at memory as similar to 'Memory Allocation Table'. 3817 <1> ;; 3818 <1> ;; Every bit of Swap Allocation Table repsesents one swap block 3819 <1> ;; (equal to page size) respectively. Bit 0 of the S.A.T. byte 0 3820 <1> ;; is reserved for swap disk/file block 0 as descriptor block 3821 <1> ;; (also for compatibility with PTE). If bit value is ZERO, 3822 <1> ;; it means relevant (respective) block is in use, and, 3823 <1> ;; of course, if bit value is 1, it means relevant (respective) 3824 <1> ;; swap disk/file block is free. 3825 <1> ;; For example: bit 1 of the byte 128 repsesents block 1025 3826 <1> ;; (128*8+1) or sector (offset) 8200 on the swap disk or 3827 <1> ;; byte (offset/position) 4198400 in the swap file. 3828 <1> ;; 4GB swap space is represented via 128KB Swap Allocation Table. 3829 <1> ;; Initial layout of Swap Allocation Table is as follows: 3830 <1> ;; ------------------------------------------------------------ 3831 <1> ;; 0111111111111111111111111 .... 11111111111111111111111111111 3832 <1> ;; ------------------------------------------------------------ 3833 <1> ;; (0 is reserved block, 1s represent free blocks respectively.) 3834 <1> ;; (Note: Allocation cell/unit of the table is bit, not byte) 3835 <1> ;; 3836 <1> ;; .............................................................. 3837 <1> ;; 3838 <1> ;; 'swap_out' procedure checks 'free_swap_blocks' count at first, 3839 <1> ;; then it searches Swap Allocation Table if free count is not 3840 <1> ;; zero. From begining the [swpd_next] dword value, the first bit 3841 <1> ;; position with value of 1 on the table is converted to swap 3842 <1> ;; disk/file offset address, in sectors (not 4096 bytes block). 3843 <1> ;; 'ldrv_write' procedure is called with ldrv (logical drive 3844 <1> ;; number of physical swap disk or virtual swap disk) 3845 <1> ;; number, sector offset (not absolute sector -LBA- number), 3846 <1> ;; and sector count (8, 512*8 = 4096) and buffer adress 3847 <1> ;; (memory page). That will be a direct disk write procedure. 3848 <1> ;; (for preventing late memory allocation, significant waiting). 3849 <1> ;; If disk write procedure returns with error or free count of 3850 <1> ;; swap blocks is ZERO, 'swap_out' procedure will return with 3851 <1> ;; 'insufficient memory error' (cf=1). 3852 <1> ;; 3853 <1> ;; (Note: Even if free swap disk/file blocks was not zero, 3854 <1> ;; any disk write error will not be fixed by 'swap_out' procedure, 3855 <1> ;; in other words, 'swap_out' will not check the table for other 3856 <1> ;; free blocks after a disk write error. It will return to 3857 <1> ;; the caller with error (CF=1) which means swapping is failed. 3858 <1> ;; 3859 <1> ;; After writing the page on to swap disk/file address/sector, 3860 <1> ;; 'swap_out' procedure returns with that swap (offset) sector 3861 <1> ;; address (cf=0). 3862 <1> ;; 3863 <1> ;; .............................................................. 3864 <1> ;; 3865 <1> ;; 'swap_in' procedure loads addressed (relevant) swap disk or 3866 <1> ;; file sectors at specified memory page. Then page allocation 3867 <1> ;; procedure updates relevant page table entry with 'present' 3868 <1> ;; attribute. If swap disk or file reading fails there is nothing 3869 <1> ;; to do, except to terminate the process which is the owner of 3870 <1> ;; the swapped page. 3871 <1> ;; 3872 <1> ;; 'swap_in' procedure sets the relevant/respective bit value 3873 <1> ;; in the Swap Allocation Table (as free block). 'swap_in' also 3874 <1> ;; updates [swpd_first] pointer if it is required. 3875 <1> ;; 3876 <1> ;; .............................................................. 3877 <1> ;; 3878 <1> ;; Note: If [swap_enabled] value is ZERO, that means there is not 3879 <1> ;; a swap disk or swap file in use... 'swap_in' and 'swap_out' 3880 <1> ;; procedures ans 'swap page que' procedures will not be active... 3881 <1> ;; 'Insufficient memory' error will be returned by 'swap_out' 3882 <1> ;; and 'general protection fault' will be returned by 'swap_in' 3883 <1> ;; procedure, if it is called mistakenly (a wrong value in a PTE). 3884 <1> ;; 3885 <1> 3886 <1> ; 24/12/2021 3887 <1> ; ('swap_in' procedure call is disabled) 3888 <1> 3889 <1> ;swap_in: 3890 <1> ; 31/08/2015 3891 <1> ; 20/07/2015 3892 <1> ; 28/04/2015 3893 <1> ; 18/04/2015 3894 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 3895 <1> ; 3896 <1> ; INPUT -> 3897 <1> ; EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE 3898 <1> ; EBP = VIRTUAL (LINEAR) ADDRESS (page fault address) 3899 <1> ; EAX = Offset Address for the swapped page on the 3900 <1> ; swap disk or in the swap file. 3901 <1> ; 3902 <1> ; OUTPUT -> 3903 <1> ; EAX = 0 if loading at memory has been successful 3904 <1> ; 3905 <1> ; CF = 1 -> swap disk reading error (disk/file not present 3906 <1> ; or sector not present or drive not ready 3907 <1> ; EAX = Error code 3908 <1> ; [u.error] = EAX 3909 <1> ; = The last error code for the process 3910 <1> ; (will be reset after returning to user) 3911 <1> ; 3912 <1> ; Modified Registers -> EAX 3913 <1> ; 3914 <1> 3915 <1> ; cmp dword [swp_drv], 0 3916 <1> ; jna short swpin_dnp_err 3917 <1> ; 3918 <1> ; cmp eax, [swpd_size] 3919 <1> ; jnb short swpin_snp_err 3920 <1> ; 3921 <1> ; push esi 3922 <1> ; push ebx 3923 <1> ; push ecx 3924 <1> ; mov esi, [swp_drv] 3925 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 3926 <1> ; ; Note: Even if corresponding physical disk's sector 3927 <1> ; ; size different than 512 bytes, logical disk sector 3928 <1> ; ; size is 512 bytes and disk reading procedure 3929 <1> ; ; will be performed for reading 4096 bytes 3930 <1> ; ; (2*2048, 8*512). 3931 <1> ; ; ESI = Logical disk description table address 3932 <1> ; ; EBX = Memory page (buffer) address (physical!) 3933 <1> ; ; EAX = Sector adress (offset address, logical sector number) 3934 <1> ; ; ECX = Sector count ; 8 sectors 3935 <1> ; push eax 3936 <1> ; call logical_disk_read 3937 <1> ; pop eax 3938 <1> ; jnc short swpin_read_ok 3939 <1> ; ; 3940 <1> ; mov eax, SWP_DISK_READ_ERR ; drive not ready or read error 3941 <1> ; mov [u.error], eax 3942 <1> ; jmp short swpin_retn 3943 <1> ; ; 3944 <1> ;swpin_read_ok: 3945 <1> ; ; EAX = Offset address (logical sector number) 3946 <1> ; call unlink_swap_block ; Deallocate swap block 3947 <1> ; ; 3948 <1> ; ; EBX = Memory page (buffer) address (physical!) 3949 <1> ; ; 20/07/2015 3950 <1> ; mov ebx, ebp ; virtual address (page fault address) 3951 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 3952 <1> ; mov bl, [u.uno] ; current process number 3953 <1> ; ; EBX = Virtual (Linear) address & process number combination 3954 <1> ; call swap_queue_shift 3955 <1> ; ; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0) 3956 <1> ; ;sub eax, eax ; 0 ; Error Code = 0 (no error) 3957 <1> ; ; zf = 1 3958 <1> ;swpin_retn: 3959 <1> ; pop ecx 3960 <1> ; pop ebx 3961 <1> ; pop esi 3962 <1> ; retn 3963 <1> ; 3964 <1> ;swpin_dnp_err: 3965 <1> ; mov eax, SWP_DISK_NOT_PRESENT_ERR 3966 <1> ;swpin_err_retn: 3967 <1> ; mov [u.error], eax 3968 <1> ; stc 3969 <1> ; retn 3970 <1> ; 3971 <1> ;swpin_snp_err: 3972 <1> ; mov eax, SWP_SECTOR_NOT_PRESENT_ERR 3973 <1> ; jmp short swpin_err_retn 3974 <1> 3975 <1> ; 24/12/2021 3976 <1> ; ('swap_out' procedure call is disabled) 3977 <1> 3978 <1> ;swap_out: 3979 <1> ; 10/06/2016 3980 <1> ; 07/06/2016 3981 <1> ; 23/05/2016 3982 <1> ; 19/05/2016 - TRDOS 386 (TRDOS v2.0) 3983 <1> ; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1) 3984 <1> ; 3985 <1> ; INPUT -> 3986 <1> ; none 3987 <1> ; 3988 <1> ; OUTPUT -> 3989 <1> ; EAX = Physical page address (which is swapped out 3990 <1> ; for allocating a new page) 3991 <1> ; CF = 1 -> swap disk writing error (disk/file not present 3992 <1> ; or sector not present or drive not ready 3993 <1> ; EAX = Error code 3994 <1> ; [u.error] = EAX 3995 <1> ; = The last error code for the process 3996 <1> ; (will be reset after returning to user) 3997 <1> ; 3998 <1> ; Modified Registers -> none (except EAX) 3999 <1> ; 4000 <1> 4001 <1> ; cmp word [swpq_count], 1 4002 <1> ; jc swpout_im_err ; 'insufficient memory' 4003 <1> ; 4004 <1> ; ;cmp dword [swp_drv], 1 4005 <1> ; ;jc short swpout_dnp_err ; 'swap disk/file not present' 4006 <1> ; 4007 <1> ; cmp dword [swpd_free], 1 4008 <1> ; jc swpout_nfspc_err ; 'no free space on swap disk' 4009 <1> ; 4010 <1> ; push ebx ; * 4011 <1> ;swpout_1: 4012 <1> ; ; 10/06/2016 4013 <1> ; xor ebx, ebx ; shift the queue and return a PTE value 4014 <1> ; call swap_queue_shift 4015 <1> ; and eax, eax ; 0 = empty queue (improper entries) 4016 <1> ; jz swpout_npts_err ; There is not any proper PTE 4017 <1> ; ; pointer in the swap queue 4018 <1> ; ; EAX = PTE value of the page 4019 <1> ; ; EBX = PTE address of the page 4020 <1> ; and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 4021 <1> ; ; 4022 <1> ; ; 07/06/2016 4023 <1> ; ; 19/05/2016 4024 <1> ; ; check this page is in timer events or not 4025 <1> ; 4026 <1> ;swpout_timer_page_0: 4027 <1> ; push edx ; ** 4028 <1> ; 4029 <1> ; ; 07/06/2016 4030 <1> ; cmp byte [timer_events], 0 4031 <1> ; jna short swpout_2 4032 <1> ; ; 4033 <1> ; mov dl, [timer_events] 4034 <1> ; 4035 <1> ; push ecx ; *** 4036 <1> ; push ebx ; **** 4037 <1> ; mov ebx, timer_set ; beginning address of timer event 4038 <1> ; ; structures 4039 <1> ;swpout_timer_page_1: 4040 <1> ; mov cl, [ebx] 4041 <1> ; or cl, cl ; 0 = free, >0 = process number 4042 <1> ; jz short swpout_timer_page_3 4043 <1> ; mov ecx, [ebx+12] ; response (signal return) address 4044 <1> ; and cx, PTE_A_CLEAR ; clear offset part (right 12 bits) 4045 <1> ; ; of the response byte address, to 4046 <1> ; ; get beginning of the page address) 4047 <1> ; cmp eax, ecx 4048 <1> ; jne short swpout_timer_page_2 ; not same page 4049 <1> ; 4050 <1> ; ; !same page! 4051 <1> ; ; 4052 <1> ; ; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! - 4053 <1> ; ; This page will be used by the kernel to put timer event 4054 <1> ; ; response (signal return) byte at the requested address; 4055 <1> ; ; in order to prevent a possible wrong write (while 4056 <1> ; ; this page is swapped out) on physical memory, 4057 <1> ; ; we must protect this page against to be swapped out! 4058 <1> ; ; 4059 <1> ; pop ebx ; **** 4060 <1> ; pop ecx ; *** 4061 <1> ; pop edx ; ** 4062 <1> ; jmp short swpout_1 ; do not swap out this page ! 4063 <1> ; 4064 <1> ;swpout_timer_page_2: 4065 <1> ; ; 07/06/2016 4066 <1> ; dec dl 4067 <1> ; jz short swpout_timer_page_4 4068 <1> ;swpout_timer_page_3: 4069 <1> ; ;cmp ebx, timer_set + 240 ; last timer event (15*16) 4070 <1> ; ;jnb short swpout_timer_page_4 4071 <1> ; add ebx, 16 4072 <1> ; jmp short swpout_timer_page_1 4073 <1> ; 4074 <1> ;swpout_timer_page_4: 4075 <1> ; pop ebx ; **** 4076 <1> ; pop ecx ; *** 4077 <1> ;swpout_2: 4078 <1> ; mov edx, ebx ; Page table entry address 4079 <1> ; mov ebx, eax ; Buffer (Page) Address 4080 <1> ; ; 4081 <1> ; call link_swap_block 4082 <1> ; jnc short swpout_3 ; It may not be needed here 4083 <1> ; ; because [swpd_free] value 4084 <1> ; ; was checked at the beginging. 4085 <1> ; pop edx ; ** 4086 <1> ; pop ebx ; * 4087 <1> ; jmp short swpout_nfspc_err 4088 <1> ;swpout_3: 4089 <1> ; test eax, 80000000h ; test bit 31 (this may not be needed!) 4090 <1> ; jnz short swpout_nfspc_err ; 10/06/2016 (bit 31 = 1 !) 4091 <1> ; ; 4092 <1> ; push esi ; ** 4093 <1> ; push ecx ; *** 4094 <1> ; push eax ; sector address ; (31 bit !, bit 31 = 0) 4095 <1> ; mov esi, [swp_drv] 4096 <1> ; mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 4097 <1> ; ; Note: Even if corresponding physical disk's sector 4098 <1> ; ; size different than 512 bytes, logical disk sector 4099 <1> ; ; size is 512 bytes and disk writing procedure 4100 <1> ; ; will be performed for writing 4096 bytes 4101 <1> ; ; (2*2048, 8*512). 4102 <1> ; ; ESI = Logical disk description table address 4103 <1> ; ; EBX = Buffer (Page) address 4104 <1> ; ; EAX = Sector adress (offset address, logical sector number) 4105 <1> ; ; ECX = Sector count ; 8 sectors 4106 <1> ; ; edx = PTE address 4107 <1> ; call logical_disk_write 4108 <1> ; ; edx = PTE address 4109 <1> ; pop ecx ; sector address 4110 <1> ; jnc short swpout_write_ok 4111 <1> ; ; 4112 <1> ; ;; call unlink_swap_block ; this block must be left as 'in use' 4113 <1> ;swpout_dw_err: 4114 <1> ; mov eax, SWP_DISK_WRITE_ERR ; drive not ready or write error 4115 <1> ; mov [u.error], eax 4116 <1> ; jmp short swpout_retn 4117 <1> ; ; 4118 <1> ;swpout_write_ok: 4119 <1> ; ; EBX = Buffer (page) address 4120 <1> ; ; EDX = Page Table Entry address 4121 <1> ; ; ECX = Swap disk sector (file block) address (31 bit) 4122 <1> ; shl ecx, 1 ; 31 bit sector address from bit 1 to bit 31 4123 <1> ; mov [edx], ecx 4124 <1> ; ; bit 0 = 0 (swapped page) 4125 <1> ; mov eax, ebx 4126 <1> ;swpout_retn: 4127 <1> ; pop ecx ; *** 4128 <1> ; pop esi ; ** 4129 <1> ; pop ebx ; * 4130 <1> ; retn 4131 <1> ; 4132 <1> ;;swpout_dnp_err: 4133 <1> ;; mov eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present 4134 <1> ;; jmp short swpout_err_retn 4135 <1> ;swpout_nfspc_err: 4136 <1> ; mov eax, SWP_NO_FREE_SPACE_ERR ; no free space 4137 <1> ;swpout_err_retn: 4138 <1> ; mov [u.error], eax 4139 <1> ; ;stc 4140 <1> ; retn 4141 <1> ;swpout_npts_err: 4142 <1> ; mov eax, SWP_NO_PAGE_TO_SWAP_ERR 4143 <1> ; pop ebx 4144 <1> ; jmp short swpout_err_retn 4145 <1> ;swpout_im_err: 4146 <1> ; mov eax, ERR_MINOR_IM ; insufficient (out of) memory 4147 <1> ; jmp short swpout_err_retn 4148 <1> 4149 <1> ; 24/12/2021 4150 <1> ; ('swap_queue_shift' procedure call is disabled) 4151 <1> 4152 <1> ;swap_queue_shift: 4153 <1> ; 26/03/2017 4154 <1> ; 10/06/2016 4155 <1> ; 09/06/2016 - TRDOS 386 (TRDOS v2.0) 4156 <1> ; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1) 4157 <1> ; 4158 <1> ; INPUT -> 4159 <1> ; EBX = Virtual (linear) address (bit 12 to 31) 4160 <1> ; and process number combination (bit 0 to 11) 4161 <1> ; EBX = 0 -> shift/drop from the head (offset 0) 4162 <1> ; 4163 <1> ; OUTPUT -> 4164 <1> ; If EBX input > 0 4165 <1> ; the queue will be shifted 4 bytes (dword), 4166 <1> ; from the tail to the head, up to entry offset 4167 <1> ; which points to EBX input value or nothing 4168 <1> ; to do if EBX value is not found on the queue. 4169 <1> ; (The entry -with EBX value- will be removed 4170 <1> ; from the queue if it is found.) 4171 <1> ; 4172 <1> ; EAX = 0 4173 <1> ; 4174 <1> ; If EBX input = 0 4175 <1> ; the queue will be shifted 4 bytes (dword), 4176 <1> ; from the tail to the head, if the PTE address 4177 <1> ; which is pointed in head of the queue is marked 4178 <1> ; as "accessed" or it is marked as "non present". 4179 <1> ; (If "accessed" flag of the PTE -which is pointed 4180 <1> ; in the head- is set -to 1-, it will be reset 4181 <1> ; -to 0- and then, the queue will be rotated 4182 <1> ; -without dropping pointer of the PTE from 4183 <1> ; the queue- for 4 bytes on head to tail direction. 4184 <1> ; Pointer in the head will be moved into the tail, 4185 <1> ; other PTEs will be shifted on head direction.) 4186 <1> ; 4187 <1> ; Swap queue will be shifted up to the first 4188 <1> ; 'present' or 'non accessed' page will be found 4189 <1> ; (as pointed) on the queue head (then it will be 4190 <1> ; removed/dropped from the queue). 4191 <1> ; 4192 <1> ; EAX (> 0) = PTE value of the page which is 4193 <1> ; (it's pointer -virtual address-) dropped 4194 <1> ; (removed) from swap queue. 4195 <1> ; EBX = PTE address of the page (if EAX > 0) 4196 <1> ; which is (it's pointer -virtual address-) 4197 <1> ; dropped (removed) from swap queue. 4198 <1> ; 4199 <1> ; EAX = 0 -> empty swap queue ! 4200 <1> ; 4201 <1> ; Modified Registers -> EAX, EBX 4202 <1> ; 4203 <1> ; movzx eax, word [swpq_count] ; Max. 1024 4204 <1> ; and ax, ax 4205 <1> ; jz short swpqs_retn 4206 <1> ; push edi 4207 <1> ; push esi 4208 <1> ; push ecx 4209 <1> ; mov esi, swap_queue 4210 <1> ; mov ecx, eax 4211 <1> ; or ebx, ebx 4212 <1> ; jz short swpqs_7 4213 <1> ;swpqs_1: 4214 <1> ; lodsd 4215 <1> ; cmp eax, ebx 4216 <1> ; je short swpqs_2 4217 <1> ; loop swpqs_1 4218 <1> ; ; 10/06/2016 4219 <1> ; sub eax, eax 4220 <1> ; jmp short swpqs_6 4221 <1> ;swpqs_2: 4222 <1> ; mov edi, esi 4223 <1> ; sub edi, 4 4224 <1> ;swpqs_3: 4225 <1> ; dec word [swpq_count] 4226 <1> ; jz short swpqs_5 4227 <1> ;swpqs_4: 4228 <1> ; dec ecx 4229 <1> ; rep movsd ; shift up (to the head) 4230 <1> ;swpqs_5: 4231 <1> ; xor eax, eax 4232 <1> ; mov [edi], eax 4233 <1> ;swpqs_6: 4234 <1> ; pop ecx 4235 <1> ; pop esi 4236 <1> ; pop edi 4237 <1> ;swpqs_retn: 4238 <1> ; retn 4239 <1> ;swpqs_7: 4240 <1> ; mov edi, esi ; head 4241 <1> ; lodsd 4242 <1> ; ; 20/07/2015 4243 <1> ; mov ebx, eax 4244 <1> ; and ebx, ~PAGE_OFF ; ~0FFFh 4245 <1> ; ; ebx = virtual address (at page boundary) 4246 <1> ; and eax, PAGE_OFF ; 0FFFh 4247 <1> ; ; ax = process number (1 to 4095) 4248 <1> ; cmp al, [u.uno] 4249 <1> ; ; Max. 16 (nproc) processes for Retro UNIX 386 v1 4250 <1> ; jne short swpqs_8 4251 <1> ; mov eax, [u.pgdir] 4252 <1> ; jmp short swpqs_9 4253 <1> ;swpqs_8: 4254 <1> ; ; 09/06/2016 4255 <1> ; cmp byte [eax+p.stat-1], 0 4256 <1> ; jna short swpqs_3 ; free (or terminated) process 4257 <1> ; cmp byte [eax+p.stat-1], 2 ; waiting 4258 <1> ; ja short swpqs_3 ; zombie (3) or undefined ? 4259 <1> ; 4260 <1> ; ;shl ax, 2 4261 <1> ; shl al, 2 4262 <1> ; mov eax, [eax+p.upage-4] 4263 <1> ; or eax, eax 4264 <1> ; jz short swpqs_3 ; invalid upage 4265 <1> ; add eax, u.pgdir - user 4266 <1> ; ; u.pgdir value for the process 4267 <1> ; ; is in [eax] 4268 <1> ; mov eax, [eax] 4269 <1> ; and eax, eax 4270 <1> ; jz short swpqs_3 ; invalid page directory 4271 <1> ;swpqs_9: 4272 <1> ; push edx 4273 <1> ; ; eax = page directory 4274 <1> ; ; ebx = virtual address 4275 <1> ; call get_pte 4276 <1> ; mov ebx, edx ; PTE address 4277 <1> ; pop edx 4278 <1> ; ; 10/06/2016 4279 <1> ; jc short swpqs_13 ; empty PDE 4280 <1> ; ; EAX = PTE value 4281 <1> ; test al, PTE_A_PRESENT ; bit 0 = 1 4282 <1> ; jz short swpqs_13 ; Drop non-present page 4283 <1> ; ; from the queue (head) 4284 <1> ; test al, PTE_A_WRITE ; bit 1 = 0 (read only) 4285 <1> ; jz short swpqs_13 ; Drop read only page 4286 <1> ; ; from the queue (head) 4287 <1> ; ;test al, PTE_A_ACCESS ; bit 5 = 1 (Accessed) 4288 <1> ; ;jnz short swpqs_11 ; present 4289 <1> ; ; accessed page 4290 <1> ; btr eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit 4291 <1> ; jc short swpqs_11 ; accessed page 4292 <1> ; 4293 <1> ; dec ecx 4294 <1> ; mov [swpq_count], cx 4295 <1> ; jz short swpqs_10 4296 <1> ; ; esi = head + 4 4297 <1> ; ; edi = head 4298 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 4299 <1> ;swpqs_10: 4300 <1> ; mov [edi], ecx ; 0 4301 <1> ; jmp short swpqs_6 ; 26/03/2017 4302 <1> ; 4303 <1> ;swpqs_11: 4304 <1> ; mov [ebx], eax ; save changed attribute 4305 <1> ; ; Rotation (head -> tail) 4306 <1> ; dec ecx ; entry count -> last entry number 4307 <1> ; jz short swpqs_10 4308 <1> ; ; esi = head + 4 4309 <1> ; ; edi = head 4310 <1> ; mov eax, [edi] ; 20/07/2015 4311 <1> ; rep movsd ; n = 1 to k-1, [n - 1] = [n] 4312 <1> ; mov [edi], eax ; head -> tail ; [k] = [1] 4313 <1> ; 4314 <1> ; mov cx, [swpq_count] 4315 <1> ; 4316 <1> ;swpqs_12: 4317 <1> ; mov esi, swap_queue ; head 4318 <1> ; jmp swpqs_7 4319 <1> ; 4320 <1> ;swpqs_13: 4321 <1> ; dec ecx 4322 <1> ; mov [swpq_count], cx 4323 <1> ; jz swpqs_5 4324 <1> ; jmp short swpqs_12 4325 <1> 4326 <1> ; 24/12/2021 4327 <1> ; ('add_to_swp_queue' procedure call is disabled) 4328 <1> 4329 <1> ;add_to_swap_queue: 4330 <1> ; 20/02/2017 4331 <1> ; 20/07/2015 4332 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4333 <1> ; 4334 <1> ; Adds new page to swap queue 4335 <1> ; (page directories and page tables must not be added 4336 <1> ; to swap queue) 4337 <1> ; 4338 <1> ; INPUT -> 4339 <1> ; EBX = Linear (Virtual) addr for current process 4340 <1> ; [u.uno] 4341 <1> ; 20/02/2017 4342 <1> ; (Linear address = CORE + user's virtual address) 4343 <1> ; 4344 <1> ; OUTPUT -> 4345 <1> ; EAX = [swpq_count] 4346 <1> ; (after the PTE has been added) 4347 <1> ; EAX = 0 -> Swap queue is full, (1024 entries) 4348 <1> ; the PTE could not be added. 4349 <1> ; 4350 <1> ; Modified Registers -> EAX 4351 <1> ; 4352 <1> ; push ebx 4353 <1> ; and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 4354 <1> ; mov bl, [u.uno] ; current process number 4355 <1> ; call swap_queue_shift ; drop from the queue if 4356 <1> ; ; it is already on the queue 4357 <1> ; ; then add it to the tail of the queue 4358 <1> ; movzx eax, word [swpq_count] 4359 <1> ; cmp ax, 1024 4360 <1> ; jb short atsq_1 4361 <1> ; sub ax, ax 4362 <1> ; pop ebx 4363 <1> ; retn 4364 <1> ;atsq_1: 4365 <1> ; push esi 4366 <1> ; mov esi, swap_queue 4367 <1> ; and ax, ax 4368 <1> ; jz short atsq_2 4369 <1> ; shl ax, 2 ; convert to offset 4370 <1> ; add esi, eax 4371 <1> ; shr ax, 2 4372 <1> ;atsq_2: 4373 <1> ; inc ax 4374 <1> ; mov [esi], ebx ; Virtual address + [u.uno] combination 4375 <1> ; mov [swpq_count], ax 4376 <1> ; pop esi 4377 <1> ; pop ebx 4378 <1> ; retn 4379 <1> 4380 <1> ; 24/12/2021 4381 <1> ; ('unlink_swap_block' procedure call is disabled) 4382 <1> 4383 <1> ;unlink_swap_block: 4384 <1> ; 15/09/2015 4385 <1> ; 30/04/2015 4386 <1> ; 18/04/2015 4387 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4388 <1> ; 4389 <1> ; INPUT -> 4390 <1> ; EAX = swap disk/file offset address 4391 <1> ; (bit 1 to bit 31) 4392 <1> ; OUTPUT -> 4393 <1> ; [swpd_free] is increased 4394 <1> ; (corresponding SWAP DISK ALLOC. TABLE bit is SET) 4395 <1> ; 4396 <1> ; Modified Registers -> EAX 4397 <1> ; 4398 <1> ; push ebx 4399 <1> ; push edx 4400 <1> ; ; 4401 <1> ; shr eax, SECTOR_SHIFT+1 ;3+1 ; shift sector address to 4402 <1> ; ; 3 bits right 4403 <1> ; ; to get swap block/page number 4404 <1> ; mov edx, eax 4405 <1> ; ; 15/09/2015 4406 <1> ; shr edx, 3 ; to get offset to S.A.T. 4407 <1> ; ; (1 allocation bit = 1 page) 4408 <1> ; ; (1 allocation bytes = 8 pages) 4409 <1> ; and dl, 0FCh ; clear lower 2 bits 4410 <1> ; ; (to get 32 bit position) 4411 <1> ; ; 4412 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table address 4413 <1> ; add ebx, edx 4414 <1> ; and eax, 1Fh ; lower 5 bits only 4415 <1> ; ; (allocation bit position) 4416 <1> ; cmp eax, [swpd_next] ; is the new free block addr. lower 4417 <1> ; ; than the address in 'swpd_next' ? 4418 <1> ; ; (next/first free block value) 4419 <1> ; jnb short uswpbl_1 ; no 4420 <1> ; mov [swpd_next], eax ; yes 4421 <1> ;uswpbl_1: 4422 <1> ; bts [ebx], eax ; unlink/release/deallocate block 4423 <1> ; ; set relevant bit to 1. 4424 <1> ; ; set CF to the previous bit value 4425 <1> ; cmc ; complement carry flag 4426 <1> ; jc short uswpbl_2 ; do not increase swfd_free count 4427 <1> ; ; if the block is already deallocated 4428 <1> ; ; before. 4429 <1> ; inc dword [swpd_free] 4430 <1> ;uswpbl_2: 4431 <1> ; pop edx 4432 <1> ; pop ebx 4433 <1> ; retn 4434 <1> 4435 <1> ; 24/12/2021 4436 <1> ; ('link_swap_block' procedure call is disabled) 4437 <1> 4438 <1> ;link_swap_block: 4439 <1> ; 01/07/2015 4440 <1> ; 18/04/2015 4441 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 4442 <1> ; 4443 <1> ; INPUT -> none 4444 <1> ; 4445 <1> ; OUTPUT -> 4446 <1> ; EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes) 4447 <1> ; in sectors (corresponding 4448 <1> ; SWAP DISK ALLOCATION TABLE bit is RESET) 4449 <1> ; 4450 <1> ; CF = 1 and EAX = 0 4451 <1> ; if there is not a free block to be allocated 4452 <1> ; 4453 <1> ; Modified Registers -> none (except EAX) 4454 <1> ; 4455 <1> 4456 <1> ; ;mov eax, [swpd_free] 4457 <1> ; ;and eax, eax 4458 <1> ; ;jz short out_of_swpspc 4459 <1> ; ; 4460 <1> ; push ebx 4461 <1> ; push ecx 4462 <1> ; ; 4463 <1> ; mov ebx, swap_alloc_table ; Swap Allocation Table offset 4464 <1> ; mov ecx, ebx 4465 <1> ; add ebx, [swpd_next] ; Free block searching starts from here 4466 <1> ; ; next_free_swap_block >> 5 4467 <1> ; add ecx, [swpd_last] ; Free block searching ends here 4468 <1> ; ; (total_swap_blocks - 1) >> 5 4469 <1> ;lswbl_scan: 4470 <1> ; cmp ebx, ecx 4471 <1> ; ja short lswbl_notfound 4472 <1> ; ; 4473 <1> ; bsf eax, [ebx] ; Scans source operand for first bit set (1). 4474 <1> ; ; Clears ZF if a bit is found set (1) and 4475 <1> ; ; loads the destination with an index to 4476 <1> ; ; first set bit. (0 -> 31) 4477 <1> ; ; Sets ZF to 1 if no bits are found set. 4478 <1> ; ; 01/07/2015 4479 <1> ; jnz short lswbl_found ; ZF = 0 -> a free block has been found 4480 <1> ; ; 4481 <1> ; ; NOTE: a Swap Disk Allocation Table bit 4482 <1> ; ; with value of 1 means 4483 <1> ; ; the corresponding page is free 4484 <1> ; ; (Retro UNIX 386 v1 feaure only!) 4485 <1> ; add ebx, 4 4486 <1> ; ; We return back for searching next page block 4487 <1> ; ; NOTE: [swpd_free] is not ZERO; so, 4488 <1> ; ; we always will find at least 1 free block here. 4489 <1> ; jmp short lswbl_scan 4490 <1> ; ; 4491 <1> ;lswbl_notfound: 4492 <1> ; sub ecx, swap_alloc_table 4493 <1> ; mov [swpd_next], ecx ; next/first free page = last page 4494 <1> ; ; (unlink_swap_block procedure will change it) 4495 <1> ; xor eax, eax 4496 <1> ; mov [swpd_free], eax 4497 <1> ; stc 4498 <1> ;lswbl_ok: 4499 <1> ; pop ecx 4500 <1> ; pop ebx 4501 <1> ; retn 4502 <1> ; ; 4503 <1> ;;out_of_swpspc: 4504 <1> ;; stc 4505 <1> ;; retn 4506 <1> ; 4507 <1> ;lswbl_found: 4508 <1> ; mov ecx, ebx 4509 <1> ; sub ecx, swap_alloc_table 4510 <1> ; mov [swpd_next], ecx ; Set first free block searching start 4511 <1> ; ; address/offset (to the next) 4512 <1> ; dec dword [swpd_free] ; 1 block has been allocated (X = X-1) 4513 <1> ; ; 4514 <1> ; btr [ebx], eax ; The destination bit indexed by the source value 4515 <1> ; ; is copied into the Carry Flag and then cleared 4516 <1> ; ; in the destination. 4517 <1> ; ; 4518 <1> ; ; Reset the bit which is corresponding to the 4519 <1> ; ; (just) allocated block. 4520 <1> ; shl ecx, 5 ; (block offset * 32) + block index 4521 <1> ; add eax, ecx ; = block number 4522 <1> ; shl eax, SECTOR_SHIFT ; 3, sector (offset) address of the block 4523 <1> ; ; 1 block = 8 sectors 4524 <1> ; ; 4525 <1> ; ; EAX = offset address of swap disk/file sector (beginning of the block) 4526 <1> ; ; 4527 <1> ; ; NOTE: The relevant page table entry will be updated 4528 <1> ; ; according to this EAX value... 4529 <1> ; ; 4530 <1> ; jmp short lswbl_ok 4531 <1> 4532 <1> ; 24/12/2021 4533 <1> ; ('logical_disk_read' procedure call is disabled) 4534 <1> 4535 <1> ;logical_disk_read: 4536 <1> ; 20/07/2015 4537 <1> ; 09/03/2015 (temporary code here) 4538 <1> ; 4539 <1> ; INPUT -> 4540 <1> ; ESI = Logical disk description table address 4541 <1> ; EBX = Memory page (buffer) address (physical!) 4542 <1> ; EAX = Sector adress (offset address, logical sector number) 4543 <1> ; ECX = Sector count 4544 <1> ; 4545 <1> ; 4546 <1> ; retn 4547 <1> 4548 <1> ; 24/12/2021 4549 <1> ; ('logical_disk_write' procedure call is disabled) 4550 <1> 4551 <1> ;logical_disk_write: 4552 <1> ; 20/07/2015 4553 <1> ; 09/03/2015 (temporary code here) 4554 <1> ; 4555 <1> ; INPUT -> 4556 <1> ; ESI = Logical disk description table address 4557 <1> ; EBX = Memory page (buffer) address (physical!) 4558 <1> ; EAX = Sector adress (offset address, logical sector number) 4559 <1> ; ECX = Sector count 4560 <1> ; 4561 <1> ; retn 4562 <1> 4563 <1> get_physical_addr: 4564 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4565 <1> ; 19/04/2020 - Retro UNIX 386 v2 4566 <1> ; 18/10/2015 4567 <1> ; 29/07/2015 4568 <1> ; 20/07/2015 4569 <1> ; 04/06/2015 4570 <1> ; 20/05/2015 4571 <1> ; 28/04/2015 4572 <1> ; 18/04/2015 4573 <1> ; Get physical address 4574 <1> ; (allocates a new page for user if it is not present) 4575 <1> ; 4576 <1> ; (This subroutine is needed for mapping user's virtual 4577 <1> ; (buffer) address to physical address (of the buffer).) 4578 <1> ; ('sys write', 'sys read' system calls...) 4579 <1> ; 4580 <1> ; INPUT -> 4581 <1> ; EBX = virtual address 4582 <1> ; u.pgdir = page directory (physical) address 4583 <1> ; 4584 <1> ; OUTPUT -> 4585 <1> ; EAX = physical address 4586 <1> ; EBX = linear address 4587 <1> ; EDX = physical address of the page frame 4588 <1> ; (with attribute bits) 4589 <1> ; ECX = byte count within the page frame 4590 <1> ; 4591 <1> ; Modified Registers -> EAX, EBX, ECX, EDX 4592 <1> ; 4593 <1> 4594 <1> ; 19/04/2020 - Retro UNIX386 v2 4595 000027A9 A1[45650000] <1> mov eax, [u.pgdir] 4596 <1> 4597 <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2 4598 <1> 4599 000027AE 81C300004000 <1> add ebx, CORE ; 18/10/2015 4600 <1> ; 4601 <1> ;mov eax, [u.pgdir] 4602 000027B4 E81AFDFFFF <1> call get_pte 4603 <1> ; EDX = Page table entry address (if CF=0) 4604 <1> ; Page directory entry address (if CF=1) 4605 <1> ; (Bit 0 value is 0 if PT is not present) 4606 <1> ; EAX = Page table entry value (page address) 4607 <1> ; CF = 1 -> PDE not present or invalid ? 4608 000027B9 731C <1> jnc short gpa_1 4609 <1> ; 4610 000027BB E801FCFFFF <1> call allocate_page 4611 000027C0 724B <1> jc short gpa_im_err ; 'insufficient memory' error 4612 <1> gpa_0: 4613 000027C2 E86BFCFFFF <1> call clear_page 4614 <1> ; EAX = Physical (base) address of the allocated (new) page 4615 000027C7 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7 4616 <1> ; lower 3 bits are used as U/S, R/W, P flags 4617 <1> ; (user, writable, present page) 4618 000027C9 8902 <1> mov [edx], eax ; Let's put the new page directory entry here ! 4619 000027CB A1[45650000] <1> mov eax, [u.pgdir] 4620 000027D0 E8FEFCFFFF <1> call get_pte 4621 000027D5 7236 <1> jc short gpa_im_err ; 'insufficient memory' error 4622 <1> gpa_1: 4623 <1> ; EAX = PTE value, EDX = PTE address 4624 000027D7 A801 <1> test al, PTE_A_PRESENT 4625 000027D9 750A <1> jnz short gpa_3 4626 000027DB 09C0 <1> or eax, eax 4627 000027DD 7420 <1> jz short gpa_4 ; Allocate a new page 4628 <1> 4629 <1> ; 24/12/2021 4630 <1> ; ('reload_page' procedure call is disabled) 4631 000027DF EB2C <1> jmp short gpa_im_err 4632 <1> 4633 <1> ; 20/07/2015 4634 <1> ; push ebp 4635 <1> ; mov ebp, ebx ; virtual (linear) address 4636 <1> ; ; reload swapped page 4637 <1> ; call reload_page ; 28/04/2015 4638 <1> ; pop ebp 4639 <1> ; jc short gpa_retn 4640 <1> gpa_2: 4641 <1> ; 24/12/2021 4642 <1> ; ('add_to_swap_queue' procedure call is disabled) 4643 <1> 4644 <1> ; 20/07/2015 4645 <1> ; 20/05/2015 4646 <1> ; add this page to swap queue 4647 <1> ; push eax 4648 <1> ; ; EBX = Linear (CORE+virtual) address ; 20/02/2017 4649 <1> ; call add_to_swap_queue 4650 <1> ; pop eax 4651 <1> ; PTE address in EDX 4652 <1> ; virtual address in EBX 4653 <1> ; EAX = memory page address 4654 000027E1 0C07 <1> or al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE 4655 <1> ; present flag, bit 0 = 1 4656 <1> ; user flag, bit 2 = 1 4657 <1> ; writable flag, bit 1 = 1 4658 000027E3 8902 <1> mov [edx], eax ; Update PTE value 4659 <1> gpa_3: 4660 <1> ; 18/10/2015 4661 000027E5 89D9 <1> mov ecx, ebx 4662 000027E7 81E1FF0F0000 <1> and ecx, PAGE_OFF 4663 000027ED 89C2 <1> mov edx, eax 4664 000027EF 662500F0 <1> and ax, PTE_A_CLEAR 4665 000027F3 01C8 <1> add eax, ecx 4666 000027F5 F7D9 <1> neg ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095 4667 000027F7 81C100100000 <1> add ecx, PAGE_SIZE 4668 000027FD F8 <1> clc 4669 <1> gpa_retn: 4670 000027FE C3 <1> retn 4671 <1> gpa_4: 4672 000027FF E8BDFBFFFF <1> call allocate_page 4673 00002804 7207 <1> jc short gpa_im_err ; 'insufficient memory' error 4674 00002806 E827FCFFFF <1> call clear_page 4675 0000280B EBD4 <1> jmp short gpa_2 4676 <1> 4677 <1> gpa_im_err: 4678 0000280D B804000000 <1> mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 4679 <1> ; Major error = 0 (No protection fault) 4680 00002812 C3 <1> retn 4681 <1> 4682 <1> ; 24/12/2021 4683 <1> ; ('reload_page' procedure call is disabled) 4684 <1> 4685 <1> ;reload_page: 4686 <1> ; 20/07/2015 4687 <1> ; 28/04/2015 (Retro UNIX 386 v1 - beginning) 4688 <1> ; 4689 <1> ; Reload (Restore) swapped page at memory 4690 <1> ; 4691 <1> ; INPUT -> 4692 <1> ; EBP = Virtual (linear) memory address 4693 <1> ; EAX = PTE value (swap disk sector address) 4694 <1> ; (Swap disk sector address = bit 1 to bit 31 of EAX) 4695 <1> ; OUTPUT -> 4696 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE 4697 <1> ; 4698 <1> ; CF = 1 and EAX = error code 4699 <1> ; 4700 <1> ; Modified Registers -> none (except EAX) 4701 <1> ; 4702 <1> ; shr eax, 1 ; Convert PTE value to swap disk address 4703 <1> ; push ebx ; 4704 <1> ; mov ebx, eax ; Swap disk (offset) address 4705 <1> ; call allocate_page 4706 <1> ; jc short rlp_im_err 4707 <1> ; xchg eax, ebx 4708 <1> ; ; EBX = Physical memory (page) address 4709 <1> ; ; EAX = Swap disk (offset) address 4710 <1> ; ; EBP = Virtual (linear) memory address 4711 <1> ; call swap_in 4712 <1> ; jc short rlp_swp_err ; (swap disk/file read error) 4713 <1> ; mov eax, ebx 4714 <1> ;rlp_retn: 4715 <1> ; pop ebx 4716 <1> ; retn 4717 <1> ; 4718 <1> ;rlp_im_err: 4719 <1> ; mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 4720 <1> ; ; Major error = 0 (No protection fault) 4721 <1> ; jmp short rlp_retn 4722 <1> ; 4723 <1> ;rlp_swp_err: 4724 <1> ; mov eax, SWP_DISK_READ_ERR ; Swap disk read error ! 4725 <1> ; jmp short rlp_retn 4726 <1> 4727 <1> copy_page_dir: 4728 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4729 <1> ; 19/09/2015 4730 <1> ; temporary - 07/09/2015 4731 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 4732 <1> ; 4733 <1> ; INPUT -> 4734 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 4735 <1> ; page directory. 4736 <1> ; OUTPUT -> 4737 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 4738 <1> ; page directory. 4739 <1> ; (New page directory with new page table entries.) 4740 <1> ; (New page tables with read only copies of the parent's 4741 <1> ; pages.) 4742 <1> ; EAX = 0 -> Error (CF = 1) 4743 <1> ; 4744 <1> ; Modified Registers -> none (except EAX) 4745 <1> ; 4746 00002813 E8A9FBFFFF <1> call allocate_page 4747 00002818 723E <1> jc short cpd_err 4748 <1> ; 4749 0000281A 55 <1> push ebp ; 20/07/2015 4750 0000281B 56 <1> push esi 4751 0000281C 57 <1> push edi 4752 0000281D 53 <1> push ebx 4753 0000281E 51 <1> push ecx 4754 0000281F 8B35[45650000] <1> mov esi, [u.pgdir] 4755 00002825 89C7 <1> mov edi, eax 4756 00002827 50 <1> push eax ; save child's page directory address 4757 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 4758 <1> ; (use same system space for all user page tables) 4759 00002828 A5 <1> movsd 4760 00002829 BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 4761 0000282E B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 4762 <1> cpd_0: 4763 00002833 AD <1> lodsd 4764 <1> ;or eax, eax 4765 <1> ;jnz short cpd_1 4766 00002834 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 4767 00002836 7508 <1> jnz short cpd_1 4768 <1> ; (virtual address at the end of the page table) 4769 00002838 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 4770 0000283E EB0F <1> jmp short cpd_2 4771 <1> cpd_1: 4772 00002840 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 4773 00002844 89C3 <1> mov ebx, eax 4774 <1> ; EBX = Parent's page table address 4775 00002846 E81F000000 <1> call copy_page_table 4776 0000284B 720C <1> jc short cpd_p_err 4777 <1> ; EAX = Child's page table address 4778 0000284D 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 4779 <1> ; set bit 0, bit 1 and bit 2 to 1 4780 <1> ; (present, writable, user) 4781 <1> cpd_2: 4782 0000284F AB <1> stosd 4783 00002850 E2E1 <1> loop cpd_0 4784 <1> ; 4785 00002852 58 <1> pop eax ; restore child's page directory address 4786 <1> cpd_3: 4787 00002853 59 <1> pop ecx 4788 00002854 5B <1> pop ebx 4789 00002855 5F <1> pop edi 4790 00002856 5E <1> pop esi 4791 00002857 5D <1> pop ebp 4792 <1> cpd_err: 4793 00002858 C3 <1> retn 4794 <1> cpd_p_err: 4795 <1> ; release the allocated pages missing (recover free space) 4796 00002859 58 <1> pop eax ; the new page directory address (physical) 4797 0000285A 8B1D[45650000] <1> mov ebx, [u.pgdir] ; parent's page directory address 4798 00002860 E88CFCFFFF <1> call deallocate_page_dir 4799 00002865 29C0 <1> sub eax, eax ; 0 4800 00002867 F9 <1> stc 4801 00002868 EBE9 <1> jmp short cpd_3 4802 <1> 4803 <1> copy_page_table: 4804 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4805 <1> ; 19/09/2015 4806 <1> ; temporary - 07/09/2015 4807 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 4808 <1> ; 4809 <1> ; INPUT -> 4810 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 4811 <1> ; EBP = page table entry index (from 'copy_page_dir') 4812 <1> ; OUTPUT -> 4813 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 4814 <1> ; EBP = (recent) page table index (for 'add_to_swap_queue') 4815 <1> ; CF = 1 -> error 4816 <1> ; 4817 <1> ; Modified Registers -> EBP (except EAX) 4818 <1> ; 4819 0000286A E852FBFFFF <1> call allocate_page 4820 0000286F 7244 <1> jc short cpt_err 4821 <1> ; 4822 00002871 50 <1> push eax ; * 4823 <1> ;push ebx 4824 00002872 56 <1> push esi 4825 00002873 57 <1> push edi 4826 00002874 52 <1> push edx 4827 00002875 51 <1> push ecx 4828 <1> ; 4829 00002876 89DE <1> mov esi, ebx 4830 00002878 89C7 <1> mov edi, eax 4831 0000287A 89C2 <1> mov edx, eax 4832 0000287C 81C200100000 <1> add edx, PAGE_SIZE 4833 <1> cpt_0: 4834 00002882 AD <1> lodsd 4835 00002883 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 4836 <1> ;jnz short cpt_1 (*) 4837 <1> ; 24/12/2021 4838 <1> ;and eax, eax (*) 4839 00002885 741E <1> jz short cpt_2 ; 24/12/2021 4840 <1> 4841 <1> ; 24/12/2021 4842 <1> ; ('reload_page' procedure call is disabled) 4843 <1> ; 4844 <1> ; ; ebp = virtual (linear) address of the memory page 4845 <1> ; call reload_page ; 28/04/2015 4846 <1> ; jc short cpt_p_err 4847 <1> cpt_1: 4848 00002887 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 4849 0000288B 89C1 <1> mov ecx, eax 4850 <1> ; Allocate a new page for the child process 4851 0000288D E82FFBFFFF <1> call allocate_page 4852 00002892 721C <1> jc short cpt_p_err 4853 00002894 57 <1> push edi 4854 00002895 56 <1> push esi 4855 00002896 89CE <1> mov esi, ecx 4856 00002898 89C7 <1> mov edi, eax 4857 0000289A B900040000 <1> mov ecx, PAGE_SIZE/4 4858 0000289F F3A5 <1> rep movsd ; copy page (4096 bytes) 4859 000028A1 5E <1> pop esi 4860 000028A2 5F <1> pop edi 4861 <1> ; 4862 <1> ; 24/12/2021 4863 <1> ; ('add_to_swap_queue' procedure call is disabled) 4864 <1> ; 4865 <1> ; push ebx 4866 <1> ; push eax 4867 <1> ; mov ebx, ebp 4868 <1> ; ; ebx = virtual address of the memory page 4869 <1> ; call add_to_swap_queue 4870 <1> ; pop eax 4871 <1> ; pop ebx 4872 <1> ; 4873 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 4874 000028A3 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 4875 <1> cpt_2: 4876 000028A5 AB <1> stosd ; EDI points to child's PTE 4877 <1> ; 4878 000028A6 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 4879 <1> ; 4880 000028AC 39D7 <1> cmp edi, edx 4881 000028AE 72D2 <1> jb short cpt_0 4882 <1> cpt_p_err: 4883 000028B0 59 <1> pop ecx 4884 000028B1 5A <1> pop edx 4885 000028B2 5F <1> pop edi 4886 000028B3 5E <1> pop esi 4887 <1> ;pop ebx 4888 000028B4 58 <1> pop eax ; * 4889 <1> cpt_err: 4890 000028B5 C3 <1> retn 4891 <1> 4892 <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS /// 4893 <1> 4894 <1> ;; Data: 4895 <1> 4896 <1> ; 09/03/2015 4897 <1> ;swpq_count: dw 0 ; count of pages on the swap que 4898 <1> ;swp_drv: dd 0 ; logical drive description table address of the swap drive/disk 4899 <1> ;swpd_size: dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 4900 <1> ;swpd_free: dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical) 4901 <1> ;swpd_next: dd 0 ; next free page block 4902 <1> ;swpd_last: dd 0 ; last swap page block 2112 %include 'sysdefs.inc' ; 09/03/2015 2113 <1> ; Retro UNIX 386 v1.1 Kernel (v0.2.1.6) - SYSDEFS.INC 2114 <1> ; Last Modification: 15/07/2022 2115 <1> ; 2116 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 2117 <1> ; (Modified from 2118 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 2119 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 2120 <1> ; UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11) 2121 <1> ; ---------------------------------------------------------------------------- 2122 <1> ; 2123 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2124 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2125 <1> ; 2126 <1> ; 2127 <1> ; 2128 <1> ; **************************************************************************** 2129 <1> 2130 <1> nproc equ 16 ; number of processes 2131 <1> nfiles equ 50 2132 <1> ntty equ 8 ; 8+1 -> 8 (10/05/2013) 2133 <1> ;nbuf equ 6 ; number of buffers (04/02/2016) 2134 <1> nbuf equ 8 ; 15/07/2022 2135 <1> 2136 <1> ;csgmnt equ 2000h ; 26/05/2013 (segment of process 1) 2137 <1> ;core equ 0 ; 19/04/2013 2138 <1> ;ecore equ 32768 - 64 ; 04/06/2013 (24/05/2013) 2139 <1> ; (if total size of argument list and arguments is 128 bytes) 2140 <1> ; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes 2141 <1> ; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570) 2142 <1> ; initial value of user's stack pointer = 32768-64-128-2 = 32574 2143 <1> ; (sp=32768-args_space-2 at the beginning of execution) 2144 <1> ; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes) 2145 <1> ; 'u' structure offset (for the '/core' dump file) = 32704 2146 <1> ; '/core' dump file size = 32768 bytes 2147 <1> 2148 <1> ; 08/03/2014 2149 <1> ;sdsegmnt equ 6C0h ; 256*16 bytes (swap data segment size for 16 processes) 2150 <1> ; 19/04/2013 Retro UNIX 8086 v1 feature only ! 2151 <1> ;;sdsegmnt equ 740h ; swap data segment (for user structures and registers) 2152 <1> 2153 <1> ; 30/08/2013 2154 <1> time_count equ 4 ; 10 --> 4 01/02/2014 2155 <1> 2156 <1> ; 05/02/2014 2157 <1> ; process status 2158 <1> ;SFREE equ 0 2159 <1> ;SRUN equ 1 2160 <1> ;SWAIT equ 2 2161 <1> ;SZOMB equ 3 2162 <1> ;SSLEEP equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup) 2163 <1> 2164 <1> ; 09/03/2015 2165 <1> userdata equ 80000h ; user structure data address for current user ; temporary 2166 <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary 2167 <1> swap_alloc_table equ 0D0000h ; swap allocation table address ; temporary 2168 <1> 2169 <1> ; 17/09/2015 2170 <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return 2171 <1> 2172 <1> ; 21/09/2015 (36) 2173 <1> ; 01/07/2015 (35) 2174 <1> ; 14/07/2013 (0-34) 2175 <1> ; UNIX v1 system calls 2176 <1> _rele equ 0 2177 <1> _exit equ 1 2178 <1> _fork equ 2 2179 <1> _read equ 3 2180 <1> _write equ 4 2181 <1> _open equ 5 2182 <1> _close equ 6 2183 <1> _wait equ 7 2184 <1> _creat equ 8 2185 <1> _link equ 9 2186 <1> _unlink equ 10 2187 <1> _exec equ 11 2188 <1> _chdir equ 12 2189 <1> _time equ 13 2190 <1> _mkdir equ 14 2191 <1> _chmod equ 15 2192 <1> _chown equ 16 2193 <1> _break equ 17 2194 <1> _stat equ 18 2195 <1> _seek equ 19 2196 <1> _tell equ 20 2197 <1> _mount equ 21 2198 <1> _umount equ 22 2199 <1> _setuid equ 23 2200 <1> _getuid equ 24 2201 <1> _stime equ 25 2202 <1> _quit equ 26 2203 <1> _intr equ 27 2204 <1> _fstat equ 28 2205 <1> _emt equ 29 2206 <1> _mdate equ 30 2207 <1> _stty equ 31 2208 <1> _gtty equ 32 2209 <1> _ilgins equ 33 2210 <1> _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 2211 <1> _msg equ 35 ; Retro UNIX 386 v1 feature only ! 2212 <1> _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 2213 <1> 2214 <1> %macro sys 1-4 2215 <1> ; 13/04/2015 2216 <1> ; Retro UNIX 386 v1 system call. 2217 <1> mov eax, %1 2218 <1> %if %0 >= 2 2219 <1> mov ebx, %2 2220 <1> %if %0 >= 3 2221 <1> mov ecx, %3 2222 <1> %if %0 = 4 2223 <1> mov edx, %4 2224 <1> %endif 2225 <1> %endif 2226 <1> %endif 2227 <1> int 30h 2228 <1> %endmacro 2229 <1> 2230 <1> ; 13/05/2015 - ERROR CODES 2231 <1> ERR_FILE_NOT_OPEN equ 10 ; 'file not open !' error 2232 <1> ERR_FILE_ACCESS equ 11 ; 'permission denied !' error 2233 <1> ; 14/05/2015 2234 <1> ERR_DIR_ACCESS equ 11 ; 'permission denied !' error 2235 <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error 2236 <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error 2237 <1> ERR_DIR_EXISTS equ 14 ; 'directory already exists !' error 2238 <1> ; 16/05/2015 2239 <1> ERR_DRV_NOT_RDY equ 15 ; 'drive not ready !' error 2240 <1> ; 18/05/2015 2241 <1> ERR_DEV_NOT_RDY equ 15 ; 'device not ready !' error 2242 <1> ERR_DEV_ACCESS equ 11 ; 'permission denied !' error 2243 <1> ERR_DEV_NOT_OPEN equ 10 ; 'device not open !' error 2244 <1> ; 07/06/2015 2245 <1> ERR_FILE_EOF equ 16 ; 'end of file !' error 2246 <1> ERR_DEV_VOL_SIZE equ 16 ; 'out of volume' error 2247 <1> ; 09/06/2015 2248 <1> ERR_DRV_READ equ 17 ; 'disk read error !' 2249 <1> ERR_DRV_WRITE equ 18 ; 'disk write error !' 2250 <1> ; 16/06/2015 2251 <1> ERR_NOT_DIR equ 19 ; 'not a (valid) directory !' error 2252 <1> ERR_FILE_SIZE equ 20 ; 'file size error !' 2253 <1> ; 22/06/2015 2254 <1> ERR_NOT_SUPERUSER equ 11 ; 'permission denied !' error 2255 <1> ERR_NOT_OWNER equ 11 ; 'permission denied !' error 2256 <1> ERR_NOT_FILE equ 11 ; 'permission denied !' error 2257 <1> ; 23/06/2015 2258 <1> ERR_FILE_EXISTS equ 14 ; 'file already exists !' error 2259 <1> ERR_DRV_NOT_SAME equ 21 ; 'not same drive !' error 2260 <1> ERR_DIR_NOT_FOUND equ 12 ; 'directory not found !' error 2261 <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error 2262 <1> ; 27/06/2015 2263 <1> ERR_INV_PARAMETER equ 23 ; 'invalid parameter !' error 2264 <1> ERR_INV_DEV_NAME equ 24 ; 'invalid device name !' error 2265 <1> ; 29/06/2015 2266 <1> ERR_TIME_OUT equ 25 ; 'time out !' error 2267 <1> ERR_DEV_NOT_RESP equ 25 ; 'device not responding !' error 2268 <1> ; 08/02/2022 2269 <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s') 2270 <1> ; 10/10/2016 2271 <1> ERR_INV_FILE_NAME equ 26 ; 'invalid file name !' error 2272 <1> ; 18/05/2016 2273 <1> ERR_MISC equ 27 ; miscellaneous/other errors 2274 <1> ; 15/10/2016 2275 <1> ERR_INV_FORMAT equ 28 ; 'invalid format !' error 2276 <1> ERR_INV_DATA equ 29 ; 'invalid data !' error 2277 <1> ; 16/10/2016 2278 <1> ERR_DISK_WRITE equ 30 ; 'disk write protected !' 2279 <1> ; 08/02/2022 2280 <1> ERR_INV_FS equ 28 ;'invalid fs/superblock !' error 2281 <1> 2282 <1> ; 13/06/2022 2283 <1> ; printer errors 2284 <1> ERR_PRN_NOT_RDY equ 15 ; 'device not ready !' error 2285 <1> ERR_PRN_TIMEOUT equ 25 ; 'time out !' error 2286 <1> ERR_PRN_PAPER equ 31 ; 'out of paper !' error 2287 <1> ERR_PRN_IO equ 32 ; 'io error !' error 2288 <1> ERR_PRN_BUSY equ 34 ; 'busy !' error 2289 <1> 2290 <1> ; 26/08/2015 2291 <1> ; 24/07/2015 2292 <1> ; 24/06/2015 2293 <1> MAX_ARG_LEN equ 256 ; max. length of sys exec arguments 2294 <1> ; 01/07/2015 2295 <1> MAX_MSG_LEN equ 255 ; max. msg length for 'sysmsg' 2296 <1> ; 24/12/2021 2297 <1> ERR_INV_FUNC equ 1 ; 'invalid system call !' error 2113 %include 'u0.s' ; 15/03/2015 2114 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS0.INC 2115 <1> ; Last Modification: 17/07/2022 2116 <1> ; ---------------------------------------------------------------------------- 2117 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2118 <1> ; (v0.1 - Beginning: 11/07/2012) 2119 <1> ; 2120 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2121 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2122 <1> ; 2123 <1> ; 2124 <1> ; 2125 <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s 2126 <1> ; 2127 <1> ; **************************************************************************** 2128 <1> 2129 <1> sys_init: 2130 <1> ; 26/02/2022 2131 <1> ; 08/01/2022 2132 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2133 <1> ; 18/10/2015 2134 <1> ; 28/08/2015 2135 <1> ; 24/08/2015 2136 <1> ; 14/08/2015 2137 <1> ; 24/07/2015 2138 <1> ; 02/07/2015 2139 <1> ; 01/07/2015 2140 <1> ; 23/06/2015 2141 <1> ; 15/04/2015 2142 <1> ; 13/03/2015 2143 <1> ; 11/03/2015 (Retro UNIX 386 v1 - Beginning) 2144 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2145 <1> ; 2146 <1> ;call ldrv_init ; Logical drive description tables initialization 2147 <1> ; 2148 <1> ; 14/02/2014 2149 <1> ; 14/07/2013 2150 <1> ;;mov ax, 41 2151 <1> ; 24/12/2021 2152 <1> ;xor eax, eax 2153 <1> ;mov al, 41 2154 <1> ;mov [rootdir], ax 2155 <1> ;mov [u.cdir], ax 2156 <1> ;;and al, 1 ; 15/04/2015 2157 <1> ;inc al ; ax = 1 2158 000028B6 B001 <1> mov al, 1 2159 000028B8 A2[3B650000] <1> mov [u.uno], al 2160 <1> ;mov [mpid], ax 2161 <1> ;mov [p.pid], ax 2162 000028BD A2[DA640000] <1> mov [mpid], al 2163 000028C2 A2[04620000] <1> mov [p.pid], al 2164 000028C7 A2[64620000] <1> mov [p.stat], al ; SRUN, 05/02/2014 2165 <1> ; 24/12/2021 2166 000028CC B029 <1> mov al, 41 2167 <1> ;mov [rootdir], ax 2168 <1> ;mov [u.cdir], ax 2169 000028CE A2[DC640000] <1> mov [rootdir], al 2170 000028D3 A2[F0640000] <1> mov [u.cdir], al 2171 <1> ; 2172 000028D8 B004 <1> mov al, time_count ; 30/08/2013 2173 000028DA A2[2E650000] <1> mov [u.quant], al ; 14/07/2013 2174 <1> ; 02/07/2015 2175 000028DF A1[28610000] <1> mov eax, [k_page_dir] 2176 <1> ;sub eax, eax 2177 000028E4 A3[45650000] <1> mov [u.pgdir], eax ; reset 2178 <1> ; 18/10/2015 2179 <1> ;mov [u.ppgdir], eax ; 0 2180 <1> ; 26/02/2022 2181 <1> ;call epoch 2182 <1> ;mov [s.time], eax ; 13/03/2015 2183 <1> ; 17/07/2013 2184 000028E9 E881060000 <1> call bf_init ; buffer initialization 2185 <1> ; 26/02/2022 2186 <1> ; (save sysinit time on sb0) 2187 000028EE E829030000 <1> call epoch 2188 000028F3 A3[48770000] <1> mov [s.time], eax ; 13/03/2015 2189 <1> ; 23/06/2015 2190 000028F8 E8C4FAFFFF <1> call allocate_page 2191 <1> ;;jc error 2192 <1> ;jc panic ; jc short panic (01/07/2015) 2193 <1> ; 24/12/2021 2194 000028FD 7305 <1> jnc short sysinit_1 2195 000028FF E989000000 <1> jmp panic 2196 <1> sysinit_1: 2197 00002904 A3[3C650000] <1> mov [u.upage], eax ; user structure page 2198 00002909 A3[74620000] <1> mov [p.upage], eax 2199 <1> ; 2200 0000290E E81FFBFFFF <1> call clear_page 2201 <1> ; 2202 <1> ; 14/08/2015 2203 00002913 FA <1> cli 2204 <1> ; 14/03/2015 2205 <1> ; 17/01/2014 2206 00002914 E8D0010000 <1> call sp_init ; serial port initialization 2207 <1> ; 14/08/2015 2208 00002919 FB <1> sti 2209 <1> ; 2210 <1> ; 30/06/2015 2211 <1> ;mov esi, kernel_init_ok_msg 2212 <1> ;call print_msg 2213 <1> ; 2214 0000291A 30DB <1> xor bl, bl ; video page 0 2215 <1> vp_clr_nxt: ; clear video pages (reset cursor positions) 2216 0000291C E8410F0000 <1> call vp_clr ; 17/07/2013 2217 00002921 FEC3 <1> inc bl 2218 00002923 80FB08 <1> cmp bl, 8 2219 00002926 72F4 <1> jb short vp_clr_nxt 2220 <1> ; 2221 <1> ; 24/07/2015 2222 <1> ;push KDATA 2223 <1> ;push esp 2224 <1> ;mov [tss.esp0], esp 2225 <1> ;mov word [tss.ss0], KDATA 2226 <1> ; 2227 <1> ; 08/01/2022 2228 <1> ; 24/08/2015 2229 <1> ;; temporary (01/07/2015) 2230 <1> ;mov byte [u.quant], time_count ; 4 2231 <1> ; it is not needed here ! 2232 <1> ;;inc byte [u.kcall] ; 'the caller is kernel' sign 2233 00002928 FE0D[E3640000] <1> dec byte [sysflg] ; FFh = ready for system call 2234 <1> ; 0 = executing a system call 2235 <1> ;;sys _msg, kernel_init_ok_msg, 255, 0 2236 <1> ; 2237 <1> ;;; 06/08/2015 2238 <1> ;;;call getch ; wait for a key stroke 2239 <1> ;;mov ecx, 0FFFFFFFh 2240 <1> ;;sys_init_msg_wait: 2241 <1> ;; push ecx 2242 <1> ;; mov al, 1 2243 <1> ;; mov ah, [ptty] ; active (current) video page 2244 <1> ;; call getc_n 2245 <1> ;; pop ecx 2246 <1> ;; jnz short sys_init_msg_ok 2247 <1> ;; loop sys_init_msg_wait 2248 <1> ; 2249 <1> ;;sys_init_msg_ok: 2250 <1> ; 28/08/2015 (initial settings for the 1st 'rswap') 2251 0000292E 6A10 <1> push KDATA ; ss 2252 00002930 54 <1> push esp 2253 00002931 9C <1> pushfd 2254 00002932 6A08 <1> push KCODE ; cs 2255 00002934 68[61290000] <1> push init_exec ; eip 2256 00002939 8925[E4640000] <1> mov [u.sp], esp 2257 0000293F 1E <1> push ds 2258 00002940 06 <1> push es 2259 00002941 0FA0 <1> push fs 2260 00002943 0FA8 <1> push gs 2261 00002945 60 <1> pushad 2262 00002946 8925[E8640000] <1> mov [u.usp], esp 2263 0000294C E8AD1B0000 <1> call wswap ; save current user (u) structure, user registers 2264 <1> ; and interrupt return components (for IRET) 2265 00002951 61 <1> popad 2266 00002952 6658 <1> pop ax ; gs 2267 00002954 6658 <1> pop ax ; fs 2268 00002956 6658 <1> pop ax ; es 2269 00002958 6658 <1> pop ax ; ds 2270 0000295A 58 <1> pop eax ; eip (init_exec) 2271 0000295B 6658 <1> pop ax ; cs (KCODE) 2272 0000295D 58 <1> pop eax ; E-FLAGS 2273 0000295E 58 <1> pop eax ; esp 2274 0000295F 6658 <1> pop ax ; ss (KDATA) 2275 <1> ; 2276 <1> ; 08/01/2022 ([u.ppgdir] is zero already) 2277 <1> ;xor eax, eax ; 0 2278 <1> ;mov [u.ppgdir], eax ; reset (to zero) for '/etc/init' 2279 <1> ; 2280 <1> ; 02/07/2015 2281 <1> ; [u.pgdir ] = [k_page_dir] 2282 <1> ; [u.ppgdir] = 0 (page dir of the parent process) 2283 <1> ; (The caller is os kernel sign for 'sysexec') 2284 <1> init_exec: 2285 <1> ; 13/03/2013 2286 <1> ; 24/07/2013 2287 00002961 BB[83290000] <1> mov ebx, init_file 2288 00002966 B9[7B290000] <1> mov ecx, init_argp 2289 <1> ; EBX contains 'etc/init' asciiz file name address 2290 <1> ; ECX contains address of argument list pointer 2291 <1> ; 2292 <1> ;dec byte [sysflg] ; FFh = ready for system call 2293 <1> ; 0 = executing a system call 2294 <1> sys _exec ; execute file 2215 <2> 2216 <2> 2217 0000296B B80B000000 <2> mov eax, %1 2218 <2> %if %0 >= 2 2219 <2> mov ebx, %2 2220 <2> %if %0 >= 3 2221 <2> mov ecx, %3 2222 <2> %if %0 = 4 2223 <2> mov edx, %4 2224 <2> %endif 2225 <2> %endif 2226 <2> %endif 2227 00002970 CD30 <2> int 30h 2295 00002972 7319 <1> jnc short panic 2296 <1> ; 2297 00002974 BE[405E0000] <1> mov esi, etc_init_err_msg 2298 <1> ; 08/01/2022 2299 <1> ;call print_msg 2300 00002979 EB17 <1> jmp short key_to_reboot 2301 <1> 2302 <1> ;align 4 2303 <1> init_argp: 2304 0000297B [83290000]00000000 <1> dd init_file, 0 ; 23/06/2015 (dw -> dd) 2305 <1> init_file: 2306 <1> ; 24/08/2015 2307 00002983 2F6574632F696E6974- <1> db '/etc/init', 0 2307 0000298C 00 <1> 2308 <1> panic: 2309 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2310 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 2311 0000298D BE[255E0000] <1> mov esi, panic_msg 2312 <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1) 2313 00002992 E819000000 <1> call print_msg 2314 <1> ;key_to_reboot: 2315 <1> ; 15/11/2015 2316 00002997 E8D82B0000 <1> call getch 2317 <1> ; wait for a character from the current tty 2318 <1> ; 2319 0000299C B00A <1> mov al, 0Ah 2320 0000299E 8A1D[56610000] <1> mov bl, [ptty] ; [active_page] 2321 000029A4 B407 <1> mov ah, 07h ; Black background, 2322 <1> ; light gray forecolor 2323 000029A6 E8F1E8FFFF <1> call write_tty 2324 000029AB E990E5FFFF <1> jmp cpu_reset 2325 <1> 2326 <1> print_msg: 2327 <1> ; 01/07/2015 2328 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2329 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 2330 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 2331 <1> ; 2332 <1> ; 2333 000029B0 AC <1> lodsb 2334 <1> pmsg1: 2335 000029B1 56 <1> push esi 2336 000029B2 0FB61D[56610000] <1> movzx ebx, byte [ptty] 2337 000029B9 B407 <1> mov ah, 07h ; Black background, light gray forecolor 2338 000029BB E8DCE8FFFF <1> call write_tty 2339 000029C0 5E <1> pop esi 2340 000029C1 AC <1> lodsb 2341 000029C2 20C0 <1> and al, al 2342 000029C4 75EB <1> jnz short pmsg1 2343 000029C6 C3 <1> retn 2344 <1> 2345 <1> ctrlbrk: 2346 <1> ; 04/02/2022 2347 <1> ; 01/02/2022 2348 <1> ; 12/11/2015 2349 <1> ; 13/03/2015 (Retro UNIX 386 v1) 2350 <1> ; 06/12/2013 (Retro UNIX 8086 v1) 2351 <1> ; 2352 <1> ; INT 1Bh (control+break) handler 2353 <1> ; 2354 <1> ; Retro Unix 8086 v1 feature only! 2355 <1> ; 2356 000029C7 66833D[30650000]00 <1> cmp word [u.intr], 0 2357 000029CF 764B <1> jna short cbrk4 2358 <1> cbrk0: 2359 <1> ; 12/11/2015 2360 <1> ; 06/12/2013 2361 000029D1 66833D[32650000]00 <1> cmp word [u.quit], 0 2362 000029D9 7441 <1> jz short cbrk4 2363 <1> ; 2364 <1> ; 20/09/2013 2365 <1> ;push ax 2366 <1> ; 01/02/2022 2367 000029DB 50 <1> push eax 2368 <1> 2369 <1> ; 04/02/2022 2370 <1> ; (repetitive ctrl+brk check) 2371 000029DC 66A1[32650000] <1> mov ax, [u.quit] 2372 000029E2 6640 <1> inc ax ; 0FFFFh -> 0 2373 000029E4 7435 <1> jz short cbrk3 2374 <1> 2375 <1> ; 20/09/2013 2376 000029E6 A0[56610000] <1> mov al, [ptty] 2377 <1> ; 2378 <1> ; 12/11/2015 2379 <1> ; 2380 <1> ; ctrl+break (EOT, CTRL+D) from serial port 2381 <1> ; or ctrl+break from console (pseudo) tty 2382 <1> ; (!redirection!) 2383 <1> ; 2384 000029EB 3C08 <1> cmp al, 8 ; serial port tty nums > 7 2385 000029ED 7211 <1> jb short cbrk1 ; console (pseudo) tty 2386 <1> ; 2387 <1> ; Serial port interrupt handler sets [ptty] 2388 <1> ; to the port's tty number (as temporary). 2389 <1> ; 2390 <1> ; If active process is using a stdin or 2391 <1> ; stdout redirection (by the shell), 2392 <1> ; console tty keyboard must be available 2393 <1> ; to terminate running process, 2394 <1> ; in order to prevent a deadlock. 2395 <1> ; 2396 000029EF 52 <1> push edx 2397 000029F0 0FB615[3B650000] <1> movzx edx, byte [u.uno] 2398 000029F7 3A82[43620000] <1> cmp al, [edx+p.ttyc-1] ; console tty (rw) 2399 000029FD 5A <1> pop edx 2400 000029FE 7412 <1> je short cbrk2 2401 <1> cbrk1: 2402 00002A00 FEC0 <1> inc al ; [u.ttyp] : 1 based tty number 2403 <1> ; 06/12/2013 2404 00002A02 3A05[1C650000] <1> cmp al, [u.ttyp] ; recent open tty (r) 2405 00002A08 7408 <1> je short cbrk2 2406 00002A0A 3A05[1D650000] <1> cmp al, [u.ttyp+1] ; recent open tty (w) 2407 00002A10 7509 <1> jne short cbrk3 2408 <1> cbrk2: 2409 <1> ;; 06/12/2013 2410 <1> ;mov ax, [u.quit] 2411 <1> ;and ax, ax 2412 <1> ;jz short cbrk3 2413 <1> ; 2414 <1> ;xor ax, ax ; 0 2415 <1> ;dec ax 2416 <1> ; 01/02/2022 2417 00002A12 31C0 <1> xor eax, eax ; 0 2418 00002A14 48 <1> dec eax ; 0FFFFFFFFh 2419 <1> ; 0FFFFh = 'ctrl+brk' keystroke 2420 00002A15 66A3[32650000] <1> mov [u.quit], ax 2421 <1> cbrk3: 2422 <1> ;pop ax 2423 <1> ; 01/02/2022 2424 00002A1B 58 <1> pop eax 2425 <1> cbrk4: 2426 00002A1C C3 <1> retn 2427 <1> 2428 <1> com2_int: 2429 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2430 <1> ; 07/11/2015 2431 <1> ; 24/10/2015 2432 <1> ; 23/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 2 interrupt handler > 2436 <1> ; 2437 00002A1D 890424 <1> mov [esp], eax ; overwrite call return address 2438 <1> ;;push eax 2439 <1> ; 08/01/2022 2440 00002A20 29C0 <1> sub eax, eax 2441 00002A22 B009 <1> mov al, 9 2442 <1> ;mov ax, 9 2443 00002A24 EB07 <1> jmp short comm_int 2444 <1> com1_int: 2445 <1> ; 07/11/2015 2446 <1> ; 24/10/2015 2447 00002A26 890424 <1> mov [esp], eax ; overwrite call return address 2448 <1> ; 23/10/2015 2449 <1> ;push eax 2450 <1> ; 08/01/2022 2451 00002A29 29C0 <1> sub eax, eax 2452 00002A2B B008 <1> mov al, 8 2453 <1> ;mov ax, 8 2454 <1> comm_int: 2455 <1> ; 08/01/2022 2456 <1> ; 20/11/2015 2457 <1> ; 18/11/2015 2458 <1> ; 17/11/2015 2459 <1> ; 16/11/2015 2460 <1> ; 09/11/2015 2461 <1> ; 08/11/2015 2462 <1> ; 07/11/2015 2463 <1> ; 06/11/2015 (serial4.asm, 'serial') 2464 <1> ; 01/11/2015 2465 <1> ; 26/10/2015 2466 <1> ; 23/10/2015 2467 00002A2D 53 <1> push ebx 2468 00002A2E 56 <1> push esi 2469 00002A2F 57 <1> push edi 2470 00002A30 1E <1> push ds 2471 00002A31 06 <1> push es 2472 <1> ; 18/11/2015 2473 00002A32 0F20DB <1> mov ebx, cr3 2474 00002A35 53 <1> push ebx ; **** 2475 <1> ; 2476 00002A36 51 <1> push ecx ; *** 2477 00002A37 52 <1> push edx ; ** 2478 <1> ; 2479 00002A38 BB10000000 <1> mov ebx, KDATA 2480 00002A3D 8EDB <1> mov ds, bx 2481 00002A3F 8EC3 <1> mov es, bx 2482 <1> ; 2483 00002A41 8B0D[28610000] <1> mov ecx, [k_page_dir] 2484 00002A47 0F22D9 <1> mov cr3, ecx 2485 <1> ; 20/11/2015 2486 <1> ; Interrupt identification register 2487 00002A4A 66BAFA02 <1> mov dx, 2FAh ; COM2 2488 <1> ; 2489 00002A4E 3C08 <1> cmp al, 8 2490 00002A50 7702 <1> ja short com_i0 2491 <1> ; 2492 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 2493 <1> ; 20/11/2015 2494 <1> ; 17/11/2015 2495 <1> ; 16/11/2015 2496 <1> ; 15/11/2015 2497 <1> ; 24/10/2015 2498 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 2499 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 2500 <1> ; < serial port 1 interrupt handler > 2501 <1> ; 2502 00002A52 FEC6 <1> inc dh ; 3FAh ; COM1 Interrupt id. register 2503 <1> com_i0: 2504 <1> ;push eax ; * 2505 <1> ; 07/11/2015 2506 00002A54 A2[96610000] <1> mov byte [ccomport], al 2507 <1> ; 09/11/2015 2508 <1> ;movzx ebx, ax ; 8 or 9 2509 <1> ; 08/01/2022 2510 00002A59 89C3 <1> mov ebx, eax ; 8 or 9 2511 <1> ; 17/11/2015 2512 <1> ; reset request for response status 2513 00002A5B 88A3[8C610000] <1> mov [ebx+req_resp-8], ah ; 0 2514 <1> ; 2515 <1> ; 20/11/2015 2516 00002A61 EC <1> in al, dx ; read interrupt id. register 2517 00002A62 EB00 <1> JMP $+2 ; I/O DELAY 2518 00002A64 2404 <1> and al, 4 ; received data available? 2519 00002A66 7470 <1> jz short com_eoi ; (transmit. holding reg. empty) 2520 <1> ; 2521 <1> ; 20/11/2015 2522 00002A68 80EA02 <1> sub dl, 3FAh-3F8h ; data register (3F8h, 2F8h) 2523 00002A6B EC <1> in al, dx ; read character 2524 <1> ;JMP $+2 ; I/O DELAY 2525 <1> ; 08/11/2015 2526 <1> ; 07/11/2015 2527 00002A6C 89DE <1> mov esi, ebx 2528 00002A6E 89DF <1> mov edi, ebx 2529 00002A70 81C6[90610000] <1> add esi, rchar - 8 ; points to last received char 2530 00002A76 81C7[92610000] <1> add edi, schar - 8 ; points to last sent char 2531 00002A7C 8806 <1> mov [esi], al ; received char (current char) 2532 <1> ; query 2533 00002A7E 20C0 <1> and al, al 2534 00002A80 7527 <1> jnz short com_i2 2535 <1> ; response 2536 <1> ; 17/11/2015 2537 <1> ; set request for response status 2538 00002A82 FE83[8C610000] <1> inc byte [ebx+req_resp-8] ; 1 2539 <1> ; 2540 00002A88 6683C205 <1> add dx, 3FDh-3F8h ; (3FDh, 2FDh) 2541 00002A8C EC <1> in al, dx ; read line status register 2542 00002A8D EB00 <1> JMP $+2 ; I/O DELAY 2543 00002A8F 2420 <1> and al, 20h ; transmitter holding reg. empty? 2544 00002A91 7445 <1> jz short com_eoi ; no 2545 00002A93 B0FF <1> mov al, 0FFh ; response 2546 00002A95 6683EA05 <1> sub dx, 3FDh-3F8h ; data port (3F8h, 2F8h) 2547 00002A99 EE <1> out dx, al ; send on serial port 2548 <1> ; 17/11/2015 2549 00002A9A 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 2550 00002A9D 7502 <1> jne short com_i1 ; no 2551 00002A9F 8807 <1> mov [edi], al ; 0FFh (responded) 2552 <1> com_i1: 2553 <1> ; 17/11/2015 2554 <1> ; reset request for response status (again) 2555 00002AA1 FE8B[8C610000] <1> dec byte [ebx+req_resp-8] ; 0 2556 00002AA7 EB2F <1> jmp short com_eoi 2557 <1> com_i2: 2558 <1> ; 08/11/2015 2559 00002AA9 3CFF <1> cmp al, 0FFh ; (response ?) 2560 00002AAB 7417 <1> je short com_i3 ; (check for response signal) 2561 <1> ; 07/11/2015 2562 00002AAD 3C04 <1> cmp al, 04h ; EOT 2563 00002AAF 751C <1> jne short com_i4 2564 <1> ; EOT = 04h (End of Transmit) - 'CTRL + D' 2565 <1> ;(an EOT char is supposed as a ctrl+brk from the terminal) 2566 <1> ; 08/11/2015 2567 <1> ; ptty -> tty 0 to 7 (pseudo screens) 2568 00002AB1 861D[56610000] <1> xchg bl, [ptty] ; tty number (8 or 9) 2569 00002AB7 E80BFFFFFF <1> call ctrlbrk 2570 00002ABC 861D[56610000] <1> xchg [ptty], bl ; (restore ptty value and BL value) 2571 <1> ;mov al, 04h ; EOT 2572 <1> ; 08/11/2015 2573 00002AC2 EB09 <1> jmp short com_i4 2574 <1> com_i3: 2575 <1> ; 08/11/2015 2576 <1> ; If 0FFh has been received just after a query 2577 <1> ; (schar, ZERO), it is a response signal. 2578 <1> ; 17/11/2015 2579 00002AC4 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 2580 00002AC7 7704 <1> ja short com_i4 ; no 2581 <1> ; reset query status (schar) 2582 00002AC9 8807 <1> mov [edi], al ; 0FFh 2583 00002ACB FEC0 <1> inc al ; 0 2584 <1> com_i4: 2585 <1> ; 27/07/2014 2586 <1> ; 09/07/2014 2587 00002ACD D0E3 <1> shl bl, 1 2588 00002ACF 81C3[58610000] <1> add ebx, ttychr 2589 <1> ; 23/07/2014 (always overwrite) 2590 <1> ;;cmp word [ebx], 0 2591 <1> ;;ja short com_eoi 2592 <1> ; 2593 00002AD5 668903 <1> mov [ebx], ax ; Save ascii code 2594 <1> ; scan code = 0 2595 <1> com_eoi: 2596 <1> ;mov al, 20h 2597 <1> ;out 20h, al ; end of interrupt 2598 <1> ; 2599 <1> ; 07/11/2015 2600 <1> ;pop eax ; * 2601 00002AD8 A0[96610000] <1> mov al, byte [ccomport] ; current COM port 2602 <1> ; al = tty number (8 or 9) 2603 00002ADD E8F61A0000 <1> call wakeup 2604 <1> com_iret: 2605 <1> ; 23/10/2015 2606 00002AE2 5A <1> pop edx ; ** 2607 00002AE3 59 <1> pop ecx ; *** 2608 <1> ; 18/11/2015 2609 <1> ;pop eax ; **** 2610 <1> ;mov cr3, eax 2611 <1> ;jmp iiret 2612 00002AE4 E99BDEFFFF <1> jmp iiretp 2613 <1> 2614 <1> ;iiretp: ; 01/09/2015 2615 <1> ; ; 28/08/2015 2616 <1> ; pop eax ; (*) page directory 2617 <1> ; mov cr3, eax 2618 <1> ;iiret: 2619 <1> ; ; 22/08/2014 2620 <1> ; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 2621 <1> ; out 20h, al ; 8259 PORT 2622 <1> ; ; 2623 <1> ; pop es 2624 <1> ; pop ds 2625 <1> ; pop edi 2626 <1> ; pop esi 2627 <1> ; pop ebx ; 29/08/2014 2628 <1> ; pop eax 2629 <1> ; iretd 2630 <1> 2631 <1> sp_init: 2632 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2633 <1> ; 07/11/2015 2634 <1> ; 29/10/2015 2635 <1> ; 26/10/2015 2636 <1> ; 23/10/2015 2637 <1> ; 29/06/2015 2638 <1> ; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud) 2639 <1> ; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud) 2640 <1> ; Initialization of Serial Port Communication Parameters 2641 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 2642 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 2643 <1> ; 2644 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 2645 <1> ; 2646 <1> ; INPUT: (29/06/2015) 2647 <1> ; AL = 0 for COM1 2648 <1> ; 1 for COM2 2649 <1> ; AH = Communication parameters 2650 <1> ; 2651 <1> ; (*) Communication parameters (except BAUD RATE): 2652 <1> ; Bit 4 3 2 1 0 2653 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 2654 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 2655 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 2656 <1> ; 11 = even 2657 <1> ; Baud rate setting bits: (29/06/2015) 2658 <1> ; Retro UNIX 386 v1 feature only ! 2659 <1> ; Bit 7 6 5 | Baud rate 2660 <1> ; ------------------------ 2661 <1> ; value 0 0 0 | Default (Divisor = 1) 2662 <1> ; 0 0 1 | 9600 (12) 2663 <1> ; 0 1 0 | 19200 (6) 2664 <1> ; 0 1 1 | 38400 (3) 2665 <1> ; 1 0 0 | 14400 (8) 2666 <1> ; 1 0 1 | 28800 (4) 2667 <1> ; 1 1 0 | 57600 (2) 2668 <1> ; 1 1 1 | 115200 (1) 2669 <1> 2670 <1> ; References: 2671 <1> ; (1) IBM PC-XT Model 286 BIOS Source Code 2672 <1> ; RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232) 2673 <1> ; (2) Award BIOS 1999 - ATORGS.ASM 2674 <1> ; (3) http://wiki.osdev.org/Serial_Ports 2675 <1> ; 2676 <1> ; Set communication parameters for COM1 (= 03h) 2677 <1> ; 2678 00002AE9 BB[92610000] <1> mov ebx, com1p ; COM1 parameters 2679 00002AEE 66BAF803 <1> mov dx, 3F8h ; COM1 2680 <1> ; 29/10/2015 2681 00002AF2 66B90103 <1> mov cx, 301h ; divisor = 1 (115200 baud) 2682 00002AF6 E84F000000 <1> call sp_i3 ; call A4 2683 00002AFB A880 <1> test al, 80h 2684 00002AFD 740E <1> jz short sp_i0 ; OK.. 2685 <1> ; Error ! 2686 <1> ;mov dx, 3F8h 2687 00002AFF 80EA05 <1> sub dl, 5 ; 3FDh -> 3F8h 2688 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 2689 <1> ; 08/01/2022 2690 00002B02 B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 2691 00002B04 E841000000 <1> call sp_i3 ; call A4 2692 00002B09 A880 <1> test al, 80h 2693 00002B0B 7508 <1> jnz short sp_i1 2694 <1> sp_i0: 2695 <1> ; (Note: Serial port interrupts will be disabled here...) 2696 <1> ; (INT 14h initialization code disables interrupts.) 2697 <1> ; 2698 00002B0D C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 2699 00002B10 E8BF000000 <1> call sp_i5 ; 29/06/2015 2700 <1> sp_i1: 2701 00002B15 43 <1> inc ebx 2702 00002B16 66BAF802 <1> mov dx, 2F8h ; COM2 2703 <1> ; 29/10/2015 2704 <1> ;mov cx, 301h ; divisor = 1 (115200 baud) 2705 <1> ; 08/01/2022 2706 00002B1A B101 <1> mov cl, 01h ; cx = 301h, divisor = 1 (115200 baud) 2707 00002B1C E829000000 <1> call sp_i3 ; call A4 2708 00002B21 A880 <1> test al, 80h 2709 00002B23 740E <1> jz short sp_i2 ; OK.. 2710 <1> ; Error ! 2711 <1> ;mov dx, 2F8h 2712 00002B25 80EA05 <1> sub dl, 5 ; 2FDh -> 2F8h 2713 <1> ;mov cx, 30Eh ; divisor = 12 (9600 baud) 2714 <1> ; 08/01/2022 2715 00002B28 B10E <1> mov cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud) 2716 00002B2A E81B000000 <1> call sp_i3 ; call A4 2717 00002B2F A880 <1> test al, 80h 2718 00002B31 7516 <1> jnz short sp_i7 2719 <1> sp_i2: 2720 00002B33 C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 2721 <1> sp_i6: 2722 <1> ;; COM2 - enabling IRQ 3 2723 <1> ; 08/01/2022 2724 00002B36 B4F7 <1> mov ah, 0F7h ; enable IRQ 3 (COM2) 2725 <1> ; 07/11/2015 2726 <1> ; 26/10/2015 2727 <1> ;pushf 2728 <1> ;cli 2729 <1> ;; 2730 <1> ;;mov dx, 2FCh ; modem control register 2731 <1> ;mov dl, 0FCh ; 08/01/2022 2732 <1> ;in al, dx ; read register 2733 <1> ;JMP $+2 ; I/O DELAY 2734 <1> ;or al, 8 ; enable bit 3 (OUT2) 2735 <1> ;out dx, al ; write back to register 2736 <1> ;JMP $+2 ; I/O DELAY 2737 <1> ;;mov dx, 2F9h ; interrupt enable register 2738 <1> ;mov dl, 0F9h ; 08/01/2022 2739 <1> ;in al, dx ; read register 2740 <1> ;JMP $+2 ; I/O DELAY 2741 <1> ;;or al, 1 ; receiver data interrupt enable and 2742 <1> ;or al, 3 ; transmitter empty interrupt enable 2743 <1> ;out dx, al ; write back to register 2744 <1> ;JMP $+2 ; I/O DELAY 2745 <1> ;in al, 21h ; read interrupt mask register 2746 <1> ;JMP $+2 ; I/O DELAY 2747 <1> ;and al, 0F7h ; enable IRQ 3 (COM2) 2748 <1> ;out 21h, al ; write back to register 2749 <1> ; 2750 <1> ; 08/01/2022 2751 00002B38 9C <1> pushf 2752 00002B39 E8AA000000 <1> call sp_i8 2753 <1> ; 23/10/2015 2754 00002B3E B8[1D2A0000] <1> mov eax, com2_int 2755 00002B43 A3[CE2F0000] <1> mov [com2_irq3], eax 2756 <1> ; 26/10/2015 2757 00002B48 9D <1> popf 2758 <1> sp_i7: 2759 00002B49 C3 <1> retn 2760 <1> 2761 <1> sp_i3: 2762 <1> ;A4: ;----- INITIALIZE THE COMMUNICATIONS PORT 2763 <1> ; 28/10/2015 2764 00002B4A FEC2 <1> inc dl ; 3F9h (2F9h) ; 3F9h, COM1 Interrupt enable register 2765 00002B4C B000 <1> mov al, 0 2766 00002B4E EE <1> out dx, al ; disable serial port interrupt 2767 00002B4F EB00 <1> JMP $+2 ; I/O DELAY 2768 00002B51 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; COM1 Line control register (3FBh) 2769 00002B54 B080 <1> mov al, 80h 2770 00002B56 EE <1> out dx, al ; SET DLAB=1 ; divisor latch access bit 2771 <1> ;----- SET BAUD RATE DIVISOR 2772 <1> ; 26/10/2015 2773 00002B57 80EA03 <1> sub dl, 3 ; 3F8h (2F8h) ; register for least significant byte 2774 <1> ; of the divisor value 2775 00002B5A 88C8 <1> mov al, cl ; 1 2776 00002B5C EE <1> out dx, al ; 1 = 115200 baud (Retro UNIX 386 v1) 2777 <1> ; 2 = 57600 baud 2778 <1> ; 3 = 38400 baud 2779 <1> ; 6 = 19200 baud 2780 <1> ; 12 = 9600 baud (Retro UNIX 8086 v1) 2781 00002B5D EB00 <1> JMP $+2 ; I/O DELAY 2782 00002B5F 28C0 <1> sub al, al 2783 00002B61 FEC2 <1> inc dl ; 3F9h (2F9h) ; register for most significant byte 2784 <1> ; of the divisor value 2785 00002B63 EE <1> out dx, al ; 0 2786 00002B64 EB00 <1> JMP $+2 ; I/O DELAY 2787 <1> ; 2788 00002B66 88E8 <1> mov al, ch ; 3 ; 8 data bits, 1 stop bit, no parity 2789 <1> ;and al, 1Fh ; Bits 0,1,2,3,4 2790 00002B68 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; Line control register 2791 00002B6B EE <1> out dx, al 2792 00002B6C EB00 <1> JMP $+2 ; I/O DELAY 2793 <1> ; 29/10/2015 2794 00002B6E FECA <1> dec dl ; 3FAh (2FAh) ; FIFO Control register (16550/16750) 2795 00002B70 30C0 <1> xor al, al ; 0 2796 00002B72 EE <1> out dx, al ; Disable FIFOs (reset to 8250 mode) 2797 00002B73 EB00 <1> JMP $+2 2798 <1> sp_i4: 2799 <1> ;A18: ;----- COMM PORT STATUS ROUTINE 2800 <1> ; 29/06/2015 (line status after modem status) 2801 00002B75 80C204 <1> add dl, 4 ; 3FEh (2FEh) ; Modem status register 2802 <1> sp_i4s: 2803 00002B78 EC <1> in al, dx ; GET MODEM CONTROL STATUS 2804 00002B79 EB00 <1> JMP $+2 ; I/O DELAY 2805 00002B7B 88C4 <1> mov ah, al ; PUT IN (AH) FOR RETURN 2806 00002B7D FECA <1> dec dl ; 3FDh (2FDh) ; POINT TO LINE STATUS REGISTER 2807 <1> ; dx = 3FDh for COM1, 2FDh for COM2 2808 00002B7F EC <1> in al, dx ; GET LINE CONTROL STATUS 2809 <1> ; AL = Line status, AH = Modem status 2810 00002B80 C3 <1> retn 2811 <1> 2812 <1> sp_status: 2813 <1> ; 29/06/2015 2814 <1> ; 27/06/2015 (Retro UNIX 386 v1) 2815 <1> ; Get serial port status 2816 00002B81 66BAFE03 <1> mov dx, 3FEh ; Modem status register (COM1) 2817 00002B85 28C6 <1> sub dh, al ; dh = 2 for COM2 (al = 1) 2818 <1> ; dx = 2FEh for COM2 2819 00002B87 EBEF <1> jmp short sp_i4s 2820 <1> 2821 <1> sp_setp: ; Set serial port communication parameters 2822 <1> ; 08/01/2022 2823 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2824 <1> ; 07/11/2015 2825 <1> ; 29/10/2015 2826 <1> ; 29/06/2015 2827 <1> ; Retro UNIX 386 v1 feature only ! 2828 <1> ; 2829 <1> ; INPUT: 2830 <1> ; AL = 0 for COM1 2831 <1> ; 1 for COM2 2832 <1> ; AH = Communication parameters (*) 2833 <1> ; OUTPUT: 2834 <1> ; CL = Line status 2835 <1> ; CH = Modem status 2836 <1> ; If cf = 1 -> Error code in [u.error] 2837 <1> ; 'invalid parameter !' 2838 <1> ; or 2839 <1> ; 'device not ready !' error 2840 <1> ; 2841 <1> ; (*) Communication parameters (except BAUD RATE): 2842 <1> ; Bit 4 3 2 1 0 2843 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 2844 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 2845 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 2846 <1> ; 11 = even 2847 <1> ; Baud rate setting bits: (29/06/2015) 2848 <1> ; Retro UNIX 386 v1 feature only ! 2849 <1> ; Bit 7 6 5 | Baud rate 2850 <1> ; ------------------------ 2851 <1> ; value 0 0 0 | Default (Divisor = 1) 2852 <1> ; 0 0 1 | 9600 (12) 2853 <1> ; 0 1 0 | 19200 (6) 2854 <1> ; 0 1 1 | 38400 (3) 2855 <1> ; 1 0 0 | 14400 (8) 2856 <1> ; 1 0 1 | 28800 (4) 2857 <1> ; 1 1 0 | 57600 (2) 2858 <1> ; 1 1 1 | 115200 (1) 2859 <1> ; 2860 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 2861 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 2862 <1> ; 2863 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 2864 <1> ; 2865 00002B89 66BAF803 <1> mov dx, 3F8h 2866 00002B8D BB[92610000] <1> mov ebx, com1p ; COM1 control byte offset 2867 00002B92 3C01 <1> cmp al, 1 2868 00002B94 7770 <1> ja short sp_invp_err 2869 00002B96 7203 <1> jb short sp_setp1 ; COM1 (AL = 0) 2870 00002B98 FECE <1> dec dh ; 2F8h 2871 00002B9A 43 <1> inc ebx ; COM2 control byte offset 2872 <1> sp_setp1: 2873 <1> ; 29/10/2015 2874 00002B9B 8823 <1> mov [ebx], ah 2875 00002B9D 0FB6CC <1> movzx ecx, ah 2876 00002BA0 C0E905 <1> shr cl, 5 ; -> baud rate index 2877 00002BA3 80E41F <1> and ah, 1Fh ; communication parameters except baud rate 2878 00002BA6 8A81[152C0000] <1> mov al, [ecx+b_div_tbl] 2879 00002BAC 6689C1 <1> mov cx, ax 2880 00002BAF E896FFFFFF <1> call sp_i3 2881 00002BB4 6689C1 <1> mov cx, ax ; CL = Line status, CH = Modem status 2882 00002BB7 A880 <1> test al, 80h 2883 00002BB9 740F <1> jz short sp_setp2 2884 00002BBB C603E3 <1> mov byte [ebx], 0E3h ; Reset to initial value (11100011b) 2885 <1> stp_dnr_err: 2886 00002BBE C705[41650000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !' 2886 00002BC6 0000 <1> 2887 <1> ; CL = Line status, CH = Modem status 2888 00002BC8 F9 <1> stc 2889 00002BC9 C3 <1> retn 2890 <1> sp_setp2: 2891 00002BCA 80FE02 <1> cmp dh, 2 ; COM2 (2F?h) 2892 <1> ;jna sp_i6 2893 <1> ; COM1 (3F?h) 2894 <1> ; 24/12/2021 2895 00002BCD 7705 <1> ja short sp_i5 2896 00002BCF E962FFFFFF <1> jmp sp_i6 2897 <1> sp_i5: 2898 <1> ; 08/01/2022 2899 00002BD4 B4EF <1> mov ah, 0EFh ; enable IRQ 4 (COM1) 2900 <1> ; 07/11/2015 2901 <1> ; 26/10/2015 2902 <1> ; 29/06/2015 2903 <1> ; 2904 <1> ;; COM1 - enabling IRQ 4 2905 <1> ;pushf 2906 <1> ;cli 2907 <1> ;;mov dx, 3FCh ; modem control register 2908 <1> ;mov dl, 0FCh ; 08/01/2022 2909 <1> ;in al, dx ; read register 2910 <1> ;JMP $+2 ; I/O DELAY 2911 <1> ;or al, 8 ; enable bit 3 (OUT2) 2912 <1> ;out dx, al ; write back to register 2913 <1> ;JMP $+2 ; I/O DELAY 2914 <1> ;;mov dx, 3F9h ; interrupt enable register 2915 <1> ;mov dl, 0F9h ; 08/01/2022 2916 <1> ;in al, dx ; read register 2917 <1> ;JMP $+2 ; I/O DELAY 2918 <1> ;;or al, 1 ; receiver data interrupt enable and 2919 <1> ;or al, 3 ; transmitter empty interrupt enable 2920 <1> ;out dx, al ; write back to register 2921 <1> ;JMP $+2 ; I/O DELAY 2922 <1> ;in al, 21h ; read interrupt mask register 2923 <1> ;JMP $+2 ; I/O DELAY 2924 <1> ;and al, 0EFh ; enable IRQ 4 (COM1) 2925 <1> ;out 21h, al ; write back to register 2926 <1> ; 2927 <1> ; 08/01/2022 2928 00002BD6 9C <1> pushf 2929 00002BD7 E80C000000 <1> call sp_i8 2930 <1> ; 23/10/2015 2931 00002BDC B8[262A0000] <1> mov eax, com1_int 2932 00002BE1 A3[CA2F0000] <1> mov [com1_irq4], eax 2933 <1> ; 26/10/2015 2934 00002BE6 9D <1> popf 2935 00002BE7 C3 <1> retn 2936 <1> 2937 <1> sp_i8: 2938 <1> ; 08/01/2022 2939 <1> ;pushf 2940 00002BE8 FA <1> cli 2941 <1> ; 2942 <1> ;mov dx, 2FCh ; 3FCh ; modem control register 2943 00002BE9 B2FC <1> mov dl, 0FCh 2944 00002BEB EC <1> in al, dx ; read register 2945 00002BEC EB00 <1> JMP $+2 ; I/O DELAY 2946 00002BEE 0C08 <1> or al, 8 ; enable bit 3 (OUT2) 2947 00002BF0 EE <1> out dx, al ; write back to register 2948 00002BF1 EB00 <1> JMP $+2 ; I/O DELAY 2949 <1> ;mov dx, 2F9h ; 3F9h ; interrupt enable register 2950 00002BF3 B2F9 <1> mov dl, 0F9h 2951 00002BF5 EC <1> in al, dx ; read register 2952 00002BF6 EB00 <1> JMP $+2 ; I/O DELAY 2953 <1> ;or al, 1 ; receiver data interrupt enable and 2954 00002BF8 0C03 <1> or al, 3 ; transmitter empty interrupt enable 2955 00002BFA EE <1> out dx, al ; write back to register 2956 00002BFB EB00 <1> JMP $+2 ; I/O DELAY 2957 00002BFD E421 <1> in al, 21h ; read interrupt mask register 2958 00002BFF EB00 <1> JMP $+2 ; I/O DELAY 2959 <1> ;and al, 0F7h ; 0EFh ; enable IRQ 3 (COM2) 2960 00002C01 20E0 <1> and al, ah ; 0F7h or 0EFh 2961 00002C03 E621 <1> out 21h, al ; write back to register 2962 <1> ; 2963 <1> ;popf 2964 00002C05 C3 <1> retn 2965 <1> 2966 <1> sp_invp_err: 2967 00002C06 C705[41650000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 2967 00002C0E 0000 <1> 2968 00002C10 31C9 <1> xor ecx, ecx 2969 00002C12 49 <1> dec ecx ; 0FFFFh 2970 00002C13 F9 <1> stc 2971 00002C14 C3 <1> retn 2972 <1> 2973 <1> ; 29/10/2015 2974 <1> b_div_tbl: ; Baud rate divisor table (115200/divisor) 2975 00002C15 010C0603080401 <1> db 1, 12, 6, 3, 8, 4, 1 2976 <1> 2977 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 2978 <1> epoch: 2979 <1> ; 17/07/2022 2980 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2981 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 2982 <1> ; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM) 2983 <1> ; 'epoch' procedure prototype: 2984 <1> ; UNIXCOPY.ASM, 10/03/2013 2985 <1> ; 14/11/2012 2986 <1> ; unixboot.asm (boot file configuration) 2987 <1> ; version of "epoch" procedure in "unixproc.asm" 2988 <1> ; 21/7/2012 2989 <1> ; 15/7/2012 2990 <1> ; 14/7/2012 2991 <1> ; Erdogan Tan - RETRO UNIX v0.1 2992 <1> ; compute current date and time as UNIX Epoch/Time 2993 <1> ; UNIX Epoch: seconds since 1/1/1970 00:00:00 2994 <1> ; 2995 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 2996 <1> ; 2997 00002C1C E818010000 <1> call get_rtc_time ; Return Current Time 2998 00002C21 86E9 <1> xchg ch,cl 2999 00002C23 66890D[985E0000] <1> mov [hour], cx 3000 00002C2A 86F2 <1> xchg dh,dl 3001 00002C2C 668915[9A5E0000] <1> mov [second], dx 3002 <1> ; 3003 00002C33 E832010000 <1> call get_rtc_date ; Return Current Date 3004 00002C38 86E9 <1> xchg ch,cl 3005 00002C3A 66890D[945E0000] <1> mov [year], cx 3006 00002C41 86F2 <1> xchg dh,dl 3007 00002C43 668915[965E0000] <1> mov [month], dx 3008 <1> ; 3009 00002C4A 66B93030 <1> mov cx, 3030h 3010 <1> ; 3011 00002C4E A0[985E0000] <1> mov al, [hour] ; Hour 3012 <1> ; AL <= BCD number) 3013 00002C53 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3014 <1> ; AH = AL / 10h 3015 <1> ; AL = AL MOD 10h 3016 00002C55 D50A <1> aad ; AX= AH*10+AL 3017 00002C57 A2[985E0000] <1> mov [hour], al 3018 00002C5C A0[995E0000] <1> mov al, [hour+1] ; Minute 3019 <1> ; AL <= BCD number) 3020 00002C61 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3021 <1> ; AH = AL / 10h 3022 <1> ; AL = AL MOD 10h 3023 00002C63 D50A <1> aad ; AX= AH*10+AL 3024 00002C65 A2[995E0000] <1> mov [minute], al 3025 00002C6A A0[9A5E0000] <1> mov al, [second] ; Second 3026 <1> ; AL <= BCD number) 3027 00002C6F D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3028 <1> ; AH = AL / 10h 3029 <1> ; AL = AL MOD 10h 3030 00002C71 D50A <1> aad ; AX= AH*10+AL 3031 00002C73 A2[9A5E0000] <1> mov [second], al 3032 00002C78 66A1[945E0000] <1> mov ax, [year] ; Year (century) 3033 <1> ;push ax 3034 <1> ; 08/01/2022 3035 00002C7E 50 <1> push eax 3036 <1> ; AL <= BCD number) 3037 00002C7F D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3038 <1> ; AH = AL / 10h 3039 <1> ; AL = AL MOD 10h 3040 00002C81 D50A <1> aad ; AX= AH*10+AL 3041 00002C83 B464 <1> mov ah, 100 3042 00002C85 F6E4 <1> mul ah 3043 00002C87 66A3[945E0000] <1> mov [year], ax 3044 <1> ;pop ax 3045 <1> ; 08/01/2022 3046 00002C8D 58 <1> pop eax 3047 00002C8E 88E0 <1> mov al, ah 3048 <1> ; AL <= BCD number) 3049 00002C90 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3050 <1> ; AH = AL / 10h 3051 <1> ; AL = AL MOD 10h 3052 00002C92 D50A <1> aad ; AX= AH*10+AL 3053 00002C94 660105[945E0000] <1> add [year], ax 3054 00002C9B A0[965E0000] <1> mov al, [month] ; Month 3055 <1> ; AL <= BCD number) 3056 00002CA0 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3057 <1> ; AH = AL / 10h 3058 <1> ; AL = AL MOD 10h 3059 00002CA2 D50A <1> aad ; AX= AH*10+AL 3060 00002CA4 A2[965E0000] <1> mov [month], al 3061 00002CA9 A0[975E0000] <1> mov al, [month+1] ; Day 3062 <1> ; AL <= BCD number) 3063 00002CAE D410 <1> db 0D4h,10h ; Undocumented inst. AAM 3064 <1> ; AH = AL / 10h 3065 <1> ; AL = AL MOD 10h 3066 00002CB0 D50A <1> aad ; AX= AH*10+AL 3067 00002CB2 A2[975E0000] <1> mov [day], al 3068 <1> 3069 <1> convert_to_epoch: 3070 <1> ; 17/07/2022 3071 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification) 3072 <1> ; 09/04/2013 (Retro UNIX 8086 v1) 3073 <1> ; 3074 <1> ; ((Modified registers: EAX, EDX, EBX)) 3075 <1> ; 3076 <1> ; Derived from DALLAS Semiconductor 3077 <1> ; Application Note 31 (DS1602/DS1603) 3078 <1> ; 6 May 1998 3079 00002CB7 29C0 <1> sub eax, eax 3080 00002CB9 66A1[945E0000] <1> mov ax, [year] 3081 00002CBF 662DB207 <1> sub ax, 1970 3082 00002CC3 BA6D010000 <1> mov edx, 365 3083 00002CC8 F7E2 <1> mul edx 3084 00002CCA 31DB <1> xor ebx, ebx 3085 00002CCC 8A1D[965E0000] <1> mov bl, [month] 3086 00002CD2 FECB <1> dec bl 3087 00002CD4 D0E3 <1> shl bl, 1 3088 <1> ;sub edx, edx 3089 00002CD6 668B93[9C5E0000] <1> mov dx, [EBX+DMonth] 3090 00002CDD 8A1D[975E0000] <1> mov bl, [day] 3091 00002CE3 FECB <1> dec bl 3092 00002CE5 01D0 <1> add eax, edx 3093 00002CE7 01D8 <1> add eax, ebx 3094 <1> ; EAX = days since 1/1/1970 3095 00002CE9 668B15[945E0000] <1> mov dx, [year] 3096 00002CF0 6681EAB107 <1> sub dx, 1969 3097 <1> ;shr dx, 1 3098 <1> ;shr dx, 1 3099 <1> ; 17/07/2022 3100 00002CF5 C1EA02 <1> shr edx, 2 3101 <1> ; (year-1969)/4 3102 00002CF8 01D0 <1> add eax, edx 3103 <1> ; + leap days since 1/1/1970 3104 00002CFA 803D[965E0000]02 <1> cmp byte [month], 2 ; if past february 3105 00002D01 7610 <1> jna short cte1 3106 00002D03 668B15[945E0000] <1> mov dx, [year] 3107 00002D0A 6683E203 <1> and dx, 3 ; year mod 4 3108 00002D0E 7503 <1> jnz short cte1 3109 <1> ; and if leap year 3110 00002D10 83C001 <1> add eax, 1 ; add this year's leap day (february 29) 3111 <1> cte1: ; compute seconds since 1/1/1970 3112 00002D13 BA18000000 <1> mov edx, 24 3113 00002D18 F7E2 <1> mul edx 3114 00002D1A 8A15[985E0000] <1> mov dl, [hour] 3115 00002D20 01D0 <1> add eax, edx 3116 <1> ; EAX = hours since 1/1/1970 00:00:00 3117 <1> ;mov ebx, 60 3118 00002D22 B33C <1> mov bl, 60 3119 00002D24 F7E3 <1> mul ebx 3120 00002D26 8A15[995E0000] <1> mov dl, [minute] 3121 00002D2C 01D0 <1> add eax, edx 3122 <1> ; EAX = minutes since 1/1/1970 00:00:00 3123 <1> ;mov ebx, 60 3124 00002D2E F7E3 <1> mul ebx 3125 00002D30 8A15[9A5E0000] <1> mov dl, [second] 3126 00002D36 01D0 <1> add eax, edx 3127 <1> ; EAX -> seconds since 1/1/1970 00:00:00 3128 00002D38 C3 <1> retn 3129 <1> 3130 <1> get_rtc_time: 3131 <1> ; 15/03/2015 3132 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3133 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3134 <1> ; INT 1Ah 3135 <1> ; (AH) = 02H READ THE REAL TIME CLOCK AND RETURN WITH, : 3136 <1> ; (CH) = HOURS IN BCD (00-23) : 3137 <1> ; (CL) = MINUTES IN BCD (00-59) : 3138 <1> ; (DH) = SECONDS IN BCD (00-59) : 3139 <1> ; (DL) = DAYLIGHT SAVINGS ENABLE (00-01). : 3140 <1> ; 3141 <1> RTC_20: ; GET RTC TIME 3142 00002D39 FA <1> cli 3143 00002D3A E8E1DDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3144 00002D3F 7227 <1> JC short RTC_29 ; EXIT IF ERROR (CY= 1) 3145 <1> 3146 00002D41 B000 <1> MOV AL, CMOS_SECONDS ; SET ADDRESS OF SECONDS 3147 00002D43 E8C2DDFFFF <1> CALL CMOS_READ ; GET SECONDS 3148 00002D48 88C6 <1> MOV DH, AL ; SAVE 3149 00002D4A B00B <1> MOV AL, CMOS_REG_B ; ADDRESS ALARM REGISTER 3150 00002D4C E8B9DDFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 3151 00002D51 2401 <1> AND AL, 00000001B ; MASK FOR VALID DSE BIT 3152 00002D53 88C2 <1> MOV DL, AL ; SET [DL] TO ZERO FOR NO DSE BIT 3153 00002D55 B002 <1> MOV AL, CMOS_MINUTES ; SET ADDRESS OF MINUTES 3154 00002D57 E8AEDDFFFF <1> CALL CMOS_READ ; GET MINUTES 3155 00002D5C 88C1 <1> MOV CL, AL ; SAVE 3156 00002D5E B004 <1> MOV AL, CMOS_HOURS ; SET ADDRESS OF HOURS 3157 00002D60 E8A5DDFFFF <1> CALL CMOS_READ ; GET HOURS 3158 00002D65 88C5 <1> MOV CH, AL ; SAVE 3159 00002D67 F8 <1> CLC ; SET CY= 0 3160 <1> RTC_29: 3161 00002D68 FB <1> sti 3162 00002D69 C3 <1> RETn ; RETURN WITH RESULT IN CARRY FLAG 3163 <1> 3164 <1> get_rtc_date: 3165 <1> ; 15/03/2015 3166 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3167 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3168 <1> ; INT 1Ah 3169 <1> ; (AH) = 04H READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,: 3170 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 3171 <1> ; (CL) = YEAR IN BCD (00-99) : 3172 <1> ; (DH) = MONTH IN BCD (01-12) : 3173 <1> ; (DL) = DAY IN BCD (01-31). 3174 <1> ; 3175 <1> RTC_40: ; GET RTC DATE 3176 00002D6A FA <1> cli 3177 00002D6B E8B0DDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3178 00002D70 7225 <1> JC short RTC_49 ; EXIT IF ERROR (CY= 1) 3179 <1> 3180 00002D72 B007 <1> MOV AL, CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH 3181 00002D74 E891DDFFFF <1> CALL CMOS_READ ; READ DAY OF MONTH 3182 00002D79 88C2 <1> MOV DL, AL ; SAVE 3183 00002D7B B008 <1> MOV AL, CMOS_MONTH ; ADDRESS MONTH 3184 00002D7D E888DDFFFF <1> CALL CMOS_READ ; READ MONTH 3185 00002D82 88C6 <1> MOV DH, AL ; SAVE 3186 00002D84 B009 <1> MOV AL, CMOS_YEAR ; ADDRESS YEAR 3187 00002D86 E87FDDFFFF <1> CALL CMOS_READ ; READ YEAR 3188 00002D8B 88C1 <1> MOV CL, AL ; SAVE 3189 00002D8D B032 <1> MOV AL, CMOS_CENTURY ; ADDRESS CENTURY LOCATION 3190 00002D8F E876DDFFFF <1> CALL CMOS_READ ; GET CENTURY BYTE 3191 00002D94 88C5 <1> MOV CH, AL ; SAVE 3192 00002D96 F8 <1> CLC ; SET CY=0 3193 <1> RTC_49: 3194 00002D97 FB <1> sti 3195 00002D98 C3 <1> RETn ; RETURN WITH RESULTS IN CARRY FLAG 3196 <1> 3197 <1> set_date_time: 3198 <1> convert_from_epoch: 3199 <1> ; 02/06/2022 3200 <1> ; 01/06/2022 (BugFix) 3201 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 3202 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 3203 <1> ; 'convert_from_epoch' procedure prototype: 3204 <1> ; UNIXCOPY.ASM, 10/03/2013 3205 <1> ; 3206 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 3207 <1> ; 3208 <1> ; Derived from DALLAS Semiconductor 3209 <1> ; Application Note 31 (DS1602/DS1603) 3210 <1> ; 6 May 1998 3211 <1> ; 3212 <1> ; INPUT: 3213 <1> ; EAX = Unix (Epoch) Time 3214 <1> ; 3215 00002D99 31D2 <1> xor edx, edx 3216 <1> ; 02/06/2022 3217 00002D9B 31C9 <1> xor ecx, ecx 3218 00002D9D 31DB <1> xor ebx, ebx 3219 <1> ;mov ecx, 60 3220 00002D9F B13C <1> mov cl, 60 3221 00002DA1 F7F1 <1> div ecx 3222 <1> ;mov [imin], eax ; whole minutes 3223 <1> ; since 1/1/1970 3224 <1> ;mov [second], dx ; leftover seconds 3225 00002DA3 8815[9A5E0000] <1> mov [second], dl ; 02/06/2022 3226 00002DA9 29D2 <1> sub edx, edx 3227 00002DAB F7F1 <1> div ecx 3228 <1> ;mov [ihrs], eax ; whole hours 3229 <1> ; ; since 1/1/1970 3230 <1> ;mov [minute], dx ; leftover minutes 3231 00002DAD 8815[995E0000] <1> mov [minute], dl ; 02/06/2022 3232 00002DB3 31D2 <1> xor edx, edx 3233 <1> ;mov cx, 24 3234 00002DB5 B118 <1> mov cl, 24 3235 00002DB7 F7F1 <1> div ecx 3236 <1> ;mov [iday], ax ; whole days 3237 <1> ; since 1/1/1970 3238 <1> ;mov [hour], dx ; leftover hours 3239 00002DB9 8815[985E0000] <1> mov [hour], dl ; 02/06/2022 3240 <1> 3241 00002DBF 05DB020000 <1> add eax, 365+366 ; whole day since 3242 <1> ; 1/1/1968 3243 <1> ;mov [iday], ax 3244 00002DC4 50 <1> push eax 3245 00002DC5 29D2 <1> sub edx, edx 3246 00002DC7 B9B5050000 <1> mov ecx, (4*365)+1 ; 4 years = 1461 days 3247 00002DCC F7F1 <1> div ecx 3248 00002DCE 59 <1> pop ecx 3249 <1> ;mov [lday], ax ; count of quadyrs (4 years) 3250 <1> ;push dx 3251 <1> ; 01/06/2022 3252 00002DCF 52 <1> push edx 3253 <1> ;mov [qday], dx ; days since quadyr began 3254 00002DD0 6683FA3C <1> cmp dx, 31+29 ; if past feb 29 then 3255 00002DD4 F5 <1> cmc ; add this quadyr's leap day 3256 00002DD5 83D000 <1> adc eax, 0 ; to # of qadyrs (leap days) 3257 <1> ;mov [lday], ax ; since 1968 3258 <1> ;mov cx, [iday] 3259 00002DD8 91 <1> xchg ecx, eax ; ECX = lday, EAX = iday 3260 00002DD9 29C8 <1> sub eax, ecx ; iday - lday 3261 00002DDB B96D010000 <1> mov ecx, 365 3262 00002DE0 31D2 <1> xor edx, edx 3263 <1> ; EAX = iday-lday, EDX = 0 3264 00002DE2 F7F1 <1> div ecx 3265 <1> ;mov [iyrs], ax ; whole years since 1968 3266 <1> ;jday = iday - (iyrs*365) - lday 3267 <1> ;mov [jday], dx ; days since 1/1 of current year 3268 <1> ;add eax, 1968 3269 00002DE4 6605B007 <1> add ax, 1968 ; compute year 3270 00002DE8 66A3[945E0000] <1> mov [year], ax 3271 <1> ;mov cx, dx 3272 <1> ; 02/06/2022 3273 00002DEE 89D1 <1> mov ecx, edx 3274 <1> ;mov dx, [qday] 3275 <1> ;pop dx 3276 <1> ; 01/06/2022 3277 00002DF0 5A <1> pop edx 3278 00002DF1 6681FA6D01 <1> cmp dx, 365 ; if qday <= 365 and qday >= 60 3279 00002DF6 7709 <1> ja short cfe1 ; jday = jday +1 3280 00002DF8 6683FA3C <1> cmp dx, 60 ; if past 2/29 and leap year then 3281 00002DFC F5 <1> cmc ; add a leap day to the # of whole 3282 00002DFD 6683D100 <1> adc cx, 0 ; days since 1/1 of current year 3283 <1> cfe1: 3284 <1> ;mov [jday], cx 3285 <1> ;mov bx, 12 ; estimate month 3286 <1> ;sub ebx, ebx 3287 <1> ; 02/06/2022 3288 00002E01 B30C <1> mov bl, 12 3289 00002E03 66BA6E01 <1> mov dx, 366 ; mday, max. days since 1/1 is 365 3290 00002E07 6683E003 <1> and ax, 11b ; year mod 4 (and dx, 3) 3291 <1> cfe2: ; Month calculation ; 0 to 11 (11 to 0) 3292 <1> ;cmp cx, dx ; mday = # of days passed from 1/1 3293 <1> ; 02/06/2022 3294 00002E0B 39D1 <1> cmp ecx, edx 3295 00002E0D 7319 <1> jnb short cfe3 3296 <1> ;dec bx ; month = month - 1 3297 00002E0F FECB <1> dec bl 3298 <1> ;shl bx, 1 3299 00002E11 D0E3 <1> shl bl, 1 3300 00002E13 668B93[9C5E0000] <1> mov dx, [ebx+DMonth] ; # elapsed days at 1st of month 3301 <1> ;shr bx, 1 ; bx = month - 1 (0 to 11) 3302 <1> ; 02/06/2022 3303 00002E1A D0EB <1> shr bl, 1 3304 00002E1C 80FB01 <1> cmp bl, 1 3305 <1> ;cmp bx, 1 ; if month > 2 and year mod 4 = 0 3306 00002E1F 76EA <1> jna short cfe2 ; then mday = mday + 1 3307 00002E21 08C0 <1> or al, al ; if past 2/29 and leap year then 3308 00002E23 75E6 <1> jnz short cfe2 ; add leap day (to mday) 3309 <1> ;inc dx ; mday = mday + 1 3310 00002E25 42 <1> inc edx 3311 00002E26 EBE3 <1> jmp short cfe2 3312 <1> cfe3: 3313 <1> ;inc bx ; -> bx = month, 1 to 12 3314 <1> ; 02/06/2022 3315 00002E28 FEC3 <1> inc bl 3316 <1> ;mov [month], bx 3317 00002E2A 881D[965E0000] <1> mov [month], bl 3318 <1> ;sub cx, dx ; day = jday - mday + 1 3319 00002E30 29D1 <1> sub ecx, edx 3320 <1> ;inc cx 3321 00002E32 FEC1 <1> inc cl 3322 <1> ;mov [day], cx 3323 00002E34 880D[975E0000] <1> mov [day], cl ; 02/06/2022 3324 <1> 3325 <1> ; eax, ebx, ecx, edx is changed at return 3326 <1> ; output -> 3327 <1> ; [year], [month], [day], [hour], [minute], [second] 3328 <1> 3329 <1> ; 01/06/2022 (BugFix) 3330 <1> _set_date: 3331 00002E3A 66A1[945E0000] <1> mov ax, [year] 3332 00002E40 B520 <1> mov ch, 20h ; century (bcd) 3333 00002E42 662DD007 <1> sub ax, 2000 3334 00002E46 7306 <1> jnc short set_date 3335 00002E48 B519 <1> mov ch, 19h ; century (bcd) 3336 00002E4A 6683C064 <1> add ax, 100 3337 <1> ; 01/06/2022 3338 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 3339 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 3340 <1> set_date: 3341 <1> ;mov al, [year+1] 3342 <1> ;aam ; ah = al / 10, al = al mod 10 3343 <1> ;db 0D5h, 10h ; Undocumented inst. AAD 3344 <1> ; ; AL = AH * 10h + AL 3345 <1> ;mov ch, al ; century (BCD) 3346 <1> ;mov al, [year] 3347 <1> ; al = year (0-99) ; 01/06/2022 3348 00002E4E D40A <1> aam ; ah = al / 10, al = al mod 10 3349 00002E50 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3350 <1> ; AL = AH * 10h + AL 3351 00002E52 88C1 <1> mov cl, al ; year (BCD) 3352 00002E54 A0[965E0000] <1> mov al, [month] 3353 00002E59 D40A <1> aam ; ah = al / 10, al = al mod 10 3354 00002E5B D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3355 <1> ; AL = AH * 10h + AL 3356 00002E5D 88C6 <1> mov dh, al ; month (BCD) 3357 00002E5F A0[975E0000] <1> mov al, [day] 3358 00002E64 D40A <1> aam ; ah = al / 10, al = al mod 10 3359 00002E66 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3360 <1> ; AL = AH * 10h + AL 3361 <1> ; 01/06/2022 (BugFix) 3362 00002E68 88C2 <1> mov dl, al ; day (BCD) 3363 <1> 3364 <1> ; Set real-time clock date 3365 00002E6A E879000000 <1> call set_rtc_date 3366 <1> set_time: 3367 <1> ; Read real-time clock time 3368 <1> ; (get day light saving time bit status) 3369 00002E6F FA <1> cli 3370 00002E70 E8ABDCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3371 <1> ; cf = 1 -> al = 0 3372 00002E75 7207 <1> jc short stime1 3373 00002E77 B00B <1> MOV AL, CMOS_REG_B ; ADDRESS ALARM REGISTER 3374 00002E79 E88CDCFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 3375 <1> stime1: 3376 00002E7E FB <1> sti 3377 00002E7F 2401 <1> AND AL, 00000001B ; MASK FOR VALID DSE BIT 3378 00002E81 88C2 <1> MOV DL, AL ; SET [DL] TO ZERO FOR NO DSE BIT 3379 <1> ; DL = 1 or 0 (day light saving time) 3380 <1> ; 3381 00002E83 A0[985E0000] <1> mov al, [hour] 3382 00002E88 D40A <1> aam ; ah = al / 10, al = al mod 10 3383 00002E8A D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3384 <1> ; AL = AH * 10h + AL 3385 00002E8C 88C5 <1> mov ch, al ; hour (BCD) 3386 00002E8E A0[995E0000] <1> mov al, [minute] 3387 00002E93 D40A <1> aam ; ah = al / 10, al = al mod 10 3388 00002E95 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3389 <1> ; AL = AH * 10h + AL 3390 00002E97 88C1 <1> mov cl, al ; minute (BCD) 3391 00002E99 A0[9A5E0000] <1> mov al, [second] 3392 00002E9E D40A <1> aam ; ah = al / 10, al = al mod 10 3393 00002EA0 D510 <1> db 0D5h, 10h ; Undocumented inst. AAD 3394 <1> ; AL = AH * 10h + AL 3395 00002EA2 88C6 <1> mov dh, al ; second (BCD) 3396 <1> 3397 <1> ; Set real-time clock time 3398 <1> ; call set_rtc_time 3399 <1> set_rtc_time: 3400 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 3401 <1> ; 15/03/2015 3402 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3403 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3404 <1> ; INT 1Ah 3405 <1> ; (AH) = 03H SET THE REAL TIME CLOCK USING, : 3406 <1> ; (CH) = HOURS IN BCD (00-23) : 3407 <1> ; (CL) = MINUTES IN BCD (00-59) : 3408 <1> ; (DH) = SECONDS IN BCD (00-59) : 3409 <1> ; (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00. : 3410 <1> ; : 3411 <1> ; NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. : 3412 <1> ; (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN : 3413 <1> ; APRIL (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN : 3414 <1> ; OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME. : 3415 <1> ; 3416 <1> RTC_30: ; SET RTC TIME 3417 00002EA4 FA <1> cli 3418 00002EA5 E876DCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3419 00002EAA 7305 <1> JNC short RTC_35 ; GO AROUND IF CLOCK OPERATING 3420 00002EAC E886000000 <1> CALL RTC_STA ; ELSE TRY INITIALIZING CLOCK 3421 <1> RTC_35: 3422 00002EB1 88F4 <1> MOV AH, DH ; GET TIME BYTE - SECONDS 3423 00002EB3 B000 <1> MOV AL, CMOS_SECONDS ; ADDRESS SECONDS 3424 00002EB5 E89D000000 <1> CALL CMOS_WRITE ; UPDATE SECONDS 3425 00002EBA 88CC <1> MOV AH, CL ; GET TIME BYTE - MINUTES 3426 00002EBC B002 <1> MOV AL, CMOS_MINUTES ; ADDRESS MINUTES 3427 00002EBE E894000000 <1> CALL CMOS_WRITE ; UPDATE MINUTES 3428 00002EC3 88EC <1> MOV AH, CH ; GET TIME BYTE - HOURS 3429 00002EC5 B004 <1> MOV AL, CMOS_HOURS ; ADDRESS HOURS 3430 00002EC7 E88B000000 <1> CALL CMOS_WRITE ; UPDATE ADDRESS 3431 <1> ;MOV AX, X*CMOS_REG_B ; ADDRESS ALARM REGISTER 3432 00002ECC 66B80B0B <1> MOV AX, 257*CMOS_REG_B ; 3433 00002ED0 E835DCFFFF <1> CALL CMOS_READ ; READ CURRENT TIME 3434 00002ED5 2462 <1> AND AL, 01100010B ; MASK FOR VALID BIT POSITIONS 3435 00002ED7 0C02 <1> OR AL, 00000010B ; TURN ON 24 HOUR MODE 3436 00002ED9 80E201 <1> AND DL, 00000001B ; USE ONLY THE DSE BIT 3437 00002EDC 08D0 <1> OR AL, DL ; GET DAY LIGHT SAVINGS TIME BIT (OSE) 3438 00002EDE 86E0 <1> XCHG AH, AL ; PLACE IN WORK REGISTER AND GET ADDRESS 3439 00002EE0 E872000000 <1> CALL CMOS_WRITE ; SET NEW ALARM BITS 3440 00002EE5 F8 <1> CLC ; SET CY= 0 3441 00002EE6 FB <1> sti 3442 00002EE7 C3 <1> RETn ; RETURN WITH CY= 0 3443 <1> 3444 <1> set_rtc_date: 3445 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 3446 <1> ; 15/03/2015 3447 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 3448 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 3449 <1> ; INT 1Ah 3450 <1> ; (AH) = 05H SET THE DATE INTO THE REAL TIME CLOCK USING, : 3451 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 3452 <1> ; (CL) = YEAR IN BCD (00-99) : 3453 <1> ; (DH) = MONTH IN BCD (01-12) : 3454 <1> ; (DL) = DAY IN BCD (01-31). 3455 <1> ; 3456 <1> RTC_50: ; SET RTC DATE 3457 00002EE8 FA <1> cli 3458 00002EE9 E832DCFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 3459 00002EEE 7305 <1> JNC short RTC_55 ; GO AROUND IF NO ERROR 3460 00002EF0 E842000000 <1> CALL RTC_STA ; ELSE INITIALIZE CLOCK 3461 <1> RTC_55: 3462 00002EF5 66B80600 <1> MOV AX, CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE 3463 00002EF9 E859000000 <1> CALL CMOS_WRITE ; LOAD ZEROS TO DAY OF WEEK 3464 00002EFE 88D4 <1> MOV AH, DL ; GET DAY OF MONTH BYTE 3465 00002F00 B007 <1> MOV AL, CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE 3466 00002F02 E850000000 <1> CALL CMOS_WRITE ; WRITE OF DAY OF MONTH REGISTER 3467 00002F07 88F4 <1> MOV AH, DH ; GET MONTH 3468 00002F09 B008 <1> MOV AL, CMOS_MONTH ; ADDRESS MONTH BYTE 3469 00002F0B E847000000 <1> CALL CMOS_WRITE ; WRITE MONTH REGISTER 3470 00002F10 88CC <1> MOV AH, CL ; GET YEAR BYTE 3471 00002F12 B009 <1> MOV AL, CMOS_YEAR ; ADDRESS YEAR REGISTER 3472 00002F14 E83E000000 <1> CALL CMOS_WRITE ; WRITE YEAR REGISTER 3473 00002F19 88EC <1> MOV AH, CH ; GET CENTURY BYTE 3474 00002F1B B032 <1> MOV AL, CMOS_CENTURY ; ADDRESS CENTURY BYTE 3475 00002F1D E835000000 <1> CALL CMOS_WRITE ; WRITE CENTURY LOCATION 3476 <1> ;MOV AX, X*CMOS_REG_B ; ADDRESS ALARM REGISTER 3477 00002F22 66B80B0B <1> MOV AX, 257*CMOS_REG_B ; 3478 00002F26 E8DFDBFFFF <1> CALL CMOS_READ ; READ CURRENT SETTINGS 3479 00002F2B 247F <1> AND AL, 07FH ; CLEAR 'SET BIT' 3480 00002F2D 86E0 <1> XCHG AH, AL ; MOVE TO WORK REGISTER 3481 00002F2F E823000000 <1> CALL CMOS_WRITE ; AND START CLOCK UPDATING 3482 00002F34 F8 <1> CLC ; SET CY= 0 3483 00002F35 FB <1> sti 3484 00002F36 C3 <1> RETn ; RETURN CY=0 3485 <1> 3486 <1> ; 15/03/2015 3487 <1> RTC_STA: ; INITIALIZE REAL TIME CLOCK 3488 00002F37 B426 <1> mov ah, 26h 3489 00002F39 B00A <1> mov al, CMOS_REG_A ; ADDRESS REGISTER A AND LOAD DATA MASK 3490 00002F3B E817000000 <1> CALL CMOS_WRITE ; INITIALIZE STATUS REGISTER A 3491 00002F40 B482 <1> mov ah, 82h 3492 00002F42 B00B <1> mov al, CMOS_REG_B ; SET "SET BIT" FOR CLOCK INITIALIZATION 3493 00002F44 E80E000000 <1> CALL CMOS_WRITE ; AND 24 HOUR MODE TO REGISTER B 3494 00002F49 B00C <1> MOV AL, CMOS_REG_C ; ADDRESS REGISTER C 3495 00002F4B E8BADBFFFF <1> CALL CMOS_READ ; READ REGISTER C TO INITIALIZE 3496 00002F50 B00D <1> MOV AL, CMOS_REG_D ; ADDRESS REGISTER D 3497 <1> ;CALL CMOS_READ ; READ REGISTER D TO INITIALIZE 3498 <1> ;RETn 3499 <1> ; 12/01/2022 3500 00002F52 E9B3DBFFFF <1> jmp CMOS_READ 3501 <1> 3502 <1> ; 15/03/2015 3503 <1> ; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm) 3504 <1> CMOS_WRITE: ; WRITE (AH) TO LOCATION (AL) 3505 00002F57 9C <1> pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 3506 <1> ;push ax ; SAVE WORK REGISTER VALUES 3507 00002F58 D0C0 <1> rol al, 1 ; MOVE NMI BIT TO LOW POSITION 3508 00002F5A F9 <1> stc ; FORCE NMI BIT ON IN CARRY FLAG 3509 00002F5B D0D8 <1> rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 3510 00002F5D FA <1> cli ; DISABLE INTERRUPTS 3511 00002F5E E670 <1> out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 3512 00002F60 88E0 <1> mov al, ah ; GET THE DATA BYTE TO WRITE 3513 00002F62 E671 <1> out CMOS_DATA, al ; PLACE IN REQUESTED CMOS LOCATION 3514 00002F64 B01E <1> mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 3515 00002F66 D0D8 <1> rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 3516 00002F68 E670 <1> out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 3517 00002F6A 90 <1> nop ; I/O DELAY 3518 00002F6B E471 <1> in al, CMOS_DATA ; OPEN STANDBY LATCH 3519 <1> ;pop ax ; RESTORE WORK REGISTERS 3520 00002F6D 9D <1> popf 3521 00002F6E C3 <1> RETn 3522 <1> 3523 <1> bf_init: 3524 <1> ; 14/08/2015 3525 <1> ; 02/07/2015 3526 <1> ; 01/07/2015 3527 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 3528 <1> ; Buffer (pointer) initialization ! 3529 <1> ; 3530 <1> ; 17/07/2013 - 24/07/2013 3531 <1> ; Retro UNIX 8086 v1 (U9.ASM) 3532 <1> ; (Retro UNIX 8086 v1 feature only !) 3533 <1> ; 3534 00002F6F BF[A8640000] <1> mov edi, bufp 3535 00002F74 B8[B4750000] <1> mov eax, buffer + (nbuf*520) 3536 00002F79 29D2 <1> sub edx, edx 3537 00002F7B FECA <1> dec dl 3538 00002F7D 31C9 <1> xor ecx, ecx 3539 00002F7F 49 <1> dec ecx 3540 <1> bi0: 3541 00002F80 2D08020000 <1> sub eax, 520 ; 8 header + 512 data 3542 00002F85 AB <1> stosd 3543 00002F86 89C6 <1> mov esi, eax 3544 00002F88 8916 <1> mov [esi], edx ; 000000FFh 3545 <1> ; Not a valid device sign 3546 00002F8A 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 3547 <1> ; Not a valid block number sign 3548 00002F8D 3D[74650000] <1> cmp eax, buffer 3549 00002F92 77EC <1> ja short bi0 3550 00002F94 B8[B4750000] <1> mov eax, sb0 3551 00002F99 AB <1> stosd 3552 00002F9A B8[BC770000] <1> mov eax, sb1 3553 00002F9F AB <1> stosd 3554 00002FA0 89C6 <1> mov esi, eax ; offset sb1 3555 00002FA2 8916 <1> mov [esi], edx ; 000000FFh 3556 <1> ; Not a valid device sign 3557 00002FA4 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 3558 <1> ; Not a valid block number sign 3559 <1> ; 14/08/2015 3560 <1> ;call rdev_init 3561 <1> ;retn 3562 <1> 3563 <1> rdev_init: ; root device, super block buffer initialization 3564 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3565 <1> ; 14/08/2015 3566 <1> ; Retro UNIX 386 v1 feature only ! 3567 <1> ; 3568 <1> ; NOTE: Disk partitions (file systems), logical 3569 <1> ; drive initialization, partition's start sector etc. 3570 <1> ; will be coded here, later in 'ldrv_init' 3571 <1> 3572 00002FA7 0FB605[485C0000] <1> movzx eax, byte [boot_drv] 3573 <1> rdi_0: 3574 00002FAE 3C80 <1> cmp al, 80h 3575 00002FB0 7202 <1> jb short rdi_1 3576 00002FB2 2C7E <1> sub al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1) 3577 <1> rdi_1: 3578 00002FB4 A2[D4640000] <1> mov [rdev], al 3579 00002FB9 BB[B4750000] <1> mov ebx, sb0 ; super block buffer 3580 00002FBE 8903 <1> mov [ebx], eax 3581 00002FC0 B001 <1> mov al, 1 ; eax = 1 3582 00002FC2 894304 <1> mov [ebx+4], eax ; super block address on disk 3583 <1> ;call diskio 3584 <1> ;retn 3585 <1> ; 24/12/2021 3586 00002FC5 E923250000 <1> jmp diskio 3587 <1> 3588 <1> ; 23/10/2015 3589 <1> com1_irq4: 3590 00002FCA [D22F0000] <1> dd dummy_retn 3591 <1> com2_irq3: 3592 00002FCE [D22F0000] <1> dd dummy_retn 3593 <1> 3594 <1> dummy_retn: 3595 00002FD2 C3 <1> retn 2114 %include 'u1.s' ; 10/05/2015 2115 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS1.INC 2116 <1> ; Last Modification: 17/07/2022 2117 <1> ; ---------------------------------------------------------------------------- 2118 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2119 <1> ; (v0.1 - Beginning: 11/07/2012) 2120 <1> ; 2121 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2122 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2123 <1> ; 2124 <1> ; 2125 <1> ; 2126 <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s 2127 <1> ; 2128 <1> ; **************************************************************************** 2129 <1> 2130 <1> unkni: ; / used for all system calls 2131 <1> sysent: ; < enter to system call > 2132 <1> ; 08/01/2022 2133 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2134 <1> ; 19/10/2015 2135 <1> ; 21/09/2015 2136 <1> ; 01/07/2015 2137 <1> ; 19/05/2015 2138 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2139 <1> ; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2140 <1> ; 2141 <1> ; 'unkni' or 'sysent' is sytem entry from various traps. 2142 <1> ; The trap type is determined and an indirect jump is made to 2143 <1> ; the appropriate system call handler. If there is a trap inside 2144 <1> ; the system a jump to panic is made. All user registers are saved 2145 <1> ; and u.sp points to the end of the users stack. The sys (trap) 2146 <1> ; instructor is decoded to get the the system code part (see 2147 <1> ; trap instruction in the PDP-11 handbook) and from this 2148 <1> ; the indirect jump address is calculated. If a bad system call is 2149 <1> ; made, i.e., the limits of the jump table are exceeded, 'badsys' 2150 <1> ; is called. If the call is legitimate control passes to the 2151 <1> ; appropriate system routine. 2152 <1> ; 2153 <1> ; Calling sequence: 2154 <1> ; Through a trap caused by any sys call outside the system. 2155 <1> ; Arguments: 2156 <1> ; Arguments of particular system call. 2157 <1> ; ............................................................... 2158 <1> ; 2159 <1> ; Retro UNIX 8086 v1 modification: 2160 <1> ; System call number is in EAX register. 2161 <1> ; 2162 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 2163 <1> ; registers depending of function details. 2164 <1> ; 2165 <1> ; 16/04/2015 2166 00002FD3 368925[E4640000] <1> mov [ss:u.sp], esp ; Kernel stack points to return address 2167 <1> ; save user registers 2168 00002FDA 1E <1> push ds 2169 00002FDB 06 <1> push es 2170 00002FDC 0FA0 <1> push fs 2171 00002FDE 0FA8 <1> push gs 2172 00002FE0 60 <1> pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 2173 <1> ; 2174 <1> ; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015 2175 <1> ; (ESPACE is size of space in kernel stack 2176 <1> ; for saving/restoring user registers.) 2177 <1> ; 2178 00002FE1 50 <1> push eax ; 01/07/2015 2179 00002FE2 66B81000 <1> mov ax, KDATA 2180 00002FE6 8ED8 <1> mov ds, ax 2181 00002FE8 8EC0 <1> mov es, ax 2182 00002FEA 8EE0 <1> mov fs, ax 2183 00002FEC 8EE8 <1> mov gs, ax 2184 00002FEE A1[28610000] <1> mov eax, [k_page_dir] 2185 00002FF3 0F22D8 <1> mov cr3, eax 2186 00002FF6 58 <1> pop eax ; 01/07/2015 2187 <1> ; 19/10/2015 2188 00002FF7 FC <1> cld 2189 <1> ; 2190 00002FF8 FE05[E3640000] <1> inc byte [sysflg] 2191 <1> ; incb sysflg / indicate a system routine is in progress 2192 00002FFE FB <1> sti ; 18/01/2014 2193 <1> ;jnz panic ; 24/05/2013 2194 <1> ; 24/12/2021 2195 00002FFF 7405 <1> jz short _1 2196 00003001 E987F9FFFF <1> jmp panic 2197 <1> ; beq 1f 2198 <1> ; jmp panic ; / called if trap inside system 2199 <1> ;1: 2200 <1> _1: ; 24/12/2021 2201 <1> ; 16/04/2015 2202 00003006 A3[EC640000] <1> mov [u.r0], eax 2203 0000300B 8925[E8640000] <1> mov [u.usp], esp ; kernel stack points to user's registers 2204 <1> ; 2205 <1> ; mov $s.syst+2,clockp 2206 <1> ; mov r0,-(sp) / save user registers 2207 <1> ; mov sp,u.r0 / pointer to bottom of users stack 2208 <1> ; / in u.r0 2209 <1> ; mov r1,-(sp) 2210 <1> ; mov r2,-(sp) 2211 <1> ; mov r3,-(sp) 2212 <1> ; mov r4,-(sp) 2213 <1> ; mov r5,-(sp) 2214 <1> ; mov ac,-(sp) / "accumulator" register for extended 2215 <1> ; / arithmetic unit 2216 <1> ; mov mq,-(sp) / "multiplier quotient" register for the 2217 <1> ; / extended arithmetic unit 2218 <1> ; mov sc,-(sp) / "step count" register for the extended 2219 <1> ; / arithmetic unit 2220 <1> ; mov sp,u.sp / u.sp points to top of users stack 2221 <1> ; mov 18.(sp),r0 / store pc in r0 2222 <1> ; mov -(r0),r0 / sys inst in r0 10400xxx 2223 <1> ; sub $sys,r0 / get xxx code 2224 00003011 C1E002 <1> shl eax, 2 2225 <1> ; asl r0 / multiply by 2 to jump indirect in bytes 2226 00003014 3D94000000 <1> cmp eax, end_of_syscalls - syscalls 2227 <1> ; cmp r0,$2f-1f / limit of table (35) exceeded 2228 <1> ;jnb short badsys 2229 <1> ; bhis badsys / yes, bad system call 2230 <1> ; 08/01/2022 2231 00003019 7205 <1> jb short _2 2232 0000301B E95D010000 <1> jmp badsys 2233 <1> _2: 2234 <1> ; 08/01/2022 2235 <1> ;cmc 2236 <1> ;pushf 2237 <1> ;push eax 2238 00003020 8B2D[E4640000] <1> mov ebp, [u.sp] ; Kernel stack at the beginning of sys call 2239 <1> ;mov al, 0FEh ; 11111110b 2240 <1> ;;adc al, 0 ; al = al + cf 2241 <1> ;and [ebp+8], al ; flags (reset carry flag) 2242 00003026 806508FE <1> and byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021 2243 <1> ; bic $341,20.(sp) / set users processor priority to 0 2244 <1> ; / and clear carry bit 2245 <1> ;pop ebp ; eax 2246 0000302A 89C5 <1> mov ebp, eax ; 25/12/2021 2247 <1> ;popf 2248 <1> ;;jc badsys 2249 <1> ; 24/12/2021 2250 <1> ;jnc short _3 ; 08/01/2022 2251 <1> ;jmp badsys 2252 <1> ;_3: 2253 0000302C A1[EC640000] <1> mov eax, [u.r0] 2254 <1> ; system call registers: EAX, EDX, ECX, EBX, ESI, EDI 2255 00003031 FFA5[37300000] <1> jmp dword [ebp+syscalls] 2256 <1> ; jmp *1f(r0) / jump indirect thru table of addresses 2257 <1> ; / to proper system routine. 2258 <1> syscalls: ; 1: 2259 <1> ; 21/09/2015 2260 <1> ; 01/07/2015 2261 <1> ; 16/04/2015 (32 bit address modification) 2262 00003037 [47310000] <1> dd sysrele ; / 0 2263 0000303B [EF310000] <1> dd sysexit ; / 1 2264 0000303F [19330000] <1> dd sysfork ; / 2 2265 00003043 [1F340000] <1> dd sysread ; / 3 2266 00003047 [32340000] <1> dd syswrite ; / 4 2267 0000304B [9B340000] <1> dd sysopen ; / 5 2268 0000304F [C6350000] <1> dd sysclose ; / 6 2269 00003053 [94320000] <1> dd syswait ; / 7 2270 00003057 [43350000] <1> dd syscreat ; / 8 2271 0000305B [7F390000] <1> dd syslink ; / 9 2272 0000305F [3B3A0000] <1> dd sysunlink ; / 10 2273 00003063 [053B0000] <1> dd sysexec ; / 11 2274 00003067 [88410000] <1> dd syschdir ; / 12 2275 0000306B [6B420000] <1> dd systime ; / 13 2276 0000306F [7F350000] <1> dd sysmkdir ; / 14 2277 00003073 [D8410000] <1> dd syschmod ; / 15 2278 00003077 [3B420000] <1> dd syschown ; / 16 2279 0000307B [9E420000] <1> dd sysbreak ; / 17 2280 0000307F [C53E0000] <1> dd sysstat ; / 18 2281 00003083 [6E430000] <1> dd sysseek ; / 19 2282 00003087 [80430000] <1> dd systell ; / 20 2283 0000308B [BE4E0000] <1> dd sysmount ; / 21 2284 0000308F [A94F0000] <1> dd sysumount ; / 22 2285 00003093 [FC430000] <1> dd syssetuid ; / 23 2286 00003097 [2D440000] <1> dd sysgetuid ; / 24 2287 0000309B [7A420000] <1> dd sysstime ; / 25 2288 0000309F [F0430000] <1> dd sysquit ; / 26 2289 000030A3 [E4430000] <1> dd sysintr ; / 27 2290 000030A7 [A23E0000] <1> dd sysfstat ; / 28 2291 000030AB [E3350000] <1> dd sysemt ; / 29 2292 000030AF [2F360000] <1> dd sysmdate ; / 30 2293 000030B3 [89360000] <1> dd sysstty ; / 31 2294 000030B7 [72380000] <1> dd sysgtty ; / 32 2295 000030BB [2A360000] <1> dd sysilgins ; / 33 2296 000030BF [0F570000] <1> dd syssleep ; 34 ; Retro UNIX 8086 v1 feature only ! 2297 <1> ; 11/06/2014 2298 000030C3 [26570000] <1> dd sysmsg ; 35 ; Retro UNIX 386 v1 feature only ! 2299 <1> ; 01/07/2015 2300 000030C7 [FE570000] <1> dd sysgeterr ; 36 ; Retro UNIX 386 v1 feature only ! 2301 <1> ; 21/09/2015 - get last error number 2302 <1> end_of_syscalls: 2303 <1> 2304 <1> error: 2305 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2306 <1> ; 17/09/2015 2307 <1> ; 03/09/2015 2308 <1> ; 01/09/2015 2309 <1> ; 09/06/2015 2310 <1> ; 13/05/2015 2311 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2312 <1> ; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 2313 <1> ; 2314 <1> ; 'error' merely sets the error bit off the processor status (c-bit) 2315 <1> ; then falls right into the 'sysret', 'sysrele' return sequence. 2316 <1> ; 2317 <1> ; INPUTS -> none 2318 <1> ; OUTPUTS -> 2319 <1> ; processor status - carry (c) bit is set (means error) 2320 <1> ; 2321 <1> ; 26/05/2013 (Stack pointer must be reset here! 2322 <1> ; Because, jumps to error procedure 2323 <1> ; disrupts push-pop nesting balance) 2324 <1> ; 2325 000030CB 8B2D[E4640000] <1> mov ebp, [u.sp] ; interrupt (system call) return (iretd) address 2326 000030D1 804D0801 <1> or byte [ebp+8], 1 ; set carry bit of flags register 2327 <1> ; (system call will return with cf = 1) 2328 <1> ; bis $1,20.(r1) / set c bit in processor status word below 2329 <1> ; / users stack 2330 <1> ; 17/09/2015 2331 000030D5 83ED30 <1> sub ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc') 2332 <1> ; for saving/restoring user registers 2333 <1> ;cmp ebp, [u.usp] 2334 <1> ;je short err0 2335 000030D8 892D[E8640000] <1> mov [u.usp], ebp 2336 <1> ;err0: 2337 <1> ; 01/09/2015 2338 000030DE 8B25[E8640000] <1> mov esp, [u.usp] ; Retro Unix 8086 v1 modification! 2339 <1> ; 10/04/2013 2340 <1> ; (If an I/O error occurs during disk I/O, 2341 <1> ; related procedures will jump to 'error' 2342 <1> ; procedure directly without returning to 2343 <1> ; the caller procedure. So, stack pointer 2344 <1> ; must be restored here.) 2345 <1> ; 13/05/2015 2346 <1> ; NOTE: (The last) error code is in 'u.error', it can be retrieved by 2347 <1> ; 'get last error' system call later. 2348 <1> 2349 <1> ; 03/09/2015 - 09/06/2015 - 07/08/2013 2350 000030E4 C605[53650000]00 <1> mov byte [u.kcall], 0 ; namei_r, mkdir_w reset 2351 <1> 2352 <1> sysret: ; < return from system call> 2353 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2354 <1> ; 10/09/2015 2355 <1> ; 29/07/2015 2356 <1> ; 25/06/2015 2357 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2358 <1> ; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 2359 <1> ; 2360 <1> ; 'sysret' first checks to see if process is about to be 2361 <1> ; terminated (u.bsys). If it is, 'sysexit' is called. 2362 <1> ; If not, following happens: 2363 <1> ; 1) The user's stack pointer is restored. 2364 <1> ; 2) r1=0 and 'iget' is called to see if last mentioned 2365 <1> ; i-node has been modified. If it has, it is written out 2366 <1> ; via 'ppoke'. 2367 <1> ; 3) If the super block has been modified, it is written out 2368 <1> ; via 'ppoke'. 2369 <1> ; 4) If the dismountable file system's super block has been 2370 <1> ; modified, it is written out to the specified device 2371 <1> ; via 'ppoke'. 2372 <1> ; 5) A check is made if user's time quantum (uquant) ran out 2373 <1> ; during his execution. If so, 'tswap' is called to give 2374 <1> ; another user a chance to run. 2375 <1> ; 6) 'sysret' now goes into 'sysrele'. 2376 <1> ; (See 'sysrele' for conclusion.) 2377 <1> ; 2378 <1> ; Calling sequence: 2379 <1> ; jump table or 'br sysret' 2380 <1> ; Arguments: 2381 <1> ; - 2382 <1> ; ............................................................... 2383 <1> ; 2384 <1> ; ((AX=r1 for 'iget' input)) 2385 <1> ; 2386 <1> ;xor ax, ax ; 04/05/2013 2387 <1> ; 24/12/2021 2388 000030EB 31C0 <1> xor eax, eax 2389 <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec) 2390 000030ED FEC0 <1> inc al ; 04/05/2013 2391 000030EF 3805[3A650000] <1> cmp [u.bsys], al ; 1 2392 <1> ; tstb u.bsys / is a process about to be terminated because 2393 <1> ;jnb sysexit ; 04/05/2013 2394 <1> ; ; bne sysexit / of an error? yes, go to sysexit 2395 <1> ; 24/12/2021 2396 000030F5 720F <1> jb short _3 2397 000030F7 C705[41650000]0100- <1> mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 2397 000030FF 0000 <1> 2398 00003101 E9E9000000 <1> jmp sysexit 2399 <1> _3: 2400 <1> ;mov esp, [u.usp] ; 24/05/2013 (that is not needed here) 2401 <1> ; mov u.sp,sp / no point stack to users stack 2402 00003106 FEC8 <1> dec al ; mov ax, 0 2403 <1> ; clr r1 / zero r1 to check last mentioned i-node 2404 00003108 E8DA160000 <1> call iget 2405 <1> ; jsr r0,iget / if last mentioned i-node has been modified 2406 <1> ; / it is written out 2407 <1> ;xor ax, ax ; 0 2408 <1> ; 24/12/2021 2409 0000310D 31C0 <1> xor eax, eax 2410 0000310F 3805[E1640000] <1> cmp [smod], al ; 0 2411 <1> ; tstb smod / has the super block been modified 2412 00003115 7614 <1> jna short sysret1 2413 <1> ; beq 1f / no, 1f 2414 00003117 A2[E1640000] <1> mov [smod], al ; 0 2415 <1> ; clrb smod / yes, clear smod 2416 0000311C BB[B4750000] <1> mov ebx, sb0 ;; 07/08//2013 2417 00003121 66810B0002 <1> or word [ebx], 200h ;; 2418 <1> ;or word [sb0], 200h ; write bit, bit 9 2419 <1> ; bis $1000,sb0 / set write bit in I/O queue for super block 2420 <1> ; / output 2421 <1> ; AX = 0 2422 00003126 E826230000 <1> call poke ; 07/08/2013 2423 <1> ; call ppoke 2424 <1> ; AX = 0 2425 <1> ; jsr r0,ppoke / write out modified super block to disk 2426 <1> sysret1: ;1: 2427 0000312B 3805[E2640000] <1> cmp [mmod], al ; 0 2428 <1> ; tstb mmod / has the super block for the dismountable file 2429 <1> ; / system 2430 00003131 7614 <1> jna short sysrel0 2431 <1> ; beq 1f / been modified? no, 1f 2432 00003133 A2[E2640000] <1> mov [mmod], al ; 0 2433 <1> ; clrb mmod / yes, clear mmod 2434 <1> ;mov ax, [mntd] 2435 <1> ;;mov al, [mdev] ; 26/04/2013 2436 00003138 BB[BC770000] <1> mov ebx, sb1 ;; 07/08//2013 2437 <1> ;;mov [ebx], al 2438 <1> ;mov [sb1], al 2439 <1> ; movb mntd,sb1 / set the I/O queue 2440 0000313D 66810B0002 <1> or word [ebx], 200h 2441 <1> ;or word [sb1], 200h ; write bit, bit 9 2442 <1> ; bis $1000,sb1 / set write bit in I/O queue for detached sb 2443 00003142 E80A230000 <1> call poke ; 07/08/2013 2444 <1> ;call ppoke 2445 <1> ; jsr r0,ppoke / write it out to its device 2446 <1> ;xor al, al ; 26/04/2013 2447 <1> ;1: 2448 <1> ; tstb uquant / is the time quantum 0? 2449 <1> ; bne 1f / no, don't swap it out 2450 <1> 2451 <1> sysrele: ; < release > 2452 <1> ; 14/10/2015 2453 <1> ; 01/09/2015 2454 <1> ; 24/07/2015 2455 <1> ; 14/05/2015 2456 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2457 <1> ; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1) 2458 <1> ; 2459 <1> ; 'sysrele' first calls 'tswap' if the time quantum for a user is 2460 <1> ; zero (see 'sysret'). It then restores the user's registers and 2461 <1> ; turns off the system flag. It then checked to see if there is 2462 <1> ; an interrupt from the user by calling 'isintr'. If there is, 2463 <1> ; the output gets flashed (see isintr) and interrupt action is 2464 <1> ; taken by a branch to 'intract'. If there is no interrupt from 2465 <1> ; the user, a rti is made. 2466 <1> ; 2467 <1> ; Calling sequence: 2468 <1> ; Fall through a 'bne' in 'sysret' & ? 2469 <1> ; Arguments: 2470 <1> ; - 2471 <1> ; ............................................................... 2472 <1> ; 2473 <1> ; 23/02/2014 (swapret) 2474 <1> ; 22/09/2013 2475 <1> sysrel0: ;1: 2476 00003147 803D[2E650000]00 <1> cmp byte [u.quant], 0 ; 16/05/2013 2477 <1> ; tstb uquant / is the time quantum 0? 2478 0000314E 7705 <1> ja short swapret 2479 <1> ; bne 1f / no, don't swap it out 2480 <1> sysrelease: ; 07/12/2013 (jump from 'clock') 2481 00003150 E828130000 <1> call tswap 2482 <1> ; jsr r0,tswap / yes, swap it out 2483 <1> ; 2484 <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address. 2485 <1> swapret: ;1: 2486 <1> ; 10/09/2015 2487 <1> ; 01/09/2015 2488 <1> ; 14/05/2015 2489 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications) 2490 <1> ; 26/05/2013 (Retro UNIX 8086 v1) 2491 <1> ; cli 2492 <1> ; 24/07/2015 2493 <1> ; 2494 <1> ;; 'esp' must be already equal to '[u.usp]' here ! 2495 <1> ;; mov esp, [u.usp] 2496 <1> 2497 <1> ; 22/09/2013 2498 00003155 E8FA140000 <1> call isintr 2499 <1> ; 20/10/2013 2500 0000315A 7405 <1> jz short sysrel1 2501 0000315C E877000000 <1> call intract 2502 <1> ; jsr r0,isintr / is there an interrupt from the user 2503 <1> ; br intract / yes, output gets flushed, take interrupt 2504 <1> ; / action 2505 <1> sysrel1: 2506 00003161 FA <1> cli ; 14/10/2015 2507 00003162 FE0D[E3640000] <1> dec byte [sysflg] 2508 <1> ; decb sysflg / turn system flag off 2509 00003168 A1[45650000] <1> mov eax, [u.pgdir] 2510 0000316D 0F22D8 <1> mov cr3, eax ; 1st PDE points to Kernel Page Table 0 (1st 4 MB) 2511 <1> ; (others are different than kernel page tables) 2512 <1> ; 10/09/2015 2513 00003170 61 <1> popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 2514 <1> ; mov (sp)+,sc / restore user registers 2515 <1> ; mov (sp)+,mq 2516 <1> ; mov (sp)+,ac 2517 <1> ; mov (sp)+,r5 2518 <1> ; mov (sp)+,r4 2519 <1> ; mov (sp)+,r3 2520 <1> ; mov (sp)+,r2 2521 <1> ; 2522 00003171 A1[EC640000] <1> mov eax, [u.r0] ; ((return value in EAX)) 2523 00003176 0FA9 <1> pop gs 2524 00003178 0FA1 <1> pop fs 2525 0000317A 07 <1> pop es 2526 0000317B 1F <1> pop ds 2527 0000317C CF <1> iretd 2528 <1> ; rti / no, return from interrupt 2529 <1> 2530 <1> badsys: 2531 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2532 <1> ; (Major Modification: 'core' dumping procedure in 2533 <1> ; original UNIX v1 and Retro UNIX 8086 v1 2534 <1> ; has been changed to print 'Invalid System Call !' 2535 <1> ; message on the user's console tty.) 2536 <1> ; (EIP, EAX values will be shown on screen with error message) 2537 <1> ; (EIP = Return address just after the system call -INT 30h-) 2538 <1> ; (EAX = Function number) 2539 <1> ; 2540 0000317D FE05[3A650000] <1> inc byte [u.bsys] 2541 <1> ; 2542 00003183 8B1D[E4640000] <1> mov ebx, [u.sp] ; esp at the beginning of 'sysent' 2543 00003189 8B03 <1> mov eax, [ebx] ; EIP (return address, not 'INT 30h' address) 2544 0000318B E83AE4FFFF <1> call dwordtohex 2545 00003190 8915[885E0000] <1> mov [bsys_msg_eip], edx 2546 00003196 A3[8C5E0000] <1> mov [bsys_msg_eip+4], eax 2547 0000319B A1[EC640000] <1> mov eax, [u.r0] 2548 000031A0 E825E4FFFF <1> call dwordtohex 2549 000031A5 8915[785E0000] <1> mov [bsys_msg_eax], edx 2550 000031AB A3[7C5E0000] <1> mov [bsys_msg_eax+4], eax 2551 <1> ; 24/12/2021 2552 <1> ;xor eax, eax 2553 <1> ;mov dword [u.base], badsys_msg ; "Invalid System Call !" 2554 <1> ;mov ebx, [u.fofp] 2555 <1> ;mov [ebx], eax 2556 <1> ;;mov eax, 1 ; inode number of console tty (for user) 2557 <1> ;inc eax 2558 <1> ;mov dword [u.count], BSYS_M_SIZE 2559 <1> ; writei 2560 <1> ; INPUTS -> 2561 <1> ; r1 - inode number 2562 <1> ; u.count - byte count to be written 2563 <1> ; u.base - points to user buffer 2564 <1> ; u.fofp - points to word with current file offset 2565 <1> ; OUTPUTS -> 2566 <1> ; u.count - cleared 2567 <1> ; u.nread - accumulates total bytes passed back 2568 <1> ; 2569 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 2570 <1> ;call writei 2571 <1> ;;mov eax, 1 2572 <1> ;jmp sysexit 2573 <1> 2574 <1> ; 24/12/2021 - Retro UNIX 386 v1.1 2575 000031B0 BE[595E0000] <1> mov esi, badsys_msg ; "Invalid System Call !" 2576 000031B5 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 2577 000031BC 8A83[43620000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2578 000031C2 C605[57610000]0F <1> mov byte [ccolor], 0Fh ; white (message) color 2579 000031C9 A2[40650000] <1> mov [u.ttyn], al ; current (active) tty (for user) 2580 000031CE E810260000 <1> call print_cmsg 2581 <1> ;mov dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !' 2582 000031D3 E9F3FEFFFF <1> jmp error 2583 <1> 2584 <1> ; incb u.bsys / turn on the user's bad-system flag 2585 <1> ; mov $3f,u.namep / point u.namep to "core\0\0" 2586 <1> ; jsr r0,namei / get the i-number for the core image file 2587 <1> ; br 1f / error 2588 <1> ; neg r1 / negate the i-number to open the core image file 2589 <1> ; / for writing 2590 <1> ; jsr r0,iopen / open the core image file 2591 <1> ; jsr r0,itrunc / free all associated blocks 2592 <1> ; br 2f 2593 <1> ;1: 2594 <1> ; mov $17,r1 / put i-node mode (17) in r1 2595 <1> ; jsr r0,maknod / make an i-node 2596 <1> ; mov u.dirbuf,r1 / put i-node number in r1 2597 <1> ;2: 2598 <1> ; mov $core,u.base / move address core to u.base 2599 <1> ; mov $ecore-core,u.count / put the byte count in u.count 2600 <1> ; mov $u.off,u.fofp / more user offset to u.fofp 2601 <1> ; clr u.off / clear user offset 2602 <1> ; jsr r0,writei / write out the core image to the user 2603 <1> ; mov $user,u.base / pt. u.base to user 2604 <1> ; mov $64.,u.count / u.count = 64 2605 <1> ; jsr r0,writei / write out all the user parameters 2606 <1> ; neg r1 / make i-number positive 2607 <1> ; jsr r0,iclose / close the core image file 2608 <1> ; br sysexit / 2609 <1> ;3: 2610 <1> ; 2611 <1> 2612 <1> intract: ; / interrupt action 2613 <1> ; 14/10/2015 2614 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2615 <1> ; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1) 2616 <1> ; 2617 <1> ; Retro UNIX 8086 v1 modification ! 2618 <1> ; (Process/task switching and quit routine by using 2619 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2620 <1> ; 2621 <1> ; input -> 'u.quit' (also value of 'u.intr' > 0) 2622 <1> ; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign) 2623 <1> ; 'intract' will jump to 'sysexit'. 2624 <1> ; Intract will return to the caller 2625 <1> ; if value of 'u.quit' <> FFFFh. 2626 <1> ; 14/10/2015 2627 000031D8 FB <1> sti 2628 <1> ; 07/12/2013 2629 000031D9 66FF05[32650000] <1> inc word [u.quit] 2630 000031E0 7408 <1> jz short intrct0 ; FFFFh -> 0 2631 000031E2 66FF0D[32650000] <1> dec word [u.quit] 2632 <1> ; 16/04/2015 2633 000031E9 C3 <1> retn 2634 <1> intrct0: 2635 000031EA 58 <1> pop eax ; call intract -> retn 2636 <1> ; 2637 000031EB 31C0 <1> xor eax, eax 2638 000031ED FEC0 <1> inc al ; mov ax, 1 2639 <1> ;;; 2640 <1> ; UNIX v1 original 'intract' routine... 2641 <1> ; / interrupt action 2642 <1> ;cmp *(sp),$rti / are you in a clock interrupt? 2643 <1> ; bne 1f / no, 1f 2644 <1> ; cmp (sp)+,(sp)+ / pop clock pointer 2645 <1> ; 1: / now in user area 2646 <1> ; mov r1,-(sp) / save r1 2647 <1> ; mov u.ttyp,r1 2648 <1> ; / pointer to tty buffer in control-to r1 2649 <1> ; cmpb 6(r1),$177 2650 <1> ; / is the interrupt char equal to "del" 2651 <1> ; beq 1f / yes, 1f 2652 <1> ; clrb 6(r1) 2653 <1> ; / no, clear the byte 2654 <1> ; / (must be a quit character) 2655 <1> ; mov (sp)+,r1 / restore r1 2656 <1> ; clr u.quit / clear quit flag 2657 <1> ; bis $20,2(sp) 2658 <1> ; / set trace for quit (sets t bit of 2659 <1> ; / ps-trace trap) 2660 <1> ; rti ; / return from interrupt 2661 <1> ; 1: / interrupt char = del 2662 <1> ; clrb 6(r1) / clear the interrupt byte 2663 <1> ; / in the buffer 2664 <1> ; mov (sp)+,r1 / restore r1 2665 <1> ; cmp u.intr,$core / should control be 2666 <1> ; / transferred to loc core? 2667 <1> ; blo 1f 2668 <1> ; jmp *u.intr / user to do rti yes, 2669 <1> ; / transfer to loc core 2670 <1> ; 1: 2671 <1> ; sys 1 / exit 2672 <1> 2673 <1> sysexit: ; 2674 <1> ; 17/07/2022 2675 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2676 <1> ; 01/09/2015 2677 <1> ; 31/08/2015 2678 <1> ; 14/05/2015 2679 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2680 <1> ; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2681 <1> ; 2682 <1> ; 'sysexit' terminates a process. First each file that 2683 <1> ; the process has opened is closed by 'flose'. The process 2684 <1> ; status is then set to unused. The 'p.pid' table is then 2685 <1> ; searched to find children of the dying process. If any of 2686 <1> ; children are zombies (died by not waited for), they are 2687 <1> ; set free. The 'p.pid' table is then searched to find the 2688 <1> ; dying process's parent. When the parent is found, it is 2689 <1> ; checked to see if it is free or it is a zombie. If it is 2690 <1> ; one of these, the dying process just dies. If it is waiting 2691 <1> ; for a child process to die, it notified that it doesn't 2692 <1> ; have to wait anymore by setting it's status from 2 to 1 2693 <1> ; (waiting to active). It is awakened and put on runq by 2694 <1> ; 'putlu'. The dying process enters a zombie state in which 2695 <1> ; it will never be run again but stays around until a 'wait' 2696 <1> ; is completed by it's parent process. If the parent is not 2697 <1> ; found, process just dies. This means 'swap' is called with 2698 <1> ; 'u.uno=0'. What this does is the 'wswap' is not called 2699 <1> ; to write out the process and 'rswap' reads the new process 2700 <1> ; over the one that dies..i.e., the dying process is 2701 <1> ; overwritten and destroyed. 2702 <1> ; 2703 <1> ; Calling sequence: 2704 <1> ; sysexit or conditional branch. 2705 <1> ; Arguments: 2706 <1> ; - 2707 <1> ; ............................................................... 2708 <1> ; 2709 <1> ; Retro UNIX 8086 v1 modification: 2710 <1> ; System call number (=1) is in EAX register. 2711 <1> ; 2712 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 2713 <1> ; registers depending of function details. 2714 <1> ; 2715 <1> ; ('swap' procedure is mostly different than original UNIX v1.) 2716 <1> ; 2717 <1> ; / terminate process 2718 <1> ; AX = 1 2719 <1> ;dec ax ; 0 2720 <1> ; 24/12/2021 2721 000031EF 48 <1> dec eax ; 0 2722 <1> ;dec ax ; 0 2723 000031F0 66A3[30650000] <1> mov [u.intr], ax ; 0 2724 <1> ; clr u.intr / clear interrupt control word 2725 <1> ; clr r1 / clear r1 2726 <1> ; AX = 0 2727 <1> sysexit_1: ; 1: 2728 <1> ; AX = File descriptor 2729 <1> ; / r1 has file descriptor (index to u.fp list) 2730 <1> ; / Search the whole list 2731 000031F6 E8680D0000 <1> call fclose 2732 <1> ; jsr r0,fclose / close all files the process opened 2733 <1> ;; ignore error return 2734 <1> ; br .+2 / ignore error return 2735 <1> ;inc ax 2736 000031FB FEC0 <1> inc al 2737 <1> ; inc r1 / increment file descriptor 2738 <1> ;cmp ax, 10 2739 000031FD 3C0A <1> cmp al, 10 2740 <1> ; cmp r1,$10. / end of u.fp list? 2741 000031FF 72F5 <1> jb short sysexit_1 2742 <1> ; blt 1b / no, go back 2743 00003201 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 2744 <1> ; movb u.uno,r1 / yes, move dying process's number to r1 2745 00003208 88A3[63620000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 2746 <1> ; clrb p.stat-1(r1) / free the process 2747 <1> ;shl bx, 1 2748 0000320E D0E3 <1> shl bl, 1 2749 <1> ; asl r1 / use r1 for index into the below tables 2750 00003210 668B8B[02620000] <1> mov cx, [ebx+p.pid-2] 2751 <1> ; mov p.pid-2(r1),r3 / move dying process's name to r3 2752 00003217 668B93[22620000] <1> mov dx, [ebx+p.ppid-2] 2753 <1> ; mov p.ppid-2(r1),r4 / move its parents name to r4 2754 <1> ; xor bx, bx ; 0 2755 0000321E 30DB <1> xor bl, bl ; 0 2756 <1> ; clr r2 2757 00003220 31F6 <1> xor esi, esi ; 0 2758 <1> ; clr r5 / initialize reg 2759 <1> sysexit_2: ; 1: 2760 <1> ; / find children of this dying process, 2761 <1> ; / if they are zombies, free them 2762 <1> ;add bx, 2 2763 00003222 80C302 <1> add bl, 2 2764 <1> ; add $2,r2 / search parent process table 2765 <1> ; / for dying process's name 2766 00003225 66398B[22620000] <1> cmp [ebx+p.ppid-2], cx 2767 <1> ; cmp p.ppid-2(r2),r3 / found it? 2768 0000322C 7513 <1> jne short sysexit_4 2769 <1> ; bne 3f / no 2770 <1> ;shr bx, 1 2771 0000322E D0EB <1> shr bl, 1 2772 <1> ; asr r2 / yes, it is a parent 2773 00003230 80BB[63620000]03 <1> cmp byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 2774 <1> ; cmpb p.stat-1(r2),$3 / is the child of this 2775 <1> ; / dying process a zombie 2776 00003237 7506 <1> jne short sysexit_3 2777 <1> ; bne 2f / no 2778 00003239 88A3[63620000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 2779 <1> ; clrb p.stat-1(r2) / yes, free the child process 2780 <1> sysexit_3: ; 2: 2781 <1> ;shr bx, 1 2782 0000323F D0E3 <1> shl bl, 1 2783 <1> ; asl r2 2784 <1> sysexit_4: ; 3: 2785 <1> ; / search the process name table 2786 <1> ; / for the dying process's parent 2787 00003241 663993[02620000] <1> cmp [ebx+p.pid-2], dx ; 17/09/2013 2788 <1> ; cmp p.pid-2(r2),r4 / found it? 2789 00003248 7502 <1> jne short sysexit_5 2790 <1> ; bne 3f / no 2791 0000324A 89DE <1> mov esi, ebx 2792 <1> ; mov r2,r5 / yes, put index to p.pid table (parents 2793 <1> ; / process # x2) in r5 2794 <1> sysexit_5: ; 3: 2795 <1> ;cmp bx, nproc + nproc 2796 0000324C 80FB20 <1> cmp bl, nproc + nproc 2797 <1> ; cmp r2,$nproc+nproc / has whole table been searched? 2798 0000324F 72D1 <1> jb short sysexit_2 2799 <1> ; blt 1b / no, go back 2800 <1> ; mov r5,r1 / yes, r1 now has parents process # x2 2801 00003251 21F6 <1> and esi, esi ; r5=r1 2802 00003253 7430 <1> jz short sysexit_6 2803 <1> ; beq 2f / no parent has been found. 2804 <1> ; / The process just dies 2805 <1> ;shr si, 1 2806 <1> ; 17/07/2022 2807 00003255 D1EE <1> shr esi, 1 2808 <1> ; asr r1 / set up index to p.stat 2809 00003257 8A86[63620000] <1> mov al, [esi+p.stat-1] 2810 <1> ; movb p.stat-1(r1),r2 / move status of parent to r2 2811 0000325D 20C0 <1> and al, al 2812 0000325F 7424 <1> jz short sysexit_6 2813 <1> ; beq 2f / if its been freed, 2f 2814 00003261 3C03 <1> cmp al, 3 2815 <1> ; cmp r2,$3 / is parent a zombie? 2816 00003263 7420 <1> je short sysexit_6 2817 <1> ; beq 2f / yes, 2f 2818 <1> ; BH = 0 2819 00003265 8A1D[3B650000] <1> mov bl, [u.uno] 2820 <1> ; movb u.uno,r3 / move dying process's number to r3 2821 0000326B C683[63620000]03 <1> mov byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 2822 <1> ; movb $3,p.stat-1(r3) / make the process a zombie 2823 <1> ; 05/02/2014 2824 00003272 3C01 <1> cmp al, 1 ; SRUN 2825 00003274 740F <1> je short sysexit_6 2826 <1> ;cmp al, 2 2827 <1> ; cmp r2,$2 / is the parent waiting for 2828 <1> ; / this child to die 2829 <1> ;jne short sysexit_6 2830 <1> ; bne 2f / yes, notify parent not to wait any more 2831 <1> ; 05/02/2014 2832 <1> ; p.stat = 2 --> waiting 2833 <1> ; p.stat = 4 --> sleeping 2834 00003276 C686[63620000]01 <1> mov byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014 2835 <1> ;dec byte [esi+p.stat-1] 2836 <1> ; decb p.stat-1(r1) / awaken it by putting it (parent) 2837 0000327D 6689F0 <1> mov ax, si ; r1 (process number in AL) 2838 <1> ; 2839 <1> ;mov ebx, runq + 4 2840 <1> ; mov $runq+4,r2 / on the runq 2841 00003280 E8CF120000 <1> call putlu 2842 <1> ; jsr r0, putlu 2843 <1> sysexit_6: ; 2: 2844 <1> ; 31/08/2015 2845 <1> ; / the process dies 2846 00003285 C605[3B650000]00 <1> mov byte [u.uno], 0 2847 <1> ; clrb u.uno / put zero as the process number, 2848 <1> ; / so "swap" will 2849 0000328C E8F6110000 <1> call swap 2850 <1> ; jsr r0,swap / overwrite process with another process 2851 <1> hlt_sys: 2852 <1> ;sti ; 18/01/2014 2853 <1> hlts0: 2854 00003291 F4 <1> hlt 2855 00003292 EBFD <1> jmp short hlts0 2856 <1> ; 0 / and thereby kill it; halt? 2857 <1> 2858 <1> 2859 <1> syswait: ; < wait for a processs to die > 2860 <1> ; 09/02/2022 2861 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 2862 <1> ; 17/09/2015 2863 <1> ; 02/09/2015 2864 <1> ; 01/09/2015 2865 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 2866 <1> ; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1) 2867 <1> ; 2868 <1> ; 'syswait' waits for a process die. 2869 <1> ; It works in following way: 2870 <1> ; 1) From the parent process number, the parent's 2871 <1> ; process name is found. The p.ppid table of parent 2872 <1> ; names is then searched for this process name. 2873 <1> ; If a match occurs, r2 contains child's process 2874 <1> ; number. The child status is checked to see if it is 2875 <1> ; a zombie, i.e; dead but not waited for (p.stat=3) 2876 <1> ; If it is, the child process is freed and it's name 2877 <1> ; is put in (u.r0). A return is then made via 'sysret'. 2878 <1> ; If the child is not a zombie, nothing happens and 2879 <1> ; the search goes on through the p.ppid table until 2880 <1> ; all processes are checked or a zombie is found. 2881 <1> ; 2) If no zombies are found, a check is made to see if 2882 <1> ; there are any children at all. If there are none, 2883 <1> ; an error return is made. If there are, the parent's 2884 <1> ; status is set to 2 (waiting for child to die), 2885 <1> ; the parent is swapped out, and a branch to 'syswait' 2886 <1> ; is made to wait on the next process. 2887 <1> ; 2888 <1> ; Calling sequence: 2889 <1> ; ? 2890 <1> ; Arguments: 2891 <1> ; - 2892 <1> ; Inputs: - 2893 <1> ; Outputs: if zombie found, it's name put in u.r0. 2894 <1> ; ............................................................... 2895 <1> ; 2896 <1> 2897 <1> ; / wait for a process to die 2898 <1> 2899 <1> syswait_0: 2900 00003294 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 2901 <1> ; movb u.uno,r1 / put parents process number in r1 2902 0000329B D0E3 <1> shl bl, 1 2903 <1> ;shl bx, 1 2904 <1> ; asl r1 / x2 to get index into p.pid table 2905 0000329D 668B83[02620000] <1> mov ax, [ebx+p.pid-2] 2906 <1> ; mov p.pid-2(r1),r1 / get the name of this process 2907 000032A4 31F6 <1> xor esi, esi 2908 <1> ; clr r2 2909 000032A6 31C9 <1> xor ecx, ecx ; 30/10/2013 2910 <1> ;xor cl, cl 2911 <1> ; clr r3 / initialize reg 3 2912 <1> syswait_1: ; 1: 2913 <1> ; 09/02/2022 2914 000032A8 46 <1> inc esi 2915 000032A9 46 <1> inc esi 2916 <1> ;add si, 2 2917 <1> ; add $2,r2 / use r2 for index into p.ppid table 2918 <1> ; / search table of parent processes 2919 <1> ; / for this process name 2920 000032AA 663B86[22620000] <1> cmp ax, [esi+p.ppid-2] 2921 <1> ; cmp p.ppid-2(r2),r1 / r2 will contain the childs 2922 <1> ; / process number 2923 000032B1 7531 <1> jne short syswait_3 2924 <1> ;bne 3f / branch if no match of parent process name 2925 <1> ;inc cx 2926 000032B3 FEC1 <1> inc cl 2927 <1> ;inc r3 / yes, a match, r3 indicates number of children 2928 <1> ; 09/02/2022 2929 000032B5 D1EE <1> shr esi, 1 2930 <1> ;shr si, 1 2931 <1> ; asr r2 / r2/2 to get index to p.stat table 2932 <1> ; The possible states ('p.stat' values) of a process are: 2933 <1> ; 0 = free or unused 2934 <1> ; 1 = active 2935 <1> ; 2 = waiting for a child process to die 2936 <1> ; 3 = terminated, but not yet waited for (zombie). 2937 000032B7 80BE[63620000]03 <1> cmp byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014 2938 <1> ; cmpb p.stat-1(r2),$3 / is the child process a zombie? 2939 000032BE 7522 <1> jne short syswait_2 2940 <1> ; bne 2f / no, skip it 2941 000032C0 88BE[63620000] <1> mov [esi+p.stat-1], bh ; 0 2942 <1> ; clrb p.stat-1(r2) / yes, free it 2943 <1> ; 09/02/2022 2944 000032C6 D1E6 <1> shl esi, 1 2945 <1> ;shl si, 1 2946 <1> ; asl r2 / r2x2 to get index into p.pid table 2947 000032C8 0FB786[02620000] <1> movzx eax, word [esi+p.pid-2] 2948 000032CF A3[EC640000] <1> mov [u.r0], eax 2949 <1> ; mov p.pid-2(r2),*u.r0 2950 <1> ; / put childs process name in (u.r0) 2951 <1> ; 2952 <1> ; Retro UNIX 386 v1 modification ! (17/09/2015) 2953 <1> ; 2954 <1> ; Parent process ID -p.ppid- field (of the child process) 2955 <1> ; must be cleared in order to prevent infinitive 'syswait' 2956 <1> ; system call loop from the application/program if it calls 2957 <1> ; 'syswait' again (mistakenly) while there is not a zombie 2958 <1> ; or running child process to wait. ('forktest.s', 17/09/2015) 2959 <1> ; 2960 <1> ; Note: syswait will return with error if there is not a 2961 <1> ; zombie or running process to wait. 2962 <1> ; 2963 <1> ;sub ax, ax 2964 <1> ; 08/01/2022 2965 000032D4 29C0 <1> sub eax, eax 2966 000032D6 668986[22620000] <1> mov [esi+p.ppid-2], ax ; 0 ; 17/09/2015 2967 000032DD E90BFEFFFF <1> jmp sysret0 ; ax = 0 2968 <1> ; 2969 <1> ;jmp sysret 2970 <1> ; br sysret1 / return cause child is dead 2971 <1> syswait_2: ; 2: 2972 <1> ; 09/02/2022 2973 000032E2 D1E6 <1> shl esi, 1 2974 <1> ;shl si, 1 2975 <1> ; asl r2 / r2x2 to get index into p.ppid table 2976 <1> syswait_3: ; 3: 2977 000032E4 6683FE20 <1> cmp si, nproc+nproc 2978 <1> ; cmp r2,$nproc+nproc / have all processes been checked? 2979 000032E8 72BE <1> jb short syswait_1 2980 <1> ; blt 1b / no, continue search 2981 <1> ;and cx, cx 2982 000032EA 20C9 <1> and cl, cl 2983 <1> ; tst r3 / one gets here if there are no children 2984 <1> ; / or children that are still active 2985 <1> ; 30/10/2013 2986 000032EC 7515 <1> jnz short syswait_4 2987 <1> ;jz error 2988 <1> ; beq error1 / there are no children, error 2989 000032EE 890D[EC640000] <1> mov [u.r0], ecx ; 0 2990 <1> ; 09/02/2022 2991 000032F4 C705[41650000]1B00- <1> mov dword [u.error], ERR_MISC ; 27 2991 000032FC 0000 <1> 2992 <1> ; miscellaneous/other errors 2993 000032FE E9C8FDFFFF <1> jmp error 2994 <1> syswait_4: 2995 00003303 8A1D[3B650000] <1> mov bl, [u.uno] 2996 <1> ; movb u.uno,r1 / there are children so put 2997 <1> ; / parent process number in r1 2998 00003309 FE83[63620000] <1> inc byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014 2999 <1> ; incb p.stat-1(r1) / it is waiting for 3000 <1> ; / other children to die 3001 <1> ; 04/11/2013 3002 0000330F E873110000 <1> call swap 3003 <1> ; jsr r0,swap / swap it out, because it's waiting 3004 00003314 E97BFFFFFF <1> jmp syswait_0 3005 <1> ; br syswait / wait on next process 3006 <1> 3007 <1> sysfork: ; < create a new process > 3008 <1> ; 26/02/2022 3009 <1> ; 25/02/2022 3010 <1> ; 08/01/2022 (Retro UNIX 386 v1.1) 3011 <1> ; 18/09/2015 3012 <1> ; 04/09/2015 3013 <1> ; 02/09/2015 3014 <1> ; 01/09/2015 3015 <1> ; 28/08/2015 3016 <1> ; 14/05/2015 3017 <1> ; 10/05/2015 3018 <1> ; 09/05/2015 3019 <1> ; 06/05/2015 (Retro UNIX 386 v1 - Beginning) 3020 <1> ; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1) 3021 <1> ; 3022 <1> ; 'sysfork' creates a new process. This process is referred 3023 <1> ; to as the child process. This new process core image is 3024 <1> ; a copy of that of the caller of 'sysfork'. The only 3025 <1> ; distinction is the return location and the fact that (u.r0) 3026 <1> ; in the old process (parent) contains the process id (p.pid) 3027 <1> ; of the new process (child). This id is used by 'syswait'. 3028 <1> ; 'sysfork' works in the following manner: 3029 <1> ; 1) The process status table (p.stat) is searched to find 3030 <1> ; a process number that is unused. If none are found 3031 <1> ; an error occurs. 3032 <1> ; 2) when one is found, it becomes the child process number 3033 <1> ; and it's status (p.stat) is set to active. 3034 <1> ; 3) If the parent had a control tty, the interrupt 3035 <1> ; character in that tty buffer is cleared. 3036 <1> ; 4) The child process is put on the lowest priority run 3037 <1> ; queue via 'putlu'. 3038 <1> ; 5) A new process name is gotten from 'mpid' (actually 3039 <1> ; it is a unique number) and is put in the child's unique 3040 <1> ; identifier; process id (p.pid). 3041 <1> ; 6) The process name of the parent is then obtained and 3042 <1> ; placed in the unique identifier of the parent process 3043 <1> ; name is then put in 'u.r0'. 3044 <1> ; 7) The child process is then written out on disk by 3045 <1> ; 'wswap',i.e., the parent process is copied onto disk 3046 <1> ; and the child is born. (The child process is written 3047 <1> ; out on disk/drum with 'u.uno' being the child process 3048 <1> ; number.) 3049 <1> ; 8) The parent process number is then restored to 'u.uno'. 3050 <1> ; 9) The child process name is put in 'u.r0'. 3051 <1> ; 10) The pc on the stack sp + 18 is incremented by 2 to 3052 <1> ; create the return address for the parent process. 3053 <1> ; 11) The 'u.fp' list as then searched to see what files 3054 <1> ; the parent has opened. For each file the parent has 3055 <1> ; opened, the corresponding 'fsp' entry must be updated 3056 <1> ; to indicate that the child process also has opened 3057 <1> ; the file. A branch to 'sysret' is then made. 3058 <1> ; 3059 <1> ; Calling sequence: 3060 <1> ; from shell ? 3061 <1> ; Arguments: 3062 <1> ; - 3063 <1> ; Inputs: - 3064 <1> ; Outputs: *u.r0 - child process name 3065 <1> ; ............................................................... 3066 <1> ; 3067 <1> ; Retro UNIX 8086 v1 modification: 3068 <1> ; AX = r0 = PID (>0) (at the return of 'sysfork') 3069 <1> ; = process id of child a parent process returns 3070 <1> ; = process id of parent when a child process returns 3071 <1> ; 3072 <1> ; In original UNIX v1, sysfork is called and returns as 3073 <1> ; in following manner: (with an example: c library, fork) 3074 <1> ; 3075 <1> ; 1: 3076 <1> ; sys fork 3077 <1> ; br 1f / child process returns here 3078 <1> ; bes 2f / parent process returns here 3079 <1> ; / pid of new process in r0 3080 <1> ; rts pc 3081 <1> ; 2: / parent process condionally branches here 3082 <1> ; mov $-1,r0 / pid = -1 means error return 3083 <1> ; rts pc 3084 <1> ; 3085 <1> ; 1: / child process brances here 3086 <1> ; clr r0 / pid = 0 in child process 3087 <1> ; rts pc 3088 <1> ; 3089 <1> ; In UNIX v7x86 (386) by Robert Nordier (1999) 3090 <1> ; // pid = fork(); 3091 <1> ; // 3092 <1> ; // pid == 0 in child process; 3093 <1> ; // pid == -1 means error return 3094 <1> ; // in child, 3095 <1> ; // parents id is in par_uid if needed 3096 <1> ; 3097 <1> ; _fork: 3098 <1> ; mov $.fork,eax 3099 <1> ; int $0x30 3100 <1> ; jmp 1f 3101 <1> ; jnc 2f 3102 <1> ; jmp cerror 3103 <1> ; 1: 3104 <1> ; mov eax,_par_uid 3105 <1> ; xor eax,eax 3106 <1> ; 2: 3107 <1> ; ret 3108 <1> ; 3109 <1> ; In Retro UNIX 8086 v1, 3110 <1> ; 'sysfork' returns in following manner: 3111 <1> ; 3112 <1> ; mov ax, sys_fork 3113 <1> ; mov bx, offset @f ; routine for child 3114 <1> ; int 20h 3115 <1> ; jc error 3116 <1> ; 3117 <1> ; ; Routine for parent process here (just after 'jc') 3118 <1> ; mov word ptr [pid_of_child], ax 3119 <1> ; jmp next_routine_for_parent 3120 <1> ; 3121 <1> ; @@: ; routine for child process here 3122 <1> ; .... 3123 <1> ; NOTE: 'sysfork' returns to specified offset 3124 <1> ; for child process by using BX input. 3125 <1> ; (at first, parent process will return then 3126 <1> ; child process will return -after swapped in- 3127 <1> ; 'syswait' is needed in parent process 3128 <1> ; if return from child process will be waited for.) 3129 <1> ; 3130 <1> 3131 <1> ; / create a new process 3132 <1> ; EBX = return address for child process 3133 <1> ; (Retro UNIX 8086 v1 modification !) 3134 00003319 31F6 <1> xor esi, esi 3135 <1> ; clr r1 3136 <1> sysfork_1: ; 1: / search p.stat table for unused process number 3137 0000331B 46 <1> inc esi 3138 <1> ; inc r1 3139 0000331C 80BE[63620000]00 <1> cmp byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014 3140 <1> ; tstb p.stat-1(r1) / is process active, unused, dead 3141 00003323 760B <1> jna short sysfork_2 3142 <1> ; beq 1f / it's unused so branch 3143 00003325 6683FE10 <1> cmp si, nproc 3144 <1> ; cmp r1,$nproc / all processes checked 3145 00003329 72F0 <1> jb short sysfork_1 3146 <1> ; blt 1b / no, branch back 3147 <1> ; 3148 <1> ; Retro UNIX 8086 v1. modification: 3149 <1> ; Parent process returns from 'sysfork' to address 3150 <1> ; which is just after 'sysfork' system call in parent 3151 <1> ; process. Child process returns to address which is put 3152 <1> ; in BX register by parent process for 'sysfork'. 3153 <1> ; 3154 <1> ;add $2,18.(sp) / add 2 to pc when trap occured, points 3155 <1> ; / to old process return 3156 <1> ; br error1 / no room for a new process 3157 <1> sysfork_0: 3158 0000332B E99BFDFFFF <1> jmp error 3159 <1> sysfork_2: ; 1: 3160 00003330 E88CF0FFFF <1> call allocate_page 3161 <1> ;jc error 3162 <1> ; 08/01/2022 3163 00003335 72F4 <1> jc short sysfork_0 3164 <1> 3165 00003337 50 <1> push eax ; UPAGE (user structure page) address 3166 <1> ; Retro UNIX 386 v1 modification! 3167 00003338 E87BF2FFFF <1> call duplicate_page_dir 3168 <1> ; EAX = New page directory 3169 0000333D 7308 <1> jnc short sysfork_3 3170 0000333F 58 <1> pop eax ; UPAGE (user structure page) address 3171 00003340 E842F2FFFF <1> call deallocate_page 3172 <1> ;jmp error 3173 <1> ; 08/01/2022 3174 00003345 EBE4 <1> jmp short sysfork_0 ; error 3175 <1> sysfork_3: 3176 <1> ; Retro UNIX 386 v1 modification ! 3177 00003347 56 <1> push esi 3178 00003348 E8B1110000 <1> call wswap ; save current user (u) structure, user registers 3179 <1> ; and interrupt return components (for IRET) 3180 0000334D 8705[45650000] <1> xchg eax, [u.pgdir] ; page directory of the child process 3181 00003353 A3[49650000] <1> mov [u.ppgdir], eax ; page directory of the parent process 3182 00003358 5E <1> pop esi 3183 00003359 58 <1> pop eax ; UPAGE (user structure page) address 3184 <1> ; [u.usp] = esp 3185 0000335A 89F7 <1> mov edi, esi 3186 <1> ;shl di, 2 3187 <1> ; 08/01/2022 3188 0000335C C1E702 <1> shl edi, 2 3189 0000335F 8987[70620000] <1> mov [edi+p.upage-4], eax ; memory page for 'user' struct 3190 00003365 A3[3C650000] <1> mov [u.upage], eax ; memory page for 'user' struct (child) 3191 <1> ; 28/08/2015 3192 0000336A 0FB605[3B650000] <1> movzx eax, byte [u.uno] ; parent process number 3193 <1> ; movb u.uno,-(sp) / save parent process number 3194 00003371 89C7 <1> mov edi, eax 3195 00003373 50 <1> push eax ; ** 3196 00003374 8A87[43620000] <1> mov al, [edi+p.ttyc-1] ; console tty (parent) 3197 <1> ; 18/09/2015 3198 0000337A 8886[43620000] <1> mov [esi+p.ttyc-1], al ; set child's console tty 3199 <1> ; 26/02/2022 (p.waitc is not used) 3200 <1> ;mov [esi+p.waitc-1], ah ; 0 ; reset child's wait channel 3201 <1> ; 25/02/2022 (BugFix) 3202 <1> ;mov [esi+p.ttyc-1], ax ; al - set child's console tty 3203 <1> ; ; ah - reset child's wait channel 3204 00003380 89F0 <1> mov eax, esi 3205 00003382 A2[3B650000] <1> mov [u.uno], al ; child process number 3206 <1> ;movb r1,u.uno / set child process number to r1 3207 00003387 FE86[63620000] <1> inc byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014 3208 <1> ; incb p.stat-1(r1) / set p.stat entry for child 3209 <1> ; / process to active status 3210 <1> ; mov u.ttyp,r2 / put pointer to parent process' 3211 <1> ; / control tty buffer in r2 3212 <1> ; beq 2f / branch, if no such tty assigned 3213 <1> ; clrb 6(r2) / clear interrupt character in tty buffer 3214 <1> ; 2: 3215 0000338D 53 <1> push ebx ; * return address for the child process 3216 <1> ; * Retro UNIX 8086 v1 feature only ! 3217 <1> ; (Retro UNIX 8086 v1 modification!) 3218 <1> ; mov $runq+4,r2 3219 0000338E E8C1110000 <1> call putlu 3220 <1> ; jsr r0,putlu / put child process on lowest priority 3221 <1> ; / run queue 3222 <1> ; 08/01/2022 3223 00003393 D1E6 <1> shl esi, 1 3224 <1> ;shl si, 1 3225 <1> ; asl r1 / multiply r1 by 2 to get index 3226 <1> ; / into p.pid table 3227 00003395 66FF05[DA640000] <1> inc word [mpid] 3228 <1> ; inc mpid / increment m.pid; get a new process name 3229 0000339C 66A1[DA640000] <1> mov ax, [mpid] 3230 000033A2 668986[02620000] <1> mov [esi+p.pid-2], ax 3231 <1> ;mov mpid,p.pid-2(r1) / put new process name 3232 <1> ; / in child process' name slot 3233 000033A9 5A <1> pop edx ; * return address for the child process 3234 <1> ; * Retro UNIX 8086 v1 feature only ! 3235 000033AA 5B <1> pop ebx ; ** 3236 <1> ;mov ebx, [esp] ; ** parent process number 3237 <1> ; movb (sp),r2 / put parent process number in r2 3238 <1> ; 08/01/2022 3239 000033AB D1E3 <1> shl ebx, 1 3240 <1> ;shl bx, 1 3241 <1> ; asl r2 / multiply by 2 to get index into below tables 3242 <1> ;movzx eax, word [ebx+p.pid-2] 3243 000033AD 668B83[02620000] <1> mov ax, [ebx+p.pid-2] 3244 <1> ; mov p.pid-2(r2),r2 / get process name of parent 3245 <1> ; / process 3246 000033B4 668986[22620000] <1> mov [esi+p.ppid-2], ax 3247 <1> ; mov r2,p.ppid-2(r1) / put parent process name 3248 <1> ; / in parent process slot for child 3249 000033BB A3[EC640000] <1> mov [u.r0], eax 3250 <1> ; mov r2,*u.r0 / put parent process name on stack 3251 <1> ; / at location where r0 was saved 3252 000033C0 8B2D[E4640000] <1> mov ebp, [u.sp] ; points to return address (EIP for IRET) 3253 000033C6 895500 <1> mov [ebp], edx ; *, CS:EIP -> EIP 3254 <1> ; * return address for the child process 3255 <1> ; mov $sysret1,-(sp) / 3256 <1> ; mov sp,u.usp / contents of sp at the time when 3257 <1> ; / user is swapped out 3258 <1> ; mov $sstack,sp / point sp to swapping stack space 3259 <1> ; 04/09/2015 - 01/09/2015 3260 <1> ; [u.usp] = esp 3261 000033C9 68[EB300000] <1> push sysret ; *** 3262 000033CE 8925[E8640000] <1> mov [u.usp], esp ; points to 'sysret' address (***) 3263 <1> ; (for child process) 3264 000033D4 31C0 <1> xor eax, eax 3265 000033D6 66A3[1C650000] <1> mov [u.ttyp], ax ; 0 3266 <1> ; 3267 000033DC E81D110000 <1> call wswap ; Retro UNIX 8086 v1 modification ! 3268 <1> ;jsr r0,wswap / put child process out on drum 3269 <1> ;jsr r0,unpack / unpack user stack 3270 <1> ;mov u.usp,sp / restore user stack pointer 3271 <1> ; tst (sp)+ / bump stack pointer 3272 <1> ; Retro UNIX 386 v1 modification ! 3273 000033E1 58 <1> pop eax ; *** 3274 <1> ; 08/01/2022 3275 000033E2 D1E3 <1> shl ebx, 1 3276 <1> ;shl bx, 1 3277 000033E4 8B83[70620000] <1> mov eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015 3278 000033EA E838110000 <1> call rswap ; restore parent process 'u' structure, 3279 <1> ; registers and return address (for IRET) 3280 <1> ;movb (sp)+,u.uno / put parent process number in u.uno 3281 000033EF 0FB705[DA640000] <1> movzx eax, word [mpid] 3282 000033F6 A3[EC640000] <1> mov [u.r0], eax 3283 <1> ; mov mpid,*u.r0 / put child process name on stack 3284 <1> ; / where r0 was saved 3285 <1> ; add $2,18.(sp) / add 2 to pc on stack; gives parent 3286 <1> ; / process return 3287 <1> ;xor ebx, ebx 3288 000033FB 31F6 <1> xor esi, esi 3289 <1> ;clr r1 3290 <1> sysfork_4: ; 1: / search u.fp list to find the files 3291 <1> ; / opened by the parent process 3292 <1> ; 01/09/2015 3293 <1> ;xor bh, bh 3294 <1> ;mov bl, [esi+u.fp] 3295 000033FD 8A86[F2640000] <1> mov al, [esi+u.fp] 3296 <1> ; movb u.fp(r1),r2 / get an open file for this process 3297 <1> ;or bl, bl 3298 00003403 08C0 <1> or al, al 3299 00003405 740C <1> jz short sysfork_5 3300 <1> ; beq 2f / file has not been opened by parent, 3301 <1> ; / so branch 3302 00003407 B40A <1> mov ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes 3303 00003409 F6E4 <1> mul ah 3304 <1> ;;movzx ebx, ax 3305 <1> ;mov bx, ax 3306 0000340B 89C3 <1> mov ebx, eax ; 08/01/2022 3307 <1> ;shl bx, 3 3308 <1> ; asl r2 / multiply by 8 3309 <1> ; asl r2 / to get index into fsp table 3310 <1> ; asl r2 3311 0000340D FE83[B2620000] <1> inc byte [ebx+fsp-2] 3312 <1> ; incb fsp-2(r2) / increment number of processes 3313 <1> ; / using file, because child will now be 3314 <1> ; / using this file 3315 <1> sysfork_5: ; 2: 3316 00003413 46 <1> inc esi 3317 <1> ; inc r1 / get next open file 3318 00003414 6683FE0A <1> cmp si, 10 3319 <1> ; cmp r1,$10. / 10. files is the maximum number which 3320 <1> ; / can be opened 3321 00003418 72E3 <1> jb short sysfork_4 3322 <1> ; blt 1b / check next entry 3323 0000341A E9CCFCFFFF <1> jmp sysret 3324 <1> ; br sysret1 3325 <1> 3326 <1> sysread: ; < read from file > 3327 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3328 <1> ; 13/05/2015 3329 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3330 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 3331 <1> ; 3332 <1> ; 'sysread' is given a buffer to read into and the number of 3333 <1> ; characters to be read. If finds the file from the file 3334 <1> ; descriptor located in *u.r0 (r0). This file descriptor 3335 <1> ; is returned from a successful open call (sysopen). 3336 <1> ; The i-number of file is obtained via 'rw1' and the data 3337 <1> ; is read into core via 'readi'. 3338 <1> ; 3339 <1> ; Calling sequence: 3340 <1> ; sysread; buffer; nchars 3341 <1> ; Arguments: 3342 <1> ; buffer - location of contiguous bytes where 3343 <1> ; input will be placed. 3344 <1> ; nchars - number of bytes or characters to be read. 3345 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 3346 <1> ; Outputs: *u.r0 - number of bytes read. 3347 <1> ; ............................................................... 3348 <1> ; 3349 <1> ; Retro UNIX 8086 v1 modification: 3350 <1> ; 'sysread' system call has three arguments; so, 3351 <1> ; * 1st argument, file descriptor is in BX register 3352 <1> ; * 2nd argument, buffer address/offset in CX register 3353 <1> ; * 3rd argument, number of bytes is in DX register 3354 <1> ; 3355 <1> ; AX register (will be restored via 'u.r0') will return 3356 <1> ; to the user with number of bytes read. 3357 <1> ; 3358 0000341F E840000000 <1> call rw1 3359 <1> ;jc error ; 13/05/2015, ax < 1 3360 <1> ; ; jsr r0,rw1 / get i-number of file to be read into r1 3361 <1> ; 24/12/2021 3362 00003424 7239 <1> jc short sysread_err 3363 00003426 F6C480 <1> test ah, 80h 3364 <1> ; tst r1 / negative i-number? 3365 00003429 752A <1> jnz short rw3 ; 24/12/2021 3366 <1> ;jnz error 3367 <1> ; ble error1 / yes, error 1 to read 3368 <1> ; / it should be positive 3369 0000342B E88B150000 <1> call readi 3370 <1> ; jsr r0,readi / read data into core 3371 00003430 EB14 <1> jmp short rw0 3372 <1> ; br 1f 3373 <1> 3374 <1> syswrite: ; < write to file > 3375 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3376 <1> ; 13/05/2015 3377 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3378 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 3379 <1> ; 3380 <1> ; 'syswrite' is given a buffer to write onto an output file 3381 <1> ; and the number of characters to write. If finds the file 3382 <1> ; from the file descriptor located in *u.r0 (r0). This file 3383 <1> ; descriptor is returned from a successful open or create call 3384 <1> ; (sysopen or syscreat). The i-number of file is obtained via 3385 <1> ; 'rw1' and buffer is written on the output file via 'write'. 3386 <1> ; 3387 <1> ; Calling sequence: 3388 <1> ; syswrite; buffer; nchars 3389 <1> ; Arguments: 3390 <1> ; buffer - location of contiguous bytes to be writtten. 3391 <1> ; nchars - number of characters to be written. 3392 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 3393 <1> ; Outputs: *u.r0 - number of bytes written. 3394 <1> ; ............................................................... 3395 <1> ; 3396 <1> ; Retro UNIX 8086 v1 modification: 3397 <1> ; 'syswrite' system call has three arguments; so, 3398 <1> ; * 1st argument, file descriptor is in BX register 3399 <1> ; * 2nd argument, buffer address/offset in CX register 3400 <1> ; * 3rd argument, number of bytes is in DX register 3401 <1> ; 3402 <1> ; AX register (will be restored via 'u.r0') will return 3403 <1> ; to the user with number of bytes written. 3404 <1> ; 3405 00003432 E82D000000 <1> call rw1 3406 <1> ;jc error ; 13/05/2015, ax < 1 3407 <1> ; ; jsr r0,rw1 / get i-number in r1 of file to write 3408 <1> ; 24/12/2021 3409 00003437 7226 <1> jc short syswrite_err 3410 00003439 F6C480 <1> test ah, 80h 3411 <1> ; tst r1 / positive i-number ? 3412 0000343C 7417 <1> jz short rw3 ; 13/05/2015 3413 <1> ;jz error 3414 <1> ; bge error1 / yes, error 1 3415 <1> ; / negative i-number means write 3416 0000343E 66F7D8 <1> neg ax 3417 <1> ; neg r1 / make it positive 3418 00003441 E867170000 <1> call writei 3419 <1> ; jsr r0,writei / write data 3420 <1> rw0: ; 1: 3421 00003446 A1[14650000] <1> mov eax, [u.nread] 3422 0000344B A3[EC640000] <1> mov [u.r0], eax 3423 <1> ; mov u.nread,*u.r0 / put no. of bytes transferred 3424 <1> ; / into (u.r0) 3425 00003450 E996FCFFFF <1> jmp sysret 3426 <1> ; br sysret1 3427 <1> 3428 <1> rw3: 3429 <1> ; 13/05/2015 3430 00003455 C705[41650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 3430 0000345D 0000 <1> 3431 <1> ;stc 3432 <1> ;retn 3433 <1> ; 24/12/2021 (BugFix) 3434 <1> sysread_err: 3435 <1> syswrite_err: 3436 0000345F E967FCFFFF <1> jmp error 3437 <1> 3438 <1> rw1: 3439 <1> ; 14/05/2015 3440 <1> ; 13/05/2015 3441 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3442 <1> ; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1) 3443 <1> ; System call registers: bx, cx, dx (through 'sysenter') 3444 <1> ; 3445 <1> ;mov [u.base], ecx ; buffer address/offset 3446 <1> ;(in the user's virtual memory space) 3447 <1> ;mov [u.count], edx 3448 <1> ; jsr r0,arg; u.base / get buffer pointer 3449 <1> ; jsr r0,arg; u.count / get no. of characters 3450 <1> ;;mov eax, ebx ; file descriptor 3451 <1> ; mov *u.r0,r1 / put file descriptor 3452 <1> ; / (index to u.fp table) in r1 3453 <1> ; 13/05/2015 3454 00003464 C705[EC640000]0000- <1> mov dword [u.r0], 0 ; r/w transfer count = 0 (reset) 3454 0000346C 0000 <1> 3455 <1> ; 3456 <1> ;; call getf 3457 <1> ; eBX = File descriptor 3458 0000346E E8330B0000 <1> call getf1 ; calling point in 'getf' from 'rw1' 3459 <1> ; jsr r0,getf / get i-number of the file in r1 3460 <1> ; AX = I-number of the file ; negative i-number means write 3461 <1> ; 13/05/2015 3462 00003473 6683F801 <1> cmp ax, 1 3463 00003477 7217 <1> jb short rw2 3464 <1> ; 3465 00003479 890D[0C650000] <1> mov [u.base], ecx ; buffer address/offset 3466 <1> ;(in the user's virtual memory space) 3467 0000347F 8915[10650000] <1> mov [u.count], edx 3468 <1> ; 14/05/2015 3469 00003485 C705[41650000]0000- <1> mov dword [u.error], 0 ; reset the last error code 3469 0000348D 0000 <1> 3470 0000348F C3 <1> retn 3471 <1> ; rts r0 3472 <1> rw2: 3473 <1> ; 13/05/2015 3474 00003490 C705[41650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 3474 00003498 0000 <1> 3475 0000349A C3 <1> retn 3476 <1> 3477 <1> sysopen: ; 3478 <1> ; 09/01/2022 3479 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3480 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3481 <1> ; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1) 3482 <1> ; 3483 <1> ; 'sysopen' opens a file in following manner: 3484 <1> ; 1) The second argument in a sysopen says whether to 3485 <1> ; open the file ro read (0) or write (>0). 3486 <1> ; 2) I-node of the particular file is obtained via 'namei'. 3487 <1> ; 3) The file is opened by 'iopen'. 3488 <1> ; 4) Next housekeeping is performed on the fsp table 3489 <1> ; and the user's open file list - u.fp. 3490 <1> ; a) u.fp and fsp are scanned for the next available slot. 3491 <1> ; b) An entry for the file is created in the fsp table. 3492 <1> ; c) The number of this entry is put on u.fp list. 3493 <1> ; d) The file descriptor index to u.fp list is pointed 3494 <1> ; to by u.r0. 3495 <1> ; 3496 <1> ; Calling sequence: 3497 <1> ; sysopen; name; mode 3498 <1> ; Arguments: 3499 <1> ; name - file name or path name 3500 <1> ; mode - 0 to open for reading 3501 <1> ; 1 to open for writing 3502 <1> ; Inputs: (arguments) 3503 <1> ; Outputs: *u.r0 - index to u.fp list (the file descriptor) 3504 <1> ; is put into r0's location on the stack. 3505 <1> ; ............................................................... 3506 <1> ; 3507 <1> ; Retro UNIX 8086 v1 modification: 3508 <1> ; 'sysopen' system call has two arguments; so, 3509 <1> ; * 1st argument, name is pointed to by BX register 3510 <1> ; * 2nd argument, mode is in CX register 3511 <1> ; 3512 <1> ; AX register (will be restored via 'u.r0') will return 3513 <1> ; to the user with the file descriptor/number 3514 <1> ; (index to u.fp list). 3515 <1> ; 3516 <1> ;call arg2 3517 <1> ; * name - 'u.namep' points to address of file/path name 3518 <1> ; in the user's program segment ('u.segmnt') 3519 <1> ; with offset in BX register (as sysopen argument 1). 3520 <1> ; * mode - sysopen argument 2 is in CX register 3521 <1> ; which is on top of stack. 3522 <1> ; 3523 <1> ; jsr r0,arg2 / get sys args into u.namep and on stack 3524 <1> ; 3525 <1> ; system call registers: ebx, ecx (through 'sysenter') 3526 <1> 3527 0000349B 891D[04650000] <1> mov [u.namep], ebx 3528 <1> ; 24/12/2021 (cx -> ecx) 3529 000034A1 51 <1> push ecx ; * 3530 000034A2 E8300B0000 <1> call namei 3531 <1> ; jsr r0,namei / i-number of file in r1 3532 <1> ;and ax, ax 3533 <1> ;jz error ; File not found 3534 000034A7 7239 <1> jc short fnotfound ; 14/05/2015 3535 <1> ;jc error ; 27/05/2013 3536 <1> ; br error2 / file not found 3537 <1> ; 24/12/2021 3538 <1> ;pop edx ; * ; mode 3539 <1> ;push edx ; * 3540 000034A9 8B1424 <1> mov edx, [esp] ; * 3541 <1> ; edx = open mode (0 or 1) 3542 <1> ;or dx, dx 3543 000034AC 08D2 <1> or dl, dl 3544 <1> ; tst (sp) / is mode = 0 (2nd arg of call; 3545 <1> ; / 0 means, open for read) 3546 000034AE 7403 <1> jz short sysopen_0 3547 <1> ; beq 1f / yes, leave i-number positive 3548 <1> syscreat_0: ; 27/12/2015 3549 000034B0 66F7D8 <1> neg ax 3550 <1> ; neg r1 / open for writing so make i-number negative 3551 <1> sysopen_0: ;1: 3552 000034B3 E8931B0000 <1> call iopen 3553 <1> ;jsr r0,iopen / open file whose i-number is in r1 3554 000034B8 5A <1> pop edx ; * ; mode ; 24/12/2021 3555 <1> ;and dx, dx 3556 000034B9 20D2 <1> and dl, dl 3557 <1> ; tst (sp)+ / pop the stack and test the mode 3558 000034BB 7403 <1> jz short sysopen_2 3559 <1> ; beq op1 / is open for read op1 3560 <1> sysopen_1: ;op0: 3561 000034BD 66F7D8 <1> neg ax 3562 <1> ; neg r1 3563 <1> ;; NOTE: iopen always make i-number positive. 3564 <1> ;; Here i-number becomes negative again. [22/05/2013] 3565 <1> sysopen_2: ;op1: 3566 000034C0 31F6 <1> xor esi, esi 3567 <1> ; clr r2 / clear registers 3568 000034C2 31DB <1> xor ebx, ebx 3569 <1> ; clr r3 3570 <1> sysopen_3: ;1: / scan the list of entries in fsp table 3571 000034C4 389E[F2640000] <1> cmp [esi+u.fp], bl ; 0 3572 <1> ; tstb u.fp(r2) / test the entry in the u.fp list 3573 000034CA 7625 <1> jna short sysopen_4 3574 <1> ; beq 1f / if byte in list is 0 branch 3575 000034CC 46 <1> inc esi 3576 <1> ; inc r2 / bump r2 so next byte can be checked 3577 000034CD 6683FE0A <1> cmp si, 10 ; OPENFILES 3578 <1> ; cmp r2,$10. / reached end of list? 3579 000034D1 72F1 <1> jb short sysopen_3 3580 <1> ; blt 1b / no, go back 3581 <1> toomanyf: 3582 <1> ; 14/05/2015 3583 000034D3 C705[41650000]0D00- <1> mov dword [u.error], ERR_TOO_MANY_FILES ; too many open files ! 3583 000034DB 0000 <1> 3584 000034DD E9E9FBFFFF <1> jmp error 3585 <1> ; br error2 / yes, error (no files open) 3586 <1> fnotfound: 3587 <1> ; 14/05/2015 3588 000034E2 C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; file not found ! 3588 000034EA 0000 <1> 3589 000034EC E9DAFBFFFF <1> jmp error 3590 <1> 3591 <1> sysopen_4: ; 1: 3592 000034F1 6683BB[B4620000]00 <1> cmp word [ebx+fsp], 0 3593 <1> ; tst fsp(r3) / scan fsp entries 3594 000034F9 760D <1> jna short sysopen_5 3595 <1> ; beq 1f / if 0 branch 3596 <1> ; 14/05/2015 - Retro UNIX 386 v1 modification ! 3597 000034FB 6683C30A <1> add bx, 10 ; fsp structure size = 10 bytes/entry 3598 <1> ; add $8.,r3 / add 8 to r3 3599 <1> ; / to bump it to next entry mfsp table 3600 000034FF 6681FBF401 <1> cmp bx, nfiles*10 3601 <1> ; cmp r3,$[nfiles*8.] / done scanning 3602 00003504 72EB <1> jb short sysopen_4 3603 <1> ; blt 1b / no, back 3604 <1> ;jmp error 3605 <1> ; ; br error2 / yes, error 3606 <1> ; 24/12/2021 3607 00003506 EBCB <1> jmp short toomanyf 3608 <1> 3609 <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table 3610 00003508 668983[B4620000] <1> mov [ebx+fsp], ax 3611 <1> ; mov r1,fsp(r3) / put i-number of open file 3612 <1> ; / into next available entry in fsp table, 3613 <1> ; 09/01/2022 3614 <1> ;mov di, [cdev] ; word ? byte ? 3615 <1> ;mov [ebx+fsp+2], di ; device number 3616 <1> ; mov cdev,fsp+2(r3) / put # of device in next word 3617 <1> ;xor edi, edi 3618 <1> ;mov [ebx+fsp+4], edi ; offset pointer (0) 3619 <1> ; ; clr fsp+4(r3) 3620 <1> ;mov [ebx+fsp+8], di ; open count (0), deleted flag (0) 3621 <1> ; ; clr fsp+6(r3) / clear the next two words 3622 0000350F 31C0 <1> xor eax, eax 3623 00003511 8983[B8620000] <1> mov [ebx+fsp+4], eax ; offset pointer (0) 3624 00003517 668983[BC620000] <1> mov [ebx+fsp+8], ax ; open count (0), deleted flag (0) 3625 <1> 3626 0000351E A0[D3640000] <1> mov al, [cdev] 3627 00003523 668983[B6620000] <1> mov [ebx+fsp+2], ax ; device number 3628 <1> 3629 0000352A 89D8 <1> mov eax, ebx 3630 0000352C B30A <1> mov bl, 10 3631 0000352E F6F3 <1> div bl 3632 <1> ; asr r3 3633 <1> ; asr r3 / divide by 8 3634 <1> ; asr r3 ; / to get number of the fsp entry-1 3635 00003530 FEC0 <1> inc al 3636 <1> ; inc r3 / add 1 to get fsp entry number 3637 00003532 8886[F2640000] <1> mov [esi+u.fp], al 3638 <1> ; movb r3,u.fp(r2) / move entry number into 3639 <1> ; / next available slot in u.fp list 3640 00003538 8935[EC640000] <1> mov [u.r0], esi 3641 <1> ; mov r2,*u.r0 / move index to u.fp list 3642 <1> ; / into r0 loc on stack 3643 0000353E E9A8FBFFFF <1> jmp sysret 3644 <1> ; br sysret2 3645 <1> 3646 <1> ; 3647 <1> ; 'fsp' table (10 bytes/entry) 3648 <1> ; bit 15 bit 0 3649 <1> ; ---|------------------------------------------- 3650 <1> ; r/w| i-number of open file 3651 <1> ; ---|------------------------------------------- 3652 <1> ; device number 3653 <1> ; ----------------------------------------------- 3654 <1> ; offset pointer, r/w pointer to file (bit 0-15) 3655 <1> ; ----------------------------------------------- 3656 <1> ; offset pointer, r/w pointer to file (bit 16-31) 3657 <1> ; ----------------------|------------------------ 3658 <1> ; flag that says file | number of processes 3659 <1> ; has been deleted | that have file open 3660 <1> ; ----------------------|------------------------ 3661 <1> ; 3662 <1> 3663 <1> syscreat: ; < create file > 3664 <1> ; 24/12/2021 3665 <1> ; 27/12/2015 (Retro UNIX 386 v1.1) 3666 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3667 <1> ; 27/05/2013 (Retro UNIX 8086 v1) 3668 <1> ; 3669 <1> ; 'syscreat' called with two arguments; name and mode. 3670 <1> ; u.namep points to name of the file and mode is put 3671 <1> ; on the stack. 'namei' is called to get i-number of the file. 3672 <1> ; If the file aready exists, it's mode and owner remain 3673 <1> ; unchanged, but it is truncated to zero length. If the file 3674 <1> ; did not exist, an i-node is created with the new mode via 3675 <1> ; 'maknod' whether or not the file already existed, it is 3676 <1> ; open for writing. The fsp table is then searched for a free 3677 <1> ; entry. When a free entry is found, proper data is placed 3678 <1> ; in it and the number of this entry is put in the u.fp list. 3679 <1> ; The index to the u.fp (also know as the file descriptor) 3680 <1> ; is put in the user's r0. 3681 <1> ; 3682 <1> ; Calling sequence: 3683 <1> ; syscreate; name; mode 3684 <1> ; Arguments: 3685 <1> ; name - name of the file to be created 3686 <1> ; mode - mode of the file to be created 3687 <1> ; Inputs: (arguments) 3688 <1> ; Outputs: *u.r0 - index to u.fp list 3689 <1> ; (the file descriptor of new file) 3690 <1> ; ............................................................... 3691 <1> ; 3692 <1> ; Retro UNIX 8086 v1 modification: 3693 <1> ; 'syscreate' system call has two arguments; so, 3694 <1> ; * 1st argument, name is pointed to by BX register 3695 <1> ; * 2nd argument, mode is in CX register 3696 <1> ; 3697 <1> ; AX register (will be restored via 'u.r0') will return 3698 <1> ; to the user with the file descriptor/number 3699 <1> ; (index to u.fp list). 3700 <1> ; 3701 <1> ;call arg2 3702 <1> ; * name - 'u.namep' points to address of file/path name 3703 <1> ; in the user's program segment ('u.segmnt') 3704 <1> ; with offset in BX register (as sysopen argument 1). 3705 <1> ; * mode - sysopen argument 2 is in CX register 3706 <1> ; which is on top of stack. 3707 <1> ; 3708 <1> ; jsr r0,arg2 / put file name in u.namep put mode 3709 <1> ; / on stack 3710 00003543 891D[04650000] <1> mov [u.namep], ebx ; file name address 3711 <1> ;push cx ; mode 3712 <1> ; 24/12/2021 3713 00003549 51 <1> push ecx ; cx = mode (permission flags) 3714 0000354A E8880A0000 <1> call namei 3715 <1> ; jsr r0,namei / get the i-number 3716 <1> ;and ax, ax 3717 <1> ;jz short syscreat_2 3718 0000354F 721B <1> jc short syscreat_2 3719 <1> ; br 2f / if file doesn't exist 2f 3720 <1> ; 27/12/2015 3721 00003551 6683F829 <1> cmp ax, 41 ; device inode ? 3722 <1> ;jb syscreat_0 ; yes 3723 <1> ; 24/12/2021 3724 00003555 7305 <1> jnb short syscreat_1 3725 00003557 E954FFFFFF <1> jmp syscreat_0 3726 <1> syscreat_1: 3727 0000355C 66F7D8 <1> neg ax 3728 <1> ; neg r1 / if file already exists make i-number 3729 <1> ; / negative (open for writing) 3730 0000355F E8E71A0000 <1> call iopen 3731 <1> ; jsr r0,iopen / 3732 00003564 E8AA130000 <1> call itrunc 3733 <1> ; jsr r0,itrunc / truncate to 0 length 3734 <1> ;pop cx ; pop mode (did not exist in original Unix v1 !?) 3735 <1> ; 04/12/2021 3736 00003569 59 <1> pop ecx 3737 <1> ; 08/01/2022 3738 0000356A EB0E <1> jmp short syscreat_3 3739 <1> ;jmp sysopen_1 3740 <1> ; br op0 3741 <1> syscreat_2: ; 2: / file doesn't exist 3742 <1> ;pop ax 3743 <1> ; ; mov (sp)+,r1 / put the mode in r1 3744 <1> ; 24/12/2021 3745 0000356C 58 <1> pop eax ; ax = mode (permission flags) 3746 0000356D 30E4 <1> xor ah, ah 3747 <1> ; bic $!377,r1 / clear upper byte 3748 0000356F E86F0D0000 <1> call maknod 3749 <1> ; jsr r0,maknod / make an i-node for this file 3750 00003574 66A1[1E650000] <1> mov ax, [u.dirbuf] 3751 <1> ; mov u.dirbuf,r1 / put i-number 3752 <1> ; / for this new file in r1 3753 <1> syscreat_3: 3754 0000357A E93EFFFFFF <1> jmp sysopen_1 3755 <1> ; br op0 / open the file 3756 <1> 3757 <1> sysmkdir: ; < make directory > 3758 <1> ; 26/02/2022 3759 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3760 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3761 <1> ; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 3762 <1> ; 3763 <1> ; 'sysmkdir' creates an empty directory whose name is 3764 <1> ; pointed to by arg 1. The mode of the directory is arg 2. 3765 <1> ; The special entries '.' and '..' are not present. 3766 <1> ; Errors are indicated if the directory already exists or 3767 <1> ; user is not the super user. 3768 <1> ; 3769 <1> ; Calling sequence: 3770 <1> ; sysmkdir; name; mode 3771 <1> ; Arguments: 3772 <1> ; name - points to the name of the directory 3773 <1> ; mode - mode of the directory 3774 <1> ; Inputs: (arguments) 3775 <1> ; Outputs: - 3776 <1> ; (sets 'directory' flag to 1; 3777 <1> ; 'set user id on execution' and 'executable' flags to 0) 3778 <1> ; ............................................................... 3779 <1> ; 3780 <1> ; Retro UNIX 8086 v1 modification: 3781 <1> ; 'sysmkdir' system call has two arguments; so, 3782 <1> ; * 1st argument, name is pointed to by BX register 3783 <1> ; * 2nd argument, mode is in CX register 3784 <1> ; 3785 <1> 3786 <1> ; / make a directory 3787 <1> 3788 <1> ;call arg2 3789 <1> ; * name - 'u.namep' points to address of file/path name 3790 <1> ; in the user's program segment ('u.segmnt') 3791 <1> ; with offset in BX register (as sysopen argument 1). 3792 <1> ; * mode - sysopen argument 2 is in CX register 3793 <1> ; which is on top of stack. 3794 <1> 3795 <1> ; jsr r0,arg2 / put file name in u.namep put mode 3796 <1> ; / on stack 3797 0000357F 891D[04650000] <1> mov [u.namep], ebx 3798 <1> ;push cx ; mode 3799 <1> ; 24/12/2021 3800 00003585 51 <1> push ecx ; cx = mode 3801 00003586 E84C0A0000 <1> call namei 3802 <1> ; jsr r0,namei / get the i-number 3803 <1> ; br .+4 / if file not found branch around error 3804 <1> ;xor ax, ax 3805 <1> ;jnz error 3806 0000358B 731B <1> jnc short dir_exists ; 14/05/2015 3807 <1> ;jnc error 3808 <1> ; br error2 / directory already exists (error) 3809 0000358D 803D[38650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 3810 <1> ;tstb u.uid / is user the super user 3811 <1> ;jna short dir_access_err ; 14/05/2015 3812 <1> ;;jna error 3813 <1> ; 26/02/2022 (BugFix) 3814 00003594 7721 <1> ja short dir_access_err 3815 <1> ;bne error2 / no, not allowed 3816 <1> ;pop ax 3817 <1> ; ;mov (sp)+,r1 / put the mode in r1 3818 <1> ; 24/12/2021 3819 00003596 58 <1> pop eax ; ax = mode 3820 00003597 6683E0CF <1> and ax, 0FFCFh ; 1111111111001111b 3821 <1> ;bic $!317,r1 / all but su and ex 3822 <1> ;or ax, 4000h ; 1011111111111111b 3823 0000359B 80CC40 <1> or ah, 40h ; Set bit 14 to 1 3824 <1> ;bis $40000,r1 / directory flag 3825 0000359E E8400D0000 <1> call maknod 3826 <1> ;jsr r0,maknod / make the i-node for the directory 3827 <1> ;sysclose_sysret: ; 26/02/2022 3828 000035A3 E943FBFFFF <1> jmp sysret 3829 <1> ;br sysret2 / 3830 <1> dir_exists: 3831 <1> ; 14/05/2015 3832 000035A8 C705[41650000]0E00- <1> mov dword [u.error], ERR_DIR_EXISTS ; dir. already exists ! 3832 000035B0 0000 <1> 3833 000035B2 E914FBFFFF <1> jmp error 3834 <1> dir_access_err: 3835 <1> ; 14/05/2015 3836 000035B7 C705[41650000]0B00- <1> mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 3836 000035BF 0000 <1> 3837 000035C1 E905FBFFFF <1> jmp error 3838 <1> 3839 <1> sysclose: ; 3840 <1> ; 26/02/2022 3841 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3842 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3843 <1> ; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1) 3844 <1> ; 3845 <1> ; 'sysclose', given a file descriptor in 'u.r0', closes the 3846 <1> ; associated file. The file descriptor (index to 'u.fp' list) 3847 <1> ; is put in r1 and 'fclose' is called. 3848 <1> ; 3849 <1> ; Calling sequence: 3850 <1> ; sysclose 3851 <1> ; Arguments: 3852 <1> ; - 3853 <1> ; Inputs: *u.r0 - file descriptor 3854 <1> ; Outputs: - 3855 <1> ; ............................................................... 3856 <1> ; 3857 <1> ; Retro UNIX 8086 v1 modification: 3858 <1> ; The user/application program puts file descriptor 3859 <1> ; in BX register as 'sysclose' system call argument. 3860 <1> ; (argument transfer method 1) 3861 <1> 3862 <1> ; / close the file 3863 <1> 3864 000035C6 89D8 <1> mov eax, ebx 3865 000035C8 E896090000 <1> call fclose 3866 <1> ; mov *u.r0,r1 / move index to u.fp list into r1 3867 <1> ; jsr r0,fclose / close the file 3868 <1> ; br error2 / unknown file descriptor 3869 <1> ; br sysret2 3870 <1> ; 14/05/2015 3871 <1> ;jnc sysret 3872 <1> ; 04/12/2021 3873 000035CD 7205 <1> jc short sysclose_err 3874 000035CF E917FBFFFF <1> jmp sysret 3875 <1> ; 26/02/2022 3876 <1> ;jnc short sysclose_sysret 3877 <1> sysclose_err: 3878 000035D4 C705[41650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 3878 000035DC 0000 <1> 3879 000035DE E9E8FAFFFF <1> jmp error 3880 <1> 3881 <1> sysemt: 3882 <1> ; 26/02/2022 3883 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3884 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3885 <1> ; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1) 3886 <1> ; 3887 <1> ; Retro UNIX 8086 v1 modification: 3888 <1> ; 'Enable Multi Tasking' system call instead 3889 <1> ; of 'Emulator Trap' in original UNIX v1 for PDP-11. 3890 <1> ; 3891 <1> ; Retro UNIX 8086 v1 feature only! 3892 <1> ; Using purpose: Kernel will start without time-out 3893 <1> ; (internal clock/timer) functionality. 3894 <1> ; Then etc/init will enable clock/timer for 3895 <1> ; multi tasking. (Then it will not be disabled again 3896 <1> ; except hardware reset/restart.) 3897 <1> ; 3898 <1> 3899 000035E3 803D[38650000]00 <1> cmp byte [u.uid], 0 ; root ? 3900 <1> ;;ja error 3901 <1> ;ja badsys ; 14/05/2015 3902 <1> ; 24/12/2021 3903 000035EA 7605 <1> jna short emt_0 3904 000035EC E98CFBFFFF <1> jmp badsys 3905 <1> emt_0: 3906 <1> ; 24/12/2021 3907 <1> ;cli 3908 000035F1 21DB <1> and ebx, ebx 3909 000035F3 7429 <1> jz short emt_2 3910 <1> ; Enable multi tasking -time sharing- 3911 000035F5 B8[9C450000] <1> mov eax, clock 3912 <1> ; 26/02/2022 3913 000035FA BA[2C0A0000] <1> mov edx, rtci_default ; disable rtc (digital) printing 3914 <1> emt_1: 3915 000035FF A3[F1060000] <1> mov [x_timer], eax 3916 <1> ; 26/02/2022 (Temporary) 3917 00003604 8915[F5060000] <1> mov [x_rtci], edx 3918 0000360A B306 <1> mov bl, 6 ; timer interrupt page, video page 6 3919 0000360C E851020000 <1> call wttyc ; clear video page 3920 00003611 B307 <1> mov bl, 7 ; rtc interrupt page, video page 7 3921 00003613 E84A020000 <1> call wttyc ; clear video page 3922 <1> ; 3923 00003618 FB <1> sti 3924 00003619 E9CDFAFFFF <1> jmp sysret 3925 <1> emt_2: 3926 <1> ; Disable multi tasking -time sharing- 3927 0000361E B8[FD060000] <1> mov eax, u_timer ; enable timer tick printing 3928 <1> ; 26/02/2022 3929 00003623 BA[330A0000] <1> mov edx, rtc_p ; enable rtc (digital) printing 3930 <1> ; 3931 00003628 EBD5 <1> jmp short emt_1 3932 <1> 3933 <1> ; Original UNIX v1 'sysemt' routine 3934 <1> ;sysemt: 3935 <1> ; 3936 <1> ;jsr r0,arg; 30 / put the argument of the sysemt call 3937 <1> ; / in loc 30 3938 <1> ;cmp 30,$core / was the argument a lower address 3939 <1> ; / than core 3940 <1> ;blo 1f / yes, rtssym 3941 <1> ;cmp 30,$ecore / no, was it higher than "core" 3942 <1> ; / and less than "ecore" 3943 <1> ;blo 2f / yes, sysret2 3944 <1> ;1: 3945 <1> ;mov $rtssym,30 3946 <1> ;2: 3947 <1> ;br sysret2 3948 <1> 3949 <1> sysilgins: 3950 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 3951 <1> ; 03/06/2013 3952 <1> ; Retro UNIX 8086 v1 modification: 3953 <1> ; not a valid system call ! (not in use) 3954 <1> ; 3955 0000362A E94EFBFFFF <1> jmp badsys 3956 <1> ;jmp error 3957 <1> ;;jmp sysret 3958 <1> 3959 <1> ; Original UNIX v1 'sysemt' routine 3960 <1> ;sysilgins: / calculate proper illegal instruction trap address 3961 <1> ;jsr r0,arg; 10 / take address from sysilgins call 3962 <1> ;/ put it in loc 8., 3963 <1> ;cmp 10,$core / making it the illegal instruction 3964 <1> ; / trap address 3965 <1> ;blo 1f / is the address a user core address? 3966 <1> ; / yes, go to 2f 3967 <1> ;cmp 10,$ecore 3968 <1> ;blo 2f 3969 <1> ;1: 3970 <1> ;mov $fpsym,10 / no, make 'fpsum' the illegal 3971 <1> ; / instruction trap address for the system 3972 <1> ;2: 3973 <1> ;br sysret2 / return to the caller via 'sysret' 3974 <1> 3975 <1> sysmdate: ; < change the modification time of a file > 3976 <1> ; 23/02/2022 (Retro UNIX 386 v1 feature/modification) 3977 <1> ; (ECX input) 3978 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3979 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 3980 <1> ; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 3981 <1> ; 3982 <1> ; 'sysmdate' is given a file name. It gets inode of this 3983 <1> ; file into core. The user is checked if he is the owner 3984 <1> ; or super user. If he is neither an error occurs. 3985 <1> ; 'setimod' is then called to set the i-node modification 3986 <1> ; byte and the modification time, but the modification time 3987 <1> ; is overwritten by whatever get put on the stack during 3988 <1> ; a 'systime' system call. This calls are restricted to 3989 <1> ; the super user. 3990 <1> ; 3991 <1> ; Calling sequence: 3992 <1> ; sysmdate; name 3993 <1> ; Arguments: 3994 <1> ; name - points to the name of file 3995 <1> ; Inputs: (arguments) 3996 <1> ; Outputs: - 3997 <1> ; ............................................................... 3998 <1> ; 3999 <1> ; Retro UNIX 8086 v1 modification: 4000 <1> ; The user/application program puts address 4001 <1> ; of the file name in BX register 4002 <1> ; as 'sysmdate' system call argument. 4003 <1> ; 4004 <1> ; / change the modification time of a file 4005 <1> ; jsr r0,arg; u.namep / point u.namep to the file name 4006 0000362F 891D[04650000] <1> mov [u.namep], ebx 4007 <1> ; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code) 4008 00003635 890D[70610000] <1> mov [p_time], ecx ; save new modification time to be set 4009 0000363B E897090000 <1> call namei 4010 <1> ; jsr r0,namei / get its i-number 4011 <1> ;;jc error 4012 <1> ; ; br error2 / no, such file 4013 <1> ;jc fnotfound ; file not found ! 4014 <1> ; 24/12/2021 4015 00003640 7305 <1> jnc short mdate_0 4016 00003642 E99BFEFFFF <1> jmp fnotfound 4017 <1> mdate_0: 4018 00003647 E89B110000 <1> call iget 4019 <1> ; jsr r0,iget / get i-node into core 4020 0000364C A0[38650000] <1> mov al, [u.uid] 4021 00003651 3A05[E7610000] <1> cmp al, [i.uid] 4022 <1> ; cmpb u.uid,i.uid / is user same as owner 4023 00003657 7413 <1> je short mdate_1 4024 <1> ; beq 1f / yes 4025 00003659 20C0 <1> and al, al 4026 <1> ; tstb u.uid / no, is user the super user 4027 <1> ;jnz error 4028 <1> ; bne error2 / no, error 4029 0000365B 740F <1> jz short mdate_1 4030 0000365D C705[41650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 4030 00003665 0000 <1> 4031 <1> sysstty_err: ; 04/02/2022 4032 00003667 E95FFAFFFF <1> jmp error 4033 <1> mdate_1: ;1: 4034 0000366C E880120000 <1> call setimod 4035 <1> ; jsr r0,setimod / fill in modification data, 4036 <1> ; / time etc. 4037 00003671 BE[70610000] <1> mov esi, p_time 4038 00003676 BF[FE610000] <1> mov edi, i.mtim 4039 0000367B A5 <1> movsd 4040 <1> ; mov 4(sp),i.mtim / move present time to 4041 <1> ; mov 2(sp),i.mtim+2 / modification time 4042 0000367C E96AFAFFFF <1> jmp sysret 4043 <1> ; br sysret2 4044 <1> 4045 <1> ; 04/02/2022 4046 <1> sysstty_err_s: 4047 00003681 880D[EC640000] <1> mov byte [u.r0], cl ; serial port's tty number 4048 00003687 EBDE <1> jmp short sysstty_err 4049 <1> 4050 <1> sysstty: ; < set tty status and mode > 4051 <1> ; 26/02/2022 4052 <1> ; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 4053 <1> ; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18) 4054 <1> ; 01/02/2022 (Retro UNIX 386 v1) -clear screen- 4055 <1> ; 17/11/2015 4056 <1> ; 12/11/2015 4057 <1> ; 29/10/2015 4058 <1> ; 17/10/2015 4059 <1> ; 13/10/2015 4060 <1> ; 29/06/2015 4061 <1> ; 27/06/2015 (Retro UNIX 386 v1 - Beginning) 4062 <1> ; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1) 4063 <1> ; 4064 <1> ; 'sysstty' sets the status and mode of the typewriter 4065 <1> ; whose file descriptor is in (u.r0). 4066 <1> ; 4067 <1> ; Calling sequence: 4068 <1> ; sysstty; arg 4069 <1> ; Arguments: 4070 <1> ; arg - address of 3 consequitive words that contain 4071 <1> ; the source of status data 4072 <1> ; Inputs: ((*u.r0 - file descriptor & argument)) 4073 <1> ; Outputs: ((status in address which is pointed to by arg)) 4074 <1> ; ............................................................... 4075 <1> ; 4076 <1> ; Retro UNIX 8086 v1 modification: 4077 <1> ; 'sysstty' system call will set the tty 4078 <1> ; (clear keyboard buffer and set cursor position) 4079 <1> ; in following manner: 4080 <1> ; NOTE: All of tty setting functions are here (16/01/2014) 4081 <1> ; 4082 <1> ; Inputs: 4083 <1> ; BX = 0 --> means 4084 <1> ; If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022 4085 <1> ; set cursor position for console tty, only 4086 <1> ; CH will be ignored (char. will not be written) 4087 <1> ; If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222 4088 <1> ; set console tty for (current) process 4089 <1> ; CL = tty number (0 to 9) 4090 <1> ; (If CH = 0, character will not be written) 4091 <1> ; If CH > 0 (CL < FFh) 4092 <1> ; CL = tty number (0 to 9) 4093 <1> ; CH = character will be written 4094 <1> ; at requested cursor position (in DX) 4095 <1> ; DX = cursor position for tty number 0 to 7. 4096 <1> ; (only tty number 0 to 7) 4097 <1> ; DL = communication parameters (for serial ports) 4098 <1> ; (only for COM1 and COM2 serial ports) 4099 <1> ; DH < 0FFh -> DL is valid, initialize serial port 4100 <1> ; or set cursor position 4101 <1> ; DH = 0FFh -> DL is not valid 4102 <1> ; do not set serial port parameters 4103 <1> ; or do not set cursor position 4104 <1> ; 4105 <1> ; BX > 0 --> points to name of tty 4106 <1> ; CH > 0 --> 4107 <1> ; CH = character will be written in current 4108 <1> ; cursor position (for tty number from 0 to 7) 4109 <1> ; or character will be sent to serial port 4110 <1> ; (for tty number 8 or 9) 4111 <1> ; CL = color of the character if tty number < 8. 4112 <1> ; CH = 0 --> Do not write a character, 4113 <1> ; set mode (tty 8 to 9) or 4114 <1> ; set current cursor positions (tty 0 to 7) only. 4115 <1> ; DX = cursor position for tty number 0 to 7. 4116 <1> ; DH = FFh --> Do not set cursor pos (or comm. params.) 4117 <1> ; (DL is not valid) 4118 <1> ; DL = communication parameters 4119 <1> ; for tty number 8 or 9 (COM1 or COM2). 4120 <1> ; 4121 <1> ; 01/02/2022 - Retro UNIX 386 v1 - 2022 modification 4122 <1> ; (30/01/2022 - Retro UNIX 8086 - 2022 modification) 4123 <1> ; If CH = 0 & DX = 0FFFFh -> 4124 <1> ; clear screen (video page) & set cursor pos to 0,0. 4125 <1> ; (for tty number 0 to 7, CL <= 7) 4126 <1> ; (if CL = 0FFh -> clear console tty) 4127 <1> ; 4128 <1> ; Outputs: 4129 <1> ; cf = 0 -> OK 4130 <1> ; AL = tty number (0 to 9) 4131 <1> ; AH = line status if tty number is 8 or 9 4132 <1> ; AH = process number (of the caller) 4133 <1> ; cf = 1 means error (requested tty is not ready) 4134 <1> ; AH = FFh if the tty is locked 4135 <1> ; (owned by another process) 4136 <1> ; = process number (of the caller) 4137 <1> ; (if < FFh and tty number < 8) 4138 <1> ; AL = tty number (0FFh if it does not exist) 4139 <1> ; AH = line status if tty number is 8 or 9 4140 <1> ; NOTE: Video page will be cleared if cf = 0. 4141 <1> ; 4142 <1> 4143 <1> ; 27/06/2015 (32 bit modifications) 4144 <1> ; 14/01/2014 4145 00003689 31C0 <1> xor eax, eax 4146 0000368B 6648 <1> dec ax ; 17/10/2015 4147 0000368D A3[EC640000] <1> mov [u.r0], eax ; 0FFFFh 4148 <1> ;;; 4149 <1> ; 01/02/2022 4150 00003692 FEC1 <1> inc cl ; 0FFh -> 0, 7 -> 8 4151 00003694 39C2 <1> cmp edx, eax 4152 <1> ;cmp dx, ax ; 0FFFFh 4153 00003696 7521 <1> jne short sysstty_18 4154 <1> ; clear video page 4155 <1> ; (CH must be 0) 4156 00003698 08ED <1> or ch, ch 4157 0000369A 75CB <1> jnz short sysstty_err ; invalid parameters 4158 0000369C 80F908 <1> cmp cl, 8 ; > tty7 (serial port?) 4159 0000369F 77C6 <1> ja short sysstty_err ; invalid parameters 4160 000036A1 20C9 <1> and cl, cl 4161 000036A3 7514 <1> jnz short sysstty_18 ; actual tty (video page) num + 1 4162 000036A5 0FB635[3B650000] <1> movzx esi, byte [u.uno] 4163 000036AC 8A8E[43620000] <1> mov cl, byte [esi+p.ttyc-1] ; current/console tty 4164 000036B2 80F907 <1> cmp cl, 7 4165 000036B5 77CA <1> ja short sysstty_err_s ; serial port ! 4166 <1> ; here CL contains (actual) tty number (tty0 to tty7) 4167 000036B7 FEC1 <1> inc cl ; 0 -> 1, 7 -> 8 4168 <1> sysstty_18: 4169 000036B9 FEC9 <1> dec cl ; 8 -> 7, 1 -> 0 4170 <1> ; cl = video page (tty) number 4171 <1> ;;; 4172 000036BB 21DB <1> and ebx, ebx 4173 <1> ;jnz sysstty_6 4174 <1> ; 01/02/2022 4175 000036BD 7405 <1> jz short sysstty_19 4176 000036BF E9C2000000 <1> jmp sysstty_6 4177 <1> sysstty_19: 4178 <1> ; set console tty 4179 <1> ; 29/10/2015 4180 <1> ; 17/01/2014 4181 000036C4 80F909 <1> cmp cl, 9 4182 000036C7 7613 <1> jna short sysstty_0 4183 <1> ; 17/11/2015 4184 000036C9 80F9FF <1> cmp cl, 0FFh 4185 000036CC 7202 <1> jb short sysstty_13 4186 000036CE 88CD <1> mov ch, cl ; force CH value to FFh 4187 <1> sysstty_13: 4188 000036D0 8A1D[3B650000] <1> mov bl, [u.uno] ; process number 4189 000036D6 8A8B[43620000] <1> mov cl, [ebx+p.ttyc-1] ; current/console tty 4190 <1> sysstty_0: 4191 <1> ; 29/06/2015 4192 <1> ;push dx 4193 <1> ;push cx 4194 <1> ; 01/02/2022 4195 000036DC 52 <1> push edx 4196 000036DD 51 <1> push ecx 4197 000036DE 30D2 <1> xor dl, dl ; sysstty call sign 4198 000036E0 88C8 <1> mov al, cl 4199 000036E2 A2[EC640000] <1> mov [u.r0], al ; tty number (0 to 9) 4200 000036E7 E8F9190000 <1> call ottyp 4201 <1> ; 01/02/2022 4202 000036EC 59 <1> pop ecx 4203 000036ED 5A <1> pop edx 4204 <1> ;pop cx 4205 <1> ;pop dx 4206 <1> ; 4207 000036EE 7220 <1> jc short sysstty_pd_err 4208 <1> ; 4209 <1> ; 26/02/2022 (Bug! BugFix) 4210 <1> ; (ebx = ?, modified in ottyp, it may be > 255) 4211 <1> ; 4212 000036F0 80F908 <1> cmp cl, 8 4213 000036F3 720C <1> jb short sysstty_2 4214 <1> ; 4215 000036F5 80FEFF <1> cmp dh, 0FFh 4216 000036F8 7407 <1> je short sysstty_2 4217 <1> ; set communication parameters for serial ports 4218 <1> 4219 <1> ; 01/02/2022 4220 <1> ; ; 29/10/2015 4221 <1> ; mov ah, dl ; communication parameters 4222 <1> ; ; ah = 0E3h = 11100011b = 115200 baud, 4223 <1> ; ; THRE int + RDA int 4224 <1> ; ; ah = 23h = 00100011b = 9600 baud, 4225 <1> ; ; THRE int + RDA int 4226 <1> ; sub al, al ; 0 4227 <1> ; ; 12/07/2014 4228 <1> ; cmp cl, 9 4229 <1> ; jb short sysstty_1 4230 <1> ; inc al 4231 <1> ;sysstty_1: 4232 <1> ; ; 01/02/2022 4233 <1> ; push ecx 4234 <1> ; ;push cx 4235 <1> ; ; 29/06/2015 4236 <1> ; call sp_setp ; Set serial port communication parameters 4237 <1> ; mov [u.r0+1], cx ; Line status (ah) 4238 <1> ; ; Modem status (EAX bits 16 to 23) 4239 <1> ; ; 01/02/2022 4240 <1> ; pop ecx 4241 <1> ; ;pop cx 4242 <1> ; jc short sysstty_tmout_err ; 29/10/2015 4243 <1> 4244 <1> ; 01/02/2022 4245 000036FA E830010000 <1> call sysstty_scp 4246 000036FF 7276 <1> jc short sysstty_tmout_err ; 29/10/2015 4247 <1> 4248 <1> sysstty_2: 4249 <1> ; 17/01/2014 4250 00003701 20ED <1> and ch, ch ; set cursor position 4251 <1> ; or comm. parameters ONLY 4252 00003703 7527 <1> jnz short sysstty_3 4253 <1> ; 01/02/2022 4254 00003705 6683FAFF <1> cmp dx, 0FFFFh 4255 00003709 7214 <1> jb short sysstty_20 4256 <1> ; clear screen (video page) 4257 0000370B E93B010000 <1> jmp sysstty_14 4258 <1> 4259 <1> sysstty_pd_err: ; 29/06/2015 4260 <1> ; 'permission denied !' error 4261 00003710 C705[41650000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER 4261 00003718 0000 <1> 4262 0000371A E9ACF9FFFF <1> jmp error 4263 <1> 4264 <1> sysstty_20: 4265 0000371F 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 4266 00003726 888B[43620000] <1> mov [ebx+p.ttyc-1], cl ; console tty 4267 <1> sysstty_3: 4268 <1> ; 16/01/2014 4269 0000372C 88E8 <1> mov al, ch ; character ; 0 to FFh 4270 <1> ; 17/11/2015 4271 0000372E B507 <1> mov ch, 7 ; Default color (light gray) 4272 00003730 38E9 <1> cmp cl, ch ; 7 (tty number) 4273 <1> ;jna sysstty_9 4274 <1> ; 01/02/2022 4275 00003732 7705 <1> ja short sysstty_12 4276 00003734 E9C5000000 <1> jmp sysstty_9 4277 <1> 4278 <1> sysstty_12: 4279 <1> ;; BX = 0, CL = 8 or CL = 9 4280 <1> ; (Set specified serial port as console tty port) 4281 <1> ; CH = character to be written 4282 <1> ; 15/04/2014 4283 <1> ; CH = 0 --> initialization only 4284 <1> ; AL = character 4285 <1> ; 26/06/2014 4286 00003739 880D[40650000] <1> mov [u.ttyn], cl 4287 <1> ; 12/07/2014 4288 0000373F 88CC <1> mov ah, cl ; tty number (8 or 9) 4289 <1> ; 02/02/2022 4290 00003741 FEC0 <1> inc al ; 0FFh -> 0, 0 -> 1 4291 00003743 740B <1> jz short sysstty_4 ; al = ch = 0 4292 00003745 FEC8 <1> dec al ; 1 -> 0 4293 <1> ;and al, al 4294 00003747 7407 <1> jz short sysstty_4 ; al = ch = 0 4295 <1> ; 04/07/2014 4296 00003749 E8AD1E0000 <1> call sndc 4297 <1> ; 12/07/2014 4298 0000374E EB0C <1> jmp short sysstty_5 4299 <1> 4300 <1> sysstty_4: 4301 <1> ; 12/07/2014 4302 <1> ;xchg ah, al ; al = 0 -> al = ah, ah = 0 4303 00003750 88E0 <1> mov al, ah ; 29/06/2015 4304 00003752 2C08 <1> sub al, 8 4305 <1> ; 27/06/2015 4306 00003754 E828F4FFFF <1> call sp_status ; get serial port status 4307 <1> ; AL = Line status, AH = Modem status 4308 <1> ; 12/11/2015 4309 00003759 3C80 <1> cmp al, 80h 4310 0000375B F5 <1> cmc 4311 <1> sysstty_5: 4312 0000375C 66A3[ED640000] <1> mov [u.r0+1], ax ; ah = line status 4313 <1> ; EAX bits 16-23 = modem status 4314 00003762 9C <1> pushf 4315 00003763 30D2 <1> xor dl, dl ; sysstty call sign 4316 00003765 A0[40650000] <1> mov al, [u.ttyn] ; 26/06/2014 4317 0000376A E8991A0000 <1> call cttyp 4318 0000376F 9D <1> popf 4319 <1> ;jnc sysret ; time out error 4320 <1> ; 01/02/2022 4321 00003770 7205 <1> jc short sysstty_tmout_err 4322 00003772 E974F9FFFF <1> jmp sysret 4323 <1> 4324 <1> sysstty_tmout_err: 4325 00003777 C705[41650000]1900- <1> mov dword [u.error], ERR_TIME_OUT 4325 0000377F 0000 <1> 4326 00003781 E945F9FFFF <1> jmp error 4327 <1> 4328 <1> sysstty_6: 4329 <1> ;push dx 4330 <1> ;push cx 4331 <1> ; 01/02/2022 4332 00003786 52 <1> push edx 4333 00003787 51 <1> push ecx 4334 00003788 891D[04650000] <1> mov [u.namep], ebx 4335 0000378E E844080000 <1> call namei 4336 <1> ; 01/02/2022 4337 00003793 59 <1> pop ecx 4338 00003794 5A <1> pop edx 4339 <1> ;pop cx 4340 <1> ;pop dx 4341 00003795 7258 <1> jc short sysstty_inv_dn 4342 <1> ; 4343 00003797 6683F813 <1> cmp ax, 19 ; inode number of /dev/COM2 4344 0000379B 7752 <1> ja short sysstty_inv_dn ; 27/06/2015 4345 <1> ; 4346 0000379D 3C0A <1> cmp al, 10 ; /dev/tty0 .. /dev/tty7 4347 <1> ; /dev/COM1, /dev/COM2 4348 0000379F 7204 <1> jb short sysstty_7 4349 000037A1 2C0A <1> sub al, 10 4350 000037A3 EB11 <1> jmp short sysstty_8 4351 <1> 4352 <1> sysstty_7: 4353 000037A5 3C01 <1> cmp al, 1 ; /dev/tty 4354 000037A7 7546 <1> jne short sysstty_inv_dn ; 27/06/2015 4355 000037A9 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 4356 000037B0 8A83[43620000] <1> mov al, [ebx+p.ttyc-1] ; console tty 4357 <1> sysstty_8: 4358 <1> ; 26/02/2022 4359 <1> ; (ebx < 256) 4360 000037B6 A2[EC640000] <1> mov [u.r0], al 4361 <1> ; 01/02/2022 4362 <1> ;push dx 4363 <1> ;push ax 4364 <1> ;push cx 4365 000037BB 52 <1> push edx 4366 000037BC 50 <1> push eax 4367 000037BD 51 <1> push ecx 4368 000037BE E822190000 <1> call ottyp 4369 000037C3 59 <1> pop ecx 4370 000037C4 58 <1> pop eax 4371 000037C5 5A <1> pop edx 4372 <1> ;pop cx 4373 <1> ;pop ax 4374 <1> ;pop dx 4375 <1> ;jc sysstty_pd_err ; 'permission denied !' 4376 <1> ; 01/02/2022 4377 000037C6 7305 <1> jnc short sysstty_21 4378 000037C8 E943FFFFFF <1> jmp sysstty_pd_err ; 'permission denied !' 4379 <1> sysstty_21: 4380 <1> ; 29/10/2015 4381 000037CD 86E9 <1> xchg ch, cl 4382 <1> ; cl = character, ch = color code 4383 000037CF 86C1 <1> xchg al, cl 4384 <1> ; al = character, cl = tty number 4385 000037D1 80F907 <1> cmp cl, 7 4386 <1> ;ja sysstty_12 4387 <1> ; 01/02/2022 4388 000037D4 7628 <1> jna short sysstty_16 4389 <1> ;; 4390 000037D6 80FEFF <1> cmp dh, 0FFh 4391 000037D9 740B <1> je short sysstty_22 ; do not set comm. parameters 4392 <1> 4393 <1> ; 01/02/2022 4394 <1> ; ; 29/10/2015 4395 <1> ; mov ah, dl ; communication parameters 4396 <1> ; ; ah = 0E3h = 11100011b = 115200 baud, 4397 <1> ; ; THRE int + RDA int 4398 <1> ; ; ah = 23h = 00100011b = 9600 baud, 4399 <1> ; ; THRE int + RDA int 4400 <1> ; sub al, al ; 0 4401 <1> ; ; 12/07/2014 4402 <1> ; cmp cl, 9 4403 <1> ; jb short sysstty_1 4404 <1> ; inc al 4405 <1> ;sysstty_1: 4406 <1> ; ; 01/02/2022 4407 <1> ; push ecx 4408 <1> ; ;push cx 4409 <1> ; ; 29/06/2015 4410 <1> ; call sp_setp ; Set serial port communication parameters 4411 <1> ; mov [u.r0+1], cx ; Line status (ah) 4412 <1> ; ; Modem status (EAX bits 16 to 23) 4413 <1> ; ; 01/02/2022 4414 <1> ; pop ecx 4415 <1> ; ;pop cx 4416 <1> ; jc short sysstty_tmout_err ; 29/10/2015 4417 <1> 4418 <1> ; 02/02/2022 4419 000037DB 88C5 <1> mov ch, al ; save char 4420 <1> ; 01/02/2022 4421 000037DD E84D000000 <1> call sysstty_scp 4422 000037E2 7293 <1> jc short sysstty_tmout_err ; 29/10/2015 4423 <1> ; 02/02/2022 4424 000037E4 88E8 <1> mov al, ch ; restore char 4425 <1> sysstty_22: 4426 <1> ; 01/02/2022 4427 000037E6 08ED <1> or ch, ch 4428 000037E8 7437 <1> jz short sysstty_11 ; do not send char to terminal 4429 <1> ; send char to (serial port) terminal 4430 <1> ; al = character 4431 <1> ; cl = tty number (8 or 9) 4432 000037EA E94AFFFFFF <1> jmp sysstty_12 ; (tty8 or tty9) 4433 <1> 4434 <1> sysstty_inv_dn: 4435 <1> ; 27/06/2015 4436 <1> ; Invalid device name (not a tty) ! error 4437 <1> ; (Device is not a tty or device name not found) 4438 000037EF C705[41650000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 4438 000037F7 0000 <1> 4439 000037F9 E9CDF8FFFF <1> jmp error 4440 <1> 4441 <1> sysstty_16: 4442 <1> ; 26/02/2022 4443 <1> ; 16/01/2014 4444 <1> ;xor bh, bh 4445 <1> ; 02/02/2022 4446 <1> sysstty_9: ; tty 0 to tty 7 4447 <1> ; al = character 4448 <1> ; ch = color/attribute ; 01/02/2022 4449 <1> ; 4450 <1> ; 26/02/2022 (BugFix) 4451 <1> ; (ebx may be > 255 here!? due to 'ottyp') 4452 000037FE 29DB <1> sub ebx, ebx ; * 4453 00003800 80FEFF <1> cmp dh, 0FFh ; Do not set cursor position 4454 00003803 740B <1> je short sysstty_10 4455 <1> ; 02/02/2022 4456 00003805 51 <1> push ecx 4457 00003806 50 <1> push eax 4458 <1> ;push cx 4459 <1> ;push ax 4460 <1> ;movzx ebx, cl 4461 00003807 88CB <1> mov bl, cl ; (tty number = video page number) 4462 00003809 E898DBFFFF <1> call set_cpos 4463 <1> ;pop ax 4464 <1> ;pop cx 4465 <1> ; 02/02/2022 4466 0000380E 58 <1> pop eax 4467 0000380F 59 <1> pop ecx 4468 <1> sysstty_10: 4469 <1> ; 29/10/2015 4470 00003810 08C0 <1> or al, al ; character 4471 00003812 740D <1> jz short sysstty_11 ; al = 0 4472 <1> ; 17/11/2015 4473 00003814 3CFF <1> cmp al, 0FFh 4474 00003816 7309 <1> jnb short sysstty_11 4475 <1> ; ch > 0 and ch < FFh 4476 <1> ; write a character at current cursor position 4477 00003818 88EC <1> mov ah, ch ; color/attribute 4478 <1> ; 12/07/2014 4479 <1> ;push cx 4480 <1> ; 02/02/2022 4481 0000381A 51 <1> push ecx 4482 0000381B E86EDCFFFF <1> call write_c_current 4483 <1> ;pop cx 4484 <1> ; 02/02/2022 4485 00003820 59 <1> pop ecx 4486 <1> sysstty_11: 4487 <1> ; 14/01/2014 4488 00003821 30D2 <1> xor dl, dl ; sysstty call sign 4489 <1> ; 18/01/2014 4490 <1> ;movzx eax, cl ; 27/06/2015 4491 00003823 88C8 <1> mov al, cl 4492 00003825 E8DE190000 <1> call cttyp 4493 0000382A E9BCF8FFFF <1> jmp sysret 4494 <1> 4495 <1> sysstty_scp: 4496 <1> ; 02/02/2022 4497 <1> ; set communication parameters (for COM1 or COM2) 4498 <1> ; 01/02/2022 4499 <1> ; 4500 <1> ; 29/10/2015 4501 0000382F 88D4 <1> mov ah, dl ; communication parameters 4502 <1> ; ah = 0E3h = 11100011b = 115200 baud, 4503 <1> ; THRE int + RDA int 4504 <1> ; ah = 23h = 00100011b = 9600 baud, 4505 <1> ; THRE int + RDA int 4506 00003831 28C0 <1> sub al, al ; 0 4507 <1> ; 12/07/2014 4508 00003833 80F909 <1> cmp cl, 9 4509 00003836 7202 <1> jb short sysstty_1 4510 00003838 FEC0 <1> inc al 4511 <1> sysstty_1: 4512 <1> ; 02/02/2022 4513 0000383A 52 <1> push edx 4514 <1> ; 01/02/2022 4515 0000383B 51 <1> push ecx 4516 <1> ;push cx 4517 <1> ; 29/06/2015 4518 0000383C E848F3FFFF <1> call sp_setp ; Set serial port communication parameters 4519 00003841 66890D[ED640000] <1> mov [u.r0+1], cx ; Line status (ah) 4520 <1> ; Modem status (EAX bits 16 to 23) 4521 <1> ; 01/02/2022 4522 00003848 59 <1> pop ecx 4523 <1> ;pop cx 4524 00003849 5A <1> pop edx ; 02/02/2022 4525 <1> ; 01/02/2022 4526 <1> ; if cf = 1 -> sysstty_tmout_err 4527 0000384A C3 <1> retn 4528 <1> 4529 <1> sysstty_14: 4530 <1> ; 26/02/2022 4531 <1> ; 02/02/2022 4532 <1> ; ch = 0 4533 <1> ; cl = video page 4534 <1> ; 4535 <1> ; dx = 0FFFFh 4536 <1> ; clear screen (video page) 4537 <1> ; 4538 <1> 4539 <1> ; 02/02/2022 4540 <1> ; clear screen 4541 <1> ; 4542 <1> ; (modified registers: eax, ebx, ecx, edx, esi, edi) 4543 <1> ; clear video page 4544 <1> 4545 <1> ; 26/02/2022 4546 0000384B 88CB <1> mov bl, cl ; CL = tty number (0 to 7) 4547 <1> 4548 <1> ; clear video page 4549 0000384D E810000000 <1> call wttyc ; 26/02/2022 4550 <1> 4551 <1> ; 26/02/2022 4552 00003852 88D8 <1> mov al, bl 4553 00003854 8A25[3B650000] <1> mov ah, [u.uno] 4554 0000385A 66A3[EC640000] <1> mov [u.r0], ax 4555 00003860 EBBF <1> jmp short sysstty_11 4556 <1> 4557 <1> vp_clr: ; 27/02/2022 4558 <1> wttyc: 4559 <1> ; 23/02/2022 4560 <1> ; (clear video page) 4561 <1> ; INPUT: 4562 <1> ; bl = video page (0 to 7) 4563 <1> ; 4564 <1> ; Modified registers: eax, ecx, edx, esi, edi 4565 <1> 4566 <1> ;xor dx, dx ; column 0, row 0 4567 <1> ;;inc dx ; 0 ; 23/02/2022 4568 <1> ; 4569 <1> ; movzx ebx, cl 4570 <1> ; mov bl, cl ; CL = tty number (0 to 7) ; 23/02/2022 4571 <1> 4572 <1> ; shl bl, 1 4573 <1> ; mov al, byte ptr [ebx+ttyl] 4574 <1> ; ; AL = lock value (0 or process number) 4575 <1> ; or al, al 4576 <1> ; jz short @f 4577 <1> ; cmp al, byte ptr [u.uno] ; process number 4578 <1> ; jne short sysstty_15 4579 <1> ; ; only the owner can clear its video page 4580 <1> ; xor al, al ; 0 4581 <1> ;@@: 4582 <1> ; ;mov bl, cl 4583 <1> ; shr bl, 1 4584 <1> 4585 00003862 30C0 <1> xor al, al ; 0 4586 00003864 B407 <1> mov ah, 07h ; attribute/color (default) 4587 <1> 4588 <1> ; scroll_up input: 4589 <1> ; 4590 <1> ; al = line count (0 or 1) ((0 == clear video page)) 4591 <1> ; ((al = 1 for write_tty (putc) procedure)) 4592 <1> ; ah = attribute to be used on blanked line 4593 <1> ; bl = video page number (0 to 7) 4594 <1> 4595 00003866 E8C1DBFFFF <1> call scroll_up ; clear video page (al=0) 4596 <1> 4597 <1> ; (modified registers: eax, ecx, edx, esi, edi) 4598 <1> 4599 <1> ; bl = video page number (0 to 7) 4600 <1> ;xor dx, dx ; column 0, row 0 4601 <1> ; 02/02/2022 4602 0000386B 31D2 <1> xor edx, edx 4603 <1> ; 26/02/2022 4604 <1> ;call set_cpos 4605 <1> ;retn 4606 0000386D E934DBFFFF <1> jmp set_cpos 4607 <1> 4608 <1> ;mov al, bl 4609 <1> ;mov ah, [u.uno] 4610 <1> ;mov [u.r0], ax 4611 <1> ;jmp short sysstty_11 4612 <1> 4613 <1> ;sysstty_15: 4614 <1> ; ; 30/01/2022 4615 <1> ; ; permission (denied) error 4616 <1> ; ;xor dl, dl ; sysstty call sign 4617 <1> ; mov al, cl 4618 <1> ; sub ah, ah ; 0 4619 <1> ; call cttyp 4620 <1> ; jmp error 4621 <1> 4622 <1> ; Original UNIX v1 'sysstty' routine: 4623 <1> ; gtty: 4624 <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments 4625 <1> ;jsr r0,gtty / r1 will have offset to tty block, 4626 <1> ; / r2 has source 4627 <1> ;mov r2,-(sp) 4628 <1> ;mov r1,-(sp) / put r1 and r2 on the stack 4629 <1> ;1: / flush the clist wait till typewriter is quiescent 4630 <1> ;mov (sp),r1 / restore r1 to tty block offset 4631 <1> ;movb tty+3(r1),0f / put cc offset into getc argument 4632 <1> ;mov $240,*$ps / set processor priority to 5 4633 <1> ;jsr r0,getc; 0:../ put character from clist in r1 4634 <1> ; br .+4 / list empty, skip branch 4635 <1> ;br 1b / get another character until list is empty 4636 <1> ;mov 0b,r1 / move cc offset to r1 4637 <1> ;inc r1 / bump it for output clist 4638 <1> ;tstb cc(r1) / is it 0 4639 <1> ;beq 1f / yes, no characters to output 4640 <1> ;mov r1,0f / no, put offset in sleep arg 4641 <1> ;jsr r0,sleep; 0:.. / put tty output process to sleep 4642 <1> ;br 1b / try to calm it down again 4643 <1> ;1: 4644 <1> ;mov (sp)+,r1 4645 <1> ;mov (sp)+,r2 / restore registers 4646 <1> ;mov (r2)+,r3 / put reader control status in r3 4647 <1> ;beq 1f / if 0, 1f 4648 <1> ;mov r3,rcsr(r1) / move r.c. status to reader 4649 <1> ; / control status register 4650 <1> ;1: 4651 <1> ;mov (r2)+,r3 / move pointer control status to r3 4652 <1> ;beq 1f / if 0 1f 4653 <1> ;mov r3,tcsr(r1) / move p.c. status to printer 4654 <1> ; / control status reg 4655 <1> ;1: 4656 <1> ;mov (r2)+,tty+4(r1) / move to flag byte of tty block 4657 <1> ;jmp sysret2 / return to user 4658 <1> 4659 <1> sysgtty: ; < get tty status > 4660 <1> ; 26/02/2022 4661 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4662 <1> ; ((32 bit reg push/pop)) 4663 <1> ; 23/11/2015 4664 <1> ; 29/10/2015 4665 <1> ; 17/10/2015 4666 <1> ; 28/06/2015 (Retro UNIX 386 v1 - Beginning) 4667 <1> ; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1) 4668 <1> ; 4669 <1> ; 'sysgtty' gets the status of tty in question. 4670 <1> ; It stores in the three words addressed by it's argument 4671 <1> ; the status of the typewriter whose file descriptor 4672 <1> ; in (u.r0). 4673 <1> ; 4674 <1> ; Calling sequence: 4675 <1> ; sysgtty; arg 4676 <1> ; Arguments: 4677 <1> ; arg - address of 3 words destination of the status 4678 <1> ; Inputs: ((*u.r0 - file descriptor)) 4679 <1> ; Outputs: ((status in address which is pointed to by arg)) 4680 <1> ; ............................................................... 4681 <1> ; 4682 <1> ; Retro UNIX 8086 v1 modification: 4683 <1> ; 'sysgtty' system call will return status of tty 4684 <1> ; (keyboard, serial port and video page status) 4685 <1> ; in following manner: 4686 <1> ; 4687 <1> ; Inputs: 4688 <1> ; BX = 0 --> means 4689 <1> ; CH = 0 --> 'return status of the console tty' 4690 <1> ; for (current) process 4691 <1> ; CL = 0 --> return keyboard status (tty 0 to 9) 4692 <1> ; CL = 1 --> return video page status (tty 0 to 7) 4693 <1> ; CL = 1 --> return serial port status (tty 8 & 9) 4694 <1> ; CH > 0 --> tty number + 1 4695 <1> ; 4696 <1> ; BX > 0 --> points to name of tty 4697 <1> ; CL = 0 --> return keyboard status 4698 <1> ; CL = 1 --> return video page status 4699 <1> ; CH = undefined 4700 <1> ; 4701 <1> ; Outputs: 4702 <1> ; cf = 0 -> 4703 <1> ; 4704 <1> ; AL = tty number from 0 to 9 4705 <1> ; (0 to 7 is also the video page of the tty) 4706 <1> ; AH = 0 if the tty is free/unused 4707 <1> ; AH = the process number of the caller 4708 <1> ; AH = FFh if the tty is locked by another process 4709 <1> ; 4710 <1> ; (if calling is for serial port status) 4711 <1> ; BX = serial port status if tty number is 8 or 9 4712 <1> ; (BH = modem status, BL = Line status) 4713 <1> ; CX = 0FFFFh (if data is ready) 4714 <1> ; CX = 0 (if data is not ready or undefined) 4715 <1> ; 4716 <1> ; (if calling is for keyboard status) 4717 <1> ; BX = current character in tty/keyboard buffer 4718 <1> ; (BH = scan code, BL = ascii code) 4719 <1> ; (BX=0 if there is not a waiting character) 4720 <1> ; CX is undefined 4721 <1> ; 4722 <1> ; (if calling is for video page status) 4723 <1> ; BX = cursor position on the video page 4724 <1> ; if tty number < 8 4725 <1> ; (BH = row, BL = column) 4726 <1> ; CX = current character (in cursor position) 4727 <1> ; on the video page of the tty 4728 <1> ; if tty number < 8 4729 <1> ; (CH = color, CL = character) 4730 <1> ; 4731 <1> ; cf = 1 means error (requested tty is not ready) 4732 <1> ; 4733 <1> ; AH = FFh if the caller is not owner of 4734 <1> ; specified tty or console tty 4735 <1> ; AL = tty number (0FFh if it does not exist) 4736 <1> ; BX, CX are undefined if cf = 1 4737 <1> ; 4738 <1> ; (If tty number is 8 or 9) 4739 <1> ; AL = tty number 4740 <1> ; AH = the process number of the caller 4741 <1> ; BX = serial port status 4742 <1> ; (BH = modem status, BL = Line status) 4743 <1> ; CX = 0 4744 <1> ; 4745 <1> 4746 <1> gtty: ; get (requested) tty number 4747 <1> ; 26/02/2022 4748 <1> ; 17/10/2015 4749 <1> ; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications) 4750 <1> ; 30/05/2013 - 12/07/2014 4751 <1> ; Retro UNIX 8086 v1 modification ! 4752 <1> ; 4753 <1> ; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP)) 4754 <1> ; 4755 <1> ; 28/06/2015 (32 bit modifications) 4756 <1> ; 16/01/2014 4757 00003872 31C0 <1> xor eax, eax 4758 00003874 6648 <1> dec ax ; 17/10/2015 4759 00003876 A3[EC640000] <1> mov [u.r0], eax ; 0FFFFh 4760 0000387B 80F901 <1> cmp cl, 1 4761 0000387E 760F <1> jna short sysgtty_0 4762 <1> sysgtty_invp: 4763 <1> ; 28/06/2015 4764 00003880 C705[41650000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 4764 00003888 0000 <1> 4765 0000388A E93CF8FFFF <1> jmp error 4766 <1> sysgtty_0: 4767 0000388F 21DB <1> and ebx, ebx 4768 00003891 742E <1> jz short sysgtty_1 4769 <1> ; 4770 00003893 891D[04650000] <1> mov [u.namep], ebx 4771 <1> ;push cx ; 23/11/2015 4772 00003899 51 <1> push ecx ; 24/12/2021 4773 0000389A E838070000 <1> call namei 4774 0000389F 59 <1> pop ecx 4775 <1> ;pop cx ; 23/11/2015 4776 000038A0 7210 <1> jc short sysgtty_inv_dn ; 28/06/2015 4777 <1> ; 4778 000038A2 6683F801 <1> cmp ax, 1 4779 000038A6 7622 <1> jna short sysgtty_2 4780 <1> ; 26/02/2022 4781 000038A8 20E4 <1> and ah, ah 4782 000038AA 7506 <1> jnz short sysgtty_inv_dn 4783 <1> ;sub ax, 10 4784 000038AC 2C0A <1> sub al, 10 4785 000038AE 3C09 <1> cmp al, 9 4786 <1> ;cmp ax, 9 4787 <1> ;ja short sysgtty_inv_dn 4788 <1> ;mov ch, al 4789 <1> ;jmp short sysgtty_4 4790 <1> ; 23/11/2015 4791 000038B0 7629 <1> jna short sysgtty_4 4792 <1> sysgtty_inv_dn: 4793 <1> ; 28/06/2015 4794 <1> ; Invalid device name (not a tty) ! error 4795 <1> ; (Device is not a tty or device name not found) 4796 000038B2 C705[41650000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 4796 000038BA 0000 <1> 4797 000038BC E90AF8FFFF <1> jmp error 4798 <1> sysgtty_1: 4799 <1> ; 16/01/2014 4800 000038C1 80FD0A <1> cmp ch, 10 4801 000038C4 77BA <1> ja short sysgtty_invp ; 28/06/2015 4802 000038C6 FECD <1> dec ch ; 0 -> FFh (negative) 4803 000038C8 790F <1> jns short sysgtty_3 ; not negative 4804 <1> ; 4805 <1> sysgtty_2: 4806 <1> ; get tty number of console tty 4807 000038CA 8A25[3B650000] <1> mov ah, [u.uno] 4808 <1> ; 28/06/2015 4809 000038D0 0FB6DC <1> movzx ebx, ah 4810 000038D3 8AAB[43620000] <1> mov ch, [ebx+p.ttyc-1] 4811 <1> sysgtty_3: 4812 000038D9 88E8 <1> mov al, ch 4813 <1> sysgtty_4: 4814 000038DB A2[EC640000] <1> mov [u.r0], al 4815 <1> ; 28/06/2015 4816 <1> ;cmp al, 9 4817 <1> ;ja short sysgtty_invp 4818 000038E0 8B2D[E8640000] <1> mov ebp, [u.usp] 4819 <1> ; 23/11/2015 4820 000038E6 20C9 <1> and cl, cl 4821 000038E8 7432 <1> jz short sysgtty_6 ; keyboard status 4822 000038EA 3C08 <1> cmp al, 8 ; cmp ch, 8 4823 000038EC 722E <1> jb short sysgtty_6 ; video page status 4824 <1> ; serial port status 4825 <1> ; 12/07/2014 4826 <1> ;mov dx, 0 4827 <1> ;je short sysgtty_5 4828 <1> ;inc dl 4829 <1> ;sysgtty_5: 4830 <1> ; 28/06/2015 4831 000038EE 2C08 <1> sub al, 8 4832 000038F0 E88CF2FFFF <1> call sp_status ; serial (COM) port (line) status 4833 <1> ; AL = Line status, AH = Modem status 4834 000038F5 66894510 <1> mov [ebp+16], ax ; serial port status (in EBX) 4835 000038F9 8A25[3B650000] <1> mov ah, [u.uno] 4836 000038FF 8825[ED640000] <1> mov [u.r0+1], ah 4837 <1> ; 24/12/2021 4838 00003905 66C745180000 <1> mov word [ebp+24], 0 ; data status (0 = not ready) 4839 <1> ; (in ECX) 4840 0000390B A880 <1> test al, 80h 4841 0000390D 7561 <1> jnz short sysgtty_dnr_err ; 29/06/2015 4842 0000390F A801 <1> test al, 1 4843 <1> ;jz sysret 4844 00003911 7404 <1> jz short sysgtty_10 4845 00003913 66FF4D18 <1> dec word [ebp+24] ; data status (FFFFh = ready) 4846 <1> sysgtty_10: 4847 00003917 E9CFF7FFFF <1> jmp sysret 4848 <1> sysgtty_6: 4849 0000391C A2[40650000] <1> mov [u.ttyn], al ; tty number 4850 <1> ;movzx ebx, al 4851 00003921 88C3 <1> mov bl, al ; tty number (0 to 9) 4852 00003923 D0E3 <1> shl bl, 1 ; aligned to word 4853 <1> ; 22/04/2014 - 29/06/2015 4854 00003925 81C3[74610000] <1> add ebx, ttyl 4855 0000392B 8A23 <1> mov ah, [ebx] 4856 0000392D 3A25[3B650000] <1> cmp ah, [u.uno] 4857 00003933 7404 <1> je short sysgtty_7 4858 00003935 20E4 <1> and ah, ah 4859 <1> ;jz short sysgtty_7 4860 00003937 7506 <1> jnz short sysgtty_8 4861 <1> ;mov ah, 0FFh 4862 <1> sysgtty_7: 4863 00003939 8825[ED640000] <1> mov [u.r0+1], ah 4864 <1> sysgtty_8: 4865 0000393F 08C9 <1> or cl, cl 4866 00003941 7510 <1> jnz short sysgtty_9 4867 00003943 B001 <1> mov al, 1 ; test a key is available 4868 00003945 E8341C0000 <1> call getc 4869 0000394A 66894510 <1> mov [ebp+16], ax ; bx, character 4870 0000394E E998F7FFFF <1> jmp sysret 4871 <1> sysgtty_9: 4872 00003953 8A1D[40650000] <1> mov bl, [u.ttyn] 4873 <1> ; bl = video page number 4874 00003959 E8911D0000 <1> call get_cpos 4875 <1> ; dx = cursor position 4876 0000395E 66895510 <1> mov [ebp+16], dx ; bx 4877 <1> ;mov bl, [u.ttyn] 4878 <1> ; bl = video page number 4879 00003962 E8991D0000 <1> call read_ac_current 4880 <1> ; ax = character and attribute/color 4881 00003967 66894518 <1> mov [ebp+24], ax ; cx 4882 0000396B E97BF7FFFF <1> jmp sysret 4883 <1> sysgtty_dnr_err: 4884 <1> ; 'device not responding !' error 4885 <1> ;mov dword [u.error], ERR_TIME_OUT ; 25 4886 00003970 C705[41650000]1900- <1> mov dword [u.error], ERR_DEV_NOT_RESP ; 25 4886 00003978 0000 <1> 4887 0000397A E94CF7FFFF <1> jmp error 4888 <1> 4889 <1> ; Original UNIX v1 'sysgtty' routine: 4890 <1> ; sysgtty: 4891 <1> ;jsr r0,gtty / r1 will have offset to tty block, 4892 <1> ; / r2 has destination 4893 <1> ;mov rcsr(r1),(r2)+ / put reader control status 4894 <1> ; / in 1st word of dest 4895 <1> ;mov tcsr(r1),(r2)+ / put printer control status 4896 <1> ; / in 2nd word of dest 4897 <1> ;mov tty+4(r1),(r2)+ / put mode in 3rd word 4898 <1> ;jmp sysret2 / return to user 4899 <1> 4900 <1> ; Original UNIX v1 'gtty' routine: 4901 <1> ; gtty: 4902 <1> ;jsr r0,arg; u.off / put first arg in u.off 4903 <1> ;mov *u.r0,r1 / put file descriptor in r1 4904 <1> ;jsr r0,getf / get the i-number of the file 4905 <1> ;tst r1 / is it open for reading 4906 <1> ;bgt 1f / yes 4907 <1> ;neg r1 / no, i-number is negative, 4908 <1> ; / so make it positive 4909 <1> ;1: 4910 <1> ;sub $14.,r1 / get i-number of tty0 4911 <1> ;cmp r1,$ntty-1 / is there such a typewriter 4912 <1> ;bhis error9 / no, error 4913 <1> ;asl r1 / 0%2 4914 <1> ;asl r1 / 0%4 / yes 4915 <1> ;asl r1 / 0%8 / multiply by 8 so r1 points to 4916 <1> ; ; / tty block 4917 <1> ;mov u.off,r2 / put argument in r2 4918 <1> ;rts r0 / return 2115 %include 'u2.s' ; 11/05/2015 2116 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.3) - SYS2.INC 2117 <1> ; Last Modification: 15/05/2022 2118 <1> ; ---------------------------------------------------------------------------- 2119 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2120 <1> ; (v0.1 - Beginning: 11/07/2012) 2121 <1> ; 2122 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2123 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2124 <1> ; 2125 <1> ; 2126 <1> ; 2127 <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s 2128 <1> ; 2129 <1> ; **************************************************************************** 2130 <1> 2131 <1> syslink: 2132 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2133 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2134 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 2135 <1> ; 2136 <1> ; 'syslink' is given two arguments, name 1 and name 2. 2137 <1> ; name 1 is a file that already exists. name 2 is the name 2138 <1> ; given to the entry that will go in the current directory. 2139 <1> ; name2 will then be a link to the name 1 file. The i-number 2140 <1> ; in the name 2 entry of current directory is the same 2141 <1> ; i-number for the name 1 file. 2142 <1> ; 2143 <1> ; Calling sequence: 2144 <1> ; syslink; name 1; name 2 2145 <1> ; Arguments: 2146 <1> ; name 1 - file name to which link will be created. 2147 <1> ; name 2 - name of entry in current directory that 2148 <1> ; links to name 1. 2149 <1> ; Inputs: - 2150 <1> ; Outputs: - 2151 <1> ; ............................................................... 2152 <1> ; 2153 <1> ; Retro UNIX 8086 v1 modification: 2154 <1> ; 'syslink' system call has two arguments; so, 2155 <1> ; * 1st argument, name 1 is pointed to by BX register 2156 <1> ; * 2nd argument, name 2 is pointed to by CX register 2157 <1> ; 2158 <1> ; / name1, name2 2159 <1> ;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd 2160 0000397F 891D[04650000] <1> mov [u.namep], ebx 2161 00003985 51 <1> push ecx 2162 00003986 E84C060000 <1> call namei 2163 <1> ; jsr r0,namei / find the i-number associated with 2164 <1> ; / the 1st path name 2165 <1> ;;and ax, ax 2166 <1> ;;jz error ; File not found 2167 <1> ;jc error 2168 <1> ; br error9 / cannot be found 2169 0000398B 730F <1> jnc short syslink0 2170 <1> ;pop ecx 2171 <1> ; 'file not found !' error 2172 0000398D C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 2172 00003995 0000 <1> 2173 00003997 E92FF7FFFF <1> jmp error 2174 <1> syslink0: 2175 0000399C E8460E0000 <1> call iget 2176 <1> ; jsr r0,iget / get the i-node into core 2177 000039A1 8F05[04650000] <1> pop dword [u.namep] ; ecx 2178 <1> ; mov (sp)+,u.namep / u.namep points to 2nd name 2179 <1> ; 24/12/2021 2180 000039A7 50 <1> push eax ; * 2181 <1> ;push ax 2182 <1> ; mov r1,-(sp) / put i-number of name1 on the stack 2183 <1> ; / (a link to this file is to be created) 2184 <1> ; 24/12/2021 2185 000039A8 8A0D[D3640000] <1> mov cl, [cdev] 2186 000039AE 51 <1> push ecx ; ** 2187 <1> ;push word [cdev] 2188 <1> ; mov cdev,-(sp) / put i-nodes device on the stack 2189 000039AF E852000000 <1> call isdir 2190 <1> ; jsr r0,isdir / is it a directory 2191 000039B4 E81E060000 <1> call namei 2192 <1> ; jsr r0,namei / no, get i-number of name2 2193 <1> ;jnc error 2194 <1> ; br .+4 / not found 2195 <1> ; / so r1 = i-number of current directory 2196 <1> ; / ii = i-number of current directory 2197 <1> ; br error9 / file already exists., error 2198 000039B9 720F <1> jc short syslink1 2199 <1> ; pop eax ; 24/12/2021 2200 <1> ; pop eax 2201 <1> ; 'file exists !' error 2202 000039BB C705[41650000]0E00- <1> mov dword [u.error], ERR_FILE_EXISTS ; 14 2202 000039C3 0000 <1> 2203 000039C5 E901F7FFFF <1> jmp error 2204 <1> syslink1: 2205 <1> ;pop cx 2206 <1> ; 24/12/2021 2207 000039CA 59 <1> pop ecx ; ** 2208 <1> ;cmp cx, [cdev] 2209 000039CB 3A0D[D3640000] <1> cmp cl, [cdev] 2210 <1> ;jne error 2211 <1> ; cmp (sp)+,cdev / u.dirp now points to 2212 <1> ; / end of current directory 2213 <1> ; bne error9 2214 000039D1 740F <1> je short syslink2 2215 <1> ; 'not same drive !' error 2216 000039D3 C705[41650000]1500- <1> mov dword [u.error], ERR_DRV_NOT_SAME ; 21 2216 000039DB 0000 <1> 2217 000039DD E9E9F6FFFF <1> jmp error 2218 <1> syslink2: 2219 <1> ;pop eax ; 24/12/2021 2220 <1> ;push eax 2221 <1> ; 24/12/2021 2222 000039E2 8B0424 <1> mov eax, [esp] ; * 2223 000039E5 66A3[1E650000] <1> mov [u.dirbuf], ax 2224 <1> ; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf 2225 000039EB E89E000000 <1> call mkdir 2226 <1> ; jsr r0,mkdir / make directory entry for name2 2227 <1> ; / in current directory 2228 <1> ; 24/12/2021 2229 000039F0 58 <1> pop eax ; * 2230 <1> ;pop ax 2231 <1> ; mov (sp)+,r1 / r1 has i-number of name1 2232 000039F1 E8F10D0000 <1> call iget 2233 <1> ; jsr r0,iget / get i-node into core 2234 000039F6 FE05[E6610000] <1> inc byte [i.nlks] 2235 <1> ; incb i.nlks / add 1 to its number of links 2236 000039FC E8F00E0000 <1> call setimod 2237 <1> ; jsr r0,setimod / set the i-node modified flag 2238 00003A01 E9E5F6FFFF <1> jmp sysret 2239 <1> 2240 <1> isdir: 2241 <1> ; 03/02/2022 2242 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 2243 <1> ; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 2244 <1> ; 2245 <1> ; 'isdir' check to see if the i-node whose i-number is in r1 2246 <1> ; is a directory. If it is, an error occurs, because 'isdir' 2247 <1> ; called by syslink and sysunlink to make sure directories 2248 <1> ; are not linked. If the user is the super user (u.uid=0), 2249 <1> ; 'isdir' does not bother checking. The current i-node 2250 <1> ; is not disturbed. 2251 <1> ; 2252 <1> ; INPUTS -> 2253 <1> ; r1 - contains the i-number whose i-node is being checked. 2254 <1> ; u.uid - user id 2255 <1> ; OUTPUTS -> 2256 <1> ; r1 - contains current i-number upon exit 2257 <1> ; (current i-node back in core) 2258 <1> ; 2259 <1> ; ((AX = R1)) 2260 <1> ; 2261 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 2262 <1> ; 2263 <1> 2264 <1> ; / if the i-node whose i-number is in r1 is a directory 2265 <1> ; / there is an error unless super user made the call 2266 <1> 2267 00003A06 803D[38650000]00 <1> cmp byte [u.uid], 0 2268 <1> ; tstb u.uid / super user 2269 00003A0D 762B <1> jna short isdir1 2270 <1> ; beq 1f / yes, don't care 2271 00003A0F 66FF35[D0640000] <1> push word [ii] 2272 <1> ; mov ii,-(sp) / put current i-number on stack 2273 00003A16 E8CC0D0000 <1> call iget 2274 <1> ; jsr r0,iget / get i-node into core (i-number in r1) 2275 <1> ; 03/02/2022 2276 00003A1B F605[E5610000]40 <1> test byte [i.flgs+1], 40h 2277 <1> ;test word [i.flgs], 4000h ; Bit 14 : Directory flag 2278 <1> ; bit $40000,i.flgs / is it a directory 2279 <1> ;jnz error 2280 <1> ; bne error9 / yes, error 2281 00003A22 740F <1> jz short isdir0 2282 00003A24 C705[41650000]0B00- <1> mov dword [u.error], ERR_NOT_FILE ; 11 ; ERR_DIR_ACCESS 2282 00003A2C 0000 <1> 2283 <1> ; 'permission denied !' error 2284 <1> ; pop ax 2285 00003A2E E998F6FFFF <1> jmp error 2286 <1> isdir0: 2287 00003A33 6658 <1> pop ax 2288 <1> ; mov (sp)+,r1 / no, put current i-number in r1 (ii) 2289 00003A35 E8AD0D0000 <1> call iget 2290 <1> ; jsr r0,iget / get it back in 2291 <1> isdir1: ; 1: 2292 00003A3A C3 <1> retn 2293 <1> ; rts r0 2294 <1> 2295 <1> sysunlink: 2296 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2297 <1> ; 04/12/2015 (14 byte file names) 2298 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2299 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 2300 <1> ; 2301 <1> ; 'sysunlink' removes the entry for the file pointed to by 2302 <1> ; name from its directory. If this entry was the last link 2303 <1> ; to the file, the contents of the file are freed and the 2304 <1> ; file is destroyed. If, however, the file was open in any 2305 <1> ; process, the actual destruction is delayed until it is 2306 <1> ; closed, even though the directory entry has disappeared. 2307 <1> ; 2308 <1> ; The error bit (e-bit) is set to indicate that the file 2309 <1> ; does not exist or that its directory can not be written. 2310 <1> ; Write permission is not required on the file itself. 2311 <1> ; It is also illegal to unlink a directory (except for 2312 <1> ; the superuser). 2313 <1> ; 2314 <1> ; Calling sequence: 2315 <1> ; sysunlink; name 2316 <1> ; Arguments: 2317 <1> ; name - name of directory entry to be removed 2318 <1> ; Inputs: - 2319 <1> ; Outputs: - 2320 <1> ; ............................................................... 2321 <1> ; 2322 <1> ; Retro UNIX 8086 v1 modification: 2323 <1> ; The user/application program puts address of the name 2324 <1> ; in BX register as 'sysunlink' system call argument. 2325 <1> 2326 <1> ; / name - remove link name 2327 00003A3B 891D[04650000] <1> mov [u.namep], ebx 2328 <1> ;jsr r0,arg; u.namep / u.namep points to name 2329 00003A41 E891050000 <1> call namei 2330 <1> ; jsr r0,namei / find the i-number associated 2331 <1> ; / with the path name 2332 <1> ;jc error 2333 <1> ; br error9 / not found 2334 00003A46 730F <1> jnc short sysunlink1 2335 <1> ; 'file not found !' error 2336 00003A48 C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 2336 00003A50 0000 <1> 2337 00003A52 E974F6FFFF <1> jmp error 2338 <1> sysunlink1: 2339 00003A57 50 <1> push eax ; 24/12/2021 2340 <1> ;push ax 2341 <1> ; mov r1,-(sp) / put its i-number on the stack 2342 00003A58 E8A9FFFFFF <1> call isdir 2343 <1> ; jsr r0,isdir / is it a directory 2344 <1> ;xor ax, ax 2345 <1> ; 24/12/2021 2346 00003A5D 31C0 <1> xor eax, eax 2347 00003A5F 66A3[1E650000] <1> mov [u.dirbuf], ax ; 0 2348 <1> ; clr u.dirbuf / no, clear the location that will 2349 <1> ; / get written into the i-number portion 2350 <1> ; / of the entry 2351 00003A65 832D[08650000]10 <1> sub dword [u.off], 16 ; 04/12/2015 (10 -> 16) 2352 <1> ; sub $10.,u.off / move u.off back 1 directory entry 2353 00003A6C E868000000 <1> call wdir 2354 <1> ; jsr r0,wdir / free the directory entry 2355 00003A71 58 <1> pop eax ; 24/12/2021 2356 <1> ;pop ax 2357 <1> ; mov (sp)+,r1 / get i-number back 2358 00003A72 E8700D0000 <1> call iget 2359 <1> ; jsr r0,iget / get i-node 2360 00003A77 E8750E0000 <1> call setimod 2361 <1> ; jsr r0,setimod / set modified flag 2362 00003A7C FE0D[E6610000] <1> dec byte [i.nlks] 2363 <1> ; decb i.nlks / decrement the number of links 2364 <1> ; 24/12/2021 2365 00003A82 7505 <1> jnz short sysunlink_2 2366 <1> ;jnz sysret 2367 <1> ; bgt sysret9 / if this was not the last link 2368 <1> ; / to file return 2369 <1> ; AX = r1 = i-number 2370 00003A84 E8B3090000 <1> call anyi 2371 <1> ; jsr r0,anyi / if it was, see if anyone has it open. 2372 <1> ; / Then free contents of file and destroy it. 2373 <1> sysunlink_2: 2374 00003A89 E95DF6FFFF <1> jmp sysret 2375 <1> ; br sysret9 2376 <1> 2377 <1> mkdir: 2378 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2379 <1> ; 04/12/2015 (14 byte directory names) 2380 <1> ; 12/10/2015 2381 <1> ; 17/06/2015 (Retro UNIX 386 v1 - Beginning) 2382 <1> ; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2383 <1> ; 2384 <1> ; 'mkdir' makes a directory entry from the name pointed to 2385 <1> ; by u.namep into the current directory. 2386 <1> ; 2387 <1> ; INPUTS -> 2388 <1> ; u.namep - points to a file name 2389 <1> ; that is about to be a directory entry. 2390 <1> ; ii - current directory's i-number. 2391 <1> ; OUTPUTS -> 2392 <1> ; u.dirbuf+2 - u.dirbuf+10 - contains file name. 2393 <1> ; u.off - points to entry to be filled 2394 <1> ; in the current directory 2395 <1> ; u.base - points to start of u.dirbuf. 2396 <1> ; r1 - contains i-number of current directory 2397 <1> ; 2398 <1> ; ((AX = R1)) output 2399 <1> ; 2400 <1> ; (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM) 2401 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 2402 <1> ; 2403 <1> 2404 <1> ; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 2405 00003A8E 31C0 <1> xor eax, eax 2406 00003A90 BF[20650000] <1> mov edi, u.dirbuf+2 2407 00003A95 89FE <1> mov esi, edi 2408 00003A97 AB <1> stosd 2409 00003A98 AB <1> stosd 2410 <1> ; 04/12/2015 (14 byte directory names) 2411 00003A99 AB <1> stosd 2412 00003A9A 66AB <1> stosw 2413 <1> ; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this 2414 00003A9C 89F7 <1> mov edi, esi ; offset to u.dirbuf 2415 <1> ; 12/10/2015 ([u.namep] -> ebp) 2416 <1> ;mov ebp, [u.namep] 2417 00003A9E E8B3060000 <1> call trans_addr_nmbp ; convert virtual address to physical 2418 <1> ; esi = physical address (page start + offset) 2419 <1> ; ecx = byte count in the page (1 - 4096) 2420 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 2421 <1> ; mov u.namep,r2 / r2 points to name of directory entry 2422 <1> ; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 2423 <1> mkdir_1: ; 1: 2424 00003AA3 45 <1> inc ebp ; 12/10/2015 2425 <1> ; 2426 <1> ; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 2427 <1> ; 01/08/2013 2428 00003AA4 AC <1> lodsb 2429 <1> ; movb (r2)+,r1 / move character in name to r1 2430 00003AA5 20C0 <1> and al, al 2431 00003AA7 7426 <1> jz short mkdir_3 2432 <1> ; beq 1f / if null, done 2433 00003AA9 3C2F <1> cmp al, '/' 2434 <1> ; cmp r1,$'/ / is it a "/"? 2435 00003AAB 7413 <1> je short mkdir_err 2436 <1> ;je error 2437 <1> ; beq error9 / yes, error 2438 <1> ; 12/10/2015 2439 <1> ;dec cx 2440 00003AAD 49 <1> dec ecx ; 24/12/2021 2441 00003AAE 7505 <1> jnz short mkdir_2 2442 <1> ; 12/10/2015 ([u.namep] -> ebp) 2443 00003AB0 E8A7060000 <1> call trans_addr_nm ; convert virtual address to physical 2444 <1> ; esi = physical address (page start + offset) 2445 <1> ; ecx = byte count in the page 2446 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 2447 <1> mkdir_2: 2448 00003AB5 81FF[2E650000] <1> cmp edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 2449 <1> ; cmp r3,$u.dirbuf+10. / have we reached the last slot for 2450 <1> ; / a char? 2451 00003ABB 74E6 <1> je short mkdir_1 2452 <1> ; beq 1b / yes, go back 2453 00003ABD AA <1> stosb 2454 <1> ; movb r1,(r3)+ / no, put the char in the u.dirbuf 2455 00003ABE EBE3 <1> jmp short mkdir_1 2456 <1> ; br 1b / get next char 2457 <1> mkdir_err: 2458 <1> ; 17/06/2015 2459 00003AC0 C705[41650000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 2459 00003AC8 0000 <1> 2460 00003ACA E9FCF5FFFF <1> jmp error 2461 <1> 2462 <1> mkdir_3: ; 1: 2463 00003ACF A1[00650000] <1> mov eax, [u.dirp] 2464 00003AD4 A3[08650000] <1> mov [u.off], eax 2465 <1> ; mov u.dirp,u.off / pointer to empty current directory 2466 <1> ; / slot to u.off 2467 <1> wdir: ; 24/12/2021 (Retro UNIX 386 v1.1) 2468 <1> ; 29/04/2013 2469 00003AD9 C705[0C650000]- <1> mov dword [u.base], u.dirbuf 2469 00003ADF [1E650000] <1> 2470 <1> ; mov $u.dirbuf,u.base / u.base points to created file name 2471 00003AE3 C705[10650000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 2471 00003AEB 0000 <1> 2472 <1> ; mov $10.,u.count / u.count = 10 2473 00003AED 66A1[D0640000] <1> mov ax, [ii] 2474 <1> ; mov ii,r1 / r1 has i-number of current directory 2475 00003AF3 B201 <1> mov dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification ! 2476 00003AF5 E8C10D0000 <1> call access 2477 <1> ; jsr r0,access; 1 / get i-node and set its file up 2478 <1> ; / for writing 2479 <1> ; AX = i-number of current directory 2480 <1> ; 01/08/2013 2481 00003AFA FE05[53650000] <1> inc byte [u.kcall] ; the caller is 'mkdir' sign 2482 <1> ;call writei 2483 <1> ; ; jsr r0,writei / write into directory 2484 <1> ;retn 2485 <1> ; ; rts r0 2486 <1> ; 24/12/2021 2487 00003B00 E9A8100000 <1> jmp writei 2488 <1> 2489 <1> sysexec: 2490 <1> ; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3) 2491 <1> ; 03/02/2022 2492 <1> ; 12/01/2022 2493 <1> ; 08/01/2022 2494 <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2495 <1> ; 23/10/2015 2496 <1> ; 19/10/2015 2497 <1> ; 10/10/2015, 18/10/2015 2498 <1> ; 29/07/2015, 05/08/2015, 26/08/2015 2499 <1> ; 21/07/2015, 24/07/2015, 25/07/2015 2500 <1> ; 01/07/2015, 02/07/2015, 20/07/2015 2501 <1> ; 24/06/2015, 25/06/2015 2502 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 2503 <1> ; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2504 <1> ; 2505 <1> ; 'sysexec' initiates execution of a file whose path name if 2506 <1> ; pointed to by 'name' in the sysexec call. 2507 <1> ; 'sysexec' performs the following operations: 2508 <1> ; 1. obtains i-number of file to be executed via 'namei'. 2509 <1> ; 2. obtains i-node of file to be exceuted via 'iget'. 2510 <1> ; 3. sets trap vectors to system routines. 2511 <1> ; 4. loads arguments to be passed to executing file into 2512 <1> ; highest locations of user's core 2513 <1> ; 5. puts pointers to arguments in locations immediately 2514 <1> ; following arguments. 2515 <1> ; 6. saves number of arguments in next location. 2516 <1> ; 7. initializes user's stack area so that all registers 2517 <1> ; will be zeroed and the PS is cleared and the PC set 2518 <1> ; to core when 'sysret' restores registers 2519 <1> ; and does an rti. 2520 <1> ; 8. inializes u.r0 and u.sp 2521 <1> ; 9. zeros user's core down to u.r0 2522 <1> ; 10. reads executable file from storage device into core 2523 <1> ; starting at location 'core'. 2524 <1> ; 11. sets u.break to point to end of user's code with 2525 <1> ; data area appended. 2526 <1> ; 12. calls 'sysret' which returns control at location 2527 <1> ; 'core' via 'rti' instruction. 2528 <1> ; 2529 <1> ; Calling sequence: 2530 <1> ; sysexec; namep; argp 2531 <1> ; Arguments: 2532 <1> ; namep - points to pathname of file to be executed 2533 <1> ; argp - address of table of argument pointers 2534 <1> ; argp1... argpn - table of argument pointers 2535 <1> ; argp1:<...0> ... argpn:<...0> - argument strings 2536 <1> ; Inputs: (arguments) 2537 <1> ; Outputs: - 2538 <1> ; ............................................................... 2539 <1> ; 2540 <1> ; Retro UNIX 386 v1 modification: 2541 <1> ; User application runs in it's own virtual space 2542 <1> ; which is izolated from kernel memory (and other 2543 <1> ; memory pages) via 80386 paging in ring 3 2544 <1> ; privilige mode. Virtual start address is always 0. 2545 <1> ; User's core memory starts at linear address 400000h 2546 <1> ; (the end of the 1st 4MB). 2547 <1> ; 2548 <1> ; Retro UNIX 8086 v1 modification: 2549 <1> ; user/application segment and system/kernel segment 2550 <1> ; are different and sysenter/sysret/sysrele routines 2551 <1> ; are different (user's registers are saved to 2552 <1> ; and then restored from system's stack.) 2553 <1> ; 2554 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 2555 <1> ; arguments which were in these registers; 2556 <1> ; but, it returns by putting the 1st argument 2557 <1> ; in 'u.namep' and the 2nd argument 2558 <1> ; on top of stack. (1st argument is offset of the 2559 <1> ; file/path name in the user's program segment.) 2560 <1> 2561 <1> ;call arg2 2562 <1> ; * name - 'u.namep' points to address of file/path name 2563 <1> ; in the user's program segment ('u.segmnt') 2564 <1> ; with offset in BX register (as sysopen argument 1). 2565 <1> ; * argp - sysexec argument 2 is in CX register 2566 <1> ; which is on top of stack. 2567 <1> ; 2568 <1> ; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack 2569 <1> 2570 <1> ; 23/06/2015 (32 bit modifications) 2571 <1> 2572 00003B05 891D[04650000] <1> mov [u.namep], ebx ; argument 1 2573 <1> ; 18/10/2015 2574 00003B0B 890D[6C650000] <1> mov [argv], ecx ; * ; argument 2 2575 00003B11 E8C1040000 <1> call namei 2576 <1> ; jsr r0,namei / namei returns i-number of file 2577 <1> ; / named in sysexec call in r1 2578 <1> ;jc error 2579 <1> ; br error9 2580 00003B16 731E <1> jnc short sysexec_0 2581 <1> ; 2582 <1> ; 'file not found !' error 2583 00003B18 C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND 2583 00003B20 0000 <1> 2584 00003B22 E9A4F5FFFF <1> jmp error 2585 <1> sysexec_not_exf: 2586 <1> ; 'not executable file !' error 2587 00003B27 C705[41650000]1600- <1> mov dword [u.error], ERR_NOT_EXECUTABLE 2587 00003B2F 0000 <1> 2588 00003B31 E995F5FFFF <1> jmp error 2589 <1> sysexec_0: 2590 00003B36 E8AC0C0000 <1> call iget 2591 <1> ; jsr r0,iget / get i-node for file to be executed 2592 <1> ; 24/12/2021 2593 00003B3B F605[E4610000]10 <1> test byte [i.flgs], 10h 2594 <1> ;test word [i.flgs], 10h 2595 <1> ; ; bit $20,i.flgs / is file executable 2596 00003B42 74E3 <1> jz short sysexec_not_exf 2597 <1> ;jz error 2598 <1> ; beq error9 2599 <1> ;; 2600 00003B44 E802150000 <1> call iopen 2601 <1> ; jsr r0,iopen / gets i-node for file with i-number 2602 <1> ; / given in r1 (opens file) 2603 <1> ; AX = i-number of the file 2604 <1> ; 24/12/2021 2605 00003B49 F605[E4610000]20 <1> test byte [i.flgs], 20h 2606 <1> ;test word [i.flgs], 20h 2607 <1> ; bit $40,i.flgs / test user id on execution bit 2608 00003B50 7415 <1> jz short sysexec_1 2609 <1> ; beq 1f 2610 00003B52 803D[38650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 2611 <1> ; tstb u.uid / test user id 2612 00003B59 760C <1> jna short sysexec_1 2613 <1> ; beq 1f / super user 2614 00003B5B 8A0D[E7610000] <1> mov cl, [i.uid] 2615 00003B61 880D[38650000] <1> mov [u.uid], cl ; 02/08/2013 2616 <1> ; movb i.uid,u.uid / put user id of owner of file 2617 <1> ; / as process user id 2618 <1> sysexec_1: 2619 <1> ; 03/02/2022 2620 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2621 <1> ; 18/10/2215 2622 <1> ; 10/10/2015 2623 <1> ; 21/07/2015, 24/07/2015 2624 <1> ; 24/06/2015, 25/06/2015 2625 <1> ; Moving arguments to the end of [u.upage] 2626 <1> ; (by regarding page borders in user's memory space) 2627 <1> ; 2628 <1> ; 10/10/2015 2629 <1> ; 21/07/2015 2630 00003B67 89E5 <1> mov ebp, esp ; (**) 2631 <1> ; 18/10/2015 2632 00003B69 89EF <1> mov edi, ebp 2633 00003B6B B900010000 <1> mov ecx, MAX_ARG_LEN ; 256 2634 <1> ;sub edi, MAX_ARG_LEN ; 256 2635 00003B70 29CF <1> sub edi, ecx 2636 00003B72 89FC <1> mov esp, edi 2637 00003B74 31C0 <1> xor eax, eax 2638 00003B76 A3[14650000] <1> mov [u.nread], eax ; 0 2639 <1> ; 12/01/2022 2640 <1> ; ([argc] must be cleared because previous 'sysexec' 2641 <1> ; may leave it with any value after an error)) 2642 <1> ;mov [argc], ax 2643 00003B7B A2[6A650000] <1> mov [argc], al ; 0 2644 <1> ; 2645 00003B80 49 <1> dec ecx ; 256 - 1 2646 00003B81 890D[10650000] <1> mov [u.count], ecx ; MAX_ARG_LEN - 1 ; 255 2647 <1> ;mov dword [u.count], MAX_ARG_LEN - 1 ; 255 2648 <1> sysexec_2: 2649 00003B87 8B35[6C650000] <1> mov esi, [argv] ; 18/10/2015 2650 00003B8D E863020000 <1> call get_argp 2651 <1> ;mov ecx, 4 2652 <1> ; 03/02/2022 2653 00003B92 31C9 <1> xor ecx, ecx 2654 00003B94 B104 <1> mov cl, 4 2655 <1> sysexec_3: 2656 00003B96 21C0 <1> and eax, eax 2657 00003B98 7455 <1> jz short sysexec_6 2658 <1> ; 18/10/2015 2659 00003B9A 010D[6C650000] <1> add [argv], ecx ; 4 2660 <1> ;inc word [argc] 2661 <1> ; 12/01/2022 ; ([argc] < 32) 2662 00003BA0 FE05[6A650000] <1> inc byte [argc] 2663 <1> ; 2664 00003BA6 A3[0C650000] <1> mov [u.base], eax 2665 <1> ; 23/10/2015 2666 00003BAB 66C705[51650000]00- <1> mov word [u.pcount], 0 2666 00003BB3 00 <1> 2667 <1> sysexec_4: 2668 00003BB4 E826120000 <1> call cpass ; get a character from user's core memory 2669 00003BB9 750B <1> jnz short sysexec_5 2670 <1> ; (max. 255 chars + null) 2671 <1> ; 18/10/2015 2672 00003BBB 28C0 <1> sub al, al 2673 00003BBD AA <1> stosb 2674 00003BBE FF05[14650000] <1> inc dword [u.nread] 2675 00003BC4 EB29 <1> jmp short sysexec_6 2676 <1> sysexec_5: 2677 00003BC6 AA <1> stosb 2678 00003BC7 20C0 <1> and al, al 2679 00003BC9 75E9 <1> jnz short sysexec_4 2680 <1> ;mov ecx, 4 2681 <1> ; 24/12/2021 2682 00003BCB 29C9 <1> sub ecx, ecx 2683 00003BCD B104 <1> mov cl, 4 2684 <1> ;cmp [ncount], ecx ; 4 2685 <1> ; 24/12/2021 2686 00003BCF 66390D[68650000] <1> cmp [ncount], cx ; 4 2687 00003BD6 72AF <1> jb short sysexec_2 2688 00003BD8 8B35[64650000] <1> mov esi, [nbase] 2689 00003BDE 010D[64650000] <1> add [nbase], ecx ; 4 2690 00003BE4 66290D[68650000] <1> sub [ncount], cx 2691 00003BEB 8B06 <1> mov eax, [esi] 2692 00003BED EBA7 <1> jmp short sysexec_3 2693 <1> sysexec_6: 2694 <1> ; 18/10/2015 2695 <1> ; argument list transfer from user's core memory to 2696 <1> ; kernel stack frame is OK here. 2697 <1> ; [u.nread] = ; argument list length 2698 <1> ;mov [argv], esp ; start address of argument list 2699 <1> ; 2700 <1> ; 18/10/2015 2701 <1> ; 24/07/2015 2702 <1> ; 21/07/2015 2703 <1> ; 02/07/2015 2704 <1> ; 25/06/2015 2705 <1> ; 24/06/2015 2706 <1> ; 23/06/2015 2707 <1> ; 2708 00003BEF 8B1D[49650000] <1> mov ebx, [u.ppgdir] ; parent's page directory 2709 00003BF5 21DB <1> and ebx, ebx ; /etc/init ? (u.ppgdir = 0) 2710 00003BF7 740A <1> jz short sysexec_7 2711 00003BF9 A1[45650000] <1> mov eax, [u.pgdir] ; physical address of page directory 2712 00003BFE E8EEE8FFFF <1> call deallocate_page_dir 2713 <1> sysexec_7: 2714 00003C03 E81EE8FFFF <1> call make_page_dir 2715 <1> ;jc short sysexec_14 2716 <1> ;jc panic ; allocation error 2717 <1> ; after a deallocation would be nonsence !? 2718 <1> ; 08/01/2022 2719 00003C08 7243 <1> jc short sysexec_panic 2720 <1> 2721 <1> ; 24/07/2015 2722 <1> ; map kernel pages (1st 4MB) to PDE 0 2723 <1> ; of the user's page directory 2724 <1> ; (It is needed for interrupts!) 2725 <1> ; 18/10/2015 2726 00003C0A 8B15[28610000] <1> mov edx, [k_page_dir] ; Kernel's page directory 2727 00003C10 8B02 <1> mov eax, [edx] ; physical address of 2728 <1> ; kernel's first page table (1st 4 MB) 2729 <1> ; (PDE 0 of kernel's page directory) 2730 00003C12 8B15[45650000] <1> mov edx, [u.pgdir] 2731 00003C18 8902 <1> mov [edx], eax ; PDE 0 (1st 4MB) 2732 <1> ; 2733 <1> ; 20/07/2015 2734 00003C1A BB00004000 <1> mov ebx, CORE ; start address = 0 (virtual) + CORE 2735 <1> ; 18/10/2015 2736 00003C1F BE[5C650000] <1> mov esi, pcore ; physical start address 2737 <1> sysexec_8: 2738 00003C24 B907000000 <1> mov ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT 2739 00003C29 E816E8FFFF <1> call make_page_table 2740 <1> ;jc panic 2741 <1> ; 24/12/2021 2742 00003C2E 721D <1> jc short sysexec_panic 2743 <1> ;mov ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT 2744 00003C30 E81DE8FFFF <1> call make_page ; make new page, clear and set the pte 2745 <1> ;jc panic 2746 <1> ; 24/12/2021 2747 00003C35 7216 <1> jc short sysexec_panic 2748 <1> ; 2749 00003C37 8906 <1> mov [esi], eax ; 24/06/2015 2750 <1> ; ebx = virtual address (24/07/2015) 2751 <1> ; 24/12/2021 2752 <1> ;call add_to_swap_queue 2753 <1> ; 18/10/2015 2754 00003C39 81FE[60650000] <1> cmp esi, ecore ; user's stack (last) page ? 2755 00003C3F 7411 <1> je short sysexec_9 ; yes 2756 00003C41 BE[60650000] <1> mov esi, ecore ; physical address of the last page 2757 <1> ; 20/07/2015 2758 00003C46 BB00F0FFFF <1> mov ebx, (ECORE - PAGE_SIZE) + CORE 2759 <1> ; ebx = virtual end address + segment base address - 4K 2760 00003C4B EBD7 <1> jmp short sysexec_8 2761 <1> 2762 <1> sysexec_panic: 2763 <1> ; 26/03/2021 2764 00003C4D E93BEDFFFF <1> jmp panic 2765 <1> 2766 <1> sysexec_9: 2767 <1> ; 18/10/2015 2768 <1> ; 26/08/2015 2769 <1> ; 25/06/2015 2770 <1> ; move arguments from kernel stack to [ecore] 2771 <1> ; (argument list/line will be copied from kernel stack 2772 <1> ; frame to the last (stack) page of user's core memory) 2773 <1> ; 18/10/2015 2774 00003C52 8B3D[60650000] <1> mov edi, [ecore] 2775 00003C58 81C700100000 <1> add edi, PAGE_SIZE 2776 <1> ;movzx eax, word [argc] 2777 <1> ; 12/01/2022 2778 00003C5E 31C0 <1> xor eax, eax 2779 00003C60 A0[6A650000] <1> mov al, [argc] 2780 00003C65 08C0 <1> or al, al 2781 <1> ;or eax, eax 2782 00003C67 7509 <1> jnz short sysexec_10 2783 00003C69 89FB <1> mov ebx, edi 2784 00003C6B 83EB04 <1> sub ebx, 4 2785 00003C6E 8903 <1> mov [ebx], eax ; 0 2786 00003C70 EB43 <1> jmp short sysexec_13 2787 <1> sysexec_10: 2788 00003C72 8B0D[14650000] <1> mov ecx, [u.nread] 2789 <1> ;mov esi, [argv] 2790 00003C78 89E6 <1> mov esi, esp ; start address of argument list 2791 00003C7A 29CF <1> sub edi, ecx ; page end address - argument list length 2792 <1> 2793 <1> ;;;; 2794 <1> ; 09/05/2022 2795 <1> ; (move edi -backward- to dword boundary) 2796 <1> ; ((this will prevent 'general protection fault' error 2797 <1> ; as result of a lodsd or dword move instruction 2798 <1> ; at the end of argument list)) 2799 00003C7C 83EF03 <1> sub edi, 3 2800 00003C7F 83E7FC <1> and edi, ~3 ; (*) 2801 <1> ;;; 2802 <1> 2803 00003C82 89C2 <1> mov edx, eax 2804 <1> ; 03/02/2022 ; ([argc] < 32) 2805 00003C84 FEC2 <1> inc dl ; argument count + 1 for argc value 2806 00003C86 C0E202 <1> shl dl, 2 ; 4 * (argument count + 1) 2807 <1> ; edx <= 128 2808 00003C89 89FB <1> mov ebx, edi 2809 <1> ; 09/05/2022 (*) - edi is already dword aligned - 2810 <1> ;and bl, 0FCh ; 32 bit (dword) alignment 2811 00003C8B 29D3 <1> sub ebx, edx 2812 00003C8D 89FA <1> mov edx, edi 2813 00003C8F F3A4 <1> rep movsb 2814 00003C91 89D6 <1> mov esi, edx 2815 00003C93 89DF <1> mov edi, ebx 2816 00003C95 BA00F0BFFF <1> mov edx, ECORE - PAGE_SIZE ; virtual addr. of the last page 2817 00003C9A 2B15[60650000] <1> sub edx, [ecore] ; difference (virtual - physical) 2818 00003CA0 AB <1> stosd ; eax = argument count 2819 <1> sysexec_11: 2820 00003CA1 89F0 <1> mov eax, esi 2821 00003CA3 01D0 <1> add eax, edx 2822 00003CA5 AB <1> stosd ; eax = virtual address 2823 00003CA6 FE0D[6A650000] <1> dec byte [argc] 2824 00003CAC 7407 <1> jz short sysexec_13 2825 <1> sysexec_12: 2826 00003CAE AC <1> lodsb 2827 00003CAF 20C0 <1> and al, al 2828 00003CB1 75FB <1> jnz short sysexec_12 2829 00003CB3 EBEC <1> jmp short sysexec_11 2830 <1> ; 2831 <1> ; 1: 2832 <1> ; mov (sp)+,r5 / r5 now contains address of list of 2833 <1> ; / pointers to arguments to be passed 2834 <1> ; mov $1,u.quit / u.quit determines handling of quits; 2835 <1> ; / u.quit = 1 take quit 2836 <1> ; mov $1,u.intr / u.intr determines handling of 2837 <1> ; / interrupts; u.intr = 1 take interrupt 2838 <1> ; mov $rtssym,30 / emt trap vector set to take 2839 <1> ; / system routine 2840 <1> ; mov $fpsym,*10 / reserved instruction trap vector 2841 <1> ; / set to take system routine 2842 <1> ; mov $sstack,sp / stack space used during swapping 2843 <1> ; mov r5,-(sp) / save arguments pointer on stack 2844 <1> ; mov $ecore,r5 / r5 has end of core 2845 <1> ; mov $core,r4 / r4 has start of users core 2846 <1> ; mov r4,u.base / u.base has start of users core 2847 <1> ; mov (sp),r2 / move arguments list pointer into r2 2848 <1> ; 1: 2849 <1> ; tst (r2)+ / argument char = "nul" 2850 <1> ; bne 1b 2851 <1> ; tst -(r2) / decrement r2 by 2; r2 has addr of 2852 <1> ; / end of argument pointer list 2853 <1> ; 1: 2854 <1> ; / move arguments to bottom of users core 2855 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 2856 <1> ; cmp r2,(sp) / is r2 = beginning of argument 2857 <1> ; / ptr list 2858 <1> ; blo 1f / branch to 1f when all arguments 2859 <1> ; / are moved 2860 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 2861 <1> ; 2: 2862 <1> ; tstb (r3)+ 2863 <1> ; bne 2b / scan argument for \0 (nul) 2864 <1> 2865 <1> ; 2: 2866 <1> ; movb -(r3),-(r5) / move argument char 2867 <1> ; / by char starting at "ecore" 2868 <1> ; cmp r3,(r2) / moved all characters in 2869 <1> ; / this argument 2870 <1> ; bhi 2b / branch 2b if not 2871 <1> ; mov r5,(r4)+ / move r5 into top of users core; 2872 <1> ; / r5 has pointer to nth arg 2873 <1> ; br 1b / string 2874 <1> ; 1: 2875 <1> ; clrb -(r5) 2876 <1> ; bic $1,r5 / make r5 even, r5 points to 2877 <1> ; / last word of argument strings 2878 <1> ; mov $core,r2 2879 <1> 2880 <1> ; 1: / move argument pointers into core following 2881 <1> ; / argument strings 2882 <1> ; cmp r2,r4 2883 <1> ; bhis 1f / branch to 1f when all pointers 2884 <1> ; / are moved 2885 <1> ; mov (r2)+,-(r5) 2886 <1> ; br 1b 2887 <1> ; 1: 2888 <1> ; sub $core,r4 / gives number of arguments *2 2889 <1> ; asr r4 / divide r4 by 2 to calculate 2890 <1> ; / the number of args stored 2891 <1> ; mov r4,-(r5) / save number of arguments ahead 2892 <1> ; / of the argument pointers 2893 <1> sysexec_13: 2894 <1> ; 19/10/2015 2895 <1> ; 18/10/2015 2896 <1> ; 29/07/2015 2897 <1> ; 25/07/2015 2898 <1> ; 24/07/2015 2899 <1> ; 20/07/2015 2900 <1> ; 25/06/2015 2901 <1> ; 24/06/2015 2902 <1> ; 23/06/2015 2903 <1> ; 2904 <1> ; moving arguments to [ecore] is OK here.. 2905 <1> ; 18/10/2015 2906 00003CB5 89EC <1> mov esp, ebp ; (**) restore kernel stack pointer 2907 <1> ; ebx = beginning addres of argument list pointers 2908 <1> ; in user's stack 2909 <1> ; 19/10/2015 2910 00003CB7 2B1D[60650000] <1> sub ebx, [ecore] 2911 00003CBD 81C300F0BFFF <1> add ebx, (ECORE - PAGE_SIZE) 2912 <1> ; end of core - 4096 (last page) 2913 <1> ; (virtual address) 2914 00003CC3 891D[6C650000] <1> mov [argv], ebx 2915 00003CC9 891D[18650000] <1> mov [u.break], ebx ; available user memory 2916 <1> ; 2917 00003CCF 29C0 <1> sub eax, eax 2918 00003CD1 C705[10650000]2000- <1> mov dword [u.count], 32 ; Executable file header size 2918 00003CD9 0000 <1> 2919 <1> ; mov $14,u.count 2920 00003CDB C705[FC640000]- <1> mov dword [u.fofp], u.off 2920 00003CE1 [08650000] <1> 2921 <1> ; mov $u.off,u.fofp 2922 00003CE5 A3[08650000] <1> mov [u.off], eax ; 0 2923 <1> ; clr u.off / set offset in file to be read to zero 2924 <1> ; 25/07/2015 2925 00003CEA A3[0C650000] <1> mov [u.base], eax ; 0, start of user's core (virtual) 2926 <1> ; 25/06/2015 2927 00003CEF 66A1[D0640000] <1> mov ax, [ii] 2928 <1> ; AX = i-number of the executable file 2929 00003CF5 E8C10C0000 <1> call readi 2930 <1> ; jsr r0,readi / read in first six words of 2931 <1> ; / user's file, starting at $core 2932 <1> ; mov sp,r5 / put users stack address in r5 2933 <1> ; sub $core+40.,r5 / subtract $core +40, 2934 <1> ; / from r5 (leaves number of words 2935 <1> ; / less 26 available for 2936 <1> ; / program in user core 2937 <1> ; mov r5,u.count / 2938 <1> ; 25/06/2015 2939 00003CFA 8B0D[18650000] <1> mov ecx, [u.break] ; top of user's stack (physical addr.) 2940 00003D00 890D[10650000] <1> mov [u.count], ecx ; save for overrun check 2941 <1> ; 2942 00003D06 8B0D[14650000] <1> mov ecx, [u.nread] 2943 00003D0C 890D[18650000] <1> mov [u.break], ecx ; virtual address (offset from start) 2944 00003D12 80F920 <1> cmp cl, 32 2945 00003D15 7540 <1> jne short sysexec_15 2946 <1> ;: 2947 <1> ; 25/06/2015 2948 <1> ; Retro UNIX 386 v1 (32 bit) executable file header format 2949 <1> ; 18/10/2015 2950 00003D17 8B35[5C650000] <1> mov esi, [pcore] ; start address of user's core memory 2951 <1> ; (phys. start addr. of the exec. file) 2952 00003D1D AD <1> lodsd 2953 00003D1E 663DEB1E <1> cmp ax, 1EEBh ; EBH, 1Eh -> jump to +32 2954 00003D22 7533 <1> jne short sysexec_15 2955 <1> ; cmp core,$405 / br .+14 is first instruction 2956 <1> ; / if file is standard a.out format 2957 <1> ; bne 1f / branch, if not standard format 2958 00003D24 AD <1> lodsd 2959 00003D25 89C1 <1> mov ecx, eax ; text (code) section size 2960 00003D27 AD <1> lodsd 2961 00003D28 01C1 <1> add ecx, eax ; + data section size (initialized data) 2962 <1> ; mov core+2,r5 / put 2nd word of users program in r5; 2963 <1> ; / number of bytes in program text 2964 <1> ; sub $14,r5 / subtract 12 2965 00003D2A 89CB <1> mov ebx, ecx 2966 <1> ; 2967 <1> ; 25/06/2015 2968 <1> ; NOTE: These are for next versions of Retro UNIX 386 2969 <1> ; and SINGLIX operating systems (as code template). 2970 <1> ; Current Retro UNIX 386 v1 files can be max. 64KB 2971 <1> ; due to RUFS (floppy disk file system) restriction... 2972 <1> ; Overrun is not possible for current version. 2973 <1> ; 2974 00003D2C AD <1> lodsd 2975 00003D2D 01C3 <1> add ebx, eax ; + bss section size (for overrun checking) 2976 00003D2F 3B1D[10650000] <1> cmp ebx, [u.count] 2977 00003D35 7711 <1> ja short sysexec_14 ; program overruns stack ! 2978 <1> ; 2979 <1> ; 24/07/2015 2980 <1> ; add bss section size to [u.break] 2981 00003D37 0105[18650000] <1> add [u.break], eax 2982 <1> ; 2983 00003D3D 83E920 <1> sub ecx, 32 ; header size (already loaded) 2984 <1> ;cmp ecx, [u.count] 2985 <1> ;jnb short sysexec_16 2986 <1> ; cmp r5,u.count / 2987 <1> ; bgt 1f / branch if r5 greater than u.count 2988 00003D40 890D[10650000] <1> mov [u.count], ecx ; required read count 2989 <1> ; mov r5,u.count 2990 <1> ; 2991 00003D46 EB2A <1> jmp short sysexec_16 2992 <1> ; 2993 <1> sysexec_14: 2994 <1> ; 23/06/2015 2995 <1> ; insufficient (out of) memory 2996 00003D48 C705[41650000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; 1 2996 00003D50 0000 <1> 2997 00003D52 E974F3FFFF <1> jmp error 2998 <1> ; 2999 <1> sysexec_15: 3000 <1> ; 25/06/2015 3001 00003D57 0FB715[E8610000] <1> movzx edx, word [i.size] ; file size 3002 00003D5E 29CA <1> sub edx, ecx ; file size - loaded bytes 3003 00003D60 7627 <1> jna short sysexec_17 ; no need to next read 3004 00003D62 01D1 <1> add ecx, edx ; [i.size] 3005 00003D64 3B0D[10650000] <1> cmp ecx, [u.count] ; overrun check (!) 3006 00003D6A 77DC <1> ja short sysexec_14 3007 00003D6C 8915[10650000] <1> mov [u.count], edx 3008 <1> sysexec_16: 3009 00003D72 66A1[D0640000] <1> mov ax, [ii] ; i-number 3010 00003D78 E83E0C0000 <1> call readi 3011 <1> ; add core+10,u.nread / add size of user data area 3012 <1> ; / to u.nread 3013 <1> ; br 2f 3014 <1> ; 1: 3015 <1> ; jsr r0,readi / read in rest of file 3016 <1> ; 2: 3017 00003D7D 8B0D[14650000] <1> mov ecx, [u.nread] 3018 00003D83 010D[18650000] <1> add [u.break], ecx 3019 <1> ; mov u.nread,u.break / set users program break to end of 3020 <1> ; / user code 3021 <1> ; add $core+14,u.break / plus data area 3022 <1> sysexec_17: ; 20/07/2015 3023 <1> ; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 3024 <1> ; ('iclose' is not needed for regular files, from now on) 3025 <1> ;;mov ax, [ii] ; i-number 3026 <1> ;call iclose 3027 <1> ; ; jsr r0,iclose / does nothing 3028 00003D89 31C0 <1> xor eax, eax 3029 00003D8B FEC0 <1> inc al 3030 00003D8D 66A3[30650000] <1> mov [u.intr], ax ; 1 (interrupt/time-out is enabled) 3031 00003D93 66A3[32650000] <1> mov [u.quit], ax ; 1 ('crtl+brk' signal is enabled) 3032 <1> ; 02/07/2015 3033 00003D99 833D[49650000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ? 3034 00003DA0 770C <1> ja short sysexec_18 ; no, the caller is user process 3035 <1> ; If the caller is kernel (sys_init), 'sysexec' will come here 3036 00003DA2 8B15[28610000] <1> mov edx, [k_page_dir] ; kernel's page directory 3037 00003DA8 8915[49650000] <1> mov [u.ppgdir], edx ; next time 'sysexec' must not come here 3038 <1> sysexec_18: 3039 <1> ; 18/10/2015 3040 <1> ; 05/08/2015 3041 <1> ; 29/07/2015 3042 00003DAE 8B2D[6C650000] <1> mov ebp, [argv] ; user's stack pointer must point to argument 3043 <1> ; list pointers (argument count) 3044 00003DB4 FA <1> cli 3045 00003DB5 8B25[C4600000] <1> mov esp, [tss.esp0] ; ring 0 (kernel) stack pointer 3046 <1> ;mov esp, [u.sp] ; Restore Kernel stack 3047 <1> ; for this process 3048 <1> ;add esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS 3049 <1> ;xor eax, eax ; 0 3050 00003DBB FEC8 <1> dec al ; eax = 0 3051 00003DBD 66BA2300 <1> mov dx, UDATA 3052 00003DC1 6652 <1> push dx ; user's stack segment 3053 00003DC3 55 <1> push ebp ; user's stack pointer 3054 <1> ; (points to number of arguments) 3055 00003DC4 FB <1> sti 3056 00003DC5 9C <1> pushfd ; EFLAGS 3057 <1> ; Set IF for enabling interrupts in user mode 3058 <1> ;or dword [esp], 200h 3059 <1> ; 3060 <1> ;mov bx, UCODE 3061 <1> ;push bx ; user's code segment 3062 00003DC6 6A1B <1> push UCODE 3063 <1> ;push 0 3064 00003DC8 50 <1> push eax ; EIP (=0) - start address - 3065 <1> ; clr -(r5) / popped into ps when rti in 3066 <1> ; / sysrele is executed 3067 <1> ; mov $core,-(r5) / popped into pc when rti 3068 <1> ; / in sysrele is executed 3069 <1> ;mov r5,0f / load second copyz argument 3070 <1> ;tst -(r5) / decrement r5 3071 00003DC9 8925[E4640000] <1> mov [u.sp], esp ; 29/07/2015 3072 <1> ; 05/08/2015 3073 <1> ; Remedy of a General Protection Fault during 'iretd' is here ! 3074 <1> ; ('push dx' would cause to general protection fault, 3075 <1> ; after 'pop ds' etc.) 3076 <1> ; 3077 <1> ;; push dx ; ds (UDATA) 3078 <1> ;; push dx ; es (UDATA) 3079 <1> ;; push dx ; fs (UDATA) 3080 <1> ;; push dx ; gs (UDATA) 3081 <1> ; 3082 <1> ; This is a trick to prevent general protection fault 3083 <1> ; during 'iretd' intruction at the end of 'sysrele' (in u1.s): 3084 00003DCF 8EC2 <1> mov es, dx ; UDATA 3085 00003DD1 06 <1> push es ; ds (UDATA) 3086 00003DD2 06 <1> push es ; es (UDATA) 3087 00003DD3 06 <1> push es ; fs (UDATA) 3088 00003DD4 06 <1> push es ; gs (UDATA) 3089 00003DD5 66BA1000 <1> mov dx, KDATA 3090 00003DD9 8EC2 <1> mov es, dx 3091 <1> ; 3092 <1> ;; pushad simulation 3093 00003DDB 89E5 <1> mov ebp, esp ; esp before pushad 3094 00003DDD 50 <1> push eax ; eax (0) 3095 00003DDE 50 <1> push eax ; ecx (0) 3096 00003DDF 50 <1> push eax ; edx (0) 3097 00003DE0 50 <1> push eax ; ebx (0) 3098 00003DE1 55 <1> push ebp ; esp before pushad 3099 00003DE2 50 <1> push eax ; ebp (0) 3100 00003DE3 50 <1> push eax ; esi (0) 3101 00003DE4 50 <1> push eax ; edi (0) 3102 <1> ; 3103 00003DE5 A3[EC640000] <1> mov [u.r0], eax ; eax = 0 3104 00003DEA 8925[E8640000] <1> mov [u.usp], esp 3105 <1> ; mov r5,u.r0 / 3106 <1> ; sub $16.,r5 / skip 8 words 3107 <1> ; mov r5,u.sp / assign user stack pointer value, 3108 <1> ; / effectively zeroes all regs 3109 <1> ; / when sysrele is executed 3110 <1> ; jsr r0,copyz; core; 0:0 / zero user's core 3111 <1> ; clr u.break 3112 <1> ; mov r5,sp / point sp to user's stack 3113 <1> ; 3114 00003DF0 E9F8F2FFFF <1> jmp sysret0 3115 <1> ;jmp sysret 3116 <1> ; br sysret3 / return to core image at $core 3117 <1> 3118 <1> get_argp: 3119 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3120 <1> ; 18/10/2015 (nbase, ncount) 3121 <1> ; 21/07/2015 3122 <1> ; 24/06/2015 (Retro UNIX 386 v1) 3123 <1> ; Get (virtual) address of argument from user's core memory 3124 <1> ; 3125 <1> ; INPUT: 3126 <1> ; esi = virtual address of argument pointer 3127 <1> ; OUTPUT: 3128 <1> ; eax = virtual address of argument 3129 <1> ; 3130 <1> ; Modified registers: EAX, EBX, ECX, EDX, ESI 3131 <1> ; 3132 00003DF5 833D[49650000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? 3133 <1> ; (the caller is kernel) 3134 <1> ;jna short get_argpk 3135 <1> ; 24/12/2021 3136 00003DFC 7719 <1> ja short get_argp5 3137 <1> get_argpk: 3138 <1> ; Argument is in kernel's memory space 3139 00003DFE 66C705[68650000]00- <1> mov word [ncount], PAGE_SIZE ; 4096 3139 00003E06 10 <1> 3140 00003E07 8935[64650000] <1> mov [nbase], esi 3141 00003E0D 8305[64650000]04 <1> add dword [nbase], 4 3142 00003E14 8B06 <1> mov eax, [esi] ; virtual addr. = physcal addr. 3143 00003E16 C3 <1> retn 3144 <1> get_argp5: 3145 00003E17 89F3 <1> mov ebx, esi 3146 00003E19 E88BE9FFFF <1> call get_physical_addr ; get physical address 3147 00003E1E 7257 <1> jc short get_argp_err ; 24/12/2021 (short jump) 3148 00003E20 A3[64650000] <1> mov [nbase], eax ; physical address 3149 00003E25 66890D[68650000] <1> mov [ncount], cx ; remain byte count in page (1-4096) 3150 00003E2C B804000000 <1> mov eax, 4 ; 21/07/2015 3151 <1> ;cmp cx, ax ; 4 3152 00003E31 39C1 <1> cmp ecx, eax ; 24/12/2021 3153 00003E33 734C <1> jnb short get_argp2 3154 00003E35 89F3 <1> mov ebx, esi 3155 00003E37 01CB <1> add ebx, ecx 3156 00003E39 E86BE9FFFF <1> call get_physical_addr ; get physical address 3157 00003E3E 7237 <1> jc short get_argp_err 3158 <1> ;push esi 3159 00003E40 89C6 <1> mov esi, eax 3160 00003E42 66870D[68650000] <1> xchg cx, [ncount] 3161 00003E49 8735[64650000] <1> xchg esi, [nbase] 3162 00003E4F B504 <1> mov ch, 4 3163 00003E51 28CD <1> sub ch, cl 3164 <1> get_argp0: 3165 00003E53 AC <1> lodsb 3166 <1> ;push ax 3167 <1> ; 24/12/2021 3168 00003E54 50 <1> push eax 3169 00003E55 FEC9 <1> dec cl 3170 00003E57 75FA <1> jnz short get_argp0 3171 00003E59 8B35[64650000] <1> mov esi, [nbase] 3172 <1> ; 21/07/2015 3173 00003E5F 0FB6C5 <1> movzx eax, ch 3174 00003E62 0105[64650000] <1> add [nbase], eax 3175 00003E68 662905[68650000] <1> sub [ncount], ax 3176 <1> get_argp1: 3177 00003E6F AC <1> lodsb 3178 00003E70 FECD <1> dec ch 3179 00003E72 7423 <1> jz short get_argp3 3180 <1> ;push ax 3181 <1> ; 24/12/2021 3182 00003E74 50 <1> push eax 3183 00003E75 EBF8 <1> jmp short get_argp1 3184 <1> ; 24/12/2021 3185 <1> get_argp_err: 3186 00003E77 A3[41650000] <1> mov [u.error], eax 3187 00003E7C E94AF2FFFF <1> jmp error 3188 <1> get_argp2: 3189 <1> ; 21/07/2015 3190 <1> ;mov eax, 4 3191 00003E81 8B15[64650000] <1> mov edx, [nbase] ; 18/10/2015 3192 00003E87 0105[64650000] <1> add [nbase], eax 3193 00003E8D 662905[68650000] <1> sub [ncount], ax 3194 <1> ; 3195 00003E94 8B02 <1> mov eax, [edx] 3196 00003E96 C3 <1> retn 3197 <1> get_argp3: 3198 00003E97 B103 <1> mov cl, 3 3199 <1> get_argp4: 3200 00003E99 C1E008 <1> shl eax, 8 3201 <1> ;pop dx 3202 <1> ; 24/12/2021 3203 00003E9C 5A <1> pop edx 3204 00003E9D 88D0 <1> mov al, dl 3205 00003E9F E2F8 <1> loop get_argp4 3206 <1> ;pop esi 3207 00003EA1 C3 <1> retn 3208 <1> 3209 <1> sysfstat: 3210 <1> ; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3) 3211 <1> ; ([idev] return in eax) 3212 <1> ; 0 = root device 3213 <1> ; 1 = mounted device (>0) 3214 <1> ; 03/02/2022 3215 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3216 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3217 <1> ; 3218 <1> ; 'sysfstat' is identical to 'sysstat' except that it operates 3219 <1> ; on open files instead of files given by name. It puts the 3220 <1> ; buffer address on the stack, gets the i-number and 3221 <1> ; checks to see if the file is open for reading or writing. 3222 <1> ; If the file is open for writing (i-number is negative) 3223 <1> ; the i-number is set positive and a branch into 'sysstat' 3224 <1> ; is made. 3225 <1> ; 3226 <1> ; Calling sequence: 3227 <1> ; sysfstat; buf 3228 <1> ; Arguments: 3229 <1> ; buf - buffer address 3230 <1> ; 3231 <1> ; Inputs: *u.r0 - file descriptor 3232 <1> ; Outputs: buffer is loaded with file information 3233 <1> ; ............................................................... 3234 <1> ; 3235 <1> ; Retro UNIX 8086 v1 modification: 3236 <1> ; 'sysfstat' system call has two arguments; so, 3237 <1> ; * 1st argument, file descriptor is in BX register 3238 <1> ; * 2nd argument, buf is pointed to by CX register 3239 <1> 3240 <1> ; / set status of open file 3241 <1> ; jsr r0,arg; u.off / put buffer address in u.off 3242 00003EA2 51 <1> push ecx 3243 <1> ; mov u.off,-(sp) / put buffer address on the stack 3244 <1> ; mov *u.r0,r1 / put file descriptor in r1 3245 <1> ; jsr r0,getf / get the files i-number 3246 <1> ; BX = file descriptor (file number) 3247 00003EA3 E8FE000000 <1> call getf1 3248 <1> ; 03/02/2022 3249 00003EA8 21C0 <1> and eax, eax 3250 <1> ;and ax, ax ; i-number of the file 3251 <1> ; tst r1 / is it 0? 3252 <1> ;jz error 3253 <1> ; beq error3 / yes, error 3254 00003EAA 750F <1> jnz short sysfstat1 3255 00003EAC C705[41650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 3255 00003EB4 0000 <1> 3256 00003EB6 E910F2FFFF <1> jmp error 3257 <1> sysfstat1: 3258 00003EBB 80FC80 <1> cmp ah, 80h 3259 00003EBE 7222 <1> jb short sysstat1 3260 <1> ; bgt 1f / if i-number is negative (open for writing) 3261 00003EC0 66F7D8 <1> neg ax 3262 <1> ; neg r1 / make it positive, then branch 3263 00003EC3 EB1D <1> jmp short sysstat1 3264 <1> ; br 1f / to 1f 3265 <1> sysstat: 3266 <1> ; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3) 3267 <1> ; ([idev] return in eax) 3268 <1> ; 0 = root device 3269 <1> ; 1 = mounted device (>0) 3270 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3271 <1> ; 18/10/2015 3272 <1> ; 07/10/2015 3273 <1> ; 02/09/2015 3274 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3275 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3276 <1> ; 3277 <1> ; 'sysstat' gets the status of a file. Its arguments are the 3278 <1> ; name of the file and buffer address. The buffer is 34 bytes 3279 <1> ; long and information about the file placed in it. 3280 <1> ; sysstat calls 'namei' to get the i-number of the file. 3281 <1> ; Then 'iget' is called to get i-node in core. The buffer 3282 <1> ; is then loaded and the results are given in the UNIX 3283 <1> ; Programmers Manual sysstat (II). 3284 <1> ; 3285 <1> ; Calling sequence: 3286 <1> ; sysstat; name; buf 3287 <1> ; Arguments: 3288 <1> ; name - points to the name of the file 3289 <1> ; buf - address of a 34 bytes buffer 3290 <1> ; Inputs: - 3291 <1> ; Outputs: buffer is loaded with file information 3292 <1> ; ............................................................... 3293 <1> ; 3294 <1> ; Retro UNIX 8086 v1 modification: 3295 <1> ; 'sysstat' system call has two arguments; so, 3296 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 3297 <1> ; to get sysstat system call arguments from the user; 3298 <1> ; * 1st argument, name is pointed to by BX register 3299 <1> ; * 2nd argument, buf is pointed to by CX register 3300 <1> ; 3301 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 3302 <1> ; arguments which were in these registers; 3303 <1> ; but, it returns by putting the 1st argument 3304 <1> ; in 'u.namep' and the 2nd argument 3305 <1> ; on top of stack. (1st argument is offset of the 3306 <1> ; file/path name in the user's program segment.) 3307 <1> 3308 <1> ; / ; name of file; buffer - get files status 3309 <1> ; jsr r0,arg2 / get the 2 arguments 3310 00003EC5 891D[04650000] <1> mov [u.namep], ebx 3311 00003ECB 51 <1> push ecx 3312 00003ECC E806010000 <1> call namei 3313 <1> ; jsr r0,namei / get the i-number for the file 3314 <1> ;jc error 3315 <1> ; br error3 / no such file, error 3316 00003ED1 730F <1> jnc short sysstat1 3317 <1> ; pop ecx 3318 <1> sysstat_err0: 3319 <1> ; 'file not found !' error 3320 00003ED3 C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 3320 00003EDB 0000 <1> 3321 00003EDD E9E9F1FFFF <1> jmp error 3322 <1> 3323 <1> ;statx: db 0 3324 <1> 3325 <1> sysstat1: ; 1: 3326 00003EE2 E800090000 <1> call iget 3327 <1> ; jsr r0,iget / get the i-node into core 3328 <1> ; 07/10/2015 (ax = [ii], inode number) 3329 <1> ; 02/09/2015 3330 00003EE7 8F05[0C650000] <1> pop dword [u.base] 3331 <1> ; mov (sp)+,r3 / move u.off to r3 (points to buffer) 3332 00003EED E861000000 <1> call sysstat_gpa ; get physical address 3333 00003EF2 730A <1> jnc short sysstat2 3334 <1> sysstat_err1: 3335 00003EF4 A3[41650000] <1> mov dword [u.error], eax ; error code 3336 00003EF9 E9CDF1FFFF <1> jmp error 3337 <1> sysstat2: 3338 00003EFE A0[D0640000] <1> mov al, [ii] ; 07/10/2015 (result of 'iget' call, above) 3339 00003F03 AA <1> stosb 3340 00003F04 FF05[0C650000] <1> inc dword [u.base] 3341 <1> ;dec cx 3342 <1> ; 24/12/2021 3343 00003F0A 49 <1> dec ecx 3344 00003F0B 7505 <1> jnz short sysstat3 3345 00003F0D E841000000 <1> call sysstat_gpa 3346 <1> ;jc short sysstat_err1 3347 <1> sysstat3: 3348 00003F12 A0[D1640000] <1> mov al, [ii+1] ; 07/10/2015 (result of 'iget' call, above) 3349 00003F17 AA <1> stosb 3350 <1> ; mov r1,(r3)+ / put i-number in 1st word of buffer 3351 00003F18 FF05[0C650000] <1> inc dword [u.base] 3352 <1> ;;dec word [u.pcount] 3353 <1> ;dec cx 3354 00003F1E 49 <1> dec ecx ; 24/12/2021 3355 00003F1F 7505 <1> jnz short sysstat4 3356 00003F21 E82D000000 <1> call sysstat_gpa 3357 <1> ;jc short sysstat_err1 3358 <1> sysstat4: 3359 00003F26 BE[E4610000] <1> mov esi, inode 3360 <1> ; mov $inode,r2 / r2 points to i-node 3361 <1> sysstat5: ; 1: 3362 00003F2B A4 <1> movsb 3363 <1> ; mov (r2)+,(r3)+ / move rest of i-node to buffer 3364 00003F2C FF05[0C650000] <1> inc dword [u.base] 3365 <1> ;;dec word [u.pcount] 3366 <1> ;dec cx 3367 <1> ; 24/12/2021 3368 00003F32 49 <1> dec ecx 3369 00003F33 7505 <1> jnz short sysstat6 3370 00003F35 E819000000 <1> call sysstat_gpa 3371 <1> ;jc short sysstat_err1 3372 <1> sysstat6: 3373 00003F3A 81FE[04620000] <1> cmp esi, inode + 32 3374 <1> ; cmp r2,$inode+32 / done? 3375 00003F40 75E9 <1> jne short sysstat5 3376 <1> ; bne 1b / no, go back 3377 <1> 3378 <1> ;;; 3379 <1> ; 09/05/2022 3380 <1> ;*** additional feature *** -retro unix only- 3381 <1> ; 3382 <1> ; !! return device number -of current inode- in eax !! 3383 <1> ; 3384 <1> ; (modification reason/purpose: 3385 <1> ; to improve 'pwd' command's pathname output/result 3386 <1> ; and to correct 'cp' command's 'can not copy file itself' 3387 <1> ; error due to same inode numbers in root file system 3388 <1> ; and mounted file system.) 3389 <1> ; 3390 00003F42 29C0 <1> sub eax, eax 3391 00003F44 A0[D2640000] <1> mov al, [idev] ; [cdev] 3392 00003F49 A3[EC640000] <1> mov [u.r0], eax 3393 <1> ;;; 3394 <1> 3395 00003F4E E998F1FFFF <1> jmp sysret 3396 <1> ; br sysret3 / return through sysret 3397 <1> ; 3398 <1> sysstat_gpa: ; get physical address of file status buffer 3399 <1> ; 02/09/2015 3400 00003F53 8B1D[0C650000] <1> mov ebx, [u.base] 3401 <1> ; 07/10/2015 3402 00003F59 E84BE8FFFF <1> call get_physical_addr ; get physical address 3403 <1> ;jc short sysstat_gpa1 3404 00003F5E 7294 <1> jc short sysstat_err1 3405 <1> ; 18/10/2015 3406 00003F60 89C7 <1> mov edi, eax ; physical address 3407 <1> ;mov [u.pcount], cx ; remain bytes in page 3408 <1> ;sysstat_gpa1: 3409 00003F62 C3 <1> retn 3410 <1> 3411 <1> fclose: 3412 <1> ; 08/01/2022 3413 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3414 <1> ; 18/06/2015 (Retro UNIX 386 v1 - Beginning) 3415 <1> ; (32 bit offset pointer modification) 3416 <1> ; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1) 3417 <1> ; 3418 <1> ; Given the file descriptor (index to the u.fp list) 3419 <1> ; 'fclose' first gets the i-number of the file via 'getf'. 3420 <1> ; If i-node is active (i-number > 0) the entry in 3421 <1> ; u.fp list is cleared. If all the processes that opened 3422 <1> ; that file close it, then fsp etry is freed and the file 3423 <1> ; is closed. If not a return is taken. 3424 <1> ; If the file has been deleted while open, 'anyi' is called 3425 <1> ; to see anyone else has it open, i.e., see if it is appears 3426 <1> ; in another entry in the fsp table. Upon return from 'anyi' 3427 <1> ; a check is made to see if the file is special. 3428 <1> ; 3429 <1> ; INPUTS -> 3430 <1> ; r1 - contains the file descriptor (value=0,1,2...) 3431 <1> ; u.fp - list of entries in the fsp table 3432 <1> ; fsp - table of entries (4 words/entry) of open files. 3433 <1> ; OUTPUTS -> 3434 <1> ; r1 - contains the same file descriptor 3435 <1> ; r2 - contains i-number 3436 <1> ; 3437 <1> ; ((AX = R1)) 3438 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 3439 <1> ; 3440 <1> ; Retro UNIX 8086 v1 modification : CF = 1 3441 <1> ; if i-number of the file is 0. (error) 3442 <1> 3443 <1> ;movzx edx, ax ; ** 3444 <1> ; 24/12/2021 3445 <1> ;movzx edx, al 3446 00003F63 89C2 <1> mov edx, eax ; eax <= 10 ; 24/12/2021 3447 00003F65 50 <1> push eax ; *** 3448 <1> ;push ax ; *** 3449 <1> ; mov r1,-(sp) / put r1 on the stack (it contains 3450 <1> ; / the index to u.fp list) 3451 00003F66 E839000000 <1> call getf 3452 <1> ; jsr r0,getf / r1 contains i-number, 3453 <1> ; / cdev has device =, u.fofp 3454 <1> ; / points to 3rd word of fsp entry 3455 00003F6B 6683F801 <1> cmp ax, 1 ; r1 3456 <1> ; tst r1 / is i-number 0? 3457 00003F6F 7231 <1> jb short fclose_2 3458 <1> ; beq 1f / yes, i-node not active so return 3459 <1> ; tst (r0)+ / no, jump over error return 3460 00003F71 89D3 <1> mov ebx, edx ; ** 3461 <1> ; 24/12/2021 3462 00003F73 89C2 <1> mov edx, eax ; * 3463 <1> ;mov dx, ax ; * 3464 <1> ; mov r1,r2 / move i-number to r2 ;* 3465 <1> ; mov (sp),r1 / restore value of r1 from the stack 3466 <1> ; / which is index to u.fp ; ** 3467 00003F75 C683[F2640000]00 <1> mov byte [ebx+u.fp], 0 3468 <1> ; clrb u.fp(r1) / clear that entry in the u.fp list 3469 00003F7C 8B1D[FC640000] <1> mov ebx, [u.fofp] 3470 <1> ; mov u.fofp,r1 / r1 points to 3rd word in fsp entry 3471 <1> fclose_0: 3472 00003F82 FE4B04 <1> dec byte [ebx+4] ; 18/06/2015 3473 <1> ; decb 2(r1) / decrement the number of processes 3474 <1> ; / that have opened the file 3475 00003F85 791B <1> jns short fclose_2 ; jump if not negative (jump if bit 7 is 0) 3476 <1> ; bge 1f / if all processes haven't closed the file, return 3477 <1> ; 3478 <1> ; 24/12/2021 3479 00003F87 52 <1> push edx ; * 3480 <1> ;push dx ; * 3481 <1> ; mov r2,-(sp) / put r2 on the stack (i-number) 3482 <1> ;xor ax, ax ; 0 3483 <1> ; 24/12/2021 3484 00003F88 31C0 <1> xor eax, eax 3485 00003F8A 668943FC <1> mov [ebx-4], ax ; 0 3486 <1> ; clr -4(r1) / clear 1st word of fsp entry 3487 00003F8E 8A4305 <1> mov al, [ebx+5] ; 18/06/2015 3488 <1> ; tstb 3(r1) / has this file been deleted 3489 00003F91 20C0 <1> and al, al 3490 00003F93 7407 <1> jz short fclose_1 3491 <1> ; beq 2f / no, branch 3492 <1> ; 08/01/2022 3493 00003F95 89D0 <1> mov eax, edx 3494 <1> ;mov ax, dx ; * 3495 <1> ; mov r2,r1 / yes, put i-number back into r1 3496 <1> ; AX = inode number 3497 00003F97 E8A0040000 <1> call anyi 3498 <1> ; jsr r0,anyi / free all blocks related to i-number 3499 <1> ; / check if file appears in fsp again 3500 <1> fclose_1: ; 2: 3501 <1> ; 24/12/2021 3502 00003F9C 58 <1> pop eax ; * 3503 <1> ;pop ax ; * 3504 <1> ; mov (sp)+,r1 / put i-number back into r1 3505 00003F9D E8E8110000 <1> call iclose ; close if it is special file 3506 <1> ; jsr r0,iclose / check to see if its a special file 3507 <1> fclose_2: ; 1: 3508 <1> ; 24/12/2021 3509 00003FA2 58 <1> pop eax ; *** 3510 <1> ;pop ax ; *** 3511 <1> ; mov (sp)+,r1 / put index to u.fp back into r1 3512 00003FA3 C3 <1> retn 3513 <1> ; rts r0 3514 <1> 3515 <1> ; 09/01/2022 3516 <1> ; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2) 3517 <1> getf: ; / get the device number and the i-number of an open file 3518 <1> ; 13/05/2015 3519 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 3520 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 3521 <1> ; 3522 00003FA4 89C3 <1> mov ebx, eax 3523 <1> getf1: ;; Calling point from 'rw1' (23/05/2013) 3524 <1> ; 08/01/2022 3525 00003FA6 29C0 <1> sub eax, eax 3526 <1> ; 3527 00003FA8 83FB0A <1> cmp ebx, 10 3528 <1> ; cmp r1,$10. / user limited to 10 open files 3529 00003FAB 7329 <1> jnb short getf2 ; 13/05/2015 3530 <1> ;jnb error 3531 <1> ; bhis error3 / u.fp is table of users open files, 3532 <1> ; / index in fsp table 3533 <1> ; 08/01/2022 3534 00003FAD 8A83[F2640000] <1> mov al, [ebx+u.fp] 3535 <1> ;mov bl, [ebx+u.fp] 3536 <1> ; movb u.fp(r1),r1 / r1 contains number of entry 3537 <1> ; / in fsp table 3538 <1> ; 08/01/2022 3539 00003FB3 08C0 <1> or al, al 3540 00003FB5 741F <1> jz short getf2 3541 <1> ;or bl, bl 3542 <1> ;jnz short getf3 3543 <1> ;;jz short getf4 3544 <1> ; beq 1f / if its zero return 3545 <1> ;getf2: 3546 <1> ; ; 08/01/2022 3547 <1> ; ; 'File not open !' error (ax=0) 3548 <1> ; ;sub eax, eax 3549 <1> ; retn 3550 <1> 3551 <1> getf3: 3552 <1> ; Retro UNIX 386 v1 modification ! (11/05/2015) 3553 <1> ; 3554 <1> ; 'fsp' table (10 bytes/entry) 3555 <1> ; bit 15 bit 0 3556 <1> ; ---|------------------------------------------- 3557 <1> ; r/w| i-number of open file 3558 <1> ; ---|------------------------------------------- 3559 <1> ; device number 3560 <1> ; ----------------------------------------------- 3561 <1> ; offset pointer, r/w pointer to file (bit 0-15) 3562 <1> ; ----------------------------------------------- 3563 <1> ; offset pointer, r/w pointer to file (bit 16-31) 3564 <1> ; ----------------------|------------------------ 3565 <1> ; flag that says file | number of processes 3566 <1> ; has been deleted | that have file open 3567 <1> ; ----------------------|------------------------ 3568 <1> ; 3569 <1> ;mov eax, 10 3570 <1> ; 08/01/2022 3571 00003FB7 B30A <1> mov bl, 10 3572 00003FB9 F6E3 <1> mul bl 3573 00003FBB BB[AE620000] <1> mov ebx, fsp-6 ; the 3rd word in the fsp entry 3574 00003FC0 01C3 <1> add ebx, eax 3575 <1> ; asl r1 3576 <1> ; asl r1 / multiply by 8 to get index into 3577 <1> ; / fsp table entry 3578 <1> ; asl r1 3579 <1> ; add $fsp-4,r1 / r1 is pointing at the 3rd word 3580 <1> ; / in the fsp entry 3581 00003FC2 891D[FC640000] <1> mov [u.fofp], ebx 3582 <1> ; mov r1,u.fofp / save address of 3rd word 3583 <1> ; / in fsp entry in u.fofp 3584 00003FC8 4B <1> dec ebx 3585 00003FC9 4B <1> dec ebx 3586 <1> ;mov ax, [ebx] 3587 <1> ; 09/01/2022 3588 00003FCA 8A03 <1> mov al, [ebx] 3589 00003FCC A2[D3640000] <1> mov [cdev], al ; ;;Retro UNIX 8086 v1 ! 3590 <1> ;mov [cdev], ax ; ;;in fact (!) 3591 <1> ;;dev number is in 1 byte 3592 <1> ; mov -(r1),cdev / remove the device number cdev 3593 00003FD1 4B <1> dec ebx 3594 00003FD2 4B <1> dec ebx 3595 00003FD3 668B03 <1> mov ax, [ebx] 3596 <1> ; mov -(r1),r1 / and the i-number r1 3597 <1> getf2: ; 08/01/2022 3598 <1> getf4: ; 1: 3599 00003FD6 C3 <1> retn 3600 <1> ; rts r0 3601 <1> 3602 <1> namei: 3603 <1> ; 15/05/2022 (mounted directory path, '..' method) 3604 <1> ; 03/02/2022 3605 <1> ; 09/01/2022 3606 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3607 <1> ; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names) 3608 <1> ; 18/10/2015 (nbase, ncount) 3609 <1> ; 12/10/2015 3610 <1> ; 21/08/2015 3611 <1> ; 18/07/2015 3612 <1> ; 02/07/2015 3613 <1> ; 17/06/2015 3614 <1> ; 16/06/2015 (Retro UNIX 386 v1 - Beginning) 3615 <1> ; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 3616 <1> ; 3617 <1> ; 'namei' takes a file path name and returns i-number of 3618 <1> ; the file in the current directory or the root directory 3619 <1> ; (if the first character of the pathname is '/'). 3620 <1> ; 3621 <1> ; INPUTS -> 3622 <1> ; u.namep - points to a file path name 3623 <1> ; u.cdir - i-number of users directory 3624 <1> ; u.cdev - device number on which user directory resides 3625 <1> ; OUTPUTS -> 3626 <1> ; r1 - i-number of file 3627 <1> ; cdev 3628 <1> ; u.dirbuf - points to directory entry where a match 3629 <1> ; occurs in the search for file path name. 3630 <1> ; If no match u.dirb points to the end of 3631 <1> ; the directory and r1 = i-number of the current 3632 <1> ; directory. 3633 <1> ; ((AX = R1)) 3634 <1> ; 3635 <1> ; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM) 3636 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 3637 <1> ; 3638 <1> 3639 00003FD7 66A1[F0640000] <1> mov ax, [u.cdir] 3640 <1> ; mov u.cdir,r1 / put the i-number of current directory 3641 <1> ; / in r1 3642 <1> ; 09/01/2022 3643 00003FDD 8A15[36650000] <1> mov dl, [u.cdrv] 3644 00003FE3 8815[D3640000] <1> mov [cdev], dl 3645 <1> ;mov dx, [u.cdrv] 3646 <1> ;mov [cdev], dx ; NOTE: Retro UNIX 8086 v1 3647 <1> ; device/drive number is in 1 byte, 3648 <1> ; not in 1 word! 3649 <1> ; mov u.cdev,cdev / device number for users directory 3650 <1> ; / into cdev 3651 <1> ; 12/10/2015 3652 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 3653 <1> ; convert virtual (pathname) addr to physical address 3654 00003FE9 E868010000 <1> call trans_addr_nmbp ; 12/10/2015 3655 <1> ; esi = physical address of [u.namep] 3656 <1> ; ecx = byte count in the page 3657 00003FEE 803E2F <1> cmp byte [esi], '/' 3658 <1> ; cmpb *u.namep,$'/ / is first char in file name a / 3659 00003FF1 751D <1> jne short namei_1 3660 <1> ; bne 1f 3661 00003FF3 FF05[04650000] <1> inc dword [u.namep] 3662 <1> ; inc u.namep / go to next char 3663 <1> ;dec cx ; remain byte count in the page 3664 <1> ; 24/12/2021 3665 00003FF9 49 <1> dec ecx 3666 00003FFA 7506 <1> jnz short namei_0 3667 <1> ; 12/10/2015 3668 00003FFC E855010000 <1> call trans_addr_nmbp ; convert virtual address to physical 3669 <1> ; esi = physical address (page start + offset) 3670 <1> ; ecx = byte count in the page 3671 00004001 4E <1> dec esi 3672 <1> namei_0: 3673 00004002 46 <1> inc esi ; go to next char 3674 00004003 66A1[DC640000] <1> mov ax, [rootdir] ; 09/07/2013 3675 <1> ; mov rootdir,r1 / put i-number of rootdirectory in r1 3676 00004009 C605[D3640000]00 <1> mov byte [cdev], 0 3677 <1> ; clr cdev / clear device number 3678 <1> namei_1: ; 1: 3679 00004010 F606FF <1> test byte [esi], 0FFh 3680 <1> namei_10: ; 24/12/2021 (jump from namei_8) 3681 00004013 74C1 <1> jz short getf4 3682 <1> ;jz nig 3683 <1> ; tstb *u.namep / is the character in file name a nul 3684 <1> ; beq nig / yes, end of file name reached; 3685 <1> ; / branch to "nig" 3686 <1> namei_2: ; 1: 3687 <1> ; 18/10/2015 3688 00004015 8935[64650000] <1> mov [nbase], esi 3689 0000401B 66890D[68650000] <1> mov [ncount], cx 3690 <1> ; 3691 <1> ;mov dx, 2 3692 00004022 B202 <1> mov dl, 2 ; user flag (read, non-owner) 3693 00004024 E892080000 <1> call access 3694 <1> ; jsr r0,access; 2 / get i-node with i-number r1 3695 <1> ; 'access' will not return here if user has not "r" permission ! 3696 <1> ; 03/02/2022 3697 00004029 F605[E5610000]40 <1> test byte [i.flgs+1], 40h 3698 <1> ;test word [i.flgs], 4000h 3699 <1> ; bit $40000,i.flgs / directory i-node? 3700 00004030 746A <1> jz short namei_err 3701 <1> ; beq error3 / no, got an error 3702 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 3703 00004032 31C0 <1> xor eax, eax 3704 00004034 A3[08650000] <1> mov [u.off], eax ; 0 3705 00004039 66A1[E8610000] <1> mov ax, [i.size] 3706 0000403F A3[00650000] <1> mov [u.dirp], eax 3707 <1> ; mov i.size,u.dirp / put size of directory in u.dirp 3708 <1> ; clr u.off / u.off is file offset used by user 3709 00004044 C705[FC640000]- <1> mov dword [u.fofp], u.off 3709 0000404A [08650000] <1> 3710 <1> ; mov $u.off,u.fofp / u.fofp is a pointer to 3711 <1> ; / the offset portion of fsp entry 3712 <1> namei_3: ; 2: 3713 0000404E C705[0C650000]- <1> mov dword [u.base], u.dirbuf 3713 00004054 [1E650000] <1> 3714 <1> ; mov $u.dirbuf,u.base / u.dirbuf holds a file name 3715 <1> ; / copied from a directory 3716 00004058 C705[10650000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 3716 00004060 0000 <1> 3717 <1> ; mov $10.,u.count / u.count is byte count 3718 <1> ; / for reads and writes 3719 00004062 66A1[D0640000] <1> mov ax, [ii] 3720 <1> ; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall') 3721 00004068 FE05[53650000] <1> inc byte [u.kcall] ; the caller is 'namei' sign 3722 0000406E E848090000 <1> call readi 3723 <1> ; jsr r0,readi / read 10. bytes of file 3724 <1> ; with i-number (r1); i.e. read a directory entry 3725 00004073 8B0D[14650000] <1> mov ecx, [u.nread] 3726 00004079 09C9 <1> or ecx, ecx 3727 <1> ; tst u.nread 3728 0000407B 741B <1> jz short nib 3729 <1> ; ble nib / gives error return 3730 <1> ; 3731 0000407D 668B1D[1E650000] <1> mov bx, [u.dirbuf] 3732 00004084 6621DB <1> and bx, bx 3733 <1> ; tst u.dirbuf / 3734 00004087 7522 <1> jnz short namei_4 3735 <1> ; bne 3f / branch when active directory entry 3736 <1> ; / (i-node word in entry non zero) 3737 00004089 A1[08650000] <1> mov eax, [u.off] 3738 0000408E 83E810 <1> sub eax, 16 ; 04/12/2015 (10 -> 16) 3739 00004091 A3[00650000] <1> mov [u.dirp], eax 3740 <1> ; mov u.off,u.dirp 3741 <1> ; sub $10.,u.dirp 3742 00004096 EBB6 <1> jmp short namei_3 3743 <1> ; br 2b 3744 <1> 3745 <1> ; 18/07/2013 3746 <1> nib: 3747 00004098 31C0 <1> xor eax, eax ; xor ax, ax ; ax = 0 -> file not found 3748 0000409A F9 <1> stc 3749 <1> nig: 3750 0000409B C3 <1> retn 3751 <1> 3752 <1> namei_err: 3753 <1> ; 16/06/2015 3754 0000409C C705[41650000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a directory !' error 3754 000040A4 0000 <1> 3755 000040A6 E920F0FFFF <1> jmp error 3756 <1> 3757 <1> namei_4: ; 3: 3758 <1> ; 18/10/2015 3759 <1> ; 12/10/2015 3760 <1> ; 21/08/2015 3761 <1> ; 18/07/2015 3762 000040AB 8B2D[04650000] <1> mov ebp, [u.namep] 3763 <1> ; mov u.namep,r2 / u.namep points into a file name string 3764 000040B1 BF[20650000] <1> mov edi, u.dirbuf + 2 3765 <1> ; mov $u.dirbuf+2,r3 / points to file name of directory entry 3766 <1> ; 18/10/2015 3767 000040B6 8B35[64650000] <1> mov esi, [nbase] 3768 000040BC 668B0D[68650000] <1> mov cx, [ncount] 3769 <1> ; 3770 000040C3 6621C9 <1> and cx, cx 3771 000040C6 7505 <1> jnz short namei_5 3772 <1> ; 3773 000040C8 E88F000000 <1> call trans_addr_nm ; convert virtual address to physical 3774 <1> ; esi = physical address (page start + offset) 3775 <1> ; ecx = byte count in the page 3776 <1> namei_5: ; 3: 3777 000040CD 45 <1> inc ebp ; 18/07/2015 3778 000040CE AC <1> lodsb ; mov al, [esi] ; inc esi (al = r4) 3779 <1> ; movb (r2)+,r4 / move a character from u.namep string into r4 3780 000040CF 08C0 <1> or al, al 3781 000040D1 741C <1> jz short namei_7 3782 <1> ; beq 3f / if char is nul, then the last char in string 3783 <1> ; / has been moved 3784 000040D3 3C2F <1> cmp al, '/' 3785 <1> ; cmp r4,$'/ / is char a 3786 000040D5 7418 <1> je short namei_7 3787 <1> ; beq 3f 3788 <1> ; 24/12/2021 3789 000040D7 49 <1> dec ecx 3790 <1> ; 12/10/2015 3791 <1> ;dec cx ; remain byte count in the page 3792 000040D8 7505 <1> jnz short namei_6 3793 000040DA E87D000000 <1> call trans_addr_nm ; convert virtual address to physical 3794 <1> ; esi = physical address (page start + offset) 3795 <1> ; ecx = byte count in the page 3796 <1> namei_6: 3797 000040DF 81FF[2E650000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 3798 <1> ; cmp r3,$u.dirbuf+10. / have I checked 3799 <1> ; / all 8 bytes of file name 3800 000040E5 74E6 <1> je short namei_5 3801 <1> ; beq 3b 3802 000040E7 AE <1> scasb 3803 <1> ; cmpb (r3)+,r4 / compare char in u.namep string to file name 3804 <1> ; / char read from directory 3805 000040E8 74E3 <1> je short namei_5 3806 <1> ; beq 3b / branch if chars match 3807 <1> namei_9: 3808 000040EA E95FFFFFFF <1> jmp namei_3 ; 2b 3809 <1> ; br 2b / file names do not match go to next directory entry 3810 <1> namei_7: ; 3: 3811 000040EF 81FF[2E650000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 3812 <1> ; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched 3813 000040F5 7406 <1> je short namei_8 3814 <1> ; beq 3f 3815 000040F7 8A27 <1> mov ah, [edi] 3816 <1> ;inc edi 3817 000040F9 20E4 <1> and ah, ah 3818 <1> ; tstb (r3)+ / 3819 <1> ;jnz namei_3 3820 <1> ; bne 2b 3821 <1> ; 24/12/2021 3822 000040FB 75ED <1> jnz short namei_9 3823 <1> namei_8: ; 3 3824 000040FD 892D[04650000] <1> mov [u.namep], ebp ; 18/07/2015 3825 <1> ; mov r2,u.namep / u.namep points to char 3826 <1> ; / following a / or nul 3827 <1> ;mov bx, [u.dirbuf] 3828 <1> ; mov u.dirbuf,r1 / move i-node number in directory 3829 <1> ; / entry to r1 3830 <1> ;;;; 3831 <1> ; 15/05/2022 - Retro UNIX (8086/386) feature only ! 3832 <1> ; ! 'pwd' utility modification ! 3833 <1> ; ((if directory entry name is a dotdot))) 3834 <1> ;; check if it is mounted device's root directory inode 3835 <1> ; and if so, replace it with parent dir inode number 3836 <1> ; of mounting directory in [mntp]. 3837 <1> 3838 00004103 668B1D[1E650000] <1> mov bx, [u.dirbuf] 3839 <1> 3840 0000410A 6683FB29 <1> cmp bx, 41 ; root directory inode number 3841 0000410E 753C <1> jne short namei_11 3842 <1> 3843 00004110 663B1D[D0640000] <1> cmp bx, [ii] ; for root dir, '.' & '..' is 41 3844 00004117 7533 <1> jne short namei_11 ; not root dir (of mounted dev) 3845 <1> 3846 <1> ;cmp [idev], bh ; 0 3847 00004119 383D[D3640000] <1> cmp [cdev], bh ; 0 3848 <1> ; 0 = root fs, dev num in [rdev] 3849 <1> ; 1 = mounted, dev num in [mdev] 3850 0000411F 762B <1> jna short namei_11 3851 <1> 3852 <1> ; dotdot (parent directory link) check 3853 00004121 66813D[20650000]2E- <1> cmp word [u.dirbuf+2], '..' 3853 00004129 2E <1> 3854 0000412A 7520 <1> jne short namei_11 3855 0000412C 803D[22650000]00 <1> cmp byte [u.dirbuf+4], 0 3856 00004133 7517 <1> jne short namei_11 3857 <1> 3858 <1> ; (This may not be necessary because [idev] = 1 3859 <1> ; and [mnti] is expected as a sub dir inode number) 3860 00004135 66391D[D6640000] <1> cmp [mnti], bx ; 41 3861 0000413C 760E <1> jna short namei_11 3862 <1> 3863 <1> ; change inumber to parent dir inum of mount directory 3864 0000413E 668B1D[D8640000] <1> mov bx, [mntp] 3865 00004145 C605[D3640000]00 <1> mov byte [cdev], 0 ; root fs 3866 <1> namei_11: 3867 <1> ;;;; 3868 <1> 3869 0000414C 20C0 <1> and al, al 3870 <1> ; tst r4 / if r4 = 0 the end of file name reached, 3871 <1> ; / if r4 = then go to next directory 3872 <1> ; 15/05/2022 3873 0000414E 6689D8 <1> mov ax, bx 3874 <1> ;mov ax, [u.dirbuf] ; 17/06/2015 3875 <1> ; 24/12/2021 3876 00004151 E9BDFEFFFF <1> jmp namei_10 ; (jnz short namei_2, retn) 3877 <1> ;jnz namei_2 3878 <1> ; bne 1b 3879 <1> ; AX = i-number of the file 3880 <1> ;;nig: 3881 <1> ;retn ; 24/12/2021 3882 <1> ; tst (r0)+ / gives non-error return 3883 <1> ;;nib: 3884 <1> ;; xor ax, ax ; Retro UNIX 8086 v1 modification ! 3885 <1> ; ax = 0 -> file not found 3886 <1> ;; stc ; 27/05/2013 3887 <1> ;; retn 3888 <1> ; rts r0 3889 <1> 3890 <1> trans_addr_nmbp: 3891 <1> ; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 3892 <1> ; 18/10/2015 3893 <1> ; 12/10/2015 3894 00004156 8B2D[04650000] <1> mov ebp, [u.namep] 3895 <1> trans_addr_nm: 3896 <1> ; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 3897 <1> ; Convert virtual (pathname) address to physical address 3898 <1> ; (Retro UNIX 386 v1 feature only !) 3899 <1> ; 18/10/2015 3900 <1> ; 12/10/2015 (u.pnbase & u.pncount has been removed from code) 3901 <1> ; 02/07/2015 3902 <1> ; 17/06/2015 3903 <1> ; 16/06/2015 3904 <1> ; 3905 <1> ; INPUTS: 3906 <1> ; ebp = pathname address (virtual) ; [u.namep] 3907 <1> ; [u.pgdir] = user's page directory 3908 <1> ; OUTPUT: 3909 <1> ; esi = physical address of the pathname 3910 <1> ; ecx = remain byte count in the page 3911 <1> ; 3912 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI) 3913 <1> ; 3914 <1> 3915 <1> ; 08/01/2022 3916 0000415C 29C9 <1> sub ecx, ecx 3917 <1> ; 3918 0000415E 833D[49650000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? (sysexec) 3919 00004165 7618 <1> jna short trans_addr_nmk ; the caller is os kernel; 3920 <1> ; it is already physical address 3921 00004167 50 <1> push eax 3922 00004168 89EB <1> mov ebx, ebp ; [u.namep] ; pathname address (virtual) 3923 0000416A E83AE6FFFF <1> call get_physical_addr ; get physical address 3924 0000416F 7204 <1> jc short tr_addr_nm_err 3925 <1> ; 18/10/2015 3926 <1> ; eax = physical address 3927 <1> ; cx = remain byte count in page (1-4096) 3928 <1> ; 12/10/2015 (cx = [u.pncount]) 3929 00004171 89C6 <1> mov esi, eax ; 12/10/2015 (esi=[u.pnbase]) 3930 00004173 58 <1> pop eax 3931 00004174 C3 <1> retn 3932 <1> 3933 <1> tr_addr_nm_err: 3934 00004175 A3[41650000] <1> mov [u.error], eax 3935 <1> ;pop eax 3936 0000417A E94CEFFFFF <1> jmp error 3937 <1> 3938 <1> trans_addr_nmk: 3939 <1> ; 12/10/2015 3940 <1> ; 02/07/2015 3941 0000417F 8B35[04650000] <1> mov esi, [u.namep] ; [u.pnbase] 3942 <1> ;mov cx, PAGE_SIZE ; 4096 ; [u.pncount] 3943 <1> ; 08/01/2022 3944 00004185 B510 <1> mov ch, PAGE_SIZE/256 3945 00004187 C3 <1> retn 3946 <1> 3947 <1> syschdir: 3948 <1> ; / makes the directory specified in the argument 3949 <1> ; / the current directory 3950 <1> ; 3951 <1> ; 09/01/2022 3952 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 3953 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 3954 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 3955 <1> ; 3956 <1> ; 'syschdir' makes the directory specified in its argument 3957 <1> ; the current working directory. 3958 <1> ; 3959 <1> ; Calling sequence: 3960 <1> ; syschdir; name 3961 <1> ; Arguments: 3962 <1> ; name - address of the path name of a directory 3963 <1> ; terminated by nul byte. 3964 <1> ; Inputs: - 3965 <1> ; Outputs: - 3966 <1> ; ............................................................... 3967 <1> ; 3968 <1> ; Retro UNIX 8086 v1 modification: 3969 <1> ; The user/application program puts address of 3970 <1> ; the path name in BX register as 'syschdir' 3971 <1> ; system call argument. 3972 <1> 3973 00004188 891D[04650000] <1> mov [u.namep], ebx 3974 <1> ; jsr r0,arg; u.namep / u.namep points to path name 3975 0000418E E844FEFFFF <1> call namei 3976 <1> ; jsr r0,namei / find its i-number 3977 <1> ;jc error 3978 <1> ; br error3 3979 00004193 730F <1> jnc short syschdir0 3980 <1> ; 'directory not found !' error 3981 00004195 C705[41650000]0C00- <1> mov dword [u.error], ERR_DIR_NOT_FOUND ; 12 3981 0000419D 0000 <1> 3982 0000419F E927EFFFFF <1> jmp error 3983 <1> syschdir0: 3984 <1> ; 08/01/2022 3985 000041A4 B202 <1> mov dl, 2 ; read access ; 08/01/2022 (BugFix) 3986 000041A6 E810070000 <1> call access 3987 <1> ; jsr r0,access; 2 / get i-node into core 3988 <1> ; 08/01/2022 3989 000041AB F605[E5610000]40 <1> test byte [i.flgs+1], 40h 3990 <1> ;test word [i.flgs], 4000h 3991 <1> ; bit $40000,i.flgs / is it a directory? 3992 <1> ;jz error 3993 <1> ; beq error3 / no error 3994 000041B2 750F <1> jnz short syschdir1 3995 000041B4 C705[41650000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 3995 000041BC 0000 <1> 3996 000041BE E908EFFFFF <1> jmp error 3997 <1> syschdir1: 3998 000041C3 66A3[F0640000] <1> mov [u.cdir], ax 3999 <1> ; mov r1,u.cdir / move i-number to users 4000 <1> ; / current directory 4001 <1> ; 09/01/2022 4002 000041C9 A0[D3640000] <1> mov al, [cdev] 4003 000041CE A2[36650000] <1> mov [u.cdrv], al 4004 <1> ;mov ax, [cdev] 4005 <1> ;mov [u.cdrv], ax 4006 <1> ; mov cdev,u.cdev / move its device to users 4007 <1> ; / current device 4008 000041D3 E913EFFFFF <1> jmp sysret 4009 <1> ; br sysret3 4010 <1> 4011 <1> syschmod: ; < change mode of file > 4012 <1> ; 29/04/2022 (bugfix) 4013 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 4014 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4015 <1> ; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1) 4016 <1> ; 4017 <1> ; 'syschmod' changes mode of the file whose name is given as 4018 <1> ; null terminated string pointed to by 'name' has it's mode 4019 <1> ; changed to 'mode'. 4020 <1> ; 4021 <1> ; Calling sequence: 4022 <1> ; syschmod; name; mode 4023 <1> ; Arguments: 4024 <1> ; name - address of the file name 4025 <1> ; terminated by null byte. 4026 <1> ; mode - (new) mode/flags < attributes > 4027 <1> ; 4028 <1> ; Inputs: - 4029 <1> ; Outputs: - 4030 <1> ; ............................................................... 4031 <1> ; 4032 <1> ; Retro UNIX 8086 v1 modification: 4033 <1> ; 'syschmod' system call has two arguments; so, 4034 <1> ; * 1st argument, name is pointed to by BX register 4035 <1> ; * 2nd argument, mode is in CX register 4036 <1> ; 4037 <1> ; Mode bits (Flags): 4038 <1> ; bit 15 - 'i-node is allocated' flag (8000h) 4039 <1> ; bit 14 - directory flag (4000h) 4040 <1> ; bit 13 - file has modified flag (always on) (2000h) 4041 <1> ; bit 12 - large file flag (1000h) 4042 <1> ; bit 6,7,8,9,10,11 are not used (undefined) 4043 <1> ; bit 5 - set user ID on execution flag (20h) 4044 <1> ; bit 4 - executable flag (10h) 4045 <1> ; bit 3 - read permission for owner (08h) 4046 <1> ; bit 2 - write permission for owner (04h) 4047 <1> ; bit 1 - read permission for non-owner (02h) 4048 <1> ; bit 0 - write permission for non-owner (01h) 4049 <1> 4050 <1> ; / name; mode 4051 000041D8 E815000000 <1> call isown 4052 <1> ;jsr r0,isown / get the i-node and check user status 4053 <1> ; 09/01/2022 4054 000041DD F605[E5610000]40 <1> test byte [i.flgs+1], 40h 4055 <1> ;test word [i.flgs], 4000h 4056 <1> ; bit $40000,i.flgs / directory? 4057 000041E4 7402 <1> jz short syschmod1 4058 <1> ; beq 2f / no 4059 <1> ; AL = (new) mode 4060 000041E6 24CF <1> and al, 0CFh ; 11001111b (clears bit 4 & 5) 4061 <1> ; bic $60,r2 / su & ex / yes, clear set user id and 4062 <1> ; / executable modes 4063 <1> syschmod1: ; 2: 4064 000041E8 A2[E4610000] <1> mov [i.flgs], al 4065 <1> ; movb r2,i.flgs / move remaining mode to i.flgs 4066 <1> ;jmp short isown1 4067 <1> ; ; br 1f ; (jmp sysret4) 4068 <1> ; 29/04/2022 4069 000041ED E9F9EEFFFF <1> jmp sysret 4070 <1> 4071 <1> isown: 4072 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4073 <1> ; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1) 4074 <1> ; 4075 <1> ; 'isown' is given a file name (the 1st argument). 4076 <1> ; It find the i-number of that file via 'namei' 4077 <1> ; then gets the i-node into core via 'iget'. 4078 <1> ; It then tests to see if the user is super user. 4079 <1> ; If not, it cheks to see if the user is owner of 4080 <1> ; the file. If he is not an error occurs. 4081 <1> ; If user is the owner 'setimod' is called to indicate 4082 <1> ; the inode has been modified and the 2nd argument of 4083 <1> ; the call is put in r2. 4084 <1> ; 4085 <1> ; INPUTS -> 4086 <1> ; arguments of syschmod and syschown calls 4087 <1> ; OUTPUTS -> 4088 <1> ; u.uid - id of user 4089 <1> ; imod - set to a 1 4090 <1> ; r2 - contains second argument of the system call 4091 <1> ; 4092 <1> ; ((AX=R2) output as 2nd argument) 4093 <1> ; 4094 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 4095 <1> ; 4096 <1> ; jsr r0,arg2 / u.namep points to file name 4097 <1> ;; ! 2nd argument on top of stack ! 4098 <1> ;; 22/06/2015 - 32 bit modifications 4099 <1> ;; 07/07/2013 4100 000041F2 891D[04650000] <1> mov [u.namep], ebx ;; 1st argument 4101 000041F8 51 <1> push ecx ;; 2nd argument 4102 <1> ;; 4103 000041F9 E8D9FDFFFF <1> call namei 4104 <1> ; jsr r0,namei / get its i-number 4105 <1> ; Retro UNIX 8086 v1 modification ! 4106 <1> ; ax = 0 -> file not found 4107 <1> ;and ax, ax 4108 <1> ;jz error 4109 <1> ;jc error ; 27/05/2013 4110 <1> ; br error3 4111 000041FE 730F <1> jnc short isown0 4112 <1> ; 'file not found !' error 4113 00004200 C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 4113 00004208 0000 <1> 4114 0000420A E9BCEEFFFF <1> jmp error 4115 <1> isown0: 4116 0000420F E8D3050000 <1> call iget 4117 <1> ; jsr r0,iget / get i-node into core 4118 00004214 A0[38650000] <1> mov al, [u.uid] ; 02/08/2013 4119 00004219 08C0 <1> or al, al 4120 <1> ; tstb u.uid / super user? 4121 0000421B 7417 <1> jz short isown1 4122 <1> ; beq 1f / yes, branch 4123 0000421D 3A05[E7610000] <1> cmp al, [i.uid] 4124 <1> ; cmpb i.uid,u.uid / no, is this the owner of 4125 <1> ; / the file 4126 <1> ;jne error 4127 <1> ; beq 1f / yes 4128 <1> ; jmp error3 / no, error 4129 00004223 740F <1> je short isown1 4130 <1> 4131 00004225 C705[41650000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER ; 11 4131 0000422D 0000 <1> 4132 <1> ; 'permission denied !' error 4133 0000422F E997EEFFFF <1> jmp error 4134 <1> isown1: ; 1: 4135 00004234 E8B8060000 <1> call setimod 4136 <1> ; jsr r0,setimod / indicates 4137 <1> ; ; / i-node has been modified 4138 00004239 58 <1> pop eax ; 2nd argument 4139 <1> ; mov (sp)+,r2 / mode is put in r2 4140 <1> ; / (u.off put on stack with 2nd arg) 4141 0000423A C3 <1> retn 4142 <1> ; rts r0 4143 <1> 4144 <1> ;;arg: ; < get system call arguments > 4145 <1> ; 'arg' extracts an argument for a routine whose call is 4146 <1> ; of form: 4147 <1> ; sys 'routine' ; arg1 4148 <1> ; or 4149 <1> ; sys 'routine' ; arg1 ; arg2 4150 <1> ; or 4151 <1> ; sys 'routine' ; arg1;...;arg10 (sys exec) 4152 <1> ; 4153 <1> ; INPUTS -> 4154 <1> ; u.sp+18 - contains a pointer to one of arg1..argn 4155 <1> ; This pointers's value is actually the value of 4156 <1> ; update pc at the the trap to sysent (unkni) is 4157 <1> ; made to process the sys instruction 4158 <1> ; r0 - contains the return address for the routine 4159 <1> ; that called arg. The data in the word pointer 4160 <1> ; to by the return address is used as address 4161 <1> ; in which the extracted argument is stored 4162 <1> ; 4163 <1> ; OUTPUTS -> 4164 <1> ; 'address' - contains the extracted argument 4165 <1> ; u.sp+18 - is incremented by 2 4166 <1> ; r1 - contains the extracted argument 4167 <1> ; r0 - points to the next instruction to be 4168 <1> ; executed in the calling routine. 4169 <1> ; 4170 <1> 4171 <1> ; mov u.sp,r1 4172 <1> ; mov *18.(r1),*(r0)+ / put argument of system call 4173 <1> ; / into argument of arg2 4174 <1> ; add $2,18.(r1) / point pc on stack 4175 <1> ; / to next system argument 4176 <1> ; rts r0 4177 <1> 4178 <1> ;;arg2: ; < get system calls arguments - with file name pointer> 4179 <1> ; 'arg2' takes first argument in system call 4180 <1> ; (pointer to name of the file) and puts it in location 4181 <1> ; u.namep; takes second argument and puts it in u.off 4182 <1> ; and on top of the stack 4183 <1> ; 4184 <1> ; INPUTS -> 4185 <1> ; u.sp, r0 4186 <1> ; 4187 <1> ; OUTPUTS -> 4188 <1> ; u.namep 4189 <1> ; u.off 4190 <1> ; u.off pushed on stack 4191 <1> ; r1 4192 <1> ; 4193 <1> 4194 <1> ; jsr r0,arg; u.namep / u.namep contains value of 4195 <1> ; / first arg in sys call 4196 <1> ; jsr r0,arg; u.off / u.off contains value of 4197 <1> ; / second arg in sys call 4198 <1> ; mov r0,r1 / r0 points to calling routine 4199 <1> ; mov (sp),r0 / put operation code back in r0 4200 <1> ; mov u.off,(sp) / put pointer to second argument 4201 <1> ; / on stack 4202 <1> ; jmp (r1) / return to calling routine 4203 <1> 4204 <1> syschown: ; < change owner of file > 4205 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4206 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4207 <1> ; 4208 <1> ; 'syschown' changes the owner of the file whose name is given 4209 <1> ; as null terminated string pointed to by 'name' has it's owner 4210 <1> ; changed to 'owner' 4211 <1> ; 4212 <1> ; Calling sequence: 4213 <1> ; syschown; name; owner 4214 <1> ; Arguments: 4215 <1> ; name - address of the file name 4216 <1> ; terminated by null byte. 4217 <1> ; owner - (new) owner (number/ID) 4218 <1> ; 4219 <1> ; Inputs: - 4220 <1> ; Outputs: - 4221 <1> ; ............................................................... 4222 <1> ; 4223 <1> ; Retro UNIX 8086 v1 modification: 4224 <1> ; 'syschown' system call has two arguments; so, 4225 <1> ; * 1st argument, name is pointed to by BX register 4226 <1> ; * 2nd argument, owner number is in CX register 4227 <1> ; 4228 <1> ; / name; owner 4229 0000423B E8B2FFFFFF <1> call isown 4230 <1> ; jsr r0,isown / get the i-node and check user status 4231 00004240 803D[38650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 4232 <1> ; tstb u.uid / super user 4233 00004247 7418 <1> jz short syschown1 4234 <1> ; beq 2f / yes, 2f 4235 00004249 F605[E4610000]20 <1> test byte [i.flgs], 20h ; 32 4236 <1> ; bit $40,i.flgs / no, set userid on execution? 4237 <1> ;jnz error 4238 <1> ; bne 3f / yes error, could create Trojan Horses 4239 00004250 740F <1> jz short syschown1 4240 <1> ; 'permission denied !' 4241 00004252 C705[41650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; 11 4241 0000425A 0000 <1> 4242 0000425C E96AEEFFFF <1> jmp error 4243 <1> syschown1: ; 2: 4244 <1> ; AL = owner (number/ID) 4245 00004261 A2[E7610000] <1> mov [i.uid], al ; 23/06/2015 4246 <1> ; movb r2,i.uid / no, put the new owners id 4247 <1> ; / in the i-node 4248 00004266 E980EEFFFF <1> jmp sysret 4249 <1> ; 1: 4250 <1> ; jmp sysret4 4251 <1> ; 3: 4252 <1> ; jmp error 4253 <1> 4254 <1> systime: ; / get time of year 4255 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4256 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 4257 <1> ; 4258 <1> ; 20/06/2013 4259 <1> ; 'systime' gets the time of the year. 4260 <1> ; The present time is put on the stack. 4261 <1> ; 4262 <1> ; Calling sequence: 4263 <1> ; systime 4264 <1> ; Arguments: - 4265 <1> ; 4266 <1> ; Inputs: - 4267 <1> ; Outputs: sp+2, sp+4 - present time 4268 <1> ; ............................................................... 4269 <1> ; 4270 <1> ; Retro UNIX 8086 v1 modification: 4271 <1> ; 'systime' system call will return to the user 4272 <1> ; with unix time (epoch) in DX:AX register pair 4273 <1> ; 4274 <1> ; !! Major modification on original Unix v1 'systime' 4275 <1> ; system call for PC compatibility !! 4276 <1> 4277 0000426B E8ACE9FFFF <1> call epoch 4278 00004270 A3[EC640000] <1> mov [u.r0], eax 4279 <1> ; mov s.time,4(sp) 4280 <1> ; mov s.time+2,2(sp) / put the present time 4281 <1> ; / on the stack 4282 <1> ; br sysret4 4283 00004275 E971EEFFFF <1> jmp sysret 4284 <1> 4285 <1> sysstime: ; / set time 4286 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4287 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4288 <1> ; 4289 <1> ; 'sysstime' sets the time. Only super user can use this call. 4290 <1> ; 4291 <1> ; Calling sequence: 4292 <1> ; sysstime 4293 <1> ; Arguments: - 4294 <1> ; 4295 <1> ; Inputs: sp+2, sp+4 - time system is to be set to. 4296 <1> ; Outputs: - 4297 <1> ; ............................................................... 4298 <1> ; 4299 <1> ; Retro UNIX 8086 v1 modification: 4300 <1> ; the user calls 'sysstime' with unix (epoch) time 4301 <1> ; (to be set) is in CX:BX register pair as two arguments. 4302 <1> ; 4303 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 4304 <1> ; to get sysstime system call arguments from the user; 4305 <1> ; * 1st argument, lowword of unix time is in BX register 4306 <1> ; * 2nd argument, highword of unix time is in CX register 4307 <1> ; 4308 <1> ; !! Major modification on original Unix v1 'sysstime' 4309 <1> ; system call for PC compatibility !! 4310 <1> 4311 0000427A 803D[38650000]00 <1> cmp byte [u.uid], 0 4312 <1> ; tstb u.uid / is user the super user 4313 <1> ;ja error 4314 <1> ; bne error4 / no, error 4315 00004281 760F <1> jna short systime1 4316 <1> ; 'permission denied !' 4317 00004283 C705[41650000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 4317 0000428B 0000 <1> 4318 0000428D E939EEFFFF <1> jmp error 4319 <1> systime1: 4320 <1> ; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version) 4321 <1> ; EBX = unix (epoch) time (from user) 4322 00004292 89D8 <1> mov eax, ebx 4323 00004294 E800EBFFFF <1> call set_date_time 4324 <1> ; mov 4(sp),s.time 4325 <1> ; mov 2(sp),s.time+2 / set the system time 4326 00004299 E94DEEFFFF <1> jmp sysret 4327 <1> ; br sysret4 4328 <1> 4329 <1> sysbreak: 4330 <1> ; 18/10/2015 4331 <1> ; 07/10/2015 4332 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 4333 <1> ; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1) 4334 <1> ; 4335 <1> ; 'sysbreak' sets the programs break points. 4336 <1> ; It checks the current break point (u.break) to see if it is 4337 <1> ; between "core" and the stack (sp). If it is, it is made an 4338 <1> ; even address (if it was odd) and the area between u.break 4339 <1> ; and the stack is cleared. The new breakpoint is then put 4340 <1> ; in u.break and control is passed to 'sysret'. 4341 <1> ; 4342 <1> ; Calling sequence: 4343 <1> ; sysbreak; addr 4344 <1> ; Arguments: - 4345 <1> ; 4346 <1> ; Inputs: u.break - current breakpoint 4347 <1> ; Outputs: u.break - new breakpoint 4348 <1> ; area between old u.break and the stack (sp) is cleared. 4349 <1> ; ............................................................... 4350 <1> ; 4351 <1> ; Retro UNIX 8086 v1 modification: 4352 <1> ; The user/application program puts breakpoint address 4353 <1> ; in BX register as 'sysbreak' system call argument. 4354 <1> ; (argument transfer method 1) 4355 <1> ; 4356 <1> ; NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 ! 4357 <1> ; ((!'sysbreak' is not needed in Retro UNIX 8086 v1!)) 4358 <1> ; NOTE: 4359 <1> ; 'sysbreak' clears extended part (beyond of previous 4360 <1> ; 'u.break' address) of user's memory for original unix's 4361 <1> ; 'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013) 4362 <1> 4363 <1> ; mov u.break,r1 / move users break point to r1 4364 <1> ; cmp r1,$core / is it the same or lower than core? 4365 <1> ; blos 1f / yes, 1f 4366 <1> ; 23/06/2015 4367 0000429E 8B2D[18650000] <1> mov ebp, [u.break] ; virtual address (offset) 4368 <1> ;and ebp, ebp 4369 <1> ;jz short sysbreak_3 4370 <1> ; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!! 4371 <1> ; (Even break point address is not needed for Retro UNIX 386 v1) 4372 000042A4 8B15[E4640000] <1> mov edx, [u.sp] ; kernel stack at the beginning of sys call 4373 000042AA 83C20C <1> add edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 4374 <1> ; 07/10/2015 4375 000042AD 891D[18650000] <1> mov [u.break], ebx ; virtual address !!! 4376 <1> ; 4377 000042B3 3B1A <1> cmp ebx, [edx] ; compare new break point with 4378 <1> ; with top of user's stack (virtual!) 4379 000042B5 7327 <1> jnb short sysbreak_3 4380 <1> ; cmp r1,sp / is it the same or higher 4381 <1> ; / than the stack? 4382 <1> ; bhis 1f / yes, 1f 4383 000042B7 89DE <1> mov esi, ebx 4384 000042B9 29EE <1> sub esi, ebp ; new break point - old break point 4385 000042BB 7621 <1> jna short sysbreak_3 4386 <1> ;push ebx 4387 <1> sysbreak_1: 4388 000042BD 89EB <1> mov ebx, ebp 4389 000042BF E8E5E4FFFF <1> call get_physical_addr ; get physical address 4390 000042C4 0F82ABFEFFFF <1> jc tr_addr_nm_err 4391 <1> ; 18/10/2015 4392 000042CA 89C7 <1> mov edi, eax 4393 000042CC 29C0 <1> sub eax, eax ; 0 4394 <1> ; ECX = remain byte count in page (1-4096) 4395 000042CE 39CE <1> cmp esi, ecx 4396 000042D0 7302 <1> jnb short sysbreak_2 4397 000042D2 89F1 <1> mov ecx, esi 4398 <1> sysbreak_2: 4399 000042D4 29CE <1> sub esi, ecx 4400 000042D6 01CD <1> add ebp, ecx 4401 000042D8 F3AA <1> rep stosb 4402 000042DA 09F6 <1> or esi, esi 4403 000042DC 75DF <1> jnz short sysbreak_1 4404 <1> ; 4405 <1> ; bit $1,r1 / is it an odd address 4406 <1> ; beq 2f / no, its even 4407 <1> ; clrb (r1)+ / yes, make it even 4408 <1> ; 2: / clear area between the break point and the stack 4409 <1> ; cmp r1,sp / is it higher or same than the stack 4410 <1> ; bhis 1f / yes, quit 4411 <1> ; clr (r1)+ / clear word 4412 <1> ; br 2b / go back 4413 <1> ;pop ebx 4414 <1> sysbreak_3: ; 1: 4415 <1> ;mov [u.break], ebx ; virtual address !!! 4416 <1> ; jsr r0,arg; u.break / put the "address" 4417 <1> ; / in u.break (set new break point) 4418 <1> ; br sysret4 / br sysret 4419 000042DE E908EEFFFF <1> jmp sysret 4420 <1> 4421 <1> maknod: 4422 <1> ; 11/02/2022 4423 <1> ; 09/01/2022 4424 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4425 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4426 <1> ; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4427 <1> ; 4428 <1> ; 'maknod' creates an i-node and makes a directory entry 4429 <1> ; for this i-node in the current directory. 4430 <1> ; 4431 <1> ; INPUTS -> 4432 <1> ; r1 - contains mode 4433 <1> ; ii - current directory's i-number 4434 <1> ; 4435 <1> ; OUTPUTS -> 4436 <1> ; u.dirbuf - contains i-number of free i-node 4437 <1> ; i.flgs - flags in new i-node 4438 <1> ; i.uid - filled with u.uid 4439 <1> ; i.nlks - 1 is put in the number of links 4440 <1> ; i.ctim - creation time 4441 <1> ; i.ctim+2 - modification time 4442 <1> ; imod - set via call to setimod 4443 <1> ; 4444 <1> ; ((AX = R1)) input 4445 <1> ; 4446 <1> ; (Retro UNIX Prototype : 4447 <1> ; 30/10/2012 - 01/03/2013, UNIXCOPY.ASM) 4448 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 4449 <1> 4450 <1> ; / r1 contains the mode 4451 000042E3 80CC80 <1> or ah, 80h ; 10000000b 4452 <1> ; bis $100000,r1 / allocate flag set 4453 000042E6 6650 <1> push ax ; * ; 24/12/2021 4454 <1> ; mov r1,-(sp) / put mode on stack 4455 <1> ; 31/07/2013 4456 000042E8 66A1[D0640000] <1> mov ax, [ii] ; move current i-number to AX/r1 4457 <1> ; mov ii,r1 / move current i-number to r1 4458 000042EE B201 <1> mov dl, 1 ; owner flag mask 4459 000042F0 E8C6050000 <1> call access 4460 <1> ; jsr r0,access; 1 / get its i-node into core 4461 000042F5 50 <1> push eax ; ** ; 24/12/2021 4462 <1> ; mov r1,-(sp) / put i-number on stack 4463 000042F6 66B82800 <1> mov ax, 40 4464 <1> ; mov $40.,r1 / r1 = 40 4465 <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions) 4466 000042FA 6640 <1> inc ax 4467 <1> ; inc r1 / r1 = r1 + 1 4468 000042FC E87F060000 <1> call imap 4469 <1> ; jsr r0,imap / get byte address and bit position in 4470 <1> ; / inode map in r2 & m 4471 <1> 4472 <1> ; DX (MQ) has a 1 in the calculated bit position 4473 <1> ; eBX (R2) has byte address of the byte with allocation bit 4474 <1> 4475 <1> ; 22/06/2015 - NOTE for next Retro UNIX version: 4476 <1> ; Inode count must be checked here 4477 <1> ; (Original UNIX v1 did not check inode count here !?) 4478 <1> 4479 <1> ; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 4480 <1> ; (inode count check) 4481 <1> ; ((if cf=1 --> requested inode number > inode count)) 4482 <1> 4483 00004301 730F <1> jnc short maknod2 4484 <1> 4485 <1> ; no free inode in inode table ! 4486 00004303 C705[41650000]1B00- <1> mov dword [u.error], ERR_MISC ; 27 4486 0000430B 0000 <1> 4487 <1> ; miscellaneous/other errors 4488 0000430D E9B9EDFFFF <1> jmp error 4489 <1> maknod2: 4490 00004312 8413 <1> test [ebx], dl 4491 <1> ; bitb mq,(r2) / is the i-node active 4492 00004314 75E4 <1> jnz short maknod1 4493 <1> ; bne 1b / yes, try the next one 4494 00004316 0813 <1> or [ebx], dl 4495 <1> ; bisb mq,(r2) / no, make it active 4496 <1> ; / (put a 1 in the bit map) 4497 00004318 E8CA040000 <1> call iget 4498 <1> ; jsr r0,iget / get i-node into core 4499 <1> ; 09/01/2022 4500 0000431D F605[E5610000]80 <1> test byte [i.flgs+1], 80h 4501 <1> ;test word [i.flgs], 8000h 4502 <1> ; tst i.flgs / is i-node already allocated 4503 00004324 75D4 <1> jnz short maknod1 4504 <1> ; blt 1b / yes, look for another one 4505 00004326 66A3[1E650000] <1> mov [u.dirbuf], ax 4506 <1> ; mov r1,u.dirbuf / no, put i-number in u.dirbuf 4507 0000432C 58 <1> pop eax ; ** ; 24/12/2021 4508 <1> ; mov (sp)+,r1 / get current i-number back 4509 0000432D E8B5040000 <1> call iget 4510 <1> ; jsr r0,iget / get i-node in core 4511 00004332 E857F7FFFF <1> call mkdir 4512 <1> ; jsr r0,mkdir / make a directory entry 4513 <1> ; / in current directory 4514 00004337 66A1[1E650000] <1> mov ax, [u.dirbuf] 4515 <1> ; mov u.dirbuf,r1 / r1 = new inode number 4516 0000433D E8A5040000 <1> call iget 4517 <1> ; jsr r0,iget / get it into core 4518 <1> ; jsr r0,copyz; inode; inode+32. / 0 it out 4519 <1> ;mov ecx, 8 4520 <1> ; 09/01/2022 4521 00004342 29C9 <1> sub ecx, ecx 4522 00004344 B108 <1> mov cl, 8 4523 00004346 31C0 <1> xor eax, eax ; 0 4524 00004348 BF[E4610000] <1> mov edi, inode 4525 0000434D F3AB <1> rep stosd 4526 <1> ; 4527 0000434F 668F05[E4610000] <1> pop word [i.flgs] ; * ; 24/12/2021 4528 <1> ; mov (sp)+,i.flgs / fill flags 4529 00004356 8A0D[38650000] <1> mov cl, [u.uid] ; 02/08/2013 4530 0000435C 880D[E7610000] <1> mov [i.uid], cl 4531 <1> ; movb u.uid,i.uid / user id 4532 00004362 C605[E6610000]01 <1> mov byte [i.nlks], 1 4533 <1> ; movb $1,i.nlks / 1 link 4534 <1> ;call epoch ; Retro UNIX 8086 v1 modification ! 4535 <1> ;mov eax, [s.time] 4536 <1> ;mov [i.ctim], eax 4537 <1> ; mov s.time,i.ctim / time created 4538 <1> ; mov s.time+2,i.ctim+2 / time modified 4539 <1> ; Retro UNIX 8086 v1 modification ! 4540 <1> ; i.ctime=0, i.ctime+2=0 and 4541 <1> ; 'setimod' will set ctime of file via 'epoch' 4542 <1> ;call setimod 4543 <1> ; ; jsr r0,setimod / set modified flag 4544 <1> ;retn 4545 <1> ; ; rts r0 / return 4546 <1> ; 24/12/2021 4547 00004369 E983050000 <1> jmp setimod 4548 <1> 4549 <1> sysseek: ; / moves read write pointer in an fsp entry 4550 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4551 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 4552 <1> ; 4553 <1> ; 'sysseek' changes the r/w pointer of (3rd word of in an 4554 <1> ; fsp entry) of an open file whose file descriptor is in u.r0. 4555 <1> ; The file descriptor refers to a file open for reading or 4556 <1> ; writing. The read (or write) pointer is set as follows: 4557 <1> ; * if 'ptrname' is 0, the pointer is set to offset. 4558 <1> ; * if 'ptrname' is 1, the pointer is set to its 4559 <1> ; current location plus offset. 4560 <1> ; * if 'ptrname' is 2, the pointer is set to the 4561 <1> ; size of file plus offset. 4562 <1> ; The error bit (e-bit) is set for an undefined descriptor. 4563 <1> ; 4564 <1> ; Calling sequence: 4565 <1> ; sysseek; offset; ptrname 4566 <1> ; Arguments: 4567 <1> ; offset - number of bytes desired to move 4568 <1> ; the r/w pointer 4569 <1> ; ptrname - a switch indicated above 4570 <1> ; 4571 <1> ; Inputs: r0 - file descriptor 4572 <1> ; Outputs: - 4573 <1> ; ............................................................... 4574 <1> ; 4575 <1> ; Retro UNIX 8086 v1 modification: 4576 <1> ; 'sysseek' system call has three arguments; so, 4577 <1> ; * 1st argument, file descriptor is in BX (BL) register 4578 <1> ; * 2nd argument, offset is in CX register 4579 <1> ; * 3rd argument, ptrname/switch is in DX (DL) register 4580 <1> ; 4581 <1> 4582 0000436E E822000000 <1> call seektell 4583 <1> ; AX = u.count 4584 <1> ; BX = *u.fofp 4585 <1> ; jsr r0,seektell / get proper value in u.count 4586 <1> ; add u.base,u.count / add u.base to it 4587 00004373 0305[0C650000] <1> add eax, [u.base] ; add offset (u.base) to base 4588 00004379 8903 <1> mov [ebx], eax 4589 <1> ; mov u.count,*u.fofp / put result into r/w pointer 4590 0000437B E96BEDFFFF <1> jmp sysret 4591 <1> ; br sysret4 4592 <1> 4593 <1> systell: ; / get the r/w pointer 4594 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 4595 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4596 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 4597 <1> ; 4598 <1> ; Retro UNIX 8086 v1 modification: 4599 <1> ; ! 'systell' does not work in original UNIX v1, 4600 <1> ; it returns with error ! 4601 <1> ; Inputs: r0 - file descriptor 4602 <1> ; Outputs: r0 - file r/w pointer 4603 <1> 4604 <1> ;xor ecx, ecx ; 0 4605 <1> ;mov edx, 1 ; 05/08/2013 4606 <1> ; 24/12/2021 4607 00004380 29D2 <1> sub edx, edx 4608 00004382 FEC2 <1> inc dl 4609 <1> ; edx = 1 4610 <1> ;call seektell 4611 00004384 E812000000 <1> call seektell0 ; 05/08/2013 4612 <1> ;mov ebx, [u.fofp] 4613 00004389 8B03 <1> mov eax, [ebx] 4614 0000438B A3[EC640000] <1> mov [u.r0], eax 4615 00004390 E956EDFFFF <1> jmp sysret 4616 <1> 4617 <1> ; Original unix v1 'systell' system call: 4618 <1> ; jsr r0,seektell 4619 <1> ; br error4 4620 <1> 4621 <1> seektell: 4622 <1> ; 03/02/2022 4623 <1> ; 03/01/2016 4624 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4625 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 4626 <1> ; 4627 <1> ; 'seektell' puts the arguments from sysseek and systell 4628 <1> ; call in u.base and u.count. It then gets the i-number of 4629 <1> ; the file from the file descriptor in u.r0 and by calling 4630 <1> ; getf. The i-node is brought into core and then u.count 4631 <1> ; is checked to see it is a 0, 1, or 2. 4632 <1> ; If it is 0 - u.count stays the same 4633 <1> ; 1 - u.count = offset (u.fofp) 4634 <1> ; 2 - u.count = i.size (size of file) 4635 <1> ; 4636 <1> ; !! Retro UNIX 8086 v1 modification: 4637 <1> ; Argument 1, file descriptor is in BX; 4638 <1> ; Argument 2, offset is in CX; 4639 <1> ; Argument 3, ptrname/switch is in DX register. 4640 <1> ; 4641 <1> ; mov ax, 3 ; Argument transfer method 3 (three arguments) 4642 <1> ; call arg 4643 <1> ; 4644 <1> ; ((Return -> ax = base for offset (position= base+offset)) 4645 <1> ; 4646 00004395 890D[0C650000] <1> mov [u.base], ecx ; offset 4647 <1> ; jsr r0,arg; u.base / puts offset in u.base 4648 <1> seektell0: 4649 0000439B 8915[10650000] <1> mov [u.count], edx 4650 <1> ; jsr r0,arg; u.count / put ptr name in u.count 4651 <1> ; mov ax, bx 4652 <1> ; mov *u.r0,r1 / file descriptor in r1 4653 <1> ; / (index in u.fp list) 4654 <1> ; call getf 4655 <1> ; jsr r0,getf / u.fofp points to 3rd word in fsp entry 4656 <1> ; BX = file descriptor (file number) 4657 000043A1 E800FCFFFF <1> call getf1 4658 <1> ; 03/02/2022 4659 000043A6 09C0 <1> or eax, eax 4660 <1> ;or ax, ax ; i-number of the file 4661 <1> ; mov r1,-(sp) / r1 has i-number of file, 4662 <1> ; / put it on the stack 4663 <1> ;jz error 4664 <1> ; beq error4 / if i-number is 0, not active so error 4665 000043A8 750F <1> jnz short seektell1 4666 000043AA C705[41650000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 4666 000043B2 0000 <1> 4667 000043B4 E912EDFFFF <1> jmp error 4668 <1> seektell1: 4669 <1> ;push eax 4670 000043B9 80FC80 <1> cmp ah, 80h 4671 000043BC 7203 <1> jb short seektell2 4672 <1> ; bgt .+4 / if its positive jump 4673 000043BE 66F7D8 <1> neg ax 4674 <1> ; neg r1 / if not make it positive 4675 <1> seektell2: 4676 000043C1 E821040000 <1> call iget 4677 <1> ; jsr r0,iget / get its i-node into core 4678 000043C6 8B1D[FC640000] <1> mov ebx, [u.fofp] ; 05/08/2013 4679 000043CC 803D[10650000]01 <1> cmp byte [u.count], 1 4680 <1> ; cmp u.count,$1 / is ptr name =1 4681 000043D3 7705 <1> ja short seektell3 4682 <1> ; blt 2f / no its zero 4683 000043D5 740A <1> je short seektell_4 4684 <1> ; beq 1f / yes its 1 4685 000043D7 31C0 <1> xor eax, eax 4686 <1> ;jmp short seektell_5 4687 000043D9 C3 <1> retn 4688 <1> seektell3: 4689 <1> ; 03/01/2016 4690 <1> ;movzx eax, word [i.size] 4691 000043DA 66A1[E8610000] <1> mov ax, [i.size] 4692 <1> ; mov i.size,u.count / put number of bytes 4693 <1> ; / in file in u.count 4694 <1> ;jmp short seektell_5 4695 <1> ; br 2f 4696 000043E0 C3 <1> retn 4697 <1> seektell_4: ; 1: / ptrname =1 4698 <1> ;mov ebx, [u.fofp] 4699 000043E1 8B03 <1> mov eax, [ebx] 4700 <1> ; mov *u.fofp,u.count / put offset in u.count 4701 <1> ;seektell_5: ; 2: / ptrname =0 4702 <1> ;mov [u.count], eax 4703 <1> ;pop eax 4704 <1> ; mov (sp)+,r1 / i-number on stack r1 4705 000043E3 C3 <1> retn 4706 <1> ; rts r0 4707 <1> 4708 <1> sysintr: ; / set interrupt handling 4709 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4710 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 4711 <1> ; 4712 <1> ; 'sysintr' sets the interrupt handling value. It puts 4713 <1> ; argument of its call in u.intr then branches into 'sysquit' 4714 <1> ; routine. u.tty is checked if to see if a control tty exists. 4715 <1> ; If one does the interrupt character in the tty buffer is 4716 <1> ; cleared and 'sysret'is called. If one does not exits 4717 <1> ; 'sysret' is just called. 4718 <1> ; 4719 <1> ; Calling sequence: 4720 <1> ; sysintr; arg 4721 <1> ; Argument: 4722 <1> ; arg - if 0, interrupts (ASCII DELETE) are ignored. 4723 <1> ; - if 1, intterupts cause their normal result 4724 <1> ; i.e force an exit. 4725 <1> ; - if arg is a location within the program, 4726 <1> ; control is passed to that location when 4727 <1> ; an interrupt occurs. 4728 <1> ; Inputs: - 4729 <1> ; Outputs: - 4730 <1> ; ............................................................... 4731 <1> ; 4732 <1> ; Retro UNIX 8086 v1 modification: 4733 <1> ; 'sysintr' system call sets u.intr to value of BX 4734 <1> ; then branches into sysquit. 4735 <1> ; 4736 000043E4 66891D[30650000] <1> mov [u.intr], bx 4737 <1> ; jsr r0,arg; u.intr / put the argument in u.intr 4738 <1> ; br 1f / go into quit routine 4739 000043EB E9FBECFFFF <1> jmp sysret 4740 <1> 4741 <1> sysquit: 4742 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4743 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 4744 <1> ; 4745 <1> ; 'sysquit' turns off the quit signal. it puts the argument of 4746 <1> ; the call in u.quit. u.tty is checked if to see if a control 4747 <1> ; tty exists. If one does the interrupt character in the tty 4748 <1> ; buffer is cleared and 'sysret'is called. If one does not exits 4749 <1> ; 'sysret' is just called. 4750 <1> ; 4751 <1> ; Calling sequence: 4752 <1> ; sysquit; arg 4753 <1> ; Argument: 4754 <1> ; arg - if 0, this call diables quit signals from the 4755 <1> ; typewriter (ASCII FS) 4756 <1> ; - if 1, quits are re-enabled and cause execution to 4757 <1> ; cease and a core image to be produced. 4758 <1> ; i.e force an exit. 4759 <1> ; - if arg is an addres in the program, 4760 <1> ; a quit causes control to sent to that 4761 <1> ; location. 4762 <1> ; Inputs: - 4763 <1> ; Outputs: - 4764 <1> ; ............................................................... 4765 <1> ; 4766 <1> ; Retro UNIX 8086 v1 modification: 4767 <1> ; 'sysquit' system call sets u.quit to value of BX 4768 <1> ; then branches into 'sysret'. 4769 <1> ; 4770 000043F0 66891D[32650000] <1> mov [u.quit], bx 4771 000043F7 E9EFECFFFF <1> jmp sysret 4772 <1> ; jsr r0,arg; u.quit / put argument in u.quit 4773 <1> ;1: 4774 <1> ; mov u.ttyp,r1 / move pointer to control tty buffer 4775 <1> ; / to r1 4776 <1> ; beq sysret4 / return to user 4777 <1> ; clrb 6(r1) / clear the interrupt character 4778 <1> ; / in the tty buffer 4779 <1> ; br sysret4 / return to user 4780 <1> 4781 <1> syssetuid: ; / set process id 4782 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4783 <1> ; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1) 4784 <1> ; 4785 <1> ; 'syssetuid' sets the user id (u.uid) of the current process 4786 <1> ; to the process id in (u.r0). Both the effective user and 4787 <1> ; u.uid and the real user u.ruid are set to this. 4788 <1> ; Only the super user can make this call. 4789 <1> ; 4790 <1> ; Calling sequence: 4791 <1> ; syssetuid 4792 <1> ; Arguments: - 4793 <1> ; 4794 <1> ; Inputs: (u.r0) - contains the process id. 4795 <1> ; Outputs: - 4796 <1> ; ............................................................... 4797 <1> ; 4798 <1> ; Retro UNIX 8086 v1 modification: 4799 <1> ; BL contains the (new) user ID of the current process 4800 <1> 4801 <1> ; movb *u.r0,r1 / move process id (number) to r1 4802 000043FC 3A1D[39650000] <1> cmp bl, [u.ruid] 4803 <1> ; cmpb r1,u.ruid / is it equal to the real user 4804 <1> ; / id number 4805 00004402 741E <1> je short setuid1 4806 <1> ; beq 1f / yes 4807 00004404 803D[38650000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 4808 <1> ; tstb u.uid / no, is current user the super user? 4809 <1> ;ja error 4810 <1> ; bne error4 / no, error 4811 0000440B 760F <1> jna short setuid0 4812 0000440D C705[41650000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 4812 00004415 0000 <1> 4813 <1> ; 'permission denied !' error 4814 00004417 E9AFECFFFF <1> jmp error 4815 <1> setuid0: 4816 0000441C 881D[39650000] <1> mov [u.ruid], bl 4817 <1> setuid1: ; 1: 4818 00004422 881D[38650000] <1> mov [u.uid], bl ; 02/08/2013 4819 <1> ; movb r1,u.uid / put process id in u.uid 4820 <1> ; movb r1,u.ruid / put process id in u.ruid 4821 00004428 E9BEECFFFF <1> jmp sysret 4822 <1> ; br sysret4 / system return 4823 <1> 4824 <1> sysgetuid: ; < get user id > 4825 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 4826 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4827 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 4828 <1> ; 4829 <1> ; 'sysgetuid' returns the real user ID of the current process. 4830 <1> ; The real user ID identifies the person who is logged in, 4831 <1> ; in contradistinction to the effective user ID, which 4832 <1> ; determines his access permission at each moment. It is thus 4833 <1> ; useful to programs which operate using the 'set user ID' 4834 <1> ; mode, to find out who invoked them. 4835 <1> ; 4836 <1> ; Calling sequence: 4837 <1> ; syssetuid 4838 <1> ; Arguments: - 4839 <1> ; 4840 <1> ; Inputs: - 4841 <1> ; Outputs: (u.r0) - contains the real user's id. 4842 <1> ; ............................................................... 4843 <1> ; 4844 <1> ; Retro UNIX 8086 v1 modification: 4845 <1> ; AL contains the real user ID at return. 4846 <1> ; 4847 <1> ;movzx eax, byte [u.ruid] 4848 <1> ; 09/01/2022 4849 0000442D A0[39650000] <1> mov al, [u.ruid] 4850 00004432 A3[EC640000] <1> mov [u.r0], eax 4851 <1> ; movb u.ruid,*u.r0 / move the real user id to (u.r0) 4852 00004437 E9AFECFFFF <1> jmp sysret 4853 <1> ; br sysret4 / systerm return, sysret 4854 <1> 4855 <1> anyi: 4856 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 4857 <1> ; 25/04/2013 (Retro UNIX 8086 v1) 4858 <1> ; 4859 <1> ; 'anyi' is called if a file deleted while open. 4860 <1> ; "anyi" checks to see if someone else has opened this file. 4861 <1> ; 4862 <1> ; INPUTS -> 4863 <1> ; r1 - contains an i-number 4864 <1> ; fsp - start of table containing open files 4865 <1> ; 4866 <1> ; OUTPUTS -> 4867 <1> ; "deleted" flag set in fsp entry of another occurrence of 4868 <1> ; this file and r2 points 1st word of this fsp entry. 4869 <1> ; if file not found - bit in i-node map is cleared 4870 <1> ; (i-node is freed) 4871 <1> ; all blocks related to i-node are freed 4872 <1> ; all flags in i-node are cleared 4873 <1> ; ((AX = R1)) input 4874 <1> ; 4875 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 4876 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 4877 <1> ; 4878 <1> ; / r1 contains an i-number 4879 0000443C BB[B4620000] <1> mov ebx, fsp 4880 <1> ; mov $fsp,r2 / move start of fsp table to r2 4881 <1> anyi_1: ; 1: 4882 00004441 663B03 <1> cmp ax, [ebx] 4883 <1> ; cmp r1,(r2) / do i-numbers match? 4884 00004444 7433 <1> je short anyi_3 4885 <1> ; beq 1f / yes, 1f 4886 00004446 66F7D8 <1> neg ax 4887 <1> ; neg r1 / no complement r1 4888 00004449 663B03 <1> cmp ax, [ebx] 4889 <1> ; cmp r1,(r2) / do they match now? 4890 0000444C 742B <1> je short anyi_3 4891 <1> ; beq 1f / yes, transfer 4892 <1> ; / i-numbers do not match 4893 0000444E 83C30A <1> add ebx, 10 ; fsp table size is 10 bytes 4894 <1> ; in Retro UNIX 386 v1 (22/06/2015) 4895 <1> ; add $8,r2 / no, bump to next entry in fsp table 4896 00004451 81FB[A8640000] <1> cmp ebx, fsp + (nfiles*10) ; 22/06/2015 4897 <1> ; cmp r2,$fsp+[nfiles*8] 4898 <1> ; / are we at last entry in the table 4899 00004457 72E8 <1> jb short anyi_1 4900 <1> ; blt 1b / no, check next entries i-number 4901 <1> ;cmp ax, 32768 4902 00004459 80FC80 <1> cmp ah, 80h ; negative number check 4903 <1> ; tst r1 / yes, no match 4904 <1> ; bge .+4 4905 0000445C 7203 <1> jb short anyi_2 4906 0000445E 66F7D8 <1> neg ax 4907 <1> ; neg r1 / make i-number positive 4908 <1> anyi_2: 4909 00004461 E81A050000 <1> call imap 4910 <1> ; jsr r0,imap / get address of allocation bit 4911 <1> ; / in the i-map in r2 4912 <1> ;; DL/DX (MQ) has a 1 in the calculated bit position 4913 <1> ;; eBX (R2) has address of the byte with allocation bit 4914 <1> ; not dx 4915 00004466 F6D2 <1> not dl ;; 0 at calculated bit position, other bits are 1 4916 <1> ;and [ebx], dx 4917 00004468 2013 <1> and [ebx], dl 4918 <1> ; bicb mq,(r2) / clear bit for i-node in the imap 4919 0000446A E8A4040000 <1> call itrunc 4920 <1> ; jsr r0,itrunc / free all blocks related to i-node 4921 0000446F 66C705[E4610000]00- <1> mov word [i.flgs], 0 4921 00004477 00 <1> 4922 <1> ; clr i.flgs / clear all flags in the i-node 4923 00004478 C3 <1> retn 4924 <1> ;rts r0 / return 4925 <1> anyi_3: ; 1: / i-numbers match 4926 00004479 FE4309 <1> inc byte [ebx+9] ; 22/06/2015 4927 <1> ;incb 7(r2) / increment upper byte of the 4th word 4928 <1> ; / in that fsp entry (deleted flag of fsp entry) 4929 0000447C C3 <1> retn 4930 <1> ; rts r0 2116 %include 'u3.s' ; 10/05/2015 2117 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC 2118 <1> ; Last Modification: 24/12/2021 2119 <1> ; ---------------------------------------------------------------------------- 2120 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2121 <1> ; (v0.1 - Beginning: 11/07/2012) 2122 <1> ; 2123 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2124 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2125 <1> ; 2126 <1> ; 2127 <1> ; 2128 <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s 2129 <1> ; 2130 <1> ; **************************************************************************** 2131 <1> 2132 <1> tswitch: ; Retro UNIX 386 v1 2133 <1> tswap: 2134 <1> ; 01/09/2015 2135 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2136 <1> ; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2137 <1> ; time out swap, called when a user times out. 2138 <1> ; the user is put on the low priority queue. 2139 <1> ; This is done by making a link from the last user 2140 <1> ; on the low priority queue to him via a call to 'putlu'. 2141 <1> ; then he is swapped out. 2142 <1> ; 2143 <1> ; Retro UNIX 386 v1 modification -> 2144 <1> ; swap (software task switch) is performed by changing 2145 <1> ; user's page directory (u.pgdir) instead of segment change 2146 <1> ; as in Retro UNIX 8086 v1. 2147 <1> ; 2148 <1> ; RETRO UNIX 8086 v1 modification -> 2149 <1> ; 'swap to disk' is replaced with 'change running segment' 2150 <1> ; according to 8086 cpu (x86 real mode) architecture. 2151 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2152 <1> ; compatibles was using 1MB segmented memory 2153 <1> ; in 8086/8088 times. 2154 <1> ; 2155 <1> ; INPUTS -> 2156 <1> ; u.uno - users process number 2157 <1> ; runq+4 - lowest priority queue 2158 <1> ; OUTPUTS -> 2159 <1> ; r0 - users process number 2160 <1> ; r2 - lowest priority queue address 2161 <1> ; 2162 <1> ; ((AX = R0, BX = R2)) output 2163 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) 2164 <1> ; 2165 0000447D A0[3B650000] <1> mov al, [u.uno] 2166 <1> ; movb u.uno,r1 / move users process number to r1 2167 <1> ; mov $runq+4,r2 2168 <1> ; / move lowest priority queue address to r2 2169 00004482 E8CD000000 <1> call putlu 2170 <1> ; jsr r0,putlu / create link from last user on Q to 2171 <1> ; / u.uno's user 2172 <1> 2173 <1> switch: ; Retro UNIX 386 v1 2174 <1> swap: 2175 <1> ; 24/12/2021 (Retro UNIX 386 v1.2) 2176 <1> ; 02/09/2015 2177 <1> ; 01/09/2015 2178 <1> ; 31/08/2015 2179 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2180 <1> ; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2181 <1> ; 'swap' is routine that controls the swapping of processes 2182 <1> ; in and out of core. 2183 <1> ; 2184 <1> ; Retro UNIX 386 v1 modification -> 2185 <1> ; swap (software task switch) is performed by changing 2186 <1> ; user's page directory (u.pgdir) instead of segment change 2187 <1> ; as in Retro UNIX 8086 v1. 2188 <1> ; 2189 <1> ; RETRO UNIX 8086 v1 modification -> 2190 <1> ; 'swap to disk' is replaced with 'change running segment' 2191 <1> ; according to 8086 cpu (x86 real mode) architecture. 2192 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2193 <1> ; compatibles was using 1MB segmented memory 2194 <1> ; in 8086/8088 times. 2195 <1> ; 2196 <1> ; INPUTS -> 2197 <1> ; runq table - contains processes to run. 2198 <1> ; p.link - contains next process in line to be run. 2199 <1> ; u.uno - process number of process in core 2200 <1> ; s.stack - swap stack used as an internal stack for swapping. 2201 <1> ; OUTPUTS -> 2202 <1> ; (original unix v1 -> present process to its disk block) 2203 <1> ; (original unix v1 -> new process into core -> 2204 <1> ; Retro Unix 8086 v1 -> segment registers changed 2205 <1> ; for new process) 2206 <1> ; u.quant = 3 (Time quantum for a process) 2207 <1> ; ((INT 1Ch count down speed -> 18.2 times per second) 2208 <1> ; RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second) 2209 <1> ; for now, it will swap the process if there is not 2210 <1> ; a keyboard event (keystroke) (Int 15h, function 4Fh) 2211 <1> ; or will count down from 3 to 0 even if there is a 2212 <1> ; keyboard event locking due to repetitive key strokes. 2213 <1> ; u.quant will be reset to 3 for RETRO UNIX 8086 v1. 2214 <1> ; 2215 <1> ; u.pri -points to highest priority run Q. 2216 <1> ; r2 - points to the run queue. 2217 <1> ; r1 - contains new process number 2218 <1> ; r0 - points to place in routine or process that called 2219 <1> ; swap all user parameters 2220 <1> ; 2221 <1> ; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI)) 2222 <1> ; 2223 <1> swap_0: 2224 <1> ;mov $300,*$ps / processor priority = 6 2225 00004487 BE[DE640000] <1> mov esi, runq 2226 <1> ; mov $runq,r2 / r2 points to runq table 2227 <1> swap_1: ; 1: / search runq table for highest priority process 2228 0000448C 668B06 <1> mov ax, [esi] 2229 0000448F 6621C0 <1> and ax, ax 2230 <1> ; tst (r2)+ / are there any processes to run 2231 <1> ; / in this Q entry 2232 00004492 7507 <1> jnz short swap_2 2233 <1> ; bne 1f / yes, process 1f 2234 <1> ; cmp r2,$runq+6 / if zero compare address 2235 <1> ; / to end of table 2236 <1> ; bne 1b / if not at end, go back 2237 00004494 E8E0000000 <1> call idle 2238 <1> ; jsr r0,idle; s.idlet+2 / wait for interrupt; 2239 <1> ; / all queues are empty 2240 00004499 EBF1 <1> jmp short swap_1 2241 <1> ; br swap 2242 <1> swap_2: ; 1: 2243 0000449B 0FB6D8 <1> movzx ebx, al ; 02/09/2015 2244 <1> ; tst -(r2) / restore pointer to right Q entry 2245 <1> ; mov r2,u.pri / set present user to this run queue 2246 <1> ; movb (r2)+,r1 / move 1st process in queue to r1 2247 0000449E 38E0 <1> cmp al, ah 2248 <1> ; cmpb r1,(r2)+ / is there only 1 process 2249 <1> ; / in this Q to be run 2250 000044A0 740A <1> je short swap_3 2251 <1> ; beq 1f / yes 2252 <1> ; tst -(r2) / no, pt r2 back to this Q entry 2253 <1> ;movzx ebx, al 2254 000044A2 8AA3[53620000] <1> mov ah, [ebx+p.link-1] 2255 000044A8 8826 <1> mov [esi], ah 2256 <1> ; movb p.link-1(r1),(r2) / move next process 2257 <1> ; / in line into run queue 2258 000044AA EB05 <1> jmp short swap_4 2259 <1> ; br 2f 2260 <1> swap_3: ; 1: 2261 <1> ;xor dx, dx 2262 <1> ; 24/12/2021 2263 000044AC 31D2 <1> xor edx, edx 2264 000044AE 668916 <1> mov [esi], dx 2265 <1> ; clr -(r2) / zero the entry; no processes on the Q 2266 <1> swap_4: ; / write out core to appropriate disk area and read 2267 <1> ; / in new process if required 2268 <1> ; clr *$ps / clear processor status 2269 000044B1 8A25[3B650000] <1> mov ah, [u.uno] 2270 000044B7 38C4 <1> cmp ah, al 2271 <1> ; cmpb r1,u.uno / is this process the same as 2272 <1> ; / the process in core? 2273 000044B9 743B <1> je short swap_8 2274 <1> ; beq 2f / yes, don't have to swap 2275 <1> ; mov r0,-(sp) / no, write out core; save r0 2276 <1> ; / (address in routine that called swap) 2277 <1> ; mov r1,-(sp) / put r1 (new process #) on the stack 2278 <1> ; 01/09/2015 2279 <1> ;mov [u.usp], esp 2280 <1> ; mov sp,u.usp / save stack pointer 2281 <1> ; mov $sstack,sp / move swap stack pointer 2282 <1> ; / to the stack pointer 2283 000044BB 08E4 <1> or ah, ah 2284 <1> ; tstb u.uno / is the process # = 0 2285 000044BD 740D <1> jz short swap_6 ; 'sysexit' 2286 <1> ; beq 1f / yes, kill process by overwriting 2287 <1> ; 02/09/2015 2288 000044BF 8925[E8640000] <1> mov [u.usp], esp ; return address for 'syswait' & 'sleep' 2289 <1> ; 2290 000044C5 E834000000 <1> call wswap 2291 <1> ; jsr r0,wswap / write out core to disk 2292 <1> ; 31/08/2015 2293 <1> ;movzx ebx, al ; New (running) process number 2294 000044CA EB1C <1> jmp short swap_7 2295 <1> swap_6: 2296 <1> ; 31/08/2015 2297 <1> ; Deallocate memory pages belong to the process 2298 <1> ; which is being terminated 2299 <1> ; 14/05/2015 ('sysexit') 2300 <1> ; Deallocate memory pages of the process 2301 <1> ; (Retro UNIX 386 v1 modification !) 2302 <1> ; 2303 <1> ; movzx ebx, al 2304 000044CC 53 <1> push ebx 2305 000044CD A1[45650000] <1> mov eax, [u.pgdir] ; page directory of the process 2306 000044D2 8B1D[49650000] <1> mov ebx, [u.ppgdir] ; page directory of the parent process 2307 000044D8 E814E0FFFF <1> call deallocate_page_dir 2308 000044DD A1[3C650000] <1> mov eax, [u.upage] ; 'user' structure page of the process 2309 000044E2 E8A0E0FFFF <1> call deallocate_page 2310 000044E7 5B <1> pop ebx 2311 <1> swap_7: ;1: 2312 <1> ; 02/09/2015 2313 <1> ; 31/08/2015 2314 <1> ; 14/05/2015 2315 000044E8 C0E302 <1> shl bl, 2 ; * 4 2316 000044EB 8B83[70620000] <1> mov eax, [ebx+p.upage-4] ; the 'u' page of the new process 2317 <1> ;cli 2318 000044F1 E831000000 <1> call rswap 2319 <1> ; mov (sp)+,r1 / restore r1 to new process number 2320 <1> ; jsr r0,rswap / read new process into core 2321 <1> ; jsr r0,unpack / unpack the users stack from next 2322 <1> ; / to his program to its normal 2323 <1> ; 01/09/2015 2324 <1> ;mov esp, [u.usp] 2325 <1> ; mov u.usp,sp / location; restore stack pointer to 2326 <1> ; / new process stack 2327 <1> ; mov (sp)+,r0 / put address of where the process 2328 <1> ; / that just got swapped in, left off., 2329 <1> ; / i.e., transfer control to new process 2330 <1> ;sti 2331 <1> swap_8: ;2: 2332 <1> ; RETRO UNIX 8086 v1 modification ! 2333 000044F6 C605[2E650000]04 <1> mov byte [u.quant], time_count 2334 <1> ; movb $30.,uquant / initialize process time quantum 2335 000044FD C3 <1> retn 2336 <1> ; rts r0 / return 2337 <1> 2338 <1> wswap: ; < swap out, swap to disk > 2339 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 2340 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2341 <1> ; 'wswap' writes out the process that is in core onto its 2342 <1> ; appropriate disk area. 2343 <1> ; 2344 <1> ; Retro UNIX 386 v1 modification -> 2345 <1> ; User (u) structure content and the user's register content 2346 <1> ; will be copied to the process's/user's UPAGE (a page for 2347 <1> ; saving 'u' structure and user registers for task switching). 2348 <1> ; u.usp - points to kernel stack address which contains 2349 <1> ; user's registers while entering system call. 2350 <1> ; u.sp - points to kernel stack address 2351 <1> ; to return from system call -for IRET-. 2352 <1> ; [u.usp]+32+16 = [u.sp] 2353 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 2354 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 2355 <1> ; 2356 <1> ; Retro UNIX 8086 v1 modification -> 2357 <1> ; 'swap to disk' is replaced with 'change running segment' 2358 <1> ; according to 8086 cpu (x86 real mode) architecture. 2359 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2360 <1> ; compatibles was using 1MB segmented memory 2361 <1> ; in 8086/8088 times. 2362 <1> ; 2363 <1> ; INPUTS -> 2364 <1> ; u.break - points to end of program 2365 <1> ; u.usp - stack pointer at the moment of swap 2366 <1> ; core - beginning of process program 2367 <1> ; ecore - end of core 2368 <1> ; user - start of user parameter area 2369 <1> ; u.uno - user process number 2370 <1> ; p.dska - holds block number of process 2371 <1> ; OUTPUTS -> 2372 <1> ; swp I/O queue 2373 <1> ; p.break - negative word count of process 2374 <1> ; r1 - process disk address 2375 <1> ; r2 - negative word count 2376 <1> ; 2377 <1> ; RETRO UNIX 8086 v1 input/output: 2378 <1> ; 2379 <1> ; INPUTS -> 2380 <1> ; u.uno - process number (to be swapped out) 2381 <1> ; OUTPUTS -> 2382 <1> ; none 2383 <1> ; 2384 <1> ; ((Modified registers: ECX, ESI, EDI)) 2385 <1> ; 2386 000044FE 8B3D[3C650000] <1> mov edi, [u.upage] ; process's user (u) structure page addr 2387 00004504 B91E000000 <1> mov ecx, (U_SIZE + 3) / 4 2388 00004509 BE[E4640000] <1> mov esi, user ; active user (u) structure 2389 0000450E F3A5 <1> rep movsd 2390 <1> ; 2391 00004510 8B35[E8640000] <1> mov esi, [u.usp] ; esp (system stack pointer, 2392 <1> ; points to user registers) 2393 00004516 8B0D[E4640000] <1> mov ecx, [u.sp] ; return address from the system call 2394 <1> ; (for IRET) 2395 <1> ; [u.sp] -> EIP (user) 2396 <1> ; [u.sp+4]-> CS (user) 2397 <1> ; [u.sp+8] -> EFLAGS (user) 2398 <1> ; [u.sp+12] -> ESP (user) 2399 <1> ; [u.sp+16] -> SS (user) 2400 0000451C 29F1 <1> sub ecx, esi ; required space for user registers 2401 0000451E 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 2402 <1> ; (for IRET) 2403 00004521 C1E902 <1> shr ecx, 2 2404 00004524 F3A5 <1> rep movsd 2405 00004526 C3 <1> retn 2406 <1> 2407 <1> ; Original UNIX v1 'wswap' routine: 2408 <1> ; wswap: 2409 <1> ; mov *$30,u.emt / determines handling of emts 2410 <1> ; mov *$10,u.ilgins / determines handling of 2411 <1> ; / illegal instructions 2412 <1> ; mov u.break,r2 / put process program break address in r2 2413 <1> ; inc r2 / add 1 to it 2414 <1> ; bic $1,r2 / make it even 2415 <1> ; mov r2,u.break / set break to an even location 2416 <1> ; mov u.usp,r3 / put users stack pointer 2417 <1> ; / at moment of swap in r3 2418 <1> ; cmp r2,$core / is u.break less than $core 2419 <1> ; blos 2f / yes 2420 <1> ; cmp r2,r3 / no, is (u.break) greater than stack ptr. 2421 <1> ; bhis 2f / yes 2422 <1> ; 1: 2423 <1> ; mov (r3)+,(r2)+ / no, pack stack next to users program 2424 <1> ; cmp r3,$ecore / has stack reached end of core 2425 <1> ; bne 1b / no, keep packing 2426 <1> ; br 1f / yes 2427 <1> ; 2: 2428 <1> ; mov $ecore,r2 / put end of core in r2 2429 <1> ; 1: 2430 <1> ; sub $user,r2 / get number of bytes to write out 2431 <1> ; / (user up to end of stack gets written out) 2432 <1> ; neg r2 / make it negative 2433 <1> ; asr r2 / change bytes to words (divide by 2) 2434 <1> ; mov r2,swp+4 / word count 2435 <1> ; movb u.uno,r1 / move user process number to r1 2436 <1> ; asl r1 / x2 for index 2437 <1> ; mov r2,p.break-2(r1) / put negative of word count 2438 <1> ; / into the p.break table 2439 <1> ; mov p.dska-2(r1),r1 / move disk address of swap area 2440 <1> ; / for process to r1 2441 <1> ; mov r1,swp+2 / put processes dska address in swp+2 2442 <1> ; / (block number) 2443 <1> ; bis $1000,swp / set it up to write (set bit 9) 2444 <1> ; jsr r0,ppoke / write process out on swap area of disk 2445 <1> ; 1: 2446 <1> ; tstb swp+1 / is lt done writing? 2447 <1> ; bne 1b / no, wait 2448 <1> ; rts r0 / yes, return to swap 2449 <1> 2450 <1> rswap: ; < swap in, swap from disk > 2451 <1> ; 15/09/2015 2452 <1> ; 28/08/2015 2453 <1> ; 14/05/2015 2454 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 2455 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 2456 <1> ; 'rswap' reads a process whose number is in r1, 2457 <1> ; from disk into core. 2458 <1> ; 2459 <1> ; Retro UNIX 386 v1 modification -> 2460 <1> ; User (u) structure content and the user's register content 2461 <1> ; will be restored from process's/user's UPAGE (a page for 2462 <1> ; saving 'u' structure and user registers for task switching). 2463 <1> ; u.usp - points to kernel stack address which contains 2464 <1> ; user's registers while entering system call. 2465 <1> ; u.sp - points to kernel stack address 2466 <1> ; to return from system call -for IRET-. 2467 <1> ; [u.usp]+32+16 = [u.sp] 2468 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 2469 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 2470 <1> ; 2471 <1> ; RETRO UNIX 8086 v1 modification -> 2472 <1> ; 'swap to disk' is replaced with 'change running segment' 2473 <1> ; according to 8086 cpu (x86 real mode) architecture. 2474 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 2475 <1> ; compatibles was using 1MB segmented memory 2476 <1> ; in 8086/8088 times. 2477 <1> ; 2478 <1> ; INPUTS -> 2479 <1> ; r1 - process number of process to be read in 2480 <1> ; p.break - negative of word count of process 2481 <1> ; p.dska - disk address of the process 2482 <1> ; u.emt - determines handling of emt's 2483 <1> ; u.ilgins - determines handling of illegal instructions 2484 <1> ; OUTPUTS -> 2485 <1> ; 8 = (u.ilgins) 2486 <1> ; 24 = (u.emt) 2487 <1> ; swp - bit 10 is set to indicate read 2488 <1> ; (bit 15=0 when reading is done) 2489 <1> ; swp+2 - disk block address 2490 <1> ; swp+4 - negative word count 2491 <1> ; ((swp+6 - address of user structure)) 2492 <1> ; 2493 <1> ; RETRO UNIX 8086 v1 input/output: 2494 <1> ; 2495 <1> ; INPUTS -> 2496 <1> ; AL - new process number (to be swapped in) 2497 <1> ; OUTPUTS -> 2498 <1> ; none 2499 <1> ; 2500 <1> ; ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 2501 <1> ; 2502 <1> ; Retro UNIX 386 v1 - modification ! 14/05/2015 2503 00004527 89C6 <1> mov esi, eax ; process's user (u) structure page addr 2504 00004529 B91E000000 <1> mov ecx, (U_SIZE + 3) / 4 2505 0000452E BF[E4640000] <1> mov edi, user ; active user (u) structure 2506 00004533 F3A5 <1> rep movsd 2507 00004535 58 <1> pop eax ; 15/09/2015, 'rswap' return address 2508 00004536 8B3D[E8640000] <1> mov edi, [u.usp] ; esp (system stack pointer, 2509 <1> ; points to user registers) 2510 0000453C 8B0D[E4640000] <1> mov ecx, [u.sp] ; return address from the system call 2511 <1> ; (for IRET) 2512 <1> ; [u.sp] -> EIP (user) 2513 <1> ; [u.sp+4]-> CS (user) 2514 <1> ; [u.sp+8] -> EFLAGS (user) 2515 <1> ; [u.sp+12] -> ESP (user) 2516 <1> ; [u.sp+16] -> SS (user) 2517 <1> ; 28/08/2015 2518 00004542 29F9 <1> sub ecx, edi ; required space for user registers 2519 00004544 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 2520 <1> ; (for IRET) 2521 00004547 C1E902 <1> shr ecx, 2 2522 0000454A F3A5 <1> rep movsd 2523 0000454C 8B25[E8640000] <1> mov esp, [u.usp] ; 15/09/2015 2524 00004552 50 <1> push eax ; 15/09/2015 'rswap' return address 2525 00004553 C3 <1> retn 2526 <1> 2527 <1> ; Original UNIX v1 'rswap' and 'unpack' routines: 2528 <1> ;rswap: 2529 <1> ; asl r1 / process number x2 for index 2530 <1> ; mov p.break-2(r1), swp+4 / word count 2531 <1> ; mov p.dska-2(r1),swp+2 / disk address 2532 <1> ; bis $2000,swp / read 2533 <1> ; jsr r0,ppoke / read it in 2534 <1> ; 1: 2535 <1> ; tstb swp+1 / done 2536 <1> ; bne 1b / no, wait for bit 15 to clear (inhibit bit) 2537 <1> ; mov u.emt,*$30 / yes move these 2538 <1> ; mov u.ilgins,*$10 / back 2539 <1> ; rts r0 / return 2540 <1> 2541 <1> ;unpack: ; / move stack back to its normal place 2542 <1> ; mov u.break,r2 / r2 points to end of user program 2543 <1> ; cmp r2,$core / at beginning of user program yet? 2544 <1> ; blos 2f / yes, return 2545 <1> ; cmp r2,u.usp / is break_above the stack pointer 2546 <1> ; / before swapping 2547 <1> ; bhis 2f / yes, return 2548 <1> ; mov $ecore,r3 / r3 points to end of core 2549 <1> ; add r3,r2 2550 <1> ; sub u.usp,r2 / end of users stack is in r2 2551 <1> ; 1: 2552 <1> ; mov -(r2),-(r3) / move stack back to its normal place 2553 <1> ; cmp r2,u.break / in core 2554 <1> ; bne 1b 2555 <1> ; 2: 2556 <1> ; rts r0 2557 <1> 2558 <1> putlu: 2559 <1> ; 12/09/2015 2560 <1> ; 02/09/2015 2561 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2562 <1> ; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 2563 <1> ; 'putlu' is called with a process number in r1 and a pointer 2564 <1> ; to lowest priority Q (runq+4) in r2. A link is created from 2565 <1> ; the last process on the queue to process in r1 by putting 2566 <1> ; the process number in r1 into the last process's link. 2567 <1> ; 2568 <1> ; INPUTS -> 2569 <1> ; r1 - user process number 2570 <1> ; r2 - points to lowest priority queue 2571 <1> ; p.dska - disk address of the process 2572 <1> ; u.emt - determines handling of emt's 2573 <1> ; u.ilgins - determines handling of illegal instructions 2574 <1> ; OUTPUTS -> 2575 <1> ; r3 - process number of last process on the queue upon 2576 <1> ; entering putlu 2577 <1> ; p.link-1 + r3 - process number in r1 2578 <1> ; r2 - points to lowest priority queue 2579 <1> ; 2580 <1> ; ((Modified registers: EDX, EBX)) 2581 <1> ; 2582 <1> ; / r1 = user process no.; r2 points to lowest priority queue 2583 <1> 2584 <1> ; eBX = r2 2585 <1> ; eAX = r1 (AL=r1b) 2586 <1> 2587 00004554 BB[DE640000] <1> mov ebx, runq 2588 00004559 0FB613 <1> movzx edx, byte [ebx] 2589 0000455C 43 <1> inc ebx 2590 0000455D 20D2 <1> and dl, dl 2591 <1> ; tstb (r2)+ / is queue empty? 2592 0000455F 740A <1> jz short putlu_1 2593 <1> ; beq 1f / yes, branch 2594 00004561 8A13 <1> mov dl, [ebx] ; 12/09/2015 2595 <1> ; movb (r2),r3 / no, save the "last user" process number 2596 <1> ; / in r3 2597 00004563 8882[53620000] <1> mov [edx+p.link-1], al 2598 <1> ; movb r1,p.link-1(r3) / put pointer to user on 2599 <1> ; / "last users" link 2600 00004569 EB03 <1> jmp short putlu_2 2601 <1> ; br 2f / 2602 <1> putlu_1: ; 1: 2603 0000456B 8843FF <1> mov [ebx-1], al 2604 <1> ; movb r1,-1(r2) / user is only user; 2605 <1> ; / put process no. at beginning and at end 2606 <1> putlu_2: ; 2: 2607 0000456E 8803 <1> mov [ebx], al 2608 <1> ; movb r1,(r2) / user process in r1 is now the last entry 2609 <1> ; / on the queue 2610 00004570 88C2 <1> mov dl, al 2611 00004572 88B2[53620000] <1> mov [edx+p.link-1], dh ; 0 2612 <1> ; dec r2 / restore r2 2613 00004578 C3 <1> retn 2614 <1> ; rts r0 2615 <1> 2616 <1> ;copyz: 2617 <1> ; mov r1,-(sp) / put r1 on stack 2618 <1> ; mov r2,-(sp) / put r2 on stack 2619 <1> ; mov (r0)+,r1 2620 <1> ; mov (r0)+,r2 2621 <1> ;1: 2622 <1> ; clr (r1)+ / clear all locations between r1 and r2 2623 <1> ; cmp r1,r2 2624 <1> ; blo 1b 2625 <1> ; mov (sp)+,r2 / restore r2 2626 <1> ; mov (sp)+,r1 / restore r1 2627 <1> ; rts r0 2628 <1> 2629 <1> idle: 2630 <1> ; 01/09/2015 2631 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2632 <1> ; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1) 2633 <1> ; (idle & wait loop) 2634 <1> ; Retro Unix 8086 v1 modification on original UNIX v1 2635 <1> ; idle procedure! 2636 <1> ; 2637 <1> ; 01/09/2015 2638 00004579 FB <1> sti 2639 <1> ; 29/07/2013 2640 0000457A F4 <1> hlt 2641 0000457B 90 <1> nop ; 10/10/2013 2642 0000457C 90 <1> nop 2643 0000457D 90 <1> nop 2644 <1> ; 23/10/2013 2645 0000457E 90 <1> nop 2646 0000457F 90 <1> nop 2647 00004580 90 <1> nop 2648 00004581 90 <1> nop 2649 00004582 C3 <1> retn 2650 <1> 2651 <1> ;mov *$ps,-(sp) / save ps on stack 2652 <1> ;clr *$ps / clear ps 2653 <1> ;mov clockp,-(sp) / save clockp on stack 2654 <1> ;mov (r0)+,clockp / arg to idle in clockp 2655 <1> ;1 / wait for interrupt 2656 <1> ;mov (sp)+,clockp / restore clockp, ps 2657 <1> ;mov (sp)+,*$ps 2658 <1> ;rts r0 2659 <1> 2660 <1> clear: 2661 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2662 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 2663 <1> ; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2664 <1> ; 'clear' zero's out of a block (whose block number is in r1) 2665 <1> ; on the current device (cdev) 2666 <1> ; 2667 <1> ; INPUTS -> 2668 <1> ; r1 - block number of block to be zeroed 2669 <1> ; cdev - current device number 2670 <1> ; OUTPUTS -> 2671 <1> ; a zeroed I/O buffer onto the current device 2672 <1> ; r1 - points to last entry in the I/O buffer 2673 <1> ; 2674 <1> ; ((AX = R1)) input/output 2675 <1> ; (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM) 2676 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP)) 2677 <1> 2678 00004583 E88E0E0000 <1> call wslot 2679 <1> ; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first 2680 <1> ; / word of I/O queue r5 points to first data word in buffer 2681 00004588 89DF <1> mov edi, ebx ; r5 2682 0000458A 89C2 <1> mov edx, eax 2683 0000458C B980000000 <1> mov ecx, 128 2684 <1> ; mov $256.,r3 2685 00004591 31C0 <1> xor eax, eax 2686 00004593 F3AB <1> rep stosd 2687 00004595 89D0 <1> mov eax, edx 2688 <1> ; 1: 2689 <1> ; clr (r5)+ / zero data word in buffer 2690 <1> ; dec r3 2691 <1> ; bgt 1b / branch until all data words in buffer are zero 2692 <1> ;call dskwr 2693 <1> ; jsr r0,dskwr / write zeroed buffer area out onto physical 2694 <1> ; / block specified in r1 2695 <1> ; eAX (r1) = block number 2696 <1> ;retn 2697 <1> ; rts r0 2698 <1> ; 24/12/2021 2699 00004597 E9870E0000 <1> jmp dskwr 2117 %include 'u4.s' ; 15/04/2015 2118 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC 2119 <1> ; Last Modification: 26/02/2022 2120 <1> ; ---------------------------------------------------------------------------- 2121 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2122 <1> ; (v0.1 - Beginning: 11/07/2012) 2123 <1> ; 2124 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2125 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2126 <1> ; 2127 <1> ; 2128 <1> ; 2129 <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s 2130 <1> ; 2131 <1> ; **************************************************************************** 2132 <1> 2133 <1> ;setisp: 2134 <1> ;mov r1,-(sp) 2135 <1> ;mov r2,-(sp) 2136 <1> ;mov r3,-(sp) 2137 <1> ;mov clockp,-(sp) 2138 <1> ;mov $s.syst+2,clockp 2139 <1> ;jmp (r0) 2140 <1> 2141 <1> clock: ; / interrupt from 60 cycle clock 2142 <1> 2143 <1> ; 14/10/2015 2144 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 2145 <1> ; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1) 2146 <1> 2147 <1> ;mov r0,-(sp) / save r0 2148 <1> ;tst *$lks / restart clock? 2149 <1> ;mov $s.time+2,r0 / increment the time of day 2150 <1> ;inc (r0) 2151 <1> ;bne 1f 2152 <1> ;inc -(r0) 2153 <1> ;1: 2154 <1> ;mov clockp,r0 / increment appropriate time category 2155 <1> ;inc (r0) 2156 <1> ;bne 1f 2157 <1> ;inc -(r0) 2158 <1> ;1: 2159 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2160 <1> 2161 0000459C 803D[2E650000]00 <1> cmp byte [u.quant], 0 2162 000045A3 772C <1> ja short clk_1 2163 <1> ; 2164 000045A5 803D[E3640000]FF <1> cmp byte [sysflg], 0FFh ; user or system space ? 2165 000045AC 7529 <1> jne short clk_2 ; system space (sysflg <> 0FFh) 2166 000045AE 803D[3B650000]01 <1> cmp byte [u.uno], 1 ; /etc/init ? 2167 000045B5 761A <1> jna short clk_1 ; yes, do not swap out 2168 000045B7 66833D[30650000]00 <1> cmp word [u.intr], 0 2169 000045BF 7616 <1> jna short clk_2 2170 <1> clk_0: 2171 <1> ; 14/10/2015 2172 000045C1 FE05[E3640000] <1> inc byte [sysflg] ; Now, we are in system space 2173 000045C7 58 <1> pop eax ; return address to the timer interrupt 2174 <1> ; 2175 000045C8 B020 <1> MOV AL,EOI ; GET END OF INTERRUPT MASK 2176 <1> ;CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 2177 000045CA E620 <1> OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 2178 <1> ; 2179 000045CC E97FEBFFFF <1> jmp sysrelease ; 'sys release' by clock/timer 2180 <1> clk_1: 2181 000045D1 FE0D[2E650000] <1> dec byte [u.quant] 2182 <1> clk_2: 2183 000045D7 C3 <1> retn ; return to (hardware) timer interrupt routine 2184 <1> 2185 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2186 <1> 2187 <1> ;mov $uquant,r0 / decrement user time quantum 2188 <1> ;decb (r0) 2189 <1> ;bge 1f / if less than 0 2190 <1> ;clrb (r0) / make it 0 2191 <1> ;1: / decrement time out counts return now if priority was not 0 2192 <1> ;cmp 4(sp),$200 / ps greater than or equal to 200 2193 <1> ;bge 2f / yes, check time outs 2194 <1> ;tstb (r0) / no, user timed out? 2195 <1> ;bne 1f / no 2196 <1> ;cmpb sysflg,$-1 / yes, are we outside the system? 2197 <1> ;bne 1f / no, 1f 2198 <1> ;mov (sp)+,r0 / yes, put users r0 in r0 2199 <1> ;sys 0 / sysrele 2200 <1> ;rti 2201 <1> ;2: / priority is high so just decrement time out counts 2202 <1> ;mov $toutt,r0 / r0 points to beginning of time out table 2203 <1> ;2: 2204 <1> ;tstb (r0) / is the time out? 2205 <1> ;beq 3f / yes, 3f (get next entry) 2206 <1> ;decb (r0) / no, decrement the time 2207 <1> ;bne 3f / isit zero now? 2208 <1> ;incb (r0) / yes, increment the time 2209 <1> ;3: 2210 <1> ;inc r0 / next entry 2211 <1> ;cmp r0,$touts / end of toutt table? 2212 <1> ;blo 2b / no, check this entry 2213 <1> ;mov (sp)+,r0 / yes, restore r0 2214 <1> ;rti / return from interrupt 2215 <1> ;1: / decrement time out counts; if 0 call subroutine 2216 <1> ;mov (sp)+,r0 / restore r0 2217 <1> ;mov $240,*$ps / set processor priority to 5 2218 <1> ;jsr r0,setisp / save registers 2219 <1> ;mov $touts-toutt-1,r0 / set up r0 as index to decrement thru 2220 <1> ; / the table 2221 <1> ;1: 2222 <1> ;tstb toutt(r0) / is the time out for this entry 2223 <1> ;beq 2f / yes 2224 <1> ;decb toutt(r0) / no, decrement the time 2225 <1> ;bne 2f / is the time 0, now 2226 <1> ;asl r0 / yes, 2 x r0 to get word index for tout entry 2227 <1> ;jsr r0,*touts(r0) / go to appropriate routine specified in this 2228 <1> ;asr r0 / touts entry; set r0 back to toutt index 2229 <1> ;2: 2230 <1> ;dec r0 / set up r0 for next entry 2231 <1> ;bge 1b / finished? , no, go back 2232 <1> ;br retisp / yes, restore registers and do a rti 2233 <1> 2234 <1> ;retisp: 2235 <1> ;mov (sp)+,clockp / pop values before interrupt off the stack 2236 <1> ;mov (sp)+,r3 2237 <1> ;mov (sp)+,r2 2238 <1> ;mov (sp)+,r1 2239 <1> ;mov (sp)+,r0 2240 <1> ;rti / return from interrupt 2241 <1> 2242 <1> 2243 <1> wakeup: ; / wakeup processes waiting for an event 2244 <1> ; / by linking them to the queue 2245 <1> ; 2246 <1> ; 26/02/2022 2247 <1> ; 15/09/2015 2248 <1> ; 29/06/2015 2249 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 2250 <1> ; 2251 <1> ; 15/05/2013 - 02/06/2014 2252 <1> ; Retro UNIX 8086 v1 modification ! 2253 <1> ; (Process/task switching routine by using 2254 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.) 2255 <1> ; 2256 <1> ; In original UNIX v1, 'wakeup' is called to wake the process 2257 <1> ; sleeping in the specified wait channel by creating a link 2258 <1> ; to it from the last user process on the run queue. 2259 <1> ; If there is no process to wake up, nothing happens. 2260 <1> ; 2261 <1> ; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set 2262 <1> ; 'switching' status of the current process (owns current tty) 2263 <1> ; (via alt + function keys) to a process which has highest 2264 <1> ; priority (on run queue) on the requested tty (0 to 7, except 2265 <1> ; 8 and 9 which are tty identifiers of COM1, COM2 serial ports) 2266 <1> ; as it's console tty. (NOTE: 'p.ttyc' is used to set console 2267 <1> ; tty for tty switching by keyboard.) 2268 <1> ; 2269 <1> ; INPUT -> 2270 <1> ; AL = wait channel (r3) ('tty number' for now) 2271 <1> ; ;;EBX = Run queue (r2) offset 2272 <1> ; 2273 <1> ; ((modified registers: EAX, EBX)) 2274 <1> ; 2275 000045D8 0FB6D8 <1> movzx ebx, al ; 29/06/2015 2276 000045DB 81C3[88610000] <1> add ebx, wlist 2277 000045E1 8A03 <1> mov al, [ebx] ; waiting list (waiting process number) 2278 000045E3 20C0 <1> and al, al 2279 000045E5 741E <1> jz short wa0 ; nothing to wakeup 2280 <1> ; 2281 000045E7 30E4 <1> xor ah, ah 2282 000045E9 8825[2E650000] <1> mov [u.quant], ah ; 0 ; time quantum = 0 2283 000045EF 8823 <1> mov [ebx], ah ; 0 ; zero wait channel entry 2284 <1> ; 15/09/2015 2285 000045F1 0FB6D8 <1> movzx ebx, al 2286 <1> ; 26/02/2022 (p.waitc is not used) 2287 <1> ;mov [ebx+p.waitc-1], ah ; 0 2288 000045F4 FEC4 <1> inc ah 2289 000045F6 88A3[63620000] <1> mov byte [ebx+p.stat-1], ah ; 1 ; SRUN 2290 <1> ; 2291 000045FC 57 <1> push edi 2292 000045FD 52 <1> push edx 2293 000045FE E851FFFFFF <1> call putlu 2294 00004603 5A <1> pop edx 2295 00004604 5F <1> pop edi 2296 <1> wa0: 2297 00004605 C3 <1> retn 2298 <1> 2299 <1> sleep: 2300 <1> ; 26/02/2022 2301 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2302 <1> ; 15/09/2015 2303 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2304 <1> ; 2305 <1> ; 09/05/2013 - 20/03/2014 2306 <1> ; 2307 <1> ; Retro UNIX 8086 v1 modification ! 2308 <1> ; (Process/task switching and quit routine by using 2309 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2310 <1> ; 2311 <1> ; In original UNIX v1, 'sleep' is called to wait for 2312 <1> ; tty and tape output or input becomes available 2313 <1> ; and process is put on waiting channel and swapped out, 2314 <1> ; then -when the tty or tape is ready to write or read- 2315 <1> ; 'wakeup' gets process back to active swapped-in status.) 2316 <1> ; 2317 <1> ; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and 2318 <1> ; Int 09h keyboard interrupt will set 'quit' or 'switching' 2319 <1> ; status of the current process also INT 1Ch will count down 2320 <1> ; 'uquant' value and INT 09h will redirect scancode of keystroke 2321 <1> ; to tty buffer of the current process and kernel will get 2322 <1> ; user input by using tty buffer of the current process 2323 <1> ; (instead of standard INT 16h interrupt). 2324 <1> ; TTY output will be redirected to related video page of text mode 2325 <1> ; (INT 10h will be called with different video page depending 2326 <1> ; on tty assignment of the active process: 0 to 7 for 2327 <1> ; pseudo screens.) 2328 <1> ; 2329 <1> ; In Retro UNIX 8086 v1, 'sleep' will be called to wait for 2330 <1> ; a keystroke from keyboard or wait for reading or writing 2331 <1> ; characters/data on serial port(s). 2332 <1> ; 2333 <1> ; Character/Terminal input/output through COM1 and COM2 will be 2334 <1> ; performed by related routines in addition to pseudo TTY routines. 2335 <1> ; 2336 <1> ; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013) 2337 <1> ; 2338 <1> ;; 05/10/2013 2339 <1> ;10/12/2013 2340 <1> ;cmp byte [u.uno], 1 2341 <1> ;ja short sleep0 2342 <1> ;retn 2343 <1> 2344 <1> ; 20/03/2014 2345 <1> ;mov bx, [runq] 2346 <1> ;cmp bl, bh 2347 <1> ;jne short sleep0 2348 <1> ; 25/02/2014 2349 <1> ;cmp word ptr [runq], 0 2350 <1> ;ja short sleep0 2351 <1> ;retn 2352 <1> sleep0: 2353 <1> ; 2354 00004606 E849000000 <1> call isintr 2355 <1> ;jnz sysret 2356 <1> ; / wait for event 2357 <1> ; jsr r0,isintr / check to see if interrupt 2358 <1> ; / or quit from user 2359 <1> ; br 2f / something happened 2360 <1> ; / yes, his interrupt so return 2361 <1> ; / to user 2362 <1> ; 24/12/2021 2363 0000460B 7405 <1> jz short sleep_2 2364 <1> sleep_3: 2365 0000460D E9D9EAFFFF <1> jmp sysret 2366 <1> sleep_2: 2367 <1> ; 30/06/2015 2368 00004612 0FB6DC <1> movzx ebx, ah ; 30/06/2015 2369 00004615 81C3[88610000] <1> add ebx, wlist 2370 0000461B 8A03 <1> mov al, [ebx] 2371 0000461D 20C0 <1> and al, al 2372 0000461F 7407 <1> jz short sleep1 2373 00004621 53 <1> push ebx 2374 00004622 E82DFFFFFF <1> call putlu 2375 00004627 5B <1> pop ebx 2376 <1> sleep1: 2377 00004628 A0[3B650000] <1> mov al, [u.uno] 2378 0000462D 8803 <1> mov [ebx], al ; put the process number 2379 <1> ; in the wait channel 2380 <1> ; mov (r0)+,r1 / put number of wait channel in r1 2381 <1> ; movb wlist(r1),-(sp) / put old process number in there, 2382 <1> ; / on the stack 2383 <1> ; movb u.uno,wlist(r1) / put process number of process 2384 <1> ; / to put to sleep in there 2385 <1> ; 15/09/2015 2386 0000462F 0FB6D8 <1> movzx ebx, al 2387 00004632 C683[63620000]04 <1> mov byte [ebx+p.stat-1], 4 ; SSLEEP 2388 <1> ; 26/02/2022 (p.waitc is not used) 2389 <1> ;inc ah 2390 <1> ;mov [ebx+p.waitc-1], ah ; wait channel + 1 2391 <1> ; 2392 00004639 66FF35[D3640000] <1> push word [cdev] 2393 <1> ; mov cdev,-(sp) / nothing happened in isintr so 2394 00004640 E842FEFFFF <1> call swap 2395 <1> ; jsr r0,swap / swap out process that needs to sleep 2396 00004645 668F05[D3640000] <1> pop word [cdev] 2397 <1> ; mov (sp)+,cdev / restore device 2398 0000464C E803000000 <1> call isintr 2399 <1> ; 22/09/2013 2400 <1> ;jnz sysret 2401 <1> ; jsr r0,isintr / check for interrupt of new process 2402 <1> ; br 2f / yes, return to new user 2403 <1> ; movb (sp)+,r1 / no, r1 = old process number that was 2404 <1> ; / originally on the wait channel 2405 <1> ; beq 1f / if 0 branch 2406 <1> ; mov $runq+4,r2 / r2 points to lowest priority queue 2407 <1> ; mov $300,*$ps / processor priority = 6 2408 <1> ; jsr r0,putlu / create link to old process number 2409 <1> ; clr *$ps / clear the status; process priority = 0 2410 <1> ; 24/12/2021 2411 00004651 75BA <1> jnz short sleep_3 ; jump to sysret 2412 <1> ;1: 2413 00004653 C3 <1> retn 2414 <1> ; rts r0 / return 2415 <1> ;2: 2416 <1> ;;jmp sysret 2417 <1> ; jmp sysret / return to user 2418 <1> 2419 <1> isintr: 2420 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2421 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2422 <1> ; 2423 <1> ; 09/05/2013 - 30/05/2014 2424 <1> ; 2425 <1> ; Retro UNIX 8086 v1 modification ! 2426 <1> ; (Process/task switching and quit routine by using 2427 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 2428 <1> ; 2429 <1> ; Retro UNIX 8086 v1 modification: 2430 <1> ; 'isintr' checks if user interrupt request is enabled 2431 <1> ; and there is a 'quit' request by user; 2432 <1> ; otherwise, 'isintr' will return with zf=1 that means 2433 <1> ; "nothing to do". (20/10/2013) 2434 <1> ; 2435 <1> ; 20/10/2013 2436 00004654 66833D[1C650000]00 <1> cmp word [u.ttyp], 0 ; has process got a tty ? 2437 0000465C 761F <1> jna short isintr2 ; retn 2438 <1> ; 03/09/2013 2439 <1> ; (nothing to do) 2440 <1> ;retn 2441 <1> ; 22/09/2013 2442 0000465E 66833D[30650000]00 <1> cmp word [u.intr], 0 2443 00004666 7615 <1> jna short isintr2 ; retn 2444 <1> ; 30/05/2014 2445 <1> ;push ax 2446 <1> ; 24/12/2021 2447 00004668 50 <1> push eax 2448 00004669 66A1[32650000] <1> mov ax, [u.quit] 2449 0000466F 6609C0 <1> or ax, ax ; 0 ? 2450 00004672 7408 <1> jz short isintr1 ; zf = 1 2451 00004674 6683F8FE <1> cmp ax, 0FFFEh ; 'ctrl + brk' check 2452 00004678 7702 <1> ja short isintr1 ; 0FFFFh, zf = 0 2453 <1> ;xor ax, ax ; zf = 1 2454 <1> ; 24/12/2021 2455 0000467A 31C0 <1> xor eax, eax ; zf = 1 2456 <1> isintr1: 2457 <1> ;pop ax 2458 <1> ; 24/12/2021 2459 0000467C 58 <1> pop eax 2460 <1> isintr2: ; 22/09/2013 2461 <1> ; zf=1 -> nothing to do 2462 0000467D C3 <1> retn 2463 <1> 2464 <1> ; UNIX v1 original 'isintr' routine... 2465 <1> ;mov r1,-(sp) / put number of wait channel on the stack 2466 <1> ;mov r2,-(sp) / save r2 2467 <1> ;mov u.ttyp,r1 / r1 = pointer to buffer of process control 2468 <1> ; / typewriter 2469 <1> ;beq 1f / if 0, do nothing except skip return 2470 <1> ;movb 6(r1),r1 / put interrupt char in the tty buffer in r1 2471 <1> ;beq 1f / if its 0 do nothing except skip return 2472 <1> ;cmp r1,$177 / is interrupt char = delete? 2473 <1> ;bne 3f / no, so it must be a quit (fs) 2474 <1> ;tst u.intr / yes, value of u.intr determines handling 2475 <1> ; / of interrupts 2476 <1> ;bne 2f / if not 0, 2f. If zero do nothing. 2477 <1> ;1: 2478 <1> ;tst (r0)+ / bump r0 past system return (skip) 2479 <1> ;4: 2480 <1> ;mov (sp)+,r2 / restore r1 and r2 2481 <1> ;mov (sp)+,r1 2482 <1> ;rts r0 2483 <1> ;3: / interrupt char = quit (fs) 2484 <1> ;tst u.quit / value of u.quit determines handling of quits 2485 <1> ;beq 1b / u.quit = 0 means do nothing 2486 <1> ;2: / get here because either u.intr <> 0 or u.qult <> O 2487 <1> ;mov $tty+6,r1 / move pointer to tty block into r1 2488 <1> ;1: / find process control tty entry in tty block 2489 <1> ;cmp (r1),u.ttyp / is this the process control tty buffer? 2490 <1> ;beq 1f / block found go to 1f 2491 <1> ;add $8,r1 / look at next tty block 2492 <1> ;cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks 2493 <1> ;blo 1b / no 2494 <1> ;br 4b / no process control tty found so go to 4b 2495 <1> ;1: 2496 <1> ;mov $240,*$ps / set processor priority to 5 2497 <1> ;movb -3(r1),0f / load getc call argument; character llst 2498 <1> ; / identifier 2499 <1> ;inc 0f / increment 2500 <1> ;1: 2501 <1> ;jsr r0,getc; 0:.. / erase output char list for control 2502 <1> ; br 4b / process tty. This prevents a line of stuff 2503 <1> ; / being typed out after you hit the interrupt 2504 <1> ; / key 2505 <1> ;br 1b 2118 %include 'u5.s' ; 03/06/2015 2119 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC 2120 <1> ; Last Modification: 22/04/2022 2121 <1> ; ---------------------------------------------------------------------------- 2122 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2123 <1> ; (v0.1 - Beginning: 11/07/2012) 2124 <1> ; 2125 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2126 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2127 <1> ; 2128 <1> ; 2129 <1> ; 2130 <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s 2131 <1> ; 2132 <1> ; **************************************************************************** 2133 <1> 2134 <1> mget: 2135 <1> ; 22/04/2022 2136 <1> ; 09/01/2022 2137 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2138 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2139 <1> ; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2140 <1> ; 2141 <1> ; Get existing or (allocate) a new disk block for file 2142 <1> ; 2143 <1> ; INPUTS -> 2144 <1> ; u.fofp (file offset pointer) 2145 <1> ; inode 2146 <1> ; u.off (file offset) 2147 <1> ; OUTPUTS -> 2148 <1> ; r1 (physical block number) 2149 <1> ; r2, r3, r5 (internal) 2150 <1> ; 2151 <1> ; ((AX = R1)) output 2152 <1> ; (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM) 2153 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 2154 <1> 2155 <1> ; mov *u.fofp,mq / file offset in mq 2156 <1> ; clr ac / later to be high sig 2157 <1> ; mov $-8,lsh / divide ac/mq by 256. 2158 <1> ; mov mq,r2 2159 <1> ; bit $10000,i.flgs / lg/sm is this a large or small file 2160 <1> ; bne 4f / branch for large file 2161 <1> mget_0: 2162 <1> ; 09/01/2022 2163 0000467E 29C0 <1> sub eax, eax 2164 00004680 29D2 <1> sub edx, edx 2165 00004682 29C9 <1> sub ecx, ecx 2166 00004684 29DB <1> sub ebx, ebx 2167 <1> 2168 00004686 8B35[FC640000] <1> mov esi, [u.fofp] 2169 <1> ;movzx ebx, byte [esi+1] 2170 <1> ; 09/01/2022 2171 0000468C 46 <1> inc esi 2172 0000468D 8A1E <1> mov bl, [esi] 2173 <1> 2174 <1> ; BX = r2 2175 <1> ; 24/12/2021 2176 0000468F F605[E5610000]10 <1> test byte [i.flgs+1], 10h 2177 <1> ;test word [i.flgs], 4096 ; 1000h 2178 <1> ; is this a large or small file 2179 00004696 756C <1> jnz short mget_5 ; 4f ; large file 2180 <1> 2181 00004698 F6C3F0 <1> test bl, 0F0h ; !0Fh 2182 <1> ; bit $!17,r2 2183 0000469B 7525 <1> jnz short mget_2 2184 <1> ; bne 3f / branch if r2 greater than or equal to 16 2185 0000469D 80E30E <1> and bl, 0Eh 2186 <1> ; bic $!16,r2 / clear all bits but bits 1,2,3 2187 <1> ; 09/01/2021 2188 000046A0 668B83[EA610000] <1> mov ax, [ebx+i.dskp] 2189 <1> ;movzx eax, word [ebx+i.dskp] ; AX = R1, physical block number 2190 <1> ; mov i.dskp(r2),r1 / r1 has physical block number 2191 <1> ; 24/12/2021 2192 000046A7 09C0 <1> or eax, eax 2193 <1> ;or ax, ax 2194 000046A9 7516 <1> jnz short mget_1 2195 <1> ; bne 2f / if physical block num is zero then need a new block 2196 <1> ; / for file 2197 000046AB E8A6000000 <1> call alloc 2198 <1> ; jsr r0,alloc / allocate a new block 2199 <1> ; eAX (r1) = Physical block number 2200 000046B0 668983[EA610000] <1> mov [ebx+i.dskp], ax 2201 <1> ; mov r1,i.dskp(r2) / physical block number stored in i-node 2202 000046B7 E835020000 <1> call setimod 2203 <1> ; jsr r0,setimod / set inode modified byte (imod) 2204 000046BC E8C2FEFFFF <1> call clear 2205 <1> ; jsr r0,clear / zero out disk/drum block just allocated 2206 <1> mget_1: ; 2: 2207 <1> ; eAX (r1) = Physical block number 2208 000046C1 C3 <1> retn 2209 <1> ; rts r0 2210 <1> mget_2: ; 3: / adding on block which changes small file to a large file 2211 000046C2 E88F000000 <1> call alloc 2212 <1> ; jsr r0,alloc / allocate a new block for this file; 2213 <1> ; / block number in r1 2214 <1> ; eAX (r1) = Physical block number 2215 000046C7 E84A0D0000 <1> call wslot 2216 <1> ; jsr r0,wslot / set up I/O buffer for write, r5 points to 2217 <1> ; / first data word in buffer 2218 <1> ; eAX (r1) = Physical block number 2219 <1> ; 09/01/2022 2220 000046CC 31C9 <1> xor ecx, ecx 2221 000046CE B108 <1> mov cl, 8 2222 <1> ;mov ecx, 8 ; R3, transfer old physical block pointers 2223 <1> ; into new indirect block area for the new 2224 <1> ; large file 2225 000046D0 89DF <1> mov edi, ebx ; r5 2226 000046D2 BE[EA610000] <1> mov esi, i.dskp 2227 <1> ; mov $8.,r3 / next 6 instructions transfer old physical 2228 <1> ; / block pointers 2229 <1> ; mov $i.dskp,r2 / into new indirect block for the new 2230 <1> ; / large file 2231 <1> ; 22/04/2022 2232 000046D7 50 <1> push eax ; * ; bugfix 2233 <1> 2234 <1> ;xor ax, ax ; mov ax, 0 2235 <1> ; 24/12/2021 2236 000046D8 31C0 <1> xor eax, eax 2237 <1> mget_3: ;1: 2238 000046DA 66A5 <1> movsw 2239 <1> ; mov (r2),(r5)+ 2240 000046DC 668946FE <1> mov [esi-2], ax 2241 <1> ; clr (r2)+ 2242 000046E0 E2F8 <1> loop mget_3 ; 1b 2243 <1> ; dec r3 2244 <1> ; bgt 1b 2245 <1> 2246 000046E2 B1F8 <1> mov cl, 256-8 2247 <1> ; mov $256.-8.,r3 / clear rest of data buffer 2248 <1> mget_4: ; 1 2249 000046E4 F366AB <1> rep stosw 2250 <1> ; clr (r5)+ 2251 <1> ; dec r3 2252 <1> ; bgt 1b 2253 <1> 2254 <1> ; 22/04/2022 2255 <1> ;pop eax ; * ; bugfix 2256 <1> 2257 <1> ; 24/03/2013 2258 <1> ; AX (r1) = Physical block number 2259 000046E7 E8370D0000 <1> call dskwr 2260 <1> ; jsr r0,dskwr / write new indirect block on disk 2261 <1> 2262 <1> ; 22/04/2022 2263 000046EC 58 <1> pop eax ; * ; bugfix 2264 <1> 2265 <1> ; eAX (r1) = Physical block number 2266 000046ED 66A3[EA610000] <1> mov [i.dskp], ax 2267 <1> ; mov r1,i.dskp / put pointer to indirect block in i-node 2268 <1> ; 09/01/2022 2269 000046F3 800D[E5610000]10 <1> or byte [i.flgs+1], 10h 2270 <1> ;or word [i.flgs], 4096 ; 1000h 2271 <1> ; bis $10000,i.flgs / set large file bit 2272 <1> ; / in i.flgs word of i-node 2273 000046FA E8F2010000 <1> call setimod 2274 <1> ; jsr r0,setimod / set i-node modified flag 2275 000046FF E97AFFFFFF <1> jmp mget_0 2276 <1> ; br mget 2277 <1> 2278 <1> mget_5: ; 4 ; large file 2279 <1> ; mov $-8,lsh / divide byte number by 256. 2280 <1> ; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset 2281 <1> ; / in indirect block 2282 <1> ; mov r2,-(sp) / save on stack (*) 2283 <1> ; mov mq,r2 / calculate offset in i-node for pointer to proper 2284 <1> ; / indirect block 2285 <1> ; bic $!16,r2 2286 00004704 80E3FE <1> and bl, 0FEh ; bh = 0 2287 00004707 53 <1> push ebx ; i-node pointer offset in indirect block (*) 2288 <1> ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512) 2289 <1> ; for this file system (offset 128 to 255 not in use) 2290 <1> ; There is always 1 indirect block for this file system 2291 <1> ; 09/01/2022 2292 00004708 66A1[EA610000] <1> mov ax, [i.dskp] 2293 <1> ;movzx eax, word [i.dskp] ; i.dskp[0] 2294 <1> ; mov i.dskp(r2),r1 2295 <1> ; 09/01/2022 2296 0000470E 09C0 <1> or eax, eax 2297 <1> ;or ax, ax ; R1 2298 00004710 7515 <1> jnz short mget_6 ; 2f 2299 <1> ; bne 2f / if no indirect block exists 2300 00004712 E83F000000 <1> call alloc 2301 <1> ; jsr r0,alloc / allocate a new block 2302 00004717 66A3[EA610000] <1> mov [i.dskp], ax ; 03/03/2013 2303 <1> ; mov r1,i.dskp(r2) / put block number of new block in i-node 2304 0000471D E8CF010000 <1> call setimod 2305 <1> ; jsr r0,setimod / set i-node modified byte 2306 <1> ; eAX = new block number 2307 00004722 E85CFEFFFF <1> call clear 2308 <1> ; jsr r0,clear / clear new block 2309 <1> mget_6: ;2 2310 <1> ; 05/03/2013 2311 <1> ; eAX = r1, physical block number (of indirect block) 2312 00004727 E8860C0000 <1> call dskrd ; read indirect block 2313 <1> ; jsr r0,dskrd / read in indirect block 2314 0000472C 5A <1> pop edx ; R2, get offset (*) 2315 <1> ; mov (sp)+,r2 / get offset 2316 <1> ; eAX = r1, physical block number (of indirect block) 2317 0000472D 50 <1> push eax ; ** ; 24/03/2013 2318 <1> ; mov r1,-(sp) / save block number of indirect block on stack 2319 <1> ; eBX (r5) = pointer to buffer (indirect block) 2320 0000472E 01D3 <1> add ebx, edx ; / r5 points to first word in indirect block, r2 2321 <1> ; add r5,r2 / r5 points to first word in indirect block, r2 2322 <1> ; / points to location of inter 2323 <1> ; 09/01/2022 2324 00004730 668B03 <1> mov ax, [ebx] 2325 <1> ;movzx eax, word [ebx] ; put physical block no of block 2326 <1> ; in file sought in R1 (AX) 2327 <1> ; mov (r2),r1 / put physical block no of block in file 2328 <1> ; / sought in r1 2329 <1> ; 09/01/2022 2330 00004733 09C0 <1> or eax, eax 2331 <1> ;or ax, ax 2332 00004735 751D <1> jnz short mget_7 ; 2f 2333 <1> ; bne 2f / if no block exists 2334 00004737 E81A000000 <1> call alloc 2335 <1> ; jsr r0,alloc / allocate a new block 2336 0000473C 668903 <1> mov [ebx], ax ; R1 2337 <1> ; mov r1,(r2) / put new block number into proper location in 2338 <1> ; / indirect block 2339 0000473F 5A <1> pop edx ; ** ; 24/03/2013 2340 <1> ; mov (sp)+,r1 / get block number of indirect block 2341 00004740 52 <1> push edx ; ** ; 31/07/2013 2342 00004741 50 <1> push eax ; * ; 24/03/2013, 31/07/2013 (new block number) 2343 00004742 89D0 <1> mov eax, edx ; 24/03/2013 2344 <1> ; mov (r2),-(sp) / save block number of new block 2345 <1> ; eAX (r1) = physical block number (of indirect block) 2346 00004744 E8CD0C0000 <1> call wslot 2347 <1> ; jsr r0,wslot 2348 <1> ; eAX (r1) = physical block number 2349 <1> ; eBX (r5) = pointer to buffer (indirect block) 2350 00004749 E8D50C0000 <1> call dskwr 2351 <1> ; eAX = r1 = physical block number (of indirect block) 2352 <1> ; jsr r0,dskwr / write newly modified indirect block 2353 <1> ; / back out on disk 2354 0000474E 58 <1> pop eax ; * ; 31/07/2013 2355 <1> ; mov (sp),r1 / restore block number of new block 2356 <1> ; eAX (r1) = physical block number of new block 2357 0000474F E82FFEFFFF <1> call clear 2358 <1> ; jsr r0,clear / clear new block 2359 <1> mget_7: ; 2 2360 00004754 5A <1> pop edx ; ** 2361 <1> ; tst (sp)+ / bump stack pointer 2362 <1> ; eAX (r1) = Block number of new block 2363 00004755 C3 <1> retn 2364 <1> ; rts r0 2365 <1> 2366 <1> alloc: 2367 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2368 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2369 <1> ; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2370 <1> ; 2371 <1> ; get a free block and 2372 <1> ; set the corresponding bit in the free storage map 2373 <1> ; 2374 <1> ; INPUTS -> 2375 <1> ; cdev (current device) 2376 <1> ; r2 2377 <1> ; r3 2378 <1> ; OUTPUTS -> 2379 <1> ; r1 (physical block number of block assigned) 2380 <1> ; smod, mmod, systm (super block), mount (mountable super block) 2381 <1> ; 2382 <1> ; ((AX = R1)) output 2383 <1> ; (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM) 2384 <1> ; ((Modified registers: DX, CX)) 2385 <1> 2386 <1> ;mov r2,-(sp) / save r2, r3 on stack 2387 <1> ;mov r3,-(sp) 2388 <1> ;push ecx 2389 00004756 53 <1> push ebx ; R2 2390 <1> ;push edx ; R3 2391 00004757 BB[BC750000] <1> mov ebx, systm ; SuperBlock 2392 <1> ; mov $systm,r2 / start of inode and free storage map for drum 2393 0000475C 803D[D3640000]00 <1> cmp byte [cdev], 0 2394 <1> ; tst cdev 2395 00004763 7605 <1> jna short alloc_1 2396 <1> ; beq 1f / drum is device 2397 00004765 BB[C4770000] <1> mov ebx, mount 2398 <1> ; mov $mount,r2 / disk or tape is device, start of inode and 2399 <1> ; / free storage map 2400 <1> alloc_1: ; 1 2401 <1> ; 09/01/2022 2402 <1> ;sub ecx, ecx 2403 <1> ;sub edx, edx 2404 <1> ;sub eax, eax 2405 <1> 2406 0000476A 668B0B <1> mov cx, [ebx] 2407 <1> ; mov (r2)+,r1 / first word contains number of bytes in free 2408 <1> ; / storage map 2409 <1> ; 09/01/2022 2410 0000476D C1E103 <1> shl ecx, 3 2411 <1> ;shl cx, 3 2412 <1> ; asl r1 / multiply r1 by eight gives 2413 <1> ; number of blocks in device 2414 <1> ; asl r1 2415 <1> ; asl r1 2416 <1> ;;push cx ;; 01/08/2013 2417 <1> ; mov r1,-(sp) / save # of blocks in device on stack 2418 00004770 31C0 <1> xor eax, eax ; 0 2419 <1> ; clr r1 / r1 contains bit count of free storage map 2420 <1> alloc_2: ; 1 2421 00004772 43 <1> inc ebx ; 18/8/2012 2422 00004773 43 <1> inc ebx ; 2423 00004774 668B13 <1> mov dx, [ebx] 2424 <1> ; mov (r2)+,r3 / word of free storage map in r3 2425 <1> ; 09/01/2022 2426 00004777 09D2 <1> or edx, edx 2427 <1> ;or dx, dx 2428 00004779 750D <1> jnz short alloc_3 ; 1f 2429 <1> ; bne 1f / branch if any free blocks in this word 2430 0000477B 6683C010 <1> add ax, 16 2431 <1> ; add $16.,r1 2432 <1> ; 09/01/2022 2433 0000477F 39C8 <1> cmp eax, ecx 2434 <1> ;cmp ax, cx 2435 <1> ; cmp r1 ,(sp) / have we examined all free storage bytes 2436 00004781 72EF <1> jb short alloc_2 2437 <1> ; blo 1b 2438 <1> ; 14/11/2015 2439 <1> ; Note: If the super block buffer has wrong content (zero bytes) 2440 <1> ; because of a (DMA or another) r/w error, 2441 <1> ; we will be here, at 'jmp panic' code address, 2442 <1> ; even if the (disk) file system space is not full !!! 2443 <1> ; (cx = 0) 2444 <1> ; 2445 00004783 E905E2FFFF <1> jmp panic 2446 <1> ; jmp panic / found no free storage 2447 <1> alloc_3: ; 1 2448 <1> ; 09/01/2022 2449 00004788 D1EA <1> shr edx, 1 2450 <1> ;shr dx, 1 2451 <1> ; asr r3 / find a free block 2452 0000478A 7203 <1> jc short alloc_4 ; 1f 2453 <1> ; bcs 1f / branch when free block found; bit for block k 2454 <1> ; / is in byte k/8 / in bit k (mod 8) 2455 <1> ; 09/01/2022 2456 0000478C 40 <1> inc eax 2457 <1> ;inc ax 2458 <1> ; inc r1 / increment bit count in bit k (mod8) 2459 0000478D EBF9 <1> jmp short alloc_3 2460 <1> ; br 1b 2461 <1> alloc_4: ; 1: 2462 <1> ;; pop cx ;; 01/08/2013 2463 <1> ; tst (sp)+ / bump sp 2464 <1> ; 02/04/2013 2465 0000478F E829000000 <1> call free3 2466 <1> ; jsr r0,3f / have found a free block 2467 <1> ; 21/8/2012 2468 00004794 66F7D2 <1> not dx ; masking bit is '0' and others are '1' 2469 00004797 662113 <1> and [ebx], dx ;; 0 -> allocated 2470 <1> ; bic r3,(r2) / set bit for this block 2471 <1> ; / i.e. assign block 2472 <1> ; br 2f 2473 0000479A EB09 <1> jmp short alloc_5 2474 <1> 2475 <1> free: 2476 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2477 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2478 <1> ; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2479 <1> ; 2480 <1> ; calculates byte address and bit position for given block number 2481 <1> ; then sets the corresponding bit in the free storage map 2482 <1> ; 2483 <1> ; INPUTS -> 2484 <1> ; r1 - block number for a block structured device 2485 <1> ; cdev - current device 2486 <1> ; OUTPUTS -> 2487 <1> ; free storage map is updated 2488 <1> ; smod is incremented if cdev is root device (fixed disk) 2489 <1> ; mmod is incremented if cdev is a removable disk 2490 <1> ; 2491 <1> ; (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM) 2492 <1> ; ((Modified registers: DX, CX)) 2493 <1> 2494 <1> ;mov r2,-(sp) / save r2, r3 2495 <1> ;mov r3,-(sp) 2496 <1> ;push ecx 2497 0000479C 53 <1> push ebx ; R2 2498 <1> ;push edx ; R3 2499 <1> 2500 0000479D E81B000000 <1> call free3 2501 <1> ; jsr r0,3f / set up bit mask and word no. 2502 <1> ; / in free storage map for block 2503 000047A2 660913 <1> or [ebx], dx 2504 <1> ; bis r3, (r2) / set free storage block bit; 2505 <1> ; / indicates free block 2506 <1> ; 0 -> allocated, 1 -> free 2507 <1> 2508 <1> alloc_5: 2509 <1> ; 07/04/2013 2510 <1> free_1: ; 2: 2511 <1> ;pop edx 2512 <1> ; mov (sp)+,r3 / restore r2, r3 2513 000047A5 5B <1> pop ebx 2514 <1> ; mov (sp)+,r2 2515 <1> ; pop ecx 2516 000047A6 803D[D3640000]00 <1> cmp byte [cdev], 0 2517 <1> ; tst cdev / cdev = 0, block structured, drum; 2518 <1> ; / cdev = 1, mountable device 2519 000047AD 7707 <1> ja short alloc_6 ; 1f 2520 <1> ; bne 1f 2521 <1> ;mov byte [smod], 1 2522 000047AF FE05[E1640000] <1> inc byte [smod] 2523 <1> ; incb smod / set super block modified for drum 2524 <1> ; eAX (r1) = block number 2525 000047B5 C3 <1> retn 2526 <1> ; rts r0 2527 <1> free_2: 2528 <1> alloc_6: ; 1: 2529 <1> ;mov byte [mmod], 1 2530 000047B6 FE05[E2640000] <1> inc byte [mmod] 2531 <1> ; incb mmod 2532 <1> ; / set super block modified for mountable device 2533 <1> ; eAX (r1) = block number 2534 000047BC C3 <1> retn 2535 <1> ; rts r0 2536 <1> free3: 2537 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2538 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2539 <1> ; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2540 <1> ; 2541 <1> ; free3 is called from 'alloc' and 'free' procedures 2542 <1> ; 2543 <1> alloc_free_3: ; 3 2544 <1> ;mov dx, 1 2545 <1> ; 09/01/2022 2546 000047BD 31D2 <1> xor edx, edx 2547 000047BF 42 <1> inc edx 2548 <1> ; edx = 1 2549 000047C0 88C1 <1> mov cl, al 2550 <1> ; mov r1,r2 / block number, k, = 1 2551 000047C2 80E10F <1> and cl, 0Fh ; 0Fh <-- (k) mod 16 2552 <1> ; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8) 2553 000047C5 7402 <1> jz short free4 2554 <1> ; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to 2555 <1> ; / (k) mod 8 2556 <1> ;shl dx, cl 2557 <1> ; 09/01/2022 2558 000047C7 D3E2 <1> shl edx, cl 2559 <1> free4: 2560 000047C9 0FB7D8 <1> movzx ebx, ax 2561 <1> ; mov r1,r2 / divide block number by 16 2562 <1> ; 09/01/2022 2563 000047CC C1EB04 <1> shr ebx, 4 2564 <1> ;shr bx, 4 2565 <1> ; asr r2 2566 <1> ; asr r2 2567 <1> ; asr r2 2568 <1> ; asr r2 2569 <1> ; bcc 1f / branch if bit 3 in r1 was 0 i.e., 2570 <1> ; / bit for block is in lower half of word 2571 <1> ; swab r3 / swap bytes in r3; bit in upper half of word in free 2572 <1> ; / storage map 2573 <1> alloc_free_4: ; 1 2574 <1> ; 09/01/2022 2575 000047CF D1E3 <1> shl ebx, 1 2576 <1> ;shl bx, 1 2577 <1> ; asl r2 / multiply block number by 2; r2 = k/8 2578 000047D1 81C3[BE750000] <1> add ebx, systm+2 ; SuperBlock+2 2579 <1> ; add $systm+2,r2 / address of word of free storage map for drum 2580 <1> ; / with block bit in it 2581 000047D7 803D[D3640000]00 <1> cmp byte [cdev], 0 2582 <1> ; tst cdev 2583 000047DE 7606 <1> jna short alloc_free_5 2584 <1> ; beq 1f / cdev = 0 indicates device is drum 2585 000047E0 81C308020000 <1> add ebx, mount - systm 2586 <1> ; add $mount-systm,r2 / address of word of free storage map for 2587 <1> ; / mountable device with bit of block to be 2588 <1> ; / freed 2589 <1> alloc_free_5: ; 1 2590 000047E6 C3 <1> retn 2591 <1> ; rts r0 / return to 'free' 2592 <1> ; 2 2593 <1> ; .byte 1,2,4,10,20,40,100,200 / masks for bits 0,...,7 2594 <1> 2595 <1> iget: 2596 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2597 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2598 <1> ; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 2599 <1> ; 2600 <1> ; get a new i-node whose i-number in r1 and whose device is in cdev 2601 <1> ; 2602 <1> ; ('iget' returns current i-number in r1, if input value of r1 is 0) 2603 <1> ; 2604 <1> ; INPUTS -> 2605 <1> ; ii - current i-number, rootdir 2606 <1> ; cdev - new i-node device 2607 <1> ; idev - current i-node device 2608 <1> ; imod - current i-node modified flag 2609 <1> ; mnti - cross device file i-number 2610 <1> ; r1 - i-numbe rof new i-node 2611 <1> ; mntd - mountable device number 2612 <1> ; 2613 <1> ; OUTPUTS -> 2614 <1> ; cdev, idev, imod, ii, r1 2615 <1> ; 2616 <1> ; ((AX = R1)) input/output 2617 <1> ; 2618 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 2619 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2620 <1> 2621 000047E7 8A15[D3640000] <1> mov dl, [cdev] ; 18/07/2013 2622 000047ED 8A35[D2640000] <1> mov dh, [idev] ; 07/08/2013 2623 <1> ; 2624 000047F3 663B05[D0640000] <1> cmp ax, [ii] 2625 <1> ; cmp r1,ii / r1 = i-number of current file 2626 000047FA 7504 <1> jne short iget_1 2627 <1> ; bne 1f 2628 000047FC 38F2 <1> cmp dl, dh 2629 <1> ; cmp idev,cdev 2630 <1> ; / is device number of i-node = current device 2631 000047FE 7472 <1> je short iget_5 2632 <1> ; beq 2f 2633 <1> iget_1: ; 1: 2634 00004800 30DB <1> xor bl, bl 2635 00004802 381D[E0640000] <1> cmp [imod], bl ; 0 2636 <1> ; tstb imod / has i-node of current file 2637 <1> ; / been modified i.e., imod set 2638 00004808 7629 <1> jna short iget_2 2639 <1> ; beq 1f 2640 0000480A 881D[E0640000] <1> mov [imod], bl ; 0 2641 <1> ; clrb imod / if it has, 2642 <1> ; / we must write the new i-node out on disk 2643 <1> ; 24/12/2021 2644 00004810 50 <1> push eax ; * 2645 <1> ;push ax 2646 <1> ; mov r1,-(sp) 2647 <1> ;mov dl, [cdev] 2648 00004811 52 <1> push edx ; ** 2649 <1> ;push dx 2650 <1> ; mov cdev,-(sp) 2651 00004812 66A1[D0640000] <1> mov ax, [ii] 2652 <1> ; mov ii,r1 2653 <1> ;mov dh, [idev] 2654 00004818 8835[D3640000] <1> mov [cdev], dh 2655 <1> ; mov idev,cdev 2656 0000481E FEC3 <1> inc bl ; 1 2657 <1> ; 31/07/2013 2658 00004820 881D[70650000] <1> mov [rw], bl ; 1 == write 2659 <1> ;;28/07/2013 rw -> u.rw 2660 <1> ;;mov [u.rw], bl ; 1 == write 2661 00004826 E848000000 <1> call icalc 2662 <1> ; jsr r0,icalc; 1 2663 <1> ;pop dx 2664 <1> ; 24/12/2021 2665 0000482B 5A <1> pop edx ; ** 2666 0000482C 8815[D3640000] <1> mov [cdev], dl 2667 <1> ; mov (sp)+,cdev 2668 <1> ; 24/12/2021 2669 00004832 58 <1> pop eax ; * 2670 <1> ;pop ax 2671 <1> ; mov (sp)+,r1 2672 <1> iget_2: ; 1: 2673 00004833 6621C0 <1> and ax, ax 2674 <1> ; tst r1 / is new i-number non zero 2675 00004836 7434 <1> jz short iget_4 ; 2f 2676 <1> ; beq 2f / branch if r1=0 2677 <1> 2678 <1> ;mov dl, [cdev] 2679 00004838 08D2 <1> or dl, dl 2680 <1> ; tst cdev / is the current device number non zero 2681 <1> ; / (i.e., device =/ drum) 2682 0000483A 7517 <1> jnz short iget_3 ; 1f 2683 <1> ; bne 1f / branch 1f cdev =/ 0 ;; (cdev != 0) 2684 0000483C 663B05[D6640000] <1> cmp ax, [mnti] 2685 <1> ; cmp r1,mnti / mnti is the i-number of the cross device 2686 <1> ; / file (root directory of mounted device) 2687 00004843 750E <1> jne short iget_3 ; 1f 2688 <1> ; bne 1f 2689 <1> ;mov bl, [mntd] 2690 00004845 FEC2 <1> inc dl ; mov dl, 1 ; 17/07/2013 2691 00004847 8815[D3640000] <1> mov [cdev], dl ; 17/07/2013 - 09/07/2013 2692 <1> ; mov mntd,cdev / make mounted device the current device 2693 0000484D 66A1[DC640000] <1> mov ax, [rootdir] 2694 <1> ; mov rootdir,r1 2695 <1> iget_3: ; 1: 2696 00004853 66A3[D0640000] <1> mov [ii], ax 2697 <1> ; mov r1,ii 2698 00004859 8815[D2640000] <1> mov [idev], dl ; cdev 2699 <1> ; mov cdev,idev 2700 0000485F 30DB <1> xor bl, bl 2701 <1> ; 31/07/2013 2702 00004861 881D[70650000] <1> mov [rw], bl ; 0 == read 2703 <1> ;;28/07/2013 rw -> u.rw 2704 <1> ;;mov [u.rw], bl ; 0 = read 2705 00004867 E807000000 <1> call icalc 2706 <1> ; jsr r0,icalc; 0 / read in i-node ii 2707 <1> iget_4: ; 2: 2708 0000486C 66A1[D0640000] <1> mov ax, [ii] 2709 <1> ; mov ii,r1 2710 <1> iget_5: 2711 00004872 C3 <1> retn 2712 <1> ; rts r0 2713 <1> 2714 <1> icalc: 2715 <1> ; 04/04/2022 (47->31) 2716 <1> ; (Inode Table/List Address modification) 2717 <1> ; 09/01/2022 2718 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2719 <1> ; 02/07/2015 2720 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2721 <1> ; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2722 <1> ; 2723 <1> ; calculate physical block number from i-number then 2724 <1> ; read or write that block 2725 <1> ; 2726 <1> ; 'icalc' is called from 'iget' 2727 <1> ; 2728 <1> ; for original unix v1: 2729 <1> ; / i-node i is located in block (i+31.)/16. and begins 32.* 2730 <1> ; / (i+31.) mod 16. bytes from its start 2731 <1> ; 2732 <1> ; for retro unix 8086 v1: 2733 <1> ; i-node is located in block (i+47)/16 and 2734 <1> ; begins 32*(i+47) mod 16 bytes from its start 2735 <1> ; 2736 <1> ; INPUTS -> 2737 <1> ; r1 - i-number of i-node 2738 <1> ; 2739 <1> ; OUTPUTS -> 2740 <1> ; inode r/w 2741 <1> ; 2742 <1> ; ((AX = R1)) input 2743 <1> ; 2744 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 2745 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 2746 <1> ; 2747 00004873 0FB7D0 <1> movzx edx, ax 2748 <1> ;add dx, 47 2749 <1> ; 04/04/2022 2750 00004876 6683C21F <1> add dx, 31 2751 0000487A 89D0 <1> mov eax, edx 2752 <1> ;;add ax, 47 ; add 47 to inode number 2753 <1> ;add ax, 31 2754 <1> ; add $31.,r1 / add 31. to i-number 2755 0000487C 50 <1> push eax 2756 <1> ; mov r1,-(sp) / save i+31. on stack 2757 <1> ; 09/01/2022 2758 0000487D C1E804 <1> shr eax, 4 2759 <1> ;shr ax, 4 2760 <1> ; asr r1 / divide by 16. 2761 <1> ; asr r1 2762 <1> ; asr r1 2763 <1> ; asr r1 / r1 contains block number of block 2764 <1> ; / in which i-node exists 2765 00004880 E82D0B0000 <1> call dskrd 2766 <1> ; jsr r0,dskrd / read in block containing i-node i. 2767 <1> ; 31/07/2013 2768 00004885 803D[70650000]00 <1> cmp byte [rw], 0 ; Retro Unix 8086 v1 feature ! 2769 <1> ;; 28/07/2013 rw -> u.rw 2770 <1> ;;cmp byte [u.rw], 0 ; Retro Unix 8086 v1 feature ! 2771 <1> ; tst (r0) 2772 0000488C 7605 <1> jna short icalc_1 2773 <1> ; beq 1f / branch to wslot when argument 2774 <1> ; / in icalc call = 1 2775 <1> ; eAX = r1 = block number 2776 0000488E E8830B0000 <1> call wslot 2777 <1> ; jsr r0,wslot / set up data buffer for write 2778 <1> ; / (will be same buffer as dskrd got) 2779 <1> ; eBX = r5 points to first word in data area for this block 2780 <1> icalc_1: ; 1: 2781 00004893 5A <1> pop edx 2782 00004894 83E20F <1> and edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16 2783 <1> ; bic $!17,(sp) / zero all but last 4 bits; 2784 <1> ; / gives (i+31.) mod 16 2785 00004897 C1E205 <1> shl edx, 5 2786 <1> ; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16) 2787 0000489A 89DE <1> mov esi, ebx ; ebx points 1st word of the buffer 2788 0000489C 01D6 <1> add esi, edx ; edx is inode offset in the buffer 2789 <1> ; eSI (r5) points to first word in i-node i. 2790 <1> ; mov (sp)+,mq / calculate offset in data buffer; 2791 <1> ; / 32.*(i+31.)mod16 2792 <1> ; mov $5,lsh / for i-node i. 2793 <1> ; add mq,r5 / r5 points to first word in i-node i. 2794 0000489E BF[E4610000] <1> mov edi, inode 2795 <1> ; mov $inode,r1 / inode is address of first word 2796 <1> ; / of current i-node 2797 <1> ; 09/01/2022 2798 000048A3 29C9 <1> sub ecx, ecx 2799 000048A5 B108 <1> mov cl, 8 2800 <1> ;mov ecx, 8 ; 02/07/2015(32 bit modification) 2801 <1> ; mov $16.,r3 2802 <1> ; 31/07/2013 2803 000048A7 382D[70650000] <1> cmp [rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 2804 <1> ;;28/07/2013 rw -> u.rw 2805 <1> ;;cmp [u.rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 2806 <1> ; tst (r0)+ / branch to 2f when argument in icalc call = 0 2807 000048AD 7609 <1> jna short icalc_3 2808 <1> ; beq 2f / r0 now contains proper return address 2809 <1> ; / for rts r0 2810 <1> icalc_2: ; 1: 2811 000048AF 87F7 <1> xchg esi, edi 2812 <1> ; overwrite old i-node (in buffer to be written) 2813 000048B1 F3A5 <1> rep movsd 2814 <1> ; mov (r1)+,(r5)+ / over write old i-node 2815 <1> ; dec r3 2816 <1> ; bgt 1b 2817 <1> ;call dskwr 2818 <1> ; jsr r0,dskwr / write inode out on device 2819 <1> ;retn 2820 <1> ; rts r0 2821 <1> ; 24/12/2021 2822 000048B3 E96B0B0000 <1> jmp dskwr 2823 <1> 2824 <1> icalc_3: ; 2: 2825 <1> ; copy new i-node into inode area of (core) memory 2826 000048B8 F3A5 <1> rep movsd 2827 <1> ; mov (r5)+,(r1)+ / read new i-node into 2828 <1> ; / "inode" area of core 2829 <1> ; dec r3 2830 <1> ; bgt 2b 2831 000048BA C3 <1> retn 2832 <1> ; rts r0 2833 <1> 2834 <1> access: 2835 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2836 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2837 <1> ; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1) 2838 <1> ; 2839 <1> ; check whether user is owner of file or user has read or write 2840 <1> ; permission (based on i.flgs). 2841 <1> ; 2842 <1> ; INPUTS -> 2843 <1> ; r1 - i-number of file 2844 <1> ; u.uid 2845 <1> ; arg0 -> (owner flag mask) 2846 <1> ; Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 2847 <1> ; OUTPUTS -> 2848 <1> ; inode (or jump to error) 2849 <1> ; 2850 <1> ; ((AX = R1)) input/output 2851 <1> ; 2852 <1> ; ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP)) 2853 <1> 2854 <1> ;push dx ; save flags (DL) 2855 <1> ; 24/12/2021 2856 000048BB 52 <1> push edx ; save flags (DL) 2857 000048BC E826FFFFFF <1> call iget 2858 <1> ; jsr r0,iget / read in i-node for current directory 2859 <1> ; / (i-number passed in r1) 2860 000048C1 8A0D[E4610000] <1> mov cl, [i.flgs] 2861 <1> ; mov i.flgs,r2 2862 <1> ; 24/12/2021 2863 000048C7 5A <1> pop edx ; restore flags (DL) 2864 <1> ;pop dx ; restore flags (DL) 2865 000048C8 8A35[38650000] <1> mov dh, [u.uid] 2866 000048CE 3A35[E7610000] <1> cmp dh, [i.uid] 2867 <1> ; cmpb i.uid,u.uid / is user same as owner of file 2868 000048D4 7503 <1> jne short access_1 2869 <1> ; bne 1f / no, then branch 2870 000048D6 C0E902 <1> shr cl, 2 2871 <1> ; asrb r2 / shift owner read write bits into non owner 2872 <1> ; / read/write bits 2873 <1> ; asrb r2 2874 <1> access_1: ; 1: 2875 000048D9 20D1 <1> and cl, dl 2876 <1> ; bit r2,(r0)+ / test read-write flags against argument 2877 <1> ; / in access call 2878 000048DB 7513 <1> jnz short access_2 2879 <1> ; bne 1f 2880 000048DD 08F6 <1> or dh, dh ; super user (root) ? 2881 <1> ; tstb u.uid 2882 000048DF 740F <1> jz short access_2 ; yes, super user 2883 <1> ;jnz error 2884 <1> ; beq 1f 2885 <1> ; jmp error 2886 000048E1 C705[41650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS 2886 000048E9 0000 <1> 2887 <1> ; 'permission denied !' error 2888 000048EB E9DBE7FFFF <1> jmp error 2889 <1> 2890 <1> access_2: ; 1: 2891 <1> ; DL = flags 2892 000048F0 C3 <1> retn 2893 <1> ; rts r0 2894 <1> 2895 <1> setimod: 2896 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2897 <1> ; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2898 <1> ; 2899 <1> ; 'setimod' sets byte at location 'imod' to 1; thus indicating that 2900 <1> ; the inode has been modified. Also puts the time of modification 2901 <1> ; into the inode. 2902 <1> ; 2903 <1> ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) 2904 <1> ; ((Modified registers: eDX, eCX, eBX)) 2905 <1> ; 2906 <1> 2907 <1> ;push edx 2908 000048F1 50 <1> push eax 2909 <1> 2910 000048F2 C605[E0640000]01 <1> mov byte [imod], 1 2911 <1> ; movb $1,imod / set current i-node modified bytes 2912 <1> ; Erdogan Tan 14-7-2012 2913 000048F9 E81EE3FFFF <1> call epoch 2914 <1> ; mov s.time,i.mtim 2915 <1> ; / put present time into file modified time 2916 <1> ; mov s.time+2,i.mtim+2 2917 <1> 2918 000048FE A3[FE610000] <1> mov [i.mtim], eax 2919 <1> 2920 <1> ; Retro UNIX 386 v1 modification ! (cmp) 2921 <1> ; Retro UNIX 8086 v1 modification ! (test) 2922 00004903 833D[FA610000]00 <1> cmp dword [i.ctim], 0 2923 0000490A 7505 <1> jnz short setimod_ok 2924 <1> 2925 0000490C A3[FA610000] <1> mov [i.ctim], eax 2926 <1> 2927 <1> setimod_ok: ; 31/07/2013 2928 00004911 58 <1> pop eax 2929 <1> ;pop edx 2930 <1> 2931 00004912 C3 <1> retn 2932 <1> ; rts r0 2933 <1> 2934 <1> itrunc: 2935 <1> ; 03/02/2022 2936 <1> ; 09/01/2022 2937 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2938 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 2939 <1> ; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 2940 <1> ; 2941 <1> ; 'itrunc' truncates a file whose i-number is given in r1 2942 <1> ; to zero length. 2943 <1> ; 2944 <1> ; INPUTS -> 2945 <1> ; r1 - i-number of i-node 2946 <1> ; i.dskp - pointer to contents or indirect block in an i-node 2947 <1> ; i.flgs - large file flag 2948 <1> ; i.size - size of file 2949 <1> ; 2950 <1> ; OUTPUTS -> 2951 <1> ; i.flgs - large file flag is cleared 2952 <1> ; i.size - set to 0 2953 <1> ; i.dskp .. i.dskp+16 - entire list is cleared 2954 <1> ; setimod - set to indicate i-node has been modified 2955 <1> ; r1 - i-number of i-node 2956 <1> ; 2957 <1> ; ((AX = R1)) input/output 2958 <1> ; 2959 <1> ; (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM) 2960 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 2961 <1> 2962 00004913 E8CFFEFFFF <1> call iget 2963 <1> ; jsr r0,iget 2964 00004918 BE[EA610000] <1> mov esi, i.dskp 2965 <1> ; mov $i.dskp,r2 / address of block pointers in r2 2966 0000491D 31C0 <1> xor eax, eax 2967 <1> itrunc_1: ; 1: 2968 0000491F 66AD <1> lodsw 2969 <1> ; mov (r2)+,r1 / move physical block number into r1 2970 <1> ; 09/01/2022 2971 00004921 09C0 <1> or eax, eax 2972 <1> ;or ax, ax 2973 00004923 7433 <1> jz short itrunc_5 2974 <1> ; beq 5f 2975 00004925 56 <1> push esi 2976 <1> ; mov r2,-(sp) 2977 <1> ; 09/01/2022 2978 00004926 F605[E5610000]10 <1> test byte [i.flgs+1], 10h 2979 <1> ;test word [i.flgs], 1000h 2980 <1> ; bit $10000,i.flgs / test large file bit? 2981 0000492D 7423 <1> jz short itrunc_4 2982 <1> ; beq 4f / if clear, branch 2983 0000492F 50 <1> push eax 2984 <1> ; mov r1,-(sp) / save block number of indirect block 2985 00004930 E87D0A0000 <1> call dskrd 2986 <1> ; jsr r0,dskrd / read in block, 1st data word 2987 <1> ; / pointed to by r5 2988 <1> ; eBX = r5 = Buffer data address (the 1st word) 2989 <1> ; 09/01/2022 2990 00004935 31C9 <1> xor ecx, ecx 2991 00004937 FEC5 <1> inc ch ; mov ch, 1 2992 <1> ; ecx = 256 2993 <1> ;mov ecx, 256 2994 <1> ; mov $256.,r3 / move word count into r3 2995 00004939 89DE <1> mov esi, ebx 2996 <1> itrunc_2: ; 2: 2997 0000493B 66AD <1> lodsw 2998 <1> ; mov (r5)+,r1 / put 1st data word in r1; 2999 <1> ; / physical block number 3000 <1> ; 09/01/2022 3001 0000493D 21C0 <1> and eax, eax 3002 <1> ;and ax, ax 3003 0000493F 7407 <1> jz short itrunc_3 3004 <1> ; beq 3f / branch if zero 3005 <1> ; 24/12/2021 3006 00004941 51 <1> push ecx 3007 <1> ;push cx 3008 <1> ; mov r3,-(sp) / save r3, r5 on stack 3009 <1> ;push esi 3010 <1> ; mov r5,-(sp) 3011 00004942 E855FEFFFF <1> call free 3012 <1> ; jsr r0,free / free block in free storage map 3013 <1> ;pop esi 3014 <1> ; mov(sp)+,r5 3015 <1> ;pop cx 3016 00004947 59 <1> pop ecx 3017 <1> ; mov (sp)+,r3 3018 <1> itrunc_3: ; 3: 3019 00004948 E2F1 <1> loop itrunc_2 3020 <1> ; dec r3 / decrement word count 3021 <1> ; bgt 2b / branch if positive 3022 0000494A 58 <1> pop eax 3023 <1> ; mov (sp)+,r1 / put physical block number of 3024 <1> ; / indirect block 3025 <1> ; 01/08/2013 3026 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 3027 <1> ; 03/02/2022 3028 0000494B 8025[E5610000]EF <1> and byte [i.flgs+1], 0EFh 3029 <1> itrunc_4: ; 4: 3030 00004952 E845FEFFFF <1> call free 3031 <1> ; jsr r0,free / free indirect block 3032 00004957 5E <1> pop esi 3033 <1> ; mov (sp)+,r2 3034 <1> itrunc_5: ; 5: 3035 00004958 81FE[FA610000] <1> cmp esi, i.dskp+16 3036 <1> ; cmp r2,$i.dskp+16. 3037 0000495E 72BF <1> jb short itrunc_1 3038 <1> ; bne 1b / branch until all i.dskp entries check 3039 <1> ; 03/02/2022 3040 <1> ;and byte [i.flgs+1], 0EFh 3041 <1> ; 01/08/2013 3042 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 3043 <1> ; bic $10000,i.flgs / clear large file bit 3044 00004960 BF[EA610000] <1> mov edi, i.dskp 3045 <1> ;mov cx, 8 3046 <1> ;xor ax, ax 3047 <1> ; 09/01/2022 3048 00004965 29C9 <1> sub ecx, ecx 3049 00004967 B108 <1> mov cl, 8 3050 00004969 29C0 <1> sub eax, eax 3051 0000496B 66A3[E8610000] <1> mov [i.size], ax ; 0 3052 <1> ; clr i.size / zero file size 3053 00004971 F366AB <1> rep stosw 3054 <1> ; jsr r0,copyz; i.dskp; i.dskp+16. 3055 <1> ; / zero block pointers 3056 00004974 E878FFFFFF <1> call setimod 3057 <1> ; jsr r0,setimod / set i-node modified flag 3058 00004979 66A1[D0640000] <1> mov ax, [ii] 3059 <1> ; mov ii,r1 3060 0000497F C3 <1> retn 3061 <1> ; rts r0 3062 <1> 3063 <1> imap: 3064 <1> ; 11/02/2022 3065 <1> ; 03/02/2022 3066 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 3067 <1> ; 26/04/2013 (Retro UNIX 8086 v1) 3068 <1> ; 3069 <1> ; 'imap' finds the byte in core (superblock) containing 3070 <1> ; allocation bit for an i-node whose number in r1. 3071 <1> ; 3072 <1> ; INPUTS -> 3073 <1> ; r1 - contains an i-number 3074 <1> ; fsp - start of table containing open files 3075 <1> ; 3076 <1> ; OUTPUTS -> 3077 <1> ; r2 - byte address of byte with the allocation bit 3078 <1> ; mq - a mask to locate the bit position. 3079 <1> ; (a 1 is in calculated bit posisiton) 3080 <1> ; 3081 <1> ; ((AX = R1)) input/output 3082 <1> ; ((DL/DX = MQ)) output 3083 <1> ; ((BX = R2)) output 3084 <1> ; 3085 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 3086 <1> ; ((Modified registers: eDX, eCX, eBX, eSI)) 3087 <1> ; 3088 <1> ; / get the byte that has the allocation bit for 3089 <1> ; / the i-number contained in r1 3090 <1> ;mov dx, 1 3091 00004980 B201 <1> mov dl, 1 3092 <1> ; mov $1,mq / put 1 in the mq 3093 00004982 0FB7D8 <1> movzx ebx, ax 3094 <1> ; mov r1,r2 / r2 now has i-number whose byte 3095 <1> ; / in the map we must find 3096 00004985 6683EB29 <1> sub bx, 41 3097 <1> ; sub $41.,r2 / r2 has i-41 3098 00004989 88D9 <1> mov cl, bl 3099 <1> ; mov r2,r3 / r3 has i-41 3100 0000498B 80E107 <1> and cl, 7 3101 <1> ; bic $!7,r3 / r3 has (i-41) mod 8 to get 3102 <1> ; / the bit position 3103 0000498E 7402 <1> jz short imap1 3104 <1> ;shl dx, cl 3105 00004990 D2E2 <1> shl dl, cl 3106 <1> ; mov r3,lsh / move the 1 over (i-41) mod 8 positions 3107 <1> imap1: ; / to the left to mask the correct bit 3108 <1> ; 03/02/2022 3109 00004992 C1EB03 <1> shr ebx, 3 3110 <1> ;shr bx, 3 3111 <1> ; asr r2 3112 <1> ; asr r2 3113 <1> ; asr r2 / r2 has (i-41) base 8 of the byte number 3114 <1> ; / from the start of the map 3115 <1> ; mov r2,-(sp) / put (i-41) base 8 on the stack 3116 00004995 BE[BC750000] <1> mov esi, systm 3117 <1> ; mov $systm,r2 / r2 points to the in-core image of 3118 <1> ; / the super block for drum 3119 <1> ;cmp word [cdev], 0 3120 0000499A 803D[D3640000]00 <1> cmp byte [cdev], 0 3121 <1> ; tst cdev / is the device the disk 3122 000049A1 7606 <1> jna short imap2 3123 <1> ; beq 1f / yes 3124 000049A3 81C608020000 <1> add esi, mount - systm 3125 <1> ; add $mount-systm,r2 / for mounted device, 3126 <1> ; / r2 points to 1st word of its super block 3127 <1> imap2: ; 1: 3128 000049A9 66031E <1> add bx, [esi] ;; add free map size to si 3129 <1> ; add (r2)+,(sp) / get byte address of allocation bit 3130 000049AC 6683C304 <1> add bx, 4 3131 000049B0 01F3 <1> add ebx, esi 3132 <1> ; add (sp)+,r2 / ? 3133 <1> ;add ebx, 4 ;; inode map offset in superblock 3134 <1> ;; (2 + free map size + 2) 3135 <1> ; add $2,r2 / ? 3136 <1> 3137 <1> ; 11/02/2022 3138 000049B2 81C68B010000 <1> add esi, eofitab-1 ; last byte of the inode table in sb 3139 000049B8 39DE <1> cmp esi, ebx ; cf will be 1 3140 <1> ; if inode num overs inode count 3141 <1> 3142 <1> ; DL/DX (MQ) has a 1 in the calculated bit position 3143 <1> ; BX (R2) has byte address of the byte with allocation bit 3144 <1> 3145 <1> ; 11/02/2022 3146 <1> ; if ebx > last byte of the inode table --> cf = 1 3147 <1> ; (number of requested inode > inode count) 3148 <1> 3149 000049BA C3 <1> retn 3150 <1> ; rts r0 2119 %include 'u6.s' ; 31/05/2015 2120 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS6.INC 2121 <1> ; Last Modification: 19/07/2022 2122 <1> ; ---------------------------------------------------------------------------- 2123 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2124 <1> ; (v0.1 - Beginning: 11/07/2012) 2125 <1> ; 2126 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2127 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2128 <1> ; 2129 <1> ; 2130 <1> ; 2131 <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s 2132 <1> ; 2133 <1> ; **************************************************************************** 2134 <1> 2135 <1> readi: 2136 <1> ; 11/01/2022 2137 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2138 <1> ; 20/05/2015 2139 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2140 <1> ; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2141 <1> ; 2142 <1> ; Reads from an inode whose number in R1 2143 <1> ; 2144 <1> ; INPUTS -> 2145 <1> ; r1 - inode number 2146 <1> ; u.count - byte count user desires 2147 <1> ; u.base - points to user buffer 2148 <1> ; u.fofp - points to word with current file offset 2149 <1> ; OUTPUTS -> 2150 <1> ; u.count - cleared 2151 <1> ; u.nread - accumulates total bytes passed back 2152 <1> ; 2153 <1> ; ((AX = R1)) input/output 2154 <1> ; (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM) 2155 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -15/07/2022- 2156 <1> 2157 000049BB 31D2 <1> xor edx, edx ; 0 2158 000049BD 8915[14650000] <1> mov [u.nread], edx ; 0 2159 <1> ; clr u.nread / accumulates number of bytes transmitted 2160 000049C3 668915[51650000] <1> mov [u.pcount], dx ; 19/05/2015 2161 000049CA 3915[10650000] <1> cmp [u.count], edx ; 0 2162 <1> ; tst u.count / is number of bytes to be read greater than 0 2163 000049D0 7701 <1> ja short readi_1 ; 1f 2164 <1> ; bgt 1f / yes, branch 2165 000049D2 C3 <1> retn 2166 <1> ; rts r0 / no, nothing to read; return to caller 2167 <1> readi_1: ; 1: 2168 <1> ; mov r1,-(sp) / save i-number on stack 2169 000049D3 6683F828 <1> cmp ax, 40 2170 <1> ; cmp r1,$40. / want to read a special file 2171 <1> ; / (i-nodes 1,...,40 are for special files) 2172 <1> ;ja dskr 2173 <1> ; ble 1f / yes, branch 2174 <1> ; jmp dskr / no, jmp to dskr; 2175 <1> ; / read file with i-node number (r1) 2176 <1> ; / starting at byte ((u.fofp)), read in u.count bytes 2177 <1> ; 24/12/2021 2178 000049D7 7605 <1> jna short readi_3 2179 000049D9 E9CF000000 <1> jmp dskr 2180 <1> readi_3: 2181 <1> ; (20/05/2015) 2182 000049DE 50 <1> push eax ; because subroutines will jump to 'ret_' 2183 <1> ; 1: 2184 000049DF 0FB6D8 <1> movzx ebx, al 2185 <1> ; 11/01/2022 2186 000049E2 C1E302 <1> shl ebx, 2 2187 <1> ;shl bx, 2 2188 <1> ; asl r1 / multiply inode number by 2 2189 000049E5 81C3[E9490000] <1> add ebx, readi_2 - 4 2190 000049EB FF23 <1> jmp dword [ebx] 2191 <1> ; jmp *1f-2(r1) 2192 <1> readi_2: ; 1: 2193 000049ED [394A0000] <1> dd rtty ; tty, AX = 1 (runix) 2194 <1> ;rtty / tty; r1=2 2195 <1> ;rppt / ppt; r1=4 2196 000049F1 [894A0000] <1> dd rmem ; mem, AX = 2 (runix) 2197 <1> ;rmem / mem; r1=6 2198 <1> ;rrf0 / rf0 2199 <1> ;rrk0 / rk0 2200 <1> ;rtap / tap0 2201 <1> ;rtap / tap1 2202 <1> ;rtap / tap2 2203 <1> ;rtap / tap3 2204 <1> ;rtap / tap4 2205 <1> ;rtap / tap5 2206 <1> ;rtap / tap6 2207 <1> ;rtap / tap7 2208 000049F5 [73520000] <1> dd rfd ; fd0, AX = 3 (runix only) 2209 000049F9 [73520000] <1> dd rfd ; fd1, AX = 4 (runix only) 2210 000049FD [73520000] <1> dd rhd ; hd0, AX = 5 (runix only) 2211 00004A01 [73520000] <1> dd rhd ; hd1, AX = 6 (runix only) 2212 00004A05 [73520000] <1> dd rhd ; hd2, AX = 7 (runix only) 2213 00004A09 [73520000] <1> dd rhd ; hd3, AX = 8 (runix only) 2214 00004A0D [9E4A0000] <1> dd rlpr ; lpr, AX = 9 (invalid, write only device !?) 2215 00004A11 [854A0000] <1> dd rcvt ; tty0, AX = 10 (runix) 2216 <1> ;rcvt / tty0 2217 00004A15 [854A0000] <1> dd rcvt ; tty1, AX = 11 (runix) 2218 <1> ;rcvt / tty1 2219 00004A19 [854A0000] <1> dd rcvt ; tty2, AX = 12 (runix) 2220 <1> ;rcvt / tty2 2221 00004A1D [854A0000] <1> dd rcvt ; tty3, AX = 13 (runix) 2222 <1> ;rcvt / tty3 2223 00004A21 [854A0000] <1> dd rcvt ; tty4, AX = 14 (runix) 2224 <1> ;rcvt / tty4 2225 00004A25 [854A0000] <1> dd rcvt ; tty5, AX = 15 (runix) 2226 <1> ;rcvt / tty5 2227 00004A29 [854A0000] <1> dd rcvt ; tty6, AX = 16 (runix) 2228 <1> ;rcvt / tty6 2229 00004A2D [854A0000] <1> dd rcvt ; tty7, AX = 17 (runix) 2230 <1> ;rcvt / tty7 2231 00004A31 [854A0000] <1> dd rcvt ; COM1, AX = 18 (runix only) 2232 <1> ;rcrd / crd 2233 00004A35 [854A0000] <1> dd rcvt ; COM2, AX = 19 (runix only) 2234 <1> 2235 <1> rtty: ; / read from console tty 2236 <1> ; 11/01/2022 2237 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2238 <1> ; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1) 2239 <1> ; (Only 1 byte is read, by ignoring byte count!) 2240 <1> ; WHAT FOR: Every character from Keyboard input 2241 <1> ; must be written immediate on video page (screen) 2242 <1> ; when it is required. 2243 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2244 <1> ; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1) 2245 <1> ; 2246 <1> ; Console tty buffer is PC keyboard buffer 2247 <1> ; and keyboard-keystroke handling is different than original 2248 <1> ; unix (PDP-11) here. TTY/Keyboard procedures here are changed 2249 <1> ; according to IBM PC compatible ROM BIOS keyboard functions. 2250 <1> ; 2251 <1> ; 06/12/2013 2252 00004A39 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 2253 00004A40 8A83[43620000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2254 <1> rttys: 2255 <1> ; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of 2256 <1> ; / of the control and status block 2257 <1> ; tst 2(r5) / for the console tty; this word points to the console 2258 <1> ; / tty buffer 2259 <1> ; 28/07/2013 2260 00004A46 A2[40650000] <1> mov [u.ttyn], al 2261 <1> ; 13/01/2014 2262 00004A4B FEC0 <1> inc al 2263 00004A4D A2[1C650000] <1> mov [u.ttyp], al ; tty number + 1 2264 <1> rtty_nc: ; 01/02/2014 2265 <1> ; 29/09/2013 2266 <1> ;mov ecx, 10 2267 <1> ; 11/01/2022 2268 00004A52 29C9 <1> sub ecx, ecx 2269 00004A54 B10A <1> mov cl, 10 2270 <1> rtty_1: ; 01/02/2014 2271 <1> ;push cx ; 29/09/2013 2272 <1> ; 24/12/2021 2273 00004A56 51 <1> push ecx 2274 <1> ; byte [u.ttyn] = tty number (0 to 9) 2275 00004A57 B001 <1> mov al, 1 2276 00004A59 E8200B0000 <1> call getc 2277 <1> ; 24/12/2021 2278 00004A5E 59 <1> pop ecx 2279 <1> ;pop cx ; 29/09/2013 2280 00004A5F 7516 <1> jnz short rtty_2 2281 <1> ; bne 1f / 2nd word of console tty buffer contains number 2282 <1> ; / of chars. Is this number non-zero? 2283 00004A61 E20D <1> loop rtty_idle ; 01/02/2014 2284 <1> ; 05/10/2013 2285 00004A63 8A25[40650000] <1> mov ah, [u.ttyn] 2286 <1> ; 29/09/2013 2287 00004A69 E898FBFFFF <1> call sleep 2288 <1> ; jsr r0,canon; ttych / if 0, call 'canon' to get a line 2289 <1> ; / (120 chars.) 2290 <1> ;byte [u.ttyn] = tty number (0 to 9) 2291 00004A6E EBE2 <1> jmp short rtty_nc ; 01/02/2014 2292 <1> 2293 <1> rtty_idle: 2294 <1> ; 29/07/2013 2295 00004A70 E804FBFFFF <1> call idle 2296 00004A75 EBDF <1> jmp short rtty_1 ; 01/02/2014 2297 <1> ;1: 2298 <1> ; tst 2(r5) / is the number of characters zero 2299 <1> ; beq ret1 / yes, return to caller via 'ret1' 2300 <1> ; movb *4(r5),r1 / no, put character in r1 2301 <1> ; inc 4(r5) / 3rd word of console tty buffer points to byte which 2302 <1> ; / contains the next char. 2303 <1> ; dec 2(r5) / decrement the character count 2304 <1> rtty_2: 2305 00004A77 30C0 <1> xor al, al 2306 00004A79 E8000B0000 <1> call getc 2307 00004A7E E896000000 <1> call passc 2308 <1> ; jsr r0,passc / move the character to core (user) 2309 <1> ;; 17/10/2015 - 16/07/2015 2310 <1> ; 19/06/2014 2311 <1> ;;jnz short rtty_nc 2312 00004A83 58 <1> pop eax ; (20/05/2015) 2313 00004A84 C3 <1> retn 2314 <1> ;ret1: 2315 <1> ; jmp ret / return to caller via 'ret' 2316 <1> 2317 <1> rcvt: ; < receive/read character from tty > 2318 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2319 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2320 <1> ; 2321 <1> ; Retro UNIX 8086 v1 modification ! 2322 <1> ; 2323 <1> ; In original UNIX v1, 'rcvt' routine 2324 <1> ; (exactly different than this one) 2325 <1> ; was in 'u9.s' file. 2326 <1> ; 2327 00004A85 2C0A <1> sub al, 10 2328 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 2329 <1> ; 16/07/2013 2330 <1> ; 21/05/2013 2331 00004A87 EBBD <1> jmp short rttys 2332 <1> 2333 <1> ;rppt: / read paper tape 2334 <1> ; jsr r0,pptic / gets next character in clist for ppt input and 2335 <1> ; / places 2336 <1> ; br ret / it in r1; if there 1s no problem with reader, it 2337 <1> ; / also enables read bit in prs 2338 <1> ; jsr r0,passc / place character in users buffer area 2339 <1> ; br rppt 2340 <1> 2341 <1> rmem: ; / transfer characters from memory to a user area of core 2342 <1> ; 17/10/2015 2343 <1> ; 11/06/2015 2344 <1> ; 24/05/2015 2345 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2346 <1> ; 2347 00004A89 8B35[FC640000] <1> mov esi, [u.fofp] 2348 <1> rmem_1: 2349 00004A8F 8B1E <1> mov ebx, [esi] 2350 <1> ; mov *u.fofp,r1 / save file offset which points to the char 2351 <1> ; / to be transferred to user 2352 00004A91 FF06 <1> inc dword [esi] ; 17/10/2015 2353 <1> ; inc *u.fofp / increment file offset to point to 'next' 2354 <1> ; / char in memory file 2355 00004A93 8A03 <1> mov al, [ebx] 2356 <1> ; movb (r1),r1 / get character from memory file, 2357 <1> ; / put it in r1 2358 00004A95 E87F000000 <1> call passc ; jsr r0,passc / move this character to 2359 <1> ; / the next byte of the users core area 2360 <1> ; br rmem / continue 2361 00004A9A 75F3 <1> jnz short rmem_1 2362 <1> ret_: 2363 00004A9C 58 <1> pop eax ; 09/06/2015 2364 00004A9D C3 <1> retn 2365 <1> 2366 <1> rlpr: 2367 <1> ;1: 2368 <1> ;rcrd: 2369 00004A9E C705[41650000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 2369 00004AA6 0000 <1> 2370 00004AA8 E91EE6FFFF <1> jmp error 2371 <1> ;jmp error / see 'error' routine 2372 <1> 2373 <1> dskr: 2374 <1> ; 19/07/2022 2375 <1> ; 12/10/2015 2376 <1> ; 21/08/2015 2377 <1> ; 25/07/2015 2378 <1> ; 10/07/2015 2379 <1> ; 16/06/2015 2380 <1> ; 31/05/2015 2381 <1> ; 24/05/2015 (Retro UNIX 386 v1 - Beginning) 2382 <1> ; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2383 <1> dskr_0: 2384 00004AAD 50 <1> push eax 2385 <1> ; mov (sp),r1 / i-number in r1 2386 <1> ; AX = i-number 2387 00004AAE E834FDFFFF <1> call iget 2388 <1> ; jsr r0,iget / get i-node (r1) into i-node section of core 2389 00004AB3 0FB715[E8610000] <1> movzx edx, word [i.size] ; 16/06/2015 2390 <1> ; mov i.size,r2 / file size in bytes in r2 2391 00004ABA 8B1D[FC640000] <1> mov ebx, [u.fofp] 2392 00004AC0 2B13 <1> sub edx, [ebx] 2393 <1> ; sub *u.fofp,r2 / subtract file offset 2394 <1> ; 12/10/2015 2395 <1> ; jna short ret_ 2396 <1> ; blos ret 2397 00004AC2 7709 <1> ja short dskr_1 2398 <1> ; 2399 <1> dskr_retn: ; 12/10/2015 2400 00004AC4 58 <1> pop eax 2401 00004AC5 C605[53650000]00 <1> mov byte [u.kcall], 0 2402 00004ACC C3 <1> retn 2403 <1> dskr_1: 2404 00004ACD 3B15[10650000] <1> cmp edx, [u.count] 2405 <1> ; cmp r2,u.count / are enough bytes left in file 2406 <1> ; / to carry out read 2407 00004AD3 7306 <1> jnb short dskr_2 2408 <1> ; bhis 1f 2409 00004AD5 8915[10650000] <1> mov [u.count], edx 2410 <1> ; mov r2,u.count / no, just read to end of file 2411 <1> dskr_2: ; 1: 2412 <1> ; AX = i-number 2413 00004ADB E89EFBFFFF <1> call mget 2414 <1> ; jsr r0,mget / returns physical block number of block 2415 <1> ; / in file where offset points 2416 <1> ; EAX = physical block number 2417 00004AE0 E8CD080000 <1> call dskrd 2418 <1> ; jsr r0,dskrd / read in block, r5 points to 2419 <1> ; / 1st word of data in buffer 2420 <1> ; 09/06/2015 2421 00004AE5 803D[53650000]00 <1> cmp byte [u.kcall], 0 ; the caller is 'namei' sign (=1) 2422 00004AEC 770F <1> ja short dskr_4 ; zf=0 -> the caller is 'namei' 2423 00004AEE 66833D[51650000]00 <1> cmp word [u.pcount], 0 2424 00004AF6 7705 <1> ja short dskr_4 2425 <1> dskr_3: 2426 <1> ; [u.base] = virtual address to transfer (as destination address) 2427 00004AF8 E857000000 <1> call trans_addr_w ; translate virtual address to physical (w) 2428 <1> dskr_4: 2429 <1> ; EBX (r5) = system (I/O) buffer address -physical- 2430 00004AFD E83D030000 <1> call sioreg 2431 <1> ; jsr r0,sioreg 2432 <1> 2433 <1> ; 19/07/2022 2434 <1> ;xchg esi, edi 2435 <1> 2436 <1> ; 19/07/2022 2437 <1> ; EDX = user data offset (previous value of [u.pbase]) 2438 <1> ; ESI = pointer to file offset 2439 <1> ; EDI = system (I/O) buffer offset 2440 <1> ; ECX = byte count 2441 <1> ; EBX = system buffer (data) address 2442 <1> ; EAX = remain bytes after byte count within page frame 2443 <1> 2444 00004B02 010E <1> add [esi], ecx 2445 <1> ; new file offset (old offset + byte count) 2446 <1> ; 2447 00004B04 89FE <1> mov esi, edi ; sector (I/O) buffer offset 2448 00004B06 89D7 <1> mov edi, edx 2449 <1> 2450 <1> ; EDI = file (user data) offset 2451 <1> ; ESI = sector (I/O) buffer offset 2452 <1> ; ECX = byte count 2453 00004B08 F3A4 <1> rep movsb 2454 <1> ; movb (r2)+,(r1)+ / move data from buffer into working core 2455 <1> ; / starting at u.base 2456 <1> ; dec r3 2457 <1> ; bne 2b / branch until proper number of bytes are transferred 2458 <1> ; 25/07/2015 2459 <1> ; eax = remain bytes in buffer 2460 <1> ; (check if remain bytes in the buffer > [u.pcount]) 2461 00004B0A 09C0 <1> or eax, eax 2462 00004B0C 75EA <1> jnz short dskr_3 ; (page end before system buffer end!) 2463 <1> ; 03/08/2013 2464 <1> ;pop eax 2465 00004B0E 390D[10650000] <1> cmp [u.count], ecx ; 0 2466 <1> ; tst u.count / all bytes read off disk 2467 <1> ; bne dskr 2468 <1> ; br ret 2469 <1> ;ja short dskr_0 2470 <1> ;mov [u.kcall], cl ; 0 ; 09/06/2015 2471 <1> ;retn 2472 <1> ; 12/10/2015 2473 00004B14 76AE <1> jna short dskr_retn 2474 00004B16 58 <1> pop eax ; (i-node number) 2475 00004B17 EB94 <1> jmp short dskr_0 2476 <1> 2477 <1> passc: 2478 <1> ; 18/10/2015 2479 <1> ; 10/07/2015 2480 <1> ; 01/07/2015 2481 <1> ; 08/06/2015 2482 <1> ; 04/06/2015 2483 <1> ; 20/05/2015 2484 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2485 <1> ; 2486 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 2487 <1> ; to physical address 2488 00004B19 66833D[51650000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 2489 <1> ; 1-4095 --> use previous physical base address 2490 <1> ; in [u.pbase] 2491 00004B21 7705 <1> ja short passc_3 2492 <1> ; 08/06/2015 - 10/07/2015 2493 00004B23 E82C000000 <1> call trans_addr_w 2494 <1> passc_3: 2495 <1> ; 19/05/2015 2496 00004B28 66FF0D[51650000] <1> dec word [u.pcount] 2497 <1> ; 2498 00004B2F 8B1D[4D650000] <1> mov ebx, [u.pbase] 2499 00004B35 8803 <1> mov [ebx], al 2500 <1> ; movb r1,*u.base / move a character to the next byte of the 2501 <1> ; / users buffer 2502 00004B37 FF05[0C650000] <1> inc dword [u.base] 2503 <1> ; inc u.base / increment the pointer to point to 2504 <1> ; / the next byte in users buffer 2505 00004B3D FF05[4D650000] <1> inc dword [u.pbase] ; 04/06/2015 2506 00004B43 FF05[14650000] <1> inc dword [u.nread] 2507 <1> ; inc u.nread / increment the number of bytes read 2508 00004B49 FF0D[10650000] <1> dec dword [u.count] 2509 <1> ; dec u.count / decrement the number of bytes to be read 2510 <1> ; bne 1f / any more bytes to read?; yes, branch 2511 00004B4F C3 <1> retn 2512 <1> ; mov (sp)+,r0 / no, do a non-local return to the caller of 2513 <1> ; / 'readi' by: 2514 <1> ;/ (1) pop the return address off the stack into r0 2515 <1> ; mov (sp)+,r1 / (2) pop the i-number off the stack into r1 2516 <1> ;1: 2517 <1> ; clr *$ps / clear processor status 2518 <1> ; rts r0 / return to address currently on top of stack 2519 <1> 2520 <1> trans_addr_r: 2521 <1> ; Translate virtual address to physical address 2522 <1> ; for reading from user's memory space 2523 <1> ; (Retro UNIX 386 v1 feature only !) 2524 <1> ; 18/10/2015 2525 <1> ; 10/07/2015 2526 <1> ; 09/06/2015 2527 <1> ; 08/06/2015 2528 <1> ; 04/06/2015 2529 <1> ; 2530 <1> ; 18/10/2015 2531 00004B50 31D2 <1> xor edx, edx ; 0 (read access sign) 2532 00004B52 EB04 <1> jmp short trans_addr_rw 2533 <1> 2534 <1> ;push eax 2535 <1> ;push ebx 2536 <1> ;mov ebx, [u.base] 2537 <1> ;call get_physical_addr ; get physical address 2538 <1> ;;jnc short cpass_0 2539 <1> ;jnc short passc_1 2540 <1> ;mov [u.error], eax 2541 <1> ;;pop ebx 2542 <1> ;;pop eax 2543 <1> ;jmp error 2544 <1> ;cpass_0: 2545 <1> ; 18/10/2015 2546 <1> ; 20/05/2015 2547 <1> ;mov [u.pbase], eax ; physical address 2548 <1> ;mov [u.pcount], cx ; remain byte count in page (1-4096) 2549 <1> ;pop ebx 2550 <1> ;pop eax 2551 <1> ;retn ; 08/06/2015 2552 <1> 2553 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2554 <1> trans_addr_w: 2555 <1> ; 31/12/2021 2556 <1> ; Translate virtual address to physical address 2557 <1> ; for writing to user's memory space 2558 <1> ; (Retro UNIX 386 v1 feature only !) 2559 <1> ; 18/10/2015 2560 <1> ; 29/07/2015 2561 <1> ; 10/07/2015 2562 <1> ; 09/06/2015 2563 <1> ; 08/06/2015 2564 <1> ; 04/06/2015 (passc) 2565 <1> ; 2566 <1> ; 18/10/2015 2567 00004B54 29D2 <1> sub edx, edx 2568 00004B56 FEC2 <1> inc dl ; 1 (write access sign) 2569 <1> trans_addr_rw: 2570 00004B58 50 <1> push eax 2571 00004B59 53 <1> push ebx 2572 <1> ; 18/10/2015 2573 00004B5A 52 <1> push edx ; r/w sign (in DL) 2574 <1> ; 2575 00004B5B 8B1D[0C650000] <1> mov ebx, [u.base] 2576 00004B61 E843DCFFFF <1> call get_physical_addr ; get physical address 2577 00004B66 730A <1> jnc short passc_0 2578 00004B68 A3[41650000] <1> mov [u.error], eax 2579 <1> ;pop edx 2580 <1> ;pop ebx 2581 <1> ;pop eax 2582 00004B6D E959E5FFFF <1> jmp error 2583 <1> passc_0: 2584 00004B72 F6C202 <1> test dl, PTE_A_WRITE ; writable page ; 18/10/2015 2585 00004B75 5A <1> pop edx ; 18/10/2015 2586 00004B76 7517 <1> jnz short passc_1 2587 <1> ; 18/10/2015 2588 00004B78 20D2 <1> and dl, dl 2589 00004B7A 7413 <1> jz short passc_1 2590 <1> ; 20/05/2015 2591 <1> ; read only (duplicated) page -must be copied to a new page- 2592 <1> ; EBX = linear address 2593 00004B7C 51 <1> push ecx 2594 00004B7D 53 <1> push ebx ; * ; 31/12/2021 (BugFix) 2595 00004B7E E897DBFFFF <1> call copy_page 2596 00004B83 5B <1> pop ebx ; * ; 31/12/2021 (BugFix) 2597 00004B84 59 <1> pop ecx 2598 00004B85 7217 <1> jc short passc_2 2599 <1> ; 24/12/2021 2600 <1> ;push eax ; physical address of the new/allocated page 2601 <1> ;call add_to_swap_queue 2602 <1> ;pop eax 2603 <1> ; 18/10/2015 2604 00004B87 81E3FF0F0000 <1> and ebx, PAGE_OFF ; 0FFFh 2605 <1> ;mov ecx, PAGE_SIZE 2606 <1> ;sub ecx, ebx 2607 00004B8D 01D8 <1> add eax, ebx 2608 <1> passc_1: 2609 <1> ; 18/10/2015 2610 <1> ; 20/05/2015 2611 00004B8F A3[4D650000] <1> mov [u.pbase], eax ; physical address 2612 00004B94 66890D[51650000] <1> mov [u.pcount], cx ; remain byte count in page (1-4096) 2613 00004B9B 5B <1> pop ebx 2614 00004B9C 58 <1> pop eax 2615 00004B9D C3 <1> retn ; 08/06/2015 2616 <1> passc_2: 2617 00004B9E C705[41650000]0400- <1> mov dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error 2617 00004BA6 0000 <1> 2618 <1> ;pop ebx 2619 <1> ;pop eax 2620 00004BA8 E91EE5FFFF <1> jmp error 2621 <1> 2622 <1> writei: 2623 <1> ; 13/06/2022 2624 <1> ; 03/02/2022 2625 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2626 <1> ; 20/05/2015 2627 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2628 <1> ; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 2629 <1> ; 2630 <1> ; Write data to file with inode number in R1 2631 <1> ; 2632 <1> ; INPUTS -> 2633 <1> ; r1 - inode number 2634 <1> ; u.count - byte count to be written 2635 <1> ; u.base - points to user buffer 2636 <1> ; u.fofp - points to word with current file offset 2637 <1> ; OUTPUTS -> 2638 <1> ; u.count - cleared 2639 <1> ; u.nread - accumulates total bytes passed back 2640 <1> ; ((AX = R1)) 2641 <1> ; (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM) 2642 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) -15/07/2022- 2643 <1> 2644 00004BAD 31C9 <1> xor ecx, ecx 2645 00004BAF 890D[14650000] <1> mov [u.nread], ecx ; 0 2646 <1> ; clr u.nread / clear the number of bytes transmitted during 2647 <1> ; / read or write calls 2648 00004BB5 66890D[51650000] <1> mov [u.pcount], cx ; 19/05/2015 2649 00004BBC 390D[10650000] <1> cmp [u.count], ecx 2650 <1> ; ; tst u.count / test the byte count specified by the user 2651 00004BC2 770B <1> ja short writei_1 ; 1f 2652 <1> ; bgt 1f / any bytes to output; yes, branch 2653 <1> 2654 <1> ; 13/06/2022 - ('get/read LPT printer status' modification) 2655 00004BC4 83F810 <1> cmp eax, 16 ; LPR_INODE ; lpt (parallel port printer) ? 2656 00004BC7 7505 <1> jne short writei_0 2657 00004BC9 E924010000 <1> jmp lpr_stat ; get/read line status 2658 <1> writei_0: 2659 00004BCE C3 <1> retn 2660 <1> ; ; rts r0 / no, return - no writing to do 2661 <1> writei_1: ;1: 2662 <1> ; mov r1 ,-(sp) / save the i-node number on the stack 2663 00004BCF 6683F828 <1> cmp ax, 40 2664 <1> ; cmp r1,$40. 2665 <1> ; / does the i-node number indicate a special file? 2666 <1> ;ja dskw 2667 <1> ; bgt dskw / no, branch to standard file output 2668 <1> ; 24/12/2021 2669 00004BD3 7605 <1> jna short writei_3 2670 00004BD5 E958010000 <1> jmp dskw 2671 <1> writei_3: 2672 <1> ; (20/05/2015) 2673 00004BDA 50 <1> push eax ; because subroutines will jump to 'wret' 2674 00004BDB 0FB6D8 <1> movzx ebx, al 2675 <1> ; 03/02/2022 2676 00004BDE C1E302 <1> shl ebx, 2 2677 <1> ;shl bx, 2 2678 <1> ; asl r1 / yes, calculate the index into the special file 2679 00004BE1 81C3[E54B0000] <1> add ebx, writei_2 - 4 2680 00004BE7 FF23 <1> jmp dword [ebx] 2681 <1> ; jmp *1f-2(r1) 2682 <1> ; / jump table and jump to the appropriate routine 2683 <1> writei_2: ;1: 2684 00004BE9 [354C0000] <1> dd wtty ; tty, AX = 1 (runix) 2685 <1> ;wtty / tty; r1=2 2686 <1> ;wppt / ppt; r1=4 2687 00004BED [884C0000] <1> dd wmem ; mem, AX = 2 (runix) 2688 <1> ;wmem / mem; r1=6 2689 <1> ;wrf0 / rf0 2690 <1> ;wrk0 / rk0 2691 <1> ;wtap / tap0 2692 <1> ;wtap / tap1 2693 <1> ;wtap / tap2 2694 <1> ;wtap / tap3 2695 <1> ;wtap / tap4 2696 <1> ;wtap / tap5 2697 <1> ;wtap / tap6 2698 <1> ;wtap / tap7 2699 00004BF1 [E8520000] <1> dd wfd ; fd0, AX = 3 (runix only) 2700 00004BF5 [E8520000] <1> dd wfd ; fd1, AX = 4 (runix only) 2701 00004BF9 [E8520000] <1> dd whd ; hd0, AX = 5 (runix only) 2702 00004BFD [E8520000] <1> dd whd ; hd1, AX = 6 (runix only) 2703 00004C01 [E8520000] <1> dd whd ; hd2, AX = 7 (runix only) 2704 00004C05 [E8520000] <1> dd whd ; hd3, AX = 8 (runix only) 2705 00004C09 [B84C0000] <1> dd wlpr ; lpr, AX = 9 (runix) 2706 00004C0D [824C0000] <1> dd xmtt ; tty0, AX = 10 (runix) 2707 <1> ;xmtt / tty0 2708 00004C11 [824C0000] <1> dd xmtt ; tty1, AX = 11 (runix) 2709 <1> ;xmtt / tty1 2710 00004C15 [824C0000] <1> dd xmtt ; tty2, AX = 12 (runix) 2711 <1> ;xmtt / tty2 2712 00004C19 [824C0000] <1> dd xmtt ; tty3, AX = 13 (runix) 2713 <1> ;xmtt / tty3 2714 00004C1D [824C0000] <1> dd xmtt ; tty4, AX = 14 (runix) 2715 <1> ;xmtt / tty4 2716 00004C21 [824C0000] <1> dd xmtt ; tty5, AX = 15 (runix) 2717 <1> ;xmtt / tty5 2718 00004C25 [824C0000] <1> dd xmtt ; tty6, AX = 16 (runix) 2719 <1> ;xmtt / tty6 2720 00004C29 [824C0000] <1> dd xmtt ; tty7, AX = 17 (runix) 2721 <1> ;xmtt / tty7 2722 00004C2D [824C0000] <1> dd xmtt ; COM1, AX = 18 (runix only) 2723 <1> ; / wlpr / lpr 2724 00004C31 [824C0000] <1> dd xmtt ; COM2, AX = 19 (runix only) 2725 <1> 2726 <1> wtty: ; write to console tty (write to screen) 2727 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2728 <1> ; 18/11/2015 2729 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2730 <1> ; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1) 2731 <1> ; 2732 <1> ; Console tty output is on current video page 2733 <1> ; Console tty character output procedure is changed here 2734 <1> ; acconding to IBM PC compatible ROM BIOS video (text mode) functions. 2735 <1> ; 2736 00004C35 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 2737 00004C3C 8AA3[43620000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 2738 00004C42 88E0 <1> mov al, ah ; 07/07/2014 2739 <1> wttys: 2740 <1> ; 10/10/2013 2741 00004C44 8825[40650000] <1> mov [u.ttyn], ah 2742 <1> ; 13/01/2014 2743 00004C4A FEC0 <1> inc al 2744 00004C4C A2[1D650000] <1> mov [u.ttyp+1], al ; tty number + 1 2745 <1> wtty_nc: ; 15/05/2013 2746 <1> ; AH = [u.ttyn] = tty number ; 28/07/2013 2747 00004C51 E889010000 <1> call cpass 2748 <1> ; jsr r0,cpass / get next character from user buffer area; if 2749 <1> ; / none go to return address in syswrite 2750 <1> ; tst r1 / is character = null 2751 <1> ; beq wtty / yes, get next character 2752 <1> ; 10/10/2013 2753 00004C56 7428 <1> jz short wret 2754 <1> ;1 : 2755 <1> ;mov $240,*$ps / no, set processor priority to five 2756 <1> ;cmpb cc+1,$20. / is character count for console tty greater 2757 <1> ; / than 20 2758 <1> ;bhis 2f / yes; branch to put process to sleep 2759 <1> ; 27/06/2014 2760 <1> wtty_1: 2761 <1> ; AH = tty number 2762 <1> ; AL = ASCII code of the character 2763 <1> ; 15/04/2014 2764 <1> ;push ax 2765 <1> ; 24/12/2021 2766 00004C58 50 <1> push eax 2767 00004C59 E88E090000 <1> call putc ; 14/05/2013 2768 00004C5E 731D <1> jnc short wtty_2 2769 <1> ; 18/11/2015 2770 00004C60 E814F9FFFF <1> call idle 2771 <1> ;mov ax, [esp] 2772 <1> ; 24/12/2021 2773 00004C65 8B0424 <1> mov eax, [esp] 2774 00004C68 E87F090000 <1> call putc 2775 00004C6D 730E <1> jnc short wtty_2 2776 <1> ; 02/06/2014 2777 00004C6F 8A25[40650000] <1> mov ah, [u.ttyn] 2778 00004C75 E88CF9FFFF <1> call sleep 2779 <1> ;pop ax 2780 <1> ; 24/12/2021 2781 00004C7A 58 <1> pop eax 2782 00004C7B EBDB <1> jmp short wtty_1 2783 <1> ; jc error ; 15/05/2013 (COM1 or COM2 serial port error) 2784 <1> ; jsr r0,putc; 1 / find place in freelist to assign to 2785 <1> ; / console tty and 2786 <1> ; br 2f / place character in list; if none available 2787 <1> ; / branch to put process to sleep 2788 <1> ; jsr r0,startty / attempt to output character on tty 2789 <1> wtty_2: 2790 <1> ; 15/04/2014 2791 <1> ;pop ax 2792 <1> ; 24/12/2021 2793 00004C7D 58 <1> pop eax 2794 00004C7E EBD1 <1> jmp short wtty_nc 2795 <1> ; br wtty 2796 <1> wret: ; 10/10/2013 (20/05/2015) 2797 00004C80 58 <1> pop eax 2798 00004C81 C3 <1> retn 2799 <1> ;2: 2800 <1> ;mov r1,-(sp) / place character on stack 2801 <1> ;jsr r0,sleep; 1 / put process to sleep 2802 <1> ;mov (sp)+,r1 / remove character from stack 2803 <1> ;br 1b / try again to place character in clist and output 2804 <1> 2805 <1> xmtt: ; < send/write character to tty > 2806 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2807 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 2808 <1> ; 2809 <1> ; Retro UNIX 8086 v1 modification ! 2810 <1> ; 2811 <1> ; In original UNIX v1, 'xmtt' routine 2812 <1> ; (exactly different than this one) 2813 <1> ; was in 'u9.s' file. 2814 <1> ; 2815 00004C82 2C0A <1> sub al, 10 2816 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 2817 <1> ; 10/10/2013 2818 00004C84 88C4 <1> mov ah, al 2819 <1> ; 28/07/2013 2820 00004C86 EBBC <1> jmp short wttys 2821 <1> 2822 <1> ;wppt: 2823 <1> ; jsr r0,cpass / get next character from user buffer area, 2824 <1> ; / if none return to writei's calling routine 2825 <1> ; jsr r0,pptoc / output character on ppt 2826 <1> ; br wppt 2827 <1> 2828 <1> wmem: ; / transfer characters from a user area of core to memory file 2829 <1> ; 17/10/2015 2830 <1> ; 11/06/2015 2831 <1> ; 24/05/2015 2832 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 2833 <1> ; 2834 00004C88 813D[F1060000]- <1> cmp dword [x_timer], clock ; multi tasking clock/timer 2834 00004C8E [9C450000] <1> 2835 00004C92 7415 <1> je short wmem_acc_err 2836 <1> ; 2837 00004C94 8B35[FC640000] <1> mov esi, [u.fofp] 2838 <1> wmem_1: 2839 00004C9A E840010000 <1> call cpass 2840 <1> ; jsr r0,cpass / get next character from users area of 2841 <1> ; / core and put it in r1 2842 <1> ; mov r1,-(sp) / put character on the stack 2843 <1> ; 20/09/2013 2844 00004C9F 74DF <1> jz short wret ; wmem_2 2845 00004CA1 8B1E <1> mov ebx, [esi] 2846 <1> ; mov *u.fofp,r1 / save file offset in r1 2847 00004CA3 FF06 <1> inc dword [esi] ; 17/10/2015 2848 <1> ; inc *u.fofp / increment file offset to point to next 2849 <1> ; / available location in file 2850 00004CA5 8803 <1> mov [ebx], al 2851 <1> ; movb (sp)+,(r1) / pop char off stack, put in memory loc 2852 <1> ; / assigned to it 2853 00004CA7 EBF1 <1> jmp short wmem_1 2854 <1> ; br wmem / continue 2855 <1> ;1: 2856 <1> ;jmp error / ? 2857 <1> ;wmem_2: 2858 <1> ; ; 20/09/2013 2859 <1> ; pop ax 2860 <1> ; retn 2861 <1> 2862 <1> wmem_acc_err: 2863 00004CA9 C705[41650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2863 00004CB1 0000 <1> 2864 00004CB3 E913E4FFFF <1> jmp error 2865 <1> 2866 <1> ;wlpr: 2867 <1> ; 13/06/2022 2868 <1> ;mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 2869 <1> ;jmp error ; ... Printing procedure will be located here ... 2870 <1> ;/ jsr r0,cpass 2871 <1> ;/ cmp r0,$'a 2872 <1> ;/ blo 1f 2873 <1> ;/ cmp r1,$'z 2874 <1> ;/ bhi 1f 2875 <1> ;/ sub $40,r1 2876 <1> ;/1: 2877 <1> ;/ jsr r0,lptoc 2878 <1> ;/ br wlpr 2879 <1> ; br rmem / continue 2880 <1> 2881 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 - PRINTER BIOS (Functions) 2882 <1> 2883 <1> ;; Ref: MSDOS 3.3 (Retro DOS 3.2) Printer driver code (MSLPT.ASM) 2884 <1> ;; MSLPT.ASM - MSDOS 3.3 - 24/07/1987 2885 <1> ;; 23/03/2018 - Retro DOS v2.0 2886 <1> ;; RETRODOS32.ASM - 03/08/2019 (Retro DOS v3.2) 2887 <1> 2888 <1> ; IBM ROMBIOS (INT 17h) STATUS BITS 2889 <1> 2890 <1> NOTBUSYSTATUS equ 10000000b ; NOT BUSY 2891 <1> ACKSTATUS equ 01000000b ; ACKNOWLEDGE (FOR WHAT?) 2892 <1> NOPAPERSTATUS equ 00100000b ; NO MORE PAPER 2893 <1> SELECTEDSTATUS equ 00010000b ; THE PRINTER SAID IT WAS SELECTED 2894 <1> IOERRSTATUS equ 00001000b ; SOME KIND ERROR 2895 <1> RESERVED equ 00000110b ; NOPS 2896 <1> TIMEOUTSTATUS equ 00000001b ; TIME OUT. 2897 <1> 2898 <1> ;---------------------------------------------------------------- 2899 <1> ; : 2900 <1> ; WRITE TO PRINTER DEVICE : 2901 <1> ; : 2902 <1> ; CX has count of bytes to be printed : 2903 <1> ; ES:DI point to source buffer contains characters : 2904 <1> ; AuxNum (in msbio.asm) has printer number : 2905 <1> ; : 2906 <1> ;---------------------------------------------------------------- 2907 <1> 2908 <1> wlpr: 2909 <1> ; 15/07/2022 2910 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 2911 <1> PRN$WRIT: 2912 <1> ; INPUT: 2913 <1> ; [u.count] = count of characters to be printed 2914 <1> ; [u.base] = buffer address in user's memory space 2915 <1> ; 2916 <1> ; (if ECX = 0, printer status will be returned) 2917 <1> 2918 <1> ;xor ebx, ebx 2919 <1> PRN$LOOP: 2920 00004CB8 E822010000 <1> call cpass ; Get a character into AL 2921 00004CBD 7431 <1> jz short pr_exit 2922 <1> ; 2923 00004CBF B302 <1> mov bl, 2 ; retry count 2924 <1> PRN$OUT: 2925 <1> ; al = character which will be printed 2926 00004CC1 30E4 <1> xor ah, ah ; 0 ; PRINT THE CHARACTER IN (AL) 2927 00004CC3 E850000000 <1> call PRNOP 2928 00004CC8 74EE <1> jz short PRN$LOOP ; if error, try to print again 2929 <1> PrRetry: 2930 <1> ; al = character 2931 00004CCA FECB <1> dec bl 2932 00004CCC 75F3 <1> jnz short PRN$OUT 2933 <1> pr_err_exit: 2934 00004CCE 0FB6C0 <1> movzx eax, al 2935 00004CD1 A3[41650000] <1> mov [u.error], eax 2936 00004CD6 A3[EC640000] <1> mov [u.r0], eax ; error code in AL 2937 <1> ;mov ebp, [u.sp] 2938 00004CDB 8B1D[E4640000] <1> mov ebx, [u.sp] ; 15/07/2022 2939 <1> ; Kernel stack at the beginning of sys call 2940 00004CE1 8B15[14650000] <1> mov edx, [u.nread] 2941 00004CE7 4A <1> dec edx ; last char failed 2942 <1> ;mov [ebp+20], edx ; count of printed characters in edx 2943 00004CE8 895314 <1> mov [ebx+20], edx ; 15/07/2022 2944 00004CEB E9DBE3FFFF <1> jmp error 2945 <1> pr_exit: 2946 00004CF0 58 <1> pop eax ; inode number 2947 <1> 2948 <1> ;mov eax, [u.nread] 2949 <1> ;mov [u.r0], eax ; count of printed chacters 2950 <1> ;jmp sysret 2951 00004CF1 C3 <1> retn ; return from writei to syswrite (rw0) 2952 <1> 2953 <1> ; 13/06/2022 2954 <1> 2955 <1> ;---------------------------------------------------------------- 2956 <1> ; : 2957 <1> ; PRINTER STATUS ROUTINE : 2958 <1> ; : 2959 <1> ;---------------------------------------------------------------- 2960 <1> ; 2961 <1> 2962 <1> lpr_stat: 2963 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 2964 <1> PRN$STAT: 2965 00004CF2 E81F000000 <1> call PRNSTAT ; get the status 2966 00004CF7 750E <1> jnz short prn_stat_retn 2967 <1> ; if error jump to error routine 2968 <1> ;mov al, 9 ; AGAIN, ASSUME OUT OF PAPER... 2969 00004CF9 B01F <1> mov al, ERR_PRN_PAPER 2970 00004CFB F6C420 <1> test ah, NOPAPERSTATUS 2971 00004CFE 7507 <1> jnz short prn_stat_retn 2972 00004D00 F6C480 <1> test ah, NOTBUSYSTATUS 2973 00004D03 750D <1> jnz short prn_stat_ok ; if not busy return (with cf=0) 2974 00004D05 B022 <1> mov al, ERR_PRN_BUSY ; else busy, return to busy exit 2975 <1> prn_stat_retn: 2976 <1> ; al = error code 2977 <1> ; ah = status flags 2978 00004D07 A3[EC640000] <1> mov [u.r0], eax 2979 <1> ;movzx eax, al 2980 <1> ;mov [u.error], eax 2981 00004D0C 58 <1> pop eax ; discard return address to syswrite 2982 00004D0D E9D9E3FFFF <1> jmp sysret 2983 <1> prn_stat_ok: 2984 00004D12 30C0 <1> xor al, al ; 0 2985 00004D14 EBF1 <1> jmp short prn_stat_retn 2986 <1> 2987 <1> ; 2988 <1> ; PRNSTAT get printer status 2989 <1> ; PRNOP print a character 2990 <1> ; 2991 <1> ; PRNSTAT and PRNOP are two routines which call on the ROM-BIOS 2992 <1> ; printer routines. The routines share code which calls on the bios and 2993 <1> ; then determines which, if any, error occured. PRNSTAT and PRNOP differ 2994 <1> ; only by the value put into AH before the ROM-BIOS call. 2995 <1> ; 2996 <1> ; INPUT if PRNOP then character in AL 2997 <1> ; 2998 <1> ; OUTPUT - AL holds error code 2999 <1> ; - AH status byte from printer 3000 <1> ; - flag NZ if error 3001 <1> 3002 <1> PRNSTAT: 3003 00004D16 B402 <1> mov ah, 2 ; set command for get status 3004 <1> 3005 <1> PRNOP: 3006 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 3007 <1> ; 3008 <1> ; Print character (on paper) 3009 <1> 3010 <1> ; INPUT: 3011 <1> ; al = character to be printed 3012 <1> ; OUTPUT: 3013 <1> ; zf = 1 -> ok 3014 <1> ; zf = 0 -> error code in AL 3015 <1> 3016 00004D18 E8080B0000 <1> call int17h ; call lpt bios 3017 <1> 3018 00004D1D F6C408 <1> test ah, IOERRSTATUS ; I/O ERROR? 3019 00004D20 740A <1> jz short short prnop_chk_nrdy ; NO, TRY NOT READY 3020 <1> 3021 <1> ; AT THIS POINT, WE KNOW WE HAVE AN ERROR. 3022 <1> ; THE CONVERSE IS NOT TRUE. 3023 <1> 3024 <1> ;mov al, 9 ; FIRST, ASSUME OUT OF PAPER 3025 00004D22 B01F <1> mov al, ERR_PRN_PAPER 3026 00004D24 F6C420 <1> test ah, NOPAPERSTATUS ; OUT OF PAPER SET? 3027 00004D27 7502 <1> jnz short PRNOP1 ; YES, ERROR IS SET 3028 <1> ;mov al, ERR_PRN_IO 3029 00004D29 FEC0 <1> inc al ; INDICATE I/O ERROR 3030 <1> PRNOP1: 3031 <1> 3032 <1> ; WE HAVE TRIAGED NOW FOR OUT OF PAPER AND IO ERR (IGNORING TIME-OUT) 3033 <1> 3034 00004D2B C3 <1> retn ; RETURN WITH ERROR 3035 <1> 3036 <1> ; THE BITS SAID NO ERROR. 3037 <1> ; UNFORTUNATELY, THERE MAY BE OTHER THINGS AT WORK HERE. 3038 <1> 3039 <1> prnop_chk_nrdy: 3040 <1> ;mov al, 2 ; ASSUME NOT-READY 3041 00004D2C B019 <1> mov al, ERR_PRN_TIMEOUT ; ''time out !' error 3042 <1> 3043 00004D2E F6C401 <1> test ah, TIMEOUTSTATUS ; IS TIME-OUT SET? 3044 <1> ; IF NZ THEN ERROR, ELSE OK??? 3045 <1> PRNOP2: 3046 00004D31 C3 <1> retn 3047 <1> 3048 <1> 3049 <1> dskw: ; / write routine for non-special files 3050 <1> ; 3051 <1> ; 19/07/2022 3052 <1> ; (file offset bugfix for 'dskwr' error return situation) 3053 <1> ; 3054 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 3055 <1> ; 25/07/2015 3056 <1> ; 16/06/2015 3057 <1> ; 09/06/2015 3058 <1> ; 31/05/2015 (Retro UNIX 386 v1 - Beginning) 3059 <1> ; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1) 3060 <1> ; 3061 <1> ; 01/08/2013 (mkdir_w check) 3062 <1> 3063 <1> ;push ax ; 26/04/2013 3064 <1> ; mov (sp),r1 / get an i-node number from the stack into r1 3065 <1> ; 24/12/2021 3066 00004D32 50 <1> push eax 3067 <1> ; AX = inode number 3068 00004D33 E8AFFAFFFF <1> call iget 3069 <1> ; jsr r0,iget / write i-node out (if modified), 3070 <1> ; / read i-node 'r1' into i-node area of core 3071 00004D38 8B1D[FC640000] <1> mov ebx, [u.fofp] 3072 00004D3E 8B13 <1> mov edx, [ebx] 3073 <1> ; mov *u.fofp,r2 / put the file offset [(u.off) or the offset 3074 <1> ; / in the fsp entry for this file] in r2 3075 00004D40 0315[10650000] <1> add edx, [u.count] 3076 <1> ; add u.count,r2 / no. of bytes to be written 3077 <1> ; / + file offset is put in r2 3078 <1> ; 16/06/2015 3079 00004D46 81FAFFFF0000 <1> cmp edx, 65535 ; file size limit (for UNIX v1 file system) 3080 00004D4C 760F <1> jna short dskw_0 3081 00004D4E C705[41650000]1400- <1> mov dword [u.error], ERR_FILE_SIZE ; 'file size error !' 3081 00004D56 0000 <1> 3082 00004D58 E96EE3FFFF <1> jmp error 3083 <1> dskw_0: 3084 00004D5D 663B15[E8610000] <1> cmp dx, [i.size] 3085 <1> ; cmp r2,i.size / is this greater than the present size of 3086 <1> ; / the file? 3087 00004D64 760C <1> jna short dskw_1 3088 <1> ; blos 1f / no, branch 3089 00004D66 668915[E8610000] <1> mov [i.size], dx 3090 <1> ; mov r2,i.size / yes, increase the file size to 3091 <1> ; / file offset + no. of data bytes 3092 00004D6D E87FFBFFFF <1> call setimod 3093 <1> ; jsr r0,setimod / set imod=1 (i.e., core inode has been 3094 <1> ; / modified), stuff time of modification into 3095 <1> ; / core image of i-node 3096 <1> dskw_1: ; 1: 3097 00004D72 E807F9FFFF <1> call mget 3098 <1> ; EAX = Block number 3099 <1> ; jsr r0,mget / get the block no. in which to write 3100 <1> ; / the next data byte 3101 <1> ; eax = block number 3102 00004D77 8B1D[FC640000] <1> mov ebx, [u.fofp] 3103 00004D7D 8B13 <1> mov edx, [ebx] 3104 00004D7F 81E2FF010000 <1> and edx, 1FFh 3105 <1> ; bit *u.fofp,$777 / test the lower 9 bits of the file offset 3106 00004D85 750C <1> jnz short dskw_2 3107 <1> ; bne 2f / if its non-zero, branch; if zero, file offset = 0, 3108 <1> ; / 512, 1024,...(i.e., start of new block) 3109 00004D87 813D[10650000]0002- <1> cmp dword [u.count], 512 3109 00004D8F 0000 <1> 3110 <1> ; cmp u.count,$512. / if zero, is there enough data to fill 3111 <1> ; / an entire block? (i.e., no. of 3112 00004D91 7305 <1> jnb short dskw_3 3113 <1> ; bhis 3f / bytes to be written greater than 512.? 3114 <1> ; / Yes, branch. Don't have to read block 3115 <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be 3116 <1> ; / overwritten). 3117 00004D93 E81A060000 <1> call dskrd 3118 <1> ; jsr r0,dskrd / no, must retain old info.. 3119 <1> ; / Hence, read block 'r1' into an I/O buffer 3120 <1> dskw_3: ; 3: 3121 <1> ; EAX (r1) = block/sector number 3122 00004D98 E879060000 <1> call wslot 3123 <1> ; jsr r0,wslot / set write and inhibit bits in I/O queue, 3124 <1> ; / proc. status=0, r5 points to 1st word of data 3125 00004D9D 803D[53650000]00 <1> cmp byte [u.kcall], 0 3126 00004DA4 770F <1> ja short dskw_5 ; zf=0 -> the caller is 'mkdir' 3127 <1> ; 3128 00004DA6 66833D[51650000]00 <1> cmp word [u.pcount], 0 3129 00004DAE 7705 <1> ja short dskw_5 3130 <1> dskw_4: 3131 <1> ; [u.base] = virtual address to transfer (as source address) 3132 00004DB0 E89BFDFFFF <1> call trans_addr_r ; translate virtual address to physical (r) 3133 <1> dskw_5: 3134 <1> ; EBX (r5) = system (I/O) buffer address 3135 00004DB5 E885000000 <1> call sioreg 3136 <1> ; jsr r0,sioreg / r3 = no. of bytes of data, 3137 <1> ; / r1 = address of data, r2 points to location 3138 <1> ; / in buffer in which to start writing data 3139 <1> ; 19/07/2022 3140 <1> ; EDX = user data offset (previous value of [u.pbase]) 3141 <1> ; ESI = pointer to file offset 3142 <1> ; EDI = system (I/O) buffer offset 3143 <1> ; ECX = byte count 3144 <1> ; EBX = system buffer (data) address 3145 <1> ; EAX = remain bytes after byte count within page frame 3146 <1> 3147 <1> ; 19/07/2022 - Erdogan Tan 3148 <1> ; BugFix (Also original unix v1 kernel code has this bug!) 3149 <1> ; ((Against a possible disk write failure/error, 3150 <1> ; file offset must not be updated/increased before 'dskwr' 3151 <1> ; but it was updated in 'sioreg'. I have modified 'sioreg' 3152 <1> ; and 'dskw' procedures for that.)) 3153 <1> 3154 <1> ; 19/07/2022 3155 00004DBA 56 <1> push esi ; * ; save file offset (pointer) 3156 00004DBB 51 <1> push ecx ; ** ; save byte count 3157 00004DBC 89D6 <1> mov esi, edx 3158 <1> 3159 <1> ; ESI = file (user data) offset 3160 <1> ; EDI = sector (I/O) buffer offset 3161 <1> ; ECX = byte count 3162 <1> ; 3163 00004DBE F3A4 <1> rep movsb 3164 <1> ; movb (r1 )+,(r2)+ 3165 <1> ; / transfer a byte of data to the I/O buffer 3166 <1> ; dec r3 / decrement no. of bytes to be written 3167 <1> ; bne 2b / have all bytes been transferred? No, branch 3168 <1> ; 25/07/2015 3169 <1> ; eax = remain bytes in buffer 3170 <1> ; (check if remain bytes in the buffer > [u.pcount]) 3171 00004DC0 09C0 <1> or eax, eax 3172 00004DC2 75EC <1> jnz short dskw_4 ; (page end before system buffer end!) 3173 <1> dskw_6: 3174 00004DC4 E85A060000 <1> call dskwr 3175 <1> ; jsr r0,dskwr / yes, write the block and the i-node 3176 <1> 3177 <1> ; 19/07/2022 3178 <1> ; (there is not a disk write error, we can increase file offset) 3179 00004DC9 58 <1> pop eax ; ** ; byte count 3180 00004DCA 5F <1> pop edi ; * ; file offset (pointer) 3181 <1> ; 3182 00004DCB 0107 <1> add [edi], eax 3183 <1> ; new file offset (old offset + byte count) 3184 <1> 3185 00004DCD 833D[10650000]00 <1> cmp dword [u.count], 0 3186 <1> ; tst u.count / any more data to write? 3187 00004DD4 779C <1> ja short dskw_1 3188 <1> ; bne 1b / yes, branch 3189 <1> ; 03/08/2013 3190 00004DD6 C605[53650000]00 <1> mov byte [u.kcall], 0 3191 <1> ; 20/09/2013 (;;) 3192 <1> ;pop ax 3193 <1> ; 24/12/2021 3194 00004DDD 58 <1> pop eax 3195 00004DDE C3 <1> retn 3196 <1> ;;jmp short dskw_ret 3197 <1> ; jmp ret / no, return to the caller via 'ret' 3198 <1> 3199 <1> cpass: ; / get next character from user area of core and put it in r1 3200 <1> ; 18/10/2015 3201 <1> ; 10/10/2015 3202 <1> ; 10/07/2015 3203 <1> ; 02/07/2015 3204 <1> ; 01/07/2015 3205 <1> ; 24/06/2015 3206 <1> ; 08/06/2015 3207 <1> ; 04/06/2015 3208 <1> ; 20/05/2015 3209 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 3210 <1> ; 3211 <1> ; INPUTS -> 3212 <1> ; [u.base] = virtual address in user area 3213 <1> ; [u.count] = byte count (max.) 3214 <1> ; [u.pcount] = byte count in page (0 = reset) 3215 <1> ; OUTPUTS -> 3216 <1> ; AL = the character which is pointed by [u.base] 3217 <1> ; zf = 1 -> transfer count has been completed 3218 <1> ; 3219 <1> ; ((Modified registers: EAX, EDX, ECX)) 3220 <1> ; 3221 <1> ; 3222 00004DDF 833D[10650000]00 <1> cmp dword [u.count], 0 ; 14/08/2013 3223 <1> ; tst u.count / have all the characters been transferred 3224 <1> ; / (i.e., u.count, # of chars. left 3225 00004DE6 763F <1> jna short cpass_3 3226 <1> ; beq 1f / to be transferred = 0?) yes, branch 3227 00004DE8 FF0D[10650000] <1> dec dword [u.count] 3228 <1> ; dec u.count / no, decrement u.count 3229 <1> ; 19/05/2015 3230 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 3231 <1> ; to physical address 3232 00004DEE 66833D[51650000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 3233 <1> ; 1-4095 --> use previous physical base address 3234 <1> ; in [u.pbase] 3235 00004DF6 770E <1> ja short cpass_1 3236 <1> ; 02/07/2015 3237 00004DF8 833D[49650000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller os kernel 3238 00004DFF 7427 <1> je short cpass_k ; (sysexec, '/etc/init') ? 3239 <1> ; 08/06/2015 - 10/07/2015 3240 00004E01 E84AFDFFFF <1> call trans_addr_r 3241 <1> cpass_1: 3242 <1> ; 02/07/2015 3243 <1> ; 24/06/2015 3244 00004E06 66FF0D[51650000] <1> dec word [u.pcount] 3245 <1> cpass_2: 3246 <1> ; 10/10/2015 3247 <1> ; 02/07/2015 3248 00004E0D 8B15[4D650000] <1> mov edx, [u.pbase] 3249 00004E13 8A02 <1> mov al, [edx] ; 10/10/2015 3250 <1> ; movb *u.base,r1 / take the character pointed to 3251 <1> ; / by u.base and put it in r1 3252 00004E15 FF05[14650000] <1> inc dword [u.nread] 3253 <1> ; inc u.nread / increment no. of bytes transferred 3254 00004E1B FF05[0C650000] <1> inc dword [u.base] 3255 <1> ; inc u.base / increment the buffer address to point to the 3256 <1> ; / next byte 3257 00004E21 FF05[4D650000] <1> inc dword [u.pbase] ; 04/06/2015 3258 <1> cpass_3: 3259 00004E27 C3 <1> retn 3260 <1> ; rts r0 / next byte 3261 <1> ; 1: 3262 <1> ; mov (sp)+,r0 3263 <1> ; / put return address of calling routine into r0 3264 <1> ; mov (sp)+,r1 / i-number in r1 3265 <1> ; rts r0 / non-local return 3266 <1> cpass_k: 3267 <1> ; 02/07/2015 3268 <1> ; The caller is os kernel 3269 <1> ; (get sysexec arguments from kernel's memory space) 3270 <1> ; 3271 00004E28 8B1D[0C650000] <1> mov ebx, [u.base] 3272 00004E2E 66C705[51650000]00- <1> mov word [u.pcount], PAGE_SIZE ; 4096 3272 00004E36 10 <1> 3273 00004E37 891D[4D650000] <1> mov [u.pbase], ebx 3274 00004E3D EBCE <1> jmp short cpass_2 3275 <1> 3276 <1> sioreg: 3277 <1> ; 19/07/2022 3278 <1> ; (file offset bugfix for 'dskwr' error return situation) 3279 <1> ; 25/07/2015 3280 <1> ; 18/07/2015 3281 <1> ; 02/07/2015 3282 <1> ; 17/06/2015 3283 <1> ; 09/06/2015 3284 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 3285 <1> ; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1) 3286 <1> ; 3287 <1> ; INPUTS -> 3288 <1> ; EBX = system buffer (data) address (r5) 3289 <1> ; [u.fofp] = pointer to file offset pointer 3290 <1> ; [u.base] = virtual address of the user buffer 3291 <1> ; [u.pbase] = physical address of the user buffer 3292 <1> ; [u.count] = byte count 3293 <1> ; [u.pcount] = byte count within page frame 3294 <1> ; OUTPUTS -> 3295 <1> ; ESI = user data offset (r1) 3296 <1> ; EDI = system (I/O) buffer offset (r2) 3297 <1> ; ECX = byte count (r3) 3298 <1> ; EAX = remain bytes after byte count within page frame 3299 <1> ; (If EAX > 0, transfer will continue from the next page) 3300 <1> ; 3301 <1> ; ((Modified registers: EDX)) 3302 <1> 3303 <1> ; 19/07/2022 3304 <1> ; OUTPUTS -> 3305 <1> ; EDX = user data offset (previous value of [u.pbase]) 3306 <1> ; ESI = pointer to file offset 3307 <1> ; EDI = system (I/O) buffer offset 3308 <1> ; ECX = byte count 3309 <1> ; EBX = system buffer (data) address 3310 <1> ; EAX = remain bytes after byte count within page frame 3311 <1> 3312 00004E3F 8B35[FC640000] <1> mov esi, [u.fofp] 3313 00004E45 8B3E <1> mov edi, [esi] 3314 <1> ; mov *u.fofp,r2 / file offset (in bytes) is moved to r2 3315 00004E47 89F9 <1> mov ecx, edi 3316 <1> ; mov r2,r3 / and also to r3 3317 00004E49 81C900FEFFFF <1> or ecx, 0FFFFFE00h 3318 <1> ; bis $177000,r3 / set bits 9,...,15 of file offset in r3 3319 00004E4F 81E7FF010000 <1> and edi, 1FFh 3320 <1> ; bic $!777,r2 / calculate file offset mod 512. 3321 00004E55 01DF <1> add edi, ebx ; EBX = system buffer (data) address 3322 <1> ; add r5,r2 / r2 now points to 1st byte in system buffer 3323 <1> ; / where data is to be placed 3324 <1> ; mov u.base,r1 / address of data is in r1 3325 00004E57 F7D9 <1> neg ecx 3326 <1> ; neg r3 / 512 - file offset (mod512.) in r3 3327 <1> ; / (i.e., the no. of free bytes in the file block) 3328 00004E59 3B0D[10650000] <1> cmp ecx, [u.count] 3329 <1> ; cmp r3,u.count / compare this with the no. of data bytes 3330 <1> ; / to be written to the file 3331 00004E5F 7606 <1> jna short sioreg_0 3332 <1> ; blos 2f / if less than branch. Use the no. of free bytes 3333 <1> ; / in the file block as the number to be written 3334 00004E61 8B0D[10650000] <1> mov ecx, [u.count] 3335 <1> ; mov u.count,r3 / if greater than, use the no. of data 3336 <1> ; / bytes as the number to be written 3337 <1> sioreg_0: 3338 <1> ; 17/06/2015 3339 00004E67 803D[53650000]00 <1> cmp byte [u.kcall], 0 3340 00004E6E 7613 <1> jna short sioreg_1 3341 <1> ; 25/07/2015 3342 <1> ; the caller is 'mkdir' or 'namei' 3343 00004E70 A1[0C650000] <1> mov eax, [u.base] ; 25/07/2015 3344 00004E75 A3[4D650000] <1> mov [u.pbase], eax ; physical address = virtual address 3345 00004E7A 66890D[51650000] <1> mov word [u.pcount], cx ; remain bytes in buffer (1 sector) 3346 00004E81 EB0B <1> jmp short sioreg_2 3347 <1> sioreg_1: 3348 <1> ; 25/07/2015 3349 <1> ; 18/07/2015 3350 <1> ; 09/06/2015 3351 00004E83 0FB715[51650000] <1> movzx edx, word [u.pcount] 3352 <1> ; ecx and [u.pcount] are always > 0, here 3353 00004E8A 39D1 <1> cmp ecx, edx 3354 00004E8C 7728 <1> ja short sioreg_4 ; transfer count > [u.pcount] 3355 <1> sioreg_2: ; 2: 3356 00004E8E 31C0 <1> xor eax, eax ; 25/07/2015 3357 <1> sioreg_3: 3358 00004E90 010D[14650000] <1> add [u.nread], ecx 3359 <1> ; add r3,u.nread / r3 + number of bytes xmitted 3360 <1> ; / during write is put into u.nread 3361 00004E96 290D[10650000] <1> sub [u.count], ecx 3362 <1> ; sub r3,u.count / u.count = no. of bytes that still 3363 <1> ; / must be written or read 3364 00004E9C 010D[0C650000] <1> add [u.base], ecx 3365 <1> ; add r3,u.base / u.base points to the 1st of the remaining 3366 <1> ; / data bytes 3367 <1> ; 19/07/2022 3368 <1> ;add [esi], ecx 3369 <1> ; ; add r3,*u.fofp / new file offset = number of bytes done 3370 <1> ; / + old file offset 3371 <1> ; 25/07/2015 3372 <1> ;mov esi, [u.pbase] 3373 <1> ; 19/07/2022 3374 00004EA2 8B15[4D650000] <1> mov edx, [u.pbase] 3375 <1> 3376 00004EA8 66290D[51650000] <1> sub [u.pcount], cx 3377 00004EAF 010D[4D650000] <1> add [u.pbase], ecx 3378 00004EB5 C3 <1> retn 3379 <1> ; rts r0 3380 <1> ; transfer count > [u.pcount] 3381 <1> sioreg_4: 3382 <1> ; 25/07/2015 3383 <1> ; transfer count > [u.pcount] 3384 <1> ; (ecx > edx) 3385 00004EB6 89C8 <1> mov eax, ecx 3386 00004EB8 29D0 <1> sub eax, edx ; remain bytes for 1 sector (block) transfer 3387 00004EBA 89D1 <1> mov ecx, edx ; current transfer count = [u.pcount] 3388 00004EBC EBD2 <1> jmp short sioreg_3 2120 %include 'u7.s' ; 18/04/2015 2121 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS7.INC 2122 <1> ; Last Modification: 13/06/2022 2123 <1> ; ---------------------------------------------------------------------------- 2124 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2125 <1> ; (v0.1 - Beginning: 11/07/2012) 2126 <1> ; 2127 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2128 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2129 <1> ; 2130 <1> ; 2131 <1> ; 2132 <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s 2133 <1> ; 2134 <1> ; **************************************************************************** 2135 <1> 2136 <1> sysmount: ; / mount file system; args special; name 2137 <1> ; 15/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3) 2138 <1> ; 09/02/2022 2139 <1> ; 08/02/2022 2140 <1> ; 07/02/2022 2141 <1> ; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2142 <1> ; 14/11/2015 2143 <1> ; 24/10/2015 2144 <1> ; 13/10/2015 2145 <1> ; 10/07/2015 2146 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 2147 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 2148 <1> ; 2149 <1> ; 'sysmount' anounces to the system that a removable 2150 <1> ; file system has been mounted on a special file. 2151 <1> ; The device number of the special file is obtained via 2152 <1> ; a call to 'getspl'. It is put in the I/O queue entry for 2153 <1> ; dismountable file system (sb1) and the I/O queue entry is 2154 <1> ; set up to read (bit 10 is set). 'ppoke' is then called to 2155 <1> ; to read file system into core, i.e. the first block on the 2156 <1> ; mountable file system is read in. This block is super block 2157 <1> ; for the file system. This call is super user restricted. 2158 <1> ; 2159 <1> ; Calling sequence: 2160 <1> ; sysmount; special; name 2161 <1> ; Arguments: 2162 <1> ; special - pointer to name of special file (device) 2163 <1> ; name - pointer to name of the root directory of the 2164 <1> ; newly mounted file system. 'name' should 2165 <1> ; always be a directory. 2166 <1> ; Inputs: - 2167 <1> ; Outputs: - 2168 <1> ; ............................................................... 2169 <1> ; 2170 <1> ; Retro UNIX 8086 v1 modification: 2171 <1> ; 'sysmount' system call has two arguments; so, 2172 <1> ; * 1st argument, special is pointed to by BX register 2173 <1> ; * 2nd argument, name is in CX register 2174 <1> ; 2175 <1> ; NOTE: Device numbers, names and related procedures are 2176 <1> ; already modified for IBM PC compatibility and 2177 <1> ; Retro UNIX 8086 v1 device configuration. 2178 <1> 2179 <1> ;call arg2 2180 <1> ; jsr r0,arg2 / get arguments special and name 2181 00004EBE 891D[04650000] <1> mov [u.namep], ebx 2182 <1> ; 09/02/2022 2183 <1> ;push ecx ; directory name 2184 00004EC4 66833D[D6640000]00 <1> cmp word [mnti], 0 2185 <1> ; tst mnti / is the i-number of the cross device file 2186 <1> ; / zero? 2187 <1> ;;ja error 2188 <1> ; bne errora / no, error 2189 <1> ;ja sysmnt_err0 2190 <1> ; 11/01/2022 2191 00004ECC 7605 <1> jna short sysmnt_0 2192 00004ECE E968010000 <1> jmp sysmnt_err0 2193 <1> sysmnt_0: 2194 <1> ; 09/02/2022 2195 00004ED3 51 <1> push ecx ; directory name 2196 00004ED4 E84A010000 <1> call getspl 2197 <1> ; jsr r0,getspl / get special files device number in r1 2198 <1> ; 09/02/2022 2199 00004ED9 8F05[04650000] <1> pop dword [u.namep] ; directory name 2200 <1> ; 13/10/2015 2201 <1> ;movzx ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5) 2202 <1> ; 11/01/2022 2203 00004EDF 29DB <1> sub ebx, ebx 2204 00004EE1 88C3 <1> mov bl, al 2205 00004EE3 F683[6E5C0000]80 <1> test byte [ebx+drv.status], 80h ; 24/10/2015 2206 00004EEA 750F <1> jnz short sysmnt_1 2207 <1> sysmnt_err1: 2208 00004EEC C705[41650000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY ; drive not ready ! 2208 00004EF4 0000 <1> 2209 00004EF6 E9D0E1FFFF <1> jmp error 2210 <1> sysmnt_1: 2211 <1> ; 09/02/2022 2212 <1> ;pop dword [u.namep] 2213 <1> ; mov (sp)+,u.namep / put the name of file to be placed 2214 <1> ; / on the device 2215 <1> ; 14/11/2015 2216 00004EFB 53 <1> push ebx ; 13/10/2015 2217 <1> ; mov r1,-(sp) / save the device number 2218 <1> ; 2219 00004EFC E8D6F0FFFF <1> call namei 2220 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 2221 <1> ; ax = 0 -> file not found 2222 <1> ;jz error 2223 <1> ;jc error 2224 <1> ; jsr r0,namei / get the i-number of the file 2225 <1> ; br errora 2226 00004F01 730F <1> jnc short sysmnt_2 2227 <1> sysmnt_err2: 2228 00004F03 C705[41650000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready ! 2228 00004F0B 0000 <1> 2229 00004F0D E9B9E1FFFF <1> jmp error 2230 <1> sysmnt_2: 2231 00004F12 66A3[D6640000] <1> mov [mnti], ax 2232 <1> ; mov r1,mnti / put it in mnti 2233 <1> 2234 <1> ; 15/05/2022 2235 <1> ; -Retro UNIX 8086/386 v1 feaure only- 2236 00004F18 66A1[D0640000] <1> mov ax, [ii] 2237 00004F1E 66A3[D8640000] <1> mov [mntp], ax ; parent dir inumber of [mnti] 2238 <1> 2239 <1> ; 11/01/2022 2240 00004F24 BB[BC770000] <1> mov ebx, sb1 ; super block buffer header (of mounted disk) 2241 <1> sysmnt_3: ;1: 2242 <1> ;cmp byte [ebx+1], 0 2243 <1> ; tstb sb1+1 / is 15th bit of I/O queue entry for 2244 <1> ; / dismountable device set? 2245 <1> ;jna short sysmnt_4 2246 <1> ; bne 1b / (inhibit bit) yes, skip writing 2247 <1> ;call idle ; (wait for hardware interrupt) 2248 <1> ;jmp short sysmnt_3 2249 <1> sysmnt_4: 2250 00004F29 58 <1> pop eax ; Retro UNIX 8086 v1 device number/ID (0 to 5) 2251 00004F2A A2[D5640000] <1> mov [mdev], al 2252 <1> ; mov (sp),mntd / no, put the device number in mntd 2253 00004F2F 8803 <1> mov [ebx], al 2254 <1> ; movb (sp),sb1 / put the device number in the lower byte 2255 <1> ; / of the I/O queue entry 2256 <1> ;mov byte [cdev], 1 ; mounted device/drive 2257 <1> ; mov (sp)+,cdev / put device number in cdev 2258 00004F31 66810B0004 <1> or word [ebx], 400h ; Bit 10, 'read' flag/bit 2259 <1> ; bis $2000,sb1 / set the read bit 2260 <1> ; Retro UNIX 386 v1 modification : 2261 <1> ; 32 bit block number at buffer header offset 4 2262 00004F36 C7430401000000 <1> mov dword [ebx+4], 1 ; physical block number = 1 2263 00004F3D E8AB050000 <1> call diskio 2264 00004F42 7345 <1> jnc short sysmnt_5 2265 00004F44 31C0 <1> xor eax, eax 2266 00004F46 66A3[D6640000] <1> mov [mnti], ax ; 0 2267 00004F4C A2[D5640000] <1> mov [mdev], al ; 0 2268 <1> ;mov [cdev], al ; 0 2269 <1> ; 08/02/2022 2270 00004F51 803D[54650000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 2271 00004F58 7508 <1> jne short sysmnt_err3 2272 <1> ; yes, clear [u.brwdev] for next check 2273 <1> ; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 2274 00004F5A FE05[54650000] <1> inc byte [u.brwdev] ; 0, reset 2275 00004F60 EB0A <1> jmp short sysmnt_err4 2276 <1> sysmnt_err3: ; 08/02/2022 2277 <1> ; no, set [u.error] to disk read error 2278 00004F62 C705[41650000]1100- <1> mov dword [u.error], ERR_DRV_READ ; 'disk read error !' 2278 00004F6A 0000 <1> 2279 <1> sysmnt_err4: 2280 <1> ; 08/02/2022 2281 <1> ; 14/11/2015 2282 00004F6C FEC8 <1> dec al 2283 00004F6E 8903 <1> mov [ebx], eax ; 000000FFh 2284 00004F70 FEC0 <1> inc al 2285 00004F72 48 <1> dec eax 2286 00004F73 894304 <1> mov [ebx+4], eax ; 0FFFFFFFFh 2287 00004F76 E950E1FFFF <1> jmp error 2288 <1> sysmnt_invd: 2289 <1> ; 08/02/2022 2290 00004F7B C705[41650000]1C00- <1> mov dword [u.error], ERR_INV_FS ; 28 2290 00004F83 0000 <1> 2291 <1> ;'invalid fs/superblock !' error 2292 00004F85 30C0 <1> xor al, al 2293 00004F87 EBE3 <1> jmp short sysmnt_err4 2294 <1> 2295 <1> sysmnt_5: 2296 <1> ; 08/02/2022 2297 <1> ; 11/01/2022 (BugFix) 2298 <1> ; 14/11/2015 (Retro UNIX 386 v1 modification) 2299 <1> ; (Following check is needed to prevent mounting an 2300 <1> ; invalid file system (invalid super block). 2301 <1> ; 2302 00004F89 0FB603 <1> movzx eax, byte [ebx] ; device number 2303 00004F8C C0E002 <1> shl al, 2 ; 4*index 2304 00004F8F 8B88[525C0000] <1> mov ecx, [eax+drv.size] ; volume (fs) size 2305 00004F95 C1E903 <1> shr ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte) 2306 <1> ; ecx = number of free map bytes (required) 2307 <1> ;movzx edx, word [sb1+8] ; the 1st data word ('mount:') 2308 00004F98 0FB75308 <1> movzx edx, word [ebx+8] ; the 1st data word (of the buffer) 2309 <1> ; edx = number of free blocks map bytes 2310 <1> ;shl edx, 3 ; convert free map bytes to free map bits 2311 <1> ; 07/02/2022 2312 <1> ;xor al, al ; 08/02/2022 2313 00004F9C 39D1 <1> cmp ecx, edx ; compare free map bits and volume size 2314 <1> ; (in sectors), if they are not equal 2315 <1> ; the disk to be mounted is an... 2316 00004F9E 75DB <1> jne short sysmnt_invd ; invalid disk ! 2317 <1> ; (which has not got a valid super block) 2318 <1> ; 2319 00004FA0 C6430100 <1> mov byte [ebx+1], 0 2320 <1> ; jsr r0,ppoke / read in entire file system 2321 <1> ;sysmnt_6: ;1: 2322 <1> ;;cmp byte [sb1+1], 0 2323 <1> ; tstb sb1+1 / done reading? 2324 <1> ;;jna sysret 2325 <1> ;;call idle ; (wait for hardware interrupt) 2326 <1> ;;jmp short sysmnt_6 2327 <1> ; bne 1b / no, wait 2328 <1> ; br sysreta / yes 2329 00004FA4 E942E1FFFF <1> jmp sysret 2330 <1> 2331 <1> sysumount: ; / special dismount file system 2332 <1> ; 15/05/2022 2333 <1> ; 09/05/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.3) 2334 <1> ; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2335 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 2336 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 2337 <1> ; 2338 <1> ; 04/11/2013 2339 <1> ; 09/07/2013 2340 <1> ; 'sysumount' anounces to the system that the special file, 2341 <1> ; indicated as an argument is no longer contain a removable 2342 <1> ; file system. 'getspl' gets the device number of the special 2343 <1> ; file. If no file system was mounted on that device an error 2344 <1> ; occurs. 'mntd' and 'mnti' are cleared and control is passed 2345 <1> ; to 'sysret'. 2346 <1> ; 2347 <1> ; Calling sequence: 2348 <1> ; sysmount; special 2349 <1> ; Arguments: 2350 <1> ; special - special file to dismount (device) 2351 <1> ; 2352 <1> ; Inputs: - 2353 <1> ; Outputs: - 2354 <1> ; ............................................................... 2355 <1> ; 2356 <1> ; Retro UNIX 8086 v1 modification: 2357 <1> ; 'sysumount' system call has one argument; so, 2358 <1> ; * Single argument, special is pointed to by BX register 2359 <1> ; 2360 <1> 2361 <1> ;mov ax, 1 ; one/single argument, put argument in BX 2362 <1> ;call arg 2363 <1> ; jsr r0,arg; u.namep / point u.namep to special 2364 00004FA9 891D[04650000] <1> mov [u.namep], ebx 2365 00004FAF E86F000000 <1> call getspl 2366 <1> ; jsr r0,getspl / get the device number in r1 2367 <1> 2368 <1> ;;; 2369 <1> ; 09/05/2022 - Erdogan Tan 2370 <1> ; (I have added [mnti] check because 2371 <1> ; retro unix device number of /dev/fd0 is 0 2372 <1> ; .. so, 'cmp al, [mdev]' is not enough 2373 <1> ; for dismounting /dev/fd0. sysumount system call would give 2374 <1> ; wrong cf=0 result while /dev/fd0 is not mounted.) 2375 00004FB4 66833D[D6640000]00 <1> cmp word [mnti], 0 2376 00004FBC 767D <1> jna short sysmnt_err0 ; there is not a mounted device ! 2377 <1> ;;; 2378 <1> 2379 00004FBE 3A05[D5640000] <1> cmp al, [mdev] 2380 <1> ; cmp r1,mntd / is it equal to the last device mounted? 2381 00004FC4 7575 <1> jne short sysmnt_err0 ; 'permission denied !' error 2382 <1> ;jne error 2383 <1> ; bne errora / no error 2384 00004FC6 30C0 <1> xor al, al ; ah = 0 2385 <1> sysumnt_0: ;1: 2386 <1> ; 11/01/2022 2387 <1> ;cmp [sb1+1], al ; 0 2388 <1> ; ; tstb sb1+1 / yes, is the device still doing I/O 2389 <1> ; ; / (inhibit bit set)? 2390 <1> ;jna short sysumnt_1 2391 <1> ; ; bne 1b / yes, wait 2392 <1> ;call idle ; (wait for hardware interrupt) 2393 <1> ;jmp short sysumnt_0 2394 <1> sysumnt_1: 2395 <1> ; 15/05/2022 2396 <1> ; change user's current directory to mounting directory 2397 <1> ; if it is on the mounted device (chdir back to root fs) 2398 00004FC8 3805[36650000] <1> cmp byte [u.cdrv], al ; 0 2399 00004FCE 7643 <1> jna short sysumnt_4 2400 <1> ;;; 2401 <1> ; 15/05/2022 2402 <1> ; It is needed to change the parent process's current 2403 <1> ; directory because shell runs (/etc/umount) 2404 <1> ; as child process. 2405 00004FD0 31DB <1> xor ebx, ebx 2406 00004FD2 8A1D[3B650000] <1> mov bl, [u.uno] 2407 00004FD8 D0E3 <1> shl bl, 1 ; >= 2 .. <= 32 2408 00004FDA 81C3[22620000] <1> add ebx, p.ppid-2 2409 00004FE0 668B13 <1> mov dx, [ebx] ; process id of the parent [p.ppid] 2410 00004FE3 BE[04620000] <1> mov esi, p.pid 2411 00004FE8 29C9 <1> sub ecx, ecx 2412 00004FEA B110 <1> mov cl, nproc ; 16 2413 <1> sysumnt_2: 2414 00004FEC 66AD <1> lodsw 2415 00004FEE 6639D0 <1> cmp ax, dx 2416 00004FF1 7402 <1> je short sysumnt_3 2417 00004FF3 E2F7 <1> loop sysumnt_2 2418 <1> sysumnt_3: 2419 00004FF5 31C0 <1> xor eax, eax 2420 00004FF7 81EE[04620000] <1> sub esi, p.pid 2421 00004FFD D1E6 <1> shl esi, 1 2422 00004FFF 8B9E[70620000] <1> mov ebx, [esi+p.upage-4] ; the parent's upage 2423 <1> ; ebx points to user (u) structure in upage 2424 00005005 668B15[D6640000] <1> mov dx, [mnti] 2425 <1> ;mov [u.cdir], dx 2426 <1> ;mov [u.cdrv], al ; 0 2427 0000500C 6689530C <1> mov [ebx+u.cdir-user], dx 2428 00005010 884352 <1> mov [ebx+u.cdrv-user], al ; 0 2429 <1> ;;; 2430 <1> sysumnt_4: 2431 00005013 A2[D5640000] <1> mov [mdev], al ; 0 2432 <1> ; clr mntd / no, clear these 2433 00005018 66A3[D6640000] <1> mov [mnti], ax ; 0 2434 <1> ; clr mnti 2435 <1> 2436 <1> ;; 15/05/2022 2437 <1> ;mov [cdev], al ; 0 ; [u.cdrv] = 0 2438 <1> ;mov ax, dx ; [u.cdir] 2439 <1> ;call iget 2440 <1> 2441 0000501E E9C8E0FFFF <1> jmp sysret 2442 <1> ; br sysreta / return 2443 <1> 2444 <1> getspl: ; / get device number from a special file name 2445 00005023 E8AFEFFFFF <1> call namei 2446 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 2447 <1> ; ax = 0 -> file not found 2448 <1> ;jc sysmnt_err2 ; 'file not found !' error 2449 <1> ; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2450 00005028 7305 <1> jnc short getspl_0 2451 0000502A E9D4FEFFFF <1> jmp sysmnt_err2 ; 'file not found !' error 2452 <1> getspl_0: 2453 <1> ;jz error 2454 <1> ;jc error 2455 <1> ; jsr r0,namei / get the i-number of the special file 2456 <1> ; br errora / no such file 2457 0000502F 6683E803 <1> sub ax, 3 ; Retro UNIX 8086 v1 modification ! 2458 <1> ; i-number-3, 0 = fd0, 5 = hd3 2459 <1> ; sub $4,r1 / i-number-4 rk=1,tap=2+n 2460 00005033 7206 <1> jc short sysmnt_err0 ; 'permission denied !' error 2461 <1> ;jc error 2462 <1> ; ble errora / less than 0? yes, error 2463 00005035 6683F805 <1> cmp ax, 5 ; 2464 <1> ; cmp r1,$9. / greater than 9 tap 7 2465 <1> ;ja short sysmnt_err0 ; 'permission denied !' error 2466 <1> ;;ja error 2467 <1> ; bgt errora / yes, error 2468 <1> ; 11/01/2022 2469 00005039 760F <1> jna short getspl_retn 2470 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 2471 <1> ;iopen_retn: 2472 <1> ; retn 2473 <1> ; rts r0 / return with device number in r1 2474 <1> sysmnt_err0: 2475 0000503B C705[41650000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 2475 00005043 0000 <1> 2476 00005045 E981E0FFFF <1> jmp error 2477 <1> 2478 <1> getspl_retn: 2479 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 2480 <1> ; 11/01/2022 2481 <1> iopen_retn: 2482 0000504A C3 <1> retn 2483 <1> 2484 <1> iopen: ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 2485 <1> ; (Printer initialization) 2486 <1> ; 11/01/2022 2487 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2488 <1> ; 19/05/2015 2489 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2490 <1> ; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1) 2491 <1> ; 2492 <1> ; open file whose i-number is in r1 2493 <1> ; 2494 <1> ; INPUTS -> 2495 <1> ; r1 - inode number 2496 <1> ; OUTPUTS -> 2497 <1> ; file's inode in core 2498 <1> ; r1 - inode number (positive) 2499 <1> ; 2500 <1> ; ((AX = R1)) 2501 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 2502 <1> ; 2503 <1> ; / open file whose i-number is in r1 2504 0000504B F6C480 <1> test ah, 80h ; Bit 15 of AX 2505 <1> ; tst r1 / write or read access? 2506 0000504E 7568 <1> jnz short iopen_2 2507 <1> ; blt 2f / write, go to 2f 2508 00005050 B202 <1> mov dl, 2 ; read access 2509 00005052 E864F8FFFF <1> call access 2510 <1> ; jsr r0,access; 2 2511 <1> ; / get inode into core with read access 2512 <1> ; DL=2 2513 <1> iopen_0: 2514 00005057 6683F828 <1> cmp ax, 40 2515 <1> ; cmp r1,$40. / is it a special file 2516 0000505B 77ED <1> ja short iopen_retn 2517 <1> ; bgt 3f / no. 3f 2518 0000505D 50 <1> push eax ; 08/01/2022 2519 <1> ;push ax 2520 <1> ; mov r1,-(sp) / yes, figure out 2521 0000505E 0FB6D8 <1> movzx ebx, al 2522 00005061 C0E302 <1> shl bl, 2 ; * 4 ; 08/01/2022 2523 <1> ;shl bx, 2 2524 <1> ; asl r1 2525 00005064 81C3[68500000] <1> add ebx, iopen_1 - 4 2526 0000506A FF23 <1> jmp dword [ebx] 2527 <1> ; jmp *1f-2(r1) / which one and transfer to it 2528 <1> iopen_1: ; 1: 2529 0000506C [D0500000] <1> dd otty ; tty, AX = 1 (runix) 2530 <1> ;otty / tty ; r1=2 2531 <1> ;oppt / ppt ; r1=4 2532 00005070 [88510000] <1> dd sret ; mem, AX = 2 (runix) 2533 <1> ;sret / mem ; r1=6 2534 <1> ;sret / rf0 2535 <1> ;sret / rk0 2536 <1> ;sret / tap0 2537 <1> ;sret / tap1 2538 <1> ;sret / tap2 2539 <1> ;sret / tap3 2540 <1> ;sret / tap4 2541 <1> ;sret / tap5 2542 <1> ;sret / tap6 2543 <1> ;sret / tap7 2544 00005074 [88510000] <1> dd sret ; fd0, AX = 3 (runix only) 2545 00005078 [88510000] <1> dd sret ; fd1, AX = 4 (runix only) 2546 0000507C [88510000] <1> dd sret ; hd0, AX = 5 (runix only) 2547 00005080 [88510000] <1> dd sret ; hd1, AX = 6 (runix only) 2548 00005084 [88510000] <1> dd sret ; hd2, AX = 7 (runix only) 2549 00005088 [88510000] <1> dd sret ; hd3, AX = 8 (runix only) 2550 <1> ;;dd error ; lpr, AX = 9 (error !) 2551 <1> ;dd sret ; lpr, AX = 9 (runix) 2552 <1> ; 13/06/2022 - (lpt_init) 2553 0000508C [54520000] <1> dd ejec ; lpr, AX = 9 (runix) 2554 00005090 [E1500000] <1> dd ocvt ; tty0, AX = 10 (runix) 2555 <1> ;ocvt / tty0 2556 00005094 [E1500000] <1> dd ocvt ; tty1, AX = 11 (runix) 2557 <1> ;ocvt / tty1 2558 00005098 [E1500000] <1> dd ocvt ; tty2, AX = 12 (runix) 2559 <1> ;ocvt / tty2 2560 0000509C [E1500000] <1> dd ocvt ; tty3, AX = 13 (runix) 2561 <1> ;ocvt / tty3 2562 000050A0 [E1500000] <1> dd ocvt ; tty4, AX = 14 (runix) 2563 <1> ;ocvt / tty4 2564 000050A4 [E1500000] <1> dd ocvt ; tty5, AX = 15 (runix) 2565 <1> ;ocvt / tty5 2566 000050A8 [E1500000] <1> dd ocvt ; tty6, AX = 16 (runix) 2567 <1> ;ocvt / tty6 2568 000050AC [E1500000] <1> dd ocvt ; tty7, AX = 17 (runix) 2569 <1> ;ocvt / tty7 2570 000050B0 [E1500000] <1> dd ocvt ; COM1, AX = 18 (runix only) 2571 <1> ;error / crd 2572 000050B4 [E1500000] <1> dd ocvt ; COM2, AX = 19 (runix only) 2573 <1> 2574 <1> iopen_2: ; 2: / check open write access 2575 000050B8 66F7D8 <1> neg ax 2576 <1> ;neg r1 / make inode number positive 2577 000050BB B201 <1> mov dl, 1 ; write access 2578 000050BD E8F9F7FFFF <1> call access 2579 <1> ;jsr r0,access; 1 / get inode in core 2580 <1> ; DL=1 2581 <1> ; 11/01/2022 2582 000050C2 F605[E5610000]40 <1> test byte [i.flgs+1], 40h 2583 <1> ;test word [i.flgs], 4000h ; Bit 14 : Directory flag 2584 <1> ; bit $40000,i.flgs / is it a directory? 2585 000050C9 748C <1> jz short iopen_0 2586 <1> ;mov [u.error], ERR_DIR_ACCESS 2587 <1> ;jmp error ; permission denied ! 2588 000050CB E96BFFFFFF <1> jmp sysmnt_err0 2589 <1> ;;jnz error 2590 <1> ; bne 2f / yes, transfer (error) 2591 <1> ;;jmp short iopen_0 2592 <1> ;cmp ax, 40 2593 <1> ; cmp r1,$40. / no, is it a special file? 2594 <1> ;ja short iopen_2 2595 <1> ; bgt 3f / no, return 2596 <1> ;push ax 2597 <1> ; mov r1,-(sp) / yes 2598 <1> ;movzx ebx, al 2599 <1> ;shl bx, 1 2600 <1> ; asl r1 2601 <1> ;add ebx, ipen_3 - 2 2602 <1> ;jmp dword [ebx] 2603 <1> ; jmp *1f-2(r1) / figure out 2604 <1> ; / which special file it is and transfer 2605 <1> ;iopen_3: ; 1: 2606 <1> ; dd otty ; tty, AX = 1 (runix) 2607 <1> ;otty / tty ; r1=2 2608 <1> ;leadr / ppt ; r1=4 2609 <1> ; dd sret ; mem, AX = 2 (runix) 2610 <1> ;sret / mem ; r1=6 2611 <1> ;sret / rf0 2612 <1> ;sret / rk0 2613 <1> ;sret / tap0 2614 <1> ;sret / tap1 2615 <1> ;sret / tap2 2616 <1> ;sret / tap3 2617 <1> ;sret / tap4 2618 <1> ;sret / tap5 2619 <1> ;sret / tap6 2620 <1> ;sret / tap7 2621 <1> ; dd sret ; fd0, AX = 3 (runix only) 2622 <1> ; dd sret ; fd1, AX = 4 (runix only) 2623 <1> ; dd sret ; hd0, AX = 5 (runix only) 2624 <1> ; dd sret ; hd1, AX = 6 (runix only) 2625 <1> ; dd sret ; hd2, AX = 7 (runix only) 2626 <1> ; dd sret ; hd3, AX = 8 (runix only) 2627 <1> ; dd sret ; lpr, AX = 9 (runix) 2628 <1> ;dd ejec ; lpr, AX = 9 (runix) 2629 <1> ; dd sret ; tty0, AX = 10 (runix) 2630 <1> ;ocvt / tty0 2631 <1> ; dd sret ; tty1, AX = 11 (runix) 2632 <1> ;ocvt / tty1 2633 <1> ; dd sret ; tty2, AX = 12 (runix) 2634 <1> ;ocvt / tty2 2635 <1> ; dd sret ; tty3, AX = 13 (runix) 2636 <1> ;ocvt / tty3 2637 <1> ; dd sret ; tty4, AX = 14 (runix) 2638 <1> ;ocvt / tty4 2639 <1> ; dd sret ; tty5, AX = 15 (runix) 2640 <1> ;ocvt / tty5 2641 <1> ; dd sret ; tty6, AX = 16 (runix) 2642 <1> ;ocvt / tty6 2643 <1> ; dd sret ; tty7, AX = 17 (runix) 2644 <1> ;ocvt / tty7 2645 <1> ; dd ocvt ; COM1, AX = 18 (runix only) 2646 <1> ;/ ejec / lpr 2647 <1> ; dd ocvt ; COM2, AX = 19 (runix only) 2648 <1> 2649 <1> otty: ;/ open console tty for reading or writing 2650 <1> ; 03/03/2022 2651 <1> ; 02/03/2022 2652 <1> ; 26/02/2022 2653 <1> ; 09/02/2022 2654 <1> ; 06/02/2022 2655 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2656 <1> ; 16/11/2015 2657 <1> ; 12/11/2015 2658 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2659 <1> ; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1) 2660 <1> ; 16/07/2013 2661 <1> ; Retro UNIX 8086 v1 modification: 2662 <1> ; If a tty is open for read or write by 2663 <1> ; a process (u.uno), only same process can open 2664 <1> ; same tty to write or read (R->R&W or W->W&R). 2665 <1> ; 2666 <1> ; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty) 2667 <1> ; 2668 000050D0 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 2669 000050D7 8A83[43620000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 2670 <1> ; 13/01/2014 2671 <1> ;jmp short ottyp 2672 <1> ; 26/02/2022 2673 000050DD 88C4 <1> mov ah, al 2674 000050DF EB06 <1> jmp short ottypc ; ah = al = console tty number 2675 <1> ocvt: 2676 000050E1 2C0A <1> sub al, 10 2677 <1> ;ottyp: ; (call from sysstty) 2678 <1> ; 08/01/2022 2679 000050E3 31DB <1> xor ebx, ebx 2680 <1> ottyp: ; (ebx < 256) ; 06/02/2022 2681 <1> ; 26/02/2022 2682 000050E5 B4FF <1> mov ah, 0FFh 2683 <1> ottypc: 2684 <1> ; 03/03/2022 2685 <1> ; 26/02/2022 2686 <1> ; 09/02/2022 2687 <1> ; 08/01/2022 2688 <1> ; 16/11/2015 2689 <1> ; 12/11/2015 2690 <1> ; 18/05/2015 (32 bit modifications) 2691 <1> ; 06/12/2013 - 13/07/2014 2692 000050E7 88C6 <1> mov dh, al ; tty number 2693 <1> ;movzx ebx, al ; AL = tty number (0 to 9), AH = 0 2694 <1> ; 08/01/2022 2695 000050E9 88C3 <1> mov bl, al 2696 000050EB D0E3 <1> shl bl, 1 ; aligned to word 2697 <1> ; 26/01/2014 2698 000050ED 81C3[74610000] <1> add ebx, ttyl 2699 000050F3 668B0B <1> mov cx, [ebx] 2700 <1> ; CL = lock value (0 or process number) 2701 <1> ; CH = open count 2702 000050F6 20C9 <1> and cl, cl 2703 <1> ; 13/01/2014 2704 <1> ;jz short otty_ret 2705 <1> ; 08/01/2022 2706 000050F8 7447 <1> jz short ottys_0 2707 <1> ; 2708 <1> ; 16/11/2015 2709 000050FA 3A0D[3B650000] <1> cmp cl, [u.uno] 2710 00005100 746E <1> je short ottys_3 2711 <1> ; 2712 <1> ; 2713 <1> ; 26/02/2022 2714 <1> ; (is it the console tty of the current process?) 2715 <1> ; ((fast check/permit for console tty open function)) 2716 00005102 38E0 <1> cmp al, ah ; cmp dh, ah 2717 00005104 746A <1> je short ottys_3 ; bypass parent process check 2718 <1> ; 2719 <1> ; 26/02/2022 2720 <1> ;movzx ebx, cl ; the process which has locked the tty 2721 <1> ;shl bl, 1 2722 <1> ;mov ax, [ebx+p.pid-2] 2723 <1> ;;movzx ebx, byte [u.uno] 2724 <1> ;mov bl, [u.uno] 2725 <1> ;shl bl, 1 2726 <1> ;cmp ax, [ebx+p.ppid-2] 2727 <1> ;je short ottys_3 ; 16/11/2015 2728 <1> ; 26/02/2022 (BugFix) ; * 2729 00005106 0FB6F1 <1> movzx esi, cl ; the process which has locked the tty 2730 00005109 D1E6 <1> shl esi, 1 2731 0000510B 668B86[02620000] <1> mov ax, [esi+p.pid-2] 2732 00005112 96 <1> xchg esi, eax 2733 00005113 A0[3B650000] <1> mov al, [u.uno] 2734 00005118 D0E0 <1> shl al, 1 2735 0000511A 663BB0[22620000] <1> cmp si, [eax+p.ppid-2] 2736 00005121 744D <1> je short ottys_3 ; * 2737 <1> ; 26/02/2022 2738 <1> ; check console tty of the process 2739 <1> ; (open permission must be given if the -requested- tty is 2740 <1> ; console tty of current process) 2741 00005123 D0E8 <1> shr al, 1 2742 00005125 38B0[43620000] <1> cmp [eax+p.ttyc-1], dh ; console tty ? 2743 0000512B 7443 <1> je short ottys_3 2744 <1> ; 2745 <1> ; the tty is locked by another process 2746 <1> ; except the parent process (p.ppid) 2747 <1> ; 2748 <1> ; 09/02/2022 2749 <1> ;mov dword [u.error], ERR_DEV_ACCESS 2750 <1> ; ; permission denied ! error 2751 <1> otty_err: ; 13/01/2014 2752 <1> ;or dl, dl ; DL = 0 -> called by sysstty 2753 <1> ;;jnz error 2754 <1> ; 05/12/2021 2755 <1> ;jz short otty_stc_retn 2756 <1> ;jmp error 2757 <1> ; 09/02/2022 2758 0000512D 80FA01 <1> cmp dl, 1 ; dl = 0 ? 2759 00005130 7257 <1> jb short otty_retn ; yes, cf=1, called by sysstty 2760 <1> ; iopen (dl=1 or dl=2) 2761 00005132 C705[41650000]0B00- <1> mov dword [u.error], ERR_DEV_ACCESS 2761 0000513A 0000 <1> 2762 <1> ; permission denied ! error 2763 0000513C E98ADFFFFF <1> jmp error 2764 <1> ;otty_stc_retn: 2765 <1> ;stc 2766 <1> ;retn 2767 <1> ottys_0: 2768 <1> ; 08/01/2022 2769 <1> otty_ret: 2770 <1> ; 13/01/2014 2771 00005141 80FE07 <1> cmp dh, 7 2772 00005144 7624 <1> jna short ottys_2 2773 <1> ; 16/11/2015 2774 <1> com_port_check: 2775 00005146 BE[92610000] <1> mov esi, com1p 2776 0000514B 80FE08 <1> cmp dh, 8 ; COM1 (tty8) ? 2777 0000514E 7601 <1> jna short ottys_1 ; yes, it is COM1 2778 00005150 46 <1> inc esi ; no, it is COM2 (tty9) 2779 <1> ottys_1: 2780 <1> ; 12/11/2015 2781 00005151 803E00 <1> cmp byte [esi], 0 ; E3h (or 23h) 2782 00005154 7714 <1> ja short com_port_ready 2783 <1> ; 2784 <1> ; 09/02/2022 2785 00005156 80FA01 <1> cmp dl, 1 ; dl = 0 ? 2786 00005159 722E <1> jb short otty_retn ; yes, cf=1, called by sysstty 2787 0000515B C705[41650000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY 2787 00005163 0000 <1> 2788 <1> ; device not ready ! error 2789 <1> ;jmp short otty_err 2790 00005165 E961DFFFFF <1> jmp error 2791 <1> com_port_ready: 2792 <1> ottys_2: 2793 <1> ; 02/03/2022 2794 <1> ;or cl, cl ; cl = lock/owner, ch = open count 2795 <1> ;jnz short ottys_3 2796 0000516A 8A0D[3B650000] <1> mov cl, [u.uno] 2797 <1> ottys_3: 2798 00005170 FEC5 <1> inc ch 2799 00005172 66890B <1> mov [ebx], cx ; set tty lock again 2800 <1> ; 06/12/2013 2801 00005175 FEC6 <1> inc dh ; tty number + 1 2802 00005177 BB[1C650000] <1> mov ebx, u.ttyp 2803 <1> ; 13/01/2014 2804 0000517C F6C202 <1> test dl, 2 ; open for read sign 2805 0000517F 7501 <1> jnz short ottys_4 2806 00005181 43 <1> inc ebx 2807 <1> ottys_4: 2808 <1> ; Set 'u.ttyp' ('the recent TTY') value 2809 00005182 8833 <1> mov [ebx], dh ; tty number + 1 2810 <1> ; 09/02/2022 2811 00005184 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 2812 00005186 7401 <1> jz short otty_retn ; 03/03/2022 2813 <1> sret: 2814 <1> ;pop ax 2815 00005188 58 <1> pop eax ; 08/01/2022 2816 <1> otty_retn: ; 09/02/2022 2817 <1> iclose_retn: 2818 00005189 C3 <1> retn 2819 <1> 2820 <1> ; 2821 <1> ; Original UNIX v1 'otty' routine: 2822 <1> ; 2823 <1> ;mov $100,*$tks / set interrupt enable bit (zero others) in 2824 <1> ; / reader status reg 2825 <1> ;mov $100,*$tps / set interrupt enable bit (zero others) in 2826 <1> ; / punch status reg 2827 <1> ;mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the 2828 <1> ; / console tty buffer 2829 <1> ;incb (r5) / increment the count of processes that opened the 2830 <1> ; / console tty 2831 <1> ;tst u.ttyp / is there a process control tty (i.e., has a tty 2832 <1> ; / buffer header 2833 <1> ;bne sret / address been loaded into u.ttyp yet)? yes, branch 2834 <1> ;mov r5,u.ttyp / no, make the console tty the process control 2835 <1> ; / tty 2836 <1> ;br sret / ? 2837 <1> ;sret: 2838 <1> ;clr *$ps / set processor priority to zero 2839 <1> ; pop ax 2840 <1> ;mov (sp)+,r1 / pop stack to r1 2841 <1> ;3: 2842 <1> ; retn 2843 <1> ;rts r0 2844 <1> 2845 <1> ;ocvt: ; < open tty > 2846 <1> ; 13/01/2014 2847 <1> ; 06/12/2013 (major modification: p.ttyc, u.ttyp) 2848 <1> ; 24/09/2013 consistency check -> ok 2849 <1> ; 16/09/2013 2850 <1> ; 03/09/2013 2851 <1> ; 27/08/2013 2852 <1> ; 16/08/2013 2853 <1> ; 16/07/2013 2854 <1> ; 27/05/2013 2855 <1> ; 21/05/2013 2856 <1> ; 2857 <1> ; Retro UNIX 8086 v1 modification ! 2858 <1> ; 2859 <1> ; In original UNIX v1, 'ocvt' routine 2860 <1> ; (exactly different than this one) 2861 <1> ; was in 'u9.s' file. 2862 <1> ; 2863 <1> ; 16/07/2013 2864 <1> ; Retro UNIX 8086 v1 modification: 2865 <1> ; If a tty is open for read or write by 2866 <1> ; a process (u.uno), only same process can open 2867 <1> ; same tty to write or read (R->R&W or W->W&R). 2868 <1> ; 2869 <1> ; INPUT: DL=2 for Read DL=1 for Write 2870 <1> 2871 <1> ; 16/09/2013 2872 <1> ; sub al, 10 2873 <1> 2874 <1> ; 06/12/2013 2875 <1> ;cmp al, 7 2876 <1> ;jna short ottyp 2877 <1> ; 13/01/2014 2878 <1> ;jmp short ottyp 2879 <1> 2880 <1> ;oppt: / open paper tape for reading or writing 2881 <1> ; mov $100,*$prs / set reader interrupt enable bit 2882 <1> ; tstb pptiflg / is file already open 2883 <1> ; bne 2f / yes, branch 2884 <1> ;1: 2885 <1> ; mov $240,*$ps / no, set processor priority to 5 2886 <1> ; jsr r0,getc; 2 / remove all entries in clist 2887 <1> ; br .+4 / for paper tape input and place in free list 2888 <1> ; br 1b 2889 <1> ; movb $2,pptiflg / set pptiflg to indicate file just open 2890 <1> ; movb $10.,toutt+1 / place 10 in paper tape input tout entry 2891 <1> ; br sret 2892 <1> ;2: 2893 <1> ; jmp error / file already open 2894 <1> 2895 <1> iclose: 2896 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2897 <1> ; 19/05/2015 2898 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 2899 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 2900 <1> ; 2901 <1> ; close file whose i-number is in r1 2902 <1> ; 2903 <1> ; INPUTS -> 2904 <1> ; r1 - inode number 2905 <1> ; OUTPUTS -> 2906 <1> ; file's inode in core 2907 <1> ; r1 - inode number (positive) 2908 <1> ; 2909 <1> ; ((AX = R1)) 2910 <1> ; ((Modified registers: -ebx-, edx)) 2911 <1> ; 2912 <1> ;/ close file whose i-number is in r1 2913 0000518A B202 <1> mov dl, 2 ; 12/01/2014 2914 0000518C F6C480 <1> test ah, 80h ; Bit 15 of AX 2915 <1> ; tst r1 / test i-number 2916 <1> ;jnz short iclose_2 2917 <1> ; blt 2f / if neg., branch 2918 0000518F 7405 <1> jz short iclose_0 ; 30/07/2013 2919 <1> ; 16/07/2013 2920 00005191 66F7D8 <1> neg ax ; make it positive 2921 <1> ; 12/01/2014 2922 00005194 FECA <1> dec dl ; dl = 1 (open for write) 2923 <1> iclose_0: 2924 00005196 6683F828 <1> cmp ax, 40 2925 <1> ; cmp r1,$40. / is it a special file 2926 0000519A 77ED <1> ja short iclose_retn ; 13/01/2014 2927 <1> ; bgt 3b / no, return 2928 <1> ; 12/01/2014 2929 <1> ; DL=2 -> special file was opened for reading 2930 <1> ; DL=1 -> special file was opened for writing 2931 0000519C 50 <1> push eax ; 08/01/2022 2932 <1> ;push ax 2933 <1> ; mov r1,-(sp) / yes, save r1 on stack 2934 0000519D 0FB6D8 <1> movzx ebx, al 2935 <1> ; 08/01/2022 2936 000051A0 C0E302 <1> shl bl, 2 2937 <1> ;shl bx, 2 2938 <1> ; asl r1 2939 000051A3 81C3[A7510000] <1> add ebx, iclose_1 - 4 2940 000051A9 FF23 <1> jmp dword [ebx] 2941 <1> ; jmp *1f-2(r1) / compute jump address and transfer 2942 <1> iclose_1 : 2943 000051AB [F7510000] <1> dd ctty ; tty, AX = 1 (runix) 2944 000051AF [52520000] <1> dd cret ; mem, AX = 2 (runix) 2945 000051B3 [52520000] <1> dd cret ; fd0, AX = 3 (runix only) 2946 000051B7 [52520000] <1> dd cret ; fd1, AX = 4 (runix only) 2947 000051BB [52520000] <1> dd cret ; hd0, AX = 5 (runix only) 2948 000051BF [52520000] <1> dd cret ; hd1, AX = 6 (runix only) 2949 000051C3 [52520000] <1> dd cret ; hd2, AX = 7 (runix only) 2950 000051C7 [52520000] <1> dd cret ; hd3, AX = 8 (runix only) 2951 000051CB [52520000] <1> dd cret ; lpr, AX = 9 (runix) 2952 <1> ;dd error; lpr, AX = 9 (error !) 2953 <1> ;;dd offset ejec ;;lpr, AX = 9 2954 000051CF [06520000] <1> dd ccvt ; tty0, AX = 10 (runix) 2955 000051D3 [06520000] <1> dd ccvt ; tty1, AX = 11 (runix) 2956 000051D7 [06520000] <1> dd ccvt ; tty2, AX = 12 (runix) 2957 000051DB [06520000] <1> dd ccvt ; tty3, AX = 13 (runix) 2958 000051DF [06520000] <1> dd ccvt ; tty4, AX = 14 (runix) 2959 000051E3 [06520000] <1> dd ccvt ; tty5, AX = 15 (runix) 2960 000051E7 [06520000] <1> dd ccvt ; tty6, AX = 16 (runix) 2961 000051EB [06520000] <1> dd ccvt ; tty7, AX = 17 (runix) 2962 000051EF [06520000] <1> dd ccvt ; COM1, AX = 18 (runix only) 2963 000051F3 [06520000] <1> dd ccvt ; COM2, AX = 19 (runix only) 2964 <1> 2965 <1> ; 1: 2966 <1> ; ctty / tty 2967 <1> ; cppt / ppt 2968 <1> ; sret / mem 2969 <1> ; sret / rf0 2970 <1> ; sret / rk0 2971 <1> ; sret / tap0 2972 <1> ; sret / tap1 2973 <1> ; sret / tap2 2974 <1> ; sret / tap3 2975 <1> ; sret / tap4 2976 <1> ; sret / tap5 2977 <1> ; sret / tap6 2978 <1> ; sret / tap7 2979 <1> ; ccvt / tty0 2980 <1> ; ccvt / tty1 2981 <1> ; ccvt / tty2 2982 <1> ; ccvt / tty3 2983 <1> ; ccvt / tty4 2984 <1> ; ccvt / tty5 2985 <1> ; ccvt / tty6 2986 <1> ; ccvt / tty7 2987 <1> ; error / crd 2988 <1> 2989 <1> ;iclose_2: ; 2: / negative i-number 2990 <1> ;neg ax 2991 <1> ;neg r1 / make it positive 2992 <1> ;cmp ax, 40 2993 <1> ;cmp r1,$40. / is it a special file? 2994 <1> ;ja short @b 2995 <1> ;bgt 3b / no. return 2996 <1> ;push ax 2997 <1> ;mov r1,-(sp) 2998 <1> ;movzx ebx, al 2999 <1> ;shl bx, 1 3000 <1> ;asl r1 / yes. compute jump address and transfer 3001 <1> ;add ebx, iclose_3 - 2 3002 <1> ;jmp dword [ebx] 3003 <1> ;jmp *1f-2(r1) / figure out 3004 <1> ;iclose_3: 3005 <1> ;dd ctty ; tty, AX = 1 (runix) 3006 <1> ;dd sret ; mem, AX = 2 (runix) 3007 <1> ;dd sret ; fd0, AX = 3 (runix only) 3008 <1> ;dd sret ; fd1, AX = 4 (runix only) 3009 <1> ;dd sret ; hd0, AX = 5 (runix only) 3010 <1> ;dd sret ; hd1, AX = 6 (runix only) 3011 <1> ;dd sret ; hd2, AX = 7 (runix only) 3012 <1> ;dd sret ; hd3, AX = 8 (runix only) 3013 <1> ;dd sret ; lpr, AX = 9 3014 <1> ;dd ejec ; lpr, AX = 9 (runix) 3015 <1> ;dd ccvt ; tty0, AX = 10 (runix) 3016 <1> ;dd ccvt ; tty1, AX = 11 (runix) 3017 <1> ;dd ccvt ; tty2, AX = 12 (runix) 3018 <1> ;dd ccvt ; tty3, AX = 13 (runix) 3019 <1> ;dd ccvt ; tty4, AX = 14 (runix) 3020 <1> ;dd ccvt ; tty5, AX = 15 (runix) 3021 <1> ;dd ccvt ; tty6, AX = 16 (runix) 3022 <1> ;dd ccvt ; tty7, AX = 17 (runix) 3023 <1> ;dd ccvt ; COM1, AX = 18 (runix only) 3024 <1> ;dd ccvt ; COM2, AX = 19 (runix only) 3025 <1> 3026 <1> ;1: 3027 <1> ; ctty / tty 3028 <1> ; leadr / ppt 3029 <1> ; sret / mem 3030 <1> ; sret / rf0 3031 <1> ; sret / rk0 3032 <1> ; sret / tap0 3033 <1> ; sret / tap1 3034 <1> ; sret / tap2 3035 <1> ; sret / tap3 3036 <1> ; sret / tap4 3037 <1> ; sret / tap5 3038 <1> ; sret / tap6 3039 <1> ; sret / tap7 3040 <1> ; ccvt / tty0 3041 <1> ; ccvt / tty1 3042 <1> ; ccvt / tty2 3043 <1> ; ccvt / tty3 3044 <1> ; ccvt / tty4 3045 <1> ; ccvt / tty5 3046 <1> ; ccvt / tty6 3047 <1> ; ccvt / tty7 3048 <1> ;/ ejec / lpr 3049 <1> 3050 <1> ctty: ; / close console tty 3051 <1> ; 26/02/2022 3052 <1> ; 09/02/2022 3053 <1> ; 06/02/2022 3054 <1> ; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 3055 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 3056 <1> ; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1) 3057 <1> ; 3058 <1> ; Retro UNIX 8086 v1 modification ! 3059 <1> ; (DL = 2 -> it is open for reading) 3060 <1> ; (DL = 1 -> it is open for writing) 3061 <1> ; (DL = 0 -> it is open for sysstty system call) 3062 <1> ; 3063 <1> ; 06/12/2013 3064 000051F7 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 3065 000051FE 8A83[43620000] <1> mov al, [ebx+p.ttyc-1] 3066 <1> ; 13/01/2014 3067 <1> ;jmp short cttyp 3068 <1> ; 06/02/2022 3069 00005204 EB04 <1> jmp short ctty_0 3070 <1> ccvt: 3071 00005206 2C0A <1> sub al, 10 3072 <1> cttyp: ; (call from sysstty) 3073 <1> ; 08/01/2022 3074 00005208 31DB <1> xor ebx, ebx 3075 <1> ctty_0: ; (ebx < 256) ; 06/02/2022 3076 <1> ; 08/01/2022 3077 <1> ; 18/05/2015 (32 bit modifications) 3078 <1> ; 16/08/2013 - 26/01/2014 3079 <1> ;movzx ebx, al ; tty number (0 to 9) 3080 <1> ; 08/01/2022 3081 0000520A 88C3 <1> mov bl, al 3082 0000520C D0E3 <1> shl bl, 1 ; aligned to word 3083 <1> ; 26/01/2014 3084 0000520E 81C3[74610000] <1> add ebx, ttyl 3085 00005214 88C6 <1> mov dh, al ; tty number 3086 00005216 668B03 <1> mov ax, [ebx] 3087 <1> ; AL = lock value (0 or process number) 3088 <1> ; AH = open count 3089 00005219 20E4 <1> and ah, ah 3090 0000521B 7514 <1> jnz short ctty_ret 3091 <1> ; 09/02/2022 3092 0000521D 80FA01 <1> cmp dl, 1 ; DL = 0 -> called by sysstty 3093 00005220 7231 <1> jb short ctty_stc_retn ; cf=1 3094 <1> ; iclose (dl=1 or dl=2) 3095 00005222 C705[41650000]0A00- <1> mov dword [u.error], ERR_DEV_NOT_OPEN 3095 0000522A 0000 <1> 3096 <1> ; device not open ! error 3097 <1> ;jmp short ctty_err ; open count = 0, it is not open ! 3098 0000522C E99ADEFFFF <1> jmp error 3099 <1> ; 26/01/2014 3100 <1> ctty_ret: 3101 00005231 FECC <1> dec ah ; decrease open count 3102 00005233 7502 <1> jnz short ctty_1 3103 00005235 30C0 <1> xor al, al ; unlock/free tty 3104 <1> ctty_1: 3105 00005237 668903 <1> mov [ebx], ax ; close tty instance 3106 <1> ; 3107 0000523A BB[1C650000] <1> mov ebx, u.ttyp 3108 <1> ;test dl, 1 ; open for write sign 3109 <1> ;jz short ctty_2 3110 <1> ; 26/02/2022 3111 0000523F F6C202 <1> test dl, 2 ; open for read sign 3112 00005242 7501 <1> jnz short ctty_2 3113 00005244 43 <1> inc ebx 3114 <1> ctty_2: 3115 00005245 FEC6 <1> inc dh ; tty number + 1 3116 00005247 3A33 <1> cmp dh, [ebx] 3117 <1> ;jne short cret 3118 00005249 7503 <1> jne short ctty_3 ; 09/02/2022 3119 <1> ; Reset/Clear 'u.ttyp' ('the recent TTY') value 3120 0000524B C60300 <1> mov byte [ebx], 0 3121 <1> ctty_3: 3122 <1> ; 09/02/2022 3123 0000524E 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 3124 00005250 7401 <1> jz short ctty_4 3125 <1> cret: 3126 <1> ;pop ax 3127 <1> ; 08/01/2022 3128 00005252 58 <1> pop eax 3129 <1> ctty_stc_retn: ; 09/02/2022 3130 <1> ctty_4: 3131 00005253 C3 <1> retn 3132 <1> 3133 <1> ;ctty_err: ; 13/01/2014 3134 <1> ; or dl, dl ; DL = 0 -> called by sysstty 3135 <1> ; jnz error 3136 <1> ; stc 3137 <1> ; retn 3138 <1> 3139 <1> ; Original UNIX v1 'ctty' routine: 3140 <1> ; 3141 <1> ;mov tty+[ntty*8]-8+6,r5 3142 <1> ; ;/ point r5 to the console tty buffer 3143 <1> ;decb (r5) / dec number of processes using console tty 3144 <1> ;br sret / return via sret 3145 <1> 3146 <1> ;ccvt: ; < close tty > 3147 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 3148 <1> ; 3149 <1> ; Retro UNIX 8086 v1 modification ! 3150 <1> ; 3151 <1> ; In original UNIX v1, 'ccvt' routine 3152 <1> ; (exactly different than this one) 3153 <1> ; was in 'u9.s' file. 3154 <1> ; 3155 <1> ; DL = 2 -> it is open for reading 3156 <1> ; DL = 1 -> it is open for writing 3157 <1> ; 3158 <1> ; 17/09/2013 3159 <1> ;sub al, 10 3160 <1> ;cmp al, 7 3161 <1> ;jna short cttyp 3162 <1> ; 13/01/2014 3163 <1> ;jmp short cttyp 3164 <1> 3165 <1> ;cppt: / close paper tape 3166 <1> ; clrb pptiflg / set pptiflg to indicate file not open 3167 <1> ;1: 3168 <1> ; mov $240,*$ps /set process or priority to 5 3169 <1> ; jsr r0,getc; 2 / remove all ppt input entries from clist 3170 <1> ; / and assign to free list 3171 <1> ; br sret 3172 <1> ; br 1b 3173 <1> 3174 <1> ;ejec: 3175 <1> ; jmp error 3176 <1> ;/ejec: 3177 <1> ;/ mov $100,*$lps / set line printer interrupt enable bit 3178 <1> ;/ mov $14,r1 / 'form feed' character in r1 (new page). 3179 <1> ;/ jsr r0,lptoc / space the printer to a new page 3180 <1> ;/ br sret / return to caller via 'sret' 3181 <1> 3182 <1> ejec: 3183 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 3184 <1> ; - Printer Initialization 3185 <1> lpt_init: 3186 <1> ; Ref: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 3187 <1> ; 3188 <1> ; Default printer port: 378h ; LPT1 3189 <1> 3190 00005254 B401 <1> mov ah, 1 ; INITIALIZE THE PRINTER PORT 3191 <1> ;call int17h 3192 00005256 E8BDFAFFFF <1> call PRNOP 3193 0000525B 7414 <1> jz short lpt_init_ok 3194 <1> 3195 <1> ; replace error code with 'device not ready' error 3196 <1> ; (this may be better for 'sysopen') 3197 0000525D B80F000000 <1> mov eax, ERR_PRN_NOT_RDY 3198 00005262 A3[41650000] <1> mov [u.error], eax 3199 <1> ;jmp sysret ; (may be) ? ([u.r0] = file descriptor) 3200 00005267 A3[EC640000] <1> mov [u.r0], eax 3201 0000526C E95ADEFFFF <1> jmp error ; (better) 3202 <1> 3203 <1> lpt_init_ok: 3204 <1> ;jmp short cret 3205 00005271 58 <1> pop eax ; inode number 3206 00005272 C3 <1> retn 3207 <1> 2121 %include 'u8.s' ; 11/06/2015 2122 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYS8.INC 2123 <1> ; Last Modification: 19/07/2022 2124 <1> ; ---------------------------------------------------------------------------- 2125 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2126 <1> ; (v0.1 - Beginning: 11/07/2012) 2127 <1> ; 2128 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2129 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2130 <1> ; 2131 <1> ; 2132 <1> ; 2133 <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s 2134 <1> ; 2135 <1> ; **************************************************************************** 2136 <1> 2137 <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2138 <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2139 <1> ;--------------------------------------------------------------------- 2140 <1> ; Buffer Header: -8 bytes- 2141 <1> ; word 1 - byte 0 - device (disk index) number (0 to 5) 2142 <1> ; byte 1 - status bits 2143 <1> ; bit 0 - valid buffer bit (1 = valid, 0 = invalid, new) 2144 <1> ; bit 1 - write bit (also modified bit) 2145 <1> ; bit 2 - read bit 2146 <1> ; bit 3 to bit 7 are not used 2147 <1> ; word 2 - byte & byte 3 not used 2148 <1> ; word 3 & word 4 - byte 3, byte 5, byte 6, byte 7: 2149 <1> ; physical block/sector address (32 bit LBA) 2150 <1> ;--------------------------------------------------------------------- 2151 <1> 2152 <1> ;; I/O Buffer - Retro UNIX 386 v1 modification 2153 <1> ;; (8+512 bytes, 8 bytes header, 512 bytes data) 2154 <1> ;; Word 1, byte 0 = device id 2155 <1> ;; Word 1, byte 1 = status bits (bits 8 to 15) 2156 <1> ;; bit 9 = write bit 2157 <1> ;; bit 10 = read bit 2158 <1> ;; bit 12 = waiting to write bit 2159 <1> ;; bit 13 = waiting to read bit 2160 <1> ;; bit 15 = inhibit bit 2161 <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015) 2162 <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 2163 <1> ;; (In fact, it is 32 bit LBA for Retro UNIX 386 v1) 2164 <1> ;; 2165 <1> ;; I/O Buffer ((8+512 bytes in original Unix v1)) 2166 <1> ;; ((4+512 bytes in Retro UNIX 8086 v1)) 2167 <1> ;; 2168 <1> ;; I/O Queue Entry (of original UNIX operating system v1) 2169 <1> ;; Word 1, Byte 0 = device id 2170 <1> ;; Word 1, Byte 1 = (bits 8 to 15) 2171 <1> ;; bit 9 = write bit 2172 <1> ;; bit 10 = read bit 2173 <1> ;; bit 12 = waiting to write bit 2174 <1> ;; bit 13 = waiting to read bit 2175 <1> ;; bit 15 = inhibit bit 2176 <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) 2177 <1> ;; 2178 <1> ;; Original UNIX v1 -> 2179 <1> ;; Word 3 = number of words in buffer (=256) 2180 <1> ;; Original UNIX v1 -> 2181 <1> ;; Word 4 = bus address (addr of first word of data buffer) 2182 <1> ;; 2183 <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! 2184 <1> ;; 2185 <1> ;; Device IDs (of Retro Unix 8086 v1) 2186 <1> ;; 0 = fd0 2187 <1> ;; 1 = fd1 2188 <1> ;; 2 = hd0 2189 <1> ;; 3 = hd1 2190 <1> ;; 4 = hd2 2191 <1> ;; 5 = hd3 2192 <1> 2193 <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015 2194 <1> 2195 <1> ; 08/02/2022 2196 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2197 <1> rfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2198 <1> ; 26/04/2013 2199 <1> ; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2200 <1> ;sub ax, 3 ; zero based device number (Floppy disk) 2201 <1> ;jmp short bread ; **** returns to routine that called readi 2202 <1> 2203 <1> ; 08/02/2022 2204 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2205 <1> rhd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2206 <1> ; 26/04/2013 2207 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2208 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2209 <1> ;jmp short bread ; **** returns to routine that called readi 2210 <1> 2211 <1> bread: 2212 <1> ; 19/07/2022 2213 <1> ; 15/07/2022 2214 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2215 <1> ; 08/02/2022 2216 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2217 <1> ; 14/07/2015 2218 <1> ; 10/07/2015 2219 <1> ; 09/06/2015 2220 <1> ; 07/06/2015 (Retro UNIX 386 v1 - Beginning) 2221 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2222 <1> ; 2223 <1> ; / read a block from a block structured device 2224 <1> ; 2225 <1> ; INPUTS -> 2226 <1> ; [u.fofp] points to the block number 2227 <1> ; ECX = maximum block number allowed on device 2228 <1> ; ; that was an arg to bread, in original Unix v1, but 2229 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 2230 <1> ; [u.count] number of bytes to read in 2231 <1> ; OUTPUTS -> 2232 <1> ; [u.base] starting address of data block or blocks in user area 2233 <1> ; [u.fofp] points to next consecutive block to be read 2234 <1> ; 2235 <1> ; ((Modified registers: EAX, EDX, ECX, EBX, ESI, EDI)) 2236 <1> ; 2237 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if read 2238 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 2239 <1> ; is increased by 1. For example: If user/program request 2240 <1> ; to read 16 bytes in current block, 'sys read' increases 2241 <1> ; the next block number just as 512 byte reading is done. 2242 <1> ; This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 2243 <1> ; for user (u) structure compatibility (because 16 bit is not 2244 <1> ; enough to keep byte position/offset of the disk), this 2245 <1> ; defect will not be corrected, user/program must request 2246 <1> ; 512 byte read per every 'sys read' call to block devices 2247 <1> ; for achieving correct result. In future version(s), 2248 <1> ; this defect will be corrected by using different 2249 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 2250 <1> 2251 <1> ; jsr r0,tstdeve / error on special file I/O 2252 <1> ; / (only works on tape) 2253 <1> ; mov *u.fofp,r1 / move block number to r1 2254 <1> ; mov $2.-cold,-(sp) / "2-cold" to stack 2255 <1> ;1: 2256 <1> ; cmp r1,(r0) / is this block # greater than or equal to 2257 <1> ; / maximum block # allowed on device 2258 <1> ; jnb short @f 2259 <1> ; bhis 1f / yes, 1f (error) 2260 <1> ; mov r1,-(sp) / no, put block # on stack 2261 <1> ; jsr r0,preread / read in the block into an I/O buffer 2262 <1> ; mov (sp)+,r1 / return block # to r1 2263 <1> ; inc r1 / bump block # to next consecutive block 2264 <1> ; dec (sp) / "2-1-cold" on stack 2265 <1> ; bgt 1b / 2-1-cold = 0? No, go back and read in next block 2266 <1> ;1: 2267 <1> ; tst (sp)+ / yes, pop stack to clear off cold calculation 2268 <1> ;push ecx ; ** 2269 <1> ; 26/04/2013 2270 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 2271 00005273 2C03 <1> sub al, 3 2272 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 2273 00005275 A2[54650000] <1> mov [u.brwdev], al 2274 <1> ; 09/06/2015 2275 <1> ;movzx ebx, al 2276 <1> ;mov ecx, [ebx+drv.size] ; disk size (in sectors) 2277 <1> ; 12/01/2022 (BugFix) 2278 0000527A C0E002 <1> shl al, 2 ; * 4 2279 0000527D 8B88[525C0000] <1> mov ecx, [eax+drv.size] ; disk size (in sectors) 2280 <1> bread_0: 2281 00005283 51 <1> push ecx ; ** ; 09/06/2015 2282 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 2283 <1> ; [u.fofp] points to byte position in disk, not sector/block ! 2284 00005284 8B1D[FC640000] <1> mov ebx, [u.fofp] 2285 0000528A 8B03 <1> mov eax, [ebx] 2286 0000528C C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 2287 <1> ; mov *u.fofp,r1 / restore r1 to initial value of the 2288 <1> ; / block # 2289 0000528F 39C8 <1> cmp eax, ecx 2290 <1> ; cmp r1,(r0)+ / block # greater than or equal to maximum 2291 <1> ; / block number allowed 2292 <1> ;jnb error ; 18/04/2013 2293 <1> ; bhis error10 / yes, error 2294 <1> ; 08/02/2022 2295 <1> ;jb short bread_1 2296 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2297 <1> ;jmp error 2298 00005291 7346 <1> jnb short brw_oov_err ; 'out of volume' error 2299 <1> bread_1: 2300 <1> ;inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 2301 <1> ; inc *u.fofp / no, *u.fofp has next block number 2302 <1> ; EAX = Block number (zero based) 2303 <1> ;;jsr r0,preread / read in the block whose number is in r1 2304 <1> preread: ;; call preread 2305 00005293 BF[54650000] <1> mov edi, u.brwdev ; block device number for direct I/O 2306 00005298 E8DC010000 <1> call bufaloc_0 ; 26/04/2013 2307 <1> ;; jc error 2308 <1> ; EBX = Buffer (Header) Address -Physical- 2309 <1> ; EAX = Block/Sector number (r1) 2310 <1> ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number) 2311 <1> ; 14/03/2013 2312 0000529D 7411 <1> jz short bread_2 ; Retro UNIX 8086 v1 modification 2313 <1> ; br 1f / branch if block already in a I/O buffer 2314 0000529F 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 2315 <1> ; bis $2000,(r5) / set read bit (bit 10 in I/O buffer) 2316 000052A4 E8A8010000 <1> call poke 2317 <1> ; jsr r0,poke / perform the read 2318 <1> ;;jc error ;2 0/07/2013 2319 <1> ; 1: 2320 <1> ; clr *$ps / ps = 0 2321 <1> ; rts r0 2322 <1> ; 08/02/2022 2323 000052A9 7305 <1> jnc short bread_2 2324 000052AB E919010000 <1> jmp dskrd_err 2325 <1> ; 2326 <1> ;; return from preread 2327 <1> bread_2: 2328 <1> ; 15/07/2022 2329 <1> ;or word [ebx], 4000h 2330 <1> ; ; bis $40000,(r5) 2331 <1> ; ; / set bit 14 of the 1st word of the I/O buffer 2332 <1> bread_3: ; 1: 2333 <1> ; 15/07/2022 2334 <1> ;test word [ebx], 2400h 2335 <1> ; ; bit $22000,(r5) / are 10th and 13th bits set (read bits) 2336 <1> ;jz short bread_4 2337 <1> ; ; beq 1f / no 2338 <1> ; ; cmp cdev,$1 / disk or drum? 2339 <1> ; ; ble 2f / yes 2340 <1> ; ; tstb uquant / is the time quantum = 0? 2341 <1> ; ; bne 2f / no, 2f 2342 <1> ; ; mov r5,-(sp) / yes, save r5 (buffer address) 2343 <1> ; ; jsr r0,sleep; 31. 2344 <1> ; ; / put process to sleep in channel 31 (tape) 2345 <1> ; ; mov (sp)+,r5 / restore r5 2346 <1> ; ; br 1b / go back 2347 <1> ; 2: / drum or disk 2348 <1> ;; mov cx, [s.wait_]+2 ;; 29/07/2013 2349 <1> ;call idle 2350 <1> ; ; jsr r0,idle; s.wait+2 / wait 2351 <1> ;jmp short bread_3 2352 <1> ; ; br 1b 2353 <1> bread_4: ; 1: / 10th and 13th bits not set 2354 <1> ;and word [ebx], 0BFFFh ; 1011111111111111b 2355 <1> ; ; bic $40000,(r5) / clear bit 14 2356 <1> ; ; jsr r0,tstdeve / test device for error (tape) 2357 <1> ; 15/07/2022 2358 000052B0 83C308 <1> add ebx, 8 2359 <1> ; add $8,r5 / r5 points to data in I/O buffer 2360 <1> ; 09/06/2015 2361 000052B3 66833D[51650000]00 <1> cmp word [u.pcount], 0 2362 000052BB 7705 <1> ja short bread_5 2363 000052BD E892F8FFFF <1> call trans_addr_w ; translate virtual address to physical (w) 2364 <1> bread_5: 2365 <1> ; EBX = system (I/O) buffer address 2366 000052C2 E87C000000 <1> call dioreg 2367 <1> ; jsr r0,dioreg / do bookkeeping on u.count etc. 2368 <1> 2369 <1> ; 19/07/2022 2370 <1> ; EDI = user data offset (previous value of [u.pbase]) 2371 <1> ; ESI = pointer to file offset 2372 <1> ; EAX = system (I/O) buffer offset (>= EBX) 2373 <1> ; ECX = byte count 2374 <1> ; EBX = system buffer (data) address 2375 <1> 2376 <1> ; 19/07/2022 2377 000052C7 010E <1> add [esi], ecx ; new file (disk) offset 2378 000052C9 89C6 <1> mov esi, eax 2379 <1> 2380 <1> ; esi = start address of the transfer (in the buffer) 2381 <1> ; edi = [u.pbase], destination address in user's memory space 2382 <1> ; ecx = transfer count (in bytes) 2383 <1> ; 2384 <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning 2385 <1> ; / of users data 2386 000052CB F3A4 <1> rep movsb 2387 <1> ; movb (r5)+,(r2)+ / move data from the I/O buffer 2388 <1> ; dec r3 / to the user's area in core starting at u.base 2389 <1> ; bne 1b 2390 000052CD 59 <1> pop ecx ; ** 2391 000052CE 833D[10650000]00 <1> cmp dword [u.count], 0 2392 <1> ; tst u.count / done 2393 000052D5 77AC <1> ja short bread_0 ; 09/06/2015 2394 <1> ; beq 1f / yes, return 2395 <1> ; tst -(r0) / no, point r0 to the argument again 2396 <1> ; br bread / read some more 2397 <1> ; 1: 2398 000052D7 58 <1> pop eax ; **** 2399 <1> ; mov (sp)+,r0 2400 000052D8 C3 <1> retn ; 09/06/2015 2401 <1> ;jmp ret_ 2402 <1> ;jmp ret / jump to routine that called readi 2403 <1> 2404 <1> ; 08/02/2022 2405 <1> brw_oov_err: 2406 000052D9 C705[41650000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2406 000052E1 0000 <1> 2407 000052E3 E9E3DDFFFF <1> jmp error 2408 <1> 2409 <1> ; 08/02/2022 2410 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2411 <1> wfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2412 <1> ; 26/04/2013 2413 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2414 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2415 <1> ;jmp short bwrite ; **** returns to routine that called writei 2416 <1> 2417 <1> ; 08/02/2022 2418 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2419 <1> whd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2420 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 2421 <1> ;sub ax, 3 ; zero based device number (Hard disk) 2422 <1> ;jmp short bwrite ; **** returns to routine that called writei ('jmp ret') 2423 <1> 2424 <1> bwrite: 2425 <1> ; 19/07/2022 2426 <1> ; (file offset bugfix for 'dskwr' error return situation) 2427 <1> ; 15/07/2022 2428 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2429 <1> ; 08/02/2022 2430 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2431 <1> ; 14/07/2015 2432 <1> ; 10/07/2015 2433 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2434 <1> ; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1) 2435 <1> ; 2436 <1> ;; / write on block structured device 2437 <1> ; 2438 <1> ; INPUTS -> 2439 <1> ; [u.fofp] points to the block number 2440 <1> ; ECX = maximum block number allowed on device 2441 <1> ; ; that was an arg to bwrite, in original Unix v1, but 2442 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 2443 <1> ; [u.count] number of bytes to user desires to write 2444 <1> ; OUTPUTS -> 2445 <1> ; [u.fofp] points to next consecutive block to be written into 2446 <1> ; 2447 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 2448 <1> ; 2449 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if write 2450 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 2451 <1> ; is increased by 1. For example: If user/program request 2452 <1> ; to write 16 bytes in current block, 'sys write' increases 2453 <1> ; the next block number just as 512 byte writing is done. 2454 <1> ; This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 2455 <1> ; for user (u) structure compatibility (because 16 bit is not 2456 <1> ; enough to keep byte position/offset of the disk), this 2457 <1> ; defect will not be corrected, user/program must request 2458 <1> ; 512 byte write per every 'sys write' call to block devices 2459 <1> ; for achieving correct result. In future version(s), 2460 <1> ; this defect will be corrected by using different 2461 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 2462 <1> 2463 <1> ; jsr r0,tstdeve / test the device for an error 2464 <1> ;push ecx ; ** 2465 <1> ; 26/04/2013 2466 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 2467 000052E8 2C03 <1> sub al, 3 2468 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 2469 000052EA A2[54650000] <1> mov [u.brwdev], al 2470 <1> ; 09/06/2015 2471 <1> ;movzx ebx, al 2472 <1> ;mov ecx, [ebx+drv.size] ; disk size (in sectors) 2473 <1> ; 12/01/2022 (BugFix) 2474 000052EF C0E002 <1> shl al, 2 ; * 4 2475 000052F2 8B88[525C0000] <1> mov ecx, [eax+drv.size] ; disk size (in sectors) 2476 <1> bwrite_0: 2477 000052F8 51 <1> push ecx ; ** ; 09/06/2015 2478 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 2479 <1> ; [u.fofp] points to byte position in disk, not sector/block ! 2480 000052F9 8B1D[FC640000] <1> mov ebx, [u.fofp] 2481 000052FF 8B03 <1> mov eax, [ebx] 2482 00005301 C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 2483 <1> ; mov *u.fofp,r1 / put the block number in r1 2484 00005304 39C8 <1> cmp eax, ecx 2485 <1> ; cmp r1,(r0)+ / does block number exceed maximum allowable # 2486 <1> ; / block number allowed 2487 <1> ;jnb error ; 18/04/2013 2488 <1> ; bhis error10 / yes, error 2489 <1> ; 08/02/2022 2490 <1> ;jb short bwrite_1 2491 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 2492 <1> ;jmp error 2493 00005306 73D1 <1> jnb short brw_oov_err ; 'out of volume' error 2494 <1> bwrite_1: 2495 <1> ;inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 2496 <1> ; inc *u.fofp / no, increment block number 2497 <1> ; 09/06/2015 - 10/07/2015 2498 00005308 66833D[51650000]00 <1> cmp word [u.pcount], 0 2499 00005310 7705 <1> ja short bwrite_2 2500 00005312 E839F8FFFF <1> call trans_addr_r ; translate virtual address to physical (r) 2501 <1> bwrite_2: 2502 00005317 BF[54650000] <1> mov edi, u.brwdev ; block device number for direct I/O 2503 0000531C E8C9000000 <1> call bwslot ; 26/04/2013 (wslot -> bwslot) 2504 <1> ; jsr r0,wslot / get an I/O buffer to write into 2505 <1> ; add $8,r5 / r5 points to data in I/O buffer 2506 00005321 E81D000000 <1> call dioreg 2507 <1> ; jsr r0,dioreg / do the necessary bookkeeping 2508 <1> 2509 <1> ; 19/07/2022 2510 <1> ; EDI = user data offset (previous value of [u.pbase]) 2511 <1> ; ESI = pointer to file offset 2512 <1> ; EAX = system (I/O) buffer offset (>= EBX) 2513 <1> ; ECX = byte count 2514 <1> ; EBX = system buffer (data) address 2515 <1> 2516 <1> ; 19/07/2022 - Erdogan Tan 2517 <1> ; ((Against a possible disk write failure/error, 2518 <1> ; file offset must not be updated/increased before 'dskwr' 2519 <1> ; but it was updated in 'dioreg'. I have modified 'dioreg' 2520 <1> ; and 'bwrite' procedures for that.)) 2521 <1> 2522 <1> ; 19/07/2022 2523 00005326 56 <1> push esi ; (!) ; save file offset (pointer) 2524 00005327 51 <1> push ecx ; (!!) ; save byte count 2525 <1> ;mov esi, eax 2526 <1> 2527 <1> ; esi = destination address (in the buffer) 2528 <1> ; edi = [u.pbase], start address of transfer in user's memory space 2529 <1> ; ecx = transfer count (in bytes) 2530 <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area 2531 <1> ;xchg esi, edi ; 14/07/2015 2532 <1> 2533 <1> ; 19/07/2022 2534 00005328 89FE <1> mov esi, edi 2535 0000532A 89C7 <1> mov edi, eax 2536 <1> 2537 0000532C F3A4 <1> rep movsb 2538 <1> ; movb (r2)+,(r5)+ / ; r3, has the byte count 2539 <1> ; dec r3 / area to the I/O buffer 2540 <1> ; bne 1b 2541 <1> 2542 0000532E E8F0000000 <1> call dskwr 2543 <1> ; jsr r0,dskwr / write it out on the device 2544 <1> 2545 <1> ; 19/07/2022 2546 <1> ; (there is not a disk write error, we can increase file offset) 2547 00005333 58 <1> pop eax ; (!!) ; byte count 2548 00005334 5F <1> pop edi ; (!) ; file offset (pointer) 2549 <1> ; 2550 00005335 0107 <1> add [edi], eax ; new file offset (old offset + byte count) 2551 <1> 2552 00005337 59 <1> pop ecx ; ** 2553 <1> 2554 00005338 833D[10650000]00 <1> cmp dword [u.count], 0 2555 <1> ; tst u.count / done 2556 0000533F 77B7 <1> ja short bwrite_0 ; 09/06/2015 2557 <1> ; beq 1f / yes, 1f 2558 <1> ; tst -(r0) / no, point r0 to the argument of the call 2559 <1> ; br bwrite / go back and write next block 2560 <1> ; 1: 2561 00005341 58 <1> pop eax ; **** 2562 <1> ; mov (sp)+,r0 2563 00005342 C3 <1> retn ; 09/06/2015 2564 <1> ;jmp ret_ 2565 <1> ; jmp ret / return to routine that called writei 2566 <1> ;error10: 2567 <1> ; jmp error ; / see 'error' routine 2568 <1> 2569 <1> dioreg: 2570 <1> ; 19/07/2022 2571 <1> ; (file offset bugfix for 'dskwr' error return situation) 2572 <1> ; 04/02/2022 2573 <1> ; 14/07/2015 2574 <1> ; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block) 2575 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2576 <1> ; 14/03/2013 (Retro UNIX 8086 v1) 2577 <1> ; 2578 <1> ; bookkeeping on block transfers of data 2579 <1> ; 2580 <1> ; * returns value of u.pbase before it gets updated, in EDI 2581 <1> ; * returns byte count (to transfer) in ECX (<=512) 2582 <1> ; 10/07/2015 2583 <1> ; * returns byte offset from beginning of current sector buffer 2584 <1> ; (beginning of data) in ESI 2585 <1> 2586 <1> ; 19/07/2022 2587 <1> ; OUTPUTS: 2588 <1> ; EDI = user data offset (previous value of [u.pbase]) 2589 <1> ; ESI = pointer to file offset 2590 <1> ; EAX = system (I/O) buffer offset 2591 <1> ; ECX = byte count 2592 <1> ; EBX = system buffer (data) address 2593 <1> 2594 00005343 8B0D[10650000] <1> mov ecx, [u.count] 2595 <1> ; mov u.count,r3 / move char count to r3 2596 <1> ; 04/02/2022 2597 00005349 31D2 <1> xor edx, edx 2598 0000534B B602 <1> mov dh, 2 2599 <1> ; edx = 512 2600 0000534D 39D1 <1> cmp ecx, edx ; 512 2601 <1> ;cmp ecx, 512 2602 <1> ; cmp r3,$512. / more than 512. char? 2603 0000534F 7602 <1> jna short dioreg_0 2604 <1> ; blos 1f / no, branch 2605 00005351 89D1 <1> mov ecx, edx ; 512 2606 <1> ;mov ecx, 512 2607 <1> ; mov $512.,r3 / yes, just take 512. 2608 <1> dioreg_0: 2609 <1> ; 09/06/2015 2610 00005353 663B0D[51650000] <1> cmp cx, [u.pcount] 2611 0000535A 7607 <1> jna short dioreg_1 2612 0000535C 668B0D[51650000] <1> mov cx, [u.pcount] 2613 <1> dioreg_1: 2614 <1> ; 1: 2615 00005363 8B15[0C650000] <1> mov edx, [u.base] ; 09/06/2015 (eax -> edx) 2616 <1> ; mov u.base,r2 / put users base in r2 2617 00005369 010D[14650000] <1> add [u.nread], ecx 2618 <1> ; add r3,u.nread / add the number to be read to u.nread 2619 0000536F 290D[10650000] <1> sub [u.count], ecx 2620 <1> ; sub r3,u.count / update count 2621 00005375 010D[0C650000] <1> add [u.base], ecx 2622 <1> ; add r3,u.base / update base 2623 <1> ; 10/07/2015 2624 <1> ; Retro UNIX 386 v1 - modification ! 2625 <1> ; (File pointer points to byte position, not block/sector no.) 2626 <1> ; (It will point to next byte position instead of next block no.) 2627 0000537B 8B35[FC640000] <1> mov esi, [u.fofp] ; u.fopf points to byte position pointer 2628 00005381 8B06 <1> mov eax, [esi] ; esi points to current byte pos. on the disk 2629 <1> ; 19/07/2022 2630 <1> ;add [esi], ecx ; ecx is added to set the next byte position 2631 00005383 25FF010000 <1> and eax, 1FFh ; get offset from beginning of current block 2632 <1> ;mov esi, ebx ; beginning of data in sector/block buffer 2633 <1> ;add esi, eax ; esi contains start address of the transfer 2634 <1> ; 19/07/2022 2635 00005388 01D8 <1> add eax, ebx ; eax contains start address of the transfer 2636 <1> ; 09/06/2015 - 10/07/2015 2637 0000538A 66290D[51650000] <1> sub [u.pcount], cx 2638 00005391 81E2FF0F0000 <1> and edx, PAGE_OFF ; 0FFFh 2639 00005397 8B3D[4D650000] <1> mov edi, [u.pbase] 2640 0000539D 81E700F0FFFF <1> and edi, ~PAGE_OFF 2641 000053A3 01D7 <1> add edi, edx 2642 000053A5 893D[4D650000] <1> mov [u.pbase], edi 2643 000053AB 010D[4D650000] <1> add [u.pbase], ecx ; 14/07/2015 2644 000053B1 C3 <1> retn 2645 <1> ; rts r0 / return 2646 <1> 2647 <1> dskrd: 2648 <1> ; 15/07/2022 2649 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2650 <1> ; 08/02/2022 (Retro UNIX 386 v1.1) 2651 <1> ; 18/08/2015 2652 <1> ; 02/07/2015 2653 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2654 <1> ; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 2655 <1> ; 2656 <1> ; 'dskrd' acquires an I/O buffer, puts in the proper 2657 <1> ; I/O queue entries (via bufaloc) then reads a block 2658 <1> ; (number specified in r1) in the acquired buffer.) 2659 <1> ; If the device is busy at the time dskrd is called, 2660 <1> ; dskrd calls idle. 2661 <1> ; 2662 <1> ; INPUTS -> 2663 <1> ; r1 - block number 2664 <1> ; cdev - current device number 2665 <1> ; OUTPUTS -> 2666 <1> ; r5 - points to first data word in I/O buffer 2667 <1> ; 2668 <1> ; ((AX = R1)) input/output 2669 <1> ; ((BX = R5)) output 2670 <1> ; 2671 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 2672 <1> ; 2673 000053B2 E8B5000000 <1> call bufaloc 2674 <1> ; jsr r0,bufaloc / shuffle off to bufaloc; 2675 <1> ; / get a free I/O buffer 2676 <1> ;;jc error ; 20/07/2013 2677 000053B7 740C <1> jz short dskrd_1 ; Retro UNIX 8086 v1 modification 2678 <1> ; br 1f / branch if block already in a I/O buffer 2679 <1> 2680 <1> ; 15/07/2022 2681 <1> ; (buffer header byte 1, bit 2 is disk read bit/flag) 2682 <1> dskrd_0: ; 10/07/2015 (wslot) 2683 000053B9 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 2684 <1> ; bis $2000,(r5) / set bit 10 of word 1 of 2685 <1> ; / I/O queue entry for buffer 2686 000053BE E88E000000 <1> call poke 2687 <1> ; jsr r0,poke / just assigned in bufaloc, 2688 <1> ; / bit 10=1 says read 2689 <1> ; 09/06/2015 2690 <1> ;jnc short dskrd_1 2691 <1> ;mov dword [u.error], ERR_DRV_READ ; disk read error ! 2692 <1> ;jmp error 2693 <1> ; 08/02/2022 2694 000053C3 7204 <1> jc short dskrd_3 2695 <1> dskrd_1: ; 1: 2696 <1> ; 15/07/2022 2697 <1> ; 2698 <1> ; ;clr *$ps 2699 <1> ;test word [ebx], 2400h 2700 <1> ; ; bit $22000,(r5) / if either bits 10, or 13 are 1; 2701 <1> ; ; / jump to idle 2702 <1> ;jz short dskrd_2 2703 <1> ; ; beq 1f 2704 <1> ;;;mov ecx, [s.wait_] 2705 <1> ;call idle 2706 <1> ; ; jsr r0,idle; s.wait+2 2707 <1> ;jmp short dskrd_1 2708 <1> ; ; br 1b 2709 <1> dskrd_2: ; 1: 2710 000053C5 83C308 <1> add ebx, 8 2711 <1> ; add $8,r5 / r5 points to first word of data in block 2712 <1> ; / just read in 2713 000053C8 C3 <1> retn 2714 <1> ; rts r0 2715 <1> dskrd_err: 2716 <1> ; 08/02/2022 2717 <1> ; (jump from 'bread' error) 2718 <1> dskrd_3: 2719 <1> ; 08/02/2022 2720 000053C9 803D[54650000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 2721 000053D0 7509 <1> jne short dskrd_4 ; no 2722 <1> ; yes, clear [u.brwdev] for next check and jump to 'error' 2723 000053D2 C605[54650000]00 <1> mov byte [u.brwdev], 0 2724 000053D9 EB0A <1> jmp short dskrd_5 2725 <1> dskrd_4: 2726 000053DB C705[41650000]1100- <1> mov dword [u.error], ERR_DRV_READ ; disk read error ! 2726 000053E3 0000 <1> 2727 <1> dskrd_5: 2728 000053E5 E9E1DCFFFF <1> jmp error 2729 <1> 2730 <1> bwslot: 2731 <1> ; 15/07/2022 2732 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2733 <1> ; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2734 <1> ; 10/07/2015 2735 <1> ; If the block/sector is not placed in a buffer 2736 <1> ; before 'wslot', it must be read before 2737 <1> ; it is written! (Otherwise transfer counts less 2738 <1> ; than 512 bytes will be able to destroy existing 2739 <1> ; data on disk.) 2740 <1> ; 2741 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2742 <1> ; 26/04/2013(Retro UNIX 8086 v1) 2743 <1> ; Retro UNIX 8086 v1 modification ! 2744 <1> ; ('bwslot' will be called from 'bwrite' only!) 2745 <1> ; INPUT -> EDI - points to device id (in u.brwdev) 2746 <1> ; -> EAX = block number 2747 <1> ; 2748 000053EA E88A000000 <1> call bufaloc_0 2749 000053EF 742A <1> jz short wslot_0 ; block/sector already is in the buffer 2750 <1> ; 12/01/2022 2751 <1> ; ebx = buffer header address 2752 <1> bwslot_0: 2753 <1> ; 10/07/2015 2754 000053F1 8B35[FC640000] <1> mov esi, [u.fofp] 2755 000053F7 8B06 <1> mov eax, [esi] 2756 000053F9 25FF010000 <1> and eax, 1FFh ; offset from beginning of the sector/block 2757 000053FE 750C <1> jnz short bwslot_1 ; it is not a full sector write 2758 <1> ; recent disk data must be placed in the buffer 2759 00005400 813D[10650000]0002- <1> cmp dword [u.count], 512 2759 00005408 0000 <1> 2760 0000540A 730F <1> jnb short wslot_0 2761 <1> bwslot_1: 2762 0000540C E8A8FFFFFF <1> call dskrd_0 2763 <1> ; 12/01/2022 2764 <1> ; ebx = buffer data address = buffer header address + 8 2765 00005411 83EB08 <1> sub ebx, 8 ; set ebx to the buffer header address again 2766 00005414 EB05 <1> jmp short wslot_0 2767 <1> 2768 <1> wslot: 2769 <1> ; 15/07/2022 2770 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2771 <1> ; 2772 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 2773 <1> ; (32 bit modifications) 2774 <1> ; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1) 2775 <1> ; 2776 <1> ; 'wslot' calls 'bufaloc' and obtains as a result, a pointer 2777 <1> ; to the I/O queue of an I/O buffer for a block structured 2778 <1> ; device. It then checks the first word of I/O queue entry. 2779 <1> ; If bits 10 and/or 13 (read bit, waiting to read bit) are set, 2780 <1> ; wslot calls 'idle'. When 'idle' returns, or if bits 10 2781 <1> ; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first 2782 <1> ; word of the I/O queue entry (write bit, inhibit bit). 2783 <1> ; 2784 <1> ; INPUTS -> 2785 <1> ; r1 - block number 2786 <1> ; cdev - current (block/disk) device number 2787 <1> ; 2788 <1> ; OUTPUTS -> 2789 <1> ; bufp - bits 9 and 15 are set, 2790 <1> ; the remainder of the word left unchanged 2791 <1> ; r5 - points to first data word in I/O buffer 2792 <1> ; 2793 <1> ; ((AX = R1)) input/output 2794 <1> ; ((BX = R5)) output 2795 <1> ; 2796 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI)) 2797 <1> 2798 00005416 E851000000 <1> call bufaloc 2799 <1> ; 10/07/2015 2800 <1> ; jsr r0,bufaloc / get a free I/O buffer; pointer to first 2801 <1> ; br 1f / word in buffer in r5 2802 <1> ; EBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) 2803 <1> ; EAX = Block/Sector number (r1) 2804 <1> wslot_0: ;1: 2805 <1> ; 14/07/2022 2806 <1> ; 2807 <1> ;test word [ebx], 2400h 2808 <1> ; ; bit $22000,(r5) / check bits 10, 13 (read, waiting to read) 2809 <1> ; ; / of I/O queue entry 2810 <1> ;jz short wslot_1 2811 <1> ; ; beq 1f / branch if 10, 13 zero (i.e., not reading, 2812 <1> ; ; / or not waiting to read) 2813 <1> ; 2814 <1> ;;mov ecx, [s.wait_] ; 29/07/2013 2815 <1> ;call idle 2816 <1> ; ; jsr r0,idle; / if buffer is reading or writing to read, 2817 <1> ; ; / idle 2818 <1> ;jmp short wslot_0 2819 <1> ; ; br 1b / till finished 2820 <1> wslot_1: ;1: 2821 <1> ;or word [ebx], 8200h 2822 <1> ; ; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue 2823 <1> ; ; / (write, inhibit bits) 2824 <1> ; ; clr *$ps / clear processor status 2825 <1> 2826 <1> ; 15/07/2022 2827 <1> ; (set disk write bit/flag) 2828 <1> ;or word [ebx], 200h 2829 0000541B 43 <1> inc ebx 2830 0000541C 800B02 <1> or byte [ebx], 2 2831 0000541F 83C307 <1> add ebx, 7 2832 <1> 2833 <1> ;add ebx, 8 ; 11/06/2015 2834 <1> ; add $8,r5 / r5 points to first word in data area 2835 <1> ; / for this block 2836 <1> dskwr_1: ; 08/02/2022 2837 00005422 C3 <1> retn 2838 <1> ; rts r0 2839 <1> dskwr: 2840 <1> ; 15/07/2022 2841 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2842 <1> ; 08/02/2022 (Retro UNIX 386 v1.1) 2843 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2844 <1> ; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1) 2845 <1> ; 2846 <1> ; 'dskwr' writes a block out on disk, via ppoke. The only 2847 <1> ; thing dskwr does is clear bit 15 in the first word of I/O queue 2848 <1> ; entry pointed by 'bufp'. 'wslot' which must have been called 2849 <1> ; previously has supplied all the information required in the 2850 <1> ; I/O queue entry. 2851 <1> ; 2852 <1> ; (Modified registers: ECX, EDX, EBX, ESI, EDI) 2853 <1> ; 2854 <1> ; 2855 00005423 8B1D[A8640000] <1> mov ebx, [bufp] 2856 <1> ; 15/07/2022 2857 <1> ;and word [ebx], 7FFFh ; 0111111111111111b 2858 <1> ; ; bic $100000,*bufp / clear bit 15 of I/O queue entry at 2859 <1> ; / bottom of queue 2860 <1> ; 15/07/2022 2861 <1> ; (set disk write bit) 2862 <1> ; ('wslot' already sets disk write bit/flag) 2863 <1> ;mov word [ebx], 200h 2864 <1> 2865 00005429 E823000000 <1> call poke 2866 <1> ; 09/06/2015 2867 0000542E 73F2 <1> jnc short dskwr_1 2868 <1> ; 08/02/2022 2869 00005430 803D[54650000]FF <1> cmp byte [u.brwdev], 0FFh ; is error code set in [u.error] ? 2870 00005437 7509 <1> jne short dskwr_0 ; no 2871 <1> ; yes, clear [u.brwdev] for next check and jump to 'error' 2872 00005439 C605[54650000]00 <1> mov byte [u.brwdev], 0 2873 00005440 EB0A <1> jmp short dskwr_2 2874 <1> dskwr_0: 2875 00005442 C705[41650000]1200- <1> mov dword [u.error], ERR_DRV_WRITE ; disk write error ! 2875 0000544A 0000 <1> 2876 <1> dskwr_2: 2877 0000544C E97ADCFFFF <1> jmp error 2878 <1> ;dskwr_1: 2879 <1> ; retn 2880 <1> 2881 <1> ;ppoke: 2882 <1> ; mov $340,*$ps 2883 <1> ; jsr r0,poke 2884 <1> ; clr *$ps 2885 <1> ; rts r0 2886 <1> 2887 <1> poke: 2888 <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2889 <1> ; 14/07/2022 2890 <1> ; ! Major Modification ! 2891 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 2892 <1> ; 2893 <1> ; 04/02/2022 (32 bit reg push pop) 2894 <1> ; 24/10/2015 2895 <1> ; 20/08/2015 2896 <1> ; 18/08/2015 2897 <1> ; 02/07/2015 2898 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2899 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2900 <1> ; 2901 <1> ; (NOTE: There are some disk I/O code modifications & extensions 2902 <1> ; & exclusions on original 'poke' & other device I/O procedures of 2903 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 2904 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 2905 <1> ; 2906 <1> ; Basic I/O functions for all block structured devices 2907 <1> ; 2908 <1> ; (Modified registers: ECX, EDX, ESI, EDI) 2909 <1> ; 2910 <1> ; 20/07/2013 modifications 2911 <1> ; (Retro UNIX 8086 v1 features only !) 2912 <1> ; INPUTS -> 2913 <1> ; EBX = buffer header address 2914 <1> ; OUTPUTS -> 2915 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 2916 <1> ; cf=1 -> error, word [EBX] = 0FFFFh 2917 <1> ; (drive not ready or r/w error!) 2918 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 2919 <1> ; (dword [EBX+4] = 0FFFFFFFFh means RW/IO error) 2920 <1> ; (also it indicates invalid buffer data) 2921 <1> 2922 <1> ; 15/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 2923 <1> ; 14/07/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.22) 2924 <1> ; Buffer header: 2925 <1> ; byte 0 - device/disk (index) number 2926 <1> ; byte 1 - status 2927 <1> ; before 'poke' 2928 <1> ; bit 0 - valid bit 2929 <1> ; (0 for new buffer) 2930 <1> ; (1 for existing buffer) 2931 <1> ; bit 1 - write (modified) bit, disk write flag 2932 <1> ; bit 2 - read bit, disk read flag 2933 <1> ; after 'poke' 2934 <1> ; if disk r/w is successed 2935 <1> ; bit 0 = 1 2936 <1> ; bit 1 = 0 2937 <1> ; bit 2 = 0 2938 <1> ; if disk r/w is failed 2939 <1> ; bit 0 = 0 (invalid buffer) 2940 <1> ; bit 1 = 0 (write bit) 2941 <1> ; bit 2 = 0 (read bit) 2942 <1> ; 2943 <1> ; byte 2 & byte 3 - not used 2944 <1> ; byte 4 to byte 7 - disk block/sector address 2945 <1> 2946 <1> ; 04/02/2022 2947 00005451 50 <1> push eax 2948 00005452 E896000000 <1> call diskio ; Retro UNIX 8086 v1 Only ! 2949 00005457 58 <1> pop eax 2950 00005458 730D <1> jnc short seta ; 14/07/2022 2951 <1> 2952 <1> ; 14/07/2022 2953 <1> ; (invalidate buffer) 2954 <1> 2955 <1> ; 02/07/2015 (32 bit modification) 2956 <1> ; 20/07/2013 2957 0000545A C74304FFFFFFFF <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 2958 <1> ; mov $-1,2(r1) / destroy associativity 2959 00005461 66C703FF00 <1> mov word [ebx], 0FFh ; 20/08/2015 2960 <1> ; clrb 1(r1) / do not do I/O 2961 <1> ;stc 2962 00005466 C3 <1> retn 2963 <1> ; rts r0 2964 <1> seta: 2965 00005467 C6430101 <1> mov byte [ebx+1], 1 ; clear write/read bits, set valid bit 2966 <1> ;clc 2967 0000546B C3 <1> retn 2968 <1> 2969 <1> %if 0 2970 <1> 2971 <1> poke: 2972 <1> ; 24/12/2021 (32 bit reg push-pop) 2973 <1> ; 24/10/2015 2974 <1> ; 20/08/2015 2975 <1> ; 18/08/2015 2976 <1> ; 02/07/2015 2977 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 2978 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 2979 <1> ; 2980 <1> ; (NOTE: There are some disk I/O code modifications & extensions 2981 <1> ; & exclusions on original 'poke' & other device I/O procedures of 2982 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 2983 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 2984 <1> ; 2985 <1> ; Basic I/O functions for all block structured devices 2986 <1> ; 2987 <1> ; (Modified registers: ECX, EDX, ESI, EDI) 2988 <1> ; 2989 <1> ; 20/07/2013 modifications 2990 <1> ; (Retro UNIX 8086 v1 features only !) 2991 <1> ; INPUTS -> 2992 <1> ; (EBX = buffer header address) 2993 <1> ; OUTPUTS -> 2994 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 2995 <1> ; cf=1 -> error, word [EBX] = 0FFFFh 2996 <1> ; (drive not ready or r/w error!) 2997 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 2998 <1> ; (dword [EBX+4] = 0FFFFFFFFh means RW/IO error) 2999 <1> ; (also it indicates invalid buffer data) 3000 <1> ; 3001 <1> push ebx 3002 <1> ; mov r1,-(sp) 3003 <1> ; mov r2,-(sp) 3004 <1> ; mov r3,-(sp) 3005 <1> push eax ; Physical Block Number (r1) (mget) 3006 <1> ; 3007 <1> ; 09/06/2015 3008 <1> ; (permit read/write after a disk R/W error) 3009 <1> mov cl, [ebx] ; device id (0 to 5) 3010 <1> mov al, 1 3011 <1> shl al, cl 3012 <1> test al, [active] ; busy ? (error) 3013 <1> jz short poke_0 3014 <1> not al 3015 <1> and [active], al ; reset busy bit for this device only 3016 <1> poke_0: 3017 <1> mov esi, bufp + (4*(nbuf+2)) 3018 <1> ; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority 3019 <1> ; / I/O queue pointer 3020 <1> poke_1: ; 1: 3021 <1> sub esi, 4 3022 <1> mov ebx, [esi] 3023 <1> ; mov -(r2),r1 / r1 points to an I/O queue entry 3024 <1> mov ax, [ebx] ; 17/07/2013 3025 <1> test ah, 06h 3026 <1> ;test word [ebx], 600h ; 0000011000000000b 3027 <1> ; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 3028 <1> ; / queue entry 3029 <1> jz short poke_5 3030 <1> ; beq 2f / branch to 2f if both are clear 3031 <1> ; 31/07/2013 3032 <1> ;test ah, 0B0h ; (*) 3033 <1> ;;test word [ebx], 0B000h ; 1011000000000000b 3034 <1> ; bit $130000,(r1) / test bits 12, 13, and 15 3035 <1> ;jnz short poke_5 ; 31/07/2013 (*) 3036 <1> ; bne 2f / branch if any are set 3037 <1> ;movzx ecx, byte [ebx] ; 09/06/2015 ; Device Id 3038 <1> ; movb (r1),r3 / get device id 3039 <1> movzx ecx, al ; 18/08/2015 3040 <1> ;mov edi, ecx ; 26/04/2013 3041 <1> xor eax, eax ; 0 3042 <1> ;cmp [edi+drv.error], al ; 0 3043 <1> ; tstb deverr(r3) / test for errors on this device 3044 <1> ;jna short poke_2 3045 <1> ; beq 3f / branch if no errors 3046 <1> ; 02/07/2015 3047 <1> ;dec eax 3048 <1> ;mov [ebx+4], ax ; 0FFFFFFFFh ; -1 3049 <1> ; mov $-1,2(r1) / destroy associativity 3050 <1> ;shr eax, 24 3051 <1> ;mov [ebx], eax ; 000000FFh, reset 3052 <1> ; clrb 1(r1) / do not do I/O 3053 <1> ;jmp short poke_5 3054 <1> ; ; br 2f 3055 <1> ; rts r0 3056 <1> poke_2: ; 3: 3057 <1> ; 02/07/2015 3058 <1> inc cl ; 0FFh -> 0 3059 <1> jz short poke_5 3060 <1> inc al ; mov ax, 1 3061 <1> dec cl 3062 <1> jz short poke_3 3063 <1> ; 26/04/2013 Modification 3064 <1> ;inc al ; mov ax, 1 3065 <1> ;or cl, cl ; Retro UNIX 8086 v1 device id. 3066 <1> ;jz short poke_3 ; cl = 0 3067 <1> shl al, cl ; shl ax, cl 3068 <1> poke_3: 3069 <1> ;test [active], ax 3070 <1> test [active], al 3071 <1> ; bit $2,active / test disk busy bit 3072 <1> jnz short poke_5 3073 <1> ; bne 2f / branch if bit is set 3074 <1> ;or [active], ax 3075 <1> or [active], al 3076 <1> ; bis $2,active / set disk busy bit 3077 <1> ;push ax 3078 <1> ; 24/12/2021 3079 <1> push eax 3080 <1> call diskio ; Retro UNIX 8086 v1 Only ! 3081 <1> ;mov [edi+drv.error], ah 3082 <1> ; 24/12/2021 3083 <1> pop eax 3084 <1> ;pop ax 3085 <1> jnc short poke_4 ; 20/07/2013 3086 <1> ;cmp [edi+drv.error], al ; 0 3087 <1> ;jna short poke_4 3088 <1> ; tstb deverr(r3) / test for errors on this device 3089 <1> ; beq 3f / branch if no errors 3090 <1> ; 02/07/2015 (32 bit modification) 3091 <1> ; 20/07/2013 3092 <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 3093 <1> ; mov $-1,2(r1) / destroy associativity 3094 <1> mov word [ebx], 0FFh ; 20/08/2015 3095 <1> ; clrb 1(r1) / do not do I/O 3096 <1> jmp short poke_5 3097 <1> poke_4: ; 20/07/2013 3098 <1> ; 17/07/2013 3099 <1> not al 3100 <1> and [active], al ; reset, not busy 3101 <1> ; EBX = system I/O buffer header (queue entry) address 3102 <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits. 3103 <1> mov ax, [ebx] 3104 <1> ; mov (r1),r3 / move word 1 of I/O queue entry into r3 3105 <1> and ax, 600h 3106 <1> ; bic $!3000,r3 / clear all bits except 9 and 10 3107 <1> and word [ebx], 0F9FFh 3108 <1> ; bic $3000,(r1) / clear only bits 9 and 10 3109 <1> shl ah, 3 3110 <1> ; rol r3 3111 <1> ; rol r3 3112 <1> ; rol r3 3113 <1> or [ebx], ax 3114 <1> ; bis r3,(r1) / or old value of bits 9 and 10 with 3115 <1> ; bits 12 and 13 3116 <1> call idle ; 18/01/2014 3117 <1> ;; sti 3118 <1> ;hlt ; wait for a hardware interrupt 3119 <1> ;; cli 3120 <1> ; NOTE: In fact, disk controller's 'disk I/O completed' 3121 <1> ; interrupt would be used to reset busy bits, but INT 13h 3122 <1> ; returns when disk I/O is completed. So, here, as temporary 3123 <1> ; method, this procedure will wait for a time according to 3124 <1> ; multi tasking and time sharing concept. 3125 <1> ; 3126 <1> ; 24/10/2015 3127 <1> ;not ax 3128 <1> mov ax, 0FFh ; 24/10/2015 (temporary) 3129 <1> and [ebx], ax ; clear bits 12 and 13 3130 <1> poke_5: ;2: 3131 <1> cmp esi, bufp 3132 <1> ; cmp r2,$bufp / test to see if entire I/O queue 3133 <1> ; / has been scanned 3134 <1> ja short poke_1 3135 <1> ; bhi 1b 3136 <1> ; 24/03/2013 3137 <1> ; mov (sp)+,r3 3138 <1> ; mov (sp)+,r2 3139 <1> ; mov (sp)+,r1 3140 <1> pop eax ; Physical Block Number (r1) (mget) 3141 <1> pop ebx 3142 <1> ; 02/07/2015 (32 bit modification) 3143 <1> ; 20/07/2013 3144 <1> ;cmp dword [ebx+4], 0FFFFFFFFh 3145 <1> cmp byte [ebx], 0FFh ; 20/08/2015 3146 <1> ; 3147 <1> ; 'poke' returns with cf=0 if the requested buffer is read 3148 <1> ; or written successfully; even if an error occurs while 3149 <1> ; reading to or writing from other buffers. 20/07/2013 3150 <1> ; 3151 <1> ; 09/06/2015 3152 <1> cmc 3153 <1> retn 3154 <1> ; rts r0 3155 <1> 3156 <1> %endif 3157 <1> 3158 <1> bufaloc: 3159 <1> ; 15/07/2022 3160 <1> ; Retro UNIX 386 v1.1 (Kernel v0.2.1.6) 3161 <1> ; 14/07/2022 3162 <1> ; Retro UNIX 386 v1 (Kernel v0.2.0.22) 3163 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 3164 <1> ; 20/08/2015 3165 <1> ; 19/08/2015 3166 <1> ; 02/07/2015 3167 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 3168 <1> ; (32 bit modifications) 3169 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 3170 <1> ; 3171 <1> ; bufaloc - Block device I/O buffer allocation 3172 <1> ; 3173 <1> ; INPUTS -> 3174 <1> ; r1 - block number 3175 <1> ; cdev - current (block/disk) device number 3176 <1> ; bufp+(2*n)-2 --- n = 1 ... nbuff 3177 <1> ; OUTPUTS -> 3178 <1> ; r5 - pointer to buffer allocated 3179 <1> ; bufp ... bufp+12 --- (bufp), (bufp)+2 3180 <1> ; 3181 <1> ; ((AX = R1)) input/output 3182 <1> ; ((BX = R5)) output 3183 <1> ; ((Modified registers: DX, CX, BX, SI, DI, BP)) 3184 <1> ; zf=1 -> block already in a I/O buffer 3185 <1> ; zf=0 -> a new I/O buffer has been allocated 3186 <1> ; ((DL = Device ID)) 3187 <1> ; (((DH = 0 or 1))) 3188 <1> ; (((CX = previous value of word ptr [bufp]))) 3189 <1> ; ((CX and DH will not be used after return))) 3190 <1> 3191 <1> ; 14/07/2022 3192 <1> ; Modified registers: EBX, ECX, EDX, ESI, EDI 3193 <1> 3194 <1> ;;push esi ; *** 3195 <1> ; mov r2,-(sp) / save r2 on stack 3196 <1> ; mov $340,*$ps / set processor priority to 7 3197 <1> ; 20/07/2013 3198 <1> ; 26/04/2013 3199 <1> ;movzx ebx, byte [cdev] ; 0 or 1 3200 <1> ;mov edi, rdev ; offset mdev = offset rdev + 1 3201 <1> ;add edi, ebx 3202 <1> ; 09/01/2022 3203 0000546C 0FB63D[D3640000] <1> movzx edi, byte [cdev] ; 0 or 1 3204 00005473 81C7[D4640000] <1> add edi, rdev 3205 <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !! 3206 <1> ;; EDI points to device id. 3207 00005479 0FB61F <1> movzx ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev 3208 <1> ; 11/06/2015 3209 0000547C 80BB[6E5C0000]F0 <1> cmp byte [ebx+drv.status], 0F0h ; Drive not ready ! 3210 00005483 720F <1> jb short bufaloc_9 3211 00005485 C705[41650000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 3211 0000548D 0000 <1> 3212 0000548F E937DCFFFF <1> jmp error 3213 <1> bufaloc_9: 3214 00005494 89DA <1> mov edx, ebx ; dh = 0, dl = device number (0 to 5) 3215 <1> bufaloc_10: ; 02/07/2015 3216 <1> ; 14/07/2022 3217 <1> ;xor ebp, ebp ; 0 3218 <1> ;push ebp ; 0 3219 <1> ;mov ebp, esp 3220 00005496 31FF <1> xor edi, edi ; 0 3221 00005498 57 <1> push edi 3222 <1> bufaloc_1: ;1: 3223 <1> ; clr -(sp) / vacant buffer 3224 00005499 BE[A8640000] <1> mov esi, bufp 3225 <1> ; mov $bufp,r2 / bufp contains pointers to I/O queue 3226 <1> ; / entrys in buffer area 3227 <1> bufaloc_2: ;2: 3228 0000549E 8B1E <1> mov ebx, [esi] 3229 <1> ; mov (r2)+,r5 / move pointer to word 1 of an I/O 3230 <1> ; queue entry into r5 3231 <1> ; 14/07/2022 3232 000054A0 8B0B <1> mov ecx, [ebx] 3233 <1> ;test word [ebx], 0F600h 3234 <1> ; 15/07/2022 3235 000054A2 F6C501 <1> test ch, 1 ; valid buffer (content) ? 3236 <1> ; bit $173000,(r5) / lock+keep+active+outstanding 3237 000054A5 7505 <1> jnz short bufaloc_3 ; yes 3238 <1> ; bne 3f / branch when 3239 <1> ; / any of bits 9,10,12,13,14,15 are set 3240 <1> ; / (i.e., buffer busy) 3241 <1> ;mov [ebp], esi ; pointer to I/0 queue entry 3242 <1> ; 14/07/2022 3243 <1> ; save free buffer pointer 3244 000054A7 893424 <1> mov [esp], esi 3245 <1> ; mov r2,(sp) ;/ save pointer to last non-busy buffer 3246 <1> ; / found points to word 2 of I/O queue entry) 3247 <1> ; continue to see if requested sector/block buffer 3248 <1> ; already is one of existing (valid) buffers 3249 <1> ;jmp short bufaloc_4 3250 000054AA EB0E <1> jmp short bufaloc_11 ; 14/07/2022 3251 <1> bufaloc_3: ;3: 3252 <1> ;mov dl, [edi] ; 26/04/2013 3253 <1> ; 3254 000054AC 38D1 <1> cmp cl, dl ; 14/07/2022 3255 <1> ;cmp [ebx], dl 3256 <1> ; cmpb (r5),cdev / is device in I/O queue entry same 3257 <1> ; / as current device 3258 000054AE 7508 <1> jne short bufaloc_4 3259 <1> ; bne 3f 3260 000054B0 394304 <1> cmp [ebx+4], eax 3261 <1> ; cmp 2(r5),r1 / is block number in I/O queue entry, 3262 <1> ; / same as current block number 3263 000054B3 7503 <1> jne short bufaloc_4 3264 <1> ; bne 3f 3265 <1> ;add esp, 4 3266 000054B5 59 <1> pop ecx 3267 <1> ; tst (sp)+ / bump stack pointer 3268 000054B6 EB1D <1> jmp short bufaloc_7 ; Retro Unix 8086 v1 modification 3269 <1> ; jump to bufaloc_6 in original Unix v1 3270 <1> ; br 1f / use this buffer 3271 <1> bufaloc_4: ;3: 3272 <1> ; 14/07/2022 3273 <1> ; save last valid buffer 3274 <1> ; (will be used if there is not a free buffer) 3275 000054B8 89F7 <1> mov edi, esi 3276 <1> bufaloc_11: 3277 000054BA 83C604 <1> add esi, 4 ; 20/08/2015 3278 <1> ; 3279 000054BD 81FE[C8640000] <1> cmp esi, bufp + (nbuf*4) 3280 <1> ; cmp r2,$bufp+nbuf+nbuf 3281 000054C3 72D9 <1> jb short bufaloc_2 3282 <1> ; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all 3283 <1> ; / buffers not checked) 3284 000054C5 5E <1> pop esi 3285 <1> ; mov (sp)+,r2 / once all bufs are examined move pointer 3286 <1> ; / to last free block 3287 000054C6 09F6 <1> or esi, esi 3288 000054C8 7502 <1> jnz short bufaloc_5 3289 <1> ; bne 2f / if (sp) is non zero, i.e., 3290 <1> ; / if a free buffer is found branch to 2f 3291 <1> 3292 <1> ; 14/07/2022 3293 <1> ; if there is not a free buffer 3294 <1> ; we can use last valid buffer (the oldest buffer) 3295 <1> ; ((ptr to new buffer is located at head of buff ptr chain)) 3296 000054CA 89FE <1> mov esi, edi 3297 <1> 3298 <1> ;;mov ecx, [s.wait_] 3299 <1> ;call idle 3300 <1> ; ; jsr r0,idle; s.wait+2 / idle if no free buffers 3301 <1> ;jmp short bufaloc_10 ; 02/07/2015 3302 <1> ; ; br 1b 3303 <1> bufaloc_5: ;2: 3304 <1> ; tst (r0)+ / skip if warmed over buffer 3305 <1> ; 14/07/2022 3306 <1> ;inc dh ; Retro UNIX 8086 v1 modification 3307 <1> bufaloc_6: ;1: 3308 000054CC 8B1E <1> mov ebx, [esi] 3309 <1> ; mov -(r2),r5 / put pointer to word 1 of I/O queue 3310 <1> ; / entry in r5 3311 <1> ;; 26/04/2013 3312 <1> ;;mov dl, [edi] ; byte [rdev] or byte [mdev] 3313 <1> ;mov [ebx], dl 3314 <1> ; movb cdev,(r5) / put current device number 3315 <1> ; / in I/O queue entry 3316 <1> ; 14/07/2022 3317 <1> ; invalidate buffer before r/w (new) disk sector/block 3318 <1> ;mov [ebx+1], dh ; 0 3319 <1> ; 14/07/2022 3320 000054CE 8913 <1> mov [ebx], edx ; dh = 0 3321 <1> 3322 000054D0 894304 <1> mov [ebx+4], eax 3323 <1> ; mov r1,2(r5) / move block number into word 2 3324 <1> ; / of I/O queue entry 3325 <1> ; 14/07/2022 3326 000054D3 FEC6 <1> inc dh ; dh = 1 3327 <1> bufaloc_7: ;1: 3328 000054D5 81FE[A8640000] <1> cmp esi, bufp 3329 <1> ; cmp r2,$bufp / bump all entrys in bufp 3330 <1> ; / and put latest assigned 3331 000054DB 760B <1> jna short bufaloc_8 3332 <1> ; blos 1f / buffer on the top 3333 <1> ; / (this makes if the lowest priority) 3334 <1> ; 14/07/2022 3335 000054DD 89F7 <1> mov edi, esi 3336 000054DF 83EE04 <1> sub esi, 4 3337 000054E2 8B0E <1> mov ecx, [esi] 3338 000054E4 890F <1> mov [edi], ecx ; 14/07/2022 3339 <1> ;mov [esi+4], ecx 3340 <1> ; mov -(r2),2(r2) / job for a particular device 3341 000054E6 EBED <1> jmp short bufaloc_7 3342 <1> ; br 1b 3343 <1> bufaloc_8: ;1: 3344 000054E8 891E <1> mov [esi], ebx 3345 <1> ; mov r5,(r2) 3346 <1> ;;pop esi ; *** 3347 <1> ; mov (sp)+,r2 / restore r2 3348 000054EA 08F6 <1> or dh, dh ; 0 or 1 ? 3349 <1> ; Retro UNIX 8086 v1 modification 3350 <1> ; zf=1 --> block already is in an I/O buffer 3351 <1> ; zf=0 --> a new I/O buffer has been allocated 3352 000054EC C3 <1> retn 3353 <1> ; rts r0 3354 <1> 3355 <1> diskio: 3356 <1> ; 12/07/2022 3357 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3358 <1> ; ((simplified and shortened 'diskio.s' code)) 3359 <1> ; 12/02/2022 3360 <1> ; 10/02/2022 3361 <1> ; 08/02/2022 3362 <1> ; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2) 3363 <1> ; 10/07/2015 3364 <1> ; 02/07/2015 3365 <1> ; 16/06/2015 3366 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 3367 <1> ; (80386 protected mode modifications) 3368 <1> ; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1) 3369 <1> ; 3370 <1> ; Retro UNIX 8086 v1 feature only ! 3371 <1> ; 3372 <1> ; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011) 3373 <1> ; 04/07/2009 - 20/07/2011 3374 <1> ; 3375 <1> ; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes) 3376 <1> ; 3377 <1> ; INPUTS -> 3378 <1> ; EBX = System I/O Buffer header address 3379 <1> ; 3380 <1> ; OUTPUTS -> cf=0 --> done 3381 <1> ; cf=1 --> error code in AH 3382 <1> ; ; 08/02/2022 3383 <1> ; cf=1 & [u.brwdev] = 0FFh --> 3384 <1> ; error code in [u.error] 3385 <1> ; 3386 <1> ; (Modified registers: EAX, ECX, EDX) 3387 <1> 3388 <1> ;rw_disk_sector: 3389 <1> ; 12/07/2022 3390 <1> ; 08/07/2022 3391 <1> ; 12/02/2022 3392 <1> ; 10/02/2022 3393 <1> ; 08/02/2022 3394 <1> ; 10/07/2015 3395 <1> ; 02/07/2015 3396 <1> ; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 3397 <1> ; 21/02/2015 ('dsectpm.s', 'read_disk_sector') 3398 <1> ; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s') 3399 <1> ; 01/12/2014 - 18/01/2015 ('dsectrm2.s') 3400 <1> ; 3401 <1> ;;mov dx, 0201h ; Read 1 sector/block 3402 <1> ;mov dh, 2 3403 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3404 000054ED B602 <1> mov dh, 2 ; Write 1 sector/block 3405 000054EF 668B03 <1> mov ax, [ebx] 3406 <1> ; 3407 000054F2 56 <1> push esi ; **** 3408 000054F3 53 <1> push ebx ; *** 3409 <1> ; 3410 000054F4 0FB6C8 <1> movzx ecx, al 3411 000054F7 89CE <1> mov esi, ecx 3412 <1> ; 3413 000054F9 38F1 <1> cmp cl, dh ; 2 3414 000054FB 7202 <1> jb short rwdsk0 3415 000054FD 047E <1> add al, 7Eh ; 80h, 81h, 82h, 83h 3416 <1> rwdsk0: 3417 <1> ; 12/07/2022 3418 <1> ;mov [drv], al 3419 000054FF 81C6[6E5C0000] <1> add esi, drv.status 3420 <1> ; 11/06/2015 3421 00005505 803EF0 <1> cmp byte [esi], 0F0h 3422 00005508 7204 <1> jb short rwdsk1 3423 <1> ; 'drive not ready' error 3424 <1> ; 10/02/2022 3425 <1> ; 08/02/2022 3426 <1> ;mov byte [u.brwdev], 0FFh ; error code in [u.error] 3427 <1> ;mov dword [u.error], ERR_DRV_NOT_RDY 3428 <1> ;;jmp error 3429 <1> ;stc ; cf = 1 3430 <1> ;retn 3431 <1> ; 10/02/2022 3432 0000550A B10F <1> mov cl, ERR_DRV_NOT_RDY 3433 0000550C EB1F <1> jmp short rwdsk_err1 3434 <1> rwdsk1: 3435 <1> ;test ah, 2 3436 <1> ;;test ax, 200h ; Bit 9 of word 0 (status word) 3437 <1> ; ; write bit 3438 <1> ;jz short rwdsk2 3439 <1> 3440 <1> ;;test ah, 4 3441 <1> ;;;test ax, 400h ; Bit 10 of word 0 (status word) 3442 <1> ;; ; read bit 3443 <1> ;;jz short diskio_ret 3444 <1> 3445 <1> ;inc dh ; 03h = write 3446 <1> 3447 <1> ; 08/07/2022 3448 0000550E 84F4 <1> test ah, dh ; test ah, 2 3449 00005510 7502 <1> jnz short rwdsk2 ; dh = 02h = write 3450 00005512 FECE <1> dec dh 3451 <1> ; dh = 01h = read 3452 <1> rwdsk2: 3453 00005514 88C2 <1> mov dl, al 3454 00005516 83C304 <1> add ebx, 4 ; sector/block address/number pointer 3455 00005519 8B03 <1> mov eax, [ebx] ; sector/block number (LBA) 3456 0000551B C0E102 <1> shl cl, 2 3457 0000551E 81C1[525C0000] <1> add ecx, drv.size ; disk size 3458 00005524 3B01 <1> cmp eax, [ecx] ; Last sector + 1 (number of secs.) 3459 00005526 7214 <1> jb short rwdsk3 3460 <1> ; 'out of volume' error 3461 <1> ; 10/02/2022 3462 <1> ; 08/02/2022 3463 <1> ;mov byte [u.brwdev], 0FFh ; error code in [u.error] 3464 <1> ;mov dword [u.error], ERR_DEV_VOL_SIZE 3465 <1> ;;jmp error 3466 <1> ;stc ; cf = 1 3467 <1> ;retn 3468 <1> ; 10/02/2022 3469 00005528 B910000000 <1> mov ecx, ERR_DEV_VOL_SIZE 3470 <1> rwdsk_err1: 3471 0000552D C605[54650000]FF <1> mov byte [u.brwdev], 0FFh 3472 00005534 890D[41650000] <1> mov [u.error], ecx ; 12/02/2022 3473 0000553A EB27 <1> jmp short rwdsk_err2 3474 <1> rwdsk3: 3475 <1> ; 11/06/2015 3476 0000553C 83C304 <1> add ebx, 4 ; buffer address 3477 0000553F C605[72650000]04 <1> mov byte [retry_count], 4 3478 <1> ; 12/07/2022 3479 <1> ;test byte [esi], 1 ; LBA ready ? 3480 <1> ;jz short rwdsk_chs 3481 <1> rwdsk_lba: 3482 <1> ; LBA read/write (with private LBA function) 3483 <1> ;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan)) 3484 00005546 83C607 <1> add esi, drv.error - drv.status ; 10/07/2015 3485 00005549 89C1 <1> mov ecx, eax ; sector number 3486 <1> ; ebx = buffer (data) address 3487 <1> ; dl = physical drive number (0, 1, 80h, 81h, 82h, 83h) 3488 <1> rwdsk_lba_retry: 3489 <1> ;mov dl, [drv] 3490 <1> ; Function 1Bh = LBA read, 1Ch = LBA write 3491 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3492 <1> ;;mov ah, 1Ch - 03h ; LBA write function number - 3 3493 <1> ;mov ah, 2 ; LBA write function number - 2 3494 <1> ;add ah, dh 3495 <1> ;mov al, 1 3496 <1> ;int 13h 3497 <1> ;call int13h 3498 <1> ; 12/07/2022 3499 0000554B 88F0 <1> mov al, dh ; function (1 or 2) 3500 <1> ; (1 = read, 2 = write ) 3501 <1> ; ecx = disk sector address (LBA) 3502 <1> ; ebx = buffer address 3503 <1> ; dl = (physical) disk number 3504 <1> ; al = function (r/w) 3505 0000554D E8FCC9FFFF <1> call DISK_IO 3506 <1> 3507 00005552 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3508 00005554 730E <1> jnc short rwdsk_lba_ok 3509 00005556 80FC80 <1> cmp ah, 80h ; time out ? 3510 00005559 7408 <1> je short rwdsk_lba_fails 3511 0000555B FE0D[72650000] <1> dec byte [retry_count] 3512 00005561 7504 <1> jnz short rwdsk_lba_reset ; 10/07/2015 3513 <1> rwdsk_err2: ; 10/02/2022 3514 <1> rwdsk_lba_fails: 3515 00005563 F9 <1> stc 3516 <1> rwdsk_lba_ok: 3517 00005564 5B <1> pop ebx ; *** 3518 00005565 5E <1> pop esi ; **** 3519 00005566 C3 <1> retn 3520 <1> rwdsk_lba_reset: 3521 <1> ;mov ah, 0Dh ; Alternate reset 3522 <1> ;int 13h 3523 <1> ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3524 <1> ;mov ah, 5 ; Alternate reset 3525 <1> ;call int13h 3526 <1> ;jnc short rwdsk_lba_retry 3527 <1> ; 12/07/2022 3528 00005567 30C0 <1> xor al, al ; 0 ; reset 3529 00005569 E8E0C9FFFF <1> call DISK_IO 3530 0000556E 73DB <1> jnc short rwdsk_lba_retry 3531 <1> 3532 00005570 8826 <1> mov [esi], ah ; error code ; 10/07/2015 3533 00005572 EBF0 <1> jmp short rwdsk_lba_ok 3534 <1> 3535 <1> ; 12/07/2022 3536 <1> ; (CHS Read/Write setup is not needed here.) 3537 <1> ; (LBA address will be converted to CHS parameters 3538 <1> ; in 'DISK_IO' procedure when/if it is required.) 3539 <1> 3540 <1> ; ; CHS read (convert LBA address to CHS values) 3541 <1> ;rwdsk_chs: 3542 <1> ; ; 10/07/2015 3543 <1> ; sub esi, drv.status 3544 <1> ; mov ecx, esi 3545 <1> ; add esi, drv.error 3546 <1> ; ; 02/07/2015 3547 <1> ; ; 16/06/2015 3548 <1> ; ; 11/06/2015 3549 <1> ; push ebx ; ** ; buffer 3550 <1> ; shl ecx, 1 3551 <1> ; push ecx ; * 3552 <1> ; ; 3553 <1> ; mov ebx, ecx 3554 <1> ; mov [rwdsk], dh ; 02/07/2015 3555 <1> ; xor edx, edx ; 0 3556 <1> ; ; 09/01/2022 3557 <1> ; ;sub ecx, ecx 3558 <1> ; add ebx, drv.spt 3559 <1> ; mov cx, [ebx] ; sector per track 3560 <1> ; ; EDX:EAX = LBA 3561 <1> ; div ecx 3562 <1> ; mov cl, dl ; sector number - 1 3563 <1> ; inc cl ; sector number (1 based) 3564 <1> ; pop ebx ; * ; 11/06/2015 3565 <1> ; ;push cx 3566 <1> ; ; 09/01/2022 3567 <1> ; push ecx 3568 <1> ; add ebx, drv.heads 3569 <1> ; mov cx, [ebx] ; heads 3570 <1> ; xor edx, edx 3571 <1> ; ; EAX = cylinders * heads + head 3572 <1> ; div ecx 3573 <1> ; ;pop cx ; sector number 3574 <1> ; ; 09/01/2022 3575 <1> ; pop ecx 3576 <1> ; mov dh, dl ; head number 3577 <1> ; mov dl, [drv] 3578 <1> ; mov ch, al ; cylinder (bits 0-7) 3579 <1> ; shl ah, 6 3580 <1> ; or cl, ah ; cylinder (bits 8-9) 3581 <1> ; ; sector (bits 0-7) 3582 <1> ; pop ebx ; ** ; buffer ; 11/06/2015 3583 <1> ; ; CL = sector (bits 0-5) 3584 <1> ; ; cylinder (bits 8-9 -> bits 6-7) 3585 <1> ; ; CH = cylinder (bits 0-7) 3586 <1> ; ; DH = head 3587 <1> ; ; DL = drive 3588 <1> ; ; 3589 <1> ; mov byte [retry_count], 4 3590 <1> ;rwdsk_retry: 3591 <1> ; ;mov ah, [rwdsk] ; 02h = read, 03h = write 3592 <1> ; ; 08/07/2022 3593 <1> ; mov ah, [rwdsk] ; 01h = read, 02h = write 3594 <1> ; mov al, 1 ; sector count 3595 <1> ; ;int 13h 3596 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3597 <1> ; call int13h 3598 <1> ; mov [esi], ah ; error code ; 10/07/2015 3599 <1> ; jnc short rwdsk_ok ; ah = 0 3600 <1> ; cmp ah, 80h ; time out ? 3601 <1> ; je short rwdsk_fails 3602 <1> ; dec byte [retry_count] 3603 <1> ; jnz short rwdsk_reset 3604 <1> ;rwdsk_fails: 3605 <1> ; stc 3606 <1> ;rwdsk_ok: 3607 <1> ; pop ebx ; *** 3608 <1> ; pop esi ; **** 3609 <1> ; retn 3610 <1> ;rwdsk_reset: 3611 <1> ; ; 02/02/2015 3612 <1> ; sub ah, ah 3613 <1> ; cmp dl, 80h 3614 <1> ; jb short rwdsk_fd_reset 3615 <1> ; ;mov ah, 0Dh ; Alternate reset 3616 <1> ; ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 3617 <1> ; mov ah, 5 ; Alternate reset 3618 <1> ;rwdsk_fd_reset: 3619 <1> ; ;int 13h 3620 <1> ; call int13h 3621 <1> ; jnc short rwdsk_retry 3622 <1> ; mov [esi], ah ; error code ; 10/07/2015 3623 <1> ; jmp short rwdsk_ok 3624 <1> 3625 <1> ; Original UNIX v1 - drum (& disk) interrupt routine 3626 <1> ; (Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts) 3627 <1> ; 3628 <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now. 3629 <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 3630 <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h 3631 <1> ; that uses hardware -transfer has been completed- interrupt inside it. 3632 <1> ; In a next Retro UNIX 386 version, these interrupts 3633 <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine 3634 <1> ; as in original unix v1. 3635 <1> ; I am not removing IBM BIOS source code derivatives -compatible code- 3636 <1> ; for now, regarding the new/next 32 bit TRDOS project by me 3637 <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.) 3638 <1> ; 3639 <1> ; Erdogan tan (10/07/2015) 3640 <1> 3641 <1> ;drum: / interrupt handler 3642 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 3643 <1> ; jsr r0,trapt; dcs; rfap; 1 / check for stray interrupt or 3644 <1> ; / error 3645 <1> ; br 3f / no, error 3646 <1> ; br 2f / error 3647 <1> ; 3648 <1> ;disk: 3649 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 3650 <1> ; jmp *$0f 3651 <1> ;0: 3652 <1> ; jsr r0,trapt; rkcs; rkap; 2 3653 <1> ; br 3f / no, errors 3654 <1> ; mov $115,(r2) / drive reset, errbit was set 3655 <1> ; mov $1f,0b-2 / next time jmp *$0f is executed jmp will be 3656 <1> ; / to 1f 3657 <1> ; br 4f 3658 <1> ;1: 3659 <1> ; bit $20000,rkcs 3660 <1> ; beq 4f / wait for seek complete 3661 <1> ; mov $0b,0b-2 3662 <1> ; mov rkap,r1 3663 <1> ;2: 3664 <1> ; bit $3000,(r1) / are bits 9 or 10 set in the 1st word of 3665 <1> ; / the disk buffer 3666 <1> ; bne 3f / no, branch ignore error if outstanding 3667 <1> ; inc r1 3668 <1> ; asr (r1) 3669 <1> ; asr (r1) 3670 <1> ; asr (r1) / reissue request 3671 <1> ; dec r1 3672 <1> ;3: 3673 <1> ; bic $30000,(r1) / clear bits 12 and 13 in 1st word of buffer 3674 <1> ; mov ac,-(sp) 3675 <1> ; mov mq,-(sp) / put these on the stack 3676 <1> ; mov sc,-(sp) 3677 <1> ; jsr r0,poke 3678 <1> ; mov (sp)+,sc 3679 <1> ; mov (sp)+,mq / pop them off stack 3680 <1> ; mov (sp)+,ac 3681 <1> ;4: 3682 <1> ; jmp retisp / u4-3 3683 <1> ; 3684 <1> ;trapt: / r2 points to the 3685 <1> ; mov (r0)+,r2 / device control register 3686 <1> ; mov *(r0)+,r1 / transaction pointer points to buffer 3687 <1> ; tst (sp)+ 3688 <1> ; tstb (r2) / is ready bit of dcs set? 3689 <1> ; bge 4b / device still active so branch 3690 <1> ; bit (r0),active / was device busy? 3691 <1> ; beq 4b / no, stray interrupt 3692 <1> ; bic (r0)+,active / yes, set active to zero 3693 <1> ; tst (r2) / test the err(bit is) of dcs 3694 <1> ; bge 2f / if no error jump to 2f 3695 <1> ; tst (r0)+ / skip on error 3696 <1> ; 2: 3697 <1> ; jmp (r0) 2122 %include 'u9.s' ; 29/06/2015 2123 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - SYS9.INC 2124 <1> ; Last Modification: 13/06/2022 2125 <1> ; ---------------------------------------------------------------------------- 2126 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 2127 <1> ; (v0.1 - Beginning: 11/07/2012) 2128 <1> ; 2129 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2130 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2131 <1> ; 2132 <1> ; 2133 <1> ; 2134 <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s 2135 <1> ; 2136 <1> ; **************************************************************************** 2137 <1> 2138 <1> getch: 2139 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2140 <1> ; 30/06/2015 2141 <1> ; 18/02/2015 - Retro UNIX 386 v1 - feature only! 2142 00005574 28C0 <1> sub al, al ; 0 2143 <1> getch_q: ; 06/08/2015 2144 00005576 8A25[56610000] <1> mov ah, [ptty] ; active (current) video page 2145 0000557C EB06 <1> jmp short getc_n 2146 <1> 2147 <1> getc: 2148 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2149 <1> ; 12/11/2015 2150 <1> ; 15/09/2015 2151 <1> ; 01/07/2015 2152 <1> ; 30/06/2015 2153 <1> ; 18/02/2015 (Retro UNIX 386 v1 - Beginning) 2154 <1> ; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1) 2155 <1> ; 2156 <1> ; Retro UNIX 8086 v1 modification ! 2157 <1> ; 2158 <1> ; 'getc' gets (next) character 2159 <1> ; from requested TTY (keyboard) buffer 2160 <1> ; INPUTS -> 2161 <1> ; [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2) 2162 <1> ; AL=0 -> Get (next) character from requested TTY buffer 2163 <1> ; (Keyboard buffer will point to 2164 <1> ; next character at next call) 2165 <1> ; AL=1 -> Test a key is available in requested TTY buffer 2166 <1> ; (Keyboard buffer will point to 2167 <1> ; current character at next call) 2168 <1> ; OUTPUTS -> 2169 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 2170 <1> ; ZF=0 -> AX has (current) character 2171 <1> ; AL = ascii code 2172 <1> ; AH = scan code (AH = line status for COM1 or COM2) 2173 <1> ; (cf=1 -> error code/flags in AH) 2174 <1> ; Original UNIX V1 'getc': 2175 <1> ; get a character off character list 2176 <1> ; 2177 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2178 <1> ; 2179 <1> ; 30/06/2015 (32 bit modifications) 2180 <1> ; 16/07/2013 2181 <1> ; mov [getctty], ah 2182 <1> ; 2183 <1> 2184 0000557E 8A25[40650000] <1> mov ah, [u.ttyn] ; 28/07/2013 2185 <1> getc_n: 2186 <1> ; 30/06/2015 2187 00005584 08E4 <1> or ah, ah 2188 00005586 740D <1> jz short getc0 2189 00005588 D0E4 <1> shl ah, 1 2190 0000558A 0FB6DC <1> movzx ebx, ah 2191 0000558D 81C3[58610000] <1> add ebx, ttychr 2192 00005593 EB05 <1> jmp short getc1 2193 <1> getc0: 2194 00005595 BB[58610000] <1> mov ebx, ttychr 2195 <1> getc1: 2196 0000559A 668B0B <1> mov cx, [ebx] ; ascii & scan code 2197 <1> ; (by kb_int) 2198 0000559D 6609C9 <1> or cx, cx 2199 000055A0 7507 <1> jnz short getc2 2200 000055A2 20C0 <1> and al, al 2201 000055A4 7415 <1> jz short getc_s 2202 <1> ;xor ax, ax 2203 <1> ; 24/12/2021 2204 000055A6 31C0 <1> xor eax, eax 2205 000055A8 C3 <1> retn 2206 <1> getc2: 2207 000055A9 20C0 <1> and al, al 2208 000055AB 6689C8 <1> mov ax, cx 2209 000055AE 66B90000 <1> mov cx, 0 2210 000055B2 7506 <1> jnz short getc3 2211 <1> getc_sn: 2212 000055B4 66890B <1> mov [ebx], cx ; 0, reset 2213 000055B7 6639C8 <1> cmp ax, cx ; zf = 0 2214 <1> getc3: 2215 000055BA C3 <1> retn 2216 <1> getc_s: 2217 <1> ; 12/11/2015 2218 <1> ; 15/09/2015 2219 <1> ; 01/07/2015 2220 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2221 <1> ; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1) 2222 <1> ; 2223 <1> ; tty of the current process is not 2224 <1> ; current tty (ptty); so, current process only 2225 <1> ; can use keyboard input when its tty becomes 2226 <1> ; current tty (ptty). 2227 <1> ; 'sleep' is for preventing an endless lock 2228 <1> ; during this tty input request. 2229 <1> ; (Because, the user is not looking at the video page 2230 <1> ; of the process to undersand there is a keyboard 2231 <1> ; input request.) 2232 <1> ; 2233 <1> ;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2234 <1> ; 2235 <1> ; 05/10/2013 2236 <1> ; ah = byte ptr [u.ttyn] ; (tty number) 2237 <1> ; 2238 <1> ; 10/10/2013 2239 <1> gcw0: 2240 000055BB B10A <1> mov cl, 10 ; ch = 0 2241 <1> gcw1: 2242 <1> ; 12/11/2015 2243 000055BD E816DCFFFF <1> call intract ; jumps to 'sysexit' if [u.quit] = FFFFh 2244 <1> ; 10/10/2013 2245 000055C2 E8B2EFFFFF <1> call idle 2246 000055C7 668B03 <1> mov ax, [ebx] ; ascii & scan code 2247 <1> ; (by kb_int) 2248 000055CA 6609C0 <1> or ax, ax 2249 <1> ; jnz short gcw3 2250 000055CD 7519 <1> jnz short gcw2 ; 15/09/2015 2251 <1> ; 30/06/2015 2252 000055CF FEC9 <1> dec cl 2253 000055D1 75EA <1> jnz short gcw1 2254 <1> ; 2255 000055D3 8A25[40650000] <1> mov ah, [u.ttyn] ; 20/10/2013 2256 <1> ; ; 10/12/2013 2257 <1> ; cmp ah, [ptty] 2258 <1> ; jne short gcw2 2259 <1> ; ; 14/02/2014 2260 <1> ; cmp byte [u.uno], 1 2261 <1> ; jna short gcw0 2262 <1> ;gcw2: 2263 000055D9 E828F0FFFF <1> call sleep 2264 <1> ; 2265 <1> ; 20/09/2013 2266 000055DE 8A25[40650000] <1> mov ah, [u.ttyn] 2267 000055E4 30C0 <1> xor al, al 2268 000055E6 EB9C <1> jmp short getc_n 2269 <1> ;gcw3: 2270 <1> gcw2: ; 15/09/2015 2271 <1> ; 10/10/2013 2272 000055E8 30C9 <1> xor cl, cl 2273 000055EA EBC8 <1> jmp short getc_sn 2274 <1> 2275 <1> putc: 2276 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2277 <1> ; 13/08/2015 2278 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2279 <1> ; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1) 2280 <1> ; 2281 <1> ; Retro UNIX 8086 v1 modification ! 2282 <1> ; 2283 <1> ; 'putc' puts a character 2284 <1> ; onto requested (tty) video page or 2285 <1> ; serial port 2286 <1> ; INPUTS -> 2287 <1> ; AL = ascii code of the character 2288 <1> ; AH = video page (tty) number (0 to 7) 2289 <1> ; (8 is COM1, 9 is COM2) 2290 <1> ; OUTPUTS -> 2291 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 2292 <1> ; ZF=0 -> AX has (current) character 2293 <1> ; cf=0 and AH = 0 -> no error 2294 <1> ; cf=1 and AH > 0 -> error (only for COM1 and COM2) 2295 <1> ; 2296 <1> ; Original UNIX V1 'putc': 2297 <1> ; put a character at the end of character list 2298 <1> ; 2299 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 2300 <1> ; 2301 000055EC 80FC07 <1> cmp ah, 7 2302 <1> ;ja sndc 2303 000055EF 770A <1> ja short sndc ; 24/12/2024 2304 <1> ; 30/06/2015 2305 000055F1 0FB6DC <1> movzx ebx, ah 2306 <1> ; 13/08/2015 2307 000055F4 B407 <1> mov ah, 07h ; black background, light gray character color 2308 000055F6 E9A1BCFFFF <1> jmp write_tty ; 'video.inc' 2309 <1> 2310 <1> sndc: ; 2311 <1> ; 2312 <1> ; 12/01/2022 2313 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2314 <1> ; 17/11/2015 2315 <1> ; 16/11/2015 2316 <1> ; 11/11/2015 2317 <1> ; 10/11/2015 2318 <1> ; 09/11/2015 2319 <1> ; 08/11/2015 2320 <1> ; 07/11/2015 2321 <1> ; 06/11/2015 (serial4.asm, 'sendchr') 2322 <1> ; 29/10/2015 2323 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 2324 <1> ; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1) 2325 <1> ; 2326 <1> ; Retro UNIX 8086 v1 feature only ! 2327 <1> ; 2328 <1> ; ah = [u.ttyn] 2329 <1> ; 2330 <1> ; 30/06/2015 2331 000055FB 80EC08 <1> sub ah, 8 ; ; 0 = tty8 or 1 = tty9 2332 <1> ; 07/11/2015 2333 000055FE 0FB6DC <1> movzx ebx, ah ; serial port index (0 or 1) 2334 <1> sndc0: 2335 <1> ; 07/11/2015 2336 00005601 E84EF0FFFF <1> call isintr ; quit (ctrl+break) check 2337 00005606 7405 <1> jz short sndc1 2338 00005608 E8CBDBFFFF <1> call intract ; quit (ctrl+break) check 2339 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 2340 <1> sndc1: 2341 <1> ; 16/11/2015 2342 <1> ;mov cx, ax ; *** al = character (to be sent) 2343 <1> ; 24/12/2021 2344 0000560D 89C1 <1> mov ecx, eax ; *** al = character (to be sent) 2345 <1> sndcx: 2346 0000560F 8A83[9A610000] <1> mov al, [ebx+schar] ; last sent character 2347 00005615 8AA3[98610000] <1> mov ah, [ebx+rchar] ; last received character 2348 <1> ; 2349 <1> ; 17/11/2015 2350 <1> ; check 'request for response' status 2351 0000561B 80BB[94610000]00 <1> cmp byte [ebx+req_resp], 0 2352 00005622 740A <1> jz short query 2353 <1> response: 2354 00005624 FE05[97610000] <1> inc byte [comqr] ; query or response status 2355 0000562A B0FF <1> mov al, 0FFh 2356 0000562C EB14 <1> jmp short sndc3 2357 <1> query: 2358 0000562E 08C0 <1> or al, al ; 0 = query (also end of text) 2359 00005630 750E <1> jnz short sndc2 ; normal character 2360 <1> ;cmp ah, 0FFh ; is it responded by terminal ? 2361 <1> ;je short sndc2 ; yes, already responded 2362 <1> ; 16/11/2015 2363 <1> ; query: request for response (again) 2364 00005632 8883[98610000] <1> mov [ebx+rchar], al ; 0 ; reset 2365 00005638 FE05[97610000] <1> inc byte [comqr] ; query or response status 2366 0000563E EB02 <1> jmp short sndc3 2367 <1> sndc2: 2368 00005640 88C8 <1> mov al, cl ; *** character (to be sent) 2369 <1> sndc3: 2370 00005642 8883[9A610000] <1> mov [ebx+schar], al ; current character (to be sent) 2371 00005648 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 2372 <1> ; 30/06/2015 2373 0000564A E832D5FFFF <1> call sp_status ; get serial port status 2374 <1> ; AL = Line status, AH = Modem status 2375 <1> ; 07/11/2015 2376 0000564F A880 <1> test al, 80h 2377 00005651 7504 <1> jnz short sndc4 2378 00005653 A820 <1> test al, 20h ; Transmitter holding register empty ? 2379 00005655 751A <1> jnz short sndc5 2380 <1> sndc4: ; Check line status again 2381 <1> ; 16/11/2015 2382 <1> ;push cx 2383 <1> ; 24/12/2021 2384 00005657 51 <1> push ecx 2385 <1> ;mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 2386 <1> ; 12/01/2022 2387 00005658 31C9 <1> xor ecx, ecx 2388 0000565A B106 <1> mov cl, 6 2389 0000565C E832BDFFFF <1> call WAITF 2390 <1> ;pop cx 2391 <1> ; 24/12/1021 2392 00005661 59 <1> pop ecx 2393 <1> ; 2394 00005662 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 2395 00005664 E818D5FFFF <1> call sp_status ; get serial port status 2396 <1> ; 16/11/2015 2397 <1> ; 09/11/2015 2398 <1> ; 08/11/2015 2399 00005669 A880 <1> test al, 80h ; time out error 2400 0000566B 7565 <1> jnz short sndc7 2401 0000566D A820 <1> test al, 20h ; Transmitter holding register empty ? 2402 0000566F 7461 <1> jz short sndc7 2403 <1> sndc5: 2404 00005671 8A83[9A610000] <1> mov al, [ebx+schar] ; character (to be sent) 2405 00005677 66BAF803 <1> mov dx, 3F8h ; data port (COM2) 2406 0000567B 28DE <1> sub dh, bl 2407 0000567D EE <1> out dx, al ; send on serial port 2408 <1> ; 10/11/2015 2409 <1> ; delay for 3*30 (3*(15..80)) micro seconds 2410 <1> ; (to improve text flow to the terminal) 2411 <1> ; ('diskette.inc': 'WAITF') 2412 <1> ; Uses port 61h, bit 4 to have CPU speed independent waiting. 2413 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2414 <1> ;push cx 2415 <1> ; 24/12/2021 2416 0000567E 51 <1> push ecx 2417 <1> ;mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 2418 <1> ; 12/01/2022 2419 0000567F 29C9 <1> sub ecx, ecx 2420 00005681 B106 <1> mov cl, 6 2421 00005683 E80BBDFFFF <1> call WAITF 2422 <1> ;pop cx 2423 <1> ; 24/12/1021 2424 00005688 59 <1> pop ecx 2425 <1> ; 2426 <1> ; 07/11/2015 2427 00005689 88D8 <1> mov al, bl ; al = 0 (tty8) or 1 (tty9) 2428 <1> ; 2429 0000568B E8F1D4FFFF <1> call sp_status ; get serial port status 2430 <1> ; AL = Line status, AH = Modem status 2431 <1> ; 2432 00005690 E8BFEFFFFF <1> call isintr ; quit (ctrl+break) check 2433 00005695 7405 <1> jz short sndc6 2434 00005697 E83CDBFFFF <1> call intract ; quit (ctrl+break) check 2435 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 2436 <1> sndc6: 2437 0000569C 3C80 <1> cmp al, 80h 2438 0000569E 7332 <1> jnb short sndc7 2439 <1> ; 2440 000056A0 803D[97610000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 2441 000056A7 7244 <1> jb short sndc8 ; no, normal character 2442 000056A9 883D[97610000] <1> mov byte [comqr], bh ; 0 ; reset 2443 <1> ; 17/11/2015 2444 000056AF E8C5EEFFFF <1> call idle 2445 <1> ; 2446 000056B4 38BB[9A610000] <1> cmp [ebx+schar], bh ; 0 ; query ? 2447 <1> ;ja sndc2 ; response (will be followed by 2448 <1> ; a normal character) 2449 <1> ; 24/12/2021 2450 000056BA 7602 <1> jna short sndc_10 2451 000056BC EB82 <1> jmp sndc2 2452 <1> sndc_10: 2453 <1> ; Query request must be responded by the terminal 2454 <1> ; before sending a normal character ! 2455 000056BE 53 <1> push ebx 2456 <1> ;push cx ; *** cl = character (to be sent) 2457 <1> ; 24/12/2021 2458 000056BF 51 <1> push ecx ; *** cl = character (to be sent) 2459 000056C0 8A25[40650000] <1> mov ah, [u.ttyn] 2460 000056C6 E83BEFFFFF <1> call sleep ; this process will be awakened by 2461 <1> ; received data available interrupt 2462 <1> ;pop cx ; *** cl = character (to be sent) 2463 <1> ; 24/12/2021 2464 000056CB 59 <1> pop ecx ; *** cl = character (to be sent) 2465 000056CC 5B <1> pop ebx 2466 000056CD E93DFFFFFF <1> jmp sndcx 2467 <1> sndc7: 2468 <1> ; 16/11/2015 2469 000056D2 803D[97610000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 2470 000056D9 7213 <1> jb short sndc9 ; no 2471 <1> ; 2472 000056DB 88BB[98610000] <1> mov [ebx+rchar], bh ; 0 ; reset 2473 000056E1 88BB[9A610000] <1> mov [ebx+schar], bh ; 0 ; reset 2474 <1> ; 2475 000056E7 883D[97610000] <1> mov byte [comqr], bh ; 0 ; reset 2476 <1> sndc8: 2477 000056ED F5 <1> cmc ; jnc -> jc, jb -> jnb 2478 <1> sndc9: 2479 <1> ; AL = Line status, AH = Modem status 2480 000056EE C3 <1> retn 2481 <1> 2482 <1> get_cpos: 2483 <1> ; 29/06/2015 (Retro UNIX 386 v1) 2484 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 2485 <1> ; 2486 <1> ; INPUT -> bl = video page number 2487 <1> ; RETURN -> dx = cursor position 2488 <1> 2489 000056EF 53 <1> push ebx 2490 000056F0 83E30F <1> and ebx, 0Fh ; 07h ; tty0 to tty7 2491 000056F3 D0E3 <1> shl bl, 1 2492 000056F5 81C3[46610000] <1> add ebx, cursor_posn 2493 000056FB 668B13 <1> mov dx, [ebx] 2494 000056FE 5B <1> pop ebx 2495 000056FF C3 <1> retn 2496 <1> 2497 <1> read_ac_current: 2498 <1> ; 29/06/2015 (Retro UNIX 386 v1) 2499 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 2500 <1> ; 2501 <1> ; INPUT -> bl = video page number 2502 <1> ; RETURN -> ax = character (al) and attribute (ah) 2503 <1> 2504 00005700 E8FDBCFFFF <1> call find_position ; 'video.inc' 2505 <1> ; dx = status port 2506 <1> ; esi = cursor location/address 2507 00005705 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 2508 0000570B 668B06 <1> mov ax, [esi] ; get the character and attribute 2509 0000570E C3 <1> retn 2510 <1> 2511 <1> syssleep: 2512 <1> ; 29/06/2015 - (Retro UNIX 386 v1) 2513 <1> ; 11/06/2014 - (Retro UNIX 8086 v1) 2514 <1> ; 2515 <1> ; Retro UNIX 8086 v1 feature only 2516 <1> ; (INPUT -> none) 2517 <1> ; 2518 0000570F 0FB61D[3B650000] <1> movzx ebx, byte [u.uno] ; process number 2519 00005716 8AA3[43620000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 2520 0000571C E8E5EEFFFF <1> call sleep 2521 00005721 E9C5D9FFFF <1> jmp sysret 2522 <1> 2523 <1> ; 27/02/2022 2524 <1> ; (u1.s, 'wttyc' & 'wpc_clr') 2525 <1> %if 0 2526 <1> 2527 <1> vp_clr: 2528 <1> ; Reset/Clear Video Page 2529 <1> ; 2530 <1> ; 24/12/2021 - (Retro UNIX 386 v1.1) 2531 <1> ; 30/06/2015 - (Retro UNIX 386 v1) 2532 <1> ; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM) 2533 <1> ; 2534 <1> ; Retro UNIX 8086 v1 feature only ! 2535 <1> ; 2536 <1> ; INPUTS -> 2537 <1> ; BL = video page number 2538 <1> ; 2539 <1> ; OUTPUT -> 2540 <1> ; none 2541 <1> ; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI)) 2542 <1> ; 2543 <1> ; 04/12/2013 2544 <1> sub al, al 2545 <1> ; al = 0 (clear video page) 2546 <1> ; bl = video page 2547 <1> mov ah, 07h 2548 <1> ; ah = 7 (attribute/color) 2549 <1> ;xor cx, cx ; 0, left upper column (cl) & row (cl) 2550 <1> ; 24/12/2021 2551 <1> xor ecx, ecx 2552 <1> mov dx, 184Fh ; right lower column & row (dl=24, dh=79) 2553 <1> call scroll_up 2554 <1> ; bl = video page 2555 <1> ;xor dx, dx ; 0 (cursor position) 2556 <1> ; 24/12/2021 2557 <1> xor edx, edx 2558 <1> jmp set_cpos 2559 <1> 2560 <1> %endif 2561 <1> 2562 <1> sysmsg: 2563 <1> ; 24/12/2021 (Retro UNIX 386 v1.1) 2564 <1> ; 11/11/2015 2565 <1> ; 01/07/2015 - (Retro UNIX 386 v1 feature only!) 2566 <1> ; Print user-application message on user's console tty 2567 <1> ; 2568 <1> ; Input -> EBX = Message address 2569 <1> ; ECX = Message length (max. 255) 2570 <1> ; DL = Color (IBM PC Rombios color attributes) 2571 <1> ; 2572 00005726 81F9FF000000 <1> cmp ecx, MAX_MSG_LEN ; 255 2573 <1> ;ja sysret ; nothing to do with big message size 2574 0000572C 7779 <1> ja short sysmsg8 ; 24/12/2021 2575 0000572E 08C9 <1> or cl, cl 2576 <1> ;jz sysret 2577 00005730 7475 <1> jz short sysmsg8 ; 24/12/2021 2578 00005732 20D2 <1> and dl, dl 2579 00005734 7502 <1> jnz short sysmsg0 2580 00005736 B207 <1> mov dl, 07h ; default color 2581 <1> ; (black background, light gray character) 2582 <1> sysmsg0: 2583 00005738 891D[0C650000] <1> mov [u.base], ebx 2584 0000573E 8815[57610000] <1> mov [ccolor], dl ; color attributes 2585 00005744 89E5 <1> mov ebp, esp 2586 00005746 31DB <1> xor ebx, ebx ; 0 2587 00005748 891D[14650000] <1> mov [u.nread], ebx ; 0 2588 <1> ; 2589 0000574E 381D[53650000] <1> cmp [u.kcall], bl ; 0 2590 00005754 7772 <1> ja short sysmsgk ; Temporary (01/07/2015) 2591 <1> ; 2592 00005756 890D[10650000] <1> mov [u.count], ecx 2593 0000575C 41 <1> inc ecx ; + 00h ; ASCIIZ 2594 <1> ; 24/12/2021 2595 <1> ; (dword alignment for esp) 2596 0000575D F6C103 <1> test cl, 3 2597 00005760 7404 <1> jz short sysmsg_7 2598 00005762 80C903 <1> or cl, 3 2599 00005765 41 <1> inc ecx 2600 <1> sysmsg_7: 2601 00005766 29CC <1> sub esp, ecx 2602 00005768 89E7 <1> mov edi, esp 2603 0000576A 89E6 <1> mov esi, esp 2604 0000576C 66891D[51650000] <1> mov [u.pcount], bx ; reset page (phy. addr.) counter 2605 <1> ; 11/11/2015 2606 00005773 8A25[1C650000] <1> mov ah, [u.ttyp] ; recent open tty 2607 <1> ; 0 = none 2608 00005779 FECC <1> dec ah 2609 0000577B 790C <1> jns short sysmsg1 2610 0000577D 8A1D[3B650000] <1> mov bl, [u.uno] ; process number 2611 00005783 8AA3[43620000] <1> mov ah, [ebx+p.ttyc-1] ; user's (process's) console tty 2612 <1> sysmsg1: 2613 00005789 8825[40650000] <1> mov [u.ttyn], ah 2614 <1> sysmsg2: 2615 0000578F E84BF6FFFF <1> call cpass 2616 00005794 7416 <1> jz short sysmsg5 2617 00005796 AA <1> stosb 2618 00005797 20C0 <1> and al, al 2619 00005799 75F4 <1> jnz short sysmsg2 2620 <1> sysmsg3: 2621 0000579B 80FC07 <1> cmp ah, 7 ; tty number 2622 0000579E 7711 <1> ja short sysmsg6 ; serial port 2623 000057A0 E83E000000 <1> call print_cmsg 2624 <1> sysmsg4: 2625 000057A5 89EC <1> mov esp, ebp 2626 <1> sysmsg8: ; 24/12/2021 2627 000057A7 E93FD9FFFF <1> jmp sysret 2628 <1> sysmsg5: 2629 000057AC C60700 <1> mov byte [edi], 0 2630 000057AF EBEA <1> jmp short sysmsg3 2631 <1> sysmsg6: 2632 000057B1 8A06 <1> mov al, [esi] 2633 000057B3 E843FEFFFF <1> call sndc 2634 000057B8 72EB <1> jc short sysmsg4 2635 000057BA 803E00 <1> cmp byte [esi], 0 ; 0 is stop character 2636 000057BD 76E6 <1> jna short sysmsg4 2637 000057BF 46 <1> inc esi 2638 000057C0 8A25[40650000] <1> mov ah, [u.ttyn] 2639 000057C6 EBE9 <1> jmp short sysmsg6 2640 <1> 2641 <1> sysmsgk: ; Temporary (01/07/2015) 2642 <1> ; The message has been sent by Kernel (ASCIIZ string) 2643 <1> ; (ECX -character count- will not be considered) 2644 000057C8 8B35[0C650000] <1> mov esi, [u.base] 2645 000057CE 8A25[56610000] <1> mov ah, [ptty] ; present/current screen (video page) 2646 000057D4 8825[40650000] <1> mov [u.ttyn], ah 2647 000057DA C605[53650000]00 <1> mov byte [u.kcall], 0 2648 000057E1 EBB8 <1> jmp short sysmsg3 2649 <1> 2650 <1> print_cmsg: 2651 <1> ; 01/07/2015 (retro UNIX 386 v1 feature only !) 2652 <1> ; 2653 <1> ; print message (on user's console tty) 2654 <1> ; with requested color 2655 <1> ; 2656 <1> ; INPUTS: 2657 <1> ; esi = message address 2658 <1> ; [u.ttyn] = tty number (0 to 7) 2659 <1> ; [ccolor] = color attributes (IBM PC BIOS colors) 2660 <1> ; 2661 000057E3 AC <1> lodsb 2662 <1> pcmsg1: 2663 000057E4 56 <1> push esi 2664 000057E5 0FB61D[40650000] <1> movzx ebx, byte [u.ttyn] 2665 000057EC 8A25[57610000] <1> mov ah, [ccolor] 2666 000057F2 E8A5BAFFFF <1> call write_tty 2667 000057F7 5E <1> pop esi 2668 000057F8 AC <1> lodsb 2669 000057F9 20C0 <1> and al, al ; 0 2670 000057FB 75E7 <1> jnz short pcmsg1 2671 000057FD C3 <1> retn 2672 <1> 2673 <1> sysgeterr: 2674 <1> ; 16/02/2022 - Retro UNIX 386 v1.1 2675 <1> ; 09/12/2015 2676 <1> ; 21/09/2015 - (Retro UNIX 386 v1 feature only!) 2677 <1> ; Get last error number or page fault count 2678 <1> ; (for debugging) 2679 <1> ; 2680 <1> ; Input -> EBX = return type 2681 <1> ; 0 = last error code (which is in 'u.error') 2682 <1> ; FFFFFFFFh = page fault count for running process 2683 <1> ; FFFFFFFEh = total page fault count 2684 <1> ; 1 .. FFFFFFFDh = undefined 2685 <1> ; 2686 <1> ; Output -> EAX = last error number or page fault count 2687 <1> ; (depending on EBX input) 2688 <1> ; 2689 000057FE 21DB <1> and ebx, ebx 2690 00005800 750F <1> jnz short glerr_2 2691 <1> glerr_0: 2692 00005802 A1[41650000] <1> mov eax, [u.error] 2693 <1> glerr_1: 2694 00005807 A3[EC640000] <1> mov [u.r0], eax 2695 <1> ;retn 2696 <1> ; 16/02/2022 (BugFix) 2697 0000580C E9DAD8FFFF <1> jmp sysret 2698 <1> glerr_2: 2699 00005811 43 <1> inc ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh 2700 00005812 74FD <1> jz short glerr_2 ; page fault count for process 2701 00005814 43 <1> inc ebx ; FFFFFFFFh -> 0 2702 00005815 75EB <1> jnz short glerr_0 2703 00005817 A1[DC610000] <1> mov eax, [PF_Count] ; total page fault count 2704 0000581C EBE9 <1> jmp short glerr_1 2705 <1> glerr_3: 2706 0000581E A1[55650000] <1> mov eax, [u.pfcount] 2707 00005823 EBE2 <1> jmp short glerr_1 2708 <1> 2709 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 2710 <1> ; - PRINTER BIOS (Functions) 2711 <1> 2712 <1> ;;; IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985 ;;; 2713 <1> ; 2714 <1> ;--- INT 17 H ------------------------------------------------------------------ 2715 <1> ; PRINTER_IO : 2716 <1> ; THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER : 2717 <1> ; INPUT : 2718 <1> ; (AH)= 00H PRINT THE CHARACTER IN (AL) : 2719 <1> ; ON RETURN, (AH)= 1 IF CHARACTER NOT BE PRINTED (TIME OUT) : 2720 <1> ; OTHER BITS SET AS ON NORMAL STATUS CALL : 2721 <1> ; (AH)= 01H INITIALIZE THE PRINTER PORT : 2722 <1> ; RETURNS WITH (AH) SET WITH PRINTER STATUS : 2723 <1> ; (AH)= 02H READ THE PRINTER STATUS INTO (AH) : 2724 <1> ; 7 6 5 4 3 2-1 0 : 2725 <1> ; | | | | | | |_TIME OUT : 2726 <1> ; | | | | | | : 2727 <1> ; | | | | | |_ UNUSED : 2728 <1> ; | | | | | : 2729 <1> ; | | | | |_ 1 = I/O ERROR : 2730 <1> ; | | | | : 2731 <1> ; | | | |_ 1 = SELECTED : 2732 <1> ; | | | : 2733 <1> ; | | |_ 1 = OUT OF PAPER : 2734 <1> ; | | : 2735 <1> ; | |_ 1 = ACKNOWLEDGE : 2736 <1> ; | : 2737 <1> ; |_ 1 = NOT BUSY : 2738 <1> ; : 2739 <1> ; (DX) = PRINTER TO BE USED (0,1,2) CORRESPONDING TO ACTUAL VALUES : 2740 <1> ; IN @PRINTER_BASE AREA : 2741 <1> ; DATA AREA @PRINTER_BASE CONTAINS THE BASE ADDRESS OF THE PRINTER CARD(S) : 2742 <1> ; AVAILABLE (LOCATED AT BEGINNING OF DATA SEGMENT, 408H ABSOLUTE, 3 WORDS) : 2743 <1> ; : 2744 <1> ; DATA AREA @PRINT_TIM_OUT (BYTE) MAY BE CHANGED TO CAUSE DIFFERENT : 2745 <1> ; TIME OUT WAITS. DEFAULT=20 * 4 : 2746 <1> ; : 2747 <1> ; REGISTERS (AH) IS MODIFIED WITH STATUS INFORMATION : 2748 <1> ; ALL OTHERS UNCHANGED : 2749 <1> ;------------------------------------------------------------------------------- 2750 <1> 2751 <1> int17h: 2752 <1> ; 13/06/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.4) 2753 <1> ; (Derived from: IBM PC-AT BIOS v3 - PRT.ASM - 15/11/1985) 2754 <1> ; 2755 <1> ; (Default printer port: 378h) ; LPT1 2756 <1> ; (Number of printers = 1) 2757 <1> 2758 <1> PRINTER_BASE equ 378h ; LPT1 2759 <1> ;PRINT_TIM_OUT equ 4*80*65536 2760 <1> ; (Ref: IBM PC-AT BIOS v2 PRT.ASM) 2761 <1> 2762 <1> PRINT_TIM_OUT equ 36000 ; WAIT_PRN_NBUSY 2763 <1> ; (Ref: AWARD BIOS 1999 ATORGS.ASM) 2764 <1> 2765 <1> ; INPUT: 2766 <1> ; ah = 0 -> print the character in AL 2767 <1> ; (sys write with write count >0) 2768 <1> ; ah = 1 -> initialize printer port 2769 <1> ; (sys open) 2770 <1> ; ah = 2 -> read the printer status 2771 <1> ; (sys write with write count = 0) 2772 <1> ; OUTPUT: 2773 <1> ; ah = printer status 2774 <1> 2775 <1> ; Modified registers: eax, ecx, edx 2776 <1> 2777 <1> PRINTER_IO_1: 2778 00005825 08E4 <1> or ah, ah 2779 00005827 7417 <1> jz short _b20 2780 00005829 FECC <1> dec ah 2781 0000582B 7444 <1> jz short _b80 2782 <1> ;dec ah 2783 <1> ;jz short _b50 2784 <1> _b50: 2785 <1> ;----- PRINTER STATUS 2786 <1> B50: 2787 0000582D 50 <1> push eax ; SAVE (AL) REGISTER 2788 <1> B60: 2789 0000582E 66BA7903 <1> mov dx, PRINTER_BASE+1 2790 <1> ; GET PRINTER ATTACHMENT BASE ADDRESS 2791 <1> ; POINT TO CONTROL PORT 2792 00005832 EC <1> in al, dx ; PRE-CHARGE +BUSY LINE IF FLOATING 2793 00005833 EC <1> in al, dx ; GET PRINTER STATUS HARDWARE BITS 2794 00005834 88C4 <1> mov ah, al ; SAVE 2795 00005836 80E4F8 <1> and ah, 0F8h ; TURN OFF UNUSED BITS 2796 <1> B70: 2797 00005839 5A <1> pop edx ; RECOVER (AL) REGISTER 2798 0000583A 88D0 <1> mov al, dl ; MOVE CHARACTER INTO (AL) 2799 0000583C 80F448 <1> xor ah, 48h ; FLIP A COUPLE OF BITS 2800 <1> B10: 2801 0000583F C3 <1> retn ; RETURN FROM ROUTINE WITH STATUS IN AH 2802 <1> _b20: 2803 <1> ;----- PRINT THE CHARACTER IN (AL) 2804 00005840 B9A08C0000 <1> mov ecx, PRINT_TIM_OUT ; (1 second) 2805 <1> B20: 2806 00005845 50 <1> push eax ; SAVE VALUE TO PRINT 2807 00005846 66BA7803 <1> mov dx, PRINTER_BASE 2808 0000584A EE <1> out dx, al ; OUTPUT CHARACTER TO DATA PORT 2809 0000584B FEC2 <1> inc dl ; POINT TO STATUS PORT 2810 <1> 2811 <1> ;----- CHECK FOR PRINTER BUSY 2812 <1> B25: 2813 <1> ;----- WAIT BUSY 2814 <1> B35: 2815 0000584D EC <1> in al, dx ; GET STATUS 2816 0000584E 88C4 <1> mov ah, al ; STATUS TO (AH) ALSO 2817 00005850 A880 <1> test al, 80h ; IS THE PRINTER CURRENTLY BUSY? (*) 2818 00005852 750F <1> jnz short B40 ; GO TO OUTPUT STROBE 2819 00005854 E831000000 <1> call WAIT_REFRESH ; (wait for 30 micro seconds) 2820 00005859 E2F2 <1> loop B35 ; LOOP IF YES (*) 2821 <1> 2822 0000585B 80CC01 <1> or ah, 1 ; SET ERROR FLAG 2823 0000585E 80E4F9 <1> and ah, 0F9h ; TURN OFF THE UNUSED BITS 2824 00005861 EBD6 <1> jmp short B70 ; RETURN WITH ERROR FLAG SET 2825 <1> 2826 <1> B40: ; SEND STROBE PULSE 2827 00005863 B00D <1> mov al, 0Dh ; SET THE STROBE LOW (BIT ON) 2828 00005865 6642 <1> inc dx ; OUTPUT STROBE TO CONTROL PORT 2829 00005867 FA <1> cli ; PREVENT INTERRUPT PULSE STRETCHING 2830 00005868 EE <1> out dx, al ; OUTPUT STROBE BIT > 1us < 5us 2831 <1> ; IODELAY 2832 <1> ;jmp short $+2 ; I/O DELAY TO ALLOW FOR LINE LOADING 2833 <1> ;jmp short $+2 ; AND FOR CORRECT PULSE WIDTH 2834 <1> ; NEWIODELAY 2835 00005869 E6EB <1> out 0EBh, al 2836 <1> 2837 0000586B B00C <1> mov al, 0Ch ; SET THE -STROBE HIGH 2838 0000586D EE <1> out dx, al 2839 0000586E FB <1> sti ; INTERRUPTS BACK ON 2840 <1> ;pop eax ; RECOVER THE OUTPUT CHAR 2841 <1> ;jmp short B50 2842 0000586F EBBD <1> jmp short B60 2843 <1> 2844 <1> _b80: 2845 <1> ;----- INITIALIZE THE PRINTER PORT 2846 <1> B80: 2847 00005871 50 <1> push eax ; SAVE (AL) 2848 00005872 66BA7A03 <1> mov dx, PRINTER_BASE+2 ; POINT TO OUTPUT PORT 2849 00005876 B008 <1> mov al, 8 ; SET INIT LINE LOW 2850 00005878 EE <1> out dx, al 2851 <1> ;mov eax, 1000*4 ; ADJUST FOR INITIALIZATION DELAY LOOP 2852 00005879 B989080000 <1> mov ecx, WAIT_PRN_INIT ; (65536 micro seconds) 2853 <1> B90: ; INIT_LOOP 2854 <1> ;dec eax ; LOOP FOR RESET TO TAKE 2855 <1> ;jnz short B90 ; INIT_LOOP 2856 0000587E E807000000 <1> call WAIT_REFRESH ; (wait for 30 micro seconds) 2857 00005883 E2F9 <1> loop B90 2858 00005885 B00C <1> mov al, 0Ch ; NO INTERRUPTS, NON AUTO LF, INIT HIGH 2859 00005887 EE <1> out dx, al 2860 00005888 EBA4 <1> jmp short B60 ; EXIT THROUGH STATUS ROUTINE 2861 <1> 2862 <1> 2863 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 2864 <1> ; ------------------------------------------------------------------- 2865 <1> ; 2866 <1> ;;Wait while printer initializes should be 65,536 microseconds. 2867 <1> ;;65536/30 = 2185 2868 <1> ; PUBLIC WAIT_PRN_INIT_LO 2869 <1> ;WAIT_PRN_INIT_LO DW 2185 2870 <1> ; PUBLIC WAIT_PRN_INIT_HI 2871 <1> ;WAIT_PRN_INIT_HI DW 0 2872 <1> ; 2873 <1> WAIT_PRN_INIT equ 2185 ; 12/06/2022 2874 <1> ; 2875 <1> ;;Wait for printer not busy should be 1,080,000 microseconds. 2876 <1> ;;Memory refresh =15 us, therefore memory refresh period = 30 Us. 2877 <1> ;;1,080,000 / 30 = 36,000 2878 <1> ; PUBLIC WAIT_PRN_NBUSY_LO 2879 <1> ;WAIT_PRN_NBUSY_LO DW 36000 2880 <1> ; PUBLIC WAIT_PRN_NBUSY_HI 2881 <1> ;WAIT_PRN_NBUSY_HI DB 0 2882 <1> ; 2883 <1> ;WAIT_PRN_NBUSY equ 36000 ; 12/06/2022 2884 <1> 2885 <1> ; AWARD BIOS - 1999 - ATORGS.ASM (27/5/1999) 2886 <1> ; ------------------------------------------ 2887 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 2888 <1> ; INPUT: BX:CX = number of refresh periods to wait 2889 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 2890 <1> ; OUTPUT: BX:CX destroyed. 2891 <1> ; 2892 <1> ; SAVES: AX (except when NO STACK) 2893 <1> ; 2894 <1> ; NOTES: This routine can be (and is) used with no stack. When 2895 <1> ; used this way, AX is assumed to be destroyed. 2896 <1> 2897 <1> WAIT_REFRESH: 2898 <1> ; 13/06/2022 2899 <1> ; Modified for Retro UNIX 386 v1.1 2900 <1> 2901 <1> ; (wait for 30 micro seconds) 2902 <1> 2903 <1> SYS1 equ 61h ; PORT_B 2904 <1> 2905 <1> WR_SHORT: 2906 0000588A 50 <1> push eax 2907 <1> WR_STAT_0: 2908 0000588B E461 <1> in al, SYS1 ; wait for high to low 2909 0000588D A810 <1> test al, 10h ; transition on memory 2910 0000588F 75FA <1> jnz short WR_STAT_0 2911 <1> WR_STAT_1: 2912 00005891 E461 <1> in al, SYS1 2913 00005893 A810 <1> test al, 10h 2914 00005895 74FA <1> jz short WR_STAT_1 2915 00005897 58 <1> pop eax 2916 00005898 C3 <1> retn 2123 2124 ; 07/03/2015 2125 ; Temporary Code 2126 display_disks: 2127 00005899 803D[4C5C0000]00 cmp byte [fd0_type], 0 2128 000058A0 7605 jna short ddsks1 2129 000058A2 E87D000000 call pdskm 2130 ddsks1: 2131 000058A7 803D[4D5C0000]00 cmp byte [fd1_type], 0 2132 000058AE 760C jna short ddsks2 2133 000058B0 C605[135E0000]31 mov byte [dskx], '1' 2134 000058B7 E868000000 call pdskm 2135 ddsks2: 2136 000058BC 803D[4E5C0000]00 cmp byte [hd0_type], 0 2137 000058C3 7654 jna short ddsk6 2138 000058C5 66C705[115E0000]68- mov word [dsktype], 'hd' 2138 000058CD 64 2139 000058CE C605[135E0000]30 mov byte [dskx], '0' 2140 000058D5 E84A000000 call pdskm 2141 ddsks3: 2142 000058DA 803D[4F5C0000]00 cmp byte [hd1_type], 0 2143 000058E1 7636 jna short ddsk6 2144 000058E3 C605[135E0000]31 mov byte [dskx], '1' 2145 000058EA E835000000 call pdskm 2146 ddsks4: 2147 000058EF 803D[505C0000]00 cmp byte [hd2_type], 0 2148 000058F6 7621 jna short ddsk6 2149 000058F8 C605[135E0000]32 mov byte [dskx], '2' 2150 000058FF E820000000 call pdskm 2151 ddsks5: 2152 00005904 803D[515C0000]00 cmp byte [hd3_type], 0 2153 0000590B 760C jna short ddsk6 2154 0000590D C605[135E0000]33 mov byte [dskx], '3' 2155 00005914 E80B000000 call pdskm 2156 ddsk6: 2157 00005919 BE[225E0000] mov esi, nextline 2158 0000591E E806000000 call pdskml 2159 pdskm_ok: 2160 00005923 C3 retn 2161 pdskm: 2162 00005924 BE[0F5E0000] mov esi, dsk_ready_msg 2163 pdskml: 2164 00005929 AC lodsb 2165 0000592A 08C0 or al, al 2166 0000592C 74F5 jz short pdskm_ok 2167 0000592E 56 push esi 2168 0000592F 31DB xor ebx, ebx ; 0 2169 ; Video page 0 (bl=0) 2170 00005931 B407 mov ah, 07h ; Black background, 2171 ; light gray forecolor 2172 00005933 E864B9FFFF call write_tty 2173 00005938 5E pop esi 2174 00005939 EBEE jmp short pdskml 2175 2176 0000593B 90 align 16 2177 2178 gdt: ; Global Descriptor Table 2179 ; (30/07/2015, conforming cs) 2180 ; (26/03/2015) 2181 ; (24/03/2015, tss) 2182 ; (19/03/2015) 2183 ; (29/12/2013) 2184 ; 2185 00005940 0000000000000000 dw 0, 0, 0, 0 ; NULL descriptor 2186 ; 18/08/2014 2187 ; 8h kernel code segment, base = 00000000h 2188 00005948 FFFF0000009ACF00 dw 0FFFFh, 0, 9A00h, 00CFh ; KCODE 2189 ; 10h kernel data segment, base = 00000000h 2190 00005950 FFFF00000092CF00 dw 0FFFFh, 0, 9200h, 00CFh ; KDATA 2191 ; 1Bh user code segment, base address = 400000h ; CORE 2192 00005958 FFFB000040FACF00 dw 0FBFFh, 0, 0FA40h, 00CFh ; UCODE 2193 ; 23h user data segment, base address = 400000h ; CORE 2194 00005960 FFFB000040F2CF00 dw 0FBFFh, 0, 0F240h, 00CFh ; UDATA 2195 ; Task State Segment 2196 00005968 6700 dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 2197 ; no IO permission in ring 3) 2198 gdt_tss0: 2199 0000596A 0000 dw 0 ; TSS base address, bits 0-15 2200 gdt_tss1: 2201 0000596C 00 db 0 ; TSS base address, bits 16-23 2202 ; 49h 2203 0000596D E9 db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1) 2204 0000596E 00 db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte) 2205 gdt_tss2: 2206 0000596F 00 db 0 ; TSS base address, bits 24-31 2207 2208 gdt_end: 2209 ;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 2210 ;; Type= 1 (code)/C=0/R=1/A=0 2211 ; P= Present, DPL=0=ring 0, 1= user (0= system) 2212 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 2213 2214 ;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 2215 ;; Type= 0 (data)/E=0/W=1/A=0 2216 ; P= Present, DPL=0=ring 0, 1= user (0= system) 2217 ; 0= Data E= Expansion direction (1= down, 0= up) 2218 ; W= Writeable, A= Accessed 2219 2220 ;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 2221 ;; Type= 1 (code)/C=0/R=1/A=0 2222 ; P= Present, DPL=3=ring 3, 1= user (0= system) 2223 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 2224 2225 ;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 2226 ;; Type= 0 (data)/E=0/W=1/A=0 2227 ; P= Present, DPL=3=ring 3, 1= user (0= system) 2228 ; 0= Data E= Expansion direction (1= down, 0= up) 2229 2230 ;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3) 2231 2232 ;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 // 2233 ; = 100000h * 1000h (G=1) = 4GB 2234 ;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 // 2235 ; = FFC00h * 1000h (G=1) = 4GB - 4MB 2236 ; G= Granularity (1= 4KB), B= Big (32 bit), 2237 ; AVL= Available to programmers 2238 2239 gdtd: 2240 00005970 2F00 dw gdt_end - gdt - 1 ; Limit (size) 2241 00005972 [40590000] dd gdt ; Address of the GDT 2242 2243 ; 20/08/2014 2244 idtd: 2245 00005976 FF01 dw idt_end - idt - 1 ; Limit (size) 2246 00005978 [C05E0000] dd idt ; Address of the IDT 2247 2248 Align 4 2249 2250 ; 21/08/2014 2251 ilist: 2252 ;times 32 dd cpu_except ; INT 0 to INT 1Fh 2253 ; 2254 ; Exception list 2255 ; 25/08/2014 2256 0000597C [05080000] dd exc0 ; 0h, Divide-by-zero Error 2257 00005980 [0C080000] dd exc1 2258 00005984 [13080000] dd exc2 2259 00005988 [1A080000] dd exc3 2260 0000598C [1E080000] dd exc4 2261 00005990 [22080000] dd exc5 2262 00005994 [26080000] dd exc6 ; 06h, Invalid Opcode 2263 00005998 [2A080000] dd exc7 2264 0000599C [2E080000] dd exc8 2265 000059A0 [32080000] dd exc9 2266 000059A4 [36080000] dd exc10 2267 000059A8 [3A080000] dd exc11 2268 000059AC [3E080000] dd exc12 2269 000059B0 [42080000] dd exc13 ; 0Dh, General Protection Fault 2270 000059B4 [46080000] dd exc14 ; 0Eh, Page Fault 2271 000059B8 [4A080000] dd exc15 2272 000059BC [4E080000] dd exc16 2273 000059C0 [52080000] dd exc17 2274 000059C4 [56080000] dd exc18 2275 000059C8 [5A080000] dd exc19 2276 000059CC [5E080000] dd exc20 2277 000059D0 [62080000] dd exc21 2278 000059D4 [66080000] dd exc22 2279 000059D8 [6A080000] dd exc23 2280 000059DC [6E080000] dd exc24 2281 000059E0 [72080000] dd exc25 2282 000059E4 [76080000] dd exc26 2283 000059E8 [7A080000] dd exc27 2284 000059EC [7E080000] dd exc28 2285 000059F0 [82080000] dd exc29 2286 000059F4 [86080000] dd exc30 2287 000059F8 [8A080000] dd exc31 2288 ; Interrupt list 2289 000059FC [40060000] dd timer_int ; INT 20h 2290 ;dd irq0 2291 00005A00 [440B0000] dd keyb_int ; 27/08/2014 2292 ;dd irq1 2293 00005A04 [5F070000] dd irq2 2294 ; COM2 int 2295 00005A08 [63070000] dd irq3 2296 ; COM1 int 2297 00005A0C [6E070000] dd irq4 2298 00005A10 [79070000] dd irq5 2299 ;DISKETTE_INT: ;06/02/2015 2300 00005A14 [B01E0000] dd fdc_int ; 16/02/2015, IRQ 6 handler 2301 ;dd irq6 2302 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 2303 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 2304 00005A18 [F50A0000] dd default_irq7 ; 25/02/2015 2305 ;dd irq7 2306 ; Real Time Clock Interrupt 2307 00005A1C [93090000] dd rtc_int ; 23/02/2015, IRQ 8 handler 2308 ;dd irq8 ; INT 28h 2309 00005A20 [89070000] dd irq9 2310 00005A24 [8D070000] dd irq10 2311 00005A28 [91070000] dd irq11 2312 00005A2C [95070000] dd irq12 2313 00005A30 [99070000] dd irq13 2314 ;HDISK_INT1: ;06/02/2015 2315 00005A34 [7A230000] dd hdc1_int ; 21/02/2015, IRQ 14 handler 2316 ;dd irq14 2317 ;HDISK_INT2: ;06/02/2015 2318 00005A38 [9D230000] dd hdc2_int ; 21/02/2015, IRQ 15 handler 2319 ;dd irq15 ; INT 2Fh 2320 ; 14/08/2015 2321 00005A3C [D32F0000] dd sysent ; INT 30h (system calls) 2322 2323 ;dd ignore_int 2324 00005A40 00000000 dd 0 2325 2326 ;;; 2327 ;;; 11/03/2015 2328 %include 'kybdata.inc' ; KEYBOARD (BIOS) DATA 2329 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.4) - KYBDATA.INC 2330 <1> ; Last Modification: 13/06/2022 2331 <1> ; (Data Section for 'KEYBOARD.INC') 2332 <1> ; 2333 <1> ; ///////// KEYBOARD DATA /////////////// 2334 <1> 2335 <1> ; 11/03/2015 2336 <1> ; 05/12/2014 2337 <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 2338 <1> ; 03/06/86 KEYBOARD BIOS 2339 <1> 2340 <1> ;--------------------------------------------------------------------------------- 2341 <1> ; KEY IDENTIFICATION SCAN TABLES 2342 <1> ;--------------------------------------------------------------------------------- 2343 <1> 2344 <1> ;----- TABLES FOR ALT CASE ------------ 2345 <1> ;----- ALT-INPUT-TABLE 2346 00005A44 524F50514B <1> K30: db 82,79,80,81,75 2347 00005A49 4C4D474849 <1> db 76,77,71,72,73 ; 10 NUMBER ON KEYPAD 2348 <1> ;----- SUPER-SHIFT-TABLE 2349 00005A4E 101112131415 <1> db 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS 2350 00005A54 161718191E1F <1> db 22,23,24,25,30,31 2351 00005A5A 202122232425 <1> db 32,33,34,35,36,37 2352 00005A60 262C2D2E2F30 <1> db 38,44,45,46,47,48 2353 00005A66 3132 <1> db 49,50 2354 <1> 2355 <1> ;----- TABLE OF SHIFT KEYS AND MASK VALUES 2356 <1> ;----- KEY_TABLE 2357 00005A68 52 <1> _K6: db INS_KEY ; INSERT KEY 2358 00005A69 3A4546381D <1> db CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY 2359 00005A6E 2A36 <1> db LEFT_KEY,RIGHT_KEY 2360 <1> _K6L equ $-_K6 2361 <1> 2362 <1> ;----- MASK_TABLE 2363 00005A70 80 <1> _K7: db INS_SHIFT ; INSERT MODE SHIFT 2364 00005A71 4020100804 <1> db CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT 2365 00005A76 0201 <1> db LEFT_SHIFT,RIGHT_SHIFT 2366 <1> 2367 <1> ;----- TABLES FOR CTRL CASE ;---- CHARACTERS ------ 2368 00005A78 1BFF00FFFFFF <1> _K8: db 27,-1,0,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5 2369 00005A7E 1EFFFFFFFF1F <1> db 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, - 2370 <1> ;db -1,127,-1,17,23,5 ; =, Bksp, Tab, Q, W, E 2371 00005A84 FF7F94111705 <1> db -1,127,148,17,23,5 ; 13/06/2022 2372 00005A8A 12141915090F <1> db 18,20,25,21,9,15 ; R, T, Y, U, I, O 2373 00005A90 101B1D0AFF01 <1> db 16,27,29,10,-1,1 ; P, [, ], Enter, Ctrl, A 2374 00005A96 13040607080A <1> db 19,4,6,7,8,10 ; S, D, F, G, H, J 2375 00005A9C 0B0CFFFFFFFF <1> db 11,12,-1,-1,-1,-1 ; K, L, :, ', `, LShift 2376 00005AA2 1C1A18031602 <1> db 28,26,24,3,22,2 ; Bkslash, Z, X, C, V, B 2377 00005AA8 0E0DFFFFFFFF <1> db 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift 2378 00005AAE 96FF20FF <1> db 150,-1,' ',-1 ; *, ALT, Spc, CL 2379 <1> ; ;----- FUNCTIONS ------ 2380 00005AB2 5E5F60616263 <1> db 94,95,96,97,98,99 ; F1 - F6 2381 00005AB8 64656667FFFF <1> db 100,101,102,103,-1,-1 ; F7 - F10, NL, SL 2382 00005ABE 778D848E738F <1> db 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5 2383 00005AC4 749075917692 <1> db 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins 2384 00005ACA 93FFFFFF898A <1> db 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12 2385 <1> 2386 <1> ;----- TABLES FOR LOWER CASE ---------- 2387 00005AD0 1B3132333435363738- <1> K10: db 27,'1234567890-=',8,9 2387 00005AD9 39302D3D0809 <1> 2388 00005ADF 71776572747975696F- <1> db 'qwertyuiop[]',13,-1,'asdfghjkl;',39 2388 00005AE8 705B5D0DFF61736466- <1> 2388 00005AF1 67686A6B6C3B27 <1> 2389 00005AF8 60FF5C7A786376626E- <1> db 96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1 2389 00005B01 6D2C2E2FFF2AFF20FF <1> 2390 <1> ;----- LC TABLE SCAN 2391 00005B0A 3B3C3D3E3F <1> db 59,60,61,62,63 ; BASE STATE OF F1 - F10 2392 00005B0F 4041424344 <1> db 64,65,66,67,68 2393 00005B14 FFFF <1> db -1,-1 ; NL, SL 2394 <1> 2395 <1> ;----- KEYPAD TABLE 2396 00005B16 474849FF4BFF <1> K15: db 71,72,73,-1,75,-1 ; BASE STATE OF KEYPAD KEYS 2397 00005B1C 4DFF4F50515253 <1> db 77,-1,79,80,81,82,83 2398 00005B23 FFFF5C8586 <1> db -1,-1,92,133,134 ; SysRq, Undef, WT, F11, F12 2399 <1> 2400 <1> ;----- TABLES FOR UPPER CASE ---------- 2401 00005B28 1B21402324255E262A- <1> K11: db 27,'!@#$%',94,'&*()_+',8,0 2401 00005B31 28295F2B0800 <1> 2402 00005B37 51574552545955494F- <1> db 'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"' 2402 00005B40 507B7D0DFF41534446- <1> 2402 00005B49 47484A4B4C3A22 <1> 2403 00005B50 7EFF7C5A584356424E- <1> db 126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1 2403 00005B59 4D3C3E3FFF2AFF20FF <1> 2404 <1> ;----- UC TABLE SCAN 2405 00005B62 5455565758 <1> K12: db 84,85,86,87,88 ; SHIFTED STATE OF F1 - F10 2406 00005B67 595A5B5C5D <1> db 89,90,91,92,93 2407 00005B6C FFFF <1> db -1,-1 ; NL, SL 2408 <1> 2409 <1> ;----- NUM STATE TABLE 2410 00005B6E 3738392D3435362B31- <1> K14: db '789-456+1230.' ; NUMLOCK STATE OF KEYPAD KEYS 2410 00005B77 3233302E <1> 2411 <1> ; 2412 00005B7B FFFF7C8788 <1> db -1,-1,124,135,136 ; SysRq, Undef, WT, F11, F12 2413 <1> 2414 <1> Align 4 2415 <1> ;---------------------------------------- 2416 <1> ; VIDEO DISPLAY DATA AREA ; 2417 <1> ;---------------------------------------- 2418 00005B80 03 <1> CRT_MODE db 3 ; CURRENT DISPLAY MODE (TYPE) 2419 00005B81 29 <1> CRT_MODE_SET db 29h ; CURRENT SETTING OF THE 3X8 REGISTER 2420 <1> ; (29h default setting for video mode 3) 2421 <1> ; Mode Select register Bits 2422 <1> ; BIT 0 - 80x25 (1), 40x25 (0) 2423 <1> ; BIT 1 - ALPHA (0), 320x200 GRAPHICS (1) 2424 <1> ; BIT 2 - COLOR (0), BW (1) 2425 <1> ; BIT 3 - Video Sig. ENABLE (1), DISABLE (0) 2426 <1> ; BIT 4 - 640x200 B&W Graphics Mode (1) 2427 <1> ; BIT 5 - ALPHA mode BLINKING (1) 2428 <1> ; BIT 6, 7 - Not Used 2429 <1> 2430 <1> ; Mode 0 - 2Ch = 101100b ; 40x25 text, 16 gray colors 2431 <1> ; Mode 1 - 28h = 101000b ; 40x25 text, 16 fore colors, 8 back colors 2432 <1> ; Mode 2 - 2Dh = 101101b ; 80x25 text, 16 gray colors 2433 <1> ; MODE 3 - 29h = 101001b ; 80x25 text, 16 fore color, 8 back color 2434 <1> ; Mode 4 - 2Ah = 101010b ; 320x200 graphics, 4 colors 2435 <1> ; Mode 5 - 2Eh = 101110b ; 320x200 graphics, 4 gray colors 2436 <1> ; Mode 6 - 1Eh = 011110b ; 640x200 graphics, 2 colors 2437 <1> ; Mode 7 - 29h = 101001b ; 80x25 text, black & white colors 2438 <1> ; Mode & 37h = Video signal OFF 2439 <1> 2440 <1> 2441 <1> ; 26/08/2014 2442 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014) 2443 <1> ; Derived from IBM "pc-at" 2444 <1> ; rombios source code (06/10/1985) 2445 <1> ; 'dseg.inc' 2446 <1> 2447 <1> ;---------------------------------------; 2448 <1> ; SYSTEM DATA AREA ; 2449 <1> ;---------------------------------------- 2450 00005B82 00 <1> BIOS_BREAK db 0 ; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED 2451 <1> 2452 <1> ;---------------------------------------- 2453 <1> ; KEYBOARD DATA AREAS ; 2454 <1> ;---------------------------------------- 2455 <1> 2456 00005B83 00 <1> KB_FLAG db 0 ; KEYBOARD SHIFT STATE AND STATUS FLAGS 2457 00005B84 00 <1> KB_FLAG_1 db 0 ; SECOND BYTE OF KEYBOARD STATUS 2458 00005B85 00 <1> KB_FLAG_2 db 0 ; KEYBOARD LED FLAGS 2459 00005B86 00 <1> KB_FLAG_3 db 0 ; KEYBOARD MODE STATE AND TYPE FLAGS 2460 00005B87 00 <1> ALT_INPUT db 0 ; STORAGE FOR ALTERNATE KEY PAD ENTRY 2461 00005B88 [985B0000] <1> BUFFER_START dd KB_BUFFER ; OFFSET OF KEYBOARD BUFFER START 2462 00005B8C [B85B0000] <1> BUFFER_END dd KB_BUFFER + 32 ; OFFSET OF END OF BUFFER 2463 00005B90 [985B0000] <1> BUFFER_HEAD dd KB_BUFFER ; POINTER TO HEAD OF KEYBOARD BUFFER 2464 00005B94 [985B0000] <1> BUFFER_TAIL dd KB_BUFFER ; POINTER TO TAIL OF KEYBOARD BUFFER 2465 <1> ; ------ HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY 2466 00005B98 0000 <1> KB_BUFFER times 16 dw 0 ; ROOM FOR 16 SCAN CODE ENTRIES 2467 <1> 2468 <1> ; /// End Of KEYBOARD DATA /// 2329 %include 'vidata.inc' ; VIDEO (BIOS) DATA 2330 <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC 2331 <1> ; Last Modification: 11/03/2015 2332 <1> ; (Data section for 'VIDEO.INC') 2333 <1> ; 2334 <1> ; ///////// VIDEO DATA /////////////// 2335 <1> 2336 <1> video_params: 2337 <1> ; 02/09/2014 (Retro UNIX 386 v1) 2338 <1> ;ORGS.ASM ----- 06/10/85 COMPATIBILITY MODULE 2339 <1> ; VIDEO MODE 3 2340 00005BB8 71505A0A1F0619 <1> db 71h,50h,5Ah,0Ah,1Fh,6,19h ; SET UP FOR 80X25 2341 00005BBF 1C02070607 <1> db 1Ch,2,7,6,7 ; cursor start = 6, cursor stop = 7 2342 00005BC4 00000000 <1> db 0,0,0,0 2343 <1> 2344 <1> ; /// End Of VIDEO DATA /// 2330 %include 'diskdata.inc' ; DISK (BIOS) DATA (initialized) 2331 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKDATA.INC 2332 <1> ; Last Modification: 11/07/2022 2333 <1> ; (Initialized Disk Parameters Data section for 'DISKIO.INC') 2334 <1> ; 2335 <1> ; ***************************************************************************** 2336 <1> 2337 <1> ;---------------------------------------- 2338 <1> ; 80286 INTERRUPT LOCATIONS : 2339 <1> ; REFERENCED BY POST & BIOS : 2340 <1> ;---------------------------------------- 2341 <1> 2342 00005BC8 [2B5C0000] <1> DISK_POINTER: dd MD_TBL6 ; Pointer to Diskette Parameter Table 2343 <1> 2344 <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014 2345 <1> ;---------------------------------------------------------------- 2346 <1> ; DISK_BASE : 2347 <1> ; THIS IS THE SET OF PARAMETERS REQUIRED FOR : 2348 <1> ; DISKETTE OPERATION. THEY ARE POINTED AT BY THE : 2349 <1> ; DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS, : 2350 <1> ; BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT : 2351 <1> ;---------------------------------------------------------------- 2352 <1> 2353 <1> ;DISK_BASE: 2354 <1> ; DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2355 <1> ; DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2356 <1> ; DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2357 <1> ; DB 2 ; 512 BYTES/SECTOR 2358 <1> ; ;DB 15 ; EOT (LAST SECTOR ON TRACK) 2359 <1> ; db 18 ; (EOT for 1.44MB diskette) 2360 <1> ; DB 01BH ; GAP LENGTH 2361 <1> ; DB 0FFH ; DTL 2362 <1> ; ;DB 054H ; GAP LENGTH FOR FORMAT 2363 <1> ; db 06ch ; (for 1.44MB dsikette) 2364 <1> ; DB 0F6H ; FILL BYTE FOR FORMAT 2365 <1> ; DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2366 <1> ; DB 8 ; MOTOR START TIME (1/8 SECONDS) 2367 <1> 2368 <1> ;---------------------------------------- 2369 <1> ; ROM BIOS DATA AREAS : 2370 <1> ;---------------------------------------- 2371 <1> 2372 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 2373 <1> 2374 <1> ;@EQUIP_FLAG DW ? ; INSTALLED HARDWARE FLAGS 2375 <1> 2376 <1> ;---------------------------------------- 2377 <1> ; DISKETTE DATA AREAS : 2378 <1> ;---------------------------------------- 2379 <1> 2380 <1> ;@SEEK_STATUS DB ? ; DRIVE RECALIBRATION STATUS 2381 <1> ; ; BIT 3-0 = DRIVE 3-0 RECALIBRATION 2382 <1> ; ; BEFORE NEXT SEEK IF BIT IS = 0 2383 <1> ;@MOTOR_STATUS DB ? ; MOTOR STATUS 2384 <1> ; ; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING 2385 <1> ; ; BIT 7 = CURRENT OPERATION IS A WRITE 2386 <1> ;@MOTOR_COUNT DB ? ; TIME OUT COUNTER FOR MOTOR(S) TURN OFF 2387 <1> ;@DSKETTE_STATUS DB ? ; RETURN CODE STATUS BYTE 2388 <1> ; ; CMD_BLOCK IN STACK FOR DISK OPERATION 2389 <1> ;@NEC_STATUS DB 7 DUP(?) ; STATUS BYTES FROM DISKETTE OPERATION 2390 <1> 2391 <1> ;---------------------------------------- 2392 <1> ; POST AND BIOS WORK DATA AREA : 2393 <1> ;---------------------------------------- 2394 <1> 2395 <1> ;@INTR_FLAG DB ? ; FLAG INDICATING AN INTERRUPT HAPPENED 2396 <1> 2397 <1> ;---------------------------------------- 2398 <1> ; TIMER DATA AREA : 2399 <1> ;---------------------------------------- 2400 <1> 2401 <1> ; 17/12/2014 (IRQ 0 - INT 08H) 2402 <1> ;TIMER_LOW equ 46Ch ; Timer ticks (counter) @ 40h:006Ch 2403 <1> ;TIMER_HIGH equ 46Eh ; (18.2 timer ticks per second) 2404 <1> ;TIMER_OFL equ 470h ; Timer - 24 hours flag @ 40h:0070h 2405 <1> 2406 <1> ;---------------------------------------- 2407 <1> ; ADDITIONAL MEDIA DATA : 2408 <1> ;---------------------------------------- 2409 <1> 2410 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 2411 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 2412 <1> ; DB ? ; DRIVE 1 MEDIA STATE 2413 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 2414 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 2415 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 2416 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 2417 <1> 2418 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 2419 <1> 2420 <1> ;-------------------------------------------------------- 2421 <1> ; DRIVE TYPE TABLE : 2422 <1> ;-------------------------------------------------------- 2423 <1> ; 16/02/2015 (unix386.s, 32 bit modifications) 2424 <1> DR_TYPE: 2425 00005BCC 01 <1> DB 01 ;DRIVE TYPE, MEDIA TABLE 2426 <1> ;DW MD_TBL1 2427 00005BCD [EA5B0000] <1> dd MD_TBL1 2428 00005BD1 82 <1> DB 02+BIT7ON 2429 <1> ;DW MD_TBL2 2430 00005BD2 [F75B0000] <1> dd MD_TBL2 2431 00005BD6 02 <1> DR_DEFAULT: DB 02 2432 <1> ;DW MD_TBL3 2433 00005BD7 [045C0000] <1> dd MD_TBL3 2434 00005BDB 03 <1> DB 03 2435 <1> ;DW MD_TBL4 2436 00005BDC [115C0000] <1> dd MD_TBL4 2437 00005BE0 84 <1> DB 04+BIT7ON 2438 <1> ;DW MD_TBL5 2439 00005BE1 [1E5C0000] <1> dd MD_TBL5 2440 00005BE5 04 <1> DB 04 2441 <1> ;DW MD_TBL6 2442 00005BE6 [2B5C0000] <1> dd MD_TBL6 2443 <1> DR_TYPE_E equ $ ; END OF TABLE 2444 <1> ;DR_CNT EQU (DR_TYPE_E-DR_TYPE)/3 2445 <1> DR_CNT equ (DR_TYPE_E-DR_TYPE)/5 2446 <1> ;-------------------------------------------------------- 2447 <1> ; MEDIA/DRIVE PARAMETER TABLES : 2448 <1> ;-------------------------------------------------------- 2449 <1> ;-------------------------------------------------------- 2450 <1> ; 360 KB MEDIA IN 360 KB DRIVE : 2451 <1> ;-------------------------------------------------------- 2452 <1> MD_TBL1: 2453 00005BEA DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2454 00005BEB 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2455 00005BEC 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2456 00005BED 02 <1> DB 2 ; 512 BYTES/SECTOR 2457 00005BEE 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2458 00005BEF 2A <1> DB 02AH ; GAP LENGTH 2459 00005BF0 FF <1> DB 0FFH ; DTL 2460 00005BF1 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2461 00005BF2 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2462 00005BF3 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2463 00005BF4 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2464 00005BF5 27 <1> DB 39 ; MAX. TRACK NUMBER 2465 00005BF6 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2466 <1> ;-------------------------------------------------------- 2467 <1> ; 360 KB MEDIA IN 1.2 MB DRIVE : 2468 <1> ;-------------------------------------------------------- 2469 <1> MD_TBL2: 2470 00005BF7 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2471 00005BF8 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2472 00005BF9 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2473 00005BFA 02 <1> DB 2 ; 512 BYTES/SECTOR 2474 00005BFB 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2475 00005BFC 2A <1> DB 02AH ; GAP LENGTH 2476 00005BFD FF <1> DB 0FFH ; DTL 2477 00005BFE 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2478 00005BFF F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2479 00005C00 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2480 00005C01 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2481 00005C02 27 <1> DB 39 ; MAX. TRACK NUMBER 2482 00005C03 40 <1> DB RATE_300 ; DATA TRANSFER RATE 2483 <1> ;-------------------------------------------------------- 2484 <1> ; 1.2 MB MEDIA IN 1.2 MB DRIVE : 2485 <1> ;-------------------------------------------------------- 2486 <1> MD_TBL3: 2487 00005C04 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2488 00005C05 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2489 00005C06 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2490 00005C07 02 <1> DB 2 ; 512 BYTES/SECTOR 2491 00005C08 0F <1> DB 15 ; EOT (LAST SECTOR ON TRACK) 2492 00005C09 1B <1> DB 01BH ; GAP LENGTH 2493 00005C0A FF <1> DB 0FFH ; DTL 2494 00005C0B 54 <1> DB 054H ; GAP LENGTH FOR FORMAT 2495 00005C0C F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2496 00005C0D 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2497 00005C0E 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2498 00005C0F 4F <1> DB 79 ; MAX. TRACK NUMBER 2499 00005C10 00 <1> DB RATE_500 ; DATA TRANSFER RATE 2500 <1> ;-------------------------------------------------------- 2501 <1> ; 720 KB MEDIA IN 720 KB DRIVE : 2502 <1> ;-------------------------------------------------------- 2503 <1> MD_TBL4: 2504 00005C11 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2505 00005C12 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2506 00005C13 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2507 00005C14 02 <1> DB 2 ; 512 BYTES/SECTOR 2508 00005C15 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2509 00005C16 2A <1> DB 02AH ; GAP LENGTH 2510 00005C17 FF <1> DB 0FFH ; DTL 2511 00005C18 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2512 00005C19 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2513 00005C1A 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2514 00005C1B 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2515 00005C1C 4F <1> DB 79 ; MAX. TRACK NUMBER 2516 00005C1D 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2517 <1> ;-------------------------------------------------------- 2518 <1> ; 720 KB MEDIA IN 1.44 MB DRIVE : 2519 <1> ;-------------------------------------------------------- 2520 <1> MD_TBL5: 2521 00005C1E DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 2522 00005C1F 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2523 00005C20 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2524 00005C21 02 <1> DB 2 ; 512 BYTES/SECTOR 2525 00005C22 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 2526 00005C23 2A <1> DB 02AH ; GAP LENGTH 2527 00005C24 FF <1> DB 0FFH ; DTL 2528 00005C25 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 2529 00005C26 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2530 00005C27 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2531 00005C28 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2532 00005C29 4F <1> DB 79 ; MAX. TRACK NUMBER 2533 00005C2A 80 <1> DB RATE_250 ; DATA TRANSFER RATE 2534 <1> ;-------------------------------------------------------- 2535 <1> ; 1.44 MB MEDIA IN 1.44 MB DRIVE : 2536 <1> ;-------------------------------------------------------- 2537 <1> MD_TBL6: 2538 00005C2B AF <1> DB 10101111B ; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE 2539 00005C2C 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 2540 00005C2D 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 2541 00005C2E 02 <1> DB 2 ; 512 BYTES/SECTOR 2542 00005C2F 12 <1> DB 18 ; EOT (LAST SECTOR ON TRACK) 2543 00005C30 1B <1> DB 01BH ; GAP LENGTH 2544 00005C31 FF <1> DB 0FFH ; DTL 2545 00005C32 6C <1> DB 06CH ; GAP LENGTH FOR FORMAT 2546 00005C33 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 2547 00005C34 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 2548 00005C35 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 2549 00005C36 4F <1> DB 79 ; MAX. TRACK NUMBER 2550 00005C37 00 <1> DB RATE_500 ; DATA TRANSFER RATE 2551 <1> 2552 <1> 2553 <1> ; << diskette.inc >> 2554 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2555 <1> ; 2556 <1> ;---------------------------------------- 2557 <1> ; ROM BIOS DATA AREAS : 2558 <1> ;---------------------------------------- 2559 <1> 2560 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 2561 <1> 2562 <1> ;---------------------------------------- 2563 <1> ; FIXED DISK DATA AREAS : 2564 <1> ;---------------------------------------- 2565 <1> 2566 <1> ;DISK_STATUS1: DB 0 ; FIXED DISK STATUS 2567 <1> ;HF_NUM: DB 0 ; COUNT OF FIXED DISK DRIVES 2568 <1> ;CONTROL_BYTE: DB 0 ; HEAD CONTROL BYTE 2569 <1> ;@PORT_OFF DB ? ; RESERVED (PORT OFFSET) 2570 <1> 2571 <1> ;---------------------------------------- 2572 <1> ; ADDITIONAL MEDIA DATA : 2573 <1> ;---------------------------------------- 2574 <1> 2575 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 2576 <1> ;HF_STATUS DB 0 ; STATUS REGISTER 2577 <1> ;HF_ERROR DB 0 ; ERROR REGISTER 2578 <1> ;HF_INT_FLAG DB 0 ; FIXED DISK INTERRUPT FLAG 2579 <1> ;HF_CNTRL DB 0 ; COMBO FIXED DISK/DISKETTE CARD BIT 0=1 2580 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 2581 <1> ; DB ? ; DRIVE 1 MEDIA STATE 2582 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 2583 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 2584 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 2585 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 2586 <1> 2587 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 2588 <1> ; 2589 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2590 <1> 2591 <1> ERR_TBL: 2592 00005C38 E0 <1> db NO_ERR 2593 00005C39 024001BB <1> db BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR 2594 00005C3D 04BB100A <1> db RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR 2595 <1> 2596 <1> ; 11/07/2022 2597 <1> ; 17/12/2014 (mov ax, [cfd]) 2598 <1> ; 11/12/2014 2599 <1> ;cfd: db 0 ; current floppy drive (for GET_PARM) 2600 <1> ; 17/12/2014 ; instead of 'DISK_POINTER' 2601 <1> ;pfd: db 1 ; previous floppy drive (for GET_PARM) 2602 <1> ; (initial value of 'pfd 2603 <1> ; must be different then 'cfd' value 2604 <1> ; to force updating/initializing 2605 <1> ; current drive parameters) 2606 <1> 2607 <1> ;; 11/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2608 00005C41 FF <1> pfd: db 0FFh 2609 <1> 2610 <1> align 2 2611 <1> 2612 00005C42 F001 <1> HF_PORT: dw 1F0h ; Default = 1F0h 2613 <1> ; (170h) 2614 00005C44 F603 <1> HF_REG_PORT: dw 3F6h ; HF_PORT + 206h 2615 <1> 2616 <1> ; 05/01/2015 2617 00005C46 00 <1> hf_m_s: db 0 ; (0 = Master, 1 = Slave) 2618 <1> 2619 <1> ; ***************************************************************************** 2331 ;;; 2332 2333 00005C47 90 Align 2 2334 2335 ; 12/11/2014 (Retro UNIX 386 v1) 2336 00005C48 00 boot_drv: db 0 ; boot drive number (physical) 2337 ; 24/11/2014 2338 00005C49 00 drv: db 0 2339 00005C4A 00 last_drv: db 0 ; last hdd 2340 00005C4B 00 hdc: db 0 ; number of hard disk drives 2341 ; (present/detected) 2342 ; 2343 ; 24/11/2014 (Retro UNIX 386 v1) 2344 ; Physical drive type & flags 2345 00005C4C 00 fd0_type: db 0 ; floppy drive type 2346 00005C4D 00 fd1_type: db 0 ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt) 2347 ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt) 2348 ; 3 = 720 Kb, 80 track, 3.5" (9 spt) 2349 ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt) 2350 ; 1 = 360 Kb, 40 track, 5.25" (9 spt) 2351 00005C4E 00 hd0_type: db 0 ; EDD status for hd0 (bit 7 = present flag) 2352 00005C4F 00 hd1_type: db 0 ; EDD status for hd1 (bit 7 = present flag) 2353 00005C50 00 hd2_type: db 0 ; EDD status for hd2 (bit 7 = present flag) 2354 00005C51 00 hd3_type: db 0 ; EDD status for hd3 (bit 7 = present flag) 2355 ; bit 0 - Fixed disk access subset supported 2356 ; bit 1 - Drive locking and ejecting 2357 ; bit 2 - Enhanced disk drive support 2358 ; bit 3 = Reserved (64 bit EDD support) 2359 ; (If bit 0 is '1' Retro UNIX 386 v1 2360 ; will interpret it as 'LBA ready'!) 2361 2362 ; 12/07/2022 2363 ; (drv.cylinders, drv.spt, drv.spt will not be used now on) 2364 ; ('diskio.inc') 2365 ; ((spt and heads and cylinder counts will be taken from DPT)) 2366 2367 ; 11/03/2015 - 10/07/2015 2368 ;drv.cylinders: dw 0,0,0,0,0,0,0 2369 ;drv.heads: dw 0,0,0,0,0,0,0 2370 ;drv.spt: dw 0,0,0,0,0,0,0 2371 ; 12/07/2022 - 11/03/2015 2372 00005C52 000000000000000000- drv.size: dd 0,0,0,0,0,0,0 2372 00005C5B 000000000000000000- 2372 00005C64 000000000000000000- 2372 00005C6D 00 2373 00005C6E 00000000000000 drv.status: db 0,0,0,0,0,0,0 2374 00005C75 00000000000000 drv.error: db 0,0,0,0,0,0,0 2375 ; 2376 2377 ; 27/08/2014 2378 scr_row: 2379 00005C7C E0810B00 dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3 2380 scr_col: 2381 00005C80 00000000 dd 0 2382 2383 ;; 14/08/2015 2384 ;;msgPM: 2385 ;; db "Protected mode and paging are ENABLED ... ", 0 2386 msgKVER: 2387 ;;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0 2388 ;;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.3 [02/06/2022]", 0 2389 ;;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.4 [14/06/2022]", 0 2390 ;db "Retro UNIX 386 v1.1 - Kernel v0.2.1.5 [12/07/2022]", 0 2391 00005C84 526574726F20554E49- db "Retro UNIX 386 v1.1 - Kernel v0.2.1.6 [24/07/2022]", 0 2391 00005C8D 58203338362076312E- 2391 00005C96 31202D204B65726E65- 2391 00005C9F 6C2076302E322E312E- 2391 00005CA8 36205B32342F30372F- 2391 00005CB1 323032325D00 2392 2393 00005CB7 90 Align 2 2394 2395 ; 20/08/2014 2396 ; /* This is the default interrupt "handler" :-) */ 2397 ; Linux v0.12 (head.s) 2398 int_msg: 2399 00005CB8 556E6B6E6F776E2069- db "Unknown interrupt ! ", 0 2399 00005CC1 6E7465727275707420- 2399 00005CCA 212000 2400 2401 00005CCD 90 Align 2 2402 2403 ; 21/08/2014 2404 timer_msg: 2405 00005CCE 49525120302028494E- db "IRQ 0 (INT 20h) ! Timer Interrupt : " 2405 00005CD7 542032306829202120- 2405 00005CE0 54696D657220496E74- 2405 00005CE9 657272757074203A20 2406 tcountstr: 2407 00005CF2 303030303020 db "00000 " 2408 00005CF8 00 db 0 2409 2410 00005CF9 90 Align 2 2411 ; 21/08/2014 2412 exc_msg: 2413 00005CFA 435055206578636570- db "CPU exception ! " 2413 00005D03 74696F6E202120 2414 excnstr: ; 25/08/2014 2415 00005D0A 3F3F68202045495020- db "??h", " EIP : " 2415 00005D13 3A20 2416 EIPstr: ; 29/08/2014 2417 00005D15 00 times 12 db 0 2418 rtc_msg: 2419 00005D21 5265616C2054696D65- db "Real Time Clock - " 2419 00005D2A 20436C6F636B202D20 2420 datestr: 2421 00005D33 30302F30302F303030- db "00/00/0000" 2421 00005D3C 30 2422 00005D3D 20 db " " 2423 daystr: 2424 00005D3E 44415920 db "DAY " 2425 timestr: 2426 00005D42 30303A30303A3030 db "00:00:00" 2427 00005D4A 20 db " " 2428 00005D4B 00 db 0 2429 2430 daytmp: 2431 ; 28/02/2015 2432 00005D4C 3F3F3F2053554E204D- db "??? SUN MON TUE WED THU FRI SAT " 2432 00005D55 4F4E20545545205745- 2432 00005D5E 442054485520465249- 2432 00005D67 2053415420 2433 2434 00005D6C FF ptime_seconds: db 0FFh 2435 2436 ; 23/02/2015 2437 ; 25/08/2014 2438 ;scounter: 2439 ; db 5 2440 ; db 19 2441 2442 ; 02/01/2022 2443 ; 05/11/2014 2444 ;msg_out_of_memory: 2445 ; db 07h, 0Dh, 0Ah 2446 ; db 'Insufficient memory ! (Minimum 2 MB memory is needed.)' 2447 ; db 0Dh, 0Ah, 0 2448 ; 2449 setup_error_msg: 2450 00005D6D 0D0A db 0Dh, 0Ah 2451 00005D6F 4469736B2053657475- db 'Disk Setup Error!' 2451 00005D78 70204572726F7221 2452 00005D80 0D0A00 db 0Dh, 0Ah,0 2453 2454 ; 02/09/2014 (Retro UNIX 386 v1) 2455 ;crt_ulc : db 0 ; upper left column (for scroll) 2456 ; db 0 ; upper left row (for scroll) 2457 2458 ;crt_lrc : db 79 ; lower right column (for scroll) 2459 ; db 24 ; lower right row (for scroll) 2460 2461 2462 ; 06/11/2014 (Temporary Data) 2463 ; Memory Information message 2464 ; 14/08/2015 2465 msg_memory_info: 2466 00005D83 07 db 07h 2467 00005D84 0D0A db 0Dh, 0Ah 2468 ;db "MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah 2469 00005D86 546F74616C206D656D- db "Total memory : " 2469 00005D8F 6F7279203A20 2470 mem_total_b_str: ; 10 digits 2471 00005D95 303030303030303030- db "0000000000 bytes", 0Dh, 0Ah 2471 00005D9E 302062797465730D0A 2472 00005DA7 202020202020202020- db " ", 20h, 20h, 20h 2472 00005DB0 202020202020202020 2473 mem_total_p_str: ; 7 digits 2474 00005DB9 303030303030302070- db "0000000 pages", 0Dh, 0Ah 2474 00005DC2 616765730D0A 2475 00005DC8 0D0A db 0Dh, 0Ah 2476 00005DCA 46726565206D656D6F- db "Free memory : " 2476 00005DD3 727920203A20 2477 free_mem_b_str: ; 10 digits 2478 00005DD9 3F3F3F3F3F3F3F3F3F- db "?????????? bytes", 0Dh, 0Ah 2478 00005DE2 3F2062797465730D0A 2479 00005DEB 202020202020202020- db " ", 20h, 20h, 20h 2479 00005DF4 202020202020202020 2480 free_mem_p_str: ; 7 digits 2481 00005DFD 3F3F3F3F3F3F3F2070- db "??????? pages", 0Dh, 0Ah 2481 00005E06 616765730D0A 2482 00005E0C 0D0A00 db 0Dh, 0Ah, 0 2483 2484 dsk_ready_msg: 2485 00005E0F 0D0A db 0Dh, 0Ah 2486 dsktype: 2487 00005E11 6664 db 'fd' 2488 dskx: 2489 00005E13 30 db '0' 2490 00005E14 20 db 20h 2491 00005E15 697320524541445920- db 'is READY ...' 2491 00005E1E 2E2E2E 2492 00005E21 00 db 0 2493 nextline: 2494 00005E22 0D0A00 db 0Dh, 0Ah, 0 2495 2496 ; KERNEL - SYSINIT Messages 2497 ; 24/08/2015 2498 ; 13/04/2015 - (Retro UNIX 386 v1 Beginning) 2499 ; 14/07/2013 2500 ;kernel_init_err_msg: 2501 ; db 0Dh, 0Ah 2502 ; db 07h 2503 ; db 'Kernel initialization ERROR !' 2504 ; db 0Dh, 0Ah, 0 2505 ; 24/08/2015 2506 ;;; (temporary kernel init message has been removed 2507 ;;; from 'sys_init' code) 2508 ;kernel_init_ok_msg: 2509 ; db 0Dh, 0Ah 2510 ; db 07h 2511 ; db 'Welcome to Retro UNIX 386 v1.1 Operating System !' 2512 ; db 0Dh, 0Ah 2513 ; db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)' 2514 ; db 0Dh, 0Ah, 0 2515 panic_msg: 2516 00005E25 0D0A07 db 0Dh, 0Ah, 07h 2517 00005E28 4552524F523A204B65- db 'ERROR: Kernel Panic !' 2517 00005E31 726E656C2050616E69- 2517 00005E3A 632021 2518 00005E3D 0D0A00 db 0Dh, 0Ah, 0 2519 etc_init_err_msg: 2520 00005E40 0D0A db 0Dh, 0Ah 2521 00005E42 07 db 07h 2522 00005E43 4552524F523A202F65- db 'ERROR: /etc/init !?' 2522 00005E4C 74632F696E69742021- 2522 00005E55 3F 2523 00005E56 0D0A00 db 0Dh, 0Ah, 0 2524 2525 ; 10/05/2015 2526 badsys_msg: 2527 00005E59 0D0A db 0Dh, 0Ah 2528 00005E5B 07 db 07h 2529 00005E5C 496E76616C69642053- db 'Invalid System Call !' 2529 00005E65 797374656D2043616C- 2529 00005E6E 6C2021 2530 00005E71 0D0A db 0Dh, 0Ah 2531 00005E73 4541583A20 db 'EAX: ' 2532 bsys_msg_eax: 2533 00005E78 303030303030303068 db '00000000h' 2534 00005E81 0D0A db 0Dh, 0Ah 2535 00005E83 4549503A20 db 'EIP: ' 2536 bsys_msg_eip: 2537 00005E88 303030303030303068 db '00000000h' 2538 00005E91 0D0A00 db 0Dh, 0Ah, 0 2539 2540 BSYS_M_SIZE equ $ - badsys_msg 2541 2542 2543 align 2 2544 2545 ; EPOCH Variables 2546 ; 13/04/2015 - Retro UNIX 386 v1 Beginning 2547 ; 09/04/2013 epoch variables 2548 ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013 2549 ; 2550 00005E94 B207 year: dw 1970 2551 ;month: dw 1 2552 ;day: dw 1 2553 ;hour: dw 0 2554 ;minute: dw 0 2555 ;second: dw 0 2556 ; 02/06/2022 2557 00005E96 01 month: db 1 2558 00005E97 01 day: db 1 2559 00005E98 01 hour: db 1 2560 00005E99 01 minute: db 1 2561 00005E9A 01 second: db 1 2562 00005E9B 01 db 1 2563 2564 DMonth: 2565 00005E9C 0000 dw 0 2566 00005E9E 1F00 dw 31 2567 00005EA0 3B00 dw 59 2568 00005EA2 5A00 dw 90 2569 00005EA4 7800 dw 120 2570 00005EA6 9700 dw 151 2571 00005EA8 B500 dw 181 2572 00005EAA D400 dw 212 2573 00005EAC F300 dw 243 2574 00005EAE 1101 dw 273 2575 00005EB0 3001 dw 304 2576 00005EB2 4E01 dw 334 2577 2578 ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2) 2579 ; 04/11/2014 (Retro UNIX 386 v1) 2580 00005EB4 0000 mem_1m_1k: dw 0 ; Number of contiguous KB between 2581 ; 1 and 16 MB, max. 3C00h = 15 MB. 2582 00005EB6 0000 dw 0 ; 02/01/2022 (Retro UNIX 386 v1.2) 2583 00005EB8 0000 mem_16m_64k: dw 0 ; Number of contiguous 64 KB blocks 2584 ; between 16 MB and 4 GB. 2585 00005EBA 0000 dw 0 ; 02/01/2022 (Retro UNIX 386 v1.2) 2586 2587 ; 02/01/2022 2588 KEND: 2589 2590 00005EBC 90 align 16 2591 2592 bss_start: 2593 2594 ABSOLUTE bss_start 2595 2596 ; 11/03/2015 2597 ; Interrupt Descriptor Table (20/08/2014) 2598 idt: 2599 00005EC0 resb 64*8 ; INT 0 to INT 3Fh 2600 idt_end: 2601 2602 ;alignb 4 2603 2604 task_state_segment: 2605 ; 24/03/2015 2606 000060C0 ???? tss.link: resw 1 2607 000060C2 ???? resw 1 2608 ; tss offset 4 2609 000060C4 ???????? tss.esp0: resd 1 2610 000060C8 ???? tss.ss0: resw 1 2611 000060CA ???? resw 1 2612 000060CC ???????? tss.esp1: resd 1 2613 000060D0 ???? tss.ss1: resw 1 2614 000060D2 ???? resw 1 2615 000060D4 ???????? tss.esp2: resd 1 2616 000060D8 ???? tss.ss2: resw 1 2617 000060DA ???? resw 1 2618 ; tss offset 28 2619 000060DC ???????? tss.CR3: resd 1 2620 000060E0 ???????? tss.eip: resd 1 2621 000060E4 ???????? tss.eflags: resd 1 2622 ; tss offset 40 2623 000060E8 ???????? tss.eax: resd 1 2624 000060EC ???????? tss.ecx: resd 1 2625 000060F0 ???????? tss.edx: resd 1 2626 000060F4 ???????? tss.ebx: resd 1 2627 000060F8 ???????? tss.esp: resd 1 2628 000060FC ???????? tss.ebp: resd 1 2629 00006100 ???????? tss.esi: resd 1 2630 00006104 ???????? tss.edi: resd 1 2631 ; tss offset 72 2632 00006108 ???? tss.ES: resw 1 2633 0000610A ???? resw 1 2634 0000610C ???? tss.CS: resw 1 2635 0000610E ???? resw 1 2636 00006110 ???? tss.SS: resw 1 2637 00006112 ???? resw 1 2638 00006114 ???? tss.DS: resw 1 2639 00006116 ???? resw 1 2640 00006118 ???? tss.FS: resw 1 2641 0000611A ???? resw 1 2642 0000611C ???? tss.GS: resw 1 2643 0000611E ???? resw 1 2644 00006120 ???? tss.LDTR: resw 1 2645 00006122 ???? resw 1 2646 ; tss offset 100 2647 00006124 ???? resw 1 2648 00006126 ???? tss.IOPB: resw 1 2649 ; tss offset 104 2650 tss_end: 2651 2652 00006128 ???????? k_page_dir: resd 1 ; Kernel's (System) Page Directory address 2653 ; (Physical address = Virtual address) 2654 0000612C ???????? memory_size: resd 1 ; memory size in pages 2655 00006130 ???????? free_pages: resd 1 ; number of free pages 2656 00006134 ???????? next_page: resd 1 ; offset value in M.A.T. for 2657 ; first free page search 2658 00006138 ???????? last_page: resd 1 ; offset value in M.A.T. which 2659 ; next free page search will be 2660 ; stopped after it. (end of M.A.T.) 2661 0000613C ???????? first_page: resd 1 ; offset value in M.A.T. which 2662 ; first free page search 2663 ; will be started on it. (for user) 2664 00006140 ???????? mat_size: resd 1 ; Memory Allocation Table size in pages 2665 2666 ;;; 2667 ; 02/09/2014 (Retro UNIX 386 v1) 2668 ; 04/12/2013 (Retro UNIX 8086 v1) 2669 00006144 ???? CRT_START: resw 1 ; starting address in regen buffer 2670 ; NOTE: active page only 2671 00006146 cursor_posn: resw 8 ; cursor positions for video pages 2672 active_page: 2673 00006156 ?? ptty: resb 1 ; current tty 2674 ; 01/07/2015 2675 00006157 ?? ccolor: resb 1 ; current color attributes ('sysmsg') 2676 ; 26/10/2015 2677 ; 07/09/2014 2678 00006158 ttychr: resw ntty+2 ; Character buffer (multiscreen) 2679 2680 ; 21/08/2014 2681 0000616C ???????? tcount: resd 1 2682 2683 ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!) 2684 00006170 ???????? p_time: resd 1 ; present time (for systime & sysmdate) 2685 2686 ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !) 2687 ; (open mode locks for pseudo TTYs) 2688 ; [ major tty locks (return error in any conflicts) ] 2689 00006174 ttyl: resw ntty+2 ; opening locks for TTYs. 2690 2691 ; 15/04/2015 (Retro UNIX 386 v1) 2692 ; 22/09/2013 (Retro UNIX 8086 v1) 2693 00006188 wlist: resb ntty+2 ; wait channel list (0 to 9 for TTYs) 2694 ; 15/04/2015 (Retro UNIX 386 v1) 2695 ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h 2696 ;; 0 means serial port is not available 2697 ;;comprm: ; 25/06/2014 2698 00006192 ?? com1p: resb 1 ;;0E3h 2699 00006193 ?? com2p: resb 1 ;;0E3h 2700 2701 ; 17/11/2015 2702 ; request for response (from the terminal) 2703 00006194 ???? req_resp: resw 1 2704 ; 07/11/2015 2705 00006196 ?? ccomport: resb 1 ; current COM (serial) port 2706 ; (0= COM1, 1= COM2) 2707 ; 09/11/2015 2708 00006197 ?? comqr: resb 1 ; 'query or response' sign (u9.s, 'sndc') 2709 ; 07/11/2015 2710 00006198 ???? rchar: resw 1 ; last received char for COM 1 and COM 2 2711 0000619A ???? schar: resw 1 ; last sent char for COM 1 and COM 2 2712 2713 ; 23/10/2015 2714 ; SERIAL PORTS - COMMUNICATION MODES 2715 ; (Retro UNIX 386 v1 feature only!) 2716 ; 0 - command mode (default/initial mode) 2717 ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars) 2718 ;;; communication modes for futre versions: 2719 ; // 2 - keyboard mode (ascii+scancode input) 2720 ; // 3 - mouse mode 2721 ; // 4 - device control (output) mode 2722 ; VALID COMMANDS for current version: 2723 ; 'LOGIN' 2724 ; Login request: db 0FFh, 'LOGIN', 0 2725 ; ("Retro UNIX 386 v1 terminal requests login") 2726 ; Login response: db 0FFh, 'login', 0 2727 ; ("login request accepted, wait for login prompt") 2728 ; When a login requests is received and acknowledged (by 2729 ; serial port interrupt handler (communication procedure), 2730 ; Retro UNIX 386 v1 operating system will start terminal mode 2731 ; (login procedure) by changing comm. mode to 1 (terminal mode) 2732 ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2) 2733 ; 2734 ; 'sys connect' system call is used to change communication mode 2735 ; except 'LOGIN' command which is used to start terminal mode 2736 ; by using (COM port) terminal. 2737 2738 ;com1own: resb 1 ; COM1 owner (u.uno) 2739 ;com2own: resb 1 ; COM2 owner (u.uno) 2740 ;com1mode: resb 1 ; communication mode for COM1 2741 ;com1com: resb 1 ; communication command for COM1 2742 ;com2mode: resb 1 ; communication mode for COM1 2743 ;com2com resb 1 ; communication command for COM1 2744 ;com1cbufp: resb 8 ; COM1 command buffer char pointer 2745 ;com2cbufp: resb 8 ; COM2 command buffer char pointer 2746 ;com1cbuf: resb 8 ; COM2 command buffer 2747 ;com2cbuf: resb 8 ; COM2 command buffer 2748 2749 ; 22/08/2014 (RTC) 2750 ; (Packed BCD) 2751 0000619C ?? time_seconds: resb 1 2752 0000619D ?? time_minutes: resb 1 2753 0000619E ?? time_hours: resb 1 2754 0000619F ?? date_wday: resb 1 2755 000061A0 ?? date_day: resb 1 2756 000061A1 ?? date_month: resb 1 2757 000061A2 ?? date_year: resb 1 2758 000061A3 ?? date_century: resb 1 2759 2760 %include 'diskbss.inc' ; UNINITIALIZED DISK (BIOS) DATA 2761 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.5) - DISKBSS.INC 2762 <1> ; Last Modification: 10/07/2022 2763 <1> ; (Uninitialized Disk Parameters Data section for 'DISKIO.INC') 2764 <1> ; 2765 <1> ; ***************************************************************************** 2766 <1> 2767 <1> alignb 2 2768 <1> 2769 <1> ;---------------------------------------- 2770 <1> ; TIMER DATA AREA : 2771 <1> ;---------------------------------------- 2772 <1> 2773 <1> TIMER_LH: ; 16/02/205 2774 000061A4 ???? <1> TIMER_LOW: resw 1 ; LOW WORD OF TIMER COUNT 2775 000061A6 ???? <1> TIMER_HIGH: resw 1 ; HIGH WORD OF TIMER COUNT 2776 000061A8 ?? <1> TIMER_OFL: resb 1 ; TIMER HAS ROLLED OVER SINCE LAST READ 2777 <1> 2778 <1> ;---------------------------------------- 2779 <1> ; DISKETTE DATA AREAS : 2780 <1> ;---------------------------------------- 2781 <1> 2782 000061A9 ?? <1> SEEK_STATUS: resb 1 2783 000061AA ?? <1> MOTOR_STATUS: resb 1 2784 000061AB ?? <1> MOTOR_COUNT: resb 1 2785 000061AC ?? <1> DSKETTE_STATUS: resb 1 2786 000061AD ?????????????? <1> NEC_STATUS: resb 7 2787 <1> 2788 <1> ;---------------------------------------- 2789 <1> ; ADDITIONAL MEDIA DATA : 2790 <1> ;---------------------------------------- 2791 <1> 2792 000061B4 ?? <1> LASTRATE: resb 1 2793 000061B5 ?? <1> HF_STATUS: resb 1 2794 <1> ;HF_ERROR: resb 1 ; 10/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2795 000061B6 ?? <1> HF_INT_FLAG: resb 1 2796 <1> ;HF_CNTRL: resb 1 ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2797 <1> ;DSK_STATE: resb 4 2798 000061B7 ???? <1> DSK_STATE: resb 2 ; 08/07/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.5) 2799 000061B9 ???? <1> DSK_TRK: resb 2 2800 <1> 2801 <1> ;---------------------------------------- 2802 <1> ; FIXED DISK DATA AREAS : 2803 <1> ;---------------------------------------- 2804 <1> 2805 000061BB ?? <1> DISK_STATUS1: resb 1 ; FIXED DISK STATUS 2806 000061BC ?? <1> HF_NUM: resb 1 ; COUNT OF FIXED DISK DRIVES 2807 000061BD ?? <1> CONTROL_BYTE: resb 1 ; HEAD CONTROL BYTE 2808 <1> ;@PORT_OFF resb 1 ; RESERVED (PORT OFFSET) 2809 <1> ;port1_off resb 1 ; Hard disk controller 1 - port offset 2810 <1> ;port2_off resb 1 ; Hard disk controller 2 - port offset 2811 <1> 2812 000061BE ???? <1> alignb 4 2813 <1> 2814 <1> ;HF_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 2815 <1> ;HF1_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 2816 <1> HF_TBL_VEC: ; 22/12/2014 2817 000061C0 ???????? <1> HDPM_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 2818 000061C4 ???????? <1> HDPS_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 2819 000061C8 ???????? <1> HDSM_TBL_VEC: resd 1 ; Secondary master disk param. tbl. pointer 2820 000061CC ???????? <1> HDSS_TBL_VEC: resd 1 ; Secondary slave disk param. tbl. pointer 2821 <1> 2822 <1> ; 03/01/2015 2823 000061D0 ?? <1> LBAMode: resb 1 2824 <1> 2825 <1> ; ***************************************************************************** 2761 2762 ;;; Real Mode Data (10/07/2015 - BSS) 2763 2764 ;alignb 2 2765 2766 ; 02/01/2022 2767 ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data) 2768 2769 ; 24/12/2021 2770 ; (memory page swap parameters are disabled as temporary) 2771 ; 2772 ;; Memory (swap) Data (11/03/2015) 2773 ; 09/03/2015 2774 ;swpq_count: resw 1 ; count of pages on the swap que 2775 ;swp_drv: resd 1 ; logical drive description table address of the swap drive/disk 2776 ;swpd_size: resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 2777 ;swpd_free: resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical) 2778 ;swpd_next: resd 1 ; next free page block 2779 ;swpd_last: resd 1 ; last swap page block 2780 2781 000061D1 ?????? alignb 4 2782 2783 ; 10/07/2015 2784 ; 28/08/2014 2785 000061D4 ???????? error_code: resd 1 2786 ; 29/08/2014 2787 000061D8 ???????? FaultOffset: resd 1 2788 ; 21/09/2015 2789 000061DC ???????? PF_Count: resd 1 ; total page fault count 2790 ; (for debugging - page fault analyze) 2791 ; 'page _fault_handler' (memory.inc) 2792 ; 'sysgeterr' (u9.s) 2793 ; 26/02/2022 2794 000061E0 ???????? rtc_ticks: resd 1 ; (temporary! this rtc counter value may be used 2795 ; for a system call in next retro unix 386 version) 2796 ; -2 ticks per second- 2797 ;; 21/08/2015 2798 ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s 2799 2800 ; 02/01/2022 2801 %include 'ux.s' ; 12/04/2015 (unix system/user/process data) 2802 <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.6) - SYSX.INC (ux.s) 2803 <1> ; Last Modification: 15/07/2022 2804 <1> ; ---------------------------------------------------------------------------- 2805 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 2806 <1> ; (Modified from 2807 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 2808 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 2809 <1> ; ---------------------------------------------------------------------------- 2810 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 2811 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 2812 <1> ; 2813 <1> ; 2814 <1> ; (Section E10 (17/3/1972) - ux.s) 2815 <1> ; **************************************************************************** 2816 <1> ; 04/12/2015 2817 <1> 2818 <1> alignb 2 2819 <1> 2820 <1> inode: 2821 <1> ; 11/03/2013. 2822 <1> ;Derived from UNIX v1 source code 'inode' structure (ux). 2823 <1> ;i. 2824 <1> 2825 000061E4 ???? <1> i.flgs: resw 1 2826 000061E6 ?? <1> i.nlks: resb 1 2827 000061E7 ?? <1> i.uid: resb 1 2828 000061E8 ???? <1> i.size: resw 1 ; size 2829 000061EA <1> i.dskp: resw 8 ; 16 bytes 2830 000061FA ???????? <1> i.ctim: resd 1 2831 000061FE ???????? <1> i.mtim: resd 1 2832 00006202 ???? <1> i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.) 2833 <1> 2834 <1> I_SIZE equ $ - inode 2835 <1> 2836 <1> process: 2837 <1> ; 26/02/2022 2838 <1> ; 12/01/2022 (Retro UNIX 386 v1.1) 2839 <1> ; 06/05/2015 2840 <1> ; 11/03/2013 - 05/02/2014 2841 <1> ;Derived from UNIX v1 source code 'proc' structure (ux). 2842 <1> ;p. 2843 <1> 2844 00006204 <1> p.pid: resw nproc 2845 00006224 <1> p.ppid: resw nproc 2846 <1> ;p.break: resw nproc ; 12/01/2022 (p.break is not used) 2847 00006244 <1> p.ttyc: resb nproc ; console tty in Retro UNIX 8086 v1. 2848 <1> ; 26/02/2022 (p.waitc is not used) 2849 <1> ;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1. 2850 00006254 <1> p.link: resb nproc 2851 00006264 <1> p.stat: resb nproc 2852 <1> 2853 <1> ; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 2854 00006274 <1> p.upage: resd nproc ; Physical address of the process's 2855 <1> ; 'user' structure 2856 <1> 2857 <1> P_SIZE equ $ - process 2858 <1> 2859 <1> ; fsp table (original UNIX v1) 2860 <1> ; 2861 <1> ;Entry 2862 <1> ; 15 0 2863 <1> ; 1 |---|---------------------------------------| 2864 <1> ; |r/w| i-number of open file | 2865 <1> ; |---|---------------------------------------| 2866 <1> ; | device number | 2867 <1> ; |-------------------------------------------| 2868 <1> ; (*) | offset pointer, i.e., r/w pointer to file | 2869 <1> ; |-------------------------------------------| 2870 <1> ; | flag that says | number of processes | 2871 <1> ; | file deleted | that have file open | 2872 <1> ; |-------------------------------------------| 2873 <1> ; 2 | | 2874 <1> ; |-------------------------------------------| 2875 <1> ; | | 2876 <1> ; |-------------------------------------------| 2877 <1> ; | | 2878 <1> ; |-------------------------------------------| 2879 <1> ; | | 2880 <1> ; |-------------------------------------------| 2881 <1> ; 3 | | 2882 <1> ; | | 2883 <1> ; 2884 <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 2885 <1> 2886 <1> ; 15/04/2015 2887 000062B4 <1> fsp: resb nfiles*10 ; 11/05/2015 (8 -> 10) 2888 000064A8 <1> bufp: resd (nbuf+2) ; will be initialized 2889 000064D0 ???? <1> ii: resw 1 2890 <1> ;idev: resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 ! 2891 <1> ;cdev: resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 ! 2892 <1> ; 11/01/2022 2893 000064D2 ?? <1> idev: resb 1 2894 000064D3 ?? <1> cdev: resb 1 2895 <1> ; 18/05/2015 2896 <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!) 2897 <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv') 2898 <1> ; 0 -> root device (which has Retro UNIX 8086 v1 file system) 2899 <1> ; 1 -> mounted device (which has Retro UNIX 8086 v1 file system) 2900 <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures) 2901 <1> ; 0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0 2902 <1> ; 1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1 2903 <1> ; 2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h 2904 <1> ; 3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h 2905 <1> ; 4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h 2906 <1> ; 5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h 2907 000064D4 ?? <1> rdev: resb 1 ; root device number ; Retro UNIX 8086 v1 feature only! 2908 <1> ; as above, for physical drives numbers in following table 2909 000064D5 ?? <1> mdev: resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only! 2910 <1> ; 15/04/2015 2911 <1> ;active: resb 1 ; 15/07/2022 2912 <1> ; resb 1 ; 09/06/2015 2913 000064D6 ???? <1> mnti: resw 1 2914 000064D8 ???? <1> mntp: resw 1 ; 15/05/2022 ; (parent dir inumber of [mnti]) 2915 000064DA ???? <1> mpid: resw 1 2916 000064DC ???? <1> rootdir: resw 1 2917 <1> ; 14/02/2014 2918 <1> ; Major Modification: Retro UNIX 8086 v1 feature only! 2919 <1> ; Single level run queue 2920 <1> ; (in order to solve sleep/wakeup lock) 2921 000064DE ???? <1> runq: resw 1 2922 000064E0 ?? <1> imod: resb 1 2923 000064E1 ?? <1> smod: resb 1 2924 000064E2 ?? <1> mmod: resb 1 2925 000064E3 ?? <1> sysflg: resb 1 2926 <1> 2927 <1> alignb 4 2928 <1> 2929 <1> user: 2930 <1> ; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2) 2931 <1> ; 04/12/2015 2932 <1> ; 18/10/2015 2933 <1> ; 12/10/2015 2934 <1> ; 21/09/2015 2935 <1> ; 24/07/2015 2936 <1> ; 16/06/2015 2937 <1> ; 09/06/2015 2938 <1> ; 11/05/2015 2939 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications) 2940 <1> ; 10/10/2013 2941 <1> ; 11/03/2013. 2942 <1> ;Derived from UNIX v1 source code 'user' structure (ux). 2943 <1> ;u. 2944 <1> 2945 000064E4 ???????? <1> u.sp: resd 1 ; esp (kernel stack at the beginning of 'sysent') 2946 000064E8 ???????? <1> u.usp: resd 1 ; esp (kernel stack points to user's registers) 2947 000064EC ???????? <1> u.r0: resd 1 ; eax 2948 000064F0 ???? <1> u.cdir: resw 1 2949 000064F2 <1> u.fp: resb 10 2950 000064FC ???????? <1> u.fofp: resd 1 2951 00006500 ???????? <1> u.dirp: resd 1 2952 00006504 ???????? <1> u.namep: resd 1 2953 00006508 ???????? <1> u.off: resd 1 2954 0000650C ???????? <1> u.base: resd 1 2955 00006510 ???????? <1> u.count: resd 1 2956 00006514 ???????? <1> u.nread: resd 1 2957 00006518 ???????? <1> u.break: resd 1 ; break 2958 0000651C ???? <1> u.ttyp: resw 1 2959 0000651E <1> u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 2960 <1> ;u.pri: resw 1 ; 14/02/2014 2961 0000652E ?? <1> u.quant: resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant) 2962 0000652F ?? <1> u.pri: resb 1 ; 2963 00006530 ???? <1> u.intr: resw 1 2964 00006532 ???? <1> u.quit: resw 1 2965 <1> ;u.emt: resw 1 ; 10/10/2013 2966 00006534 ???? <1> u.ilgins: resw 1 2967 <1> ;u.cdrv: resw 1 ; cdev 2968 00006536 ?? <1> u.cdrv: resb 1 ; 09/01/2022 2969 00006537 ?? <1> resb 1 ; 09/01/2022 (dword alignment) 2970 00006538 ?? <1> u.uid: resb 1 ; uid 2971 00006539 ?? <1> u.ruid: resb 1 2972 0000653A ?? <1> u.bsys: resb 1 2973 0000653B ?? <1> u.uno: resb 1 2974 0000653C ???????? <1> u.upage: resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only ! 2975 <1> ; tty number (rtty, rcvt, wtty) 2976 00006540 ?? <1> u.ttyn: resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only ! 2977 <1> ; last error number 2978 00006541 ???????? <1> u.error: resd 1 ; 28/07/2013 - 09/03/2015 2979 <1> ; Retro UNIX 8086/386 v1 feature only! 2980 00006545 ???????? <1> u.pgdir: resd 1 ; 09/03/2015 (page dir addr of process) 2981 00006549 ???????? <1> u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process) 2982 0000654D ???????? <1> u.pbase: resd 1 ; 20/05/2015 (physical base/transfer address) 2983 00006551 ???? <1> u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page) 2984 <1> ;u.pncount: resw 1 2985 <1> ; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir') 2986 <1> ;u.pnbase: resd 1 2987 <1> ; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir') 2988 <1> ; 09/06/2015 2989 00006553 ?? <1> u.kcall: resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign 2990 00006554 ?? <1> u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite) 2991 <1> ; 24/07/2015 - 24/06/2015 2992 <1> ;u.args: resd 1 ; arguments list (line) offset from start of [u.upage] 2993 <1> ; (arg list/line is from offset [u.args] to 4096 in [u.upage]) 2994 <1> ; ([u.args] points to argument count -argc- address offset) 2995 <1> ; 24/06/2015 2996 <1> ;u.core: resd 1 ; physical start address of user's memory space (for sys exec) 2997 <1> ;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec) 2998 <1> ; 21/09/2015 (debugging - page fault analyze) 2999 00006555 ???????? <1> u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr) 3000 <1> 3001 00006559 ?????? <1> alignb 4 3002 <1> 3003 <1> U_SIZE equ $ - user 3004 <1> 3005 <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec') 3006 0000655C ???????? <1> pcore: resd 1 ; physical start address of user's memory space (for sys exec) 3007 00006560 ???????? <1> ecore: resd 1 ; physical start address of user's memory space (for sys exec) 3008 00006564 ???????? <1> nbase: resd 1 ; physical base address for 'namei' & 'sysexec' 3009 00006568 ???? <1> ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec' 3010 <1> ;argc: resw 1 ; argument count for 'sysexec' 3011 0000656A ?? <1> argc: resb 1 ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 3012 0000656B ?? <1> resb 1 3013 0000656C ???????? <1> argv: resd 1 ; argument list (recent) address for 'sysexec' 3014 <1> 3015 <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning 3016 <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1 3017 00006570 ?? <1> rw: resb 1 ;; Read/Write sign (iget) 3018 00006571 ?? <1> rwdsk: resb 1 ;; Read/Write function number (diskio) - 16/06/2015 3019 00006572 ?? <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015 3020 00006573 ?? <1> resb 1 ;; Reserved (16/06/2015) 3021 <1> 3022 <1> ;alignb 4 3023 <1> 3024 <1> ; 22/08/2015 3025 00006574 <1> buffer: resb nbuf * 520 3026 <1> 3027 000075B4 ???????????????? <1> sb0: resd 2 3028 <1> ;s: 3029 <1> ; (root disk) super block buffer 3030 <1> systm: 3031 <1> ; 13/11/2015 (Retro UNIX 386 v1) 3032 <1> ; 11/03/2013. 3033 <1> ;Derived from UNIX v1 source code 'systm' structure (ux). 3034 <1> ;s. 3035 <1> 3036 000075BC ???? <1> resw 1 3037 000075BE <1> resb 360 ; 2880 sectors ; original UNIX v1 value: 128 3038 00007726 ???? <1> resw 1 3039 00007728 <1> resb 32 ; 256+40 inodes ; original UNIX v1 value: 64 3040 <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table) 3041 00007748 ???????? <1> s.time: resd 1 3042 0000774C ???????? <1> s.syst: resd 1 3043 00007750 ???????? <1> s.wait_: resd 1 ; wait 3044 00007754 ???????? <1> s.idlet: resd 1 3045 00007758 ???????? <1> s.chrgt: resd 1 3046 0000775C ???? <1> s.drerr: resw 1 3047 <1> 3048 <1> S_SIZE equ $ - systm 3049 <1> 3050 0000775E <1> resb 512-S_SIZE ; 03/06/2015 3051 <1> 3052 000077BC ???????????????? <1> sb1: resd 2 3053 <1> ; (mounted disk) super block buffer 3054 <1> mount: 3055 000077C4 <1> resb 512 ; 03/06/2015 3056 <1> 3057 <1> ;/ ux -- unix 3058 <1> ; 3059 <1> ;systm: 3060 <1> ; 3061 <1> ; .=.+2 3062 <1> ; .=.+128. 3063 <1> ; .=.+2 3064 <1> ; .=.+64. 3065 <1> ; s.time: .=.+4 3066 <1> ; s.syst: .=.+4 3067 <1> ; s.wait: .=.+4 3068 <1> ; s.idlet:.=.+4 3069 <1> ; s.chrgt:.=.+4 3070 <1> ; s.drerr:.=.+2 3071 <1> ;inode: 3072 <1> ; i.flgs: .=.+2 3073 <1> ; i.nlks: .=.+1 3074 <1> ; i.uid: .=.+1 3075 <1> ; i.size: .=.+2 3076 <1> ; i.dskp: .=.+16. 3077 <1> ; i.ctim: .=.+4 3078 <1> ; i.mtim: .=.+4 3079 <1> ; . = inode+32. 3080 <1> ;mount: .=.+1024. 3081 <1> ;proc: 3082 <1> ; p.pid: .=.+[2*nproc] 3083 <1> ; p.dska: .=.+[2*nproc] 3084 <1> ; p.ppid: .=.+[2*nproc] 3085 <1> ; p.break:.=.+[2*nproc] 3086 <1> ; p.link: .=.+nproc 3087 <1> ; p.stat: .=.+nproc 3088 <1> ;tty: 3089 <1> ; . = .+[ntty*8.] 3090 <1> ;fsp: .=.+[nfiles*8.] 3091 <1> ;bufp: .=.+[nbuf*2]+6 3092 <1> ;sb0: .=.+8 3093 <1> ;sb1: .=.+8 3094 <1> ;swp: .=.+8 3095 <1> ;ii: .=.+2 3096 <1> ;idev: .=.+2 3097 <1> ;cdev: .=.+2 3098 <1> ;deverr: .=.+12. 3099 <1> ;active: .=.+2 3100 <1> ;rfap: .=.+2 3101 <1> ;rkap: .=.+2 3102 <1> ;tcap: .=.+2 3103 <1> ;tcstate:.=.+2 3104 <1> ;tcerrc: .=.+2 3105 <1> ;mnti: .=.+2 3106 <1> ;mntd: .=.+2 3107 <1> ;mpid: .=.+2 3108 <1> ;clockp: .=.+2 3109 <1> ;rootdir:.=.+2 3110 <1> ;toutt: .=.+16. 3111 <1> ;touts: .=.+32. 3112 <1> ;runq: .=.+6 3113 <1> ; 3114 <1> ;wlist: .=.+40. 3115 <1> ;cc: .=.+30. 3116 <1> ;cf: .=.+31. 3117 <1> ;cl: .=.+31. 3118 <1> ;clist: .=.+510. 3119 <1> ;imod: .=.+1 3120 <1> ;smod: .=.+1 3121 <1> ;mmod: .=.+1 3122 <1> ;uquant: .=.+1 3123 <1> ;sysflg: .=.+1 3124 <1> ;pptiflg:.=.+1 3125 <1> ;ttyoch: .=.+1 3126 <1> ; .even 3127 <1> ; .=.+100.; sstack: 3128 <1> ;buffer: .=.+[ntty*140.] 3129 <1> ; .=.+[nbuf*520.] 3130 <1> ; 3131 <1> ; . = core-64. 3132 <1> ;user: 3133 <1> ; u.sp: .=.+2 3134 <1> ; u.usp: .=.+2 3135 <1> ; u.r0: .=.+2 3136 <1> ; u.cdir: .=.+2 3137 <1> ; u.fp: .=.+10. 3138 <1> ; u.fofp: .=.+2 3139 <1> ; u.dirp: .=.+2 3140 <1> ; u.namep: .=.+2 3141 <1> ; u.off: .=.+2 3142 <1> ; u.base: .=.+2 3143 <1> ; u.count: .=.+2 3144 <1> ; u.nread: .=.+2 3145 <1> ; u.break: .=.+2 3146 <1> ; u.ttyp: .=.+2 3147 <1> ; u.dirbuf:.=.+10. 3148 <1> ; u.pri: .=.+2 3149 <1> ; u.intr: .=.+2 3150 <1> ; u.quit: .=.+2 3151 <1> ; u.emt: .=.+2 3152 <1> ; u.ilgins:.=.+2 3153 <1> ; u.cdev: .=.+2 3154 <1> ; u.uid: .=.+1 3155 <1> ; u.ruid: .=.+1 3156 <1> ; u.bsys: .=.+1 3157 <1> ; u.uno: .=.+1 3158 <1> ;. = core 2802 2803 ; 27/12/2021 2804 ;buffer: resb (nbuf*520) 2805 2806 bss_end: 2807 2808 ; 02/01/2022 2809 BSS_SIZE equ bss_end - bss_start 2810 2811 ; 27/12/2013 2812 _end: ; end of kernel code (and read only data, just before bss)