These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / drivers / net / ecm.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 <stdint.h>
27 #include <errno.h>
28 #include <ipxe/netdevice.h>
29 #include <ipxe/ethernet.h>
30 #include <ipxe/if_ether.h>
31 #include <ipxe/base16.h>
32 #include <ipxe/profile.h>
33 #include <ipxe/usb.h>
34 #include "ecm.h"
35
36 /** @file
37  *
38  * CDC-ECM USB Ethernet driver
39  *
40  */
41
42 /** Interrupt completion profiler */
43 static struct profiler ecm_intr_profiler __profiler =
44         { .name = "ecm.intr" };
45
46 /** Bulk IN completion profiler */
47 static struct profiler ecm_in_profiler __profiler =
48         { .name = "ecm.in" };
49
50 /** Bulk OUT profiler */
51 static struct profiler ecm_out_profiler __profiler =
52         { .name = "ecm.out" };
53
54 /******************************************************************************
55  *
56  * Ethernet functional descriptor
57  *
58  ******************************************************************************
59  */
60
61 /**
62  * Locate Ethernet functional descriptor
63  *
64  * @v config            Configuration descriptor
65  * @v interface         Interface descriptor
66  * @ret desc            Descriptor, or NULL if not found
67  */
68 struct ecm_ethernet_descriptor *
69 ecm_ethernet_descriptor ( struct usb_configuration_descriptor *config,
70                           struct usb_interface_descriptor *interface ) {
71         struct ecm_ethernet_descriptor *desc;
72
73         for_each_interface_descriptor ( desc, config, interface ) {
74                 if ( ( desc->header.type == USB_CS_INTERFACE_DESCRIPTOR ) &&
75                      ( desc->subtype == CDC_SUBTYPE_ETHERNET ) )
76                         return desc;
77         }
78         return NULL;
79 }
80
81 /**
82  * Get hardware MAC address
83  *
84  * @v usb               USB device
85  * @v desc              Ethernet functional descriptor
86  * @v hw_addr           Hardware address to fill in
87  * @ret rc              Return status code
88  */
89 int ecm_fetch_mac ( struct usb_device *usb,
90                     struct ecm_ethernet_descriptor *desc, uint8_t *hw_addr ) {
91         char buf[ base16_encoded_len ( ETH_ALEN ) + 1 /* NUL */ ];
92         int len;
93         int rc;
94
95         /* Fetch MAC address string */
96         len = usb_get_string_descriptor ( usb, desc->mac, 0, buf,
97                                           sizeof ( buf ) );
98         if ( len < 0 ) {
99                 rc = len;
100                 return rc;
101         }
102
103         /* Sanity check */
104         if ( len != ( ( int ) ( sizeof ( buf ) - 1 /* NUL */ ) ) )
105                 return -EINVAL;
106
107         /* Decode MAC address */
108         len = base16_decode ( buf, hw_addr, ETH_ALEN );
109         if ( len < 0 ) {
110                 rc = len;
111                 return rc;
112         }
113
114         return 0;
115 }
116
117 /******************************************************************************
118  *
119  * CDC-ECM communications interface
120  *
121  ******************************************************************************
122  */
123
124 /**
125  * Complete interrupt transfer
126  *
127  * @v ep                USB endpoint
128  * @v iobuf             I/O buffer
129  * @v rc                Completion status code
130  */
131 static void ecm_intr_complete ( struct usb_endpoint *ep,
132                                 struct io_buffer *iobuf, int rc ) {
133         struct ecm_device *ecm = container_of ( ep, struct ecm_device,
134                                                 usbnet.intr );
135         struct net_device *netdev = ecm->netdev;
136         struct usb_setup_packet *message;
137         size_t len = iob_len ( iobuf );
138
139         /* Profile completions */
140         profile_start ( &ecm_intr_profiler );
141
142         /* Ignore packets cancelled when the endpoint closes */
143         if ( ! ep->open )
144                 goto ignore;
145
146         /* Drop packets with errors */
147         if ( rc != 0 ) {
148                 DBGC ( ecm, "ECM %p interrupt failed: %s\n",
149                        ecm, strerror ( rc ) );
150                 DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
151                 goto error;
152         }
153
154         /* Extract message header */
155         if ( len < sizeof ( *message ) ) {
156                 DBGC ( ecm, "ECM %p underlength interrupt:\n", ecm );
157                 DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
158                 rc = -EINVAL;
159                 goto error;
160         }
161         message = iobuf->data;
162
163         /* Parse message header */
164         switch ( message->request ) {
165
166         case cpu_to_le16 ( CDC_NETWORK_CONNECTION ) :
167                 if ( message->value && ! netdev_link_ok ( netdev ) ) {
168                         DBGC ( ecm, "ECM %p link up\n", ecm );
169                         netdev_link_up ( netdev );
170                 } else if ( netdev_link_ok ( netdev ) && ! message->value ) {
171                         DBGC ( ecm, "ECM %p link down\n", ecm );
172                         netdev_link_down ( netdev );
173                 }
174                 break;
175
176         case cpu_to_le16 ( CDC_CONNECTION_SPEED_CHANGE ) :
177                 /* Ignore */
178                 break;
179
180         default:
181                 DBGC ( ecm, "ECM %p unrecognised interrupt:\n", ecm );
182                 DBGC_HDA ( ecm, 0, iobuf->data, iob_len ( iobuf ) );
183                 rc = -ENOTSUP;
184                 goto error;
185         }
186
187         /* Free I/O buffer */
188         free_iob ( iobuf );
189         profile_stop ( &ecm_intr_profiler );
190
191         return;
192
193  error:
194         netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
195  ignore:
196         free_iob ( iobuf );
197         return;
198 }
199
200 /** Interrupt endpoint operations */
201 static struct usb_endpoint_driver_operations ecm_intr_operations = {
202         .complete = ecm_intr_complete,
203 };
204
205 /******************************************************************************
206  *
207  * CDC-ECM data interface
208  *
209  ******************************************************************************
210  */
211
212 /**
213  * Complete bulk IN transfer
214  *
215  * @v ep                USB endpoint
216  * @v iobuf             I/O buffer
217  * @v rc                Completion status code
218  */
219 static void ecm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
220                               int rc ) {
221         struct ecm_device *ecm = container_of ( ep, struct ecm_device,
222                                                 usbnet.in );
223         struct net_device *netdev = ecm->netdev;
224
225         /* Profile receive completions */
226         profile_start ( &ecm_in_profiler );
227
228         /* Ignore packets cancelled when the endpoint closes */
229         if ( ! ep->open )
230                 goto ignore;
231
232         /* Record USB errors against the network device */
233         if ( rc != 0 ) {
234                 DBGC ( ecm, "ECM %p bulk IN failed: %s\n",
235                        ecm, strerror ( rc ) );
236                 goto error;
237         }
238
239         /* Hand off to network stack */
240         netdev_rx ( netdev, iob_disown ( iobuf ) );
241
242         profile_stop ( &ecm_in_profiler );
243         return;
244
245  error:
246         netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
247  ignore:
248         free_iob ( iobuf );
249 }
250
251 /** Bulk IN endpoint operations */
252 static struct usb_endpoint_driver_operations ecm_in_operations = {
253         .complete = ecm_in_complete,
254 };
255
256 /**
257  * Transmit packet
258  *
259  * @v ecm               CDC-ECM device
260  * @v iobuf             I/O buffer
261  * @ret rc              Return status code
262  */
263 static int ecm_out_transmit ( struct ecm_device *ecm,
264                               struct io_buffer *iobuf ) {
265         int rc;
266
267         /* Profile transmissions */
268         profile_start ( &ecm_out_profiler );
269
270         /* Enqueue I/O buffer */
271         if ( ( rc = usb_stream ( &ecm->usbnet.out, iobuf, 1 ) ) != 0 )
272                 return rc;
273
274         profile_stop ( &ecm_out_profiler );
275         return 0;
276 }
277
278 /**
279  * Complete bulk OUT transfer
280  *
281  * @v ep                USB endpoint
282  * @v iobuf             I/O buffer
283  * @v rc                Completion status code
284  */
285 static void ecm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
286                                int rc ) {
287         struct ecm_device *ecm = container_of ( ep, struct ecm_device,
288                                                 usbnet.out );
289         struct net_device *netdev = ecm->netdev;
290
291         /* Report TX completion */
292         netdev_tx_complete_err ( netdev, iobuf, rc );
293 }
294
295 /** Bulk OUT endpoint operations */
296 static struct usb_endpoint_driver_operations ecm_out_operations = {
297         .complete = ecm_out_complete,
298 };
299
300 /******************************************************************************
301  *
302  * Network device interface
303  *
304  ******************************************************************************
305  */
306
307 /**
308  * Open network device
309  *
310  * @v netdev            Network device
311  * @ret rc              Return status code
312  */
313 static int ecm_open ( struct net_device *netdev ) {
314         struct ecm_device *ecm = netdev->priv;
315         struct usb_device *usb = ecm->usb;
316         unsigned int filter;
317         int rc;
318
319         /* Open USB network device */
320         if ( ( rc = usbnet_open ( &ecm->usbnet ) ) != 0 ) {
321                 DBGC ( ecm, "ECM %p could not open: %s\n",
322                        ecm, strerror ( rc ) );
323                 goto err_open;
324         }
325
326         /* Set packet filter */
327         filter = ( ECM_PACKET_TYPE_PROMISCUOUS |
328                    ECM_PACKET_TYPE_ALL_MULTICAST |
329                    ECM_PACKET_TYPE_DIRECTED |
330                    ECM_PACKET_TYPE_BROADCAST );
331         if ( ( rc = usb_control ( usb, ECM_SET_ETHERNET_PACKET_FILTER,
332                                   filter, ecm->usbnet.comms, NULL, 0 ) ) != 0 ){
333                 DBGC ( ecm, "ECM %p could not set packet filter: %s\n",
334                        ecm, strerror ( rc ) );
335                 goto err_set_filter;
336         }
337
338         return 0;
339
340  err_set_filter:
341         usbnet_close ( &ecm->usbnet );
342  err_open:
343         return rc;
344 }
345
346 /**
347  * Close network device
348  *
349  * @v netdev            Network device
350  */
351 static void ecm_close ( struct net_device *netdev ) {
352         struct ecm_device *ecm = netdev->priv;
353
354         /* Close USB network device */
355         usbnet_close ( &ecm->usbnet );
356 }
357
358 /**
359  * Transmit packet
360  *
361  * @v netdev            Network device
362  * @v iobuf             I/O buffer
363  * @ret rc              Return status code
364  */
365 static int ecm_transmit ( struct net_device *netdev,
366                           struct io_buffer *iobuf ) {
367         struct ecm_device *ecm = netdev->priv;
368         int rc;
369
370         /* Transmit packet */
371         if ( ( rc = ecm_out_transmit ( ecm, iobuf ) ) != 0 )
372                 return rc;
373
374         return 0;
375 }
376
377 /**
378  * Poll for completed and received packets
379  *
380  * @v netdev            Network device
381  */
382 static void ecm_poll ( struct net_device *netdev ) {
383         struct ecm_device *ecm = netdev->priv;
384         int rc;
385
386         /* Poll USB bus */
387         usb_poll ( ecm->bus );
388
389         /* Refill endpoints */
390         if ( ( rc = usbnet_refill ( &ecm->usbnet ) ) != 0 )
391                 netdev_rx_err ( netdev, NULL, rc );
392 }
393
394 /** CDC-ECM network device operations */
395 static struct net_device_operations ecm_operations = {
396         .open           = ecm_open,
397         .close          = ecm_close,
398         .transmit       = ecm_transmit,
399         .poll           = ecm_poll,
400 };
401
402 /******************************************************************************
403  *
404  * USB interface
405  *
406  ******************************************************************************
407  */
408
409 /**
410  * Probe device
411  *
412  * @v func              USB function
413  * @v config            Configuration descriptor
414  * @ret rc              Return status code
415  */
416 static int ecm_probe ( struct usb_function *func,
417                        struct usb_configuration_descriptor *config ) {
418         struct usb_device *usb = func->usb;
419         struct net_device *netdev;
420         struct ecm_device *ecm;
421         struct usb_interface_descriptor *comms;
422         struct ecm_ethernet_descriptor *ethernet;
423         int rc;
424
425         /* Allocate and initialise structure */
426         netdev = alloc_etherdev ( sizeof ( *ecm ) );
427         if ( ! netdev ) {
428                 rc = -ENOMEM;
429                 goto err_alloc;
430         }
431         netdev_init ( netdev, &ecm_operations );
432         netdev->dev = &func->dev;
433         ecm = netdev->priv;
434         memset ( ecm, 0, sizeof ( *ecm ) );
435         ecm->usb = usb;
436         ecm->bus = usb->port->hub->bus;
437         ecm->netdev = netdev;
438         usbnet_init ( &ecm->usbnet, func, &ecm_intr_operations,
439                       &ecm_in_operations, &ecm_out_operations );
440         usb_refill_init ( &ecm->usbnet.intr, 0, ECM_INTR_MAX_FILL );
441         usb_refill_init ( &ecm->usbnet.in, ECM_IN_MTU, ECM_IN_MAX_FILL );
442         DBGC ( ecm, "ECM %p on %s\n", ecm, func->name );
443
444         /* Describe USB network device */
445         if ( ( rc = usbnet_describe ( &ecm->usbnet, config ) ) != 0 ) {
446                 DBGC ( ecm, "ECM %p could not describe: %s\n",
447                        ecm, strerror ( rc ) );
448                 goto err_describe;
449         }
450
451         /* Locate Ethernet descriptor */
452         comms = usb_interface_descriptor ( config, ecm->usbnet.comms, 0 );
453         assert ( comms != NULL );
454         ethernet = ecm_ethernet_descriptor ( config, comms );
455         if ( ! ethernet ) {
456                 DBGC ( ecm, "ECM %p has no Ethernet descriptor\n", ecm );
457                 rc = -EINVAL;
458                 goto err_ethernet;
459         }
460
461         /* Fetch MAC address */
462         if ( ( rc = ecm_fetch_mac ( usb, ethernet, netdev->hw_addr ) ) != 0 ) {
463                 DBGC ( ecm, "ECM %p could not fetch MAC address: %s\n",
464                        ecm, strerror ( rc ) );
465                 goto err_fetch_mac;
466         }
467
468         /* Register network device */
469         if ( ( rc = register_netdev ( netdev ) ) != 0 )
470                 goto err_register;
471
472         usb_func_set_drvdata ( func, ecm );
473         return 0;
474
475         unregister_netdev ( netdev );
476  err_register:
477  err_fetch_mac:
478  err_ethernet:
479  err_describe:
480         netdev_nullify ( netdev );
481         netdev_put ( netdev );
482  err_alloc:
483         return rc;
484 }
485
486 /**
487  * Remove device
488  *
489  * @v func              USB function
490  */
491 static void ecm_remove ( struct usb_function *func ) {
492         struct ecm_device *ecm = usb_func_get_drvdata ( func );
493         struct net_device *netdev = ecm->netdev;
494
495         unregister_netdev ( netdev );
496         netdev_nullify ( netdev );
497         netdev_put ( netdev );
498 }
499
500 /** CDC-ECM device IDs */
501 static struct usb_device_id ecm_ids[] = {
502         {
503                 .name = "cdc-ecm",
504                 .vendor = USB_ANY_ID,
505                 .product = USB_ANY_ID,
506                 .class = {
507                         .class = USB_CLASS_CDC,
508                         .subclass = USB_SUBCLASS_CDC_ECM,
509                         .protocol = 0,
510                 },
511         },
512 };
513
514 /** CDC-ECM driver */
515 struct usb_driver ecm_driver __usb_driver = {
516         .ids = ecm_ids,
517         .id_count = ( sizeof ( ecm_ids ) / sizeof ( ecm_ids[0] ) ),
518         .probe = ecm_probe,
519         .remove = ecm_remove,
520 };