Big update

Added support SDIO card
Fixed bugs
Added support 4-bit mode for sd card
Added support all slots on controllers
and other
This commit is contained in:
Doczom
2023-06-05 11:11:13 +05:00
committed by GitHub
parent 870202a99f
commit 519942fec4
9 changed files with 1307 additions and 615 deletions

102
README.md
View File

@@ -1,52 +1,50 @@
# SDHCI_driver_for_Kolibrios
Driver for SD host controller on Kolibri OS
## WARNING!!!
The driver is being developed and tested for the controller version 2.0 (integrated into the FCH Bolton D3). On controllers of another version or another manufacturer, it may work unstable and may lead to equipment failure.
## Information
Version controller:
- 1.0 - no supported
- 2.0 - Supported
- 3.0 - no supported
- 4.0 - no supported
DMA modes:
- no-DMA - not supported
- SDMA - Supported
- ADMA1 - not supported
- ADMA2 32bit - not supported
- ADMA2 64bit - not supported
Version OS:
* rev 9897
Bus protocol:
- SD Bus protocol - Supported
- SPI Bus protocol - no supported
- UHS-II Bus protocol - no supported
- PCIe/NVMe Bus protocol - no supported
## TODO:
- инициализация контроллера, вывод информации об контроллере
- Установка изначальных значений для работы контроллера
- ~~регистрация обработчика прерываний~~
- документирование и реализация команд контроллера
- ~~написание алгоритма инициализации SD карт~~
- переписать обнаружение карт при инициализации контроллера
- написание алгоритма инициализации SDIO карт
- написание алгоритма инициализации MMC карт
- написание функций передачи блоков через SDMA и ADMA и без применения DMA
- реализация функций card_init и card_destryct
- написание алгоритма инициализации для карт с интерфейсом SPI
- ~~Получение базовых данных о карте(CID, CSD, RCA)~~
- реализовать функции смены частоты
- реализовать функции переключения шины SD в 4bit режим и обратно в 1bit режим
- реализовать функции смены питания на 1.8V
- реализация функций обработки сообщений контроллера
- реализация функций SDIO и их экспорт для драйверов и прикладного ПО
- реализация встроенного драйвера на SD карты памяти
- ~~получение объёма карты в секторах(512 байт)~~
# SDHCI_driver_for_Kolibrios
Driver for SD host controller on Kolibri OS
## WARNING!!!
The driver is being developed and tested for the controller version 2.0 (integrated into the FCH Bolton D3). On controllers of another version or another manufacturer, it may work unstable and may lead to equipment failure.
## Information
Version controller:
- 1.0 - no supported
- 2.0 - Supported
- 3.0 - no supported
- 4.0 - no supported
DMA modes:
- no-DMA - not supported
- SDMA - Supported
- ADMA1 - not supported
- ADMA2 32bit - not supported
- ADMA2 64bit - not supported
Version OS:
* rev 9897
Bus protocol:
- SD Bus protocol - Supported
- UHS-II Bus protocol - no supported
- PCIe/NVMe Bus protocol - no supported
## TODO:
- ~~инициализация контроллера, вывод информации об контроллере~~
- ~~Установка изначальных значений для работы контроллера~~
- ~~регистрация обработчика прерываний~~
- ~~документирование и реализация команд контроллера~~
- ~~написание алгоритма инициализации SD карт~~
- ~~переписать обнаружение карт при инициализации контроллера~~
- написание алгоритма инициализации SDIO карт
- написание алгоритма инициализации MMC карт
- написание функций передачи блоков через SDMA и ADMA и без применения DMA
- ~~реализация функций card_init и card_destryct~~
- ~~Получение базовых данных о карте(CID, CSD, RCA)~~
- ~~реализовать функции смены частоты~~
- ~~реализовать функции переключения шины SD в 4bit режим и обратно в 1bit режим~~
- реализовать функции смены питания на 1.8V
- ~~реализация функций обработки сообщений контроллера~~
- реализация функций SDIO и их экспорт для драйверов и прикладного ПО
- ~~реализация встроенного драйвера на SD карты памяти~~
- ~~получение объёма карты в секторах(512 байт)~~

View File

@@ -47,7 +47,7 @@
;0-11 Transfer Block Size
; Этот регистр определяет размер блока передачи данных для CMD17, CMD18, CMD24, CMD25, CMD35.
; можно задать значение от 1 до 2048 байт. не изменять и не читать во время транзакции
; In case of memory? it shall be set up to 512 bytes( Reffer to Implementation Note in Section 1.7.2)
; In case of memory<EFBFBD> it shall be set up to 512 bytes( Reffer to Implementation Note in Section 1.7.2)
;12-14 SDMA Buffer Boundary
; Размер выделяемой нами физической памяти для SDMA команд.(4кб 8 кб 16 кб и тд. до 512к)
; когда контроллер дошёл до конца выделенной нами памяти, вызывается прерывание DMA interrupt
@@ -650,3 +650,124 @@
;Для обнаружения ошибка таймаута на DAT линии. Установку этого значения делать при любой sd
;транзакцией.
;; CODE FOR TEST WORKING
;DEBUGF 1,"SDHCI: TEST1 SDMA - read first sector\n"
;call TEST_SDMA_R
;DEBUGF 1,"SDHCI: TEST2 SDMA - read first sector\n"
;call TEST_SDMA_R_MUL
;proc TEST_SDMA_R
; or dword[eax + SDHC_INT_MASK], 0xFFFFFFFF
; or dword[eax + SDHC_SOG_MASK], 0xFFFFFFFF
; and dword[eax + SDHC_CTRL1], not 11000b ; set SDMA mode
; mov byte[eax + 0x2E], 1110b ; set max
; mov ebp, eax
; invoke KernelAlloc, 4096
; push eax
; invoke GetPhysAddr ; arg = eax
; xchg eax, ebp
; mov dword[eax], ebp;phys addr
; mov dword[eax + 4], SD_BLOCK_SIZE
; ;(block_count shl) 16 + (sdma_buffer_boundary shl 12) + block_size
; mov dword[eax + 8], 0 ; arg - num sector
; mov dword[eax + 0xC], (((17 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + 010001b
;@@:
; cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
; hlt
; jz @b
; ;DEBUGF 1,"SDHCI: resp1=%x resp2=%x \n", [eax + SDHC_RESP1_0], [eax + SDHC_RESP3_2]
;.wait_int:
; mov dword[esi + SDHCI_CONTROLLER.int_status], 0
; hlt
; cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
; jz .wait_int
; ;DEBUGF 1,"SDHCI: resp1=%x resp2=%x \n", [eax + SDHC_RESP1_0], [eax + SDHC_RESP3_2]
; pop ebp
; test dword[eax + SDHC_RESP1_0], 0x8000
; jnz @f
; push eax
; mov dword[.ptr], ebp
; mov ebx, .file_struct
; invoke FS_Service
; pop eax
;@@:
; ret
;.file_struct:
; dd 2
; dd 0
; dd 0
; dd 512
;.ptr: dd 0
; db '/tmp0/1/dump_first_sector',0
;
;endp
; Заметка к SDMA: Прерывание DMA возникает только при пересечении границы блока данных
; у меня это граница в 4кб
;proc TEST_SDMA_R_MUL
; or dword[eax + SDHC_INT_MASK], 0xFFFFFFFF
; or dword[eax + SDHC_SOG_MASK], 0xFFFFFFFF
; and dword[eax + SDHC_CTRL1], not 11000b ; set SDMA mode
; mov byte[eax + 0x2E], 1110b ; set max
; mov ebp, eax
; invoke KernelAlloc, 4096*0x800;128;4096*512
; push eax
; push eax
; invoke GetPhysAddr ; arg = eax
; xchg eax, ebp
; mov dword[eax], ebp;phys addr
; mov dword[eax + 4], ((8*0x800) shl 16) + SD_BLOCK_SIZE
; ;(block_count shl) 16 + (sdma_buffer_boundary shl 12) + block_size
; mov dword[eax + 8], 0;0x2000 ; arg - num sector
; mov dword[eax + 0xC], (((18 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + CMD_TYPE.Multiple + 10101b
;@@:
; cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
; hlt
; jz @b
; ;DEBUGF 1,"SDHCI: resp1=%x resp2=%x \n", [eax + SDHC_RESP1_0], [eax + SDHC_RESP3_2]
;.wait_int:
; mov dword[esi + SDHCI_CONTROLLER.int_status], 0
; hlt
; cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
; jz .wait_int
; test dword[esi + SDHCI_CONTROLLER.int_status], 10b
; jnz @f
; test dword[esi + SDHCI_CONTROLLER.int_status], 1000b
; jz @f
;
; xchg eax, ebp
; mov eax, dword[esp]
; add eax, 4096
; mov dword[esp], eax
; invoke GetPhysAddr
; xchg eax, ebp
; mov dword[eax], ebp;phys addr
;
; jmp .wait_int
;
; ;DEBUGF 1,"SDHCI: resp1=%x resp2=%x \n", [eax + SDHC_RESP1_0], [eax + SDHC_RESP3_2]
;@@:
; pop ebp
; pop ebp
; test dword[eax + SDHC_RESP1_0], 0x8000
; jnz @f
; push eax
; mov dword[.ptr], ebp
; mov ebx, .file_struct
; invoke FS_Service
; pop eax
;@@:
; ret
;.file_struct:
; dd 2
; dd 0
; dd 0
; dd 4096*0x800;128
;.ptr: dd 0
; db '/tmp0/1/dump_first_sector_mul',0
;
;endp

View File

@@ -41,6 +41,16 @@ SD_BLOCK_SIZE = 0x200 ;standart sector = 512
R1_APP_CMD = 100000b ; êàðòà îæèäàåò ACMD êîìàíäó
R1_READY_FOR_DATA = 100000000b ; 0x100 ñîîòâåòñÿòâóåò ñèãíàëó î ïóñòîì áóôåðå íà øèíå
CMD55_VALID_RESP = R1_READY_FOR_DATA + R1_APP_CMD
OCR_REG:
.S18A = (1 shl 24)
.CO2T = 0x08000000
.CCS = 0x40000000
.UHSII = 0x20000000
.Busy = 0x80000000
; sdio
.MP = (1 shl 27)
; in: eax - reg map, esi - struct controller
; ebx - arg 32 bit â ãîòîâîì âèäå edx - 0x0C register ;command reg with flags
proc send_sdhc_command
@@ -48,12 +58,12 @@ proc send_sdhc_command
test dword[eax + SDHC_PRSNT_STATE], 0x07 ; check cmd_inhid_cmd + cmd_inhibit_dat + DAT Line Active
jnz @b
mov dword[eax + SDHC_CMD_ARG], ebx
mov dword[esi + SDHCI_CONTROLLER.int_status], 0
mov dword[esi + SDHCI_SLOT.int_status], 0
DEBUGF 1,"SDHCI: Command send\n"
mov dword[eax + SDHC_CMD_TRN], edx ; íà÷àëî âûïîëíåíèÿ êîìàíäû
@@:
hlt
cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
cmp dword[esi + SDHCI_SLOT.int_status], 0
jz @b
DEBUGF 1,"SDHCI: resp1=%x resp2=%x \n", [eax + SDHC_RESP1_0], [eax + SDHC_RESP3_2]
ret
@@ -63,14 +73,16 @@ endp
; ebx - argument 32 bit ecx - 0x0C register
; edx - (block_count shl 16) + block_size edi - virtual addr ; save in stack
proc send_sdhc_transfer_command
;DEBUGF 1,"SDHCI: VIRT ADDR %x\n", edi
push edx
push edi
push edi ; virt addr
sub esp, 4 ; for save ADMA2\ADMA1 table
@@:
test dword[eax + SDHC_PRSNT_STATE], 0x07
jnz @b ; check cmd_inhid_cmd + cmd_inhibit_dat + DAT Line Active
mov dword[esi + SDHCI_SLOT.virt_addr_buff],edi
; (1) Set Block Size Reg
; (2) Set Block Count Reg
mov dword[eax + SDHX_BLK_CS], edx
@@ -98,65 +110,38 @@ proc send_sdhc_transfer_command
mov dword[esp], edi
.end_set_addr:
mov dword[esi + SDHCI_CONTROLLER.int_status], 0
mov dword[esi + SDHCI_SLOT.int_status], 0
; (4) Set Transfer Mode Reg
; (5) Set Command Reg
mov dword[eax + SDHC_CMD_TRN], ecx
@@:
hlt
cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
jz @b
cmp dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.CMD_DONE
jnz .err
; wait interrupt transfer
.wait_int:
mov dword[esi + SDHCI_CONTROLLER.int_status], 0
@@:
hlt
cmp dword[esi + SDHCI_CONTROLLER.int_status], 0
jz @b;.wait_int
cmp dword[esi + SDHCI_SLOT.int_status], 0
jz .wait_int
test dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.ERROR
jnz .dat_err
test dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.DAT_DONE ; Transfer complate
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.DAT_DONE \
+ INT_STATUS.ERROR \
+ INT_STATUS.BUF_WR_RDY \
+ INT_STATUS.BUF_RD_RDY
jnz @f
mov dword[esi + SDHCI_SLOT.int_status], 0
jmp .wait_int
@@:
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
jnz .err
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.DAT_DONE
jnz .good_transfer
test dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.DMA_EVT ; DMA intr
jz .no_sdma
; SDMA add addr and set new phys addr
and dword[esp + 4], -4096
add dword[esp + 4], 4096
mov ecx, dword[esp + 4]
xchg eax, ecx
invoke GetPhysAddr
xchg eax, ecx
mov dword[eax + SDHC_SYS_ADDR], ecx
jmp .wait_int
.no_sdma:
test dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.BUF_WR_RDY ; port write
jz .no_w_port
jmp .wait_int
.no_w_port:
test dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.BUF_RD_RDY ; port read
jz .wait_int ; undefined interrupt
mov ecx, [eax + SDHC_BUFFER]
;TODO: add code for cory data in not DMA mode !!!
jmp .wait_int
.good_transfer:
DEBUGF 1,"SDHCI: GOOD COMMAND\n"
add esp, 4*4
ret
.dat_err:
DEBUGF 1,"SDHCI: ERROR CMD COMMAND\n"
add esp, 4*4
;DEBUGF 1,"SDHCI: GOOD COMMAND\n"
add esp, 4*3
ret
.err:
DEBUGF 1,"SDHCI: ERROR DAT COMMAND\n"
add esp, 4*4
DEBUGF 1,"SDHCI: ERROR DAT COMMAND %x\n", [esi + SDHCI_SLOT.int_status]
add esp, 4*3
ret
endp
@@ -180,10 +165,10 @@ macro ALL_SEND_CID {
mov ebx, [eax + SDHC_RESP3_2]
mov edx, [eax + SDHC_RESP5_4]
mov edi, [eax + SDHC_RESP7_6]
mov [esi + SDHCI_CONTROLLER.card_reg_cid], ecx
mov [esi + SDHCI_CONTROLLER.card_reg_cid + 4], ebx
mov [esi + SDHCI_CONTROLLER.card_reg_cid + 8], edx
mov [esi + SDHCI_CONTROLLER.card_reg_cid + 12], edi
mov [esi + SDHCI_SLOT.card_reg_cid], ecx
mov [esi + SDHCI_SLOT.card_reg_cid + 4], ebx
mov [esi + SDHCI_SLOT.card_reg_cid + 8], edx
mov [esi + SDHCI_SLOT.card_reg_cid + 12], edi
DEBUGF 1,"SDHCI: resp3=%x resp4=%x \n", [eax + SDHC_RESP5_4], [eax + SDHC_RESP7_6]
}
;cmd3 - Ask the card to publish a new relative address(RCA)
@@ -196,26 +181,52 @@ proc SEND_RCA
mov ecx, [eax + SDHC_RESP1_0]
shr ecx, 16
mov word[esi + SDHCI_CONTROLLER.card_reg_rca], cx
mov word[esi + SDHCI_SLOT.card_reg_rca], cx
ret
endp
; ÍÅ ÈÑÏÎËÜÇÎÂÀÒÜ, ýòî ÷òî-òî ñ ïèòàíèåì, íó íàôèã
;cmd4 - programs the DSR of all cards
;resp =
;args =
proc SET_DSR
;proc SET_DSR
;
; ret
;endp
ret
;cmd6 - for class 10 , see chapter 4.3.10
;resp = R1 + 512 bit
;args = [31] mode 0 - check function 1 - switch function
; [30:24] reserved, set "0"
; ...
; [7:4] Command System
; [3:0] Access Mode
; if function no switch, set 0xF for skip set set new mode function
; 0x80fffff1 for switch on high speed
; IN: ebx - arg
; edi - ptr to buffer on 64byte(512 bit)
proc SWITCH_FUNC
and dword[eax + SDHC_CTRL1], not 11000b ; set SDMA mode
; edi
mov edx, 512/8
mov ecx, (((6 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + CMD_TYPE.Single \
+ CMD_TYPE.Read \
+ DMA_EN
call send_sdhc_transfer_command
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
ret
endp
;cmd7 - select card for switch in transfer state
;resp = R1b , ZF - good; not ZF - error
;args = RCA in ebx
proc SELECT_CARD
mov bx, word[esi + SDHCI_CONTROLLER.card_reg_rca]
mov bx, word[esi + SDHCI_SLOT.card_reg_rca]
shl ebx, 16
mov edx, ((7 shl 8) + RESP_TYPE.R1b ) shl 16
call send_sdhc_command
test dword[esi + SDHCI_CONTROLLER.int_status],0x8000
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
ret
endp
;cmd7 - switch card in stable state
@@ -225,7 +236,7 @@ proc DESELECT_CARD
mov edx, ((7 shl 8) + RESP_TYPE.R1b ) shl 16
call send_sdhc_command
test dword[esi + SDHCI_CONTROLLER.int_status],0x8000
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
ret
endp
;cmd8 - ïðîâåðêà âîëüòàæà êàðòû äëÿ âåðñèè 2.0 è âûøå. Èñïîëüçóåòñÿ äëÿ îïðåäåëåíèÿ âåðñèè.
@@ -236,6 +247,7 @@ endp
; òî îøèáêà òàéìàóò
; Ïðèìå÷àíèå: Åñëè íå âûçûâàòü ýòó êîìàíäó òî êàðòà âûäàñò îøèáêó èíèöèàëèçàöèè ïðè ACMD41
proc SEND_IF_COUND
;DEBUGF 1,"SDHCI: CMD8 - check SDHC card\n"
mov ebx, (0001b shl 8) + 10101010b
cmp byte[eax + 0x29],1011b
@@ -253,7 +265,7 @@ endp
;args = [16:31]RCA card
proc SEND_CSD
;DEBUGF 1,"SDHCI: get CSD reg\n"
mov bx, word[esi + SDHCI_CONTROLLER.card_reg_rca]
mov bx, word[esi + SDHCI_SLOT.card_reg_rca]
shl ebx, 16
mov edx, ((9 shl 8) + RESP_TYPE.R2 ) shl 16
call send_sdhc_command
@@ -262,10 +274,10 @@ proc SEND_CSD
mov ebx, [eax + SDHC_RESP3_2]
mov edx, [eax + SDHC_RESP5_4]
mov edi, [eax + SDHC_RESP7_6]
mov [esi + SDHCI_CONTROLLER.card_reg_csd], ecx
mov [esi + SDHCI_CONTROLLER.card_reg_csd + 4], ebx
mov [esi + SDHCI_CONTROLLER.card_reg_csd + 8], edx
mov [esi + SDHCI_CONTROLLER.card_reg_csd + 12], edi
mov [esi + SDHCI_SLOT.card_reg_csd], ecx
mov [esi + SDHCI_SLOT.card_reg_csd + 4], ebx
mov [esi + SDHCI_SLOT.card_reg_csd + 8], edx
mov [esi + SDHCI_SLOT.card_reg_csd + 12], edi
DEBUGF 1,"SDHCI: resp3=%x resp4=%x \n", [eax + SDHC_RESP5_4], [eax + SDHC_RESP7_6]
ret
endp
@@ -274,7 +286,7 @@ endp
;args = [16:31]RCA card
proc SEND_CID
;DEBUGF 1,"SDHCI: get CID reg\n"
mov bx, word[esi + SDHCI_CONTROLLER.card_reg_rca]
mov bx, word[esi + SDHCI_SLOT.card_reg_rca]
shl ebx, 16
mov edx, ((10 shl 8) + RESP_TYPE.R2 ) shl 16
call send_sdhc_command
@@ -283,33 +295,33 @@ proc SEND_CID
mov ebx, [eax + SDHC_RESP3_2]
mov edx, [eax + SDHC_RESP5_4]
mov edi, [eax + SDHC_RESP7_6]
mov [esi + SDHCI_CONTROLLER.card_reg_cid], ecx
mov [esi + SDHCI_CONTROLLER.card_reg_cid + 4], ebx
mov [esi + SDHCI_CONTROLLER.card_reg_cid + 8], edx
mov [esi + SDHCI_CONTROLLER.card_reg_cid + 12], edi
mov [esi + SDHCI_SLOT.card_reg_cid], ecx
mov [esi + SDHCI_SLOT.card_reg_cid + 4], ebx
mov [esi + SDHCI_SLOT.card_reg_cid + 8], edx
mov [esi + SDHCI_SLOT.card_reg_cid + 12], edi
DEBUGF 1,"SDHCI: resp3=%x resp4=%x \n", [eax + SDHC_RESP5_4], [eax + SDHC_RESP7_6]
ret
endp
;cmd55 = switch to ACMD mode command
;resp = R1
;args = [31:16]RCA [15:0]stuff bits
; êîìàíäà ñîîáùàåò êàðòå, ÷òî ñäóäóþùàÿ êîìàíäà áóäåò acmd
;OUT: ZF - good ; NO ZF - error timeout
; WARNING!!! Ïðè îòêëþ÷åíèè êàðòû èëè äðóãèõ îøèáêàõ âûçûâàåò çàâèñàíèå
proc APP_CMD
push ecx edx ebx
dec esp
mov byte[esp], 0
@@:
inc byte[esp]
mov bx, word[esi + SDHCI_CONTROLLER.card_reg_rca]
mov bx, word[esi + SDHCI_SLOT.card_reg_rca]
shl ebx, 16
mov edx, ((55 shl 8) + RESP_TYPE.R1 ) shl 16
call send_sdhc_command
; òóò êàê ÿ ïîíèìàþ íàäî ïðîâåðÿòü ñîñòîÿíèå
cmp dword[eax + SDHC_RESP1_0], CMD55_VALID_RESP
jz .good ; ïî ñïåêå(ôèç óðîâåíü, ñòð 63(74))
test byte[esp], 0x80 ; ýòî ôëàãè APP_CMD è READY_FOR_DATA
mov ecx, dword[eax + SDHC_RESP1_0]
and ecx, CMD55_VALID_RESP ; clear all bits response
cmp ecx, CMD55_VALID_RESP ; check switch in APP mode
jz .good ; ïî ñïåêå(ôèç óðîâåíü, ñòð 63(74))
test byte[esp], 0x80 ; ýòî ôëàãè APP_CMD è READY_FOR_DATA
jz @b
.good:
lea esp, [esp + 1]
@@ -317,19 +329,65 @@ proc APP_CMD
ret
endp
;acmd41 -
;acmd6 = SET_BUS_WIDTH
;resp = R1
;args = [1:0]bus width 00 - 1bit; 10 - 4bit
; IN: ebx - arg 00-1bit 10-4bit
proc SET_BUS_WIDTH
call APP_CMD
jnz .err
mov edx, ((6 shl 8) + RESP_TYPE.R1) shl 16
call send_sdhc_command
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
.err:
ret
endp
;acmd13 = SD_STATUS
;resp = R1 AND 512 bits ˜
;args =
;acmd51 = SEND_SCR
;resp = R1 AND 64 bits
;args =
proc SEND_SCR
call APP_CMD
jnz .err
and dword[eax + SDHC_CTRL1], not 11000b ; set SDMA mode
xor ebx, ebx
lea edi, [esi + SDHCI_SLOT.card_reg_scr]
mov edx, 8;64/8
mov ecx, (((51 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + CMD_TYPE.Single \
+ CMD_TYPE.Read \
+ DMA_EN
call send_sdhc_transfer_command
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
DEBUGF 1,"SDHCI: scr=%x scr+4=%x\n", [esi + SDHCI_SLOT.card_reg_scr],\
[esi + SDHCI_SLOT.card_reg_scr + 4]
.err:
ret
endp
;acmd41 - get OCR and set voltage
;resp = R3
;args = [31]reserved bit [30]HCS(OCR[30]) [29:24]reserved bits
; [23:0]Vdd Voltage Window(OCR[23:0])
;IN: ebx - argument command
proc SD_SEND_OP_COND
;DEBUGF 1,"SDHCI: ACMD41 - get OCR\n"
call APP_CMD
jnz .err
mov edx, ((41 shl 8) + RESP_TYPE.R3 ) shl 16
call send_sdhc_command
mov ecx, [eax + SDHC_RESP1_0]
mov [esi + SDHCI_CONTROLLER.card_reg_ocr], ecx
test dword[esi + SDHCI_CONTROLLER.int_status],0x8000
mov [esi + SDHCI_SLOT.card_reg_ocr], ecx
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
.err:
ret
endp
; block read/write
@@ -339,12 +397,12 @@ endp
;resp = R1
; IN: ebx - 32bit block length
proc SET_BLOCKLEN
DEBUGF 1,"SDHCI: SET_BLOCKLEN 0x%x\n", ebx
;DEBUGF 1,"SDHCI: SET_BLOCKLEN 0x%x\n", ebx
mov edx, ((16 shl 8) + RESP_TYPE.R1 ) shl 16
call send_sdhc_command
mov ecx, [eax + SDHC_RESP1_0]
mov [esi + SDHCI_CONTROLLER.card_reg_ocr], ecx
test dword[esi + SDHCI_CONTROLLER.int_status],0x8000
mov [esi + SDHCI_SLOT.card_reg_ocr], ecx
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
ret
endp
; block read
@@ -395,7 +453,7 @@ proc WRITE_BLOCK
and dword[eax + SDHC_CTRL1], not 11000b ; set SDMA mode
mov edx, SD_BLOCK_SIZE
mov ecx, (((24 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + CMD_TYPE.Single \
+ CMD_TYPE.Read \
+ CMD_TYPE.Write \
+ DMA_EN
call send_sdhc_transfer_command
ret
@@ -412,7 +470,7 @@ proc WRITE_MULTIPLE_BLOCK
shl edx, 16
add edx, SD_BLOCK_SIZE
mov ecx, (((25 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + CMD_TYPE.Multiple \
+ CMD_TYPE.Read \
+ CMD_TYPE.Write \
+ ACMD12_EN \
+ DMA_EN
call send_sdhc_transfer_command
@@ -424,6 +482,21 @@ endp
; ret
;endp
;cmd42 - works with password and PWD register card
;resp = R1
;args = -
; IN: edi - virt addr data
proc LOCK_UNLOCK
xor ebx, ebx
mov ecx, (((42 shl 8) + DATA_PRSNT + RESP_TYPE.R1 ) shl 16) + CMD_TYPE.Single \
+ CMD_TYPE.Write \
+ DMA_EN
call send_sdhc_transfer_command
ret
endp
; SDIO mode
; Îòëè÷èÿ îò SD memory:
; - CID ðåãèñòð îòñóòñòâóåò
@@ -439,16 +512,30 @@ proc IO_SEND_OP_COND
call send_sdhc_command
mov ecx, [eax + SDHC_RESP1_0]
mov [esi + SDHCI_CONTROLLER.card_reg_ocr], ecx
test dword[esi + SDHCI_CONTROLLER.int_status], INT_STATUS.ERROR
mov [esi + SDHCI_SLOT.card_reg_ocr], ecx
test dword[esi + SDHCI_SLOT.int_status], INT_STATUS.ERROR
ret
endp
;cmd52 -
;cmd52 - Read\Write Byte. No using DAT line.
;arg =
;resp = R5
; fastcall i32 IO_RW_DIRECT(i32 arg); esi - rtp SDHCI_SLOT
; IN: ecx - data for sending to card
proc IO_RW_DIRECT
ret
push ebx
mov eax, [esi + SDHCI_SLOT.base_reg_map]
mov ebx, ecx
mov edx, ((52 shl 8) + RESP_TYPE.R5 ) shl 16
call send_sdhc_command
pop ebx
mov eax, [eax + SDHC_RESP1_0]
ret
endp
;cmd53 -
;arg =
;resp = R5 or R5b
proc IO_RW_EXTENDED
ret

View File

@@ -10,24 +10,24 @@ proc GET_SDSC_SIZE
; MULT = 2^(C_SIZE_MULT + 2)
; BLOCK_LEN = 2^LEN_BL_READ
push ecx edx
mov ecx, dword[esi + SDHCI_CONTROLLER.card_reg_csd + 4] ; C_SIZE_MULT
mov ecx, dword[esi + SDHCI_SLOT.card_reg_csd + 4] ; C_SIZE_MULT
shr ecx, 7; 39 - 32 = 7
and ecx, 111b
add ecx, 2
mov edx, dword[esi + SDHCI_CONTROLLER.card_reg_csd + 6] ; C_SIZE 48/8
mov edx, dword[esi + SDHCI_SLOT.card_reg_csd + 6] ; C_SIZE 48/8
shr edx, 6 ; 48 + 6
and edx, 0xFFF ; data in 12 low bits
inc edx
shl edx, cl
movzx ecx, byte[esi + SDHCI_CONTROLLER.card_reg_csd + 9] ; LEN_BL_READ 72/8
movzx ecx, byte[esi + SDHCI_SLOT.card_reg_csd + 9] ; LEN_BL_READ 72/8
and ecx, 0x0f
shl edx, cl
; get sectors = edx / 512 <- sectorsize for kernel
shr edx, BSF 512
mov dword[esi + SDHCI_CONTROLLER.sector_count], edx
mov dword[esi + SDHCI_CONTROLLER.sector_count + 4], 0
mov dword[esi + SDHCI_SLOT.sector_count], edx
mov dword[esi + SDHCI_SLOT.sector_count + 4], 0
pop edx ecx
ret
endp
@@ -36,14 +36,14 @@ proc GET_SDHC_SIZE
; 22 bit [40:61]
; ((C_SIZE + 1) * 512Kbyte ) / sectorsize
push ebx
mov ebx, dword[esi + SDHCI_CONTROLLER.card_reg_csd + 5]
mov ebx, dword[esi + SDHCI_SLOT.card_reg_csd + 5]
and ebx, not 0xFFC00000 ; îáíóëÿåì ñòàðøèå áèòû
mov dword[esi + SDHCI_CONTROLLER.sector_count + 4], 0
mov dword[esi + SDHCI_SLOT.sector_count + 4], 0
inc edx ; C_SIZE + 1
shl ebx, 10 ; *512Kbyte / sectorsize(512)
mov dword[esi + SDHCI_CONTROLLER.sector_count], ebx
mov dword[esi + SDHCI_SLOT.sector_count], ebx
;bt dword[esi + SDHCI_CONTROLLER.card_reg_csd + 4], 29 ; read 22 bit C_SIZE
adc dword[esi + SDHCI_CONTROLLER.sector_count + 4], 0
adc dword[esi + SDHCI_SLOT.sector_count + 4], 0
pop ebx
ret
endp
@@ -52,13 +52,13 @@ proc GET_SDUC_SIZE
; 28 bit [40:67] 40bit=5*8bit
; ((C_SIZE + 1) * 512Kbyte ) / sectorsize
push ebx
mov ebx, dword[esi + SDHCI_CONTROLLER.card_reg_csd + 5]
mov ebx, dword[esi + SDHCI_SLOT.card_reg_csd + 5]
and ebx, not 0xC0000000 ; îáíóëÿåì ñòàðøèå áèòû
inc edx
mov dword[esi + SDHCI_CONTROLLER.sector_count], ebx
mov dword[esi + SDHCI_SLOT.sector_count], ebx
shr ebx, 31-10 ; get hign LBA addr
mov dword[esi + SDHCI_CONTROLLER.card_reg_csd + 4], ebx
shl dword[esi + SDHCI_CONTROLLER.sector_count], 10
mov dword[esi + SDHCI_SLOT.card_reg_csd + 4], ebx
shl dword[esi + SDHCI_SLOT.sector_count], 10
pop ebx
ret
endp
@@ -75,51 +75,57 @@ proc add_card_disk stdcall, hd_name:dword
invoke DiskAdd, sdhci_callbacks, [hd_name], esi, 0
test eax, eax
jz .disk_add_fail
mov dword[esi + SDHCI_SLOT.disk_hand], eax
invoke DiskMediaChanged, eax, 1 ; system will scan for partitions on disk
ret
.disk_add_fail:
DEBUGF 1, "Failed to add disk\n"
ret
endp
proc del_card_disk
ret
endp
; Functions for kernel
; Ïîÿñíåíèå ê ðåàëèçàöèè ÷òåíèÿ/çàïèñè ñåêòîðîâ:
; Ýòîò äðàéâåð äîëæåí îáðàáàòûâàòü SD êàðòû ðàçíûõ âåðñèé,
; SDIO êàðòû(â òîì ÷èñëå è ñîâìåù¸ííûå) è MMC(eMMC) êàðòû.
; Âî âñåõ âàðèàíòàõ êàðò ÷òåíèå è çàïèñü ïðîèñõîäèòü ïðè ïîìîùè
; îäíèõ è òåõ æå êîìàíä(17,18,24,25), ïðè ÷¸ì ïîñëåäîâàòåëüíîñòü
; îñòàëüíûõ êîìàíä òàêæå ñõîæà.
; Ïî ýòîìó ðàçëè÷àòüñÿ áóäóò òîëüêî ìåòîäû ðàáîòû ñ êîíòðîëëåðîì,
; ýòî ëèáî èñïîëüçîâàíèå SDMA èëè ADMA2 èëè, åñëè ýòîãî íåò, òî
; ðàáîòà ÷åðåç ïîðò áóôåðà
proc sdhci_read stdcall pdata: dword, buffer: dword, startsector: qword, numsectors_ptr:dword
pusha
mov esi, [pdata]
mov eax, [esi + SDHCI_CONTROLLER.base_reg_map]
mov eax, [esi + SDHCI_SLOT.base_reg_map]
mov ebx, dword[startsector]
mov edx, [numsectors_ptr]
mov edx, [edx]
mov edi, [buffer]
DEBUGF 1,"SDHCI: read sector=%x num=%x \n", ebx, edx
;DEBUGF 1,"SDHCI: read sector=%x num=%x \n", ebx, edx
cmp edx, 1
ja .multiple
; send CMD 17
call READ_SIGLE_BLOCK
popa
mov eax, 0
ret
.multiple:
push edx ebx edi
@@:
mov edx, dword[esp + 8]
mov ebx, dword[esp + 4]
mov edi, dword[esp]
cmp dword[esp + 8], 0xFFFF
jbe .send
; send CMD 18
mov edx, 0xFFFF
sub dword[esp + 8], edx
add dword[esp + 4], edx
shl edx, 9
add dword[esp], edx
shr edx, 9
.send:
push edx
call READ_MULTIPLE_BLOCK
pop edx
cmp edx, dword[esp + 8]
jnz @b
pop edi ebx edx
popa
mov eax, 0
@@ -128,26 +134,44 @@ endp
proc sdhci_write stdcall pdata: dword, buffer: dword, startsector: qword, numsectors_ptr:dword
pusha
mov esi, [pdata]
mov eax, [esi + SDHCI_CONTROLLER.base_reg_map]
mov eax, [esi + SDHCI_SLOT.base_reg_map]
mov ebx, dword[startsector]
mov edx, [numsectors_ptr]
mov edx, [edx]
mov edi, [buffer]
DEBUGF 1,"SDHCI: write sector=%x num=%x \n", ebx, edx
;DEBUGF 1,"SDHCI: write sector=%x num=%x \n", ebx, edx
cmp edx, 1
ja .multiple
; send CMD 24
call WRITE_BLOCK
popa
mov eax, 0
ret
.multiple:
push edx ebx edi
@@:
mov edx, dword[esp + 8]
mov ebx, dword[esp + 4]
mov edi, dword[esp]
cmp dword[esp + 8], 0xFFFF
jbe .send
; send CMD 25
mov edx, 0xFFFF
sub dword[esp + 8], edx
add dword[esp + 4], edx
shl edx, 9
add dword[esp], edx
shr edx, 9
.send:
push edx
call WRITE_MULTIPLE_BLOCK
pop edx
cmp edx, dword[esp + 8]
jnz @b
pop edi ebx edx
popa
mov eax, 0
@@ -166,9 +190,9 @@ proc sdhci_querymedia stdcall, pdata, mediainfo
mov edx, [pdata]
mov [eax + DISKMEDIAINFO.Flags], 0
mov [eax + DISKMEDIAINFO.SectorSize], SD_BLOCK_SIZE
mov ecx, dword[edx + SDHCI_CONTROLLER.sector_count]
mov ecx, dword[edx + SDHCI_SLOT.sector_count]
mov dword [eax + DISKMEDIAINFO.Capacity], ecx
mov ecx, dword[edx + SDHCI_CONTROLLER.sector_count + 4]
mov ecx, dword[edx + SDHCI_SLOT.sector_count + 4]
mov dword [eax + DISKMEDIAINFO.Capacity + 4], ecx
pop edx ecx
xor eax, eax
@@ -186,11 +210,11 @@ sdhci_callbacks:
dd 0 ;sdhci_close ; close function -
dd 0 ; closemedia function
dd sdhci_querymedia ; +
dd sdhci_read ; -
dd sdhci_write ; -
dd sdhci_read ; +
dd sdhci_write ; +
dd 0 ; no flush function
dd 0 ; use default cache size
.end:
sdcard_disk_name: db 'sdcard00',0
mmccard_disk_name: db 'MMC00',0
; ; /sdhciXXXS/1
;sdhci_disk_name: db 'sdhci0000',0,0 ; xxx - number of controller
; ; s - number slot in select controller

1127
sdhci.asm

File diff suppressed because it is too large Load Diff

BIN
sdhci.sys

Binary file not shown.

118
sdio-test.asm Normal file
View File

@@ -0,0 +1,118 @@
format PE native
entry START
use32
DEBUG = 1
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1 ; 1 = verbose, 2 = errors only
section '.flat' code readable writable executable
include 'drivers/proc32.inc'
include 'drivers/struct.inc'
include 'drivers/macros.inc'
include 'drivers/peimport.inc'
include 'drivers/fdo.inc'
struct IMPORT_SDIO_FUNC
reg_sdio rd 1
unreg_sdio rd 1
scan_dev rd 1
cmd52 rd 1
cmd53 rd 1
ends
proc START c, state:dword, cmdline:dword
cmp [state], DRV_ENTRY
jne .stop_drv
DEBUGF 1,"SDIO-TEST: Loading driver\n"
invoke GetService, sdhci_str
DEBUGF 1,"SDIO-TEST: Get service %x\n", eax
test eax, eax
jz .err
mov [sdhci_handle], eax
; get import sdio func
invoke ServiceHandler, ioctl_get_export
; reg sdio
test eax, eax
jnz .err
DEBUGF 1,"SDIO-TEST: import table %x\n", [ptr_import_table]
mov eax, [ptr_import_table]
stdcall [eax + IMPORT_SDIO_FUNC.reg_sdio], drv_table_func
DEBUGF 1,"SDIO-TEST: Reg sdio %x\n", eax
test eax, eax
jz .err
mov [sdio_hand], eax
; TODO: scan dev
; reg driver
invoke RegService, drv_name, 0
ret
.stop_drv:
; unreg
.err:
xor eax, eax
ret
endp
proc check_dev stdcall ptr_slot: dword
push esi ebx edi
; Âûâîä ñîîáùåíèÿ îá îáíàðóæåíèè SDIO óñòðîéñòâà
DEBUGF 1,"SDIO-TEST: Check SDIO dev\n"
mov esi, [ptr_slot]
mov edi, [ptr_import_table]
; âûâîä âåðñèè SDIO èíòåðôåéñà
mov ecx, 0
call [edi + IMPORT_SDIO_FUNC.cmd52]
mov ecx, eax
shr al, 4
and cl, 0x0F
and al, 0x0f
DEBUGF 1,"SDIO-TEST: SDIO ver= %d CCCR ver = %d\n", al, cl
; âûâîä êëàññà FBR1
mov ecx, (0x100 shl 9)
call [edi + IMPORT_SDIO_FUNC.cmd52]
and al, 0x0f
DEBUGF 1,"SDIO-TEST: FBR interface code= %d\n", cl
pop edi ebx esi
mov eax,[ptr_slot]
ret
endp
proc int_handle stdcall pdata: dword
ret
endp
proc close_dev stdcall pdata: dword
DEBUGF 1,"SDIO-TEST: Close sdio device\n"
ret
endp
ioctl_get_export:
sdhci_handle: dd 0
dd 3
dd 0
dd 0
dd ptr_import_table
dd 4
ptr_import_table: dd 0
sdio_hand: dd 0
PDATA_STRUCT: dd 0
drv_table_func:
dd check_dev
dd int_handle
dd close_dev
sdhci_str: db 'SDHCI',0
drv_name: db 'SDIO-TEST',0
align 4
data fixups
end data
include_debug_strings

BIN
sdio-test.sys Normal file

Binary file not shown.

83
sdio.inc Normal file
View File

@@ -0,0 +1,83 @@
;; Copyright (C) 2022, Michael Frolov(aka Doczom)
;; SDIO subsystem SDHCI driver. Base functons for working.
; Ñïèñîê âíåøíèõ SDIO ìîäóëåé ÿäðà
sdio_drv_list:
dd sdio_drv_list
dd sdio_drv_list
struct SDIO_SERVICE
next rd 1
prev rd 1
sdio_func rd 1 ;ptr
ends
struct SDIO_SERVICE_FUNC
check_fbr rd 1
; stdcall void* check_fbr(SDHCI_SLOT* slot_str)
; Called for find driver to this card. Function rerturning
; DWORD or zero. Return value - pdata for calling func
int_handler rd 1
; stdcall int int_handler(void* pdata)
; This function calling in sdhc_irq() when geting
; card interrupt
close_card rd 1
; stdcall int close_card(void* pdata)
; Calling when card removed.
ends
export_sdio_api:
dd REG_SDIO_SERVICE
dd UNREG_SDIO_SERVICE
dd SCAN_SDIO_DEV
dd IO_RW_DIRECT ;cmd52
dd IO_RW_EXTENDED ; cmd53
proc REG_SDIO_SERVICE stdcall sdio_func: dword
; alloc new item list
mov eax, sizeof.SDIO_SERVICE
invoke Kmalloc
test eax, eax
jz .exit
mov ecx, [sdio_func]
mov [eax + SDIO_SERVICE.sdio_func], ecx
cli
mov ecx, [sdio_drv_list]
mov [eax], ecx
mov [eax + SDIO_SERVICE.prev], sdio_drv_list
mov [ecx + SDIO_SERVICE.prev], eax
mov [sdio_drv_list], eax
sti
.exit:
ret
endp
proc UNREG_SDIO_SERVICE stdcall sdio_hand: dword
; del in list
mov eax, [sdio_hand]
mov edx, [eax]
mov ecx, [eax + SDIO_SERVICE.prev]
mov [edx + SDIO_SERVICE.prev], ecx
mov [ecx], edx
; find all slots, using this service
; free struct
mov eax, [sdio_hand]
invoke Kfree
ret
endp
proc SCAN_SDIO_DEV stdcall sdio_hand: dword
ret
endp