1 /* $NetBSD: if_prom.c,v 1.1 2002/02/23 21:44:00 gmcgarry 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 struct netif_stats prom_stats[NENTS(prom_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 NENTS(prom_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 = desc->io_netif->nif_driver->netif_bname; 139 char *c, *enet; 140 int i, j, num; 141 142 #ifdef NET_DEBUG 143 printf("prom_init: called\n"); 144 #endif 145 146 try_bootp = 1; 147 148 /* 149 * Get our hardware address (this prom call is one of the rare ones 150 * which is the same for new and old proms) 151 */ 152 enet = (*callv->_getenv)("enet"); 153 154 #ifdef NET_DEBUG 155 if (debug) 156 printf("enet=%s\n", enet); 157 #endif 158 159 i=0; 160 c = enet; 161 for (i=0; i<6; i++) { 162 j = *c - '0'; 163 num = (j<10?j:j-39); 164 num <<= 4; 165 c++; 166 j = *c - '0'; 167 num += (j<10?j:j-39); 168 desc->myea[i] = num; 169 c++; 170 c++; /* skip '-' */ 171 } 172 173 desc->xid = 0x66d30000; 174 175 if (callv == &callvec) 176 sc_fd = prom_open(device, 0); 177 else 178 sc_fd = (*callv->_bootinit)(device); 179 180 if (sc_fd < 0) 181 printf("problem initialising device\n"); 182 } 183 184 185 int 186 prom_put(desc, pkt, len) 187 struct iodesc *desc; 188 void *pkt; 189 size_t len; 190 { 191 int s; 192 193 #ifdef NET_DEBUG 194 printf("prom_put: called\n"); 195 #endif 196 197 #ifdef NET_DEBUG 198 if (debug) 199 dump_packet_info(pkt,len); 200 #endif 201 202 if (callv == &callvec) 203 s = prom_write(sc_fd, pkt, len); 204 else { 205 s = (*callv->_bootwrite)(0, pkt, len); 206 (*callv->_wbflush)(); /* didn't really make a difference */ 207 } 208 if (s < 0) 209 return (EIO); 210 return s; 211 } 212 213 214 int 215 prom_get(desc, pkt, len, timeout) 216 struct iodesc *desc; 217 void *pkt; 218 size_t len; 219 time_t timeout; 220 { 221 int s; 222 time_t t; 223 224 #ifdef NET_DEBUG 225 printf("prom_get: called\n"); 226 #endif 227 228 t = getsecs(); 229 s = 0; 230 while (((getsecs() - t) < timeout) && !s) { 231 if (callv == &callvec) 232 s = prom_read(sc_fd, pkt, len); 233 else 234 s = (*callv->_bootread)(0, pkt, len); 235 } 236 237 #ifdef FILL_ARPCACHE 238 if (s > 0) 239 fill_arpcache(pkt,s); 240 #endif 241 242 return s; 243 244 } 245 246 247 void 248 prom_end(nif) 249 struct netif *nif; 250 { 251 252 #ifdef NET_DEBUG 253 printf("prom_end: called\n"); 254 #endif 255 256 if (callv == &callvec) 257 prom_close(sc_fd); 258 } 259 260 261 #ifdef FILL_ARPCACHE 262 void fill_arpcache (pkt, len) 263 void *pkt; 264 int len; 265 { 266 int i; 267 struct arp_list *al; 268 struct ether_header *eh = (struct ether_header *)pkt; 269 struct ip *ih = (struct ip *)(eh + 1); 270 271 #ifdef NET_DEBUG 272 if (debug) 273 dump_packet_info(pkt, len); 274 #endif 275 276 if (ntohs(eh->ether_type) == 0x0800) { 277 278 /* check arp cache */ 279 for (i=0, al=arp_list; i<arp_num; ++i, ++al) { 280 if (al->addr.s_addr == ih->ip_src.s_addr) { 281 /* already in cache */ 282 return; 283 } 284 } 285 if (arp_num > 7) 286 arp_num = 1; /* recycle */ 287 al->addr.s_addr = ih->ip_src.s_addr; 288 for (i=0; i<6; i++) 289 al->ea[i] = eh->ether_shost[i]; 290 ++arp_num; 291 } 292 293 } 294 #endif 295 296 #ifdef NET_DEBUG 297 void dump_packet_info(pkt, len) 298 void *pkt; 299 int len; 300 { 301 struct ether_header *eh = (struct ether_header *)pkt; 302 struct ip *ih = (struct ip *)(eh + 1); 303 304 printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost)); 305 printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost)); 306 printf("ether_type = 0x%x\n", ntohs(eh->ether_type)); 307 308 if (ntohs(eh->ether_type) == 0x0800) { 309 printf("ip packet version %d\n", ih->ip_v); 310 printf("source ip: 0x%x\n", ih->ip_src.s_addr); 311 printf("dest ip: 0x%x\n", ih->ip_dst.s_addr); 312 313 } 314 315 } 316 #endif 317