xref: /netbsd-src/sys/arch/pmax/stand/common/if_prom.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*      $NetBSD: if_prom.c,v 1.2 2003/03/13 13:55:24 drochner 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 #define NPROM_IFS (sizeof(prom_ifs) / sizeof(prom_ifs[0]))
92 struct netif_stats prom_stats[NPROM_IFS];
93 
94 struct netif_driver prom_netif_driver = {
95 	"prom",				/* netif_bname */
96 	prom_match,			/* netif_match */
97 	prom_probe,			/* netif_probe */
98 	prom_init,			/* netif_init */
99 	prom_get,			/* netif_get */
100 	prom_put,			/* netif_put */
101 	prom_end,			/* netif_end */
102 	prom_ifs,			/* netif_ifs */
103 	NPROM_IFS			/* netif_nifs */
104 };
105 
106 static int sc_fd;				/* PROM file id */
107 
108 int
109 prom_match(nif, machdep_hint)
110 	struct netif *nif;
111 	void *machdep_hint;
112 {
113 
114 #ifdef NET_DEBUG
115 	printf("prom_match: called\n");
116 #endif
117 	return (1);
118 }
119 
120 
121 int
122 prom_probe(nif, machdep_hint)
123 	struct netif *nif;
124 	void *machdep_hint;
125 {
126 
127 #ifdef NET_DEBUG
128 	printf("prom_probe: called\n");
129 #endif
130 	return 0;
131 }
132 
133 
134 void
135 prom_init(desc, machdep_hint)
136 	struct iodesc *desc;
137 	void *machdep_hint;
138 {
139 	char *device =
140 		((struct netif *)desc->io_netif)->nif_driver->netif_bname;
141 	char *c, *enet;
142 	int i, j, num;
143 
144 #ifdef NET_DEBUG
145 	printf("prom_init: called\n");
146 #endif
147 
148 	try_bootp = 1;
149 
150 	/*
151 	 * Get our hardware address (this prom call is one of the rare ones
152          * which is the same for new and old proms)
153          */
154 	enet = (*callv->_getenv)("enet");
155 
156 #ifdef NET_DEBUG
157 	if (debug)
158 		printf("enet=%s\n", enet);
159 #endif
160 
161 	i=0;
162 	c = enet;
163 	for (i=0; i<6; i++) {
164 		j = *c - '0';
165 		num = (j<10?j:j-39);
166 		num <<= 4;
167 		c++;
168 		j = *c - '0';
169 		num += (j<10?j:j-39);
170 		desc->myea[i] = num;
171 		c++;
172 		c++; /* skip '-' */
173 	}
174 
175 	desc->xid = 0x66d30000;
176 
177 	if (callv == &callvec)
178 		sc_fd = prom_open(device, 0);
179 	else
180 		sc_fd = (*callv->_bootinit)(device);
181 
182 	if (sc_fd < 0)
183 		printf("problem initialising device\n");
184 }
185 
186 
187 int
188 prom_put(desc, pkt, len)
189 	struct iodesc *desc;
190 	void *pkt;
191 	size_t len;
192 {
193 	int s;
194 
195 #ifdef NET_DEBUG
196 	printf("prom_put: called\n");
197 #endif
198 
199 #ifdef NET_DEBUG
200 	if (debug)
201 		dump_packet_info(pkt,len);
202 #endif
203 
204 	if (callv == &callvec)
205 		s = prom_write(sc_fd, pkt, len);
206 	else {
207 		s = (*callv->_bootwrite)(0, pkt, len);
208 		(*callv->_wbflush)(); /* didn't really make a difference */
209 	}
210 	if (s < 0)
211 		return (EIO);
212 	return s;
213 }
214 
215 
216 int
217 prom_get(desc, pkt, len, timeout)
218 	struct iodesc *desc;
219 	void *pkt;
220 	size_t len;
221 	time_t timeout;
222 {
223 	int s;
224 	time_t t;
225 
226 #ifdef NET_DEBUG
227 	printf("prom_get: called\n");
228 #endif
229 
230 	t = getsecs();
231 	s = 0;
232 	while (((getsecs() - t) < timeout) && !s) {
233 		if (callv == &callvec)
234 			s = prom_read(sc_fd, pkt, len);
235 		else
236 			s = (*callv->_bootread)(0, pkt, len);
237 	}
238 
239 #ifdef FILL_ARPCACHE
240 	if (s > 0)
241 		fill_arpcache(pkt,s);
242 #endif
243 
244 	return s;
245 
246 }
247 
248 
249 void
250 prom_end(nif)
251 	struct netif *nif;
252 {
253 
254 #ifdef NET_DEBUG
255 	printf("prom_end: called\n");
256 #endif
257 
258 	if (callv == &callvec)
259 		prom_close(sc_fd);
260 }
261 
262 
263 #ifdef FILL_ARPCACHE
264 void fill_arpcache (pkt, len)
265 	void *pkt;
266 	int len;
267 {
268 	int i;
269 	struct arp_list *al;
270 	struct ether_header *eh = (struct ether_header *)pkt;
271 	struct ip *ih = (struct ip *)(eh + 1);
272 
273 #ifdef NET_DEBUG
274 	if (debug)
275 		dump_packet_info(pkt, len);
276 #endif
277 
278 	if (ntohs(eh->ether_type) == 0x0800) {
279 
280 		/* check arp cache */
281 		for (i=0, al=arp_list; i<arp_num; ++i, ++al) {
282 			if (al->addr.s_addr == ih->ip_src.s_addr) {
283 				/* already in cache */
284 				return;
285 			}
286 		}
287         	if (arp_num > 7)
288                		arp_num = 1;    /* recycle */
289 		al->addr.s_addr = ih->ip_src.s_addr;
290 		for (i=0; i<6; i++)
291 			al->ea[i] = eh->ether_shost[i];
292 		++arp_num;
293 	}
294 
295 }
296 #endif
297 
298 #ifdef NET_DEBUG
299 void dump_packet_info(pkt, len)
300 	void *pkt;
301 	int len;
302 {
303 	struct ether_header *eh = (struct ether_header *)pkt;
304 	struct ip *ih = (struct ip *)(eh + 1);
305 
306 	printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost));
307 	printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost));
308 	printf("ether_type = 0x%x\n", ntohs(eh->ether_type));
309 
310 	if (ntohs(eh->ether_type) == 0x0800) {
311 		printf("ip packet version %d\n", ih->ip_v);
312 		printf("source ip: 0x%x\n", ih->ip_src.s_addr);
313 		printf("dest ip: 0x%x\n", ih->ip_dst.s_addr);
314 
315 	}
316 
317 }
318 #endif
319