Introduce biosdiskreset(), and call it to reset the disk (with Int

0x13 Function 0) after a read error. This is a requirement mentioned
in most BIOS documentation.

This answers PR 18591.

Incidentally, on the Soekris Engineering net45x1 single-board
computer, this fixes a bug where the bootloader corrupts the kernel
while loading it from certain varieties of CompactFlash card
(especially varieties identified by NetBSD as <TOSHIBA THNCF064MBA>).
This commit is contained in:
dyoung 2002-10-10 18:52:42 +00:00
parent 5ad5ca60a5
commit e57ba8d648
2 changed files with 47 additions and 4 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: bios_disk.S,v 1.8 2000/05/21 16:59:28 perry Exp $ */
/* $NetBSD: bios_disk.S,v 1.9 2002/10/10 18:52:42 dyoung Exp $ */
/*
* Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
@ -58,6 +58,41 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define addr32 .byte 0x67
#define data32 .byte 0x66
/*
# BIOS call "INT 0x13 Function 0x0" to reset the disk subsystem
# Call with %ah = 0x0
# %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
# Return:
# %al = 0x0 on success; err code on failure
*/
ENTRY(biosdiskreset)
pushl %ebp
movl %esp, %ebp
pushl %ebx
push %edx
push %edi
movb 8(%ebp), %dl # device
call _C_LABEL(prot_to_real) # enter real mode
movb $0x0, %ah # subfunction
int $0x13
setc %bl
movb %ah, %bh # save error code
data32
call _C_LABEL(real_to_prot) # back to protected mode
xorl %eax, %eax
movw %bx, %ax # return value in %ax
pop %edi
pop %edx
popl %ebx
popl %ebp
ret
/*
# BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
# Call with %ah = 0x2
@ -69,6 +104,9 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# %es:%bx = segment:offset of buffer
# Return:
# %al = 0x0 on success; err code on failure
#
# Note: On failure, you must reset the disk with biosdiskreset() before
# sending another command.
*/
ENTRY(biosread)
pushl %ebp

View File

@ -1,4 +1,4 @@
/* $NetBSD: biosdisk_ll.c,v 1.11 2001/07/07 22:57:57 perry Exp $ */
/* $NetBSD: biosdisk_ll.c,v 1.12 2002/10/10 18:52:42 dyoung Exp $ */
/*
* Copyright (c) 1996
@ -50,6 +50,7 @@ extern long ourseg;
extern int get_diskinfo __P((int));
extern void int13_getextinfo __P((int, struct biosdisk_ext13info *));
extern int int13_extension __P((int));
extern int biosdiskreset __P((int));
extern int biosread __P((int, int, int, int, int, char *));
extern int biosextread __P((int, void *));
static int do_read __P((struct biosdisk_ll *, int, int, char *));
@ -130,8 +131,10 @@ do_read(d, dblk, num, buf)
ext.seg = ourseg;
ext.sec = dblk;
if (biosextread(d->dev, &ext))
if (biosextread(d->dev, &ext)) {
(void)biosdiskreset(d->dev);
return -1;
}
return ext.cnt;
} else {
@ -144,8 +147,10 @@ do_read(d, dblk, num, buf)
if (nsec > num)
nsec = num;
if (biosread(d->dev, cyl, head, sec, nsec, buf))
if (biosread(d->dev, cyl, head, sec, nsec, buf)) {
(void)biosdiskreset(d->dev);
return -1;
}
return nsec;
}