source: mainline/uspace/drv/uhci-rhd/port.c@ 7ce0fe3

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

Root ub driver uses unified debug logging and some other polishing.

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