⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbmisc.asm

📁 dos下的USB源码(包括UHCI
💻 ASM
📖 第 1 页 / 共 4 页
字号:
; Modified:	Nothing
;
; Referrals:
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMisc_SpeakerBeep	PROC NEAR SYSCALL PUBLIC


	test	dUSBInitFlag, INIT_FLAG_BEEP_ENABLE
	jz	USB_SkipBeep		; Branch if beeps are disabled

	mov	al, 10110110b		; Initialize timer #2
	out	43h, al
	mov	al, bl			; Frequency low byte
	out	42h, al
	out	42h, al			; Frequency high byte
	in	al, 61h			; on speaker bit

	push	ax

	or	al, 00000011b		; Speaker gate, speaker bit
	out	61h, al

	mov	ax, cx
	call	USBMisc_FixedDelay

	pop	ax			; Reset speaker bit

	out	61h, al

USB_SkipBeep:
	ret
USBMisc_SpeakerBeep	ENDP

;<AMI_GHDR_START>
;----------------------------------------------------------------------------
; Name:		USB_MEMORY_POOL_ARCHITECTURE
;
; Type:		Architecture
;
; Description:	USB working memory requirement is satisfied by having a
;		memory pool with predefined length of blocks (in our case
;		it will be 32 bytes). Group of blocks can be allocated and
;		freed. Maximum number of blocks allocated or freed at a time
; 		should be less than or equal to 32. This limitation is
;		imposed because the status bits are manipulated in 32 bit
;		double words. Each block will have a corresponding status
;		bit which indicates whether the block is free or allocated.
;		Blocks can be allocated and freed at any order.
;
;----------------------------------------------------------------------------
;<AMI_GHDR_END>

	PUBLIC	USBMem_Code_Start
USBMem_Code_Start		LABEL		BYTE

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_Init
;
; Description:	This routine initializes the memory pool and sets the
;		memory block status bits to available
;
; Input: 	Nothing
;
; Output: 	Nothing
;
; Modified:	EAX
;
; Referrals:	USBMem_Alloc, USBMem_Free, USB_MEMORY_POOL_ARCHITECTURE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_Init		PROC	NEAR SYSCALL PUBLIC USES ES CX DI
	pushf
	push	eax

; Initialize the memory pool with all zeros
	push	ds
	pop	es
	mov	di, MEMORY_POOL_OFFSET
	mov	cx, (USB_MEM_POOL_SIZE SHR 2)	; Pool size in dwords
	cld
	xor	eax, eax
	rep	stosd

; Initialize the memory pool status bits to available
	mov	di, OFFSET MemoryBlockStatus
	mov	cx, (USB_MEM_STATUS_DATA_SIZE SHR 2) ; Size in dwords
	not	eax				; Set to 0FFFFFFFFh
	rep	stosd

	pop	eax
	popf
	ret
USBMem_Init		ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_Alloc
;
; Description:	This routine allocates blocks of memory from the global
;		memory bool
;
; Input: 	AL	Number of 32 byte blocks needed (MAX 32)
;
; Output: 	AX	Start offset to the allocated block (0 on error)
;		ZR	On error
;		NZ	On success
;
; Modified:	AX
;
; Referrals:	USBMem_Free, USB_MEMORY_POOL_ARCHITECTURE
;
; Notes:	This routine allocates continuous memory blocks starting
;		from the address AX. DS should point to the global data
;		area
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_Alloc		PROC	NEAR SYSCALL PUBLIC USES BX CX DX SI

	LOCAL	wStartBlock:WORD

	pushf
	cli

	mov	cl, al		; Number of blocks
; Get free block offset
	call	USBMem_LocateFreeBlocks	; AL - Number of blocks
	cmp	ax, 0FFFFh
	je	UMA_Exit
	mov	si, ax

; Change the block status to not available
; SI	Starting block number
; CL	Number of blocks needed
; CH	USB_MEM_ALLOCATED
	mov	ch, USB_MEM_ALLOCATED
	call	USBMem_ChangeBlockStatus

; Free block found. Get the address of it
	mov	ax, si
	mov	dx, USB_MEM_BLK_SIZE
	mul	dx
	add	ax, MEMORY_POOL_OFFSET

UMA_Exit:
	popf
	or	ax, ax
	ret
USBMem_Alloc		ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_Free
;
; Description:	This routine frees the chunk of memory allocated using
;		the USBMem_Alloc call
;
; Input: 	AL	Number of 32 byte blocks to be freed
;		BX	Pointer to the memory block to be freed
;
; Output: 	Nothing
;
; Modified:	Nothing
;
; Referrals:	USBMem_Alloc, USB_MEMORY_POOL_ARCHITECTURE
;
; Notes:	This routine frees the continuous memory blocks starting
;		from the address wMemBlock.
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_Free	PROC NEAR SYSCALL PUBLIC USES EAX BX CX DX SI DI,

	or	bx, bx
	jz	UMF_ImmediateExit

	pushf
	cli

; Save AL in DL
	mov	dl, al

	mov	di, bx
	mov	si, bx
; Find the starting block number
	sub	si, MEMORY_POOL_OFFSET
	shr	si, USB_MEM_BLK_SIZE_SHIFT	; Divide by USB_MEM_BLK_SIZE
	cmp	si, USB_MEM_NUMBER_OF_BLK
	jae	UMF_Error

; Clear the memory area
	push	eax
	push	cx
	push	es

	push	ds
	pop	es
	movzx	cx, dl
	shl	cx, (USB_MEM_BLK_SIZE_SHIFT)
	shr	cx, 2				; Size in DWORDs
	xor	eax, eax
	cld
	rep	stosd

	pop	es
	pop	cx
	pop	eax

	mov	cl, dl
; SI	Starting block number
; CL	Number of blocks needed
; CH	USB_MEM_FREE
	mov	ch, USB_MEM_FREE
	call	USBMem_ChangeBlockStatus
	jmp	short UMF_Exit

UMF_Error:

UMF_Exit:
	popf
UMF_ImmediateExit:
	ret
USBMem_Free	ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_AllocOne
;
; Description:	This routine allocates one block of memory from the global
;		memory bool
;
; Input: 	Nothing
;
; Output: 	AX	Start offset to the allocated block (0 on error)
;		ZR	On error
;		NZ	On success
;
; Modified:	AX
;
; Referrals:	USBMem_Alloc, USBMem_Free, USB_MEMORY_POOL_ARCHITECTURE
;
; Notes:	This routine allocates continuous memory blocks starting
;		from the address AX. DS should point to the global data
;		area
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_AllocOne		PROC	NEAR SYSCALL PUBLIC

	mov	al, 1
	call	USBMem_Alloc

	ret
USBMem_AllocOne		ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_FreeOne
;
; Description:	This routine frees a block of memory allocated using
;		the USBMem_Alloc call
;
; Input: 	BX	Pointer to the memory block to be freed
;
; Output: 	Nothing
;
; Modified:	Nothing
;
; Referrals:	USBMem_Alloc, USB_MEMORY_POOL_ARCHITECTURE
;
; Notes:	This routine frees the continuous memory blocks starting
;		from the address wMemBlock.
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_FreeOne		PROC NEAR SYSCALL PUBLIC USES AX

	mov	al, 1
	call	USBMem_Free

	ret
USBMem_FreeOne	ENDP


;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_LocateFreeBlocks
;
; Description:	This routine finds continuous free blocks (Maximum 32 blocks)
;
; Input: 	CL	Number of blocks to find
;
; Output: 	AX - Block offset, 0FFFFh on error
;
; Modified:	EAX
;
; Referrals:	USBMem_Alloc, USBMem_Free, USB_MEMORY_POOL_ARCHITECTURE
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_LocateFreeBlocks		PROC NEAR SYSCALL USES EBX EDX ECX SI

		LOCAL	dMask:DWORD, bBitPosition:BYTE
; Form the mask bit pattern
	xor	eax, eax
	not	eax
	shl	eax, cl
	not	eax
	mov	dMask, eax			; Mask

; Load the start of memory allocation status
	mov	si, OFFSET MemoryBlockStatus
	mov	cx, (USB_MEM_STATUS_DATA_SIZE SHR 2)	; Size in Dwords

	lodsd				; Current double word
ULFB_CheckNextDW:
	xchg	eax, ebx
	lodsd				; Next double word
	xchg	eax, ebx


	push	cx
	mov	cx, 32			; Check the 32 bit shifts
ULFB_CheckAfterBitShift:
	push	eax			; Save current double word
	and	eax, dMask		; Mask off unwanted bits
	cmp	eax, dMask		; Compare for necesary bit
	pop	eax
	je	ULFB_MemoryFound	; STACK HAS ECX VALUE
	shrd	eax, ebx, 1
	shr	ebx, 1
	loop	ULFB_CheckAfterBitShift

	pop	cx
	loop	ULFB_CheckNextDW

; Memory not found return with error
	mov	ax, 0FFFFh
	jmp	short ULFB_Exit

ULFB_MemoryFound:
; NOTE: There is a word in the stack (CX)
; Set SI to point to the correct memory offset
	mov	al, 32
	sub	al, cl
	movzx	ebx, al			; EBX - Starting bit position
					;	in the current DWORD


	pop	cx		; Adjust stack

	mov	ax, (USB_MEM_STATUS_DATA_SIZE SHR 2)	; Size in Dwords
	sub	ax, cx
	movzx	eax, ax

	shl	eax, 5
	add	eax, ebx

ULFB_Exit:
	ret
USBMem_LocateFreeBlocks		ENDP

;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMem_ChangeBlockStatus
;
; Description:	This routine changes the status bits for the specified
;		number of blocks starting from the specified block number
;
; Input: 	The following are the inputs to the function
;		SI	Starting offset of the block
;		CL	Number of 32 byte blocks needed
;		CH	Status to be updated
;
; Output: 	Nothing
;
; Modified:	Nothing
;
; Referrals:	USBMem_Alloc, USBMem_Free, USB_MEMORY_POOL_ARCHITECTURE
;
; Notes:	Memory block status is a bit stream with each bit
;		representing a block. If the bit is 1 then the block is free
;		otherwise it is allocated. Maximum 32 blocks can be allocated
;		or freed at a time. Status bits are manipulated in double
;		words (aka dword). As status bits can be in two dwords,
;		the algorithm always work on two consecutive dwords.
;		Let
;		    The first dword be  X = x4x3x2x1 and
;		    The second dword be Y = y4y3y2y1
;			(each x or y representing a byte)
;		Number of status bits to be updated can be within X or Y
;		or it can be in both X & Y.
;		If starting bit position + number of blocks is greater than
;		32 then status bits are in two dwords.
;		Let us assume we have to update x1y4. Then the working dword
;		Z=x3x2x1y4 is formed and x1y4 inside it is updated. Finally
;		both the modified dwords are updated back into the memory.
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMem_ChangeBlockStatus	PROC NEAR SYSCALL USES EAX EBX CX DX SI

	LOCAL	dMask:DWORD, bBitPosition:BYTE

; Form the mask bit pattern
	xor	eax, eax
	not	eax
	shl	eax, cl
	not	eax
	mov	dMask, eax		; Mask

	movzx	eax, si
; AX - Block offset
	mov	bBitPosition, al
	and	bBitPosition, 01Fh	; Bit position inside the dword
	shr	eax, 5			; AX = Dword number

; Get the double word offset
	shl	ax, 2			; Multiply by 4 (in bytes)
	add	ax, OFFSET MemoryBlockStatus
	mov	dx, ax
	mov	si, ax

; bBitPosition	Starting bit position in the DWORD of the free blocks
; CL		Number of blocks
; dMask		Bit mask
; SI		Pointer to the first DWORD of the memory block status
; CH		Status to be updated

; Form the 32bit working bit mask which will be updated.  The 32bit working
; bit mask is formed from the two consecutive double words. The algorithm to
; extract the 32bit working bit pattern is as follows:
;   * Check whether block status bit pattern crosses double word boundary
;          If starting bit + number of bits to be updated > 32 then
;          the block status bit pattern crosses double word.
;          That is, (bBitPosition+bNumBlocks) > 32.
;			Let N = ((bBitPosition + 1) + bNumBlocks) - 32
;          (bBitPosition+1) is used as bBitPosition is a zero based value.
;          If N is positive then the bit pattern crosses double word boundary
;   * If the working bit pattern crosses dword boundary then the new
;     dword is formed by shifting the 64bit value to right. Number of shifts
;     needed is calculated as follows :
;	Number of shifts M = bBitPosition - N
;         where bBitPosition = Starting bit position in the dword
;         and   N            = Number of bits in the second dword

	mov	al, bBitPosition
	inc	al			; To take care of 0 based numbering
	add	al, cl

; Form the new bit pattern
	sub	al, 32			; AL = N
	jns	UMCS_SetPattern
	xor	al, al
UMCS_SetPattern:
	mov	cl, al			; CL = N
	sub	bBitPosition, al	; bBitPosition = M

	push	cx
; Position mask pattern at right bit position
	mov	cl, bBitPosition			; CL = M
	shl	dMask, cl
	not	dMask
	pop	cx

; Load the two double words
	lodsd
	xchg	eax, ebx
	lodsd
	xchg	eax, ebx
	shrd	eax, ebx, cl
	shr	ebx, cl

; Set the bits to allocated
	and	eax, dMask
; Update the bit pattern
	cmp	ch, USB_MEM_ALLOCATED
	je	UMCS_BitUpdated		; Already updated
; Make the status as freed
	not	dMask
	or	eax, dMask
UMCS_BitUpdated:

	shld	ebx, eax, cl
	shl	eax, cl

; Write back the registers to memory
	sub	si, 4
	mov	DWORD PTR [SI], ebx
	sub	si, 4
	mov	DWORD PTR [SI], eax

	ret
USBMem_ChangeBlockStatus	ENDP

	PUBLIC	USBMem_Code_End
USBMem_Code_End		LABEL		BYTE


IF	MKF_USB_OHCI OR MKF_USB_EHCI

IF	MKF_USB_MODE EQ 1
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
; Procedure:	USBMiscDwordReadMemReg
;
; Description:	This function reads a double word value from the host
;		controller memory space address
;
; Input: 	wMemOffs	Register offset to read
;		pHCStruc	HCStruc structure
;        	DS = ES		USB data area
;
; Output: 	EAX		Value read from register
;
; Modified:	EAX
;
; Referrals:	HCStruc
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>

USBMiscDwordReadMemReg	PROC NEAR C PUBLIC USES ESI EBX DS,
					pHCStruc:NEAR, wMemOffs:DWORD

	pushf
	cli
	mov	ebx, wMemOffs
	mov	si, pHCStruc
	add	ebx, (HCStruc PTR [si]).dBaseAddress

	push	ds
; The following routine modifies AX. If AX is non-zero then it modifies
; DS and EBX also.
; SI	HCStruc pointer
	call	USBMiscCheckAndUpdateBaseAddress
	or	ax, ax

	jz	ODRM_NotOS

	add	ebx, wMemOffs
	mov	eax, DWORD PTR ds:[bx]
	jmp	SHORT ODRM_DataRead

ODRM_NotOS:
	push	0
	pop	ds
	mov	eax, DWORD PTR ds:[ebx]

ODRM_DataRead:

	pop	ds

; Restore the base address to the original value
; SI	HCStruc pointer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -