По поводу получения параметров диска была тема:
http://forum.vingrad.ru/index.php?showtopic=20370
(ты же спрашивал - ?)
Насчет того, что у тебя "полный бред" в количестве головок и тд так это очень может быть и не бред, а связано с тем, что давно-давно, когда винты были по 40 мегабайт, количество секторов и тп вполне вмещалось в отведенные ячейки памяти. Сейчас же все стало иначе, поэтому стали делать "нереальное" число головок и тп. Посмотри мой исходник - он же на эту тему: я как раз читал сектора, опираясь на инфу из int 41h:
| Цитата | push offset MyHardDiskParams call GetHard80h_Info_by_INT41 ; Получить инфу по int 41h push offset MyLogDiskStruc call GetHard80h_Info_by_MBR ; Прочтя MBR
; Вычислить номер головки
mov ax,MyLogDiskStruc.LastCylSec push ax and al,00111111b mov byte ptr CurrSect,al pop ax and al,11000000b xchg al,ah shr ah,6 mov dh,MyLogDiskStruc.LastHead ; push dx and dh,11000000b or ah,dh mov word ptr CurrCyl,ax pop dx and dh,00111111b mov byte ptr CurrHead,dh
...
; Сравнить с тем, что дал нам int 41h
mov al,byte ptr CurrHead cmp al,byte ptr MyHardDiskParams.Heads jb @@UseTheseCylHead
|
В си можно все делать неплохо, опираясь на стандартные средства (вроде):
| Цитата |
struct { unsigned int number_of_cylinders; unsigned char number_of_heads; unsigned int starting_reduced_write_current_cylinder; unsigned int starting_write_precompensation_cylinder_number; unsigned char maximum_ECC_burst_length; unsigned char control_byte; unsigned char standard_timeout; unsigned char formatting_timeout; unsigned char timeout_for_checking_drive; unsigned int cylinder_number_of_landing_zone; unsigned char number_of_sectors_per_track; unsigned char reserved; } tHDTP;
asm { mov ax, 0x3541 int 0x21 mov ax, es:[bx].number_of_cylinders mov cyl,ax mov al, es:[bx].number_of_heads }
// Или так - я си не знаю:
#define tPtrtHDTP= *tHDTP // Типа того tPtrtHDTP PtrtHDTP; tHDTP HDTP;
asm { mov ax, 0x3541 int 0x21 mov word ptr ds:PtrtHDTP,bx mov word ptr ds:PtrtHDTP+2,es }
memcpy(&HDTP,(char *)PtrtHDTP,sizeof(tHDTP));
printf("number_of_heads:%02x",HDTP.number_of_heads);
|
А делал я это вот зачем (моя неопубликованная "статья"):
| Цитата | Данный док о том, как не надо читать сектора.
Итак, как гласит документация(Ральф Браун), при чтении сектора(ов) мы должны задать BIOS следующие параметры:
| Цитата | INT 13 - DISK - READ SECTOR(S) INTO MEMORY AH = 02h AL = number of sectors to read (must be nonzero) CH = low eight bits of cylinder number CL = sector number 1-63 (bits 0-5) high two bits of cylinder (bits 6-7, hard disk only) DH = head number DL = drive number (bit 7 set for hard disk) ES:BX -> data buffer Return: CF set on error if AH = 11h (corrected ECC error), AL = burst length CF clear if successful AH = status (see #0144) AL = number of sectors transferred (only valid if CF set for some BIOSes) Notes: errors on a floppy may be due to the motor failing to spin up quickly enough; the read should be retried at least three times, resetting the disk with AH=00h between attempts most BIOSes support "multitrack" reads, where the value in AL exceeds the number of sectors remaining on the track, in which case any additional sectors are read beginning at sector 1 on the following head in the same cylinder; the CONFIG.SYS command MULTITRACK can be used to force DOS to split disk accesses which would wrap across a track boundary into two separate calls the IBM AT BIOS and many other BIOSes use only the low four bits of DH (head number) since the WD-1003 controller which is the standard AT controller (and the controller that IDE emulates) only supports 16 heads AWARD AT BIOS and AMI 386sx BIOS have been extended to handle more than 1024 cylinders by placing bits 10 and 11 of the cylinder number into bits 6 and 7 of DH under Windows95, a volume must be locked (see INT 21/AX=440Dh/CX=084Bh) in order to perform direct accesses such as INT 13h reads and writes SeeAlso: AH=03h,AH=0Ah,AH=06h"V10DISK.SYS",AH=21h"PS/1",AH=42h"IBM" SeeAlso: INT 21/AX=440Dh/CX=084Bh,INT 4D/AH=02h
|
Откуда видно, что для задания начального сектора для чтения необходимы три параметра:
- Головка(Head); - Дорожка или Цилиндр (Cylinder); - Номер сектора на дорожке(цилиндре ?) - Sector.
Из описания ф-ции 2 прерывания int 13h видно, что делатется это следующим образом:
Регистр CX Биты/Назначение 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 C C C C C C C C C C S S S S S S
Регистр DH Биты/Назначение 7 6 5 4 3 2 1 0 C C H H H H H H
C - сокращение от Cylinder, S - сокращение от Sector, H - сокращение от Head.
Мой диск (параметры взяты из Setup BIOS и они идентичны содержимому таблицы, адрес которой хранит вектор int 41h) содержит следующие параметры:
BIOS AWARD ROM PCI/ISA Primary Master TYPE SIZE CYLS HEAD PRECOMP LANDZ SECTOR MOD User 1207 585 64 0 2339 63 LBA
Итак, у меня диск объемом ~1207 МБайт. Как же соотносится эта величина с количеством секторов, цилиндров и головок ? Раз тут подразумевается, что указываются МАКСИМАЛЬНЫЕ значения (а что еще ?), то несложное перемножение должно нам дать показанный объем:
HEAD * CYLS * SECTOR * (512байт в МБайтах) ~= 1207МБайт ?
512 байт - размер в байтах одного сектора. В мегабайтах это будет: Размер сектора в МБайтах = 512/1МБайт = 200h/100000h = 1/2048 МБайт.
HEAD * CYLS * SECTOR * (512байт в МБайтах) ~= 64 * 585 * 63 * 1/2048 ~= ~= 1152 МБайт < 1207 МБайт ?
Итак, декларированное BIOS и поддерживаемое программным интерфейсом (содержимое вектора int 41h) число CYLS, HEAD и SECTOR не дает нам полного объема диска ? Куда же девались эти 1207- 1152 = 55 МБайт ?! ... Выполним последовательное чтение сектора номер 1 с цилиндра 584(максимальный номер) на разных Head:
Cylinder = 584 Head (биты 0-5 в регистре DH) 0 Сектор прочитан 30 Сектор прочитан 63 Сектор прочитан
Пока все нормально, в пределах декларированных BIOS параметров. Предположим, что реальное число цилиндров больше декларированного. Тогда чтение с цилиндров 585.. может дать нам дополнительные(недостающие) сектора:
Cylinder = 585 Head (биты 0-6 в регистре DH) 0 Сектор не прочитан 30 Сектор не прочитан 63 Сектор не прочитан
Номер ошибки - 0Ah:
| Цитата | Ральф Браун: 0Ah bad sector detected (hard disk)
|
Итак, номер цилиндра не может превышать установленного в BIOS. Однако обратим внимание вот на этот комментарий к ф-ции чтения сектора:
| Цитата | AWARD AT BIOS and AMI 386sx BIOS have been extended to handle more than 1024 cylinders by placing bits 10 and 11 of the cylinder number into bits 6 and 7 of DH
|
Ага, тут говриться, что номер цилиндра, если цилиндров > 1024 (номер не может быть размещен в битах 8-15 и 6-7 регистра CX), помещается также в биты 6-7 регистра DH.
Или вот еще цитата(http://www.citforum.ru/pp/pc03_09.shtml):
| Цитата | ...Также, в силу исторических причин, многие операционные системы, работающие с накопителями на ЖМД через BIOS, разработаны таким образом, что не могут оперировать числом цилиндров более 1024. Поскольку в настоящее время, накопители больших объемов (более 1Мб) имеют более 1024 физических цилиндра, то применяется программный пересчет, при котором, накопитель определяется его контроллером и процедурами BIOS как имеющий не более 1024 цилиндра, но имеющий некоторое нереальное число головок, поверхностей и секторов. Функция же пересчета для отыскания нужного сектора ложится либо на BIOS ПК, либо на BIOS контроллера, либо на интерфейс.
|
Выполним последовательное чтение сектора номер 1 с цилиндра 584(максимальный номер) на разных Head:
Cylinder = 584 Head Low/High (биты 0-5 в регистре DH/биты 6-7 в регистре DH) = содержимое DH 0/1 = 40h Сектор не прочитан 30/1 = 5Eh Сектор не прочитан 63/1 = 7Fh Сектор не прочитан
Ошибка прежняя - 0Ah.
Итак, получается в некотром роде странная сиуация: мы должны "растянуть" число битов, отводимое под номер цилиндра(по Ральфу Брауну), чтобы правильно описывать большие диски. Но чтение даже с CYLS+1 цилиндра приводит к ошибке. Т.е. "цилиндров" у нас по прежнему не более CYLS. Первая попытка увеличить число головок до 65 к успеху не привела. Может быть, на этих "дополнительных" головках не CYLS цилиндров, а меньше ?! Проверим это таким чтением:
Cylinder = 1 Head Low/High (биты 0-5 в регистре DH/биты 6-7 в регистре DH) = содержимое DH 0/1 = 40h Сектор прочитан ! Cylinder = 584 Head Low/High (биты 0-5 в регистре DH/биты 6-7 в регистре DH) = содержимое DH 0/1 = 40h Сектор не прочитан !
Очень интересно ! А на сколько меньше ? Попробуем увеличивать номер цилиндра для этой головки:
Head Low/High: 0/1 = 40h Cylinder 1 Сектор прочитан 100 Сектор прочитан 200 Сектор прочитан 300 Сектор прочитан 583 Сектор прочитан 584 Сектор не прочитан ! ... Та же самая картина и для Head-Low 30 и 63 - последний доступный цилиндр 583.
А какое максимальное число цилиндров можно задавать для Head-High = 2 и 3 ? Т.е. если DH=10??????b и DH=11??????b. Повторим предидущий опыт для этих значений и вот что оказалось:
Для Head-High = 2 - 582 цилиндра, для Head-High = 3 - 581 цилиндр.
Итак, если мы зададим в битах 6 и 7 регистра DH ненулевые значения, то максимально доступный номер цилиндра станет 584-DH-High вместо 584.
Может быть, задавая в битах 6 и 7 регистра DH дополнительную информацию, мы просто по-иному задаем какой-либо сектор, доступный обычным способом (без установки этих бит) ? Это легко проверить. Прочтем какой-нибудь сектор, установив один или оба этих бита в 1, а потом прочтем все возможные сектора, доступные нам без установки этого бита, при этом будем сравнивать с ними исходный сектор. Очевидно, нам нужно перебрать все комбинации значения головок в диапазоне 0..HEAD-1, а цилиндров - 0..CYLS-1, что составляет в случае моего винта 0..63 для головок и 0..584 для цилиндров. Вот результат этого опыта:
Начальный сектор Совпавший с ним сектор DH-High/Low Cyl Sect DH Cyl Sect 1/0 0 1 0 1 1 2/0 0 1 0 2 1 3/0 0 1 0 3 1 3/1 0 1 1 3 1 3/63 0 1 63 3 1 1/0 1 1 0 2 1 1/0 2 1 0 3 1 1/0 3 1 0 4 1 2/0 1 1 0 3 1 1/0 255 1 0 256 1 1/3 255 63 3 256 63 2/3 255 63 3 257 63 3/3 255 63 3 258 63
Получается, что в случае Cyl = 0 DH-high как бы просто складывается с номером цилиндра ! И в результате заполнение DH-High - это просто иной способ чтения секторов, доступных в обычном режиме ? Как же в таком случае все же прочесть недостающие 50 Мегабайт ?!
А оказалось все ГОРАЗДО проще: просто объем диска дается в БАЙТАХ:
585 цилиндров x 64 головки x 63 сектора x 512 байт в секторе = 1 207 664 640 байт ! ;)
Вот и все.
|
|