Home | History | Annotate | Line # | Download | only in lib
      1 /*	$NetBSD: bios_disk.S,v 1.23 2022/09/10 12:14:17 rillig Exp $	*/
      2 
      3 /*
      4  * Ported to boot 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
      5  *
      6  * Mach Operating System
      7  * Copyright (c) 1992, 1991 Carnegie Mellon University
      8  * All Rights Reserved.
      9  *
     10  * Permission to use, copy, modify and distribute this software and its
     11  * documentation is hereby granted, provided that both the copyright
     12  * notice and this permission notice appear in all copies of the
     13  * software, derivative works or modified versions, and any portions
     14  * thereof, and that both notices appear in supporting documentation.
     15  *
     16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     18  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     19  *
     20  * Carnegie Mellon requests users of this software to return to
     21  *
     22  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     23  *  School of Computer Science
     24  *  Carnegie Mellon University
     25  *  Pittsburgh PA 15213-3890
     26  *
     27  * any improvements or extensions that they make and grant Carnegie Mellon
     28  * the rights to redistribute these changes.
     29  */
     30 
     31 /*
     32   Copyright 1988, 1989, 1990, 1991, 1992
     33    by Intel Corporation, Santa Clara, California.
     34 
     35                 All Rights Reserved
     36 
     37 Permission to use, copy, modify, and distribute this software and
     38 its documentation for any purpose and without fee is hereby
     39 granted, provided that the above copyright notice appears in all
     40 copies and that both the copyright notice and this permission notice
     41 appear in supporting documentation, and that the name of Intel
     42 not be used in advertising or publicity pertaining to distribution
     43 of the software without specific, written prior permission.
     44 
     45 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
     46 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
     47 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
     48 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
     49 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
     50 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
     51 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     52 */
     53 
     54 /* extracted from netbsd:sys/arch/i386/boot/bios.S */
     55 
     56 #include <machine/asm.h>
     57 
     58 /*
     59  * BIOS call "INT 0x13 Function 0x0" to reset the disk subsystem
     60  *	Call with	%ah = 0x0
     61  *			%dl = drive (0x80 for hard disk, 0x0 for floppy disk)
     62  *	Return:
     63  *			%al = 0x0 on success; err code on failure
     64  */
     65 ENTRY(biosdisk_reset)
     66 	pusha
     67 
     68 	movb	%al, %dl	# device
     69 
     70 	call	_C_LABEL(prot_to_real)	# enter real mode
     71 	.code16
     72 
     73 	movb	$0x0, %ah	# subfunction
     74 	int	$0x13
     75 	setc	%bl
     76 	movb	%ah, %bh	# save error code
     77 
     78 	calll	_C_LABEL(real_to_prot) # back to protected mode
     79 	.code32
     80 
     81 	movzwl	%bx, %eax	# return value in %eax
     82 	movl	%eax, 28(%esp)
     83 
     84 	popa
     85 	ret
     86 
     87 /*
     88  * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
     89  *	Call with	%ah = 0x2
     90  *			%al = number of sectors
     91  *			%ch = cylinder
     92  *			%cl = sector
     93  *			%dh = head
     94  *			%dl = drive (0x80 for hard disk, 0x0 for floppy disk)
     95  *			%es:%bx = segment:offset of buffer
     96  *	Return:
     97  *			%al = 0x0 on success; err code on failure
     98  *
     99  * biosdisk_read(dev, cyl, head, sect, count, buff_addr);
    100  *
    101  *  Note: On failure, you must reset the disk with biosdisk_reset() before
    102  *        sending another command.
    103  */
    104 ENTRY(biosdisk_read)
    105 	pusha
    106 
    107 	movb	44(%esp), %dh
    108 	movw	40(%esp), %cx
    109 	xchgb	%ch, %cl	# cylinder; the highest 2 bits of cyl is in %cl
    110 	rorb	$2, %cl
    111 	movb	48(%esp), %al
    112 	orb	%al, %cl
    113 	incb	%cl		# sector; sec starts from 1, not 0
    114 	movb	36(%esp), %dl	# device
    115 	movl	56(%esp), %ebx	# buffer address (may be >64k)
    116 	movb	52(%esp), %al	# number of sectors
    117 
    118 	call	_C_LABEL(prot_to_real)	# enter real mode
    119 	.code16
    120 
    121 	push	%bx
    122 	shrl	$4, %ebx	# max segment
    123 	mov	%ds, %si
    124 	add	%si, %bx
    125 	mov	%bx, %es	# %es:%bx now valid buffer address
    126 	pop	%bx
    127 	and	$0xf, %bx	# and min offset - to avoid overrun
    128 
    129 	movb	$0x2, %ah	# subfunction
    130 	int	$0x13
    131 	setc	%al		# error code is in %ah
    132 
    133 	calll	_C_LABEL(real_to_prot) # back to protected mode
    134 	.code32
    135 
    136 	andl    $0x0000FFFF, %eax  # Some bioses set high bits in %eax
    137 	                           #  on success, interfering with our
    138 	                           #  return value.  Clear those out.
    139 	movl	%eax, 28(%esp)
    140 
    141 	popa
    142 	ret
    143 
    144 /*
    145  * biosdisk_getinfo(int dev):  return a word that represents the
    146  *	max number of sectors, heads and cylinders for this device
    147  */
    148 ENTRY(biosdisk_getinfo)
    149 	push	%es
    150 	pusha
    151 
    152 	movb	%al, %dl		# diskinfo(drive #)
    153 
    154 	call	_C_LABEL(prot_to_real)	# enter real mode
    155 	.code16
    156 
    157 	push	%dx			# save drive #
    158 	movb	$0x08, %ah		# ask for disk info
    159 	int	$0x13
    160 	pop	%bx			# restore drive #
    161 	jnc	ok
    162 
    163 	testb	$0x80, %bl		# is it a hard disk?
    164 	jnz	ok
    165 
    166 	/*
    167 	 * Urk.  Call failed.  It is not supported for floppies by old BIOS's.
    168 	 * Guess it's a 15-sector floppy.  Initialize all the registers for
    169 	 * documentation, although we only need head and sector counts.
    170 	 */
    171 	xorw	%ax, %ax		# set status to success
    172 #	movb	%ah, %bh		# %bh = 0
    173 #	movb	$2, %bl			# %bl bits 0-3 = drive type, 2 = 1.2M
    174 	movb	$79, %ch		# max track
    175 	movb	$15, %cl		# max sector
    176 	movb	$1, %dh			# max head
    177 #	movb	$1, %dl			# # floppy drives installed
    178 	# es:di = parameter table
    179 	# carry = 0
    180 
    181 ok:
    182 	calll	_C_LABEL(real_to_prot)	# back to protected mode
    183 	.code32
    184 
    185 	/* form a longword representing all this gunk */
    186 	shrl	$8, %eax		# clear unnecessary bits
    187 	shll	$24, %eax
    188 	shll	$16, %ecx		# do the same for %ecx
    189 	shrl	$8, %ecx
    190 	movb	%dh, %cl		# max head
    191 	orl	%ecx, %eax		# return value in %eax
    192 	movl	%eax, 28(%esp)
    193 
    194 	popa
    195 	pop	%es
    196 	ret
    197 
    198 /*
    199  * int biosdisk_int13ext(int dev):
    200  *	check for availability of int13 extensions.
    201  */
    202 ENTRY(biosdisk_int13ext)
    203 	pusha
    204 
    205 	movb	%al, %dl		# drive #
    206 	movw	$0x55aa, %bx
    207 
    208 	call	_C_LABEL(prot_to_real)	# enter real mode
    209 	.code16
    210 
    211 	movb	$0x41, %ah		# ask for disk info
    212 	int	$0x13
    213 	setnc	%dl
    214 
    215 	calll	_C_LABEL(real_to_prot)	# switch back
    216 	.code32
    217 
    218 	movzbl	%dl, %eax		# return value in %eax
    219 
    220 	cmpw	$0xaa55, %bx
    221 	sete	%dl
    222 	andb	%dl, %al
    223 
    224 	andb	%cl, %al
    225 	movl	%eax, 28(%esp)
    226 
    227 	popa
    228 	ret
    229 
    230 /*
    231  * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
    232  *	Call with	%ah = 0x42
    233  *			%ds:%si = parameter block (data buffer address
    234  *				must be a real mode physical address).
    235  *			%dl = drive (0x80 for hard disk, 0x0 for floppy disk)
    236  *	Return:
    237  *			%al = 0x0 on success; err code on failure
    238  */
    239 ENTRY(biosdisk_extread)
    240 	pusha
    241 
    242 	movl	%edx, %esi	# parameter block
    243 	movb	%al, %dl	# device
    244 
    245 	call	_C_LABEL(prot_to_real)	# enter real mode
    246 	.code16
    247 
    248 	push	%ds
    249 	movl	%esi, %eax
    250 	shrl	$4, %eax
    251 	movw	%ds, %bx
    252 	addw	%bx, %ax
    253 	movw	%ax, %ds
    254 	andw	$0xf, %si
    255 
    256 	movb	$0x42, %ah	# subfunction
    257 	int	$0x13
    258 	setc	%bl
    259 	movb	%ah, %bh	# save error code
    260 	pop	%ds
    261 
    262 	calll	_C_LABEL(real_to_prot) # back to protected mode
    263 	.code32
    264 
    265 	movzwl	%bx, %eax	# return value in %eax
    266 	movl	%eax, 28(%esp)
    267 
    268 	popa
    269 	ret
    270 
    271 ENTRY(biosdisk_getextinfo)
    272 	pusha
    273 
    274 	movl	%edx, %esi	# parameter block
    275 	movb	%al, %dl	# device
    276 
    277 	call	_C_LABEL(prot_to_real)	# enter real mode
    278 	.code16
    279 
    280 	push	%ds
    281 	movl	%esi, %eax
    282 	shrl	$4, %eax
    283 	andw	$0xf, %si
    284 	movw	%ds, %bx
    285 	addw	%bx, %ax
    286 	movw	%ax, %ds
    287 
    288 	movb	$0x48, %ah	# subfunction
    289 	int	$0x13
    290 	setc	%bl
    291 	pop	%ds
    292 
    293 	calll	_C_LABEL(real_to_prot) # back to protected mode
    294 	.code32
    295 
    296 	movzbl	%bl, %eax	# return value in %eax
    297 	movl	%eax, 28(%esp)
    298 
    299 	popa
    300 	ret
    301