1 /* $NetBSD: netif_sun.c,v 1.5 2005/12/11 12:19:29 christos 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(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 char *dmabuf; 282 int rv, slen; 283 284 #ifdef NETIF_DEBUG 285 if (debug > 1) { 286 struct ether_header *eh; 287 288 printf("netif_put: desc=0x%x pkt=0x%x len=%d\n", 289 desc, pkt, len); 290 eh = pkt; 291 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 292 printf("src: %s ", ether_sprintf(eh->ether_shost)); 293 printf("type: 0x%x\n", eh->ether_type & 0xFFFF); 294 } 295 #endif 296 297 nif = desc->io_netif; 298 dd = nif->nif_devdata; 299 si = &dd->dd_si; 300 sif = si->si_sif; 301 slen = len; 302 303 #ifdef PARANOID 304 if (sif == NULL) 305 panic("netif_put: no saif ptr"); 306 #endif 307 308 /* 309 * Copy into our transmit buffer because the PROM 310 * network driver might continue using the packet 311 * after the sif_xmit call returns. We never send 312 * very much data anyway, so the copy is fine. 313 */ 314 if (slen > dd->tbuf_len) 315 panic("netif_put: slen=%d", slen); 316 memcpy(dd->tbuf, pkt, slen); 317 318 if (slen < 60) { 319 slen = 60; 320 } 321 322 rv = (*sif->sif_xmit)(si->si_devdata, dd->tbuf, slen); 323 324 #ifdef NETIF_DEBUG 325 if (debug > 1) 326 printf("netif_put: xmit returned %d\n", rv); 327 #endif 328 /* 329 * Just ignore the return value. If the PROM transmit 330 * function fails, it will make some noise, such as: 331 * le: No Carrier 332 */ 333 334 return len; 335 } 336 337 /* 338 * Receive a packet, including the ether header. 339 * Return the total length received (or -1 on error). 340 */ 341 int 342 netif_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timo) 343 { 344 struct netif *nif; 345 struct devdata *dd; 346 struct saioreq *si; 347 struct saif *sif; 348 int tick0, tmo_ticks; 349 int rlen = 0; 350 351 #ifdef NETIF_DEBUG 352 if (debug > 1) 353 printf("netif_get: pkt=0x%x, maxlen=%d, tmo=%d\n", 354 pkt, maxlen, timo); 355 #endif 356 357 nif = desc->io_netif; 358 dd = nif->nif_devdata; 359 si = &dd->dd_si; 360 sif = si->si_sif; 361 362 tmo_ticks = timo * hz; 363 364 /* Have to receive into our own buffer and copy. */ 365 do { 366 tick0 = getticks(); 367 do { 368 rlen = (*sif->sif_poll)(si->si_devdata, dd->rbuf); 369 if (rlen != 0) 370 goto break2; 371 } while (getticks() == tick0); 372 } while (--tmo_ticks > 0); 373 374 #if 0 375 /* No packet arrived. Better reset the interface. */ 376 printf("netif_get: timeout; resetting\n"); 377 (*sif->sif_reset)(si->si_devdata, si); 378 #endif 379 380 break2: 381 382 #ifdef NETIF_DEBUG 383 if (debug > 1) 384 printf("netif_get: received rlen=%d\n", rlen); 385 #endif 386 387 /* Need at least a valid Ethernet header. */ 388 if (rlen < 12) 389 return -1; 390 391 /* If we went beyond our buffer, were dead! */ 392 if (rlen > dd->rbuf_len) 393 panic("netif_get: rlen=%d", rlen); 394 395 /* The caller's buffer may be smaller... */ 396 if (rlen > maxlen) 397 rlen = maxlen; 398 399 memcpy(pkt, dd->rbuf, rlen); 400 401 #ifdef NETIF_DEBUG 402 if (debug > 1) { 403 struct ether_header *eh = pkt; 404 405 printf("dst: %s ", ether_sprintf(eh->ether_dhost)); 406 printf("src: %s ", ether_sprintf(eh->ether_shost)); 407 printf("type: 0x%x\n", eh->ether_type & 0xFFFF); 408 } 409 #endif 410 411 return rlen; 412 } 413 414 /* 415 * Copy our Ethernet address into the passed array. 416 */ 417 void 418 netif_getether(struct saif *sif, u_char *ea) 419 { 420 char *rev; 421 422 if (_is3x == 0) { 423 /* 424 * Sun3: These usually have old PROMs 425 * without the sif_macaddr function, but 426 * reading the IDPROM on these machines is 427 * very easy, so just always do that. 428 */ 429 idprom_etheraddr(ea); 430 return; 431 } 432 433 /* 434 * Sun3X: Want to use sif->sif_macaddr(), but 435 * it's only in PROM revisions 3.0 and later, 436 * so we have to check the PROM rev first. 437 * Note that old PROMs prefix the rev string 438 * with "Rev " (i.e. "Rev 2.6"). 439 */ 440 rev = romVectorPtr->monId; 441 if (!strncmp(rev, "Rev ", 4)) 442 rev += 4; 443 if (!strncmp(rev, "3.", 2)) { 444 /* Great! We can call the PROM. */ 445 (*sif->sif_macaddr)(ea); 446 return; 447 } 448 449 /* 450 * Sun3X with PROM rev < 3.0. 451 * Finding the IDPROM is a pain, but 452 * we have no choice. Warn the user. 453 */ 454 printf("netboot: Old PROM Rev (%s)\n", rev); 455 idprom_etheraddr(ea); 456 } 457