1 1.14 tsutsui /* $NetBSD: netif_of.c,v 1.14 2009/01/28 13:10:05 tsutsui Exp $ */ 2 1.1 tsubai 3 1.1 tsubai /* 4 1.1 tsubai * Copyright (C) 1995 Wolfgang Solfrank. 5 1.1 tsubai * Copyright (C) 1995 TooLs GmbH. 6 1.1 tsubai * All rights reserved. 7 1.1 tsubai * 8 1.1 tsubai * Redistribution and use in source and binary forms, with or without 9 1.1 tsubai * modification, are permitted provided that the following conditions 10 1.1 tsubai * are met: 11 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 12 1.1 tsubai * notice, this list of conditions and the following disclaimer. 13 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 15 1.1 tsubai * documentation and/or other materials provided with the distribution. 16 1.1 tsubai * 3. All advertising materials mentioning features or use of this software 17 1.1 tsubai * must display the following acknowledgement: 18 1.1 tsubai * This product includes software developed by TooLs GmbH. 19 1.1 tsubai * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 1.1 tsubai * derived from this software without specific prior written permission. 21 1.1 tsubai * 22 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 1.1 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 1.1 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 1.1 tsubai * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 1.1 tsubai * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 1.1 tsubai * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 1.1 tsubai * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 1.1 tsubai * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 1.1 tsubai * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 1.1 tsubai * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 tsubai */ 33 1.1 tsubai 34 1.1 tsubai /* 35 1.1 tsubai * Open Firmware does most of the job for interfacing to the hardware, 36 1.1 tsubai * so it is easiest to just replace the netif module with 37 1.1 tsubai * this adaptation to the PROM network interface. 38 1.1 tsubai * 39 1.1 tsubai * Note: this is based in part on sys/arch/sparc/stand/netif_sun.c 40 1.1 tsubai */ 41 1.1 tsubai 42 1.1 tsubai #include <sys/param.h> 43 1.1 tsubai #include <sys/socket.h> 44 1.1 tsubai 45 1.1 tsubai #include <net/if.h> 46 1.1 tsubai #include <net/if_ether.h> 47 1.1 tsubai 48 1.1 tsubai #include <netinet/in.h> 49 1.1 tsubai #include <netinet/in_systm.h> 50 1.1 tsubai 51 1.1 tsubai #include <lib/libsa/stand.h> 52 1.1 tsubai #include <lib/libsa/net.h> 53 1.1 tsubai 54 1.1 tsubai #include "ofdev.h" 55 1.1 tsubai #include "openfirm.h" 56 1.1 tsubai 57 1.6 drochner #include "netif_of.h" 58 1.1 tsubai 59 1.8 drochner static struct iodesc sdesc; 60 1.1 tsubai 61 1.1 tsubai struct iodesc * 62 1.9 aymeric socktodesc(int sock) 63 1.1 tsubai { 64 1.1 tsubai if (sock != 0) 65 1.1 tsubai return NULL; 66 1.8 drochner return &sdesc; 67 1.1 tsubai } 68 1.1 tsubai 69 1.1 tsubai int 70 1.9 aymeric netif_of_open(struct of_dev *op) 71 1.1 tsubai { 72 1.1 tsubai struct iodesc *io; 73 1.12 tsutsui int rv; 74 1.5 tsutsui 75 1.1 tsubai #ifdef NETIF_DEBUG 76 1.1 tsubai printf("netif_open..."); 77 1.1 tsubai #endif 78 1.1 tsubai /* find a free socket */ 79 1.8 drochner io = &sdesc; 80 1.1 tsubai if (io->io_netif) { 81 1.1 tsubai #ifdef NETIF_DEBUG 82 1.1 tsubai printf("device busy\n"); 83 1.1 tsubai #endif 84 1.1 tsubai errno = ENFILE; 85 1.1 tsubai return -1; 86 1.1 tsubai } 87 1.4 wiz memset(io, 0, sizeof *io); 88 1.1 tsubai 89 1.8 drochner io->io_netif = (void *)op; 90 1.5 tsutsui 91 1.1 tsubai /* Put our ethernet address in io->myea */ 92 1.12 tsutsui rv = OF_getprop(OF_instance_to_package(op->handle), 93 1.12 tsutsui "local-mac-address", io->myea, sizeof io->myea); 94 1.12 tsutsui if (rv == -1) 95 1.12 tsutsui OF_getprop(OF_instance_to_package(op->handle), 96 1.12 tsutsui "mac-address", io->myea, sizeof io->myea); 97 1.1 tsubai 98 1.1 tsubai #ifdef NETIF_DEBUG 99 1.1 tsubai printf("OK\n"); 100 1.1 tsubai #endif 101 1.1 tsubai return 0; 102 1.1 tsubai } 103 1.1 tsubai 104 1.7 drochner void 105 1.9 aymeric netif_of_close(int fd) 106 1.1 tsubai { 107 1.1 tsubai struct iodesc *io; 108 1.1 tsubai 109 1.1 tsubai #ifdef NETIF_DEBUG 110 1.1 tsubai printf("netif_close(%x)...", fd); 111 1.1 tsubai #endif 112 1.7 drochner 113 1.7 drochner #ifdef NETIF_DEBUG 114 1.1 tsubai if (fd != 0) { 115 1.1 tsubai printf("EBADF\n"); 116 1.7 drochner return; 117 1.7 drochner } 118 1.1 tsubai #endif 119 1.1 tsubai 120 1.8 drochner io = &sdesc; 121 1.6 drochner io->io_netif = NULL; 122 1.6 drochner 123 1.1 tsubai #ifdef NETIF_DEBUG 124 1.1 tsubai printf("OK\n"); 125 1.1 tsubai #endif 126 1.1 tsubai } 127 1.1 tsubai 128 1.1 tsubai /* 129 1.1 tsubai * Send a packet. The ether header is already there. 130 1.1 tsubai * Return the length sent (or -1 on error). 131 1.1 tsubai */ 132 1.1 tsubai ssize_t 133 1.9 aymeric netif_put(struct iodesc *desc, void *pkt, size_t len) 134 1.1 tsubai { 135 1.1 tsubai struct of_dev *op; 136 1.1 tsubai ssize_t rv; 137 1.1 tsubai size_t sendlen; 138 1.1 tsubai 139 1.8 drochner op = (struct of_dev *)desc->io_netif; 140 1.1 tsubai 141 1.1 tsubai #ifdef NETIF_DEBUG 142 1.1 tsubai { 143 1.1 tsubai struct ether_header *eh; 144 1.1 tsubai 145 1.1 tsubai printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", 146 1.14 tsutsui (u_int)desc, (u_int)pkt, len); 147 1.1 tsubai eh = pkt; 148 1.1 tsubai printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 149 1.1 tsubai printf("src: %s ", ether_sprintf(eh->ether_shost)); 150 1.1 tsubai printf("type: 0x%x\n", eh->ether_type & 0xFFFF); 151 1.1 tsubai } 152 1.1 tsubai #endif 153 1.1 tsubai 154 1.1 tsubai sendlen = len; 155 1.1 tsubai if (sendlen < 60) { 156 1.1 tsubai sendlen = 60; 157 1.1 tsubai #ifdef NETIF_DEBUG 158 1.1 tsubai printf("netif_put: length padded to %d\n", sendlen); 159 1.1 tsubai #endif 160 1.1 tsubai } 161 1.1 tsubai 162 1.3 tsubai if (op->dmabuf) { 163 1.4 wiz memcpy(op->dmabuf, pkt, sendlen); 164 1.3 tsubai pkt = op->dmabuf; 165 1.3 tsubai } 166 1.1 tsubai rv = OF_write(op->handle, pkt, sendlen); 167 1.1 tsubai 168 1.1 tsubai #ifdef NETIF_DEBUG 169 1.1 tsubai printf("netif_put: xmit returned %d\n", rv); 170 1.1 tsubai #endif 171 1.1 tsubai 172 1.1 tsubai return rv; 173 1.1 tsubai } 174 1.1 tsubai 175 1.1 tsubai /* 176 1.1 tsubai * Receive a packet, including the ether header. 177 1.1 tsubai * Return the total length received (or -1 on error). 178 1.1 tsubai */ 179 1.1 tsubai ssize_t 180 1.13 tsutsui netif_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timo) 181 1.1 tsubai { 182 1.1 tsubai struct of_dev *op; 183 1.1 tsubai int tick0, tmo_ms; 184 1.1 tsubai int len; 185 1.1 tsubai 186 1.8 drochner op = (struct of_dev *)desc->io_netif; 187 1.1 tsubai 188 1.1 tsubai #ifdef NETIF_DEBUG 189 1.1 tsubai printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", 190 1.14 tsutsui (u_int)pkt, maxlen, timo); 191 1.1 tsubai #endif 192 1.1 tsubai 193 1.1 tsubai tmo_ms = timo * 1000; 194 1.1 tsubai tick0 = OF_milliseconds(); 195 1.1 tsubai 196 1.1 tsubai do { 197 1.1 tsubai len = OF_read(op->handle, pkt, maxlen); 198 1.1 tsubai } while ((len == -2 || len == 0) && 199 1.1 tsubai (OF_milliseconds() - tick0 < tmo_ms)); 200 1.1 tsubai 201 1.1 tsubai #ifdef NETIF_DEBUG 202 1.1 tsubai printf("netif_get: received len=%d\n", len); 203 1.1 tsubai #endif 204 1.1 tsubai 205 1.1 tsubai if (len < 12) 206 1.1 tsubai return -1; 207 1.1 tsubai 208 1.1 tsubai #ifdef NETIF_DEBUG 209 1.1 tsubai { 210 1.1 tsubai struct ether_header *eh = pkt; 211 1.1 tsubai 212 1.1 tsubai printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 213 1.1 tsubai printf("src: %s ", ether_sprintf(eh->ether_shost)); 214 1.1 tsubai printf("type: 0x%x\n", eh->ether_type & 0xFFFF); 215 1.1 tsubai } 216 1.1 tsubai #endif 217 1.1 tsubai 218 1.1 tsubai return len; 219 1.1 tsubai } 220 1.1 tsubai 221 1.1 tsubai /* 222 1.1 tsubai * Shouldn't really be here, but is used solely for networking, so... 223 1.1 tsubai */ 224 1.13 tsutsui satime_t 225 1.9 aymeric getsecs(void) 226 1.1 tsubai { 227 1.13 tsutsui 228 1.1 tsubai return OF_milliseconds() / 1000; 229 1.1 tsubai } 230