if_prom.c revision 1.1 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