|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2010 VMware, Inc. All Rights Reserved. ! 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 St, Fifth Floor, Boston, MA 02110-1301 USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <errno.h> ! 22: #include <string.h> ! 23: #include <ipxe/io.h> ! 24: #include <ipxe/iobuf.h> ! 25: #include <ipxe/netdevice.h> ! 26: #include <ipxe/if_ether.h> ! 27: #include <ipxe/ethernet.h> ! 28: #include <ipxe/efi/efi.h> ! 29: #include <ipxe/efi/Protocol/SimpleNetwork.h> ! 30: #include "snp.h" ! 31: #include "snpnet.h" ! 32: ! 33: /** @file ! 34: * ! 35: * SNP network device driver ! 36: * ! 37: */ ! 38: ! 39: /** SNP net device structure */ ! 40: struct snpnet_device { ! 41: /** The underlying simple network protocol */ ! 42: EFI_SIMPLE_NETWORK_PROTOCOL *snp; ! 43: ! 44: /** State that the SNP should be in after close */ ! 45: UINT32 close_state; ! 46: }; ! 47: ! 48: /** ! 49: * Transmit packet ! 50: * ! 51: * @v netdev Network device ! 52: * @v iobuf I/O buffer ! 53: * @ret rc Return status code ! 54: */ ! 55: static int snpnet_transmit ( struct net_device *netdev, ! 56: struct io_buffer *iobuf ) { ! 57: struct snpnet_device *snpnetdev = netdev->priv; ! 58: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; ! 59: EFI_STATUS efirc; ! 60: size_t len = iob_len ( iobuf ); ! 61: ! 62: efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, NULL ); ! 63: return EFIRC_TO_RC ( efirc ); ! 64: } ! 65: ! 66: /** ! 67: * Find a I/O buffer on the list of outstanding Tx buffers and complete it. ! 68: * ! 69: * @v snpnetdev SNP network device ! 70: * @v txbuf Buffer address ! 71: */ ! 72: static void snpnet_complete ( struct net_device *netdev, void *txbuf ) { ! 73: struct io_buffer *tmp; ! 74: struct io_buffer *iobuf; ! 75: ! 76: list_for_each_entry_safe ( iobuf, tmp, &netdev->tx_queue, list ) { ! 77: if ( iobuf->data == txbuf ) { ! 78: netdev_tx_complete ( netdev, iobuf ); ! 79: break; ! 80: } ! 81: } ! 82: } ! 83: ! 84: /** ! 85: * Poll for received packets ! 86: * ! 87: * @v netdev Network device ! 88: */ ! 89: static void snpnet_poll ( struct net_device *netdev ) { ! 90: struct snpnet_device *snpnetdev = netdev->priv; ! 91: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; ! 92: EFI_STATUS efirc; ! 93: struct io_buffer *iobuf = NULL; ! 94: UINTN len; ! 95: void *txbuf; ! 96: ! 97: /* Process Tx completions */ ! 98: while ( 1 ) { ! 99: efirc = snp->GetStatus ( snp, NULL, &txbuf ); ! 100: if ( efirc ) { ! 101: DBGC ( snp, "SNP %p could not get status %s\n", snp, ! 102: efi_strerror ( efirc ) ); ! 103: break; ! 104: } ! 105: ! 106: if ( txbuf == NULL ) ! 107: break; ! 108: ! 109: snpnet_complete ( netdev, txbuf ); ! 110: } ! 111: ! 112: /* Process received packets */ ! 113: while ( 1 ) { ! 114: /* The spec is not clear if the max packet size refers to the ! 115: * payload or the entire packet including headers. The Receive ! 116: * function needs a buffer large enough to contain the headers, ! 117: * and potentially a 4-byte CRC and 4-byte VLAN tag (?), so add ! 118: * some breathing room. ! 119: */ ! 120: len = snp->Mode->MaxPacketSize + ETH_HLEN + 8; ! 121: iobuf = alloc_iob ( len ); ! 122: if ( iobuf == NULL ) { ! 123: netdev_rx_err ( netdev, NULL, -ENOMEM ); ! 124: break; ! 125: } ! 126: ! 127: efirc = snp->Receive ( snp, NULL, &len, iobuf->data, ! 128: NULL, NULL, NULL ); ! 129: ! 130: /* No packets left? */ ! 131: if ( efirc == EFI_NOT_READY ) { ! 132: free_iob ( iobuf ); ! 133: break; ! 134: } ! 135: ! 136: /* Other error? */ ! 137: if ( efirc ) { ! 138: DBGC ( snp, "SNP %p receive packet error: %s " ! 139: "(len was %zd, is now %zd)\n", ! 140: snp, efi_strerror ( efirc ), iob_len(iobuf), ! 141: (size_t)len ); ! 142: netdev_rx_err ( netdev, iobuf, efirc ); ! 143: break; ! 144: } ! 145: ! 146: /* Packet is valid, deliver it */ ! 147: iob_put ( iobuf, len ); ! 148: netdev_rx ( netdev, iob_disown ( iobuf ) ); ! 149: } ! 150: } ! 151: ! 152: /** ! 153: * Open NIC ! 154: * ! 155: * @v netdev Net device ! 156: * @ret rc Return status code ! 157: */ ! 158: static int snpnet_open ( struct net_device *netdev ) { ! 159: struct snpnet_device *snpnetdev = netdev->priv; ! 160: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; ! 161: EFI_STATUS efirc; ! 162: UINT32 enableFlags, disableFlags; ! 163: ! 164: snpnetdev->close_state = snp->Mode->State; ! 165: if ( snp->Mode->State != EfiSimpleNetworkInitialized ) { ! 166: efirc = snp->Initialize ( snp, 0, 0 ); ! 167: if ( efirc ) { ! 168: DBGC ( snp, "SNP %p could not initialize: %s\n", ! 169: snp, efi_strerror ( efirc ) ); ! 170: return EFIRC_TO_RC ( efirc ); ! 171: } ! 172: } ! 173: ! 174: /* Use the default MAC address */ ! 175: efirc = snp->StationAddress ( snp, FALSE, ! 176: (EFI_MAC_ADDRESS *)netdev->ll_addr ); ! 177: if ( efirc ) { ! 178: DBGC ( snp, "SNP %p could not reset station address: %s\n", ! 179: snp, efi_strerror ( efirc ) ); ! 180: } ! 181: ! 182: /* Set up receive filters to receive unicast and broadcast packets ! 183: * always. Also, enable either promiscuous multicast (if possible) or ! 184: * promiscuous operation, in order to catch all multicast packets. ! 185: */ ! 186: enableFlags = snp->Mode->ReceiveFilterMask & ! 187: ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | ! 188: EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ); ! 189: disableFlags = snp->Mode->ReceiveFilterMask & ! 190: ( EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | ! 191: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | ! 192: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST ); ! 193: if ( snp->Mode->ReceiveFilterMask & ! 194: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST ) { ! 195: enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; ! 196: } else if ( snp->Mode->ReceiveFilterMask & ! 197: EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS ) { ! 198: enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; ! 199: } ! 200: disableFlags &= ~enableFlags; ! 201: efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags, ! 202: FALSE, 0, NULL ); ! 203: if ( efirc ) { ! 204: DBGC ( snp, "SNP %p could not set receive filters: %s\n", ! 205: snp, efi_strerror ( efirc ) ); ! 206: } ! 207: ! 208: DBGC ( snp, "SNP %p opened\n", snp ); ! 209: return 0; ! 210: } ! 211: ! 212: /** ! 213: * Close NIC ! 214: * ! 215: * @v netdev Net device ! 216: */ ! 217: static void snpnet_close ( struct net_device *netdev ) { ! 218: struct snpnet_device *snpnetdev = netdev->priv; ! 219: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; ! 220: EFI_STATUS efirc; ! 221: ! 222: if ( snpnetdev->close_state != EfiSimpleNetworkInitialized ) { ! 223: efirc = snp->Shutdown ( snp ); ! 224: if ( efirc ) { ! 225: DBGC ( snp, "SNP %p could not shut down: %s\n", ! 226: snp, efi_strerror ( efirc ) ); ! 227: } ! 228: } ! 229: } ! 230: ! 231: /** ! 232: * Enable/disable interrupts ! 233: * ! 234: * @v netdev Net device ! 235: * @v enable Interrupts should be enabled ! 236: */ ! 237: static void snpnet_irq ( struct net_device *netdev, int enable ) { ! 238: struct snpnet_device *snpnetdev = netdev->priv; ! 239: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; ! 240: ! 241: /* On EFI, interrupts are never necessary. (This function is only ! 242: * required for BIOS PXE.) If interrupts were required, they could be ! 243: * simulated using a fast timer. ! 244: */ ! 245: DBGC ( snp, "SNP %p cannot %s interrupts\n", ! 246: snp, ( enable ? "enable" : "disable" ) ); ! 247: } ! 248: ! 249: /** SNP network device operations */ ! 250: static struct net_device_operations snpnet_operations = { ! 251: .open = snpnet_open, ! 252: .close = snpnet_close, ! 253: .transmit = snpnet_transmit, ! 254: .poll = snpnet_poll, ! 255: .irq = snpnet_irq, ! 256: }; ! 257: ! 258: /** ! 259: * Probe SNP device ! 260: * ! 261: * @v snpdev SNP device ! 262: * @ret rc Return status code ! 263: */ ! 264: int snpnet_probe ( struct snp_device *snpdev ) { ! 265: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp; ! 266: EFI_STATUS efirc; ! 267: struct net_device *netdev; ! 268: struct snpnet_device *snpnetdev; ! 269: int rc; ! 270: ! 271: DBGC ( snp, "SNP %p probing...\n", snp ); ! 272: ! 273: /* Allocate net device */ ! 274: netdev = alloc_etherdev ( sizeof ( struct snpnet_device ) ); ! 275: if ( ! netdev ) ! 276: return -ENOMEM; ! 277: netdev_init ( netdev, &snpnet_operations ); ! 278: netdev->dev = &snpdev->dev; ! 279: snpdev->netdev = netdev; ! 280: snpnetdev = netdev->priv; ! 281: snpnetdev->snp = snp; ! 282: snpdev->removal_state = snp->Mode->State; ! 283: ! 284: /* Start the interface */ ! 285: if ( snp->Mode->State == EfiSimpleNetworkStopped ) { ! 286: efirc = snp->Start ( snp ); ! 287: if ( efirc ) { ! 288: DBGC ( snp, "SNP %p could not start: %s\n", snp, ! 289: efi_strerror ( efirc ) ); ! 290: rc = EFIRC_TO_RC ( efirc ); ! 291: goto err_start; ! 292: } ! 293: } ! 294: ! 295: if ( snp->Mode->HwAddressSize > sizeof ( netdev->hw_addr ) ) { ! 296: DBGC ( snp, "SNP %p hardware address is too large\n", snp ); ! 297: rc = -EINVAL; ! 298: goto err_hwaddr; ! 299: } ! 300: memcpy ( netdev->hw_addr, snp->Mode->PermanentAddress.Addr, ! 301: snp->Mode->HwAddressSize ); ! 302: ! 303: /* Register network device */ ! 304: if ( ( rc = register_netdev ( netdev ) ) != 0 ) ! 305: goto err_register; ! 306: ! 307: /* Mark as link up; we don't handle link state */ ! 308: netdev_link_up ( netdev ); ! 309: ! 310: DBGC ( snp, "SNP %p added\n", snp ); ! 311: return 0; ! 312: ! 313: err_register: ! 314: err_hwaddr: ! 315: if ( snpdev->removal_state == EfiSimpleNetworkStopped ) ! 316: snp->Stop ( snp ); ! 317: ! 318: err_start: ! 319: netdev_nullify ( netdev ); ! 320: netdev_put ( netdev ); ! 321: snpdev->netdev = NULL; ! 322: return rc; ! 323: } ! 324: ! 325: /** ! 326: * Remove SNP device ! 327: * ! 328: * @v snpdev SNP device ! 329: */ ! 330: void snpnet_remove ( struct snp_device *snpdev ) { ! 331: EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp; ! 332: EFI_STATUS efirc; ! 333: struct net_device *netdev = snpdev->netdev; ! 334: ! 335: if ( snp->Mode->State == EfiSimpleNetworkInitialized && ! 336: snpdev->removal_state != EfiSimpleNetworkInitialized ) { ! 337: DBGC ( snp, "SNP %p shutting down\n", snp ); ! 338: efirc = snp->Shutdown ( snp ); ! 339: if ( efirc ) { ! 340: DBGC ( snp, "SNP %p could not shut down: %s\n", ! 341: snp, efi_strerror ( efirc ) ); ! 342: } ! 343: } ! 344: ! 345: if ( snp->Mode->State == EfiSimpleNetworkStarted && ! 346: snpdev->removal_state == EfiSimpleNetworkStopped ) { ! 347: DBGC ( snp, "SNP %p stopping\n", snp ); ! 348: efirc = snp->Stop ( snp ); ! 349: if ( efirc ) { ! 350: DBGC ( snp, "SNP %p could not be stopped\n", snp ); ! 351: } ! 352: } ! 353: ! 354: /* Unregister net device */ ! 355: unregister_netdev ( netdev ); ! 356: ! 357: /* Free network device */ ! 358: netdev_nullify ( netdev ); ! 359: netdev_put ( netdev ); ! 360: ! 361: DBGC ( snp, "SNP %p removed\n", snp ); ! 362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.