1 /* $NetBSD: if_prom.c,v 1.7 2009/03/14 15:36:12 dsl 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(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(void *, int); 67 #endif 68 69 /* forward declarations */ 70 int prom_probe(struct netif *, void *); 71 int prom_match(struct netif *, void *); 72 void prom_init(struct iodesc *, void *); 73 int prom_get(struct iodesc *, void *, size_t, saseconds_t); 74 int prom_put(struct iodesc *, void *, size_t); 75 void prom_end(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(struct netif *nif, void *machdep_hint) 101 { 102 103 #ifdef NET_DEBUG 104 printf("prom_match: called\n"); 105 #endif 106 return (1); 107 } 108 109 110 int 111 prom_probe(struct netif *nif, void *machdep_hint) 112 { 113 114 #ifdef NET_DEBUG 115 printf("prom_probe: called\n"); 116 #endif 117 return 0; 118 } 119 120 121 void 122 prom_init(struct iodesc *desc, void *machdep_hint) 123 { 124 char *device = 125 ((struct netif *)desc->io_netif)->nif_driver->netif_bname; 126 char *c, *enet; 127 int i, j, num; 128 129 #ifdef NET_DEBUG 130 printf("prom_init: called\n"); 131 #endif 132 133 try_bootp = 1; 134 135 /* 136 * Get our hardware address (this prom call is one of the rare ones 137 * which is the same for new and old proms) 138 */ 139 enet = (*callv->_getenv)("enet"); 140 141 #ifdef NET_DEBUG 142 if (debug) 143 printf("enet=%s\n", enet); 144 #endif 145 146 i=0; 147 c = enet; 148 for (i=0; i<6; i++) { 149 j = *c - '0'; 150 num = (j<10?j:j-39); 151 num <<= 4; 152 c++; 153 j = *c - '0'; 154 num += (j<10?j:j-39); 155 desc->myea[i] = num; 156 c++; 157 c++; /* skip '-' */ 158 } 159 160 desc->xid = 0x66d30000; 161 162 if (callv == &callvec) 163 sc_fd = prom_open(device, 0); 164 else 165 sc_fd = (*callv->_bootinit)(device); 166 167 if (sc_fd < 0) 168 printf("problem initialising device\n"); 169 } 170 171 172 int 173 prom_put(struct iodesc *desc, void *pkt, size_t len) 174 { 175 int s; 176 177 #ifdef NET_DEBUG 178 printf("prom_put: called\n"); 179 #endif 180 181 #ifdef NET_DEBUG 182 if (debug) 183 dump_packet_info(pkt,len); 184 #endif 185 186 if (callv == &callvec) 187 s = prom_write(sc_fd, pkt, len); 188 else { 189 s = (*callv->_bootwrite)(0, pkt, len); 190 (*callv->_wbflush)(); /* didn't really make a difference */ 191 } 192 if (s < 0) 193 return (EIO); 194 return s; 195 } 196 197 198 int 199 prom_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) 200 { 201 int s; 202 satime_t t; 203 204 #ifdef NET_DEBUG 205 printf("prom_get: called\n"); 206 #endif 207 208 t = getsecs(); 209 s = 0; 210 while (((getsecs() - t) < timeout) && !s) { 211 if (callv == &callvec) 212 s = prom_read(sc_fd, pkt, len); 213 else 214 s = (*callv->_bootread)(0, pkt, len); 215 } 216 217 #ifdef FILL_ARPCACHE 218 if (s > 0) 219 fill_arpcache(pkt,s); 220 #endif 221 222 return s; 223 224 } 225 226 227 void 228 prom_end(struct netif *nif) 229 { 230 231 #ifdef NET_DEBUG 232 printf("prom_end: called\n"); 233 #endif 234 235 if (callv == &callvec) 236 prom_close(sc_fd); 237 } 238 239 240 #ifdef FILL_ARPCACHE 241 void fill_arpcache (pkt, len) 242 void *pkt; 243 int len; 244 { 245 int i; 246 struct arp_list *al; 247 struct ether_header *eh = (struct ether_header *)pkt; 248 struct ip *ih = (struct ip *)(eh + 1); 249 250 #ifdef NET_DEBUG 251 if (debug) 252 dump_packet_info(pkt, len); 253 #endif 254 255 if (ntohs(eh->ether_type) == 0x0800) { 256 257 /* check arp cache */ 258 for (i=0, al=arp_list; i<arp_num; ++i, ++al) { 259 if (al->addr.s_addr == ih->ip_src.s_addr) { 260 /* already in cache */ 261 return; 262 } 263 } 264 if (arp_num > 7) 265 arp_num = 1; /* recycle */ 266 al->addr.s_addr = ih->ip_src.s_addr; 267 for (i=0; i<6; i++) 268 al->ea[i] = eh->ether_shost[i]; 269 ++arp_num; 270 } 271 272 } 273 #endif 274 275 #ifdef NET_DEBUG 276 void dump_packet_info(pkt, len) 277 void *pkt; 278 int len; 279 { 280 struct ether_header *eh = (struct ether_header *)pkt; 281 struct ip *ih = (struct ip *)(eh + 1); 282 283 printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost)); 284 printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost)); 285 printf("ether_type = 0x%x\n", ntohs(eh->ether_type)); 286 287 if (ntohs(eh->ether_type) == 0x0800) { 288 printf("ip packet version %d\n", ih->ip_v); 289 printf("source ip: 0x%x\n", ih->ip_src.s_addr); 290 printf("dest ip: 0x%x\n", ih->ip_dst.s_addr); 291 292 } 293 294 } 295 #endif 296