source: mainline/uspace/drv/uhci/root_hub/port.c@ 62d9827

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 62d9827 was 62d9827, checked in by Jan Vesely <jano.vesely@…>, 15 years ago

Switched to address hadling interface, instead of direct access.

  • Property mode set to 100644
File size: 4.3 KB
RevLine 
[28f660d]1
[92f924c8]2#include <errno.h>
[28f660d]3#include <usb/usb.h>
[f9dd44d]4#include <usb/usbdrv.h>
[28f660d]5
6#include "debug.h"
7#include "port.h"
8#include "port_status.h"
9
10static int uhci_port_new_device(uhci_port_t *port);
[0bd2879]11static int uhci_port_remove_device(uhci_port_t *port);
[28f660d]12static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
13
14/*----------------------------------------------------------------------------*/
15int uhci_port_check(void *port)
16{
17 uhci_port_t *port_instance = port;
18 assert(port_instance);
[f9dd44d]19 port_instance->hc_phone = devman_device_connect(port_instance->hc->handle, 0);
[28f660d]20
21 while (1) {
22 uhci_print_info("Port(%d) status address %p:\n",
23 port_instance->number, port_instance->address);
24
25 /* read register value */
[8f748215]26 port_status_t port_status =
27 port_status_read(port_instance->address);
[28f660d]28
29 /* debug print */
[15701921]30 uhci_print_info("Port(%d) status %#.4x:\n",
[8f748215]31 port_instance->number, port_status);
[2e38385]32 print_port_status(port_status);
[28f660d]33
[8f748215]34 if (port_status & STATUS_CONNECTED_CHANGED) {
35 if (port_status & STATUS_CONNECTED) {
[f0e25e8]36 /* new device */
[28f660d]37 uhci_port_new_device(port_instance);
38 } else {
[0bd2879]39 uhci_port_remove_device(port_instance);
[28f660d]40 }
41 }
42 async_usleep(port_instance->wait_period_usec);
43 }
44 return EOK;
45}
46/*----------------------------------------------------------------------------*/
47static int uhci_port_new_device(uhci_port_t *port)
48{
49 assert(port);
[62d9827]50 assert(port->hc_phone);
[28f660d]51
52 uhci_print_info("Adding new device on port %d.\n", port->number);
53
54
55 /* get default address */
[62d9827]56 int ret = usb_drv_reserve_default_address(port->hc_phone);
57 if (ret != EOK) {
58 uhci_print_error("Failed to reserve default address.\n");
59 return ret;
60 }
[28f660d]61
[62d9827]62 const usb_address_t usb_address = usb_drv_request_address(port->hc_phone);
[f9dd44d]63
64 if (usb_address <= 0) {
[62d9827]65 uhci_print_error("Recieved invalid address(%d).\n", usb_address);
[f9dd44d]66 return usb_address;
67 }
[e68de30]68 /*
69 * the host then waits for at least 100 ms to allow completion of
70 * an insertion process and for power at the device to become stable.
71 */
72 async_usleep(100000);
[f9dd44d]73
[28f660d]74 /* enable port */
[2e38385]75 uhci_port_set_enabled(port, true);
[28f660d]76
[e68de30]77 /* The hub maintains the reset signal to that port for 10 ms
78 * (See Section 11.5.1.5)
79 */
80 port_status_t port_status =
81 port_status_read(port->address);
82 port_status |= STATUS_IN_RESET;
83 port_status_write(port->address, port_status);
84 async_usleep(10000);
85 port_status =
86 port_status_read(port->address);
87 port_status &= ~STATUS_IN_RESET;
88 port_status_write(port->address, port_status);
89
[28f660d]90 /* assign address to device */
[62d9827]91 ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
[28f660d]92
93
[f9dd44d]94 if (ret != EOK) { /* address assigning went wrong */
95 uhci_print_error("Failed(%d) to assign address to the device.\n", ret);
[0bd2879]96 uhci_port_set_enabled(port, false);
[62d9827]97 int release = usb_drv_release_default_address(port->hc_phone);
98 if (release != EOK) {
99 uhci_print_fatal("Failed to release default address.\n");
100 return release;
101 }
102 return ret;
[28f660d]103 }
104
[0bd2879]105 /* release default address */
[62d9827]106 ret = usb_drv_release_default_address(port->hc_phone);
107 if (ret != EOK) {
108 uhci_print_fatal("Failed to release default address.\n");
109 return ret;
110 }
[0bd2879]111
[b276c3b]112 /* communicate and possibly report to devman */
[0bd2879]113 assert(port->attached_device == 0);
[28f660d]114
[f9dd44d]115 ret = usb_drv_register_child_in_devman(port->hc_phone, port->hc, usb_address,
116 &port->attached_device);
[0bd2879]117
[f9dd44d]118 if (ret != EOK) { /* something went wrong */
119 uhci_print_error("Failed(%d) in usb_drv_register_child.\n", ret);
120 uhci_port_set_enabled(port, false);
121 return ENOMEM;
122 }
[0bd2879]123
[62d9827]124 /* TODO: bind the address here */
125
[28f660d]126 return EOK;
127}
128/*----------------------------------------------------------------------------*/
[0bd2879]129static int uhci_port_remove_device(uhci_port_t *port)
130{
[2e38385]131 uhci_print_error("Don't know how to remove device %#x.\n",
[62d9827]132 (unsigned int)port->attached_device);
[0bd2879]133 uhci_port_set_enabled(port, false);
134 return EOK;
135}
136/*----------------------------------------------------------------------------*/
[28f660d]137static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
138{
139 assert(port);
140
141 /* read register value */
[8f748215]142 port_status_t port_status
143 = port_status_read(port->address);
[28f660d]144
145 /* enable port: register write */
[8f748215]146 if (enabled) {
147 port_status |= STATUS_ENABLED;
148 } else {
149 port_status &= ~STATUS_ENABLED;
150 }
[2e38385]151 port_status_write(port->address, port_status);
[8f748215]152
[2e38385]153 uhci_print_info("%s port %d.\n",
154 enabled ? "Enabled" : "Disabled", port->number);
[28f660d]155 return EOK;
156}
157/*----------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.