Код:
;------------------------------------------------
; NEMO драйвер HDD
;------------------------------------------------
.module nemo_drv
.area _CODE
; i:Status o:Command
P_CTRL = 0xF0 ;РЕГИСТР СОСТОЯНИЯ/РЕГИСТР КОМАНД
; io: Drive/Head / LBA24-27
P_LBA3 = 0xD0 ;CHS-НОМЕР ГОЛОВЫ И УСТР/LBA АДРЕС 24-27
; io: Cylinder High / LBA16-23
P_LBA2 = 0xB0 ;CHS-ЦИЛИНДР 8-15/LBA АДРЕС 16-23
; io: Cylinder Low / LBA8-15
P_LBA1 = 0x90 ;CHS-ЦИЛИНДР 0-7/LBA АДРЕС 8-15
; io: Sector Number / LBA0-7
P_LBA0 = 0x70 ;CHS-НОМЕР СЕКТОРА/LBA АДРЕС 0-7
; io: Sector Count
P_SECTCNT = 0x50 ;СЧЕТЧИК СЕКТОРОВ
; i:Error register o:Features
P_FUTERROR = 0x30 ;ПОРТ ОШИБОК/СВОЙСТВ
; io: Data register
P_DATAL = 0x10 ;ПОРТ ДАННЫХ (low)
P_DATAH = 0x11 ;СТАРШИЕ 8 БИТ (hi)
;
P_EXTCTL = 0xC8 ; Доп. РЕГИСТР СОСТОЯНИЯ/УПРАВЛЕНИЯ
;------------------------------------------------
; Error register mask
E_ABRT = 0x04 ; Последняя команда не выполнена (Aborted Command)
E_IDNF = 0x10 ; Сектор не найден (ID not Found)
E_UNC = 0x40 ; Некорректируемая ошибка данных (Uncorrectable Data Error)
E_BBK = 0x80 ; Ошибка CRC-кода или обнаружен сбойный блок (Bad Block Detected)
;------------------------------------------------
; Drive/Head format: 1m1dXXXX
; m - 0=CHS, 1=LBA
; d - 0=master, 1=slave
M_MASL =0x10
M_LBA =0x40
M_ADR =0x0F
M_CTL =0xA0
;------------------------------------------------
; Status mask
SM_BSY =0x80 ; =1 устройство занято
SM_DRDY =0x40 ; =1 устройство готово к приему команды
SM_DF =0x20 ; =1 индикатор ошибки устройства
SM_DSC =0x10 ; =1 Признак успешного позиционирования головки
SM_DRQ =0x08 ; =1 DRQ сообщает о том, что устройство готово к приему данных
SM_ERR =0x01 ; =1 во время выполнения последней команды произошла ошибка
; Дополнительная информация об ошибке находится в Error register.
;------------------------------------------------
CMD_ID =0xEC ; Identify Drive
CMD_RECAL =0x10 ; Recalibrate
CMD_RDS =0x20 ; Read Sector(s)
CMD_WRS =0x30 ; Write Sector(s)
;------------------------------------------------
; Ждать готовности устройства
; i: o: C=1 - таймаут, C=0, устройство готово
NO_BSY:
LD BC,#P_CTRL ; порт состояния
LD DE,#0x0000 ; тайм-аут (65536 циклов)
NO_BSY1:
in a,(c)
RLCA
RET NC ; выход - устройство готово, C=0
;
dec de
ld a,e
or d
jr NZ,NO_BSY1 ; ждём, таймаут не кончился
; Таймаут. C=1, устройство не готово
scf
ret
;------------------------------------------------
; Ожидание готовности к приёму данных
; io:
W_DRQ:
LD BC,#P_CTRL ; порт состояния
LD DE,#0x0000 ; тайм-аут (65536 циклов)
W_DRQ1:
in a,(c)
and #SM_DRQ
RET NZ ; выход - устройство готово, C=0
;
jr NZ,W_DRQ1
; Таймаут. C=1, устройство не готово
scf
ret
;------------------------------------------------
; Проверить на ошибку
; i: o: С=1 - ошибка, C=0 - всё ОК
;
ERR_: LD BC,#P_CTRL
in a,(c)
RRCA
; Если была ошибка - считать ее код
LD BC,#P_FUTERROR
in a,(c)
RET
;------------------------------------------------
;HDD Send Command.
;IN: [A] - код команды.
;OUT: CY - Операция выполнена с ошибкой.
;
HDSC:
LD BC,#P_CTRL
out (c),a ; послали команду.
CALL NO_BSY ; ждем выполнения.
RET C ; таймаут
JP ERR_ ; смотрим, нет ли ошибок.
;------------------------------------------------
;Чтение заданного количества секторов
; i: HL-адрес буфера, A-количество секторов
; o: С=1 - ошибка, C=0 - всё ОК
READ:
LD B,A
PUSH BC
LD BC,#P_SECTCNT
out (c),a
LD A,#CMD_RDS
CALL HDSC ;команда читать...
jr C,RWERR
POP BC
READ1:
PUSH BC
CALL W_DRQ
jr C,RWERR
LD BC,#P_DATAL ;Читаем сектор из (2 раза по 256 байт)
INIR
INIR
POP BC
DJNZ READ1
and a ; C=0
RET
;------------------------------------------------
; Выход их процедур чтения и записи секторов при ошибке
RWERR:
POP BC
RET
;------------------------------------------------
;Запись заданного количества секторов
; i: HL-адрес буфера, A-количество секторов
; o: С=1 - ошибка, C=0 - всё ОК
WRITE:
LD B,A
PUSH BC
LD BC,#P_SECTCNT
out (c),a
;
LD A,#CMD_WRS
CALL HDSC ;команда писать...
jr C,RWERR
POP BC
WRITE1:
PUSH BC
CALL W_DRQ
jr C,RWERR
LD BC,#P_DATAL ;Пишем сектор в (2 раза по 256 байт)
OTIR
OTIR
POP BC
DJNZ WRITE1
and a ; C=0
RET
;------------------------------------------------
; Интерфейс для С
;------------------------------------------------
; Чтение описателя диска
.globl _ID_HDD
_ID_HDD:
ld IX,#0002
add IX,sp
;
ld a,(IX) ; mode
;
ld l,1(ix)
ld h,2(ix) ; hl=buffer
; master or slave ?
or a
ld a,#(M_MASL + M_CTL + M_LBA)
jr nz,ID_HDD_SL
ld a,#(M_CTL + M_LBA)
ID_HDD_SL:
LD BC,#P_LBA3
out (c),a
; Команда - считать инфу о винте
LD A,#CMD_ID
CALL HDSC
; Читаем один сектор
ld b,#1
call READ1
ld l,#00
ret nc
ld l,#0xFF
ret
;------------------------------------------------
Для SMUC будет нечто подобное, я полагаю, только адреса портов другие.