;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 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 ; ; OHCI.ASM ; OHCI-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 hc_reg STRUC HcRevision DD ? HcControl DD ? HcCommandStatus DD ? HcInterruptStatus DD ? HcInterruptEnable DD ? HcInterruptDisable DD ? HcHCCA DD ? HcPeriodCurrentED DD ? HcControlHeadED DD ? HcControlCurrentED DD ? HcBulkHeadED DD ? HcBulkCurrentED DD ? HcDoneHeadED DD ? HcFmInterval DD ? HcFmRemain DD ? HcFmNumber DD ? HcPeriodicStart DD ? HcLSThreshold DD ? HcRhDescriptorA DD ? HcRhDescriptorB DD ? HcRhStatus DD ? HcRhPortStatus DD ? hc_reg ENDS ; this structure should be kept less than 32 bytes long! ohc_es_struc STRUC ;HC part oes_fa_en DW ? oes_mps DW ? oes_tailp DD ? oes_headp DD ? oes_nexted DD ? ;driver part oes_my_va DD ? oes_tail_va DD ? oes_head_va DD ? oes_next_va DD ? ohc_es_struc ENDS ; this structure should be kept less than 32 bytes long! ohc_td_struc STRUC ;HC part otd_resv DW ? otd_flags DW ? otd_cbp DD ? otd_next_td DD ? otd_be DD ? ;driver part otd_my_va DD ? otd_next_va DD ? otd_buffer_va DD ? otd_buffer_size DW ? otd_pipe_sel DW ? ohc_td_struc ENDS OSP_FLAG_TRANSFER_PENDING = 1 OSP_FLAG_TRANSFER_OK = 2 ohci_pipe STRUC osp_pipe_base usb_pipe_struc <> osp_ed DD ? osp_prev DW ? osp_next DW ? osp_data_list DD ? osp_signal DW ? osp_sync_linear DD ? osp_intr_list DW ? osp_intr_count DW ? osp_data_size DW ? osp_setup_linear DD ? osp_flags DB ? ohci_pipe ENDS ohci_func_sel STRUC usb_dev_base usb_dev_struc <> ohc_reg_sel DW ? ohc_map_sel DW ? ohc_map_linear DD ? ohc_int_status DD ? ohc_linear DD ? ohc_phys DD ? ohc_control_linear DD ? ohc_bulk_linear DD ? ohc_pipe_list DW ? ohc_reclaim_list DD ? ohc_spinlock spinlock_typ <> ohc_reset DW ? ohc_section section_typ <> ohc_32_cnt DB 32 DUP(?) ohc_16_cnt DB 16 DUP(?) ohc_8_cnt DB 8 DUP(?) ohc_4_cnt DB 4 DUP(?) ohc_2_cnt DB 2 DUP(?) ohc_1_cnt DB ? ohc_curr_cnt DB 32 DUP(?) ohci_func_sel ENDS ; this should be at 700h in the ohci_func_sel, interrupt ES descriptors ohc_int_base = 700h ohc_int_struc STRUC ohc_32_es DB 32 * 32 DUP(?) ohc_16_es DB 16 * 32 DUP(?) ohc_8_es DB 8 * 32 DUP(?) ohc_4_es DB 4 * 32 DUP(?) ohc_2_es DB 2 * 32 DUP(?) ohc_1_es DB 1 * 32 DUP(?) ohc_iso_es DB 1 * 32 DUP(?) ohc_int_struc ENDS ohc_hca_base = 0F00h ; HCCA is at the end (F00h) of ohci_func_sel hcca_struc STRUC hcca_int_table DD 32 DUP(?) hcca_frame_number DW ? hcca_pad1 DW ? hcca_done_head DD ? hcca_struc ENDS data SEGMENT byte public 'DATA' OhciUsedBlocks DD ? OhciCloseCount DD ? OhciList32 DD ? OhciSection section_typ <> OhciThread DW ? OhciFuncCount DW ? OhciFuncArr DW MAX_USB_DEVICES DUP(?) data ENDS code SEGMENT byte public 'CODE' assume cs:code IFDEF __WASM__ .686p .xmm2 ELSE .386p ENDIF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: OhciInt ; ; DESCRIPTION: OHCI interrupt ; ; PARAMETERS: DS Register selector ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; OhciInt Proc far mov ax,SEG data mov es,ax mov bx,es:OhciThread ; mov cx,es:OhciFuncCount mov si,OFFSET OhciFuncArr oiSignalLoop: push es mov es,es:[si] mov ds,es:ohc_reg_sel mov eax,ds:HcInterruptStatus mov ds:HcInterruptStatus,eax or es:ohc_int_status,eax ; and eax,52h jz oiNext ; Signal oiNext: pop es add si,2 loop oiSignalLoop ; ret OhciInt Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateBlock32 ; ; DESCRIPTION: Allocate 32-byte block with page-alignment ; ; PARAMETERS: ES Flat sel ; ; RETURNS: EDX Data address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateBlock32 PROC near push ds push eax ; mov ax,SEG data mov ds,ax EnterSection ds:OhciSection inc ds:OhciUsedBlocks mov edx,ds:OhciList32 or edx,edx jnz allocate_block32_done ; push ecx mov eax,1000h AllocateBigLinear mov ecx,32 mov ds:OhciList32,edx allocate_block32_loop: mov eax,edx add eax,ecx mov es:[edx],eax mov edx,eax test dx,0FFFh jnz allocate_block32_loop ; sub edx,ecx mov dword ptr es:[edx],0 mov edx,ds:OhciList32 pop ecx allocate_block32_done: mov eax,es:[edx] mov ds:OhciList32,eax LeaveSection ds:OhciSection ; pop eax pop ds ret AllocateBlock32 ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FreeBlock32 ; ; DESCRIPTION: Free 32-byte block ; ; PARAMETERS: ES Flat sel ; ; PARAMETERS: EDX Data address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FreeBlock32 PROC near push ds push eax ; mov ax,SEG data mov ds,ax ; EnterSection ds:OhciSection dec ds:OhciUsedBlocks mov eax,ds:OhciList32 mov es:[edx],eax mov ds:OhciList32,edx LeaveSection ds:OhciSection ; pop eax pop ds ret FreeBlock32 ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InsertPipe ; ; DESCRIPTION: Insert pipe into function pipe-list ; ; PARAMETERS: DS Function ; FS Pipe ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InsertPipe Proc near push di RequestSpinlock ds:ohc_spinlock ; mov di,ds:ohc_pipe_list or di,di je ipEmpty ; push ds push si mov ds,di mov si,ds:osp_prev mov ds:osp_prev,fs mov ds,si mov ds:osp_next,fs mov fs:osp_next,di mov fs:osp_prev,si pop si pop ds pop di jmp ipDone ipEmpty: mov fs:osp_next,fs mov fs:osp_prev,fs pop di mov ds:ohc_pipe_list,fs ipDone: mov fs:osp_data_list,0 mov fs:osp_signal,0 mov fs:osp_flags,0 ReleaseSpinlock ds:ohc_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:ohc_spinlock push ds mov si,fs:osp_prev mov di,fs:osp_next mov ds,di mov ds:osp_prev,si mov ds,si mov ds:osp_next,di pop ds ; mov si,fs cmp si,ds:ohc_pipe_list jne rpDone ; cmp si,di je rpEmpty ; mov ds:ohc_pipe_list,di jmp rpDone rpEmpty: mov ds:ohc_pipe_list,0 rpDone: ReleaseSpinlock ds:ohc_spinlock pop di pop si ret RemovePipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitEd ; ; DESCRIPTION: Initialize an already allocated ED ; ; PARAMETERS: DS Function sel ; ES Flat sel ; EDX ED ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitEd PROC near mov es:[edx].oes_fa_en,4000h mov es:[edx].oes_mps,0 mov es:[edx].oes_tailp,0 mov es:[edx].oes_headp,0 mov es:[edx].oes_nexted,0 mov es:[edx].oes_my_va,edx mov es:[edx].oes_tail_va,0 mov es:[edx].oes_head_va,0 mov es:[edx].oes_next_va,0 ret InitEd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitTd ; ; DESCRIPTION: Initialize an already allocated TD ; ; PARAMETERS: ES Flat sel ; FS Pipe sel ; EDX TD ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitTd PROC near mov es:[edx].otd_resv,0 mov es:[edx].otd_flags,0E4h mov es:[edx].otd_cbp,0 mov es:[edx].otd_next_td,0 mov es:[edx].otd_be,0 mov es:[edx].otd_my_va,edx mov es:[edx].otd_next_va,0 mov es:[edx].otd_pipe_sel,fs ret InitTd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateEd ; ; DESCRIPTION: Allocate & initialize an endpoint descriptor ; ; PARAMETERS: DS Function selector ; ES Flat sel ; ; RETURNS: EDX Linear address of ED ; EAX Physical address of ED ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateEd PROC near push cx call AllocateBlock32 call InitEd ; GetPhysicalPage and ax,0F000h mov cx,dx and cx,0FFFh or ax,cx pop cx ret AllocateEd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AllocateTd ; ; DESCRIPTION: Allocate & initialize transfer descriptor ; ; PARAMETERS: ES Flat sel ; FS Pipe sel ; ; RETURNS: EDX Linear address of TD ; EAX Physical address of TD ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AllocateTd PROC near push cx call AllocateBlock32 call InitTd ; GetPhysicalPage and ax,0F000h mov cx,dx and cx,0FFFh or ax,cx pop cx ret AllocateTd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateSyncBlock ; ; DESCRIPTION: Allocate sync block ; ; PARAMETERS: FS Pipe sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateSyncBlock Proc near push eax push ecx push edx ; mov eax,1000h AllocateBigLinear mov fs:osp_sync_linear,edx ; pop edx pop ecx pop eax ret CreateSyncBlock Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SyncHead ; ; DESCRIPTION: Sync head ptr in pipe ; ; PARAMETERS: DS Function sel ; ES Flat sel ; FS Pipe sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SyncHead Proc near push eax push ebx push edx ; mov ebx,fs:osp_ed mov eax,es:[ebx].oes_headp mov edx,fs:osp_sync_linear movzx ebx,ax and bx,0FF0h and ax,0F000h or ax,803h SetPhysicalPage mov edx,es:[ebx+edx].otd_my_va mov ebx,fs:osp_ed mov es:[ebx].oes_head_va,edx ; pop edx pop ebx pop eax ret SyncHead Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddControlEd ; ; DESCRIPTION: Add control ED ; ; PARAMETERS: DS Function sel ; ES Flat sel ; FS Pipe sel ; ; RETURNS: EDX Linear address of ED added ; EAX Physical address of ED added ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddControlEd PROC near push gs push ebx ; EnterSection ds:ohc_section call AllocateEd mov gs,ds:ohc_reg_sel mov ebx,gs:HcControlHeadEd mov es:[edx].oes_nexted,ebx mov ebx,ds:ohc_control_linear mov es:[edx].oes_next_va,ebx ; mov ds:ohc_control_linear,edx mov gs:HcControlHeadEd,eax ; mov ebx,edx push eax push edx ; call AllocateTd mov es:[ebx].oes_headp,eax mov es:[ebx].oes_tailp,eax mov es:[ebx].oes_head_va,edx mov es:[ebx].oes_tail_va,edx ; pop edx pop eax LeaveSection ds:ohc_section ; pop ebx pop gs ret AddControlEd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddBulkEd ; ; DESCRIPTION: Add bulk ED ; ; PARAMETERS: DS Function sel ; ES Flat sel ; FS Pipe sel ; ; RETURNS: EDX Linear address of ED added ; EAX Physical address of ED added ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddBulkEd PROC near push gs push ebx ; EnterSection ds:ohc_section call AllocateEd mov gs,ds:ohc_reg_sel mov ebx,gs:HcBulkHeadEd mov es:[edx].oes_nexted,ebx mov ebx,ds:ohc_bulk_linear mov es:[edx].oes_next_va,ebx ; mov ds:ohc_bulk_linear,edx mov gs:HcBulkHeadEd,eax ; mov ebx,edx push eax push edx ; call AllocateTd mov es:[ebx].oes_headp,eax mov es:[ebx].oes_tailp,eax mov es:[ebx].oes_head_va,edx mov es:[ebx].oes_tail_va,edx ; pop edx pop eax LeaveSection ds:ohc_section ; pop ebx pop gs ret AddBulkEd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetIntrEd ; ; DESCRIPTION: Get interrupt ED ; ; PARAMETERS: DS Function sel ; ES Flat sel ; FS Pipe sel ; CL Interval ; ; RETURNS: DI Offset to ED list entry to use ; SI Offset to count array ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetIntrEd PROC near push ax push bx push cx push bp ; cmp cl,1 jbe gie1 ; cmp cl,3 jbe gie2 ; cmp cl,7 jbe gie4 ; cmp cl,15 jbe gie8 ; cmp cl,31 jbe gie16 gie32: mov bx,OFFSET ohc_32_cnt mov si,OFFSET ohc_32_es mov cx,32 jmp gieLnkOk gie16: mov bx,OFFSET ohc_16_cnt mov si,OFFSET ohc_16_es mov cx,16 jmp gieLnkOk gie8: mov bx,OFFSET ohc_8_cnt mov si,OFFSET ohc_8_es mov cx,8 jmp gieLnkOk gie4: mov bx,OFFSET ohc_4_cnt mov si,OFFSET ohc_4_es mov cx,4 jmp gieLnkOk gie2: mov bx,OFFSET ohc_2_cnt mov si,OFFSET ohc_2_es mov cx,2 jmp gieLnkOk gie1: mov bx,OFFSET ohc_1_cnt mov si,OFFSET ohc_1_es mov cx,1 gieLnkOk: push cx mov di,OFFSET ohc_curr_cnt xor al,al gieInitCnt: mov [di],al inc di loop gieInitCnt ; pop cx ; push bx push cx push si ; mov si,1 gieAddListLoop: push cx mov di,OFFSET ohc_curr_cnt gieAddCount: mov al,[bx] mov bp,si gieAddLoop: add [di],al inc di sub bp,1 jnz gieAddLoop ; inc bx loop gieAddCount ; pop cx ; shl si,1 shr cx,1 or cx,cx jnz gieAddListLoop ; pop si pop cx pop bx ; mov ah,0FFh mov di,OFFSET ohc_curr_cnt gieSmallestLoop: mov al,[di] cmp al,ah jae gieSmallestNext ; mov ah,al mov bp,di gieSmallestNext: inc di loop gieSmallestLoop ; mov di,bp sub di,OFFSET ohc_curr_cnt ; add bx,di inc byte ptr [bx] shl di,5 add di,si add di,ohc_int_base mov si,bx ; pop bp pop cx pop bx pop ax ret GetIntrEd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddIntrEd ; ; DESCRIPTION: Add interrupt ED ; ; PARAMETERS: DS Function sel ; ES Flat sel ; FS Pipe sel ; CL Interval ; ; RETURNS: EDX Linear address of ED added ; EAX Physical address of ED added ; SI Interrupt count array entry ; DI Interrupt ED used ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddIntrEd PROC near push ebx ; EnterSection ds:ohc_section call AllocateEd ; call GetIntrEd mov ebx,ds:[di].oes_next_va mov es:[edx].oes_next_va,ebx mov ebx,ds:[di].oes_nexted mov es:[edx].oes_nexted,ebx ; mov ds:[di].oes_next_va,edx mov ds:[di].oes_nexted,eax ; mov ebx,edx push eax push edx ; call AllocateTd mov es:[ebx].oes_headp,eax mov es:[ebx].oes_tailp,eax mov es:[ebx].oes_head_va,edx mov es:[ebx].oes_tail_va,edx ; pop edx pop eax LeaveSection ds:ohc_section ; pop ebx ret AddIntrEd ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitPipeEd ; ; DESCRIPTION: Init endpoint descriptor from pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ES Flat sel ; EDX ED linear address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InitPipeEd Proc near push eax push edx ; mov ax,fs:usbp_maxlen cmp ax,800h jb init_pipe_size_ok ; mov ax,7FFh init_pipe_size_ok: mov es:[edx].oes_mps,ax ; mov ah,fs:usbp_endpoint xor al,al shr ax,1 or al,fs:usbp_address ; test fs:usbp_speed,USB_LOW_SPEED jz init_pipe_speed_ok ; or ah,20h init_pipe_speed_ok: mov es:[edx].oes_fa_en,ax init_pipe_done: pop edx pop eax ret InitPipeEd Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddPipeTd ; ; DESCRIPTION: Add TD to pipe ; ; PARAMETERS: DS Function selector ; ES Flat sel ; FS Pipe ; EDI Data buffer ; CX Size of data ; AX Flags field of TD ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddPipeTd PROC near push eax push ebx push ecx push edx ; mov edx,fs:osp_ed mov ebx,es:[edx].oes_tail_va or ebx,ebx jz add_pipe_done ; or ax,0F000h mov es:[ebx].otd_flags,ax mov es:[ebx].otd_buffer_size,cx mov es:[ebx].otd_buffer_va,edi ; or cx,cx jnz add_pipe_has_buffer ; mov eax,1 jmp add_pipe_buf_ads_ok add_pipe_has_buffer: push cx push edx mov al,es:[edi] mov edx,edi GetPhysicalPage and ax,0F000h mov cx,dx and cx,0FFFh or ax,cx pop edx pop cx add_pipe_buf_ads_ok: movzx ecx,cx ; mov es:[ebx].otd_cbp,eax add eax,ecx dec eax mov es:[ebx].otd_be,eax ; call AllocateTd mov es:[ebx].otd_next_td,eax mov es:[ebx].otd_next_va,edx ; mov ebx,fs:osp_ed mov es:[ebx].oes_tail_va,edx mov es:[ebx].oes_tailp,eax add_pipe_done: pop edx pop ecx pop ebx pop eax ret AddPipeTd Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateInterrupt ; ; DESCRIPTION: Create interrupt queues ; ; PARAMETERS: DS Function selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateInterrupt PROC near push eax push bx push cx push edx ; mov cx,32 mov bx,ohc_hca_base + OFFSET hcca_int_table mov eax,ohc_int_base + OFFSET ohc_32_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ci_int32: call InitEd mov ds:[bx],eax add eax,32 add edx,32 add bx,4 loop ci_int32 ; mov cx,32 mov bx,ohc_int_base + OFFSET ohc_32_es mov eax,ohc_int_base + OFFSET ohc_16_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ci_int16_init: call InitEd ci_int16_link: mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx add bx,32 ; test cx,1 jz ci_int16_link_next ; add eax,32 add edx,32 loop ci_int16_init ; jmp ci_int16_done ci_int16_link_next: loop ci_int16_link ci_int16_done: mov cx,16 mov bx,ohc_int_base + OFFSET ohc_16_es mov eax,ohc_int_base + OFFSET ohc_8_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ci_int8_init: call InitEd ci_int8_link: mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx add bx,32 ; test cx,1 jz ci_int8_link_next ; add eax,32 add edx,32 loop ci_int8_init ; jmp ci_int8_done ci_int8_link_next: loop ci_int8_link ci_int8_done: mov cx,8 mov bx,ohc_int_base + OFFSET ohc_8_es mov eax,ohc_int_base + OFFSET ohc_4_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ci_int4_init: call InitEd ci_int4_link: mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx add bx,32 ; test cx,1 jz ci_int4_link_next ; add eax,32 add edx,32 loop ci_int4_init ; jmp ci_int4_done ci_int4_link_next: loop ci_int4_link ci_int4_done: mov bx,ohc_int_base + OFFSET ohc_4_es mov eax,ohc_int_base + OFFSET ohc_2_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ; call InitEd mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; add bx,32 mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; add eax,32 add edx,32 call InitEd mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; add bx,32 mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; mov bx,ohc_int_base + OFFSET ohc_2_es mov eax,ohc_int_base + OFFSET ohc_1_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ; call InitEd mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; add bx,32 mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; mov bx,ohc_int_base + OFFSET ohc_1_es mov eax,ohc_int_base + OFFSET ohc_iso_es mov edx,eax add eax,ds:ohc_phys add edx,ds:ohc_linear ; call InitEd mov ds:[bx].oes_nexted,eax mov ds:[bx].oes_next_va,edx ; mov cx,32+16+8+4+2+1 mov bx,OFFSET ohc_32_cnt xor al,al ciInitCount: mov ds:[bx],al inc bx loop ciInitCount ; pop edx pop cx pop bx pop eax ret CreateInterrupt Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateControl ; ; DESCRIPTION: Create control pipe ; ; PARAMETERS: DS Function selector ; ; RETURNS: FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateControl Proc far push es pushad ; mov eax,SIZE ohci_pipe AllocateSmallGlobalMem xor di,di mov cx,ax xor al,al rep stosb ; mov eax,1000h AllocateBigLinear mov es:osp_setup_linear,edx ; mov ax,es mov fs,ax mov dx,flat_sel mov es,dx call AddControlEd mov fs:osp_ed,edx call CreateSyncBlock 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 push es pushad ; mov eax,SIZE ohci_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 AddBulkEd mov fs:osp_ed,edx call CreateSyncBlock call InsertPipe ; popad pop es ret CreateBulk Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CreateIntr ; ; DESCRIPTION: Create interrupt pipe ; ; PARAMETERS: DS Function selector ; AL Interval ; ; RETURNS: FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CreateIntr Proc far push es pushad ; mov cl,al mov eax,SIZE ohci_pipe AllocateSmallGlobalMem push cx xor di,di mov cx,ax xor al,al rep stosb pop cx ; mov ax,es mov fs,ax mov dx,flat_sel mov es,dx call AddIntrEd mov fs:osp_ed,edx mov fs:osp_intr_count,si mov fs:osp_intr_list,di ; call CreateSyncBlock call InsertPipe ; popad pop es ret CreateIntr Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddBuffer ; ; DESCRIPTION: Allocate input/output buffer ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; CX Size ; ES:EDI Buffer ; AX Flags field of TD ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddBuffer Proc near push es pushad ; movzx ecx,cx mov si,ax or cx,cx jnz abHasData ; mov ax,flat_sel mov es,ax xor edi,edi mov ax,si and ax,NOT 0E0h or ax,20h call AddPipeTd jmp abDone abHasData: push ecx mov bx,es GetSelectorBaseSize add edx,edi sub ecx,edi mov eax,ecx pop ecx jc abDone ; cmp eax,ecx jb abDone ; mov ax,flat_sel mov es,ax mov edi,edx abLoop: mov ax,1000h mov dx,di and dx,0FFFh sub ax,dx cmp ax,fs:usbp_maxlen jb abMinOk ; mov ax,fs:usbp_maxlen abMinOk: cmp ax,cx jae abLast ; movzx eax,ax push ax push cx mov cx,ax mov ax,si call AddPipeTd pop cx pop ax add edi,eax sub cx,ax jmp abLoop abLast: mov ax,si and ax,NOT 0E0h or ax,20h call AddPipeTd abDone: popad pop es ret AddBuffer 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 push gs push es pushad ; mov al,fs:usbp_mode cmp al,MODE_CONTROL jne asDone ; mov ax,es mov gs,ax mov esi,edi ; mov ax,flat_sel mov es,ax mov edi,fs:osp_setup_linear ; movzx ecx,cx push ecx push ecx shr ecx,2 rep movs dword ptr es:[edi],gs:[esi] pop ecx and ecx,3 rep movs byte ptr es:[edi],gs:[esi] pop ecx ; mov edi,fs:osp_setup_linear mov ax,2E4h call AddPipeTd asDone: popad pop es pop gs 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 push eax push ecx push edx ; mov ax,0ECh call AddBuffer ; pop edx pop ecx pop eax 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 push eax push ecx push edx ; mov ax,0F4h call AddBuffer ; pop edx pop ecx pop eax ret AddIn Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddStatusOut ; ; DESCRIPTION: Add status OUT transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddStatusOut Proc far push eax push ecx push edx ; mov al,fs:usbp_mode cmp al,MODE_CONTROL jne asoDone ; xor cx,cx mov ax,3ECh call AddBuffer asoDone: pop edx pop ecx pop eax ret AddStatusOut Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddStatusIn ; ; DESCRIPTION: Add status IN transaction to queue ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AddStatusIn Proc far push eax push ecx push edx ; mov al,fs:usbp_mode cmp al,MODE_CONTROL jne asiDone ; xor cx,cx mov ax,3F4h call AddBuffer asiDone: pop edx pop ecx pop eax ret AddStatusIn Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IssueTransfer ; ; DESCRIPTION: Issue transfer ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; EDX Queue handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IssueTransfer Proc far push es push eax push edx ; mov ax,flat_sel mov es,ax mov edx,fs:osp_ed ; ClearSignal GetThread mov fs:osp_signal,ax and fs:osp_flags, NOT OSP_FLAG_TRANSFER_OK or fs:osp_flags, OSP_FLAG_TRANSFER_PENDING ; test es:[edx].oes_fa_en,4000h jz issue_transfer_enabled ; call InitPipeEd issue_transfer_enabled: mov al,fs:usbp_mode cmp al,MODE_CONTROL jne issue_not_control ; push ds mov ds,ds:ohc_reg_sel mov eax,ds:HcCommandStatus or al,2 mov ds:HcCommandStatus,eax pop ds jmp issue_done issue_not_control: cmp al,MODE_BULK jne issue_done ; push ds mov ds,ds:ohc_reg_sel mov eax,ds:HcCommandStatus or al,4 mov ds:HcCommandStatus,eax pop ds issue_done: clc pop edx pop eax pop es ret IssueTransfer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IsTransferDone ; ; DESCRIPTION: Check if transfer is done ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IsTransferDone Proc far push es push eax push bx push edx ; test fs:osp_flags, OSP_FLAG_TRANSFER_PENDING jz itdOk ; call IsConnected jc itdOk ; mov ax,flat_sel mov es,ax ; mov bx,fs:osp_signal or bx,bx jnz itdFail ; mov edx,fs:osp_ed mov eax,es:[edx].oes_headp test al,1 jnz itdOk ; and ax,0FFF0h cmp eax,es:[edx].oes_tailp je itdOk itdFail: stc jmp itdDone itdOk: clc itdDone: pop edx pop bx pop eax pop es ret IsTransferDone Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WaitForCompletion ; ; DESCRIPTION: Wait for transfer to complete ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WaitForCompletion Proc far push eax ; test fs:osp_flags, OSP_FLAG_TRANSFER_PENDING jz wfcDone wfcLoop: call IsTransferDone jnc wfcDone ; WaitForSignal jmp wfcLoop wfcDone: call EndTransfer ; pop eax ret WaitForCompletion Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WasTransferOk ; ; DESCRIPTION: Check if transfer was ok ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ; RETURNS: NC Transfer ok ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; WasTransferOk Proc far test fs:osp_flags, OSP_FLAG_TRANSFER_PENDING jz wtoNotPending ; call EndTransfer wtoNotPending: test fs:osp_flags, OSP_FLAG_TRANSFER_OK jnz wtoOk ; stc jmp wtoDone wtoOk: clc wtoDone: ret WasTransferOk Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EndTransfer ; ; DESCRIPTION: End transfer ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; EndTransfer Proc far push es push eax push cx push edx push esi push edi push bp ; test fs:osp_flags, OSP_FLAG_TRANSFER_PENDING jz etDone ; mov fs:osp_data_size,0 and fs:osp_flags, NOT OSP_FLAG_TRANSFER_PENDING and fs:osp_flags, NOT OSP_FLAG_TRANSFER_OK ; mov edx,fs:osp_data_list or edx,edx jz etDone ; mov ax,flat_sel mov es,ax ; xor bp,bp xor edx,edx xchg edx,fs:osp_data_list etLoop: mov ax,es:[edx].otd_flags and ax,18h cmp ax,10h jne etNext ; mov esi,es:[edx].otd_buffer_va or esi,esi jz etNext ; mov ecx,es:[edx].otd_cbp or ecx,ecx jz etFull ; sub ecx,es:[edx].otd_buffer_va and ecx,0FFFh jmp etSizeOk etFull: movzx ecx,es:[edx].otd_buffer_size etSizeOk: add bp,cx etNext: mov edi,es:[edx].otd_next_va call FreeBlock32 mov edx,edi or edx,edx jnz etLoop ; mov fs:osp_data_size,bp or fs:osp_flags, OSP_FLAG_TRANSFER_OK etReset: mov edx,fs:osp_ed or es:[edx].oes_fa_en,4000h etDone: pop bp pop edi pop esi pop edx pop cx pop eax pop es ret EndTransfer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetDataSize ; ; DESCRIPTION: Get data size ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ; RETURNS: CX Bytes read ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetDataSize Proc far xor cx,cx test fs:osp_flags, OSP_FLAG_TRANSFER_OK jz gdsDone ; mov cx,fs:osp_data_size gdsDone: ret GetDataSize Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ClosePipe ; ; DESCRIPTION: Close pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ClosePipe Proc far push es pushad ; push ds mov ax,SEG data mov ds,ax inc ds:OhciCloseCount pop ds ; call RemovePipe ; EnterSection ds:ohc_section mov edx,fs:osp_ed mov al,fs:usbp_mode cmp al,MODE_CONTROL je cpControl ; cmp al,MODE_BULK je cpBulk ; cmp al,MODE_INTR je cpIntr ; int 3 jmp cpFreeEdList cpControl: mov ax,flat_sel mov es,ax ; xor ecx,ecx mov ebx,ds:ohc_control_linear cpControlLoop: cmp ebx,edx je cpControlUnlink ; mov ecx,ebx mov ebx,es:[ebx].oes_next_va or ebx,ebx jnz cpControlLoop jmp cpFreeEdList cpControlUnlink: or ecx,ecx jz cpControlHead ; mov esi,es:[edx].oes_next_va mov edi,es:[edx].oes_nexted mov es:[ecx].oes_next_va,esi mov es:[ecx].oes_nexted,edi jmp cpFreeEdList cpControlHead: push gs mov gs,ds:ohc_reg_sel mov esi,es:[edx].oes_next_va mov edi,es:[edx].oes_nexted mov ds:ohc_control_linear,esi mov gs:HcControlHeadEd,edi pop gs jmp cpFreeEdList cpBulk: mov ax,flat_sel mov es,ax ; xor ecx,ecx mov ebx,ds:ohc_bulk_linear cpBulkLoop: cmp ebx,edx je cpBulkUnlink ; mov ecx,ebx mov ebx,es:[ebx].oes_next_va or ebx,ebx jnz cpBulkLoop jmp cpFreeEdList cpBulkUnlink: or ecx,ecx jz cpBulkHead ; mov esi,es:[edx].oes_next_va mov edi,es:[edx].oes_nexted mov es:[ecx].oes_next_va,esi mov es:[ecx].oes_nexted,edi jmp cpFreeEdList cpBulkHead: push gs mov gs,ds:ohc_reg_sel mov esi,es:[edx].oes_next_va mov edi,es:[edx].oes_nexted mov ds:ohc_bulk_linear,esi mov gs:HcBulkHeadEd,edi pop gs jmp cpFreeEdList cpIntr: mov ax,flat_sel mov es,ax mov di,fs:osp_intr_count dec byte ptr ds:[di] ; mov di,fs:osp_intr_list mov ebx,ds:[di].oes_my_va xor ecx,ecx cpIntrLoop: cmp ebx,edx je cpIntrUnlink ; mov ecx,ebx mov ebx,es:[ebx].oes_next_va or ebx,ebx jnz cpIntrLoop jmp cpFreeEdList cpIntrUnlink: or ecx,ecx jz cpIntrHead ; mov esi,es:[edx].oes_next_va mov edi,es:[edx].oes_nexted mov es:[ecx].oes_next_va,esi mov es:[ecx].oes_nexted,edi jmp cpFreeEdList cpIntrHead: mov esi,es:[edx].oes_next_va mov ecx,es:[edx].oes_nexted mov ds:[di].oes_next_va,esi mov ds:[di].oes_nexted,ecx jmp cpFreeEdList cpFreeEdList: mov eax,es:[edx].oes_headp test al,1 jnz cpFreeTd ; and ax,0FFF0h cmp eax,es:[edx].oes_tailp je cpFreeTd ; call IsConnected jc cpFreeTd ; mov ax,1 WaitMilliSec jmp cpFreeEdList cpFreeTd: call EndTransfer call SyncHead mov edx,es:[edx].oes_head_va cpTdListLoop: or edx,edx jz cpTdListOk ; mov eax,es:[edx].otd_next_va call FreeBlock32 mov edx,eax jmp cpTdListLoop cpTdListOk: mov edx,fs:osp_ed call FreeBlock32 dpDone: mov edx,fs:osp_setup_linear or edx,edx jz rpSetupDone ; mov ecx,1000h FreeLinear rpSetupDone: mov edx,fs:osp_sync_linear xor eax,eax SetPhysicalPage ; mov ecx,1000h FreeLinear ; mov ax,2 WaitMilliSec ; LeaveSection ds:ohc_section mov ax,fs mov es,ax xor ax,ax mov fs,ax FreeMem ; popad pop es ret ClosePipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ChangeAddress ; ; DESCRIPTION: Change address for pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ChangeAddress Proc far push es push edx ; mov dx,flat_sel mov es,dx ; mov edx,fs:osp_ed call InitPipeEd ; pop edx pop es ret ChangeAddress Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IsConnected ; ; DESCRIPTION: Check if pipe is connected ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IsConnected Proc far push es push ax push dx push si ; mov es,fs:usbp_function_sel movzx si,es:usbf_port ; shl si,2 mov es,ds:ohc_reg_sel mov eax,es:[si].HcRhPortStatus test al,1 clc jnz icDone ; stc icDone: pop si pop dx pop ax pop es ret IsConnected Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ResetPipe ; ; DESCRIPTION: Reset port for pipe ; ; PARAMETERS: DS Function selector ; FS Pipe selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ResetPipe Proc far push es push ax push cx ; mov es,fs:usbp_function_sel mov cl,es:usbf_port mov ax,1 shl ax,cl or ds:ohc_reset,ax ; pop cx pop ax pop es ret ResetPipe Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UpdateQueue ; ; DESCRIPTION: Update done queue ; ; PARAMETERS: DS Function selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UpdateQueue Proc near push es push fs push gs push eax push bx push ecx push edx ; xor eax,eax mov bx,ohc_hca_base + OFFSET hcca_done_head lock xchg eax,ds:[bx] and al,NOT 1 or eax,eax jz update_queue_done ; mov dx,flat_sel mov es,dx mov fs,ds:ohc_map_sel update_reverse_loop: mov bx,ax and ax,0F000h and bx,0FFFh or ax,803h mov edx,ds:ohc_map_linear SetPhysicalPage ; mov edx,fs:[bx].otd_my_va ; mov ax,es:[edx].otd_pipe_sel or ax,ax jz update_insert_reclaim update_insert_pipe: mov gs,ax test gs:osp_flags, OSP_FLAG_TRANSFER_PENDING jz update_insert_reclaim ; mov ecx,gs:osp_data_list mov es:[edx].otd_next_va,ecx mov gs:osp_data_list,edx ; xor bx,bx xchg bx,gs:osp_signal Signal jmp update_reverse_next update_insert_reclaim: mov ecx,ds:ohc_reclaim_list mov es:[edx].otd_next_va,ecx mov ds:ohc_reclaim_list,edx update_reverse_next: mov eax,es:[edx].otd_next_td or eax,eax jnz update_reverse_loop update_queue_done: pop edx pop ecx pop bx pop eax pop gs pop fs pop es ret UpdateQueue Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UpdatePort ; ; DESCRIPTION: Update root-hub port status ; ; PARAMETERS: DS Function selector ; CL Port # (0,1) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UpdatePort Proc near push es push ax push bx push cx push dx push si push di ; mov eax,ds:ohc_reclaim_list or eax,eax jz upNoReclaim ; push gs push ecx push edx mov ax,flat_sel mov es,ax ; RequestSpinlock ds:ohc_spinlock mov edx,ds:ohc_reclaim_list mov ecx,es:[edx].otd_next_va mov ds:ohc_reclaim_list,ecx ReleaseSpinlock ds:ohc_spinlock ; mov ax,es:[edx].otd_pipe_sel or ax,ax jz upReclaimOk ; push ax mov ax,5 WaitMilliSec pop ax ; IsValidUsbPipeSel jc upReclaimOk ; mov gs,ax test gs:osp_flags, OSP_FLAG_TRANSFER_PENDING jz upReclaimOk ; mov ecx,gs:osp_data_list mov es:[edx].otd_next_va,ecx mov gs:osp_data_list,edx ; xor bx,bx xchg bx,gs:osp_signal Signal upReclaimOk: pop edx pop ecx pop gs upNoReclaim: movzx si,cl shl si,2 movzx di,cl add di,di mov es,ds:ohc_reg_sel ; mov ax,1 shl ax,cl test ax,ds:ohc_reset jz upNoReset ; not ax and ds:ohc_reset,ax ; mov eax,es:[si].HcRhPortStatus test al,1 jz upNoReset ; mov bx,ds:[di].usb_port_sel_arr or bx,bx jz upNoReset ; mov al,cl NotifyUsbDetach jmp upAttach upNoReset: mov eax,es:[si].HcRhPortStatus test al,1 stc jz upDetach upAttach: mov bx,ds:[di].usb_port_sel_arr or bx,bx jnz upDone ; mov ax,50 WaitMilliSec ; mov eax,10h mov es:[si].HcRhPortStatus,eax upResetLoop: mov ax,5 WaitMilliSec ; mov eax,es:[si].HcRhPortStatus test al,1 jz upDone ; test al,10h jnz upResetLoop ; mov eax,2 mov es:[si].HcRhPortStatus,eax epNotify: mov ax,200 WaitMilliSec ; mov eax,es:[si].HcRhPortStatus shr ah,1 and ah,1 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: UpdateUsb ; ; DESCRIPTION: Update USB status ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UpdateUsb Proc near mov ax,SEG data mov ds,ax mov cx,ds:OhciFuncCount or cx,cx jz uuDone ; mov si,OFFSET OhciFuncArr uuLoop: push ds push cx push si ; mov ds,ds:[si] ; xor cl,cl call UpdatePort ; mov cl,1 call UpdatePort ; pop si pop cx pop ds ; add si,2 loop uuLoop uuDone: ret UpdateUsb Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ohci_timer ; ; DESCRIPTION: Timer that scans for status change in controller ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ohci_timer Proc far push edx push eax ; mov ax,SEG data mov ds,ax mov bx,ds:OhciThread ; mov cx,ds:OhciFuncCount or cx,cx jz otDone ; mov si,OFFSET OhciFuncArr otLoop: push ds push cx push si ; mov ds,ds:[si] mov es,ds:ohc_reg_sel mov eax,es:HcInterruptStatus test eax,2 jz otQueueDone ; call UpdateQueue otQueueDone: mov es,ds:ohc_reg_sel mov es:HcInterruptStatus,eax or ds:ohc_int_status,eax ; and eax,52h jz otNext ; Signal otNext: pop si pop cx pop ds ; add si,2 loop otLoop otDone: pop eax pop edx ; add eax,1193 adc edx,0 mov bx,cs mov es,bx mov bx,cs mov edi,OFFSET ohci_timer StartTimer retf32 ohci_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: InitFunction ; ; DESCRIPTION: Init OHCI function ; ; PARAMETERS: DS Function selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ohci_tab: ot00 DW OFFSET CreateControl, SEG code ot01 DW OFFSET CreateBulk, SEG code ot02 DW OFFSET CreateIntr, SEG code ot03 DW OFFSET AddSetup, SEG code ot04 DW OFFSET AddOut, SEG code ot05 DW OFFSET AddIn, SEG code ot06 DW OFFSET AddStatusOut, SEG code ot07 DW OFFSET AddStatusIn, SEG code ot08 DW OFFSET IssueTransfer, SEG code ot09 DW OFFSET IsTransferDone, SEG code ot10 DW OFFSET EndTransfer, SEG code ot11 DW OFFSET WasTransferOk, SEG code ot12 DW OFFSET GetDataSize, SEG code ot13 DW OFFSET ClosePipe, SEG code ot14 DW OFFSET WaitForCompletion, SEG code ot15 DW OFFSET ChangeAddress, SEG code ot16 DW OFFSET IsConnected, SEG code ot17 DW OFFSET ResetPipe, SEG code InitFunction Proc near push es push fs pushad ; mov ax,flat_sel mov es,ax ; mov si,OFFSET ohci_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:ohc_section mov fs,ds:ohc_reg_sel mov ecx,fs:HcControl and cl,0C0h mov edx,fs:HcFmInterval test fs:HcControl,100h jz ifNotSmm ; or fs:HcCommandStatus,8 ifWait: test fs:HcControl,100h jnz ifWait ifNotSmm: mov eax,0C000007Fh mov fs:HcInterruptStatus,eax ; or fs:HcCommandStatus,1 ; mov ax,25 WaitMicroSec mov fs:HcFmInterval,edx mov fs:HcPeriodicStart,0 ; or cl,cl jnz ifNotReset ; mov ax,5 WaitMilliSec mov eax,fs:HcControl and al,NOT 0C0h or al,40h mov fs:HcControl,eax ifNotReset: cmp cl,80h je ifOperational ; mov ax,25 WaitMilliSec ifOperational: call CreateInterrupt ; mov eax,ohc_hca_base add eax,ds:ohc_phys mov fs:HcHCCA,eax ; mov ds:ohc_control_linear,0 mov fs:HcControlHeadED,0 ; mov ds:ohc_bulk_linear,0 mov fs:HcBulkHeadED,0 ; mov eax,fs:HcControl and ax,0F83Fh or al,0BCh mov fs:HcControl,eax ; popad pop es pop ds ret InitFunction Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: AddFunction ; ; DESCRIPTION: Add OHCI 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 ; InitSpinlock ds:ohc_spinlock mov ds:ohc_pipe_list,0 mov ds:ohc_reclaim_list,0 mov ds:ohc_reset,0 mov ds:ohc_reg_sel,bp mov ds:ohc_int_status,0 mov ds:ohc_linear,edx GetPhysicalPage and ax,0F000h mov ds:ohc_phys,eax mov bp,bx ; mov eax,1000h AllocateBigLinear mov ecx,eax AllocateGdt CreateDataSelector16 mov ds:ohc_map_linear,edx mov ds:ohc_map_sel,bx ; mov ax,SEG data mov ds,ax mov si,ds:OhciFuncCount add si,si mov ds:[si].OhciFuncArr,bp inc ds:OhciFuncCount ; 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,10h 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,10h 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: Init_net ; ; DESCRIPTION: inits adpater ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ohci_name DB 'OHCI',0 ohci_thread: mov ax,SEG data mov ds,ax GetThread mov ds:OhciThread,ax ; mov si,OFFSET OhciFuncArr mov cx,ds:OhciFuncCount otInitLoop: ClearSignal push ds push cx push si ; mov ds,ds:[si] call InitFunction ; pop si pop cx pop ds ; add si,2 loop otInitLoop ; GetSystemTime add eax,11930 adc edx,0 mov bx,cs mov es,bx mov bx,cs mov edi,OFFSET ohci_timer StartTimer ; call UpdateUsb ohci_thread_loop: WaitForSignal call UpdateUsb jmp ohci_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:OhciFuncCount or cx,cx jz init_usb_done ; mov ax,cs mov ds,ax mov es,ax mov di,OFFSET ohci_name mov si,OFFSET ohci_thread mov ax,4 mov cx,stack0_size CreateThread init_usb_done: popa pop es pop ds retf32 init_usb Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetAllocatedUsbBlocks ; ; DESCRIPTION: Get allocated USB blocks ; ; PARAMETERS: ; ; RETURNS: EAX Number of blocks ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_allocated_usb_blocks_name DB 'Get Allocated USB Blocks',0 get_allocated_usb_blocks Proc far push ds mov ax,SEG data mov ds,ax mov eax,ds:OhciUsedBlocks pop ds retf32 get_allocated_usb_blocks Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetUsbClosedCount ; ; DESCRIPTION: Get closed count ; ; PARAMETERS: ; ; RETURNS: EAX Number of blocks ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_usb_close_count_name DB 'Get USB Close Count',0 get_usb_close_count Proc far push ds mov ax,SEG data mov ds,ax mov eax,ds:OhciCloseCount pop ds retf32 get_usb_close_count Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Init ; ; DESCRIPTION: init device ; ; PARAMETERS: ; ; RETURNS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Init Proc far mov ax,cs mov ds,ax mov es,ax ; mov bx,SEG data mov ds,bx InitSection ds:OhciSection mov ds:OhciFuncCount,0 mov ds:OhciUsedBlocks,0 mov ds:OhciCloseCount,0 ; mov ax,cs mov ds,ax mov es,ax mov edi,OFFSET init_usb HookInitPci ; mov esi,OFFSET get_allocated_usb_blocks mov edi,OFFSET get_allocated_usb_blocks_name xor dx,dx mov ax,get_allocated_usb_blocks_nr RegisterBimodalUserGate ; mov esi,OFFSET get_usb_close_count mov edi,OFFSET get_usb_close_count_name xor dx,dx mov ax,get_usb_close_count_nr RegisterBimodalUserGate ; clc ; ret Init Endp code ENDS END init