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)
55 movl %eax,_biosdisk_drive
57 movl %eax,_biosdisk_head
59 movl %eax,_biosdisk_track
61 movl %eax,_biosdisk_sector
63 movl %eax,_biosdisk_nsects
65 movl %eax,_biosdisk_buffer
70 pushw %es // Save this just in case
71 movb $3,_biosdisk_retrycount // Set the retry count to 3
74 movl _biosdisk_buffer,%eax // Get buffer address in eax
75 shrl $4,%eax // Make linear address into segment
76 movw %ax,%es // Load ES with segment
77 movl _biosdisk_buffer,%ebx // and BX with offset
78 andl $0x0f,%ebx // so that data gets loaded to [ES:BX]
79 movb _biosdisk_sector,%cl // Get the sector in CL
80 movw _biosdisk_track,%ax // Cylinder in AX
81 movb %al,%ch // Now put it in CH
82 rorb $1,%ah // Low 8 bits of cylinder in CH, high 2 bits
83 rorb $1,%ah // in CL shifted to bits 6 & 7
84 andb $0xc0,%ah // Clear out low six bits
85 orb %ah,%cl // Or with sector number
86 movb _biosdisk_head,%dh // Get the head
87 movb _biosdisk_drive,%dl // Get the drive
88 movb $2,%ah // BIOS int 0x13, function 2 - Read Disk Sectors
89 movb _biosdisk_nsects,%al // Number of sectors to read
90 int $0x13 // Read a sector
92 // I have recently learned that not all bioses return
93 // the sector read count in the AL register (at least mine doesn't)
94 // even if the sectors were read correctly. So instead
95 // of checking the sector read count we will rely solely
96 // on the carry flag being set on error
99 //cmpb _biosdisk_nsects,%al // See how many sectors we actually read
100 //jne _biosdisk_error // Jump if no error
102 movb $1,%al // Set the return value to be one (will be set to zero later if needed)
103 jc _biosdisk_error // Jump if error (CF = 1 on error)
108 movb %ah,_biosdisk_error_code// Save the error code
110 cmpb $0x11,%ah // Check and see if it was a corrected ECC error
111 je _biosdisk_done // If so then the data is still good, if not fail
113 movb _biosdisk_retrycount,%al// Get the current retry count
114 decb %al // Decrement it
115 movb %al,_biosdisk_retrycount// Save it
116 cmpb $0,%al // Is it zero?
117 jz _biosdisk_zero // Yes, return zero
119 movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
120 movb _biosdisk_drive,%dl // Get the drive
121 int $0x13 // Reset the disk system
122 jmp _biosdisk_read // Try reading again
125 movb $0,%al // We will return zero
128 movzbl %al,%eax // Put the number of sectors read into EAX
129 movl %eax,_biosdisk_retval // Save it as the return value
131 popw %es // Restore ES
138 movl _biosdisk_retval,%eax // Get return value
144 * BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer);
146 _disk_address_packet:
151 _packet_sector_count:
153 _packet_transfer_buffer_offset:
155 _packet_transfer_buffer_segment:
157 _packet_lba_sector_number:
159 _packet_64bit_flat_address:
161 _int13_extended_drive:
163 _int13_extended_sector_count:
165 _int13_extended_retval:
167 _int13_extended_retrycount:
169 EXTERN(_BiosInt13ReadExtended)
176 movl %eax,_int13_extended_drive
178 movl %eax,_packet_lba_sector_number
180 movw %ax,_packet_sector_count
181 movl %eax,_int13_extended_sector_count
182 movl 0x30(%esp),%eax // Get buffer address in eax
183 shrl $4,%eax // Make linear address into segment
184 movw %ax,_packet_transfer_buffer_segment // Save segment
185 movl 0x34(%esp),%eax // Get buffer address in eax
186 andl $0x0f,%eax // Make linear address into offset
187 movw %ax,_packet_transfer_buffer_offset // Save offset
192 pushw %es // Save this just in case
193 movb $3,_int13_extended_retrycount // Set the retry count to 3
195 _int13_extended_read:
196 movb _int13_extended_drive,%dl // Get the drive
197 movb $0x42,%ah // BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
198 movw $_disk_address_packet,%si // DS:SI -> disk address packet
199 int $0x13 // Read sectors
201 jc _int13_extended_error // Jump if error (CF = 1 on error)
203 movl _int13_extended_sector_count,%eax // Get the sector count in eax
204 cmpw _packet_sector_count,%ax // See how many sectors we actually read (returned in disk address packet sector count)
205 jne _int13_extended_error // Jump if not equal
207 jmp _int13_extended_done
210 _int13_extended_error:
211 movb %ah,_biosdisk_error_code // Save the error code
213 cmpb $0x11,%ah // Check and see if it was a corrected ECC error
214 je _int13_extended_done // If so then the data is still good, if not fail
216 movb _int13_extended_retrycount,%al // Get the current retry count
217 decb %al // Decrement it
218 movb %al,_int13_extended_retrycount // Save it
219 cmpb $0,%al // Is it zero?
220 jz _int13_extended_zero // Yes, return zero
222 movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
223 movb _int13_extended_drive,%dl // Get the drive
224 int $0x13 // Reset the disk system
225 jmp _int13_extended_read // Try reading again
227 _int13_extended_zero:
228 movb $0,%al // We will return zero
230 _int13_extended_done:
231 movzbl %al,%eax // Put the number of sectors read into EAX
232 movl %eax,_int13_extended_retval // Save it as the return value
234 popw %es // Restore ES
241 movl _int13_extended_retval,%eax // Get return value
246 * BOOL BiosInt13ExtensionsSupported(ULONG Drive);
248 _int13_extension_check_drive:
250 _int13_extension_check_retval:
252 EXTERN(_BiosInt13ExtensionsSupported)
259 movl %eax,_int13_extension_check_drive
264 // Now make sure this computer supports extended reads
265 movb $0x41,%ah // AH = 41h
266 movw $0x55aa,%bx // BX = 55AAh
267 movb _int13_extension_check_drive,%dl // DL = drive (80h-FFh)
268 int $0x13 // IBM/MS INT 13 Extensions - INSTALLATION CHECK
269 jc _int13_extension_check_error // CF set on error (extensions not supported)
270 cmpw $0xaa55,%bx // BX = AA55h if installed
271 jne _int13_extension_check_error
272 testb $1,%cl // CX = API subset support bitmap
273 jz _int13_extension_check_error // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
275 // If we get here then we passed all the int13 extension tests
276 movl $1,_int13_extension_check_retval // Set return value to TRUE
277 jmp _int13_extension_check_done
279 _int13_extension_check_error:
281 movl $0,_int13_extension_check_retval // The tests failed so return FALSE
283 _int13_extension_check_done:
291 movl _int13_extension_check_retval,%eax // Get return value
296 * ULONG BiosInt13GetLastErrorCode(VOID);
298 EXTERN(_BiosInt13GetLastErrorCode)
301 movzbl _biosdisk_error_code,%eax // Get return value
307 * void StopFloppyMotor(void);
309 * Stops the floppy drive from spinning, so that other software is
310 * jumped to with a known state.
312 EXTERN(_StopFloppyMotor)
334 * int get_heads(int drive);
344 movl %eax,_biosdisk_drive
351 movb _biosdisk_drive,%dl
357 movl %edx,_biosdisk_retval
361 movl $0xff,_biosdisk_retval
372 movl _biosdisk_retval,%eax // Get return value
377 * int get_cylinders(int drive);
379 EXTERN(_get_cylinders)
387 movl %eax,_biosdisk_drive
394 movb _biosdisk_drive,%dl
396 jc _get_cylinders_error
404 movl %edx,_biosdisk_retval
405 jmp _get_cylinders_done
407 _get_cylinders_error:
408 movl $0xff,_biosdisk_retval
419 movl _biosdisk_retval,%eax // Get return value
424 * int get_sectors(int drive);
434 movl %eax,_biosdisk_drive
441 movb _biosdisk_drive,%dl
443 jc _get_sectors_error
447 movl %ecx,_biosdisk_retval
448 jmp _get_sectors_done
451 movl $0xff,_biosdisk_retval
462 movl _biosdisk_retval,%eax // Get return value
468 * BOOL BiosInt13GetDriveParameters(ULONG Drive, PGEOMETRY Geometry);
470 _bios_int13_cylinders:
476 _bios_int13_bytes_per_sector:
478 _bios_int13_drive_parameters_struct_address:
480 EXTERN(_BiosInt13GetDriveParameters)
488 movl %eax,_biosdisk_drive
490 movl %eax,_bios_int13_drive_parameters_struct_address
497 movb _biosdisk_drive,%dl
499 jc _BiosInt13GetDriveParameters_Error
504 movl %eax,_bios_int13_heads
510 movl %edx,_bios_int13_sectors
519 movl %edx,_bios_int13_cylinders
521 // Get the bytes per sector
522 movl $512,_bios_int13_bytes_per_sector // Just assume 512 bytes per sector
523 movl $0x01,_biosdisk_retval
524 jmp _BiosInt13GetDriveParameters_Done
526 _BiosInt13GetDriveParameters_Error:
527 movl $0x00,_biosdisk_retval
529 _BiosInt13GetDriveParameters_Done:
535 // Copy drive parameters to structure
536 movl $_bios_int13_cylinders,%esi
537 movl _bios_int13_drive_parameters_struct_address,%edi
545 movl _biosdisk_retval,%eax // Get return value