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