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

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

Added license statement to all .c files

  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/** @addtogroup usb
29 * @{
30 */
31/** @file
32 * @brief UHCI driver
33 */
34#include <errno.h>
35
36#include <usb/usb.h> /* usb_address_t */
37#include <usb/usbdrv.h> /* usb_drv_* */
38#include <usb/debug.h>
39
40#include "port.h"
41#include "port_status.h"
42
43static int uhci_port_new_device(uhci_port_t *port);
44static int uhci_port_remove_device(uhci_port_t *port);
45static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
46static int uhci_port_check(void *port);
47
48int uhci_port_init(
49 uhci_port_t *port, port_status_t *address, unsigned number,
50 unsigned usec, device_t *rh)
51{
52 assert(port);
53 port->address = address;
54 port->number = number;
55 port->wait_period_usec = usec;
56 port->attached_device = 0;
57 port->rh = rh;
58 port->hc_phone = rh->parent_phone;
59
60 port->checker = fibril_create(uhci_port_check, port);
61 if (port->checker == 0) {
62 usb_log_error(": failed to launch root hub fibril.");
63 return ENOMEM;
64 }
65 fibril_add_ready(port->checker);
66 usb_log_debug(
67 "Added fibril for port %d: %p.\n", number, port->checker);
68 return EOK;
69}
70/*----------------------------------------------------------------------------*/
71void uhci_port_fini(uhci_port_t *port)
72{
73// fibril_teardown(port->checker);
74 return;
75}
76/*----------------------------------------------------------------------------*/
77int uhci_port_check(void *port)
78{
79 async_usleep( 1000000 );
80 uhci_port_t *port_instance = port;
81 assert(port_instance);
82
83 while (1) {
84 usb_log_debug("Port(%d) status address %p:\n",
85 port_instance->number, port_instance->address);
86
87 /* read register value */
88 port_status_t port_status =
89 port_status_read(port_instance->address);
90
91 /* debug print */
92 usb_log_info("Port(%d) status %#.4x\n",
93 port_instance->number, port_status);
94 print_port_status(port_status);
95
96 if (port_status & STATUS_CONNECTED_CHANGED) {
97 if (port_status & STATUS_CONNECTED) {
98 /* new device */
99 uhci_port_new_device(port_instance);
100 } else {
101 uhci_port_remove_device(port_instance);
102 }
103 }
104 async_usleep(port_instance->wait_period_usec);
105 }
106 return EOK;
107}
108/*----------------------------------------------------------------------------*/
109static int uhci_port_new_device(uhci_port_t *port)
110{
111 assert(port);
112 assert(port->hc_phone);
113
114 usb_log_info("Adding new device on port %d.\n", port->number);
115
116
117 /* get default address */
118 int ret = usb_drv_reserve_default_address(port->hc_phone);
119 if (ret != EOK) {
120 usb_log_error("Failed to reserve default address.\n");
121 return ret;
122 }
123
124 const usb_address_t usb_address = usb_drv_request_address(port->hc_phone);
125
126 if (usb_address <= 0) {
127 usb_log_error("Recieved invalid address(%d).\n", usb_address);
128 return usb_address;
129 }
130 /*
131 * the host then waits for at least 100 ms to allow completion of
132 * an insertion process and for power at the device to become stable.
133 */
134 async_usleep(100000);
135
136 /* enable port */
137 uhci_port_set_enabled(port, true);
138
139 /* The hub maintains the reset signal to that port for 10 ms
140 * (See Section 11.5.1.5)
141 */
142 port_status_t port_status =
143 port_status_read(port->address);
144 port_status |= STATUS_IN_RESET;
145 port_status_write(port->address, port_status);
146 async_usleep(10000);
147 port_status =
148 port_status_read(port->address);
149 port_status &= ~STATUS_IN_RESET;
150 port_status_write(port->address, port_status);
151
152 /* assign address to device */
153 ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
154
155
156 if (ret != EOK) { /* address assigning went wrong */
157 usb_log_error("Failed(%d) to assign address to the device.\n", ret);
158 uhci_port_set_enabled(port, false);
159 int release = usb_drv_release_default_address(port->hc_phone);
160 if (release != EOK) {
161 usb_log_error("Failed to release default address.\n");
162 return release;
163 }
164 return ret;
165 }
166
167 /* release default address */
168 ret = usb_drv_release_default_address(port->hc_phone);
169 if (ret != EOK) {
170 usb_log_error("Failed to release default address.\n");
171 return ret;
172 }
173
174 /* communicate and possibly report to devman */
175 assert(port->attached_device == 0);
176
177 ret = usb_drv_register_child_in_devman(port->hc_phone, port->rh,
178 usb_address, &port->attached_device);
179
180 if (ret != EOK) { /* something went wrong */
181 usb_log_error("Failed(%d) in usb_drv_register_child.\n", ret);
182 uhci_port_set_enabled(port, false);
183 return ENOMEM;
184 }
185 usb_log_info("Sucessfully added device on port(%d) address(%d).\n",
186 port->number, usb_address);
187
188 /* TODO: bind the address here */
189
190 return EOK;
191}
192/*----------------------------------------------------------------------------*/
193static int uhci_port_remove_device(uhci_port_t *port)
194{
195 usb_log_error("Don't know how to remove device %#x.\n",
196 (unsigned int)port->attached_device);
197 uhci_port_set_enabled(port, false);
198 return EOK;
199}
200/*----------------------------------------------------------------------------*/
201static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
202{
203 assert(port);
204
205 /* read register value */
206 port_status_t port_status
207 = port_status_read(port->address);
208
209 /* enable port: register write */
210 if (enabled) {
211 port_status |= STATUS_ENABLED;
212 } else {
213 port_status &= ~STATUS_ENABLED;
214 }
215 port_status_write(port->address, port_status);
216
217 usb_log_info("%s port %d.\n",
218 enabled ? "Enabled" : "Disabled", port->number);
219 return EOK;
220}
221/*----------------------------------------------------------------------------*/
222/**
223 * @}
224 */
Note: See TracBrowser for help on using the repository browser.