1 ; **************************************************************************** 2 ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.0 3 ; ---------------------------------------------------------------------------- 4 ; NASM version 2.11 (unix386.s) 5 ; 6 ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix) 7 ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013) 8 ; 9 ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 10 ; (v0.1 - Beginning: 11/07/2012) 11 ; 12 ; [ Last Modification: 04/02/2016 ] 13 ; 14 ; Derived from UNIX Operating System (v1.0 for PDP-11) 15 ; (Original) Source Code by Ken Thompson (1971-1972) 16 ; 17 ; 18 ; 19 ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999) 20 ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details. 21 ; 22 ; **************************************************************************** 23 24 ; 24/12/2013 25 26 ; Entering protected mode: 27 ; Derived from 'simple_asm.txt' source code file and 28 ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003) 29 ; (gregor.brunmar@home.se) 30 ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode 31 ; 32 33 ; "The Real, Protected, Long mode assembly tutorial for PCs" 34 ; by Michael Chourdakis (2009) 35 ; http://www.codeproject.com/Articles/45788/ 36 ; http://www.michaelchourdakis.com 37 ; 38 39 ; Global Descriptor Table: 40 ; Derived from 'head.s" source code of Linux v1.0 kernel 41 ; by Linus Torvalds (1991-1992) 42 ; 43 44 KLOAD equ 10000h ; Kernel loading address 45 ; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 46 KCODE equ 08h ; Code segment descriptor (ring 0) 47 KDATA equ 10h ; Data segment descriptor (ring 0) 48 ; 19/03/2015 49 UCODE equ 1Bh ; 18h + 3h (ring 3) 50 UDATA equ 23h ; 20h + 3h (ring 3) 51 ; 24/03/2015 52 TSS equ 28h ; Task state segment descriptor (ring 0) 53 ; 19/03/2015 54 CORE equ 400000h ; Start of USER's virtual/linear address space 55 ; (at the end of the 1st 4MB) 56 ECORE equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB) 57 ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT) 58 59 ; 27/12/2013 60 KEND equ KLOAD + 65536 ; (28/12/2013) (end of kernel space) 61 62 ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc) 63 ;--------- CMOS TABLE LOCATION ADDRESS'S ------------------------------------- 64 CMOS_SECONDS EQU 00H ; SECONDS (BCD) 65 CMOS_MINUTES EQU 02H ; MINUTES (BCD) 66 CMOS_HOURS EQU 04H ; HOURS (BCD) 67 CMOS_DAY_WEEK EQU 06H ; DAY OF THE WEEK (BCD) 68 CMOS_DAY_MONTH EQU 07H ; DAY OF THE MONTH (BCD) 69 CMOS_MONTH EQU 08H ; MONTH (BCD) 70 CMOS_YEAR EQU 09H ; YEAR (TWO DIGITS) (BCD) 71 CMOS_CENTURY EQU 32H ; DATE CENTURY BYTE (BCD) 72 CMOS_REG_A EQU 0AH ; STATUS REGISTER A 73 CMOS_REG_B EQU 00BH ; STATUS REGISTER B ALARM 74 CMOS_REG_C EQU 00CH ; STATUS REGISTER C FLAGS 75 CMOS_REG_D EQU 0DH ; STATUS REGISTER D BATTERY 76 CMOS_SHUT_DOWN EQU 0FH ; SHUTDOWN STATUS COMMAND BYTE 77 ;---------------------------------------- 78 ; CMOS EQUATES FOR THIS SYSTEM ; 79 ;----------------------------------------------------------------------------- 80 CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 81 CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 82 NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 83 ; HIGH BIT OF CMOS LOCATION ADDRESS 84 85 ; Memory Allocation Table Address 86 ; 05/11/2014 87 ; 31/10/2014 88 MEM_ALLOC_TBL equ 100000h ; Memory Allocation Table at the end of 89 ; the 1st 1 MB memory space. 90 ; (This address must be aligned 91 ; on 128 KB boundary, if it will be 92 ; changed later.) 93 ; ((lower 17 bits of 32 bit M.A.T. 94 ; address must be ZERO)). 95 ; ((((Reason: 32 bit allocation 96 ; instructions, dword steps))) 97 ; (((byte >> 12 --> page >> 5))) 98 ;04/11/2014 99 PDE_A_PRESENT equ 1 ; Present flag for PDE 100 PDE_A_WRITE equ 2 ; Writable (write permission) flag 101 PDE_A_USER equ 4 ; User (non-system/kernel) page flag 102 ; 103 PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 104 PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 105 PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 106 PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 107 108 ; 17/02/2015 (unix386.s) 109 ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s) 110 DPT_SEGM equ 09000h ; FDPT segment (EDD v1.1, EDD v3) 111 ; 112 HD0_DPT equ 0 ; Disk parameter table address for hd0 113 HD1_DPT equ 32 ; Disk parameter table address for hd1 114 HD2_DPT equ 64 ; Disk parameter table address for hd2 115 HD3_DPT equ 96 ; Disk parameter table address for hd3 116 117 118 ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0) 119 ; (HDPT: Programmer's Guide to the AMIBIOS, 1993) 120 ; 121 FDPT_CYLS equ 0 ; 1 word, number of cylinders 122 FDPT_HDS equ 2 ; 1 byte, number of heads 123 FDPT_TT equ 3 ; 1 byte, A0h = translated FDPT with logical values 124 ; otherwise it is standard FDPT with physical values 125 FDPT_PCMP equ 5 ; 1 word, starting write precompensation cylinder 126 ; (obsolete for IDE/ATA drives) 127 FDPT_CB equ 8 ; 1 byte, drive control byte 128 ; Bits 7-6 : Enable or disable retries (00h = enable) 129 ; Bit 5 : 1 = Defect map is located at last cyl. + 1 130 ; Bit 4 : Reserved. Always 0 131 ; Bit 3 : Set to 1 if more than 8 heads 132 ; Bit 2-0 : Reserved. Alsways 0 133 FDPT_LZ equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives) 134 FDPT_SPT equ 14 ; 1 byte, sectors per track 135 136 ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993) 137 ; (11 bytes long) will be used by diskette handler/bios 138 ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986). 139 140 [BITS 16] ; We need 16-bit intructions for Real mode 141 142 [ORG 0] 143 ; 12/11/2014 144 ; Save boot drive number (that is default root drive) 145 00000000 8816[1A6B] mov [boot_drv], dl ; physical drv number 146 147 ; Determine installed memory 148 ; 31/10/2014 149 ; 150 00000004 B801E8 mov ax, 0E801h ; Get memory size 151 00000007 CD15 int 15h ; for large configurations 152 00000009 7308 jnc short chk_ms 153 0000000B B488 mov ah, 88h ; Get extended memory size 154 0000000D CD15 int 15h 155 ; 156 ;mov al, 17h ; Extended memory (1K blocks) low byte 157 ;out 70h, al ; select CMOS register 158 ;in al, 71h ; read data (1 byte) 159 ;mov cl, al 160 ;mov al, 18h ; Extended memory (1K blocks) high byte 161 ;out 70h, al ; select CMOS register 162 ;in al, 71h ; read data (1 byte) 163 ;mov ch, al 164 ; 165 0000000F 89C1 mov cx, ax 166 00000011 31D2 xor dx, dx 167 chk_ms: 168 00000013 890E[F06D] mov [mem_1m_1k], cx 169 00000017 8916[F26D] mov [mem_16m_64k], dx 170 ; 05/11/2014 171 ;and dx, dx 172 ;jz short L2 173 0000001B 81F90004 cmp cx, 1024 174 0000001F 7315 jnb short L0 175 ; insufficient memory_error 176 ; Minimum 2 MB memory is needed... 177 ; 05/11/2014 178 ; (real mode error printing) 179 00000021 FB sti 180 00000022 BE[696C] mov si, msg_out_of_memory 181 00000025 BB0700 mov bx, 7 182 00000028 B40E mov ah, 0Eh ; write tty 183 oom_1: 184 0000002A AC lodsb 185 0000002B 08C0 or al, al 186 0000002D 7404 jz short oom_2 187 0000002F CD10 int 10h 188 00000031 EBF7 jmp short oom_1 189 oom_2: 190 00000033 F4 hlt 191 00000034 EBFD jmp short oom_2 192 193 L0: 194 %include 'diskinit.inc' ; 07/03/2015 195 <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC 196 <1> ; Last Modification: 04/02/2016 197 <1> 198 <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project) 199 <1> 200 <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION /////////////// 201 <1> 202 <1> ; 10/12/2014 - 02/02/2015 - dsectrm2.s 203 <1> ;L0: 204 <1> ; 12/11/2014 (Retro UNIX 386 v1 - beginning) 205 <1> ; Detecting disk drives... (by help of ROM-BIOS) 206 00000036 BA7F00 <1> mov dx, 7Fh 207 <1> L1: 208 00000039 FEC2 <1> inc dl 209 0000003B B441 <1> mov ah, 41h ; Check extensions present 210 <1> ; Phoenix EDD v1.1 - EDD v3 211 0000003D BBAA55 <1> mov bx, 55AAh 212 00000040 CD13 <1> int 13h 213 00000042 721A <1> jc short L2 214 <1> 215 00000044 81FB55AA <1> cmp bx, 0AA55h 216 00000048 7514 <1> jne short L2 217 0000004A FE06[1D6B] <1> inc byte [hdc] ; count of hard disks (EDD present) 218 0000004E 8816[1C6B] <1> mov [last_drv], dl ; last hard disk number 219 00000052 BB[A06A] <1> mov bx, hd0_type - 80h 220 00000055 01D3 <1> add bx, dx 221 00000057 880F <1> mov [bx], cl ; Interface support bit map in CX 222 <1> ; Bit 0 - 1, Fixed disk access subset ready 223 <1> ; Bit 1 - 1, Drv locking and ejecting ready 224 <1> ; Bit 2 - 1, Enhanced Disk Drive Support 225 <1> ; (EDD) ready (DPTE ready) 226 <1> ; Bit 3 - 1, 64bit extensions are present 227 <1> ; (EDD-3) 228 <1> ; Bit 4 to 15 - 0, Reserved 229 00000059 80FA83 <1> cmp dl, 83h ; drive number < 83h 230 0000005C 72DB <1> jb short L1 231 <1> L2: 232 <1> ; 23/11/2014 233 <1> ; 19/11/2014 234 0000005E 30D2 <1> xor dl, dl ; 0 235 <1> ; 04/02/2016 (esi -> si) 236 00000060 BE[1E6B] <1> mov si, fd0_type 237 <1> L3: 238 <1> ; 14/01/2015 239 00000063 8816[1B6B] <1> mov [drv], dl 240 <1> ; 241 00000067 B408 <1> mov ah, 08h ; Return drive parameters 242 00000069 CD13 <1> int 13h 243 0000006B 7210 <1> jc short L4 244 <1> ; BL = drive type (for floppy drives) 245 <1> ; DL = number of floppy drives 246 <1> ; 247 <1> ; ES:DI = Address of DPT from BIOS 248 <1> ; 249 0000006D 881C <1> mov [si], bl ; Drive type 250 <1> ; 4 = 1.44 MB, 80 track, 3 1/2" 251 <1> ; 14/01/2015 252 0000006F E8A202 <1> call set_disk_parms 253 <1> ; 10/12/2014 254 00000072 81FE[1E6B] <1> cmp si, fd0_type 255 00000076 7705 <1> ja short L4 256 00000078 46 <1> inc si ; fd1_type 257 00000079 B201 <1> mov dl, 1 258 0000007B EBE6 <1> jmp short L3 259 <1> L4: 260 <1> ; Older BIOS (INT 13h, AH = 48h is not available) 261 0000007D B27F <1> mov dl, 7Fh 262 <1> ; 24/12/2014 (Temporary) 263 0000007F 803E[1D6B]00 <1> cmp byte [hdc], 0 ; EDD present or not ? 264 00000084 0F879000 <1> ja L10 ; yes, all fixed disk operations 265 <1> ; will be performed according to 266 <1> ; present EDD specification 267 <1> L6: 268 00000088 FEC2 <1> inc dl 269 0000008A 8816[1B6B] <1> mov [drv], dl 270 0000008E 8816[1C6B] <1> mov [last_drv], dl ; 14/01/2015 271 00000092 B408 <1> mov ah, 08h ; Return drive parameters 272 00000094 CD13 <1> int 13h ; (conventional function) 273 00000096 0F828201 <1> jc L13 ; fixed disk drive not ready 274 0000009A 8816[1D6B] <1> mov [hdc], dl ; number of drives 275 <1> ;; 14/01/2013 276 <1> ;;push cx 277 0000009E E87302 <1> call set_disk_parms 278 <1> ;;pop cx 279 <1> ; 280 <1> ;;and cl, 3Fh ; sectors per track (bits 0-6) 281 000000A1 8A16[1B6B] <1> mov dl, [drv] 282 000000A5 BB0401 <1> mov bx, 65*4 ; hd0 parameters table (INT 41h) 283 000000A8 80FA80 <1> cmp dl, 80h 284 000000AB 7603 <1> jna short L7 285 000000AD 83C314 <1> add bx, 5*4 ; hd1 parameters table (INT 46h) 286 <1> L7: 287 000000B0 31C0 <1> xor ax, ax 288 000000B2 8ED8 <1> mov ds, ax 289 000000B4 8B37 <1> mov si, [bx] 290 000000B6 8B4702 <1> mov ax, [bx+2] 291 000000B9 8ED8 <1> mov ds, ax 292 000000BB 3A4C0E <1> cmp cl, [si+FDPT_SPT] ; sectors per track 293 000000BE 0F855601 <1> jne L12 ; invalid FDPT 294 000000C2 BF0000 <1> mov di, HD0_DPT 295 000000C5 80FA80 <1> cmp dl, 80h 296 000000C8 7603 <1> jna short L8 297 000000CA BF2000 <1> mov di, HD1_DPT 298 <1> L8: 299 <1> ; 30/12/2014 300 000000CD B80090 <1> mov ax, DPT_SEGM 301 000000D0 8EC0 <1> mov es, ax 302 <1> ; 24/12/2014 303 000000D2 B90800 <1> mov cx, 8 304 000000D5 F3A5 <1> rep movsw ; copy 16 bytes to the kernel's DPT location 305 000000D7 8CC8 <1> mov ax, cs 306 000000D9 8ED8 <1> mov ds, ax 307 <1> ; 02/02/2015 308 000000DB 8A0E[1B6B] <1> mov cl, [drv] 309 000000DF 88CB <1> mov bl, cl 310 000000E1 B8F001 <1> mov ax, 1F0h 311 000000E4 80E301 <1> and bl, 1 312 000000E7 7406 <1> jz short L9 313 000000E9 C0E304 <1> shl bl, 4 314 000000EC 2D8000 <1> sub ax, 1F0h-170h 315 <1> L9: 316 000000EF AB <1> stosw ; I/O PORT Base Address (1F0h, 170h) 317 000000F0 050602 <1> add ax, 206h 318 000000F3 AB <1> stosw ; CONTROL PORT Address (3F6h, 376h) 319 000000F4 88D8 <1> mov al, bl 320 000000F6 04A0 <1> add al, 0A0h 321 000000F8 AA <1> stosb ; Device/Head Register upper nibble 322 <1> ; 323 000000F9 FE06[1B6B] <1> inc byte [drv] 324 000000FD BB[A06A] <1> mov bx, hd0_type - 80h 325 00000100 01CB <1> add bx, cx 326 00000102 800F80 <1> or byte [bx], 80h ; present sign (when lower nibble is 0) 327 00000105 A0[1D6B] <1> mov al, [hdc] 328 00000108 FEC8 <1> dec al 329 0000010A 0F840E01 <1> jz L13 330 0000010E 80FA80 <1> cmp dl, 80h 331 00000111 0F8673FF <1> jna L6 332 00000115 E90401 <1> jmp L13 333 <1> L10: 334 00000118 FEC2 <1> inc dl 335 <1> ; 25/12/2014 336 0000011A 8816[1B6B] <1> mov [drv], dl 337 0000011E B408 <1> mov ah, 08h ; Return drive parameters 338 00000120 CD13 <1> int 13h ; (conventional function) 339 00000122 0F82F600 <1> jc L13 340 <1> ; 14/01/2015 341 00000126 8A16[1B6B] <1> mov dl, [drv] 342 0000012A 52 <1> push dx 343 0000012B 51 <1> push cx 344 0000012C E8E501 <1> call set_disk_parms 345 0000012F 59 <1> pop cx 346 00000130 5A <1> pop dx 347 <1> ; 04/02/2016 (esi -> si) 348 00000131 BE[3485] <1> mov si, _end ; 30 byte temporary buffer address 349 <1> ; at the '_end' of kernel. 350 00000134 C7041E00 <1> mov word [si], 30 351 00000138 B448 <1> mov ah, 48h ; Get drive parameters (EDD function) 352 0000013A CD13 <1> int 13h 353 0000013C 0F82DC00 <1> jc L13 354 <1> ; 04/02/2016 (ebx -> bx) 355 <1> ; 14/01/2015 356 00000140 29DB <1> sub bx, bx 357 00000142 88D3 <1> mov bl, dl 358 00000144 80EB80 <1> sub bl, 80h 359 00000147 81C3[206B] <1> add bx, hd0_type 360 0000014B 8A07 <1> mov al, [bx] 361 0000014D 0C80 <1> or al, 80h 362 0000014F 8807 <1> mov [bx], al 363 00000151 81EB[1E6B] <1> sub bx, hd0_type - 2 ; 15/01/2015 364 00000155 81C3[6A6B] <1> add bx, drv.status 365 00000159 8807 <1> mov [bx], al 366 <1> ; 04/02/2016 (eax -> ax) 367 0000015B 8B4410 <1> mov ax, [si+16] 368 0000015E 854412 <1> test ax, [si+18] 369 00000161 7412 <1> jz short L10_A0h 370 <1> ; 'CHS only' disks on EDD system 371 <1> ; are reported with ZERO disk size 372 00000163 81EB[6A6B] <1> sub bx, drv.status 373 00000167 C1E302 <1> shl bx, 2 374 0000016A 81C3[4E6B] <1> add bx, drv.size ; disk size (in sectors) 375 0000016E 8907 <1> mov [bx], ax 376 00000170 8B4412 <1> mov ax, [si+18] 377 00000173 8907 <1> mov [bx], ax 378 <1> 379 <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 380 <1> ; for CHS disks (28/02/2015) 381 <1> ; 30/12/2014 382 00000175 BF0000 <1> mov di, HD0_DPT 383 00000178 88D0 <1> mov al, dl 384 0000017A 83E003 <1> and ax, 3 385 0000017D C0E005 <1> shl al, 5 ; *32 386 00000180 01C7 <1> add di, ax 387 00000182 B80090 <1> mov ax, DPT_SEGM 388 00000185 8EC0 <1> mov es, ax 389 <1> ; 390 00000187 88E8 <1> mov al, ch ; max. cylinder number (bits 0-7) 391 00000189 88CC <1> mov ah, cl 392 0000018B C0EC06 <1> shr ah, 6 ; max. cylinder number (bits 8-9) 393 0000018E 40 <1> inc ax ; logical cylinders (limit 1024) 394 0000018F AB <1> stosw 395 00000190 88F0 <1> mov al, dh ; max. head number 396 00000192 FEC0 <1> inc al 397 00000194 AA <1> stosb ; logical heads (limits 256) 398 00000195 B0A0 <1> mov al, 0A0h ; Indicates translated table 399 00000197 AA <1> stosb 400 00000198 8A440C <1> mov al, [si+12] 401 0000019B AA <1> stosb ; physical sectors per track 402 0000019C 31C0 <1> xor ax, ax 403 <1> ;dec ax ; 02/01/2015 404 0000019E AB <1> stosw ; precompensation (obsolete) 405 <1> ;xor al, al ; 02/01/2015 406 0000019F AA <1> stosb ; reserved 407 000001A0 B008 <1> mov al, 8 ; drive control byte 408 <1> ; (do not disable retries, 409 <1> ; more than 8 heads) 410 000001A2 AA <1> stosb 411 000001A3 8B4404 <1> mov ax, [si+4] 412 000001A6 AB <1> stosw ; physical number of cylinders 413 <1> ;push ax ; 02/01/2015 414 000001A7 8A4408 <1> mov al, [si+8] 415 000001AA AA <1> stosb ; physical num. of heads (limit 16) 416 000001AB 29C0 <1> sub ax, ax 417 <1> ;pop ax ; 02/01/2015 418 000001AD AB <1> stosw ; landing zone (obsolete) 419 000001AE 88C8 <1> mov al, cl ; logical sectors per track (limit 63) 420 000001B0 243F <1> and al, 3Fh 421 000001B2 AA <1> stosb 422 <1> ;sub al, al ; checksum 423 <1> ;stosb 424 <1> ; 425 000001B3 83C61A <1> add si, 26 ; (BIOS) DPTE address pointer 426 000001B6 AD <1> lodsw 427 000001B7 50 <1> push ax ; (BIOS) DPTE offset 428 000001B8 AD <1> lodsw 429 000001B9 50 <1> push ax ; (BIOS) DPTE segment 430 <1> ; 431 <1> ; checksum calculation 432 000001BA 89FE <1> mov si, di 433 000001BC 06 <1> push es 434 000001BD 1F <1> pop ds 435 <1> ;mov cx, 16 436 000001BE B90F00 <1> mov cx, 15 437 000001C1 29CE <1> sub si, cx 438 000001C3 30E4 <1> xor ah, ah 439 <1> ;del cl 440 <1> L11: 441 000001C5 AC <1> lodsb 442 000001C6 00C4 <1> add ah, al 443 000001C8 E2FB <1> loop L11 444 <1> ; 445 000001CA 88E0 <1> mov al, ah 446 000001CC F6D8 <1> neg al ; -x+x = 0 447 000001CE AA <1> stosb ; put checksum in byte 15 of the tbl 448 <1> ; 449 000001CF 1F <1> pop ds ; (BIOS) DPTE segment 450 000001D0 5E <1> pop si ; (BIOS) DPTE offset 451 <1> ; 452 <1> ; 23/02/2015 453 000001D1 57 <1> push di 454 <1> ; ES:DI points to DPTE (FDPTE) location 455 <1> ;mov cx, 8 456 000001D2 B108 <1> mov cl, 8 457 000001D4 F3A5 <1> rep movsw 458 <1> ; 459 <1> ; 23/02/2015 460 <1> ; (P)ATA drive and LBA validation 461 <1> ; (invalidating SATA drives and setting 462 <1> ; CHS type I/O for old type fixed disks) 463 000001D6 5B <1> pop bx 464 000001D7 8CC8 <1> mov ax, cs 465 000001D9 8ED8 <1> mov ds, ax 466 000001DB 268B07 <1> mov ax, [es:bx] 467 000001DE 3DF001 <1> cmp ax, 1F0h 468 000001E1 7418 <1> je short L11a 469 000001E3 3D7001 <1> cmp ax, 170h 470 000001E6 7413 <1> je short L11a 471 <1> ; invalidation 472 <1> ; (because base port address is not 1F0h or 170h) 473 000001E8 30FF <1> xor bh, bh 474 000001EA 88D3 <1> mov bl, dl 475 000001EC 80EB80 <1> sub bl, 80h 476 000001EF C687[206B]00 <1> mov byte [bx+hd0_type], 0 ; not a valid disk drive ! 477 000001F4 808F[6C6B]F0 <1> or byte [bx+drv.status+2], 0F0h ; (failure sign) 478 000001F9 EB14 <1> jmp short L11b 479 <1> L11a: 480 <1> ; LBA validation 481 000001FB 268A4704 <1> mov al, [es:bx+4] ; Head register upper nibble 482 000001FF A840 <1> test al, 40h ; LBA bit (bit 6) 483 00000201 750C <1> jnz short L11b ; LBA type I/O is OK! (E0h or F0h) 484 <1> ; force CHS type I/O for this drive (A0h or B0h) 485 00000203 28FF <1> sub bh, bh 486 00000205 88D3 <1> mov bl, dl 487 00000207 80EB80 <1> sub bl, 80h ; 26/02/2015 488 0000020A 80A7[6C6B]FE <1> and byte [bx+drv.status+2], 0FEh ; clear bit 0 489 <1> ; bit 0 = LBA ready bit 490 <1> ; 'diskio' procedure will check this bit ! 491 <1> L11b: 492 0000020F 3A16[1C6B] <1> cmp dl, [last_drv] ; 25/12/2014 493 00000213 7307 <1> jnb short L13 494 00000215 E900FF <1> jmp L10 495 <1> L12: 496 <1> ; Restore data registers 497 00000218 8CC8 <1> mov ax, cs 498 0000021A 8ED8 <1> mov ds, ax 499 <1> L13: 500 <1> ; 13/12/2014 501 0000021C 0E <1> push cs 502 0000021D 07 <1> pop es 503 <1> L14: 504 0000021E B411 <1> mov ah, 11h 505 00000220 CD16 <1> int 16h 506 00000222 7406 <1> jz short L15 ; no keys in keyboard buffer 507 00000224 B010 <1> mov al, 10h 508 00000226 CD16 <1> int 16h 509 00000228 EBF4 <1> jmp short L14 510 <1> L15: 511 <1> ; ////// 512 <1> ; 24/11/2014 513 <1> ; 19/11/2014 514 <1> ; 14/11/2014 515 <1> ; Temporary code for disk searching code check 516 <1> ; 517 <1> ; This code will show existing (usable) drives and also 518 <1> ; will show EDD interface support status for hard disks 519 <1> ; (If status bit 7 is 1, Identify Device info is ready, 520 <1> ; no need to get it again in protected mode...) 521 <1> ; 522 <1> ; 13/11/2014 523 0000022A BB0700 <1> mov bx, 7 524 0000022D B40E <1> mov ah, 0Eh 525 0000022F A0[1E6B] <1> mov al, [fd0_type] 526 00000232 20C0 <1> and al, al 527 00000234 743D <1> jz short L15a 528 00000236 88C2 <1> mov dl, al 529 00000238 B046 <1> mov al, 'F' 530 0000023A CD10 <1> int 10h 531 0000023C B044 <1> mov al, 'D' 532 0000023E CD10 <1> int 10h 533 00000240 B030 <1> mov al, '0' 534 00000242 CD10 <1> int 10h 535 00000244 B020 <1> mov al, ' ' 536 00000246 CD10 <1> int 10h 537 00000248 E8B200 <1> call L15c 538 0000024B B020 <1> mov al, ' ' 539 0000024D CD10 <1> int 10h 540 <1> ; 541 0000024F A0[1F6B] <1> mov al, [fd1_type] 542 00000252 20C0 <1> and al, al 543 00000254 741D <1> jz short L15a 544 00000256 88C2 <1> mov dl, al 545 00000258 B046 <1> mov al, 'F' 546 0000025A CD10 <1> int 10h 547 0000025C B044 <1> mov al, 'D' 548 0000025E CD10 <1> int 10h 549 00000260 B031 <1> mov al, '1' 550 00000262 CD10 <1> int 10h 551 00000264 B020 <1> mov al, ' ' 552 00000266 CD10 <1> int 10h 553 00000268 E89200 <1> call L15c 554 0000026B B020 <1> mov al, ' ' 555 0000026D CD10 <1> int 10h 556 0000026F B020 <1> mov al, ' ' 557 00000271 CD10 <1> int 10h 558 <1> L15a: 559 00000273 A0[206B] <1> mov al, [hd0_type] 560 00000276 20C0 <1> and al, al 561 00000278 7479 <1> jz short L15b 562 0000027A 88C2 <1> mov dl, al 563 0000027C B048 <1> mov al, 'H' 564 0000027E CD10 <1> int 10h 565 00000280 B044 <1> mov al, 'D' 566 00000282 CD10 <1> int 10h 567 00000284 B030 <1> mov al, '0' 568 00000286 CD10 <1> int 10h 569 00000288 B020 <1> mov al, ' ' 570 0000028A CD10 <1> int 10h 571 0000028C E86E00 <1> call L15c 572 0000028F B020 <1> mov al, ' ' 573 00000291 CD10 <1> int 10h 574 <1> ; 575 00000293 A0[216B] <1> mov al, [hd1_type] 576 00000296 20C0 <1> and al, al 577 00000298 7459 <1> jz short L15b 578 0000029A 88C2 <1> mov dl, al 579 0000029C B048 <1> mov al, 'H' 580 0000029E CD10 <1> int 10h 581 000002A0 B044 <1> mov al, 'D' 582 000002A2 CD10 <1> int 10h 583 000002A4 B031 <1> mov al, '1' 584 000002A6 CD10 <1> int 10h 585 000002A8 B020 <1> mov al, ' ' 586 000002AA CD10 <1> int 10h 587 000002AC E84E00 <1> call L15c 588 000002AF B020 <1> mov al, ' ' 589 000002B1 CD10 <1> int 10h 590 <1> ; 591 000002B3 A0[226B] <1> mov al, [hd2_type] 592 000002B6 20C0 <1> and al, al 593 000002B8 7439 <1> jz short L15b 594 000002BA 88C2 <1> mov dl, al 595 000002BC B048 <1> mov al, 'H' 596 000002BE CD10 <1> int 10h 597 000002C0 B044 <1> mov al, 'D' 598 000002C2 CD10 <1> int 10h 599 000002C4 B032 <1> mov al, '2' 600 000002C6 CD10 <1> int 10h 601 000002C8 B020 <1> mov al, ' ' 602 000002CA CD10 <1> int 10h 603 000002CC E82E00 <1> call L15c 604 000002CF B020 <1> mov al, ' ' 605 000002D1 CD10 <1> int 10h 606 <1> ; 607 000002D3 A0[236B] <1> mov al, [hd3_type] 608 000002D6 20C0 <1> and al, al 609 000002D8 7419 <1> jz short L15b 610 000002DA 88C2 <1> mov dl, al 611 000002DC B048 <1> mov al, 'H' 612 000002DE CD10 <1> int 10h 613 000002E0 B044 <1> mov al, 'D' 614 000002E2 CD10 <1> int 10h 615 000002E4 B033 <1> mov al, '3' 616 000002E6 CD10 <1> int 10h 617 000002E8 B020 <1> mov al, ' ' 618 000002EA CD10 <1> int 10h 619 000002EC E80E00 <1> call L15c 620 000002EF B020 <1> mov al, ' ' 621 000002F1 CD10 <1> int 10h 622 <1> ; 623 <1> L15b: 624 000002F3 B00D <1> mov al, 0Dh 625 000002F5 CD10 <1> int 10h 626 000002F7 B00A <1> mov al, 0Ah 627 000002F9 CD10 <1> int 10h 628 <1> ;;xor ah, ah 629 <1> ;;int 16h 630 <1> ; 631 000002FB EB77 <1> jmp L16 ; jmp short L16 632 <1> ; 633 <1> L15c: 634 000002FD 88D6 <1> mov dh, dl 635 000002FF C0EE04 <1> shr dh, 4 636 00000302 80C630 <1> add dh, 30h 637 00000305 80E20F <1> and dl, 15 638 00000308 80C230 <1> add dl, 30h 639 0000030B 88F0 <1> mov al, dh 640 0000030D CD10 <1> int 10h 641 0000030F 88D0 <1> mov al, dl 642 00000311 CD10 <1> int 10h 643 00000313 C3 <1> retn 644 <1> ; 645 <1> ; end of temporary code for disk searching code check 646 <1> 647 <1> ; ////// 648 <1> 649 <1> set_disk_parms: 650 <1> ; 04/02/2016 (ebx -> bx) 651 <1> ; 10/07/2015 652 <1> ; 14/01/2015 653 <1> ;push bx 654 00000314 28FF <1> sub bh, bh 655 00000316 8A1E[1B6B] <1> mov bl, [drv] 656 0000031A 80FB80 <1> cmp bl, 80h 657 0000031D 7203 <1> jb short sdp0 658 0000031F 80EB7E <1> sub bl, 7Eh 659 <1> sdp0: 660 00000322 81C3[6A6B] <1> add bx, drv.status 661 00000326 C60780 <1> mov byte [bx], 80h ; 'Present' flag 662 <1> ; 663 00000329 88E8 <1> mov al, ch ; last cylinder (bits 0-7) 664 0000032B 88CC <1> mov ah, cl ; 665 0000032D C0EC06 <1> shr ah, 6 ; last cylinder (bits 8-9) 666 00000330 81EB[6A6B] <1> sub bx, drv.status 667 00000334 D0E3 <1> shl bl, 1 668 00000336 81C3[246B] <1> add bx, drv.cylinders 669 0000033A 40 <1> inc ax ; convert max. cyl number to cyl count 670 0000033B 8907 <1> mov [bx], ax 671 0000033D 50 <1> push ax ; ** cylinders 672 0000033E 81EB[246B] <1> sub bx, drv.cylinders 673 00000342 81C3[326B] <1> add bx, drv.heads 674 00000346 30E4 <1> xor ah, ah 675 00000348 88F0 <1> mov al, dh ; heads 676 0000034A 40 <1> inc ax 677 0000034B 8907 <1> mov [bx], ax 678 0000034D 81EB[326B] <1> sub bx, drv.heads 679 00000351 81C3[406B] <1> add bx, drv.spt 680 00000355 30ED <1> xor ch, ch 681 00000357 80E13F <1> and cl, 3Fh ; sectors (bits 0-6) 682 0000035A 890F <1> mov [bx], cx 683 0000035C 81EB[406B] <1> sub bx, drv.spt 684 00000360 D1E3 <1> shl bx, 1 685 00000362 81C3[4E6B] <1> add bx, drv.size ; disk size (in sectors) 686 <1> ; LBA size = cylinders * heads * secpertrack 687 00000366 F7E1 <1> mul cx 688 00000368 89C2 <1> mov dx, ax ; heads*spt 689 0000036A 58 <1> pop ax ; ** cylinders 690 0000036B 48 <1> dec ax ; 1 cylinder reserved (!?) 691 0000036C F7E2 <1> mul dx ; cylinders * (heads*spt) 692 0000036E 8907 <1> mov [bx], ax 693 00000370 895702 <1> mov [bx+2], dx 694 <1> ; 695 <1> ;pop bx 696 00000373 C3 <1> retn 697 <1> 698 <1> ;align 2 699 <1> 700 <1> ;cylinders : dw 0, 0, 0, 0, 0, 0 701 <1> ;heads : dw 0, 0, 0, 0, 0, 0 702 <1> ;spt : dw 0, 0, 0, 0, 0, 0 703 <1> ;disk_size : dd 0, 0, 0, 0, 0, 0 704 <1> 705 <1> ;last_drv: 706 <1> ; db 0 707 <1> ;drv_status: 708 <1> ; db 0,0,0,0,0,0 709 <1> ; db 0 710 <1> 711 <1> 712 <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015 713 <1> 714 <1> L16: 715 716 ; 10/11/2014 717 00000374 FA cli ; Disable interrupts (clear interrupt flag) 718 ; Reset Interrupt MASK Registers (Master&Slave) 719 ;mov al, 0FFh ; mask off all interrupts 720 ;out 21h, al ; on master PIC (8259) 721 ;jmp $+2 ; (delay) 722 ;out 0A1h, al ; on slave PIC (8259) 723 ; 724 ; Disable NMI 725 00000375 B080 mov al, 80h 726 00000377 E670 out 70h, al ; set bit 7 to 1 for disabling NMI 727 ;23/02/2015 728 00000379 90 nop ; 729 ;in al, 71h ; read in 71h just after writing out to 70h 730 ; for preventing unknown state (!?) 731 ; 732 ; 20/08/2014 733 ; Moving the kernel 64 KB back (to physical address 0) 734 ; DS = CS = 1000h 735 ; 05/11/2014 736 0000037A 31C0 xor ax, ax 737 0000037C 8EC0 mov es, ax ; ES = 0 738 ; 739 0000037E B90040 mov cx, (KEND - KLOAD)/4 740 00000381 31F6 xor si, si 741 00000383 31FF xor di, di 742 00000385 F366A5 rep movsd 743 ; 744 00000388 06 push es ; 0 745 00000389 68[8D03] push L17 746 0000038C CB retf 747 ; 748 L17: 749 ; Turn off the floppy drive motor 750 0000038D BAF203 mov dx, 3F2h 751 00000390 EE out dx, al ; 0 ; 31/12/2013 752 753 ; Enable access to memory above one megabyte 754 L18: 755 00000391 E464 in al, 64h 756 00000393 A802 test al, 2 757 00000395 75FA jnz short L18 758 00000397 B0D1 mov al, 0D1h ; Write output port 759 00000399 E664 out 64h, al 760 L19: 761 0000039B E464 in al, 64h 762 0000039D A802 test al, 2 763 0000039F 75FA jnz short L19 764 000003A1 B0DF mov al, 0DFh ; Enable A20 line 765 000003A3 E660 out 60h, al 766 ;L20: 767 ; 768 ; Load global descriptor table register 769 770 ;mov ax, cs 771 ;mov ds, ax 772 773 000003A5 2E0F0116[4068] lgdt [cs:gdtd] 774 775 000003AB 0F20C0 mov eax, cr0 776 ; or eax, 1 777 000003AE 40 inc ax 778 000003AF 0F22C0 mov cr0, eax 779 780 ; Jump to 32 bit code 781 782 000003B2 66 db 66h ; Prefix for 32-bit 783 000003B3 EA db 0EAh ; Opcode for far jump 784 000003B4 [BA030000] dd StartPM ; Offset to start, 32-bit 785 ; (1000h:StartPM = StartPM + 10000h) 786 000003B8 0800 dw KCODE ; This is the selector for CODE32_DESCRIPTOR, 787 ; assuming that StartPM resides in code32 788 789 [BITS 32] 790 791 StartPM: 792 ; Kernel Base Address = 0 ; 30/12/2013 793 000003BA 66B81000 mov ax, KDATA ; Save data segment identifier 794 000003BE 8ED8 mov ds, ax ; Move a valid data segment into DS register 795 000003C0 8EC0 mov es, ax ; Move data segment into ES register 796 000003C2 8EE0 mov fs, ax ; Move data segment into FS register 797 000003C4 8EE8 mov gs, ax ; Move data segment into GS register 798 000003C6 8ED0 mov ss, ax ; Move data segment into SS register 799 000003C8 BC00000900 mov esp, 90000h ; Move the stack pointer to 090000h 800 801 clear_bss: ; Clear uninitialized data area 802 ; 11/03/2015 803 000003CD 31C0 xor eax, eax ; 0 804 000003CF B9CD050000 mov ecx, (bss_end - bss_start)/4 805 ;shr ecx, 2 ; bss section is already aligned for double words 806 000003D4 BF[006E0000] mov edi, bss_start 807 000003D9 F3AB rep stosd 808 809 memory_init: 810 ; Initialize memory allocation table and page tables 811 ; 16/11/2014 812 ; 15/11/2014 813 ; 07/11/2014 814 ; 06/11/2014 815 ; 05/11/2014 816 ; 04/11/2014 817 ; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 818 ; 819 ; xor eax, eax 820 ; xor ecx, ecx 821 000003DB B108 mov cl, 8 822 000003DD BF00001000 mov edi, MEM_ALLOC_TBL 823 000003E2 F3AB rep stosd ; clear Memory Allocation Table 824 ; for the first 1 MB memory 825 ; 826 000003E4 668B0D[F06D0000] mov cx, [mem_1m_1k] ; Number of contiguous KB between 827 ; 1 and 16 MB, max. 3C00h = 15 MB. 828 000003EB 66C1E902 shr cx, 2 ; convert 1 KB count to 4 KB count 829 000003EF 890D[70700000] mov [free_pages], ecx 830 000003F5 668B15[F26D0000] mov dx, [mem_16m_64k] ; Number of contiguous 64 KB blocks 831 ; between 16 MB and 4 GB. 832 000003FC 6609D2 or dx, dx 833 000003FF 7413 jz short mi_0 834 ; 835 00000401 6689D0 mov ax, dx 836 00000404 C1E004 shl eax, 4 ; 64 KB -> 4 KB (page count) 837 00000407 0105[70700000] add [free_pages], eax 838 0000040D 0500100000 add eax, 4096 ; 16 MB = 4096 pages 839 00000412 EB07 jmp short mi_1 840 mi_0: 841 00000414 6689C8 mov ax, cx 842 00000417 66050001 add ax, 256 ; add 256 pages for the first 1 MB 843 mi_1: 844 0000041B A3[6C700000] mov [memory_size], eax ; Total available memory in pages 845 ; 1 alloc. tbl. bit = 1 memory page 846 ; 32 allocation bits = 32 mem. pages 847 ; 848 00000420 05FF7F0000 add eax, 32767 ; 32768 memory pages per 1 M.A.T. page 849 00000425 C1E80F shr eax, 15 ; ((32768 * x) + y) pages (y < 32768) 850 ; --> x + 1 M.A.T. pages, if y > 0 851 ; --> x M.A.T. pages, if y = 0 852 00000428 66A3[80700000] mov [mat_size], ax ; Memory Alloc. Table Size in pages 853 0000042E C1E00C shl eax, 12 ; 1 M.A.T. page = 4096 bytes 854 ; ; Max. 32 M.A.T. pages (4 GB memory) 855 00000431 89C3 mov ebx, eax ; M.A.T. size in bytes 856 ; Set/Calculate Kernel's Page Directory Address 857 00000433 81C300001000 add ebx, MEM_ALLOC_TBL 858 00000439 891D[68700000] mov [k_page_dir], ebx ; Kernel's Page Directory address 859 ; just after the last M.A.T. page 860 ; 861 0000043F 83E804 sub eax, 4 ; convert M.A.T. size to offset value 862 00000442 A3[78700000] mov [last_page], eax ; last page ofset in the M.A.T. 863 ; ; (allocation status search must be 864 ; stopped after here) 865 00000447 31C0 xor eax, eax 866 00000449 48 dec eax ; FFFFFFFFh (set all bits to 1) 867 0000044A 6651 push cx 868 0000044C C1E905 shr ecx, 5 ; convert 1 - 16 MB page count to 869 ; count of 32 allocation bits 870 0000044F F3AB rep stosd 871 00000451 6659 pop cx 872 00000453 40 inc eax ; 0 873 00000454 80E11F and cl, 31 ; remain bits 874 00000457 7412 jz short mi_4 875 00000459 8907 mov [edi], eax ; reset 876 mi_2: 877 0000045B 0FAB07 bts [edi], eax ; 06/11/2014 878 0000045E FEC9 dec cl 879 00000460 7404 jz short mi_3 880 00000462 FEC0 inc al 881 00000464 EBF5 jmp short mi_2 882 mi_3: 883 00000466 28C0 sub al, al ; 0 884 00000468 83C704 add edi, 4 ; 15/11/2014 885 mi_4: 886 0000046B 6609D2 or dx, dx ; check 16M to 4G memory space 887 0000046E 7421 jz short mi_6 ; max. 16 MB memory, no more... 888 ; 889 00000470 B900021000 mov ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory 890 ; 891 00000475 29F9 sub ecx, edi ; displacement (to end of 16 MB) 892 00000477 7406 jz short mi_5 ; jump if EDI points to 893 ; end of first 16 MB 894 00000479 D1E9 shr ecx, 1 ; convert to dword count 895 0000047B D1E9 shr ecx, 1 ; (shift 2 bits right) 896 0000047D F3AB rep stosd ; reset all bits for reserved pages 897 ; (memory hole under 16 MB) 898 mi_5: 899 0000047F 6689D1 mov cx, dx ; count of 64 KB memory blocks 900 00000482 D1E9 shr ecx, 1 ; 1 alloc. dword per 128 KB memory 901 00000484 9C pushf ; 16/11/2014 902 00000485 48 dec eax ; FFFFFFFFh (set all bits to 1) 903 00000486 F3AB rep stosd 904 00000488 40 inc eax ; 0 905 00000489 9D popf ; 16/11/2014 906 0000048A 7305 jnc short mi_6 907 0000048C 6648 dec ax ; eax = 0000FFFFh 908 0000048E AB stosd 909 0000048F 6640 inc ax ; 0 910 mi_6: 911 00000491 39DF cmp edi, ebx ; check if EDI points to 912 00000493 730A jnb short mi_7 ; end of memory allocation table 913 ; ; (>= MEM_ALLOC_TBL + 4906) 914 00000495 89D9 mov ecx, ebx ; end of memory allocation table 915 00000497 29F9 sub ecx, edi ; convert displacement/offset 916 00000499 D1E9 shr ecx, 1 ; to dword count 917 0000049B D1E9 shr ecx, 1 ; (shift 2 bits right) 918 0000049D F3AB rep stosd ; reset all remain M.A.T. bits 919 mi_7: 920 ; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages) 921 0000049F BA00001000 mov edx, MEM_ALLOC_TBL 922 ;sub ebx, edx ; Mem. Alloc. Tbl. size in bytes 923 ;shr ebx, 12 ; Mem. Alloc. Tbl. size in pages 924 000004A4 668B0D[80700000] mov cx, [mat_size] ; Mem. Alloc. Tbl. size in pages 925 000004AB 89D7 mov edi, edx 926 000004AD C1EF0F shr edi, 15 ; convert M.A.T. address to 927 ; byte offset in M.A.T. 928 ; (1 M.A.T. byte points to 929 ; 32768 bytes) 930 ; Note: MEM_ALLOC_TBL address 931 ; must be aligned on 128 KB 932 ; boundary! 933 000004B0 01D7 add edi, edx ; points to M.A.T.'s itself 934 ; eax = 0 935 000004B2 290D[70700000] sub [free_pages], ecx ; 07/11/2014 936 mi_8: 937 000004B8 0FB307 btr [edi], eax ; clear bit 0 to bit x (1 to 31) 938 ;dec bl 939 000004BB FEC9 dec cl 940 000004BD 7404 jz short mi_9 941 000004BF FEC0 inc al 942 000004C1 EBF5 jmp short mi_8 943 mi_9: 944 ; 945 ; Reset Kernel's Page Dir. and Page Table bits in M.A.T. 946 ; (allocate pages for system page tables) 947 948 ; edx = MEM_ALLOC_TBL 949 000004C3 8B0D[6C700000] mov ecx, [memory_size] ; memory size in pages (PTEs) 950 000004C9 81C1FF030000 add ecx, 1023 ; round up (1024 PTEs per table) 951 000004CF C1E90A shr ecx, 10 ; convert memory page count to 952 ; page table count (PDE count) 953 ; 954 000004D2 51 push ecx ; (**) PDE count (<= 1024) 955 ; 956 000004D3 41 inc ecx ; +1 for kernel page directory 957 ; 958 000004D4 290D[70700000] sub [free_pages], ecx ; 07/11/2014 959 ; 960 000004DA 8B35[68700000] mov esi, [k_page_dir] ; Kernel's Page Directory address 961 000004E0 C1EE0C shr esi, 12 ; convert to page number 962 mi_10: 963 000004E3 89F0 mov eax, esi ; allocation bit offset 964 000004E5 89C3 mov ebx, eax 965 000004E7 C1EB03 shr ebx, 3 ; convert to alloc. byte offset 966 000004EA 80E3FC and bl, 0FCh ; clear bit 0 and bit 1 967 ; to align on dword boundary 968 000004ED 83E01F and eax, 31 ; set allocation bit position 969 ; (bit 0 to bit 31) 970 ; 971 000004F0 01D3 add ebx, edx ; offset in M.A.T. + M.A.T. address 972 ; 973 000004F2 0FB303 btr [ebx], eax ; reset relevant bit (0 to 31) 974 ; 975 000004F5 46 inc esi ; next page table 976 000004F6 E2EB loop mi_10 ; allocate next kernel page table 977 ; (ecx = page table count + 1) 978 ; 979 000004F8 59 pop ecx ; (**) PDE count (= pg. tbl. count) 980 ; 981 ; Initialize Kernel Page Directory and Kernel Page Tables 982 ; 983 ; Initialize Kernel's Page Directory 984 000004F9 8B3D[68700000] mov edi, [k_page_dir] 985 000004FF 89F8 mov eax, edi 986 00000501 0C03 or al, PDE_A_PRESENT + PDE_A_WRITE 987 ; supervisor + read&write + present 988 00000503 89CA mov edx, ecx ; (**) PDE count (= pg. tbl. count) 989 mi_11: 990 00000505 0500100000 add eax, 4096 ; Add page size (PGSZ) 991 ; EAX points to next page table 992 0000050A AB stosd 993 0000050B E2F8 loop mi_11 994 0000050D 29C0 sub eax, eax ; Empty PDE 995 0000050F 66B90004 mov cx, 1024 ; Entry count (PGSZ/4) 996 00000513 29D1 sub ecx, edx 997 00000515 7402 jz short mi_12 998 00000517 F3AB rep stosd ; clear remain (empty) PDEs 999 ; 1000 ; Initialization of Kernel's Page Directory is OK, here. 1001 mi_12: 1002 ; Initialize Kernel's Page Tables 1003 ; 1004 ; (EDI points to address of page table 0) 1005 ; eax = 0 1006 00000519 8B0D[6C700000] mov ecx, [memory_size] ; memory size in pages 1007 0000051F 89CA mov edx, ecx ; (***) 1008 00000521 B003 mov al, PTE_A_PRESENT + PTE_A_WRITE 1009 ; supervisor + read&write + present 1010 mi_13: 1011 00000523 AB stosd 1012 00000524 0500100000 add eax, 4096 1013 00000529 E2F8 loop mi_13 1014 0000052B 6681E2FF03 and dx, 1023 ; (***) 1015 00000530 740B jz short mi_14 1016 00000532 66B90004 mov cx, 1024 1017 00000536 6629D1 sub cx, dx ; from dx (<= 1023) to 1024 1018 00000539 31C0 xor eax, eax 1019 0000053B F3AB rep stosd ; clear remain (empty) PTEs 1020 ; of the last page table 1021 mi_14: 1022 ; Initialization of Kernel's Page Tables is OK, here. 1023 ; 1024 0000053D 89F8 mov eax, edi ; end of the last page table page 1025 ; (beginging of user space pages) 1026 0000053F C1E80F shr eax, 15 ; convert to M.A.T. byte offset 1027 00000542 24FC and al, 0FCh ; clear bit 0 and bit 1 for 1028 ; aligning on dword boundary 1029 1030 00000544 A3[7C700000] mov [first_page], eax 1031 00000549 A3[74700000] mov [next_page], eax ; The first free page pointer 1032 ; for user programs 1033 ; (Offset in Mem. Alloc. Tbl.) 1034 ; 1035 ; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here. 1036 ; 1037 1038 ; Enable paging 1039 ; 1040 0000054E A1[68700000] mov eax, [k_page_dir] 1041 00000553 0F22D8 mov cr3, eax 1042 00000556 0F20C0 mov eax, cr0 1043 00000559 0D00000080 or eax, 80000000h ; set paging bit (bit 31) 1044 0000055E 0F22C0 mov cr0, eax 1045 ;jmp KCODE:StartPMP 1046 1047 00000561 EA db 0EAh ; Opcode for far jump 1048 00000562 [68050000] dd StartPMP ; 32 bit offset 1049 00000566 0800 dw KCODE ; kernel code segment descriptor 1050 1051 1052 StartPMP: 1053 ; 06/11//2014 1054 ; Clear video page 0 1055 ; 1056 ; Temporary Code 1057 ; 1058 00000568 B9E8030000 mov ecx, 80*25/2 1059 0000056D BF00800B00 mov edi, 0B8000h 1060 00000572 31C0 xor eax, eax ; black background, black fore color 1061 00000574 F3AB rep stosd 1062 1063 ; 19/08/2014 1064 ; Kernel Base Address = 0 1065 ; It is mapped to (physically) 0 in the page table. 1066 ; So, here is exactly 'StartPMP' address. 1067 ; 1068 ;;mov ah, 4Eh ; Red background, yellow forecolor 1069 ;;mov esi, msgPM 1070 ;; 14/08/2015 (kernel version message will appear 1071 ;; when protected mode and paging is enabled) 1072 00000576 B40B mov ah, 0Bh ; Black background, light cyan forecolor 1073 00000578 BE[806B0000] mov esi, msgKVER 1074 0000057D BF00800B00 mov edi, 0B8000h ; 27/08/2014 1075 ; 20/08/2014 1076 00000582 E896010000 call printk 1077 1078 ; 'UNIX v7/x86' source code by Robert Nordier (1999) 1079 ; // Set IRQ offsets 1080 ; 1081 ; Linux (v0.12) source code by Linus Torvalds (1991) 1082 ; 1083 ;; ICW1 1084 00000587 B011 mov al, 11h ; Initialization sequence 1085 00000589 E620 out 20h, al ; 8259A-1 1086 ; jmp $+2 1087 0000058B E6A0 out 0A0h, al ; 8259A-2 1088 ;; ICW2 1089 0000058D B020 mov al, 20h ; Start of hardware ints (20h) 1090 0000058F E621 out 21h, al ; for 8259A-1 1091 ; jmp $+2 1092 00000591 B028 mov al, 28h ; Start of hardware ints (28h) 1093 00000593 E6A1 out 0A1h, al ; for 8259A-2 1094 ; 1095 00000595 B004 mov al, 04h ;; ICW3 1096 00000597 E621 out 21h, al ; IRQ2 of 8259A-1 (master) 1097 ; jmp $+2 1098 00000599 B002 mov al, 02h ; is 8259A-2 (slave) 1099 0000059B E6A1 out 0A1h, al ; 1100 ;; ICW4 1101 0000059D B001 mov al, 01h ; 1102 0000059F E621 out 21h, al ; 8086 mode, normal EOI 1103 ; jmp $+2 1104 000005A1 E6A1 out 0A1h, al ; for both chips. 1105 1106 ;mov al, 0FFh ; mask off all interrupts for now 1107 ;out 21h, al 1108 ;; jmp $+2 1109 ;out 0A1h, al 1110 1111 ; 02/04/2015 1112 ; 26/03/2015 System call (INT 30h) modification 1113 ; DPL = 3 (Interrupt service routine can be called from user mode) 1114 ; 1115 ;; Linux (v0.12) source code by Linus Torvalds (1991) 1116 ; setup_idt: 1117 ; 1118 ;; 16/02/2015 1119 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 1120 ; 21/08/2014 (timer_int) 1121 000005A3 BE[4C680000] mov esi, ilist 1122 000005A8 8D3D[006E0000] lea edi, [idt] 1123 ; 26/03/2015 1124 000005AE B930000000 mov ecx, 48 ; 48 hardware interrupts (INT 0 to INT 2Fh) 1125 ; 02/04/2015 1126 000005B3 BB00000800 mov ebx, 80000h 1127 rp_sidt1: 1128 000005B8 AD lodsd 1129 000005B9 89C2 mov edx, eax 1130 000005BB 66BA008E mov dx, 8E00h 1131 000005BF 6689C3 mov bx, ax 1132 000005C2 89D8 mov eax, ebx ; /* selector = 0x0008 = cs */ 1133 ; /* interrupt gate - dpl=0, present */ 1134 000005C4 AB stosd ; selector & offset bits 0-15 1135 000005C5 89D0 mov eax, edx 1136 000005C7 AB stosd ; attributes & offset bits 16-23 1137 000005C8 E2EE loop rp_sidt1 1138 000005CA B110 mov cl, 16 ; 16 software interrupts (INT 30h to INT 3Fh) 1139 rp_sidt2: 1140 000005CC AD lodsd 1141 000005CD 21C0 and eax, eax 1142 000005CF 7413 jz short rp_sidt3 1143 000005D1 89C2 mov edx, eax 1144 000005D3 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 1145 000005D7 6689C3 mov bx, ax 1146 000005DA 89D8 mov eax, ebx ; selector & offset bits 0-15 1147 000005DC AB stosd 1148 000005DD 89D0 mov eax, edx 1149 000005DF AB stosd 1150 000005E0 E2EA loop rp_sidt2 1151 000005E2 EB16 jmp short sidt_OK 1152 rp_sidt3: 1153 000005E4 B8[470A0000] mov eax, ignore_int 1154 000005E9 89C2 mov edx, eax 1155 000005EB 66BA00EE mov dx, 0EE00h ; P=1b/DPL=11b/01110b 1156 000005EF 6689C3 mov bx, ax 1157 000005F2 89D8 mov eax, ebx ; selector & offset bits 0-15 1158 rp_sidt4: 1159 000005F4 AB stosd 1160 000005F5 92 xchg eax, edx 1161 000005F6 AB stosd 1162 000005F7 92 xchg edx, eax 1163 000005F8 E2FA loop rp_sidt4 1164 sidt_OK: 1165 000005FA 0F011D[46680000] lidt [idtd] 1166 ; 1167 ; TSS descriptor setup ; 24/03/2015 1168 00000601 B8[00700000] mov eax, task_state_segment 1169 00000606 66A3[3A680000] mov [gdt_tss0], ax 1170 0000060C C1C010 rol eax, 16 1171 0000060F A2[3C680000] mov [gdt_tss1], al 1172 00000614 8825[3F680000] mov [gdt_tss2], ah 1173 0000061A 66C705[66700000]68- mov word [tss.IOPB], tss_end - task_state_segment 1174 00000622 00 1175 ; 1176 ; IO Map Base address (When this address points 1177 ; to end of the TSS, CPU does not use IO port 1178 ; permission bit map for RING 3 IO permissions, 1179 ; access to any IO ports in ring 3 will be forbidden.) 1180 ; 1181 ;mov [tss.esp0], esp ; TSS offset 4 1182 ;mov word [tss.ss0], KDATA ; TSS offset 8 (SS) 1183 00000623 66B82800 mov ax, TSS ; It is needed when an interrupt 1184 ; occurs (or a system call -software INT- is requested) 1185 ; while cpu running in ring 3 (in user mode). 1186 ; (Kernel stack pointer and segment will be loaded 1187 ; from offset 4 and 8 of the TSS, by the CPU.) 1188 00000627 0F00D8 ltr ax ; Load task register 1189 ; 1190 esp0_set0: 1191 ; 30/07/2015 1192 0000062A 8B0D[6C700000] mov ecx, [memory_size] ; memory size in pages 1193 00000630 C1E10C shl ecx, 12 ; convert page count to byte count 1194 00000633 81F900004000 cmp ecx, CORE ; beginning of user's memory space (400000h) 1195 ; (kernel mode virtual address) 1196 00000639 7605 jna short esp0_set1 1197 ; 1198 ; If available memory > CORE (end of the 1st 4 MB) 1199 ; set stack pointer to CORE 1200 ;(Because, PDE 0 is reserved for kernel space in user's page directory) 1201 ;(PDE 0 points to page table of the 1st 4 MB virtual address space) 1202 0000063B B900004000 mov ecx, CORE 1203 esp0_set1: 1204 00000640 89CC mov esp, ecx ; top of kernel stack (**tss.esp0**) 1205 esp0_set_ok: 1206 ; 30/07/2015 (**tss.esp0**) 1207 00000642 8925[04700000] mov [tss.esp0], esp 1208 00000648 66C705[08700000]10- mov word [tss.ss0], KDATA 1209 00000650 00 1210 ; 14/08/2015 1211 ; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan) 1212 ; 1213 ;cli ; Disable interrupts (for CPU) 1214 ; (CPU will not handle hardware interrupts, except NMI!) 1215 ; 1216 00000651 30C0 xor al, al ; Enable all hardware interrupts! 1217 00000653 E621 out 21h, al ; (IBM PC-AT compatibility) 1218 00000655 EB00 jmp $+2 ; (All conventional PC-AT hardware 1219 00000657 E6A1 out 0A1h, al ; interrupts will be in use.) 1220 ; (Even if related hardware component 1221 ; does not exist!) 1222 ; Enable NMI 1223 00000659 B07F mov al, 7Fh ; Clear bit 7 to enable NMI (again) 1224 0000065B E670 out 70h, al 1225 ; 23/02/2015 1226 0000065D 90 nop 1227 0000065E E471 in al, 71h ; read in 71h just after writing out to 70h 1228 ; for preventing unknown state (!?) 1229 ; 1230 ; Only a NMI can occur here... (Before a 'STI' instruction) 1231 ; 1232 ; 02/09/2014 1233 00000660 6631DB xor bx, bx 1234 00000663 66BA0002 mov dx, 0200h ; Row 2, column 0 ; 07/03/2015 1235 00000667 E8920F0000 call set_cpos 1236 ; 1237 ; 06/11/2014 1238 ; Temporary Code 1239 ; 1240 0000066C E8C2110000 call memory_info 1241 ; 14/08/2015 1242 ;call getch ; 28/02/2015 1243 drv_init: 1244 00000671 FB sti ; Enable Interrupts 1245 ; 06/02/2015 1246 00000672 8B15[206B0000] mov edx, [hd0_type] ; hd0, hd1, hd2, hd3 1247 00000678 668B1D[1E6B0000] mov bx, [fd0_type] ; fd0, fd1 1248 ; 22/02/2015 1249 0000067F 6621DB and bx, bx 1250 00000682 751B jnz short di1 1251 ; 1252 00000684 09D2 or edx, edx 1253 00000686 7529 jnz short di2 1254 ; 1255 setup_error: 1256 00000688 BE[A56C0000] mov esi, setup_error_msg 1257 psem: 1258 0000068D AC lodsb 1259 0000068E 08C0 or al, al 1260 ;jz short haltx ; 22/02/2015 1261 00000690 7426 jz short di3 1262 00000692 56 push esi 1263 00000693 31DB xor ebx, ebx ; 0 1264 ; Video page 0 (bl=0) 1265 00000695 B407 mov ah, 07h ; Black background, 1266 ; light gray forecolor 1267 00000697 E83E0E0000 call write_tty 1268 0000069C 5E pop esi 1269 0000069D EBEE jmp short psem 1270 1271 di1: 1272 ; supress 'jmp short T6' 1273 ; (activate fdc motor control code) 1274 0000069F 66C705[9E070000]90- mov word [T5], 9090h ; nop 1275 000006A7 90 1276 ; 1277 ;mov ax, int_0Eh ; IRQ 6 handler 1278 ;mov di, 0Eh*4 ; IRQ 6 vector 1279 ;stosw 1280 ;mov ax, cs 1281 ;stosw 1282 ;; 16/02/2015 1283 ;;mov dword [DISKETTE_INT], fdc_int ; IRQ 6 handler 1284 ; 1285 000006A8 E8D8200000 CALL DSKETTE_SETUP ; Initialize Floppy Disks 1286 ; 1287 000006AD 09D2 or edx, edx 1288 000006AF 7407 jz short di3 1289 di2: 1290 000006B1 E814210000 call DISK_SETUP ; Initialize Fixed Disks 1291 000006B6 72D0 jc short setup_error 1292 di3: 1293 000006B8 E84A110000 call setup_rtc_int ; 22/05/2015 (dsectrpm.s) 1294 ; 1295 000006BD E8A6600000 call display_disks ; 07/03/2015 (Temporary) 1296 ;haltx: 1297 ; 14/08/2015 1298 ;call getch ; 22/02/2015 1299 000006C2 FB sti ; Enable interrupts (for CPU) 1300 ; 14/08/2015 1301 000006C3 B9FFFFFF0F mov ecx, 0FFFFFFFh 1302 md_info_msg_wait: 1303 000006C8 51 push ecx 1304 000006C9 B001 mov al, 1 1305 000006CB 8A25[96700000] mov ah, [ptty] ; active (current) video page 1306 000006D1 E8CE5D0000 call getc_n 1307 000006D6 59 pop ecx 1308 000006D7 7502 jnz short md_info_msg_ok 1309 000006D9 E2ED loop md_info_msg_wait 1310 md_info_msg_ok: 1311 ; 30/06/2015 1312 000006DB E801310000 call sys_init 1313 ; 1314 ;jmp cpu_reset ; 22/02/2015 1315 hang: 1316 ; 23/02/2015 1317 ;sti ; Enable interrupts 1318 000006E0 F4 hlt 1319 ; 1320 ;nop 1321 ;; 03/12/2014 1322 ;; 28/08/2014 1323 ;mov ah, 11h 1324 ;call getc 1325 ;jz _c8 1326 ; 1327 ; 23/02/2015 1328 ; 06/02/2015 1329 ; 07/09/2014 1330 000006E1 31DB xor ebx, ebx 1331 000006E3 8A1D[96700000] mov bl, [ptty] ; active_page 1332 000006E9 89DE mov esi, ebx 1333 000006EB 66D1E6 shl si, 1 1334 000006EE 81C6[98700000] add esi, ttychr 1335 000006F4 668B06 mov ax, [esi] 1336 000006F7 6621C0 and ax, ax 1337 ;jz short _c8 1338 000006FA 74E4 jz short hang 1339 000006FC 66C7060000 mov word [esi], 0 1340 00000701 80FB03 cmp bl, 3 ; Video page 3 1341 ;jb short _c8 1342 00000704 72DA jb short hang 1343 ; 1344 ; 02/09/2014 1345 00000706 B40E mov ah, 0Eh ; Yellow character 1346 ; on black background 1347 ; 07/09/2014 1348 nxtl: 1349 00000708 6653 push bx 1350 ; 1351 ;xor bx, bx ; bl = 0 (video page 0) 1352 ; bh = 0 (video mode) 1353 ; Retro UNIX 386 v1 - Video Mode 0 1354 ; (PC/AT Video Mode 3 - 80x25 Alpha.) 1355 0000070A 6650 push ax 1356 0000070C E8C90D0000 call write_tty 1357 00000711 6658 pop ax 1358 00000713 665B pop bx ; 07/09/2014 1359 00000715 3C0D cmp al, 0Dh ; carriage return (enter) 1360 ;jne short _c8 1361 00000717 75C7 jne short hang 1362 00000719 B00A mov al, 0Ah ; next line 1363 0000071B EBEB jmp short nxtl 1364 1365 ;_c8: 1366 ; ; 25/08/2014 1367 ; cli ; Disable interrupts 1368 ; mov al, [scounter + 1] 1369 ; and al, al 1370 ; jnz hang 1371 ; call rtc_p 1372 ; jmp hang 1373 1374 1375 ; 27/08/2014 1376 ; 20/08/2014 1377 printk: 1378 ;mov edi, [scr_row] 1379 pkl: 1380 0000071D AC lodsb 1381 0000071E 08C0 or al, al 1382 00000720 7404 jz short pkr 1383 00000722 66AB stosw 1384 00000724 EBF7 jmp short pkl 1385 pkr: 1386 00000726 C3 retn 1387 1388 ; 25/07/2015 1389 ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer) 1390 ; 17/02/2015 1391 ; 06/02/2015 (unix386.s) 1392 ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 1393 ; 1394 ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85) 1395 ; 1396 ;-- HARDWARE INT 08 H - ( IRQ LEVEL 0 ) --------------------------------------- 1397 ; THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF : 1398 ; THE 8254 TIMER. INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR : 1399 ; IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND. : 1400 ; : 1401 ; THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE : 1402 ; POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY. : 1403 ; THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40) : 1404 ; OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE : 1405 ; DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS. : 1406 ; THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH : 1407 ; INTERRUPT 1CH AT EVERY TIME TICK. THE USER MUST CODE A : 1408 ; ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE. : 1409 ;------------------------------------------------------------------------------- 1410 ; 1411 1412 timer_int: ; IRQ 0 1413 ;int_08h: ; Timer 1414 ; 14/10/2015 1415 ; Here, we are simulating system call entry (for task switch) 1416 ; (If multitasking is enabled, 1417 ; 'clock' procedure may jump to 'sysrelease') 1418 00000727 1E push ds 1419 00000728 06 push es 1420 00000729 0FA0 push fs 1421 0000072B 0FA8 push gs 1422 0000072D 60 pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 1423 0000072E 66B91000 mov cx, KDATA 1424 00000732 8ED9 mov ds, cx 1425 00000734 8EC1 mov es, cx 1426 00000736 8EE1 mov fs, cx 1427 00000738 8EE9 mov gs, cx 1428 ; 1429 0000073A 0F20D9 mov ecx, cr3 1430 0000073D 890D[DC070000] mov [cr3reg], ecx ; save current cr3 register value/content 1431 ; 1432 00000743 3B0D[68700000] cmp ecx, [k_page_dir] 1433 00000749 741F je short T3 1434 ; 1435 ; timer interrupt has been occurred while OS is in user mode 1436 0000074B A3[48740000] mov [u.r0], eax 1437 00000750 89E1 mov ecx, esp 1438 00000752 83C130 add ecx, ESPACE ; 4 * 12 (stack frame) 1439 00000755 890D[40740000] mov [u.sp], ecx ; kernel stack pointer at the start of interrupt 1440 0000075B 8925[44740000] mov [u.usp], esp ; kernel stack points to user's registers 1441 ; 1442 00000761 8B0D[68700000] mov ecx, [k_page_dir] 1443 00000767 0F22D9 mov cr3, ecx 1444 T3: 1445 0000076A FB sti ; INTERRUPTS BACK ON 1446 0000076B 66FF05[E4700000] INC word [TIMER_LOW] ; INCREMENT TIME 1447 00000772 7507 JNZ short T4 ; GO TO TEST_DAY 1448 00000774 66FF05[E6700000] INC word [TIMER_HIGH] ; INCREMENT HIGH WORD OF TIME 1449 T4: ; TEST_DAY 1450 0000077B 66833D[E6700000]18 CMP word [TIMER_HIGH],018H ; TEST FOR COUNT EQUALING 24 HOURS 1451 00000783 7519 JNZ short T5 ; GO TO DISKETTE_CTL 1452 00000785 66813D[E4700000]B0- CMP word [TIMER_LOW],0B0H 1453 0000078D 00 1454 0000078E 750E JNZ short T5 ; GO TO DISKETTE_CTL 1455 1456 ;----- TIMER HAS GONE 24 HOURS 1457 ;;SUB AX,AX 1458 ;MOV [TIMER_HIGH],AX 1459 ;MOV [TIMER_LOW],AX 1460 00000790 29C0 sub eax, eax 1461 00000792 A3[E4700000] mov [TIMER_LH], eax 1462 ; 1463 00000797 C605[E8700000]01 MOV byte [TIMER_OFL],1 1464 1465 ;----- TEST FOR DISKETTE TIME OUT 1466 1467 T5: 1468 ; 23/12/2014 1469 0000079E EB1D jmp short T6 ; will be replaced with nop, nop 1470 ; (9090h) if a floppy disk 1471 ; is detected. 1472 ;mov al,[CS:MOTOR_COUNT] 1473 000007A0 A0[EB700000] mov al, [MOTOR_COUNT] 1474 000007A5 FEC8 dec al 1475 ;mov [CS:MOTOR_COUNT], al ; DECREMENT DISKETTE MOTOR CONTROL 1476 000007A7 A2[EB700000] mov [MOTOR_COUNT], al 1477 ;mov [ORG_MOTOR_COUNT], al 1478 000007AC 750F JNZ short T6 ; RETURN IF COUNT NOT OUT 1479 000007AE B0F0 mov al,0F0h 1480 ;AND [CS:MOTOR_STATUS],al ; TURN OFF MOTOR RUNNING BITS 1481 000007B0 2005[EA700000] and [MOTOR_STATUS], al 1482 ;and [ORG_MOTOR_STATUS], al 1483 000007B6 B00C MOV AL,0CH ; bit 3 = enable IRQ & DMA, 1484 ; bit 2 = enable controller 1485 ; 1 = normal operation 1486 ; 0 = reset 1487 ; bit 0, 1 = drive select 1488 ; bit 4-7 = motor running bits 1489 000007B8 66BAF203 MOV DX,03F2H ; FDC CTL PORT 1490 000007BC EE OUT DX,AL ; TURN OFF THE MOTOR 1491 T6: 1492 ;inc word [CS:wait_count] ; 22/12/2014 (byte -> word) 1493 ; TIMER TICK INTERRUPT 1494 ;;inc word [wait_count] ;;27/02/2015 1495 ;INT 1CH ; TRANSFER CONTROL TO A USER ROUTINE 1496 ;;;;cli 1497 ;call u_timer ; TRANSFER CONTROL TO A USER ROUTINE 1498 000007BD FF15[D8070000] call [x_timer] ; 14/05/2015 1499 T7: 1500 ; 14/10/2015 1501 000007C3 B020 MOV AL,EOI ; GET END OF INTERRUPT MASK 1502 000007C5 FA CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 1503 000007C6 E620 OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 1504 ; 1505 000007C8 A1[DC070000] mov eax, [cr3reg] ; previous value/content of cr3 register 1506 000007CD 0F22D8 mov cr3, eax ; restore cr3 register content 1507 ; 1508 000007D0 61 popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 1509 ; 1510 000007D1 0FA9 pop gs 1511 000007D3 0FA1 pop fs 1512 000007D5 07 pop es 1513 000007D6 1F pop ds 1514 000007D7 CF iretd ; return from interrupt 1515 1516 1517 ; //////////////// 1518 1519 ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt) 1520 x_timer: 1521 000007D8 [E0070000] dd u_timer ; 14/05/2015 1522 ;dd clock 1523 1524 ; 14/10/2015 1525 000007DC 00000000 cr3reg: dd 0 1526 1527 ; 06/02/2015 1528 ; 07/09/2014 1529 ; 21/08/2014 1530 u_timer: 1531 ;timer_int: ; IRQ 0 1532 ; 06/02/2015 1533 ;push eax 1534 ;push edx 1535 ;push ecx 1536 ;push ebx 1537 ;push ds 1538 ;push es 1539 ;mov eax, KDATA 1540 ;mov ds, ax 1541 ;mov es, ax 1542 000007E0 FF05[AC700000] inc dword [tcount] 1543 000007E6 BB[F26B0000] mov ebx, tcountstr + 4 1544 000007EB 66A1[AC700000] mov ax, [tcount] 1545 000007F1 B90A000000 mov ecx, 10 1546 rp_divtcnt: 1547 000007F6 31D2 xor edx, edx 1548 000007F8 F7F1 div ecx 1549 000007FA 80C230 add dl, 30h 1550 000007FD 8813 mov [ebx], dl 1551 000007FF 6609C0 or ax, ax 1552 00000802 7403 jz short print_lzero 1553 00000804 4B dec ebx 1554 00000805 EBEF jmp short rp_divtcnt 1555 print_lzero: 1556 00000807 81FB[EE6B0000] cmp ebx, tcountstr 1557 0000080D 7606 jna short print_tcount 1558 0000080F 4B dec ebx 1559 00000810 C60330 mov byte [ebx], 30h 1560 00000813 EBF2 jmp short print_lzero 1561 print_tcount: 1562 00000815 56 push esi 1563 00000816 57 push edi 1564 00000817 BE[CA6B0000] mov esi, timer_msg ; Timer interrupt message 1565 ; 07/09/2014 1566 0000081C 66BB0100 mov bx, 1 ; Video page 1 1567 ptmsg: 1568 00000820 AC lodsb 1569 00000821 08C0 or al, al 1570 00000823 740F jz short ptmsg_ok 1571 00000825 56 push esi 1572 00000826 6653 push bx 1573 00000828 B42F mov ah, 2Fh ; Green background, white forecolor 1574 0000082A E8AB0C0000 call write_tty 1575 0000082F 665B pop bx 1576 00000831 5E pop esi 1577 00000832 EBEC jmp short ptmsg 1578 ;; 27/08/2014 1579 ;mov edi, 0B8000h + 0A0h ; Row 1 1580 ;call printk 1581 ; 1582 ptmsg_ok: 1583 ; 07/09/2014 1584 00000834 6631D2 xor dx, dx ; column 0, row 0 1585 00000837 E8C20D0000 call set_cpos ; set cursor position to 0,0 1586 ; 23/02/2015 1587 ; 25/08/2014 1588 ;mov ebx, scounter ; (seconds counter) 1589 ;dec byte [ebx+1] ; (for reading real time clock) 1590 ; dec byte [scounter+1] 1591 ;; jns short timer_eoi ; 0 -> 0FFh ? 1592 ; jns short u_timer_retn 1593 ; 26/02/2015 1594 ; call rtc_p 1595 ; mov ebx, scounter ; (seconds counter) 1596 ; mov byte [ebx+1], 18 ; (18.2 timer ticks per second) 1597 ; dec byte [ebx] ; 19+18+18+18+18 (5) 1598 ; jnz short timer_eoi ; (109 timer ticks in 5 seconds) 1599 ; jnz short u_timer_retn ; 06/02/2015 1600 ; mov byte [ebx], 5 1601 ; inc byte [ebx+1] ; 19 1602 ;;timer_eoi: 1603 ;; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1604 ;; out 20h, al ; 8259 PORT 1605 ; 1606 ;u_timer_retn: ; 06/02/2015 1607 0000083C 5F pop edi 1608 0000083D 5E pop esi 1609 ;pop es 1610 ;pop ds 1611 ;pop ebx 1612 ;pop ecx 1613 ;pop edx 1614 ;pop eax 1615 ;iret 1616 0000083E C3 retn ; 06/02/2015 1617 1618 ; 28/08/2014 1619 irq0: 1620 0000083F 6A00 push dword 0 1621 00000841 EB48 jmp short which_irq 1622 irq1: 1623 00000843 6A01 push dword 1 1624 00000845 EB44 jmp short which_irq 1625 irq2: 1626 00000847 6A02 push dword 2 1627 00000849 EB40 jmp short which_irq 1628 irq3: 1629 ; 20/11/2015 1630 ; 24/10/2015 1631 0000084B 2EFF15[393F0000] call dword [cs:com2_irq3] 1632 00000852 6A03 push dword 3 1633 00000854 EB35 jmp short which_irq 1634 irq4: 1635 ; 20/11/2015 1636 ; 24/10/2015 1637 00000856 2EFF15[353F0000] call dword [cs:com1_irq4] 1638 0000085D 6A04 push dword 4 1639 0000085F EB2A jmp short which_irq 1640 irq5: 1641 00000861 6A05 push dword 5 1642 00000863 EB26 jmp short which_irq 1643 irq6: 1644 00000865 6A06 push dword 6 1645 00000867 EB22 jmp short which_irq 1646 irq7: 1647 00000869 6A07 push dword 7 1648 0000086B EB1E jmp short which_irq 1649 irq8: 1650 0000086D 6A08 push dword 8 1651 0000086F EB1A jmp short which_irq 1652 irq9: 1653 00000871 6A09 push dword 9 1654 00000873 EB16 jmp short which_irq 1655 irq10: 1656 00000875 6A0A push dword 10 1657 00000877 EB12 jmp short which_irq 1658 irq11: 1659 00000879 6A0B push dword 11 1660 0000087B EB0E jmp short which_irq 1661 irq12: 1662 0000087D 6A0C push dword 12 1663 0000087F EB0A jmp short which_irq 1664 irq13: 1665 00000881 6A0D push dword 13 1666 00000883 EB06 jmp short which_irq 1667 irq14: 1668 00000885 6A0E push dword 14 1669 00000887 EB02 jmp short which_irq 1670 irq15: 1671 00000889 6A0F push dword 15 1672 ;jmp short which_irq 1673 1674 ; 19/10/2015 1675 ; 29/08/2014 1676 ; 21/08/2014 1677 which_irq: 1678 0000088B 870424 xchg eax, [esp] ; 28/08/2014 1679 0000088E 53 push ebx 1680 0000088F 56 push esi 1681 00000890 57 push edi 1682 00000891 1E push ds 1683 00000892 06 push es 1684 ; 1685 00000893 88C3 mov bl, al 1686 ; 1687 00000895 B810000000 mov eax, KDATA 1688 0000089A 8ED8 mov ds, ax 1689 0000089C 8EC0 mov es, ax 1690 ; 19/10/2015 1691 0000089E FC cld 1692 ; 27/08/2014 1693 0000089F 8105[786B0000]A000- add dword [scr_row], 0A0h 1694 000008A7 0000 1695 ; 1696 000008A9 B417 mov ah, 17h ; blue (1) background, 1697 ; light gray (7) forecolor 1698 000008AB 8B3D[786B0000] mov edi, [scr_row] 1699 000008B1 B049 mov al, 'I' 1700 000008B3 66AB stosw 1701 000008B5 B052 mov al, 'R' 1702 000008B7 66AB stosw 1703 000008B9 B051 mov al, 'Q' 1704 000008BB 66AB stosw 1705 000008BD B020 mov al, ' ' 1706 000008BF 66AB stosw 1707 000008C1 88D8 mov al, bl 1708 000008C3 3C0A cmp al, 10 1709 000008C5 7208 jb short iix 1710 000008C7 B031 mov al, '1' 1711 000008C9 66AB stosw 1712 000008CB 88D8 mov al, bl 1713 000008CD 2C0A sub al, 10 1714 iix: 1715 000008CF 0430 add al, '0' 1716 000008D1 66AB stosw 1717 000008D3 B020 mov al, ' ' 1718 000008D5 66AB stosw 1719 000008D7 B021 mov al, '!' 1720 000008D9 66AB stosw 1721 000008DB B020 mov al, ' ' 1722 000008DD 66AB stosw 1723 ; 23/02/2015 1724 000008DF 80FB07 cmp bl, 7 ; check for IRQ 8 to IRQ 15 1725 000008E2 0F868D010000 jna iiret 1726 000008E8 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 1727 000008EA E6A0 out 0A0h, al ; the 2nd 8259 1728 000008EC E984010000 jmp iiret 1729 ; 1730 ; 22/08/2014 1731 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1732 ;out 20h, al ; 8259 PORT 1733 ; 1734 ;pop es 1735 ;pop ds 1736 ;pop edi 1737 ;pop esi 1738 ;pop ebx 1739 ;pop eax 1740 ;iret 1741 1742 ; 02/04/2015 1743 ; 25/08/2014 1744 exc0: 1745 000008F1 6A00 push dword 0 1746 000008F3 E990000000 jmp cpu_except 1747 exc1: 1748 000008F8 6A01 push dword 1 1749 000008FA E989000000 jmp cpu_except 1750 exc2: 1751 000008FF 6A02 push dword 2 1752 00000901 E982000000 jmp cpu_except 1753 exc3: 1754 00000906 6A03 push dword 3 1755 00000908 EB7E jmp cpu_except 1756 exc4: 1757 0000090A 6A04 push dword 4 1758 0000090C EB7A jmp cpu_except 1759 exc5: 1760 0000090E 6A05 push dword 5 1761 00000910 EB76 jmp cpu_except 1762 exc6: 1763 00000912 6A06 push dword 6 1764 00000914 EB72 jmp cpu_except 1765 exc7: 1766 00000916 6A07 push dword 7 1767 00000918 EB6E jmp cpu_except 1768 exc8: 1769 ; [esp] = Error code 1770 0000091A 6A08 push dword 8 1771 0000091C EB5C jmp cpu_except_en 1772 exc9: 1773 0000091E 6A09 push dword 9 1774 00000920 EB66 jmp cpu_except 1775 exc10: 1776 ; [esp] = Error code 1777 00000922 6A0A push dword 10 1778 00000924 EB54 jmp cpu_except_en 1779 exc11: 1780 ; [esp] = Error code 1781 00000926 6A0B push dword 11 1782 00000928 EB50 jmp cpu_except_en 1783 exc12: 1784 ; [esp] = Error code 1785 0000092A 6A0C push dword 12 1786 0000092C EB4C jmp cpu_except_en 1787 exc13: 1788 ; [esp] = Error code 1789 0000092E 6A0D push dword 13 1790 00000930 EB48 jmp cpu_except_en 1791 exc14: 1792 ; [esp] = Error code 1793 00000932 6A0E push dword 14 1794 00000934 EB44 jmp short cpu_except_en 1795 exc15: 1796 00000936 6A0F push dword 15 1797 00000938 EB4E jmp cpu_except 1798 exc16: 1799 0000093A 6A10 push dword 16 1800 0000093C EB4A jmp cpu_except 1801 exc17: 1802 ; [esp] = Error code 1803 0000093E 6A11 push dword 17 1804 00000940 EB38 jmp short cpu_except_en 1805 exc18: 1806 00000942 6A12 push dword 18 1807 00000944 EB42 jmp short cpu_except 1808 exc19: 1809 00000946 6A13 push dword 19 1810 00000948 EB3E jmp short cpu_except 1811 exc20: 1812 0000094A 6A14 push dword 20 1813 0000094C EB3A jmp short cpu_except 1814 exc21: 1815 0000094E 6A15 push dword 21 1816 00000950 EB36 jmp short cpu_except 1817 exc22: 1818 00000952 6A16 push dword 22 1819 00000954 EB32 jmp short cpu_except 1820 exc23: 1821 00000956 6A17 push dword 23 1822 00000958 EB2E jmp short cpu_except 1823 exc24: 1824 0000095A 6A18 push dword 24 1825 0000095C EB2A jmp short cpu_except 1826 exc25: 1827 0000095E 6A19 push dword 25 1828 00000960 EB26 jmp short cpu_except 1829 exc26: 1830 00000962 6A1A push dword 26 1831 00000964 EB22 jmp short cpu_except 1832 exc27: 1833 00000966 6A1B push dword 27 1834 00000968 EB1E jmp short cpu_except 1835 exc28: 1836 0000096A 6A1C push dword 28 1837 0000096C EB1A jmp short cpu_except 1838 exc29: 1839 0000096E 6A1D push dword 29 1840 00000970 EB16 jmp short cpu_except 1841 exc30: 1842 00000972 6A1E push dword 30 1843 00000974 EB04 jmp short cpu_except_en 1844 exc31: 1845 00000976 6A1F push dword 31 1846 00000978 EB0E jmp short cpu_except 1847 1848 ; 19/10/2015 1849 ; 19/09/2015 1850 ; 01/09/2015 1851 ; 28/08/2015 1852 ; 28/08/2014 1853 cpu_except_en: 1854 0000097A 87442404 xchg eax, [esp+4] ; Error code 1855 0000097E 36A3[28850000] mov [ss:error_code], eax 1856 00000984 58 pop eax ; Exception number 1857 00000985 870424 xchg eax, [esp] 1858 ; eax = eax before exception 1859 ; [esp] -> exception number 1860 ; [esp+4] -> EIP to return 1861 ; 19/10/2015 1862 ; 19/09/2015 1863 ; 01/09/2015 1864 ; 28/08/2015 1865 ; 29/08/2014 1866 ; 28/08/2014 1867 ; 25/08/2014 1868 ; 21/08/2014 1869 cpu_except: ; CPU Exceptions 1870 00000988 FC cld 1871 00000989 870424 xchg eax, [esp] 1872 ; eax = Exception number 1873 ; [esp] = eax (before exception) 1874 0000098C 53 push ebx 1875 0000098D 56 push esi 1876 0000098E 57 push edi 1877 0000098F 1E push ds 1878 00000990 06 push es 1879 ; 28/08/2015 1880 00000991 66BB1000 mov bx, KDATA 1881 00000995 8EDB mov ds, bx 1882 00000997 8EC3 mov es, bx 1883 00000999 0F20DB mov ebx, cr3 1884 0000099C 53 push ebx ; (*) page directory 1885 ; 19/10/2015 1886 0000099D FC cld 1887 ; 25/03/2015 1888 0000099E 8B1D[68700000] mov ebx, [k_page_dir] 1889 000009A4 0F22DB mov cr3, ebx 1890 ; 28/08/2015 1891 000009A7 83F80E cmp eax, 0Eh ; 14, PAGE FAULT 1892 000009AA 7512 jne short cpu_except_nfp 1893 000009AC E816290000 call page_fault_handler 1894 000009B1 21C0 and eax, eax 1895 000009B3 0F84B8000000 jz iiretp ; 01/09/2015 1896 000009B9 B80E000000 mov eax, 0Eh ; 14 1897 cpu_except_nfp: 1898 ; 02/04/2015 1899 000009BE BB[E0060000] mov ebx, hang 1900 000009C3 875C241C xchg ebx, [esp+28] 1901 ; EIP (points to instruction which faults) 1902 ; New EIP (hang) 1903 000009C7 891D[2C850000] mov [FaultOffset], ebx 1904 000009CD C744242008000000 mov dword [esp+32], KCODE ; kernel's code segment 1905 000009D5 814C242400020000 or dword [esp+36], 200h ; enable interrupts (set IF) 1906 ; 1907 000009DD 88C4 mov ah, al 1908 000009DF 240F and al, 0Fh 1909 000009E1 3C09 cmp al, 9 1910 000009E3 7602 jna short h1ok 1911 000009E5 0407 add al, 'A'-':' 1912 h1ok: 1913 000009E7 D0EC shr ah, 1 1914 000009E9 D0EC shr ah, 1 1915 000009EB D0EC shr ah, 1 1916 000009ED D0EC shr ah, 1 1917 000009EF 80FC09 cmp ah, 9 1918 000009F2 7603 jna short h2ok 1919 000009F4 80C407 add ah, 'A'-':' 1920 h2ok: 1921 000009F7 86E0 xchg ah, al 1922 000009F9 66053030 add ax, '00' 1923 000009FD 66A3[066C0000] mov [excnstr], ax 1924 ; 1925 ; 29/08/2014 1926 00000A03 A1[2C850000] mov eax, [FaultOffset] 1927 00000A08 51 push ecx 1928 00000A09 52 push edx 1929 00000A0A 89E3 mov ebx, esp 1930 ; 28/08/2015 1931 00000A0C B910000000 mov ecx, 16 ; divisor value to convert binary number 1932 ; to hexadecimal string 1933 ;mov ecx, 10 ; divisor to convert 1934 ; binary number to decimal string 1935 b2d1: 1936 00000A11 31D2 xor edx, edx 1937 00000A13 F7F1 div ecx 1938 00000A15 6652 push dx 1939 00000A17 39C8 cmp eax, ecx 1940 00000A19 73F6 jnb short b2d1 1941 00000A1B BF[116C0000] mov edi, EIPstr ; EIP value 1942 ; points to instruction which faults 1943 ; 28/08/2015 1944 00000A20 89C2 mov edx, eax 1945 b2d2: 1946 ;add al, '0' 1947 00000A22 8A82[EF180000] mov al, [edx+hexchrs] 1948 00000A28 AA stosb ; write hexadecimal digit to its place 1949 00000A29 39E3 cmp ebx, esp 1950 00000A2B 7606 jna short b2d3 1951 00000A2D 6658 pop ax 1952 00000A2F 88C2 mov dl, al 1953 00000A31 EBEF jmp short b2d2 1954 b2d3: 1955 00000A33 B068 mov al, 'h' ; 28/08/2015 1956 00000A35 AA stosb 1957 00000A36 B020 mov al, 20h ; space 1958 00000A38 AA stosb 1959 00000A39 30C0 xor al, al ; to do it an ASCIIZ string 1960 00000A3B AA stosb 1961 ; 1962 00000A3C 5A pop edx 1963 00000A3D 59 pop ecx 1964 ; 1965 00000A3E B44F mov ah, 4Fh ; red (4) background, 1966 ; white (F) forecolor 1967 00000A40 BE[F66B0000] mov esi, exc_msg ; message offset 1968 ; 1969 00000A45 EB11 jmp short piemsg 1970 ; 1971 ;add dword [scr_row], 0A0h 1972 ;mov edi, [scr_row] 1973 ; 1974 ;call printk 1975 ; 1976 ;mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 1977 ;out 20h, al ; 8259 PORT 1978 ; 1979 ;pop es 1980 ;pop ds 1981 ;pop edi 1982 ;pop esi 1983 ;pop eax 1984 ;iret 1985 1986 ; 28/08/2015 1987 ; 23/02/2015 1988 ; 20/08/2014 1989 ignore_int: 1990 00000A47 50 push eax 1991 00000A48 53 push ebx ; 23/02/2015 1992 00000A49 56 push esi 1993 00000A4A 57 push edi 1994 00000A4B 1E push ds 1995 00000A4C 06 push es 1996 ; 28/08/2015 1997 00000A4D 0F20D8 mov eax, cr3 1998 00000A50 50 push eax ; (*) page directory 1999 ; 2000 00000A51 B467 mov ah, 67h ; brown (6) background, 2001 ; light gray (7) forecolor 2002 00000A53 BE[B46B0000] mov esi, int_msg ; message offset 2003 piemsg: 2004 ; 27/08/2014 2005 00000A58 8105[786B0000]A000- add dword [scr_row], 0A0h 2006 00000A60 0000 2007 00000A62 8B3D[786B0000] mov edi, [scr_row] 2008 ; 2009 00000A68 E8B0FCFFFF call printk 2010 ; 2011 ; 23/02/2015 2012 00000A6D B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 2013 00000A6F E6A0 out 0A0h, al ; the 2nd 8259 2014 iiretp: ; 01/09/2015 2015 ; 28/08/2015 2016 00000A71 58 pop eax ; (*) page directory 2017 00000A72 0F22D8 mov cr3, eax 2018 ; 2019 iiret: 2020 ; 22/08/2014 2021 00000A75 B020 mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 2022 00000A77 E620 out 20h, al ; 8259 PORT 2023 ; 2024 00000A79 07 pop es 2025 00000A7A 1F pop ds 2026 00000A7B 5F pop edi 2027 00000A7C 5E pop esi 2028 00000A7D 5B pop ebx ; 29/08/2014 2029 00000A7E 58 pop eax 2030 00000A7F CF iretd 2031 2032 ; 26/02/2015 2033 ; 07/09/2014 2034 ; 25/08/2014 2035 rtc_int: ; Real Time Clock Interrupt (IRQ 8) 2036 ; 22/08/2014 2037 00000A80 50 push eax 2038 00000A81 53 push ebx ; 29/08/2014 2039 00000A82 56 push esi 2040 00000A83 57 push edi 2041 00000A84 1E push ds 2042 00000A85 06 push es 2043 ; 2044 00000A86 B810000000 mov eax, KDATA 2045 00000A8B 8ED8 mov ds, ax 2046 00000A8D 8EC0 mov es, ax 2047 ; 2048 ; 25/08/2014 2049 00000A8F E884000000 call rtc_p 2050 ; 2051 ; 22/02/2015 - dsectpm.s 2052 ; [ source: http://wiki.osdev.org/RTC ] 2053 ; read status register C to complete procedure 2054 ;(it is needed to get a next IRQ 8) 2055 00000A94 B00C mov al, 0Ch ; 2056 00000A96 E670 out 70h, al ; select register C 2057 00000A98 90 nop 2058 00000A99 E471 in al, 71h ; just throw away contents 2059 ; 22/02/2015 2060 00000A9B B020 MOV AL,EOI ; END OF INTERRUPT 2061 00000A9D E6A0 OUT INTB00,AL ; FOR CONTROLLER #2 2062 ; 2063 00000A9F EBD4 jmp short iiret 2064 2065 ; 22/08/2014 2066 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm) 2067 ; (INT 1Ah) 2068 ;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991) 2069 time_of_day: 2070 00000AA1 E866010000 call UPD_IPR ; WAIT TILL UPDATE NOT IN PROGRESS 2071 00000AA6 726F jc short rtc_retn 2072 00000AA8 B000 mov al, CMOS_SECONDS 2073 00000AAA E845010000 call CMOS_READ 2074 00000AAF A2[DC700000] mov [time_seconds], al 2075 00000AB4 B002 mov al, CMOS_MINUTES 2076 00000AB6 E839010000 call CMOS_READ 2077 00000ABB A2[DD700000] mov [time_minutes], al 2078 00000AC0 B004 mov al, CMOS_HOURS 2079 00000AC2 E82D010000 call CMOS_READ 2080 00000AC7 A2[DE700000] mov [time_hours], al 2081 00000ACC B006 mov al, CMOS_DAY_WEEK 2082 00000ACE E821010000 call CMOS_READ 2083 00000AD3 A2[DF700000] mov [date_wday], al 2084 00000AD8 B007 mov al, CMOS_DAY_MONTH 2085 00000ADA E815010000 call CMOS_READ 2086 00000ADF A2[E0700000] mov [date_day], al 2087 00000AE4 B008 mov al, CMOS_MONTH 2088 00000AE6 E809010000 call CMOS_READ 2089 00000AEB A2[E1700000] mov [date_month], al 2090 00000AF0 B009 mov al, CMOS_YEAR 2091 00000AF2 E8FD000000 call CMOS_READ 2092 00000AF7 A2[E2700000] mov [date_year], al 2093 00000AFC B032 mov al, CMOS_CENTURY 2094 00000AFE E8F1000000 call CMOS_READ 2095 00000B03 A2[E3700000] mov [date_century], al 2096 ; 2097 00000B08 B000 mov al, CMOS_SECONDS 2098 00000B0A E8E5000000 call CMOS_READ 2099 00000B0F 3A05[DC700000] cmp al, [time_seconds] 2100 00000B15 758A jne short time_of_day 2101 2102 rtc_retn: 2103 00000B17 C3 retn 2104 2105 rtc_p: 2106 ; 07/09/2014 2107 ; 29/08/2014 2108 ; 27/08/2014 2109 ; 25/08/2014 2110 ; Print Real Time Clock content 2111 ; 2112 ; 2113 00000B18 E884FFFFFF call time_of_day 2114 00000B1D 72F8 jc short rtc_retn 2115 ; 2116 00000B1F 3A05[686C0000] cmp al, [ptime_seconds] 2117 00000B25 74F0 je short rtc_retn ; 29/08/2014 2118 ; 2119 00000B27 A2[686C0000] mov [ptime_seconds], al 2120 ; 2121 00000B2C A0[E3700000] mov al, [date_century] 2122 00000B31 E8F1000000 call bcd_to_ascii 2123 00000B36 66A3[356C0000] mov [datestr+6], ax 2124 00000B3C A0[E2700000] mov al, [date_year] 2125 00000B41 E8E1000000 call bcd_to_ascii 2126 00000B46 66A3[376C0000] mov [datestr+8], ax 2127 00000B4C A0[E1700000] mov al, [date_month] 2128 00000B51 E8D1000000 call bcd_to_ascii 2129 00000B56 66A3[326C0000] mov [datestr+3], ax 2130 00000B5C A0[E0700000] mov al, [date_day] 2131 00000B61 E8C1000000 call bcd_to_ascii 2132 00000B66 66A3[2F6C0000] mov [datestr], ax 2133 ; 2134 00000B6C 0FB61D[DF700000] movzx ebx, byte [date_wday] 2135 00000B73 C0E302 shl bl, 2 2136 00000B76 81C3[486C0000] add ebx, daytmp 2137 00000B7C 8B03 mov eax, [ebx] 2138 00000B7E A3[3A6C0000] mov [daystr], eax 2139 ; 2140 00000B83 A0[DE700000] mov al, [time_hours] 2141 00000B88 E89A000000 call bcd_to_ascii 2142 00000B8D 66A3[3E6C0000] mov [timestr], ax 2143 00000B93 A0[DD700000] mov al, [time_minutes] 2144 00000B98 E88A000000 call bcd_to_ascii 2145 00000B9D 66A3[416C0000] mov [timestr+3], ax 2146 00000BA3 A0[DC700000] mov al, [time_seconds] 2147 00000BA8 E87A000000 call bcd_to_ascii 2148 00000BAD 66A3[446C0000] mov [timestr+6], ax 2149 ; 2150 00000BB3 BE[1D6C0000] mov esi, rtc_msg ; message offset 2151 ; 23/02/2015 2152 00000BB8 52 push edx 2153 00000BB9 51 push ecx 2154 ; 07/09/2014 2155 00000BBA 66BB0200 mov bx, 2 ; Video page 2 2156 prtmsg: 2157 00000BBE AC lodsb 2158 00000BBF 08C0 or al, al 2159 00000BC1 740F jz short prtmsg_ok 2160 00000BC3 56 push esi 2161 00000BC4 6653 push bx 2162 00000BC6 B43F mov ah, 3Fh ; cyan (6) background, 2163 ; white (F) forecolor 2164 00000BC8 E80D090000 call write_tty 2165 00000BCD 665B pop bx 2166 00000BCF 5E pop esi 2167 00000BD0 EBEC jmp short prtmsg 2168 ; 2169 ;mov edi, 0B8000h+0A0h+0A0h ; Row 2 2170 ;call printk 2171 prtmsg_ok: 2172 ; 07/09/2014 2173 00000BD2 6631D2 xor dx, dx ; column 0, row 0 2174 00000BD5 E8240A0000 call set_cpos ; set curspor position to 0,0 2175 ; 23/02/2015 2176 00000BDA 59 pop ecx 2177 00000BDB 5A pop edx 2178 00000BDC C3 retn 2179 2180 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 2181 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 2182 default_irq7: 2183 00000BDD 6650 push ax 2184 00000BDF B00B mov al, 0Bh ; In-Service register 2185 00000BE1 E620 out 20h, al 2186 00000BE3 EB00 jmp short $+2 2187 00000BE5 EB00 jmp short $+2 2188 00000BE7 E420 in al, 20h 2189 00000BE9 2480 and al, 80h ; bit 7 (is it real IRQ 7 or fake?) 2190 00000BEB 7404 jz short irq7_iret ; Fake (spurious) IRQ, do not send EOI 2191 00000BED B020 mov al, 20h ; EOI 2192 00000BEF E620 out 20h, al 2193 irq7_iret: 2194 00000BF1 6658 pop ax 2195 00000BF3 CF iretd 2196 2197 ; 22/08/2014 2198 ; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm) 2199 CMOS_READ: 2200 00000BF4 9C pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 2201 00000BF5 D0C0 rol al, 1 ; MOVE NMI BIT TO LOW POSITION 2202 00000BF7 F9 stc ; FORCE NMI BIT ON IN CARRY FLAG 2203 00000BF8 D0D8 rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 2204 00000BFA FA cli ; DISABLE INTERRUPTS 2205 00000BFB E670 out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 2206 00000BFD 90 nop ; I/O DELAY 2207 00000BFE E471 in al, CMOS_DATA ; READ THE REQUESTED CMOS LOCATION 2208 00000C00 6650 push ax ; SAVE (AH) REGISTER VALUE AND CMOS BYTE 2209 ; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 2210 ; ----- 10/06/85 (test4.asm) 2211 00000C02 B01E mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 2212 ;mov al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION 2213 00000C04 D0D8 rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 2214 00000C06 E670 out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 2215 00000C08 6658 pop ax ; RESTORE (AH) AND (AL), CMOS BYTE 2216 00000C0A 9D popf 2217 00000C0B C3 retn ; RETURN WITH FLAGS RESTORED 2218 2219 ; 22/08/2014 2220 ; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm) 2221 UPD_IPR: ; WAIT TILL UPDATE NOT IN PROGRESS 2222 00000C0C 51 push ecx 2223 00000C0D B9FFFF0000 mov ecx, 65535 ; SET TIMEOUT LOOP COUNT (= 800) 2224 ; mov cx, 800 2225 UPD_10: 2226 00000C12 B00A mov al, CMOS_REG_A ; ADDRESS STATUS REGISTER A 2227 00000C14 FA cli ; NO TIMER INTERRUPTS DURING UPDATES 2228 00000C15 E8DAFFFFFF call CMOS_READ ; READ UPDATE IN PROCESS FLAG 2229 00000C1A A880 test al, 80h ; IF UIP BIT IS ON ( CANNOT READ TIME ) 2230 00000C1C 7406 jz short UPD_90 ; EXIT WITH CY= 0 IF CAN READ CLOCK NOW 2231 00000C1E FB sti ; ALLOW INTERRUPTS WHILE WAITING 2232 00000C1F E2F1 loop UPD_10 ; LOOP TILL READY OR TIMEOUT 2233 00000C21 31C0 xor eax, eax ; CLEAR RESULTS IF ERROR 2234 ; xor ax, ax 2235 00000C23 F9 stc ; SET CARRY FOR ERROR 2236 UPD_90: 2237 00000C24 59 pop ecx ; RESTORE CALLERS REGISTER 2238 00000C25 FA cli ; INTERRUPTS OFF DURING SET 2239 00000C26 C3 retn ; RETURN WITH CY FLAG SET 2240 2241 bcd_to_ascii: 2242 ; 25/08/2014 2243 ; INPUT -> 2244 ; al = Packed BCD number 2245 ; OUTPUT -> 2246 ; ax = ASCII word/number 2247 ; 2248 ; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011) 2249 ; 2250 00000C27 D410 db 0D4h,10h ; Undocumented inst. AAM 2251 ; AH = AL / 10h 2252 ; AL = AL MOD 10h 2253 00000C29 660D3030 or ax,'00' ; Make it ASCII based 2254 2255 00000C2D 86E0 xchg ah, al 2256 2257 00000C2F C3 retn 2258 2259 2260 %include 'keyboard.inc' ; 07/03/2015 2261 <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC 2262 <1> ; Last Modification: 17/10/2015 2263 <1> ; (Keyboard Data is in 'KYBDATA.INC') 2264 <1> ; 2265 <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) /////////////// 2266 <1> 2267 <1> ; 30/06/2015 2268 <1> ; 11/03/2015 2269 <1> ; 28/02/2015 2270 <1> ; 25/02/2015 2271 <1> ; 20/02/2015 2272 <1> ; 18/02/2015 2273 <1> ; 03/12/2014 2274 <1> ; 07/09/2014 2275 <1> ; KEYBOARD INTERRUPT HANDLER 2276 <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014) 2277 <1> 2278 <1> ;getch: 2279 <1> ; ; 18/02/2015 2280 <1> ; ; This routine will be replaced with Retro UNIX 386 2281 <1> ; ; version of Retro UNIX 8086 getch (tty input) 2282 <1> ; ; routine, later... (multi tasking ability) 2283 <1> ; ; 28/02/2015 2284 <1> ; sti ; enable interrupts 2285 <1> ; ; 2286 <1> ; ;push esi 2287 <1> ; ;push ebx 2288 <1> ; ;xor ebx, ebx 2289 <1> ; ;mov bl, [ptty] ; active_page 2290 <1> ; ;mov esi, ebx 2291 <1> ; ;shl si, 1 2292 <1> ; ;add esi, ttychr 2293 <1> ;getch_1: 2294 <1> ; ;mov ax, [esi] 2295 <1> ; mov ax, [ttychr] ; video page 0 (tty0) 2296 <1> ; and ax, ax 2297 <1> ; jz short getch_2 2298 <1> ; mov word [ttychr], 0 2299 <1> ; ;mov word [esi], 0 2300 <1> ; ;pop ebx 2301 <1> ; ;pop esi 2302 <1> ; retn 2303 <1> ;getch_2: 2304 <1> ; hlt ; not proper for multi tasking! 2305 <1> ; ; (temporary halt for now) 2306 <1> ; ; 'sleep' on tty 2307 <1> ; ; will (must) be located here 2308 <1> ; nop 2309 <1> ; jmp short getch_1 2310 <1> 2311 <1> keyb_int: 2312 <1> ; 30/06/2015 2313 <1> ; 25/02/2015 2314 <1> ; 20/02/2015 2315 <1> ; 03/12/2014 (getc_int - INT 16h modifications) 2316 <1> ; 07/09/2014 - Retro UNIX 386 v1 2317 <1> ; 30/06/2014 2318 <1> ; 10/05/2013 2319 <1> ; Retro Unix 8086 v1 feature only! 2320 <1> ; 03/03/2014 2321 <1> 2322 00000C30 1E <1> push ds 2323 00000C31 53 <1> push ebx 2324 00000C32 50 <1> push eax 2325 <1> ; 2326 00000C33 66B81000 <1> mov ax, KDATA 2327 00000C37 8ED8 <1> mov ds, ax 2328 <1> ; 2329 00000C39 9C <1> pushfd 2330 00000C3A 0E <1> push cs 2331 00000C3B E823020000 <1> call kb_int ; int_09h 2332 <1> ; 2333 00000C40 B411 <1> mov ah, 11h ; 03/12/2014 2334 <1> ;call getc 2335 00000C42 E856000000 <1> call int_16h ; 30/06/2015 2336 00000C47 7450 <1> jz short keyb_int4 2337 <1> ; 2338 00000C49 B410 <1> mov ah, 10h ; 03/12/2014 2339 <1> ;call getc 2340 00000C4B E84D000000 <1> call int_16h ; 30/06/2015 2341 <1> ; 2342 <1> ; 20/02/2015 2343 00000C50 0FB61D[96700000] <1> movzx ebx, byte [ptty] ; active_page 2344 <1> ; 2345 00000C57 20C0 <1> and al, al 2346 00000C59 751E <1> jnz short keyb_int1 2347 <1> ; 2348 00000C5B 80FC68 <1> cmp ah, 68h ; ALT + F1 key 2349 00000C5E 7219 <1> jb short keyb_int1 2350 00000C60 80FC6F <1> cmp ah, 6Fh ; ALT + F8 key 2351 00000C63 7714 <1> ja short keyb_int1 2352 <1> ; 2353 00000C65 88D8 <1> mov al, bl 2354 00000C67 0468 <1> add al, 68h 2355 00000C69 38E0 <1> cmp al, ah 2356 00000C6B 7409 <1> je short keyb_int0 2357 00000C6D 88E0 <1> mov al, ah 2358 00000C6F 2C68 <1> sub al, 68h 2359 00000C71 E8520B0000 <1> call tty_sw 2360 <1> ;movzx ebx, [ptty] ; active_page 2361 <1> keyb_int0: ; 30/06/2015 2362 00000C76 6631C0 <1> xor ax, ax 2363 <1> keyb_int1: 2364 00000C79 D0E3 <1> shl bl, 1 2365 00000C7B 81C3[98700000] <1> add ebx, ttychr 2366 <1> ; 2367 00000C81 6609C0 <1> or ax, ax 2368 00000C84 7406 <1> jz short keyb_int2 2369 <1> ; 2370 00000C86 66833B00 <1> cmp word [ebx], 0 2371 00000C8A 7703 <1> ja short keyb_int3 2372 <1> keyb_int2: 2373 00000C8C 668903 <1> mov [ebx], ax ; Save ascii code 2374 <1> ; and scan code of the character 2375 <1> ; for current tty (or last tty 2376 <1> ; just before tty switch). 2377 <1> keyb_int3: 2378 00000C8F A0[96700000] <1> mov al, [ptty] 2379 00000C94 E820480000 <1> call wakeup 2380 <1> ; 2381 <1> keyb_int4: 2382 00000C99 58 <1> pop eax 2383 00000C9A 5B <1> pop ebx 2384 00000C9B 1F <1> pop ds 2385 00000C9C CF <1> iret 2386 <1> 2387 <1> ; 18/02/2015 2388 <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc. 2389 <1> ; 'keyb_int' always handles 'getc' at 1st and puts the 2390 <1> ; scancode and ascii code of the character 2391 <1> ; in the tty input (ttychr) buffer. 2392 <1> ; Test procedures must call 'getch' for tty input 2393 <1> ; otherwise, 'getc' will not be able to return to the caller 2394 <1> ; due to infinite (key press) waiting loop. 2395 <1> ; 2396 <1> ; 03/12/2014 2397 <1> ; 26/08/2014 2398 <1> ; KEYBOARD I/O 2399 <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014) 2400 <1> 2401 <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers. 2402 <1> ; (The reason of using '_k' labels!!!) (27/08/2014) 2403 <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM. 2404 <1> ; ('NOT LC_HC' --> '~LC_HC') (bit reversing operator) 2405 <1> 2406 <1> int_16h: ; 30/06/2015 2407 <1> ;getc: 2408 00000C9D 9C <1> pushfd ; 28/08/2014 2409 00000C9E 0E <1> push cs 2410 00000C9F E801000000 <1> call getc_int 2411 00000CA4 C3 <1> retn 2412 <1> 2413 <1> getc_int: 2414 <1> ; 28/02/2015 2415 <1> ; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2416 <1> ; instead of pc-at bios - 1985-) 2417 <1> ; 28/08/2014 (_k1d) 2418 <1> ; 30/06/2014 2419 <1> ; 03/03/2014 2420 <1> ; 28/02/2014 2421 <1> ; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 2422 <1> ; rombios source code (21/04/1986) 2423 <1> ; 'keybd.asm', INT 16H, KEYBOARD_IO 2424 <1> ; 2425 <1> ; KYBD --- 03/06/86 KEYBOARD BIOS 2426 <1> ; 2427 <1> ;--- INT 16 H ----------------------------------------------------------------- 2428 <1> ; KEYBOARD I/O : 2429 <1> ; THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT : 2430 <1> ; INPUT : 2431 <1> ; (AH)= 00H READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD, : 2432 <1> ; RETURN THE RESULT IN (AL), SCAN CODE IN (AH). : 2433 <1> ; THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE : 2434 <1> ; STANDARD PC OR PCAT KEYBOARD : 2435 <1> ;-----------------------------------------------------------------------------: 2436 <1> ; (AH)= 01H SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS : 2437 <1> ; AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER. : 2438 <1> ; (ZF)= 1 -- NO CODE AVAILABLE : 2439 <1> ; (ZF)= 0 -- CODE IS AVAILABLE (AX)= CHARACTER : 2440 <1> ; IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS : 2441 <1> ; IN (AX), AND THE ENTRY REMAINS IN THE BUFFER. : 2442 <1> ; THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES : 2443 <1> ;-----------------------------------------------------------------------------: 2444 <1> ; (AH)= 02H RETURN THE CURRENT SHIFT STATUS IN AL REGISTER : 2445 <1> ; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE : 2446 <1> ; EQUATES FOR @KB_FLAG : 2447 <1> ;-----------------------------------------------------------------------------: 2448 <1> ; (AH)= 03H SET TYPAMATIC RATE AND DELAY : 2449 <1> ; (AL) = 05H : 2450 <1> ; (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0) : 2451 <1> ; : 2452 <1> ; REGISTER RATE REGISTER RATE : 2453 <1> ; VALUE SELECTED VALUE SELECTED : 2454 <1> ; -------------------------------------------- : 2455 <1> ; 00H 30.0 10H 7.5 : 2456 <1> ; 01H 26.7 11H 6.7 : 2457 <1> ; 02H 24.0 12H 6.0 : 2458 <1> ; 03H 21.8 13H 5.5 : 2459 <1> ; 04H 20.0 14H 5.0 : 2460 <1> ; 05H 18.5 15H 4.6 : 2461 <1> ; 06H 17.1 16H 4.3 : 2462 <1> ; 07H 16.0 17H 4.0 : 2463 <1> ; 08H 15.0 18H 3.7 : 2464 <1> ; 09H 13.3 19H 3.3 : 2465 <1> ; 0AH 12.0 1AH 3.0 : 2466 <1> ; 0BH 10.9 1BH 2.7 : 2467 <1> ; 0CH 10.0 1CH 2.5 : 2468 <1> ; 0DH 9.2 1DH 2.3 : 2469 <1> ; 0EH 8.6 1EH 2.1 : 2470 <1> ; 0FH 8.0 1FH 2.0 : 2471 <1> ; : 2472 <1> ; (BH) = TYPAMATIC DELAY (BITS 2 - 7 MUST BE RESET TO 0) : 2473 <1> ; : 2474 <1> ; REGISTER DELAY : 2475 <1> ; VALUE VALUE : 2476 <1> ; ------------------ : 2477 <1> ; 00H 250 ms : 2478 <1> ; 01H 500 ms : 2479 <1> ; 02H 750 ms : 2480 <1> ; 03H 1000 ms : 2481 <1> ;-----------------------------------------------------------------------------: 2482 <1> ; (AH)= 05H PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD : 2483 <1> ; BUFFER AS IF STRUCK FROM KEYBOARD : 2484 <1> ; ENTRY: (CL) = ASCII CHARACTER : 2485 <1> ; (CH) = SCAN CODE : 2486 <1> ; EXIT: (AH) = 00H = SUCCESSFUL OPERATION : 2487 <1> ; (AL) = 01H = UNSUCCESSFUL - BUFFER FULL : 2488 <1> ; FLAGS: CARRY IF ERROR : 2489 <1> ;-----------------------------------------------------------------------------: 2490 <1> ; (AH)= 10H EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD, : 2491 <1> ; OTHERWISE SAME AS FUNCTION AH=0 : 2492 <1> ;-----------------------------------------------------------------------------: 2493 <1> ; (AH)= 11H EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD, : 2494 <1> ; OTHERWISE SAME AS FUNCTION AH=1 : 2495 <1> ;-----------------------------------------------------------------------------: 2496 <1> ; (AH)= 12H RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER : 2497 <1> ; AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT : 2498 <1> ; CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3 : 2499 <1> ; OUTPUT : 2500 <1> ; AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED : 2501 <1> ; ALL REGISTERS RETAINED : 2502 <1> ;------------------------------------------------------------------------------ 2503 <1> 2504 00000CA5 FB <1> sti ; INTERRUPTS BACK ON 2505 00000CA6 1E <1> push ds ; SAVE CURRENT DS 2506 00000CA7 53 <1> push ebx ; SAVE BX TEMPORARILY 2507 <1> ;push ecx ; SAVE CX TEMPORARILY 2508 00000CA8 66BB1000 <1> mov bx, KDATA 2509 00000CAC 8EDB <1> mov ds, bx ; PUT SEGMENT VALUE OF DATA AREA INTO DS 2510 00000CAE 08E4 <1> or ah, ah ; CHECK FOR (AH)= 00H 2511 00000CB0 7439 <1> jz short _K1 ; ASCII_READ 2512 00000CB2 FECC <1> dec ah ; CHECK FOR (AH)= 01H 2513 00000CB4 7452 <1> jz short _K2 ; ASCII_STATUS 2514 00000CB6 FECC <1> dec ah ; CHECK FOR (AH)= 02H 2515 00000CB8 0F8485000000 <1> jz _K3 ; SHIFT STATUS 2516 00000CBE FECC <1> dec ah ; CHECK FOR (AH)= 03H 2517 00000CC0 0F8484000000 <1> jz _K300 ; SET TYPAMATIC RATE/DELAY 2518 00000CC6 80EC02 <1> sub ah, 2 ; CHECK FOR (AH)= 05H 2519 00000CC9 0F84A1000000 <1> jz _K500 ; KEYBOARD WRITE 2520 <1> _KIO1: 2521 00000CCF 80EC0B <1> sub ah, 11 ; AH = 10H 2522 00000CD2 740B <1> jz short _K1E ; EXTENDED ASCII READ 2523 00000CD4 FECC <1> dec ah ; CHECK FOR (AH)= 11H 2524 00000CD6 7421 <1> jz short _K2E ; EXTENDED_ASCII_STATUS 2525 00000CD8 FECC <1> dec ah ; CHECK FOR (AH)= 12H 2526 00000CDA 7449 <1> jz short _K3E ; EXTENDED_SHIFT_STATUS 2527 <1> _KIO_EXIT: 2528 <1> ;pop ecx ; RECOVER REGISTER 2529 00000CDC 5B <1> pop ebx ; RECOVER REGISTER 2530 00000CDD 1F <1> pop ds ; RECOVER SEGMENT 2531 00000CDE CF <1> iretd ; INVALID COMMAND, EXIT 2532 <1> 2533 <1> ;----- ASCII CHARACTER 2534 <1> _K1E: 2535 00000CDF E8B9000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER (EXTENDED) 2536 00000CE4 E82E010000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2537 00000CE9 EBF1 <1> jmp short _KIO_EXIT ; GIVE IT TO THE CALLER 2538 <1> _K1: 2539 00000CEB E8AD000000 <1> call _K1S ; GET A CHARACTER FROM THE BUFFER 2540 00000CF0 E82D010000 <1> call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2541 00000CF5 72F4 <1> jc short _K1 ; CARRY SET MEANS TROW CODE AWAY 2542 <1> _K1A: 2543 00000CF7 EBE3 <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2544 <1> 2545 <1> ;----- ASCII STATUS 2546 <1> _K2E: 2547 00000CF9 E8EA000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER (EXTENDED) 2548 00000CFE 7420 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2549 00000D00 9C <1> pushf ; SAVE ZF FROM TEST 2550 00000D01 E811010000 <1> call _KIO_E_XLAT ; ROUTINE TO XLATE FOR EXTENDED CALLS 2551 00000D06 EB17 <1> jmp short _K2A ; GIVE IT TO THE CALLER 2552 <1> _K2: 2553 00000D08 E8DB000000 <1> call _K2S ; TEST FOR CHARACTER IN BUFFER 2554 00000D0D 7411 <1> jz short _K2B ; RETURN IF BUFFER EMPTY 2555 00000D0F 9C <1> pushf ; SAVE ZF FROM TEST 2556 00000D10 E80D010000 <1> call _KIO_S_XLAT ; ROUTINE TO XLATE FOR STANDARD CALLS 2557 00000D15 7308 <1> jnc short _K2A ; CARRY CLEAR MEANS PASS VALID CODE 2558 00000D17 9D <1> popf ; INVALID CODE FOR THIS TYPE OF CALL 2559 00000D18 E880000000 <1> call _K1S ; THROW THE CHARACTER AWAY 2560 00000D1D EBE9 <1> jmp short _K2 ; GO LOOK FOR NEXT CHAR, IF ANY 2561 <1> _K2A: 2562 00000D1F 9D <1> popf ; RESTORE ZF FROM TEST 2563 <1> _K2B: 2564 <1> ;pop ecx ; RECOVER REGISTER 2565 00000D20 5B <1> pop ebx ; RECOVER REGISTER 2566 00000D21 1F <1> pop ds ; RECOVER SEGMENT 2567 00000D22 CA0400 <1> retf 4 ; THROW AWAY (e)FLAGS 2568 <1> 2569 <1> ;----- SHIFT STATUS 2570 <1> _K3E: ; GET THE EXTENDED SHIFT STATUS FLAGS 2571 00000D25 8A25[546A0000] <1> mov ah, [KB_FLAG_1] ; GET SYSTEM SHIFT KEY STATUS 2572 00000D2B 80E404 <1> and ah, SYS_SHIFT ; MASK ALL BUT SYS KEY BIT 2573 <1> ;mov cl, 5 ; SHIFT THEW SYSTEMKEY BIT OVER TO 2574 <1> ;shl ah, cl ; BIT 7 POSITION 2575 00000D2E C0E405 <1> shl ah, 5 2576 00000D31 A0[546A0000] <1> mov al, [KB_FLAG_1] ; GET SYSTEM SHIFT STATES BACK 2577 00000D36 2473 <1> and al, 01110011b ; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT 2578 00000D38 08C4 <1> or ah, al ; MERGE REMAINING BITS INTO AH 2579 00000D3A A0[566A0000] <1> mov al, [KB_FLAG_3] ; GET RIGHT CTL AND ALT 2580 00000D3F 240C <1> and al, 00001100b ; ELIMINATE LC_E0 AND LC_E1 2581 00000D41 08C4 <1> or ah, al ; OR THE SHIFT FLAGS TOGETHER 2582 <1> _K3: 2583 00000D43 A0[536A0000] <1> mov al, [KB_FLAG] ; GET THE SHIFT STATUS FLAGS 2584 00000D48 EB92 <1> jmp short _KIO_EXIT ; RETURN TO CALLER 2585 <1> 2586 <1> ;----- SET TYPAMATIC RATE AND DELAY 2587 <1> _K300: 2588 00000D4A 3C05 <1> cmp al, 5 ; CORRECT FUNCTION CALL? 2589 00000D4C 758E <1> jne short _KIO_EXIT ; NO, RETURN 2590 00000D4E F6C3E0 <1> test bl, 0E0h ; TEST FOR OUT-OF-RANGE RATE 2591 00000D51 7589 <1> jnz short _KIO_EXIT ; RETURN IF SO 2592 00000D53 F6C7FC <1> test BH, 0FCh ; TEST FOR OUT-OF-RANGE DELAY 2593 00000D56 7584 <1> jnz short _KIO_EXIT ; RETURN IF SO 2594 00000D58 B0F3 <1> mov al, KB_TYPA_RD ; COMMAND FOR TYPAMATIC RATE/DELAY 2595 00000D5A E8B6060000 <1> call SND_DATA ; SEND TO KEYBOARD 2596 <1> ;mov cx, 5 ; SHIFT COUNT 2597 <1> ;shl bh, cl ; SHIFT DELAY OVER 2598 00000D5F C0E705 <1> shl bh, 5 2599 00000D62 88D8 <1> mov al, bl ; PUT IN RATE 2600 00000D64 08F8 <1> or al, bh ; AND DELAY 2601 00000D66 E8AA060000 <1> call SND_DATA ; SEND TO KEYBOARD 2602 00000D6B E96CFFFFFF <1> jmp _KIO_EXIT ; RETURN TO CALLER 2603 <1> 2604 <1> ;----- WRITE TO KEYBOARD BUFFER 2605 <1> _K500: 2606 00000D70 56 <1> push esi ; SAVE SI (esi) 2607 00000D71 FA <1> cli ; 2608 00000D72 8B1D[646A0000] <1> mov ebx, [BUFFER_TAIL] ; GET THE 'IN TO' POINTER TO THE BUFFER 2609 00000D78 89DE <1> mov esi, ebx ; SAVE A COPY IN CASE BUFFER NOT FULL 2610 00000D7A E8D3000000 <1> call _K4 ; BUMP THE POINTER TO SEE IF BUFFER IS FULL 2611 00000D7F 3B1D[606A0000] <1> cmp ebx, [BUFFER_HEAD] ; WILL THE BUFFER OVERRUN IF WE STORE THIS? 2612 00000D85 740D <1> je short _K502 ; YES - INFORM CALLER OF ERROR 2613 00000D87 66890E <1> mov [esi], cx ; NO - PUT ASCII/SCAN CODE INTO BUFFER 2614 00000D8A 891D[646A0000] <1> mov [BUFFER_TAIL], ebx ; ADJUST 'IN TO' POINTER TO REFLECT CHANGE 2615 00000D90 28C0 <1> sub al, al ; TELL CALLER THAT OPERATION WAS SUCCESSFUL 2616 00000D92 EB02 <1> jmp short _K504 ; SUB INSTRUCTION ALSO RESETS CARRY FLAG 2617 <1> _K502: 2618 00000D94 B001 <1> mov al, 01h ; BUFFER FULL INDICATION 2619 <1> _K504: 2620 00000D96 FB <1> sti 2621 00000D97 5E <1> pop esi ; RECOVER SI (esi) 2622 00000D98 E93FFFFFFF <1> jmp _KIO_EXIT ; RETURN TO CALLER WITH STATUS IN AL 2623 <1> 2624 <1> ;----- READ THE KEY TO FIGURE OUT WHAT TO DO ----- 2625 <1> _K1S: 2626 00000D9D FA <1> cli ; 03/12/2014 2627 00000D9E 8B1D[606A0000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2628 00000DA4 3B1D[646A0000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2629 <1> ;jne short _K1U ; IF ANYTHING IN BUFFER SKIP INTERRUPT 2630 00000DAA 750F <1> jne short _k1x ; 03/12/2014 2631 <1> ; 2632 <1> ; 03/12/2014 2633 <1> ; 28/08/2014 2634 <1> ; PERFORM OTHER FUNCTION ?? here ! 2635 <1> ;; MOV AX, 9002h ; MOVE IN WAIT CODE & TYPE 2636 <1> ;; INT 15H ; PERFORM OTHER FUNCTION 2637 <1> _K1T: ; ASCII READ 2638 00000DAC FB <1> sti ; INTERRUPTS BACK ON DURING LOOP 2639 00000DAD 90 <1> nop ; ALLOW AN INTERRUPT TO OCCUR 2640 <1> _K1U: 2641 00000DAE FA <1> cli ; INTERRUPTS BACK OFF 2642 00000DAF 8B1D[606A0000] <1> mov ebx, [BUFFER_HEAD] ; GET POINTER TO HEAD OF BUFFER 2643 00000DB5 3B1D[646A0000] <1> cmp ebx, [BUFFER_TAIL] ; TEST END OF BUFFER 2644 <1> _k1x: 2645 00000DBB 53 <1> push ebx ; SAVE ADDRESS 2646 00000DBC 9C <1> pushf ; SAVE FLAGS 2647 00000DBD E80B070000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2648 00000DC2 8A1D[556A0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2649 00000DC8 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2650 00000DCA 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2651 00000DCD 7406 <1> jz short _K1V ; IF NO CHANGE BYPASS UPDATE 2652 00000DCF E8A5060000 <1> call SND_LED1 2653 00000DD4 FA <1> cli ; DISABLE INTERRUPTS 2654 <1> _K1V: 2655 00000DD5 9D <1> popf ; RESTORE FLAGS 2656 00000DD6 5B <1> pop ebx ; RESTORE ADDRESS 2657 00000DD7 74D3 <1> je short _K1T ; LOOP UNTIL SOMETHING IN BUFFER 2658 <1> ; 2659 00000DD9 668B03 <1> mov ax, [ebx] ; GET SCAN CODE AND ASCII CODE 2660 00000DDC E871000000 <1> call _K4 ; MOVE POINTER TO NEXT POSITION 2661 00000DE1 891D[606A0000] <1> mov [BUFFER_HEAD], ebx ; STORE VALUE IN VARIABLE 2662 00000DE7 C3 <1> retn ; RETURN 2663 <1> 2664 <1> ;----- READ THE KEY TO SEE IF ONE IS PRESENT ----- 2665 <1> _K2S: 2666 00000DE8 FA <1> cli ; INTERRUPTS OFF 2667 00000DE9 8B1D[606A0000] <1> mov ebx, [BUFFER_HEAD] ; GET HEAD POINTER 2668 00000DEF 3B1D[646A0000] <1> cmp ebx, [BUFFER_TAIL] ; IF EQUAL (Z=1) THEN NOTHING THERE 2669 00000DF5 668B03 <1> mov ax, [ebx] 2670 00000DF8 9C <1> pushf ; SAVE FLAGS 2671 00000DF9 6650 <1> push ax ; SAVE CODE 2672 00000DFB E8CD060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2673 00000E00 8A1D[556A0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2674 00000E06 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2675 00000E08 80E307 <1> and bl, 07h ; KB_LEDS ; ISOLATE INDICATOR BITS 2676 00000E0B 7405 <1> jz short _K2T ; IF NO CHANGE BYPASS UPDATE 2677 00000E0D E850060000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2678 <1> _K2T: 2679 00000E12 6658 <1> pop ax ; RESTORE CODE 2680 00000E14 9D <1> popf ; RESTORE FLAGS 2681 00000E15 FB <1> sti ; INTERRUPTS BACK ON 2682 00000E16 C3 <1> retn ; RETURN 2683 <1> 2684 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS ----- 2685 <1> _KIO_E_XLAT: 2686 00000E17 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2687 00000E19 7506 <1> jne short _KIO_E_RET ; NO, PASS IT ON 2688 00000E1B 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2689 00000E1D 7402 <1> jz short _KIO_E_RET ; PASS THIS ON UNCHANGED 2690 00000E1F 30C0 <1> xor al, al ; OTHERWISE SET AL = 0 2691 <1> _KIO_E_RET: 2692 00000E21 C3 <1> retn ; GO BACK 2693 <1> 2694 <1> ;----- ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS ----- 2695 <1> _KIO_S_XLAT: 2696 00000E22 80FCE0 <1> cmp ah, 0E0h ; IS IT KEYPAD ENTER OR / ? 2697 00000E25 750F <1> jne short _KIO_S2 ; NO, CONTINUE 2698 00000E27 3C0D <1> cmp al, 0Dh ; KEYPAD ENTER CODE? 2699 00000E29 7408 <1> je short _KIO_S1 ; YES, MASSAGE A BIT 2700 00000E2B 3C0A <1> cmp al, 0Ah ; CTRL KEYPAD ENTER CODE? 2701 00000E2D 7404 <1> je short _KIO_S1 ; YES, MASSAGE THE SAME 2702 00000E2F B435 <1> mov ah, 35h ; NO, MUST BE KEYPAD / 2703 <1> _kio_ret: ; 03/12/2014 2704 00000E31 F8 <1> clc 2705 00000E32 C3 <1> retn 2706 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2707 <1> _KIO_S1: 2708 00000E33 B41C <1> mov ah, 1Ch ; CONVERT TO COMPATIBLE OUTPUT 2709 <1> ;jmp short _KIO_USE ; GIVE TO CALLER 2710 00000E35 C3 <1> retn 2711 <1> _KIO_S2: 2712 00000E36 80FC84 <1> cmp ah, 84h ; IS IT ONE OF EXTENDED ONES? 2713 00000E39 7715 <1> ja short _KIO_DIS ; YES, THROW AWAY AND GET ANOTHER CHAR 2714 00000E3B 3CF0 <1> cmp al, 0F0h ; IS IT ONE OF THE FILL-INs? 2715 00000E3D 7506 <1> jne short _KIO_S3 ; NO, TRY LAST TEST 2716 00000E3F 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2717 00000E41 740C <1> jz short _KIO_USE ; PASS THIS ON UNCHANGED 2718 00000E43 EB0B <1> jmp short _KIO_DIS ; THROW AWAY THE REST 2719 <1> _KIO_S3: 2720 00000E45 3CE0 <1> cmp al, 0E0h ; IS IT AN EXTENSION OF A PREVIOUS ONE? 2721 <1> ;jne short _KIO_USE ; NO, MUST BE A STANDARD CODE 2722 00000E47 75E8 <1> jne short _kio_ret 2723 00000E49 08E4 <1> or ah, ah ; AH = 0 IS SPECIAL CASE 2724 00000E4B 7402 <1> jz short _KIO_USE ; JUMP IF AH = 0 2725 00000E4D 30C0 <1> xor al, al ; CONVERT TO COMPATIBLE OUTPUT 2726 <1> ;jmp short _KIO_USE ; PASS IT ON TO CALLER 2727 <1> _KIO_USE: 2728 <1> ;clc ; CLEAR CARRY TO INDICATE GOOD CODE 2729 00000E4F C3 <1> retn ; RETURN 2730 <1> _KIO_DIS: 2731 00000E50 F9 <1> stc ; SET CARRY TO INDICATE DISCARD CODE 2732 00000E51 C3 <1> retn ; RETURN 2733 <1> 2734 <1> ;----- INCREMENT BUFFER POINTER ROUTINE ----- 2735 <1> _K4: 2736 00000E52 43 <1> inc ebx 2737 00000E53 43 <1> inc ebx ; MOVE TO NEXT WORD IN LIST 2738 00000E54 3B1D[5C6A0000] <1> cmp ebx, [BUFFER_END] ; AT END OF BUFFER? 2739 <1> ;jne short _K5 ; NO, CONTINUE 2740 00000E5A 7206 <1> jb short _K5 2741 00000E5C 8B1D[586A0000] <1> mov ebx, [BUFFER_START] ; YES, RESET TO BUFFER BEGINNING 2742 <1> _K5: 2743 00000E62 C3 <1> retn 2744 <1> 2745 <1> ; 20/02/2015 2746 <1> ; 05/12/2014 2747 <1> ; 26/08/2014 2748 <1> ; KEYBOARD (HARDWARE) INTERRUPT - IRQ LEVEL 1 2749 <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014) 2750 <1> ; 2751 <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 2752 <1> ; rombios source code (06/10/1985) 2753 <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1) 2754 <1> 2755 <1> ;--------- 8042 COMMANDS ------------------------------------------------------- 2756 <1> ENA_KBD equ 0AEh ; ENABLE KEYBOARD COMMAND 2757 <1> DIS_KBD equ 0ADh ; DISABLE KEYBOARD COMMAND 2758 <1> SHUT_CMD equ 0FEh ; CAUSE A SHUTDOWN COMMAND 2759 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 2760 <1> STATUS_PORT equ 064h ; 8042 STATUS PORT 2761 <1> INPT_BUF_FULL equ 00000010b ; 1 = +INPUT BUFFER FULL 2762 <1> PORT_A equ 060h ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 2763 <1> ;---------- 8042 KEYBOARD RESPONSE --------------------------------------------- 2764 <1> KB_ACK equ 0FAh ; ACKNOWLEDGE PROM TRANSMISSION 2765 <1> KB_RESEND equ 0FEh ; RESEND REQUEST 2766 <1> KB_OVER_RUN equ 0FFh ; OVER RUN SCAN CODE 2767 <1> ;---------- KEYBOARD/LED COMMANDS ---------------------------------------------- 2768 <1> KB_ENABLE equ 0F4h ; KEYBOARD ENABLE 2769 <1> LED_CMD equ 0EDh ; LED WRITE COMMAND 2770 <1> KB_TYPA_RD equ 0F3h ; TYPAMATIC RATE/DELAY COMMAND 2771 <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------ 2772 <1> NUM_KEY equ 69 ; SCAN CODE FOR NUMBER LOCK KEY 2773 <1> SCROLL_KEY equ 70 ; SCAN CODE FOR SCROLL LOCK KEY 2774 <1> ALT_KEY equ 56 ; SCAN CODE FOR ALTERNATE SHIFT KEY 2775 <1> CTL_KEY equ 29 ; SCAN CODE FOR CONTROL KEY 2776 <1> CAPS_KEY equ 58 ; SCAN CODE FOR SHIFT LOCK KEY 2777 <1> DEL_KEY equ 83 ; SCAN CODE FOR DELETE KEY 2778 <1> INS_KEY equ 82 ; SCAN CODE FOR INSERT KEY 2779 <1> LEFT_KEY equ 42 ; SCAN CODE FOR LEFT SHIFT 2780 <1> RIGHT_KEY equ 54 ; SCAN CODE FOR RIGHT SHIFT 2781 <1> SYS_KEY equ 84 ; SCAN CODE FOR SYSTEM KEY 2782 <1> ;---------- ENHANCED KEYBOARD SCAN CODES --------------------------------------- 2783 <1> ID_1 equ 0ABh ; 1ST ID CHARACTER FOR KBX 2784 <1> ID_2 equ 041h ; 2ND ID CHARACTER FOR KBX 2785 <1> ID_2A equ 054h ; ALTERNATE 2ND ID CHARACTER FOR KBX 2786 <1> F11_M equ 87 ; F11 KEY MAKE 2787 <1> F12_M equ 88 ; F12 KEY MAKE 2788 <1> MC_E0 equ 224 ; GENERAL MARKER CODE 2789 <1> MC_E1 equ 225 ; PAUSE KEY MARKER CODE 2790 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG---------------------------------------- 2791 <1> RIGHT_SHIFT equ 00000001b ; RIGHT SHIFT KEY DEPRESSED 2792 <1> LEFT_SHIFT equ 00000010b ; LEFT SHIFT KEY DEPRESSED 2793 <1> CTL_SHIFT equ 00000100b ; CONTROL SHIFT KEY DEPRESSED 2794 <1> ALT_SHIFT equ 00001000b ; ALTERNATE SHIFT KEY DEPRESSED 2795 <1> SCROLL_STATE equ 00010000b ; SCROLL LOCK STATE IS ACTIVE 2796 <1> NUM_STATE equ 00100000b ; NUM LOCK STATE IS ACTIVE 2797 <1> CAPS_STATE equ 01000000b ; CAPS LOCK STATE IS ACTIVE 2798 <1> INS_STATE equ 10000000b ; INSERT STATE IS ACTIVE 2799 <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG_1 ------------------------------------- 2800 <1> L_CTL_SHIFT equ 00000001b ; LEFT CTL KEY DOWN 2801 <1> L_ALT_SHIFT equ 00000010b ; LEFT ALT KEY DOWN 2802 <1> SYS_SHIFT equ 00000100b ; SYSTEM KEY DEPRESSED AND HELD 2803 <1> HOLD_STATE equ 00001000b ; SUSPEND KEY HAS BEEN TOGGLED 2804 <1> SCROLL_SHIFT equ 00010000b ; SCROLL LOCK KEY IS DEPRESSED 2805 <1> NUM_SHIFT equ 00100000b ; NUM LOCK KEY IS DEPRESSED 2806 <1> CAPS_SHIFT equ 01000000b ; CAPS LOCK KEY IS DEPRE55ED 2807 <1> INS_SHIFT equ 10000000b ; INSERT KEY IS DEPRESSED 2808 <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 ----------------------------------- 2809 <1> KB_LEDS equ 00000111b ; KEYBOARD LED STATE BITS 2810 <1> ; equ 00000001b ; SCROLL LOCK INDICATOR 2811 <1> ; equ 00000010b ; NUM LOCK INDICATOR 2812 <1> ; equ 00000100b ; CAPS LOCK INDICATOR 2813 <1> ; equ 00001000b ; RESERVED (MUST BE ZERO) 2814 <1> KB_FA equ 00010000b ; ACKNOWLEDGMENT RECEIVED 2815 <1> KB_FE equ 00100000b ; RESEND RECEIVED FLAG 2816 <1> KB_PR_LED equ 01000000b ; MODE INDICATOR UPDATE 2817 <1> KB_ERR equ 10000000b ; KEYBOARD TRANSMIT ERROR FLAG 2818 <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 ----------------------------------- 2819 <1> LC_E1 equ 00000001b ; LAST CODE WAS THE E1 HIDDEN CODE 2820 <1> LC_E0 equ 00000010b ; LAST CODE WAS THE E0 HIDDEN CODE 2821 <1> R_CTL_SHIFT equ 00000100b ; RIGHT CTL KEY DOWN 2822 <1> R_ALT_SHIFT equ 00001000b ; RIGHT ALT KEY DOWN 2823 <1> GRAPH_ON equ 00001000b ; ALT GRAPHICS KEY DOWN (WT ONLY) 2824 <1> KBX equ 00010000b ; ENHANCED KEYBOARD INSTALLED 2825 <1> SET_NUM_LK equ 00100000b ; FORCE NUM LOCK IF READ ID AND KBX 2826 <1> LC_AB equ 01000000b ; LAST CHARACTER WAS FIRST ID CHARACTER 2827 <1> RD_ID equ 10000000b ; DOING A READ ID (MUST BE BIT0) 2828 <1> ; 2829 <1> ;----------- INTERRUPT EQUATES ------------------------------------------------- 2830 <1> EOI equ 020h ; END OF INTERRUPT COMMAND TO 8259 2831 <1> INTA00 equ 020h ; 8259 PORT 2832 <1> 2833 <1> 2834 <1> kb_int: 2835 <1> 2836 <1> ; 17/10/2015 ('ctrlbrk') 2837 <1> ; 05/12/2014 2838 <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 2839 <1> ; instead of pc-at bios - 1985-) 2840 <1> ; 26/08/2014 2841 <1> ; 2842 <1> ; 03/06/86 KEYBOARD BIOS 2843 <1> ; 2844 <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------ 2845 <1> ; ; 2846 <1> ; KEYBOARD INTERRUPT ROUTINE ; 2847 <1> ; ; 2848 <1> ;-------------------------------------------------------------------------------- 2849 <1> 2850 <1> KB_INT_1: 2851 00000E63 FB <1> sti ; ENABLE INTERRUPTS 2852 <1> ;push ebp 2853 00000E64 50 <1> push eax 2854 00000E65 53 <1> push ebx 2855 00000E66 51 <1> push ecx 2856 00000E67 52 <1> push edx 2857 00000E68 56 <1> push esi 2858 00000E69 57 <1> push edi 2859 00000E6A 1E <1> push ds 2860 00000E6B 06 <1> push es 2861 00000E6C FC <1> cld ; FORWARD DIRECTION 2862 00000E6D 66B81000 <1> mov ax, KDATA 2863 00000E71 8ED8 <1> mov ds, ax 2864 00000E73 8EC0 <1> mov es, ax 2865 <1> ; 2866 <1> ;----- WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED 2867 00000E75 B0AD <1> mov al, DIS_KBD ; DISABLE THE KEYBOARD COMMAND 2868 00000E77 E885050000 <1> call SHIP_IT ; EXECUTE DISABLE 2869 00000E7C FA <1> cli ; DISABLE INTERRUPTS 2870 00000E7D B900000100 <1> mov ecx, 10000h ; SET MAXIMUM TIMEOUT 2871 <1> KB_INT_01: 2872 00000E82 E464 <1> in al, STATUS_PORT ; READ ADAPTER STATUS 2873 00000E84 A802 <1> test al, INPT_BUF_FULL ; CHECK INPUT BUFFER FULL STATUS BIT 2874 00000E86 E0FA <1> loopnz KB_INT_01 ; WAIT FOR COMMAND TO BE ACCEPTED 2875 <1> ; 2876 <1> ;----- READ CHARACTER FROM KEYBOARD INTERFACE 2877 00000E88 E460 <1> in al, PORT_A ; READ IN THE CHARACTER 2878 <1> ; 2879 <1> ;----- SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 2880 <1> ;MOV AH, 04FH ; SYSTEM INTERCEPT - KEY CODE FUNCTION 2881 <1> ;STC ; SET CY=1 (IN CASE OF IRET) 2882 <1> ;INT 15H ; CASETTE CALL (AL)=KEY SCAN CODE 2883 <1> ; ; RETURNS CY=1 FOR INVALID FUNCTION 2884 <1> ;JC KB_INT_02 ; CONTINUE IF CARRY FLAG SET ((AL)=CODE) 2885 <1> ;JMP K26 ; EXIT IF SYSTEM HANDLES SCAN CODE 2886 <1> ; ; EXÝT HANDLES HARDWARE EOI AND ENABLE 2887 <1> ; 2888 <1> ;----- CHECK FOR A RESEND COMMAND TO KEYBOARD 2889 <1> KB_INT_02: ; (AL)= SCAN CODE 2890 00000E8A FB <1> sti ; ENABLE INTERRUPTS AGAIN 2891 00000E8B 3CFE <1> cmp al, KB_RESEND ; IS THE INPUT A RESEND 2892 00000E8D 7411 <1> je short KB_INT_4 ; GO IF RESEND 2893 <1> ; 2894 <1> ;----- CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD 2895 00000E8F 3CFA <1> cmp al, KB_ACK ; IS THE INPUT AN ACKNOWLEDGE 2896 00000E91 751A <1> jne short KB_INT_2 ; GO IF NOT 2897 <1> ; 2898 <1> ;----- A COMMAND TO THE KEYBOARD WAS ISSUED 2899 00000E93 FA <1> cli ; DISABLE INTERRUPTS 2900 00000E94 800D[556A0000]10 <1> or byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED 2901 00000E9B E97A020000 <1> jmp K26 ; RETURN IF NOT (ACK RETURNED FOR DATA) 2902 <1> ; 2903 <1> ;----- RESEND THE LAST BYTE 2904 <1> KB_INT_4: 2905 00000EA0 FA <1> cli ; DISABLE INTERRUPTS 2906 00000EA1 800D[556A0000]20 <1> or byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED 2907 00000EA8 E96D020000 <1> jmp K26 ; RETURN IF NOT ACK RETURNED FOR DATA) 2908 <1> ; 2909 <1> ;----- UPDATE MODE INDICATORS IF CHANGE IN STATE 2910 <1> KB_INT_2: 2911 00000EAD 6650 <1> push ax ; SAVE DATA IN 2912 00000EAF E819060000 <1> call MAKE_LED ; GO GET MODE INDICATOR DATA BYTE 2913 00000EB4 8A1D[556A0000] <1> mov bl, [KB_FLAG_2] ; GET PREVIOUS BITS 2914 00000EBA 30C3 <1> xor bl, al ; SEE IF ANY DIFFERENT 2915 00000EBC 80E307 <1> and bl, KB_LEDS ; ISOLATE INDICATOR BITS 2916 00000EBF 7405 <1> jz short UP0 ; IF NO CHANGE BYPASS UPDATE 2917 00000EC1 E89C050000 <1> call SND_LED ; GO TURN ON MODE INDICATORS 2918 <1> UP0: 2919 00000EC6 6658 <1> pop ax ; RESTORE DATA IN 2920 <1> ;------------------------------------------------------------------------ 2921 <1> ; START OF KEY PROCESSING ; 2922 <1> ;------------------------------------------------------------------------ 2923 00000EC8 88C4 <1> mov ah, al ; SAVE SCAN CODE IN AH ALSO 2924 <1> ; 2925 <1> ;----- TEST FOR OVERRUN SCAN CODE FROM KEYBOARD 2926 00000ECA 3CFF <1> cmp al, KB_OVER_RUN ; IS THIS AN OVERRUN CHAR 2927 00000ECC 0F841B050000 <1> je K62 ; BUFFER_FULL_BEEP 2928 <1> ; 2929 <1> K16: 2930 00000ED2 8A3D[566A0000] <1> mov bh, [KB_FLAG_3] ; LOAD FLAGS FOR TESTING 2931 <1> ; 2932 <1> ;----- TEST TO SEE IF A READ_ID IS IN PROGRESS 2933 00000ED8 F6C7C0 <1> test bh, RD_ID+LC_AB ; ARE WE DOING A READ ID? 2934 00000EDB 7449 <1> jz short NOT_ID ; CONTINUE IF NOT 2935 00000EDD 7917 <1> jns short TST_ID_2 ; IS THE RD_ID FLAG ON? 2936 00000EDF 3CAB <1> cmp al, ID_1 ; IS THIS THE 1ST ID CHARACTER? 2937 00000EE1 7507 <1> jne short RST_RD_ID 2938 00000EE3 800D[566A0000]40 <1> or byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK 2939 <1> RST_RD_ID: 2940 00000EEA 8025[566A0000]7F <1> and byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG 2941 <1> ;jmp short ID_EX ; AND EXIT 2942 00000EF1 E924020000 <1> jmp K26 2943 <1> ; 2944 <1> TST_ID_2: 2945 00000EF6 8025[566A0000]BF <1> and byte [KB_FLAG_3], ~LC_AB ; RESET FLAG 2946 00000EFD 3C54 <1> cmp al, ID_2A ; IS THIS THE 2ND ID CHARACTER? 2947 00000EFF 7419 <1> je short KX_BIT ; JUMP IF SO 2948 00000F01 3C41 <1> cmp al, ID_2 ; IS THIS THE 2ND ID CHARACTER? 2949 <1> ;jne short ID_EX ; LEAVE IF NOT 2950 00000F03 0F8511020000 <1> jne K26 2951 <1> ; 2952 <1> ;----- A READ ID SAID THAT IT WAS ENHANCED KEYBOARD 2953 00000F09 F6C720 <1> test bh, SET_NUM_LK ; SHOULD WE SET NUM LOCK? 2954 00000F0C 740C <1> jz short KX_BIT ; EXIT IF NOT 2955 00000F0E 800D[536A0000]20 <1> or byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON 2956 00000F15 E848050000 <1> call SND_LED ; GO SET THE NUM LOCK INDICATOR 2957 <1> KX_BIT: 2958 00000F1A 800D[566A0000]10 <1> or byte [KB_FLAG_3], KBX ; INDICATE ENHANCED KEYBOARD WAS FOUND 2959 00000F21 E9F4010000 <1> ID_EX: jmp K26 ; EXIT 2960 <1> ; 2961 <1> NOT_ID: 2962 00000F26 3CE0 <1> cmp al, MC_E0 ; IS THIS THE GENERAL MARKER CODE? 2963 00000F28 750C <1> jne short TEST_E1 2964 00000F2A 800D[566A0000]12 <1> or byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND 2965 <1> ;jmp short EXIT ; THROW AWAY THIS CODE 2966 00000F31 E9EB010000 <1> jmp K26A 2967 <1> TEST_E1: 2968 00000F36 3CE1 <1> cmp al, MC_E1 ; IS THIS THE PAUSE KEY? 2969 00000F38 750C <1> jne short NOT_HC 2970 00000F3A 800D[566A0000]11 <1> or byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND 2971 00000F41 E9DB010000 <1> EXIT: jmp K26A ; THROW AWAY THIS CODE 2972 <1> ; 2973 <1> NOT_HC: 2974 00000F46 247F <1> and al, 07Fh ; TURN OFF THE BREAK BIT 2975 00000F48 F6C702 <1> test bh, LC_E0 ; LAST CODE THE E0 MARKER CODE 2976 00000F4B 7414 <1> jz short NOT_LC_E0 ; JUMP IF NOT 2977 <1> ; 2978 00000F4D BF[3E690000] <1> mov edi, _K6+6 ; IS THIS A SHIFT KEY? 2979 00000F52 AE <1> scasb 2980 00000F53 0F84C1010000 <1> je K26 ; K16B ; YES, THROW AWAY & RESET FLAG 2981 00000F59 AE <1> scasb 2982 00000F5A 757C <1> jne short K16A ; NO, CONTINUE KEY PROCESSING 2983 <1> ;jmp short K16B ; YES, THROW AWAY & RESET FLAG 2984 00000F5C E9B9010000 <1> jmp K26 2985 <1> ; 2986 <1> NOT_LC_E0: 2987 00000F61 F6C701 <1> test bh, LC_E1 ; LAST CODE THE E1 MARKER CODE? 2988 00000F64 7435 <1> jz short T_SYS_KEY ; JUMP IF NOT 2989 00000F66 B904000000 <1> mov ecx, 4 ; LENGHT OF SEARCH 2990 00000F6B BF[3C690000] <1> mov edi, _K6+4 ; IS THIS AN ALT, CTL, OR SHIFT? 2991 00000F70 F2AE <1> repne scasb ; CHECK IT 2992 <1> ;je short EXIT ; THROW AWAY IF SO 2993 00000F72 0F84A9010000 <1> je K26A 2994 <1> ; 2995 00000F78 3C45 <1> cmp al, NUM_KEY ; IS IT THE PAUSE KEY? 2996 <1> ;jne short K16B ; NO, THROW AWAY & RESET FLAG 2997 00000F7A 0F859A010000 <1> jne K26 2998 00000F80 F6C480 <1> test ah, 80h ; YES, IS IT THE BREAK OF THE KEY? 2999 <1> ;jnz short K16B ; YES, THROW THIS AWAY, TOO 3000 00000F83 0F8591010000 <1> jnz K26 3001 <1> ; 20/02/2015 3002 00000F89 F605[546A0000]08 <1> test byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY? 3003 <1> ;jnz short K16B ; YES, THROW AWAY 3004 00000F90 0F8584010000 <1> jnz K26 3005 00000F96 E9E1020000 <1> jmp K39P ; NO, THIS IS THE REAL PAUSE STATE 3006 <1> ; 3007 <1> ;----- TEST FOR SYSTEM KEY 3008 <1> T_SYS_KEY: 3009 00000F9B 3C54 <1> cmp al, SYS_KEY ; IS IT THE SYSTEM KEY? 3010 00000F9D 7539 <1> jnz short K16A ; CONTINUE IF NOT 3011 <1> ; 3012 00000F9F F6C480 <1> test ah, 80h ; CHECK IF THIS A BREAK CODE 3013 00000FA2 7524 <1> jnz short K16C ; DO NOT TOUCH SYSTEM INDICATOR IF TRUE 3014 <1> ; 3015 00000FA4 F605[546A0000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 3016 <1> ;jnz short K16B ; IF YES, DO NOT PROCESS SYSTEM INDICATOR 3017 00000FAB 0F8569010000 <1> jnz K26 3018 <1> ; 3019 00000FB1 800D[546A0000]04 <1> or byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED 3020 00000FB8 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3021 00000FBA E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3022 <1> ; INTERRUPT-RETURN-NO-EOI 3023 00000FBC B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3024 00000FBE E83E040000 <1> call SHIP_IT ; EXECUTE ENABLE 3025 <1> ; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!! 3026 <1> ;MOV AL, 8500H ; FUNCTION VALUE FOR MAKE OF SYSTEM KEY 3027 <1> ;STI ; MAKE SURE INTERRUPTS ENABLED 3028 <1> ;INT 15H ; USER INTERRUPT 3029 00000FC3 E965010000 <1> jmp K27A ; END PROCESSING 3030 <1> ; 3031 <1> ;K16B: jmp K26 ; IGNORE SYSTEM KEY 3032 <1> ; 3033 <1> K16C: 3034 00000FC8 8025[546A0000]FB <1> and byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN 3035 00000FCF B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3036 00000FD1 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3037 <1> ; INTERRUPT-RETURN-NO-EOI 3038 <1> ;MOV AL, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3039 <1> ;CALL SHIP_IT ; EXECUTE ENABLE 3040 <1> ; 3041 <1> ;MOV AX, 8501H ; FUNCTION VALUE FOR BREAK OF SYSTEM KEY 3042 <1> ;STI ; MAKE SURE INTERRUPTS ENABLED 3043 <1> ;INT 15H ; USER INTERRUPT 3044 <1> ;JMP K27A ; INGONRE SYSTEM KEY 3045 <1> ; 3046 00000FD3 E94E010000 <1> jmp K27 ; IGNORE SYSTEM KEY 3047 <1> ; 3048 <1> ;----- TEST FOR SHIFT KEYS 3049 <1> K16A: 3050 00000FD8 8A1D[536A0000] <1> mov bl, [KB_FLAG] ; PUT STATE FLAGS IN BL 3051 00000FDE BF[38690000] <1> mov edi, _K6 ; SHIFT KEY TABLE offset 3052 00000FE3 B908000000 <1> mov ecx, _K6L ; LENGTH 3053 00000FE8 F2AE <1> repne scasb ; LOOK THROUGH THE TABLE FOR A MATCH 3054 00000FEA 88E0 <1> mov al, ah ; RECOVER SCAN CODE 3055 00000FEC 0F8510010000 <1> jne K25 ; IF NO MATCH, THEN SHIFT NOT FOUND 3056 <1> ; 3057 <1> ;------ SHIFT KEY FOUND 3058 <1> K17: 3059 00000FF2 81EF[39690000] <1> sub edi, _K6+1 ; ADJUST PTR TO SCAN CODE MATCH 3060 00000FF8 8AA7[40690000] <1> mov ah, [edi+_K7] ; GET MASK INTO AH 3061 00000FFE B102 <1> mov cl, 2 ; SETUP COUNT FOR FLAG SHIFTS 3062 00001000 A880 <1> test al, 80h ; TEST FOR BREAK KEY 3063 00001002 0F8596000000 <1> jnz K23 ; JUMP OF BREAK 3064 <1> ; 3065 <1> ;----- SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE 3066 <1> K17C: 3067 00001008 80FC10 <1> cmp ah, SCROLL_SHIFT 3068 0000100B 732B <1> jae short K18 ; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY 3069 <1> ; 3070 <1> ;----- PLAIN SHIFT KEY, SET SHIFT ON 3071 0000100D 0825[536A0000] <1> or [KB_FLAG], ah ; TURN ON SHIFT BIT 3072 00001013 A80C <1> test al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL? 3073 <1> ;jnz short K17D ; YES, MORE FLAGS TO SET 3074 00001015 0F84FF000000 <1> jz K26 ; NO, INTERRUPT RETURN 3075 <1> K17D: 3076 0000101B F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF NEW KEYS? 3077 0000101E 740B <1> jz short K17E ; NO, JUMP 3078 00001020 0825[566A0000] <1> or [KB_FLAG_3], ah ; SET BITS FOR RIGHT CTRL, ALT 3079 00001026 E9EF000000 <1> jmp K26 ; INTERRUPT RETURN 3080 <1> K17E: 3081 0000102B D2EC <1> shr ah, cl ; MOVE FLAG BITS TWO POSITIONS 3082 0000102D 0825[546A0000] <1> or [KB_FLAG_1], ah ; SET BITS FOR LEFT CTRL, ALT 3083 00001033 E9E2000000 <1> jmp K26 3084 <1> ; 3085 <1> ;----- TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT 3086 <1> K18: ; SHIFT-TOGGLE 3087 00001038 F6C304 <1> test bl, CTL_SHIFT ; CHECK CTL SHIFT STATE 3088 <1> ;jz short K18A ; JUMP IF NOT CTL STATE 3089 0000103B 0F85C1000000 <1> jnz K25 ; JUMP IF CTL STATE 3090 <1> K18A: 3091 00001041 3C52 <1> cmp al, INS_KEY ; CHECK FOR INSERT KEY 3092 00001043 7524 <1> jne short K22 ; JUMP IF NOT INSERT KEY 3093 00001045 F6C308 <1> test bl, ALT_SHIFT ; CHECK FOR ALTERNATE SHIFT 3094 <1> ;jz short K18B ; JUMP IF NOT ALTERNATE SHIFT 3095 00001048 0F85B4000000 <1> jnz K25 ; JUMP IF ALTERNATE SHIFT 3096 <1> K18B: 3097 0000104E F6C702 <1> test bh, LC_E0 ;20/02/2015 ; IS THIS NEW INSERT KEY? 3098 00001051 7516 <1> jnz short K22 ; YES, THIS ONE'S NEVER A '0' 3099 <1> K19: 3100 00001053 F6C320 <1> test bl, NUM_STATE ; CHECK FOR BASE STATE 3101 00001056 750C <1> jnz short K21 ; JUMP IF NUM LOCK IS ON 3102 00001058 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE 3103 0000105B 740C <1> jz short K22 ; JUMP IF BASE STATE 3104 <1> K20: ; NUMERIC ZERO, NOT INSERT KEY 3105 0000105D 88C4 <1> mov ah, al ; PUT SCAN CODE BACK IN AH 3106 0000105F E99E000000 <1> jmp K25 ; NUMERAL '0', STNDRD. PROCESSING 3107 <1> K21: ; MIGHT BE NUMERIC 3108 00001064 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3109 00001067 74F4 <1> jz short K20 ; IS NUMERIC, STD. PROC. 3110 <1> ; 3111 <1> K22: ; SHIFT TOGGLE KEY HIT; PROCESS IT 3112 00001069 8425[546A0000] <1> test ah, [KB_FLAG_1] ; IS KEY ALREADY DEPRESSED 3113 0000106F 0F85A5000000 <1> jnz K26 ; JUMP IF KEY ALREADY DEPRESSED 3114 <1> K22A: 3115 00001075 0825[546A0000] <1> or [KB_FLAG_1], ah ; INDICATE THAT THE KEY IS DEPRESSED 3116 0000107B 3025[536A0000] <1> xor [KB_FLAG], ah ; TOGGLE THE SHIFT STATE 3117 <1> ; 3118 <1> ;----- TOGGLE LED IF CAPS, NUM OR SCROLL KEY DEPRESSED 3119 00001081 F6C470 <1> test ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE? 3120 00001084 7409 <1> jz short K22B ; GO IF NOT 3121 <1> ; 3122 00001086 6650 <1> push ax ; SAVE SCAN CODE AND SHIFT MASK 3123 00001088 E8D5030000 <1> call SND_LED ; GO TURN MODE INDICATORS ON 3124 0000108D 6658 <1> pop ax ; RESTORE SCAN CODE 3125 <1> K22B: 3126 0000108F 3C52 <1> cmp al, INS_KEY ; TEST FOR 1ST MAKE OF INSERT KEY 3127 00001091 0F8583000000 <1> jne K26 ; JUMP IF NOT INSERT KEY 3128 00001097 88C4 <1> mov ah, al ; SCAN CODE IN BOTH HALVES OF AX 3129 00001099 E999000000 <1> jmp K28 ; FLAGS UPDATED, PROC. FOR BUFFER 3130 <1> ; 3131 <1> ;----- BREAK SHIFT FOUND 3132 <1> K23: ; BREAK-SHIFT-FOUND 3133 0000109E 80FC10 <1> cmp ah, SCROLL_SHIFT ; IS THIS A TOGGLE KEY 3134 000010A1 F6D4 <1> not ah ; INVERT MASK 3135 000010A3 7355 <1> jae short K24 ; YES, HANDLE BREAK TOGGLE 3136 000010A5 2025[536A0000] <1> and [KB_FLAG], ah ; TURN OFF SHIFT BIT 3137 000010AB 80FCFB <1> cmp ah, ~CTL_SHIFT ; IS THIS ALT OR CTL? 3138 000010AE 7730 <1> ja short K23D ; NO, ALL DONE 3139 <1> ; 3140 000010B0 F6C702 <1> test bh, LC_E0 ; 2ND ALT OR CTL? 3141 000010B3 7408 <1> jz short K23A ; NO, HANSLE NORMALLY 3142 000010B5 2025[566A0000] <1> and [KB_FLAG_3], ah ; RESET BIT FOR RIGHT ALT OR CTL 3143 000010BB EB08 <1> jmp short K23B ; CONTINUE 3144 <1> K23A: 3145 000010BD D2FC <1> sar ah, cl ; MOVE THE MASK BIT TWO POSITIONS 3146 000010BF 2025[546A0000] <1> and [KB_FLAG_1], ah ; RESET BIT FOR LEFT ALT AND CTL 3147 <1> K23B: 3148 000010C5 88C4 <1> mov ah, al ; SAVE SCAN CODE 3149 000010C7 A0[566A0000] <1> mov al, [KB_FLAG_3] ; GET RIGHT ALT & CTRL FLAGS 3150 000010CC D2E8 <1> shr al, cl ; MOVE TO BITS 1 & 0 3151 000010CE 0A05[546A0000] <1> or al, [KB_FLAG_1] ; PUT IN LEFT ALÞT & CTL FLAGS 3152 000010D4 D2E0 <1> shl al, cl ; MOVE BACK TO BITS 3 & 2 3153 000010D6 240C <1> and al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE 3154 000010D8 0805[536A0000] <1> or [KB_FLAG], al ; PUT RESULT IN THE REAL FLAGS 3155 000010DE 88E0 <1> mov al, ah 3156 <1> K23D: 3157 000010E0 3CB8 <1> cmp al, ALT_KEY+80h ; IS THIS ALTERNATE SHIFT RELEASE 3158 000010E2 7536 <1> jne short K26 ; INTERRUPT RETURN 3159 <1> ; 3160 <1> ;----- ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER 3161 000010E4 A0[576A0000] <1> mov al, [ALT_INPUT] 3162 000010E9 B400 <1> mov ah, 0 ; SCAN CODE OF 0 3163 000010EB 8825[576A0000] <1> mov [ALT_INPUT], ah ; ZERO OUT THE FIELD 3164 000010F1 3C00 <1> cmp al, 0 ; WAS THE INPUT = 0? 3165 000010F3 7425 <1> je short K26 ; INTERRUPT_RETURN 3166 000010F5 E9D0020000 <1> jmp K61 ; IT WASN'T, SO PUT IN BUFFER 3167 <1> ; 3168 <1> K24: ; BREAK-TOGGLE 3169 000010FA 2025[546A0000] <1> and [KB_FLAG_1], ah ; INDICATE NO LONGER DEPRESSED 3170 00001100 EB18 <1> jmp short K26 ; INTERRUPT_RETURN 3171 <1> ; 3172 <1> ;----- TEST FOR HOLD STATE 3173 <1> ; AL, AH = SCAN CODE 3174 <1> K25: ; NO-SHIFT-FOUND 3175 00001102 3C80 <1> cmp al, 80h ; TEST FOR BREAK KEY 3176 00001104 7314 <1> jae short K26 ; NOTHING FOR BREAK CHARS FROM HERE ON 3177 00001106 F605[546A0000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE 3178 0000110D 7428 <1> jz short K28 ; BRANCH AROUND TEST IF NOT 3179 0000110F 3C45 <1> cmp al, NUM_KEY 3180 00001111 7407 <1> je short K26 ; CAN'T END HOLD ON NUM_LOCK 3181 00001113 8025[546A0000]F7 <1> and byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT 3182 <1> ; 3183 <1> K26: 3184 0000111A 8025[566A0000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3185 <1> K26A: ; INTERRUPT-RETURN 3186 00001121 FA <1> cli ; TURN OFF INTERRUPTS 3187 00001122 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3188 00001124 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3189 <1> K27: ; INTERRUPT-RETURN-NO-EOI 3190 00001126 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3191 00001128 E8D4020000 <1> call SHIP_IT ; EXECUTE ENABLE 3192 <1> K27A: 3193 0000112D FA <1> cli ; DISABLE INTERRUPTS 3194 0000112E 07 <1> pop es ; RESTORE REGISTERS 3195 0000112F 1F <1> pop ds 3196 00001130 5F <1> pop edi 3197 00001131 5E <1> pop esi 3198 00001132 5A <1> pop edx 3199 00001133 59 <1> pop ecx 3200 00001134 5B <1> pop ebx 3201 00001135 58 <1> pop eax 3202 <1> ;pop ebp 3203 00001136 CF <1> iret ; RETURN 3204 <1> 3205 <1> ;----- NOT IN HOLD STATE 3206 <1> K28: ; NO-HOLD-STATE 3207 00001137 3C58 <1> cmp al, 88 ; TEST FOR OUT-OF-RANGE SCAN CODES 3208 00001139 77DF <1> ja short K26 ; IGNORE IF OUT-OF-RANGE 3209 <1> ; 3210 0000113B F6C308 <1> test bl, ALT_SHIFT ; ARE WE IN ALTERNATE SHIFT 3211 <1> ;jz short K28A ; IF NOT ALTERNATE 3212 0000113E 0F84F1000000 <1> jz K38 3213 <1> ; 3214 00001144 F6C710 <1> test bh, KBX ; IS THIS THE ENCHANCED KEYBOARD? 3215 00001147 740D <1> jz short K29 ; NO, ALT STATE IS REAL 3216 <1> ;28/02/2015 3217 00001149 F605[546A0000]04 <1> test byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN? 3218 <1> ;jz short K29 ; NO, ALT STATE IS REAL 3219 00001150 0F85DF000000 <1> jnz K38 ; YES, THIS IS PHONY ALT STATE 3220 <1> ; ; DUE TO PRESSING SYSREQ 3221 <1> ;K28A: jmp short K38 3222 <1> ; 3223 <1> ;----- TEST FOR RESET KEY SEQUENCE (CTL ALT DEL) 3224 <1> K29: ; TEST-RESET 3225 00001156 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT ALSO? 3226 00001159 740B <1> jz short K31 ; NO_RESET 3227 0000115B 3C53 <1> cmp al, DEL_KEY ; CTL-ALT STATE, TEST FOR DELETE KEY 3228 0000115D 7507 <1> jne short K31 ; NO_RESET, IGNORE 3229 <1> ; 3230 <1> ;----- CTL-ALT-DEL HAS BEEN FOUND 3231 <1> ; 26/08/2014 3232 <1> cpu_reset: 3233 <1> ; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN) 3234 <1> ; Send FEh (system reset command) to the keyboard controller. 3235 0000115F B0FE <1> mov al, SHUT_CMD ; SHUTDOWN COMMAND 3236 00001161 E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROL PORT 3237 <1> khere: 3238 00001163 F4 <1> hlt ; WAIT FOR 80286 RESET 3239 00001164 EBFD <1> jmp short khere ; INSURE HALT 3240 <1> 3241 <1> ; 3242 <1> ;----- IN ALTERNATE SHIFT, RESET NOT FOUND 3243 <1> K31: ; NO-RESET 3244 00001166 3C39 <1> cmp al, 57 ; TEST FOR SPACE KEY 3245 00001168 7507 <1> jne short K311 ; NOT THERE 3246 0000116A B020 <1> mov al, ' ' ; SET SPACE CHAR 3247 0000116C E948020000 <1> jmp K57 ; BUFFER_FILL 3248 <1> K311: 3249 00001171 3C0F <1> cmp al, 15 ; TEST FOR TAB KEY 3250 00001173 7509 <1> jne short K312 ; NOT THERE 3251 00001175 66B800A5 <1> mov ax, 0A500h ; SET SPECIAL CODE FOR ALT-TAB 3252 00001179 E93B020000 <1> jmp K57 ; BUFFER_FILL 3253 <1> K312: 3254 0000117E 3C4A <1> cmp al, 74 ; TEST FOR KEY PAD - 3255 00001180 0F84A2000000 <1> je K37B ; GO PROCESS 3256 00001186 3C4E <1> cmp al, 78 ; TEST FOR KEY PAD + 3257 00001188 0F849A000000 <1> je K37B ; GO PROCESS 3258 <1> ; 3259 <1> ;----- LOOK FOR KEY PAD ENTRY 3260 <1> K32: ; ALT-KEY-PAD 3261 0000118E BF[14690000] <1> mov edi, K30 ; ALT-INPUT-TABLE offset 3262 00001193 B90A000000 <1> mov ecx, 10 ; LOOK FOR ENTRY USING KEYPAD 3263 00001198 F2AE <1> repne scasb ; LOOK FOR MATCH 3264 0000119A 7525 <1> jne short K33 ; NO_ALT_KEYPAD 3265 0000119C F6C702 <1> test bh, LC_E0 ; IS THIS ONE OF THE NEW KEYS? 3266 0000119F 0F858A000000 <1> jnz K37C ; YES, JUMP, NOT NUMPAD KEY 3267 000011A5 81EF[15690000] <1> sub edi, K30+1 ; DI NOW HAS ENTRY VALUE 3268 000011AB A0[576A0000] <1> mov al, [ALT_INPUT] ; GET THE CURRENT BYTE 3269 000011B0 B40A <1> mov ah, 10 ; MULTIPLY BY 10 3270 000011B2 F6E4 <1> mul ah 3271 000011B4 6601F8 <1> add ax, di ; ADD IN THE LATEST ENTRY 3272 000011B7 A2[576A0000] <1> mov [ALT_INPUT], al ; STORE IT AWAY 3273 <1> ;K32A: 3274 000011BC E959FFFFFF <1> jmp K26 ; THROW AWAY THAT KEYSTROKE 3275 <1> ; 3276 <1> ;----- LOOK FOR SUPERSHIFT ENTRY 3277 <1> K33: ; NO-ALT-KEYPAD 3278 000011C1 C605[576A0000]00 <1> mov byte [ALT_INPUT], 0 ; ZERO ANY PREVIOUS ENTRY INTO INPUT 3279 000011C8 B91A000000 <1> mov ecx, 26 ; (DI),(ES) ALREADY POINTING 3280 000011CD F2AE <1> repne scasb ; LOOK FOR MATCH IN ALPHABET 3281 000011CF 7450 <1> je short K37A ; MATCH FOUND, GO FILLL THE BUFFER 3282 <1> ; 3283 <1> ;----- LOOK FOR TOP ROW OF ALTERNATE SHIFT 3284 <1> K34: ; ALT-TOP-ROW 3285 000011D1 3C02 <1> cmp al, 2 ; KEY WITH '1' ON IT 3286 000011D3 7253 <1> jb short K37B ; MUST BE ESCAPE 3287 000011D5 3C0D <1> cmp al, 13 ; IS IT IN THE REGION 3288 000011D7 7705 <1> ja short K35 ; NO, ALT SOMETHING ELSE 3289 000011D9 80C476 <1> add ah, 118 ; CONVERT PSEUDO SCAN CODE TO RANGE 3290 000011DC EB43 <1> jmp short K37A ; GO FILL THE BUFFER 3291 <1> ; 3292 <1> ;----- TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES 3293 <1> K35: ; ALT-FUNCTION 3294 000011DE 3C57 <1> cmp al, F11_M ; IS IT F11? 3295 000011E0 7209 <1> jb short K35A ; 20/02/2015 ; NO, BRANCH 3296 000011E2 3C58 <1> cmp al, F12_M ; IS IT F12? 3297 000011E4 7705 <1> ja short K35A ; 20/02/2015 ; NO, BRANCH 3298 000011E6 80C434 <1> add ah, 52 ; CONVERT TO PSEUDO SCAN CODE 3299 000011E9 EB36 <1> jmp short K37A ; GO FILL THE BUFFER 3300 <1> K35A: 3301 000011EB F6C702 <1> test bh, LC_E0 ; DO WE HAVE ONE OF THE NEW KEYS? 3302 000011EE 7422 <1> jz short K37 ; NO, JUMP 3303 000011F0 3C1C <1> cmp al, 28 ; TEST FOR KEYPAD ENTER 3304 000011F2 7509 <1> jne short K35B ; NOT THERE 3305 000011F4 66B800A6 <1> mov ax, 0A600h ; SPECIAL CODE 3306 000011F8 E9BC010000 <1> jmp K57 ; BUFFER FILL 3307 <1> K35B: 3308 000011FD 3C53 <1> cmp al, 83 ; TEST FOR DELETE KEY 3309 000011FF 742E <1> je short K37C ; HANDLE WITH OTHER EDIT KEYS 3310 00001201 3C35 <1> cmp al, 53 ; TEST FOR KEYPAD / 3311 <1> ;jne short K32A ; NOT THERE, NO OTHER E0 SPECIALS 3312 00001203 0F8511FFFFFF <1> jne K26 3313 00001209 66B800A4 <1> mov ax, 0A400h ; SPECIAL CODE 3314 0000120D E9A7010000 <1> jmp K57 ; BUFFER FILL 3315 <1> K37: 3316 00001212 3C3B <1> cmp al, 59 ; TEST FOR FUNCTION KEYS (F1) 3317 00001214 7212 <1> jb short K37B ; NO FN, HANDLE W/OTHER EXTENDED 3318 00001216 3C44 <1> cmp al, 68 ; IN KEYPAD REGION? 3319 <1> ;ja short K32A ; IF SO, IGNORE 3320 00001218 0F87FCFEFFFF <1> ja K26 3321 0000121E 80C42D <1> add ah, 45 ; CONVERT TO PSEUDO SCAN CODE 3322 <1> K37A: 3323 00001221 B000 <1> mov al, 0 ; ASCII CODE OF ZERO 3324 00001223 E991010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3325 <1> K37B: 3326 00001228 B0F0 <1> mov al, 0F0h ; USE SPECIAL ASCII CODE 3327 0000122A E98A010000 <1> jmp K57 ; PUT IT IN THE BUFFER 3328 <1> K37C: 3329 0000122F 0450 <1> add al, 80 ; CONVERT SCAN CODE (EDIT KEYS) 3330 00001231 88C4 <1> mov ah, al ; (SCAN CODE NOT IN AH FOR INSERT) 3331 00001233 EBEC <1> jmp short K37A ; PUT IT IN THE BUFFER 3332 <1> ; 3333 <1> ;----- NOT IN ALTERNATE SHIFT 3334 <1> K38: ; NOT-ALT-SHIFT 3335 <1> ; BL STILL HAS SHIFT FLAGS 3336 00001235 F6C304 <1> test bl, CTL_SHIFT ; ARE WE IN CONTROL SHIFT? 3337 <1> ;jnz short K38A ; YES, START PROCESSING 3338 00001238 0F84B0000000 <1> jz K44 ; NOT-CTL-SHIFT 3339 <1> ; 3340 <1> ;----- CONTROL SHIFT, TEST SPECIAL CHARACTERS 3341 <1> ;----- TEST FOR BREAK 3342 <1> K38A: 3343 0000123E 3C46 <1> cmp al, SCROLL_KEY ; TEST FOR BREAK 3344 00001240 7531 <1> jne short K39 ; JUMP, NO-BREAK 3345 00001242 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3346 00001245 7405 <1> jz short K38B ; NO, BREAK IS VALID 3347 00001247 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3348 0000124A 7427 <1> jz short K39 ; NO-BREAK, TEST FOR PAUSE 3349 <1> K38B: 3350 0000124C 8B1D[606A0000] <1> mov ebx, [BUFFER_HEAD] ; RESET BUFFER TO EMPTY 3351 00001252 891D[646A0000] <1> mov [BUFFER_TAIL], ebx 3352 00001258 C605[526A0000]80 <1> mov byte [BIOS_BREAK], 80h ; TURN ON BIOS_BREAK BIT 3353 <1> ; 3354 <1> ;----- ENABLE KEYBOARD 3355 0000125F B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3356 00001261 E89B010000 <1> call SHIP_IT ; EXECUTE ENABLE 3357 <1> ; 3358 <1> ; CTRL+BREAK code here !!! 3359 <1> ;INT 1BH ; BREAK INTERRUPT VECTOR 3360 <1> ; 17/10/2015 3361 00001266 E89F260000 <1> call ctrlbrk ; control+break subroutine 3362 <1> ; 3363 0000126B 6629C0 <1> sub ax, ax ; PUT OUT DUMMY CHARACTER 3364 0000126E E946010000 <1> jmp K57 ; BUFFER_FILL 3365 <1> ; 3366 <1> ;----- TEST FOR PAUSE 3367 <1> K39: ; NO_BREAK 3368 00001273 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3369 00001276 7537 <1> jnz short K41 ; YES, THEN THIS CAN'T BE PAUSE 3370 00001278 3C45 <1> cmp al, NUM_KEY ; LOOK FOR PAUSE KEY 3371 0000127A 7533 <1> jne short K41 ; NO-PAUSE 3372 <1> K39P: 3373 0000127C 800D[546A0000]08 <1> or byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG 3374 <1> ; 3375 <1> ;----- ENABLE KEYBOARD 3376 00001283 B0AE <1> mov al, ENA_KBD ; ENABLE KEYBOARD 3377 00001285 E877010000 <1> call SHIP_IT ; EXECUTE ENABLE 3378 <1> K39A: 3379 0000128A B020 <1> mov al, EOI ; END OF INTERRUPT TO CONTROL PORT 3380 0000128C E620 <1> out 20h, al ;out INTA00, al ; ALLOW FURTHER KEYSTROKE INTERRUPTS 3381 <1> ; 3382 <1> ;----- DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON 3383 0000128E 803D[506A0000]07 <1> cmp byte [CRT_MODE], 7 ; IS THIS BLACK AND WHITE CARD 3384 00001295 740A <1> je short K40 ; YES, NOTHING TO DO 3385 00001297 66BAD803 <1> mov dx, 03D8h ; PORT FOR COLOR CARD 3386 0000129B A0[516A0000] <1> mov al, [CRT_MODE_SET] ; GET THE VALUE OF THE CURRENT MODE 3387 000012A0 EE <1> out dx, al ; SET THE CRT MODE, SO THAT CRT IS ON 3388 <1> ; 3389 <1> K40: ; PAUSE-LOOP 3390 000012A1 F605[546A0000]08 <1> test byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG 3391 000012A8 75F7 <1> jnz short K40 ; LOOP UNTIL FLAG TURNED OFF 3392 <1> ; 3393 000012AA E977FEFFFF <1> jmp K27 ; INTERRUPT_RETURN_NO_EOI 3394 <1> ; 3395 <1> ;----- TEST SPECIAL CASE KEY 55 3396 <1> K41: ; NO-PAUSE 3397 000012AF 3C37 <1> cmp al, 55 ; TEST FOR */PRTSC KEY 3398 000012B1 7513 <1> jne short K42 ; NOT-KEY-55 3399 000012B3 F6C710 <1> test bh, KBX ; IS THIS THE ENHANCED KEYBOARD? 3400 000012B6 7405 <1> jz short K41A ; NO, CTL-PRTSC IS VALID 3401 000012B8 F6C702 <1> test bh, LC_E0 ; YES, WAS LAST CODE AN E0? 3402 000012BB 7421 <1> jz short K42B ; NO, TRANSLATE TO A FUNCTION 3403 <1> K41A: 3404 000012BD 66B80072 <1> mov ax, 114*256 ; START/STOP PRINTING SWITCH 3405 000012C1 E9F3000000 <1> jmp K57 ; BUFFER_FILL 3406 <1> ; 3407 <1> ;----- SET UP TO TRANSLATE CONTROL SHIFT 3408 <1> K42: ; NOT-KEY-55 3409 000012C6 3C0F <1> cmp al, 15 ; IS IT THE TAB KEY? 3410 000012C8 7414 <1> je short K42B ; YES, XLATE TO FUNCTION CODE 3411 000012CA 3C35 <1> cmp al, 53 ; IS IT THE / KEY? 3412 000012CC 750E <1> jne short K42A ; NO, NO MORE SPECIAL CASES 3413 000012CE F6C702 <1> test bh, LC_E0 ; YES, IS IT FROM THE KEY PAD? 3414 000012D1 7409 <1> jz short K42A ; NO, JUST TRANSLATE 3415 000012D3 66B80095 <1> mov ax, 9500h ; YES, SPECIAL CODE FOR THIS ONE 3416 000012D7 E9DD000000 <1> jmp K57 ; BUFFER FILL 3417 <1> K42A: 3418 <1> ;;mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3419 000012DC 3C3B <1> cmp al, 59 ; IS IT IN CHARACTER TABLE? 3420 <1> ;jb short K45F ; YES, GO TRANSLATE CHAR 3421 <1> ;;jb K56 ; 20/02/2015 3422 <1> ;;jmp K64 ; 20/02/2015 3423 <1> K42B: 3424 000012DE BB[48690000] <1> mov ebx, _K8 ; SET UP TO TRANSLATE CTL 3425 000012E3 0F82AE000000 <1> jb K56 ;; 20/02/2015 3426 000012E9 E9B9000000 <1> jmp K64 3427 <1> ; 3428 <1> ;----- NOT IN CONTROL SHIFT 3429 <1> K44: ; NOT-CTL-SHIFT 3430 000012EE 3C37 <1> cmp al, 55 ; PRINT SCREEN KEY? 3431 000012F0 7528 <1> jne short K45 ; NOT PRINT SCREEN 3432 000012F2 F6C710 <1> test bh, KBX ; IS THIS ENHANCED KEYBOARD? 3433 000012F5 7407 <1> jz short K44A ; NO, TEST FOR SHIFT STATE 3434 000012F7 F6C702 <1> test bh, LC_E0 ; YES, LAST CODE A MARKER? 3435 000012FA 7507 <1> jnz short K44B ; YES, IS PRINT SCREEN 3436 000012FC EB41 <1> jmp short K45C ; NO, TRANSLATE TO '*' CHARACTER 3437 <1> K44A: 3438 000012FE F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN? 3439 00001301 743C <1> jz short K45C ; NO, TRANSLATE TO '*' CHARACTER 3440 <1> ; 3441 <1> ;----- ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION 3442 <1> K44B: 3443 00001303 B0AE <1> mov al, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3444 00001305 E8F7000000 <1> call SHIP_IT ; EXECUTE ENABLE 3445 0000130A B020 <1> mov al, EOI ; END OF CURRENT INTERRUPT 3446 0000130C E620 <1> out 20h, al ;out INTA00, al ; SO FURTHER THINGS CAN HAPPEN 3447 <1> ; Print Screen !!! ; ISSUE PRINT SCREEN INTERRUPT (INT 05h) 3448 <1> ;PUSH BP ; SAVE POINTER 3449 <1> ;INT 5H ; ISSUE PRINT SCREEN INTERRUPT 3450 <1> ;POP BP ; RESTORE POINTER 3451 0000130E 8025[566A0000]FC <1> and byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS 3452 00001315 E90CFEFFFF <1> jmp K27 ; GO BACK WITHOUT EOI OCCURRING 3453 <1> ; 3454 <1> ;----- HANDLE IN-CORE KEYS 3455 <1> K45: ; NOT-PRINT-SCREEN 3456 0000131A 3C3A <1> cmp al, 58 ; TEST FOR IN-CORE AREA 3457 0000131C 7734 <1> ja short K46 ; JUMP IF NOT 3458 0000131E 3C35 <1> cmp al, 53 ; IS THIS THE '/' KEY? 3459 00001320 7505 <1> jne short K45A ; NO, JUMP 3460 00001322 F6C702 <1> test bh, LC_E0 ; WAS THE LAST CODE THE MARKER? 3461 00001325 7518 <1> jnz short K45C ; YES, TRANSLATE TO CHARACTER 3462 <1> K45A: 3463 00001327 B91A000000 <1> mov ecx, 26 ; LENGHT OF SEARCH 3464 0000132C BF[1E690000] <1> mov edi, K30+10 ; POINT TO TABLE OF A-Z CHARS 3465 00001331 F2AE <1> repne scasb ; IS THIS A LETTER KEY? 3466 <1> ; 20/02/2015 3467 00001333 7505 <1> jne short K45B ; NO, SYMBOL KEY 3468 <1> ; 3469 00001335 F6C340 <1> test bl, CAPS_STATE ; ARE WE IN CAPS_LOCK? 3470 00001338 750C <1> jnz short K45D ; TEST FOR SURE 3471 <1> K45B: 3472 0000133A F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3473 0000133D 750C <1> jnz short K45E ; YES, UPPERCASE 3474 <1> ; NO, LOWERCASE 3475 <1> K45C: 3476 0000133F BB[A0690000] <1> mov ebx, K10 ; TRANSLATE TO LOWERCASE LETTERS 3477 00001344 EB51 <1> jmp short K56 3478 <1> K45D: ; ALMOST-CAPS-STATE 3479 00001346 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO? 3480 00001349 75F4 <1> jnz short K45C ; SHIFTED TEMP OUT OF CAPS STATE 3481 <1> K45E: 3482 0000134B BB[F8690000] <1> mov ebx, K11 ; TRANSLATE TO UPPER CASE LETTERS 3483 00001350 EB45 <1> K45F: jmp short K56 3484 <1> ; 3485 <1> ;----- TEST FOR KEYS F1 - F10 3486 <1> K46: ; NOT IN-CORE AREA 3487 00001352 3C44 <1> cmp al, 68 ; TEST FOR F1 - F10 3488 <1> ;ja short K47 ; JUMP IF NOT 3489 <1> ;jmp short K53 ; YES, GO DO FN KEY PROCESS 3490 00001354 7635 <1> jna short K53 3491 <1> ; 3492 <1> ;----- HANDLE THE NUMERIC PAD KEYS 3493 <1> K47: ; NOT F1 - F10 3494 00001356 3C53 <1> cmp al, 83 ; TEST NUMPAD KEYS 3495 00001358 772D <1> ja short K52 ; JUMP IF NOT 3496 <1> ; 3497 <1> ;----- KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION 3498 <1> K48: 3499 0000135A 3C4A <1> cmp al , 74 ; SPECIAL CASE FOR MINUS 3500 0000135C 74ED <1> je short K45E ; GO TRANSLATE 3501 0000135E 3C4E <1> cmp al , 78 ; SPECIAL CASE FOR PLUS 3502 00001360 74E9 <1> je short K45E ; GO TRANSLATE 3503 00001362 F6C702 <1> test bh, LC_E0 ; IS THIS ONE OFTHE NEW KEYS? 3504 00001365 750A <1> jnz short K49 ; YES, TRANSLATE TO BASE STATE 3505 <1> ; 3506 00001367 F6C320 <1> test bl, NUM_STATE ; ARE WE IN NUM LOCK 3507 0000136A 7514 <1> jnz short K50 ; TEST FOR SURE 3508 0000136C F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE? 3509 <1> ;jnz short K51 ; IF SHIFTED, REALLY NUM STATE 3510 0000136F 75DA <1> jnz short K45E 3511 <1> ; 3512 <1> ;----- BASE CASE FOR KEYPAD 3513 <1> K49: 3514 00001371 3C4C <1> cmp al, 76 ; SPECIAL CASE FOR BASE STATE 5 3515 00001373 7504 <1> jne short K49A ; CONTINUE IF NOT KEYPAD 5 3516 00001375 B0F0 <1> mov al, 0F0h ; SPECIAL ASCII CODE 3517 00001377 EB40 <1> jmp short K57 ; BUFFER FILL 3518 <1> K49A: 3519 00001379 BB[A0690000] <1> mov ebx, K10 ; BASE CASE TABLE 3520 0000137E EB27 <1> jmp short K64 ; CONVERT TO PSEUDO SCAN 3521 <1> ; 3522 <1> ;----- MIGHT BE NUM LOCK, TEST SHIFT STATUS 3523 <1> K50: ; ALMOST-NUM-STATE 3524 00001380 F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT 3525 00001383 75EC <1> jnz short K49 ; SHIFTED TEMP OUT OF NUM STATE 3526 00001385 EBC4 <1> K51: jmp short K45E ; REALLY NUM STATE 3527 <1> ; 3528 <1> ;----- TEST FOR THE NEW KEYS ON WT KEYBOARDS 3529 <1> K52: ; NOT A NUMPAD KEY 3530 00001387 3C56 <1> cmp al, 86 ; IS IT THE NEW WT KEY? 3531 <1> ;jne short K53 ; JUMP IF NOT 3532 <1> ;jmp short K45B ; HANDLE WITH REST OF LETTER KEYS 3533 00001389 74AF <1> je short K45B 3534 <1> ; 3535 <1> ;----- MUST BE F11 OR F12 3536 <1> K53: ; F1 - F10 COME HERE, TOO 3537 0000138B F6C303 <1> test bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE 3538 0000138E 74E1 <1> jz short K49 ; JUMP, LOWER CASE PSEUDO SC'S 3539 <1> ; 20/02/2015 3540 00001390 BB[F8690000] <1> mov ebx, K11 ; UPPER CASE PSEUDO SCAN CODES 3541 00001395 EB10 <1> jmp short K64 ; TRANSLATE SCAN 3542 <1> ; 3543 <1> ;----- TRANSLATE THE CHARACTER 3544 <1> K56: ; TRANSLATE-CHAR 3545 00001397 FEC8 <1> dec al ; CONVERT ORIGIN 3546 00001399 D7 <1> xlat ; CONVERT THE SCAN CODE TO ASCII 3547 0000139A F605[566A0000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3548 000013A1 7416 <1> jz short K57 ; NO, GO FILL BUFFER 3549 000013A3 B4E0 <1> mov ah, MC_E0 ; YES, PUT SPECIAL MARKER IN AH 3550 000013A5 EB12 <1> jmp short K57 ; PUT IT INTO THE BUFFER 3551 <1> ; 3552 <1> ;----- TRANSLATE SCAN FOR PSEUDO SCAN CODES 3553 <1> K64: ; TRANSLATE-SCAN-ORGD 3554 000013A7 FEC8 <1> dec al ; CONVERT ORIGIN 3555 000013A9 D7 <1> xlat ; CTL TABLE SCAN 3556 000013AA 88C4 <1> mov ah, al ; PUT VALUE INTO AH 3557 000013AC B000 <1> mov al, 0 ; ZERO ASCII CODE 3558 000013AE F605[566A0000]02 <1> test byte [KB_FLAG_3], LC_E0 ; IS THIS A NEW KEY? 3559 000013B5 7402 <1> jz short K57 ; NO, GO FILL BUFFER 3560 000013B7 B0E0 <1> mov al, MC_E0 ; YES, PUT SPECIAL MARKER IN AL 3561 <1> ; 3562 <1> ;----- PUT CHARACTER INTO BUFFER 3563 <1> K57: ; BUFFER_FILL 3564 000013B9 3CFF <1> cmp al, -1 ; IS THIS AN IGNORE CHAR 3565 <1> ;je short K59 ; YES, DO NOTHING WITH IT 3566 000013BB 0F8459FDFFFF <1> je K26 ; YES, DO NOTHING WITH IT 3567 000013C1 80FCFF <1> cmp ah, -1 ; LOOK FOR -1 PSEUDO SCAN 3568 <1> ;jne short K61 ; NEAR_INTERRUPT_RETURN 3569 000013C4 0F8450FDFFFF <1> je K26 ; INTERRUPT_RETURN 3570 <1> ;K59: ; NEAR_INTERRUPT_RETURN 3571 <1> ; jmp K26 ; INTERRUPT_RETURN 3572 <1> K61: ; NOT-CAPS-STATE 3573 000013CA 8B1D[646A0000] <1> mov ebx, [BUFFER_TAIL] ; GET THE END POINTER TO THE BUFFER 3574 000013D0 89DE <1> mov esi, ebx ; SAVE THE VALUE 3575 000013D2 E87BFAFFFF <1> call _K4 ; ADVANCE THE TAIL 3576 000013D7 3B1D[606A0000] <1> cmp ebx, [BUFFER_HEAD] ; HAS THE BUFFER WRAPPED AROUND 3577 000013DD 740E <1> je short K62 ; BUFFER_FULL_BEEP 3578 000013DF 668906 <1> mov [esi], ax ; STORE THE VALUE 3579 000013E2 891D[646A0000] <1> mov [BUFFER_TAIL], ebx ; MOVE THE POINTER UP 3580 000013E8 E92DFDFFFF <1> jmp K26 3581 <1> ;;cli ; TURN OFF INTERRUPTS 3582 <1> ;;mov al, EOI ; END OF INTERRUPT COMMAND 3583 <1> ;;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3584 <1> ;MOV AL, ENA_KBD ; INSURE KEYBOARD IS ENABLED 3585 <1> ;CALL SHIP_IT ; EXECUTE ENABLE 3586 <1> ;MOV AX, 9102H ; MOVE IN POST CODE & TYPE 3587 <1> ;INT 15H ; PERFORM OTHER FUNCTION 3588 <1> ;;and byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG 3589 <1> ;JMP K27A ; INTERRUPT_RETURN 3590 <1> ;;jmp K27 3591 <1> ; 3592 <1> ;----- BUFFER IS FULL SOUND THE BEEPER 3593 <1> K62: 3594 000013ED B020 <1> mov al, EOI ; ENABLE INTERRUPT CONTROLLER CHIP 3595 000013EF E620 <1> out INTA00, al 3596 000013F1 66B9A602 <1> mov cx, 678 ; DIVISOR FOR 1760 HZ 3597 000013F5 B304 <1> mov bl, 4 ; SHORT BEEP COUNT (1/16 + 1/64 DELAY) 3598 000013F7 E8A1010000 <1> call beep ; GO TO COMMON BEEP HANDLER 3599 000013FC E925FDFFFF <1> jmp K27 ; EXIT 3600 <1> 3601 <1> SHIP_IT: 3602 <1> ;--------------------------------------------------------------------------------- 3603 <1> ; SHIP_IT 3604 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3605 <1> ; TO THE KEYBOARD CONTROLLER. 3606 <1> ;--------------------------------------------------------------------------------- 3607 <1> ; 3608 00001401 6650 <1> push ax ; SAVE DATA TO SEND 3609 <1> 3610 <1> ;----- WAIT FOR COMMAND TO ACCEPTED 3611 00001403 FA <1> cli ; DISABLE INTERRUPTS TILL DATA SENT 3612 <1> ; xor ecx, ecx ; CLEAR TIMEOUT COUNTER 3613 00001404 B900000100 <1> mov ecx, 10000h 3614 <1> S10: 3615 00001409 E464 <1> in al, STATUS_PORT ; READ KEYBOARD CONTROLLER STATUS 3616 0000140B A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ITS INPUT BUFFER BUSY 3617 0000140D E0FA <1> loopnz S10 ; WAIT FOR COMMAND TO BE ACCEPTED 3618 <1> 3619 0000140F 6658 <1> pop ax ; GET DATA TO SEND 3620 00001411 E664 <1> out STATUS_PORT, al ; SEND TO KEYBOARD CONTROLLER 3621 00001413 FB <1> sti ; ENABLE INTERRUPTS AGAIN 3622 00001414 C3 <1> retn ; RETURN TO CALLER 3623 <1> 3624 <1> SND_DATA: 3625 <1> ; --------------------------------------------------------------------------------- 3626 <1> ; SND_DATA 3627 <1> ; THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES 3628 <1> ; TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO 3629 <1> ; HANDLES ANY RETRIES IF REQUIRED 3630 <1> ; --------------------------------------------------------------------------------- 3631 <1> ; 3632 00001415 6650 <1> push ax ; SAVE REGISTERS 3633 00001417 6653 <1> push bx 3634 00001419 51 <1> push ecx 3635 0000141A 88C7 <1> mov bh, al ; SAVE TRANSMITTED BYTE FOR RETRIES 3636 0000141C B303 <1> mov bl, 3 ; LOAD RETRY COUNT 3637 <1> SD0: 3638 0000141E FA <1> cli ; DISABLE INTERRUPTS 3639 0000141F 8025[556A0000]CF <1> and byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS 3640 <1> ; 3641 <1> ;----- WAIT FOR COMMAND TO BE ACCEPTED 3642 00001426 B900000100 <1> mov ecx, 10000h ; MAXIMUM WAIT COUNT 3643 <1> SD5: 3644 0000142B E464 <1> in al, STATUS_PORT ; READ KEYBOARD PROCESSOR STATUS PORT 3645 0000142D A802 <1> test al, INPT_BUF_FULL ; CHECK FOR ANY PENDING COMMAND 3646 0000142F E0FA <1> loopnz SD5 ; WAIT FOR COMMAND TO BE ACCEPTED 3647 <1> ; 3648 00001431 88F8 <1> mov al, bh ; REESTABLISH BYTE TO TRANSMIT 3649 00001433 E660 <1> out PORT_A, al ; SEND BYTE 3650 00001435 FB <1> sti ; ENABLE INTERRUPTS 3651 <1> ;mov cx, 01A00h ; LOAD COUNT FOR 10 ms+ 3652 00001436 B9FFFF0000 <1> mov ecx, 0FFFFh 3653 <1> SD1: 3654 0000143B F605[556A0000]30 <1> test byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET 3655 00001442 750F <1> jnz short SD3 ; IF SET, SOMETHING RECEIVED GO PROCESS 3656 00001444 E2F5 <1> loop SD1 ; OTHERWISE WAIT 3657 <1> SD2: 3658 00001446 FECB <1> dec bl ; DECREMENT RETRY COUNT 3659 00001448 75D4 <1> jnz short SD0 ; RETRY TRANSMISSION 3660 0000144A 800D[556A0000]80 <1> or byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG 3661 00001451 EB09 <1> jmp short SD4 ; RETRIES EXHAUSTED FORGET TRANSMISSION 3662 <1> SD3: 3663 00001453 F605[556A0000]10 <1> test byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE 3664 0000145A 74EA <1> jz short SD2 ; IF NOT, GO RESEND 3665 <1> SD4: 3666 0000145C 59 <1> pop ecx ; RESTORE REGISTERS 3667 0000145D 665B <1> pop bx 3668 0000145F 6658 <1> pop ax 3669 00001461 C3 <1> retn ; RETURN, GOOD TRANSMISSION 3670 <1> 3671 <1> SND_LED: 3672 <1> ; --------------------------------------------------------------------------------- 3673 <1> ; SND_LED 3674 <1> ; THIS ROUTINES TURNS ON THE MODE INDICATORS. 3675 <1> ; 3676 <1> ;---------------------------------------------------------------------------------- 3677 <1> ; 3678 00001462 FA <1> cli ; TURN OFF INTERRUPTS 3679 00001463 F605[556A0000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3680 0000146A 755F <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3681 <1> ; 3682 0000146C 800D[556A0000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3683 00001473 B020 <1> mov al, EOI ; END OF INTERRUPT COMMAND 3684 00001475 E620 <1> out 20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT 3685 00001477 EB11 <1> jmp short SL0 ; GO SEND MODE INDICATOR COMMAND 3686 <1> SND_LED1: 3687 00001479 FA <1> cli ; TURN OFF INTERRUPTS 3688 0000147A F605[556A0000]40 <1> test byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE 3689 00001481 7548 <1> jnz short SL1 ; DON'T UPDATE AGAIN IF UPDATE UNDERWAY 3690 <1> ; 3691 00001483 800D[556A0000]40 <1> or byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS 3692 <1> SL0: 3693 0000148A B0ED <1> mov al, LED_CMD ; LED CMD BYTE 3694 0000148C E884FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3695 00001491 FA <1> cli 3696 00001492 E836000000 <1> call MAKE_LED ; GO FORM INDICATOR DATA BYTE 3697 00001497 8025[556A0000]F8 <1> and byte [KB_FLAG_2], 0F8h ; ~KB_LEDS ; CLEAR MODE INDICATOR BITS 3698 0000149E 0805[556A0000] <1> or [KB_FLAG_2], al ; SAVE PRESENT INDICATORS FOR NEXT TIME 3699 000014A4 F605[556A0000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3700 000014AB 750F <1> jnz short SL2 ; IF SO, BYPASS SECOND BYTE TRANSMISSION 3701 <1> ; 3702 000014AD E863FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3703 000014B2 FA <1> cli ; TURN OFF INTERRUPTS 3704 000014B3 F605[556A0000]80 <1> test byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED 3705 000014BA 7408 <1> jz short SL3 ; IF NOT, DON'T SEND AN ENABLE COMMAND 3706 <1> SL2: 3707 000014BC B0F4 <1> mov al, KB_ENABLE ; GET KEYBOARD CSA ENABLE COMMAND 3708 000014BE E852FFFFFF <1> call SND_DATA ; SEND DATA TO KEYBOARD 3709 000014C3 FA <1> cli ; TURN OFF INTERRUPTS 3710 <1> SL3: 3711 000014C4 8025[556A0000]3F <1> and byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR 3712 <1> SL1: ; UPDATE AND TRANSMIT ERROR FLAG 3713 000014CB FB <1> sti ; ENABLE INTERRUPTS 3714 000014CC C3 <1> retn ; RETURN TO CALLER 3715 <1> 3716 <1> MAKE_LED: 3717 <1> ;--------------------------------------------------------------------------------- 3718 <1> ; MAKE_LED 3719 <1> ; THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF 3720 <1> ; THE MODE INDICATORS. 3721 <1> ;--------------------------------------------------------------------------------- 3722 <1> ; 3723 <1> ;push cx ; SAVE CX 3724 000014CD A0[536A0000] <1> mov al, [KB_FLAG] ; GET CAPS & NUM LOCK INDICATORS 3725 000014D2 2470 <1> and al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS 3726 <1> ;mov cl, 4 ; SHIFT COUNT 3727 <1> ;rol al, cl ; SHIFT BITS OVER TO TURN ON INDICATORS 3728 000014D4 C0C004 <1> rol al, 4 ; 20/02/2015 3729 000014D7 2407 <1> and al, 07h ; MAKE SURE ONLY MODE BITS ON 3730 <1> ;pop cx 3731 000014D9 C3 <1> retn ; RETURN TO CALLER 3732 <1> 3733 <1> ; % include 'kybdata.inc' ; KEYBOARD DATA ; 11/03/2015 3734 <1> 3735 <1> 3736 <1> ; /// End Of KEYBOARD FUNCTIONS /// 3737 3738 %include 'video.inc' ; 07/03/2015 3739 <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC 3740 <1> ; Last Modification: 16/01/2016 3741 <1> ; (Video Data is in 'VIDATA.INC') 3742 <1> ; 3743 <1> ; ///////// VIDEO (CGA) FUNCTIONS /////////////// 3744 <1> 3745 <1> ; 30/06/2015 3746 <1> ; 27/06/2015 3747 <1> ; 11/03/2015 3748 <1> ; 02/09/2014 3749 <1> ; 30/08/2014 3750 <1> ; VIDEO FUNCTIONS 3751 <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014) 3752 <1> 3753 <1> write_tty: 3754 <1> ; 13/08/2015 3755 <1> ; 02/09/2014 3756 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 3757 <1> ; 01/02/2014 (Retro UNIX 8086 v1 - last update) 3758 <1> ; 03/12/2013 (Retro UNIX 8086 v1 - beginning) 3759 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 3760 <1> ; 3761 <1> ; INPUT -> AH = Color (Forecolor, Backcolor) 3762 <1> ; AL = Character to be written 3763 <1> ; EBX = Video Page (0 to 7) 3764 <1> ; (BH = 0 --> Video Mode 3) 3765 <1> 3766 <1> RVRT equ 00001000b ; VIDEO VERTICAL RETRACE BIT 3767 <1> RHRZ equ 00000001b ; VIDEO HORIZONTAL RETRACE BIT 3768 <1> 3769 <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code 3770 <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO 3771 <1> ; 3772 <1> ; 06/10/85 VIDEO DISPLAY BIOS 3773 <1> ; 3774 <1> ;--- WRITE_TTY ------------------------------------------------------------------ 3775 <1> ; : 3776 <1> ; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE : 3777 <1> ; VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT : 3778 <1> ; CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION. : 3779 <1> ; IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN : 3780 <1> ; IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW : 3781 <1> ; ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW, : 3782 <1> ; FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE. : 3783 <1> ; WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE : 3784 <1> ; NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS : 3785 <1> ; LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE, : 3786 <1> ; THE 0 COLOR IS USED. : 3787 <1> ; ENTRY -- : 3788 <1> ; (AH) = CURRENT CRT MODE : 3789 <1> ; (AL) = CHARACTER TO BE WRITTEN : 3790 <1> ; NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE : 3791 <1> ; HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS : 3792 <1> ; (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE : 3793 <1> ; EXIT -- : 3794 <1> ; ALL REGISTERS SAVED : 3795 <1> ;-------------------------------------------------------------------------------- 3796 <1> 3797 000014DA FA <1> cli 3798 <1> ; 3799 <1> ; READ CURSOR (04/12/2013) 3800 <1> ; Retro UNIX 386 v1 Modifications: 30/08/2014 3801 000014DB 08FF <1> or bh, bh 3802 000014DD 0F85AB000000 <1> jnz beeper 3803 <1> ; 01/09/2014 3804 000014E3 803D[506A0000]03 <1> cmp byte [CRT_MODE], 3 3805 000014EA 7405 <1> je short m3 3806 <1> ; 3807 000014EC E887020000 <1> call set_mode 3808 <1> m3: 3809 000014F1 89DE <1> mov esi, ebx ; 13/08/2015 (0 to 7) 3810 000014F3 66D1E6 <1> shl si, 1 3811 000014F6 81C6[86700000] <1> add esi, cursor_posn 3812 000014FC 668B16 <1> mov dx, [esi] 3813 <1> ; 3814 <1> ; dx now has the current cursor position 3815 <1> ; 3816 000014FF 3C0D <1> cmp al, 0Dh ; is it carriage return or control character 3817 00001501 764D <1> jbe short u8 3818 <1> ; 3819 <1> ; write the char to the screen 3820 <1> u0: 3821 <1> ; ah = attribute/color 3822 <1> ; al = character 3823 <1> ; bl = video page number (0 to 7) 3824 <1> ; bh = 0 3825 <1> ; 3826 00001503 E83F020000 <1> call write_c_current 3827 <1> ; 3828 <1> ; position the cursor for next char 3829 00001508 FEC2 <1> inc dl ; next column 3830 <1> ;cmp dl, [CRT_COLS] 3831 0000150A 80FA50 <1> cmp dl, 80 ; test for column overflow 3832 0000150D 0F85EB000000 <1> jne set_cpos 3833 00001513 B200 <1> mov dl, 0 ; column = 0 3834 <1> u10: ; (line feed found) 3835 00001515 80FE18 <1> cmp dh, 25-1 ; check for last row 3836 00001518 722F <1> jb short u6 3837 <1> ; 3838 <1> ; scroll required 3839 <1> u1: 3840 <1> ; SET CURSOR POSITION (04/12/2013) 3841 0000151A E8DF000000 <1> call set_cpos 3842 <1> ; 3843 <1> ; determine value to fill with during scroll 3844 <1> u2: 3845 <1> ; READ_AC_CURRENT : 3846 <1> ; THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER 3847 <1> ; AT THE CURRENT CURSOR POSITION 3848 <1> ; 3849 <1> ; INPUT 3850 <1> ; (AH) = CURRENT CRT MODE 3851 <1> ; (BH) = DISPLAY PAGE ( ALPHA MODES ONLY ) 3852 <1> ; (DS) = DATA SEGMENT 3853 <1> ; (ES) = REGEN SEGMENT 3854 <1> ; OUTPUT 3855 <1> ; (AL) = CHARACTER READ 3856 <1> ; (AH) = ATTRIBUTE READ 3857 <1> ; 3858 <1> ; mov ah, [CRT_MODE] ; move current mode into ah 3859 <1> ; 3860 <1> ; bl = video page number 3861 <1> ; 3862 0000151F E837010000 <1> call find_position ; get regen location and port address 3863 <1> ; dx = status port 3864 <1> ; esi = cursor location/address 3865 <1> p11: 3866 00001524 FB <1> sti ; enable interrupts 3867 00001525 90 <1> nop ; allow for small interupts window 3868 00001526 FA <1> cli ; blocks interrupts for single loop 3869 00001527 EC <1> in al, dx ; get status from adapter 3870 00001528 A801 <1> test al, RHRZ ; is horizontal retrace low 3871 0000152A 75F8 <1> jnz short p11 ; wait until it is 3872 <1> p12: ; now wait for either retrace high 3873 0000152C EC <1> in al, dx ; get status 3874 0000152D A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 3875 0000152F 74FB <1> jz short p12 ; wait until either is active 3876 <1> p13: 3877 00001531 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 3878 00001537 668B06 <1> mov ax, [esi] ; get the character and attribute 3879 <1> ; 3880 <1> ; al = character, ah = attribute 3881 <1> ; 3882 0000153A FB <1> sti 3883 <1> ; bl = video page number 3884 <1> u3: 3885 <1> ;;mov ax, 0601h ; scroll one line 3886 <1> ;;sub cx, cx ; upper left corner 3887 <1> ;;mov dh, 25-1 ; lower right row 3888 <1> ;;;mov dl, [CRT_COLS] 3889 <1> ;mov dl, 80 ; lower right column 3890 <1> ;;dec dl 3891 <1> ;;mov dl, 79 3892 <1> 3893 <1> ;;call scroll_up ; 04/12/2013 3894 <1> ;;; 11/03/2015 3895 <1> ; 02/09/2014 3896 <1> ;;;mov cx, [crt_ulc] ; Upper left corner (0000h) 3897 <1> ;;;mov dx, [crt_lrc] ; Lower right corner (184Fh) 3898 <1> ; 11/03/2015 3899 0000153B 6629C9 <1> sub cx, cx 3900 0000153E 66BA4F18 <1> mov dx, 184Fh ; dl= 79 (column), dh = 24 (row) 3901 <1> ; 3902 00001542 B001 <1> mov al, 1 ; scroll 1 line up 3903 <1> ; ah = attribute 3904 00001544 E93E010000 <1> jmp scroll_up 3905 <1> ;u4: 3906 <1> ;;int 10h ; video-call return 3907 <1> ; scroll up the screen 3908 <1> ; tty return 3909 <1> ;u5: 3910 <1> ;retn ; return to the caller 3911 <1> 3912 <1> u6: ; set-cursor-inc 3913 00001549 FEC6 <1> inc dh ; next row 3914 <1> ; set cursor 3915 <1> ;u7: 3916 <1> ;;mov ah, 02h 3917 <1> ;;jmp short u4 ; establish the new cursor 3918 <1> ;call set_cpos 3919 <1> ;jmp short u5 3920 0000154B E9AE000000 <1> jmp set_cpos 3921 <1> 3922 <1> ; check for control characters 3923 <1> u8: 3924 00001550 7438 <1> je short u9 3925 00001552 3C0A <1> cmp al, 0Ah ; is it a line feed (0Ah) 3926 00001554 74BF <1> je short u10 3927 00001556 3C07 <1> cmp al, 07h ; is it a bell 3928 00001558 7434 <1> je short u11 3929 0000155A 3C08 <1> cmp al, 08h ; is it a backspace 3930 <1> ;jne short u0 3931 0000155C 7424 <1> je short bs ; 12/12/2013 3932 <1> ; 12/12/2013 (tab stop) 3933 0000155E 3C09 <1> cmp al, 09h ; is it a tab stop 3934 00001560 75A1 <1> jne short u0 3935 00001562 88D0 <1> mov al, dl 3936 00001564 6698 <1> cbw 3937 00001566 B108 <1> mov cl, 8 3938 00001568 F6F1 <1> div cl 3939 0000156A 28E1 <1> sub cl, ah 3940 <1> ts: 3941 <1> ; 02/09/2014 3942 <1> ; 01/09/2014 3943 0000156C B020 <1> mov al, 20h 3944 <1> tsloop: 3945 0000156E 6651 <1> push cx 3946 00001570 6650 <1> push ax 3947 00001572 30FF <1> xor bh, bh 3948 <1> ;mov bl, [active_page] 3949 00001574 E878FFFFFF <1> call m3 3950 00001579 6658 <1> pop ax ; ah = attribute/color 3951 0000157B 6659 <1> pop cx 3952 0000157D FEC9 <1> dec cl 3953 0000157F 75ED <1> jnz short tsloop 3954 00001581 C3 <1> retn 3955 <1> bs: 3956 <1> ; back space found 3957 <1> 3958 00001582 08D2 <1> or dl, dl ; is it already at start of line 3959 <1> ;je short u7 ; set_cursor 3960 00001584 7478 <1> jz short set_cpos 3961 00001586 664A <1> dec dx ; no -- just move it back 3962 <1> ;jmp short u7 3963 00001588 EB74 <1> jmp short set_cpos 3964 <1> 3965 <1> ; carriage return found 3966 <1> u9: 3967 0000158A B200 <1> mov dl, 0 ; move to first column 3968 <1> ;jmp short u7 3969 0000158C EB70 <1> jmp short set_cpos 3970 <1> 3971 <1> ; line feed found 3972 <1> ;u10: 3973 <1> ; cmp dh, 25-1 ; bottom of screen 3974 <1> ; jne short u6 ; no, just set the cursor 3975 <1> ; jmp u1 ; yes, scroll the screen 3976 <1> 3977 <1> beeper: 3978 <1> ; 30/08/2014 (Retro UNIX 386 v1) 3979 <1> ; 18/01/2014 3980 <1> ; 03/12/2013 3981 <1> ; bell found 3982 <1> u11: 3983 0000158E FB <1> sti 3984 0000158F 3A1D[96700000] <1> cmp bl, [active_page] 3985 00001595 7551 <1> jne short u12 ; Do not sound the beep 3986 <1> ; if it is not written on the active page 3987 00001597 66B93305 <1> mov cx, 1331 ; divisor for 896 hz tone 3988 0000159B B31F <1> mov bl, 31 ; set count for 31/64 second for beep 3989 <1> ;call beep ; sound the pod bell 3990 <1> ;jmp short u5 ; tty_return 3991 <1> ;retn 3992 <1> 3993 <1> TIMER equ 040h ; 8254 TIMER - BASE ADDRESS 3994 <1> PORT_B equ 061h ; PORT B READ/WRITE DIAGNOSTIC REGISTER 3995 <1> GATE2 equ 00000001b ; TIMER 2 INPUT CATE CLOCK BIT 3996 <1> SPK2 equ 00000010b ; SPEAKER OUTPUT DATA ENABLE BIT 3997 <1> 3998 <1> beep: 3999 <1> ; 07/02/2015 4000 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4001 <1> ; 18/01/2014 4002 <1> ; 03/12/2013 4003 <1> ; 4004 <1> ; TEST4.ASM - 06/10/85 POST AND BIOS UTILITY ROUTINES 4005 <1> ; 4006 <1> ; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE 4007 <1> ; 4008 <1> ; ENTRY: 4009 <1> ; (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND ) 4010 <1> ; (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ) 4011 <1> ; EXIT: : 4012 <1> ; (AX),(BL),(CX) MODIFIED. 4013 <1> 4014 0000159D 9C <1> pushf ; 18/01/2014 ; save interrupt status 4015 0000159E FA <1> cli ; block interrupts during update 4016 0000159F B0B6 <1> mov al, 10110110b ; select timer 2, lsb, msb binary 4017 000015A1 E643 <1> out TIMER+3, al ; write timer mode register 4018 000015A3 EB00 <1> jmp $+2 ; I/O delay 4019 000015A5 88C8 <1> mov al, cl ; divisor for hz (low) 4020 000015A7 E642 <1> out TIMER+2,AL ; write timer 2 count - lsb 4021 000015A9 EB00 <1> jmp $+2 ; I/O delay 4022 000015AB 88E8 <1> mov al, ch ; divisor for hz (high) 4023 000015AD E642 <1> out TIMER+2, al ; write timer 2 count - msb 4024 000015AF E461 <1> in al, PORT_B ; get current setting of port 4025 000015B1 88C4 <1> mov ah, al ; save that setting 4026 000015B3 0C03 <1> or al, GATE2+SPK2 ; gate timer 2 and turn speaker on 4027 000015B5 E661 <1> out PORT_B, al ; and restore interrupt status 4028 <1> ;popf ; 18/01/2014 4029 000015B7 FB <1> sti 4030 <1> g7: ; 1/64 second per count (bl) 4031 000015B8 B90B040000 <1> mov ecx, 1035 ; delay count for 1/64 of a second 4032 000015BD E827000000 <1> call waitf ; go to beep delay 1/64 count 4033 000015C2 FECB <1> dec bl ; (bl) length count expired? 4034 000015C4 75F2 <1> jnz short g7 ; no - continue beeping speaker 4035 <1> ; 4036 <1> ;pushf ; save interrupt status 4037 000015C6 FA <1> cli ; 18/01/2014 ; block interrupts during update 4038 000015C7 E461 <1> in al, PORT_B ; get current port value 4039 <1> ;or al, not (GATE2+SPK2) ; isolate current speaker bits in case 4040 000015C9 0CFC <1> or al, ~(GATE2+SPK2) 4041 000015CB 20C4 <1> and ah, al ; someone turned them off during beep 4042 000015CD 88E0 <1> mov al, ah ; recover value of port 4043 <1> ;or al, not (GATE2+SPK2) ; force speaker data off 4044 000015CF 0CFC <1> or al, ~(GATE2+SPK2) ; isolate current speaker bits in case 4045 000015D1 E661 <1> out PORT_B, al ; and stop speaker timer 4046 <1> ;popf ; restore interrupt flag state 4047 000015D3 FB <1> sti 4048 000015D4 B90B040000 <1> mov ecx, 1035 ; force 1/64 second delay (short) 4049 000015D9 E80B000000 <1> call waitf ; minimum delay between all beeps 4050 <1> ;pushf ; save interrupt status 4051 000015DE FA <1> cli ; block interrupts during update 4052 000015DF E461 <1> in al, PORT_B ; get current port value in case 4053 000015E1 2403 <1> and al, GATE2+SPK2 ; someone turned them on 4054 000015E3 08E0 <1> or al, ah ; recover value of port_b 4055 000015E5 E661 <1> out PORT_B, al ; restore speaker status 4056 000015E7 9D <1> popf ; restore interrupt flag state 4057 <1> u12: 4058 000015E8 C3 <1> retn 4059 <1> 4060 <1> REFRESH_BIT equ 00010000b ; REFRESH TEST BIT 4061 <1> 4062 <1> WAITF: 4063 <1> waitf: 4064 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4065 <1> ; 03/12/2013 4066 <1> ; 4067 <1> ; push ax ; save work register (ah) 4068 <1> ;waitf1: 4069 <1> ; use timer 1 output bits 4070 <1> ; in al, PORT_B ; read current counter output status 4071 <1> ; and al, REFRESH_BIT ; mask for refresh determine bit 4072 <1> ; cmp al, ah ; did it just change 4073 <1> ; je short waitf1 ; wait for a change in output line 4074 <1> ; ; 4075 <1> ; mov ah, al ; save new lflag state 4076 <1> ; loop waitf1 ; decrement half cycles till count end 4077 <1> ; ; 4078 <1> ; pop ax ; restore (ah) 4079 <1> ; retn ; return (cx)=0 4080 <1> 4081 <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s) 4082 <1> ; 17/12/2014 (dsectrm2.s) 4083 <1> ; WAITF 4084 <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 /// 4085 <1> ; 4086 <1> ;---WAITF----------------------------------------------------------------------- 4087 <1> ; FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR) 4088 <1> ; ENTRY: 4089 <1> ; (CX) = COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT 4090 <1> ; MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE 4091 <1> ; EXIT: 4092 <1> ; AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS) 4093 <1> ; (CX) = 0 4094 <1> ;------------------------------------------------------------------------------- 4095 <1> 4096 <1> ; Refresh period: 30 micro seconds (15-80 us) 4097 <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH) 4098 <1> 4099 <1> ;WAITF: ; DELAY FOR (CX)*15.085737 US 4100 000015E9 6650 <1> PUSH AX ; SAVE WORK REGISTER (AH) 4101 <1> ; 16/12/2014 4102 <1> ;shr cx, 1 ; convert to count of 30 micro seconds 4103 000015EB D1E9 <1> shr ecx, 1 ; 21/02/2015 4104 <1> ;17/12/2014 4105 <1> ;WAITF1: 4106 <1> ; IN AL, PORT_B ;061h ; READ CURRENT COUNTER OUTPUT STATUS 4107 <1> ; AND AL, REFRESH_BIT ;00010000b ; MASK FOR REFRESH DETERMINE BIT 4108 <1> ; CMP AL, AH ; DID IT JUST CHANGE 4109 <1> ; JE short WAITF1 ; WAIT FOR A CHANGE IN OUTPUT LINE 4110 <1> ; MOV AH, AL ; SAVE NEW FLAG STATE 4111 <1> ; LOOP WAITF1 ; DECREMENT HALF CYCLES TILL COUNT END 4112 <1> ; 4113 <1> ; 17/12/2014 4114 <1> ; 4115 <1> ; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999 4116 <1> ; 4117 <1> ;WAIT_REFRESH: Uses port 61, bit 4 to have CPU speed independent waiting. 4118 <1> ; INPUT: CX = number of refresh periods to wait 4119 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 4120 <1> WR_STATE_0: 4121 000015ED E461 <1> IN AL,PORT_B ; IN AL,SYS1 4122 000015EF A810 <1> TEST AL,010H 4123 000015F1 74FA <1> JZ SHORT WR_STATE_0 4124 <1> WR_STATE_1: 4125 000015F3 E461 <1> IN AL,PORT_B ; IN AL,SYS1 4126 000015F5 A810 <1> TEST AL,010H 4127 000015F7 75FA <1> JNZ SHORT WR_STATE_1 4128 000015F9 E2F2 <1> LOOP WR_STATE_0 4129 <1> ; 4130 000015FB 6658 <1> POP AX ; RESTORE (AH) 4131 000015FD C3 <1> RETn ; (CX) = 0 4132 <1> 4133 <1> set_cpos: 4134 <1> ; 27/06/2015 4135 <1> ; 01/09/2014 4136 <1> ; 30/08/2014 (Retro UNIX 386 v1 - beginning) 4137 <1> ; 4138 <1> ; 12/12/2013 (Retro UNIX 8086 v1 - last update) 4139 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - beginning) 4140 <1> ; 4141 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4142 <1> ; 4143 <1> ; SET_CPOS 4144 <1> ; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE 4145 <1> ; NEW X-Y VALUES PASSED 4146 <1> ; INPUT 4147 <1> ; DX - ROW,COLUMN OF NEW CURSOR 4148 <1> ; BH - DISPLAY PAGE OF CURSOR 4149 <1> ; OUTPUT 4150 <1> ; CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY 4151 <1> ; 4152 000015FE 0FB6C3 <1> movzx eax, bl ; BL = video page number ; 27/06/2015 (movzx) 4153 00001601 D0E0 <1> shl al, 1 ; word offset 4154 00001603 BE[86700000] <1> mov esi, cursor_posn 4155 00001608 01C6 <1> add esi, eax 4156 0000160A 668916 <1> mov [esi], dx ; save the pointer 4157 0000160D 381D[96700000] <1> cmp [active_page], bl 4158 00001613 7532 <1> jne short m17 4159 <1> ;call m18 ; CURSOR SET 4160 <1> ;m17: ; SET_CPOS_RETURN 4161 <1> ; 01/09/2014 4162 <1> ; retn 4163 <1> ; DX = row/column 4164 <1> m18: 4165 00001615 E832000000 <1> call position ; determine location in regen buffer 4166 0000161A 668B0D[84700000] <1> mov cx, [CRT_START] 4167 00001621 6601C1 <1> add cx, ax ; add char position in regen buffer 4168 <1> ; to the start address (offset) for this page 4169 00001624 66D1E9 <1> shr cx, 1 ; divide by 2 for char only count 4170 00001627 B40E <1> mov ah, 14 ; register number for cursor 4171 <1> ;call m16 ; output value to the 6845 4172 <1> ;retn 4173 <1> 4174 <1> ;----- THIS ROUTINE OUTPUTS THE CX REGISTER 4175 <1> ; TO THE 6845 REGISTERS NAMED IN (AH) 4176 <1> m16: 4177 00001629 FA <1> cli 4178 <1> ;mov dx, [addr_6845] ; address register 4179 0000162A 66BAD403 <1> mov dx, 03D4h ; I/O address of color card 4180 0000162E 88E0 <1> mov al, ah ; get value 4181 00001630 EE <1> out dx, al ; register set 4182 00001631 6642 <1> inc dx ; data register 4183 00001633 EB00 <1> jmp $+2 ; i/o delay 4184 00001635 88E8 <1> mov al, ch ; data 4185 00001637 EE <1> out dx, al 4186 00001638 664A <1> dec dx 4187 0000163A 88E0 <1> mov al, ah 4188 0000163C FEC0 <1> inc al ; point to other data register 4189 0000163E EE <1> out dx, al ; set for second register 4190 0000163F 6642 <1> inc dx 4191 00001641 EB00 <1> jmp $+2 ; i/o delay 4192 00001643 88C8 <1> mov al, cl ; second data value 4193 00001645 EE <1> out dx, al 4194 00001646 FB <1> sti 4195 <1> m17: 4196 00001647 C3 <1> retn 4197 <1> 4198 <1> 4199 <1> set_ctype: 4200 <1> ; 02/09/2014 (Retro UNIX 386 v1) 4201 <1> ; 4202 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4203 <1> 4204 <1> ; CH) = BITS 4-0 = START LINE FOR CURSOR 4205 <1> ; ** HARDWARE WILL ALWAYS CAUSE BLINK 4206 <1> ; ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING 4207 <1> ; OR NO CURSOR AT ALL 4208 <1> ; (CL) = BITS 4-0 = END LINE FOR CURSOR 4209 <1> 4210 <1> ;------------------------------------------------ 4211 <1> ; SET_CTYPE 4212 <1> ; THIS ROUTINE SETS THE CURSOR VALUE 4213 <1> ; INPUT 4214 <1> ; (CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE 4215 <1> ; OUTPUT 4216 <1> ; NONE 4217 <1> ;------------------------------------------------ 4218 <1> 4219 00001648 B40A <1> mov ah, 10 ; 6845 register for cursor set 4220 <1> ;mov [CURSOR_MODE], cx ; save in data area 4221 <1> ;call m16 ; output cx register 4222 <1> ;retn 4223 0000164A EBDD <1> jmp m16 4224 <1> 4225 <1> 4226 <1> position: 4227 <1> ; 27/06/2015 4228 <1> ; 02/09/2014 4229 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4230 <1> ; 04/12/2013 (Retro UNIX 8086 v1) 4231 <1> ; 4232 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4233 <1> ; 4234 <1> ; POSITION 4235 <1> ; THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS 4236 <1> ; OF A CHARACTER IN THE ALPHA MODE 4237 <1> ; INPUT 4238 <1> ; AX = ROW, COLUMN POSITION 4239 <1> ; OUTPUT 4240 <1> ; AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 4241 <1> 4242 <1> ; DX = ROW, COLUMN POSITION 4243 <1> ;movzx eax, byte [CRT_COLS] ; 27/06/2015 4244 0000164C 31C0 <1> xor eax, eax ; 02/09/2014 4245 0000164E B050 <1> mov al, 80 ; determine bytes to row 4246 00001650 F6E6 <1> mul dh ; row value 4247 00001652 30F6 <1> xor dh, dh ; 0 4248 00001654 6601D0 <1> add ax, dx ; add column value to the result 4249 00001657 66D1E0 <1> shl ax, 1 ; * 2 for attribute bytes 4250 <1> ; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 4251 0000165A C3 <1> retn 4252 <1> 4253 <1> find_position: 4254 <1> ; 27/06/2015 4255 <1> ; 07/09/2014 4256 <1> ; 02/09/2014 4257 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4258 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4259 0000165B 0FB6CB <1> movzx ecx, bl ; video page number ; 27/06/2015 (movzx) 4260 0000165E 89CE <1> mov esi, ecx 4261 00001660 66D1E6 <1> shl si, 1 4262 00001663 668B96[86700000] <1> mov dx, [esi + cursor_posn] 4263 0000166A 740A <1> jz short p21 4264 0000166C 6631F6 <1> xor si, si 4265 <1> p20: 4266 <1> ;add si, [CRT_LEN] 4267 0000166F 6681C6A00F <1> add si, 80*25*2 ; add length of buffer for one page 4268 00001674 E2F9 <1> loop p20 4269 <1> p21: 4270 00001676 6621D2 <1> and dx, dx 4271 00001679 7407 <1> jz short p22 4272 0000167B E8CCFFFFFF <1> call position ; determine location in regen in page 4273 00001680 01C6 <1> add esi, eax ; add location to start of regen page 4274 <1> p22: 4275 <1> ;mov dx, [addr_6845] ; get base address of active display 4276 <1> ;mov dx, 03D4h ; I/O address of color card 4277 <1> ;add dx, 6 ; point at status port 4278 00001682 66BADA03 <1> mov dx, 03DAh ; status port 4279 <1> ; cx = 0 4280 00001686 C3 <1> retn 4281 <1> 4282 <1> scroll_up: 4283 <1> ; 16/01/2016 4284 <1> ; 07/09/2014 4285 <1> ; 02/09/2014 4286 <1> ; 01/09/2014 (Retro UNIX 386 v1 - beginning) 4287 <1> ; 04/04/2014 4288 <1> ; 04/12/2013 4289 <1> ; 4290 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4291 <1> ; 4292 <1> ; SCROLL UP 4293 <1> ; THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP 4294 <1> ; ON THE SCREEN 4295 <1> ; INPUT 4296 <1> ; (AH) = CURRENT CRT MODE 4297 <1> ; (AL) = NUMBER OF ROWS TO SCROLL 4298 <1> ; (CX) = ROW/COLUMN OF UPPER LEFT CORNER 4299 <1> ; (DX) = ROW/COLUMN OF LOWER RIGHT CORNER 4300 <1> ; (BH) = ATTRIBUTE TO BE USED ON BLANKED LINE 4301 <1> ; (DS) = DATA SEGMENT 4302 <1> ; (ES) = REGEN BUFFER SEGMENT 4303 <1> ; OUTPUT 4304 <1> ; NONE -- THE REGEN BUFFER IS MODIFIED 4305 <1> ; 4306 <1> ; bh = 0 (02/09/2014) 4307 <1> ; 4308 <1> ; ((ah = 3)) 4309 <1> ; cl = left upper column 4310 <1> ; ch = left upper row 4311 <1> ; dl = right lower column 4312 <1> ; dh = right lower row 4313 <1> ; 4314 <1> ; al = line count 4315 <1> ; ah = attribute to be used on blanked line 4316 <1> ; bl = video page number (0 to 7) 4317 <1> ; 4318 <1> 4319 <1> ; Test Line Count 4320 00001687 08C0 <1> or al, al 4321 00001689 740C <1> jz short al_set 4322 0000168B 88F7 <1> mov bh, dh ; subtract lower row from upper row 4323 0000168D 28EF <1> sub bh, ch 4324 0000168F FEC7 <1> inc bh ; adjust difference by 1 4325 00001691 38C7 <1> cmp bh, al ; line count = amount of rows in window? 4326 00001693 7502 <1> jne short al_set ; if not the we're all set 4327 00001695 30C0 <1> xor al, al ; otherwise set al to zero 4328 <1> al_set: 4329 00001697 30FF <1> xor bh, bh ; 0 4330 00001699 6650 <1> push ax 4331 <1> ;mov esi, [crt_base] 4332 0000169B BE00800B00 <1> mov esi, 0B8000h 4333 000016A0 3A1D[96700000] <1> cmp bl, [active_page] 4334 000016A6 750B <1> jne short n0 4335 <1> ; 4336 000016A8 66A1[84700000] <1> mov ax, [CRT_START] 4337 000016AE 6601C6 <1> add si, ax 4338 000016B1 EB0F <1> jmp short n1 4339 <1> n0: 4340 000016B3 20DB <1> and bl, bl 4341 000016B5 740B <1> jz short n1 4342 000016B7 88D8 <1> mov al, bl 4343 <1> n0x: 4344 <1> ;add si, [CRT_LEN] 4345 <1> ;add esi, 80*25*2 4346 000016B9 6681C6A00F <1> add si, 80*25*2 4347 000016BE FEC8 <1> dec al 4348 000016C0 75F7 <1> jnz short n0x 4349 <1> n1: 4350 <1> ;Scroll position 4351 000016C2 6652 <1> push dx 4352 000016C4 6689CA <1> mov dx, cx ; now, upper left position in DX 4353 000016C7 E880FFFFFF <1> call position 4354 000016CC 01C6 <1> add esi, eax 4355 000016CE 89F7 <1> mov edi, esi 4356 000016D0 665A <1> pop dx ; lower right position in DX 4357 000016D2 6629CA <1> sub dx, cx 4358 000016D5 FEC6 <1> inc dh ; dh = #rows 4359 000016D7 FEC2 <1> inc dl ; dl = #cols in block 4360 000016D9 6658 <1> pop ax ; al = line count, ah = attribute 4361 000016DB 31C9 <1> xor ecx, ecx 4362 000016DD 6689C1 <1> mov cx, ax 4363 <1> ;mov ah, [CRT_COLS] 4364 000016E0 B450 <1> mov ah, 80 4365 000016E2 F6E4 <1> mul ah ; determine offset to from address 4366 000016E4 6601C0 <1> add ax, ax ; *2 for attribute byte 4367 <1> ; 4368 000016E7 6650 <1> push ax ; offset 4369 000016E9 6652 <1> push dx 4370 <1> ; 4371 <1> ; 04/04/2014 4372 000016EB 66BADA03 <1> mov dx, 3DAh ; guaranteed to be color card here 4373 <1> n8: ; wait_display_enable 4374 000016EF EC <1> in al, dx ; get port 4375 000016F0 A808 <1> test al, RVRT ; wait for vertical retrace 4376 000016F2 74FB <1> jz short n8 ; wait_display_enable 4377 000016F4 B025 <1> mov al, 25h 4378 000016F6 B2D8 <1> mov dl, 0D8h ; address control port 4379 000016F8 EE <1> out dx, al ; turn off video during vertical retrace 4380 000016F9 665A <1> pop dx ; #rows, #cols 4381 000016FB 6658 <1> pop ax ; offset 4382 000016FD 6691 <1> xchg ax, cx ; 4383 <1> ; ecx = offset, al = line count, ah = attribute 4384 <1> ;n9: 4385 000016FF 08C0 <1> or al, al 4386 00001701 7420 <1> jz short n3 4387 00001703 01CE <1> add esi, ecx ; from address for scroll 4388 00001705 88F7 <1> mov bh, dh ; #rows in block 4389 00001707 28C7 <1> sub bh, al ; #rows to be moved 4390 <1> n2: 4391 <1> ; Move rows 4392 00001709 88D1 <1> mov cl, dl ; get # of cols to move 4393 0000170B 56 <1> push esi 4394 0000170C 57 <1> push edi ; save start address 4395 <1> n10: 4396 0000170D 66A5 <1> movsw ; move that line on screen 4397 0000170F FEC9 <1> dec cl 4398 00001711 75FA <1> jnz short n10 4399 00001713 5F <1> pop edi 4400 00001714 5E <1> pop esi ; recover addresses 4401 <1> ;mov cl, [CRT_COLS] 4402 <1> ;add cl, cl 4403 <1> ;mov ecx, 80*2 4404 00001715 66B9A000 <1> mov cx, 80*2 4405 00001719 01CE <1> add esi, ecx ; next line 4406 0000171B 01CF <1> add edi, ecx 4407 0000171D FECF <1> dec bh ; count of lines to move 4408 0000171F 75E8 <1> jnz short n2 ; row loop 4409 <1> ; bh = 0 4410 00001721 88C6 <1> mov dh, al ; #rows 4411 <1> n3: 4412 <1> ; attribute in ah 4413 00001723 B020 <1> mov al, ' ' ; fill with blanks 4414 <1> n3x: 4415 <1> ; Clear rows 4416 <1> ; dh = #rows 4417 00001725 88D1 <1> mov cl, dl ; get # of cols to clear 4418 00001727 57 <1> push edi ; save address 4419 <1> n11: 4420 00001728 66AB <1> stosw ; store fill character 4421 0000172A FEC9 <1> dec cl 4422 0000172C 75FA <1> jnz short n11 4423 0000172E 5F <1> pop edi ; recover address 4424 <1> ;mov cl, [CRT_COLS] 4425 <1> ;add cl, cl 4426 <1> ;mov ecx, 80*2 4427 0000172F B1A0 <1> mov cl, 80*2 4428 00001731 01CF <1> add edi, ecx 4429 00001733 FECE <1> dec dh 4430 00001735 75EE <1> jnz short n3x ; 16/01/2016 4431 <1> ; 4432 00001737 3A1D[96700000] <1> cmp bl, [active_page] 4433 0000173D 7507 <1> jne short n6 4434 <1> ;mov al, [CRT_MODE_SET] ; get the value of mode set 4435 0000173F B029 <1> mov al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3 4436 00001741 66BAD803 <1> mov dx, 03D8h ; always set color card port 4437 00001745 EE <1> out dx, al 4438 <1> n6: 4439 00001746 C3 <1> retn 4440 <1> 4441 <1> 4442 <1> write_c_current: 4443 <1> ; 30/08/2014 (Retro UNIX 386 v1) 4444 <1> ; 18/01/2014 4445 <1> ; 04/12/2013 4446 <1> ; 4447 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4448 <1> ; 4449 <1> ; WRITE_C_CURRENT 4450 <1> ; THIS ROUTINE WRITES THE CHARACTER AT 4451 <1> ; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED 4452 <1> ; INPUT 4453 <1> ; (AH) = CURRENT CRT MODE 4454 <1> ; (BH) = DISPLAY PAGE 4455 <1> ; (CX) = COUNT OF CHARACTERS TO WRITE 4456 <1> ; (AL) = CHAR TO WRITE 4457 <1> ; (DS) = DATA SEGMENT 4458 <1> ; (ES) = REGEN SEGMENT 4459 <1> ; OUTPUT 4460 <1> ; DISPLAY REGEN BUFFER UPDATED 4461 <1> 4462 00001747 FA <1> cli 4463 <1> ; bl = video page 4464 <1> ; al = character 4465 <1> ; ah = color/attribute 4466 00001748 6652 <1> push dx 4467 0000174A 6650 <1> push ax ; save character & attribute/color 4468 0000174C E80AFFFFFF <1> call find_position ; get regen location and port address 4469 <1> ; esi = regen location 4470 <1> ; dx = status port 4471 <1> ; 4472 <1> ; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE 4473 <1> ; 4474 <1> p41: ; wait for horizontal retrace is low or vertical 4475 00001751 FB <1> sti ; enable interrupts first 4476 00001752 3A1D[96700000] <1> cmp bl, [active_page] 4477 00001758 7510 <1> jne short p44 4478 0000175A FA <1> cli ; block interrupts for single loop 4479 0000175B EC <1> in al, dx ; get status from the adapter 4480 0000175C A808 <1> test al, RVRT ; check for vertical retrace first 4481 0000175E 7509 <1> jnz short p43 ; Do fast write now if vertical retrace 4482 00001760 A801 <1> test al, RHRZ ; is horizontal retrace low 4483 00001762 75ED <1> jnz short p41 ; wait until it is 4484 <1> p42: ; wait for either retrace high 4485 00001764 EC <1> in al, dx ; get status again 4486 00001765 A809 <1> test al, RVRT+RHRZ ; is horizontal or vertical retrace high 4487 00001767 74FB <1> jz short p42 ; wait until either retrace active 4488 <1> p43: 4489 00001769 FB <1> sti 4490 <1> p44: 4491 0000176A 6658 <1> pop ax ; restore the character (al) & attribute (ah) 4492 0000176C 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (crt_base) 4493 <1> ; Retro UNIX 386 v1 feature only! 4494 00001772 668906 <1> mov [esi], ax 4495 00001775 665A <1> pop dx 4496 00001777 C3 <1> retn 4497 <1> 4498 <1> set_mode: 4499 <1> ; 16/01/2016 4500 <1> ; 02/09/2014 (Retro UNIX 386 v1) 4501 <1> ; 4502 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4503 <1> 4504 <1> ;------------------------------------------------------ 4505 <1> ; SET MODE : 4506 <1> ; THIS ROUTINE INITIALIZES THE ATTACHMENT TO : 4507 <1> ; THE SELECTED MODE, THE SCREEN IS BLANKED. : 4508 <1> ; INPUT : 4509 <1> ; (AL) - MODE SELECTED (RANGE 0-7) : 4510 <1> ; OUTPUT : 4511 <1> ; NONE : 4512 <1> ;------------------------------------------------------ 4513 <1> 4514 00001778 57 <1> push edi ; 16/01/2016 4515 00001779 53 <1> push ebx 4516 0000177A 52 <1> push edx 4517 0000177B 51 <1> push ecx ; 16/01/2016 4518 0000177C 50 <1> push eax 4519 <1> 4520 <1> ;mov dx, 03D4h ; address or color card 4521 0000177D B003 <1> mov al, 3 4522 <1> ;M8: 4523 0000177F A2[506A0000] <1> mov [CRT_MODE], al ; save mode in global variable 4524 00001784 B029 <1> mov al, 29h 4525 <1> ;mov [CRT_MODE_SET], al ; save the mode set value 4526 00001786 2437 <1> and al, 037h ; video off, save high resolution bit 4527 <1> ;push dx ; save port value 4528 <1> ;add dx, 4 ; point to control register 4529 00001788 66BAD803 <1> mov dx, 3D8h 4530 0000178C EE <1> out dx, al ; reset video to off to suppress rolling 4531 <1> ;pop dx 4532 <1> ;M9: 4533 0000178D BB[886A0000] <1> mov ebx, video_params ; initialization table 4534 <1> ;mov ax, [ebx+10] ; get the cursor mode from the table 4535 <1> ;xchg ah, al 4536 <1> ;mov [CURSOR_MODE], ax ; save cursor mode 4537 00001792 30E4 <1> xor ah, ah ; ah is register number during loop 4538 <1> 4539 <1> ;----- LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE 4540 00001794 B910000000 <1> mov ecx, 16 ; 16/01/2016 4541 <1> M10: ; initialization loop 4542 00001799 88E0 <1> mov al, ah ; get 6845 register number 4543 0000179B EE <1> out dx, al 4544 0000179C 6642 <1> inc dx ; point to data port 4545 0000179E FEC4 <1> inc ah ; next register value 4546 000017A0 8A03 <1> mov al, [ebx] ; get table value 4547 000017A2 EE <1> out dx, al ; out to chip 4548 000017A3 43 <1> inc ebx ; next in table 4549 000017A4 664A <1> dec dx ; back to pointer register 4550 000017A6 E2F1 <1> loop M10 ; do the whole table 4551 <1> 4552 <1> ;----- FILL REGEN AREA WITH BLANK 4553 <1> ;xor ax, ax 4554 <1> ;mov [CRT_START], ax ; start address saved in global 4555 <1> ;mov [ACTIVE_PAGE], al ; 0 ; (re)set page value 4556 <1> ;mov ecx, 8192 ; number of words in color card 4557 <1> ; black background, light gray characeter color, space character 4558 <1> ;mov ax, 0720h ; fill char for alpha - attribute 4559 <1> ;M13: ; clear buffer 4560 <1> ;add edi, 0B8000h ; [crt_base] 4561 <1> ;rep stosw ; FILL THE REGEN BUFFER WITH BLANKS 4562 <1> 4563 <1> ;----- ENABLE VIDEO AND CORRECT PORT SETTING 4564 <1> ;mov dx, 3D4h ; mov dx, word [ADDR_6845] 4565 <1> ; prepare to output to video enable port 4566 <1> ;add dx,4 ; point to the mode control gerister 4567 000017A8 66BAD803 <1> mov dx, 3D8h 4568 <1> ;mov al, [CRT_MODE_SET] ; get the mode set value 4569 000017AC B029 <1> mov al, 29h 4570 000017AE EE <1> out dx, al ; set video enable port 4571 <1> 4572 <1> ;----- DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY 4573 <1> ;----- AND THE NUMBER TO BE USED FOR TTY INTERFACE 4574 <1> ; 4575 <1> ;mov byte [CRT_COLS], 80h ; initialize number of columns count 4576 <1> ; 4577 <1> ;----- SET CURSOR POSITIONS 4578 <1> ;push edi 4579 <1> ;mov word [CRT_LEN], 80*25*2 4580 000017AF BF[86700000] <1> mov edi, cursor_posn 4581 000017B4 B904000000 <1> mov ecx, 4 ; clear all cursor positions (16 bytes) 4582 000017B9 31C0 <1> xor eax, eax 4583 000017BB F3AB <1> rep stosd ; fill with zeroes 4584 <1> ;pop edi 4585 <1> 4586 <1> ;----- SET UP OVERSCAN REGISTER 4587 000017BD 6642 <1> inc dx ; set overscan port to a default 4588 000017BF B030 <1> mov al, 30h ; 30H valuye for all modes except 640X200 bw 4589 <1> ;M14: 4590 000017C1 EE <1> out dx, al ; output the correct value to 3D9 port 4591 <1> ;mov [CRT_PALETTE], al ; save the value for future use 4592 <1> 4593 <1> ;----- NORMAL RETURN FROM ALL VIDEO RETURNS 4594 <1> ; 4595 000017C2 58 <1> pop eax 4596 000017C3 59 <1> pop ecx ; 16/01/2016 4597 000017C4 5A <1> pop edx 4598 000017C5 5B <1> pop ebx 4599 000017C6 5F <1> pop edi ; 16/01/2016 4600 000017C7 C3 <1> retn 4601 <1> 4602 <1> tty_sw: 4603 <1> ; 30/06/2015 4604 <1> ; 27/06/2015 4605 <1> ; 07/09/2014 4606 <1> ; 02/09/2014 (Retro UNIX 386 v1 - beginning) 4607 <1> ; 4608 <1> ; (Modified registers : EAX) 4609 <1> ; 4610 <1> ;mov byte [u.quant], 0 ; 04/03/2014 4611 <1> ; 4612 <1> ;act_disp_page: 4613 <1> ; 30/06/2015 4614 <1> ; 04/03/2014 (act_disp_page --> tty_sw) 4615 <1> ; 10/12/2013 4616 <1> ; 04/12/2013 4617 <1> ; 4618 <1> ; VIDEO.ASM - 06/10/85 VIDEO DISPLAY BIOS 4619 <1> ; 4620 <1> ; ACT_DISP_PAGE 4621 <1> ; THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING 4622 <1> ; THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT 4623 <1> ; INPUT 4624 <1> ; AL HAS THE NEW ACTIVE DISPLAY PAGE 4625 <1> ; OUTPUT 4626 <1> ; THE 6845 IS RESET TO DISPLAY THAT PAGE 4627 <1> 4628 <1> ;cli 4629 <1> 4630 000017C8 53 <1> push ebx 4631 000017C9 6651 <1> push cx 4632 000017CB 6652 <1> push dx 4633 <1> ; 4634 000017CD A2[96700000] <1> mov [active_page], al ; save active page value ; [ptty] 4635 <1> ;mov cx, [CRT_LEN] ; get saved length of regen buffer 4636 000017D2 66B9A00F <1> mov cx, 25*80*2 4637 <1> ; 27/06/2015 4638 000017D6 0FB6D8 <1> movzx ebx, al 4639 <1> ; 4640 000017D9 6698 <1> cbw ; 07/09/2014 (ah=0) 4641 000017DB 66F7E1 <1> mul cx ; display page times regen length 4642 <1> ; 10/12/2013 4643 000017DE 66A3[84700000] <1> mov [CRT_START], ax ; save start address for later 4644 000017E4 6689C1 <1> mov cx, ax ; start address to cx 4645 <1> ;sar cx, 1 4646 000017E7 66D1E9 <1> shr cx, 1 ; divide by 2 for 6845 handling 4647 000017EA B40C <1> mov ah, 12 ; 6845 register for start address 4648 000017EC E838FEFFFF <1> call m16 4649 <1> ;sal bx, 1 4650 <1> ; 01/09/2014 4651 000017F1 D0E3 <1> shl bl, 1 ; *2 for word offset 4652 000017F3 81C3[86700000] <1> add ebx, cursor_posn 4653 000017F9 668B13 <1> mov dx, [ebx] ; get cursor for this page 4654 000017FC E814FEFFFF <1> call m18 4655 <1> ; 4656 00001801 665A <1> pop dx 4657 00001803 6659 <1> pop cx 4658 00001805 5B <1> pop ebx 4659 <1> ; 4660 <1> ;sti 4661 <1> ; 4662 00001806 C3 <1> retn 4663 <1> 4664 <1> ; % include 'vidata.inc' ; VIDEO DATA ; 11/03/2015 4665 <1> 4666 <1> 4667 <1> ; /// End Of VIDEO FUNCTIONS /// 4668 4669 setup_rtc_int: 4670 ; source: http://wiki.osdev.org/RTC 4671 00001807 FA cli ; disable interrupts 4672 ; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6) 4673 ; in order to change this ... 4674 ; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024 4675 ; (rate must be above 2 and not over 15) 4676 ; new rate = 15 --> 32768 >> (15-1) = 2 Hz 4677 00001808 B08A mov al, 8Ah 4678 0000180A E670 out 70h, al ; set index to register A, disable NMI 4679 0000180C 90 nop 4680 0000180D E471 in al, 71h ; get initial value of register A 4681 0000180F 88C4 mov ah, al 4682 00001811 80E4F0 and ah, 0F0h 4683 00001814 B08A mov al, 8Ah 4684 00001816 E670 out 70h, al ; reset index to register A 4685 00001818 88E0 mov al, ah 4686 0000181A 0C0F or al, 0Fh ; new rate (0Fh -> 15) 4687 0000181C E671 out 71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 4688 ; enable RTC interrupt 4689 0000181E B08B mov al, 8Bh ; 4690 00001820 E670 out 70h, al ; select register B and disable NMI 4691 00001822 90 nop 4692 00001823 E471 in al, 71h ; read the current value of register B 4693 00001825 88C4 mov ah, al ; 4694 00001827 B08B mov al, 8Bh ; 4695 00001829 E670 out 70h, al ; set the index again (a read will reset the index to register B) 4696 0000182B 88E0 mov al, ah ; 4697 0000182D 0C40 or al, 40h ; 4698 0000182F E671 out 71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B 4699 00001831 FB sti 4700 00001832 C3 retn 4701 4702 ; Write memory information 4703 ; Temporary Code 4704 ; 06/11/2014 4705 ; 14/08/2015 4706 memory_info: 4707 00001833 A1[6C700000] mov eax, [memory_size] ; in pages 4708 00001838 50 push eax 4709 00001839 C1E00C shl eax, 12 ; in bytes 4710 0000183C BB0A000000 mov ebx, 10 4711 00001841 89D9 mov ecx, ebx ; 10 4712 00001843 BE[CD6C0000] mov esi, mem_total_b_str 4713 00001848 E8B2000000 call bintdstr 4714 0000184D 58 pop eax 4715 0000184E B107 mov cl, 7 4716 00001850 BE[F16C0000] mov esi, mem_total_p_str 4717 00001855 E8A5000000 call bintdstr 4718 ; 14/08/2015 4719 0000185A E8BD000000 call calc_free_mem 4720 ; edx = calculated free pages 4721 ; ecx = 0 4722 0000185F A1[70700000] mov eax, [free_pages] 4723 00001864 39D0 cmp eax, edx ; calculated free mem value 4724 ; and initial free mem value are same or not? 4725 00001866 751D jne short pmim ; print mem info with '?' if not 4726 00001868 52 push edx ; free memory in pages 4727 ;mov eax, edx 4728 00001869 C1E00C shl eax, 12 ; convert page count 4729 ; to byte count 4730 0000186C B10A mov cl, 10 4731 0000186E BE[116D0000] mov esi, free_mem_b_str 4732 00001873 E887000000 call bintdstr 4733 00001878 58 pop eax 4734 00001879 B107 mov cl, 7 4735 0000187B BE[356D0000] mov esi, free_mem_p_str 4736 00001880 E87A000000 call bintdstr 4737 pmim: 4738 00001885 BE[BB6C0000] mov esi, msg_memory_info 4739 pmim_nb: 4740 0000188A AC lodsb 4741 0000188B 08C0 or al, al 4742 0000188D 740D jz short pmim_ok 4743 0000188F 56 push esi 4744 00001890 31DB xor ebx, ebx ; 0 4745 ; Video page 0 (bl=0) 4746 00001892 B407 mov ah, 07h ; Black background, 4747 ; light gray forecolor 4748 00001894 E841FCFFFF call write_tty 4749 00001899 5E pop esi 4750 0000189A EBEE jmp short pmim_nb 4751 pmim_ok: 4752 0000189C C3 retn 4753 4754 ; Convert binary number to hexadecimal string 4755 ; 10/05/2015 4756 ; dsectpm.s (28/02/2015) 4757 ; Retro UNIX 386 v1 - Kernel v0.2.0.6 4758 ; 01/12/2014 4759 ; 25/11/2014 4760 ; 4761 bytetohex: 4762 ; INPUT -> 4763 ; AL = byte (binary number) 4764 ; OUTPUT -> 4765 ; AX = hexadecimal string 4766 ; 4767 0000189D 53 push ebx 4768 0000189E 31DB xor ebx, ebx 4769 000018A0 88C3 mov bl, al 4770 000018A2 C0EB04 shr bl, 4 4771 000018A5 8A9B[EF180000] mov bl, [ebx+hexchrs] 4772 000018AB 86D8 xchg bl, al 4773 000018AD 80E30F and bl, 0Fh 4774 000018B0 8AA3[EF180000] mov ah, [ebx+hexchrs] 4775 000018B6 5B pop ebx 4776 000018B7 C3 retn 4777 4778 wordtohex: 4779 ; INPUT -> 4780 ; AX = word (binary number) 4781 ; OUTPUT -> 4782 ; EAX = hexadecimal string 4783 ; 4784 000018B8 53 push ebx 4785 000018B9 31DB xor ebx, ebx 4786 000018BB 86E0 xchg ah, al 4787 000018BD 6650 push ax 4788 000018BF 88E3 mov bl, ah 4789 000018C1 C0EB04 shr bl, 4 4790 000018C4 8A83[EF180000] mov al, [ebx+hexchrs] 4791 000018CA 88E3 mov bl, ah 4792 000018CC 80E30F and bl, 0Fh 4793 000018CF 8AA3[EF180000] mov ah, [ebx+hexchrs] 4794 000018D5 C1E010 shl eax, 16 4795 000018D8 6658 pop ax 4796 000018DA 5B pop ebx 4797 000018DB EBC0 jmp short bytetohex 4798 ;mov bl, al 4799 ;shr bl, 4 4800 ;mov bl, [ebx+hexchrs] 4801 ;xchg bl, al 4802 ;and bl, 0Fh 4803 ;mov ah, [ebx+hexchrs] 4804 ;pop ebx 4805 ;retn 4806 4807 dwordtohex: 4808 ; INPUT -> 4809 ; EAX = dword (binary number) 4810 ; OUTPUT -> 4811 ; EDX:EAX = hexadecimal string 4812 ; 4813 000018DD 50 push eax 4814 000018DE C1E810 shr eax, 16 4815 000018E1 E8D2FFFFFF call wordtohex 4816 000018E6 89C2 mov edx, eax 4817 000018E8 58 pop eax 4818 000018E9 E8CAFFFFFF call wordtohex 4819 000018EE C3 retn 4820 4821 ; 10/05/2015 4822 hex_digits: 4823 hexchrs: 4824 000018EF 303132333435363738- db '0123456789ABCDEF' 4825 000018F8 39414243444546 4826 4827 ; Convert binary number to decimal/numeric string 4828 ; 06/11/2014 4829 ; Temporary Code 4830 ; 4831 4832 bintdstr: 4833 ; EAX = binary number 4834 ; ESI = decimal/numeric string address 4835 ; EBX = divisor (10) 4836 ; ECX = string length (<=10) 4837 000018FF 01CE add esi, ecx 4838 btdstr0: 4839 00001901 4E dec esi 4840 00001902 31D2 xor edx, edx 4841 00001904 F7F3 div ebx 4842 00001906 80C230 add dl, 30h 4843 00001909 8816 mov [esi], dl 4844 0000190B FEC9 dec cl 4845 0000190D 740C jz btdstr2 4846 0000190F 09C0 or eax, eax 4847 00001911 75EE jnz short btdstr0 4848 btdstr1: 4849 00001913 4E dec esi 4850 00001914 C60620 mov byte [esi], 20h ; blank space 4851 00001917 FEC9 dec cl 4852 00001919 75F8 jnz short btdstr1 4853 btdstr2: 4854 0000191B C3 retn 4855 4856 ; Calculate free memory pages on M.A.T. 4857 ; 06/11/2014 4858 ; Temporary Code 4859 ; 4860 4861 calc_free_mem: 4862 0000191C 31D2 xor edx, edx 4863 ;xor ecx, ecx 4864 0000191E 668B0D[80700000] mov cx, [mat_size] ; in pages 4865 00001925 C1E10A shl ecx, 10 ; 1024 dwords per page 4866 00001928 BE00001000 mov esi, MEM_ALLOC_TBL 4867 cfm0: 4868 0000192D AD lodsd 4869 0000192E 51 push ecx 4870 0000192F B920000000 mov ecx, 32 4871 cfm1: 4872 00001934 D1E8 shr eax, 1 4873 00001936 7301 jnc short cfm2 4874 00001938 42 inc edx 4875 cfm2: 4876 00001939 E2F9 loop cfm1 4877 0000193B 59 pop ecx 4878 0000193C E2EF loop cfm0 4879 0000193E C3 retn 4880 4881 %include 'diskio.inc' ; 07/03/2015 4882 <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC 4883 <1> ; Last Modification: 04/02/2016 4884 <1> ; (Initialized Disk Parameters Data is in 'DISKDATA.INC') 4885 <1> ; (Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 4886 <1> 4887 <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project) 4888 <1> 4889 <1> ; ///////// DISK I/O SYSTEM /////////////// 4890 <1> 4891 <1> ; 06/02/2015 4892 <1> diskette_io: 4893 0000193F 9C <1> pushfd 4894 00001940 0E <1> push cs 4895 00001941 E809000000 <1> call DISKETTE_IO_1 4896 00001946 C3 <1> retn 4897 <1> 4898 <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;; 4899 <1> ;////////////////////////////////////////////////////// 4900 <1> 4901 <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project) 4902 <1> ; 20/02/2015 4903 <1> ; 06/02/2015 (unix386.s) 4904 <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s) 4905 <1> ; 4906 <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC) 4907 <1> ; 4908 <1> ; ADISK.EQU 4909 <1> 4910 <1> ;----- Wait control constants 4911 <1> 4912 <1> ;amount of time to wait while RESET is active. 4913 <1> 4914 <1> WAITCPU_RESET_ON EQU 21 ;Reset on must last at least 14us 4915 <1> ;at 250 KBS xfer rate. 4916 <1> ;see INTEL MCS, 1985, pg. 5-456 4917 <1> 4918 <1> WAITCPU_FOR_STATUS EQU 100 ;allow 30 microseconds for 4919 <1> ;status register to become valid 4920 <1> ;before re-reading. 4921 <1> 4922 <1> ;After sending a byte to NEC, status register may remain 4923 <1> ;incorrectly set for 24 us. 4924 <1> 4925 <1> WAITCPU_RQM_LOW EQU 24 ;number of loops to check for 4926 <1> ;RQM low. 4927 <1> 4928 <1> ; COMMON.MAC 4929 <1> ; 4930 <1> ; Timing macros 4931 <1> ; 4932 <1> 4933 <1> %macro SIODELAY 0 ; SHORT IODELAY 4934 <1> jmp short $+2 4935 <1> %endmacro 4936 <1> 4937 <1> %macro IODELAY 0 ; NORMAL IODELAY 4938 <1> jmp short $+2 4939 <1> jmp short $+2 4940 <1> %endmacro 4941 <1> 4942 <1> %macro NEWIODELAY 0 4943 <1> out 0ebh,al 4944 <1> %endmacro 4945 <1> 4946 <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ) 4947 <1> ;;; WAIT_FOR_MEM 4948 <1> ;WAIT_FDU_INT_LO equ 017798 ; 2.5 secs in 30 micro units. 4949 <1> ;WAIT_FDU_INT_HI equ 1 4950 <1> WAIT_FDU_INT_LH equ 83334 ; 27/02/2015 (2.5 seconds waiting) 4951 <1> ;;; WAIT_FOR_PORT 4952 <1> ;WAIT_FDU_SEND_LO equ 16667 ; .5 secons in 30 us units. 4953 <1> ;WAIT_FDU_SEND_HI equ 0 4954 <1> WAIT_FDU_SEND_LH equ 16667 ; 27/02/2015 4955 <1> ;Time to wait while waiting for each byte of NEC results = .5 4956 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 4957 <1> ;WAIT_FDU_RESULTS_LO equ 16667 ; .5 seconds in 30 micro units. 4958 <1> ;WAIT_FDU_RESULTS_HI equ 0 4959 <1> WAIT_FDU_RESULTS_LH equ 16667 ; 27/02/2015 4960 <1> ;;; WAIT_REFRESH 4961 <1> ;amount of time to wait for head settle, per unit in parameter 4962 <1> ;table = 1 ms. 4963 <1> WAIT_FDU_HEAD_SETTLE equ 33 ; 1 ms in 30 micro units. 4964 <1> 4965 <1> 4966 <1> ; //////////////// DISKETTE I/O //////////////// 4967 <1> 4968 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC) 4969 <1> 4970 <1> ;---------------------------------------- 4971 <1> ; EQUATES USED BY POST AND BIOS : 4972 <1> ;---------------------------------------- 4973 <1> 4974 <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------ 4975 <1> ;PORT_A EQU 060H ; 8042 KEYBOARD SCAN CODE/CONTROL PORT 4976 <1> ;PORT_B EQU 061H ; PORT B READ/WRITE DIAGNOSTIC REGISTER 4977 <1> ;REFRESH_BIT EQU 00010000B ; REFRESH TEST BIT 4978 <1> 4979 <1> ;---------------------------------------- 4980 <1> ; CMOS EQUATES FOR THIS SYSTEM : 4981 <1> ;------------------------------------------------------------------------------- 4982 <1> ;CMOS_PORT EQU 070H ; I/O ADDRESS OF CMOS ADDRESS PORT 4983 <1> ;CMOS_DATA EQU 071H ; I/O ADDRESS OF CMOS DATA PORT 4984 <1> ;NMI EQU 10000000B ; DISABLE NMI INTERRUPTS MASK - 4985 <1> ; HIGH BIT OF CMOS LOCATION ADDRESS 4986 <1> 4987 <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## ----------------------------------- 4988 <1> CMOS_DISKETTE EQU 010H ; DISKETTE DRIVE TYPE BYTE ; 4989 <1> ; EQU 011H ; - RESERVED ;C 4990 <1> CMOS_DISK EQU 012H ; FIXED DISK TYPE BYTE ;H 4991 <1> ; EQU 013H ; - RESERVED ;E 4992 <1> CMOS_EQUIP EQU 014H ; EQUIPMENT WORD LOW BYTE ;C 4993 <1> 4994 <1> ;---------- DISKETTE EQUATES --------------------------------------------------- 4995 <1> INT_FLAG EQU 10000000B ; INTERRUPT OCCURRENCE FLAG 4996 <1> DSK_CHG EQU 10000000B ; DISKETTE CHANGE FLAG MASK BIT 4997 <1> DETERMINED EQU 00010000B ; SET STATE DETERMINED IN STATE BITS 4998 <1> HOME EQU 00010000B ; TRACK 0 MASK 4999 <1> SENSE_DRV_ST EQU 00000100B ; SENSE DRIVE STATUS COMMAND 5000 <1> TRK_SLAP EQU 030H ; CRASH STOP (48 TPI DRIVES) 5001 <1> QUIET_SEEK EQU 00AH ; SEEK TO TRACK 10 5002 <1> ;MAX_DRV EQU 2 ; MAX NUMBER OF DRIVES 5003 <1> HD12_SETTLE EQU 15 ; 1.2 M HEAD SETTLE TIME 5004 <1> HD320_SETTLE EQU 20 ; 320 K HEAD SETTLE TIME 5005 <1> MOTOR_WAIT EQU 37 ; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF 5006 <1> 5007 <1> ;---------- DISKETTE ERRORS ---------------------------------------------------- 5008 <1> ;TIME_OUT EQU 080H ; ATTACHMENT FAILED TO RESPOND 5009 <1> ;BAD_SEEK EQU 040H ; SEEK OPERATION FAILED 5010 <1> BAD_NEC EQU 020H ; DISKETTE CONTROLLER HAS FAILED 5011 <1> BAD_CRC EQU 010H ; BAD CRC ON DISKETTE READ 5012 <1> MED_NOT_FND EQU 00CH ; MEDIA TYPE NOT FOUND 5013 <1> DMA_BOUNDARY EQU 009H ; ATTEMPT TO DMA ACROSS 64K BOUNDARY 5014 <1> BAD_DMA EQU 008H ; DMA OVERRUN ON OPERATION 5015 <1> MEDIA_CHANGE EQU 006H ; MEDIA REMOVED ON DUAL ATTACH CARD 5016 <1> RECORD_NOT_FND EQU 004H ; REQUESTED SECTOR NOT FOUND 5017 <1> WRITE_PROTECT EQU 003H ; WRITE ATTEMPTED ON WRITE PROTECT DISK 5018 <1> BAD_ADDR_MARK EQU 002H ; ADDRESS MARK NOT FOUND 5019 <1> BAD_CMD EQU 001H ; BAD COMMAND PASSED TO DISKETTE I/O 5020 <1> 5021 <1> ;---------- DISK CHANGE LINE EQUATES ------------------------------------------- 5022 <1> NOCHGLN EQU 001H ; NO DISK CHANGE LINE AVAILABLE 5023 <1> CHGLN EQU 002H ; DISK CHANGE LINE AVAILABLE 5024 <1> 5025 <1> ;---------- MEDIA/DRIVE STATE INDICATORS --------------------------------------- 5026 <1> TRK_CAPA EQU 00000001B ; 80 TRACK CAPABILITY 5027 <1> FMT_CAPA EQU 00000010B ; MULTIPLE FORMAT CAPABILITY (1.2M) 5028 <1> DRV_DET EQU 00000100B ; DRIVE DETERMINED 5029 <1> MED_DET EQU 00010000B ; MEDIA DETERMINED BIT 5030 <1> DBL_STEP EQU 00100000B ; DOUBLE STEP BIT 5031 <1> RATE_MSK EQU 11000000B ; MASK FOR CLEARING ALL BUT RATE 5032 <1> RATE_500 EQU 00000000B ; 500 KBS DATA RATE 5033 <1> RATE_300 EQU 01000000B ; 300 KBS DATA RATE 5034 <1> RATE_250 EQU 10000000B ; 250 KBS DATA RATE 5035 <1> STRT_MSK EQU 00001100B ; OPERATION START RATE MASK 5036 <1> SEND_MSK EQU 11000000B ; MASK FOR SEND RATE BITS 5037 <1> 5038 <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY ------------------------- 5039 <1> M3D3U EQU 00000000B ; 360 MEDIA/DRIVE NOT ESTABLISHED 5040 <1> M3D1U EQU 00000001B ; 360 MEDIA,1.2DRIVE NOT ESTABLISHED 5041 <1> M1D1U EQU 00000010B ; 1.2 MEDIA/DRIVE NOT ESTABLISHED 5042 <1> MED_UNK EQU 00000111B ; NONE OF THE ABOVE 5043 <1> 5044 <1> ;---------- INTERRUPT EQUATES -------------------------------------------------- 5045 <1> ;EOI EQU 020H ; END OF INTERRUPT COMMAND TO 8259 5046 <1> ;INTA00 EQU 020H ; 8259 PORT 5047 <1> INTA01 EQU 021H ; 8259 PORT 5048 <1> INTB00 EQU 0A0H ; 2ND 8259 5049 <1> INTB01 EQU 0A1H ; 5050 <1> 5051 <1> ;------------------------------------------------------------------------------- 5052 <1> DMA08 EQU 008H ; DMA STATUS REGISTER PORT ADDRESS 5053 <1> DMA EQU 000H ; DMA CH.0 ADDRESS REGISTER PORT ADDRESS 5054 <1> DMA18 EQU 0D0H ; 2ND DMA STATUS PORT ADDRESS 5055 <1> DMA1 EQU 0C0H ; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS 5056 <1> ;------------------------------------------------------------------------------- 5057 <1> ;TIMER EQU 040H ; 8254 TIMER - BASE ADDRESS 5058 <1> 5059 <1> ;------------------------------------------------------------------------------- 5060 <1> DMA_PAGE EQU 081H ; START OF DMA PAGE REGISTERS 5061 <1> 5062 <1> ; 06/02/2015 (unix386.s, protected mode modifications) 5063 <1> ; (unix386.s <-- dsectrm2.s) 5064 <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC) 5065 <1> 5066 <1> ; 10/12/2014 5067 <1> ; 5068 <1> ;int40h: 5069 <1> ; pushf 5070 <1> ; push cs 5071 <1> ; ;cli 5072 <1> ; call DISKETTE_IO_1 5073 <1> ; retn 5074 <1> 5075 <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS 5076 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 5077 <1> ; 5078 <1> 5079 <1> ;-- INT13H --------------------------------------------------------------------- 5080 <1> ; DISKETTE I/O 5081 <1> ; THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB, 5082 <1> ; 1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES. 5083 <1> ; INPUT 5084 <1> ; (AH) = 00H RESET DISKETTE SYSTEM 5085 <1> ; HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED 5086 <1> ; ON ALL DRIVES 5087 <1> ;------------------------------------------------------------------------------- 5088 <1> ; (AH)= 01H READ THE STATUS OF THE SYSTEM INTO (AH) 5089 <1> ; @DISKETTE_STATUS FROM LAST OPERATION IS USED 5090 <1> ;------------------------------------------------------------------------------- 5091 <1> ; REGISTERS FOR READ/WRITE/VERIFY/FORMAT 5092 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 5093 <1> ; (DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED) 5094 <1> ; (CH) - TRACK NUMBER (NOT VALUE CHECKED) 5095 <1> ; MEDIA DRIVE TRACK NUMBER 5096 <1> ; 320/360 320/360 0-39 5097 <1> ; 320/360 1.2M 0-39 5098 <1> ; 1.2M 1.2M 0-79 5099 <1> ; 720K 720K 0-79 5100 <1> ; 1.44M 1.44M 0-79 5101 <1> ; (CL) - SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT) 5102 <1> ; MEDIA DRIVE SECTOR NUMBER 5103 <1> ; 320/360 320/360 1-8/9 5104 <1> ; 320/360 1.2M 1-8/9 5105 <1> ; 1.2M 1.2M 1-15 5106 <1> ; 720K 720K 1-9 5107 <1> ; 1.44M 1.44M 1-18 5108 <1> ; (AL) NUMBER OF SECTORS (NOT VALUE CHECKED) 5109 <1> ; MEDIA DRIVE MAX NUMBER OF SECTORS 5110 <1> ; 320/360 320/360 8/9 5111 <1> ; 320/360 1.2M 8/9 5112 <1> ; 1.2M 1.2M 15 5113 <1> ; 720K 720K 9 5114 <1> ; 1.44M 1.44M 18 5115 <1> ; 5116 <1> ; (ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY) 5117 <1> ; 5118 <1> ;------------------------------------------------------------------------------- 5119 <1> ; (AH)= 02H READ THE DESIRED SECTORS INTO MEMORY 5120 <1> ;------------------------------------------------------------------------------- 5121 <1> ; (AH)= 03H WRITE THE DESIRED SECTORS FROM MEMORY 5122 <1> ;------------------------------------------------------------------------------- 5123 <1> ; (AH)= 04H VERIFY THE DESIRED SECTORS 5124 <1> ;------------------------------------------------------------------------------- 5125 <1> ; (AH)= 05H FORMAT THE DESIRED TRACK 5126 <1> ; (ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS 5127 <1> ; FOR THE TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N), 5128 <1> ; WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 5129 <1> ; N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024), 5130 <1> ; THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK. 5131 <1> ; THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 5132 <1> ; READ/WRITE ACCESS. 5133 <1> ; PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN 5134 <1> ; ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION, 5135 <1> ; THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE' 5136 <1> ; (INT 13H, AH = 18H) MUST BE CALLED TO SET THE DISKETTE TYPE 5137 <1> ; THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE" 5138 <1> ; IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 5139 <1> ; MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE. 5140 <1> ; 5141 <1> ; THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO 5142 <1> ; FORMAT THE FOLLOWING MEDIAS: 5143 <1> ; --------------------------------------------- 5144 <1> ; : MEDIA : DRIVE : PARM 1 : PARM 2 : 5145 <1> ; --------------------------------------------- 5146 <1> ; : 320K : 320K/360K/1.2M : 50H : 8 : 5147 <1> ; : 360K : 320K/360K/1.2M : 50H : 9 : 5148 <1> ; : 1.2M : 1.2M : 54H : 15 : 5149 <1> ; : 720K : 720K/1.44M : 50H : 9 : 5150 <1> ; : 1.44M : 1.44M : 6CH : 18 : 5151 <1> ; --------------------------------------------- 5152 <1> ; NOTES: - PARM 1 = GAP LENGTH FOR FORMAT 5153 <1> ; - PARM 2 = EOT (LAST SECTOR ON TRACK) 5154 <1> ; - DISK BASE IS POINTED BY DISK POINTER LOCATED 5155 <1> ; AT ABSOLUTE ADDRESS 0:78. 5156 <1> ; - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS 5157 <1> ; SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES. 5158 <1> ;------------------------------------------------------------------------------- 5159 <1> ; (AH) = 08H READ DRIVE PARAMETERS 5160 <1> ; REGISTERS 5161 <1> ; INPUT 5162 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 5163 <1> ; OUTPUT 5164 <1> ; (ES:DI) POINTS TO DRIVE PARAMETER TABLE 5165 <1> ; (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS 5166 <1> ; (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS 5167 <1> ; BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK 5168 <1> ; (DH) - MAXIMUM HEAD NUMBER 5169 <1> ; (DL) - NUMBER OF DISKETTE DRIVES INSTALLED 5170 <1> ; (BH) - 0 5171 <1> ; (BL) - BITS 7 THRU 4 - 0 5172 <1> ; BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS 5173 <1> ; (AX) - 0 5174 <1> ; UNDER THE FOLLOWING CIRCUMSTANCES: 5175 <1> ; (1) THE DRIVE NUMBER IS INVALID, 5176 <1> ; (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 5177 <1> ; (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD, 5178 <1> ; (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID 5179 <1> ; THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 5180 <1> ; IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0. 5181 <1> ; @DISKETTE_STATUS = 0 AND CY IS RESET. 5182 <1> ;------------------------------------------------------------------------------- 5183 <1> ; (AH)= 15H READ DASD TYPE 5184 <1> ; OUTPUT REGISTERS 5185 <1> ; (AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR 5186 <1> ; 00 - DRIVE NOT PRESENT 5187 <1> ; 01 - DISKETTE, NO CHANGE LINE AVAILABLE 5188 <1> ; 02 - DISKETTE, CHANGE LINE AVAILABLE 5189 <1> ; 03 - RESERVED (FIXED DISK) 5190 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 5191 <1> ;------------------------------------------------------------------------------- 5192 <1> ; (AH)= 16H DISK CHANGE LINE STATUS 5193 <1> ; OUTPUT REGISTERS 5194 <1> ; (AH) - 00 - DISK CHANGE LINE NOT ACTIVE 5195 <1> ; 06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON 5196 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED) 5197 <1> ;------------------------------------------------------------------------------- 5198 <1> ; (AH)= 17H SET DASD TYPE FOR FORMAT 5199 <1> ; INPUT REGISTERS 5200 <1> ; (AL) - 00 - NOT USED 5201 <1> ; 01 - DISKETTE 320/360K IN 360K DRIVE 5202 <1> ; 02 - DISKETTE 360K IN 1.2M DRIVE 5203 <1> ; 03 - DISKETTE 1.2M IN 1.2M DRIVE 5204 <1> ; 04 - DISKETTE 720K IN 720K DRIVE 5205 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED: 5206 <1> ; (DO NOT USE WHEN DISKETTE ATTACH CARD USED) 5207 <1> ;------------------------------------------------------------------------------- 5208 <1> ; (AH)= 18H SET MEDIA TYPE FOR FORMAT 5209 <1> ; INPUT REGISTERS 5210 <1> ; (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS 5211 <1> ; (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS 5212 <1> ; BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK 5213 <1> ; (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED) 5214 <1> ; OUTPUT REGISTERS: 5215 <1> ; (ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE, 5216 <1> ; UNCHANGED IF (AH) IS NON-ZERO 5217 <1> ; (AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED 5218 <1> ; - 01H, CY = 1, FUNCTION IS NOT AVAILABLE 5219 <1> ; - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED 5220 <1> ; - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT) 5221 <1> ;------------------------------------------------------------------------------- 5222 <1> ; DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER 5223 <1> ; THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE 5224 <1> ; ACTIVE THE FOLLOWING ACTIONS TAKE PLACE: 5225 <1> ; ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 5226 <1> ; IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 5227 <1> ; CHANGE ERROR CODE 5228 <1> ; IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 5229 <1> ; TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN. 5230 <1> ; IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT. 5231 <1> ; 5232 <1> ; DATA VARIABLE -- @DISK_POINTER 5233 <1> ; DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS 5234 <1> ;------------------------------------------------------------------------------- 5235 <1> ; OUTPUT FOR ALL FUNCTIONS 5236 <1> ; AH = STATUS OF OPERATION 5237 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS 5238 <1> ; VARIABLE IN THE DATA SEGMENT OF THIS MODULE 5239 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD 5240 <1> ; TYPE AH=(15)). 5241 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) 5242 <1> ; FOR READ/WRITE/VERIFY 5243 <1> ; DS,BX,DX,CX PRESERVED 5244 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 5245 <1> ; ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION. 5246 <1> ; ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 5247 <1> ; THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 5248 <1> ; PROBLEM IS NOT DUE TO MOTOR START-UP. 5249 <1> ;------------------------------------------------------------------------------- 5250 <1> ; 5251 <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B) 5252 <1> ; 5253 <1> ; ----------------------------------------------------------------- 5254 <1> ; | | | | | | | | | 5255 <1> ; | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 5256 <1> ; | | | | | | | | | 5257 <1> ; ----------------------------------------------------------------- 5258 <1> ; | | | | | | | | 5259 <1> ; | | | | | ----------------- 5260 <1> ; | | | | | | 5261 <1> ; | | | | RESERVED | 5262 <1> ; | | | | PRESENT STATE 5263 <1> ; | | | | 000: 360K IN 360K DRIVE UNESTABLISHED 5264 <1> ; | | | | 001: 360K IN 1.2M DRIVE UNESTABLISHED 5265 <1> ; | | | | 010: 1.2M IN 1.2M DRIVE UNESTABLISHED 5266 <1> ; | | | | 011: 360K IN 360K DRIVE ESTABLISHED 5267 <1> ; | | | | 100: 360K IN 1.2M DRIVE ESTABLISHED 5268 <1> ; | | | | 101: 1.2M IN 1.2M DRIVE ESTABLISHED 5269 <1> ; | | | | 110: RESERVED 5270 <1> ; | | | | 111: NONE OF THE ABOVE 5271 <1> ; | | | | 5272 <1> ; | | | ------> MEDIA/DRIVE ESTABLISHED 5273 <1> ; | | | 5274 <1> ; | | --------------> DOUBLE STEPPING REQUIRED (360K IN 1.2M 5275 <1> ; | | DRIVE) 5276 <1> ; | | 5277 <1> ; ------------------------------> DATA TRANSFER RATE FOR THIS DRIVE: 5278 <1> ; 5279 <1> ; 00: 500 KBS 5280 <1> ; 01: 300 KBS 5281 <1> ; 10: 250 KBS 5282 <1> ; 11: RESERVED 5283 <1> ; 5284 <1> ; 5285 <1> ;------------------------------------------------------------------------------- 5286 <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B) 5287 <1> ;------------------------------------------------------------------------------- 5288 <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B) 5289 <1> ;------------------------------------------------------------------------------- 5290 <1> 5291 <1> struc MD 5292 00000000 <1> .SPEC1 resb 1 ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 5293 00000001 <1> .SPEC2 resb 1 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 5294 00000002 <1> .OFF_TIM resb 1 ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 5295 00000003 <1> .BYT_SEC resb 1 ; 512 BYTES/SECTOR 5296 00000004 <1> .SEC_TRK resb 1 ; EOT (LAST SECTOR ON TRACK) 5297 00000005 <1> .GAP resb 1 ; GAP LENGTH 5298 00000006 <1> .DTL resb 1 ; DTL 5299 00000007 <1> .GAP3 resb 1 ; GAP LENGTH FOR FORMAT 5300 00000008 <1> .FIL_BYT resb 1 ; FILL BYTE FOR FORMAT 5301 00000009 <1> .HD_TIM resb 1 ; HEAD SETTLE TIME (MILLISECONDS) 5302 0000000A <1> .STR_TIM resb 1 ; MOTOR START TIME (1/8 SECONDS) 5303 0000000B <1> .MAX_TRK resb 1 ; MAX. TRACK NUMBER 5304 0000000C <1> .RATE resb 1 ; DATA TRANSFER RATE 5305 <1> endstruc 5306 <1> 5307 <1> BIT7OFF EQU 7FH 5308 <1> BIT7ON EQU 80H 5309 <1> 5310 <1> ;;int13h: ; 16/02/2015 5311 <1> ;; 16/02/2015 - 21/02/2015 5312 <1> int40h: 5313 00001947 9C <1> pushfd 5314 00001948 0E <1> push cs 5315 00001949 E801000000 <1> call DISKETTE_IO_1 5316 0000194E C3 <1> retn 5317 <1> 5318 <1> DISKETTE_IO_1: 5319 <1> 5320 0000194F FB <1> STI ; INTERRUPTS BACK ON 5321 00001950 55 <1> PUSH eBP ; USER REGISTER 5322 00001951 57 <1> PUSH eDI ; USER REGISTER 5323 00001952 52 <1> PUSH eDX ; HEAD #, DRIVE # OR USER REGISTER 5324 00001953 53 <1> PUSH eBX ; BUFFER OFFSET PARAMETER OR REGISTER 5325 00001954 51 <1> PUSH eCX ; TRACK #-SECTOR # OR USER REGISTER 5326 00001955 89E5 <1> MOV eBP,eSP ; BP => PARAMETER LIST DEP. ON AH 5327 <1> ; [BP] = SECTOR # 5328 <1> ; [BP+1] = TRACK # 5329 <1> ; [BP+2] = BUFFER OFFSET 5330 <1> ; FOR RETURN OF DRIVE PARAMETERS: 5331 <1> ; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL 5332 <1> ; BITS 0-5 MAX SECTORS/TRACK 5333 <1> ; CH/[BP+1] = LOW 8 BITS OF MAX CYL. 5334 <1> ; BL/[BP+2] = BITS 7-4 = 0 5335 <1> ; BITS 3-0 = VALID CMOS TYPE 5336 <1> ; BH/[BP+3] = 0 5337 <1> ; DL/[BP+4] = # DRIVES INSTALLED 5338 <1> ; DH/[BP+5] = MAX HEAD # 5339 <1> ; DI/[BP+6] = OFFSET TO DISK BASE 5340 00001957 06 <1> push es ; 06/02/2015 5341 00001958 1E <1> PUSH DS ; BUFFER SEGMENT PARM OR USER REGISTER 5342 00001959 56 <1> PUSH eSI ; USER REGISTERS 5343 <1> ;CALL DDS ; SEGMENT OF BIOS DATA AREA TO DS 5344 <1> ;mov cx, cs 5345 <1> ;mov ds, cx 5346 0000195A 66B91000 <1> mov cx, KDATA 5347 0000195E 8ED9 <1> mov ds, cx 5348 00001960 8EC1 <1> mov es, cx 5349 <1> 5350 <1> ;CMP AH,(FNC_TAE-FNC_TAB)/2 ; CHECK FOR > LARGEST FUNCTION 5351 00001962 80FC19 <1> cmp ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015 5352 00001965 7202 <1> JB short OK_FUNC ; FUNCTION OK 5353 00001967 B414 <1> MOV AH,14H ; REPLACE WITH KNOWN INVALID FUNCTION 5354 <1> OK_FUNC: 5355 00001969 80FC01 <1> CMP AH,1 ; RESET OR STATUS ? 5356 0000196C 760C <1> JBE short OK_DRV ; IF RESET OR STATUS DRIVE ALWAYS OK 5357 0000196E 80FC08 <1> CMP AH,8 ; READ DRIVE PARMS ? 5358 00001971 7407 <1> JZ short OK_DRV ; IF SO DRIVE CHECKED LATER 5359 00001973 80FA01 <1> CMP DL,1 ; DRIVES 0 AND 1 OK 5360 00001976 7602 <1> JBE short OK_DRV ; IF 0 OR 1 THEN JUMP 5361 00001978 B414 <1> MOV AH,14H ; REPLACE WITH KNOWN INVALID FUNCTION 5362 <1> OK_DRV: 5363 0000197A 31C9 <1> xor ecx, ecx 5364 <1> ;mov esi, ecx ; 08/02/2015 5365 0000197C 89CF <1> mov edi, ecx ; 08/02/2015 5366 0000197E 88E1 <1> MOV CL,AH ; CL = FUNCTION 5367 <1> ;XOR CH,CH ; CX = FUNCTION 5368 <1> ;SHL CL, 1 ; FUNCTION TIMES 2 5369 00001980 C0E102 <1> SHL CL, 2 ; 20/02/2015 ; FUNCTION TIMES 4 (for 32 bit offset) 5370 00001983 BB[BB190000] <1> MOV eBX,FNC_TAB ; LOAD START OF FUNCTION TABLE 5371 00001988 01CB <1> ADD eBX,eCX ; ADD OFFSET INTO TABLE => ROUTINE 5372 0000198A 88F4 <1> MOV AH,DH ; AX = HEAD #,# OF SECTORS OR DASD TYPE 5373 0000198C 30F6 <1> XOR DH,DH ; DX = DRIVE # 5374 0000198E 6689C6 <1> MOV SI,AX ; SI = HEAD #,# OF SECTORS OR DASD TYPE 5375 00001991 6689D7 <1> MOV DI,DX ; DI = DRIVE # 5376 <1> ; 5377 <1> ; 11/12/2014 5378 00001994 8815[116B0000] <1> mov [cfd], dl ; current floppy drive (for 'GET_PARM') 5379 <1> ; 5380 0000199A 8A25[EC700000] <1> MOV AH, [DSKETTE_STATUS] ; LOAD STATUS TO AH FOR STATUS FUNCTION 5381 000019A0 C605[EC700000]00 <1> MOV byte [DSKETTE_STATUS],0 ; INITIALIZE FOR ALL OTHERS 5382 <1> 5383 <1> ; THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN 5384 <1> ; THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS 5385 <1> ; FUNCTIONS REQUIRE ALL OF THESE PARAMETERS. 5386 <1> ; 5387 <1> ; DI : DRIVE # 5388 <1> ; SI-HI : HEAD # 5389 <1> ; SI-LOW : # OF SECTORS OR DASD TYPE FOR FORMAT 5390 <1> ; ES : BUFFER SEGMENT 5391 <1> ; [BP] : SECTOR # 5392 <1> ; [BP+1] : TRACK # 5393 <1> ; [BP+2] : BUFFER OFFSET 5394 <1> ; 5395 <1> ; ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 5396 <1> ; SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 5397 <1> ; CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 5398 <1> ; SPECIFIC ERROR CODE. 5399 <1> ; 5400 <1> ; (AH) = @DSKETTE_STATUS 5401 000019A7 FF13 <1> CALL dWORD [eBX] ; CALL THE REQUESTED FUNCTION 5402 000019A9 5E <1> POP eSI ; RESTORE ALL REGISTERS 5403 000019AA 1F <1> POP DS 5404 000019AB 07 <1> pop es ; 06/02/2015 5405 000019AC 59 <1> POP eCX 5406 000019AD 5B <1> POP eBX 5407 000019AE 5A <1> POP eDX 5408 000019AF 5F <1> POP eDI 5409 000019B0 89E5 <1> MOV eBP, eSP 5410 000019B2 50 <1> PUSH eAX 5411 000019B3 9C <1> PUSHFd 5412 000019B4 58 <1> POP eAX 5413 <1> ;MOV [BP+6], AX 5414 000019B5 89450C <1> mov [ebp+12], eax ; 18/02/2015, flags 5415 000019B8 58 <1> POP eAX 5416 000019B9 5D <1> POP eBP 5417 000019BA CF <1> IRETd 5418 <1> 5419 <1> ;------------------------------------------------------------------------------- 5420 <1> ; DW --> dd (06/02/2015) 5421 000019BB [1F1A0000] <1> FNC_TAB dd DSK_RESET ; AH = 00H; RESET 5422 000019BF [981A0000] <1> dd DSK_STATUS ; AH = 01H; STATUS 5423 000019C3 [A91A0000] <1> dd DSK_READ ; AH = 02H; READ 5424 000019C7 [BA1A0000] <1> dd DSK_WRITE ; AH = 03H; WRITE 5425 000019CB [CB1A0000] <1> dd DSK_VERF ; AH = 04H; VERIFY 5426 000019CF [DC1A0000] <1> dd DSK_FORMAT ; AH = 05H; FORMAT 5427 000019D3 [611B0000] <1> dd FNC_ERR ; AH = 06H; INVALID 5428 000019D7 [611B0000] <1> dd FNC_ERR ; AH = 07H; INVALID 5429 000019DB [6E1B0000] <1> dd DSK_PARMS ; AH = 08H; READ DRIVE PARAMETERS 5430 000019DF [611B0000] <1> dd FNC_ERR ; AH = 09H; INVALID 5431 000019E3 [611B0000] <1> dd FNC_ERR ; AH = 0AH; INVALID 5432 000019E7 [611B0000] <1> dd FNC_ERR ; AH = 0BH; INVALID 5433 000019EB [611B0000] <1> dd FNC_ERR ; AH = 0CH; INVALID 5434 000019EF [611B0000] <1> dd FNC_ERR ; AH = 0DH; INVALID 5435 000019F3 [611B0000] <1> dd FNC_ERR ; AH = 0EH; INVALID 5436 000019F7 [611B0000] <1> dd FNC_ERR ; AH = 0FH; INVALID 5437 000019FB [611B0000] <1> dd FNC_ERR ; AH = 10H; INVALID 5438 000019FF [611B0000] <1> dd FNC_ERR ; AH = 11H; INVALID 5439 00001A03 [611B0000] <1> dd FNC_ERR ; AH = 12H; INVALID 5440 00001A07 [611B0000] <1> dd FNC_ERR ; AH = 13H; INVALID 5441 00001A0B [611B0000] <1> dd FNC_ERR ; AH = 14H; INVALID 5442 00001A0F [2F1C0000] <1> dd DSK_TYPE ; AH = 15H; READ DASD TYPE 5443 00001A13 [5A1C0000] <1> dd DSK_CHANGE ; AH = 16H; CHANGE STATUS 5444 00001A17 [941C0000] <1> dd FORMAT_SET ; AH = 17H; SET DASD TYPE 5445 00001A1B [171D0000] <1> dd SET_MEDIA ; AH = 18H; SET MEDIA TYPE 5446 <1> FNC_TAE EQU $ ; END 5447 <1> 5448 <1> ;------------------------------------------------------------------------------- 5449 <1> ; DISK_RESET (AH = 00H) 5450 <1> ; RESET THE DISKETTE SYSTEM. 5451 <1> ; 5452 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5453 <1> ;------------------------------------------------------------------------------- 5454 <1> DSK_RESET: 5455 00001A1F 66BAF203 <1> MOV DX,03F2H ; ADAPTER CONTROL PORT 5456 00001A23 FA <1> CLI ; NO INTERRUPTS 5457 00001A24 A0[EA700000] <1> MOV AL,[MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 5458 00001A29 243F <1> AND AL,00111111B ; KEEP SELECTED AND MOTOR ON BITS 5459 00001A2B C0C004 <1> ROL AL,4 ; MOTOR VALUE TO HIGH NIBBLE 5460 <1> ; DRIVE SELECT TO LOW NIBBLE 5461 00001A2E 0C08 <1> OR AL,00001000B ; TURN ON INTERRUPT ENABLE 5462 00001A30 EE <1> OUT DX,AL ; RESET THE ADAPTER 5463 00001A31 C605[E9700000]00 <1> MOV byte [SEEK_STATUS],0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 5464 <1> ;JMP $+2 ; WAIT FOR I/O 5465 <1> ;JMP $+2 ; WAIT FOR I/O (TO INSURE MINIMUM 5466 <1> ; PULSE WIDTH) 5467 <1> ; 19/12/2014 5468 <1> NEWIODELAY 5469 00001A38 E6EB <2> out 0ebh,al 5470 <1> 5471 <1> ; 17/12/2014 5472 <1> ; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM) 5473 00001A3A B915000000 <1> mov ecx, WAITCPU_RESET_ON ; cx = 21 -- Min. 14 micro seconds !? 5474 <1> wdw1: 5475 <1> NEWIODELAY ; 27/02/2015 5476 00001A3F E6EB <2> out 0ebh,al 5477 00001A41 E2FC <1> loop wdw1 5478 <1> ; 5479 00001A43 0C04 <1> OR AL,00000100B ; TURN OFF RESET BIT 5480 00001A45 EE <1> OUT DX,AL ; RESET THE ADAPTER 5481 <1> ; 16/12/2014 5482 <1> IODELAY 5483 00001A46 EB00 <2> jmp short $+2 5484 00001A48 EB00 <2> jmp short $+2 5485 <1> ; 5486 <1> ;STI ; ENABLE THE INTERRUPTS 5487 00001A4A E8250C0000 <1> CALL WAIT_INT ; WAIT FOR THE INTERRUPT 5488 00001A4F 723E <1> JC short DR_ERR ; IF ERROR, RETURN IT 5489 00001A51 66B9C000 <1> MOV CX,11000000B ; CL = EXPECTED @NEC_STATUS 5490 <1> NXT_DRV: 5491 00001A55 6651 <1> PUSH CX ; SAVE FOR CALL 5492 00001A57 B8[8D1A0000] <1> MOV eAX, DR_POP_ERR ; LOAD NEC_OUTPUT ERROR ADDRESS 5493 00001A5C 50 <1> PUSH eAX ; " 5494 00001A5D B408 <1> MOV AH,08H ; SENSE INTERRUPT STATUS COMMAND 5495 00001A5F E8030B0000 <1> CALL NEC_OUTPUT 5496 00001A64 58 <1> POP eAX ; THROW AWAY ERROR RETURN 5497 00001A65 E83A0C0000 <1> CALL RESULTS ; READ IN THE RESULTS 5498 00001A6A 6659 <1> POP CX ; RESTORE AFTER CALL 5499 00001A6C 7221 <1> JC short DR_ERR ; ERROR RETURN 5500 00001A6E 3A0D[ED700000] <1> CMP CL, [NEC_STATUS] ; TEST FOR DRIVE READY TRANSITION 5501 00001A74 7519 <1> JNZ short DR_ERR ; EVERYTHING OK 5502 00001A76 FEC1 <1> INC CL ; NEXT EXPECTED @NEC_STATUS 5503 00001A78 80F9C3 <1> CMP CL,11000011B ; ALL POSSIBLE DRIVES CLEARED 5504 00001A7B 76D8 <1> JBE short NXT_DRV ; FALL THRU IF 11000100B OR > 5505 <1> ; 5506 00001A7D E852030000 <1> CALL SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 5507 <1> RESBAC: 5508 00001A82 E806090000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 5509 00001A87 6689F3 <1> MOV BX,SI ; GET SAVED AL TO BL 5510 00001A8A 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 5511 00001A8C C3 <1> RETn 5512 <1> DR_POP_ERR: 5513 00001A8D 6659 <1> POP CX ; CLEAR STACK 5514 <1> DR_ERR: 5515 00001A8F 800D[EC700000]20 <1> OR byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE 5516 00001A96 EBEA <1> JMP SHORT RESBAC ; RETURN FROM RESET 5517 <1> 5518 <1> ;------------------------------------------------------------------------------- 5519 <1> ; DISK_STATUS (AH = 01H) 5520 <1> ; DISKETTE STATUS. 5521 <1> ; 5522 <1> ; ON ENTRY: AH : STATUS OF PREVIOUS OPERATION 5523 <1> ; 5524 <1> ; ON EXIT: AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION. 5525 <1> ;------------------------------------------------------------------------------- 5526 <1> DSK_STATUS: 5527 00001A98 8825[EC700000] <1> MOV [DSKETTE_STATUS],AH ; PUT BACK FOR SETUP END 5528 00001A9E E8EA080000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 5529 00001AA3 6689F3 <1> MOV BX,SI ; GET SAVED AL TO BL 5530 00001AA6 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 5531 00001AA8 C3 <1> RETn 5532 <1> 5533 <1> ;------------------------------------------------------------------------------- 5534 <1> ; DISK_READ (AH = 02H) 5535 <1> ; DISKETTE READ. 5536 <1> ; 5537 <1> ; ON ENTRY: DI : DRIVE # 5538 <1> ; SI-HI : HEAD # 5539 <1> ; SI-LOW : # OF SECTORS 5540 <1> ; ES : BUFFER SEGMENT 5541 <1> ; [BP] : SECTOR # 5542 <1> ; [BP+1] : TRACK # 5543 <1> ; [BP+2] : BUFFER OFFSET 5544 <1> ; 5545 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5546 <1> ;------------------------------------------------------------------------------- 5547 <1> 5548 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 5549 <1> 5550 <1> DSK_READ: 5551 00001AA9 8025[EA700000]7F <1> AND byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION 5552 00001AB0 66B846E6 <1> MOV AX,0E646H ; AX = NEC COMMAND, DMA COMMAND 5553 00001AB4 E825040000 <1> CALL RD_WR_VF ; COMMON READ/WRITE/VERIFY 5554 00001AB9 C3 <1> RETn 5555 <1> 5556 <1> ;------------------------------------------------------------------------------- 5557 <1> ; DISK_WRITE (AH = 03H) 5558 <1> ; DISKETTE WRITE. 5559 <1> ; 5560 <1> ; ON ENTRY: DI : DRIVE # 5561 <1> ; SI-HI : HEAD # 5562 <1> ; SI-LOW : # OF SECTORS 5563 <1> ; ES : BUFFER SEGMENT 5564 <1> ; [BP] : SECTOR # 5565 <1> ; [BP+1] : TRACK # 5566 <1> ; [BP+2] : BUFFER OFFSET 5567 <1> ; 5568 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5569 <1> ;------------------------------------------------------------------------------- 5570 <1> 5571 <1> ; 06/02/2015, ES:BX -> EBX (unix386.s) 5572 <1> 5573 <1> DSK_WRITE: 5574 00001ABA 66B84AC5 <1> MOV AX,0C54AH ; AX = NEC COMMAND, DMA COMMAND 5575 00001ABE 800D[EA700000]80 <1> OR byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION 5576 00001AC5 E814040000 <1> CALL RD_WR_VF ; COMMON READ/WRITE/VERIFY 5577 00001ACA C3 <1> RETn 5578 <1> 5579 <1> ;------------------------------------------------------------------------------- 5580 <1> ; DISK_VERF (AH = 04H) 5581 <1> ; DISKETTE VERIFY. 5582 <1> ; 5583 <1> ; ON ENTRY: DI : DRIVE # 5584 <1> ; SI-HI : HEAD # 5585 <1> ; SI-LOW : # OF SECTORS 5586 <1> ; ES : BUFFER SEGMENT 5587 <1> ; [BP] : SECTOR # 5588 <1> ; [BP+1] : TRACK # 5589 <1> ; [BP+2] : BUFFER OFFSET 5590 <1> ; 5591 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5592 <1> ;------------------------------------------------------------------------------- 5593 <1> DSK_VERF: 5594 00001ACB 8025[EA700000]7F <1> AND byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION 5595 00001AD2 66B842E6 <1> MOV AX,0E642H ; AX = NEC COMMAND, DMA COMMAND 5596 00001AD6 E803040000 <1> CALL RD_WR_VF ; COMMON READ/WRITE/VERIFY 5597 00001ADB C3 <1> RETn 5598 <1> 5599 <1> ;------------------------------------------------------------------------------- 5600 <1> ; DISK_FORMAT (AH = 05H) 5601 <1> ; DISKETTE FORMAT. 5602 <1> ; 5603 <1> ; ON ENTRY: DI : DRIVE # 5604 <1> ; SI-HI : HEAD # 5605 <1> ; SI-LOW : # OF SECTORS 5606 <1> ; ES : BUFFER SEGMENT 5607 <1> ; [BP] : SECTOR # 5608 <1> ; [BP+1] : TRACK # 5609 <1> ; [BP+2] : BUFFER OFFSET 5610 <1> ; @DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE 5611 <1> ; 5612 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5613 <1> ;------------------------------------------------------------------------------- 5614 <1> DSK_FORMAT: 5615 00001ADC E83C030000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 5616 00001AE1 E838050000 <1> CALL FMT_INIT ; ESTABLISH STATE IF UNESTABLISHED 5617 00001AE6 800D[EA700000]80 <1> OR byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION 5618 00001AED E880050000 <1> CALL MED_CHANGE ; CHECK MEDIA CHANGE AND RESET IF SO 5619 00001AF2 725D <1> JC short FM_DON ; MEDIA CHANGED, SKIP 5620 00001AF4 E8DB020000 <1> CALL SEND_SPEC ; SEND SPECIFY COMMAND TO NEC 5621 00001AF9 E8E6050000 <1> CALL CHK_LASTRATE ; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE 5622 00001AFE 7405 <1> JZ short FM_WR ; YES, SKIP SPECIFY COMMAND 5623 00001B00 E8BD050000 <1> CALL SEND_RATE ; SEND DATA RATE TO CONTROLLER 5624 <1> FM_WR: 5625 00001B05 E873060000 <1> CALL FMTDMA_SET ; SET UP THE DMA FOR FORMAT 5626 00001B0A 7245 <1> JC short FM_DON ; RETURN WITH ERROR 5627 00001B0C B44D <1> MOV AH,04DH ; ESTABLISH THE FORMAT COMMAND 5628 00001B0E E8D0060000 <1> CALL NEC_INIT ; INITIALIZE THE NEC 5629 00001B13 723C <1> JC short FM_DON ; ERROR - EXIT 5630 00001B15 B8[511B0000] <1> MOV eAX, FM_DON ; LOAD ERROR ADDRESS 5631 00001B1A 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 5632 00001B1B B203 <1> MOV DL,3 ; BYTES/SECTOR VALUE TO NEC 5633 00001B1D E83F090000 <1> CALL GET_PARM 5634 00001B22 E8400A0000 <1> CALL NEC_OUTPUT 5635 00001B27 B204 <1> MOV DL,4 ; SECTORS/TRACK VALUE TO NEC 5636 00001B29 E833090000 <1> CALL GET_PARM 5637 00001B2E E8340A0000 <1> CALL NEC_OUTPUT 5638 00001B33 B207 <1> MOV DL,7 ; GAP LENGTH VALUE TO NEC 5639 00001B35 E827090000 <1> CALL GET_PARM 5640 00001B3A E8280A0000 <1> CALL NEC_OUTPUT 5641 00001B3F B208 <1> MOV DL,8 ; FILLER BYTE TO NEC 5642 00001B41 E81B090000 <1> CALL GET_PARM 5643 00001B46 E81C0A0000 <1> CALL NEC_OUTPUT 5644 00001B4B 58 <1> POP eAX ; THROW AWAY ERROR 5645 00001B4C E810070000 <1> CALL NEC_TERM ; TERMINATE, RECEIVE STATUS, ETC, 5646 <1> FM_DON: 5647 00001B51 E8F8020000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 5648 00001B56 E832080000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 5649 00001B5B 6689F3 <1> MOV BX,SI ; GET SAVED AL TO BL 5650 00001B5E 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 5651 00001B60 C3 <1> RETn 5652 <1> 5653 <1> ;------------------------------------------------------------------------------- 5654 <1> ; FNC_ERR 5655 <1> ; INVALID FUNCTION REQUESTED OR INVALID DRIVE: 5656 <1> ; SET BAD COMMAND IN STATUS. 5657 <1> ; 5658 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 5659 <1> ;------------------------------------------------------------------------------- 5660 <1> FNC_ERR: ; INVALID FUNCTION REQUEST 5661 00001B61 6689F0 <1> MOV AX,SI ; RESTORE AL 5662 00001B64 B401 <1> MOV AH,BAD_CMD ; SET BAD COMMAND ERROR 5663 00001B66 8825[EC700000] <1> MOV [DSKETTE_STATUS],AH ; STORE IN DATA AREA 5664 00001B6C F9 <1> STC ; SET CARRY INDICATING ERROR 5665 00001B6D C3 <1> RETn 5666 <1> 5667 <1> ;------------------------------------------------------------------------------- 5668 <1> ; DISK_PARMS (AH = 08H) 5669 <1> ; READ DRIVE PARAMETERS. 5670 <1> ; 5671 <1> ; ON ENTRY: DI : DRIVE # 5672 <1> ; 5673 <1> ; ON EXIT: CL/[BP] = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER 5674 <1> ; BITS 0-5 MAX SECTORS/TRACK 5675 <1> ; CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER 5676 <1> ; BL/[BP+2] = BITS 7-4 = 0 5677 <1> ; BITS 3-0 = VALID CMOS DRIVE TYPE 5678 <1> ; BH/[BP+3] = 0 5679 <1> ; DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED) 5680 <1> ; DH/[BP+5] = MAX HEAD # 5681 <1> ; DI/[BP+6] = OFFSET TO DISK_BASE 5682 <1> ; ES = SEGMENT OF DISK_BASE 5683 <1> ; AX = 0 5684 <1> ; 5685 <1> ; NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT 5686 <1> ; THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM 5687 <1> ; INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE 5688 <1> ; CALLER. 5689 <1> ;------------------------------------------------------------------------------- 5690 <1> DSK_PARMS: 5691 00001B6E E8AA020000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH, 5692 <1> ; MOV WORD [BP+2],0 ; DRIVE TYPE = 0 5693 00001B73 29D2 <1> sub edx, edx ; 20/02/2015 5694 00001B75 895504 <1> mov [ebp+4], edx ; 20/02/2015 5695 <1> ; MOV AX, [EQUIP_FLAG] ; LOAD EQUIPMENT FLAG FOR # DISKETTES 5696 <1> ; AND AL,11000001B ; KEEP DISKETTE DRIVE BITS 5697 <1> ; MOV DL,2 ; DISKETTE DRIVES = 2 5698 <1> ; CMP AL,01000001B ; 2 DRIVES INSTALLED ? 5699 <1> ; JZ short STO_DL ; IF YES JUMP 5700 <1> ; DEC DL ; DISKETTE DRIVES = 1 5701 <1> ; CMP AL,00000001B ; 1 DRIVE INSTALLED ? 5702 <1> ; JNZ short NON_DRV ; IF NO JUMP 5703 <1> ;sub edx, edx 5704 00001B78 66A1[1E6B0000] <1> mov ax, [fd0_type] 5705 00001B7E 6621C0 <1> and ax, ax 5706 00001B81 7474 <1> jz short NON_DRV 5707 00001B83 FEC2 <1> inc dl 5708 00001B85 20E4 <1> and ah, ah 5709 00001B87 7402 <1> jz short STO_DL 5710 00001B89 FEC2 <1> inc dl 5711 <1> STO_DL: 5712 <1> ;MOV [BP+4],DL ; STORE NUMBER OF DRIVES 5713 00001B8B 895508 <1> mov [ebp+8], edx ; 20/02/2015 5714 00001B8E 6683FF01 <1> CMP DI,1 ; CHECK FOR VALID DRIVE 5715 00001B92 7766 <1> JA short NON_DRV1 ; DRIVE INVALID 5716 <1> ;MOV BYTE [BP+5],1 ; MAXIMUM HEAD NUMBER = 1 5717 00001B94 C6450901 <1> mov byte [ebp+9], 1 ; 20/02/2015 5718 00001B98 E8BB080000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL 5719 <1> ;;20/02/2015 5720 <1> ;;JC short CHK_EST ; IF CMOS BAD CHECKSUM ESTABLISHED 5721 <1> ;;OR AL,AL ; TEST FOR NO DRIVE TYPE 5722 00001B9D 7412 <1> JZ short CHK_EST ; JUMP IF SO 5723 00001B9F E805020000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 5724 00001BA4 720B <1> JC short CHK_EST ; TYPE NOT IN TABLE (POSSIBLE BAD CMOS) 5725 <1> ;MOV [BP+2],AL ; STORE VALID CMOS DRIVE TYPE 5726 00001BA6 884504 <1> mov [ebp+4], al ; 06/02/2015 5727 00001BA9 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 5728 00001BAC 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 5729 00001BAF EB36 <1> JMP SHORT STO_CX ; CMOS GOOD, USE CMOS 5730 <1> CHK_EST: 5731 00001BB1 8AA7[F9700000] <1> MOV AH, [DSK_STATE+eDI] ; LOAD STATE FOR THIS DRIVE 5732 00001BB7 F6C410 <1> TEST AH,MED_DET ; CHECK FOR ESTABLISHED STATE 5733 00001BBA 743E <1> JZ short NON_DRV1 ; CMOS BAD/INVALID OR UNESTABLISHED 5734 <1> USE_EST: 5735 00001BBC 80E4C0 <1> AND AH,RATE_MSK ; ISOLATE STATE 5736 00001BBF 80FC80 <1> CMP AH,RATE_250 ; RATE 250 ? 5737 00001BC2 7557 <1> JNE short USE_EST2 ; NO, GO CHECK OTHER RATE 5738 <1> 5739 <1> ;----- DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST 5740 <1> 5741 00001BC4 B001 <1> MOV AL,01 ; DRIVE TYPE 1 (360KB) 5742 00001BC6 E8DE010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 5743 00001BCB 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 5744 00001BCE 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 5745 00001BD1 F687[F9700000]01 <1> TEST byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ? 5746 00001BD8 740D <1> JZ short STO_CX ; MUST BE 360KB DRIVE 5747 <1> 5748 <1> ;----- IT IS 1.44 MB DRIVE 5749 <1> 5750 <1> PARM144: 5751 00001BDA B004 <1> MOV AL,04 ; DRIVE TYPE 4 (1.44MB) 5752 00001BDC E8C8010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 5753 00001BE1 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 5754 00001BE4 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 5755 <1> STO_CX: 5756 00001BE7 894D00 <1> MOV [eBP],eCX ; SAVE POINTER IN STACK FOR RETURN 5757 <1> ES_DI: 5758 <1> ;MOV [BP+6],BX ; ADDRESS OF MEDIA/DRIVE PARM TABLE 5759 00001BEA 895D0C <1> mov [ebp+12], ebx ; 06/02/2015 5760 <1> ;MOV AX,CS ; SEGMENT MEDIA/DRIVE PARAMETER TABLE 5761 <1> ;MOV ES,AX ; ES IS SEGMENT OF TABLE 5762 <1> DP_OUT: 5763 00001BED E85C020000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 5764 00001BF2 6631C0 <1> XOR AX,AX ; CLEAR 5765 00001BF5 F8 <1> CLC 5766 00001BF6 C3 <1> RETn 5767 <1> 5768 <1> ;----- NO DRIYE PRESENT HANDLER 5769 <1> 5770 <1> NON_DRV: 5771 <1> ;MOV BYTE [BP+4],0 ; CLEAR NUMBER OF DRIVES 5772 00001BF7 895508 <1> mov [ebp+8], edx ; 0 ; 20/02/2015 5773 <1> NON_DRV1: 5774 00001BFA 6681FF8000 <1> CMP DI,80H ; CHECK FOR FIXED MEDIA TYPE REQUEST 5775 00001BFF 720C <1> JB short NON_DRV2 ; CONTINUE IF NOT REQUEST FALL THROUGH 5776 <1> 5777 <1> ;----- FIXED DISK REQUEST FALL THROUGH ERROR 5778 <1> 5779 00001C01 E848020000 <1> CALL XLAT_OLD ; ELSE TRANSLATE TO COMPATIBLE MODE 5780 00001C06 6689F0 <1> MOV AX,SI ; RESTORE AL 5781 00001C09 B401 <1> MOV AH,BAD_CMD ; SET BAD COMMAND ERROR 5782 00001C0B F9 <1> STC 5783 00001C0C C3 <1> RETn 5784 <1> 5785 <1> NON_DRV2: 5786 <1> ;XOR AX,AX ; CLEAR PARMS IF NO DRIVES OR CMOS BAD 5787 00001C0D 31C0 <1> xor eax, eax 5788 00001C0F 66894500 <1> MOV [eBP],AX ; TRACKS, SECTORS/TRACK = 0 5789 <1> ;MOV [BP+5],AH ; HEAD = 0 5790 00001C13 886509 <1> mov [ebp+9], ah ; 06/02/2015 5791 <1> ;MOV [BP+6],AX ; OFFSET TO DISK_BASE = 0 5792 00001C16 89450C <1> mov [ebp+12], eax 5793 <1> ;MOV ES,AX ; ES IS SEGMENT OF TABLE 5794 00001C19 EBD2 <1> JMP SHORT DP_OUT 5795 <1> 5796 <1> ;----- DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST 5797 <1> 5798 <1> USE_EST2: 5799 00001C1B B002 <1> MOV AL,02 ; DRIVE TYPE 2 (1.2MB) 5800 00001C1D E887010000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 5801 00001C22 8A4B04 <1> MOV CL, [eBX+MD.SEC_TRK] ; GET SECTOR/TRACK 5802 00001C25 8A6B0B <1> MOV CH, [eBX+MD.MAX_TRK] ; GET MAX. TRACK NUMBER 5803 00001C28 80FC40 <1> CMP AH,RATE_300 ; RATE 300 ? 5804 00001C2B 74BA <1> JZ short STO_CX ; MUST BE 1.2MB DRIVE 5805 00001C2D EBAB <1> JMP SHORT PARM144 ; ELSE, IT IS 1.44MB DRIVE 5806 <1> 5807 <1> ;------------------------------------------------------------------------------- 5808 <1> ; DISK_TYPE (AH = 15H) 5809 <1> ; THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED. 5810 <1> ; 5811 <1> ; ON ENTRY: DI = DRIVE # 5812 <1> ; 5813 <1> ; ON EXIT: AH = DRIVE TYPE, CY=0 5814 <1> ;------------------------------------------------------------------------------- 5815 <1> DSK_TYPE: 5816 00001C2F E8E9010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 5817 00001C34 8A87[F9700000] <1> MOV AL, [DSK_STATE+eDI] ; GET PRESENT STATE INFORMATION 5818 00001C3A 08C0 <1> OR AL,AL ; CHECK FOR NO DRIVE 5819 00001C3C 7418 <1> JZ short NO_DRV 5820 00001C3E B401 <1> MOV AH,NOCHGLN ; NO CHANGE LINE FOR 40 TRACK DRIVE 5821 00001C40 A801 <1> TEST AL,TRK_CAPA ; IS THIS DRIVE AN 80 TRACK DRIVE? 5822 00001C42 7402 <1> JZ short DT_BACK ; IF NO JUMP 5823 00001C44 B402 <1> MOV AH,CHGLN ; CHANGE LINE FOR 80 TRACK DRIVE 5824 <1> DT_BACK: 5825 00001C46 6650 <1> PUSH AX ; SAVE RETURN VALUE 5826 00001C48 E801020000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 5827 00001C4D 6658 <1> POP AX ; RESTORE RETURN VALUE 5828 00001C4F F8 <1> CLC ; NO ERROR 5829 00001C50 6689F3 <1> MOV BX,SI ; GET SAVED AL TO BL 5830 00001C53 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 5831 00001C55 C3 <1> RETn 5832 <1> NO_DRV: 5833 00001C56 30E4 <1> XOR AH,AH ; NO DRIVE PRESENT OR UNKNOWN 5834 00001C58 EBEC <1> JMP SHORT DT_BACK 5835 <1> 5836 <1> ;------------------------------------------------------------------------------- 5837 <1> ; DISK_CHANGE (AH = 16H) 5838 <1> ; THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE. 5839 <1> ; 5840 <1> ; ON ENTRY: DI = DRIVE # 5841 <1> ; 5842 <1> ; ON EXIT: AH = @DSKETTE_STATUS 5843 <1> ; 00 - DISK CHANGE LINE INACTIVE, CY = 0 5844 <1> ; 06 - DISK CHANGE LINE ACTIVE, CY = 1 5845 <1> ;------------------------------------------------------------------------------- 5846 <1> DSK_CHANGE: 5847 00001C5A E8BE010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 5848 00001C5F 8A87[F9700000] <1> MOV AL, [DSK_STATE+eDI] ; GET MEDIA STATE INFORMATION 5849 00001C65 08C0 <1> OR AL,AL ; DRIVE PRESENT ? 5850 00001C67 7422 <1> JZ short DC_NON ; JUMP IF NO DRIVE 5851 00001C69 A801 <1> TEST AL,TRK_CAPA ; 80 TRACK DRIVE ? 5852 00001C6B 7407 <1> JZ short SETIT ; IF SO , CHECK CHANGE LINE 5853 <1> DC0: 5854 00001C6D E88D0A0000 <1> CALL READ_DSKCHNG ; GO CHECK STATE OF DISK CHANGE LINE 5855 00001C72 7407 <1> JZ short FINIS ; CHANGE LINE NOT ACTIVE 5856 <1> 5857 00001C74 C605[EC700000]06 <1> SETIT: MOV byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED 5858 <1> 5859 00001C7B E8CE010000 <1> FINIS: CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 5860 00001C80 E808070000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 5861 00001C85 6689F3 <1> MOV BX,SI ; GET SAVED AL TO BL 5862 00001C88 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 5863 00001C8A C3 <1> RETn 5864 <1> DC_NON: 5865 00001C8B 800D[EC700000]80 <1> OR byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE 5866 00001C92 EBE7 <1> JMP SHORT FINIS 5867 <1> 5868 <1> ;------------------------------------------------------------------------------- 5869 <1> ; FORMAT_SET (AH = 17H) 5870 <1> ; THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED 5871 <1> ; FOR THE FOLLOWING FORMAT OPERATION. 5872 <1> ; 5873 <1> ; ON ENTRY: SI LOW = DASD TYPE FOR FORMAT 5874 <1> ; DI = DRIVE # 5875 <1> ; 5876 <1> ; ON EXIT: @DSKETTE_STATUS REFLECTS STATUS 5877 <1> ; AH = @DSKETTE_STATUS 5878 <1> ; CY = 1 IF ERROR 5879 <1> ;------------------------------------------------------------------------------- 5880 <1> FORMAT_SET: 5881 00001C94 E884010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 5882 00001C99 6656 <1> PUSH SI ; SAVE DASD TYPE 5883 00001C9B 6689F0 <1> MOV AX,SI ; AH = ? , AL , DASD TYPE 5884 00001C9E 30E4 <1> XOR AH,AH ; AH , 0 , AL , DASD TYPE 5885 00001CA0 6689C6 <1> MOV SI,AX ; SI = DASD TYPE 5886 00001CA3 80A7[F9700000]0F <1> AND byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE 5887 00001CAA 664E <1> DEC SI ; CHECK FOR 320/360K MEDIA & DRIVE 5888 00001CAC 7509 <1> JNZ short NOT_320 ; BYPASS IF NOT 5889 00001CAE 808F[F9700000]90 <1> OR byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360 5890 00001CB5 EB48 <1> JMP SHORT S0 5891 <1> 5892 <1> NOT_320: 5893 00001CB7 E8B6030000 <1> CALL MED_CHANGE ; CHECK FOR TIME_OUT 5894 00001CBC 803D[EC700000]80 <1> CMP byte [DSKETTE_STATUS], TIME_OUT 5895 00001CC3 743A <1> JZ short S0 ; IF TIME OUT TELL CALLER 5896 <1> S3: 5897 00001CC5 664E <1> DEC SI ; CHECK FOR 320/360K IN 1.2M DRIVE 5898 00001CC7 7509 <1> JNZ short NOT_320_12 ; BYPASS IF NOT 5899 00001CC9 808F[F9700000]70 <1> OR byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE 5900 00001CD0 EB2D <1> JMP SHORT S0 5901 <1> 5902 <1> NOT_320_12: 5903 00001CD2 664E <1> DEC SI ; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE 5904 00001CD4 7509 <1> JNZ short NOT_12 ; BYPASS IF NOT 5905 00001CD6 808F[F9700000]10 <1> OR byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE 5906 00001CDD EB20 <1> JMP SHORT S0 ; RETURN TO CALLER 5907 <1> 5908 <1> NOT_12: 5909 00001CDF 664E <1> DEC SI ; CHECK FOR SET DASD TYPE 04 5910 00001CE1 752B <1> JNZ short FS_ERR ; BAD COMMAND EXIT IF NOT VALID TYPE 5911 <1> 5912 00001CE3 F687[F9700000]04 <1> TEST byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ? 5913 00001CEA 740B <1> JZ short ASSUME ; IF STILL NOT DETERMINED ASSUME 5914 00001CEC B050 <1> MOV AL,MED_DET+RATE_300 5915 00001CEE F687[F9700000]02 <1> TEST byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ? 5916 00001CF5 7502 <1> JNZ short OR_IT_IN ; IF 1.2 M THEN DATA RATE 300 5917 <1> 5918 <1> ASSUME: 5919 00001CF7 B090 <1> MOV AL,MED_DET+RATE_250 ; SET UP 5920 <1> 5921 <1> OR_IT_IN: 5922 00001CF9 0887[F9700000] <1> OR [DSK_STATE+eDI], AL ; OR IN THE CORRECT STATE 5923 <1> S0: 5924 00001CFF E84A010000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 5925 00001D04 E884060000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 5926 00001D09 665B <1> POP BX ; GET SAVED AL TO BL 5927 00001D0B 88D8 <1> MOV AL,BL ; PUT BACK FOR RETURN 5928 00001D0D C3 <1> RETn 5929 <1> 5930 <1> FS_ERR: 5931 00001D0E C605[EC700000]01 <1> MOV byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND 5932 00001D15 EBE8 <1> JMP SHORT S0 5933 <1> 5934 <1> ;------------------------------------------------------------------------------- 5935 <1> ; SET_MEDIA (AH = 18H) 5936 <1> ; THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 5937 <1> ; TO BE USED FOR THE FOLLOWING FORMAT OPERATION. 5938 <1> ; 5939 <1> ; ON ENTRY: 5940 <1> ; [BP] = SECTOR PER TRACK 5941 <1> ; [BP+1] = TRACK # 5942 <1> ; DI = DRIVE # 5943 <1> ; 5944 <1> ; ON EXIT: 5945 <1> ; @DSKETTE_STATUS REFLECTS STATUS 5946 <1> ; IF NO ERROR: 5947 <1> ; AH = 0 5948 <1> ; CY = 0 5949 <1> ; ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE 5950 <1> ; DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE 5951 <1> ; IF ERROR: 5952 <1> ; AH = @DSKETTE_STATUS 5953 <1> ; CY = 1 5954 <1> ;------------------------------------------------------------------------------- 5955 <1> SET_MEDIA: 5956 00001D17 E801010000 <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 5957 00001D1C F687[F9700000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE 5958 00001D23 7415 <1> JZ short SM_CMOS ; JUMP IF 40 TRACK DRIVE 5959 00001D25 E848030000 <1> CALL MED_CHANGE ; RESET CHANGE LINE 5960 00001D2A 803D[EC700000]80 <1> CMP byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER 5961 00001D31 746B <1> JE short SM_RTN 5962 00001D33 C605[EC700000]00 <1> MOV byte [DSKETTE_STATUS], 0 ; CLEAR STATUS 5963 <1> SM_CMOS: 5964 00001D3A E819070000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 5965 <1> ;;20/02/2015 5966 <1> ;;JC short MD_NOT_FND ; ERROR IN CMOS 5967 <1> ;;OR AL,AL ; TEST FOR NO DRIVE 5968 00001D3F 745D <1> JZ short SM_RTN ; RETURN IF SO 5969 00001D41 E863000000 <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL 5970 00001D46 7231 <1> JC short MD_NOT_FND ; TYPE NOT IN TABLE (BAD CMOS) 5971 00001D48 57 <1> PUSH eDI ; SAVE REG. 5972 00001D49 31DB <1> XOR eBX,eBX ; BX = INDEX TO DR. TYPE TABLE 5973 00001D4B B906000000 <1> MOV eCX,DR_CNT ; CX = LOOP COUNT 5974 <1> DR_SEARCH: 5975 00001D50 8AA3[9C6A0000] <1> MOV AH, [DR_TYPE+eBX] ; GET DRIVE TYPE 5976 00001D56 80E47F <1> AND AH,BIT7OFF ; MASK OUT MSB 5977 00001D59 38E0 <1> CMP AL,AH ; DRIVE TYPE MATCH ? 5978 00001D5B 7516 <1> JNE short NXT_MD ; NO, CHECK NEXT DRIVE TYPE 5979 <1> DR_FND: 5980 00001D5D 8BBB[9D6A0000] <1> MOV eDI, [DR_TYPE+eBX+1] ; DI = MEDIA/DRIVE PARAM TABLE 5981 <1> MD_SEARCH: 5982 00001D63 8A6704 <1> MOV AH, [eDI+MD.SEC_TRK] ; GET SECTOR/TRACK 5983 00001D66 386500 <1> CMP [eBP],AH ; MATCH? 5984 00001D69 7508 <1> JNE short NXT_MD ; NO, CHECK NEXT MEDIA 5985 00001D6B 8A670B <1> MOV AH, [eDI+MD.MAX_TRK] ; GET MAX. TRACK # 5986 00001D6E 386501 <1> CMP [eBP+1],AH ; MATCH? 5987 00001D71 740F <1> JE short MD_FND ; YES, GO GET RATE 5988 <1> NXT_MD: 5989 <1> ;ADD BX,3 ; CHECK NEXT DRIVE TYPE 5990 00001D73 83C305 <1> add ebx, 5 ; 18/02/2015 5991 00001D76 E2D8 <1> LOOP DR_SEARCH 5992 00001D78 5F <1> POP eDI ; RESTORE REG. 5993 <1> MD_NOT_FND: 5994 00001D79 C605[EC700000]0C <1> MOV byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND 5995 00001D80 EB1C <1> JMP SHORT SM_RTN ; RETURN 5996 <1> MD_FND: 5997 00001D82 8A470C <1> MOV AL, [eDI+MD.RATE] ; GET RATE 5998 00001D85 3C40 <1> CMP AL,RATE_300 ; DOUBLE STEP REQUIRED FOR RATE 300 5999 00001D87 7502 <1> JNE short MD_SET 6000 00001D89 0C20 <1> OR AL,DBL_STEP 6001 <1> MD_SET: 6002 <1> ;MOV [BP+6],DI ; SAVE TABLE POINTER IN STACK 6003 00001D8B 897D0C <1> mov [ebp+12], edi ; 18/02/2015 6004 00001D8E 0C10 <1> OR AL,MED_DET ; SET MEDIA ESTABLISHED 6005 00001D90 5F <1> POP eDI 6006 00001D91 80A7[F9700000]0F <1> AND byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE 6007 00001D98 0887[F9700000] <1> OR [DSK_STATE+eDI], AL 6008 <1> ;MOV AX, CS ; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE 6009 <1> ;MOV ES, AX ; ES IS SEGMENT OF TABLE 6010 <1> SM_RTN: 6011 00001D9E E8AB000000 <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 6012 00001DA3 E8E5050000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 6013 00001DA8 C3 <1> RETn 6014 <1> 6015 <1> ;---------------------------------------------------------------- 6016 <1> ; DR_TYPE_CHECK : 6017 <1> ; CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL) : 6018 <1> ; IS SUPPORTED IN BIOS DRIVE TYPE TABLE : 6019 <1> ; ON ENTRY: : 6020 <1> ; AL = DRIVE TYPE : 6021 <1> ; ON EXIT: : 6022 <1> ; CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE) : 6023 <1> ; CY = 0 DRIVE TYPE SUPPORTED : 6024 <1> ; BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE : 6025 <1> ; CY = 1 DRIVE TYPE NOT SUPPORTED : 6026 <1> ; REGISTERS ALTERED: eBX : 6027 <1> ;---------------------------------------------------------------- 6028 <1> DR_TYPE_CHECK: 6029 00001DA9 6650 <1> PUSH AX 6030 00001DAB 51 <1> PUSH eCX 6031 00001DAC 31DB <1> XOR eBX,eBX ; BX = INDEX TO DR_TYPE TABLE 6032 00001DAE B906000000 <1> MOV eCX,DR_CNT ; CX = LOOP COUNT 6033 <1> TYPE_CHK: 6034 00001DB3 8AA3[9C6A0000] <1> MOV AH,[DR_TYPE+eBX] ; GET DRIVE TYPE 6035 00001DB9 38E0 <1> CMP AL,AH ; DRIVE TYPE MATCH? 6036 00001DBB 740D <1> JE short DR_TYPE_VALID ; YES, RETURN WITH CARRY RESET 6037 <1> ;ADD BX,3 ; CHECK NEXT DRIVE TYPE 6038 00001DBD 83C305 <1> add ebx, 5 ; 16/02/2015 (32 bit address modification) 6039 00001DC0 E2F1 <1> LOOP TYPE_CHK 6040 <1> ; 6041 00001DC2 BB[FB6A0000] <1> mov ebx, MD_TBL6 ; 1.44MB fd parameter table 6042 <1> ; Default for GET_PARM (11/12/2014) 6043 <1> ; 6044 00001DC7 F9 <1> STC ; DRIVE TYPE NOT FOUND IN TABLE 6045 00001DC8 EB06 <1> JMP SHORT TYPE_RTN 6046 <1> DR_TYPE_VALID: 6047 00001DCA 8B9B[9D6A0000] <1> MOV eBX,[DR_TYPE+eBX+1] ; BX = MEDIA TABLE 6048 <1> TYPE_RTN: 6049 00001DD0 59 <1> POP eCX 6050 00001DD1 6658 <1> POP AX 6051 00001DD3 C3 <1> RETn 6052 <1> 6053 <1> ;---------------------------------------------------------------- 6054 <1> ; SEND_SPEC : 6055 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 6056 <1> ; THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER : 6057 <1> ; ON ENTRY: @DISK_POINTER = DRIVE PARAMETER TABLE : 6058 <1> ; ON EXIT: NONE : 6059 <1> ; REGISTERS ALTERED: CX, DX : 6060 <1> ;---------------------------------------------------------------- 6061 <1> SEND_SPEC: 6062 00001DD4 50 <1> PUSH eAX ; SAVE AX 6063 00001DD5 B8[FB1D0000] <1> MOV eAX, SPECBAC ; LOAD ERROR ADDRESS 6064 00001DDA 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 6065 00001DDB B403 <1> MOV AH,03H ; SPECIFY COMMAND 6066 00001DDD E885070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 6067 00001DE2 28D2 <1> SUB DL,DL ; FIRST SPECIFY BYTE 6068 00001DE4 E878060000 <1> CALL GET_PARM ; GET PARAMETER TO AH 6069 00001DE9 E879070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 6070 00001DEE B201 <1> MOV DL,1 ; SECOND SPECIFY BYTE 6071 00001DF0 E86C060000 <1> CALL GET_PARM ; GET PARAMETER TO AH 6072 00001DF5 E86D070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 6073 00001DFA 58 <1> POP eAX ; POP ERROR RETURN 6074 <1> SPECBAC: 6075 00001DFB 58 <1> POP eAX ; RESTORE ORIGINAL AX VALUE 6076 00001DFC C3 <1> RETn 6077 <1> 6078 <1> ;---------------------------------------------------------------- 6079 <1> ; SEND_SPEC_MD : 6080 <1> ; SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM : 6081 <1> ; THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX) : 6082 <1> ; ON ENTRY: CS:BX = MEDIA/DRIVE PARAMETER TABLE : 6083 <1> ; ON EXIT: NONE : 6084 <1> ; REGISTERS ALTERED: AX : 6085 <1> ;---------------------------------------------------------------- 6086 <1> SEND_SPEC_MD: 6087 00001DFD 50 <1> PUSH eAX ; SAVE RATE DATA 6088 00001DFE B8[1B1E0000] <1> MOV eAX, SPEC_ESBAC ; LOAD ERROR ADDRESS 6089 00001E03 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 6090 00001E04 B403 <1> MOV AH,03H ; SPECIFY COMMAND 6091 00001E06 E85C070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 6092 00001E0B 8A23 <1> MOV AH, [eBX+MD.SPEC1] ; GET 1ST SPECIFY BYTE 6093 00001E0D E855070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 6094 00001E12 8A6301 <1> MOV AH, [eBX+MD.SPEC2] ; GET SECOND SPECIFY BYTE 6095 00001E15 E84D070000 <1> CALL NEC_OUTPUT ; OUTPUT THE COMMAND 6096 00001E1A 58 <1> POP eAX ; POP ERROR RETURN 6097 <1> SPEC_ESBAC: 6098 00001E1B 58 <1> POP eAX ; RESTORE ORIGINAL AX VALUE 6099 00001E1C C3 <1> RETn 6100 <1> 6101 <1> ;------------------------------------------------------------------------------- 6102 <1> ; XLAT_NEW 6103 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE 6104 <1> ; MODE TO NEW ARCHITECTURE. 6105 <1> ; 6106 <1> ; ON ENTRY: DI = DRIVE # 6107 <1> ;------------------------------------------------------------------------------- 6108 <1> XLAT_NEW: 6109 00001E1D 83FF01 <1> CMP eDI,1 ; VALID DRIVE 6110 00001E20 7725 <1> JA short XN_OUT ; IF INVALID BACK 6111 00001E22 80BF[F9700000]00 <1> CMP byte [DSK_STATE+eDI], 0 ; NO DRIVE ? 6112 00001E29 741D <1> JZ short DO_DET ; IF NO DRIVE ATTEMPT DETERMINE 6113 00001E2B 6689F9 <1> MOV CX,DI ; CX = DRIVE NUMBER 6114 00001E2E C0E102 <1> SHL CL,2 ; CL = SHIFT COUNT, A=0, B=4 6115 00001E31 A0[F8700000] <1> MOV AL, [HF_CNTRL] ; DRIVE INFORMATION 6116 00001E36 D2C8 <1> ROR AL,CL ; TO LOW NIBBLE 6117 00001E38 2407 <1> AND AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 6118 00001E3A 80A7[F9700000]F8 <1> AND byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) 6119 00001E41 0887[F9700000] <1> OR [DSK_STATE+eDI], AL ; UPDATE DRIVE STATE 6120 <1> XN_OUT: 6121 00001E47 C3 <1> RETn 6122 <1> DO_DET: 6123 00001E48 E8BF080000 <1> CALL DRIVE_DET ; TRY TO DETERMINE 6124 00001E4D C3 <1> RETn 6125 <1> 6126 <1> ;------------------------------------------------------------------------------- 6127 <1> ; XLAT_OLD 6128 <1> ; TRANSLATES DISKETTE STATE LOCATIONS FROM NEW 6129 <1> ; ARCHITECTURE TO COMPATIBLE MODE. 6130 <1> ; 6131 <1> ; ON ENTRY: DI = DRIVE 6132 <1> ;------------------------------------------------------------------------------- 6133 <1> XLAT_OLD: 6134 00001E4E 83FF01 <1> CMP eDI,1 ; VALID DRIVE ? 6135 <1> ;JA short XO_OUT ; IF INVALID BACK 6136 00001E51 0F8786000000 <1> ja XO_OUT 6137 00001E57 80BF[F9700000]00 <1> CMP byte [DSK_STATE+eDI],0 ; NO DRIVE ? 6138 00001E5E 747D <1> JZ short XO_OUT ; IF NO DRIVE TRANSLATE DONE 6139 <1> 6140 <1> ;----- TEST FOR SAVED DRIVE INFORMATION ALREADY SET 6141 <1> 6142 00001E60 6689F9 <1> MOV CX,DI ; CX = DRIVE NUMBER 6143 00001E63 C0E102 <1> SHL CL,2 ; CL = SHIFT COUNT, A=0, B=4 6144 00001E66 B402 <1> MOV AH,FMT_CAPA ; LOAD MULTIPLE DATA RATE BIT MASK 6145 00001E68 D2CC <1> ROR AH,CL ; ROTATE BY MASK 6146 00001E6A 8425[F8700000] <1> TEST [HF_CNTRL], AH ; MULTIPLE-DATA RATE DETERMINED ? 6147 00001E70 751C <1> JNZ short SAVE_SET ; IF SO, NO NEED TO RE-SAVE 6148 <1> 6149 <1> ;----- ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE 6150 <1> 6151 00001E72 B407 <1> MOV AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP 6152 00001E74 D2CC <1> ROR AH,CL ; FIX MASK TO KEEP 6153 00001E76 F6D4 <1> NOT AH ; TRANSLATE MASK 6154 00001E78 2025[F8700000] <1> AND [HF_CNTRL], AH ; KEEP BITS FROM OTHER DRIVE INTACT 6155 <1> 6156 <1> ;----- ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL 6157 <1> 6158 00001E7E 8A87[F9700000] <1> MOV AL, [DSK_STATE+eDI] ; ACCESS STATE 6159 00001E84 2407 <1> AND AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS 6160 00001E86 D2C8 <1> ROR AL,CL ; FIX FOR THIS DRIVE 6161 00001E88 0805[F8700000] <1> OR [HF_CNTRL], AL ; UPDATE SAVED DRIVE STATE 6162 <1> 6163 <1> ;----- TRANSLATE TO COMPATIBILITY MODE 6164 <1> 6165 <1> SAVE_SET: 6166 00001E8E 8AA7[F9700000] <1> MOV AH, [DSK_STATE+eDI] ; ACCESS STATE 6167 00001E94 88E7 <1> MOV BH,AH ; TO BH FOR LATER 6168 00001E96 80E4C0 <1> AND AH,RATE_MSK ; KEEP ONLY RATE 6169 00001E99 80FC00 <1> CMP AH,RATE_500 ; RATE 500 ? 6170 00001E9C 7410 <1> JZ short CHK_144 ; YES 1.2/1.2 OR 1.44/1.44 6171 00001E9E B001 <1> MOV AL,M3D1U ; AL = 360 IN 1.2 UNESTABLISHED 6172 00001EA0 80FC40 <1> CMP AH,RATE_300 ; RATE 300 ? 6173 00001EA3 7518 <1> JNZ short CHK_250 ; NO, 360/360, 720/720 OR 720/1.44 6174 00001EA5 F6C720 <1> TEST BH,DBL_STEP ; CHECK FOR DOUBLE STEP 6175 00001EA8 751F <1> JNZ short TST_DET ; MUST BE 360 IN 1.2 6176 <1> UNKNO: 6177 00001EAA B007 <1> MOV AL,MED_UNK ; NONE OF THE ABOVE 6178 00001EAC EB22 <1> JMP SHORT AL_SET ; PROCESS COMPLETE 6179 <1> CHK_144: 6180 00001EAE E8A5050000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 6181 <1> ;;20/02/2015 6182 <1> ;;JC short UNKNO ; ERROR, SET 'NONE OF ABOVE' 6183 00001EB3 74F5 <1> jz short UNKNO ;; 20/02/2015 6184 00001EB5 3C02 <1> CMP AL,2 ; 1.2MB DRIVE ? 6185 00001EB7 75F1 <1> JNE short UNKNO ; NO, GO SET 'NONE OF ABOVE' 6186 00001EB9 B002 <1> MOV AL,M1D1U ; AL = 1.2 IN 1.2 UNESTABLISHED 6187 00001EBB EB0C <1> JMP SHORT TST_DET 6188 <1> CHK_250: 6189 00001EBD B000 <1> MOV AL,M3D3U ; AL = 360 IN 360 UNESTABLISHED 6190 00001EBF 80FC80 <1> CMP AH,RATE_250 ; RATE 250 ? 6191 00001EC2 75E6 <1> JNZ short UNKNO ; IF SO FALL IHRU 6192 00001EC4 F6C701 <1> TEST BH,TRK_CAPA ; 80 TRACK CAPABILITY ? 6193 00001EC7 75E1 <1> JNZ short UNKNO ; IF SO JUMP, FALL THRU TEST DET 6194 <1> TST_DET: 6195 00001EC9 F6C710 <1> TEST BH,MED_DET ; DETERMINED ? 6196 00001ECC 7402 <1> JZ short AL_SET ; IF NOT THEN SET 6197 00001ECE 0403 <1> ADD AL,3 ; MAKE DETERMINED/ESTABLISHED 6198 <1> AL_SET: 6199 00001ED0 80A7[F9700000]F8 <1> AND byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE 6200 00001ED7 0887[F9700000] <1> OR [DSK_STATE+eDI], AL ; REPLACE WITH COMPATIBLE MODE 6201 <1> XO_OUT: 6202 00001EDD C3 <1> RETn 6203 <1> 6204 <1> ;------------------------------------------------------------------------------- 6205 <1> ; RD_WR_VF 6206 <1> ; COMMON READ, WRITE AND VERIFY: 6207 <1> ; MAIN LOOP FOR STATE RETRIES. 6208 <1> ; 6209 <1> ; ON ENTRY: AH = READ/WRITE/VERIFY NEC PARAMETER 6210 <1> ; AL = READ/WRITE/VERIFY DMA PARAMETER 6211 <1> ; 6212 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6213 <1> ;------------------------------------------------------------------------------- 6214 <1> RD_WR_VF: 6215 00001EDE 6650 <1> PUSH AX ; SAVE DMA, NEC PARAMETERS 6216 00001EE0 E838FFFFFF <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH. 6217 00001EE5 E8F3000000 <1> CALL SETUP_STATE ; INITIALIZE START AND END RATE 6218 00001EEA 6658 <1> POP AX ; RESTORE READ/WRITE/VERIFY 6219 <1> DO_AGAIN: 6220 00001EEC 6650 <1> PUSH AX ; SAVE READ/WRITE/VERIFY PARAMETER 6221 00001EEE E87F010000 <1> CALL MED_CHANGE ; MEDIA CHANGE AND RESET IF CHANGED 6222 00001EF3 6658 <1> POP AX ; RESTORE READ/WRITE/VERIFY 6223 00001EF5 0F82C9000000 <1> JC RWV_END ; MEDIA CHANGE ERROR OR TIME-OUT 6224 <1> RWV: 6225 00001EFB 6650 <1> PUSH AX ; SAVE READ/WRITE/VERIFY PARAMETER 6226 00001EFD 8AB7[F9700000] <1> MOV DH, [DSK_STATE+eDI] ; GET RATE STATE OF THIS DRIVE 6227 00001F03 80E6C0 <1> AND DH,RATE_MSK ; KEEP ONLY RATE 6228 00001F06 E84D050000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL (AL) 6229 <1> ;;20/02/2015 6230 <1> ;;JC short RWV_ASSUME ; ERROR IN CMOS 6231 00001F0B 7451 <1> jz short RWV_ASSUME ; 20/02/2015 6232 00001F0D 3C01 <1> CMP AL,1 ; 40 TRACK DRIVE? 6233 00001F0F 750D <1> JNE short RWV_1 ; NO, BYPASS CMOS VALIDITY CHECK 6234 00001F11 F687[F9700000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE 6235 00001F18 7413 <1> JZ short RWV_2 ; YES, CMOS IS CORRECT 6236 00001F1A B002 <1> MOV AL,2 ; CHANGE TO 1.2M 6237 00001F1C EB0F <1> JMP SHORT RWV_2 6238 <1> RWV_1: 6239 00001F1E 720D <1> JB short RWV_2 ; NO DRIVE SPECIFIED, CONTINUE 6240 00001F20 F687[F9700000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK? 6241 00001F27 7504 <1> JNZ short RWV_2 ; NO, 80 TRACK 6242 00001F29 B001 <1> MOV AL,1 ; IT IS 40 TRACK, FIX CMOS VALUE 6243 00001F2B EB04 <1> jmp short rwv_3 6244 <1> RWV_2: 6245 00001F2D 08C0 <1> OR AL,AL ; TEST FOR NO DRIVE 6246 00001F2F 742D <1> JZ short RWV_ASSUME ; ASSUME TYPE, USE MAX TRACK 6247 <1> rwv_3: 6248 00001F31 E873FEFFFF <1> CALL DR_TYPE_CHECK ; RTN CS:BX = MEDIA/DRIVE PARAM TBL. 6249 00001F36 7226 <1> JC short RWV_ASSUME ; TYPE NOT IN TABLE (BAD CMOS) 6250 <1> 6251 <1> ;----- SEARCH FOR MEDIA/DRIVE PARAMETER TABLE 6252 <1> 6253 00001F38 57 <1> PUSH eDI ; SAVE DRIVE # 6254 00001F39 31DB <1> XOR eBX,eBX ; BX = INDEX TO DR_TYPE TABLE 6255 00001F3B B906000000 <1> MOV eCX,DR_CNT ; CX = LOOP COUNT 6256 <1> RWV_DR_SEARCH: 6257 00001F40 8AA3[9C6A0000] <1> MOV AH, [DR_TYPE+eBX] ; GET DRIVE TYPE 6258 00001F46 80E47F <1> AND AH,BIT7OFF ; MASK OUT MSB 6259 00001F49 38E0 <1> CMP AL,AH ; DRIVE TYPE MATCH? 6260 00001F4B 750B <1> JNE short RWV_NXT_MD ; NO, CHECK NEXT DRIVE TYPE 6261 <1> RWV_DR_FND: 6262 00001F4D 8BBB[9D6A0000] <1> MOV eDI, [DR_TYPE+eBX+1] ; DI = MEDIA/DRIVE PARAMETER TABLE 6263 <1> RWV_MD_SEARH: 6264 00001F53 3A770C <1> CMP DH, [eDI+MD.RATE] ; MATCH? 6265 00001F56 741B <1> JE short RWV_MD_FND ; YES, GO GET 1ST SPECIFY BYTE 6266 <1> RWV_NXT_MD: 6267 <1> ;ADD BX,3 ; CHECK NEXT DRIVE TYPE 6268 00001F58 83C305 <1> add eBX, 5 6269 00001F5B E2E3 <1> LOOP RWV_DR_SEARCH 6270 00001F5D 5F <1> POP eDI ; RESTORE DRIVE # 6271 <1> 6272 <1> ;----- ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED 6273 <1> 6274 <1> RWV_ASSUME: 6275 00001F5E BB[BA6A0000] <1> MOV eBX, MD_TBL1 ; POINT TO 40 TRACK 250 KBS 6276 00001F63 F687[F9700000]01 <1> TEST byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK 6277 00001F6A 740A <1> JZ short RWV_MD_FND1 ; MUST BE 40 TRACK 6278 00001F6C BB[D46A0000] <1> MOV eBX, MD_TBL3 ; POINT TO 80 TRACK 500 KBS 6279 00001F71 EB03 <1> JMP short RWV_MD_FND1 ; GO SPECIFY PARAMTERS 6280 <1> 6281 <1> ;----- CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE 6282 <1> 6283 <1> RWV_MD_FND: 6284 00001F73 89FB <1> MOV eBX,eDI ; BX = MEDIA/DRIVE PARAMETER TABLE 6285 00001F75 5F <1> POP eDI ; RESTORE DRIVE # 6286 <1> 6287 <1> ;----- SEND THE SPECIFY COMMAND TO THE CONTROLLER 6288 <1> 6289 <1> RWV_MD_FND1: 6290 00001F76 E882FEFFFF <1> CALL SEND_SPEC_MD 6291 00001F7B E864010000 <1> CALL CHK_LASTRATE ; ZF=1 ATTEMP RATE IS SAME AS LAST RATE 6292 00001F80 7405 <1> JZ short RWV_DBL ; YES,SKIP SEND RATE COMMAND 6293 00001F82 E83B010000 <1> CALL SEND_RATE ; SEND DATA RATE TO NEC 6294 <1> RWV_DBL: 6295 00001F87 53 <1> PUSH eBX ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 6296 00001F88 E822040000 <1> CALL SETUP_DBL ; CHECK FOR DOUBLE STEP 6297 00001F8D 5B <1> POP eBX ; RESTORE ADDRESS 6298 00001F8E 7226 <1> JC short CHK_RET ; ERROR FROM READ ID, POSSIBLE RETRY 6299 00001F90 6658 <1> POP AX ; RESTORE NEC, DMA COMMAND 6300 00001F92 6650 <1> PUSH AX ; SAVE NEC COMMAND 6301 00001F94 53 <1> PUSH eBX ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 6302 00001F95 E861010000 <1> CALL DMA_SETUP ; SET UP THE DMA 6303 00001F9A 5B <1> POP eBX 6304 00001F9B 6658 <1> POP AX ; RESTORE NEC COMMAND 6305 00001F9D 722F <1> JC short RWV_BAC ; CHECK FOR DMA BOUNDARY ERROR 6306 00001F9F 6650 <1> PUSH AX ; SAVE NEC COMMAND 6307 00001FA1 53 <1> PUSH eBX ; SAVE MEDIA/DRIVE PARAM TBL ADDRESS 6308 00001FA2 E83C020000 <1> CALL NEC_INIT ; INITIALIZE NEC 6309 00001FA7 5B <1> POP eBX ; RESTORE ADDRESS 6310 00001FA8 720C <1> JC short CHK_RET ; ERROR - EXIT 6311 00001FAA E866020000 <1> CALL RWV_COM ; OP CODE COMMON TO READ/WRITE/VERIFY 6312 00001FAF 7205 <1> JC short CHK_RET ; ERROR - EXIT 6313 00001FB1 E8AB020000 <1> CALL NEC_TERM ; TERMINATE, GET STATUS, ETC. 6314 <1> CHK_RET: 6315 00001FB6 E84A030000 <1> CALL RETRY ; CHECK FOR, SETUP RETRY 6316 00001FBB 6658 <1> POP AX ; RESTORE READ/WRITE/VERIFY PARAMETER 6317 00001FBD 7305 <1> JNC short RWV_END ; CY = 0 NO RETRY 6318 00001FBF E928FFFFFF <1> JMP DO_AGAIN ; CY = 1 MEANS RETRY 6319 <1> RWV_END: 6320 00001FC4 E8F4020000 <1> CALL DSTATE ; ESTABLISH STATE IF SUCCESSFUL 6321 00001FC9 E887030000 <1> CALL NUM_TRANS ; AL = NUMBER TRANSFERRED 6322 <1> RWV_BAC: ; BAD DMA ERROR ENTRY 6323 00001FCE 6650 <1> PUSH AX ; SAVE NUMBER TRANSFERRED 6324 00001FD0 E879FEFFFF <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 6325 00001FD5 6658 <1> POP AX ; RESTORE NUMBER TRANSFERRED 6326 00001FD7 E8B1030000 <1> CALL SETUP_END ; VARIOUS CLEANUPS 6327 00001FDC C3 <1> RETn 6328 <1> 6329 <1> ;------------------------------------------------------------------------------- 6330 <1> ; SETUP_STATE: INITIALIZES START AND END RATES. 6331 <1> ;------------------------------------------------------------------------------- 6332 <1> SETUP_STATE: 6333 00001FDD F687[F9700000]10 <1> TEST byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ? 6334 00001FE4 7537 <1> JNZ short J1C ; NO STATES IF DETERMINED 6335 00001FE6 66B84000 <1> MOV AX,(RATE_500*256)+RATE_300 ; AH = START RATE, AL = END RATE 6336 00001FEA F687[F9700000]04 <1> TEST byte [DSK_STATE+eDI],DRV_DET ; DRIVE ? 6337 00001FF1 740D <1> JZ short AX_SET ; DO NOT KNOW DRIVE 6338 00001FF3 F687[F9700000]02 <1> TEST byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE? 6339 00001FFA 7504 <1> JNZ short AX_SET ; JUMP IF YES 6340 00001FFC 66B88080 <1> MOV AX,RATE_250*257 ; START A END RATE 250 FOR 360 DRIVE 6341 <1> AX_SET: 6342 00002000 80A7[F9700000]1F <1> AND byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE 6343 00002007 08A7[F9700000] <1> OR [DSK_STATE+eDI], AH ; RATE FIRST TO TRY 6344 0000200D 8025[F4700000]F3 <1> AND byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS 6345 00002014 C0C804 <1> ROR AL,4 ; TO OPERATION LAST RATE LOCATION 6346 00002017 0805[F4700000] <1> OR [LASTRATE], AL ; LAST RATE 6347 <1> J1C: 6348 0000201D C3 <1> RETn 6349 <1> 6350 <1> ;------------------------------------------------------------------------------- 6351 <1> ; FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME. 6352 <1> ;------------------------------------------------------------------------------- 6353 <1> FMT_INIT: 6354 0000201E F687[F9700000]10 <1> TEST byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED 6355 00002025 7546 <1> JNZ short F1_OUT ; IF SO RETURN 6356 00002027 E82C040000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN AL 6357 <1> ;; 20/02/2015 6358 <1> ;;JC short CL_DRV ; ERROR IN CMOS ASSUME NO DRIVE 6359 0000202C 7440 <1> jz short CL_DRV ;; 20/02/2015 6360 0000202E FEC8 <1> DEC AL ; MAKE ZERO ORIGIN 6361 <1> ;;JS short CL_DRV ; NO DRIVE IF AL 0 6362 00002030 8AA7[F9700000] <1> MOV AH, [DSK_STATE+eDI] ; AH = CURRENT STATE 6363 00002036 80E40F <1> AND AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR 6364 00002039 08C0 <1> OR AL,AL ; CHECK FOR 360 6365 0000203B 7505 <1> JNZ short N_360 ; IF 360 WILL BE 0 6366 0000203D 80CC90 <1> OR AH,MED_DET+RATE_250 ; ESTABLISH MEDIA 6367 00002040 EB25 <1> JMP SHORT SKP_STATE ; SKIP OTHER STATE PROCESSING 6368 <1> N_360: 6369 00002042 FEC8 <1> DEC AL ; 1.2 M DRIVE 6370 00002044 7505 <1> JNZ short N_12 ; JUMP IF NOT 6371 <1> F1_RATE: 6372 00002046 80CC10 <1> OR AH,MED_DET+RATE_500 ; SET FORMAT RATE 6373 00002049 EB1C <1> JMP SHORT SKP_STATE ; SKIP OTHER STATE PROCESSING 6374 <1> N_12: 6375 0000204B FEC8 <1> DEC AL ; CHECK FOR TYPE 3 6376 0000204D 750F <1> JNZ short N_720 ; JUMP IF NOT 6377 0000204F F6C404 <1> TEST AH,DRV_DET ; IS DRIVE DETERMINED 6378 00002052 7410 <1> JZ short ISNT_12 ; TREAT AS NON 1.2 DRIVE 6379 00002054 F6C402 <1> TEST AH,FMT_CAPA ; IS 1.2M 6380 00002057 740B <1> JZ short ISNT_12 ; JUMP IF NOT 6381 00002059 80CC50 <1> OR AH,MED_DET+RATE_300 ; RATE 300 6382 0000205C EB09 <1> JMP SHORT SKP_STATE ; CONTINUE 6383 <1> N_720: 6384 0000205E FEC8 <1> DEC AL ; CHECK FOR TYPE 4 6385 00002060 750C <1> JNZ short CL_DRV ; NO DRIVE, CMOS BAD 6386 00002062 EBE2 <1> JMP SHORT F1_RATE 6387 <1> ISNT_12: 6388 00002064 80CC90 <1> OR AH,MED_DET+RATE_250 ; MUST BE RATE 250 6389 <1> 6390 <1> SKP_STATE: 6391 00002067 88A7[F9700000] <1> MOV [DSK_STATE+eDI], AH ; STORE AWAY 6392 <1> F1_OUT: 6393 0000206D C3 <1> RETn 6394 <1> CL_DRV: 6395 0000206E 30E4 <1> XOR AH,AH ; CLEAR STATE 6396 00002070 EBF5 <1> JMP SHORT SKP_STATE ; SAVE IT 6397 <1> 6398 <1> ;------------------------------------------------------------------------------- 6399 <1> ; MED_CHANGE 6400 <1> ; CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 6401 <1> ; CHECKS MEDIA CHANGE AGAIN. 6402 <1> ; 6403 <1> ; ON EXIT: CY = 1 MEANS MEDIA CHANGE OR TIMEOUT 6404 <1> ; @DSKETTE_STATUS = ERROR CODE 6405 <1> ;------------------------------------------------------------------------------- 6406 <1> MED_CHANGE: 6407 00002072 E888060000 <1> CALL READ_DSKCHNG ; READ DISK CHANCE LINE STATE 6408 00002077 7447 <1> JZ short MC_OUT ; BYPASS HANDLING DISK CHANGE LINE 6409 00002079 80A7[F9700000]EF <1> AND byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE 6410 <1> 6411 <1> ; THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT 6412 <1> ; ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL 6413 <1> ; BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING). 6414 <1> 6415 00002080 6689F9 <1> MOV CX,DI ; CL = DRIVE 0 6416 00002083 B001 <1> MOV AL,1 ; MOTOR ON BIT MASK 6417 00002085 D2E0 <1> SHL AL,CL ; TO APPROPRIATE POSITION 6418 00002087 F6D0 <1> NOT AL ; KEEP ALL BUT MOTOR ON 6419 00002089 FA <1> CLI ; NO INTERRUPTS 6420 0000208A 2005[EA700000] <1> AND [MOTOR_STATUS], AL ; TURN MOTOR OFF INDICATOR 6421 00002090 FB <1> STI ; INTERRUPTS ENABLED 6422 00002091 E810040000 <1> CALL MOTOR_ON ; TURN MOTOR ON 6423 <1> 6424 <1> ;----- THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL 6425 <1> 6426 00002096 E884F9FFFF <1> CALL DSK_RESET ; RESET NEC 6427 0000209B B501 <1> MOV CH,01H ; MOVE TO CYLINDER 1 6428 0000209D E8FF040000 <1> CALL SEEK ; ISSUE SEEK 6429 000020A2 30ED <1> XOR CH,CH ; MOVE TO CYLINDER 0 6430 000020A4 E8F8040000 <1> CALL SEEK ; ISSUE SEEK 6431 000020A9 C605[EC700000]06 <1> MOV byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS 6432 <1> OK1: 6433 000020B0 E84A060000 <1> CALL READ_DSKCHNG ; CHECK MEDIA CHANGED AGAIN 6434 000020B5 7407 <1> JZ short OK2 ; IF ACTIVE, NO DISKETTE, TIMEOUT 6435 <1> OK4: 6436 000020B7 C605[EC700000]80 <1> MOV byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY 6437 <1> OK2: 6438 000020BE F9 <1> STC ; MEDIA CHANGED, SET CY 6439 000020BF C3 <1> RETn 6440 <1> MC_OUT: 6441 000020C0 F8 <1> CLC ; NO MEDIA CHANGED, CLEAR CY 6442 000020C1 C3 <1> RETn 6443 <1> 6444 <1> ;------------------------------------------------------------------------------- 6445 <1> ; SEND_RATE 6446 <1> ; SENDS DATA RATE COMMAND TO NEC 6447 <1> ; ON ENTRY: DI = DRIVE # 6448 <1> ; ON EXIT: NONE 6449 <1> ; REGISTERS ALTERED: DX 6450 <1> ;------------------------------------------------------------------------------- 6451 <1> SEND_RATE: 6452 000020C2 6650 <1> PUSH AX ; SAVE REG. 6453 000020C4 8025[F4700000]3F <1> AND byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED 6454 000020CB 8A87[F9700000] <1> MOV AL, [DSK_STATE+eDI] ; GET RATE STATE OF THIS DRIVE 6455 000020D1 24C0 <1> AND AL,SEND_MSK ; KEEP ONLY RATE BITS 6456 000020D3 0805[F4700000] <1> OR [LASTRATE], AL ; SAVE NEW RATE FOR NEXT CHECK 6457 000020D9 C0C002 <1> ROL AL,2 ; MOVE TO BIT OUTPUT POSITIONS 6458 000020DC 66BAF703 <1> MOV DX,03F7H ; OUTPUT NEW DATA RATE 6459 000020E0 EE <1> OUT DX,AL 6460 000020E1 6658 <1> POP AX ; RESTORE REG. 6461 000020E3 C3 <1> RETn 6462 <1> 6463 <1> ;------------------------------------------------------------------------------- 6464 <1> ; CHK_LASTRATE 6465 <1> ; CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER. 6466 <1> ; ON ENTRY: 6467 <1> ; DI = DRIVE # 6468 <1> ; ON EXIT: 6469 <1> ; ZF = 1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC 6470 <1> ; ZF = 0 DATA RATE IS DIFFERENT FROM LAST RATE 6471 <1> ; REGISTERS ALTERED: DX 6472 <1> ;------------------------------------------------------------------------------- 6473 <1> CHK_LASTRATE: 6474 000020E4 6650 <1> PUSH AX ; SAVE REG 6475 000020E6 2225[F4700000] <1> AND AH, [LASTRATE] ; GET LAST DATA RATE SELECTED 6476 000020EC 8A87[F9700000] <1> MOV AL, [DSK_STATE+eDI] ; GET RATE STATE OF THIS DRIVE 6477 000020F2 6625C0C0 <1> AND AX, SEND_MSK*257 ; KEEP ONLY RATE BITS OF BOTH 6478 000020F6 38E0 <1> CMP AL, AH ; COMPARE TO PREVIOUSLY TRIED 6479 <1> ; ZF = 1 RATE IS THE SAME 6480 000020F8 6658 <1> POP AX ; RESTORE REG. 6481 000020FA C3 <1> RETn 6482 <1> 6483 <1> ;------------------------------------------------------------------------------- 6484 <1> ; DMA_SETUP 6485 <1> ; THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS. 6486 <1> ; 6487 <1> ; ON ENTRY: AL = DMA COMMAND 6488 <1> ; 6489 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6490 <1> ;------------------------------------------------------------------------------- 6491 <1> 6492 <1> ; SI = Head #, # of Sectors or DASD Type 6493 <1> 6494 <1> ; 22/08/2015 6495 <1> ; 08/02/2015 - Protected Mode Modification 6496 <1> ; 06/02/2015 - 07/02/2015 6497 <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit). 6498 <1> ; (DMA Addres = Physical Address) 6499 <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address) 6500 <1> ; 6501 <1> ; 04/02/2016 (clc) 6502 <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP) 6503 <1> ; 16/12/2014 (IODELAY) 6504 <1> 6505 <1> DMA_SETUP: 6506 <1> 6507 <1> ;; 20/02/2015 6508 000020FB 8B5504 <1> mov edx, [ebp+4] ; Buffer address 6509 000020FE F7C2000000FF <1> test edx, 0FF000000h ; 16 MB limit (22/08/2015, bugfix) 6510 00002104 756E <1> jnz short dma_bnd_err_stc 6511 <1> ; 6512 00002106 6650 <1> push ax ; DMA command 6513 00002108 52 <1> push edx ; * 6514 00002109 B203 <1> mov dl, 3 ; GET BYTES/SECTOR PARAMETER 6515 0000210B E851030000 <1> call GET_PARM ; 6516 00002110 88E1 <1> mov cl, ah ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 6517 00002112 6689F0 <1> mov ax, si ; Sector count 6518 00002115 88C4 <1> mov ah, al ; AH = # OF SECTORS 6519 00002117 28C0 <1> sub al, al ; AL = 0, AX = # SECTORS * 256 6520 00002119 66D1E8 <1> shr ax, 1 ; AX = # SECTORS * 128 6521 0000211C 66D3E0 <1> shl ax, cl ; SHIFT BY PARAMETER VALUE 6522 0000211F 6648 <1> dec ax ; -1 FOR DMA VALUE 6523 00002121 6689C1 <1> mov cx, ax 6524 00002124 5A <1> pop edx ; * 6525 00002125 6658 <1> pop ax 6526 00002127 3C42 <1> cmp al, 42h 6527 00002129 7507 <1> jne short NOT_VERF 6528 0000212B BA0000FF00 <1> mov edx, 0FF0000h 6529 00002130 EB08 <1> jmp short J33 6530 <1> NOT_VERF: 6531 00002132 6601CA <1> add dx, cx ; check for overflow 6532 00002135 723E <1> jc short dma_bnd_err 6533 <1> ; 6534 00002137 6629CA <1> sub dx, cx ; Restore start address 6535 <1> J33: 6536 0000213A FA <1> CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 6537 0000213B E60C <1> OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 6538 <1> IODELAY ; WAIT FOR I/O 6539 0000213D EB00 <2> jmp short $+2 6540 0000213F EB00 <2> jmp short $+2 6541 00002141 E60B <1> OUT DMA+11,AL ; OUTPUT THE MODE BYTE 6542 00002143 89D0 <1> mov eax, edx ; Buffer address 6543 00002145 E604 <1> OUT DMA+4,AL ; OUTPUT LOW ADDRESS 6544 <1> IODELAY ; WAIT FOR I/O 6545 00002147 EB00 <2> jmp short $+2 6546 00002149 EB00 <2> jmp short $+2 6547 0000214B 88E0 <1> MOV AL,AH 6548 0000214D E604 <1> OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 6549 0000214F C1E810 <1> shr eax, 16 6550 <1> IODELAY ; I/O WAIT STATE 6551 00002152 EB00 <2> jmp short $+2 6552 00002154 EB00 <2> jmp short $+2 6553 00002156 E681 <1> OUT 081H,AL ; OUTPUT highest BITS TO PAGE REGISTER 6554 <1> IODELAY 6555 00002158 EB00 <2> jmp short $+2 6556 0000215A EB00 <2> jmp short $+2 6557 0000215C 6689C8 <1> mov ax, cx ; Byte count - 1 6558 0000215F E605 <1> OUT DMA+5,AL ; LOW BYTE OF COUNT 6559 <1> IODELAY ; WAIT FOR I/O 6560 00002161 EB00 <2> jmp short $+2 6561 00002163 EB00 <2> jmp short $+2 6562 00002165 88E0 <1> MOV AL, AH 6563 00002167 E605 <1> OUT DMA+5,AL ; HIGH BYTE OF COUNT 6564 <1> IODELAY 6565 00002169 EB00 <2> jmp short $+2 6566 0000216B EB00 <2> jmp short $+2 6567 0000216D FB <1> STI ; RE-ENABLE INTERRUPTS 6568 0000216E B002 <1> MOV AL, 2 ; MODE FOR 8237 6569 00002170 E60A <1> OUT DMA+10, AL ; INITIALIZE THE DISKETTE CHANNEL 6570 <1> 6571 00002172 F8 <1> clc ; 04/02/2016 6572 00002173 C3 <1> retn 6573 <1> 6574 <1> dma_bnd_err_stc: 6575 00002174 F9 <1> stc 6576 <1> dma_bnd_err: 6577 00002175 C605[EC700000]09 <1> MOV byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 6578 0000217C C3 <1> RETn ; CY SET BY ABOVE IF ERROR 6579 <1> 6580 <1> ;; 16/12/2014 6581 <1> ;; CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 6582 <1> ;; OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 6583 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6584 <1> ;; IODELAY 6585 <1> ;; OUT DMA+11,AL ; OUTPUT THE MODE BYTE 6586 <1> ;; ;SIODELAY 6587 <1> ;; ;CMP AL, 42H ; DMA VERIFY COMMAND 6588 <1> ;; ;JNE short NOT_VERF ; NO 6589 <1> ;; ;XOR AX, AX ; START ADDRESS 6590 <1> ;; ;JMP SHORT J33 6591 <1> ;;;NOT_VERF: 6592 <1> ;; ;MOV AX,ES ; GET THE ES VALUE 6593 <1> ;; ;ROL AX,4 ; ROTATE LEFT 6594 <1> ;; ;MOV CH,AL ; GET HIGHEST NIBBLE OF ES TO CH 6595 <1> ;; ;AND AL,11110000B ; ZERO THE LOW NIBBLE FROM SEGMENT 6596 <1> ;; ;ADD AX,[BP+2] ; TEST FOR CARRY FROM ADDITION 6597 <1> ;; mov eax, [ebp+4] ; 06/02/2015 6598 <1> ;; ;JNC short J33 6599 <1> ;; ;INC CH ; CARRY MEANS HIGH 4 BITS MUST BE INC 6600 <1> ;;;J33: 6601 <1> ;; PUSH eAX ; SAVE START ADDRESS 6602 <1> ;; OUT DMA+4,AL ; OUTPUT LOW ADDRESS 6603 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6604 <1> ;; IODELAY 6605 <1> ;; MOV AL,AH 6606 <1> ;; OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 6607 <1> ;; shr eax, 16 ; 07/02/2015 6608 <1> ;; ;MOV AL,CH ; GET HIGH 4 BITS 6609 <1> ;; ;JMP $+2 ; I/O WAIT STATE 6610 <1> ;; IODELAY 6611 <1> ;; ;AND AL,00001111B 6612 <1> ;; OUT 081H,AL ; OUTPUT HIGH 4 BITS TO PAGE REGISTER 6613 <1> ;; ;SIODELAY 6614 <1> ;; 6615 <1> ;;;----- DETERMINE COUNT 6616 <1> ;; sub eax, eax ; 08/02/2015 6617 <1> ;; MOV AX, SI ; AL = # OF SECTORS 6618 <1> ;; XCHG AL, AH ; AH = # OF SECTORS 6619 <1> ;; SUB AL, AL ; AL = 0, AX = # SECTORS * 256 6620 <1> ;; SHR AX, 1 ; AX = # SECTORS * 128 6621 <1> ;; PUSH AX ; SAVE # OF SECTORS * 128 6622 <1> ;; MOV DL, 3 ; GET BYTES/SECTOR PARAMETER 6623 <1> ;; CALL GET_PARM ; " 6624 <1> ;; MOV CL,AH ; SHIFT COUNT (0=128, 1=256, 2=512 ETC) 6625 <1> ;; POP AX ; AX = # SECTORS * 128 6626 <1> ;; SHL AX,CL ; SHIFT BY PARAMETER VALUE 6627 <1> ;; DEC AX ; -1 FOR DMA VALUE 6628 <1> ;; PUSH eAX ; 08/02/2015 ; SAVE COUNT VALUE 6629 <1> ;; OUT DMA+5,AL ; LOW BYTE OF COUNT 6630 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6631 <1> ;; IODELAY 6632 <1> ;; MOV AL, AH 6633 <1> ;; OUT DMA+5,AL ; HIGH BYTE OF COUNT 6634 <1> ;; ;IODELAY 6635 <1> ;; STI ; RE-ENABLE INTERRUPTS 6636 <1> ;; POP eCX ; 08/02/2015 ; RECOVER COUNT VALUE 6637 <1> ;; POP eAX ; 08/02/2015 ; RECOVER ADDRESS VALUE 6638 <1> ;; ;ADD AX, CX ; ADD, TEST FOR 64K OVERFLOW 6639 <1> ;; add ecx, eax ; 08/02/2015 6640 <1> ;; MOV AL, 2 ; MODE FOR 8237 6641 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6642 <1> ;; SIODELAY 6643 <1> ;; OUT DMA+10, AL ; INITIALIZE THE DISKETTE CHANNEL 6644 <1> ;; ;JNC short NO_BAD ; CHECK FOR ERROR 6645 <1> ;; jc short dma_bnd_err ; 08/02/2015 6646 <1> ;; and ecx, 0FFF00000h ; 16 MB limit 6647 <1> ;; jz short NO_BAD 6648 <1> ;;dma_bnd_err: 6649 <1> ;; MOV byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 6650 <1> ;;NO_BAD: 6651 <1> ;; RETn ; CY SET BY ABOVE IF ERROR 6652 <1> 6653 <1> ;------------------------------------------------------------------------------- 6654 <1> ; FMTDMA_SET 6655 <1> ; THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION. 6656 <1> ; 6657 <1> ; ON ENTRY: NOTHING REQUIRED 6658 <1> ; 6659 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6660 <1> ;------------------------------------------------------------------------------- 6661 <1> 6662 <1> FMTDMA_SET: 6663 <1> ;; 20/02/2015 modification 6664 0000217D 8B5504 <1> mov edx, [ebp+4] ; Buffer address 6665 00002180 F7C20000F0FF <1> test edx, 0FFF00000h ; 16 MB limit 6666 00002186 75EC <1> jnz short dma_bnd_err_stc 6667 <1> ; 6668 00002188 6652 <1> push dx ; * 6669 0000218A B204 <1> mov DL, 4 ; SECTORS/TRACK VALUE IN PARM TABLE 6670 0000218C E8D0020000 <1> call GET_PARM ; " 6671 00002191 88E0 <1> mov al, ah ; AL = SECTORS/TRACK VALUE 6672 00002193 28E4 <1> sub ah, ah ; AX = SECTORS/TRACK VALUE 6673 00002195 66C1E002 <1> shl ax, 2 ; AX = SEC/TRK * 4 (OFFSET C,H,R,N) 6674 00002199 6648 <1> dec ax ; -1 FOR DMA VALUE 6675 0000219B 6689C1 <1> mov cx, ax 6676 0000219E 665A <1> pop dx ; * 6677 000021A0 6601CA <1> add dx, cx ; check for overflow 6678 000021A3 72D0 <1> jc short dma_bnd_err 6679 <1> ; 6680 000021A5 6629CA <1> sub dx, cx ; Restore start address 6681 <1> ; 6682 000021A8 B04A <1> MOV AL, 04AH ; WILL WRITE TO THE DISKETTE 6683 000021AA FA <1> CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 6684 000021AB E60C <1> OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 6685 <1> IODELAY ; WAIT FOR I/O 6686 000021AD EB00 <2> jmp short $+2 6687 000021AF EB00 <2> jmp short $+2 6688 000021B1 E60B <1> OUT DMA+11,AL ; OUTPUT THE MODE BYTE 6689 000021B3 89D0 <1> mov eax, edx ; Buffer address 6690 000021B5 E604 <1> OUT DMA+4,AL ; OUTPUT LOW ADDRESS 6691 <1> IODELAY ; WAIT FOR I/O 6692 000021B7 EB00 <2> jmp short $+2 6693 000021B9 EB00 <2> jmp short $+2 6694 000021BB 88E0 <1> MOV AL,AH 6695 000021BD E604 <1> OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 6696 000021BF C1E810 <1> shr eax, 16 6697 <1> IODELAY ; I/O WAIT STATE 6698 000021C2 EB00 <2> jmp short $+2 6699 000021C4 EB00 <2> jmp short $+2 6700 000021C6 E681 <1> OUT 081H,AL ; OUTPUT highest BITS TO PAGE REGISTER 6701 <1> IODELAY 6702 000021C8 EB00 <2> jmp short $+2 6703 000021CA EB00 <2> jmp short $+2 6704 000021CC 6689C8 <1> mov ax, cx ; Byte count - 1 6705 000021CF E605 <1> OUT DMA+5,AL ; LOW BYTE OF COUNT 6706 <1> IODELAY ; WAIT FOR I/O 6707 000021D1 EB00 <2> jmp short $+2 6708 000021D3 EB00 <2> jmp short $+2 6709 000021D5 88E0 <1> MOV AL, AH 6710 000021D7 E605 <1> OUT DMA+5,AL ; HIGH BYTE OF COUNT 6711 <1> IODELAY 6712 000021D9 EB00 <2> jmp short $+2 6713 000021DB EB00 <2> jmp short $+2 6714 000021DD FB <1> STI ; RE-ENABLE INTERRUPTS 6715 000021DE B002 <1> MOV AL, 2 ; MODE FOR 8237 6716 000021E0 E60A <1> OUT DMA+10, AL ; INITIALIZE THE DISKETTE CHANNEL 6717 000021E2 C3 <1> retn 6718 <1> 6719 <1> ;; 08/02/2015 - Protected Mode Modification 6720 <1> ;; MOV AL, 04AH ; WILL WRITE TO THE DISKETTE 6721 <1> ;; CLI ; DISABLE INTERRUPTS DURING DMA SET-UP 6722 <1> ;; OUT DMA+12,AL ; SET THE FIRST/LA5T F/F 6723 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6724 <1> ;; IODELAY 6725 <1> ;; OUT DMA+11,AL ; OUTPUT THE MODE BYTE 6726 <1> ;; ;MOV AX,ES ; GET THE ES VALUE 6727 <1> ;; ;ROL AX,4 ; ROTATE LEFT 6728 <1> ;; ;MOV CH,AL ; GET HIGHEST NIBBLE OF ES TO CH 6729 <1> ;; ;AND AL,11110000B ; ZERO THE LOW NIBBLE FROM SEGMENT 6730 <1> ;; ;ADD AX,[BP+2] ; TEST FOR CARRY FROM ADDITION 6731 <1> ;; ;JNC short J33A 6732 <1> ;; ;INC CH ; CARRY MEANS HIGH 4 BITS MUST BE INC 6733 <1> ;; mov eax, [ebp+4] ; 08/02/2015 6734 <1> ;;;J33A: 6735 <1> ;; PUSH eAX ; 08/02/2015 ; SAVE START ADDRESS 6736 <1> ;; OUT DMA+4,AL ; OUTPUT LOW ADDRESS 6737 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6738 <1> ;; IODELAY 6739 <1> ;; MOV AL,AH 6740 <1> ;; OUT DMA+4,AL ; OUTPUT HIGH ADDRESS 6741 <1> ;; shr eax, 16 ; 08/02/2015 6742 <1> ;; ;MOV AL,CH ; GET HIGH 4 BITS 6743 <1> ;; ;JMP $+2 ; I/O WAIT STATE 6744 <1> ;; IODELAY 6745 <1> ;; ;AND AL,00001111B 6746 <1> ;; OUT 081H,AL ; OUTPUT HIGH 4 BITS TO PAGE REGISTER 6747 <1> ;; 6748 <1> ;;;----- DETERMINE COUNT 6749 <1> ;; sub eax, eax ; 08/02/2015 6750 <1> ;; MOV DL, 4 ; SECTORS/TRACK VALUE IN PARM TABLE 6751 <1> ;; CALL GET_PARM ; " 6752 <1> ;; XCHG AL, AH ; AL = SECTORS/TRACK VALUE 6753 <1> ;; SUB AH, AH ; AX = SECTORS/TRACK VALUE 6754 <1> ;; SHL AX, 2 ; AX = SEC/TRK * 4 (OFFSET C,H,R,N) 6755 <1> ;; DEC AX ; -1 FOR DMA VALUE 6756 <1> ;; PUSH eAX ; 08/02/2015 ; SAVE # OF BYTES TO BE TRANSFERED 6757 <1> ;; OUT DMA+5,AL ; LOW BYTE OF COUNT 6758 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6759 <1> ;; IODELAY 6760 <1> ;; MOV AL, AH 6761 <1> ;; OUT DMA+5,AL ; HIGH BYTE OF COUNT 6762 <1> ;; STI ; RE-ENABLE INTERRUPTS 6763 <1> ;; POP eCX ; 08/02/2015 ; RECOVER COUNT VALUE 6764 <1> ;; POP eAX ; 08/02/2015 ; RECOVER ADDRESS VALUE 6765 <1> ;; ;ADD AX, CX ; ADD, TEST FOR 64K OVERFLOW 6766 <1> ;; add ecx, eax ; 08/02/2015 6767 <1> ;; MOV AL, 2 ; MODE FOR 8237 6768 <1> ;; ;JMP $+2 ; WAIT FOR I/O 6769 <1> ;; SIODELAY 6770 <1> ;; OUT DMA+10, AL ; INITIALIZE THE DISKETTE CHANNEL 6771 <1> ;; ;JNC short FMTDMA_OK ; CHECK FOR ERROR 6772 <1> ;; jc short fmtdma_bnd_err ; 08/02/2015 6773 <1> ;; and ecx, 0FFF00000h ; 16 MB limit 6774 <1> ;; jz short FMTDMA_OK 6775 <1> ;; stc ; 20/02/2015 6776 <1> ;;fmtdma_bnd_err: 6777 <1> ;; MOV byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR 6778 <1> ;;FMTDMA_OK: 6779 <1> ;; RETn ; CY SET BY ABOVE IF ERROR 6780 <1> 6781 <1> ;------------------------------------------------------------------------------- 6782 <1> ; NEC_INIT 6783 <1> ; THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES 6784 <1> ; THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION. 6785 <1> ; 6786 <1> ; ON ENTRY: AH = NEC COMMAND TO BE PERFORMED 6787 <1> ; 6788 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6789 <1> ;------------------------------------------------------------------------------- 6790 <1> NEC_INIT: 6791 000021E3 6650 <1> PUSH AX ; SAVE NEC COMMAND 6792 000021E5 E8BC020000 <1> CALL MOTOR_ON ; TURN MOTOR ON FOR SPECIFIC DRIVE 6793 <1> 6794 <1> ;----- DO THE SEEK OPERATION 6795 <1> 6796 000021EA 8A6D01 <1> MOV CH,[eBP+1] ; CH = TRACK # 6797 000021ED E8AF030000 <1> CALL SEEK ; MOVE TO CORRECT TRACK 6798 000021F2 6658 <1> POP AX ; RECOVER COMMAND 6799 000021F4 721E <1> JC short ER_1 ; ERROR ON SEEK 6800 000021F6 BB[14220000] <1> MOV eBX, ER_1 ; LOAD ERROR ADDRESS 6801 000021FB 53 <1> PUSH eBX ; PUSH NEC_OUT ERROR RETURN 6802 <1> 6803 <1> ;----- SEND OUT THE PARAMETERS TO THE CONTROLLER 6804 <1> 6805 000021FC E866030000 <1> CALL NEC_OUTPUT ; OUTPUT THE OPERATION COMMAND 6806 00002201 6689F0 <1> MOV AX,SI ; AH = HEAD # 6807 00002204 89FB <1> MOV eBX,eDI ; BL = DRIVE # 6808 00002206 C0E402 <1> SAL AH,2 ; MOVE IT TO BIT 2 6809 00002209 80E404 <1> AND AH,00000100B ; ISOLATE THAT BIT 6810 0000220C 08DC <1> OR AH,BL ; OR IN THE DRIVE NUMBER 6811 0000220E E854030000 <1> CALL NEC_OUTPUT ; FALL THRU CY SET IF ERROR 6812 00002213 5B <1> POP eBX ; THROW AWAY ERROR RETURN 6813 <1> ER_1: 6814 00002214 C3 <1> RETn 6815 <1> 6816 <1> ;------------------------------------------------------------------------------- 6817 <1> ; RWV_COM 6818 <1> ; THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 6819 <1> ; READ/WRITE/VERIFY OPERATIONS. 6820 <1> ; 6821 <1> ; ON ENTRY: CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE 6822 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6823 <1> ;------------------------------------------------------------------------------- 6824 <1> RWV_COM: 6825 00002215 B8[60220000] <1> MOV eAX, ER_2 ; LOAD ERROR ADDRESS 6826 0000221A 50 <1> PUSH eAX ; PUSH NEC_OUT ERROR RETURN 6827 0000221B 8A6501 <1> MOV AH,[eBP+1] ; OUTPUT TRACK # 6828 0000221E E844030000 <1> CALL NEC_OUTPUT 6829 00002223 6689F0 <1> MOV AX,SI ; OUTPUT HEAD # 6830 00002226 E83C030000 <1> CALL NEC_OUTPUT 6831 0000222B 8A6500 <1> MOV AH,[eBP] ; OUTPUT SECTOR # 6832 0000222E E834030000 <1> CALL NEC_OUTPUT 6833 00002233 B203 <1> MOV DL,3 ; BYTES/SECTOR PARAMETER FROM BLOCK 6834 00002235 E827020000 <1> CALL GET_PARM ; ... TO THE NEC 6835 0000223A E828030000 <1> CALL NEC_OUTPUT ; OUTPUT TO CONTROLLER 6836 0000223F B204 <1> MOV DL,4 ; EOT PARAMETER FROM BLOCK 6837 00002241 E81B020000 <1> CALL GET_PARM ; ... TO THE NEC 6838 00002246 E81C030000 <1> CALL NEC_OUTPUT ; OUTPUT TO CONTROLLER 6839 0000224B 8A6305 <1> MOV AH, [eBX+MD.GAP] ; GET GAP LENGTH 6840 <1> _R15: 6841 0000224E E814030000 <1> CALL NEC_OUTPUT 6842 00002253 B206 <1> MOV DL,6 ; DTL PARAMETER PROM BLOCK 6843 00002255 E807020000 <1> CALL GET_PARM ; TO THE NEC 6844 0000225A E808030000 <1> CALL NEC_OUTPUT ; OUTPUT TO CONTROLLER 6845 0000225F 58 <1> POP eAX ; THROW AWAY ERROR EXIT 6846 <1> ER_2: 6847 00002260 C3 <1> RETn 6848 <1> 6849 <1> ;------------------------------------------------------------------------------- 6850 <1> ; NEC_TERM 6851 <1> ; THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 6852 <1> ; FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION. 6853 <1> ; 6854 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 6855 <1> ;------------------------------------------------------------------------------- 6856 <1> NEC_TERM: 6857 <1> 6858 <1> ;----- LET THE OPERATION HAPPEN 6859 <1> 6860 00002261 56 <1> PUSH eSI ; SAVE HEAD #, # OF SECTORS 6861 00002262 E80D040000 <1> CALL WAIT_INT ; WAIT FOR THE INTERRUPT 6862 00002267 9C <1> PUSHF 6863 00002268 E837040000 <1> CALL RESULTS ; GET THE NEC STATUS 6864 0000226D 724B <1> JC short SET_END_POP 6865 0000226F 9D <1> POPF 6866 00002270 723E <1> JC short SET_END ; LOOK FOR ERROR 6867 <1> 6868 <1> ;----- CHECK THE RESULTS RETURNED BY THE CONTROLLER 6869 <1> 6870 00002272 FC <1> CLD ; SET THE CORRECT DIRECTION 6871 00002273 BE[ED700000] <1> MOV eSI, NEC_STATUS ; POINT TO STATUS FIELD 6872 00002278 AC <1> lodsb ; GET ST0 6873 00002279 24C0 <1> AND AL,11000000B ; TEST FOR NORMAL TERMINATION 6874 0000227B 7433 <1> JZ short SET_END 6875 0000227D 3C40 <1> CMP AL,01000000B ; TEST FOR ABNORMAL TERMINATION 6876 0000227F 7527 <1> JNZ short J18 ; NOT ABNORMAL, BAD NEC 6877 <1> 6878 <1> ;----- ABNORMAL TERMINATION, FIND OUT WHY 6879 <1> 6880 00002281 AC <1> lodsb ; GET ST1 6881 00002282 D0E0 <1> SAL AL,1 ; TEST FOR EDT FOUND 6882 00002284 B404 <1> MOV AH,RECORD_NOT_FND 6883 00002286 7222 <1> JC short J19 6884 00002288 C0E002 <1> SAL AL,2 6885 0000228B B410 <1> MOV AH,BAD_CRC 6886 0000228D 721B <1> JC short J19 6887 0000228F D0E0 <1> SAL AL,1 ; TEST FOR DMA OVERRUN 6888 00002291 B408 <1> MOV AH,BAD_DMA 6889 00002293 7215 <1> JC short J19 6890 00002295 C0E002 <1> SAL AL,2 ; TEST FOR RECORD NOT FOUND 6891 00002298 B404 <1> MOV AH,RECORD_NOT_FND 6892 0000229A 720E <1> JC short J19 6893 0000229C D0E0 <1> SAL AL,1 6894 0000229E B403 <1> MOV AH,WRITE_PROTECT ; TEST FOR WRITE_PROTECT 6895 000022A0 7208 <1> JC short J19 6896 000022A2 D0E0 <1> SAL AL,1 ; TEST MISSING ADDRESS MARK 6897 000022A4 B402 <1> MOV AH,BAD_ADDR_MARK 6898 000022A6 7202 <1> JC short J19 6899 <1> 6900 <1> ;----- NEC MUST HAVE FAILED 6901 <1> J18: 6902 000022A8 B420 <1> MOV AH,BAD_NEC 6903 <1> J19: 6904 000022AA 0825[EC700000] <1> OR [DSKETTE_STATUS], AH 6905 <1> SET_END: 6906 000022B0 803D[EC700000]01 <1> CMP byte [DSKETTE_STATUS], 1 ; SET ERROR CONDITION 6907 000022B7 F5 <1> CMC 6908 000022B8 5E <1> POP eSI 6909 000022B9 C3 <1> RETn ; RESTORE HEAD #, # OF SECTORS 6910 <1> 6911 <1> SET_END_POP: 6912 000022BA 9D <1> POPF 6913 000022BB EBF3 <1> JMP SHORT SET_END 6914 <1> 6915 <1> ;------------------------------------------------------------------------------- 6916 <1> ; DSTATE: ESTABLISH STATE UPON SUCCESSFUL OPERATION. 6917 <1> ;------------------------------------------------------------------------------- 6918 <1> DSTATE: 6919 000022BD 803D[EC700000]00 <1> CMP byte [DSKETTE_STATUS],0 ; CHECK FOR ERROR 6920 000022C4 753E <1> JNZ short SETBAC ; IF ERROR JUMP 6921 000022C6 808F[F9700000]10 <1> OR byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED 6922 000022CD F687[F9700000]04 <1> TEST byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ? 6923 000022D4 752E <1> JNZ short SETBAC ; IF DETERMINED NO TRY TO DETERMINE 6924 000022D6 8A87[F9700000] <1> MOV AL,[DSK_STATE+eDI] ; LOAD STATE 6925 000022DC 24C0 <1> AND AL,RATE_MSK ; KEEP ONLY RATE 6926 000022DE 3C80 <1> CMP AL,RATE_250 ; RATE 250 ? 6927 000022E0 751B <1> JNE short M_12 ; NO, MUST BE 1.2M OR 1.44M DRIVE 6928 <1> 6929 <1> ;----- CHECK IF IT IS 1.44M 6930 <1> 6931 000022E2 E871010000 <1> CALL CMOS_TYPE ; RETURN DRIVE TYPE IN (AL) 6932 <1> ;;20/02/2015 6933 <1> ;;JC short M_12 ; CMOS BAD 6934 000022E7 7414 <1> jz short M_12 ;; 20/02/2015 6935 000022E9 3C04 <1> CMP AL, 4 ; 1.44MB DRIVE ? 6936 000022EB 7410 <1> JE short M_12 ; YES 6937 <1> M_720: 6938 000022ED 80A7[F9700000]FD <1> AND byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY 6939 000022F4 808F[F9700000]04 <1> OR byte [DSK_STATE+eDI],DRV_DET ; MARK DRIVE DETERMINED 6940 000022FB EB07 <1> JMP SHORT SETBAC ; BACK 6941 <1> M_12: 6942 000022FD 808F[F9700000]06 <1> OR byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 6943 <1> ; TURN ON DETERMINED & FMT CAPA 6944 <1> SETBAC: 6945 00002304 C3 <1> RETn 6946 <1> 6947 <1> ;------------------------------------------------------------------------------- 6948 <1> ; RETRY 6949 <1> ; DETERMINES WHETHER A RETRY IS NECESSARY. 6950 <1> ; IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY. 6951 <1> ; 6952 <1> ; ON EXIT: CY = 1 FOR RETRY, CY = 0 FOR NO RETRY 6953 <1> ;------------------------------------------------------------------------------- 6954 <1> RETRY: 6955 00002305 803D[EC700000]00 <1> CMP byte [DSKETTE_STATUS],0 ; GET STATUS OF OPERATION 6956 0000230C 7445 <1> JZ short NO_RETRY ; SUCCESSFUL OPERATION 6957 0000230E 803D[EC700000]80 <1> CMP byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY 6958 00002315 743C <1> JZ short NO_RETRY 6959 00002317 8AA7[F9700000] <1> MOV AH,[DSK_STATE+eDI] ; GET MEDIA STATE OF DRIVE 6960 0000231D F6C410 <1> TEST AH,MED_DET ; ESTABLISHED/DETERMINED ? 6961 00002320 7531 <1> JNZ short NO_RETRY ; IF ESTABLISHED STATE THEN TRUE ERROR 6962 00002322 80E4C0 <1> AND AH,RATE_MSK ; ISOLATE RATE 6963 00002325 8A2D[F4700000] <1> MOV CH,[LASTRATE] ; GET START OPERATION STATE 6964 0000232B C0C504 <1> ROL CH,4 ; TO CORRESPONDING BITS 6965 0000232E 80E5C0 <1> AND CH,RATE_MSK ; ISOLATE RATE BITS 6966 00002331 38E5 <1> CMP CH,AH ; ALL RATES TRIED 6967 00002333 741E <1> JE short NO_RETRY ; IF YES, THEN TRUE ERROR 6968 <1> 6969 <1> ; SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE 6970 <1> ; 00000000B (500) -> 10000000B (250) 6971 <1> ; 10000000B (250) -> 01000000B (300) 6972 <1> ; 01000000B (300) -> 00000000B (500) 6973 <1> 6974 00002335 80FC01 <1> CMP AH,RATE_500+1 ; SET CY FOR RATE 500 6975 00002338 D0DC <1> RCR AH,1 ; TO NEXT STATE 6976 0000233A 80E4C0 <1> AND AH,RATE_MSK ; KEEP ONLY RATE BITS 6977 0000233D 80A7[F9700000]1F <1> AND byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) 6978 <1> ; RATE, DBL STEP OFF 6979 00002344 08A7[F9700000] <1> OR [DSK_STATE+eDI],AH ; TURN ON NEW RATE 6980 0000234A C605[EC700000]00 <1> MOV byte [DSKETTE_STATUS],0 ; RESET STATUS FOR RETRY 6981 00002351 F9 <1> STC ; SET CARRY FOR RETRY 6982 00002352 C3 <1> RETn ; RETRY RETURN 6983 <1> 6984 <1> NO_RETRY: 6985 00002353 F8 <1> CLC ; CLEAR CARRY NO RETRY 6986 00002354 C3 <1> RETn ; NO RETRY RETURN 6987 <1> 6988 <1> ;------------------------------------------------------------------------------- 6989 <1> ; NUM_TRANS 6990 <1> ; THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE 6991 <1> ; ACTUALLY TRANSFERRED TO/FROM THE DISKETTE. 6992 <1> ; 6993 <1> ; ON ENTRY: [BP+1] = TRACK 6994 <1> ; SI-HI = HEAD 6995 <1> ; [BP] = START SECTOR 6996 <1> ; 6997 <1> ; ON EXIT: AL = NUMBER ACTUALLY TRANSFERRED 6998 <1> ;------------------------------------------------------------------------------- 6999 <1> NUM_TRANS: 7000 00002355 30C0 <1> XOR AL,AL ; CLEAR FOR ERROR 7001 00002357 803D[EC700000]00 <1> CMP byte [DSKETTE_STATUS],0 ; CHECK FOR ERROR 7002 0000235E 752C <1> JNZ NT_OUT ; IF ERROR 0 TRANSFERRED 7003 00002360 B204 <1> MOV DL,4 ; SECTORS/TRACK OFFSET TO DL 7004 00002362 E8FA000000 <1> CALL GET_PARM ; AH = SECTORS/TRACK 7005 00002367 8A1D[F2700000] <1> MOV BL, [NEC_STATUS+5] ; GET ENDING SECTOR 7006 0000236D 6689F1 <1> MOV CX,SI ; CH = HEAD # STARTED 7007 00002370 3A2D[F1700000] <1> CMP CH, [NEC_STATUS+4] ; GET HEAD ENDED UP ON 7008 00002376 750D <1> JNZ DIF_HD ; IF ON SAME HEAD, THEN NO ADJUST 7009 00002378 8A2D[F0700000] <1> MOV CH, [NEC_STATUS+3] ; GET TRACK ENDED UP ON 7010 0000237E 3A6D01 <1> CMP CH,[eBP+1] ; IS IT ASKED FOR TRACK 7011 00002381 7404 <1> JZ short SAME_TRK ; IF SAME TRACK NO INCREASE 7012 00002383 00E3 <1> ADD BL,AH ; ADD SECTORS/TRACK 7013 <1> DIF_HD: 7014 00002385 00E3 <1> ADD BL,AH ; ADD SECTORS/TRACK 7015 <1> SAME_TRK: 7016 00002387 2A5D00 <1> SUB BL,[eBP] ; SUBTRACT START FROM END 7017 0000238A 88D8 <1> MOV AL,BL ; TO AL 7018 <1> NT_OUT: 7019 0000238C C3 <1> RETn 7020 <1> 7021 <1> ;------------------------------------------------------------------------------- 7022 <1> ; SETUP_END 7023 <1> ; RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 7024 <1> ; AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY. 7025 <1> ; 7026 <1> ; ON EXIT: 7027 <1> ; AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 7028 <1> ;------------------------------------------------------------------------------- 7029 <1> SETUP_END: 7030 0000238D B202 <1> MOV DL,2 ; GET THE MOTOR WAIT PARAMETER 7031 0000238F 6650 <1> PUSH AX ; SAVE NUMBER TRANSFERRED 7032 00002391 E8CB000000 <1> CALL GET_PARM 7033 00002396 8825[EB700000] <1> MOV [MOTOR_COUNT],AH ; STORE UPON RETURN 7034 0000239C 6658 <1> POP AX ; RESTORE NUMBER TRANSFERRED 7035 0000239E 8A25[EC700000] <1> MOV AH, [DSKETTE_STATUS] ; GET STATUS OF OPERATION 7036 000023A4 08E4 <1> OR AH,AH ; CHECK FOR ERROR 7037 000023A6 7402 <1> JZ short NUN_ERR ; NO ERROR 7038 000023A8 30C0 <1> XOR AL,AL ; CLEAR NUMBER RETURNED 7039 <1> NUN_ERR: 7040 000023AA 80FC01 <1> CMP AH,1 ; SET THE CARRY FLAG TO INDICATE 7041 000023AD F5 <1> CMC ; SUCCESS OR FAILURE 7042 000023AE C3 <1> RETn 7043 <1> 7044 <1> ;------------------------------------------------------------------------------- 7045 <1> ; SETUP_DBL 7046 <1> ; CHECK DOUBLE STEP. 7047 <1> ; 7048 <1> ; ON ENTRY : DI = DRIVE 7049 <1> ; 7050 <1> ; ON EXIT : CY = 1 MEANS ERROR 7051 <1> ;------------------------------------------------------------------------------- 7052 <1> SETUP_DBL: 7053 000023AF 8AA7[F9700000] <1> MOV AH, [DSK_STATE+eDI] ; ACCESS STATE 7054 000023B5 F6C410 <1> TEST AH,MED_DET ; ESTABLISHED STATE ? 7055 000023B8 757E <1> JNZ short NO_DBL ; IF ESTABLISHED THEN DOUBLE DONE 7056 <1> 7057 <1> ;----- CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE 7058 <1> 7059 000023BA C605[E9700000]00 <1> MOV byte [SEEK_STATUS],0 ; SET RECALIBRATE REQUIRED ON ALL DRIVES 7060 000023C1 E8E0000000 <1> CALL MOTOR_ON ; ENSURE MOTOR STAY ON 7061 000023C6 B500 <1> MOV CH,0 ; LOAD TRACK 0 7062 000023C8 E8D4010000 <1> CALL SEEK ; SEEK TO TRACK 0 7063 000023CD E868000000 <1> CALL READ_ID ; READ ID FUNCTION 7064 000023D2 7249 <1> JC short SD_ERR ; IF ERROR NO TRACK 0 7065 <1> 7066 <1> ;----- INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS) 7067 <1> 7068 000023D4 66B95004 <1> MOV CX,0450H ; START, MAX TRACKS 7069 000023D8 F687[F9700000]01 <1> TEST byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY 7070 000023DF 7402 <1> JZ short CNT_OK ; IF NOT COUNT IS SETUP 7071 000023E1 B1A0 <1> MOV CL,0A0H ; MAXIMUM TRACK 1.2 MB 7072 <1> 7073 <1> ; ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS, 7074 <1> ; MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT 7075 <1> ; THEN SET DOUBLE STEP ON. 7076 <1> 7077 <1> CNT_OK: 7078 000023E3 C605[EB700000]FF <1> MOV byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 7079 000023EA 6651 <1> PUSH CX ; SAVE TRACK, COUNT 7080 000023EC C605[EC700000]00 <1> MOV byte [DSKETTE_STATUS],0 ; CLEAR STATUS, EXPECT ERRORS 7081 000023F3 6631C0 <1> XOR AX,AX ; CLEAR AX 7082 000023F6 D0ED <1> SHR CH,1 ; HALVE TRACK, CY = HEAD 7083 000023F8 C0D003 <1> RCL AL,3 ; AX = HEAD IN CORRECT BIT 7084 000023FB 6650 <1> PUSH AX ; SAVE HEAD 7085 000023FD E89F010000 <1> CALL SEEK ; SEEK TO TRACK 7086 00002402 6658 <1> POP AX ; RESTORE HEAD 7087 00002404 6609C7 <1> OR DI,AX ; DI = HEAD OR'ED DRIVE 7088 00002407 E82E000000 <1> CALL READ_ID ; READ ID HEAD 0 7089 0000240C 9C <1> PUSHF ; SAVE RETURN FROM READ_ID 7090 0000240D 6681E7FB00 <1> AND DI,11111011B ; TURN OFF HEAD 1 BIT 7091 00002412 9D <1> POPF ; RESTORE ERROR RETURN 7092 00002413 6659 <1> POP CX ; RESTORE COUNT 7093 00002415 7308 <1> JNC short DO_CHK ; IF OK, ASKED = RETURNED TRACK ? 7094 00002417 FEC5 <1> INC CH ; INC FOR NEXT TRACK 7095 00002419 38CD <1> CMP CH,CL ; REACHED MAXIMUM YET 7096 0000241B 75C6 <1> JNZ short CNT_OK ; CONTINUE TILL ALL TRIED 7097 <1> 7098 <1> ;----- FALL THRU, READ ID FAILED FOR ALL TRACKS 7099 <1> 7100 <1> SD_ERR: 7101 0000241D F9 <1> STC ; SET CARRY FOR ERROR 7102 0000241E C3 <1> RETn ; SETUP_DBL ERROR EXIT 7103 <1> 7104 <1> DO_CHK: 7105 0000241F 8A0D[F0700000] <1> MOV CL, [NEC_STATUS+3] ; LOAD RETURNED TRACK 7106 00002425 888F[FD700000] <1> MOV [DSK_TRK+eDI], CL ; STORE TRACK NUMBER 7107 0000242B D0ED <1> SHR CH,1 ; HALVE TRACK 7108 0000242D 38CD <1> CMP CH,CL ; IS IT THE SAME AS ASKED FOR TRACK 7109 0000242F 7407 <1> JZ short NO_DBL ; IF SAME THEN NO DOUBLE STEP 7110 00002431 808F[F9700000]20 <1> OR byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED 7111 <1> NO_DBL: 7112 00002438 F8 <1> CLC ; CLEAR ERROR FLAG 7113 00002439 C3 <1> RETn 7114 <1> 7115 <1> ;------------------------------------------------------------------------------- 7116 <1> ; READ_ID 7117 <1> ; READ ID FUNCTION. 7118 <1> ; 7119 <1> ; ON ENTRY: DI : BIT 2 = HEAD; BITS 1,0 = DRIVE 7120 <1> ; 7121 <1> ; ON EXIT: DI : BIT 2 IS RESET, BITS 1,0 = DRIVE 7122 <1> ; @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION 7123 <1> ;------------------------------------------------------------------------------- 7124 <1> READ_ID: 7125 0000243A B8[57240000] <1> MOV eAX, ER_3 ; MOVE NEC OUTPUT ERROR ADDRESS 7126 0000243F 50 <1> PUSH eAX 7127 00002440 B44A <1> MOV AH,4AH ; READ ID COMMAND 7128 00002442 E820010000 <1> CALL NEC_OUTPUT ; TO CONTROLLER 7129 00002447 6689F8 <1> MOV AX,DI ; DRIVE # TO AH, HEAD 0 7130 0000244A 88C4 <1> MOV AH,AL 7131 0000244C E816010000 <1> CALL NEC_OUTPUT ; TO CONTROLLER 7132 00002451 E80BFEFFFF <1> CALL NEC_TERM ; WAIT FOR OPERATION, GET STATUS 7133 00002456 58 <1> POP eAX ; THROW AWAY ERROR ADDRESS 7134 <1> ER_3: 7135 00002457 C3 <1> RETn 7136 <1> 7137 <1> ;------------------------------------------------------------------------------- 7138 <1> ; CMOS_TYPE 7139 <1> ; RETURNS DISKETTE TYPE FROM CMOS 7140 <1> ; 7141 <1> ; ON ENTRY: DI = DRIVE # 7142 <1> ; 7143 <1> ; ON EXIT: AL = TYPE; CY REFLECTS STATUS 7144 <1> ;------------------------------------------------------------------------------- 7145 <1> 7146 <1> CMOS_TYPE: ; 11/12/2014 7147 00002458 8A87[1E6B0000] <1> mov al, [eDI+fd0_type] 7148 0000245E 20C0 <1> and al, al ; 18/12/2014 7149 00002460 C3 <1> retn 7150 <1> 7151 <1> ;CMOS_TYPE: 7152 <1> ; MOV AL, CMOS_DIAG ; CMOS DIAGNOSTIC STATUS BYTE ADDRESS 7153 <1> ; CALL CMOS_READ ; GET CMOS STATUS 7154 <1> ; TEST AL,BAD_BAT+BAD_CKSUM ; BATTERY GOOD AND CHECKSUM VALID 7155 <1> ; STC ; SET CY = 1 INDICATING ERROR FOR RETURN 7156 <1> ; JNZ short BAD_CM ; ERROR IF EITHER BIT ON 7157 <1> ; MOV AL,CMOS_DISKETTE ; ADDRESS OF DISKETTE BYTE IN CMOS 7158 <1> ; CALL CMOS_READ ; GET DISKETTE BYTE 7159 <1> ; OR DI,DI ; SEE WHICH DRIVE IN QUESTION 7160 <1> ; JNZ short TB ; IF DRIVE 1, DATA IN LOW NIBBLE 7161 <1> ; ROR AL,4 ; EXCHANGE NIBBLES IF SECOND DRIVE 7162 <1> ;TB: 7163 <1> ; AND AL,0FH ; KEEP ONLY DRIVE DATA, RESET CY, 0 7164 <1> ;BAD_CM: 7165 <1> ; RETn ; CY, STATUS OF READ 7166 <1> 7167 <1> ;------------------------------------------------------------------------------- 7168 <1> ; GET_PARM 7169 <1> ; THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE 7170 <1> ; BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM 7171 <1> ; THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING 7172 <1> ; THE PARAMETER IN DL. 7173 <1> ; 7174 <1> ; ON ENTRY: DL = INDEX OF BYTE TO BE FETCHED 7175 <1> ; 7176 <1> ; ON EXIT: AH = THAT BYTE FROM BLOCK 7177 <1> ; AL,DH DESTROYED 7178 <1> ;------------------------------------------------------------------------------- 7179 <1> GET_PARM: 7180 <1> ;PUSH DS 7181 00002461 56 <1> PUSH eSI 7182 <1> ;SUB AX,AX ; DS = 0, BIOS DATA AREA 7183 <1> ;MOV DS,AX 7184 <1> ;;mov ax, cs 7185 <1> ;;mov ds, ax 7186 <1> ; 08/02/2015 (protected mode modifications, bx -> ebx) 7187 00002462 87D3 <1> XCHG eDX,eBX ; BL = INDEX 7188 <1> ;SUB BH,BH ; BX = INDEX 7189 00002464 81E3FF000000 <1> and ebx, 0FFh 7190 <1> ;LDS SI, [DISK_POINTER] ; POINT TO BLOCK 7191 <1> ; 7192 <1> ; 17/12/2014 7193 0000246A 66A1[116B0000] <1> mov ax, [cfd] ; current (AL) and previous fd (AH) 7194 00002470 38E0 <1> cmp al, ah 7195 00002472 7425 <1> je short gpndc 7196 00002474 A2[126B0000] <1> mov [pfd], al ; current drive -> previous drive 7197 00002479 53 <1> push ebx ; 08/02/2015 7198 0000247A 88C3 <1> mov bl, al 7199 <1> ; 11/12/2014 7200 0000247C 8A83[1E6B0000] <1> mov al, [eBX+fd0_type] ; Drive type (0,1,2,3,4) 7201 <1> ; 18/12/2014 7202 00002482 20C0 <1> and al, al 7203 00002484 7507 <1> jnz short gpdtc 7204 00002486 BB[FB6A0000] <1> mov ebx, MD_TBL6 ; 1.44 MB param. tbl. (default) 7205 0000248B EB05 <1> jmp short gpdpu 7206 <1> gpdtc: 7207 0000248D E817F9FFFF <1> call DR_TYPE_CHECK 7208 <1> ; cf = 1 -> eBX points to 1.44MB fd parameter table (default) 7209 <1> gpdpu: 7210 00002492 891D[986A0000] <1> mov [DISK_POINTER], ebx 7211 00002498 5B <1> pop ebx 7212 <1> gpndc: 7213 00002499 8B35[986A0000] <1> mov esi, [DISK_POINTER] ; 08/02/2015, si -> esi 7214 0000249F 8A241E <1> MOV AH, [eSI+eBX] ; GET THE WORD 7215 000024A2 87D3 <1> XCHG eDX,eBX ; RESTORE BX 7216 000024A4 5E <1> POP eSI 7217 <1> ;POP DS 7218 000024A5 C3 <1> RETn 7219 <1> 7220 <1> ;------------------------------------------------------------------------------- 7221 <1> ; MOTOR_ON 7222 <1> ; TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT 7223 <1> ; IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE 7224 <1> ; THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE 7225 <1> ; MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION 7226 <1> ; (AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM 7227 <1> ; THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS 7228 <1> ; FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT 7229 <1> ; HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE 7230 <1> ; THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID 7231 <1> ; NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE 7232 <1> ; PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN, 7233 <1> ; IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE 7234 <1> ; WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT. 7235 <1> ; 7236 <1> ; ON ENTRY: DI = DRIVE # 7237 <1> ; ON EXIT: AX,CX,DX DESTROYED 7238 <1> ;------------------------------------------------------------------------------- 7239 <1> MOTOR_ON: 7240 000024A6 53 <1> PUSH eBX ; SAVE REG. 7241 000024A7 E82A000000 <1> CALL TURN_ON ; TURN ON MOTOR 7242 000024AC 7226 <1> JC short MOT_IS_ON ; IF CY=1 NO WAIT 7243 000024AE E89BF9FFFF <1> CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 7244 000024B3 E865F9FFFF <1> CALL XLAT_NEW ; TRANSLATE STATE TO PRESENT ARCH, 7245 <1> ;CALL TURN_ON ; CHECK AGAIN IF MOTOR ON 7246 <1> ;JC MOT_IS_ON ; IF NO WAIT MEANS IT IS ON 7247 <1> M_WAIT: 7248 000024B8 B20A <1> MOV DL,10 ; GET THE MOTOR WAIT PARAMETER 7249 000024BA E8A2FFFFFF <1> CALL GET_PARM 7250 <1> ;MOV AL,AH ; AL = MOTOR WAIT PARAMETER 7251 <1> ;XOR AH,AH ; AX = MOTOR WAIT PARAMETER 7252 <1> ;CMP AL,8 ; SEE IF AT LEAST A SECOND IS SPECIFIED 7253 000024BF 80FC08 <1> cmp ah, 8 7254 <1> ;JAE short GP2 ; IF YES, CONTINUE 7255 000024C2 7702 <1> ja short J13 7256 <1> ;MOV AL,8 ; ONE SECOND WAIT FOR MOTOR START UP 7257 000024C4 B408 <1> mov ah, 8 7258 <1> 7259 <1> ;----- AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT 7260 <1> GP2: 7261 <1> ;----- FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE 7262 <1> J13: ; WAIT FOR 1/8 SECOND PER (AL) 7263 000024C6 B95E200000 <1> MOV eCX,8286 ; COUNT FOR 1/8 SECOND AT 15.085737 US 7264 000024CB E819F1FFFF <1> CALL WAITF ; GO TO FIXED WAIT ROUTINE 7265 <1> ;DEC AL ; DECREMENT TIME VALUE 7266 000024D0 FECC <1> dec ah 7267 000024D2 75F2 <1> JNZ short J13 ; ARE WE DONE YET 7268 <1> MOT_IS_ON: 7269 000024D4 5B <1> POP eBX ; RESTORE REG. 7270 000024D5 C3 <1> RETn 7271 <1> 7272 <1> ;------------------------------------------------------------------------------- 7273 <1> ; TURN_ON 7274 <1> ; TURN MOTOR ON AND RETURN WAIT STATE. 7275 <1> ; 7276 <1> ; ON ENTRY: DI = DRIVE # 7277 <1> ; 7278 <1> ; ON EXIT: CY = 0 MEANS WAIT REQUIRED 7279 <1> ; CY = 1 MEANS NO WAIT REQUIRED 7280 <1> ; AX,BX,CX,DX DESTROYED 7281 <1> ;------------------------------------------------------------------------------- 7282 <1> TURN_ON: 7283 000024D6 89FB <1> MOV eBX,eDI ; BX = DRIVE # 7284 000024D8 88D9 <1> MOV CL,BL ; CL = DRIVE # 7285 000024DA C0C304 <1> ROL BL,4 ; BL = DRIVE SELECT 7286 000024DD FA <1> CLI ; NO INTERRUPTS WHILE DETERMINING STATUS 7287 000024DE C605[EB700000]FF <1> MOV byte [MOTOR_COUNT],0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 7288 000024E5 A0[EA700000] <1> MOV AL, [MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 7289 000024EA 2430 <1> AND AL,00110000B ; KEEP ONLY DRIVE SELECT BITS 7290 000024EC B401 <1> MOV AH,1 ; MASK FOR DETERMINING MOTOR BIT 7291 000024EE D2E4 <1> SHL AH,CL ; AH = MOTOR ON, A=00000001, B=00000010 7292 <1> 7293 <1> ; AL = DRIVE SELECT FROM @MOTOR_STATUS 7294 <1> ; BL = DRIVE SELECT DESIRED 7295 <1> ; AH = MOTOR ON MASK DESIRED 7296 <1> 7297 000024F0 38D8 <1> CMP AL,BL ; REQUESTED DRIVE ALREADY SELECTED ? 7298 000024F2 7508 <1> JNZ short TURN_IT_ON ; IF NOT SELECTED JUMP 7299 000024F4 8425[EA700000] <1> TEST AH, [MOTOR_STATUS] ; TEST MOTOR ON BIT 7300 000024FA 7535 <1> JNZ short NO_MOT_WAIT ; JUMP IF MOTOR ON AND SELECTED 7301 <1> 7302 <1> TURN_IT_ON: 7303 000024FC 08DC <1> OR AH,BL ; AH = DRIVE SELECT AND MOTOR ON 7304 000024FE 8A3D[EA700000] <1> MOV BH,[MOTOR_STATUS] ; SAVE COPY OF @MOTOR_STATUS BEFORE 7305 00002504 80E70F <1> AND BH,00001111B ; KEEP ONLY MOTOR BITS 7306 00002507 8025[EA700000]CF <1> AND byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT 7307 0000250E 0825[EA700000] <1> OR [MOTOR_STATUS],AH ; OR IN DRIVE SELECTED AND MOTOR ON 7308 00002514 A0[EA700000] <1> MOV AL,[MOTOR_STATUS] ; GET DIGITAL OUTPUT REGISTER REFLECTION 7309 00002519 88C3 <1> MOV BL,AL ; BL=@MOTOR_STATUS AFTER, BH=BEFORE 7310 0000251B 80E30F <1> AND BL,00001111B ; KEEP ONLY MOTOR BITS 7311 0000251E FB <1> STI ; ENABLE INTERRUPTS AGAIN 7312 0000251F 243F <1> AND AL,00111111B ; STRIP AWAY UNWANTED BITS 7313 00002521 C0C004 <1> ROL AL,4 ; PUT BITS IN DESIRED POSITIONS 7314 00002524 0C0C <1> OR AL,00001100B ; NO RESET, ENABLE DMA/INTERRUPT 7315 00002526 66BAF203 <1> MOV DX,03F2H ; SELECT DRIVE AND TURN ON MOTOR 7316 0000252A EE <1> OUT DX,AL 7317 0000252B 38FB <1> CMP BL,BH ; NEW MOTOR TURNED ON ? 7318 <1> ;JZ short NO_MOT_WAIT ; NO WAIT REQUIRED IF JUST SELECT 7319 0000252D 7403 <1> je short no_mot_w1 ; 27/02/2015 7320 0000252F F8 <1> CLC ; (re)SET CARRY MEANING WAIT 7321 00002530 C3 <1> RETn 7322 <1> 7323 <1> NO_MOT_WAIT: 7324 00002531 FB <1> sti 7325 <1> no_mot_w1: ; 27/02/2015 7326 00002532 F9 <1> STC ; SET NO WAIT REQUIRED 7327 <1> ;STI ; INTERRUPTS BACK ON 7328 00002533 C3 <1> RETn 7329 <1> 7330 <1> ;------------------------------------------------------------------------------- 7331 <1> ; HD_WAIT 7332 <1> ; WAIT FOR HEAD SETTLE TIME. 7333 <1> ; 7334 <1> ; ON ENTRY: DI = DRIVE # 7335 <1> ; 7336 <1> ; ON EXIT: AX,BX,CX,DX DESTROYED 7337 <1> ;------------------------------------------------------------------------------- 7338 <1> HD_WAIT: 7339 00002534 B209 <1> MOV DL,9 ; GET HEAD SETTLE PARAMETER 7340 00002536 E826FFFFFF <1> CALL GET_PARM 7341 0000253B 08E4 <1> or ah, ah ; 17/12/2014 7342 0000253D 7519 <1> jnz short DO_WAT 7343 0000253F F605[EA700000]80 <1> TEST byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION 7344 <1> ;JZ short ISNT_WRITE ; IF NOT, DO NOT ENFORCE ANY VALUES 7345 <1> ;OR AH,AH ; CHECK FOR ANY WAIT? 7346 <1> ;JNZ short DO_WAT ; IF THERE DO NOT ENFORCE 7347 00002546 741E <1> jz short HW_DONE 7348 00002548 B40F <1> MOV AH,HD12_SETTLE ; LOAD 1.2M HEAD SETTLE MINIMUM 7349 0000254A 8A87[F9700000] <1> MOV AL,[DSK_STATE+eDI] ; LOAD STATE 7350 00002550 24C0 <1> AND AL,RATE_MSK ; KEEP ONLY RATE 7351 00002552 3C80 <1> CMP AL,RATE_250 ; 1.2 M DRIVE ? 7352 00002554 7502 <1> JNZ short DO_WAT ; DEFAULT HEAD SETTLE LOADED 7353 <1> ;GP3: 7354 00002556 B414 <1> MOV AH,HD320_SETTLE ; USE 320/360 HEAD SETTLE 7355 <1> ; JMP SHORT DO_WAT 7356 <1> 7357 <1> ;ISNT_WRITE: 7358 <1> ; OR AH,AH ; CHECK FOR NO WAIT 7359 <1> ; JZ short HW_DONE ; IF NOT WRITE AND 0 ITS OK 7360 <1> 7361 <1> ;----- AH CONTAINS NUMBER OF MILLISECONDS TO WAIT 7362 <1> DO_WAT: 7363 <1> ; MOV AL,AH ; AL = # MILLISECONDS 7364 <1> ; ;XOR AH,AH ; AX = # MILLISECONDS 7365 <1> J29: ; 1 MILLISECOND LOOP 7366 <1> ;mov cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units. 7367 00002558 B942000000 <1> MOV eCX,66 ; COUNT AT 15.085737 US PER COUNT 7368 0000255D E887F0FFFF <1> CALL WAITF ; DELAY FOR 1 MILLISECOND 7369 <1> ;DEC AL ; DECREMENT THE COUNT 7370 00002562 FECC <1> dec ah 7371 00002564 75F2 <1> JNZ short J29 ; DO AL MILLISECOND # OF TIMES 7372 <1> HW_DONE: 7373 00002566 C3 <1> RETn 7374 <1> 7375 <1> ;------------------------------------------------------------------------------- 7376 <1> ; NEC_OUTPUT 7377 <1> ; THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING 7378 <1> ; FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL 7379 <1> ; TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT 7380 <1> ; OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION. 7381 <1> ; 7382 <1> ; ON ENTRY: AH = BYTE TO BE OUTPUT 7383 <1> ; 7384 <1> ; ON EXIT: CY = 0 SUCCESS 7385 <1> ; CY = 1 FAILURE -- DISKETTE STATUS UPDATED 7386 <1> ; IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL 7387 <1> ; HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE 7388 <1> ; REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT. 7389 <1> ; AX,CX,DX DESTROYED 7390 <1> ;------------------------------------------------------------------------------- 7391 <1> 7392 <1> ; 09/12/2014 [Erdogan Tan] 7393 <1> ; (from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.) 7394 <1> ; Diskette Drive Controller Status Register (3F4h) 7395 <1> ; This read only register facilitates the transfer of data between 7396 <1> ; the system microprocessor and the controller. 7397 <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 7398 <1> ; with the system micrprocessor. 7399 <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0, 7400 <1> ; the transfer is to the controller. 7401 <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode. 7402 <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed. 7403 <1> ; Bit 3 - Reserved. 7404 <1> ; Bit 2 - Reserved. 7405 <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode. 7406 <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode. 7407 <1> 7408 <1> ; Data Register (3F5h) 7409 <1> ; This read/write register passes data, commands and parameters, and provides 7410 <1> ; diskette status information. 7411 <1> 7412 <1> NEC_OUTPUT: 7413 <1> ;PUSH BX ; SAVE REG. 7414 00002567 66BAF403 <1> MOV DX,03F4H ; STATUS PORT 7415 <1> ;MOV BL,2 ; HIGH ORDER COUNTER 7416 <1> ;XOR CX,CX ; COUNT FOR TIME OUT 7417 <1> ; 16/12/2014 7418 <1> ; waiting for (max.) 0.5 seconds 7419 <1> ;;mov byte [wait_count], 0 ;; 27/02/2015 7420 <1> ; 7421 <1> ; 17/12/2014 7422 <1> ; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND 7423 <1> ; 7424 <1> ;WAIT_FOR_PORT: Waits for a bit at a port pointed to by DX to 7425 <1> ; go on. 7426 <1> ;INPUT: 7427 <1> ; AH=Mask for isolation bits. 7428 <1> ; AL=pattern to look for. 7429 <1> ; DX=Port to test for 7430 <1> ; BH:CX=Number of memory refresh periods to delay. 7431 <1> ; (normally 30 microseconds per period.) 7432 <1> ; 7433 <1> ;WFP_SHORT: 7434 <1> ; Wait for port if refresh cycle is short (15-80 Us range). 7435 <1> ; 7436 <1> 7437 <1> ; mov bl, WAIT_FDU_SEND_HI+1 ; 0+1 7438 <1> ; mov cx, WAIT_FDU_SEND_LO ; 16667 7439 0000256B B91B410000 <1> mov ecx, WAIT_FDU_SEND_LH ; 16667 (27/02/2015) 7440 <1> ; 7441 <1> ;WFPS_OUTER_LP: 7442 <1> ; ; 7443 <1> ;WFPS_CHECK_PORT: 7444 <1> J23: 7445 00002570 EC <1> IN AL,DX ; GET STATUS 7446 00002571 24C0 <1> AND AL,11000000B ; KEEP STATUS AND DIRECTION 7447 00002573 3C80 <1> CMP AL,10000000B ; STATUS 1 AND DIRECTION 0 ? 7448 00002575 7418 <1> JZ short J27 ; STATUS AND DIRECTION OK 7449 <1> WFPS_HI: 7450 00002577 E461 <1> IN AL, PORT_B ;061h ; SYS1 ; wait for hi to lo 7451 00002579 A810 <1> TEST AL,010H ; transition on memory 7452 0000257B 75FA <1> JNZ SHORT WFPS_HI ; refresh. 7453 <1> WFPS_LO: 7454 0000257D E461 <1> IN AL, PORT_B ; SYS1 7455 0000257F A810 <1> TEST AL,010H 7456 00002581 74FA <1> JZ SHORT WFPS_LO 7457 <1> ;LOOP SHORT WFPS_CHECK_PORT 7458 00002583 E2EB <1> loop J23 ; 27/02/2015 7459 <1> ; ; 7460 <1> ; dec bl 7461 <1> ; jnz short WFPS_OUTER_LP 7462 <1> ; jmp short WFPS_TIMEOUT ; fail 7463 <1> ;J23: 7464 <1> ; IN AL,DX ; GET STATUS 7465 <1> ; AND AL,11000000B ; KEEP STATUS AND DIRECTION 7466 <1> ; CMP AL,10000000B ; STATUS 1 AND DIRECTION 0 ? 7467 <1> ; JZ short J27 ; STATUS AND DIRECTION OK 7468 <1> ;LOOP J23 ; CONTINUE TILL CX EXHAUSTED 7469 <1> ;DEC BL ; DECREMENT COUNTER 7470 <1> ;JNZ short J23 ; REPEAT TILL DELAY FINISHED, CX = 0 7471 <1> 7472 <1> ;;27/02/2015 7473 <1> ;16/12/2014 7474 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 7475 <1> ;;jb short J23 7476 <1> 7477 <1> ;WFPS_TIMEOUT: 7478 <1> 7479 <1> ;----- FALL THRU TO ERROR RETURN 7480 <1> 7481 00002585 800D[EC700000]80 <1> OR byte [DSKETTE_STATUS],TIME_OUT 7482 <1> ;POP BX ; RESTORE REG. 7483 0000258C 58 <1> POP eAX ; 08/02/2015 ; DISCARD THE RETURN ADDRESS 7484 0000258D F9 <1> STC ; INDICATE ERROR TO CALLER 7485 0000258E C3 <1> RETn 7486 <1> 7487 <1> ;----- DIRECTION AND STATUS OK; OUTPUT BYTE 7488 <1> 7489 <1> J27: 7490 0000258F 88E0 <1> MOV AL,AH ; GET BYTE TO OUTPUT 7491 00002591 6642 <1> INC DX ; DATA PORT = STATUS PORT + 1 7492 00002593 EE <1> OUT DX,AL ; OUTPUT THE BYTE 7493 <1> ;;NEWIODELAY ;; 27/02/2015 7494 <1> ; 27/02/2015 7495 00002594 9C <1> PUSHF ; SAVE FLAGS 7496 00002595 B903000000 <1> MOV eCX, 3 ; 30 TO 45 MICROSECONDS WAIT FOR 7497 0000259A E84AF0FFFF <1> CALL WAITF ; NEC FLAGS UPDATE CYCLE 7498 0000259F 9D <1> POPF ; RESTORE FLAGS FOR EXIT 7499 <1> ;POP BX ; RESTORE REG 7500 000025A0 C3 <1> RETn ; CY = 0 FROM TEST INSTRUCTION 7501 <1> 7502 <1> ;------------------------------------------------------------------------------- 7503 <1> ; SEEK 7504 <1> ; THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED 7505 <1> ; TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE 7506 <1> ; RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED. 7507 <1> ; 7508 <1> ; ON ENTRY: DI = DRIVE # 7509 <1> ; CH = TRACK # 7510 <1> ; 7511 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7512 <1> ; AX,BX,CX DX DESTROYED 7513 <1> ;------------------------------------------------------------------------------- 7514 <1> SEEK: 7515 000025A1 89FB <1> MOV eBX,eDI ; BX = DRIVE # 7516 000025A3 B001 <1> MOV AL,1 ; ESTABLISH MASK FOR RECALIBRATE TEST 7517 000025A5 86CB <1> XCHG CL,BL ; SET DRIVE VALULE INTO CL 7518 000025A7 D2C0 <1> ROL AL,CL ; SHIFT MASK BY THE DRIVE VALUE 7519 000025A9 86CB <1> XCHG CL,BL ; RECOVER TRACK VALUE 7520 000025AB 8405[E9700000] <1> TEST AL,[SEEK_STATUS] ; TEST FOR RECALIBRATE REQUIRED 7521 000025B1 7526 <1> JNZ short J28A ; JUMP IF RECALIBRATE NOT REQUIRED 7522 <1> 7523 000025B3 0805[E9700000] <1> OR [SEEK_STATUS],AL ; TURN ON THE NO RECALIBRATE BIT IN FLAG 7524 000025B9 E862000000 <1> CALL RECAL ; RECALIBRATE DRIVE 7525 000025BE 730E <1> JNC short AFT_RECAL ; RECALIBRATE DONE 7526 <1> 7527 <1> ;----- ISSUE RECALIBRATE FOR 80 TRACK DISKETTES 7528 <1> 7529 000025C0 C605[EC700000]00 <1> MOV byte [DSKETTE_STATUS],0 ; CLEAR OUT INVALID STATUS 7530 000025C7 E854000000 <1> CALL RECAL ; RECALIBRATE DRIVE 7531 000025CC 7251 <1> JC short RB ; IF RECALIBRATE FAILS TWICE THEN ERROR 7532 <1> 7533 <1> AFT_RECAL: 7534 000025CE C687[FD700000]00 <1> MOV byte [DSK_TRK+eDI],0 ; SAVE NEW CYLINDER AS PRESENT POSITION 7535 000025D5 08ED <1> OR CH,CH ; CHECK FOR SEEK TO TRACK 0 7536 000025D7 743F <1> JZ short DO_WAIT ; HEAD SETTLE, CY = 0 IF JUMP 7537 <1> 7538 <1> ;----- DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK 7539 <1> 7540 000025D9 F687[F9700000]20 <1> J28A: TEST byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED 7541 000025E0 7402 <1> JZ short _R7 ; SINGLE STEP REQUIRED BYPASS DOUBLE 7542 000025E2 D0E5 <1> SHL CH,1 ; DOUBLE NUMBER OF STEP TO TAKE 7543 <1> 7544 000025E4 3AAF[FD700000] <1> _R7: CMP CH, [DSK_TRK+eDI] ; SEE IF ALREADY AT THE DESIRED TRACK 7545 000025EA 7433 <1> JE short RB ; IF YES, DO NOT NEED TO SEEK 7546 <1> 7547 000025EC BA[1F260000] <1> MOV eDX, NEC_ERR ; LOAD RETURN ADDRESS 7548 000025F1 52 <1> PUSH eDX ; (*) ; ON STACK FOR NEC OUTPUT ERROR 7549 000025F2 88AF[FD700000] <1> MOV [DSK_TRK+eDI],CH ; SAVE NEW CYLINDER AS PRESENT POSITION 7550 000025F8 B40F <1> MOV AH,0FH ; SEEK COMMAND TO NEC 7551 000025FA E868FFFFFF <1> CALL NEC_OUTPUT 7552 000025FF 89FB <1> MOV eBX,eDI ; BX = DRIVE # 7553 00002601 88DC <1> MOV AH,BL ; OUTPUT DRIVE NUMBER 7554 00002603 E85FFFFFFF <1> CALL NEC_OUTPUT 7555 00002608 8AA7[FD700000] <1> MOV AH, [DSK_TRK+eDI] ; GET CYLINDER NUMBER 7556 0000260E E854FFFFFF <1> CALL NEC_OUTPUT 7557 00002613 E829000000 <1> CALL CHK_STAT_2 ; ENDING INTERRUPT AND SENSE STATUS 7558 <1> 7559 <1> ;----- WAIT FOR HEAD SETTLE 7560 <1> 7561 <1> DO_WAIT: 7562 00002618 9C <1> PUSHF ; SAVE STATUS 7563 00002619 E816FFFFFF <1> CALL HD_WAIT ; WAIT FOR HEAD SETTLE TIME 7564 0000261E 9D <1> POPF ; RESTORE STATUS 7565 <1> RB: 7566 <1> NEC_ERR: 7567 <1> ; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM) 7568 <1> ; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn 7569 0000261F C3 <1> RETn ; RETURN TO CALLER 7570 <1> 7571 <1> ;------------------------------------------------------------------------------- 7572 <1> ; RECAL 7573 <1> ; RECALIBRATE DRIVE 7574 <1> ; 7575 <1> ; ON ENTRY: DI = DRIVE # 7576 <1> ; 7577 <1> ; ON EXIT: CY REFLECTS STATUS OF OPERATION. 7578 <1> ;------------------------------------------------------------------------------- 7579 <1> RECAL: 7580 00002620 6651 <1> PUSH CX 7581 00002622 B8[3E260000] <1> MOV eAX, RC_BACK ; LOAD NEC_OUTPUT ERROR 7582 00002627 50 <1> PUSH eAX 7583 00002628 B407 <1> MOV AH,07H ; RECALIBRATE COMMAND 7584 0000262A E838FFFFFF <1> CALL NEC_OUTPUT 7585 0000262F 89FB <1> MOV eBX,eDI ; BX = DRIVE # 7586 00002631 88DC <1> MOV AH,BL 7587 00002633 E82FFFFFFF <1> CALL NEC_OUTPUT ; OUTPUT THE DRIVE NUMBER 7588 00002638 E804000000 <1> CALL CHK_STAT_2 ; GET THE INTERRUPT AND SENSE INT STATUS 7589 0000263D 58 <1> POP eAX ; THROW AWAY ERROR 7590 <1> RC_BACK: 7591 0000263E 6659 <1> POP CX 7592 00002640 C3 <1> RETn 7593 <1> 7594 <1> ;------------------------------------------------------------------------------- 7595 <1> ; CHK_STAT_2 7596 <1> ; THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE, 7597 <1> ; OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE 7598 <1> ; INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER. 7599 <1> ; 7600 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7601 <1> ;------------------------------------------------------------------------------- 7602 <1> CHK_STAT_2: 7603 00002641 B8[69260000] <1> MOV eAX, CS_BACK ; LOAD NEC_OUTPUT ERROR ADDRESS 7604 00002646 50 <1> PUSH eAX 7605 00002647 E828000000 <1> CALL WAIT_INT ; WAIT FOR THE INTERRUPT 7606 0000264C 721A <1> JC short J34 ; IF ERROR, RETURN IT 7607 0000264E B408 <1> MOV AH,08H ; SENSE INTERRUPT STATUS COMMAND 7608 00002650 E812FFFFFF <1> CALL NEC_OUTPUT 7609 00002655 E84A000000 <1> CALL RESULTS ; READ IN THE RESULTS 7610 0000265A 720C <1> JC short J34 7611 0000265C A0[ED700000] <1> MOV AL,[NEC_STATUS] ; GET THE FIRST STATUS BYTE 7612 00002661 2460 <1> AND AL,01100000B ; ISOLATE THE BITS 7613 00002663 3C60 <1> CMP AL,01100000B ; TEST FOR CORRECT VALUE 7614 00002665 7403 <1> JZ short J35 ; IF ERROR, GO MARK IT 7615 00002667 F8 <1> CLC ; GOOD RETURN 7616 <1> J34: 7617 00002668 58 <1> POP eAX ; THROW AWAY ERROR RETURN 7618 <1> CS_BACK: 7619 00002669 C3 <1> RETn 7620 <1> J35: 7621 0000266A 800D[EC700000]40 <1> OR byte [DSKETTE_STATUS], BAD_SEEK 7622 00002671 F9 <1> STC ; ERROR RETURN CODE 7623 00002672 EBF4 <1> JMP SHORT J34 7624 <1> 7625 <1> ;------------------------------------------------------------------------------- 7626 <1> ; WAIT_INT 7627 <1> ; THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE 7628 <1> ; TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED 7629 <1> ; IF THE DRIVE IS NOT READY. 7630 <1> ; 7631 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7632 <1> ;------------------------------------------------------------------------------- 7633 <1> 7634 <1> ; 17/12/2014 7635 <1> ; 2.5 seconds waiting ! 7636 <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI) 7637 <1> ; amount of time to wait for completion interrupt from NEC. 7638 <1> 7639 <1> 7640 <1> WAIT_INT: 7641 00002674 FB <1> STI ; TURN ON INTERRUPTS, JUST IN CASE 7642 00002675 F8 <1> CLC ; CLEAR TIMEOUT INDICATOR 7643 <1> ;MOV BL,10 ; CLEAR THE COUNTERS 7644 <1> ;XOR CX,CX ; FOR 2 SECOND WAIT 7645 <1> 7646 <1> ; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT 7647 <1> ; 7648 <1> ;WAIT_FOR_MEM: 7649 <1> ; Waits for a bit at a specified memory location pointed 7650 <1> ; to by ES:[DI] to become set. 7651 <1> ;INPUT: 7652 <1> ; AH=Mask to test with. 7653 <1> ; ES:[DI] = memory location to watch. 7654 <1> ; BH:CX=Number of memory refresh periods to delay. 7655 <1> ; (normally 30 microseconds per period.) 7656 <1> 7657 <1> ; waiting for (max.) 2.5 secs in 30 micro units. 7658 <1> ; mov cx, WAIT_FDU_INT_LO ; 017798 7659 <1> ;; mov bl, WAIT_FDU_INT_HI 7660 <1> ; mov bl, WAIT_FDU_INT_HI + 1 7661 <1> ; 27/02/2015 7662 00002676 B986450100 <1> mov ecx, WAIT_FDU_INT_LH ; 83334 (2.5 seconds) 7663 <1> WFMS_CHECK_MEM: 7664 0000267B F605[E9700000]80 <1> test byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING 7665 00002682 7516 <1> jnz short J37 7666 <1> WFMS_HI: 7667 00002684 E461 <1> IN AL,PORT_B ; 061h ; SYS1, wait for lo to hi 7668 00002686 A810 <1> TEST AL,010H ; transition on memory 7669 00002688 75FA <1> JNZ SHORT WFMS_HI ; refresh. 7670 <1> WFMS_LO: 7671 0000268A E461 <1> IN AL,PORT_B ;SYS1 7672 0000268C A810 <1> TEST AL,010H 7673 0000268E 74FA <1> JZ SHORT WFMS_LO 7674 00002690 E2E9 <1> LOOP WFMS_CHECK_MEM 7675 <1> ;WFMS_OUTER_LP: 7676 <1> ;; or bl, bl ; check outer counter 7677 <1> ;; jz short J36A ; WFMS_TIMEOUT 7678 <1> ; dec bl 7679 <1> ; jz short J36A 7680 <1> ; jmp short WFMS_CHECK_MEM 7681 <1> 7682 <1> ;17/12/2014 7683 <1> ;16/12/2014 7684 <1> ; mov byte [wait_count], 0 ; Reset (INT 08H) counter 7685 <1> ;J36: 7686 <1> ; TEST byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING 7687 <1> ; JNZ short J37 7688 <1> ;16/12/2014 7689 <1> ;LOOP J36 ; COUNT DOWN WHILE WAITING 7690 <1> ;DEC BL ; SECOND LEVEL COUNTER 7691 <1> ;JNZ short J36 7692 <1> ; cmp byte [wait_count], 46 ; (46/18.2 seconds) 7693 <1> ; jb short J36 7694 <1> 7695 <1> ;WFMS_TIMEOUT: 7696 <1> ;J36A: 7697 00002692 800D[EC700000]80 <1> OR byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED 7698 00002699 F9 <1> STC ; ERROR RETURN 7699 <1> J37: 7700 0000269A 9C <1> PUSHF ; SAVE CURRENT CARRY 7701 0000269B 8025[E9700000]7F <1> AND byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG 7702 000026A2 9D <1> POPF ; RECOVER CARRY 7703 000026A3 C3 <1> RETn ; GOOD RETURN CODE 7704 <1> 7705 <1> ;------------------------------------------------------------------------------- 7706 <1> ; RESULTS 7707 <1> ; THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 7708 <1> ; FOLLOWING AN INTERRUPT. 7709 <1> ; 7710 <1> ; ON EXIT: @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION. 7711 <1> ; AX,BX,CX,DX DESTROYED 7712 <1> ;------------------------------------------------------------------------------- 7713 <1> RESULTS: 7714 000026A4 57 <1> PUSH eDI 7715 000026A5 BF[ED700000] <1> MOV eDI, NEC_STATUS ; POINTER TO DATA AREA 7716 000026AA B307 <1> MOV BL,7 ; MAX STATUS BYTES 7717 000026AC 66BAF403 <1> MOV DX,03F4H ; STATUS PORT 7718 <1> 7719 <1> ;----- WAIT FOR REQUEST FOR MASTER 7720 <1> 7721 <1> _R10: 7722 <1> ; 16/12/2014 7723 <1> ; wait for (max) 0.5 seconds 7724 <1> ;MOV BH,2 ; HIGH ORDER COUNTER 7725 <1> ;XOR CX,CX ; COUNTER 7726 <1> 7727 <1> ;Time to wait while waiting for each byte of NEC results = .5 7728 <1> ;seconds. .5 seconds = 500,000 micros. 500,000/30 = 16,667. 7729 <1> ; 27/02/2015 7730 000026B0 B91B410000 <1> mov ecx, WAIT_FDU_RESULTS_LH ; 16667 7731 <1> ;mov cx, WAIT_FDU_RESULTS_LO ; 16667 7732 <1> ;mov bh, WAIT_FDU_RESULTS_HI+1 ; 0+1 7733 <1> 7734 <1> WFPSR_OUTER_LP: 7735 <1> ; 7736 <1> WFPSR_CHECK_PORT: 7737 <1> J39: ; WAIT FOR MASTER 7738 000026B5 EC <1> IN AL,DX ; GET STATUS 7739 000026B6 24C0 <1> AND AL,11000000B ; KEEP ONLY STATUS AND DIRECTION 7740 000026B8 3CC0 <1> CMP AL,11000000B ; STATUS 1 AND DIRECTION 1 ? 7741 000026BA 7418 <1> JZ short J42 ; STATUS AND DIRECTION OK 7742 <1> WFPSR_HI: 7743 000026BC E461 <1> IN AL, PORT_B ;061h ; SYS1 ; wait for hi to lo 7744 000026BE A810 <1> TEST AL,010H ; transition on memory 7745 000026C0 75FA <1> JNZ SHORT WFPSR_HI ; refresh. 7746 <1> WFPSR_LO: 7747 000026C2 E461 <1> IN AL, PORT_B ; SYS1 7748 000026C4 A810 <1> TEST AL,010H 7749 000026C6 74FA <1> JZ SHORT WFPSR_LO 7750 000026C8 E2EB <1> LOOP WFPSR_CHECK_PORT 7751 <1> ;; 27/02/2015 7752 <1> ;;dec bh 7753 <1> ;;jnz short WFPSR_OUTER_LP 7754 <1> ;jmp short WFPSR_TIMEOUT ; fail 7755 <1> 7756 <1> ;;mov byte [wait_count], 0 7757 <1> ;J39: ; WAIT FOR MASTER 7758 <1> ; IN AL,DX ; GET STATUS 7759 <1> ; AND AL,11000000B ; KEEP ONLY STATUS AND DIRECTION 7760 <1> ; CMP AL,11000000B ; STATUS 1 AND DIRECTION 1 ? 7761 <1> ; JZ short J42 ; STATUS AND DIRECTION OK 7762 <1> ;LOOP J39 ; LOOP TILL TIMEOUT 7763 <1> ;DEC BH ; DECREMENT HIGH ORDER COUNTER 7764 <1> ;JNZ short J39 ; REPEAT TILL DELAY DONE 7765 <1> ; 7766 <1> ;;cmp byte [wait_count], 10 ; (10/18.2 seconds) 7767 <1> ;;jb short J39 7768 <1> 7769 <1> ;WFPSR_TIMEOUT: 7770 000026CA 800D[EC700000]80 <1> OR byte [DSKETTE_STATUS],TIME_OUT 7771 000026D1 F9 <1> STC ; SET ERROR RETURN 7772 000026D2 EB29 <1> JMP SHORT POPRES ; POP REGISTERS AND RETURN 7773 <1> 7774 <1> ;----- READ IN THE STATUS 7775 <1> 7776 <1> J42: 7777 000026D4 EB00 <1> JMP $+2 ; I/O DELAY 7778 000026D6 6642 <1> INC DX ; POINT AT DATA PORT 7779 000026D8 EC <1> IN AL,DX ; GET THE DATA 7780 <1> ; 16/12/2014 7781 <1> NEWIODELAY 7782 000026D9 E6EB <2> out 0ebh,al 7783 000026DB 8807 <1> MOV [eDI],AL ; STORE THE BYTE 7784 000026DD 47 <1> INC eDI ; INCREMENT THE POINTER 7785 <1> ; 16/12/2014 7786 <1> ; push cx 7787 <1> ; mov cx, 30 7788 <1> ;wdw2: 7789 <1> ; NEWIODELAY 7790 <1> ; loop wdw2 7791 <1> ; pop cx 7792 <1> 7793 000026DE B903000000 <1> MOV eCX,3 ; MINIMUM 24 MICROSECONDS FOR NEC 7794 000026E3 E801EFFFFF <1> CALL WAITF ; WAIT 30 TO 45 MICROSECONDS 7795 000026E8 664A <1> DEC DX ; POINT AT STATUS PORT 7796 000026EA EC <1> IN AL,DX ; GET STATUS 7797 <1> ; 16/12/2014 7798 <1> NEWIODELAY 7799 000026EB E6EB <2> out 0ebh,al 7800 <1> ; 7801 000026ED A810 <1> TEST AL,00010000B ; TEST FOR NEC STILL BUSY 7802 000026EF 740C <1> JZ short POPRES ; RESULTS DONE ? 7803 <1> 7804 000026F1 FECB <1> DEC BL ; DECREMENT THE STATUS COUNTER 7805 000026F3 75BB <1> JNZ short _R10 ; GO BACK FOR MORE 7806 000026F5 800D[EC700000]20 <1> OR byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES 7807 000026FC F9 <1> STC ; SET ERROR FLAG 7808 <1> 7809 <1> ;----- RESULT OPERATION IS DONE 7810 <1> POPRES: 7811 000026FD 5F <1> POP eDI 7812 000026FE C3 <1> RETn ; RETURN WITH CARRY SET 7813 <1> 7814 <1> ;------------------------------------------------------------------------------- 7815 <1> ; READ_DSKCHNG 7816 <1> ; READS THE STATE OF THE DISK CHANGE LINE. 7817 <1> ; 7818 <1> ; ON ENTRY: DI = DRIVE # 7819 <1> ; 7820 <1> ; ON EXIT: DI = DRIVE # 7821 <1> ; ZF = 0 : DISK CHANGE LINE INACTIVE 7822 <1> ; ZF = 1 : DISK CHANGE LINE ACTIVE 7823 <1> ; AX,CX,DX DESTROYED 7824 <1> ;------------------------------------------------------------------------------- 7825 <1> READ_DSKCHNG: 7826 000026FF E8A2FDFFFF <1> CALL MOTOR_ON ; TURN ON THE MOTOR IF OFF 7827 00002704 66BAF703 <1> MOV DX,03F7H ; ADDRESS DIGITAL INPUT REGISTER 7828 00002708 EC <1> IN AL,DX ; INPUT DIGITAL INPUT REGISTER 7829 00002709 A880 <1> TEST AL,DSK_CHG ; CHECK FOR DISK CHANGE LINE ACTIVE 7830 0000270B C3 <1> RETn ; RETURN TO CALLER WITH ZERO FLAG SET 7831 <1> 7832 <1> ;------------------------------------------------------------------------------- 7833 <1> ; DRIVE_DET 7834 <1> ; DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND 7835 <1> ; UPDATES STATE INFORMATION ACCORDINGLY. 7836 <1> ; ON ENTRY: DI = DRIVE # 7837 <1> ;------------------------------------------------------------------------------- 7838 <1> DRIVE_DET: 7839 0000270C E895FDFFFF <1> CALL MOTOR_ON ; TURN ON MOTOR IF NOT ALREADY ON 7840 00002711 E80AFFFFFF <1> CALL RECAL ; RECALIBRATE DRIVE 7841 00002716 7251 <1> JC short DD_BAC ; ASSUME NO DRIVE PRESENT 7842 00002718 B530 <1> MOV CH,TRK_SLAP ; SEEK TO TRACK 48 7843 0000271A E882FEFFFF <1> CALL SEEK 7844 0000271F 7248 <1> JC short DD_BAC ; ERROR NO DRIVE 7845 00002721 B50B <1> MOV CH,QUIET_SEEK+1 ; SEEK TO TRACK 10 7846 <1> SK_GIN: 7847 00002723 FECD <1> DEC CH ; DECREMENT TO NEXT TRACK 7848 00002725 6651 <1> PUSH CX ; SAVE TRACK 7849 00002727 E875FEFFFF <1> CALL SEEK 7850 0000272C 723C <1> JC short POP_BAC ; POP AND RETURN 7851 0000272E B8[6A270000] <1> MOV eAX, POP_BAC ; LOAD NEC OUTPUT ERROR ADDRESS 7852 00002733 50 <1> PUSH eAX 7853 00002734 B404 <1> MOV AH,SENSE_DRV_ST ; SENSE DRIVE STATUS COMMAND BYTE 7854 00002736 E82CFEFFFF <1> CALL NEC_OUTPUT ; OUTPUT TO NEC 7855 0000273B 6689F8 <1> MOV AX,DI ; AL = DRIVE 7856 0000273E 88C4 <1> MOV AH,AL ; AH = DRIVE 7857 00002740 E822FEFFFF <1> CALL NEC_OUTPUT ; OUTPUT TO NEC 7858 00002745 E85AFFFFFF <1> CALL RESULTS ; GO GET STATUS 7859 0000274A 58 <1> POP eAX ; THROW AWAY ERROR ADDRESS 7860 0000274B 6659 <1> POP CX ; RESTORE TRACK 7861 0000274D F605[ED700000]10 <1> TEST byte [NEC_STATUS], HOME ; TRACK 0 ? 7862 00002754 74CD <1> JZ short SK_GIN ; GO TILL TRACK 0 7863 00002756 08ED <1> OR CH,CH ; IS HOME AT TRACK 0 7864 00002758 7408 <1> JZ short IS_80 ; MUST BE 80 TRACK DRIVE 7865 <1> 7866 <1> ; DRIVE IS A 360; SET DRIVE TO DETERMINED; 7867 <1> ; SET MEDIA TO DETERMINED AT RATE 250. 7868 <1> 7869 0000275A 808F[F9700000]94 <1> OR byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250 7870 00002761 C3 <1> RETn ; ALL INFORMATION SET 7871 <1> IS_80: 7872 00002762 808F[F9700000]01 <1> OR byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY 7873 <1> DD_BAC: 7874 00002769 C3 <1> RETn 7875 <1> POP_BAC: 7876 0000276A 6659 <1> POP CX ; THROW AWAY 7877 0000276C C3 <1> RETn 7878 <1> 7879 <1> fdc_int: 7880 <1> ; 30/07/2015 7881 <1> ; 16/02/2015 7882 <1> ;int_0Eh: ; 11/12/2014 7883 <1> 7884 <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL 6 ) -------------------------------------- 7885 <1> ; DISK_INT 7886 <1> ; THIS ROUTINE HANDLES THE DISKETTE INTERRUPT. 7887 <1> ; 7888 <1> ; ON EXIT: THE INTERRUPT FLAG IS SET IN @SEEK_STATUS. 7889 <1> ;------------------------------------------------------------------------------- 7890 <1> DISK_INT_1: 7891 <1> 7892 0000276D 6650 <1> PUSH AX ; SAVE WORK REGISTER 7893 0000276F 1E <1> push ds 7894 00002770 66B81000 <1> mov ax, KDATA 7895 00002774 8ED8 <1> mov ds, ax 7896 00002776 800D[E9700000]80 <1> OR byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED 7897 0000277D B020 <1> MOV AL,EOI ; END OF INTERRUPT MARKER 7898 0000277F E620 <1> OUT INTA00,AL ; INTERRUPT CONTROL PORT 7899 00002781 1F <1> pop ds 7900 00002782 6658 <1> POP AX ; RECOVER REGISTER 7901 00002784 CF <1> IRET ; RETURN FROM INTERRUPT 7902 <1> 7903 <1> ;------------------------------------------------------------------------------- 7904 <1> ; DSKETTE_SETUP 7905 <1> ; THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF 7906 <1> ; DISKETTE DRIVES ARE ATTACH TO THE SYSTEM. 7907 <1> ;------------------------------------------------------------------------------- 7908 <1> DSKETTE_SETUP: 7909 <1> ;PUSH AX ; SAVE REGISTERS 7910 <1> ;PUSH BX 7911 <1> ;PUSH CX 7912 00002785 52 <1> PUSH eDX 7913 <1> ;PUSH DI 7914 <1> ;;PUSH DS 7915 <1> ; 14/12/2014 7916 <1> ;mov word [DISK_POINTER], MD_TBL6 7917 <1> ;mov [DISK_POINTER+2], cs 7918 <1> ; 7919 <1> ;OR byte [RTC_WAIT_FLAG], 1 ; NO RTC WAIT, FORCE USE OF LOOP 7920 00002786 31FF <1> XOR eDI,eDI ; INITIALIZE DRIVE POINTER 7921 00002788 66C705[F9700000]00- <1> MOV WORD [DSK_STATE],0 ; INITIALIZE STATES 7922 00002790 00 <1> 7923 00002791 8025[F4700000]33 <1> AND byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND 7924 00002798 800D[F4700000]C0 <1> OR byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE 7925 0000279F C605[E9700000]00 <1> MOV byte [SEEK_STATUS],0 ; INDICATE RECALIBRATE NEEDED 7926 000027A6 C605[EB700000]00 <1> MOV byte [MOTOR_COUNT],0 ; INITIALIZE MOTOR COUNT 7927 000027AD C605[EA700000]00 <1> MOV byte [MOTOR_STATUS],0 ; INITIALIZE DRIVES TO OFF STATE 7928 000027B4 C605[EC700000]00 <1> MOV byte [DSKETTE_STATUS],0 ; NO ERRORS 7929 <1> ; 7930 <1> ; 28/02/2015 7931 <1> ;mov word [cfd], 100h 7932 000027BB E85FF2FFFF <1> call DSK_RESET 7933 000027C0 5A <1> pop edx 7934 000027C1 C3 <1> retn 7935 <1> 7936 <1> ;SUP0: 7937 <1> ; CALL DRIVE_DET ; DETERMINE DRIVE 7938 <1> ; CALL XLAT_OLD ; TRANSLATE STATE TO COMPATIBLE MODE 7939 <1> ; ; 02/01/2015 7940 <1> ; ;INC DI ; POINT TO NEXT DRIVE 7941 <1> ; ;CMP DI,MAX_DRV ; SEE IF DONE 7942 <1> ; ;JNZ short SUP0 ; REPEAT FOR EACH ORIVE 7943 <1> ; cmp byte [fd1_type], 0 7944 <1> ; jna short sup1 7945 <1> ; or di, di 7946 <1> ; jnz short sup1 7947 <1> ; inc di 7948 <1> ; jmp short SUP0 7949 <1> ;sup1: 7950 <1> ; MOV byte [SEEK_STATUS],0 ; FORCE RECALIBRATE 7951 <1> ; ;AND byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT 7952 <1> ; CALL SETUP_END ; VARIOUS CLEANUPS 7953 <1> ; ;;POP DS ; RESTORE CALLERS REGISTERS 7954 <1> ; ;POP DI 7955 <1> ; POP eDX 7956 <1> ; ;POP CX 7957 <1> ; ;POP BX 7958 <1> ; ;POP AX 7959 <1> ; RETn 7960 <1> 7961 <1> ;////////////////////////////////////////////////////// 7962 <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7963 <1> ; 7964 <1> 7965 <1> int13h: ; 21/02/2015 7966 000027C2 9C <1> pushfd 7967 000027C3 0E <1> push cs 7968 000027C4 E858000000 <1> call DISK_IO 7969 000027C9 C3 <1> retn 7970 <1> 7971 <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;; 7972 <1> ;///////////////////////////////////////////////////////////////////// 7973 <1> 7974 <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project) 7975 <1> ; 23/02/2015 7976 <1> ; 21/02/2015 (unix386.s) 7977 <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s) 7978 <1> ; 7979 <1> ; Original Source Code: 7980 <1> ; DISK ----- 09/25/85 FIXED DISK BIOS 7981 <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86) 7982 <1> ; 7983 <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 7984 <1> ; Source Code - ATORGS.ASM, AHDSK.ASM 7985 <1> ; 7986 <1> 7987 <1> 7988 <1> ;The wait for controller to be not busy is 10 seconds. 7989 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 7990 <1> ;;WAIT_HDU_CTLR_BUSY_LO equ 1615h 7991 <1> ;;WAIT_HDU_CTLR_BUSY_HI equ 05h 7992 <1> WAIT_HDU_CTRL_BUSY_LH equ 51615h ;21/02/2015 7993 <1> 7994 <1> ;The wait for controller to issue completion interrupt is 10 seconds. 7995 <1> ;10,000,000 / 30 = 333,333. 333,333 decimal = 051615h 7996 <1> ;;WAIT_HDU_INT_LO equ 1615h 7997 <1> ;;WAIT_HDU_INT_HI equ 05h 7998 <1> WAIT_HDU_INT_LH equ 51615h ; 21/02/2015 7999 <1> 8000 <1> ;The wait for Data request on read and write longs is 8001 <1> ;2000 us. (?) 8002 <1> ;;WAIT_HDU_DRQ_LO equ 1000 ; 03E8h 8003 <1> ;;WAIT_HDU_DRQ_HI equ 0 8004 <1> WAIT_HDU_DRQ_LH equ 1000 ; 21/02/2015 8005 <1> 8006 <1> ; Port 61h (PORT_B) 8007 <1> SYS1 equ 61h ; PORT_B (diskette.inc) 8008 <1> 8009 <1> ; 23/12/2014 8010 <1> %define CMD_BLOCK eBP-8 ; 21/02/2015 8011 <1> 8012 <1> 8013 <1> ;--- INT 13H ------------------------------------------------------------------- 8014 <1> ; : 8015 <1> ; FIXED DISK I/O INTERFACE : 8016 <1> ; : 8017 <1> ; THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH : 8018 <1> ; THE IBM FIXED DISK CONTROLLER. : 8019 <1> ; : 8020 <1> ; THE BIOS ROUTINES ARE MEANT TO BE ACCESSED THROUGH : 8021 <1> ; SOFTWARE INTERRUPTS ONLY. ANY ADDRESSES PRESENT IN : 8022 <1> ; THESE LISTINGS ARE INCLUDED ONLY FOR COMPLETENESS, : 8023 <1> ; NOT FOR REFERENCE. APPLICATIONS WHICH REFERENCE ANY : 8024 <1> ; ABSOLUTE ADDRESSES WITHIN THE CODE SEGMENTS OF BIOS : 8025 <1> ; VIOLATE THE STRUCTURE AND DESIGN OF BIOS. : 8026 <1> ; : 8027 <1> ;------------------------------------------------------------------------------: 8028 <1> ; : 8029 <1> ; INPUT (AH)= HEX COMMAND VALUE : 8030 <1> ; : 8031 <1> ; (AH)= 00H RESET DISK (DL = 80H,81H) / DISKETTE : 8032 <1> ; (AH)= 01H READ THE STATUS OF THE LAST DISK OPERATION INTO (AL) : 8033 <1> ; NOTE: DL < 80H - DISKETTE : 8034 <1> ; DL > 80H - DISK : 8035 <1> ; (AH)= 02H READ THE DESIRED SECTORS INTO MEMORY : 8036 <1> ; (AH)= 03H WRITE THE DESIRED SECTORS FROM MEMORY : 8037 <1> ; (AH)= 04H VERIFY THE DESIRED SECTORS : 8038 <1> ; (AH)= 05H FORMAT THE DESIRED TRACK : 8039 <1> ; (AH)= 06H UNUSED : 8040 <1> ; (AH)= 07H UNUSED : 8041 <1> ; (AH)= 08H RETURN THE CURRENT DRIVE PARAMETERS : 8042 <1> ; (AH)= 09H INITIALIZE DRIVE PAIR CHARACTERISTICS : 8043 <1> ; INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0 : 8044 <1> ; INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1 : 8045 <1> ; (AH)= 0AH READ LONG : 8046 <1> ; (AH)= 0BH WRITE LONG (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) : 8047 <1> ; (AH)= 0CH SEEK : 8048 <1> ; (AH)= 0DH ALTERNATE DISK RESET (SEE DL) : 8049 <1> ; (AH)= 0EH UNUSED : 8050 <1> ; (AH)= 0FH UNUSED : 8051 <1> ; (AH)= 10H TEST DRIVE READY : 8052 <1> ; (AH)= 11H RECALIBRATE : 8053 <1> ; (AH)= 12H UNUSED : 8054 <1> ; (AH)= 13H UNUSED : 8055 <1> ; (AH)= 14H CONTROLLER INTERNAL DIAGNOSTIC : 8056 <1> ; (AH)= 15H READ DASD TYPE : 8057 <1> ; : 8058 <1> ;------------------------------------------------------------------------------- 8059 <1> ; : 8060 <1> ; REGISTERS USED FOR FIXED DISK OPERATIONS : 8061 <1> ; : 8062 <1> ; (DL) - DRIVE NUMBER (80H-81H FOR DISK. VALUE CHECKED) : 8063 <1> ; (DH) - HEAD NUMBER (0-15 ALLOWED, NOT VALUE CHECKED) : 8064 <1> ; (CH) - CYLINDER NUMBER (0-1023, NOT VALUE CHECKED)(SEE CL): 8065 <1> ; (CL) - SECTOR NUMBER (1-17, NOT VALUE CHECKED) : 8066 <1> ; : 8067 <1> ; NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED : 8068 <1> ; IN THE HIGH 2 BITS OF THE CL REGISTER : 8069 <1> ; (10 BITS TOTAL) : 8070 <1> ; : 8071 <1> ; (AL) - NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H, : 8072 <1> ; FOR READ/WRITE LONG 1-79H) : 8073 <1> ; : 8074 <1> ; (ES:BX) - ADDRESS OF BUFFER FOR READS AND WRITES, : 8075 <1> ; (NOT REQUIRED FOR VERIFY) : 8076 <1> ; : 8077 <1> ; FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST : 8078 <1> ; 2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.: 8079 <1> ; F = 00H FOR A GOOD SECTOR : 8080 <1> ; 80H FOR A BAD SECTOR : 8081 <1> ; N = SECTOR NUMBER : 8082 <1> ; FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK : 8083 <1> ; THE TABLE SHOULD BE: : 8084 <1> ; : 8085 <1> ; DB 00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH : 8086 <1> ; DB 00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH : 8087 <1> ; DB 00H,07H,00H,10H,00H,08H,00H,11H,00H,09H : 8088 <1> ; : 8089 <1> ;------------------------------------------------------------------------------- 8090 <1> 8091 <1> ;------------------------------------------------------------------------------- 8092 <1> ; OUTPUT : 8093 <1> ; AH = STATUS OF CURRENT OPERATION : 8094 <1> ; STATUS BITS ARE DEFINED IN THE EQUATES BELOW : 8095 <1> ; CY = 0 SUCCESSFUL OPERATION (AH=0 ON RETURN) : 8096 <1> ; CY = 1 FAILED OPERATION (AH HAS ERROR REASON) : 8097 <1> ; : 8098 <1> ; NOTE: ERROR 11H INDICATES THAT THE DATA READ HAD A RECOVERABLE : 8099 <1> ; ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM. THE DATA : 8100 <1> ; IS PROBABLY GOOD, HOWEVER THE BIOS ROUTINE INDICATES AN : 8101 <1> ; ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE : 8102 <1> ; FOR ITSELF. THE ERROR MAY NOT RECUR IF THE DATA IS : 8103 <1> ; REWRITTEN. : 8104 <1> ; : 8105 <1> ; IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), : 8106 <1> ; INPUT: : 8107 <1> ; (DL) = DRIVE NUMBER : 8108 <1> ; OUTPUT: : 8109 <1> ; (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2) : 8110 <1> ; (CONTROLLER CARD ZERO TALLY ONLY) : 8111 <1> ; (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER : 8112 <1> ; (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER : 8113 <1> ; (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER : 8114 <1> ; AND CYLINDER NUMBER HIGH BITS : 8115 <1> ; : 8116 <1> ; IF READ DASD TYPE WAS REQUESTED, : 8117 <1> ; : 8118 <1> ; AH = 0 - NOT PRESENT : 8119 <1> ; 1 - DISKETTE - NO CHANGE LINE AVAILABLE : 8120 <1> ; 2 - DISKETTE - CHANGE LINE AVAILABLE : 8121 <1> ; 3 - FIXED DISK : 8122 <1> ; : 8123 <1> ; CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3 : 8124 <1> ; : 8125 <1> ; REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN : 8126 <1> ; INFORMATION. : 8127 <1> ; : 8128 <1> ; NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE : 8129 <1> ; ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION. : 8130 <1> ; : 8131 <1> ;------------------------------------------------------------------------------- 8132 <1> 8133 <1> SENSE_FAIL EQU 0FFH ; NOT IMPLEMENTED 8134 <1> NO_ERR EQU 0E0H ; STATUS ERROR/ERROR REGISTER=0 8135 <1> WRITE_FAULT EQU 0CCH ; WRITE FAULT ON SELECTED DRIVE 8136 <1> UNDEF_ERR EQU 0BBH ; UNDEFINED ERROR OCCURRED 8137 <1> NOT_RDY EQU 0AAH ; DRIVE NOT READY 8138 <1> TIME_OUT EQU 80H ; ATTACHMENT FAILED TO RESPOND 8139 <1> BAD_SEEK EQU 40H ; SEEK OPERATION FAILED 8140 <1> BAD_CNTLR EQU 20H ; CONTROLLER HAS FAILED 8141 <1> DATA_CORRECTED EQU 11H ; ECC CORRECTED DATA ERROR 8142 <1> BAD_ECC EQU 10H ; BAD ECC ON DISK READ 8143 <1> BAD_TRACK EQU 0BH ; NOT IMPLEMENTED 8144 <1> BAD_SECTOR EQU 0AH ; BAD SECTOR FLAG DETECTED 8145 <1> ;DMA_BOUNDARY EQU 09H ; DATA EXTENDS TOO FAR 8146 <1> INIT_FAIL EQU 07H ; DRIVE PARAMETER ACTIVITY FAILED 8147 <1> BAD_RESET EQU 05H ; RESET FAILED 8148 <1> ;RECORD_NOT_FND EQU 04H ; REQUESTED SECTOR NOT FOUND 8149 <1> ;BAD_ADDR_MARK EQU 02H ; ADDRESS MARK NOT FOUND 8150 <1> ;BAD_CMD EQU 01H ; BAD COMMAND PASSED TO DISK I/O 8151 <1> 8152 <1> ;-------------------------------------------------------- 8153 <1> ; : 8154 <1> ; FIXED DISK PARAMETER TABLE : 8155 <1> ; - THE TABLE IS COMPOSED OF A BLOCK DEFINED AS: : 8156 <1> ; : 8157 <1> ; +0 (1 WORD) - MAXIMUM NUMBER OF CYLINDERS : 8158 <1> ; +2 (1 BYTE) - MAXIMUM NUMBER OF HEADS : 8159 <1> ; +3 (1 WORD) - NOT USED/SEE PC-XT : 8160 <1> ; +5 (1 WORD) - STARTING WRITE PRECOMPENSATION CYL : 8161 <1> ; +7 (1 BYTE) - MAXIMUM ECC DATA BURST LENGTH : 8162 <1> ; +8 (1 BYTE) - CONTROL BYTE : 8163 <1> ; BIT 7 DISABLE RETRIES -OR- : 8164 <1> ; BIT 6 DISABLE RETRIES : 8165 <1> ; BIT 3 MORE THAN 8 HEADS : 8166 <1> ; +9 (3 BYTES)- NOT USED/SEE PC-XT : 8167 <1> ; +12 (1 WORD) - LANDING ZONE : 8168 <1> ; +14 (1 BYTE) - NUMBER OF SECTORS/TRACK : 8169 <1> ; +15 (1 BYTE) - RESERVED FOR FUTURE USE : 8170 <1> ; : 8171 <1> ; - TO DYNAMICALLY DEFINE A SET OF PARAMETERS : 8172 <1> ; BUILD A TABLE FOR UP TO 15 TYPES AND PLACE : 8173 <1> ; THE CORRESPONDING VECTOR INTO INTERRUPT 41 : 8174 <1> ; FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1. : 8175 <1> ; : 8176 <1> ;-------------------------------------------------------- 8177 <1> 8178 <1> ;-------------------------------------------------------- 8179 <1> ; : 8180 <1> ; HARDWARE SPECIFIC VALUES : 8181 <1> ; : 8182 <1> ; - CONTROLLER I/O PORT : 8183 <1> ; : 8184 <1> ; > WHEN READ FROM: : 8185 <1> ; HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU) : 8186 <1> ; HF_PORT+1 - GET ERROR REGISTER : 8187 <1> ; HF_PORT+2 - GET SECTOR COUNT : 8188 <1> ; HF_PORT+3 - GET SECTOR NUMBER : 8189 <1> ; HF_PORT+4 - GET CYLINDER LOW : 8190 <1> ; HF_PORT+5 - GET CYLINDER HIGH (2 BITS) : 8191 <1> ; HF_PORT+6 - GET SIZE/DRIVE/HEAD : 8192 <1> ; HF_PORT+7 - GET STATUS REGISTER : 8193 <1> ; : 8194 <1> ; > WHEN WRITTEN TO: : 8195 <1> ; HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) : 8196 <1> ; HF_PORT+1 - SET PRECOMPENSATION CYLINDER : 8197 <1> ; HF_PORT+2 - SET SECTOR COUNT : 8198 <1> ; HF_PORT+3 - SET SECTOR NUMBER : 8199 <1> ; HF_PORT+4 - SET CYLINDER LOW : 8200 <1> ; HF_PORT+5 - SET CYLINDER HIGH (2 BITS) : 8201 <1> ; HF_PORT+6 - SET SIZE/DRIVE/HEAD : 8202 <1> ; HF_PORT+7 - SET COMMAND REGISTER : 8203 <1> ; : 8204 <1> ;-------------------------------------------------------- 8205 <1> 8206 <1> ;HF_PORT EQU 01F0H ; DISK PORT 8207 <1> ;HF1_PORT equ 0170h 8208 <1> ;HF_REG_PORT EQU 03F6H 8209 <1> ;HF1_REG_PORT equ 0376h 8210 <1> 8211 <1> HDC1_BASEPORT equ 1F0h 8212 <1> HDC2_BASEPORT equ 170h 8213 <1> 8214 <1> align 2 8215 <1> 8216 <1> ;----- STATUS REGISTER 8217 <1> 8218 <1> ST_ERROR EQU 00000001B ; 8219 <1> ST_INDEX EQU 00000010B ; 8220 <1> ST_CORRCTD EQU 00000100B ; ECC CORRECTION SUCCESSFUL 8221 <1> ST_DRQ EQU 00001000B ; 8222 <1> ST_SEEK_COMPL EQU 00010000B ; SEEK COMPLETE 8223 <1> ST_WRT_FLT EQU 00100000B ; WRITE FAULT 8224 <1> ST_READY EQU 01000000B ; 8225 <1> ST_BUSY EQU 10000000B ; 8226 <1> 8227 <1> ;----- ERROR REGISTER 8228 <1> 8229 <1> ERR_DAM EQU 00000001B ; DATA ADDRESS MARK NOT FOUND 8230 <1> ERR_TRK_0 EQU 00000010B ; TRACK 0 NOT FOUND ON RECAL 8231 <1> ERR_ABORT EQU 00000100B ; ABORTED COMMAND 8232 <1> ; EQU 00001000B ; NOT USED 8233 <1> ERR_ID EQU 00010000B ; ID NOT FOUND 8234 <1> ; EQU 00100000B ; NOT USED 8235 <1> ERR_DATA_ECC EQU 01000000B 8236 <1> ERR_BAD_BLOCK EQU 10000000B 8237 <1> 8238 <1> 8239 <1> RECAL_CMD EQU 00010000B ; DRIVE RECAL (10H) 8240 <1> READ_CMD EQU 00100000B ; READ (20H) 8241 <1> WRITE_CMD EQU 00110000B ; WRITE (30H) 8242 <1> VERIFY_CMD EQU 01000000B ; VERIFY (40H) 8243 <1> FMTTRK_CMD EQU 01010000B ; FORMAT TRACK (50H) 8244 <1> INIT_CMD EQU 01100000B ; INITIALIZE (60H) 8245 <1> SEEK_CMD EQU 01110000B ; SEEK (70H) 8246 <1> DIAG_CMD EQU 10010000B ; DIAGNOSTIC (90H) 8247 <1> SET_PARM_CMD EQU 10010001B ; DRIVE PARMS (91H) 8248 <1> NO_RETRIES EQU 00000001B ; CHD MODIFIER (01H) 8249 <1> ECC_MODE EQU 00000010B ; CMD MODIFIER (02H) 8250 <1> BUFFER_MODE EQU 00001000B ; CMD MODIFIER (08H) 8251 <1> 8252 <1> ;MAX_FILE EQU 2 8253 <1> ;S_MAX_FILE EQU 2 8254 <1> MAX_FILE equ 4 ; 22/12/2014 8255 <1> S_MAX_FILE equ 4 ; 22/12/2014 8256 <1> 8257 <1> DELAY_1 EQU 25H ; DELAY FOR OPERATION COMPLETE 8258 <1> DELAY_2 EQU 0600H ; DELAY FOR READY 8259 <1> DELAY_3 EQU 0100H ; DELAY FOR DATA REQUEST 8260 <1> 8261 <1> HF_FAIL EQU 08H ; CMOS FLAG IN BYTE 0EH 8262 <1> 8263 <1> ;----- COMMAND BLOCK REFERENCE 8264 <1> 8265 <1> ;CMD_BLOCK EQU BP-8 ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS 8266 <1> ; (BP) POINTS TO COMMAND BLOCK TAIL 8267 <1> ; AS DEFINED BY THE "ENTER" PARMS 8268 <1> ; 19/12/2014 8269 <1> ORG_VECTOR equ 4*13h ; INT 13h vector 8270 <1> DISK_VECTOR equ 4*40h ; INT 40h vector (for floppy disks) 8271 <1> ;HDISK_INT equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 8272 <1> ;HDISK_INT1 equ 4*76h ; Primary HDC - Hardware interrupt (IRQ14) 8273 <1> ;HDISK_INT2 equ 4*77h ; Secondary HDC - Hardware interrupt (IRQ15) 8274 <1> ;HF_TBL_VEC equ 4*41h ; Pointer to 1st fixed disk parameter table 8275 <1> ;HF1_TBL_VEC equ 4*46h ; Pointer to 2nd fixed disk parameter table 8276 <1> 8277 <1> align 2 8278 <1> 8279 <1> ;---------------------------------------------------------------- 8280 <1> ; FIXED DISK I/O SETUP : 8281 <1> ; : 8282 <1> ; - ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK : 8283 <1> ; - PERFORM POWER ON DIAGNOSTICS : 8284 <1> ; SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED : 8285 <1> ; : 8286 <1> ;---------------------------------------------------------------- 8287 <1> 8288 <1> DISK_SETUP: 8289 <1> ;CLI 8290 <1> ;;MOV AX,ABS0 ; GET ABSOLUTE SEGMENT 8291 <1> ;xor ax,ax 8292 <1> ;MOV DS,AX ; SET SEGMENT REGISTER 8293 <1> ;MOV AX, [ORG_VECTOR] ; GET DISKETTE VECTOR 8294 <1> ;MOV [DISK_VECTOR],AX ; INTO INT 40H 8295 <1> ;MOV AX, [ORG_VECTOR+2] 8296 <1> ;MOV [DISK_VECTOR+2],AX 8297 <1> ;MOV word [ORG_VECTOR],DISK_IO ; FIXED DISK HANDLER 8298 <1> ;MOV [ORG_VECTOR+2],CS 8299 <1> ; 1st controller (primary master, slave) - IRQ 14 8300 <1> ;;MOV word [HDISK_INT],HD_INT ; FIXED DISK INTERRUPT 8301 <1> ;mov word [HDISK_INT1],HD_INT ; 8302 <1> ;;MOV [HDISK_INT+2],CS 8303 <1> ;mov [HDISK_INT1+2],CS 8304 <1> ; 2nd controller (secondary master, slave) - IRQ 15 8305 <1> ;mov word [HDISK_INT2],HD1_INT ; 8306 <1> ;mov [HDISK_INT2+2],CS 8307 <1> ; 8308 <1> ;;MOV word [HF_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80 8309 <1> ;;MOV word [HF_TBL_VEC+2],DPT_SEGM 8310 <1> ;;MOV word [HF1_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81 8311 <1> ;;MOV word [HF1_TBL_VEC+2],DPT_SEGM 8312 <1> ;push cs 8313 <1> ;pop ds 8314 <1> ;mov word [HDPM_TBL_VEC],HD0_DPT ; PARM TABLE DRIVE 80h 8315 <1> ;mov word [HDPM_TBL_VEC+2],DPT_SEGM 8316 000027CA C705[04710000]0000- <1> mov dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT 8317 000027D2 0900 <1> 8318 <1> ;mov word [HDPS_TBL_VEC],HD1_DPT ; PARM TABLE DRIVE 81h 8319 <1> ;mov word [HDPS_TBL_VEC+2],DPT_SEGM 8320 000027D4 C705[08710000]2000- <1> mov dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT 8321 000027DC 0900 <1> 8322 <1> ;mov word [HDSM_TBL_VEC],HD2_DPT ; PARM TABLE DRIVE 82h 8323 <1> ;mov word [HDSM_TBL_VEC+2],DPT_SEGM 8324 000027DE C705[0C710000]4000- <1> mov dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT 8325 000027E6 0900 <1> 8326 <1> ;mov word [HDSS_TBL_VEC],HD3_DPT ; PARM TABLE DRIVE 83h 8327 <1> ;mov word [HDSS_TBL_VEC+2],DPT_SEGM 8328 000027E8 C705[10710000]6000- <1> mov dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT 8329 000027F0 0900 <1> 8330 <1> ; 8331 <1> ;;IN AL,INTB01 ; TURN ON SECOND INTERRUPT CHIP 8332 <1> ;;;AND AL,0BFH 8333 <1> ;;and al, 3Fh ; enable IRQ 14 and IRQ 15 8334 <1> ;;;JMP $+2 8335 <1> ;;IODELAY 8336 <1> ;;OUT INTB01,AL 8337 <1> ;;IODELAY 8338 <1> ;;IN AL,INTA01 ; LET INTERRUPTS PASS THRU TO 8339 <1> ;;AND AL,0FBH ; SECOND CHIP 8340 <1> ;;;JMP $+2 8341 <1> ;;IODELAY 8342 <1> ;;OUT INTA01,AL 8343 <1> ; 8344 <1> ;STI 8345 <1> ;;PUSH DS ; MOVE ABS0 POINTER TO 8346 <1> ;;POP ES ; EXTRA SEGMENT POINTER 8347 <1> ;;;CALL DDS ; ESTABLISH DATA SEGMENT 8348 <1> ;;MOV byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 8349 <1> ;;MOV byte [HF_NUM],0 ; ZERO NUMBER OF FIXED DISKS 8350 <1> ;;MOV byte [CONTROL_BYTE],0 8351 <1> ;;MOV byte [PORT_OFF],0 ; ZERO CARD OFFSET 8352 <1> ; 20/12/2014 - private code by Erdogan Tan 8353 <1> ; (out of original PC-AT, PC-XT BIOS code) 8354 <1> ;mov si, hd0_type 8355 000027F2 BE[206B0000] <1> mov esi, hd0_type 8356 <1> ;mov cx, 4 8357 000027F7 B904000000 <1> mov ecx, 4 8358 <1> hde_l: 8359 000027FC AC <1> lodsb 8360 000027FD 3C80 <1> cmp al, 80h ; 8?h = existing 8361 000027FF 7206 <1> jb short _L4 8362 00002801 FE05[00710000] <1> inc byte [HF_NUM] ; + 1 hard (fixed) disk drives 8363 <1> _L4: ; 26/02/2015 8364 00002807 E2F3 <1> loop hde_l 8365 <1> ;_L4: ; 0 <= [HF_NUM] =< 4 8366 <1> ;L4: 8367 <1> ; 8368 <1> ;; 31/12/2014 - cancel controller diagnostics here 8369 <1> ;;;mov cx, 3 ; 26/12/2014 (Award BIOS 1999) 8370 <1> ;;mov cl, 3 8371 <1> ;; 8372 <1> ;;MOV DL,80H ; CHECK THE CONTROLLER 8373 <1> ;;hdc_dl: 8374 <1> ;;MOV AH,14H ; USE CONTROLLER DIAGNOSTIC COMMAND 8375 <1> ;;INT 13H ; CALL BIOS WITH DIAGNOSTIC COMMAND 8376 <1> ;;;JC short CTL_ERRX ; DISPLAY ERROR MESSAGE IF BAD RETURN 8377 <1> ;;;jc short POD_DONE ;22/12/2014 8378 <1> ;;jnc short hdc_reset0 8379 <1> ;;loop hdc_dl 8380 <1> ;;; 27/12/2014 8381 <1> ;;stc 8382 <1> ;;retn 8383 <1> ; 8384 <1> ;;hdc_reset0: 8385 <1> ; 18/01/2015 8386 00002809 8A0D[00710000] <1> mov cl, [HF_NUM] 8387 0000280F 20C9 <1> and cl, cl 8388 00002811 740D <1> jz short POD_DONE 8389 <1> ; 8390 00002813 B27F <1> mov dl, 7Fh 8391 <1> hdc_reset1: 8392 00002815 FEC2 <1> inc dl 8393 <1> ;; 31/12/2015 8394 <1> ;;push dx 8395 <1> ;;push cx 8396 <1> ;;push ds 8397 <1> ;;sub ax, ax 8398 <1> ;;mov ds, ax 8399 <1> ;;MOV AX, [TIMER_LOW] ; GET START TIMER COUNTS 8400 <1> ;;pop ds 8401 <1> ;;MOV BX,AX 8402 <1> ;;ADD AX,6*182 ; 60 SECONDS* 18.2 8403 <1> ;;MOV CX,AX 8404 <1> ;;mov word [wait_count], 0 ; 22/12/2014 (reset wait counter) 8405 <1> ;; 8406 <1> ;; 31/12/2014 - cancel HD_RESET_1 8407 <1> ;;CALL HD_RESET_1 ; SET UP DRIVE 0, (1,2,3) 8408 <1> ;;pop cx 8409 <1> ;;pop dx 8410 <1> ;; 8411 <1> ; 18/01/2015 8412 00002817 B40D <1> mov ah, 0Dh ; ALTERNATE RESET 8413 <1> ;int 13h 8414 00002819 E8A4FFFFFF <1> call int13h 8415 0000281E E2F5 <1> loop hdc_reset1 8416 <1> POD_DONE: 8417 00002820 C3 <1> RETn 8418 <1> 8419 <1> ;;----- POD_ERROR 8420 <1> 8421 <1> ;;CTL_ERRX: 8422 <1> ; ;MOV SI,OFFSET F1782 ; CONTROLLER ERROR 8423 <1> ; ;CALL SET_FAIL ; DO NOT IPL FROM DISK 8424 <1> ; ;CALL E_MSG ; DISPLAY ERROR AND SET (BP) ERROR FLAG 8425 <1> ; ;JMP short POD_DONE 8426 <1> 8427 <1> ;;HD_RESET_1: 8428 <1> ;; ;PUSH BX ; SAVE TIMER LIMITS 8429 <1> ;; ;PUSH CX 8430 <1> ;;RES_1: MOV AH,09H ; SET DRIVE PARAMETERS 8431 <1> ;; INT 13H 8432 <1> ;; JC short RES_2 8433 <1> ;; MOV AH,11H ; RECALIBRATE DRIVE 8434 <1> ;; INT 13H 8435 <1> ;; JNC short RES_CK ; DRIVE OK 8436 <1> ;;RES_2: ;CALL POD_TCHK ; CHECK TIME OUT 8437 <1> ;; cmp word [wait_count], 6*182 ; waiting time (in timer ticks) 8438 <1> ;; ; (30 seconds) 8439 <1> ;; ;cmc 8440 <1> ;; ;JNC short RES_1 8441 <1> ;; jb short RES_1 8442 <1> ;;;RES_FL: ;MOV SI,OFFSET F1781 ; INDICATE DISK 1 FAILURE; 8443 <1> ;; ;TEST DL,1 8444 <1> ;; ;JNZ RES_E1 8445 <1> ;; ;MOV SI,OFFSET F1780 ; INDICATE DISK 0 FAILURE 8446 <1> ;; ;CALL SET_FAIL ; DO NOT TRY TO IPL DISK 0 8447 <1> ;; ;JMP SHORT RES_E1 8448 <1> ;;RES_ER: ; 22/12/2014 8449 <1> ;;RES_OK: 8450 <1> ;; ;POP CX ; RESTORE TIMER LIMITS 8451 <1> ;; ;POP BX 8452 <1> ;; RETn 8453 <1> ;; 8454 <1> ;;RES_RS: MOV AH,00H ; RESET THE DRIVE 8455 <1> ;; INT 13H 8456 <1> ;;RES_CK: MOV AH,08H ; GET MAX CYLINDER,HEAD,SECTOR 8457 <1> ;; MOV BL,DL ; SAVE DRIVE CODE 8458 <1> ;; INT 13H 8459 <1> ;; JC short RES_ER 8460 <1> ;; MOV [NEC_STATUS],CX ; SAVE MAX CYLINDER, SECTOR 8461 <1> ;; MOV DL,BL ; RESTORE DRIVE CODE 8462 <1> ;;RES_3: MOV AX,0401H ; VERIFY THE LAST SECTOR 8463 <1> ;; INT 13H 8464 <1> ;; JNC short RES_OK ; VERIFY OK 8465 <1> ;; CMP AH,BAD_SECTOR ; OK ALSO IF JUST ID READ 8466 <1> ;; JE short RES_OK 8467 <1> ;; CMP AH,DATA_CORRECTED 8468 <1> ;; JE short RES_OK 8469 <1> ;; CMP AH,BAD_ECC 8470 <1> ;; JE short RES_OK 8471 <1> ;; ;CALL POD_TCHK ; CHECK FOR TIME OUT 8472 <1> ;; cmp word [wait_count], 6*182 ; waiting time (in timer ticks) 8473 <1> ;; ; (60 seconds) 8474 <1> ;; cmc 8475 <1> ;; JC short RES_ER ; FAILED 8476 <1> ;; MOV CX,[NEC_STATUS] ; GET SECTOR ADDRESS, AND CYLINDER 8477 <1> ;; MOV AL,CL ; SEPARATE OUT SECTOR NUMBER 8478 <1> ;; AND AL,3FH 8479 <1> ;; DEC AL ; TRY PREVIOUS ONE 8480 <1> ;; JZ short RES_RS ; WE'VE TRIED ALL SECTORS ON TRACK 8481 <1> ;; AND CL,0C0H ; KEEP CYLINDER BITS 8482 <1> ;; OR CL,AL ; MERGE SECTOR WITH CYLINDER BITS 8483 <1> ;; MOV [NEC_STATUS],CX ; SAVE CYLINDER, NEW SECTOR NUMBER 8484 <1> ;; JMP short RES_3 ; TRY AGAIN 8485 <1> ;;;RES_ER: MOV SI,OFFSET F1791 ; INDICATE DISK 1 ERROR 8486 <1> ;; ;TEST DL,1 8487 <1> ;; ;JNZ short RES_E1 8488 <1> ;; ;MOV SI,OFFSET F1790 ; INDICATE DISK 0 ERROR 8489 <1> ;;;RES_E1: 8490 <1> ;; ;CALL E_MSG ; DISPLAY ERROR AND SET (BP) ERROR FLAG 8491 <1> ;;;RES_OK: 8492 <1> ;; ;POP CX ; RESTORE TIMER LIMITS 8493 <1> ;; ;POP BX 8494 <1> ;; ;RETn 8495 <1> ; 8496 <1> ;;SET_FAIL: 8497 <1> ; ;MOV AX,X*(CMOS_DIAG+NMI) ; GET CMOS ERROR BYTE 8498 <1> ; ;CALL CMOS_READ 8499 <1> ; ;OR AL,HF_FAIL ; SET DO NOT IPL FROM DISK FLAG 8500 <1> ; ;XCHG AH,AL ; SAVE IT 8501 <1> ; ;CALL CMOS_WRITE ; PUT IT OUT 8502 <1> ; ;RETn 8503 <1> ; 8504 <1> ;;POD_TCHK: ; CHECK FOR 30 SECOND TIME OUT 8505 <1> ; ;POP AX ; SAVE RETURN 8506 <1> ; ;POP CX ; GET TIME OUT LIMITS 8507 <1> ; ;POP BX 8508 <1> ; ;PUSH BX ; AND SAVE THEM AGAIN 8509 <1> ; ;PUSH CX 8510 <1> ; ;PUSH AX 8511 <1> ; ;push ds 8512 <1> ; ;xor ax, ax 8513 <1> ; ;mov ds, ax ; RESTORE RETURN 8514 <1> ; ;MOV AX, [TIMER_LOW] ; AX = CURRENT TIME 8515 <1> ; ; ; BX = START TIME 8516 <1> ; ; ; CX = END TIME 8517 <1> ; ;pop ds 8518 <1> ; ;CMP BX,CX 8519 <1> ; ;JB short TCHK1 ; START < END 8520 <1> ; ;CMP BX,AX 8521 <1> ; ;JB short TCHKG ; END < START < CURRENT 8522 <1> ; ;JMP SHORT TCHK2 ; END, CURRENT < START 8523 <1> ;;TCHK1: CMP AX,BX 8524 <1> ;; JB short TCHKNG ; CURRENT < START < END 8525 <1> ;;TCHK2: CMP AX,CX 8526 <1> ;; JB short TCHKG ; START < CURRENT < END 8527 <1> ;; ; OR CURRENT < END < START 8528 <1> ;;TCHKNG: STC ; CARRY SET INDICATES TIME OUT 8529 <1> ;; RETn 8530 <1> ;;TCHKG: CLC ; INDICATE STILL TIME 8531 <1> ;; RETn 8532 <1> ;; 8533 <1> ;;int_13h: 8534 <1> 8535 <1> ;---------------------------------------- 8536 <1> ; FIXED DISK BIOS ENTRY POINT : 8537 <1> ;---------------------------------------- 8538 <1> 8539 <1> DISK_IO: 8540 00002821 80FA80 <1> CMP DL,80H ; TEST FOR FIXED DISK DRIVE 8541 <1> ;JAE short A1 ; YES, HANDLE HERE 8542 <1> ;;;INT 40H ; DISKETTE HANDLER 8543 <1> ;;call int40h 8544 00002824 0F8225F1FFFF <1> jb DISKETTE_IO_1 8545 <1> ;RET_2: 8546 <1> ;RETf 2 ; BACK TO CALLER 8547 <1> ; retf 4 8548 <1> A1: 8549 0000282A FB <1> STI ; ENABLE INTERRUPTS 8550 <1> ;; 04/01/2015 8551 <1> ;;OR AH,AH 8552 <1> ;;JNZ short A2 8553 <1> ;;INT 40H ; RESET NEC WHEN AH=0 8554 <1> ;;SUB AH,AH 8555 0000282B 80FA83 <1> CMP DL,(80H + S_MAX_FILE - 1) 8556 0000282E 772C <1> JA short RET_2 8557 <1> ; 18/01/2015 8558 00002830 08E4 <1> or ah,ah 8559 00002832 742B <1> jz short A4 8560 00002834 80FC0D <1> cmp ah, 0Dh ; Alternate reset 8561 00002837 7504 <1> jne short A2 8562 00002839 28E4 <1> sub ah,ah ; Reset 8563 0000283B EB22 <1> jmp short A4 8564 <1> A2: 8565 0000283D 80FC08 <1> CMP AH,08H ; GET PARAMETERS IS A SPECIAL CASE 8566 <1> ;JNZ short A3 8567 <1> ;JMP GET_PARM_N 8568 00002840 0F841C030000 <1> je GET_PARM_N 8569 00002846 80FC15 <1> A3: CMP AH,15H ; READ DASD TYPE IS ALSO 8570 <1> ;JNZ short A4 8571 <1> ;JMP READ_DASD_TYPE 8572 00002849 0F84C7020000 <1> je READ_DASD_TYPE 8573 <1> ; 02/02/2015 8574 0000284F 80FC1D <1> cmp ah, 1Dh ;(Temporary for Retro UNIX 386 v1) 8575 <1> ; 12/01/2015 8576 00002852 F5 <1> cmc 8577 00002853 730A <1> jnc short A4 8578 <1> ; 30/01/2015 8579 <1> ;mov byte [CS:DISK_STATUS1],BAD_CMD ; COMMAND ERROR 8580 00002855 C605[FF700000]01 <1> mov byte [DISK_STATUS1], BAD_CMD 8581 <1> ;jmp short RET_2 8582 <1> RET_2: 8583 0000285C CA0400 <1> retf 4 8584 <1> A4: ; SAVE REGISTERS DURING OPERATION 8585 0000285F C8080000 <1> ENTER 8,0 ; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK 8586 00002863 53 <1> PUSH eBX ; IN THE STACK, THE COMMAND BLOCK IS: 8587 00002864 51 <1> PUSH eCX ; @CMD_BLOCK == BYTE PTR [BP]-8 8588 00002865 52 <1> PUSH eDX 8589 00002866 1E <1> PUSH DS 8590 00002867 06 <1> PUSH ES 8591 00002868 56 <1> PUSH eSI 8592 00002869 57 <1> PUSH eDI 8593 <1> ;;04/01/2015 8594 <1> ;;OR AH,AH ; CHECK FOR RESET 8595 <1> ;;JNZ short A5 8596 <1> ;;MOV DL,80H ; FORCE DRIVE 80 FOR RESET 8597 <1> ;;A5: 8598 <1> ;push cs 8599 <1> ;pop ds 8600 <1> ; 21/02/2015 8601 0000286A 6650 <1> push ax 8602 0000286C 66B81000 <1> mov ax, KDATA 8603 00002870 8ED8 <1> mov ds, ax 8604 00002872 8EC0 <1> mov es, ax 8605 00002874 6658 <1> pop ax 8606 00002876 E889000000 <1> CALL DISK_IO_CONT ; PERFORM THE OPERATION 8607 <1> ;;CALL DDS ; ESTABLISH SEGMENT 8608 0000287B 8A25[FF700000] <1> MOV AH,[DISK_STATUS1] ; GET STATUS FROM OPERATION 8609 00002881 80FC01 <1> CMP AH,1 ; SET THE CARRY FLAG TO INDICATE 8610 00002884 F5 <1> CMC ; SUCCESS OR FAILURE 8611 00002885 5F <1> POP eDI ; RESTORE REGISTERS 8612 00002886 5E <1> POP eSI 8613 00002887 07 <1> POP ES 8614 00002888 1F <1> POP DS 8615 00002889 5A <1> POP eDX 8616 0000288A 59 <1> POP eCX 8617 0000288B 5B <1> POP eBX 8618 0000288C C9 <1> LEAVE ; ADJUST (SP) AND RESTORE (BP) 8619 <1> ;RETf 2 ; THROW AWAY SAVED FLAGS 8620 0000288D CA0400 <1> retf 4 8621 <1> ; 21/02/2015 8622 <1> ; dw --> dd 8623 <1> M1: ; FUNCTION TRANSFER TABLE 8624 00002890 [522A0000] <1> dd DISK_RESET ; 000H 8625 00002894 [C92A0000] <1> dd RETURN_STATUS ; 001H 8626 00002898 [D62A0000] <1> dd DISK_READ ; 002H 8627 0000289C [DF2A0000] <1> dd DISK_WRITE ; 003H 8628 000028A0 [E82A0000] <1> dd DISK_VERF ; 004H 8629 000028A4 [002B0000] <1> dd FMT_TRK ; 005H 8630 000028A8 [482A0000] <1> dd BAD_COMMAND ; 006H FORMAT BAD SECTORS 8631 000028AC [482A0000] <1> dd BAD_COMMAND ; 007H FORMAT DRIVE 8632 000028B0 [482A0000] <1> dd BAD_COMMAND ; 008H RETURN PARAMETERS 8633 000028B4 [C72B0000] <1> dd INIT_DRV ; 009H 8634 000028B8 [262C0000] <1> dd RD_LONG ; 00AH 8635 000028BC [2F2C0000] <1> dd WR_LONG ; 00BH 8636 000028C0 [382C0000] <1> dd DISK_SEEK ; 00CH 8637 000028C4 [522A0000] <1> dd DISK_RESET ; 00DH 8638 000028C8 [482A0000] <1> dd BAD_COMMAND ; 00EH READ BUFFER 8639 000028CC [482A0000] <1> dd BAD_COMMAND ; 00FH WRITE BUFFER 8640 000028D0 [602C0000] <1> dd TST_RDY ; 010H 8641 000028D4 [842C0000] <1> dd HDISK_RECAL ; 011H 8642 000028D8 [482A0000] <1> dd BAD_COMMAND ; 012H MEMORY DIAGNOSTIC 8643 000028DC [482A0000] <1> dd BAD_COMMAND ; 013H DRIVE DIAGNOSTIC 8644 000028E0 [BA2C0000] <1> dd CTLR_DIAGNOSTIC ; 014H CONTROLLER DIAGNOSTIC 8645 <1> ; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test) 8646 000028E4 [482A0000] <1> dd BAD_COMMAND ; 015h 8647 000028E8 [482A0000] <1> dd BAD_COMMAND ; 016h 8648 000028EC [482A0000] <1> dd BAD_COMMAND ; 017h 8649 000028F0 [482A0000] <1> dd BAD_COMMAND ; 018h 8650 000028F4 [482A0000] <1> dd BAD_COMMAND ; 019h 8651 000028F8 [482A0000] <1> dd BAD_COMMAND ; 01Ah 8652 000028FC [D62A0000] <1> dd DISK_READ ; 01Bh ; LBA read 8653 00002900 [DF2A0000] <1> dd DISK_WRITE ; 01Ch ; LBA write 8654 <1> M1L EQU $-M1 8655 <1> 8656 <1> DISK_IO_CONT: 8657 <1> ;;CALL DDS ; ESTABLISH SEGMENT 8658 00002904 80FC01 <1> CMP AH,01H ; RETURN STATUS 8659 <1> ;;JNZ short SU0 8660 <1> ;;JMP RETURN_STATUS 8661 00002907 0F84BC010000 <1> je RETURN_STATUS 8662 <1> SU0: 8663 0000290D C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 ; RESET THE STATUS INDICATOR 8664 <1> ;;PUSH BX ; SAVE DATA ADDRESS 8665 <1> ;mov si, bx ;; 14/02/2015 8666 00002914 89DE <1> mov esi, ebx ; 21/02/2015 8667 00002916 8A1D[00710000] <1> MOV BL,[HF_NUM] ; GET NUMBER OF DRIVES 8668 <1> ;; 04/01/2015 8669 <1> ;;PUSH AX 8670 0000291C 80E27F <1> AND DL,7FH ; GET DRIVE AS 0 OR 1 8671 <1> ; (get drive number as 0 to 3) 8672 0000291F 38D3 <1> CMP BL,DL 8673 <1> ;;JBE BAD_COMMAND_POP ; INVALID DRIVE 8674 00002921 0F8621010000 <1> jbe BAD_COMMAND ;; 14/02/2015 8675 <1> ; 8676 <1> ;;03/01/2015 8677 00002927 29DB <1> sub ebx, ebx 8678 00002929 88D3 <1> mov bl, dl 8679 <1> ;sub bh, bh 8680 0000292B 883D[14710000] <1> mov [LBAMode], bh ; 0 8681 <1> ;;test byte [bx+hd0_type], 1 ; LBA ready ? 8682 <1> ;test byte [ebx+hd0_type], 1 8683 <1> ;jz short su1 ; no 8684 <1> ;inc byte [LBAMode] 8685 <1> ;su1: 8686 <1> ; 21/02/2015 (32 bit modification) 8687 <1> ;04/01/2015 8688 00002931 6650 <1> push ax ; *** 8689 <1> ;PUSH ES ; ** 8690 00002933 6652 <1> PUSH DX ; * 8691 00002935 6650 <1> push ax 8692 00002937 E85C060000 <1> CALL GET_VEC ; GET DISK PARAMETERS 8693 <1> ; 02/02/2015 8694 <1> ;mov ax, [ES:BX+16] ; I/O port base address (1F0h, 170h) 8695 0000293C 668B4310 <1> mov ax, [ebx+16] 8696 00002940 66A3[146B0000] <1> mov [HF_PORT], ax 8697 <1> ;mov dx, [ES:BX+18] ; control port address (3F6h, 376h) 8698 00002946 668B5312 <1> mov dx, [ebx+18] 8699 0000294A 668915[166B0000] <1> mov [HF_REG_PORT], dx 8700 <1> ;mov al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h) 8701 00002951 8A4314 <1> mov al, [ebx+20] 8702 <1> ; 23/02/2015 8703 00002954 A840 <1> test al, 40h ; LBA bit (bit 6) 8704 00002956 7406 <1> jz short su1 8705 00002958 FE05[14710000] <1> inc byte [LBAMode] ; 1 8706 <1> su1: 8707 0000295E C0E804 <1> shr al, 4 8708 00002961 2401 <1> and al, 1 8709 00002963 A2[186B0000] <1> mov [hf_m_s], al 8710 <1> ; 8711 <1> ; 03/01/2015 8712 <1> ;MOV AL,byte [ES:BX+8] ; GET CONTROL BYTE MODIFIER 8713 00002968 8A4308 <1> mov al, [ebx+8] 8714 <1> ;MOV DX,[HF_REG_PORT] ; Device Control register 8715 0000296B EE <1> OUT DX,AL ; SET EXTRA HEAD OPTION 8716 <1> ; Control Byte: (= 08h, here) 8717 <1> ; bit 0 - 0 8718 <1> ; bit 1 - nIEN (1 = disable irq) 8719 <1> ; bit 2 - SRST (software RESET) 8720 <1> ; bit 3 - use extra heads (8 to 15) 8721 <1> ; -always set to 1- 8722 <1> ; (bits 3 to 7 are reserved 8723 <1> ; for ATA devices) 8724 0000296C 8A25[01710000] <1> MOV AH,[CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 8725 00002972 80E4C0 <1> AND AH,0C0H ; CONTROL BYTE 8726 00002975 08C4 <1> OR AH,AL 8727 00002977 8825[01710000] <1> MOV [CONTROL_BYTE],AH 8728 <1> ; 04/01/2015 8729 0000297D 6658 <1> pop ax 8730 0000297F 665A <1> pop dx ; * ;; 14/02/2015 8731 00002981 20E4 <1> and ah, ah ; Reset function ? 8732 00002983 7507 <1> jnz short su2 8733 <1> ;;pop dx ; * ;; 14/02/2015 8734 <1> ;pop es ; ** 8735 00002985 6658 <1> pop ax ; *** 8736 <1> ;;pop bx 8737 00002987 E9C6000000 <1> jmp DISK_RESET 8738 <1> su2: 8739 0000298C 803D[14710000]00 <1> cmp byte [LBAMode], 0 8740 00002993 7661 <1> jna short su3 8741 <1> ; 8742 <1> ; 02/02/2015 (LBA read/write function calls) 8743 00002995 80FC1B <1> cmp ah, 1Bh 8744 00002998 720B <1> jb short lbarw1 8745 0000299A 80FC1C <1> cmp ah, 1Ch 8746 0000299D 775C <1> ja short invldfnc 8747 <1> ;;pop dx ; * ; 14/02/2015 8748 <1> ;mov ax, cx ; Lower word of LBA address (bits 0-15) 8749 0000299F 89C8 <1> mov eax, ecx ; LBA address (21/02/2015) 8750 <1> ;; 14/02/2015 8751 000029A1 88D1 <1> mov cl, dl ; 14/02/2015 8752 <1> ;;mov dx, bx 8753 <1> ;mov dx, si ; higher word of LBA address (bits 16-23) 8754 <1> ;;mov bx, di 8755 <1> ;mov si, di ; Buffer offset 8756 000029A3 EB31 <1> jmp short lbarw2 8757 <1> lbarw1: 8758 <1> ; convert CHS to LBA 8759 <1> ; 8760 <1> ; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM 8761 <1> ; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track 8762 <1> ; + Sector - 1 8763 000029A5 6652 <1> push dx ; * ;; 14/02/2015 8764 <1> ;xor dh, dh 8765 000029A7 31D2 <1> xor edx, edx 8766 <1> ;mov dl, [ES:BX+14] ; sectors per track (logical) 8767 000029A9 8A530E <1> mov dl, [ebx+14] 8768 <1> ;xor ah, ah 8769 000029AC 31C0 <1> xor eax, eax 8770 <1> ;mov al, [ES:BX+2] ; heads (logical) 8771 000029AE 8A4302 <1> mov al, [ebx+2] 8772 000029B1 FEC8 <1> dec al 8773 000029B3 6640 <1> inc ax ; 0 = 256 8774 000029B5 66F7E2 <1> mul dx 8775 <1> ; AX = # of Heads" * Sectors/Track 8776 000029B8 6689CA <1> mov dx, cx 8777 <1> ;and cx, 3Fh ; sector (1 to 63) 8778 000029BB 83E13F <1> and ecx, 3fh 8779 000029BE 86D6 <1> xchg dl, dh 8780 000029C0 C0EE06 <1> shr dh, 6 8781 <1> ; DX = cylinder (0 to 1023) 8782 <1> ;mul dx 8783 <1> ; DX:AX = # of Heads" * Sectors/Track * Cylinder 8784 000029C3 F7E2 <1> mul edx 8785 000029C5 FEC9 <1> dec cl ; sector - 1 8786 <1> ;add ax, cx 8787 <1> ;adc dx, 0 8788 <1> ; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1 8789 000029C7 01C8 <1> add eax, ecx 8790 000029C9 6659 <1> pop cx ; * ; ch = head, cl = drive number (zero based) 8791 <1> ;push dx 8792 <1> ;push ax 8793 000029CB 50 <1> push eax 8794 <1> ;mov al, [ES:BX+14] ; sectors per track (logical) 8795 000029CC 8A430E <1> mov al, [ebx+14] 8796 000029CF F6E5 <1> mul ch 8797 <1> ; AX = Head * Sectors/Track 8798 000029D1 6699 <1> cwd 8799 <1> ;pop dx 8800 000029D3 5A <1> pop edx 8801 <1> ;add ax, dx 8802 <1> ;pop dx 8803 <1> ;adc dx, 0 ; add carry bit 8804 000029D4 01D0 <1> add eax, edx 8805 <1> lbarw2: 8806 000029D6 29D2 <1> sub edx, edx ; 21/02/2015 8807 000029D8 88CA <1> mov dl, cl ; 21/02/2015 8808 000029DA C645F800 <1> mov byte [CMD_BLOCK], 0 ; Features Register 8809 <1> ; NOTE: Features register (1F1h, 171h) 8810 <1> ; is not used for ATA device R/W functions. 8811 <1> ; It is old/obsolete 'write precompensation' 8812 <1> ; register and error register 8813 <1> ; for old ATA/IDE devices. 8814 <1> ; 18/01/2014 8815 <1> ;mov ch, [hf_m_s] ; Drive 0 (master) or 1 (slave) 8816 000029DE 8A0D[186B0000] <1> mov cl, [hf_m_s] 8817 <1> ;shl ch, 4 ; bit 4 (drive bit) 8818 <1> ;or ch, 0E0h ; bit 5 = 1 8819 <1> ; bit 6 = 1 = LBA mode 8820 <1> ; bit 7 = 1 8821 000029E4 80C90E <1> or cl, 0Eh ; 1110b 8822 <1> ;and dh, 0Fh ; LBA byte 4 (bits 24 to 27) 8823 000029E7 25FFFFFF0F <1> and eax, 0FFFFFFFh 8824 000029EC C1E11C <1> shl ecx, 28 ; 21/02/2015 8825 <1> ;or dh, ch 8826 000029EF 09C8 <1> or eax, ecx 8827 <1> ;;mov [CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7) 8828 <1> ; (Sector Number Register) 8829 <1> ;;mov [CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15) 8830 <1> ; (Cylinder Low Register) 8831 <1> ;mov [CMD_BLOCK+2], ax ; LBA byte 1, 2 8832 <1> ;mov [CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23) 8833 <1> ; (Cylinder High Register) 8834 <1> ;;mov [CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27) 8835 <1> ; (Drive/Head Register) 8836 <1> 8837 <1> ;mov [CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits 8838 000029F1 8945FA <1> mov [CMD_BLOCK+2], eax ; 21/02/2015 8839 <1> ;14/02/2015 8840 <1> ;mov dl, cl ; Drive number (INIT_DRV) 8841 000029F4 EB38 <1> jmp short su4 8842 <1> su3: 8843 <1> ; 02/02/2015 8844 <1> ; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 8845 000029F6 80FC14 <1> cmp ah, 14h 8846 000029F9 7604 <1> jna short chsfnc 8847 <1> invldfnc: 8848 <1> ; 14/02/2015 8849 <1> ;pop es ; ** 8850 000029FB 6658 <1> pop ax ; *** 8851 <1> ;jmp short BAD_COMMAND_POP 8852 000029FD EB49 <1> jmp short BAD_COMMAND 8853 <1> chsfnc: 8854 <1> ;MOV AX,[ES:BX+5] ; GET WRITE PRE-COMPENSATION CYLINDER 8855 000029FF 668B4305 <1> mov ax, [ebx+5] 8856 00002A03 66C1E802 <1> SHR AX,2 8857 00002A07 8845F8 <1> MOV [CMD_BLOCK],AL 8858 <1> ;;MOV AL,[ES:BX+8] ; GET CONTROL BYTE MODIFIER 8859 <1> ;;PUSH DX 8860 <1> ;;MOV DX,[HF_REG_PORT] 8861 <1> ;;OUT DX,AL ; SET EXTRA HEAD OPTION 8862 <1> ;;POP DX ; * 8863 <1> ;;POP ES ; ** 8864 <1> ;;MOV AH,[CONTROL_BYTE] ; SET EXTRA HEAD OPTION IN 8865 <1> ;;AND AH,0C0H ; CONTROL BYTE 8866 <1> ;;OR AH,AL 8867 <1> ;;MOV [CONTROL_BYTE],AH 8868 <1> ; 8869 00002A0A 88C8 <1> MOV AL,CL ; GET SECTOR NUMBER 8870 00002A0C 243F <1> AND AL,3FH 8871 00002A0E 8845FA <1> MOV [CMD_BLOCK+2],AL 8872 00002A11 886DFB <1> MOV [CMD_BLOCK+3],CH ; GET CYLINDER NUMBER 8873 00002A14 88C8 <1> MOV AL,CL 8874 00002A16 C0E806 <1> SHR AL,6 8875 00002A19 8845FC <1> MOV [CMD_BLOCK+4],AL ; CYLINDER HIGH ORDER 2 BITS 8876 <1> ;;05/01/2015 8877 <1> ;;MOV AL,DL ; DRIVE NUMBER 8878 00002A1C A0[186B0000] <1> mov al, [hf_m_s] 8879 00002A21 C0E004 <1> SHL AL,4 8880 00002A24 80E60F <1> AND DH,0FH ; HEAD NUMBER 8881 00002A27 08F0 <1> OR AL,DH 8882 <1> ;OR AL,80H or 20H 8883 00002A29 0CA0 <1> OR AL,80h+20h ; ECC AND 512 BYTE SECTORS 8884 00002A2B 8845FD <1> MOV [CMD_BLOCK+5],AL ; ECC/SIZE/DRIVE/HEAD 8885 <1> su4: 8886 <1> ;POP ES ; ** 8887 <1> ;; 14/02/2015 8888 <1> ;;POP AX 8889 <1> ;;MOV [CMD_BLOCK+1],AL ; SECTOR COUNT 8890 <1> ;;PUSH AX 8891 <1> ;;MOV AL,AH ; GET INTO LOW BYTE 8892 <1> ;;XOR AH,AH ; ZERO HIGH BYTE 8893 <1> ;;SAL AX,1 ; *2 FOR TABLE LOOKUP 8894 00002A2E 6658 <1> pop ax ; *** 8895 00002A30 8845F9 <1> mov [CMD_BLOCK+1], al 8896 00002A33 29DB <1> sub ebx, ebx 8897 00002A35 88E3 <1> mov bl, ah 8898 <1> ;xor bh, bh 8899 <1> ;sal bx, 1 8900 00002A37 66C1E302 <1> sal bx, 2 ; 32 bit offset (21/02/2015) 8901 <1> ;;MOV SI,AX ; PUT INTO SI FOR BRANCH 8902 <1> ;;CMP AX,M1L ; TEST WITHIN RANGE 8903 <1> ;;JNB short BAD_COMMAND_POP 8904 <1> ;cmp bx, M1L 8905 00002A3B 83FB74 <1> cmp ebx, M1L 8906 00002A3E 7308 <1> jnb short BAD_COMMAND 8907 <1> ;xchg bx, si 8908 00002A40 87DE <1> xchg ebx, esi 8909 <1> ;;;POP AX ; RESTORE AX 8910 <1> ;;;POP BX ; AND DATA ADDRESS 8911 <1> 8912 <1> ;;PUSH CX 8913 <1> ;;PUSH AX ; ADJUST ES:BX 8914 <1> ;MOV CX,BX ; GET 3 HIGH ORDER NIBBLES OF BX 8915 <1> ;SHR CX,4 8916 <1> ;MOV AX,ES 8917 <1> ;ADD AX,CX 8918 <1> ;MOV ES,AX 8919 <1> ;AND BX,000FH ; ES:BX CHANGED TO ES:000X 8920 <1> ;;POP AX 8921 <1> ;;POP CX 8922 <1> ;;JMP word [CS:SI+M1] 8923 <1> ;jmp word [SI+M1] 8924 00002A42 FFA6[90280000] <1> jmp dword [esi+M1] 8925 <1> ;;BAD_COMMAND_POP: 8926 <1> ;; POP AX 8927 <1> ;; POP BX 8928 <1> BAD_COMMAND: 8929 00002A48 C605[FF700000]01 <1> MOV byte [DISK_STATUS1],BAD_CMD ; COMMAND ERROR 8930 00002A4F B000 <1> MOV AL,0 8931 00002A51 C3 <1> RETn 8932 <1> 8933 <1> ;---------------------------------------- 8934 <1> ; RESET THE DISK SYSTEM (AH=00H) : 8935 <1> ;---------------------------------------- 8936 <1> 8937 <1> ; 18-1-2015 : one controller reset (not other one) 8938 <1> 8939 <1> DISK_RESET: 8940 00002A52 FA <1> CLI 8941 00002A53 E4A1 <1> IN AL,INTB01 ; GET THE MASK REGISTER 8942 <1> ;JMP $+2 8943 <1> IODELAY 8944 00002A55 EB00 <2> jmp short $+2 8945 00002A57 EB00 <2> jmp short $+2 8946 <1> ;AND AL,0BFH ; ENABLE FIXED DISK INTERRUPT 8947 00002A59 243F <1> and al,3Fh ; 22/12/2014 (IRQ 14 & IRQ 15) 8948 00002A5B E6A1 <1> OUT INTB01,AL 8949 00002A5D FB <1> STI ; START INTERRUPTS 8950 <1> ; 14/02/2015 8951 00002A5E 6689D7 <1> mov di, dx 8952 <1> ; 04/01/2015 8953 <1> ;xor di,di 8954 <1> drst0: 8955 00002A61 B004 <1> MOV AL,04H ; bit 2 - SRST 8956 <1> ;MOV DX,HF_REG_PORT 8957 00002A63 668B15[166B0000] <1> MOV DX,[HF_REG_PORT] 8958 00002A6A EE <1> OUT DX,AL ; RESET 8959 <1> ; MOV CX,10 ; DELAY COUNT 8960 <1> ;DRD: DEC CX 8961 <1> ; JNZ short DRD ; WAIT 4.8 MICRO-SEC 8962 <1> ;mov cx,2 ; wait for 30 micro seconds 8963 00002A6B B902000000 <1> mov ecx, 2 ; 21/02/2015 8964 00002A70 E874EBFFFF <1> call WAITF ; (Award Bios 1999 - WAIT_REFRESH, 8965 <1> ; 40 micro seconds) 8966 00002A75 A0[01710000] <1> mov al,[CONTROL_BYTE] 8967 00002A7A 240F <1> AND AL,0FH ; SET HEAD OPTION 8968 00002A7C EE <1> OUT DX,AL ; TURN RESET OFF 8969 00002A7D E80E040000 <1> CALL NOT_BUSY 8970 00002A82 7515 <1> JNZ short DRERR ; TIME OUT ON RESET 8971 00002A84 668B15[146B0000] <1> MOV DX,[HF_PORT] 8972 00002A8B FEC2 <1> inc dl ; HF_PORT+1 8973 <1> ; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM 8974 <1> ;mov cl, 10 8975 00002A8D B90A000000 <1> mov ecx, 10 ; 21/02/2015 8976 <1> drst1: 8977 00002A92 EC <1> IN AL,DX ; GET RESET STATUS 8978 00002A93 3C01 <1> CMP AL,1 8979 <1> ; 04/01/2015 8980 00002A95 740A <1> jz short drst2 8981 <1> ;JNZ short DRERR ; BAD RESET STATUS 8982 <1> ; Drive/Head Register - bit 4 8983 00002A97 E2F9 <1> loop drst1 8984 <1> DRERR: 8985 00002A99 C605[FF700000]05 <1> MOV byte [DISK_STATUS1],BAD_RESET ; CARD FAILED 8986 00002AA0 C3 <1> RETn 8987 <1> drst2: 8988 <1> ; 14/02/2015 8989 00002AA1 6689FA <1> mov dx,di 8990 <1> ;drst3: 8991 <1> ; ; 05/01/2015 8992 <1> ; shl di,1 8993 <1> ; ; 04/01/2015 8994 <1> ; mov ax,[di+hd_cports] 8995 <1> ; cmp ax,[HF_REG_PORT] 8996 <1> ; je short drst4 8997 <1> ; mov [HF_REG_PORT], ax 8998 <1> ; ; 03/01/2015 8999 <1> ; mov ax,[di+hd_ports] 9000 <1> ; mov [HF_PORT], ax 9001 <1> ; ; 05/01/2014 9002 <1> ; shr di,1 9003 <1> ; ; 04/01/2015 9004 <1> ; jmp short drst0 ; reset other controller 9005 <1> ;drst4: 9006 <1> ; ; 05/01/2015 9007 <1> ; shr di,1 9008 <1> ; mov al,[di+hd_dregs] 9009 <1> ; and al,10h ; bit 4 only 9010 <1> ; shr al,4 ; bit 4 -> bit 0 9011 <1> ; mov [hf_m_s], al ; (0 = master, 1 = slave) 9012 <1> ; 9013 00002AA4 A0[186B0000] <1> mov al, [hf_m_s] ; 18/01/2015 9014 00002AA9 A801 <1> test al,1 9015 <1> ; jnz short drst6 9016 00002AAB 7516 <1> jnz short drst4 9017 00002AAD 8065FDEF <1> AND byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0 9018 <1> ;drst5: 9019 <1> drst3: 9020 00002AB1 E811010000 <1> CALL INIT_DRV ; SET MAX HEADS 9021 <1> ;mov dx,di 9022 00002AB6 E8C9010000 <1> CALL HDISK_RECAL ; RECAL TO RESET SEEK SPEED 9023 <1> ; 04/01/2014 9024 <1> ; inc di 9025 <1> ; mov dx,di 9026 <1> ; cmp dl,[HF_NUM] 9027 <1> ; jb short drst3 9028 <1> ;DRE: 9029 00002ABB C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 ; IGNORE ANY SET UP ERRORS 9030 00002AC2 C3 <1> RETn 9031 <1> ;drst6: 9032 <1> drst4: ; Drive/Head Register - bit 4 9033 00002AC3 804DFD10 <1> OR byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1 9034 <1> ;jmp short drst5 9035 00002AC7 EBE8 <1> jmp short drst3 9036 <1> 9037 <1> ;---------------------------------------- 9038 <1> ; DISK STATUS ROUTINE (AH = 01H) : 9039 <1> ;---------------------------------------- 9040 <1> 9041 <1> RETURN_STATUS: 9042 00002AC9 A0[FF700000] <1> MOV AL,[DISK_STATUS1] ; OBTAIN PREVIOUS STATUS 9043 00002ACE C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 ; RESET STATUS 9044 00002AD5 C3 <1> RETn 9045 <1> 9046 <1> ;---------------------------------------- 9047 <1> ; DISK READ ROUTINE (AH = 02H) : 9048 <1> ;---------------------------------------- 9049 <1> 9050 <1> DISK_READ: 9051 00002AD6 C645FE20 <1> MOV byte [CMD_BLOCK+6],READ_CMD 9052 00002ADA E930020000 <1> JMP COMMANDI 9053 <1> 9054 <1> ;---------------------------------------- 9055 <1> ; DISK WRITE ROUTINE (AH = 03H) : 9056 <1> ;---------------------------------------- 9057 <1> 9058 <1> DISK_WRITE: 9059 00002ADF C645FE30 <1> MOV byte [CMD_BLOCK+6],WRITE_CMD 9060 00002AE3 E97C020000 <1> JMP COMMANDO 9061 <1> 9062 <1> ;---------------------------------------- 9063 <1> ; DISK VERIFY (AH = 04H) : 9064 <1> ;---------------------------------------- 9065 <1> 9066 <1> DISK_VERF: 9067 00002AE8 C645FE40 <1> MOV byte [CMD_BLOCK+6],VERIFY_CMD 9068 00002AEC E8EA020000 <1> CALL COMMAND 9069 00002AF1 750C <1> JNZ short VERF_EXIT ; CONTROLLER STILL BUSY 9070 00002AF3 E85C030000 <1> CALL _WAIT ; (Original: CALL WAIT) 9071 00002AF8 7505 <1> JNZ short VERF_EXIT ; TIME OUT 9072 00002AFA E8E9030000 <1> CALL CHECK_STATUS 9073 <1> VERF_EXIT: 9074 00002AFF C3 <1> RETn 9075 <1> 9076 <1> ;---------------------------------------- 9077 <1> ; FORMATTING (AH = 05H) : 9078 <1> ;---------------------------------------- 9079 <1> 9080 <1> FMT_TRK: ; FORMAT TRACK (AH = 005H) 9081 00002B00 C645FE50 <1> MOV byte [CMD_BLOCK+6],FMTTRK_CMD 9082 <1> ;PUSH ES 9083 <1> ;PUSH BX 9084 00002B04 53 <1> push ebx 9085 00002B05 E88E040000 <1> CALL GET_VEC ; GET DISK PARAMETERS ADDRESS 9086 <1> ;MOV AL,[ES:BX+14] ; GET SECTORS/TRACK 9087 00002B0A 8A430E <1> mov al, [ebx+14] 9088 00002B0D 8845F9 <1> MOV [CMD_BLOCK+1],AL ; SET SECTOR COUNT IN COMMAND 9089 00002B10 5B <1> pop ebx 9090 <1> ;POP BX 9091 <1> ;POP ES 9092 00002B11 E955020000 <1> JMP CMD_OF ; GO EXECUTE THE COMMAND 9093 <1> 9094 <1> ;---------------------------------------- 9095 <1> ; READ DASD TYPE (AH = 15H) : 9096 <1> ;---------------------------------------- 9097 <1> 9098 <1> READ_DASD_TYPE: 9099 <1> READ_D_T: ; GET DRIVE PARAMETERS 9100 00002B16 1E <1> PUSH DS ; SAVE REGISTERS 9101 <1> ;PUSH ES 9102 00002B17 53 <1> PUSH eBX 9103 <1> ;CALL DDS ; ESTABLISH ADDRESSING 9104 <1> ;push cs 9105 <1> ;pop ds 9106 00002B18 66BB1000 <1> mov bx, KDATA 9107 00002B1C 8EDB <1> mov ds, bx 9108 <1> ;mov es, bx 9109 00002B1E C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 9110 00002B25 8A1D[00710000] <1> MOV BL,[HF_NUM] ; GET NUMBER OF DRIVES 9111 00002B2B 80E27F <1> AND DL,7FH ; GET DRIVE NUMBER 9112 00002B2E 38D3 <1> CMP BL,DL 9113 00002B30 7625 <1> JBE short RDT_NOT_PRESENT ; RETURN DRIVE NOT PRESENT 9114 00002B32 E861040000 <1> CALL GET_VEC ; GET DISK PARAMETER ADDRESS 9115 <1> ;MOV AL,[ES:BX+2] ; HEADS 9116 00002B37 8A4302 <1> mov al, [ebx+2] 9117 <1> ;MOV CL,[ES:BX+14] 9118 00002B3A 8A4B0E <1> mov cl, [ebx+14] 9119 00002B3D F6E9 <1> IMUL CL ; * NUMBER OF SECTORS 9120 <1> ;MOV CX,[ES:BX] ; MAX NUMBER OF CYLINDERS 9121 00002B3F 668B0B <1> mov cx ,[ebx] 9122 <1> ; 9123 <1> ; 02/01/2015 9124 <1> ; ** leave the last cylinder as reserved for diagnostics ** 9125 <1> ; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1) 9126 00002B42 6649 <1> DEC CX ; LEAVE ONE FOR DIAGNOSTICS 9127 <1> ; 9128 00002B44 66F7E9 <1> IMUL CX ; NUMBER OF SECTORS 9129 00002B47 6689D1 <1> MOV CX,DX ; HIGH ORDER HALF 9130 00002B4A 6689C2 <1> MOV DX,AX ; LOW ORDER HALF 9131 <1> ;SUB AX,AX 9132 00002B4D 28C0 <1> sub al, al 9133 00002B4F B403 <1> MOV AH,03H ; INDICATE FIXED DISK 9134 00002B51 5B <1> RDT2: POP eBX ; RESTORE REGISTERS 9135 <1> ;POP ES 9136 00002B52 1F <1> POP DS 9137 00002B53 F8 <1> CLC ; CLEAR CARRY 9138 <1> ;RETf 2 9139 00002B54 CA0400 <1> retf 4 9140 <1> RDT_NOT_PRESENT: 9141 00002B57 6629C0 <1> SUB AX,AX ; DRIVE NOT PRESENT RETURN 9142 00002B5A 6689C1 <1> MOV CX,AX ; ZERO BLOCK COUNT 9143 00002B5D 6689C2 <1> MOV DX,AX 9144 00002B60 EBEF <1> JMP short RDT2 9145 <1> 9146 <1> ;---------------------------------------- 9147 <1> ; GET PARAMETERS (AH = 08H) : 9148 <1> ;---------------------------------------- 9149 <1> 9150 <1> GET_PARM_N: 9151 <1> ;GET_PARM: ; GET DRIVE PARAMETERS 9152 00002B62 1E <1> PUSH DS ; SAVE REGISTERS 9153 <1> ;PUSH ES 9154 00002B63 53 <1> PUSH eBX 9155 <1> ;MOV AX,ABS0 ; ESTABLISH ADDRESSING 9156 <1> ;MOV DS,AX 9157 <1> ;TEST DL,1 ; CHECK FOR DRIVE 1 9158 <1> ;JZ short G0 9159 <1> ;LES BX,@HF1_TBL_VEC 9160 <1> ;JMP SHORT G1 9161 <1> ;G0: LES BX,@HF_TBL_VEC 9162 <1> ;G1: 9163 <1> ;CALL DDS ; ESTABLISH SEGMENT 9164 <1> ; 22/12/2014 9165 <1> ;push cs 9166 <1> ;pop ds 9167 00002B64 66BB1000 <1> mov bx, KDATA 9168 00002B68 8EDB <1> mov ds, bx 9169 <1> ;mov es, bx 9170 <1> ; 9171 00002B6A 80EA80 <1> SUB DL,80H 9172 00002B6D 80FA04 <1> CMP DL,MAX_FILE ; TEST WITHIN RANGE 9173 00002B70 7341 <1> JAE short G4 9174 <1> ; 9175 00002B72 31DB <1> xor ebx, ebx ; 21/02/2015 9176 <1> ; 22/12/2014 9177 00002B74 88D3 <1> mov bl, dl 9178 <1> ;xor bh, bh 9179 00002B76 C0E302 <1> shl bl, 2 ; convert index to offset 9180 <1> ;add bx, HF_TBL_VEC 9181 00002B79 81C3[04710000] <1> add ebx, HF_TBL_VEC 9182 <1> ;mov ax, [bx+2] 9183 <1> ;mov es, ax ; dpt segment 9184 <1> ;mov bx, [bx] ; dpt offset 9185 00002B7F 8B1B <1> mov ebx, [ebx] ; 32 bit offset 9186 <1> 9187 00002B81 C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 9188 <1> ;MOV AX,[ES:BX] ; MAX NUMBER OF CYLINDERS 9189 00002B88 668B03 <1> mov ax, [ebx] 9190 <1> ;;SUB AX,2 ; ADJUST FOR 0-N 9191 00002B8B 6648 <1> dec ax ; max. cylinder number 9192 00002B8D 88C5 <1> MOV CH,AL 9193 00002B8F 66250003 <1> AND AX,0300H ; HIGH TWO BITS OF CYLINDER 9194 00002B93 66D1E8 <1> SHR AX,1 9195 00002B96 66D1E8 <1> SHR AX,1 9196 <1> ;OR AL,[ES:BX+14] ; SECTORS 9197 00002B99 0A430E <1> or al, [ebx+14] 9198 00002B9C 88C1 <1> MOV CL,AL 9199 <1> ;MOV DH,[ES:BX+2] ; HEADS 9200 00002B9E 8A7302 <1> mov dh, [ebx+2] 9201 00002BA1 FECE <1> DEC DH ; 0-N RANGE 9202 00002BA3 8A15[00710000] <1> MOV DL,[HF_NUM] ; DRIVE COUNT 9203 00002BA9 6629C0 <1> SUB AX,AX 9204 <1> ;27/12/2014 9205 <1> ; ES:DI = Address of disk parameter table from BIOS 9206 <1> ;(Programmer's Guide to the AMIBIOS - 1993) 9207 <1> ;mov di, bx ; HDPT offset 9208 00002BAC 89DF <1> mov edi, ebx 9209 <1> G5: 9210 00002BAE 5B <1> POP eBX ; RESTORE REGISTERS 9211 <1> ;POP ES 9212 00002BAF 1F <1> POP DS 9213 <1> ;RETf 2 9214 00002BB0 CA0400 <1> retf 4 9215 <1> G4: 9216 00002BB3 C605[FF700000]07 <1> MOV byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED 9217 00002BBA B407 <1> MOV AH,INIT_FAIL 9218 00002BBC 28C0 <1> SUB AL,AL 9219 00002BBE 6629D2 <1> SUB DX,DX 9220 00002BC1 6629C9 <1> SUB CX,CX 9221 00002BC4 F9 <1> STC ; SET ERROR FLAG 9222 00002BC5 EBE7 <1> JMP short G5 9223 <1> 9224 <1> ;---------------------------------------- 9225 <1> ; INITIALIZE DRIVE (AH = 09H) : 9226 <1> ;---------------------------------------- 9227 <1> ; 03/01/2015 9228 <1> ; According to ATA-ATAPI specification v2.0 to v5.0 9229 <1> ; logical sector per logical track 9230 <1> ; and logical heads - 1 would be set but 9231 <1> ; it is seen as it will be good 9232 <1> ; if physical parameters will be set here 9233 <1> ; because, number of heads <= 16. 9234 <1> ; (logical heads usually more than 16) 9235 <1> ; NOTE: ATA logical parameters (software C, H, S) 9236 <1> ; == INT 13h physical parameters 9237 <1> 9238 <1> ;INIT_DRV: 9239 <1> ; MOV byte [CMD_BLOCK+6],SET_PARM_CMD 9240 <1> ; CALL GET_VEC ; ES:BX -> PARAMETER BLOCK 9241 <1> ; MOV AL,[ES:BX+2] ; GET NUMBER OF HEADS 9242 <1> ; DEC AL ; CONVERT TO 0-INDEX 9243 <1> ; MOV AH,[CMD_BLOCK+5] ; GET SDH REGISTER 9244 <1> ; AND AH,0F0H ; CHANGE HEAD NUMBER 9245 <1> ; OR AH,AL ; TO MAX HEAD 9246 <1> ; MOV [CMD_BLOCK+5],AH 9247 <1> ; MOV AL,[ES:BX+14] ; MAX SECTOR NUMBER 9248 <1> ; MOV [CMD_BLOCK+1],AL 9249 <1> ; SUB AX,AX 9250 <1> ; MOV [CMD_BLOCK+3],AL ; ZERO FLAGS 9251 <1> ; CALL COMMAND ; TELL CONTROLLER 9252 <1> ; JNZ short INIT_EXIT ; CONTROLLER BUSY ERROR 9253 <1> ; CALL NOT_BUSY ; WAIT FOR IT TO BE DONE 9254 <1> ; JNZ short INIT_EXIT ; TIME OUT 9255 <1> ; CALL CHECK_STATUS 9256 <1> ;INIT_EXIT: 9257 <1> ; RETn 9258 <1> 9259 <1> ; 04/01/2015 9260 <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999 9261 <1> ; AHDSK.ASM - INIT_DRIVE 9262 <1> INIT_DRV: 9263 <1> ;xor ah,ah 9264 00002BC7 31C0 <1> xor eax, eax ; 21/02/2015 9265 00002BC9 B00B <1> mov al,11 ; Physical heads from translated HDPT 9266 00002BCB 3825[14710000] <1> cmp [LBAMode], ah ; 0 9267 00002BD1 7702 <1> ja short idrv0 9268 00002BD3 B002 <1> mov al,2 ; Physical heads from standard HDPT 9269 <1> idrv0: 9270 <1> ; DL = drive number (0 based) 9271 00002BD5 E8BE030000 <1> call GET_VEC 9272 <1> ;push bx 9273 00002BDA 53 <1> push ebx ; 21/02/2015 9274 <1> ;add bx,ax 9275 00002BDB 01C3 <1> add ebx, eax 9276 <1> ;; 05/01/2015 9277 00002BDD 8A25[186B0000] <1> mov ah, [hf_m_s] ; drive number (0= master, 1= slave) 9278 <1> ;;and ah,1 9279 00002BE3 C0E404 <1> shl ah,4 9280 00002BE6 80CCA0 <1> or ah,0A0h ; Drive/Head register - 10100000b (A0h) 9281 <1> ;mov al,[es:bx] 9282 00002BE9 8A03 <1> mov al, [ebx] ; 21/02/2015 9283 00002BEB FEC8 <1> dec al ; last head number 9284 <1> ;and al,0Fh 9285 00002BED 08E0 <1> or al,ah ; lower 4 bits for head number 9286 <1> ; 9287 00002BEF C645FE91 <1> mov byte [CMD_BLOCK+6],SET_PARM_CMD 9288 00002BF3 8845FD <1> mov [CMD_BLOCK+5],al 9289 <1> ;pop bx 9290 00002BF6 5B <1> pop ebx 9291 00002BF7 29C0 <1> sub eax, eax ; 21/02/2015 9292 00002BF9 B004 <1> mov al,4 ; Physical sec per track from translated HDPT 9293 00002BFB 803D[14710000]00 <1> cmp byte [LBAMode], 0 9294 00002C02 7702 <1> ja short idrv1 9295 00002C04 B00E <1> mov al,14 ; Physical sec per track from standard HDPT 9296 <1> idrv1: 9297 <1> ;xor ah,ah 9298 <1> ;add bx,ax 9299 00002C06 01C3 <1> add ebx, eax ; 21/02/2015 9300 <1> ;mov al,[es:bx] 9301 <1> ; sector number 9302 00002C08 8A03 <1> mov al, [ebx] 9303 00002C0A 8845F9 <1> mov [CMD_BLOCK+1],al 9304 00002C0D 28C0 <1> sub al,al 9305 00002C0F 8845FB <1> mov [CMD_BLOCK+3],al ; ZERO FLAGS 9306 00002C12 E8C4010000 <1> call COMMAND ; TELL CONTROLLER 9307 00002C17 750C <1> jnz short INIT_EXIT ; CONTROLLER BUSY ERROR 9308 00002C19 E872020000 <1> call NOT_BUSY ; WAIT FOR IT TO BE DONE 9309 00002C1E 7505 <1> jnz short INIT_EXIT ; TIME OUT 9310 00002C20 E8C3020000 <1> call CHECK_STATUS 9311 <1> INIT_EXIT: 9312 00002C25 C3 <1> RETn 9313 <1> 9314 <1> ;---------------------------------------- 9315 <1> ; READ LONG (AH = 0AH) : 9316 <1> ;---------------------------------------- 9317 <1> 9318 <1> RD_LONG: 9319 <1> ;MOV @CMD_BLOCK+6,READ_CMD OR ECC_MODE 9320 00002C26 C645FE22 <1> mov byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 9321 00002C2A E9E0000000 <1> JMP COMMANDI 9322 <1> 9323 <1> ;---------------------------------------- 9324 <1> ; WRITE LONG (AH = 0BH) : 9325 <1> ;---------------------------------------- 9326 <1> 9327 <1> WR_LONG: 9328 <1> ;MOV @CMD_BLOCK+6,WRITE_CMD OR ECC_MODE 9329 00002C2F C645FE32 <1> MOV byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE 9330 00002C33 E92C010000 <1> JMP COMMANDO 9331 <1> 9332 <1> ;---------------------------------------- 9333 <1> ; SEEK (AH = 0CH) : 9334 <1> ;---------------------------------------- 9335 <1> 9336 <1> DISK_SEEK: 9337 00002C38 C645FE70 <1> MOV byte [CMD_BLOCK+6],SEEK_CMD 9338 00002C3C E89A010000 <1> CALL COMMAND 9339 00002C41 751C <1> JNZ short DS_EXIT ; CONTROLLER BUSY ERROR 9340 00002C43 E80C020000 <1> CALL _WAIT 9341 00002C48 7515 <1> JNZ DS_EXIT ; TIME OUT ON SEEK 9342 00002C4A E899020000 <1> CALL CHECK_STATUS 9343 00002C4F 803D[FF700000]40 <1> CMP byte [DISK_STATUS1],BAD_SEEK 9344 00002C56 7507 <1> JNE short DS_EXIT 9345 00002C58 C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 9346 <1> DS_EXIT: 9347 00002C5F C3 <1> RETn 9348 <1> 9349 <1> ;---------------------------------------- 9350 <1> ; TEST DISK READY (AH = 10H) : 9351 <1> ;---------------------------------------- 9352 <1> 9353 <1> TST_RDY: ; WAIT FOR CONTROLLER 9354 00002C60 E82B020000 <1> CALL NOT_BUSY 9355 00002C65 751C <1> JNZ short TR_EX 9356 00002C67 8A45FD <1> MOV AL,[CMD_BLOCK+5] ; SELECT DRIVE 9357 00002C6A 668B15[146B0000] <1> MOV DX,[HF_PORT] 9358 00002C71 80C206 <1> add dl,6 9359 00002C74 EE <1> OUT DX,AL 9360 00002C75 E886020000 <1> CALL CHECK_ST ; CHECK STATUS ONLY 9361 00002C7A 7507 <1> JNZ short TR_EX 9362 00002C7C C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 ; WIPE OUT DATA CORRECTED ERROR 9363 <1> TR_EX: 9364 00002C83 C3 <1> RETn 9365 <1> 9366 <1> ;---------------------------------------- 9367 <1> ; RECALIBRATE (AH = 11H) : 9368 <1> ;---------------------------------------- 9369 <1> 9370 <1> HDISK_RECAL: 9371 00002C84 C645FE10 <1> MOV byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16 9372 00002C88 E84E010000 <1> CALL COMMAND ; START THE OPERATION 9373 00002C8D 7523 <1> JNZ short RECAL_EXIT ; ERROR 9374 00002C8F E8C0010000 <1> CALL _WAIT ; WAIT FOR COMPLETION 9375 00002C94 7407 <1> JZ short RECAL_X ; TIME OUT ONE OK ? 9376 00002C96 E8B9010000 <1> CALL _WAIT ; WAIT FOR COMPLETION LONGER 9377 00002C9B 7515 <1> JNZ short RECAL_EXIT ; TIME OUT TWO TIMES IS ERROR 9378 <1> RECAL_X: 9379 00002C9D E846020000 <1> CALL CHECK_STATUS 9380 00002CA2 803D[FF700000]40 <1> CMP byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE 9381 00002CA9 7507 <1> JNE short RECAL_EXIT ; IS OK 9382 00002CAB C605[FF700000]00 <1> MOV byte [DISK_STATUS1],0 9383 <1> RECAL_EXIT: 9384 00002CB2 803D[FF700000]00 <1> CMP byte [DISK_STATUS1],0 9385 00002CB9 C3 <1> RETn 9386 <1> 9387 <1> ;---------------------------------------- 9388 <1> ; CONTROLLER DIAGNOSTIC (AH = 14H) : 9389 <1> ;---------------------------------------- 9390 <1> 9391 <1> CTLR_DIAGNOSTIC: 9392 00002CBA FA <1> CLI ; DISABLE INTERRUPTS WHILE CHANGING MASK 9393 00002CBB E4A1 <1> IN AL,INTB01 ; TURN ON SECOND INTERRUPT CHIP 9394 <1> ;AND AL,0BFH 9395 00002CBD 243F <1> and al, 3Fh ; enable IRQ 14 & IRQ 15 9396 <1> ;JMP $+2 9397 <1> IODELAY 9398 00002CBF EB00 <2> jmp short $+2 9399 00002CC1 EB00 <2> jmp short $+2 9400 00002CC3 E6A1 <1> OUT INTB01,AL 9401 <1> IODELAY 9402 00002CC5 EB00 <2> jmp short $+2 9403 00002CC7 EB00 <2> jmp short $+2 9404 00002CC9 E421 <1> IN AL,INTA01 ; LET INTERRUPTS PASS THRU TO 9405 00002CCB 24FB <1> AND AL,0FBH ; SECOND CHIP 9406 <1> ;JMP $+2 9407 <1> IODELAY 9408 00002CCD EB00 <2> jmp short $+2 9409 00002CCF EB00 <2> jmp short $+2 9410 00002CD1 E621 <1> OUT INTA01,AL 9411 00002CD3 FB <1> STI 9412 00002CD4 E8B7010000 <1> CALL NOT_BUSY ; WAIT FOR CARD 9413 00002CD9 752B <1> JNZ short CD_ERR ; BAD CARD 9414 <1> ;MOV DX, HF_PORT+7 9415 00002CDB 668B15[146B0000] <1> mov dx, [HF_PORT] 9416 00002CE2 80C207 <1> add dl, 7 9417 00002CE5 B090 <1> MOV AL,DIAG_CMD ; START DIAGNOSE 9418 00002CE7 EE <1> OUT DX,AL 9419 00002CE8 E8A3010000 <1> CALL NOT_BUSY ; WAIT FOR IT TO COMPLETE 9420 00002CED B480 <1> MOV AH,TIME_OUT 9421 00002CEF 7517 <1> JNZ short CD_EXIT ; TIME OUT ON DIAGNOSTIC 9422 <1> ;MOV DX,HF_PORT+1 ; GET ERROR REGISTER 9423 00002CF1 668B15[146B0000] <1> mov dx, [HF_PORT] 9424 00002CF8 FEC2 <1> inc dl 9425 00002CFA EC <1> IN AL,DX 9426 00002CFB A2[F6700000] <1> MOV [HF_ERROR],AL ; SAVE IT 9427 00002D00 B400 <1> MOV AH,0 9428 00002D02 3C01 <1> CMP AL,1 ; CHECK FOR ALL OK 9429 00002D04 7402 <1> JE SHORT CD_EXIT 9430 00002D06 B420 <1> CD_ERR: MOV AH,BAD_CNTLR 9431 <1> CD_EXIT: 9432 00002D08 8825[FF700000] <1> MOV [DISK_STATUS1],AH 9433 00002D0E C3 <1> RETn 9434 <1> 9435 <1> ;---------------------------------------- 9436 <1> ; COMMANDI : 9437 <1> ; REPEATEDLY INPUTS DATA TILL : 9438 <1> ; NSECTOR RETURNS ZERO : 9439 <1> ;---------------------------------------- 9440 <1> COMMANDI: 9441 00002D0F E85A020000 <1> CALL CHECK_DMA ; CHECK 64K BOUNDARY ERROR 9442 00002D14 724D <1> JC short CMD_ABORT 9443 <1> ;MOV DI,BX 9444 00002D16 89DF <1> mov edi, ebx ; 21/02/2015 9445 00002D18 E8BE000000 <1> CALL COMMAND ; OUTPUT COMMAND 9446 00002D1D 7544 <1> JNZ short CMD_ABORT 9447 <1> CMD_I1: 9448 00002D1F E830010000 <1> CALL _WAIT ; WAIT FOR DATA REQUEST INTERRUPT 9449 00002D24 753D <1> JNZ short TM_OUT ; TIME OUT 9450 <1> ;MOV CX,256 ; SECTOR SIZE IN WORDS 9451 00002D26 B900010000 <1> mov ecx, 256 ; 21/02/2015 9452 <1> ;MOV DX,HF_PORT 9453 00002D2B 668B15[146B0000] <1> mov dx,[HF_PORT] 9454 00002D32 FA <1> CLI 9455 00002D33 FC <1> CLD 9456 00002D34 F3666D <1> REP INSW ; GET THE SECTOR 9457 00002D37 FB <1> STI 9458 00002D38 F645FE02 <1> TEST byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT 9459 00002D3C 7419 <1> JZ CMD_I3 9460 00002D3E E87A010000 <1> CALL WAIT_DRQ ; WAIT FOR DATA REQUEST 9461 00002D43 721E <1> JC short TM_OUT 9462 <1> ;MOV DX,HF_PORT 9463 00002D45 668B15[146B0000] <1> mov dx,[HF_PORT] 9464 <1> ;MOV CX,4 ; GET ECC BYTES 9465 00002D4C B904000000 <1> mov ecx, 4 ; mov cx, 4 9466 00002D51 EC <1> CMD_I2: IN AL,DX 9467 <1> ;MOV [ES:DI],AL ; GO SLOW FOR BOARD 9468 00002D52 8807 <1> mov [edi], al ; 21/02/2015 9469 00002D54 47 <1> INC eDI 9470 00002D55 E2FA <1> LOOP CMD_I2 9471 00002D57 E88C010000 <1> CMD_I3: CALL CHECK_STATUS 9472 00002D5C 7505 <1> JNZ short CMD_ABORT ; ERROR RETURNED 9473 00002D5E FE4DF9 <1> DEC byte [CMD_BLOCK+1] ; CHECK FOR MORE 9474 00002D61 75BC <1> JNZ SHORT CMD_I1 9475 <1> CMD_ABORT: 9476 00002D63 C3 <1> TM_OUT: RETn 9477 <1> 9478 <1> ;---------------------------------------- 9479 <1> ; COMMANDO : 9480 <1> ; REPEATEDLY OUTPUTS DATA TILL : 9481 <1> ; NSECTOR RETURNS ZERO : 9482 <1> ;---------------------------------------- 9483 <1> COMMANDO: 9484 00002D64 E805020000 <1> CALL CHECK_DMA ; CHECK 64K BOUNDARY ERROR 9485 00002D69 72F8 <1> JC short CMD_ABORT 9486 00002D6B 89DE <1> CMD_OF: MOV eSI,eBX ; 21/02/2015 9487 00002D6D E869000000 <1> CALL COMMAND ; OUTPUT COMMAND 9488 00002D72 75EF <1> JNZ short CMD_ABORT 9489 00002D74 E844010000 <1> CALL WAIT_DRQ ; WAIT FOR DATA REQUEST 9490 00002D79 72E8 <1> JC short TM_OUT ; TOO LONG 9491 <1> CMD_O1: ;PUSH DS 9492 <1> ;PUSH ES ; MOVE ES TO DS 9493 <1> ;POP DS 9494 <1> ;MOV CX,256 ; PUT THE DATA OUT TO THE CARD 9495 <1> ;MOV DX,HF_PORT 9496 <1> ; 01/02/2015 9497 00002D7B 668B15[146B0000] <1> mov dx, [HF_PORT] 9498 <1> ;push es 9499 <1> ;pop ds 9500 <1> ;mov cx, 256 9501 00002D82 B900010000 <1> mov ecx, 256 ; 21/02/2015 9502 00002D87 FA <1> CLI 9503 00002D88 FC <1> CLD 9504 00002D89 F3666F <1> REP OUTSW 9505 00002D8C FB <1> STI 9506 <1> ;POP DS ; RESTORE DS 9507 00002D8D F645FE02 <1> TEST byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT 9508 00002D91 7419 <1> JZ short CMD_O3 9509 00002D93 E825010000 <1> CALL WAIT_DRQ ; WAIT FOR DATA REQUEST 9510 00002D98 72C9 <1> JC short TM_OUT 9511 <1> ;MOV DX,HF_PORT 9512 00002D9A 668B15[146B0000] <1> mov dx, [HF_PORT] 9513 <1> ;MOV CX,4 ; OUTPUT THE ECC BYTES 9514 00002DA1 B904000000 <1> mov ecx, 4 ; mov cx, 4 9515 <1> CMD_O2: ;MOV AL,[ES:SI] 9516 00002DA6 8A06 <1> mov al, [esi] 9517 00002DA8 EE <1> OUT DX,AL 9518 00002DA9 46 <1> INC eSI 9519 00002DAA E2FA <1> LOOP CMD_O2 9520 <1> CMD_O3: 9521 00002DAC E8A3000000 <1> CALL _WAIT ; WAIT FOR SECTOR COMPLETE INTERRUPT 9522 00002DB1 75B0 <1> JNZ short TM_OUT ; ERROR RETURNED 9523 00002DB3 E830010000 <1> CALL CHECK_STATUS 9524 00002DB8 75A9 <1> JNZ short CMD_ABORT 9525 00002DBA F605[F5700000]08 <1> TEST byte [HF_STATUS],ST_DRQ ; CHECK FOR MORE 9526 00002DC1 75B8 <1> JNZ SHORT CMD_O1 9527 <1> ;MOV DX,HF_PORT+2 ; CHECK RESIDUAL SECTOR COUNT 9528 00002DC3 668B15[146B0000] <1> mov dx, [HF_PORT] 9529 <1> ;add dl, 2 9530 00002DCA FEC2 <1> inc dl 9531 00002DCC FEC2 <1> inc dl 9532 00002DCE EC <1> IN AL,DX ; 9533 00002DCF A8FF <1> TEST AL,0FFH ; 9534 00002DD1 7407 <1> JZ short CMD_O4 ; COUNT = 0 OK 9535 00002DD3 C605[FF700000]BB <1> MOV byte [DISK_STATUS1],UNDEF_ERR 9536 <1> ; OPERATION ABORTED - PARTIAL TRANSFER 9537 <1> CMD_O4: 9538 00002DDA C3 <1> RETn 9539 <1> 9540 <1> ;-------------------------------------------------------- 9541 <1> ; COMMAND : 9542 <1> ; THIS ROUTINE OUTPUTS THE COMMAND BLOCK : 9543 <1> ; OUTPUT : 9544 <1> ; BL = STATUS : 9545 <1> ; BH = ERROR REGISTER : 9546 <1> ;-------------------------------------------------------- 9547 <1> 9548 <1> COMMAND: 9549 00002DDB 53 <1> PUSH eBX ; WAIT FOR SEEK COMPLETE AND READY 9550 <1> ;;MOV CX,DELAY_2 ; SET INITIAL DELAY BEFORE TEST 9551 <1> COMMAND1: 9552 <1> ;;PUSH CX ; SAVE LOOP COUNT 9553 00002DDC E87FFEFFFF <1> CALL TST_RDY ; CHECK DRIVE READY 9554 <1> ;;POP CX 9555 00002DE1 7419 <1> JZ short COMMAND2 ; DRIVE IS READY 9556 00002DE3 803D[FF700000]80 <1> CMP byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP 9557 <1> ;JZ short CMD_TIMEOUT 9558 <1> ;;LOOP COMMAND1 ; KEEP TRYING FOR A WHILE 9559 <1> ;JMP SHORT COMMAND4 ; ITS NOT GOING TO GET READY 9560 00002DEA 7507 <1> jne short COMMAND4 9561 <1> CMD_TIMEOUT: 9562 00002DEC C605[FF700000]20 <1> MOV byte [DISK_STATUS1],BAD_CNTLR 9563 <1> COMMAND4: 9564 00002DF3 5B <1> POP eBX 9565 00002DF4 803D[FF700000]00 <1> CMP byte [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 9566 00002DFB C3 <1> RETn 9567 <1> COMMAND2: 9568 00002DFC 5B <1> POP eBX 9569 00002DFD 57 <1> PUSH eDI 9570 00002DFE C605[F7700000]00 <1> MOV byte [HF_INT_FLAG],0 ; RESET INTERRUPT FLAG 9571 00002E05 FA <1> CLI ; INHIBIT INTERRUPTS WHILE CHANGING MASK 9572 00002E06 E4A1 <1> IN AL,INTB01 ; TURN ON SECOND INTERRUPT CHIP 9573 <1> ;AND AL,0BFH 9574 00002E08 243F <1> and al, 3Fh ; Enable IRQ 14 & 15 9575 <1> ;JMP $+2 9576 <1> IODELAY 9577 00002E0A EB00 <2> jmp short $+2 9578 00002E0C EB00 <2> jmp short $+2 9579 00002E0E E6A1 <1> OUT INTB01,AL 9580 00002E10 E421 <1> IN AL,INTA01 ; LET INTERRUPTS PASS THRU TO 9581 00002E12 24FB <1> AND AL,0FBH ; SECOND CHIP 9582 <1> ;JMP $+2 9583 <1> IODELAY 9584 00002E14 EB00 <2> jmp short $+2 9585 00002E16 EB00 <2> jmp short $+2 9586 00002E18 E621 <1> OUT INTA01,AL 9587 00002E1A FB <1> STI 9588 00002E1B 31FF <1> XOR eDI,eDI ; INDEX THE COMMAND TABLE 9589 <1> ;MOV DX,HF_PORT+1 ; DISK ADDRESS 9590 00002E1D 668B15[146B0000] <1> mov dx, [HF_PORT] 9591 00002E24 FEC2 <1> inc dl 9592 00002E26 F605[01710000]C0 <1> TEST byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION 9593 00002E2D 7411 <1> JZ short COMMAND3 9594 00002E2F 8A45FE <1> MOV AL, [CMD_BLOCK+6] ; YES-GET OPERATION CODE 9595 00002E32 24F0 <1> AND AL,0F0H ; GET RID OF MODIFIERS 9596 00002E34 3C20 <1> CMP AL,20H ; 20H-40H IS READ, WRITE, VERIFY 9597 00002E36 7208 <1> JB short COMMAND3 9598 00002E38 3C40 <1> CMP AL,40H 9599 00002E3A 7704 <1> JA short COMMAND3 9600 00002E3C 804DFE01 <1> OR byte [CMD_BLOCK+6],NO_RETRIES 9601 <1> ; VALID OPERATION FOR RETRY SUPPRESS 9602 <1> COMMAND3: 9603 00002E40 8A443DF8 <1> MOV AL,[CMD_BLOCK+eDI] ; GET THE COMMAND STRING BYTE 9604 00002E44 EE <1> OUT DX,AL ; GIVE IT TO CONTROLLER 9605 <1> IODELAY 9606 00002E45 EB00 <2> jmp short $+2 9607 00002E47 EB00 <2> jmp short $+2 9608 00002E49 47 <1> INC eDI ; NEXT BYTE IN COMMAND BLOCK 9609 00002E4A 6642 <1> INC DX ; NEXT DISK ADAPTER REGISTER 9610 00002E4C 6683FF07 <1> cmp di, 7 ; 1/1/2015 ; ALL DONE? 9611 00002E50 75EE <1> JNZ short COMMAND3 ; NO--GO DO NEXT ONE 9612 00002E52 5F <1> POP eDI 9613 00002E53 C3 <1> RETn ; ZERO FLAG IS SET 9614 <1> 9615 <1> ;CMD_TIMEOUT: 9616 <1> ; MOV byte [DISK_STATUS1],BAD_CNTLR 9617 <1> ;COMMAND4: 9618 <1> ; POP BX 9619 <1> ; CMP [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 9620 <1> ; RETn 9621 <1> 9622 <1> ;---------------------------------------- 9623 <1> ; WAIT FOR INTERRUPT : 9624 <1> ;---------------------------------------- 9625 <1> ;WAIT: 9626 <1> _WAIT: 9627 00002E54 FB <1> STI ; MAKE SURE INTERRUPTS ARE ON 9628 <1> ;SUB CX,CX ; SET INITIAL DELAY BEFORE TEST 9629 <1> ;CLC 9630 <1> ;MOV AX,9000H ; DEVICE WAIT INTERRUPT 9631 <1> ;INT 15H 9632 <1> ;JC WT2 ; DEVICE TIMED OUT 9633 <1> ;MOV BL,DELAY_1 ; SET DELAY COUNT 9634 <1> 9635 <1> ;mov bl, WAIT_HDU_INT_HI 9636 <1> ;; 21/02/2015 9637 <1> ;;mov bl, WAIT_HDU_INT_HI + 1 9638 <1> ;;mov cx, WAIT_HDU_INT_LO 9639 00002E55 B915160500 <1> mov ecx, WAIT_HDU_INT_LH 9640 <1> ; (AWARD BIOS -> WAIT_FOR_MEM) 9641 <1> ;----- WAIT LOOP 9642 <1> 9643 <1> WT1: 9644 <1> ;TEST byte [HF_INT_FLAG],80H ; TEST FOR INTERRUPT 9645 00002E5A F605[F7700000]C0 <1> test byte [HF_INT_FLAG],0C0h 9646 <1> ;LOOPZ WT1 9647 00002E61 7517 <1> JNZ short WT3 ; INTERRUPT--LETS GO 9648 <1> ;DEC BL 9649 <1> ;JNZ short WT1 ; KEEP TRYING FOR A WHILE 9650 <1> 9651 <1> WT1_hi: 9652 00002E63 E461 <1> in al, SYS1 ; 61h (PORT_B) ; wait for lo to hi 9653 00002E65 A810 <1> test al, 10h ; transition on memory 9654 00002E67 75FA <1> jnz short WT1_hi ; refresh. 9655 <1> WT1_lo: 9656 00002E69 E461 <1> in al, SYS1 ; 061h (PORT_B) 9657 00002E6B A810 <1> test al, 10h 9658 00002E6D 74FA <1> jz short WT1_lo 9659 00002E6F E2E9 <1> loop WT1 9660 <1> ;;or bl, bl 9661 <1> ;;jz short WT2 9662 <1> ;;dec bl 9663 <1> ;;jmp short WT1 9664 <1> ;dec bl 9665 <1> ;jnz short WT1 9666 <1> 9667 00002E71 C605[FF700000]80 <1> WT2: MOV byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR 9668 00002E78 EB0E <1> JMP SHORT WT4 9669 00002E7A C605[FF700000]00 <1> WT3: MOV byte [DISK_STATUS1],0 9670 00002E81 C605[F7700000]00 <1> MOV byte [HF_INT_FLAG],0 9671 00002E88 803D[FF700000]00 <1> WT4: CMP byte [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 9672 00002E8F C3 <1> RETn 9673 <1> 9674 <1> ;---------------------------------------- 9675 <1> ; WAIT FOR CONTROLLER NOT BUSY : 9676 <1> ;---------------------------------------- 9677 <1> NOT_BUSY: 9678 00002E90 FB <1> STI ; MAKE SURE INTERRUPTS ARE ON 9679 <1> ;PUSH eBX 9680 <1> ;SUB CX,CX ; SET INITIAL DELAY BEFORE TEST 9681 00002E91 668B15[146B0000] <1> mov DX, [HF_PORT] 9682 00002E98 80C207 <1> add dl, 7 ; Status port (HF_PORT+7) 9683 <1> ;MOV BL,DELAY_1 9684 <1> ; wait for 10 seconds 9685 <1> ;mov cx, WAIT_HDU_INT_LO ; 1615h 9686 <1> ;;mov bl, WAIT_HDU_INT_HI ; 05h 9687 <1> ;mov bl, WAIT_HDU_INT_HI + 1 9688 00002E9B B915160500 <1> mov ecx, WAIT_HDU_INT_LH ; 21/02/2015 9689 <1> ; 9690 <1> ;; mov byte [wait_count], 0 ; Reset wait counter 9691 <1> NB1: 9692 00002EA0 EC <1> IN AL,DX ; CHECK STATUS 9693 <1> ;TEST AL,ST_BUSY 9694 00002EA1 2480 <1> and al, ST_BUSY 9695 <1> ;LOOPNZ NB1 9696 00002EA3 7410 <1> JZ short NB2 ; NOT BUSY--LETS GO 9697 <1> ;DEC BL 9698 <1> ;JNZ short NB1 ; KEEP TRYING FOR A WHILE 9699 <1> 9700 00002EA5 E461 <1> NB1_hi: IN AL,SYS1 ; wait for hi to lo 9701 00002EA7 A810 <1> TEST AL,010H ; transition on memory 9702 00002EA9 75FA <1> JNZ SHORT NB1_hi ; refresh. 9703 00002EAB E461 <1> NB1_lo: IN AL,SYS1 9704 00002EAD A810 <1> TEST AL,010H 9705 00002EAF 74FA <1> JZ short NB1_lo 9706 00002EB1 E2ED <1> LOOP NB1 9707 <1> ;dec bl 9708 <1> ;jnz short NB1 9709 <1> ; 9710 <1> ;; cmp byte [wait_count], 182 ; 10 seconds (182 timer ticks) 9711 <1> ;; jb short NB1 9712 <1> ; 9713 <1> ;MOV [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR 9714 <1> ;JMP SHORT NB3 9715 00002EB3 B080 <1> mov al, TIME_OUT 9716 <1> NB2: 9717 <1> ;MOV byte [DISK_STATUS1],0 9718 <1> ;NB3: 9719 <1> ;POP eBX 9720 00002EB5 A2[FF700000] <1> mov [DISK_STATUS1], al ;;; will be set after return 9721 <1> ;CMP byte [DISK_STATUS1],0 ; SET CONDITION CODE FOR CALLER 9722 00002EBA 08C0 <1> or al, al ; (zf = 0 --> timeout) 9723 00002EBC C3 <1> RETn 9724 <1> 9725 <1> ;---------------------------------------- 9726 <1> ; WAIT FOR DATA REQUEST : 9727 <1> ;---------------------------------------- 9728 <1> WAIT_DRQ: 9729 <1> ;MOV CX,DELAY_3 9730 <1> ;MOV DX,HF_PORT+7 9731 00002EBD 668B15[146B0000] <1> mov dx, [HF_PORT] 9732 00002EC4 80C207 <1> add dl, 7 9733 <1> ;;MOV bl, WAIT_HDU_DRQ_HI ; 0 9734 <1> ;MOV cx, WAIT_HDU_DRQ_LO ; 1000 (30 milli seconds) 9735 <1> ; (but it is written as 2000 9736 <1> ; micro seconds in ATORGS.ASM file 9737 <1> ; of Award Bios - 1999, D1A0622) 9738 00002EC7 B9E8030000 <1> mov ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 9739 00002ECC EC <1> WQ_1: IN AL,DX ; GET STATUS 9740 00002ECD A808 <1> TEST AL,ST_DRQ ; WAIT FOR DRQ 9741 00002ECF 7516 <1> JNZ short WQ_OK 9742 <1> ;LOOP WQ_1 ; KEEP TRYING FOR A SHORT WHILE 9743 <1> WQ_hi: 9744 00002ED1 E461 <1> IN AL,SYS1 ; wait for hi to lo 9745 00002ED3 A810 <1> TEST AL,010H ; transition on memory 9746 00002ED5 75FA <1> JNZ SHORT WQ_hi ; refresh. 9747 00002ED7 E461 <1> WQ_lo: IN AL,SYS1 9748 00002ED9 A810 <1> TEST AL,010H 9749 00002EDB 74FA <1> JZ SHORT WQ_lo 9750 00002EDD E2ED <1> LOOP WQ_1 9751 <1> 9752 00002EDF C605[FF700000]80 <1> MOV byte [DISK_STATUS1],TIME_OUT ; ERROR 9753 00002EE6 F9 <1> STC 9754 <1> WQ_OK: 9755 00002EE7 C3 <1> RETn 9756 <1> ;WQ_OK: ;CLC 9757 <1> ; RETn 9758 <1> 9759 <1> ;---------------------------------------- 9760 <1> ; CHECK FIXED DISK STATUS : 9761 <1> ;---------------------------------------- 9762 <1> CHECK_STATUS: 9763 00002EE8 E813000000 <1> CALL CHECK_ST ; CHECK THE STATUS BYTE 9764 00002EED 7509 <1> JNZ short CHECK_S1 ; AN ERROR WAS FOUND 9765 00002EEF A801 <1> TEST AL,ST_ERROR ; WERE THERE ANY OTHER ERRORS 9766 00002EF1 7405 <1> JZ short CHECK_S1 ; NO ERROR REPORTED 9767 00002EF3 E847000000 <1> CALL CHECK_ER ; ERROR REPORTED 9768 <1> CHECK_S1: 9769 00002EF8 803D[FF700000]00 <1> CMP byte [DISK_STATUS1],0 ; SET STATUS FOR CALLER 9770 00002EFF C3 <1> RETn 9771 <1> 9772 <1> ;---------------------------------------- 9773 <1> ; CHECK FIXED DISK STATUS BYTE : 9774 <1> ;---------------------------------------- 9775 <1> CHECK_ST: 9776 <1> ;MOV DX,HF_PORT+7 ; GET THE STATUS 9777 00002F00 668B15[146B0000] <1> mov dx, [HF_PORT] 9778 00002F07 80C207 <1> add dl, 7 9779 00002F0A EC <1> IN AL,DX 9780 00002F0B A2[F5700000] <1> MOV [HF_STATUS],AL 9781 00002F10 B400 <1> MOV AH,0 9782 00002F12 A880 <1> TEST AL,ST_BUSY ; IF STILL BUSY 9783 00002F14 751A <1> JNZ short CKST_EXIT ; REPORT OK 9784 00002F16 B4CC <1> MOV AH,WRITE_FAULT 9785 00002F18 A820 <1> TEST AL,ST_WRT_FLT ; CHECK FOR WRITE FAULT 9786 00002F1A 7514 <1> JNZ short CKST_EXIT 9787 00002F1C B4AA <1> MOV AH,NOT_RDY 9788 00002F1E A840 <1> TEST AL,ST_READY ; CHECK FOR NOT READY 9789 00002F20 740E <1> JZ short CKST_EXIT 9790 00002F22 B440 <1> MOV AH,BAD_SEEK 9791 00002F24 A810 <1> TEST AL,ST_SEEK_COMPL ; CHECK FOR SEEK NOT COMPLETE 9792 00002F26 7408 <1> JZ short CKST_EXIT 9793 00002F28 B411 <1> MOV AH,DATA_CORRECTED 9794 00002F2A A804 <1> TEST AL,ST_CORRCTD ; CHECK FOR CORRECTED ECC 9795 00002F2C 7502 <1> JNZ short CKST_EXIT 9796 00002F2E B400 <1> MOV AH,0 9797 <1> CKST_EXIT: 9798 00002F30 8825[FF700000] <1> MOV [DISK_STATUS1],AH ; SET ERROR FLAG 9799 00002F36 80FC11 <1> CMP AH,DATA_CORRECTED ; KEEP GOING WITH DATA CORRECTED 9800 00002F39 7403 <1> JZ short CKST_EX1 9801 00002F3B 80FC00 <1> CMP AH,0 9802 <1> CKST_EX1: 9803 00002F3E C3 <1> RETn 9804 <1> 9805 <1> ;---------------------------------------- 9806 <1> ; CHECK FIXED DISK ERROR REGISTER : 9807 <1> ;---------------------------------------- 9808 <1> CHECK_ER: 9809 <1> ;MOV DX, HF_PORT+1 ; GET THE ERROR REGISTER 9810 00002F3F 668B15[146B0000] <1> mov dx, [HF_PORT] ; 9811 00002F46 FEC2 <1> inc dl 9812 00002F48 EC <1> IN AL,DX 9813 00002F49 A2[F6700000] <1> MOV [HF_ERROR],AL 9814 00002F4E 53 <1> PUSH eBX ; 21/02/2015 9815 00002F4F B908000000 <1> MOV eCX,8 ; TEST ALL 8 BITS 9816 00002F54 D0E0 <1> CK1: SHL AL,1 ; MOVE NEXT ERROR BIT TO CARRY 9817 00002F56 7202 <1> JC short CK2 ; FOUND THE ERROR 9818 00002F58 E2FA <1> LOOP CK1 ; KEEP TRYING 9819 00002F5A BB[086B0000] <1> CK2: MOV eBX, ERR_TBL ; COMPUTE ADDRESS OF 9820 00002F5F 01CB <1> ADD eBX,eCX ; ERROR CODE 9821 <1> ;;MOV AH,BYTE [CS:BX] ; GET ERROR CODE 9822 <1> ;mov ah, [bx] 9823 00002F61 8A23 <1> mov ah, [ebx] ; 21/02/2015 9824 00002F63 8825[FF700000] <1> CKEX: MOV [DISK_STATUS1],AH ; SAVE ERROR CODE 9825 00002F69 5B <1> POP eBX 9826 00002F6A 80FC00 <1> CMP AH,0 9827 00002F6D C3 <1> RETn 9828 <1> 9829 <1> ;-------------------------------------------------------- 9830 <1> ; CHECK_DMA : 9831 <1> ; -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL : 9832 <1> ; FIT WITHOUT SEGMENT OVERFLOW. : 9833 <1> ; -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X : 9834 <1> ; -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE) : 9835 <1> ; -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H) : 9836 <1> ; -ERROR OTHERWISE : 9837 <1> ;-------------------------------------------------------- 9838 <1> CHECK_DMA: 9839 00002F6E 6650 <1> PUSH AX ; SAVE REGISTERS 9840 00002F70 66B80080 <1> MOV AX,8000H ; AH = MAX # SECTORS AL = MAX OFFSET 9841 00002F74 F645FE02 <1> TEST byte [CMD_BLOCK+6],ECC_MODE 9842 00002F78 7404 <1> JZ short CKD1 9843 00002F7A 66B8047F <1> MOV AX,7F04H ; ECC IS 4 MORE BYTES 9844 00002F7E 3A65F9 <1> CKD1: CMP AH, [CMD_BLOCK+1] ; NUMBER OF SECTORS 9845 00002F81 7706 <1> JA short CKDOK ; IT WILL FIT 9846 00002F83 7208 <1> JB short CKDERR ; TOO MANY 9847 00002F85 38D8 <1> CMP AL,BL ; CHECK OFFSET ON MAX SECTORS 9848 00002F87 7204 <1> JB short CKDERR ; ERROR 9849 00002F89 F8 <1> CKDOK: CLC ; CLEAR CARRY 9850 00002F8A 6658 <1> POP AX 9851 00002F8C C3 <1> RETn ; NORMAL RETURN 9852 00002F8D F9 <1> CKDERR: STC ; INDICATE ERROR 9853 00002F8E C605[FF700000]09 <1> MOV byte [DISK_STATUS1],DMA_BOUNDARY 9854 00002F95 6658 <1> POP AX 9855 00002F97 C3 <1> RETn 9856 <1> 9857 <1> ;---------------------------------------- 9858 <1> ; SET UP ES:BX-> DISK PARMS : 9859 <1> ;---------------------------------------- 9860 <1> 9861 <1> ; INPUT -> DL = 0 based drive number 9862 <1> ; OUTPUT -> ES:BX = disk parameter table address 9863 <1> 9864 <1> GET_VEC: 9865 <1> ;SUB AX,AX ; GET DISK PARAMETER ADDRESS 9866 <1> ;MOV ES,AX 9867 <1> ;TEST DL,1 9868 <1> ;JZ short GV_0 9869 <1> ; LES BX,[HF1_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 9870 <1> ; JMP SHORT GV_EXIT 9871 <1> ;GV_0: 9872 <1> ; LES BX,[HF_TBL_VEC] ; ES:BX -> DRIVE PARAMETERS 9873 <1> ; 9874 <1> ;xor bh, bh 9875 00002F98 31DB <1> xor ebx, ebx 9876 00002F9A 88D3 <1> mov bl, dl 9877 <1> ;;02/01/2015 9878 <1> ;;shl bl, 1 ; port address offset 9879 <1> ;;mov ax, [bx+hd_ports] ; Base port address (1F0h, 170h) 9880 <1> ;;shl bl, 1 ; dpt pointer offset 9881 00002F9C C0E302 <1> shl bl, 2 ;; 9882 <1> ;add bx, HF_TBL_VEC ; Disk parameter table pointer 9883 00002F9F 81C3[04710000] <1> add ebx, HF_TBL_VEC ; 21/02/2015 9884 <1> ;push word [bx+2] ; dpt segment 9885 <1> ;pop es 9886 <1> ;mov bx, [bx] ; dpt offset 9887 00002FA5 8B1B <1> mov ebx, [ebx] 9888 <1> ;GV_EXIT: 9889 00002FA7 C3 <1> RETn 9890 <1> 9891 <1> hdc1_int: ; 21/02/2015 9892 <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL 14 ) ---------------------- 9893 <1> ; : 9894 <1> ; FIXED DISK INTERRUPT ROUTINE : 9895 <1> ; : 9896 <1> ;---------------------------------------------------------------- 9897 <1> 9898 <1> ; 22/12/2014 9899 <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT) 9900 <1> ; '11/15/85' 9901 <1> ; AWARD BIOS 1999 (D1A0622) 9902 <1> ; Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1) 9903 <1> 9904 <1> ;int_76h: 9905 <1> HD_INT: 9906 00002FA8 6650 <1> PUSH AX 9907 00002FAA 1E <1> PUSH DS 9908 <1> ;CALL DDS 9909 <1> ; 21/02/2015 (32 bit, 386 pm modification) 9910 00002FAB 66B81000 <1> mov ax, KDATA 9911 00002FAF 8ED8 <1> mov ds, ax 9912 <1> ; 9913 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 9914 <1> ;mov byte [CS:HF_INT_FLAG], 0FFh 9915 00002FB1 C605[F7700000]FF <1> mov byte [HF_INT_FLAG], 0FFh 9916 <1> ; 9917 00002FB8 6652 <1> push dx 9918 00002FBA 66BAF701 <1> mov dx, HDC1_BASEPORT+7 ; Status Register (1F7h) 9919 <1> ; Clear Controller 9920 <1> Clear_IRQ1415: ; (Award BIOS - 1999) 9921 00002FBE EC <1> in al, dx ; 9922 00002FBF 665A <1> pop dx 9923 <1> NEWIODELAY 9924 00002FC1 E6EB <2> out 0ebh,al 9925 <1> ; 9926 00002FC3 B020 <1> MOV AL,EOI ; NON-SPECIFIC END OF INTERRUPT 9927 00002FC5 E6A0 <1> OUT INTB00,AL ; FOR CONTROLLER #2 9928 <1> ;JMP $+2 ; WAIT 9929 <1> NEWIODELAY 9930 00002FC7 E6EB <2> out 0ebh,al 9931 00002FC9 E620 <1> OUT INTA00,AL ; FOR CONTROLLER #1 9932 00002FCB 1F <1> POP DS 9933 <1> ;STI ; RE-ENABLE INTERRUPTS 9934 <1> ;MOV AX,9100H ; DEVICE POST 9935 <1> ;INT 15H ; INTERRUPT 9936 <1> irq15_iret: ; 25/02/2015 9937 00002FCC 6658 <1> POP AX 9938 00002FCE CF <1> IRETd ; RETURN FROM INTERRUPT 9939 <1> 9940 <1> hdc2_int: ; 21/02/2015 9941 <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL 15 ) +++++++++++++++++++++ 9942 <1> ; : 9943 <1> ; FIXED DISK INTERRUPT ROUTINE : 9944 <1> ; : 9945 <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9946 <1> 9947 <1> ;int_77h: 9948 <1> HD1_INT: 9949 00002FCF 6650 <1> PUSH AX 9950 <1> ; Check if that is a spurious IRQ (from slave PIC) 9951 <1> ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 9952 00002FD1 B00B <1> mov al, 0Bh ; In-Service Register 9953 00002FD3 E6A0 <1> out 0A0h, al 9954 00002FD5 EB00 <1> jmp short $+2 9955 00002FD7 EB00 <1> jmp short $+2 9956 00002FD9 E4A0 <1> in al, 0A0h 9957 00002FDB 2480 <1> and al, 80h ; bit 7 (is it real IRQ 15 or fake?) 9958 00002FDD 74ED <1> jz short irq15_iret ; Fake (spurious)IRQ, do not send EOI) 9959 <1> ; 9960 00002FDF 1E <1> PUSH DS 9961 <1> ;CALL DDS 9962 <1> ; 21/02/2015 (32 bit, 386 pm modification) 9963 00002FE0 66B81000 <1> mov ax, KDATA 9964 00002FE4 8ED8 <1> mov ds, ax 9965 <1> ; 9966 <1> ;;MOV @HF_INT_FLAG,0FFH ; ALL DONE 9967 <1> ;or byte [CS:HF_INT_FLAG],0C0h 9968 00002FE6 800D[F7700000]C0 <1> or byte [HF_INT_FLAG], 0C0h 9969 <1> ; 9970 00002FED 6652 <1> push dx 9971 00002FEF 66BA7701 <1> mov dx, HDC2_BASEPORT+7 ; Status Register (177h) 9972 <1> ; Clear Controller (Award BIOS 1999) 9973 00002FF3 EBC9 <1> jmp short Clear_IRQ1415 9974 <1> 9975 <1> 9976 <1> ;%include 'diskdata.inc' ; 11/03/2015 9977 <1> ;%include 'diskbss.inc' ; 11/03/2015 9978 <1> 9979 <1> 9980 <1> ;//////////////////////////////////////////////////////////////////// 9981 <1> ;; END OF DISK I/O SYTEM /// 9982 %include 'memory.inc' ; 09/03/2015 9983 <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) 9984 <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC 9985 <1> ; Last Modification: 18/10/2015 (!not completed!) 9986 <1> ; 9987 <1> ; Source code for NASM - Netwide Assembler (2.11) 9988 <1> 9989 <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) /////////////// 9990 <1> 9991 <1> ;;04/11/2014 (unix386.s) 9992 <1> ;PDE_A_PRESENT equ 1 ; Present flag for PDE 9993 <1> ;PDE_A_WRITE equ 2 ; Writable (write permission) flag 9994 <1> ;PDE_A_USER equ 4 ; User (non-system/kernel) page flag 9995 <1> ;; 9996 <1> ;PTE_A_PRESENT equ 1 ; Present flag for PTE (bit 0) 9997 <1> ;PTE_A_WRITE equ 2 ; Writable (write permission) flag (bit 1) 9998 <1> ;PTE_A_USER equ 4 ; User (non-system/kernel) page flag (bit 2) 9999 <1> ;PTE_A_ACCESS equ 32 ; Accessed flag (bit 5) ; 09/03/2015 10000 <1> 10001 <1> ; 27/04/2015 10002 <1> ; 09/03/2015 10003 <1> PAGE_SIZE equ 4096 ; page size in bytes 10004 <1> PAGE_SHIFT equ 12 ; page table shift count 10005 <1> PAGE_D_SHIFT equ 22 ; 12 + 10 ; page directory shift count 10006 <1> PAGE_OFF equ 0FFFh ; 12 bit byte offset in page frame 10007 <1> PTE_MASK equ 03FFh ; page table entry mask 10008 <1> PTE_DUPLICATED equ 200h ; duplicated page sign (AVL bit 0) 10009 <1> PDE_A_CLEAR equ 0F000h ; to clear PDE attribute bits 10010 <1> PTE_A_CLEAR equ 0F000h ; to clear PTE attribute bits 10011 <1> LOGIC_SECT_SIZE equ 512 ; logical sector size 10012 <1> ERR_MAJOR_PF equ 0E0h ; major error: page fault 10013 <1> ERR_MINOR_IM equ 1 ; insufficient (out of) memory 10014 <1> ERR_MINOR_DSK equ 2 ; disk read/write error 10015 <1> ERR_MINOR_PV equ 3 ; protection violation 10016 <1> SWP_DISK_READ_ERR equ 4 10017 <1> SWP_DISK_NOT_PRESENT_ERR equ 5 10018 <1> SWP_SECTOR_NOT_PRESENT_ERR equ 6 10019 <1> SWP_NO_FREE_SPACE_ERR equ 7 10020 <1> SWP_DISK_WRITE_ERR equ 8 10021 <1> SWP_NO_PAGE_TO_SWAP_ERR equ 9 10022 <1> PTE_A_ACCESS_BIT equ 5 ; Bit 5 (accessed flag) 10023 <1> SECTOR_SHIFT equ 3 ; sector shift (to convert page block number) 10024 <1> 10025 <1> ; 10026 <1> ;; Retro Unix 386 v1 - paging method/principles 10027 <1> ;; 10028 <1> ;; 10/10/2014 10029 <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES 10030 <1> ;; 10031 <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map 10032 <1> ;; (virtual address = physical address) 10033 <1> ;; KERNEL PAGE TABLES: 10034 <1> ;; Kernel page directory and all page tables are 10035 <1> ;; on memory as initialized, as equal to physical memory 10036 <1> ;; layout. Kernel pages can/must not be swapped out/in. 10037 <1> ;; 10038 <1> ;; what for: User pages may be swapped out, when accessing 10039 <1> ;; a page in kernel/system mode, if it would be swapped out, 10040 <1> ;; kernel would have to swap it in! But it is also may be 10041 <1> ;; in use by a user process. (In system/kernel mode 10042 <1> ;; kernel can access all memory pages even if they are 10043 <1> ;; reserved/allocated for user processes. Swap out/in would 10044 <1> ;; cause conflicts.) 10045 <1> ;; 10046 <1> ;; As result of these conditions, 10047 <1> ;; all kernel pages must be initialized as equal to 10048 <1> ;; physical layout for preventing page faults. 10049 <1> ;; Also, calling "allocate page" procedure after 10050 <1> ;; a page fault can cause another page fault (double fault) 10051 <1> ;; if all kernel page tables would not be initialized. 10052 <1> ;; 10053 <1> ;; [first_page] = Beginning of users space, as offset to 10054 <1> ;; memory allocation table. (double word aligned) 10055 <1> ;; 10056 <1> ;; [next_page] = first/next free space to be searched 10057 <1> ;; as offset to memory allocation table. (dw aligned) 10058 <1> ;; 10059 <1> ;; [last_page] = End of memory (users space), as offset 10060 <1> ;; to memory allocation table. (double word aligned) 10061 <1> ;; 10062 <1> ;; USER PAGE TABLES: 10063 <1> ;; Demand paging (& 'copy on write' allocation method) ... 10064 <1> ;; 'ready only' marked copies of the 10065 <1> ;; parent process's page table entries (for 10066 <1> ;; same physical memory). 10067 <1> ;; (A page will be copied to a new page after 10068 <1> ;; if it causes R/W page fault.) 10069 <1> ;; 10070 <1> ;; Every user process has own (different) 10071 <1> ;; page directory and page tables. 10072 <1> ;; 10073 <1> ;; Code starts at virtual address 0, always. 10074 <1> ;; (Initial value of EIP is 0 in user mode.) 10075 <1> ;; (Programs can be written/developed as simple 10076 <1> ;; flat memory programs.) 10077 <1> ;; 10078 <1> ;; MEMORY ALLOCATION STRATEGY: 10079 <1> ;; Memory page will be allocated by kernel only 10080 <1> ;; (in kernel/system mode only). 10081 <1> ;; * After a 10082 <1> ;; - 'not present' page fault 10083 <1> ;; - 'writing attempt on read only page' page fault 10084 <1> ;; * For loading (opening, reading) a file or disk/drive 10085 <1> ;; * As responce to 'allocate additional memory blocks' 10086 <1> ;; request by running process. 10087 <1> ;; * While creating a process, allocating a new buffer, 10088 <1> ;; new page tables etc. 10089 <1> ;; 10090 <1> ;; At first, 10091 <1> ;; - 'allocate page' procedure will be called; 10092 <1> ;, if it will return with a valid (>0) physical address 10093 <1> ;; (that means the relevant M.A.T. bit has been RESET) 10094 <1> ;; relevant memory page/block will be cleared (zeroed). 10095 <1> ;; - 'allocate page' will be called for allocating page 10096 <1> ;; directory, page table and running space (data/code). 10097 <1> ;; - every successful 'allocate page' call will decrease 10098 <1> ;; 'free_pages' count (pointer). 10099 <1> ;; - 'out of (insufficient) memory error' will be returned 10100 <1> ;; if 'free_pages' points to a ZERO. 10101 <1> ;; - swapping out and swapping in (if it is not a new page) 10102 <1> ;; procedures will be called as responce to 'out of memory' 10103 <1> ;; error except errors caused by attribute conflicts. 10104 <1> ;; (swapper functions) 10105 <1> ;; 10106 <1> ;; At second, 10107 <1> ;; - page directory entry will be updated then page table 10108 <1> ;; entry will be updated. 10109 <1> ;; 10110 <1> ;; MEMORY ALLOCATION TABLE FORMAT: 10111 <1> ;; - M.A.T. has a size according to available memory as 10112 <1> ;; follows: 10113 <1> ;; - 1 (allocation) bit per 1 page (4096 bytes) 10114 <1> ;; - a bit with value of 0 means allocated page 10115 <1> ;; - a bit with value of 1 means a free page 10116 <1> ;, - 'free_pages' pointer holds count of free pages 10117 <1> ;; depending on M.A.T. 10118 <1> ;; (NOTE: Free page count will not be checked 10119 <1> ;; again -on M.A.T.- after initialization. 10120 <1> ;; Kernel will trust on initial count.) 10121 <1> ;, - 'free_pages' count will be decreased by allocation 10122 <1> ;; and it will be increased by deallocation procedures. 10123 <1> ;; 10124 <1> ;; - Available memory will be calculated during 10125 <1> ;; the kernel's initialization stage (in real mode). 10126 <1> ;; Memory allocation table and kernel page tables 10127 <1> ;; will be formatted/sized as result of available 10128 <1> ;; memory calculation before paging is enabled. 10129 <1> ;; 10130 <1> ;; For 4GB Available/Present Memory: (max. possible memory size) 10131 <1> ;; - Memory Allocation Table size will be 128 KB. 10132 <1> ;; - Memory allocation for kernel page directory size 10133 <1> ;; is always 4 KB. (in addition to total allocation size 10134 <1> ;; for page tables) 10135 <1> ;; - Memory allocation for kernel page tables (1024 tables) 10136 <1> ;; is 4 MB (1024*4*1024 bytes). 10137 <1> ;; - User (available) space will be started 10138 <1> ;; at 6th MB of the memory (after 1MB+4MB). 10139 <1> ;; - The first 640 KB is for kernel's itself plus 10140 <1> ;; memory allocation table and kernel's page directory 10141 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 10142 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 10143 <1> ;; for buffers. 10144 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 10145 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 10146 <1> ;; - Kernel page tables start at 100000h (2nd MB) 10147 <1> ;; 10148 <1> ;; For 1GB Available Memory: 10149 <1> ;; - Memory Allocation Table size will be 32 KB. 10150 <1> ;; - Memory allocation for kernel page directory size 10151 <1> ;; is always 4 KB. (in addition to total allocation size 10152 <1> ;; for page tables) 10153 <1> ;; - Memory allocation for kernel page tables (256 tables) 10154 <1> ;; is 1 MB (256*4*1024 bytes). 10155 <1> ;; - User (available) space will be started 10156 <1> ;; at 3th MB of the memory (after 1MB+1MB). 10157 <1> ;; - The first 640 KB is for kernel's itself plus 10158 <1> ;; memory allocation table and kernel's page directory 10159 <1> ;; (D0000h-EFFFFh may be used as kernel space...) 10160 <1> ;; - B0000h to B7FFFh address space (32 KB) will be used 10161 <1> ;; for buffers. 10162 <1> ;; - ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved. 10163 <1> ;, (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh) 10164 <1> ;; - Kernel page tables start at 100000h (2nd MB). 10165 <1> ;; 10166 <1> ;; 10167 <1> 10168 <1> 10169 <1> ;;************************************************************************************ 10170 <1> ;; 10171 <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle) 10172 <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015) 10173 <1> 10174 <1> ;; Main factor: "sys fork" system call 10175 <1> ;; 10176 <1> ;; FORK 10177 <1> ;; |----> parent - duplicated PTEs, read only pages 10178 <1> ;; writable pages ---->| 10179 <1> ;; |----> child - duplicated PTEs, read only pages 10180 <1> ;; 10181 <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 10182 <1> ;; 10183 <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set) 10184 <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9) 10185 <1> ;; -while R/W bit is 0-. 10186 <1> ;; 10187 <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process): 10188 <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 10189 <1> ;; as duplicated PTE bit -AVL bit 0, PTE bit 9- are reset/clear. 10190 <1> ;; # Then Parent's Page Table is copied to Child's Page Table. 10191 <1> ;; # Child's Page Table Entries are updated as duplicated child bit 10192 <1> ;; -AVL bit 0, PTE bit 9- is set. 10193 <1> ;; 10194 <1> ;; Duplicate page tables with read only pages (several sys fork system calls): 10195 <1> ;; # Parent's read only pages are copied to new child pages. 10196 <1> ;; Parent's PTE attributes are not changed. 10197 <1> ;; (Because, there is another parent-child fork before this fork! We must not 10198 <1> ;; destroy/mix previous fork result). 10199 <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 10200 <1> ;; read only pages) are set as writable (while duplicated PTE bit is clear). 10201 <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 10202 <1> ;; as read only, (while) duplicated PTE bit is reset (clear). 10203 <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 10204 <1> ;; as Child's Page Table Entries without copying actual page. 10205 <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 10206 <1> ;; pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set. 10207 <1> ;; 10208 <1> ;; !? WHAT FOR (duplication after duplication): 10209 <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init) 10210 <1> ;; program/executable code continues from specified location as child process, 10211 <1> ;; returns back previous code location as parent process, every child after 10212 <1> ;; every sys fork uses last image of code and data just prior the fork. 10213 <1> ;; Even if the parent code changes data, the child will not see the changed data 10214 <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB) 10215 <1> ;; was copied to child's process segment (all of code and data) according to 10216 <1> ;; original UNIX v1 which copies all of parent process code and data -core- 10217 <1> ;; to child space -core- but swaps that core image -of child- on to disk. 10218 <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core 10219 <1> ;; (complete running image of parent process) to the child process; 10220 <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 10221 <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork, 10222 <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes 10223 <1> ;; a new/fresh core -running space-, by clearing all code/data content). 10224 <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write 10225 <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 10226 <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and 10227 <1> ;; new/fresh pages will be used to load and run new executable/program. 10228 <1> ;; That is what for i have preferred "copy on write", "duplication" method 10229 <1> ;; for sharing same read only pages between parent and child processes. 10230 <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 10231 <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 10232 <1> ;; and it's child processes; otherwise parent process would destroy data belongs 10233 <1> ;; to its child or vice versa; or some pages would remain unclaimed 10234 <1> ;; -deallocation problem-. 10235 <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 10236 <1> ;; 10237 <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 10238 <1> ;; # Page fault handler will do those: 10239 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 10240 <1> ;; - If it is reset/clear, there is a child uses same page. 10241 <1> ;; - Parent's read only page -previous page- is copied to a new writable page. 10242 <1> ;; - Parent's PTE is updated as writable page, as unique page (AVL=0) 10243 <1> ;; - (Page fault handler whill check this PTE later, if child process causes to 10244 <1> ;; page fault due to write attempt on read only page. Of course, the previous 10245 <1> ;; read only page will be converted to writable and unique page which belongs 10246 <1> ;; to child process.) 10247 <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE: 10248 <1> ;; # Page fault handler will do those: 10249 <1> ;; - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE). 10250 <1> ;; - If it is set, there is a parent uses -or was using- same page. 10251 <1> ;; - Same PTE address within parent's page table is checked if it has same page 10252 <1> ;; address or not. 10253 <1> ;; - If parent's PTE has same address, child will continue with a new writable page. 10254 <1> ;; Parent's PTE will point to same (previous) page as writable, unique (AVL=0). 10255 <1> ;; - If parent's PTE has different address, child will continue with it's 10256 <1> ;; own/same page but read only flag (0) will be changed to writable flag (1) and 10257 <1> ;; 'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 10258 <1> ;; 10259 <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables 10260 <1> ;; will be set as writable (and unique) in case of child process was using 10261 <1> ;; same pages with duplicated child PTE sign... Depending on sys fork and 10262 <1> ;; duplication method details, it is not possible multiple child processes 10263 <1> ;; were using same page with duplicated PTEs. 10264 <1> ;; 10265 <1> ;;************************************************************************************ 10266 <1> 10267 <1> ;; 08/10/2014 10268 <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft 10269 <1> ;; by Erdogan Tan (Based on KolibriOS 'memory.inc') 10270 <1> 10271 <1> ;; 'allocate_page' code is derived and modified from KolibriOS 10272 <1> ;; 'alloc_page' procedure in 'memory.inc' 10273 <1> ;; (25/08/2014, Revision: 5057) file 10274 <1> ;; by KolibriOS Team (2004-2012) 10275 <1> 10276 <1> allocate_page: 10277 <1> ; 01/07/2015 10278 <1> ; 05/05/2015 10279 <1> ; 30/04/2015 10280 <1> ; 16/10/2014 10281 <1> ; 08/10/2014 10282 <1> ; 09/09/2014 (Retro UNIX 386 v1 - beginning) 10283 <1> ; 10284 <1> ; INPUT -> none 10285 <1> ; 10286 <1> ; OUTPUT -> 10287 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 10288 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is RESET) 10289 <1> ; 10290 <1> ; CF = 1 and EAX = 0 10291 <1> ; if there is not a free page to be allocated 10292 <1> ; 10293 <1> ; Modified Registers -> none (except EAX) 10294 <1> ; 10295 00002FF5 A1[70700000] <1> mov eax, [free_pages] 10296 00002FFA 21C0 <1> and eax, eax 10297 00002FFC 7438 <1> jz short out_of_memory 10298 <1> ; 10299 00002FFE 53 <1> push ebx 10300 00002FFF 51 <1> push ecx 10301 <1> ; 10302 00003000 BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table offset 10303 00003005 89D9 <1> mov ecx, ebx 10304 <1> ; NOTE: 32 (first_page) is initial 10305 <1> ; value of [next_page]. 10306 <1> ; It points to the first available 10307 <1> ; page block for users (ring 3) ... 10308 <1> ; (MAT offset 32 = 1024/32) 10309 <1> ; (at the of the first 4 MB) 10310 00003007 031D[74700000] <1> add ebx, [next_page] ; Free page searching starts from here 10311 <1> ; next_free_page >> 5 10312 0000300D 030D[78700000] <1> add ecx, [last_page] ; Free page searching ends here 10313 <1> ; (total_pages - 1) >> 5 10314 <1> al_p_scan: 10315 00003013 39CB <1> cmp ebx, ecx 10316 00003015 770A <1> ja short al_p_notfound 10317 <1> ; 10318 <1> ; 01/07/2015 10319 <1> ; AMD64 Architecture Programmer’s Manual 10320 <1> ; Volume 3: 10321 <1> ; General-Purpose and System Instructions 10322 <1> ; 10323 <1> ; BSF - Bit Scan Forward 10324 <1> ; 10325 <1> ; Searches the value in a register or a memory location 10326 <1> ; (second operand) for the least-significant set bit. 10327 <1> ; If a set bit is found, the instruction clears the zero flag (ZF) 10328 <1> ; and stores the index of the least-significant set bit in a destination 10329 <1> ; register (first operand). If the second operand contains 0, 10330 <1> ; the instruction sets ZF to 1 and does not change the contents of the 10331 <1> ; destination register. The bit index is an unsigned offset from bit 0 10332 <1> ; of the searched value 10333 <1> ; 10334 00003017 0FBC03 <1> bsf eax, [ebx] ; Scans source operand for first bit set (1). 10335 <1> ; Clear ZF if a bit is found set (1) and 10336 <1> ; loads the destination with an index to 10337 <1> ; first set bit. (0 -> 31) 10338 <1> ; Sets ZF to 1 if no bits are found set. 10339 0000301A 7525 <1> jnz short al_p_found ; ZF = 0 -> a free page has been found 10340 <1> ; 10341 <1> ; NOTE: a Memory Allocation Table bit 10342 <1> ; with value of 1 means 10343 <1> ; the corresponding page is free 10344 <1> ; (Retro UNIX 386 v1 feaure only!) 10345 0000301C 83C304 <1> add ebx, 4 10346 <1> ; We return back for searching next page block 10347 <1> ; NOTE: [free_pages] is not ZERO; so, 10348 <1> ; we always will find at least 1 free page here. 10349 0000301F EBF2 <1> jmp short al_p_scan 10350 <1> ; 10351 <1> al_p_notfound: 10352 00003021 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 10353 00003027 890D[74700000] <1> mov [next_page], ecx ; next/first free page = last page 10354 <1> ; (deallocate_page procedure will change it) 10355 0000302D 31C0 <1> xor eax, eax 10356 0000302F A3[70700000] <1> mov [free_pages], eax ; 0 10357 00003034 59 <1> pop ecx 10358 00003035 5B <1> pop ebx 10359 <1> ; 10360 <1> out_of_memory: 10361 00003036 E857040000 <1> call swap_out 10362 0000303B 7325 <1> jnc short al_p_ok ; [free_pages] = 0, re-allocation by swap_out 10363 <1> ; 10364 0000303D 29C0 <1> sub eax, eax ; 0 10365 0000303F F9 <1> stc 10366 00003040 C3 <1> retn 10367 <1> 10368 <1> al_p_found: 10369 00003041 89D9 <1> mov ecx, ebx 10370 00003043 81E900001000 <1> sub ecx, MEM_ALLOC_TBL 10371 00003049 890D[74700000] <1> mov [next_page], ecx ; Set first free page searching start 10372 <1> ; address/offset (to the next) 10373 0000304F FF0D[70700000] <1> dec dword [free_pages] ; 1 page has been allocated (X = X-1) 10374 <1> ; 10375 00003055 0FB303 <1> btr [ebx], eax ; The destination bit indexed by the source value 10376 <1> ; is copied into the Carry Flag and then cleared 10377 <1> ; in the destination. 10378 <1> ; 10379 <1> ; Reset the bit which is corresponding to the 10380 <1> ; (just) allocated page. 10381 <1> ; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages) 10382 00003058 C1E103 <1> shl ecx, 3 ; (page block offset * 32) + page index 10383 0000305B 01C8 <1> add eax, ecx ; = page number 10384 0000305D C1E00C <1> shl eax, 12 ; physical address of the page (flat/real value) 10385 <1> ; EAX = physical address of memory page 10386 <1> ; 10387 <1> ; NOTE: The relevant page directory and page table entry will be updated 10388 <1> ; according to this EAX value... 10389 00003060 59 <1> pop ecx 10390 00003061 5B <1> pop ebx 10391 <1> al_p_ok: 10392 00003062 C3 <1> retn 10393 <1> 10394 <1> 10395 <1> make_page_dir: 10396 <1> ; 18/04/2015 10397 <1> ; 12/04/2015 10398 <1> ; 23/10/2014 10399 <1> ; 16/10/2014 10400 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 10401 <1> ; 10402 <1> ; INPUT -> 10403 <1> ; none 10404 <1> ; OUTPUT -> 10405 <1> ; (EAX = 0) 10406 <1> ; cf = 1 -> insufficient (out of) memory error 10407 <1> ; cf = 0 -> 10408 <1> ; u.pgdir = page directory (physical) address of the current 10409 <1> ; process/user. 10410 <1> ; 10411 <1> ; Modified Registers -> EAX 10412 <1> ; 10413 00003063 E88DFFFFFF <1> call allocate_page 10414 00003068 7216 <1> jc short mkpd_error 10415 <1> ; 10416 0000306A A3[A1740000] <1> mov [u.pgdir], eax ; Page dir address for current user/process 10417 <1> ; (Physical address) 10418 <1> clear_page: 10419 <1> ; 18/04/2015 10420 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 10421 <1> ; 10422 <1> ; INPUT -> 10423 <1> ; EAX = physical address of the page 10424 <1> ; OUTPUT -> 10425 <1> ; all bytes of the page will be cleared 10426 <1> ; 10427 <1> ; Modified Registers -> none 10428 <1> ; 10429 0000306F 57 <1> push edi 10430 00003070 51 <1> push ecx 10431 00003071 50 <1> push eax 10432 00003072 B900040000 <1> mov ecx, PAGE_SIZE / 4 10433 00003077 89C7 <1> mov edi, eax 10434 00003079 31C0 <1> xor eax, eax 10435 0000307B F3AB <1> rep stosd 10436 0000307D 58 <1> pop eax 10437 0000307E 59 <1> pop ecx 10438 0000307F 5F <1> pop edi 10439 <1> mkpd_error: 10440 <1> mkpt_error: 10441 00003080 C3 <1> retn 10442 <1> 10443 <1> make_page_table: 10444 <1> ; 23/06/2015 10445 <1> ; 18/04/2015 10446 <1> ; 12/04/2015 10447 <1> ; 16/10/2014 10448 <1> ; 09/10/2014 ; (Retro UNIX 386 v1 - beginning) 10449 <1> ; 10450 <1> ; INPUT -> 10451 <1> ; EBX = virtual (linear) address 10452 <1> ; ECX = page table attributes (lower 12 bits) 10453 <1> ; (higher 20 bits must be ZERO) 10454 <1> ; (bit 0 must be 1) 10455 <1> ; u.pgdir = page directory (physical) address 10456 <1> ; OUTPUT -> 10457 <1> ; EDX = Page directory entry address 10458 <1> ; EAX = Page table address 10459 <1> ; cf = 1 -> insufficient (out of) memory error 10460 <1> ; cf = 0 -> page table address in the PDE (EDX) 10461 <1> ; 10462 <1> ; Modified Registers -> EAX, EDX 10463 <1> ; 10464 00003081 E86FFFFFFF <1> call allocate_page 10465 00003086 72F8 <1> jc short mkpt_error 10466 00003088 E811000000 <1> call set_pde 10467 0000308D EBE0 <1> jmp short clear_page 10468 <1> 10469 <1> make_page: 10470 <1> ; 24/07/2015 10471 <1> ; 23/06/2015 ; (Retro UNIX 386 v1 - beginning) 10472 <1> ; 10473 <1> ; INPUT -> 10474 <1> ; EBX = virtual (linear) address 10475 <1> ; ECX = page attributes (lower 12 bits) 10476 <1> ; (higher 20 bits must be ZERO) 10477 <1> ; (bit 0 must be 1) 10478 <1> ; u.pgdir = page directory (physical) address 10479 <1> ; OUTPUT -> 10480 <1> ; EBX = Virtual address 10481 <1> ; (EDX = PTE value) 10482 <1> ; EAX = Physical address 10483 <1> ; cf = 1 -> insufficient (out of) memory error 10484 <1> ; 10485 <1> ; Modified Registers -> EAX, EDX 10486 <1> ; 10487 0000308F E861FFFFFF <1> call allocate_page 10488 00003094 7207 <1> jc short mkp_err 10489 00003096 E821000000 <1> call set_pte 10490 0000309B 73D2 <1> jnc short clear_page ; 18/04/2015 10491 <1> mkp_err: 10492 0000309D C3 <1> retn 10493 <1> 10494 <1> 10495 <1> set_pde: ; Set page directory entry (PDE) 10496 <1> ; 20/07/2015 10497 <1> ; 18/04/2015 10498 <1> ; 12/04/2015 10499 <1> ; 23/10/2014 10500 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10501 <1> ; 10502 <1> ; INPUT -> 10503 <1> ; EAX = physical address 10504 <1> ; (use present value if EAX = 0) 10505 <1> ; EBX = virtual (linear) address 10506 <1> ; ECX = page table attributes (lower 12 bits) 10507 <1> ; (higher 20 bits must be ZERO) 10508 <1> ; (bit 0 must be 1) 10509 <1> ; u.pgdir = page directory (physical) address 10510 <1> ; OUTPUT -> 10511 <1> ; EDX = PDE address 10512 <1> ; EAX = page table address (physical) 10513 <1> ; ;(CF=1 -> Invalid page address) 10514 <1> ; 10515 <1> ; Modified Registers -> EDX 10516 <1> ; 10517 0000309E 89DA <1> mov edx, ebx 10518 000030A0 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 10519 000030A3 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 10520 000030A6 0315[A1740000] <1> add edx, [u.pgdir] 10521 <1> ; 10522 000030AC 21C0 <1> and eax, eax 10523 000030AE 7506 <1> jnz short spde_1 10524 <1> ; 10525 000030B0 8B02 <1> mov eax, [edx] ; old PDE value 10526 <1> ;test al, 1 10527 <1> ;jz short spde_2 10528 000030B2 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 10529 <1> spde_1: 10530 <1> ;and cx, 0FFFh 10531 000030B6 8902 <1> mov [edx], eax 10532 000030B8 66090A <1> or [edx], cx 10533 000030BB C3 <1> retn 10534 <1> ;spde_2: ; error 10535 <1> ; stc 10536 <1> ; retn 10537 <1> 10538 <1> set_pte: ; Set page table entry (PTE) 10539 <1> ; 24/07/2015 10540 <1> ; 20/07/2015 10541 <1> ; 23/06/2015 10542 <1> ; 18/04/2015 10543 <1> ; 12/04/2015 10544 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10545 <1> ; 10546 <1> ; INPUT -> 10547 <1> ; EAX = physical page address 10548 <1> ; (use present value if EAX = 0) 10549 <1> ; EBX = virtual (linear) address 10550 <1> ; ECX = page attributes (lower 12 bits) 10551 <1> ; (higher 20 bits must be ZERO) 10552 <1> ; (bit 0 must be 1) 10553 <1> ; u.pgdir = page directory (physical) address 10554 <1> ; OUTPUT -> 10555 <1> ; EAX = physical page address 10556 <1> ; (EDX = PTE value) 10557 <1> ; EBX = virtual address 10558 <1> ; 10559 <1> ; CF = 1 -> error 10560 <1> ; 10561 <1> ; Modified Registers -> EAX, EDX 10562 <1> ; 10563 000030BC 50 <1> push eax 10564 000030BD A1[A1740000] <1> mov eax, [u.pgdir] ; 20/07/2015 10565 000030C2 E837000000 <1> call get_pde 10566 <1> ; EDX = PDE address 10567 <1> ; EAX = PDE value 10568 000030C7 5A <1> pop edx ; physical page address 10569 000030C8 722A <1> jc short spte_err ; PDE not present 10570 <1> ; 10571 000030CA 53 <1> push ebx ; 24/07/2015 10572 000030CB 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 10573 <1> ; EDX = PT address (physical) 10574 000030CF C1EB0C <1> shr ebx, PAGE_SHIFT ; 12 10575 000030D2 81E3FF030000 <1> and ebx, PTE_MASK ; 03FFh 10576 <1> ; clear higher 10 bits (PD bits) 10577 000030D8 C1E302 <1> shl ebx, 2 ; offset to page table (1024*4) 10578 000030DB 01C3 <1> add ebx, eax 10579 <1> ; 10580 000030DD 8B03 <1> mov eax, [ebx] ; Old PTE value 10581 000030DF A801 <1> test al, 1 10582 000030E1 740C <1> jz short spte_0 10583 000030E3 09D2 <1> or edx, edx 10584 000030E5 750F <1> jnz short spte_1 10585 000030E7 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits 10586 000030EB 89C2 <1> mov edx, eax 10587 000030ED EB09 <1> jmp short spte_2 10588 <1> spte_0: 10589 <1> ; If this PTE contains a swap (disk) address, 10590 <1> ; it can be updated by using 'swap_in' procedure 10591 <1> ; only! 10592 000030EF 21C0 <1> and eax, eax 10593 000030F1 7403 <1> jz short spte_1 10594 <1> ; 24/07/2015 10595 <1> ; swapped page ! (on disk) 10596 000030F3 5B <1> pop ebx 10597 <1> spte_err: 10598 000030F4 F9 <1> stc 10599 000030F5 C3 <1> retn 10600 <1> spte_1: 10601 000030F6 89D0 <1> mov eax, edx 10602 <1> spte_2: 10603 000030F8 09CA <1> or edx, ecx 10604 <1> ; 23/06/2015 10605 000030FA 8913 <1> mov [ebx], edx ; PTE value in EDX 10606 <1> ; 24/07/2015 10607 000030FC 5B <1> pop ebx 10608 000030FD C3 <1> retn 10609 <1> 10610 <1> get_pde: ; Get present value of the relevant PDE 10611 <1> ; 20/07/2015 10612 <1> ; 18/04/2015 10613 <1> ; 12/04/2015 10614 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10615 <1> ; 10616 <1> ; INPUT -> 10617 <1> ; EBX = virtual (linear) address 10618 <1> ; EAX = page directory (physical) address 10619 <1> ; OUTPUT -> 10620 <1> ; EDX = Page directory entry address 10621 <1> ; EAX = Page directory entry value 10622 <1> ; CF = 1 -> PDE not present or invalid ? 10623 <1> ; Modified Registers -> EDX, EAX 10624 <1> ; 10625 000030FE 89DA <1> mov edx, ebx 10626 00003100 C1EA16 <1> shr edx, PAGE_D_SHIFT ; 22 (12+10) 10627 00003103 C1E202 <1> shl edx, 2 ; offset to page directory (1024*4) 10628 00003106 01C2 <1> add edx, eax ; page directory address (physical) 10629 00003108 8B02 <1> mov eax, [edx] 10630 0000310A A801 <1> test al, PDE_A_PRESENT ; page table is present or not ! 10631 0000310C 751F <1> jnz short gpte_retn 10632 0000310E F9 <1> stc 10633 <1> gpde_retn: 10634 0000310F C3 <1> retn 10635 <1> 10636 <1> get_pte: 10637 <1> ; Get present value of the relevant PTE 10638 <1> ; 29/07/2015 10639 <1> ; 20/07/2015 10640 <1> ; 18/04/2015 10641 <1> ; 12/04/2015 10642 <1> ; 10/10/2014 ; (Retro UNIX 386 v1 - beginning) 10643 <1> ; 10644 <1> ; INPUT -> 10645 <1> ; EBX = virtual (linear) address 10646 <1> ; EAX = page directory (physical) address 10647 <1> ; OUTPUT -> 10648 <1> ; EDX = Page table entry address (if CF=0) 10649 <1> ; Page directory entry address (if CF=1) 10650 <1> ; (Bit 0 value is 0 if PT is not present) 10651 <1> ; EAX = Page table entry value (page address) 10652 <1> ; CF = 1 -> PDE not present or invalid ? 10653 <1> ; Modified Registers -> EAX, EDX 10654 <1> ; 10655 00003110 E8E9FFFFFF <1> call get_pde 10656 00003115 72F8 <1> jc short gpde_retn ; page table is not present 10657 <1> ;jnc short gpte_1 10658 <1> ;retn 10659 <1> ;gpte_1: 10660 00003117 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits 10661 0000311B 89DA <1> mov edx, ebx 10662 0000311D C1EA0C <1> shr edx, PAGE_SHIFT ; 12 10663 00003120 81E2FF030000 <1> and edx, PTE_MASK ; 03FFh 10664 <1> ; clear higher 10 bits (PD bits) 10665 00003126 C1E202 <1> shl edx, 2 ; offset from start of page table (1024*4) 10666 00003129 01C2 <1> add edx, eax 10667 0000312B 8B02 <1> mov eax, [edx] 10668 <1> gpte_retn: 10669 0000312D C3 <1> retn 10670 <1> 10671 <1> deallocate_page_dir: 10672 <1> ; 15/09/2015 10673 <1> ; 05/08/2015 10674 <1> ; 30/04/2015 10675 <1> ; 28/04/2015 10676 <1> ; 17/10/2014 10677 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 10678 <1> ; 10679 <1> ; INPUT -> 10680 <1> ; EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD) 10681 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 10682 <1> ; OUTPUT -> 10683 <1> ; All of page tables in the page directory 10684 <1> ; and page dir's itself will be deallocated 10685 <1> ; except 'read only' duplicated pages (will be converted 10686 <1> ; to writable pages). 10687 <1> ; 10688 <1> ; Modified Registers -> EAX 10689 <1> ; 10690 <1> ; 10691 0000312E 56 <1> push esi 10692 0000312F 51 <1> push ecx 10693 00003130 50 <1> push eax 10694 00003131 89C6 <1> mov esi, eax 10695 00003133 31C9 <1> xor ecx, ecx 10696 <1> ; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB), 10697 <1> ; it must not be deallocated 10698 00003135 890E <1> mov [esi], ecx ; 0 ; clear PDE 0 10699 <1> dapd_0: 10700 00003137 AD <1> lodsd 10701 00003138 A801 <1> test al, PDE_A_PRESENT ; bit 0, present flag (must be 1) 10702 0000313A 7409 <1> jz short dapd_1 10703 0000313C 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 10704 00003140 E812000000 <1> call deallocate_page_table 10705 <1> dapd_1: 10706 00003145 41 <1> inc ecx ; page directory entry index 10707 00003146 81F900040000 <1> cmp ecx, PAGE_SIZE / 4 ; 1024 10708 0000314C 72E9 <1> jb short dapd_0 10709 <1> dapd_2: 10710 0000314E 58 <1> pop eax 10711 0000314F E879000000 <1> call deallocate_page ; deallocate the page dir's itself 10712 00003154 59 <1> pop ecx 10713 00003155 5E <1> pop esi 10714 00003156 C3 <1> retn 10715 <1> 10716 <1> deallocate_page_table: 10717 <1> ; 19/09/2015 10718 <1> ; 15/09/2015 10719 <1> ; 05/08/2015 10720 <1> ; 30/04/2015 10721 <1> ; 28/04/2015 10722 <1> ; 24/10/2014 10723 <1> ; 23/10/2014 10724 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 10725 <1> ; 10726 <1> ; INPUT -> 10727 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE 10728 <1> ; EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY 10729 <1> ; (ECX = page directory entry index) 10730 <1> ; OUTPUT -> 10731 <1> ; All of pages in the page table and page table's itself 10732 <1> ; will be deallocated except 'read only' duplicated pages 10733 <1> ; (will be converted to writable pages). 10734 <1> ; 10735 <1> ; Modified Registers -> EAX 10736 <1> ; 10737 00003157 56 <1> push esi 10738 00003158 57 <1> push edi 10739 00003159 52 <1> push edx 10740 0000315A 50 <1> push eax ; * 10741 0000315B 89C6 <1> mov esi, eax 10742 0000315D 31FF <1> xor edi, edi ; 0 10743 <1> dapt_0: 10744 0000315F AD <1> lodsd 10745 00003160 A801 <1> test al, PTE_A_PRESENT ; bit 0, present flag (must be 1) 10746 00003162 7441 <1> jz short dapt_1 10747 <1> ; 10748 00003164 A802 <1> test al, PTE_A_WRITE ; bit 1, writable (r/w) flag 10749 <1> ; (must be 1) 10750 00003166 754C <1> jnz short dapt_3 10751 <1> ; Read only -duplicated- page (belongs to a parent or a child) 10752 00003168 66A90002 <1> test ax, PTE_DUPLICATED ; Was this page duplicated 10753 <1> ; as child's page ? 10754 0000316C 744B <1> jz short dapt_4 ; Clear PTE but don't deallocate the page! 10755 <1> ; check the parent's PTE value is read only & same page or not.. 10756 <1> ; ECX = page directory entry index (0-1023) 10757 0000316E 53 <1> push ebx 10758 0000316F 51 <1> push ecx 10759 00003170 66C1E102 <1> shl cx, 2 ; *4 10760 00003174 01CB <1> add ebx, ecx ; PDE offset (for the parent) 10761 00003176 8B0B <1> mov ecx, [ebx] 10762 00003178 F6C101 <1> test cl, PDE_A_PRESENT ; present (valid) or not ? 10763 0000317B 7435 <1> jz short dapt_2 ; parent process does not use this page 10764 0000317D 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 10765 <1> ; EDI = page table entry index (0-1023) 10766 00003182 89FA <1> mov edx, edi 10767 00003184 66C1E202 <1> shl dx, 2 ; *4 10768 00003188 01CA <1> add edx, ecx ; PTE offset (for the parent) 10769 0000318A 8B1A <1> mov ebx, [edx] 10770 0000318C F6C301 <1> test bl, PTE_A_PRESENT ; present or not ? 10771 0000318F 7421 <1> jz short dapt_2 ; parent process does not use this page 10772 00003191 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 10773 00003195 6681E300F0 <1> and bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 10774 0000319A 39D8 <1> cmp eax, ebx ; parent's and child's pages are same ? 10775 0000319C 7514 <1> jne short dapt_2 ; not same page 10776 <1> ; deallocate the child's page 10777 0000319E 800A02 <1> or byte [edx], PTE_A_WRITE ; convert to writable page (parent) 10778 000031A1 59 <1> pop ecx 10779 000031A2 5B <1> pop ebx 10780 000031A3 EB14 <1> jmp short dapt_4 10781 <1> dapt_1: 10782 000031A5 09C0 <1> or eax, eax ; swapped page ? 10783 000031A7 7417 <1> jz short dapt_5 ; no 10784 <1> ; yes 10785 000031A9 D1E8 <1> shr eax, 1 10786 000031AB E848040000 <1> call unlink_swap_block ; Deallocate swapped page block 10787 <1> ; on the swap disk (or in file) 10788 000031B0 EB0E <1> jmp short dapt_5 10789 <1> dapt_2: 10790 000031B2 59 <1> pop ecx 10791 000031B3 5B <1> pop ebx 10792 <1> dapt_3: 10793 <1> ;and ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits 10794 000031B4 E814000000 <1> call deallocate_page 10795 <1> dapt_4: 10796 000031B9 C746FC00000000 <1> mov dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent) 10797 <1> dapt_5: 10798 000031C0 47 <1> inc edi ; page table entry index 10799 000031C1 81FF00040000 <1> cmp edi, PAGE_SIZE / 4 ; 1024 10800 000031C7 7296 <1> jb short dapt_0 10801 <1> ; 10802 000031C9 58 <1> pop eax ; * 10803 000031CA 5A <1> pop edx 10804 000031CB 5F <1> pop edi 10805 000031CC 5E <1> pop esi 10806 <1> ; 10807 <1> ;call deallocate_page ; deallocate the page table's itself 10808 <1> ;retn 10809 <1> 10810 <1> deallocate_page: 10811 <1> ; 15/09/2015 10812 <1> ; 28/04/2015 10813 <1> ; 10/03/2015 10814 <1> ; 17/10/2014 10815 <1> ; 12/10/2014 (Retro UNIX 386 v1 - beginning) 10816 <1> ; 10817 <1> ; INPUT -> 10818 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 10819 <1> ; OUTPUT -> 10820 <1> ; [free_pages] is increased 10821 <1> ; (corresponding MEMORY ALLOCATION TABLE bit is SET) 10822 <1> ; CF = 1 if the page is already deallocated 10823 <1> ; (or not allocated) before. 10824 <1> ; 10825 <1> ; Modified Registers -> EAX 10826 <1> ; 10827 000031CD 53 <1> push ebx 10828 000031CE 52 <1> push edx 10829 <1> ; 10830 000031CF C1E80C <1> shr eax, PAGE_SHIFT ; shift physical address to 10831 <1> ; 12 bits right 10832 <1> ; to get page number 10833 000031D2 89C2 <1> mov edx, eax 10834 <1> ; 15/09/2015 10835 000031D4 C1EA03 <1> shr edx, 3 ; to get offset to M.A.T. 10836 <1> ; (1 allocation bit = 1 page) 10837 <1> ; (1 allocation bytes = 8 pages) 10838 000031D7 80E2FC <1> and dl, 0FCh ; clear lower 2 bits 10839 <1> ; (to get 32 bit position) 10840 <1> ; 10841 000031DA BB00001000 <1> mov ebx, MEM_ALLOC_TBL ; Memory Allocation Table address 10842 000031DF 01D3 <1> add ebx, edx 10843 000031E1 83E01F <1> and eax, 1Fh ; lower 5 bits only 10844 <1> ; (allocation bit position) 10845 000031E4 3B15[74700000] <1> cmp edx, [next_page] ; is the new free page address lower 10846 <1> ; than the address in 'next_page' ? 10847 <1> ; (next/first free page value) 10848 000031EA 7306 <1> jnb short dap_1 ; no 10849 000031EC 8915[74700000] <1> mov [next_page], edx ; yes 10850 <1> dap_1: 10851 000031F2 0FAB03 <1> bts [ebx], eax ; unlink/release/deallocate page 10852 <1> ; set relevant bit to 1. 10853 <1> ; set CF to the previous bit value 10854 <1> ;cmc ; complement carry flag 10855 <1> ;jc short dap_2 ; do not increase free_pages count 10856 <1> ; if the page is already deallocated 10857 <1> ; before. 10858 000031F5 FF05[70700000] <1> inc dword [free_pages] 10859 <1> dap_2: 10860 000031FB 5A <1> pop edx 10861 000031FC 5B <1> pop ebx 10862 000031FD C3 <1> retn 10863 <1> 10864 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10865 <1> ;; ;; 10866 <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; 10867 <1> ;; Distributed under terms of the GNU General Public License ;; 10868 <1> ;; ;; 10869 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 10870 <1> 10871 <1> ;;$Revision: 5057 $ 10872 <1> 10873 <1> 10874 <1> ;;align 4 10875 <1> ;;proc alloc_page 10876 <1> 10877 <1> ;; pushfd 10878 <1> ;; cli 10879 <1> ;; push ebx 10880 <1> ;;;//- 10881 <1> ;; cmp [pg_data.pages_free], 1 10882 <1> ;; jle .out_of_memory 10883 <1> ;;;//- 10884 <1> ;; 10885 <1> ;; mov ebx, [page_start] 10886 <1> ;; mov ecx, [page_end] 10887 <1> ;;.l1: 10888 <1> ;; bsf eax, [ebx]; 10889 <1> ;; jnz .found 10890 <1> ;; add ebx, 4 10891 <1> ;; cmp ebx, ecx 10892 <1> ;; jb .l1 10893 <1> ;; pop ebx 10894 <1> ;; popfd 10895 <1> ;; xor eax, eax 10896 <1> ;; ret 10897 <1> ;;.found: 10898 <1> ;;;//- 10899 <1> ;; dec [pg_data.pages_free] 10900 <1> ;; jz .out_of_memory 10901 <1> ;;;//- 10902 <1> ;; btr [ebx], eax 10903 <1> ;; mov [page_start], ebx 10904 <1> ;; sub ebx, sys_pgmap 10905 <1> ;; lea eax, [eax+ebx*8] 10906 <1> ;; shl eax, 12 10907 <1> ;;;//- dec [pg_data.pages_free] 10908 <1> ;; pop ebx 10909 <1> ;; popfd 10910 <1> ;; ret 10911 <1> ;;;//- 10912 <1> ;;.out_of_memory: 10913 <1> ;; mov [pg_data.pages_free], 1 10914 <1> ;; xor eax, eax 10915 <1> ;; pop ebx 10916 <1> ;; popfd 10917 <1> ;; ret 10918 <1> ;;;//- 10919 <1> ;;endp 10920 <1> 10921 <1> duplicate_page_dir: 10922 <1> ; 21/09/2015 10923 <1> ; 31/08/2015 10924 <1> ; 20/07/2015 10925 <1> ; 28/04/2015 10926 <1> ; 27/04/2015 10927 <1> ; 18/04/2015 10928 <1> ; 12/04/2015 10929 <1> ; 18/10/2014 10930 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 10931 <1> ; 10932 <1> ; INPUT -> 10933 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 10934 <1> ; page directory. 10935 <1> ; OUTPUT -> 10936 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 10937 <1> ; page directory. 10938 <1> ; (New page directory with new page table entries.) 10939 <1> ; (New page tables with read only copies of the parent's 10940 <1> ; pages.) 10941 <1> ; EAX = 0 -> Error (CF = 1) 10942 <1> ; 10943 <1> ; Modified Registers -> none (except EAX) 10944 <1> ; 10945 000031FE E8F2FDFFFF <1> call allocate_page 10946 00003203 723E <1> jc short dpd_err 10947 <1> ; 10948 00003205 55 <1> push ebp ; 20/07/2015 10949 00003206 56 <1> push esi 10950 00003207 57 <1> push edi 10951 00003208 53 <1> push ebx 10952 00003209 51 <1> push ecx 10953 0000320A 8B35[A1740000] <1> mov esi, [u.pgdir] 10954 00003210 89C7 <1> mov edi, eax 10955 00003212 50 <1> push eax ; save child's page directory address 10956 <1> ; 31/08/2015 10957 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 10958 <1> ; (use same system space for all user page tables) 10959 00003213 A5 <1> movsd 10960 00003214 BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 10961 00003219 B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 10962 <1> dpd_0: 10963 0000321E AD <1> lodsd 10964 <1> ;or eax, eax 10965 <1> ;jnz short dpd_1 10966 0000321F A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 10967 00003221 7508 <1> jnz short dpd_1 10968 <1> ; 20/07/2015 (virtual address at the end of the page table) 10969 00003223 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 10970 00003229 EB0F <1> jmp short dpd_2 10971 <1> dpd_1: 10972 0000322B 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 10973 0000322F 89C3 <1> mov ebx, eax 10974 <1> ; EBX = Parent's page table address 10975 00003231 E81F000000 <1> call duplicate_page_table 10976 00003236 720C <1> jc short dpd_p_err 10977 <1> ; EAX = Child's page table address 10978 00003238 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 10979 <1> ; set bit 0, bit 1 and bit 2 to 1 10980 <1> ; (present, writable, user) 10981 <1> dpd_2: 10982 0000323A AB <1> stosd 10983 0000323B E2E1 <1> loop dpd_0 10984 <1> ; 10985 0000323D 58 <1> pop eax ; restore child's page directory address 10986 <1> dpd_3: 10987 0000323E 59 <1> pop ecx 10988 0000323F 5B <1> pop ebx 10989 00003240 5F <1> pop edi 10990 00003241 5E <1> pop esi 10991 00003242 5D <1> pop ebp ; 20/07/2015 10992 <1> dpd_err: 10993 00003243 C3 <1> retn 10994 <1> dpd_p_err: 10995 <1> ; release the allocated pages missing (recover free space) 10996 00003244 58 <1> pop eax ; the new page directory address (physical) 10997 00003245 8B1D[A1740000] <1> mov ebx, [u.pgdir] ; parent's page directory address 10998 0000324B E8DEFEFFFF <1> call deallocate_page_dir 10999 00003250 29C0 <1> sub eax, eax ; 0 11000 00003252 F9 <1> stc 11001 00003253 EBE9 <1> jmp short dpd_3 11002 <1> 11003 <1> duplicate_page_table: 11004 <1> ; 21/09/2015 11005 <1> ; 20/07/2015 11006 <1> ; 05/05/2015 11007 <1> ; 28/04/2015 11008 <1> ; 27/04/2015 11009 <1> ; 18/04/2015 11010 <1> ; 18/10/2014 11011 <1> ; 16/10/2014 (Retro UNIX 386 v1 - beginning) 11012 <1> ; 11013 <1> ; INPUT -> 11014 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 11015 <1> ; EBP = page table entry index (from 'duplicate_page_dir') 11016 <1> ; OUTPUT -> 11017 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 11018 <1> ; (with 'read only' attribute of page table entries) 11019 <1> ; EBP = (recent) page table index (for 'add_to_swap_queue') 11020 <1> ; CF = 1 -> error 11021 <1> ; 11022 <1> ; Modified Registers -> EBP (except EAX) 11023 <1> ; 11024 00003255 E89BFDFFFF <1> call allocate_page 11025 0000325A 726A <1> jc short dpt_err 11026 <1> ; 11027 0000325C 50 <1> push eax ; * 11028 0000325D 56 <1> push esi 11029 0000325E 57 <1> push edi 11030 0000325F 52 <1> push edx 11031 00003260 51 <1> push ecx 11032 <1> ; 11033 00003261 89DE <1> mov esi, ebx 11034 00003263 89C7 <1> mov edi, eax 11035 00003265 89C2 <1> mov edx, eax 11036 00003267 81C200100000 <1> add edx, PAGE_SIZE 11037 <1> dpt_0: 11038 0000326D AD <1> lodsd 11039 0000326E 21C0 <1> and eax, eax 11040 00003270 7444 <1> jz short dpt_3 11041 00003272 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 11042 00003274 7507 <1> jnz short dpt_1 11043 <1> ; 20/07/2015 11044 <1> ; ebp = virtual (linear) address of the memory page 11045 00003276 E887040000 <1> call reload_page ; 28/04/2015 11046 0000327B 7244 <1> jc short dpt_p_err 11047 <1> dpt_1: 11048 <1> ; 21/09/2015 11049 0000327D 89C1 <1> mov ecx, eax 11050 0000327F 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11051 00003283 F6C102 <1> test cl, PTE_A_WRITE ; writable page ? 11052 00003286 7525 <1> jnz short dpt_2 11053 <1> ; Read only (parent) page 11054 <1> ; - there is a third process which uses this page - 11055 <1> ; Allocate a new page for the child process 11056 00003288 E868FDFFFF <1> call allocate_page 11057 0000328D 7232 <1> jc short dpt_p_err 11058 0000328F 57 <1> push edi 11059 00003290 56 <1> push esi 11060 00003291 89CE <1> mov esi, ecx 11061 00003293 89C7 <1> mov edi, eax 11062 00003295 B900040000 <1> mov ecx, PAGE_SIZE/4 11063 0000329A F3A5 <1> rep movsd ; copy page (4096 bytes) 11064 0000329C 5E <1> pop esi 11065 0000329D 5F <1> pop edi 11066 <1> ; 11067 0000329E 53 <1> push ebx 11068 0000329F 50 <1> push eax 11069 <1> ; 20/07/2015 11070 000032A0 89EB <1> mov ebx, ebp 11071 <1> ; ebx = virtual address of the memory page 11072 000032A2 E80B030000 <1> call add_to_swap_queue 11073 000032A7 58 <1> pop eax 11074 000032A8 5B <1> pop ebx 11075 <1> ; 21/09/2015 11076 000032A9 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 11077 <1> ; user + writable + present page 11078 000032AB EB09 <1> jmp short dpt_3 11079 <1> dpt_2: 11080 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 11081 000032AD 0C05 <1> or al, PTE_A_USER+PTE_A_PRESENT 11082 <1> ; (read only page!) 11083 000032AF 8946FC <1> mov [esi-4], eax ; update parent's PTE 11084 000032B2 660D0002 <1> or ax, PTE_DUPLICATED ; (read only page & duplicated PTE!) 11085 <1> dpt_3: 11086 000032B6 AB <1> stosd ; EDI points to child's PTE 11087 <1> ; 11088 000032B7 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 11089 <1> ; 11090 000032BD 39D7 <1> cmp edi, edx 11091 000032BF 72AC <1> jb short dpt_0 11092 <1> dpt_p_err: 11093 000032C1 59 <1> pop ecx 11094 000032C2 5A <1> pop edx 11095 000032C3 5F <1> pop edi 11096 000032C4 5E <1> pop esi 11097 000032C5 58 <1> pop eax ; * 11098 <1> dpt_err: 11099 000032C6 C3 <1> retn 11100 <1> 11101 <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault ! 11102 <1> ; 21/09/2015 11103 <1> ; 19/09/2015 11104 <1> ; 17/09/2015 11105 <1> ; 28/08/2015 11106 <1> ; 20/07/2015 11107 <1> ; 28/06/2015 11108 <1> ; 03/05/2015 11109 <1> ; 30/04/2015 11110 <1> ; 18/04/2015 11111 <1> ; 12/04/2015 11112 <1> ; 30/10/2014 11113 <1> ; 11/09/2014 11114 <1> ; 10/09/2014 (Retro UNIX 386 v1 - beginning) 11115 <1> ; 11116 <1> ; Note: This is not an interrupt/exception handler. 11117 <1> ; This is a 'page fault remedy' subroutine 11118 <1> ; which will be called by standard/uniform 11119 <1> ; exception handler. 11120 <1> ; 11121 <1> ; INPUT -> 11122 <1> ; [error_code] = 32 bit ERROR CODE (lower 5 bits are valid) 11123 <1> ; 11124 <1> ; cr2 = the virtual (linear) address 11125 <1> ; which has caused to page fault (19/09/2015) 11126 <1> ; 11127 <1> ; OUTPUT -> 11128 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 11129 <1> ; EAX = 0 -> no error 11130 <1> ; EAX > 0 -> error code in EAX (also CF = 1) 11131 <1> ; 11132 <1> ; Modified Registers -> none (except EAX) 11133 <1> ; 11134 <1> ; 11135 <1> ; ERROR CODE: 11136 <1> ; 31 ..... 4 3 2 1 0 11137 <1> ; +---+-- --+---+---+---+---+---+---+ 11138 <1> ; | Reserved | I | R | U | W | P | 11139 <1> ; +---+-- --+---+---+---+---+---+---+ 11140 <1> ; 11141 <1> ; P : PRESENT - When set, the page fault was caused by 11142 <1> ; a page-protection violation. When not set, 11143 <1> ; it was caused by a non-present page. 11144 <1> ; W : WRITE - When set, the page fault was caused by 11145 <1> ; a page write. When not set, it was caused 11146 <1> ; by a page read. 11147 <1> ; U : USER - When set, the page fault was caused 11148 <1> ; while CPL = 3. 11149 <1> ; This does not necessarily mean that 11150 <1> ; the page fault was a privilege violation. 11151 <1> ; R : RESERVD - When set, the page fault was caused by 11152 <1> ; WRITE reading a 1 in a reserved field. 11153 <1> ; I : INSTRUC - When set, the page fault was caused by 11154 <1> ; FETCH an instruction fetch 11155 <1> ; 11156 <1> ;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION 11157 <1> ; 31 22 12 11 0 11158 <1> ; +-------------------+-------------------+-----------------------+ 11159 <1> ; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # | OFFSET | 11160 <1> ; +-------------------+-------------------+-----------------------+ 11161 <1> ; 11162 <1> 11163 <1> ;; CR3 REGISTER (Control Register 3) 11164 <1> ; 31 12 5 4 3 2 0 11165 <1> ; +---------------------------------------+-------------+---+-----+ 11166 <1> ; | | |P|P| | 11167 <1> ; | PAGE DIRECTORY TABLE BASE ADDRESS | reserved |C|W|rsvrd| 11168 <1> ; | | |D|T| | 11169 <1> ; +---------------------------------------+-------------+---+-----+ 11170 <1> ; 11171 <1> ; PWT - WRITE THROUGH 11172 <1> ; PCD - CACHE DISABLE 11173 <1> ; 11174 <1> ; 11175 <1> ;; x86 PAGE DIRECTORY ENTRY (4 KByte Page) 11176 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 11177 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11178 <1> ; | | | | | | |P|P|U|R| | 11179 <1> ; | PAGE TABLE BASE ADDRESS 31..12 | AVL |G|0|D|A|C|W|/|/|P| 11180 <1> ; | | | | | | |D|T|S|W| | 11181 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11182 <1> ; 11183 <1> ; P - PRESENT 11184 <1> ; R/W - READ/WRITE 11185 <1> ; U/S - USER/SUPERVISOR 11186 <1> ; PWT - WRITE THROUGH 11187 <1> ; PCD - CACHE DISABLE 11188 <1> ; A - ACCESSED 11189 <1> ; D - DIRTY (IGNORED) 11190 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 11191 <1> ; G - GLOBAL (IGNORED) 11192 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 11193 <1> ; 11194 <1> ; 11195 <1> ;; x86 PAGE TABLE ENTRY (4 KByte Page) 11196 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 11197 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11198 <1> ; | | | |P| | |P|P|U|R| | 11199 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |G|A|D|A|C|W|/|/|P| 11200 <1> ; | | | |T| | |D|T|S|W| | 11201 <1> ; +---------------------------------------+-----+---+-+-+---+-+-+-+ 11202 <1> ; 11203 <1> ; P - PRESENT 11204 <1> ; R/W - READ/WRITE 11205 <1> ; U/S - USER/SUPERVISOR 11206 <1> ; PWT - WRITE THROUGH 11207 <1> ; PCD - CACHE DISABLE 11208 <1> ; A - ACCESSED 11209 <1> ; D - DIRTY 11210 <1> ; PAT - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR) 11211 <1> ; G - GLOBAL 11212 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 11213 <1> ; 11214 <1> ; 11215 <1> ;; 80386 PAGE TABLE ENTRY (4 KByte Page) 11216 <1> ; 31 12 11 9 8 7 6 5 4 3 2 1 0 11217 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 11218 <1> ; | | | | | | | | |U|R| | 11219 <1> ; | PAGE FRAME BASE ADDRESS 31..12 | AVL |0|0|D|A|0|0|/|/|P| 11220 <1> ; | | | | | | | | |S|W| | 11221 <1> ; +---------------------------------------+-----+-+-+-+-+---+-+-+-+ 11222 <1> ; 11223 <1> ; P - PRESENT 11224 <1> ; R/W - READ/WRITE 11225 <1> ; U/S - USER/SUPERVISOR 11226 <1> ; D - DIRTY 11227 <1> ; AVL - AVAILABLE FOR SYSTEMS PROGRAMMER USE 11228 <1> ; 11229 <1> ; NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE. 11230 <1> ; 11231 <1> ; 11232 <1> ;; Invalid Page Table Entry 11233 <1> ; 31 1 0 11234 <1> ; +-------------------------------------------------------------+-+ 11235 <1> ; | | | 11236 <1> ; | AVAILABLE |0| 11237 <1> ; | | | 11238 <1> ; +-------------------------------------------------------------+-+ 11239 <1> ; 11240 <1> 11241 000032C7 53 <1> push ebx 11242 000032C8 52 <1> push edx 11243 000032C9 51 <1> push ecx 11244 <1> ; 11245 <1> ; 21/09/2015 (debugging) 11246 000032CA FF05[B1740000] <1> inc dword [u.pfcount] ; page fault count for running process 11247 000032D0 FF05[30850000] <1> inc dword [PF_Count] ; total page fault count 11248 <1> ; 28/06/2015 11249 <1> ;mov edx, [error_code] ; Lower 5 bits are valid 11250 000032D6 8A15[28850000] <1> mov dl, [error_code] 11251 <1> ; 11252 000032DC F6C201 <1> test dl, 1 ; page fault was caused by a non-present page 11253 <1> ; sign 11254 000032DF 7422 <1> jz short pfh_alloc_np 11255 <1> ; 11256 <1> ; If it is not a 'write on read only page' type page fault 11257 <1> ; major page fault error with minor reason must be returned without 11258 <1> ; fixing the problem. 'sys_exit with error' will be needed 11259 <1> ; after return here! 11260 <1> ; Page fault will be remedied, by copying page contents 11261 <1> ; to newly allocated page with write permission; 11262 <1> ; sys_fork -> sys_exec -> copy on write, demand paging method is 11263 <1> ; used for working with minimum possible memory usage. 11264 <1> ; sys_fork will duplicate page directory and tables of parent 11265 <1> ; process with 'read only' flag. If the child process attempts to 11266 <1> ; write on these read only pages, page fault will be directed here 11267 <1> ; for allocating a new page with same data/content. 11268 <1> ; 11269 <1> ; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS) 11270 <1> ; will not force to separate CODE and DATA space 11271 <1> ; in a process/program... 11272 <1> ; CODE segment/section may contain DATA! 11273 <1> ; It is flat, smoth and simplest programming method already as in 11274 <1> ; Retro UNIX 8086 v1 and MS-DOS programs. 11275 <1> ; 11276 000032E1 F6C202 <1> test dl, 2 ; page fault was caused by a page write 11277 <1> ; sign 11278 000032E4 0F84AB000000 <1> jz pfh_p_err 11279 <1> ; 31/08/2015 11280 000032EA F6C204 <1> test dl, 4 ; page fault was caused while CPL = 3 (user mode) 11281 <1> ; sign. (U+W+P = 4+2+1 = 7) 11282 000032ED 0F84A2000000 <1> jz pfh_pv_err 11283 <1> ; 11284 <1> ; make a new page and copy the parent's page content 11285 <1> ; as the child's new page content 11286 <1> ; 11287 000032F3 0F20D3 <1> mov ebx, cr2 ; CR2 contains the linear address 11288 <1> ; which has caused to page fault 11289 000032F6 E8A2000000 <1> call copy_page 11290 000032FB 0F828D000000 <1> jc pfh_im_err ; insufficient memory 11291 <1> ; 11292 00003301 EB7D <1> jmp pfh_cpp_ok 11293 <1> ; 11294 <1> pfh_alloc_np: 11295 00003303 E8EDFCFFFF <1> call allocate_page ; (allocate a new page) 11296 00003308 0F8280000000 <1> jc pfh_im_err ; 'insufficient memory' error 11297 <1> pfh_chk_cpl: 11298 <1> ; EAX = Physical (base) address of the allocated (new) page 11299 <1> ; (Lower 12 bits are ZERO, because 11300 <1> ; the address is on a page boundary) 11301 0000330E 80E204 <1> and dl, 4 ; CPL = 3 ? 11302 00003311 7505 <1> jnz short pfh_um 11303 <1> ; Page fault handler for kernel/system mode (CPL=0) 11304 00003313 0F20DB <1> mov ebx, cr3 ; CR3 (Control Register 3) contains physical address 11305 <1> ; of the current/active page directory 11306 <1> ; (Always kernel/system mode page directory, here!) 11307 <1> ; Note: Lower 12 bits are 0. (page boundary) 11308 00003316 EB06 <1> jmp short pfh_get_pde 11309 <1> ; 11310 <1> pfh_um: ; Page fault handler for user/appl. mode (CPL=3) 11311 00003318 8B1D[A1740000] <1> mov ebx, [u.pgdir] ; Page directory of current/active process 11312 <1> ; Physical address of the USER's page directory 11313 <1> ; Note: Lower 12 bits are 0. (page boundary) 11314 <1> pfh_get_pde: 11315 0000331E 80CA03 <1> or dl, 3 ; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT 11316 00003321 0F20D1 <1> mov ecx, cr2 ; CR2 contains the virtual address 11317 <1> ; which has been caused to page fault 11318 <1> ; 11319 00003324 C1E914 <1> shr ecx, 20 ; shift 20 bits right 11320 00003327 80E1FC <1> and cl, 0FCh ; mask lower 2 bits to get PDE offset 11321 <1> ; 11322 0000332A 01CB <1> add ebx, ecx ; now, EBX points to the relevant page dir entry 11323 0000332C 8B0B <1> mov ecx, [ebx] ; physical (base) address of the page table 11324 0000332E F6C101 <1> test cl, 1 ; check bit 0 is set (1) or not (0). 11325 00003331 740B <1> jz short pfh_set_pde ; Page directory entry is not valid, 11326 <1> ; set/validate page directory entry 11327 00003333 6681E100F0 <1> and cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits 11328 00003338 89CB <1> mov ebx, ecx ; Physical address of the page table 11329 0000333A 89C1 <1> mov ecx, eax ; new page address (physical) 11330 0000333C EB16 <1> jmp short pfh_get_pte 11331 <1> pfh_set_pde: 11332 <1> ;; NOTE: Page directories and page tables never be swapped out! 11333 <1> ;; (So, we know this PDE is empty or invalid) 11334 <1> ; 11335 0000333E 08D0 <1> or al, dl ; lower 3 bits are used as U/S, R/W, P flags 11336 00003340 8903 <1> mov [ebx], eax ; Let's put the new page directory entry here ! 11337 00003342 30C0 <1> xor al, al ; clear lower (3..8) bits 11338 00003344 89C3 <1> mov ebx, eax 11339 00003346 E8AAFCFFFF <1> call allocate_page ; (allocate a new page) 11340 0000334B 7241 <1> jc short pfh_im_err ; 'insufficient memory' error 11341 <1> pfh_spde_1: 11342 <1> ; EAX = Physical (base) address of the allocated (new) page 11343 0000334D 89C1 <1> mov ecx, eax 11344 0000334F E81BFDFFFF <1> call clear_page ; Clear page content 11345 <1> pfh_get_pte: 11346 00003354 0F20D0 <1> mov eax, cr2 ; virtual address 11347 <1> ; which has been caused to page fault 11348 00003357 89C7 <1> mov edi, eax ; 20/07/2015 11349 00003359 C1E80C <1> shr eax, 12 ; shift 12 bit right to get 11350 <1> ; higher 20 bits of the page fault address 11351 0000335C 25FF030000 <1> and eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 11352 00003361 C1E002 <1> shl eax, 2 ; shift 2 bits left to get PTE offset 11353 00003364 01C3 <1> add ebx, eax ; now, EBX points to the relevant page table entry 11354 00003366 8B03 <1> mov eax, [ebx] ; get previous value of pte 11355 <1> ; bit 0 of EAX is always 0 (otherwise we would not be here) 11356 00003368 21C0 <1> and eax, eax 11357 0000336A 7410 <1> jz short pfh_gpte_1 11358 <1> ; 20/07/2015 11359 0000336C 87D9 <1> xchg ebx, ecx ; new page address (physical) 11360 0000336E 55 <1> push ebp ; 20/07/2015 11361 0000336F 0F20D5 <1> mov ebp, cr2 11362 <1> ; ECX = physical address of the page table entry 11363 <1> ; EBX = Memory page address (physical!) 11364 <1> ; EAX = Swap disk (offset) address 11365 <1> ; EBP = virtual address (page fault address) 11366 00003372 E8B7000000 <1> call swap_in 11367 00003377 5D <1> pop ebp 11368 00003378 7210 <1> jc short pfh_err_retn 11369 0000337A 87CB <1> xchg ecx, ebx 11370 <1> ; EBX = physical address of the page table entry 11371 <1> ; ECX = new page 11372 <1> pfh_gpte_1: 11373 0000337C 08D1 <1> or cl, dl ; lower 3 bits are used as U/S, R/W, P flags 11374 0000337E 890B <1> mov [ebx], ecx ; Let's put the new page table entry here ! 11375 <1> pfh_cpp_ok: 11376 <1> ; 20/07/2015 11377 00003380 0F20D3 <1> mov ebx, cr2 11378 00003383 E82A020000 <1> call add_to_swap_queue 11379 <1> ; 11380 <1> ; The new PTE (which contains the new page) will be added to 11381 <1> ; the swap queue, here. 11382 <1> ; (Later, if memory will become insufficient, 11383 <1> ; one page will be swapped out which is at the head of 11384 <1> ; the swap queue by using FIFO and access check methods.) 11385 <1> ; 11386 00003388 31C0 <1> xor eax, eax ; 0 11387 <1> ; 11388 <1> pfh_err_retn: 11389 0000338A 59 <1> pop ecx 11390 0000338B 5A <1> pop edx 11391 0000338C 5B <1> pop ebx 11392 0000338D C3 <1> retn 11393 <1> 11394 <1> pfh_im_err: 11395 0000338E B8E1000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX 11396 <1> ; Major (Primary) Error: Page Fault 11397 <1> ; Minor (Secondary) Error: Insufficient Memory ! 11398 00003393 EBF5 <1> jmp short pfh_err_retn 11399 <1> 11400 <1> 11401 <1> pfh_p_err: ; 09/03/2015 11402 <1> pfh_pv_err: 11403 <1> ; Page fault was caused by a protection-violation 11404 00003395 B8E3000000 <1> mov eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX 11405 <1> ; Major (Primary) Error: Page Fault 11406 <1> ; Minor (Secondary) Error: Protection violation ! 11407 0000339A F9 <1> stc 11408 0000339B EBED <1> jmp short pfh_err_retn 11409 <1> 11410 <1> copy_page: 11411 <1> ; 22/09/2015 11412 <1> ; 21/09/2015 11413 <1> ; 19/09/2015 11414 <1> ; 07/09/2015 11415 <1> ; 31/08/2015 11416 <1> ; 20/07/2015 11417 <1> ; 05/05/2015 11418 <1> ; 03/05/2015 11419 <1> ; 18/04/2015 11420 <1> ; 12/04/2015 11421 <1> ; 30/10/2014 11422 <1> ; 18/10/2014 (Retro UNIX 386 v1 - beginning) 11423 <1> ; 11424 <1> ; INPUT -> 11425 <1> ; EBX = Virtual (linear) address of source page 11426 <1> ; (Page fault address) 11427 <1> ; OUTPUT -> 11428 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE 11429 <1> ; (corresponding PAGE TABLE ENTRY is mapped/set) 11430 <1> ; EAX = 0 (CF = 1) 11431 <1> ; if there is not a free page to be allocated 11432 <1> ; (page content of the source page will be copied 11433 <1> ; onto the target/new page) 11434 <1> ; 11435 <1> ; Modified Registers -> ecx, ebx (except EAX) 11436 <1> ; 11437 0000339D 56 <1> push esi 11438 0000339E 57 <1> push edi 11439 <1> ;push ebx 11440 <1> ;push ecx 11441 0000339F 31F6 <1> xor esi, esi 11442 000033A1 C1EB0C <1> shr ebx, 12 ; shift 12 bits right to get PDE & PTE numbers 11443 000033A4 89D9 <1> mov ecx, ebx ; save page fault address (as 12 bit shifted) 11444 000033A6 C1EB08 <1> shr ebx, 8 ; shift 8 bits right and then 11445 000033A9 80E3FC <1> and bl, 0FCh ; mask lower 2 bits to get PDE offset 11446 000033AC 89DF <1> mov edi, ebx ; save it for the parent of current process 11447 000033AE 031D[A1740000] <1> add ebx, [u.pgdir] ; EBX points to the relevant page dir entry 11448 000033B4 8B03 <1> mov eax, [ebx] ; physical (base) address of the page table 11449 000033B6 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11450 000033BA 89CB <1> mov ebx, ecx ; (restore higher 20 bits of page fault address) 11451 000033BC 81E3FF030000 <1> and ebx, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 11452 000033C2 66C1E302 <1> shl bx, 2 ; shift 2 bits left to get PTE offset 11453 000033C6 01C3 <1> add ebx, eax ; EBX points to the relevant page table entry 11454 <1> ; 07/09/2015 11455 000033C8 66F7030002 <1> test word [ebx], PTE_DUPLICATED ; (Does current process share this 11456 <1> ; read only page as a child process?) 11457 000033CD 7509 <1> jnz short cpp_0 ; yes 11458 000033CF 8B0B <1> mov ecx, [ebx] ; PTE value 11459 000033D1 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 11460 000033D6 EB32 <1> jmp short cpp_1 11461 <1> cpp_0: 11462 000033D8 89FE <1> mov esi, edi 11463 000033DA 0335[A5740000] <1> add esi, [u.ppgdir] ; the parent's page directory entry 11464 000033E0 8B06 <1> mov eax, [esi] ; physical (base) address of the page table 11465 000033E2 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11466 000033E6 89CE <1> mov esi, ecx ; (restore higher 20 bits of page fault address) 11467 000033E8 81E6FF030000 <1> and esi, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023) 11468 000033EE 66C1E602 <1> shl si, 2 ; shift 2 bits left to get PTE offset 11469 000033F2 01C6 <1> add esi, eax ; EDX points to the relevant page table entry 11470 000033F4 8B0E <1> mov ecx, [esi] ; PTE value of the parent process 11471 <1> ; 21/09/2015 11472 000033F6 8B03 <1> mov eax, [ebx] ; PTE value of the child process 11473 000033F8 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear page attributes 11474 <1> ; 11475 000033FC F6C101 <1> test cl, PTE_A_PRESENT ; is it a present/valid page ? 11476 000033FF 7424 <1> jz short cpp_3 ; the parent's page is not same page 11477 <1> ; 11478 00003401 6681E100F0 <1> and cx, PTE_A_CLEAR ; 0F000h ; clear page attributes 11479 00003406 39C8 <1> cmp eax, ecx ; Same page? 11480 00003408 751B <1> jne short cpp_3 ; Parent page and child page are not same 11481 <1> ; Convert child's page to writable page 11482 <1> cpp_1: 11483 0000340A E8E6FBFFFF <1> call allocate_page 11484 0000340F 721A <1> jc short cpp_4 ; 'insufficient memory' error 11485 00003411 21F6 <1> and esi, esi ; check ESI is valid or not 11486 00003413 7405 <1> jz short cpp_2 11487 <1> ; Convert read only page to writable page 11488 <1> ;(for the parent of the current process) 11489 <1> ;and word [esi], PTE_A_CLEAR ; 0F000h 11490 <1> ; 22/09/2015 11491 00003415 890E <1> mov [esi], ecx 11492 00003417 800E07 <1> or byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER 11493 <1> ; 1+2+4 = 7 11494 <1> cpp_2: 11495 0000341A 89C7 <1> mov edi, eax ; new page address of the child process 11496 <1> ; 07/09/2015 11497 0000341C 89CE <1> mov esi, ecx ; the page address of the parent process 11498 0000341E B900040000 <1> mov ecx, PAGE_SIZE / 4 11499 00003423 F3A5 <1> rep movsd ; 31/08/2015 11500 <1> cpp_3: 11501 00003425 0C07 <1> or al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7 11502 00003427 8903 <1> mov [ebx], eax ; Update PTE 11503 00003429 28C0 <1> sub al, al ; clear attributes 11504 <1> cpp_4: 11505 <1> ;pop ecx 11506 <1> ;pop ebx 11507 0000342B 5F <1> pop edi 11508 0000342C 5E <1> pop esi 11509 0000342D C3 <1> retn 11510 <1> 11511 <1> ;; 28/04/2015 11512 <1> ;; 24/10/2014 11513 <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning) 11514 <1> ;; SWAP_PAGE_QUEUE (4096 bytes) 11515 <1> ;; 11516 <1> ;; 0000 0001 0002 0003 .... 1020 1021 1022 1023 11517 <1> ;; +------+------+------+------+- -+------+------+------+------+ 11518 <1> ;; | pg1 | pg2 | pg3 | pg4 | .... |pg1021|pg1022|pg1023|pg1024| 11519 <1> ;; +------+------+------+------+- -+------+------+------+------+ 11520 <1> ;; 11521 <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue 11522 <1> ;; 11523 <1> ;; Method: 11524 <1> ;; Swap page queue is a list of allocated pages with physical 11525 <1> ;; addresses (system mode virtual adresses = physical addresses). 11526 <1> ;; It is used for 'swap_in' and 'swap_out' procedures. 11527 <1> ;; When a new page is being allocated, swap queue is updated 11528 <1> ;; by 'swap_queue_shift' procedure, header of the queue (offset 0) 11529 <1> ;; is checked for 'accessed' flag. If the 1st page on the queue 11530 <1> ;; is 'accessed' or 'read only', it is dropped from the list; 11531 <1> ;; other pages from the 2nd to the last (in [swpq_last]) shifted 11532 <1> ;; to head then the 2nd page becomes the 1st and '[swpq_last]' 11533 <1> ;; offset value becomes it's previous offset value - 4. 11534 <1> ;; If the 1st page of the swap page queue is not 'accessed' 11535 <1> ;; the queue/list is not shifted. 11536 <1> ;; After the queue/list shift, newly allocated page is added 11537 <1> ;; to the tail of the queue at the [swpq_count*4] position. 11538 <1> ;; But, if [swpq_count] > 1023, the newly allocated page 11539 <1> ;; will not be added to the tail of swap page queue. 11540 <1> ;; 11541 <1> ;; During 'swap_out' procedure, swap page queue is checked for 11542 <1> ;; the first non-accessed, writable page in the list, 11543 <1> ;; from the head to the tail. The list is shifted to left 11544 <1> ;; (to the head) till a non-accessed page will be found in the list. 11545 <1> ;; Then, this page is swapped out (to disk) and then it is dropped 11546 <1> ;; from the list by a final swap queue shift. [swpq_count] value 11547 <1> ;; is changed. If all pages on the queue' are 'accessed', 11548 <1> ;; 'insufficient memory' error will be returned ('swap_out' 11549 <1> ;; procedure will be failed)... 11550 <1> ;; 11551 <1> ;; Note: If the 1st page of the queue is an 'accessed' page, 11552 <1> ;; 'accessed' flag of the page will be reset (0) and that page 11553 <1> ;; (PTE) will be added to the tail of the queue after 11554 <1> ;; the check, if [swpq_count] < 1023. If [swpq_count] = 1024 11555 <1> ;; the queue will be rotated and the PTE in the head will be 11556 <1> ;; added to the tail after resetting 'accessed' bit. 11557 <1> ;; 11558 <1> ;; 11559 <1> ;; 11560 <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks) 11561 <1> ;; 11562 <1> ;; 00000000 00000004 00000008 0000000C ... size-8 size-4 11563 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 11564 <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) | 11565 <1> ;; +---------+---------+---------+---------+-- --+---------+---------+ 11566 <1> ;; 11567 <1> ;; [swpd_next] = the first free block address in swapped page records 11568 <1> ;; for next free block search by 'swap_out' procedure. 11569 <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes) 11570 <1> ;; NOTE: max. possible swap disk size is 1024 GB 11571 <1> ;; (entire swap space must be accessed by using 11572 <1> ;; 31 bit offset address) 11573 <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space 11574 <1> ;; [swpd_start] = absolute/start address of the swap disk/file 11575 <1> ;; 0 for file, or beginning sector of the swap partition 11576 <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file 11577 <1> ;; 11578 <1> ;; 11579 <1> ;; Method: 11580 <1> ;; When the memory (ram) becomes insufficient, page allocation 11581 <1> ;; procedure swaps out a page from memory to the swap disk 11582 <1> ;; (partition) or swap file to get a new free page at the memory. 11583 <1> ;; Swapping out is performed by using swap page queue. 11584 <1> ;; 11585 <1> ;; Allocation block size of swap disk/file is equal to page size 11586 <1> ;; (4096 bytes). Swapping address (in sectors) is recorded 11587 <1> ;; into relevant page file entry as 31 bit physical (logical) 11588 <1> ;; offset address as 1 bit shifted to left for present flag (0). 11589 <1> ;; Swapped page address is between 1 and swap disk/file size - 4. 11590 <1> ;; Absolute physical (logical) address of the swapped page is 11591 <1> ;; calculated by adding offset value to the swap partition's 11592 <1> ;; start address. If the swap device (disk) is a virtual disk 11593 <1> ;; or it is a file, start address of the swap disk/volume is 0, 11594 <1> ;; and offset value is equal to absolute (physical or logical) 11595 <1> ;; address/position. (It has not to be ZERO if the swap partition 11596 <1> ;; is in a partitioned virtual hard disk.) 11597 <1> ;; 11598 <1> ;; Note: Swap addresses are always specified/declared in sectors, 11599 <1> ;; not in bytes or in blocks/zones/clusters (4096 bytes) as unit. 11600 <1> ;; 11601 <1> ;; Swap disk/file allocation is mapped via 'Swap Allocation Table' 11602 <1> ;; at memory as similar to 'Memory Allocation Table'. 11603 <1> ;; 11604 <1> ;; Every bit of Swap Allocation Table repsesents one swap block 11605 <1> ;; (equal to page size) respectively. Bit 0 of the S.A.T. byte 0 11606 <1> ;; is reserved for swap disk/file block 0 as descriptor block 11607 <1> ;; (also for compatibility with PTE). If bit value is ZERO, 11608 <1> ;; it means relevant (respective) block is in use, and, 11609 <1> ;; of course, if bit value is 1, it means relevant (respective) 11610 <1> ;; swap disk/file block is free. 11611 <1> ;; For example: bit 1 of the byte 128 repsesents block 1025 11612 <1> ;; (128*8+1) or sector (offset) 8200 on the swap disk or 11613 <1> ;; byte (offset/position) 4198400 in the swap file. 11614 <1> ;; 4GB swap space is represented via 128KB Swap Allocation Table. 11615 <1> ;; Initial layout of Swap Allocation Table is as follows: 11616 <1> ;; ------------------------------------------------------------ 11617 <1> ;; 0111111111111111111111111 .... 11111111111111111111111111111 11618 <1> ;; ------------------------------------------------------------ 11619 <1> ;; (0 is reserved block, 1s represent free blocks respectively.) 11620 <1> ;; (Note: Allocation cell/unit of the table is bit, not byte) 11621 <1> ;; 11622 <1> ;; .............................................................. 11623 <1> ;; 11624 <1> ;; 'swap_out' procedure checks 'free_swap_blocks' count at first, 11625 <1> ;; then it searches Swap Allocation Table if free count is not 11626 <1> ;; zero. From begining the [swpd_next] dword value, the first bit 11627 <1> ;; position with value of 1 on the table is converted to swap 11628 <1> ;; disk/file offset address, in sectors (not 4096 bytes block). 11629 <1> ;; 'ldrv_write' procedure is called with ldrv (logical drive 11630 <1> ;; number of physical swap disk or virtual swap disk) 11631 <1> ;; number, sector offset (not absolute sector -LBA- number), 11632 <1> ;; and sector count (8, 512*8 = 4096) and buffer adress 11633 <1> ;; (memory page). That will be a direct disk write procedure. 11634 <1> ;; (for preventing late memory allocation, significant waiting). 11635 <1> ;; If disk write procedure returns with error or free count of 11636 <1> ;; swap blocks is ZERO, 'swap_out' procedure will return with 11637 <1> ;; 'insufficient memory error' (cf=1). 11638 <1> ;; 11639 <1> ;; (Note: Even if free swap disk/file blocks was not zero, 11640 <1> ;; any disk write error will not be fixed by 'swap_out' procedure, 11641 <1> ;; in other words, 'swap_out' will not check the table for other 11642 <1> ;; free blocks after a disk write error. It will return to 11643 <1> ;; the caller with error (CF=1) which means swapping is failed. 11644 <1> ;; 11645 <1> ;; After writing the page on to swap disk/file address/sector, 11646 <1> ;; 'swap_out' procesure returns with that swap (offset) sector 11647 <1> ;; address (cf=0). 11648 <1> ;; 11649 <1> ;; .............................................................. 11650 <1> ;; 11651 <1> ;; 'swap_in' procedure loads addressed (relevant) swap disk or 11652 <1> ;; file sectors at specified memory page. Then page allocation 11653 <1> ;; procedure updates relevant page table entry with 'present' 11654 <1> ;; attribute. If swap disk or file reading fails there is nothing 11655 <1> ;; to do, except to terminate the process which is the owner of 11656 <1> ;; the swapped page. 11657 <1> ;; 11658 <1> ;; 'swap_in' procedure sets the relevant/respective bit value 11659 <1> ;; in the Swap Allocation Table (as free block). 'swap_in' also 11660 <1> ;; updates [swpd_first] pointer if it is required. 11661 <1> ;; 11662 <1> ;; .............................................................. 11663 <1> ;; 11664 <1> ;; Note: If [swap_enabled] value is ZERO, that means there is not 11665 <1> ;; a swap disk or swap file in use... 'swap_in' and 'swap_out' 11666 <1> ;; procedures ans 'swap page que' procedures will not be active... 11667 <1> ;; 'Insufficient memory' error will be returned by 'swap_out' 11668 <1> ;; and 'general protection fault' will be returned by 'swap_in' 11669 <1> ;; procedure, if it is called mistakenly (a wrong value in a PTE). 11670 <1> ;; 11671 <1> 11672 <1> swap_in: 11673 <1> ; 31/08/2015 11674 <1> ; 20/07/2015 11675 <1> ; 28/04/2015 11676 <1> ; 18/04/2015 11677 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 11678 <1> ; 11679 <1> ; INPUT -> 11680 <1> ; EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE 11681 <1> ; EBP = VIRTUAL (LINEAR) ADDRESS (page fault address) 11682 <1> ; EAX = Offset Address for the swapped page on the 11683 <1> ; swap disk or in the swap file. 11684 <1> ; 11685 <1> ; OUTPUT -> 11686 <1> ; EAX = 0 if loading at memory has been successful 11687 <1> ; 11688 <1> ; CF = 1 -> swap disk reading error (disk/file not present 11689 <1> ; or sector not present or drive not ready 11690 <1> ; EAX = Error code 11691 <1> ; [u.error] = EAX 11692 <1> ; = The last error code for the process 11693 <1> ; (will be reset after returning to user) 11694 <1> ; 11695 <1> ; Modified Registers -> EAX 11696 <1> ; 11697 <1> 11698 0000342E 833D[12850000]00 <1> cmp dword [swp_drv], 0 11699 00003435 7648 <1> jna short swpin_dnp_err 11700 <1> 11701 00003437 3B05[16850000] <1> cmp eax, [swpd_size] 11702 0000343D 734C <1> jnb short swpin_snp_err 11703 <1> 11704 0000343F 56 <1> push esi 11705 00003440 53 <1> push ebx 11706 00003441 51 <1> push ecx 11707 00003442 8B35[12850000] <1> mov esi, [swp_drv] 11708 00003448 B908000000 <1> mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 11709 <1> ; Note: Even if corresponding physical disk's sector 11710 <1> ; size different than 512 bytes, logical disk sector 11711 <1> ; size is 512 bytes and disk reading procedure 11712 <1> ; will be performed for reading 4096 bytes 11713 <1> ; (2*2048, 8*512). 11714 <1> ; ESI = Logical disk description table address 11715 <1> ; EBX = Memory page (buffer) address (physical!) 11716 <1> ; EAX = Sector adress (offset address, logical sector number) 11717 <1> ; ECX = Sector count ; 8 sectors 11718 0000344D 50 <1> push eax 11719 0000344E E833020000 <1> call logical_disk_read 11720 00003453 58 <1> pop eax 11721 00003454 730C <1> jnc short swpin_read_ok 11722 <1> ; 11723 00003456 B804000000 <1> mov eax, SWP_DISK_READ_ERR ; drive not ready or read error 11724 0000345B A3[9D740000] <1> mov [u.error], eax 11725 00003460 EB19 <1> jmp short swpin_retn 11726 <1> ; 11727 <1> swpin_read_ok: 11728 <1> ; EAX = Offset address (logical sector number) 11729 00003462 E891010000 <1> call unlink_swap_block ; Deallocate swap block 11730 <1> ; 11731 <1> ; EBX = Memory page (buffer) address (physical!) 11732 <1> ; 20/07/2015 11733 00003467 89EB <1> mov ebx, ebp ; virtual address (page fault address) 11734 00003469 6681E300F0 <1> and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 11735 0000346E 8A1D[97740000] <1> mov bl, [u.uno] ; current process number 11736 <1> ; EBX = Virtual address & process number combination 11737 00003474 E89E000000 <1> call swap_queue_shift 11738 00003479 29C0 <1> sub eax, eax ; 0 ; Error Code = 0 (no error) 11739 <1> ; 11740 <1> swpin_retn: 11741 0000347B 59 <1> pop ecx 11742 0000347C 5B <1> pop ebx 11743 0000347D 5E <1> pop esi 11744 0000347E C3 <1> retn 11745 <1> 11746 <1> swpin_dnp_err: 11747 0000347F B805000000 <1> mov eax, SWP_DISK_NOT_PRESENT_ERR 11748 <1> swpin_err_retn: 11749 00003484 A3[9D740000] <1> mov [u.error], eax 11750 00003489 F9 <1> stc 11751 0000348A C3 <1> retn 11752 <1> 11753 <1> swpin_snp_err: 11754 0000348B B806000000 <1> mov eax, SWP_SECTOR_NOT_PRESENT_ERR 11755 00003490 EBF2 <1> jmp short swpin_err_retn 11756 <1> 11757 <1> swap_out: 11758 <1> ; 31/08/2015 11759 <1> ; 05/05/2015 11760 <1> ; 30/04/2015 11761 <1> ; 28/04/2015 11762 <1> ; 18/04/2015 11763 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 11764 <1> ; 11765 <1> ; INPUT -> 11766 <1> ; none 11767 <1> ; 11768 <1> ; OUTPUT -> 11769 <1> ; EAX = Physical page address (which is swapped out 11770 <1> ; for allocating a new page) 11771 <1> ; CF = 1 -> swap disk writing error (disk/file not present 11772 <1> ; or sector not present or drive not ready 11773 <1> ; EAX = Error code 11774 <1> ; [u.error] = EAX 11775 <1> ; = The last error code for the process 11776 <1> ; (will be reset after returning to user) 11777 <1> ; 11778 <1> ; Modified Registers -> non (except EAX) 11779 <1> ; 11780 00003492 66833D[10850000]01 <1> cmp word [swpq_count], 1 11781 0000349A 7274 <1> jc short swpout_im_err ; 'insufficient memory' 11782 <1> 11783 <1> ;cmp dword [swp_drv], 1 11784 <1> ;jc short swpout_dnp_err ; 'swap disk/file not present' 11785 <1> 11786 0000349C 833D[1A850000]01 <1> cmp dword [swpd_free], 1 11787 000034A3 7258 <1> jc short swpout_nfspc_err ; 'no free space on swap disk' 11788 <1> 11789 000034A5 53 <1> push ebx 11790 <1> swpout_1: 11791 000034A6 31DB <1> xor ebx, ebx 11792 000034A8 E86A000000 <1> call swap_queue_shift 11793 000034AD 21C0 <1> and eax, eax ; entry count (before shifting) 11794 000034AF 7457 <1> jz short swpout_npts_err ; There is no any PTE in 11795 <1> ; the swap queue 11796 000034B1 BB00E00800 <1> mov ebx, swap_queue ; Addres of the head of 11797 <1> ; the swap queue 11798 000034B6 8B03 <1> mov eax, [ebx] ; The PTE in the queue head 11799 <1> 11800 <1> ;test al, PTE_A_PRESENT ; bit 0 = 1 11801 <1> ;jz short swpout_1 ; non-present page already 11802 <1> ; must not be in the queue 11803 <1> 11804 <1> ;test al, PTE_A_WRITE ; bit 1 = 0 11805 <1> ;jz short swpout_1 ; read only page (must not be 11806 <1> ; swapped out) 11807 <1> 11808 000034B8 A820 <1> test al, PTE_A_ACCESS ; bit 5 = 1 (Accessed) 11809 000034BA 75EA <1> jnz short swpout_1 ; accessed page (must not be 11810 <1> ; swapped out, at this stage) 11811 <1> ; 11812 000034BC 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 11813 <1> ; 11814 000034C0 52 <1> push edx 11815 000034C1 89DA <1> mov edx, ebx ; Page table entry address 11816 000034C3 89C3 <1> mov ebx, eax ; Buffer (Page) Address 11817 <1> ; 11818 000034C5 E861010000 <1> call link_swap_block 11819 000034CA 7304 <1> jnc short swpout_2 ; It may not be needed here 11820 000034CC 5A <1> pop edx ; because [swpd_free] value 11821 000034CD 5B <1> pop ebx 11822 000034CE EB2D <1> jmp short swpout_nfspc_err ; was checked at the beginging. 11823 <1> swpout_2: 11824 000034D0 56 <1> push esi 11825 000034D1 51 <1> push ecx 11826 000034D2 50 <1> push eax ; sector address 11827 000034D3 8B35[12850000] <1> mov esi, [swp_drv] 11828 000034D9 B908000000 <1> mov ecx, PAGE_SIZE / LOGIC_SECT_SIZE ; 8 ! 11829 <1> ; Note: Even if corresponding physical disk's sector 11830 <1> ; size different than 512 bytes, logical disk sector 11831 <1> ; size is 512 bytes and disk writing procedure 11832 <1> ; will be performed for writing 4096 bytes 11833 <1> ; (2*2048, 8*512). 11834 <1> ; ESI = Logical disk description table address 11835 <1> ; EBX = Buffer address 11836 <1> ; EAX = Sector adress (offset address, logical sector number) 11837 <1> ; ECX = Sector count ; 8 sectors 11838 000034DE E8A4010000 <1> call logical_disk_write 11839 000034E3 59 <1> pop ecx ; sector address 11840 000034E4 730C <1> jnc short swpout_write_ok 11841 <1> ; 11842 <1> ;; call unlink_swap_block ; this block must be left as 'in use' 11843 <1> swpout_dw_err: 11844 000034E6 B808000000 <1> mov eax, SWP_DISK_WRITE_ERR ; drive not ready or write error 11845 000034EB A3[9D740000] <1> mov [u.error], eax 11846 000034F0 EB06 <1> jmp short swpout_retn 11847 <1> ; 11848 <1> swpout_write_ok: 11849 <1> ; EBX = Buffer (page) address 11850 <1> ; EDX = Page Table entry address 11851 <1> ; ECX = Swap disk sector (file block) address (31 bit) 11852 000034F2 D1E1 <1> shl ecx, 1 ; 31 bit sector address from bit 1 to bit 31 11853 000034F4 890A <1> mov [edx], ecx 11854 <1> ; bit 0 = 0 (swapped page) 11855 000034F6 89D8 <1> mov eax, ebx 11856 <1> swpout_retn: 11857 000034F8 59 <1> pop ecx 11858 000034F9 5E <1> pop esi 11859 000034FA 5A <1> pop edx 11860 000034FB 5B <1> pop ebx 11861 000034FC C3 <1> retn 11862 <1> 11863 <1> ; Note: Swap_queue will not be updated in 'swap_out' procedure 11864 <1> ; after the page is swapped out. (the PTE at the queue head 11865 <1> ; -with 'non-present' attribute- will be dropped from the 11866 <1> ; the queue in next 'swap_out' or in next 'swap_queue_shift'. 11867 <1> 11868 <1> ;swpout_dnp_err: 11869 <1> ; mov eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present 11870 <1> ; jmp short swpout_err_retn 11871 <1> swpout_nfspc_err: 11872 000034FD B807000000 <1> mov eax, SWP_NO_FREE_SPACE_ERR ; no free space 11873 <1> swpout_err_retn: 11874 00003502 A3[9D740000] <1> mov [u.error], eax 11875 <1> ;stc 11876 00003507 C3 <1> retn 11877 <1> swpout_npts_err: 11878 00003508 B809000000 <1> mov eax, SWP_NO_PAGE_TO_SWAP_ERR 11879 0000350D 5B <1> pop ebx 11880 0000350E EBF2 <1> jmp short swpout_err_retn 11881 <1> swpout_im_err: 11882 00003510 B801000000 <1> mov eax, ERR_MINOR_IM ; insufficient (out of) memory 11883 00003515 EBEB <1> jmp short swpout_err_retn 11884 <1> 11885 <1> swap_queue_shift: 11886 <1> ; 20/07/2015 11887 <1> ; 28/04/2015 11888 <1> ; 18/04/2015 11889 <1> ; 23/10/2014 (Retro UNIX 386 v1 - beginning) 11890 <1> ; 11891 <1> ; INPUT -> 11892 <1> ; EBX = Virtual (linear) address (bit 12 to 31) 11893 <1> ; and process number combination (bit 0 to 11) 11894 <1> ; EBX = 0 -> shift/drop from the head (offset 0) 11895 <1> ; OUTPUT -> 11896 <1> ; If EBX input > 0 11897 <1> ; the queue will be shifted 4 bytes (dword), 11898 <1> ; from the tail to the head, up to entry offset 11899 <1> ; which points to EBX input value or nothing 11900 <1> ; to do if EBX value is not found in the queue. 11901 <1> ; (The entry -with EBX value- will be removed 11902 <1> ; from the queue if it is found.) 11903 <1> ; If EBX input = 0 11904 <1> ; the queue will be shifted 4 bytes (dword), 11905 <1> ; from the tail to the head, if the PTE address 11906 <1> ; in head of the queue is marked as "accessed" 11907 <1> ; or it is marked as "non present". 11908 <1> ; (If "accessed" flag of the PTE -in the head- 11909 <1> ; is set -to 1-, it will be reset -to 0- and then, 11910 <1> ; the queue will be rotated -without dropping 11911 <1> ; the PTE from the queue-, for 4 bytes on head 11912 <1> ; to tail direction. The PTE in the head will be 11913 <1> ; moved in the tail, other PTEs will be shifted on 11914 <1> ; head direction.) 11915 <1> ; 11916 <1> ; EAX = [swpq_count] (before the shifting) 11917 <1> ; (EAX = 0 -> next 'swap_out' stage 11918 <1> ; is not applicable) 11919 <1> ; 11920 <1> ; Modified Registers -> EAX 11921 <1> ; 11922 00003517 0FB705[10850000] <1> movzx eax, word [swpq_count] ; Max. 1024 11923 0000351E 6621C0 <1> and ax, ax 11924 00003521 7433 <1> jz short swpqs_retn 11925 00003523 57 <1> push edi 11926 00003524 56 <1> push esi 11927 00003525 53 <1> push ebx 11928 00003526 51 <1> push ecx 11929 00003527 50 <1> push eax 11930 00003528 BE00E00800 <1> mov esi, swap_queue 11931 0000352D 89C1 <1> mov ecx, eax 11932 0000352F 09DB <1> or ebx, ebx 11933 00003531 7424 <1> jz short swpqs_7 11934 <1> swpqs_1: 11935 00003533 AD <1> lodsd 11936 00003534 39D8 <1> cmp eax, ebx 11937 00003536 7404 <1> je short swpqs_2 11938 00003538 E2F9 <1> loop swpqs_1 11939 0000353A EB15 <1> jmp short swpqs_6 11940 <1> swpqs_2: 11941 0000353C 89F7 <1> mov edi, esi 11942 0000353E 83EF04 <1> sub edi, 4 11943 <1> swpqs_3: 11944 00003541 66FF0D[10850000] <1> dec word [swpq_count] 11945 00003548 7403 <1> jz short swpqs_5 11946 <1> swpqs_4: 11947 0000354A 49 <1> dec ecx 11948 0000354B F3A5 <1> rep movsd ; shift up (to the head) 11949 <1> swpqs_5: 11950 0000354D 31C0 <1> xor eax, eax 11951 0000354F 8907 <1> mov [edi], eax 11952 <1> swpqs_6: 11953 00003551 58 <1> pop eax 11954 00003552 59 <1> pop ecx 11955 00003553 5B <1> pop ebx 11956 00003554 5E <1> pop esi 11957 00003555 5F <1> pop edi 11958 <1> swpqs_retn: 11959 00003556 C3 <1> retn 11960 <1> swpqs_7: 11961 00003557 89F7 <1> mov edi, esi ; head 11962 00003559 AD <1> lodsd 11963 <1> ; 20/07/2015 11964 0000355A 89C3 <1> mov ebx, eax 11965 0000355C 81E300F0FFFF <1> and ebx, ~PAGE_OFF ; ~0FFFh 11966 <1> ; ebx = virtual address (at page boundary) 11967 00003562 25FF0F0000 <1> and eax, PAGE_OFF ; 0FFFh 11968 <1> ; ax = process number (1 to 4095) 11969 00003567 3A05[97740000] <1> cmp al, [u.uno] 11970 <1> ; Max. 16 (nproc) processes for Retro UNIX 386 v1 11971 0000356D 7507 <1> jne short swpqs_8 11972 0000356F A1[A1740000] <1> mov eax, [u.pgdir] 11973 00003574 EB16 <1> jmp short swpqs_9 11974 <1> swpqs_8: 11975 <1> ;shl ax, 2 11976 00003576 C0E002 <1> shl al, 2 11977 00003579 8B80[D2710000] <1> mov eax, [eax+p.upage-4] 11978 0000357F 09C0 <1> or eax, eax 11979 00003581 74BE <1> jz short swpqs_3 ; invalid upage 11980 00003583 83C061 <1> add eax, u.pgdir - user 11981 <1> ; u.pgdir value for the process 11982 <1> ; is in [eax] 11983 00003586 8B00 <1> mov eax, [eax] 11984 00003588 21C0 <1> and eax, eax 11985 0000358A 74B5 <1> jz short swpqs_3 ; invalid page directory 11986 <1> swpqs_9: 11987 0000358C 52 <1> push edx 11988 <1> ; eax = page directory 11989 <1> ; ebx = virtual address 11990 0000358D E87EFBFFFF <1> call get_pte 11991 00003592 89D3 <1> mov ebx, edx ; PTE address 11992 00003594 5A <1> pop edx 11993 00003595 72AA <1> jc short swpqs_3 ; empty PDE 11994 <1> ; EAX = PTE value 11995 00003597 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 11996 00003599 74A6 <1> jz short swpqs_3 ; Drop non-present page 11997 <1> ; from the queue (head) 11998 0000359B A802 <1> test al, PTE_A_WRITE ; bit 1 = 0 11999 0000359D 74A2 <1> jz short swpqs_3 ; Drop read only page 12000 <1> ; from the queue (head) 12001 <1> ;test al, PTE_A_ACCESS ; bit 5 = 1 (Accessed) 12002 <1> ;jz short swpqs_6 ; present 12003 <1> ; non-accessed page 12004 0000359F 0FBAF005 <1> btr eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit 12005 000035A3 73AC <1> jnc short swpqs_6 ; non-accessed page 12006 000035A5 8903 <1> mov [ebx], eax ; save changed attribute 12007 <1> ; 12008 <1> ; Rotation (head -> tail) 12009 000035A7 49 <1> dec ecx ; entry count -> last entry number 12010 000035A8 74A7 <1> jz short swpqs_6 12011 <1> ; esi = head + 4 12012 <1> ; edi = head 12013 000035AA 8B07 <1> mov eax, [edi] ; 20/07/2015 12014 000035AC F3A5 <1> rep movsd ; n = 1 to k-1, [n - 1] = [n] 12015 000035AE 8907 <1> mov [edi], eax ; head -> tail ; [k] = [1] 12016 000035B0 EB9F <1> jmp short swpqs_6 12017 <1> 12018 <1> add_to_swap_queue: 12019 <1> ; temporary - 16/09/2015 12020 000035B2 C3 <1> retn 12021 <1> ; 20/07/2015 12022 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 12023 <1> ; 12024 <1> ; Adds new page to swap queue 12025 <1> ; (page directories and page tables must not be added 12026 <1> ; to swap queue) 12027 <1> ; 12028 <1> ; INPUT -> 12029 <1> ; EBX = Virtual address (for current process, [u.uno]) 12030 <1> ; 12031 <1> ; OUTPUT -> 12032 <1> ; EAX = [swpq_count] 12033 <1> ; (after the PTE has been added) 12034 <1> ; EAX = 0 -> Swap queue is full, (1024 entries) 12035 <1> ; the pte could not be added. 12036 <1> ; 12037 <1> ; Modified Registers -> EAX 12038 <1> ; 12039 000035B3 53 <1> push ebx 12040 000035B4 6681E300F0 <1> and bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11 12041 000035B9 8A1D[97740000] <1> mov bl, [u.uno] ; current process number 12042 000035BF E853FFFFFF <1> call swap_queue_shift ; drop from the queue if 12043 <1> ; it is already in the queue 12044 <1> ; Then add it to the tail of the queue 12045 000035C4 0FB705[10850000] <1> movzx eax, word [swpq_count] 12046 000035CB 663D0004 <1> cmp ax, 1024 12047 000035CF 7205 <1> jb short atsq_1 12048 000035D1 6629C0 <1> sub ax, ax 12049 000035D4 5B <1> pop ebx 12050 000035D5 C3 <1> retn 12051 <1> atsq_1: 12052 000035D6 56 <1> push esi 12053 000035D7 BE00E00800 <1> mov esi, swap_queue 12054 000035DC 6621C0 <1> and ax, ax 12055 000035DF 740A <1> jz short atsq_2 12056 000035E1 66C1E002 <1> shl ax, 2 ; convert to offset 12057 000035E5 01C6 <1> add esi, eax 12058 000035E7 66C1E802 <1> shr ax, 2 12059 <1> atsq_2: 12060 000035EB 6640 <1> inc ax 12061 000035ED 891E <1> mov [esi], ebx ; Virtual address + [u.uno] combination 12062 000035EF 66A3[10850000] <1> mov [swpq_count], ax 12063 000035F5 5E <1> pop esi 12064 000035F6 5B <1> pop ebx 12065 000035F7 C3 <1> retn 12066 <1> 12067 <1> unlink_swap_block: 12068 <1> ; 15/09/2015 12069 <1> ; 30/04/2015 12070 <1> ; 18/04/2015 12071 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 12072 <1> ; 12073 <1> ; INPUT -> 12074 <1> ; EAX = swap disk/file offset address 12075 <1> ; (bit 1 to bit 31) 12076 <1> ; OUTPUT -> 12077 <1> ; [swpd_free] is increased 12078 <1> ; (corresponding SWAP DISK ALLOC. TABLE bit is SET) 12079 <1> ; 12080 <1> ; Modified Registers -> EAX 12081 <1> ; 12082 000035F8 53 <1> push ebx 12083 000035F9 52 <1> push edx 12084 <1> ; 12085 000035FA C1E804 <1> shr eax, SECTOR_SHIFT+1 ;3+1 ; shift sector address to 12086 <1> ; 3 bits right 12087 <1> ; to get swap block/page number 12088 000035FD 89C2 <1> mov edx, eax 12089 <1> ; 15/09/2015 12090 000035FF C1EA03 <1> shr edx, 3 ; to get offset to S.A.T. 12091 <1> ; (1 allocation bit = 1 page) 12092 <1> ; (1 allocation bytes = 8 pages) 12093 00003602 80E2FC <1> and dl, 0FCh ; clear lower 2 bits 12094 <1> ; (to get 32 bit position) 12095 <1> ; 12096 00003605 BB00000D00 <1> mov ebx, swap_alloc_table ; Swap Allocation Table address 12097 0000360A 01D3 <1> add ebx, edx 12098 0000360C 83E01F <1> and eax, 1Fh ; lower 5 bits only 12099 <1> ; (allocation bit position) 12100 0000360F 3B05[1E850000] <1> cmp eax, [swpd_next] ; is the new free block addr. lower 12101 <1> ; than the address in 'swpd_next' ? 12102 <1> ; (next/first free block value) 12103 00003615 7305 <1> jnb short uswpbl_1 ; no 12104 00003617 A3[1E850000] <1> mov [swpd_next], eax ; yes 12105 <1> uswpbl_1: 12106 0000361C 0FAB03 <1> bts [ebx], eax ; unlink/release/deallocate block 12107 <1> ; set relevant bit to 1. 12108 <1> ; set CF to the previous bit value 12109 0000361F F5 <1> cmc ; complement carry flag 12110 00003620 7206 <1> jc short uswpbl_2 ; do not increase swfd_free count 12111 <1> ; if the block is already deallocated 12112 <1> ; before. 12113 00003622 FF05[1A850000] <1> inc dword [swpd_free] 12114 <1> uswpbl_2: 12115 00003628 5A <1> pop edx 12116 00003629 5B <1> pop ebx 12117 0000362A C3 <1> retn 12118 <1> 12119 <1> link_swap_block: 12120 <1> ; 01/07/2015 12121 <1> ; 18/04/2015 12122 <1> ; 24/10/2014 (Retro UNIX 386 v1 - beginning) 12123 <1> ; 12124 <1> ; INPUT -> none 12125 <1> ; 12126 <1> ; OUTPUT -> 12127 <1> ; EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes) 12128 <1> ; in sectors (corresponding 12129 <1> ; SWAP DISK ALLOCATION TABLE bit is RESET) 12130 <1> ; 12131 <1> ; CF = 1 and EAX = 0 12132 <1> ; if there is not a free block to be allocated 12133 <1> ; 12134 <1> ; Modified Registers -> none (except EAX) 12135 <1> ; 12136 <1> 12137 <1> ;mov eax, [swpd_free] 12138 <1> ;and eax, eax 12139 <1> ;jz short out_of_swpspc 12140 <1> ; 12141 0000362B 53 <1> push ebx 12142 0000362C 51 <1> push ecx 12143 <1> ; 12144 0000362D BB00000D00 <1> mov ebx, swap_alloc_table ; Swap Allocation Table offset 12145 00003632 89D9 <1> mov ecx, ebx 12146 00003634 031D[1E850000] <1> add ebx, [swpd_next] ; Free block searching starts from here 12147 <1> ; next_free_swap_block >> 5 12148 0000363A 030D[22850000] <1> add ecx, [swpd_last] ; Free block searching ends here 12149 <1> ; (total_swap_blocks - 1) >> 5 12150 <1> lswbl_scan: 12151 00003640 39CB <1> cmp ebx, ecx 12152 00003642 770A <1> ja short lswbl_notfound 12153 <1> ; 12154 00003644 0FBC03 <1> bsf eax, [ebx] ; Scans source operand for first bit set (1). 12155 <1> ; Clears ZF if a bit is found set (1) and 12156 <1> ; loads the destination with an index to 12157 <1> ; first set bit. (0 -> 31) 12158 <1> ; Sets ZF to 1 if no bits are found set. 12159 <1> ; 01/07/2015 12160 00003647 751C <1> jnz short lswbl_found ; ZF = 0 -> a free block has been found 12161 <1> ; 12162 <1> ; NOTE: a Swap Disk Allocation Table bit 12163 <1> ; with value of 1 means 12164 <1> ; the corresponding page is free 12165 <1> ; (Retro UNIX 386 v1 feaure only!) 12166 00003649 83C304 <1> add ebx, 4 12167 <1> ; We return back for searching next page block 12168 <1> ; NOTE: [swpd_free] is not ZERO; so, 12169 <1> ; we always will find at least 1 free block here. 12170 0000364C EBF2 <1> jmp short lswbl_scan 12171 <1> ; 12172 <1> lswbl_notfound: 12173 0000364E 81E900000D00 <1> sub ecx, swap_alloc_table 12174 00003654 890D[1E850000] <1> mov [swpd_next], ecx ; next/first free page = last page 12175 <1> ; (unlink_swap_block procedure will change it) 12176 0000365A 31C0 <1> xor eax, eax 12177 0000365C A3[1A850000] <1> mov [swpd_free], eax 12178 00003661 F9 <1> stc 12179 <1> lswbl_ok: 12180 00003662 59 <1> pop ecx 12181 00003663 5B <1> pop ebx 12182 00003664 C3 <1> retn 12183 <1> ; 12184 <1> ;out_of_swpspc: 12185 <1> ; stc 12186 <1> ; retn 12187 <1> 12188 <1> lswbl_found: 12189 00003665 89D9 <1> mov ecx, ebx 12190 00003667 81E900000D00 <1> sub ecx, swap_alloc_table 12191 0000366D 890D[1E850000] <1> mov [swpd_next], ecx ; Set first free block searching start 12192 <1> ; address/offset (to the next) 12193 00003673 FF0D[1A850000] <1> dec dword [swpd_free] ; 1 block has been allocated (X = X-1) 12194 <1> ; 12195 00003679 0FB303 <1> btr [ebx], eax ; The destination bit indexed by the source value 12196 <1> ; is copied into the Carry Flag and then cleared 12197 <1> ; in the destination. 12198 <1> ; 12199 <1> ; Reset the bit which is corresponding to the 12200 <1> ; (just) allocated block. 12201 0000367C C1E105 <1> shl ecx, 5 ; (block offset * 32) + block index 12202 0000367F 01C8 <1> add eax, ecx ; = block number 12203 00003681 C1E003 <1> shl eax, SECTOR_SHIFT ; 3, sector (offset) address of the block 12204 <1> ; 1 block = 8 sectors 12205 <1> ; 12206 <1> ; EAX = offset address of swap disk/file sector (beginning of the block) 12207 <1> ; 12208 <1> ; NOTE: The relevant page table entry will be updated 12209 <1> ; according to this EAX value... 12210 <1> ; 12211 00003684 EBDC <1> jmp short lswbl_ok 12212 <1> 12213 <1> logical_disk_read: 12214 <1> ; 20/07/2015 12215 <1> ; 09/03/2015 (temporary code here) 12216 <1> ; 12217 <1> ; INPUT -> 12218 <1> ; ESI = Logical disk description table address 12219 <1> ; EBX = Memory page (buffer) address (physical!) 12220 <1> ; EAX = Sector adress (offset address, logical sector number) 12221 <1> ; ECX = Sector count 12222 <1> ; 12223 <1> ; 12224 00003686 C3 <1> retn 12225 <1> 12226 <1> logical_disk_write: 12227 <1> ; 20/07/2015 12228 <1> ; 09/03/2015 (temporary code here) 12229 <1> ; 12230 <1> ; INPUT -> 12231 <1> ; ESI = Logical disk description table address 12232 <1> ; EBX = Memory page (buffer) address (physical!) 12233 <1> ; EAX = Sector adress (offset address, logical sector number) 12234 <1> ; ECX = Sector count 12235 <1> ; 12236 00003687 C3 <1> retn 12237 <1> 12238 <1> get_physical_addr: 12239 <1> ; 18/10/2015 12240 <1> ; 29/07/2015 12241 <1> ; 20/07/2015 12242 <1> ; 04/06/2015 12243 <1> ; 20/05/2015 12244 <1> ; 28/04/2015 12245 <1> ; 18/04/2015 12246 <1> ; Get physical address 12247 <1> ; (allocates a new page for user if it is not present) 12248 <1> ; 12249 <1> ; (This subroutine is needed for mapping user's virtual 12250 <1> ; (buffer) address to physical address (of the buffer).) 12251 <1> ; ('sys write', 'sys read' system calls...) 12252 <1> ; 12253 <1> ; INPUT -> 12254 <1> ; EBX = virtual address 12255 <1> ; u.pgdir = page directory (physical) address 12256 <1> ; 12257 <1> ; OUTPUT -> 12258 <1> ; EAX = physical address 12259 <1> ; EBX = linear address 12260 <1> ; EDX = physical address of the page frame 12261 <1> ; (with attribute bits) 12262 <1> ; ECX = byte count within the page frame 12263 <1> ; 12264 <1> ; Modified Registers -> EAX, EBX, ECX, EDX 12265 <1> ; 12266 00003688 81C300004000 <1> add ebx, CORE ; 18/10/2015 12267 <1> ; 12268 0000368E A1[A1740000] <1> mov eax, [u.pgdir] 12269 00003693 E878FAFFFF <1> call get_pte 12270 <1> ; EDX = Page table entry address (if CF=0) 12271 <1> ; Page directory entry address (if CF=1) 12272 <1> ; (Bit 0 value is 0 if PT is not present) 12273 <1> ; EAX = Page table entry value (page address) 12274 <1> ; CF = 1 -> PDE not present or invalid ? 12275 00003698 731C <1> jnc short gpa_1 12276 <1> ; 12277 0000369A E856F9FFFF <1> call allocate_page 12278 0000369F 725B <1> jc short gpa_im_err ; 'insufficient memory' error 12279 <1> gpa_0: 12280 000036A1 E8C9F9FFFF <1> call clear_page 12281 <1> ; EAX = Physical (base) address of the allocated (new) page 12282 000036A6 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7 12283 <1> ; lower 3 bits are used as U/S, R/W, P flags 12284 <1> ; (user, writable, present page) 12285 000036A8 8902 <1> mov [edx], eax ; Let's put the new page directory entry here ! 12286 000036AA A1[A1740000] <1> mov eax, [u.pgdir] 12287 000036AF E85CFAFFFF <1> call get_pte 12288 000036B4 7246 <1> jc short gpa_im_err ; 'insufficient memory' error 12289 <1> gpa_1: 12290 <1> ; EAX = PTE value, EDX = PTE address 12291 000036B6 A801 <1> test al, PTE_A_PRESENT 12292 000036B8 751A <1> jnz short gpa_3 12293 000036BA 09C0 <1> or eax, eax 12294 000036BC 7430 <1> jz short gpa_4 ; Allocate a new page 12295 <1> ; 20/07/2015 12296 000036BE 55 <1> push ebp 12297 000036BF 89DD <1> mov ebp, ebx ; virtual (linear) address 12298 <1> ; reload swapped page 12299 000036C1 E83C000000 <1> call reload_page ; 28/04/2015 12300 000036C6 5D <1> pop ebp 12301 000036C7 7224 <1> jc short gpa_retn 12302 <1> gpa_2: 12303 <1> ; 20/07/2015 12304 <1> ; 20/05/2015 12305 <1> ; add this page to swap queue 12306 000036C9 50 <1> push eax 12307 <1> ; EBX = virtual address 12308 000036CA E8E3FEFFFF <1> call add_to_swap_queue 12309 000036CF 58 <1> pop eax 12310 <1> ; PTE address in EDX 12311 <1> ; virtual address in EBX 12312 <1> ; EAX = memory page address 12313 000036D0 0C07 <1> or al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE 12314 <1> ; present flag, bit 0 = 1 12315 <1> ; user flag, bit 2 = 1 12316 <1> ; writable flag, bit 1 = 1 12317 000036D2 8902 <1> mov [edx], eax ; Update PTE value 12318 <1> gpa_3: 12319 <1> ; 18/10/2015 12320 000036D4 89D9 <1> mov ecx, ebx 12321 000036D6 81E1FF0F0000 <1> and ecx, PAGE_OFF 12322 000036DC 89C2 <1> mov edx, eax 12323 000036DE 662500F0 <1> and ax, PTE_A_CLEAR 12324 000036E2 01C8 <1> add eax, ecx 12325 000036E4 F7D9 <1> neg ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095 12326 000036E6 81C100100000 <1> add ecx, PAGE_SIZE 12327 000036EC F8 <1> clc 12328 <1> gpa_retn: 12329 000036ED C3 <1> retn 12330 <1> gpa_4: 12331 000036EE E802F9FFFF <1> call allocate_page 12332 000036F3 7207 <1> jc short gpa_im_err ; 'insufficient memory' error 12333 000036F5 E875F9FFFF <1> call clear_page 12334 000036FA EBCD <1> jmp short gpa_2 12335 <1> 12336 <1> gpa_im_err: 12337 000036FC B801000000 <1> mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 12338 <1> ; Major error = 0 (No protection fault) 12339 00003701 C3 <1> retn 12340 <1> 12341 <1> reload_page: 12342 <1> ; 20/07/2015 12343 <1> ; 28/04/2015 (Retro UNIX 386 v1 - beginning) 12344 <1> ; 12345 <1> ; Reload (Restore) swapped page at memory 12346 <1> ; 12347 <1> ; INPUT -> 12348 <1> ; EBP = Virtual (linear) memory address 12349 <1> ; EAX = PTE value (swap disk sector address) 12350 <1> ; (Swap disk sector address = bit 1 to bit 31 of EAX) 12351 <1> ; OUTPUT -> 12352 <1> ; EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE 12353 <1> ; 12354 <1> ; CF = 1 and EAX = error code 12355 <1> ; 12356 <1> ; Modified Registers -> none (except EAX) 12357 <1> ; 12358 00003702 D1E8 <1> shr eax, 1 ; Convert PTE value to swap disk address 12359 00003704 53 <1> push ebx ; 12360 00003705 89C3 <1> mov ebx, eax ; Swap disk (offset) address 12361 00003707 E8E9F8FFFF <1> call allocate_page 12362 0000370C 720C <1> jc short rlp_im_err 12363 0000370E 93 <1> xchg eax, ebx 12364 <1> ; EBX = Physical memory (page) address 12365 <1> ; EAX = Swap disk (offset) address 12366 <1> ; EBP = Virtual (linear) memory address 12367 0000370F E81AFDFFFF <1> call swap_in 12368 00003714 720B <1> jc short rlp_swp_err ; (swap disk/file read error) 12369 00003716 89D8 <1> mov eax, ebx 12370 <1> rlp_retn: 12371 00003718 5B <1> pop ebx 12372 00003719 C3 <1> retn 12373 <1> 12374 <1> rlp_im_err: 12375 0000371A B801000000 <1> mov eax, ERR_MINOR_IM ; Insufficient memory (minor) error! 12376 <1> ; Major error = 0 (No protection fault) 12377 0000371F EBF7 <1> jmp short rlp_retn 12378 <1> 12379 <1> rlp_swp_err: 12380 00003721 B804000000 <1> mov eax, SWP_DISK_READ_ERR ; Swap disk read error ! 12381 00003726 EBF0 <1> jmp short rlp_retn 12382 <1> 12383 <1> 12384 <1> copy_page_dir: 12385 <1> ; 19/09/2015 12386 <1> ; temporary - 07/09/2015 12387 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 12388 <1> ; 12389 <1> ; INPUT -> 12390 <1> ; [u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's 12391 <1> ; page directory. 12392 <1> ; OUTPUT -> 12393 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's 12394 <1> ; page directory. 12395 <1> ; (New page directory with new page table entries.) 12396 <1> ; (New page tables with read only copies of the parent's 12397 <1> ; pages.) 12398 <1> ; EAX = 0 -> Error (CF = 1) 12399 <1> ; 12400 <1> ; Modified Registers -> none (except EAX) 12401 <1> ; 12402 00003728 E8C8F8FFFF <1> call allocate_page 12403 0000372D 723E <1> jc short cpd_err 12404 <1> ; 12405 0000372F 55 <1> push ebp ; 20/07/2015 12406 00003730 56 <1> push esi 12407 00003731 57 <1> push edi 12408 00003732 53 <1> push ebx 12409 00003733 51 <1> push ecx 12410 00003734 8B35[A1740000] <1> mov esi, [u.pgdir] 12411 0000373A 89C7 <1> mov edi, eax 12412 0000373C 50 <1> push eax ; save child's page directory address 12413 <1> ; copy PDE 0 from the parent's page dir to the child's page dir 12414 <1> ; (use same system space for all user page tables) 12415 0000373D A5 <1> movsd 12416 0000373E BD00004000 <1> mov ebp, 1024*4096 ; pass the 1st 4MB (system space) 12417 00003743 B9FF030000 <1> mov ecx, (PAGE_SIZE / 4) - 1 ; 1023 12418 <1> cpd_0: 12419 00003748 AD <1> lodsd 12420 <1> ;or eax, eax 12421 <1> ;jnz short cpd_1 12422 00003749 A801 <1> test al, PDE_A_PRESENT ; bit 0 = 1 12423 0000374B 7508 <1> jnz short cpd_1 12424 <1> ; (virtual address at the end of the page table) 12425 0000374D 81C500004000 <1> add ebp, 1024*4096 ; page size * PTE count 12426 00003753 EB0F <1> jmp short cpd_2 12427 <1> cpd_1: 12428 00003755 662500F0 <1> and ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits 12429 00003759 89C3 <1> mov ebx, eax 12430 <1> ; EBX = Parent's page table address 12431 0000375B E81F000000 <1> call copy_page_table 12432 00003760 720C <1> jc short cpd_p_err 12433 <1> ; EAX = Child's page table address 12434 00003762 0C07 <1> or al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER 12435 <1> ; set bit 0, bit 1 and bit 2 to 1 12436 <1> ; (present, writable, user) 12437 <1> cpd_2: 12438 00003764 AB <1> stosd 12439 00003765 E2E1 <1> loop cpd_0 12440 <1> ; 12441 00003767 58 <1> pop eax ; restore child's page directory address 12442 <1> cpd_3: 12443 00003768 59 <1> pop ecx 12444 00003769 5B <1> pop ebx 12445 0000376A 5F <1> pop edi 12446 0000376B 5E <1> pop esi 12447 0000376C 5D <1> pop ebp 12448 <1> cpd_err: 12449 0000376D C3 <1> retn 12450 <1> cpd_p_err: 12451 <1> ; release the allocated pages missing (recover free space) 12452 0000376E 58 <1> pop eax ; the new page directory address (physical) 12453 0000376F 8B1D[A1740000] <1> mov ebx, [u.pgdir] ; parent's page directory address 12454 00003775 E8B4F9FFFF <1> call deallocate_page_dir 12455 0000377A 29C0 <1> sub eax, eax ; 0 12456 0000377C F9 <1> stc 12457 0000377D EBE9 <1> jmp short cpd_3 12458 <1> 12459 <1> copy_page_table: 12460 <1> ; 19/09/2015 12461 <1> ; temporary - 07/09/2015 12462 <1> ; 07/09/2015 (Retro UNIX 386 v1 - beginning) 12463 <1> ; 12464 <1> ; INPUT -> 12465 <1> ; EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table. 12466 <1> ; EBP = page table entry index (from 'copy_page_dir') 12467 <1> ; OUTPUT -> 12468 <1> ; EAX = PHYSICAL (real/flat) ADDRESS of the child's page table. 12469 <1> ; EBP = (recent) page table index (for 'add_to_swap_queue') 12470 <1> ; CF = 1 -> error 12471 <1> ; 12472 <1> ; Modified Registers -> EBP (except EAX) 12473 <1> ; 12474 0000377F E871F8FFFF <1> call allocate_page 12475 00003784 725A <1> jc short cpt_err 12476 <1> ; 12477 00003786 50 <1> push eax ; * 12478 <1> ;push ebx 12479 00003787 56 <1> push esi 12480 00003788 57 <1> push edi 12481 00003789 52 <1> push edx 12482 0000378A 51 <1> push ecx 12483 <1> ; 12484 0000378B 89DE <1> mov esi, ebx 12485 0000378D 89C7 <1> mov edi, eax 12486 0000378F 89C2 <1> mov edx, eax 12487 00003791 81C200100000 <1> add edx, PAGE_SIZE 12488 <1> cpt_0: 12489 00003797 AD <1> lodsd 12490 00003798 A801 <1> test al, PTE_A_PRESENT ; bit 0 = 1 12491 0000379A 750B <1> jnz short cpt_1 12492 0000379C 21C0 <1> and eax, eax 12493 0000379E 7430 <1> jz short cpt_2 12494 <1> ; ebp = virtual (linear) address of the memory page 12495 000037A0 E85DFFFFFF <1> call reload_page ; 28/04/2015 12496 000037A5 7234 <1> jc short cpt_p_err 12497 <1> cpt_1: 12498 000037A7 662500F0 <1> and ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 12499 000037AB 89C1 <1> mov ecx, eax 12500 <1> ; Allocate a new page for the child process 12501 000037AD E843F8FFFF <1> call allocate_page 12502 000037B2 7227 <1> jc short cpt_p_err 12503 000037B4 57 <1> push edi 12504 000037B5 56 <1> push esi 12505 000037B6 89CE <1> mov esi, ecx 12506 000037B8 89C7 <1> mov edi, eax 12507 000037BA B900040000 <1> mov ecx, PAGE_SIZE/4 12508 000037BF F3A5 <1> rep movsd ; copy page (4096 bytes) 12509 000037C1 5E <1> pop esi 12510 000037C2 5F <1> pop edi 12511 <1> ; 12512 000037C3 53 <1> push ebx 12513 000037C4 50 <1> push eax 12514 000037C5 89EB <1> mov ebx, ebp 12515 <1> ; ebx = virtual address of the memory page 12516 000037C7 E8E6FDFFFF <1> call add_to_swap_queue 12517 000037CC 58 <1> pop eax 12518 000037CD 5B <1> pop ebx 12519 <1> ; 12520 <1> ;or ax, PTE_A_USER+PTE_A_PRESENT 12521 000037CE 0C07 <1> or al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 12522 <1> cpt_2: 12523 000037D0 AB <1> stosd ; EDI points to child's PTE 12524 <1> ; 12525 000037D1 81C500100000 <1> add ebp, 4096 ; 20/07/2015 (next page) 12526 <1> ; 12527 000037D7 39D7 <1> cmp edi, edx 12528 000037D9 72BC <1> jb short cpt_0 12529 <1> cpt_p_err: 12530 000037DB 59 <1> pop ecx 12531 000037DC 5A <1> pop edx 12532 000037DD 5F <1> pop edi 12533 000037DE 5E <1> pop esi 12534 <1> ;pop ebx 12535 000037DF 58 <1> pop eax ; * 12536 <1> cpt_err: 12537 000037E0 C3 <1> retn 12538 <1> 12539 <1> 12540 <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS /// 12541 <1> 12542 <1> ;; Data: 12543 <1> 12544 <1> ; 09/03/2015 12545 <1> ;swpq_count: dw 0 ; count of pages on the swap que 12546 <1> ;swp_drv: dd 0 ; logical drive description table address of the swap drive/disk 12547 <1> ;swpd_size: dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 12548 <1> ;swpd_free: dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical) 12549 <1> ;swpd_next: dd 0 ; next free page block 12550 <1> ;swpd_last: dd 0 ; last swap page block 12551 %include 'sysdefs.inc' ; 09/03/2015 12552 <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC 12553 <1> ; Last Modification: 04/02/2016 12554 <1> ; 12555 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 12556 <1> ; (Modified from 12557 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 12558 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 12559 <1> ; UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11) 12560 <1> ; ---------------------------------------------------------------------------- 12561 <1> ; 12562 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 12563 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 12564 <1> ; 12565 <1> ; 12566 <1> ; 12567 <1> ; **************************************************************************** 12568 <1> 12569 <1> nproc equ 16 ; number of processes 12570 <1> nfiles equ 50 12571 <1> ntty equ 8 ; 8+1 -> 8 (10/05/2013) 12572 <1> nbuf equ 6 ; number of buffers (04/02/2016) 12573 <1> 12574 <1> ;csgmnt equ 2000h ; 26/05/2013 (segment of process 1) 12575 <1> ;core equ 0 ; 19/04/2013 12576 <1> ;ecore equ 32768 - 64 ; 04/06/2013 (24/05/2013) 12577 <1> ; (if total size of argument list and arguments is 128 bytes) 12578 <1> ; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes 12579 <1> ; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570) 12580 <1> ; initial value of user's stack pointer = 32768-64-128-2 = 32574 12581 <1> ; (sp=32768-args_space-2 at the beginning of execution) 12582 <1> ; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes) 12583 <1> ; 'u' structure offset (for the '/core' dump file) = 32704 12584 <1> ; '/core' dump file size = 32768 bytes 12585 <1> 12586 <1> ; 08/03/2014 12587 <1> ;sdsegmnt equ 6C0h ; 256*16 bytes (swap data segment size for 16 processes) 12588 <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only ! 12589 <1> ;;sdsegmnt equ 740h ; swap data segment (for user structures and registers) 12590 <1> 12591 <1> ; 30/08/2013 12592 <1> time_count equ 4 ; 10 --> 4 01/02/2014 12593 <1> 12594 <1> ; 05/02/2014 12595 <1> ; process status 12596 <1> ;SFREE equ 0 12597 <1> ;SRUN equ 1 12598 <1> ;SWAIT equ 2 12599 <1> ;SZOMB equ 3 12600 <1> ;SSLEEP equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup) 12601 <1> 12602 <1> ; 09/03/2015 12603 <1> userdata equ 80000h ; user structure data address for current user ; temporary 12604 <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary 12605 <1> swap_alloc_table equ 0D0000h ; swap allocation table address ; temporary 12606 <1> 12607 <1> ; 17/09/2015 12608 <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return 12609 <1> 12610 <1> ; 21/09/2015 (36) 12611 <1> ; 01/07/2015 (35) 12612 <1> ; 14/07/2013 (0-34) 12613 <1> ; UNIX v1 system calls 12614 <1> _rele equ 0 12615 <1> _exit equ 1 12616 <1> _fork equ 2 12617 <1> _read equ 3 12618 <1> _write equ 4 12619 <1> _open equ 5 12620 <1> _close equ 6 12621 <1> _wait equ 7 12622 <1> _creat equ 8 12623 <1> _link equ 9 12624 <1> _unlink equ 10 12625 <1> _exec equ 11 12626 <1> _chdir equ 12 12627 <1> _time equ 13 12628 <1> _mkdir equ 14 12629 <1> _chmod equ 15 12630 <1> _chown equ 16 12631 <1> _break equ 17 12632 <1> _stat equ 18 12633 <1> _seek equ 19 12634 <1> _tell equ 20 12635 <1> _mount equ 21 12636 <1> _umount equ 22 12637 <1> _setuid equ 23 12638 <1> _getuid equ 24 12639 <1> _stime equ 25 12640 <1> _quit equ 26 12641 <1> _intr equ 27 12642 <1> _fstat equ 28 12643 <1> _emt equ 29 12644 <1> _mdate equ 30 12645 <1> _stty equ 31 12646 <1> _gtty equ 32 12647 <1> _ilgins equ 33 12648 <1> _sleep equ 34 ; Retro UNIX 8086 v1 feature only ! 12649 <1> _msg equ 35 ; Retro UNIX 386 v1 feature only ! 12650 <1> _geterr equ 36 ; Retro UNIX 386 v1 feature only ! 12651 <1> 12652 <1> %macro sys 1-4 12653 <1> ; 13/04/2015 12654 <1> ; Retro UNIX 386 v1 system call. 12655 <1> mov eax, %1 12656 <1> %if %0 >= 2 12657 <1> mov ebx, %2 12658 <1> %if %0 >= 3 12659 <1> mov ecx, %3 12660 <1> %if %0 = 4 12661 <1> mov edx, %4 12662 <1> %endif 12663 <1> %endif 12664 <1> %endif 12665 <1> int 30h 12666 <1> %endmacro 12667 <1> 12668 <1> ; 13/05/2015 - ERROR CODES 12669 <1> ERR_FILE_NOT_OPEN equ 10 ; 'file not open !' error 12670 <1> ERR_FILE_ACCESS equ 11 ; 'permission denied !' error 12671 <1> ; 14/05/2015 12672 <1> ERR_DIR_ACCESS equ 11 ; 'permission denied !' error 12673 <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error 12674 <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error 12675 <1> ERR_DIR_EXISTS equ 14 ; 'directory already exists !' error 12676 <1> ; 16/05/2015 12677 <1> ERR_DRV_NOT_RDY equ 15 ; 'drive not ready !' error 12678 <1> ; 18/05/2015 12679 <1> ERR_DEV_NOT_RDY equ 15 ; 'device not ready !' error 12680 <1> ERR_DEV_ACCESS equ 11 ; 'permission denied !' error 12681 <1> ERR_DEV_NOT_OPEN equ 10 ; 'device not open !' error 12682 <1> ; 07/06/2015 12683 <1> ERR_FILE_EOF equ 16 ; 'end of file !' error 12684 <1> ERR_DEV_VOL_SIZE equ 16 ; 'out of volume' error 12685 <1> ; 09/06/2015 12686 <1> ERR_DRV_READ equ 17 ; 'disk read error !' 12687 <1> ERR_DRV_WRITE equ 18 ; 'disk write error !' 12688 <1> ; 16/06/2015 12689 <1> ERR_NOT_DIR equ 19 ; 'not a (valid) directory !' error 12690 <1> ERR_FILE_SIZE equ 20 ; 'file size error !' 12691 <1> ; 22/06/2015 12692 <1> ERR_NOT_SUPERUSER equ 11 ; 'permission denied !' error 12693 <1> ERR_NOT_OWNER equ 11 ; 'permission denied !' error 12694 <1> ERR_NOT_FILE equ 11 ; 'permission denied !' error 12695 <1> ; 23/06/2015 12696 <1> ERR_FILE_EXISTS equ 14 ; 'file already exists !' error 12697 <1> ERR_DRV_NOT_SAME equ 21 ; 'not same drive !' error 12698 <1> ERR_DIR_NOT_FOUND equ 12 ; 'directory not found !' error 12699 <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error 12700 <1> ; 27/06/2015 12701 <1> ERR_INV_PARAMETER equ 23 ; 'invalid parameter !' error 12702 <1> ERR_INV_DEV_NAME equ 24 ; 'invalid device name !' error 12703 <1> ; 29/06/2015 12704 <1> ERR_TIME_OUT equ 25 ; 'time out !' error 12705 <1> ERR_DEV_NOT_RESP equ 25 ; 'device not responding !' error 12706 <1> 12707 <1> ; 26/08/2015 12708 <1> ; 24/07/2015 12709 <1> ; 24/06/2015 12710 <1> MAX_ARG_LEN equ 256 ; max. length of sys exec arguments 12711 <1> ; 01/07/2015 12712 <1> MAX_MSG_LEN equ 255 ; max. msg length for 'sysmsg' 12713 <1> ; 12714 %include 'u0.s' ; 15/03/2015 12715 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS0.INC 12716 <1> ; Last Modification: 20/11/2015 12717 <1> ; ---------------------------------------------------------------------------- 12718 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 12719 <1> ; (v0.1 - Beginning: 11/07/2012) 12720 <1> ; 12721 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 12722 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 12723 <1> ; 12724 <1> ; 12725 <1> ; 12726 <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s 12727 <1> ; 12728 <1> ; **************************************************************************** 12729 <1> 12730 <1> sys_init: 12731 <1> ; 18/10/2015 12732 <1> ; 28/08/2015 12733 <1> ; 24/08/2015 12734 <1> ; 14/08/2015 12735 <1> ; 24/07/2015 12736 <1> ; 02/07/2015 12737 <1> ; 01/07/2015 12738 <1> ; 23/06/2015 12739 <1> ; 15/04/2015 12740 <1> ; 13/04/2015 12741 <1> ; 11/03/2015 (Retro UNIX 386 v1 - Beginning) 12742 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 12743 <1> ; 12744 <1> ;call ldrv_init ; Logical drive description tables initialization 12745 <1> ; 12746 <1> ; 14/02/2014 12747 <1> ; 14/07/2013 12748 000037E1 66B82900 <1> mov ax, 41 12749 000037E5 66A3[38740000] <1> mov [rootdir], ax 12750 000037EB 66A3[4C740000] <1> mov [u.cdir], ax 12751 000037F1 2401 <1> and al, 1 ; 15/04/2015 12752 000037F3 A2[97740000] <1> mov [u.uno], al 12753 000037F8 66A3[36740000] <1> mov [mpid], ax 12754 000037FE 66A3[36710000] <1> mov [p.pid], ax 12755 00003804 A2[C6710000] <1> mov [p.stat], al ; SRUN, 05/02/2014 12756 <1> ; 12757 00003809 B004 <1> mov al, time_count ; 30/08/2013 12758 0000380B A2[8A740000] <1> mov [u.quant], al ; 14/07/2013 12759 <1> ; 02/07/2015 12760 00003810 A1[68700000] <1> mov eax, [k_page_dir] 12761 <1> ;sub eax, eax 12762 00003815 A3[A1740000] <1> mov [u.pgdir], eax ; reset 12763 <1> ; 18/10/2015 12764 <1> ;mov [u.ppgdir], eax ; 0 12765 <1> ; 12766 0000381A E856030000 <1> call epoch 12767 0000381F A3[94820000] <1> mov [s.time], eax ; 13/03/2015 12768 <1> ; 17/07/2013 12769 00003824 E8B0060000 <1> call bf_init ; buffer initialization 12770 <1> ; 23/06/2015 12771 00003829 E8C7F7FFFF <1> call allocate_page 12772 <1> ;;jc error 12773 0000382E 0F829C000000 <1> jc panic ; jc short panic (01/07/2015) 12774 00003834 A3[98740000] <1> mov [u.upage], eax ; user structure page 12775 00003839 A3[D6710000] <1> mov [p.upage], eax 12776 <1> ; 12777 0000383E E82CF8FFFF <1> call clear_page 12778 <1> ; 12779 <1> ; 14/08/2015 12780 00003843 FA <1> cli 12781 <1> ; 14/03/2015 12782 <1> ; 17/01/2014 12783 00003844 E8DE010000 <1> call sp_init ; serial port initialization 12784 <1> ; 14/08/2015 12785 00003849 FB <1> sti 12786 <1> ; 12787 <1> ; 30/06/2015 12788 <1> ;mov esi, kernel_init_ok_msg 12789 <1> ;call print_msg 12790 <1> ; 12791 0000384A 30DB <1> xor bl, bl ; video page 0 12792 <1> vp_clr_nxt: ; clear video pages (reset cursor positions) 12793 0000384C E8052E0000 <1> call vp_clr ; 17/07/2013 12794 00003851 FEC3 <1> inc bl 12795 00003853 80FB08 <1> cmp bl, 8 12796 00003856 72F4 <1> jb short vp_clr_nxt 12797 <1> ; 12798 <1> ; 24/07/2015 12799 <1> ;push KDATA 12800 <1> ;push esp 12801 <1> ;mov [tss.esp0], esp 12802 <1> ;mov word [tss.ss0], KDATA 12803 <1> ; 12804 <1> ; 24/08/2015 12805 <1> ;; temporary (01/07/2015) 12806 00003858 C605[8A740000]04 <1> mov byte [u.quant], time_count ; 4 12807 <1> ; it is not needed here ! 12808 <1> ;;inc byte [u.kcall] ; 'the caller is kernel' sign 12809 0000385F FE0D[3F740000] <1> dec byte [sysflg] ; FFh = ready for system call 12810 <1> ; 0 = executing a system call 12811 <1> ;;sys _msg, kernel_init_ok_msg, 255, 0 12812 <1> ; 12813 <1> ;;; 06/08/2015 12814 <1> ;;;call getch ; wait for a key stroke 12815 <1> ;;mov ecx, 0FFFFFFFh 12816 <1> ;;sys_init_msg_wait: 12817 <1> ;; push ecx 12818 <1> ;; mov al, 1 12819 <1> ;; mov ah, [ptty] ; active (current) video page 12820 <1> ;; call getc_n 12821 <1> ;; pop ecx 12822 <1> ;; jnz short sys_init_msg_ok 12823 <1> ;; loop sys_init_msg_wait 12824 <1> ; 12825 <1> ;;sys_init_msg_ok: 12826 <1> ; 28/08/2015 (initial settings for the 1st 'rswap') 12827 00003865 6A10 <1> push KDATA ; ss 12828 00003867 54 <1> push esp 12829 00003868 9C <1> pushfd 12830 00003869 6A08 <1> push KCODE ; cs 12831 0000386B 68[9F380000] <1> push init_exec ; eip 12832 00003870 8925[40740000] <1> mov [u.sp], esp 12833 00003876 1E <1> push ds 12834 00003877 06 <1> push es 12835 00003878 0FA0 <1> push fs 12836 0000387A 0FA8 <1> push gs 12837 0000387C 60 <1> pushad 12838 0000387D 8925[44740000] <1> mov [u.usp], esp 12839 00003883 E8561B0000 <1> call wswap ; save current user (u) structure, user registers 12840 <1> ; and interrupt return components (for IRET) 12841 00003888 61 <1> popad 12842 00003889 6658 <1> pop ax ; gs 12843 0000388B 6658 <1> pop ax ; fs 12844 0000388D 6658 <1> pop ax ; es 12845 0000388F 6658 <1> pop ax ; ds 12846 00003891 58 <1> pop eax ; eip (init_exec) 12847 00003892 6658 <1> pop ax ; cs (KCODE) 12848 00003894 58 <1> pop eax ; E-FLAGS 12849 00003895 58 <1> pop eax ; esp 12850 00003896 6658 <1> pop ax ; ss (KDATA) 12851 <1> ; 12852 00003898 31C0 <1> xor eax, eax ; 0 12853 0000389A A3[A5740000] <1> mov [u.ppgdir], eax ; reset (to zero) for '/etc/init' 12854 <1> ; 12855 <1> ; 02/07/2015 12856 <1> ; [u.pgdir ] = [k_page_dir] 12857 <1> ; [u.ppgdir] = 0 (page dir of the parent process) 12858 <1> ; (The caller is os kernel sign for 'sysexec') 12859 <1> init_exec: 12860 <1> ; 13/03/2013 12861 <1> ; 24/07/2013 12862 0000389F BB[C6380000] <1> mov ebx, init_file 12863 000038A4 B9[BE380000] <1> mov ecx, init_argp 12864 <1> ; EBX contains 'etc/init' asciiz file name address 12865 <1> ; ECX contains address of argument list pointer 12866 <1> ; 12867 <1> ;dec byte [sysflg] ; FFh = ready for system call 12868 <1> ; 0 = executing a system call 12869 <1> sys _exec ; execute file 12870 <2> 12871 <2> 12872 000038A9 B80B000000 <2> mov eax, %1 12873 <2> %if %0 >= 2 12874 <2> mov ebx, %2 12875 <2> %if %0 >= 3 12876 <2> mov ecx, %3 12877 <2> %if %0 = 4 12878 <2> mov edx, %4 12879 <2> %endif 12880 <2> %endif 12881 <2> %endif 12882 000038AE CD30 <2> int 30h 12883 000038B0 731E <1> jnc short panic 12884 <1> ; 12885 000038B2 BE[786D0000] <1> mov esi, etc_init_err_msg 12886 000038B7 E837000000 <1> call print_msg 12887 000038BC EB1C <1> jmp short key_to_reboot 12888 <1> 12889 <1> ;align 4 12890 <1> init_argp: 12891 000038BE [C6380000]00000000 <1> dd init_file, 0 ; 23/06/2015 (dw -> dd) 12892 <1> init_file: 12893 <1> ; 24/08/2015 12894 000038C6 2F6574632F696E6974- <1> db '/etc/init', 0 12895 000038CF 00 <1> 12896 <1> panic: 12897 <1> ; 13/03/2015 (Retro UNIX 386 v1) 12898 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 12899 000038D0 BE[5D6D0000] <1> mov esi, panic_msg 12900 000038D5 E819000000 <1> call print_msg 12901 <1> key_to_reboot: 12902 <1> ; 15/11/2015 12903 000038DA E8B52B0000 <1> call getch 12904 <1> ; wait for a character from the current tty 12905 <1> ; 12906 000038DF B00A <1> mov al, 0Ah 12907 000038E1 8A1D[96700000] <1> mov bl, [ptty] ; [active_page] 12908 000038E7 B407 <1> mov ah, 07h ; Black background, 12909 <1> ; light gray forecolor 12910 000038E9 E8ECDBFFFF <1> call write_tty 12911 000038EE E96CD8FFFF <1> jmp cpu_reset 12912 <1> 12913 <1> print_msg: 12914 <1> ; 01/07/2015 12915 <1> ; 13/03/2015 (Retro UNIX 386 v1) 12916 <1> ; 07/03/2014 (Retro UNIX 8086 v1) 12917 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI) 12918 <1> ; 12919 <1> ; 12920 000038F3 AC <1> lodsb 12921 <1> pmsg1: 12922 000038F4 56 <1> push esi 12923 000038F5 0FB61D[96700000] <1> movzx ebx, byte [ptty] 12924 000038FC B407 <1> mov ah, 07h ; Black background, light gray forecolor 12925 000038FE E8D7DBFFFF <1> call write_tty 12926 00003903 5E <1> pop esi 12927 00003904 AC <1> lodsb 12928 00003905 20C0 <1> and al, al 12929 00003907 75EB <1> jnz short pmsg1 12930 00003909 C3 <1> retn 12931 <1> 12932 <1> ctrlbrk: 12933 <1> ; 12/11/2015 12934 <1> ; 13/03/2015 (Retro UNIX 386 v1) 12935 <1> ; 06/12/2013 (Retro UNIX 8086 v1) 12936 <1> ; 12937 <1> ; INT 1Bh (control+break) handler 12938 <1> ; 12939 <1> ; Retro Unix 8086 v1 feature only! 12940 <1> ; 12941 0000390A 66833D[8C740000]00 <1> cmp word [u.intr], 0 12942 00003912 7645 <1> jna short cbrk4 12943 <1> cbrk0: 12944 <1> ; 12/11/2015 12945 <1> ; 06/12/2013 12946 00003914 66833D[8E740000]00 <1> cmp word [u.quit], 0 12947 0000391C 743B <1> jz short cbrk4 12948 <1> ; 12949 <1> ; 20/09/2013 12950 0000391E 6650 <1> push ax 12951 00003920 A0[96700000] <1> mov al, [ptty] 12952 <1> ; 12953 <1> ; 12/11/2015 12954 <1> ; 12955 <1> ; ctrl+break (EOT, CTRL+D) from serial port 12956 <1> ; or ctrl+break from console (pseudo) tty 12957 <1> ; (!redirection!) 12958 <1> ; 12959 00003925 3C08 <1> cmp al, 8 ; serial port tty nums > 7 12960 00003927 7211 <1> jb short cbrk1 ; console (pseudo) tty 12961 <1> ; 12962 <1> ; Serial port interrupt handler sets [ptty] 12963 <1> ; to the port's tty number (as temporary). 12964 <1> ; 12965 <1> ; If active process is using a stdin or 12966 <1> ; stdout redirection (by the shell), 12967 <1> ; console tty keyboard must be available 12968 <1> ; to terminate running process, 12969 <1> ; in order to prevent a deadlock. 12970 <1> ; 12971 00003929 52 <1> push edx 12972 0000392A 0FB615[97740000] <1> movzx edx, byte [u.uno] 12973 00003931 3A82[95710000] <1> cmp al, [edx+p.ttyc-1] ; console tty (rw) 12974 00003937 5A <1> pop edx 12975 00003938 7412 <1> je short cbrk2 12976 <1> cbrk1: 12977 0000393A FEC0 <1> inc al ; [u.ttyp] : 1 based tty number 12978 <1> ; 06/12/2013 12979 0000393C 3A05[78740000] <1> cmp al, [u.ttyp] ; recent open tty (r) 12980 00003942 7408 <1> je short cbrk2 12981 00003944 3A05[79740000] <1> cmp al, [u.ttyp+1] ; recent open tty (w) 12982 0000394A 750B <1> jne short cbrk3 12983 <1> cbrk2: 12984 <1> ;; 06/12/2013 12985 <1> ;mov ax, [u.quit] 12986 <1> ;and ax, ax 12987 <1> ;jz short cbrk3 12988 <1> ; 12989 0000394C 6631C0 <1> xor ax, ax ; 0 12990 0000394F 6648 <1> dec ax 12991 <1> ; 0FFFFh = 'ctrl+brk' keystroke 12992 00003951 66A3[8E740000] <1> mov [u.quit], ax 12993 <1> cbrk3: 12994 00003957 6658 <1> pop ax 12995 <1> cbrk4: 12996 00003959 C3 <1> retn 12997 <1> 12998 <1> com2_int: 12999 <1> ; 07/11/2015 13000 <1> ; 24/10/2015 13001 <1> ; 23/10/2015 13002 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 13003 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 13004 <1> ; < serial port 2 interrupt handler > 13005 <1> ; 13006 0000395A 890424 <1> mov [esp], eax ; overwrite call return address 13007 <1> ;push eax 13008 0000395D 66B80900 <1> mov ax, 9 13009 00003961 EB07 <1> jmp short comm_int 13010 <1> com1_int: 13011 <1> ; 07/11/2015 13012 <1> ; 24/10/2015 13013 00003963 890424 <1> mov [esp], eax ; overwrite call return address 13014 <1> ; 23/10/2015 13015 <1> ;push eax 13016 00003966 66B80800 <1> mov ax, 8 13017 <1> comm_int: 13018 <1> ; 20/11/2015 13019 <1> ; 18/11/2015 13020 <1> ; 17/11/2015 13021 <1> ; 16/11/2015 13022 <1> ; 09/11/2015 13023 <1> ; 08/11/2015 13024 <1> ; 07/11/2015 13025 <1> ; 06/11/2015 (serial4.asm, 'serial') 13026 <1> ; 01/11/2015 13027 <1> ; 26/10/2015 13028 <1> ; 23/10/2015 13029 0000396A 53 <1> push ebx 13030 0000396B 56 <1> push esi 13031 0000396C 57 <1> push edi 13032 0000396D 1E <1> push ds 13033 0000396E 06 <1> push es 13034 <1> ; 18/11/2015 13035 0000396F 0F20DB <1> mov ebx, cr3 13036 00003972 53 <1> push ebx ; **** 13037 <1> ; 13038 00003973 51 <1> push ecx ; *** 13039 00003974 52 <1> push edx ; ** 13040 <1> ; 13041 00003975 BB10000000 <1> mov ebx, KDATA 13042 0000397A 8EDB <1> mov ds, bx 13043 0000397C 8EC3 <1> mov es, bx 13044 <1> ; 13045 0000397E 8B0D[68700000] <1> mov ecx, [k_page_dir] 13046 00003984 0F22D9 <1> mov cr3, ecx 13047 <1> ; 20/11/2015 13048 <1> ; Interrupt identification register 13049 00003987 66BAFA02 <1> mov dx, 2FAh ; COM2 13050 <1> ; 13051 0000398B 3C08 <1> cmp al, 8 13052 0000398D 7702 <1> ja short com_i0 13053 <1> ; 13054 <1> ; 20/11/2015 13055 <1> ; 17/11/2015 13056 <1> ; 16/11/2015 13057 <1> ; 15/11/2015 13058 <1> ; 24/10/2015 13059 <1> ; 14/03/2015 (Retro UNIX 386 v1 - Beginning) 13060 <1> ; 28/07/2014 (Retro UNIX 8086 v1) 13061 <1> ; < serial port 1 interrupt handler > 13062 <1> ; 13063 0000398F FEC6 <1> inc dh ; 3FAh ; COM1 Interrupt id. register 13064 <1> com_i0: 13065 <1> ;push eax ; * 13066 <1> ; 07/11/2015 13067 00003991 A2[D6700000] <1> mov byte [ccomport], al 13068 <1> ; 09/11/2015 13069 00003996 0FB7D8 <1> movzx ebx, ax ; 8 or 9 13070 <1> ; 17/11/2015 13071 <1> ; reset request for response status 13072 00003999 88A3[CC700000] <1> mov [ebx+req_resp-8], ah ; 0 13073 <1> ; 13074 <1> ; 20/11/2015 13075 0000399F EC <1> in al, dx ; read interrupt id. register 13076 000039A0 EB00 <1> JMP $+2 ; I/O DELAY 13077 000039A2 2404 <1> and al, 4 ; received data available? 13078 000039A4 7470 <1> jz short com_eoi ; (transmit. holding reg. empty) 13079 <1> ; 13080 <1> ; 20/11/2015 13081 000039A6 80EA02 <1> sub dl, 3FAh-3F8h ; data register (3F8h, 2F8h) 13082 000039A9 EC <1> in al, dx ; read character 13083 <1> ;JMP $+2 ; I/O DELAY 13084 <1> ; 08/11/2015 13085 <1> ; 07/11/2015 13086 000039AA 89DE <1> mov esi, ebx 13087 000039AC 89DF <1> mov edi, ebx 13088 000039AE 81C6[D0700000] <1> add esi, rchar - 8 ; points to last received char 13089 000039B4 81C7[D2700000] <1> add edi, schar - 8 ; points to last sent char 13090 000039BA 8806 <1> mov [esi], al ; received char (current char) 13091 <1> ; query 13092 000039BC 20C0 <1> and al, al 13093 000039BE 7527 <1> jnz short com_i2 13094 <1> ; response 13095 <1> ; 17/11/2015 13096 <1> ; set request for response status 13097 000039C0 FE83[CC700000] <1> inc byte [ebx+req_resp-8] ; 1 13098 <1> ; 13099 000039C6 6683C205 <1> add dx, 3FDh-3F8h ; (3FDh, 2FDh) 13100 000039CA EC <1> in al, dx ; read line status register 13101 000039CB EB00 <1> JMP $+2 ; I/O DELAY 13102 000039CD 2420 <1> and al, 20h ; transmitter holding reg. empty? 13103 000039CF 7445 <1> jz short com_eoi ; no 13104 000039D1 B0FF <1> mov al, 0FFh ; response 13105 000039D3 6683EA05 <1> sub dx, 3FDh-3F8h ; data port (3F8h, 2F8h) 13106 000039D7 EE <1> out dx, al ; send on serial port 13107 <1> ; 17/11/2015 13108 000039D8 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 13109 000039DB 7502 <1> jne short com_i1 ; no 13110 000039DD 8807 <1> mov [edi], al ; 0FFh (responded) 13111 <1> com_i1: 13112 <1> ; 17/11/2015 13113 <1> ; reset request for response status (again) 13114 000039DF FE8B[CC700000] <1> dec byte [ebx+req_resp-8] ; 0 13115 000039E5 EB2F <1> jmp short com_eoi 13116 <1> com_i2: 13117 <1> ; 08/11/2015 13118 000039E7 3CFF <1> cmp al, 0FFh ; (response ?) 13119 000039E9 7417 <1> je short com_i3 ; (check for response signal) 13120 <1> ; 07/11/2015 13121 000039EB 3C04 <1> cmp al, 04h ; EOT 13122 000039ED 751C <1> jne short com_i4 13123 <1> ; EOT = 04h (End of Transmit) - 'CTRL + D' 13124 <1> ;(an EOT char is supposed as a ctrl+brk from the terminal) 13125 <1> ; 08/11/2015 13126 <1> ; ptty -> tty 0 to 7 (pseudo screens) 13127 000039EF 861D[96700000] <1> xchg bl, [ptty] ; tty number (8 or 9) 13128 000039F5 E810FFFFFF <1> call ctrlbrk 13129 000039FA 861D[96700000] <1> xchg [ptty], bl ; (restore ptty value and BL value) 13130 <1> ;mov al, 04h ; EOT 13131 <1> ; 08/11/2015 13132 00003A00 EB09 <1> jmp short com_i4 13133 <1> com_i3: 13134 <1> ; 08/11/2015 13135 <1> ; If 0FFh has been received just after a query 13136 <1> ; (schar, ZERO), it is a response signal. 13137 <1> ; 17/11/2015 13138 00003A02 803F00 <1> cmp byte [edi], 0 ; query ? (schar) 13139 00003A05 7704 <1> ja short com_i4 ; no 13140 <1> ; reset query status (schar) 13141 00003A07 8807 <1> mov [edi], al ; 0FFh 13142 00003A09 FEC0 <1> inc al ; 0 13143 <1> com_i4: 13144 <1> ; 27/07/2014 13145 <1> ; 09/07/2014 13146 00003A0B D0E3 <1> shl bl, 1 13147 00003A0D 81C3[98700000] <1> add ebx, ttychr 13148 <1> ; 23/07/2014 (always overwrite) 13149 <1> ;;cmp word [ebx], 0 13150 <1> ;;ja short com_eoi 13151 <1> ; 13152 00003A13 668903 <1> mov [ebx], ax ; Save ascii code 13153 <1> ; scan code = 0 13154 <1> com_eoi: 13155 <1> ;mov al, 20h 13156 <1> ;out 20h, al ; end of interrupt 13157 <1> ; 13158 <1> ; 07/11/2015 13159 <1> ;pop eax ; * 13160 00003A16 A0[D6700000] <1> mov al, byte [ccomport] ; current COM port 13161 <1> ; al = tty number (8 or 9) 13162 00003A1B E8991A0000 <1> call wakeup 13163 <1> com_iret: 13164 <1> ; 23/10/2015 13165 00003A20 5A <1> pop edx ; ** 13166 00003A21 59 <1> pop ecx ; *** 13167 <1> ; 18/11/2015 13168 <1> ;pop eax ; **** 13169 <1> ;mov cr3, eax 13170 <1> ;jmp iiret 13171 00003A22 E94AD0FFFF <1> jmp iiretp 13172 <1> 13173 <1> ;iiretp: ; 01/09/2015 13174 <1> ; ; 28/08/2015 13175 <1> ; pop eax ; (*) page directory 13176 <1> ; mov cr3, eax 13177 <1> ;iiret: 13178 <1> ; ; 22/08/2014 13179 <1> ; mov al, 20h ; END OF INTERRUPT COMMAND TO 8259 13180 <1> ; out 20h, al ; 8259 PORT 13181 <1> ; ; 13182 <1> ; pop es 13183 <1> ; pop ds 13184 <1> ; pop edi 13185 <1> ; pop esi 13186 <1> ; pop ebx ; 29/08/2014 13187 <1> ; pop eax 13188 <1> ; iretd 13189 <1> 13190 <1> sp_init: 13191 <1> ; 07/11/2015 13192 <1> ; 29/10/2015 13193 <1> ; 26/10/2015 13194 <1> ; 23/10/2015 13195 <1> ; 29/06/2015 13196 <1> ; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud) 13197 <1> ; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud) 13198 <1> ; Initialization of Serial Port Communication Parameters 13199 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 13200 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 13201 <1> ; 13202 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 13203 <1> ; 13204 <1> ; INPUT: (29/06/2015) 13205 <1> ; AL = 0 for COM1 13206 <1> ; 1 for COM2 13207 <1> ; AH = Communication parameters 13208 <1> ; 13209 <1> ; (*) Communication parameters (except BAUD RATE): 13210 <1> ; Bit 4 3 2 1 0 13211 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 13212 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 13213 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 13214 <1> ; 11 = even 13215 <1> ; Baud rate setting bits: (29/06/2015) 13216 <1> ; Retro UNIX 386 v1 feature only ! 13217 <1> ; Bit 7 6 5 | Baud rate 13218 <1> ; ------------------------ 13219 <1> ; value 0 0 0 | Default (Divisor = 1) 13220 <1> ; 0 0 1 | 9600 (12) 13221 <1> ; 0 1 0 | 19200 (6) 13222 <1> ; 0 1 1 | 38400 (3) 13223 <1> ; 1 0 0 | 14400 (8) 13224 <1> ; 1 0 1 | 28800 (4) 13225 <1> ; 1 1 0 | 57600 (2) 13226 <1> ; 1 1 1 | 115200 (1) 13227 <1> 13228 <1> ; References: 13229 <1> ; (1) IBM PC-XT Model 286 BIOS Source Code 13230 <1> ; RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232) 13231 <1> ; (2) Award BIOS 1999 - ATORGS.ASM 13232 <1> ; (3) http://wiki.osdev.org/Serial_Ports 13233 <1> ; 13234 <1> ; Set communication parameters for COM1 (= 03h) 13235 <1> ; 13236 00003A27 BB[D2700000] <1> mov ebx, com1p ; COM1 parameters 13237 00003A2C 66BAF803 <1> mov dx, 3F8h ; COM1 13238 <1> ; 29/10/2015 13239 00003A30 66B90103 <1> mov cx, 301h ; divisor = 1 (115200 baud) 13240 00003A34 E86F000000 <1> call sp_i3 ; call A4 13241 00003A39 A880 <1> test al, 80h 13242 00003A3B 7410 <1> jz short sp_i0 ; OK.. 13243 <1> ; Error ! 13244 <1> ;mov dx, 3F8h 13245 00003A3D 80EA05 <1> sub dl, 5 ; 3FDh -> 3F8h 13246 00003A40 66B90E03 <1> mov cx, 30Eh ; divisor = 12 (9600 baud) 13247 00003A44 E85F000000 <1> call sp_i3 ; call A4 13248 00003A49 A880 <1> test al, 80h 13249 00003A4B 7508 <1> jnz short sp_i1 13250 <1> sp_i0: 13251 <1> ; (Note: Serial port interrupts will be disabled here...) 13252 <1> ; (INT 14h initialization code disables interrupts.) 13253 <1> ; 13254 00003A4D C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 13255 00003A50 E8DC000000 <1> call sp_i5 ; 29/06/2015 13256 <1> sp_i1: 13257 00003A55 43 <1> inc ebx 13258 00003A56 66BAF802 <1> mov dx, 2F8h ; COM2 13259 <1> ; 29/10/2015 13260 00003A5A 66B90103 <1> mov cx, 301h ; divisor = 1 (115200 baud) 13261 00003A5E E845000000 <1> call sp_i3 ; call A4 13262 00003A63 A880 <1> test al, 80h 13263 00003A65 7410 <1> jz short sp_i2 ; OK.. 13264 <1> ; Error ! 13265 <1> ;mov dx, 2F8h 13266 00003A67 80EA05 <1> sub dl, 5 ; 2FDh -> 2F8h 13267 00003A6A 66B90E03 <1> mov cx, 30Eh ; divisor = 12 (9600 baud) 13268 00003A6E E835000000 <1> call sp_i3 ; call A4 13269 00003A73 A880 <1> test al, 80h 13270 00003A75 7530 <1> jnz short sp_i7 13271 <1> sp_i2: 13272 00003A77 C603E3 <1> mov byte [ebx], 0E3h ; 11100011b 13273 <1> sp_i6: 13274 <1> ;; COM2 - enabling IRQ 3 13275 <1> ; 07/11/2015 13276 <1> ; 26/10/2015 13277 00003A7A 9C <1> pushf 13278 00003A7B FA <1> cli 13279 <1> ; 13280 00003A7C 66BAFC02 <1> mov dx, 2FCh ; modem control register 13281 00003A80 EC <1> in al, dx ; read register 13282 00003A81 EB00 <1> JMP $+2 ; I/O DELAY 13283 00003A83 0C08 <1> or al, 8 ; enable bit 3 (OUT2) 13284 00003A85 EE <1> out dx, al ; write back to register 13285 00003A86 EB00 <1> JMP $+2 ; I/O DELAY 13286 00003A88 66BAF902 <1> mov dx, 2F9h ; interrupt enable register 13287 00003A8C EC <1> in al, dx ; read register 13288 00003A8D EB00 <1> JMP $+2 ; I/O DELAY 13289 <1> ;or al, 1 ; receiver data interrupt enable and 13290 00003A8F 0C03 <1> or al, 3 ; transmitter empty interrupt enable 13291 00003A91 EE <1> out dx, al ; write back to register 13292 00003A92 EB00 <1> JMP $+2 ; I/O DELAY 13293 00003A94 E421 <1> in al, 21h ; read interrupt mask register 13294 00003A96 EB00 <1> JMP $+2 ; I/O DELAY 13295 00003A98 24F7 <1> and al, 0F7h ; enable IRQ 3 (COM2) 13296 00003A9A E621 <1> out 21h, al ; write back to register 13297 <1> ; 13298 <1> ; 23/10/2015 13299 00003A9C B8[5A390000] <1> mov eax, com2_int 13300 00003AA1 A3[393F0000] <1> mov [com2_irq3], eax 13301 <1> ; 26/10/2015 13302 00003AA6 9D <1> popf 13303 <1> sp_i7: 13304 00003AA7 C3 <1> retn 13305 <1> 13306 <1> sp_i3: 13307 <1> ;A4: ;----- INITIALIZE THE COMMUNICATIONS PORT 13308 <1> ; 28/10/2015 13309 00003AA8 FEC2 <1> inc dl ; 3F9h (2F9h) ; 3F9h, COM1 Interrupt enable register 13310 00003AAA B000 <1> mov al, 0 13311 00003AAC EE <1> out dx, al ; disable serial port interrupt 13312 00003AAD EB00 <1> JMP $+2 ; I/O DELAY 13313 00003AAF 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; COM1 Line control register (3FBh) 13314 00003AB2 B080 <1> mov al, 80h 13315 00003AB4 EE <1> out dx, al ; SET DLAB=1 ; divisor latch access bit 13316 <1> ;----- SET BAUD RATE DIVISOR 13317 <1> ; 26/10/2015 13318 00003AB5 80EA03 <1> sub dl, 3 ; 3F8h (2F8h) ; register for least significant byte 13319 <1> ; of the divisor value 13320 00003AB8 88C8 <1> mov al, cl ; 1 13321 00003ABA EE <1> out dx, al ; 1 = 115200 baud (Retro UNIX 386 v1) 13322 <1> ; 2 = 57600 baud 13323 <1> ; 3 = 38400 baud 13324 <1> ; 6 = 19200 baud 13325 <1> ; 12 = 9600 baud (Retro UNIX 8086 v1) 13326 00003ABB EB00 <1> JMP $+2 ; I/O DELAY 13327 00003ABD 28C0 <1> sub al, al 13328 00003ABF FEC2 <1> inc dl ; 3F9h (2F9h) ; register for most significant byte 13329 <1> ; of the divisor value 13330 00003AC1 EE <1> out dx, al ; 0 13331 00003AC2 EB00 <1> JMP $+2 ; I/O DELAY 13332 <1> ; 13333 00003AC4 88E8 <1> mov al, ch ; 3 ; 8 data bits, 1 stop bit, no parity 13334 <1> ;and al, 1Fh ; Bits 0,1,2,3,4 13335 00003AC6 80C202 <1> add dl, 2 ; 3FBh (2FBh) ; Line control register 13336 00003AC9 EE <1> out dx, al 13337 00003ACA EB00 <1> JMP $+2 ; I/O DELAY 13338 <1> ; 29/10/2015 13339 00003ACC FECA <1> dec dl ; 3FAh (2FAh) ; FIFO Control register (16550/16750) 13340 00003ACE 30C0 <1> xor al, al ; 0 13341 00003AD0 EE <1> out dx, al ; Disable FIFOs (reset to 8250 mode) 13342 00003AD1 EB00 <1> JMP $+2 13343 <1> sp_i4: 13344 <1> ;A18: ;----- COMM PORT STATUS ROUTINE 13345 <1> ; 29/06/2015 (line status after modem status) 13346 00003AD3 80C204 <1> add dl, 4 ; 3FEh (2FEh) ; Modem status register 13347 <1> sp_i4s: 13348 00003AD6 EC <1> in al, dx ; GET MODEM CONTROL STATUS 13349 00003AD7 EB00 <1> JMP $+2 ; I/O DELAY 13350 00003AD9 88C4 <1> mov ah, al ; PUT IN (AH) FOR RETURN 13351 00003ADB FECA <1> dec dl ; 3FDh (2FDh) ; POINT TO LINE STATUS REGISTER 13352 <1> ; dx = 3FDh for COM1, 2FDh for COM2 13353 00003ADD EC <1> in al, dx ; GET LINE CONTROL STATUS 13354 <1> ; AL = Line status, AH = Modem status 13355 00003ADE C3 <1> retn 13356 <1> 13357 <1> sp_status: 13358 <1> ; 29/06/2015 13359 <1> ; 27/06/2015 (Retro UNIX 386 v1) 13360 <1> ; Get serial port status 13361 00003ADF 66BAFE03 <1> mov dx, 3FEh ; Modem status register (COM1) 13362 00003AE3 28C6 <1> sub dh, al ; dh = 2 for COM2 (al = 1) 13363 <1> ; dx = 2FEh for COM2 13364 00003AE5 EBEF <1> jmp short sp_i4s 13365 <1> 13366 <1> sp_setp: ; Set serial port communication parameters 13367 <1> ; 07/11/2015 13368 <1> ; 29/10/2015 13369 <1> ; 29/06/2015 13370 <1> ; Retro UNIX 386 v1 feature only ! 13371 <1> ; 13372 <1> ; INPUT: 13373 <1> ; AL = 0 for COM1 13374 <1> ; 1 for COM2 13375 <1> ; AH = Communication parameters (*) 13376 <1> ; OUTPUT: 13377 <1> ; CL = Line status 13378 <1> ; CH = Modem status 13379 <1> ; If cf = 1 -> Error code in [u.error] 13380 <1> ; 'invalid parameter !' 13381 <1> ; or 13382 <1> ; 'device not ready !' error 13383 <1> ; 13384 <1> ; (*) Communication parameters (except BAUD RATE): 13385 <1> ; Bit 4 3 2 1 0 13386 <1> ; -PARITY-- STOP BIT -WORD LENGTH- 13387 <1> ; this one --> 00 = none 0 = 1 bit 11 = 8 bits 13388 <1> ; 01 = odd 1 = 2 bits 10 = 7 bits 13389 <1> ; 11 = even 13390 <1> ; Baud rate setting bits: (29/06/2015) 13391 <1> ; Retro UNIX 386 v1 feature only ! 13392 <1> ; Bit 7 6 5 | Baud rate 13393 <1> ; ------------------------ 13394 <1> ; value 0 0 0 | Default (Divisor = 1) 13395 <1> ; 0 0 1 | 9600 (12) 13396 <1> ; 0 1 0 | 19200 (6) 13397 <1> ; 0 1 1 | 38400 (3) 13398 <1> ; 1 0 0 | 14400 (8) 13399 <1> ; 1 0 1 | 28800 (4) 13400 <1> ; 1 1 0 | 57600 (2) 13401 <1> ; 1 1 1 | 115200 (1) 13402 <1> ; 13403 <1> ; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4) 13404 <1> ; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3) 13405 <1> ; 13406 <1> ; ((Modified registers: EAX, ECX, EDX, EBX)) 13407 <1> ; 13408 00003AE7 66BAF803 <1> mov dx, 3F8h 13409 00003AEB BB[D2700000] <1> mov ebx, com1p ; COM1 control byte offset 13410 00003AF0 3C01 <1> cmp al, 1 13411 00003AF2 776B <1> ja short sp_invp_err 13412 00003AF4 7203 <1> jb short sp_setp1 ; COM1 (AL = 0) 13413 00003AF6 FECE <1> dec dh ; 2F8h 13414 00003AF8 43 <1> inc ebx ; COM2 control byte offset 13415 <1> sp_setp1: 13416 <1> ; 29/10/2015 13417 00003AF9 8823 <1> mov [ebx], ah 13418 00003AFB 0FB6CC <1> movzx ecx, ah 13419 00003AFE C0E905 <1> shr cl, 5 ; -> baud rate index 13420 00003B01 80E41F <1> and ah, 1Fh ; communication parameters except baud rate 13421 00003B04 8A81[6E3B0000] <1> mov al, [ecx+b_div_tbl] 13422 00003B0A 6689C1 <1> mov cx, ax 13423 00003B0D E896FFFFFF <1> call sp_i3 13424 00003B12 6689C1 <1> mov cx, ax ; CL = Line status, CH = Modem status 13425 00003B15 A880 <1> test al, 80h 13426 00003B17 740F <1> jz short sp_setp2 13427 00003B19 C603E3 <1> mov byte [ebx], 0E3h ; Reset to initial value (11100011b) 13428 <1> stp_dnr_err: 13429 00003B1C C705[9D740000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !' 13430 00003B24 0000 <1> 13431 <1> ; CL = Line status, CH = Modem status 13432 00003B26 F9 <1> stc 13433 00003B27 C3 <1> retn 13434 <1> sp_setp2: 13435 00003B28 80FE02 <1> cmp dh, 2 ; COM2 (2F?h) 13436 00003B2B 0F8649FFFFFF <1> jna sp_i6 13437 <1> ; COM1 (3F?h) 13438 <1> sp_i5: 13439 <1> ; 07/11/2015 13440 <1> ; 26/10/2015 13441 <1> ; 29/06/2015 13442 <1> ; 13443 <1> ;; COM1 - enabling IRQ 4 13444 00003B31 9C <1> pushf 13445 00003B32 FA <1> cli 13446 00003B33 66BAFC03 <1> mov dx, 3FCh ; modem control register 13447 00003B37 EC <1> in al, dx ; read register 13448 00003B38 EB00 <1> JMP $+2 ; I/O DELAY 13449 00003B3A 0C08 <1> or al, 8 ; enable bit 3 (OUT2) 13450 00003B3C EE <1> out dx, al ; write back to register 13451 00003B3D EB00 <1> JMP $+2 ; I/O DELAY 13452 00003B3F 66BAF903 <1> mov dx, 3F9h ; interrupt enable register 13453 00003B43 EC <1> in al, dx ; read register 13454 00003B44 EB00 <1> JMP $+2 ; I/O DELAY 13455 <1> ;or al, 1 ; receiver data interrupt enable and 13456 00003B46 0C03 <1> or al, 3 ; transmitter empty interrupt enable 13457 00003B48 EE <1> out dx, al ; write back to register 13458 00003B49 EB00 <1> JMP $+2 ; I/O DELAY 13459 00003B4B E421 <1> in al, 21h ; read interrupt mask register 13460 00003B4D EB00 <1> JMP $+2 ; I/O DELAY 13461 00003B4F 24EF <1> and al, 0EFh ; enable IRQ 4 (COM1) 13462 00003B51 E621 <1> out 21h, al ; write back to register 13463 <1> ; 13464 <1> ; 23/10/2015 13465 00003B53 B8[63390000] <1> mov eax, com1_int 13466 00003B58 A3[353F0000] <1> mov [com1_irq4], eax 13467 <1> ; 26/10/2015 13468 00003B5D 9D <1> popf 13469 00003B5E C3 <1> retn 13470 <1> 13471 <1> sp_invp_err: 13472 00003B5F C705[9D740000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 13473 00003B67 0000 <1> 13474 00003B69 31C9 <1> xor ecx, ecx 13475 00003B6B 49 <1> dec ecx ; 0FFFFh 13476 00003B6C F9 <1> stc 13477 00003B6D C3 <1> retn 13478 <1> 13479 <1> ; 29/10/2015 13480 <1> b_div_tbl: ; Baud rate divisor table (115200/divisor) 13481 00003B6E 010C0603080401 <1> db 1, 12, 6, 3, 8, 4, 1 13482 <1> 13483 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 13484 <1> epoch: 13485 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 13486 <1> ; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM) 13487 <1> ; 'epoch' procedure prototype: 13488 <1> ; UNIXCOPY.ASM, 10/03/2013 13489 <1> ; 14/11/2012 13490 <1> ; unixboot.asm (boot file configuration) 13491 <1> ; version of "epoch" procedure in "unixproc.asm" 13492 <1> ; 21/7/2012 13493 <1> ; 15/7/2012 13494 <1> ; 14/7/2012 13495 <1> ; Erdogan Tan - RETRO UNIX v0.1 13496 <1> ; compute current date and time as UNIX Epoch/Time 13497 <1> ; UNIX Epoch: seconds since 1/1/1970 00:00:00 13498 <1> ; 13499 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 13500 <1> ; 13501 00003B75 E81D010000 <1> call get_rtc_time ; Return Current Time 13502 00003B7A 86E9 <1> xchg ch,cl 13503 00003B7C 66890D[D26D0000] <1> mov [hour], cx 13504 00003B83 86F2 <1> xchg dh,dl 13505 00003B85 668915[D66D0000] <1> mov [second], dx 13506 <1> ; 13507 00003B8C E837010000 <1> call get_rtc_date ; Return Current Date 13508 00003B91 86E9 <1> xchg ch,cl 13509 00003B93 66890D[CC6D0000] <1> mov [year], cx 13510 00003B9A 86F2 <1> xchg dh,dl 13511 00003B9C 668915[CE6D0000] <1> mov [month], dx 13512 <1> ; 13513 00003BA3 66B93030 <1> mov cx, 3030h 13514 <1> ; 13515 00003BA7 A0[D26D0000] <1> mov al, [hour] ; Hour 13516 <1> ; AL <= BCD number) 13517 00003BAC D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13518 <1> ; AH = AL / 10h 13519 <1> ; AL = AL MOD 10h 13520 00003BAE D50A <1> aad ; AX= AH*10+AL 13521 00003BB0 A2[D26D0000] <1> mov [hour], al 13522 00003BB5 A0[D36D0000] <1> mov al, [hour+1] ; Minute 13523 <1> ; AL <= BCD number) 13524 00003BBA D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13525 <1> ; AH = AL / 10h 13526 <1> ; AL = AL MOD 10h 13527 00003BBC D50A <1> aad ; AX= AH*10+AL 13528 00003BBE A2[D46D0000] <1> mov [minute], al 13529 00003BC3 A0[D66D0000] <1> mov al, [second] ; Second 13530 <1> ; AL <= BCD number) 13531 00003BC8 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13532 <1> ; AH = AL / 10h 13533 <1> ; AL = AL MOD 10h 13534 00003BCA D50A <1> aad ; AX= AH*10+AL 13535 00003BCC A2[D66D0000] <1> mov [second], al 13536 00003BD1 66A1[CC6D0000] <1> mov ax, [year] ; Year (century) 13537 00003BD7 6650 <1> push ax 13538 <1> ; AL <= BCD number) 13539 00003BD9 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13540 <1> ; AH = AL / 10h 13541 <1> ; AL = AL MOD 10h 13542 00003BDB D50A <1> aad ; AX= AH*10+AL 13543 00003BDD B464 <1> mov ah, 100 13544 00003BDF F6E4 <1> mul ah 13545 00003BE1 66A3[CC6D0000] <1> mov [year], ax 13546 00003BE7 6658 <1> pop ax 13547 00003BE9 88E0 <1> mov al, ah 13548 <1> ; AL <= BCD number) 13549 00003BEB D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13550 <1> ; AH = AL / 10h 13551 <1> ; AL = AL MOD 10h 13552 00003BED D50A <1> aad ; AX= AH*10+AL 13553 00003BEF 660105[CC6D0000] <1> add [year], ax 13554 00003BF6 A0[CE6D0000] <1> mov al, [month] ; Month 13555 <1> ; AL <= BCD number) 13556 00003BFB D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13557 <1> ; AH = AL / 10h 13558 <1> ; AL = AL MOD 10h 13559 00003BFD D50A <1> aad ; AX= AH*10+AL 13560 00003BFF A2[CE6D0000] <1> mov [month], al 13561 00003C04 A0[CF6D0000] <1> mov al, [month+1] ; Day 13562 <1> ; AL <= BCD number) 13563 00003C09 D410 <1> db 0D4h,10h ; Undocumented inst. AAM 13564 <1> ; AH = AL / 10h 13565 <1> ; AL = AL MOD 10h 13566 00003C0B D50A <1> aad ; AX= AH*10+AL 13567 00003C0D A2[D06D0000] <1> mov [day], al 13568 <1> 13569 <1> convert_to_epoch: 13570 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification) 13571 <1> ; 09/04/2013 (retro UNIX 8086 v1) 13572 <1> ; 13573 <1> ; ((Modified registers: EAX, EDX, EBX)) 13574 <1> ; 13575 <1> ; Derived from DALLAS Semiconductor 13576 <1> ; Application Note 31 (DS1602/DS1603) 13577 <1> ; 6 May 1998 13578 00003C12 29C0 <1> sub eax, eax 13579 00003C14 66A1[CC6D0000] <1> mov ax, [year] 13580 00003C1A 662DB207 <1> sub ax, 1970 13581 00003C1E BA6D010000 <1> mov edx, 365 13582 00003C23 F7E2 <1> mul edx 13583 00003C25 31DB <1> xor ebx, ebx 13584 00003C27 8A1D[CE6D0000] <1> mov bl, [month] 13585 00003C2D FECB <1> dec bl 13586 00003C2F D0E3 <1> shl bl, 1 13587 <1> ;sub edx, edx 13588 00003C31 668B93[D86D0000] <1> mov dx, [EBX+DMonth] 13589 00003C38 8A1D[D06D0000] <1> mov bl, [day] 13590 00003C3E FECB <1> dec bl 13591 00003C40 01D0 <1> add eax, edx 13592 00003C42 01D8 <1> add eax, ebx 13593 <1> ; EAX = days since 1/1/1970 13594 00003C44 668B15[CC6D0000] <1> mov dx, [year] 13595 00003C4B 6681EAB107 <1> sub dx, 1969 13596 00003C50 66D1EA <1> shr dx, 1 13597 00003C53 66D1EA <1> shr dx, 1 13598 <1> ; (year-1969)/4 13599 00003C56 01D0 <1> add eax, edx 13600 <1> ; + leap days since 1/1/1970 13601 00003C58 803D[CE6D0000]02 <1> cmp byte [month], 2 ; if past february 13602 00003C5F 7610 <1> jna short cte1 13603 00003C61 668B15[CC6D0000] <1> mov dx, [year] 13604 00003C68 6683E203 <1> and dx, 3 ; year mod 4 13605 00003C6C 7503 <1> jnz short cte1 13606 <1> ; and if leap year 13607 00003C6E 83C001 <1> add eax, 1 ; add this year's leap day (february 29) 13608 <1> cte1: ; compute seconds since 1/1/1970 13609 00003C71 BA18000000 <1> mov edx, 24 13610 00003C76 F7E2 <1> mul edx 13611 00003C78 8A15[D26D0000] <1> mov dl, [hour] 13612 00003C7E 01D0 <1> add eax, edx 13613 <1> ; EAX = hours since 1/1/1970 00:00:00 13614 <1> ;mov ebx, 60 13615 00003C80 B33C <1> mov bl, 60 13616 00003C82 F7E3 <1> mul ebx 13617 00003C84 8A15[D46D0000] <1> mov dl, [minute] 13618 00003C8A 01D0 <1> add eax, edx 13619 <1> ; EAX = minutes since 1/1/1970 00:00:00 13620 <1> ;mov ebx, 60 13621 00003C8C F7E3 <1> mul ebx 13622 00003C8E 8A15[D66D0000] <1> mov dl, [second] 13623 00003C94 01D0 <1> add eax, edx 13624 <1> ; EAX -> seconds since 1/1/1970 00:00:00 13625 00003C96 C3 <1> retn 13626 <1> 13627 <1> get_rtc_time: 13628 <1> ; 15/03/2015 13629 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 13630 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 13631 <1> ; INT 1Ah 13632 <1> ; (AH) = 02H READ THE REAL TIME CLOCK AND RETURN WITH, : 13633 <1> ; (CH) = HOURS IN BCD (00-23) : 13634 <1> ; (CL) = MINUTES IN BCD (00-59) : 13635 <1> ; (DH) = SECONDS IN BCD (00-59) : 13636 <1> ; (DL) = DAYLIGHT SAVINGS ENABLE (00-01). : 13637 <1> ; 13638 <1> RTC_20: ; GET RTC TIME 13639 00003C97 FA <1> cli 13640 00003C98 E86FCFFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13641 00003C9D 7227 <1> JC short RTC_29 ; EXIT IF ERROR (CY= 1) 13642 <1> 13643 00003C9F B000 <1> MOV AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS 13644 00003CA1 E84ECFFFFF <1> CALL CMOS_READ ; GET SECONDS 13645 00003CA6 88C6 <1> MOV DH,AL ; SAVE 13646 00003CA8 B00B <1> MOV AL,CMOS_REG_B ; ADDRESS ALARM REGISTER 13647 00003CAA E845CFFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 13648 00003CAF 2401 <1> AND AL,00000001B ; MASK FOR VALID DSE BIT 13649 00003CB1 88C2 <1> MOV DL,AL ; SET [DL] TO ZERO FOR NO DSE BIT 13650 00003CB3 B002 <1> MOV AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES 13651 00003CB5 E83ACFFFFF <1> CALL CMOS_READ ; GET MINUTES 13652 00003CBA 88C1 <1> MOV CL,AL ; SAVE 13653 00003CBC B004 <1> MOV AL,CMOS_HOURS ; SET ADDRESS OF HOURS 13654 00003CBE E831CFFFFF <1> CALL CMOS_READ ; GET HOURS 13655 00003CC3 88C5 <1> MOV CH,AL ; SAVE 13656 00003CC5 F8 <1> CLC ; SET CY= 0 13657 <1> RTC_29: 13658 00003CC6 FB <1> sti 13659 00003CC7 C3 <1> RETn ; RETURN WITH RESULT IN CARRY FLAG 13660 <1> 13661 <1> get_rtc_date: 13662 <1> ; 15/03/2015 13663 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 13664 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 13665 <1> ; INT 1Ah 13666 <1> ; (AH) = 04H READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,: 13667 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 13668 <1> ; (CL) = YEAR IN BCD (00-99) : 13669 <1> ; (DH) = MONTH IN BCD (01-12) : 13670 <1> ; (DL) = DAY IN BCD (01-31). 13671 <1> ; 13672 <1> RTC_40: ; GET RTC DATE 13673 00003CC8 FA <1> cli 13674 00003CC9 E83ECFFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13675 00003CCE 7225 <1> JC short RTC_49 ; EXIT IF ERROR (CY= 1) 13676 <1> 13677 00003CD0 B007 <1> MOV AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH 13678 00003CD2 E81DCFFFFF <1> CALL CMOS_READ ; READ DAY OF MONTH 13679 00003CD7 88C2 <1> MOV DL,AL ; SAVE 13680 00003CD9 B008 <1> MOV AL,CMOS_MONTH ; ADDRESS MONTH 13681 00003CDB E814CFFFFF <1> CALL CMOS_READ ; READ MONTH 13682 00003CE0 88C6 <1> MOV DH,AL ; SAVE 13683 00003CE2 B009 <1> MOV AL,CMOS_YEAR ; ADDRESS YEAR 13684 00003CE4 E80BCFFFFF <1> CALL CMOS_READ ; READ YEAR 13685 00003CE9 88C1 <1> MOV CL,AL ; SAVE 13686 00003CEB B032 <1> MOV AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION 13687 00003CED E802CFFFFF <1> CALL CMOS_READ ; GET CENTURY BYTE 13688 00003CF2 88C5 <1> MOV CH,AL ; SAVE 13689 00003CF4 F8 <1> CLC ; SET CY=0 13690 <1> RTC_49: 13691 00003CF5 FB <1> sti 13692 00003CF6 C3 <1> RETn ; RETURN WITH RESULTS IN CARRY FLAG 13693 <1> 13694 <1> set_date_time: 13695 <1> convert_from_epoch: 13696 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 13697 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 13698 <1> ; 'convert_from_epoch' procedure prototype: 13699 <1> ; UNIXCOPY.ASM, 10/03/2013 13700 <1> ; 13701 <1> ; ((Modified registers: EAX, EDX, ECX, EBX)) 13702 <1> ; 13703 <1> ; Derived from DALLAS Semiconductor 13704 <1> ; Application Note 31 (DS1602/DS1603) 13705 <1> ; 6 May 1998 13706 <1> ; 13707 <1> ; INPUT: 13708 <1> ; EAX = Unix (Epoch) Time 13709 <1> ; 13710 00003CF7 31D2 <1> xor edx, edx 13711 00003CF9 B93C000000 <1> mov ecx, 60 13712 00003CFE F7F1 <1> div ecx 13713 <1> ;mov [imin], eax ; whole minutes 13714 <1> ; since 1/1/1970 13715 00003D00 668915[D66D0000] <1> mov [second], dx ; leftover seconds 13716 00003D07 29D2 <1> sub edx, edx 13717 00003D09 F7F1 <1> div ecx 13718 <1> ;mov [ihrs], eax ; whole hours 13719 <1> ; ; since 1/1/1970 13720 00003D0B 668915[D46D0000] <1> mov [minute], dx ; leftover minutes 13721 00003D12 31D2 <1> xor edx, edx 13722 <1> ;mov cx, 24 13723 00003D14 B118 <1> mov cl, 24 13724 00003D16 F7F1 <1> div ecx 13725 <1> ;mov [iday], ax ; whole days 13726 <1> ; since 1/1/1970 13727 00003D18 668915[D26D0000] <1> mov [hour], dx ; leftover hours 13728 00003D1F 05DB020000 <1> add eax, 365+366 ; whole day since 13729 <1> ; 1/1/1968 13730 <1> ;mov [iday], ax 13731 00003D24 50 <1> push eax 13732 00003D25 29D2 <1> sub edx, edx 13733 00003D27 B9B5050000 <1> mov ecx, (4*365)+1 ; 4 years = 1461 days 13734 00003D2C F7F1 <1> div ecx 13735 00003D2E 59 <1> pop ecx 13736 <1> ;mov [lday], ax ; count of quadyrs (4 years) 13737 00003D2F 6652 <1> push dx 13738 <1> ;mov [qday], dx ; days since quadyr began 13739 00003D31 6683FA3C <1> cmp dx, 31 + 29 ; if past feb 29 then 13740 00003D35 F5 <1> cmc ; add this quadyr's leap day 13741 00003D36 83D000 <1> adc eax, 0 ; to # of qadyrs (leap days) 13742 <1> ;mov [lday], ax ; since 1968 13743 <1> ;mov cx, [iday] 13744 00003D39 91 <1> xchg ecx, eax ; ECX = lday, EAX = iday 13745 00003D3A 29C8 <1> sub eax, ecx ; iday - lday 13746 00003D3C B96D010000 <1> mov ecx, 365 13747 00003D41 31D2 <1> xor edx, edx 13748 <1> ; EAX = iday-lday, EDX = 0 13749 00003D43 F7F1 <1> div ecx 13750 <1> ;mov [iyrs], ax ; whole years since 1968 13751 <1> ;jday = iday - (iyrs*365) - lday 13752 <1> ;mov [jday], dx ; days since 1/1 of current year 13753 <1> ;add eax, 1968 13754 00003D45 6605B007 <1> add ax, 1968 ; compute year 13755 00003D49 66A3[CC6D0000] <1> mov [year], ax 13756 00003D4F 6689D1 <1> mov cx, dx 13757 <1> ;mov dx, [qday] 13758 00003D52 665A <1> pop dx 13759 00003D54 6681FA6D01 <1> cmp dx, 365 ; if qday <= 365 and qday >= 60 13760 00003D59 7709 <1> ja short cfe1 ; jday = jday +1 13761 00003D5B 6683FA3C <1> cmp dx, 60 ; if past 2/29 and leap year then 13762 00003D5F F5 <1> cmc ; add a leap day to the # of whole 13763 00003D60 6683D100 <1> adc cx, 0 ; days since 1/1 of current year 13764 <1> cfe1: 13765 <1> ;mov [jday], cx 13766 00003D64 66BB0C00 <1> mov bx, 12 ; estimate month 13767 00003D68 66BA6E01 <1> mov dx, 366 ; mday, max. days since 1/1 is 365 13768 00003D6C 6683E003 <1> and ax, 11b ; year mod 4 (and dx, 3) 13769 <1> cfe2: ; Month calculation ; 0 to 11 (11 to 0) 13770 00003D70 6639D1 <1> cmp cx, dx ; mday = # of days passed from 1/1 13771 00003D73 731D <1> jnb short cfe3 13772 00003D75 664B <1> dec bx ; month = month - 1 13773 00003D77 66D1E3 <1> shl bx, 1 13774 00003D7A 668B93[D86D0000] <1> mov dx, [EBX+DMonth] ; # elapsed days at 1st of month 13775 00003D81 66D1EB <1> shr bx, 1 ; bx = month - 1 (0 to 11) 13776 00003D84 6683FB01 <1> cmp bx, 1 ; if month > 2 and year mod 4 = 0 13777 00003D88 76E6 <1> jna short cfe2 ; then mday = mday + 1 13778 00003D8A 08C0 <1> or al, al ; if past 2/29 and leap year then 13779 00003D8C 75E2 <1> jnz short cfe2 ; add leap day (to mday) 13780 00003D8E 6642 <1> inc dx ; mday = mday + 1 13781 00003D90 EBDE <1> jmp short cfe2 13782 <1> cfe3: 13783 00003D92 6643 <1> inc bx ; -> bx = month, 1 to 12 13784 00003D94 66891D[CE6D0000] <1> mov [month], bx 13785 00003D9B 6629D1 <1> sub cx, dx ; day = jday - mday + 1 13786 00003D9E 6641 <1> inc cx 13787 00003DA0 66890D[D06D0000] <1> mov [day], cx 13788 <1> 13789 <1> ; eax, ebx, ecx, edx is changed at return 13790 <1> ; output -> 13791 <1> ; [year], [month], [day], [hour], [minute], [second] 13792 <1> 13793 <1> ; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version) 13794 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 13795 <1> set_date: 13796 00003DA7 A0[CD6D0000] <1> mov al, [year+1] 13797 00003DAC D40A <1> aam ; ah = al / 10, al = al mod 10 13798 00003DAE D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13799 <1> ; AL = AH * 10h + AL 13800 00003DB0 88C5 <1> mov ch, al ; century (BCD) 13801 00003DB2 A0[CC6D0000] <1> mov al, [year] 13802 00003DB7 D40A <1> aam ; ah = al / 10, al = al mod 10 13803 00003DB9 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13804 <1> ; AL = AH * 10h + AL 13805 00003DBB 88C1 <1> mov cl, al ; year (BCD) 13806 00003DBD A0[CE6D0000] <1> mov al, [month] 13807 00003DC2 D40A <1> aam ; ah = al / 10, al = al mod 10 13808 00003DC4 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13809 <1> ; AL = AH * 10h + AL 13810 00003DC6 88C6 <1> mov dh, al ; month (BCD) 13811 00003DC8 A0[D06D0000] <1> mov al, [day] 13812 00003DCD D40A <1> aam ; ah = al / 10, al = al mod 10 13813 00003DCF D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13814 <1> ; AL = AH * 10h + AL 13815 00003DD1 88C6 <1> mov dh, al ; day (BCD) 13816 <1> ; Set real-time clock date 13817 00003DD3 E879000000 <1> call set_rtc_date 13818 <1> set_time: 13819 <1> ; Read real-time clock time 13820 <1> ; (get day light saving time bit status) 13821 00003DD8 FA <1> cli 13822 00003DD9 E82ECEFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13823 <1> ; cf = 1 -> al = 0 13824 00003DDE 7207 <1> jc short stime1 13825 00003DE0 B00B <1> MOV AL,CMOS_REG_B ; ADDRESS ALARM REGISTER 13826 00003DE2 E80DCEFFFF <1> CALL CMOS_READ ; READ CURRENT VALUE OF DSE BIT 13827 <1> stime1: 13828 00003DE7 FB <1> sti 13829 00003DE8 2401 <1> AND AL,00000001B ; MASK FOR VALID DSE BIT 13830 00003DEA 88C2 <1> MOV DL,AL ; SET [DL] TO ZERO FOR NO DSE BIT 13831 <1> ; DL = 1 or 0 (day light saving time) 13832 <1> ; 13833 00003DEC A0[D26D0000] <1> mov al, [hour] 13834 00003DF1 D40A <1> aam ; ah = al / 10, al = al mod 10 13835 00003DF3 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13836 <1> ; AL = AH * 10h + AL 13837 00003DF5 88C5 <1> mov ch, al ; hour (BCD) 13838 00003DF7 A0[D46D0000] <1> mov al, [minute] 13839 00003DFC D40A <1> aam ; ah = al / 10, al = al mod 10 13840 00003DFE D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13841 <1> ; AL = AH * 10h + AL 13842 00003E00 88C1 <1> mov cl, al ; minute (BCD) 13843 00003E02 A0[D66D0000] <1> mov al, [second] 13844 00003E07 D40A <1> aam ; ah = al / 10, al = al mod 10 13845 00003E09 D510 <1> db 0D5h,10h ; Undocumented inst. AAD 13846 <1> ; AL = AH * 10h + AL 13847 00003E0B 88C6 <1> mov dh, al ; second (BCD) 13848 <1> ; Set real-time clock time 13849 <1> ; call set_rtc_time 13850 <1> set_rtc_time: 13851 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 13852 <1> ; 15/03/2015 13853 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 13854 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 13855 <1> ; INT 1Ah 13856 <1> ; (AH) = 03H SET THE REAL TIME CLOCK USING, : 13857 <1> ; (CH) = HOURS IN BCD (00-23) : 13858 <1> ; (CL) = MINUTES IN BCD (00-59) : 13859 <1> ; (DH) = SECONDS IN BCD (00-59) : 13860 <1> ; (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00. : 13861 <1> ; : 13862 <1> ; NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. : 13863 <1> ; (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN : 13864 <1> ; APRIL (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN : 13865 <1> ; OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME. : 13866 <1> ; 13867 <1> RTC_30: ; SET RTC TIME 13868 00003E0D FA <1> cli 13869 00003E0E E8F9CDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13870 00003E13 7305 <1> JNC short RTC_35 ; GO AROUND IF CLOCK OPERATING 13871 00003E15 E886000000 <1> CALL RTC_STA ; ELSE TRY INITIALIZING CLOCK 13872 <1> RTC_35: 13873 00003E1A 88F4 <1> MOV AH,DH ; GET TIME BYTE - SECONDS 13874 00003E1C B000 <1> MOV AL,CMOS_SECONDS ; ADDRESS SECONDS 13875 00003E1E E89E000000 <1> CALL CMOS_WRITE ; UPDATE SECONDS 13876 00003E23 88CC <1> MOV AH,CL ; GET TIME BYTE - MINUTES 13877 00003E25 B002 <1> MOV AL,CMOS_MINUTES ; ADDRESS MINUTES 13878 00003E27 E895000000 <1> CALL CMOS_WRITE ; UPDATE MINUTES 13879 00003E2C 88EC <1> MOV AH,CH ; GET TIME BYTE - HOURS 13880 00003E2E B004 <1> MOV AL,CMOS_HOURS ; ADDRESS HOURS 13881 00003E30 E88C000000 <1> CALL CMOS_WRITE ; UPDATE ADDRESS 13882 <1> ;MOV AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER 13883 00003E35 66B80B0B <1> MOV AX,257*CMOS_REG_B ; 13884 00003E39 E8B6CDFFFF <1> CALL CMOS_READ ; READ CURRENT TIME 13885 00003E3E 2462 <1> AND AL,01100010B ; MASK FOR VALID BIT POSITIONS 13886 00003E40 0C02 <1> OR AL,00000010B ; TURN ON 24 HOUR MODE 13887 00003E42 80E201 <1> AND DL,00000001B ; USE ONLY THE DSE BIT 13888 00003E45 08D0 <1> OR AL,DL ; GET DAY LIGHT SAVINGS TIME BIT (OSE) 13889 00003E47 86E0 <1> XCHG AH,AL ; PLACE IN WORK REGISTER AND GET ADDRESS 13890 00003E49 E873000000 <1> CALL CMOS_WRITE ; SET NEW ALARM BITS 13891 00003E4E F8 <1> CLC ; SET CY= 0 13892 00003E4F FB <1> sti 13893 00003E50 C3 <1> RETn ; RETURN WITH CY= 0 13894 <1> 13895 <1> set_rtc_date: 13896 <1> ; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1) 13897 <1> ; 15/03/2015 13898 <1> ; Derived from IBM PC-XT Model 286 BIOS Source Code 13899 <1> ; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES 13900 <1> ; INT 1Ah 13901 <1> ; (AH) = 05H SET THE DATE INTO THE REAL TIME CLOCK USING, : 13902 <1> ; (CH) = CENTURY IN BCD (19 OR 20) : 13903 <1> ; (CL) = YEAR IN BCD (00-99) : 13904 <1> ; (DH) = MONTH IN BCD (01-12) : 13905 <1> ; (DL) = DAY IN BCD (01-31). 13906 <1> ; 13907 <1> RTC_50: ; SET RTC DATE 13908 00003E51 FA <1> cli 13909 00003E52 E8B5CDFFFF <1> CALL UPD_IPR ; CHECK FOR UPDATE IN PROCESS 13910 00003E57 7305 <1> JNC short RTC_55 ; GO AROUND IF NO ERROR 13911 00003E59 E842000000 <1> CALL RTC_STA ; ELSE INITIALIZE CLOCK 13912 <1> RTC_55: 13913 00003E5E 66B80600 <1> MOV AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE 13914 00003E62 E85A000000 <1> CALL CMOS_WRITE ; LOAD ZEROS TO DAY OF WEEK 13915 00003E67 88D4 <1> MOV AH,DL ; GET DAY OF MONTH BYTE 13916 00003E69 B007 <1> MOV AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE 13917 00003E6B E851000000 <1> CALL CMOS_WRITE ; WRITE OF DAY OF MONTH REGISTER 13918 00003E70 88F4 <1> MOV AH,DH ; GET MONTH 13919 00003E72 B008 <1> MOV AL,CMOS_MONTH ; ADDRESS MONTH BYTE 13920 00003E74 E848000000 <1> CALL CMOS_WRITE ; WRITE MONTH REGISTER 13921 00003E79 88CC <1> MOV AH,CL ; GET YEAR BYTE 13922 00003E7B B009 <1> MOV AL,CMOS_YEAR ; ADDRESS YEAR REGISTER 13923 00003E7D E83F000000 <1> CALL CMOS_WRITE ; WRITE YEAR REGISTER 13924 00003E82 88EC <1> MOV AH,CH ; GET CENTURY BYTE 13925 00003E84 B032 <1> MOV AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE 13926 00003E86 E836000000 <1> CALL CMOS_WRITE ; WRITE CENTURY LOCATION 13927 <1> ;MOV AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER 13928 00003E8B 66B80B0B <1> MOV AX,257*CMOS_REG_B ; 13929 00003E8F E860CDFFFF <1> CALL CMOS_READ ; READ CURRENT SETTINGS 13930 00003E94 247F <1> AND AL,07FH ; CLEAR 'SET BIT' 13931 00003E96 86E0 <1> XCHG AH,AL ; MOVE TO WORK REGISTER 13932 00003E98 E824000000 <1> CALL CMOS_WRITE ; AND START CLOCK UPDATING 13933 00003E9D F8 <1> CLC ; SET CY= 0 13934 00003E9E FB <1> sti 13935 00003E9F C3 <1> RETn ; RETURN CY=0 13936 <1> 13937 <1> ; 15/03/2015 13938 <1> RTC_STA: ; INITIALIZE REAL TIME CLOCK 13939 00003EA0 B426 <1> mov ah, 26h 13940 00003EA2 B00A <1> mov al, CMOS_REG_A ; ADDRESS REGISTER A AND LOAD DATA MASK 13941 00003EA4 E818000000 <1> CALL CMOS_WRITE ; INITIALIZE STATUS REGISTER A 13942 00003EA9 B482 <1> mov ah, 82h 13943 00003EAB B00B <1> mov al, CMOS_REG_B ; SET "SET BIT" FOR CLOCK INITIALIZATION 13944 00003EAD E80F000000 <1> CALL CMOS_WRITE ; AND 24 HOUR MODE TO REGISTER B 13945 00003EB2 B00C <1> MOV AL,CMOS_REG_C ; ADDRESS REGISTER C 13946 00003EB4 E83BCDFFFF <1> CALL CMOS_READ ; READ REGISTER C TO INITIALIZE 13947 00003EB9 B00D <1> MOV AL,CMOS_REG_D ; ADDRESS REGISTER D 13948 00003EBB E834CDFFFF <1> CALL CMOS_READ ; READ REGISTER D TO INITIALIZE 13949 00003EC0 C3 <1> RETn 13950 <1> 13951 <1> ; 15/03/2015 13952 <1> ; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm) 13953 <1> CMOS_WRITE: ; WRITE (AH) TO LOCATION (AL) 13954 00003EC1 9C <1> pushf ; SAVE INTERRUPT ENABLE STATUS AND FLAGS 13955 <1> ;push ax ; SAVE WORK REGISTER VALUES 13956 00003EC2 D0C0 <1> rol al, 1 ; MOVE NMI BIT TO LOW POSITION 13957 00003EC4 F9 <1> stc ; FORCE NMI BIT ON IN CARRY FLAG 13958 00003EC5 D0D8 <1> rcr al, 1 ; HIGH BIT ON TO DISABLE NMI - OLD IN CY 13959 00003EC7 FA <1> cli ; DISABLE INTERRUPTS 13960 00003EC8 E670 <1> out CMOS_PORT, al ; ADDRESS LOCATION AND DISABLE NMI 13961 00003ECA 88E0 <1> mov al, ah ; GET THE DATA BYTE TO WRITE 13962 00003ECC E671 <1> out CMOS_DATA, al ; PLACE IN REQUESTED CMOS LOCATION 13963 00003ECE B01E <1> mov al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION 13964 00003ED0 D0D8 <1> rcr al, 1 ; PUT ORIGINAL NMI MASK BIT INTO ADDRESS 13965 00003ED2 E670 <1> out CMOS_PORT, al ; SET DEFAULT TO READ ONLY REGISTER 13966 00003ED4 90 <1> nop ; I/O DELAY 13967 00003ED5 E471 <1> in al, CMOS_DATA ; OPEN STANDBY LATCH 13968 <1> ;pop ax ; RESTORE WORK REGISTERS 13969 00003ED7 9D <1> popf 13970 00003ED8 C3 <1> RETn 13971 <1> 13972 <1> bf_init: 13973 <1> ; 14/08/2015 13974 <1> ; 02/07/2015 13975 <1> ; 01/07/2015 13976 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 13977 <1> ; Buffer (pointer) initialization ! 13978 <1> ; 13979 <1> ; 17/07/2013 - 24/07/2013 13980 <1> ; Retro UNIX 8086 v1 (U9.ASM) 13981 <1> ; (Retro UNIX 8086 v1 feature only !) 13982 <1> ; 13983 00003ED9 BF[0A740000] <1> mov edi, bufp 13984 00003EDE B8[00810000] <1> mov eax, buffer + (nbuf*520) 13985 00003EE3 29D2 <1> sub edx, edx 13986 00003EE5 FECA <1> dec dl 13987 00003EE7 31C9 <1> xor ecx, ecx 13988 00003EE9 49 <1> dec ecx 13989 <1> bi0: 13990 00003EEA 2D08020000 <1> sub eax, 520 ; 8 header + 512 data 13991 00003EEF AB <1> stosd 13992 00003EF0 89C6 <1> mov esi, eax 13993 00003EF2 8916 <1> mov [esi], edx ; 000000FFh 13994 <1> ; Not a valid device sign 13995 00003EF4 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 13996 <1> ; Not a valid block number sign 13997 00003EF7 3D[D0740000] <1> cmp eax, buffer 13998 00003EFC 77EC <1> ja short bi0 13999 00003EFE B8[00810000] <1> mov eax, sb0 14000 00003F03 AB <1> stosd 14001 00003F04 B8[08830000] <1> mov eax, sb1 14002 00003F09 AB <1> stosd 14003 00003F0A 89C6 <1> mov esi, eax ; offset sb1 14004 00003F0C 8916 <1> mov [esi], edx ; 000000FFh 14005 <1> ; Not a valid device sign 14006 00003F0E 894E04 <1> mov [esi+4], ecx ; 0FFFFFFFFh 14007 <1> ; Not a valid block number sign 14008 <1> ; 14/08/2015 14009 <1> ;call rdev_init 14010 <1> ;retn 14011 <1> 14012 <1> rdev_init: ; root device, super block buffer initialization 14013 <1> ; 14/08/2015 14014 <1> ; Retro UNIX 386 v1 feature only ! 14015 <1> ; 14016 <1> ; NOTE: Disk partitions (file systems), logical 14017 <1> ; drive initialization, partition's start sector etc. 14018 <1> ; will be coded here, later in 'ldrv_init' 14019 <1> 14020 00003F11 0FB605[1A6B0000] <1> movzx eax, byte [boot_drv] 14021 <1> rdi_0: 14022 00003F18 3C80 <1> cmp al, 80h 14023 00003F1A 7202 <1> jb short rdi_1 14024 00003F1C 2C7E <1> sub al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1) 14025 <1> rdi_1: 14026 00003F1E A2[30740000] <1> mov [rdev], al 14027 00003F23 BB[00810000] <1> mov ebx, sb0 ; super block buffer 14028 00003F28 8903 <1> mov [ebx], eax 14029 00003F2A B001 <1> mov al, 1 ; eax = 1 14030 00003F2C 894304 <1> mov [ebx+4], eax ; super block address on disk 14031 00003F2F E838240000 <1> call diskio 14032 00003F34 C3 <1> retn 14033 <1> 14034 <1> ; 23/10/2015 14035 <1> com1_irq4: 14036 00003F35 [3D3F0000] <1> dd dummy_retn 14037 <1> com2_irq3: 14038 00003F39 [3D3F0000] <1> dd dummy_retn 14039 <1> 14040 <1> dummy_retn: 14041 00003F3D C3 <1> retn 14042 %include 'u1.s' ; 10/05/2015 14043 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC 14044 <1> ; Last Modification: 27/12/2015 14045 <1> ; ---------------------------------------------------------------------------- 14046 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 14047 <1> ; (v0.1 - Beginning: 11/07/2012) 14048 <1> ; 14049 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 14050 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 14051 <1> ; 14052 <1> ; 14053 <1> ; 14054 <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s 14055 <1> ; 14056 <1> ; **************************************************************************** 14057 <1> 14058 <1> unkni: ; / used for all system calls 14059 <1> sysent: ; < enter to system call > 14060 <1> ;19/10/2015 14061 <1> ; 21/09/2015 14062 <1> ; 01/07/2015 14063 <1> ; 19/05/2015 14064 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14065 <1> ; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1) 14066 <1> ; 14067 <1> ; 'unkni' or 'sysent' is sytem entry from various traps. 14068 <1> ; The trap type is determined and an indirect jump is made to 14069 <1> ; the appropriate system call handler. If there is a trap inside 14070 <1> ; the system a jump to panic is made. All user registers are saved 14071 <1> ; and u.sp points to the end of the users stack. The sys (trap) 14072 <1> ; instructor is decoded to get the the system code part (see 14073 <1> ; trap instruction in the PDP-11 handbook) and from this 14074 <1> ; the indirect jump address is calculated. If a bad system call is 14075 <1> ; made, i.e., the limits of the jump table are exceeded, 'badsys' 14076 <1> ; is called. If the call is legitimate control passes to the 14077 <1> ; appropriate system routine. 14078 <1> ; 14079 <1> ; Calling sequence: 14080 <1> ; Through a trap caused by any sys call outside the system. 14081 <1> ; Arguments: 14082 <1> ; Arguments of particular system call. 14083 <1> ; ............................................................... 14084 <1> ; 14085 <1> ; Retro UNIX 8086 v1 modification: 14086 <1> ; System call number is in EAX register. 14087 <1> ; 14088 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 14089 <1> ; registers depending of function details. 14090 <1> ; 14091 <1> ; 16/04/2015 14092 00003F3E 368925[40740000] <1> mov [ss:u.sp], esp ; Kernel stack points to return address 14093 <1> ; save user registers 14094 00003F45 1E <1> push ds 14095 00003F46 06 <1> push es 14096 00003F47 0FA0 <1> push fs 14097 00003F49 0FA8 <1> push gs 14098 00003F4B 60 <1> pushad ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi 14099 <1> ; 14100 <1> ; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015 14101 <1> ; (ESPACE is size of space in kernel stack 14102 <1> ; for saving/restoring user registers.) 14103 <1> ; 14104 00003F4C 50 <1> push eax ; 01/07/2015 14105 00003F4D 66B81000 <1> mov ax, KDATA 14106 00003F51 8ED8 <1> mov ds, ax 14107 00003F53 8EC0 <1> mov es, ax 14108 00003F55 8EE0 <1> mov fs, ax 14109 00003F57 8EE8 <1> mov gs, ax 14110 00003F59 A1[68700000] <1> mov eax, [k_page_dir] 14111 00003F5E 0F22D8 <1> mov cr3, eax 14112 00003F61 58 <1> pop eax ; 01/07/2015 14113 <1> ; 19/10/2015 14114 00003F62 FC <1> cld 14115 <1> ; 14116 00003F63 FE05[3F740000] <1> inc byte [sysflg] 14117 <1> ; incb sysflg / indicate a system routine is in progress 14118 00003F69 FB <1> sti ; 18/01/2014 14119 00003F6A 0F8560F9FFFF <1> jnz panic ; 24/05/2013 14120 <1> ; beq 1f 14121 <1> ; jmp panic ; / called if trap inside system 14122 <1> ;1: 14123 <1> ; 16/04/2015 14124 00003F70 A3[48740000] <1> mov [u.r0], eax 14125 00003F75 8925[44740000] <1> mov [u.usp], esp ; kernel stack points to user's registers 14126 <1> ; 14127 <1> ; mov $s.syst+2,clockp 14128 <1> ; mov r0,-(sp) / save user registers 14129 <1> ; mov sp,u.r0 / pointer to bottom of users stack 14130 <1> ; / in u.r0 14131 <1> ; mov r1,-(sp) 14132 <1> ; mov r2,-(sp) 14133 <1> ; mov r3,-(sp) 14134 <1> ; mov r4,-(sp) 14135 <1> ; mov r5,-(sp) 14136 <1> ; mov ac,-(sp) / "accumulator" register for extended 14137 <1> ; / arithmetic unit 14138 <1> ; mov mq,-(sp) / "multiplier quotient" register for the 14139 <1> ; / extended arithmetic unit 14140 <1> ; mov sc,-(sp) / "step count" register for the extended 14141 <1> ; / arithmetic unit 14142 <1> ; mov sp,u.sp / u.sp points to top of users stack 14143 <1> ; mov 18.(sp),r0 / store pc in r0 14144 <1> ; mov -(r0),r0 / sys inst in r0 10400xxx 14145 <1> ; sub $sys,r0 / get xxx code 14146 00003F7B C1E002 <1> shl eax, 2 14147 <1> ; asl r0 / multiply by 2 to jump indirect in bytes 14148 00003F7E 3D94000000 <1> cmp eax, end_of_syscalls - syscalls 14149 <1> ; cmp r0,$2f-1f / limit of table (35) exceeded 14150 <1> ;jnb short badsys 14151 <1> ; bhis badsys / yes, bad system call 14152 00003F83 F5 <1> cmc 14153 00003F84 9C <1> pushf 14154 00003F85 50 <1> push eax 14155 00003F86 8B2D[40740000] <1> mov ebp, [u.sp] ; Kernel stack at the beginning of sys call 14156 00003F8C B0FE <1> mov al, 0FEh ; 11111110b 14157 00003F8E 1400 <1> adc al, 0 ; al = al + cf 14158 00003F90 204508 <1> and [ebp+8], al ; flags (reset carry flag) 14159 <1> ; bic $341,20.(sp) / set users processor priority to 0 14160 <1> ; / and clear carry bit 14161 00003F93 5D <1> pop ebp ; eax 14162 00003F94 9D <1> popf 14163 00003F95 0F8248010000 <1> jc badsys 14164 00003F9B A1[48740000] <1> mov eax, [u.r0] 14165 <1> ; system call registers: EAX, EDX, ECX, EBX, ESI, EDI 14166 00003FA0 FFA5[A63F0000] <1> jmp dword [ebp+syscalls] 14167 <1> ; jmp *1f(r0) / jump indirect thru table of addresses 14168 <1> ; / to proper system routine. 14169 <1> syscalls: ; 1: 14170 <1> ; 21/09/2015 14171 <1> ; 01/07/2015 14172 <1> ; 16/04/2015 (32 bit address modification) 14173 00003FA6 [AD400000] <1> dd sysrele ; / 0 14174 00003FAA [53410000] <1> dd sysexit ; / 1 14175 00003FAE [78420000] <1> dd sysfork ; / 2 14176 00003FB2 [8B430000] <1> dd sysread ; / 3 14177 00003FB6 [A6430000] <1> dd syswrite ; / 4 14178 00003FBA [10440000] <1> dd sysopen ; / 5 14179 00003FBE [4A450000] <1> dd sysclose ; / 6 14180 00003FC2 [FA410000] <1> dd syswait ; / 7 14181 00003FC6 [C0440000] <1> dd syscreat ; / 8 14182 00003FCA [71480000] <1> dd syslink ; / 9 14183 00003FCE [33490000] <1> dd sysunlink ; / 10 14184 00003FD2 [064A0000] <1> dd sysexec ; / 11 14185 00003FD6 [6D500000] <1> dd syschdir ; / 12 14186 00003FDA [51510000] <1> dd systime ; / 13 14187 00003FDE [01450000] <1> dd sysmkdir ; / 14 14188 00003FE2 [BF500000] <1> dd syschmod ; / 15 14189 00003FE6 [21510000] <1> dd syschown ; / 16 14190 00003FEA [84510000] <1> dd sysbreak ; / 17 14191 00003FEE [DE4D0000] <1> dd sysstat ; / 18 14192 00003FF2 [49520000] <1> dd sysseek ; / 19 14193 00003FF6 [5B520000] <1> dd systell ; / 20 14194 00003FFA [585D0000] <1> dd sysmount ; / 21 14195 00003FFE [0A5E0000] <1> dd sysumount ; / 22 14196 00004002 [D9520000] <1> dd syssetuid ; / 23 14197 00004006 [0A530000] <1> dd sysgetuid ; / 24 14198 0000400A [60510000] <1> dd sysstime ; / 25 14199 0000400E [CD520000] <1> dd sysquit ; / 26 14200 00004012 [C1520000] <1> dd sysintr ; / 27 14201 00004016 [BA4D0000] <1> dd sysfstat ; / 28 14202 0000401A [66450000] <1> dd sysemt ; / 29 14203 0000401E [94450000] <1> dd sysmdate ; / 30 14204 00004022 [DF450000] <1> dd sysstty ; / 31 14205 00004026 [5E470000] <1> dd sysgtty ; / 32 14206 0000402A [8F450000] <1> dd sysilgins ; / 33 14207 0000402E [3F660000] <1> dd syssleep ; 34 ; Retro UNIX 8086 v1 feature only ! 14208 <1> ; 11/06/2014 14209 00004032 [6E660000] <1> dd sysmsg ; 35 ; Retro UNIX 386 v1 feature only ! 14210 <1> ; 01/07/2015 14211 00004036 [45670000] <1> dd sysgeterr ; 36 ; Retro UNIX 386 v1 feature only ! 14212 <1> ; 21/09/2015 - get last error number 14213 <1> end_of_syscalls: 14214 <1> 14215 <1> error: 14216 <1> ; 17/09/2015 14217 <1> ; 03/09/2015 14218 <1> ; 01/09/2015 14219 <1> ; 09/06/2015 14220 <1> ; 13/05/2015 14221 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14222 <1> ; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 14223 <1> ; 14224 <1> ; 'error' merely sets the error bit off the processor status (c-bit) 14225 <1> ; then falls right into the 'sysret', 'sysrele' return sequence. 14226 <1> ; 14227 <1> ; INPUTS -> none 14228 <1> ; OUTPUTS -> 14229 <1> ; processor status - carry (c) bit is set (means error) 14230 <1> ; 14231 <1> ; 26/05/2013 (Stack pointer must be reset here! 14232 <1> ; Because, jumps to error procedure 14233 <1> ; disrupts push-pop nesting balance) 14234 <1> ; 14235 0000403A 8B2D[40740000] <1> mov ebp, [u.sp] ; interrupt (system call) return (iretd) address 14236 00004040 804D0801 <1> or byte [ebp+8], 1 ; set carry bit of flags register 14237 <1> ; (system call will return with cf = 1) 14238 <1> ; bis $1,20.(r1) / set c bit in processor status word below 14239 <1> ; / users stack 14240 <1> ; 17/09/2015 14241 00004044 83ED30 <1> sub ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc') 14242 <1> ; for saving/restoring user registers 14243 <1> ;cmp ebp, [u.usp] 14244 <1> ;je short err0 14245 00004047 892D[44740000] <1> mov [u.usp], ebp 14246 <1> ;err0: 14247 <1> ; 01/09/2015 14248 0000404D 8B25[44740000] <1> mov esp, [u.usp] ; Retro Unix 8086 v1 modification! 14249 <1> ; 10/04/2013 14250 <1> ; (If an I/O error occurs during disk I/O, 14251 <1> ; related procedures will jump to 'error' 14252 <1> ; procedure directly without returning to 14253 <1> ; the caller procedure. So, stack pointer 14254 <1> ; must be restored here.) 14255 <1> ; 13/05/2015 14256 <1> ; NOTE: (The last) error code is in 'u.error', it can be retrieved by 14257 <1> ; 'get last error' system call later. 14258 <1> 14259 <1> ; 03/09/2015 - 09/06/2015 - 07/08/2013 14260 00004053 C605[AF740000]00 <1> mov byte [u.kcall], 0 ; namei_r, mkdir_w reset 14261 <1> 14262 <1> sysret: ; < return from system call> 14263 <1> ; 10/09/2015 14264 <1> ; 29/07/2015 14265 <1> ; 25/06/2015 14266 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14267 <1> ; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 14268 <1> ; 14269 <1> ; 'sysret' first checks to see if process is about to be 14270 <1> ; terminated (u.bsys). If it is, 'sysexit' is called. 14271 <1> ; If not, following happens: 14272 <1> ; 1) The user's stack pointer is restored. 14273 <1> ; 2) r1=0 and 'iget' is called to see if last mentioned 14274 <1> ; i-node has been modified. If it has, it is written out 14275 <1> ; via 'ppoke'. 14276 <1> ; 3) If the super block has been modified, it is written out 14277 <1> ; via 'ppoke'. 14278 <1> ; 4) If the dismountable file system's super block has been 14279 <1> ; modified, it is written out to the specified device 14280 <1> ; via 'ppoke'. 14281 <1> ; 5) A check is made if user's time quantum (uquant) ran out 14282 <1> ; during his execution. If so, 'tswap' is called to give 14283 <1> ; another user a chance to run. 14284 <1> ; 6) 'sysret' now goes into 'sysrele'. 14285 <1> ; (See 'sysrele' for conclusion.) 14286 <1> ; 14287 <1> ; Calling sequence: 14288 <1> ; jump table or 'br sysret' 14289 <1> ; Arguments: 14290 <1> ; - 14291 <1> ; ............................................................... 14292 <1> ; 14293 <1> ; ((AX=r1 for 'iget' input)) 14294 <1> ; 14295 0000405A 6631C0 <1> xor ax, ax ; 04/05/2013 14296 <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec) 14297 0000405D FEC0 <1> inc al ; 04/05/2013 14298 0000405F 3805[96740000] <1> cmp [u.bsys], al ; 1 14299 <1> ; tstb u.bsys / is a process about to be terminated because 14300 00004065 0F83E8000000 <1> jnb sysexit ; 04/05/2013 14301 <1> ; bne sysexit / of an error? yes, go to sysexit 14302 <1> ;mov esp, [u.usp] ; 24/05/2013 (that is not needed here) 14303 <1> ; mov u.sp,sp / no point stack to users stack 14304 0000406B FEC8 <1> dec al ; mov ax, 0 14305 <1> ; clr r1 / zero r1 to check last mentioned i-node 14306 0000406D E874160000 <1> call iget 14307 <1> ; jsr r0,iget / if last mentioned i-node has been modified 14308 <1> ; / it is written out 14309 00004072 6631C0 <1> xor ax, ax ; 0 14310 00004075 3805[3D740000] <1> cmp [smod], al ; 0 14311 <1> ; tstb smod / has the super block been modified 14312 0000407B 7614 <1> jna short sysret1 14313 <1> ; beq 1f / no, 1f 14314 0000407D A2[3D740000] <1> mov [smod], al ; 0 14315 <1> ; clrb smod / yes, clear smod 14316 00004082 BB[00810000] <1> mov ebx, sb0 ;; 07/08//2013 14317 00004087 66810B0002 <1> or word [ebx], 200h ;; 14318 <1> ;or word [sb0], 200h ; write bit, bit 9 14319 <1> ; bis $1000,sb0 / set write bit in I/O queue for super block 14320 <1> ; / output 14321 <1> ; AX = 0 14322 0000408C E8C0210000 <1> call poke ; 07/08/2013 14323 <1> ; call ppoke 14324 <1> ; AX = 0 14325 <1> ; jsr r0,ppoke / write out modified super block to disk 14326 <1> sysret1: ;1: 14327 00004091 3805[3E740000] <1> cmp [mmod], al ; 0 14328 <1> ; tstb mmod / has the super block for the dismountable file 14329 <1> ; / system 14330 00004097 7614 <1> jna short sysrel0 14331 <1> ; beq 1f / been modified? no, 1f 14332 00004099 A2[3E740000] <1> mov [mmod], al ; 0 14333 <1> ; clrb mmod / yes, clear mmod 14334 <1> ;mov ax, [mntd] 14335 <1> ;;mov al, [mdev] ; 26/04/2013 14336 0000409E BB[08830000] <1> mov ebx, sb1 ;; 07/08//2013 14337 <1> ;;mov [ebx], al 14338 <1> ;mov [sb1], al 14339 <1> ; movb mntd,sb1 / set the I/O queue 14340 000040A3 66810B0002 <1> or word [ebx], 200h 14341 <1> ;or word [sb1], 200h ; write bit, bit 9 14342 <1> ; bis $1000,sb1 / set write bit in I/O queue for detached sb 14343 000040A8 E8A4210000 <1> call poke ; 07/08/2013 14344 <1> ;call ppoke 14345 <1> ; jsr r0,ppoke / write it out to its device 14346 <1> ;xor al, al ; 26/04/2013 14347 <1> ;1: 14348 <1> ; tstb uquant / is the time quantum 0? 14349 <1> ; bne 1f / no, don't swap it out 14350 <1> 14351 <1> sysrele: ; < release > 14352 <1> ; 14/10/2015 14353 <1> ; 01/09/2015 14354 <1> ; 24/07/2015 14355 <1> ; 14/05/2015 14356 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14357 <1> ; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1) 14358 <1> ; 14359 <1> ; 'sysrele' first calls 'tswap' if the time quantum for a user is 14360 <1> ; zero (see 'sysret'). It then restores the user's registers and 14361 <1> ; turns off the system flag. It then checked to see if there is 14362 <1> ; an interrupt from the user by calling 'isintr'. If there is, 14363 <1> ; the output gets flashed (see isintr) and interrupt action is 14364 <1> ; taken by a branch to 'intract'. If there is no interrupt from 14365 <1> ; the user, a rti is made. 14366 <1> ; 14367 <1> ; Calling sequence: 14368 <1> ; Fall through a 'bne' in 'sysret' & ? 14369 <1> ; Arguments: 14370 <1> ; - 14371 <1> ; ............................................................... 14372 <1> ; 14373 <1> ; 23/02/2014 (swapret) 14374 <1> ; 22/09/2013 14375 <1> sysrel0: ;1: 14376 000040AD 803D[8A740000]00 <1> cmp byte [u.quant], 0 ; 16/05/2013 14377 <1> ; tstb uquant / is the time quantum 0? 14378 000040B4 7705 <1> ja short swapret 14379 <1> ; bne 1f / no, don't swap it out 14380 <1> sysrelease: ; 07/12/2013 (jump from 'clock') 14381 000040B6 E8A1120000 <1> call tswap 14382 <1> ; jsr r0,tswap / yes, swap it out 14383 <1> ; 14384 <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address. 14385 <1> swapret: ;1: 14386 <1> ; 10/09/2015 14387 <1> ; 01/09/2015 14388 <1> ; 14/05/2015 14389 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications) 14390 <1> ; 26/05/2013 (Retro UNIX 8086 v1) 14391 <1> ; cli 14392 <1> ; 24/07/2015 14393 <1> ; 14394 <1> ;; 'esp' must be already equal to '[u.usp]' here ! 14395 <1> ;; mov esp, [u.usp] 14396 <1> 14397 <1> ; 22/09/2013 14398 000040BB E886140000 <1> call isintr 14399 <1> ; 20/10/2013 14400 000040C0 7405 <1> jz short sysrel1 14401 000040C2 E875000000 <1> call intract 14402 <1> ; jsr r0,isintr / is there an interrupt from the user 14403 <1> ; br intract / yes, output gets flushed, take interrupt 14404 <1> ; / action 14405 <1> sysrel1: 14406 000040C7 FA <1> cli ; 14/10/2015 14407 000040C8 FE0D[3F740000] <1> dec byte [sysflg] 14408 <1> ; decb sysflg / turn system flag off 14409 000040CE A1[A1740000] <1> mov eax, [u.pgdir] 14410 000040D3 0F22D8 <1> mov cr3, eax ; 1st PDE points to Kernel Page Table 0 (1st 4 MB) 14411 <1> ; (others are different than kernel page tables) 14412 <1> ; 10/09/2015 14413 000040D6 61 <1> popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax 14414 <1> ; mov (sp)+,sc / restore user registers 14415 <1> ; mov (sp)+,mq 14416 <1> ; mov (sp)+,ac 14417 <1> ; mov (sp)+,r5 14418 <1> ; mov (sp)+,r4 14419 <1> ; mov (sp)+,r3 14420 <1> ; mov (sp)+,r2 14421 <1> ; 14422 000040D7 A1[48740000] <1> mov eax, [u.r0] ; ((return value in EAX)) 14423 000040DC 0FA9 <1> pop gs 14424 000040DE 0FA1 <1> pop fs 14425 000040E0 07 <1> pop es 14426 000040E1 1F <1> pop ds 14427 000040E2 CF <1> iretd 14428 <1> ; rti / no, return from interrupt 14429 <1> 14430 <1> badsys: 14431 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14432 <1> ; (Major Modification: 'core' dumping procedure in 14433 <1> ; original UNIX v1 and Retro UNIX 8086 v1 14434 <1> ; has been changed to print 'Invalid System Call !' 14435 <1> ; message on the user's console tty.) 14436 <1> ; (EIP, EAX values will be shown on screen with error message) 14437 <1> ; (EIP = Return address just after the system call -INT 30h-) 14438 <1> ; (EAX = Function number) 14439 <1> ; 14440 000040E3 FE05[96740000] <1> inc byte [u.bsys] 14441 <1> ; 14442 000040E9 8B1D[40740000] <1> mov ebx, [u.sp] ; esp at the beginning of 'sysent' 14443 000040EF 8B03 <1> mov eax, [ebx] ; EIP (return address, not 'INT 30h' address) 14444 000040F1 E8E7D7FFFF <1> call dwordtohex 14445 000040F6 8915[C06D0000] <1> mov [bsys_msg_eip], edx 14446 000040FC A3[C46D0000] <1> mov [bsys_msg_eip+4], eax 14447 00004101 A1[48740000] <1> mov eax, [u.r0] 14448 00004106 E8D2D7FFFF <1> call dwordtohex 14449 0000410B 8915[B06D0000] <1> mov [bsys_msg_eax], edx 14450 00004111 A3[B46D0000] <1> mov [bsys_msg_eax+4], eax 14451 00004116 31C0 <1> xor eax, eax 14452 00004118 C705[68740000]- <1> mov dword [u.base], badsys_msg ; "Invalid System call !" 14453 0000411E [916D0000] <1> 14454 00004122 8B1D[58740000] <1> mov ebx, [u.fofp] 14455 00004128 8903 <1> mov [ebx], eax 14456 <1> ;mov eax, 1 ; inode number of console tty (for user) 14457 0000412A 40 <1> inc eax 14458 0000412B C705[6C740000]3B00- <1> mov dword [u.count], BSYS_M_SIZE 14459 00004133 0000 <1> 14460 <1> ; writei 14461 <1> ; INPUTS -> 14462 <1> ; r1 - inode number 14463 <1> ; u.count - byte count to be written 14464 <1> ; u.base - points to user buffer 14465 <1> ; u.fofp - points to word with current file offset 14466 <1> ; OUTPUTS -> 14467 <1> ; u.count - cleared 14468 <1> ; u.nread - accumulates total bytes passed back 14469 <1> ; 14470 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 14471 00004135 E882190000 <1> call writei 14472 <1> ;mov eax, 1 14473 0000413A EB17 <1> jmp sysexit 14474 <1> 14475 <1> ; incb u.bsys / turn on the user's bad-system flag 14476 <1> ; mov $3f,u.namep / point u.namep to "core\0\0" 14477 <1> ; jsr r0,namei / get the i-number for the core image file 14478 <1> ; br 1f / error 14479 <1> ; neg r1 / negate the i-number to open the core image file 14480 <1> ; / for writing 14481 <1> ; jsr r0,iopen / open the core image file 14482 <1> ; jsr r0,itrunc / free all associated blocks 14483 <1> ; br 2f 14484 <1> ;1: 14485 <1> ; mov $17,r1 / put i-node mode (17) in r1 14486 <1> ; jsr r0,maknod / make an i-node 14487 <1> ; mov u.dirbuf,r1 / put i-node number in r1 14488 <1> ;2: 14489 <1> ; mov $core,u.base / move address core to u.base 14490 <1> ; mov $ecore-core,u.count / put the byte count in u.count 14491 <1> ; mov $u.off,u.fofp / more user offset to u.fofp 14492 <1> ; clr u.off / clear user offset 14493 <1> ; jsr r0,writei / write out the core image to the user 14494 <1> ; mov $user,u.base / pt. u.base to user 14495 <1> ; mov $64.,u.count / u.count = 64 14496 <1> ; jsr r0,writei / write out all the user parameters 14497 <1> ; neg r1 / make i-number positive 14498 <1> ; jsr r0,iclose / close the core image file 14499 <1> ; br sysexit / 14500 <1> ;3: 14501 <1> ; 14502 <1> 14503 <1> intract: ; / interrupt action 14504 <1> ; 14/10/2015 14505 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14506 <1> ; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1) 14507 <1> ; 14508 <1> ; Retro UNIX 8086 v1 modification ! 14509 <1> ; (Process/task switching and quit routine by using 14510 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 14511 <1> ; 14512 <1> ; input -> 'u.quit' (also value of 'u.intr' > 0) 14513 <1> ; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign) 14514 <1> ; 'intract' will jump to 'sysexit'. 14515 <1> ; Intract will return to the caller 14516 <1> ; if value of 'u.quit' <> FFFFh. 14517 <1> ; 14/10/2015 14518 0000413C FB <1> sti 14519 <1> ; 07/12/2013 14520 0000413D 66FF05[8E740000] <1> inc word [u.quit] 14521 00004144 7408 <1> jz short intrct0 ; FFFFh -> 0 14522 00004146 66FF0D[8E740000] <1> dec word [u.quit] 14523 <1> ; 16/04/2015 14524 0000414D C3 <1> retn 14525 <1> intrct0: 14526 0000414E 58 <1> pop eax ; call intract -> retn 14527 <1> ; 14528 0000414F 31C0 <1> xor eax, eax 14529 00004151 FEC0 <1> inc al ; mov ax, 1 14530 <1> ;;; 14531 <1> ; UNIX v1 original 'intract' routine... 14532 <1> ; / interrupt action 14533 <1> ;cmp *(sp),$rti / are you in a clock interrupt? 14534 <1> ; bne 1f / no, 1f 14535 <1> ; cmp (sp)+,(sp)+ / pop clock pointer 14536 <1> ; 1: / now in user area 14537 <1> ; mov r1,-(sp) / save r1 14538 <1> ; mov u.ttyp,r1 14539 <1> ; / pointer to tty buffer in control-to r1 14540 <1> ; cmpb 6(r1),$177 14541 <1> ; / is the interrupt char equal to "del" 14542 <1> ; beq 1f / yes, 1f 14543 <1> ; clrb 6(r1) 14544 <1> ; / no, clear the byte 14545 <1> ; / (must be a quit character) 14546 <1> ; mov (sp)+,r1 / restore r1 14547 <1> ; clr u.quit / clear quit flag 14548 <1> ; bis $20,2(sp) 14549 <1> ; / set trace for quit (sets t bit of 14550 <1> ; / ps-trace trap) 14551 <1> ; rti ; / return from interrupt 14552 <1> ; 1: / interrupt char = del 14553 <1> ; clrb 6(r1) / clear the interrupt byte 14554 <1> ; / in the buffer 14555 <1> ; mov (sp)+,r1 / restore r1 14556 <1> ; cmp u.intr,$core / should control be 14557 <1> ; / transferred to loc core? 14558 <1> ; blo 1f 14559 <1> ; jmp *u.intr / user to do rti yes, 14560 <1> ; / transfer to loc core 14561 <1> ; 1: 14562 <1> ; sys 1 / exit 14563 <1> 14564 <1> sysexit: ; 14565 <1> ; 01/09/2015 14566 <1> ; 31/08/2015 14567 <1> ; 14/05/2015 14568 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14569 <1> ; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 14570 <1> ; 14571 <1> ; 'sysexit' terminates a process. First each file that 14572 <1> ; the process has opened is closed by 'flose'. The process 14573 <1> ; status is then set to unused. The 'p.pid' table is then 14574 <1> ; searched to find children of the dying process. If any of 14575 <1> ; children are zombies (died by not waited for), they are 14576 <1> ; set free. The 'p.pid' table is then searched to find the 14577 <1> ; dying process's parent. When the parent is found, it is 14578 <1> ; checked to see if it is free or it is a zombie. If it is 14579 <1> ; one of these, the dying process just dies. If it is waiting 14580 <1> ; for a child process to die, it notified that it doesn't 14581 <1> ; have to wait anymore by setting it's status from 2 to 1 14582 <1> ; (waiting to active). It is awakened and put on runq by 14583 <1> ; 'putlu'. The dying process enters a zombie state in which 14584 <1> ; it will never be run again but stays around until a 'wait' 14585 <1> ; is completed by it's parent process. If the parent is not 14586 <1> ; found, process just dies. This means 'swap' is called with 14587 <1> ; 'u.uno=0'. What this does is the 'wswap' is not called 14588 <1> ; to write out the process and 'rswap' reads the new process 14589 <1> ; over the one that dies..i.e., the dying process is 14590 <1> ; overwritten and destroyed. 14591 <1> ; 14592 <1> ; Calling sequence: 14593 <1> ; sysexit or conditional branch. 14594 <1> ; Arguments: 14595 <1> ; - 14596 <1> ; ............................................................... 14597 <1> ; 14598 <1> ; Retro UNIX 8086 v1 modification: 14599 <1> ; System call number (=1) is in EAX register. 14600 <1> ; 14601 <1> ; Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP 14602 <1> ; registers depending of function details. 14603 <1> ; 14604 <1> ; ('swap' procedure is mostly different than original UNIX v1.) 14605 <1> ; 14606 <1> ; / terminate process 14607 <1> ; AX = 1 14608 00004153 6648 <1> dec ax ; 0 14609 00004155 66A3[8C740000] <1> mov [u.intr], ax ; 0 14610 <1> ; clr u.intr / clear interrupt control word 14611 <1> ; clr r1 / clear r1 14612 <1> ; AX = 0 14613 <1> sysexit_1: ; 1: 14614 <1> ; AX = File descriptor 14615 <1> ; / r1 has file descriptor (index to u.fp list) 14616 <1> ; / Search the whole list 14617 0000415B E8140D0000 <1> call fclose 14618 <1> ; jsr r0,fclose / close all files the process opened 14619 <1> ;; ignore error return 14620 <1> ; br .+2 / ignore error return 14621 <1> ;inc ax 14622 00004160 FEC0 <1> inc al 14623 <1> ; inc r1 / increment file descriptor 14624 <1> ;cmp ax, 10 14625 00004162 3C0A <1> cmp al, 10 14626 <1> ; cmp r1,$10. / end of u.fp list? 14627 00004164 72F5 <1> jb short sysexit_1 14628 <1> ; blt 1b / no, go back 14629 00004166 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 14630 <1> ; movb u.uno,r1 / yes, move dying process's number to r1 14631 0000416D 88A3[C5710000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 14632 <1> ; clrb p.stat-1(r1) / free the process 14633 <1> ;shl bx, 1 14634 00004173 D0E3 <1> shl bl, 1 14635 <1> ; asl r1 / use r1 for index into the below tables 14636 00004175 668B8B[34710000] <1> mov cx, [ebx+p.pid-2] 14637 <1> ; mov p.pid-2(r1),r3 / move dying process's name to r3 14638 0000417C 668B93[54710000] <1> mov dx, [ebx+p.ppid-2] 14639 <1> ; mov p.ppid-2(r1),r4 / move its parents name to r4 14640 <1> ; xor bx, bx ; 0 14641 00004183 30DB <1> xor bl, bl ; 0 14642 <1> ; clr r2 14643 00004185 31F6 <1> xor esi, esi ; 0 14644 <1> ; clr r5 / initialize reg 14645 <1> sysexit_2: ; 1: 14646 <1> ; / find children of this dying process, 14647 <1> ; / if they are zombies, free them 14648 <1> ;add bx, 2 14649 00004187 80C302 <1> add bl, 2 14650 <1> ; add $2,r2 / search parent process table 14651 <1> ; / for dying process's name 14652 0000418A 66398B[54710000] <1> cmp [ebx+p.ppid-2], cx 14653 <1> ; cmp p.ppid-2(r2),r3 / found it? 14654 00004191 7513 <1> jne short sysexit_4 14655 <1> ; bne 3f / no 14656 <1> ;shr bx, 1 14657 00004193 D0EB <1> shr bl, 1 14658 <1> ; asr r2 / yes, it is a parent 14659 00004195 80BB[C5710000]03 <1> cmp byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 14660 <1> ; cmpb p.stat-1(r2),$3 / is the child of this 14661 <1> ; / dying process a zombie 14662 0000419C 7506 <1> jne short sysexit_3 14663 <1> ; bne 2f / no 14664 0000419E 88A3[C5710000] <1> mov [ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014 14665 <1> ; clrb p.stat-1(r2) / yes, free the child process 14666 <1> sysexit_3: ; 2: 14667 <1> ;shr bx, 1 14668 000041A4 D0E3 <1> shl bl, 1 14669 <1> ; asl r2 14670 <1> sysexit_4: ; 3: 14671 <1> ; / search the process name table 14672 <1> ; / for the dying process's parent 14673 000041A6 663993[34710000] <1> cmp [ebx+p.pid-2], dx ; 17/09/2013 14674 <1> ; cmp p.pid-2(r2),r4 / found it? 14675 000041AD 7502 <1> jne short sysexit_5 14676 <1> ; bne 3f / no 14677 000041AF 89DE <1> mov esi, ebx 14678 <1> ; mov r2,r5 / yes, put index to p.pid table (parents 14679 <1> ; / process # x2) in r5 14680 <1> sysexit_5: ; 3: 14681 <1> ;cmp bx, nproc + nproc 14682 000041B1 80FB20 <1> cmp bl, nproc + nproc 14683 <1> ; cmp r2,$nproc+nproc / has whole table been searched? 14684 000041B4 72D1 <1> jb short sysexit_2 14685 <1> ; blt 1b / no, go back 14686 <1> ; mov r5,r1 / yes, r1 now has parents process # x2 14687 000041B6 21F6 <1> and esi, esi ; r5=r1 14688 000041B8 7431 <1> jz short sysexit_6 14689 <1> ; beq 2f / no parent has been found. 14690 <1> ; / The process just dies 14691 000041BA 66D1EE <1> shr si, 1 14692 <1> ; asr r1 / set up index to p.stat 14693 000041BD 8A86[C5710000] <1> mov al, [esi+p.stat-1] 14694 <1> ; movb p.stat-1(r1),r2 / move status of parent to r2 14695 000041C3 20C0 <1> and al, al 14696 000041C5 7424 <1> jz short sysexit_6 14697 <1> ; beq 2f / if its been freed, 2f 14698 000041C7 3C03 <1> cmp al, 3 14699 <1> ; cmp r2,$3 / is parent a zombie? 14700 000041C9 7420 <1> je short sysexit_6 14701 <1> ; beq 2f / yes, 2f 14702 <1> ; BH = 0 14703 000041CB 8A1D[97740000] <1> mov bl, [u.uno] 14704 <1> ; movb u.uno,r3 / move dying process's number to r3 14705 000041D1 C683[C5710000]03 <1> mov byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014 14706 <1> ; movb $3,p.stat-1(r3) / make the process a zombie 14707 <1> ; 05/02/2014 14708 000041D8 3C01 <1> cmp al, 1 ; SRUN 14709 000041DA 740F <1> je short sysexit_6 14710 <1> ;cmp al, 2 14711 <1> ; cmp r2,$2 / is the parent waiting for 14712 <1> ; / this child to die 14713 <1> ;jne short sysexit_6 14714 <1> ; bne 2f / yes, notify parent not to wait any more 14715 <1> ; 05/02/2014 14716 <1> ; p.stat = 2 --> waiting 14717 <1> ; p.stat = 4 --> sleeping 14718 000041DC C686[C5710000]01 <1> mov byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014 14719 <1> ;dec byte [esi+p.stat-1] 14720 <1> ; decb p.stat-1(r1) / awaken it by putting it (parent) 14721 000041E3 6689F0 <1> mov ax, si ; r1 (process number in AL) 14722 <1> ; 14723 <1> ;mov ebx, runq + 4 14724 <1> ; mov $runq+4,r2 / on the runq 14725 000041E6 E849120000 <1> call putlu 14726 <1> ; jsr r0, putlu 14727 <1> sysexit_6: ; 2: 14728 <1> ; 31/08/2015 14729 <1> ; / the process dies 14730 000041EB C605[97740000]00 <1> mov byte [u.uno], 0 14731 <1> ; clrb u.uno / put zero as the process number, 14732 <1> ; / so "swap" will 14733 000041F2 E86F110000 <1> call swap 14734 <1> ; jsr r0,swap / overwrite process with another process 14735 <1> hlt_sys: 14736 <1> ;sti ; 18/01/2014 14737 <1> hlts0: 14738 000041F7 F4 <1> hlt 14739 000041F8 EBFD <1> jmp short hlts0 14740 <1> ; 0 / and thereby kill it; halt? 14741 <1> 14742 <1> 14743 <1> syswait: ; < wait for a processs to die > 14744 <1> ; 17/09/2015 14745 <1> ; 02/09/2015 14746 <1> ; 01/09/2015 14747 <1> ; 16/04/2015 (Retro UNIX 386 v1 - Beginning) 14748 <1> ; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1) 14749 <1> ; 14750 <1> ; 'syswait' waits for a process die. 14751 <1> ; It works in following way: 14752 <1> ; 1) From the parent process number, the parent's 14753 <1> ; process name is found. The p.ppid table of parent 14754 <1> ; names is then searched for this process name. 14755 <1> ; If a match occurs, r2 contains child's process 14756 <1> ; number. The child status is checked to see if it is 14757 <1> ; a zombie, i.e; dead but not waited for (p.stat=3) 14758 <1> ; If it is, the child process is freed and it's name 14759 <1> ; is put in (u.r0). A return is then made via 'sysret'. 14760 <1> ; If the child is not a zombie, nothing happens and 14761 <1> ; the search goes on through the p.ppid table until 14762 <1> ; all processes are checked or a zombie is found. 14763 <1> ; 2) If no zombies are found, a check is made to see if 14764 <1> ; there are any children at all. If there are none, 14765 <1> ; an error return is made. If there are, the parent's 14766 <1> ; status is set to 2 (waiting for child to die), 14767 <1> ; the parent is swapped out, and a branch to 'syswait' 14768 <1> ; is made to wait on the next process. 14769 <1> ; 14770 <1> ; Calling sequence: 14771 <1> ; ? 14772 <1> ; Arguments: 14773 <1> ; - 14774 <1> ; Inputs: - 14775 <1> ; Outputs: if zombie found, it's name put in u.r0. 14776 <1> ; ............................................................... 14777 <1> ; 14778 <1> 14779 <1> ; / wait for a process to die 14780 <1> 14781 <1> syswait_0: 14782 000041FA 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; 01/09/2015 14783 <1> ; movb u.uno,r1 / put parents process number in r1 14784 00004201 D0E3 <1> shl bl, 1 14785 <1> ;shl bx, 1 14786 <1> ; asl r1 / x2 to get index into p.pid table 14787 00004203 668B83[34710000] <1> mov ax, [ebx+p.pid-2] 14788 <1> ; mov p.pid-2(r1),r1 / get the name of this process 14789 0000420A 31F6 <1> xor esi, esi 14790 <1> ; clr r2 14791 0000420C 31C9 <1> xor ecx, ecx ; 30/10/2013 14792 <1> ;xor cl, cl 14793 <1> ; clr r3 / initialize reg 3 14794 <1> syswait_1: ; 1: 14795 0000420E 6683C602 <1> add si, 2 14796 <1> ; add $2,r2 / use r2 for index into p.ppid table 14797 <1> ; / search table of parent processes 14798 <1> ; / for this process name 14799 00004212 663B86[54710000] <1> cmp ax, [esi+p.ppid-2] 14800 <1> ; cmp p.ppid-2(r2),r1 / r2 will contain the childs 14801 <1> ; / process number 14802 00004219 7535 <1> jne short syswait_3 14803 <1> ;bne 3f / branch if no match of parent process name 14804 <1> ;inc cx 14805 0000421B FEC1 <1> inc cl 14806 <1> ;inc r3 / yes, a match, r3 indicates number of children 14807 0000421D 66D1EE <1> shr si, 1 14808 <1> ; asr r2 / r2/2 to get index to p.stat table 14809 <1> ; The possible states ('p.stat' values) of a process are: 14810 <1> ; 0 = free or unused 14811 <1> ; 1 = active 14812 <1> ; 2 = waiting for a child process to die 14813 <1> ; 3 = terminated, but not yet waited for (zombie). 14814 00004220 80BE[C5710000]03 <1> cmp byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014 14815 <1> ; cmpb p.stat-1(r2),$3 / is the child process a zombie? 14816 00004227 7524 <1> jne short syswait_2 14817 <1> ; bne 2f / no, skip it 14818 00004229 88BE[C5710000] <1> mov [esi+p.stat-1], bh ; 0 14819 <1> ; clrb p.stat-1(r2) / yes, free it 14820 0000422F 66D1E6 <1> shl si, 1 14821 <1> ; asl r2 / r2x2 to get index into p.pid table 14822 00004232 0FB786[34710000] <1> movzx eax, word [esi+p.pid-2] 14823 00004239 A3[48740000] <1> mov [u.r0], eax 14824 <1> ; mov p.pid-2(r2),*u.r0 14825 <1> ; / put childs process name in (u.r0) 14826 <1> ; 14827 <1> ; Retro UNIX 386 v1 modification ! (17/09/2015) 14828 <1> ; 14829 <1> ; Parent process ID -p.ppid- field (of the child process) 14830 <1> ; must be cleared in order to prevent infinitive 'syswait' 14831 <1> ; system call loop from the application/program if it calls 14832 <1> ; 'syswait' again (mistakenly) while there is not a zombie 14833 <1> ; or running child process to wait. ('forktest.s', 17/09/2015) 14834 <1> ; 14835 <1> ; Note: syswait will return with error if there is not a 14836 <1> ; zombie or running process to wait. 14837 <1> ; 14838 0000423E 6629C0 <1> sub ax, ax 14839 00004241 668986[54710000] <1> mov [esi+p.ppid-2], ax ; 0 ; 17/09/2015 14840 00004248 E910FEFFFF <1> jmp sysret0 ; ax = 0 14841 <1> ; 14842 <1> ;jmp sysret 14843 <1> ; br sysret1 / return cause child is dead 14844 <1> syswait_2: ; 2: 14845 0000424D 66D1E6 <1> shl si, 1 14846 <1> ; asl r2 / r2x2 to get index into p.ppid table 14847 <1> syswait_3: ; 3: 14848 00004250 6683FE20 <1> cmp si, nproc+nproc 14849 <1> ; cmp r2,$nproc+nproc / have all processes been checked? 14850 00004254 72B8 <1> jb short syswait_1 14851 <1> ; blt 1b / no, continue search 14852 <1> ;and cx, cx 14853 00004256 20C9 <1> and cl, cl 14854 <1> ; tst r3 / one gets here if there are no children 14855 <1> ; / or children that are still active 14856 <1> ; 30/10/2013 14857 00004258 750B <1> jnz short syswait_4 14858 <1> ;jz error 14859 <1> ; beq error1 / there are no children, error 14860 0000425A 890D[48740000] <1> mov [u.r0], ecx ; 0 14861 00004260 E9D5FDFFFF <1> jmp error 14862 <1> syswait_4: 14863 00004265 8A1D[97740000] <1> mov bl, [u.uno] 14864 <1> ; movb u.uno,r1 / there are children so put 14865 <1> ; / parent process number in r1 14866 0000426B FE83[C5710000] <1> inc byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014 14867 <1> ; incb p.stat-1(r1) / it is waiting for 14868 <1> ; / other children to die 14869 <1> ; 04/11/2013 14870 00004271 E8F0100000 <1> call swap 14871 <1> ; jsr r0,swap / swap it out, because it's waiting 14872 00004276 EB82 <1> jmp syswait_0 14873 <1> ; br syswait / wait on next process 14874 <1> 14875 <1> sysfork: ; < create a new process > 14876 <1> ; 18/09/2015 14877 <1> ; 04/09/2015 14878 <1> ; 02/09/2015 14879 <1> ; 01/09/2015 14880 <1> ; 28/08/2015 14881 <1> ; 14/05/2015 14882 <1> ; 10/05/2015 14883 <1> ; 09/05/2015 14884 <1> ; 06/05/2015 (Retro UNIX 386 v1 - Beginning) 14885 <1> ; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1) 14886 <1> ; 14887 <1> ; 'sysfork' creates a new process. This process is referred 14888 <1> ; to as the child process. This new process core image is 14889 <1> ; a copy of that of the caller of 'sysfork'. The only 14890 <1> ; distinction is the return location and the fact that (u.r0) 14891 <1> ; in the old process (parent) contains the process id (p.pid) 14892 <1> ; of the new process (child). This id is used by 'syswait'. 14893 <1> ; 'sysfork' works in the following manner: 14894 <1> ; 1) The process status table (p.stat) is searched to find 14895 <1> ; a process number that is unused. If none are found 14896 <1> ; an error occurs. 14897 <1> ; 2) when one is found, it becomes the child process number 14898 <1> ; and it's status (p.stat) is set to active. 14899 <1> ; 3) If the parent had a control tty, the interrupt 14900 <1> ; character in that tty buffer is cleared. 14901 <1> ; 4) The child process is put on the lowest priority run 14902 <1> ; queue via 'putlu'. 14903 <1> ; 5) A new process name is gotten from 'mpid' (actually 14904 <1> ; it is a unique number) and is put in the child's unique 14905 <1> ; identifier; process id (p.pid). 14906 <1> ; 6) The process name of the parent is then obtained and 14907 <1> ; placed in the unique identifier of the parent process 14908 <1> ; name is then put in 'u.r0'. 14909 <1> ; 7) The child process is then written out on disk by 14910 <1> ; 'wswap',i.e., the parent process is copied onto disk 14911 <1> ; and the child is born. (The child process is written 14912 <1> ; out on disk/drum with 'u.uno' being the child process 14913 <1> ; number.) 14914 <1> ; 8) The parent process number is then restored to 'u.uno'. 14915 <1> ; 9) The child process name is put in 'u.r0'. 14916 <1> ; 10) The pc on the stack sp + 18 is incremented by 2 to 14917 <1> ; create the return address for the parent process. 14918 <1> ; 11) The 'u.fp' list as then searched to see what files 14919 <1> ; the parent has opened. For each file the parent has 14920 <1> ; opened, the corresponding 'fsp' entry must be updated 14921 <1> ; to indicate that the child process also has opened 14922 <1> ; the file. A branch to 'sysret' is then made. 14923 <1> ; 14924 <1> ; Calling sequence: 14925 <1> ; from shell ? 14926 <1> ; Arguments: 14927 <1> ; - 14928 <1> ; Inputs: - 14929 <1> ; Outputs: *u.r0 - child process name 14930 <1> ; ............................................................... 14931 <1> ; 14932 <1> ; Retro UNIX 8086 v1 modification: 14933 <1> ; AX = r0 = PID (>0) (at the return of 'sysfork') 14934 <1> ; = process id of child a parent process returns 14935 <1> ; = process id of parent when a child process returns 14936 <1> ; 14937 <1> ; In original UNIX v1, sysfork is called and returns as 14938 <1> ; in following manner: (with an example: c library, fork) 14939 <1> ; 14940 <1> ; 1: 14941 <1> ; sys fork 14942 <1> ; br 1f / child process returns here 14943 <1> ; bes 2f / parent process returns here 14944 <1> ; / pid of new process in r0 14945 <1> ; rts pc 14946 <1> ; 2: / parent process condionally branches here 14947 <1> ; mov $-1,r0 / pid = -1 means error return 14948 <1> ; rts pc 14949 <1> ; 14950 <1> ; 1: / child process brances here 14951 <1> ; clr r0 / pid = 0 in child process 14952 <1> ; rts pc 14953 <1> ; 14954 <1> ; In UNIX v7x86 (386) by Robert Nordier (1999) 14955 <1> ; // pid = fork(); 14956 <1> ; // 14957 <1> ; // pid == 0 in child process; 14958 <1> ; // pid == -1 means error return 14959 <1> ; // in child, 14960 <1> ; // parents id is in par_uid if needed 14961 <1> ; 14962 <1> ; _fork: 14963 <1> ; mov $.fork,eax 14964 <1> ; int $0x30 14965 <1> ; jmp 1f 14966 <1> ; jnc 2f 14967 <1> ; jmp cerror 14968 <1> ; 1: 14969 <1> ; mov eax,_par_uid 14970 <1> ; xor eax,eax 14971 <1> ; 2: 14972 <1> ; ret 14973 <1> ; 14974 <1> ; In Retro UNIX 8086 v1, 14975 <1> ; 'sysfork' returns in following manner: 14976 <1> ; 14977 <1> ; mov ax, sys_fork 14978 <1> ; mov bx, offset @f ; routine for child 14979 <1> ; int 20h 14980 <1> ; jc error 14981 <1> ; 14982 <1> ; ; Routine for parent process here (just after 'jc') 14983 <1> ; mov word ptr [pid_of_child], ax 14984 <1> ; jmp next_routine_for_parent 14985 <1> ; 14986 <1> ; @@: ; routine for child process here 14987 <1> ; .... 14988 <1> ; NOTE: 'sysfork' returns to specified offset 14989 <1> ; for child process by using BX input. 14990 <1> ; (at first, parent process will return then 14991 <1> ; child process will return -after swapped in- 14992 <1> ; 'syswait' is needed in parent process 14993 <1> ; if return from child process will be waited for.) 14994 <1> ; 14995 <1> 14996 <1> ; / create a new process 14997 <1> ; EBX = return address for child process 14998 <1> ; (Retro UNIX 8086 v1 modification !) 14999 00004278 31F6 <1> xor esi, esi 15000 <1> ; clr r1 15001 <1> sysfork_1: ; 1: / search p.stat table for unused process number 15002 0000427A 46 <1> inc esi 15003 <1> ; inc r1 15004 0000427B 80BE[C5710000]00 <1> cmp byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014 15005 <1> ; tstb p.stat-1(r1) / is process active, unused, dead 15006 00004282 760B <1> jna short sysfork_2 15007 <1> ; beq 1f / it's unused so branch 15008 00004284 6683FE10 <1> cmp si, nproc 15009 <1> ; cmp r1,$nproc / all processes checked 15010 00004288 72F0 <1> jb short sysfork_1 15011 <1> ; blt 1b / no, branch back 15012 <1> ; 15013 <1> ; Retro UNIX 8086 v1. modification: 15014 <1> ; Parent process returns from 'sysfork' to address 15015 <1> ; which is just after 'sysfork' system call in parent 15016 <1> ; process. Child process returns to address which is put 15017 <1> ; in BX register by parent process for 'sysfork'. 15018 <1> ; 15019 <1> ;add $2,18.(sp) / add 2 to pc when trap occured, points 15020 <1> ; / to old process return 15021 <1> ; br error1 / no room for a new process 15022 0000428A E9ABFDFFFF <1> jmp error 15023 <1> sysfork_2: ; 1: 15024 0000428F E861EDFFFF <1> call allocate_page 15025 00004294 0F82A0FDFFFF <1> jc error 15026 0000429A 50 <1> push eax ; UPAGE (user structure page) address 15027 <1> ; Retro UNIX 386 v1 modification! 15028 0000429B E85EEFFFFF <1> call duplicate_page_dir 15029 <1> ; EAX = New page directory 15030 000042A0 730B <1> jnc short sysfork_3 15031 000042A2 58 <1> pop eax ; UPAGE (user structure page) address 15032 000042A3 E825EFFFFF <1> call deallocate_page 15033 000042A8 E98DFDFFFF <1> jmp error 15034 <1> sysfork_3: 15035 <1> ; Retro UNIX 386 v1 modification ! 15036 000042AD 56 <1> push esi 15037 000042AE E82B110000 <1> call wswap ; save current user (u) structure, user registers 15038 <1> ; and interrupt return components (for IRET) 15039 000042B3 8705[A1740000] <1> xchg eax, [u.pgdir] ; page directory of the child process 15040 000042B9 A3[A5740000] <1> mov [u.ppgdir], eax ; page directory of the parent process 15041 000042BE 5E <1> pop esi 15042 000042BF 58 <1> pop eax ; UPAGE (user structure page) address 15043 <1> ; [u.usp] = esp 15044 000042C0 89F7 <1> mov edi, esi 15045 000042C2 66C1E702 <1> shl di, 2 15046 000042C6 8987[D2710000] <1> mov [edi+p.upage-4], eax ; memory page for 'user' struct 15047 000042CC A3[98740000] <1> mov [u.upage], eax ; memory page for 'user' struct (child) 15048 <1> ; 28/08/2015 15049 000042D1 0FB605[97740000] <1> movzx eax, byte [u.uno] ; parent process number 15050 <1> ; movb u.uno,-(sp) / save parent process number 15051 000042D8 89C7 <1> mov edi, eax 15052 000042DA 50 <1> push eax ; ** 15053 000042DB 8A87[95710000] <1> mov al, [edi+p.ttyc-1] ; console tty (parent) 15054 <1> ; 18/09/2015 15055 <1> ;mov [esi+p.ttyc-1], al ; set child's console tty 15056 <1> ;mov [esi+p.waitc-1], ah ; 0 ; reset child's wait channel 15057 000042E1 668986[95710000] <1> mov [esi+p.ttyc-1], ax ; al - set child's console tty 15058 <1> ; ah - reset child's wait channel 15059 000042E8 89F0 <1> mov eax, esi 15060 000042EA A2[97740000] <1> mov [u.uno], al ; child process number 15061 <1> ;movb r1,u.uno / set child process number to r1 15062 000042EF FE86[C5710000] <1> inc byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014 15063 <1> ; incb p.stat-1(r1) / set p.stat entry for child 15064 <1> ; / process to active status 15065 <1> ; mov u.ttyp,r2 / put pointer to parent process' 15066 <1> ; / control tty buffer in r2 15067 <1> ; beq 2f / branch, if no such tty assigned 15068 <1> ; clrb 6(r2) / clear interrupt character in tty buffer 15069 <1> ; 2: 15070 000042F5 53 <1> push ebx ; * return address for the child process 15071 <1> ; * Retro UNIX 8086 v1 feature only ! 15072 <1> ; (Retro UNIX 8086 v1 modification!) 15073 <1> ; mov $runq+4,r2 15074 000042F6 E839110000 <1> call putlu 15075 <1> ; jsr r0,putlu / put child process on lowest priority 15076 <1> ; / run queue 15077 000042FB 66D1E6 <1> shl si, 1 15078 <1> ; asl r1 / multiply r1 by 2 to get index 15079 <1> ; / into p.pid table 15080 000042FE 66FF05[36740000] <1> inc word [mpid] 15081 <1> ; inc mpid / increment m.pid; get a new process name 15082 00004305 66A1[36740000] <1> mov ax, [mpid] 15083 0000430B 668986[34710000] <1> mov [esi+p.pid-2], ax 15084 <1> ;mov mpid,p.pid-2(r1) / put new process name 15085 <1> ; / in child process' name slot 15086 00004312 5A <1> pop edx ; * return address for the child process 15087 <1> ; * Retro UNIX 8086 v1 feature only ! 15088 00004313 5B <1> pop ebx ; ** 15089 <1> ;mov ebx, [esp] ; ** parent process number 15090 <1> ; movb (sp),r2 / put parent process number in r2 15091 00004314 66D1E3 <1> shl bx, 1 15092 <1> ;asl r2 / multiply by 2 to get index into below tables 15093 <1> ;movzx eax, word [ebx+p.pid-2] 15094 00004317 668B83[34710000] <1> mov ax, [ebx+p.pid-2] 15095 <1> ; mov p.pid-2(r2),r2 / get process name of parent 15096 <1> ; / process 15097 0000431E 668986[54710000] <1> mov [esi+p.ppid-2], ax 15098 <1> ; mov r2,p.ppid-2(r1) / put parent process name 15099 <1> ; / in parent process slot for child 15100 00004325 A3[48740000] <1> mov [u.r0], eax 15101 <1> ; mov r2,*u.r0 / put parent process name on stack 15102 <1> ; / at location where r0 was saved 15103 0000432A 8B2D[40740000] <1> mov ebp, [u.sp] ; points to return address (EIP for IRET) 15104 00004330 895500 <1> mov [ebp], edx ; *, CS:EIP -> EIP 15105 <1> ; * return address for the child process 15106 <1> ; mov $sysret1,-(sp) / 15107 <1> ; mov sp,u.usp / contents of sp at the time when 15108 <1> ; / user is swapped out 15109 <1> ; mov $sstack,sp / point sp to swapping stack space 15110 <1> ; 04/09/2015 - 01/09/2015 15111 <1> ; [u.usp] = esp 15112 00004333 68[5A400000] <1> push sysret ; *** 15113 00004338 8925[44740000] <1> mov [u.usp], esp ; points to 'sysret' address (***) 15114 <1> ; (for child process) 15115 0000433E 31C0 <1> xor eax, eax 15116 00004340 66A3[78740000] <1> mov [u.ttyp], ax ; 0 15117 <1> ; 15118 00004346 E893100000 <1> call wswap ; Retro UNIX 8086 v1 modification ! 15119 <1> ;jsr r0,wswap / put child process out on drum 15120 <1> ;jsr r0,unpack / unpack user stack 15121 <1> ;mov u.usp,sp / restore user stack pointer 15122 <1> ; tst (sp)+ / bump stack pointer 15123 <1> ; Retro UNIX 386 v1 modification ! 15124 0000434B 58 <1> pop eax ; *** 15125 0000434C 66D1E3 <1> shl bx, 1 15126 0000434F 8B83[D2710000] <1> mov eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015 15127 00004355 E8AD100000 <1> call rswap ; restore parent process 'u' structure, 15128 <1> ; registers and return address (for IRET) 15129 <1> ;movb (sp)+,u.uno / put parent process number in u.uno 15130 0000435A 0FB705[36740000] <1> movzx eax, word [mpid] 15131 00004361 A3[48740000] <1> mov [u.r0], eax 15132 <1> ; mov mpid,*u.r0 / put child process name on stack 15133 <1> ; / where r0 was saved 15134 <1> ; add $2,18.(sp) / add 2 to pc on stack; gives parent 15135 <1> ; / process return 15136 <1> ;xor ebx, ebx 15137 00004366 31F6 <1> xor esi, esi 15138 <1> ;clr r1 15139 <1> sysfork_4: ; 1: / search u.fp list to find the files 15140 <1> ; / opened by the parent process 15141 <1> ; 01/09/2015 15142 <1> ;xor bh, bh 15143 <1> ;mov bl, [esi+u.fp] 15144 00004368 8A86[4E740000] <1> mov al, [esi+u.fp] 15145 <1> ; movb u.fp(r1),r2 / get an open file for this process 15146 <1> ;or bl, bl 15147 0000436E 08C0 <1> or al, al 15148 00004370 740D <1> jz short sysfork_5 15149 <1> ; beq 2f / file has not been opened by parent, 15150 <1> ; / so branch 15151 00004372 B40A <1> mov ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes 15152 00004374 F6E4 <1> mul ah 15153 <1> ;movzx ebx, ax 15154 00004376 6689C3 <1> mov bx, ax 15155 <1> ;shl bx, 3 15156 <1> ; asl r2 / multiply by 8 15157 <1> ; asl r2 / to get index into fsp table 15158 <1> ; asl r2 15159 00004379 FE83[14720000] <1> inc byte [ebx+fsp-2] 15160 <1> ; incb fsp-2(r2) / increment number of processes 15161 <1> ; / using file, because child will now be 15162 <1> ; / using this file 15163 <1> sysfork_5: ; 2: 15164 0000437F 46 <1> inc esi 15165 <1> ; inc r1 / get next open file 15166 00004380 6683FE0A <1> cmp si, 10 15167 <1> ; cmp r1,$10. / 10. files is the maximum number which 15168 <1> ; / can be opened 15169 00004384 72E2 <1> jb short sysfork_4 15170 <1> ; blt 1b / check next entry 15171 00004386 E9CFFCFFFF <1> jmp sysret 15172 <1> ; br sysret1 15173 <1> 15174 <1> sysread: ; < read from file > 15175 <1> ; 13/05/2015 15176 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 15177 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 15178 <1> ; 15179 <1> ; 'sysread' is given a buffer to read into and the number of 15180 <1> ; characters to be read. If finds the file from the file 15181 <1> ; descriptor located in *u.r0 (r0). This file descriptor 15182 <1> ; is returned from a successful open call (sysopen). 15183 <1> ; The i-number of file is obtained via 'rw1' and the data 15184 <1> ; is read into core via 'readi'. 15185 <1> ; 15186 <1> ; Calling sequence: 15187 <1> ; sysread; buffer; nchars 15188 <1> ; Arguments: 15189 <1> ; buffer - location of contiguous bytes where 15190 <1> ; input will be placed. 15191 <1> ; nchars - number of bytes or characters to be read. 15192 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 15193 <1> ; Outputs: *u.r0 - number of bytes read. 15194 <1> ; ............................................................... 15195 <1> ; 15196 <1> ; Retro UNIX 8086 v1 modification: 15197 <1> ; 'sysread' system call has three arguments; so, 15198 <1> ; * 1st argument, file descriptor is in BX register 15199 <1> ; * 2nd argument, buffer address/offset in CX register 15200 <1> ; * 3rd argument, number of bytes is in DX register 15201 <1> ; 15202 <1> ; AX register (will be restored via 'u.r0') will return 15203 <1> ; to the user with number of bytes read. 15204 <1> ; 15205 0000438B E83D000000 <1> call rw1 15206 00004390 0F82A4FCFFFF <1> jc error ; 13/05/2015, ax < 1 15207 <1> ; jsr r0,rw1 / get i-number of file to be read into r1 15208 00004396 F6C480 <1> test ah, 80h 15209 <1> ; tst r1 / negative i-number? 15210 00004399 0F859BFCFFFF <1> jnz error 15211 <1> ; ble error1 / yes, error 1 to read 15212 <1> ; / it should be positive 15213 0000439F E822150000 <1> call readi 15214 <1> ; jsr r0,readi / read data into core 15215 000043A4 EB18 <1> jmp short rw0 15216 <1> ; br 1f 15217 <1> syswrite: ; < write to file > 15218 <1> ; 13/05/2015 15219 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 15220 <1> ; 23/05/2013 (Retro UNIX 8086 v1) 15221 <1> ; 15222 <1> ; 'syswrite' is given a buffer to write onto an output file 15223 <1> ; and the number of characters to write. If finds the file 15224 <1> ; from the file descriptor located in *u.r0 (r0). This file 15225 <1> ; descriptor is returned from a successful open or create call 15226 <1> ; (sysopen or syscreat). The i-number of file is obtained via 15227 <1> ; 'rw1' and buffer is written on the output file via 'write'. 15228 <1> ; 15229 <1> ; Calling sequence: 15230 <1> ; syswrite; buffer; nchars 15231 <1> ; Arguments: 15232 <1> ; buffer - location of contiguous bytes to be writtten. 15233 <1> ; nchars - number of characters to be written. 15234 <1> ; Inputs: *u.r0 - file descriptor (& arguments) 15235 <1> ; Outputs: *u.r0 - number of bytes written. 15236 <1> ; ............................................................... 15237 <1> ; 15238 <1> ; Retro UNIX 8086 v1 modification: 15239 <1> ; 'syswrite' system call has three arguments; so, 15240 <1> ; * 1st argument, file descriptor is in BX register 15241 <1> ; * 2nd argument, buffer address/offset in CX register 15242 <1> ; * 3rd argument, number of bytes is in DX register 15243 <1> ; 15244 <1> ; AX register (will be restored via 'u.r0') will return 15245 <1> ; to the user with number of bytes written. 15246 <1> ; 15247 000043A6 E822000000 <1> call rw1 15248 000043AB 0F8289FCFFFF <1> jc error ; 13/05/2015, ax < 1 15249 <1> ; jsr r0,rw1 / get i-number in r1 of file to write 15250 000043B1 F6C480 <1> test ah, 80h 15251 <1> ; tst r1 / positive i-number ? 15252 000043B4 744E <1> jz short rw3 ; 13/05/2015 15253 <1> ;jz error 15254 <1> ; bge error1 / yes, error 1 15255 <1> ; / negative i-number means write 15256 000043B6 66F7D8 <1> neg ax 15257 <1> ; neg r1 / make it positive 15258 000043B9 E8FE160000 <1> call writei 15259 <1> ; jsr r0,writei / write data 15260 <1> rw0: ; 1: 15261 000043BE A1[70740000] <1> mov eax, [u.nread] 15262 000043C3 A3[48740000] <1> mov [u.r0], eax 15263 <1> ; mov u.nread,*u.r0 / put no. of bytes transferred 15264 <1> ; / into (u.r0) 15265 000043C8 E98DFCFFFF <1> jmp sysret 15266 <1> ; br sysret1 15267 <1> rw1: 15268 <1> ; 14/05/2015 15269 <1> ; 13/05/2015 15270 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 15271 <1> ; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1) 15272 <1> ; System call registers: bx, cx, dx (through 'sysenter') 15273 <1> ; 15274 <1> ;mov [u.base], ecx ; buffer address/offset 15275 <1> ;(in the user's virtual memory space) 15276 <1> ;mov [u.count], edx 15277 <1> ; jsr r0,arg; u.base / get buffer pointer 15278 <1> ; jsr r0,arg; u.count / get no. of characters 15279 <1> ;;mov eax, ebx ; file descriptor 15280 <1> ; mov *u.r0,r1 / put file descriptor 15281 <1> ; / (index to u.fp table) in r1 15282 <1> ; 13/05/2015 15283 000043CD C705[48740000]0000- <1> mov dword [u.r0], 0 ; r/w transfer count = 0 (reset) 15284 000043D5 0000 <1> 15285 <1> ; 15286 <1> ;; call getf 15287 <1> ; eBX = File descriptor 15288 000043D7 E8E30A0000 <1> call getf1 ; calling point in 'getf' from 'rw1' 15289 <1> ; jsr r0,getf / get i-number of the file in r1 15290 <1> ; AX = I-number of the file ; negative i-number means write 15291 <1> ; 13/05/2015 15292 000043DC 6683F801 <1> cmp ax, 1 15293 000043E0 7217 <1> jb short rw2 15294 <1> ; 15295 000043E2 890D[68740000] <1> mov [u.base], ecx ; buffer address/offset 15296 <1> ;(in the user's virtual memory space) 15297 000043E8 8915[6C740000] <1> mov [u.count], edx 15298 <1> ; 14/05/2015 15299 000043EE C705[9D740000]0000- <1> mov dword [u.error], 0 ; reset the last error code 15300 000043F6 0000 <1> 15301 000043F8 C3 <1> retn 15302 <1> ; rts r0 15303 <1> rw2: 15304 <1> ; 13/05/2015 15305 000043F9 C705[9D740000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 15306 00004401 0000 <1> 15307 00004403 C3 <1> retn 15308 <1> rw3: 15309 <1> ; 13/05/2015 15310 00004404 C705[9D740000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 15311 0000440C 0000 <1> 15312 0000440E F9 <1> stc 15313 0000440F C3 <1> retn 15314 <1> 15315 <1> sysopen: ; 15316 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15317 <1> ; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1) 15318 <1> ; 15319 <1> ; 'sysopen' opens a file in following manner: 15320 <1> ; 1) The second argument in a sysopen says whether to 15321 <1> ; open the file ro read (0) or write (>0). 15322 <1> ; 2) I-node of the particular file is obtained via 'namei'. 15323 <1> ; 3) The file is opened by 'iopen'. 15324 <1> ; 4) Next housekeeping is performed on the fsp table 15325 <1> ; and the user's open file list - u.fp. 15326 <1> ; a) u.fp and fsp are scanned for the next available slot. 15327 <1> ; b) An entry for the file is created in the fsp table. 15328 <1> ; c) The number of this entry is put on u.fp list. 15329 <1> ; d) The file descriptor index to u.fp list is pointed 15330 <1> ; to by u.r0. 15331 <1> ; 15332 <1> ; Calling sequence: 15333 <1> ; sysopen; name; mode 15334 <1> ; Arguments: 15335 <1> ; name - file name or path name 15336 <1> ; mode - 0 to open for reading 15337 <1> ; 1 to open for writing 15338 <1> ; Inputs: (arguments) 15339 <1> ; Outputs: *u.r0 - index to u.fp list (the file descriptor) 15340 <1> ; is put into r0's location on the stack. 15341 <1> ; ............................................................... 15342 <1> ; 15343 <1> ; Retro UNIX 8086 v1 modification: 15344 <1> ; 'sysopen' system call has two arguments; so, 15345 <1> ; * 1st argument, name is pointed to by BX register 15346 <1> ; * 2nd argument, mode is in CX register 15347 <1> ; 15348 <1> ; AX register (will be restored via 'u.r0') will return 15349 <1> ; to the user with the file descriptor/number 15350 <1> ; (index to u.fp list). 15351 <1> ; 15352 <1> ;call arg2 15353 <1> ; * name - 'u.namep' points to address of file/path name 15354 <1> ; in the user's program segment ('u.segmnt') 15355 <1> ; with offset in BX register (as sysopen argument 1). 15356 <1> ; * mode - sysopen argument 2 is in CX register 15357 <1> ; which is on top of stack. 15358 <1> ; 15359 <1> ; jsr r0,arg2 / get sys args into u.namep and on stack 15360 <1> ; 15361 <1> ; system call registers: ebx, ecx (through 'sysenter') 15362 <1> 15363 00004410 891D[60740000] <1> mov [u.namep], ebx 15364 00004416 6651 <1> push cx 15365 00004418 E8D90A0000 <1> call namei 15366 <1> ; jsr r0,namei / i-number of file in r1 15367 <1> ;and ax, ax 15368 <1> ;jz error ; File not found 15369 0000441D 723B <1> jc short fnotfound ; 14/05/2015 15370 <1> ;jc error ; 27/05/2013 15371 <1> ; br error2 / file not found 15372 0000441F 665A <1> pop dx ; mode 15373 00004421 6652 <1> push dx 15374 <1> ;or dx, dx 15375 00004423 08D2 <1> or dl, dl 15376 <1> ; tst (sp) / is mode = 0 (2nd arg of call; 15377 <1> ; / 0 means, open for read) 15378 00004425 7403 <1> jz short sysopen_0 15379 <1> ; beq 1f / yes, leave i-number positive 15380 <1> syscreat_0: ; 27/12/2015 15381 00004427 66F7D8 <1> neg ax 15382 <1> ; neg r1 / open for writing so make i-number negative 15383 <1> sysopen_0: ;1: 15384 0000442A E8361A0000 <1> call iopen 15385 <1> ;jsr r0,iopen / open file whose i-number is in r1 15386 0000442F 665A <1> pop dx 15387 <1> ;and dx, dx 15388 00004431 20D2 <1> and dl, dl 15389 <1> ; tst (sp)+ / pop the stack and test the mode 15390 00004433 7403 <1> jz short sysopen_2 15391 <1> ; beq op1 / is open for read op1 15392 <1> sysopen_1: ;op0: 15393 00004435 66F7D8 <1> neg ax 15394 <1> ; neg r1 15395 <1> ;/ make i-number positive if open for writing [???] 15396 <1> ;; NOTE: iopen always make i-number positive. 15397 <1> ;; Here i-number becomes negative again. [22/05/2013] 15398 <1> sysopen_2: ;op1: 15399 00004438 31F6 <1> xor esi, esi 15400 <1> ; clr r2 / clear registers 15401 0000443A 31DB <1> xor ebx, ebx 15402 <1> ; clr r3 15403 <1> sysopen_3: ;1: / scan the list of entries in fsp table 15404 0000443C 389E[4E740000] <1> cmp [esi+u.fp], bl ; 0 15405 <1> ; tstb u.fp(r2) / test the entry in the u.fp list 15406 00004442 7625 <1> jna short sysopen_4 15407 <1> ; beq 1f / if byte in list is 0 branch 15408 00004444 46 <1> inc esi 15409 <1> ; inc r2 / bump r2 so next byte can be checked 15410 00004445 6683FE0A <1> cmp si, 10 15411 <1> ; cmp r2,$10. / reached end of list? 15412 00004449 72F1 <1> jb short sysopen_3 15413 <1> ; blt 1b / no, go back 15414 <1> toomanyf: 15415 <1> ; 14/05/2015 15416 0000444B C705[9D740000]0D00- <1> mov dword [u.error], ERR_TOO_MANY_FILES ; too many open files ! 15417 00004453 0000 <1> 15418 00004455 E9E0FBFFFF <1> jmp error 15419 <1> ; br error2 / yes, error (no files open) 15420 <1> fnotfound: 15421 <1> ; 14/05/2015 15422 0000445A C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; file not found ! 15423 00004462 0000 <1> 15424 00004464 E9D1FBFFFF <1> jmp error 15425 <1> 15426 <1> sysopen_4: ; 1: 15427 00004469 6683BB[16720000]00 <1> cmp word [ebx+fsp], 0 15428 <1> ; tst fsp(r3) / scan fsp entries 15429 00004471 7610 <1> jna short sysopen_5 15430 <1> ; beq 1f / if 0 branch 15431 <1> ; 14/05/2015 - Retro UNIX 386 v1 modification ! 15432 00004473 6683C30A <1> add bx, 10 ; fsp structure size = 10 bytes/entry 15433 <1> ; add $8.,r3 / add 8 to r3 15434 <1> ; / to bump it to next entry mfsp table 15435 00004477 6681FBF401 <1> cmp bx, nfiles*10 15436 <1> ; cmp r3,$[nfiles*8.] / done scanning 15437 0000447C 72EB <1> jb short sysopen_4 15438 <1> ; blt 1b / no, back 15439 0000447E E9B7FBFFFF <1> jmp error 15440 <1> ; br error2 / yes, error 15441 <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table 15442 00004483 668983[16720000] <1> mov [ebx+fsp], ax 15443 <1> ; mov r1,fsp(r3) / put i-number of open file 15444 <1> ; / into next available entry in fsp table, 15445 0000448A 668B3D[2E740000] <1> mov di, [cdev] ; word ? byte ? 15446 00004491 6689BB[18720000] <1> mov [ebx+fsp+2], di ; device number 15447 <1> ; mov cdev,fsp+2(r3) / put # of device in next word 15448 00004498 31FF <1> xor edi, edi 15449 0000449A 89BB[1A720000] <1> mov [ebx+fsp+4], edi ; offset pointer (0) 15450 <1> ; clr fsp+4(r3) 15451 000044A0 6689BB[1E720000] <1> mov [ebx+fsp+8], di ; open count (0), deleted flag (0) 15452 <1> ; clr fsp+6(r3) / clear the next two words 15453 000044A7 89D8 <1> mov eax, ebx 15454 000044A9 B30A <1> mov bl, 10 15455 000044AB F6F3 <1> div bl 15456 <1> ; asr r3 15457 <1> ; asr r3 / divide by 8 15458 <1> ; asr r3 ; / to get number of the fsp entry-1 15459 000044AD FEC0 <1> inc al 15460 <1> ; inc r3 / add 1 to get fsp entry number 15461 000044AF 8886[4E740000] <1> mov [esi+u.fp], al 15462 <1> ; movb r3,u.fp(r2) / move entry number into 15463 <1> ; / next available slot in u.fp list 15464 000044B5 8935[48740000] <1> mov [u.r0], esi 15465 <1> ; mov r2,*u.r0 / move index to u.fp list 15466 <1> ; / into r0 loc on stack 15467 000044BB E99AFBFFFF <1> jmp sysret 15468 <1> ; br sysret2 15469 <1> 15470 <1> ; 15471 <1> ; 'fsp' table (10 bytes/entry) 15472 <1> ; bit 15 bit 0 15473 <1> ; ---|------------------------------------------- 15474 <1> ; r/w| i-number of open file 15475 <1> ; ---|------------------------------------------- 15476 <1> ; device number 15477 <1> ; ----------------------------------------------- 15478 <1> ; offset pointer, r/w pointer to file (bit 0-15) 15479 <1> ; ----------------------------------------------- 15480 <1> ; offset pointer, r/w pointer to file (bit 16-31) 15481 <1> ; ----------------------|------------------------ 15482 <1> ; flag that says file | number of processes 15483 <1> ; has been deleted | that have file open 15484 <1> ; ----------------------|------------------------ 15485 <1> ; 15486 <1> 15487 <1> syscreat: ; < create file > 15488 <1> ; 27/12/2015 (Retro UNIX 386 v1.1) 15489 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15490 <1> ; 27/05/2013 (Retro UNIX 8086 v1) 15491 <1> ; 15492 <1> ; 'syscreat' called with two arguments; name and mode. 15493 <1> ; u.namep points to name of the file and mode is put 15494 <1> ; on the stack. 'namei' is called to get i-number of the file. 15495 <1> ; If the file aready exists, it's mode and owner remain 15496 <1> ; unchanged, but it is truncated to zero length. If the file 15497 <1> ; did not exist, an i-node is created with the new mode via 15498 <1> ; 'maknod' whether or not the file already existed, it is 15499 <1> ; open for writing. The fsp table is then searched for a free 15500 <1> ; entry. When a free entry is found, proper data is placed 15501 <1> ; in it and the number of this entry is put in the u.fp list. 15502 <1> ; The index to the u.fp (also know as the file descriptor) 15503 <1> ; is put in the user's r0. 15504 <1> ; 15505 <1> ; Calling sequence: 15506 <1> ; syscreate; name; mode 15507 <1> ; Arguments: 15508 <1> ; name - name of the file to be created 15509 <1> ; mode - mode of the file to be created 15510 <1> ; Inputs: (arguments) 15511 <1> ; Outputs: *u.r0 - index to u.fp list 15512 <1> ; (the file descriptor of new file) 15513 <1> ; ............................................................... 15514 <1> ; 15515 <1> ; Retro UNIX 8086 v1 modification: 15516 <1> ; 'syscreate' system call has two arguments; so, 15517 <1> ; * 1st argument, name is pointed to by BX register 15518 <1> ; * 2nd argument, mode is in CX register 15519 <1> ; 15520 <1> ; AX register (will be restored via 'u.r0') will return 15521 <1> ; to the user with the file descriptor/number 15522 <1> ; (index to u.fp list). 15523 <1> ; 15524 <1> ;call arg2 15525 <1> ; * name - 'u.namep' points to address of file/path name 15526 <1> ; in the user's program segment ('u.segmnt') 15527 <1> ; with offset in BX register (as sysopen argument 1). 15528 <1> ; * mode - sysopen argument 2 is in CX register 15529 <1> ; which is on top of stack. 15530 <1> ; 15531 <1> ; jsr r0,arg2 / put file name in u.namep put mode 15532 <1> ; / on stack 15533 000044C0 891D[60740000] <1> mov [u.namep], ebx ; file name address 15534 000044C6 6651 <1> push cx ; mode 15535 000044C8 E8290A0000 <1> call namei 15536 <1> ; jsr r0,namei / get the i-number 15537 <1> ;and ax, ax 15538 <1> ;jz short syscreat_1 15539 000044CD 721E <1> jc short syscreat_1 15540 <1> ; br 2f / if file doesn't exist 2f 15541 <1> ; 27/12/2015 15542 000044CF 6683F829 <1> cmp ax, 41 ; device inode ? 15543 000044D3 0F824EFFFFFF <1> jb syscreat_0 ; yes 15544 <1> ; 15545 000044D9 66F7D8 <1> neg ax 15546 <1> ; neg r1 / if file already exists make i-number 15547 <1> ; / negative (open for writing) 15548 000044DC E884190000 <1> call iopen 15549 <1> ; jsr r0,iopen / 15550 000044E1 E835130000 <1> call itrunc 15551 <1> ; jsr r0,itrunc / truncate to 0 length 15552 000044E6 6659 <1> pop cx ; pop mode (did not exist in original Unix v1 !?) 15553 000044E8 E948FFFFFF <1> jmp sysopen_1 15554 <1> ; br op0 15555 <1> syscreat_1: ; 2: / file doesn't exist 15556 000044ED 6658 <1> pop ax 15557 <1> ; mov (sp)+,r1 / put the mode in r1 15558 000044EF 30E4 <1> xor ah, ah 15559 <1> ; bic $!377,r1 / clear upper byte 15560 000044F1 E8D30C0000 <1> call maknod 15561 <1> ; jsr r0,maknod / make an i-node for this file 15562 000044F6 66A1[7A740000] <1> mov ax, [u.dirbuf] 15563 <1> ; mov u.dirbuf,r1 / put i-number 15564 <1> ; / for this new file in r1 15565 000044FC E934FFFFFF <1> jmp sysopen_1 15566 <1> ; br op0 / open the file 15567 <1> 15568 <1> sysmkdir: ; < make directory > 15569 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15570 <1> ; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 15571 <1> ; 15572 <1> ; 'sysmkdir' creates an empty directory whose name is 15573 <1> ; pointed to by arg 1. The mode of the directory is arg 2. 15574 <1> ; The special entries '.' and '..' are not present. 15575 <1> ; Errors are indicated if the directory already exists or 15576 <1> ; user is not the super user. 15577 <1> ; 15578 <1> ; Calling sequence: 15579 <1> ; sysmkdir; name; mode 15580 <1> ; Arguments: 15581 <1> ; name - points to the name of the directory 15582 <1> ; mode - mode of the directory 15583 <1> ; Inputs: (arguments) 15584 <1> ; Outputs: - 15585 <1> ; (sets 'directory' flag to 1; 15586 <1> ; 'set user id on execution' and 'executable' flags to 0) 15587 <1> ; ............................................................... 15588 <1> ; 15589 <1> ; Retro UNIX 8086 v1 modification: 15590 <1> ; 'sysmkdir' system call has two arguments; so, 15591 <1> ; * 1st argument, name is pointed to by BX register 15592 <1> ; * 2nd argument, mode is in CX register 15593 <1> ; 15594 <1> 15595 <1> ; / make a directory 15596 <1> 15597 <1> ;call arg2 15598 <1> ; * name - 'u.namep' points to address of file/path name 15599 <1> ; in the user's program segment ('u.segmnt') 15600 <1> ; with offset in BX register (as sysopen argument 1). 15601 <1> ; * mode - sysopen argument 2 is in CX register 15602 <1> ; which is on top of stack. 15603 <1> 15604 <1> ; jsr r0,arg2 / put file name in u.namep put mode 15605 <1> ; / on stack 15606 00004501 891D[60740000] <1> mov [u.namep], ebx 15607 00004507 6651 <1> push cx ; mode 15608 00004509 E8E8090000 <1> call namei 15609 <1> ; jsr r0,namei / get the i-number 15610 <1> ; br .+4 / if file not found branch around error 15611 <1> ;xor ax, ax 15612 <1> ;jnz error 15613 0000450E 731C <1> jnc short dir_exists ; 14/05/2015 15614 <1> ;jnc error 15615 <1> ; br error2 / directory already exists (error) 15616 00004510 803D[94740000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 15617 <1> ;tstb u.uid / is user the super user 15618 00004517 7622 <1> jna short dir_access_err ; 14/05/2015 15619 <1> ;jna error 15620 <1> ;bne error2 / no, not allowed 15621 00004519 6658 <1> pop ax 15622 <1> ;mov (sp)+,r1 / put the mode in r1 15623 0000451B 6683E0CF <1> and ax, 0FFCFh ; 1111111111001111b 15624 <1> ;bic $!317,r1 / all but su and ex 15625 <1> ;or ax , 4000h ; 1011111111111111b 15626 0000451F 80CC40 <1> or ah, 40h ; Set bit 14 to 1 15627 <1> ;bis $40000,r1 / directory flag 15628 00004522 E8A20C0000 <1> call maknod 15629 <1> ;jsr r0,maknod / make the i-node for the directory 15630 00004527 E92EFBFFFF <1> jmp sysret 15631 <1> ;br sysret2 / 15632 <1> dir_exists: 15633 <1> ; 14/05/2015 15634 0000452C C705[9D740000]0E00- <1> mov dword [u.error], ERR_DIR_EXISTS ; dir. already exists ! 15635 00004534 0000 <1> 15636 00004536 E9FFFAFFFF <1> jmp error 15637 <1> dir_access_err: 15638 <1> ; 14/05/2015 15639 0000453B C705[9D740000]0B00- <1> mov dword [u.error], ERR_DIR_ACCESS ; permission denied ! 15640 00004543 0000 <1> 15641 00004545 E9F0FAFFFF <1> jmp error 15642 <1> 15643 <1> sysclose: ; 15644 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15645 <1> ; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1) 15646 <1> ; 15647 <1> ; 'sysclose', given a file descriptor in 'u.r0', closes the 15648 <1> ; associated file. The file descriptor (index to 'u.fp' list) 15649 <1> ; is put in r1 and 'fclose' is called. 15650 <1> ; 15651 <1> ; Calling sequence: 15652 <1> ; sysclose 15653 <1> ; Arguments: 15654 <1> ; - 15655 <1> ; Inputs: *u.r0 - file descriptor 15656 <1> ; Outputs: - 15657 <1> ; ............................................................... 15658 <1> ; 15659 <1> ; Retro UNIX 8086 v1 modification: 15660 <1> ; The user/application program puts file descriptor 15661 <1> ; in BX register as 'sysclose' system call argument. 15662 <1> ; (argument transfer method 1) 15663 <1> 15664 <1> ; / close the file 15665 <1> 15666 0000454A 89D8 <1> mov eax, ebx 15667 0000454C E823090000 <1> call fclose 15668 <1> ; mov *u.r0,r1 / move index to u.fp list into r1 15669 <1> ; jsr r0,fclose / close the file 15670 <1> ; br error2 / unknown file descriptor 15671 <1> ; br sysret2 15672 <1> ; 14/05/2015 15673 00004551 0F8303FBFFFF <1> jnc sysret 15674 00004557 C705[9D740000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; file not open ! 15675 0000455F 0000 <1> 15676 00004561 E9D4FAFFFF <1> jmp error 15677 <1> 15678 <1> sysemt: 15679 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15680 <1> ; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1) 15681 <1> ; 15682 <1> ; Retro UNIX 8086 v1 modification: 15683 <1> ; 'Enable Multi Tasking' system call instead 15684 <1> ; of 'Emulator Trap' in original UNIX v1 for PDP-11. 15685 <1> ; 15686 <1> ; Retro UNIX 8086 v1 feature only! 15687 <1> ; Using purpose: Kernel will start without time-out 15688 <1> ; (internal clock/timer) functionality. 15689 <1> ; Then etc/init will enable clock/timer for 15690 <1> ; multi tasking. (Then it will not be disabled again 15691 <1> ; except hardware reset/restart.) 15692 <1> ; 15693 <1> 15694 00004566 803D[94740000]00 <1> cmp byte [u.uid], 0 ; root ? 15695 <1> ;ja error 15696 0000456D 0F8770FBFFFF <1> ja badsys ; 14/05/2015 15697 <1> emt_0: 15698 00004573 FA <1> cli 15699 00004574 21DB <1> and ebx, ebx 15700 00004576 7410 <1> jz short emt_2 15701 <1> ; Enable multi tasking -time sharing- 15702 00004578 B8[7D540000] <1> mov eax, clock 15703 <1> emt_1: 15704 0000457D A3[D8070000] <1> mov [x_timer], eax 15705 00004582 FB <1> sti 15706 00004583 E9D2FAFFFF <1> jmp sysret 15707 <1> emt_2: 15708 <1> ; Disable multi tasking -time sharing- 15709 00004588 B8[E0070000] <1> mov eax, u_timer 15710 0000458D EBEE <1> jmp short emt_1 15711 <1> 15712 <1> ; Original UNIX v1 'sysemt' routine 15713 <1> ;sysemt: 15714 <1> ; 15715 <1> ;jsr r0,arg; 30 / put the argument of the sysemt call 15716 <1> ; / in loc 30 15717 <1> ;cmp 30,$core / was the argument a lower address 15718 <1> ; / than core 15719 <1> ;blo 1f / yes, rtssym 15720 <1> ;cmp 30,$ecore / no, was it higher than "core" 15721 <1> ; / and less than "ecore" 15722 <1> ;blo 2f / yes, sysret2 15723 <1> ;1: 15724 <1> ;mov $rtssym,30 15725 <1> ;2: 15726 <1> ;br sysret2 15727 <1> 15728 <1> sysilgins: 15729 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 15730 <1> ; 03/06/2013 15731 <1> ; Retro UNIX 8086 v1 modification: 15732 <1> ; not a valid system call ! (not in use) 15733 <1> ; 15734 0000458F E94FFBFFFF <1> jmp badsys 15735 <1> ;jmp error 15736 <1> ;;jmp sysret 15737 <1> 15738 <1> ; Original UNIX v1 'sysemt' routine 15739 <1> ;sysilgins: / calculate proper illegal instruction trap address 15740 <1> ;jsr r0,arg; 10 / take address from sysilgins call 15741 <1> ;/ put it in loc 8., 15742 <1> ;cmp 10,$core / making it the illegal instruction 15743 <1> ; / trap address 15744 <1> ;blo 1f / is the address a user core address? 15745 <1> ; / yes, go to 2f 15746 <1> ;cmp 10,$ecore 15747 <1> ;blo 2f 15748 <1> ;1: 15749 <1> ;mov $fpsym,10 / no, make 'fpsum' the illegal 15750 <1> ; / instruction trap address for the system 15751 <1> ;2: 15752 <1> ;br sysret2 / return to the caller via 'sysret' 15753 <1> 15754 <1> sysmdate: ; < change the modification time of a file > 15755 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 15756 <1> ; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 15757 <1> ; 15758 <1> ; 'sysmdate' is given a file name. It gets inode of this 15759 <1> ; file into core. The user is checked if he is the owner 15760 <1> ; or super user. If he is neither an error occurs. 15761 <1> ; 'setimod' is then called to set the i-node modification 15762 <1> ; byte and the modification time, but the modification time 15763 <1> ; is overwritten by whatever get put on the stack during 15764 <1> ; a 'systime' system call. This calls are restricted to 15765 <1> ; the super user. 15766 <1> ; 15767 <1> ; Calling sequence: 15768 <1> ; sysmdate; name 15769 <1> ; Arguments: 15770 <1> ; name - points to the name of file 15771 <1> ; Inputs: (arguments) 15772 <1> ; Outputs: - 15773 <1> ; ............................................................... 15774 <1> ; 15775 <1> ; Retro UNIX 8086 v1 modification: 15776 <1> ; The user/application program puts address 15777 <1> ; of the file name in BX register 15778 <1> ; as 'sysmdate' system call argument. 15779 <1> ; 15780 <1> ; / change the modification time of a file 15781 <1> ; jsr r0,arg; u.namep / point u.namep to the file name 15782 00004594 891D[60740000] <1> mov [u.namep], ebx 15783 0000459A E857090000 <1> call namei 15784 <1> ; jsr r0,namei / get its i-number 15785 0000459F 0F82B5FEFFFF <1> jc fnotfound ; file not found ! 15786 <1> ;jc error 15787 <1> ; br error2 / no, such file 15788 000045A5 E83C110000 <1> call iget 15789 <1> ; jsr r0,iget / get i-node into core 15790 000045AA A0[94740000] <1> mov al, [u.uid] 15791 000045AF 3A05[19710000] <1> cmp al, [i.uid] 15792 <1> ; cmpb u.uid,i.uid / is user same as owner 15793 000045B5 7413 <1> je short mdate_1 15794 <1> ; beq 1f / yes 15795 000045B7 20C0 <1> and al, al 15796 <1> ; tstb u.uid / no, is user the super user 15797 <1> ;jnz error 15798 <1> ; bne error2 / no, error 15799 000045B9 740F <1> jz short mdate_1 15800 000045BB C705[9D740000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 15801 000045C3 0000 <1> 15802 000045C5 E970FAFFFF <1> jmp error 15803 <1> mdate_1: ;1: 15804 000045CA E82A120000 <1> call setimod 15805 <1> ; jsr r0,setimod / fill in modification data, 15806 <1> ; / time etc. 15807 000045CF BE[B0700000] <1> mov esi, p_time 15808 000045D4 BF[30710000] <1> mov edi, i.mtim 15809 000045D9 A5 <1> movsd 15810 <1> ; mov 4(sp),i.mtim / move present time to 15811 <1> ; mov 2(sp),i.mtim+2 / modification time 15812 000045DA E97BFAFFFF <1> jmp sysret 15813 <1> ; br sysret2 15814 <1> 15815 <1> sysstty: ; < set tty status and mode > 15816 <1> ; 17/11/2015 15817 <1> ; 12/11/2015 15818 <1> ; 29/10/2015 15819 <1> ; 17/10/2015 15820 <1> ; 13/10/2015 15821 <1> ; 29/06/2015 15822 <1> ; 27/06/2015 (Retro UNIX 386 v1 - Beginning) 15823 <1> ; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1) 15824 <1> ; 15825 <1> ; 'sysstty' sets the status and mode of the typewriter 15826 <1> ; whose file descriptor is in (u.r0). 15827 <1> ; 15828 <1> ; Calling sequence: 15829 <1> ; sysstty; arg 15830 <1> ; Arguments: 15831 <1> ; arg - address of 3 consequitive words that contain 15832 <1> ; the source of status data 15833 <1> ; Inputs: ((*u.r0 - file descriptor & argument)) 15834 <1> ; Outputs: ((status in address which is pointed to by arg)) 15835 <1> ; ............................................................... 15836 <1> ; 15837 <1> ; Retro UNIX 8086 v1 modification: 15838 <1> ; 'sysstty' system call will set the tty 15839 <1> ; (clear keyboard buffer and set cursor position) 15840 <1> ; in following manner: 15841 <1> ; NOTE: All of tty setting functions are here (16/01/2014) 15842 <1> ; 15843 <1> ; Inputs: 15844 <1> ; BX = 0 --> means 15845 <1> ; If CL = FFh 15846 <1> ; set cursor position for console tty, only 15847 <1> ; CH will be ignored (char. will not be written) 15848 <1> ; If CH = 0 (CL < FFh) 15849 <1> ; set console tty for (current) process 15850 <1> ; CL = tty number (0 to 9) 15851 <1> ; (If CH = 0, character will not be written) 15852 <1> ; If CH > 0 (CL < FFh) 15853 <1> ; CL = tty number (0 to 9) 15854 <1> ; CH = character will be written 15855 <1> ; at requested cursor position (in DX) 15856 <1> ; DX = cursor position for tty number 0 to 7. 15857 <1> ; (only tty number 0 to 7) 15858 <1> ; DL = communication parameters (for serial ports) 15859 <1> ; (only for COM1 and COM2 serial ports) 15860 <1> ; DH < 0FFh -> DL is valid, initialize serial port 15861 <1> ; or set cursor position 15862 <1> ; DH = 0FFh -> DL is not valid 15863 <1> ; do not set serial port parameters 15864 <1> ; or do not set cursor position 15865 <1> ; 15866 <1> ; BX > 0 --> points to name of tty 15867 <1> ; CH > 0 --> 15868 <1> ; CH = character will be written in current 15869 <1> ; cursor position (for tty number from 0 to 7) 15870 <1> ; or character will be sent to serial port 15871 <1> ; (for tty number 8 or 9) 15872 <1> ; CL = color of the character if tty number < 8. 15873 <1> ; CH = 0 --> Do not write a character, 15874 <1> ; set mode (tty 8 to 9) or 15875 <1> ; set current cursor positions (tty 0 to 7) only. 15876 <1> ; DX = cursor position for tty number 0 to 7. 15877 <1> ; DH = FFh --> Do not set cursor pos (or comm. params.) 15878 <1> ; (DL is not valid) 15879 <1> ; DL = communication parameters 15880 <1> ; for tty number 8 or 9 (COM1 or COM2). 15881 <1> ; Outputs: 15882 <1> ; cf = 0 -> OK 15883 <1> ; AL = tty number (0 to 9) 15884 <1> ; AH = line status if tty number is 8 or 9 15885 <1> ; AH = process number (of the caller) 15886 <1> ; cf = 1 means error (requested tty is not ready) 15887 <1> ; AH = FFh if the tty is locked 15888 <1> ; (owned by another process) 15889 <1> ; = process number (of the caller) 15890 <1> ; (if < FFh and tty number < 8) 15891 <1> ; AL = tty number (0FFh if it does not exist) 15892 <1> ; AH = line status if tty number is 8 or 9 15893 <1> ; NOTE: Video page will be cleared if cf = 0. 15894 <1> ; 15895 <1> ; 27/06/2015 (32 bit modifications) 15896 <1> ; 14/01/2014 15897 000045DF 31C0 <1> xor eax, eax 15898 000045E1 6648 <1> dec ax ; 17/10/2015 15899 000045E3 A3[48740000] <1> mov [u.r0], eax ; 0FFFFh 15900 000045E8 21DB <1> and ebx, ebx 15901 000045EA 0F85CB000000 <1> jnz sysstty_6 15902 <1> ; set console tty 15903 <1> ; 29/10/2015 15904 <1> ; 17/01/2014 15905 000045F0 80F909 <1> cmp cl, 9 15906 000045F3 7613 <1> jna short sysstty_0 15907 <1> ; 17/11/2015 15908 000045F5 80F9FF <1> cmp cl, 0FFh 15909 000045F8 7202 <1> jb short sysstty_13 15910 000045FA 88CD <1> mov ch, cl ; force CH value to FFh 15911 <1> sysstty_13: 15912 000045FC 8A1D[97740000] <1> mov bl, [u.uno] ; process number 15913 00004602 8A8B[95710000] <1> mov cl, [ebx+p.ttyc-1] ; current/console tty 15914 <1> sysstty_0: 15915 <1> ; 29/06/2015 15916 00004608 6652 <1> push dx 15917 0000460A 6651 <1> push cx 15918 0000460C 30D2 <1> xor dl, dl ; sysstty call sign 15919 0000460E 88C8 <1> mov al, cl 15920 00004610 A2[48740000] <1> mov [u.r0], al ; tyy number (0 to 9) 15921 00004615 E8E5180000 <1> call ottyp 15922 0000461A 6659 <1> pop cx 15923 0000461C 665A <1> pop dx 15924 <1> ; 15925 0000461E 7257 <1> jc short sysstty_pd_err 15926 <1> ; 15927 00004620 80F908 <1> cmp cl, 8 15928 00004623 7222 <1> jb short sysstty_2 15929 <1> ; 15930 00004625 80FEFF <1> cmp dh, 0FFh 15931 00004628 741D <1> je short sysstty_2 15932 <1> ; set communication parameters for serial ports 15933 <1> ; 29/10/2015 15934 0000462A 88D4 <1> mov ah, dl ; communication parameters 15935 <1> ; ah = 0E3h = 11100011b = 115200 baud, 15936 <1> ; THRE int + RDA int 15937 <1> ; ah = 23h = 00100011b = 9600 baud, 15938 <1> ; THRE int + RDA int 15939 0000462C 28C0 <1> sub al, al ; 0 15940 <1> ; 12/07/2014 15941 0000462E 80F909 <1> cmp cl, 9 15942 00004631 7202 <1> jb short sysstty_1 15943 00004633 FEC0 <1> inc al 15944 <1> sysstty_1: 15945 00004635 6651 <1> push cx 15946 <1> ; 29/06/2015 15947 00004637 E8ABF4FFFF <1> call sp_setp ; Set serial port communication parameters 15948 0000463C 66890D[49740000] <1> mov [u.r0+1], cx ; Line status (ah) 15949 <1> ; Modem status (EAX bits 16 to 23) 15950 00004643 6659 <1> pop cx 15951 00004645 7265 <1> jc short sysstty_tmout_err ; 29/10/2015 15952 <1> sysstty_2: 15953 <1> ; 17/01/2014 15954 00004647 20ED <1> and ch, ch ; set cursor position 15955 <1> ; or comm. parameters ONLY 15956 00004649 750D <1> jnz short sysstty_3 15957 0000464B 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 15958 00004652 888B[95710000] <1> mov [ebx+p.ttyc-1], cl ; console tty 15959 <1> sysstty_3: 15960 <1> ; 16/01/2014 15961 00004658 88E8 <1> mov al, ch ; character ; 0 to FFh 15962 <1> ; 17/11/2015 15963 0000465A B507 <1> mov ch, 7 ; Default color (light gray) 15964 0000465C 38E9 <1> cmp cl, ch ; 7 (tty number) 15965 0000465E 0F86C5000000 <1> jna sysstty_9 15966 <1> sysstty_12: 15967 <1> ;; BX = 0, CL = 8 or CL = 9 15968 <1> ; (Set specified serial port as console tty port) 15969 <1> ; CH = character to be written 15970 <1> ; 15/04/2014 15971 <1> ; CH = 0 --> initialization only 15972 <1> ; AL = character 15973 <1> ; 26/06/2014 15974 00004664 880D[9C740000] <1> mov [u.ttyn], cl 15975 <1> ; 12/07/2014 15976 0000466A 88CC <1> mov ah, cl ; tty number (8 or 9) 15977 0000466C 20C0 <1> and al, al 15978 0000466E 7416 <1> jz short sysstty_4 ; al = ch = 0 15979 <1> ; 04/07/2014 15980 00004670 E8981E0000 <1> call sndc 15981 <1> ; 12/07/2014 15982 00004675 EB1B <1> jmp short sysstty_5 15983 <1> sysstty_pd_err: ; 29/06/2015 15984 <1> ; 'permission denied !' error 15985 00004677 C705[9D740000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER 15986 0000467F 0000 <1> 15987 00004681 E9B4F9FFFF <1> jmp error 15988 <1> sysstty_4: 15989 <1> ; 12/07/2014 15990 <1> ;xchg ah, al ; al = 0 -> al = ah, ah = 0 15991 00004686 88E0 <1> mov al, ah ; 29/06/2015 15992 00004688 2C08 <1> sub al, 8 15993 <1> ; 27/06/2015 15994 0000468A E850F4FFFF <1> call sp_status ; get serial port status 15995 <1> ; AL = Line status, AH = Modem status 15996 <1> ; 12/11/2015 15997 0000468F 3C80 <1> cmp al, 80h 15998 00004691 F5 <1> cmc 15999 <1> sysstty_5: 16000 00004692 66A3[49740000] <1> mov [u.r0+1], ax ; ah = line status 16001 <1> ; EAX bits 16-23 = modem status 16002 00004698 9C <1> pushf 16003 00004699 30D2 <1> xor dl, dl ; sysstty call sign 16004 0000469B A0[9C740000] <1> mov al, [u.ttyn] ; 26/06/2014 16005 000046A0 E86D190000 <1> call cttyp 16006 000046A5 9D <1> popf 16007 000046A6 0F83AEF9FFFF <1> jnc sysret ; time out error 16008 <1> 16009 <1> sysstty_tmout_err: 16010 000046AC C705[9D740000]1900- <1> mov dword [u.error], ERR_TIME_OUT 16011 000046B4 0000 <1> 16012 000046B6 E97FF9FFFF <1> jmp error 16013 <1> sysstty_6: 16014 000046BB 6652 <1> push dx 16015 000046BD 6651 <1> push cx 16016 000046BF 891D[60740000] <1> mov [u.namep], ebx 16017 000046C5 E82C080000 <1> call namei 16018 000046CA 6659 <1> pop cx 16019 000046CC 665A <1> pop dx 16020 000046CE 720E <1> jc short sysstty_inv_dn 16021 <1> ; 16022 000046D0 6683F813 <1> cmp ax, 19 ; inode number of /dev/COM2 16023 000046D4 7708 <1> ja short sysstty_inv_dn ; 27/06/2015 16024 <1> ; 16025 000046D6 3C0A <1> cmp al, 10 ; /dev/tty0 .. /dev/tty7 16026 <1> ; /dev/COM1, /dev/COM2 16027 000046D8 7213 <1> jb short sysstty_7 16028 000046DA 2C0A <1> sub al, 10 16029 000046DC EB20 <1> jmp short sysstty_8 16030 <1> sysstty_inv_dn: 16031 <1> ; 27/06/2015 16032 <1> ; Invalid device name (not a tty) ! error 16033 <1> ; (Device is not a tty or device name not found) 16034 000046DE C705[9D740000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 16035 000046E6 0000 <1> 16036 000046E8 E94DF9FFFF <1> jmp error 16037 <1> sysstty_7: 16038 000046ED 3C01 <1> cmp al, 1 ; /dev/tty 16039 000046EF 75ED <1> jne short sysstty_inv_dn ; 27/06/2015 16040 000046F1 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 16041 000046F8 8A83[95710000] <1> mov al, [ebx+p.ttyc-1] ; console tty 16042 <1> sysstty_8: 16043 000046FE A2[48740000] <1> mov [u.r0], al 16044 00004703 6652 <1> push dx 16045 00004705 6650 <1> push ax 16046 00004707 6651 <1> push cx 16047 00004709 E8F1170000 <1> call ottyp 16048 0000470E 6659 <1> pop cx 16049 00004710 6658 <1> pop ax 16050 00004712 665A <1> pop dx 16051 00004714 0F825DFFFFFF <1> jc sysstty_pd_err ; 'permission denied !' 16052 <1> ; 29/10/2015 16053 0000471A 86E9 <1> xchg ch, cl 16054 <1> ; cl = character, ch = color code 16055 0000471C 86C1 <1> xchg al, cl 16056 <1> ; al = character, cl = tty number 16057 0000471E 80F907 <1> cmp cl, 7 16058 00004721 0F873DFFFFFF <1> ja sysstty_12 16059 <1> ; 16060 <1> ; 16/01/2014 16061 00004727 30FF <1> xor bh, bh 16062 <1> ; 16063 <1> sysstty_9: ; tty 0 to tty 7 16064 <1> ; al = character 16065 00004729 80FEFF <1> cmp dh, 0FFh ; Do not set cursor position 16066 0000472C 740F <1> je short sysstty_10 16067 0000472E 6651 <1> push cx 16068 00004730 6650 <1> push ax 16069 <1> ; movzx, ebx, cl 16070 00004732 88CB <1> mov bl, cl ; (tty number = video page number) 16071 00004734 E8C5CEFFFF <1> call set_cpos 16072 00004739 6658 <1> pop ax 16073 0000473B 6659 <1> pop cx 16074 <1> sysstty_10: 16075 <1> ; 29/10/2015 16076 0000473D 08C0 <1> or al, al ; character 16077 0000473F 740F <1> jz short sysstty_11 ; al = 0 16078 <1> ; 17/11/2015 16079 00004741 3CFF <1> cmp al, 0FFh 16080 00004743 730B <1> jnb short sysstty_11 16081 <1> ; ch > 0 and ch < FFh 16082 <1> ; write a character at current cursor position 16083 00004745 88EC <1> mov ah, ch ; color/attribute 16084 <1> ; 12/07/2014 16085 00004747 6651 <1> push cx 16086 00004749 E8F9CFFFFF <1> call write_c_current 16087 0000474E 6659 <1> pop cx 16088 <1> sysstty_11: 16089 <1> ; 14/01/2014 16090 00004750 30D2 <1> xor dl, dl ; sysstty call sign 16091 <1> ; 18/01/2014 16092 <1> ;movzx eax, cl ; 27/06/2015 16093 00004752 88C8 <1> mov al, cl 16094 00004754 E8B9180000 <1> call cttyp 16095 00004759 E9FCF8FFFF <1> jmp sysret 16096 <1> 16097 <1> ; Original UNIX v1 'sysstty' routine: 16098 <1> ; gtty: 16099 <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments 16100 <1> ;jsr r0,gtty / r1 will have offset to tty block, 16101 <1> ; / r2 has source 16102 <1> ;mov r2,-(sp) 16103 <1> ;mov r1,-(sp) / put r1 and r2 on the stack 16104 <1> ;1: / flush the clist wait till typewriter is quiescent 16105 <1> ;mov (sp),r1 / restore r1 to tty block offset 16106 <1> ;movb tty+3(r1),0f / put cc offset into getc argument 16107 <1> ;mov $240,*$ps / set processor priority to 5 16108 <1> ;jsr r0,getc; 0:../ put character from clist in r1 16109 <1> ; br .+4 / list empty, skip branch 16110 <1> ;br 1b / get another character until list is empty 16111 <1> ;mov 0b,r1 / move cc offset to r1 16112 <1> ;inc r1 / bump it for output clist 16113 <1> ;tstb cc(r1) / is it 0 16114 <1> ;beq 1f / yes, no characters to output 16115 <1> ;mov r1,0f / no, put offset in sleep arg 16116 <1> ;jsr r0,sleep; 0:.. / put tty output process to sleep 16117 <1> ;br 1b / try to calm it down again 16118 <1> ;1: 16119 <1> ;mov (sp)+,r1 16120 <1> ;mov (sp)+,r2 / restore registers 16121 <1> ;mov (r2)+,r3 / put reader control status in r3 16122 <1> ;beq 1f / if 0, 1f 16123 <1> ;mov r3,rcsr(r1) / move r.c. status to reader 16124 <1> ; / control status register 16125 <1> ;1: 16126 <1> ;mov (r2)+,r3 / move pointer control status to r3 16127 <1> ;beq 1f / if 0 1f 16128 <1> ;mov r3,tcsr(r1) / move p.c. status to printer 16129 <1> ; / control status reg 16130 <1> ;1: 16131 <1> ;mov (r2)+,tty+4(r1) / move to flag byte of tty block 16132 <1> ;jmp sysret2 / return to user 16133 <1> 16134 <1> sysgtty: ; < get tty status > 16135 <1> ; 23/11/2015 16136 <1> ; 29/10/2015 16137 <1> ; 17/10/2015 16138 <1> ; 28/06/2015 (Retro UNIX 386 v1 - Beginning) 16139 <1> ; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1) 16140 <1> ; 16141 <1> ; 'sysgtty' gets the status of tty in question. 16142 <1> ; It stores in the three words addressed by it's argument 16143 <1> ; the status of the typewriter whose file descriptor 16144 <1> ; in (u.r0). 16145 <1> ; 16146 <1> ; Calling sequence: 16147 <1> ; sysgtty; arg 16148 <1> ; Arguments: 16149 <1> ; arg - address of 3 words destination of the status 16150 <1> ; Inputs: ((*u.r0 - file descriptor)) 16151 <1> ; Outputs: ((status in address which is pointed to by arg)) 16152 <1> ; ............................................................... 16153 <1> ; 16154 <1> ; Retro UNIX 8086 v1 modification: 16155 <1> ; 'sysgtty' system call will return status of tty 16156 <1> ; (keyboard, serial port and video page status) 16157 <1> ; in following manner: 16158 <1> ; 16159 <1> ; Inputs: 16160 <1> ; BX = 0 --> means 16161 <1> ; CH = 0 --> 'return status of the console tty' 16162 <1> ; for (current) process 16163 <1> ; CL = 0 --> return keyboard status (tty 0 to 9) 16164 <1> ; CL = 1 --> return video page status (tty 0 to 7) 16165 <1> ; CL = 1 --> return serial port status (tty 8 & 9) 16166 <1> ; CH > 0 --> tty number + 1 16167 <1> ; 16168 <1> ; BX > 0 --> points to name of tty 16169 <1> ; CL = 0 --> return keyboard status 16170 <1> ; CL = 1 --> return video page status 16171 <1> ; CH = undefined 16172 <1> ; 16173 <1> ; Outputs: 16174 <1> ; cf = 0 -> 16175 <1> ; 16176 <1> ; AL = tty number from 0 to 9 16177 <1> ; (0 to 7 is also the video page of the tty) 16178 <1> ; AH = 0 if the tty is free/unused 16179 <1> ; AH = the process number of the caller 16180 <1> ; AH = FFh if the tty is locked by another process 16181 <1> ; 16182 <1> ; (if calling is for serial port status) 16183 <1> ; BX = serial port status if tty number is 8 or 9 16184 <1> ; (BH = modem status, BL = Line status) 16185 <1> ; CX = 0FFFFh (if data is ready) 16186 <1> ; CX = 0 (if data is not ready or undefined) 16187 <1> ; 16188 <1> ; (if calling is for keyboard status) 16189 <1> ; BX = current character in tty/keyboard buffer 16190 <1> ; (BH = scan code, BL = ascii code) 16191 <1> ; (BX=0 if there is not a waiting character) 16192 <1> ; CX is undefined 16193 <1> ; 16194 <1> ; (if calling is for video page status) 16195 <1> ; BX = cursor position on the video page 16196 <1> ; if tty number < 8 16197 <1> ; (BH = row, BL = column) 16198 <1> ; CX = current character (in cursor position) 16199 <1> ; on the video page of the tty 16200 <1> ; if tty number < 8 16201 <1> ; (CH = color, CL = character) 16202 <1> ; 16203 <1> ; cf = 1 means error (requested tty is not ready) 16204 <1> ; 16205 <1> ; AH = FFh if the caller is not owner of 16206 <1> ; specified tty or console tty 16207 <1> ; AL = tty number (0FFh if it does not exist) 16208 <1> ; BX, CX are undefined if cf = 1 16209 <1> ; 16210 <1> ; (If tty number is 8 or 9) 16211 <1> ; AL = tty number 16212 <1> ; AH = the process number of the caller 16213 <1> ; BX = serial port status 16214 <1> ; (BH = modem status, BL = Line status) 16215 <1> ; CX = 0 16216 <1> ; 16217 <1> 16218 <1> gtty: ; get (requested) tty number 16219 <1> ; 17/10/2015 16220 <1> ; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications) 16221 <1> ; 30/05/2013 - 12/07/2014 16222 <1> ; Retro UNIX 8086 v1 modification ! 16223 <1> ; 16224 <1> ; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP)) 16225 <1> ; 16226 <1> ; 28/06/2015 (32 bit modifications) 16227 <1> ; 16/01/2014 16228 0000475E 31C0 <1> xor eax, eax 16229 00004760 6648 <1> dec ax ; 17/10/2015 16230 00004762 A3[48740000] <1> mov [u.r0], eax ; 0FFFFh 16231 00004767 80F901 <1> cmp cl, 1 16232 0000476A 760F <1> jna short sysgtty_0 16233 <1> sysgtty_invp: 16234 <1> ; 28/06/2015 16235 0000476C C705[9D740000]1700- <1> mov dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 16236 00004774 0000 <1> 16237 00004776 E9BFF8FFFF <1> jmp error 16238 <1> sysgtty_0: 16239 0000477B 21DB <1> and ebx, ebx 16240 0000477D 7430 <1> jz short sysgtty_1 16241 <1> ; 16242 0000477F 891D[60740000] <1> mov [u.namep], ebx 16243 00004785 6651 <1> push cx ; 23/11/2015 16244 00004787 E86A070000 <1> call namei 16245 0000478C 6659 <1> pop cx ; 23/11/2015 16246 0000478E 7210 <1> jc short sysgtty_inv_dn ; 28/06/2015 16247 <1> ; 16248 00004790 6683F801 <1> cmp ax, 1 16249 00004794 7622 <1> jna short sysgtty_2 16250 00004796 6683E80A <1> sub ax, 10 16251 0000479A 6683F809 <1> cmp ax, 9 16252 <1> ;ja short sysgtty_inv_dn 16253 <1> ;mov ch, al 16254 <1> ;jmp short sysgtty_4 16255 <1> ; 23/11/2015 16256 0000479E 7629 <1> jna short sysgtty_4 16257 <1> sysgtty_inv_dn: 16258 <1> ; 28/06/2015 16259 <1> ; Invalid device name (not a tty) ! error 16260 <1> ; (Device is not a tty or device name not found) 16261 000047A0 C705[9D740000]1800- <1> mov dword [u.error], ERR_INV_DEV_NAME 16262 000047A8 0000 <1> 16263 000047AA E98BF8FFFF <1> jmp error 16264 <1> sysgtty_1: 16265 <1> ; 16/01/2014 16266 000047AF 80FD0A <1> cmp ch, 10 16267 000047B2 77B8 <1> ja short sysgtty_invp ; 28/06/2015 16268 000047B4 FECD <1> dec ch ; 0 -> FFh (negative) 16269 000047B6 790F <1> jns short sysgtty_3 ; not negative 16270 <1> ; 16271 <1> sysgtty_2: 16272 <1> ; get tty number of console tty 16273 000047B8 8A25[97740000] <1> mov ah, [u.uno] 16274 <1> ; 28/06/2015 16275 000047BE 0FB6DC <1> movzx ebx, ah 16276 000047C1 8AAB[95710000] <1> mov ch, [ebx+p.ttyc-1] 16277 <1> sysgtty_3: 16278 000047C7 88E8 <1> mov al, ch 16279 <1> sysgtty_4: 16280 000047C9 A2[48740000] <1> mov [u.r0], al 16281 <1> ; 28/06/2015 16282 <1> ;cmp al, 9 16283 <1> ;ja short sysgtty_invp 16284 000047CE 8B2D[44740000] <1> mov ebp, [u.usp] 16285 <1> ; 23/11/2015 16286 000047D4 20C9 <1> and cl, cl 16287 000047D6 7436 <1> jz short sysgtty_6 ; keyboard status 16288 000047D8 3C08 <1> cmp al, 8 ; cmp ch, 8 16289 000047DA 7232 <1> jb short sysgtty_6 ; video page status 16290 <1> ; serial port status 16291 <1> ; 12/07/2014 16292 <1> ;mov dx, 0 16293 <1> ;je short sysgtty_5 16294 <1> ;inc dl 16295 <1> ;sysgtty_5: 16296 <1> ; 28/06/2015 16297 000047DC 2C08 <1> sub al, 8 16298 000047DE E8FCF2FFFF <1> call sp_status ; serial (COM) port (line) status 16299 <1> ; AL = Line status, AH = Modem status 16300 000047E3 66894510 <1> mov [ebp+16], ax ; serial port status (in EBX) 16301 000047E7 8A25[97740000] <1> mov ah, [u.uno] 16302 000047ED 8825[49740000] <1> mov [u.r0+1], ah 16303 000047F3 66C745180000 <1> mov word [ebp+24], 0 ; data status (0 = not ready) 16304 <1> ; (in ECX) 16305 000047F9 A880 <1> test al, 80h 16306 000047FB 7565 <1> jnz short sysgtty_dnr_err ; 29/06/2015 16307 000047FD A801 <1> test al, 1 16308 000047FF 0F8455F8FFFF <1> jz sysret 16309 00004805 66FF4D18 <1> dec word [ebp+24] ; data status (FFFFh = ready) 16310 00004809 E94CF8FFFF <1> jmp sysret 16311 <1> sysgtty_6: 16312 0000480E A2[9C740000] <1> mov [u.ttyn], al ; tty number 16313 <1> ;movzx ebx, al 16314 00004813 88C3 <1> mov bl, al ; tty number (0 to 9) 16315 00004815 D0E3 <1> shl bl, 1 ; aligned to word 16316 <1> ; 22/04/2014 - 29/06/2015 16317 00004817 81C3[B4700000] <1> add ebx, ttyl 16318 0000481D 8A23 <1> mov ah, [ebx] 16319 0000481F 3A25[97740000] <1> cmp ah, [u.uno] 16320 00004825 7404 <1> je short sysgtty_7 16321 00004827 20E4 <1> and ah, ah 16322 <1> ;jz short sysgtty_7 16323 00004829 7506 <1> jnz short sysgtty_8 16324 <1> ;mov ah, 0FFh 16325 <1> sysgtty_7: 16326 0000482B 8825[49740000] <1> mov [u.r0+1], ah 16327 <1> sysgtty_8: 16328 00004831 08C9 <1> or cl, cl 16329 00004833 7510 <1> jnz short sysgtty_9 16330 00004835 B001 <1> mov al, 1 ; test a key is available 16331 00004837 E8621C0000 <1> call getc 16332 0000483C 66894510 <1> mov [ebp+16], ax ; bx, character 16333 00004840 E915F8FFFF <1> jmp sysret 16334 <1> sysgtty_9: 16335 00004845 8A1D[9C740000] <1> mov bl, [u.ttyn] 16336 <1> ; bl = video page number 16337 0000484B E8CF1D0000 <1> call get_cpos 16338 <1> ; dx = cursor position 16339 00004850 66895510 <1> mov [ebp+16], dx ; bx 16340 <1> ;mov bl, [u.ttyn] 16341 <1> ; bl = video page number 16342 00004854 E8D71D0000 <1> call read_ac_current 16343 <1> ; ax = character and attribute/color 16344 00004859 66894518 <1> mov [ebp+24], ax ; cx 16345 0000485D E9F8F7FFFF <1> jmp sysret 16346 <1> sysgtty_dnr_err: 16347 <1> ; 'device not responding !' error 16348 <1> ;mov dword [u.error], ERR_TIME_OUT ; 25 16349 00004862 C705[9D740000]1900- <1> mov dword [u.error], ERR_DEV_NOT_RESP ; 25 16350 0000486A 0000 <1> 16351 0000486C E9C9F7FFFF <1> jmp error 16352 <1> 16353 <1> ; Original UNIX v1 'sysgtty' routine: 16354 <1> ; sysgtty: 16355 <1> ;jsr r0,gtty / r1 will have offset to tty block, 16356 <1> ; / r2 has destination 16357 <1> ;mov rcsr(r1),(r2)+ / put reader control status 16358 <1> ; / in 1st word of dest 16359 <1> ;mov tcsr(r1),(r2)+ / put printer control status 16360 <1> ; / in 2nd word of dest 16361 <1> ;mov tty+4(r1),(r2)+ / put mode in 3rd word 16362 <1> ;jmp sysret2 / return to user 16363 <1> 16364 <1> ; Original UNIX v1 'gtty' routine: 16365 <1> ; gtty: 16366 <1> ;jsr r0,arg; u.off / put first arg in u.off 16367 <1> ;mov *u.r0,r1 / put file descriptor in r1 16368 <1> ;jsr r0,getf / get the i-number of the file 16369 <1> ;tst r1 / is it open for reading 16370 <1> ;bgt 1f / yes 16371 <1> ;neg r1 / no, i-number is negative, 16372 <1> ; / so make it positive 16373 <1> ;1: 16374 <1> ;sub $14.,r1 / get i-number of tty0 16375 <1> ;cmp r1,$ntty-1 / is there such a typewriter 16376 <1> ;bhis error9 / no, error 16377 <1> ;asl r1 / 0%2 16378 <1> ;asl r1 / 0%4 / yes 16379 <1> ;asl r1 / 0%8 / multiply by 8 so r1 points to 16380 <1> ; ; / tty block 16381 <1> ;mov u.off,r2 / put argument in r2 16382 <1> ;rts r0 / return 16383 %include 'u2.s' ; 11/05/2015 16384 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC 16385 <1> ; Last Modification: 03/01/2016 16386 <1> ; ---------------------------------------------------------------------------- 16387 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 16388 <1> ; (v0.1 - Beginning: 11/07/2012) 16389 <1> ; 16390 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 16391 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 16392 <1> ; 16393 <1> ; 16394 <1> ; 16395 <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s 16396 <1> ; 16397 <1> ; **************************************************************************** 16398 <1> 16399 <1> syslink: 16400 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 16401 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 16402 <1> ; 16403 <1> ; 'syslink' is given two arguments, name 1 and name 2. 16404 <1> ; name 1 is a file that already exists. name 2 is the name 16405 <1> ; given to the entry that will go in the current directory. 16406 <1> ; name2 will then be a link to the name 1 file. The i-number 16407 <1> ; in the name 2 entry of current directory is the same 16408 <1> ; i-number for the name 1 file. 16409 <1> ; 16410 <1> ; Calling sequence: 16411 <1> ; syslink; name 1; name 2 16412 <1> ; Arguments: 16413 <1> ; name 1 - file name to which link will be created. 16414 <1> ; name 2 - name of entry in current directory that 16415 <1> ; links to name 1. 16416 <1> ; Inputs: - 16417 <1> ; Outputs: - 16418 <1> ; ............................................................... 16419 <1> ; 16420 <1> ; Retro UNIX 8086 v1 modification: 16421 <1> ; 'syslink' system call has two arguments; so, 16422 <1> ; * 1st argument, name 1 is pointed to by BX register 16423 <1> ; * 2nd argument, name 2 is pointed to by CX register 16424 <1> ; 16425 <1> ; / name1, name2 16426 <1> ;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd 16427 00004871 891D[60740000] <1> mov [u.namep], ebx 16428 00004877 51 <1> push ecx 16429 00004878 E879060000 <1> call namei 16430 <1> ; jsr r0,namei / find the i-number associated with 16431 <1> ; / the 1st path name 16432 <1> ;;and ax, ax 16433 <1> ;;jz error ; File not found 16434 <1> ;jc error 16435 <1> ; br error9 / cannot be found 16436 0000487D 730F <1> jnc short syslink0 16437 <1> ;pop ecx 16438 <1> ; 'file not found !' error 16439 0000487F C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 16440 00004887 0000 <1> 16441 00004889 E9ACF7FFFF <1> jmp error 16442 <1> syslink0: 16443 0000488E E8530E0000 <1> call iget 16444 <1> ; jsr r0,iget / get the i-node into core 16445 00004893 8F05[60740000] <1> pop dword [u.namep] ; ecx 16446 <1> ; mov (sp)+,u.namep / u.namep points to 2nd name 16447 00004899 6650 <1> push ax 16448 <1> ; mov r1,-(sp) / put i-number of name1 on the stack 16449 <1> ; / (a link to this file is to be created) 16450 0000489B 66FF35[2E740000] <1> push word [cdev] 16451 <1> ; mov cdev,-(sp) / put i-nodes device on the stack 16452 000048A2 E855000000 <1> call isdir 16453 <1> ; jsr r0,isdir / is it a directory 16454 000048A7 E84A060000 <1> call namei 16455 <1> ; jsr r0,namei / no, get i-number of name2 16456 <1> ;jnc error 16457 <1> ; br .+4 / not found 16458 <1> ; / so r1 = i-number of current directory 16459 <1> ; / ii = i-number of current directory 16460 <1> ; br error9 / file already exists., error 16461 000048AC 720F <1> jc short syslink1 16462 <1> ; pop ax 16463 <1> ; pop ax 16464 <1> ; 'file exists !' error 16465 000048AE C705[9D740000]0E00- <1> mov dword [u.error], ERR_FILE_EXISTS ; 14 16466 000048B6 0000 <1> 16467 000048B8 E97DF7FFFF <1> jmp error 16468 <1> syslink1: 16469 000048BD 6659 <1> pop cx 16470 <1> ;cmp cx, [cdev] 16471 000048BF 3A0D[2E740000] <1> cmp cl, [cdev] 16472 <1> ;jne error 16473 <1> ; cmp (sp)+,cdev / u.dirp now points to 16474 <1> ; / end of current directory 16475 <1> ; bne error9 16476 000048C5 740F <1> je short syslink2 16477 <1> ; 'not same drive !' error 16478 000048C7 C705[9D740000]1500- <1> mov dword [u.error], ERR_DRV_NOT_SAME ; 21 16479 000048CF 0000 <1> 16480 000048D1 E964F7FFFF <1> jmp error 16481 <1> syslink2: 16482 000048D6 6658 <1> pop ax 16483 000048D8 6650 <1> push ax 16484 000048DA 66A3[7A740000] <1> mov [u.dirbuf], ax 16485 <1> ; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf 16486 000048E0 E8A8000000 <1> call mkdir 16487 <1> ; jsr r0,mkdir / make directory entry for name2 16488 <1> ; / in current directory 16489 000048E5 6658 <1> pop ax 16490 <1> ; mov (sp)+,r1 / r1 has i-number of name1 16491 000048E7 E8FA0D0000 <1> call iget 16492 <1> ; jsr r0,iget / get i-node into core 16493 000048EC FE05[18710000] <1> inc byte [i.nlks] 16494 <1> ; incb i.nlks / add 1 to its number of links 16495 000048F2 E8020F0000 <1> call setimod 16496 <1> ; jsr r0,setimod / set the i-node modified flag 16497 000048F7 E95EF7FFFF <1> jmp sysret 16498 <1> 16499 <1> isdir: 16500 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 16501 <1> ; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 16502 <1> ; 16503 <1> ; 'isdir' check to see if the i-node whose i-number is in r1 16504 <1> ; is a directory. If it is, an error occurs, because 'isdir' 16505 <1> ; called by syslink and sysunlink to make sure directories 16506 <1> ; are not linked. If the user is the super user (u.uid=0), 16507 <1> ; 'isdir' does not bother checking. The current i-node 16508 <1> ; is not disturbed. 16509 <1> ; 16510 <1> ; INPUTS -> 16511 <1> ; r1 - contains the i-number whose i-node is being checked. 16512 <1> ; u.uid - user id 16513 <1> ; OUTPUTS -> 16514 <1> ; r1 - contains current i-number upon exit 16515 <1> ; (current i-node back in core) 16516 <1> ; 16517 <1> ; ((AX = R1)) 16518 <1> ; 16519 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 16520 <1> ; 16521 <1> 16522 <1> ; / if the i-node whose i-number is in r1 is a directory 16523 <1> ; / there is an error unless super user made the call 16524 <1> 16525 000048FC 803D[94740000]00 <1> cmp byte [u.uid], 0 16526 <1> ; tstb u.uid / super user 16527 00004903 762D <1> jna short isdir1 16528 <1> ; beq 1f / yes, don't care 16529 00004905 66FF35[2A740000] <1> push word [ii] 16530 <1> ; mov ii,-(sp) / put current i-number on stack 16531 0000490C E8D50D0000 <1> call iget 16532 <1> ; jsr r0,iget / get i-node into core (i-number in r1) 16533 00004911 66F705[16710000]00- <1> test word [i.flgs], 4000h ; Bit 14 : Directory flag 16534 00004919 40 <1> 16535 <1> ; bit $40000,i.flgs / is it a directory 16536 <1> ;jnz error 16537 <1> ; bne error9 / yes, error 16538 0000491A 740F <1> jz short isdir0 16539 0000491C C705[9D740000]0B00- <1> mov dword [u.error], ERR_NOT_FILE ; 11 ; ERR_DIR_ACCESS 16540 00004924 0000 <1> 16541 <1> ; 'permission denied !' error 16542 <1> ; pop ax 16543 00004926 E90FF7FFFF <1> jmp error 16544 <1> isdir0: 16545 0000492B 6658 <1> pop ax 16546 <1> ; mov (sp)+,r1 / no, put current i-number in r1 (ii) 16547 0000492D E8B40D0000 <1> call iget 16548 <1> ; jsr r0,iget / get it back in 16549 <1> isdir1: ; 1: 16550 00004932 C3 <1> retn 16551 <1> ; rts r0 16552 <1> 16553 <1> sysunlink: 16554 <1> ; 04/12/2015 (14 byte file names) 16555 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 16556 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 16557 <1> ; 16558 <1> ; 'sysunlink' removes the entry for the file pointed to by 16559 <1> ; name from its directory. If this entry was the last link 16560 <1> ; to the file, the contents of the file are freed and the 16561 <1> ; file is destroyed. If, however, the file was open in any 16562 <1> ; process, the actual destruction is delayed until it is 16563 <1> ; closed, even though the directory entry has disappeared. 16564 <1> ; 16565 <1> ; The error bit (e-bit) is set to indicate that the file 16566 <1> ; does not exist or that its directory can not be written. 16567 <1> ; Write permission is not required on the file itself. 16568 <1> ; It is also illegal to unlink a directory (except for 16569 <1> ; the superuser). 16570 <1> ; 16571 <1> ; Calling sequence: 16572 <1> ; sysunlink; name 16573 <1> ; Arguments: 16574 <1> ; name - name of directory entry to be removed 16575 <1> ; Inputs: - 16576 <1> ; Outputs: - 16577 <1> ; ............................................................... 16578 <1> ; 16579 <1> ; Retro UNIX 8086 v1 modification: 16580 <1> ; The user/application program puts address of the name 16581 <1> ; in BX register as 'sysunlink' system call argument. 16582 <1> 16583 <1> ; / name - remove link name 16584 00004933 891D[60740000] <1> mov [u.namep], ebx 16585 <1> ;jsr r0,arg; u.namep / u.namep points to name 16586 00004939 E8B8050000 <1> call namei 16587 <1> ; jsr r0,namei / find the i-number associated 16588 <1> ; / with the path name 16589 <1> ;jc error 16590 <1> ; br error9 / not found 16591 0000493E 730F <1> jnc short sysunlink1 16592 <1> ; 'file not found !' error 16593 00004940 C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 16594 00004948 0000 <1> 16595 0000494A E9EBF6FFFF <1> jmp error 16596 <1> sysunlink1: 16597 0000494F 6650 <1> push ax 16598 <1> ; mov r1,-(sp) / put its i-number on the stack 16599 00004951 E8A6FFFFFF <1> call isdir 16600 <1> ; jsr r0,isdir / is it a directory 16601 00004956 6631C0 <1> xor ax, ax 16602 00004959 66A3[7A740000] <1> mov [u.dirbuf], ax ; 0 16603 <1> ; clr u.dirbuf / no, clear the location that will 16604 <1> ; / get written into the i-number portion 16605 <1> ; / of the entry 16606 0000495F 832D[64740000]10 <1> sub dword [u.off], 16 ; 04/12/2015 (10 -> 16) 16607 <1> ; sub $10.,u.off / move u.off back 1 directory entry 16608 00004966 E86E000000 <1> call wdir 16609 <1> ; jsr r0,wdir / free the directory entry 16610 0000496B 6658 <1> pop ax 16611 <1> ; mov (sp)+,r1 / get i-number back 16612 0000496D E8740D0000 <1> call iget 16613 <1> ; jsr r0,iget / get i-node 16614 00004972 E8820E0000 <1> call setimod 16615 <1> ; jsr r0,setimod / set modified flag 16616 00004977 FE0D[18710000] <1> dec byte [i.nlks] 16617 <1> ; decb i.nlks / decrement the number of links 16618 0000497D 0F85D7F6FFFF <1> jnz sysret 16619 <1> ; bgt sysret9 / if this was not the last link 16620 <1> ; / to file return 16621 <1> ; AX = r1 = i-number 16622 00004983 E893090000 <1> call anyi 16623 <1> ; jsr r0,anyi / if it was, see if anyone has it open. 16624 <1> ; / Then free contents of file and destroy it. 16625 00004988 E9CDF6FFFF <1> jmp sysret 16626 <1> ; br sysret9 16627 <1> 16628 <1> mkdir: 16629 <1> ; 04/12/2015 (14 byte directory names) 16630 <1> ; 12/10/2015 16631 <1> ; 17/06/2015 (Retro UNIX 386 v1 - Beginning) 16632 <1> ; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 16633 <1> ; 16634 <1> ; 'mkdir' makes a directory entry from the name pointed to 16635 <1> ; by u.namep into the current directory. 16636 <1> ; 16637 <1> ; INPUTS -> 16638 <1> ; u.namep - points to a file name 16639 <1> ; that is about to be a directory entry. 16640 <1> ; ii - current directory's i-number. 16641 <1> ; OUTPUTS -> 16642 <1> ; u.dirbuf+2 - u.dirbuf+10 - contains file name. 16643 <1> ; u.off - points to entry to be filled 16644 <1> ; in the current directory 16645 <1> ; u.base - points to start of u.dirbuf. 16646 <1> ; r1 - contains i-number of current directory 16647 <1> ; 16648 <1> ; ((AX = R1)) output 16649 <1> ; 16650 <1> ; (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM) 16651 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 16652 <1> ; 16653 <1> 16654 <1> ; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 16655 0000498D 31C0 <1> xor eax, eax 16656 0000498F BF[7C740000] <1> mov edi, u.dirbuf+2 16657 00004994 89FE <1> mov esi, edi 16658 00004996 AB <1> stosd 16659 00004997 AB <1> stosd 16660 <1> ; 04/12/2015 (14 byte directory names) 16661 00004998 AB <1> stosd 16662 00004999 66AB <1> stosw 16663 <1> ; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this 16664 0000499B 89F7 <1> mov edi, esi ; offset to u.dirbuf 16665 <1> ; 12/10/2015 ([u.namep] -> ebp) 16666 <1> ;mov ebp, [u.namep] 16667 0000499D E899060000 <1> call trans_addr_nmbp ; convert virtual address to physical 16668 <1> ; esi = physical address (page start + offset) 16669 <1> ; ecx = byte count in the page (1 - 4096) 16670 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 16671 <1> ; mov u.namep,r2 / r2 points to name of directory entry 16672 <1> ; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2 16673 <1> mkdir_1: ; 1: 16674 000049A2 45 <1> inc ebp ; 12/10/2015 16675 <1> ; 16676 <1> ; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10 16677 <1> ; 01/08/2013 16678 000049A3 AC <1> lodsb 16679 <1> ; movb (r2)+,r1 / move character in name to r1 16680 000049A4 20C0 <1> and al, al 16681 000049A6 7427 <1> jz short mkdir_3 16682 <1> ; beq 1f / if null, done 16683 000049A8 3C2F <1> cmp al, '/' 16684 <1> ; cmp r1,$'/ / is it a "/"? 16685 000049AA 7414 <1> je short mkdir_err 16686 <1> ;je error 16687 <1> ; beq error9 / yes, error 16688 <1> ; 12/10/2015 16689 000049AC 6649 <1> dec cx 16690 000049AE 7505 <1> jnz short mkdir_2 16691 <1> ; 12/10/2015 ([u.namep] -> ebp) 16692 000049B0 E88C060000 <1> call trans_addr_nm ; convert virtual address to physical 16693 <1> ; esi = physical address (page start + offset) 16694 <1> ; ecx = byte count in the page 16695 <1> ; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm) 16696 <1> mkdir_2: 16697 000049B5 81FF[8A740000] <1> cmp edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 16698 <1> ; cmp r3,$u.dirbuf+10. / have we reached the last slot for 16699 <1> ; / a char? 16700 000049BB 74E5 <1> je short mkdir_1 16701 <1> ; beq 1b / yes, go back 16702 000049BD AA <1> stosb 16703 <1> ; movb r1,(r3)+ / no, put the char in the u.dirbuf 16704 000049BE EBE2 <1> jmp short mkdir_1 16705 <1> ; br 1b / get next char 16706 <1> mkdir_err: 16707 <1> ; 17/06/2015 16708 000049C0 C705[9D740000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 16709 000049C8 0000 <1> 16710 000049CA E96BF6FFFF <1> jmp error 16711 <1> 16712 <1> mkdir_3: ; 1: 16713 000049CF A1[5C740000] <1> mov eax, [u.dirp] 16714 000049D4 A3[64740000] <1> mov [u.off], eax 16715 <1> ; mov u.dirp,u.off / pointer to empty current directory 16716 <1> ; / slot to u.off 16717 <1> wdir: ; 29/04/2013 16718 000049D9 C705[68740000]- <1> mov dword [u.base], u.dirbuf 16719 000049DF [7A740000] <1> 16720 <1> ; mov $u.dirbuf,u.base / u.base points to created file name 16721 000049E3 C705[6C740000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 16722 000049EB 0000 <1> 16723 <1> ; mov $10.,u.count / u.count = 10 16724 000049ED 66A1[2A740000] <1> mov ax, [ii] 16725 <1> ; mov ii,r1 / r1 has i-number of current directory 16726 000049F3 B201 <1> mov dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification ! 16727 000049F5 E8C70D0000 <1> call access 16728 <1> ; jsr r0,access; 1 / get i-node and set its file up 16729 <1> ; / for writing 16730 <1> ; AX = i-number of current directory 16731 <1> ; 01/08/2013 16732 000049FA FE05[AF740000] <1> inc byte [u.kcall] ; the caller is 'mkdir' sign 16733 00004A00 E8B7100000 <1> call writei 16734 <1> ; jsr r0,writei / write into directory 16735 00004A05 C3 <1> retn 16736 <1> ; rts r0 16737 <1> 16738 <1> sysexec: 16739 <1> ; 23/10/2015 16740 <1> ; 19/10/2015 16741 <1> ; 18/10/2015 16742 <1> ; 10/10/2015 16743 <1> ; 26/08/2015 16744 <1> ; 05/08/2015 16745 <1> ; 29/07/2015 16746 <1> ; 25/07/2015 16747 <1> ; 24/07/2015 16748 <1> ; 21/07/2015 16749 <1> ; 20/07/2015 16750 <1> ; 02/07/2015 16751 <1> ; 01/07/2015 16752 <1> ; 25/06/2015 16753 <1> ; 24/06/2015 16754 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 16755 <1> ; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1) 16756 <1> ; 16757 <1> ; 'sysexec' initiates execution of a file whose path name if 16758 <1> ; pointed to by 'name' in the sysexec call. 16759 <1> ; 'sysexec' performs the following operations: 16760 <1> ; 1. obtains i-number of file to be executed via 'namei'. 16761 <1> ; 2. obtains i-node of file to be exceuted via 'iget'. 16762 <1> ; 3. sets trap vectors to system routines. 16763 <1> ; 4. loads arguments to be passed to executing file into 16764 <1> ; highest locations of user's core 16765 <1> ; 5. puts pointers to arguments in locations immediately 16766 <1> ; following arguments. 16767 <1> ; 6. saves number of arguments in next location. 16768 <1> ; 7. intializes user's stack area so that all registers 16769 <1> ; will be zeroed and the PS is cleared and the PC set 16770 <1> ; to core when 'sysret' restores registers 16771 <1> ; and does an rti. 16772 <1> ; 8. inializes u.r0 and u.sp 16773 <1> ; 9. zeros user's core down to u.r0 16774 <1> ; 10. reads executable file from storage device into core 16775 <1> ; starting at location 'core'. 16776 <1> ; 11. sets u.break to point to end of user's code with 16777 <1> ; data area appended. 16778 <1> ; 12. calls 'sysret' which returns control at location 16779 <1> ; 'core' via 'rti' instruction. 16780 <1> ; 16781 <1> ; Calling sequence: 16782 <1> ; sysexec; namep; argp 16783 <1> ; Arguments: 16784 <1> ; namep - points to pathname of file to be executed 16785 <1> ; argp - address of table of argument pointers 16786 <1> ; argp1... argpn - table of argument pointers 16787 <1> ; argp1:<...0> ... argpn:<...0> - argument strings 16788 <1> ; Inputs: (arguments) 16789 <1> ; Outputs: - 16790 <1> ; ............................................................... 16791 <1> ; 16792 <1> ; Retro UNIX 386 v1 modification: 16793 <1> ; User application runs in it's own virtual space 16794 <1> ; which is izolated from kernel memory (and other 16795 <1> ; memory pages) via 80386 paging in ring 3 16796 <1> ; privilige mode. Virtual start address is always 0. 16797 <1> ; User's core memory starts at linear address 400000h 16798 <1> ; (the end of the 1st 4MB). 16799 <1> ; 16800 <1> ; Retro UNIX 8086 v1 modification: 16801 <1> ; user/application segment and system/kernel segment 16802 <1> ; are different and sysenter/sysret/sysrele routines 16803 <1> ; are different (user's registers are saved to 16804 <1> ; and then restored from system's stack.) 16805 <1> ; 16806 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 16807 <1> ; arguments which were in these registers; 16808 <1> ; but, it returns by putting the 1st argument 16809 <1> ; in 'u.namep' and the 2nd argument 16810 <1> ; on top of stack. (1st argument is offset of the 16811 <1> ; file/path name in the user's program segment.) 16812 <1> 16813 <1> ;call arg2 16814 <1> ; * name - 'u.namep' points to address of file/path name 16815 <1> ; in the user's program segment ('u.segmnt') 16816 <1> ; with offset in BX register (as sysopen argument 1). 16817 <1> ; * argp - sysexec argument 2 is in CX register 16818 <1> ; which is on top of stack. 16819 <1> ; 16820 <1> ; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack 16821 <1> 16822 <1> ; 23/06/2015 (32 bit modifications) 16823 <1> 16824 00004A06 891D[60740000] <1> mov [u.namep], ebx ; argument 1 16825 <1> ; 18/10/2015 16826 00004A0C 890D[C8740000] <1> mov [argv], ecx ; * ; argument 2 16827 00004A12 E8DF040000 <1> call namei 16828 <1> ; jsr r0,namei / namei returns i-number of file 16829 <1> ; / named in sysexec call in r1 16830 <1> ;jc error 16831 <1> ; br error9 16832 00004A17 731E <1> jnc short sysexec_0 16833 <1> ; 16834 <1> ; 'file not found !' error 16835 00004A19 C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND 16836 00004A21 0000 <1> 16837 00004A23 E912F6FFFF <1> jmp error 16838 <1> sysexec_not_exf: 16839 <1> ; 'not executable file !' error 16840 00004A28 C705[9D740000]1600- <1> mov dword [u.error], ERR_NOT_EXECUTABLE 16841 00004A30 0000 <1> 16842 00004A32 E903F6FFFF <1> jmp error 16843 <1> sysexec_0: 16844 00004A37 E8AA0C0000 <1> call iget 16845 <1> ; jsr r0,iget / get i-node for file to be executed 16846 00004A3C 66F705[16710000]10- <1> test word [i.flgs], 10h 16847 00004A44 00 <1> 16848 <1> ; bit $20,i.flgs / is file executable 16849 00004A45 74E1 <1> jz short sysexec_not_exf 16850 <1> ;jz error 16851 <1> ; beq error9 16852 <1> ;; 16853 00004A47 E819140000 <1> call iopen 16854 <1> ; jsr r0,iopen / gets i-node for file with i-number 16855 <1> ; / given in r1 (opens file) 16856 <1> ; AX = i-number of the file 16857 00004A4C 66F705[16710000]20- <1> test word [i.flgs], 20h 16858 00004A54 00 <1> 16859 <1> ; bit $40,i.flgs / test user id on execution bit 16860 00004A55 7415 <1> jz short sysexec_1 16861 <1> ; beq 1f 16862 00004A57 803D[94740000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 16863 <1> ; tstb u.uid / test user id 16864 00004A5E 760C <1> jna short sysexec_1 16865 <1> ; beq 1f / super user 16866 00004A60 8A0D[19710000] <1> mov cl, [i.uid] 16867 00004A66 880D[94740000] <1> mov [u.uid], cl ; 02/08/2013 16868 <1> ; movb i.uid,u.uid / put user id of owner of file 16869 <1> ; / as process user id 16870 <1> sysexec_1: 16871 <1> ; 18/10/2215 16872 <1> ; 10/10/2015 16873 <1> ; 24/07/2015 16874 <1> ; 21/07/2015 16875 <1> ; 25/06/2015 16876 <1> ; 24/06/2015 16877 <1> ; Moving arguments to the end of [u.upage] 16878 <1> ; (by regarding page borders in user's memory space) 16879 <1> ; 16880 <1> ; 10/10/2015 16881 <1> ; 21/07/2015 16882 00004A6C 89E5 <1> mov ebp, esp ; (**) 16883 <1> ; 18/10/2015 16884 00004A6E 89EF <1> mov edi, ebp 16885 00004A70 B900010000 <1> mov ecx, MAX_ARG_LEN ; 256 16886 <1> ;sub edi, MAX_ARG_LEN ; 256 16887 00004A75 29CF <1> sub edi, ecx 16888 00004A77 89FC <1> mov esp, edi 16889 00004A79 31C0 <1> xor eax, eax 16890 00004A7B A3[70740000] <1> mov [u.nread], eax ; 0 16891 00004A80 49 <1> dec ecx ; 256 - 1 16892 00004A81 890D[6C740000] <1> mov [u.count], ecx ; MAX_ARG_LEN - 1 ; 255 16893 <1> ;mov dword [u.count], MAX_ARG_LEN - 1 ; 255 16894 <1> sysexec_2: 16895 00004A87 8B35[C8740000] <1> mov esi, [argv] ; 18/10/2015 16896 00004A8D E873020000 <1> call get_argp 16897 00004A92 B904000000 <1> mov ecx, 4 ; mov ecx, 4 16898 <1> sysexec_3: 16899 00004A97 21C0 <1> and eax, eax 16900 00004A99 7456 <1> jz short sysexec_6 16901 <1> ; 18/10/2015 16902 00004A9B 010D[C8740000] <1> add [argv], ecx ; 4 16903 00004AA1 66FF05[C6740000] <1> inc word [argc] 16904 <1> ; 16905 00004AA8 A3[68740000] <1> mov [u.base], eax 16906 <1> ; 23/10/2015 16907 00004AAD 66C705[AD740000]00- <1> mov word [u.pcount], 0 16908 00004AB5 00 <1> 16909 <1> sysexec_4: 16910 00004AB6 E8BC110000 <1> call cpass ; get a character from user's core memory 16911 00004ABB 750B <1> jnz short sysexec_5 16912 <1> ; (max. 255 chars + null) 16913 <1> ; 18/10/2015 16914 00004ABD 28C0 <1> sub al, al 16915 00004ABF AA <1> stosb 16916 00004AC0 FF05[70740000] <1> inc dword [u.nread] 16917 00004AC6 EB29 <1> jmp short sysexec_6 16918 <1> sysexec_5: 16919 00004AC8 AA <1> stosb 16920 00004AC9 20C0 <1> and al, al 16921 00004ACB 75E9 <1> jnz short sysexec_4 16922 00004ACD B904000000 <1> mov ecx, 4 16923 00004AD2 390D[C4740000] <1> cmp [ncount], ecx ; 4 16924 00004AD8 72AD <1> jb short sysexec_2 16925 00004ADA 8B35[C0740000] <1> mov esi, [nbase] 16926 00004AE0 010D[C0740000] <1> add [nbase], ecx ; 4 16927 00004AE6 66290D[C4740000] <1> sub [ncount], cx 16928 00004AED 8B06 <1> mov eax, [esi] 16929 00004AEF EBA6 <1> jmp short sysexec_3 16930 <1> sysexec_6: 16931 <1> ; 18/10/2015 16932 <1> ; argument list transfer from user's core memory to 16933 <1> ; kernel stack frame is OK here. 16934 <1> ; [u.nread] = ; argument list length 16935 <1> ;mov [argv], esp ; start address of argument list 16936 <1> ; 16937 <1> ; 18/10/2015 16938 <1> ; 24/07/2015 16939 <1> ; 21/07/2015 16940 <1> ; 02/07/2015 16941 <1> ; 25/06/2015 16942 <1> ; 24/06/2015 16943 <1> ; 23/06/2015 16944 <1> ; 16945 00004AF1 8B1D[A5740000] <1> mov ebx, [u.ppgdir] ; parent's page directory 16946 00004AF7 21DB <1> and ebx, ebx ; /etc/init ? (u.ppgdir = 0) 16947 00004AF9 740A <1> jz short sysexec_7 16948 00004AFB A1[A1740000] <1> mov eax, [u.pgdir] ; physical address of page directory 16949 00004B00 E829E6FFFF <1> call deallocate_page_dir 16950 <1> sysexec_7: 16951 00004B05 E859E5FFFF <1> call make_page_dir 16952 <1> ;jc short sysexec_14 16953 00004B0A 0F82C0EDFFFF <1> jc panic ; allocation error 16954 <1> ; after a deallocation would be nonsence !? 16955 <1> ; 24/07/2015 16956 <1> ; map kernel pages (1st 4MB) to PDE 0 16957 <1> ; of the user's page directory 16958 <1> ; (It is needed for interrupts!) 16959 <1> ; 18/10/2015 16960 00004B10 8B15[68700000] <1> mov edx, [k_page_dir] ; Kernel's page directory 16961 00004B16 8B02 <1> mov eax, [edx] ; physical address of 16962 <1> ; kernel's first page table (1st 4 MB) 16963 <1> ; (PDE 0 of kernel's page directory) 16964 00004B18 8B15[A1740000] <1> mov edx, [u.pgdir] 16965 00004B1E 8902 <1> mov [edx], eax ; PDE 0 (1st 4MB) 16966 <1> ; 16967 <1> ; 20/07/2015 16968 00004B20 BB00004000 <1> mov ebx, CORE ; start address = 0 (virtual) + CORE 16969 <1> ; 18/10/2015 16970 00004B25 BE[B8740000] <1> mov esi, pcore ; physical start address 16971 <1> sysexec_8: 16972 00004B2A B907000000 <1> mov ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT 16973 00004B2F E84DE5FFFF <1> call make_page_table 16974 00004B34 0F8296EDFFFF <1> jc panic 16975 <1> ;mov ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT 16976 00004B3A E850E5FFFF <1> call make_page ; make new page, clear and set the pte 16977 00004B3F 0F828BEDFFFF <1> jc panic 16978 <1> ; 16979 00004B45 8906 <1> mov [esi], eax ; 24/06/2015 16980 <1> ; ebx = virtual address (24/07/2015) 16981 00004B47 E866EAFFFF <1> call add_to_swap_queue 16982 <1> ; 18/10/2015 16983 00004B4C 81FE[BC740000] <1> cmp esi, ecore ; user's stack (last) page ? 16984 00004B52 740C <1> je short sysexec_9 ; yes 16985 00004B54 BE[BC740000] <1> mov esi, ecore ; physical address of the last page 16986 <1> ; 20/07/2015 16987 00004B59 BB00F0FFFF <1> mov ebx, (ECORE - PAGE_SIZE) + CORE 16988 <1> ; ebx = virtual end address + segment base address - 4K 16989 00004B5E EBCA <1> jmp short sysexec_8 16990 <1> 16991 <1> sysexec_9: 16992 <1> ; 18/10/2015 16993 <1> ; 26/08/2015 16994 <1> ; 25/06/2015 16995 <1> ; move arguments from kernel stack to [ecore] 16996 <1> ; (argument list/line will be copied from kernel stack 16997 <1> ; frame to the last (stack) page of user's core memory) 16998 <1> ; 18/10/2015 16999 00004B60 8B3D[BC740000] <1> mov edi, [ecore] 17000 00004B66 81C700100000 <1> add edi, PAGE_SIZE 17001 00004B6C 0FB705[C6740000] <1> movzx eax, word [argc] 17002 00004B73 09C0 <1> or eax, eax 17003 00004B75 7509 <1> jnz short sysexec_10 17004 00004B77 89FB <1> mov ebx, edi 17005 00004B79 83EB04 <1> sub ebx, 4 17006 00004B7C 8903 <1> mov [ebx], eax ; 0 17007 00004B7E EB40 <1> jmp short sysexec_13 17008 <1> sysexec_10: 17009 00004B80 8B0D[70740000] <1> mov ecx, [u.nread] 17010 <1> ;mov esi, [argv} 17011 00004B86 89E6 <1> mov esi, esp ; start address of argument list 17012 00004B88 29CF <1> sub edi, ecx ; page end address - argument list length 17013 00004B8A 89C2 <1> mov edx, eax 17014 00004B8C FEC2 <1> inc dl ; argument count + 1 for argc value 17015 00004B8E C0E202 <1> shl dl, 2 ; 4 * (argument count + 1) 17016 00004B91 89FB <1> mov ebx, edi 17017 00004B93 80E3FC <1> and bl, 0FCh ; 32 bit (dword) alignment 17018 00004B96 29D3 <1> sub ebx, edx 17019 00004B98 89FA <1> mov edx, edi 17020 00004B9A F3A4 <1> rep movsb 17021 00004B9C 89D6 <1> mov esi, edx 17022 00004B9E 89DF <1> mov edi, ebx 17023 00004BA0 BA00F0BFFF <1> mov edx, ECORE - PAGE_SIZE ; virtual addr. of the last page 17024 00004BA5 2B15[BC740000] <1> sub edx, [ecore] ; difference (virtual - physical) 17025 00004BAB AB <1> stosd ; eax = argument count 17026 <1> sysexec_11: 17027 00004BAC 89F0 <1> mov eax, esi 17028 00004BAE 01D0 <1> add eax, edx 17029 00004BB0 AB <1> stosd ; eax = virtual address 17030 00004BB1 FE0D[C6740000] <1> dec byte [argc] 17031 00004BB7 7407 <1> jz short sysexec_13 17032 <1> sysexec_12: 17033 00004BB9 AC <1> lodsb 17034 00004BBA 20C0 <1> and al, al 17035 00004BBC 75FB <1> jnz short sysexec_12 17036 00004BBE EBEC <1> jmp short sysexec_11 17037 <1> ; 17038 <1> ; 1: 17039 <1> ; mov (sp)+,r5 / r5 now contains address of list of 17040 <1> ; / pointers to arguments to be passed 17041 <1> ; mov $1,u.quit / u.quit determines handling of quits; 17042 <1> ; / u.quit = 1 take quit 17043 <1> ; mov $1,u.intr / u.intr determines handling of 17044 <1> ; / interrupts; u.intr = 1 take interrupt 17045 <1> ; mov $rtssym,30 / emt trap vector set to take 17046 <1> ; / system routine 17047 <1> ; mov $fpsym,*10 / reserved instruction trap vector 17048 <1> ; / set to take system routine 17049 <1> ; mov $sstack,sp / stack space used during swapping 17050 <1> ; mov r5,-(sp) / save arguments pointer on stack 17051 <1> ; mov $ecore,r5 / r5 has end of core 17052 <1> ; mov $core,r4 / r4 has start of users core 17053 <1> ; mov r4,u.base / u.base has start of users core 17054 <1> ; mov (sp),r2 / move arguments list pointer into r2 17055 <1> ; 1: 17056 <1> ; tst (r2)+ / argument char = "nul" 17057 <1> ; bne 1b 17058 <1> ; tst -(r2) / decrement r2 by 2; r2 has addr of 17059 <1> ; / end of argument pointer list 17060 <1> ; 1: 17061 <1> ; / move arguments to bottom of users core 17062 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 17063 <1> ; cmp r2,(sp) / is r2 = beginning of argument 17064 <1> ; / ptr list 17065 <1> ; blo 1f / branch to 1f when all arguments 17066 <1> ; / are moved 17067 <1> ; mov -(r2),r3 / (r3) last non zero argument ptr 17068 <1> ; 2: 17069 <1> ; tstb (r3)+ 17070 <1> ; bne 2b / scan argument for \0 (nul) 17071 <1> 17072 <1> ; 2: 17073 <1> ; movb -(r3),-(r5) / move argument char 17074 <1> ; / by char starting at "ecore" 17075 <1> ; cmp r3,(r2) / moved all characters in 17076 <1> ; / this argument 17077 <1> ; bhi 2b / branch 2b if not 17078 <1> ; mov r5,(r4)+ / move r5 into top of users core; 17079 <1> ; / r5 has pointer to nth arg 17080 <1> ; br 1b / string 17081 <1> ; 1: 17082 <1> ; clrb -(r5) 17083 <1> ; bic $1,r5 / make r5 even, r5 points to 17084 <1> ; / last word of argument strings 17085 <1> ; mov $core,r2 17086 <1> 17087 <1> ; 1: / move argument pointers into core following 17088 <1> ; / argument strings 17089 <1> ; cmp r2,r4 17090 <1> ; bhis 1f / branch to 1f when all pointers 17091 <1> ; / are moved 17092 <1> ; mov (r2)+,-(r5) 17093 <1> ; br 1b 17094 <1> ; 1: 17095 <1> ; sub $core,r4 / gives number of arguments *2 17096 <1> ; asr r4 / divide r4 by 2 to calculate 17097 <1> ; / the number of args stored 17098 <1> ; mov r4,-(r5) / save number of arguments ahead 17099 <1> ; / of the argument pointers 17100 <1> sysexec_13: 17101 <1> ; 19/10/2015 17102 <1> ; 18/10/2015 17103 <1> ; 29/07/2015 17104 <1> ; 25/07/2015 17105 <1> ; 24/07/2015 17106 <1> ; 20/07/2015 17107 <1> ; 25/06/2015 17108 <1> ; 24/06/2015 17109 <1> ; 23/06/2015 17110 <1> ; 17111 <1> ; moving arguments to [ecore] is OK here.. 17112 <1> ; 18/10/2015 17113 00004BC0 89EC <1> mov esp, ebp ; (**) restore kernel stack pointer 17114 <1> ; ebx = beginning addres of argument list pointers 17115 <1> ; in user's stack 17116 <1> ; 19/10/2015 17117 00004BC2 2B1D[BC740000] <1> sub ebx, [ecore] 17118 00004BC8 81C300F0BFFF <1> add ebx, (ECORE - PAGE_SIZE) 17119 <1> ; end of core - 4096 (last page) 17120 <1> ; (virtual address) 17121 00004BCE 891D[C8740000] <1> mov [argv], ebx 17122 00004BD4 891D[74740000] <1> mov [u.break], ebx ; available user memory 17123 <1> ; 17124 00004BDA 29C0 <1> sub eax, eax 17125 00004BDC C705[6C740000]2000- <1> mov dword [u.count], 32 ; Executable file header size 17126 00004BE4 0000 <1> 17127 <1> ; mov $14,u.count 17128 00004BE6 C705[58740000]- <1> mov dword [u.fofp], u.off 17129 00004BEC [64740000] <1> 17130 <1> ; mov $u.off,u.fofp 17131 00004BF0 A3[64740000] <1> mov [u.off], eax ; 0 17132 <1> ; clr u.off / set offset in file to be read to zero 17133 <1> ; 25/07/2015 17134 00004BF5 A3[68740000] <1> mov [u.base], eax ; 0, start of user's core (virtual) 17135 <1> ; 25/06/2015 17136 00004BFA 66A1[2A740000] <1> mov ax, [ii] 17137 <1> ; AX = i-number of the executable file 17138 00004C00 E8C10C0000 <1> call readi 17139 <1> ; jsr r0,readi / read in first six words of 17140 <1> ; / user's file, starting at $core 17141 <1> ; mov sp,r5 / put users stack address in r5 17142 <1> ; sub $core+40.,r5 / subtract $core +40, 17143 <1> ; / from r5 (leaves number of words 17144 <1> ; / less 26 available for 17145 <1> ; / program in user core 17146 <1> ; mov r5,u.count / 17147 <1> ; 25/06/2015 17148 00004C05 8B0D[74740000] <1> mov ecx, [u.break] ; top of user's stack (physical addr.) 17149 00004C0B 890D[6C740000] <1> mov [u.count], ecx ; save for overrun check 17150 <1> ; 17151 00004C11 8B0D[70740000] <1> mov ecx, [u.nread] 17152 00004C17 890D[74740000] <1> mov [u.break], ecx ; virtual address (offset from start) 17153 00004C1D 80F920 <1> cmp cl, 32 17154 00004C20 7540 <1> jne short sysexec_15 17155 <1> ;: 17156 <1> ; 25/06/2015 17157 <1> ; Retro UNIX 386 v1 (32 bit) executable file header format 17158 <1> ; 18/10/2015 17159 00004C22 8B35[B8740000] <1> mov esi, [pcore] ; start address of user's core memory 17160 <1> ; (phys. start addr. of the exec. file) 17161 00004C28 AD <1> lodsd 17162 00004C29 663DEB1E <1> cmp ax, 1EEBh ; EBH, 1Eh -> jump to +32 17163 00004C2D 7533 <1> jne short sysexec_15 17164 <1> ; cmp core,$405 / br .+14 is first instruction 17165 <1> ; / if file is standard a.out format 17166 <1> ; bne 1f / branch, if not standard format 17167 00004C2F AD <1> lodsd 17168 00004C30 89C1 <1> mov ecx, eax ; text (code) section size 17169 00004C32 AD <1> lodsd 17170 00004C33 01C1 <1> add ecx, eax ; + data section size (initialized data) 17171 <1> ; mov core+2,r5 / put 2nd word of users program in r5; 17172 <1> ; / number of bytes in program text 17173 <1> ; sub $14,r5 / subtract 12 17174 00004C35 89CB <1> mov ebx, ecx 17175 <1> ; 17176 <1> ; 25/06/2015 17177 <1> ; NOTE: These are for next versions of Retro UNIX 386 17178 <1> ; and SINGLIX operating systems (as code template). 17179 <1> ; Current Retro UNIX 386 v1 files can be max. 64KB 17180 <1> ; due to RUFS (floppy disk file system) restriction... 17181 <1> ; Overrun is not possible for current version. 17182 <1> ; 17183 00004C37 AD <1> lodsd 17184 00004C38 01C3 <1> add ebx, eax ; + bss section size (for overrun checking) 17185 00004C3A 3B1D[6C740000] <1> cmp ebx, [u.count] 17186 00004C40 7711 <1> ja short sysexec_14 ; program overruns stack ! 17187 <1> ; 17188 <1> ; 24/07/2015 17189 <1> ; add bss section size to [u.break] 17190 00004C42 0105[74740000] <1> add [u.break], eax 17191 <1> ; 17192 00004C48 83E920 <1> sub ecx, 32 ; header size (already loaded) 17193 <1> ;cmp ecx, [u.count] 17194 <1> ;jnb short sysexec_16 17195 <1> ; cmp r5,u.count / 17196 <1> ; bgt 1f / branch if r5 greater than u.count 17197 00004C4B 890D[6C740000] <1> mov [u.count], ecx ; required read count 17198 <1> ; mov r5,u.count 17199 <1> ; 17200 00004C51 EB2A <1> jmp short sysexec_16 17201 <1> ; 17202 <1> sysexec_14: 17203 <1> ; 23/06/2015 17204 <1> ; insufficient (out of) memory 17205 00004C53 C705[9D740000]0100- <1> mov dword [u.error], ERR_MINOR_IM ; 1 17206 00004C5B 0000 <1> 17207 00004C5D E9D8F3FFFF <1> jmp error 17208 <1> ; 17209 <1> sysexec_15: 17210 <1> ; 25/06/2015 17211 00004C62 0FB715[1A710000] <1> movzx edx, word [i.size] ; file size 17212 00004C69 29CA <1> sub edx, ecx ; file size - loaded bytes 17213 00004C6B 7627 <1> jna short sysexec_17 ; no need to next read 17214 00004C6D 01D1 <1> add ecx, edx ; [i.size] 17215 00004C6F 3B0D[6C740000] <1> cmp ecx, [u.count] ; overrun check (!) 17216 00004C75 77DC <1> ja short sysexec_14 17217 00004C77 8915[6C740000] <1> mov [u.count], edx 17218 <1> sysexec_16: 17219 00004C7D 66A1[2A740000] <1> mov ax, [ii] ; i-number 17220 00004C83 E83E0C0000 <1> call readi 17221 <1> ; add core+10,u.nread / add size of user data area 17222 <1> ; / to u.nread 17223 <1> ; br 2f 17224 <1> ; 1: 17225 <1> ; jsr r0,readi / read in rest of file 17226 <1> ; 2: 17227 00004C88 8B0D[70740000] <1> mov ecx, [u.nread] 17228 00004C8E 010D[74740000] <1> add [u.break], ecx 17229 <1> ; mov u.nread,u.break / set users program break to end of 17230 <1> ; / user code 17231 <1> ; add $core+14,u.break / plus data area 17232 <1> sysexec_17: ; 20/07/2015 17233 <1> ;mov ax, [ii] ;rgc i-number 17234 00004C94 E8F9120000 <1> call iclose 17235 <1> ; jsr r0,iclose / does nothing 17236 00004C99 31C0 <1> xor eax, eax 17237 00004C9B FEC0 <1> inc al 17238 00004C9D 66A3[8C740000] <1> mov [u.intr], ax ; 1 (interrupt/time-out is enabled) 17239 00004CA3 66A3[8E740000] <1> mov [u.quit], ax ; 1 ('crtl+brk' signal is enabled) 17240 <1> ; 02/07/2015 17241 00004CA9 833D[A5740000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ? 17242 00004CB0 770C <1> ja short sysexec_18 ; no, the caller is user process 17243 <1> ; If the caller is kernel (sys_init), 'sysexec' will come here 17244 00004CB2 8B15[68700000] <1> mov edx, [k_page_dir] ; kernel's page directory 17245 00004CB8 8915[A5740000] <1> mov [u.ppgdir], edx ; next time 'sysexec' must not come here 17246 <1> sysexec_18: 17247 <1> ; 18/10/2015 17248 <1> ; 05/08/2015 17249 <1> ; 29/07/2015 17250 00004CBE 8B2D[C8740000] <1> mov ebp, [argv] ; user's stack pointer must point to argument 17251 <1> ; list pointers (argument count) 17252 00004CC4 FA <1> cli 17253 00004CC5 8B25[04700000] <1> mov esp, [tss.esp0] ; ring 0 (kernel) stack pointer 17254 <1> ;mov esp, [u.sp] ; Restore Kernel stack 17255 <1> ; for this process 17256 <1> ;add esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS 17257 <1> ;xor eax, eax ; 0 17258 00004CCB FEC8 <1> dec al ; eax = 0 17259 00004CCD 66BA2300 <1> mov dx, UDATA 17260 00004CD1 6652 <1> push dx ; user's stack segment 17261 00004CD3 55 <1> push ebp ; user's stack pointer 17262 <1> ; (points to number of arguments) 17263 00004CD4 FB <1> sti 17264 00004CD5 9C <1> pushfd ; EFLAGS 17265 <1> ; Set IF for enabling interrupts in user mode 17266 <1> ;or dword [esp], 200h 17267 <1> ; 17268 <1> ;mov bx, UCODE 17269 <1> ;push bx ; user's code segment 17270 00004CD6 6A1B <1> push UCODE 17271 <1> ;push 0 17272 00004CD8 50 <1> push eax ; EIP (=0) - start address - 17273 <1> ; clr -(r5) / popped into ps when rti in 17274 <1> ; / sysrele is executed 17275 <1> ; mov $core,-(r5) / popped into pc when rti 17276 <1> ; / in sysrele is executed 17277 <1> ;mov r5,0f / load second copyz argument 17278 <1> ;tst -(r5) / decrement r5 17279 00004CD9 8925[40740000] <1> mov [u.sp], esp ; 29/07/2015 17280 <1> ; 05/08/2015 17281 <1> ; Remedy of a General Protection Fault during 'iretd' is here ! 17282 <1> ; ('push dx' would cause to general protection fault, 17283 <1> ; after 'pop ds' etc.) 17284 <1> ; 17285 <1> ;; push dx ; ds (UDATA) 17286 <1> ;; push dx ; es (UDATA) 17287 <1> ;; push dx ; fs (UDATA) 17288 <1> ;; push dx ; gs (UDATA) 17289 <1> ; 17290 <1> ; This is a trick to prevent general protection fault 17291 <1> ; during 'iretd' intruction at the end of 'sysrele' (in u1.s): 17292 00004CDF 8EC2 <1> mov es, dx ; UDATA 17293 00004CE1 06 <1> push es ; ds (UDATA) 17294 00004CE2 06 <1> push es ; es (UDATA) 17295 00004CE3 06 <1> push es ; fs (UDATA) 17296 00004CE4 06 <1> push es ; gs (UDATA) 17297 00004CE5 66BA1000 <1> mov dx, KDATA 17298 00004CE9 8EC2 <1> mov es, dx 17299 <1> ; 17300 <1> ;; pushad simulation 17301 00004CEB 89E5 <1> mov ebp, esp ; esp before pushad 17302 00004CED 50 <1> push eax ; eax (0) 17303 00004CEE 50 <1> push eax ; ecx (0) 17304 00004CEF 50 <1> push eax ; edx (0) 17305 00004CF0 50 <1> push eax ; ebx (0) 17306 00004CF1 55 <1> push ebp ; esp before pushad 17307 00004CF2 50 <1> push eax ; ebp (0) 17308 00004CF3 50 <1> push eax ; esi (0) 17309 00004CF4 50 <1> push eax ; edi (0) 17310 <1> ; 17311 00004CF5 A3[48740000] <1> mov [u.r0], eax ; eax = 0 17312 00004CFA 8925[44740000] <1> mov [u.usp], esp 17313 <1> ; mov r5,u.r0 / 17314 <1> ; sub $16.,r5 / skip 8 words 17315 <1> ; mov r5,u.sp / assign user stack pointer value, 17316 <1> ; / effectively zeroes all regs 17317 <1> ; / when sysrele is executed 17318 <1> ; jsr r0,copyz; core; 0:0 / zero user's core 17319 <1> ; clr u.break 17320 <1> ; mov r5,sp / point sp to user's stack 17321 <1> ; 17322 00004D00 E958F3FFFF <1> jmp sysret0 17323 <1> ;jmp sysret 17324 <1> ; br sysret3 / return to core image at $core 17325 <1> 17326 <1> get_argp: 17327 <1> ; 18/10/2015 (nbase, ncount) 17328 <1> ; 21/07/2015 17329 <1> ; 24/06/2015 (Retro UNIX 386 v1) 17330 <1> ; Get (virtual) address of argument from user's core memory 17331 <1> ; 17332 <1> ; INPUT: 17333 <1> ; esi = virtual address of argument pointer 17334 <1> ; OUTPUT: 17335 <1> ; eax = virtual address of argument 17336 <1> ; 17337 <1> ; Modified registers: EAX, EBX, ECX, EDX, ESI 17338 <1> ; 17339 00004D05 833D[A5740000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? 17340 <1> ; (the caller is kernel) 17341 00004D0C 7667 <1> jna short get_argpk 17342 <1> ; 17343 00004D0E 89F3 <1> mov ebx, esi 17344 00004D10 E873E9FFFF <1> call get_physical_addr ; get physical address 17345 00004D15 0F8289000000 <1> jc get_argp_err 17346 00004D1B A3[C0740000] <1> mov [nbase], eax ; physical address 17347 00004D20 66890D[C4740000] <1> mov [ncount], cx ; remain byte count in page (1-4096) 17348 00004D27 B804000000 <1> mov eax, 4 ; 21/07/2015 17349 00004D2C 6639C1 <1> cmp cx, ax ; 4 17350 00004D2F 735D <1> jnb short get_argp2 17351 00004D31 89F3 <1> mov ebx, esi 17352 00004D33 01CB <1> add ebx, ecx 17353 00004D35 E84EE9FFFF <1> call get_physical_addr ; get physical address 17354 00004D3A 7268 <1> jc short get_argp_err 17355 <1> ;push esi 17356 00004D3C 89C6 <1> mov esi, eax 17357 00004D3E 66870D[C4740000] <1> xchg cx, [ncount] 17358 00004D45 8735[C0740000] <1> xchg esi, [nbase] 17359 00004D4B B504 <1> mov ch, 4 17360 00004D4D 28CD <1> sub ch, cl 17361 <1> get_argp0: 17362 00004D4F AC <1> lodsb 17363 00004D50 6650 <1> push ax 17364 00004D52 FEC9 <1> dec cl 17365 00004D54 75F9 <1> jnz short get_argp0 17366 00004D56 8B35[C0740000] <1> mov esi, [nbase] 17367 <1> ; 21/07/2015 17368 00004D5C 0FB6C5 <1> movzx eax, ch 17369 00004D5F 0105[C0740000] <1> add [nbase], eax 17370 00004D65 662905[C4740000] <1> sub [ncount], ax 17371 <1> get_argp1: 17372 00004D6C AC <1> lodsb 17373 00004D6D FECD <1> dec ch 17374 00004D6F 743D <1> jz short get_argp3 17375 00004D71 6650 <1> push ax 17376 00004D73 EBF7 <1> jmp short get_argp1 17377 <1> get_argpk: 17378 <1> ; Argument is in kernel's memory space 17379 00004D75 66C705[C4740000]00- <1> mov word [ncount], PAGE_SIZE ; 4096 17380 00004D7D 10 <1> 17381 00004D7E 8935[C0740000] <1> mov [nbase], esi 17382 00004D84 8305[C0740000]04 <1> add dword [nbase], 4 17383 00004D8B 8B06 <1> mov eax, [esi] ; virtual addr. = physcal addr. 17384 00004D8D C3 <1> retn 17385 <1> get_argp2: 17386 <1> ; 21/07/2015 17387 <1> ;mov eax, 4 17388 00004D8E 8B15[C0740000] <1> mov edx, [nbase] ; 18/10/2015 17389 00004D94 0105[C0740000] <1> add [nbase], eax 17390 00004D9A 662905[C4740000] <1> sub [ncount], ax 17391 <1> ; 17392 00004DA1 8B02 <1> mov eax, [edx] 17393 00004DA3 C3 <1> retn 17394 <1> get_argp_err: 17395 00004DA4 A3[9D740000] <1> mov [u.error], eax 17396 00004DA9 E98CF2FFFF <1> jmp error 17397 <1> get_argp3: 17398 00004DAE B103 <1> mov cl, 3 17399 <1> get_argp4: 17400 00004DB0 C1E008 <1> shl eax, 8 17401 00004DB3 665A <1> pop dx 17402 00004DB5 88D0 <1> mov al, dl 17403 00004DB7 E2F7 <1> loop get_argp4 17404 <1> ;pop esi 17405 00004DB9 C3 <1> retn 17406 <1> 17407 <1> sysfstat: 17408 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 17409 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 17410 <1> ; 17411 <1> ; 'sysfstat' is identical to 'sysstat' except that it operates 17412 <1> ; on open files instead of files given by name. It puts the 17413 <1> ; buffer address on the stack, gets the i-number and 17414 <1> ; checks to see if the file is open for reading or writing. 17415 <1> ; If the file is open for writing (i-number is negative) 17416 <1> ; the i-number is set positive and a branch into 'sysstat' 17417 <1> ; is made. 17418 <1> ; 17419 <1> ; Calling sequence: 17420 <1> ; sysfstat; buf 17421 <1> ; Arguments: 17422 <1> ; buf - buffer address 17423 <1> ; 17424 <1> ; Inputs: *u.r0 - file descriptor 17425 <1> ; Outputs: buffer is loaded with file information 17426 <1> ; ............................................................... 17427 <1> ; 17428 <1> ; Retro UNIX 8086 v1 modification: 17429 <1> ; 'sysfstat' system call has two arguments; so, 17430 <1> ; * 1st argument, file descriptor is in BX register 17431 <1> ; * 2nd argument, buf is pointed to by CX register 17432 <1> 17433 <1> ; / set status of open file 17434 <1> ; jsr r0,arg; u.off / put buffer address in u.off 17435 00004DBA 51 <1> push ecx 17436 <1> ; mov u.off,-(sp) / put buffer address on the stack 17437 <1> ; mov *u.r0,r1 / put file descriptor in r1 17438 <1> ; jsr r0,getf / get the files i-number 17439 <1> ; BX = file descriptor (file number) 17440 00004DBB E8FF000000 <1> call getf1 17441 00004DC0 6621C0 <1> and ax, ax ; i-number of the file 17442 <1> ; tst r1 / is it 0? 17443 <1> ;jz error 17444 <1> ; beq error3 / yes, error 17445 00004DC3 750F <1> jnz short sysfstat1 17446 00004DC5 C705[9D740000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 17447 00004DCD 0000 <1> 17448 00004DCF E966F2FFFF <1> jmp error 17449 <1> sysfstat1: 17450 00004DD4 80FC80 <1> cmp ah, 80h 17451 00004DD7 7223 <1> jb short sysstat1 17452 <1> ; bgt 1f / if i-number is negative (open for writing) 17453 00004DD9 66F7D8 <1> neg ax 17454 <1> ; neg r1 / make it positive, then branch 17455 00004DDC EB1E <1> jmp short sysstat1 17456 <1> ; br 1f / to 1f 17457 <1> sysstat: 17458 <1> ; 18/10/2015 17459 <1> ; 07/10/2015 17460 <1> ; 02/09/2015 17461 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 17462 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 17463 <1> ; 17464 <1> ; 'sysstat' gets the status of a file. Its arguments are the 17465 <1> ; name of the file and buffer address. The buffer is 34 bytes 17466 <1> ; long and information about the file placed in it. 17467 <1> ; sysstat calls 'namei' to get the i-number of the file. 17468 <1> ; Then 'iget' is called to get i-node in core. The buffer 17469 <1> ; is then loaded and the results are given in the UNIX 17470 <1> ; Programmers Manual sysstat (II). 17471 <1> ; 17472 <1> ; Calling sequence: 17473 <1> ; sysstat; name; buf 17474 <1> ; Arguments: 17475 <1> ; name - points to the name of the file 17476 <1> ; buf - address of a 34 bytes buffer 17477 <1> ; Inputs: - 17478 <1> ; Outputs: buffer is loaded with file information 17479 <1> ; ............................................................... 17480 <1> ; 17481 <1> ; Retro UNIX 8086 v1 modification: 17482 <1> ; 'sysstat' system call has two arguments; so, 17483 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 17484 <1> ; to get sysstat system call arguments from the user; 17485 <1> ; * 1st argument, name is pointed to by BX register 17486 <1> ; * 2nd argument, buf is pointed to by CX register 17487 <1> ; 17488 <1> ; NOTE: Retro UNIX 8086 v1 'arg2' routine gets these 17489 <1> ; arguments which were in these registers; 17490 <1> ; but, it returns by putting the 1st argument 17491 <1> ; in 'u.namep' and the 2nd argument 17492 <1> ; on top of stack. (1st argument is offset of the 17493 <1> ; file/path name in the user's program segment.) 17494 <1> 17495 <1> ; / ; name of file; buffer - get files status 17496 <1> ; jsr r0,arg2 / get the 2 arguments 17497 00004DDE 891D[60740000] <1> mov [u.namep], ebx 17498 00004DE4 51 <1> push ecx 17499 00004DE5 E80C010000 <1> call namei 17500 <1> ; jsr r0,namei / get the i-number for the file 17501 <1> ;jc error 17502 <1> ; br error3 / no such file, error 17503 00004DEA 7310 <1> jnc short sysstat1 17504 <1> ; pop ecx 17505 <1> sysstat_err0: 17506 <1> ; 'file not found !' error 17507 00004DEC C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 17508 00004DF4 0000 <1> 17509 00004DF6 E93FF2FFFF <1> jmp error 17510 <1> 17511 00004DFB 00 <1> statx: db 0 17512 <1> 17513 <1> sysstat1: ; 1: 17514 00004DFC E8E5080000 <1> call iget 17515 <1> ; jsr r0,iget / get the i-node into core 17516 <1> ; 07/10/2015 (ax = [ii], inode number) 17517 <1> ; 02/09/2015 17518 00004E01 8F05[68740000] <1> pop dword [u.base] 17519 <1> ; mov (sp)+,r3 / move u.off to r3 (points to buffer) 17520 00004E07 E858000000 <1> call sysstat_gpa ; get physical address 17521 00004E0C 730A <1> jnc short sysstat2 17522 <1> sysstat_err1: 17523 00004E0E A3[9D740000] <1> mov dword [u.error], eax ; error code 17524 00004E13 E922F2FFFF <1> jmp error 17525 <1> sysstat2: 17526 00004E18 A0[2A740000] <1> mov al, [ii] ; 07/10/2015 (result of 'iget' call, above) 17527 00004E1D AA <1> stosb 17528 00004E1E FF05[68740000] <1> inc dword [u.base] 17529 00004E24 6649 <1> dec cx 17530 00004E26 7505 <1> jnz short sysstat3 17531 00004E28 E837000000 <1> call sysstat_gpa 17532 <1> ;jc short sysstat_err1 17533 <1> sysstat3: 17534 00004E2D A0[2B740000] <1> mov al, [ii+1] ; 07/10/2015 (result of 'iget' call, above) 17535 00004E32 AA <1> stosb 17536 <1> ; mov r1,(r3)+ / put i-number in 1st word of buffer 17537 00004E33 FF05[68740000] <1> inc dword [u.base] 17538 <1> ;dec word [u.pcount] 17539 00004E39 6649 <1> dec cx 17540 00004E3B 7505 <1> jnz short sysstat4 17541 00004E3D E822000000 <1> call sysstat_gpa 17542 <1> ;jc short sysstat_err1 17543 <1> sysstat4: 17544 00004E42 BE[16710000] <1> mov esi, inode 17545 <1> ; mov $inode,r2 / r2 points to i-node 17546 <1> sysstat5: ; 1: 17547 00004E47 A4 <1> movsb 17548 <1> ; mov (r2)+,(r3)+ / move rest of i-node to buffer 17549 00004E48 FF05[68740000] <1> inc dword [u.base] 17550 <1> ;dec word [u.pcount] 17551 00004E4E 6649 <1> dec cx 17552 00004E50 7505 <1> jnz short sysstat6 17553 00004E52 E80D000000 <1> call sysstat_gpa 17554 <1> ;jc short sysstat_err1 17555 <1> sysstat6: 17556 00004E57 81FE[36710000] <1> cmp esi, inode + 32 17557 <1> ; cmp r2,$inode+32 / done? 17558 00004E5D 75E8 <1> jne short sysstat5 17559 <1> ; bne 1b / no, go back 17560 00004E5F E9F6F1FFFF <1> jmp sysret 17561 <1> ; br sysret3 / return through sysret 17562 <1> ; 17563 <1> sysstat_gpa: ; get physical address of file status buffer 17564 <1> ; 02/09/2015 17565 00004E64 8B1D[68740000] <1> mov ebx, [u.base] 17566 <1> ; 07/10/2015 17567 00004E6A E819E8FFFF <1> call get_physical_addr ; get physical address 17568 <1> ;jc short sysstat_gpa1 17569 00004E6F 729D <1> jc short sysstat_err1 17570 <1> ; 18/10/2015 17571 00004E71 89C7 <1> mov edi, eax ; physical address 17572 <1> ;mov [u.pcount], cx ; remain bytes in page 17573 <1> ;sysstat_gpa1: 17574 00004E73 C3 <1> retn 17575 <1> 17576 <1> fclose: 17577 <1> ; 18/06/2015 (Retro UNIX 386 v1 - Beginning) 17578 <1> ; (32 bit offset pointer modification) 17579 <1> ; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1) 17580 <1> ; 17581 <1> ; Given the file descriptor (index to the u.fp list) 17582 <1> ; 'fclose' first gets the i-number of the file via 'getf'. 17583 <1> ; If i-node is active (i-number > 0) the entry in 17584 <1> ; u.fp list is cleared. If all the processes that opened 17585 <1> ; that file close it, then fsp etry is freed and the file 17586 <1> ; is closed. If not a return is taken. 17587 <1> ; If the file has been deleted while open, 'anyi' is called 17588 <1> ; to see anyone else has it open, i.e., see if it is appears 17589 <1> ; in another entry in the fsp table. Upon return from 'anyi' 17590 <1> ; a check is made to see if the file is special. 17591 <1> ; 17592 <1> ; INPUTS -> 17593 <1> ; r1 - contains the file descriptor (value=0,1,2...) 17594 <1> ; u.fp - list of entries in the fsp table 17595 <1> ; fsp - table of entries (4 words/entry) of open files. 17596 <1> ; OUTPUTS -> 17597 <1> ; r1 - contains the same file descriptor 17598 <1> ; r2 - contains i-number 17599 <1> ; 17600 <1> ; ((AX = R1)) 17601 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 17602 <1> ; 17603 <1> ; Retro UNIX 8086 v1 modification : CF = 1 17604 <1> ; if i-number of the file is 0. (error) 17605 <1> ; 17606 00004E74 0FB7D0 <1> movzx edx, ax ; ** 17607 00004E77 6650 <1> push ax ; *** 17608 <1> ; mov r1,-(sp) / put r1 on the stack (it contains 17609 <1> ; / the index to u.fp list) 17610 00004E79 E83F000000 <1> call getf 17611 <1> ; jsr r0,getf / r1 contains i-number, 17612 <1> ; / cdev has device =, u.fofp 17613 <1> ; / points to 3rd word of fsp entry 17614 00004E7E 6683F801 <1> cmp ax, 1 ; r1 17615 <1> ; tst r1 / is i-number 0? 17616 00004E82 7236 <1> jb short fclose_2 17617 <1> ; beq 1f / yes, i-node not active so return 17618 <1> ; tst (r0)+ / no, jump over error return 17619 00004E84 89D3 <1> mov ebx, edx ; ** 17620 00004E86 6689C2 <1> mov dx, ax ; * 17621 <1> ; mov r1,r2 / move i-number to r2 ;* 17622 <1> ; mov (sp),r1 / restore value of r1 from the stack 17623 <1> ; / which is index to u.fp ; ** 17624 00004E89 C683[4E740000]00 <1> mov byte [ebx+u.fp], 0 17625 <1> ; clrb u.fp(r1) / clear that entry in the u.fp list 17626 00004E90 8B1D[58740000] <1> mov ebx, [u.fofp] 17627 <1> ; mov u.fofp,r1 / r1 points to 3rd word in fsp entry 17628 <1> fclose_0: 17629 00004E96 FE4B04 <1> dec byte [ebx+4] ; 18/06/2015 17630 <1> ; decb 2(r1) / decrement the number of processes 17631 <1> ; / that have opened the file 17632 00004E99 791F <1> jns short fclose_2 ; jump if not negative (jump if bit 7 is 0) 17633 <1> ; bge 1f / if all processes haven't closed the file, return 17634 <1> ; 17635 00004E9B 6652 <1> push dx ;* 17636 <1> ; mov r2,-(sp) / put r2 on the stack (i-number) 17637 00004E9D 6631C0 <1> xor ax, ax ; 0 17638 00004EA0 668943FC <1> mov [ebx-4], ax ; 0 17639 <1> ; clr -4(r1) / clear 1st word of fsp entry 17640 00004EA4 8A4305 <1> mov al, [ebx+5] ; 18/06/2015 17641 <1> ; tstb 3(r1) / has this file been deleted 17642 00004EA7 20C0 <1> and al, al 17643 00004EA9 7408 <1> jz short fclose_1 17644 <1> ; beq 2f / no, branch 17645 00004EAB 6689D0 <1> mov ax, dx ; * 17646 <1> ; mov r2,r1 / yes, put i-number back into r1 17647 <1> ; AX = inode number 17648 00004EAE E868040000 <1> call anyi 17649 <1> ; jsr r0,anyi / free all blocks related to i-number 17650 <1> ; / check if file appears in fsp again 17651 <1> fclose_1: ; 2: 17652 00004EB3 6658 <1> pop ax ; * 17653 <1> ; mov (sp)+,r1 / put i-number back into r1 17654 00004EB5 E8D8100000 <1> call iclose ; close if it is special file 17655 <1> ; jsr r0,iclose / check to see if its a special file 17656 <1> fclose_2: ; 1: 17657 00004EBA 6658 <1> pop ax ; *** 17658 <1> ; mov (sp)+,r1 / put index to u.fp back into r1 17659 00004EBC C3 <1> retn 17660 <1> ; rts r0 17661 <1> 17662 <1> getf: ; / get the device number and the i-number of an open file 17663 <1> ; 13/05/2015 17664 <1> ; 11/05/2015 (Retro UNIX 386 v1 - Beginning) 17665 <1> ; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1) 17666 <1> ; 17667 00004EBD 89C3 <1> mov ebx, eax 17668 <1> getf1: ;; Calling point from 'rw1' (23/05/2013) 17669 00004EBF 83FB0A <1> cmp ebx, 10 17670 <1> ; cmp r1,$10. / user limited to 10 open files 17671 00004EC2 730A <1> jnb short getf2 ; 13/05/2015 17672 <1> ;jnb error 17673 <1> ; bhis error3 / u.fp is table of users open files, 17674 <1> ; / index in fsp table 17675 00004EC4 8A9B[4E740000] <1> mov bl, [ebx+u.fp] 17676 <1> ; movb u.fp(r1),r1 / r1 contains number of entry 17677 <1> ; / in fsp table 17678 00004ECA 08DB <1> or bl, bl 17679 00004ECC 7503 <1> jnz short getf3 17680 <1> ;jz short getf4 17681 <1> ; beq 1f / if its zero return 17682 <1> getf2: 17683 <1> ; 'File not open !' error (ax=0) 17684 00004ECE 29C0 <1> sub eax, eax 17685 00004ED0 C3 <1> retn 17686 <1> getf3: 17687 <1> ; Retro UNIX 386 v1 modification ! (11/05/2015) 17688 <1> ; 17689 <1> ; 'fsp' table (10 bytes/entry) 17690 <1> ; bit 15 bit 0 17691 <1> ; ---|------------------------------------------- 17692 <1> ; r/w| i-number of open file 17693 <1> ; ---|------------------------------------------- 17694 <1> ; device number 17695 <1> ; ----------------------------------------------- 17696 <1> ; offset pointer, r/w pointer to file (bit 0-15) 17697 <1> ; ----------------------------------------------- 17698 <1> ; offset pointer, r/w pointer to file (bit 16-31) 17699 <1> ; ----------------------|------------------------ 17700 <1> ; flag that says file | number of processes 17701 <1> ; has been deleted | that have file open 17702 <1> ; ----------------------|------------------------ 17703 <1> ; 17704 00004ED1 B80A000000 <1> mov eax, 10 17705 00004ED6 F6E3 <1> mul bl 17706 00004ED8 BB[10720000] <1> mov ebx, fsp - 6 ; the 3rd word in the fsp entry 17707 00004EDD 01C3 <1> add ebx, eax 17708 <1> ; asl r1 17709 <1> ; asl r1 / multiply by 8 to get index into 17710 <1> ; / fsp table entry 17711 <1> ; asl r1 17712 <1> ; add $fsp-4,r1 / r1 is pointing at the 3rd word 17713 <1> ; / in the fsp entry 17714 00004EDF 891D[58740000] <1> mov [u.fofp], ebx 17715 <1> ; mov r1,u.fofp / save address of 3rd word 17716 <1> ; / in fsp entry in u.fofp 17717 00004EE5 4B <1> dec ebx 17718 00004EE6 4B <1> dec ebx 17719 00004EE7 668B03 <1> mov ax, [ebx] 17720 <1> ;mov [cdev], al ; ;;Retro UNIX 8086 v1 ! 17721 00004EEA 66A3[2E740000] <1> mov [cdev], ax ; ;;in fact (!) 17722 <1> ;;dev number is in 1 byte 17723 <1> ; mov -(r1),cdev / remove the device number cdev 17724 00004EF0 4B <1> dec ebx 17725 00004EF1 4B <1> dec ebx 17726 00004EF2 668B03 <1> mov ax, [ebx] 17727 <1> ; mov -(r1),r1 / and the i-number r1 17728 <1> getf4: ; 1: 17729 00004EF5 C3 <1> retn 17730 <1> ; rts r0 17731 <1> 17732 <1> namei: 17733 <1> ; 04/12/2015 (14 byte file names) 17734 <1> ; 18/10/2015 (nbase, ncount) 17735 <1> ; 12/10/2015 17736 <1> ; 21/08/2015 17737 <1> ; 18/07/2015 17738 <1> ; 02/07/2015 17739 <1> ; 17/06/2015 17740 <1> ; 16/06/2015 (Retro UNIX 386 v1 - Beginning) 17741 <1> ; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 17742 <1> ; 17743 <1> ; 'namei' takes a file path name and returns i-number of 17744 <1> ; the file in the current directory or the root directory 17745 <1> ; (if the first character of the pathname is '/'). 17746 <1> ; 17747 <1> ; INPUTS -> 17748 <1> ; u.namep - points to a file path name 17749 <1> ; u.cdir - i-number of users directory 17750 <1> ; u.cdev - device number on which user directory resides 17751 <1> ; OUTPUTS -> 17752 <1> ; r1 - i-number of file 17753 <1> ; cdev 17754 <1> ; u.dirbuf - points to directory entry where a match 17755 <1> ; occurs in the search for file path name. 17756 <1> ; If no match u.dirb points to the end of 17757 <1> ; the directory and r1 = i-number of the current 17758 <1> ; directory. 17759 <1> ; ((AX = R1)) 17760 <1> ; 17761 <1> ; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM) 17762 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 17763 <1> ; 17764 <1> 17765 00004EF6 66A1[4C740000] <1> mov ax, [u.cdir] 17766 <1> ; mov u.cdir,r1 / put the i-number of current directory 17767 <1> ; / in r1 17768 00004EFC 668B15[92740000] <1> mov dx, [u.cdrv] 17769 00004F03 668915[2E740000] <1> mov [cdev], dx ; NOTE: Retro UNIX 8086 v1 17770 <1> ; device/drive number is in 1 byte, 17771 <1> ; not in 1 word! 17772 <1> ; mov u.cdev,cdev / device number for users directory 17773 <1> ; / into cdev 17774 <1> ; 12/10/2015 17775 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 17776 <1> ; convert virtual (pathname) addr to physical address 17777 00004F0A E82C010000 <1> call trans_addr_nmbp ; 12/10/2015 17778 <1> ; esi = physical address of [u.namep] 17779 <1> ; ecx = byte count in the page 17780 00004F0F 803E2F <1> cmp byte [esi], '/' 17781 <1> ; cmpb *u.namep,$'/ / is first char in file name a / 17782 00004F12 751E <1> jne short namei_1 17783 <1> ; bne 1f 17784 00004F14 FF05[60740000] <1> inc dword [u.namep] 17785 <1> ; inc u.namep / go to next char 17786 00004F1A 6649 <1> dec cx ; remain byte count in the page 17787 00004F1C 7506 <1> jnz short namei_0 17788 <1> ; 12/10/2015 17789 00004F1E E818010000 <1> call trans_addr_nmbp ; convert virtual address to physical 17790 <1> ; esi = physical address (page start + offset) 17791 <1> ; ecx = byte count in the page 17792 00004F23 4E <1> dec esi 17793 <1> namei_0: 17794 00004F24 46 <1> inc esi ; go to next char 17795 00004F25 66A1[38740000] <1> mov ax, [rootdir] ; 09/07/2013 17796 <1> ; mov rootdir,r1 / put i-number of rootdirectory in r1 17797 00004F2B C605[2E740000]00 <1> mov byte [cdev], 0 17798 <1> ; clr cdev / clear device number 17799 <1> namei_1: ; 1: 17800 00004F32 F606FF <1> test byte [esi], 0FFh 17801 00004F35 74BE <1> jz short getf4 17802 <1> ;jz nig 17803 <1> ; tstb *u.namep / is the character in file name a nul 17804 <1> ; beq nig / yes, end of file name reached; 17805 <1> ; / branch to "nig" 17806 <1> namei_2: ; 1: 17807 <1> ; 18/10/2015 17808 00004F37 8935[C0740000] <1> mov [nbase], esi 17809 00004F3D 66890D[C4740000] <1> mov [ncount], cx 17810 <1> ; 17811 <1> ;mov dx, 2 17812 00004F44 B202 <1> mov dl, 2 ; user flag (read, non-owner) 17813 00004F46 E876080000 <1> call access 17814 <1> ; jsr r0,access; 2 / get i-node with i-number r1 17815 <1> ; 'access' will not return here if user has not "r" permission ! 17816 00004F4B 66F705[16710000]00- <1> test word [i.flgs], 4000h 17817 00004F53 40 <1> 17818 <1> ; bit $40000,i.flgs / directory i-node? 17819 00004F54 746A <1> jz short namei_err 17820 <1> ; beq error3 / no, got an error 17821 <1> ; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1) 17822 00004F56 31C0 <1> xor eax, eax 17823 00004F58 A3[64740000] <1> mov [u.off], eax ; 0 17824 00004F5D 66A1[1A710000] <1> mov ax, [i.size] 17825 00004F63 A3[5C740000] <1> mov [u.dirp], eax 17826 <1> ; mov i.size,u.dirp / put size of directory in u.dirp 17827 <1> ; clr u.off / u.off is file offset used by user 17828 00004F68 C705[58740000]- <1> mov dword [u.fofp], u.off 17829 00004F6E [64740000] <1> 17830 <1> ; mov $u.off,u.fofp / u.fofp is a pointer to 17831 <1> ; / the offset portion of fsp entry 17832 <1> namei_3: ; 2: 17833 00004F72 C705[68740000]- <1> mov dword [u.base], u.dirbuf 17834 00004F78 [7A740000] <1> 17835 <1> ; mov $u.dirbuf,u.base / u.dirbuf holds a file name 17836 <1> ; / copied from a directory 17837 00004F7C C705[6C740000]1000- <1> mov dword [u.count], 16 ; 04/12/2015 (10 -> 16) 17838 00004F84 0000 <1> 17839 <1> ; mov $10.,u.count / u.count is byte count 17840 <1> ; / for reads and writes 17841 00004F86 66A1[2A740000] <1> mov ax, [ii] 17842 <1> ; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall') 17843 00004F8C FE05[AF740000] <1> inc byte [u.kcall] ; the caller is 'namei' sign 17844 00004F92 E82F090000 <1> call readi 17845 <1> ; jsr r0,readi / read 10. bytes of file 17846 <1> ; with i-number (r1); i.e. read a directory entry 17847 00004F97 8B0D[70740000] <1> mov ecx, [u.nread] 17848 00004F9D 09C9 <1> or ecx, ecx 17849 <1> ; tst u.nread 17850 00004F9F 741B <1> jz short nib 17851 <1> ; ble nib / gives error return 17852 <1> ; 17853 00004FA1 668B1D[7A740000] <1> mov bx, [u.dirbuf] 17854 00004FA8 6621DB <1> and bx, bx 17855 <1> ; tst u.dirbuf / 17856 00004FAB 7522 <1> jnz short namei_4 17857 <1> ; bne 3f / branch when active directory entry 17858 <1> ; / (i-node word in entry non zero) 17859 00004FAD A1[64740000] <1> mov eax, [u.off] 17860 00004FB2 83E810 <1> sub eax, 16 ; 04/12/2015 (10 -> 16) 17861 00004FB5 A3[5C740000] <1> mov [u.dirp], eax 17862 <1> ; mov u.off,u.dirp 17863 <1> ; sub $10.,u.dirp 17864 00004FBA EBB6 <1> jmp short namei_3 17865 <1> ; br 2b 17866 <1> 17867 <1> ; 18/07/2013 17868 <1> nib: 17869 00004FBC 31C0 <1> xor eax, eax ; xor ax, ax ; ax = 0 -> file not found 17870 00004FBE F9 <1> stc 17871 <1> nig: 17872 00004FBF C3 <1> retn 17873 <1> 17874 <1> namei_err: 17875 <1> ; 16/06/2015 17876 00004FC0 C705[9D740000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a directory !' error 17877 00004FC8 0000 <1> 17878 00004FCA E96BF0FFFF <1> jmp error 17879 <1> 17880 <1> namei_4: ; 3: 17881 <1> ; 18/10/2015 17882 <1> ; 12/10/2015 17883 <1> ; 21/08/2015 17884 <1> ; 18/07/2015 17885 00004FCF 8B2D[60740000] <1> mov ebp, [u.namep] 17886 <1> ; mov u.namep,r2 / u.namep points into a file name string 17887 00004FD5 BF[7C740000] <1> mov edi, u.dirbuf + 2 17888 <1> ; mov $u.dirbuf+2,r3 / points to file name of directory entry 17889 <1> ; 18/10/2015 17890 00004FDA 8B35[C0740000] <1> mov esi, [nbase] 17891 00004FE0 668B0D[C4740000] <1> mov cx, [ncount] 17892 <1> ; 17893 00004FE7 6621C9 <1> and cx, cx 17894 00004FEA 7505 <1> jnz short namei_5 17895 <1> ; 17896 00004FEC E850000000 <1> call trans_addr_nm ; convert virtual address to physical 17897 <1> ; esi = physical address (page start + offset) 17898 <1> ; ecx = byte count in the page 17899 <1> namei_5: ; 3: 17900 00004FF1 45 <1> inc ebp ; 18/07/2015 17901 00004FF2 AC <1> lodsb ; mov al, [esi] ; inc esi (al = r4) 17902 <1> ; movb (r2)+,r4 / move a character from u.namep string into r4 17903 00004FF3 08C0 <1> or al, al 17904 00004FF5 741D <1> jz short namei_7 17905 <1> ; beq 3f / if char is nul, then the last char in string 17906 <1> ; / has been moved 17907 00004FF7 3C2F <1> cmp al, '/' 17908 <1> ; cmp r4,$'/ / is char a 17909 00004FF9 7419 <1> je short namei_7 17910 <1> ; beq 3f 17911 <1> ; 12/10/2015 17912 00004FFB 6649 <1> dec cx ; remain byte count in the page 17913 00004FFD 7505 <1> jnz short namei_6 17914 00004FFF E83D000000 <1> call trans_addr_nm ; convert virtual address to physical 17915 <1> ; esi = physical address (page start + offset) 17916 <1> ; ecx = byte count in the page 17917 <1> namei_6: 17918 00005004 81FF[8A740000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 17919 <1> ; cmp r3,$u.dirbuf+10. / have I checked 17920 <1> ; / all 8 bytes of file name 17921 0000500A 74E5 <1> je short namei_5 17922 <1> ; beq 3b 17923 0000500C AE <1> scasb 17924 <1> ; cmpb (r3)+,r4 / compare char in u.namep string to file name 17925 <1> ; / char read from directory 17926 0000500D 74E2 <1> je short namei_5 17927 <1> ; beq 3b / branch if chars match 17928 <1> 17929 0000500F E95EFFFFFF <1> jmp namei_3 ; 2b 17930 <1> ; br 2b / file names do not match go to next directory entry 17931 <1> namei_7: ; 3: 17932 00005014 81FF[8A740000] <1> cmp edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 17933 <1> ; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched 17934 0000501A 740A <1> je short namei_8 17935 <1> ; beq 3f 17936 0000501C 8A27 <1> mov ah, [edi] 17937 <1> ;inc edi 17938 0000501E 20E4 <1> and ah, ah 17939 <1> ; tstb (r3)+ / 17940 00005020 0F854CFFFFFF <1> jnz namei_3 17941 <1> ; bne 2b 17942 <1> namei_8: ; 3 17943 00005026 892D[60740000] <1> mov [u.namep], ebp ; 18/07/2015 17944 <1> ; mov r2,u.namep / u.namep points to char 17945 <1> ; / following a / or nul 17946 <1> ;mov bx, [u.dirbuf] 17947 <1> ; mov u.dirbuf,r1 / move i-node number in directory 17948 <1> ; / entry to r1 17949 0000502C 20C0 <1> and al, al 17950 <1> ; tst r4 / if r4 = 0 the end of file name reached, 17951 <1> ; / if r4 = then go to next directory 17952 <1> ; mov ax, bx 17953 0000502E 66A1[7A740000] <1> mov ax, [u.dirbuf] ; 17/06/2015 17954 00005034 0F85FDFEFFFF <1> jnz namei_2 17955 <1> ; bne 1b 17956 <1> ; AX = i-number of the file 17957 <1> ;;nig: 17958 0000503A C3 <1> retn 17959 <1> ; tst (r0)+ / gives non-error return 17960 <1> ;;nib: 17961 <1> ;; xor ax, ax ; Retro UNIX 8086 v1 modification ! 17962 <1> ; ax = 0 -> file not found 17963 <1> ;; stc ; 27/05/2013 17964 <1> ;; retn 17965 <1> ; rts r0 17966 <1> 17967 <1> trans_addr_nmbp: 17968 <1> ; 18/10/2015 17969 <1> ; 12/10/2015 17970 0000503B 8B2D[60740000] <1> mov ebp, [u.namep] 17971 <1> trans_addr_nm: 17972 <1> ; Convert virtual (pathname) address to physical address 17973 <1> ; (Retro UNIX 386 v1 feature only !) 17974 <1> ; 18/10/2015 17975 <1> ; 12/10/2015 (u.pnbase & u.pncount has been removed from code) 17976 <1> ; 02/07/2015 17977 <1> ; 17/06/2015 17978 <1> ; 16/06/2015 17979 <1> ; 17980 <1> ; INPUTS: 17981 <1> ; ebp = pathname address (virtual) ; [u.namep] 17982 <1> ; [u.pgdir] = user's page directory 17983 <1> ; OUTPUT: 17984 <1> ; esi = physical address of the pathname 17985 <1> ; ecx = remain byte count in the page 17986 <1> ; 17987 <1> ; (Modified registers: EAX, EBX, ECX, EDX, ESI) 17988 <1> ; 17989 00005041 833D[A5740000]00 <1> cmp dword [u.ppgdir], 0 ; /etc/init ? (sysexec) 17990 00005048 7618 <1> jna short trans_addr_nmk ; the caller is os kernel; 17991 <1> ; it is already physical address 17992 0000504A 50 <1> push eax 17993 0000504B 89EB <1> mov ebx, ebp ; [u.namep] ; pathname address (virtual) 17994 0000504D E836E6FFFF <1> call get_physical_addr ; get physical address 17995 00005052 7204 <1> jc short tr_addr_nm_err 17996 <1> ; 18/10/2015 17997 <1> ; eax = physical address 17998 <1> ; cx = remain byte count in page (1-4096) 17999 <1> ; 12/10/2015 (cx = [u.pncount]) 18000 00005054 89C6 <1> mov esi, eax ; 12/10/2015 (esi=[u.pnbase]) 18001 00005056 58 <1> pop eax 18002 00005057 C3 <1> retn 18003 <1> 18004 <1> tr_addr_nm_err: 18005 00005058 A3[9D740000] <1> mov [u.error], eax 18006 <1> ;pop eax 18007 0000505D E9D8EFFFFF <1> jmp error 18008 <1> 18009 <1> trans_addr_nmk: 18010 <1> ; 12/10/2015 18011 <1> ; 02/07/2015 18012 00005062 8B35[60740000] <1> mov esi, [u.namep] ; [u.pnbase] 18013 00005068 66B90010 <1> mov cx, PAGE_SIZE ; 4096 ; [u.pncount] 18014 0000506C C3 <1> retn 18015 <1> 18016 <1> syschdir: 18017 <1> ; / makes the directory specified in the argument 18018 <1> ; / the current directory 18019 <1> ; 18020 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18021 <1> ; 19/06/2013 (Retro UNIX 8086 v1) 18022 <1> ; 18023 <1> ; 'syschdir' makes the directory specified in its argument 18024 <1> ; the current working directory. 18025 <1> ; 18026 <1> ; Calling sequence: 18027 <1> ; syschdir; name 18028 <1> ; Arguments: 18029 <1> ; name - address of the path name of a directory 18030 <1> ; terminated by nul byte. 18031 <1> ; Inputs: - 18032 <1> ; Outputs: - 18033 <1> ; ............................................................... 18034 <1> ; 18035 <1> ; Retro UNIX 8086 v1 modification: 18036 <1> ; The user/application program puts address of 18037 <1> ; the path name in BX register as 'syschdir' 18038 <1> ; system call argument. 18039 <1> 18040 0000506D 891D[60740000] <1> mov [u.namep], ebx 18041 <1> ;jsr r0,arg; u.namep / u.namep points to path name 18042 00005073 E87EFEFFFF <1> call namei 18043 <1> ; jsr r0,namei / find its i-number 18044 <1> ;jc error 18045 <1> ; br error3 18046 00005078 730F <1> jnc short syschdir0 18047 <1> ; 'directory not found !' error 18048 0000507A C705[9D740000]0C00- <1> mov dword [u.error], ERR_DIR_NOT_FOUND ; 12 18049 00005082 0000 <1> 18050 00005084 E9B1EFFFFF <1> jmp error 18051 <1> syschdir0: 18052 00005089 E833070000 <1> call access 18053 <1> ; jsr r0,access; 2 / get i-node into core 18054 0000508E 66F705[16710000]00- <1> test word [i.flgs], 4000h 18055 00005096 40 <1> 18056 <1> ; bit $40000,i.flgs / is it a directory? 18057 <1> ;jz error 18058 <1> ; beq error3 / no error 18059 00005097 750F <1> jnz short syschdir1 18060 00005099 C705[9D740000]1300- <1> mov dword [u.error], ERR_NOT_DIR ; 'not a valid directory !' 18061 000050A1 0000 <1> 18062 000050A3 E992EFFFFF <1> jmp error 18063 <1> syschdir1: 18064 000050A8 66A3[4C740000] <1> mov [u.cdir], ax 18065 <1> ; mov r1,u.cdir / move i-number to users 18066 <1> ; / current directory 18067 000050AE 66A1[2E740000] <1> mov ax, [cdev] 18068 000050B4 66A3[92740000] <1> mov [u.cdrv], ax 18069 <1> ; mov cdev,u.cdev / move its device to users 18070 <1> ; / current device 18071 000050BA E99BEFFFFF <1> jmp sysret 18072 <1> ; br sysret3 18073 <1> 18074 <1> syschmod: ; < change mode of file > 18075 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18076 <1> ; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1) 18077 <1> ; 18078 <1> ; 'syschmod' changes mode of the file whose name is given as 18079 <1> ; null terminated string pointed to by 'name' has it's mode 18080 <1> ; changed to 'mode'. 18081 <1> ; 18082 <1> ; Calling sequence: 18083 <1> ; syschmod; name; mode 18084 <1> ; Arguments: 18085 <1> ; name - address of the file name 18086 <1> ; terminated by null byte. 18087 <1> ; mode - (new) mode/flags < attributes > 18088 <1> ; 18089 <1> ; Inputs: - 18090 <1> ; Outputs: - 18091 <1> ; ............................................................... 18092 <1> ; 18093 <1> ; Retro UNIX 8086 v1 modification: 18094 <1> ; 'syschmod' system call has two arguments; so, 18095 <1> ; * 1st argument, name is pointed to by BX register 18096 <1> ; * 2nd argument, mode is in CX register 18097 <1> ; 18098 <1> ; Mode bits (Flags): 18099 <1> ; bit 0 - write permission for non-owner (1) 18100 <1> ; bit 1 - read permission for non-owner (2) 18101 <1> ; bit 2 - write permission for owner (4) 18102 <1> ; bit 3 - read permission for owner (8) 18103 <1> ; bit 4 - executable flag (16) 18104 <1> ; bit 5 - set user ID on execution flag (32) 18105 <1> ; bit 6,7,8,9,10,11 are not used (undefined) 18106 <1> ; bit 12 - large file flag (4096) 18107 <1> ; bit 13 - file has modified flag (always on) (8192) 18108 <1> ; bit 14 - directory flag (16384) 18109 <1> ; bit 15 - 'i-node is allocated' flag (32768) 18110 <1> 18111 <1> ; / name; mode 18112 000050BF E814000000 <1> call isown 18113 <1> ;jsr r0,isown / get the i-node and check user status 18114 000050C4 66F705[16710000]00- <1> test word [i.flgs], 4000h 18115 000050CC 40 <1> 18116 <1> ; bit $40000,i.flgs / directory? 18117 000050CD 7402 <1> jz short syschmod1 18118 <1> ; beq 2f / no 18119 <1> ; AL = (new) mode 18120 000050CF 24CF <1> and al, 0CFh ; 11001111b (clears bit 4 & 5) 18121 <1> ; bic $60,r2 / su & ex / yes, clear set user id and 18122 <1> ; / executable modes 18123 <1> syschmod1: ; 2: 18124 000050D1 A2[16710000] <1> mov [i.flgs], al 18125 <1> ; movb r2,i.flgs / move remaining mode to i.flgs 18126 000050D6 EB42 <1> jmp short isown1 18127 <1> ; br 1f 18128 <1> 18129 <1> isown: 18130 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18131 <1> ; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1) 18132 <1> ; 18133 <1> ; 'isown' is given a file name (the 1st argument). 18134 <1> ; It find the i-number of that file via 'namei' 18135 <1> ; then gets the i-node into core via 'iget'. 18136 <1> ; It then tests to see if the user is super user. 18137 <1> ; If not, it cheks to see if the user is owner of 18138 <1> ; the file. If he is not an error occurs. 18139 <1> ; If user is the owner 'setimod' is called to indicate 18140 <1> ; the inode has been modificed and the 2nd argument of 18141 <1> ; the call is put in r2. 18142 <1> ; 18143 <1> ; INPUTS -> 18144 <1> ; arguments of syschmod and syschown calls 18145 <1> ; OUTPUTS -> 18146 <1> ; u.uid - id of user 18147 <1> ; imod - set to a 1 18148 <1> ; r2 - contains second argument of the system call 18149 <1> ; 18150 <1> ; ((AX=R2) output as 2nd argument) 18151 <1> ; 18152 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 18153 <1> ; 18154 <1> ; jsr r0,arg2 / u.namep points to file name 18155 <1> ;; ! 2nd argument on top of stack ! 18156 <1> ;; 22/06/2015 - 32 bit modifications 18157 <1> ;; 07/07/2013 18158 000050D8 891D[60740000] <1> mov [u.namep], ebx ;; 1st argument 18159 000050DE 51 <1> push ecx ;; 2nd argument 18160 <1> ;; 18161 000050DF E812FEFFFF <1> call namei 18162 <1> ; jsr r0,namei / get its i-number 18163 <1> ; Retro UNIX 8086 v1 modification ! 18164 <1> ; ax = 0 -> file not found 18165 <1> ;and ax, ax 18166 <1> ;jz error 18167 <1> ;jc error ; 27/05/2013 18168 <1> ; br error3 18169 000050E4 730F <1> jnc short isown0 18170 <1> ; 'file not found !' error 18171 000050E6 C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; 12 18172 000050EE 0000 <1> 18173 000050F0 E945EFFFFF <1> jmp error 18174 <1> isown0: 18175 000050F5 E8EC050000 <1> call iget 18176 <1> ; jsr r0,iget / get i-node into core 18177 000050FA A0[94740000] <1> mov al, [u.uid] ; 02/08/2013 18178 000050FF 08C0 <1> or al, al 18179 <1> ; tstb u.uid / super user? 18180 00005101 7417 <1> jz short isown1 18181 <1> ; beq 1f / yes, branch 18182 00005103 3A05[19710000] <1> cmp al, [i.uid] 18183 <1> ; cmpb i.uid,u.uid / no, is this the owner of 18184 <1> ; / the file 18185 <1> ;jne error 18186 <1> ; beq 1f / yes 18187 <1> ; jmp error3 / no, error 18188 00005109 740F <1> je short isown1 18189 <1> 18190 0000510B C705[9D740000]0B00- <1> mov dword [u.error], ERR_NOT_OWNER ; 11 18191 00005113 0000 <1> 18192 <1> ; 'permission denied !' error 18193 00005115 E920EFFFFF <1> jmp error 18194 <1> isown1: ; 1: 18195 0000511A E8DA060000 <1> call setimod 18196 <1> ; jsr r0,setimod / indicates 18197 <1> ; ; / i-node has been modified 18198 0000511F 58 <1> pop eax ; 2nd argument 18199 <1> ; mov (sp)+,r2 / mode is put in r2 18200 <1> ; / (u.off put on stack with 2nd arg) 18201 00005120 C3 <1> retn 18202 <1> ; rts r0 18203 <1> 18204 <1> ;;arg: ; < get system call arguments > 18205 <1> ; 'arg' extracts an argument for a routine whose call is 18206 <1> ; of form: 18207 <1> ; sys 'routine' ; arg1 18208 <1> ; or 18209 <1> ; sys 'routine' ; arg1 ; arg2 18210 <1> ; or 18211 <1> ; sys 'routine' ; arg1;...;arg10 (sys exec) 18212 <1> ; 18213 <1> ; INPUTS -> 18214 <1> ; u.sp+18 - contains a pointer to one of arg1..argn 18215 <1> ; This pointers's value is actually the value of 18216 <1> ; update pc at the the trap to sysent (unkni) is 18217 <1> ; made to process the sys instruction 18218 <1> ; r0 - contains the return address for the routine 18219 <1> ; that called arg. The data in the word pointer 18220 <1> ; to by the return address is used as address 18221 <1> ; in which the extracted argument is stored 18222 <1> ; 18223 <1> ; OUTPUTS -> 18224 <1> ; 'address' - contains the extracted argument 18225 <1> ; u.sp+18 - is incremented by 2 18226 <1> ; r1 - contains the extracted argument 18227 <1> ; r0 - points to the next instruction to be 18228 <1> ; executed in the calling routine. 18229 <1> ; 18230 <1> 18231 <1> ; mov u.sp,r1 18232 <1> ; mov *18.(r1),*(r0)+ / put argument of system call 18233 <1> ; / into argument of arg2 18234 <1> ; add $2,18.(r1) / point pc on stack 18235 <1> ; / to next system argument 18236 <1> ; rts r0 18237 <1> 18238 <1> ;;arg2: ; < get system calls arguments - with file name pointer> 18239 <1> ; 'arg2' takes first argument in system call 18240 <1> ; (pointer to name of the file) and puts it in location 18241 <1> ; u.namep; takes second argument and puts it in u.off 18242 <1> ; and on top of the stack 18243 <1> ; 18244 <1> ; INPUTS -> 18245 <1> ; u.sp, r0 18246 <1> ; 18247 <1> ; OUTPUTS -> 18248 <1> ; u.namep 18249 <1> ; u.off 18250 <1> ; u.off pushed on stack 18251 <1> ; r1 18252 <1> ; 18253 <1> 18254 <1> ; jsr r0,arg; u.namep / u.namep contains value of 18255 <1> ; / first arg in sys call 18256 <1> ; jsr r0,arg; u.off / u.off contains value of 18257 <1> ; / second arg in sys call 18258 <1> ; mov r0,r1 / r0 points to calling routine 18259 <1> ; mov (sp),r0 / put operation code back in r0 18260 <1> ; mov u.off,(sp) / put pointer to second argument 18261 <1> ; / on stack 18262 <1> ; jmp (r1) / return to calling routine 18263 <1> 18264 <1> syschown: ; < change owner of file > 18265 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18266 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 18267 <1> ; 18268 <1> ; 'syschown' changes the owner of the file whose name is given 18269 <1> ; as null terminated string pointed to by 'name' has it's owner 18270 <1> ; changed to 'owner' 18271 <1> ; 18272 <1> ; Calling sequence: 18273 <1> ; syschown; name; owner 18274 <1> ; Arguments: 18275 <1> ; name - address of the file name 18276 <1> ; terminated by null byte. 18277 <1> ; owner - (new) owner (number/ID) 18278 <1> ; 18279 <1> ; Inputs: - 18280 <1> ; Outputs: - 18281 <1> ; ............................................................... 18282 <1> ; 18283 <1> ; Retro UNIX 8086 v1 modification: 18284 <1> ; 'syschown' system call has two arguments; so, 18285 <1> ; * 1st argument, name is pointed to by BX register 18286 <1> ; * 2nd argument, owner number is in CX register 18287 <1> ; 18288 <1> ; / name; owner 18289 00005121 E8B2FFFFFF <1> call isown 18290 <1> ; jsr r0,isown / get the i-node and check user status 18291 00005126 803D[94740000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 18292 <1> ; tstb u.uid / super user 18293 0000512D 7418 <1> jz short syschown1 18294 <1> ; beq 2f / yes, 2f 18295 0000512F F605[16710000]20 <1> test byte [i.flgs], 20h ; 32 18296 <1> ; bit $40,i.flgs / no, set userid on execution? 18297 <1> ;jnz error 18298 <1> ; bne 3f / yes error, could create Trojan Horses 18299 00005136 740F <1> jz short syschown1 18300 <1> ; 'permission denied !' 18301 00005138 C705[9D740000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; 11 18302 00005140 0000 <1> 18303 00005142 E9F3EEFFFF <1> jmp error 18304 <1> syschown1: ; 2: 18305 <1> ; AL = owner (number/ID) 18306 00005147 A2[19710000] <1> mov [i.uid], al ; 23/06/2015 18307 <1> ; movb r2,i.uid / no, put the new owners id 18308 <1> ; / in the i-node 18309 0000514C E909EFFFFF <1> jmp sysret 18310 <1> ; 1: 18311 <1> ; jmp sysret4 18312 <1> ; 3: 18313 <1> ; jmp error 18314 <1> 18315 <1> systime: ; / get time of year 18316 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18317 <1> ; 20/06/2013 (Retro UNIX 8086 v1) 18318 <1> ; 18319 <1> ; 20/06/2013 18320 <1> ; 'systime' gets the time of the year. 18321 <1> ; The present time is put on the stack. 18322 <1> ; 18323 <1> ; Calling sequence: 18324 <1> ; systime 18325 <1> ; Arguments: - 18326 <1> ; 18327 <1> ; Inputs: - 18328 <1> ; Outputs: sp+2, sp+4 - present time 18329 <1> ; ............................................................... 18330 <1> ; 18331 <1> ; Retro UNIX 8086 v1 modification: 18332 <1> ; 'systime' system call will return to the user 18333 <1> ; with unix time (epoch) in DX:AX register pair 18334 <1> ; 18335 <1> ; !! Major modification on original Unix v1 'systime' 18336 <1> ; system call for PC compatibility !! 18337 <1> 18338 00005151 E81FEAFFFF <1> call epoch 18339 00005156 A3[48740000] <1> mov [u.r0], eax 18340 <1> ; mov s.time,4(sp) 18341 <1> ; mov s.time+2,2(sp) / put the present time 18342 <1> ; / on the stack 18343 <1> ; br sysret4 18344 0000515B E9FAEEFFFF <1> jmp sysret 18345 <1> 18346 <1> sysstime: ; / set time 18347 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18348 <1> ; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1) 18349 <1> ; 18350 <1> ; 'sysstime' sets the time. Only super user can use this call. 18351 <1> ; 18352 <1> ; Calling sequence: 18353 <1> ; sysstime 18354 <1> ; Arguments: - 18355 <1> ; 18356 <1> ; Inputs: sp+2, sp+4 - time system is to be set to. 18357 <1> ; Outputs: - 18358 <1> ; ............................................................... 18359 <1> ; 18360 <1> ; Retro UNIX 8086 v1 modification: 18361 <1> ; the user calls 'sysstime' with unix (epoch) time 18362 <1> ; (to be set) is in CX:BX register pair as two arguments. 18363 <1> ; 18364 <1> ; Retro UNIX 8086 v1 argument transfer method 2 is used 18365 <1> ; to get sysstime system call arguments from the user; 18366 <1> ; * 1st argument, lowword of unix time is in BX register 18367 <1> ; * 2nd argument, highword of unix time is in CX register 18368 <1> ; 18369 <1> ; !! Major modification on original Unix v1 'sysstime' 18370 <1> ; system call for PC compatibility !! 18371 <1> 18372 00005160 803D[94740000]00 <1> cmp byte [u.uid], 0 18373 <1> ; tstb u.uid / is user the super user 18374 <1> ;ja error 18375 <1> ; bne error4 / no, error 18376 00005167 760F <1> jna short systime1 18377 <1> ; 'permission denied !' 18378 00005169 C705[9D740000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 18379 00005171 0000 <1> 18380 00005173 E9C2EEFFFF <1> jmp error 18381 <1> systime1: 18382 <1> ; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version) 18383 <1> ; EBX = unix (epoch) time (from user) 18384 00005178 89D8 <1> mov eax, ebx 18385 0000517A E878EBFFFF <1> call set_date_time 18386 <1> ; mov 4(sp),s.time 18387 <1> ; mov 2(sp),s.time+2 / set the system time 18388 0000517F E9D6EEFFFF <1> jmp sysret 18389 <1> ; br sysret4 18390 <1> 18391 <1> sysbreak: 18392 <1> ; 18/10/2015 18393 <1> ; 07/10/2015 18394 <1> ; 23/06/2015 (Retro UNIX 386 v1 - Beginning) 18395 <1> ; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1) 18396 <1> ; 18397 <1> ; 'sysbreak' sets the programs break points. 18398 <1> ; It checks the current break point (u.break) to see if it is 18399 <1> ; between "core" and the stack (sp). If it is, it is made an 18400 <1> ; even address (if it was odd) and the area between u.break 18401 <1> ; and the stack is cleared. The new breakpoint is then put 18402 <1> ; in u.break and control is passed to 'sysret'. 18403 <1> ; 18404 <1> ; Calling sequence: 18405 <1> ; sysbreak; addr 18406 <1> ; Arguments: - 18407 <1> ; 18408 <1> ; Inputs: u.break - current breakpoint 18409 <1> ; Outputs: u.break - new breakpoint 18410 <1> ; area between old u.break and the stack (sp) is cleared. 18411 <1> ; ............................................................... 18412 <1> ; 18413 <1> ; Retro UNIX 8086 v1 modification: 18414 <1> ; The user/application program puts breakpoint address 18415 <1> ; in BX register as 'sysbreak' system call argument. 18416 <1> ; (argument transfer method 1) 18417 <1> ; 18418 <1> ; NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 ! 18419 <1> ; ((!'sysbreak' is not needed in Retro UNIX 8086 v1!)) 18420 <1> ; NOTE: 18421 <1> ; 'sysbreak' clears extended part (beyond of previous 18422 <1> ; 'u.break' address) of user's memory for original unix's 18423 <1> ; 'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013) 18424 <1> 18425 <1> ; mov u.break,r1 / move users break point to r1 18426 <1> ; cmp r1,$core / is it the same or lower than core? 18427 <1> ; blos 1f / yes, 1f 18428 <1> ; 23/06/2015 18429 00005184 8B2D[74740000] <1> mov ebp, [u.break] ; virtual address (offset) 18430 <1> ;and ebp, ebp 18431 <1> ;jz short sysbreak_3 18432 <1> ; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!! 18433 <1> ; (Even break point address is not needed for Retro UNIX 386 v1) 18434 0000518A 8B15[40740000] <1> mov edx, [u.sp] ; kernel stack at the beginning of sys call 18435 00005190 83C20C <1> add edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 18436 <1> ; 07/10/2015 18437 00005193 891D[74740000] <1> mov [u.break], ebx ; virtual address !!! 18438 <1> ; 18439 00005199 3B1A <1> cmp ebx, [edx] ; compare new break point with 18440 <1> ; with top of user's stack (virtual!) 18441 0000519B 7327 <1> jnb short sysbreak_3 18442 <1> ; cmp r1,sp / is it the same or higher 18443 <1> ; / than the stack? 18444 <1> ; bhis 1f / yes, 1f 18445 0000519D 89DE <1> mov esi, ebx 18446 0000519F 29EE <1> sub esi, ebp ; new break point - old break point 18447 000051A1 7621 <1> jna short sysbreak_3 18448 <1> ;push ebx 18449 <1> sysbreak_1: 18450 000051A3 89EB <1> mov ebx, ebp 18451 000051A5 E8DEE4FFFF <1> call get_physical_addr ; get physical address 18452 000051AA 0F82A8FEFFFF <1> jc tr_addr_nm_err 18453 <1> ; 18/10/2015 18454 000051B0 89C7 <1> mov edi, eax 18455 000051B2 29C0 <1> sub eax, eax ; 0 18456 <1> ; ECX = remain byte count in page (1-4096) 18457 000051B4 39CE <1> cmp esi, ecx 18458 000051B6 7302 <1> jnb short sysbreak_2 18459 000051B8 89F1 <1> mov ecx, esi 18460 <1> sysbreak_2: 18461 000051BA 29CE <1> sub esi, ecx 18462 000051BC 01CD <1> add ebp, ecx 18463 000051BE F3AA <1> rep stosb 18464 000051C0 09F6 <1> or esi, esi 18465 000051C2 75DF <1> jnz short sysbreak_1 18466 <1> ; 18467 <1> ; bit $1,r1 / is it an odd address 18468 <1> ; beq 2f / no, its even 18469 <1> ; clrb (r1)+ / yes, make it even 18470 <1> ; 2: / clear area between the break point and the stack 18471 <1> ; cmp r1,sp / is it higher or same than the stack 18472 <1> ; bhis 1f / yes, quit 18473 <1> ; clr (r1)+ / clear word 18474 <1> ; br 2b / go back 18475 <1> ;pop ebx 18476 <1> sysbreak_3: ; 1: 18477 <1> ;mov [u.break], ebx ; virtual address !!! 18478 <1> ; jsr r0,arg; u.break / put the "address" 18479 <1> ; / in u.break (set new break point) 18480 <1> ; br sysret4 / br sysret 18481 000051C4 E991EEFFFF <1> jmp sysret 18482 <1> 18483 <1> 18484 <1> maknod: 18485 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18486 <1> ; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1) 18487 <1> ; 18488 <1> ; 'maknod' creates an i-node and makes a directory entry 18489 <1> ; for this i-node in the current directory. 18490 <1> ; 18491 <1> ; INPUTS -> 18492 <1> ; r1 - contains mode 18493 <1> ; ii - current directory's i-number 18494 <1> ; 18495 <1> ; OUTPUTS -> 18496 <1> ; u.dirbuf - contains i-number of free i-node 18497 <1> ; i.flgs - flags in new i-node 18498 <1> ; i.uid - filled with u.uid 18499 <1> ; i.nlks - 1 is put in the number of links 18500 <1> ; i.ctim - creation time 18501 <1> ; i.ctim+2 - modification time 18502 <1> ; imod - set via call to setimod 18503 <1> ; 18504 <1> ; ((AX = R1)) input 18505 <1> ; 18506 <1> ; (Retro UNIX Prototype : 18507 <1> ; 30/10/2012 - 01/03/2013, UNIXCOPY.ASM) 18508 <1> ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP)) 18509 <1> 18510 <1> ; / r1 contains the mode 18511 000051C9 80CC80 <1> or ah, 80h ; 10000000b 18512 <1> ; bis $100000,r1 / allocate flag set 18513 000051CC 6650 <1> push ax 18514 <1> ; mov r1,-(sp) / put mode on stack 18515 <1> ; 31/07/2013 18516 000051CE 66A1[2A740000] <1> mov ax, [ii] ; move current i-number to AX/r1 18517 <1> ; mov ii,r1 / move current i-number to r1 18518 000051D4 B201 <1> mov dl, 1 ; owner flag mask 18519 000051D6 E8E6050000 <1> call access 18520 <1> ; jsr r0,access; 1 / get its i-node into core 18521 000051DB 6650 <1> push ax 18522 <1> ; mov r1,-(sp) / put i-number on stack 18523 000051DD 66B82800 <1> mov ax, 40 18524 <1> ; mov $40.,r1 / r1 = 40 18525 <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions) 18526 000051E1 6640 <1> inc ax 18527 <1> ; inc r1 / r1 = r1 + 1 18528 000051E3 E8AA060000 <1> call imap 18529 <1> ; jsr r0,imap / get byte address and bit position in 18530 <1> ; / inode map in r2 & m 18531 <1> ; DX (MQ) has a 1 in the calculated bit position 18532 <1> ; eBX (R2) has byte address of the byte with allocation bit 18533 <1> ; 22/06/2015 - NOTE for next Retro UNIX version: 18534 <1> ; Inode count must be checked here 18535 <1> ; (Original UNIX v1 did not check inode count here !?) 18536 000051E8 8413 <1> test [ebx], dl 18537 <1> ; bitb mq,(r2) / is the i-node active 18538 000051EA 75F5 <1> jnz short maknod1 18539 <1> ; bne 1b / yes, try the next one 18540 000051EC 0813 <1> or [ebx], dl 18541 <1> ; bisb mq,(r2) / no, make it active 18542 <1> ; / (put a 1 in the bit map) 18543 000051EE E8F3040000 <1> call iget 18544 <1> ; jsr r0,iget / get i-node into core 18545 000051F3 66F705[16710000]00- <1> test word [i.flgs], 8000h 18546 000051FB 80 <1> 18547 <1> ; tst i.flgs / is i-node already allocated 18548 000051FC 75E3 <1> jnz short maknod1 18549 <1> ; blt 1b / yes, look for another one 18550 000051FE 66A3[7A740000] <1> mov [u.dirbuf], ax 18551 <1> ; mov r1,u.dirbuf / no, put i-number in u.dirbuf 18552 00005204 6658 <1> pop ax 18553 <1> ; mov (sp)+,r1 / get current i-number back 18554 00005206 E8DB040000 <1> call iget 18555 <1> ; jsr r0,iget / get i-node in core 18556 0000520B E87DF7FFFF <1> call mkdir 18557 <1> ; jsr r0,mkdir / make a directory entry 18558 <1> ; / in current directory 18559 00005210 66A1[7A740000] <1> mov ax, [u.dirbuf] 18560 <1> ; mov u.dirbuf,r1 / r1 = new inode number 18561 00005216 E8CB040000 <1> call iget 18562 <1> ; jsr r0,iget / get it into core 18563 <1> ; jsr r0,copyz; inode; inode+32. / 0 it out 18564 0000521B B908000000 <1> mov ecx, 8 18565 00005220 31C0 <1> xor eax, eax ; 0 18566 00005222 BF[16710000] <1> mov edi, inode 18567 00005227 F3AB <1> rep stosd 18568 <1> ; 18569 00005229 668F05[16710000] <1> pop word [i.flgs] 18570 <1> ; mov (sp)+,i.flgs / fill flags 18571 00005230 8A0D[94740000] <1> mov cl, [u.uid] ; 02/08/2013 18572 00005236 880D[19710000] <1> mov [i.uid], cl 18573 <1> ; movb u.uid,i.uid / user id 18574 0000523C C605[18710000]01 <1> mov byte [i.nlks], 1 18575 <1> ; movb $1,i.nlks / 1 link 18576 <1> ;call epoch ; Retro UNIX 8086 v1 modification ! 18577 <1> ;mov eax, [s.time] 18578 <1> ;mov [i.ctim], eax 18579 <1> ; mov s.time,i.ctim / time created 18580 <1> ; mov s.time+2,i.ctim+2 / time modified 18581 <1> ; Retro UNIX 8086 v1 modification ! 18582 <1> ; i.ctime=0, i.ctime+2=0 and 18583 <1> ; 'setimod' will set ctime of file via 'epoch' 18584 00005243 E8B1050000 <1> call setimod 18585 <1> ; jsr r0,setimod / set modified flag 18586 00005248 C3 <1> retn 18587 <1> ; rts r0 / return 18588 <1> 18589 <1> sysseek: ; / moves read write pointer in an fsp entry 18590 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18591 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 18592 <1> ; 18593 <1> ; 'sysseek' changes the r/w pointer of (3rd word of in an 18594 <1> ; fsp entry) of an open file whose file descriptor is in u.r0. 18595 <1> ; The file descriptor refers to a file open for reading or 18596 <1> ; writing. The read (or write) pointer is set as follows: 18597 <1> ; * if 'ptrname' is 0, the pointer is set to offset. 18598 <1> ; * if 'ptrname' is 1, the pointer is set to its 18599 <1> ; current location plus offset. 18600 <1> ; * if 'ptrname' is 2, the pointer is set to the 18601 <1> ; size of file plus offset. 18602 <1> ; The error bit (e-bit) is set for an undefined descriptor. 18603 <1> ; 18604 <1> ; Calling sequence: 18605 <1> ; sysseek; offset; ptrname 18606 <1> ; Arguments: 18607 <1> ; offset - number of bytes desired to move 18608 <1> ; the r/w pointer 18609 <1> ; ptrname - a switch indicated above 18610 <1> ; 18611 <1> ; Inputs: r0 - file descriptor 18612 <1> ; Outputs: - 18613 <1> ; ............................................................... 18614 <1> ; 18615 <1> ; Retro UNIX 8086 v1 modification: 18616 <1> ; 'sysseek' system call has three arguments; so, 18617 <1> ; * 1st argument, file descriptor is in BX (BL) register 18618 <1> ; * 2nd argument, offset is in CX register 18619 <1> ; * 3rd argument, ptrname/switch is in DX (DL) register 18620 <1> ; 18621 <1> 18622 00005249 E823000000 <1> call seektell 18623 <1> ; AX = u.count 18624 <1> ; BX = *u.fofp 18625 <1> ; jsr r0,seektell / get proper value in u.count 18626 <1> ; add u.base,u.count / add u.base to it 18627 0000524E 0305[68740000] <1> add eax, [u.base] ; add offset (u.base) to base 18628 00005254 8903 <1> mov [ebx], eax 18629 <1> ; mov u.count,*u.fofp / put result into r/w pointer 18630 00005256 E9FFEDFFFF <1> jmp sysret 18631 <1> ; br sysret4 18632 <1> 18633 <1> systell: ; / get the r/w pointer 18634 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18635 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 18636 <1> ; 18637 <1> ; Retro UNIX 8086 v1 modification: 18638 <1> ; ! 'systell' does not work in original UNIX v1, 18639 <1> ; it returns with error ! 18640 <1> ; Inputs: r0 - file descriptor 18641 <1> ; Outputs: r0 - file r/w pointer 18642 <1> 18643 <1> ;xor ecx, ecx ; 0 18644 0000525B BA01000000 <1> mov edx, 1 ; 05/08/2013 18645 <1> ;call seektell 18646 00005260 E812000000 <1> call seektell0 ; 05/08/2013 18647 <1> ;mov ebx, [u.fofp] 18648 00005265 8B03 <1> mov eax, [ebx] 18649 00005267 A3[48740000] <1> mov [u.r0], eax 18650 0000526C E9E9EDFFFF <1> jmp sysret 18651 <1> 18652 <1> ; Original unix v1 'systell' system call: 18653 <1> ; jsr r0,seektell 18654 <1> ; br error4 18655 <1> 18656 <1> seektell: 18657 <1> ; 03/01/2016 18658 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18659 <1> ; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1) 18660 <1> ; 18661 <1> ; 'seektell' puts the arguments from sysseek and systell 18662 <1> ; call in u.base and u.count. It then gets the i-number of 18663 <1> ; the file from the file descriptor in u.r0 and by calling 18664 <1> ; getf. The i-node is brought into core and then u.count 18665 <1> ; is checked to see it is a 0, 1, or 2. 18666 <1> ; If it is 0 - u.count stays the same 18667 <1> ; 1 - u.count = offset (u.fofp) 18668 <1> ; 2 - u.count = i.size (size of file) 18669 <1> ; 18670 <1> ; !! Retro UNIX 8086 v1 modification: 18671 <1> ; Argument 1, file descriptor is in BX; 18672 <1> ; Argument 2, offset is in CX; 18673 <1> ; Argument 3, ptrname/switch is in DX register. 18674 <1> ; 18675 <1> ; mov ax, 3 ; Argument transfer method 3 (three arguments) 18676 <1> ; call arg 18677 <1> ; 18678 <1> ; ((Return -> ax = base for offset (position= base+offset)) 18679 <1> ; 18680 00005271 890D[68740000] <1> mov [u.base], ecx ; offset 18681 <1> ; jsr r0,arg; u.base / puts offset in u.base 18682 <1> seektell0: 18683 00005277 8915[6C740000] <1> mov [u.count], edx 18684 <1> ; jsr r0,arg; u.count / put ptr name in u.count 18685 <1> ; mov ax, bx 18686 <1> ; mov *u.r0,r1 / file descriptor in r1 18687 <1> ; / (index in u.fp list) 18688 <1> ; call getf 18689 <1> ; jsr r0,getf / u.fofp points to 3rd word in fsp entry 18690 <1> ; BX = file descriptor (file number) 18691 0000527D E83DFCFFFF <1> call getf1 18692 00005282 6609C0 <1> or ax, ax ; i-number of the file 18693 <1> ; mov r1,-(sp) / r1 has i-number of file, 18694 <1> ; / put it on the stack 18695 <1> ;jz error 18696 <1> ; beq error4 / if i-number is 0, not active so error 18697 00005285 750F <1> jnz short seektell1 18698 00005287 C705[9D740000]0A00- <1> mov dword [u.error], ERR_FILE_NOT_OPEN ; 'file not open !' 18699 0000528F 0000 <1> 18700 00005291 E9A4EDFFFF <1> jmp error 18701 <1> seektell1: 18702 <1> ;push eax 18703 00005296 80FC80 <1> cmp ah, 80h 18704 00005299 7203 <1> jb short seektell2 18705 <1> ; bgt .+4 / if its positive jump 18706 0000529B 66F7D8 <1> neg ax 18707 <1> ; neg r1 / if not make it positive 18708 <1> seektell2: 18709 0000529E E843040000 <1> call iget 18710 <1> ; jsr r0,iget / get its i-node into core 18711 000052A3 8B1D[58740000] <1> mov ebx, [u.fofp] ; 05/08/2013 18712 000052A9 803D[6C740000]01 <1> cmp byte [u.count], 1 18713 <1> ; cmp u.count,$1 / is ptr name =1 18714 000052B0 7705 <1> ja short seektell3 18715 <1> ; blt 2f / no its zero 18716 000052B2 740A <1> je short seektell_4 18717 <1> ; beq 1f / yes its 1 18718 000052B4 31C0 <1> xor eax, eax 18719 <1> ;jmp short seektell_5 18720 000052B6 C3 <1> retn 18721 <1> seektell3: 18722 <1> ; 03/01/2016 18723 <1> ;movzx eax, word [i.size] 18724 000052B7 66A1[1A710000] <1> mov ax, [i.size] 18725 <1> ; mov i.size,u.count / put number of bytes 18726 <1> ; / in file in u.count 18727 <1> ;jmp short seektell_5 18728 <1> ; br 2f 18729 000052BD C3 <1> retn 18730 <1> seektell_4: ; 1: / ptrname =1 18731 <1> ;mov ebx, [u.fofp] 18732 000052BE 8B03 <1> mov eax, [ebx] 18733 <1> ; mov *u.fofp,u.count / put offset in u.count 18734 <1> ;seektell_5: ; 2: / ptrname =0 18735 <1> ;mov [u.count], eax 18736 <1> ;pop eax 18737 <1> ; mov (sp)+,r1 / i-number on stack r1 18738 000052C0 C3 <1> retn 18739 <1> ; rts r0 18740 <1> 18741 <1> sysintr: ; / set interrupt handling 18742 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18743 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 18744 <1> ; 18745 <1> ; 'sysintr' sets the interrupt handling value. It puts 18746 <1> ; argument of its call in u.intr then branches into 'sysquit' 18747 <1> ; routine. u.tty is checked if to see if a control tty exists. 18748 <1> ; If one does the interrupt character in the tty buffer is 18749 <1> ; cleared and 'sysret'is called. If one does not exits 18750 <1> ; 'sysret' is just called. 18751 <1> ; 18752 <1> ; Calling sequence: 18753 <1> ; sysintr; arg 18754 <1> ; Argument: 18755 <1> ; arg - if 0, interrupts (ASCII DELETE) are ignored. 18756 <1> ; - if 1, intterupts cause their normal result 18757 <1> ; i.e force an exit. 18758 <1> ; - if arg is a location within the program, 18759 <1> ; control is passed to that location when 18760 <1> ; an interrupt occurs. 18761 <1> ; Inputs: - 18762 <1> ; Outputs: - 18763 <1> ; ............................................................... 18764 <1> ; 18765 <1> ; Retro UNIX 8086 v1 modification: 18766 <1> ; 'sysintr' system call sets u.intr to value of BX 18767 <1> ; then branches into sysquit. 18768 <1> ; 18769 000052C1 66891D[8C740000] <1> mov [u.intr], bx 18770 <1> ; jsr r0,arg; u.intr / put the argument in u.intr 18771 <1> ; br 1f / go into quit routine 18772 000052C8 E98DEDFFFF <1> jmp sysret 18773 <1> 18774 <1> sysquit: 18775 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18776 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 18777 <1> ; 18778 <1> ; 'sysquit' turns off the quit signal. it puts the argument of 18779 <1> ; the call in u.quit. u.tty is checked if to see if a control 18780 <1> ; tty exists. If one does the interrupt character in the tty 18781 <1> ; buffer is cleared and 'sysret'is called. If one does not exits 18782 <1> ; 'sysret' is just called. 18783 <1> ; 18784 <1> ; Calling sequence: 18785 <1> ; sysquit; arg 18786 <1> ; Argument: 18787 <1> ; arg - if 0, this call diables quit signals from the 18788 <1> ; typewriter (ASCII FS) 18789 <1> ; - if 1, quits are re-enabled and cause execution to 18790 <1> ; cease and a core image to be produced. 18791 <1> ; i.e force an exit. 18792 <1> ; - if arg is an addres in the program, 18793 <1> ; a quit causes control to sent to that 18794 <1> ; location. 18795 <1> ; Inputs: - 18796 <1> ; Outputs: - 18797 <1> ; ............................................................... 18798 <1> ; 18799 <1> ; Retro UNIX 8086 v1 modification: 18800 <1> ; 'sysquit' system call sets u.quit to value of BX 18801 <1> ; then branches into 'sysret'. 18802 <1> ; 18803 000052CD 66891D[8E740000] <1> mov [u.quit], bx 18804 000052D4 E981EDFFFF <1> jmp sysret 18805 <1> ; jsr r0,arg; u.quit / put argument in u.quit 18806 <1> ;1: 18807 <1> ; mov u.ttyp,r1 / move pointer to control tty buffer 18808 <1> ; / to r1 18809 <1> ; beq sysret4 / return to user 18810 <1> ; clrb 6(r1) / clear the interrupt character 18811 <1> ; / in the tty buffer 18812 <1> ; br sysret4 / return to user 18813 <1> 18814 <1> syssetuid: ; / set process id 18815 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18816 <1> ; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1) 18817 <1> ; 18818 <1> ; 'syssetuid' sets the user id (u.uid) of the current process 18819 <1> ; to the process id in (u.r0). Both the effective user and 18820 <1> ; u.uid and the real user u.ruid are set to this. 18821 <1> ; Only the super user can make this call. 18822 <1> ; 18823 <1> ; Calling sequence: 18824 <1> ; syssetuid 18825 <1> ; Arguments: - 18826 <1> ; 18827 <1> ; Inputs: (u.r0) - contains the process id. 18828 <1> ; Outputs: - 18829 <1> ; ............................................................... 18830 <1> ; 18831 <1> ; Retro UNIX 8086 v1 modification: 18832 <1> ; BL contains the (new) user ID of the current process 18833 <1> 18834 <1> ; movb *u.r0,r1 / move process id (number) to r1 18835 000052D9 3A1D[95740000] <1> cmp bl, [u.ruid] 18836 <1> ; cmpb r1,u.ruid / is it equal to the real user 18837 <1> ; / id number 18838 000052DF 741E <1> je short setuid1 18839 <1> ; beq 1f / yes 18840 000052E1 803D[94740000]00 <1> cmp byte [u.uid], 0 ; 02/08/2013 18841 <1> ; tstb u.uid / no, is current user the super user? 18842 <1> ;ja error 18843 <1> ; bne error4 / no, error 18844 000052E8 760F <1> jna short setuid0 18845 000052EA C705[9D740000]0B00- <1> mov dword [u.error], ERR_NOT_SUPERUSER ; 11 18846 000052F2 0000 <1> 18847 <1> ; 'permission denied !' error 18848 000052F4 E941EDFFFF <1> jmp error 18849 <1> setuid0: 18850 000052F9 881D[95740000] <1> mov [u.ruid], bl 18851 <1> setuid1: ; 1: 18852 000052FF 881D[94740000] <1> mov [u.uid], bl ; 02/08/2013 18853 <1> ; movb r1,u.uid / put process id in u.uid 18854 <1> ; movb r1,u.ruid / put process id in u.ruid 18855 00005305 E950EDFFFF <1> jmp sysret 18856 <1> ; br sysret4 / system return 18857 <1> 18858 <1> sysgetuid: ; < get user id > 18859 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18860 <1> ; 07/07/2013 (Retro UNIX 8086 v1) 18861 <1> ; 18862 <1> ; 'sysgetuid' returns the real user ID of the current process. 18863 <1> ; The real user ID identifies the person who is logged in, 18864 <1> ; in contradistinction to the effective user ID, which 18865 <1> ; determines his access permission at each moment. It is thus 18866 <1> ; useful to programs which operate using the 'set user ID' 18867 <1> ; mode, to find out who invoked them. 18868 <1> ; 18869 <1> ; Calling sequence: 18870 <1> ; syssetuid 18871 <1> ; Arguments: - 18872 <1> ; 18873 <1> ; Inputs: - 18874 <1> ; Outputs: (u.r0) - contains the real user's id. 18875 <1> ; ............................................................... 18876 <1> ; 18877 <1> ; Retro UNIX 8086 v1 modification: 18878 <1> ; AL contains the real user ID at return. 18879 <1> ; 18880 0000530A 0FB605[95740000] <1> movzx eax, byte [u.ruid] 18881 00005311 A3[48740000] <1> mov [u.r0], eax 18882 <1> ; movb u.ruid,*u.r0 / move the real user id to (u.r0) 18883 00005316 E93FEDFFFF <1> jmp sysret 18884 <1> ; br sysret4 / systerm return, sysret 18885 <1> 18886 <1> anyi: 18887 <1> ; 22/06/2015 (Retro UNIX 386 v1 - Beginning) 18888 <1> ; 25/04/2013 (Retro UNIX 8086 v1) 18889 <1> ; 18890 <1> ; 'anyi' is called if a file deleted while open. 18891 <1> ; "anyi" checks to see if someone else has opened this file. 18892 <1> ; 18893 <1> ; INPUTS -> 18894 <1> ; r1 - contains an i-number 18895 <1> ; fsp - start of table containing open files 18896 <1> ; 18897 <1> ; OUTPUTS -> 18898 <1> ; "deleted" flag set in fsp entry of another occurrence of 18899 <1> ; this file and r2 points 1st word of this fsp entry. 18900 <1> ; if file not found - bit in i-node map is cleared 18901 <1> ; (i-node is freed) 18902 <1> ; all blocks related to i-node are freed 18903 <1> ; all flags in i-node are cleared 18904 <1> ; ((AX = R1)) input 18905 <1> ; 18906 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 18907 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 18908 <1> ; 18909 <1> ; / r1 contains an i-number 18910 0000531B BB[16720000] <1> mov ebx, fsp 18911 <1> ; mov $fsp,r2 / move start of fsp table to r2 18912 <1> anyi_1: ; 1: 18913 00005320 663B03 <1> cmp ax, [ebx] 18914 <1> ; cmp r1,(r2) / do i-numbers match? 18915 00005323 7433 <1> je short anyi_3 18916 <1> ; beq 1f / yes, 1f 18917 00005325 66F7D8 <1> neg ax 18918 <1> ; neg r1 / no complement r1 18919 00005328 663B03 <1> cmp ax, [ebx] 18920 <1> ; cmp r1,(r2) / do they match now? 18921 0000532B 742B <1> je short anyi_3 18922 <1> ; beq 1f / yes, transfer 18923 <1> ; / i-numbers do not match 18924 0000532D 83C30A <1> add ebx, 10 ; fsp table size is 10 bytes 18925 <1> ; in Retro UNIX 386 v1 (22/06/2015) 18926 <1> ; add $8,r2 / no, bump to next entry in fsp table 18927 00005330 81FB[0A740000] <1> cmp ebx, fsp + (nfiles*10) ; 22/06/2015 18928 <1> ; cmp r2,$fsp+[nfiles*8] 18929 <1> ; / are we at last entry in the table 18930 00005336 72E8 <1> jb short anyi_1 18931 <1> ; blt 1b / no, check next entries i-number 18932 <1> ;cmp ax, 32768 18933 00005338 80FC80 <1> cmp ah, 80h ; negative number check 18934 <1> ; tst r1 / yes, no match 18935 <1> ; bge .+4 18936 0000533B 7203 <1> jb short anyi_2 18937 0000533D 66F7D8 <1> neg ax 18938 <1> ; neg r1 / make i-number positive 18939 <1> anyi_2: 18940 00005340 E84D050000 <1> call imap 18941 <1> ; jsr r0,imap / get address of allocation bit 18942 <1> ; / in the i-map in r2 18943 <1> ;; DL/DX (MQ) has a 1 in the calculated bit position 18944 <1> ;; eBX (R2) has address of the byte with allocation bit 18945 <1> ; not dx 18946 00005345 F6D2 <1> not dl ;; 0 at calculated bit position, other bits are 1 18947 <1> ;and [ebx], dx 18948 00005347 2013 <1> and [ebx], dl 18949 <1> ; bicb mq,(r2) / clear bit for i-node in the imap 18950 00005349 E8CD040000 <1> call itrunc 18951 <1> ; jsr r0,itrunc / free all blocks related to i-node 18952 0000534E 66C705[16710000]00- <1> mov word [i.flgs], 0 18953 00005356 00 <1> 18954 <1> ; clr i.flgs / clear all flags in the i-node 18955 00005357 C3 <1> retn 18956 <1> ;rts r0 / return 18957 <1> anyi_3: ; 1: / i-numbers match 18958 00005358 FE4309 <1> inc byte [ebx+9] ; 22/06/2015 18959 <1> ;incb 7(r2) / increment upper byte of the 4th word 18960 <1> ; / in that fsp entry (deleted flag of fsp entry) 18961 0000535B C3 <1> retn 18962 <1> ; rts r0 18963 %include 'u3.s' ; 10/05/2015 18964 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC 18965 <1> ; Last Modification: 15/09/2015 18966 <1> ; ---------------------------------------------------------------------------- 18967 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 18968 <1> ; (v0.1 - Beginning: 11/07/2012) 18969 <1> ; 18970 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 18971 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 18972 <1> ; 18973 <1> ; 18974 <1> ; 18975 <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s 18976 <1> ; 18977 <1> ; **************************************************************************** 18978 <1> 18979 <1> tswitch: ; Retro UNIX 386 v1 18980 <1> tswap: 18981 <1> ; 01/09/2015 18982 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 18983 <1> ; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1) 18984 <1> ; time out swap, called when a user times out. 18985 <1> ; the user is put on the low priority queue. 18986 <1> ; This is done by making a link from the last user 18987 <1> ; on the low priority queue to him via a call to 'putlu'. 18988 <1> ; then he is swapped out. 18989 <1> ; 18990 <1> ; Retro UNIX 386 v1 modification -> 18991 <1> ; swap (software task switch) is performed by changing 18992 <1> ; user's page directory (u.pgdir) instead of segment change 18993 <1> ; as in Retro UNIX 8086 v1. 18994 <1> ; 18995 <1> ; RETRO UNIX 8086 v1 modification -> 18996 <1> ; 'swap to disk' is replaced with 'change running segment' 18997 <1> ; according to 8086 cpu (x86 real mode) architecture. 18998 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 18999 <1> ; compatibles was using 1MB segmented memory 19000 <1> ; in 8086/8088 times. 19001 <1> ; 19002 <1> ; INPUTS -> 19003 <1> ; u.uno - users process number 19004 <1> ; runq+4 - lowest priority queue 19005 <1> ; OUTPUTS -> 19006 <1> ; r0 - users process number 19007 <1> ; r2 - lowest priority queue address 19008 <1> ; 19009 <1> ; ((AX = R0, BX = R2)) output 19010 <1> ; ((Modified registers: EDX, EBX, ECX, ESI, EDI)) 19011 <1> ; 19012 0000535C A0[97740000] <1> mov al, [u.uno] 19013 <1> ; movb u.uno,r1 / move users process number to r1 19014 <1> ; mov $runq+4,r2 19015 <1> ; / move lowest priority queue address to r2 19016 00005361 E8CE000000 <1> call putlu 19017 <1> ; jsr r0,putlu / create link from last user on Q to 19018 <1> ; / u.uno's user 19019 <1> 19020 <1> switch: ; Retro UNIX 386 v1 19021 <1> swap: 19022 <1> ; 02/09/2015 19023 <1> ; 01/09/2015 19024 <1> ; 31/08/2015 19025 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 19026 <1> ; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1) 19027 <1> ; 'swap' is routine that controls the swapping of processes 19028 <1> ; in and out of core. 19029 <1> ; 19030 <1> ; Retro UNIX 386 v1 modification -> 19031 <1> ; swap (software task switch) is performed by changing 19032 <1> ; user's page directory (u.pgdir) instead of segment change 19033 <1> ; as in Retro UNIX 8086 v1. 19034 <1> ; 19035 <1> ; RETRO UNIX 8086 v1 modification -> 19036 <1> ; 'swap to disk' is replaced with 'change running segment' 19037 <1> ; according to 8086 cpu (x86 real mode) architecture. 19038 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 19039 <1> ; compatibles was using 1MB segmented memory 19040 <1> ; in 8086/8088 times. 19041 <1> ; 19042 <1> ; INPUTS -> 19043 <1> ; runq table - contains processes to run. 19044 <1> ; p.link - contains next process in line to be run. 19045 <1> ; u.uno - process number of process in core 19046 <1> ; s.stack - swap stack used as an internal stack for swapping. 19047 <1> ; OUTPUTS -> 19048 <1> ; (original unix v1 -> present process to its disk block) 19049 <1> ; (original unix v1 -> new process into core -> 19050 <1> ; Retro Unix 8086 v1 -> segment registers changed 19051 <1> ; for new process) 19052 <1> ; u.quant = 3 (Time quantum for a process) 19053 <1> ; ((INT 1Ch count down speed -> 18.2 times per second) 19054 <1> ; RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second) 19055 <1> ; for now, it will swap the process if there is not 19056 <1> ; a keyboard event (keystroke) (Int 15h, function 4Fh) 19057 <1> ; or will count down from 3 to 0 even if there is a 19058 <1> ; keyboard event locking due to repetitive key strokes. 19059 <1> ; u.quant will be reset to 3 for RETRO UNIX 8086 v1. 19060 <1> ; 19061 <1> ; u.pri -points to highest priority run Q. 19062 <1> ; r2 - points to the run queue. 19063 <1> ; r1 - contains new process number 19064 <1> ; r0 - points to place in routine or process that called 19065 <1> ; swap all user parameters 19066 <1> ; 19067 <1> ; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI)) 19068 <1> ; 19069 <1> swap_0: 19070 <1> ;mov $300,*$ps / processor priority = 6 19071 00005366 BE[3A740000] <1> mov esi, runq 19072 <1> ; mov $runq,r2 / r2 points to runq table 19073 <1> swap_1: ; 1: / search runq table for highest priority process 19074 0000536B 668B06 <1> mov ax, [esi] 19075 0000536E 6621C0 <1> and ax, ax 19076 <1> ; tst (r2)+ / are there any processes to run 19077 <1> ; / in this Q entry 19078 00005371 7507 <1> jnz short swap_2 19079 <1> ; bne 1f / yes, process 1f 19080 <1> ; cmp r2,$runq+6 / if zero compare address 19081 <1> ; / to end of table 19082 <1> ; bne 1b / if not at end, go back 19083 00005373 E8E1000000 <1> call idle 19084 <1> ; jsr r0,idle; s.idlet+2 / wait for interrupt; 19085 <1> ; / all queues are empty 19086 00005378 EBF1 <1> jmp short swap_1 19087 <1> ; br swap 19088 <1> swap_2: ; 1: 19089 0000537A 0FB6D8 <1> movzx ebx, al ; 02/09/2015 19090 <1> ; tst -(r2) / restore pointer to right Q entry 19091 <1> ; mov r2,u.pri / set present user to this run queue 19092 <1> ; movb (r2)+,r1 / move 1st process in queue to r1 19093 0000537D 38E0 <1> cmp al, ah 19094 <1> ; cmpb r1,(r2)+ / is there only 1 process 19095 <1> ; / in this Q to be run 19096 0000537F 740A <1> je short swap_3 19097 <1> ; beq 1f / yes 19098 <1> ; tst -(r2) / no, pt r2 back to this Q entry 19099 <1> ;movzx ebx, al 19100 00005381 8AA3[B5710000] <1> mov ah, [ebx+p.link-1] 19101 00005387 8826 <1> mov [esi], ah 19102 <1> ; movb p.link-1(r1),(r2) / move next process 19103 <1> ; / in line into run queue 19104 00005389 EB06 <1> jmp short swap_4 19105 <1> ; br 2f 19106 <1> swap_3: ; 1: 19107 0000538B 6631D2 <1> xor dx, dx 19108 0000538E 668916 <1> mov [esi], dx 19109 <1> ; clr -(r2) / zero the entry; no processes on the Q 19110 <1> swap_4: ; / write out core to appropriate disk area and read 19111 <1> ; / in new process if required 19112 <1> ; clr *$ps / clear processor status 19113 00005391 8A25[97740000] <1> mov ah, [u.uno] 19114 00005397 38C4 <1> cmp ah, al 19115 <1> ; cmpb r1,u.uno / is this process the same as 19116 <1> ; / the process in core? 19117 00005399 743B <1> je short swap_8 19118 <1> ; beq 2f / yes, don't have to swap 19119 <1> ; mov r0,-(sp) / no, write out core; save r0 19120 <1> ; / (address in routine that called swap) 19121 <1> ; mov r1,-(sp) / put r1 (new process #) on the stack 19122 <1> ; 01/09/2015 19123 <1> ;mov [u.usp], esp 19124 <1> ; mov sp,u.usp / save stack pointer 19125 <1> ; mov $sstack,sp / move swap stack pointer 19126 <1> ; / to the stack pointer 19127 0000539B 08E4 <1> or ah, ah 19128 <1> ; tstb u.uno / is the process # = 0 19129 0000539D 740D <1> jz short swap_6 ; 'sysexit' 19130 <1> ; beq 1f / yes, kill process by overwriting 19131 <1> ; 02/09/2015 19132 0000539F 8925[44740000] <1> mov [u.usp], esp ; return address for 'syswait' & 'sleep' 19133 <1> ; 19134 000053A5 E834000000 <1> call wswap 19135 <1> ;jsr r0,wswap / write out core to disk 19136 <1> ; 31/08/2015 19137 <1> ;movzx ebx, al ; New (running) process number 19138 000053AA EB1C <1> jmp short swap_7 19139 <1> swap_6: 19140 <1> ; 31/08/2015 19141 <1> ; Deallocate memory pages belong to the process 19142 <1> ; which is being terminated 19143 <1> ; 14/05/2015 ('sysexit') 19144 <1> ; Deallocate memory pages of the process 19145 <1> ; (Retro UNIX 386 v1 modification !) 19146 <1> ; 19147 <1> ; movzx ebx, al 19148 000053AC 53 <1> push ebx 19149 000053AD A1[A1740000] <1> mov eax, [u.pgdir] ; page directory of the process 19150 000053B2 8B1D[A5740000] <1> mov ebx, [u.ppgdir] ; page directory of the parent process 19151 000053B8 E871DDFFFF <1> call deallocate_page_dir 19152 000053BD A1[98740000] <1> mov eax, [u.upage] ; 'user' structure page of the process 19153 000053C2 E806DEFFFF <1> call deallocate_page 19154 000053C7 5B <1> pop ebx 19155 <1> swap_7: ;1: 19156 <1> ; 02/09/2015 19157 <1> ; 31/08/2015 19158 <1> ; 14/05/2015 19159 000053C8 C0E302 <1> shl bl, 2 ; * 4 19160 000053CB 8B83[D2710000] <1> mov eax, [ebx+p.upage-4] ; the 'u' page of the new process 19161 <1> ;cli 19162 000053D1 E831000000 <1> call rswap 19163 <1> ; mov (sp)+,r1 / restore r1 to new process number 19164 <1> ; jsr r0,rswap / read new process into core 19165 <1> ; jsr r0,unpack / unpack the users stack from next 19166 <1> ; / to his program to its normal 19167 <1> ; 01/09/2015 19168 <1> ;mov esp, [u.usp] 19169 <1> ; mov u.usp,sp / location; restore stack pointer to 19170 <1> ; / new process stack 19171 <1> ; mov (sp)+,r0 / put address of where the process 19172 <1> ; / that just got swapped in, left off., 19173 <1> ; / i.e., transfer control to new process 19174 <1> ;sti 19175 <1> swap_8: ;2: 19176 <1> ; RETRO UNIX 8086 v1 modification ! 19177 000053D6 C605[8A740000]04 <1> mov byte [u.quant], time_count 19178 <1> ; movb $30.,uquant / initialize process time quantum 19179 000053DD C3 <1> retn 19180 <1> ; rts r0 / return 19181 <1> 19182 <1> wswap: ; < swap out, swap to disk > 19183 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 19184 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 19185 <1> ; 'wswap' writes out the process that is in core onto its 19186 <1> ; appropriate disk area. 19187 <1> ; 19188 <1> ; Retro UNIX 386 v1 modification -> 19189 <1> ; User (u) structure content and the user's register content 19190 <1> ; will be copied to the process's/user's UPAGE (a page for 19191 <1> ; saving 'u' structure and user registers for task switching). 19192 <1> ; u.usp - points to kernel stack address which contains 19193 <1> ; user's registers while entering system call. 19194 <1> ; u.sp - points to kernel stack address 19195 <1> ; to return from system call -for IRET-. 19196 <1> ; [u.usp]+32+16 = [u.sp] 19197 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 19198 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 19199 <1> ; 19200 <1> ; Retro UNIX 8086 v1 modification -> 19201 <1> ; 'swap to disk' is replaced with 'change running segment' 19202 <1> ; according to 8086 cpu (x86 real mode) architecture. 19203 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 19204 <1> ; compatibles was using 1MB segmented memory 19205 <1> ; in 8086/8088 times. 19206 <1> ; 19207 <1> ; INPUTS -> 19208 <1> ; u.break - points to end of program 19209 <1> ; u.usp - stack pointer at the moment of swap 19210 <1> ; core - beginning of process program 19211 <1> ; ecore - end of core 19212 <1> ; user - start of user parameter area 19213 <1> ; u.uno - user process number 19214 <1> ; p.dska - holds block number of process 19215 <1> ; OUTPUTS -> 19216 <1> ; swp I/O queue 19217 <1> ; p.break - negative word count of process 19218 <1> ; r1 - process disk address 19219 <1> ; r2 - negative word count 19220 <1> ; 19221 <1> ; RETRO UNIX 8086 v1 input/output: 19222 <1> ; 19223 <1> ; INPUTS -> 19224 <1> ; u.uno - process number (to be swapped out) 19225 <1> ; OUTPUTS -> 19226 <1> ; none 19227 <1> ; 19228 <1> ; ((Modified registers: ECX, ESI, EDI)) 19229 <1> ; 19230 000053DE 8B3D[98740000] <1> mov edi, [u.upage] ; process's user (u) structure page addr 19231 000053E4 B91E000000 <1> mov ecx, (U_SIZE + 3) / 4 19232 000053E9 BE[40740000] <1> mov esi, user ; active user (u) structure 19233 000053EE F3A5 <1> rep movsd 19234 <1> ; 19235 000053F0 8B35[44740000] <1> mov esi, [u.usp] ; esp (system stack pointer, 19236 <1> ; points to user registers) 19237 000053F6 8B0D[40740000] <1> mov ecx, [u.sp] ; return address from the system call 19238 <1> ; (for IRET) 19239 <1> ; [u.sp] -> EIP (user) 19240 <1> ; [u.sp+4]-> CS (user) 19241 <1> ; [u.sp+8] -> EFLAGS (user) 19242 <1> ; [u.sp+12] -> ESP (user) 19243 <1> ; [u.sp+16] -> SS (user) 19244 000053FC 29F1 <1> sub ecx, esi ; required space for user registers 19245 000053FE 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 19246 <1> ; (for IRET) 19247 00005401 C1E902 <1> shr ecx, 2 19248 00005404 F3A5 <1> rep movsd 19249 00005406 C3 <1> retn 19250 <1> 19251 <1> ; Original UNIX v1 'wswap' routine: 19252 <1> ; wswap: 19253 <1> ; mov *$30,u.emt / determines handling of emts 19254 <1> ; mov *$10,u.ilgins / determines handling of 19255 <1> ; / illegal instructions 19256 <1> ; mov u.break,r2 / put process program break address in r2 19257 <1> ; inc r2 / add 1 to it 19258 <1> ; bic $1,r2 / make it even 19259 <1> ; mov r2,u.break / set break to an even location 19260 <1> ; mov u.usp,r3 / put users stack pointer 19261 <1> ; / at moment of swap in r3 19262 <1> ; cmp r2,$core / is u.break less than $core 19263 <1> ; blos 2f / yes 19264 <1> ; cmp r2,r3 / no, is (u.break) greater than stack ptr. 19265 <1> ; bhis 2f / yes 19266 <1> ; 1: 19267 <1> ; mov (r3)+,(r2)+ / no, pack stack next to users program 19268 <1> ; cmp r3,$ecore / has stack reached end of core 19269 <1> ; bne 1b / no, keep packing 19270 <1> ; br 1f / yes 19271 <1> ; 2: 19272 <1> ; mov $ecore,r2 / put end of core in r2 19273 <1> ; 1: 19274 <1> ; sub $user,r2 / get number of bytes to write out 19275 <1> ; / (user up to end of stack gets written out) 19276 <1> ; neg r2 / make it negative 19277 <1> ; asr r2 / change bytes to words (divide by 2) 19278 <1> ; mov r2,swp+4 / word count 19279 <1> ; movb u.uno,r1 / move user process number to r1 19280 <1> ; asl r1 / x2 for index 19281 <1> ; mov r2,p.break-2(r1) / put negative of word count 19282 <1> ; / into the p.break table 19283 <1> ; mov p.dska-2(r1),r1 / move disk address of swap area 19284 <1> ; / for process to r1 19285 <1> ; mov r1,swp+2 / put processes dska address in swp+2 19286 <1> ; / (block number) 19287 <1> ; bis $1000,swp / set it up to write (set bit 9) 19288 <1> ; jsr r0,ppoke / write process out on swap area of disk 19289 <1> ; 1: 19290 <1> ; tstb swp+1 / is lt done writing? 19291 <1> ; bne 1b / no, wait 19292 <1> ; rts r0 / yes, return to swap 19293 <1> 19294 <1> rswap: ; < swap in, swap from disk > 19295 <1> ; 15/09/2015 19296 <1> ; 28/08/2015 19297 <1> ; 14/05/2015 19298 <1> ; 09/05/2015 (Retro UNIX 386 v1 - Beginning) 19299 <1> ; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1) 19300 <1> ; 'rswap' reads a process whose number is in r1, 19301 <1> ; from disk into core. 19302 <1> ; 19303 <1> ; Retro UNIX 386 v1 modification -> 19304 <1> ; User (u) structure content and the user's register content 19305 <1> ; will be restored from process's/user's UPAGE (a page for 19306 <1> ; saving 'u' structure and user registers for task switching). 19307 <1> ; u.usp - points to kernel stack address which contains 19308 <1> ; user's registers while entering system call. 19309 <1> ; u.sp - points to kernel stack address 19310 <1> ; to return from system call -for IRET-. 19311 <1> ; [u.usp]+32+16 = [u.sp] 19312 <1> ; [u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 19313 <1> ; edx, ecx, eax, gs, fs, es, ds, -> [u.sp]. 19314 <1> ; 19315 <1> ; RETRO UNIX 8086 v1 modification -> 19316 <1> ; 'swap to disk' is replaced with 'change running segment' 19317 <1> ; according to 8086 cpu (x86 real mode) architecture. 19318 <1> ; pdp-11 was using 64KB uniform memory while IBM PC 19319 <1> ; compatibles was using 1MB segmented memory 19320 <1> ; in 8086/8088 times. 19321 <1> ; 19322 <1> ; INPUTS -> 19323 <1> ; r1 - process number of process to be read in 19324 <1> ; p.break - negative of word count of process 19325 <1> ; p.dska - disk address of the process 19326 <1> ; u.emt - determines handling of emt's 19327 <1> ; u.ilgins - determines handling of illegal instructions 19328 <1> ; OUTPUTS -> 19329 <1> ; 8 = (u.ilgins) 19330 <1> ; 24 = (u.emt) 19331 <1> ; swp - bit 10 is set to indicate read 19332 <1> ; (bit 15=0 when reading is done) 19333 <1> ; swp+2 - disk block address 19334 <1> ; swp+4 - negative word count 19335 <1> ; ((swp+6 - address of user structure)) 19336 <1> ; 19337 <1> ; RETRO UNIX 8086 v1 input/output: 19338 <1> ; 19339 <1> ; INPUTS -> 19340 <1> ; AL - new process number (to be swapped in) 19341 <1> ; OUTPUTS -> 19342 <1> ; none 19343 <1> ; 19344 <1> ; ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 19345 <1> ; 19346 <1> ; Retro UNIX 386 v1 - modification ! 14/05/2015 19347 00005407 89C6 <1> mov esi, eax ; process's user (u) structure page addr 19348 00005409 B91E000000 <1> mov ecx, (U_SIZE + 3) / 4 19349 0000540E BF[40740000] <1> mov edi, user ; active user (u) structure 19350 00005413 F3A5 <1> rep movsd 19351 00005415 58 <1> pop eax ; 15/09/2015, 'rswap' return address 19352 00005416 8B3D[44740000] <1> mov edi, [u.usp] ; esp (system stack pointer, 19353 <1> ; points to user registers) 19354 0000541C 8B0D[40740000] <1> mov ecx, [u.sp] ; return address from the system call 19355 <1> ; (for IRET) 19356 <1> ; [u.sp] -> EIP (user) 19357 <1> ; [u.sp+4]-> CS (user) 19358 <1> ; [u.sp+8] -> EFLAGS (user) 19359 <1> ; [u.sp+12] -> ESP (user) 19360 <1> ; [u.sp+16] -> SS (user) 19361 <1> ; 28/08/2015 19362 00005422 29F9 <1> sub ecx, edi ; required space for user registers 19363 00005424 83C114 <1> add ecx, 20 ; +5 dwords to return from system call 19364 <1> ; (for IRET) 19365 00005427 C1E902 <1> shr ecx, 2 19366 0000542A F3A5 <1> rep movsd 19367 0000542C 8B25[44740000] <1> mov esp, [u.usp] ; 15/09/2015 19368 00005432 50 <1> push eax ; 15/09/2015 'rswap' return address 19369 00005433 C3 <1> retn 19370 <1> 19371 <1> ; Original UNIX v1 'rswap' and 'unpack' routines: 19372 <1> ;rswap: 19373 <1> ; asl r1 / process number x2 for index 19374 <1> ; mov p.break-2(r1), swp+4 / word count 19375 <1> ; mov p.dska-2(r1),swp+2 / disk address 19376 <1> ; bis $2000,swp / read 19377 <1> ; jsr r0,ppoke / read it in 19378 <1> ; 1: 19379 <1> ; tstb swp+1 / done 19380 <1> ; bne 1b / no, wait for bit 15 to clear (inhibit bit) 19381 <1> ; mov u.emt,*$30 / yes move these 19382 <1> ; mov u.ilgins,*$10 / back 19383 <1> ; rts r0 / return 19384 <1> 19385 <1> ;unpack: ; / move stack back to its normal place 19386 <1> ; mov u.break,r2 / r2 points to end of user program 19387 <1> ; cmp r2,$core / at beginning of user program yet? 19388 <1> ; blos 2f / yes, return 19389 <1> ; cmp r2,u.usp / is break_above the stack pointer 19390 <1> ; / before swapping 19391 <1> ; bhis 2f / yes, return 19392 <1> ; mov $ecore,r3 / r3 points to end of core 19393 <1> ; add r3,r2 19394 <1> ; sub u.usp,r2 / end of users stack is in r2 19395 <1> ; 1: 19396 <1> ; mov -(r2),-(r3) / move stack back to its normal place 19397 <1> ; cmp r2,u.break / in core 19398 <1> ; bne 1b 19399 <1> ; 2: 19400 <1> ; rts r0 19401 <1> 19402 <1> putlu: 19403 <1> ; 12/09/2015 19404 <1> ; 02/09/2015 19405 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 19406 <1> ; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1) 19407 <1> ; 'putlu' is called with a process number in r1 and a pointer 19408 <1> ; to lowest priority Q (runq+4) in r2. A link is created from 19409 <1> ; the last process on the queue to process in r1 by putting 19410 <1> ; the process number in r1 into the last process's link. 19411 <1> ; 19412 <1> ; INPUTS -> 19413 <1> ; r1 - user process number 19414 <1> ; r2 - points to lowest priority queue 19415 <1> ; p.dska - disk address of the process 19416 <1> ; u.emt - determines handling of emt's 19417 <1> ; u.ilgins - determines handling of illegal instructions 19418 <1> ; OUTPUTS -> 19419 <1> ; r3 - process number of last process on the queue upon 19420 <1> ; entering putlu 19421 <1> ; p.link-1 + r3 - process number in r1 19422 <1> ; r2 - points to lowest priority queue 19423 <1> ; 19424 <1> ; ((Modified registers: EDX, EBX)) 19425 <1> ; 19426 <1> ; / r1 = user process no.; r2 points to lowest priority queue 19427 <1> 19428 <1> ; eBX = r2 19429 <1> ; eAX = r1 (AL=r1b) 19430 <1> 19431 00005434 BB[3A740000] <1> mov ebx, runq 19432 00005439 0FB613 <1> movzx edx, byte [ebx] 19433 0000543C 43 <1> inc ebx 19434 0000543D 20D2 <1> and dl, dl 19435 <1> ; tstb (r2)+ / is queue empty? 19436 0000543F 740A <1> jz short putlu_1 19437 <1> ; beq 1f / yes, branch 19438 00005441 8A13 <1> mov dl, [ebx] ; 12/09/2015 19439 <1> ; movb (r2),r3 / no, save the "last user" process number 19440 <1> ; / in r3 19441 00005443 8882[B5710000] <1> mov [edx+p.link-1], al 19442 <1> ; movb r1,p.link-1(r3) / put pointer to user on 19443 <1> ; / "last users" link 19444 00005449 EB03 <1> jmp short putlu_2 19445 <1> ; br 2f / 19446 <1> putlu_1: ; 1: 19447 0000544B 8843FF <1> mov [ebx-1], al 19448 <1> ; movb r1,-1(r2) / user is only user; 19449 <1> ; / put process no. at beginning and at end 19450 <1> putlu_2: ; 2: 19451 0000544E 8803 <1> mov [ebx], al 19452 <1> ; movb r1,(r2) / user process in r1 is now the last entry 19453 <1> ; / on the queue 19454 00005450 88C2 <1> mov dl, al 19455 00005452 88B2[B5710000] <1> mov [edx+p.link-1], dh ; 0 19456 <1> ; dec r2 / restore r2 19457 00005458 C3 <1> retn 19458 <1> ; rts r0 19459 <1> 19460 <1> ;copyz: 19461 <1> ; mov r1,-(sp) / put r1 on stack 19462 <1> ; mov r2,-(sp) / put r2 on stack 19463 <1> ; mov (r0)+,r1 19464 <1> ; mov (r0)+,r2 19465 <1> ;1: 19466 <1> ; clr (r1)+ / clear all locations between r1 and r2 19467 <1> ; cmp r1,r2 19468 <1> ; blo 1b 19469 <1> ; mov (sp)+,r2 / restore r2 19470 <1> ; mov (sp)+,r1 / restore r1 19471 <1> ; rts r0 19472 <1> 19473 <1> idle: 19474 <1> ; 01/09/2015 19475 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 19476 <1> ; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1) 19477 <1> ; (idle & wait loop) 19478 <1> ; Retro Unix 8086 v1 modification on original UNIX v1 19479 <1> ; idle procedure! 19480 <1> ; 19481 <1> ; 01/09/2015 19482 00005459 FB <1> sti 19483 <1> ; 29/07/2013 19484 0000545A F4 <1> hlt 19485 0000545B 90 <1> nop ; 10/10/2013 19486 0000545C 90 <1> nop 19487 0000545D 90 <1> nop 19488 <1> ; 23/10/2013 19489 0000545E 90 <1> nop 19490 0000545F 90 <1> nop 19491 00005460 90 <1> nop 19492 00005461 90 <1> nop 19493 00005462 C3 <1> retn 19494 <1> 19495 <1> ;mov *$ps,-(sp) / save ps on stack 19496 <1> ;clr *$ps / clear ps 19497 <1> ;mov clockp,-(sp) / save clockp on stack 19498 <1> ;mov (r0)+,clockp / arg to idle in clockp 19499 <1> ;1 / wait for interrupt 19500 <1> ;mov (sp)+,clockp / restore clockp, ps 19501 <1> ;mov (sp)+,*$ps 19502 <1> ;rts r0 19503 <1> 19504 <1> clear: 19505 <1> ; 10/05/2015 (Retro UNIX 386 v1 - Beginning) 19506 <1> ; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 19507 <1> ; 'clear' zero's out of a block (whose block number is in r1) 19508 <1> ; on the current device (cdev) 19509 <1> ; 19510 <1> ; INPUTS -> 19511 <1> ; r1 - block number of block to be zeroed 19512 <1> ; cdev - current device number 19513 <1> ; OUTPUTS -> 19514 <1> ; a zeroed I/O buffer onto the current device 19515 <1> ; r1 - points to last entry in the I/O buffer 19516 <1> ; 19517 <1> ; ((AX = R1)) input/output 19518 <1> ; (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM) 19519 <1> ; ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP)) 19520 <1> 19521 00005463 E8AB0D0000 <1> call wslot 19522 <1> ; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first 19523 <1> ; / word of I/O queue r5 points to first data word in buffer 19524 00005468 89DF <1> mov edi, ebx ; r5 19525 0000546A 89C2 <1> mov edx, eax 19526 0000546C B980000000 <1> mov ecx, 128 19527 <1> ; mov $256.,r3 19528 00005471 31C0 <1> xor eax, eax 19529 00005473 F3AB <1> rep stosd 19530 00005475 89D0 <1> mov eax, edx 19531 <1> ; 1: 19532 <1> ; clr (r5)+ / zero data word in buffer 19533 <1> ; dec r3 19534 <1> ; bgt 1b / branch until all data words in buffer are zero 19535 00005477 E8B30D0000 <1> call dskwr 19536 <1> ; jsr r0,dskwr / write zeroed buffer area out onto physical 19537 <1> ; / block specified in r1 19538 <1> ; eAX (r1) = block number 19539 0000547C C3 <1> retn 19540 <1> ; rts r0 19541 %include 'u4.s' ; 15/04/2015 19542 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC 19543 <1> ; Last Modification: 14/10/2015 19544 <1> ; ---------------------------------------------------------------------------- 19545 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 19546 <1> ; (v0.1 - Beginning: 11/07/2012) 19547 <1> ; 19548 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 19549 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 19550 <1> ; 19551 <1> ; 19552 <1> ; 19553 <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s 19554 <1> ; 19555 <1> ; **************************************************************************** 19556 <1> 19557 <1> ;setisp: 19558 <1> ;mov r1,-(sp) 19559 <1> ;mov r2,-(sp) 19560 <1> ;mov r3,-(sp) 19561 <1> ;mov clockp,-(sp) 19562 <1> ;mov $s.syst+2,clockp 19563 <1> ;jmp (r0) 19564 <1> 19565 <1> clock: ; / interrupt from 60 cycle clock 19566 <1> 19567 <1> ; 14/10/2015 19568 <1> ; 14/05/2015 (Retro UNIX 386 v1 - Beginning) 19569 <1> ; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1) 19570 <1> 19571 <1> ;mov r0,-(sp) / save r0 19572 <1> ;tst *$lks / restart clock? 19573 <1> ;mov $s.time+2,r0 / increment the time of day 19574 <1> ;inc (r0) 19575 <1> ;bne 1f 19576 <1> ;inc -(r0) 19577 <1> ;1: 19578 <1> ;mov clockp,r0 / increment appropriate time category 19579 <1> ;inc (r0) 19580 <1> ;bne 1f 19581 <1> ;inc -(r0) 19582 <1> ;1: 19583 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 19584 <1> 19585 0000547D 803D[8A740000]00 <1> cmp byte [u.quant], 0 19586 00005484 772C <1> ja short clk_1 19587 <1> ; 19588 00005486 803D[3F740000]FF <1> cmp byte [sysflg], 0FFh ; user or system space ? 19589 0000548D 7529 <1> jne short clk_2 ; system space (sysflg <> 0FFh) 19590 0000548F 803D[97740000]01 <1> cmp byte [u.uno], 1 ; /etc/init ? 19591 00005496 761A <1> jna short clk_1 ; yes, do not swap out 19592 00005498 66833D[8C740000]00 <1> cmp word [u.intr], 0 19593 000054A0 7616 <1> jna short clk_2 19594 <1> clk_0: 19595 <1> ; 14/10/2015 19596 000054A2 FE05[3F740000] <1> inc byte [sysflg] ; Now, we are in system space 19597 000054A8 58 <1> pop eax ; return address to the timer interrupt 19598 <1> ; 19599 000054A9 B020 <1> MOV AL,EOI ; GET END OF INTERRUPT MASK 19600 <1> ;CLI ; DISABLE INTERRUPTS TILL STACK CLEARED 19601 000054AB E620 <1> OUT INTA00,AL ; END OF INTERRUPT TO 8259 - 1 19602 <1> ; 19603 000054AD E904ECFFFF <1> jmp sysrelease ; 'sys release' by clock/timer 19604 <1> clk_1: 19605 000054B2 FE0D[8A740000] <1> dec byte [u.quant] 19606 <1> clk_2: 19607 000054B8 C3 <1> retn ; return to (hardware) timer interrupt routine 19608 <1> 19609 <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 19610 <1> 19611 <1> ;mov $uquant,r0 / decrement user time quantum 19612 <1> ;decb (r0) 19613 <1> ;bge 1f / if less than 0 19614 <1> ;clrb (r0) / make it 0 19615 <1> ;1: / decrement time out counts return now if priority was not 0 19616 <1> ;cmp 4(sp),$200 / ps greater than or equal to 200 19617 <1> ;bge 2f / yes, check time outs 19618 <1> ;tstb (r0) / no, user timed out? 19619 <1> ;bne 1f / no 19620 <1> ;cmpb sysflg,$-1 / yes, are we outside the system? 19621 <1> ;bne 1f / no, 1f 19622 <1> ;mov (sp)+,r0 / yes, put users r0 in r0 19623 <1> ;sys 0 / sysrele 19624 <1> ;rti 19625 <1> ;2: / priority is high so just decrement time out counts 19626 <1> ;mov $toutt,r0 / r0 points to beginning of time out table 19627 <1> ;2: 19628 <1> ;tstb (r0) / is the time out? 19629 <1> ;beq 3f / yes, 3f (get next entry) 19630 <1> ;decb (r0) / no, decrement the time 19631 <1> ;bne 3f / isit zero now? 19632 <1> ;incb (r0) / yes, increment the time 19633 <1> ;3: 19634 <1> ;inc r0 / next entry 19635 <1> ;cmp r0,$touts / end of toutt table? 19636 <1> ;blo 2b / no, check this entry 19637 <1> ;mov (sp)+,r0 / yes, restore r0 19638 <1> ;rti / return from interrupt 19639 <1> ;1: / decrement time out counts; if 0 call subroutine 19640 <1> ;mov (sp)+,r0 / restore r0 19641 <1> ;mov $240,*$ps / set processor priority to 5 19642 <1> ;jsr r0,setisp / save registers 19643 <1> ;mov $touts-toutt-1,r0 / set up r0 as index to decrement thru 19644 <1> ; / the table 19645 <1> ;1: 19646 <1> ;tstb toutt(r0) / is the time out for this entry 19647 <1> ;beq 2f / yes 19648 <1> ;decb toutt(r0) / no, decrement the time 19649 <1> ;bne 2f / is the time 0, now 19650 <1> ;asl r0 / yes, 2 x r0 to get word index for tout entry 19651 <1> ;jsr r0,*touts(r0) / go to appropriate routine specified in this 19652 <1> ;asr r0 / touts entry; set r0 back to toutt index 19653 <1> ;2: 19654 <1> ;dec r0 / set up r0 for next entry 19655 <1> ;bge 1b / finished? , no, go back 19656 <1> ;br retisp / yes, restore registers and do a rti 19657 <1> 19658 <1> ;retisp: 19659 <1> ;mov (sp)+,clockp / pop values before interrupt off the stack 19660 <1> ;mov (sp)+,r3 19661 <1> ;mov (sp)+,r2 19662 <1> ;mov (sp)+,r1 19663 <1> ;mov (sp)+,r0 19664 <1> ;rti / return from interrupt 19665 <1> 19666 <1> 19667 <1> wakeup: ; / wakeup processes waiting for an event 19668 <1> ; / by linking them to the queue 19669 <1> ; 19670 <1> ; 15/09/2015 19671 <1> ; 29/06/2015 19672 <1> ; 15/04/2015 (Retro UNIX 386 v1 - Beginning) 19673 <1> ; 19674 <1> ; 15/05/2013 - 02/06/2014 19675 <1> ; Retro UNIX 8086 v1 modification ! 19676 <1> ; (Process/task switching routine by using 19677 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.) 19678 <1> ; 19679 <1> ; In original UNIX v1, 'wakeup' is called to wake the process 19680 <1> ; sleeping in the specified wait channel by creating a link 19681 <1> ; to it from the last user process on the run queue. 19682 <1> ; If there is no process to wake up, nothing happens. 19683 <1> ; 19684 <1> ; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set 19685 <1> ; 'switching' status of the current process (owns current tty) 19686 <1> ; (via alt + function keys) to a process which has highest 19687 <1> ; priority (on run queue) on the requested tty (0 to 7, except 19688 <1> ; 8 and 9 which are tty identifiers of COM1, COM2 serial ports) 19689 <1> ; as it's console tty. (NOTE: 'p.ttyc' is used to set console 19690 <1> ; tty for tty switching by keyboard.) 19691 <1> ; 19692 <1> ; INPUT -> 19693 <1> ; AL = wait channel (r3) ('tty number' for now) 19694 <1> ; ;;EBX = Run queue (r2) offset 19695 <1> ; 19696 <1> ; ((modified registers: EAX, EBX)) 19697 <1> ; 19698 000054B9 0FB6D8 <1> movzx ebx, al ; 29/06/2015 19699 000054BC 81C3[C8700000] <1> add ebx, wlist 19700 000054C2 8A03 <1> mov al, [ebx] ; waiting list (waiting process number) 19701 000054C4 20C0 <1> and al, al 19702 000054C6 7424 <1> jz short wa0 ; nothing to wakeup 19703 <1> ; 19704 000054C8 30E4 <1> xor ah, ah 19705 000054CA 8825[8A740000] <1> mov [u.quant], ah ; 0 ; time quantum = 0 19706 000054D0 8823 <1> mov [ebx], ah ; 0 ; zero wait channel entry 19707 <1> ; 15/09/2015 19708 000054D2 0FB6D8 <1> movzx ebx, al 19709 000054D5 88A3[A5710000] <1> mov [ebx+p.waitc-1], ah ; 0 19710 000054DB FEC4 <1> inc ah 19711 000054DD 88A3[C5710000] <1> mov byte [ebx+p.stat-1], ah ; 1 ; SRUN 19712 <1> ; 19713 000054E3 57 <1> push edi 19714 000054E4 52 <1> push edx 19715 000054E5 E84AFFFFFF <1> call putlu 19716 000054EA 5A <1> pop edx 19717 000054EB 5F <1> pop edi 19718 <1> wa0: 19719 000054EC C3 <1> retn 19720 <1> 19721 <1> sleep: 19722 <1> ; 15/09/2015 19723 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 19724 <1> ; 19725 <1> ; 09/05/2013 - 20/03/2014 19726 <1> ; 19727 <1> ; Retro UNIX 8086 v1 modification ! 19728 <1> ; (Process/task switching and quit routine by using 19729 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 19730 <1> ; 19731 <1> ; In original UNIX v1, 'sleep' is called to wait for 19732 <1> ; tty and tape output or input becomes available 19733 <1> ; and process is put on waiting channel and swapped out, 19734 <1> ; then -when the tty or tape is ready to write or read- 19735 <1> ; 'wakeup' gets process back to active swapped-in status.) 19736 <1> ; 19737 <1> ; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and 19738 <1> ; Int 09h keyboard interrupt will set 'quit' or 'switching' 19739 <1> ; status of the current process also INT 1Ch will count down 19740 <1> ; 'uquant' value and INT 09h will redirect scancode of keystroke 19741 <1> ; to tty buffer of the current process and kernel will get 19742 <1> ; user input by using tty buffer of the current process 19743 <1> ; (instead of standard INT 16h interrupt). 19744 <1> ; TTY output will be redirected to related video page of text mode 19745 <1> ; (INT 10h will be called with different video page depending 19746 <1> ; on tty assignment of the active process: 0 to 7 for 19747 <1> ; pseudo screens.) 19748 <1> ; 19749 <1> ; In Retro UNIX 8086 v1, 'sleep' will be called to wait for 19750 <1> ; a keystroke from keyboard or wait for reading or writing 19751 <1> ; characters/data on serial port(s). 19752 <1> ; 19753 <1> ; Character/Terminal input/output through COM1 and COM2 will be 19754 <1> ; performed by related routines in addition to pseudo TTY routines. 19755 <1> ; 19756 <1> ; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013) 19757 <1> ; 19758 <1> ;; 05/10/2013 19759 <1> ;10/12/2013 19760 <1> ;cmp byte [u.uno], 1 19761 <1> ;ja short sleep0 19762 <1> ;retn 19763 <1> 19764 <1> ; 20/03/2014 19765 <1> ;mov bx, [runq] 19766 <1> ;cmp bl, bh 19767 <1> ;jne short sleep0 19768 <1> ; 25/02/2014 19769 <1> ;cmp word ptr [runq], 0 19770 <1> ;ja short sleep0 19771 <1> ;retn 19772 <1> sleep0: 19773 <1> ; 19774 000054ED E854000000 <1> call isintr 19775 000054F2 0F8562EBFFFF <1> jnz sysret 19776 <1> ; / wait for event 19777 <1> ; jsr r0,isintr / check to see if interrupt 19778 <1> ; / or quit from user 19779 <1> ; br 2f / something happened 19780 <1> ; / yes, his interrupt so return 19781 <1> ; / to user 19782 <1> 19783 <1> ; 30/06/2015 19784 000054F8 0FB6DC <1> movzx ebx, ah ; 30/06/2015 19785 000054FB 81C3[C8700000] <1> add ebx, wlist 19786 00005501 8A03 <1> mov al, [ebx] 19787 00005503 20C0 <1> and al, al 19788 00005505 7407 <1> jz short sleep1 19789 00005507 53 <1> push ebx 19790 00005508 E827FFFFFF <1> call putlu 19791 0000550D 5B <1> pop ebx 19792 <1> sleep1: 19793 0000550E A0[97740000] <1> mov al, [u.uno] 19794 00005513 8803 <1> mov [ebx], al ; put the process number 19795 <1> ; in the wait channel 19796 <1> ; mov (r0)+,r1 / put number of wait channel in r1 19797 <1> ; movb wlist(r1),-(sp) / put old process number in there, 19798 <1> ; / on the stack 19799 <1> ; movb u.uno,wlist(r1) / put process number of process 19800 <1> ; / to put to sleep in there 19801 <1> ; 15/09/2015 19802 00005515 0FB6D8 <1> movzx ebx, al 19803 00005518 C683[C5710000]04 <1> mov byte [ebx+p.stat-1], 4 ; SSLEEP 19804 0000551F FEC4 <1> inc ah 19805 00005521 88A3[A5710000] <1> mov [ebx+p.waitc-1], ah ; wait channel + 1 19806 <1> ; 19807 00005527 66FF35[2E740000] <1> push word [cdev] 19808 <1> ; mov cdev,-(sp) / nothing happened in isintr so 19809 0000552E E833FEFFFF <1> call swap 19810 <1> ; jsr r0,swap / swap out process that needs to sleep 19811 00005533 668F05[2E740000] <1> pop word [cdev] 19812 <1> ; mov (sp)+,cdev / restore device 19813 0000553A E807000000 <1> call isintr 19814 <1> ; 22/09/2013 19815 0000553F 0F8515EBFFFF <1> jnz sysret 19816 <1> ; jsr r0,isintr / check for interrupt of new process 19817 <1> ; br 2f / yes, return to new user 19818 <1> ; movb (sp)+,r1 / no, r1 = old process number that was 19819 <1> ; / originally on the wait channel 19820 <1> ; beq 1f / if 0 branch 19821 <1> ; mov $runq+4,r2 / r2 points to lowest priority queue 19822 <1> ; mov $300,*$ps / processor priority = 6 19823 <1> ; jsr r0,putlu / create link to old process number 19824 <1> ; clr *$ps / clear the status; process priority = 0 19825 <1> ;1: 19826 00005545 C3 <1> retn 19827 <1> ; rts r0 / return 19828 <1> ;2: 19829 <1> ;;jmp sysret 19830 <1> ; jmp sysret / return to user 19831 <1> 19832 <1> isintr: 19833 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 19834 <1> ; 19835 <1> ; 09/05/2013 - 30/05/2014 19836 <1> ; 19837 <1> ; Retro UNIX 8086 v1 modification ! 19838 <1> ; (Process/task switching and quit routine by using 19839 <1> ; Retro UNIX 8086 v1 keyboard interrupt output.)) 19840 <1> ; 19841 <1> ; Retro UNIX 8086 v1 modification: 19842 <1> ; 'isintr' checks if user interrupt request is enabled 19843 <1> ; and there is a 'quit' request by user; 19844 <1> ; otherwise, 'isintr' will return with zf=1 that means 19845 <1> ; "nothing to do". (20/10/2013) 19846 <1> ; 19847 <1> ; 20/10/2013 19848 00005546 66833D[78740000]00 <1> cmp word [u.ttyp], 0 ; has process got a tty ? 19849 0000554E 7622 <1> jna short isintr2 ; retn 19850 <1> ; 03/09/2013 19851 <1> ; (nothing to do) 19852 <1> ;retn 19853 <1> ; 22/09/2013 19854 00005550 66833D[8C740000]00 <1> cmp word [u.intr], 0 19855 00005558 7618 <1> jna short isintr2 ; retn 19856 <1> ; 30/05/2014 19857 0000555A 6650 <1> push ax 19858 0000555C 66A1[8E740000] <1> mov ax, [u.quit] 19859 00005562 6609C0 <1> or ax, ax ; 0 ? 19860 00005565 7409 <1> jz short isintr1 ; zf = 1 19861 00005567 6683F8FE <1> cmp ax, 0FFFEh ; 'ctrl + brk' check 19862 0000556B 7703 <1> ja short isintr1 ; 0FFFFh, zf = 0 19863 0000556D 6631C0 <1> xor ax, ax ; zf = 1 19864 <1> isintr1: 19865 00005570 6658 <1> pop ax 19866 <1> isintr2: ; 22/09/2013 19867 <1> ; zf=1 -> nothing to do 19868 00005572 C3 <1> retn 19869 <1> 19870 <1> ; UNIX v1 original 'isintr' routine... 19871 <1> ;mov r1,-(sp) / put number of wait channel on the stack 19872 <1> ;mov r2,-(sp) / save r2 19873 <1> ;mov u.ttyp,r1 / r1 = pointer to buffer of process control 19874 <1> ; / typewriter 19875 <1> ;beq 1f / if 0, do nothing except skip return 19876 <1> ;movb 6(r1),r1 / put interrupt char in the tty buffer in r1 19877 <1> ;beq 1f / if its 0 do nothing except skip return 19878 <1> ;cmp r1,$177 / is interrupt char = delete? 19879 <1> ;bne 3f / no, so it must be a quit (fs) 19880 <1> ;tst u.intr / yes, value of u.intr determines handling 19881 <1> ; / of interrupts 19882 <1> ;bne 2f / if not 0, 2f. If zero do nothing. 19883 <1> ;1: 19884 <1> ;tst (r0)+ / bump r0 past system return (skip) 19885 <1> ;4: 19886 <1> ;mov (sp)+,r2 / restore r1 and r2 19887 <1> ;mov (sp)+,r1 19888 <1> ;rts r0 19889 <1> ;3: / interrupt char = quit (fs) 19890 <1> ;tst u.quit / value of u.quit determines handling of quits 19891 <1> ;beq 1b / u.quit = 0 means do nothing 19892 <1> ;2: / get here because either u.intr <> 0 or u.qult <> O 19893 <1> ;mov $tty+6,r1 / move pointer to tty block into r1 19894 <1> ;1: / find process control tty entry in tty block 19895 <1> ;cmp (r1),u.ttyp / is this the process control tty buffer? 19896 <1> ;beq 1f / block found go to 1f 19897 <1> ;add $8,r1 / look at next tty block 19898 <1> ;cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks 19899 <1> ;blo 1b / no 19900 <1> ;br 4b / no process control tty found so go to 4b 19901 <1> ;1: 19902 <1> ;mov $240,*$ps / set processor priority to 5 19903 <1> ;movb -3(r1),0f / load getc call argument; character llst 19904 <1> ; / identifier 19905 <1> ;inc 0f / increment 19906 <1> ;1: 19907 <1> ;jsr r0,getc; 0:.. / erase output char list for control 19908 <1> ; br 4b / process tty. This prevents a line of stuff 19909 <1> ; / being typed out after you hit the interrupt 19910 <1> ; / key 19911 <1> ;br 1b 19912 %include 'u5.s' ; 03/06/2015 19913 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC 19914 <1> ; Last Modification: 14/11/2015 19915 <1> ; ---------------------------------------------------------------------------- 19916 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 19917 <1> ; (v0.1 - Beginning: 11/07/2012) 19918 <1> ; 19919 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 19920 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 19921 <1> ; 19922 <1> ; 19923 <1> ; 19924 <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s 19925 <1> ; 19926 <1> ; **************************************************************************** 19927 <1> 19928 <1> mget: 19929 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 19930 <1> ; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 19931 <1> ; 19932 <1> ; Get existing or (allocate) a new disk block for file 19933 <1> ; 19934 <1> ; INPUTS -> 19935 <1> ; u.fofp (file offset pointer) 19936 <1> ; inode 19937 <1> ; u.off (file offset) 19938 <1> ; OUTPUTS -> 19939 <1> ; r1 (physical block number) 19940 <1> ; r2, r3, r5 (internal) 19941 <1> ; 19942 <1> ; ((AX = R1)) output 19943 <1> ; (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM) 19944 <1> ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP)) 19945 <1> 19946 <1> ; mov *u.fofp,mq / file offset in mq 19947 <1> ; clr ac / later to be high sig 19948 <1> ; mov $-8,lsh / divide ac/mq by 256. 19949 <1> ; mov mq,r2 19950 <1> ; bit $10000,i.flgs / lg/sm is this a large or small file 19951 <1> ; bne 4f / branch for large file 19952 <1> mget_0: 19953 00005573 8B35[58740000] <1> mov esi, [u.fofp] 19954 00005579 0FB65E01 <1> movzx ebx, byte [esi+1] 19955 <1> ; BX = r2 19956 0000557D 66F705[16710000]00- <1> test word [i.flgs], 4096 ; 1000h 19957 00005585 10 <1> 19958 <1> ; is this a large or small file 19959 00005586 756F <1> jnz short mget_5 ; 4f ; large file 19960 <1> 19961 00005588 F6C3F0 <1> test bl, 0F0h ; !0Fh 19962 <1> ; bit $!17,r2 19963 0000558B 7526 <1> jnz short mget_2 19964 <1> ; bne 3f / branch if r2 greater than or equal to 16 19965 0000558D 80E30E <1> and bl, 0Eh 19966 <1> ; bic $!16,r2 / clear all bits but bits 1,2,3 19967 00005590 0FB783[1C710000] <1> movzx eax, word [ebx+i.dskp] ; AX = R1, physical block number 19968 <1> ; mov i.dskp(r2),r1 / r1 has physical block number 19969 00005597 6609C0 <1> or ax, ax 19970 0000559A 7516 <1> jnz short mget_1 19971 <1> ; bne 2f / if physical block num is zero then need a new block 19972 <1> ; / for file 19973 0000559C E8AB000000 <1> call alloc 19974 <1> ; jsr r0,alloc / allocate a new block 19975 <1> ; eAX (r1) = Physical block number 19976 000055A1 668983[1C710000] <1> mov [ebx+i.dskp], ax 19977 <1> ; mov r1,i.dskp(r2) / physical block number stored in i-node 19978 000055A8 E84C020000 <1> call setimod 19979 <1> ; jsr r0,setimod / set inode modified byte (imod) 19980 000055AD E8B1FEFFFF <1> call clear 19981 <1> ; jsr r0,clear / zero out disk/drum block just allocated 19982 <1> mget_1: ; 2: 19983 <1> ; eAX (r1) = Physical block number 19984 000055B2 C3 <1> retn 19985 <1> ; rts r0 19986 <1> mget_2: ; 3: / adding on block which changes small file to a large file 19987 000055B3 E894000000 <1> call alloc 19988 <1> ; jsr r0,alloc / allocate a new block for this file; 19989 <1> ; / block number in r1 19990 <1> ; eAX (r1) = Physical block number 19991 000055B8 E8560C0000 <1> call wslot 19992 <1> ; jsr r0,wslot / set up I/O buffer for write, r5 points to 19993 <1> ; / first data word in buffer 19994 <1> ; eAX (r1) = Physical block number 19995 000055BD B908000000 <1> mov ecx, 8 ; R3, transfer old physical block pointers 19996 <1> ; into new indirect block area for the new 19997 <1> ; large file 19998 000055C2 89DF <1> mov edi, ebx ; r5 19999 000055C4 BE[1C710000] <1> mov esi, i.dskp 20000 <1> ; mov $8.,r3 / next 6 instructions transfer old physical 20001 <1> ; / block pointers 20002 <1> ; mov $i.dskp,r2 / into new indirect block for the new 20003 <1> ; / large file 20004 000055C9 6631C0 <1> xor ax, ax ; mov ax, 0 20005 <1> mget_3: ;1: 20006 000055CC 66A5 <1> movsw 20007 <1> ; mov (r2),(r5)+ 20008 000055CE 668946FE <1> mov [esi-2], ax 20009 <1> ; clr (r2)+ 20010 000055D2 E2F8 <1> loop mget_3 ; 1b 20011 <1> ; dec r3 20012 <1> ; bgt 1b 20013 <1> 20014 000055D4 B1F8 <1> mov cl, 256-8 20015 <1> ; mov $256.-8.,r3 / clear rest of data buffer 20016 <1> mget_4: ; 1 20017 000055D6 F366AB <1> rep stosw 20018 <1> ; clr (r5)+ 20019 <1> ; dec r3 20020 <1> ; bgt 1b 20021 <1> ; 24/03/2013 20022 <1> ; AX (r1) = Physical block number 20023 000055D9 E8510C0000 <1> call dskwr 20024 <1> ; jsr r0,dskwr / write new indirect block on disk 20025 <1> ; eAX (r1) = Physical block number 20026 000055DE 66A3[1C710000] <1> mov [i.dskp], ax 20027 <1> ; mov r1,i.dskp / put pointer to indirect block in i-node 20028 000055E4 66810D[16710000]00- <1> or word [i.flgs], 4096 ; 1000h 20029 000055EC 10 <1> 20030 <1> ; bis $10000,i.flgs / set large file bit 20031 <1> ; / in i.flgs word of i-node 20032 000055ED E807020000 <1> call setimod 20033 <1> ; jsr r0,setimod / set i-node modified flag 20034 000055F2 E97CFFFFFF <1> jmp mget_0 20035 <1> ; br mget 20036 <1> 20037 <1> mget_5: ; 4 ; large file 20038 <1> ; mov $-8,lsh / divide byte number by 256. 20039 <1> ; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset 20040 <1> ; / in indirect block 20041 <1> ; mov r2,-(sp) / save on stack (*) 20042 <1> ; mov mq,r2 / calculate offset in i-node for pointer to proper 20043 <1> ; / indirect block 20044 <1> ; bic $!16,r2 20045 000055F7 80E3FE <1> and bl, 0FEh ; bh = 0 20046 000055FA 53 <1> push ebx ; i-node pointer offset in indirect block (*) 20047 <1> ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512) 20048 <1> ; for this file system (offset 128 to 255 not in use) 20049 <1> ; There is always 1 indirect block for this file system 20050 000055FB 0FB705[1C710000] <1> movzx eax, word [i.dskp] ; i.dskp[0] 20051 <1> ; mov i.dskp(r2),r1 20052 00005602 6609C0 <1> or ax, ax ; R1 20053 00005605 7515 <1> jnz short mget_6 ; 2f 20054 <1> ; bne 2f / if no indirect block exists 20055 00005607 E840000000 <1> call alloc 20056 <1> ; jsr r0,alloc / allocate a new block 20057 0000560C 66A3[1C710000] <1> mov [i.dskp], ax ; 03/03/2013 20058 <1> ; mov r1,i.dskp(r2) / put block number of new block in i-node 20059 00005612 E8E2010000 <1> call setimod 20060 <1> ; jsr r0,setimod / set i-node modified byte 20061 <1> ; eAX = new block number 20062 00005617 E847FEFFFF <1> call clear 20063 <1> ; jsr r0,clear / clear new block 20064 <1> mget_6: ;2 20065 <1> ; 05/03/2013 20066 <1> ; eAX = r1, physical block number (of indirect block) 20067 0000561C E8920B0000 <1> call dskrd ; read indirect block 20068 <1> ; jsr r0,dskrd / read in indirect block 20069 00005621 5A <1> pop edx ; R2, get offset (*) 20070 <1> ; mov (sp)+,r2 / get offset 20071 <1> ; eAX = r1, physical block number (of indirect block) 20072 00005622 50 <1> push eax ; ** ; 24/03/2013 20073 <1> ; mov r1,-(sp) / save block number of indirect block on stack 20074 <1> ; eBX (r5) = pointer to buffer (indirect block) 20075 00005623 01D3 <1> add ebx, edx ; / r5 points to first word in indirect block, r2 20076 <1> ; add r5,r2 / r5 points to first word in indirect block, r2 20077 <1> ; / points to location of inter 20078 00005625 0FB703 <1> movzx eax, word [ebx] ; put physical block no of block 20079 <1> ; in file sought in R1 (AX) 20080 <1> ; mov (r2),r1 / put physical block no of block in file 20081 <1> ; / sought in r1 20082 00005628 6609C0 <1> or ax, ax 20083 0000562B 751D <1> jnz short mget_7 ; 2f 20084 <1> ; bne 2f / if no block exists 20085 0000562D E81A000000 <1> call alloc 20086 <1> ; jsr r0,alloc / allocate a new block 20087 00005632 668903 <1> mov [ebx], ax ; R1 20088 <1> ; mov r1,(r2) / put new block number into proper location in 20089 <1> ; / indirect block 20090 00005635 5A <1> pop edx ; ** ; 24/03/2013 20091 <1> ; mov (sp)+,r1 / get block number of indirect block 20092 00005636 52 <1> push edx ; ** ; 31/07/2013 20093 00005637 50 <1> push eax ; * ; 24/03/2013, 31/07/2013 (new block number) 20094 00005638 89D0 <1> mov eax, edx ; 24/03/2013 20095 <1> ; mov (r2),-(sp) / save block number of new block 20096 <1> ; eAX (r1) = physical block number (of indirect block) 20097 0000563A E8D40B0000 <1> call wslot 20098 <1> ; jsr r0,wslot 20099 <1> ; eAX (r1) = physical block number 20100 <1> ; eBX (r5) = pointer to buffer (indirect block) 20101 0000563F E8EB0B0000 <1> call dskwr 20102 <1> ; eAX = r1 = physical block number (of indirect block) 20103 <1> ; jsr r0,dskwr / write newly modified indirect block 20104 <1> ; / back out on disk 20105 00005644 58 <1> pop eax ; * ; 31/07/2013 20106 <1> ; mov (sp),r1 / restore block number of new block 20107 <1> ; eAX (r1) = physical block number of new block 20108 00005645 E819FEFFFF <1> call clear 20109 <1> ; jsr r0,clear / clear new block 20110 <1> mget_7: ; 2 20111 0000564A 5A <1> pop edx ; ** 20112 <1> ; tst (sp)+ / bump stack pointer 20113 <1> ; eAX (r1) = Block number of new block 20114 0000564B C3 <1> retn 20115 <1> ; rts r0 20116 <1> 20117 <1> alloc: 20118 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20119 <1> ; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 20120 <1> ; 20121 <1> ; get a free block and 20122 <1> ; set the corresponding bit in the free storage map 20123 <1> ; 20124 <1> ; INPUTS -> 20125 <1> ; cdev (current device) 20126 <1> ; r2 20127 <1> ; r3 20128 <1> ; OUTPUTS -> 20129 <1> ; r1 (physical block number of block assigned) 20130 <1> ; smod, mmod, systm (super block), mount (mountable super block) 20131 <1> ; 20132 <1> ; ((AX = R1)) output 20133 <1> ; (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM) 20134 <1> ; ((Modified registers: DX, CX)) 20135 <1> 20136 <1> ;mov r2,-(sp) / save r2, r3 on stack 20137 <1> ;mov r3,-(sp) 20138 <1> ;push ecx 20139 0000564C 53 <1> push ebx ; R2 20140 <1> ;push edx ; R3 20141 0000564D BB[08810000] <1> mov ebx, systm ; SuperBlock 20142 <1> ; mov $systm,r2 / start of inode and free storage map for drum 20143 00005652 803D[2E740000]00 <1> cmp byte [cdev], 0 20144 <1> ; tst cdev 20145 00005659 7605 <1> jna short alloc_1 20146 <1> ; beq 1f / drum is device 20147 0000565B BB[10830000] <1> mov ebx, mount 20148 <1> ; mov $mount,r2 / disk or tape is device, start of inode and 20149 <1> ; / free storage map 20150 <1> alloc_1: ; 1 20151 00005660 668B0B <1> mov cx, [ebx] 20152 <1> ; mov (r2)+,r1 / first word contains number of bytes in free 20153 <1> ; / storage map 20154 00005663 66C1E103 <1> shl cx, 3 20155 <1> ; asl r1 / multiply r1 by eight gives 20156 <1> ; number of blocks in device 20157 <1> ; asl r1 20158 <1> ; asl r1 20159 <1> ;; push cx ;; 01/08/2013 20160 <1> ; mov r1,-(sp) / save # of blocks in device on stack 20161 00005667 31C0 <1> xor eax, eax ; 0 20162 <1> ; clr r1 / r1 contains bit count of free storage map 20163 <1> alloc_2: ; 1 20164 00005669 43 <1> inc ebx ; 18/8/2012 20165 0000566A 43 <1> inc ebx ; 20166 0000566B 668B13 <1> mov dx, [ebx] 20167 <1> ; mov (r2)+,r3 / word of free storage map in r3 20168 0000566E 6609D2 <1> or dx, dx 20169 00005671 750E <1> jnz short alloc_3 ; 1f 20170 <1> ; bne 1f / branch if any free blocks in this word 20171 00005673 6683C010 <1> add ax, 16 20172 <1> ; add $16.,r1 20173 00005677 6639C8 <1> cmp ax, cx 20174 <1> ; cmp r1 ,(sp) / have we examined all free storage bytes 20175 0000567A 72ED <1> jb short alloc_2 20176 <1> ; blo 1b 20177 <1> ; 14/11/2015 20178 <1> ; Note: If the super block buffer has wrong content (zero bytes) 20179 <1> ; because of a (DMA or another) r/w error, 20180 <1> ; we will be here, at 'jmp panic' code address, 20181 <1> ; even if the (disk) file system space is not full !!! 20182 <1> ; (cx = 0) 20183 <1> ; 20184 0000567C E94FE2FFFF <1> jmp panic 20185 <1> ; jmp panic / found no free storage 20186 <1> alloc_3: ; 1 20187 00005681 66D1EA <1> shr dx, 1 20188 <1> ; asr r3 / find a free block 20189 00005684 7204 <1> jc short alloc_4 ; 1f 20190 <1> ; bcs 1f / branch when free block found; bit for block k 20191 <1> ; / is in byte k/8 / in bit k (mod 8) 20192 00005686 6640 <1> inc ax 20193 <1> ; inc r1 / increment bit count in bit k (mod8) 20194 00005688 EBF7 <1> jmp short alloc_3 20195 <1> ; br 1b 20196 <1> alloc_4: ; 1: 20197 <1> ;; pop cx ;; 01/08/2013 20198 <1> ; tst (sp)+ / bump sp 20199 <1> ; 02/04/2013 20200 0000568A E829000000 <1> call free3 20201 <1> ; jsr r0,3f / have found a free block 20202 <1> ; 21/8/2012 20203 0000568F 66F7D2 <1> not dx ; masking bit is '0' and others are '1' 20204 00005692 662113 <1> and [ebx], dx ;; 0 -> allocated 20205 <1> ; bic r3,(r2) / set bit for this block 20206 <1> ; / i.e. assign block 20207 <1> ; br 2f 20208 00005695 EB09 <1> jmp short alloc_5 20209 <1> 20210 <1> free: 20211 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20212 <1> ; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 20213 <1> ; 20214 <1> ; calculates byte address and bit position for given block number 20215 <1> ; then sets the corresponding bit in the free storage map 20216 <1> ; 20217 <1> ; INPUTS -> 20218 <1> ; r1 - block number for a block structured device 20219 <1> ; cdev - current device 20220 <1> ; OUTPUTS -> 20221 <1> ; free storage map is updated 20222 <1> ; smod is incremented if cdev is root device (fixed disk) 20223 <1> ; mmod is incremented if cdev is a removable disk 20224 <1> ; 20225 <1> ; (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM) 20226 <1> ; ((Modified registers: DX, CX)) 20227 <1> 20228 <1> ;mov r2,-(sp) / save r2, r3 20229 <1> ;mov r3,-(sp) 20230 <1> ;push ecx 20231 00005697 53 <1> push ebx ; R2 20232 <1> ;push edx ; R3 20233 <1> 20234 00005698 E81B000000 <1> call free3 20235 <1> ; jsr r0,3f / set up bit mask and word no. 20236 <1> ; / in free storage map for block 20237 0000569D 660913 <1> or [ebx], dx 20238 <1> ; bis r3, (r2) / set free storage block bit; 20239 <1> ; / indicates free block 20240 <1> ; 0 -> allocated, 1 -> free 20241 <1> 20242 <1> alloc_5: 20243 <1> ; 07/04/2013 20244 <1> free_1: ; 2: 20245 <1> ; pop edx 20246 <1> ; mov (sp)+,r3 / restore r2, r3 20247 000056A0 5B <1> pop ebx 20248 <1> ; mov (sp)+,r2 20249 <1> ; pop ecx 20250 000056A1 803D[2E740000]00 <1> cmp byte [cdev], 0 20251 <1> ; tst cdev / cdev = 0, block structured, drum; 20252 <1> ; / cdev = 1, mountable device 20253 000056A8 7707 <1> ja short alloc_6 ; 1f 20254 <1> ; bne 1f 20255 <1> ;mov byte [smod], 1 20256 000056AA FE05[3D740000] <1> inc byte [smod] 20257 <1> ; incb smod / set super block modified for drum 20258 <1> ; eAX (r1) = block number 20259 000056B0 C3 <1> retn 20260 <1> ; rts r0 20261 <1> free_2: 20262 <1> alloc_6: ; 1: 20263 <1> ;mov byte [mmod], 1 20264 000056B1 FE05[3E740000] <1> inc byte [mmod] 20265 <1> ; incb mmod 20266 <1> ; / set super block modified for mountable device 20267 <1> ; eAX (r1) = block number 20268 000056B7 C3 <1> retn 20269 <1> ; rts r0 20270 <1> free3: 20271 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20272 <1> ; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 20273 <1> ; 20274 <1> ; free3 is called from 'alloc' and 'free' procedures 20275 <1> ; 20276 <1> alloc_free_3: ; 3 20277 000056B8 66BA0100 <1> mov dx, 1 20278 000056BC 88C1 <1> mov cl, al 20279 <1> ; mov r1,r2 / block number, k, = 1 20280 000056BE 80E10F <1> and cl, 0Fh ; 0Fh <-- (k) mod 16 20281 <1> ; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8) 20282 000056C1 7403 <1> jz short free4 20283 <1> ; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to 20284 <1> ; / (k) mod 8 20285 000056C3 66D3E2 <1> shl dx, cl 20286 <1> free4: 20287 000056C6 0FB7D8 <1> movzx ebx, ax 20288 <1> ; mov r1,r2 / divide block number by 16 20289 000056C9 66C1EB04 <1> shr bx, 4 20290 <1> ; asr r2 20291 <1> ; asr r2 20292 <1> ; asr r2 20293 <1> ; asr r2 20294 <1> ; bcc 1f / branch if bit 3 in r1 was 0 i.e., 20295 <1> ; / bit for block is in lower half of word 20296 <1> ; swab r3 / swap bytes in r3; bit in upper half of word in free 20297 <1> ; / storage map 20298 <1> alloc_free_4: ; 1 20299 000056CD 66D1E3 <1> shl bx, 1 20300 <1> ; asl r2 / multiply block number by 2; r2 = k/8 20301 000056D0 81C3[0A810000] <1> add ebx, systm+2 ; SuperBlock+2 20302 <1> ; add $systm+2,r2 / address of word of free storage map for drum 20303 <1> ; / with block bit in it 20304 000056D6 803D[2E740000]00 <1> cmp byte [cdev], 0 20305 <1> ; tst cdev 20306 000056DD 7606 <1> jna short alloc_free_5 20307 <1> ; beq 1f / cdev = 0 indicates device is drum 20308 000056DF 81C308020000 <1> add ebx, mount - systm 20309 <1> ; add $mount-systm,r2 / address of word of free storage map for 20310 <1> ; / mountable device with bit of block to be 20311 <1> ; / freed 20312 <1> alloc_free_5: ; 1 20313 000056E5 C3 <1> retn 20314 <1> ; rts r0 / return to 'free' 20315 <1> ; 2 20316 <1> ; .byte 1,2,4,10,20,40,100,200 / masks for bits 0,...,7 20317 <1> 20318 <1> iget: 20319 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20320 <1> ; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1) 20321 <1> ; 20322 <1> ; get a new i-node whose i-number in r1 and whose device is in cdev 20323 <1> ; 20324 <1> ; ('iget' returns current i-number in r1, if input value of r1 is 0) 20325 <1> ; 20326 <1> ; INPUTS -> 20327 <1> ; ii - current i-number, rootdir 20328 <1> ; cdev - new i-node device 20329 <1> ; idev - current i-node device 20330 <1> ; imod - current i-node modified flag 20331 <1> ; mnti - cross device file i-number 20332 <1> ; r1 - i-numbe rof new i-node 20333 <1> ; mntd - mountable device number 20334 <1> ; 20335 <1> ; OUTPUTS -> 20336 <1> ; cdev, idev, imod, ii, r1 20337 <1> ; 20338 <1> ; ((AX = R1)) input/output 20339 <1> ; 20340 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 20341 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 20342 <1> 20343 000056E6 8A15[2E740000] <1> mov dl, [cdev] ; 18/07/2013 20344 000056EC 8A35[2C740000] <1> mov dh, [idev] ; 07/08/2013 20345 <1> ; 20346 000056F2 663B05[2A740000] <1> cmp ax, [ii] 20347 <1> ; cmp r1,ii / r1 = i-number of current file 20348 000056F9 7504 <1> jne short iget_1 20349 <1> ; bne 1f 20350 000056FB 38F2 <1> cmp dl, dh 20351 <1> ; cmp idev,cdev 20352 <1> ; / is device number of i-node = current device 20353 000056FD 7476 <1> je short iget_5 20354 <1> ; beq 2f 20355 <1> iget_1: ; 1: 20356 000056FF 30DB <1> xor bl, bl 20357 00005701 381D[3C740000] <1> cmp [imod], bl ; 0 20358 <1> ; tstb imod / has i-node of current file 20359 <1> ; / been modified i.e., imod set 20360 00005707 762D <1> jna short iget_2 20361 <1> ; beq 1f 20362 00005709 881D[3C740000] <1> mov [imod], bl ; 0 20363 <1> ; clrb imod / if it has, 20364 <1> ; / we must write the new i-node out on disk 20365 0000570F 6650 <1> push ax 20366 <1> ; mov r1,-(sp) 20367 <1> ;mov dl, [cdev] 20368 00005711 6652 <1> push dx 20369 <1> ; mov cdev,-(sp) 20370 00005713 66A1[2A740000] <1> mov ax, [ii] 20371 <1> ; mov ii,r1 20372 <1> ;mov dh, [idev] 20373 00005719 8835[2E740000] <1> mov [cdev], dh 20374 <1> ; mov idev,cdev 20375 0000571F FEC3 <1> inc bl ; 1 20376 <1> ; 31/07/2013 20377 00005721 881D[CC740000] <1> mov [rw], bl ; 1 == write 20378 <1> ;;28/07/2013 rw -> u.rw 20379 <1> ;;mov [u.rw], bl ; 1 == write 20380 00005727 E84A000000 <1> call icalc 20381 <1> ; jsr r0,icalc; 1 20382 0000572C 665A <1> pop dx 20383 0000572E 8815[2E740000] <1> mov [cdev], dl 20384 <1> ; mov (sp)+,cdev 20385 00005734 6658 <1> pop ax 20386 <1> ; mov (sp)+,r1 20387 <1> iget_2: ; 1: 20388 00005736 6621C0 <1> and ax, ax 20389 <1> ; tst r1 / is new i-number non zero 20390 00005739 7434 <1> jz short iget_4 ; 2f 20391 <1> ; beq 2f / branch if r1=0 20392 <1> 20393 <1> ; mov dl, [cdev] 20394 0000573B 08D2 <1> or dl, dl 20395 <1> ; tst cdev / is the current device number non zero 20396 <1> ; / (i.e., device =/ drum) 20397 0000573D 7517 <1> jnz short iget_3 ; 1f 20398 <1> ; bne 1f / branch 1f cdev =/ 0 ;; (cdev != 0) 20399 0000573F 663B05[34740000] <1> cmp ax, [mnti] 20400 <1> ; cmp r1,mnti / mnti is the i-number of the cross device 20401 <1> ; / file (root directory of mounted device) 20402 00005746 750E <1> jne short iget_3 ; 1f 20403 <1> ; bne 1f 20404 <1> ;mov bl, [mntd] 20405 00005748 FEC2 <1> inc dl ; mov dl, 1 ; 17/07/2013 20406 0000574A 8815[2E740000] <1> mov [cdev], dl ; 17/07/2013 - 09/07/2013 20407 <1> ; mov mntd,cdev / make mounted device the current device 20408 00005750 66A1[38740000] <1> mov ax, [rootdir] 20409 <1> ; mov rootdir,r1 20410 <1> iget_3: ; 1: 20411 00005756 66A3[2A740000] <1> mov [ii], ax 20412 <1> ; mov r1,ii 20413 0000575C 8815[2C740000] <1> mov [idev], dl ; cdev 20414 <1> ; mov cdev,idev 20415 00005762 30DB <1> xor bl, bl 20416 <1> ; 31/07/2013 20417 00005764 881D[CC740000] <1> mov [rw], bl ; 0 == read 20418 <1> ;;28/07/2013 rw -> u.rw 20419 <1> ;;mov [u.rw], bl ; 0 = read 20420 0000576A E807000000 <1> call icalc 20421 <1> ; jsr r0,icalc; 0 / read in i-node ii 20422 <1> iget_4: ; 2: 20423 0000576F 66A1[2A740000] <1> mov ax, [ii] 20424 <1> ; mov ii,r1 20425 <1> iget_5: 20426 00005775 C3 <1> retn 20427 <1> ; rts r0 20428 <1> 20429 <1> icalc: 20430 <1> ; 02/07/2015 20431 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20432 <1> ; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 20433 <1> ; 20434 <1> ; calculate physical block number from i-number then 20435 <1> ; read or write that block 20436 <1> ; 20437 <1> ; 'icalc' is called from 'iget' 20438 <1> ; 20439 <1> ; for original unix v1: 20440 <1> ; / i-node i is located in block (i+31.)/16. and begins 32.* 20441 <1> ; / (i+31.) mod 16. bytes from its start 20442 <1> ; 20443 <1> ; for retro unix 8086 v1: 20444 <1> ; i-node is located in block (i+47)/16 and 20445 <1> ; begins 32*(i+47) mod 16 bytes from its start 20446 <1> ; 20447 <1> ; INPUTS -> 20448 <1> ; r1 - i-number of i-node 20449 <1> ; 20450 <1> ; OUTPUTS -> 20451 <1> ; inode r/w 20452 <1> ; 20453 <1> ; ((AX = R1)) input 20454 <1> ; 20455 <1> ; (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM) 20456 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 20457 <1> ; 20458 00005776 0FB7D0 <1> movzx edx, ax 20459 00005779 6683C22F <1> add dx, 47 20460 0000577D 89D0 <1> mov eax, edx 20461 <1> ;add ax, 47 ; add 47 to inode number 20462 <1> ; add $31.,r1 / add 31. to i-number 20463 0000577F 50 <1> push eax 20464 <1> ; mov r1,-(sp) / save i+31. on stack 20465 00005780 66C1E804 <1> shr ax, 4 20466 <1> ; asr r1 / divide by 16. 20467 <1> ; asr r1 20468 <1> ; asr r1 20469 <1> ; asr r1 / r1 contains block number of block 20470 <1> ; / in which i-node exists 20471 00005784 E82A0A0000 <1> call dskrd 20472 <1> ; jsr r0,dskrd / read in block containing i-node i. 20473 <1> ; 31/07/2013 20474 00005789 803D[CC740000]00 <1> cmp byte [rw], 0 ; Retro Unix 8086 v1 feature ! 20475 <1> ;; 28/07/2013 rw -> u.rw 20476 <1> ;;cmp byte [u.rw], 0 ; Retro Unix 8086 v1 feature ! 20477 <1> ; tst (r0) 20478 00005790 7605 <1> jna short icalc_1 20479 <1> ; beq 1f / branch to wslot when argument 20480 <1> ; / in icalc call = 1 20481 <1> ; eAX = r1 = block number 20482 00005792 E87C0A0000 <1> call wslot 20483 <1> ; jsr r0,wslot / set up data buffer for write 20484 <1> ; / (will be same buffer as dskrd got) 20485 <1> ; eBX = r5 points to first word in data area for this block 20486 <1> icalc_1: ; 1: 20487 00005797 5A <1> pop edx 20488 00005798 83E20F <1> and edx, 0Fh ; (i+47) mod 16 20489 <1> ; bic $!17,(sp) / zero all but last 4 bits; 20490 <1> ; / gives (i+31.) mod 16 20491 0000579B C1E205 <1> shl edx, 5 20492 <1> ; eDX = 32 * ((i+47) mod 16) 20493 0000579E 89DE <1> mov esi, ebx ; ebx points 1st word of the buffer 20494 000057A0 01D6 <1> add esi, edx ; edx is inode offset in the buffer 20495 <1> ; eSI (r5) points to first word in i-node i. 20496 <1> ; mov (sp)+,mq / calculate offset in data buffer; 20497 <1> ; / 32.*(i+31.)mod16 20498 <1> ; mov $5,lsh / for i-node i. 20499 <1> ; add mq,r5 / r5 points to first word in i-node i. 20500 000057A2 BF[16710000] <1> mov edi, inode 20501 <1> ; mov $inode,r1 / inode is address of first word 20502 <1> ; / of current i-node 20503 000057A7 B908000000 <1> mov ecx, 8 ; 02/07/2015(32 bit modification) 20504 <1> ; mov $16.,r3 20505 <1> ; 31/07/2013 20506 000057AC 382D[CC740000] <1> cmp [rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 20507 <1> ;;28/07/2013 rw -> u.rw 20508 <1> ;;cmp [u.rw], ch ; 0 ;; Retro Unix 8086 v1 feature ! 20509 <1> ; tst (r0)+ / branch to 2f when argument in icalc call = 0 20510 000057B2 760A <1> jna short icalc_3 20511 <1> ; beq 2f / r0 now contains proper return address 20512 <1> ; / for rts r0 20513 <1> icalc_2: ; 1: 20514 000057B4 87F7 <1> xchg esi, edi 20515 <1> ; overwrite old i-node (in buffer to be written) 20516 000057B6 F3A5 <1> rep movsd 20517 <1> ; mov (r1)+,(r5)+ / over write old i-node 20518 <1> ; dec r3 20519 <1> ; bgt 1b 20520 000057B8 E8720A0000 <1> call dskwr 20521 <1> ; jsr r0,dskwr / write inode out on device 20522 000057BD C3 <1> retn 20523 <1> ; rts r0 20524 <1> icalc_3: ; 2: 20525 <1> ; copy new i-node into inode area of (core) memory 20526 000057BE F3A5 <1> rep movsd 20527 <1> ; mov (r5)+,(r1)+ / read new i-node into 20528 <1> ; / "inode" area of core 20529 <1> ; dec r3 20530 <1> ; bgt 2b 20531 000057C0 C3 <1> retn 20532 <1> ; rts r0 20533 <1> 20534 <1> access: 20535 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20536 <1> ; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1) 20537 <1> ; 20538 <1> ; check whether user is owner of file or user has read or write 20539 <1> ; permission (based on i.flgs). 20540 <1> ; 20541 <1> ; INPUTS -> 20542 <1> ; r1 - i-number of file 20543 <1> ; u.uid 20544 <1> ; arg0 -> (owner flag mask) 20545 <1> ; Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 20546 <1> ; OUTPUTS -> 20547 <1> ; inode (or jump to error) 20548 <1> ; 20549 <1> ; ((AX = R1)) input/output 20550 <1> ; 20551 <1> ; ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP)) 20552 <1> ; 20553 000057C1 6652 <1> push dx ; save flags (DL) 20554 000057C3 E81EFFFFFF <1> call iget 20555 <1> ; jsr r0,iget / read in i-node for current directory 20556 <1> ; / (i-number passed in r1) 20557 000057C8 8A0D[16710000] <1> mov cl, [i.flgs] 20558 <1> ; mov i.flgs,r2 20559 000057CE 665A <1> pop dx ; restore flags (DL) 20560 000057D0 8A35[94740000] <1> mov dh, [u.uid] 20561 000057D6 3A35[19710000] <1> cmp dh, [i.uid] 20562 <1> ; cmpb i.uid,u.uid / is user same as owner of file 20563 000057DC 7503 <1> jne short access_1 20564 <1> ; bne 1f / no, then branch 20565 000057DE C0E902 <1> shr cl, 2 20566 <1> ; asrb r2 / shift owner read write bits into non owner 20567 <1> ; / read/write bits 20568 <1> ; asrb r2 20569 <1> access_1: ; 1: 20570 000057E1 20D1 <1> and cl, dl 20571 <1> ; bit r2,(r0)+ / test read-write flags against argument 20572 <1> ; / in access call 20573 000057E3 7513 <1> jnz short access_2 20574 <1> ; bne 1f 20575 000057E5 08F6 <1> or dh, dh ; super user (root) ? 20576 <1> ; tstb u.uid 20577 000057E7 740F <1> jz short access_2 ; yes, super user 20578 <1> ;jnz error 20579 <1> ; beq 1f 20580 <1> ; jmp error 20581 000057E9 C705[9D740000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS 20582 000057F1 0000 <1> 20583 <1> ; 'permission denied !' error 20584 000057F3 E942E8FFFF <1> jmp error 20585 <1> 20586 <1> access_2: ; 1: 20587 <1> ; DL = flags 20588 000057F8 C3 <1> retn 20589 <1> ; rts r0 20590 <1> 20591 <1> setimod: 20592 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20593 <1> ; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1) 20594 <1> ; 20595 <1> ; 'setimod' sets byte at location 'imod' to 1; thus indicating that 20596 <1> ; the inode has been modified. Also puts the time of modification 20597 <1> ; into the inode. 20598 <1> ; 20599 <1> ; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM) 20600 <1> ; ((Modified registers: eDX, eCX, eBX)) 20601 <1> ; 20602 <1> 20603 <1> ; push edx 20604 000057F9 50 <1> push eax 20605 <1> 20606 000057FA C605[3C740000]01 <1> mov byte [imod], 1 20607 <1> ; movb $1,imod / set current i-node modified bytes 20608 <1> ; Erdogan Tan 14-7-2012 20609 00005801 E86FE3FFFF <1> call epoch 20610 <1> ; mov s.time,i.mtim 20611 <1> ; / put present time into file modified time 20612 <1> ; mov s.time+2,i.mtim+2 20613 <1> 20614 00005806 A3[30710000] <1> mov [i.mtim], eax 20615 <1> 20616 <1> ; Retro UNIX 386 v1 modification ! (cmp) 20617 <1> ; Retro UNIX 8086 v1 modification ! (test) 20618 0000580B 833D[2C710000]00 <1> cmp dword [i.ctim], 0 20619 00005812 7505 <1> jnz short setimod_ok 20620 <1> 20621 00005814 A3[2C710000] <1> mov [i.ctim], eax 20622 <1> 20623 <1> setimod_ok: ; 31/07/2013 20624 00005819 58 <1> pop eax 20625 <1> ;pop edx 20626 <1> 20627 0000581A C3 <1> retn 20628 <1> ; rts r0 20629 <1> 20630 <1> itrunc: 20631 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20632 <1> ; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1) 20633 <1> ; 20634 <1> ; 'itrunc' truncates a file whose i-number is given in r1 20635 <1> ; to zero length. 20636 <1> ; 20637 <1> ; INPUTS -> 20638 <1> ; r1 - i-number of i-node 20639 <1> ; i.dskp - pointer to contents or indirect block in an i-node 20640 <1> ; i.flgs - large file flag 20641 <1> ; i.size - size of file 20642 <1> ; 20643 <1> ; OUTPUTS -> 20644 <1> ; i.flgs - large file flag is cleared 20645 <1> ; i.size - set to 0 20646 <1> ; i.dskp .. i.dskp+16 - entire list is cleared 20647 <1> ; setimod - set to indicate i-node has been modified 20648 <1> ; r1 - i-number of i-node 20649 <1> ; 20650 <1> ; ((AX = R1)) input/output 20651 <1> ; 20652 <1> ; (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM) 20653 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 20654 <1> 20655 0000581B E8C6FEFFFF <1> call iget 20656 <1> ; jsr r0,iget 20657 00005820 BE[1C710000] <1> mov esi, i.dskp 20658 <1> ; mov $i.dskp,r2 / address of block pointers in r2 20659 00005825 31C0 <1> xor eax, eax 20660 <1> itrunc_1: ; 1: 20661 00005827 66AD <1> lodsw 20662 <1> ; mov (r2)+,r1 / move physical block number into r1 20663 00005829 6609C0 <1> or ax, ax 20664 0000582C 743B <1> jz short itrunc_5 20665 <1> ; beq 5f 20666 0000582E 56 <1> push esi 20667 <1> ; mov r2,-(sp) 20668 0000582F 66F705[16710000]00- <1> test word [i.flgs], 1000h 20669 00005837 10 <1> 20670 <1> ; bit $10000,i.flgs / test large file bit? 20671 00005838 7429 <1> jz short itrunc_4 20672 <1> ; beq 4f / if clear, branch 20673 0000583A 50 <1> push eax 20674 <1> ; mov r1,-(sp) / save block number of indirect block 20675 0000583B E873090000 <1> call dskrd 20676 <1> ; jsr r0,dskrd / read in block, 1st data word 20677 <1> ; / pointed to by r5 20678 <1> ; eBX = r5 = Buffer data address (the 1st word) 20679 00005840 B900010000 <1> mov ecx, 256 20680 <1> ; mov $256.,r3 / move word count into r3 20681 00005845 89DE <1> mov esi, ebx 20682 <1> itrunc_2: ; 2: 20683 00005847 66AD <1> lodsw 20684 <1> ; mov (r5)+,r1 / put 1st data word in r1; 20685 <1> ; / physical block number 20686 00005849 6621C0 <1> and ax, ax 20687 0000584C 7409 <1> jz short itrunc_3 20688 <1> ; beq 3f / branch if zero 20689 <1> ;push ecx 20690 0000584E 6651 <1> push cx 20691 <1> ; mov r3,-(sp) / save r3, r5 on stack 20692 <1> ;push esi 20693 <1> ; mov r5,-(sp) 20694 00005850 E842FEFFFF <1> call free 20695 <1> ; jsr r0,free / free block in free storage map 20696 <1> ;pop esi 20697 <1> ; mov(sp)+,r5 20698 00005855 6659 <1> pop cx 20699 <1> ;pop ecx 20700 <1> ; mov (sp)+,r3 20701 <1> itrunc_3: ; 3: 20702 00005857 E2EE <1> loop itrunc_2 20703 <1> ; dec r3 / decrement word count 20704 <1> ; bgt 2b / branch if positive 20705 00005859 58 <1> pop eax 20706 <1> ; mov (sp)+,r1 / put physical block number of 20707 <1> ; / indirect block 20708 <1> ; 01/08/2013 20709 0000585A 668125[16710000]FF- <1> and word [i.flgs], 0EFFFh ; 1110111111111111b 20710 00005862 EF <1> 20711 <1> itrunc_4: ; 4: 20712 00005863 E82FFEFFFF <1> call free 20713 <1> ; jsr r0,free / free indirect block 20714 00005868 5E <1> pop esi 20715 <1> ; mov (sp)+,r2 20716 <1> itrunc_5: ; 5: 20717 00005869 81FE[2C710000] <1> cmp esi, i.dskp+16 20718 <1> ; cmp r2,$i.dskp+16. 20719 0000586F 72B6 <1> jb short itrunc_1 20720 <1> ; bne 1b / branch until all i.dskp entries check 20721 <1> ; 01/08/2013 20722 <1> ;and word [i.flgs], 0EFFFh ; 1110111111111111b 20723 <1> ; bic $10000,i.flgs / clear large file bit 20724 00005871 BF[1C710000] <1> mov edi, i.dskp 20725 00005876 66B90800 <1> mov cx, 8 20726 0000587A 6631C0 <1> xor ax, ax 20727 0000587D 66A3[1A710000] <1> mov [i.size], ax ; 0 20728 <1> ; clr i.size / zero file size 20729 00005883 F366AB <1> rep stosw 20730 <1> ; jsr r0,copyz; i.dskp; i.dskp+16. 20731 <1> ; / zero block pointers 20732 00005886 E86EFFFFFF <1> call setimod 20733 <1> ; jsr r0,setimod / set i-node modified flag 20734 0000588B 66A1[2A740000] <1> mov ax, [ii] 20735 <1> ; mov ii,r1 20736 00005891 C3 <1> retn 20737 <1> ; rts r0 20738 <1> 20739 <1> imap: 20740 <1> ; 03/06/2015 (Retro UNIX 386 v1 - Beginning) 20741 <1> ; 26/04/2013 (Retro UNIX 8086 v1) 20742 <1> ; 20743 <1> ; 'imap' finds the byte in core (superblock) containing 20744 <1> ; allocation bit for an i-node whose number in r1. 20745 <1> ; 20746 <1> ; INPUTS -> 20747 <1> ; r1 - contains an i-number 20748 <1> ; fsp - start of table containing open files 20749 <1> ; 20750 <1> ; OUTPUTS -> 20751 <1> ; r2 - byte address of byte with the allocation bit 20752 <1> ; mq - a mask to locate the bit position. 20753 <1> ; (a 1 is in calculated bit posisiton) 20754 <1> ; 20755 <1> ; ((AX = R1)) input/output 20756 <1> ; ((DL/DX = MQ)) output 20757 <1> ; ((BX = R2)) output 20758 <1> ; 20759 <1> ; (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM) 20760 <1> ; ((Modified registers: eDX, eCX, eBX, eSI)) 20761 <1> ; 20762 <1> ; / get the byte that has the allocation bit for 20763 <1> ; / the i-number contained in r1 20764 <1> ;mov dx, 1 20765 00005892 B201 <1> mov dl, 1 20766 <1> ; mov $1,mq / put 1 in the mq 20767 00005894 0FB7D8 <1> movzx ebx, ax 20768 <1> ; mov r1,r2 / r2 now has i-number whose byte 20769 <1> ; / in the map we must find 20770 00005897 6683EB29 <1> sub bx, 41 20771 <1> ; sub $41.,r2 / r2 has i-41 20772 0000589B 88D9 <1> mov cl, bl 20773 <1> ; mov r2,r3 / r3 has i-41 20774 0000589D 80E107 <1> and cl, 7 20775 <1> ; bic $!7,r3 / r3 has (i-41) mod 8 to get 20776 <1> ; / the bit position 20777 000058A0 7402 <1> jz short imap1 20778 <1> ;shl dx, cl 20779 000058A2 D2E2 <1> shl dl, cl 20780 <1> ; mov r3,lsh / move the 1 over (i-41) mod 8 positions 20781 <1> imap1: ; / to the left to mask the correct bit 20782 000058A4 66C1EB03 <1> shr bx, 3 20783 <1> ; asr r2 20784 <1> ; asr r2 20785 <1> ; asr r2 / r2 has (i-41) base 8 of the byte number 20786 <1> ; / from the start of the map 20787 <1> ; mov r2,-(sp) / put (i-41) base 8 on the stack 20788 000058A8 BE[08810000] <1> mov esi, systm 20789 <1> ; mov $systm,r2 / r2 points to the in-core image of 20790 <1> ; / the super block for drum 20791 <1> ;cmp word [cdev], 0 20792 000058AD 803D[2E740000]00 <1> cmp byte [cdev], 0 20793 <1> ; tst cdev / is the device the disk 20794 000058B4 7606 <1> jna short imap2 20795 <1> ; beq 1f / yes 20796 000058B6 81C608020000 <1> add esi, mount - systm 20797 <1> ; add $mount-systm,r2 / for mounted device, 20798 <1> ; / r2 points to 1st word of its super block 20799 <1> imap2: ; 1: 20800 000058BC 66031E <1> add bx, [esi] ;; add free map size to si 20801 <1> ; add (r2)+,(sp) / get byte address of allocation bit 20802 000058BF 6683C304 <1> add bx, 4 20803 000058C3 01F3 <1> add ebx, esi 20804 <1> ; add (sp)+,r2 / ? 20805 <1> ;add ebx, 4 ;; inode map offset in superblock 20806 <1> ;; (2 + free map size + 2) 20807 <1> ; add $2,r2 / ? 20808 <1> ; DL/DX (MQ) has a 1 in the calculated bit position 20809 <1> ; BX (R2) has byte address of the byte with allocation bit 20810 000058C5 C3 <1> retn 20811 <1> ; rts r0 20812 %include 'u6.s' ; 31/05/2015 20813 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC 20814 <1> ; Last Modification: 18/11/2015 20815 <1> ; ---------------------------------------------------------------------------- 20816 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 20817 <1> ; (v0.1 - Beginning: 11/07/2012) 20818 <1> ; 20819 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 20820 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 20821 <1> ; 20822 <1> ; 20823 <1> ; 20824 <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s 20825 <1> ; 20826 <1> ; **************************************************************************** 20827 <1> 20828 <1> readi: 20829 <1> ; 20/05/2015 20830 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 20831 <1> ; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 20832 <1> ; 20833 <1> ; Reads from an inode whose number in R1 20834 <1> ; 20835 <1> ; INPUTS -> 20836 <1> ; r1 - inode number 20837 <1> ; u.count - byte count user desires 20838 <1> ; u.base - points to user buffer 20839 <1> ; u.fofp - points to word with current file offset 20840 <1> ; OUTPUTS -> 20841 <1> ; u.count - cleared 20842 <1> ; u.nread - accumulates total bytes passed back 20843 <1> ; 20844 <1> ; ((AX = R1)) input/output 20845 <1> ; (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM) 20846 <1> ; ((Modified registers: edx, ebx, ecx, esi, esi, ebp)) 20847 <1> 20848 000058C6 31D2 <1> xor edx, edx ; 0 20849 000058C8 8915[70740000] <1> mov [u.nread], edx ; 0 20850 <1> ; clr u.nread / accumulates number of bytes transmitted 20851 000058CE 668915[AD740000] <1> mov [u.pcount], dx ; 19/05/2015 20852 000058D5 3915[6C740000] <1> cmp [u.count], edx ; 0 20853 <1> ; tst u.count / is number of bytes to be read greater than 0 20854 000058DB 7701 <1> ja short readi_1 ; 1f 20855 <1> ; bgt 1f / yes, branch 20856 000058DD C3 <1> retn 20857 <1> ; rts r0 / no, nothing to read; return to caller 20858 <1> readi_1: ; 1: 20859 <1> ; mov r1,-(sp) / save i-number on stack 20860 000058DE 6683F828 <1> cmp ax, 40 20861 <1> ; cmp r1,$40. / want to read a special file 20862 <1> ; / (i-nodes 1,...,40 are for special files) 20863 000058E2 0F87D3000000 <1> ja dskr 20864 <1> ; ble 1f / yes, branch 20865 <1> ; jmp dskr / no, jmp to dskr; 20866 <1> ; / read file with i-node number (r1) 20867 <1> ; / starting at byte ((u.fofp)), read in u.count bytes 20868 <1> ; (20/05/2015) 20869 000058E8 50 <1> push eax ; because subroutines will jump to 'ret_' 20870 <1> ; 1: 20871 000058E9 0FB6D8 <1> movzx ebx, al 20872 000058EC 66C1E302 <1> shl bx, 2 20873 <1> ; asl r1 / multiply inode number by 2 20874 000058F0 81C3[F4580000] <1> add ebx, readi_2 - 4 20875 000058F6 FF23 <1> jmp dword [ebx] 20876 <1> ; jmp *1f-2(r1) 20877 <1> readi_2: ; 1: 20878 000058F8 [44590000] <1> dd rtty ; tty, AX = 1 (runix) 20879 <1> ;rtty / tty; r1=2 20880 <1> ;rppt / ppt; r1=4 20881 000058FC [97590000] <1> dd rmem ; mem, AX = 2 (runix) 20882 <1> ;rmem / mem; r1=6 20883 <1> ;rrf0 / rf0 20884 <1> ;rrk0 / rk0 20885 <1> ;rtap / tap0 20886 <1> ;rtap / tap1 20887 <1> ;rtap / tap2 20888 <1> ;rtap / tap3 20889 <1> ;rtap / tap4 20890 <1> ;rtap / tap5 20891 <1> ;rtap / tap6 20892 <1> ;rtap / tap7 20893 00005900 [59600000] <1> dd rfd ; fd0, AX = 3 (runix only) 20894 00005904 [59600000] <1> dd rfd ; fd1, AX = 4 (runix only) 20895 00005908 [59600000] <1> dd rhd ; hd0, AX = 5 (runix only) 20896 0000590C [59600000] <1> dd rhd ; hd1, AX = 6 (runix only) 20897 00005910 [59600000] <1> dd rhd ; hd2, AX = 7 (runix only) 20898 00005914 [59600000] <1> dd rhd ; hd3, AX = 8 (runix only) 20899 00005918 [AC590000] <1> dd rlpr ; lpr, AX = 9 (invalid, write only device !?) 20900 0000591C [93590000] <1> dd rcvt ; tty0, AX = 10 (runix) 20901 <1> ;rcvt / tty0 20902 00005920 [93590000] <1> dd rcvt ; tty1, AX = 11 (runix) 20903 <1> ;rcvt / tty1 20904 00005924 [93590000] <1> dd rcvt ; tty2, AX = 12 (runix) 20905 <1> ;rcvt / tty2 20906 00005928 [93590000] <1> dd rcvt ; tty3, AX = 13 (runix) 20907 <1> ;rcvt / tty3 20908 0000592C [93590000] <1> dd rcvt ; tty4, AX = 14 (runix) 20909 <1> ;rcvt / tty4 20910 00005930 [93590000] <1> dd rcvt ; tty5, AX = 15 (runix) 20911 <1> ;rcvt / tty5 20912 00005934 [93590000] <1> dd rcvt ; tty6, AX = 16 (runix) 20913 <1> ;rcvt / tty6 20914 00005938 [93590000] <1> dd rcvt ; tty7, AX = 17 (runix) 20915 <1> ;rcvt / tty7 20916 0000593C [93590000] <1> dd rcvt ; COM1, AX = 18 (runix only) 20917 <1> ;rcrd / crd 20918 00005940 [93590000] <1> dd rcvt ; COM2, AX = 19 (runix only) 20919 <1> 20920 <1> rtty: ; / read from console tty 20921 <1> ; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1) 20922 <1> ; (Only 1 byte is read, by ignoring byte count!) 20923 <1> ; WHAT FOR: Every character from Keyboard input 20924 <1> ; must be written immediate on video page (screen) 20925 <1> ; when it is required. 20926 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 20927 <1> ; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1) 20928 <1> ; 20929 <1> ; Console tty buffer is PC keyboard buffer 20930 <1> ; and keyboard-keystroke handling is different than original 20931 <1> ; unix (PDP-11) here. TTY/Keyboard procedures here are changed 20932 <1> ; according to IBM PC compatible ROM BIOS keyboard functions. 20933 <1> ; 20934 <1> ; 06/12/2013 20935 00005944 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 20936 0000594B 8A83[95710000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 20937 <1> rttys: 20938 <1> ; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of 20939 <1> ; / of the control and status block 20940 <1> ; tst 2(r5) / for the console tty; this word points to the console 20941 <1> ; / tty buffer 20942 <1> ; 28/07/2013 20943 00005951 A2[9C740000] <1> mov [u.ttyn], al 20944 <1> ; 13/01/2014 20945 00005956 FEC0 <1> inc al 20946 00005958 A2[78740000] <1> mov [u.ttyp], al ; tty number + 1 20947 <1> rtty_nc: ; 01/02/2014 20948 <1> ; 29/09/2013 20949 0000595D B90A000000 <1> mov ecx, 10 20950 <1> rtty_1: ; 01/02/2014 20951 00005962 6651 <1> push cx ; 29/09/2013 20952 <1> ; byte [u.ttyn] = tty number (0 to 9) 20953 00005964 B001 <1> mov al, 1 20954 00005966 E8330B0000 <1> call getc 20955 0000596B 6659 <1> pop cx ; 29/09/2013 20956 0000596D 7516 <1> jnz short rtty_2 20957 <1> ; bne 1f / 2nd word of console tty buffer contains number 20958 <1> ; / of chars. Is this number non-zero? 20959 0000596F E20D <1> loop rtty_idle ; 01/02/2014 20960 <1> ; 05/10/2013 20961 00005971 8A25[9C740000] <1> mov ah, [u.ttyn] 20962 <1> ; 29/09/2013 20963 00005977 E871FBFFFF <1> call sleep 20964 <1> ; jsr r0,canon; ttych / if 0, call 'canon' to get a line 20965 <1> ; / (120 chars.) 20966 <1> ;byte [u.ttyn] = tty number (0 to 9) 20967 0000597C EBDF <1> jmp short rtty_nc ; 01/02/2014 20968 <1> 20969 <1> rtty_idle: 20970 <1> ; 29/07/2013 20971 0000597E E8D6FAFFFF <1> call idle 20972 00005983 EBDD <1> jmp short rtty_1 ; 01/02/2014 20973 <1> ;1: 20974 <1> ; tst 2(r5) / is the number of characters zero 20975 <1> ; beq ret1 / yes, return to caller via 'ret1' 20976 <1> ; movb *4(r5),r1 / no, put character in r1 20977 <1> ; inc 4(r5) / 3rd word of console tty buffer points to byte which 20978 <1> ; / contains the next char. 20979 <1> ; dec 2(r5) / decrement the character count 20980 <1> rtty_2: 20981 00005985 30C0 <1> xor al, al 20982 00005987 E8120B0000 <1> call getc 20983 0000598C E892000000 <1> call passc 20984 <1> ; jsr r0,passc / move the character to core (user) 20985 <1> ;; 17/10/2015 - 16/07/2015 20986 <1> ; 19/06/2014 20987 <1> ;;jnz short rtty_nc 20988 00005991 58 <1> pop eax ; (20/05/2015) 20989 00005992 C3 <1> retn 20990 <1> ;ret1: 20991 <1> ; jmp ret / return to caller via 'ret' 20992 <1> 20993 <1> rcvt: ; < receive/read character from tty > 20994 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 20995 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 20996 <1> ; 20997 <1> ; Retro UNIX 8086 v1 modification ! 20998 <1> ; 20999 <1> ; In original UNIX v1, 'rcvt' routine 21000 <1> ; (exactly different than this one) 21001 <1> ; was in 'u9.s' file. 21002 <1> ; 21003 00005993 2C0A <1> sub al, 10 21004 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 21005 <1> ; 16/07/2013 21006 <1> ; 21/05/2013 21007 00005995 EBBA <1> jmp short rttys 21008 <1> 21009 <1> ;rppt: / read paper tape 21010 <1> ; jsr r0,pptic / gets next character in clist for ppt input and 21011 <1> ; / places 21012 <1> ; br ret / it in r1; if there 1s no problem with reader, it 21013 <1> ; / also enables read bit in prs 21014 <1> ; jsr r0,passc / place character in users buffer area 21015 <1> ; br rppt 21016 <1> 21017 <1> rmem: ; / transfer characters from memory to a user area of core 21018 <1> ; 17/10/2015 21019 <1> ; 11/06/2015 21020 <1> ; 24/05/2015 21021 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21022 <1> ; 21023 00005997 8B35[58740000] <1> mov esi, [u.fofp] 21024 <1> rmem_1: 21025 0000599D 8B1E <1> mov ebx, [esi] 21026 <1> ; mov *u.fofp,r1 / save file offset which points to the char 21027 <1> ; / to be transferred to user 21028 0000599F FF06 <1> inc dword [esi] ; 17/10/2015 21029 <1> ; inc *u.fofp / increment file offset to point to 'next' 21030 <1> ; / char in memory file 21031 000059A1 8A03 <1> mov al, [ebx] 21032 <1> ; movb (r1),r1 / get character from memory file, 21033 <1> ; / put it in r1 21034 000059A3 E87B000000 <1> call passc ; jsr r0,passc / move this character to 21035 <1> ; / the next byte of the users core area 21036 <1> ; br rmem / continue 21037 000059A8 75F3 <1> jnz short rmem_1 21038 <1> ret_: 21039 000059AA 58 <1> pop eax ; 09/06/2015 21040 000059AB C3 <1> retn 21041 <1> 21042 <1> rlpr: 21043 <1> ;1: 21044 <1> ;rcrd: 21045 000059AC C705[9D740000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 21046 000059B4 0000 <1> 21047 000059B6 E97FE6FFFF <1> jmp error 21048 <1> ;jmp error / see 'error' routine 21049 <1> 21050 <1> dskr: 21051 <1> ; 12/10/2015 21052 <1> ; 21/08/2015 21053 <1> ; 25/07/2015 21054 <1> ; 10/07/2015 21055 <1> ; 16/06/2015 21056 <1> ; 31/05/2015 21057 <1> ; 24/05/2015 (Retro UNIX 386 v1 - Beginning) 21058 <1> ; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1) 21059 <1> dskr_0: 21060 000059BB 50 <1> push eax 21061 <1> ; mov (sp),r1 / i-number in r1 21062 <1> ; AX = i-number 21063 000059BC E825FDFFFF <1> call iget 21064 <1> ; jsr r0,iget / get i-node (r1) into i-node section of core 21065 000059C1 0FB715[1A710000] <1> movzx edx, word [i.size] ; 16/06/2015 21066 <1> ; mov i.size,r2 / file size in bytes in r2 21067 000059C8 8B1D[58740000] <1> mov ebx, [u.fofp] 21068 000059CE 2B13 <1> sub edx, [ebx] 21069 <1> ; sub *u.fofp,r2 / subtract file offset 21070 <1> ; 12/10/2015 21071 <1> ; jna short ret_ 21072 <1> ; blos ret 21073 000059D0 7709 <1> ja short dskr_1 21074 <1> ; 21075 <1> dskr_retn: ; 12/10/2015 21076 000059D2 58 <1> pop eax 21077 000059D3 C605[AF740000]00 <1> mov byte [u.kcall], 0 21078 000059DA C3 <1> retn 21079 <1> dskr_1: 21080 000059DB 3B15[6C740000] <1> cmp edx, [u.count] 21081 <1> ; cmp r2,u.count / are enough bytes left in file 21082 <1> ; / to carry out read 21083 000059E1 7306 <1> jnb short dskr_2 21084 <1> ; bhis 1f 21085 000059E3 8915[6C740000] <1> mov [u.count], edx 21086 <1> ; mov r2,u.count / no, just read to end of file 21087 <1> dskr_2: ; 1: 21088 <1> ; AX = i-number 21089 000059E9 E885FBFFFF <1> call mget 21090 <1> ; jsr r0,mget / returns physical block number of block 21091 <1> ; / in file where offset points 21092 <1> ; eAX = physical block number 21093 000059EE E8C0070000 <1> call dskrd 21094 <1> ; jsr r0,dskrd / read in block, r5 points to 21095 <1> ; / 1st word of data in buffer 21096 <1> ; 09/06/2015 21097 000059F3 803D[AF740000]00 <1> cmp byte [u.kcall], 0 ; the caller is 'namei' sign (=1) 21098 000059FA 770F <1> ja short dskr_4 ; zf=0 -> the caller is 'namei' 21099 000059FC 66833D[AD740000]00 <1> cmp word [u.pcount], 0 21100 00005A04 7705 <1> ja short dskr_4 21101 <1> dskr_3: 21102 <1> ; [u.base] = virtual address to transfer (as destination address) 21103 00005A06 E853000000 <1> call trans_addr_w ; translate virtual address to physical (w) 21104 <1> dskr_4: 21105 <1> ; eBX (r5) = system (I/O) buffer address -physical- 21106 00005A0B E8C7020000 <1> call sioreg 21107 <1> ; jsr r0,sioreg 21108 00005A10 87F7 <1> xchg esi, edi 21109 <1> ; eDI = file (user data) offset 21110 <1> ; eSI = sector (I/O) buffer offset 21111 <1> ; eCX = byte count 21112 00005A12 F3A4 <1> rep movsb 21113 <1> ; movb (r2)+,(r1)+ / move data from buffer into working core 21114 <1> ; / starting at u.base 21115 <1> ; dec r3 21116 <1> ; bne 2b / branch until proper number of bytes are transferred 21117 <1> ; 25/07/2015 21118 <1> ; eax = remain bytes in buffer 21119 <1> ; (check if remain bytes in the buffer > [u.pcount]) 21120 00005A14 09C0 <1> or eax, eax 21121 00005A16 75EE <1> jnz short dskr_3 ; (page end before system buffer end!) 21122 <1> ; 03/08/2013 21123 <1> ;pop eax 21124 00005A18 390D[6C740000] <1> cmp [u.count], ecx ; 0 21125 <1> ; tst u.count / all bytes read off disk 21126 <1> ; bne dskr 21127 <1> ; br ret 21128 <1> ;ja short dskr_0 21129 <1> ;mov [u.kcall], cl ; 0 ; 09/06/2015 21130 <1> ;retn 21131 <1> ; 12/10/2015 21132 00005A1E 76B2 <1> jna short dskr_retn 21133 00005A20 58 <1> pop eax ; (i-node number) 21134 00005A21 EB98 <1> jmp short dskr_0 21135 <1> 21136 <1> passc: 21137 <1> ; 18/10/2015 21138 <1> ; 10/07/2015 21139 <1> ; 01/07/2015 21140 <1> ; 08/06/2015 21141 <1> ; 04/06/2015 21142 <1> ; 20/05/2015 21143 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21144 <1> ; 21145 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 21146 <1> ; to physical address 21147 00005A23 66833D[AD740000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 21148 <1> ; 1-4095 --> use previous physical base address 21149 <1> ; in [u.pbase] 21150 00005A2B 7705 <1> ja short passc_3 21151 <1> ; 08/06/2015 - 10/07/2015 21152 00005A2D E82C000000 <1> call trans_addr_w 21153 <1> passc_3: 21154 <1> ; 19/05/2015 21155 00005A32 66FF0D[AD740000] <1> dec word [u.pcount] 21156 <1> ; 21157 00005A39 8B1D[A9740000] <1> mov ebx, [u.pbase] 21158 00005A3F 8803 <1> mov [ebx], al 21159 <1> ; movb r1,*u.base / move a character to the next byte of the 21160 <1> ; / users buffer 21161 00005A41 FF05[68740000] <1> inc dword [u.base] 21162 <1> ; inc u.base / increment the pointer to point to 21163 <1> ; / the next byte in users buffer 21164 00005A47 FF05[A9740000] <1> inc dword [u.pbase] ; 04/06/2015 21165 00005A4D FF05[70740000] <1> inc dword [u.nread] 21166 <1> ; inc u.nread / increment the number of bytes read 21167 00005A53 FF0D[6C740000] <1> dec dword [u.count] 21168 <1> ; dec u.count / decrement the number of bytes to be read 21169 <1> ; bne 1f / any more bytes to read?; yes, branch 21170 00005A59 C3 <1> retn 21171 <1> ; mov (sp)+,r0 / no, do a non-local return to the caller of 21172 <1> ; / 'readi' by: 21173 <1> ;/ (1) pop the return address off the stack into r0 21174 <1> ; mov (sp)+,r1 / (2) pop the i-number off the stack into r1 21175 <1> ;1: 21176 <1> ; clr *$ps / clear processor status 21177 <1> ; rts r0 / return to address currently on top of stack 21178 <1> 21179 <1> trans_addr_r: 21180 <1> ; Translate virtual address to physical address 21181 <1> ; for reading from user's memory space 21182 <1> ; (Retro UNIX 386 v1 feature only !) 21183 <1> ; 18/10/2015 21184 <1> ; 10/07/2015 21185 <1> ; 09/06/2015 21186 <1> ; 08/06/2015 21187 <1> ; 04/06/2015 21188 <1> ; 21189 <1> ; 18/10/2015 21190 00005A5A 31D2 <1> xor edx, edx ; 0 (read access sign) 21191 00005A5C EB04 <1> jmp short trans_addr_rw 21192 <1> 21193 <1> ;push eax 21194 <1> ;push ebx 21195 <1> ;mov ebx, [u.base] 21196 <1> ;call get_physical_addr ; get physical address 21197 <1> ;;jnc short cpass_0 21198 <1> ;jnc short passc_1 21199 <1> ;mov [u.error], eax 21200 <1> ;;pop ebx 21201 <1> ;;pop eax 21202 <1> ;jmp error 21203 <1> ;cpass_0: 21204 <1> ; 18/10/2015 21205 <1> ; 20/05/2015 21206 <1> ;mov [u.pbase], eax ; physical address 21207 <1> ;mov [u.pcount], cx ; remain byte count in page (1-4096) 21208 <1> ;pop ebx 21209 <1> ;pop eax 21210 <1> ;retn ; 08/06/2015 21211 <1> 21212 <1> trans_addr_w: 21213 <1> ; Translate virtual address to physical address 21214 <1> ; for writing to user's memory space 21215 <1> ; (Retro UNIX 386 v1 feature only !) 21216 <1> ; 18/10/2015 21217 <1> ; 29/07/2015 21218 <1> ; 10/07/2015 21219 <1> ; 09/06/2015 21220 <1> ; 08/06/2015 21221 <1> ; 04/06/2015 (passc) 21222 <1> ; 21223 <1> ; 18/10/2015 21224 00005A5E 29D2 <1> sub edx, edx 21225 00005A60 FEC2 <1> inc dl ; 1 (write access sign) 21226 <1> trans_addr_rw: 21227 00005A62 50 <1> push eax 21228 00005A63 53 <1> push ebx 21229 <1> ; 18/10/2015 21230 00005A64 52 <1> push edx ; r/w sign (in DL) 21231 <1> ; 21232 00005A65 8B1D[68740000] <1> mov ebx, [u.base] 21233 00005A6B E818DCFFFF <1> call get_physical_addr ; get physical address 21234 00005A70 730A <1> jnc short passc_0 21235 00005A72 A3[9D740000] <1> mov [u.error], eax 21236 <1> ;pop edx 21237 <1> ;pop ebx 21238 <1> ;pop eax 21239 00005A77 E9BEE5FFFF <1> jmp error 21240 <1> passc_0: 21241 00005A7C F6C202 <1> test dl, PTE_A_WRITE ; writable page ; 18/10/2015 21242 00005A7F 5A <1> pop edx ; 18/10/2015 21243 00005A80 751C <1> jnz short passc_1 21244 <1> ; 18/10/2015 21245 00005A82 20D2 <1> and dl, dl 21246 00005A84 7418 <1> jz short passc_1 21247 <1> ; 20/05/2015 21248 <1> ; read only (duplicated) page -must be copied to a new page- 21249 <1> ; EBX = linear address 21250 00005A86 51 <1> push ecx 21251 00005A87 E811D9FFFF <1> call copy_page 21252 00005A8C 59 <1> pop ecx 21253 00005A8D 721E <1> jc short passc_2 21254 00005A8F 50 <1> push eax ; physical address of the new/allocated page 21255 00005A90 E81DDBFFFF <1> call add_to_swap_queue 21256 00005A95 58 <1> pop eax 21257 <1> ; 18/10/2015 21258 00005A96 81E3FF0F0000 <1> and ebx, PAGE_OFF ; 0FFFh 21259 <1> ;mov ecx, PAGE_SIZE 21260 <1> ;sub ecx, ebx 21261 00005A9C 01D8 <1> add eax, ebx 21262 <1> passc_1: 21263 <1> ; 18/10/2015 21264 <1> ; 20/05/2015 21265 00005A9E A3[A9740000] <1> mov [u.pbase], eax ; physical address 21266 00005AA3 66890D[AD740000] <1> mov [u.pcount], cx ; remain byte count in page (1-4096) 21267 00005AAA 5B <1> pop ebx 21268 00005AAB 58 <1> pop eax 21269 00005AAC C3 <1> retn ; 08/06/2015 21270 <1> passc_2: 21271 00005AAD C705[9D740000]0100- <1> mov dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error 21272 00005AB5 0000 <1> 21273 <1> ;pop ebx 21274 <1> ;pop eax 21275 00005AB7 E97EE5FFFF <1> jmp error 21276 <1> 21277 <1> writei: 21278 <1> ; 20/05/2015 21279 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21280 <1> ; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1) 21281 <1> ; 21282 <1> ; Write data to file with inode number in R1 21283 <1> ; 21284 <1> ; INPUTS -> 21285 <1> ; r1 - inode number 21286 <1> ; u.count - byte count to be written 21287 <1> ; u.base - points to user buffer 21288 <1> ; u.fofp - points to word with current file offset 21289 <1> ; OUTPUTS -> 21290 <1> ; u.count - cleared 21291 <1> ; u.nread - accumulates total bytes passed back 21292 <1> ; ((AX = R1)) 21293 <1> ; (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM) 21294 <1> ; ((Modified registers: DX, BX, CX, SI, DI, BP)) 21295 <1> 21296 00005ABC 31C9 <1> xor ecx, ecx 21297 00005ABE 890D[70740000] <1> mov [u.nread], ecx ; 0 21298 <1> ; clr u.nread / clear the number of bytes transmitted during 21299 <1> ; / read or write calls 21300 00005AC4 66890D[AD740000] <1> mov [u.pcount], cx ; 19/05/2015 21301 00005ACB 390D[6C740000] <1> cmp [u.count], ecx 21302 <1> ; ; tst u.count / test the byte count specified by the user 21303 00005AD1 7701 <1> ja short writei_1 ; 1f 21304 <1> ; bgt 1f / any bytes to output; yes, branch 21305 00005AD3 C3 <1> retn 21306 <1> ; ; rts r0 / no, return - no writing to do 21307 <1> writei_1: ;1: 21308 <1> ; mov r1 ,-(sp) / save the i-node number on the stack 21309 00005AD4 6683F828 <1> cmp ax, 40 21310 <1> ; cmp r1,$40. 21311 <1> ; / does the i-node number indicate a special file? 21312 00005AD8 0F87F2000000 <1> ja dskw 21313 <1> ; bgt dskw / no, branch to standard file output 21314 <1> ; (20/05/2015) 21315 00005ADE 50 <1> push eax ; because subroutines will jump to 'ret_' 21316 00005ADF 0FB6D8 <1> movzx ebx, al 21317 00005AE2 66C1E302 <1> shl bx, 2 21318 <1> ; asl r1 / yes, calculate the index into the special file 21319 00005AE6 81C3[EA5A0000] <1> add ebx, writei_2 - 4 21320 00005AEC FF23 <1> jmp dword [ebx] 21321 <1> ; jmp *1f-2(r1) 21322 <1> ; / jump table and jump to the appropriate routine 21323 <1> writei_2: ;1: 21324 00005AEE [3A5B0000] <1> dd wtty ; tty, AX = 1 (runix) 21325 <1> ;wtty / tty; r1=2 21326 <1> ;wppt / ppt; r1=4 21327 00005AF2 [A05B0000] <1> dd wmem ; mem, AX = 2 (runix) 21328 <1> ;wmem / mem; r1=6 21329 <1> ;wrf0 / rf0 21330 <1> ;wrk0 / rk0 21331 <1> ;wtap / tap0 21332 <1> ;wtap / tap1 21333 <1> ;wtap / tap2 21334 <1> ;wtap / tap3 21335 <1> ;wtap / tap4 21336 <1> ;wtap / tap5 21337 <1> ;wtap / tap6 21338 <1> ;wtap / tap7 21339 00005AF6 [DB600000] <1> dd wfd ; fd0, AX = 3 (runix only) 21340 00005AFA [DB600000] <1> dd wfd ; fd1, AX = 4 (runix only) 21341 00005AFE [DB600000] <1> dd whd ; hd0, AX = 5 (runix only) 21342 00005B02 [DB600000] <1> dd whd ; hd1, AX = 6 (runix only) 21343 00005B06 [DB600000] <1> dd whd ; hd2, AX = 7 (runix only) 21344 00005B0A [DB600000] <1> dd whd ; hd3, AX = 8 (runix only) 21345 00005B0E [915B0000] <1> dd wlpr ; lpr, AX = 9 (runix) 21346 00005B12 [8B5B0000] <1> dd xmtt ; tty0, AX = 10 (runix) 21347 <1> ;xmtt / tty0 21348 00005B16 [8B5B0000] <1> dd xmtt ; tty1, AX = 11 (runix) 21349 <1> ;xmtt / tty1 21350 00005B1A [8B5B0000] <1> dd xmtt ; tty2, AX = 12 (runix) 21351 <1> ;xmtt / tty2 21352 00005B1E [8B5B0000] <1> dd xmtt ; tty3, AX = 13 (runix) 21353 <1> ;xmtt / tty3 21354 00005B22 [8B5B0000] <1> dd xmtt ; tty4, AX = 14 (runix) 21355 <1> ;xmtt / tty4 21356 00005B26 [8B5B0000] <1> dd xmtt ; tty5, AX = 15 (runix) 21357 <1> ;xmtt / tty5 21358 00005B2A [8B5B0000] <1> dd xmtt ; tty6, AX = 16 (runix) 21359 <1> ;xmtt / tty6 21360 00005B2E [8B5B0000] <1> dd xmtt ; tty7, AX = 17 (runix) 21361 <1> ;xmtt / tty7 21362 00005B32 [8B5B0000] <1> dd xmtt ; COM1, AX = 18 (runix only) 21363 <1> ; / wlpr / lpr 21364 00005B36 [8B5B0000] <1> dd xmtt ; COM2, AX = 19 (runix only) 21365 <1> 21366 <1> wtty: ; write to console tty (write to screen) 21367 <1> ; 18/11/2015 21368 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21369 <1> ; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1) 21370 <1> ; 21371 <1> ; Console tty output is on current video page 21372 <1> ; Console tty character output procedure is changed here 21373 <1> ; acconding to IBM PC compatible ROM BIOS video (text mode) functions. 21374 <1> ; 21375 00005B3A 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 21376 00005B41 8AA3[95710000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 21377 00005B47 88E0 <1> mov al, ah ; 07/07/2014 21378 <1> wttys: 21379 <1> ; 10/10/2013 21380 00005B49 8825[9C740000] <1> mov [u.ttyn], ah 21381 <1> ; 13/01/2014 21382 00005B4F FEC0 <1> inc al 21383 00005B51 A2[79740000] <1> mov [u.ttyp+1], al ; tty number + 1 21384 <1> wtty_nc: ; 15/05/2013 21385 <1> ; AH = [u.ttyn] = tty number ; 28/07/2013 21386 00005B56 E81C010000 <1> call cpass 21387 <1> ; jsr r0,cpass / get next character from user buffer area; if 21388 <1> ; / none go to return address in syswrite 21389 <1> ; tst r1 / is character = null 21390 <1> ; beq wtty / yes, get next character 21391 <1> ; 10/10/2013 21392 00005B5B 742C <1> jz short wret 21393 <1> ;1 : 21394 <1> ;mov $240,*$ps / no, set processor priority to five 21395 <1> ;cmpb cc+1,$20. / is character count for console tty greater 21396 <1> ; / than 20 21397 <1> ;bhis 2f / yes; branch to put process to sleep 21398 <1> ; 27/06/2014 21399 <1> wtty_1: 21400 <1> ; AH = tty number 21401 <1> ; AL = ASCII code of the character 21402 <1> ; 15/04/2014 21403 00005B5D 6650 <1> push ax 21404 00005B5F E8A80A0000 <1> call putc ; 14/05/2013 21405 00005B64 731F <1> jnc short wtty_2 21406 <1> ; 18/11/2015 21407 00005B66 E8EEF8FFFF <1> call idle 21408 00005B6B 668B0424 <1> mov ax, [esp] 21409 00005B6F E8980A0000 <1> call putc 21410 00005B74 730F <1> jnc short wtty_2 21411 <1> ; 02/06/2014 21412 00005B76 8A25[9C740000] <1> mov ah, [u.ttyn] 21413 00005B7C E86CF9FFFF <1> call sleep 21414 00005B81 6658 <1> pop ax 21415 00005B83 EBD8 <1> jmp short wtty_1 21416 <1> ; jc error ; 15/05/2013 (COM1 or COM2 serial port error) 21417 <1> ; jsr r0,putc; 1 / find place in freelist to assign to 21418 <1> ; / console tty and 21419 <1> ; br 2f / place character in list; if none available 21420 <1> ; / branch to put process to sleep 21421 <1> ; jsr r0,startty / attempt to output character on tty 21422 <1> wtty_2: 21423 <1> ; 15/04/2014 21424 00005B85 6658 <1> pop ax 21425 00005B87 EBCD <1> jmp short wtty_nc 21426 <1> ; br wtty 21427 <1> wret: ; 10/10/2013 (20/05/2015) 21428 00005B89 58 <1> pop eax 21429 00005B8A C3 <1> retn 21430 <1> ;2: 21431 <1> ;mov r1,-(sp) / place character on stack 21432 <1> ;jsr r0,sleep; 1 / put process to sleep 21433 <1> ;mov (sp)+,r1 / remove character from stack 21434 <1> ;br 1b / try again to place character in clist and output 21435 <1> 21436 <1> xmtt: ; < send/write character to tty > 21437 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21438 <1> ; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1) 21439 <1> ; 21440 <1> ; Retro UNIX 8086 v1 modification ! 21441 <1> ; 21442 <1> ; In original UNIX v1, 'xmtt' routine 21443 <1> ; (exactly different than this one) 21444 <1> ; was in 'u9.s' file. 21445 <1> ; 21446 00005B8B 2C0A <1> sub al, 10 21447 <1> ; AL = tty number (0 to 9), (COM1=8, COM2=9) 21448 <1> ; 10/10/2013 21449 00005B8D 88C4 <1> mov ah, al 21450 <1> ; 28/07/2013 21451 00005B8F EBB8 <1> jmp short wttys 21452 <1> 21453 <1> ;wppt: 21454 <1> ; jsr r0,cpass / get next character from user buffer area, 21455 <1> ; / if none return to writei's calling routine 21456 <1> ; jsr r0,pptoc / output character on ppt 21457 <1> ; br wppt 21458 <1> wlpr: 21459 00005B91 C705[9D740000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015 21460 00005B99 0000 <1> 21461 00005B9B E99AE4FFFF <1> jmp error ; ... Printing procedure will be located here ... 21462 <1> ;/ jsr r0,cpass 21463 <1> ;/ cmp r0,$'a 21464 <1> ;/ blo 1f 21465 <1> ;/ cmp r1,$'z 21466 <1> ;/ bhi 1f 21467 <1> ;/ sub $40,r1 21468 <1> ;/1: 21469 <1> ;/ jsr r0,lptoc 21470 <1> ;/ br wlpr 21471 <1> ; br rmem / continue 21472 <1> 21473 <1> wmem: ; / transfer characters from a user area of core to memory file 21474 <1> ; 17/10/2015 21475 <1> ; 11/06/2015 21476 <1> ; 24/05/2015 21477 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21478 <1> ; 21479 00005BA0 813D[D8070000]- <1> cmp dword [x_timer], clock ; multi tasking clock/timer 21480 00005BA6 [7D540000] <1> 21481 00005BAA 7415 <1> je short wmem_acc_err 21482 <1> ; 21483 00005BAC 8B35[58740000] <1> mov esi, [u.fofp] 21484 <1> wmem_1: 21485 00005BB2 E8C0000000 <1> call cpass 21486 <1> ; jsr r0,cpass / get next character from users area of 21487 <1> ; / core and put it in r1 21488 <1> ; mov r1,-(sp) / put character on the stack 21489 <1> ; 20/09/2013 21490 00005BB7 74D0 <1> jz short wret ; wmem_2 21491 00005BB9 8B1E <1> mov ebx, [esi] 21492 <1> ; mov *u.fofp,r1 / save file offset in r1 21493 00005BBB FF06 <1> inc dword [esi] ; 17/10/2015 21494 <1> ; inc *u.fofp / increment file offset to point to next 21495 <1> ; / available location in file 21496 00005BBD 8803 <1> mov [ebx], al 21497 <1> ; movb (sp)+,(r1) / pop char off stack, put in memory loc 21498 <1> ; / assigned to it 21499 00005BBF EBF1 <1> jmp short wmem_1 21500 <1> ; br wmem / continue 21501 <1> ;1: 21502 <1> ;jmp error / ? 21503 <1> ;wmem_2: 21504 <1> ; ; 20/09/2013 21505 <1> ; pop ax 21506 <1> ; retn 21507 <1> 21508 <1> wmem_acc_err: 21509 00005BC1 C705[9D740000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 21510 00005BC9 0000 <1> 21511 00005BCB E96AE4FFFF <1> jmp error 21512 <1> 21513 <1> 21514 <1> dskw: ; / write routine for non-special files 21515 <1> ; 21516 <1> ; 25/07/2015 21517 <1> ; 16/06/2015 21518 <1> ; 09/06/2015 21519 <1> ; 31/05/2015 (Retro UNIX 386 v1 - Beginning) 21520 <1> ; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1) 21521 <1> ; 21522 <1> ; 01/08/2013 (mkdir_w check) 21523 00005BD0 6650 <1> push ax ; 26/04/2013 21524 <1> ; mov (sp),r1 / get an i-node number from the stack into r1 21525 <1> ; AX = inode number 21526 00005BD2 E80FFBFFFF <1> call iget 21527 <1> ; jsr r0,iget / write i-node out (if modified), 21528 <1> ; / read i-node 'r1' into i-node area of core 21529 00005BD7 8B1D[58740000] <1> mov ebx, [u.fofp] 21530 00005BDD 8B13 <1> mov edx, [ebx] 21531 <1> ; mov *u.fofp,r2 / put the file offset [(u.off) or the offset 21532 <1> ; / in the fsp entry for this file] in r2 21533 00005BDF 0315[6C740000] <1> add edx, [u.count] 21534 <1> ; add u.count,r2 / no. of bytes to be written 21535 <1> ; / + file offset is put in r2 21536 <1> ; 16/06/2015 21537 00005BE5 81FAFFFF0000 <1> cmp edx, 65535 ; file size limit (for UNIX v1 file system) 21538 00005BEB 760F <1> jna short dskw_0 21539 00005BED C705[9D740000]1400- <1> mov dword [u.error], ERR_FILE_SIZE ; 'file size error !' 21540 00005BF5 0000 <1> 21541 00005BF7 E93EE4FFFF <1> jmp error 21542 <1> dskw_0: 21543 00005BFC 663B15[1A710000] <1> cmp dx, [i.size] 21544 <1> ; cmp r2,i.size / is this greater than the present size of 21545 <1> ; / the file? 21546 00005C03 760C <1> jna short dskw_1 21547 <1> ; blos 1f / no, branch 21548 00005C05 668915[1A710000] <1> mov [i.size], dx 21549 <1> ; mov r2,i.size / yes, increase the file size to 21550 <1> ; / file offset + no. of data bytes 21551 00005C0C E8E8FBFFFF <1> call setimod 21552 <1> ; jsr r0,setimod / set imod=1 (i.e., core inode has been 21553 <1> ; / modified), stuff time of modification into 21554 <1> ; / core image of i-node 21555 <1> dskw_1: ; 1: 21556 00005C11 E85DF9FFFF <1> call mget 21557 <1> ; eAX = Block number 21558 <1> ; jsr r0,mget / get the block no. in which to write 21559 <1> ; / the next data byte 21560 <1> ; eax = block number 21561 00005C16 8B1D[58740000] <1> mov ebx, [u.fofp] 21562 00005C1C 8B13 <1> mov edx, [ebx] 21563 00005C1E 81E2FF010000 <1> and edx, 1FFh 21564 <1> ; bit *u.fofp,$777 / test the lower 9 bits of the file offset 21565 00005C24 750C <1> jnz short dskw_2 21566 <1> ; bne 2f / if its non-zero, branch; if zero, file offset = 0, 21567 <1> ; / 512, 1024,...(i.e., start of new block) 21568 00005C26 813D[6C740000]0002- <1> cmp dword [u.count], 512 21569 00005C2E 0000 <1> 21570 <1> ; cmp u.count,$512. / if zero, is there enough data to fill 21571 <1> ; / an entire block? (i.e., no. of 21572 00005C30 7305 <1> jnb short dskw_3 21573 <1> ; bhis 3f / bytes to be written greater than 512.? 21574 <1> ; / Yes, branch. Don't have to read block 21575 <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be 21576 <1> ; / overwritten). 21577 00005C32 E87C050000 <1> call dskrd 21578 <1> ; jsr r0,dskrd / no, must retain old info.. 21579 <1> ; / Hence, read block 'r1' into an I/O buffer 21580 <1> dskw_3: ; 3: 21581 <1> ; eAX (r1) = block/sector number 21582 00005C37 E8D7050000 <1> call wslot 21583 <1> ; jsr r0,wslot / set write and inhibit bits in I/O queue, 21584 <1> ; / proc. status=0, r5 points to 1st word of data 21585 00005C3C 803D[AF740000]00 <1> cmp byte [u.kcall], 0 21586 00005C43 770F <1> ja short dskw_5 ; zf=0 -> the caller is 'mkdir' 21587 <1> ; 21588 00005C45 66833D[AD740000]00 <1> cmp word [u.pcount], 0 21589 00005C4D 7705 <1> ja short dskw_5 21590 <1> dskw_4: 21591 <1> ; [u.base] = virtual address to transfer (as source address) 21592 00005C4F E806FEFFFF <1> call trans_addr_r ; translate virtual address to physical (r) 21593 <1> dskw_5: 21594 <1> ; eBX (r5) = system (I/O) buffer address 21595 00005C54 E87E000000 <1> call sioreg 21596 <1> ; jsr r0,sioreg / r3 = no. of bytes of data, 21597 <1> ; / r1 = address of data, r2 points to location 21598 <1> ; / in buffer in which to start writing data 21599 <1> ; eSI = file (user data) offset 21600 <1> ; eDI = sector (I/O) buffer offset 21601 <1> ; eCX = byte count 21602 <1> ; 21603 00005C59 F3A4 <1> rep movsb 21604 <1> ; movb (r1 )+,(r2)+ 21605 <1> ; / transfer a byte of data to the I/O buffer 21606 <1> ; dec r3 / decrement no. of bytes to be written 21607 <1> ; bne 2b / have all bytes been transferred? No, branch 21608 <1> ; 25/07/2015 21609 <1> ; eax = remain bytes in buffer 21610 <1> ; (check if remain bytes in the buffer > [u.pcount]) 21611 00005C5B 09C0 <1> or eax, eax 21612 00005C5D 75F0 <1> jnz short dskw_4 ; (page end before system buffer end!) 21613 <1> dskw_6: 21614 00005C5F E8CB050000 <1> call dskwr 21615 <1> ; jsr r0,dskwr / yes, write the block and the i-node 21616 00005C64 833D[6C740000]00 <1> cmp dword [u.count], 0 21617 <1> ; tst u.count / any more data to write? 21618 00005C6B 77A4 <1> ja short dskw_1 21619 <1> ; bne 1b / yes, branch 21620 <1> ; 03/08/2013 21621 00005C6D C605[AF740000]00 <1> mov byte [u.kcall], 0 21622 <1> ; 20/09/2013 (;;) 21623 00005C74 6658 <1> pop ax 21624 00005C76 C3 <1> retn 21625 <1> ;;jmp short dskw_ret 21626 <1> ; jmp ret / no, return to the caller via 'ret' 21627 <1> 21628 <1> cpass: ; / get next character from user area of core and put it in r1 21629 <1> ; 18/10/2015 21630 <1> ; 10/10/2015 21631 <1> ; 10/07/2015 21632 <1> ; 02/07/2015 21633 <1> ; 01/07/2015 21634 <1> ; 24/06/2015 21635 <1> ; 08/06/2015 21636 <1> ; 04/06/2015 21637 <1> ; 20/05/2015 21638 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21639 <1> ; 21640 <1> ; INPUTS -> 21641 <1> ; [u.base] = virtual address in user area 21642 <1> ; [u.count] = byte count (max.) 21643 <1> ; [u.pcount] = byte count in page (0 = reset) 21644 <1> ; OUTPUTS -> 21645 <1> ; AL = the character which is pointed by [u.base] 21646 <1> ; zf = 1 -> transfer count has been completed 21647 <1> ; 21648 <1> ; ((Modified registers: EAX, EDX, ECX)) 21649 <1> ; 21650 <1> ; 21651 00005C77 833D[6C740000]00 <1> cmp dword [u.count], 0 ; 14/08/2013 21652 <1> ; tst u.count / have all the characters been transferred 21653 <1> ; / (i.e., u.count, # of chars. left 21654 00005C7E 763F <1> jna short cpass_3 21655 <1> ; beq 1f / to be transferred = 0?) yes, branch 21656 00005C80 FF0D[6C740000] <1> dec dword [u.count] 21657 <1> ; dec u.count / no, decrement u.count 21658 <1> ; 19/05/2015 21659 <1> ;(Retro UNIX 386 v1 - translation from user's virtual address 21660 <1> ; to physical address 21661 00005C86 66833D[AD740000]00 <1> cmp word [u.pcount], 0 ; byte count in page = 0 (initial value) 21662 <1> ; 1-4095 --> use previous physical base address 21663 <1> ; in [u.pbase] 21664 00005C8E 770E <1> ja short cpass_1 21665 <1> ; 02/07/2015 21666 00005C90 833D[A5740000]00 <1> cmp dword [u.ppgdir], 0 ; is the caller os kernel 21667 00005C97 7427 <1> je short cpass_k ; (sysexec, '/etc/init') ? 21668 <1> ; 08/06/2015 - 10/07/2015 21669 00005C99 E8BCFDFFFF <1> call trans_addr_r 21670 <1> cpass_1: 21671 <1> ; 02/07/2015 21672 <1> ; 24/06/2015 21673 00005C9E 66FF0D[AD740000] <1> dec word [u.pcount] 21674 <1> cpass_2: 21675 <1> ;10/10/2015 21676 <1> ; 02/07/2015 21677 00005CA5 8B15[A9740000] <1> mov edx, [u.pbase] 21678 00005CAB 8A02 <1> mov al, [edx] ; 10/10/2015 21679 <1> ; movb *u.base,r1 / take the character pointed to 21680 <1> ; / by u.base and put it in r1 21681 00005CAD FF05[70740000] <1> inc dword [u.nread] 21682 <1> ; inc u.nread / increment no. of bytes transferred 21683 00005CB3 FF05[68740000] <1> inc dword [u.base] 21684 <1> ; inc u.base / increment the buffer address to point to the 21685 <1> ; / next byte 21686 00005CB9 FF05[A9740000] <1> inc dword [u.pbase] ; 04/06/2015 21687 <1> cpass_3: 21688 00005CBF C3 <1> retn 21689 <1> ; rts r0 / next byte 21690 <1> ; 1: 21691 <1> ; mov (sp)+,r0 21692 <1> ; / put return address of calling routine into r0 21693 <1> ; mov (sp)+,r1 / i-number in r1 21694 <1> ; rts r0 / non-local return 21695 <1> cpass_k: 21696 <1> ; 02/07/2015 21697 <1> ; The caller is os kernel 21698 <1> ; (get sysexec arguments from kernel's memory space) 21699 <1> ; 21700 00005CC0 8B1D[68740000] <1> mov ebx, [u.base] 21701 00005CC6 66C705[AD740000]00- <1> mov word [u.pcount], PAGE_SIZE ; 4096 21702 00005CCE 10 <1> 21703 00005CCF 891D[A9740000] <1> mov [u.pbase], ebx 21704 00005CD5 EBCE <1> jmp short cpass_2 21705 <1> 21706 <1> sioreg: 21707 <1> ; 25/07/2015 21708 <1> ; 18/07/2015 21709 <1> ; 02/07/2015 21710 <1> ; 17/06/2015 21711 <1> ; 09/06/2015 21712 <1> ; 19/05/2015 (Retro UNIX 386 v1 - Beginning) 21713 <1> ; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1) 21714 <1> ; 21715 <1> ; INPUTS -> 21716 <1> ; eBX = system buffer (data) address (r5) 21717 <1> ; [u.fofp] = pointer to file offset pointer 21718 <1> ; [u.base] = virtual address of the user buffer 21719 <1> ; [u.pbase] = physical address of the user buffer 21720 <1> ; [u.count] = byte count 21721 <1> ; [u.pcount] = byte count within page frame 21722 <1> ; OUTPUTS -> 21723 <1> ; eSI = user data offset (r1) 21724 <1> ; eDI = system (I/O) buffer offset (r2) 21725 <1> ; eCX = byte count (r3) 21726 <1> ; EAX = remain bytes after byte count within page frame 21727 <1> ; (If EAX > 0, transfer will continue from the next page) 21728 <1> ; 21729 <1> ; ((Modified registers: EDX)) 21730 <1> 21731 00005CD7 8B35[58740000] <1> mov esi, [u.fofp] 21732 00005CDD 8B3E <1> mov edi, [esi] 21733 <1> ; mov *u.fofp,r2 / file offset (in bytes) is moved to r2 21734 00005CDF 89F9 <1> mov ecx, edi 21735 <1> ; mov r2,r3 / and also to r3 21736 00005CE1 81C900FEFFFF <1> or ecx, 0FFFFFE00h 21737 <1> ; bis $177000,r3 / set bits 9,...,15 of file offset in r3 21738 00005CE7 81E7FF010000 <1> and edi, 1FFh 21739 <1> ; bic $!777,r2 / calculate file offset mod 512. 21740 00005CED 01DF <1> add edi, ebx ; EBX = system buffer (data) address 21741 <1> ; add r5,r2 / r2 now points to 1st byte in system buffer 21742 <1> ; / where data is to be placed 21743 <1> ; mov u.base,r1 / address of data is in r1 21744 00005CEF F7D9 <1> neg ecx 21745 <1> ; neg r3 / 512 - file offset (mod512.) in r3 21746 <1> ; / (i.e., the no. of free bytes in the file block) 21747 00005CF1 3B0D[6C740000] <1> cmp ecx, [u.count] 21748 <1> ; cmp r3,u.count / compare this with the no. of data bytes 21749 <1> ; / to be written to the file 21750 00005CF7 7606 <1> jna short sioreg_0 21751 <1> ; blos 2f / if less than branch. Use the no. of free bytes 21752 <1> ; / in the file block as the number to be written 21753 00005CF9 8B0D[6C740000] <1> mov ecx, [u.count] 21754 <1> ; mov u.count,r3 / if greater than, use the no. of data 21755 <1> ; / bytes as the number to be written 21756 <1> sioreg_0: 21757 <1> ; 17/06/2015 21758 00005CFF 803D[AF740000]00 <1> cmp byte [u.kcall], 0 21759 00005D06 7613 <1> jna short sioreg_1 21760 <1> ; 25/07/2015 21761 <1> ; the caller is 'mkdir' or 'namei' 21762 00005D08 A1[68740000] <1> mov eax, [u.base] ; 25/07/2015 21763 00005D0D A3[A9740000] <1> mov [u.pbase], eax ; physical address = virtual address 21764 00005D12 66890D[AD740000] <1> mov word [u.pcount], cx ; remain bytes in buffer (1 sector) 21765 00005D19 EB0B <1> jmp short sioreg_2 21766 <1> sioreg_1: 21767 <1> ; 25/07/2015 21768 <1> ; 18/07/2015 21769 <1> ; 09/06/2015 21770 00005D1B 0FB715[AD740000] <1> movzx edx, word [u.pcount] 21771 <1> ; ecx and [u.pcount] are always > 0, here 21772 00005D22 39D1 <1> cmp ecx, edx 21773 00005D24 772A <1> ja short sioreg_4 ; transfer count > [u.pcount] 21774 <1> sioreg_2: ; 2: 21775 00005D26 31C0 <1> xor eax, eax ; 25/07/2015 21776 <1> sioreg_3: 21777 00005D28 010D[70740000] <1> add [u.nread], ecx 21778 <1> ; add r3,u.nread / r3 + number of bytes xmitted 21779 <1> ; / during write is put into u.nread 21780 00005D2E 290D[6C740000] <1> sub [u.count], ecx 21781 <1> ; sub r3,u.count / u.count = no. of bytes that still 21782 <1> ; / must be written or read 21783 00005D34 010D[68740000] <1> add [u.base], ecx 21784 <1> ; add r3,u.base / u.base points to the 1st of the remaining 21785 <1> ; / data bytes 21786 00005D3A 010E <1> add [esi], ecx 21787 <1> ; add r3,*u.fofp / new file offset = number of bytes done 21788 <1> ; / + old file offset 21789 <1> ; 25/07/2015 21790 00005D3C 8B35[A9740000] <1> mov esi, [u.pbase] 21791 00005D42 66290D[AD740000] <1> sub [u.pcount], cx 21792 00005D49 010D[A9740000] <1> add [u.pbase], ecx 21793 00005D4F C3 <1> retn 21794 <1> ; rts r0 21795 <1> ; transfer count > [u.pcount] 21796 <1> sioreg_4: 21797 <1> ; 25/07/2015 21798 <1> ; transfer count > [u.pcount] 21799 <1> ; (ecx > edx) 21800 00005D50 89C8 <1> mov eax, ecx 21801 00005D52 29D0 <1> sub eax, edx ; remain bytes for 1 sector (block) transfer 21802 00005D54 89D1 <1> mov ecx, edx ; current transfer count = [u.pcount] 21803 00005D56 EBD0 <1> jmp short sioreg_3 21804 %include 'u7.s' ; 18/04/2015 21805 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC 21806 <1> ; Last Modification: 14/11/2015 21807 <1> ; ---------------------------------------------------------------------------- 21808 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 21809 <1> ; (v0.1 - Beginning: 11/07/2012) 21810 <1> ; 21811 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 21812 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 21813 <1> ; 21814 <1> ; 21815 <1> ; 21816 <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s 21817 <1> ; 21818 <1> ; **************************************************************************** 21819 <1> 21820 <1> sysmount: ; / mount file system; args special; name 21821 <1> ; 14/11/2015 21822 <1> ; 24/10/2015 21823 <1> ; 13/10/2015 21824 <1> ; 10/07/2015 21825 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 21826 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 21827 <1> ; 21828 <1> ; 'sysmount' anounces to the system that a removable 21829 <1> ; file system has been mounted on a special file. 21830 <1> ; The device number of the special file is obtained via 21831 <1> ; a call to 'getspl'. It is put in the I/O queue entry for 21832 <1> ; dismountable file system (sb1) and the I/O queue entry is 21833 <1> ; set up to read (bit 10 is set). 'ppoke' is then called to 21834 <1> ; to read file system into core, i.e. the first block on the 21835 <1> ; mountable file system is read in. This block is super block 21836 <1> ; for the file system. This call is super user restricted. 21837 <1> ; 21838 <1> ; Calling sequence: 21839 <1> ; sysmount; special; name 21840 <1> ; Arguments: 21841 <1> ; special - pointer to name of special file (device) 21842 <1> ; name - pointer to name of the root directory of the 21843 <1> ; newly mounted file system. 'name' should 21844 <1> ; always be a directory. 21845 <1> ; Inputs: - 21846 <1> ; Outputs: - 21847 <1> ; ............................................................... 21848 <1> ; 21849 <1> ; Retro UNIX 8086 v1 modification: 21850 <1> ; 'sysmount' system call has two arguments; so, 21851 <1> ; * 1st argument, special is pointed to by BX register 21852 <1> ; * 2nd argument, name is in CX register 21853 <1> ; 21854 <1> ; NOTE: Device numbers, names and related procedures are 21855 <1> ; already modified for IBM PC compatibility and 21856 <1> ; Retro UNIX 8086 v1 device configuration. 21857 <1> 21858 <1> ;call arg2 21859 <1> ; jsr r0,arg2 / get arguments special and name 21860 00005D58 891D[60740000] <1> mov [u.namep], ebx 21861 00005D5E 51 <1> push ecx ; directory name 21862 00005D5F 66833D[34740000]00 <1> cmp word [mnti], 0 21863 <1> ; tst mnti / is the i-number of the cross device file 21864 <1> ; / zero? 21865 <1> ;ja error 21866 <1> ; bne errora / no, error 21867 00005D67 0F87E9000000 <1> ja sysmnt_err0 21868 <1> ; 21869 00005D6D E8CC000000 <1> call getspl 21870 <1> ; jsr r0,getspl / get special files device number in r1 21871 <1> ; 13/10/2015 21872 00005D72 0FB7D8 <1> movzx ebx, ax ; ; Retro UNIX 8086 v1 device number (0 to 5) 21873 00005D75 F683[6A6B0000]80 <1> test byte [ebx+drv.status], 80h ; 24/10/2015 21874 00005D7C 750F <1> jnz short sysmnt_1 21875 <1> sysmnt_err1: 21876 00005D7E C705[9D740000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY ; drive not ready ! 21877 00005D86 0000 <1> 21878 00005D88 E9ADE2FFFF <1> jmp error 21879 <1> sysmnt_1: 21880 00005D8D 8F05[60740000] <1> pop dword [u.namep] 21881 <1> ; mov (sp)+,u.namep / put the name of file to be placed 21882 <1> ; / on the device 21883 <1> ; 14/11/2015 21884 00005D93 53 <1> push ebx ; 13/10/2015 21885 <1> ; mov r1,-(sp) / save the device number 21886 <1> ; 21887 00005D94 E85DF1FFFF <1> call namei 21888 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 21889 <1> ; ax = 0 -> file not found 21890 <1> ;jz error 21891 <1> ;jc error 21892 <1> ; jsr r0,namei / get the i-number of the file 21893 <1> ; br errora 21894 00005D99 730F <1> jnc short sysmnt_2 21895 <1> sysmnt_err2: 21896 00005D9B C705[9D740000]0C00- <1> mov dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready ! 21897 00005DA3 0000 <1> 21898 00005DA5 E990E2FFFF <1> jmp error 21899 <1> sysmnt_2: 21900 00005DAA 66A3[34740000] <1> mov [mnti], ax 21901 <1> ; mov r1,mnti / put it in mnti 21902 <1> ; mov ebx, sb1 ; super block buffer (of mounted disk) 21903 <1> sysmnt_3: ;1: 21904 <1> ;cmp byte [ebx+1], 0 21905 <1> ; tstb sb1+1 / is 15th bit of I/O queue entry for 21906 <1> ; / dismountable device set? 21907 <1> ;jna short sysmnt_4 21908 <1> ; bne 1b / (inhibit bit) yes, skip writing 21909 <1> ;call idle ; (wait for hardware interrupt) 21910 <1> ;jmp short sysmnt_3 21911 <1> sysmnt_4: 21912 00005DB0 58 <1> pop eax ; Retro UNIX 8086 v1 device number/ID (0 to 5) 21913 00005DB1 A2[31740000] <1> mov [mdev], al 21914 <1> ; mov (sp),mntd / no, put the device number in mntd 21915 00005DB6 8803 <1> mov [ebx], al 21916 <1> ; movb (sp),sb1 / put the device number in the lower byte 21917 <1> ; / of the I/O queue entry 21918 <1> ;mov byte [cdev], 1 ; mounted device/drive 21919 <1> ; mov (sp)+,cdev / put device number in cdev 21920 00005DB8 66810B0004 <1> or word [ebx], 400h ; Bit 10, 'read' flag/bit 21921 <1> ; bis $2000,sb1 / set the read bit 21922 <1> ; Retro UNIX 386 v1 modification : 21923 <1> ; 32 bit block number at buffer header offset 4 21924 00005DBD C7430401000000 <1> mov dword [ebx+4], 1 ; physical block number = 1 21925 00005DC4 E8A3050000 <1> call diskio 21926 00005DC9 731C <1> jnc short sysmnt_5 21927 00005DCB 31C0 <1> xor eax, eax 21928 00005DCD 66A3[34740000] <1> mov [mnti], ax ; 0 21929 00005DD3 A2[31740000] <1> mov [mdev], al ; 0 21930 <1> ;mov [cdev], al ; 0 21931 <1> sysmnt_invd: 21932 <1> ; 14/11/2015 21933 00005DD8 FEC8 <1> dec al 21934 00005DDA 8903 <1> mov [ebx], eax ; 000000FFh 21935 00005DDC FEC0 <1> inc al 21936 00005DDE 48 <1> dec eax 21937 00005DDF 894304 <1> mov [ebx+4], eax ; 0FFFFFFFFh 21938 00005DE2 E953E2FFFF <1> jmp error 21939 <1> sysmnt_5: 21940 <1> ; 14/11/2015 (Retro UNIX 386 v1 modification) 21941 <1> ; (Following check is needed to prevent mounting an 21942 <1> ; in valid valid file system (in valid super block). 21943 <1> ; 21944 00005DE7 0FB603 <1> movzx eax, byte [ebx] ; device number 21945 00005DEA C0E002 <1> shl al, 2 ; 4*index 21946 00005DED 8B88[4E6B0000] <1> mov ecx, [eax+drv.size] ; volume (fs) size 21947 00005DF3 C1E103 <1> shl ecx, 3 21948 00005DF6 0FB715[0C830000] <1> movzx edx, word [sb1+4] ; the 1st data word 21949 00005DFD 39D1 <1> cmp ecx, edx ; compare free map bits and volume size 21950 <1> ; (in sectors), if they are not equal 21951 <1> ; the disk to be mounted is an... 21952 00005DFF 75D7 <1> jne short sysmnt_invd ; invalid disk ! 21953 <1> ; (which has not got a valid super block) 21954 <1> ; 21955 00005E01 C6430100 <1> mov byte [ebx+1], 0 21956 <1> ; jsr r0,ppoke / read in entire file system 21957 <1> ;sysmnt_6: ;1: 21958 <1> ;;cmp byte [sb1+1], 0 21959 <1> ; tstb sb1+1 / done reading? 21960 <1> ;;jna sysret 21961 <1> ;;call idle ; (wait for hardware interrupt) 21962 <1> ;;jmp short sysmnt_6 21963 <1> ;bne 1b / no, wait 21964 <1> ;br sysreta / yes 21965 00005E05 E950E2FFFF <1> jmp sysret 21966 <1> 21967 <1> sysumount: ; / special dismount file system 21968 <1> ; 16/05/2015 (Retro UNIX 386 v1 - Beginning) 21969 <1> ; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1) 21970 <1> ; 21971 <1> ; 04/11/2013 21972 <1> ; 09/07/2013 21973 <1> ; 'sysumount' anounces to the system that the special file, 21974 <1> ; indicated as an argument is no longer contain a removable 21975 <1> ; file system. 'getspl' gets the device number of the special 21976 <1> ; file. If no file system was mounted on that device an error 21977 <1> ; occurs. 'mntd' and 'mnti' are cleared and control is passed 21978 <1> ; to 'sysret'. 21979 <1> ; 21980 <1> ; Calling sequence: 21981 <1> ; sysmount; special 21982 <1> ; Arguments: 21983 <1> ; special - special file to dismount (device) 21984 <1> ; 21985 <1> ; Inputs: - 21986 <1> ; Outputs: - 21987 <1> ; ............................................................... 21988 <1> ; 21989 <1> ; Retro UNIX 8086 v1 modification: 21990 <1> ; 'sysumount' system call has one argument; so, 21991 <1> ; * Single argument, special is pointed to by BX register 21992 <1> ; 21993 <1> 21994 <1> ;mov ax, 1 ; one/single argument, put argument in BX 21995 <1> ;call arg 21996 <1> ; jsr r0,arg; u.namep / point u.namep to special 21997 00005E0A 891D[60740000] <1> mov [u.namep], ebx 21998 00005E10 E829000000 <1> call getspl 21999 <1> ; jsr r0,getspl / get the device number in r1 22000 00005E15 3A05[31740000] <1> cmp al, [mdev] 22001 <1> ; cmp r1,mntd / is it equal to the last device mounted? 22002 00005E1B 7539 <1> jne short sysmnt_err0 ; 'permission denied !' error 22003 <1> ;jne error 22004 <1> ; bne errora / no error 22005 00005E1D 30C0 <1> xor al, al ; ah = 0 22006 <1> sysumnt_0: ;1: 22007 00005E1F 3805[09830000] <1> cmp [sb1+1], al ; 0 22008 <1> ; tstb sb1+1 / yes, is the device still doing I/O 22009 <1> ; / (inhibit bit set)? 22010 00005E25 7607 <1> jna short sysumnt_1 22011 <1> ; bne 1b / yes, wait 22012 00005E27 E82DF6FFFF <1> call idle ; (wait for hardware interrupt) 22013 00005E2C EBF1 <1> jmp short sysumnt_0 22014 <1> sysumnt_1: 22015 00005E2E A2[31740000] <1> mov [mdev], al 22016 <1> ; clr mntd / no, clear these 22017 00005E33 66A3[34740000] <1> mov [mnti], ax 22018 <1> ; clr mnti 22019 00005E39 E91CE2FFFF <1> jmp sysret 22020 <1> ; br sysreta / return 22021 <1> 22022 <1> getspl: ; / get device number from a special file name 22023 00005E3E E8B3F0FFFF <1> call namei 22024 <1> ;or ax, ax ; Retro UNIX 8086 v1 modification ! 22025 <1> ; ax = 0 -> file not found 22026 00005E43 0F8252FFFFFF <1> jc sysmnt_err2 ; 'file not found !' error 22027 <1> ;jz error 22028 <1> ;jc error 22029 <1> ; jsr r0,namei / get the i-number of the special file 22030 <1> ; br errora / no such file 22031 00005E49 6683E803 <1> sub ax, 3 ; Retro UNIX 8086 v1 modification ! 22032 <1> ; i-number-3, 0 = fd0, 5 = hd3 22033 <1> ; sub $4,r1 / i-number-4 rk=1,tap=2+n 22034 00005E4D 7207 <1> jc short sysmnt_err0 ; 'permission denied !' error 22035 <1> ;jc error 22036 <1> ; ble errora / less than 0? yes, error 22037 00005E4F 6683F805 <1> cmp ax, 5 ; 22038 <1> ; cmp r1,$9. / greater than 9 tap 7 22039 00005E53 7701 <1> ja short sysmnt_err0 ; 'permission denied !' error 22040 <1> ;ja error 22041 <1> ; bgt errora / yes, error 22042 <1> ; AX = Retro UNIX 8086 v1 Device Number (0 to 5) 22043 <1> iopen_retn: 22044 00005E55 C3 <1> retn 22045 <1> ; rts r0 / return with device number in r1 22046 <1> sysmnt_err0: 22047 00005E56 C705[9D740000]0B00- <1> mov dword [u.error], ERR_FILE_ACCESS ; permission denied ! 22048 00005E5E 0000 <1> 22049 00005E60 E9D5E1FFFF <1> jmp error 22050 <1> iopen: 22051 <1> ; 19/05/2015 22052 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 22053 <1> ; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1) 22054 <1> ; 22055 <1> ; open file whose i-number is in r1 22056 <1> ; 22057 <1> ; INPUTS -> 22058 <1> ; r1 - inode number 22059 <1> ; OUTPUTS -> 22060 <1> ; file's inode in core 22061 <1> ; r1 - inode number (positive) 22062 <1> ; 22063 <1> ; ((AX = R1)) 22064 <1> ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 22065 <1> ; 22066 <1> ; / open file whose i-number is in r1 22067 00005E65 F6C480 <1> test ah, 80h ; Bit 15 of AX 22068 <1> ;tst r1 / write or read access? 22069 00005E68 756A <1> jnz short iopen_2 22070 <1> ;blt 2f / write, go to 2f 22071 00005E6A B202 <1> mov dl, 2 ; read access 22072 00005E6C E850F9FFFF <1> call access 22073 <1> ; jsr r0,access; 2 22074 <1> ; / get inode into core with read access 22075 <1> ; DL=2 22076 <1> iopen_0: 22077 00005E71 6683F828 <1> cmp ax, 40 22078 <1> ; cmp r1,$40. / is it a special file 22079 00005E75 77DE <1> ja short iopen_retn 22080 <1> ;bgt 3f / no. 3f 22081 00005E77 6650 <1> push ax 22082 <1> ; mov r1,-(sp) / yes, figure out 22083 00005E79 0FB6D8 <1> movzx ebx, al 22084 00005E7C 66C1E302 <1> shl bx, 2 22085 <1> ; asl r1 22086 00005E80 81C3[845E0000] <1> add ebx, iopen_1 - 4 22087 00005E86 FF23 <1> jmp dword [ebx] 22088 <1> ; jmp *1f-2(r1) / which one and transfer to it 22089 <1> iopen_1: ; 1: 22090 00005E88 [EE5E0000] <1> dd otty ; tty, AX = 1 (runix) 22091 <1> ;otty / tty ; r1=2 22092 <1> ;oppt / ppt ; r1=4 22093 00005E8C [8B5F0000] <1> dd sret ; mem, AX = 2 (runix) 22094 <1> ;sret / mem ; r1=6 22095 <1> ;sret / rf0 22096 <1> ;sret / rk0 22097 <1> ;sret / tap0 22098 <1> ;sret / tap1 22099 <1> ;sret / tap2 22100 <1> ;sret / tap3 22101 <1> ;sret / tap4 22102 <1> ;sret / tap5 22103 <1> ;sret / tap6 22104 <1> ;sret / tap7 22105 00005E90 [8B5F0000] <1> dd sret ; fd0, AX = 3 (runix only) 22106 00005E94 [8B5F0000] <1> dd sret ; fd1, AX = 4 (runix only) 22107 00005E98 [8B5F0000] <1> dd sret ; hd0, AX = 5 (runix only) 22108 00005E9C [8B5F0000] <1> dd sret ; hd1, AX = 6 (runix only) 22109 00005EA0 [8B5F0000] <1> dd sret ; hd2, AX = 7 (runix only) 22110 00005EA4 [8B5F0000] <1> dd sret ; hd3, AX = 8 (runix only) 22111 <1> ;dd error ; lpr, AX = 9 (error !) 22112 00005EA8 [8B5F0000] <1> dd sret ; lpr, AX = 9 (runix) 22113 00005EAC [FD5E0000] <1> dd ocvt ; tty0, AX = 10 (runix) 22114 <1> ;ocvt / tty0 22115 00005EB0 [FD5E0000] <1> dd ocvt ; tty1, AX = 11 (runix) 22116 <1> ;ocvt / tty1 22117 00005EB4 [FD5E0000] <1> dd ocvt ; tty2, AX = 12 (runix) 22118 <1> ;ocvt / tty2 22119 00005EB8 [FD5E0000] <1> dd ocvt ; tty3, AX = 13 (runix) 22120 <1> ;ocvt / tty3 22121 00005EBC [FD5E0000] <1> dd ocvt ; tty4, AX = 14 (runix) 22122 <1> ;ocvt / tty4 22123 00005EC0 [FD5E0000] <1> dd ocvt ; tty5, AX = 15 (runix) 22124 <1> ;ocvt / tty5 22125 00005EC4 [FD5E0000] <1> dd ocvt ; tty6, AX = 16 (runix) 22126 <1> ;ocvt / tty6 22127 00005EC8 [FD5E0000] <1> dd ocvt ; tty7, AX = 17 (runix) 22128 <1> ;ocvt / tty7 22129 00005ECC [FD5E0000] <1> dd ocvt ; COM1, AX = 18 (runix only) 22130 <1> ;error / crd 22131 00005ED0 [FD5E0000] <1> dd ocvt ; COM2, AX = 19 (runix only) 22132 <1> 22133 <1> iopen_2: ; 2: / check open write access 22134 00005ED4 66F7D8 <1> neg ax 22135 <1> ;neg r1 / make inode number positive 22136 00005ED7 B201 <1> mov dl, 1 ; write access 22137 00005ED9 E8E3F8FFFF <1> call access 22138 <1> ;jsr r0,access; 1 / get inode in core 22139 <1> ; DL=1 22140 00005EDE 66F705[16710000]00- <1> test word [i.flgs], 4000h ; Bit 14 : Directory flag 22141 00005EE6 40 <1> 22142 <1> ;bit $40000,i.flgs / is it a directory? 22143 00005EE7 7488 <1> jz short iopen_0 22144 <1> ;mov [u.error], ERR_DIR_ACCESS 22145 <1> ;jmp error ; permission denied ! 22146 00005EE9 E968FFFFFF <1> jmp sysmnt_err0 22147 <1> ;;jnz error 22148 <1> ; bne 2f / yes, transfer (error) 22149 <1> ;;jmp short iopen_0 22150 <1> ;cmp ax, 40 22151 <1> ; cmp r1,$40. / no, is it a special file? 22152 <1> ;ja short iopen_2 22153 <1> ;bgt 3f / no, return 22154 <1> ;push ax 22155 <1> ;mov r1,-(sp) / yes 22156 <1> ;movzx ebx, al 22157 <1> ;shl bx, 1 22158 <1> ; asl r1 22159 <1> ;add ebx, ipen_3 - 2 22160 <1> ;jmp dword [ebx] 22161 <1> ; jmp *1f-2(r1) / figure out 22162 <1> ; / which special file it is and transfer 22163 <1> ;iopen_3: ; 1: 22164 <1> ; dd otty ; tty, AX = 1 (runix) 22165 <1> ;otty / tty ; r1=2 22166 <1> ;leadr / ppt ; r1=4 22167 <1> ; dd sret ; mem, AX = 2 (runix) 22168 <1> ;sret / mem ; r1=6 22169 <1> ;sret / rf0 22170 <1> ;sret / rk0 22171 <1> ;sret / tap0 22172 <1> ;sret / tap1 22173 <1> ;sret / tap2 22174 <1> ;sret / tap3 22175 <1> ;sret / tap4 22176 <1> ;sret / tap5 22177 <1> ;sret / tap6 22178 <1> ;sret / tap7 22179 <1> ; dd sret ; fd0, AX = 3 (runix only) 22180 <1> ; dd sret ; fd1, AX = 4 (runix only) 22181 <1> ; dd sret ; hd0, AX = 5 (runix only) 22182 <1> ; dd sret ; hd1, AX = 6 (runix only) 22183 <1> ; dd sret ; hd2, AX = 7 (runix only) 22184 <1> ; dd sret ; hd3, AX = 8 (runix only) 22185 <1> ; dd sret ; lpr, AX = 9 (runix) 22186 <1> ;dd ejec ; lpr, AX = 9 (runix) 22187 <1> ; dd sret ; tty0, AX = 10 (runix) 22188 <1> ;ocvt / tty0 22189 <1> ; dd sret ; tty1, AX = 11 (runix) 22190 <1> ;ocvt / tty1 22191 <1> ; dd sret ; tty2, AX = 12 (runix) 22192 <1> ;ocvt / tty2 22193 <1> ; dd sret ; tty3, AX = 13 (runix) 22194 <1> ;ocvt / tty3 22195 <1> ; dd sret ; tty4, AX = 14 (runix) 22196 <1> ;ocvt / tty4 22197 <1> ; dd sret ; tty5, AX = 15 (runix) 22198 <1> ;ocvt / tty5 22199 <1> ; dd sret ; tty6, AX = 16 (runix) 22200 <1> ;ocvt / tty6 22201 <1> ; dd sret ; tty7, AX = 17 (runix) 22202 <1> ;ocvt / tty7 22203 <1> ; dd ocvt ; COM1, AX = 18 (runix only) 22204 <1> ;/ ejec / lpr 22205 <1> ; dd ocvt ; COM2, AX = 19 (runix only) 22206 <1> 22207 <1> 22208 <1> otty: ;/ open console tty for reading or writing 22209 <1> ; 16/11/2015 22210 <1> ; 12/11/2015 22211 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 22212 <1> ; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1) 22213 <1> ; 16/07/2013 22214 <1> ; Retro UNIX 8086 v1 modification: 22215 <1> ; If a tty is open for read or write by 22216 <1> ; a process (u.uno), only same process can open 22217 <1> ; same tty to write or read (R->R&W or W->W&R). 22218 <1> ; 22219 <1> ; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty) 22220 <1> ; 22221 00005EEE 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 22222 00005EF5 8A83[95710000] <1> mov al, [ebx+p.ttyc-1] ; current/console tty 22223 <1> ; 13/01/2014 22224 00005EFB EB02 <1> jmp short ottyp 22225 <1> ocvt: 22226 00005EFD 2C0A <1> sub al, 10 22227 <1> ottyp: 22228 <1> ; 16/11/2015 22229 <1> ; 12/11/2015 22230 <1> ; 18/05/2015 (32 bit modifications) 22231 <1> ; 06/12/2013 - 13/07/2014 22232 00005EFF 88C6 <1> mov dh, al ; tty number 22233 00005F01 0FB6D8 <1> movzx ebx, al ; AL = tty number (0 to 9), AH = 0 22234 00005F04 D0E3 <1> shl bl, 1 ; aligned to word 22235 <1> ;26/01/2014 22236 00005F06 81C3[B4700000] <1> add ebx, ttyl 22237 00005F0C 668B0B <1> mov cx, [ebx] 22238 <1> ; CL = lock value (0 or process number) 22239 <1> ; CH = open count 22240 00005F0F 20C9 <1> and cl, cl 22241 <1> ; 13/01/2014 22242 00005F11 7439 <1> jz short otty_ret 22243 <1> ; 22244 <1> ; 16/11/2015 22245 00005F13 3A0D[97740000] <1> cmp cl, [u.uno] 22246 00005F19 745C <1> je short ottys_3 22247 <1> ; 22248 00005F1B 0FB6D9 <1> movzx ebx, cl ; the process which has locked the tty 22249 00005F1E D0E3 <1> shl bl, 1 22250 00005F20 668B83[34710000] <1> mov ax, [ebx+p.pid-2] 22251 <1> ;movzx ebx, byte [u.uno] 22252 00005F27 8A1D[97740000] <1> mov bl, [u.uno] 22253 00005F2D D0E3 <1> shl bl, 1 22254 00005F2F 663B83[54710000] <1> cmp ax, [ebx+p.ppid-2] 22255 00005F36 743F <1> je short ottys_3 ; 16/11/2015 22256 <1> ; 22257 <1> ; the tty is locked by another process 22258 <1> ; except the parent process (p.ppid) 22259 <1> ; 22260 00005F38 C705[9D740000]0B00- <1> mov dword [u.error], ERR_DEV_ACCESS 22261 00005F40 0000 <1> 22262 <1> ; permission denied ! error 22263 <1> otty_err: ; 13/01/2014 22264 00005F42 08D2 <1> or dl, dl ; DL = 0 -> called by sysstty 22265 00005F44 0F85F0E0FFFF <1> jnz error 22266 00005F4A F9 <1> stc 22267 00005F4B C3 <1> retn 22268 <1> otty_ret: 22269 <1> ; 13/01/2014 22270 00005F4C 80FE07 <1> cmp dh, 7 22271 00005F4F 761C <1> jna short ottys_2 22272 <1> ; 16/11/2015 22273 <1> com_port_check: 22274 00005F51 BE[D2700000] <1> mov esi, com1p 22275 00005F56 80FE08 <1> cmp dh, 8 ; COM1 (tty8) ? 22276 00005F59 7601 <1> jna short ottys_1 ; yes, it is COM1 22277 00005F5B 46 <1> inc esi ; no, it is COM2 (tty9) 22278 <1> ottys_1: 22279 <1> ; 12/11/2015 22280 00005F5C 803E00 <1> cmp byte [esi], 0 ; E3h (or 23h) 22281 00005F5F 770C <1> ja short com_port_ready 22282 <1> ; 22283 00005F61 C705[9D740000]0F00- <1> mov dword [u.error], ERR_DEV_NOT_RDY 22284 00005F69 0000 <1> 22285 <1> ; device not ready ! error 22286 00005F6B EBD5 <1> jmp short otty_err 22287 <1> com_port_ready: 22288 <1> ottys_2: 22289 00005F6D 08C9 <1> or cl, cl ; cl = lock/owner, ch = open count 22290 00005F6F 7506 <1> jnz short ottys_3 22291 00005F71 8A0D[97740000] <1> mov cl, [u.uno] 22292 <1> ottys_3: 22293 00005F77 FEC5 <1> inc ch 22294 00005F79 66890B <1> mov [ebx], cx ; set tty lock again 22295 <1> ; 06/12/2013 22296 00005F7C FEC6 <1> inc dh ; tty number + 1 22297 00005F7E BB[78740000] <1> mov ebx, u.ttyp 22298 <1> ; 13/01/2014 22299 00005F83 F6C202 <1> test dl, 2 ; open for read sign 22300 00005F86 7501 <1> jnz short ottys_4 22301 00005F88 43 <1> inc ebx 22302 <1> ottys_4: 22303 <1> ; Set 'u.ttyp' ('the recent TTY') value 22304 00005F89 8833 <1> mov [ebx], dh ; tty number + 1 22305 <1> sret: 22306 00005F8B 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 22307 00005F8D 7402 <1> jz short iclose_retn 22308 00005F8F 6658 <1> pop ax 22309 <1> iclose_retn: 22310 00005F91 C3 <1> retn 22311 <1> 22312 <1> ; 22313 <1> ; Original UNIX v1 'otty' routine: 22314 <1> ; 22315 <1> ;mov $100,*$tks / set interrupt enable bit (zero others) in 22316 <1> ; / reader status reg 22317 <1> ;mov $100,*$tps / set interrupt enable bit (zero others) in 22318 <1> ; / punch status reg 22319 <1> ;mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the 22320 <1> ; / console tty buffer 22321 <1> ;incb (r5) / increment the count of processes that opened the 22322 <1> ; / console tty 22323 <1> ;tst u.ttyp / is there a process control tty (i.e., has a tty 22324 <1> ; / buffer header 22325 <1> ;bne sret / address been loaded into u.ttyp yet)? yes, branch 22326 <1> ;mov r5,u.ttyp / no, make the console tty the process control 22327 <1> ; / tty 22328 <1> ;br sret / ? 22329 <1> ;sret: 22330 <1> ;clr *$ps / set processor priority to zero 22331 <1> ; pop ax 22332 <1> ;mov (sp)+,r1 / pop stack to r1 22333 <1> ;3: 22334 <1> ; retn 22335 <1> ;rts r0 22336 <1> 22337 <1> ;ocvt: ; < open tty > 22338 <1> ; 13/01/2014 22339 <1> ; 06/12/2013 (major modification: p.ttyc, u.ttyp) 22340 <1> ; 24/09/2013 consistency check -> ok 22341 <1> ; 16/09/2013 22342 <1> ; 03/09/2013 22343 <1> ; 27/08/2013 22344 <1> ; 16/08/2013 22345 <1> ; 16/07/2013 22346 <1> ; 27/05/2013 22347 <1> ; 21/05/2013 22348 <1> ; 22349 <1> ; Retro UNIX 8086 v1 modification ! 22350 <1> ; 22351 <1> ; In original UNIX v1, 'ocvt' routine 22352 <1> ; (exactly different than this one) 22353 <1> ; was in 'u9.s' file. 22354 <1> ; 22355 <1> ; 16/07/2013 22356 <1> ; Retro UNIX 8086 v1 modification: 22357 <1> ; If a tty is open for read or write by 22358 <1> ; a process (u.uno), only same process can open 22359 <1> ; same tty to write or read (R->R&W or W->W&R). 22360 <1> ; 22361 <1> ; INPUT: DL=2 for Read DL=1 for Write 22362 <1> 22363 <1> ; 16/09/2013 22364 <1> ; sub al, 10 22365 <1> 22366 <1> ; 06/12/2013 22367 <1> ;cmp al, 7 22368 <1> ;jna short ottyp 22369 <1> ; 13/01/2014 22370 <1> ;jmp short ottyp 22371 <1> 22372 <1> 22373 <1> ;oppt: / open paper tape for reading or writing 22374 <1> ; mov $100,*$prs / set reader interrupt enable bit 22375 <1> ; tstb pptiflg / is file already open 22376 <1> ; bne 2f / yes, branch 22377 <1> ;1: 22378 <1> ; mov $240,*$ps / no, set processor priority to 5 22379 <1> ; jsr r0,getc; 2 / remove all entries in clist 22380 <1> ; br .+4 / for paper tape input and place in free list 22381 <1> ; br 1b 22382 <1> ; movb $2,pptiflg / set pptiflg to indicate file just open 22383 <1> ; movb $10.,toutt+1 / place 10 in paper tape input tout entry 22384 <1> ; br sret 22385 <1> ;2: 22386 <1> ; jmp error / file already open 22387 <1> 22388 <1> iclose: 22389 <1> ; 19/05/2015 22390 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 22391 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 22392 <1> ; 22393 <1> ; close file whose i-number is in r1 22394 <1> ; 22395 <1> ; INPUTS -> 22396 <1> ; r1 - inode number 22397 <1> ; OUTPUTS -> 22398 <1> ; file's inode in core 22399 <1> ; r1 - inode number (positive) 22400 <1> ; 22401 <1> ; ((AX = R1)) 22402 <1> ; ((Modified registers: -ebx-, edx)) 22403 <1> ; 22404 <1> ;/ close file whose i-number is in r1 22405 00005F92 B202 <1> mov dl, 2 ; 12/01/2014 22406 00005F94 F6C480 <1> test ah, 80h ; Bit 15 of AX 22407 <1> ;tst r1 / test i-number 22408 <1> ;jnz short iclose_2 22409 <1> ;blt 2f / if neg., branch 22410 00005F97 7405 <1> jz short iclose_0 ; 30/07/2013 22411 <1> ; 16/07/2013 22412 00005F99 66F7D8 <1> neg ax ; make it positive 22413 <1> ; 12/01/2014 22414 00005F9C FECA <1> dec dl ; dl = 1 (open for write) 22415 <1> iclose_0: 22416 00005F9E 6683F828 <1> cmp ax, 40 22417 <1> ;cmp r1,$40. / is it a special file 22418 00005FA2 77ED <1> ja short iclose_retn ; 13/01/2014 22419 <1> ;bgt 3b / no, return 22420 <1> ; 12/01/2014 22421 <1> ; DL=2 -> special file was opened for reading 22422 <1> ; DL=1 -> special file was opened for writing 22423 00005FA4 6650 <1> push ax 22424 <1> ;mov r1,-(sp) / yes, save r1 on stack 22425 00005FA6 0FB6D8 <1> movzx ebx, al 22426 00005FA9 66C1E302 <1> shl bx, 2 22427 <1> ; asl r1 22428 00005FAD 81C3[B15F0000] <1> add ebx, iclose_1 - 4 22429 00005FB3 FF23 <1> jmp dword [ebx] 22430 <1> ; jmp *1f-2(r1) / compute jump address and transfer 22431 <1> iclose_1 : 22432 00005FB5 [01600000] <1> dd ctty ; tty, AX = 1 (runix) 22433 00005FB9 [52600000] <1> dd cret ; mem, AX = 2 (runix) 22434 00005FBD [52600000] <1> dd cret ; fd0, AX = 3 (runix only) 22435 00005FC1 [52600000] <1> dd cret ; fd1, AX = 4 (runix only) 22436 00005FC5 [52600000] <1> dd cret ; hd0, AX = 5 (runix only) 22437 00005FC9 [52600000] <1> dd cret ; hd1, AX = 6 (runix only) 22438 00005FCD [52600000] <1> dd cret ; hd2, AX = 7 (runix only) 22439 00005FD1 [52600000] <1> dd cret ; hd3, AX = 8 (runix only) 22440 00005FD5 [52600000] <1> dd cret ; lpr, AX = 9 (runix) 22441 <1> ;dd error; lpr, AX = 9 (error !) 22442 <1> ;;dd offset ejec ;;lpr, AX = 9 22443 00005FD9 [10600000] <1> dd ccvt ; tty0, AX = 10 (runix) 22444 00005FDD [10600000] <1> dd ccvt ; tty1, AX = 11 (runix) 22445 00005FE1 [10600000] <1> dd ccvt ; tty2, AX = 12 (runix) 22446 00005FE5 [10600000] <1> dd ccvt ; tty3, AX = 13 (runix) 22447 00005FE9 [10600000] <1> dd ccvt ; tty4, AX = 14 (runix) 22448 00005FED [10600000] <1> dd ccvt ; tty5, AX = 15 (runix) 22449 00005FF1 [10600000] <1> dd ccvt ; tty6, AX = 16 (runix) 22450 00005FF5 [10600000] <1> dd ccvt ; tty7, AX = 17 (runix) 22451 00005FF9 [10600000] <1> dd ccvt ; COM1, AX = 18 (runix only) 22452 00005FFD [10600000] <1> dd ccvt ; COM2, AX = 19 (runix only) 22453 <1> 22454 <1> ; 1: 22455 <1> ; ctty / tty 22456 <1> ; cppt / ppt 22457 <1> ; sret / mem 22458 <1> ; sret / rf0 22459 <1> ; sret / rk0 22460 <1> ; sret / tap0 22461 <1> ; sret / tap1 22462 <1> ; sret / tap2 22463 <1> ; sret / tap3 22464 <1> ; sret / tap4 22465 <1> ; sret / tap5 22466 <1> ; sret / tap6 22467 <1> ; sret / tap7 22468 <1> ; ccvt / tty0 22469 <1> ; ccvt / tty1 22470 <1> ; ccvt / tty2 22471 <1> ; ccvt / tty3 22472 <1> ; ccvt / tty4 22473 <1> ; ccvt / tty5 22474 <1> ; ccvt / tty6 22475 <1> ; ccvt / tty7 22476 <1> ; error / crd 22477 <1> 22478 <1> ;iclose_2: ; 2: / negative i-number 22479 <1> ;neg ax 22480 <1> ;neg r1 / make it positive 22481 <1> ;cmp ax, 40 22482 <1> ;cmp r1,$40. / is it a special file? 22483 <1> ;ja short @b 22484 <1> ;bgt 3b / no. return 22485 <1> ;push ax 22486 <1> ;mov r1,-(sp) 22487 <1> ;movzx ebx, al 22488 <1> ;shl bx, 1 22489 <1> ;asl r1 / yes. compute jump address and transfer 22490 <1> ;add ebx, iclose_3 - 2 22491 <1> ;jmp dword [ebx] 22492 <1> ;jmp *1f-2(r1) / figure out 22493 <1> ;iclose_3: 22494 <1> ;dd ctty ; tty, AX = 1 (runix) 22495 <1> ;dd sret ; mem, AX = 2 (runix) 22496 <1> ;dd sret ; fd0, AX = 3 (runix only) 22497 <1> ;dd sret ; fd1, AX = 4 (runix only) 22498 <1> ;dd sret ; hd0, AX = 5 (runix only) 22499 <1> ;dd sret ; hd1, AX = 6 (runix only) 22500 <1> ;dd sret ; hd2, AX = 7 (runix only) 22501 <1> ;dd sret ; hd3, AX = 8 (runix only) 22502 <1> ;dd sret ; lpr, AX = 9 22503 <1> ;dd ejec ; lpr, AX = 9 (runix) 22504 <1> ;dd ccvt ; tty0, AX = 10 (runix) 22505 <1> ;dd ccvt ; tty1, AX = 11 (runix) 22506 <1> ;dd ccvt ; tty2, AX = 12 (runix) 22507 <1> ;dd ccvt ; tty3, AX = 13 (runix) 22508 <1> ;dd ccvt ; tty4, AX = 14 (runix) 22509 <1> ;dd ccvt ; tty5, AX = 15 (runix) 22510 <1> ;dd ccvt ; tty6, AX = 16 (runix) 22511 <1> ;dd ccvt ; tty7, AX = 17 (runix) 22512 <1> ;dd ccvt ; COM1, AX = 18 (runix only) 22513 <1> ;dd ccvt ; COM2, AX = 19 (runix only) 22514 <1> 22515 <1> ;1: 22516 <1> ; ctty / tty 22517 <1> ; leadr / ppt 22518 <1> ; sret / mem 22519 <1> ; sret / rf0 22520 <1> ; sret / rk0 22521 <1> ; sret / tap0 22522 <1> ; sret / tap1 22523 <1> ; sret / tap2 22524 <1> ; sret / tap3 22525 <1> ; sret / tap4 22526 <1> ; sret / tap5 22527 <1> ; sret / tap6 22528 <1> ; sret / tap7 22529 <1> ; ccvt / tty0 22530 <1> ; ccvt / tty1 22531 <1> ; ccvt / tty2 22532 <1> ; ccvt / tty3 22533 <1> ; ccvt / tty4 22534 <1> ; ccvt / tty5 22535 <1> ; ccvt / tty6 22536 <1> ; ccvt / tty7 22537 <1> ;/ ejec / lpr 22538 <1> 22539 <1> ctty: ; / close console tty 22540 <1> ; 18/05/2015 (Retro UNIX 386 v1 - Beginning) 22541 <1> ; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1) 22542 <1> ; 22543 <1> ; Retro UNIX 8086 v1 modification ! 22544 <1> ; (DL = 2 -> it is open for reading) 22545 <1> ; (DL = 1 -> it is open for writing) 22546 <1> ; (DL = 0 -> it is open for sysstty system call) 22547 <1> ; 22548 <1> ; 06/12/2013 22549 00006001 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 22550 00006008 8A83[95710000] <1> mov al, [ebx+p.ttyc-1] 22551 <1> ; 13/01/2014 22552 0000600E EB02 <1> jmp short cttyp 22553 <1> ccvt: 22554 00006010 2C0A <1> sub al, 10 22555 <1> cttyp: 22556 <1> ; 18/05/2015 (32 bit modifications) 22557 <1> ; 16/08/2013 - 26/01/2014 22558 00006012 0FB6D8 <1> movzx ebx, al ; tty number (0 to 9) 22559 00006015 D0E3 <1> shl bl, 1 ; aligned to word 22560 <1> ; 26/01/2014 22561 00006017 81C3[B4700000] <1> add ebx, ttyl 22562 0000601D 88C6 <1> mov dh, al ; tty number 22563 0000601F 668B03 <1> mov ax, [ebx] 22564 <1> ; AL = lock value (0 or process number) 22565 <1> ; AH = open count 22566 00006022 20E4 <1> and ah, ah 22567 00006024 750F <1> jnz short ctty_ret 22568 00006026 C705[9D740000]0A00- <1> mov dword [u.error], ERR_DEV_NOT_OPEN 22569 0000602E 0000 <1> 22570 <1> ; device not open ! error 22571 <1> ;jmp short ctty_err ; open count = 0, it is not open ! 22572 00006030 E905E0FFFF <1> jmp error 22573 <1> ; 26/01/2014 22574 <1> ctty_ret: 22575 00006035 FECC <1> dec ah ; decrease open count 22576 00006037 7502 <1> jnz short ctty_1 22577 00006039 30C0 <1> xor al, al ; unlock/free tty 22578 <1> ctty_1: 22579 0000603B 668903 <1> mov [ebx], ax ; close tty instance 22580 <1> ; 22581 0000603E BB[78740000] <1> mov ebx, u.ttyp 22582 00006043 F6C201 <1> test dl, 1 ; open for write sign 22583 00006046 7401 <1> jz short ctty_2 22584 00006048 43 <1> inc ebx 22585 <1> ctty_2: 22586 00006049 FEC6 <1> inc dh ; tty number + 1 22587 0000604B 3A33 <1> cmp dh, [ebx] 22588 0000604D 7503 <1> jne short cret 22589 <1> ; Reset/Clear 'u.ttyp' ('the recent TTY') value 22590 0000604F C60300 <1> mov byte [ebx], 0 22591 <1> cret: 22592 00006052 08D2 <1> or dl, dl ; sysstty system call check (DL=0) 22593 00006054 7402 <1> jz short ctty_3 22594 00006056 6658 <1> pop ax 22595 <1> ctty_3: 22596 00006058 C3 <1> retn 22597 <1> 22598 <1> ;ctty_err: ; 13/01/2014 22599 <1> ; or dl, dl ; DL = 0 -> called by sysstty 22600 <1> ; jnz error 22601 <1> ; stc 22602 <1> ; retn 22603 <1> 22604 <1> 22605 <1> ; Original UNIX v1 'ctty' routine: 22606 <1> ; 22607 <1> ;mov tty+[ntty*8]-8+6,r5 22608 <1> ; ;/ point r5 to the console tty buffer 22609 <1> ;decb (r5) / dec number of processes using console tty 22610 <1> ;br sret / return via sret 22611 <1> 22612 <1> ;ccvt: ; < close tty > 22613 <1> ; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1) 22614 <1> ; 22615 <1> ; Retro UNIX 8086 v1 modification ! 22616 <1> ; 22617 <1> ; In original UNIX v1, 'ccvt' routine 22618 <1> ; (exactly different than this one) 22619 <1> ; was in 'u9.s' file. 22620 <1> ; 22621 <1> ; DL = 2 -> it is open for reading 22622 <1> ; DL = 1 -> it is open for writing 22623 <1> ; 22624 <1> ; 17/09/2013 22625 <1> ;sub al, 10 22626 <1> ;cmp al, 7 22627 <1> ;jna short cttyp 22628 <1> ; 13/01/2014 22629 <1> ;jmp short cttyp 22630 <1> 22631 <1> ;cppt: / close paper tape 22632 <1> ; clrb pptiflg / set pptiflg to indicate file not open 22633 <1> ;1: 22634 <1> ; mov $240,*$ps /set process or priority to 5 22635 <1> ; jsr r0,getc; 2 / remove all ppt input entries from clist 22636 <1> ; / and assign to free list 22637 <1> ; br sret 22638 <1> ; br 1b 22639 <1> 22640 <1> ;ejec: 22641 <1> ; jmp error 22642 <1> ;/ejec: 22643 <1> ;/ mov $100,*$lps / set line printer interrupt enable bit 22644 <1> ;/ mov $14,r1 / 'form feed' character in r1 (new page). 22645 <1> ;/ jsr r0,lptoc / space the printer to a new page 22646 <1> ;/ br sret / return to caller via 'sret' 22647 %include 'u8.s' ; 11/06/2015 22648 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC 22649 <1> ; Last Modification: 24/10/2015 22650 <1> ; ---------------------------------------------------------------------------- 22651 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 22652 <1> ; (v0.1 - Beginning: 11/07/2012) 22653 <1> ; 22654 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 22655 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 22656 <1> ; 22657 <1> ; 22658 <1> ; 22659 <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s 22660 <1> ; 22661 <1> ; **************************************************************************** 22662 <1> 22663 <1> ;; I/O Buffer - Retro UNIX 386 v1 modification 22664 <1> ;; (8+512 bytes, 8 bytes header, 512 bytes data) 22665 <1> ;; Word 1, byte 0 = device id 22666 <1> ;; Word 1, byte 1 = status bits (bits 8 to 15) 22667 <1> ;; bit 9 = write bit 22668 <1> ;; bit 10 = read bit 22669 <1> ;; bit 12 = waiting to write bit 22670 <1> ;; bit 13 = waiting to read bit 22671 <1> ;; bit 15 = inhibit bit 22672 <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015) 22673 <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 22674 <1> ;; (In fact, it is 32 bit LBA for Retro UNIX 386 v1) 22675 <1> ;; 22676 <1> ;; I/O Buffer ((8+512 bytes in original Unix v1)) 22677 <1> ;; ((4+512 bytes in Retro UNIX 8086 v1)) 22678 <1> ;; 22679 <1> ;; I/O Queue Entry (of original UNIX operating system v1) 22680 <1> ;; Word 1, Byte 0 = device id 22681 <1> ;; Word 1, Byte 1 = (bits 8 to 15) 22682 <1> ;; bit 9 = write bit 22683 <1> ;; bit 10 = read bit 22684 <1> ;; bit 12 = waiting to write bit 22685 <1> ;; bit 13 = waiting to read bit 22686 <1> ;; bit 15 = inhibit bit 22687 <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1) 22688 <1> ;; 22689 <1> ;; Original UNIX v1 -> 22690 <1> ;; Word 3 = number of words in buffer (=256) 22691 <1> ;; Original UNIX v1 -> 22692 <1> ;; Word 4 = bus address (addr of first word of data buffer) 22693 <1> ;; 22694 <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes ! 22695 <1> ;; 22696 <1> ;; Device IDs (of Retro Unix 8086 v1) 22697 <1> ;; 0 = fd0 22698 <1> ;; 1 = fd1 22699 <1> ;; 2 = hd0 22700 <1> ;; 3 = hd1 22701 <1> ;; 4 = hd2 22702 <1> ;; 5 = hd3 22703 <1> 22704 <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015 22705 <1> 22706 <1> rfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 22707 <1> ; 26/04/2013 22708 <1> ; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 22709 <1> ;sub ax, 3 ; zero based device number (Floppy disk) 22710 <1> ;jmp short bread ; **** returns to routine that called readi 22711 <1> 22712 <1> rhd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 22713 <1> ; 26/04/2013 22714 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 22715 <1> ;sub ax, 3 ; zero based device number (Hard disk) 22716 <1> ;jmp short bread ; **** returns to routine that called readi 22717 <1> 22718 <1> bread: 22719 <1> ; 14/07/2015 22720 <1> ; 10/07/2015 22721 <1> ; 09/06/2015 22722 <1> ; 07/06/2015 (Retro UNIX 386 v1 - Beginning) 22723 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 22724 <1> ; 22725 <1> ; / read a block from a block structured device 22726 <1> ; 22727 <1> ; INPUTS -> 22728 <1> ; [u.fopf] points to the block number 22729 <1> ; CX = maximum block number allowed on device 22730 <1> ; ; that was an arg to bread, in original Unix v1, but 22731 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 22732 <1> ; [u.count] number of bytes to read in 22733 <1> ; OUTPUTS -> 22734 <1> ; [u.base] starting address of data block or blocks in user area 22735 <1> ; [u.fopf] points to next consecutive block to be read 22736 <1> ; 22737 <1> ; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP)) 22738 <1> ; 22739 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if read 22740 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 22741 <1> ; is increased by 1. For example: If user/program request 22742 <1> ; to read 16 bytes in current block, 'sys read' increases 22743 <1> ; the next block number just as 512 byte reading is done. 22744 <1> ; This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 22745 <1> ; for user (u) structure compatibility (because 16 bit is not 22746 <1> ; enough to keep byte position/offset of the disk), this 22747 <1> ; defect will not be corrected, user/program must request 22748 <1> ; 512 byte read per every 'sys read' call to block devices 22749 <1> ; for achieving correct result. In future version(s), 22750 <1> ; this defect will be corrected by using different 22751 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 22752 <1> 22753 <1> ; jsr r0,tstdeve / error on special file I/O 22754 <1> ; / (only works on tape) 22755 <1> ; mov *u.fofp,r1 / move block number to r1 22756 <1> ; mov $2.-cold,-(sp) / "2-cold" to stack 22757 <1> ;1: 22758 <1> ; cmp r1,(r0) / is this block # greater than or equal to 22759 <1> ; / maximum block # allowed on device 22760 <1> ; jnb short @f 22761 <1> ; bhis 1f / yes, 1f (error) 22762 <1> ; mov r1,-(sp) / no, put block # on stack 22763 <1> ; jsr r0,preread / read in the block into an I/O buffer 22764 <1> ; mov (sp)+,r1 / return block # to r1 22765 <1> ; inc r1 / bump block # to next consecutive block 22766 <1> ; dec (sp) / "2-1-cold" on stack 22767 <1> ; bgt 1b / 2-1-cold = 0? No, go back and read in next block 22768 <1> ;1: 22769 <1> ; tst (sp)+ / yes, pop stack to clear off cold calculation 22770 <1> ;push ecx ; ** 22771 <1> ;26/04/2013 22772 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 22773 00006059 2C03 <1> sub al, 3 22774 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 22775 0000605B A2[B0740000] <1> mov [u.brwdev], al 22776 <1> ; 09/06/2015 22777 00006060 0FB6D8 <1> movzx ebx, al 22778 00006063 8B8B[4E6B0000] <1> mov ecx, [ebx+drv.size] ; disk size (in sectors) 22779 <1> bread_0: 22780 00006069 51 <1> push ecx ; ** ; 09/06/2015 22781 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 22782 <1> ; [u.fopf] points to byte position in disk, not sector/block ! 22783 0000606A 8B1D[58740000] <1> mov ebx, [u.fofp] 22784 00006070 8B03 <1> mov eax, [ebx] 22785 00006072 C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 22786 <1> ; mov *u.fofp,r1 / restore r1 to initial value of the 22787 <1> ; / block # 22788 00006075 39C8 <1> cmp eax, ecx 22789 <1> ; cmp r1,(r0)+ / block # greater than or equal to maximum 22790 <1> ; / block number allowed 22791 <1> ;jnb error ; 18/04/2013 22792 <1> ; bhis error10 / yes, error 22793 00006077 720F <1> jb short bread_1 22794 00006079 C705[9D740000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 22795 00006081 0000 <1> 22796 00006083 E9B2DFFFFF <1> jmp error 22797 <1> bread_1: 22798 <1> ; inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 22799 <1> ; inc *u.fofp / no, *u.fofp has next block number 22800 <1> ; eAX = Block number (zero based) 22801 <1> ;;jsr r0,preread / read in the block whose number is in r1 22802 <1> preread: ;; call preread 22803 00006088 BF[B0740000] <1> mov edi, u.brwdev ; block device number for direct I/O 22804 0000608D E864020000 <1> call bufaloc_0 ; 26/04/2013 22805 <1> ;; jc error 22806 <1> ; eBX = Buffer (Header) Address -Physical- 22807 <1> ; eAX = Block/Sector number (r1) 22808 <1> ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number) 22809 <1> ; 14/03/2013 22810 00006092 740A <1> jz short bread_2 ; Retro UNIX 8086 v1 modification 22811 <1> ; br 1f / branch if block already in a I/O buffer 22812 00006094 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 22813 <1> ; bis $2000,(r5) / set read bit (bit 10 in I/O buffer) 22814 00006099 E8B3010000 <1> call poke 22815 <1> ; jsr r0,poke / perform the read 22816 <1> ;;jc error ;2 0/07/2013 22817 <1> ; 1: 22818 <1> ; clr *$ps / ps = 0 22819 <1> ; rts r0 22820 <1> ;; return from preread 22821 <1> bread_2: 22822 0000609E 66810B0040 <1> or word [ebx], 4000h 22823 <1> ; bis $40000,(r5) 22824 <1> ; / set bit 14 of the 1st word of the I/O buffer 22825 <1> bread_3: ; 1: 22826 000060A3 66F7030024 <1> test word [ebx], 2400h 22827 <1> ; bit $22000,(r5) / are 10th and 13th bits set (read bits) 22828 000060A8 7407 <1> jz short bread_4 22829 <1> ; beq 1f / no 22830 <1> ; cmp cdev,$1 / disk or drum? 22831 <1> ; ble 2f / yes 22832 <1> ; tstb uquant / is the time quantum = 0? 22833 <1> ; bne 2f / no, 2f 22834 <1> ; mov r5,-(sp) / yes, save r5 (buffer address) 22835 <1> ; jsr r0,sleep; 31. 22836 <1> ; / put process to sleep in channel 31 (tape) 22837 <1> ; mov (sp)+,r5 / restore r5 22838 <1> ; br 1b / go back 22839 <1> ; 2: / drum or disk 22840 <1> ;; mov cx, [s.wait_]+2 ;; 29/07/2013 22841 000060AA E8AAF3FFFF <1> call idle 22842 <1> ; jsr r0,idle; s.wait+2 / wait 22843 000060AF EBF2 <1> jmp short bread_3 22844 <1> ; br 1b 22845 <1> bread_4: ; 1: / 10th and 13th bits not set 22846 000060B1 668123FFBF <1> and word [ebx], 0BFFFh ; 1011111111111111b 22847 <1> ; bic $40000,(r5) / clear bit 14 22848 <1> ; jsr r0,tstdeve / test device for error (tape) 22849 000060B6 83C308 <1> add ebx, 8 22850 <1> ; add $8,r5 / r5 points to data in I/O buffer 22851 <1> ; 09/06/2015 22852 000060B9 66833D[AD740000]00 <1> cmp word [u.pcount], 0 22853 000060C1 7705 <1> ja short bread_5 22854 000060C3 E896F9FFFF <1> call trans_addr_w ; translate virtual address to physical (w) 22855 <1> bread_5: 22856 <1> ; eBX = system (I/O) buffer address 22857 000060C8 E870000000 <1> call dioreg 22858 <1> ; jsr r0,dioreg / do bookkeeping on u.count etc. 22859 <1> ; esi = start address of the transfer (in the buffer) 22860 <1> ; edi = [u.pbase], destination address in user's memory space 22861 <1> ; ecx = transfer count (in bytes) 22862 <1> ; 22863 <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning 22864 <1> ; / of users data 22865 000060CD F3A4 <1> rep movsb 22866 <1> ; movb (r5)+,(r2)+ / move data from the I/O buffer 22867 <1> ; dec r3 / to the user's area in core starting at u.base 22868 <1> ; bne 1b 22869 000060CF 59 <1> pop ecx ; ** 22870 000060D0 833D[6C740000]00 <1> cmp dword [u.count], 0 22871 <1> ; tst u.count / done 22872 000060D7 7790 <1> ja short bread_0 ; 09/06/2015 22873 <1> ; beq 1f / yes, return 22874 <1> ; tst -(r0) / no, point r0 to the argument again 22875 <1> ; br bread / read some more 22876 <1> ; 1: 22877 000060D9 58 <1> pop eax ; **** 22878 <1> ; mov (sp)+,r0 22879 000060DA C3 <1> retn ; 09/06/2015 22880 <1> ;jmp ret_ 22881 <1> ;jmp ret / jump to routine that called readi 22882 <1> 22883 <1> wfd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 22884 <1> ; 26/04/2013 22885 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 22886 <1> ;sub ax, 3 ; zero based device number (Hard disk) 22887 <1> ;jmp short bwrite ; **** returns to routine that called writei 22888 <1> 22889 <1> whd: ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 22890 <1> ; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device) 22891 <1> ;sub ax, 3 ; zero based device number (Hard disk) 22892 <1> ;jmp short bwrite ; **** returns to routine that called writei ('jmp ret') 22893 <1> 22894 <1> bwrite: 22895 <1> ; 14/07/2015 22896 <1> ; 10/07/2015 22897 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 22898 <1> ; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1) 22899 <1> ; 22900 <1> ;; / write on block structured device 22901 <1> ; 22902 <1> ; INPUTS -> 22903 <1> ; [u.fopf] points to the block number 22904 <1> ; CX = maximum block number allowed on device 22905 <1> ; ; that was an arg to bwrite, in original Unix v1, but 22906 <1> ; ; CX register is used instead of arg in Retro Unix 8086 v1 22907 <1> ; [u.count] number of bytes to user desires to write 22908 <1> ; OUTPUTS -> 22909 <1> ; [u.fopf] points to next consecutive block to be written into 22910 <1> ; 22911 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 22912 <1> ; 22913 <1> ; NOTE: Original UNIX v1 has/had a defect/bug here, even if write 22914 <1> ; byte count is less than 512, block number in *u.fofp (u.off) 22915 <1> ; is increased by 1. For example: If user/program request 22916 <1> ; to write 16 bytes in current block, 'sys write' increases 22917 <1> ; the next block number just as 512 byte writing is done. 22918 <1> ; This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 22919 <1> ; for user (u) structure compatibility (because 16 bit is not 22920 <1> ; enough to keep byte position/offset of the disk), this 22921 <1> ; defect will not be corrected, user/program must request 22922 <1> ; 512 byte write per every 'sys write' call to block devices 22923 <1> ; for achieving correct result. In future version(s), 22924 <1> ; this defect will be corrected by using different 22925 <1> ; user (u) structure. 26/07/2013 - Erdogan Tan 22926 <1> 22927 <1> ; jsr r0,tstdeve / test the device for an error 22928 <1> ;push ecx ; ** 22929 <1> ;26/04/2013 22930 <1> ;sub ax, 3 ; 3 to 8 -> 0 to 5 22931 000060DB 2C03 <1> sub al, 3 22932 <1> ; AL = Retro Unix 8086 v1 disk (block device) number 22933 000060DD A2[B0740000] <1> mov [u.brwdev], al 22934 <1> ; 09/06/2015 22935 000060E2 0FB6D8 <1> movzx ebx, al 22936 000060E5 8B8B[4E6B0000] <1> mov ecx, [ebx+drv.size] ; disk size (in sectors) 22937 <1> bwrite_0: 22938 000060EB 51 <1> push ecx ; ** ; 09/06/2015 22939 <1> ; 10/07/2015 (Retro UNIX 386 v1 modification!) 22940 <1> ; [u.fopf] points to byte position in disk, not sector/block ! 22941 000060EC 8B1D[58740000] <1> mov ebx, [u.fofp] 22942 000060F2 8B03 <1> mov eax, [ebx] 22943 000060F4 C1E809 <1> shr eax, 9 ; convert byte position to block/sector number 22944 <1> ; mov *u.fofp,r1 / put the block number in r1 22945 000060F7 39C8 <1> cmp eax, ecx 22946 <1> ; cmp r1,(r0)+ / does block number exceed maximum allowable # 22947 <1> ; / block number allowed 22948 <1> ;jnb error ; 18/04/2013 22949 <1> ; bhis error10 / yes, error 22950 000060F9 720F <1> jb short bwrite_1 22951 000060FB C705[9D740000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE ; 'out of volume' error 22952 00006103 0000 <1> 22953 00006105 E930DFFFFF <1> jmp error 22954 <1> bwrite_1: 22955 <1> ; inc dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!) 22956 <1> ; inc *u.fofp / no, increment block number 22957 <1> ; 09/06/2015 - 10/07/2015 22958 0000610A 66833D[AD740000]00 <1> cmp word [u.pcount], 0 22959 00006112 7705 <1> ja short bwrite_2 22960 00006114 E841F9FFFF <1> call trans_addr_r ; translate virtual address to physical (r) 22961 <1> bwrite_2: 22962 00006119 BF[B0740000] <1> mov edi, u.brwdev ; block device number for direct I/O 22963 0000611E E8C4000000 <1> call bwslot ; 26/04/2013 (wslot -> bwslot) 22964 <1> ; jsr r0,wslot / get an I/O buffer to write into 22965 <1> ; add $8,r5 / r5 points to data in I/O buffer 22966 00006123 E815000000 <1> call dioreg 22967 <1> ; jsr r0,dioreg / do the necessary bookkeeping 22968 <1> ; esi = destination address (in the buffer) 22969 <1> ; edi = [u.pbase], start address of transfer in user's memory space 22970 <1> ; ecx = transfer count (in bytes) 22971 <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area 22972 00006128 87F7 <1> xchg esi, edi ; 14/07/2015 22973 0000612A F3A4 <1> rep movsb 22974 <1> ; movb (r2)+,(r5)+ / ; r3, has the byte count 22975 <1> ; dec r3 / area to the I/O buffer 22976 <1> ; bne 1b 22977 0000612C E8FE000000 <1> call dskwr 22978 <1> ; jsr r0,dskwr / write it out on the device 22979 00006131 59 <1> pop ecx ; ** 22980 00006132 833D[6C740000]00 <1> cmp dword [u.count], 0 22981 <1> ; tst u.count / done 22982 00006139 77B0 <1> ja short bwrite_0 ; 09/06/2015 22983 <1> ; beq 1f / yes, 1f 22984 <1> ; tst -(r0) / no, point r0 to the argument of the call 22985 <1> ; br bwrite / go back and write next block 22986 <1> ; 1: 22987 0000613B 58 <1> pop eax ; **** 22988 <1> ; mov (sp)+,r0 22989 0000613C C3 <1> retn ; 09/06/2015 22990 <1> ;jmp ret_ 22991 <1> ; jmp ret / return to routine that called writei 22992 <1> ;error10: 22993 <1> ; jmp error ; / see 'error' routine 22994 <1> 22995 <1> dioreg: 22996 <1> ; 14/07/2015 22997 <1> ; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block) 22998 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 22999 <1> ; 14/03/2013 (Retro UNIX 8086 v1) 23000 <1> ; 23001 <1> ; bookkeeping on block transfers of data 23002 <1> ; 23003 <1> ; * returns value of u.pbase before it gets updated, in EDI 23004 <1> ; * returns byte count (to transfer) in ECX (<=512) 23005 <1> ; 10/07/2015 23006 <1> ; * returns byte offset from beginning of current sector buffer 23007 <1> ; (beginning of data) in ESI 23008 <1> ; 23009 0000613D 8B0D[6C740000] <1> mov ecx, [u.count] 23010 <1> ; mov u.count,r3 / move char count to r3 23011 00006143 81F900020000 <1> cmp ecx, 512 23012 <1> ; cmp r3,$512. / more than 512. char? 23013 00006149 7605 <1> jna short dioreg_0 23014 <1> ; blos 1f / no, branch 23015 0000614B B900020000 <1> mov ecx, 512 23016 <1> ; mov $512.,r3 / yes, just take 512. 23017 <1> dioreg_0: 23018 <1> ; 09/06/2015 23019 00006150 663B0D[AD740000] <1> cmp cx, [u.pcount] 23020 00006157 7607 <1> jna short dioreg_1 23021 00006159 668B0D[AD740000] <1> mov cx, [u.pcount] 23022 <1> dioreg_1: 23023 <1> ; 1: 23024 00006160 8B15[68740000] <1> mov edx, [u.base] ; 09/06/2015 (eax -> edx) 23025 <1> ; mov u.base,r2 / put users base in r2 23026 00006166 010D[70740000] <1> add [u.nread], ecx 23027 <1> ; add r3,u.nread / add the number to be read to u.nread 23028 0000616C 290D[6C740000] <1> sub [u.count], ecx 23029 <1> ; sub r3,u.count / update count 23030 00006172 010D[68740000] <1> add [u.base], ecx 23031 <1> ; add r3,u.base / update base 23032 <1> ; 10/07/2015 23033 <1> ; Retro UNIX 386 v1 - modification ! 23034 <1> ; (File pointer points to byte position, not block/sector no.) 23035 <1> ; (It will point to next byte position instead of next block no.) 23036 00006178 8B35[58740000] <1> mov esi, [u.fofp] ; u.fopf points to byte position pointer 23037 0000617E 8B06 <1> mov eax, [esi] ; esi points to current byte pos. on the disk 23038 00006180 010E <1> add [esi], ecx ; ecx is added to set the next byte position 23039 00006182 25FF010000 <1> and eax, 1FFh ; get offset from beginning of current block 23040 00006187 89DE <1> mov esi, ebx ; beginning of data in sector/block buffer 23041 00006189 01C6 <1> add esi, eax ; esi contains start address of the transfer 23042 <1> ; 09/06/2015 - 10/07/2015 23043 0000618B 66290D[AD740000] <1> sub [u.pcount], cx 23044 00006192 81E2FF0F0000 <1> and edx, PAGE_OFF ; 0FFFh 23045 00006198 8B3D[A9740000] <1> mov edi, [u.pbase] 23046 0000619E 81E700F0FFFF <1> and edi, ~PAGE_OFF 23047 000061A4 01D7 <1> add edi, edx 23048 000061A6 893D[A9740000] <1> mov [u.pbase], edi 23049 000061AC 010D[A9740000] <1> add [u.pbase], ecx ; 14/07/2015 23050 000061B2 C3 <1> retn 23051 <1> ; rts r0 / return 23052 <1> 23053 <1> dskrd: 23054 <1> ; 18/08/2015 23055 <1> ; 02/07/2015 23056 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 23057 <1> ; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 23058 <1> ; 23059 <1> ; 'dskrd' acquires an I/O buffer, puts in the proper 23060 <1> ; I/O queue entries (via bufaloc) then reads a block 23061 <1> ; (number specified in r1) in the acquired buffer.) 23062 <1> ; If the device is busy at the time dskrd is called, 23063 <1> ; dskrd calls idle. 23064 <1> ; 23065 <1> ; INPUTS -> 23066 <1> ; r1 - block number 23067 <1> ; cdev - current device number 23068 <1> ; OUTPUTS -> 23069 <1> ; r5 - points to first data word in I/O buffer 23070 <1> ; 23071 <1> ; ((AX = R1)) input/output 23072 <1> ; ((BX = R5)) output 23073 <1> ; 23074 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 23075 <1> ; 23076 000061B3 E830010000 <1> call bufaloc 23077 <1> ; jsr r0,bufaloc / shuffle off to bufaloc; 23078 <1> ; / get a free I/O buffer 23079 <1> ;;jc error ; 20/07/2013 23080 000061B8 741B <1> jz short dskrd_1 ; Retro UNIX 8086 v1 modification 23081 <1> ; br 1f / branch if block already in a I/O buffer 23082 <1> dskrd_0: ; 10/07/2015 (wslot) 23083 000061BA 66810B0004 <1> or word [ebx], 400h ; set read bit (10) in I/O Buffer 23084 <1> ; bis $2000,(r5) / set bit 10 of word 1 of 23085 <1> ; / I/O queue entry for buffer 23086 000061BF E88D000000 <1> call poke 23087 <1> ; jsr r0,poke / just assigned in bufaloc, 23088 <1> ; / bit 10=1 says read 23089 <1> ; 09/06/2015 23090 000061C4 730F <1> jnc short dskrd_1 23091 <1> ; 23092 000061C6 C705[9D740000]1100- <1> mov dword [u.error], ERR_DRV_READ ; disk read error ! 23093 000061CE 0000 <1> 23094 000061D0 E965DEFFFF <1> jmp error 23095 <1> dskrd_1: ; 1: 23096 <1> ;clr *$ps 23097 000061D5 66F7030024 <1> test word [ebx], 2400h 23098 <1> ; bit $22000,(r5) / if either bits 10, or 13 are 1; 23099 <1> ; / jump to idle 23100 000061DA 7407 <1> jz short dskrd_2 23101 <1> ; beq 1f 23102 <1> ;;mov ecx, [s.wait_] 23103 000061DC E878F2FFFF <1> call idle 23104 <1> ; jsr r0,idle; s.wait+2 23105 000061E1 EBF2 <1> jmp short dskrd_1 23106 <1> ; br 1b 23107 <1> dskrd_2: ; 1: 23108 000061E3 83C308 <1> add ebx, 8 23109 <1> ; add $8,r5 / r5 points to first word of data in block 23110 <1> ; / just read in 23111 000061E6 C3 <1> retn 23112 <1> ; rts r0 23113 <1> 23114 <1> bwslot: 23115 <1> ; 10/07/2015 23116 <1> ; If the block/sector is not placed in a buffer 23117 <1> ; before 'wslot', it must be read before 23118 <1> ; it is written! (Otherwise transfer counts less 23119 <1> ; than 512 bytes will be able to destroy existing 23120 <1> ; data on disk.) 23121 <1> ; 23122 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 23123 <1> ; 26/04/2013(Retro UNIX 8086 v1) 23124 <1> ; Retro UNIX 8086 v1 modification ! 23125 <1> ; ('bwslot' will be called from 'bwrite' only!) 23126 <1> ; INPUT -> eDI - points to device id (in u.brwdev) 23127 <1> ; -> eAX = block number 23128 <1> ; 23129 000061E7 E80A010000 <1> call bufaloc_0 23130 000061EC 742A <1> jz short wslot_0 ; block/sector already is in the buffer 23131 <1> bwslot_0: 23132 <1> ; 10/07/2015 23133 000061EE 8B35[58740000] <1> mov esi, [u.fofp] 23134 000061F4 8B06 <1> mov eax, [esi] 23135 000061F6 25FF010000 <1> and eax, 1FFh ; offset from beginning of the sector/block 23136 000061FB 750C <1> jnz short bwslot_1 ; it is not a full sector write 23137 <1> ; recent disk data must be placed in the buffer 23138 000061FD 813D[6C740000]0002- <1> cmp dword [u.count], 512 23139 00006205 0000 <1> 23140 00006207 730F <1> jnb short wslot_0 23141 <1> bwslot_1: 23142 00006209 E8ACFFFFFF <1> call dskrd_0 23143 0000620E 83EB08 <1> sub ebx, 8 ; set ebx to the buffer header address again 23144 00006211 EB05 <1> jmp short wslot_0 23145 <1> 23146 <1> wslot: 23147 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 23148 <1> ; (32 bit modifications) 23149 <1> ; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1) 23150 <1> ; 23151 <1> ; 'wslot' calls 'bufaloc' and obtains as a result, a pointer 23152 <1> ; to the I/O queue of an I/O buffer for a block structured 23153 <1> ; device. It then checks the first word of I/O queue entry. 23154 <1> ; If bits 10 and/or 13 (read bit, waiting to read bit) are set, 23155 <1> ; wslot calls 'idle'. When 'idle' returns, or if bits 10 23156 <1> ; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first 23157 <1> ; word of the I/O queue entry (write bit, inhibit bit). 23158 <1> ; 23159 <1> ; INPUTS -> 23160 <1> ; r1 - block number 23161 <1> ; cdev - current (block/disk) device number 23162 <1> ; 23163 <1> ; OUTPUTS -> 23164 <1> ; bufp - bits 9 and 15 are set, 23165 <1> ; the remainder of the word left unchanged 23166 <1> ; r5 - points to first data word in I/O buffer 23167 <1> ; 23168 <1> ; ((AX = R1)) input/output 23169 <1> ; ((BX = R5)) output 23170 <1> ; 23171 <1> ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 23172 <1> 23173 00006213 E8D0000000 <1> call bufaloc 23174 <1> ; 10/07/2015 23175 <1> ; jsr r0,bufaloc / get a free I/O buffer; pointer to first 23176 <1> ; br 1f / word in buffer in r5 23177 <1> ; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment) 23178 <1> ; eAX = Block/Sector number (r1) 23179 <1> wslot_0: ;1: 23180 00006218 66F7030024 <1> test word [ebx], 2400h 23181 <1> ; bit $22000,(r5) / check bits 10, 13 (read, waiting to read) 23182 <1> ; / of I/O queue entry 23183 0000621D 7407 <1> jz short wslot_1 23184 <1> ; beq 1f / branch if 10, 13 zero (i.e., not reading, 23185 <1> ; / or not waiting to read) 23186 <1> 23187 <1> ;; mov ecx, [s.wait_] ; 29/07/2013 23188 0000621F E835F2FFFF <1> call idle 23189 <1> ; jsr r0,idle; / if buffer is reading or writing to read, 23190 <1> ; / idle 23191 00006224 EBF2 <1> jmp short wslot_0 23192 <1> ; br 1b / till finished 23193 <1> wslot_1: ;1: 23194 00006226 66810B0082 <1> or word [ebx], 8200h 23195 <1> ; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue 23196 <1> ; / (write, inhibit bits) 23197 <1> ; clr *$ps / clear processor status 23198 0000622B 83C308 <1> add ebx, 8 ; 11/06/2015 23199 <1> ; add $8,r5 / r5 points to first word in data area 23200 <1> ; / for this block 23201 0000622E C3 <1> retn 23202 <1> ; rts r0 23203 <1> dskwr: 23204 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 23205 <1> ; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1) 23206 <1> ; 23207 <1> ; 'dskwr' writes a block out on disk, via ppoke. The only 23208 <1> ; thing dskwr does is clear bit 15 in the first word of I/O queue 23209 <1> ; entry pointed by 'bufp'. 'wslot' which must have been called 23210 <1> ; previously has supplied all the information required in the 23211 <1> ; I/O queue entry. 23212 <1> ; 23213 <1> ; (Modified registers: eCX, eDX, eBX, eSI, eDI) 23214 <1> ; 23215 <1> ; 23216 0000622F 8B1D[0A740000] <1> mov ebx, [bufp] 23217 00006235 668123FF7F <1> and word [ebx], 7FFFh ; 0111111111111111b 23218 <1> ; bic $100000,*bufp / clear bit 15 of I/O queue entry at 23219 <1> ; / bottom of queue 23220 0000623A E812000000 <1> call poke 23221 <1> ; 09/06/2015 23222 0000623F 730F <1> jnc short dskwr_1 23223 00006241 C705[9D740000]1200- <1> mov dword [u.error], ERR_DRV_WRITE ; disk write error ! 23224 00006249 0000 <1> 23225 0000624B E9EADDFFFF <1> jmp error 23226 <1> dskwr_1: 23227 00006250 C3 <1> retn 23228 <1> 23229 <1> 23230 <1> ;ppoke: 23231 <1> ; mov $340,*$ps 23232 <1> ; jsr r0,poke 23233 <1> ; clr *$ps 23234 <1> ; rts r0 23235 <1> poke: 23236 <1> ; 24/10/2015 23237 <1> ; 20/08/2015 23238 <1> ; 18/08/2015 23239 <1> ; 02/07/2015 23240 <1> ; 09/06/2015 (Retro UNIX 386 v1 - Beginning) 23241 <1> ; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1) 23242 <1> ; 23243 <1> ; (NOTE: There are some disk I/O code modifications & extensions 23244 <1> ; & exclusions on original 'poke' & other device I/O procedures of 23245 <1> ; UNIX v1 OS for performing disk I/O functions by using IBM PC 23246 <1> ; compatible rombios calls in Retro UNIX 8086 v1 kernel.) 23247 <1> ; 23248 <1> ; Basic I/O functions for all block structured devices 23249 <1> ; 23250 <1> ; (Modified registers: eCX, eDX, eSI, eDI) 23251 <1> ; 23252 <1> ; 20/07/2013 modifications 23253 <1> ; (Retro UNIX 8086 v1 features only !) 23254 <1> ; INPUTS -> 23255 <1> ; (EBX = buffer header address) 23256 <1> ; OUTPUTS -> 23257 <1> ; cf=0 -> successed r/w (at least, for the caller's buffer) 23258 <1> ; cf=1 -> error, word [eBX] = 0FFFFh 23259 <1> ; (drive not ready or r/w error!) 23260 <1> ; (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success) 23261 <1> ; (dword [EBx+4] = 0FFFFFFFFh means RW/IO error) 23262 <1> ; (also it indicates invalid buffer data) 23263 <1> ; 23264 00006251 53 <1> push ebx 23265 <1> ; mov r1,-(sp) 23266 <1> ; mov r2,-(sp) 23267 <1> ; mov r3,-(sp) 23268 00006252 50 <1> push eax ; Physical Block Number (r1) (mget) 23269 <1> ; 23270 <1> ; 09/06/2015 23271 <1> ; (permit read/write after a disk R/W error) 23272 00006253 8A0B <1> mov cl, [ebx] ; device id (0 to 5) 23273 00006255 B001 <1> mov al, 1 23274 00006257 D2E0 <1> shl al, cl 23275 00006259 8405[32740000] <1> test al, [active] ; busy ? (error) 23276 0000625F 7408 <1> jz short poke_0 23277 00006261 F6D0 <1> not al 23278 00006263 2005[32740000] <1> and [active], al ; reset busy bit for this device only 23279 <1> poke_0: 23280 00006269 BE[2A740000] <1> mov esi, bufp + (4*(nbuf+2)) 23281 <1> ; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority 23282 <1> ; / I/O queue pointer 23283 <1> poke_1: ; 1: 23284 0000626E 83EE04 <1> sub esi, 4 23285 00006271 8B1E <1> mov ebx, [esi] 23286 <1> ; mov -(r2),r1 / r1 points to an I/O queue entry 23287 00006273 668B03 <1> mov ax, [ebx] ; 17/07/2013 23288 00006276 F6C406 <1> test ah, 06h 23289 <1> ;test word [ebx], 600h ; 0000011000000000b 23290 <1> ; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 23291 <1> ; / queue entry 23292 00006279 745E <1> jz short poke_5 23293 <1> ; beq 2f / branch to 2f if both are clear 23294 <1> ; 31/07/2013 23295 <1> ;test ah, 0B0h ; (*) 23296 <1> ;;test word [ebx], 0B000h ; 1011000000000000b 23297 <1> ; bit $130000,(r1) / test bits 12, 13, and 15 23298 <1> ;jnz short poke_5 ; 31/07/2013 (*) 23299 <1> ; bne 2f / branch if any are set 23300 <1> ;movzx ecx, byte [ebx] ; 09/06/2015 ; Device Id 23301 <1> ; movb (r1),r3 / get device id 23302 0000627B 0FB6C8 <1> movzx ecx, al ; 18/08/2015 23303 <1> ;mov edi, ecx ; 26/04/2013 23304 0000627E 31C0 <1> xor eax, eax ; 0 23305 <1> ;cmp [edi+drv.error], al ; 0 23306 <1> ; tstb deverr(r3) / test for errors on this device 23307 <1> ;jna short poke_2 23308 <1> ; beq 3f / branch if no errors 23309 <1> ; 02/07/2015 23310 <1> ;dec eax 23311 <1> ;mov [ebx+4], ax ; 0FFFFFFFFh ; -1 23312 <1> ; mov $-1,2(r1) / destroy associativity 23313 <1> ;shr eax, 24 23314 <1> ;mov [ebx], eax ; 000000FFh, reset 23315 <1> ; clrb 1(r1) / do not do I/O 23316 <1> ;jmp short poke_5 23317 <1> ; ; br 2f 23318 <1> ; rts r0 23319 <1> poke_2: ; 3: 23320 <1> ; 02/07/2015 23321 00006280 FEC1 <1> inc cl ; 0FFh -> 0 23322 00006282 7455 <1> jz short poke_5 23323 00006284 FEC0 <1> inc al ; mov ax, 1 23324 00006286 FEC9 <1> dec cl 23325 00006288 7402 <1> jz short poke_3 23326 <1> ; 26/04/2013 Modification 23327 <1> ;inc al ; mov ax, 1 23328 <1> ;or cl, cl ; Retro UNIX 8086 v1 device id. 23329 <1> ;jz short poke_3 ; cl = 0 23330 0000628A D2E0 <1> shl al, cl ; shl ax, cl 23331 <1> poke_3: 23332 <1> ;test [active], ax 23333 0000628C 8405[32740000] <1> test [active], al 23334 <1> ; bit $2,active / test disk busy bit 23335 00006292 7545 <1> jnz short poke_5 23336 <1> ; bne 2f / branch if bit is set 23337 <1> ;or [active], ax 23338 00006294 0805[32740000] <1> or [active], al 23339 <1> ; bis $2,active / set disk busy bit 23340 0000629A 6650 <1> push ax 23341 0000629C E8CB000000 <1> call diskio ; Retro UNIX 8086 v1 Only ! 23342 <1> ;mov [edi+drv.error], ah 23343 000062A1 6658 <1> pop ax 23344 000062A3 730E <1> jnc short poke_4 ; 20/07/2013 23345 <1> ;cmp [edi+drv.error], al ; 0 23346 <1> ;jna short poke_4 23347 <1> ; tstb deverr(r3) / test for errors on this device 23348 <1> ; beq 3f / branch if no errors 23349 <1> ; 02/07/2015 (32 bit modification) 23350 <1> ; 20/07/2013 23351 000062A5 C74304FFFFFFFF <1> mov dword [ebx+4], 0FFFFFFFFh ; -1 23352 <1> ; mov $-1,2(r1) / destroy associativity 23353 000062AC 66C703FF00 <1> mov word [ebx], 0FFh ; 20/08/2015 23354 <1> ; clrb 1(r1) / do not do I/O 23355 000062B1 EB26 <1> jmp short poke_5 23356 <1> poke_4: ; 20/07/2013 23357 <1> ; 17/07/2013 23358 000062B3 F6D0 <1> not al 23359 000062B5 2005[32740000] <1> and [active], al ; reset, not busy 23360 <1> ; eBX = system I/O buffer header (queue entry) address 23361 <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits. 23362 000062BB 668B03 <1> mov ax, [ebx] 23363 <1> ; mov (r1),r3 / move word 1 of I/O queue entry into r3 23364 000062BE 66250006 <1> and ax, 600h 23365 <1> ; bic $!3000,r3 / clear all bits except 9 and 10 23366 000062C2 668123FFF9 <1> and word [ebx], 0F9FFh 23367 <1> ; bic $3000,(r1) / clear only bits 9 and 10 23368 000062C7 C0E403 <1> shl ah, 3 23369 <1> ; rol r3 23370 <1> ; rol r3 23371 <1> ; rol r3 23372 000062CA 660903 <1> or [ebx], ax 23373 <1> ; bis r3,(r1) / or old value of bits 9 and 10 with 23374 <1> ; bits 12 and 13 23375 000062CD E887F1FFFF <1> call idle ; 18/01/2014 23376 <1> ;; sti 23377 <1> ;hlt ; wait for a hardware interrupt 23378 <1> ;; cli 23379 <1> ; NOTE: In fact, disk controller's 'disk I/O completed' 23380 <1> ; interrupt would be used to reset busy bits, but INT 13h 23381 <1> ; returns when disk I/O is completed. So, here, as temporary 23382 <1> ; method, this procedure will wait for a time according to 23383 <1> ; multi tasking and time sharing concept. 23384 <1> ; 23385 <1> ; 24/10/2015 23386 <1> ;not ax 23387 000062D2 66B8FF00 <1> mov ax, 0FFh ; 24/10/2015 (temporary) 23388 000062D6 662103 <1> and [ebx], ax ; clear bits 12 and 13 23389 <1> poke_5: ;2: 23390 000062D9 81FE[0A740000] <1> cmp esi, bufp 23391 <1> ; cmp r2,$bufp / test to see if entire I/O queue 23392 <1> ; / has been scanned 23393 000062DF 778D <1> ja short poke_1 23394 <1> ; bhi 1b 23395 <1> ; 24/03/2013 23396 <1> ; mov (sp)+,r3 23397 <1> ; mov (sp)+,r2 23398 <1> ; mov (sp)+,r1 23399 000062E1 58 <1> pop eax ; Physical Block Number (r1) (mget) 23400 000062E2 5B <1> pop ebx 23401 <1> ; 02/07/2015 (32 bit modification) 23402 <1> ; 20/07/2013 23403 <1> ;cmp dword [ebx+4], 0FFFFFFFFh 23404 000062E3 803BFF <1> cmp byte [ebx], 0FFh ; 20/08/2015 23405 <1> ; 23406 <1> ; 'poke' returns with cf=0 if the requested buffer is read 23407 <1> ; or written succesfully; even if an error occurs while 23408 <1> ; reading to or writing from other buffers. 20/07/2013 23409 <1> ; 23410 <1> ; 09/06/2015 23411 000062E6 F5 <1> cmc 23412 000062E7 C3 <1> retn 23413 <1> ; rts r0 23414 <1> 23415 <1> bufaloc: 23416 <1> ; 20/08/2015 23417 <1> ; 19/08/2015 23418 <1> ; 02/07/2015 23419 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 23420 <1> ; (32 bit modifications) 23421 <1> ; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1) 23422 <1> ; 23423 <1> ; bufaloc - Block device I/O buffer allocation 23424 <1> ; 23425 <1> ; INPUTS -> 23426 <1> ; r1 - block number 23427 <1> ; cdev - current (block/disk) device number 23428 <1> ; bufp+(2*n)-2 --- n = 1 ... nbuff 23429 <1> ; OUTPUTS -> 23430 <1> ; r5 - pointer to buffer allocated 23431 <1> ; bufp ... bufp+12 --- (bufp), (bufp)+2 23432 <1> ; 23433 <1> ; ((AX = R1)) input/output 23434 <1> ; ((BX = R5)) output 23435 <1> ; ((Modified registers: DX, CX, BX, SI, DI, BP)) 23436 <1> ; zf=1 -> block already in a I/O buffer 23437 <1> ; zf=0 -> a new I/O buffer has been allocated 23438 <1> ; ((DL = Device ID)) 23439 <1> ; (((DH = 0 or 1))) 23440 <1> ; (((CX = previous value of word ptr [bufp]))) 23441 <1> ; ((CX and DH will not be used after return))) 23442 <1> 23443 <1> ;;push esi ; *** 23444 <1> ; mov r2,-(sp) / save r2 on stack 23445 <1> ; mov $340,*$ps / set processor priority to 7 23446 <1> ; 20/07/2013 23447 <1> ; 26/04/2013 23448 000062E8 0FB61D[2E740000] <1> movzx ebx, byte [cdev] ; 0 or 1 23449 000062EF BF[30740000] <1> mov edi, rdev ; offset mdev = offset rdev + 1 23450 000062F4 01DF <1> add edi, ebx 23451 <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !! 23452 <1> ;; eDI points to device id. 23453 000062F6 0FB61F <1> movzx ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev 23454 <1> ; 11/06/20215 23455 000062F9 80BB[6A6B0000]F0 <1> cmp byte [ebx+drv.status], 0F0h ; Drive not ready ! 23456 00006300 720F <1> jb short bufaloc_9 23457 00006302 C705[9D740000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 23458 0000630A 0000 <1> 23459 0000630C E929DDFFFF <1> jmp error 23460 <1> bufaloc_9: 23461 00006311 89DA <1> mov edx, ebx ; dh = 0, dl = device number (0 to 5) 23462 <1> bufaloc_10: ; 02/07/2015 23463 00006313 31ED <1> xor ebp, ebp ; 0 23464 00006315 55 <1> push ebp ; 0 23465 00006316 89E5 <1> mov ebp, esp 23466 <1> ; 23467 <1> bufaloc_1: ;1: 23468 <1> ; clr -(sp) / vacant buffer 23469 00006318 BE[0A740000] <1> mov esi, bufp 23470 <1> ; mov $bufp,r2 / bufp contains pointers to I/O queue 23471 <1> ; / entrys in buffer area 23472 <1> bufaloc_2: ;2: 23473 0000631D 8B1E <1> mov ebx, [esi] 23474 <1> ; mov (r2)+,r5 / move pointer to word 1 of an I/O 23475 <1> ; queue entry into r5 23476 0000631F 66F70300F6 <1> test word [ebx], 0F600h 23477 <1> ; bit $173000,(r5) / lock+keep+active+outstanding 23478 00006324 7503 <1> jnz short bufaloc_3 23479 <1> ; bne 3f / branch when 23480 <1> ; / any of bits 9,10,12,13,14,15 are set 23481 <1> ; / (i.e., buffer busy) 23482 00006326 897500 <1> mov [ebp], esi ; pointer to I/0 queue entry 23483 <1> ; mov r2,(sp) ;/ save pointer to last non-busy buffer 23484 <1> ; / found points to word 2 of I/O queue entry) 23485 <1> bufaloc_3: ;3: 23486 <1> ;mov dl, [edi] ; 26/04/2013 23487 <1> ; 23488 00006329 3813 <1> cmp [ebx], dl 23489 <1> ; cmpb (r5),cdev / is device in I/O queue entry same 23490 <1> ; / as current device 23491 0000632B 7508 <1> jne short bufaloc_4 23492 <1> ; bne 3f 23493 0000632D 394304 <1> cmp [ebx+4], eax 23494 <1> ; cmp 2(r5),r1 / is block number in I/O queue entry, 23495 <1> ; / same as current block number 23496 00006330 7503 <1> jne short bufaloc_4 23497 <1> ; bne 3f 23498 <1> ;add esp, 4 23499 00006332 59 <1> pop ecx 23500 <1> ; tst (sp)+ / bump stack pointer 23501 00006333 EB20 <1> jmp short bufaloc_7 ; Retro Unix 8086 v1 modification 23502 <1> ; jump to bufaloc_6 in original Unix v1 23503 <1> ; br 1f / use this buffer 23504 <1> bufaloc_4: ;3: 23505 00006335 83C604 <1> add esi, 4 ; 20/08/2015 23506 <1> ; 23507 00006338 81FE[22740000] <1> cmp esi, bufp + (nbuf*4) 23508 <1> ; cmp r2,$bufp+nbuf+nbuf 23509 0000633E 72DD <1> jb short bufaloc_2 23510 <1> ; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all 23511 <1> ; / buffers not checked) 23512 00006340 5E <1> pop esi 23513 <1> ; mov (sp)+,r2 / once all bufs are examined move pointer 23514 <1> ; / to last free block 23515 00006341 09F6 <1> or esi, esi 23516 00006343 7507 <1> jnz short bufaloc_5 23517 <1> ; bne 2f / if (sp) is non zero, i.e., 23518 <1> ; / if a free buffer is found branch to 2f 23519 <1> ;; mov ecx, [s.wait_] 23520 00006345 E80FF1FFFF <1> call idle 23521 <1> ; jsr r0,idle; s.wait+2 / idle if no free buffers 23522 0000634A EBC7 <1> jmp short bufaloc_10 ; 02/07/2015 23523 <1> ; br 1b 23524 <1> bufaloc_5: ;2: 23525 <1> ; tst (r0)+ / skip if warmed over buffer 23526 0000634C FEC6 <1> inc dh ; Retro UNIX 8086 v1 modification 23527 <1> bufaloc_6: ;1: 23528 0000634E 8B1E <1> mov ebx, [esi] 23529 <1> ; mov -(r2),r5 / put pointer to word 1 of I/O queue 23530 <1> ; / entry in r5 23531 <1> ;; 26/04/2013 23532 <1> ;mov dl, [edi] ; byte [rdev] or byte [mdev] 23533 00006350 8813 <1> mov [ebx], dl 23534 <1> ; movb cdev,(r5) / put current device number 23535 <1> ; / in I/O queue entry 23536 00006352 894304 <1> mov [ebx+4], eax 23537 <1> ; mov r1,2(r5) / move block number into word 2 23538 <1> ; / of I/O queue entry 23539 <1> bufaloc_7: ;1: 23540 00006355 81FE[0A740000] <1> cmp esi, bufp 23541 <1> ; cmp r2,$bufp / bump all entrys in bufp 23542 <1> ; / and put latest assigned 23543 0000635B 760A <1> jna short bufaloc_8 23544 <1> ; blos 1f / buffer on the top 23545 <1> ; / (this makes if the lowest priority) 23546 0000635D 83EE04 <1> sub esi, 4 23547 00006360 8B0E <1> mov ecx, [esi] 23548 00006362 894E04 <1> mov [esi+4], ecx 23549 <1> ; mov -(r2),2(r2) / job for a particular device 23550 00006365 EBEE <1> jmp short bufaloc_7 23551 <1> ; br 1b 23552 <1> bufaloc_8: ;1: 23553 00006367 891E <1> mov [esi], ebx 23554 <1> ; mov r5,(r2) 23555 <1> ;;pop esi ; *** 23556 <1> ; mov (sp)+,r2 / restore r2 23557 00006369 08F6 <1> or dh, dh ; 0 or 1 ? 23558 <1> ; Retro UNIX 8086 v1 modification 23559 <1> ; zf=1 --> block already is in an I/O buffer 23560 <1> ; zf=0 --> a new I/O buffer has been allocated 23561 0000636B C3 <1> retn 23562 <1> ; rts r0 23563 <1> 23564 <1> diskio: 23565 <1> ; 10/07/2015 23566 <1> ; 02/07/2015 23567 <1> ; 16/06/2015 23568 <1> ; 11/06/2015 (Retro UNIX 386 v1 - Beginning) 23569 <1> ; (80386 protected mode modifications) 23570 <1> ; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1) 23571 <1> ; 23572 <1> ; Retro UNIX 8086 v1 feature only ! 23573 <1> ; 23574 <1> ; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011) 23575 <1> ; 04/07/2009 - 20/07/2011 23576 <1> ; 23577 <1> ; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes) 23578 <1> ; 23579 <1> ; INPUTS -> 23580 <1> ; eBX = System I/O Buffer header address 23581 <1> ; 23582 <1> ; OUTPUTS -> cf=0 --> done 23583 <1> ; cf=1 ---> error code in AH 23584 <1> ; 23585 <1> ; (Modified registers: eAX, eCX, eDX) 23586 <1> 23587 <1> ;rw_disk_sector: 23588 <1> ; 10/07/2015 23589 <1> ; 02/07/2015 23590 <1> ; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 23591 <1> ; 21/02/2015 ('dsectpm.s', 'read_disk_sector') 23592 <1> ; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s') 23593 <1> ; 01/12/2014 - 18/01/2015 ('dsectrm2.s') 23594 <1> ; 23595 <1> ;mov dx, 0201h ; Read 1 sector/block 23596 0000636C B602 <1> mov dh, 2 23597 0000636E 668B03 <1> mov ax, [ebx] 23598 <1> ; 23599 00006371 56 <1> push esi ; **** 23600 00006372 53 <1> push ebx ; *** 23601 <1> ; 23602 00006373 0FB6C8 <1> movzx ecx, al 23603 00006376 89CE <1> mov esi, ecx 23604 <1> ; 23605 00006378 38F1 <1> cmp cl, dh ; 2 23606 0000637A 7202 <1> jb short rwdsk0 23607 0000637C 047E <1> add al, 7Eh ; 80h, 81h, 82h, 83h 23608 <1> rwdsk0: 23609 0000637E A2[1B6B0000] <1> mov [drv], al 23610 00006383 81C6[6A6B0000] <1> add esi, drv.status 23611 <1> ; 11/06/2015 23612 00006389 803EF0 <1> cmp byte [esi], 0F0h 23613 0000638C 720F <1> jb short rwdsk1 23614 <1> ; 'drive not ready' error 23615 0000638E C705[9D740000]0F00- <1> mov dword [u.error], ERR_DRV_NOT_RDY 23616 00006396 0000 <1> 23617 00006398 E99DDCFFFF <1> jmp error 23618 <1> rwdsk1: 23619 0000639D F6C402 <1> test ah, 2 23620 <1> ;test ax, 200h ; Bit 9 of word 0 (status word) 23621 <1> ; write bit 23622 000063A0 7402 <1> jz short rwdsk2 23623 <1> ;test ah, 4 23624 <1> ;;test ax, 400h ; Bit 10 of word 0 (status word) 23625 <1> ; ; read bit 23626 <1> ;jz short diskio_ret 23627 000063A2 FEC6 <1> inc dh ; 03h = write 23628 <1> rwdsk2: 23629 000063A4 88C2 <1> mov dl, al 23630 000063A6 83C304 <1> add ebx, 4 ; sector/block address/number pointer 23631 000063A9 8B03 <1> mov eax, [ebx] ; sector/block number (LBA) 23632 000063AB C0E102 <1> shl cl, 2 23633 000063AE 81C1[4E6B0000] <1> add ecx, drv.size ; disk size 23634 000063B4 3B01 <1> cmp eax, [ecx] ; Last sector + 1 (number of secs.) 23635 000063B6 720F <1> jb short rwdsk3 23636 <1> ; 'out of volume' error 23637 000063B8 C705[9D740000]1000- <1> mov dword [u.error], ERR_DEV_VOL_SIZE 23638 000063C0 0000 <1> 23639 000063C2 E973DCFFFF <1> jmp error 23640 <1> rwdsk3: 23641 <1> ; 11/06/2015 23642 000063C7 83C304 <1> add ebx, 4 ; buffer address 23643 000063CA C605[CE740000]04 <1> mov byte [retry_count], 4 23644 000063D1 F60601 <1> test byte [esi], 1 ; LBA ready ? 23645 000063D4 7432 <1> jz short rwdsk_chs 23646 <1> rwdsk_lba: 23647 <1> ; LBA read/write (with private LBA function) 23648 <1> ;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan)) 23649 000063D6 83C607 <1> add esi, drv.error - drv.status ; 10/07/2015 23650 000063D9 89C1 <1> mov ecx, eax ; sector number 23651 <1> ; ebx = buffer (data) address 23652 <1> ; dl = physical drive number (0,1, 80h, 81h, 82h, 83h) 23653 <1> rwdsk_lba_retry: 23654 <1> ;mov dl, [drv] 23655 <1> ; Function 1Bh = LBA read, 1Ch = LBA write 23656 000063DB B419 <1> mov ah, 1Ch - 3h ; LBA write function number - 3 23657 000063DD 00F4 <1> add ah, dh 23658 000063DF B001 <1> mov al, 1 23659 <1> ;int 13h 23660 000063E1 E8DCC3FFFF <1> call int13h 23661 000063E6 8826 <1> mov [esi], ah ; error code ; 10/07/2015 23662 000063E8 730E <1> jnc short rwdsk_lba_ok 23663 000063EA 80FC80 <1> cmp ah, 80h ; time out ? 23664 000063ED 7408 <1> je short rwdsk_lba_fails 23665 000063EF FE0D[CE740000] <1> dec byte [retry_count] 23666 000063F5 7504 <1> jnz short rwdsk_lba_reset ; 10/07/2015 23667 <1> rwdsk_lba_fails: 23668 000063F7 F9 <1> stc 23669 <1> rwdsk_lba_ok: 23670 000063F8 5B <1> pop ebx ; *** 23671 000063F9 5E <1> pop esi ; **** 23672 000063FA C3 <1> retn 23673 <1> rwdsk_lba_reset: 23674 000063FB B40D <1> mov ah, 0Dh ; Alternate reset 23675 <1> ;int 13h 23676 000063FD E8C0C3FFFF <1> call int13h 23677 00006402 73D7 <1> jnc short rwdsk_lba_retry 23678 00006404 8826 <1> mov [esi], ah ; error code ; 10/07/2015 23679 00006406 EBF0 <1> jmp short rwdsk_lba_ok 23680 <1> ; 23681 <1> ; CHS read (convert LBA address to CHS values) 23682 <1> rwdsk_chs: 23683 <1> ; 10/07/2015 23684 00006408 81EE[6A6B0000] <1> sub esi, drv.status 23685 0000640E 89F1 <1> mov ecx, esi 23686 00006410 81C6[716B0000] <1> add esi, drv.error 23687 <1> ; 02/07/2015 23688 <1> ; 16/06/2015 23689 <1> ; 11/06/2015 23690 00006416 53 <1> push ebx ; ** ; buffer 23691 00006417 D1E1 <1> shl ecx, 1 23692 00006419 51 <1> push ecx ; * 23693 <1> ; 23694 0000641A 89CB <1> mov ebx, ecx 23695 0000641C 8835[CD740000] <1> mov [rwdsk], dh ; 02/07/2015 23696 00006422 31D2 <1> xor edx, edx ; 0 23697 00006424 29C9 <1> sub ecx, ecx 23698 00006426 81C3[406B0000] <1> add ebx, drv.spt 23699 0000642C 668B0B <1> mov cx, [ebx] ; sector per track 23700 <1> ; EDX:EAX = LBA 23701 0000642F F7F1 <1> div ecx 23702 00006431 88D1 <1> mov cl, dl ; sector number - 1 23703 00006433 FEC1 <1> inc cl ; sector number (1 based) 23704 00006435 5B <1> pop ebx ; * ; 11/06/2015 23705 00006436 6651 <1> push cx 23706 00006438 81C3[326B0000] <1> add ebx, drv.heads 23707 0000643E 668B0B <1> mov cx, [ebx] ; heads 23708 00006441 31D2 <1> xor edx, edx 23709 <1> ; EAX = cylinders * heads + head 23710 00006443 F7F1 <1> div ecx 23711 00006445 6659 <1> pop cx ; sector number 23712 00006447 88D6 <1> mov dh, dl ; head number 23713 00006449 8A15[1B6B0000] <1> mov dl, [drv] 23714 0000644F 88C5 <1> mov ch, al ; cylinder (bits 0-7) 23715 00006451 C0E406 <1> shl ah, 6 23716 00006454 08E1 <1> or cl, ah ; cylinder (bits 8-9) 23717 <1> ; sector (bits 0-7) 23718 00006456 5B <1> pop ebx ; ** ; buffer ; 11/06/2015 23719 <1> ; CL = sector (bits 0-5) 23720 <1> ; cylinder (bits 8-9 -> bits 6-7) 23721 <1> ; CH = cylinder (bits 0-7) 23722 <1> ; DH = head 23723 <1> ; DL = drive 23724 <1> ; 23725 00006457 C605[CE740000]04 <1> mov byte [retry_count], 4 23726 <1> rwdsk_retry: 23727 0000645E 8A25[CD740000] <1> mov ah, [rwdsk] ; 02h = read, 03h = write 23728 00006464 B001 <1> mov al, 1 ; sector count 23729 <1> ;int 13h 23730 00006466 E857C3FFFF <1> call int13h 23731 0000646B 8826 <1> mov [esi], ah ; error code ; 10/07/2015 23732 0000646D 730E <1> jnc short rwdsk_ok ; ah = 0 23733 0000646F 80FC80 <1> cmp ah, 80h ; time out ? 23734 00006472 7408 <1> je short rwdsk_fails 23735 00006474 FE0D[CE740000] <1> dec byte [retry_count] 23736 0000647A 7504 <1> jnz short rwdsk_reset 23737 <1> rwdsk_fails: 23738 0000647C F9 <1> stc 23739 <1> rwdsk_ok: 23740 0000647D 5B <1> pop ebx ; *** 23741 0000647E 5E <1> pop esi ; **** 23742 0000647F C3 <1> retn 23743 <1> rwdsk_reset: 23744 <1> ; 02/02/2015 23745 00006480 28E4 <1> sub ah, ah 23746 00006482 80FA80 <1> cmp dl, 80h 23747 00006485 7202 <1> jb short rwdsk_fd_reset 23748 00006487 B40D <1> mov ah, 0Dh ; Alternate reset 23749 <1> rwdsk_fd_reset: 23750 <1> ;int 13h 23751 00006489 E834C3FFFF <1> call int13h 23752 0000648E 73CE <1> jnc short rwdsk_retry 23753 00006490 8826 <1> mov [esi], ah ; error code ; 10/07/2015 23754 00006492 EBE9 <1> jmp short rwdsk_ok 23755 <1> 23756 <1> 23757 <1> ; Original UNIX v1 - drum (& disk) interrupt routine 23758 <1> ; (Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts) 23759 <1> ; 23760 <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now. 23761 <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 23762 <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h 23763 <1> ; that uses hardware -transfer has been completed- interrupt inside it. 23764 <1> ; In a next Retro UNIX 386 version, these interrupts 23765 <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine 23766 <1> ; as in original unix v1. 23767 <1> ; I am not removing IBM BIOS source code derivatives -compatible code- 23768 <1> ; for now, regarding the new/next 32 bit TRDOS project by me 23769 <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.) 23770 <1> ; 23771 <1> ; Erdogan tan (10/07/2015) 23772 <1> 23773 <1> ;drum: / interrupt handler 23774 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 23775 <1> ; jsr r0,trapt; dcs; rfap; 1 / check for stray interrupt or 23776 <1> ; / error 23777 <1> ; br 3f / no, error 23778 <1> ; br 2f / error 23779 <1> ; 23780 <1> ;disk: 23781 <1> ; jsr r0,setisp / save r1,r2,r3, and clockp on the stack 23782 <1> ; jmp *$0f 23783 <1> ;0: 23784 <1> ; jsr r0,trapt; rkcs; rkap; 2 23785 <1> ; br 3f / no, errors 23786 <1> ; mov $115,(r2) / drive reset, errbit was set 23787 <1> ; mov $1f,0b-2 / next time jmp *$0f is executed jmp will be 23788 <1> ; / to 1f 23789 <1> ; br 4f 23790 <1> ;1: 23791 <1> ; bit $20000,rkcs 23792 <1> ; beq 4f / wait for seek complete 23793 <1> ; mov $0b,0b-2 23794 <1> ; mov rkap,r1 23795 <1> ;2: 23796 <1> ; bit $3000,(r1) / are bits 9 or 10 set in the 1st word of 23797 <1> ; / the disk buffer 23798 <1> ; bne 3f / no, branch ignore error if outstanding 23799 <1> ; inc r1 23800 <1> ; asr (r1) 23801 <1> ; asr (r1) 23802 <1> ; asr (r1) / reissue request 23803 <1> ; dec r1 23804 <1> ;3: 23805 <1> ; bic $30000,(r1) / clear bits 12 and 13 in 1st word of buffer 23806 <1> ; mov ac,-(sp) 23807 <1> ; mov mq,-(sp) / put these on the stack 23808 <1> ; mov sc,-(sp) 23809 <1> ; jsr r0,poke 23810 <1> ; mov (sp)+,sc 23811 <1> ; mov (sp)+,mq / pop them off stack 23812 <1> ; mov (sp)+,ac 23813 <1> ;4: 23814 <1> ; jmp retisp / u4-3 23815 <1> ; 23816 <1> ;trapt: / r2 points to the 23817 <1> ; mov (r0)+,r2 / device control register 23818 <1> ; mov *(r0)+,r1 / transaction pointer points to buffer 23819 <1> ; tst (sp)+ 23820 <1> ; tstb (r2) / is ready bit of dcs set? 23821 <1> ; bge 4b / device still active so branch 23822 <1> ; bit (r0),active / was device busy? 23823 <1> ; beq 4b / no, stray interrupt 23824 <1> ; bic (r0)+,active / yes, set active to zero 23825 <1> ; tst (r2) / test the err(bit is) of dcs 23826 <1> ; bge 2f / if no error jump to 2f 23827 <1> ; tst (r0)+ / skip on error 23828 <1> ; 2: 23829 <1> ; jmp (r0) 23830 %include 'u9.s' ; 29/06/2015 23831 <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS9.INC 23832 <1> ; Last Modification: 09/12/2015 23833 <1> ; ---------------------------------------------------------------------------- 23834 <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan 23835 <1> ; (v0.1 - Beginning: 11/07/2012) 23836 <1> ; 23837 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 23838 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 23839 <1> ; 23840 <1> ; 23841 <1> ; 23842 <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s 23843 <1> ; 23844 <1> ; **************************************************************************** 23845 <1> 23846 <1> getch: 23847 <1> ; 30/06/2015 23848 <1> ; 18/02/2015 - Retro UNIX 386 v1 - feature only! 23849 00006494 28C0 <1> sub al, al ; 0 23850 <1> getch_q: ; 06/08/2015 23851 00006496 8A25[96700000] <1> mov ah, [ptty] ; active (current) video page 23852 0000649C EB06 <1> jmp short getc_n 23853 <1> 23854 <1> getc: 23855 <1> ; 12/11/2015 23856 <1> ; 15/09/2015 23857 <1> ; 01/07/2015 23858 <1> ; 30/06/2015 23859 <1> ; 18/02/2015 (Retro UNIX 386 v1 - Beginning) 23860 <1> ; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1) 23861 <1> ; 23862 <1> ; Retro UNIX 8086 v1 modification ! 23863 <1> ; 23864 <1> ; 'getc' gets (next) character 23865 <1> ; from requested TTY (keyboard) buffer 23866 <1> ; INPUTS -> 23867 <1> ; [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2) 23868 <1> ; AL=0 -> Get (next) character from requested TTY buffer 23869 <1> ; (Keyboard buffer will point to 23870 <1> ; next character at next call) 23871 <1> ; AL=1 -> Test a key is available in requested TTY buffer 23872 <1> ; (Keyboard buffer will point to 23873 <1> ; current character at next call) 23874 <1> ; OUTPUTS -> 23875 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 23876 <1> ; ZF=0 -> AX has (current) character 23877 <1> ; AL = ascii code 23878 <1> ; AH = scan code (AH = line status for COM1 or COM2) 23879 <1> ; (cf=1 -> error code/flags in AH) 23880 <1> ; Original UNIX V1 'getc': 23881 <1> ; get a character off character list 23882 <1> ; 23883 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 23884 <1> ; 23885 <1> ; 30/06/20045 (32 bit modifications) 23886 <1> ; 16/07/2013 23887 <1> ; mov [getctty], ah 23888 <1> ; 23889 <1> 23890 0000649E 8A25[9C740000] <1> mov ah, [u.ttyn] ; 28/07/2013 23891 <1> getc_n: 23892 <1> ; 30/06/2015 23893 000064A4 08E4 <1> or ah, ah 23894 000064A6 740D <1> jz short getc0 23895 000064A8 D0E4 <1> shl ah, 1 23896 000064AA 0FB6DC <1> movzx ebx, ah 23897 000064AD 81C3[98700000] <1> add ebx, ttychr 23898 000064B3 EB05 <1> jmp short getc1 23899 <1> getc0: 23900 000064B5 BB[98700000] <1> mov ebx, ttychr 23901 <1> getc1: 23902 000064BA 668B0B <1> mov cx, [ebx] ; ascii & scan code 23903 <1> ; (by kb_int) 23904 000064BD 6609C9 <1> or cx, cx 23905 000064C0 7508 <1> jnz short getc2 23906 000064C2 20C0 <1> and al, al 23907 000064C4 7416 <1> jz short getc_s 23908 000064C6 6631C0 <1> xor ax, ax 23909 000064C9 C3 <1> retn 23910 <1> getc2: 23911 000064CA 20C0 <1> and al, al 23912 000064CC 6689C8 <1> mov ax, cx 23913 000064CF 66B90000 <1> mov cx, 0 23914 000064D3 7506 <1> jnz short getc3 23915 <1> getc_sn: 23916 000064D5 66890B <1> mov [ebx], cx ; 0, reset 23917 000064D8 6639C8 <1> cmp ax, cx ; zf = 0 23918 <1> getc3: 23919 000064DB C3 <1> retn 23920 <1> getc_s: 23921 <1> ; 12/11/2015 23922 <1> ; 15/09/2015 23923 <1> ; 01/07/2015 23924 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 23925 <1> ; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1) 23926 <1> ; 23927 <1> ; tty of the current process is not 23928 <1> ; current tty (ptty); so, current process only 23929 <1> ; can use keyboard input when its tty becomes 23930 <1> ; current tty (ptty). 23931 <1> ; 'sleep' is for preventing an endless lock 23932 <1> ; during this tty input request. 23933 <1> ; (Because, the user is not looking at the video page 23934 <1> ; of the process to undersand there is a keyboard 23935 <1> ; input request.) 23936 <1> ; 23937 <1> ;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 23938 <1> ; 23939 <1> ; 05/10/2013 23940 <1> ; ah = byte ptr [u.ttyn] ; (tty number) 23941 <1> ; 23942 <1> ; 10/10/2013 23943 <1> gcw0: 23944 000064DC B10A <1> mov cl, 10 ; ch = 0 23945 <1> gcw1: 23946 <1> ; 12/11/2015 23947 000064DE E859DCFFFF <1> call intract ; jumps to 'sysexit' if [u.quit] = FFFFh 23948 <1> ; 10/10/2013 23949 000064E3 E871EFFFFF <1> call idle 23950 000064E8 668B03 <1> mov ax, [ebx] ; ascii & scan code 23951 <1> ; (by kb_int) 23952 000064EB 6609C0 <1> or ax, ax 23953 <1> ; jnz short gcw3 23954 000064EE 7519 <1> jnz short gcw2 ; 15/09/2015 23955 <1> ; 30/06/2015 23956 000064F0 FEC9 <1> dec cl 23957 000064F2 75EA <1> jnz short gcw1 23958 <1> ; 23959 000064F4 8A25[9C740000] <1> mov ah, [u.ttyn] ; 20/10/2013 23960 <1> ; ; 10/12/2013 23961 <1> ; cmp ah, [ptty] 23962 <1> ; jne short gcw2 23963 <1> ; ; 14/02/2014 23964 <1> ; cmp byte [u.uno], 1 23965 <1> ; jna short gcw0 23966 <1> ;gcw2: 23967 000064FA E8EEEFFFFF <1> call sleep 23968 <1> ; 23969 <1> ; 20/09/2013 23970 000064FF 8A25[9C740000] <1> mov ah, [u.ttyn] 23971 00006505 30C0 <1> xor al, al 23972 00006507 EB9B <1> jmp short getc_n 23973 <1> ;gcw3: 23974 <1> gcw2: ; 15/09/2015 23975 <1> ; 10/10/2013 23976 00006509 30C9 <1> xor cl, cl 23977 0000650B EBC8 <1> jmp short getc_sn 23978 <1> 23979 <1> sndc: ; 23980 <1> ; 23981 <1> ; 17/11/2015 23982 <1> ; 16/11/2015 23983 <1> ; 11/11/2015 23984 <1> ; 10/11/2015 23985 <1> ; 09/11/2015 23986 <1> ; 08/11/2015 23987 <1> ; 07/11/2015 23988 <1> ; 06/11/2015 (serial4.asm, 'sendchr') 23989 <1> ; 29/10/2015 23990 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 23991 <1> ; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1) 23992 <1> ; 23993 <1> ; Retro UNIX 8086 v1 feature only ! 23994 <1> ; 23995 <1> ; ah = [u.ttyn] 23996 <1> ; 23997 <1> ; 30/06/2015 23998 0000650D 80EC08 <1> sub ah, 8 ; ; 0 = tty8 or 1 = tty9 23999 <1> ; 07/11/2015 24000 00006510 0FB6DC <1> movzx ebx, ah ; serial port index (0 or 1) 24001 <1> sndc0: 24002 <1> ; 07/11/2015 24003 00006513 E82EF0FFFF <1> call isintr ; quit (ctrl+break) check 24004 00006518 7405 <1> jz short sndc1 24005 0000651A E81DDCFFFF <1> call intract ; quit (ctrl+break) check 24006 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 24007 <1> sndc1: 24008 <1> ; 16/11/2015 24009 0000651F 6689C1 <1> mov cx, ax ; *** al = character (to be sent) 24010 <1> sndcx: 24011 00006522 8A83[DA700000] <1> mov al, [ebx+schar] ; last sent character 24012 00006528 8AA3[D8700000] <1> mov ah, [ebx+rchar] ; last received character 24013 <1> ; 24014 <1> ; 17/11/2015 24015 <1> ; check 'request for response' status 24016 0000652E 80BB[D4700000]00 <1> cmp byte [ebx+req_resp], 0 24017 00006535 740A <1> jz short query 24018 <1> response: 24019 00006537 FE05[D7700000] <1> inc byte [comqr] ; query or response status 24020 0000653D B0FF <1> mov al, 0FFh 24021 0000653F EB14 <1> jmp short sndc3 24022 <1> query: 24023 00006541 08C0 <1> or al, al ; 0 = query (also end of text) 24024 00006543 750E <1> jnz short sndc2 ; normal character 24025 <1> ;cmp ah, 0FFh ; is it responded by terminal ? 24026 <1> ;je short sndc2 ; yes, already responded 24027 <1> ; 16/11/2015 24028 <1> ; query: request for response (again) 24029 00006545 8883[D8700000] <1> mov [ebx+rchar], al ; 0 ; reset 24030 0000654B FE05[D7700000] <1> inc byte [comqr] ; query or response status 24031 00006551 EB02 <1> jmp short sndc3 24032 <1> sndc2: 24033 00006553 88C8 <1> mov al, cl ; *** character (to be sent) 24034 <1> sndc3: 24035 00006555 8883[DA700000] <1> mov [ebx+schar], al ; current character (to be sent) 24036 0000655B 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 24037 <1> ; 30/06/2015 24038 0000655D E87DD5FFFF <1> call sp_status ; get serial port status 24039 <1> ; AL = Line status, AH = Modem status 24040 <1> ; 07/11/2015 24041 00006562 A880 <1> test al, 80h 24042 00006564 7504 <1> jnz short sndc4 24043 00006566 A820 <1> test al, 20h ; Transmitter holding register empty ? 24044 00006568 751D <1> jnz short sndc5 24045 <1> sndc4: ; Check line status again 24046 <1> ; 16/11/2015 24047 0000656A 6651 <1> push cx 24048 0000656C B906000000 <1> mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 24049 00006571 E873B0FFFF <1> call WAITF 24050 00006576 6659 <1> pop cx 24051 <1> ; 24052 00006578 88D8 <1> mov al, bl ; 0 or 1 (serial port index) 24053 0000657A E860D5FFFF <1> call sp_status ; get serial port status 24054 <1> ; 16/11/2015 24055 <1> ; 09/11/2015 24056 <1> ; 08/11/2015 24057 0000657F A880 <1> test al, 80h ; time out error 24058 00006581 756C <1> jnz short sndc7 24059 00006583 A820 <1> test al, 20h ; Transmitter holding register empty ? 24060 00006585 7468 <1> jz short sndc7 24061 <1> sndc5: 24062 00006587 8A83[DA700000] <1> mov al, [ebx+schar] ; character (to be sent) 24063 0000658D 66BAF803 <1> mov dx, 3F8h ; data port (COM2) 24064 00006591 28DE <1> sub dh, bl 24065 00006593 EE <1> out dx, al ; send on serial port 24066 <1> ; 10/11/2015 24067 <1> ; delay for 3*30 (3*(15..80)) micro seconds 24068 <1> ; (to improve text flow to the terminal) 24069 <1> ; ('diskette.inc': 'WAITF') 24070 <1> ; Uses port 61h, bit 4 to have CPU speed independent waiting. 24071 <1> ; (refresh periods = 1 per 30 microseconds on most machines) 24072 00006594 6651 <1> push cx 24073 00006596 B906000000 <1> mov ecx, 6 ; 6*30 micro seconds (~5556 chars/second) 24074 0000659B E849B0FFFF <1> call WAITF 24075 000065A0 6659 <1> pop cx 24076 <1> ; 24077 <1> ; 07/11/2015 24078 000065A2 88D8 <1> mov al, bl ; al = 0 (tty8) or 1 (tty9) 24079 <1> ; 24080 000065A4 E836D5FFFF <1> call sp_status ; get serial port status 24081 <1> ; AL = Line status, AH = Modem status 24082 <1> ; 24083 000065A9 E898EFFFFF <1> call isintr ; quit (ctrl+break) check 24084 000065AE 7405 <1> jz short sndc6 24085 000065B0 E887DBFFFF <1> call intract ; quit (ctrl+break) check 24086 <1> ; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes) 24087 <1> sndc6: 24088 000065B5 3C80 <1> cmp al, 80h 24089 000065B7 7336 <1> jnb short sndc7 24090 <1> ; 24091 000065B9 803D[D7700000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 24092 000065C0 7248 <1> jb short sndc8 ; no, normal character 24093 000065C2 883D[D7700000] <1> mov byte [comqr], bh ; 0 ; reset 24094 <1> ; 17/11/2015 24095 000065C8 E88CEEFFFF <1> call idle 24096 <1> ; 24097 000065CD 38BB[DA700000] <1> cmp [ebx+schar], bh ; 0 ; query ? 24098 000065D3 0F877AFFFFFF <1> ja sndc2 ; response (will be followed by 24099 <1> ; a normal character) 24100 <1> ; Query request must be responded by the terminal 24101 <1> ; before sending a normal character ! 24102 000065D9 53 <1> push ebx 24103 000065DA 6651 <1> push cx ; *** cl = character (to be sent) 24104 000065DC 8A25[9C740000] <1> mov ah, [u.ttyn] 24105 000065E2 E806EFFFFF <1> call sleep ; this process will be awakened by 24106 <1> ; received data available interrupt 24107 000065E7 6659 <1> pop cx ; *** cl = character (to be sent) 24108 000065E9 5B <1> pop ebx 24109 000065EA E933FFFFFF <1> jmp sndcx 24110 <1> sndc7: 24111 <1> ; 16/11/2015 24112 000065EF 803D[D7700000]01 <1> cmp byte [comqr], 1 ; 'query or response' ? 24113 000065F6 7213 <1> jb short sndc9 ; no 24114 <1> ; 24115 000065F8 88BB[D8700000] <1> mov [ebx+rchar], bh ; 0 ; reset 24116 000065FE 88BB[DA700000] <1> mov [ebx+schar], bh ; 0 ; reset 24117 <1> ; 24118 00006604 883D[D7700000] <1> mov byte [comqr], bh ; 0 ; reset 24119 <1> sndc8: 24120 0000660A F5 <1> cmc ; jnc -> jc, jb -> jnb 24121 <1> sndc9: 24122 <1> ; AL = Line status, AH = Modem status 24123 0000660B C3 <1> retn 24124 <1> 24125 <1> putc: 24126 <1> ; 13/08/2015 24127 <1> ; 30/06/2015 (Retro UNIX 386 v1 - Beginning) 24128 <1> ; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1) 24129 <1> ; 24130 <1> ; Retro UNIX 8086 v1 modification ! 24131 <1> ; 24132 <1> ; 'putc' puts a character 24133 <1> ; onto requested (tty) video page or 24134 <1> ; serial port 24135 <1> ; INPUTS -> 24136 <1> ; AL = ascii code of the character 24137 <1> ; AH = video page (tty) number (0 to 7) 24138 <1> ; (8 is COM1, 9 is COM2) 24139 <1> ; OUTPUTS -> 24140 <1> ; (If AL input is 1) ZF=1 -> 'empty buffer' (no chars) 24141 <1> ; ZF=0 -> AX has (current) character 24142 <1> ; cf=0 and AH = 0 -> no error 24143 <1> ; cf=1 and AH > 0 -> error (only for COM1 and COM2) 24144 <1> ; 24145 <1> ; Original UNIX V1 'putc': 24146 <1> ; put a character at the end of character list 24147 <1> ; 24148 <1> ; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI)) 24149 <1> ; 24150 0000660C 80FC07 <1> cmp ah, 7 24151 0000660F 0F87F8FEFFFF <1> ja sndc 24152 <1> ; 30/06/2015 24153 00006615 0FB6DC <1> movzx ebx, ah 24154 <1> ; 13/08/2015 24155 00006618 B407 <1> mov ah, 07h ; black background, light gray character color 24156 0000661A E9BBAEFFFF <1> jmp write_tty ; 'video.inc' 24157 <1> 24158 <1> get_cpos: 24159 <1> ; 29/06/2015 (Retro UNIX 386 v1) 24160 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 24161 <1> ; 24162 <1> ; INPUT -> bl = video page number 24163 <1> ; RETURN -> dx = cursor position 24164 <1> 24165 0000661F 53 <1> push ebx 24166 00006620 83E30F <1> and ebx, 0Fh ; 07h ; tty0 to tty7 24167 00006623 D0E3 <1> shl bl, 1 24168 00006625 81C3[86700000] <1> add ebx, cursor_posn 24169 0000662B 668B13 <1> mov dx, [ebx] 24170 0000662E 5B <1> pop ebx 24171 0000662F C3 <1> retn 24172 <1> 24173 <1> read_ac_current: 24174 <1> ; 29/06/2015 (Retro UNIX 386 v1) 24175 <1> ; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty') 24176 <1> ; 24177 <1> ; INPUT -> bl = video page number 24178 <1> ; RETURN -> ax = character (al) and attribute (ah) 24179 <1> 24180 00006630 E826B0FFFF <1> call find_position ; 'video.inc' 24181 <1> ; dx = status port 24182 <1> ; esi = cursor location/address 24183 00006635 81C600800B00 <1> add esi, 0B8000h ; 30/08/2014 (Retro UNIX 386 v1) 24184 0000663B 668B06 <1> mov ax, [esi] ; get the character and attribute 24185 0000663E C3 <1> retn 24186 <1> 24187 <1> syssleep: 24188 <1> ; 29/06/2015 - (Retro UNIX 386 v1) 24189 <1> ; 11/06/2014 - (Retro UNIX 8086 v1) 24190 <1> ; 24191 <1> ; Retro UNIX 8086 v1 feature only 24192 <1> ; (INPUT -> none) 24193 <1> ; 24194 0000663F 0FB61D[97740000] <1> movzx ebx, byte [u.uno] ; process number 24195 00006646 8AA3[95710000] <1> mov ah, [ebx+p.ttyc-1] ; current/console tty 24196 0000664C E89CEEFFFF <1> call sleep 24197 00006651 E904DAFFFF <1> jmp sysret 24198 <1> 24199 <1> vp_clr: 24200 <1> ; Reset/Clear Video Page 24201 <1> ; 24202 <1> ; 30/06/2015 - (Retro UNIX 386 v1) 24203 <1> ; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM) 24204 <1> ; 24205 <1> ; Retro UNIX 8086 v1 feature only ! 24206 <1> ; 24207 <1> ; INPUTS -> 24208 <1> ; BL = video page number 24209 <1> ; 24210 <1> ; OUTPUT -> 24211 <1> ; none 24212 <1> ; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI)) 24213 <1> ; 24214 <1> ; 04/12/2013 24215 00006656 28C0 <1> sub al, al 24216 <1> ; al = 0 (clear video page) 24217 <1> ; bl = video page 24218 00006658 B407 <1> mov ah, 07h 24219 <1> ; ah = 7 (attribute/color) 24220 0000665A 6631C9 <1> xor cx, cx ; 0, left upper column (cl) & row (cl) 24221 0000665D 66BA4F18 <1> mov dx, 184Fh ; right lower column & row (dl=24, dh=79) 24222 00006661 E821B0FFFF <1> call scroll_up 24223 <1> ; bl = video page 24224 00006666 6631D2 <1> xor dx, dx ; 0 (cursor position) 24225 00006669 E990AFFFFF <1> jmp set_cpos 24226 <1> 24227 <1> sysmsg: 24228 <1> ; 11/11/2015 24229 <1> ; 01/07/2015 - (Retro UNIX 386 v1 feature only!) 24230 <1> ; Print user-application message on user's console tty 24231 <1> ; 24232 <1> ; Input -> EBX = Message address 24233 <1> ; ECX = Message length (max. 255) 24234 <1> ; DL = Color (IBM PC Rombios color attributes) 24235 <1> ; 24236 0000666E 81F9FF000000 <1> cmp ecx, MAX_MSG_LEN ; 255 24237 00006674 0F87E0D9FFFF <1> ja sysret ; nothing to do with big message size 24238 0000667A 08C9 <1> or cl, cl 24239 0000667C 0F84D8D9FFFF <1> jz sysret 24240 00006682 20D2 <1> and dl, dl 24241 00006684 7502 <1> jnz short sysmsg0 24242 00006686 B207 <1> mov dl, 07h ; default color 24243 <1> ; (black background, light gray character) 24244 <1> sysmsg0: 24245 00006688 891D[68740000] <1> mov [u.base], ebx 24246 0000668E 8815[97700000] <1> mov [ccolor], dl ; color attributes 24247 00006694 89E5 <1> mov ebp, esp 24248 00006696 31DB <1> xor ebx, ebx ; 0 24249 00006698 891D[70740000] <1> mov [u.nread], ebx ; 0 24250 <1> ; 24251 0000669E 381D[AF740000] <1> cmp [u.kcall], bl ; 0 24252 000066A4 7769 <1> ja short sysmsgk ; Temporary (01/07/2015) 24253 <1> ; 24254 000066A6 890D[6C740000] <1> mov [u.count], ecx 24255 000066AC 41 <1> inc ecx ; + 00h ; ASCIZZ 24256 000066AD 29CC <1> sub esp, ecx 24257 000066AF 89E7 <1> mov edi, esp 24258 000066B1 89E6 <1> mov esi, esp 24259 000066B3 66891D[AD740000] <1> mov [u.pcount], bx ; reset page (phy. addr.) counter 24260 <1> ; 11/11/2015 24261 000066BA 8A25[78740000] <1> mov ah, [u.ttyp] ; recent open tty 24262 <1> ; 0 = none 24263 000066C0 FECC <1> dec ah 24264 000066C2 790C <1> jns short sysmsg1 24265 000066C4 8A1D[97740000] <1> mov bl, [u.uno] ; process number 24266 000066CA 8AA3[95710000] <1> mov ah, [ebx+p.ttyc-1] ; user's (process's) console tty 24267 <1> sysmsg1: 24268 000066D0 8825[9C740000] <1> mov [u.ttyn], ah 24269 <1> sysmsg2: 24270 000066D6 E89CF5FFFF <1> call cpass 24271 000066DB 7416 <1> jz short sysmsg5 24272 000066DD AA <1> stosb 24273 000066DE 20C0 <1> and al, al 24274 000066E0 75F4 <1> jnz short sysmsg2 24275 <1> sysmsg3: 24276 000066E2 80FC07 <1> cmp ah, 7 ; tty number 24277 000066E5 7711 <1> ja short sysmsg6 ; serial port 24278 000066E7 E83E000000 <1> call print_cmsg 24279 <1> sysmsg4: 24280 000066EC 89EC <1> mov esp, ebp 24281 000066EE E967D9FFFF <1> jmp sysret 24282 <1> sysmsg5: 24283 000066F3 C60700 <1> mov byte [edi], 0 24284 000066F6 EBEA <1> jmp short sysmsg3 24285 <1> sysmsg6: 24286 000066F8 8A06 <1> mov al, [esi] 24287 000066FA E80EFEFFFF <1> call sndc 24288 000066FF 72EB <1> jc short sysmsg4 24289 00006701 803E00 <1> cmp byte [esi], 0 ; 0 is stop character 24290 00006704 76E6 <1> jna short sysmsg4 24291 00006706 46 <1> inc esi 24292 00006707 8A25[9C740000] <1> mov ah, [u.ttyn] 24293 0000670D EBE9 <1> jmp short sysmsg6 24294 <1> 24295 <1> sysmsgk: ; Temporary (01/07/2015) 24296 <1> ; The message has been sent by Kernel (ASCIIZ string) 24297 <1> ; (ECX -character count- will not be considered) 24298 0000670F 8B35[68740000] <1> mov esi, [u.base] 24299 00006715 8A25[96700000] <1> mov ah, [ptty] ; present/current screen (video page) 24300 0000671B 8825[9C740000] <1> mov [u.ttyn], ah 24301 00006721 C605[AF740000]00 <1> mov byte [u.kcall], 0 24302 00006728 EBB8 <1> jmp short sysmsg3 24303 <1> 24304 <1> 24305 <1> print_cmsg: 24306 <1> ; 01/07/2015 (retro UNIX 386 v1 feature only !) 24307 <1> ; 24308 <1> ; print message (on user's console tty) 24309 <1> ; with requested color 24310 <1> ; 24311 <1> ; INPUTS: 24312 <1> ; esi = message address 24313 <1> ; [u.ttyn] = tty number (0 to 7) 24314 <1> ; [ccolor] = color attributes (IBM PC BIOS colors) 24315 <1> ; 24316 0000672A AC <1> lodsb 24317 <1> pcmsg1: 24318 0000672B 56 <1> push esi 24319 0000672C 0FB61D[9C740000] <1> movzx ebx, byte [u.ttyn] 24320 00006733 8A25[97700000] <1> mov ah, [ccolor] 24321 00006739 E89CADFFFF <1> call write_tty 24322 0000673E 5E <1> pop esi 24323 0000673F AC <1> lodsb 24324 00006740 20C0 <1> and al, al ; 0 24325 00006742 75E7 <1> jnz short pcmsg1 24326 00006744 C3 <1> retn 24327 <1> 24328 <1> sysgeterr: 24329 <1> ; 09/12/2015 24330 <1> ; 21/09/2015 - (Retro UNIX 386 v1 feature only!) 24331 <1> ; Get last error number or page fault count 24332 <1> ; (for debugging) 24333 <1> ; 24334 <1> ; Input -> EBX = return type 24335 <1> ; 0 = last error code (which is in 'u.error') 24336 <1> ; FFFFFFFFh = page fault count for running process 24337 <1> ; FFFFFFFEh = total page fault count 24338 <1> ; 1 .. FFFFFFFDh = undefined 24339 <1> ; 24340 <1> ; Output -> EAX = last error number or page fault count 24341 <1> ; (depending on EBX input) 24342 <1> ; 24343 00006745 21DB <1> and ebx, ebx 24344 00006747 750B <1> jnz short glerr_2 24345 <1> glerr_0: 24346 00006749 A1[9D740000] <1> mov eax, [u.error] 24347 <1> glerr_1: 24348 0000674E A3[48740000] <1> mov [u.r0], eax 24349 00006753 C3 <1> retn 24350 <1> glerr_2: 24351 00006754 43 <1> inc ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh 24352 00006755 74FD <1> jz short glerr_2 ; page fault count for process 24353 00006757 43 <1> inc ebx ; FFFFFFFFh -> 0 24354 00006758 75EF <1> jnz short glerr_0 24355 0000675A A1[30850000] <1> mov eax, [PF_Count] ; total page fault count 24356 0000675F EBED <1> jmp short glerr_1 24357 <1> glerr_3: 24358 00006761 A1[B1740000] <1> mov eax, [u.pfcount] 24359 00006766 EBE6 <1> jmp short glerr_1 24360 24361 ; 07/03/2015 24362 ; Temporary Code 24363 display_disks: 24364 00006768 803D[1E6B0000]00 cmp byte [fd0_type], 0 24365 0000676F 7605 jna short ddsks1 24366 00006771 E87D000000 call pdskm 24367 ddsks1: 24368 00006776 803D[1F6B0000]00 cmp byte [fd1_type], 0 24369 0000677D 760C jna short ddsks2 24370 0000677F C605[4B6D0000]31 mov byte [dskx], '1' 24371 00006786 E868000000 call pdskm 24372 ddsks2: 24373 0000678B 803D[206B0000]00 cmp byte [hd0_type], 0 24374 00006792 7654 jna short ddsk6 24375 00006794 66C705[496D0000]68- mov word [dsktype], 'hd' 24376 0000679C 64 24377 0000679D C605[4B6D0000]30 mov byte [dskx], '0' 24378 000067A4 E84A000000 call pdskm 24379 ddsks3: 24380 000067A9 803D[216B0000]00 cmp byte [hd1_type], 0 24381 000067B0 7636 jna short ddsk6 24382 000067B2 C605[4B6D0000]31 mov byte [dskx], '1' 24383 000067B9 E835000000 call pdskm 24384 ddsks4: 24385 000067BE 803D[226B0000]00 cmp byte [hd2_type], 0 24386 000067C5 7621 jna short ddsk6 24387 000067C7 C605[4B6D0000]32 mov byte [dskx], '2' 24388 000067CE E820000000 call pdskm 24389 ddsks5: 24390 000067D3 803D[236B0000]00 cmp byte [hd3_type], 0 24391 000067DA 760C jna short ddsk6 24392 000067DC C605[4B6D0000]33 mov byte [dskx], '3' 24393 000067E3 E80B000000 call pdskm 24394 ddsk6: 24395 000067E8 BE[5A6D0000] mov esi, nextline 24396 000067ED E806000000 call pdskml 24397 pdskm_ok: 24398 000067F2 C3 retn 24399 pdskm: 24400 000067F3 BE[476D0000] mov esi, dsk_ready_msg 24401 pdskml: 24402 000067F8 AC lodsb 24403 000067F9 08C0 or al, al 24404 000067FB 74F5 jz short pdskm_ok 24405 000067FD 56 push esi 24406 000067FE 31DB xor ebx, ebx ; 0 24407 ; Video page 0 (bl=0) 24408 00006800 B407 mov ah, 07h ; Black background, 24409 ; light gray forecolor 24410 00006802 E8D3ACFFFF call write_tty 24411 00006807 5E pop esi 24412 00006808 EBEE jmp short pdskml 24413 24414 0000680A 90 align 16 24415 24416 gdt: ; Global Descriptor Table 24417 ; (30/07/2015, conforming cs) 24418 ; (26/03/2015) 24419 ; (24/03/2015, tss) 24420 ; (19/03/2015) 24421 ; (29/12/2013) 24422 ; 24423 00006810 0000000000000000 dw 0, 0, 0, 0 ; NULL descriptor 24424 ; 18/08/2014 24425 ; 8h kernel code segment, base = 00000000h 24426 00006818 FFFF0000009ACF00 dw 0FFFFh, 0, 9A00h, 00CFh ; KCODE 24427 ; 10h kernel data segment, base = 00000000h 24428 00006820 FFFF00000092CF00 dw 0FFFFh, 0, 9200h, 00CFh ; KDATA 24429 ; 1Bh user code segment, base address = 400000h ; CORE 24430 00006828 FFFB000040FACF00 dw 0FBFFh, 0, 0FA40h, 00CFh ; UCODE 24431 ; 23h user data segment, base address = 400000h ; CORE 24432 00006830 FFFB000040F2CF00 dw 0FBFFh, 0, 0F240h, 00CFh ; UDATA 24433 ; Task State Segment 24434 00006838 6700 dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 24435 ; no IO permission in ring 3) 24436 gdt_tss0: 24437 0000683A 0000 dw 0 ; TSS base address, bits 0-15 24438 gdt_tss1: 24439 0000683C 00 db 0 ; TSS base address, bits 16-23 24440 ; 49h 24441 0000683D E9 db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1) 24442 0000683E 00 db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte) 24443 gdt_tss2: 24444 0000683F 00 db 0 ; TSS base address, bits 24-31 24445 24446 gdt_end: 24447 ;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 24448 ;; Type= 1 (code)/C=0/R=1/A=0 24449 ; P= Present, DPL=0=ring 0, 1= user (0= system) 24450 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 24451 24452 ;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 24453 ;; Type= 0 (data)/E=0/W=1/A=0 24454 ; P= Present, DPL=0=ring 0, 1= user (0= system) 24455 ; 0= Data E= Expansion direction (1= down, 0= up) 24456 ; W= Writeable, A= Accessed 24457 24458 ;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 24459 ;; Type= 1 (code)/C=0/R=1/A=0 24460 ; P= Present, DPL=3=ring 3, 1= user (0= system) 24461 ; 1= Code C= non-Conforming, R= Readable, A = Accessed 24462 24463 ;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 24464 ;; Type= 0 (data)/E=0/W=1/A=0 24465 ; P= Present, DPL=3=ring 3, 1= user (0= system) 24466 ; 0= Data E= Expansion direction (1= down, 0= up) 24467 24468 ;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3) 24469 24470 ;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 // 24471 ; = 100000h * 1000h (G=1) = 4GB 24472 ;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 // 24473 ; = FFC00h * 1000h (G=1) = 4GB - 4MB 24474 ; G= Granularity (1= 4KB), B= Big (32 bit), 24475 ; AVL= Available to programmers 24476 24477 gdtd: 24478 00006840 2F00 dw gdt_end - gdt - 1 ; Limit (size) 24479 00006842 [10680000] dd gdt ; Address of the GDT 24480 24481 ; 20/08/2014 24482 idtd: 24483 00006846 FF01 dw idt_end - idt - 1 ; Limit (size) 24484 00006848 [006E0000] dd idt ; Address of the IDT 24485 24486 Align 4 24487 24488 ; 21/08/2014 24489 ilist: 24490 ;times 32 dd cpu_except ; INT 0 to INT 1Fh 24491 ; 24492 ; Exception list 24493 ; 25/08/2014 24494 0000684C [F1080000] dd exc0 ; 0h, Divide-by-zero Error 24495 00006850 [F8080000] dd exc1 24496 00006854 [FF080000] dd exc2 24497 00006858 [06090000] dd exc3 24498 0000685C [0A090000] dd exc4 24499 00006860 [0E090000] dd exc5 24500 00006864 [12090000] dd exc6 ; 06h, Invalid Opcode 24501 00006868 [16090000] dd exc7 24502 0000686C [1A090000] dd exc8 24503 00006870 [1E090000] dd exc9 24504 00006874 [22090000] dd exc10 24505 00006878 [26090000] dd exc11 24506 0000687C [2A090000] dd exc12 24507 00006880 [2E090000] dd exc13 ; 0Dh, General Protection Fault 24508 00006884 [32090000] dd exc14 ; 0Eh, Page Fault 24509 00006888 [36090000] dd exc15 24510 0000688C [3A090000] dd exc16 24511 00006890 [3E090000] dd exc17 24512 00006894 [42090000] dd exc18 24513 00006898 [46090000] dd exc19 24514 0000689C [4A090000] dd exc20 24515 000068A0 [4E090000] dd exc21 24516 000068A4 [52090000] dd exc22 24517 000068A8 [56090000] dd exc23 24518 000068AC [5A090000] dd exc24 24519 000068B0 [5E090000] dd exc25 24520 000068B4 [62090000] dd exc26 24521 000068B8 [66090000] dd exc27 24522 000068BC [6A090000] dd exc28 24523 000068C0 [6E090000] dd exc29 24524 000068C4 [72090000] dd exc30 24525 000068C8 [76090000] dd exc31 24526 ; Interrupt list 24527 000068CC [27070000] dd timer_int ; INT 20h 24528 ;dd irq0 24529 000068D0 [300C0000] dd keyb_int ; 27/08/2014 24530 ;dd irq1 24531 000068D4 [47080000] dd irq2 24532 ; COM2 int 24533 000068D8 [4B080000] dd irq3 24534 ; COM1 int 24535 000068DC [56080000] dd irq4 24536 000068E0 [61080000] dd irq5 24537 ;DISKETTE_INT: ;06/02/2015 24538 000068E4 [6D270000] dd fdc_int ; 16/02/2015, IRQ 6 handler 24539 ;dd irq6 24540 ; Default IRQ 7 handler against spurious IRQs (from master PIC) 24541 ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC) 24542 000068E8 [DD0B0000] dd default_irq7 ; 25/02/2015 24543 ;dd irq7 24544 ; Real Time Clock Interrupt 24545 000068EC [800A0000] dd rtc_int ; 23/02/2015, IRQ 8 handler 24546 ;dd irq8 ; INT 28h 24547 000068F0 [71080000] dd irq9 24548 000068F4 [75080000] dd irq10 24549 000068F8 [79080000] dd irq11 24550 000068FC [7D080000] dd irq12 24551 00006900 [81080000] dd irq13 24552 ;HDISK_INT1: ;06/02/2015 24553 00006904 [A82F0000] dd hdc1_int ; 21/02/2015, IRQ 14 handler 24554 ;dd irq14 24555 ;HDISK_INT2: ;06/02/2015 24556 00006908 [CF2F0000] dd hdc2_int ; 21/02/2015, IRQ 15 handler 24557 ;dd irq15 ; INT 2Fh 24558 ; 14/08/2015 24559 0000690C [3E3F0000] dd sysent ; INT 30h (system calls) 24560 24561 ;dd ignore_int 24562 00006910 00000000 dd 0 24563 24564 ;;; 24565 ;;; 11/03/2015 24566 %include 'kybdata.inc' ; KEYBOARD (BIOS) DATA 24567 <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC 24568 <1> ; Last Modification: 11/03/2015 24569 <1> ; (Data Section for 'KEYBOARD.INC') 24570 <1> ; 24571 <1> ; ///////// KEYBOARD DATA /////////////// 24572 <1> 24573 <1> ; 05/12/2014 24574 <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 24575 <1> ; 03/06/86 KEYBOARD BIOS 24576 <1> 24577 <1> ;--------------------------------------------------------------------------------- 24578 <1> ; KEY IDENTIFICATION SCAN TABLES 24579 <1> ;--------------------------------------------------------------------------------- 24580 <1> 24581 <1> ;----- TABLES FOR ALT CASE ------------ 24582 <1> ;----- ALT-INPUT-TABLE 24583 00006914 524F50514B <1> K30: db 82,79,80,81,75 24584 00006919 4C4D474849 <1> db 76,77,71,72,73 ; 10 NUMBER ON KEYPAD 24585 <1> ;----- SUPER-SHIFT-TABLE 24586 0000691E 101112131415 <1> db 16,17,18,19,20,21 ; A-Z TYPEWRITER CHARS 24587 00006924 161718191E1F <1> db 22,23,24,25,30,31 24588 0000692A 202122232425 <1> db 32,33,34,35,36,37 24589 00006930 262C2D2E2F30 <1> db 38,44,45,46,47,48 24590 00006936 3132 <1> db 49,50 24591 <1> 24592 <1> ;----- TABLE OF SHIFT KEYS AND MASK VALUES 24593 <1> ;----- KEY_TABLE 24594 00006938 52 <1> _K6: db INS_KEY ; INSERT KEY 24595 00006939 3A4546381D <1> db CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY 24596 0000693E 2A36 <1> db LEFT_KEY,RIGHT_KEY 24597 <1> _K6L equ $-_K6 24598 <1> 24599 <1> ;----- MASK_TABLE 24600 00006940 80 <1> _K7: db INS_SHIFT ; INSERT MODE SHIFT 24601 00006941 4020100804 <1> db CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT 24602 00006946 0201 <1> db LEFT_SHIFT,RIGHT_SHIFT 24603 <1> 24604 <1> ;----- TABLES FOR CTRL CASE ;---- CHARACTERS ------ 24605 00006948 1BFF00FFFFFF <1> _K8: db 27,-1,0,-1,-1,-1 ; Esc, 1, 2, 3, 4, 5 24606 0000694E 1EFFFFFFFF1F <1> db 30,-1,-1,-1,-1,31 ; 6, 7, 8, 9, 0, - 24607 00006954 FF7FFF111705 <1> db -1,127,-1,17,23,5 ; =, Bksp, Tab, Q, W, E 24608 0000695A 12141915090F <1> db 18,20,25,21,9,15 ; R, T, Y, U, I, O 24609 00006960 101B1D0AFF01 <1> db 16,27,29,10,-1,1 ; P, [, ], Enter, Ctrl, A 24610 00006966 13040607080A <1> db 19,4,6,7,8,10 ; S, D, F, G, H, J 24611 0000696C 0B0CFFFFFFFF <1> db 11,12,-1,-1,-1,-1 ; K, L, :, ', `, LShift 24612 00006972 1C1A18031602 <1> db 28,26,24,3,22,2 ; Bkslash, Z, X, C, V, B 24613 00006978 0E0DFFFFFFFF <1> db 14,13,-1,-1,-1,-1 ; N, M, ,, ., /, RShift 24614 0000697E 96FF20FF <1> db 150,-1,' ',-1 ; *, ALT, Spc, CL 24615 <1> ; ;----- FUNCTIONS ------ 24616 00006982 5E5F60616263 <1> db 94,95,96,97,98,99 ; F1 - F6 24617 00006988 64656667FFFF <1> db 100,101,102,103,-1,-1 ; F7 - F10, NL, SL 24618 0000698E 778D848E738F <1> db 119,141,132,142,115,143 ; Home, Up, PgUp, -, Left, Pad5 24619 00006994 749075917692 <1> db 116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins 24620 0000699A 93FFFFFF898A <1> db 147,-1,-1,-1,137,138 ; Del, SysReq, Undef, WT, F11, F12 24621 <1> 24622 <1> ;----- TABLES FOR LOWER CASE ---------- 24623 000069A0 1B3132333435363738- <1> K10: db 27,'1234567890-=',8,9 24624 000069A9 39302D3D0809 <1> 24625 000069AF 71776572747975696F- <1> db 'qwertyuiop[]',13,-1,'asdfghjkl;',39 24626 000069B8 705B5D0DFF61736466- <1> 24627 000069C1 67686A6B6C3B27 <1> 24628 000069C8 60FF5C7A786376626E- <1> db 96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1 24629 000069D1 6D2C2E2FFF2AFF20FF <1> 24630 <1> ;----- LC TABLE SCAN 24631 000069DA 3B3C3D3E3F <1> db 59,60,61,62,63 ; BASE STATE OF F1 - F10 24632 000069DF 4041424344 <1> db 64,65,66,67,68 24633 000069E4 FFFF <1> db -1,-1 ; NL, SL 24634 <1> 24635 <1> ;----- KEYPAD TABLE 24636 000069E6 474849FF4BFF <1> K15: db 71,72,73,-1,75,-1 ; BASE STATE OF KEYPAD KEYS 24637 000069EC 4DFF4F50515253 <1> db 77,-1,79,80,81,82,83 24638 000069F3 FFFF5C8586 <1> db -1,-1,92,133,134 ; SysRq, Undef, WT, F11, F12 24639 <1> 24640 <1> ;----- TABLES FOR UPPER CASE ---------- 24641 000069F8 1B21402324255E262A- <1> K11: db 27,'!@#$%',94,'&*()_+',8,0 24642 00006A01 28295F2B0800 <1> 24643 00006A07 51574552545955494F- <1> db 'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"' 24644 00006A10 507B7D0DFF41534446- <1> 24645 00006A19 47484A4B4C3A22 <1> 24646 00006A20 7EFF7C5A584356424E- <1> db 126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1 24647 00006A29 4D3C3E3FFF2AFF20FF <1> 24648 <1> ;----- UC TABLE SCAN 24649 00006A32 5455565758 <1> K12: db 84,85,86,87,88 ; SHIFTED STATE OF F1 - F10 24650 00006A37 595A5B5C5D <1> db 89,90,91,92,93 24651 00006A3C FFFF <1> db -1,-1 ; NL, SL 24652 <1> 24653 <1> ;----- NUM STATE TABLE 24654 00006A3E 3738392D3435362B31- <1> K14: db '789-456+1230.' ; NUMLOCK STATE OF KEYPAD KEYS 24655 00006A47 3233302E <1> 24656 <1> ; 24657 00006A4B FFFF7C8788 <1> db -1,-1,124,135,136 ; SysRq, Undef, WT, F11, F12 24658 <1> 24659 <1> Align 4 24660 <1> ;---------------------------------------- 24661 <1> ; VIDEO DISPLAY DATA AREA ; 24662 <1> ;---------------------------------------- 24663 00006A50 03 <1> CRT_MODE db 3 ; CURRENT DISPLAY MODE (TYPE) 24664 00006A51 29 <1> CRT_MODE_SET db 29h ; CURRENT SETTING OF THE 3X8 REGISTER 24665 <1> ; (29h default setting for video mode 3) 24666 <1> ; Mode Select register Bits 24667 <1> ; BIT 0 - 80x25 (1), 40x25 (0) 24668 <1> ; BIT 1 - ALPHA (0), 320x200 GRAPHICS (1) 24669 <1> ; BIT 2 - COLOR (0), BW (1) 24670 <1> ; BIT 3 - Video Sig. ENABLE (1), DISABLE (0) 24671 <1> ; BIT 4 - 640x200 B&W Graphics Mode (1) 24672 <1> ; BIT 5 - ALPHA mode BLINKING (1) 24673 <1> ; BIT 6, 7 - Not Used 24674 <1> 24675 <1> ; Mode 0 - 2Ch = 101100b ; 40x25 text, 16 gray colors 24676 <1> ; Mode 1 - 28h = 101000b ; 40x25 text, 16 fore colors, 8 back colors 24677 <1> ; Mode 2 - 2Dh = 101101b ; 80x25 text, 16 gray colors 24678 <1> ; MODE 3 - 29h = 101001b ; 80x25 text, 16 fore color, 8 back color 24679 <1> ; Mode 4 - 2Ah = 101010b ; 320x200 graphics, 4 colors 24680 <1> ; Mode 5 - 2Eh = 101110b ; 320x200 graphics, 4 gray colors 24681 <1> ; Mode 6 - 1Eh = 011110b ; 640x200 graphics, 2 colors 24682 <1> ; Mode 7 - 29h = 101001b ; 80x25 text, black & white colors 24683 <1> ; Mode & 37h = Video signal OFF 24684 <1> 24685 <1> 24686 <1> ; 26/08/2014 24687 <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014) 24688 <1> ; Derived from IBM "pc-at" 24689 <1> ; rombios source code (06/10/1985) 24690 <1> ; 'dseg.inc' 24691 <1> 24692 <1> ;---------------------------------------; 24693 <1> ; SYSTEM DATA AREA ; 24694 <1> ;---------------------------------------- 24695 00006A52 00 <1> BIOS_BREAK db 0 ; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED 24696 <1> 24697 <1> ;---------------------------------------- 24698 <1> ; KEYBOARD DATA AREAS ; 24699 <1> ;---------------------------------------- 24700 <1> 24701 00006A53 00 <1> KB_FLAG db 0 ; KEYBOARD SHIFT STATE AND STATUS FLAGS 24702 00006A54 00 <1> KB_FLAG_1 db 0 ; SECOND BYTE OF KEYBOARD STATUS 24703 00006A55 00 <1> KB_FLAG_2 db 0 ; KEYBOARD LED FLAGS 24704 00006A56 00 <1> KB_FLAG_3 db 0 ; KEYBOARD MODE STATE AND TYPE FLAGS 24705 00006A57 00 <1> ALT_INPUT db 0 ; STORAGE FOR ALTERNATE KEY PAD ENTRY 24706 00006A58 [686A0000] <1> BUFFER_START dd KB_BUFFER ; OFFSET OF KEYBOARD BUFFER START 24707 00006A5C [886A0000] <1> BUFFER_END dd KB_BUFFER + 32 ; OFFSET OF END OF BUFFER 24708 00006A60 [686A0000] <1> BUFFER_HEAD dd KB_BUFFER ; POINTER TO HEAD OF KEYBOARD BUFFER 24709 00006A64 [686A0000] <1> BUFFER_TAIL dd KB_BUFFER ; POINTER TO TAIL OF KEYBOARD BUFFER 24710 <1> ; ------ HEAD = TAIL INDICATES THAT THE BUFFER IS EMPTY 24711 00006A68 0000 <1> KB_BUFFER times 16 dw 0 ; ROOM FOR 16 SCAN CODE ENTRIES 24712 <1> 24713 <1> ; /// End Of KEYBOARD DATA /// 24714 %include 'vidata.inc' ; VIDEO (BIOS) DATA 24715 <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC 24716 <1> ; Last Modification: 11/03/2015 24717 <1> ; (Data section for 'VIDEO.INC') 24718 <1> ; 24719 <1> ; ///////// VIDEO DATA /////////////// 24720 <1> 24721 <1> video_params: 24722 <1> ; 02/09/2014 (Retro UNIX 386 v1) 24723 <1> ;ORGS.ASM ----- 06/10/85 COMPATIBILITY MODULE 24724 <1> ; VIDEO MODE 3 24725 00006A88 71505A0A1F0619 <1> db 71h,50h,5Ah,0Ah,1Fh,6,19h ; SET UP FOR 80X25 24726 00006A8F 1C02070607 <1> db 1Ch,2,7,6,7 ; cursor start = 6, cursor stop = 7 24727 00006A94 00000000 <1> db 0,0,0,0 24728 <1> 24729 <1> ; /// End Of VIDEO DATA /// 24730 %include 'diskdata.inc' ; DISK (BIOS) DATA (initialized) 24731 <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC 24732 <1> ; Last Modification: 11/03/2015 24733 <1> ; (Initialized Disk Parameters Data section for 'DISKIO.INC') 24734 <1> ; 24735 <1> ; ***************************************************************************** 24736 <1> 24737 <1> ;---------------------------------------- 24738 <1> ; 80286 INTERRUPT LOCATIONS : 24739 <1> ; REFERENCED BY POST & BIOS : 24740 <1> ;---------------------------------------- 24741 <1> 24742 00006A98 [FB6A0000] <1> DISK_POINTER: dd MD_TBL6 ; Pointer to Diskette Parameter Table 24743 <1> 24744 <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014 24745 <1> ;---------------------------------------------------------------- 24746 <1> ; DISK_BASE : 24747 <1> ; THIS IS THE SET OF PARAMETERS REQUIRED FOR : 24748 <1> ; DISKETTE OPERATION. THEY ARE POINTED AT BY THE : 24749 <1> ; DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS, : 24750 <1> ; BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT : 24751 <1> ;---------------------------------------------------------------- 24752 <1> 24753 <1> ;DISK_BASE: 24754 <1> ; DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 24755 <1> ; DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24756 <1> ; DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24757 <1> ; DB 2 ; 512 BYTES/SECTOR 24758 <1> ; ;DB 15 ; EOT (LAST SECTOR ON TRACK) 24759 <1> ; db 18 ; (EOT for 1.44MB diskette) 24760 <1> ; DB 01BH ; GAP LENGTH 24761 <1> ; DB 0FFH ; DTL 24762 <1> ; ;DB 054H ; GAP LENGTH FOR FORMAT 24763 <1> ; db 06ch ; (for 1.44MB dsikette) 24764 <1> ; DB 0F6H ; FILL BYTE FOR FORMAT 24765 <1> ; DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24766 <1> ; DB 8 ; MOTOR START TIME (1/8 SECONDS) 24767 <1> 24768 <1> ;---------------------------------------- 24769 <1> ; ROM BIOS DATA AREAS : 24770 <1> ;---------------------------------------- 24771 <1> 24772 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 24773 <1> 24774 <1> ;@EQUIP_FLAG DW ? ; INSTALLED HARDWARE FLAGS 24775 <1> 24776 <1> ;---------------------------------------- 24777 <1> ; DISKETTE DATA AREAS : 24778 <1> ;---------------------------------------- 24779 <1> 24780 <1> ;@SEEK_STATUS DB ? ; DRIVE RECALIBRATION STATUS 24781 <1> ; ; BIT 3-0 = DRIVE 3-0 RECALIBRATION 24782 <1> ; ; BEFORE NEXT SEEK IF BIT IS = 0 24783 <1> ;@MOTOR_STATUS DB ? ; MOTOR STATUS 24784 <1> ; ; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING 24785 <1> ; ; BIT 7 = CURRENT OPERATION IS A WRITE 24786 <1> ;@MOTOR_COUNT DB ? ; TIME OUT COUNTER FOR MOTOR(S) TURN OFF 24787 <1> ;@DSKETTE_STATUS DB ? ; RETURN CODE STATUS BYTE 24788 <1> ; ; CMD_BLOCK IN STACK FOR DISK OPERATION 24789 <1> ;@NEC_STATUS DB 7 DUP(?) ; STATUS BYTES FROM DISKETTE OPERATION 24790 <1> 24791 <1> ;---------------------------------------- 24792 <1> ; POST AND BIOS WORK DATA AREA : 24793 <1> ;---------------------------------------- 24794 <1> 24795 <1> ;@INTR_FLAG DB ? ; FLAG INDICATING AN INTERRUPT HAPPENED 24796 <1> 24797 <1> ;---------------------------------------- 24798 <1> ; TIMER DATA AREA : 24799 <1> ;---------------------------------------- 24800 <1> 24801 <1> ; 17/12/2014 (IRQ 0 - INT 08H) 24802 <1> ;TIMER_LOW equ 46Ch ; Timer ticks (counter) @ 40h:006Ch 24803 <1> ;TIMER_HIGH equ 46Eh ; (18.2 timer ticks per second) 24804 <1> ;TIMER_OFL equ 470h ; Timer - 24 hours flag @ 40h:0070h 24805 <1> 24806 <1> ;---------------------------------------- 24807 <1> ; ADDITIONAL MEDIA DATA : 24808 <1> ;---------------------------------------- 24809 <1> 24810 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 24811 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 24812 <1> ; DB ? ; DRIVE 1 MEDIA STATE 24813 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 24814 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 24815 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 24816 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 24817 <1> 24818 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 24819 <1> 24820 <1> ;-------------------------------------------------------- 24821 <1> ; DRIVE TYPE TABLE : 24822 <1> ;-------------------------------------------------------- 24823 <1> ; 16/02/2015 (unix386.s, 32 bit modifications) 24824 <1> DR_TYPE: 24825 00006A9C 01 <1> DB 01 ;DRIVE TYPE, MEDIA TABLE 24826 <1> ;DW MD_TBL1 24827 00006A9D [BA6A0000] <1> dd MD_TBL1 24828 00006AA1 82 <1> DB 02+BIT7ON 24829 <1> ;DW MD_TBL2 24830 00006AA2 [C76A0000] <1> dd MD_TBL2 24831 00006AA6 02 <1> DR_DEFAULT: DB 02 24832 <1> ;DW MD_TBL3 24833 00006AA7 [D46A0000] <1> dd MD_TBL3 24834 00006AAB 03 <1> DB 03 24835 <1> ;DW MD_TBL4 24836 00006AAC [E16A0000] <1> dd MD_TBL4 24837 00006AB0 84 <1> DB 04+BIT7ON 24838 <1> ;DW MD_TBL5 24839 00006AB1 [EE6A0000] <1> dd MD_TBL5 24840 00006AB5 04 <1> DB 04 24841 <1> ;DW MD_TBL6 24842 00006AB6 [FB6A0000] <1> dd MD_TBL6 24843 <1> DR_TYPE_E equ $ ; END OF TABLE 24844 <1> ;DR_CNT EQU (DR_TYPE_E-DR_TYPE)/3 24845 <1> DR_CNT equ (DR_TYPE_E-DR_TYPE)/5 24846 <1> ;-------------------------------------------------------- 24847 <1> ; MEDIA/DRIVE PARAMETER TABLES : 24848 <1> ;-------------------------------------------------------- 24849 <1> ;-------------------------------------------------------- 24850 <1> ; 360 KB MEDIA IN 360 KB DRIVE : 24851 <1> ;-------------------------------------------------------- 24852 <1> MD_TBL1: 24853 00006ABA DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 24854 00006ABB 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24855 00006ABC 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24856 00006ABD 02 <1> DB 2 ; 512 BYTES/SECTOR 24857 00006ABE 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 24858 00006ABF 2A <1> DB 02AH ; GAP LENGTH 24859 00006AC0 FF <1> DB 0FFH ; DTL 24860 00006AC1 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 24861 00006AC2 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 24862 00006AC3 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24863 00006AC4 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 24864 00006AC5 27 <1> DB 39 ; MAX. TRACK NUMBER 24865 00006AC6 80 <1> DB RATE_250 ; DATA TRANSFER RATE 24866 <1> ;-------------------------------------------------------- 24867 <1> ; 360 KB MEDIA IN 1.2 MB DRIVE : 24868 <1> ;-------------------------------------------------------- 24869 <1> MD_TBL2: 24870 00006AC7 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 24871 00006AC8 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24872 00006AC9 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24873 00006ACA 02 <1> DB 2 ; 512 BYTES/SECTOR 24874 00006ACB 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 24875 00006ACC 2A <1> DB 02AH ; GAP LENGTH 24876 00006ACD FF <1> DB 0FFH ; DTL 24877 00006ACE 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 24878 00006ACF F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 24879 00006AD0 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24880 00006AD1 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 24881 00006AD2 27 <1> DB 39 ; MAX. TRACK NUMBER 24882 00006AD3 40 <1> DB RATE_300 ; DATA TRANSFER RATE 24883 <1> ;-------------------------------------------------------- 24884 <1> ; 1.2 MB MEDIA IN 1.2 MB DRIVE : 24885 <1> ;-------------------------------------------------------- 24886 <1> MD_TBL3: 24887 00006AD4 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 24888 00006AD5 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24889 00006AD6 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24890 00006AD7 02 <1> DB 2 ; 512 BYTES/SECTOR 24891 00006AD8 0F <1> DB 15 ; EOT (LAST SECTOR ON TRACK) 24892 00006AD9 1B <1> DB 01BH ; GAP LENGTH 24893 00006ADA FF <1> DB 0FFH ; DTL 24894 00006ADB 54 <1> DB 054H ; GAP LENGTH FOR FORMAT 24895 00006ADC F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 24896 00006ADD 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24897 00006ADE 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 24898 00006ADF 4F <1> DB 79 ; MAX. TRACK NUMBER 24899 00006AE0 00 <1> DB RATE_500 ; DATA TRANSFER RATE 24900 <1> ;-------------------------------------------------------- 24901 <1> ; 720 KB MEDIA IN 720 KB DRIVE : 24902 <1> ;-------------------------------------------------------- 24903 <1> MD_TBL4: 24904 00006AE1 DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 24905 00006AE2 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24906 00006AE3 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24907 00006AE4 02 <1> DB 2 ; 512 BYTES/SECTOR 24908 00006AE5 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 24909 00006AE6 2A <1> DB 02AH ; GAP LENGTH 24910 00006AE7 FF <1> DB 0FFH ; DTL 24911 00006AE8 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 24912 00006AE9 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 24913 00006AEA 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24914 00006AEB 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 24915 00006AEC 4F <1> DB 79 ; MAX. TRACK NUMBER 24916 00006AED 80 <1> DB RATE_250 ; DATA TRANSFER RATE 24917 <1> ;-------------------------------------------------------- 24918 <1> ; 720 KB MEDIA IN 1.44 MB DRIVE : 24919 <1> ;-------------------------------------------------------- 24920 <1> MD_TBL5: 24921 00006AEE DF <1> DB 11011111B ; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE 24922 00006AEF 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24923 00006AF0 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24924 00006AF1 02 <1> DB 2 ; 512 BYTES/SECTOR 24925 00006AF2 09 <1> DB 09 ; EOT (LAST SECTOR ON TRACK) 24926 00006AF3 2A <1> DB 02AH ; GAP LENGTH 24927 00006AF4 FF <1> DB 0FFH ; DTL 24928 00006AF5 50 <1> DB 050H ; GAP LENGTH FOR FORMAT 24929 00006AF6 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 24930 00006AF7 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24931 00006AF8 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 24932 00006AF9 4F <1> DB 79 ; MAX. TRACK NUMBER 24933 00006AFA 80 <1> DB RATE_250 ; DATA TRANSFER RATE 24934 <1> ;-------------------------------------------------------- 24935 <1> ; 1.44 MB MEDIA IN 1.44 MB DRIVE : 24936 <1> ;-------------------------------------------------------- 24937 <1> MD_TBL6: 24938 00006AFB AF <1> DB 10101111B ; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE 24939 00006AFC 02 <1> DB 2 ; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE 24940 00006AFD 25 <1> DB MOTOR_WAIT ; WAIT TIME AFTER OPERATION TILL MOTOR OFF 24941 00006AFE 02 <1> DB 2 ; 512 BYTES/SECTOR 24942 00006AFF 12 <1> DB 18 ; EOT (LAST SECTOR ON TRACK) 24943 00006B00 1B <1> DB 01BH ; GAP LENGTH 24944 00006B01 FF <1> DB 0FFH ; DTL 24945 00006B02 6C <1> DB 06CH ; GAP LENGTH FOR FORMAT 24946 00006B03 F6 <1> DB 0F6H ; FILL BYTE FOR FORMAT 24947 00006B04 0F <1> DB 15 ; HEAD SETTLE TIME (MILLISECONDS) 24948 00006B05 08 <1> DB 8 ; MOTOR START TIME (1/8 SECONDS) 24949 00006B06 4F <1> DB 79 ; MAX. TRACK NUMBER 24950 00006B07 00 <1> DB RATE_500 ; DATA TRANSFER RATE 24951 <1> 24952 <1> 24953 <1> ; << diskette.inc >> 24954 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 24955 <1> ; 24956 <1> ;---------------------------------------- 24957 <1> ; ROM BIOS DATA AREAS : 24958 <1> ;---------------------------------------- 24959 <1> 24960 <1> ;DATA SEGMENT AT 40H ; ADDRESS= 0040:0000 24961 <1> 24962 <1> ;---------------------------------------- 24963 <1> ; FIXED DISK DATA AREAS : 24964 <1> ;---------------------------------------- 24965 <1> 24966 <1> ;DISK_STATUS1: DB 0 ; FIXED DISK STATUS 24967 <1> ;HF_NUM: DB 0 ; COUNT OF FIXED DISK DRIVES 24968 <1> ;CONTROL_BYTE: DB 0 ; HEAD CONTROL BYTE 24969 <1> ;@PORT_OFF DB ? ; RESERVED (PORT OFFSET) 24970 <1> 24971 <1> ;---------------------------------------- 24972 <1> ; ADDITIONAL MEDIA DATA : 24973 <1> ;---------------------------------------- 24974 <1> 24975 <1> ;@LASTRATE DB ? ; LAST DISKETTE DATA RATE SELECTED 24976 <1> ;HF_STATUS DB 0 ; STATUS REGISTER 24977 <1> ;HF_ERROR DB 0 ; ERROR REGISTER 24978 <1> ;HF_INT_FLAG DB 0 ; FIXED DISK INTERRUPT FLAG 24979 <1> ;HF_CNTRL DB 0 ; COMBO FIXED DISK/DISKETTE CARD BIT 0=1 24980 <1> ;@DSK_STATE DB ? ; DRIVE 0 MEDIA STATE 24981 <1> ; DB ? ; DRIVE 1 MEDIA STATE 24982 <1> ; DB ? ; DRIVE 0 OPERATION START STATE 24983 <1> ; DB ? ; DRIVE 1 OPERATION START STATE 24984 <1> ;@DSK_TRK DB ? ; DRIVE 0 PRESENT CYLINDER 24985 <1> ; DB ? ; DRIVE 1 PRESENT CYLINDER 24986 <1> 24987 <1> ;DATA ENDS ; END OF BIOS DATA SEGMENT 24988 <1> ; 24989 <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 24990 <1> 24991 <1> ERR_TBL: 24992 00006B08 E0 <1> db NO_ERR 24993 00006B09 024001BB <1> db BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR 24994 00006B0D 04BB100A <1> db RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR 24995 <1> 24996 <1> ; 17/12/2014 (mov ax, [cfd]) 24997 <1> ; 11/12/2014 24998 00006B11 00 <1> cfd: db 0 ; current floppy drive (for GET_PARM) 24999 <1> ; 17/12/2014 ; instead of 'DISK_POINTER' 25000 00006B12 01 <1> pfd: db 1 ; previous floppy drive (for GET_PARM) 25001 <1> ; (initial value of 'pfd 25002 <1> ; must be different then 'cfd' value 25003 <1> ; to force updating/initializing 25004 <1> ; current drive parameters) 25005 00006B13 90 <1> align 2 25006 <1> 25007 00006B14 F001 <1> HF_PORT: dw 1F0h ; Default = 1F0h 25008 <1> ; (170h) 25009 00006B16 F603 <1> HF_REG_PORT: dw 3F6h ; HF_PORT + 206h 25010 <1> 25011 <1> ; 05/01/2015 25012 00006B18 00 <1> hf_m_s: db 0 ; (0 = Master, 1 = Slave) 25013 <1> 25014 <1> ; ***************************************************************************** 25015 ;;; 25016 25017 00006B19 90 Align 2 25018 25019 ; 12/11/2014 (Retro UNIX 386 v1) 25020 00006B1A 00 boot_drv: db 0 ; boot drive number (physical) 25021 ; 24/11/2014 25022 00006B1B 00 drv: db 0 25023 00006B1C 00 last_drv: db 0 ; last hdd 25024 00006B1D 00 hdc: db 0 ; number of hard disk drives 25025 ; (present/detected) 25026 ; 25027 ; 24/11/2014 (Retro UNIX 386 v1) 25028 ; Physical drive type & flags 25029 00006B1E 00 fd0_type: db 0 ; floppy drive type 25030 00006B1F 00 fd1_type: db 0 ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt) 25031 ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt) 25032 ; 3 = 720 Kb, 80 track, 3.5" (9 spt) 25033 ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt) 25034 ; 1 = 360 Kb, 40 track, 5.25" (9 spt) 25035 00006B20 00 hd0_type: db 0 ; EDD status for hd0 (bit 7 = present flag) 25036 00006B21 00 hd1_type: db 0 ; EDD status for hd1 (bit 7 = present flag) 25037 00006B22 00 hd2_type: db 0 ; EDD status for hd2 (bit 7 = present flag) 25038 00006B23 00 hd3_type: db 0 ; EDD status for hd3 (bit 7 = present flag) 25039 ; bit 0 - Fixed disk access subset supported 25040 ; bit 1 - Drive locking and ejecting 25041 ; bit 2 - Enhanced disk drive support 25042 ; bit 3 = Reserved (64 bit EDD support) 25043 ; (If bit 0 is '1' Retro UNIX 386 v1 25044 ; will interpret it as 'LBA ready'!) 25045 25046 ; 11/03/2015 - 10/07/2015 25047 00006B24 000000000000000000- drv.cylinders: dw 0,0,0,0,0,0,0 25048 00006B2D 0000000000 25049 00006B32 000000000000000000- drv.heads: dw 0,0,0,0,0,0,0 25050 00006B3B 0000000000 25051 00006B40 000000000000000000- drv.spt: dw 0,0,0,0,0,0,0 25052 00006B49 0000000000 25053 00006B4E 000000000000000000- drv.size: dd 0,0,0,0,0,0,0 25054 00006B57 000000000000000000- 25055 00006B60 000000000000000000- 25056 00006B69 00 25057 00006B6A 00000000000000 drv.status: db 0,0,0,0,0,0,0 25058 00006B71 00000000000000 drv.error: db 0,0,0,0,0,0,0 25059 ; 25060 25061 ; 27/08/2014 25062 scr_row: 25063 00006B78 E0810B00 dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3 25064 scr_col: 25065 00006B7C 00000000 dd 0 25066 25067 ;; 14/08/2015 25068 ;;msgPM: 25069 ;; db "Protected mode and paging are ENABLED ... ", 0 25070 msgKVER: 25071 00006B80 526574726F20554E49- db "Retro UNIX 386 v1.1 - Kernel v0.2.1.0 [04/02/2016]", 0 25072 00006B89 58203338362076312E- 25073 00006B92 31202D204B65726E65- 25074 00006B9B 6C2076302E322E312E- 25075 00006BA4 30205B30342F30322F- 25076 00006BAD 323031365D00 25077 25078 00006BB3 90 Align 2 25079 25080 ; 20/08/2014 25081 ; /* This is the default interrupt "handler" :-) */ 25082 ; Linux v0.12 (head.s) 25083 int_msg: 25084 00006BB4 556E6B6E6F776E2069- db "Unknown interrupt ! ", 0 25085 00006BBD 6E7465727275707420- 25086 00006BC6 212000 25087 25088 00006BC9 90 Align 2 25089 25090 ; 21/08/2014 25091 timer_msg: 25092 00006BCA 49525120302028494E- db "IRQ 0 (INT 20h) ! Timer Interrupt : " 25093 00006BD3 542032306829202120- 25094 00006BDC 54696D657220496E74- 25095 00006BE5 657272757074203A20 25096 tcountstr: 25097 00006BEE 303030303020 db "00000 " 25098 00006BF4 00 db 0 25099 25100 00006BF5 90 Align 2 25101 ; 21/08/2014 25102 exc_msg: 25103 00006BF6 435055206578636570- db "CPU exception ! " 25104 00006BFF 74696F6E202120 25105 excnstr: ; 25/08/2014 25106 00006C06 3F3F68202045495020- db "??h", " EIP : " 25107 00006C0F 3A20 25108 EIPstr: ; 29/08/2014 25109 00006C11 00 times 12 db 0 25110 rtc_msg: 25111 00006C1D 5265616C2054696D65- db "Real Time Clock - " 25112 00006C26 20436C6F636B202D20 25113 datestr: 25114 00006C2F 30302F30302F303030- db "00/00/0000" 25115 00006C38 30 25116 00006C39 20 db " " 25117 daystr: 25118 00006C3A 44415920 db "DAY " 25119 timestr: 25120 00006C3E 30303A30303A3030 db "00:00:00" 25121 00006C46 20 db " " 25122 00006C47 00 db 0 25123 25124 daytmp: 25125 ; 28/02/2015 25126 00006C48 3F3F3F2053554E204D- db "??? SUN MON TUE WED THU FRI SAT " 25127 00006C51 4F4E20545545205745- 25128 00006C5A 442054485520465249- 25129 00006C63 2053415420 25130 25131 00006C68 FF ptime_seconds: db 0FFh 25132 25133 ; 23/02/2015 25134 ; 25/08/2014 25135 ;scounter: 25136 ; db 5 25137 ; db 19 25138 25139 ; 05/11/2014 25140 msg_out_of_memory: 25141 00006C69 070D0A db 07h, 0Dh, 0Ah 25142 00006C6C 496E73756666696369- db 'Insufficient memory ! (Minimum 2 MB memory is needed.)' 25143 00006C75 656E74206D656D6F72- 25144 00006C7E 79202120284D696E69- 25145 00006C87 6D756D2032204D4220- 25146 00006C90 6D656D6F7279206973- 25147 00006C99 206E65656465642E29 25148 00006CA2 0D0A00 db 0Dh, 0Ah, 0 25149 ; 25150 setup_error_msg: 25151 00006CA5 0D0A db 0Dh, 0Ah 25152 00006CA7 4469736B2053657475- db 'Disk Setup Error!' 25153 00006CB0 70204572726F7221 25154 00006CB8 0D0A00 db 0Dh, 0Ah,0 25155 25156 ; 02/09/2014 (Retro UNIX 386 v1) 25157 ;crt_ulc : db 0 ; upper left column (for scroll) 25158 ; db 0 ; upper left row (for scroll) 25159 25160 ;crt_lrc : db 79 ; lower right column (for scroll) 25161 ; db 24 ; lower right row (for scroll) 25162 25163 25164 ; 06/11/2014 (Temporary Data) 25165 ; Memory Information message 25166 ; 14/08/2015 25167 msg_memory_info: 25168 00006CBB 07 db 07h 25169 00006CBC 0D0A db 0Dh, 0Ah 25170 ;db "MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah 25171 00006CBE 546F74616C206D656D- db "Total memory : " 25172 00006CC7 6F7279203A20 25173 mem_total_b_str: ; 10 digits 25174 00006CCD 303030303030303030- db "0000000000 bytes", 0Dh, 0Ah 25175 00006CD6 302062797465730D0A 25176 00006CDF 202020202020202020- db " ", 20h, 20h, 20h 25177 00006CE8 202020202020202020 25178 mem_total_p_str: ; 7 digits 25179 00006CF1 303030303030302070- db "0000000 pages", 0Dh, 0Ah 25180 00006CFA 616765730D0A 25181 00006D00 0D0A db 0Dh, 0Ah 25182 00006D02 46726565206D656D6F- db "Free memory : " 25183 00006D0B 727920203A20 25184 free_mem_b_str: ; 10 digits 25185 00006D11 3F3F3F3F3F3F3F3F3F- db "?????????? bytes", 0Dh, 0Ah 25186 00006D1A 3F2062797465730D0A 25187 00006D23 202020202020202020- db " ", 20h, 20h, 20h 25188 00006D2C 202020202020202020 25189 free_mem_p_str: ; 7 digits 25190 00006D35 3F3F3F3F3F3F3F2070- db "??????? pages", 0Dh, 0Ah 25191 00006D3E 616765730D0A 25192 00006D44 0D0A00 db 0Dh, 0Ah, 0 25193 25194 dsk_ready_msg: 25195 00006D47 0D0A db 0Dh, 0Ah 25196 dsktype: 25197 00006D49 6664 db 'fd' 25198 dskx: 25199 00006D4B 30 db '0' 25200 00006D4C 20 db 20h 25201 00006D4D 697320524541445920- db 'is READY ...' 25202 00006D56 2E2E2E 25203 00006D59 00 db 0 25204 nextline: 25205 00006D5A 0D0A00 db 0Dh, 0Ah, 0 25206 25207 ; KERNEL - SYSINIT Messages 25208 ; 24/08/2015 25209 ; 13/04/2015 - (Retro UNIX 386 v1 Beginning) 25210 ; 14/07/2013 25211 ;kernel_init_err_msg: 25212 ; db 0Dh, 0Ah 25213 ; db 07h 25214 ; db 'Kernel initialization ERROR !' 25215 ; db 0Dh, 0Ah, 0 25216 ; 24/08/2015 25217 ;;; (temporary kernel init message has been removed 25218 ;;; from 'sys_init' code) 25219 ;kernel_init_ok_msg: 25220 ; db 0Dh, 0Ah 25221 ; db 07h 25222 ; db 'Welcome to Retro UNIX 386 v1.1 Operating System !' 25223 ; db 0Dh, 0Ah 25224 ; db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)' 25225 ; db 0Dh, 0Ah, 0 25226 panic_msg: 25227 00006D5D 0D0A07 db 0Dh, 0Ah, 07h 25228 00006D60 4552524F523A204B65- db 'ERROR: Kernel Panic !' 25229 00006D69 726E656C2050616E69- 25230 00006D72 632021 25231 00006D75 0D0A00 db 0Dh, 0Ah, 0 25232 etc_init_err_msg: 25233 00006D78 0D0A db 0Dh, 0Ah 25234 00006D7A 07 db 07h 25235 00006D7B 4552524F523A202F65- db 'ERROR: /etc/init !?' 25236 00006D84 74632F696E69742021- 25237 00006D8D 3F 25238 00006D8E 0D0A00 db 0Dh, 0Ah, 0 25239 25240 ; 10/05/2015 25241 badsys_msg: 25242 00006D91 0D0A db 0Dh, 0Ah 25243 00006D93 07 db 07h 25244 00006D94 496E76616C69642053- db 'Invalid System Call !' 25245 00006D9D 797374656D2043616C- 25246 00006DA6 6C2021 25247 00006DA9 0D0A db 0Dh, 0Ah 25248 00006DAB 4541583A20 db 'EAX: ' 25249 bsys_msg_eax: 25250 00006DB0 303030303030303068 db '00000000h' 25251 00006DB9 0D0A db 0Dh, 0Ah 25252 00006DBB 4549503A20 db 'EIP: ' 25253 bsys_msg_eip: 25254 00006DC0 303030303030303068 db '00000000h' 25255 00006DC9 0D0A00 db 0Dh, 0Ah, 0 25256 25257 BSYS_M_SIZE equ $ - badsys_msg 25258 25259 25260 align 2 25261 25262 ; EPOCH Variables 25263 ; 13/04/2015 - Retro UNIX 386 v1 Beginning 25264 ; 09/04/2013 epoch variables 25265 ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013 25266 ; 25267 00006DCC B207 year: dw 1970 25268 00006DCE 0100 month: dw 1 25269 00006DD0 0100 day: dw 1 25270 00006DD2 0000 hour: dw 0 25271 00006DD4 0000 minute: dw 0 25272 00006DD6 0000 second: dw 0 25273 25274 DMonth: 25275 00006DD8 0000 dw 0 25276 00006DDA 1F00 dw 31 25277 00006DDC 3B00 dw 59 25278 00006DDE 5A00 dw 90 25279 00006DE0 7800 dw 120 25280 00006DE2 9700 dw 151 25281 00006DE4 B500 dw 181 25282 00006DE6 D400 dw 212 25283 00006DE8 F300 dw 243 25284 00006DEA 1101 dw 273 25285 00006DEC 3001 dw 304 25286 00006DEE 4E01 dw 334 25287 25288 ; 04/11/2014 (Retro UNIX 386 v1) 25289 00006DF0 0000 mem_1m_1k: dw 0 ; Number of contiguous KB between 25290 ; 1 and 16 MB, max. 3C00h = 15 MB. 25291 00006DF2 0000 mem_16m_64k: dw 0 ; Number of contiguous 64 KB blocks 25292 ; between 16 MB and 4 GB. 25293 00006DF4 90 align 16 25294 25295 bss_start: 25296 25297 ABSOLUTE bss_start 25298 25299 ; 11/03/2015 25300 ; Interrupt Descriptor Table (20/08/2014) 25301 idt: 25302 00006E00 resb 64*8 ; INT 0 to INT 3Fh 25303 idt_end: 25304 25305 ;alignb 4 25306 25307 task_state_segment: 25308 ; 24/03/2015 25309 00007000 tss.link: resw 1 25310 00007002 resw 1 25311 ; tss offset 4 25312 00007004 tss.esp0: resd 1 25313 00007008 tss.ss0: resw 1 25314 0000700A resw 1 25315 0000700C tss.esp1: resd 1 25316 00007010 tss.ss1: resw 1 25317 00007012 resw 1 25318 00007014 tss.esp2: resd 1 25319 00007018 tss.ss2: resw 1 25320 0000701A resw 1 25321 ; tss offset 28 25322 0000701C tss.CR3: resd 1 25323 00007020 tss.eip: resd 1 25324 00007024 tss.eflags: resd 1 25325 ; tss offset 40 25326 00007028 tss.eax: resd 1 25327 0000702C tss.ecx: resd 1 25328 00007030 tss.edx: resd 1 25329 00007034 tss.ebx: resd 1 25330 00007038 tss.esp: resd 1 25331 0000703C tss.ebp: resd 1 25332 00007040 tss.esi: resd 1 25333 00007044 tss.edi: resd 1 25334 ; tss offset 72 25335 00007048 tss.ES: resw 1 25336 0000704A resw 1 25337 0000704C tss.CS: resw 1 25338 0000704E resw 1 25339 00007050 tss.SS: resw 1 25340 00007052 resw 1 25341 00007054 tss.DS: resw 1 25342 00007056 resw 1 25343 00007058 tss.FS: resw 1 25344 0000705A resw 1 25345 0000705C tss.GS: resw 1 25346 0000705E resw 1 25347 00007060 tss.LDTR: resw 1 25348 00007062 resw 1 25349 ; tss offset 100 25350 00007064 resw 1 25351 00007066 tss.IOPB: resw 1 25352 ; tss offset 104 25353 tss_end: 25354 25355 00007068 k_page_dir: resd 1 ; Kernel's (System) Page Directory address 25356 ; (Physical address = Virtual address) 25357 0000706C memory_size: resd 1 ; memory size in pages 25358 00007070 free_pages: resd 1 ; number of free pages 25359 00007074 next_page: resd 1 ; offset value in M.A.T. for 25360 ; first free page search 25361 00007078 last_page: resd 1 ; offset value in M.A.T. which 25362 ; next free page search will be 25363 ; stopped after it. (end of M.A.T.) 25364 0000707C first_page: resd 1 ; offset value in M.A.T. which 25365 ; first free page search 25366 ; will be started on it. (for user) 25367 00007080 mat_size: resd 1 ; Memory Allocation Table size in pages 25368 25369 ;;; 25370 ; 02/09/2014 (Retro UNIX 386 v1) 25371 ; 04/12/2013 (Retro UNIX 8086 v1) 25372 00007084 CRT_START: resw 1 ; starting address in regen buffer 25373 ; NOTE: active page only 25374 00007086 cursor_posn: resw 8 ; cursor positions for video pages 25375 active_page: 25376 00007096 ptty: resb 1 ; current tty 25377 ; 01/07/2015 25378 00007097 ccolor: resb 1 ; current color attributes ('sysmsg') 25379 ; 26/10/2015 25380 ; 07/09/2014 25381 00007098 ttychr: resw ntty+2 ; Character buffer (multiscreen) 25382 25383 ; 21/08/2014 25384 000070AC tcount: resd 1 25385 25386 ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!) 25387 000070B0 p_time: resd 1 ; present time (for systime & sysmdate) 25388 25389 ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !) 25390 ; (open mode locks for pseudo TTYs) 25391 ; [ major tty locks (return error in any conflicts) ] 25392 000070B4 ttyl: resw ntty+2 ; opening locks for TTYs. 25393 25394 ; 15/04/2015 (Retro UNIX 386 v1) 25395 ; 22/09/2013 (Retro UNIX 8086 v1) 25396 000070C8 wlist: resb ntty+2 ; wait channel list (0 to 9 for TTYs) 25397 ; 15/04/2015 (Retro UNIX 386 v1) 25398 ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h 25399 ;; 0 means serial port is not available 25400 ;;comprm: ; 25/06/2014 25401 000070D2 com1p: resb 1 ;;0E3h 25402 000070D3 com2p: resb 1 ;;0E3h 25403 25404 ; 17/11/2015 25405 ; request for response (from the terminal) 25406 000070D4 req_resp: resw 1 25407 ; 07/11/2015 25408 000070D6 ccomport: resb 1 ; current COM (serial) port 25409 ; (0= COM1, 1= COM2) 25410 ; 09/11/2015 25411 000070D7 comqr: resb 1 ; 'query or response' sign (u9.s, 'sndc') 25412 ; 07/11/2015 25413 000070D8 rchar: resw 1 ; last received char for COM 1 and COM 2 25414 000070DA schar: resw 1 ; last sent char for COM 1 and COM 2 25415 25416 ; 23/10/2015 25417 ; SERIAL PORTS - COMMUNICATION MODES 25418 ; (Retro UNIX 386 v1 feature only!) 25419 ; 0 - command mode (default/initial mode) 25420 ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars) 25421 ;;; communication modes for futre versions: 25422 ; // 2 - keyboard mode (ascii+scancode input) 25423 ; // 3 - mouse mode 25424 ; // 4 - device control (output) mode 25425 ; VALID COMMANDS for current version: 25426 ; 'LOGIN' 25427 ; Login request: db 0FFh, 'LOGIN', 0 25428 ; ("Retro UNIX 386 v1 terminal requests login") 25429 ; Login response: db 0FFh, 'login', 0 25430 ; ("login request accepted, wait for login prompt") 25431 ; When a login requests is received and acknowledged (by 25432 ; serial port interrupt handler (communication procedure), 25433 ; Retro UNIX 386 v1 operating system will start terminal mode 25434 ; (login procedure) by changing comm. mode to 1 (terminal mode) 25435 ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2) 25436 ; 25437 ; 'sys connect' system call is used to change communication mode 25438 ; except 'LOGIN' command which is used to start terminal mode 25439 ; by using (COM port) terminal. 25440 25441 ;com1own: resb 1 ; COM1 owner (u.uno) 25442 ;com2own: resb 1 ; COM2 owner (u.uno) 25443 ;com1mode: resb 1 ; communication mode for COM1 25444 ;com1com: resb 1 ; communication command for COM1 25445 ;com2mode: resb 1 ; communication mode for COM1 25446 ;com2com resb 1 ; communication command for COM1 25447 ;com1cbufp: resb 8 ; COM1 command buffer char pointer 25448 ;com2cbufp: resb 8 ; COM2 command buffer char pointer 25449 ;com1cbuf: resb 8 ; COM2 command buffer 25450 ;com2cbuf: resb 8 ; COM2 command buffer 25451 25452 ; 22/08/2014 (RTC) 25453 ; (Packed BCD) 25454 000070DC time_seconds: resb 1 25455 000070DD time_minutes: resb 1 25456 000070DE time_hours: resb 1 25457 000070DF date_wday: resb 1 25458 000070E0 date_day: resb 1 25459 000070E1 date_month: resb 1 25460 000070E2 date_year: resb 1 25461 000070E3 date_century: resb 1 25462 25463 %include 'diskbss.inc' ; UNINITIALIZED DISK (BIOS) DATA 25464 <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC 25465 <1> ; Last Modification: 10/07/2015 25466 <1> ; (Unnitialized Disk Parameters Data section for 'DISKIO.INC') 25467 <1> ; 25468 <1> ; ***************************************************************************** 25469 <1> 25470 <1> alignb 2 25471 <1> 25472 <1> ;---------------------------------------- 25473 <1> ; TIMER DATA AREA : 25474 <1> ;---------------------------------------- 25475 <1> 25476 <1> TIMER_LH: ; 16/02/205 25477 000070E4 <1> TIMER_LOW: resw 1 ; LOW WORD OF TIMER COUNT 25478 000070E6 <1> TIMER_HIGH: resw 1 ; HIGH WORD OF TIMER COUNT 25479 000070E8 <1> TIMER_OFL: resb 1 ; TIMER HAS ROLLED OVER SINCE LAST READ 25480 <1> 25481 <1> ;---------------------------------------- 25482 <1> ; DISKETTE DATA AREAS : 25483 <1> ;---------------------------------------- 25484 <1> 25485 000070E9 <1> SEEK_STATUS: resb 1 25486 000070EA <1> MOTOR_STATUS: resb 1 25487 000070EB <1> MOTOR_COUNT: resb 1 25488 000070EC <1> DSKETTE_STATUS: resb 1 25489 000070ED <1> NEC_STATUS: resb 7 25490 <1> 25491 <1> ;---------------------------------------- 25492 <1> ; ADDITIONAL MEDIA DATA : 25493 <1> ;---------------------------------------- 25494 <1> 25495 000070F4 <1> LASTRATE: resb 1 25496 000070F5 <1> HF_STATUS: resb 1 25497 000070F6 <1> HF_ERROR: resb 1 25498 000070F7 <1> HF_INT_FLAG: resb 1 25499 000070F8 <1> HF_CNTRL: resb 1 25500 000070F9 <1> DSK_STATE: resb 4 25501 000070FD <1> DSK_TRK: resb 2 25502 <1> 25503 <1> ;---------------------------------------- 25504 <1> ; FIXED DISK DATA AREAS : 25505 <1> ;---------------------------------------- 25506 <1> 25507 000070FF <1> DISK_STATUS1: resb 1 ; FIXED DISK STATUS 25508 00007100 <1> HF_NUM: resb 1 ; COUNT OF FIXED DISK DRIVES 25509 00007101 <1> CONTROL_BYTE: resb 1 ; HEAD CONTROL BYTE 25510 <1> ;@PORT_OFF resb 1 ; RESERVED (PORT OFFSET) 25511 <1> ;port1_off resb 1 ; Hard disk controller 1 - port offset 25512 <1> ;port2_off resb 1 ; Hard idsk controller 2 - port offset 25513 <1> 25514 00007102 <1> alignb 4 25515 <1> 25516 <1> ;HF_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 25517 <1> ;HF1_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 25518 <1> HF_TBL_VEC: ; 22/12/2014 25519 00007104 <1> HDPM_TBL_VEC: resd 1 ; Primary master disk param. tbl. pointer 25520 00007108 <1> HDPS_TBL_VEC: resd 1 ; Primary slave disk param. tbl. pointer 25521 0000710C <1> HDSM_TBL_VEC: resd 1 ; Secondary master disk param. tbl. pointer 25522 00007110 <1> HDSS_TBL_VEC: resd 1 ; Secondary slave disk param. tbl. pointer 25523 <1> 25524 <1> ; 03/01/2015 25525 00007114 <1> LBAMode: resb 1 25526 <1> 25527 <1> ; ***************************************************************************** 25528 25529 ;;; Real Mode Data (10/07/2015 - BSS) 25530 25531 ;alignb 2 25532 25533 %include 'ux.s' ; 12/04/2015 (unix system/user/process data) 25534 <1> ; Retro UNIX 386 v1 Kernel - ux.s 25535 <1> ; Last Modification: 04/12/2015 25536 <1> ; 25537 <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS /////////////// 25538 <1> ; (Modified from 25539 <1> ; Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014) 25540 <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014)) 25541 <1> ; ---------------------------------------------------------------------------- 25542 <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 25543 <1> ; (Original) Source Code by Ken Thompson (1971-1972) 25544 <1> ; 25545 <1> ; 25546 <1> ; (Section E10 (17/3/1972) - ux.s) 25547 <1> ; **************************************************************************** 25548 <1> 25549 00007115 <1> alignb 2 25550 <1> 25551 <1> inode: 25552 <1> ; 11/03/2013. 25553 <1> ;Derived from UNIX v1 source code 'inode' structure (ux). 25554 <1> ;i. 25555 <1> 25556 00007116 <1> i.flgs: resw 1 25557 00007118 <1> i.nlks: resb 1 25558 00007119 <1> i.uid: resb 1 25559 0000711A <1> i.size: resw 1 ; size 25560 0000711C <1> i.dskp: resw 8 ; 16 bytes 25561 0000712C <1> i.ctim: resd 1 25562 00007130 <1> i.mtim: resd 1 25563 00007134 <1> i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.) 25564 <1> 25565 <1> I_SIZE equ $ - inode 25566 <1> 25567 <1> process: 25568 <1> ; 06/05/2015 25569 <1> ; 11/03/2013 - 05/02/2014 25570 <1> ;Derived from UNIX v1 source code 'proc' structure (ux). 25571 <1> ;p. 25572 <1> 25573 00007136 <1> p.pid: resw nproc 25574 00007156 <1> p.ppid: resw nproc 25575 00007176 <1> p.break: resw nproc 25576 00007196 <1> p.ttyc: resb nproc ; console tty in Retro UNIX 8086 v1. 25577 000071A6 <1> p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1. 25578 000071B6 <1> p.link: resb nproc 25579 000071C6 <1> p.stat: resb nproc 25580 <1> 25581 <1> ; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 25582 000071D6 <1> p.upage: resd nproc ; Physical address of the process's 25583 <1> ; 'user' structure 25584 <1> 25585 <1> 25586 <1> P_SIZE equ $ - process 25587 <1> 25588 <1> 25589 <1> ; fsp table (original UNIX v1) 25590 <1> ; 25591 <1> ;Entry 25592 <1> ; 15 0 25593 <1> ; 1 |---|---------------------------------------| 25594 <1> ; |r/w| i-number of open file | 25595 <1> ; |---|---------------------------------------| 25596 <1> ; | device number | 25597 <1> ; |-------------------------------------------| 25598 <1> ; (*) | offset pointer, i.e., r/w pointer to file | 25599 <1> ; |-------------------------------------------| 25600 <1> ; | flag that says | number of processes | 25601 <1> ; | file deleted | that have file open | 25602 <1> ; |-------------------------------------------| 25603 <1> ; 2 | | 25604 <1> ; |-------------------------------------------| 25605 <1> ; | | 25606 <1> ; |-------------------------------------------| 25607 <1> ; | | 25608 <1> ; |-------------------------------------------| 25609 <1> ; | | 25610 <1> ; |-------------------------------------------| 25611 <1> ; 3 | | 25612 <1> ; | | 25613 <1> ; 25614 <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 25615 <1> 25616 <1> 25617 <1> ; 15/04/2015 25618 00007216 <1> fsp: resb nfiles * 10 ; 11/05/2015 (8 -> 10) 25619 0000740A <1> bufp: resd (nbuf+2) ; will be initialized 25620 0000742A <1> ii: resw 1 25621 0000742C <1> idev: resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 ! 25622 0000742E <1> cdev: resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 ! 25623 <1> ; 18/05/2015 25624 <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!) 25625 <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv') 25626 <1> ; 0 -> root device (which has Retro UNIX 8086 v1 file system) 25627 <1> ; 1 -> mounted device (which has Retro UNIX 8086 v1 file system) 25628 <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures) 25629 <1> ; 0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0 25630 <1> ; 1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1 25631 <1> ; 2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h 25632 <1> ; 3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h 25633 <1> ; 4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h 25634 <1> ; 5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h 25635 00007430 <1> rdev: resb 1 ; root device number ; Retro UNIX 8086 v1 feature only! 25636 <1> ; as above, for physical drives numbers in following table 25637 00007431 <1> mdev: resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only! 25638 <1> ; 15/04/2015 25639 00007432 <1> active: resb 1 25640 00007433 <1> resb 1 ; 09/06/2015 25641 00007434 <1> mnti: resw 1 25642 00007436 <1> mpid: resw 1 25643 00007438 <1> rootdir: resw 1 25644 <1> ; 14/02/2014 25645 <1> ; Major Modification: Retro UNIX 8086 v1 feature only! 25646 <1> ; Single level run queue 25647 <1> ; (in order to solve sleep/wakeup lock) 25648 0000743A <1> runq: resw 1 25649 0000743C <1> imod: resb 1 25650 0000743D <1> smod: resb 1 25651 0000743E <1> mmod: resb 1 25652 0000743F <1> sysflg: resb 1 25653 <1> 25654 <1> alignb 4 25655 <1> 25656 <1> user: 25657 <1> ; 04/12/2015 25658 <1> ; 18/10/2015 25659 <1> ; 12/10/2015 25660 <1> ; 21/09/2015 25661 <1> ; 24/07/2015 25662 <1> ; 16/06/2015 25663 <1> ; 09/06/2015 25664 <1> ; 11/05/2015 25665 <1> ; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications) 25666 <1> ; 10/10/2013 25667 <1> ; 11/03/2013. 25668 <1> ;Derived from UNIX v1 source code 'user' structure (ux). 25669 <1> ;u. 25670 <1> 25671 00007440 <1> u.sp: resd 1 ; esp (kernel stack at the beginning of 'sysent') 25672 00007444 <1> u.usp: resd 1 ; esp (kernel stack points to user's registers) 25673 00007448 <1> u.r0: resd 1 ; eax 25674 0000744C <1> u.cdir: resw 1 25675 0000744E <1> u.fp: resb 10 25676 00007458 <1> u.fofp: resd 1 25677 0000745C <1> u.dirp: resd 1 25678 00007460 <1> u.namep: resd 1 25679 00007464 <1> u.off: resd 1 25680 00007468 <1> u.base: resd 1 25681 0000746C <1> u.count: resd 1 25682 00007470 <1> u.nread: resd 1 25683 00007474 <1> u.break: resd 1 ; break 25684 00007478 <1> u.ttyp: resw 1 25685 0000747A <1> u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 25686 <1> ;u.pri: resw 1 ; 14/02/2014 25687 0000748A <1> u.quant: resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant) 25688 0000748B <1> u.pri: resb 1 ; 25689 0000748C <1> u.intr: resw 1 25690 0000748E <1> u.quit: resw 1 25691 <1> ;u.emt: resw 1 ; 10/10/2013 25692 00007490 <1> u.ilgins: resw 1 25693 00007492 <1> u.cdrv: resw 1 ; cdev 25694 00007494 <1> u.uid: resb 1 ; uid 25695 00007495 <1> u.ruid: resb 1 25696 00007496 <1> u.bsys: resb 1 25697 00007497 <1> u.uno: resb 1 25698 00007498 <1> u.upage: resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only ! 25699 <1> ; tty number (rtty, rcvt, wtty) 25700 0000749C <1> u.ttyn: resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only ! 25701 <1> ; last error number 25702 0000749D <1> u.error: resd 1 ; 28/07/2013 - 09/03/2015 25703 <1> ; Retro UNIX 8086/386 v1 feature only! 25704 000074A1 <1> u.pgdir: resd 1 ; 09/03/2015 (page dir addr of process) 25705 000074A5 <1> u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process) 25706 000074A9 <1> u.pbase: resd 1 ; 20/05/2015 (physical base/transfer address) 25707 000074AD <1> u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page) 25708 <1> ;u.pncount: resw 1 25709 <1> ; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir') 25710 <1> ;u.pnbase: resd 1 25711 <1> ; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir') 25712 <1> ; 09/06/2015 25713 000074AF <1> u.kcall: resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign 25714 000074B0 <1> u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite) 25715 <1> ; 24/07/2015 - 24/06/2015 25716 <1> ;u.args: resd 1 ; arguments list (line) offset from start of [u.upage] 25717 <1> ; (arg list/line is from offset [u.args] to 4096 in [u.upage]) 25718 <1> ; ([u.args] points to argument count -argc- address offset) 25719 <1> ; 24/06/2015 25720 <1> ;u.core: resd 1 ; physical start address of user's memory space (for sys exec) 25721 <1> ;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec) 25722 <1> ; 21/09/2015 (debugging - page fault analyze) 25723 000074B1 <1> u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr) 25724 <1> 25725 000074B5 <1> alignb 4 25726 <1> 25727 <1> U_SIZE equ $ - user 25728 <1> 25729 <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec') 25730 000074B8 <1> pcore: resd 1 ; physical start address of user's memory space (for sys exec) 25731 000074BC <1> ecore: resd 1 ; physical start address of user's memory space (for sys exec) 25732 000074C0 <1> nbase: resd 1 ; physical base address for 'namei' & 'sysexec' 25733 000074C4 <1> ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec' 25734 000074C6 <1> argc: resw 1 ; argument count for 'sysexec' 25735 000074C8 <1> argv: resd 1 ; argument list (recent) address for 'sysexec' 25736 <1> 25737 <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning 25738 <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1 25739 000074CC <1> rw: resb 1 ;; Read/Write sign (iget) 25740 000074CD <1> rwdsk: resb 1 ;; Read/Write function number (diskio) - 16/06/2015 25741 000074CE <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015 25742 000074CF <1> resb 1 ;; Reserved (16/06/2015) 25743 <1> 25744 <1> ;alignb 4 25745 <1> 25746 <1> ; 22/08/2015 25747 000074D0 <1> buffer: resb nbuf * 520 25748 <1> 25749 00008100 <1> sb0: resd 2 25750 <1> ;s: 25751 <1> ; (root disk) super block buffer 25752 <1> systm: 25753 <1> ; 13/11/2015 (Retro UNIX 386 v1) 25754 <1> ; 11/03/2013. 25755 <1> ;Derived from UNIX v1 source code 'systm' structure (ux). 25756 <1> ;s. 25757 <1> 25758 00008108 <1> resw 1 25759 0000810A <1> resb 360 ; 2880 sectors ; original UNIX v1 value: 128 25760 00008272 <1> resw 1 25761 00008274 <1> resb 32 ; 256+40 inodes ; original UNIX v1 value: 64 25762 00008294 <1> s.time: resd 1 25763 00008298 <1> s.syst: resd 1 25764 0000829C <1> s.wait_: resd 1 ; wait 25765 000082A0 <1> s.idlet: resd 1 25766 000082A4 <1> s.chrgt: resd 1 25767 000082A8 <1> s.drerr: resw 1 25768 <1> 25769 <1> S_SIZE equ $ - systm 25770 <1> 25771 000082AA <1> resb 512-S_SIZE ; 03/06/2015 25772 <1> 25773 00008308 <1> sb1: resd 2 25774 <1> ; (mounted disk) super block buffer 25775 <1> mount: 25776 00008310 <1> resb 512 ; 03/06/2015 25777 <1> 25778 <1> ;/ ux -- unix 25779 <1> ; 25780 <1> ;systm: 25781 <1> ; 25782 <1> ; .=.+2 25783 <1> ; .=.+128. 25784 <1> ; .=.+2 25785 <1> ; .=.+64. 25786 <1> ; s.time: .=.+4 25787 <1> ; s.syst: .=.+4 25788 <1> ; s.wait: .=.+4 25789 <1> ; s.idlet:.=.+4 25790 <1> ; s.chrgt:.=.+4 25791 <1> ; s.drerr:.=.+2 25792 <1> ;inode: 25793 <1> ; i.flgs: .=.+2 25794 <1> ; i.nlks: .=.+1 25795 <1> ; i.uid: .=.+1 25796 <1> ; i.size: .=.+2 25797 <1> ; i.dskp: .=.+16. 25798 <1> ; i.ctim: .=.+4 25799 <1> ; i.mtim: .=.+4 25800 <1> ; . = inode+32. 25801 <1> ;mount: .=.+1024. 25802 <1> ;proc: 25803 <1> ; p.pid: .=.+[2*nproc] 25804 <1> ; p.dska: .=.+[2*nproc] 25805 <1> ; p.ppid: .=.+[2*nproc] 25806 <1> ; p.break:.=.+[2*nproc] 25807 <1> ; p.link: .=.+nproc 25808 <1> ; p.stat: .=.+nproc 25809 <1> ;tty: 25810 <1> ; . = .+[ntty*8.] 25811 <1> ;fsp: .=.+[nfiles*8.] 25812 <1> ;bufp: .=.+[nbuf*2]+6 25813 <1> ;sb0: .=.+8 25814 <1> ;sb1: .=.+8 25815 <1> ;swp: .=.+8 25816 <1> ;ii: .=.+2 25817 <1> ;idev: .=.+2 25818 <1> ;cdev: .=.+2 25819 <1> ;deverr: .=.+12. 25820 <1> ;active: .=.+2 25821 <1> ;rfap: .=.+2 25822 <1> ;rkap: .=.+2 25823 <1> ;tcap: .=.+2 25824 <1> ;tcstate:.=.+2 25825 <1> ;tcerrc: .=.+2 25826 <1> ;mnti: .=.+2 25827 <1> ;mntd: .=.+2 25828 <1> ;mpid: .=.+2 25829 <1> ;clockp: .=.+2 25830 <1> ;rootdir:.=.+2 25831 <1> ;toutt: .=.+16. 25832 <1> ;touts: .=.+32. 25833 <1> ;runq: .=.+6 25834 <1> ; 25835 <1> ;wlist: .=.+40. 25836 <1> ;cc: .=.+30. 25837 <1> ;cf: .=.+31. 25838 <1> ;cl: .=.+31. 25839 <1> ;clist: .=.+510. 25840 <1> ;imod: .=.+1 25841 <1> ;smod: .=.+1 25842 <1> ;mmod: .=.+1 25843 <1> ;uquant: .=.+1 25844 <1> ;sysflg: .=.+1 25845 <1> ;pptiflg:.=.+1 25846 <1> ;ttyoch: .=.+1 25847 <1> ; .even 25848 <1> ; .=.+100.; sstack: 25849 <1> ;buffer: .=.+[ntty*140.] 25850 <1> ; .=.+[nbuf*520.] 25851 <1> ; 25852 <1> ; . = core-64. 25853 <1> ;user: 25854 <1> ; u.sp: .=.+2 25855 <1> ; u.usp: .=.+2 25856 <1> ; u.r0: .=.+2 25857 <1> ; u.cdir: .=.+2 25858 <1> ; u.fp: .=.+10. 25859 <1> ; u.fofp: .=.+2 25860 <1> ; u.dirp: .=.+2 25861 <1> ; u.namep: .=.+2 25862 <1> ; u.off: .=.+2 25863 <1> ; u.base: .=.+2 25864 <1> ; u.count: .=.+2 25865 <1> ; u.nread: .=.+2 25866 <1> ; u.break: .=.+2 25867 <1> ; u.ttyp: .=.+2 25868 <1> ; u.dirbuf:.=.+10. 25869 <1> ; u.pri: .=.+2 25870 <1> ; u.intr: .=.+2 25871 <1> ; u.quit: .=.+2 25872 <1> ; u.emt: .=.+2 25873 <1> ; u.ilgins:.=.+2 25874 <1> ; u.cdev: .=.+2 25875 <1> ; u.uid: .=.+1 25876 <1> ; u.ruid: .=.+1 25877 <1> ; u.bsys: .=.+1 25878 <1> ; u.uno: .=.+1 25879 <1> ;. = core 25880 25881 ;; Memory (swap) Data (11/03/2015) 25882 ; 09/03/2015 25883 00008510 swpq_count: resw 1 ; count of pages on the swap que 25884 00008512 swp_drv: resd 1 ; logical drive description table address of the swap drive/disk 25885 00008516 swpd_size: resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 25886 0000851A swpd_free: resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical) 25887 0000851E swpd_next: resd 1 ; next free page block 25888 00008522 swpd_last: resd 1 ; last swap page block 25889 25890 00008526 alignb 4 25891 25892 ; 10/07/2015 25893 ; 28/08/2014 25894 00008528 error_code: resd 1 25895 ; 29/08/2014 25896 0000852C FaultOffset: resd 1 25897 ; 21/09/2015 25898 00008530 PF_Count: resd 1 ; total page fault count 25899 ; (for debugging - page fault analyze) 25900 ; 'page _fault_handler' (memory.inc) 25901 ; 'sysgeterr' (u9.s) 25902 ;; 21/08/2015 25903 ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s 25904 25905 bss_end: 25906 25907 ; 27/12/2013 25908 _end: ; end of kernel code (and read only data, just before bss)