ofw_net.c revision 214494
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 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/boot/ofw/libofw/ofw_net.c 214494 2010-10-29 00:36:44Z nwhitehorn $"); 29 30#include <sys/param.h> 31#include <sys/types.h> 32#include <sys/socket.h> 33 34#include <net/if.h> 35#include <netinet/in.h> 36#include <netinet/in_systm.h> 37#include <netinet/if_ether.h> 38#include <netinet/ip.h> 39 40#include <stand.h> 41#include <net.h> 42#include <netif.h> 43 44#include "openfirm.h" 45 46static int ofwn_probe(struct netif *, void *); 47static int ofwn_match(struct netif *, void *); 48static void ofwn_init(struct iodesc *, void *); 49static int ofwn_get(struct iodesc *, void *, size_t, time_t); 50static int ofwn_put(struct iodesc *, void *, size_t); 51static void ofwn_end(struct netif *); 52 53extern struct netif_stats ofwn_stats[]; 54 55struct netif_dif ofwn_ifs[] = { 56 /* dif_unit dif_nsel dif_stats dif_private */ 57 { 0, 1, &ofwn_stats[0], 0, }, 58}; 59 60struct netif_stats ofwn_stats[NENTS(ofwn_ifs)]; 61 62struct netif_driver ofwnet = { 63 "net", /* netif_bname */ 64 ofwn_match, /* netif_match */ 65 ofwn_probe, /* netif_probe */ 66 ofwn_init, /* netif_init */ 67 ofwn_get, /* netif_get */ 68 ofwn_put, /* netif_put */ 69 ofwn_end, /* netif_end */ 70 ofwn_ifs, /* netif_ifs */ 71 NENTS(ofwn_ifs) /* netif_nifs */ 72}; 73 74static ihandle_t netinstance; 75 76static void *dmabuf; 77 78static int 79ofwn_match(struct netif *nif, void *machdep_hint) 80{ 81 return 1; 82} 83 84static int 85ofwn_probe(struct netif *nif, void *machdep_hint) 86{ 87 return 0; 88} 89 90static int 91ofwn_put(struct iodesc *desc, void *pkt, size_t len) 92{ 93 struct ether_header *eh; 94 size_t sendlen; 95 ssize_t rv; 96 97#if defined(NETIF_DEBUG) 98 printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len); 99 eh = pkt; 100 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 101 printf("src: %s ", ether_sprintf(eh->ether_shost)); 102 printf("type: 0x%x\n", eh->ether_type & 0xffff); 103#endif 104 105 sendlen = len; 106 if (sendlen < 60) { 107 sendlen = 60; 108#if defined(NETIF_DEBUG) 109 printf("netif_put: length padded to %d\n", sendlen); 110#endif 111 } 112 113 if (dmabuf) { 114 bcopy(pkt, dmabuf, sendlen); 115 pkt = dmabuf; 116 } 117 118 rv = OF_write(netinstance, pkt, len); 119 120#if defined(NETIF_DEBUG) 121 printf("netif_put: OF_write returned %d\n", rv); 122#endif 123 124 return rv; 125} 126 127static int 128ofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 129{ 130 time_t t; 131 int length; 132 133#if defined(NETIF_DEBUG) 134 printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len, 135 timeout); 136#endif 137 138 t = getsecs(); 139 do { 140 length = OF_read(netinstance, pkt, len); 141 } while ((length == -2 || length == 0) && 142 (getsecs() - t < timeout)); 143 144#if defined(NETIF_DEBUG) 145 printf("netif_get: received length=%d (%x)\n", length, length); 146#endif 147 148 if (length < 12) 149 return -1; 150 151#if defined(NETIF_VERBOSE_DEBUG) 152 { 153 char *ch = pkt; 154 int i; 155 156 for(i = 0; i < 96; i += 4) { 157 printf("%02x%02x%02x%02x ", ch[i], ch[i+1], 158 ch[i+2], ch[i+3]); 159 } 160 printf("\n"); 161 } 162#endif 163 164#if defined(NETIF_DEBUG) 165 { 166 struct ether_header *eh = pkt; 167 168 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 169 printf("src: %s ", ether_sprintf(eh->ether_shost)); 170 printf("type: 0x%x\n", eh->ether_type & 0xffff); 171 } 172#endif 173 174 return length; 175} 176 177extern char *strchr(); 178 179static void 180ofwn_init(struct iodesc *desc, void *machdep_hint) 181{ 182 phandle_t netdev; 183 char path[64]; 184 char *ch; 185 int pathlen; 186 187 pathlen = OF_getprop(chosen, "bootpath", path, 64); 188 if ((ch = index(path, ':')) != NULL) 189 *ch = '\0'; 190 netdev = OF_finddevice(path); 191#ifdef __sparc64__ 192 if (OF_getprop(netdev, "mac-address", desc->myea, 6) == -1) 193#else 194 if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1) 195#endif 196 goto punt; 197 198 printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea)); 199 200 if ((netinstance = OF_open(path)) == -1) { 201 printf("Could not open network device.\n"); 202 goto punt; 203 } 204 205#if defined(NETIF_DEBUG) 206 printf("ofwn_init: Open Firmware instance handle: %08x\n", netinstance); 207#endif 208 209#ifndef __sparc64__ 210 dmabuf = NULL; 211 if (OF_call_method("dma-alloc", netinstance, 1, 1, (64 * 1024), &dmabuf) 212 < 0) { 213 printf("Failed to allocate DMA buffer (got %08x).\n", dmabuf); 214 goto punt; 215 } 216 217#if defined(NETIF_DEBUG) 218 printf("ofwn_init: allocated DMA buffer: %08x\n", dmabuf); 219#endif 220#endif 221 222 return; 223 224punt: 225 printf("\n"); 226 printf("Could not boot from %s.\n", path); 227 OF_enter(); 228} 229 230static void 231ofwn_end(struct netif *nif) 232{ 233#ifdef BROKEN 234 /* dma-free freezes at least some Apple ethernet controllers */ 235 OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS); 236#endif 237 OF_close(netinstance); 238} 239 240#if 0 241int 242ofwn_getunit(const char *path) 243{ 244 int i; 245 char newpath[255]; 246 247 OF_canon(path, newpath, 254); 248 249 for (i = 0; i < nofwninfo; i++) { 250 printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path); 251 if (strcmp(path, ofwninfo[i].ofwn_path) == 0) 252 return i; 253 254 if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0) 255 return i; 256 } 257 258 return -1; 259} 260#endif 261