2 * ehci.c - USB driver stack project for Windows NT 4.0
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "usbdriver.h"
25 //----------------------------------------------------------
29 #define DEFAULT_ENDP( enDP ) \
30 ( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP )
32 #define dev_from_endp( enDP ) \
33 ( DEFAULT_ENDP( enDP )\
34 ? ( ( PUSB_DEV )( enDP )->pusb_if )\
35 : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) )
37 #define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK )
39 #define endp_num( enDP ) \
40 ( DEFAULT_ENDP( enDP )\
42 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) )
44 #define endp_dir( enDP ) \
45 ( DEFAULT_ENDP( enDP )\
47 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ? 1 : 0 )
49 #define dev_set_state( pdEV, staTE ) \
50 ( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) )
52 #define endp_max_packet_size( enDP ) \
53 ( DEFAULT_ENDP( enDP )\
54 ? ( ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc ? \
55 ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc->bMaxPacketSize0\
57 : ( enDP->pusb_endp_desc->wMaxPacketSize & 0x7ff ) )
59 #define endp_mult_count( endp ) ( ( ( endp->pusb_endp_desc->wMaxPacketSize & 0x1800 ) >> 11 ) + 1 )
63 #define release_adapter( padapTER ) \
68 #define release_adapter( padapTER ) (void)(padapTER)
71 #define get_int_idx( _urb, _idx ) \
74 interVAL = ( UCHAR )( ( _urb )->pipe >> 24 );\
75 for( _idx = 1; _idx < 9; _idx++ )\
84 #define ehci_insert_urb_to_schedule( eHCI, pURB, rET ) \
86 SYNC_PARAM sync_param;\
87 sync_param.ehci = eHCI;\
88 sync_param.context = ( pURB );\
89 sync_param.ret = FALSE;\
91 rET = KeSynchronizeExecution( eHCI->pdev_ext->ehci_int, ehci_sync_insert_urb_schedule, &sync_param );\
94 #define EHCI_ERROR_INT ( STS_FATAL | STS_ERR )
95 #define EHCI_QH_ERROR( qh_contENT ) ( ( qh_contENT )->cur_qtd.status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) )
96 #define EHCI_QTD_ERROR( qtd_contENT ) ( ( qtd_contENT )->status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) )
98 #define EHCI_READ_PORT_ULONG( pul ) ( *pul )
99 #define EHCI_WRITE_PORT_ULONG( pul, src ) \
102 *pul = ( ULONG )src;\
103 cmd_reg = EHCI_READ_PORT_ULONG( ehci->port_base + EHCI_USBCMD );\
108 #define EHCI_READ_PORT_UCHAR( pch ) ( *pch )
109 #define EHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src )
111 #define EHCI_READ_PORT_USHORT( psh ) ( *psh )
112 #define EHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src )
114 #define press_doorbell( eHCI ) \
117 tmp = EHCI_READ_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ) );\
119 EHCI_WRITE_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ), tmp );\
121 #define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) )
123 #define qh_from_list_entry( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
124 #define qtd_from_list_entry( pentry ) ( ( PEHCI_QTD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
125 #define itd_from_list_entry( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
126 #define sitd_from_list_entry( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
127 #define fstn_from_list_entry( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
129 #define qh_from_schedule( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
130 #define itd_from_schedule( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
131 #define sitd_from_schedule( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
132 #define fstn_from_schedule( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) )
134 #define elem_type( ptr, from_list ) ( from_list ? ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, elem_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) \
135 : ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, sched_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) )
137 // #define elem_type_list_entry( pentry ) ( ( qh_from_schedule( pentry )->hw_next & 0x06 ) >> 1 )
138 #define elem_type_list_entry( pentry ) ( elem_type( pentry, TRUE ) )
140 #define get_parent_hs_hub( pDEV, parent_HUB, port_IDX ) \
142 parent_HUB = pDEV->parent_dev;\
143 port_IDX = pdev->port_idx;\
146 if( ( parent_HUB->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_HUB )\
151 if( ( parent_HUB->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )\
153 port_IDX = parent_HUB->port_idx;\
154 parent_HUB = parent_HUB->parent_dev;\
161 #define init_elem_phys_part( pelnk ) RtlZeroMemory( ( PVOID )( ( ( ULONG )( pelnk )->phys_part ) & PHYS_PART_ADDR_MASK ), get_elem_phys_part_size( ( ( ( ULONG )( pelnk )->phys_part ) & 0x06 ) >> 1 ) )
162 #define REAL_INTERVAL ( 1 << pipe_content->interval )
164 #define elem_safe_free( ptHIS, single ) \
167 em_type = ( UCHAR )elem_type( ptHIS, TRUE ); \
170 if( em_type == INIT_LIST_FLAG_QTD )\
172 elem_pool_lock( qtd_pool, TRUE );\
174 elem_pool_free_elem( qtd_from_list_entry( ptHIS )->elem_head_link );\
176 elem_pool_free_elems( qtd_from_list_entry( ptHIS )->elem_head_link );\
177 elem_pool_unlock( qtd_pool, TRUE );\
179 else if( em_type == INIT_LIST_FLAG_ITD )\
181 elem_pool_lock( itd_pool, TRUE );\
183 elem_pool_free_elem( itd_from_list_entry( ptHIS )->elem_head_link );\
185 elem_pool_free_elems( itd_from_list_entry( ptHIS )->elem_head_link );\
186 elem_pool_unlock( itd_pool, TRUE );\
188 else if( em_type == INIT_LIST_FLAG_SITD )\
190 elem_pool_lock( sitd_pool, TRUE );\
192 elem_pool_free_elem( sitd_from_list_entry( ptHIS )->elem_head_link );\
194 elem_pool_free_elems( sitd_from_list_entry( ptHIS )->elem_head_link );\
195 elem_pool_unlock( sitd_pool, TRUE );\
197 else if( em_type == INIT_LIST_FLAG_FSTN )\
199 elem_pool_lock( fstn_pool, TRUE );\
201 elem_pool_free_elem( fstn_from_list_entry( ptHIS )->elem_head_link );\
203 elem_pool_free_elems( fstn_from_list_entry( ptHIS )->elem_head_link );\
204 elem_pool_unlock( fstn_pool, TRUE );\
206 else if( em_type == INIT_LIST_FLAG_QH )\
208 elem_pool_lock( qh_pool, TRUE );\
210 elem_pool_free_elem( qh_from_list_entry( ptHIS )->elem_head_link );\
212 elem_pool_free_elems( qh_from_list_entry( ptHIS )->elem_head_link );\
213 elem_pool_unlock( qh_pool, TRUE );\
219 #define min( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
222 #define max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
225 #define CLR_RH2_PORTSTAT( port_idx, x ) \
228 addr = ( PULONG )( ehci->port_base + port_idx ); \
229 status = EHCI_READ_PORT_ULONG( addr ); \
230 status = ( status & 0xfffffd5 ) & ~( x ); \
231 EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \
234 #define SET_RH2_PORTSTAT( port_idx, x ) \
237 addr = ( PULONG )( ehci->port_base + port_idx ); \
238 status = EHCI_READ_PORT_ULONG( addr ); \
240 status = ( status & 0xffffffd1 ) | ( x ); \
242 status = ( status & 0xffffffd5 ) | ( x ); \
243 EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \
246 #define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) )
247 #define ehci_from_dev( dEV ) ( ehci_from_hcd( dEV->hcd ) )
249 #define ehci_copy_overlay( pQHC, pTDC ) \
254 pqh1 = ( PEHCI_QH )( pQHC );\
255 ptd1 = ( PEHCI_QTD )( pTDC );\
256 td_size = get_elem_phys_part_size( INIT_LIST_FLAG_QTD );\
257 ( pQHC )->cur_qtd_ptr = ptd1->phys_addr;\
258 RtlZeroMemory( &( pQHC )->cur_qtd, td_size );\
259 ( pQHC )->cur_qtd.data_toggle = ( pTDC )->data_toggle;\
260 pqh1->hw_qtd_next = ptd1->phys_addr;\
261 pqh1->hw_alt_next = EHCI_PTR_TERM;\
275 } SYNC_PARAM
, *PSYNC_PARAM
;
278 ehci_alloc(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, ULONG bus_addr
, PUSB_DEV_MANAGER dev_mgr
);
280 BOOLEAN
ehci_init_schedule(PEHCI_DEV ehci
, PADAPTER_OBJECT padapter
);
282 BOOLEAN
ehci_release(PDEVICE_OBJECT pdev
);
284 static VOID
ehci_stop(PEHCI_DEV ehci
);
286 BOOLEAN
ehci_destroy_schedule(PEHCI_DEV ehci
);
288 BOOLEAN NTAPI
ehci_sync_insert_urb_schedule(PVOID context
);
290 VOID
ehci_init_hcd_interface(PEHCI_DEV ehci
);
292 NTSTATUS
ehci_rh_submit_urb(PUSB_DEV rh
, PURB purb
);
294 NTSTATUS
ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP irp
);
296 VOID
ehci_generic_urb_completion(PURB purb
, PVOID context
);
298 static NTSTATUS
ehci_internal_submit_bulk(PEHCI_DEV ehci
, PURB purb
);
300 static NTSTATUS
ehci_internal_submit_int(PEHCI_DEV ehci
, PURB purb
);
302 static NTSTATUS
ehci_internal_submit_ctrl(PEHCI_DEV ehci
, PURB purb
);
304 static NTSTATUS
ehci_internal_submit_iso(PEHCI_DEV ehci
, PURB purb
);
306 static ULONG
ehci_scan_iso_error(PEHCI_DEV ehci
, PURB purb
);
308 BOOLEAN
ehci_claim_bandwidth(PEHCI_DEV ehci
, PURB purb
, BOOLEAN claim_bw
); //true to claim band-width, false to free band-width
310 static VOID
ehci_insert_bulk_schedule(PEHCI_DEV ehci
, PURB purb
);
312 #define ehci_insert_control_schedule ehci_insert_bulk_schedule
314 static VOID
ehci_insert_int_schedule(PEHCI_DEV ehci
, PURB purb
);
316 static VOID
ehci_insert_iso_schedule(PEHCI_DEV ehci
, PURB purb
);
318 #define ehci_remove_control_from_schedule ehci_remove_bulk_from_schedule
320 PDEVICE_OBJECT
ehci_probe(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, PUSB_DEV_MANAGER dev_mgr
);
322 PDEVICE_OBJECT
ehci_create_device(PDRIVER_OBJECT drvr_obj
, PUSB_DEV_MANAGER dev_mgr
);
324 BOOLEAN
ehci_delete_device(PDEVICE_OBJECT pdev
);
326 VOID
ehci_get_capabilities(PEHCI_DEV ehci
, PBYTE base
);
328 BOOLEAN NTAPI
ehci_isr(PKINTERRUPT interrupt
, PVOID context
);
330 BOOLEAN
ehci_start(PHCD hcd
);
332 extern VOID
rh_timer_svc_reset_port_completion(PUSB_DEV dev
, PVOID context
);
334 extern VOID
rh_timer_svc_int_completion(PUSB_DEV dev
, PVOID context
);
336 extern USB_DEV_MANAGER g_dev_mgr
;
339 ULONG debug_level
= DBGLVL_MAXIMUM
;
340 PDRIVER_OBJECT usb_driver_obj
= NULL
;
342 //pending endpoint pool funcs
344 ehci_wait_ms(PEHCI_DEV ehci
, LONG ms
)
350 lms
.QuadPart
= -10 * ms
;
351 KeSetTimer(&ehci
->reset_timer
, lms
, NULL
);
353 KeWaitForSingleObject(&ehci
->reset_timer
, Executive
, KernelMode
, FALSE
, NULL
);
359 init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
)
365 pool
->pending_endp_array
=
366 usb_alloc_mem(NonPagedPool
, sizeof(UHCI_PENDING_ENDP
) * UHCI_MAX_PENDING_ENDPS
);
367 InitializeListHead(&pool
->free_que
);
368 pool
->free_count
= 0;
369 pool
->total_count
= UHCI_MAX_PENDING_ENDPS
;
370 KeInitializeSpinLock(&pool
->pool_lock
);
372 for(i
= 0; i
< MAX_TIMER_SVCS
; i
++)
374 free_pending_endp(pool
, &pool
->pending_endp_array
[i
]);
382 free_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, PUHCI_PENDING_ENDP pending_endp
)
384 if (pool
== NULL
|| pending_endp
== NULL
)
389 RtlZeroMemory(pending_endp
, sizeof(UHCI_PENDING_ENDP
));
390 InsertTailList(&pool
->free_que
, (PLIST_ENTRY
) & pending_endp
->endp_link
);
397 alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, LONG count
)
399 PUHCI_PENDING_ENDP
new;
400 if (pool
== NULL
|| count
!= 1)
403 if (pool
->free_count
<= 0)
406 new = (PUHCI_PENDING_ENDP
) RemoveHeadList(&pool
->free_que
);
412 destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
)
417 InitializeListHead(&pool
->free_que
);
418 pool
->free_count
= pool
->total_count
= 0;
419 usb_free_mem(pool
->pending_endp_array
);
420 pool
->pending_endp_array
= NULL
;
426 #define ehci_wait_ms uhci_wait_ms
427 extern VOID
uhci_wait_ms(PEHCI_DEV ehci
, LONG ms
);
429 extern BOOLEAN
init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
);
431 extern BOOLEAN
free_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, PUHCI_PENDING_ENDP pending_endp
);
433 extern PUHCI_PENDING_ENDP
alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool
, LONG count
);
435 extern BOOLEAN
destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool
);
439 //end of pending endpoint pool funcs
442 ehci_cancel_pending_endp_urb(IN PVOID Parameter
)
444 PLIST_ENTRY abort_list
;
447 USE_BASIC_NON_PENDING_IRQL
;
449 abort_list
= (PLIST_ENTRY
) Parameter
;
451 if (abort_list
== NULL
)
454 while (IsListEmpty(abort_list
) == FALSE
)
456 //these devs are protected by purb's ref-count
457 purb
= (PURB
) RemoveHeadList(abort_list
);
459 // purb->status is set when they are added to abort_list
461 ehci_generic_urb_completion(purb
, purb
->context
);
463 lock_dev(pdev
, FALSE
);
465 unlock_dev(pdev
, FALSE
);
467 usb_free_mem(abort_list
);
472 ehci_process_pending_endp(PEHCI_DEV ehci
)
475 LIST_ENTRY temp_list
, abort_list
;
479 NTSTATUS can_submit
= STATUS_SUCCESS
;
480 PWORK_QUEUE_ITEM pwork_item
;
481 PLIST_ENTRY cancel_list
;
482 PUSB_DEV pparent
= NULL
;
491 InitializeListHead(&temp_list
);
492 InitializeListHead(&abort_list
);
495 ehci_dbg_print(DBGLVL_MEDIUM
, ("ehci_process_pending_endp(): entering..., ehci=0x%x\n", ehci
));
497 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
498 while (IsListEmpty(&ehci
->pending_endp_list
) == FALSE
)
501 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_process_pending_endp(): pending_endp_list=0x%x\n",
502 &ehci
->pending_endp_list
));
505 pthis
= RemoveHeadList(&ehci
->pending_endp_list
);
506 pendp
= ((PUHCI_PENDING_ENDP
) pthis
)->pendp
;
507 pdev
= dev_from_endp(pendp
);
508 lock_dev(pdev
, TRUE
);
510 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
512 unlock_dev(pdev
, TRUE
);
513 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
514 //delegate to ehci_remove_device for remiving the purb queue on the endpoint
517 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
519 // prepare split transaction
520 unlock_dev(pdev
, TRUE
);
522 // pparent won't be removed when pending_endp_list_lock is acquired.
523 get_parent_hs_hub(pdev
, pparent
, port_idx
);
528 ehci_dbg_print(DBGLVL_MEDIUM
,
529 ("ehci_process_pending_endp(): full/low speed device with no parent!!!\n"));
530 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
534 if (hub_lock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
)) == FALSE
)
536 lock_dev(pdev
, TRUE
);
537 if (dev_state(pdev
) != USB_DEV_STATE_ZOMB
)
539 // reinsert the pending-endp to the list
540 InsertTailList(&temp_list
, pthis
);
541 unlock_dev(pdev
, TRUE
);
545 // delegate to ehci_remove_device for purb removal
546 unlock_dev(pdev
, TRUE
);
547 free_pending_endp(&ehci
->pending_endp_pool
,
548 struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
553 // backup the hub address for future use
554 hub_addr
= pparent
->dev_addr
;
556 lock_dev(pdev
, TRUE
);
557 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
559 unlock_dev(pdev
, TRUE
);
560 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
561 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
568 if (endp_state(pendp
) == USB_ENDP_FLAG_STALL
)
570 while (IsListEmpty(&pendp
->urb_list
) == FALSE
)
572 purb
= (PURB
) RemoveHeadList(&pendp
->urb_list
);
573 purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
574 InsertTailList(&abort_list
, (LIST_ENTRY
*) purb
);
576 InitializeListHead(&pendp
->urb_list
);
577 unlock_dev(pdev
, TRUE
);
578 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
580 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
584 if (IsListEmpty(&pendp
->urb_list
) == FALSE
)
586 purb
= (PURB
) RemoveHeadList(&pendp
->urb_list
);
591 InitializeListHead(&pendp
->urb_list
);
592 unlock_dev(pdev
, TRUE
);
593 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
595 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
601 ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
= hub_addr
;
602 ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
= port_idx
;
605 // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
606 switch (endp_type(pendp
))
608 case USB_ENDPOINT_XFER_BULK
:
610 can_submit
= ehci_internal_submit_bulk(ehci
, purb
);
613 case USB_ENDPOINT_XFER_CONTROL
:
615 can_submit
= ehci_internal_submit_ctrl(ehci
, purb
);
618 case USB_ENDPOINT_XFER_INT
:
620 can_submit
= ehci_internal_submit_int(ehci
, purb
);
623 case USB_ENDPOINT_XFER_ISOC
:
625 can_submit
= ehci_internal_submit_iso(ehci
, purb
);
630 if (can_submit
== STATUS_NO_MORE_ENTRIES
)
632 //no enough bandwidth or tds
633 InsertHeadList(&pendp
->urb_list
, &purb
->urb_link
);
634 InsertTailList(&temp_list
, pthis
);
638 // otherwise error or success
639 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
641 if (can_submit
!= STATUS_SUCCESS
)
644 InsertTailList(&abort_list
, (LIST_ENTRY
*) purb
);
645 purb
->status
= can_submit
;
648 unlock_dev(pdev
, TRUE
);
649 if (can_submit
!= STATUS_SUCCESS
&& tt_needed
)
651 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
655 if (IsListEmpty(&temp_list
) == FALSE
)
657 //re-append them to the pending_endp_list
658 ListFirst(&temp_list
, pthis
);
659 RemoveEntryList(&temp_list
);
660 MergeList(&ehci
->pending_endp_list
, pthis
);
662 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
664 if (IsListEmpty(&abort_list
) == FALSE
)
667 cancel_list
= (PLIST_ENTRY
) usb_alloc_mem(NonPagedPool
, sizeof(WORK_QUEUE_ITEM
) + sizeof(LIST_ENTRY
));
670 ListFirst(&abort_list
, pthis
);
671 RemoveEntryList(&abort_list
);
672 InsertTailList(pthis
, cancel_list
);
674 pwork_item
= (PWORK_QUEUE_ITEM
) & cancel_list
[1];
676 // we do not need to worry the ehci_cancel_pending_endp_urb running when the
677 // driver is unloading since purb-reference count will prevent the dev_mgr to
678 // quit till all the reference count to the dev drop to zero.
679 ExInitializeWorkItem(pwork_item
, ehci_cancel_pending_endp_urb
, (PVOID
) cancel_list
);
680 ExQueueWorkItem(pwork_item
, DelayedWorkQueue
);
686 ehci_submit_urb(PEHCI_DEV ehci
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
689 PUHCI_PENDING_ENDP pending_endp
;
694 return STATUS_INVALID_PARAMETER
;
696 if (pdev
== NULL
|| pendp
== NULL
|| purb
== NULL
)
698 // give a chance to those pending urb, especially for clearing hub tt
699 ehci_process_pending_endp(ehci
);
700 return STATUS_INVALID_PARAMETER
;
703 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
704 lock_dev(pdev
, TRUE
);
706 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
708 status
= purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
712 if (dev_class(pdev
) == USB_DEV_CLASS_ROOT_HUB
)
714 unlock_dev(pdev
, TRUE
);
715 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
716 status
= ehci_rh_submit_urb(pdev
, purb
);
723 purb
->pendp
= &pdev
->default_endp
;
725 if (dev_from_endp(purb
->pendp
) != pdev
)
727 status
= purb
->status
= STATUS_INVALID_PARAMETER
;
731 if (endp_state(purb
->pendp
) == USB_ENDP_FLAG_STALL
)
733 status
= purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
737 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
744 purb
->rest_bytes
= purb
->data_length
;
746 if (endp_type(purb
->pendp
) == USB_ENDPOINT_XFER_BULK
)
747 purb
->bytes_to_transfer
= (purb
->data_length
> EHCI_MAX_SIZE_TRANSFER
? EHCI_MAX_SIZE_TRANSFER
: purb
->data_length
); //multiple transfer for large data block
749 purb
->bytes_to_transfer
= purb
->data_length
;
751 ehci_dbg_print(DBGLVL_MEDIUM
, ("ehci_submit_urb(): bytes_to_transfer=0x%x\n", purb
->bytes_to_transfer
));
753 purb
->bytes_transfered
= 0;
754 InitializeListHead(&purb
->trasac_list
);
755 purb
->last_finished_td
= &purb
->trasac_list
;
756 purb
->flags
&= ~(URB_FLAG_STATE_MASK
| URB_FLAG_IN_SCHEDULE
| URB_FLAG_FORCE_CANCEL
);
757 purb
->flags
|= URB_FLAG_STATE_PENDING
;
760 i
= IsListEmpty(&pendp
->urb_list
);
761 InsertTailList(&pendp
->urb_list
, &purb
->urb_link
);
763 pdev
->ref_count
++; //for purb reference
767 //there is purb pending, simply queue it and return
768 status
= purb
->status
= STATUS_PENDING
;
771 else if (usb_endp_busy_count(purb
->pendp
) && endp_type(purb
->pendp
) != USB_ENDPOINT_XFER_ISOC
)
774 //No purb waiting but purb overlap not allowed,
775 //so leave it in queue and return, will be scheduled
778 status
= purb
->status
= STATUS_PENDING
;
782 pending_endp
= alloc_pending_endp(&ehci
->pending_endp_pool
, 1);
783 if (pending_endp
== NULL
)
786 status
= purb
->status
= STATUS_UNSUCCESSFUL
;
790 pending_endp
->pendp
= purb
->pendp
;
791 InsertTailList(&ehci
->pending_endp_list
, &pending_endp
->endp_link
);
793 unlock_dev(pdev
, TRUE
);
794 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
796 ehci_process_pending_endp(ehci
);
797 return STATUS_PENDING
;
801 RemoveEntryList(&purb
->urb_link
);
804 unlock_dev(pdev
, TRUE
);
805 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
806 ehci_process_pending_endp(ehci
);
811 ehci_set_error_code(PURB purb
, ULONG raw_status
)
813 PURB_HS_PIPE_CONTENT pipe_content
;
815 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
817 //test if the purb is canceled
818 if (purb
->flags
& URB_FLAG_FORCE_CANCEL
)
820 purb
->status
= STATUS_CANCELLED
;
822 else if (raw_status
== 0)
823 purb
->status
= STATUS_SUCCESS
;
825 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
||
826 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
827 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
)
830 if (raw_status
& QTD_STS_BABBLE
)
831 purb
->status
= USB_STATUS_DATA_OVERRUN
;
833 else if (raw_status
& QTD_STS_HALT
)
834 purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
836 else if (raw_status
& QTD_STS_DBE
)
837 purb
->status
= USB_STATUS_BUFFER_OVERRUN
;
839 else if (raw_status
& QTD_STS_XACT
)
840 purb
->status
= USB_STATUS_CRC
; // crc is included in xact err.
842 else if (raw_status
& QTD_STS_MMF
)
843 purb
->status
= USB_STATUS_BTSTUFF
;
846 purb
->status
= STATUS_UNSUCCESSFUL
;
848 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
850 if (pipe_content
->speed_high
)
852 if (raw_status
& ITD_STS_BUFERR
)
853 purb
->status
= USB_STATUS_BUFFER_OVERRUN
;
855 else if (raw_status
& ITD_STS_BABBLE
)
856 purb
->status
= USB_STATUS_BABBLE_DETECTED
;
858 else if (raw_status
& ITD_STS_XACTERR
) // Xact Err
859 purb
->status
= USB_STATUS_CRC
;
862 purb
->status
= STATUS_UNSUCCESSFUL
;
867 if (raw_status
& SITD_STS_ERR
) // ERR is received from hub's tt
868 purb
->status
= USB_STATUS_ERROR
;
870 else if (raw_status
& SITD_STS_DBE
)
871 purb
->status
= USB_STATUS_BUFFER_OVERRUN
;
873 else if (raw_status
& SITD_STS_BABBLE
)
874 purb
->status
= USB_STATUS_BABBLE_DETECTED
;
876 else if (raw_status
& SITD_STS_XACTERR
) // Xact Error
877 purb
->status
= USB_STATUS_CRC
;
879 else if (raw_status
& SITD_STS_MISSFRM
) // missing microframe
880 purb
->status
= USB_STATUS_DATA_TOGGLE_MISMATCH
;
883 purb
->status
= STATUS_UNSUCCESSFUL
;
886 if (purb
->status
!= STATUS_SUCCESS
)
888 hcd_dbg_print(DBGLVL_MEDIUM
, ("ehci_set_error_code(): error status 0x%x\n", raw_status
));
894 ehci_sync_remove_urb_finished(PVOID context
)
897 PLIST_ENTRY pthis
, pnext
, ptemp
;
901 pparam
= (PSYNC_PARAM
) context
;
903 ptemp
= (PLIST_ENTRY
) pparam
->context
;
907 return (UCHAR
) (pparam
->ret
= FALSE
);
910 ListFirst(&ehci
->urb_list
, pthis
);
913 //remove urbs not in the schedule
914 ListNext(&ehci
->urb_list
, pthis
, pnext
);
917 if ((purb
->flags
& URB_FLAG_IN_SCHEDULE
) == 0)
919 //finished or canceled( not applied for split bulk ).
920 RemoveEntryList(pthis
);
921 InsertTailList(ptemp
, pthis
);
930 ehci_dpc_callback(PKDPC dpc
, PVOID context
, PVOID sysarg1
, PVOID sysarg2
)
935 PLIST_ENTRY pthis
, pnext
;
939 PUHCI_PENDING_ENDP pending_endp
;
945 ULONG ehci_status
, urb_status
;
947 SYNC_PARAM sync_param
;
949 USE_BASIC_NON_PENDING_IRQL
;
951 ehci
= (PEHCI_DEV
) context
;
955 ehci_status
= (ULONG
) sysarg1
;
957 InitializeListHead(&temp_list
);
959 sync_param
.ehci
= ehci
;
960 sync_param
.context
= (PVOID
) & temp_list
;
962 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_dpc_callback(): entering..., ehci=0x%x\n", ehci
));
963 //remove finished purb from ehci's purb-list
964 KeSynchronizeExecution(ehci
->pdev_ext
->ehci_int
, ehci_sync_remove_urb_finished
, &sync_param
);
966 //release resources( itds, sitds, fstns, tds, and qhs ) allocated for the purb
967 while (IsListEmpty(&temp_list
) == FALSE
)
969 //not in any public queue, if do not access into dev, no race
970 //condition will occur
971 purb
= (PURB
) RemoveHeadList(&temp_list
);
972 urb_status
= purb
->status
;
973 ep_type
= endp_type(purb
->pendp
);
975 if (ep_type
== USB_ENDPOINT_XFER_ISOC
)
977 // collect error for iso transfer
978 urb_status
= ehci_scan_iso_error(ehci
, purb
);
981 //the only place we do not use this lock on non-pending-endp-list data
982 KeAcquireSpinLockAtDpcLevel(&ehci
->pending_endp_list_lock
);
983 while (IsListEmpty(&purb
->trasac_list
) == FALSE
)
986 pthis
= RemoveHeadList(&purb
->trasac_list
);
987 em_type
= (UCHAR
) elem_type(pthis
, TRUE
);
989 if (em_type
== INIT_LIST_FLAG_QH
)
991 pqh
= qh_from_list_entry(pthis
);
992 elem_safe_free(pthis
, TRUE
);
996 //must be an itd, sitd chain
997 InsertHeadList(&purb
->trasac_list
, pthis
);
998 for(i
= 0, purb
->bytes_transfered
= 0; i
< purb
->td_count
; i
++)
1000 PEHCI_QTD_CONTENT ptdc
= NULL
;
1001 PEHCI_ITD_CONTENT pitdc
;
1002 PEHCI_SITD_CONTENT psitdc
;
1004 em_type
= (UCHAR
) elem_type(pthis
, TRUE
);
1006 // accumulate data transfered in tds
1007 if (em_type
== INIT_LIST_FLAG_QTD
)
1009 ptd
= qtd_from_list_entry(pthis
);
1010 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1011 if ((ptdc
->status
& QTD_STS_ACTIVE
) == 0 && ((ptdc
->status
& QTD_ANY_ERROR
) == 0))
1012 purb
->bytes_transfered
+= ptd
->bytes_to_transfer
;
1014 else if (em_type
== INIT_LIST_FLAG_ITD
)
1017 pitdc
= (PEHCI_ITD_CONTENT
) itd_from_list_entry(pthis
);
1018 for(j
= 0; j
< 8; j
++)
1020 if ((pitdc
->status_slot
[j
].status
& ITD_STS_ACTIVE
) == 0
1021 && (pitdc
->status_slot
[j
].status
& ITD_ANY_ERROR
) == 0)
1022 purb
->bytes_transfered
+= ptdc
->bytes_to_transfer
;
1025 else if (em_type
== INIT_LIST_FLAG_SITD
)
1027 psitdc
= (PEHCI_SITD_CONTENT
) sitd_from_list_entry(pthis
);
1028 if ((psitdc
->status
& SITD_STS_ACTIVE
) == 0 && (psitdc
->status
& SITD_ANY_ERROR
) == 0)
1029 purb
->bytes_transfered
+= ptdc
->bytes_to_transfer
;
1031 ListNext(&purb
->trasac_list
, pthis
, pnext
);
1035 // check to see if an fstn is there
1036 ListFirstPrev(&purb
->trasac_list
, pthis
);
1037 if (elem_type(pthis
, TRUE
) == INIT_LIST_FLAG_FSTN
)
1039 RemoveEntryList(pthis
);
1040 elem_safe_free(pthis
, TRUE
);
1043 ListFirst(&purb
->trasac_list
, pthis
);
1044 RemoveEntryList(&purb
->trasac_list
);
1047 elem_safe_free(pthis
, FALSE
);
1049 //termination condition
1050 InitializeListHead(&purb
->trasac_list
);
1051 purb
->last_finished_td
= NULL
;
1055 if (ep_type
== USB_ENDPOINT_XFER_ISOC
|| ep_type
== USB_ENDPOINT_XFER_INT
)
1056 ehci_claim_bandwidth(ehci
, purb
, FALSE
); //release band-width
1058 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1060 ehci_set_error_code(purb
, urb_status
);
1062 pdev
= dev_from_endp(purb
->pendp
);
1063 pendp
= purb
->pendp
;
1065 // perform clear tt buffer if error on full/low bulk/control pipe
1066 if (ep_type
== USB_ENDPOINT_XFER_BULK
|| ep_type
== USB_ENDPOINT_XFER_CONTROL
)
1068 PURB_HS_PIPE_CONTENT pipe_content
;
1072 get_parent_hs_hub(pdev
, phub
, port_idx
);
1073 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1075 if (pipe_content
->speed_high
== 0 && purb
->status
!= STATUS_SUCCESS
)
1077 // lets schedule an event to clear the tt buffer
1078 hub_post_clear_tt_event(phub
, port_idx
, purb
->pipe
);
1080 else if (pipe_content
->speed_high
== 0)
1086 // release tt if no error
1087 hub_unlock_tt(phub
, (UCHAR
) port_idx
, (UCHAR
) pipe_content
->trans_type
);
1094 //since the ref_count for the purb is not released, we can safely have one
1097 if (purb
->status
== USB_STATUS_BABBLE_DETECTED
)
1099 usb_dbg_print(DBGLVL_MEDIUM
,
1100 ("ehci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n"));
1101 // ehci_start( ehci );
1104 if (ehci_status
& STS_HALT
) //&& !ehci->is_suspended
1106 ehci_start(&ehci
->hcd_interf
);
1109 //this will let the new request in ehci_generic_urb_completion to this endp
1110 //be processed rather than queued in the pending_endp_list
1111 lock_dev(pdev
, TRUE
);
1112 usb_endp_busy_count_dec(pendp
);
1113 unlock_dev(pdev
, TRUE
);
1115 if (usb_success(purb
->status
) == FALSE
)
1117 // set error code and complete the purb and purb is invalid from this point
1118 ehci_generic_urb_completion(purb
, purb
->context
);
1122 if (ep_type
== USB_ENDPOINT_XFER_BULK
)
1124 purb
->rest_bytes
-= purb
->bytes_transfered
;
1125 if (purb
->rest_bytes
)
1131 ehci_generic_urb_completion(purb
, purb
->context
);
1136 ehci_generic_urb_completion(purb
, purb
->context
);
1138 //purb is now invalid
1142 KeAcquireSpinLockAtDpcLevel(&ehci
->pending_endp_list_lock
);
1143 lock_dev(pdev
, TRUE
);
1148 if (urb_status
&& ((ep_type
== USB_ENDPOINT_XFER_BULK
) || (ep_type
== USB_ENDPOINT_XFER_INT
)))
1150 // error on int or bulk pipe, cleared in usb_reset_pipe_completion
1151 pendp
->flags
&= ~USB_ENDP_FLAG_STAT_MASK
;
1152 pendp
->flags
|= USB_ENDP_FLAG_STALL
;
1155 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1157 unlock_dev(pdev
, TRUE
);
1158 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1159 if (finished
== FALSE
)
1162 purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
1163 ehci_generic_urb_completion(purb
, purb
->context
);
1165 lock_dev(pdev
, TRUE
);
1167 unlock_dev(pdev
, TRUE
);
1172 if (finished
&& IsListEmpty(&pendp
->urb_list
) == TRUE
)
1174 unlock_dev(pdev
, TRUE
);
1175 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1178 else if (finished
== TRUE
)
1180 //has purb in the endp's purb-list
1181 if (usb_endp_busy_count(pendp
) > 0)
1183 //the urbs still have chance to be sheduled but not this time
1184 unlock_dev(pdev
, TRUE
);
1185 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1190 if (finished
== FALSE
)
1192 //a split bulk transfer, ( not the high speed split transfer )
1193 purb
->bytes_transfered
= 0;
1194 purb
->bytes_to_transfer
=
1195 EHCI_MAX_SIZE_TRANSFER
> purb
->rest_bytes
? purb
->rest_bytes
: EHCI_MAX_SIZE_TRANSFER
;
1197 //the purb is not finished
1198 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
1199 purb
->flags
|= URB_FLAG_STATE_PENDING
;
1201 InsertHeadList(&pendp
->urb_list
, &purb
->urb_link
);
1204 pending_endp
= alloc_pending_endp(&ehci
->pending_endp_pool
, 1);
1207 unlock_dev(pdev
, TRUE
);
1208 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1211 pending_endp
->pendp
= pendp
;
1212 InsertTailList(&ehci
->pending_endp_list
, &pending_endp
->endp_link
);
1214 unlock_dev(pdev
, TRUE
);
1215 KeReleaseSpinLockFromDpcLevel(&ehci
->pending_endp_list_lock
);
1218 //ah...exhausted, let's find some in the pending_endp_list to rock
1219 ehci_process_pending_endp(ehci
);
1223 static BOOLEAN NTAPI
1224 ehci_sync_cancel_urbs_dev(PVOID context
)
1226 //cancel all the urbs on one dev
1228 PUSB_DEV pdev
, dest_dev
;
1229 PSYNC_PARAM sync_param
;
1230 PLIST_ENTRY pthis
, pnext
;
1233 sync_param
= (PSYNC_PARAM
) context
;
1234 dest_dev
= (PUSB_DEV
) sync_param
->context
;
1235 ehci
= sync_param
->ehci
;
1237 if (ehci
== NULL
|| dest_dev
== NULL
)
1239 return (UCHAR
) (sync_param
->ret
= FALSE
);
1242 ListFirst(&ehci
->urb_list
, pthis
);
1245 pdev
= dev_from_endp(((PURB
) pthis
)->pendp
);
1246 if (pdev
== dest_dev
)
1248 ((PURB
) pthis
)->flags
|= URB_FLAG_FORCE_CANCEL
;
1250 ListNext(&ehci
->urb_list
, pthis
, pnext
);
1257 // signal an int for further process
1258 press_doorbell(ehci
);
1260 return (UCHAR
) (sync_param
->ret
= TRUE
);
1264 ehci_remove_device(PEHCI_DEV ehci
, PUSB_DEV dev
)
1266 PUHCI_PENDING_ENDP ppending_endp
;
1267 PLIST_ENTRY pthis
, pnext
;
1269 LIST_HEAD temp_list
;
1271 SYNC_PARAM sync_param
;
1275 if (ehci
== NULL
|| dev
== NULL
)
1278 InitializeListHead(&temp_list
);
1280 //free pending endp that has purb queued from pending endp list
1281 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1283 ListFirst(&ehci
->pending_endp_list
, pthis
);
1287 ppending_endp
= (PUHCI_PENDING_ENDP
) pthis
;
1288 ListNext(&ehci
->pending_endp_list
, pthis
, pnext
);
1289 if (dev_from_endp(ppending_endp
->pendp
) == dev
)
1291 RemoveEntryList(pthis
);
1292 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
1296 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1298 //cancel all the urbs in the purb-list
1299 sync_param
.ehci
= ehci
;
1300 sync_param
.context
= (PVOID
) dev
;
1302 KeSynchronizeExecution(ehci
->pdev_ext
->ehci_int
, ehci_sync_cancel_urbs_dev
, &sync_param
);
1304 //cancel all the purb in the endp's purb-list
1306 lock_dev(dev
, FALSE
);
1307 if (dev
->usb_config
)
1309 //only for configed dev
1310 for(i
= 0; i
< dev
->usb_config
->if_count
; i
++)
1312 for(j
= 0; j
< dev
->usb_config
->interf
[i
].endp_count
; j
++)
1314 ListFirst(&dev
->usb_config
->interf
[i
].endp
[j
].urb_list
, pthis
);
1317 ListNext(&dev
->usb_config
->interf
[i
].endp
[j
].urb_list
, pthis
, pnext
);
1319 RemoveEntryList(pthis
);
1320 InsertHeadList(&temp_list
, pthis
);
1328 ListFirst(&dev
->default_endp
.urb_list
, pthis
);
1332 ListNext(&dev
->default_endp
.urb_list
, pthis
, pnext
);
1334 RemoveEntryList(pthis
);
1335 InsertHeadList(&temp_list
, pthis
);
1339 unlock_dev(dev
, FALSE
);
1341 if (IsListEmpty(&temp_list
) == FALSE
)
1343 for(i
= 0; i
< k
; i
++)
1345 //complete those urbs with error
1346 pthis
= RemoveHeadList(&temp_list
);
1347 purb
= (PURB
) pthis
;
1348 purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
1350 ehci_generic_urb_completion(purb
, purb
->context
);
1355 lock_dev(dev
, FALSE
) dev
->ref_count
-= k
;
1356 unlock_dev(dev
, FALSE
);
1362 ehci_insert_urb_schedule(PEHCI_DEV ehci
, PURB purb
)
1363 // must have dev_lock( ehci_process_pending_endp ) and frame_list_lock acquired
1365 PURB_HS_PIPE_CONTENT pipe_content
;
1367 if (ehci
== NULL
|| purb
== NULL
)
1370 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1371 switch (pipe_content
->trans_type
)
1373 case USB_ENDPOINT_XFER_CONTROL
:
1374 ehci_insert_control_schedule(ehci
, purb
);
1376 case USB_ENDPOINT_XFER_BULK
:
1377 ehci_insert_bulk_schedule(ehci
, purb
);
1379 case USB_ENDPOINT_XFER_INT
:
1380 ehci_insert_int_schedule(ehci
, purb
);
1382 case USB_ENDPOINT_XFER_ISOC
:
1383 ehci_insert_iso_schedule(ehci
, purb
);
1389 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
1390 purb
->flags
|= URB_FLAG_STATE_IN_PROCESS
| URB_FLAG_IN_SCHEDULE
;
1391 InsertTailList(&ehci
->urb_list
, &purb
->urb_link
);
1397 ehci_insert_tds_qh(PEHCI_DEV ehci
, PEHCI_QH pqh
, PEHCI_QTD td_chain
)
1399 if (pqh
== NULL
|| td_chain
== NULL
)
1402 UNREFERENCED_PARAMETER(ehci
);
1404 ehci_copy_overlay((PEHCI_QH_CONTENT
) pqh
, (PEHCI_QTD_CONTENT
) td_chain
);
1405 InsertTailList(&td_chain
->elem_head_link
->elem_link
, &pqh
->elem_head_link
->elem_link
);
1410 ehci_insert_qh_urb(PURB purb
, PEHCI_QH pqh
)
1412 PLIST_ENTRY pthis
, pnext
;
1413 if (pqh
== NULL
|| purb
== NULL
)
1416 InsertTailList(&pqh
->elem_head_link
->elem_link
, &purb
->trasac_list
);
1417 ListFirst(&purb
->trasac_list
, pthis
) while (pthis
)
1419 // note: fstn may in this chain
1420 struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->purb
= purb
;
1421 ListNext(&purb
->trasac_list
, pthis
, pnext
);
1427 #define calc_td_count( pURB, start_aDDR, td_coUNT ) \
1431 k = ( ( pURB )->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size;\
1434 LONG packets_per_td, packets_per_page;\
1435 packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;\
1436 packets_per_page = PAGE_SIZE / max_packet_size;\
1437 i = ( ( LONG )&( pURB )->data_buffer[ ( start_aDDR ) ] ) & ( PAGE_SIZE - 1 );\
1441 j = i & ( max_packet_size - 1 );\
1442 k -= ( EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j ) / max_packet_size;\
1448 i = packets_per_td - packets_per_page;\
1450 i = packets_per_td;\
1451 td_coUNT = 1 + ( k + i - 1 ) / i; \
1456 td_coUNT = ( k + packets_per_td - 1 ) / packets_per_td;\
1462 ehci_fill_td_buf_ptr(PURB purb
, LONG start_addr
, // start idx into purb->data_buffer
1463 PLIST_ENTRY td_list
, LONG td_count
, ULONG toggle
)
1464 // fill the tds' bytes_to_transfer and hw_buf, return next toggle value: true 1, false 0
1466 LONG i
, j
, k
, data_load
;
1467 LONG packets_per_td
, packets_per_page
, bytes_to_transfer
, max_packet_size
;
1468 PLIST_ENTRY pthis
, pnext
;
1469 PEHCI_QTD_CONTENT ptdc
;
1473 if (purb
== NULL
|| td_list
== NULL
|| td_count
== 0)
1476 max_packet_size
= 1 << ((PURB_HS_PIPE_CONTENT
) & purb
->pipe
)->max_packet_size
;
1477 packets_per_td
= EHCI_QTD_MAX_TRANS_SIZE
/ max_packet_size
;
1478 packets_per_page
= PAGE_SIZE
/ max_packet_size
;
1481 bytes_to_transfer
= purb
->bytes_to_transfer
;
1483 i
= ((LONG
) & (purb
)->data_buffer
[(start_addr
)]) & (PAGE_SIZE
- 1);
1487 j
= i
& (max_packet_size
- 1);
1494 while (bytes_to_transfer
)
1496 ptd
= qtd_from_list_entry(pthis
);
1497 ptd
->hw_buf
[0] = MmGetPhysicalAddress(&purb
->data_buffer
[start_addr
]).LowPart
;
1498 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1502 data_load
= (LONG
) (EHCI_QTD_MAX_TRANS_SIZE
- PAGE_SIZE
+ i
- j
) < bytes_to_transfer
1503 ? (LONG
) (EHCI_QTD_MAX_TRANS_SIZE
- PAGE_SIZE
+ i
- j
) : bytes_to_transfer
;
1505 ptdc
->bytes_to_transfer
= (USHORT
) data_load
;
1506 ptd
->bytes_to_transfer
= (USHORT
) data_load
;
1508 // subtract the header part
1509 data_load
-= (i
< data_load
? i
: data_load
);
1511 for(k
= 1; data_load
> 0; k
++)
1513 ptr
= &purb
->data_buffer
[start_addr
+ i
+ (k
- 1) * PAGE_SIZE
];
1514 ptr
= (PVOID
) (((ULONG
) ptr
) & ~(PAGE_SIZE
- 1));
1515 ptd
->hw_buf
[k
] = MmGetPhysicalAddress(ptr
).LowPart
;
1516 data_load
-= PAGE_SIZE
< data_load
? PAGE_SIZE
: data_load
;
1521 // aligned on page boundary
1522 data_load
= EHCI_QTD_MAX_TRANS_SIZE
< bytes_to_transfer
1523 ? EHCI_QTD_MAX_TRANS_SIZE
: bytes_to_transfer
;
1525 ptdc
->bytes_to_transfer
= (USHORT
) data_load
;
1526 ptd
->bytes_to_transfer
= (USHORT
) data_load
;
1528 data_load
-= (PAGE_SIZE
< data_load
? PAGE_SIZE
: data_load
);
1530 for(k
= 1; data_load
> 0; k
++)
1532 ptr
= &purb
->data_buffer
[start_addr
+ k
* PAGE_SIZE
];
1533 ptr
= (PVOID
) (((ULONG
) ptr
) & ~(PAGE_SIZE
- 1));
1534 ptd
->hw_buf
[k
] = MmGetPhysicalAddress(ptr
).LowPart
;
1535 data_load
-= PAGE_SIZE
< data_load
? PAGE_SIZE
: data_load
;
1538 ptdc
->data_toggle
= toggle
;
1539 if (((ptdc
->bytes_to_transfer
+ max_packet_size
- 1) / max_packet_size
) & 1)
1541 //only odd num of transactions has effect
1544 start_addr
+= ptdc
->bytes_to_transfer
;
1545 bytes_to_transfer
-= ptdc
->bytes_to_transfer
;
1546 ListNext(td_list
, pthis
, pnext
);
1554 ehci_internal_submit_bulk(PEHCI_DEV ehci
, PURB purb
)
1556 // assume that the purb has its rest_bytes and bytes_to_transfer set
1557 // and bytes_transfered is zeroed.
1558 // dev_lock must be acquired outside
1559 // purb comes from dev's endpoint purb-list. it is already removed from
1560 // the endpoint purb-list.
1564 LONG max_packet_size
, td_count
, offset
, bytes_to_transfer
;
1568 LIST_ENTRY td_list
, *pthis
, *pnext
;
1569 BOOLEAN old_toggle
, toggle
, ret
;
1572 PURB_HS_PIPE_CONTENT pipe_content
;
1573 PEHCI_QTD_CONTENT ptdc
;
1574 PEHCI_QH_CONTENT pqhc
;
1575 PEHCI_ELEM_LINKS pelnk
;
1576 PEHCI_ELEM_LINKS plnk
;
1578 if (ehci
== NULL
|| purb
== NULL
)
1579 return STATUS_INVALID_PARAMETER
;
1581 max_packet_size
= endp_max_packet_size(purb
->pendp
);
1582 if (purb
->bytes_to_transfer
== 0)
1584 return STATUS_INVALID_PARAMETER
;
1587 start_addr
= &purb
->data_buffer
[purb
->data_length
- purb
->rest_bytes
];
1588 calc_td_count(purb
, purb
->data_length
- purb
->rest_bytes
, td_count
);
1590 elem_pool_lock(qtd_pool
, TRUE
);
1591 pelnk
= elem_pool_alloc_elems(qtd_pool
, td_count
);
1592 elem_pool_unlock(qtd_pool
, TRUE
);
1596 return STATUS_UNSUCCESSFUL
;
1598 ptd
= (PEHCI_QTD
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
1600 InitializeListHead(&td_list
);
1601 InsertTailList(&ptd
->elem_head_link
->elem_link
, &td_list
);
1603 ListFirst(&td_list
, pthis
);
1604 ListNext(&td_list
, pthis
, pnext
);
1608 old_toggle
= toggle
= (purb
->pendp
->flags
& USB_ENDP_FLAG_DATATOGGLE
) ? TRUE
: FALSE
;
1609 bytes_to_transfer
= purb
->bytes_to_transfer
;
1610 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_internal_submit_bulk():dev toggle=%d\n", toggle
));
1612 for(i
= 1; i
< 16; i
++)
1614 if ((max_packet_size
>> i
) == 0)
1621 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1622 pipe_content
->max_packet_size
= i
;
1623 pipe_content
->endp_addr
= endp_num(purb
->pendp
);
1624 pipe_content
->dev_addr
= dev_from_endp(purb
->pendp
)->dev_addr
;
1625 pipe_content
->trans_dir
= endp_dir(purb
->pendp
);
1626 pipe_content
->trans_type
= USB_ENDPOINT_XFER_BULK
;
1627 pipe_content
->data_toggle
= toggle
;
1628 pipe_content
->speed_high
= (dev_from_endp(purb
->pendp
)->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0;
1629 pipe_content
->speed_low
= (dev_from_endp(purb
->pendp
)->flags
& USB_DEV_FLAG_LOW_SPEED
) ? 1 : 0;
1631 pid
= (((ULONG
) purb
->pendp
->pusb_endp_desc
->bEndpointAddress
& USB_DIR_IN
) ? QTD_PID_IN
: QTD_PID_OUT
);
1633 i
= ((ULONG
) start_addr
) & (PAGE_SIZE
- 1); // header part within first page
1637 if (i
< purb
->bytes_to_transfer
)
1638 j
= i
& (max_packet_size
- 1);
1645 // fill the page pointer and toggle
1647 toggle
= ehci_fill_td_buf_ptr(purb
, purb
->data_length
- purb
->rest_bytes
, pthis
, td_count
, toggle
);
1650 ptd
= qtd_from_list_entry(pthis
);
1651 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1653 // ptdc->alt_terminal = 1;
1654 // ptdc->alt_qtd = 0;
1655 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1658 // ptd->elem_head_link->purb = purb; will be filled later
1659 ptdc
->err_count
= 3;
1660 ptdc
->status
= 0x80; // active, and do_start_split for split transfer
1662 // ptdc->data_toggle = toggle;
1666 ptd
->hw_next
= qtd_from_list_entry(pnext
)->phys_addr
;
1670 //Last one, enable ioc and short packet detect if necessary
1671 ptd
->hw_next
= EHCI_PTR_TERM
;
1673 if (bytes_to_transfer
< max_packet_size
&& (pid
== QTD_PID_IN
))
1675 //ptd->status |= TD_CTRL_SPD;
1682 ListNext(&td_list
, pthis
, pnext
);
1685 ListFirst(&td_list
, pthis
);
1686 RemoveEntryList(&td_list
);
1688 elem_pool_lock(qh_pool
, TRUE
);
1690 plnk
= elem_pool_alloc_elem(qh_pool
);
1694 elem_safe_free(pthis
, TRUE
);
1695 if (qh_pool
) elem_pool_unlock(qh_pool
, TRUE
);
1696 return STATUS_UNSUCCESSFUL
;
1699 pqh
= (PEHCI_QH
) ((ULONG
) plnk
->phys_part
& PHYS_PART_ADDR_MASK
);
1700 elem_pool_unlock(qh_pool
, TRUE
);
1705 elem_safe_free(pthis
, TRUE
);
1706 return STATUS_NO_MORE_ENTRIES
;
1710 purb
->td_count
= td_count
;
1711 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
1712 pqh
->hw_next
= EHCI_PTR_TERM
; // filled later
1713 pqhc
->dev_addr
= pipe_content
->dev_addr
;
1715 pqhc
->endp_addr
= pipe_content
->endp_addr
;
1716 pqhc
->data_toggle
= 0; //pipe_content->data_toggle;
1717 pqhc
->is_async_head
= 0;
1718 pqhc
->max_packet_size
= (1 << pipe_content
->max_packet_size
);
1719 pqhc
->is_ctrl_endp
= 0;
1720 pqhc
->reload_counter
= EHCI_NAK_RL_COUNT
;
1722 if (pipe_content
->speed_high
)
1723 pqhc
->endp_spd
= USB_SPEED_HIGH
;
1724 else if (pipe_content
->speed_low
)
1725 pqhc
->endp_spd
= USB_SPEED_LOW
;
1727 pqhc
->endp_spd
= USB_SPEED_FULL
;
1731 pqh
->hw_current
= 0;
1732 pqh
->hw_qtd_next
= 0; // filled later
1733 pqh
->hw_alt_next
= EHCI_PTR_TERM
;
1734 pqh
->hw_token
= 0; //indicate to advance queue before execution
1736 if (!pipe_content
->speed_high
)
1738 pqhc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
1739 pqhc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
1742 ptd
= qtd_from_list_entry(pthis
);
1743 ehci_insert_tds_qh(ehci
, pqh
, ptd
);
1744 ehci_insert_qh_urb(purb
, pqh
);
1745 purb
->pendp
->flags
=
1746 (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | (toggle
? USB_ENDP_FLAG_DATATOGGLE
: 0);
1747 usb_endp_busy_count_inc(purb
->pendp
);
1748 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
1752 // undo all we have done
1753 ListFirst(&pqh
->elem_head_link
->elem_link
, pthis
);
1755 RemoveEntryList(&purb
->trasac_list
);
1756 RemoveEntryList(&pqh
->elem_head_link
->elem_link
); //remove qh from td_chain
1758 elem_safe_free(pthis
, FALSE
);
1759 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
1761 InitializeListHead(&purb
->trasac_list
);
1762 // usb_endp_busy_count_dec( purb->pendp ); // the decrement is done in the dpc callback
1763 purb
->pendp
->flags
=
1764 (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | (old_toggle
? USB_ENDP_FLAG_DATATOGGLE
: 0);
1765 return STATUS_UNSUCCESSFUL
;
1767 return STATUS_SUCCESS
;
1771 ehci_internal_submit_ctrl(PEHCI_DEV ehci
, PURB purb
)
1774 LIST_ENTRY td_list
, *pthis
, *pnext
;
1777 LONG max_packet_size
, bytes_to_transfer
, bytes_rest
, start_idx
;
1781 PEHCI_QH_CONTENT pqhc
;
1784 PURB_HS_PIPE_CONTENT pipe_content
;
1785 PEHCI_QTD_CONTENT ptdc
;
1786 PEHCI_ELEM_LINKS pelnk
;
1789 if (ehci
== NULL
|| purb
== NULL
)
1790 return STATUS_INVALID_PARAMETER
;
1792 bytes_rest
= purb
->rest_bytes
;
1793 bytes_to_transfer
= purb
->bytes_to_transfer
;
1794 max_packet_size
= endp_max_packet_size(purb
->pendp
);
1795 start_idx
= purb
->data_length
- purb
->rest_bytes
;
1797 calc_td_count(purb
, start_idx
, td_count
);
1798 td_count
+= 2; // add setup td and handshake td
1800 elem_pool_lock(qtd_pool
, TRUE
);
1801 pelnk
= elem_pool_alloc_elems(qtd_pool
, td_count
);
1802 elem_pool_unlock(qtd_pool
, TRUE
);
1806 return STATUS_NO_MORE_ENTRIES
;
1809 InsertTailList(&pelnk
->elem_link
, &td_list
);
1810 ListFirst(&td_list
, pthis
);
1811 ListNext(&td_list
, pthis
, pnext
);
1813 ptd
= qtd_from_list_entry(pthis
);
1815 pdev
= dev_from_endp(purb
->pendp
);
1816 dev_addr
= pdev
->dev_addr
;
1818 if (dev_state(pdev
) <= USB_DEV_STATE_RESET
) //only valid for control transfer
1821 usb_dbg_print(DBGLVL_MAXIMUM
, ("ehci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr
));
1823 // fill the setup packet
1824 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1825 ptd
->hw_next
= qtd_from_list_entry(pnext
)->phys_addr
;
1826 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1827 ptdc
->status
= 0x80; // active
1828 ptdc
->pid
= QTD_PID_SETUP
;
1829 ptdc
->err_count
= 3;
1832 ptdc
->bytes_to_transfer
= sizeof(USB_CTRL_SETUP_PACKET
);
1833 ptdc
->data_toggle
= 0;
1834 ptd
->hw_buf
[0] = MmGetPhysicalAddress(purb
->setup_packet
).LowPart
;
1836 for(i
= 1; i
< 16; i
++)
1838 if ((max_packet_size
>> i
) == 0)
1845 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
1846 pipe_content
->max_packet_size
= i
;
1847 pipe_content
->endp_addr
= endp_num(purb
->pendp
);
1848 pipe_content
->dev_addr
= dev_addr
;
1849 pipe_content
->speed_low
= (pdev
->flags
& USB_DEV_FLAG_LOW_SPEED
) ? 1 : 0;
1850 pipe_content
->speed_high
= (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0;
1851 pipe_content
->trans_type
= USB_ENDPOINT_XFER_CONTROL
;
1854 ListNext(&td_list
, pthis
, pnext
);
1856 // all the tds's toggle and data_buffer pointer is filled here
1858 ehci_fill_td_buf_ptr(purb
, start_idx
, pthis
, td_count
- 2, toggle
);
1860 for(i
= 0; ((i
< td_count
- 2) && pthis
); i
++)
1862 //construct tds for DATA packets of data stage.
1863 ptd
= qtd_from_list_entry(pthis
);
1864 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1865 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1866 ptdc
->status
= 0x80; // active and startXSplit
1867 ptdc
->pid
= ((purb
->setup_packet
[0] & USB_DIR_IN
) ? QTD_PID_IN
: QTD_PID_OUT
);
1868 ptdc
->err_count
= 3;
1873 ptd
->hw_next
= qtd_from_list_entry(pnext
)->phys_addr
;
1875 ptd
->hw_next
= EHCI_PTR_TERM
;
1879 ListNext(&td_list
, pthis
, pnext
);
1883 ptd
->hw_next
= qtd_from_list_entry(pthis
)->phys_addr
;
1887 // ListFirstPrev( &td_list, pthis );
1888 ptd
= qtd_from_list_entry(pthis
);
1890 //the last is an IN transaction
1891 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
1892 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
1893 ptdc
->status
= 0x80;
1894 ptdc
->pid
= ((td_count
> 2)
1895 ? ((purb
->setup_packet
[0] & USB_DIR_IN
) ? QTD_PID_OUT
: QTD_PID_IN
) : QTD_PID_IN
);
1897 ptdc
->err_count
= 3;
1900 ptdc
->bytes_to_transfer
= 0;
1901 ptdc
->data_toggle
= 1;
1902 ptd
->hw_next
= EHCI_PTR_TERM
;
1904 ListFirst(&td_list
, pthis
);
1905 RemoveEntryList(&td_list
);
1907 ptd
= qtd_from_list_entry(pthis
);
1908 elem_pool_lock(qh_pool
, TRUE
);
1909 pelnk
= elem_pool_alloc_elem(qh_pool
);
1910 elem_pool_unlock(qh_pool
, TRUE
);
1914 elem_safe_free(pthis
, FALSE
);
1915 return STATUS_NO_MORE_ENTRIES
;
1918 pqh
= (PEHCI_QH
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
1919 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
1921 pqh
->hw_alt_next
= pqh
->hw_next
= EHCI_PTR_TERM
;
1923 pqhc
->dev_addr
= dev_addr
;
1925 pqhc
->endp_addr
= endp_num(purb
->pendp
);
1927 if (pipe_content
->speed_high
)
1928 pqhc
->endp_spd
= USB_SPEED_HIGH
;
1929 else if (pipe_content
->speed_low
)
1930 pqhc
->endp_spd
= USB_SPEED_LOW
;
1932 pqhc
->endp_spd
= USB_SPEED_FULL
;
1934 pqhc
->data_toggle
= 1; // use dt from qtd
1935 pqhc
->is_async_head
= 0;
1936 pqhc
->max_packet_size
= endp_max_packet_size(purb
->pendp
);
1938 if (pipe_content
->speed_high
== 0)
1939 pqhc
->is_ctrl_endp
= 1;
1941 pqhc
->is_ctrl_endp
= 0;
1943 pqhc
->reload_counter
= EHCI_NAK_RL_COUNT
;
1949 if (!pipe_content
->speed_high
)
1951 pqhc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
1952 pqhc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
1955 purb
->td_count
= td_count
;
1957 ehci_insert_tds_qh(ehci
, pqh
, ptd
);
1958 ehci_insert_qh_urb(purb
, pqh
);
1960 usb_endp_busy_count_inc(purb
->pendp
);
1961 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
1965 RemoveEntryList(&purb
->trasac_list
);
1966 RemoveEntryList(&pqh
->elem_head_link
->elem_link
);
1968 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
1969 elem_safe_free(pthis
, FALSE
);
1971 InitializeListHead(&purb
->trasac_list
);
1972 // usb_endp_busy_count_dec( purb->pendp );
1973 return STATUS_UNSUCCESSFUL
;
1975 return STATUS_SUCCESS
;
1979 ehci_internal_submit_int(PEHCI_DEV ehci
, PURB purb
)
1981 LONG i
, max_packet_size
;
1985 PURB_HS_PIPE_CONTENT pipe_content
;
1986 UCHAR mult_trans
, toggle
, old_toggle
;
1987 PEHCI_ELEM_LINKS pelnk
;
1988 PEHCI_QTD_CONTENT ptdc
;
1990 PEHCI_QH_CONTENT pqhc
;
1993 if (ehci
== NULL
|| purb
== NULL
)
1994 return STATUS_INVALID_PARAMETER
;
1996 old_toggle
= toggle
= (purb
->pendp
->flags
& USB_ENDP_FLAG_DATATOGGLE
) ? TRUE
: FALSE
;
1997 max_packet_size
= endp_max_packet_size(purb
->pendp
);
1998 pdev
= dev_from_endp(purb
->pendp
);
2000 if (max_packet_size
== 0 || max_packet_size
> 64)
2001 return STATUS_INVALID_PARAMETER
;
2003 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
2005 if (max_packet_size
< purb
->data_length
)
2006 return STATUS_INVALID_PARAMETER
;
2008 for(i
= 1; i
< 16; i
++)
2010 if ((((ULONG
) purb
->pendp
->pusb_endp_desc
->bInterval
) >> i
) == 0)
2018 mult_trans
= endp_mult_count(purb
->pendp
);
2019 if (max_packet_size
* endp_mult_count(purb
->pendp
) < purb
->data_length
)
2020 return STATUS_INVALID_PARAMETER
;
2021 i
= purb
->pendp
->pusb_endp_desc
->bInterval
- 1;
2025 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
2026 pipe_content
->interval
= i
;
2027 pipe_content
->trans_type
= USB_ENDPOINT_XFER_INT
; // bit 0-1
2028 pipe_content
->speed_high
= (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0; // bit 5
2029 pipe_content
->speed_low
= (pdev
->flags
& USB_DEV_FLAG_LOW_SPEED
) ? 1 : 0; // bit 6
2030 pipe_content
->trans_dir
= endp_dir(purb
->pendp
); // bit 7
2031 pipe_content
->dev_addr
= pdev
->dev_addr
; // bit 8-14
2032 pipe_content
->endp_addr
= endp_num(purb
->pendp
); // bit 15-18
2033 pipe_content
->data_toggle
= 1; // bit 19
2034 pipe_content
->mult_count
= mult_trans
;
2036 // pipe_content->start_uframe : 3; // bit 28-30 will be filled later
2038 for(i
= 1; i
<= 16; i
++)
2040 if (((ULONG
) max_packet_size
) >> i
)
2048 pipe_content
->max_packet_size
= i
; // bit 20-23 log2( max_packet_size )
2050 if (ehci_claim_bandwidth(ehci
, purb
, TRUE
) == FALSE
)
2052 // can not allocate bandwidth for it
2053 return STATUS_UNSUCCESSFUL
;
2056 // one qtd is enough
2057 elem_pool_lock(qtd_pool
, TRUE
);
2058 pelnk
= elem_pool_alloc_elem(qtd_pool
);
2059 elem_pool_unlock(qtd_pool
, TRUE
);
2063 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2064 return STATUS_NO_MORE_ENTRIES
;
2067 ptd
= (PEHCI_QTD
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
2068 ptdc
= (PEHCI_QTD_CONTENT
) ptd
;
2069 ptd
->hw_next
= EHCI_PTR_TERM
;
2071 ptd
->hw_alt_next
= EHCI_PTR_TERM
;
2073 ptdc
->status
= 0x80;
2074 ptdc
->pid
= pipe_content
->trans_dir
? QTD_PID_IN
: QTD_PID_OUT
;
2075 ptdc
->err_count
= 3;
2078 ptdc
->bytes_to_transfer
= purb
->data_length
;
2079 toggle
= (UCHAR
) ehci_fill_td_buf_ptr(purb
, 0, &pelnk
->elem_link
, 1, toggle
);
2081 elem_pool_lock(qh_pool
, TRUE
);
2082 pelnk
= elem_pool_alloc_elem(qh_pool
);
2083 elem_pool_unlock(qh_pool
, TRUE
);
2086 elem_safe_free(&ptd
->elem_head_link
->elem_link
, TRUE
);
2087 InitializeListHead(&purb
->trasac_list
);
2088 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2089 return STATUS_NO_MORE_ENTRIES
;
2091 pqh
= (PEHCI_QH
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
2092 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
2094 pqh
->hw_next
= EHCI_PTR_TERM
;
2095 pqhc
->dev_addr
= pdev
->dev_addr
;
2097 pqhc
->endp_addr
= endp_num(purb
->pendp
);
2099 if (pipe_content
->speed_high
)
2100 pqhc
->endp_spd
= USB_SPEED_HIGH
;
2101 else if (pipe_content
->speed_low
)
2102 pqhc
->endp_spd
= USB_SPEED_LOW
;
2104 pqhc
->endp_spd
= USB_SPEED_FULL
;
2106 pqhc
->data_toggle
= 0;
2107 pqhc
->is_async_head
= 0;
2108 pqhc
->max_packet_size
= endp_max_packet_size(purb
->pendp
);
2109 pqhc
->is_ctrl_endp
= 0;
2110 pqhc
->reload_counter
= 0;
2114 pqhc
->mult
= mult_trans
;
2116 if (pipe_content
->speed_high
)
2118 if (pipe_content
->interval
== 0) // one poll per uframe
2119 pqhc
->s_mask
= 0xff;
2120 else if (pipe_content
->interval
== 1) // one poll every 2 uframe
2121 pqhc
->s_mask
= pipe_content
->start_uframe
== 0 ? 0x55 : 0xbb;
2122 else if (pipe_content
->interval
== 2)
2124 pqhc
->s_mask
= 0x11;
2125 pqhc
->s_mask
<<= pipe_content
->start_uframe
;
2129 pqhc
->s_mask
= 1 << (pipe_content
->start_uframe
);
2133 else // full/low speed
2135 pqhc
->s_mask
= 1 << pipe_content
->start_uframe
;
2136 if (pipe_content
->start_uframe
< 4)
2138 pqhc
->c_mask
= 0x07 << (pipe_content
->start_uframe
+ 2);
2140 else if (pipe_content
->start_uframe
== 4)
2142 pqhc
->c_mask
= 0xc1;
2144 else if (pipe_content
->start_uframe
>= 5)
2147 pqhc
->c_mask
= 0x03;
2148 if (pipe_content
->start_uframe
== 5)
2150 pqhc
->c_mask
|= 0x80;
2153 if (pipe_content
->start_uframe
>= 4)
2156 elem_pool_lock(fstn_pool
, TRUE
);
2157 pelnk
= elem_pool_alloc_elem(fstn_pool
);
2158 elem_pool_unlock(fstn_pool
, TRUE
);
2161 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
2162 elem_safe_free(&ptd
->elem_head_link
->elem_link
, TRUE
);
2163 InitializeListHead(&purb
->trasac_list
);
2164 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2165 return STATUS_NO_MORE_ENTRIES
;
2167 pfstn
= (PEHCI_FSTN
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
2168 pfstn
->hw_prev
= ptd
->phys_addr
;
2169 pfstn
->elem_head_link
->purb
= purb
;
2170 InsertTailList(&ptd
->elem_head_link
->elem_link
, &pfstn
->elem_head_link
->elem_link
);
2172 pqhc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
2173 pqhc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
2179 InitializeListHead(&purb
->trasac_list
);
2180 ehci_insert_tds_qh(ehci
, pqh
, ptd
);
2181 ehci_insert_qh_urb(purb
, pqh
);
2183 purb
->pendp
->flags
= (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | (toggle
<< 31);
2184 usb_endp_busy_count_inc(purb
->pendp
);
2186 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
2190 RemoveEntryList(&purb
->trasac_list
);
2191 RemoveEntryList(&pqh
->elem_head_link
->elem_link
);
2193 elem_safe_free(&pqh
->elem_head_link
->elem_link
, TRUE
);
2194 // an fstn may follow the td
2195 elem_safe_free(&ptd
->elem_head_link
->elem_link
, FALSE
);
2197 InitializeListHead(&purb
->trasac_list
);
2198 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2200 purb
->pendp
->flags
= (purb
->pendp
->flags
& ~USB_ENDP_FLAG_DATATOGGLE
) | ((toggle
^ 1) << 31);
2201 // usb_endp_busy_count_dec( purb->pendp );
2203 return STATUS_UNSUCCESSFUL
;
2206 return STATUS_SUCCESS
;
2211 ehci_internal_submit_iso(PEHCI_DEV ehci
, PURB purb
)
2213 LONG i
, j
, td_count
, temp
;
2216 PEHCI_SITD_CONTENT psitdc
;
2217 PEHCI_ITD_CONTENT pitdc
;
2218 LIST_ENTRY td_list
, *pthis
, *pnext
, *pprev
;
2220 PURB_HS_PIPE_CONTENT pipe_content
;
2222 PEHCI_ELEM_LINKS pelnk
;
2224 if (ehci
== NULL
|| purb
== NULL
)
2225 return STATUS_INVALID_PARAMETER
;
2227 if (purb
->iso_frame_count
== 0)
2228 return STATUS_INVALID_PARAMETER
;
2230 pdev
= dev_from_endp(purb
->pendp
);
2232 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
2233 pipe_content
->trans_type
= USB_ENDPOINT_XFER_ISOC
; // bit 0-1
2234 pipe_content
->speed_high
= (pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) ? 1 : 0; // bit 5
2235 pipe_content
->speed_low
= 0; // bit 6
2236 pipe_content
->trans_dir
= endp_dir(purb
->pendp
); // bit 7
2237 pipe_content
->dev_addr
= pdev
->dev_addr
; // bit 8-14
2238 pipe_content
->endp_addr
= endp_num(purb
->pendp
); // bit 15-18
2239 pipe_content
->data_toggle
= 0; // bit 19
2242 purb
->params
[0] = j
= endp_max_packet_size(purb
->pendp
);
2244 if (pipe_content
->speed_high
== 0)
2246 // check to see if the frame data is too long to transfer
2247 if (purb
->iso_frame_count
>= (LONG
) ehci
->frame_count
)
2248 return STATUS_INVALID_PARAMETER
;
2250 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
2252 if (purb
->iso_packet_desc
[i
].length
> j
)
2253 return STATUS_INVALID_PARAMETER
;
2258 // excess the frame count limit
2259 if (purb
->iso_frame_count
>= (LONG
) (ehci
->frame_count
<< 3))
2260 return STATUS_INVALID_PARAMETER
;
2262 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
2264 if (purb
->iso_packet_desc
[i
].length
> j
* endp_mult_count(purb
->pendp
)) // 3 is max mult-transaction count
2265 return STATUS_INVALID_PARAMETER
;
2268 pipe_content
->mult_count
= endp_mult_count(purb
->pendp
);
2271 pipe_content
->max_packet_size
= 0; // bit 20-23 log( max_packet_size ), not correct, should not be used
2273 if (pipe_content
->speed_high
== 0)
2275 for(i
= 1; i
< 16; i
++)
2277 if ((((ULONG
) purb
->pendp
->pusb_endp_desc
->bInterval
) >> i
) == 0)
2284 i
= purb
->pendp
->pusb_endp_desc
->bInterval
- 1;
2287 pipe_content
->interval
= i
; // bit 24-27 the same definition as in USB2.0 spec, for high or full/low speed
2289 if (ehci_claim_bandwidth(ehci
, purb
, TRUE
) == FALSE
)
2290 return STATUS_UNSUCCESSFUL
;
2292 if (pipe_content
->speed_high
== 0)
2294 td_count
= purb
->iso_frame_count
;
2296 // test to see if the last td needs one more sitd for pure complete-split
2297 if (pipe_content
->trans_dir
== 0)
2299 j
= (purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].length
+ 187) / 188;
2300 if (purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].params
.start_uframe
+ 1 + j
>= 8)
2306 elem_pool_lock(itd_pool
, TRUE
);
2307 pelnk
= elem_pool_alloc_elems(itd_pool
, td_count
);
2308 elem_pool_unlock(itd_pool
, TRUE
);
2314 if (pipe_content
->interval
>= 3)
2316 td_count
= purb
->iso_frame_count
;
2321 j
= purb
->iso_start_frame
& 0x07;
2324 td_count
= (purb
->iso_frame_count
+ 8 / i
- 1) * i
/ 8;
2328 j
= 1 + (7 - j
) / i
; // the leading packets from the 8-trans boundary
2329 td_count
= (j
>= (LONG
) purb
->iso_frame_count
?
2330 1 : 1 + (purb
->iso_frame_count
- j
+ 8 / i
- 1) * i
/ 8);
2334 elem_pool_lock(sitd_pool
, TRUE
);
2335 pelnk
= elem_pool_alloc_elems(sitd_pool
, td_count
);
2336 elem_pool_unlock(sitd_pool
, TRUE
);
2341 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2342 return STATUS_NO_MORE_ENTRIES
;
2345 InsertTailList(&pelnk
->elem_link
, &td_list
);
2346 ListFirst(&td_list
, pthis
);
2348 purb
->td_count
= td_count
;
2350 //set up offset for high speed and interval == 1
2351 if (pipe_content
->speed_high
&& pipe_content
->interval
== 0)
2353 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
2356 purb
->iso_packet_desc
[i
].offset
= 0;
2358 purb
->iso_packet_desc
[i
].offset
= purb
->iso_packet_desc
[i
- 1].offset
+
2359 purb
->iso_packet_desc
[i
].length
;
2367 init_elem_phys_part(struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
));
2368 if (pipe_content
->speed_high
)
2370 LONG start_uframe
, k
;
2371 LONG l
, pk_idx
, offset
, start_uf
, td_length
;
2375 pitd
= itd_from_list_entry(pthis
);
2376 pitdc
= (PEHCI_ITD_CONTENT
) pitd
;
2377 start_uframe
= purb
->iso_start_frame
& 0x07;
2379 // will be filled later
2380 pitd
->hw_next
= EHCI_PTR_TERM
;
2383 pitdc
->dev_addr
= pdev
->dev_addr
;
2384 pitdc
->endp_num
= endp_num(purb
->pendp
);
2386 pitdc
->max_packet_size
= endp_max_packet_size(purb
->pendp
);
2387 pitdc
->io_dir
= pipe_content
->trans_dir
;
2388 pitdc
->mult
= endp_mult_count(purb
->pendp
);
2390 pbuf
= pitd
->hw_bufp
;
2391 RtlZeroMemory(phys_addr
, sizeof(phys_addr
));
2393 if (pipe_content
->interval
< 3)
2395 // this indicates one itd schedules more than one uframes
2396 // for multiple transactions described by iso_packet_desc
2398 k
= td_count
== 1 ? purb
->iso_frame_count
: j
; // the first itd
2400 k
= (LONG
) (purb
->iso_frame_count
- i
) <= 8 / REAL_INTERVAL
2401 ? (purb
->iso_frame_count
- i
) : 8 / REAL_INTERVAL
;
2403 // j is the header transactions out of the interval
2404 // aligned transactions per td
2405 if (j
> 0 && i
== 0) // handle the first itd
2406 start_uf
= start_uframe
;
2408 start_uf
= start_uframe
% REAL_INTERVAL
;
2412 k
= 1, start_uf
= start_uframe
& 0x07;
2416 // calculate the data to transfer with this td
2418 for(l
= start_uf
, pk_idx
= i
; pk_idx
< i
+ k
; pk_idx
++, l
+= REAL_INTERVAL
)
2420 td_length
+= purb
->iso_packet_desc
[pk_idx
].length
;
2422 MmGetPhysicalAddress(&purb
->data_buffer
[purb
->iso_packet_desc
[pk_idx
].offset
]).LowPart
;
2425 // fill the page pointer, and offset
2426 if (pipe_content
->interval
!= 0)
2428 for(l
= start_uf
, pk_idx
= i
; pk_idx
< i
+ k
; pk_idx
++, l
+= REAL_INTERVAL
)
2430 pitdc
->status_slot
[l
].offset
= phys_addr
[l
] & (PAGE_SIZE
- 1);
2431 pbuf
[l
>> pipe_content
->interval
] |= phys_addr
[l
] & (~(PAGE_SIZE
- 1));
2432 pitdc
->status_slot
[l
].page_sel
= l
>> pipe_content
->interval
;
2433 pitdc
->status_slot
[l
].status
= 0x08;
2434 pitdc
->status_slot
[l
].trans_length
= purb
->iso_packet_desc
[pk_idx
].length
;
2435 if (PAGE_SIZE
- pitdc
->status_slot
[l
].offset
<
2436 (ULONG
) purb
->iso_packet_desc
[pk_idx
].length
)
2438 // fill the next page buf, we can not simply add
2439 // PAGE_SIZE to the phys_addr[ l ].
2440 pbuf
[(l
>> pipe_content
->interval
) + 1] |=
2441 MmGetPhysicalAddress((PBYTE
)
2443 data_buffer
[purb
->iso_packet_desc
[pk_idx
].
2444 offset
]) & (~(PAGE_SIZE
- 1))) +
2449 else // interval == 0
2451 LONG m
, n
= 0, n2
= 0;
2452 // fill the page buffer first
2453 // calculate the page buffer needed
2454 offset
= phys_addr
[0] & (PAGE_SIZE
- 1);
2457 offset
= PAGE_SIZE
- offset
;
2458 l
= 1 + (td_length
- offset
+ PAGE_SIZE
- 1) / PAGE_SIZE
;
2462 l
= (td_length
+ PAGE_SIZE
- 1) / PAGE_SIZE
;
2468 // fill the hw_bufp array and PG field, pk_idx is index into hw_bufp
2469 for(pk_idx
= 0; pk_idx
< l
; pk_idx
++)
2473 offset
= phys_addr
[start_uf
] & (~(PAGE_SIZE
- 1));
2474 pbuf
[pk_idx
] |= offset
;
2476 pitdc
->status_slot
[0].page_sel
= n
;
2481 // scan to find if the buf pointer already filled in the td
2482 // since interval = 1, we do not need k * REAL_INTERVAL
2483 // k is transaction count for current td,
2484 // n is hw_bufp( pbuf ) index
2485 // n2 is the last phys_addr index we stopped
2486 for(m
= n2
; m
< start_uf
+ k
; m
++)
2488 // we can not determine the phys_addr[ x ] is piror
2489 // to offset if it is less than offset.
2490 // because phys_addr is discrete.
2491 // if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) < offset )
2494 if ((phys_addr
[m
] & (~(PAGE_SIZE
- 1))) == (ULONG
) offset
)
2496 pitdc
->status_slot
[m
].page_sel
= n
;
2502 if (m
== start_uf
+ k
)
2505 offset
= phys_addr
[m
] & (~(PAGE_SIZE
- 1));
2506 pbuf
[pk_idx
] |= offset
;
2509 pitdc
->status_slot
[m
].page_sel
= n
;
2512 // fill offset and others
2513 for(l
= start_uf
, pk_idx
= i
; l
< start_uf
+ k
; l
++, pk_idx
++)
2515 pitdc
->status_slot
[l
].offset
= (phys_addr
[l
] & (PAGE_SIZE
- 1));
2516 pitdc
->status_slot
[l
].status
= 0x08;
2517 pitdc
->status_slot
[l
].trans_length
= purb
->iso_packet_desc
[pk_idx
].length
;
2523 else // full/low speed
2525 psitd
= sitd_from_list_entry(pthis
);
2526 psitdc
= (PEHCI_SITD_CONTENT
) psitd
;
2527 psitd
->hw_next
= EHCI_PTR_TERM
;
2530 psitdc
->dev_addr
= pdev
->dev_addr
;
2531 psitdc
->endp_num
= endp_num(purb
->pendp
);
2532 psitdc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
2533 psitdc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
2534 psitdc
->io_dir
= endp_dir(purb
->pendp
);
2536 psitdc
->status
&= 0x80; // in DWORD 3
2539 j
= (purb
->iso_packet_desc
[i
].length
+ 187) / 188;
2541 if (psitdc
->io_dir
== 0)
2545 psitdc
->s_mask
|= (1 << (j
- 1));
2547 psitdc
->s_mask
<<= purb
->iso_packet_desc
[i
].params
.start_uframe
& 0x07;
2554 psitdc
->s_mask
= 1 << purb
->iso_packet_desc
[i
].params
.start_uframe
& 0x07;
2555 // iso split case 2b: ehci spec 1.0
2559 j
= j
- 1 + 2; // actual complete-split count
2561 psitdc
->c_mask
|= temp
>> 8; // the previous sitd's complete split
2562 if (temp
>> 8) // link back for sitd split completion
2564 psitd
->hw_backpointer
= sitd_from_list_entry(pprev
)->phys_addr
;
2565 psitdc
->status
&= 0x82;
2569 psitd
->hw_backpointer
= EHCI_PTR_TERM
;
2572 for(k
= temp
= 0; k
< j
; k
++)
2577 temp
<<= ((purb
->iso_packet_desc
[i
].params
.start_uframe
& 0x07) + 2);
2579 // only uframe zero and one have complete split for prev sitd
2580 if ((temp
>> 8) > 3)
2583 psitdc
->c_mask
|= temp
& 0xff;
2587 psitdc
->c_prog_mask
= 0;
2588 psitdc
->bytes_to_transfer
= purb
->iso_packet_desc
[i
].length
;
2589 psitdc
->page_sel
= 0;
2593 j
= (ULONG
) ((PBYTE
) purb
->data_buffer
+ purb
->iso_packet_desc
[i
].offset
);
2594 psitd
->hw_tx_results2
= MmGetPhysicalAddress((PVOID
) j
).LowPart
;
2597 if (PAGE_SIZE
- (j
& (PAGE_SIZE
- 1)) < (ULONG
) purb
->iso_packet_desc
[i
].length
)
2599 // need to fill another slot
2601 MmGetPhysicalAddress((PVOID
) ((j
& ~(PAGE_SIZE
- 1)) + PAGE_SIZE
)).LowPart
>> 12;
2604 if (purb
->iso_packet_desc
[i
].length
> 188)
2605 psitdc
->trans_pos
= 0x00;
2606 else if (purb
->iso_packet_desc
[i
].length
<= 188)
2607 psitdc
->trans_pos
= 0x01;
2609 if (psitdc
->io_dir
== 0)
2610 psitdc
->trans_count
= (purb
->iso_packet_desc
[i
].length
+ 187) / 188;
2613 ListNext(&td_list
, pthis
, pnext
);
2619 if (pipe_content
->speed_high
== 0)
2621 // has an extra sitd to fill at the tail
2624 ListFirstPrev(&td_list
, pthis
);
2625 init_elem_phys_part(struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
));
2627 psitd
= sitd_from_list_entry(pthis
);
2628 psitdc
= (PEHCI_SITD_CONTENT
) psitd
;
2629 psitd
->hw_next
= EHCI_PTR_TERM
;
2632 psitdc
->dev_addr
= pdev
->dev_addr
;
2633 psitdc
->endp_num
= endp_num(purb
->pendp
);
2634 psitdc
->hub_addr
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
;
2635 psitdc
->port_idx
= ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
;
2636 psitdc
->io_dir
= endp_dir(purb
->pendp
);
2638 psitdc
->status
&= 0x80; // in DWORD 3
2641 psitdc
->s_mask
= 0x04; // uframe 2, random selection
2643 psitdc
->c_mask
= 0x70; // complete split at uframe 4, 5, 6
2644 ListFirstPrev(pthis
, pprev
);
2645 psitd
->hw_backpointer
= sitd_from_list_entry(pprev
)->phys_addr
;
2646 psitdc
->status
&= 0x82;
2649 psitdc
->c_prog_mask
= 0;
2650 psitdc
->bytes_to_transfer
= 1; // purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length;
2651 psitdc
->page_sel
= 0;
2653 j
= (ULONG
) ((PBYTE
) purb
->data_buffer
+ purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].offset
);
2654 // the last byte is overridden.
2655 j
+= purb
->iso_packet_desc
[purb
->iso_frame_count
- 1].length
- 1;
2656 psitd
->hw_tx_results2
= MmGetPhysicalAddress((PVOID
) j
).LowPart
;
2659 // set the interrupt
2660 ListFirstPrev(&td_list
, pthis
);
2661 psitdc
= (PEHCI_SITD_CONTENT
) sitd_from_list_entry(pthis
);
2667 ListFirstPrev(&td_list
, pthis
);
2668 pitdc
= (PEHCI_ITD_CONTENT
) itd_from_list_entry(pthis
);
2669 for(i
= 7; i
>= 0; i
--)
2671 if (pitdc
->status_slot
[i
].status
== 0x08)
2673 pitdc
->status_slot
[i
].ioc
= 1;
2681 ListFirst(&td_list
, pthis
);
2682 // ListFirst( &purb->trasac_list, pthis )
2683 RemoveEntryList(&td_list
);
2684 InsertTailList(pthis
, &purb
->trasac_list
);
2688 // fill the purb ptr
2689 struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->purb
= purb
;
2690 ListNext(&purb
->trasac_list
, pthis
, pnext
);
2694 //indirectly guarded by pending_endp_list_lock
2695 usb_endp_busy_count_inc(purb
->pendp
);
2696 ehci_insert_urb_to_schedule(ehci
, purb
, ret
);
2700 // usb_endp_busy_count_dec( purb->pendp );
2702 ListFirst(&purb
->trasac_list
, pthis
);
2703 RemoveEntryList(&purb
->trasac_list
);
2705 elem_safe_free(pthis
, FALSE
);
2706 ehci_claim_bandwidth(ehci
, purb
, FALSE
);
2707 return STATUS_UNSUCCESSFUL
;
2709 return STATUS_SUCCESS
;
2713 //this function used as the KeSynchronizeExecution param to delegate control to ehci_insert_urb_schedule
2714 ehci_sync_insert_urb_schedule(PVOID context
)
2716 PSYNC_PARAM sync_param
;
2720 sync_param
= (PSYNC_PARAM
) context
;
2721 if (sync_param
== NULL
)
2724 ehci
= sync_param
->ehci
;
2725 purb
= (PURB
) sync_param
->context
;
2727 if (ehci
== NULL
|| purb
== NULL
)
2728 return (UCHAR
) (sync_param
->ret
= FALSE
);
2730 return (UCHAR
) (sync_param
->ret
= ehci_insert_urb_schedule(ehci
, purb
));
2733 static BOOLEAN NTAPI
2734 ehci_sync_cancel_urb(PVOID context
)
2736 //cancel a single purb
2738 PSYNC_PARAM sync_param
;
2739 PURB purb2
, dest_urb
;
2740 PLIST_ENTRY pthis
, pnext
;
2741 BOOLEAN found
= FALSE
;
2743 if (context
== NULL
)
2746 sync_param
= (PSYNC_PARAM
) context
;
2747 ehci
= sync_param
->ehci
;
2748 dest_urb
= (PURB
) sync_param
->context
;
2750 if (ehci
== NULL
|| dest_urb
== NULL
)
2751 return (UCHAR
) (sync_param
->ret
= FALSE
);
2753 ListFirst(&ehci
->urb_list
, pthis
);
2756 purb2
= (PURB
) pthis
;
2757 if (purb2
== dest_urb
)
2760 purb2
->flags
|= URB_FLAG_FORCE_CANCEL
;
2763 ListNext(&ehci
->urb_list
, pthis
, pnext
);
2769 press_doorbell(ehci
);
2771 return (UCHAR
) (sync_param
->ret
= found
);
2775 ehci_cancel_urb(PEHCI_DEV ehci
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
2776 //note any fields of the purb can not be referenced unless it is found in some queue
2778 PLIST_ENTRY pthis
, pnext
;
2782 SYNC_PARAM sync_param
;
2784 USE_BASIC_NON_PENDING_IRQL
;
2786 if (ehci
== NULL
|| purb
== NULL
|| pdev
== NULL
|| pendp
== NULL
)
2787 return STATUS_INVALID_PARAMETER
;
2789 lock_dev(pdev
, FALSE
);
2791 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2793 unlock_dev(pdev
, FALSE
);
2794 //delegate to remove device for this job
2795 return STATUS_DEVICE_DOES_NOT_EXIST
;
2798 if (dev_from_endp(pendp
) != pdev
)
2800 unlock_dev(pdev
, FALSE
);
2801 return STATUS_INVALID_PARAMETER
;
2804 if (endp_state(pendp
) == USB_ENDP_FLAG_STALL
)
2806 //it will be canceled in ehci_process_pending_endp
2807 unlock_dev(pdev
, FALSE
);
2808 return USB_STATUS_ENDPOINT_HALTED
;
2812 ListFirst(&pendp
->urb_list
, pthis
);
2815 purb2
= (PURB
) pthis
;
2819 RemoveEntryList(pthis
);
2820 InitializeListHead(pthis
);
2823 ListNext(&pendp
->urb_list
, pthis
, pnext
);
2826 unlock_dev(pdev
, FALSE
);
2830 purb
->status
= STATUS_CANCELLED
;
2832 ehci_generic_urb_completion(purb
, purb
->context
);
2834 lock_dev(pdev
, FALSE
);
2836 unlock_dev(pdev
, FALSE
);
2837 return STATUS_SUCCESS
;
2840 // search the purb in the purb-list and try to cancel
2841 sync_param
.ehci
= ehci
;
2842 sync_param
.context
= purb
;
2844 KeSynchronizeExecution(ehci
->pdev_ext
->ehci_int
, ehci_sync_cancel_urb
, &sync_param
);
2846 found
= sync_param
.ret
;
2849 return USB_STATUS_CANCELING
;
2851 return STATUS_INVALID_PARAMETER
;
2855 ehci_generic_urb_completion(PURB purb
, PVOID context
)
2858 BOOLEAN is_ctrl
= FALSE
;
2859 USE_NON_PENDING_IRQL
;
2861 old_irql
= KeGetCurrentIrql();
2862 if (old_irql
> DISPATCH_LEVEL
)
2865 if (old_irql
< DISPATCH_LEVEL
)
2866 KeRaiseIrql(DISPATCH_LEVEL
, &old_irql
);
2870 goto LBL_LOWER_IRQL
;
2873 goto LBL_LOWER_IRQL
;
2875 lock_dev(pdev
, TRUE
);
2877 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2879 // no need to do following statistics
2880 unlock_dev(pdev
, TRUE
);
2881 goto LBL_CLIENT_PROCESS
;
2883 if (usb_error(purb
->status
))
2885 pdev
->error_count
++;
2888 if (purb
->pendp
== &pdev
->default_endp
)
2890 if (usb_halted(purb
->status
))
2892 pdev
->time_out_count
++;
2893 if (pdev
->time_out_count
> 3)
2895 dev_set_state(pdev
, USB_DEV_STATE_ZOMB
);
2896 ehci_dbg_print(DBGLVL_MAXIMUM
,
2897 ("ehci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n",
2902 pdev
->time_out_count
= 0;
2906 if (endp_type(purb
->pendp
) == USB_ENDPOINT_XFER_CONTROL
)
2909 unlock_dev(pdev
, TRUE
);
2914 if (purb
->completion
)
2915 purb
->completion(purb
, context
);
2919 if (purb
->ctrl_req_context
.ctrl_stack_count
== 0)
2921 if (purb
->completion
)
2922 purb
->completion(purb
, context
);
2926 // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ];
2927 // if( pstack->urb_completion )
2928 // pstack->urb_completion( purb, pstack->context );
2929 usb_call_ctrl_completion(purb
);
2934 if (old_irql
< DISPATCH_LEVEL
)
2935 KeLowerIrql(old_irql
);
2941 ehci_rh_submit_urb(PUSB_DEV pdev
, PURB purb
)
2943 PUSB_DEV_MANAGER dev_mgr
;
2945 PUSB_CTRL_SETUP_PACKET psetup
;
2948 PHUB2_EXTENSION hub_ext
;
2949 PUSB_PORT_STATUS ps
, psret
;
2953 USE_NON_PENDING_IRQL
;
2954 if (pdev
== NULL
|| purb
== NULL
)
2955 return STATUS_INVALID_PARAMETER
;
2957 dev_mgr
= dev_mgr_from_dev(pdev
);
2959 KeAcquireSpinLock(&dev_mgr
->timer_svc_list_lock
, &old_irql
);
2960 lock_dev(pdev
, FALSE
);
2961 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
2963 unlock_dev(pdev
, FALSE
);
2964 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
2965 return STATUS_DEVICE_DOES_NOT_EXIST
;
2968 ehci
= ehci_from_hcd(pdev
->hcd
);
2969 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
2971 hub_ext
= ((PHUB2_EXTENSION
) pdev
->dev_ext
);
2972 port_count
= (UCHAR
) ((PEHCI_HCS_CONTENT
) & ehci
->ehci_caps
.hcs_params
)->port_count
;
2974 switch (endp_type(purb
->pendp
))
2976 case USB_ENDPOINT_XFER_CONTROL
:
2978 if (psetup
->bmRequestType
== 0xa3 && psetup
->bRequest
== USB_REQ_GET_STATUS
)
2981 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
|| psetup
->wLength
< 4)
2983 purb
->status
= STATUS_INVALID_PARAMETER
;
2987 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
2988 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
2989 ps
= &hub_ext
->rh_port_status
[psetup
->wIndex
];
2991 psret
= (PUSB_PORT_STATUS
) purb
->data_buffer
;
2992 ps
->wPortStatus
= 0;
2994 if (status
& PORT_CCS
)
2996 ps
->wPortStatus
|= USB_PORT_STAT_CONNECTION
;
2998 if (status
& PORT_PE
)
3000 ps
->wPortStatus
|= USB_PORT_STAT_ENABLE
;
3001 ps
->wPortStatus
|= USB_PORT_STAT_HIGH_SPEED
; // ehci spec
3003 if (status
& PORT_PR
)
3005 ps
->wPortStatus
|= USB_PORT_STAT_RESET
;
3007 if (status
& PORT_SUSP
)
3009 ps
->wPortStatus
|= USB_PORT_STAT_SUSPEND
;
3011 if (PORT_USB11(status
))
3013 ps
->wPortStatus
|= USB_PORT_STAT_LOW_SPEED
;
3017 ps
->wPortStatus
|= USB_PORT_STAT_POWER
;
3019 //now set change field
3020 if ((status
& PORT_CSC
) && !(ps
->wPortStatus
& USB_PORT_STAT_LOW_SPEED
))
3022 ps
->wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
3024 if ((status
& PORT_PEC
) && !(ps
->wPortStatus
& USB_PORT_STAT_LOW_SPEED
))
3026 ps
->wPortChange
|= USB_PORT_STAT_C_ENABLE
;
3029 //don't touch other fields, might be filled by
3032 usb_dbg_print(DBGLVL_MAXIMUM
,
3033 ("ehci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n",
3034 ps
->wPortStatus
, ps
->wPortChange
, ps
));
3036 psret
->wPortChange
= ps
->wPortChange
;
3037 psret
->wPortStatus
= ps
->wPortStatus
;
3039 purb
->status
= STATUS_SUCCESS
;
3043 else if (psetup
->bmRequestType
== 0x23 && psetup
->bRequest
== USB_REQ_CLEAR_FEATURE
)
3045 //clear-port-feature
3046 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
)
3048 purb
->status
= STATUS_INVALID_PARAMETER
;
3052 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
3053 ps
= &hub_ext
->rh_port_status
[psetup
->wIndex
];
3055 purb
->status
= STATUS_SUCCESS
;
3056 switch (psetup
->wValue
)
3058 case USB_PORT_FEAT_C_CONNECTION
:
3060 SET_RH2_PORTSTAT(i
, USBPORTSC_CSC
);
3061 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3062 usb_dbg_print(DBGLVL_MAXIMUM
,
3063 ("ehci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup
->wIndex
));
3064 ps
->wPortChange
&= ~USB_PORT_STAT_C_CONNECTION
;
3067 case USB_PORT_FEAT_C_ENABLE
:
3069 SET_RH2_PORTSTAT(i
, USBPORTSC_PEC
);
3070 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3071 usb_dbg_print(DBGLVL_MAXIMUM
,
3072 ("ehci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup
->wIndex
));
3073 ps
->wPortChange
&= ~USB_PORT_STAT_C_ENABLE
;
3076 case USB_PORT_FEAT_C_RESET
:
3078 ps
->wPortChange
&= ~USB_PORT_STAT_C_RESET
;
3079 //the reset signal is down in rh_timer_svc_reset_port_completion
3080 // enable or not is set by host controller
3081 // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) );
3082 usb_dbg_print(DBGLVL_MAXIMUM
,
3083 ("ehci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n",
3087 case USB_PORT_FEAT_ENABLE
:
3089 ps
->wPortStatus
&= ~USB_PORT_STAT_ENABLE
;
3090 CLR_RH2_PORTSTAT(i
, USBPORTSC_PE
);
3091 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3092 usb_dbg_print(DBGLVL_MAXIMUM
,
3093 ("ehci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup
->wIndex
));
3097 purb
->status
= STATUS_UNSUCCESSFUL
;
3101 else if (psetup
->bmRequestType
== 0xd3 && psetup
->bRequest
== HUB_REQ_GET_STATE
)
3104 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
|| psetup
->wLength
== 0)
3106 purb
->status
= STATUS_INVALID_PARAMETER
;
3110 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
3111 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3112 purb
->data_buffer
[0] = (status
& USBPORTSC_LS
);
3114 // reverse the order
3115 purb
->data_buffer
[0] ^= 0x3;
3116 purb
->status
= STATUS_SUCCESS
;
3119 else if (psetup
->bmRequestType
== 0x23 && psetup
->bRequest
== USB_REQ_SET_FEATURE
)
3122 if (psetup
->wValue
!= USB_PORT_FEAT_RESET
)
3124 purb
->status
= STATUS_INVALID_PARAMETER
;
3125 ehci_dbg_print(DBGLVL_MAXIMUM
,
3126 ("ehci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup
->wValue
));
3130 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
3132 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
3135 purb
->status
= STATUS_NO_MEMORY
;
3139 ptimer
->threshold
= 0; // within [ 50ms, 60ms ], one tick is 10 ms
3140 ptimer
->context
= (ULONG
) purb
;
3141 ptimer
->pdev
= pdev
;
3142 ptimer
->func
= rh_timer_svc_reset_port_completion
;
3145 pdev
->ref_count
+= 2; //one for timer and one for purb
3147 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3148 usb_dbg_print(DBGLVL_MAXIMUM
,
3149 ("ehci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup
->wIndex
, status
));
3150 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
3151 purb
->status
= STATUS_PENDING
;
3155 purb
->status
= STATUS_INVALID_PARAMETER
;
3159 case USB_ENDPOINT_XFER_INT
:
3161 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
3164 purb
->status
= STATUS_NO_MEMORY
;
3167 ptimer
->threshold
= RH_INTERVAL
;
3168 ptimer
->context
= (ULONG
) purb
;
3169 ptimer
->pdev
= pdev
;
3170 ptimer
->func
= rh_timer_svc_int_completion
;
3173 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
3175 usb_dbg_print(DBGLVL_MAXIMUM
,
3176 ("ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev
->ref_count
));
3177 pdev
->ref_count
+= 2; //one for timer and one for purb
3179 purb
->status
= STATUS_PENDING
;
3182 case USB_ENDPOINT_XFER_BULK
:
3183 case USB_ENDPOINT_XFER_ISOC
:
3186 purb
->status
= STATUS_INVALID_PARAMETER
;
3190 unlock_dev(pdev
, FALSE
);
3191 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
3192 return purb
->status
;
3195 //must have rh dev_lock acquired
3197 ehci_rh_reset_port(PHCD hcd
, UCHAR port_idx
)
3207 ehci
= ehci_from_hcd(hcd
);
3208 port_count
= (UCHAR
) ((PEHCI_HCS_CONTENT
) & ehci
->ehci_caps
.hcs_params
)->port_count
;
3210 if (port_idx
< 1 || port_idx
> port_count
)
3213 i
= (ULONG
) (EHCI_PORTSC
+ 4 * (port_idx
- 1));
3215 // assert the reset signal,(implicitly disable the port)
3216 SET_RH2_PORTSTAT(i
, PORT_PR
);
3218 usb_wait_ms_dpc(50);
3219 // clear the reset signal, delay port enable till clearing port feature
3220 CLR_RH2_PORTSTAT(i
, PORT_PR
);
3222 // wait the port stable
3225 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3226 if (!(status
& PORT_PE
))
3228 // release the ownership from ehci to companion hc
3229 status
|= PORT_OWNER
;
3230 EHCI_WRITE_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
), status
);
3231 // the host controller will set PORTSC automatically
3234 usb_wait_us_dpc(10);
3235 // SET_RH_PORTSTAT( i, PORT_PE );
3237 //recovery time 10ms
3238 usb_wait_ms_dpc(10);
3240 // clear PORT_PEC and PORT_PCC
3241 SET_RH2_PORTSTAT(i
, 0x0a);
3243 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
3244 usb_dbg_print(DBGLVL_MAXIMUM
, ("ehci_rh_reset_port(): status after written=0x%x\n", status
));
3249 ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP irp
)
3251 PEHCI_DEVICE_EXTENSION pdev_ext
;
3252 PUSB_DEV_MANAGER dev_mgr
;
3255 pdev_ext
= DeviceObject
->DeviceExtension
;
3256 ehci
= pdev_ext
->ehci
;
3258 dev_mgr
= ehci
->hcd_interf
.hcd_get_dev_mgr(&ehci
->hcd_interf
);
3259 return dev_mgr_dispatch(dev_mgr
, irp
);
3262 //the following are for hcd interface methods
3264 ehci_set_dev_mgr(PHCD hcd
, PUSB_DEV_MANAGER dev_mgr
)
3266 hcd
->dev_mgr
= dev_mgr
;
3270 ehci_get_dev_mgr(PHCD hcd
)
3272 return hcd
->dev_mgr
;
3276 ehci_get_type(PHCD hcd
)
3278 return HCD_TYPE_EHCI
; // ( hcd->flags & HCD_TYPE_MASK );
3282 ehci_set_id(PHCD hcd
, UCHAR id
)
3284 hcd
->flags
&= ~HCD_ID_MASK
;
3285 hcd
->flags
|= (HCD_ID_MASK
& id
);
3289 ehci_get_id(PHCD hcd
)
3291 return (UCHAR
) (hcd
->flags
& HCD_ID_MASK
);
3296 ehci_alloc_addr(PHCD hcd
)
3302 for(i
= 1; i
< MAX_DEVS
; i
++)
3304 if (hcd
->dev_addr_map
[i
>> 3] & (1 << (i
& 7)))
3317 hcd
->dev_addr_map
[i
>> 3] |= (1 << (i
& 7));
3323 ehci_free_addr(PHCD hcd
, UCHAR addr
)
3331 hcd
->dev_addr_map
[addr
>> 3] &= ~(1 << (addr
& 7));
3337 ehci_submit_urb2(PHCD hcd
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
3339 return ehci_submit_urb(ehci_from_hcd(hcd
), pdev
, pendp
, purb
);
3343 ehci_get_root_hub(PHCD hcd
)
3345 return ehci_from_hcd(hcd
)->root_hub
;
3349 ehci_set_root_hub(PHCD hcd
, PUSB_DEV root_hub
)
3351 if (hcd
== NULL
|| root_hub
== NULL
)
3353 ehci_from_hcd(hcd
)->root_hub
= root_hub
;
3358 ehci_remove_device2(PHCD hcd
, PUSB_DEV pdev
)
3360 if (hcd
== NULL
|| pdev
== NULL
)
3363 return ehci_remove_device(ehci_from_hcd(hcd
), pdev
);
3367 ehci_hcd_release(PHCD hcd
)
3370 PEHCI_DEVICE_EXTENSION pdev_ext
;
3375 ehci
= ehci_from_hcd(hcd
);
3376 pdev_ext
= ehci
->pdev_ext
;
3377 return ehci_release(pdev_ext
->pdev_obj
);
3381 ehci_cancel_urb2(PHCD hcd
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
3385 return STATUS_INVALID_PARAMETER
;
3387 ehci
= ehci_from_hcd(hcd
);
3388 return ehci_cancel_urb(ehci
, pdev
, pendp
, purb
);
3392 ehci_rh_get_dev_change(PHCD hcd
, PBYTE buf
) //must have the rh dev_lock acquired
3401 ehci
= ehci_from_hcd(hcd
);
3402 port_count
= HCS_N_PORTS(ehci
->ehci_caps
.hcs_params
);
3403 for(i
= 0; i
< port_count
; i
++)
3405 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_PORTSC
+ (i
<< 2)));
3406 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_rh_get_dev_change(): erh port%d status=0x%x\n", i
, status
));
3408 if (status
& (PORT_PEC
| PORT_CSC
| PORT_OCC
))
3410 buf
[(i
+ 1) >> 3] |= (1 << ((i
+ 1) & 7));
3417 ehci_hcd_dispatch(PHCD hcd
, LONG disp_code
, PVOID param
)
3422 return STATUS_INVALID_PARAMETER
;
3423 ehci
= ehci_from_hcd(hcd
);
3426 case HCD_DISP_READ_PORT_COUNT
:
3429 return STATUS_INVALID_PARAMETER
;
3430 *((PUCHAR
) param
) = (UCHAR
) HCS_N_PORTS(ehci
->ehci_caps
.hcs_params
);
3431 return STATUS_SUCCESS
;
3433 case HCD_DISP_READ_RH_DEV_CHANGE
:
3435 if (ehci_rh_get_dev_change(hcd
, param
) == FALSE
)
3436 return STATUS_INVALID_PARAMETER
;
3437 return STATUS_SUCCESS
;
3440 return STATUS_NOT_IMPLEMENTED
;
3443 //------------------------------------------------------------------------------
3444 // EHCI routines follows
3446 VOID
ehci_init_int8_qh(PEHCI_QH_CONTENT qh
);
3449 ehci_cal_cpu_freq(PVOID context
)
3456 ehci_probe(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, PUSB_DEV_MANAGER dev_mgr
)
3458 LONG bus
, i
, j
, ret
= 0;
3459 PCI_SLOT_NUMBER slot_num
;
3460 PPCI_COMMON_CONFIG pci_config
;
3461 PDEVICE_OBJECT pdev
;
3462 BYTE buffer
[sizeof(PCI_COMMON_CONFIG
)];
3463 PEHCI_DEVICE_EXTENSION pdev_ext
;
3465 slot_num
.u
.AsULONG
= 0;
3466 pci_config
= (PPCI_COMMON_CONFIG
) buffer
;
3469 //scan the bus to find ehci controller
3470 for(bus
= 0; bus
< 3; bus
++) /* enum bus0-bus2 */
3472 for(i
= 0; i
< PCI_MAX_DEVICES
; i
++)
3474 slot_num
.u
.bits
.DeviceNumber
= i
;
3475 for(j
= 0; j
< PCI_MAX_FUNCTIONS
; j
++)
3477 slot_num
.u
.bits
.FunctionNumber
= j
;
3479 ret
= HalGetBusData(PCIConfiguration
,
3480 bus
, slot_num
.u
.AsULONG
, pci_config
, PCI_COMMON_HDR_LENGTH
);
3482 if (ret
== 0) /*no this bus */
3485 if (ret
== 2) /*no device on the slot */
3488 if (pci_config
->BaseClass
== 0x0c && pci_config
->SubClass
== 0x03
3489 && pci_config
->ProgIf
== 0x20)
3491 //well, we find our usb host controller( EHCI ), create device
3492 pdev
= ehci_alloc(drvr_obj
, reg_path
, ((bus
<< 8) | (i
<< 3) | j
), dev_mgr
);
3506 pdev_ext
= pdev
->DeviceExtension
;
3509 // acquire higher irql to eliminate pre-empty
3510 KeSynchronizeExecution(pdev_ext
->ehci_int
, ehci_cal_cpu_freq
, NULL
);
3517 ehci_alloc(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, ULONG bus_addr
, PUSB_DEV_MANAGER dev_mgr
)
3520 LONG frd_num
, prd_num
;
3521 PDEVICE_OBJECT pdev
;
3522 PEHCI_DEVICE_EXTENSION pdev_ext
;
3523 ULONG vector
, addr_space
;
3528 DEVICE_DESCRIPTION dev_desc
;
3529 CM_PARTIAL_RESOURCE_DESCRIPTOR
*pprd
;
3530 PCI_SLOT_NUMBER slot_num
;
3534 pdev
= ehci_create_device(drvr_obj
, dev_mgr
);
3539 pdev_ext
= pdev
->DeviceExtension
;
3541 pdev_ext
->pci_addr
= bus_addr
;
3542 bus
= (bus_addr
>> 8);
3544 slot_num
.u
.AsULONG
= 0;
3545 slot_num
.u
.bits
.DeviceNumber
= ((bus_addr
& 0xff) >> 3);
3546 slot_num
.u
.bits
.FunctionNumber
= (bus_addr
& 0x07);
3548 //now create adapter object
3549 RtlZeroMemory(&dev_desc
, sizeof(dev_desc
));
3551 dev_desc
.Version
= DEVICE_DESCRIPTION_VERSION
;
3552 dev_desc
.Master
= TRUE
;
3553 dev_desc
.ScatterGather
= TRUE
;
3554 dev_desc
.Dma32BitAddresses
= TRUE
;
3555 dev_desc
.BusNumber
= bus
;
3556 dev_desc
.InterfaceType
= PCIBus
;
3557 dev_desc
.MaximumLength
= EHCI_MAX_SIZE_TRANSFER
;
3559 pdev_ext
->map_regs
= 2; // we do not use it seriously
3561 pdev_ext
->padapter
= HalGetAdapter(&dev_desc
, &pdev_ext
->map_regs
);
3563 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_alloc(): padapter=0x%x\n", pdev_ext
->padapter
));
3564 if (pdev_ext
->padapter
== NULL
)
3567 ehci_delete_device(pdev
);
3571 DbgPrint("ehci_alloc(): reg_path=0x%x, \n \
3572 ehci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \
3573 ehci_alloc(): slot_num=0x%x, &res_list=0x%x \n \
3574 ehci_alloc(): adapter=0x%x \n", (DWORD
) reg_path
, (DWORD
) PCIBus
, (DWORD
) bus
, (DWORD
) bus_addr
, (DWORD
) slot_num
.u
.AsULONG
, (DWORD
) & pdev_ext
->res_list
, pdev_ext
->padapter
);
3576 //let's allocate resources for this device
3577 DbgPrint("ehci_alloc(): about to assign slot res\n");
3578 if ((status
= HalAssignSlotResources(reg_path
, NULL
, //no class name yet
3579 drvr_obj
, NULL
, //no support of another ehci controller
3581 bus
, slot_num
.u
.AsULONG
, &pdev_ext
->res_list
)) != STATUS_SUCCESS
)
3583 DbgPrint("ehci_alloc(): error assign slot res, 0x%x\n", status
);
3584 release_adapter(pdev_ext
->padapter
);
3585 pdev_ext
->padapter
= NULL
;
3586 ehci_delete_device(pdev
);
3590 //parse the resource list
3591 for(frd_num
= 0; frd_num
< (LONG
) pdev_ext
->res_list
->Count
; frd_num
++)
3593 for(prd_num
= 0; prd_num
< (LONG
) pdev_ext
->res_list
->List
[frd_num
].PartialResourceList
.Count
;
3596 pprd
= &pdev_ext
->res_list
->List
[frd_num
].PartialResourceList
.PartialDescriptors
[prd_num
];
3597 if (pprd
->Type
== CmResourceTypePort
)
3599 RtlCopyMemory(&pdev_ext
->res_port
, &pprd
->u
.Port
, sizeof(pprd
->u
.Port
));
3602 else if (pprd
->Type
== CmResourceTypeInterrupt
)
3604 RtlCopyMemory(&pdev_ext
->res_interrupt
, &pprd
->u
.Interrupt
, sizeof(pprd
->u
.Interrupt
));
3606 else if (pprd
->Type
== CmResourceTypeMemory
)
3608 RtlCopyMemory(&pdev_ext
->res_memory
, &pprd
->u
.Memory
, sizeof(pprd
->u
.Memory
));
3613 //for port, translate them to system address
3615 if (HalTranslateBusAddress(PCIBus
, bus
, pdev_ext
->res_port
.Start
, &addr_space
, //io space
3616 &pdev_ext
->ehci
->ehci_reg_base
) != (BOOLEAN
) TRUE
)
3618 DbgPrint("ehci_alloc(): error, can not translate bus address\n");
3619 release_adapter(pdev_ext
->padapter
);
3620 pdev_ext
->padapter
= NULL
;
3621 ehci_delete_device(pdev
);
3625 DbgPrint("ehci_alloc(): address space=0x%x\n, reg_base=0x%x\n",
3626 addr_space
, pdev_ext
->ehci
->ehci_reg_base
.u
.LowPart
);
3628 if (addr_space
== 0)
3630 //port has been mapped to memory space
3631 pdev_ext
->ehci
->port_mapped
= TRUE
;
3632 pdev_ext
->ehci
->port_base
= (PBYTE
) MmMapIoSpace(pdev_ext
->ehci
->ehci_reg_base
,
3633 pdev_ext
->res_port
.Length
, FALSE
);
3635 //fatal error can not map the registers
3636 if (pdev_ext
->ehci
->port_base
== NULL
)
3638 release_adapter(pdev_ext
->padapter
);
3639 pdev_ext
->padapter
= NULL
;
3640 ehci_delete_device(pdev
);
3647 pdev_ext
->ehci
->port_mapped
= FALSE
;
3648 pdev_ext
->ehci
->port_base
= (PBYTE
) pdev_ext
->ehci
->ehci_reg_base
.LowPart
;
3651 //before we connect the interrupt, we have to init ehci
3652 pdev_ext
->ehci
->pdev_ext
= pdev_ext
;
3655 // i = ( ( PEHCI_HCS_CONTENT )( &pdev_ext->ehci->ehci_caps.hcs_params ) )->length;
3657 ehci_get_capabilities(pdev_ext
->ehci
, pdev_ext
->ehci
->port_base
);
3658 i
= pdev_ext
->ehci
->ehci_caps
.length
;
3659 pdev_ext
->ehci
->port_base
+= i
;
3661 if (ehci_init_schedule(pdev_ext
->ehci
, pdev_ext
->padapter
) == FALSE
)
3663 release_adapter(pdev_ext
->padapter
);
3664 pdev_ext
->padapter
= NULL
;
3665 ehci_delete_device(pdev
);
3669 InitializeListHead(&pdev_ext
->ehci
->urb_list
);
3670 KeInitializeSpinLock(&pdev_ext
->ehci
->pending_endp_list_lock
);
3671 InitializeListHead(&pdev_ext
->ehci
->pending_endp_list
);
3673 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_alloc(): pending_endp_list=0x%x\n",
3674 &pdev_ext
->ehci
->pending_endp_list
));
3676 init_pending_endp_pool(&pdev_ext
->ehci
->pending_endp_pool
);
3678 KeInitializeTimer(&pdev_ext
->ehci
->reset_timer
);
3680 vector
= HalGetInterruptVector(PCIBus
,
3682 pdev_ext
->res_interrupt
.level
,
3683 pdev_ext
->res_interrupt
.vector
, &irql
, &affinity
);
3685 KeInitializeDpc(&pdev_ext
->ehci_dpc
, ehci_dpc_callback
, (PVOID
) pdev_ext
->ehci
);
3687 //connect the interrupt
3688 DbgPrint("ehci_alloc(): the int=0x%x\n", vector
);
3689 if (IoConnectInterrupt(&pdev_ext
->ehci_int
, ehci_isr
, pdev_ext
->ehci
, NULL
, //&pdev_ext->ehci->frame_list_lock,
3690 vector
, irql
, irql
, LevelSensitive
, TRUE
, //share the vector
3691 affinity
, FALSE
) //No float save
3702 ehci_create_device(PDRIVER_OBJECT drvr_obj
, PUSB_DEV_MANAGER dev_mgr
)
3705 PDEVICE_OBJECT pdev
;
3706 PEHCI_DEVICE_EXTENSION pdev_ext
;
3708 UNICODE_STRING dev_name
;
3709 UNICODE_STRING symb_name
;
3711 STRING string
, another_string
;
3712 CHAR str_dev_name
[64], str_symb_name
[64];
3715 if (drvr_obj
== NULL
)
3718 //note: hcd count wont increment till the hcd is registered in dev_mgr
3719 sprintf(str_dev_name
, "%s%d", EHCI_DEVICE_NAME
, dev_mgr
->hcd_count
);
3720 sprintf(str_symb_name
, "%s%d", EHCI_DOS_DEVICE_NAME
, dev_mgr
->hcd_count
);
3722 RtlInitString(&string
, str_dev_name
);
3723 RtlAnsiStringToUnicodeString(&dev_name
, &string
, TRUE
);
3726 status
= IoCreateDevice(drvr_obj
,
3727 sizeof(EHCI_DEVICE_EXTENSION
) + sizeof(EHCI_DEV
),
3728 &dev_name
, FILE_EHCI_DEV_TYPE
, 0, FALSE
, &pdev
);
3730 if (status
!= STATUS_SUCCESS
|| pdev
== NULL
)
3732 RtlFreeUnicodeString(&dev_name
);
3733 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_create_device(): error create device 0x%x\n", status
));
3737 pdev_ext
= pdev
->DeviceExtension
;
3738 RtlZeroMemory(pdev_ext
, sizeof(EHCI_DEVICE_EXTENSION
) + sizeof(EHCI_DEV
));
3740 pdev_ext
->dev_ext_hdr
.type
= NTDEV_TYPE_HCD
;
3741 pdev_ext
->dev_ext_hdr
.dispatch
= ehci_dispatch_irp
;
3742 pdev_ext
->dev_ext_hdr
.start_io
= NULL
; //we do not support startio
3743 pdev_ext
->dev_ext_hdr
.dev_mgr
= dev_mgr
;
3745 pdev_ext
->pdev_obj
= pdev
;
3746 pdev_ext
->pdrvr_obj
= drvr_obj
;
3748 pdev_ext
->ehci
= (PEHCI_DEV
) & (pdev_ext
[1]);
3750 RtlInitString(&another_string
, str_symb_name
);
3751 RtlAnsiStringToUnicodeString(&symb_name
, &another_string
, TRUE
);
3752 //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME );
3754 IoCreateSymbolicLink(&symb_name
, &dev_name
);
3756 ehci_dbg_print(DBGLVL_MAXIMUM
,
3757 ("ehci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", pdev
,
3758 pdev_ext
, pdev_ext
->ehci
, dev_mgr
));
3760 RtlFreeUnicodeString(&dev_name
);
3761 RtlFreeUnicodeString(&symb_name
);
3763 //register with dev_mgr though it is not initilized
3764 ehci_init_hcd_interface(pdev_ext
->ehci
);
3765 hcd_id
= dev_mgr_register_hcd(dev_mgr
, &pdev_ext
->ehci
->hcd_interf
);
3767 pdev_ext
->ehci
->hcd_interf
.hcd_set_id(&pdev_ext
->ehci
->hcd_interf
, hcd_id
);
3768 pdev_ext
->ehci
->hcd_interf
.hcd_set_dev_mgr(&pdev_ext
->ehci
->hcd_interf
, dev_mgr
);
3775 ehci_init_hcd_interface(PEHCI_DEV ehci
)
3777 ehci
->hcd_interf
.hcd_set_dev_mgr
= ehci_set_dev_mgr
;
3778 ehci
->hcd_interf
.hcd_get_dev_mgr
= ehci_get_dev_mgr
;
3779 ehci
->hcd_interf
.hcd_get_type
= ehci_get_type
;
3780 ehci
->hcd_interf
.hcd_set_id
= ehci_set_id
;
3781 ehci
->hcd_interf
.hcd_get_id
= ehci_get_id
;
3782 ehci
->hcd_interf
.hcd_alloc_addr
= ehci_alloc_addr
;
3783 ehci
->hcd_interf
.hcd_free_addr
= ehci_free_addr
;
3784 ehci
->hcd_interf
.hcd_submit_urb
= ehci_submit_urb2
;
3785 ehci
->hcd_interf
.hcd_generic_urb_completion
= ehci_generic_urb_completion
;
3786 ehci
->hcd_interf
.hcd_get_root_hub
= ehci_get_root_hub
;
3787 ehci
->hcd_interf
.hcd_set_root_hub
= ehci_set_root_hub
;
3788 ehci
->hcd_interf
.hcd_remove_device
= ehci_remove_device2
;
3789 ehci
->hcd_interf
.hcd_rh_reset_port
= ehci_rh_reset_port
;
3790 ehci
->hcd_interf
.hcd_release
= ehci_hcd_release
;
3791 ehci
->hcd_interf
.hcd_cancel_urb
= ehci_cancel_urb2
;
3792 ehci
->hcd_interf
.hcd_start
= ehci_start
;
3793 ehci
->hcd_interf
.hcd_dispatch
= ehci_hcd_dispatch
;
3795 ehci
->hcd_interf
.flags
= HCD_TYPE_EHCI
; //hcd types | hcd id
3799 ehci_init_schedule(PEHCI_DEV ehci
, PADAPTER_OBJECT padapter
)
3801 PEHCI_DEVICE_EXTENSION pdev_ext
;
3804 PEHCI_QH_CONTENT pqh_content
;
3806 PEHCI_ELEM_LINKS pelnk
;
3811 pdev_ext
= ehci
->pdev_ext
;
3812 if (pdev_ext
== NULL
)
3815 // padapter = pdev_ext->padapter;
3816 if (ehci
->frame_count
== 0)
3817 ehci
->frame_count
= EHCI_DEFAULT_FRAMES
;
3820 for(i
= 0; i
< 5; i
++)
3822 ret
= elem_pool_init_pool(&ehci
->elem_pools
[i
], i
, padapter
);
3831 elem_pool_destroy_pool(&ehci
->elem_pools
[i
]);
3835 // allocate periodic frame list
3837 HalAllocateCommonBuffer(padapter
,
3838 sizeof(ULONG
) * ehci
->frame_count
, &ehci
->frame_list_phys_addr
, FALSE
);
3839 if (ehci
->frame_list
== NULL
)
3842 RtlZeroMemory(ehci
->frame_list
, sizeof(ULONG
) * ehci
->frame_count
);
3843 ehci
->frame_list_cpu
= usb_alloc_mem(NonPagedPool
, sizeof(LIST_HEAD
) * ehci
->frame_count
);
3845 if (ehci
->frame_list_cpu
== NULL
)
3848 for(i
= 0; i
< (LONG
) ehci
->frame_count
; i
++)
3850 InitializeListHead(&ehci
->frame_list_cpu
[i
].td_link
);
3853 for(i
= 0; i
< 8; i
++)
3855 InitializeListHead(&ehci
->periodic_list_cpu
[i
]);
3858 InitializeListHead(&ehci
->async_list_cpu
);
3860 // init frame band budget array
3861 ehci
->frame_bw
= usb_alloc_mem(NonPagedPool
, sizeof(USHORT
) * ehci
->frame_count
* 8);
3862 if (ehci
->frame_bw
== NULL
)
3865 for(i
= 0; i
< (LONG
) ehci
->frame_count
* 8; i
++)
3867 ehci
->frame_bw
[i
] = EHCI_MAX_SYNC_BUS_TIME
;
3869 ehci
->min_bw
= EHCI_MAX_SYNC_BUS_TIME
;
3871 // chain the 1ms interrupt qh to the schedule
3872 if ((pelnk
= elem_pool_alloc_elem(&ehci
->elem_pools
[EHCI_QH_POOL_IDX
])) == NULL
)
3875 pqh_content
= (PEHCI_QH_CONTENT
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
3876 ehci_init_int8_qh(pqh_content
);
3878 // chain qh to the shadow list
3879 InsertTailList(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], &pelnk
->sched_link
);
3881 // chain it to the periodic schedule, we use it as a docking point
3882 // for req of 8- uframes request
3883 pqh
= (PEHCI_QH
) pqh_content
;
3885 for(i
= 0; i
< (LONG
) ehci
->frame_count
; i
++)
3887 ehci
->frame_list
[i
] = pqh
->phys_addr
;
3891 /*if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] ) ) == NULL )
3894 pfstn = ( PEHCI_FSTN )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK );
3895 pfstn->hw_next = EHCI_PTR_TERM;
3896 pfstn->hw_prev = EHCI_PTR_TERM | ( INIT_LIST_FLAG_QH << 1 );
3897 InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_FSTN_INDEX ], &pelnk->sched_link );
3898 pqh->hw_next = pfstn->phys_addr; */
3900 // allocate for async list head
3901 if ((pelnk
= elem_pool_alloc_elem(&ehci
->elem_pools
[EHCI_QH_POOL_IDX
])) == NULL
)
3904 // init the async list head
3905 pqh
= (PEHCI_QH
) ((ULONG
) pelnk
->phys_part
& PHYS_PART_ADDR_MASK
);
3906 pqh_content
= (PEHCI_QH_CONTENT
) pqh
;
3907 ehci_init_int8_qh(pqh_content
);
3908 pqh
->hw_next
= pqh
->phys_addr
;
3909 pqh_content
->s_mask
= 0;
3910 pqh_content
->is_async_head
= 1;
3911 pqh_content
->endp_addr
= 0;
3912 ehci
->skel_async_qh
= pqh
;
3913 InsertTailList(&ehci
->async_list_cpu
, &pqh
->elem_head_link
->sched_link
);
3917 ehci_destroy_schedule(ehci
);
3922 ehci_destroy_schedule(PEHCI_DEV ehci
)
3929 usb_free_mem(ehci
->frame_bw
);
3930 ehci
->frame_bw
= NULL
;
3932 if (ehci
->frame_list_cpu
)
3933 usb_free_mem(ehci
->frame_list_cpu
);
3934 ehci
->frame_list_cpu
= NULL
;
3936 if (ehci
->frame_list
)
3937 HalFreeCommonBuffer(ehci
->pdev_ext
->padapter
,
3938 sizeof(ULONG
) * ehci
->frame_count
,
3939 ehci
->frame_list_phys_addr
, ehci
->frame_list
, FALSE
);
3941 ehci
->frame_list
= NULL
;
3942 ehci
->frame_list_phys_addr
.LowPart
= 0;
3943 ehci
->frame_list_phys_addr
.HighPart
= 0;
3945 for(i
= 0; i
< 5; i
++)
3946 elem_pool_destroy_pool(&ehci
->elem_pools
[i
]);
3952 ehci_init_int8_qh(PEHCI_QH_CONTENT qh
)
3957 qh
->terminal
= EHCI_PTR_TERM
;
3963 qh
->dev_addr
= 126; // a fake addr
3965 qh
->endp_addr
= 1; // a fake endp
3966 qh
->endp_spd
= USB_SPEED_HIGH
;
3967 qh
->data_toggle
= 0;
3968 qh
->is_async_head
= 0;
3969 qh
->max_packet_size
= 64;
3970 qh
->is_ctrl_endp
= 0;
3971 qh
->reload_counter
= 0;
3974 qh
->s_mask
= 0x80; // we are interrupt qh
3981 qh
->cur_qtd_ptr
= 0; // a terminal
3984 // !active and !halted
3985 RtlZeroMemory(&qh
->cur_qtd
, get_elem_phys_part_size(INIT_LIST_FLAG_QTD
));
3986 qh
->cur_qtd
.alt_terminal
= 1; // don't use this
3987 qh
->cur_qtd
.terminal
= 1;
3988 qh
->cur_qtd
.status
= QTD_STS_HALT
;
3992 ehci_get_capabilities(PEHCI_DEV ehci
, PBYTE base
)
3993 // fetch capabilities register from ehci
3996 PEHCI_HCS_CONTENT phcs
;
4002 pcap
= &ehci
->ehci_caps
;
4003 pcap
->length
= EHCI_READ_PORT_UCHAR((PUCHAR
) (base
+ 0));
4004 pcap
->reserved
= EHCI_READ_PORT_UCHAR((PUCHAR
) (base
+ 1));
4005 pcap
->hci_version
= EHCI_READ_PORT_USHORT((PUSHORT
) (base
+ 2));
4006 pcap
->hcs_params
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ 4));
4007 pcap
->hcc_params
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ 8));
4009 phcs
= (PEHCI_HCS_CONTENT
) & pcap
->hcs_params
;
4010 if (phcs
->port_rout_rules
)
4012 for(i
= 0; i
< 8; i
++)
4013 pcap
->portroute
[i
] = EHCI_READ_PORT_UCHAR((PUCHAR
) (base
+ 12 + i
));
4019 ehci_delete_device(PDEVICE_OBJECT pdev
)
4022 UNICODE_STRING symb_name
;
4023 CHAR str_symb_name
[64];
4024 PEHCI_DEVICE_EXTENSION pdev_ext
;
4029 pdev_ext
= pdev
->DeviceExtension
;
4031 sprintf(str_symb_name
,
4032 "%s%d", EHCI_DOS_DEVICE_NAME
, pdev_ext
->ehci
->hcd_interf
.hcd_get_id(&pdev_ext
->ehci
->hcd_interf
));
4034 RtlInitString(&string
, str_symb_name
);
4035 RtlAnsiStringToUnicodeString(&symb_name
, &string
, TRUE
);
4036 IoDeleteSymbolicLink(&symb_name
);
4037 RtlFreeUnicodeString(&symb_name
);
4039 if (pdev_ext
->res_list
)
4040 ExFreePool(pdev_ext
->res_list
); // not allocated by usb_alloc_mem
4042 IoDeleteDevice(pdev
);
4043 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_delete_device(): device deleted\n"));
4048 ehci_stop(PEHCI_DEV ehci
)
4051 PEHCI_USBCMD_CONTENT usbcmd
;
4054 base
= ehci
->port_base
;
4055 // turn off all the interrupt
4056 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBINTR
), 0);
4057 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4058 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4059 usbcmd
->run_stop
= 0;
4060 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4064 ehci_release(PDEVICE_OBJECT pdev
)
4066 PEHCI_DEVICE_EXTENSION pdev_ext
;
4072 pdev_ext
= pdev
->DeviceExtension
;
4074 if (pdev_ext
== NULL
)
4077 ehci
= pdev_ext
->ehci
;
4083 if (pdev_ext
->ehci_int
)
4085 IoDisconnectInterrupt(pdev_ext
->ehci_int
);
4086 pdev_ext
->ehci_int
= NULL
;
4090 destroy_pending_endp_pool(&pdev_ext
->ehci
->pending_endp_pool
);
4092 ehci_destroy_schedule(ehci
);
4094 release_adapter(pdev_ext
->padapter
);
4095 pdev_ext
->padapter
= NULL
;
4097 ehci_delete_device(pdev
);
4104 ehci_start(PHCD hcd
)
4108 PEHCI_USBCMD_CONTENT usbcmd
;
4114 ehci
= struct_ptr(hcd
, EHCI_DEV
, hcd_interf
);
4115 base
= ehci
->port_base
;
4117 // stop the controller
4118 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4119 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4120 usbcmd
->run_stop
= 0;
4121 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4123 // wait the controller stop( ehci spec, 16 microframe )
4126 // reset the controller
4127 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4128 usbcmd
->hcreset
= TRUE
;
4129 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4133 // interval.QuadPart = -100 * 10000; // 10 ms
4134 // KeDelayExecutionThread( KernelMode, FALSE, &interval );
4135 KeStallExecutionProcessor(10);
4136 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4137 if (!usbcmd
->hcreset
)
4141 // prepare the registers
4142 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_CTRLDSSEGMENT
), 0);
4144 // turn on all the int
4145 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBINTR
),
4146 EHCI_USBINTR_INTE
| EHCI_USBINTR_ERR
| EHCI_USBINTR_ASYNC
| EHCI_USBINTR_HSERR
4147 // EHCI_USBINTR_FLROVR | \ // it is noisy
4148 // EHCI_USBINTR_PC | // we detect it by polling
4150 // write the list base reg
4151 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_PERIODICLISTBASE
), ehci
->frame_list_phys_addr
.LowPart
);
4153 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_ASYNCLISTBASE
), ehci
->skel_async_qh
->phys_addr
& ~(0x1f));
4155 usbcmd
->int_threshold
= 1;
4156 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4159 usbcmd
->run_stop
= 1;
4160 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4162 // set the configuration flag
4163 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_CONFIGFLAG
), 1);
4165 // enable the list traversaling
4166 usbcmd
->async_enable
= 1;
4167 usbcmd
->periodic_enable
= 1;
4168 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4174 ehci_run_stop(PEHCI_DEV ehci
, BOOLEAN start
)
4176 PEHCI_USBCMD_CONTENT usbcmd
;
4177 PEHCI_USBSTS_CONTENT usbsts
;
4184 base
= ehci
->port_base
;
4185 usbcmd
= (PEHCI_USBCMD_CONTENT
) & tmp
;
4186 usbsts
= (PEHCI_USBSTS_CONTENT
) & tmp
;
4188 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBSTS
));
4189 if (start
&& usbsts
->hc_halted
== 0)
4192 usb_dbg_print(DBGLVL_MEDIUM
, ("ehci_run_stop(): WARNING: hc running, can not start again\n"));
4195 tmp
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
));
4196 usbcmd
->run_stop
= start
? 1 : 0;
4197 EHCI_WRITE_PORT_ULONG((PULONG
) (base
+ EHCI_USBCMD
), tmp
);
4199 usb_wait_ms_dpc(2); //ehci spec 16 microframes
4203 ehci_find_min_bandwidth(PEHCI_DEV ehci
)
4209 for(i
= 0; i
< (LONG
) (ehci
->frame_count
<< 3); i
++)
4211 ehci
->min_bw
= ehci
->min_bw
< ehci
->frame_bw
[i
] ? ehci
->min_bw
: ehci
->frame_bw
[i
];
4217 ehci_claim_bw_for_int(PEHCI_DEV ehci
, PURB purb
, BOOLEAN release
)
4218 // should have pending_endp_list_lock acquired, and purb->pipe prepared
4220 PURB_HS_PIPE_CONTENT pipe_content
;
4222 ULONG interval
, bus_time
, ss_time
, cs_time
;
4224 ULONG max_packet_size
;
4226 if (ehci
== NULL
|| purb
== NULL
)
4229 if (purb
->pipe
== 0)
4233 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4234 interval
= REAL_INTERVAL
;
4235 if (pipe_content
->speed_high
== 0)
4237 // translate to high speed uframe count
4241 if (interval
> (ehci
->frame_count
<< 3))
4242 interval
= (ehci
->frame_count
<< 3);
4244 max_packet_size
= (1 << pipe_content
->max_packet_size
);
4245 if (pipe_content
->speed_high
)
4247 // this is a high speed endp
4249 bus_time
= usb_calc_bus_time(USB_SPEED_HIGH
,
4250 (pipe_content
->trans_dir
) << 7,
4251 FALSE
, min(purb
->data_length
, (LONG
) max_packet_size
));
4253 // multiple transactions per uframe
4254 if (purb
->data_length
> (LONG
) max_packet_size
)
4256 bus_time
*= (purb
->data_length
) / max_packet_size
;
4257 bus_time
+= usb_calc_bus_time(USB_SPEED_HIGH
,
4258 (pipe_content
->trans_dir
) << 7,
4259 FALSE
, purb
->data_length
% max_packet_size
);
4261 bus_time
= (bus_time
+ 1) >> 1;
4265 for(i
= pipe_content
->start_uframe
+ (purb
->int_start_frame
<< 3);
4266 i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4268 ehci
->frame_bw
[i
] += (USHORT
) bus_time
;
4272 if (bus_time
< ehci
->min_bw
)
4274 // start the poll from uframe zero of each frame
4276 pipe_content
->start_uframe
= 0;
4277 for(i
= 0; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4279 ehci
->frame_bw
[i
] -= (USHORT
) bus_time
;
4280 if (ehci
->frame_bw
[i
] < ehci
->min_bw
)
4281 ehci
->min_bw
= ehci
->frame_bw
[i
];
4284 else // bother to find a pattern
4286 for(j
= 0; j
< (LONG
) interval
; j
++)
4288 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4290 if (ehci
->frame_bw
[i
] < bus_time
)
4293 if (i
> (LONG
) (ehci
->frame_count
<< 3))
4301 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4303 ehci
->frame_bw
[i
] -= (USHORT
) bus_time
;
4304 if (ehci
->frame_bw
[i
] < ehci
->min_bw
)
4305 ehci
->min_bw
= ehci
->frame_bw
[i
];
4307 pipe_content
->start_uframe
= j
& 7;
4308 purb
->int_start_frame
= j
>> 3;
4312 else // full/low speed pipe
4314 // split condition is considered
4315 if (pipe_content
->trans_dir
)
4317 // an input interrupt, with handshake
4318 // 55 is 144 - 90 + 1, turnaround time is one byte not the worst case 90 bytes,
4319 // refer to ehci-1.0 table 4-5 p64
4320 ss_time
= 231 * 25 / 12;
4321 // cs_time = ( 55 * 8 + ( LONG )( ( ( 19 + 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12;
4322 cs_time
= (55 * 8 + (LONG
) (((7 * 8 * purb
->data_length
) / 6))) * 25 / 12;
4326 // according to ehci-1.0 table 4-5 p64
4327 ss_time
= (49 * 8 + (LONG
) (((7 * 8 * purb
->data_length
) / 6))) * 25 / 12;
4328 // 287 = 237 + 48( handshake ) + 8( turn around time )
4329 cs_time
= 287 * 25 / 12;
4331 ss_time
>>= 1, cs_time
>>= 1;
4334 for(i
= pipe_content
->start_uframe
+ (purb
->int_start_frame
<< 3);
4335 i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4337 ehci
->frame_bw
[i
] += (USHORT
) ss_time
;
4338 ehci
->frame_bw
[i
+ 2] += (USHORT
) cs_time
;
4339 ehci
->frame_bw
[i
+ 3] += (USHORT
) cs_time
;
4340 if ((i
& 0x07) != 0x06)
4341 ehci
->frame_bw
[i
+ 4] += (USHORT
) cs_time
;
4345 if (ss_time
< ehci
->min_bw
&& cs_time
< ehci
->min_bw
)
4347 pipe_content
->start_uframe
= 0;
4349 for(i
= 0; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4351 ehci
->frame_bw
[i
] -= (USHORT
) ss_time
;
4352 ehci
->min_bw
= min(ehci
->frame_bw
[i
], ehci
->min_bw
);
4353 ehci
->frame_bw
[i
+ 2] -= (USHORT
) cs_time
;
4354 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 2], ehci
->min_bw
);
4355 ehci
->frame_bw
[i
+ 3] -= (USHORT
) cs_time
;
4356 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 3], ehci
->min_bw
);
4357 if ((i
& 0x07) != 0x06)
4359 ehci
->frame_bw
[i
+ 4] -= (USHORT
) cs_time
;
4360 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 4], ehci
->min_bw
);
4366 for(j
= 0; j
< (LONG
) interval
; j
++)
4368 if ((j
& 0x7) == 7) // start-split not allowed at this uframe
4371 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4373 if (ehci
->frame_bw
[i
] < ss_time
)
4375 if (ehci
->frame_bw
[i
+ 2] < cs_time
)
4377 if (ehci
->frame_bw
[i
+ 3] < cs_time
)
4380 if (ehci
->frame_bw
[i
+ 4] < cs_time
)
4383 if (i
> (LONG
) (ehci
->frame_count
<< 3))
4390 pipe_content
->start_uframe
= j
& 7;
4391 purb
->int_start_frame
= j
>> 3;
4393 for(i
= j
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
4395 ehci
->frame_bw
[i
] -= (USHORT
) ss_time
;
4396 ehci
->min_bw
= min(ehci
->frame_bw
[i
], ehci
->min_bw
);
4397 ehci
->frame_bw
[i
+ 2] -= (USHORT
) cs_time
;
4398 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 2], ehci
->min_bw
);
4399 ehci
->frame_bw
[i
+ 3] -= (USHORT
) cs_time
;
4400 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 3], ehci
->min_bw
);
4403 ehci
->frame_bw
[i
+ 4] -= (USHORT
) cs_time
;
4404 ehci
->min_bw
= min(ehci
->frame_bw
[i
+ 4], ehci
->min_bw
);
4415 ehci_find_min_bandwidth(ehci
);
4421 ehci_get_cache_policy(PEHCI_DEV ehci
)
4423 PEHCI_HCC_CONTENT hcc_content
;
4425 hcc_content
= (PEHCI_HCC_CONTENT
) & ehci
->ehci_caps
;
4426 if (hcc_content
->iso_sched_threshold
>= 8)
4428 if (hcc_content
->iso_sched_threshold
== 0)
4430 return hcc_content
->iso_sched_threshold
+ 2;
4433 // 25/12 is bus-time per bit ( 1000 / 480 )
4434 #define BEST_BUDGET_TIME_UFRAME ( ( 188 * 7 / 6 ) * 25 / 12 )
4436 // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet
4437 // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet
4438 #define iso_max_data_load( dir ) ( dir == USB_DIR_IN ? \
4439 ( ( 188 * 8 - 231 - 8 - 67 + ( 8 - 1 ) ) / 8 ) : ( 188 - 49 ) )
4441 #define iso_uframes_data_load( dir, data_load, uf_cnt )
4444 ehci_claim_bw_for_iso(PEHCI_DEV ehci
, PURB purb
, BOOLEAN release
)
4446 PURB_HS_PIPE_CONTENT pipe_content
;
4448 ULONG interval
, bus_time
, ss_time
, cs_time
, remainder
;
4450 ULONG cur_uframe
, start_uframe
= 0, max_time
, max_packet_size
;
4452 if (ehci
== NULL
|| purb
== NULL
)
4455 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4456 base
= ehci
->port_base
;
4457 cur_uframe
= EHCI_READ_PORT_ULONG((PULONG
) (base
+ EHCI_FRINDEX
)) + 1;
4460 max_packet_size
= purb
->params
[0]; //( 1 << pipe_content->max_packet_size );
4462 if (pipe_content
->speed_high
)
4464 interval
= REAL_INTERVAL
;
4465 if (purb
->iso_frame_count
== 0 || purb
->iso_frame_count
+ 2 * 8 > (LONG
) (ehci
->frame_count
<< 3))
4468 for(i
= 0, max_time
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4470 bus_time
= usb_calc_bus_time(USB_SPEED_HIGH
,
4471 (pipe_content
->trans_dir
) << 7,
4472 TRUE
, min(purb
->iso_packet_desc
[i
].length
, (LONG
) max_packet_size
));
4473 // NOTE: we did not use endp_mult_count here, because the comparison is enough
4474 // to calculate the bandwidth
4475 if (purb
->iso_packet_desc
[i
].length
> (LONG
) max_packet_size
)
4477 // multiple transactions per uframe
4478 bus_time
*= purb
->iso_packet_desc
[i
].length
/ max_packet_size
;
4479 bus_time
+= usb_calc_bus_time(USB_SPEED_HIGH
,
4480 (pipe_content
->trans_dir
) << 7,
4481 TRUE
, purb
->iso_packet_desc
[i
].length
% max_packet_size
);
4483 bus_time
= (bus_time
+ 1) >> 1;
4484 max_time
= max(bus_time
, max_time
);
4485 purb
->iso_packet_desc
[i
].bus_time
= bus_time
;
4490 // it is a release operation
4491 for(i
= purb
->iso_start_frame
, k
= 0; k
< (LONG
) purb
->iso_frame_count
;
4492 k
++, i
= (i
+ interval
) % (ehci
->frame_count
<< 3))
4494 ehci
->frame_bw
[i
] += (USHORT
) purb
->iso_packet_desc
[k
].bus_time
;
4496 ehci_find_min_bandwidth(ehci
);
4500 if (max_time
< ehci
->min_bw
)
4502 start_uframe
= cur_uframe
+ ehci_get_cache_policy(ehci
); // avoid cache
4503 for(i
= start_uframe
, j
= 0; j
< (LONG
) purb
->iso_frame_count
;
4504 i
= (i
+ interval
) % (ehci
->frame_count
<< 3), j
++)
4506 ehci
->frame_bw
[i
] -= (USHORT
) purb
->iso_packet_desc
[j
].bus_time
;
4507 ehci
->min_bw
= min(ehci
->frame_bw
[j
], ehci
->min_bw
);
4509 purb
->iso_start_frame
= start_uframe
;
4512 else // max_time >= ehci->min_bw
4514 for(j
= 0; j
< (LONG
) interval
; j
++)
4516 start_uframe
= cur_uframe
+ ehci_get_cache_policy(ehci
) + j
;
4517 for(i
= start_uframe
, k
= 0; k
< (LONG
) purb
->iso_frame_count
;
4518 k
++, i
= (i
+ interval
) % (ehci
->frame_count
<< 3))
4520 if (ehci
->frame_bw
[i
] < (USHORT
) purb
->iso_packet_desc
[k
].bus_time
)
4526 if (k
< (LONG
) purb
->iso_frame_count
)
4533 // allocate the bandwidth
4534 for(i
= start_uframe
, k
= 0; k
< (LONG
) purb
->iso_frame_count
;
4535 k
++, i
= (i
+ interval
) % (ehci
->frame_count
<< 3))
4537 ehci
->frame_bw
[i
] -= (USHORT
) purb
->iso_packet_desc
[k
].bus_time
;
4538 ehci
->min_bw
= min(ehci
->min_bw
, ehci
->frame_bw
[i
]);
4540 purb
->iso_start_frame
= start_uframe
;
4544 else // not high speed endpoint
4547 if (purb
->iso_frame_count
== 0 || purb
->iso_frame_count
+ 2 > (LONG
) ehci
->frame_count
)
4550 if (max_packet_size
> 1023)
4556 // calculate for each frame
4557 // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet
4558 // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet
4559 // bit-stuffing is for high speed bus transfer
4562 if (pipe_content
->trans_dir
)
4564 // an input transfer, no handshake
4565 ss_time
= 231 * 25 / 12;
4566 // cs_time = ( 231 + 8 + 67 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
4567 cs_time
= (231 + 8 + 67 + (LONG
) (((7 * 8 * 188) / 6))) * 25 / 12;
4571 // an output transfer according to ehci-1.0 table 4-5 p64
4572 // ss_time = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12;
4573 ss_time
= (49 * 8 + (LONG
) (((7 * 8 * 188) / 6))) * 25 / 12;
4575 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4577 // remainder = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * ( purb->iso_packet_desc[ i ].length % 188 ) ) / 6 ) ) ) * 25 / 12;
4579 (49 * 8 + (LONG
) (((7 * 8 * (purb
->iso_packet_desc
[i
].length
% 188)) / 6))) * 25 / 12;
4581 purb
->iso_packet_desc
[i
].params
.bus_time
= (USHORT
) remainder
;
4587 cur_uframe
= (cur_uframe
+ 7) & (~0x07);
4589 j
= ehci
->frame_count
<< 3;
4592 if (pipe_content
->trans_dir
)
4594 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4596 ehci
->frame_bw
[purb
->iso_packet_desc
[i
].params
.start_uframe
] += (USHORT
) ss_time
;
4597 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4599 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] += (USHORT
) cs_time
;
4602 // two extra complete-split
4603 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] += (USHORT
) cs_time
;
4604 ehci
->frame_bw
[(cur_uframe
+ 0x13 + (i
<< 3) + k
) % j
] += (USHORT
) cs_time
;
4609 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4611 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4613 ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3) + k
) % j
] += (USHORT
) ss_time
;
4617 ehci_find_min_bandwidth(ehci
);
4620 // search for available bw
4621 if (ss_time
< ehci
->min_bw
&& cs_time
< ehci
->min_bw
)
4623 if (pipe_content
->trans_dir
)
4625 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4627 ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3)) % j
] -= (USHORT
) ss_time
;
4628 ehci
->min_bw
= min(ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3)) % j
], ehci
->min_bw
);
4630 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4632 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] -= (USHORT
) cs_time
;
4634 min(ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
], ehci
->min_bw
);
4637 // two extra complete-split
4638 ehci
->frame_bw
[(cur_uframe
+ 0x12 + (i
<< 3) + k
) % j
] -= (USHORT
) cs_time
;
4639 ehci
->min_bw
= min(ehci
->frame_bw
[cur_uframe
+ 0x12 + (i
<< 3) + k
], ehci
->min_bw
);
4640 ehci
->frame_bw
[(cur_uframe
+ 0x13 + (i
<< 3) + k
) % j
] -= (USHORT
) cs_time
;
4641 ehci
->min_bw
= min(ehci
->frame_bw
[cur_uframe
+ 0x13 + (i
<< 3) + k
], ehci
->min_bw
);
4646 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4648 for(k
= 0; k
< (purb
->iso_packet_desc
[i
].length
+ 187) / 188; k
++)
4650 ehci
->frame_bw
[(cur_uframe
+ 0x10 + (i
<< 3) + k
) % j
] -= (USHORT
) ss_time
;
4652 min(ehci
->frame_bw
[(cur_uframe
+ 0x11 + (i
<< 3) + k
) % j
], ehci
->min_bw
);
4656 purb
->iso_start_frame
= 0;
4657 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4660 purb
->iso_packet_desc
[i
].params
.start_uframe
= (USHORT
) (cur_uframe
+ 0x10);
4662 purb
->iso_packet_desc
[i
].params
.start_uframe
=
4663 purb
->iso_packet_desc
[i
- 1].params
.start_uframe
+ 0x8;
4667 else // take the pain to find one
4672 for(j
= (cur_uframe
>> 3) + 2; j
!= (LONG
) (cur_uframe
>> 3); j
= (j
+ 1) % ehci
->frame_count
)
4676 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4678 large
= purb
->iso_packet_desc
[i
].length
> 579;
4679 base
= (purb
->iso_packet_desc
[i
].length
+ 187) / 188;
4684 if (pipe_content
->trans_dir
)
4686 // input split iso, for those large than 579, schedule it at the uframe boundary
4687 for(temp
= 0; temp
< (large
== FALSE
) ? (8 - base
- 1) : 1; temp
++)
4689 k
= (((j
+ i
) << 3) + temp
) % (ehci
->frame_count
<< 3);
4690 if (ehci
->frame_bw
[k
] > ss_time
)
4697 frame_bw
[(((j
+ i
) << 3) + 1 + temp
+ k
) % (ehci
->frame_count
<< 3)] <
4702 if (k
> 0) // not available
4705 // the first following extra cs
4706 k
= (((j
+ i
) << 3) + 2 + temp
+ base
) % (ehci
->frame_count
<< 3);
4707 if (ehci
->frame_bw
[k
] < cs_time
)
4712 // very large one does not have this second extra cs
4713 if (ehci
->frame_bw
[(k
+ 1) % (ehci
->frame_count
<< 3)] < cs_time
)
4718 if (temp
== 8 - 1 - base
) // no bandwidth for ss
4723 // note: 8 - 1 - base has different meaning from the above
4724 // it is to avoid the ss on H-Frame 7, but the above one is
4725 // the latency of the classic bus.
4726 for(temp
= 0; temp
< 8 - 1 - base
; temp
++)
4728 if (ehci
->frame_bw
[((j
+ i
) << 3) % (ehci
->frame_count
<< 3) + temp
] > ss_time
)
4731 for(k
= temp
; k
< temp
+ base
; k
++)
4733 if (ehci
->frame_bw
[((j
+ i
) << 3) % (ehci
->frame_count
<< 3) + k
] < ss_time
)
4738 if (temp
== 8 - 1 - base
)
4742 purb
->iso_packet_desc
[i
].params
.start_uframe
=
4743 (USHORT
) ((((j
+ i
) << 3) + temp
) % (ehci
->frame_count
<< 3));
4746 if (i
< (LONG
) purb
->iso_frame_count
)
4748 // skip to the next section
4749 j
= (j
+ i
) % (ehci
->frame_count
<< 3);
4755 // FIXME: Should we claim bw for the last complete split sitd? this is not done
4759 if (pipe_content
->trans_dir
)
4762 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4764 j
= purb
->iso_packet_desc
[i
].length
;
4765 temp
= (purb
->iso_packet_desc
[i
].params
.start_uframe
) % (ehci
->frame_count
<< 3);
4766 ehci
->frame_bw
[temp
] -= (USHORT
) ss_time
;
4767 for(k
= 0; k
< (j
+ 187) / 188; j
++)
4769 ehci
->frame_bw
[temp
+ 2 + k
] -= (USHORT
) cs_time
;
4771 ehci
->frame_bw
[temp
+ 2 + k
] -= (USHORT
) cs_time
;
4772 if ((j
+ 187) / 188 < 6) //ehci restriction
4774 ehci
->frame_bw
[temp
+ 3 + k
] -= (USHORT
) cs_time
;
4780 for(i
= 0; i
< (LONG
) purb
->iso_frame_count
; i
++)
4782 j
= purb
->iso_packet_desc
[i
].length
;
4783 temp
= (purb
->iso_packet_desc
[i
].params
.start_uframe
) % (ehci
->frame_count
<< 3);
4784 for(k
= 0; k
< j
/ 188; j
++)
4786 ehci
->frame_bw
[temp
+ k
] -= (USHORT
) ss_time
;
4789 ehci
->frame_bw
[temp
+ k
] -= purb
->iso_packet_desc
[i
].params
.bus_time
;
4799 ehci_claim_bandwidth(PEHCI_DEV ehci
, PURB purb
, BOOLEAN claim_bw
) //true to claim band-width, false to free band-width
4800 // should have pending_endp_list_lock acquired, and purb->pipe prepared
4802 PURB_HS_PIPE_CONTENT pipe_content
;
4805 if (ehci
== NULL
|| purb
== NULL
)
4809 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4810 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
4812 ret
= ehci_claim_bw_for_iso(ehci
, purb
, claim_bw
? FALSE
: TRUE
);
4814 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
4816 ret
= ehci_claim_bw_for_int(ehci
, purb
, claim_bw
? FALSE
: TRUE
);
4824 ehci_can_remove(PURB purb
, BOOLEAN door_bell_rings
, ULONG cur_frame
)
4825 // test if the purb can be removed from the schedule, by current frame index and
4828 PURB_HS_PIPE_CONTENT pipe_content
;
4831 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4832 interval
= REAL_INTERVAL
;
4834 switch (purb
->flags
& URB_FLAG_STATE_MASK
)
4836 case URB_FLAG_STATE_PENDING
:
4842 case URB_FLAG_STATE_IN_PROCESS
:
4846 case URB_FLAG_STATE_DOORBELL
:
4848 if ((pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
4849 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
) && door_bell_rings
== TRUE
)
4853 else if ((pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
4854 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
))
4864 case URB_FLAG_STATE_WAIT_FRAME
:
4866 // need more processing
4867 if ((purb
->flags
& URB_FLAG_FORCE_CANCEL
) == 0)
4872 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
4874 return door_bell_rings
;
4876 else // isochronous can not be canceled
4886 NTSTATUS
ehci_remove_urb_from_schedule(PEHCI_DEV ehci
, PURB purb
);
4889 ehci_deactivate_urb(PURB purb
)
4891 PURB_HS_PIPE_CONTENT pipe_content
;
4892 PLIST_ENTRY pthis
, pnext
;
4893 PEHCI_QH_CONTENT pqh_content
;
4894 PEHCI_QTD_CONTENT pqtd_content
;
4899 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
4900 switch (pipe_content
->trans_type
)
4902 case USB_ENDPOINT_XFER_CONTROL
:
4903 case USB_ENDPOINT_XFER_BULK
:
4904 case USB_ENDPOINT_XFER_INT
:
4906 ListFirst(&purb
->trasac_list
, pthis
);
4907 pqh_content
= (PEHCI_QH_CONTENT
) qh_from_list_entry(pthis
);
4908 ListNext(&purb
->trasac_list
, pthis
, pnext
);
4911 pqtd_content
= (PEHCI_QTD_CONTENT
) qtd_from_list_entry(pthis
);
4912 if (pqtd_content
->status
& QTD_STS_ACTIVE
)
4914 pqtd_content
->status
&= ~QTD_STS_ACTIVE
;
4916 ListNext(&purb
->trasac_list
, pthis
, pnext
);
4923 case USB_ENDPOINT_XFER_ISOC
:
4934 ehci_insert_bulk_schedule(PEHCI_DEV ehci
, PURB purb
)
4935 // list head is only a handle, the qh and qtd are following it.
4937 PLIST_ENTRY list_head
;
4938 PEHCI_QH pqh
, pqhprev
, pqhnext
;
4939 PLIST_ENTRY pthis
, pprev
, pnext
;
4941 if (ehci
== NULL
|| purb
== NULL
)
4944 list_head
= &purb
->trasac_list
;
4945 ListFirst(list_head
, pthis
);
4949 if (elem_type_list_entry(pthis
) != INIT_LIST_FLAG_QH
)
4952 pqh
= qh_from_list_entry(pthis
);
4954 ListFirstPrev(&ehci
->async_list_cpu
, pprev
);
4955 pqhprev
= qh_from_schedule(pprev
);
4958 ListFirst(&ehci
->async_list_cpu
, pnext
);
4959 pqhnext
= qh_from_schedule(pnext
);
4961 if (pprev
== &ehci
->async_list_cpu
)
4963 // always a qh in async list
4967 pqh
->hw_next
= pqhnext
->phys_addr
;
4968 InsertTailList(&ehci
->async_list_cpu
, &pqh
->elem_head_link
->sched_link
);
4969 pqhprev
->hw_next
= pqh
->phys_addr
;
4974 ehci_remove_bulk_from_schedule(PEHCI_DEV ehci
, PURB purb
)
4975 // executed in isr, and have frame_list_lock acquired, so
4976 // never try to acquire any spin-lock
4977 // remove the bulk purb from schedule, and mark it not in
4980 PLIST_ENTRY list_head
;
4981 PEHCI_QH pqh
, pqhprev
, pqhnext
;
4982 PEHCI_QH_CONTENT pqhc
;
4983 PLIST_ENTRY pthis
, pprev
, pnext
;
4985 if (ehci
== NULL
|| purb
== NULL
)
4988 list_head
= &purb
->trasac_list
;
4989 ListFirst(list_head
, pthis
);
4995 pqh
= qh_from_list_entry(pthis
);
4996 pqhc
= (PEHCI_QH_CONTENT
) pqh
;
4998 if (pqhc
->is_async_head
)
5001 ListFirst(&pqh
->elem_head_link
->sched_link
, pnext
);
5002 ListFirstPrev(&pqh
->elem_head_link
->sched_link
, pprev
);
5004 if (pprev
== &ehci
->async_list_cpu
)
5006 // we will at least have a qh with H-bit 1 in the async-list
5009 else if (pnext
== &ehci
->async_list_cpu
)
5011 // remove the last one
5012 pqhprev
= qh_from_schedule(pprev
);
5013 ListFirst(&ehci
->async_list_cpu
, pnext
);
5014 pqhnext
= qh_from_schedule(pnext
);
5015 pqhprev
->hw_next
= pqhnext
->phys_addr
;
5019 pqhprev
= qh_from_schedule(pprev
);
5020 pqhnext
= qh_from_schedule(pnext
);
5021 pqhprev
->hw_next
= pqhnext
->phys_addr
;
5023 RemoveEntryList(&pqh
->elem_head_link
->sched_link
);
5029 ehci_insert_fstn_schedule(PEHCI_DEV ehci
, PURB purb
)
5032 PURB_HS_PIPE_CONTENT pipe_content
, pc
;
5033 PLIST_ENTRY pthis
, list_head
, pnext
= NULL
, pprev
;
5038 ULONG interval
, start_frame
, start_uframe
;
5041 if (ehci
== NULL
|| purb
== NULL
)
5044 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5045 interval
= (1 << (pipe_content
->interval
+ 3));
5046 list_head
= &purb
->trasac_list
;
5047 start_frame
= purb
->int_start_frame
;
5048 start_uframe
= (start_frame
<< 3) + 1; //( start_frame << 3 ) + pipe_content->start_uframe;
5050 if ((start_frame
<< 3) >= interval
)
5053 ListFirstPrev(list_head
, pprev
);
5055 if (elem_type_list_entry(pprev
) != INIT_LIST_FLAG_FSTN
)
5061 pfstn
= fstn_from_list_entry(pprev
);
5065 ListFirst(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
);
5067 // skip the first one
5068 ListNext(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
, pnext
);
5074 purb1
= qh_from_schedule(pthis
)->elem_head_link
->purb
;
5075 pc
= (PURB_HS_PIPE_CONTENT
) & purb1
->pipe
;
5081 if ((1 << (pc
->interval
+ 3)) > (LONG
) interval
)
5086 else if ((1 << (pc
->interval
+ 3) < (LONG
) interval
))
5090 else if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5092 ListNext(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
, pnext
);
5096 else if (pc
->start_uframe
<= 1)
5098 ListNext(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
], pthis
, pnext
);
5112 InsertTailList(&ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
],
5113 &pfstn
->elem_head_link
->sched_link
);
5117 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5119 InsertHeadList(&fstn_from_schedule(pprev
)->elem_head_link
->sched_link
,
5120 &pfstn
->elem_head_link
->sched_link
);
5124 InsertHeadList(&qh_from_schedule(pprev
)->elem_head_link
->sched_link
,
5125 &pfstn
->elem_head_link
->sched_link
);
5128 pfstn
->hw_next
= qh_from_schedule(pprev
)->hw_next
;
5129 qh_from_schedule(pprev
)->hw_next
= pfstn
->phys_addr
;
5134 for(i
= start_frame
; i
< (LONG
) start_frame
+ 1; i
+= (interval
>> 3))
5136 list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5137 ListFirst(list_head
, pthis
);
5142 // skip itds and sitds
5143 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_ITD
||
5144 elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_SITD
)
5146 ListNext(list_head
, pthis
, pnext
);
5156 // find the insertion point
5159 pqhnext
= qh_from_schedule(pthis
);
5160 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5161 purb1
= fstn_from_schedule(pthis
)->elem_head_link
->purb
;
5163 purb1
= pqhnext
->elem_head_link
->purb
;
5168 pc
= (PURB_HS_PIPE_CONTENT
) & purb1
->pipe
;
5169 u
= 1 << (pc
->speed_high
? (1 << pc
->interval
) : (1 << (pc
->interval
+ 3)));
5173 ListNext(list_head
, pthis
, pnext
);
5178 else if (u
== interval
)
5181 (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
?
5182 1 : pc
->start_uframe
) + (purb1
->int_start_frame
<< 3))
5184 ListNext(list_head
, pthis
, pnext
);
5192 else if (u
< interval
)
5198 if (pprev
== list_head
)
5200 // insert to the list head
5201 pnext
= pfstn
->elem_head_link
->sched_link
.Flink
= list_head
->Flink
;
5202 list_head
->Flink
= &pfstn
->elem_head_link
->sched_link
;
5203 pfstn
->hw_next
= ehci
->frame_list
[i
]; // point to following node
5204 ehci
->frame_list
[i
] = pfstn
->phys_addr
;
5208 pnext
= pfstn
->elem_head_link
->sched_link
.Flink
= pprev
->Flink
;
5209 pprev
->Flink
= &pfstn
->elem_head_link
->sched_link
;
5211 // fstn can be handled correctly
5212 pfstn
->hw_next
= qh_from_schedule(pprev
)->hw_next
;
5213 qh_from_schedule(pprev
)->hw_next
= pfstn
->phys_addr
;
5216 // the pointer to next node of this fstn is alway same across the frame list.
5217 for(i
= start_frame
+ (interval
>> 3); i
< (LONG
) ehci
->frame_count
; i
+= (interval
>> 3))
5219 pprev
= list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5220 ListFirst(list_head
, pthis
);
5229 ListNext(list_head
, pthis
, pthis
);
5232 pprev
->Flink
= &pfstn
->elem_head_link
->sched_link
;
5233 if (pprev
== list_head
)
5234 ehci
->frame_list
[i
] = pfstn
->phys_addr
;
5236 qh_from_schedule(pprev
)->hw_next
= pfstn
->phys_addr
;
5242 ehci_remove_fstn_from_schedule(PEHCI_DEV ehci
, PURB purb
)
5244 PURB_HS_PIPE_CONTENT pipe_content
;
5245 PLIST_ENTRY pthis
, list_head
, pnext
, pprev
;
5248 ULONG interval
, start_frame
, start_uframe
;
5251 if (ehci
== NULL
|| purb
== NULL
)
5254 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5255 interval
= (1 << (pipe_content
->interval
+ 3));
5256 list_head
= &purb
->trasac_list
;
5257 start_frame
= purb
->int_start_frame
;
5260 if ((start_frame
<< 3) >= interval
)
5264 ListFirstPrev(list_head
, pprev
);
5265 if (elem_type_list_entry(pprev
) != INIT_LIST_FLAG_FSTN
)
5271 pfstn
= fstn_from_list_entry(pprev
);
5279 ListFirstPrev(&pfstn
->elem_head_link
->sched_link
, pprev
);
5280 qh_from_schedule(pprev
)->hw_next
= pfstn
->hw_next
;
5281 RemoveEntryList(&pfstn
->elem_head_link
->sched_link
);
5285 for(i
= start_frame
; i
< (LONG
) ehci
->frame_count
; i
++)
5287 ListFirst(&ehci
->frame_list_cpu
[i
].td_link
, pthis
);
5293 pprev
= &ehci
->frame_list_cpu
[i
].td_link
;
5294 while (pthis
&& pthis
!= &pfstn
->elem_head_link
->sched_link
)
5297 ListNext(&ehci
->frame_list_cpu
[i
].td_link
, pthis
, pnext
);
5305 qh_from_schedule(pprev
)->hw_next
= pfstn
->hw_next
;
5306 pprev
->Flink
= pfstn
->elem_head_link
->sched_link
.Flink
;
5313 ehci_insert_int_schedule(PEHCI_DEV ehci
, PURB purb
)
5315 PURB_HS_PIPE_CONTENT pipe_content
, pc
;
5316 PLIST_ENTRY pthis
, list_head
, pnext
= NULL
, pprev
;
5317 PEHCI_ELEM_LINKS elem_link
;
5318 PEHCI_QH pqh
, pqhprev
, pqhnext
;
5321 ULONG interval
, u
, start_frame
, start_uframe
;
5325 if (ehci
== NULL
|| purb
== NULL
)
5328 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5329 interval
= REAL_INTERVAL
;
5330 start_uframe
= (purb
->int_start_frame
<< 3) + pipe_content
->start_uframe
;
5331 start_frame
= purb
->int_start_frame
;
5333 list_head
= &purb
->trasac_list
;
5335 ListFirst(list_head
, pthis
);
5339 pqh
= qh_from_list_entry(pthis
);
5341 if (!pipe_content
->speed_high
)
5343 interval
= (interval
<< 3);
5344 ListFirstPrev(list_head
, pprev
);
5345 if (elem_type_list_entry(pprev
) == INIT_LIST_FLAG_FSTN
)
5351 pqhprev
= pqhnext
= NULL
;
5354 list_head
= &ehci
->periodic_list_cpu
[EHCI_SCHED_FSTN_INDEX
];
5355 ListFirst(list_head
, pthis
);
5356 InsertTailList(list_head
, &pqh
->elem_head_link
->sched_link
);
5357 ListFirstPrev(&pqh
->elem_head_link
->sched_link
, pprev
);
5358 pqh
->hw_next
= EHCI_PTR_TERM
;
5361 fstn_from_schedule(pthis
)->hw_next
= pqh
->phys_addr
;
5365 qh_from_schedule(pthis
)->hw_next
= pqh
->phys_addr
;
5368 else // interval == 2 or 4 or 8
5370 list_head
= &ehci
->periodic_list_cpu
[EHCI_SCHED_INT8_INDEX
];
5371 ListFirst(list_head
, pthis
);
5375 elem_link
= struct_ptr(pthis
, EHCI_ELEM_LINKS
, sched_link
);
5376 purb1
= elem_link
->purb
;
5377 pc
= (PURB_HS_PIPE_CONTENT
) purb1
->pipe
;
5378 u
= (pc
->speed_high
? (1 << pc
->interval
) : (1 << (pc
->interval
+ 3)));
5382 ListFirstPrev(pthis
, pprev
);
5385 else if (interval
> u
)
5387 ListNext(list_head
, pthis
, pnext
);
5392 // FIXME: is this right to fix fstn's start_uf 1???
5393 else if (start_uframe
<=
5394 (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
?
5395 1 : pc
->start_uframe
) + (purb1
->int_start_frame
<< 3))
5397 ListNext(list_head
, pthis
, pnext
);
5402 else // interval is equal, and start_uframe is greater
5404 ListFirstPrev(pthis
, pprev
);
5410 // at least one dummy qh is there
5413 else if (pnext
== NULL
)
5415 // the last one in this chain, fstn can be handled correctly
5416 InsertTailList(list_head
, &pqh
->elem_head_link
->sched_link
);
5417 pqhprev
= qh_from_schedule(pprev
);
5418 pqh
->hw_next
= pqhprev
->hw_next
;
5419 pqhprev
->hw_next
= pqh
->phys_addr
;
5423 pqhprev
= qh_from_schedule(pprev
);
5424 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_QH
)
5426 InsertHeadList(&pqhprev
->elem_head_link
->sched_link
, &pqh
->elem_head_link
->sched_link
);
5428 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5430 InsertHeadList(&fstn_from_schedule(pprev
)->elem_head_link
->sched_link
,
5431 &pqh
->elem_head_link
->sched_link
);
5433 pqh
->hw_next
= pqhprev
->hw_next
;
5434 pqhprev
->hw_next
= pqh
->phys_addr
;
5438 else // interval >= 16
5440 if ((start_frame
<< 3) >= interval
)
5443 for(i
= start_frame
; i
< (LONG
) start_frame
+ 1; i
+= (interval
>> 3))
5445 list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5446 ListFirst(list_head
, pthis
);
5451 // skip itds and sitds
5452 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_ITD
||
5453 elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_SITD
)
5455 ListNext(list_head
, pthis
, pnext
);
5465 // find the insertion point
5467 pqhnext
= qh_from_schedule(pthis
);
5468 if (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5469 purb1
= fstn_from_schedule(pthis
)->elem_head_link
->purb
;
5471 purb1
= pqhnext
->elem_head_link
->purb
;
5476 pc
= (PURB_HS_PIPE_CONTENT
) & purb1
->pipe
;
5477 u
= 1 << (pc
->speed_high
? (1 << pc
->interval
) : (1 << (pc
->interval
+ 3)));
5481 ListNext(list_head
, pthis
, pnext
);
5486 else if (u
== interval
)
5489 (elem_type(pthis
, FALSE
) == INIT_LIST_FLAG_FSTN
?
5490 1 : pc
->start_uframe
) + (purb1
->int_start_frame
<< 3))
5492 ListNext(list_head
, pthis
, pnext
);
5500 else if (u
< interval
)
5505 if (pprev
== list_head
)
5507 // insert to the list head
5508 pnext
= pqh
->elem_head_link
->sched_link
.Flink
= list_head
->Flink
;
5509 list_head
->Flink
= &pqh
->elem_head_link
->sched_link
;
5510 pqh
->hw_next
= ehci
->frame_list
[i
]; // point to following node
5511 ehci
->frame_list
[i
] = pqh
->phys_addr
;
5515 pnext
= pqh
->elem_head_link
->sched_link
.Flink
= pprev
->Flink
;
5516 pprev
->Flink
= &pqh
->elem_head_link
->sched_link
;
5518 // fstn can be handled correctly
5519 pqh
->hw_next
= qh_from_schedule(pprev
)->hw_next
;
5520 qh_from_schedule(pprev
)->hw_next
= pqh
->phys_addr
;
5523 for(i
= start_frame
+ (interval
>> 3); i
< (LONG
) ehci
->frame_count
; i
+= (interval
>> 3))
5525 pprev
= list_head
= &ehci
->frame_list_cpu
[i
].td_link
;
5526 ListFirst(list_head
, pthis
);
5535 ListNext(list_head
, pthis
, pthis
);
5538 pprev
->Flink
= &pqh
->elem_head_link
->sched_link
;
5539 if (pprev
== list_head
)
5540 ehci
->frame_list
[i
] = pqh
->phys_addr
;
5542 qh_from_schedule(pprev
)->hw_next
= pqh
->phys_addr
;
5547 ehci_insert_fstn_schedule(ehci
, purb
);
5553 ehci_remove_int_from_schedule(PEHCI_DEV ehci
, PURB purb
)
5555 PURB_HS_PIPE_CONTENT pipe_content
;
5556 PLIST_ENTRY pthis
, list_head
, pnext
, pprev
, pcur
;
5557 PEHCI_QH pqh
, pqhprev
;
5559 ULONG interval
, start_frame
, start_uframe
;
5562 if (ehci
== NULL
|| purb
== NULL
)
5565 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5566 interval
= REAL_INTERVAL
;
5567 start_uframe
= (purb
->int_start_frame
<< 3) + pipe_content
->start_uframe
;
5568 start_frame
= purb
->int_start_frame
;
5570 ListFirst(&purb
->trasac_list
, pthis
);
5574 pqh
= qh_from_list_entry(pthis
);
5575 list_head
= &purb
->trasac_list
;
5577 if (IsListEmpty(list_head
))
5583 if (!pipe_content
->speed_high
)
5585 interval
= (interval
<< 3);
5588 if (interval
>= 256 * 8)
5593 ListFirstPrev(&pqh
->elem_head_link
->sched_link
, pprev
);
5594 RemoveEntryList(&pqh
->elem_head_link
->sched_link
);
5597 pqhprev
= qh_from_schedule(pprev
);
5598 pqhprev
->hw_next
= pqh
->hw_next
;
5602 ListFirst(&ehci
->frame_list_cpu
[EHCI_SCHED_FSTN_INDEX
].td_link
, list_head
);
5603 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5605 fstn_from_schedule(list_head
)->hw_next
= pqh
->hw_next
;
5609 qh_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5613 else if (interval
>= 16)
5615 ListFirst(list_head
, pthis
);
5616 pthis
= &pqh
->elem_head_link
->sched_link
;
5618 for(i
= start_uframe
; i
< (LONG
) (ehci
->frame_count
<< 3); i
+= interval
)
5620 ListFirst(&ehci
->frame_list_cpu
[i
].td_link
, pcur
);
5622 while (pthis
!= pcur
&& pcur
)
5624 ListNext(&ehci
->frame_list_cpu
[i
].td_link
, pcur
, pnext
);
5634 else if (pprev
== NULL
)
5636 // the first one in the frame list
5637 ehci
->frame_list_cpu
[i
].td_link
.Flink
= pthis
->Flink
;
5638 ehci
->frame_list
[i
] = qh_from_schedule(pthis
)->hw_next
;
5642 if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_QH
)
5644 qh_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5645 pqh
->elem_head_link
->sched_link
.Flink
;
5646 qh_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5648 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_ITD
)
5650 itd_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5651 pqh
->elem_head_link
->sched_link
.Flink
;
5652 itd_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5654 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_SITD
)
5656 sitd_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5657 pqh
->elem_head_link
->sched_link
.Flink
;
5658 sitd_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5660 else if (elem_type(pprev
, FALSE
) == INIT_LIST_FLAG_FSTN
)
5662 fstn_from_schedule(pprev
)->elem_head_link
->sched_link
.Flink
=
5663 pqh
->elem_head_link
->sched_link
.Flink
;
5664 fstn_from_schedule(pprev
)->hw_next
= pqh
->hw_next
;
5672 ListFirstPrev(&purb
->trasac_list
, pprev
);
5673 if (elem_type_list_entry(pprev
) == INIT_LIST_FLAG_FSTN
)
5674 ehci_remove_fstn_from_schedule(ehci
, purb
);
5679 ehci_insert_iso_schedule(PEHCI_DEV ehci
, PURB purb
)
5681 PURB_HS_PIPE_CONTENT pipe_content
;
5682 PLIST_ENTRY pthis
, list_head
, pnext
;
5684 ULONG interval
, start_frame
;
5687 if (ehci
== NULL
|| purb
== NULL
)
5690 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5693 if (pipe_content
->speed_high
)
5694 interval
= REAL_INTERVAL
;
5696 start_frame
= purb
->iso_start_frame
;
5698 ListFirst(&purb
->trasac_list
, pthis
);
5705 list_head
= &purb
->trasac_list
;
5706 if (IsListEmpty(list_head
))
5715 if (pipe_content
->speed_high
)
5717 itd_from_list_entry(pthis
)->elem_head_link
->sched_link
.Flink
=
5718 ehci
->frame_list_cpu
[i
].td_link
.Flink
;
5719 itd_from_list_entry(pthis
)->hw_next
= ehci
->frame_list
[i
];
5721 ehci
->frame_list
[i
] = itd_from_list_entry(pthis
)->phys_addr
;
5722 ehci
->frame_list_cpu
[i
].td_link
.Flink
= pthis
;
5726 sitd_from_list_entry(pthis
)->elem_head_link
->sched_link
.Flink
=
5727 ehci
->frame_list_cpu
[i
].td_link
.Flink
;
5728 sitd_from_list_entry(pthis
)->hw_next
= ehci
->frame_list
[i
];
5730 ehci
->frame_list
[i
] = sitd_from_list_entry(pthis
)->phys_addr
;
5731 ehci
->frame_list_cpu
[i
].td_link
.Flink
= pthis
;
5734 ListNext(list_head
, pthis
, pnext
);
5740 i
+= (interval
>> 3);
5746 ehci_remove_iso_from_schedule(PEHCI_DEV ehci
, PURB purb
)
5748 PURB_HS_PIPE_CONTENT pipe_content
;
5749 PLIST_ENTRY pthis
, list_head
, pnext
, pprev
, pcur
;
5751 ULONG interval
, start_frame
;
5754 if (ehci
== NULL
|| purb
== NULL
)
5757 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5760 if (pipe_content
->speed_high
)
5761 interval
= REAL_INTERVAL
;
5763 start_frame
= purb
->iso_start_frame
;
5765 ListFirst(&purb
->trasac_list
, pthis
);
5772 list_head
= &purb
->trasac_list
;
5773 if (IsListEmpty(list_head
))
5782 // for the possible existance of sitd back pointer, we can not use for(...)
5783 ListFirst(&ehci
->frame_list_cpu
[i
].td_link
, pcur
);
5784 pprev
= &ehci
->frame_list_cpu
[i
].td_link
;
5789 ListNext(&ehci
->frame_list_cpu
[i
].td_link
, pcur
, pnext
);
5801 pprev
->Flink
= pcur
->Flink
;
5802 if (pprev
!= &ehci
->frame_list_cpu
[i
].td_link
)
5803 qh_from_schedule(pprev
)->hw_next
= qh_from_schedule(pcur
)->hw_next
;
5805 ehci
->frame_list
[i
] = qh_from_schedule(pcur
)->hw_next
;
5807 ListNext(list_head
, pthis
, pnext
);
5813 i
+= (interval
>> 3);
5819 ehci_isr_removing_urb(PEHCI_DEV ehci
, PURB purb
, BOOLEAN doorbell_rings
, ULONG cur_frame
)
5823 PURB_HS_PIPE_CONTENT pipe_content
;
5824 PEHCI_ITD_CONTENT pitd_content
;
5825 PEHCI_SITD_CONTENT psitd_content
;
5826 PEHCI_QH_CONTENT pqh_content
;
5827 PEHCI_QTD_CONTENT pqtd_content
;
5830 if (purb
== NULL
|| ehci
== NULL
)
5831 return STATUS_INVALID_PARAMETER
;
5833 if ((purb
->flags
& URB_FLAG_STATE_MASK
) == URB_FLAG_STATE_FINISHED
)
5834 return STATUS_SUCCESS
;
5837 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
5839 switch (purb
->flags
& URB_FLAG_STATE_MASK
)
5841 case URB_FLAG_STATE_IN_PROCESS
:
5843 // determine the removal type: complete, error or cancel
5844 ListFirst(&purb
->trasac_list
, pthis
);
5845 if (purb
->flags
& URB_FLAG_FORCE_CANCEL
)
5851 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
5852 pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
||
5853 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
)
5856 (PEHCI_QH_CONTENT
) ((ULONG
) struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->
5857 phys_part
& PHYS_PART_ADDR_MASK
);
5858 if (EHCI_QH_ERROR(pqh_content
))
5860 purb
->status
= pqh_content
->cur_qtd
.status
;
5865 pqtd_content
= &pqh_content
->cur_qtd
;
5866 if (pqtd_content
->terminal
&& ((pqtd_content
->status
& QTD_STS_ACTIVE
) == 0))
5870 // else, not finished
5873 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
5875 // FIXME: do we need to check if current frame falls out of the
5876 // frame range of iso transfer
5877 // inspect the last td to determine if finished
5878 ListFirstPrev(&purb
->trasac_list
, pthis
);
5881 if (pipe_content
->speed_high
)
5884 (PEHCI_ITD_CONTENT
) ((ULONG
) struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->
5885 phys_part
& PHYS_PART_ADDR_MASK
);
5886 for(i
= 0; i
< 8; i
++)
5888 if (pitd_content
->status_slot
[i
].trans_length
&&
5889 pitd_content
->status_slot
[i
].status
& 0x08)
5896 // the itds are all inactive
5903 (PEHCI_SITD_CONTENT
) ((ULONG
) struct_ptr(pthis
, EHCI_ELEM_LINKS
, elem_link
)->
5904 phys_part
& PHYS_PART_ADDR_MASK
);
5905 if ((psitd_content
->status
& 0x80) == 0)
5911 else // empty transaction list in purb
5914 else // unknown transfer type
5917 } // end of not force cancel
5920 return STATUS_SUCCESS
;
5926 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
||
5927 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
)
5929 ehci_remove_bulk_from_schedule(ehci
, purb
);
5930 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5931 purb
->flags
|= URB_FLAG_STATE_DOORBELL
;
5933 press_doorbell(ehci
);
5934 return STATUS_SUCCESS
;
5936 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_ISOC
)
5938 ehci_remove_iso_from_schedule(ehci
, purb
);
5940 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
5942 ehci_remove_int_from_schedule(ehci
, purb
);
5944 else // unknown transfer type
5947 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5948 purb
->flags
|= URB_FLAG_STATE_FINISHED
;
5950 // notify dpc the purb can be completed;
5951 purb
->flags
&= ~URB_FLAG_IN_SCHEDULE
;
5954 return STATUS_SUCCESS
;
5958 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
||
5959 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
)
5961 ehci_deactivate_urb(purb
);
5962 ehci_remove_bulk_from_schedule(ehci
, purb
);
5963 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5964 purb
->flags
|= URB_FLAG_STATE_DOORBELL
;
5965 press_doorbell(ehci
);
5967 else if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
5969 ehci_remove_int_from_schedule(ehci
, purb
);
5971 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5972 purb
->flags
|= URB_FLAG_STATE_FINISHED
;
5973 purb
->flags
&= ~URB_FLAG_IN_SCHEDULE
;
5975 else // unknown transfer or iso transfer
5977 return STATUS_SUCCESS
;
5981 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
||
5982 pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
5983 pipe_content
->trans_type
== USB_ENDPOINT_XFER_INT
)
5985 ehci_deactivate_urb(purb
);
5986 if (pipe_content
->trans_type
== USB_ENDPOINT_XFER_BULK
||
5987 pipe_content
->trans_type
== USB_ENDPOINT_XFER_CONTROL
)
5988 ehci_remove_bulk_from_schedule(ehci
, purb
);
5990 ehci_remove_int_from_schedule(ehci
, purb
);
5992 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
5993 purb
->flags
|= URB_FLAG_STATE_DOORBELL
;
5995 press_doorbell(ehci
);
5998 else // unknown transfer or iso transfer
6001 return STATUS_SUCCESS
;
6007 case URB_FLAG_STATE_DOORBELL
:
6009 if (doorbell_rings
== FALSE
)
6010 return STATUS_SUCCESS
;
6012 purb
->flags
&= ~URB_FLAG_STATE_MASK
;
6013 purb
->flags
|= URB_FLAG_STATE_FINISHED
;
6014 purb
->flags
&= ~URB_FLAG_IN_SCHEDULE
;
6015 return STATUS_SUCCESS
;
6018 return STATUS_SUCCESS
;
6022 ehci_scan_iso_error(PEHCI_DEV ehci
, PURB purb
)
6023 // we only report the first error of the ITDs, purb->status is the status code
6024 // return the raw status for ehci_set_error_code
6026 PURB_HS_PIPE_CONTENT pipe_content
;
6027 PEHCI_SITD_CONTENT psitd_content
;
6028 PEHCI_ITD_CONTENT pitd_content
;
6029 PLIST_ENTRY pthis
, pnext
;
6032 if (ehci
== NULL
|| purb
== NULL
)
6035 pipe_content
= (PURB_HS_PIPE_CONTENT
) & purb
->pipe
;
6036 if (pipe_content
->trans_type
!= USB_ENDPOINT_XFER_ISOC
)
6041 ListFirst(&purb
->trasac_list
, pthis
);
6042 if (pipe_content
->speed_high
)
6046 pitd_content
= (PEHCI_ITD_CONTENT
) itd_from_list_entry(pthis
);
6047 for(i
= 0; i
< 8; i
++)
6049 if (pitd_content
->status_slot
[i
].status
& ITD_ANY_ERROR
)
6055 return purb
->status
= pitd_content
->status_slot
[i
].status
;
6057 ListNext(&purb
->trasac_list
, pthis
, pnext
);
6065 psitd_content
= (PEHCI_SITD_CONTENT
) sitd_from_list_entry(pthis
);
6066 if (psitd_content
->status
& SITD_ANY_ERROR
)
6069 if (psitd_content
->s_mask
== 0x04 &&
6070 psitd_content
->c_mask
== 0x70 && psitd_content
->bytes_to_transfer
== 1)
6071 return purb
->status
= 0;
6073 return purb
->status
= psitd_content
->status
;
6075 ListNext(&purb
->trasac_list
, pthis
, pnext
);
6083 ehci_isr(PKINTERRUPT interrupt
, PVOID context
)
6084 // we can not use endp here for it is within the dev scope, and
6085 // we can not acquire the dev-lock, fortunately we saved some
6086 // info in purb->pipe in ehci_internal_submit_XXX.
6094 PLIST_ENTRY pthis
, pnext
;
6096 BOOLEAN door_bell_rings
;
6099 * Read the interrupt status, and write it back to clear the
6102 ehci
= (PEHCI_DEV
) context
;
6106 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_USBSTS
));
6107 cur_frame
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_FRINDEX
));
6109 status
&= (EHCI_ERROR_INT
| STS_INT
| STS_IAA
);
6110 if (!status
) /* shared interrupt, not mine */
6112 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): not our int\n"));
6117 EHCI_WRITE_PORT_ULONG((PULONG
) (ehci
->port_base
+ EHCI_USBSTS
), status
);
6119 if (status
& EHCI_ERROR_INT
)
6121 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): current ehci status=0x%x\n", status
));
6125 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): congratulations, no error occurs\n"));
6129 if (status
& STS_FATAL
)
6131 DbgPrint("ehci_isr(): host system error, PCI problems?\n");
6136 if (status
& STS_HALT
) //&& !ehci->is_suspended
6138 DbgPrint("ehci_isr(): host controller halted. very bad\n");
6139 /* FIXME: Reset the controller, fix the offending TD */
6140 // reset is performed in dpc
6144 door_bell_rings
= ((status
& STS_IAA
) != 0);
6146 // scan to remove those due
6148 urb_count
= dbg_count_list(&ehci
->urb_list
);
6149 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ehci_isr(): urb# in process is %d\n", urb_count
));
6152 ListFirst(&ehci
->urb_list
, pthis
);
6155 purb
= (PURB
) pthis
;
6156 ehci_isr_removing_urb(ehci
, purb
, door_bell_rings
, cur_frame
);
6157 ListNext(&ehci
->urb_list
, pthis
, pnext
);
6161 KeInsertQueueDpc(&ehci
->pdev_ext
->ehci_dpc
, (PVOID
) status
, 0);
6165 #ifndef INCLUDE_EHCI
6167 ehci_unload(IN PDRIVER_OBJECT DriverObject
)
6169 PDEVICE_OBJECT pdev
;
6170 PEHCI_DEVICE_EXTENSION pdev_ext
;
6171 PUSB_DEV_MANAGER dev_mgr
;
6174 pdev
= DriverObject
->DeviceObject
;
6179 pdev_ext
= pdev
->DeviceExtension
;
6180 if (pdev_ext
== NULL
)
6183 dev_mgr
= &g_dev_mgr
;
6184 if (dev_mgr
== NULL
)
6187 // set the termination flag
6189 dev_mgr
->term_flag
= TRUE
;
6191 // wake up the thread if it is
6193 KeSetEvent(&dev_mgr
->wake_up_event
, 0, FALSE
);
6194 KeWaitForSingleObject(dev_mgr
->pthread
, Executive
, KernelMode
, TRUE
, NULL
);
6195 ObDereferenceObject(dev_mgr
->pthread
);
6196 dev_mgr
->pthread
= NULL
;
6198 dev_mgr_release_hcd(dev_mgr
);
6203 generic_dispatch_irp(IN PDEVICE_OBJECT dev_obj
, IN PIRP irp
)
6205 PDEVEXT_HEADER dev_ext
;
6207 dev_ext
= (PDEVEXT_HEADER
) dev_obj
->DeviceExtension
;
6209 if (dev_ext
&& dev_ext
->dispatch
)
6210 return dev_ext
->dispatch(dev_obj
, irp
);
6212 irp
->IoStatus
.Information
= 0;
6214 EXIT_DISPATCH(STATUS_UNSUCCESSFUL
, irp
);
6218 generic_start_io(IN PDEVICE_OBJECT dev_obj
, IN PIRP irp
)
6220 PDEVEXT_HEADER dev_ext
;
6224 IoAcquireCancelSpinLock(&old_irql
);
6225 if (irp
!= dev_obj
->CurrentIrp
|| irp
->Cancel
)
6227 IoReleaseCancelSpinLock(old_irql
);
6232 IoSetCancelRoutine(irp
, NULL
);
6233 IoReleaseCancelSpinLock(old_irql
);
6236 dev_ext
= (PDEVEXT_HEADER
) dev_obj
->DeviceExtension
;
6238 if (dev_ext
&& dev_ext
->start_io
)
6240 dev_ext
->start_io(dev_obj
, irp
);
6244 irp
->IoStatus
.Information
= 0;
6245 irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
6247 IoStartNextPacket(dev_obj
, FALSE
);
6248 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
6253 DriverEntry(IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING RegistryPath
)
6255 NTSTATUS ntStatus
= STATUS_SUCCESS
;
6259 // should be done before any debug output is done.
6260 // read our debug verbosity level from the registry
6261 //NetacOD_GetRegistryDword( NetacOD_REGISTRY_PARAMETERS_PATH, //absolute registry path
6262 // L"DebugLevel", // REG_DWORD ValueName
6263 // &gDebugLevel ); // Value receiver
6265 // debug_level = DBGLVL_MAXIMUM;
6268 ehci_dbg_print_cond(DBGLVL_MINIMUM
, DEBUG_UHCI
,
6269 ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath
->Buffer
));
6271 // Remember our driver object, for when we create our child PDO
6272 usb_driver_obj
= DriverObject
;
6275 // Create dispatch points for create, close, unload
6276 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = generic_dispatch_irp
;
6277 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = generic_dispatch_irp
;
6278 DriverObject
->DriverUnload
= ehci_unload
;
6280 // User mode DeviceIoControl() calls will be routed here
6281 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = generic_dispatch_irp
;
6282 DriverObject
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = generic_dispatch_irp
;
6284 // User mode ReadFile()/WriteFile() calls will be routed here
6285 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = generic_dispatch_irp
;
6286 DriverObject
->MajorFunction
[IRP_MJ_READ
] = generic_dispatch_irp
;
6288 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = generic_dispatch_irp
;
6289 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = generic_dispatch_irp
;
6290 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = generic_dispatch_irp
;
6292 DriverObject
->DriverStartIo
= generic_start_io
;
6293 // routines for handling system PNP and power management requests
6294 //DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = generic_dispatch_irp;
6296 // The Functional Device Object (FDO) will not be created for PNP devices until
6297 // this routine is called upon device plug-in.
6298 RtlZeroMemory(&g_dev_mgr
, sizeof(USB_DEV_MANAGER
));
6299 g_dev_mgr
.usb_driver_obj
= DriverObject
;
6301 ehci_probe(DriverObject
, RegistryPath
, &g_dev_mgr
);
6303 if (dev_mgr_strobe(&g_dev_mgr
) == FALSE
)
6305 dev_mgr_release_hcd(&g_dev_mgr
);
6306 return STATUS_UNSUCCESSFUL
;
6309 dev_mgr_start_hcd(&g_dev_mgr
);
6310 ehci_dbg_print_cond(DBGLVL_DEFAULT
, DEBUG_UHCI
, ("DriverEntry(): exiting... (%x)\n", ntStatus
));
6311 return STATUS_SUCCESS
;
6315 //note: the initialization will be in the following order
6319 // to kill dev_mgr_thread:
6320 // dev_mgr->term_flag = TRUE;
6321 // KeSetEvent( &dev_mgr->wake_up_event );
6322 // this piece of code must run at passive-level