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