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
RevLine 
[28f660d]1
[92f924c8]2#include <errno.h>
[7ce0fe3]3
[245b56b5]4#include <usb/usb.h> /* usb_address_t */
5#include <usb/usbdrv.h> /* usb_drv_* */
[7ce0fe3]6#include <usb/debug.h>
[28f660d]7
8#include "port.h"
9#include "port_status.h"
10
11static int uhci_port_new_device(uhci_port_t *port);
[0bd2879]12static int uhci_port_remove_device(uhci_port_t *port);
[28f660d]13static int uhci_port_set_enabled(uhci_port_t *port, bool enabled);
[1256a0a]14static int uhci_port_check(void *port);
[28f660d]15
[1256a0a]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) {
[7ce0fe3]30 usb_log_error(": failed to launch root hub fibril.");
[1256a0a]31 return ENOMEM;
32 }
33 fibril_add_ready(port->checker);
[7ce0fe3]34 usb_log_debug(
[1256a0a]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}
[28f660d]44/*----------------------------------------------------------------------------*/
45int uhci_port_check(void *port)
46{
[72e19f50]47 async_usleep( 1000000 );
[28f660d]48 uhci_port_t *port_instance = port;
49 assert(port_instance);
50
51 while (1) {
[7ce0fe3]52 usb_log_debug("Port(%d) status address %p:\n",
[28f660d]53 port_instance->number, port_instance->address);
54
55 /* read register value */
[8f748215]56 port_status_t port_status =
57 port_status_read(port_instance->address);
[28f660d]58
59 /* debug print */
[7ce0fe3]60 usb_log_info("Port(%d) status %#.4x\n",
[8f748215]61 port_instance->number, port_status);
[2e38385]62 print_port_status(port_status);
[28f660d]63
[8f748215]64 if (port_status & STATUS_CONNECTED_CHANGED) {
65 if (port_status & STATUS_CONNECTED) {
[f0e25e8]66 /* new device */
[28f660d]67 uhci_port_new_device(port_instance);
68 } else {
[0bd2879]69 uhci_port_remove_device(port_instance);
[28f660d]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);
[62d9827]80 assert(port->hc_phone);
[28f660d]81
[7ce0fe3]82 usb_log_info("Adding new device on port %d.\n", port->number);
[28f660d]83
84
85 /* get default address */
[62d9827]86 int ret = usb_drv_reserve_default_address(port->hc_phone);
87 if (ret != EOK) {
[7ce0fe3]88 usb_log_error("Failed to reserve default address.\n");
[62d9827]89 return ret;
90 }
[28f660d]91
[62d9827]92 const usb_address_t usb_address = usb_drv_request_address(port->hc_phone);
[f9dd44d]93
94 if (usb_address <= 0) {
[7ce0fe3]95 usb_log_error("Recieved invalid address(%d).\n", usb_address);
[f9dd44d]96 return usb_address;
97 }
[e68de30]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);
[f9dd44d]103
[28f660d]104 /* enable port */
[2e38385]105 uhci_port_set_enabled(port, true);
[28f660d]106
[e68de30]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
[28f660d]120 /* assign address to device */
[62d9827]121 ret = usb_drv_req_set_address(port->hc_phone, 0, usb_address);
[28f660d]122
123
[f9dd44d]124 if (ret != EOK) { /* address assigning went wrong */
[7ce0fe3]125 usb_log_error("Failed(%d) to assign address to the device.\n", ret);
[0bd2879]126 uhci_port_set_enabled(port, false);
[62d9827]127 int release = usb_drv_release_default_address(port->hc_phone);
128 if (release != EOK) {
[7ce0fe3]129 usb_log_error("Failed to release default address.\n");
[62d9827]130 return release;
131 }
132 return ret;
[28f660d]133 }
134
[0bd2879]135 /* release default address */
[62d9827]136 ret = usb_drv_release_default_address(port->hc_phone);
137 if (ret != EOK) {
[7ce0fe3]138 usb_log_error("Failed to release default address.\n");
[62d9827]139 return ret;
140 }
[0bd2879]141
[b276c3b]142 /* communicate and possibly report to devman */
[0bd2879]143 assert(port->attached_device == 0);
[28f660d]144
[1256a0a]145 ret = usb_drv_register_child_in_devman(port->hc_phone, port->rh,
146 usb_address, &port->attached_device);
[0bd2879]147
[f9dd44d]148 if (ret != EOK) { /* something went wrong */
[7ce0fe3]149 usb_log_error("Failed(%d) in usb_drv_register_child.\n", ret);
[f9dd44d]150 uhci_port_set_enabled(port, false);
151 return ENOMEM;
152 }
[7ce0fe3]153 usb_log_info("Sucessfully added device on port(%d) address(%d).\n",
[245b56b5]154 port->number, usb_address);
[0bd2879]155
[62d9827]156 /* TODO: bind the address here */
157
[28f660d]158 return EOK;
159}
160/*----------------------------------------------------------------------------*/
[0bd2879]161static int uhci_port_remove_device(uhci_port_t *port)
162{
[7ce0fe3]163 usb_log_error("Don't know how to remove device %#x.\n",
[62d9827]164 (unsigned int)port->attached_device);
[0bd2879]165 uhci_port_set_enabled(port, false);
166 return EOK;
167}
168/*----------------------------------------------------------------------------*/
[28f660d]169static int uhci_port_set_enabled(uhci_port_t *port, bool enabled)
170{
171 assert(port);
172
173 /* read register value */
[8f748215]174 port_status_t port_status
175 = port_status_read(port->address);
[28f660d]176
177 /* enable port: register write */
[8f748215]178 if (enabled) {
179 port_status |= STATUS_ENABLED;
180 } else {
181 port_status &= ~STATUS_ENABLED;
182 }
[2e38385]183 port_status_write(port->address, port_status);
[8f748215]184
[7ce0fe3]185 usb_log_info("%s port %d.\n",
[2e38385]186 enabled ? "Enabled" : "Disabled", port->number);
[28f660d]187 return EOK;
188}
189/*----------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.