ofw_net.c revision 229403
1139738Simp/*- 284617Sbenno * Copyright (c) 2000-2001 Benno Rice 367204Sobrien * All rights reserved. 467204Sobrien * 567204Sobrien * Redistribution and use in source and binary forms, with or without 667204Sobrien * modification, are permitted provided that the following conditions 767204Sobrien * are met: 867204Sobrien * 1. Redistributions of source code must retain the above copyright 967204Sobrien * notice, this list of conditions and the following disclaimer. 1067204Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1167204Sobrien * notice, this list of conditions and the following disclaimer in the 1267204Sobrien * documentation and/or other materials provided with the distribution. 1367204Sobrien * 1467204Sobrien * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND 1567204Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1667204Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1767204Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1867204Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1967204Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2067204Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2167204Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2267204Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2367204Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2467204Sobrien * SUCH DAMAGE. 2567204Sobrien */ 2667204Sobrien 27124140Sobrien#include <sys/cdefs.h> 28124140Sobrien__FBSDID("$FreeBSD: head/sys/boot/ofw/libofw/ofw_net.c 229403 2012-01-03 18:51:58Z ed $"); 29124140Sobrien 3067204Sobrien#include <sys/param.h> 3167204Sobrien#include <sys/types.h> 3268548Sbenno#include <sys/socket.h> 3367204Sobrien 3468548Sbenno#include <net/if.h> 3567204Sobrien#include <netinet/in.h> 3667204Sobrien#include <netinet/in_systm.h> 3768548Sbenno#include <netinet/if_ether.h> 3868548Sbenno#include <netinet/ip.h> 3967204Sobrien 4067204Sobrien#include <stand.h> 4167204Sobrien#include <net.h> 4267204Sobrien#include <netif.h> 4367204Sobrien 4468548Sbenno#include "openfirm.h" 4567204Sobrien 4668548Sbennostatic int ofwn_probe(struct netif *, void *); 4768548Sbennostatic int ofwn_match(struct netif *, void *); 4868548Sbennostatic void ofwn_init(struct iodesc *, void *); 4984617Sbennostatic int ofwn_get(struct iodesc *, void *, size_t, time_t); 5084617Sbennostatic int ofwn_put(struct iodesc *, void *, size_t); 5168548Sbennostatic void ofwn_end(struct netif *); 5267204Sobrien 5368548Sbennoextern struct netif_stats ofwn_stats[]; 5468548Sbenno 5568548Sbennostruct netif_dif ofwn_ifs[] = { 5667204Sobrien /* dif_unit dif_nsel dif_stats dif_private */ 5768548Sbenno { 0, 1, &ofwn_stats[0], 0, }, 5867204Sobrien}; 5967204Sobrien 6068548Sbennostruct netif_stats ofwn_stats[NENTS(ofwn_ifs)]; 6167204Sobrien 6267204Sobrienstruct netif_driver ofwnet = { 6367204Sobrien "net", /* netif_bname */ 6467204Sobrien ofwn_match, /* netif_match */ 6567204Sobrien ofwn_probe, /* netif_probe */ 6667204Sobrien ofwn_init, /* netif_init */ 6767204Sobrien ofwn_get, /* netif_get */ 6867204Sobrien ofwn_put, /* netif_put */ 6967204Sobrien ofwn_end, /* netif_end */ 7067204Sobrien ofwn_ifs, /* netif_ifs */ 7167204Sobrien NENTS(ofwn_ifs) /* netif_nifs */ 7267204Sobrien}; 7367204Sobrien 7468548Sbennostatic ihandle_t netinstance; 7567204Sobrien 7668548Sbennostatic void *dmabuf; 7768548Sbenno 7868548Sbennostatic int 7967204Sobrienofwn_match(struct netif *nif, void *machdep_hint) 8067204Sobrien{ 8168548Sbenno return 1; 8267204Sobrien} 8367204Sobrien 8468548Sbennostatic int 8567204Sobrienofwn_probe(struct netif *nif, void *machdep_hint) 8667204Sobrien{ 8767204Sobrien return 0; 8867204Sobrien} 8967204Sobrien 9068548Sbennostatic int 9184617Sbennoofwn_put(struct iodesc *desc, void *pkt, size_t len) 9267204Sobrien{ 9368548Sbenno size_t sendlen; 9468548Sbenno ssize_t rv; 9567204Sobrien 9668548Sbenno#if defined(NETIF_DEBUG) 97215437Sandreast struct ether_header *eh; 9868548Sbenno printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len); 9968548Sbenno eh = pkt; 10068548Sbenno printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 10168548Sbenno printf("src: %s ", ether_sprintf(eh->ether_shost)); 10268548Sbenno printf("type: 0x%x\n", eh->ether_type & 0xffff); 10367204Sobrien#endif 10468548Sbenno 10568548Sbenno sendlen = len; 10668548Sbenno if (sendlen < 60) { 10768548Sbenno sendlen = 60; 10868548Sbenno#if defined(NETIF_DEBUG) 10968548Sbenno printf("netif_put: length padded to %d\n", sendlen); 11068548Sbenno#endif 11168548Sbenno } 11268548Sbenno 11368548Sbenno if (dmabuf) { 11468548Sbenno bcopy(pkt, dmabuf, sendlen); 11568548Sbenno pkt = dmabuf; 11668548Sbenno } 11768548Sbenno 11868548Sbenno rv = OF_write(netinstance, pkt, len); 11968548Sbenno 12068548Sbenno#if defined(NETIF_DEBUG) 12168548Sbenno printf("netif_put: OF_write returned %d\n", rv); 12268548Sbenno#endif 12368548Sbenno 12468548Sbenno return rv; 12567204Sobrien} 12667204Sobrien 12768548Sbennostatic int 12884617Sbennoofwn_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 12967204Sobrien{ 13068548Sbenno time_t t; 13168548Sbenno int length; 13267204Sobrien 13368548Sbenno#if defined(NETIF_DEBUG) 13468548Sbenno printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len, 13568548Sbenno timeout); 13668548Sbenno#endif 13767204Sobrien 13868548Sbenno t = getsecs(); 13968548Sbenno do { 14068548Sbenno length = OF_read(netinstance, pkt, len); 14168548Sbenno } while ((length == -2 || length == 0) && 14268548Sbenno (getsecs() - t < timeout)); 14367204Sobrien 14468548Sbenno#if defined(NETIF_DEBUG) 14568548Sbenno printf("netif_get: received length=%d (%x)\n", length, length); 14668548Sbenno#endif 14767204Sobrien 14868548Sbenno if (length < 12) 14968548Sbenno return -1; 15067204Sobrien 15168548Sbenno#if defined(NETIF_VERBOSE_DEBUG) 15268548Sbenno { 15368548Sbenno char *ch = pkt; 15468548Sbenno int i; 15567204Sobrien 15668548Sbenno for(i = 0; i < 96; i += 4) { 15768548Sbenno printf("%02x%02x%02x%02x ", ch[i], ch[i+1], 15868548Sbenno ch[i+2], ch[i+3]); 15967204Sobrien } 16068548Sbenno printf("\n"); 16167204Sobrien } 16268548Sbenno#endif 16367204Sobrien 16468548Sbenno#if defined(NETIF_DEBUG) 16568548Sbenno { 16668548Sbenno struct ether_header *eh = pkt; 16767204Sobrien 16868548Sbenno printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 16968548Sbenno printf("src: %s ", ether_sprintf(eh->ether_shost)); 17068548Sbenno printf("type: 0x%x\n", eh->ether_type & 0xffff); 17168548Sbenno } 17268548Sbenno#endif 17367204Sobrien 17468548Sbenno return length; 17568548Sbenno} 17667204Sobrien 17768548Sbennoextern char *strchr(); 17867204Sobrien 17968548Sbennostatic void 18068548Sbennoofwn_init(struct iodesc *desc, void *machdep_hint) 18168548Sbenno{ 182170854Smarius phandle_t netdev; 18368548Sbenno char path[64]; 18468548Sbenno char *ch; 18568548Sbenno int pathlen; 18667204Sobrien 18768548Sbenno pathlen = OF_getprop(chosen, "bootpath", path, 64); 188229403Sed if ((ch = strchr(path, ':')) != NULL) 18991112Sjake *ch = '\0'; 19068548Sbenno netdev = OF_finddevice(path); 19191112Sjake#ifdef __sparc64__ 19291112Sjake if (OF_getprop(netdev, "mac-address", desc->myea, 6) == -1) 19391112Sjake#else 19468548Sbenno if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1) 19591112Sjake#endif 19668548Sbenno goto punt; 19768548Sbenno 19867204Sobrien printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea)); 19967204Sobrien 20084617Sbenno if ((netinstance = OF_open(path)) == -1) { 20184617Sbenno printf("Could not open network device.\n"); 20268548Sbenno goto punt; 20384617Sbenno } 20468548Sbenno 20568548Sbenno#if defined(NETIF_DEBUG) 206133862Smarius printf("ofwn_init: Open Firmware instance handle: %08x\n", netinstance); 20768548Sbenno#endif 20868548Sbenno 20991112Sjake#ifndef __sparc64__ 21098013Sbenno dmabuf = NULL; 21198013Sbenno if (OF_call_method("dma-alloc", netinstance, 1, 1, (64 * 1024), &dmabuf) 21282343Sbenno < 0) { 21382343Sbenno printf("Failed to allocate DMA buffer (got %08x).\n", dmabuf); 21468548Sbenno goto punt; 21582343Sbenno } 21668548Sbenno 21768548Sbenno#if defined(NETIF_DEBUG) 21868548Sbenno printf("ofwn_init: allocated DMA buffer: %08x\n", dmabuf); 21968548Sbenno#endif 22091112Sjake#endif 22168548Sbenno 22267204Sobrien return; 22367204Sobrien 22467204Sobrienpunt: 22567204Sobrien printf("\n"); 22668548Sbenno printf("Could not boot from %s.\n", path); 22784617Sbenno OF_enter(); 22867204Sobrien} 22967204Sobrien 23068548Sbennostatic void 23167204Sobrienofwn_end(struct netif *nif) 23267204Sobrien{ 233214494Snwhitehorn#ifdef BROKEN 234214494Snwhitehorn /* dma-free freezes at least some Apple ethernet controllers */ 23568548Sbenno OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS); 236214494Snwhitehorn#endif 23768548Sbenno OF_close(netinstance); 23867204Sobrien} 23968548Sbenno 24068548Sbenno#if 0 24168548Sbennoint 24268548Sbennoofwn_getunit(const char *path) 24368548Sbenno{ 24468548Sbenno int i; 24568548Sbenno char newpath[255]; 24668548Sbenno 24768548Sbenno OF_canon(path, newpath, 254); 24868548Sbenno 24968548Sbenno for (i = 0; i < nofwninfo; i++) { 25068548Sbenno printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path); 25168548Sbenno if (strcmp(path, ofwninfo[i].ofwn_path) == 0) 25268548Sbenno return i; 25368548Sbenno 25468548Sbenno if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0) 25568548Sbenno return i; 25668548Sbenno } 25768548Sbenno 25868548Sbenno return -1; 25968548Sbenno} 26068548Sbenno#endif 261