You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  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. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <ipxe/netdevice.h>
  23. #include <ipxe/ethernet.h>
  24. #include <ipxe/if_ether.h>
  25. #include <ipxe/profile.h>
  26. #include <ipxe/usb.h>
  27. #include "ecm.h"
  28. #include "ncm.h"
  29. /** @file
  30. *
  31. * CDC-NCM USB Ethernet driver
  32. *
  33. */
  34. /** Ring refill profiler */
  35. static struct profiler ncm_refill_profiler __profiler =
  36. { .name = "ncm.refill" };
  37. /** Interrupt completion profiler */
  38. static struct profiler ncm_intr_profiler __profiler =
  39. { .name = "ncm.intr" };
  40. /** Bulk IN completion profiler */
  41. static struct profiler ncm_in_profiler __profiler =
  42. { .name = "ncm.in" };
  43. /** Bulk IN per-datagram profiler */
  44. static struct profiler ncm_in_datagram_profiler __profiler =
  45. { .name = "ncm.in_dgram" };
  46. /** Bulk OUT profiler */
  47. static struct profiler ncm_out_profiler __profiler =
  48. { .name = "ncm.out" };
  49. /******************************************************************************
  50. *
  51. * Ring management
  52. *
  53. ******************************************************************************
  54. */
  55. /**
  56. * Transcribe receive ring name (for debugging)
  57. *
  58. * @v ncm CDC-NCM device
  59. * @v ring Receive ring
  60. * @ret name Receive ring name
  61. */
  62. static inline const char * ncm_rx_name ( struct ncm_device *ncm,
  63. struct ncm_rx_ring *ring ) {
  64. if ( ring == &ncm->intr ) {
  65. return "interrupt";
  66. } else if ( ring == &ncm->in ) {
  67. return "bulk IN";
  68. } else {
  69. return "UNKNOWN";
  70. }
  71. }
  72. /**
  73. * Allocate receive ring buffers
  74. *
  75. * @v ncm CDC-NCM device
  76. * @v ring Receive ring
  77. * @v mtu I/O buffer size
  78. * @v count Number of I/O buffers
  79. * @ret rc Return status code
  80. */
  81. static int ncm_rx_alloc ( struct ncm_device *ncm, struct ncm_rx_ring *ring,
  82. size_t mtu, unsigned int count ) {
  83. struct io_buffer *iobuf;
  84. struct io_buffer *tmp;
  85. unsigned int i;
  86. int rc;
  87. /* Initialise ring */
  88. ring->mtu = mtu;
  89. INIT_LIST_HEAD ( &ring->list );
  90. /* Allocate I/O buffers */
  91. for ( i = 0 ; i < count ; i++ ) {
  92. iobuf = alloc_iob ( mtu );
  93. if ( ! iobuf ) {
  94. DBGC ( ncm, "NCM %p could not allocate %dx %zd-byte "
  95. "buffers for %s\n", ncm, count, mtu,
  96. ncm_rx_name ( ncm, ring ) );
  97. rc = -ENOMEM;
  98. goto err_alloc;
  99. }
  100. list_add ( &iobuf->list, &ring->list );
  101. }
  102. return 0;
  103. err_alloc:
  104. list_for_each_entry_safe ( iobuf, tmp, &ring->list, list ) {
  105. list_del ( &iobuf->list );
  106. free_iob ( iobuf );
  107. }
  108. return rc;
  109. }
  110. /**
  111. * Refill receive ring
  112. *
  113. * @v ncm CDC-NCM device
  114. * @v ring Receive ring
  115. * @ret rc Return status code
  116. */
  117. static int ncm_rx_refill ( struct ncm_device *ncm, struct ncm_rx_ring *ring ) {
  118. struct io_buffer *iobuf;
  119. int rc;
  120. /* Enqueue any recycled I/O buffers */
  121. while ( ( iobuf = list_first_entry ( &ring->list, struct io_buffer,
  122. list ) ) ) {
  123. /* Profile refill */
  124. profile_start ( &ncm_refill_profiler );
  125. /* Reset size */
  126. iob_put ( iobuf, ( ring->mtu - iob_len ( iobuf ) ) );
  127. /* Enqueue I/O buffer */
  128. if ( ( rc = usb_stream ( &ring->ep, iobuf, 0 ) ) != 0 ) {
  129. DBGC ( ncm, "NCM %p could not enqueue %s: %s\n", ncm,
  130. ncm_rx_name ( ncm, ring ), strerror ( rc ) );
  131. /* Leave in recycled list and wait for next refill */
  132. return rc;
  133. }
  134. /* Remove from recycled list */
  135. list_del ( &iobuf->list );
  136. profile_stop ( &ncm_refill_profiler );
  137. }
  138. return 0;
  139. }
  140. /**
  141. * Recycle receive buffer
  142. *
  143. * @v ncm CDC-NCM device
  144. * @v ring Receive ring
  145. * @v iobuf I/O buffer
  146. */
  147. static inline void ncm_rx_recycle ( struct ncm_device *ncm __unused,
  148. struct ncm_rx_ring *ring,
  149. struct io_buffer *iobuf ) {
  150. /* Add to recycled list */
  151. list_add_tail ( &iobuf->list, &ring->list );
  152. }
  153. /**
  154. * Free receive ring
  155. *
  156. * @v ncm CDC-NCM device
  157. * @v ring Receive ring
  158. */
  159. static void ncm_rx_free ( struct ncm_device *ncm __unused,
  160. struct ncm_rx_ring *ring ) {
  161. struct io_buffer *iobuf;
  162. struct io_buffer *tmp;
  163. /* Free I/O buffers */
  164. list_for_each_entry_safe ( iobuf, tmp, &ring->list, list ) {
  165. list_del ( &iobuf->list );
  166. free_iob ( iobuf );
  167. }
  168. }
  169. /******************************************************************************
  170. *
  171. * CDC-NCM communications interface
  172. *
  173. ******************************************************************************
  174. */
  175. /**
  176. * Complete interrupt transfer
  177. *
  178. * @v ep USB endpoint
  179. * @v iobuf I/O buffer
  180. * @v rc Completion status code
  181. */
  182. static void ncm_intr_complete ( struct usb_endpoint *ep,
  183. struct io_buffer *iobuf, int rc ) {
  184. struct ncm_device *ncm = container_of ( ep, struct ncm_device, intr.ep);
  185. struct net_device *netdev = ncm->netdev;
  186. struct usb_setup_packet *message;
  187. size_t len = iob_len ( iobuf );
  188. /* Profile completions */
  189. profile_start ( &ncm_intr_profiler );
  190. /* Ignore packets cancelled when the endpoint closes */
  191. if ( ! ep->open )
  192. goto done;
  193. /* Ignore packets with errors */
  194. if ( rc != 0 ) {
  195. DBGC ( ncm, "NCM %p interrupt failed: %s\n",
  196. ncm, strerror ( rc ) );
  197. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  198. goto done;
  199. }
  200. /* Extract message header */
  201. if ( len < sizeof ( *message ) ) {
  202. DBGC ( ncm, "NCM %p underlength interrupt:\n", ncm );
  203. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  204. goto done;
  205. }
  206. message = iobuf->data;
  207. /* Parse message header */
  208. switch ( message->request ) {
  209. case cpu_to_le16 ( CDC_NETWORK_CONNECTION ) :
  210. if ( message->value ) {
  211. DBGC ( ncm, "NCM %p link up\n", ncm );
  212. netdev_link_up ( netdev );
  213. } else {
  214. DBGC ( ncm, "NCM %p link down\n", ncm );
  215. netdev_link_down ( netdev );
  216. }
  217. break;
  218. case cpu_to_le16 ( CDC_CONNECTION_SPEED_CHANGE ) :
  219. /* Ignore */
  220. break;
  221. default:
  222. DBGC ( ncm, "NCM %p unrecognised interrupt:\n", ncm );
  223. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  224. break;
  225. }
  226. done:
  227. /* Recycle buffer */
  228. ncm_rx_recycle ( ncm, &ncm->intr, iobuf );
  229. profile_stop ( &ncm_intr_profiler );
  230. }
  231. /** Interrupt endpoint operations */
  232. static struct usb_endpoint_driver_operations ncm_intr_operations = {
  233. .complete = ncm_intr_complete,
  234. };
  235. /**
  236. * Open communications interface
  237. *
  238. * @v ncm CDC-NCM device
  239. * @ret rc Return status code
  240. */
  241. static int ncm_comms_open ( struct ncm_device *ncm ) {
  242. int rc;
  243. /* Allocate I/O buffers */
  244. if ( ( rc = ncm_rx_alloc ( ncm, &ncm->intr, ncm->intr.ep.mtu,
  245. NCM_INTR_COUNT ) ) != 0 ) {
  246. DBGC ( ncm, "NCM %p could not allocate RX buffers: %s\n",
  247. ncm, strerror ( rc ) );
  248. goto err_alloc;
  249. }
  250. /* Open interrupt endpoint */
  251. if ( ( rc = usb_endpoint_open ( &ncm->intr.ep ) ) != 0 ) {
  252. DBGC ( ncm, "NCM %p could not open interrupt: %s\n",
  253. ncm, strerror ( rc ) );
  254. goto err_open;
  255. }
  256. return 0;
  257. usb_endpoint_close ( &ncm->intr.ep );
  258. err_open:
  259. ncm_rx_free ( ncm, &ncm->intr );
  260. err_alloc:
  261. return rc;
  262. }
  263. /**
  264. * Close communications interface
  265. *
  266. * @v ncm CDC-NCM device
  267. */
  268. static void ncm_comms_close ( struct ncm_device *ncm ) {
  269. /* Close interrupt endpoint */
  270. usb_endpoint_close ( &ncm->intr.ep );
  271. /* Free I/O buffers */
  272. ncm_rx_free ( ncm, &ncm->intr );
  273. }
  274. /******************************************************************************
  275. *
  276. * CDC-NCM data interface
  277. *
  278. ******************************************************************************
  279. */
  280. /**
  281. * Allocate bulk IN receive ring buffers
  282. *
  283. * @v ncm CDC-NCM device
  284. * @ret rc Return status code
  285. */
  286. static int ncm_in_alloc ( struct ncm_device *ncm ) {
  287. size_t mtu;
  288. unsigned int count;
  289. int rc;
  290. /* Some devices have a very small number of internal buffers,
  291. * and rely on being able to pack multiple packets into each
  292. * buffer. We therefore want to use large buffers if
  293. * possible. However, large allocations have a reasonable
  294. * chance of failure, especially if this is not the first or
  295. * only device to be opened.
  296. *
  297. * We therefore attempt to find a usable buffer size, starting
  298. * large and working downwards until allocation succeeds.
  299. * Smaller buffers will still work, albeit with a higher
  300. * chance of packet loss and so lower overall throughput.
  301. */
  302. for ( mtu = ncm->mtu ; mtu >= NCM_MIN_NTB_INPUT_SIZE ; mtu >>= 1 ) {
  303. /* Attempt allocation at this MTU */
  304. if ( mtu > NCM_MAX_NTB_INPUT_SIZE )
  305. continue;
  306. count = ( NCM_IN_MIN_SIZE / mtu );
  307. if ( count < NCM_IN_MIN_COUNT )
  308. count = NCM_IN_MIN_COUNT;
  309. if ( ( count * mtu ) > NCM_IN_MAX_SIZE )
  310. continue;
  311. if ( ( rc = ncm_rx_alloc ( ncm, &ncm->in, mtu, count ) ) != 0 )
  312. continue;
  313. DBGC ( ncm, "NCM %p using %dx %zd-byte buffers for bulk IN\n",
  314. ncm, count, mtu );
  315. return 0;
  316. }
  317. DBGC ( ncm, "NCM %p could not allocate bulk IN buffers\n", ncm );
  318. return -ENOMEM;
  319. }
  320. /**
  321. * Complete bulk IN transfer
  322. *
  323. * @v ep USB endpoint
  324. * @v iobuf I/O buffer
  325. * @v rc Completion status code
  326. */
  327. static void ncm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
  328. int rc ) {
  329. struct ncm_device *ncm = container_of ( ep, struct ncm_device, in.ep );
  330. struct net_device *netdev = ncm->netdev;
  331. struct ncm_transfer_header *nth;
  332. struct ncm_datagram_pointer *ndp;
  333. struct ncm_datagram_descriptor *desc;
  334. struct io_buffer *pkt;
  335. unsigned int remaining;
  336. size_t ndp_offset;
  337. size_t ndp_len;
  338. size_t pkt_offset;
  339. size_t pkt_len;
  340. size_t headroom;
  341. size_t len;
  342. /* Profile overall bulk IN completion */
  343. profile_start ( &ncm_in_profiler );
  344. /* Ignore packets cancelled when the endpoint closes */
  345. if ( ! ep->open )
  346. goto ignore;
  347. /* Record USB errors against the network device */
  348. if ( rc != 0 ) {
  349. DBGC ( ncm, "NCM %p bulk IN failed: %s\n",
  350. ncm, strerror ( rc ) );
  351. goto drop;
  352. }
  353. /* Locate transfer header */
  354. len = iob_len ( iobuf );
  355. if ( sizeof ( *nth ) > len ) {
  356. DBGC ( ncm, "NCM %p packet too short for NTH:\n", ncm );
  357. goto error;
  358. }
  359. nth = iobuf->data;
  360. /* Locate datagram pointer */
  361. ndp_offset = le16_to_cpu ( nth->offset );
  362. if ( ( ndp_offset + sizeof ( *ndp ) ) > len ) {
  363. DBGC ( ncm, "NCM %p packet too short for NDP:\n", ncm );
  364. goto error;
  365. }
  366. ndp = ( iobuf->data + ndp_offset );
  367. ndp_len = le16_to_cpu ( ndp->header_len );
  368. if ( ndp_len < offsetof ( typeof ( *ndp ), desc ) ) {
  369. DBGC ( ncm, "NCM %p NDP header length too short:\n", ncm );
  370. goto error;
  371. }
  372. if ( ( ndp_offset + ndp_len ) > len ) {
  373. DBGC ( ncm, "NCM %p packet too short for NDP:\n", ncm );
  374. goto error;
  375. }
  376. /* Process datagrams */
  377. remaining = ( ( ndp_len - offsetof ( typeof ( *ndp ), desc ) ) /
  378. sizeof ( ndp->desc[0] ) );
  379. for ( desc = ndp->desc ; remaining && desc->offset ; remaining-- ) {
  380. /* Profile individual datagrams */
  381. profile_start ( &ncm_in_datagram_profiler );
  382. /* Locate datagram */
  383. pkt_offset = le16_to_cpu ( desc->offset );
  384. pkt_len = le16_to_cpu ( desc->len );
  385. if ( pkt_len < ETH_HLEN ) {
  386. DBGC ( ncm, "NCM %p underlength datagram:\n", ncm );
  387. goto error;
  388. }
  389. if ( ( pkt_offset + pkt_len ) > len ) {
  390. DBGC ( ncm, "NCM %p datagram exceeds packet:\n", ncm );
  391. goto error;
  392. }
  393. /* Move to next descriptor */
  394. desc++;
  395. /* Copy data to a new I/O buffer. Our USB buffers may
  396. * be very large and so we choose to recycle the
  397. * buffers directly rather than attempt reallocation
  398. * while the device is running. We therefore copy the
  399. * data to a new I/O buffer even if this is the only
  400. * (or last) packet within the buffer.
  401. *
  402. * We reserve enough space at the start of each buffer
  403. * to allow for our own transmission header, to
  404. * support protocols such as ARP which may modify the
  405. * received packet and reuse the same I/O buffer for
  406. * transmission.
  407. */
  408. headroom = ( sizeof ( struct ncm_ntb_header ) +
  409. ncm->out.padding );
  410. pkt = alloc_iob ( headroom + pkt_len );
  411. if ( ! pkt ) {
  412. /* Record error and continue */
  413. netdev_rx_err ( netdev, NULL, -ENOMEM );
  414. continue;
  415. }
  416. iob_reserve ( pkt, headroom );
  417. memcpy ( iob_put ( pkt, pkt_len ),
  418. ( iobuf->data + pkt_offset ), pkt_len );
  419. /* Strip CRC, if present */
  420. if ( ndp->magic & cpu_to_le32 ( NCM_DATAGRAM_POINTER_MAGIC_CRC))
  421. iob_unput ( pkt, 4 /* CRC32 */ );
  422. /* Hand off to network stack */
  423. netdev_rx ( netdev, pkt );
  424. profile_stop ( &ncm_in_datagram_profiler );
  425. }
  426. /* Recycle I/O buffer */
  427. ncm_rx_recycle ( ncm, &ncm->in, iobuf );
  428. profile_stop ( &ncm_in_profiler );
  429. return;
  430. error:
  431. rc = -EIO;
  432. drop:
  433. /* Record error against network device */
  434. DBGC_HDA ( ncm, 0, iobuf->data, iob_len ( iobuf ) );
  435. netdev_rx_err ( netdev, NULL, rc );
  436. ignore:
  437. ncm_rx_recycle ( ncm, &ncm->in, iobuf );
  438. }
  439. /** Bulk IN endpoint operations */
  440. static struct usb_endpoint_driver_operations ncm_in_operations = {
  441. .complete = ncm_in_complete,
  442. };
  443. /**
  444. * Transmit packet
  445. *
  446. * @v ncm CDC-NCM device
  447. * @v iobuf I/O buffer
  448. * @ret rc Return status code
  449. */
  450. static int ncm_out_transmit ( struct ncm_device *ncm,
  451. struct io_buffer *iobuf ) {
  452. struct ncm_ntb_header *header;
  453. size_t len = iob_len ( iobuf );
  454. size_t header_len = ( sizeof ( *header ) + ncm->out.padding );
  455. int rc;
  456. /* Profile transmissions */
  457. profile_start ( &ncm_out_profiler );
  458. /* Prepend header */
  459. if ( ( rc = iob_ensure_headroom ( iobuf, header_len ) ) != 0 )
  460. return rc;
  461. header = iob_push ( iobuf, header_len );
  462. /* Populate header */
  463. header->nth.magic = cpu_to_le32 ( NCM_TRANSFER_HEADER_MAGIC );
  464. header->nth.header_len = cpu_to_le16 ( sizeof ( header->nth ) );
  465. header->nth.sequence = cpu_to_le16 ( ncm->out.sequence );
  466. header->nth.len = cpu_to_le16 ( iob_len ( iobuf ) );
  467. header->nth.offset =
  468. cpu_to_le16 ( offsetof ( typeof ( *header ), ndp ) );
  469. header->ndp.magic = cpu_to_le32 ( NCM_DATAGRAM_POINTER_MAGIC );
  470. header->ndp.header_len = cpu_to_le16 ( sizeof ( header->ndp ) +
  471. sizeof ( header->desc ) );
  472. header->ndp.offset = cpu_to_le16 ( 0 );
  473. header->desc[0].offset = cpu_to_le16 ( header_len );
  474. header->desc[0].len = cpu_to_le16 ( len );
  475. memset ( &header->desc[1], 0, sizeof ( header->desc[1] ) );
  476. /* Enqueue I/O buffer */
  477. if ( ( rc = usb_stream ( &ncm->out.ep, iobuf, 0 ) ) != 0 )
  478. return rc;
  479. /* Increment sequence number */
  480. ncm->out.sequence++;
  481. profile_stop ( &ncm_out_profiler );
  482. return 0;
  483. }
  484. /**
  485. * Complete bulk OUT transfer
  486. *
  487. * @v ep USB endpoint
  488. * @v iobuf I/O buffer
  489. * @v rc Completion status code
  490. */
  491. static void ncm_out_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
  492. int rc ) {
  493. struct ncm_device *ncm = container_of ( ep, struct ncm_device, out.ep );
  494. struct net_device *netdev = ncm->netdev;
  495. /* Report TX completion */
  496. netdev_tx_complete_err ( netdev, iobuf, rc );
  497. }
  498. /** Bulk OUT endpoint operations */
  499. static struct usb_endpoint_driver_operations ncm_out_operations = {
  500. .complete = ncm_out_complete,
  501. };
  502. /**
  503. * Open data interface
  504. *
  505. * @v ncm CDC-NCM device
  506. * @ret rc Return status code
  507. */
  508. static int ncm_data_open ( struct ncm_device *ncm ) {
  509. struct usb_device *usb = ncm->usb;
  510. struct ncm_set_ntb_input_size size;
  511. int rc;
  512. /* Allocate I/O buffers */
  513. if ( ( rc = ncm_in_alloc ( ncm ) ) != 0 )
  514. goto err_alloc;
  515. /* Set maximum input size */
  516. memset ( &size, 0, sizeof ( size ) );
  517. size.mtu = cpu_to_le32 ( ncm->in.mtu );
  518. if ( ( rc = usb_control ( usb, NCM_SET_NTB_INPUT_SIZE, 0, ncm->comms,
  519. &size, sizeof ( size ) ) ) != 0 ) {
  520. DBGC ( ncm, "NCM %p could not set input size to %zd: %s\n",
  521. ncm, ncm->in.mtu, strerror ( rc ) );
  522. goto err_set_ntb_input_size;
  523. }
  524. /* Select alternate setting for data interface */
  525. if ( ( rc = usb_set_interface ( usb, ncm->data,
  526. NCM_DATA_ALTERNATE ) ) != 0 ) {
  527. DBGC ( ncm, "NCM %p could not set alternate interface: %s\n",
  528. ncm, strerror ( rc ) );
  529. goto err_set_interface;
  530. }
  531. /* Open bulk IN endpoint */
  532. if ( ( rc = usb_endpoint_open ( &ncm->in.ep ) ) != 0 ) {
  533. DBGC ( ncm, "NCM %p could not open bulk IN: %s\n",
  534. ncm, strerror ( rc ) );
  535. goto err_open_in;
  536. }
  537. /* Open bulk OUT endpoint */
  538. if ( ( rc = usb_endpoint_open ( &ncm->out.ep ) ) != 0 ) {
  539. DBGC ( ncm, "NCM %p could not open bulk OUT: %s\n",
  540. ncm, strerror ( rc ) );
  541. goto err_open_out;
  542. }
  543. /* Reset transmit sequence number */
  544. ncm->out.sequence = 0;
  545. return 0;
  546. usb_endpoint_close ( &ncm->out.ep );
  547. err_open_out:
  548. usb_endpoint_close ( &ncm->in.ep );
  549. err_open_in:
  550. usb_set_interface ( usb, ncm->data, 0 );
  551. err_set_interface:
  552. err_set_ntb_input_size:
  553. ncm_rx_free ( ncm, &ncm->in );
  554. err_alloc:
  555. return rc;
  556. }
  557. /**
  558. * Close data interface
  559. *
  560. * @v ncm CDC-NCM device
  561. */
  562. static void ncm_data_close ( struct ncm_device *ncm ) {
  563. struct usb_device *usb = ncm->usb;
  564. /* Close endpoints */
  565. usb_endpoint_close ( &ncm->out.ep );
  566. usb_endpoint_close ( &ncm->in.ep );
  567. /* Reset data interface */
  568. usb_set_interface ( usb, ncm->data, 0 );
  569. /* Free I/O buffers */
  570. ncm_rx_free ( ncm, &ncm->in );
  571. }
  572. /******************************************************************************
  573. *
  574. * Network device interface
  575. *
  576. ******************************************************************************
  577. */
  578. /**
  579. * Open network device
  580. *
  581. * @v netdev Network device
  582. * @ret rc Return status code
  583. */
  584. static int ncm_open ( struct net_device *netdev ) {
  585. struct ncm_device *ncm = netdev->priv;
  586. int rc;
  587. /* Reset sequence number */
  588. ncm->out.sequence = 0;
  589. /* Open communications interface */
  590. if ( ( rc = ncm_comms_open ( ncm ) ) != 0 )
  591. goto err_comms_open;
  592. /* Refill interrupt ring */
  593. if ( ( rc = ncm_rx_refill ( ncm, &ncm->intr ) ) != 0 )
  594. goto err_intr_refill;
  595. /* Open data interface */
  596. if ( ( rc = ncm_data_open ( ncm ) ) != 0 )
  597. goto err_data_open;
  598. /* Refill bulk IN ring */
  599. if ( ( rc = ncm_rx_refill ( ncm, &ncm->in ) ) != 0 )
  600. goto err_in_refill;
  601. return 0;
  602. err_in_refill:
  603. ncm_data_close ( ncm );
  604. err_data_open:
  605. err_intr_refill:
  606. ncm_comms_close ( ncm );
  607. err_comms_open:
  608. return rc;
  609. }
  610. /**
  611. * Close network device
  612. *
  613. * @v netdev Network device
  614. */
  615. static void ncm_close ( struct net_device *netdev ) {
  616. struct ncm_device *ncm = netdev->priv;
  617. /* Close data interface */
  618. ncm_data_close ( ncm );
  619. /* Close communications interface */
  620. ncm_comms_close ( ncm );
  621. }
  622. /**
  623. * Transmit packet
  624. *
  625. * @v netdev Network device
  626. * @v iobuf I/O buffer
  627. * @ret rc Return status code
  628. */
  629. static int ncm_transmit ( struct net_device *netdev,
  630. struct io_buffer *iobuf ) {
  631. struct ncm_device *ncm = netdev->priv;
  632. int rc;
  633. /* Transmit packet */
  634. if ( ( rc = ncm_out_transmit ( ncm, iobuf ) ) != 0 )
  635. return rc;
  636. return 0;
  637. }
  638. /**
  639. * Poll for completed and received packets
  640. *
  641. * @v netdev Network device
  642. */
  643. static void ncm_poll ( struct net_device *netdev ) {
  644. struct ncm_device *ncm = netdev->priv;
  645. int rc;
  646. /* Poll USB bus */
  647. usb_poll ( ncm->bus );
  648. /* Refill interrupt ring */
  649. if ( ( rc = ncm_rx_refill ( ncm, &ncm->intr ) ) != 0 )
  650. netdev_rx_err ( netdev, NULL, rc );
  651. /* Refill bulk IN ring */
  652. if ( ( rc = ncm_rx_refill ( ncm, &ncm->in ) ) != 0 )
  653. netdev_rx_err ( netdev, NULL, rc );
  654. }
  655. /** CDC-NCM network device operations */
  656. static struct net_device_operations ncm_operations = {
  657. .open = ncm_open,
  658. .close = ncm_close,
  659. .transmit = ncm_transmit,
  660. .poll = ncm_poll,
  661. };
  662. /******************************************************************************
  663. *
  664. * USB interface
  665. *
  666. ******************************************************************************
  667. */
  668. /**
  669. * Probe device
  670. *
  671. * @v func USB function
  672. * @v config Configuration descriptor
  673. * @ret rc Return status code
  674. */
  675. static int ncm_probe ( struct usb_function *func,
  676. struct usb_configuration_descriptor *config ) {
  677. struct usb_device *usb = func->usb;
  678. struct net_device *netdev;
  679. struct ncm_device *ncm;
  680. struct usb_interface_descriptor *comms;
  681. struct usb_interface_descriptor *data;
  682. struct ecm_ethernet_descriptor *ethernet;
  683. struct ncm_ntb_parameters params;
  684. int rc;
  685. /* Allocate and initialise structure */
  686. netdev = alloc_etherdev ( sizeof ( *ncm ) );
  687. if ( ! netdev ) {
  688. rc = -ENOMEM;
  689. goto err_alloc;
  690. }
  691. netdev_init ( netdev, &ncm_operations );
  692. netdev->dev = &func->dev;
  693. ncm = netdev->priv;
  694. memset ( ncm, 0, sizeof ( *ncm ) );
  695. ncm->usb = usb;
  696. ncm->bus = usb->port->hub->bus;
  697. ncm->netdev = netdev;
  698. usb_endpoint_init ( &ncm->intr.ep, usb, &ncm_intr_operations );
  699. usb_endpoint_init ( &ncm->in.ep, usb, &ncm_in_operations );
  700. usb_endpoint_init ( &ncm->out.ep, usb, &ncm_out_operations );
  701. DBGC ( ncm, "NCM %p on %s\n", ncm, func->name );
  702. /* Identify interfaces */
  703. if ( func->count < NCM_INTERFACE_COUNT ) {
  704. DBGC ( ncm, "NCM %p has only %d interfaces\n",
  705. ncm, func->count );
  706. rc = -EINVAL;
  707. goto err_count;
  708. }
  709. ncm->comms = func->interface[NCM_INTERFACE_COMMS];
  710. ncm->data = func->interface[NCM_INTERFACE_DATA];
  711. /* Locate communications interface descriptor */
  712. comms = usb_interface_descriptor ( config, ncm->comms, 0 );
  713. if ( ! comms ) {
  714. DBGC ( ncm, "NCM %p has no communications interface\n", ncm );
  715. rc = -EINVAL;
  716. goto err_comms;
  717. }
  718. /* Locate data interface descriptor */
  719. data = usb_interface_descriptor ( config, ncm->data,
  720. NCM_DATA_ALTERNATE );
  721. if ( ! data ) {
  722. DBGC ( ncm, "NCM %p has no data interface\n", ncm );
  723. rc = -EINVAL;
  724. goto err_data;
  725. }
  726. /* Describe interrupt endpoint */
  727. if ( ( rc = usb_endpoint_described ( &ncm->intr.ep, config, comms,
  728. USB_INTERRUPT, 0 ) ) != 0 ) {
  729. DBGC ( ncm, "NCM %p could not describe interrupt endpoint: "
  730. "%s\n", ncm, strerror ( rc ) );
  731. goto err_interrupt;
  732. }
  733. /* Describe bulk IN endpoint */
  734. if ( ( rc = usb_endpoint_described ( &ncm->in.ep, config, data,
  735. USB_BULK_IN, 0 ) ) != 0 ) {
  736. DBGC ( ncm, "NCM %p could not describe bulk IN endpoint: "
  737. "%s\n", ncm, strerror ( rc ) );
  738. goto err_bulk_in;
  739. }
  740. /* Describe bulk OUT endpoint */
  741. if ( ( rc = usb_endpoint_described ( &ncm->out.ep, config, data,
  742. USB_BULK_OUT, 0 ) ) != 0 ) {
  743. DBGC ( ncm, "NCM %p could not describe bulk OUT endpoint: "
  744. "%s\n", ncm, strerror ( rc ) );
  745. goto err_bulk_out;
  746. }
  747. /* Locate Ethernet descriptor */
  748. ethernet = ecm_ethernet_descriptor ( config, comms );
  749. if ( ! ethernet ) {
  750. DBGC ( ncm, "NCM %p has no Ethernet descriptor\n", ncm );
  751. rc = -EINVAL;
  752. goto err_ethernet;
  753. }
  754. /* Fetch MAC address */
  755. if ( ( rc = ecm_fetch_mac ( usb, ethernet, netdev->hw_addr ) ) != 0 ) {
  756. DBGC ( ncm, "NCM %p could not fetch MAC address: %s\n",
  757. ncm, strerror ( rc ) );
  758. goto err_fetch_mac;
  759. }
  760. /* Get NTB parameters */
  761. if ( ( rc = usb_control ( usb, NCM_GET_NTB_PARAMETERS, 0, ncm->comms,
  762. &params, sizeof ( params ) ) ) != 0 ) {
  763. DBGC ( ncm, "NCM %p could not get NTB parameters: %s\n",
  764. ncm, strerror ( rc ) );
  765. goto err_ntb_parameters;
  766. }
  767. /* Get maximum supported input size */
  768. ncm->mtu = le32_to_cpu ( params.in.mtu );
  769. DBGC2 ( ncm, "NCM %p maximum IN size is %zd bytes\n", ncm, ncm->mtu );
  770. /* Calculate transmit padding */
  771. ncm->out.padding = ( ( le16_to_cpu ( params.out.remainder ) -
  772. sizeof ( struct ncm_ntb_header ) - ETH_HLEN ) &
  773. ( le16_to_cpu ( params.out.divisor ) - 1 ) );
  774. DBGC2 ( ncm, "NCM %p using %zd-byte transmit padding\n",
  775. ncm, ncm->out.padding );
  776. assert ( ( ( sizeof ( struct ncm_ntb_header ) + ncm->out.padding +
  777. ETH_HLEN ) % le16_to_cpu ( params.out.divisor ) ) ==
  778. le16_to_cpu ( params.out.remainder ) );
  779. /* Register network device */
  780. if ( ( rc = register_netdev ( netdev ) ) != 0 )
  781. goto err_register;
  782. usb_func_set_drvdata ( func, ncm );
  783. return 0;
  784. unregister_netdev ( netdev );
  785. err_register:
  786. err_ntb_parameters:
  787. err_fetch_mac:
  788. err_ethernet:
  789. err_bulk_out:
  790. err_bulk_in:
  791. err_interrupt:
  792. err_data:
  793. err_comms:
  794. err_count:
  795. netdev_nullify ( netdev );
  796. netdev_put ( netdev );
  797. err_alloc:
  798. return rc;
  799. }
  800. /**
  801. * Remove device
  802. *
  803. * @v func USB function
  804. */
  805. static void ncm_remove ( struct usb_function *func ) {
  806. struct ncm_device *ncm = usb_func_get_drvdata ( func );
  807. struct net_device *netdev = ncm->netdev;
  808. unregister_netdev ( netdev );
  809. netdev_nullify ( netdev );
  810. netdev_put ( netdev );
  811. }
  812. /** CDC-NCM device IDs */
  813. static struct usb_device_id ncm_ids[] = {
  814. {
  815. .name = "cdc-ncm",
  816. .vendor = USB_ANY_ID,
  817. .product = USB_ANY_ID,
  818. .class = {
  819. .class = USB_CLASS_CDC,
  820. .subclass = USB_SUBCLASS_CDC_NCM,
  821. .protocol = 0,
  822. },
  823. },
  824. };
  825. /** CDC-NCM driver */
  826. struct usb_driver ncm_driver __usb_driver = {
  827. .ids = ncm_ids,
  828. .id_count = ( sizeof ( ncm_ids ) / sizeof ( ncm_ids[0] ) ),
  829. .probe = ncm_probe,
  830. .remove = ncm_remove,
  831. };