diff --git a/io.asm b/io.asm index b2f5f66..f4dec7e 100644 --- a/io.asm +++ b/io.asm @@ -26,21 +26,21 @@ assume cs:iogroup, ds:iogroup, es:iogroup org 0 ; Jump table -jmp init -jmp status -jmp getch -jmp putch -jmp unimplemented ; Output to printer -jmp unimplemented ; Serial read -jmp unimplemented ; Serial write -jmp diskread -jmp diskwrite -jmp diskchange -jmp setdate -jmp settime -jmp gettime -jmp flush -jmp mapdev +jmp init ; 0000 +jmp status ; 0003 +jmp getch ; 0006 +jmp putch ; 0009 +jmp unimplemented ; 000c Output to printer +jmp unimplemented ; 000f Serial read +jmp unimplemented ; 0012 Serial write +jmp diskread ; 0015 +jmp diskwrite ; 0018 +jmp near ptr diskchange ; 001b +jmp setdate ; 001e +jmp settime ; 0021 +jmp gettime ; 0024 +jmp flush ; 0027 +jmp near ptr mapdev ; 002a init: cld @@ -70,13 +70,39 @@ init: call dosinit - mov al, 'c' - jmp error + ; Memory for command.com is at ds, save for later and revert ds + push ds + mov ax, cs + mov ds, ax + + ; Open command.com + mov dx, offset iogroup:command_fcb + mov ah, 0fh + int 21h + + test al, al + jnz open_error + + mov al, '+' + jmp unfinished + + open_error: + mov al, '-' + + unfinished: + mov ah, 0eh + int 10h + jmp hang ; OUT: ; al = character if any ; zf = there were no characters status proc far + push ax + mov ax, 0e00h + 's' + int 10h + pop ax + call far_caller ; TODO: Implement xor ax, ax test ax, ax @@ -97,15 +123,164 @@ putch proc far ret putch endp -diskread: - mov al, 'r' - jmp error +; IN: +; al = driver number +; ds:bx = buffer +; cx = number of sectors to read +; dx = LBA of first sector +; OUT: +; TODO: Document +diskread proc far + push ax + mov ax, 0e00h + 'r' + int 10h + pop ax + call far_caller + + push es + push ax + push bx + push cx + push dx + push di + + ; Save driver number + push ax + + ; BIOS uses es:bx instead of ds:bx + mov ax, ds + mov es, ax + + mov ax, dx + + ; Put drive(r) number in dl + pop dx + + sector_read_loop: + jcxz ret_diskread + + mov di, 3 + 1 ; 3 retries, + 1 since we dec first + + try_sector_read: + push ax + push cx + + call chs + + mov ah, 2 + mov al, 1 + int 13h + + jnc sector_read_success + + dec di + jz sector_read_fail + pop cx + pop ax + jmp try_sector_read + + sector_read_fail: + pop cx + pop ax + + pop di + pop dx + pop ax ; Would be cx, don't overwrite + pop bx + pop ax + pop es + + mov al, 12 ; TODO: Don't hardcode + ret + + sector_read_success: + pop cx + pop ax + dec cx + inc ax + add bx, 512 + jmp sector_read_loop + + ret_diskread: + pop di + pop dx + pop cx + pop bx + pop ax + pop es + + ret + +diskread endp + +; IN: +; ax = LBA +; OUT: +; ch = cylinder +; cl = sector & 2 high bits of cylinder +; dh = head +chs proc + push ax + push dx + + xor dx, dx + ; cylinder (track) - head - sector + ; cylinder = LBA / sectorspertrack / heads + ; head = LBA / sectorspertrack % heads + ; sector = LBA % sectorspertrack + 1 + div cs:sectorspertrack + ; ax = LBA / sectorspertrack + ; dx = LBA % sectorspertrack + + ; sector + mov cl, dl + inc cl + + xor dx, dx + div cs:heads + ; ax = LBA / sectorspertrack / heads + ; dx = LBA / sectorspertrack % heads + + ; head + mov dh, dl + + ; cylinder (track) + mov ch, al + ;shr ax, 1 + ;shr ax, 1 + ;and al, 0c0h + ;or cl, al + + mov ax, dx + pop dx + mov dh, ah + pop ax + + ret +chs endp + diskwrite: mov al, 'w' jmp error -diskchange: - mov al, 'c' - jmp error + +; IN: +; al = drive +; OUT: +; ah = -1 different / 0 dunno / 1 same +; cf = 0 -> al = driver num +; cf = 1 -> al = disk error code +diskchange proc far + push ax + mov ax, 0e00h + 'd' + int 10h + pop ax + call far_caller + ; TODO: Implement + mov ax, 0100h + clc + ret +diskchange endp + setdate: mov al, 'd' jmp error @@ -119,9 +294,15 @@ flush: mov al, 'f' jmp error -mapdev: - mov al, 'm' - jmp error +mapdev proc far + push ax + mov ax, 0e00h + 'm' + int 10h + pop ax + call far_caller + ; TODO: Figure out if this does anything? + ret +mapdev endp unimplemented: mov al, '@' @@ -129,6 +310,10 @@ unimplemented: error: mov ah, 0eh int 10h + mov ah, 0eh + mov al, '!' + int 10h + call far_caller hang: hlt @@ -136,10 +321,15 @@ hang: code ends +; TODO: STRUC? + constants segment +sectorspertrack dw 8 ; TODO: Don't hardcode +heads dw 2 ; TODO: Don't hardcode + disks_table: - db 1 ; 1 drive + db 1 ; 1 drive, TODO: Don't hardcode db 0 ; Physical drive 0 dw offset iogroup:parameters_320k @@ -154,4 +344,105 @@ parameters_320k: constants ends +data segment + +command_fcb: + db 1 ; First drive, TODO: Don't hardcode + db "COMMAND COM" + db 25 dup (?) + +data ends + +code segment +hexprint16 proc + xchg al, ah + call hexprint8 + xchg al, ah +hexprint8 proc + rol al, 1 + rol al, 1 + rol al, 1 + rol al, 1 + call hexprint4 + rol al, 1 + rol al, 1 + rol al, 1 + rol al, 1 +hexprint4 proc + push ax + + and al, 0fh + cmp al, 9 + jbe under_10 + add al, 'a' - 10 - '0' + +under_10: + add al, '0' + mov ah, 0eh + int 10h + + pop ax + ret +hexprint4 endp +hexprint8 endp +hexprint16 endp +newline proc + push ax + mov ax, 0e0dh + int 10h + mov ax, 0e0ah + int 10h + pop ax + ret +newline endp +space proc + push ax + mov ax, 0e20h + int 10h + pop ax + ret +space endp + +far_caller proc + push ax + push bx + mov bx, sp + mov ax, [ss:bx + 8] + call hexprint16 + mov al, ':' + mov ah, 0eh + int 10h + pop bx + pop ax + +near_caller proc + push ax + push bx + mov bx, sp + mov ax, [ss:bx + 6] + call hexprint16 + call space + pop bx + pop ax + ret +near_caller endp +far_caller endp + +logaddr proc + push ax + push bx + mov al, '>' + mov ah, 0eh + int 10h + mov bx, sp + mov ax, [ss:bx + 4] + call hexprint16 + call space + pop bx + pop ax + ret +logaddr endp + +code ends + end