Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/libofw/ofw_net.c
34677 views
1
/*-
2
* Copyright (c) 2000-2001 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
27
#include <sys/param.h>
28
#include <sys/types.h>
29
#include <sys/socket.h>
30
31
#include <net/if.h>
32
#include <netinet/in.h>
33
#include <netinet/in_systm.h>
34
#include <netinet/if_ether.h>
35
#include <netinet/ip.h>
36
37
#include <stand.h>
38
#include <net.h>
39
#include <netif.h>
40
41
#include "libofw.h"
42
#include "openfirm.h"
43
44
static int ofwn_probe(struct netif *, void *);
45
static int ofwn_match(struct netif *, void *);
46
static void ofwn_init(struct iodesc *, void *);
47
static ssize_t ofwn_get(struct iodesc *, void **, time_t);
48
static ssize_t ofwn_put(struct iodesc *, void *, size_t);
49
static void ofwn_end(struct netif *);
50
51
extern struct netif_stats ofwn_stats[];
52
53
struct netif_dif ofwn_ifs[] = {
54
{
55
.dif_unit=0,
56
.dif_nsel=1,
57
.dif_stats=&ofwn_stats[0],
58
.dif_private=0,
59
},
60
};
61
62
struct netif_stats ofwn_stats[nitems(ofwn_ifs)];
63
64
struct netif_driver ofwnet = {
65
.netif_bname="net",
66
.netif_match=ofwn_match,
67
.netif_probe=ofwn_probe,
68
.netif_init=ofwn_init,
69
.netif_get=ofwn_get,
70
.netif_put=ofwn_put,
71
.netif_end=ofwn_end,
72
.netif_ifs=ofwn_ifs,
73
.netif_nifs=nitems(ofwn_ifs)
74
};
75
76
static ihandle_t netinstance;
77
78
static void *dmabuf;
79
80
static int
81
ofwn_match(struct netif *nif, void *machdep_hint)
82
{
83
return (1);
84
}
85
86
static int
87
ofwn_probe(struct netif *nif, void *machdep_hint)
88
{
89
return (0);
90
}
91
92
static ssize_t
93
ofwn_put(struct iodesc *desc, void *pkt, size_t len)
94
{
95
size_t sendlen;
96
ssize_t rv;
97
98
#if defined(NETIF_DEBUG)
99
struct ether_header *eh;
100
printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", desc, pkt, len);
101
eh = pkt;
102
printf("dst: %s ", ether_sprintf(eh->ether_dhost));
103
printf("src: %s ", ether_sprintf(eh->ether_shost));
104
printf("type: 0x%x\n", eh->ether_type & 0xffff);
105
#endif
106
107
sendlen = len;
108
if (sendlen < 60) {
109
sendlen = 60;
110
#if defined(NETIF_DEBUG)
111
printf("netif_put: length padded to %d\n", sendlen);
112
#endif
113
}
114
115
if (dmabuf) {
116
bcopy(pkt, dmabuf, sendlen);
117
pkt = dmabuf;
118
}
119
120
rv = OF_write(netinstance, pkt, len);
121
122
#if defined(NETIF_DEBUG)
123
printf("netif_put: OF_write returned %d\n", rv);
124
#endif
125
126
return (rv);
127
}
128
129
static ssize_t
130
ofwn_get(struct iodesc *desc, void **pkt, time_t timeout)
131
{
132
time_t t;
133
ssize_t length;
134
size_t len;
135
char *buf, *ptr;
136
137
#if defined(NETIF_DEBUG)
138
printf("netif_get: pkt=%p, timeout=%d\n", pkt, timeout);
139
#endif
140
141
/*
142
* We should read the "max-frame-size" int property instead,
143
* but at this time the iodesc does not have mtu, so we will take
144
* a small shortcut here.
145
*/
146
len = ETHER_MAX_LEN;
147
buf = malloc(len + ETHER_ALIGN);
148
if (buf == NULL)
149
return (-1);
150
ptr = buf + ETHER_ALIGN;
151
152
t = getsecs();
153
do {
154
length = OF_read(netinstance, ptr, len);
155
} while ((length == -2 || length == 0) &&
156
(getsecs() - t < timeout));
157
158
#if defined(NETIF_DEBUG)
159
printf("netif_get: received length=%d (%x)\n", length, length);
160
#endif
161
162
if (length < 12) {
163
free(buf);
164
return (-1);
165
}
166
167
#if defined(NETIF_VERBOSE_DEBUG)
168
{
169
char *ch = ptr;
170
int i;
171
172
for(i = 0; i < 96; i += 4) {
173
printf("%02x%02x%02x%02x ", ch[i], ch[i+1],
174
ch[i+2], ch[i+3]);
175
}
176
printf("\n");
177
}
178
#endif
179
180
#if defined(NETIF_DEBUG)
181
{
182
struct ether_header *eh = ptr;
183
184
printf("dst: %s ", ether_sprintf(eh->ether_dhost));
185
printf("src: %s ", ether_sprintf(eh->ether_shost));
186
printf("type: 0x%x\n", eh->ether_type & 0xffff);
187
}
188
#endif
189
190
*pkt = buf;
191
return (length);
192
}
193
194
static void
195
ofwn_init(struct iodesc *desc, void *machdep_hint)
196
{
197
phandle_t netdev;
198
char path[64];
199
char *ch;
200
int pathlen;
201
202
pathlen = OF_getprop(chosen, "bootpath", path, 64);
203
if ((ch = strchr(path, ':')) != NULL)
204
*ch = '\0';
205
netdev = OF_finddevice(path);
206
if (OF_getprop(netdev, "local-mac-address", desc->myea, 6) == -1)
207
goto punt;
208
209
printf("boot: ethernet address: %s\n", ether_sprintf(desc->myea));
210
211
if ((netinstance = OF_open(path)) == -1) {
212
printf("Could not open network device.\n");
213
goto punt;
214
}
215
216
#if defined(NETIF_DEBUG)
217
printf("ofwn_init: Open Firmware instance handle: %08x\n", netinstance);
218
#endif
219
dmabuf = NULL;
220
if (OF_call_method("dma-alloc", netinstance, 1, 1, (64 * 1024), &dmabuf)
221
< 0) {
222
printf("Failed to allocate DMA buffer (got %p).\n", dmabuf);
223
goto punt;
224
}
225
#if defined(NETIF_DEBUG)
226
printf("ofwn_init: allocated DMA buffer: %p\n", dmabuf);
227
#endif
228
229
return;
230
231
punt:
232
printf("\n");
233
printf("Could not boot from %s.\n", path);
234
OF_enter();
235
}
236
237
static void
238
ofwn_end(struct netif *nif)
239
{
240
#ifdef BROKEN
241
/* dma-free freezes at least some Apple ethernet controllers */
242
OF_call_method("dma-free", netinstance, 2, 0, dmabuf, MAXPHYS);
243
#endif
244
OF_close(netinstance);
245
}
246
247
#if 0
248
int
249
ofwn_getunit(const char *path)
250
{
251
int i;
252
char newpath[255];
253
254
OF_canon(path, newpath, 254);
255
256
for (i = 0; i < nofwninfo; i++) {
257
printf(">>> test =\t%s\n", ofwninfo[i].ofwn_path);
258
if (strcmp(path, ofwninfo[i].ofwn_path) == 0)
259
return (i);
260
261
if (strcmp(newpath, ofwninfo[i].ofwn_path) == 0)
262
return (i);
263
}
264
265
return (-1);
266
}
267
#endif
268
269
/*
270
* To properly match network devices, we have to subclass the netdev device.
271
* It has a different devdesc than a normal network device (which is fine:
272
* it's a struct superset) and different matching criteria (since it has to
273
* look at the path, find a handle and see if that handle is a network node
274
* or not).
275
*/
276
277
static int ofwnd_init(void);
278
static int ofwnd_parsedev(struct devdesc **, const char *, const char **);
279
static bool ofwnd_match(struct devsw *, const char *);
280
static char *ofwnd_fmtdev(struct devdesc *);
281
282
struct devsw ofw_netdev = {
283
.dv_name = "network",
284
.dv_type = DEVT_NET,
285
.dv_init = ofwnd_init,
286
.dv_match = ofwnd_match,
287
.dv_fmtdev = ofwnd_fmtdev,
288
.dv_parsedev = ofwnd_parsedev,
289
};
290
291
static int ofwnd_init(void)
292
{
293
netdev.dv_init();
294
ofw_netdev.dv_strategy = netdev.dv_strategy;
295
ofw_netdev.dv_open = netdev.dv_open;
296
ofw_netdev.dv_close = netdev.dv_close;
297
ofw_netdev.dv_ioctl = netdev.dv_ioctl;
298
ofw_netdev.dv_print = netdev.dv_print;
299
ofw_netdev.dv_fmtdev = netdev.dv_fmtdev;
300
/* parsedev is unique to ofwnd */
301
/* match is unique to ofwnd */
302
return (0);
303
}
304
305
static int
306
ofwnd_parsedev(struct devdesc **dev, const char *devspec, const char **path)
307
{
308
return (ofw_common_parsedev(dev, devspec, path, ofw_netdev.dv_name));
309
}
310
311
static bool
312
ofwnd_match(struct devsw *devsw, const char *devspec)
313
{
314
const char *path;
315
316
return (ofw_path_to_handle(devspec, devsw->dv_name, &path) != -1);
317
}
318
319
static char *
320
ofwnd_fmtdev(struct devdesc *idev)
321
{
322
struct ofw_devdesc *dev = (struct ofw_devdesc *)idev;
323
324
return (dev->d_path);
325
}
326
327