Home | History | Annotate | Line # | Download | only in libefi
efinet.c revision 1.2.74.2
      1  1.2.74.2    yamt /*	$NetBSD: efinet.c,v 1.2.74.2 2010/03/11 15:02:32 yamt Exp $	*/
      2       1.1  cherry 
      3       1.1  cherry /*-
      4       1.1  cherry  * Copyright (c) 2001 Doug Rabson
      5       1.1  cherry  * All rights reserved.
      6       1.1  cherry  *
      7       1.1  cherry  * Redistribution and use in source and binary forms, with or without
      8       1.1  cherry  * modification, are permitted provided that the following conditions
      9       1.1  cherry  * are met:
     10       1.1  cherry  * 1. Redistributions of source code must retain the above copyright
     11       1.1  cherry  *    notice, this list of conditions and the following disclaimer.
     12       1.1  cherry  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1  cherry  *    notice, this list of conditions and the following disclaimer in the
     14       1.1  cherry  *    documentation and/or other materials provided with the distribution.
     15       1.1  cherry  *
     16       1.1  cherry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17       1.1  cherry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18       1.1  cherry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19       1.1  cherry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20       1.1  cherry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21       1.1  cherry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22       1.1  cherry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23       1.1  cherry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24       1.1  cherry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25       1.1  cherry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26       1.1  cherry  * SUCH DAMAGE.
     27       1.1  cherry  */
     28       1.1  cherry 
     29       1.1  cherry #include <sys/cdefs.h>
     30       1.2  cherry /* __FBSDID("$FreeBSD: src/sys/boot/efi/libefi/efinet.c,v 1.6 2004/01/04 23:28:16 obrien Exp $"); */
     31       1.1  cherry 
     32       1.1  cherry #include <sys/param.h>
     33       1.1  cherry #include <netinet/in.h>
     34       1.1  cherry #include <netinet/in_systm.h>
     35       1.1  cherry 
     36       1.1  cherry #include <lib/libsa/stand.h>
     37       1.1  cherry #include <net.h>
     38       1.1  cherry #include <netif.h>
     39       1.1  cherry 
     40       1.1  cherry #include <efi.h>
     41       1.1  cherry #include <efilib.h>
     42       1.1  cherry 
     43       1.1  cherry extern struct netif_driver efi_net;
     44       1.1  cherry 
     45       1.1  cherry #ifdef EFINET_DEBUG
     46       1.1  cherry static void
     47       1.1  cherry dump_mode(EFI_SIMPLE_NETWORK_MODE *mode)
     48       1.1  cherry {
     49       1.1  cherry 	int i;
     50       1.1  cherry 
     51       1.1  cherry 	printf("State                 = %x\n", mode->State);
     52       1.1  cherry 	printf("HwAddressSize         = %u\n", mode->HwAddressSize);
     53       1.1  cherry 	printf("MediaHeaderSize       = %u\n", mode->MediaHeaderSize);
     54       1.1  cherry 	printf("MaxPacketSize         = %u\n", mode->MaxPacketSize);
     55       1.1  cherry 	printf("NvRamSize             = %u\n", mode->NvRamSize);
     56       1.1  cherry 	printf("NvRamAccessSize       = %u\n", mode->NvRamAccessSize);
     57       1.1  cherry 	printf("ReceiveFilterMask     = %x\n", mode->ReceiveFilterMask);
     58       1.1  cherry 	printf("ReceiveFilterSetting  = %u\n", mode->ReceiveFilterSetting);
     59       1.1  cherry 	printf("MaxMCastFilterCount   = %u\n", mode->MaxMCastFilterCount);
     60       1.1  cherry 	printf("MCastFilterCount      = %u\n", mode->MCastFilterCount);
     61       1.1  cherry 	printf("MCastFilter           = {");
     62       1.1  cherry 	for (i = 0; i < mode->MCastFilterCount; i++)
     63       1.1  cherry 		printf(" %s", ether_sprintf(mode->MCastFilter[i].Addr));
     64       1.1  cherry 	printf(" }\n");
     65       1.1  cherry 	printf("CurrentAddress        = %s\n",
     66       1.1  cherry 	    ether_sprintf(mode->CurrentAddress.Addr));
     67       1.1  cherry 	printf("BroadcastAddress      = %s\n",
     68       1.1  cherry 	    ether_sprintf(mode->BroadcastAddress.Addr));
     69       1.1  cherry 	printf("PermanentAddress      = %s\n",
     70       1.1  cherry 	    ether_sprintf(mode->PermanentAddress.Addr));
     71       1.1  cherry 	printf("IfType                = %u\n", mode->IfType);
     72       1.1  cherry 	printf("MacAddressChangeable  = %d\n", mode->MacAddressChangeable);
     73       1.1  cherry 	printf("MultipleTxSupported   = %d\n", mode->MultipleTxSupported);
     74       1.1  cherry 	printf("MediaPresentSupported = %d\n", mode->MediaPresentSupported);
     75       1.1  cherry 	printf("MediaPresent          = %d\n", mode->MediaPresent);
     76       1.1  cherry }
     77       1.1  cherry #endif
     78       1.1  cherry 
     79       1.1  cherry int
     80       1.1  cherry efinet_match(struct netif *nif, void *machdep_hint)
     81       1.1  cherry {
     82       1.1  cherry 
     83       1.1  cherry 	return (1);
     84       1.1  cherry }
     85       1.1  cherry 
     86       1.1  cherry int
     87       1.1  cherry efinet_probe(struct netif *nif, void *machdep_hint)
     88       1.1  cherry {
     89       1.1  cherry 
     90       1.1  cherry 	return (0);
     91       1.1  cherry }
     92       1.1  cherry 
     93       1.1  cherry int
     94       1.1  cherry efinet_put(struct iodesc *desc, void *pkt, size_t len)
     95       1.1  cherry {
     96       1.1  cherry 	struct netif *nif = desc->io_netif;
     97       1.1  cherry 	EFI_SIMPLE_NETWORK *net;
     98       1.1  cherry 	EFI_STATUS status;
     99       1.1  cherry 	void *buf;
    100       1.1  cherry 
    101       1.1  cherry 	net = nif->nif_devdata;
    102       1.1  cherry 
    103       1.1  cherry 	status = net->Transmit(net, 0, len, pkt, 0, 0, 0);
    104       1.1  cherry 	if (status != EFI_SUCCESS)
    105       1.1  cherry 		return -1;
    106       1.1  cherry 
    107       1.1  cherry 	/* Wait for the buffer to be transmitted */
    108       1.1  cherry 	do {
    109       1.1  cherry 		buf = 0;	/* XXX Is this needed? */
    110       1.1  cherry 		status = net->GetStatus(net, 0, &buf);
    111       1.1  cherry 		/*
    112       1.1  cherry 		 * XXX EFI1.1 and the E1000 card returns a different
    113       1.1  cherry 		 * address than we gave.  Sigh.
    114       1.1  cherry 		 */
    115       1.1  cherry 	} while (status == EFI_SUCCESS && buf == 0);
    116       1.1  cherry 
    117       1.1  cherry 	/* XXX How do we deal with status != EFI_SUCCESS now? */
    118       1.1  cherry 	return (status == EFI_SUCCESS) ? len : -1;
    119       1.1  cherry }
    120       1.1  cherry 
    121       1.1  cherry 
    122       1.1  cherry int
    123       1.1  cherry efinet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
    124       1.1  cherry {
    125       1.1  cherry 	struct netif *nif = desc->io_netif;
    126       1.1  cherry 	EFI_SIMPLE_NETWORK *net;
    127       1.1  cherry 	EFI_STATUS status;
    128       1.1  cherry 	UINTN bufsz;
    129       1.1  cherry 	time_t t;
    130       1.1  cherry 	char buf[2048];
    131       1.1  cherry 
    132       1.1  cherry 	net = nif->nif_devdata;
    133       1.1  cherry 
    134       1.1  cherry 	t = time(0);
    135       1.1  cherry 	while ((time(0) - t) < timeout) {
    136       1.1  cherry 		bufsz = sizeof(buf);
    137       1.1  cherry 		status = net->Receive(net, 0, &bufsz, buf, 0, 0, 0);
    138       1.1  cherry 		if (status == EFI_SUCCESS) {
    139       1.1  cherry 			/*
    140       1.1  cherry 			 * XXX EFI1.1 and the E1000 card trash our
    141       1.1  cherry 			 * workspace if we do not do this silly copy.
    142       1.1  cherry 			 * Either they are not respecting the len
    143       1.1  cherry 			 * value or do not like the alignment.
    144       1.1  cherry 			 */
    145       1.1  cherry 			if (bufsz > len)
    146       1.1  cherry 				bufsz = len;
    147  1.2.74.2    yamt 			memcpy(pkt, buf, bufsz);
    148       1.1  cherry 			return bufsz;
    149       1.1  cherry 		}
    150       1.1  cherry 		if (status != EFI_NOT_READY)
    151       1.1  cherry 			return 0;
    152       1.1  cherry 	}
    153       1.1  cherry 
    154       1.1  cherry 	return 0;
    155       1.1  cherry }
    156       1.1  cherry 
    157       1.1  cherry void
    158       1.1  cherry efinet_init(struct iodesc *desc, void *machdep_hint)
    159       1.1  cherry {
    160       1.1  cherry 	struct netif *nif = desc->io_netif;
    161       1.1  cherry 	EFI_SIMPLE_NETWORK *net;
    162       1.1  cherry 	EFI_STATUS status;
    163       1.1  cherry 
    164       1.1  cherry 	net = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private;
    165       1.1  cherry 	nif->nif_devdata = net;
    166       1.1  cherry 
    167       1.1  cherry 	if (net->Mode->State == EfiSimpleNetworkStopped) {
    168       1.1  cherry 		status = net->Start(net);
    169       1.1  cherry 		if (status != EFI_SUCCESS) {
    170       1.1  cherry 			printf("net%d: cannot start interface (status=%ld)\n",
    171       1.1  cherry 			    nif->nif_unit, status);
    172       1.1  cherry 			return;
    173       1.1  cherry 		}
    174       1.1  cherry 	}
    175       1.1  cherry 
    176       1.1  cherry 	if (net->Mode->State != EfiSimpleNetworkInitialized) {
    177       1.1  cherry 		status = net->Initialize(net, 0, 0);
    178       1.1  cherry 		if (status != EFI_SUCCESS) {
    179       1.1  cherry 			printf("net%d: cannot init. interface (status=%ld)\n",
    180       1.1  cherry 			    nif->nif_unit, status);
    181       1.1  cherry 			return;
    182       1.1  cherry 		}
    183       1.1  cherry 	}
    184       1.1  cherry 
    185       1.1  cherry 	if (net->Mode->ReceiveFilterSetting == 0) {
    186       1.1  cherry 		UINT32 mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
    187       1.1  cherry 		    EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
    188       1.1  cherry 
    189       1.1  cherry 		status = net->ReceiveFilters(net, mask, 0, FALSE, 0, 0);
    190       1.1  cherry 		if (status != EFI_SUCCESS) {
    191       1.1  cherry 			printf("net%d: cannot set rx. filters (status=%ld)\n",
    192       1.1  cherry 			    nif->nif_unit, status);
    193       1.1  cherry 			return;
    194       1.1  cherry 		}
    195       1.1  cherry 	}
    196       1.1  cherry 
    197       1.1  cherry #ifdef EFINET_DEBUG
    198       1.1  cherry 	dump_mode(net->Mode);
    199       1.1  cherry #endif
    200       1.1  cherry 
    201  1.2.74.2    yamt 	memcpy(desc->myea, net->Mode->CurrentAddress.Addr, 6);
    202       1.1  cherry 	desc->xid = 1;
    203       1.1  cherry 
    204       1.1  cherry 	return;
    205       1.1  cherry }
    206       1.1  cherry 
    207       1.1  cherry void
    208  1.2.74.1    yamt efinet_init_driver(void)
    209       1.1  cherry {
    210       1.1  cherry 	EFI_STATUS	status;
    211       1.1  cherry 	UINTN		sz;
    212       1.1  cherry 	static EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
    213       1.1  cherry 	EFI_HANDLE	*handles;
    214       1.1  cherry 	int		nifs, i;
    215       1.1  cherry #define MAX_INTERFACES	4
    216       1.1  cherry 	static struct netif_dif difs[MAX_INTERFACES];
    217       1.1  cherry 	static struct netif_stats stats[MAX_INTERFACES];
    218       1.1  cherry 
    219       1.1  cherry 	sz = 0;
    220       1.1  cherry 	status = BS->LocateHandle(ByProtocol, &netid, 0, &sz, 0);
    221       1.1  cherry 	if (status != EFI_BUFFER_TOO_SMALL)
    222       1.1  cherry 		return;
    223       1.1  cherry 	handles = (EFI_HANDLE *) alloc(sz);
    224       1.1  cherry 	status = BS->LocateHandle(ByProtocol, &netid, 0, &sz, handles);
    225       1.1  cherry 	if (EFI_ERROR(status)) {
    226       1.1  cherry 		free(handles, sz);
    227       1.1  cherry 		return;
    228       1.1  cherry 	}
    229       1.1  cherry 
    230       1.1  cherry 	nifs = sz / sizeof(EFI_HANDLE);
    231       1.1  cherry 	if (nifs > MAX_INTERFACES)
    232       1.1  cherry 		nifs = MAX_INTERFACES;
    233       1.1  cherry 
    234       1.1  cherry 	efi_net.netif_nifs = nifs;
    235       1.1  cherry 	efi_net.netif_ifs = difs;
    236       1.1  cherry 
    237  1.2.74.1    yamt 	memset(stats, 0, sizeof(stats));
    238       1.1  cherry 	for (i = 0; i < nifs; i++) {
    239       1.1  cherry 		struct netif_dif *dif = &efi_net.netif_ifs[i];
    240       1.1  cherry 		dif->dif_unit = i;
    241       1.1  cherry 		dif->dif_nsel = 1;
    242       1.1  cherry 		dif->dif_stats = &stats[i];
    243       1.1  cherry 
    244       1.1  cherry 		BS->HandleProtocol(handles[i], &netid,
    245       1.1  cherry 				   (VOID**) &dif->dif_private);
    246       1.1  cherry 	}
    247       1.1  cherry 
    248       1.1  cherry 	return;
    249       1.1  cherry }
    250       1.1  cherry 
    251       1.1  cherry void
    252       1.1  cherry efinet_end(struct netif *nif)
    253       1.1  cherry {
    254       1.1  cherry 	EFI_SIMPLE_NETWORK *net = nif->nif_devdata;
    255       1.1  cherry 
    256       1.1  cherry 	net->Shutdown(net);
    257       1.1  cherry }
    258       1.1  cherry 
    259       1.1  cherry struct netif_driver efi_net = {
    260       1.1  cherry 	"net",			/* netif_bname */
    261       1.1  cherry 	efinet_match,		/* netif_match */
    262       1.1  cherry 	efinet_probe,		/* netif_probe */
    263       1.1  cherry 	efinet_init,		/* netif_init */
    264       1.1  cherry 	efinet_get,		/* netif_get */
    265       1.1  cherry 	efinet_put,		/* netif_put */
    266       1.1  cherry 	efinet_end,		/* netif_end */
    267       1.1  cherry 	0,			/* netif_ifs */
    268       1.1  cherry 	0			/* netif_nifs */
    269       1.1  cherry };
    270       1.1  cherry 
    271