1176348Smarcel/*- 2176348Smarcel * Copyright (c) 2000-2001 Benno Rice 3176348Smarcel * Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@semihalf.com> 4176348Smarcel * All rights reserved. 5176348Smarcel * 6176348Smarcel * Redistribution and use in source and binary forms, with or without 7176348Smarcel * modification, are permitted provided that the following conditions 8176348Smarcel * are met: 9176348Smarcel * 1. Redistributions of source code must retain the above copyright 10176348Smarcel * notice, this list of conditions and the following disclaimer. 11176348Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12176348Smarcel * notice, this list of conditions and the following disclaimer in the 13176348Smarcel * documentation and/or other materials provided with the distribution. 14176348Smarcel * 15176348Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16176348Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17176348Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18176348Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19176348Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20176348Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21176348Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22176348Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23176348Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24176348Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25176348Smarcel * SUCH DAMAGE. 26176348Smarcel */ 27176348Smarcel 28176348Smarcel#include <sys/cdefs.h> 29176348Smarcel__FBSDID("$FreeBSD$"); 30176348Smarcel 31176348Smarcel#include <sys/param.h> 32176348Smarcel#include <sys/types.h> 33176348Smarcel#include <sys/socket.h> 34176348Smarcel 35176348Smarcel#include <net/if.h> 36176348Smarcel#include <netinet/in.h> 37176348Smarcel#include <netinet/in_systm.h> 38176348Smarcel#include <netinet/if_ether.h> 39176348Smarcel#include <netinet/ip.h> 40176348Smarcel 41176348Smarcel#include <stand.h> 42176348Smarcel#include <net.h> 43176348Smarcel#include <netif.h> 44176348Smarcel 45176348Smarcel#include "api_public.h" 46182723Sraj#include "glue.h" 47176348Smarcel#include "libuboot.h" 48176348Smarcel 49176348Smarcelstatic int net_probe(struct netif *, void *); 50176348Smarcelstatic int net_match(struct netif *, void *); 51176348Smarcelstatic void net_init(struct iodesc *, void *); 52176348Smarcelstatic int net_get(struct iodesc *, void *, size_t, time_t); 53176348Smarcelstatic int net_put(struct iodesc *, void *, size_t); 54176348Smarcelstatic void net_end(struct netif *); 55176348Smarcel 56183599Srajextern struct netif_stats net_stats[]; 57176348Smarcel 58176348Smarcelstruct netif_dif net_ifs[] = { 59177152Sobrien /* dif_unit dif_nsel dif_stats dif_private */ 60176348Smarcel { 0, 1, &net_stats[0], 0, }, 61176348Smarcel}; 62176348Smarcel 63176348Smarcelstruct netif_stats net_stats[NENTS(net_ifs)]; 64176348Smarcel 65176348Smarcelstruct netif_driver uboot_net = { 66176348Smarcel "uboot_eth", /* netif_bname */ 67176348Smarcel net_match, /* netif_match */ 68176348Smarcel net_probe, /* netif_probe */ 69176348Smarcel net_init, /* netif_init */ 70176348Smarcel net_get, /* netif_get */ 71176348Smarcel net_put, /* netif_put */ 72176348Smarcel net_end, /* netif_end */ 73176348Smarcel net_ifs, /* netif_ifs */ 74176348Smarcel NENTS(net_ifs) /* netif_nifs */ 75176348Smarcel}; 76176348Smarcel 77176348Smarcelstruct uboot_softc { 78183599Sraj uint32_t sc_pad; 79183599Sraj uint8_t sc_rxbuf[ETHER_MAX_LEN]; 80183599Sraj uint8_t sc_txbuf[ETHER_MAX_LEN + PKTALIGN]; 81183599Sraj uint8_t *sc_txbufp; 82176348Smarcel int sc_handle; /* device handle for ub_dev_xxx */ 83176348Smarcel}; 84176348Smarcel 85176348Smarcelstatic struct uboot_softc uboot_softc; 86176348Smarcel 87176348Smarcelstatic int 88176348Smarcelnet_match(struct netif *nif, void *machdep_hint) 89176348Smarcel{ 90176348Smarcel char **a = (char **)machdep_hint; 91176348Smarcel 92176348Smarcel if (memcmp("net", *a, 3) == 0) 93177108Sraj return (1); 94177108Sraj 95176348Smarcel printf("net_match: could not match network device\n"); 96177108Sraj return (0); 97176348Smarcel} 98176348Smarcel 99176348Smarcelstatic int 100176348Smarcelnet_probe(struct netif *nif, void *machdep_hint) 101176348Smarcel{ 102182723Sraj struct device_info *di; 103182723Sraj int i; 104176348Smarcel 105176348Smarcel for (i = 0; i < devs_no; i++) 106182723Sraj if ((di = ub_dev_get(i)) != NULL) 107176348Smarcel if (di->type == DEV_TYP_NET) 108176348Smarcel break; 109182723Sraj 110176348Smarcel if (i == devs_no) { 111177152Sobrien printf("net_probe: no network devices found, maybe not" 112177152Sobrien " enumerated yet..?\n"); 113177108Sraj return (-1); 114176348Smarcel } 115176348Smarcel 116176348Smarcel#if defined(NETIF_DEBUG) 117176348Smarcel printf("net_probe: network device found: %d\n", i); 118176348Smarcel#endif 119176348Smarcel uboot_softc.sc_handle = i; 120177108Sraj 121177108Sraj return (0); 122176348Smarcel} 123176348Smarcel 124176348Smarcelstatic int 125176348Smarcelnet_put(struct iodesc *desc, void *pkt, size_t len) 126176348Smarcel{ 127182723Sraj struct netif *nif = desc->io_netif; 128182723Sraj struct uboot_softc *sc = nif->nif_devdata; 129182723Sraj size_t sendlen; 130182723Sraj ssize_t rv; 131176348Smarcel 132182723Sraj#if defined(NETIF_DEBUG) 133182723Sraj struct ether_header *eh; 134176348Smarcel 135193111Smarcel printf("net_put: desc %p, pkt %p, len %d\n", desc, pkt, len); 136176348Smarcel eh = pkt; 137176348Smarcel printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 138176348Smarcel printf("src: %s ", ether_sprintf(eh->ether_shost)); 139176348Smarcel printf("type: 0x%x\n", eh->ether_type & 0xffff); 140176348Smarcel#endif 141176348Smarcel 142176348Smarcel if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) { 143176348Smarcel sendlen = ETHER_MIN_LEN - ETHER_CRC_LEN; 144176348Smarcel bzero(sc->sc_txbufp, sendlen); 145176348Smarcel } else 146176348Smarcel sendlen = len; 147176348Smarcel 148176348Smarcel memcpy(sc->sc_txbufp, pkt, len); 149176348Smarcel 150176348Smarcel rv = ub_dev_send(sc->sc_handle, sc->sc_txbufp, sendlen); 151176348Smarcel 152176348Smarcel#if defined(NETIF_DEBUG) 153176348Smarcel printf("net_put: ub_send returned %d\n", rv); 154176348Smarcel#endif 155176348Smarcel if (rv == 0) 156176348Smarcel rv = len; 157176348Smarcel else 158176348Smarcel rv = -1; 159176348Smarcel 160177108Sraj return (rv); 161176348Smarcel} 162176348Smarcel 163176348Smarcelstatic int 164176348Smarcelnet_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 165176348Smarcel{ 166183599Sraj struct netif *nif = desc->io_netif; 167183599Sraj struct uboot_softc *sc = nif->nif_devdata; 168183599Sraj time_t t; 169183599Sraj int err, rlen; 170176348Smarcel 171176348Smarcel#if defined(NETIF_DEBUG) 172193111Smarcel printf("net_get: pkt %p, len %d, timeout %d\n", pkt, len, timeout); 173176348Smarcel#endif 174176348Smarcel t = getsecs(); 175176348Smarcel do { 176183598Sraj err = ub_dev_recv(sc->sc_handle, sc->sc_rxbuf, len, &rlen); 177176348Smarcel 178183598Sraj if (err != 0) { 179183598Sraj printf("net_get: ub_dev_recv() failed, error=%d\n", 180183598Sraj err); 181183598Sraj rlen = 0; 182183598Sraj break; 183183598Sraj } 184183598Sraj } while ((rlen == -1 || rlen == 0) && (getsecs() - t < timeout)); 185183598Sraj 186176348Smarcel#if defined(NETIF_DEBUG) 187183598Sraj printf("net_get: received len %d (%x)\n", rlen, rlen); 188176348Smarcel#endif 189176348Smarcel 190183598Sraj if (rlen > 0) { 191183598Sraj memcpy(pkt, sc->sc_rxbuf, MIN(len, rlen)); 192183598Sraj if (rlen != len) { 193176348Smarcel#if defined(NETIF_DEBUG) 194183598Sraj printf("net_get: len %x, rlen %x\n", len, rlen); 195176348Smarcel#endif 196176348Smarcel } 197183598Sraj return (rlen); 198176348Smarcel } 199176348Smarcel 200177108Sraj return (-1); 201176348Smarcel} 202176348Smarcel 203176348Smarcelstatic void 204176348Smarcelnet_init(struct iodesc *desc, void *machdep_hint) 205176348Smarcel{ 206182723Sraj struct netif *nif = desc->io_netif; 207182723Sraj struct uboot_softc *sc; 208182723Sraj struct device_info *di; 209182723Sraj int err; 210177152Sobrien 211176348Smarcel sc = nif->nif_devdata = &uboot_softc; 212176348Smarcel 213182723Sraj if ((err = ub_dev_open(sc->sc_handle)) != 0) 214176348Smarcel panic("%s%d: initialisation failed with error %d\n", 215177108Sraj nif->nif_driver->netif_bname, nif->nif_unit, err); 216176348Smarcel 217176348Smarcel /* Get MAC address */ 218176348Smarcel di = ub_dev_get(sc->sc_handle); 219176348Smarcel memcpy(desc->myea, di->di_net.hwaddr, 6); 220176348Smarcel if (memcmp (desc->myea, "\0\0\0\0\0\0", 6) == 0) { 221176348Smarcel panic("%s%d: empty ethernet address!", 222177108Sraj nif->nif_driver->netif_bname, nif->nif_unit); 223176348Smarcel } 224176348Smarcel 225176348Smarcel#if defined(NETIF_DEBUG) 226176348Smarcel printf("network: %s%d attached to %s\n", nif->nif_driver->netif_bname, 227177108Sraj nif->nif_unit, ether_sprintf(desc->myea)); 228176348Smarcel#endif 229176348Smarcel 230176348Smarcel /* Set correct alignment for TX packets */ 231176348Smarcel sc->sc_txbufp = sc->sc_txbuf; 232176348Smarcel if ((unsigned long)sc->sc_txbufp % PKTALIGN) 233177152Sobrien sc->sc_txbufp += PKTALIGN - 234177152Sobrien (unsigned long)sc->sc_txbufp % PKTALIGN; 235176348Smarcel} 236176348Smarcel 237176348Smarcelstatic void 238176348Smarcelnet_end(struct netif *nif) 239176348Smarcel{ 240182723Sraj struct uboot_softc *sc = nif->nif_devdata; 241182723Sraj int err; 242176348Smarcel 243182723Sraj if ((err = ub_dev_close(sc->sc_handle)) != 0) 244176348Smarcel panic("%s%d: net_end failed with error %d\n", 245177108Sraj nif->nif_driver->netif_bname, nif->nif_unit, err); 246176348Smarcel} 247