1 /* $NetBSD: netif_sun.c,v 1.9 2009/01/17 12:47:02 he 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 <lib/libkern/libkern.h> 54 55 #include "libsa.h" 56 #include "dvma.h" 57 #include "saio.h" 58 #include "netif.h" 59 60 #define PKT_BUF_SIZE 2048 61 62 int errno; 63 64 struct iodesc sockets[SOPEN_MAX]; 65 66 struct netif prom_netif; 67 struct devdata { 68 struct saioreq dd_si; 69 int rbuf_len; 70 char *rbuf; 71 int tbuf_len; 72 char *tbuf; 73 u_short dd_opens; 74 u_char dd_myea[6]; 75 } netif_devdata; 76 77 struct devdata * netif_init(void *); 78 void netif_fini(struct devdata *); 79 int netif_attach(struct netif *, struct iodesc *, void *); 80 void netif_detach(struct netif *); 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(void *aux) 91 { 92 struct devdata *dd = &netif_devdata; 93 struct saioreq *si; 94 struct bootparam *bp; 95 int error; 96 97 /* 98 * Setup our part of the saioreq. 99 * (determines what gets opened) 100 */ 101 si = &dd->dd_si; 102 memset(si, 0, sizeof(*si)); 103 bp = *romVectorPtr->bootParam; 104 si->si_boottab = bp->bootDevice; 105 si->si_ctlr = bp->ctlrNum; 106 si->si_unit = bp->unitNum; 107 si->si_boff = bp->partNum; 108 109 #ifdef NETIF_DEBUG 110 if (debug) 111 printf("netif_init: calling prom_iopen\n"); 112 #endif 113 114 /* 115 * Note: Sun PROMs will do RARP on open, but does not tell 116 * you the IP address it gets, so it is just noise to us... 117 */ 118 if ((error = prom_iopen(si)) != 0) { 119 printf("netif_init: prom_iopen, error=%d\n", error); 120 return (NULL); 121 } 122 123 if (si->si_sif == NULL) { 124 printf("netif_init: not a network device\n"); 125 prom_iclose(si); 126 return (NULL); 127 } 128 129 /* Allocate the transmit/receive buffers. */ 130 if (dd->rbuf == NULL) { 131 dd->rbuf_len = PKT_BUF_SIZE; 132 dd->rbuf = dvma_alloc(dd->rbuf_len); 133 } 134 if (dd->tbuf == NULL) { 135 dd->tbuf_len = PKT_BUF_SIZE; 136 dd->tbuf = dvma_alloc(dd->tbuf_len); 137 } 138 if ((dd->rbuf == NULL) || 139 (dd->tbuf == NULL)) 140 panic("netif_init: malloc failed"); 141 142 #ifdef NETIF_DEBUG 143 if (debug) 144 printf("netif_init: rbuf=0x%x, tbuf=0x%x\n", 145 dd->rbuf, dd->tbuf); 146 #endif 147 148 /* Record our ethernet address. */ 149 netif_getether(si->si_sif, dd->dd_myea); 150 151 dd->dd_opens = 0; 152 153 return(dd); 154 } 155 156 void 157 netif_fini(struct devdata *dd) 158 { 159 struct saioreq *si; 160 161 si = &dd->dd_si; 162 163 #ifdef NETIF_DEBUG 164 if (debug) 165 printf("netif_fini: calling prom_iclose\n"); 166 #endif 167 168 prom_iclose(si); 169 /* Dellocate the transmit/receive buffers. */ 170 if (dd->rbuf) { 171 dvma_free(dd->rbuf, dd->rbuf_len); 172 dd->rbuf = NULL; 173 } 174 if (dd->tbuf) { 175 dvma_free(dd->tbuf, dd->tbuf_len); 176 dd->tbuf = NULL; 177 } 178 } 179 180 int 181 netif_attach(struct netif *nif, struct iodesc *s, void *aux) 182 { 183 struct devdata *dd; 184 185 dd = nif->nif_devdata; 186 if (dd == NULL) { 187 dd = netif_init(aux); 188 if (dd == NULL) 189 return (ENXIO); 190 nif->nif_devdata = dd; 191 } 192 dd->dd_opens++; 193 MACPY(dd->dd_myea, s->myea); 194 s->io_netif = nif; 195 return(0); 196 } 197 198 void 199 netif_detach(struct netif *nif) 200 { 201 struct devdata *dd; 202 203 dd = nif->nif_devdata; 204 if (dd == NULL) 205 return; 206 dd->dd_opens--; 207 if (dd->dd_opens > 0) 208 return; 209 netif_fini(dd); 210 nif->nif_devdata = NULL; 211 } 212 213 int 214 netif_open(void *aux) 215 { 216 struct netif *nif; 217 struct iodesc *s; 218 int fd, error; 219 220 /* find a free socket */ 221 for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++) 222 if (s->io_netif == NULL) 223 goto found; 224 errno = EMFILE; 225 return (-1); 226 227 found: 228 memset(s, 0, sizeof(*s)); 229 nif = &prom_netif; 230 error = netif_attach(nif, s, aux); 231 if (error != 0) { 232 errno = error; 233 return (-1); 234 } 235 return (fd); 236 } 237 238 int 239 netif_close(int fd) 240 { 241 struct iodesc *s; 242 struct netif *nif; 243 244 if (fd < 0 || fd >= SOPEN_MAX) { 245 errno = EBADF; 246 return(-1); 247 } 248 s = &sockets[fd]; 249 nif = s->io_netif; 250 /* Already closed? */ 251 if (nif == NULL) 252 return(0); 253 netif_detach(nif); 254 s->io_netif = NULL; 255 return(0); 256 } 257 258 259 struct iodesc * 260 socktodesc(int fd) 261 { 262 if (fd < 0 || fd >= SOPEN_MAX) { 263 errno = EBADF; 264 return (NULL); 265 } 266 return (&sockets[fd]); 267 } 268 269 270 /* 271 * Send a packet. The ether header is already there. 272 * Return the length sent (or -1 on error). 273 */ 274 int 275 netif_put(struct iodesc *desc, void *pkt, size_t len) 276 { 277 struct netif *nif; 278 struct devdata *dd; 279 struct saioreq *si; 280 struct saif *sif; 281 int rv, slen; 282 283 #ifdef NETIF_DEBUG 284 if (debug > 1) { 285 struct ether_header *eh; 286 287 printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", 288 desc, pkt, len); 289 eh = pkt; 290 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 291 printf("src: %s ", ether_sprintf(eh->ether_shost)); 292 printf("type: 0x%x\n", eh->ether_type & 0xFFFF); 293 } 294 #endif 295 296 nif = desc->io_netif; 297 dd = nif->nif_devdata; 298 si = &dd->dd_si; 299 sif = si->si_sif; 300 slen = len; 301 302 #ifdef PARANOID 303 if (sif == NULL) 304 panic("netif_put: no saif ptr"); 305 #endif 306 307 /* 308 * Copy into our transmit buffer because the PROM 309 * network driver might continue using the packet 310 * after the sif_xmit call returns. We never send 311 * very much data anyway, so the copy is fine. 312 */ 313 if (slen > dd->tbuf_len) 314 panic("netif_put: slen=%d", slen); 315 memcpy(dd->tbuf, pkt, slen); 316 317 if (slen < 60) { 318 slen = 60; 319 } 320 321 rv = (*sif->sif_xmit)(si->si_devdata, dd->tbuf, slen); 322 323 #ifdef NETIF_DEBUG 324 if (debug > 1) 325 printf("netif_put: xmit returned %d\n", rv); 326 #endif 327 /* 328 * Just ignore the return value. If the PROM transmit 329 * function fails, it will make some noise, such as: 330 * le: No Carrier 331 */ 332 333 return len; 334 } 335 336 /* 337 * Receive a packet, including the ether header. 338 * Return the total length received (or -1 on error). 339 */ 340 ssize_t 341 netif_get(struct iodesc *desc, void *pkt, size_t maxlen, saseconds_t timo) 342 { 343 struct netif *nif; 344 struct devdata *dd; 345 struct saioreq *si; 346 struct saif *sif; 347 int tick0, tmo_ticks; 348 int rlen = 0; 349 350 #ifdef NETIF_DEBUG 351 if (debug > 1) 352 printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", 353 pkt, maxlen, timo); 354 #endif 355 356 nif = desc->io_netif; 357 dd = nif->nif_devdata; 358 si = &dd->dd_si; 359 sif = si->si_sif; 360 361 tmo_ticks = timo * hz; 362 363 /* Have to receive into our own buffer and copy. */ 364 do { 365 tick0 = getticks(); 366 do { 367 rlen = (*sif->sif_poll)(si->si_devdata, dd->rbuf); 368 if (rlen != 0) 369 goto break2; 370 } while (getticks() == tick0); 371 } while (--tmo_ticks > 0); 372 373 #if 0 374 /* No packet arrived. Better reset the interface. */ 375 printf("netif_get: timeout; resetting\n"); 376 (*sif->sif_reset)(si->si_devdata, si); 377 #endif 378 379 break2: 380 381 #ifdef NETIF_DEBUG 382 if (debug > 1) 383 printf("netif_get: received rlen=%d\n", rlen); 384 #endif 385 386 /* Need at least a valid Ethernet header. */ 387 if (rlen < 12) 388 return -1; 389 390 /* If we went beyond our buffer, were dead! */ 391 if (rlen > dd->rbuf_len) 392 panic("netif_get: rlen=%d", rlen); 393 394 /* The caller's buffer may be smaller... */ 395 if (rlen > maxlen) 396 rlen = maxlen; 397 398 memcpy(pkt, dd->rbuf, rlen); 399 400 #ifdef NETIF_DEBUG 401 if (debug > 1) { 402 struct ether_header *eh = pkt; 403 404 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 405 printf("src: %s ", ether_sprintf(eh->ether_shost)); 406 printf("type: 0x%x\n", eh->ether_type & 0xFFFF); 407 } 408 #endif 409 410 return rlen; 411 } 412 413 /* 414 * Copy our Ethernet address into the passed array. 415 */ 416 void 417 netif_getether(struct saif *sif, u_char *ea) 418 { 419 char *rev; 420 421 if (_is3x == 0) { 422 /* 423 * Sun3: These usually have old PROMs 424 * without the sif_macaddr function, but 425 * reading the IDPROM on these machines is 426 * very easy, so just always do that. 427 */ 428 idprom_etheraddr(ea); 429 return; 430 } 431 432 /* 433 * Sun3X: Want to use sif->sif_macaddr(), but 434 * it's only in PROM revisions 3.0 and later, 435 * so we have to check the PROM rev first. 436 * Note that old PROMs prefix the rev string 437 * with "Rev " (i.e. "Rev 2.6"). 438 */ 439 rev = romVectorPtr->monId; 440 if (!strncmp(rev, "Rev ", 4)) 441 rev += 4; 442 if (!strncmp(rev, "3.", 2)) { 443 /* Great! We can call the PROM. */ 444 (*sif->sif_macaddr)(ea); 445 return; 446 } 447 448 /* 449 * Sun3X with PROM rev < 3.0. 450 * Finding the IDPROM is a pain, but 451 * we have no choice. Warn the user. 452 */ 453 printf("netboot: Old PROM Rev (%s)\n", rev); 454 idprom_etheraddr(ea); 455 } 456