These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / usb / usbhub.c
1 /*
2  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <assert.h>
31 #include <byteswap.h>
32 #include <ipxe/usb.h>
33 #include "usbhub.h"
34
35 /** @file
36  *
37  * USB hub driver
38  *
39  */
40
41 /**
42  * Refill interrupt ring
43  *
44  * @v hubdev            Hub device
45  */
46 static void hub_refill ( struct usb_hub_device *hubdev ) {
47         int rc;
48
49         /* Refill interrupt endpoint */
50         if ( ( rc = usb_refill ( &hubdev->intr ) ) != 0 ) {
51                 DBGC ( hubdev, "HUB %s could not refill interrupt: %s\n",
52                        hubdev->name, strerror ( rc ) );
53                 /* Continue attempting to refill */
54                 return;
55         }
56
57         /* Stop refill process */
58         process_del ( &hubdev->refill );
59 }
60
61 /** Refill process descriptor */
62 static struct process_descriptor hub_refill_desc =
63         PROC_DESC ( struct usb_hub_device, refill, hub_refill );
64
65 /**
66  * Complete interrupt transfer
67  *
68  * @v ep                USB endpoint
69  * @v iobuf             I/O buffer
70  * @v rc                Completion status code
71  */
72 static void hub_complete ( struct usb_endpoint *ep,
73                            struct io_buffer *iobuf, int rc ) {
74         struct usb_hub_device *hubdev =
75                 container_of ( ep, struct usb_hub_device, intr );
76         struct usb_hub *hub = hubdev->hub;
77         uint8_t *data = iobuf->data;
78         unsigned int bits = ( 8 * iob_len ( iobuf ) );
79         unsigned int i;
80
81         /* Ignore packets cancelled when the endpoint closes */
82         if ( ! ep->open )
83                 goto done;
84
85         /* Ignore packets with errors */
86         if ( rc != 0 ) {
87                 DBGC ( hubdev, "HUB %s interrupt failed: %s\n",
88                        hubdev->name, strerror ( rc ) );
89                 DBGC_HDA ( hubdev, 0, iobuf->data, iob_len ( iobuf ) );
90                 goto done;
91         }
92
93         /* Report any port status changes */
94         for ( i = 1 ; i <= hub->ports ; i++ ) {
95
96                 /* Sanity check */
97                 if ( i > bits ) {
98                         DBGC ( hubdev, "HUB %s underlength interrupt:\n",
99                                hubdev->name );
100                         DBGC_HDA ( hubdev, 0, iobuf->data, iob_len ( iobuf ) );
101                         goto done;
102                 }
103
104                 /* Report port status change if applicable */
105                 if ( data[ i / 8 ] & ( 1 << ( i % 8 ) ) ) {
106                         DBGC2 ( hubdev, "HUB %s port %d status changed\n",
107                                 hubdev->name, i );
108                         usb_port_changed ( usb_port ( hub, i ) );
109                 }
110         }
111
112  done:
113         /* Start refill process */
114         process_add ( &hubdev->refill );
115 }
116
117 /** Interrupt endpoint operations */
118 static struct usb_endpoint_driver_operations usb_hub_intr_operations = {
119         .complete = hub_complete,
120 };
121
122 /**
123  * Open hub
124  *
125  * @v hub               USB hub
126  * @ret rc              Return status code
127  */
128 static int hub_open ( struct usb_hub *hub ) {
129         struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
130         struct usb_device *usb = hubdev->usb;
131         unsigned int i;
132         int rc;
133
134         /* Ensure ports are powered */
135         for ( i = 1 ; i <= hub->ports ; i++ ) {
136                 if ( ( rc = usb_hub_set_port_feature ( usb, i,
137                                                        USB_HUB_PORT_POWER,
138                                                        0 ) ) != 0 ) {
139                         DBGC ( hubdev, "HUB %s port %d could not apply power: "
140                                "%s\n", hubdev->name, i, strerror ( rc ) );
141                         goto err_power;
142                 }
143         }
144
145         /* Open interrupt endpoint */
146         if ( ( rc = usb_endpoint_open ( &hubdev->intr ) ) != 0 ) {
147                 DBGC ( hubdev, "HUB %s could not register interrupt: %s\n",
148                        hubdev->name, strerror ( rc ) );
149                 goto err_open;
150         }
151
152         /* Start refill process */
153         process_add ( &hubdev->refill );
154
155         /* Refill interrupt ring */
156         hub_refill ( hubdev );
157
158         return 0;
159
160         usb_endpoint_close ( &hubdev->intr );
161  err_open:
162  err_power:
163         return rc;
164 }
165
166 /**
167  * Close hub
168  *
169  * @v hub               USB hub
170  */
171 static void hub_close ( struct usb_hub *hub ) {
172         struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
173
174         /* Close interrupt endpoint */
175         usb_endpoint_close ( &hubdev->intr );
176
177         /* Stop refill process */
178         process_del ( &hubdev->refill );
179 }
180
181 /**
182  * Enable port
183  *
184  * @v hub               USB hub
185  * @v port              USB port
186  * @ret rc              Return status code
187  */
188 static int hub_enable ( struct usb_hub *hub, struct usb_port *port ) {
189         struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
190         struct usb_device *usb = hubdev->usb;
191         struct usb_hub_port_status status;
192         unsigned int current;
193         unsigned int i;
194         int rc;
195
196         /* Initiate reset if applicable */
197         if ( ( hub->protocol < USB_PROTO_3_0 ) &&
198              ( ( rc = usb_hub_set_port_feature ( usb, port->address,
199                                                  USB_HUB_PORT_RESET, 0 ) )!=0)){
200                 DBGC ( hubdev, "HUB %s port %d could not initiate reset: %s\n",
201                        hubdev->name, port->address, strerror ( rc ) );
202                 return rc;
203         }
204
205         /* Wait for port to become enabled */
206         for ( i = 0 ; i < USB_HUB_ENABLE_MAX_WAIT_MS ; i++ ) {
207
208                 /* Check for port being enabled */
209                 if ( ( rc = usb_hub_get_port_status ( usb, port->address,
210                                                       &status ) ) != 0 ) {
211                         DBGC ( hubdev, "HUB %s port %d could not get status: "
212                                "%s\n", hubdev->name, port->address,
213                                strerror ( rc ) );
214                         return rc;
215                 }
216                 current = le16_to_cpu ( status.current );
217                 if ( current & ( 1 << USB_HUB_PORT_ENABLE ) )
218                         return 0;
219
220                 /* Delay */
221                 mdelay ( 1 );
222         }
223
224         DBGC ( hubdev, "HUB %s port %d timed out waiting for enable\n",
225                hubdev->name, port->address );
226         return -ETIMEDOUT;
227 }
228
229 /**
230  * Disable port
231  *
232  * @v hub               USB hub
233  * @v port              USB port
234  * @ret rc              Return status code
235  */
236 static int hub_disable ( struct usb_hub *hub, struct usb_port *port ) {
237         struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
238         struct usb_device *usb = hubdev->usb;
239         int rc;
240
241         /* Disable port */
242         if ( ( rc = usb_hub_clear_port_feature ( usb, port->address,
243                                                  USB_HUB_PORT_ENABLE, 0 ) )!=0){
244                 DBGC ( hubdev, "HUB %s port %d could not disable: %s\n",
245                        hubdev->name, port->address, strerror ( rc ) );
246                 return rc;
247         }
248
249         return 0;
250 }
251
252 /**
253  * Clear port status change bits
254  *
255  * @v hubdev            USB hub device
256  * @v port              Port number
257  * @v changed           Port status change bits
258  * @ret rc              Return status code
259  */
260 static int hub_clear_changes ( struct usb_hub_device *hubdev,
261                                unsigned int port, uint16_t changed ) {
262         struct usb_device *usb = hubdev->usb;
263         unsigned int bit;
264         unsigned int feature;
265         int rc;
266
267         /* Clear each set bit */
268         for ( bit = 0 ; bit < 16 ; bit++ ) {
269
270                 /* Skip unset bits */
271                 if ( ! ( changed & ( 1 << bit ) ) )
272                         continue;
273
274                 /* Skip unused features */
275                 feature = USB_HUB_C_FEATURE ( bit );
276                 if ( ! ( hubdev->features & ( 1 << feature ) ) )
277                         continue;
278
279                 /* Clear bit */
280                 if ( ( rc = usb_hub_clear_port_feature ( usb, port,
281                                                          feature, 0 ) ) != 0 ) {
282                         DBGC ( hubdev, "HUB %s port %d could not clear feature "
283                                "%d: %s\n", hubdev->name, port, feature,
284                                strerror ( rc ) );
285                         return rc;
286                 }
287         }
288
289         return 0;
290 }
291
292 /**
293  * Update port speed
294  *
295  * @v hub               USB hub
296  * @v port              USB port
297  * @ret rc              Return status code
298  */
299 static int hub_speed ( struct usb_hub *hub, struct usb_port *port ) {
300         struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
301         struct usb_device *usb = hubdev->usb;
302         struct usb_hub_port_status status;
303         unsigned int current;
304         unsigned int changed;
305         int rc;
306
307         /* Get port status */
308         if ( ( rc = usb_hub_get_port_status ( usb, port->address,
309                                               &status ) ) != 0 ) {
310                 DBGC ( hubdev, "HUB %s port %d could not get status: %s\n",
311                        hubdev->name, port->address, strerror ( rc ) );
312                 return rc;
313         }
314         current = le16_to_cpu ( status.current );
315         changed = le16_to_cpu ( status.changed );
316         DBGC2 ( hubdev, "HUB %s port %d status is %04x:%04x\n",
317                 hubdev->name, port->address, changed, current );
318
319         /* Update port speed */
320         if ( current & ( 1 << USB_HUB_PORT_CONNECTION ) ) {
321                 if ( hub->protocol >= USB_PROTO_3_0 ) {
322                         port->speed = USB_SPEED_SUPER;
323                 } else if ( current & ( 1 << USB_HUB_PORT_LOW_SPEED ) ) {
324                         port->speed = USB_SPEED_LOW;
325                 } else if ( current & ( 1 << USB_HUB_PORT_HIGH_SPEED ) ) {
326                         port->speed = USB_SPEED_HIGH;
327                 } else {
328                         port->speed = USB_SPEED_FULL;
329                 }
330         } else {
331                 port->speed = USB_SPEED_NONE;
332         }
333
334         /* Record disconnections */
335         port->disconnected |= ( changed & ( 1 << USB_HUB_PORT_CONNECTION ) );
336
337         /* Clear port status change bits */
338         if ( ( rc = hub_clear_changes ( hubdev, port->address, changed ) ) != 0)
339                 return rc;
340
341         return 0;
342 }
343
344 /**
345  * Clear transaction translator buffer
346  *
347  * @v hub               USB hub
348  * @v port              USB port
349  * @v ep                USB endpoint
350  * @ret rc              Return status code
351  */
352 static int hub_clear_tt ( struct usb_hub *hub, struct usb_port *port,
353                           struct usb_endpoint *ep ) {
354         struct usb_hub_device *hubdev = usb_hub_get_drvdata ( hub );
355         struct usb_device *usb = hubdev->usb;
356         int rc;
357
358         /* Clear transaction translator buffer.  All hubs must support
359          * single-TT operation; we simplify our code by supporting
360          * only this configuration.
361          */
362         if ( ( rc = usb_hub_clear_tt_buffer ( usb, ep->usb->address,
363                                               ep->address, ep->attributes,
364                                               USB_HUB_TT_SINGLE ) ) != 0 ) {
365                 DBGC ( hubdev, "HUB %s port %d could not clear TT buffer: %s\n",
366                        hubdev->name, port->address, strerror ( rc ) );
367                 return rc;
368         }
369
370         return 0;
371 }
372
373 /** USB hub operations */
374 static struct usb_hub_driver_operations hub_operations = {
375         .open = hub_open,
376         .close = hub_close,
377         .enable = hub_enable,
378         .disable = hub_disable,
379         .speed = hub_speed,
380         .clear_tt = hub_clear_tt,
381 };
382
383 /**
384  * Probe USB hub
385  *
386  * @v func              USB function
387  * @v config            Configuration descriptor
388  * @ret rc              Return status code
389  */
390 static int hub_probe ( struct usb_function *func,
391                        struct usb_configuration_descriptor *config ) {
392         struct usb_device *usb = func->usb;
393         struct usb_bus *bus = usb->port->hub->bus;
394         struct usb_hub_device *hubdev;
395         struct usb_interface_descriptor *interface;
396         union usb_hub_descriptor desc;
397         unsigned int depth;
398         unsigned int ports;
399         int enhanced;
400         int rc;
401
402         /* Allocate and initialise structure */
403         hubdev = zalloc ( sizeof ( *hubdev ) );
404         if ( ! hubdev ) {
405                 rc = -ENOMEM;
406                 goto err_alloc;
407         }
408         enhanced = ( usb->port->protocol >= USB_PROTO_3_0 );
409         hubdev->name = func->name;
410         hubdev->usb = usb;
411         hubdev->features =
412                 ( enhanced ? USB_HUB_FEATURES_ENHANCED : USB_HUB_FEATURES );
413         usb_endpoint_init ( &hubdev->intr, usb, &usb_hub_intr_operations );
414         usb_refill_init ( &hubdev->intr, 0, USB_HUB_INTR_FILL );
415         process_init_stopped ( &hubdev->refill, &hub_refill_desc, NULL );
416
417         /* Locate hub interface descriptor */
418         interface = usb_interface_descriptor ( config, func->interface[0], 0 );
419         if ( ! interface ) {
420                 DBGC ( hubdev, "HUB %s has no interface descriptor\n",
421                        hubdev->name );
422                 rc = -EINVAL;
423                 goto err_interface;
424         }
425
426         /* Locate interrupt endpoint descriptor */
427         if ( ( rc = usb_endpoint_described ( &hubdev->intr, config, interface,
428                                              USB_INTERRUPT_IN, 0 ) ) != 0 ) {
429                 DBGC ( hubdev, "HUB %s could not describe interrupt endpoint: "
430                        "%s\n", hubdev->name, strerror ( rc ) );
431                 goto err_endpoint;
432         }
433
434         /* Set hub depth */
435         depth = usb_depth ( usb );
436         if ( enhanced ) {
437                 if ( ( rc = usb_hub_set_hub_depth ( usb, depth ) ) != 0 ) {
438                         DBGC ( hubdev, "HUB %s could not set hub depth to %d: "
439                                "%s\n", hubdev->name, depth, strerror ( rc ) );
440                         goto err_set_hub_depth;
441                 }
442         }
443
444         /* Get hub descriptor */
445         if ( ( rc = usb_hub_get_descriptor ( usb, enhanced, &desc ) ) != 0 ) {
446                 DBGC ( hubdev, "HUB %s could not get hub descriptor: %s\n",
447                        hubdev->name, strerror ( rc ) );
448                 goto err_hub_descriptor;
449         }
450         ports = desc.basic.ports;
451         DBGC ( hubdev, "HUB %s has %d ports at depth %d%s\n", hubdev->name,
452                ports, depth, ( enhanced ? " (enhanced)" : "" ) );
453
454         /* Allocate hub */
455         hubdev->hub = alloc_usb_hub ( bus, usb, ports, &hub_operations );
456         if ( ! hubdev->hub ) {
457                 rc = -ENOMEM;
458                 goto err_alloc_hub;
459         }
460         usb_hub_set_drvdata ( hubdev->hub, hubdev );
461
462         /* Register hub */
463         if ( ( rc = register_usb_hub ( hubdev->hub ) ) != 0 ) {
464                 DBGC ( hubdev, "HUB %s could not register: %s\n",
465                        hubdev->name, strerror ( rc ) );
466                 goto err_register_hub;
467         }
468
469         usb_func_set_drvdata ( func, hubdev );
470         return 0;
471
472         unregister_usb_hub ( hubdev->hub );
473  err_register_hub:
474         free_usb_hub ( hubdev->hub );
475  err_alloc_hub:
476  err_hub_descriptor:
477  err_set_hub_depth:
478  err_endpoint:
479  err_interface:
480         free ( hubdev );
481  err_alloc:
482         return rc;
483 }
484
485 /**
486  * Remove USB hub
487  *
488  * @v func              USB function
489  * @ret rc              Return status code
490  */
491 static void hub_remove ( struct usb_function *func ) {
492         struct usb_hub_device *hubdev = usb_func_get_drvdata ( func );
493         struct usb_hub *hub = hubdev->hub;
494         struct usb_device *usb = hubdev->usb;
495         struct usb_port *port;
496         unsigned int i;
497
498         /* If hub has been unplugged, mark all ports as unplugged */
499         if ( usb->port->speed == USB_SPEED_NONE ) {
500                 for ( i = 1 ; i <= hub->ports ; i++ ) {
501                         port = usb_port ( hub, i );
502                         port->speed = USB_SPEED_NONE;
503                 }
504         }
505
506         /* Unregister hub */
507         unregister_usb_hub ( hubdev->hub );
508         assert ( ! process_running ( &hubdev->refill ) );
509
510         /* Free hub */
511         free_usb_hub ( hubdev->hub );
512
513         /* Free hub device */
514         free ( hubdev );
515 }
516
517 /** USB hub device IDs */
518 static struct usb_device_id hub_ids[] = {
519         {
520                 .name = "hub-1",
521                 .vendor = USB_ANY_ID,
522                 .product = USB_ANY_ID,
523                 .class = {
524                         .class = USB_CLASS_HUB,
525                         .subclass = 0,
526                         .protocol = 0,
527                 },
528         },
529         {
530                 .name = "hub-2",
531                 .vendor = USB_ANY_ID,
532                 .product = USB_ANY_ID,
533                 .class = {
534                         .class = USB_CLASS_HUB,
535                         .subclass = 0,
536                         .protocol = 1,
537                 },
538         },
539 };
540
541 /** USB hub driver */
542 struct usb_driver usb_hub_driver __usb_driver = {
543         .ids = hub_ids,
544         .id_count = ( sizeof ( hub_ids ) / sizeof ( hub_ids[0] ) ),
545         .probe = hub_probe,
546         .remove = hub_remove,
547 };