2 * ohci.c - USB driver stack project
4 * Copyright (c) 2007 Aleksey Bragin <aleksey@reactos.org>
5 * based on some code by Zhiming <mypublic99@yahoo.com>
7 * This program/include file is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program/include file is distributed in the hope that it will be
13 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program (in the main directory of the distribution, the file
19 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
20 * Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "usbdriver.h"
27 PDEVICE_OBJECT
ohci_alloc(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
,
28 ULONG bus_addr
, PUSB_DEV_MANAGER dev_mgr
);
29 //BOOLEAN ohci_release(PDEVICE_OBJECT pdev);
30 //static VOID ohci_stop(PEHCI_DEV ehci);
31 PDEVICE_OBJECT
ohci_probe(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
,
32 PUSB_DEV_MANAGER dev_mgr
);
33 PDEVICE_OBJECT
ohci_create_device(PDRIVER_OBJECT drvr_obj
, PUSB_DEV_MANAGER dev_mgr
);
34 //BOOLEAN ohci_delete_device(PDEVICE_OBJECT pdev);
35 //VOID ohci_get_capabilities(PEHCI_DEV ehci, PBYTE base);
36 //BOOLEAN NTAPI ohci_isr(PKINTERRUPT interrupt, PVOID context);
37 //BOOLEAN ohci_start(PHCD hcd);
38 VOID
ohci_init_hcd_interface(POHCI_DEV ohci
);
39 BOOLEAN
ohci_rh_reset_port(PHCD hcd
, UCHAR port_idx
);
40 VOID
ohci_generic_urb_completion(PURB purb
, PVOID context
);
43 NTSTATUS
ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject
, IN PIRP irp
);
44 PUSB_DEV_MANAGER
ehci_get_dev_mgr(PHCD hcd
);
45 VOID
ehci_set_dev_mgr(PHCD hcd
, PUSB_DEV_MANAGER dev_mgr
);
46 VOID
ehci_set_id(PHCD hcd
, UCHAR id
);
47 UCHAR
ehci_get_id(PHCD hcd
);
48 UCHAR
ehci_alloc_addr(PHCD hcd
);
49 VOID
ehci_free_addr(PHCD hcd
, UCHAR addr
);
50 BOOLEAN NTAPI
ehci_cal_cpu_freq(PVOID context
);
52 VOID
rh_timer_svc_int_completion(PUSB_DEV pdev
, PVOID context
);
53 VOID
rh_timer_svc_reset_port_completion(PUSB_DEV pdev
, PVOID context
);
55 extern USB_DEV_MANAGER g_dev_mgr
;
57 /* wrap-aware logic morphed from <linux/jiffies.h> */
58 #define tick_before(t1,t2) ((SHORT)(((SHORT)(t1))-((SHORT)(t2))) < 0)
60 #define OHCI_READ_PORT_ULONG( pul ) ( *pul )
61 #define OHCI_WRITE_PORT_ULONG( pul, src ) \
66 #define OHCI_READ_PORT_UCHAR( pch ) ( *pch )
67 #define OHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src )
68 #define OHCI_READ_PORT_USHORT( psh ) ( *psh )
69 #define OHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src )
71 /* AMD-756 (D2 rev) reports corrupt register contents in some cases.
72 * The erratum (#4) description is incorrect. AMD's workaround waits
73 * till some bits (mostly reserved) are clear; ok for all revs.
75 #define read_roothub(hc, register, mask) ({ \
76 ULONG temp = OHCI_READ_PORT_ULONG(&((hc)->regs->roothub.register)); \
79 /*else if (hc->flags & OHCI_QUIRK_AMD756) \
81 temp = ohci_readl (hc, &hc->regs->roothub.register); */ \
84 static ULONG
roothub_a (POHCI_DEV hc
)
85 { return read_roothub (hc
, a
, 0xfc0fe000); }
87 static inline u32 roothub_b (struct ohci_hcd *hc)
88 { return ohci_readl (hc, &hc->regs->roothub.b); }
89 static inline u32 roothub_status (struct ohci_hcd *hc)
90 { return ohci_readl (hc, &hc->regs->roothub.status); }
91 static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
92 { return read_roothub (hc, portstatus [i], 0xffe0fce0); }
96 /* For initializing controller (mask in an HCFS mode too) */
97 #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
98 #define OHCI_INTR_INIT \
99 (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
101 /* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling,
102 * not necessarily continuous ... to guard against resume signaling.
103 * The short timeout is safe for non-root hubs, and is backward-compatible
104 * with earlier Linux hosts.
106 #ifdef CONFIG_USB_SUSPEND
107 #define PORT_RESET_MSEC 50
109 #define PORT_RESET_MSEC 10
112 /* this timer value might be vendor-specific ... */
113 #define PORT_RESET_HW_MSEC 10
115 #define DEFAULT_ENDP( enDP ) \
116 ( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP )
118 #define dev_from_endp( enDP ) \
119 ( DEFAULT_ENDP( enDP )\
120 ? ( ( PUSB_DEV )( enDP )->pusb_if )\
121 : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) )
123 #define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK )
125 #define endp_num( enDP ) \
126 ( DEFAULT_ENDP( enDP )\
128 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) )
130 #define endp_dir( enDP ) \
131 ( DEFAULT_ENDP( enDP )\
133 : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) )
135 #define dev_set_state( pdEV, staTE ) \
136 ( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) )
138 #define endp_max_packet_size( enDP ) \
139 ( DEFAULT_ENDP( enDP )\
140 ? ( ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc ? \
141 ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc->bMaxPacketSize0\
143 : ( enDP->pusb_endp_desc->wMaxPacketSize & 0x7ff ) )
145 #define endp_mult_count( endp ) ( ( ( endp->pusb_endp_desc->wMaxPacketSize & 0x1800 ) >> 11 ) + 1 )
147 #define get_parent_hs_hub( pDEV, parent_HUB, port_IDX ) \
149 parent_HUB = pDEV->parent_dev;\
150 port_IDX = pdev->port_idx;\
153 if( ( parent_HUB->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_HUB )\
158 if( ( parent_HUB->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )\
160 port_IDX = parent_HUB->port_idx;\
161 parent_HUB = parent_HUB->parent_dev;\
169 ohci_wait_ms(POHCI_DEV ohci
, LONG ms
)
175 lms
.QuadPart
= -10 * ms
;
176 KeSetTimer(&ohci
->reset_timer
, lms
, NULL
);
178 KeWaitForSingleObject(&ohci
->reset_timer
, Executive
, KernelMode
, FALSE
, NULL
);
183 PDEVICE_OBJECT
ohci_probe(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
,
184 PUSB_DEV_MANAGER dev_mgr
)
186 LONG bus
, i
, j
, ret
= 0;
187 PCI_SLOT_NUMBER slot_num
;
188 PPCI_COMMON_CONFIG pci_config
;
190 BYTE buffer
[sizeof(PCI_COMMON_CONFIG
)];
191 POHCI_DEVICE_EXTENSION pdev_ext
;
193 slot_num
.u
.AsULONG
= 0;
194 pci_config
= (PPCI_COMMON_CONFIG
) buffer
;
197 //scan the bus to find ohci controller
198 for(bus
= 0; bus
< 2; bus
++) /*enum only bus0 and bus1 */
200 for(i
= 0; i
< PCI_MAX_DEVICES
; i
++)
202 slot_num
.u
.bits
.DeviceNumber
= i
;
203 for(j
= 0; j
< PCI_MAX_FUNCTIONS
; j
++)
205 slot_num
.u
.bits
.FunctionNumber
= j
;
207 ret
= HalGetBusData(PCIConfiguration
,
208 bus
, slot_num
.u
.AsULONG
, pci_config
, PCI_COMMON_HDR_LENGTH
);
210 /* Don't look further on this device */
211 if ((ret
== 0) || (ret
== 2))
214 if (pci_config
->BaseClass
== 0x0c && pci_config
->SubClass
== 0x03
215 && pci_config
->ProgIf
== 0x10)
217 // we found our usb host controller( OHCI ), create device
218 pdev
= ohci_alloc(drvr_obj
, reg_path
, ((bus
<< 8) | (i
<< 3) | j
), dev_mgr
);
232 pdev_ext
= pdev
->DeviceExtension
;
235 // acquire higher irql to eliminate pre-empty
236 //KeSynchronizeExecution(pdev_ext->ohci_int, ehci_cal_cpu_freq, NULL);
242 BOOLEAN
ohci_mem_init (POHCI_DEVICE_EXTENSION dev_ext
)
244 dev_ext
->ohci
->td_cache
= HalAllocateCommonBuffer(dev_ext
->padapter
,
245 sizeof(OHCI_TD
), &dev_ext
->ohci
->td_logic_addr
, FALSE
);
247 if (!dev_ext
->ohci
->td_cache
)
250 dev_ext
->ohci
->ed_cache
= HalAllocateCommonBuffer(dev_ext
->padapter
,
251 sizeof(OHCI_ED
), &dev_ext
->ohci
->ed_logic_addr
, FALSE
);
253 if (!dev_ext
->ohci
->ed_cache
)
255 HalFreeCommonBuffer(dev_ext
->padapter
, sizeof(OHCI_TD
), dev_ext
->ohci
->td_logic_addr
,
256 dev_ext
->ohci
->td_cache
, FALSE
);
265 ohci_alloc(PDRIVER_OBJECT drvr_obj
, PUNICODE_STRING reg_path
, ULONG bus_addr
, PUSB_DEV_MANAGER dev_mgr
)
267 LONG frd_num
, prd_num
;
268 PDEVICE_OBJECT pdev
= NULL
;
269 POHCI_DEVICE_EXTENSION pdev_ext
;
274 //KAFFINITY affinity;
276 DEVICE_DESCRIPTION dev_desc
;
277 CM_PARTIAL_RESOURCE_DESCRIPTOR
*pprd
;
278 PCI_SLOT_NUMBER slot_num
;
281 pdev
= ohci_create_device(drvr_obj
, dev_mgr
);
286 pdev_ext
= pdev
->DeviceExtension
;
288 pdev_ext
->pci_addr
= bus_addr
;
289 bus
= (bus_addr
>> 8);
291 slot_num
.u
.AsULONG
= 0;
292 slot_num
.u
.bits
.DeviceNumber
= ((bus_addr
& 0xff) >> 3);
293 slot_num
.u
.bits
.FunctionNumber
= (bus_addr
& 0x07);
295 //now create adapter object
296 RtlZeroMemory(&dev_desc
, sizeof(dev_desc
));
298 dev_desc
.Version
= DEVICE_DESCRIPTION_VERSION
;
299 dev_desc
.Master
= TRUE
;
300 dev_desc
.ScatterGather
= TRUE
;
301 dev_desc
.Dma32BitAddresses
= TRUE
;
302 dev_desc
.BusNumber
= bus
;
303 dev_desc
.InterfaceType
= PCIBus
;
304 dev_desc
.MaximumLength
= EHCI_MAX_SIZE_TRANSFER
;
305 pdev_ext
->map_regs
= 2; // we do not use it seriously
306 pdev_ext
->padapter
= HalGetAdapter(&dev_desc
, &pdev_ext
->map_regs
);
308 DbgPrint("ohci_alloc(): reg_path=0x%x, \n \
309 ohci_alloc(): bus=0x%x, bus_addr=0x%x \n \
310 ohci_alloc(): slot_num=0x%x \n \
311 ", (DWORD
) reg_path
, (DWORD
) bus
, (DWORD
) bus_addr
, (DWORD
) slot_num
.u
.AsULONG
);
313 //let's allocate resources for this device
314 DbgPrint("ohci_alloc(): about to assign slot res\n");
315 if ((status
= HalAssignSlotResources(reg_path
, NULL
, //no class name yet
316 drvr_obj
, NULL
, //no support of another ehci controller
318 bus
, slot_num
.u
.AsULONG
, &pdev_ext
->res_list
)) != STATUS_SUCCESS
)
320 DbgPrint("ohci_alloc(): error assign slot res, 0x%x\n", status
);
322 release_adapter(pdev_ext
->padapter
);
323 pdev_ext
->padapter
= NULL
;
324 ohci_delete_device(pdev
);
329 //parse the resource list
330 for(frd_num
= 0; frd_num
< (LONG
) pdev_ext
->res_list
->Count
; frd_num
++)
332 for(prd_num
= 0; prd_num
< (LONG
) pdev_ext
->res_list
->List
[frd_num
].PartialResourceList
.Count
;
335 pprd
= &pdev_ext
->res_list
->List
[frd_num
].PartialResourceList
.PartialDescriptors
[prd_num
];
336 if (pprd
->Type
== CmResourceTypePort
)
338 RtlCopyMemory(&pdev_ext
->res_port
, &pprd
->u
.Port
, sizeof(pprd
->u
.Port
));
341 else if (pprd
->Type
== CmResourceTypeInterrupt
)
343 RtlCopyMemory(&pdev_ext
->res_interrupt
, &pprd
->u
.Interrupt
, sizeof(pprd
->u
.Interrupt
));
345 else if (pprd
->Type
== CmResourceTypeMemory
)
347 RtlCopyMemory(&pdev_ext
->res_memory
, &pprd
->u
.Memory
, sizeof(pprd
->u
.Memory
));
352 //for port, translate them to system address
354 if (HalTranslateBusAddress(PCIBus
, bus
, pdev_ext
->res_port
.Start
, &addr_space
, //io space
355 &pdev_ext
->ohci
->ohci_reg_base
) != (BOOLEAN
) TRUE
)
357 DbgPrint("ohci_alloc(): error, can not translate bus address\n");
359 release_adapter(pdev_ext
->padapter
);
360 pdev_ext
->padapter
= NULL
;
361 ehci_delete_device(pdev
);
366 DbgPrint("ohci_alloc(): address space=0x%x\n, reg_base=0x%x\n",
367 addr_space
, pdev_ext
->ohci
->ohci_reg_base
.u
.LowPart
);
371 //port has been mapped to memory space
372 pdev_ext
->ohci
->port_mapped
= TRUE
;
373 pdev_ext
->ohci
->port_base
= (PBYTE
) MmMapIoSpace(pdev_ext
->ohci
->ohci_reg_base
,
374 pdev_ext
->res_port
.Length
, FALSE
);
376 //fatal error can not map the registers
377 if (pdev_ext
->ohci
->port_base
== NULL
)
380 release_adapter(pdev_ext
->padapter
);
381 pdev_ext
->padapter
= NULL
;
382 ehci_delete_device(pdev
);
390 pdev_ext
->ohci
->port_mapped
= FALSE
;
391 pdev_ext
->ohci
->port_base
= (PBYTE
) pdev_ext
->ohci
->ohci_reg_base
.LowPart
;
394 //before we connect the interrupt, we have to init ohci
395 pdev_ext
->ohci
->pdev_ext
= pdev_ext
;
396 pdev_ext
->ohci
->regs
= (POHCI_REGS
)pdev_ext
->ohci
->port_base
;
398 KeInitializeTimer(&pdev_ext
->ohci
->reset_timer
);
400 // take it over from SMM/BIOS/whoever has it
401 if (OHCI_READ_PORT_ULONG((PULONG
)(pdev_ext
->ohci
->port_base
+ OHCI_CONTROL
)) & OHCI_CTRL_IR
)
405 DbgPrint("USB HC TakeOver from BIOS/SMM\n");
407 /* this timeout is arbitrary. we make it long, so systems
408 * depending on usb keyboards may be usable even if the
409 * BIOS/SMM code seems pretty broken.
411 temp
= 500; /* arbitrary: five seconds */
413 OHCI_WRITE_PORT_ULONG((PULONG
)(pdev_ext
->ohci
->port_base
+ OHCI_INTRENABLE
), OHCI_INTR_OC
);
414 OHCI_WRITE_PORT_ULONG((PULONG
)(pdev_ext
->ohci
->port_base
+ OHCI_CMDSTATUS
), OHCI_OCR
);
416 while (OHCI_READ_PORT_ULONG((PULONG
)(pdev_ext
->ohci
->port_base
+ OHCI_CONTROL
)) & OHCI_CTRL_IR
)
418 ohci_wait_ms(pdev_ext
->ohci
, 10);
420 DbgPrint("USB HC takeover failed!"
421 " (BIOS/SMM bug)\n");
425 //ohci_usb_reset (ohci);
428 /* Disable HC interrupts */
429 OHCI_WRITE_PORT_ULONG((PULONG
)(pdev_ext
->ohci
->port_base
+ OHCI_INTRDISABLE
), OHCI_INTR_MIE
);
431 (VOID
)OHCI_READ_PORT_ULONG((PULONG
)(pdev_ext
->ohci
->port_base
+ OHCI_CONTROL
));
433 /* Read the number of ports unless overridden */
434 pdev_ext
->ohci
->num_ports
= roothub_a(pdev_ext
->ohci
) & RH_A_NDP
;
436 DbgPrint("OHCI: %d ports\n", pdev_ext
->ohci
->num_ports
);
438 pdev_ext
->ohci
->hcca
= HalAllocateCommonBuffer(pdev_ext
->padapter
,
439 sizeof(*pdev_ext
->ohci
->hcca
), &pdev_ext
->ohci
->hcca_logic_addr
, FALSE
);
441 if (!pdev_ext
->ohci
->hcca
)
443 DbgPrint("OHCI: HCCA allocation failed!\n");
447 if (!ohci_mem_init(pdev_ext
))
449 DbgPrint("OHCI: Mem init failed!\n");
454 if (ehci_init_schedule(pdev_ext
->ehci
, pdev_ext
->padapter
) == FALSE
)
456 release_adapter(pdev_ext
->padapter
);
457 pdev_ext
->padapter
= NULL
;
458 ehci_delete_device(pdev
);
463 InitializeListHead(&pdev_ext
->ohci
->urb_list
);
464 KeInitializeSpinLock(&pdev_ext
->ohci
->pending_endp_list_lock
);
465 InitializeListHead(&pdev_ext
->ohci
->pending_endp_list
);
467 ohci_dbg_print(DBGLVL_MAXIMUM
, ("ohci_alloc(): pending_endp_list=0x%x\n",
468 &pdev_ext
->ohci
->pending_endp_list
));
470 init_pending_endp_pool(&pdev_ext
->ohci
->pending_endp_pool
);
473 vector
= HalGetInterruptVector(PCIBus
,
475 pdev_ext
->res_interrupt
.level
,
476 pdev_ext
->res_interrupt
.vector
, &irql
, &affinity
);
478 //connect the interrupt
479 DbgPrint("ehci_alloc(): the int=0x%x\n", vector
);
480 if ((status
= IoConnectInterrupt(&pdev_ext
->ehci_int
, ehci_isr
, pdev_ext
->ehci
, NULL
, //&pdev_ext->ehci->frame_list_lock,
481 vector
, irql
, irql
, LevelSensitive
, TRUE
, //share the vector
482 affinity
, FALSE
)) //No float save
485 DbgPrint("ehci_alloc(): Failed to connect interrupt, status = 0x%x!\n", status
);
490 KeInitializeDpc(&pdev_ext
->ehci_dpc
, ehci_dpc_callback
, (PVOID
) pdev_ext
->ehci
);
497 ohci_create_device(PDRIVER_OBJECT drvr_obj
, PUSB_DEV_MANAGER dev_mgr
)
501 POHCI_DEVICE_EXTENSION pdev_ext
;
503 UNICODE_STRING dev_name
;
504 UNICODE_STRING symb_name
;
506 STRING string
, another_string
;
507 CHAR str_dev_name
[64], str_symb_name
[64];
510 if (drvr_obj
== NULL
)
513 //note: hcd count wont increment till the hcd is registered in dev_mgr
514 sprintf(str_dev_name
, "%s%d", OHCI_DEVICE_NAME
, dev_mgr
->hcd_count
);
515 sprintf(str_symb_name
, "%s%d", OHCI_DOS_DEVICE_NAME
, dev_mgr
->hcd_count
);
517 RtlInitString(&string
, str_dev_name
);
518 RtlAnsiStringToUnicodeString(&dev_name
, &string
, TRUE
);
521 status
= IoCreateDevice(drvr_obj
,
522 sizeof(OHCI_DEVICE_EXTENSION
) + sizeof(OHCI_DEV
),
523 &dev_name
, FILE_OHCI_DEV_TYPE
, 0, FALSE
, &pdev
);
525 if (status
!= STATUS_SUCCESS
|| pdev
== NULL
)
527 RtlFreeUnicodeString(&dev_name
);
528 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ohci_create_device(): error create device 0x%x\n", status
));
532 pdev_ext
= pdev
->DeviceExtension
;
533 RtlZeroMemory(pdev_ext
, sizeof(OHCI_DEVICE_EXTENSION
) + sizeof(OHCI_DEV
));
535 pdev_ext
->dev_ext_hdr
.type
= NTDEV_TYPE_HCD
;
536 pdev_ext
->dev_ext_hdr
.dispatch
= ehci_dispatch_irp
;
537 pdev_ext
->dev_ext_hdr
.start_io
= NULL
; //we do not support startio
538 pdev_ext
->dev_ext_hdr
.dev_mgr
= dev_mgr
;
540 pdev_ext
->pdev_obj
= pdev
;
541 pdev_ext
->pdrvr_obj
= drvr_obj
;
543 pdev_ext
->ohci
= (POHCI_DEV
) & (pdev_ext
[1]);
545 RtlInitString(&another_string
, str_symb_name
);
546 RtlAnsiStringToUnicodeString(&symb_name
, &another_string
, TRUE
);
547 //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME );
549 IoCreateSymbolicLink(&symb_name
, &dev_name
);
551 ehci_dbg_print(DBGLVL_MAXIMUM
,
552 ("ohci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", pdev
,
553 pdev_ext
, pdev_ext
->ohci
, dev_mgr
));
555 RtlFreeUnicodeString(&dev_name
);
556 RtlFreeUnicodeString(&symb_name
);
558 //register with dev_mgr though it is not initilized
559 ohci_init_hcd_interface(pdev_ext
->ohci
);
560 hcd_id
= dev_mgr_register_hcd(dev_mgr
, &pdev_ext
->ohci
->hcd_interf
);
562 pdev_ext
->ohci
->hcd_interf
.hcd_set_id(&pdev_ext
->ohci
->hcd_interf
, hcd_id
);
563 pdev_ext
->ohci
->hcd_interf
.hcd_set_dev_mgr(&pdev_ext
->ohci
->hcd_interf
, dev_mgr
);
573 //PEHCI_USBCMD_CONTENT usbcmd;
580 ohci
= struct_ptr(hcd
, OHCI_DEV
, hcd_interf
);
582 /* Reset USB nearly "by the book". RemoteWakeupConnected
583 * saved if boot firmware (BIOS/SMM/...) told us it's connected
584 * (for OHCI integrated on mainboard, it normally is)
586 hc_control
= OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->control
);
587 DbgPrint("OHCI: resetting from state %x, control = 0x%x\n",
588 (hc_control
& OHCI_CTRL_HCFS
),
591 //if (hc_control & OHCI_CTRL_RWC
592 // && !(ohci->flags & OHCI_QUIRK_AMD756))
593 // ohci_to_hcd(ohci)->can_wakeup = 1;
595 switch (hc_control
& OHCI_CTRL_HCFS
) {
599 case OHCI_USB_SUSPEND
:
600 case OHCI_USB_RESUME
:
601 hc_control
&= OHCI_CTRL_RWC
;
602 hc_control
|= OHCI_USB_RESUME
;
603 temp
= 10 /* msec wait */;
605 // case OHCI_USB_RESET:
607 hc_control
&= OHCI_CTRL_RWC
;
608 hc_control
|= OHCI_USB_RESET
;
609 temp
= 50 /* msec wait */;
612 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->control
, hc_control
);
615 (VOID
)OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->control
);
617 ohci_wait_ms(ohci
, temp
);
618 temp
= roothub_a (ohci
);
619 if (!(temp
& RH_A_NPS
)) {
620 /* power down each port */
621 for (temp
= 0; temp
< ohci
->num_ports
; temp
++)
623 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[temp
], RH_PS_LSDA
);
626 // flush those writes
627 (VOID
)OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->control
);
628 RtlZeroMemory(ohci
->hcca
, sizeof(OHCI_HCCA
));
630 /* 2msec timelimit here means no irqs/preempt */
631 //spin_lock_irq (&ohci->lock);
634 /* HC Reset requires max 10 us delay */
635 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->cmdstatus
, OHCI_HCR
);
636 temp
= 30; /* ... allow extra time */
637 while ((OHCI_READ_PORT_ULONG ((PULONG
)&ohci
->regs
->cmdstatus
) & OHCI_HCR
) != 0) {
639 //spin_unlock_irq (&ohci->lock);
640 //ohci_err (ohci, "USB HC reset timed out!\n");
641 DbgPrint("OHCI: USB HC reset timed out!\n");
644 KeStallExecutionProcessor(1);
647 /* now we're in the SUSPEND state ... must go OPERATIONAL
648 * within 2msec else HC enters RESUME
650 * ... but some hardware won't init fmInterval "by the book"
651 * (SiS, OPTi ...), so reset again instead. SiS doesn't need
652 * this if we write fmInterval after we're OPERATIONAL.
653 * Unclear about ALi, ServerWorks, and others ... this could
654 * easily be a longstanding bug in chip init on Linux.
657 if (ohci
->flags
& OHCI_QUIRK_INITRESET
) {
658 ohci_writel (ohci
, ohci
->hc_control
, &ohci
->regs
->control
);
659 // flush those writes
660 (void) ohci_readl (ohci
, &ohci
->regs
->control
);
663 /* Tell the controller where the control and bulk lists are
664 * The lists are empty now. */
665 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->ed_controlhead
, 0);
666 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->ed_bulkhead
, 0);
668 /* a reset clears this */
669 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->hcca
, (ULONG
)ohci
->hcca_logic_addr
.LowPart
);
671 //periodic_reinit (ohci);
673 /* start controller operations */
674 hc_control
&= OHCI_CTRL_RWC
;
675 hc_control
|= OHCI_CONTROL_INIT
| OHCI_USB_OPER
;
676 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->control
, hc_control
);
677 //ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
679 /* wake on ConnectStatusChange, matching external hubs */
680 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.status
, RH_HS_DRWE
);
682 /* Choose the interrupts we care about now, others later on demand */
683 mask
= OHCI_INTR_INIT
;
684 //OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->intrstatus, mask);
685 //OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->intrenable, mask);
687 /* handle root hub init quirks ... */
688 temp
= roothub_a(ohci
);
689 temp
&= ~(RH_A_PSM
| RH_A_OCPM
);
690 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.status
, RH_HS_LPSC
);
691 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.b
, (temp
& RH_A_NPS
) ? 0 : RH_B_PPCM
);
692 // flush those writes
693 (VOID
)OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->control
);
695 //spin_unlock_irq (&ohci->lock);
697 // POTPGT delay is bits 24-31, in 2 ms units.
698 ohci_wait_ms(ohci
, (temp
>> 23) & 0x1fe);
699 //ohci_to_hcd(ohci)->state = HC_STATE_RUNNING;
702 // Debug code follows!
703 /*(VOID)ohci_rh_reset_port(hcd, 1);
704 (VOID)ohci_rh_reset_port(hcd, 2);
705 (VOID)ohci_rh_reset_port(hcd, 3);
706 (VOID)ohci_rh_reset_port(hcd, 4);*/
714 ohci_cancel_pending_endp_urb(IN PVOID Parameter
)
716 PLIST_ENTRY abort_list
;
719 USE_BASIC_NON_PENDING_IRQL
;
721 abort_list
= (PLIST_ENTRY
) Parameter
;
723 if (abort_list
== NULL
)
726 while (IsListEmpty(abort_list
) == FALSE
)
728 //these devs are protected by purb's ref-count
729 purb
= (PURB
) RemoveHeadList(abort_list
);
731 // purb->status is set when they are added to abort_list
733 ohci_generic_urb_completion(purb
, purb
->context
);
735 lock_dev(pdev
, FALSE
);
737 unlock_dev(pdev
, FALSE
);
739 usb_free_mem(abort_list
);
744 ohci_internal_submit_bulk(POHCI_DEV ohci
, PURB purb
)
746 return STATUS_SUCCESS
;
750 ohci_internal_submit_ctrl(POHCI_DEV ohci
, PURB purb
)
752 return STATUS_SUCCESS
;
756 ohci_internal_submit_int(POHCI_DEV ohci
, PURB purb
)
758 return STATUS_SUCCESS
;
762 ohci_internal_submit_iso(POHCI_DEV ohci
, PURB purb
)
764 return STATUS_SUCCESS
;
769 ohci_process_pending_endp(POHCI_DEV ehci
)
772 LIST_ENTRY temp_list
, abort_list
;
776 NTSTATUS can_submit
= STATUS_SUCCESS
;
777 PWORK_QUEUE_ITEM pwork_item
;
778 PLIST_ENTRY cancel_list
;
779 PUSB_DEV pparent
= NULL
;
788 InitializeListHead(&temp_list
);
789 InitializeListHead(&abort_list
);
792 ohci_dbg_print(DBGLVL_MEDIUM
, ("ohci_process_pending_endp(): entering..., ehci=0x%x\n", ehci
));
794 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
795 while (IsListEmpty(&ehci
->pending_endp_list
) == FALSE
)
798 ehci_dbg_print(DBGLVL_MAXIMUM
, ("ohci_process_pending_endp(): pending_endp_list=0x%x\n",
799 &ehci
->pending_endp_list
));
802 pthis
= RemoveHeadList(&ehci
->pending_endp_list
);
803 pendp
= ((PUHCI_PENDING_ENDP
) pthis
)->pendp
;
804 pdev
= dev_from_endp(pendp
);
805 lock_dev(pdev
, TRUE
);
807 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
809 unlock_dev(pdev
, TRUE
);
810 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
811 //delegate to ehci_remove_device for remiving the purb queue on the endpoint
814 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
816 // prepare split transaction
817 unlock_dev(pdev
, TRUE
);
819 // pparent won't be removed when pending_endp_list_lock is acquired.
820 get_parent_hs_hub(pdev
, pparent
, port_idx
);
825 ehci_dbg_print(DBGLVL_MEDIUM
,
826 ("ohci_process_pending_endp(): full/low speed device with no parent!!!\n"));
827 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
831 if (hub_lock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
)) == FALSE
)
833 lock_dev(pdev
, TRUE
);
834 if (dev_state(pdev
) != USB_DEV_STATE_ZOMB
)
836 // reinsert the pending-endp to the list
837 InsertTailList(&temp_list
, pthis
);
838 unlock_dev(pdev
, TRUE
);
842 // delegate to ehci_remove_device for purb removal
843 unlock_dev(pdev
, TRUE
);
844 free_pending_endp(&ehci
->pending_endp_pool
,
845 struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
850 // backup the hub address for future use
851 hub_addr
= pparent
->dev_addr
;
853 lock_dev(pdev
, TRUE
);
854 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
856 unlock_dev(pdev
, TRUE
);
857 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
858 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
865 if (endp_state(pendp
) == USB_ENDP_FLAG_STALL
)
867 while (IsListEmpty(&pendp
->urb_list
) == FALSE
)
869 purb
= (PURB
) RemoveHeadList(&pendp
->urb_list
);
870 purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
871 InsertTailList(&abort_list
, (LIST_ENTRY
*) purb
);
873 InitializeListHead(&pendp
->urb_list
);
874 unlock_dev(pdev
, TRUE
);
875 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
877 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
881 if (IsListEmpty(&pendp
->urb_list
) == FALSE
)
883 purb
= (PURB
) RemoveHeadList(&pendp
->urb_list
);
888 InitializeListHead(&pendp
->urb_list
);
889 unlock_dev(pdev
, TRUE
);
890 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
892 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
898 ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->hub_addr
= hub_addr
;
899 ((PURB_HS_CONTEXT_CONTENT
) & purb
->hs_context
)->port_idx
= port_idx
;
902 // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule
903 switch (endp_type(pendp
))
905 case USB_ENDPOINT_XFER_BULK
:
907 can_submit
= ohci_internal_submit_bulk(ehci
, purb
);
910 case USB_ENDPOINT_XFER_CONTROL
:
912 can_submit
= ohci_internal_submit_ctrl(ehci
, purb
);
915 case USB_ENDPOINT_XFER_INT
:
917 can_submit
= ohci_internal_submit_int(ehci
, purb
);
920 case USB_ENDPOINT_XFER_ISOC
:
922 can_submit
= ohci_internal_submit_iso(ehci
, purb
);
927 if (can_submit
== STATUS_NO_MORE_ENTRIES
)
929 //no enough bandwidth or tds
930 InsertHeadList(&pendp
->urb_list
, (PLIST_ENTRY
) purb
);
931 InsertTailList(&temp_list
, pthis
);
935 // otherwise error or success
936 free_pending_endp(&ehci
->pending_endp_pool
, struct_ptr(pthis
, UHCI_PENDING_ENDP
, endp_link
));
938 if (can_submit
!= STATUS_SUCCESS
)
941 InsertTailList(&abort_list
, (LIST_ENTRY
*) purb
);
942 purb
->status
= can_submit
;
945 unlock_dev(pdev
, TRUE
);
946 if (can_submit
!= STATUS_SUCCESS
&& tt_needed
)
948 hub_unlock_tt(pparent
, port_idx
, (UCHAR
) endp_type(pendp
));
952 if (IsListEmpty(&temp_list
) == FALSE
)
954 //re-append them to the pending_endp_list
955 ListFirst(&temp_list
, pthis
);
956 RemoveEntryList(&temp_list
);
957 MergeList(&ehci
->pending_endp_list
, pthis
);
959 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
961 if (IsListEmpty(&abort_list
) == FALSE
)
964 cancel_list
= (PLIST_ENTRY
) usb_alloc_mem(NonPagedPool
, sizeof(WORK_QUEUE_ITEM
) + sizeof(LIST_ENTRY
));
967 ListFirst(&abort_list
, pthis
);
968 RemoveEntryList(&abort_list
);
969 InsertTailList(pthis
, cancel_list
);
971 pwork_item
= (PWORK_QUEUE_ITEM
) & cancel_list
[1];
973 // we do not need to worry the ehci_cancel_pending_endp_urb running when the
974 // driver is unloading since purb-reference count will prevent the dev_mgr to
975 // quit till all the reference count to the dev drop to zero.
976 ExInitializeWorkItem(pwork_item
, ohci_cancel_pending_endp_urb
, (PVOID
) cancel_list
);
977 ExQueueWorkItem(pwork_item
, DelayedWorkQueue
);
983 ohci_rh_submit_urb(PUSB_DEV pdev
, PURB purb
)
985 PUSB_DEV_MANAGER dev_mgr
;
987 PUSB_CTRL_SETUP_PACKET psetup
;
990 PHUB2_EXTENSION hub_ext
;
991 PUSB_PORT_STATUS ps
, psret
;
995 USE_NON_PENDING_IRQL
;
996 if (pdev
== NULL
|| purb
== NULL
)
997 return STATUS_INVALID_PARAMETER
;
999 dev_mgr
= dev_mgr_from_dev(pdev
);
1001 KeAcquireSpinLock(&dev_mgr
->timer_svc_list_lock
, &old_irql
);
1002 lock_dev(pdev
, FALSE
);
1003 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1005 unlock_dev(pdev
, FALSE
);
1006 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1007 return STATUS_DEVICE_DOES_NOT_EXIST
;
1010 ohci
= ohci_from_hcd(pdev
->hcd
);
1011 psetup
= (PUSB_CTRL_SETUP_PACKET
) purb
->setup_packet
;
1013 hub_ext
= ((PHUB2_EXTENSION
) pdev
->dev_ext
);
1014 port_count
= ohci
->num_ports
;
1016 switch (endp_type(purb
->pendp
))
1018 case USB_ENDPOINT_XFER_CONTROL
:
1020 if (psetup
->bmRequestType
== 0xa3 && psetup
->bRequest
== USB_REQ_GET_STATUS
)
1023 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
|| psetup
->wLength
< 4)
1025 purb
->status
= STATUS_INVALID_PARAMETER
;
1029 ps
= &hub_ext
->rh_port_status
[psetup
->wIndex
];
1030 psret
= (PUSB_PORT_STATUS
) purb
->data_buffer
;
1033 OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[psetup
->wIndex
-1]);
1035 ps
->wPortStatus
= 0;
1037 if (status
& RH_PS_CCS
)
1039 ps
->wPortStatus
|= USB_PORT_STAT_CONNECTION
;
1041 if (status
& RH_PS_PES
)
1043 ps
->wPortStatus
|= USB_PORT_STAT_ENABLE
;
1044 //ps->wPortStatus |= USB_PORT_STAT_HIGH_SPEED; // ehci spec
1046 if (status
& RH_PS_PRS
)
1048 ps
->wPortStatus
|= USB_PORT_STAT_RESET
;
1050 if (status
& RH_PS_PSS
)
1052 ps
->wPortStatus
|= USB_PORT_STAT_SUSPEND
;
1054 if (status
& RH_PS_LSDA
)
1056 ps
->wPortStatus
|= USB_PORT_STAT_LOW_SPEED
;
1060 ps
->wPortStatus
|= USB_PORT_STAT_POWER
;
1062 //now set change field
1063 if ((status
& RH_PS_CSC
) && !(ps
->wPortStatus
& USB_PORT_STAT_LOW_SPEED
))
1065 ps
->wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
1067 if ((status
& RH_PS_PESC
) && !(ps
->wPortStatus
& USB_PORT_STAT_LOW_SPEED
))
1069 ps
->wPortChange
|= USB_PORT_STAT_C_ENABLE
;
1072 //don't touch other fields, might be filled by
1075 usb_dbg_print(DBGLVL_MAXIMUM
,
1076 ("ohci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n",
1077 ps
->wPortStatus
, ps
->wPortChange
, ps
));
1079 psret
->wPortChange
= ps
->wPortChange
;
1080 psret
->wPortStatus
= ps
->wPortStatus
;
1082 purb
->status
= STATUS_SUCCESS
;
1086 else if (psetup
->bmRequestType
== 0x23 && psetup
->bRequest
== USB_REQ_CLEAR_FEATURE
)
1088 //clear-port-feature
1089 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
)
1091 purb
->status
= STATUS_INVALID_PARAMETER
;
1095 i
= psetup
->wIndex
- 1;
1096 ps
= &hub_ext
->rh_port_status
[psetup
->wIndex
];
1098 purb
->status
= STATUS_SUCCESS
;
1099 switch (psetup
->wValue
)
1101 case USB_PORT_FEAT_C_CONNECTION
:
1103 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[i
], RH_PS_CSC
);
1104 status
= OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[i
]);
1105 usb_dbg_print(DBGLVL_MAXIMUM
,
1106 ("ohci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup
->wIndex
, status
));
1107 ps
->wPortChange
&= ~USB_PORT_STAT_C_CONNECTION
;
1110 case USB_PORT_FEAT_C_ENABLE
:
1112 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[i
], RH_PS_PESC
);
1113 status
= OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[i
]);
1114 usb_dbg_print(DBGLVL_MAXIMUM
,
1115 ("ohci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup
->wIndex
, status
));
1116 ps
->wPortChange
&= ~USB_PORT_STAT_C_ENABLE
;
1119 case USB_PORT_FEAT_C_RESET
:
1121 ps
->wPortChange
&= ~USB_PORT_STAT_C_RESET
;
1122 //the reset signal is down in rh_timer_svc_reset_port_completion
1123 // enable or not is set by host controller
1124 // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) );
1125 usb_dbg_print(DBGLVL_MAXIMUM
,
1126 ("ohci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n",
1127 psetup
->wIndex
, 0));
1130 case USB_PORT_FEAT_ENABLE
:
1132 ps
->wPortStatus
&= ~USB_PORT_STAT_ENABLE
;
1133 OHCI_WRITE_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[i
], RH_PS_PES
);
1134 status
= OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[i
]);
1135 usb_dbg_print(DBGLVL_MAXIMUM
,
1136 ("ohci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup
->wIndex
, status
));
1140 purb
->status
= STATUS_UNSUCCESSFUL
;
1145 else if (psetup
->bmRequestType
== 0xd3 && psetup
->bRequest
== HUB_REQ_GET_STATE
)
1148 if (psetup
->wIndex
== 0 || psetup
->wIndex
> port_count
|| psetup
->wLength
== 0)
1150 purb
->status
= STATUS_INVALID_PARAMETER
;
1154 i
= EHCI_PORTSC
+ 4 * (psetup
->wIndex
- 1); // USBPORTSC1;
1155 status
= EHCI_READ_PORT_ULONG((PULONG
) (ehci
->port_base
+ i
));
1156 purb
->data_buffer
[0] = (status
& USBPORTSC_LS
);
1158 // reverse the order
1159 purb
->data_buffer
[0] ^= 0x3;
1161 purb
->status
= STATUS_SUCCESS
;
1164 else if (psetup
->bmRequestType
== 0x23 && psetup
->bRequest
== USB_REQ_SET_FEATURE
)
1167 if (psetup
->wValue
!= USB_PORT_FEAT_RESET
)
1169 purb
->status
= STATUS_INVALID_PARAMETER
;
1170 ehci_dbg_print(DBGLVL_MAXIMUM
,
1171 ("ohci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup
->wValue
));
1175 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
1176 ptimer
->threshold
= 0; // within [ 50ms, 60ms ], one tick is 10 ms
1177 ptimer
->context
= (ULONG
) purb
;
1178 ptimer
->pdev
= pdev
;
1179 ptimer
->func
= rh_timer_svc_reset_port_completion
;
1182 pdev
->ref_count
+= 2; //one for timer and one for purb
1185 OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->roothub
.portstatus
[psetup
->wIndex
-1]);
1187 usb_dbg_print(DBGLVL_MAXIMUM
,
1188 ("ohci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup
->wIndex
, status
));
1189 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
1190 purb
->status
= STATUS_PENDING
;
1194 purb
->status
= STATUS_INVALID_PARAMETER
;
1198 case USB_ENDPOINT_XFER_INT
:
1200 ptimer
= alloc_timer_svc(&dev_mgr
->timer_svc_pool
, 1);
1201 ptimer
->threshold
= RH_INTERVAL
;
1202 ptimer
->context
= (ULONG
) purb
;
1203 ptimer
->pdev
= pdev
;
1204 ptimer
->func
= rh_timer_svc_int_completion
;
1207 InsertTailList(&dev_mgr
->timer_svc_list
, &ptimer
->timer_svc_link
);
1209 //usb_dbg_print(DBGLVL_MAXIMUM,
1210 // ("ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count));
1211 pdev
->ref_count
+= 2; //one for timer and one for purb
1213 purb
->status
= STATUS_PENDING
;
1216 case USB_ENDPOINT_XFER_BULK
:
1217 case USB_ENDPOINT_XFER_ISOC
:
1220 purb
->status
= STATUS_INVALID_PARAMETER
;
1224 unlock_dev(pdev
, FALSE
);
1225 KeReleaseSpinLock(&dev_mgr
->timer_svc_list_lock
, old_irql
);
1226 return purb
->status
;
1230 ohci_submit_urb(POHCI_DEV ehci
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
1233 PUHCI_PENDING_ENDP pending_endp
;
1238 return STATUS_INVALID_PARAMETER
;
1240 if (pdev
== NULL
|| pendp
== NULL
|| purb
== NULL
)
1242 // give a chance to those pending urb, especially for clearing hub tt
1243 ohci_process_pending_endp(ehci
);
1244 return STATUS_INVALID_PARAMETER
;
1247 lock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1248 lock_dev(pdev
, TRUE
);
1250 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1252 status
= purb
->status
= STATUS_DEVICE_DOES_NOT_EXIST
;
1256 if (dev_class(pdev
) == USB_DEV_CLASS_ROOT_HUB
)
1258 unlock_dev(pdev
, TRUE
);
1259 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1260 status
= ohci_rh_submit_urb(pdev
, purb
);
1265 purb
->pendp
= pendp
;
1267 purb
->pendp
= &pdev
->default_endp
;
1269 if (dev_from_endp(purb
->pendp
) != pdev
)
1271 status
= purb
->status
= STATUS_INVALID_PARAMETER
;
1275 if (endp_state(purb
->pendp
) == USB_ENDP_FLAG_STALL
)
1277 status
= purb
->status
= USB_STATUS_ENDPOINT_HALTED
;
1281 if ((pdev
->flags
& USB_DEV_FLAG_HIGH_SPEED
) == 0)
1288 purb
->rest_bytes
= purb
->data_length
;
1290 if (endp_type(purb
->pendp
) == USB_ENDPOINT_XFER_BULK
)
1291 purb
->bytes_to_transfer
= (purb
->data_length
> EHCI_MAX_SIZE_TRANSFER
? EHCI_MAX_SIZE_TRANSFER
: purb
->data_length
); //multiple transfer for large data block
1293 purb
->bytes_to_transfer
= purb
->data_length
;
1295 ehci_dbg_print(DBGLVL_MEDIUM
, ("ohci_submit_urb(): bytes_to_transfer=0x%x\n", purb
->bytes_to_transfer
));
1297 purb
->bytes_transfered
= 0;
1298 InitializeListHead(&purb
->trasac_list
);
1299 purb
->last_finished_td
= &purb
->trasac_list
;
1300 purb
->flags
&= ~(URB_FLAG_STATE_MASK
| URB_FLAG_IN_SCHEDULE
| URB_FLAG_FORCE_CANCEL
);
1301 purb
->flags
|= URB_FLAG_STATE_PENDING
;
1304 i
= IsListEmpty(&pendp
->urb_list
);
1305 InsertTailList(&pendp
->urb_list
, &purb
->urb_link
);
1307 pdev
->ref_count
++; //for purb reference
1311 //there is purb pending, simply queue it and return
1312 status
= purb
->status
= STATUS_PENDING
;
1315 else if (usb_endp_busy_count(purb
->pendp
) && endp_type(purb
->pendp
) != USB_ENDPOINT_XFER_ISOC
)
1318 //No purb waiting but purb overlap not allowed,
1319 //so leave it in queue and return, will be scheduled
1322 status
= purb
->status
= STATUS_PENDING
;
1326 pending_endp
= alloc_pending_endp(&ehci
->pending_endp_pool
, 1);
1327 if (pending_endp
== NULL
)
1330 status
= purb
->status
= STATUS_UNSUCCESSFUL
;
1334 pending_endp
->pendp
= purb
->pendp
;
1335 InsertTailList(&ehci
->pending_endp_list
, (PLIST_ENTRY
) pending_endp
);
1337 unlock_dev(pdev
, TRUE
);
1338 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1340 ohci_process_pending_endp(ehci
);
1341 return STATUS_PENDING
;
1345 RemoveEntryList((PLIST_ENTRY
) purb
);
1348 unlock_dev(pdev
, TRUE
);
1349 unlock_pending_endp_list(&ehci
->pending_endp_list_lock
);
1350 ohci_process_pending_endp(ehci
);
1355 ohci_get_type(PHCD hcd
)
1357 return HCD_TYPE_OHCI
; // ( hcd->flags & HCD_TYPE_MASK );
1361 ohci_submit_urb2(PHCD hcd
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
1363 return ohci_submit_urb(ohci_from_hcd(hcd
), pdev
, pendp
, purb
);
1367 ohci_get_root_hub(PHCD hcd
)
1369 return ohci_from_hcd(hcd
)->root_hub
;
1373 ohci_set_root_hub(PHCD hcd
, PUSB_DEV root_hub
)
1375 if (hcd
== NULL
|| root_hub
== NULL
)
1377 ohci_from_hcd(hcd
)->root_hub
= root_hub
;
1382 ohci_remove_device2(PHCD hcd
, PUSB_DEV pdev
)
1384 if (hcd
== NULL
|| pdev
== NULL
)
1388 //return ehci_remove_device(ehci_from_hcd(hcd), pdev);
1392 ohci_hcd_release(PHCD hcd
)
1395 POHCI_DEVICE_EXTENSION pdev_ext
;
1400 ohci
= ohci_from_hcd(hcd
);
1401 pdev_ext
= ohci
->pdev_ext
;
1402 return FALSE
;//ehci_release(pdev_ext->pdev_obj);
1406 ohci_cancel_urb2(PHCD hcd
, PUSB_DEV pdev
, PUSB_ENDPOINT pendp
, PURB purb
)
1410 return STATUS_INVALID_PARAMETER
;
1412 ohci
= ohci_from_hcd(hcd
);
1413 DbgPrint("ohci_cancel_urb2 called, but not implemented!\n");
1414 return STATUS_UNSUCCESSFUL
;//ehci_cancel_urb(ehci, pdev, pendp, purb);
1418 ohci_generic_urb_completion(PURB purb
, PVOID context
)
1421 BOOLEAN is_ctrl
= FALSE
;
1422 USE_NON_PENDING_IRQL
;
1424 old_irql
= KeGetCurrentIrql();
1425 if (old_irql
> DISPATCH_LEVEL
)
1428 if (old_irql
< DISPATCH_LEVEL
)
1429 KeRaiseIrql(DISPATCH_LEVEL
, &old_irql
);
1433 goto LBL_LOWER_IRQL
;
1436 goto LBL_LOWER_IRQL
;
1438 lock_dev(pdev
, TRUE
);
1440 if (dev_state(pdev
) == USB_DEV_STATE_ZOMB
)
1442 // no need to do following statistics
1443 unlock_dev(pdev
, TRUE
);
1444 goto LBL_CLIENT_PROCESS
;
1446 if (usb_error(purb
->status
))
1448 pdev
->error_count
++;
1451 if (purb
->pendp
== &pdev
->default_endp
)
1453 if (usb_halted(purb
->status
))
1455 pdev
->time_out_count
++;
1456 if (pdev
->time_out_count
> 3)
1458 dev_set_state(pdev
, USB_DEV_STATE_ZOMB
);
1459 ohci_dbg_print(DBGLVL_MAXIMUM
,
1460 ("ohci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n",
1465 pdev
->time_out_count
= 0;
1469 if (endp_type(purb
->pendp
) == USB_ENDPOINT_XFER_CONTROL
)
1472 unlock_dev(pdev
, TRUE
);
1477 if (purb
->completion
)
1478 purb
->completion(purb
, context
);
1482 if (purb
->ctrl_req_context
.ctrl_stack_count
== 0)
1484 if (purb
->completion
)
1485 purb
->completion(purb
, context
);
1489 // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ];
1490 // if( pstack->urb_completion )
1491 // pstack->urb_completion( purb, pstack->context );
1492 usb_call_ctrl_completion(purb
);
1497 if (old_irql
< DISPATCH_LEVEL
)
1498 KeLowerIrql(old_irql
);
1504 ohci_rh_reset_port(PHCD hcd
, UCHAR port_idx
)
1509 USHORT Now
, ResetDone
;
1514 ohci
= ohci_from_hcd(hcd
);
1516 if (port_idx
< 1 || port_idx
> ohci
->num_ports
)
1521 PortStatus
= &ohci
->regs
->roothub
.portstatus
[port_idx
];
1523 Now
= OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->fmnumber
);
1524 ResetDone
= Now
+ PORT_RESET_MSEC
;
1526 /* build a "continuous enough" reset signal, with up to
1527 * 3msec gap between pulses. scheduler HZ==100 must work;
1528 * this might need to be deadline-scheduled.
1531 /* spin until any current reset finishes */
1533 temp
= OHCI_READ_PORT_ULONG(PortStatus
);
1534 if (!(temp
& RH_PS_PRS
))
1536 usb_wait_us_dpc(500);
1539 if (!(temp
& RH_PS_CCS
))
1541 if (temp
& RH_PS_PRSC
)
1543 OHCI_WRITE_PORT_ULONG(PortStatus
, RH_PS_PRSC
);
1546 /* start the next reset, sleep till it's probably done */
1547 OHCI_WRITE_PORT_ULONG(PortStatus
, RH_PS_PRS
);
1548 usb_wait_ms_dpc(PORT_RESET_HW_MSEC
);
1549 Now
= OHCI_READ_PORT_ULONG((PULONG
)&ohci
->regs
->fmnumber
);
1550 } while (tick_before(Now
, ResetDone
));
1552 status
= OHCI_READ_PORT_ULONG((PULONG
)(&ohci
->regs
->roothub
.portstatus
[port_idx
]));
1553 usb_dbg_print(DBGLVL_MAXIMUM
, ("ohci_rh_reset_port(): status after written=0x%x\n", status
));
1558 ohci_rh_get_dev_change(PHCD hcd
, PBYTE buf
) //must have the rh dev_lock acquired
1567 ohci
= ohci_from_hcd(hcd
);
1569 for(i
= 0; i
< ohci
->num_ports
; i
++)
1571 status
= OHCI_READ_PORT_ULONG((PULONG
)(&ohci
->regs
->roothub
.portstatus
[i
]));
1575 ohci_dbg_print(DBGLVL_MAXIMUM
, ("ohci_rh_get_dev_change(): erh port%d status=0x%x\n", i
, status
));
1578 if (status
& (RH_PS_PESC
| RH_PS_CSC
| RH_PS_OCIC
))
1580 buf
[(i
+ 1) >> 3] |= (1 << ((i
+ 1) & 7));
1588 ohci_hcd_dispatch(PHCD hcd
, LONG disp_code
, PVOID param
)
1593 return STATUS_INVALID_PARAMETER
;
1594 ohci
= ohci_from_hcd(hcd
);
1598 case HCD_DISP_READ_PORT_COUNT
:
1601 return STATUS_INVALID_PARAMETER
;
1602 *((PUCHAR
) param
) = ohci
->num_ports
;
1603 return STATUS_SUCCESS
;
1605 case HCD_DISP_READ_RH_DEV_CHANGE
:
1607 if (ohci_rh_get_dev_change(hcd
, param
) == FALSE
)
1608 return STATUS_INVALID_PARAMETER
;
1609 return STATUS_SUCCESS
;
1613 return STATUS_NOT_IMPLEMENTED
;
1617 ohci_init_hcd_interface(POHCI_DEV ohci
)
1619 ohci
->hcd_interf
.hcd_set_dev_mgr
= ehci_set_dev_mgr
;
1620 ohci
->hcd_interf
.hcd_get_dev_mgr
= ehci_get_dev_mgr
;
1621 ohci
->hcd_interf
.hcd_get_type
= ohci_get_type
;
1622 ohci
->hcd_interf
.hcd_set_id
= ehci_set_id
;
1623 ohci
->hcd_interf
.hcd_get_id
= ehci_get_id
;
1624 ohci
->hcd_interf
.hcd_alloc_addr
= ehci_alloc_addr
;
1625 ohci
->hcd_interf
.hcd_free_addr
= ehci_free_addr
;
1626 ohci
->hcd_interf
.hcd_submit_urb
= ohci_submit_urb2
;
1627 ohci
->hcd_interf
.hcd_generic_urb_completion
= ohci_generic_urb_completion
;
1628 ohci
->hcd_interf
.hcd_get_root_hub
= ohci_get_root_hub
;
1629 ohci
->hcd_interf
.hcd_set_root_hub
= ohci_set_root_hub
;
1630 ohci
->hcd_interf
.hcd_remove_device
= ohci_remove_device2
;
1631 ohci
->hcd_interf
.hcd_rh_reset_port
= ohci_rh_reset_port
;
1632 ohci
->hcd_interf
.hcd_release
= ohci_hcd_release
;
1633 ohci
->hcd_interf
.hcd_cancel_urb
= ohci_cancel_urb2
;
1634 ohci
->hcd_interf
.hcd_start
= ohci_start
;
1635 ohci
->hcd_interf
.hcd_dispatch
= ohci_hcd_dispatch
;
1637 ohci
->hcd_interf
.flags
= HCD_TYPE_OHCI
; //hcd types | hcd id