add new files
git-svn-id: svn://kolibrios.org@4419 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
a10422fbce
commit
daba8a5f6a
66
drivers/kglobals.inc
Normal file
66
drivers/kglobals.inc
Normal file
@ -0,0 +1,66 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;------------------------------------------------------------------
|
||||
; use "iglobal" for inserting initialized global data definitions.
|
||||
;------------------------------------------------------------------
|
||||
macro iglobal {
|
||||
IGlobals equ IGlobals,
|
||||
macro __IGlobalBlock { }
|
||||
|
||||
macro iglobal_nested {
|
||||
IGlobals equ IGlobals,
|
||||
macro __IGlobalBlock \{ }
|
||||
|
||||
;-------------------------------------------------------------
|
||||
; use 'uglobal' for inserting uninitialized global definitions.
|
||||
; even when you define some data values, these variables
|
||||
; will be stored as uninitialized data.
|
||||
;-------------------------------------------------------------
|
||||
macro uglobal {
|
||||
UGlobals equ UGlobals,
|
||||
macro __UGlobalBlock { }
|
||||
|
||||
macro uglobal_nested {
|
||||
UGlobals equ UGlobals,
|
||||
macro __UGlobalBlock \{ }
|
||||
|
||||
endg fix } ; Use endg for ending iglobal and uglobal blocks.
|
||||
endg_nested fix \}
|
||||
|
||||
macro IncludeIGlobals{
|
||||
macro IGlobals dummy,[n] \{ __IGlobalBlock
|
||||
purge __IGlobalBlock \}
|
||||
match I, IGlobals \{ I \} }
|
||||
|
||||
|
||||
macro IncludeUGlobals{
|
||||
macro UGlobals dummy,[n] \{
|
||||
\common
|
||||
\local begin, size
|
||||
begin = $
|
||||
virtual at $
|
||||
\forward
|
||||
__UGlobalBlock
|
||||
purge __UGlobalBlock
|
||||
\common
|
||||
size = $ - begin
|
||||
end virtual
|
||||
rb size
|
||||
\}
|
||||
match U, UGlobals \{ U \} }
|
||||
|
||||
macro IncludeAllGlobals {
|
||||
IncludeIGlobals
|
||||
IncludeUGlobals
|
||||
}
|
||||
|
||||
iglobal
|
||||
endg
|
||||
|
||||
uglobal
|
||||
endg
|
106
drivers/macros.inc
Normal file
106
drivers/macros.inc
Normal file
@ -0,0 +1,106 @@
|
||||
include 'kglobals.inc'
|
||||
|
||||
PG_UNMAP equ 0x000
|
||||
PG_MAP equ 0x001
|
||||
PG_WRITE equ 0x002
|
||||
PG_SW equ 0x003
|
||||
PG_USER equ 0x005
|
||||
PG_UW equ 0x007
|
||||
PG_NOCACHE equ 0x018
|
||||
PG_LARGE equ 0x080
|
||||
PG_GLOBAL equ 0x100
|
||||
|
||||
DRV_ENTRY equ 1
|
||||
DRV_EXIT equ -1
|
||||
|
||||
struct LHEAD
|
||||
next dd ? ;next object in list
|
||||
prev dd ? ;prev object in list
|
||||
ends
|
||||
|
||||
struct MUTEX
|
||||
lhead LHEAD
|
||||
count dd ?
|
||||
ends
|
||||
|
||||
struct PCIDEV
|
||||
bk dd ?
|
||||
fd dd ?
|
||||
vendor_device_id dd ?
|
||||
class dd ?
|
||||
devfn db ?
|
||||
bus db ?
|
||||
rb 2
|
||||
owner dd ? ; pointer to SRV or 0
|
||||
ends
|
||||
|
||||
; The following macro assume that we are on uniprocessor machine.
|
||||
; Serious work is needed for multiprocessor machines.
|
||||
macro spin_lock_irqsave spinlock
|
||||
{
|
||||
pushf
|
||||
cli
|
||||
}
|
||||
macro spin_unlock_irqrestore spinlock
|
||||
{
|
||||
popf
|
||||
}
|
||||
macro spin_lock_irq spinlock
|
||||
{
|
||||
cli
|
||||
}
|
||||
macro spin_unlock_irq spinlock
|
||||
{
|
||||
sti
|
||||
}
|
||||
|
||||
; \begin{diamond}[29.09.2006]
|
||||
; may be useful for kernel debugging
|
||||
; example 1:
|
||||
; dbgstr 'Hello, World!'
|
||||
; example 2:
|
||||
; dbgstr 'Hello, World!', save_flags
|
||||
macro dbgstr string*, f
|
||||
{
|
||||
local a
|
||||
iglobal_nested
|
||||
a db 'K : ',string,13,10,0
|
||||
endg_nested
|
||||
if ~ f eq
|
||||
pushfd
|
||||
end if
|
||||
push esi
|
||||
mov esi, a
|
||||
if defined SysMsgBoardStr._pe_import
|
||||
invoke SysMsgBoardStr
|
||||
else
|
||||
call SysMsgBoardStr
|
||||
end if
|
||||
pop esi
|
||||
if ~ f eq
|
||||
popfd
|
||||
end if
|
||||
}
|
||||
; \end{diamond}[29.09.2006]
|
||||
|
||||
; MOV Immediate.
|
||||
; Useful for things like movi eax,10:
|
||||
; shorter than regular mov, but slightly slower,
|
||||
; do not use it in performance-critical places.
|
||||
macro movi dst, imm
|
||||
{
|
||||
if imm >= -0x80 & imm <= 0x7F
|
||||
push imm
|
||||
pop dst
|
||||
else
|
||||
mov dst, imm
|
||||
end if
|
||||
}
|
||||
|
||||
macro call name
|
||||
{
|
||||
if name eqtype func & defined name#._pe_import
|
||||
err Use invoke, not call/stdcall for PE imports!
|
||||
end if
|
||||
call name
|
||||
}
|
152
drivers/peimport.inc
Normal file
152
drivers/peimport.inc
Normal file
@ -0,0 +1,152 @@
|
||||
|
||||
; Macroinstructions for making import section
|
||||
; Based on import32.inc from FASM, with small modifications
|
||||
; and list of actual kernel exports.
|
||||
|
||||
macro library [name,string]
|
||||
{ common
|
||||
import.data:
|
||||
forward
|
||||
local _label
|
||||
if defined name#.redundant
|
||||
if ~ name#.redundant
|
||||
dd 0,0,0,RVA _label,RVA name#.address
|
||||
end if
|
||||
end if
|
||||
name#.referred = 1
|
||||
common
|
||||
dd 0,0,0,0,0
|
||||
forward
|
||||
if defined name#.redundant
|
||||
if ~ name#.redundant
|
||||
_label db string,0
|
||||
end if
|
||||
end if }
|
||||
|
||||
macro import name,[label]
|
||||
{ common
|
||||
rb (- rva $) and 3
|
||||
if defined name#.referred
|
||||
name#.address:
|
||||
forward
|
||||
if used label
|
||||
local _label
|
||||
label dd RVA _label
|
||||
label#._pe_import = 1
|
||||
end if
|
||||
common
|
||||
if $ > name#.address
|
||||
name#.redundant = 0
|
||||
dw 0
|
||||
else
|
||||
name#.redundant = 1
|
||||
end if
|
||||
forward
|
||||
if used label
|
||||
_label dw 0
|
||||
db `label
|
||||
end if
|
||||
common
|
||||
db 0
|
||||
end if }
|
||||
|
||||
align 4
|
||||
data import
|
||||
library core,'core.dll'
|
||||
import core,\
|
||||
RegService,\
|
||||
GetService,\
|
||||
ServiceHandler,\
|
||||
AttachIntHandler,\
|
||||
GetIntHandler,\
|
||||
FpuSave,\
|
||||
FpuRestore,\
|
||||
ReservePortArea,\
|
||||
Boot_Log,\
|
||||
\
|
||||
MutexInit,\
|
||||
MutexLock,\
|
||||
MutexUnlock,\
|
||||
\
|
||||
PciApi,\
|
||||
PciRead32,\
|
||||
PciRead16,\
|
||||
PciRead8,\
|
||||
PciWrite8,\
|
||||
PciWrite16,\
|
||||
PciWrite32,\
|
||||
\
|
||||
AllocPage,\
|
||||
AllocPages,\
|
||||
FreePage,\
|
||||
MapPage,\
|
||||
MapSpace,\
|
||||
MapIoMem,\
|
||||
GetPgAddr,\
|
||||
GetPhysAddr,\
|
||||
CommitPages,\
|
||||
ReleasePages,\
|
||||
\
|
||||
AllocKernelSpace,\
|
||||
FreeKernelSpace,\
|
||||
KernelAlloc,\
|
||||
KernelFree,\
|
||||
UserAlloc,\
|
||||
UserFree,\
|
||||
Kmalloc,\
|
||||
Kfree,\
|
||||
CreateRingBuffer,\
|
||||
\
|
||||
GetPid,\
|
||||
CreateThread,\
|
||||
CreateObject,\
|
||||
DestroyObject,\
|
||||
CreateEvent,\
|
||||
RaiseEvent,\
|
||||
WaitEvent,\
|
||||
DestroyEvent,\
|
||||
ClearEvent,\
|
||||
\
|
||||
LoadCursor,\
|
||||
SelectHwCursor,\
|
||||
SetHwCursor,\
|
||||
HwCursorRestore,\
|
||||
HwCursorCreate,\
|
||||
\
|
||||
SysMsgBoardStr,\
|
||||
SysMsgBoard,\
|
||||
GetCurrentTask,\
|
||||
LoadFile,\
|
||||
SendEvent,\
|
||||
SetMouseData,\
|
||||
SetKeyboardData,\
|
||||
RegKeyboard,\
|
||||
DelKeyboard,\
|
||||
Sleep,\
|
||||
GetTimerTicks,\
|
||||
\
|
||||
strncat,\
|
||||
strncpy,\
|
||||
strncmp,\
|
||||
strnlen,\
|
||||
strchr,\
|
||||
strrchr,\
|
||||
\
|
||||
LFBAddress,\
|
||||
GetDisplay,\
|
||||
SetScreen,\
|
||||
\
|
||||
RegUSBDriver,\
|
||||
USBOpenPipe,\
|
||||
USBNormalTransferAsync,\
|
||||
USBControlTransferAsync,\
|
||||
USBGetParam,\
|
||||
USBHCFunc,\
|
||||
\
|
||||
DiskAdd,\
|
||||
DiskMediaChanged,\
|
||||
DiskDel,\
|
||||
\
|
||||
TimerHS,\
|
||||
CancelTimerHS
|
||||
end data
|
446
kernel/trunk/bus/usb/common.inc
Normal file
446
kernel/trunk/bus/usb/common.inc
Normal file
@ -0,0 +1,446 @@
|
||||
; Constants and structures that are shared between different parts of
|
||||
; USB subsystem and *HCI drivers.
|
||||
|
||||
; =============================================================================
|
||||
; ================================= Constants =================================
|
||||
; =============================================================================
|
||||
; Version of all structures related to host controllers.
|
||||
; Must be the same in kernel and *hci-drivers.
|
||||
USBHC_VERSION = 1
|
||||
|
||||
; USB device must have at least 100ms of stable power before initializing can
|
||||
; proceed; one timer tick is 10ms, so enforce delay in 10 ticks
|
||||
USB_CONNECT_DELAY = 10
|
||||
; USB requires at least 10 ms for reset signalling. Normally, this is one timer
|
||||
; tick. However, it is possible that we start reset signalling in the end of
|
||||
; interval between timer ticks and then we test time in the start of the next
|
||||
; interval; in this case, the delta between [timer_ticks] is 1, but the real
|
||||
; time passed is significantly less than 10 ms. To avoid this, we add an extra
|
||||
; tick; this guarantees that at least 10 ms have passed.
|
||||
USB_RESET_TIME = 2
|
||||
; USB requires at least 10 ms of reset recovery, a delay between reset
|
||||
; signalling and any commands to device. Add an extra tick for the same reasons
|
||||
; as with the previous constant.
|
||||
USB_RESET_RECOVERY_TIME = 2
|
||||
|
||||
; USB pipe types
|
||||
CONTROL_PIPE = 0
|
||||
ISOCHRONOUS_PIPE = 1
|
||||
BULK_PIPE = 2
|
||||
INTERRUPT_PIPE = 3
|
||||
|
||||
; Status codes for transfer callbacks.
|
||||
; Taken from OHCI as most verbose controller in this sense.
|
||||
USB_STATUS_OK = 0 ; no error
|
||||
USB_STATUS_CRC = 1 ; CRC error
|
||||
USB_STATUS_BITSTUFF = 2 ; bit stuffing violation
|
||||
USB_STATUS_TOGGLE = 3 ; data toggle mismatch
|
||||
USB_STATUS_STALL = 4 ; device returned STALL
|
||||
USB_STATUS_NORESPONSE = 5 ; device not responding
|
||||
USB_STATUS_PIDCHECK = 6 ; invalid PID check bits
|
||||
USB_STATUS_WRONGPID = 7 ; unexpected PID value
|
||||
USB_STATUS_OVERRUN = 8 ; too many data from endpoint
|
||||
USB_STATUS_UNDERRUN = 9 ; too few data from endpoint
|
||||
USB_STATUS_BUFOVERRUN = 12 ; overflow of internal controller buffer
|
||||
USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer
|
||||
USB_STATUS_CLOSED = 16 ; pipe closed
|
||||
; either explicitly with USBClosePipe
|
||||
; or implicitly due to device disconnect
|
||||
|
||||
; Possible speeds of USB devices
|
||||
USB_SPEED_FS = 0 ; full-speed
|
||||
USB_SPEED_LS = 1 ; low-speed
|
||||
USB_SPEED_HS = 2 ; high-speed
|
||||
|
||||
; flags for usb_pipe.Flags
|
||||
USB_FLAG_CLOSED = 1 ; pipe is closed, no new transfers
|
||||
; pipe is closed, return error instead of submitting any new transfer
|
||||
USB_FLAG_CAN_FREE = 2
|
||||
; pipe is closed via explicit call to USBClosePipe, so it can be freed without
|
||||
; any driver notification; if this flag is not set, then the pipe is closed due
|
||||
; to device disconnect, so it must remain valid until return from disconnect
|
||||
; callback provided by the driver
|
||||
USB_FLAG_EXTRA_WAIT = 4
|
||||
; The pipe was in wait list, while another event occured;
|
||||
; when the first wait will be done, reinsert the pipe to wait list
|
||||
USB_FLAG_CLOSED_BIT = 0 ; USB_FLAG_CLOSED = 1 shl USB_FLAG_CLOSED_BIT
|
||||
|
||||
; =============================================================================
|
||||
; ================================ Structures =================================
|
||||
; =============================================================================
|
||||
|
||||
; Description of controller-specific data and functions.
|
||||
struct usb_hardware_func
|
||||
Version dd ? ; must be USBHC_VERSION
|
||||
ID dd ? ; '*HCI'
|
||||
DataSize dd ? ; sizeof(*hci_controller)
|
||||
BeforeInit dd ?
|
||||
; Early initialization: take ownership from BIOS.
|
||||
; in: [ebp-4] = (bus shl 8) + devfn
|
||||
Init dd ?
|
||||
; Initialize controller-specific part of controller data.
|
||||
; in: eax -> *hci_controller to initialize, [ebp-4] = (bus shl 8) + devfn
|
||||
; out: eax = 0 <=> failed, otherwise eax -> usb_controller
|
||||
ProcessDeferred dd ?
|
||||
; Called regularly from the main loop of USB thread
|
||||
; (either due to timeout from a previous call, or due to explicit wakeup).
|
||||
; in: esi -> usb_controller
|
||||
; out: eax = maximum timeout for next call (-1 = infinity)
|
||||
SetDeviceAddress dd ?
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address
|
||||
GetDeviceAddress dd ?
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe
|
||||
; out: eax = address
|
||||
PortDisable dd ?
|
||||
; Disable the given port in the root hub.
|
||||
; in: esi -> usb_controller, ecx = port (zero-based)
|
||||
InitiateReset dd ?
|
||||
; Start reset signalling on the given port.
|
||||
; in: esi -> usb_controller, ecx = port (zero-based)
|
||||
SetEndpointPacketSize dd ?
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size
|
||||
AllocPipe dd ?
|
||||
; out: eax = pointer to allocated usb_pipe
|
||||
FreePipe dd ?
|
||||
; void stdcall with one argument = pointer to previously allocated usb_pipe
|
||||
InitPipe dd ?
|
||||
; in: edi -> usb_pipe for target, ecx -> usb_pipe for config pipe,
|
||||
; esi -> usb_controller, eax -> usb_gtd for the first TD,
|
||||
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type
|
||||
UnlinkPipe dd ?
|
||||
; esi -> usb_controller, ebx -> usb_pipe
|
||||
AllocTD dd ?
|
||||
; out: eax = pointer to allocated usb_gtd
|
||||
FreeTD dd ?
|
||||
; void stdcall with one argument = pointer to previously allocated usb_gtd
|
||||
AllocTransfer dd ?
|
||||
; Allocate and initialize one stage of a transfer.
|
||||
; ebx -> usb_pipe, other parameters are passed through the stack:
|
||||
; buffer,size = data to transfer
|
||||
; flags = same as in usb_open_pipe:
|
||||
; bit 0 = allow short transfer, other bits reserved
|
||||
; td = pointer to the current end-of-queue descriptor
|
||||
; direction =
|
||||
; 0000b for normal transfers,
|
||||
; 1000b for control SETUP transfer,
|
||||
; 1101b for control OUT transfer,
|
||||
; 1110b for control IN transfer
|
||||
; returns eax = pointer to the new end-of-queue descriptor
|
||||
; (not included in the queue itself) or 0 on error
|
||||
InsertTransfer dd ?
|
||||
; Activate previously initialized transfer (maybe with multiple stages).
|
||||
; esi -> usb_controller, ebx -> usb_pipe,
|
||||
; [esp+4] -> first usb_gtd for the transfer,
|
||||
; ecx -> last descriptor for the transfer
|
||||
NewDevice dd ?
|
||||
; Initiate configuration of a new device (create pseudo-pipe describing that
|
||||
; device and call usb_new_device).
|
||||
; esi -> usb_controller, eax = speed (one of USB_SPEED_* constants).
|
||||
ends
|
||||
|
||||
; pointers to kernel API functions that are called from *HCI-drivers
|
||||
struct usbhc_func
|
||||
usb_process_gtd dd ?
|
||||
usb_init_static_endpoint dd ?
|
||||
usb_wakeup_if_needed dd ?
|
||||
usb_subscribe_control dd ?
|
||||
usb_subscription_done dd ?
|
||||
usb_allocate_common dd ?
|
||||
usb_free_common dd ?
|
||||
usb_td_to_virt dd ?
|
||||
usb_init_transfer dd ?
|
||||
usb_undo_tds dd ?
|
||||
usb_test_pending_port dd ?
|
||||
usb_get_tt dd ?
|
||||
usb_get_tt_think_time dd ?
|
||||
usb_new_device dd ?
|
||||
usb_disconnect_stage2 dd ?
|
||||
usb_process_wait_lists dd ?
|
||||
usb_unlink_td dd ?
|
||||
usb_is_final_packet dd ?
|
||||
usb_find_ehci_companion dd ?
|
||||
ends
|
||||
|
||||
; Controller descriptor.
|
||||
; This structure represents the common (controller-independent) part
|
||||
; of a controller for the USB code. The corresponding controller-dependent
|
||||
; part *hci_controller is located immediately before usb_controller.
|
||||
struct usb_controller
|
||||
; Two following fields organize all controllers in the global linked list.
|
||||
Next dd ?
|
||||
Prev dd ?
|
||||
HardwareFunc dd ?
|
||||
; Pointer to usb_hardware_func structure with controller-specific functions.
|
||||
NumPorts dd ?
|
||||
; Number of ports in the root hub.
|
||||
PCICoordinates dd ?
|
||||
; Device:function and bus number from PCI.
|
||||
;
|
||||
; The hardware is allowed to cache some data from hardware structures.
|
||||
; Regular operations are designed considering this,
|
||||
; but sometimes it is required to wait for synchronization of hardware cache
|
||||
; with modified structures in memory.
|
||||
; The code keeps two queues of pipes waiting for synchronization,
|
||||
; one for asynchronous (bulk/control) pipes, one for periodic pipes, hardware
|
||||
; cache is invalidated under different conditions for those types.
|
||||
; Both queues are organized in the same way, as single-linked lists.
|
||||
; There are three special positions: the head of list (new pipes are added
|
||||
; here), the first pipe to be synchronized at the current iteration,
|
||||
; the tail of list (all pipes starting from here are synchronized).
|
||||
WaitPipeListAsync dd ?
|
||||
WaitPipeListPeriodic dd ?
|
||||
; List heads.
|
||||
WaitPipeRequestAsync dd ?
|
||||
WaitPipeRequestPeriodic dd ?
|
||||
; Pending request to hardware to refresh cache for items from WaitPipeList*.
|
||||
; (Pointers to some items in WaitPipeList* or NULLs).
|
||||
ReadyPipeHeadAsync dd ?
|
||||
ReadyPipeHeadPeriodic dd ?
|
||||
; Items of RemovingList* which were released by hardware and are ready
|
||||
; for further processing.
|
||||
; (Pointers to some items in WaitPipeList* or NULLs).
|
||||
NewConnected dd ?
|
||||
; bit mask of recently connected ports of the root hub,
|
||||
; bit set = a device was recently connected to the corresponding port;
|
||||
; after USB_CONNECT_DELAY ticks of stable status these ports are moved to
|
||||
; PendingPorts
|
||||
NewDisconnected dd ?
|
||||
; bit mask of disconnected ports of the root hub,
|
||||
; bit set = a device in the corresponding port was disconnected,
|
||||
; disconnect processing is required.
|
||||
PendingPorts dd ?
|
||||
; bit mask of ports which are ready to be initialized
|
||||
ControlLock MUTEX ?
|
||||
; mutex which guards all operations with control queue
|
||||
BulkLock MUTEX ?
|
||||
; mutex which guards all operations with bulk queue
|
||||
PeriodicLock MUTEX ?
|
||||
; mutex which guards all operations with periodic queues
|
||||
WaitSpinlock:
|
||||
; spinlock guarding WaitPipeRequest/ReadyPipeHead (but not WaitPipeList)
|
||||
StartWaitFrame dd ?
|
||||
; USB frame number when WaitPipeRequest* was registered.
|
||||
ResettingHub dd ?
|
||||
; Pointer to usb_hub responsible for the currently resetting port, if any.
|
||||
; NULL for the root hub.
|
||||
ResettingPort db ?
|
||||
; Port that is currently resetting, 0-based.
|
||||
ResettingSpeed db ?
|
||||
; Speed of currently resetting device.
|
||||
ResettingStatus db ?
|
||||
; Status of port reset. 0 = no port is resetting, -1 = reset failed,
|
||||
; 1 = reset in progress, 2 = reset recovery in progress.
|
||||
rb 1 ; alignment
|
||||
ResetTime dd ?
|
||||
; Time when reset signalling or reset recovery has been started.
|
||||
SetAddressBuffer rb 8
|
||||
; Buffer for USB control command SET_ADDRESS.
|
||||
ExistingAddresses rd 128/32
|
||||
; Bitmask for 128 bits; bit i is cleared <=> address i is free for allocating
|
||||
; for new devices. Bit 0 is always set.
|
||||
ConnectedTime rd 16
|
||||
; Time, in timer ticks, when the port i has signalled the connect event.
|
||||
; Valid only if bit i in NewConnected is set.
|
||||
DevicesByPort rd 16
|
||||
; Pointer to usb_pipe for zero endpoint (which serves as device handle)
|
||||
; for each port.
|
||||
ends
|
||||
|
||||
; Pipe descriptor.
|
||||
; * An USB pipe is described by two structures, for hardware and for software.
|
||||
; * This is the software part. The hardware part is defined in a driver
|
||||
; of the corresponding controller.
|
||||
; * The hardware part is located immediately before usb_pipe,
|
||||
; both are allocated at once by controller-specific code
|
||||
; (it knows the total length, which depends on the hardware part).
|
||||
struct usb_pipe
|
||||
Controller dd ?
|
||||
; Pointer to usb_controller structure corresponding to this pipe.
|
||||
; Must be the first dword after hardware part, see *hci_new_device.
|
||||
;
|
||||
; Every endpoint is included into one of processing lists:
|
||||
; * Bulk list contains all Bulk endpoints.
|
||||
; * Control list contains all Control endpoints.
|
||||
; * Several Periodic lists serve Interrupt endpoints with different interval.
|
||||
; - There are N=2^n "leaf" periodic lists for N ms interval, one is processed
|
||||
; in the frames 0,N,2N,..., another is processed in the frames
|
||||
; 1,1+N,1+2N,... and so on. The hardware starts processing of periodic
|
||||
; endpoints in every frame from the list identified by lower n bits of the
|
||||
; frame number; the addresses of these N lists are written to the
|
||||
; controller data area during the initialization.
|
||||
; - We assume that n=5, N=32 to simplify the code and compact the data.
|
||||
; OHCI works in this way. UHCI and EHCI actually have n=10, N=1024,
|
||||
; but this is an overkill for interrupt endpoints; the large value of N is
|
||||
; useful only for isochronous transfers in UHCI and EHCI. UHCI/EHCI code
|
||||
; initializes "leaf" lists k,k+32,k+64,...,k+(1024-32) to the same value,
|
||||
; giving essentially N=32.
|
||||
; This restriction means that the actual maximum interval of polling any
|
||||
; interrupt endpoint is 32ms, which seems to be a reasonable value.
|
||||
; - Similarly, there are 16 lists for 16-ms interval, 8 lists for 8-ms
|
||||
; interval and so on. Finally, there is one list for 1ms interval. Their
|
||||
; addresses are not directly known to the controller.
|
||||
; - The hardware serves endpoints following a physical link from the hardware
|
||||
; part.
|
||||
; - The hardware links are organized as follows. If the list item is not the
|
||||
; last, it's hardware link points to the next item. The hardware link of
|
||||
; the last item points to the first item of the "next" list.
|
||||
; - The "next" list for k-th and (k+M)-th periodic lists for interval 2M ms
|
||||
; is the k-th periodic list for interval M ms, M >= 1. In this scheme,
|
||||
; if two "previous" lists are served in the frames k,k+2M,k+4M,...
|
||||
; and k+M,k+3M,k+5M,... correspondingly, the "next" list is served in
|
||||
; the frames k,k+M,k+2M,k+3M,k+4M,k+5M,..., which is exactly what we want.
|
||||
; - The links between Periodic, Control, Bulk lists and the processing of
|
||||
; Isochronous endpoints are controller-specific.
|
||||
; * The head of every processing list is a static entry which does not
|
||||
; correspond to any real pipe. It is described by usb_static_ep
|
||||
; structure, not usb_pipe. For OHCI and UHCI, sizeof.usb_static_ep plus
|
||||
; sizeof hardware part is 20h, the total number of lists is
|
||||
; 32+16+8+4+2+1+1+1 = 65, so all these structures fit in one page,
|
||||
; leaving space for other data. This is another reason for 32ms limit.
|
||||
; * Static endpoint descriptors are kept in *hci_controller structure.
|
||||
; * All items in every processing list, including the static head, are
|
||||
; organized in a double-linked list using .NextVirt and .PrevVirt fields.
|
||||
; * [[item.NextVirt].PrevVirt] = [[item.PrevVirt].NextVirt] for all items.
|
||||
NextVirt dd ?
|
||||
; Next endpoint in the processing list.
|
||||
; See also PrevVirt field and the description before NextVirt field.
|
||||
PrevVirt dd ?
|
||||
; Previous endpoint in the processing list.
|
||||
; See also NextVirt field and the description before NextVirt field.
|
||||
;
|
||||
; Every pipe has the associated transfer queue, that is, the double-linked
|
||||
; list of Transfer Descriptors aka TD. For Control, Bulk and Interrupt
|
||||
; endpoints this list consists of usb_gtd structures
|
||||
; (GTD = General Transfer Descriptors), for Isochronous endpoints
|
||||
; this list consists of usb_itd structures, which are not developed yet.
|
||||
; The pipe needs to know only the last TD; the first TD can be
|
||||
; obtained as [[pipe.LastTD].NextVirt].
|
||||
LastTD dd ?
|
||||
; Last TD in the transfer queue.
|
||||
;
|
||||
; All opened pipes corresponding to the same physical device are organized in
|
||||
; the double-linked list using .NextSibling and .PrevSibling fields.
|
||||
; The head of this list is kept in usb_device_data structure (OpenedPipeList).
|
||||
; This list is used when the device is disconnected and all pipes for the
|
||||
; device should be closed.
|
||||
; Also, all pipes closed due to disconnect must remain valid at least until
|
||||
; driver-provided disconnect function returns; all should-be-freed-but-not-now
|
||||
; pipes for one device are organized in another double-linked list with
|
||||
; the head in usb_device_data.ClosedPipeList; this list uses the same link
|
||||
; fields, one pipe can never be in both lists.
|
||||
NextSibling dd ?
|
||||
; Next pipe for the physical device.
|
||||
PrevSibling dd ?
|
||||
; Previous pipe for the physical device.
|
||||
;
|
||||
; When hardware part of pipe is changed, some time is needed before further
|
||||
; actions so that hardware reacts on this change. During that time,
|
||||
; all changed pipes are organized in single-linked list with the head
|
||||
; usb_controller.WaitPipeList* and link field NextWait.
|
||||
; Currently there are two possible reasons to change:
|
||||
; change of address/packet size in initial configuration,
|
||||
; close of the pipe. They are distinguished by USB_FLAG_CLOSED.
|
||||
NextWait dd ?
|
||||
Lock MUTEX
|
||||
; Mutex that guards operations with transfer queue for this pipe.
|
||||
Type db ?
|
||||
; Type of pipe, one of {CONTROL,ISOCHRONOUS,BULK,INTERRUPT}_PIPE.
|
||||
Flags db ?
|
||||
; Combination of flags, USB_FLAG_*.
|
||||
rb 2 ; dword alignment
|
||||
DeviceData dd ?
|
||||
; Pointer to usb_device_data, common for all pipes for one device.
|
||||
ends
|
||||
|
||||
; This structure describes the static head of every list of pipes.
|
||||
struct usb_static_ep
|
||||
; software fields
|
||||
Bandwidth dd ?
|
||||
; valid only for interrupt/isochronous USB1 lists
|
||||
; The offsets of the following two fields must be the same in this structure
|
||||
; and in usb_pipe.
|
||||
NextVirt dd ?
|
||||
PrevVirt dd ?
|
||||
ends
|
||||
|
||||
; This structure represents one transfer descriptor
|
||||
; ('g' stands for "general" as opposed to isochronous usb_itd).
|
||||
; Note that one transfer can have several descriptors:
|
||||
; a control transfer has three stages.
|
||||
; Additionally, every controller has a limit on transfer length with
|
||||
; one descriptor (packet size for UHCI, 1K for OHCI, 4K for EHCI),
|
||||
; large transfers must be split into individual packets according to that limit.
|
||||
struct usb_gtd
|
||||
Callback dd ?
|
||||
; Zero for intermediate descriptors, pointer to callback function
|
||||
; for final descriptor. See the docs for description of the callback.
|
||||
UserData dd ?
|
||||
; Dword which is passed to Callback as is, not used by USB code itself.
|
||||
; Two following fields organize all descriptors for one pipe in
|
||||
; the linked list.
|
||||
NextVirt dd ?
|
||||
PrevVirt dd ?
|
||||
Pipe dd ?
|
||||
; Pointer to the parent usb_pipe.
|
||||
Buffer dd ?
|
||||
; Pointer to data for this descriptor.
|
||||
Length dd ?
|
||||
; Length of data for this descriptor.
|
||||
ends
|
||||
|
||||
; Interface-specific data. Several interfaces of one device can operate
|
||||
; independently, each is controlled by some driver and is identified by
|
||||
; some driver-specific data passed as is to the driver.
|
||||
struct usb_interface_data
|
||||
DriverData dd ?
|
||||
; Passed as is to the driver.
|
||||
DriverFunc dd ?
|
||||
; Pointer to USBSRV structure for the driver.
|
||||
ends
|
||||
|
||||
; Device-specific data.
|
||||
struct usb_device_data
|
||||
PipeListLock MUTEX
|
||||
; Lock guarding OpenedPipeList. Must be the first item of the structure,
|
||||
; the code passes pointer to usb_device_data as is to mutex_lock/unlock.
|
||||
OpenedPipeList rd 2
|
||||
; List of all opened pipes for the device.
|
||||
; Used when the device is disconnected, so all pipes should be closed.
|
||||
ClosedPipeList rd 2
|
||||
; List of all closed, but still valid pipes for the device.
|
||||
; A pipe closed with USBClosePipe is just deallocated,
|
||||
; but a pipe closed due to disconnect must remain valid until driver-provided
|
||||
; disconnect handler returns; this list links all such pipes to deallocate them
|
||||
; after disconnect processing.
|
||||
NumPipes dd ?
|
||||
; Number of not-yet-closed pipes.
|
||||
Hub dd ?
|
||||
; NULL if connected to the root hub, pointer to usb_hub otherwise.
|
||||
TTHub dd ?
|
||||
; Pointer to usb_hub for (the) hub with Transaction Translator for the device,
|
||||
; NULL if the device operates in the same speed as the controller.
|
||||
Port db ?
|
||||
; Port on the hub, zero-based.
|
||||
TTPort db ?
|
||||
; Port on the TTHub, zero-based.
|
||||
DeviceDescrSize db ?
|
||||
; Size of device descriptor.
|
||||
Speed db ?
|
||||
; Device speed, one of USB_SPEED_*.
|
||||
NumInterfaces dd ?
|
||||
; Number of interfaces.
|
||||
ConfigDataSize dd ?
|
||||
; Total size of data associated with the configuration descriptor
|
||||
; (including the configuration descriptor itself).
|
||||
Interfaces dd ?
|
||||
; Offset from the beginning of this structure to Interfaces field.
|
||||
; Variable-length fields:
|
||||
; DeviceDescriptor:
|
||||
; device descriptor starts here
|
||||
; ConfigDescriptor = DeviceDescriptor + DeviceDescrSize
|
||||
; configuration descriptor with all associated data
|
||||
; Interfaces = ALIGN_UP(ConfigDescriptor + ConfigDataSize, 4)
|
||||
; array of NumInterfaces elements of type usb_interface_data
|
||||
ends
|
||||
|
||||
usb_device_data.DeviceDescriptor = sizeof.usb_device_data
|
Loading…
Reference in New Issue
Block a user