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