xref: /netbsd-src/sys/arch/pmax/stand/common/if_prom.c (revision e3b6673e18064f1bd82f8b1736012d1a58e7cae8)
1 /*      $NetBSD: if_prom.c,v 1.11 2011/01/12 15:32:43 tsutsui 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 #define DPRINTF(x)	printf(x)
50 #else
51 #define DPRINTF(x)
52 #endif
53 
54 #ifdef NET_DEBUG
55 void dump_packet_info(void *, int);
56 #endif
57 
58 /*
59  *  For some reason the proms won't pass arp responses back to us.  I
60  *  have checked if the first parameter to bootread/bootwrite do anything
61  *  but it doesn't appear so.  Therefore, we stop the upper layers from
62  *  sending arp requests in the first place, by monitoring packets which
63  *  come in and filling the arp cache ourselves.  - gmcgarry
64  */
65 #ifdef FILL_ARPCACHE
66 struct arp_list {
67 	struct in_addr	addr;
68 	u_char		ea[6];
69 };
70 extern struct arp_list arp_list[8];
71 extern int arp_num;
72 void fill_arpcache(void *, int);
73 #endif
74 
75 /* forward declarations */
76 int prom_probe(struct netif *, void *);
77 int prom_match(struct netif *, void *);
78 void prom_init(struct iodesc *, void *);
79 int prom_get(struct iodesc *, void *, size_t, saseconds_t);
80 int prom_put(struct iodesc *, void *, size_t);
81 void prom_end(struct netif *);
82 
83 extern struct netif_stats       prom_stats[];
84 struct netif_dif prom_ifs[] = {
85 /*	dif_unit	dif_nsel	dif_stats	dif_private	*/
86 {	0,		1,		&prom_stats[0],	0,		},
87 };
88 #define NPROM_IFS (sizeof(prom_ifs) / sizeof(prom_ifs[0]))
89 struct netif_stats prom_stats[NPROM_IFS];
90 
91 struct netif_driver prom_netif_driver = {
92 	"prom",				/* netif_bname */
93 	prom_match,			/* netif_match */
94 	prom_probe,			/* netif_probe */
95 	prom_init,			/* netif_init */
96 	prom_get,			/* netif_get */
97 	prom_put,			/* netif_put */
98 	prom_end,			/* netif_end */
99 	prom_ifs,			/* netif_ifs */
100 	NPROM_IFS			/* netif_nifs */
101 };
102 
103 static int sc_fd;				/* PROM file id */
104 
105 int
prom_match(struct netif * nif,void * machdep_hint)106 prom_match(struct netif *nif, void *machdep_hint)
107 {
108 
109 	DPRINTF(("prom_match: called\n"));
110 	return 1;
111 }
112 
113 
114 int
prom_probe(struct netif * nif,void * machdep_hint)115 prom_probe(struct netif *nif, void *machdep_hint)
116 {
117 
118 	DPRINTF(("prom_probe: called\n"));
119 	return 0;
120 }
121 
122 
123 void
prom_init(struct iodesc * desc,void * machdep_hint)124 prom_init(struct iodesc *desc, void *machdep_hint)
125 {
126 	struct netif *nif;
127 	char *device, *enet;
128 	uint8_t *cp, *dest;
129 	int i;
130 
131 	DPRINTF(("prom_init: called\n"));
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 	if (enet == NULL) {
142 		printf("No `enet' environment variable found.\n"
143 		    "Set MAC address to `enet' manually by setenv command.\n");
144 		prom_restart();
145 		/* NOTREACHED */
146 	}
147 
148 #ifdef NET_DEBUG
149 	if (debug)
150 		printf("enet=%s\n", enet);
151 #endif
152 
153 #define atox(c)	(((c) <= '9') ? ((c) - '0') : ((toupper(c) - 'A') + 10))
154 
155 	cp = (uint8_t *)enet;
156 	dest = desc->myea;
157 	for (i = 0; i < 6; i++) {
158 		if (isxdigit(*cp)) {
159 			*dest = atox(*cp);
160 			cp++;
161 			if (isxdigit(*cp)) {
162 				*dest = (*dest << 4) | atox(*cp);
163 				cp++;
164 			}
165 		}
166 		dest++;
167 		cp++;	/* skip '-' or ':' etc. */
168 	}
169 
170 	desc->xid = 0x66d30000;
171 
172 	nif = desc->io_netif;
173 	device = nif->nif_driver->netif_bname;
174 	if (callv == &callvec)
175 		sc_fd = prom_open(device, 0);
176 	else
177 		sc_fd = (*callv->_bootinit)(device);
178 
179 	if (sc_fd < 0)
180 		printf("problem initialising device\n");
181 }
182 
183 
184 int
prom_put(struct iodesc * desc,void * pkt,size_t len)185 prom_put(struct iodesc *desc, void *pkt, size_t len)
186 {
187 	int s;
188 
189 	DPRINTF(("prom_put: called\n"));
190 
191 #ifdef NET_DEBUG
192 	if (debug)
193 		dump_packet_info(pkt,len);
194 #endif
195 
196 	if (callv == &callvec)
197 		s = prom_write(sc_fd, pkt, len);
198 	else {
199 		s = (*callv->_bootwrite)(0, pkt, len);
200 		(*callv->_wbflush)(); /* didn't really make a difference */
201 	}
202 	if (s < 0)
203 		return EIO;
204 	return s;
205 }
206 
207 
208 int
prom_get(struct iodesc * desc,void * pkt,size_t len,saseconds_t timeout)209 prom_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout)
210 {
211 	int s;
212 	satime_t t;
213 
214 	DPRINTF(("prom_get: called\n"));
215 
216 	t = getsecs();
217 	s = 0;
218 	while (((getsecs() - t) < timeout) && !s) {
219 		if (callv == &callvec)
220 			s = prom_read(sc_fd, pkt, len);
221 		else
222 			s = (*callv->_bootread)(0, pkt, len);
223 	}
224 
225 #ifdef FILL_ARPCACHE
226 	if (s > 0)
227 		fill_arpcache(pkt,s);
228 #endif
229 
230 	return s;
231 }
232 
233 
234 void
prom_end(struct netif * nif)235 prom_end(struct netif *nif)
236 {
237 
238 	DPRINTF(("prom_end: called\n"));
239 
240 	if (callv == &callvec)
241 		prom_close(sc_fd);
242 }
243 
244 
245 #ifdef FILL_ARPCACHE
246 void
fill_arpcache(void * pkt,int len)247 fill_arpcache(void *pkt, int len)
248 {
249 	int i;
250 	struct arp_list *al;
251 	struct ether_header *eh = (struct ether_header *)pkt;
252 	struct ip *ih = (struct ip *)(eh + 1);
253 
254 #ifdef NET_DEBUG
255 	if (debug)
256 		dump_packet_info(pkt, len);
257 #endif
258 
259 	if (ntohs(eh->ether_type) == 0x0800) {
260 
261 		/* check arp cache */
262 		for (i=0, al=arp_list; i<arp_num; ++i, ++al) {
263 			if (al->addr.s_addr == ih->ip_src.s_addr) {
264 				/* already in cache */
265 				return;
266 			}
267 		}
268 		if (arp_num > 7)
269 			arp_num = 1;	/* recycle */
270 		al->addr.s_addr = ih->ip_src.s_addr;
271 		for (i = 0; i < 6; i++)
272 			al->ea[i] = eh->ether_shost[i];
273 		++arp_num;
274 	}
275 }
276 #endif
277 
278 #ifdef NET_DEBUG
279 void
dump_packet_info(void * pkt,int len)280 dump_packet_info(void *pkt, int len)
281 {
282 	struct ether_header *eh = (struct ether_header *)pkt;
283 	struct ip *ih = (struct ip *)(eh + 1);
284 
285 	printf("ether_dhost = %s\n", ether_sprintf(eh->ether_dhost));
286 	printf("ether_shost = %s\n", ether_sprintf(eh->ether_shost));
287 	printf("ether_type = 0x%x\n", ntohs(eh->ether_type));
288 
289 	if (ntohs(eh->ether_type) == 0x0800) {
290 		printf("ip packet version %d\n", ih->ip_v);
291 		printf("source ip: 0x%x\n", ih->ip_src.s_addr);
292 		printf("dest ip: 0x%x\n", ih->ip_dst.s_addr);
293 	}
294 }
295 #endif
296