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

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

uhci-rhd - UHCI Root hub drier as a separated process

this wil deffinitely need a lot of polishing

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