3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * BOOL BiosInt13Read(ULONG Drive, ULONG Head, ULONG Track, ULONG Sector, ULONG SectorCount, PVOID Buffer);
48 EXTERN(_BiosInt13Read)
60 movl %eax,_biosdisk_drive
62 movl %eax,_biosdisk_head
64 movl %eax,_biosdisk_track
66 movl %eax,_biosdisk_sector
68 movl %eax,_biosdisk_nsects
70 movl %eax,_biosdisk_buffer
75 pushw %es // Save this just in case
76 movb $3,_biosdisk_retrycount // Set the retry count to 3
79 movl _biosdisk_buffer,%eax // Get buffer address in eax
80 shrl $4,%eax // Make linear address into segment
81 movw %ax,%es // Load ES with segment
82 movl _biosdisk_buffer,%ebx // and BX with offset
83 andl $0x0f,%ebx // so that data gets loaded to [ES:BX]
84 movb _biosdisk_sector,%cl // Get the sector in CL
85 movw _biosdisk_track,%ax // Cylinder in AX
86 movb %al,%ch // Now put it in CH
87 rorb $1,%ah // Low 8 bits of cylinder in CH, high 2 bits
88 rorb $1,%ah // in CL shifted to bits 6 & 7
89 andb $0xc0,%ah // Clear out low six bits
90 orb %ah,%cl // Or with sector number
91 movb _biosdisk_head,%dh // Get the head
92 movb _biosdisk_drive,%dl // Get the drive
93 movb $2,%ah // BIOS int 0x13, function 2 - Read Disk Sectors
94 movb _biosdisk_nsects,%al // Number of sectors to read
95 int $0x13 // Read a sector
97 // I have recently learned that not all bioses return
98 // the sector read count in the AL register (at least mine doesn't)
99 // even if the sectors were read correctly. So instead
100 // of checking the sector read count we will rely solely
101 // on the carry flag being set on error
104 //cmpb _biosdisk_nsects,%al // See how many sectors we actually read
105 //jne _biosdisk_error // Jump if no error
107 movb $1,%al // Set the return value to be one (will be set to zero later if needed)
108 jc _biosdisk_error // Jump if error (CF = 1 on error)
113 movb %ah,_biosdisk_error_code// Save the error code
115 cmpb $0x11,%ah // Check and see if it was a corrected ECC error
116 je _biosdisk_done // If so then the data is still good, if not fail
118 movb _biosdisk_retrycount,%al// Get the current retry count
119 decb %al // Decrement it
120 movb %al,_biosdisk_retrycount// Save it
121 cmpb $0,%al // Is it zero?
122 jz _biosdisk_zero // Yes, return zero
124 movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
125 movb _biosdisk_drive,%dl // Get the drive
126 int $0x13 // Reset the disk system
127 jmp _biosdisk_read // Try reading again
130 movb $0,%al // We will return zero
133 movzbl %al,%eax // Put the number of sectors read into EAX
134 movl %eax,_biosdisk_retval // Save it as the return value
136 popw %es // Restore ES
141 movl _biosdisk_retval,%eax // Get return value
153 * BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer);
155 _disk_address_packet:
160 _packet_sector_count:
162 _packet_transfer_buffer_segment:
164 _packet_transfer_buffer_offset:
166 _packet_lba_sector_number:
168 _packet_64bit_flat_address:
170 _int13_extended_drive:
172 _int13_extended_sector_count:
174 _int13_extended_retval:
176 _int13_extended_retrycount:
178 EXTERN(_BiosInt13ReadExtended)
190 movl %eax,_int13_extended_drive
192 movl %eax,_packet_lba_sector_number
194 movw %ax,_packet_sector_count
195 movl %eax,_int13_extended_sector_count
196 movl 0x28(%esp),%eax // Get buffer address in eax
197 shrl $4,%eax // Make linear address into segment
198 movw %ax,_packet_transfer_buffer_segment // Save segment
199 movl 0x28(%esp),%eax // Get buffer address in eax
200 andl $0x0f,%eax // Make linear address into offset
201 movw %ax,_packet_transfer_buffer_offset // Save offset
206 pushw %es // Save this just in case
207 movb $3,_int13_extended_retrycount // Set the retry count to 3
209 _int13_extended_read:
210 movb _int13_extended_drive,%dl // Get the drive
211 movb $42,%ah // BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
212 movw $_disk_address_packet,%si // DS:SI -> disk address packet
213 int $0x13 // Read sectors
215 movb $1,%al // Set the return value to be one (will be set to zero later if needed)
216 jc _int13_extended_error // Jump if error (CF = 1 on error)
218 movl _int13_extended_sector_count,%eax // Get the sector count in eax
219 cmpw _packet_sector_count,%ax // See how many sectors we actually read (returned in disk address packet sector count)
220 jne _int13_extended_error // Jump if not equal
222 jmp _int13_extended_done
225 _int13_extended_error:
226 movb %ah,_biosdisk_error_code // Save the error code
228 cmpb $0x11,%ah // Check and see if it was a corrected ECC error
229 je _int13_extended_done // If so then the data is still good, if not fail
231 movb _int13_extended_retrycount,%al // Get the current retry count
232 decb %al // Decrement it
233 movb %al,_int13_extended_retrycount // Save it
234 cmpb $0,%al // Is it zero?
235 jz _int13_extended_zero // Yes, return zero
237 movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
238 movb _int13_extended_drive,%dl // Get the drive
239 int $0x13 // Reset the disk system
240 jmp _int13_extended_read // Try reading again
242 _int13_extended_zero:
243 movb $0,%al // We will return zero
245 _int13_extended_done:
246 movzbl %al,%eax // Put the number of sectors read into EAX
247 movl %eax,_int13_extended_retval // Save it as the return value
249 popw %es // Restore ES
254 movl _int13_extended_retval,%eax // Get return value
266 * BOOL BiosInt13ExtensionsSupported(ULONG Drive);
268 _int13_extension_check_drive:
270 _int13_extension_check_retval:
272 EXTERN(_BiosInt13ExtensionsSupported)
284 movl %eax,_int13_extension_check_drive
289 // Now make sure this computer supports extended reads
290 movb $0x41,%ah // AH = 41h
291 movw $0x55aa,%bx // BX = 55AAh
292 movb _int13_extension_check_drive,%dl // DL = drive (80h-FFh)
293 int $0x13 // IBM/MS INT 13 Extensions - INSTALLATION CHECK
294 jc _int13_extension_check_error // CF set on error (extensions not supported)
295 cmpw $0x55aa,%bx // BX = AA55h if installed
296 jne _int13_extension_check_error
297 testb $1,%cl // CX = API subset support bitmap
298 jz _int13_extension_check_error // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
300 // If we get here then we passed all the int13 extension tests
301 movl $1,_int13_extension_check_retval // Set return value to TRUE
302 jmp _int13_extension_check_done
304 _int13_extension_check_error:
306 movl $0,_int13_extension_check_retval // The tests failed so return FALSE
308 _int13_extension_check_done:
314 movl _int13_extension_check_retval,%eax // Get return value
325 * ULONG BiosInt13GetLastErrorCode(VOID);
327 EXTERN(_BiosInt13GetLastErrorCode)
330 movzbl _biosdisk_error_code,%eax // Get return value
336 * void stop_floppy(void);
338 * Stops the floppy drive from spinning, so that other software is
339 * jumped to with a known state.
364 * int get_heads(int drive);
377 movl %eax,_biosdisk_drive
384 movb _biosdisk_drive,%dl
390 movl %edx,_biosdisk_retval
394 movl $0xff,_biosdisk_retval
402 movl _biosdisk_retval,%eax // Get return value
413 * int get_cylinders(int drive);
415 EXTERN(_get_cylinders)
426 movl %eax,_biosdisk_drive
433 movb _biosdisk_drive,%dl
435 jc _get_cylinders_error
443 movl %edx,_biosdisk_retval
444 jmp _get_cylinders_done
446 _get_cylinders_error:
447 movl $0xff,_biosdisk_retval
455 movl _biosdisk_retval,%eax // Get return value
466 * int get_sectors(int drive);
479 movl %eax,_biosdisk_drive
486 movb _biosdisk_drive,%dl
488 jc _get_sectors_error
492 movl %ecx,_biosdisk_retval
493 jmp _get_sectors_done
496 movl $0xff,_biosdisk_retval
504 movl _biosdisk_retval,%eax // Get return value