1 /* $NetBSD: if_prom.c,v 1.3 2007/10/27 12:23:44 tsutsui Exp $ */ 2 3 /* Copyright (c) 1999 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Gregory McGarry. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/types.h> 41 42 #include <net/if_ether.h> 43 #include <netinet/in.h> 44 #include <netinet/in_systm.h> 45 #include <netinet/ip.h> 46 47 #include <lib/libsa/stand.h> 48 #include <lib/libsa/net.h> 49 #include <lib/libsa/netif.h> 50 #include <lib/libsa/dev_net.h> 51 #include <lib/libkern/libkern.h> 52 53 #include <machine/dec_prom.h> 54 #include <stand/common/common.h> 55 56 #ifdef NET_DEBUG 57 void dump_packet_info __P((void *, int)); 58 #endif 59 60 /* 61 * For some reason the proms won't pass arp responses back to us. I 62 * have checked if the first parameter to bootread/bootwrite do anything 63 * but it doesn't appear so. Therefore, we stop the upper layers from 64 * sending arp requests in the first place, by monitoring packets which 65 * come in and filling the arp cache ourselves. - gmcgarry 66 */ 67 #ifdef FILL_ARPCACHE 68 struct arp_list { 69 struct in_addr addr; 70 u_char ea[6]; 71 }; 72 extern struct arp_list arp_list[8]; 73 extern int arp_num; 74 void fill_arpcache __P((void *, int)); 75 #endif 76 77 /* forward declarations */ 78 int prom_probe __P((struct netif *, void *)); 79 int prom_match __P((struct netif *, void *)); 80 void prom_init __P((struct iodesc *, void *)); 81 int prom_get __P((struct iodesc *, void *, size_t, time_t)); 82 int prom_put __P((struct iodesc *, void *, size_t)); 83 void prom_end __P((struct netif *)); 84 85 extern struct netif_stats prom_stats[]; 86 struct netif_dif prom_ifs[] = { 87 /* dif_unit dif_nsel dif_stats dif_private */ 88 { 0, 1, &prom_stats[0], 0, }, 89 }; 90 #define NPROM_IFS (sizeof(prom_ifs) / sizeof(prom_ifs[0])) 91 struct netif_stats prom_stats[NPROM_IFS]; 92 93 struct netif_driver prom_netif_driver = { 94 "prom", /* netif_bname */ 95 prom_match, /* netif_match */ 96 prom_probe, /* netif_probe */ 97 prom_init, /* netif_init */ 98 prom_get, /* netif_get */ 99 prom_put, /* netif_put */ 100 prom_end, /* netif_end */ 101 prom_ifs, /* netif_ifs */ 102 NPROM_IFS /* netif_nifs */ 103 }; 104 105 static int sc_fd; /* PROM file id */ 106 107 int 108 prom_match(nif, machdep_hint) 109 struct netif *nif; 110 void *machdep_hint; 111 { 112 113 #ifdef NET_DEBUG 114 printf("prom_match: called\n"); 115 #endif 116 return (1); 117 } 118 119 120 int 121 prom_probe(nif, machdep_hint) 122 struct netif *nif; 123 void *machdep_hint; 124 { 125 126 #ifdef NET_DEBUG 127 printf("prom_probe: called\n"); 128 #endif 129 return 0; 130 } 131 132 133 void 134 prom_init(desc, machdep_hint) 135 struct iodesc *desc; 136 void *machdep_hint; 137 { 138 char *device = 139 ((struct netif *)desc->io_netif)->nif_driver->netif_bname; 140 char *c, *enet; 141 int i, j, num; 142 143 #ifdef NET_DEBUG 144 printf("prom_init: called\n"); 145 #endif 146 147 try_bootp = 1; 148 149 /* 150 * Get our hardware address (this prom call is one of the rare ones 151 * which is the same for new and old proms) 152 */ 153 enet = (*callv->_getenv)("enet"); 154 155 #ifdef NET_DEBUG 156 if (debug) 157 printf("enet=%s\n", enet); 158 #endif 159 160 i=0; 161 c = enet; 162 for (i=0; i<6; i++) { 163 j = *c - '0'; 164 num = (j<10?j:j-39); 165 num <<= 4; 166 c++; 167 j = *c - '0'; 168 num += (j<10?j:j-39); 169 desc->myea[i] = num; 170 c++; 171 c++; /* skip '-' */ 172 } 173 174 desc->xid = 0x66d30000; 175 176 if (callv == &callvec) 177 sc_fd = prom_open(device, 0); 178 else 179 sc_fd = (*callv->_bootinit)(device); 180 181 if (sc_fd < 0) 182 printf("problem initialising device\n"); 183 } 184 185 186 int 187 prom_put(desc, pkt, len) 188 struct iodesc *desc; 189 void *pkt; 190 size_t len; 191 { 192 int s; 193 194 #ifdef NET_DEBUG 195 printf("prom_put: called\n"); 196 #endif 197 198 #ifdef NET_DEBUG 199 if (debug) 200 dump_packet_info(pkt,len); 201 #endif 202 203 if (callv == &callvec) 204 s = prom_write(sc_fd, pkt, len); 205 else { 206 s = (*callv->_bootwrite)(0, pkt, len); 207 (*callv->_wbflush)(); /* didn't really make a difference */ 208 } 209 if (s < 0) 210 return (EIO); 211 return s; 212 } 213 214 215 int 216 prom_get(desc, pkt, len, timeout) 217 struct iodesc *desc; 218 void *pkt; 219 size_t len; 220 time_t timeout; 221 { 222 int s; 223 time_t t; 224 225 #ifdef NET_DEBUG 226 printf("prom_get: called\n"); 227 #endif 228 229 t = getsecs(); 230 s = 0; 231 while (((getsecs() - t) < timeout) && !s) { 232 if (callv == &callvec) 233 s = prom_read(sc_fd, pkt, len); 234 else 235 s = (*callv->_bootread)(0, pkt, len); 236 } 237 238 #ifdef FILL_ARPCACHE 239 if (s > 0) 240 fill_arpcache(pkt,s); 241 #endif 242 243 return s; 244 245 } 246 247 248 void 249 prom_end(nif) 250 struct netif *nif; 251 { 252 253 #ifdef NET_DEBUG 254 printf("prom_end: called\n"); 255 #endif 256 257 if (callv == &callvec) 258 prom_close(sc_fd); 259 } 260 261 262 #ifdef FILL_ARPCACHE 263 void fill_arpcache (pkt, len) 264 void *pkt; 265 int len; 266 { 267 int i; 268 struct arp_list *al; 269 struct ether_header *eh = (struct ether_header *)pkt; 270 struct ip *ih = (struct ip *)(eh + 1); 271 272 #ifdef NET_DEBUG 273 if (debug) 274 dump_packet_info(pkt, len); 275 #endif 276 277 if (ntohs(eh->ether_type) == 0x0800) { 278 279 /* check arp cache */ 280 for (i=0, al=arp_list; i<arp_num; ++i, ++al) { 281 if (al->addr.s_addr == ih->ip_src.s_addr) { 282 /* already in cache */ 283 return; 284 } 285 } 286 if (arp_num > 7) 287 arp_num = 1; /* recycle */ 288 al->addr.s_addr = ih->ip_src.s_addr; 289 for (i=0; i<6; i++) 290 al->ea[i] = eh->ether_shost[i]; 291 ++arp_num; 292 } 293 294 } 295 #endif 296 297 #ifdef NET_DEBUG 298 void dump_packet_info(pkt, len) 299 void *pkt; 300 int len; 301 { 302 struct ether_header *eh = (struct ether_header *)pkt; 303 struct ip *ih = (struct ip *)(eh + 1); 304 305 printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost)); 306 printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost)); 307 printf("ether_type = 0x%x\n", ntohs(eh->ether_type)); 308 309 if (ntohs(eh->ether_type) == 0x0800) { 310 printf("ip packet version %d\n", ih->ip_v); 311 printf("source ip: 0x%x\n", ih->ip_src.s_addr); 312 printf("dest ip: 0x%x\n", ih->ip_dst.s_addr); 313 314 } 315 316 } 317 #endif 318