Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

snpnet.c 14KB

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