1 /* $NetBSD: if_prom.c,v 1.2 2003/03/13 13:55:24 drochner 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/libkern/libkern.h> 51 52 #include <machine/dec_prom.h> 53 #include <stand/common/common.h> 54 55 #ifdef NET_DEBUG 56 void dump_packet_info __P((void *, int)); 57 #endif 58 59 /* 60 * For some reason the proms won't pass arp responses back to us. I 61 * have checked if the first parameter to bootread/bootwrite do anything 62 * but it doesn't appear so. Therefore, we stop the upper layers from 63 * sending arp requests in the first place, by monitoring packets which 64 * come in and filling the arp cache ourselves. - gmcgarry 65 */ 66 #ifdef FILL_ARPCACHE 67 struct arp_list { 68 struct in_addr addr; 69 u_char ea[6]; 70 }; 71 extern struct arp_list arp_list[8]; 72 extern int arp_num; 73 void fill_arpcache __P((void *, int)); 74 #endif 75 76 /* forward declarations */ 77 int prom_probe __P((struct netif *, void *)); 78 int prom_match __P((struct netif *, void *)); 79 void prom_init __P((struct iodesc *, void *)); 80 int prom_get __P((struct iodesc *, void *, size_t, time_t)); 81 int prom_put __P((struct iodesc *, void *, size_t)); 82 void prom_end __P((struct netif *)); 83 84 extern int try_bootp; 85 86 extern struct netif_stats prom_stats[]; 87 struct netif_dif prom_ifs[] = { 88 /* dif_unit dif_nsel dif_stats dif_private */ 89 { 0, 1, &prom_stats[0], 0, }, 90 }; 91 #define NPROM_IFS (sizeof(prom_ifs) / sizeof(prom_ifs[0])) 92 struct netif_stats prom_stats[NPROM_IFS]; 93 94 struct netif_driver prom_netif_driver = { 95 "prom", /* netif_bname */ 96 prom_match, /* netif_match */ 97 prom_probe, /* netif_probe */ 98 prom_init, /* netif_init */ 99 prom_get, /* netif_get */ 100 prom_put, /* netif_put */ 101 prom_end, /* netif_end */ 102 prom_ifs, /* netif_ifs */ 103 NPROM_IFS /* netif_nifs */ 104 }; 105 106 static int sc_fd; /* PROM file id */ 107 108 int 109 prom_match(nif, machdep_hint) 110 struct netif *nif; 111 void *machdep_hint; 112 { 113 114 #ifdef NET_DEBUG 115 printf("prom_match: called\n"); 116 #endif 117 return (1); 118 } 119 120 121 int 122 prom_probe(nif, machdep_hint) 123 struct netif *nif; 124 void *machdep_hint; 125 { 126 127 #ifdef NET_DEBUG 128 printf("prom_probe: called\n"); 129 #endif 130 return 0; 131 } 132 133 134 void 135 prom_init(desc, machdep_hint) 136 struct iodesc *desc; 137 void *machdep_hint; 138 { 139 char *device = 140 ((struct netif *)desc->io_netif)->nif_driver->netif_bname; 141 char *c, *enet; 142 int i, j, num; 143 144 #ifdef NET_DEBUG 145 printf("prom_init: called\n"); 146 #endif 147 148 try_bootp = 1; 149 150 /* 151 * Get our hardware address (this prom call is one of the rare ones 152 * which is the same for new and old proms) 153 */ 154 enet = (*callv->_getenv)("enet"); 155 156 #ifdef NET_DEBUG 157 if (debug) 158 printf("enet=%s\n", enet); 159 #endif 160 161 i=0; 162 c = enet; 163 for (i=0; i<6; i++) { 164 j = *c - '0'; 165 num = (j<10?j:j-39); 166 num <<= 4; 167 c++; 168 j = *c - '0'; 169 num += (j<10?j:j-39); 170 desc->myea[i] = num; 171 c++; 172 c++; /* skip '-' */ 173 } 174 175 desc->xid = 0x66d30000; 176 177 if (callv == &callvec) 178 sc_fd = prom_open(device, 0); 179 else 180 sc_fd = (*callv->_bootinit)(device); 181 182 if (sc_fd < 0) 183 printf("problem initialising device\n"); 184 } 185 186 187 int 188 prom_put(desc, pkt, len) 189 struct iodesc *desc; 190 void *pkt; 191 size_t len; 192 { 193 int s; 194 195 #ifdef NET_DEBUG 196 printf("prom_put: called\n"); 197 #endif 198 199 #ifdef NET_DEBUG 200 if (debug) 201 dump_packet_info(pkt,len); 202 #endif 203 204 if (callv == &callvec) 205 s = prom_write(sc_fd, pkt, len); 206 else { 207 s = (*callv->_bootwrite)(0, pkt, len); 208 (*callv->_wbflush)(); /* didn't really make a difference */ 209 } 210 if (s < 0) 211 return (EIO); 212 return s; 213 } 214 215 216 int 217 prom_get(desc, pkt, len, timeout) 218 struct iodesc *desc; 219 void *pkt; 220 size_t len; 221 time_t timeout; 222 { 223 int s; 224 time_t t; 225 226 #ifdef NET_DEBUG 227 printf("prom_get: called\n"); 228 #endif 229 230 t = getsecs(); 231 s = 0; 232 while (((getsecs() - t) < timeout) && !s) { 233 if (callv == &callvec) 234 s = prom_read(sc_fd, pkt, len); 235 else 236 s = (*callv->_bootread)(0, pkt, len); 237 } 238 239 #ifdef FILL_ARPCACHE 240 if (s > 0) 241 fill_arpcache(pkt,s); 242 #endif 243 244 return s; 245 246 } 247 248 249 void 250 prom_end(nif) 251 struct netif *nif; 252 { 253 254 #ifdef NET_DEBUG 255 printf("prom_end: called\n"); 256 #endif 257 258 if (callv == &callvec) 259 prom_close(sc_fd); 260 } 261 262 263 #ifdef FILL_ARPCACHE 264 void fill_arpcache (pkt, len) 265 void *pkt; 266 int len; 267 { 268 int i; 269 struct arp_list *al; 270 struct ether_header *eh = (struct ether_header *)pkt; 271 struct ip *ih = (struct ip *)(eh + 1); 272 273 #ifdef NET_DEBUG 274 if (debug) 275 dump_packet_info(pkt, len); 276 #endif 277 278 if (ntohs(eh->ether_type) == 0x0800) { 279 280 /* check arp cache */ 281 for (i=0, al=arp_list; i<arp_num; ++i, ++al) { 282 if (al->addr.s_addr == ih->ip_src.s_addr) { 283 /* already in cache */ 284 return; 285 } 286 } 287 if (arp_num > 7) 288 arp_num = 1; /* recycle */ 289 al->addr.s_addr = ih->ip_src.s_addr; 290 for (i=0; i<6; i++) 291 al->ea[i] = eh->ether_shost[i]; 292 ++arp_num; 293 } 294 295 } 296 #endif 297 298 #ifdef NET_DEBUG 299 void dump_packet_info(pkt, len) 300 void *pkt; 301 int len; 302 { 303 struct ether_header *eh = (struct ether_header *)pkt; 304 struct ip *ih = (struct ip *)(eh + 1); 305 306 printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost)); 307 printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost)); 308 printf("ether_type = 0x%x\n", ntohs(eh->ether_type)); 309 310 if (ntohs(eh->ether_type) == 0x0800) { 311 printf("ip packet version %d\n", ih->ip_v); 312 printf("source ip: 0x%x\n", ih->ip_src.s_addr); 313 printf("dest ip: 0x%x\n", ih->ip_dst.s_addr); 314 315 } 316 317 } 318 #endif 319