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
Line 
1
2#include <errno.h>
3#include <usb/usb.h>
4#include <usb/usbdrv.h>
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);
11static int uhci_port_remove_device(uhci_port_t *port);
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);
19 port_instance->hc_phone = devman_device_connect(port_instance->hc->handle, 0);
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 */
26 port_status_t port_status =
27 port_status_read(port_instance->address);
28
29 /* debug print */
30 uhci_print_info("Port(%d) status %#.4x:\n",
31 port_instance->number, port_status);
32 print_port_status(port_status);
33
34 if (port_status & STATUS_CONNECTED_CHANGED) {
35 if (port_status & STATUS_CONNECTED) {
36 /* new device */
37 uhci_port_new_device(port_instance);
38 } else {
39 uhci_port_remove_device(port_instance);
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);
50 assert(port->hc_phone);
51
52 uhci_print_info("Adding new device on port %d.\n", port->number);
53
54
55 /* get default address */
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 }
61
62 const usb_address_t usb_address = usb_drv_request_address(port->hc_phone);
63
64 if (usb_address <= 0) {
65 uhci_print_error("Recieved invalid address(%d).\n", usb_address);
66 return usb_address;
67 }
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);
73
74 /* enable port */
75 uhci_port_set_enabled(port, true);
76
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
90 /* assign address to device */
91 ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
92
93
94 if (ret != EOK) { /* address assigning went wrong */
95 uhci_print_error("Failed(%d) to assign address to the device.\n", ret);
96 uhci_port_set_enabled(port, false);
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;
103 }
104
105 /* release default address */
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 }
111
112 /* communicate and possibly report to devman */
113 assert(port->attached_device == 0);
114
115 ret = usb_drv_register_child_in_devman(port->hc_phone, port->hc, usb_address,
116 &port->attached_device);
117
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 }
123
124 /* TODO: bind the address here */
125
126 return EOK;
127}
128/*----------------------------------------------------------------------------*/
129static int uhci_port_remove_device(uhci_port_t *port)
130{
131 uhci_print_error("Don't know how to remove device %#x.\n",
132 (unsigned int)port->attached_device);
133 uhci_port_set_enabled(port, false);
134 return EOK;
135}
136/*----------------------------------------------------------------------------*/
137static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
138{
139 assert(port);
140
141 /* read register value */
142 port_status_t port_status
143 = port_status_read(port->address);
144
145 /* enable port: register write */
146 if (enabled) {
147 port_status |= STATUS_ENABLED;
148 } else {
149 port_status &= ~STATUS_ENABLED;
150 }
151 port_status_write(port->address, port_status);
152
153 uhci_print_info("%s port %d.\n",
154 enabled ? "Enabled" : "Disabled", port->number);
155 return EOK;
156}
157/*----------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.