Author: fireball Date: Tue Nov 20 18:16:16 2007 New Revision: 30596
URL: http://svn.reactos.org/svn/reactos?rev=30596&view=rev Log: - Add roothub status operations. - Ports count is correctly detected now. - Added all necessary stubs for HCD interface, so that usbdriver can work further.
Modified: trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.h
Modified: trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/nt4compat/usbdr... ============================================================================== --- trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c (original) +++ trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.c Tue Nov 20 18:16:16 2007 @@ -39,8 +39,13 @@
// shared with EHCI NTSTATUS ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp); +PUSB_DEV_MANAGER ehci_get_dev_mgr(PHCD hcd); VOID ehci_set_dev_mgr(PHCD hcd, PUSB_DEV_MANAGER dev_mgr); VOID ehci_set_id(PHCD hcd, UCHAR id); +UCHAR ehci_get_id(PHCD hcd); +UCHAR ehci_alloc_addr(PHCD hcd); +VOID ehci_free_addr(PHCD hcd, UCHAR addr); + BOOLEAN NTAPI ehci_cal_cpu_freq(PVOID context);
extern USB_DEV_MANAGER g_dev_mgr; @@ -56,6 +61,31 @@ #define OHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src ) #define OHCI_READ_PORT_USHORT( psh ) ( *psh ) #define OHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src ) + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define read_roothub(hc, register, mask) ({ \ + ULONG temp = OHCI_READ_PORT_ULONG(&((hc)->regs->roothub.register)); \ + if (temp == -1) \ + /*disable (hc)*/; \ + /*else if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = ohci_readl (hc, &hc->regs->roothub.register); */ \ + temp; }) + +static ULONG roothub_a (POHCI_DEV hc) + { return read_roothub (hc, a, 0xfc0fe000); } +/* +static inline u32 roothub_b (struct ohci_hcd *hc) + { return ohci_readl (hc, &hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci_hcd *hc) + { return ohci_readl (hc, &hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci_hcd *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } +*/ +
VOID ohci_wait_ms(POHCI_DEV ohci, LONG ms) @@ -261,6 +291,7 @@
//before we connect the interrupt, we have to init ohci pdev_ext->ohci->pdev_ext = pdev_ext; + pdev_ext->ohci->regs = (POHCI_REGS)pdev_ext->ohci->port_base;
KeInitializeTimer(&pdev_ext->ohci->reset_timer);
@@ -292,6 +323,23 @@ //ohci_usb_reset (ohci); }
+ /* Disable HC interrupts */ + OHCI_WRITE_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_INTRDISABLE), OHCI_INTR_MIE); + // flush the writes + (VOID)OHCI_READ_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_CONTROL)); + + /* Read the number of ports unless overridden */ + pdev_ext->ohci->num_ports = roothub_a(pdev_ext->ohci) & RH_A_NDP; + + DbgPrint("OHCI: %d ports\n", pdev_ext->ohci->num_ports); + + //ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller, + // sizeof *ohci->hcca, &ohci->hcca_dma, 0); + //if (!ohci->hcca) + // return -ENOMEM; + + //if ((ret = ohci_mem_init (ohci)) < 0) + // ohci_stop (ohci_to_hcd(ohci));
#if 0 //init ehci_caps @@ -413,30 +461,217 @@ return pdev; }
+BOOLEAN +ohci_start(PHCD hcd) +{ + //ULONG tmp; + //PBYTE base; + //PEHCI_USBCMD_CONTENT usbcmd; + //POHCI_DEV ohci; + + if (hcd == NULL) + return FALSE; + + return TRUE; +#if 0 + ehci = struct_ptr(hcd, EHCI_DEV, hcd_interf); + base = ehci->port_base; + + // stop the controller + tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD)); + usbcmd = (PEHCI_USBCMD_CONTENT) & tmp; + usbcmd->run_stop = 0; + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); + + // wait the controller stop( ehci spec, 16 microframe ) + usb_wait_ms_dpc(2); + + // reset the controller + usbcmd = (PEHCI_USBCMD_CONTENT) & tmp; + usbcmd->hcreset = TRUE; + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); + + for(;;) + { + // interval.QuadPart = -100 * 10000; // 10 ms + // KeDelayExecutionThread( KernelMode, FALSE, &interval ); + KeStallExecutionProcessor(10); + tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD)); + if (!usbcmd->hcreset) + break; + } + + // prepare the registers + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CTRLDSSEGMENT), 0); + + // turn on all the int + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBINTR), + EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR + // EHCI_USBINTR_FLROVR | \ // it is noisy + // EHCI_USBINTR_PC // we detect it by polling + ); + // write the list base reg + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_PERIODICLISTBASE), ehci->frame_list_phys_addr.LowPart); + + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_ASYNCLISTBASE), ehci->skel_async_qh->phys_addr & ~(0x1f)); + + usbcmd->int_threshold = 1; + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); + + // let's rock + usbcmd->run_stop = 1; + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); + + // set the configuration flag + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CONFIGFLAG), 1); + + // enable the list traversaling + usbcmd->async_enable = 1; + usbcmd->periodic_enable = 1; + EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); +#endif + return TRUE; +} + + +ULONG +ohci_get_type(PHCD hcd) +{ + return HCD_TYPE_OHCI; // ( hcd->flags & HCD_TYPE_MASK ); +} + +NTSTATUS +ohci_submit_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) +{ + return STATUS_UNSUCCESSFUL; +} + +PUSB_DEV +ohci_get_root_hub(PHCD hcd) +{ + return ohci_from_hcd(hcd)->root_hub; +} + +VOID +ohci_set_root_hub(PHCD hcd, PUSB_DEV root_hub) +{ + if (hcd == NULL || root_hub == NULL) + return; + ohci_from_hcd(hcd)->root_hub = root_hub; + return; +} + +BOOLEAN +ohci_remove_device2(PHCD hcd, PUSB_DEV pdev) +{ + if (hcd == NULL || pdev == NULL) + return FALSE; + + return FALSE; + //return ehci_remove_device(ehci_from_hcd(hcd), pdev); +} + +BOOLEAN +ohci_hcd_release(PHCD hcd) +{ + POHCI_DEV ohci; + POHCI_DEVICE_EXTENSION pdev_ext; + + if (hcd == NULL) + return FALSE; + + ohci = ohci_from_hcd(hcd); + pdev_ext = ohci->pdev_ext; + return FALSE;//ehci_release(pdev_ext->pdev_obj); +} + +NTSTATUS +ohci_cancel_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) +{ + POHCI_DEV ohci; + if (hcd == NULL) + return STATUS_INVALID_PARAMETER; + + ohci = ohci_from_hcd(hcd); + return STATUS_UNSUCCESSFUL;//ehci_cancel_urb(ehci, pdev, pendp, purb); +} + +VOID +ohci_generic_urb_completion(PURB purb, PVOID context) +{ +} + +BOOLEAN +ohci_rh_reset_port(PHCD hcd, UCHAR port_idx) +{ + //ULONG i; + POHCI_DEV ohci; + //ULONG status; + //UCHAR port_count; + + if (hcd == NULL) + return FALSE; + + ohci = ohci_from_hcd(hcd); + //port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count; + + //if (port_idx < 1 || port_idx > port_count) + // return FALSE; + + //usb_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_reset_port(): status after written=0x%x\n", status)); + return TRUE; +} + +NTSTATUS +ohci_hcd_dispatch(PHCD hcd, LONG disp_code, PVOID param) +{ + POHCI_DEV ohci; + + if (hcd == NULL) + return STATUS_INVALID_PARAMETER; + ohci = ohci_from_hcd(hcd); +#if 0 + switch (disp_code) + { + case HCD_DISP_READ_PORT_COUNT: + { + if (param == NULL) + return STATUS_INVALID_PARAMETER; + *((PUCHAR) param) = (UCHAR) HCS_N_PORTS(ehci->ehci_caps.hcs_params); + return STATUS_SUCCESS; + } + case HCD_DISP_READ_RH_DEV_CHANGE: + { + if (ehci_rh_get_dev_change(hcd, param) == FALSE) + return STATUS_INVALID_PARAMETER; + return STATUS_SUCCESS; + } + } +#endif + return STATUS_NOT_IMPLEMENTED; +} + VOID ohci_init_hcd_interface(POHCI_DEV ohci) { ohci->hcd_interf.hcd_set_dev_mgr = ehci_set_dev_mgr; -#if 0 ohci->hcd_interf.hcd_get_dev_mgr = ehci_get_dev_mgr; - ohci->hcd_interf.hcd_get_type = ehci_get_type; -#endif + ohci->hcd_interf.hcd_get_type = ohci_get_type; ohci->hcd_interf.hcd_set_id = ehci_set_id; -#if 0 ohci->hcd_interf.hcd_get_id = ehci_get_id; ohci->hcd_interf.hcd_alloc_addr = ehci_alloc_addr; ohci->hcd_interf.hcd_free_addr = ehci_free_addr; - ohci->hcd_interf.hcd_submit_urb = ehci_submit_urb2; - ohci->hcd_interf.hcd_generic_urb_completion = ehci_generic_urb_completion; - ohci->hcd_interf.hcd_get_root_hub = ehci_get_root_hub; - ohci->hcd_interf.hcd_set_root_hub = ehci_set_root_hub; - ohci->hcd_interf.hcd_remove_device = ehci_remove_device2; - ohci->hcd_interf.hcd_rh_reset_port = ehci_rh_reset_port; - ohci->hcd_interf.hcd_release = ehci_hcd_release; - ohci->hcd_interf.hcd_cancel_urb = ehci_cancel_urb2; - ohci->hcd_interf.hcd_start = ehci_start; - ohci->hcd_interf.hcd_dispatch = ehci_hcd_dispatch; -#endif + ohci->hcd_interf.hcd_submit_urb = ohci_submit_urb2; + ohci->hcd_interf.hcd_generic_urb_completion = ohci_generic_urb_completion; + ohci->hcd_interf.hcd_get_root_hub = ohci_get_root_hub; + ohci->hcd_interf.hcd_set_root_hub = ohci_set_root_hub; + ohci->hcd_interf.hcd_remove_device = ohci_remove_device2; + ohci->hcd_interf.hcd_rh_reset_port = ohci_rh_reset_port; + ohci->hcd_interf.hcd_release = ohci_hcd_release; + ohci->hcd_interf.hcd_cancel_urb = ohci_cancel_urb2; + ohci->hcd_interf.hcd_start = ohci_start; + ohci->hcd_interf.hcd_dispatch = ohci_hcd_dispatch; + ohci->hcd_interf.flags = HCD_TYPE_OHCI; //hcd types | hcd id }
Modified: trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/usb/nt4compat/usbdr... ============================================================================== --- trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.h (original) +++ trunk/reactos/drivers/usb/nt4compat/usbdriver/ohci.h Tue Nov 20 18:16:16 2007 @@ -119,7 +119,7 @@ * You must use readl() and writel() (in <asm/io.h>) to access these fields!! * Layout is in section 7 (and appendix B) of the spec. */ -struct _OHCI_REGS +typedef struct _OHCI_REGS { /* control and status registers (section 7.1) */ ULONG revision; @@ -164,6 +164,9 @@ PHYSICAL_ADDRESS ohci_reg_base; // io space BOOLEAN port_mapped; PBYTE port_base; // note: added by ehci_caps.length, operational regs base addr, not the actural base + struct _OHCI_REGS *regs; + + USHORT num_ports;
KTIMER reset_timer; //used to reset the host controller struct _OHCI_DEVICE_EXTENSION *pdev_ext; @@ -193,6 +196,6 @@ KDPC ohci_dpc; } OHCI_DEVICE_EXTENSION, *POHCI_DEVICE_EXTENSION;
- +#define ohci_from_hcd( hCD ) ( struct_ptr( ( hCD ), OHCI_DEV, hcd_interf ) )
#endif /* __OHCI_H__ */