xref: /minix3/sys/arch/i386/stand/lib/bios_disk.S (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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