📄 usbmisc.asm
字号:
; 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 + -