ofw_net.c revision 133862
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 133862 2004-08-16 15:45:27Z marius $"); 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 phandle_t netdevice; 75static ihandle_t netinstance; 76static ihandle_t memory; 77 78static void *dmabuf; 79 80static int 81ofwn_match(struct netif *nif, void *machdep_hint) 82{ 83 return 1; 84} 85 86static int 87ofwn_probe(struct netif *nif, void *machdep_hint) 88{ 89 return 0; 90} 91 92static int 93ofwn_put(struct iodesc *desc, void *pkt, size_t len) 94{ 95 struct ether_header *eh; 96 size_t sendlen; 97 ssize_t rv; 98 99#if defined(NETIF_DEBUG) 100 printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len); 101 eh = pkt; 102 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 103 printf("src: %s ", ether_sprintf(eh->ether_shost)); 104 printf("type: 0x%x\n", eh->ether_type & 0xffff); 105#endif 106 107 sendlen = len; 108 if (sendlen < 60) { 109 sendlen = 60; 110#if defined(NETIF_DEBUG) 111 printf("netif_put: length padded to %d\n", sendlen); 112#endif 113 } 114 115 if (dmabuf) { 116 bcopy(pkt, dmabuf, sendlen); 117 pkt = dmabuf; 118 } 119 120 rv = OF_write(netinstance, pkt, len); 121 122#if defined(NETIF_DEBUG) 123 printf("netif_put: OF_write returned %d\n", rv); 124#endif 125 126 return rv; 127} 128 129static int 130ofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 131{ 132 time_t t; 133 int length; 134 135#if defined(NETIF_DEBUG) 136 printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len, 137 timeout); 138#endif 139 140 t = getsecs(); 141 do { 142 length = OF_read(netinstance, pkt, len); 143 } while ((length == -2 || length == 0) && 144 (getsecs() - t < timeout)); 145 146#if defined(NETIF_DEBUG) 147 printf("netif_get: received length=%d (%x)\n", length, length); 148#endif 149 150 if (length < 12) 151 return -1; 152 153#if defined(NETIF_VERBOSE_DEBUG) 154 { 155 char *ch = pkt; 156 int i; 157 158 for(i = 0; i < 96; i += 4) { 159 printf("%02x%02x%02x%02x ", ch[i], ch[i+1], 160 ch[i+2], ch[i+3]); 161 } 162 printf("\n"); 163 } 164#endif 165 166#if defined(NETIF_DEBUG) 167 { 168 struct ether_header *eh = pkt; 169 170 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 171 printf("src: %s ", ether_sprintf(eh->ether_shost)); 172 printf("type: 0x%x\n", eh->ether_type & 0xffff); 173 } 174#endif 175 176 return length; 177} 178 179extern char *strchr(); 180 181static void 182ofwn_init(struct iodesc *desc, void *machdep_hint) 183{ 184 phandle_t chosen, netdev; 185 char path[64]; 186 char *ch; 187 int pathlen; 188 189 chosen = OF_finddevice("/chosen"); 190 OF_getprop(chosen, "memory", &memory, sizeof(memory)); 191 pathlen = OF_getprop(chosen, "bootpath", path, 64); 192 if ((ch = index(path, ':')) != NULL) 193 *ch = '\0'; 194 netdev = OF_finddevice(path); 195#ifdef __sparc64__ 196 if (OF_getprop(netdev, "mac-address", desc->myea, 6) == -1) 197#else 198 if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1) 199#endif 200 goto punt; 201 202 printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea)); 203 204 if ((netinstance = OF_open(path)) == -1) { 205 printf("Could not open network device.\n"); 206 goto punt; 207 } 208 209#if defined(NETIF_DEBUG) 210 printf("ofwn_init: Open Firmware instance handle: %08x\n", netinstance); 211#endif 212 213#ifndef __sparc64__ 214 dmabuf = NULL; 215 if (OF_call_method("dma-alloc", netinstance, 1, 1, (64 * 1024), &dmabuf) 216 < 0) { 217 printf("Failed to allocate DMA buffer (got %08x).\n", dmabuf); 218 goto punt; 219 } 220 221#if defined(NETIF_DEBUG) 222 printf("ofwn_init: allocated DMA buffer: %08x\n", dmabuf); 223#endif 224#endif 225 226 return; 227 228punt: 229 printf("\n"); 230 printf("Could not boot from %s.\n", path); 231 OF_enter(); 232} 233 234static void 235ofwn_end(struct netif *nif) 236{ 237 OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS); 238 OF_close(netinstance); 239} 240 241#if 0 242int 243ofwn_getunit(const char *path) 244{ 245 int i; 246 char newpath[255]; 247 248 OF_canon(path, newpath, 254); 249 250 for (i = 0; i < nofwninfo; i++) { 251 printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path); 252 if (strcmp(path, ofwninfo[i].ofwn_path) == 0) 253 return i; 254 255 if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0) 256 return i; 257 } 258 259 return -1; 260} 261#endif 262