![]() |
|
:: СОДЕРЖАНИЕ НОМЕРА
:: Газетные рубрики
:: АВТОРЫ
:: Поиск
:: Поддержка проекта
Webmoney:
|
:: №32 (10.10.2009) Просмотров: 5654
![]() Автор: Александр Синяков / 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. Метод обкатан и работает, а вот в самой программе могут быть ошибки - я её писал по памяти, не проверяя. Если кого-то заинтересует, могу найти рабочие исходники. |