;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; RDOS operating system ; Copyright (C) 1988-2000, Leif Ekblad ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. The only exception to this rule ; is for commercial usage in embedded systems. For information on ; usage in commercial embedded systems, contact embedded@rdos.net ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ; ; The author of this program may be contacted at leif@rdos.net ; ; EHCI.ASM ; EHCI-based USB host controller driver ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INCLUDE ..\driver.def INCLUDE ..\os.def INCLUDE ..\os.inc INCLUDE ..\user.def INCLUDE ..\user.inc INCLUDE ..\os\protseg.def INCLUDE ..\pcdev\pci.inc INCLUDE usb.inc MAX_USB_DEVICES = 16 ; ehc_flags EHC_PORT_IND = 1 EHC_COMPANION = 2 EHC_PORT_POWER = 4 hccap STRUC hcp_CAPLEN DB ? hcp_resv DB ? hcp_HCIVERSION DW ? hcp_HCSPARAMS DW ?,? hcp_HCCPARAMS DD ? hcp_ROUTE DB ? hccap ENDS hc_reg STRUC HcCommand DD ? HcStatus DD ? HcInterruptEnable DD ? HcFrameIndex DD ? HcSegmentSelector DD ? HcPeriodicListBase DD ? HcAsyncList DD ? HcResv DD 9 DUP(?) HcConfig DD ? HcPortSc DD ? hc_reg ENDS ehci_func_sel STRUC usb_dev_base usb_dev_struc <> ehc_reg_sel DW ? ehc_map_sel DW ? ehc_map_linear DD ? ehc_linear DD ? ehc_phys DD ? ehc_op_offs DB ? ehc_flags DW ? ehc_ports DB ? ehc_debug_port DB ? ehc_comp_ports DB ? ehc_section section_typ <> ehc_pipe_list DW ? ehc_async_head_va DD ? ehc_spinlock spinlock_typ <> ehci_func_sel ENDS ehci_pipe STRUC esp_pipe_base usb_pipe_struc <> esp_qh DD ? esp_prev DW ? esp_next DW ? esp_pending DD ? ehci_pipe ENDS ; this structure should be kept less than 64 bytes long! qtd_struc STRUC ; HC part qtd_next DD ? qtd_alt DD ? qtd_status DB ? qtd_flags DB ? qtd_size DW ? qtd_page0 DD ? qtd_page1 DD ? qtd_page2 DD ? qtd_page3 DD ? qtd_page4 DD ? ; driver part qtd_my_phys DD ? qtd_my_va DD ? qtd_next_va DD ? qtd_alt_va DD ? qtd_buffer_va DD ? qtd_buffer_size DW ? qtd_struc ENDS ; this structure should be kept less than 64 bytes long! qh_struc STRUC ; HC part qh_link DD ? qh_adress DB ? qh_endpoint DB ? qh_max_packet DW ? qh_s_mask DB ? qh_c_mask DB ? qh_hub_port DW ? qh_current_qtd DD ? qh_next_qtd DD ? qh_alt_qtd DD ? qh_status DB ? qh_flags DB ? qh_size DW ? qh_page0 DD ? qh_page1 DD ? qh_page2 DD ? qh_page3 DD ? qh_page4 DD ? ; driver part qh_my_va DD ? qh_link_va DD ? qh_next_va DD ? qh_alt_va DD ? qh_struc ENDS data SEGMENT byte public 'DATA' EhciList64 DD ? EhciSection section_typ <> EhciThread DW ? EhciFuncCount DW ? EhciFuncArr DW MAX_USB_DEVICES DUP(?) data ENDS code SEGMENT byte public 'CODE' assume cs:code IFDEF __WASM__ .686p .xmm2 ELSE .386p ENDIF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateBlock64 ; ; DESCRIPTION: Allocate 64-byte block with page-alignment ; ; PARAMETERS: ES Flat sel ; ; RETURNS: EDX Data address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateBlock64 PROC near push ds push eax ; mov ax,SEG data mov ds,ax EnterSection ds:EhciSection mov edx,ds:EhciList64 or edx,edx jnz allocate_block64_done ; push ecx mov eax,1000h AllocateBigLinear mov ecx,64 mov ds:EhciList64,edx allocate_block64_loop: mov eax,edx add eax,ecx mov es:[edx],eax mov edx,eax test dx,0FFFh jnz allocate_block64_loop ; sub edx,ecx mov dword ptr es:[edx],0 mov edx,ds:EhciList64 pop ecx allocate_block64_done: mov eax,es:[edx] mov ds:EhciList64,eax LeaveSection ds:EhciSection ; pop eax pop ds ret AllocateBlock64 ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FreeBlock64 ; ; DESCRIPTION: Free 64-byte block ; ; PARAMETERS: ES Flat sel ; ; PARAMETERS: EDX Data address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FreeBlock64 PROC near push ds push eax ; mov ax,SEG data mov ds,ax ; EnterSection ds:EhciSection mov eax,ds:EhciList64 mov es:[edx],eax mov ds:EhciList64,edx LeaveSection ds:EhciSection ; pop eax pop ds ret FreeBlock64 ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InsertPipe ; ; DESCRIPTION: Insert pipe into function pipe-list ; ; PARAMETERS: DS Function ; FS Pipe ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InsertPipe Proc near push di RequestSpinlock ds:ehc_spinlock mov di,ds:ehc_pipe_list or di,di je ipEmpty ; push ds push si mov ds,di mov si,ds:esp_prev mov ds:esp_prev,fs mov ds,si mov ds:esp_next,fs mov fs:esp_next,di mov fs:esp_prev,si pop si pop ds pop di jmp ipDone ipEmpty: mov fs:esp_next,fs mov fs:esp_prev,fs pop di mov ds:ehc_pipe_list,fs ipDone: ReleaseSpinlock ds:ehc_spinlock ret InsertPipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RemovePipe ; ; DESCRIPTION: Remove pipe from function pipe-list ; ; PARAMETERS: DS Function ; FS Pipe ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RemovePipe Proc near push si push di ; RequestSpinlock ds:ehc_spinlock push ds mov si,fs:esp_prev mov di,fs:esp_next mov ds,di mov ds:esp_prev,si mov ds,si mov ds:esp_next,di pop ds ; mov si,fs cmp si,ds:ehc_pipe_list jne rpDone ; cmp si,di je rpEmpty ; mov ds:ehc_pipe_list,di jmp rpDone rpEmpty: mov ds:ehc_pipe_list,0 rpDone: ReleaseSpinlock ds:ehc_spinlock pop di pop si ret RemovePipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitQh ; ; DESCRIPTION: Initialize an already allocated qh ; ; PARAMETERS: DS Function sel ; ES Flat sel ; EDX QH ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitQh PROC near mov es:[edx].qh_link,1 mov es:[edx].qh_adress,0 mov es:[edx].qh_endpoint,0 mov es:[edx].qh_max_packet,0 mov es:[edx].qh_s_mask,0 mov es:[edx].qh_c_mask,0 mov es:[edx].qh_hub_port,0C000h mov es:[edx].qh_current_qtd,0 mov es:[edx].qh_next_qtd,1 mov es:[edx].qh_alt_qtd,1 mov es:[edx].qh_status,0 mov es:[edx].qh_flags,0 mov es:[edx].qh_size,0 mov es:[edx].qh_page0,0 mov es:[edx].qh_page1,0 mov es:[edx].qh_page2,0 mov es:[edx].qh_page3,0 mov es:[edx].qh_page4,0 mov es:[edx].qh_my_va,edx mov es:[edx].qh_link_va,0 mov es:[edx].qh_next_va,0 mov es:[edx].qh_alt_va,0 ret InitQh ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitQtd ; ; DESCRIPTION: Initialize an already allocated qTD ; ; PARAMETERS: ES Flat sel ; FS Pipe sel ; EAX qTD physical ; EDX qTD linear ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitQtd PROC near mov es:[edx].qtd_next,1 mov es:[edx].qtd_alt,1 mov es:[edx].qtd_status,0 mov es:[edx].qtd_flags,0Fh mov es:[edx].qtd_size,0 mov es:[edx].qtd_page0,0 mov es:[edx].qtd_page1,0 mov es:[edx].qtd_page2,0 mov es:[edx].qtd_page3,0 mov es:[edx].qtd_page4,0 mov es:[edx].qtd_my_va,edx mov es:[edx].qtd_my_phys,eax mov es:[edx].qtd_next_va,0 mov es:[edx].qtd_alt_va,0 mov es:[edx].qtd_buffer_va,0 mov es:[edx].qtd_buffer_size,0 ret InitQtd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateQh ; ; DESCRIPTION: Allocate & initialize an qh descriptor ; ; PARAMETERS: DS Function selector ; ES Flat sel ; ; RETURNS: EDX Linear address of qh ; EAX Physical address of qh ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateQh PROC near push cx call AllocateBlock64 call InitQh ; GetPhysicalPage and ax,0F000h mov cx,dx and cx,0FFFh or ax,cx pop cx ret AllocateQh ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateQtd ; ; DESCRIPTION: Allocate & initialize qTD ; ; PARAMETERS: ES Flat sel ; FS Pipe sel ; ; RETURNS: EDX Linear address of qTD ; EAX Physical address of qTD ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateQtd PROC near push cx call AllocateBlock64 ; GetPhysicalPage and ax,0F000h mov cx,dx and cx,0FFFh or ax,cx pop cx ; call InitQtd ret AllocateQtd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddControlQh ; ; DESCRIPTION: Add control qh ; ; PARAMETERS: DS Function sel ; ES Flat sel ; FS Pipe sel ; ; RETURNS: EDX Linear address of qh added ; EAX Physical address of qh added ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddControlQh PROC near push gs push ebx ; EnterSection ds:ehc_section call AllocateQh mov ebx,eax ; mov al,fs:usbp_address mov es:[edx].qh_adress,al ; mov al,fs:usbp_endpoint or al,20h mov es:[edx].qh_endpoint,al ; mov ax,3008h mov es:[edx].qh_max_packet,ax ; mov eax,ds:ehc_async_head_va or eax,eax jnz acqInsert ; or es:[edx].qh_endpoint,80h mov ds:ehc_async_head_va,edx mov eax,ebx or al,2 mov es:[edx].qh_link,eax mov es:[edx].qh_link_va,edx ; mov gs,ds:ehc_reg_sel mov gs:HcAsyncList,ebx ; mov eax,gs:HcCommand or al,20h mov gs:HcCommand,eax jmp acqDone acqInsert: push esi ; mov esi,eax mov eax,es:[esi].qh_link mov es:[edx].qh_link,eax mov eax,es:[esi].qh_link_va mov es:[edx].qh_link_va,eax mov eax,esi acqFindEnd: cmp esi,es:[eax].qh_link_va je acqEndFound ; mov eax,es:[eax].qh_link_va jmp acqFindEnd acqEndFound: mov esi,ebx or si,2 mov es:[eax].qh_link,esi mov es:[eax].qh_link_va,edx ; pop esi acqDone: mov eax,ebx LeaveSection ds:ehc_section ; pop ebx pop gs ret AddControlQh ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateFillQtd ; ; DESCRIPTION: Allocate and fill qtd buffer pointers from buffer ; ; PARAMETERS: DS Function selector ; ES:EDI Data buffer ; CX Size of data ; ; RETURNS: EDX Allocated & filled qTD ; EAX qTD physical ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateFillQtd PROC near push es push eax push ebx push ecx push edx push esi push edi ; push ecx mov bx,es GetSelectorBaseSize add edx,edi mov cx,flat_sel mov es,cx pop ecx ; push edx call AllocateQtd mov esi,edx mov edi,eax pop edx ; mov es:[esi].qtd_size,cx or cx,cx jz afqDone ; mov al,es:[edx] GetPhysicalPage and ax,0F000h mov bx,dx and bx,0FFFh or ax,bx mov es:[esi].qtd_page0,eax ; mov ax,1000h sub ax,bx sub cx,ax jc afqDone ; movzx ebx,ax add edx,ebx mov ebx,OFFSET qtd_page1 afqLoop: mov al,es:[edx] GetPhysicalPage and ax,0F000h mov es:[esi+ebx],eax sub cx,1000h jc afqDone ; add edx,1000h add ebx,4 jmp afqLoop afqDone: pop edi pop esi pop edx pop ecx pop ebx pop eax pop es ret AllocateFillQtd Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InsertQtd ; ; DESCRIPTION: Insert qTD into pipe schedule ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; AL PID code ; EDX qTD linear ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InsertQtd PROC near push es push ax push ebx ; mov bx,flat_sel mov es,bx ; and al,3 or al,0Ch mov es:[edx].qtd_flags,cl ; mov ebx,fs:esp_pending mov fs:esp_pending,edx or ebx,ebx jz iqEmpty ; mov es:[edx].qtd_next_va,ebx mov ebx,es:[ebx].qtd_my_phys mov es:[edx].qtd_next,ebx jmp iqLinked iqEmpty: mov es:[edx].qtd_next_va,0 mov es:[edx].qtd_next,1 iqLinked: pop ebx pop ax pop es ret InsertQtd Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateControl ; ; DESCRIPTION: Create control pipe ; ; PARAMETERS: DS Function selector ; ; RETURNS: FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateControl Proc far push es pushad ; mov eax,SIZE ehci_pipe AllocateSmallGlobalMem xor di,di mov cx,ax xor al,al rep stosb ; mov ax,es mov fs,ax mov dx,flat_sel mov es,dx call AddControlQh mov fs:esp_qh,edx call InsertPipe ; popad pop es ret CreateControl Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateBulk ; ; DESCRIPTION: Create bulk pipe ; ; PARAMETERS: DS Function selector ; ; RETURNS: FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateBulk Proc far int 3 ret CreateBulk Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateIntr ; ; DESCRIPTION: Create interrupt pipe ; ; PARAMETERS: DS Function selector ; AL Interval ; ; RETURNS: FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateIntr Proc far int 3 ret CreateIntr Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddSetup ; ; DESCRIPTION: Add setup transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; CX Buffer size ; ES:EDI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddSetup Proc far int 3 push eax push edx ; call AllocateFillQtd ; mov al,2 call InsertQtd ; pop edx pop eax ret AddSetup Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddOut ; ; DESCRIPTION: Add out transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; CX Buffer size ; ES:EDI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddOut Proc far int 3 ret AddOut Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddIn ; ; DESCRIPTION: Add in transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; CX Buffer size ; ES:EDI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddIn Proc far int 3 ret AddIn Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddStatusOut ; ; DESCRIPTION: Add status OUT transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddStatusOut Proc far int 3 ret AddStatusOut Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddStatusIn ; ; DESCRIPTION: Add status IN transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddStatusIn Proc far int 3 ret AddStatusIn Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IssueTransfer ; ; DESCRIPTION: Issue transfer ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; EDX Queue handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IssueTransfer Proc far int 3 ret IssueTransfer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IsTransferDone ; ; DESCRIPTION: Check if transfer is done ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ; RETURNS: NC Transfer is done ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IsTransferDone Proc far int 3 stc ret IsTransferDone Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WaitForCompletion ; ; DESCRIPTION: Wait for transfer to complete ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WaitForCompletion Proc far int 3 stc ret WaitForCompletion Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EndTransfer ; ; DESCRIPTION: End transfer ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EndTransfer Proc far int 3 ret EndTransfer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WasTransferOk ; ; DESCRIPTION: Was transfer ok ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ; RETURNS: NC Transfer ok ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WasTransferOk Proc far int 3 stc ret WasTransferOk Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetDataSize ; ; DESCRIPTION: Get data size ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ; RETURNS: CX Bytes read ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetDataSize Proc far int 3 ret GetDataSize Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ClosePipe ; ; DESCRIPTION: Close pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ClosePipe Proc far int 3 ret ClosePipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ChangeAddress ; ; DESCRIPTION: Change address for pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ChangeAddress Proc far int 3 ret ChangeAddress Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IsConnected ; ; DESCRIPTION: Check if pipe is connected ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IsConnected Proc far int 3 stc ret IsConnected Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ResetPipe ; ; DESCRIPTION: Reset port for pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ResetPipe Proc far int 3 stc ret ResetPipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UpdatePort ; ; DESCRIPTION: Update root-hub port status ; ; PARAMETERS: DS Function selector ; CL Port # (0..EHCI ports) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UpdatePort Proc near push es push ax push bx push cx push dx push si push di ; movzx si,cl shl si,2 movzx di,cl add di,di ; mov es,ds:ehc_reg_sel mov eax,es:[si].HcPortSc test al,2 jz upDone ; mov es:[si].HcPortSc,eax ; reset change bit! ; test al,1 jz upDetach upAttach: mov bx,ds:[di].usb_port_sel_arr or bx,bx jnz upDone ; mov ax,50 WaitMilliSec ; mov eax,es:[si].HcPortSc test al,1 jz upDone ; and ax,0C00h cmp ax,400h jne upDoReset ; test ds:ehc_flags,EHC_COMPANION jz upDone ; cmp cl,ds:ehc_comp_ports jae upDone ; mov eax,es:[si].HcPortSc or ax,2000h mov es:[si].HcPortSc,eax jmp upDone upDoReset: mov eax,es:[si].HcPortSc and al,NOT 4 or ax,100h mov es:[si].HcPortSc,eax ; mov ax,25 WaitMilliSec ; mov eax,es:[si].HcPortSc and ax,NOT 100h mov es:[si].HcPortSc,eax upResetLoop: mov eax,es:[si].HcPortSc test al,1 jz upDone ; test ax,100h jz upResetDone ; mov ax,5 WaitMilliSec jmp upResetLoop upResetDone: mov ax,2 WaitMilliSec ; mov eax,es:[si].HcPortSc test al,4 jnz upNotify ; test ds:ehc_flags,EHC_COMPANION jz upDone ; cmp cl,ds:ehc_comp_ports jae upDone ; mov eax,es:[si].HcPortSc or ax,2000h mov es:[si].HcPortSc,eax jmp upDone upNotify: mov ax,200 WaitMilliSec ; xor ah,ah mov al,cl NotifyUsbAttach jmp upDone upDetach: mov bx,ds:[di].usb_port_sel_arr or bx,bx jz upDone ; mov al,cl NotifyUsbDetach upDone: pop di pop si pop dx pop cx pop bx pop ax pop es ret UpdatePort Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UpdateAllPorts ; ; DESCRIPTION: Update all root-hub port status ; ; PARAMETERS: DS Function selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UpdateAllPorts Proc near push cx ; xor cl,cl uaPortLoop: cmp cl,ds:ehc_ports jae uaPortDone ; push cx call UpdatePort pop cx ; inc cl jmp uaPortLoop uaPortDone: pop cx ret UpdateAllPorts Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UpdateUsb ; ; DESCRIPTION: Update USB status ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UpdateUsb Proc near mov ax,SEG data mov ds,ax mov cx,ds:EhciFuncCount or cx,cx jz uuDone ; mov si,OFFSET EhciFuncArr uuLoop: push ds push cx push si ; mov ds,ds:[si] mov es,ds:ehc_reg_sel mov eax,es:HcStatus and al,7 mov es:HcStatus,eax ; test al,1 jz uuIocDone ; int 3 uuIocDone: test al,2 jz uuErrorDone ; int 3 uuErrorDone: test al,4 jz uuNext ; call UpdateAllPorts uuNext: pop si pop cx pop ds ; add si,2 loop uuLoop uuDone: ret UpdateUsb Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ehci_timer ; ; DESCRIPTION: Timer that scans for status change in controller ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ehci_timer Proc far push edx push eax ; mov ax,SEG data mov ds,ax mov bx,ds:EhciThread ; mov cx,ds:EhciFuncCount or cx,cx jz etDone ; mov si,OFFSET EhciFuncArr etLoop: push ds push cx push si ; mov ds,ds:[si] mov es,ds:ehc_reg_sel mov eax,es:HcStatus and al,7 jz etNext ; Signal etNext: pop si pop cx pop ds ; add si,2 loop etLoop etDone: pop eax pop edx ; add eax,1193 adc edx,0 mov bx,cs mov es,bx mov bx,cs mov edi,OFFSET ehci_timer StartTimer retf32 ehci_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitFunction ; ; DESCRIPTION: Init EHCI function ; ; PARAMETERS: DS Function selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ehci_tab: et00 DW OFFSET CreateControl, SEG code et01 DW OFFSET CreateBulk, SEG code et02 DW OFFSET CreateIntr, SEG code et03 DW OFFSET AddSetup, SEG code et04 DW OFFSET AddOut, SEG code et05 DW OFFSET AddIn, SEG code et06 DW OFFSET AddStatusOut, SEG code et07 DW OFFSET AddStatusIn, SEG code et08 DW OFFSET IssueTransfer, SEG code et09 DW OFFSET IsTransferDone, SEG code et10 DW OFFSET EndTransfer, SEG code et11 DW OFFSET WasTransferOk, SEG code et12 DW OFFSET GetDataSize, SEG code et13 DW OFFSET ClosePipe, SEG code et14 DW OFFSET WaitForCompletion, SEG code et15 DW OFFSET ChangeAddress, SEG code et16 DW OFFSET IsConnected, SEG code et17 DW OFFSET ResetPipe, SEG code InitFunction Proc near push es push fs pushad ; mov ax,flat_sel mov es,ax ; mov si,OFFSET ehci_tab xor di,di mov cx,18 ifTabLoop: lods dword ptr cs:[si] mov ds:[di],eax add di,4 loop ifTabLoop ; InitUsbDevice InitSection ds:ehc_section ; mov fs,ds:ehc_reg_sel mov fs:HcSegmentSelector,0 ; mov eax,fs:HcCommand or al,80h mov fs:HcCommand,eax ifWaitReset: mov eax,fs:HcCommand test al,80h jz ifResetDone ; mov ax,10 WaitMilliSec jmp ifWaitReset ifResetDone: mov eax,fs:HcCommand and al,NOT 0Ch mov fs:HcCommand,eax ; or al,1 mov fs:HcCommand,eax mov fs:HcConfig,1 ; xor cl,cl ifPortLoop: cmp cl,ds:ehc_ports jae ifPortDone ; movzx si,cl shl si,2 ; mov eax,fs:[si].HcPortSc test ax,1000h jnz ifPowerOk ; or ax,1000h mov fs:[si].HcPortSc,eax ifPowerOk: inc cl jmp ifPortLoop ifPortDone: popad pop fs pop es ret InitFunction Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddFunction ; ; DESCRIPTION: Add EHCI function ; ; PARAMETERS: BX Bus/device ; CH Function ; EAX Register base ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddFunction Proc near push es push ds push eax push bx push edx push di push bp ; push eax mov eax,1000h AllocateBigLinear pop eax ; or ax,803h SetPhysicalPage ; push ecx AllocateGdt mov ecx,1000h CreateDataSelector16 pop ecx mov bp,bx ; mov eax,1000h AllocateBigLinear mov ecx,eax AllocateGdt CreateDataSelector16 mov ds,bx mov es,bx xor di,di xor eax,eax mov cx,400h rep stosd ; mov ds:ehc_reg_sel,bp mov ds:ehc_linear,edx GetPhysicalPage and ax,0F000h mov ds:ehc_phys,eax ; mov eax,1000h AllocateBigLinear mov ecx,eax AllocateGdt CreateDataSelector16 mov ds:ehc_map_linear,edx mov ds:ehc_map_sel,bx mov ds:ehc_pipe_list,0 mov ds:ehc_async_head_va,0 InitSpinlock ds:ehc_spinlock ; mov es,bp mov cl,es:hcp_CAPLEN mov ds:ehc_op_offs,cl mov ds:ehc_flags,0 ; mov ax,es:hcp_HCSPARAMS+2 test al,1 jz afIndOk ; or ds:ehc_flags,EHC_PORT_IND afIndOk: shr ax,4 and al,0Fh mov ds:ehc_debug_port,al ; mov ax,es:hcp_HCSPARAMS test ax,0F000h jz afCompOk ; or ds:ehc_flags,EHC_COMPANION afCompOk: and ah,0Fh mov ds:ehc_comp_ports,ah test al,10h jz afPowerOk ; or ds:ehc_flags,EHC_PORT_POWER afPowerOk: and al,0Fh mov ds:ehc_ports,al ; mov bx,es GetSelectorBaseSize movzx eax,ds:ehc_op_offs add edx,eax sub ecx,eax CreateDataSelector16 mov es,bx ; mov bx,ds mov ax,SEG data mov ds,ax mov di,ds:EhciFuncCount shl di,1 mov ds:[di].EhciFuncArr,bx inc ds:EhciFuncCount ; pop bp pop di pop edx pop bx pop eax pop ds pop es ret AddFunction Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitPciAdapter ; ; DESCRIPTION: Init PCI adapter if found ; ; PARAMETERS: ; ; RETURNS: NC Adapter found ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitPciAdapter Proc near xor ax,ax mov bh,0Ch mov bl,3 mov ch,20h FindPciClass jc init_pci_done ; mov cl,10h ReadPciDword and ax,0F000h mov ebp,eax call AddFunction ; mov dx,1 init_pci_next_device: mov ax,dx mov bh,0Ch mov bl,3 mov ch,20h FindPciClass jc init_pci_done ; mov cl,10h ReadPciDword and ax,0F000h cmp eax,ebp je init_pci_done ; call AddFunction inc dx jmp init_pci_next_device init_pci_done: ret InitPciAdapter Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EHCI thread ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ehci_name DB 'EHCI',0 ehci_thread: mov ax,SEG data mov ds,ax GetThread mov ds:EhciThread,ax ; mov si,OFFSET EhciFuncArr mov cx,ds:EhciFuncCount etInitLoop: ClearSignal push ds push si mov ds,ds:[si] call InitFunction pop si pop ds add si,2 loop etInitLoop ; GetSystemTime add eax,11930 adc edx,0 mov bx,cs mov es,bx mov bx,cs mov edi,OFFSET ehci_timer StartTimer ; mov ax,20 WaitMilliSec ehci_thread_loop: WaitForSignal call UpdateUsb jmp ehci_thread_loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Init_usb ; ; DESCRIPTION: inits adpater ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init_usb Proc far push ds push es pusha ; mov ax,SEG data mov ds,ax call InitPciAdapter mov cx,ds:EhciFuncCount or cx,cx jz init_usb_done ; mov ax,cs mov ds,ax mov es,ax mov di,OFFSET ehci_name mov si,OFFSET ehci_thread mov ax,4 mov cx,stack0_size CreateThread init_usb_done: popa pop es pop ds retf32 init_usb Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Init ; ; DESCRIPTION: init device ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init Proc far mov bx,SEG data mov ds,bx InitSection ds:EhciSection mov ds:EhciFuncCount,0 ; mov ax,cs mov es,ax mov edi,OFFSET init_usb HookInitPci clc ; ret Init Endp code ENDS END init