Login

Subversion Repositories NedoOS

Rev

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

;на входе ожидается pgstructs в c000. на выходе всегда ставить pgstructs

;/* Results of Disk Functions */
;typedef enum {
;       RES_OK = 0,             /* 0: Successful */
;       RES_ERROR,              /* 1: R/W Error */
;       RES_WRPRT,              /* 2: Write Protected */
;       RES_NOTRDY,             /* 3: Not Ready */
;       RES_PARERR              /* 4: Invalid Parameter */
;} DRESULT;

         ifdef KOE
        macro NOPSDCARD
        ;ds 4
        endm
         else
        macro NOPSDCARD
        endm
         endif
       
device_states
        db 1
        db 1
        db 1
        db 1
        db 1

disk_status:
        ld d,0
        ld hl,device_states
        add hl,de
                if INETDRV != 1
                        ld a,(hl)
                        ret
                else
                        ld a,4
                        cp e
                        ld a,(hl)
                        jr z,.isSL811
                        ret
.isSL811
                        or a
                        ret nz
                        ld bc,0x82ab
                        in a,(c)
                        and 0xaf                ;хост-мод и сл811 в портах
                        out (c),a      
                        ld b,0x80
                        ld a,0x0d
                        out (c),a
                        in a,(0xab)
                        jr z,.resSL811
                        and 0x40
                        ret z
.resSL811
                        ld a,1
                        ld (hl),a
                        ret
                endif
devices_init
;bc=?
;e=device number
;out: a=?
;        xor a
;        ld d,a
;       ld hl,device_states
;       add hl,de
;       cp (hl)
;       ret z
        push bc
        call disk_status
        pop hl
        or a
        ret z
        ld a,e ;a=e
        or a
        jr nz,devices_init_noIDEmaster
        ld a,0xe0
        call IDE_INIT
        ld (device_states+0),a
        ret  
devices_init_noIDEmaster
        dec a
        jr nz,devices_init_noIDEslave
        ld a,0xf0
        call IDE_INIT
        ld (device_states+1),a
        ret  
devices_init_noIDEslave
        dec a
        jr nz,devices_init_noSD
        ifdef KOE
         ifdef KOEDI
                di
         endif
                call SD_INIT
         ifdef KOEDI
                ei
         endif
        else
    if (atm==3) || (atm==1)
                call SD_INIT
    else
        ld a,1
    endif
        endif
        ld (device_states+2),a
        ret  
devices_init_noSD
        dec a
        jr nz,devices_init_noGS
        ifdef NGSSD
        call GS_INIT
        else
        ld a,1
        endif
        ld (device_states+3),a
        ret  
devices_init_noGS
        if INETDRV == 1
                dec a
                jr nz,devices_init_noSL811
                call SL811.init
                ld (device_states+4),a
                ret
devices_init_noSL811
        endif
        ld a,0x01 ;нет такого устройства
        ret  

diskgetpars
        ld hl,(fatfs_org+FFS_DRV.lba_ptr)
        ld e,(hl)
        inc hl
        ld d,(hl)
        inc hl
        ld c,(hl)
        inc hl
        ld b,(hl)
        ld hl,(fatfs_org+FFS_DRV.dma_addr)
        ld a,(fatfs_org+FFS_DRV.count)
        exa  
        ld a,(fatfs_org+FFS_DRV.dio_drv)
        ;or a
;hl=buffer
;a=drive
;bcde=sector
;a'=count
        ret
       
;?????????????????????????????? чтение секторов
devices_read
        call BDOS_setdepage
        call devices_readnopg;devices_read_go
        push af
        call BDOS_setpgstructs
        pop af ;error
        ret
devices_readnopg
        ;call BDOS_setpgstructs
        call diskgetpars
devices_read_go_regs
    ifdef KOEDI
                di
                call devices_read_go
                ei
                ret
devices_read_go
    endif
;hl=buffer
;a=drive
;bcde=sector
;a'=count
         or a
        jr nz,readsectors_noIDEmaster
        ld a,0xe0 ;master ;почему bit6=1???
;b+a=head+device
;c=cylHI
;d=cylLO
;e=sec
;a'=count      
        jp readsectorsIDE
readsectors_noIDEmaster
        dec a
        jr nz,readsectors_noIDEslave
        ld a,0xf0 ;slave ;почему bit6=1???
;b+a=head+device
;c=cylHI
;d=cylLO
;e=sec
;a'=count      
        jp readsectorsIDE
readsectors_noIDEslave
        dec a
        jp z,readsectorsSD
        dec a
        jp z,readsectorsGS
        if INETDRV == 1
                dec a
                jp z,SL811.RBC_Read
        endif
        ld a,0x01
        ret  

;?????????????????????????????? запись секторов
devices_write
        call BDOS_setdepage
        call devices_writenopg;devices_write_go
        push af
        call BDOS_setpgstructs
        pop af ;error
        ret
devices_writenopg
        ;call BDOS_setpgstructs
        call diskgetpars
devices_write_go_regs
    ifdef KOEDI
                di
                call devices_write_go
                ei
                ret
devices_write_go
    endif
;hl=buffer
;a=drive
;bcde=sector
;a'=count
         or a
        jr nz,writesectors_noIDEmaster
        ld a,0xe0 ;master ;почему bit6=1???
;b+a=head+device
;c=cylHI
;d=cylLO
;e=sec
;a'=count      
        jp writesectorsIDE
writesectors_noIDEmaster
        dec a
        jr nz,writesectors_noIDEslave
        ld a,0xf0 ;slave ;почему bit6=1???
;b+a=head+device
;c=cylHI
;d=cylLO
;e=sec
;a'=count      
        jp writesectorsIDE
writesectors_noIDEslave
        dec a
        jp z,writesectorsSD
        dec a
        jp z,writesectorsGS
        if INETDRV == 1
                dec a
                jp z,SL811.RBC_Write
        endif
        ld a,0x01
        ret  

;;;;;;;;;;;;;;;;;;;;;;;;;;; IDE
       
IDE_INIT
;a=device (0xe0/f0)
        push hl
        call readidentIDE
        pop hl
        and a
        ret nz
        ;jp checkidentIDE
checkidentIDE
;зачем сохранять hl? TODO убрать
        push hl
        ;ld d,h
        ;ld e,l
        ex de,hl
        ld hl,0x0063
        add hl,de
        ld a,(hl)
        and 0x02
        jr z,ldaff_pophl
        ;ld bc,0xff00+hddcount;????
        ld bc,hddcount
        ld hl,0x000c
        add hl,de
        ld a,(hl) ;0x3f???
        out (C),a
        ld hl,0x0006
        ld bc,hddhead
        add hl,de
        ld a,(hl)
        dec a ;0x0f???
        out (C),a
        ld bc,hddcmd
        ld a,0x91
        out (C),a
        ld de,0x1000
nobsywithtimeout0
        dec de
        ld a,d
        or e
        jr z,ldaff_pophl
        in a,(C)
        and 0x80
        jr nz,nobsywithtimeout0
        pop hl
        ret
ldaff_pophl
        ld a,0xff
        pop hl
        ret

sendcmd_waitDRQ
        ld bc,hddcmd
        out (C),a
waitDRQ
        ;ld a,(sys_timer)
        ;add a,2
        ;ld (waitDRQmaxtime),a
        ld bc,hddstat
waitDRQ0
       ;ld a,(sys_timer)
waitDRQmaxtime=$+1
       ;cp 0
       ;ret z
        in a,(C)
        and 0x88
        cp 0x08
        jr nz,waitDRQ0 ;ожидание готовности передачи данных
        ret

readsectorsIDE
;b+a=head+device
;c=cylHI
;d=cylLO
;e=sec
;a'=count
    add a,b
        ld b,a
;b=head
;c=cylHI
;d=cylLO
;e=sec
;a'=count
        call setblockparsIDE
        exa  
        ld a,0x20
        call sendcmd_waitDRQ
        exa  
readsectorsIDE0
        exa  
        call readsecIDE
        ld bc,hddstat
nobsy0
        in a,(C)
        and 0x80
        jr nz,nobsy0
        exa  
        dec a
        jr nz,readsectorsIDE0
        jr lda0

writesectorsIDE
;b+a=head+device
;c=cylHI
;d=cylLO
;e=sec
;a'=count
        add a,b
        ld b,a
;b=head
;c=cylHI
;d=cylLO
;e=sec
;a'=count
        call setblockparsIDE
        exa  
        ld a,0x30
        call sendcmd_waitDRQ
        exa
writesectorsIDE0
        exa  
        call writesecIDE
        ;inc h
        ;inc h
        ld bc,hddstat
nobsy01
        in a,(C)
        and 0x80
        jr nz,nobsy01
        exa  
        dec a
        jr nz,writesectorsIDE0
lda0   
        xor a;ld a,0x00
        ret

readsecIDE
        ;jr $
        xor a;ld a,0
readsecIDE0
        ld bc,hdddatlo
        in e,(C)
        ld bc,hdddathi
        in d,(C)
        ld (hl),e
        inc hl
        ld (hl),d
        inc hl
        dec a
        jr nz,readsecIDE0
        ret
       
writesecIDE
        if (hdddatlo != 0x10)
        xor a
writesecIDE0
        ld e,(hl)
        inc hl
        ld d,(hl)
        inc hl
        ld bc,hdddathi
        out (c),d
        ld bc,hdddatlo
        out (c),e
        dec a
        jr nz,writesecIDE0
        else
        ld bc,0x0000 + hdddathi
writesecIDE0
        ld a,(hl)
        inc hl
        outi
        out (hdddatlo),a
        ld a,(hl)
        inc hl
        outi
        out (hdddatlo),a
        ld a,(hl)
        inc hl
        outi
        out (hdddatlo),a
        ld a,(hl)
        inc hl
        outi
        out (hdddatlo),a
        jr nz,writesecIDE0
        endif
        ret
       
setblockparsIDE
;b=head
;c=cylHI
;d=cylLO
;e=sec
;a'=count      
        push de
        ld d,b
        ld e,c
        ;ld bc,0xff00+hddhead ;зачем ff???
        ld bc,hddhead
        out (C),d ;head
        ld bc,hddstat
nobsy02
        in a,(C)
        and 0x80
        jr nz,nobsy02
        ld bc,hddcylhi
        out (C),e ;cylHI
        pop de
        ld bc,hddcyllo
        out (C),d ;cylLo
        ld bc,hddsec
        out (C),e ;sec
        ld bc,hddcount
        exa  
        out (C),a ;count
        ret
       
readidentIDE
        ;ld bc,0xff00+hddhead ;зачем ff???
        ;потому что неучаствующие биты в единице обычно
        ld bc,hddhead
        out (C),a
        ld bc,hddstat
        ld d,0x1a
LL7c06  ;ei  
        halt  
        ;di  
        dec d
        jr z,ldaff
        in a,(C)
        bit 7,a
        jr nz,LL7c06
        and a
        jr z,ldaff
        inc a
        jr z,ldaff
        xor a
        ld bc,hddcylhi
        out (C),a
        ld bc,hddcyllo
        out (C),a
        ld a,0xec
        ld bc,hddcmd
        out (C),a
        ld bc,hddstat
LL7c29  in a,(C)
        and a
        jr z,ldaff
        inc a
        jr z,ldaff
        dec a
        rrca  
        jr c,LL7c3c
        rlca  
        and 0x88
        cp 0x08
        jr nz,LL7c29
LL7c3c  ld bc,hddcyllo
        in e,(C)
        ld bc,hddcylhi
        in d,(C)
        ld a,d
        or e
        jp z,readsecIDE
        ld hl,0xeb14 ;???
        sbc hl,de
        ld a,0x01
        ret z
ldaff  
        ld a,0xff
        ret  
       
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Z-Controller (SD-card) ;;;;;;;;;;;;;;;;

SD_INIT
        call cs_highSD ;включаем питание карты при снятом выборе
        ld bc,0x0057
        ld de,0x20ff
LL7c5d  out (C),e
        dec d
        jr nz,LL7c5d ;записываем в порт много единичек
        xor a
        exa  
LL7c64  ld hl,cmd00SD ;GO_IDLE_STATE ;команда сброса и перевода карты в SPI режим после включения питания
        call outcom_hlSD ;этой командой карточка переводится в режим SPI
        call read32byteswaitnoffSD
        exa  
        dec a
        jp z,errexitSD ;если карта 256 раз не ответила, то карты нет
        exa  
        dec a
        jr nz,LL7c64
        ld hl,cmd08SD ;SEND_IF_COND ;запрос поддерживаемых напряжений
        call outcom_hlSD
        call read32byteswaitnoffSD
        in h,(C)
        NOPSDCARD  
        in h,(C)
        NOPSDCARD  
        in h,(C)
        NOPSDCARD  
        in h,(C)
        ld hl,0
        bit 2,a
        jr nz,LL7c92
        ld h,0x40
LL7c92  ld a,0x77 ;запускаем процесс внутренней инициализации
        call outcom_zeroparsSD
        call read32byteswaitnoffSD
       ifndef KOE
        in f,(c)
        NOPSDCARD
        in f,(c)
        NOPSDCARD
       endif
        ld a,0x69
        out (C),a ;бит 6 установлен для инициализации SDHC карты
        NOPSDCARD  
        out (C),h
        NOPSDCARD  
        out (C),l
        NOPSDCARD  
        out (C),l
        NOPSDCARD  
        out (C),l
        NOPSDCARD
        ld a,0xff
        out (C),a
        call read32byteswaitnoffSD ;ждем перевода карты в режим готовности
        and a ;время ожидания примерно 1 секунда
        jr nz,LL7c92
LL7cb4  ld a,0x7b ;принудительно отключаем CRC16
        call outcom_zeroparsSD
        call read32byteswaitnoffSD
        and a
        jr nz,LL7cb4
LL7cbf  ld hl,cmd16SD ;SET_BLOCKEN ;команда изменения размера блока
        call outcom_hlSD ;принудительно задаем размер блока 512 байт
        call read32byteswaitnoffSD
        and a
        jr nz,LL7cbf
       
        ;запомним размер блока
        ld a,0x7a ;READ_OCR
        ld bc,0x0057
        call outcom_zeroparsSD
        call read32byteswaitnoffSD
        in a,(C)
        NOPSDCARD  
        in h,(C)
        NOPSDCARD  
        in h,(C)
        NOPSDCARD  
        in h,(C)
        and 0x40
        ld (zsd_blsize),a
       
;включение питания карты при снятом сигнале выбора карты
cs_highSD
        push af
        ld a,0x03
        ld bc,0x8057
        out (C),a ;включаем питание, снимаем выбор карты
        xor a
        dec b
        out (C),a ;обнуляем порт данных
;обнуление порта можно не делать, просто последний записанный бит всегда 1, а при сбросе через вывод данных карты напряжение попадает на вывод питания карты и светодиод на питании подсвечивается
        pop af
        xor a;ld a,0x00
        ret  

errexitSD
        call SD_OFF
        ld a,0x03
        ret  

SD_OFF
        xor a
        ld bc,0x8057
        out (C),a ;выключение питания карты
        dec b
        out (C),a ;обнуление порта данных
        ret  

;выбираем карту сигналом 0
cs_lowSD
        push af
        ld a,0x01
        ld bc,0x8057
        out (C),a
        pop af
        ret  

;запись в карту команды с неизменяемым параметром из памяти
;адрес команды в HL
outcom_hlSD
    call cs_lowSD
        ld bc,0x0657
        otir  
        ret  

;запись в карту команды с нулевыми аргументами
;А=код команды, аргумент команды равен 0
outcom_zeroparsSD
    call cs_lowSD
        ld b,0x0057
       ifndef KOE
        in f,(c)
        NOPSDCARD
        in f,(c)
        NOPSDCARD
       endif
        out (C),a
        NOPSDCARD
    xor a
        out (C),a
        NOPSDCARD  
        out (C),a
        NOPSDCARD  
        out (C),a
        NOPSDCARD  
        out (C),a
        NOPSDCARD
        dec a
        out (C),a
        ret  
zsd_blsize
        DEFB 0
;запись команды чтения/записи с номером сектора в BCDE для карт стандартного размера
;при изменяемом размере сектора номер сектора нужно умножать на его размер, для карт
;SDHC, мини и микро размер сектора не требует умножения
setcmdparsSD
        push hl
        push de
        push bc
        push af
;       push bc
;       ld a,0x7a ;READ_OCR
;       ld bc,0x0057
;       call outcom_zeroparsSD
;       call read32byteswaitnoffSD
;       in a,(C)
;       NOPSDCARD  
;       in h,(C)
;       NOPSDCARD  
;       in h,(C)
;       NOPSDCARD  
;       in h,(C)
;       bit 6,a ;проверяем 30 бит регистра OCR (6 бит в "А")
;       pop hl       ;при установленном бите умножение номера сектора
        ld h,b
        ld l,c
        call cs_lowSD
        ld bc,0x0057
        ld a,(zsd_blsize)
        or a
        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,0x00
SECN200 pop af ;заготовленный номер сектора находится в HLDE
       ifndef KOE
        in f,(c)
        NOPSDCARD
        in f,(c)
        NOPSDCARD
       endif
        out (C),a ;команда
        NOPSDCARD  
        out (C),h ;;пишем номер сектора от старшего
        NOPSDCARD  
        out (C),l
        NOPSDCARD  
        out (C),d
        NOPSDCARD  
        out (C),e ;до младшего байта
        NOPSDCARD
        ld a,0xff
        out (C),a ;пишем пустой CRC7 и стоповый бит
        pop bc
        pop de
        pop hl
        ret
       
;чтение ответа карты до 32 раз, если ответ не 0xFF - немедленный выход
read32byteswaitnoffSD
        push de
        ld de,0x20ff
        ld bc,0x0057
LL7d5e  in a,(C)
        cp e
        jr nz,LL7d66
        dec d
        jr nz,LL7d5e
LL7d66  pop de
        ret  

cmd00SD
;GO_IDLE_STATE
;команда сброса и перевода карты в SPI режим после включения питания
        db 0x40
        db 0x00
        db 0x00
        db 0x00
        db 0x00
        db 0x95
cmd08SD
;SEND_IF_COND
;запрос поддерживаемых напряжений
        db 0x48
        db 0x00
        db 0x00
        db 0x01
        db 0xaa
        db 0x87
cmd16SD
;SET_BLOCKEN
;команда изменения размера блока
        db 0x50
        db 0x00
        db 0x00
        db 0x02
        db 0x00
        db 0xff

readsectorsSD
        ld a,0x52
        call setcmdparsSD
        exa  
LL7dbd  exa  
LL7dbe  call read32byteswaitnoffSD
        cp 0xfe
        jr nz,LL7dbe
        ;call readsecSDcard
readsecSDcard  
    ;push bc
        ld bc,0x7f57
        inir  
        ld b,0x7f
        inir  
        ld b,0x7f
        inir  
        ld b,0x7f
        inir  
        ld b,0x04
        inir  
        NOPSDCARD  
        in a,(C)
        NOPSDCARD  
        in a,(C)
        ;pop bc
       
        exa  
        dec a
        jr nz,LL7dbd
        ld a,0x4c
        call outcom_zeroparsSD
readsectorsSD_q
        call read32byteswaitnoffSD_loopnoff
        jp cs_highSD

read32byteswaitnoffSD_loopnoff
        call read32byteswaitnoffSD
        inc a
        jr nz,read32byteswaitnoffSD_loopnoff
        ret

writesectorsSD
        ld a,0x59
        call setcmdparsSD
;LL7ddf call read32byteswaitnoffSD
;       inc a
;       jr nz,LL7ddf
        call read32byteswaitnoffSD_loopnoff
        EX AF,AF'  
WRMULT1 EX AF,AF'
 
        ld a,0xfc
;       call writesecSDcard
writesecSDcard 
    ;push bc
        ld bc,0x0057
        out (C),a
        ld b,0x80
        otir  
        ld b,0x80
        otir  
        ld b,0x80
        otir  
        ld b,0x80
        otir  
        NOPSDCARD
        ld a,0xff
        out (C),a
        NOPSDCARD  
        out (C),a
        ;pop bc
;LL7dec call read32byteswaitnoffSD
;       inc a
;       jr nz,LL7dec
        call read32byteswaitnoffSD_loopnoff
        EX AF,AF'  
        dec a
        jr nz,WRMULT1
        ld c,0x57
        ld a,0xfd
        out (C),a
;LL7dfc call read32byteswaitnoffSD
;       inc a
;       jr nz,LL7dfc
        ;call read32byteswaitnoffSD_loopnoff
        ;jp cs_highSD
        jr readsectorsSD_q

   
        include "portsngs.asm"
        include "ngssddrv.asm"
   

get_fattime:
;de=buf
                if atm==1
                        call readtime
                endif
        ld hl,sys_time_date
                ld bc,4
        ldir
        ret

        if INETDRV == 1
                include "sl811.asm"
        endif