Index: uspace/drv/bus/usb/ehci/ehci_regs.h
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_regs.h	(revision 4ee52726789edb40f954a15caac430e9a866cd8e)
+++ uspace/drv/bus/usb/ehci/ehci_regs.h	(revision 2be477d52d8fed39a2862f10b87d12afb454b9c7)
@@ -42,6 +42,6 @@
 #define EHCI_RD(reg) uint32_t_le2host(pio_read_32(&(reg)))
 #define EHCI_RD8(reg) pio_read_8(&(reg))
-//#define EHCI_SET(reg, val) reg |= host2uint32_t_le(val)
-//#define EHCI_CLR(reg, val) reg &= host2uint32_t_le(~val)
+#define EHCI_SET(reg, val) pio_set_32(&(reg), host2uint32_t_le(val), 0)
+#define EHCI_CLR(reg, val) pio_clear_32(&(reg), host2uint32_t_le(val), 0)
 
 /** EHCI memory mapped capability registers structure */
@@ -135,24 +135,21 @@
 #define USB_PORTSC_WKDSCNNT_E_FLAG   (1 << 21)
 #define USB_PORTSC_WKCNNT_E_FLAG     (1 << 20)
-#define USB_PORTSC_PORT_TEST_MASK    0xf
-#define USB_PORTSC_PORT_TEST_SHIFT   16
-#define USB_PORTSC_NO_TEST           0x0
-#define USB_PORTSC_TEST_J_STATE      0x1
-#define USB_PORTSC_TEST_K_STATE      0x2
-#define USB_PORTSC_TEST_SE0_NAK      0x3
-#define USB_PORTSC_TEST_PACKET       0x4
-#define USB_PORTSC_TEST_FORCE_ENABLE 0x5
-#define USB_PORTSC_INDICATOR_MASK    0x3
-#define USB_PORTSC_INDICATOR_SHIFT   14
-#define USB_PORTSC_INDICATOR_OFF     0x0
-#define USB_PORTSC_INDICATOR_AMBER   0x1
-#define USB_PORTSC_INDICATOR_GREEN   0x2
+#define USB_PORTSC_PORT_TEST_MASK    (0xf << 16)
+#define USB_PORTSC_NO_TEST           (0x0 << 16)
+#define USB_PORTSC_TEST_J_STATE      (0x1 << 16)
+#define USB_PORTSC_TEST_K_STATE      (0x2 << 16)
+#define USB_PORTSC_TEST_SE0_NAK      (0x3 << 16)
+#define USB_PORTSC_TEST_PACKET       (0x4 << 16)
+#define USB_PORTSC_TEST_FORCE_ENABLE (0x5 << 16)
+#define USB_PORTSC_INDICATOR_MASK    (0x3 << 14)
+#define USB_PORTSC_INDICATOR_OFF     (0x0 << 14)
+#define USB_PORTSC_INDICATOR_AMBER   (0x1 << 14)
+#define USB_PORTSC_INDICATOR_GREEN   (0x2 << 14)
 #define USB_PORTSC_PORT_OWNER_FLAG   (1 << 13)
 #define USB_PORTSC_PORT_POWER_FLAG   (1 << 12)
-#define USB_PORTSC_LINE_STATUS_MASK  0x3
-#define USB_PORTSC_LINE_STATUS_SHIFT 10
-#define USB_PORTSC_LINE_STATUS_SE0   0x0
-#define USB_PORTSC_LINE_STATUS_K     0x1
-#define USB_PORTSC_LINE_STATUS_J     0x2
+#define USB_PORTSC_LINE_STATUS_MASK  (0x3 << 10)
+#define USB_PORTSC_LINE_STATUS_SE0   (0x0 << 10)
+#define USB_PORTSC_LINE_STATUS_K     (0x1 << 10)
+#define USB_PORTSC_LINE_STATUS_J     (0x2 << 10)
 #define USB_PORTSC_PORT_RESET_FLAG   (1 << 8)
 #define USB_PORTSC_SUSPEND_FLAG      (1 << 7)
@@ -164,4 +161,7 @@
 #define USB_PORTSC_CONNECT_CH_FLAG   (1 << 1)
 #define USB_PORTSC_CONNECT_FLAG      (1 << 0)
+
+#define USB_PORTSC_WC_MASK \
+    (USB_PORTSC_CONNECT_CH_FLAG | USB_PORTSC_EN_CHANGE_FLAG | USB_PORTSC_OC_CHANGE_FLAG)
 } ehci_regs_t;
 
Index: uspace/drv/bus/usb/ehci/ehci_rh.c
===================================================================
--- uspace/drv/bus/usb/ehci/ehci_rh.c	(revision 4ee52726789edb40f954a15caac430e9a866cd8e)
+++ uspace/drv/bus/usb/ehci/ehci_rh.c	(revision 2be477d52d8fed39a2862f10b87d12afb454b9c7)
@@ -116,4 +116,5 @@
 	ehci_rh_hub_desc_init(instance, EHCI_RD(caps->hcsparams));
 	instance->unfinished_interrupt_transfer = NULL;
+
 	return virthub_base_init(&instance->base, name, &ops, instance,
 	    NULL, &instance->hub_descriptor.header, HUB_STATUS_CHANGE_PIPE);
@@ -206,6 +207,6 @@
 	if (uint16_usb2host(setup_packet->length) != 4)
 		return ESTALL;
+	/* ECHI RH does not report global OC, and local power is always good */
 	const uint32_t val = 0;
-	//TODO: implement
 	memcpy(data, &val, sizeof(val));
 	*act_size = sizeof(val);
@@ -231,15 +232,9 @@
 	 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
 	 * C_HUB_OVER_CURRENT are supported.
-	 * C_HUB_LOCAL_POWER is not supported
-	 * because root hubs do not support local power status feature.
-	 * C_HUB_OVER_CURRENT is represented by EHCI RHS_OCIC_FLAG.
-	 * (EHCI pg. 127)
+	 * C_HUB_LOCAL_POWER is not supported because root hubs do not support
+	 * local power status feature.
+	 * EHCI RH does not report global OC condition either
 	 */
-	const unsigned feature = uint16_usb2host(setup_packet->value);
-	if (feature == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) {
-		//TODO: Implement
-//		EHCI_WR(hub->registers->rh_status, RHS_OCIC_FLAG);
-	}
-	return EOK;
+	return ESTALL;
 }
 
@@ -262,7 +257,19 @@
 		return EINVAL;
 
-	const uint32_t status = 0;
-	// TODO: Implement
-	//EHCI_RD(hub->registers->rh_port_status[port]);
+	const uint32_t reg = EHCI_RD(hub->registers->portsc[port]);
+	const uint32_t status = uint32_host2usb(0 |
+	    (reg & USB_PORTSC_CONNECT_FLAG) ? (1 << 0) : 0 |
+	    (reg & USB_PORTSC_ENABLED_FLAG) ? (1 << 1) : 0 |
+	    (reg & USB_PORTSC_SUSPEND_FLAG) ? (1 << 2) : 0 |
+	    (reg & USB_PORTSC_OC_ACTIVE_FLAG) ? (1 << 3) : 0 |
+	    (reg & USB_PORTSC_PORT_RESET_FLAG) ? (1 << 4) : 0 |
+	    (reg & USB_PORTSC_PORT_POWER_FLAG) ? (1 << 8) : 0 |
+	    ((reg & USB_PORTSC_LINE_STATUS_MASK) == USB_PORTSC_LINE_STATUS_K) ?
+	        (1 << 9) : 0 |
+	    (reg & USB_PORTSC_PORT_OWNER_FLAG) ? (1 << 10) : 0 |
+	    (reg & USB_PORTSC_PORT_TEST_MASK) ? (1 << 11) : 0 |
+	    (reg & USB_PORTSC_INDICATOR_MASK) ? (1 << 12) : 0)
+	;
+	//TODO: use hub status flags here
 	memcpy(data, &status, sizeof(status));
 	*act_size = sizeof(status);
@@ -290,31 +297,41 @@
 	{
 	case USB_HUB_FEATURE_PORT_POWER:          /*8*/
-		{
-//			EHCI_WR(hub->registers->rh_port_status[port],
-//			    RHPS_CLEAR_PORT_POWER);
-//			    TODO: Implement
-			return EOK;
-		}
+		EHCI_CLR(hub->registers->portsc[port],
+		    USB_PORTSC_PORT_POWER_FLAG);
+		return EOK;
 
 	case USB_HUB_FEATURE_PORT_ENABLE:         /*1*/
-//		EHCI_WR(hub->registers->rh_port_status[port],
-//		    RHPS_CLEAR_PORT_ENABLE);
+		EHCI_CLR(hub->registers->portsc[port],
+		    USB_PORTSC_ENABLED_FLAG);
 		return EOK;
 
 	case USB_HUB_FEATURE_PORT_SUSPEND:        /*2*/
-//		EHCI_WR(hub->registers->rh_port_status[port],
-//		    RHPS_CLEAR_PORT_SUSPEND);
+		/* If not in suspend it's noop */
+		if ((EHCI_RD(hub->registers->portsc[port]) &
+		    USB_PORTSC_SUSPEND_FLAG) == 0)
+		    return EOK;
+		/* Host driven resume */
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_RESUME_FLAG);
+		async_usleep(20000);
+		EHCI_CLR(hub->registers->portsc[port],
+		    USB_PORTSC_RESUME_FLAG);
 		return EOK;
 
 	case USB_HUB_FEATURE_C_PORT_CONNECTION:   /*16*/
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_CONNECT_CH_FLAG);
+		return EOK;
 	case USB_HUB_FEATURE_C_PORT_ENABLE:       /*17*/
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_CONNECT_CH_FLAG);
+		return EOK;
+	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_OC_CHANGE_FLAG);
+		return EOK;
 	case USB_HUB_FEATURE_C_PORT_SUSPEND:      /*18*/
-	case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/
 	case USB_HUB_FEATURE_C_PORT_RESET:        /*20*/
-		usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, "
-		    "C_SUSPEND, C_OC or C_RESET on port %"PRIu16".\n", port);
-		/* Bit offsets correspond to the feature number */
-//		EHCI_WR(hub->registers->rh_port_status[port],
-//		    1 << feature);
+		//TODO these are not represented in hw, think of something
 		return EOK;
 
@@ -341,23 +358,32 @@
 	const unsigned feature = uint16_usb2host(setup_packet->value);
 	switch (feature) {
+	case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_ENABLED_FLAG);
+		return EOK;
+	case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_SUSPEND_FLAG);
+		return EOK;
+	case USB_HUB_FEATURE_PORT_RESET:   /*4*/
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_PORT_RESET_FLAG);
+		async_usleep(50000);
+		EHCI_CLR(hub->registers->portsc[port],
+		    USB_PORTSC_PORT_RESET_FLAG);
+		/* wait for reset to complete */
+		while (EHCI_RD(hub->registers->portsc[port]) &
+		    USB_PORTSC_PORT_RESET_FLAG);
+		/* Handle port ownership, if the port is not enabled
+		 * after reset it's a full speed device */
+		if (!(EHCI_RD(hub->registers->portsc[port]) &
+		    USB_PORTSC_ENABLED_FLAG))
+			EHCI_CLR(hub->registers->portsc[port],
+			    USB_PORTSC_PORT_OWNER_FLAG);
+
+		return EOK;
 	case USB_HUB_FEATURE_PORT_POWER:   /*8*/
-	{
-		/* No power switching */
-//		if (rhda & RHDA_NPS_FLAG)
-			return EOK;
-		/* Ganged power switching, one port powers all */
-//		if (!(rhda & RHDA_PSM_FLAG)) {
-//			EHCI_WR(hub->registers->rh_status,RHS_SET_GLOBAL_POWER);
-//			return EOK;
-//		}
-	}
-	/* Fall through, for per port power */
-	case USB_HUB_FEATURE_PORT_ENABLE:  /*1*/
-	case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/
-	case USB_HUB_FEATURE_PORT_RESET:   /*4*/
-		usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET "
-		    "on port %"PRIu16".\n", port);
-		/* Bit offsets correspond to the feature number */
-//		EHCI_WR(hub->registers->rh_port_status[port], 1 << feature);
+		EHCI_SET(hub->registers->portsc[port],
+		    USB_PORTSC_PORT_POWER_FLAG);
 		return EOK;
 	default:
@@ -389,16 +415,17 @@
 
 	uint16_t mask = 0;
-
-	/* Only local power source change and over-current change can happen */
-//	if (EHCI_RD(hub->registers->rh_status) & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) {
-//		mask |= 1;
-//	}
-
-	for (unsigned port = 1; port <= hub->port_count; ++port) {
+	for (unsigned port = 0; port < hub->port_count; ++port) {
 		/* Write-clean bits are those that indicate change */
-//		if (EHCI_RD(hub->registers->rh_port_status[port - 1])
-//		    & RHPS_CHANGE_WC_MASK) {
-//			mask |= (1 << port);
-//		}
+		uint32_t status = EHCI_RD(hub->registers->portsc[port]);
+		if (status & USB_PORTSC_WC_MASK) {
+			/* Ignore new LS device */
+			if ((status & USB_PORTSC_CONNECT_CH_FLAG) &&
+			    (status & USB_PORTSC_LINE_STATUS_MASK) ==
+			        USB_PORTSC_LINE_STATUS_K)
+				EHCI_CLR(hub->registers->portsc[port],
+				    USB_PORTSC_PORT_OWNER_FLAG);
+			else
+				mask |= (2 << port);
+		}
 	}
 
