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