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