1*0a6a1f1dSLionel Sambuc/* $NetBSD: bios_disk.S,v 1.22 2014/07/19 14:50:21 erh Exp $ */ 258a2b000SEvgeniy Ivanov 358a2b000SEvgeniy Ivanov/* 458a2b000SEvgeniy Ivanov * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 558a2b000SEvgeniy Ivanov * 658a2b000SEvgeniy Ivanov * Mach Operating System 758a2b000SEvgeniy Ivanov * Copyright (c) 1992, 1991 Carnegie Mellon University 858a2b000SEvgeniy Ivanov * All Rights Reserved. 958a2b000SEvgeniy Ivanov * 1058a2b000SEvgeniy Ivanov * Permission to use, copy, modify and distribute this software and its 1158a2b000SEvgeniy Ivanov * documentation is hereby granted, provided that both the copyright 1258a2b000SEvgeniy Ivanov * notice and this permission notice appear in all copies of the 1358a2b000SEvgeniy Ivanov * software, derivative works or modified versions, and any portions 1458a2b000SEvgeniy Ivanov * thereof, and that both notices appear in supporting documentation. 1558a2b000SEvgeniy Ivanov * 1658a2b000SEvgeniy Ivanov * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 1758a2b000SEvgeniy Ivanov * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 1858a2b000SEvgeniy Ivanov * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1958a2b000SEvgeniy Ivanov * 2058a2b000SEvgeniy Ivanov * Carnegie Mellon requests users of this software to return to 2158a2b000SEvgeniy Ivanov * 2258a2b000SEvgeniy Ivanov * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 2358a2b000SEvgeniy Ivanov * School of Computer Science 2458a2b000SEvgeniy Ivanov * Carnegie Mellon University 2558a2b000SEvgeniy Ivanov * Pittsburgh PA 15213-3890 2658a2b000SEvgeniy Ivanov * 2758a2b000SEvgeniy Ivanov * any improvements or extensions that they make and grant Carnegie Mellon 2858a2b000SEvgeniy Ivanov * the rights to redistribute these changes. 2958a2b000SEvgeniy Ivanov */ 3058a2b000SEvgeniy Ivanov 3158a2b000SEvgeniy Ivanov/* 3258a2b000SEvgeniy Ivanov Copyright 1988, 1989, 1990, 1991, 1992 3358a2b000SEvgeniy Ivanov by Intel Corporation, Santa Clara, California. 3458a2b000SEvgeniy Ivanov 3558a2b000SEvgeniy Ivanov All Rights Reserved 3658a2b000SEvgeniy Ivanov 3758a2b000SEvgeniy IvanovPermission to use, copy, modify, and distribute this software and 3858a2b000SEvgeniy Ivanovits documentation for any purpose and without fee is hereby 3958a2b000SEvgeniy Ivanovgranted, provided that the above copyright notice appears in all 4058a2b000SEvgeniy Ivanovcopies and that both the copyright notice and this permission notice 4158a2b000SEvgeniy Ivanovappear in supporting documentation, and that the name of Intel 4258a2b000SEvgeniy Ivanovnot be used in advertising or publicity pertaining to distribution 4358a2b000SEvgeniy Ivanovof the software without specific, written prior permission. 4458a2b000SEvgeniy Ivanov 4558a2b000SEvgeniy IvanovINTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 4658a2b000SEvgeniy IvanovINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, 4758a2b000SEvgeniy IvanovIN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 4858a2b000SEvgeniy IvanovCONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 4958a2b000SEvgeniy IvanovLOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 5058a2b000SEvgeniy IvanovNEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 5158a2b000SEvgeniy IvanovWITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 5258a2b000SEvgeniy Ivanov*/ 5358a2b000SEvgeniy Ivanov 5458a2b000SEvgeniy Ivanov/* extracted from netbsd:sys/arch/i386/boot/bios.S */ 5558a2b000SEvgeniy Ivanov 5658a2b000SEvgeniy Ivanov#include <machine/asm.h> 5758a2b000SEvgeniy Ivanov 5858a2b000SEvgeniy Ivanov/* 5958a2b000SEvgeniy Ivanov * BIOS call "INT 0x13 Function 0x0" to reset the disk subsystem 6058a2b000SEvgeniy Ivanov * Call with %ah = 0x0 6158a2b000SEvgeniy Ivanov * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) 6258a2b000SEvgeniy Ivanov * Return: 6358a2b000SEvgeniy Ivanov * %al = 0x0 on success; err code on failure 6458a2b000SEvgeniy Ivanov */ 6558a2b000SEvgeniy IvanovENTRY(biosdisk_reset) 6658a2b000SEvgeniy Ivanov pusha 6758a2b000SEvgeniy Ivanov 6858a2b000SEvgeniy Ivanov movb %al, %dl # device 6958a2b000SEvgeniy Ivanov 7058a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 7158a2b000SEvgeniy Ivanov .code16 7258a2b000SEvgeniy Ivanov 7358a2b000SEvgeniy Ivanov movb $0x0, %ah # subfunction 7458a2b000SEvgeniy Ivanov int $0x13 7558a2b000SEvgeniy Ivanov setc %bl 7658a2b000SEvgeniy Ivanov movb %ah, %bh # save error code 7758a2b000SEvgeniy Ivanov 7858a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 7958a2b000SEvgeniy Ivanov .code32 8058a2b000SEvgeniy Ivanov 8158a2b000SEvgeniy Ivanov movzwl %bx, %eax # return value in %eax 8258a2b000SEvgeniy Ivanov movl %eax, 28(%esp) 8358a2b000SEvgeniy Ivanov 8458a2b000SEvgeniy Ivanov popa 8558a2b000SEvgeniy Ivanov ret 8658a2b000SEvgeniy Ivanov 8758a2b000SEvgeniy Ivanov/* 8858a2b000SEvgeniy Ivanov * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory 8958a2b000SEvgeniy Ivanov * Call with %ah = 0x2 9058a2b000SEvgeniy Ivanov * %al = number of sectors 9158a2b000SEvgeniy Ivanov * %ch = cylinder 9258a2b000SEvgeniy Ivanov * %cl = sector 9358a2b000SEvgeniy Ivanov * %dh = head 9458a2b000SEvgeniy Ivanov * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) 9558a2b000SEvgeniy Ivanov * %es:%bx = segment:offset of buffer 9658a2b000SEvgeniy Ivanov * Return: 9758a2b000SEvgeniy Ivanov * %al = 0x0 on success; err code on failure 9858a2b000SEvgeniy Ivanov * 9958a2b000SEvgeniy Ivanov * biosdisk_read(dev, cyl, head, sect, count, buff_addr); 10058a2b000SEvgeniy Ivanov * 10158a2b000SEvgeniy Ivanov * Note: On failure, you must reset the disk with biosdisk_reset() before 10258a2b000SEvgeniy Ivanov * sending another command. 10358a2b000SEvgeniy Ivanov */ 10458a2b000SEvgeniy IvanovENTRY(biosdisk_read) 10558a2b000SEvgeniy Ivanov pusha 10658a2b000SEvgeniy Ivanov 10758a2b000SEvgeniy Ivanov movb 44(%esp), %dh 10858a2b000SEvgeniy Ivanov movw 40(%esp), %cx 10958a2b000SEvgeniy Ivanov xchgb %ch, %cl # cylinder; the highest 2 bits of cyl is in %cl 11058a2b000SEvgeniy Ivanov rorb $2, %cl 11158a2b000SEvgeniy Ivanov movb 48(%esp), %al 11258a2b000SEvgeniy Ivanov orb %al, %cl 11358a2b000SEvgeniy Ivanov incb %cl # sector; sec starts from 1, not 0 11458a2b000SEvgeniy Ivanov movb 36(%esp), %dl # device 11558a2b000SEvgeniy Ivanov movl 56(%esp), %ebx # buffer address (may be >64k) 11658a2b000SEvgeniy Ivanov movb 52(%esp), %al # number of sectors 11758a2b000SEvgeniy Ivanov 11858a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 11958a2b000SEvgeniy Ivanov .code16 12058a2b000SEvgeniy Ivanov 12158a2b000SEvgeniy Ivanov push %bx 12258a2b000SEvgeniy Ivanov shrl $4, %ebx # max segment 12358a2b000SEvgeniy Ivanov mov %ds, %si 12458a2b000SEvgeniy Ivanov add %si, %bx 12558a2b000SEvgeniy Ivanov mov %bx, %es # %es:%bx now valid buffer address 12658a2b000SEvgeniy Ivanov pop %bx 12758a2b000SEvgeniy Ivanov and $0xf, %bx # and min offset - to avoid overrun 12858a2b000SEvgeniy Ivanov 12958a2b000SEvgeniy Ivanov movb $0x2, %ah # subfunction 13058a2b000SEvgeniy Ivanov int $0x13 13158a2b000SEvgeniy Ivanov setc %al # error code is in %ah 13258a2b000SEvgeniy Ivanov 13358a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 13458a2b000SEvgeniy Ivanov .code32 13558a2b000SEvgeniy Ivanov 136*0a6a1f1dSLionel Sambuc andl $0x0000FFFF, %eax # Some bioses set high bits in %eax 137*0a6a1f1dSLionel Sambuc # on success, interfering with our 138*0a6a1f1dSLionel Sambuc # return value. Clear those out. 13958a2b000SEvgeniy Ivanov movl %eax, 28(%esp) 14058a2b000SEvgeniy Ivanov 14158a2b000SEvgeniy Ivanov popa 14258a2b000SEvgeniy Ivanov ret 14358a2b000SEvgeniy Ivanov 14458a2b000SEvgeniy Ivanov/* 14558a2b000SEvgeniy Ivanov * biosdisk_getinfo(int dev): return a word that represents the 14658a2b000SEvgeniy Ivanov * max number of sectors, heads and cylinders for this device 14758a2b000SEvgeniy Ivanov */ 14858a2b000SEvgeniy IvanovENTRY(biosdisk_getinfo) 14958a2b000SEvgeniy Ivanov push %es 15058a2b000SEvgeniy Ivanov pusha 15158a2b000SEvgeniy Ivanov 15258a2b000SEvgeniy Ivanov movb %al, %dl # diskinfo(drive #) 15358a2b000SEvgeniy Ivanov 15458a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 15558a2b000SEvgeniy Ivanov .code16 15658a2b000SEvgeniy Ivanov 15758a2b000SEvgeniy Ivanov push %dx # save drive # 15858a2b000SEvgeniy Ivanov movb $0x08, %ah # ask for disk info 15958a2b000SEvgeniy Ivanov int $0x13 16058a2b000SEvgeniy Ivanov pop %bx # restore drive # 16158a2b000SEvgeniy Ivanov jnc ok 16258a2b000SEvgeniy Ivanov 16358a2b000SEvgeniy Ivanov testb $0x80, %bl # is it a hard disk? 16458a2b000SEvgeniy Ivanov jnz ok 16558a2b000SEvgeniy Ivanov 16658a2b000SEvgeniy Ivanov /* 16758a2b000SEvgeniy Ivanov * Urk. Call failed. It is not supported for floppies by old BIOS's. 16858a2b000SEvgeniy Ivanov * Guess it's a 15-sector floppy. Initialize all the registers for 16958a2b000SEvgeniy Ivanov * documentation, although we only need head and sector counts. 17058a2b000SEvgeniy Ivanov */ 17158a2b000SEvgeniy Ivanov xorw %ax, %ax # set status to success 17258a2b000SEvgeniy Ivanov# movb %ah, %bh # %bh = 0 17358a2b000SEvgeniy Ivanov# movb $2, %bl # %bl bits 0-3 = drive type, 2 = 1.2M 17458a2b000SEvgeniy Ivanov movb $79, %ch # max track 17558a2b000SEvgeniy Ivanov movb $15, %cl # max sector 17658a2b000SEvgeniy Ivanov movb $1, %dh # max head 17758a2b000SEvgeniy Ivanov# movb $1, %dl # # floppy drives installed 17858a2b000SEvgeniy Ivanov # es:di = parameter table 17958a2b000SEvgeniy Ivanov # carry = 0 18058a2b000SEvgeniy Ivanov 18158a2b000SEvgeniy Ivanovok: 18258a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 18358a2b000SEvgeniy Ivanov .code32 18458a2b000SEvgeniy Ivanov 18558a2b000SEvgeniy Ivanov /* form a longword representing all this gunk */ 18658a2b000SEvgeniy Ivanov shrl $8, %eax # clear unnecessary bits 18758a2b000SEvgeniy Ivanov shll $24, %eax 18858a2b000SEvgeniy Ivanov shll $16, %ecx # do the same for %ecx 18958a2b000SEvgeniy Ivanov shrl $8, %ecx 19058a2b000SEvgeniy Ivanov movb %dh, %cl # max head 19158a2b000SEvgeniy Ivanov orl %ecx, %eax # return value in %eax 19258a2b000SEvgeniy Ivanov movl %eax, 28(%esp) 19358a2b000SEvgeniy Ivanov 19458a2b000SEvgeniy Ivanov popa 19558a2b000SEvgeniy Ivanov pop %es 19658a2b000SEvgeniy Ivanov ret 19758a2b000SEvgeniy Ivanov 19858a2b000SEvgeniy Ivanov/* 19958a2b000SEvgeniy Ivanov * int biosdisk_int13ext(int dev): 20058a2b000SEvgeniy Ivanov * check for availibility of int13 extensions. 20158a2b000SEvgeniy Ivanov */ 20258a2b000SEvgeniy IvanovENTRY(biosdisk_int13ext) 20358a2b000SEvgeniy Ivanov pusha 20458a2b000SEvgeniy Ivanov 20558a2b000SEvgeniy Ivanov movb %al, %dl # drive # 20658a2b000SEvgeniy Ivanov movw $0x55aa, %bx 20758a2b000SEvgeniy Ivanov 20858a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 20958a2b000SEvgeniy Ivanov .code16 21058a2b000SEvgeniy Ivanov 21158a2b000SEvgeniy Ivanov movb $0x41, %ah # ask for disk info 21258a2b000SEvgeniy Ivanov int $0x13 21358a2b000SEvgeniy Ivanov setnc %dl 21458a2b000SEvgeniy Ivanov 21558a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # switch back 21658a2b000SEvgeniy Ivanov .code32 21758a2b000SEvgeniy Ivanov 21858a2b000SEvgeniy Ivanov movzbl %dl, %eax # return value in %eax 21958a2b000SEvgeniy Ivanov 22058a2b000SEvgeniy Ivanov cmpw $0xaa55, %bx 22158a2b000SEvgeniy Ivanov sete %dl 22258a2b000SEvgeniy Ivanov andb %dl, %al 22358a2b000SEvgeniy Ivanov 22458a2b000SEvgeniy Ivanov andb %cl, %al 22558a2b000SEvgeniy Ivanov movl %eax, 28(%esp) 22658a2b000SEvgeniy Ivanov 22758a2b000SEvgeniy Ivanov popa 22858a2b000SEvgeniy Ivanov ret 22958a2b000SEvgeniy Ivanov 23058a2b000SEvgeniy Ivanov/* 23158a2b000SEvgeniy Ivanov * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory 23258a2b000SEvgeniy Ivanov * Call with %ah = 0x42 23358a2b000SEvgeniy Ivanov * %ds:%si = parameter block (data buffer address 23458a2b000SEvgeniy Ivanov * must be a real mode physical address). 23558a2b000SEvgeniy Ivanov * %dl = drive (0x80 for hard disk, 0x0 for floppy disk) 23658a2b000SEvgeniy Ivanov * Return: 23758a2b000SEvgeniy Ivanov * %al = 0x0 on success; err code on failure 23858a2b000SEvgeniy Ivanov */ 23958a2b000SEvgeniy IvanovENTRY(biosdisk_extread) 24058a2b000SEvgeniy Ivanov pusha 24158a2b000SEvgeniy Ivanov 24258a2b000SEvgeniy Ivanov movl %edx, %esi # parameter block 24358a2b000SEvgeniy Ivanov movb %al, %dl # device 24458a2b000SEvgeniy Ivanov 24558a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 24658a2b000SEvgeniy Ivanov .code16 24758a2b000SEvgeniy Ivanov 24858a2b000SEvgeniy Ivanov push %ds 24958a2b000SEvgeniy Ivanov movl %esi, %eax 25058a2b000SEvgeniy Ivanov shrl $4, %eax 25158a2b000SEvgeniy Ivanov movw %ds, %bx 25258a2b000SEvgeniy Ivanov addw %bx, %ax 25358a2b000SEvgeniy Ivanov movw %ax, %ds 25458a2b000SEvgeniy Ivanov andw $0xf, %si 25558a2b000SEvgeniy Ivanov 25658a2b000SEvgeniy Ivanov movb $0x42, %ah # subfunction 25758a2b000SEvgeniy Ivanov int $0x13 25858a2b000SEvgeniy Ivanov setc %bl 25958a2b000SEvgeniy Ivanov movb %ah, %bh # save error code 26058a2b000SEvgeniy Ivanov pop %ds 26158a2b000SEvgeniy Ivanov 26258a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 26358a2b000SEvgeniy Ivanov .code32 26458a2b000SEvgeniy Ivanov 26558a2b000SEvgeniy Ivanov movzwl %bx, %eax # return value in %eax 26658a2b000SEvgeniy Ivanov movl %eax, 28(%esp) 26758a2b000SEvgeniy Ivanov 26858a2b000SEvgeniy Ivanov popa 26958a2b000SEvgeniy Ivanov ret 27058a2b000SEvgeniy Ivanov 27158a2b000SEvgeniy IvanovENTRY(biosdisk_getextinfo) 27258a2b000SEvgeniy Ivanov pusha 27358a2b000SEvgeniy Ivanov 27458a2b000SEvgeniy Ivanov movl %edx, %esi # parameter block 27558a2b000SEvgeniy Ivanov movb %al, %dl # device 27658a2b000SEvgeniy Ivanov 27758a2b000SEvgeniy Ivanov call _C_LABEL(prot_to_real) # enter real mode 27858a2b000SEvgeniy Ivanov .code16 27958a2b000SEvgeniy Ivanov 28058a2b000SEvgeniy Ivanov push %ds 28158a2b000SEvgeniy Ivanov movl %esi, %eax 28258a2b000SEvgeniy Ivanov shrl $4, %eax 28358a2b000SEvgeniy Ivanov andw $0xf, %si 28458a2b000SEvgeniy Ivanov movw %ds, %bx 28558a2b000SEvgeniy Ivanov addw %bx, %ax 28658a2b000SEvgeniy Ivanov movw %ax, %ds 28758a2b000SEvgeniy Ivanov 28858a2b000SEvgeniy Ivanov movb $0x48, %ah # subfunction 28958a2b000SEvgeniy Ivanov int $0x13 29058a2b000SEvgeniy Ivanov setc %bl 29158a2b000SEvgeniy Ivanov pop %ds 29258a2b000SEvgeniy Ivanov 29358a2b000SEvgeniy Ivanov calll _C_LABEL(real_to_prot) # back to protected mode 29458a2b000SEvgeniy Ivanov .code32 29558a2b000SEvgeniy Ivanov 29658a2b000SEvgeniy Ivanov movzbl %bl, %eax # return value in %eax 29758a2b000SEvgeniy Ivanov movl %eax, 28(%esp) 29858a2b000SEvgeniy Ivanov 29958a2b000SEvgeniy Ivanov popa 30058a2b000SEvgeniy Ivanov ret 301