Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

Obsah / Ovladače / DMA / Globální funkce ovladače řadiče DMA

Zdrojový kód: DRIVERS\SYSTEM\DMA.ASM


Globální funkce ovladače řadiče DMA

Globální funkce ovladače řadiče DMA se provádějí s implicitním ovladačem DMA řadiče, jehož popisovač je uchován v proměnné DMADevice.


; -----------------------------------------------------------------------------
;                  DMA global function: Get DMA channel info
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
; OUTPUT:	ECX = number of channels
;		EDX = flags (see Channel info flags), 0=invalid channel
;		CY = invalid channel number (ECX is valid, EDX = 0)
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMAInfo:	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Info	; get DMA channel info
		pop	ebx		; pop EBX
		ret

Funkce DMAInfo poskytne informace o kanálu DMA, jehož číslo je funkci předáno v registru EAX. Na výstupu z funkce je navrácen v registru ECX počet kanálů DMA a v registru EDX příznaky (nebo jejich kombinace) s těmito hodnotami: DMAINFO_VALID kanál je platný, DMAINFO_USED kanál je používán (vlastněn), DMAINFO_RUNNING na kanálu probíhá přenos dat, DMAINFO_8BIT kanál je 8-bitový (jinak 16-bitový), DMAINFO_BOUND blok dat nesmí překročit hranici 64 KB (jinak 128 KB), DMAINFO_ALIGN adresa musí být zarovnána na slovo, DMAINFO_16M limitace na nižších 16 MB paměti. V případě neplatného čísla DMA kanálu navrátí funkce příznak CY a obsah registru EDX je nulový. Počet kanálů navrácený v registru ECX je i v případě chyby platný. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                 DMA global function: Allocate DMA channel
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
; OUTPUT:	CY = cannot allocate, channel allready used
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMAAlloc:	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Alloc ; allocate DMA channel
		pop	ebx		; pop EBX
		ret

Funkce DMAAlloc slouží k alokaci (přivlastnění) DMA kanálu. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA, který má být alokován. V případě chyby (kanál je již alokován nebo zadáno neplatné číslo kanálu) navrátí funkce příznak chyby CY. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                   DMA global function: Free DMA channel
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
; OUTPUT:	CY = invalid channel number or it is already free or it is
;			still running
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMAFree:	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Free	; free DMA channel
		pop	ebx		; pop EBX
		ret

Funkce DMAFree slouží k dealokaci (uvolnění) DMA kanálu. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA, který má být uvolněn. V případě chyby (kanál není alokován nebo zadáno neplatné číslo kanálu nebo probíhá přenos dat) navrátí funkce příznak chyby CY. Není kontrolováno, zda kanál uvolňuje stejný vlastník, který si zažádal o jeho alokaci. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                   DMA global function: Start DMA transfer
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
;		ECX = number of bytes (cannot be 0, max. 64K, word aligned)
;		EDX = system address (word aligned)
;		ESI = DMA direction (DMADIR_READ, DMADIR_WRITE, DMADIR_VERIFY)
; OUTPUT:	CY = invalid argument or channel is already running
; NOTES:	Function translates system address to physical address.
;		Block cannot cross 64K boundary, size and address must be word
;			aligned, size can be max. 64 KB and transfered block 
;			must be in lower 16MB of physical RAM.
; 		It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMAStart:	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Start ; start DMA transfer
		pop	ebx		; pop EBX
		ret

Funkce DMAStart odstartuje DMA přenos dat. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA, na kterém má být přenos odstartován. V registru ECX je nastaven počet bajtů k přenosu, v registru EDX adresa paměti v systému (tedy ne fyzické paměti) a v registru ESI je příznak směru přenosu: DMADIR_READ čtení ze zařízení, DMADIR_WRITE zápis na zařízení a DMADIR_VERIFY je verifikace dat ze zařízení. Současná verze ovladače má následující omezení: blok dat nesmí překrýt hranici adres 64 KB, maximální velikost bloku 64 KB, minimální velikost bloku 2 B, velikost musí být zarovnaná na slovo, adresa musí být zarovnaná na slovo a lze používat pouze nižších 16 MB fyzické paměti (blok získaný pomocí funkce DMAMemAlloc). V případě neplatného zadání některého z argumentů navrátí funkce příznak chyby CY. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                   DMA global function: Stop DMA transfer
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
; OUTPUT:	CY = invalid channel number or channel is not running
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMAStop: 	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Stop	; stop DMA transfer
		pop	ebx		; pop EBX
		ret

Funkce DMAStop zastaví DMA přenos dat. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA, na kterém má být přenos zastaven. V případě neplatného čísla kanálu nebo pokud přenos nebrobíhá navrátí funkce příznak chyby CY. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;               DMA global function: Get remaining transfer size
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
; OUTPUT:	CY = invalid channel number or channel is not running
;		ECX = remaining bytes (0 on error)
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMARemain: 	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Remain ; get remaining transfer size
		pop	ebx		; pop EBX
		ret

Funkce DMARemain zjistí zbývající počet bajtů k přenosu. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA, ze kterého je potřeba zjistit počet zbylých dat. Na výstupu funkce je v registru ECX navrácen počet zbývajících bajtů k přenosu. Hodnota 0 indikuje ukončení přenosu. Při prvním volání (pokud kanál nebyl dosud inicializován) může být navrácena hodnota 1. V případě neplatného čísla kanálu nebo pokud přenos neprobíhá navrátí funkce příznak chyby CY a registr ECX je vynulován. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;               DMA global function: Check if channel is still running
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
; OUTPUT:	CY = invalid channel number or channel is not running
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

DMACheck: 	push	ebx		; push EBX
		mov	ebx,[DMADevice]	; EBX <- current DMA device
		DEVFNCLOCKC DEVDMA_Check ; check if channel is still running
		pop	ebx		; pop EBX
		ret

Funkce DMACheck zjistí, zda probíhá přenos dat na kanálu. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA, na kterém má být přenos dat zjištěn. Na výstupu funkce je navrácen příznak CY v případě neplatného čísla kanálu nebo není-li kanál přidělen nebo pokud přenos dat neprobíhá. Při prvním volání (pokud kanál nebyl dosud inicializován) může být navrácen příznak přenosu dat (NC). Funkce se používá jako rychlejší varianta ke zjištění přenosu dat než DMARemain. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;               DMA global function: Wait until transfer stops
; -----------------------------------------------------------------------------
; INPUT:	EAX = channel number
;		EBX = minimal time in ms (0=immediately)
;		ECX = maximal time in ms (time-out, 0=immediately)
;		EDX = delta time in ms of tests until stops (1 minimal)
; OUTPUT:	CY = invalid channel number or it is not running or time-out
; NOTES:	It locks fast spin-lock of device interface.
; -----------------------------------------------------------------------------

; ------------- Push registers

DMAWait:	push	ebx		; push EBX
		push	ecx		; push ECX (it must be last)

; ------------- Check if channel is valid, used and running

		push	edx		; push EDX
		call	DMAInfo		; get DMA channel info
		jc	DMAWait2	; invalid channel
		and	dl,DMAINFO_RUNNING+DMAINFO_USED	; flags
		cmp	dl,DMAINFO_RUNNING+DMAINFO_USED	; is used + running?
DMAWait2:	pop	edx		; pop EDX
		jc	DMAWait8	; invalid channel or not running
		pop	ecx		; pop ECX
		push	ecx		; push ECX

; ------------- Wait for a while

DMAWait3:	push	eax		; push EAX
		mov	eax,ebx		; EAX <- time in ms
		cmp	eax,ecx		; check time-out
		jb	DMAWait4	; time-out is OK
		mov	eax,ecx		; EAX <- limit time-out
DMAWait4:	or	eax,eax		; any time?
		jz	DMAWait6	; no time
		call	Sleep		; sleep for a while
DMAWait6:	sub	ecx,ebx		; check time-out
		pop	eax		; pop EAX
		jb	DMAWait8	; time-out
		mov	ebx,edx		; EBX <- delta time

; ------------- Check if channel is running

		call	DMACheck	; check if channel is running
		jc	DMAWait7	; transfer stops

; ------------- Time-out is 0

		or	ecx,ecx		; is time-out 0 ?
		jnz	DMAWait3	; continue waiting
DMAWait7:	cmc			; CY = error flag

; ------------- Pop registers

DMAWait8:	pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		ret

Funkce DMAWait zajistí čekání na ukončeí DMA přenosu v případě, že zařízení nepodporuje indikaci ukončení přenosu pomocí přerušení. Na vstupu funkce obsahuje registr EAX číslo kanálu DMA. Registr EBX obsahuje minimální čas v [ms], po který bude čekáno na ukončení přenosu. Do uplynutí minimálního času nebude prováděn test ukončení DMA přenosu. Minimální čas může být 0, v tom případě se první test ukončení přenosu provede okamžitě. Registr ECX obsahuje maximální čas doby čekání na ukončení přenosu v [ms]. Pokud do požadované maximální doby nebude přenos ukončen, funkce se ukončí s navrácením příznaku chyby CY. Je-li obsah registr ECX nulový a současně obsah registru EBX je nula, funkce pouze otestuje ukončení přenosu a ihned se ukončí. Registr EDX obsahuje interval mezi jednotlivými testy ukončení přenosu v [ms]. Interval musí být minimálně 1 ms. V případě neplatného čísla kanálu nebo pokud přenos nebrobíhá nebo pokud přenos nebyl ukončen do uplynutí maximálního času navrátí funkce příznak chyby CY. Funkce uzamyká ovladač pomocí rychlého zámku.


Obsah / Ovladače / DMA / Globální funkce ovladače řadiče DMA