freebsd-dev/sys/boot/ofw/libofw/ofw_net.c
Marius Strobl aa785996fd - Make better use of the global chosen, memory and mmu handles instead
of obtaining them over and over again and pretending we could do
  anything useful without them (for chosen this includes adding a
  declaration and initializing it in OF_init()).
- In OF_init() if obtaining the memory or mmu handle fails just call
  OF_exit() instead of panic() as the loader hasn't initialized the
  console at these early stages yet and trying to print out something
  causes a hang. With OF_exit() one at least has a change to get back
  to the OFW boot monitor and debug the problem.
- Fix OF_call_method() on 64-bit machines (this is a merge of
  sys/dev/ofw/openfirm.c rev 1.6).
- Replace OF_alloc_phys(), OF_claim_virt(), OF_map_phys() and
  OF_release_phys() in the MI part of the loader with wrappers around
  OF_call_method() in the sparc64. Beside the fact that they duplicate
  OF_call_method() the formers should never have been in the MI part
  of the loader as contrary to the OFW spec they use two-cell physical
  addresses.
- Remove unused functions which are also MD dupes of OF_call_method().
- In sys/boot/sparc64/loader/main.c add __func__ to panic strings as
  different functions use otherwise identical panic strings and make
  some of the panic strings a tad more user-friendly instead of just
  mentioning the name of the function that returned an unexpected
  result.
2007-06-17 00:17:15 +00:00

258 lines
5.8 KiB
C

/*-
* Copyright (c) 2000-2001 Benno Rice
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <stand.h>
#include <net.h>
#include <netif.h>
#include "openfirm.h"
static int ofwn_probe(struct netif *, void *);
static int ofwn_match(struct netif *, void *);
static void ofwn_init(struct iodesc *, void *);
static int ofwn_get(struct iodesc *, void *, size_t, time_t);
static int ofwn_put(struct iodesc *, void *, size_t);
static void ofwn_end(struct netif *);
extern struct netif_stats ofwn_stats[];
struct netif_dif ofwn_ifs[] = {
/* dif_unit dif_nsel dif_stats dif_private */
{ 0, 1, &ofwn_stats[0], 0, },
};
struct netif_stats ofwn_stats[NENTS(ofwn_ifs)];
struct netif_driver ofwnet = {
"net", /* netif_bname */
ofwn_match, /* netif_match */
ofwn_probe, /* netif_probe */
ofwn_init, /* netif_init */
ofwn_get, /* netif_get */
ofwn_put, /* netif_put */
ofwn_end, /* netif_end */
ofwn_ifs, /* netif_ifs */
NENTS(ofwn_ifs) /* netif_nifs */
};
static ihandle_t netinstance;
static void *dmabuf;
static int
ofwn_match(struct netif *nif, void *machdep_hint)
{
return 1;
}
static int
ofwn_probe(struct netif *nif, void *machdep_hint)
{
return 0;
}
static int
ofwn_put(struct iodesc *desc, void *pkt, size_t len)
{
struct ether_header *eh;
size_t sendlen;
ssize_t rv;
#if defined(NETIF_DEBUG)
printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len);
eh = pkt;
printf("dst: %s ", ether_sprintf(eh->ether_dhost));
printf("src: %s ", ether_sprintf(eh->ether_shost));
printf("type: 0x%x\n", eh->ether_type & 0xffff);
#endif
sendlen = len;
if (sendlen < 60) {
sendlen = 60;
#if defined(NETIF_DEBUG)
printf("netif_put: length padded to %d\n", sendlen);
#endif
}
if (dmabuf) {
bcopy(pkt, dmabuf, sendlen);
pkt = dmabuf;
}
rv = OF_write(netinstance, pkt, len);
#if defined(NETIF_DEBUG)
printf("netif_put: OF_write returned %d\n", rv);
#endif
return rv;
}
static int
ofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout)
{
time_t t;
int length;
#if defined(NETIF_DEBUG)
printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len,
timeout);
#endif
t = getsecs();
do {
length = OF_read(netinstance, pkt, len);
} while ((length == -2 || length == 0) &&
(getsecs() - t < timeout));
#if defined(NETIF_DEBUG)
printf("netif_get: received length=%d (%x)\n", length, length);
#endif
if (length < 12)
return -1;
#if defined(NETIF_VERBOSE_DEBUG)
{
char *ch = pkt;
int i;
for(i = 0; i < 96; i += 4) {
printf("%02x%02x%02x%02x ", ch[i], ch[i+1],
ch[i+2], ch[i+3]);
}
printf("\n");
}
#endif
#if defined(NETIF_DEBUG)
{
struct ether_header *eh = pkt;
printf("dst: %s ", ether_sprintf(eh->ether_dhost));
printf("src: %s ", ether_sprintf(eh->ether_shost));
printf("type: 0x%x\n", eh->ether_type & 0xffff);
}
#endif
return length;
}
extern char *strchr();
static void
ofwn_init(struct iodesc *desc, void *machdep_hint)
{
phandle_t netdev;
char path[64];
char *ch;
int pathlen;
pathlen = OF_getprop(chosen, "bootpath", path, 64);
if ((ch = index(path, ':')) != NULL)
*ch = '\0';
netdev = OF_finddevice(path);
#ifdef __sparc64__
if (OF_getprop(netdev, "mac-address", desc->myea, 6) == -1)
#else
if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1)
#endif
goto punt;
printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea));
if ((netinstance = OF_open(path)) == -1) {
printf("Could not open network device.\n");
goto punt;
}
#if defined(NETIF_DEBUG)
printf("ofwn_init: Open Firmware instance handle: %08x\n", netinstance);
#endif
#ifndef __sparc64__
dmabuf = NULL;
if (OF_call_method("dma-alloc", netinstance, 1, 1, (64 * 1024), &dmabuf)
< 0) {
printf("Failed to allocate DMA buffer (got %08x).\n", dmabuf);
goto punt;
}
#if defined(NETIF_DEBUG)
printf("ofwn_init: allocated DMA buffer: %08x\n", dmabuf);
#endif
#endif
return;
punt:
printf("\n");
printf("Could not boot from %s.\n", path);
OF_enter();
}
static void
ofwn_end(struct netif *nif)
{
OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS);
OF_close(netinstance);
}
#if 0
int
ofwn_getunit(const char *path)
{
int i;
char newpath[255];
OF_canon(path, newpath, 254);
for (i = 0; i < nofwninfo; i++) {
printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path);
if (strcmp(path, ofwninfo[i].ofwn_path) == 0)
return i;
if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0)
return i;
}
return -1;
}
#endif