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