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.

snpnet.c 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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 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 <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <ipxe/iobuf.h>
  25. #include <ipxe/netdevice.h>
  26. #include <ipxe/ethernet.h>
  27. #include <ipxe/vsprintf.h>
  28. #include <ipxe/efi/efi.h>
  29. #include <ipxe/efi/Protocol/SimpleNetwork.h>
  30. #include <ipxe/efi/efi_driver.h>
  31. #include <ipxe/efi/efi_utils.h>
  32. #include "snpnet.h"
  33. /** @file
  34. *
  35. * SNP NIC driver
  36. *
  37. */
  38. /** An SNP NIC */
  39. struct snp_nic {
  40. /** EFI device */
  41. struct efi_device *efidev;
  42. /** Simple network protocol */
  43. EFI_SIMPLE_NETWORK_PROTOCOL *snp;
  44. /** Generic device */
  45. struct device dev;
  46. /** Maximum packet size
  47. *
  48. * This is calculated as the sum of MediaHeaderSize and
  49. * MaxPacketSize, and may therefore be an overestimate.
  50. */
  51. size_t mtu;
  52. /** Current transmit buffer */
  53. struct io_buffer *txbuf;
  54. /** Current receive buffer */
  55. struct io_buffer *rxbuf;
  56. };
  57. /** Maximum number of received packets per poll */
  58. #define SNP_RX_QUOTA 4
  59. /**
  60. * Format SNP MAC address (for debugging)
  61. *
  62. * @v mac MAC address
  63. * @v len Length of MAC address
  64. * @ret text MAC address as text
  65. */
  66. static const char * snpnet_mac_text ( EFI_MAC_ADDRESS *mac, size_t len ) {
  67. static char buf[ sizeof ( *mac ) * 3 /* "xx:" or "xx\0" */ ];
  68. size_t used = 0;
  69. unsigned int i;
  70. for ( i = 0 ; i < len ; i++ ) {
  71. used += ssnprintf ( &buf[used], ( sizeof ( buf ) - used ),
  72. "%s%02x", ( used ? ":" : "" ),
  73. mac->Addr[i] );
  74. }
  75. return buf;
  76. }
  77. /**
  78. * Dump SNP mode information (for debugging)
  79. *
  80. * @v netdev Network device
  81. */
  82. static void snpnet_dump_mode ( struct net_device *netdev ) {
  83. struct snp_nic *snp = netdev_priv ( netdev );
  84. EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
  85. size_t mac_len = mode->HwAddressSize;
  86. unsigned int i;
  87. /* Do nothing unless debugging is enabled */
  88. if ( ! DBG_EXTRA )
  89. return;
  90. DBGC2 ( snp, "SNP %s st %d type %d hdr %d pkt %d rxflt %#x/%#x%s "
  91. "nvram %d acc %d mcast %d/%d\n", netdev->name, mode->State,
  92. mode->IfType, mode->MediaHeaderSize, mode->MaxPacketSize,
  93. mode->ReceiveFilterSetting, mode->ReceiveFilterMask,
  94. ( mode->MultipleTxSupported ? " multitx" : "" ),
  95. mode->NvRamSize, mode->NvRamAccessSize,
  96. mode->MCastFilterCount, mode->MaxMCastFilterCount );
  97. DBGC2 ( snp, "SNP %s hw %s", netdev->name,
  98. snpnet_mac_text ( &mode->PermanentAddress, mac_len ) );
  99. DBGC2 ( snp, " addr %s%s",
  100. snpnet_mac_text ( &mode->CurrentAddress, mac_len ),
  101. ( mode->MacAddressChangeable ? "" : "(f)" ) );
  102. DBGC2 ( snp, " bcast %s\n",
  103. snpnet_mac_text ( &mode->BroadcastAddress, mac_len ) );
  104. for ( i = 0 ; i < mode->MCastFilterCount ; i++ ) {
  105. DBGC2 ( snp, "SNP %s mcast %s\n", netdev->name,
  106. snpnet_mac_text ( &mode->MCastFilter[i], mac_len ) );
  107. }
  108. DBGC2 ( snp, "SNP %s media %s\n", netdev->name,
  109. ( mode->MediaPresentSupported ?
  110. ( mode->MediaPresent ? "present" : "not present" ) :
  111. "presence not supported" ) );
  112. }
  113. /**
  114. * Check link state
  115. *
  116. * @v netdev Network device
  117. */
  118. static void snpnet_check_link ( struct net_device *netdev ) {
  119. struct snp_nic *snp = netdev_priv ( netdev );
  120. EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
  121. /* Do nothing unless media presence detection is supported */
  122. if ( ! mode->MediaPresentSupported )
  123. return;
  124. /* Report any link status change */
  125. if ( mode->MediaPresent && ( ! netdev_link_ok ( netdev ) ) ) {
  126. netdev_link_up ( netdev );
  127. } else if ( ( ! mode->MediaPresent ) && netdev_link_ok ( netdev ) ) {
  128. netdev_link_down ( netdev );
  129. }
  130. }
  131. /**
  132. * Transmit packet
  133. *
  134. * @v netdev Network device
  135. * @v iobuf I/O buffer
  136. * @ret rc Return status code
  137. */
  138. static int snpnet_transmit ( struct net_device *netdev,
  139. struct io_buffer *iobuf ) {
  140. struct snp_nic *snp = netdev_priv ( netdev );
  141. EFI_STATUS efirc;
  142. int rc;
  143. /* Defer the packet if there is already a transmission in progress */
  144. if ( snp->txbuf ) {
  145. netdev_tx_defer ( netdev, iobuf );
  146. return 0;
  147. }
  148. /* Transmit packet */
  149. if ( ( efirc = snp->snp->Transmit ( snp->snp, 0, iob_len ( iobuf ),
  150. iobuf->data, NULL, NULL,
  151. NULL ) ) != 0 ) {
  152. rc = -EEFI ( efirc );
  153. DBGC ( snp, "SNP %s could not transmit: %s\n",
  154. netdev->name, strerror ( rc ) );
  155. return rc;
  156. }
  157. snp->txbuf = iobuf;
  158. return 0;
  159. }
  160. /**
  161. * Poll for completed packets
  162. *
  163. * @v netdev Network device
  164. */
  165. static void snpnet_poll_tx ( struct net_device *netdev ) {
  166. struct snp_nic *snp = netdev->priv;
  167. struct io_buffer *iobuf;
  168. UINT32 irq;
  169. VOID *txbuf;
  170. EFI_STATUS efirc;
  171. int rc;
  172. /* Get status */
  173. if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) {
  174. rc = -EEFI ( efirc );
  175. DBGC ( snp, "SNP %s could not get status: %s\n",
  176. netdev->name, strerror ( rc ) );
  177. netdev_rx_err ( netdev, NULL, rc );
  178. return;
  179. }
  180. /* Do nothing unless we have a completion */
  181. if ( ! txbuf )
  182. return;
  183. /* Sanity check */
  184. if ( ! snp->txbuf ) {
  185. DBGC ( snp, "SNP %s reported spurious TX completion\n",
  186. netdev->name );
  187. netdev_tx_err ( netdev, NULL, -EPIPE );
  188. return;
  189. }
  190. /* Complete transmission */
  191. iobuf = snp->txbuf;
  192. snp->txbuf = NULL;
  193. netdev_tx_complete ( netdev, iobuf );
  194. }
  195. /**
  196. * Poll for received packets
  197. *
  198. * @v netdev Network device
  199. */
  200. static void snpnet_poll_rx ( struct net_device *netdev ) {
  201. struct snp_nic *snp = netdev->priv;
  202. UINTN len;
  203. unsigned int quota;
  204. EFI_STATUS efirc;
  205. int rc;
  206. /* Retrieve up to SNP_RX_QUOTA packets */
  207. for ( quota = SNP_RX_QUOTA ; quota ; quota-- ) {
  208. /* Allocate buffer, if required */
  209. if ( ! snp->rxbuf ) {
  210. snp->rxbuf = alloc_iob ( snp->mtu );
  211. if ( ! snp->rxbuf ) {
  212. /* Leave for next poll */
  213. break;
  214. }
  215. }
  216. /* Receive packet */
  217. len = iob_tailroom ( snp->rxbuf );
  218. if ( ( efirc = snp->snp->Receive ( snp->snp, NULL, &len,
  219. snp->rxbuf->data, NULL,
  220. NULL, NULL ) ) != 0 ) {
  221. /* EFI_NOT_READY is just the usual "no packet"
  222. * status indication; ignore it.
  223. */
  224. if ( efirc == EFI_NOT_READY )
  225. break;
  226. /* Anything else is an error */
  227. rc = -EEFI ( efirc );
  228. DBGC ( snp, "SNP %s could not receive: %s\n",
  229. netdev->name, strerror ( rc ) );
  230. netdev_rx_err ( netdev, NULL, rc );
  231. break;
  232. }
  233. /* Hand off to network stack */
  234. iob_put ( snp->rxbuf, len );
  235. netdev_rx ( netdev, snp->rxbuf );
  236. snp->rxbuf = NULL;
  237. }
  238. }
  239. /**
  240. * Poll for completed packets
  241. *
  242. * @v netdev Network device
  243. */
  244. static void snpnet_poll ( struct net_device *netdev ) {
  245. /* Process any TX completions */
  246. snpnet_poll_tx ( netdev );
  247. /* Process any RX completions */
  248. snpnet_poll_rx ( netdev );
  249. /* Check for link state changes */
  250. snpnet_check_link ( netdev );
  251. }
  252. /**
  253. * Set receive filters
  254. *
  255. * @v netdev Network device
  256. * @ret rc Return status code
  257. */
  258. static int snpnet_rx_filters ( struct net_device *netdev ) {
  259. struct snp_nic *snp = netdev->priv;
  260. UINT32 filters[] = {
  261. snp->snp->Mode->ReceiveFilterMask,
  262. ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
  263. EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
  264. EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
  265. ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
  266. EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
  267. ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST ),
  268. };
  269. unsigned int i;
  270. EFI_STATUS efirc;
  271. int rc;
  272. /* Try possible receive filters in turn */
  273. for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) {
  274. efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i],
  275. 0, TRUE, 0, NULL );
  276. if ( efirc == 0 )
  277. return 0;
  278. rc = -EEFI ( efirc );
  279. DBGC ( snp, "SNP %s could not set receive filters %#02x (have "
  280. "%#02x): %s\n", netdev->name, filters[i],
  281. snp->snp->Mode->ReceiveFilterSetting, strerror ( rc ) );
  282. }
  283. return rc;
  284. }
  285. /**
  286. * Open network device
  287. *
  288. * @v netdev Network device
  289. * @ret rc Return status code
  290. */
  291. static int snpnet_open ( struct net_device *netdev ) {
  292. struct snp_nic *snp = netdev->priv;
  293. EFI_MAC_ADDRESS *mac = ( ( void * ) netdev->ll_addr );
  294. EFI_STATUS efirc;
  295. int rc;
  296. /* Try setting MAC address (before initialising) */
  297. if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
  298. rc = -EEFI ( efirc );
  299. DBGC ( snp, "SNP %s could not set station address before "
  300. "initialising: %s\n", netdev->name, strerror ( rc ) );
  301. /* Ignore error */
  302. }
  303. /* Initialise NIC */
  304. if ( ( efirc = snp->snp->Initialize ( snp->snp, 0, 0 ) ) != 0 ) {
  305. rc = -EEFI ( efirc );
  306. snpnet_dump_mode ( netdev );
  307. DBGC ( snp, "SNP %s could not initialise: %s\n",
  308. netdev->name, strerror ( rc ) );
  309. return rc;
  310. }
  311. /* Try setting MAC address (after initialising) */
  312. if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
  313. rc = -EEFI ( efirc );
  314. DBGC ( snp, "SNP %s could not set station address after "
  315. "initialising: %s\n", netdev->name, strerror ( rc ) );
  316. /* Ignore error */
  317. }
  318. /* Set receive filters */
  319. if ( ( rc = snpnet_rx_filters ( netdev ) ) != 0 ) {
  320. /* Ignore error */
  321. }
  322. /* Dump mode information (for debugging) */
  323. snpnet_dump_mode ( netdev );
  324. return 0;
  325. }
  326. /**
  327. * Close network device
  328. *
  329. * @v netdev Network device
  330. */
  331. static void snpnet_close ( struct net_device *netdev ) {
  332. struct snp_nic *snp = netdev->priv;
  333. EFI_STATUS efirc;
  334. int rc;
  335. /* Shut down NIC */
  336. if ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) {
  337. rc = -EEFI ( efirc );
  338. DBGC ( snp, "SNP %s could not shut down: %s\n",
  339. netdev->name, strerror ( rc ) );
  340. /* Nothing we can do about this */
  341. }
  342. /* Discard transmit buffer, if applicable */
  343. if ( snp->txbuf ) {
  344. netdev_tx_complete_err ( netdev, snp->txbuf, -ECANCELED );
  345. snp->txbuf = NULL;
  346. }
  347. /* Discard receive buffer, if applicable */
  348. if ( snp->rxbuf ) {
  349. free_iob ( snp->rxbuf );
  350. snp->rxbuf = NULL;
  351. }
  352. }
  353. /** SNP network device operations */
  354. static struct net_device_operations snpnet_operations = {
  355. .open = snpnet_open,
  356. .close = snpnet_close,
  357. .transmit = snpnet_transmit,
  358. .poll = snpnet_poll,
  359. };
  360. /**
  361. * Attach driver to device
  362. *
  363. * @v efidev EFI device
  364. * @ret rc Return status code
  365. */
  366. int snpnet_start ( struct efi_device *efidev ) {
  367. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  368. EFI_HANDLE device = efidev->device;
  369. EFI_SIMPLE_NETWORK_MODE *mode;
  370. struct net_device *netdev;
  371. struct snp_nic *snp;
  372. void *interface;
  373. EFI_STATUS efirc;
  374. int rc;
  375. /* Open SNP protocol */
  376. if ( ( efirc = bs->OpenProtocol ( device,
  377. &efi_simple_network_protocol_guid,
  378. &interface, efi_image_handle, device,
  379. ( EFI_OPEN_PROTOCOL_BY_DRIVER |
  380. EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
  381. rc = -EEFI ( efirc );
  382. DBGC ( device, "SNP %p %s cannot open SNP protocol: %s\n",
  383. device, efi_handle_name ( device ), strerror ( rc ) );
  384. DBGC_EFI_OPENERS ( device, device,
  385. &efi_simple_network_protocol_guid );
  386. goto err_open_protocol;
  387. }
  388. /* Allocate and initialise structure */
  389. netdev = alloc_etherdev ( sizeof ( *snp ) );
  390. if ( ! netdev ) {
  391. rc = -ENOMEM;
  392. goto err_alloc;
  393. }
  394. netdev_init ( netdev, &snpnet_operations );
  395. snp = netdev->priv;
  396. snp->efidev = efidev;
  397. snp->snp = interface;
  398. mode = snp->snp->Mode;
  399. efidev_set_drvdata ( efidev, netdev );
  400. /* Populate underlying device information */
  401. efi_device_info ( device, "SNP", &snp->dev );
  402. snp->dev.driver_name = "SNP";
  403. snp->dev.parent = &efidev->dev;
  404. list_add ( &snp->dev.siblings, &efidev->dev.children );
  405. INIT_LIST_HEAD ( &snp->dev.children );
  406. netdev->dev = &snp->dev;
  407. /* Bring to the Started state */
  408. if ( ( mode->State == EfiSimpleNetworkStopped ) &&
  409. ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) {
  410. rc = -EEFI ( efirc );
  411. DBGC ( device, "SNP %p %s could not start: %s\n", device,
  412. efi_handle_name ( device ), strerror ( rc ) );
  413. goto err_start;
  414. }
  415. if ( ( mode->State == EfiSimpleNetworkInitialized ) &&
  416. ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
  417. rc = -EEFI ( efirc );
  418. DBGC ( device, "SNP %p %s could not shut down: %s\n", device,
  419. efi_handle_name ( device ), strerror ( rc ) );
  420. goto err_shutdown;
  421. }
  422. /* Populate network device parameters */
  423. if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) {
  424. DBGC ( device, "SNP %p %s has invalid hardware address "
  425. "length %d\n", device, efi_handle_name ( device ),
  426. mode->HwAddressSize );
  427. rc = -ENOTSUP;
  428. goto err_hw_addr_len;
  429. }
  430. memcpy ( netdev->hw_addr, &mode->PermanentAddress,
  431. netdev->ll_protocol->hw_addr_len );
  432. if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) {
  433. DBGC ( device, "SNP %p %s has invalid link-layer address "
  434. "length %d\n", device, efi_handle_name ( device ),
  435. mode->HwAddressSize );
  436. rc = -ENOTSUP;
  437. goto err_ll_addr_len;
  438. }
  439. memcpy ( netdev->ll_addr, &mode->CurrentAddress,
  440. netdev->ll_protocol->ll_addr_len );
  441. snp->mtu = ( snp->snp->Mode->MaxPacketSize +
  442. snp->snp->Mode->MediaHeaderSize );
  443. /* Register network device */
  444. if ( ( rc = register_netdev ( netdev ) ) != 0 )
  445. goto err_register_netdev;
  446. DBGC ( device, "SNP %p %s registered as %s\n",
  447. device, efi_handle_name ( device ), netdev->name );
  448. /* Set initial link state */
  449. if ( snp->snp->Mode->MediaPresentSupported ) {
  450. snpnet_check_link ( netdev );
  451. } else {
  452. netdev_link_up ( netdev );
  453. }
  454. return 0;
  455. unregister_netdev ( netdev );
  456. err_register_netdev:
  457. err_ll_addr_len:
  458. err_hw_addr_len:
  459. err_shutdown:
  460. err_start:
  461. list_del ( &snp->dev.siblings );
  462. netdev_nullify ( netdev );
  463. netdev_put ( netdev );
  464. err_alloc:
  465. bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
  466. efi_image_handle, device );
  467. err_open_protocol:
  468. return rc;
  469. }
  470. /**
  471. * Detach driver from device
  472. *
  473. * @v efidev EFI device
  474. */
  475. void snpnet_stop ( struct efi_device *efidev ) {
  476. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  477. struct net_device *netdev = efidev_get_drvdata ( efidev );
  478. struct snp_nic *snp = netdev->priv;
  479. EFI_HANDLE device = efidev->device;
  480. EFI_STATUS efirc;
  481. int rc;
  482. /* Unregister network device */
  483. unregister_netdev ( netdev );
  484. /* Stop SNP protocol */
  485. if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) {
  486. rc = -EEFI ( efirc );
  487. DBGC ( device, "SNP %p %s could not stop: %s\n", device,
  488. efi_handle_name ( device ), strerror ( rc ) );
  489. /* Nothing we can do about this */
  490. }
  491. /* Free network device */
  492. list_del ( &snp->dev.siblings );
  493. netdev_nullify ( netdev );
  494. netdev_put ( netdev );
  495. /* Close SNP protocol */
  496. bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
  497. efi_image_handle, device );
  498. }