netif_sun.c revision 1.5.74.1 1 /* $NetBSD: netif_sun.c,v 1.5.74.1 2008/06/02 13:22:47 mjf Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Gordon W. Ross.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * The Sun PROM has a fairly general set of network drivers,
34 * so it is easiest to just replace the netif module with
35 * this adaptation to the PROM network interface.
36 */
37
38 #include <sys/param.h>
39 #include <sys/socket.h>
40
41 #include <net/if.h>
42 #include <net/if_ether.h>
43
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
46
47 #include <machine/idprom.h>
48 #include <machine/mon.h>
49
50 #include <stand.h>
51 #include <net.h>
52
53 #include "libsa.h"
54 #include "dvma.h"
55 #include "saio.h"
56 #include "netif.h"
57
58 #define PKT_BUF_SIZE 2048
59
60 int errno;
61
62 struct iodesc sockets[SOPEN_MAX];
63
64 struct netif prom_netif;
65 struct devdata {
66 struct saioreq dd_si;
67 int rbuf_len;
68 char *rbuf;
69 int tbuf_len;
70 char *tbuf;
71 u_short dd_opens;
72 u_char dd_myea[6];
73 } netif_devdata;
74
75 void netif_getether(struct saif *, u_char *);
76
77
78 /*
79 * Open the PROM device.
80 * Return netif ptr on success.
81 */
82 struct devdata *
83 netif_init(void *aux)
84 {
85 struct devdata *dd = &netif_devdata;
86 struct saioreq *si;
87 struct bootparam *bp;
88 int error;
89
90 /*
91 * Setup our part of the saioreq.
92 * (determines what gets opened)
93 */
94 si = &dd->dd_si;
95 memset(si, 0, sizeof(*si));
96 bp = *romVectorPtr->bootParam;
97 si->si_boottab = bp->bootDevice;
98 si->si_ctlr = bp->ctlrNum;
99 si->si_unit = bp->unitNum;
100 si->si_boff = bp->partNum;
101
102 #ifdef NETIF_DEBUG
103 if (debug)
104 printf("netif_init: calling prom_iopen\n");
105 #endif
106
107 /*
108 * Note: Sun PROMs will do RARP on open, but does not tell
109 * you the IP address it gets, so it is just noise to us...
110 */
111 if ((error = prom_iopen(si)) != 0) {
112 printf("netif_init: prom_iopen, error=%d\n", error);
113 return (NULL);
114 }
115
116 if (si->si_sif == NULL) {
117 printf("netif_init: not a network device\n");
118 prom_iclose(si);
119 return (NULL);
120 }
121
122 /* Allocate the transmit/receive buffers. */
123 if (dd->rbuf == NULL) {
124 dd->rbuf_len = PKT_BUF_SIZE;
125 dd->rbuf = dvma_alloc(dd->rbuf_len);
126 }
127 if (dd->tbuf == NULL) {
128 dd->tbuf_len = PKT_BUF_SIZE;
129 dd->tbuf = dvma_alloc(dd->tbuf_len);
130 }
131 if ((dd->rbuf == NULL) ||
132 (dd->tbuf == NULL))
133 panic("netif_init: malloc failed");
134
135 #ifdef NETIF_DEBUG
136 if (debug)
137 printf("netif_init: rbuf=0x%x, tbuf=0x%x\n",
138 dd->rbuf, dd->tbuf);
139 #endif
140
141 /* Record our ethernet address. */
142 netif_getether(si->si_sif, dd->dd_myea);
143
144 dd->dd_opens = 0;
145
146 return(dd);
147 }
148
149 void
150 netif_fini(struct devdata *dd)
151 {
152 struct saioreq *si;
153
154 si = &dd->dd_si;
155
156 #ifdef NETIF_DEBUG
157 if (debug)
158 printf("netif_fini: calling prom_iclose\n");
159 #endif
160
161 prom_iclose(si);
162 /* Dellocate the transmit/receive buffers. */
163 if (dd->rbuf) {
164 dvma_free(dd->rbuf, dd->rbuf_len);
165 dd->rbuf = NULL;
166 }
167 if (dd->tbuf) {
168 dvma_free(dd->tbuf, dd->tbuf_len);
169 dd->tbuf = NULL;
170 }
171 }
172
173 int
174 netif_attach(struct netif *nif, struct iodesc *s, void *aux)
175 {
176 struct devdata *dd;
177
178 dd = nif->nif_devdata;
179 if (dd == NULL) {
180 dd = netif_init(aux);
181 if (dd == NULL)
182 return (ENXIO);
183 nif->nif_devdata = dd;
184 }
185 dd->dd_opens++;
186 MACPY(dd->dd_myea, s->myea);
187 s->io_netif = nif;
188 return(0);
189 }
190
191 void
192 netif_detach(struct netif *nif)
193 {
194 struct devdata *dd;
195
196 dd = nif->nif_devdata;
197 if (dd == NULL)
198 return;
199 dd->dd_opens--;
200 if (dd->dd_opens > 0)
201 return;
202 netif_fini(dd);
203 nif->nif_devdata = NULL;
204 }
205
206 int
207 netif_open(void *aux)
208 {
209 struct netif *nif;
210 struct iodesc *s;
211 int fd, error;
212
213 /* find a free socket */
214 for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++)
215 if (s->io_netif == NULL)
216 goto found;
217 errno = EMFILE;
218 return (-1);
219
220 found:
221 memset(s, 0, sizeof(*s));
222 nif = &prom_netif;
223 error = netif_attach(nif, s, aux);
224 if (error != 0) {
225 errno = error;
226 return (-1);
227 }
228 return (fd);
229 }
230
231 int
232 netif_close(int fd)
233 {
234 struct iodesc *s;
235 struct netif *nif;
236
237 if (fd < 0 || fd >= SOPEN_MAX) {
238 errno = EBADF;
239 return(-1);
240 }
241 s = &sockets[fd];
242 nif = s->io_netif;
243 /* Already closed? */
244 if (nif == NULL)
245 return(0);
246 netif_detach(nif);
247 s->io_netif = NULL;
248 return(0);
249 }
250
251
252 struct iodesc *
253 socktodesc(int fd)
254 {
255 if (fd < 0 || fd >= SOPEN_MAX) {
256 errno = EBADF;
257 return (NULL);
258 }
259 return (&sockets[fd]);
260 }
261
262
263 /*
264 * Send a packet. The ether header is already there.
265 * Return the length sent (or -1 on error).
266 */
267 int
268 netif_put(struct iodesc *desc, void *pkt, size_t len)
269 {
270 struct netif *nif;
271 struct devdata *dd;
272 struct saioreq *si;
273 struct saif *sif;
274 char *dmabuf;
275 int rv, slen;
276
277 #ifdef NETIF_DEBUG
278 if (debug > 1) {
279 struct ether_header *eh;
280
281 printf("netif_put: desc=0x%x pkt=0x%x len=%d\n",
282 desc, pkt, len);
283 eh = pkt;
284 printf("dst: %s ", ether_sprintf(eh->ether_dhost));
285 printf("src: %s ", ether_sprintf(eh->ether_shost));
286 printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
287 }
288 #endif
289
290 nif = desc->io_netif;
291 dd = nif->nif_devdata;
292 si = &dd->dd_si;
293 sif = si->si_sif;
294 slen = len;
295
296 #ifdef PARANOID
297 if (sif == NULL)
298 panic("netif_put: no saif ptr");
299 #endif
300
301 /*
302 * Copy into our transmit buffer because the PROM
303 * network driver might continue using the packet
304 * after the sif_xmit call returns. We never send
305 * very much data anyway, so the copy is fine.
306 */
307 if (slen > dd->tbuf_len)
308 panic("netif_put: slen=%d", slen);
309 memcpy(dd->tbuf, pkt, slen);
310
311 if (slen < 60) {
312 slen = 60;
313 }
314
315 rv = (*sif->sif_xmit)(si->si_devdata, dd->tbuf, slen);
316
317 #ifdef NETIF_DEBUG
318 if (debug > 1)
319 printf("netif_put: xmit returned %d\n", rv);
320 #endif
321 /*
322 * Just ignore the return value. If the PROM transmit
323 * function fails, it will make some noise, such as:
324 * le: No Carrier
325 */
326
327 return len;
328 }
329
330 /*
331 * Receive a packet, including the ether header.
332 * Return the total length received (or -1 on error).
333 */
334 int
335 netif_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timo)
336 {
337 struct netif *nif;
338 struct devdata *dd;
339 struct saioreq *si;
340 struct saif *sif;
341 int tick0, tmo_ticks;
342 int rlen = 0;
343
344 #ifdef NETIF_DEBUG
345 if (debug > 1)
346 printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n",
347 pkt, maxlen, timo);
348 #endif
349
350 nif = desc->io_netif;
351 dd = nif->nif_devdata;
352 si = &dd->dd_si;
353 sif = si->si_sif;
354
355 tmo_ticks = timo * hz;
356
357 /* Have to receive into our own buffer and copy. */
358 do {
359 tick0 = getticks();
360 do {
361 rlen = (*sif->sif_poll)(si->si_devdata, dd->rbuf);
362 if (rlen != 0)
363 goto break2;
364 } while (getticks() == tick0);
365 } while (--tmo_ticks > 0);
366
367 #if 0
368 /* No packet arrived. Better reset the interface. */
369 printf("netif_get: timeout; resetting\n");
370 (*sif->sif_reset)(si->si_devdata, si);
371 #endif
372
373 break2:
374
375 #ifdef NETIF_DEBUG
376 if (debug > 1)
377 printf("netif_get: received rlen=%d\n", rlen);
378 #endif
379
380 /* Need at least a valid Ethernet header. */
381 if (rlen < 12)
382 return -1;
383
384 /* If we went beyond our buffer, were dead! */
385 if (rlen > dd->rbuf_len)
386 panic("netif_get: rlen=%d", rlen);
387
388 /* The caller's buffer may be smaller... */
389 if (rlen > maxlen)
390 rlen = maxlen;
391
392 memcpy(pkt, dd->rbuf, rlen);
393
394 #ifdef NETIF_DEBUG
395 if (debug > 1) {
396 struct ether_header *eh = pkt;
397
398 printf("dst: %s ", ether_sprintf(eh->ether_dhost));
399 printf("src: %s ", ether_sprintf(eh->ether_shost));
400 printf("type: 0x%x\n", eh->ether_type & 0xFFFF);
401 }
402 #endif
403
404 return rlen;
405 }
406
407 /*
408 * Copy our Ethernet address into the passed array.
409 */
410 void
411 netif_getether(struct saif *sif, u_char *ea)
412 {
413 char *rev;
414
415 if (_is3x == 0) {
416 /*
417 * Sun3: These usually have old PROMs
418 * without the sif_macaddr function, but
419 * reading the IDPROM on these machines is
420 * very easy, so just always do that.
421 */
422 idprom_etheraddr(ea);
423 return;
424 }
425
426 /*
427 * Sun3X: Want to use sif->sif_macaddr(), but
428 * it's only in PROM revisions 3.0 and later,
429 * so we have to check the PROM rev first.
430 * Note that old PROMs prefix the rev string
431 * with "Rev " (i.e. "Rev 2.6").
432 */
433 rev = romVectorPtr->monId;
434 if (!strncmp(rev, "Rev ", 4))
435 rev += 4;
436 if (!strncmp(rev, "3.", 2)) {
437 /* Great! We can call the PROM. */
438 (*sif->sif_macaddr)(ea);
439 return;
440 }
441
442 /*
443 * Sun3X with PROM rev < 3.0.
444 * Finding the IDPROM is a pain, but
445 * we have no choice. Warn the user.
446 */
447 printf("netboot: Old PROM Rev (%s)\n", rev);
448 idprom_etheraddr(ea);
449 }
450