ofw_net.c revision 82343
1/*
2 * Copyright (c) 2000 Benno Rice
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/boot/ofw/libofw/ofw_net.c 82343 2001-08-26 07:07:47Z benno $
27 */
28
29#include <sys/param.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32
33#include <net/if.h>
34#include <netinet/in.h>
35#include <netinet/in_systm.h>
36#include <netinet/if_ether.h>
37#include <netinet/ip.h>
38
39#include <stand.h>
40#include <net.h>
41#include <netif.h>
42
43#include "openfirm.h"
44
45static int	ofwn_probe(struct netif *, void *);
46static int	ofwn_match(struct netif *, void *);
47static void	ofwn_init(struct iodesc *, void *);
48static int	ofwn_get(struct iodesc *, void *, int, time_t);
49static int	ofwn_put(struct iodesc *, void *, int);
50static void	ofwn_end(struct netif *);
51
52extern struct netif_stats	ofwn_stats[];
53
54struct netif_dif ofwn_ifs[] = {
55	/*	dif_unit	dif_nsel	dif_stats	dif_private	*/
56	{	0,		1,		&ofwn_stats[0],	0,	},
57};
58
59struct netif_stats ofwn_stats[NENTS(ofwn_ifs)];
60
61struct netif_driver ofwnet = {
62	"net",			/* netif_bname */
63	ofwn_match,		/* netif_match */
64	ofwn_probe,		/* netif_probe */
65	ofwn_init,		/* netif_init */
66	ofwn_get,		/* netif_get */
67	ofwn_put,		/* netif_put */
68	ofwn_end,		/* netif_end */
69	ofwn_ifs,		/* netif_ifs */
70	NENTS(ofwn_ifs)		/* netif_nifs */
71};
72
73static phandle_t	netdevice;
74static ihandle_t	netinstance;
75static ihandle_t	memory;
76
77static void		*dmabuf;
78
79static int
80ofwn_match(struct netif *nif, void *machdep_hint)
81{
82	return 1;
83}
84
85static int
86ofwn_probe(struct netif *nif, void *machdep_hint)
87{
88	return 0;
89}
90
91static int
92ofwn_put(struct iodesc *desc, void *pkt, int len)
93{
94	struct ether_header	*eh;
95	size_t			sendlen;
96	ssize_t			rv;
97
98#if defined(NETIF_DEBUG)
99	printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len);
100	eh = pkt;
101	printf("dst: %s ", ether_sprintf(eh->ether_dhost));
102	printf("src: %s ", ether_sprintf(eh->ether_shost));
103	printf("type: 0x%x\n", eh->ether_type & 0xffff);
104#endif
105
106	sendlen = len;
107	if (sendlen < 60) {
108		sendlen = 60;
109#if defined(NETIF_DEBUG)
110		printf("netif_put: length padded to %d\n", sendlen);
111#endif
112	}
113
114	if (dmabuf) {
115		bcopy(pkt, dmabuf, sendlen);
116		pkt = dmabuf;
117	}
118
119	rv = OF_write(netinstance, pkt, len);
120
121#if defined(NETIF_DEBUG)
122	printf("netif_put: OF_write returned %d\n", rv);
123#endif
124
125	return rv;
126}
127
128static int
129ofwn_get(struct iodesc *desc, void *pkt, int len, time_t timeout)
130{
131	time_t	t;
132	int	length;
133
134#if defined(NETIF_DEBUG)
135	printf("netif_get: pkt=%p, maxlen=%d, timeout=%d\n", pkt, len,
136	    timeout);
137#endif
138
139	t = getsecs();
140	do {
141		length = OF_read(netinstance, pkt, len);
142	} while ((length == -2 || length == 0) &&
143		(getsecs() - t < timeout));
144
145#if defined(NETIF_DEBUG)
146	printf("netif_get: received length=%d (%x)\n", length, length);
147#endif
148
149	if (length < 12)
150		return -1;
151
152#if defined(NETIF_VERBOSE_DEBUG)
153	{
154		char *ch = pkt;
155		int i;
156
157		for(i = 0; i < 96; i += 4) {
158			printf("%02x%02x%02x%02x  ", ch[i], ch[i+1],
159			    ch[i+2], ch[i+3]);
160		}
161		printf("\n");
162	}
163#endif
164
165#if defined(NETIF_DEBUG)
166	{
167		struct ether_header *eh = pkt;
168
169		printf("dst: %s ", ether_sprintf(eh->ether_dhost));
170		printf("src: %s ", ether_sprintf(eh->ether_shost));
171		printf("type: 0x%x\n", eh->ether_type & 0xffff);
172	}
173#endif
174
175	return length;
176}
177
178extern char *strchr();
179
180static void
181ofwn_init(struct iodesc *desc, void *machdep_hint)
182{
183	phandle_t	chosen, netdev;
184	char		path[64];
185	char		*ch;
186	int		pathlen;
187
188	chosen = OF_finddevice("/chosen");
189	OF_getprop(chosen, "memory", &memory, sizeof(memory));
190	pathlen = OF_getprop(chosen, "bootpath", path, 64);
191	ch = index(path, ':');
192	*ch = '\0';
193	netdev = OF_finddevice(path);
194	if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1)
195		goto punt;
196
197	printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea));
198
199	if ((netinstance = OF_open(path)) == -1)
200		goto punt;
201
202#if defined(NETIF_DEBUG)
203	printf("ofwn_init: OpenFirmware instance handle: %08x\n", netinstance);
204#endif
205
206	if (OF_call_method("dma-alloc", netinstance, 1, 1, NULL, &dmabuf)
207	    < 0) {
208		printf("Failed to allocate DMA buffer (got %08x).\n", dmabuf);
209		goto punt;
210	}
211
212#if defined(NETIF_DEBUG)
213	printf("ofwn_init: allocated DMA buffer: %08x\n", dmabuf);
214#endif
215
216	return;
217
218punt:
219	printf("\n");
220	printf("Could not boot from %s.\n", path);
221	OF_exit();
222}
223
224static void
225ofwn_end(struct netif *nif)
226{
227	OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS);
228	OF_close(netinstance);
229}
230
231#if 0
232int
233ofwn_getunit(const char *path)
234{
235	int		i;
236	char		newpath[255];
237
238	OF_canon(path, newpath, 254);
239
240	for (i = 0; i < nofwninfo; i++) {
241		printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path);
242		if (strcmp(path, ofwninfo[i].ofwn_path) == 0)
243			return i;
244
245		if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0)
246			return i;
247	}
248
249	return -1;
250}
251#endif
252