Login

Subversion Repositories NedoOS

Rev

Rev 55 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

MODULE SAVELIJ  ;15950
  PUBLIC disk_initialize
  PUBLIC disk_read
  PUBLIC disk_write
  PUBLIC disk_status
  EXTERN dio_par
 
  RSEG NEAR_Z

  RSEG CODE
               
ds_m:
        DEFB 1,1,1,1
               
disk_status:
        ld d,0
        ld hl,ds_m
        add hl,de
        ld a,(hl)
                ret
               
disk_initialize:
                call disk_status
        or a
        ret z
        ld h,b
        ld l,c
        LD A,e
        or a
        jr nz,di_l1
        call zsd_init
        ld (ds_m),a
        ret
di_l1   dec a
        jr nz,di_l2
        ld a,0xe0
        call nemo_init
        ld (ds_m+1),a
        ret
di_l2   dec a
        jr nz,di_l3
        ld a,0xf0
        call nemo_init
        ld (ds_m+2),a
        ret
di_l3   dec a
        jr nz,di_l4
        call GSDINIT
        ld (ds_m+3),a
        ret
di_l4   ld a,1
        ret

       
get_params
        ld hl,(dio_par+3)
        ld e,(hl)
        inc hl
        ld d,(hl)
        inc hl
        ld c,(hl)
        inc hl
        ld b,(hl)
        ld hl,(dio_par+1)
        ld a,(dio_par+5)
        ex af,af
        ld a,(dio_par)
        or a
        ret
       
disk_read:
        call get_params
        jp z,zsd_read
        dec a
        jr nz,disk_read_nomaster
        ld a,$e0
        jp nemo_read
disk_read_nomaster
        dec a
        jr nz,disk_read_nonemo
        ld a,$f0
        jp nemo_read
disk_read_nonemo
        dec a
        jp z,SDRDMUL
        ld a,1
        ret
       
disk_write:
        call get_params
        jp z,zsd_write
        dec a
        jr nz,disk_write_nomaster
        ld a,$e0
        jp nemo_write
disk_write_nomaster
        dec a
        jr nz,disk_write_nonemo
        ld a,$f0
        jp nemo_write
disk_write_nonemo
        dec a
        jp z,SDWRMUL
        ld a,1
        ret
;Входные параметры общие:
;HL-адрес загрузки в память
;BCDE-32-х битный номер сектора
;A-количество блоков (блок=512 байт)
;только для многоблочной записи/чтении

P_1F7   EQU 0xF0                        ;РЕГИСТР СОСТОЯНИЯ/РЕГИСТР КОМАНД
P_1F6   EQU 0xD0                        ;CHS-НОМЕР ГОЛОВЫ И УСТР/LBA АДРЕС 24-27
P_1F5   EQU 0xB0                        ;CHS-ЦИЛИНДР 8-15/LBA АДРЕС 16-23
P_1F4   EQU 0x90                        ;CHS-ЦИЛИНДР 0-7/LBA АДРЕС 8-15
P_1F3   EQU 0x70                        ;CHS-НОМЕР СЕКТОРА/LBA АДРЕС 0-7
P_1F2   EQU 0x50                        ;СЧЕТЧИК СЕКТОРОВ
P_1F1   EQU 0x30                        ;ПОРТ ОШИБОК/СВОЙСТВ
P_1F0   EQU 0x10                        ;ПОРТ ДАННЫХ
P_3F6   EQU 0xC8                        ;РЕГИСТР СОСТОЯНИЯ/УПРАВЛЕНИЯ
P_HI    EQU 0x11                        ;СТАРШИЕ 8 БИТ
PRT_RW  EQU P_1F0*256+P_HI      ;ПОРТЫ ЧТЕНИЯ/ЗАПИСИ ОДНИМ СЛОВОМ

;НА ВЫХОДЕ:
;H-ДЛЯ MASTER 0-HDD, 1-CDROM, 0xFF-NONE
;L-ДЛЯ SLAVE  0-HDD, 1-CDROM, 0xFF-NONE
nemo_init:
                PUSH HL
                CALL ID_DEV
                POP HL
                AND A
                CALL Z,INIT_91
nemo_off:
                RET

INIT_91:
                PUSH HL
                ld d,h
                ld e,l
                LD hl,49*2+1
                add hl,de
                LD A,(HL)
                AND 2
                JR Z,INI_912
                LD BC,0xFF00+P_1F2
                LD hl,0x0C
                add hl,de
                LD A,(HL)
                OUT (C),A
                LD hl,6
                LD C,P_1F6
                add hl,de
                LD A,(HL)
                DEC A
                OUT (C),A
                LD C,P_1F7
                LD A,0x91
                OUT (C),A
                LD DE,0x1000
INI_911:
                DEC DE
                LD A,D
                OR E
                JR Z,INI_912
                IN A,(C)
                AND 0x80
                JR NZ,INI_911
                POP HL
                RET

INI_912:
                LD A,0xFF
                POP HL
                RET

;READ "A" SECTORS HDD
nemo_read:        
                add a,b
                ld b,a
                CALL SETHREG
                EX AF,AF
                LD C,0xf0
                LD A,0x20
                OUT (C),A
                LD C,0xf0
HDDRD1:
                IN A,(C)
                AND 0x88
                CP 8
                JR NZ,HDDRD1
                EX AF,AF
HDDRD2:
                EX AF,AF
                CALL READSEC
                LD C,0xf0
HDDRD3:
                IN A,(C)
                AND 0x80
                JR NZ,HDDRD3
                EX AF,AF
                DEC A
                JR NZ,HDDRD2
                JR EXITNHD

;WRITE "A" SECTORS HDD
nemo_write:
                add a,b
                ld b,a
                CALL SETHREG
                EX AF,AF
                LD C,P_1F7
                LD A,0x30
                OUT (C),A
                LD C,P_1F7
HDDWR1:
                IN A,(C)
                AND 0x88
                CP 8
                JR NZ,HDDWR1
                EX AF,AF
HDDWR2:
               
                EX AF,AF
                CALL WRITSEC
                inc h
                inc h
                LD C,P_1F7
HDDWR3:
                IN A,(C)
                AND 0x80
                JR NZ,HDDWR3
                EX AF,AF
                DEC A
                JR NZ,HDDWR2
EXITNHD:
                ld a,0
                RET

;READ SECTOR (512 BYTES)
READSEC:
                LD A,0x40
                LD C,P_1F0      ;HI
READSC1:
                IN E,(C)
                INC C
                IN D,(C)
                DEC C
                LD (HL),E
                INC HL
                LD (HL),D
                INC HL
                IN E,(C)
                INC C
                IN D,(C)
                DEC C
                LD (HL),E
                INC HL
                LD (HL),D
                INC HL
                IN E,(C)
                INC C
                IN D,(C)
                DEC C
                LD (HL),E
                INC HL
                LD (HL),D
                INC HL
                IN E,(C)
                INC C
                IN D,(C)
                DEC C
                LD (HL),E
                INC HL
                LD (HL),D
                INC HL
                DEC A
                JR NZ,READSC1
                RET

;SAVE SECTOR (512 BYTES)
WRITSEC:
                PUSH HL
                LD (WR_SEC_SP+1),SP
                LD SP,HL
                LD A,0x40
                LD HL,PRT_RW
WR_SEC1:
                POP DE
                LD C,L
                OUT (C),D
                LD C,H
                OUT (C),E
                POP DE
                LD C,L
                OUT (C),D
                LD C,H
                OUT (C),E
                POP DE
                LD C,L
                OUT (C),D
                LD C,H
                OUT (C),E
                POP DE
                LD C,L
                OUT (C),D
                LD C,H
                OUT (C),E
                DEC A
                JR NZ,WR_SEC1
WR_SEC_SP       LD SP,0
                POP HL
                RET

;SET HDD PORTS
SETHREG:
                PUSH DE
                LD D,B
                LD E,C
                LD BC,0xffd0
                OUT (C),D
                LD C,0xf0
SETHRE1:
                IN A,(C)
                AND 0x80
                JR NZ,SETHRE1
                LD C,0xb0
                OUT (C),E
                POP DE
                LD C,0x90
                OUT (C),D
                LD C,0x70
                OUT (C),E
                LD C,0x50
                EX AF,AF
                OUT (C),A
                RET

;HL-АДРЕС БУФЕРА СЕКТОРА ИДЕНТИФИКАЦИИ
;A=E0-ДЛЯ MASTER, A=F0-ДЛЯ SLAVE
ID_DEV:
                LD BC,0xFF00+P_1F6
                OUT (C),A
                LD C,P_1F7
                LD D,26
ID_DEV3:
                HALT
                DEC D
                JR Z,NO_DEV
                IN A,(C)
                BIT 7,A
                JR NZ,ID_DEV3
                AND A
                JR Z,NO_DEV
                INC A
                JR Z,NO_DEV
                XOR A
                LD C,P_1F5
                OUT (C),A
                LD C,P_1F4
                OUT (C),A
                LD A,0xEC
                LD C,P_1F7
                OUT (C),A
                LD C,P_1F7
ID_DEV1:
                IN A,(C)
                AND A
                JR Z,NO_DEV
                INC A
                JR Z,NO_DEV
                DEC A
                RRCA
                JR C,ID_DEV2
                RLCA
                AND 0x88
                CP 8
                JR NZ,ID_DEV1
ID_DEV2:
                LD C,P_1F4
                IN E,(C)
                LD C,P_1F5
                IN D,(C)
                LD A,D
                OR E
                JP Z,READSEC
                LD HL,0xEB14
                SBC HL,DE
                LD A,1
                RET Z
NO_DEV:
                LD A,0xFF
                RET


;Драйвер SD карты
;LAST UPDATE 14.04.2009 savelij
;Входные параметры общие:
;HL-адрес загрузки в память
;BCDE-32-х битный номер сектора
;A-количество блоков (блок=512 байт) - только для многоблочной записи/чтения
;Ошибки выдаваемые на выходе:
;A=0 - инициализация прошла успешно
;A=1 - карта не найдена или не ответила
;A=2 - карта защищена от записи
;A=3 - попытка записи в сектор 0 карты
P_DATA    EQU 0x0057    ;порт данных
P_CONF    EQU 0x8057    ;порт конфигурации
CMD_12    EQU 0x4C    ;STOP_TRANSMISSION
CMD_17    EQU 0x51    ;READ_SINGLE_BLOCK
CMD_18    EQU 0x52    ;READ_MULTIPLE_BLOCK
CMD_24    EQU 0x58    ;WRITE_BLOCK
CMD_25    EQU 0x59    ;WRITE_MULTIPLE_BLOCK
CMD_55    EQU 0x77    ;APP_CMD
CMD_58    EQU 0x7A    ;READ_OCR
CMD_59    EQU 0x7B    ;CRC_ON_OFF
ACMD_41   EQU 0x69   ;SD_SEND_OP_COND

zsd_init
    CALL CS_HIGH    ;включаем питание карты при снятом выборе
    LD BC,P_DATA
    LD DE,0x20FF    ;бит выбора карты в <1>
SD_INITloop
    OUT (C),E    ;записываем в порт много единичек
    DEC D    ;количество единичек несколько больше
    JR NZ,SD_INITloop    ;чем надо
    XOR A    ;запускаем счетчик на 256
    EX AF,AF    ;для ожидания инициализации карты
ZAW001    
    LD HL,CMD00    ;даем команду сброса
    CALL OUTCOM    ;этой командой карточка переводится в режим SPI
    CALL IN_OOUT    ;читаем ответ карты
    EX AF,AF
    DEC A
    JR Z,ZAW003    ;если карта 256 раз не ответила, то карты нет
    EX AF,AF
    DEC A
    JR NZ,ZAW001    ;ответ карты <1>, перевод в SPI прошел успешно
    LD HL,CMD08    ;запрос на поддерживаемые напряжения
    CALL OUTCOM    ;команда поддерживается начиная со спецификации
    CALL IN_OOUT    ;версии 2.0 и только SDHC, мини и микро SD картами
    IN H,(C)    ;в A=код ответа карты
    NOP    ;считываем 4 байта длинного ответа
    IN H,(C)    ;но не используем
    NOP
    IN H,(C)
    NOP
    IN H,(C)
    LD HL,0    ;HL=аргумент для команды инициализации
    BIT 2,A    ;если бит 2 установлен, то карта стандартная
    JR NZ,ZAW006    ;стандартная карта выдаст <ошибка команды>
    LD H,0x40    ;если ошибки не было, то карта SDHC, мини или микро SD
ZAW006    
    LD A,CMD_55    ;запускаем процесс внутренней инициализации
    CALL OUT_COM    ;для карт MMC здесь должна быть другая команда
    CALL IN_OOUT    ;соответственно наличие в слоте MMC-карты
    LD A,ACMD_41    ;вызовет зависание драйвера, от применения
    OUT (C),A    ;общей команды запуска инициализации я отказался
    NOP    ;бит 6 установлен для инициализации SDHC карты
    OUT (C),H    ;для стандартной сброшен
    NOP
    OUT (C),L
    NOP
    OUT (C),L
    NOP
    OUT (C),L
    LD A,0xFF
    OUT (C),A
    CALL IN_OOUT    ;ждем перевода карты в режим готовности
    AND A    ;время ожидания примерно 1 секунда
    JR NZ,ZAW006
ZAW004    LD A,CMD_59    ;принудительно отключаем CRC16
    CALL OUT_COM
    CALL IN_OOUT
    AND A
    JR NZ,ZAW004
ZAW005    LD HL,CMD16    ;принудительно задаем размер блока 512 байт
    CALL OUTCOM
    CALL IN_OOUT
    AND A
    JR NZ,ZAW005
;включение питания карты при снятом сигнале выбора карты
CS_HIGH    
    PUSH AF
    LD A,3
    ld bc,P_CONF
    OUT (c),A    ;включаем питание, снимаем выбор карты
    XOR A
    dec b       ; P_DATA
    OUT (c),A    ;обнуляем порт данных
    POP AF    ;обнуление порта можно не делать, просто последний
    ld a,0
    RET    ;записанный бит всегда 1, а при сбросе через вывод
        ;данных карты напряжение попадает на вывод питания
        ;карты и светодиод на питании подсвечивается
;возврат при не ответе карты с кодом ошибки 1
ZAW003    
    CALL zsd_off
    ld a,3
    RET
zsd_off    ;patch
    XOR A
        ld bc,P_CONF
    OUT (c),A    ;выключение питания карты
        dec b           ;P_DATA
    OUT (c),A    ;обнуление порта данных
    RET
;выбираем карту сигналом 0
CS__LOW    ;patch
    PUSH AF
    LD A,1
        ld bc,P_CONF
    OUT (c),A
    POP AF
    RET
;запись в карту команды с неизменяемым параметром из памяти
;адрес команды в <HL>
OUTCOM    ;patch
    CALL CS__LOW
    LD BC,0x600+P_DATA
    OTIR    ;передаем 6 байт команды из памяти
    RET
;запись в карту команды с нулевыми аргументами
;А-код команды, аргумент команды равен 0
OUT_COM    ;patch
    CALL CS__LOW
    LD BC,P_DATA
    OUT (C),A
    XOR A
    OUT (C),A
    NOP
    OUT (C),A
    NOP
    OUT (C),A
    NOP
    OUT (C),A
    DEC A
    OUT (C),A    ;пишем пустой CRC7 и стоповый бит
    RET
;запись команды чтения/записи с номером сектора в BCDE для карт стандартного размера
;при изменяемом размере сектора номер сектора нужно умножать на его размер, для карт
;SDHC, мини и микро размер сектора не требует умножения
SECM200    PUSH HL  ;patch
    PUSH DE
    PUSH BC
    PUSH AF
    PUSH BC
    LD A,CMD_58
    LD BC,P_DATA
    CALL OUT_COM
    CALL IN_OOUT
    IN A,(C)
    NOP
    IN H,(C)
    NOP
    IN H,(C)
    NOP
    IN H,(C)
    BIT 6,A    ;проверяем 30 бит регистра OCR (6 бит в <А>)        
    POP HL    ;при установленном бите умножение номера сектора
    JR NZ,SECN200    ;не требуется
    EX DE,HL    ;при сброшенном бите соответственно
    ADD HL,HL    ;умножаем номер сектора на 512 (0x200)
    EX DE,HL
    ADC HL,HL
    LD H,L
    LD L,D
    LD D,E
    LD E,0
SECN200    
    POP AF    ;заготовленный номер сектора находится в <HLDE>
    OUT (C),A    ;пишем команду из <А> на SD карту
    NOP    ;записываем 4 байта аргумента
    OUT (C),H    ;пишем номер сектора от старшего
    NOP
    OUT (C),L
    NOP
    OUT (C),D
    NOP
    OUT (C),E    ;до младшего байта
    LD A,0xFF
    OUT (C),A    ;пишем пустой CRC7 и стоповый бит
    POP BC
    POP DE
    POP HL
    RET
;чтение ответа карты до 32 раз, если ответ не 0xFF - немедленный выход
IN_OOUT    ;patch
    push de
    LD DE,0x20FF
        ld bc,P_DATA
IN_WAIT    IN A,(c)
    CP E
    JR NZ,IN_EXIT
IN_NEXT    DEC D
    JR NZ,IN_WAIT
IN_EXIT    POP DE
    RET
CMD00    DEFB  0x40,0x00,0x00,0x00,0x00,0x95 ;GO_IDLE_STATE
    ;команда сброса и перевода карты в SPI режим после включения питания
CMD08    DEFB  0x48,0x00,0x00,0x01,0xAA,0x87 ;SEND_IF_COND
    ;запрос поддерживаемых напряжений
CMD16    DEFB 0x50,0x00,0x00,0x02,0x00,0xFF ;SET_BLOCKEN
    ;команда изменения размера блока
;читаем один сектор из карты в память, адрес чтения в <HL>
RD_SECT    PUSH BC
    LD BC,P_DATA+0x7F00
    INIR
    LD B,0x7F
    INIR
    LD B,0x7F
    INIR
    LD B,0x7F
    INIR
    LD B,0x04
    INIR
    NOP
    IN A,(C)
    NOP
    IN A,(C)
    POP BC
    RET
;записываем один сектор из памяти в карту, адрес записи в <HL>
WR_SECT    PUSH BC
    LD BC,P_DATA
    OUT (C),A
    LD B,0x80
    OTIR
    LD B,0x80
    OTIR
    LD B,0x80
    OTIR
    LD B,0x80
    OTIR
    LD A,0xFF
    OUT (C),A
    NOP
    OUT (C),A
    POP BC
    RET
;многосекторное чтение
zsd_read ld a,1
    out (0xbf),a
    LD A,CMD_18
    CALL SECM200    ;даем команду многосекторного чтения
    EX AF,AF
RDMULT1    EX AF,AF
RDMULT2
    CALL IN_OOUT
    CP 0xFE
    JR NZ,RDMULT2    ;ждем маркер готовности 0xFE для начала чтения
    CALL RD_SECT    ;читаем сектор
    EX AF,AF
    DEC A
    JR NZ,RDMULT1    ;продолжаем пока не обнулится счетчик
    LD A,CMD_12    ;по окончании чтения даем команду карте <СТОП>
    CALL OUT_COM    ;команда мультичтения не имеет счетчика и
RDMULT3
    CALL IN_OOUT    ;должна останавливаться здесь командой 12
    INC A
    JR NZ,RDMULT3    ;ждем освобождения карты
    JP CS_HIGH    ;снимаем выбор с карты и выходим с кодом 0

;многосекторная запись
zsd_write ld a,1
    out (0xbf),a
    LD A,CMD_25 ;даем команду мультисекторной записи
    CALL SECM200
WRMULTI2
    CALL IN_OOUT
    INC A
    JR NZ,WRMULTI2 ;ждем освобождения карты
    EX AF,AF
WRMULT1 EX AF,AF
    LD A,0xFC ;пишем стартовый маркер, сам блок и пустое CRC16
    CALL WR_SECT
WRMULTI3
    CALL IN_OOUT
    INC A
    JR NZ,WRMULTI3 ;ждем освобождения карты
    EX AF,AF
    DEC A
    JR NZ,WRMULT1 ;продолжаем пока счетчик не обнулится
    LD C,P_DATA
    LD A,0xFD
    OUT (C),A ;даем команду остановки записи
WRMULTI4
    CALL IN_OOUT
    INC A
    JR NZ,WRMULTI4 ;ждем освобождения карты
    JP CS_HIGH ;снимаем выбор карты и выходим с кодом 0
   
   
;------------------------------------------------------
;---------------------------=NeoGS=--------------------
;------------------------------------------------------



GSCOM           EQU 0XBB        ; write-only, command for NGS
GSDAT           EQU 0XB3        ; read-write
GSCTR           EQU 0X33        ; write-only, control register for NGS:
;АДРЕС УСТАНОВЩИКА ДРАЙВЕРА НА NeoGS
SETUPSD         EQU 0x5B00

;NGSSDT         DEFW GSDINIT            ;ИНИТ SD КАРТЫ
;               DEFW GSDOFF             ;ОТКЛЮЧЕНИЕ SD КАРТЫ
;               DEFW SDRDSIN            ;ЧИТАТЬ 1 СЕКТОР
;               DEFW SDRDMUL            ;ЧИТАТЬ "A" СЕКТОРОВ
;               DEFW SDWRSIN            ;ПИСАТЬ 1 СЕКТОР
;               DEFW SDWRMUL            ;ПИСАТЬ "A" СЕКТОРОВ

;ЗАПИСЬ "A" СЕКТОРОВ
SDWRMUL         LD A,5
SDWRSN3         CALL COMM2SD
                EX AF,AF
                PUSH DE
                PUSH BC
                LD BC,GSDAT
SDWRSN1         EX AF,AF
                OUT (GSCOM),A
                CALL WC_
                LD DE,0x0200
SDWRSN2         OUTI
                CALL WD_
                DEC DE
                LD A,D
                OR E
                JR NZ,SDWRSN2
                EX AF,AF
                DEC A
                JR NZ,SDWRSN1
                CALL WN_
                IN A,(C)
                CP 0x77
                JR NZ,$-4
                POP BC
                POP DE
                XOR A
                RET

;ЧТЕНИЕ "A" СЕКТОРОВ
SDRDMUL         LD A,3
SDRDSN3         CALL COMM2SD
                EX AF,AF
                PUSH DE
                PUSH BC
                LD BC,GSDAT
SDRDSN1         EX AF,AF
                OUT (GSCOM),A
                CALL WC_
                LD DE,0x0200
SDRDSN2         CALL WN_
                INI
                DEC DE
                LD A,D
                OR E
                JR NZ,SDRDSN2
                EX AF,AF
                DEC A
                JR NZ,SDRDSN1
                CALL WN_
                IN A,(C)
                CP 0x77
                JR NZ,$-4
                POP BC
                POP DE
                XOR A
                RET

;ОТКЛЮЧЕНИЕ ВЫБОРА КАРТОЧКИ
GSDOFF          LD A,1
                JR GSDINIT+1

;ИНИЦИАЛИЗАЦИЯ КАРТОЧКИ
GSDINIT         CALL INSTSDD
                OR A
                RET NZ
                XOR A
                CALL COMM2SD
                CALL WN_
                IN A,(GSDAT)
                CP 0x77
                JR NZ,SD_NO
                XOR A
                RET

SD_NO           LD A,1
                RET

;ПЕРЕДАТЧИК КОМАНД/ПАРАМЕТРОВ В ДРАЙВЕР НА NeoGS
COMM2SD         OUT (GSDAT),A                   ;УШЛА КОМАНДА ДРАЙВЕРУ
                LD A,0x1E
                OUT (GSCOM),A
                CALL WC_                        ;УШЛА КОМАНДА ПРОШИВКЕ
                LD A,B
                OUT (GSDAT),A
                CALL WD_                        ;УШЛИ БИТЫ 31-24 ПАРАМЕТРОВ
                LD A,C
                OUT (GSDAT),A
                CALL WD_                        ;УШЛИ БИТЫ 23-16 ПАРАМЕТРОВ
                LD A,D
                OUT (GSDAT),A
                CALL WD_                        ;УШЛИ БИТЫ 15-8 ПАРАМЕТРОВ
                LD A,E
                OUT (GSDAT),A
                CALL WD_                        ;УШЛИ БИТЫ 7-0 ПАРАМЕТРОВ
                EX AF,AF
                OUT (GSDAT),A
                EX AF,AF
                DEFS 9
                RET                             ;УШЛО КОЛ-ВО СЕКТОРОВ

;ОЖИДАНИЕ КОГДА NeoGS БАЙТ ЗАБЕРЕТ
WD_             IN A,(GSCOM)
                RLA
                JR C,$-3
                RET

;ОЖИДАНИЕ КОГДА NeoGS ДАСТ БАЙТ
WN_             IN A,(GSCOM)
                RLA
                JR NC,$-3
                RET

;ОЖИДАНИЕ КОГДА NeoGS КОМАНДУ ЗАБЕРЕТ
WC_             IN A,(GSCOM)
                RRA
                JR C,$-3
                RET

;УСТАНОВЩИК ДРАЙВЕРА НА NeoGS
INSTSDD         LD A,0x80
                OUT (GSCTR),A
                HALT
                HALT
                LD A,0xF3
                LD B,0x30
                OUT (GSCOM),A
ISDD1   HALT
                DEC B
                JR Z,SD_NO
                IN A,(GSCOM)
                RRA
                JR C,ISDD1
                LD BC,GSDAT
                IN A,(C)
                LD DE,0x0300
                LD HL,SETUPSD
                OUT (C),E
                LD A,0x14
                OUT (GSCOM),A
                CALL WC_
                OUT (C),D
                CALL WD_
                OUT (C),L
                CALL WD_
                OUT (C),H
                CALL WD_
                LD HL,(0x0006)
ISDD3           OUTI
                CALL WD_
                DEC DE
                LD A,D
                OR E
                JR NZ,ISDD3
                LD HL,SETUPSD
                OUT (C),L
                LD A,0x13
                OUT (GSCOM),A
                CALL WC_
                OUT (C),H
                HALT
                HALT
                IN A,(GSDAT)
                CP 0x77
                JP NZ,SD_NO
                XOR A
                RET



ENDMOD
END