source: mainline/uspace/drv/bus/usb/uhci/main.c@ e4d7363

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e4d7363 was e4d7363, checked in by Ondřej Hlavatý <aearsis@…>, 8 years ago

usbhost: refactor the initialization

Before that, drivers had to setup MMIO range multiple times, or even parse hw
resources themselves again. The former init method was split in half - init and
start. Init shall allocate and initialize inner structures, start shall start
the HC.

In the XHCI it is demonstrated how to isolate inner HC implementation from the
fact this driver is using libusbhost. It adds some boilerplate code, but
I think it leads to cleaner design.

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky, 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
29/** @addtogroup drvusbuhci
30 * @{
31 */
32/** @file
33 * @brief UHCI driver initialization
34 */
35
36#include <assert.h>
37#include <ddf/driver.h>
38#include <devman.h>
39#include <errno.h>
40#include <io/log.h>
41#include <io/logctl.h>
42#include <pci_dev_iface.h>
43#include <stdio.h>
44#include <str_error.h>
45#include <usb/debug.h>
46#include <usb/host/ddf_helpers.h>
47
48#include "hc.h"
49
50#define NAME "uhci"
51
52static int uhci_driver_init(hcd_t *, const hw_res_list_parsed_t *);
53static int uhci_driver_start(hcd_t *, bool);
54static void uhci_driver_fini(hcd_t *);
55static int disable_legacy(hcd_t *, ddf_dev_t *);
56
57static const ddf_hc_driver_t uhci_hc_driver = {
58 .claim = disable_legacy,
59 .hc_speed = USB_SPEED_FULL,
60 .irq_code_gen = uhci_hc_gen_irq_code,
61 .init = uhci_driver_init,
62 .start = uhci_driver_start,
63 .fini = uhci_driver_fini,
64 .name = "UHCI",
65 .ops = {
66 .schedule = uhci_hc_schedule,
67 .irq_hook = uhci_hc_interrupt,
68 .status_hook = uhci_hc_status,
69 },
70};
71
72static int uhci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res)
73{
74 assert(hcd);
75 assert(hcd_get_driver_data(hcd) == NULL);
76
77 hc_t *instance = malloc(sizeof(hc_t));
78 if (!instance)
79 return ENOMEM;
80
81 const int ret = hc_init(instance, res);
82 if (ret == EOK) {
83 hcd_set_implementation(hcd, instance, &uhci_hc_driver.ops);
84 } else {
85 free(instance);
86 }
87 return ret;
88}
89
90static int uhci_driver_start(hcd_t *hcd, bool interrupts)
91{
92 assert(hcd);
93 hc_t *hc = hcd_get_driver_data(hcd);
94
95 hc->hw_interrupts = interrupts;
96 hc_start(hc);
97 return EOK;
98}
99
100static void uhci_driver_fini(hcd_t *hcd)
101{
102 assert(hcd);
103 hc_t *hc = hcd_get_driver_data(hcd);
104 if (hc)
105 hc_fini(hc);
106
107 hcd_set_implementation(hcd, NULL, NULL);
108 free(hc);
109}
110
111/** Call the PCI driver with a request to clear legacy support register
112 *
113 * @param[in] device Device asking to disable interrupts
114 * @return Error code.
115 */
116static int disable_legacy(hcd_t *hcd, ddf_dev_t *device)
117{
118 assert(device);
119
120 async_sess_t *parent_sess = devman_parent_device_connect(
121 ddf_dev_get_handle(device), IPC_FLAG_BLOCKING);
122 if (!parent_sess)
123 return ENOMEM;
124
125 /* See UHCI design guide page 45 for these values.
126 * Write all WC bits in USB legacy register */
127 const int rc = pci_config_space_write_16(parent_sess, 0xc0, 0xaf00);
128
129 async_hangup(parent_sess);
130 return rc;
131}
132
133/** Initialize a new ddf driver instance for uhci hc and hub.
134 *
135 * @param[in] device DDF instance of the device to initialize.
136 * @return Error code.
137 */
138static int uhci_dev_add(ddf_dev_t *device)
139{
140 usb_log_debug2("uhci_dev_add() called\n");
141 assert(device);
142 return hcd_ddf_add_hc(device, &uhci_hc_driver);
143}
144
145static const driver_ops_t uhci_driver_ops = {
146 .dev_add = uhci_dev_add,
147};
148
149static const driver_t uhci_driver = {
150 .name = NAME,
151 .driver_ops = &uhci_driver_ops
152};
153
154
155/** Initialize global driver structures (NONE).
156 *
157 * @param[in] argc Number of arguments in argv vector (ignored).
158 * @param[in] argv Cmdline argument vector (ignored).
159 * @return Error code.
160 *
161 * Driver debug level is set here.
162 */
163int main(int argc, char *argv[])
164{
165 printf(NAME ": HelenOS UHCI driver.\n");
166 log_init(NAME);
167 logctl_set_log_level(NAME, LVL_NOTE);
168 return ddf_driver_main(&uhci_driver);
169}
170/**
171 * @}
172 */
Note: See TracBrowser for help on using the repository browser.