/*
* 测试输入的段值.必须位于内存地址64KB边界处,否则进入死循环.
*/
movw %es, %ax
testw $0x0fff, %ax
die: jne die # es must be at 64kB boundary
xorw %bx, %bx # bx is starting address within segment [bx为段内偏移位置]
rp_read:
#ifdef __BIG_KERNEL__
bootsect_kludge = 0x220 # 0x200 (size of bootsector) + 0x20 (offset
lcall bootsect_kludge # of bootsect_kludge in setup.S)
#else
movw %es, %ax
subw $SYSSEG, %ax
#endif
cmpw syssize, %ax # have we loaded all yet ?
jbe ok1_read
ret
ok1_read:
movw sectors, %ax /* 取每磁道扇区数 */
subw sread, %ax /* 减去当前磁道已读扇区数 */
movw %ax, %cx /* cx = ax = 当前磁道未读扇区数. */
shlw $9, %cx /* cx = cx * 512字节. */
addw %bx, %cx /* cx = cx + 段内当前偏移值(bx) = 此次读操作后,段内共读入的字节数. */
jnc ok2_read /* 无进位转移.若没超过64KB字节,则跳转至ok2_read处执行. */
je ok2_read
xorw %ax, %ax /* 若加上此次将读磁道上所有未读扇区时会超过64KB,则计算此时最多能读 */
subw %bx, %ax /* 入的字节数(64KB - 段内读偏移位置),再转换需要读取的扇区数. */
shrw $9, %ax
ok2_read:
call read_track
movw %ax, %cx /* cx = 该次操作已读取的扇区数. */
addw sread, %ax /* 当前磁道上已经读取的扇区数. */
cmpw sectors, %ax /* 如果当前磁道上还有扇区未读,则跳到ok3_read处. */
jne ok3_read
/* 读该磁道的下一磁头面(1号磁头)上的数据.如果已经完成,则去读下一磁道. */
mov $1, %ax
subw head, %ax /* 判断当前磁头号. */
jne ok4_read /* 如果是0磁头,则再去读1磁头同上的扇区数据. */
incw track /* 否则去读下一磁道. */
ok4_read:
movw %ax, head /* 保存当前磁头号. */
xorw %ax, %ax /* 清当前磁道已读扇区数. */
ok3_read:
movw %ax, sread /* 保存当前磁道已读扇区数. */
shlw $9, %cx /* 上次已读扇区数 * 512字节. */
addw %cx, %bx /* 调整当前段内数据开始位置. */
jnc rp_read /* 若小于64KB边界值,则跳转到rp_read处,继续读数据.
* 否则调整当前值,为读下一段数据作准备. */
movw %es, %ax
addb $0x10, %ah /* 将段基址调整为指向下一个64KB段内存. */
movw %ax, %es
xorw %bx, %bx /* 清段内数据开始偏移值. */
jmp rp_read /* 继续读数据. */
read_track:
pusha
pusha
movw $0xe2e, %ax # loading... message 2e = .
movw $7, %bx
int $0x10
popa
movw track, %dx /* 取当前磁道号. */
movw sread, %cx /* 取当前磁道上已读扇区数. */
incw %cx /* cl = 开始读扇区. */
movb %dl, %ch /* ch = 当前磁道号. */
movw head, %dx /* 取当前磁头号 */
movb %dl, %dh /* dh等于磁头号 */
andw $0x0100, %dx /* 磁头号不大于1. */
movb $2, %ah /* ah = 2,读磁盘扇区功能号 */
pushw %dx # save for error dump
pushw %cx
pushw %bx
pushw %ax
int $0x13
jc bad_rt /* 若出错,则跳转至bad_rt. */
addw $8, %sp
popa
ret
/* 执行驱动器复位操作(磁盘中断功能号0),再跳转到read_track处重试. */
bad_rt:
pushw %ax # save error code
call print_all # ah = error, al = read
xorb %ah, %ah
xorb %dl, %dl
int $0x13
addw $10, %sp
popa
jmp read_track
# print_all is for debugging purposes.
#
# it will print out all of the registers. The assumption(假定) is that this is
# called from a routine, with a stack frame like
#
# %dx
# %cx
# %bx
# %ax
# (error)
# ret <- %sp
print_all:
movw $5, %cx # error code + 4 registers
movw %sp, %bp
print_loop:
pushw %cx # save count left
call print_nl # nl for readability
cmpb $5, %cl
jae no_reg # see if register name is needed
movw $0xe05 + 'A' - 1, %ax
subb %cl, %al
int $0x10
movb $'X', %al
int $0x10
movb $':', %al
int $0x10
no_reg:
addw $2, %bp # next register
call print_hex # print it
popw %cx
loop print_loop
ret
/* 屏幕打印"回车/换行"符 */
print_nl:
movw $0xe0d, %ax # CR
int $0x10
movb $0xa, %al # LF
int $0x10
ret
# print_hex is for debugging purposes, and prints the word
# pointed to by ss:bp in hexadecimal(十六进制).
/* 用十六进制的格式打印ss:bp处的字 */
print_hex:
movw $4, %cx # 4 hex digits
movw (%bp), %dx # load word into dx
print_digit:
rolw $4, %dx # rotate to use low 4 bits
movw $0xe0f, %ax # ah = request
andb %dl, %al # al = mask for nybble
addb $0x90, %al # convert al to ascii hex
daa # in only four instructions!
adc $0x40, %al
daa
int $0x10
loop print_digit
ret
# this procedure turns off the floppy drive motor, so
# that we enter the kernel in a known state, and
# don't have to worry about it later.'
# 这个子程序用于关闭软驱的马达,这样我们进入内核后它处于已知状态,以后也就无须担心它了
kill_motor:
movw $0x3f2, %dx # 软驱控制卡的驱动端口,只写
xorb %al, %al # A驱动器,关闭FDC,禁止DMA和中断请求,关闭马达
outb %al, %dx
ret
sectors: .word 0 # 存放当前启动软盘每磁道的扇区数
disksizes: .byte 36, 18, 15, 0
msg1: .byte 13, 10 # 回车,换行的ASCII码
.ascii "Loading"
# XXX: This is a "very" snug fit.
.org 497
setup_sects: .byte SETUPSECS
root_flags: .word CONFIG_ROOT_RDONLY
syssize: .word SYSSIZE
swap_dev: .word SWAP_DEV
ram_size: .word RAMDISK
vid_mode: .word SVGA_MODE
root_dev: .word ROOT_DEV
boot_flag: .word 0xAA55
