ofw_net.c revision 91112
1/* 2 * Copyright (c) 2000-2001 Benno Rice 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/boot/ofw/libofw/ofw_net.c 91112 2002-02-23 04:31:30Z jake $ 27 */ 28 29#include <sys/param.h> 30#include <sys/types.h> 31#include <sys/socket.h> 32 33#include <net/if.h> 34#include <netinet/in.h> 35#include <netinet/in_systm.h> 36#include <netinet/if_ether.h> 37#include <netinet/ip.h> 38 39#include <stand.h> 40#include <net.h> 41#include <netif.h> 42 43#include "openfirm.h" 44 45static int ofwn_probe(struct netif *, void *); 46static int ofwn_match(struct netif *, void *); 47static void ofwn_init(struct iodesc *, void *); 48static int ofwn_get(struct iodesc *, void *, size_t, time_t); 49static int ofwn_put(struct iodesc *, void *, size_t); 50static void ofwn_end(struct netif *); 51 52extern struct netif_stats ofwn_stats[]; 53 54struct netif_dif ofwn_ifs[] = { 55 /* dif_unit dif_nsel dif_stats dif_private */ 56 { 0, 1, &ofwn_stats[0], 0, }, 57}; 58 59struct netif_stats ofwn_stats[NENTS(ofwn_ifs)]; 60 61struct netif_driver ofwnet = { 62 "net", /* netif_bname */ 63 ofwn_match, /* netif_match */ 64 ofwn_probe, /* netif_probe */ 65 ofwn_init, /* netif_init */ 66 ofwn_get, /* netif_get */ 67 ofwn_put, /* netif_put */ 68 ofwn_end, /* netif_end */ 69 ofwn_ifs, /* netif_ifs */ 70 NENTS(ofwn_ifs) /* netif_nifs */ 71}; 72 73static phandle_t netdevice; 74static ihandle_t netinstance; 75static ihandle_t memory; 76 77static void *dmabuf; 78 79static int 80ofwn_match(struct netif *nif, void *machdep_hint) 81{ 82 return 1; 83} 84 85static int 86ofwn_probe(struct netif *nif, void *machdep_hint) 87{ 88 return 0; 89} 90 91static int 92ofwn_put(struct iodesc *desc, void *pkt, size_t len) 93{ 94 struct ether_header *eh; 95 size_t sendlen; 96 ssize_t rv; 97 98#if defined(NETIF_DEBUG) 99 printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len); 100 eh = pkt; 101 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 102 printf("src: %s ", ether_sprintf(eh->ether_shost)); 103 printf("type: 0x%x\n", eh->ether_type & 0xffff); 104#endif 105 106 sendlen = len; 107 if (sendlen < 60) { 108 sendlen = 60; 109#if defined(NETIF_DEBUG) 110 printf("netif_put: length padded to %d\n", sendlen); 111#endif 112 } 113 114 if (dmabuf) { 115 bcopy(pkt, dmabuf, sendlen); 116 pkt = dmabuf; 117 } 118 119 rv = OF_write(netinstance, pkt, len); 120 121#if defined(NETIF_DEBUG) 122 printf("netif_put: OF_write returned %d\n", rv); 123#endif 124 125 return rv; 126} 127 128static int 129ofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 130{ 131 time_t t; 132 int length; 133 134#if defined(NETIF_DEBUG) 135 printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len, 136 timeout); 137#endif 138 139 t = getsecs(); 140 do { 141 length = OF_read(netinstance, pkt, len); 142 } while ((length == -2 || length == 0) && 143 (getsecs() - t < timeout)); 144 145#if defined(NETIF_DEBUG) 146 printf("netif_get: received length=%d (%x)\n", length, length); 147#endif 148 149 if (length < 12) 150 return -1; 151 152#if defined(NETIF_VERBOSE_DEBUG) 153 { 154 char *ch = pkt; 155 int i; 156 157 for(i = 0; i < 96; i += 4) { 158 printf("%02x%02x%02x%02x ", ch[i], ch[i+1], 159 ch[i+2], ch[i+3]); 160 } 161 printf("\n"); 162 } 163#endif 164 165#if defined(NETIF_DEBUG) 166 { 167 struct ether_header *eh = pkt; 168 169 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 170 printf("src: %s ", ether_sprintf(eh->ether_shost)); 171 printf("type: 0x%x\n", eh->ether_type & 0xffff); 172 } 173#endif 174 175 return length; 176} 177 178extern char *strchr(); 179 180static void 181ofwn_init(struct iodesc *desc, void *machdep_hint) 182{ 183 phandle_t chosen, netdev; 184 char path[64]; 185 char *ch; 186 int pathlen; 187 188 chosen = OF_finddevice("/chosen"); 189 OF_getprop(chosen, "memory", &memory, sizeof(memory)); 190 pathlen = OF_getprop(chosen, "bootpath", path, 64); 191 if ((ch = index(path, ':')) != NULL) 192 *ch = '\0'; 193 netdev = OF_finddevice(path); 194#ifdef __sparc64__ 195 if (OF_getprop(netdev, "mac-address", desc->myea, 6) == -1) 196#else 197 if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1) 198#endif 199 goto punt; 200 201 printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea)); 202 203 if ((netinstance = OF_open(path)) == -1) { 204 printf("Could not open network device.\n"); 205 goto punt; 206 } 207 208#if defined(NETIF_DEBUG) 209 printf("ofwn_init: OpenFirmware instance handle: %08x\n", netinstance); 210#endif 211 212#ifndef __sparc64__ 213 if (OF_call_method("dma-alloc", netinstance, 1, 1, NULL, &dmabuf) 214 < 0) { 215 printf("Failed to allocate DMA buffer (got %08x).\n", dmabuf); 216 goto punt; 217 } 218 219#if defined(NETIF_DEBUG) 220 printf("ofwn_init: allocated DMA buffer: %08x\n", dmabuf); 221#endif 222#endif 223 224 return; 225 226punt: 227 printf("\n"); 228 printf("Could not boot from %s.\n", path); 229 OF_enter(); 230} 231 232static void 233ofwn_end(struct netif *nif) 234{ 235 OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS); 236 OF_close(netinstance); 237} 238 239#if 0 240int 241ofwn_getunit(const char *path) 242{ 243 int i; 244 char newpath[255]; 245 246 OF_canon(path, newpath, 254); 247 248 for (i = 0; i < nofwninfo; i++) { 249 printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path); 250 if (strcmp(path, ofwninfo[i].ofwn_path) == 0) 251 return i; 252 253 if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0) 254 return i; 255 } 256 257 return -1; 258} 259#endif 260