![]() |
:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №32 (10.10.2009) Просмотров: 5325
![]() Автор: Александр Синяков / SAM style. Рубрика: В помощь разработчику. Номер: №32 (10.10.2009). Автоопределение схемы IDE и подключенных устройствВ этой статье рассматривается автоматическое определение схемы IDE программным способом. На данный момент широкое распространение получили схемы Nemo (и её модификация Nemo-A8), ATM и SMUC. Наша задача - программно определить тип схемы и подключенные устройства (HDD, CD-ROM, DVD-ROM).Для начала, составим таблицу портов данных схем: Назначение порта SMUC ATM Nemo NemoA8 команда (in)/состояние (out) #FFBE #FEEF #FFF0 #FEF0 регистр головки, устройства, режима LBA #FEBE #FECF #FFD0 #FED0 цилиндр (старшая часть) #FDBE #FEAF #FFB0 #FEB0 цилиндр (младшая часть) #FCBE #FE8F #FF90 #FE90 сектор #FBBE #FE6F #FF70 #FE70 счётчик #FABE #FE4F #FF50 #FE50 регистр ошибки #F9BE #FE2F #FF30 #FE30 данные (старшая часть) #D8BE #FF0F #FF11 #FF10 данные (младшая часть) #F8BE #FE0F #FF10 #FE10 Стоит заметить, что SMUC и ATM используют для работы теневые порты, и для корректного чтения из портов нам необходимо знать адрес, по которому в TRDOS расположена пара команд: IN A,(C) RET Обозначим этот адрес TRD_IN_ADR. Работа с разными схемами подключения IDE различается лишь номерами портов, поэтому логично использовать одни и те же процедуры с различными входными параметрами. В рассматриваемой программе номера портов передаются через таблицу, на которую указывает регистр IX. Проверка на тип схемы и устройства производится по следующей схеме: 1. Выбираем устройство MASTER, проверяем его на занятость (бит 7 в регистре состояний) - если он занят - полагается, что его нет. Тогда также проверяем устройство SLAVE. - если занят и SLAVE - либо оба устройства не подключены, либо тестируемая схема проверку не прошла. 2. Записываем в регистры цилиндра 0 и даём команду #EC - идентификация винчестера - если команда принята без ошибок, то это винчестер. Необходимо считать в буфер 512 байт и проверить байт по смещению +256. Это делается, чтобы различить Nemo и Nemo-A8, если этот байт равен 255 - тест провален, иначе - прошёл успешно. - если команда выдала ошибку и в регистре цилиндра не содержится число #EB14, то тест провален (либо схема не та, либо устройство не опознано). - если команда выдала ошибку и регистр цилиндра равен #EB14, мы имеем дело с ATAPI-устройством (это может быть либо CDROM, либо DVDROM). В этом случае даём команду #A1 (аналог команды #EC для atapi) и считываем в буфер 2048 байт (?) и аналогично проверяем байт +1024 3. Если тест данной схемы провален, переходим на тест следующей схемы. (здесь возникли неувязочки, потому как при тесте в Unreal0.32b7 с DVD считалось только 512 байт, остальные были забиты значениями 255). Далее следует листинг программы. ide_detect ld ix,ide_tab ;IX - указатель на таблицу портов ide_next ld a,(ix) ;проверяем конец таблицы or (ix+1) jr z,no_ide ;если конец - подстановка «ложной таблицы» ld a,#a0 ;тестируем master call test_ide ld (master),a push af ld a,#b0 ;тестируем slave call test_ide ld (slave),a pop bc or b ret nz ;если хоть одно устройство ;определилось нормально - выход ld de,23 add ix,de jr ide_next no_ide ld ix,fake_ide ;когда все тесты провалены - ;подсовываем «ложный IDE» scf ret test_ide call out_head ;выбираем устройство (master/slave) call in_state ;устройство должно быть не занято! rla ld a,0 ret c ld de,0 ;регистр цилиндра = 0 call out_cylind ld a,#EC ;#EC - команда идентификации hdd call ide_command jr nc,hdd_detect ;если ошибки нет - это винчестер call in_cylind ;иначе проверяем регистр цилиндра ld hl,#EB14 ;если он не #EB14 - устройство не определено and a sbc hl,de ld a,h or l jr nz,test_fail ld a,#A1 ;#A1 - команда идентификации atapi call ide_command jr c,test_fail ld hl,bufer ;считываем в буфер 2048 байт ld bc,1024 call ide_read ld a,(bufer+1024) ;и проверяем байт +1024 на равенство 255 inc a jr z,test_fail ld a,2 ret hdd_detect ld hl,bufer ;для винчестера - считываем в буфер 512 байт ld bc,256 call ide_read ld a,(bufer+256) ;и проверяем +256 на равенство 255 inc a jr z,test_fail ld a,1 ret test_fail xor a ret ;Далее следует таблица портов IDE ;+0 comand/state ;+2 head ;+4 cyl.hi ;+6 cyl.low ;+8 sector ;+10 counter ;+12 error ;+14 data.hi ;+16 data.low ;+18 IN prog adr ;+20 OUT prog adr ;+22 sheme ID ide_tab dw #FFBE ;порты SMUC (см. таблицу выше) dw #FEBE dw #FDBE dw #FCBE dw #FBBE dw #FABE dw #F9BE dw #D8BE dw #F8BE dw shadow_in ;адреса чтения и записи в/из портов dw shadow_out db 1 ;идентификатор (для удобства) dw #FEEF ;порты ATM2+ dw #FECF dw #FEAF dw #FE8F dw #FE6F dw #FE4F dw #FE2F dw #FF0F dw #FE0F dw shadow_in dw shadow_out db 2 dw #FFF0 ;порты Nemo dw #FFD0 dw #FFB0 dw #FF90 dw #FF70 dw #FF50 dw #FF30 dw #FF11 dw #FF10 dw open_in dw open_out db 3 dw #FEF0 ;порты Nemo-A8 dw #FED0 dw #FEB0 dw #FE90 dw #FE70 dw #FE50 dw #FE30 dw #FF10 dw #FE10 dw open_in dw open_out db 4 fake_ide ds 18,#FF ;ложная таблица dw fake_in dw fake_out db 0 ide_command call out_com ;подать устройству команду call ide_busy ide_error call in_state rra ret nc call in_error scf ret ide_busy call in_state ;дождаться освобождения устройства rla jr c,ide_busy ret ide_read push bc ;считать bc слов на hl call in_data_l ;устройство должно быть готово к передаче ld (hl),a inc hl call in_data_h ld (hl),a inc hl pop bc dec bc ld a,b or c jr nz,ide_read ret out_cylind ld a,d ;вывод de в регистр цилиндра call out_cyl_h ld a,e jr out_cyl_l in_cylind call in_cyl_h ;чтение регистра цилиндра в de ld d,a call in_cyl_l ld e,a ret in_state ld c,(ix) ;подпрограммы чтения из регистров IDE ld b,(ix+1) jr in_bc in_head ld c,(ix+2) ld b,(ix+3) jr in_bc in_cyl_h ld c,(ix+4) ld b,(ix+5) jr in_bc in_cyl_l ld c,(ix+6) ld b,(ix+7) jr in_bc in_sector ld c,(ix+8) ld b,(ix+9) jr in_bc in_count ld c,(ix+10) ld b,(ix+11) jr in_bc in_error ld c,(ix+12) ld b,(ix+13) jr in_bc in_data_h ld c,(ix+14) ld b,(ix+15) jr in_bc in_data_l ld c,(ix+16) ld b,(ix+17) in_bc push hl ld l,(ix+18) ld h,(ix+19) ex (sp),hl ret out_com ld c,(ix) ;подпрограммы записи в регистры IDE ld b,(ix+1) jr out_bc out_head ld c,(ix+2) ld b,(ix+3) jr out_bc out_cyl_h ld c,(ix+4) ld b,(ix+5) jr out_bc out_cyl_l ld c,(ix+6) ld b,(ix+7) jr out_bc out_sector ld c,(ix+8) ld b,(ix+9) jr out_bc out_count ld c,(ix+10) ld b,(ix+11) jr out_bc out_error ld c,(ix+12) ld b,(ix+13) jr out_bc out_data_h ld c,(ix+14) ld b,(ix+15) jr out_bc out_data_l ld c,(ix+16) ld b,(ix+17) out_bc push hl ld l,(ix+20) ld h,(ix+21) ex (sp),hl ret open_in in a,(c) ;вывод/ввод для открытых портов ret open_out out (c),a ret shadow_in push hl ;вывод/ввод для закрытых портов ld hl,trd_in_adr jr to_dos shadow_out push hl ld hl,10835 to_dos ex (sp),hl jp 15663 fake_in ld a,#FF fake_out ret master db 0 slave db 0 bufer ds 2048 После вызова ide_detect регистр IX будет указывать на таблицу портов определённой схемы IDE (или на ложную таблицу). В ячейке (IX+22) содержится идентификатор схемы. После этого можно использовать подпрограммы записи/чтения в/из портов, не заботясь о том, какая схема подключена (и подключена ли). Но перед этим необходимо записывать в IX адрес таблицы, который нам выдала программа. P.S. Метод обкатан и работает, а вот в самой программе могут быть ошибки - я её писал по памяти, не проверяя. Если кого-то заинтересует, могу найти рабочие исходники. |