|
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
26
|
26
|
#include <ipxe/if_ether.h>
|
27
|
27
|
#include <ipxe/profile.h>
|
28
|
28
|
#include <ipxe/usb.h>
|
|
29
|
+#include <ipxe/usbnet.h>
|
29
|
30
|
#include "ecm.h"
|
30
|
31
|
#include "ncm.h"
|
31
|
32
|
|
|
@@ -67,7 +68,8 @@ static struct profiler ncm_out_profiler __profiler =
|
67
|
68
|
*/
|
68
|
69
|
static void ncm_intr_complete ( struct usb_endpoint *ep,
|
69
|
70
|
struct io_buffer *iobuf, int rc ) {
|
70
|
|
- struct ncm_device *ncm = container_of ( ep, struct ncm_device, intr );
|
|
71
|
+ struct ncm_device *ncm = container_of ( ep, struct ncm_device,
|
|
72
|
+ usbnet.intr );
|
71
|
73
|
struct net_device *netdev = ncm->netdev;
|
72
|
74
|
struct usb_setup_packet *message;
|
73
|
75
|
size_t len = iob_len ( iobuf );
|
|
@@ -137,43 +139,6 @@ static struct usb_endpoint_driver_operations ncm_intr_operations = {
|
137
|
139
|
.complete = ncm_intr_complete,
|
138
|
140
|
};
|
139
|
141
|
|
140
|
|
-/**
|
141
|
|
- * Open communications interface
|
142
|
|
- *
|
143
|
|
- * @v ncm CDC-NCM device
|
144
|
|
- * @ret rc Return status code
|
145
|
|
- */
|
146
|
|
-static int ncm_comms_open ( struct ncm_device *ncm ) {
|
147
|
|
- int rc;
|
148
|
|
-
|
149
|
|
- /* Open interrupt endpoint */
|
150
|
|
- if ( ( rc = usb_endpoint_open ( &ncm->intr ) ) != 0 ) {
|
151
|
|
- DBGC ( ncm, "NCM %p could not open interrupt: %s\n",
|
152
|
|
- ncm, strerror ( rc ) );
|
153
|
|
- goto err_open;
|
154
|
|
- }
|
155
|
|
-
|
156
|
|
- /* Refill interrupt endpoint */
|
157
|
|
- usb_refill ( &ncm->intr );
|
158
|
|
-
|
159
|
|
- return 0;
|
160
|
|
-
|
161
|
|
- usb_endpoint_close ( &ncm->intr );
|
162
|
|
- err_open:
|
163
|
|
- return rc;
|
164
|
|
-}
|
165
|
|
-
|
166
|
|
-/**
|
167
|
|
- * Close communications interface
|
168
|
|
- *
|
169
|
|
- * @v ncm CDC-NCM device
|
170
|
|
- */
|
171
|
|
-static void ncm_comms_close ( struct ncm_device *ncm ) {
|
172
|
|
-
|
173
|
|
- /* Close interrupt endpoint */
|
174
|
|
- usb_endpoint_close ( &ncm->intr );
|
175
|
|
-}
|
176
|
|
-
|
177
|
142
|
/******************************************************************************
|
178
|
143
|
*
|
179
|
144
|
* CDC-NCM data interface
|
|
@@ -214,8 +179,8 @@ static int ncm_in_prefill ( struct ncm_device *ncm ) {
|
214
|
179
|
count = NCM_IN_MIN_COUNT;
|
215
|
180
|
if ( ( count * mtu ) > NCM_IN_MAX_SIZE )
|
216
|
181
|
continue;
|
217
|
|
- usb_refill_init ( &ncm->in, mtu, count );
|
218
|
|
- if ( ( rc = usb_prefill ( &ncm->in ) ) != 0 ) {
|
|
182
|
+ usb_refill_init ( &ncm->usbnet.in, mtu, count );
|
|
183
|
+ if ( ( rc = usb_prefill ( &ncm->usbnet.in ) ) != 0 ) {
|
219
|
184
|
DBGC ( ncm, "NCM %p could not prefill %dx %zd-byte "
|
220
|
185
|
"buffers for bulk IN\n", ncm, count, mtu );
|
221
|
186
|
continue;
|
|
@@ -239,7 +204,8 @@ static int ncm_in_prefill ( struct ncm_device *ncm ) {
|
239
|
204
|
*/
|
240
|
205
|
static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
241
|
206
|
int rc ) {
|
242
|
|
- struct ncm_device *ncm = container_of ( ep, struct ncm_device, in );
|
|
207
|
+ struct ncm_device *ncm = container_of ( ep, struct ncm_device,
|
|
208
|
+ usbnet.in );
|
243
|
209
|
struct net_device *netdev = ncm->netdev;
|
244
|
210
|
struct ncm_transfer_header *nth;
|
245
|
211
|
struct ncm_datagram_pointer *ndp;
|
|
@@ -355,7 +321,7 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
355
|
321
|
}
|
356
|
322
|
|
357
|
323
|
/* Recycle I/O buffer */
|
358
|
|
- usb_recycle ( &ncm->in, iobuf );
|
|
324
|
+ usb_recycle ( &ncm->usbnet.in, iobuf );
|
359
|
325
|
profile_stop ( &ncm_in_profiler );
|
360
|
326
|
|
361
|
327
|
return;
|
|
@@ -365,7 +331,7 @@ static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
365
|
331
|
DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
|
366
|
332
|
netdev_rx_err ( netdev, NULL, rc );
|
367
|
333
|
ignore:
|
368
|
|
- usb_recycle ( &ncm->in, iobuf );
|
|
334
|
+ usb_recycle ( &ncm->usbnet.in, iobuf );
|
369
|
335
|
}
|
370
|
336
|
|
371
|
337
|
/** Bulk IN endpoint operations */
|
|
@@ -411,7 +377,7 @@ static int ncm_out_transmit ( struct ncm_device *ncm,
|
411
|
377
|
memset ( &header->desc[1], 0, sizeof ( header->desc[1] ) );
|
412
|
378
|
|
413
|
379
|
/* Enqueue I/O buffer */
|
414
|
|
- if ( ( rc = usb_stream ( &ncm->out, iobuf, 0 ) ) != 0 )
|
|
380
|
+ if ( ( rc = usb_stream ( &ncm->usbnet.out, iobuf, 0 ) ) != 0 )
|
415
|
381
|
return rc;
|
416
|
382
|
|
417
|
383
|
/* Increment sequence number */
|
|
@@ -430,7 +396,8 @@ static int ncm_out_transmit ( struct ncm_device *ncm,
|
430
|
396
|
*/
|
431
|
397
|
static void ncm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
|
432
|
398
|
int rc ) {
|
433
|
|
- struct ncm_device *ncm = container_of ( ep, struct ncm_device, out );
|
|
399
|
+ struct ncm_device *ncm = container_of ( ep, struct ncm_device,
|
|
400
|
+ usbnet.out );
|
434
|
401
|
struct net_device *netdev = ncm->netdev;
|
435
|
402
|
|
436
|
403
|
/* Report TX completion */
|
|
@@ -442,128 +409,60 @@ static struct usb_endpoint_driver_operations ncm_out_operations = {
|
442
|
409
|
.complete = ncm_out_complete,
|
443
|
410
|
};
|
444
|
411
|
|
|
412
|
+/******************************************************************************
|
|
413
|
+ *
|
|
414
|
+ * Network device interface
|
|
415
|
+ *
|
|
416
|
+ ******************************************************************************
|
|
417
|
+ */
|
|
418
|
+
|
445
|
419
|
/**
|
446
|
|
- * Open data interface
|
|
420
|
+ * Open network device
|
447
|
421
|
*
|
448
|
|
- * @v ncm CDC-NCM device
|
|
422
|
+ * @v netdev Network device
|
449
|
423
|
* @ret rc Return status code
|
450
|
424
|
*/
|
451
|
|
-static int ncm_data_open ( struct ncm_device *ncm ) {
|
|
425
|
+static int ncm_open ( struct net_device *netdev ) {
|
|
426
|
+ struct ncm_device *ncm = netdev->priv;
|
452
|
427
|
struct usb_device *usb = ncm->usb;
|
453
|
428
|
struct ncm_set_ntb_input_size size;
|
454
|
429
|
int rc;
|
455
|
430
|
|
|
431
|
+ /* Reset sequence number */
|
|
432
|
+ ncm->sequence = 0;
|
|
433
|
+
|
456
|
434
|
/* Prefill I/O buffers */
|
457
|
435
|
if ( ( rc = ncm_in_prefill ( ncm ) ) != 0 )
|
458
|
436
|
goto err_prefill;
|
459
|
437
|
|
460
|
438
|
/* Set maximum input size */
|
461
|
439
|
memset ( &size, 0, sizeof ( size ) );
|
462
|
|
- size.mtu = cpu_to_le32 ( ncm->in.len );
|
463
|
|
- if ( ( rc = usb_control ( usb, NCM_SET_NTB_INPUT_SIZE, 0, ncm->comms,
|
464
|
|
- &size, sizeof ( size ) ) ) != 0 ) {
|
|
440
|
+ size.mtu = cpu_to_le32 ( ncm->usbnet.in.len );
|
|
441
|
+ if ( ( rc = usb_control ( usb, NCM_SET_NTB_INPUT_SIZE, 0,
|
|
442
|
+ ncm->usbnet.comms, &size,
|
|
443
|
+ sizeof ( size ) ) ) != 0 ) {
|
465
|
444
|
DBGC ( ncm, "NCM %p could not set input size to %zd: %s\n",
|
466
|
|
- ncm, ncm->in.mtu, strerror ( rc ) );
|
|
445
|
+ ncm, ncm->usbnet.in.len, strerror ( rc ) );
|
467
|
446
|
goto err_set_ntb_input_size;
|
468
|
447
|
}
|
469
|
448
|
|
470
|
|
- /* Select alternate setting for data interface */
|
471
|
|
- if ( ( rc = usb_set_interface ( usb, ncm->data,
|
472
|
|
- NCM_DATA_ALTERNATE ) ) != 0 ) {
|
473
|
|
- DBGC ( ncm, "NCM %p could not set alternate interface: %s\n",
|
474
|
|
- ncm, strerror ( rc ) );
|
475
|
|
- goto err_set_interface;
|
476
|
|
- }
|
477
|
|
-
|
478
|
|
- /* Open bulk IN endpoint */
|
479
|
|
- if ( ( rc = usb_endpoint_open ( &ncm->in ) ) != 0 ) {
|
480
|
|
- DBGC ( ncm, "NCM %p could not open bulk IN: %s\n",
|
481
|
|
- ncm, strerror ( rc ) );
|
482
|
|
- goto err_open_in;
|
483
|
|
- }
|
484
|
|
-
|
485
|
|
- /* Open bulk OUT endpoint */
|
486
|
|
- if ( ( rc = usb_endpoint_open ( &ncm->out ) ) != 0 ) {
|
487
|
|
- DBGC ( ncm, "NCM %p could not open bulk OUT: %s\n",
|
|
449
|
+ /* Open USB network device */
|
|
450
|
+ if ( ( rc = usbnet_open ( &ncm->usbnet ) ) != 0 ) {
|
|
451
|
+ DBGC ( ncm, "NCM %p could not open: %s\n",
|
488
|
452
|
ncm, strerror ( rc ) );
|
489
|
|
- goto err_open_out;
|
490
|
|
- }
|
491
|
|
-
|
492
|
|
- /* Refill bulk IN endpoint */
|
493
|
|
- if ( ( rc = usb_refill ( &ncm->in ) ) != 0 ) {
|
494
|
|
- DBGC ( ncm, "NCM %p could not refill bulk IN: %s\n",
|
495
|
|
- ncm, strerror ( rc ) );
|
496
|
|
- goto err_refill;
|
|
453
|
+ goto err_open;
|
497
|
454
|
}
|
498
|
455
|
|
499
|
456
|
return 0;
|
500
|
457
|
|
501
|
|
- err_refill:
|
502
|
|
- usb_endpoint_close ( &ncm->out );
|
503
|
|
- err_open_out:
|
504
|
|
- usb_endpoint_close ( &ncm->in );
|
505
|
|
- err_open_in:
|
506
|
|
- usb_set_interface ( usb, ncm->data, 0 );
|
507
|
|
- err_set_interface:
|
|
458
|
+ usbnet_close ( &ncm->usbnet );
|
|
459
|
+ err_open:
|
508
|
460
|
err_set_ntb_input_size:
|
509
|
|
- usb_flush ( &ncm->in );
|
|
461
|
+ usb_flush ( &ncm->usbnet.in );
|
510
|
462
|
err_prefill:
|
511
|
463
|
return rc;
|
512
|
464
|
}
|
513
|
465
|
|
514
|
|
-/**
|
515
|
|
- * Close data interface
|
516
|
|
- *
|
517
|
|
- * @v ncm CDC-NCM device
|
518
|
|
- */
|
519
|
|
-static void ncm_data_close ( struct ncm_device *ncm ) {
|
520
|
|
- struct usb_device *usb = ncm->usb;
|
521
|
|
-
|
522
|
|
- /* Close endpoints */
|
523
|
|
- usb_endpoint_close ( &ncm->out );
|
524
|
|
- usb_endpoint_close ( &ncm->in );
|
525
|
|
-
|
526
|
|
- /* Reset data interface */
|
527
|
|
- usb_set_interface ( usb, ncm->data, 0 );
|
528
|
|
-}
|
529
|
|
-
|
530
|
|
-/******************************************************************************
|
531
|
|
- *
|
532
|
|
- * Network device interface
|
533
|
|
- *
|
534
|
|
- ******************************************************************************
|
535
|
|
- */
|
536
|
|
-
|
537
|
|
-/**
|
538
|
|
- * Open network device
|
539
|
|
- *
|
540
|
|
- * @v netdev Network device
|
541
|
|
- * @ret rc Return status code
|
542
|
|
- */
|
543
|
|
-static int ncm_open ( struct net_device *netdev ) {
|
544
|
|
- struct ncm_device *ncm = netdev->priv;
|
545
|
|
- int rc;
|
546
|
|
-
|
547
|
|
- /* Reset sequence number */
|
548
|
|
- ncm->sequence = 0;
|
549
|
|
-
|
550
|
|
- /* Open communications interface */
|
551
|
|
- if ( ( rc = ncm_comms_open ( ncm ) ) != 0 )
|
552
|
|
- goto err_comms_open;
|
553
|
|
-
|
554
|
|
- /* Open data interface */
|
555
|
|
- if ( ( rc = ncm_data_open ( ncm ) ) != 0 )
|
556
|
|
- goto err_data_open;
|
557
|
|
-
|
558
|
|
- return 0;
|
559
|
|
-
|
560
|
|
- ncm_data_close ( ncm );
|
561
|
|
- err_data_open:
|
562
|
|
- ncm_comms_close ( ncm );
|
563
|
|
- err_comms_open:
|
564
|
|
- return rc;
|
565
|
|
-}
|
566
|
|
-
|
567
|
466
|
/**
|
568
|
467
|
* Close network device
|
569
|
468
|
*
|
|
@@ -572,11 +471,8 @@ static int ncm_open ( struct net_device *netdev ) {
|
572
|
471
|
static void ncm_close ( struct net_device *netdev ) {
|
573
|
472
|
struct ncm_device *ncm = netdev->priv;
|
574
|
473
|
|
575
|
|
- /* Close data interface */
|
576
|
|
- ncm_data_close ( ncm );
|
577
|
|
-
|
578
|
|
- /* Close communications interface */
|
579
|
|
- ncm_comms_close ( ncm );
|
|
474
|
+ /* Close USB network device */
|
|
475
|
+ usbnet_close ( &ncm->usbnet );
|
580
|
476
|
}
|
581
|
477
|
|
582
|
478
|
/**
|
|
@@ -610,13 +506,10 @@ static void ncm_poll ( struct net_device *netdev ) {
|
610
|
506
|
/* Poll USB bus */
|
611
|
507
|
usb_poll ( ncm->bus );
|
612
|
508
|
|
613
|
|
- /* Refill interrupt endpoint */
|
614
|
|
- if ( ( rc = usb_refill ( &ncm->intr ) ) != 0 )
|
|
509
|
+ /* Refill endpoints */
|
|
510
|
+ if ( ( rc = usbnet_refill ( &ncm->usbnet ) ) != 0 )
|
615
|
511
|
netdev_rx_err ( netdev, NULL, rc );
|
616
|
512
|
|
617
|
|
- /* Refill bulk IN endpoint */
|
618
|
|
- if ( ( rc = usb_refill ( &ncm->in ) ) != 0 )
|
619
|
|
- netdev_rx_err ( netdev, NULL, rc );
|
620
|
513
|
}
|
621
|
514
|
|
622
|
515
|
/** CDC-NCM network device operations */
|
|
@@ -647,7 +540,6 @@ static int ncm_probe ( struct usb_function *func,
|
647
|
540
|
struct net_device *netdev;
|
648
|
541
|
struct ncm_device *ncm;
|
649
|
542
|
struct usb_interface_descriptor *comms;
|
650
|
|
- struct usb_interface_descriptor *data;
|
651
|
543
|
struct ecm_ethernet_descriptor *ethernet;
|
652
|
544
|
struct ncm_ntb_parameters params;
|
653
|
545
|
int rc;
|
|
@@ -665,64 +557,21 @@ static int ncm_probe ( struct usb_function *func,
|
665
|
557
|
ncm->usb = usb;
|
666
|
558
|
ncm->bus = usb->port->hub->bus;
|
667
|
559
|
ncm->netdev = netdev;
|
668
|
|
- usb_endpoint_init ( &ncm->intr, usb, &ncm_intr_operations );
|
669
|
|
- usb_endpoint_init ( &ncm->in, usb, &ncm_in_operations );
|
670
|
|
- usb_endpoint_init ( &ncm->out, usb, &ncm_out_operations );
|
671
|
|
- usb_refill_init ( &ncm->intr, 0, NCM_INTR_COUNT );
|
|
560
|
+ usbnet_init ( &ncm->usbnet, func, &ncm_intr_operations,
|
|
561
|
+ &ncm_in_operations, &ncm_out_operations );
|
|
562
|
+ usb_refill_init ( &ncm->usbnet.intr, 0, NCM_INTR_COUNT );
|
672
|
563
|
DBGC ( ncm, "NCM %p on %s\n", ncm, func->name );
|
673
|
564
|
|
674
|
|
- /* Identify interfaces */
|
675
|
|
- if ( func->count < NCM_INTERFACE_COUNT ) {
|
676
|
|
- DBGC ( ncm, "NCM %p has only %d interfaces\n",
|
677
|
|
- ncm, func->count );
|
678
|
|
- rc = -EINVAL;
|
679
|
|
- goto err_count;
|
680
|
|
- }
|
681
|
|
- ncm->comms = func->interface[NCM_INTERFACE_COMMS];
|
682
|
|
- ncm->data = func->interface[NCM_INTERFACE_DATA];
|
683
|
|
-
|
684
|
|
- /* Locate communications interface descriptor */
|
685
|
|
- comms = usb_interface_descriptor ( config, ncm->comms, 0 );
|
686
|
|
- if ( ! comms ) {
|
687
|
|
- DBGC ( ncm, "NCM %p has no communications interface\n", ncm );
|
688
|
|
- rc = -EINVAL;
|
689
|
|
- goto err_comms;
|
690
|
|
- }
|
691
|
|
-
|
692
|
|
- /* Locate data interface descriptor */
|
693
|
|
- data = usb_interface_descriptor ( config, ncm->data,
|
694
|
|
- NCM_DATA_ALTERNATE );
|
695
|
|
- if ( ! data ) {
|
696
|
|
- DBGC ( ncm, "NCM %p has no data interface\n", ncm );
|
697
|
|
- rc = -EINVAL;
|
698
|
|
- goto err_data;
|
699
|
|
- }
|
700
|
|
-
|
701
|
|
- /* Describe interrupt endpoint */
|
702
|
|
- if ( ( rc = usb_endpoint_described ( &ncm->intr, config, comms,
|
703
|
|
- USB_INTERRUPT, 0 ) ) != 0 ) {
|
704
|
|
- DBGC ( ncm, "NCM %p could not describe interrupt endpoint: "
|
705
|
|
- "%s\n", ncm, strerror ( rc ) );
|
706
|
|
- goto err_interrupt;
|
707
|
|
- }
|
708
|
|
-
|
709
|
|
- /* Describe bulk IN endpoint */
|
710
|
|
- if ( ( rc = usb_endpoint_described ( &ncm->in, config, data,
|
711
|
|
- USB_BULK_IN, 0 ) ) != 0 ) {
|
712
|
|
- DBGC ( ncm, "NCM %p could not describe bulk IN endpoint: "
|
713
|
|
- "%s\n", ncm, strerror ( rc ) );
|
714
|
|
- goto err_bulk_in;
|
715
|
|
- }
|
716
|
|
-
|
717
|
|
- /* Describe bulk OUT endpoint */
|
718
|
|
- if ( ( rc = usb_endpoint_described ( &ncm->out, config, data,
|
719
|
|
- USB_BULK_OUT, 0 ) ) != 0 ) {
|
720
|
|
- DBGC ( ncm, "NCM %p could not describe bulk OUT endpoint: "
|
721
|
|
- "%s\n", ncm, strerror ( rc ) );
|
722
|
|
- goto err_bulk_out;
|
|
565
|
+ /* Describe USB network device */
|
|
566
|
+ if ( ( rc = usbnet_describe ( &ncm->usbnet, config ) ) != 0 ) {
|
|
567
|
+ DBGC ( ncm, "NCM %p could not describe: %s\n",
|
|
568
|
+ ncm, strerror ( rc ) );
|
|
569
|
+ goto err_describe;
|
723
|
570
|
}
|
724
|
571
|
|
725
|
572
|
/* Locate Ethernet descriptor */
|
|
573
|
+ comms = usb_interface_descriptor ( config, ncm->usbnet.comms, 0 );
|
|
574
|
+ assert ( comms != NULL );
|
726
|
575
|
ethernet = ecm_ethernet_descriptor ( config, comms );
|
727
|
576
|
if ( ! ethernet ) {
|
728
|
577
|
DBGC ( ncm, "NCM %p has no Ethernet descriptor\n", ncm );
|
|
@@ -738,8 +587,9 @@ static int ncm_probe ( struct usb_function *func,
|
738
|
587
|
}
|
739
|
588
|
|
740
|
589
|
/* Get NTB parameters */
|
741
|
|
- if ( ( rc = usb_control ( usb, NCM_GET_NTB_PARAMETERS, 0, ncm->comms,
|
742
|
|
- ¶ms, sizeof ( params ) ) ) != 0 ) {
|
|
590
|
+ if ( ( rc = usb_control ( usb, NCM_GET_NTB_PARAMETERS, 0,
|
|
591
|
+ ncm->usbnet.comms, ¶ms,
|
|
592
|
+ sizeof ( params ) ) ) != 0 ) {
|
743
|
593
|
DBGC ( ncm, "NCM %p could not get NTB parameters: %s\n",
|
744
|
594
|
ncm, strerror ( rc ) );
|
745
|
595
|
goto err_ntb_parameters;
|
|
@@ -771,12 +621,7 @@ static int ncm_probe ( struct usb_function *func,
|
771
|
621
|
err_ntb_parameters:
|
772
|
622
|
err_fetch_mac:
|
773
|
623
|
err_ethernet:
|
774
|
|
- err_bulk_out:
|
775
|
|
- err_bulk_in:
|
776
|
|
- err_interrupt:
|
777
|
|
- err_data:
|
778
|
|
- err_comms:
|
779
|
|
- err_count:
|
|
624
|
+ err_describe:
|
780
|
625
|
netdev_nullify ( netdev );
|
781
|
626
|
netdev_put ( netdev );
|
782
|
627
|
err_alloc:
|