1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Computer Consoles Inc. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)if_enp.c 7.8 (Berkeley) 12/16/90 11 */ 12 13 #include "enp.h" 14 #if NENP > 0 15 /* 16 * CMC ENP-20 Ethernet Controller. 17 */ 18 #include "sys/param.h" 19 #include "sys/systm.h" 20 #include "sys/mbuf.h" 21 #include "sys/buf.h" 22 #include "sys/protosw.h" 23 #include "sys/socket.h" 24 #include "sys/vmmac.h" 25 #include "sys/ioctl.h" 26 #include "sys/errno.h" 27 #include "sys/vmparam.h" 28 #include "sys/syslog.h" 29 #include "sys/uio.h" 30 31 #include "net/if.h" 32 #include "net/netisr.h" 33 #include "net/route.h" 34 #ifdef INET 35 #include "netinet/in.h" 36 #include "netinet/in_systm.h" 37 #include "netinet/in_var.h" 38 #include "netinet/ip.h" 39 #include "netinet/ip_var.h" 40 #include "netinet/if_ether.h" 41 #endif 42 #ifdef NS 43 #include "netns/ns.h" 44 #include "netns/ns_if.h" 45 #endif 46 47 #include "../include/cpu.h" 48 #include "../include/pte.h" 49 #include "../include/mtpr.h" 50 51 #include "../vba/vbavar.h" 52 #include "../if/if_enpreg.h" 53 54 #define ENPSTART 0xf02000 /* standard enp start addr */ 55 #define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */ 56 /* macros for dealing with longs in i/o space */ 57 #define ENPGETLONG(a) ((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1])) 58 #define ENPSETLONG(a,v) \ 59 { register u_short *wp = (u_short *)(a); \ 60 wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];} 61 62 int enpprobe(), enpattach(), enpintr(); 63 long enpstd[] = { 0xfff41000, 0xfff61000, 0 }; 64 struct vba_device *enpinfo[NENP]; 65 struct vba_driver enpdriver = 66 { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 }; 67 68 int enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart(); 69 struct mbuf *enpget(); 70 71 /* 72 * Ethernet software status per interface. 73 * 74 * Each interface is referenced by a network interface structure, 75 * es_if, which the routing code uses to locate the interface. 76 * This structure contains the output queue for the interface, its address, ... 77 */ 78 struct enp_softc { 79 struct arpcom es_ac; /* common ethernet structures */ 80 #define es_if es_ac.ac_if 81 #define es_addr es_ac.ac_enaddr 82 short es_ivec; /* interrupt vector */ 83 } enp_softc[NENP]; 84 extern struct ifnet loif; 85 86 enpprobe(reg, vi) 87 caddr_t reg; 88 struct vba_device *vi; 89 { 90 register br, cvec; /* must be r12, r11 */ 91 register struct enpdevice *addr = (struct enpdevice *)reg; 92 struct enp_softc *es = &enp_softc[vi->ui_unit]; 93 94 #ifdef lint 95 br = 0; cvec = br; br = cvec; 96 enpintr(0); 97 #endif 98 if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2)) 99 return (0); 100 es->es_ivec = --vi->ui_hd->vh_lastiv; 101 addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */ 102 br = 0x14, cvec = es->es_ivec; /* XXX */ 103 return (sizeof (struct enpdevice)); 104 } 105 106 /* 107 * Interface exists: make available by filling in network interface 108 * record. System will initialize the interface when it is ready 109 * to accept packets. 110 */ 111 enpattach(ui) 112 register struct vba_device *ui; 113 { 114 struct enp_softc *es = &enp_softc[ui->ui_unit]; 115 register struct ifnet *ifp = &es->es_if; 116 117 ifp->if_unit = ui->ui_unit; 118 ifp->if_name = "enp"; 119 ifp->if_mtu = ETHERMTU; 120 ifp->if_init = enpinit; 121 ifp->if_ioctl = enpioctl; 122 ifp->if_output = ether_output; 123 ifp->if_start = enpstart; 124 ifp->if_reset = enpreset; 125 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 126 if_attach(ifp); 127 } 128 129 /* 130 * Reset of interface after "system" reset. 131 */ 132 enpreset(unit, vban) 133 int unit, vban; 134 { 135 register struct vba_device *ui; 136 137 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || 138 ui->ui_vbanum != vban) 139 return; 140 printf(" enp%d", unit); 141 enpinit(unit); 142 } 143 144 /* 145 * Initialization of interface; clear recorded pending operations. 146 */ 147 enpinit(unit) 148 int unit; 149 { 150 struct enp_softc *es = &enp_softc[unit]; 151 register struct vba_device *ui = enpinfo[unit]; 152 struct enpdevice *addr; 153 register struct ifnet *ifp = &es->es_if; 154 int s; 155 156 if (ifp->if_addrlist == (struct ifaddr *)0) 157 return; 158 if ((ifp->if_flags & IFF_RUNNING) == 0) { 159 addr = (struct enpdevice *)ui->ui_addr; 160 s = splimp(); 161 RESET_ENP(addr); 162 DELAY(200000); 163 es->es_if.if_flags |= IFF_RUNNING; 164 splx(s); 165 } 166 } 167 168 /* 169 * Ethernet interface interrupt. 170 */ 171 enpintr(unit) 172 int unit; 173 { 174 register struct enpdevice *addr; 175 register BCB *bcbp; 176 177 addr = (struct enpdevice *)enpinfo[unit]->ui_addr; 178 #if ENP == 30 179 if (!IS_ENP_INTR(addr)) 180 return; 181 ACK_ENP_INTR(addr); 182 #endif 183 while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) { 184 enpread(&enp_softc[unit], bcbp); 185 (void) ringput((RING *)&addr->enp_enpfree, bcbp); 186 } 187 } 188 189 /* 190 * Read input packet, examine its packet type, and enqueue it. 191 */ 192 enpread(es, bcbp) 193 struct enp_softc *es; 194 register BCB *bcbp; 195 { 196 register struct ether_header *enp; 197 struct mbuf *m; 198 int s, len, off, resid; 199 200 es->es_if.if_ipackets++; 201 /* 202 * Get input data length. 203 * Get pointer to ethernet header (in input buffer). 204 * Deal with trailer protocol: if type is PUP trailer 205 * get true type from first 16-bit word past data. 206 * Remember that type was trailer by setting off. 207 */ 208 len = bcbp->b_msglen - sizeof (struct ether_header); 209 enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr); 210 #define enpdataaddr(enp, off, type) \ 211 ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off)))) 212 enp->ether_type = ntohs((u_short)enp->ether_type); 213 if (enp->ether_type >= ETHERTYPE_TRAIL && 214 enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 215 off = (enp->ether_type - ETHERTYPE_TRAIL) * 512; 216 if (off >= ETHERMTU) 217 return; 218 enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *)); 219 resid = ntohs(*(enpdataaddr(enp, off+2, u_short *))); 220 if (off + resid > len) 221 return; 222 len = off + resid; 223 } else 224 off = 0; 225 if (len == 0) 226 return; 227 228 /* 229 * Pull packet off interface. Off is nonzero if packet 230 * has trailing header; enpget will then force this header 231 * information to be at the front. 232 */ 233 m = enpget((u_char *)enp, len, off, &es->es_if); 234 if (m == 0) 235 return; 236 ether_input(&es->es_if, enp, m); 237 } 238 239 enpstart(ifp) 240 struct ifnet *ifp; 241 { 242 243 if (enpput(ifp)) 244 return (ENOBUFS); 245 else 246 return (0); 247 } 248 249 /* 250 * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus. 251 */ 252 enpput(ifp) 253 struct ifnet *ifp; 254 { 255 register BCB *bcbp; 256 register struct enpdevice *addr; 257 register struct mbuf *mp; 258 register u_char *bp; 259 register u_int len; 260 int unit = ifp->if_unit, ret = 1; 261 struct mbuf *m; 262 263 addr = (struct enpdevice *)enpinfo[unit]->ui_addr; 264 again: 265 if (ringempty((RING *)&addr->enp_hostfree)) { 266 /* ifp->if_flags |= IFF_OACTIVE; */ 267 return (ret); 268 } 269 IF_DEQUEUE(&ifp->if_snd, m); 270 if (m == 0) { 271 ifp->if_flags &= ~IFF_OACTIVE; 272 return (0); 273 } 274 bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree); 275 bcbp->b_len = 0; 276 bp = (u_char *)ENPGETLONG(&bcbp->b_addr); 277 for (mp = m; mp; mp = mp->m_next) { 278 len = mp->m_len; 279 if (len == 0) 280 continue; 281 enpcopy(mtod(mp, u_char *), bp, len); 282 bp += len; 283 bcbp->b_len += len; 284 } 285 bcbp->b_len = max(ETHERMIN+sizeof (struct ether_header), bcbp->b_len); 286 bcbp->b_reserved = 0; 287 if (ringput((RING *)&addr->enp_toenp, bcbp) == 1) 288 INTR_ENP(addr); 289 m_freem(m); 290 ret = 0; 291 goto again; 292 } 293 294 /* 295 * Routine to copy from VERSAbus memory into mbufs. 296 * 297 * Warning: This makes the fairly safe assumption that 298 * mbufs have even lengths. 299 */ 300 struct mbuf * 301 enpget(rxbuf, totlen, off, ifp) 302 u_char *rxbuf; 303 int totlen, off; 304 struct ifnet *ifp; 305 { 306 register u_char *cp; 307 register struct mbuf *m; 308 struct mbuf *top = 0, **mp = ⊤ 309 int len; 310 u_char *packet_end; 311 312 rxbuf += sizeof (struct ether_header); 313 cp = rxbuf; 314 packet_end = cp + totlen; 315 if (off) { 316 off += 2 * sizeof(u_short); 317 totlen -= 2 *sizeof(u_short); 318 cp = rxbuf + off; 319 } 320 321 MGETHDR(m, M_DONTWAIT, MT_DATA); 322 if (m == 0) 323 return (0); 324 m->m_pkthdr.rcvif = ifp; 325 m->m_pkthdr.len = totlen; 326 m->m_len = MHLEN; 327 328 while (totlen > 0) { 329 if (top) { 330 MGET(m, M_DONTWAIT, MT_DATA); 331 if (m == 0) { 332 m_freem(top); 333 return (0); 334 } 335 m->m_len = MLEN; 336 } 337 len = min(totlen, (packet_end - cp)); 338 if (len >= MINCLSIZE) { 339 MCLGET(m, M_DONTWAIT); 340 if (m->m_flags & M_EXT) 341 m->m_len = len = min(len, MCLBYTES); 342 else 343 len = m->m_len; 344 } else { 345 /* 346 * Place initial small packet/header at end of mbuf. 347 */ 348 if (len < m->m_len) { 349 if (top == 0 && len + max_linkhdr <= m->m_len) 350 m->m_data += max_linkhdr; 351 m->m_len = len; 352 } else 353 len = m->m_len; 354 } 355 enpcopy(cp, mtod(m, u_char *), (u_int)len); 356 *mp = m; 357 mp = &m->m_next; 358 totlen -= len; 359 cp += len; 360 if (cp == packet_end) 361 cp = rxbuf; 362 } 363 return (top); 364 } 365 366 enpcopy(from, to, cnt) 367 register u_char *from, *to; 368 register u_int cnt; 369 { 370 register c; 371 register short *f, *t; 372 373 if (((int)from&01) && ((int)to&01)) { 374 /* source & dest at odd addresses */ 375 *to++ = *from++; 376 --cnt; 377 } 378 if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) { 379 t = (short *)to; 380 f = (short *)from; 381 for (c = cnt>>1; c; --c) /* even address copy */ 382 *t++ = *f++; 383 cnt &= 1; 384 if (cnt) { /* odd len */ 385 from = (u_char *)f; 386 to = (u_char *)t; 387 *to = *from; 388 } 389 } 390 while ((int)cnt-- > 0) /* one of the address(es) must be odd */ 391 *to++ = *from++; 392 } 393 394 /* 395 * Process an ioctl request. 396 */ 397 enpioctl(ifp, cmd, data) 398 register struct ifnet *ifp; 399 int cmd; 400 caddr_t data; 401 { 402 register struct ifaddr *ifa = (struct ifaddr *)data; 403 struct enpdevice *addr; 404 int s = splimp(), error = 0; 405 406 switch (cmd) { 407 408 case SIOCSIFADDR: 409 ifp->if_flags |= IFF_UP; 410 switch (ifa->ifa_addr->sa_family) { 411 #ifdef INET 412 case AF_INET: 413 enpinit(ifp->if_unit); 414 ((struct arpcom *)ifp)->ac_ipaddr = 415 IA_SIN(ifa)->sin_addr; 416 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 417 break; 418 #endif 419 #ifdef NS 420 case AF_NS: { 421 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 422 struct enp_softc *es = &enp_softc[ifp->if_unit]; 423 424 if (!ns_nullhost(*ina)) { 425 ifp->if_flags &= ~IFF_RUNNING; 426 addr = (struct enpdevice *) 427 enpinfo[ifp->if_unit]->ui_addr; 428 enpsetaddr(ifp->if_unit, addr, 429 ina->x_host.c_host); 430 } else 431 ina->x_host = *(union ns_host *)es->es_addr; 432 enpinit(ifp->if_unit); 433 break; 434 } 435 #endif 436 default: 437 enpinit(ifp->if_unit); 438 break; 439 } 440 break; 441 442 case SIOCSIFFLAGS: 443 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { 444 enpinit(ifp->if_unit); /* reset board */ 445 ifp->if_flags &= ~IFF_RUNNING; 446 } else if (ifp->if_flags&IFF_UP && 447 (ifp->if_flags&IFF_RUNNING) == 0) 448 enpinit(ifp->if_unit); 449 break; 450 451 default: 452 error = EINVAL; 453 } 454 splx(s); 455 return (error); 456 } 457 458 enpsetaddr(unit, addr, enaddr) 459 int unit; 460 struct enpdevice *addr; 461 u_char *enaddr; 462 { 463 464 enpcopy(enaddr, addr->enp_addr.e_baseaddr.ea_addr, 465 sizeof (struct ether_addr)); 466 enpinit(unit); 467 enpgetaddr(unit, addr); 468 } 469 470 enpgetaddr(unit, addr) 471 int unit; 472 struct enpdevice *addr; 473 { 474 struct enp_softc *es = &enp_softc[unit]; 475 476 enpcopy(addr->enp_addr.e_baseaddr.ea_addr, es->es_addr, 477 sizeof (struct ether_addr)); 478 printf("enp%d: hardware address %s\n", 479 unit, ether_sprintf(es->es_addr)); 480 } 481 482 /* 483 * Routines to synchronize enp and host. 484 */ 485 #ifdef notdef 486 static 487 ringinit(rp, size) 488 register RING *rp; 489 { 490 491 rp->r_rdidx = rp->r_wrtidx = 0; 492 rp->r_size = size; 493 } 494 495 static 496 ringfull(rp) 497 register RING *rp; 498 { 499 register short idx; 500 501 idx = (rp->r_wrtidx + 1) & (rp->r_size-1); 502 return (idx == rp->r_rdidx); 503 } 504 505 static 506 fir(rp) 507 register RING *rp; 508 { 509 510 return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0); 511 } 512 #endif 513 514 static 515 ringempty(rp) 516 register RING *rp; 517 { 518 519 return (rp->r_rdidx == rp->r_wrtidx); 520 } 521 522 static 523 ringput(rp, v) 524 register RING *rp; 525 BCB *v; 526 { 527 register int idx; 528 529 idx = (rp->r_wrtidx + 1) & (rp->r_size-1); 530 if (idx != rp->r_rdidx) { 531 ENPSETLONG(&rp->r_slot[rp->r_wrtidx], v); 532 rp->r_wrtidx = idx; 533 if ((idx -= rp->r_rdidx) < 0) 534 idx += rp->r_size; 535 return (idx); /* num ring entries */ 536 } 537 return (0); 538 } 539 540 static 541 ringget(rp) 542 register RING *rp; 543 { 544 register int i = 0; 545 546 if (rp->r_rdidx != rp->r_wrtidx) { 547 i = ENPGETLONG(&rp->r_slot[rp->r_rdidx]); 548 rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1); 549 } 550 return (i); 551 } 552 553 /* 554 * ENP Ram device. 555 */ 556 enpr_open(dev) 557 dev_t dev; 558 { 559 register int unit = ENPUNIT(dev); 560 struct vba_device *ui; 561 struct enpdevice *addr; 562 563 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || 564 (addr = (struct enpdevice *)ui->ui_addr) == 0) 565 return (ENODEV); 566 if (addr->enp_state != S_ENPRESET) 567 return (EACCES); /* enp is not in reset state, don't open */ 568 return (0); 569 } 570 571 /*ARGSUSED*/ 572 enpr_close(dev) 573 dev_t dev; 574 { 575 576 return (0); 577 } 578 579 enpr_read(dev, uio) 580 dev_t dev; 581 register struct uio *uio; 582 { 583 register struct iovec *iov; 584 struct enpdevice *addr; 585 586 if (uio->uio_offset > RAM_SIZE) 587 return (ENODEV); 588 iov = uio->uio_iov; 589 if (uio->uio_offset + iov->iov_len > RAM_SIZE) 590 iov->iov_len = RAM_SIZE - uio->uio_offset; 591 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; 592 if (useracc(iov->iov_base, (unsigned)iov->iov_len, 0) == 0) 593 return (EFAULT); 594 enpcopy((u_char *)&addr->enp_ram[uio->uio_offset], 595 (u_char *)iov->iov_base, (u_int)iov->iov_len); 596 uio->uio_resid -= iov->iov_len; 597 iov->iov_len = 0; 598 return (0); 599 } 600 601 enpr_write(dev, uio) 602 dev_t dev; 603 register struct uio *uio; 604 { 605 register struct enpdevice *addr; 606 register struct iovec *iov; 607 608 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr; 609 iov = uio->uio_iov; 610 if (uio->uio_offset > RAM_SIZE) 611 return (ENODEV); 612 if (uio->uio_offset + iov->iov_len > RAM_SIZE) 613 iov->iov_len = RAM_SIZE - uio->uio_offset; 614 if (useracc(iov->iov_base, (unsigned)iov->iov_len, 1) == 0) 615 return (EFAULT); 616 enpcopy((u_char *)iov->iov_base, 617 (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len); 618 uio->uio_resid -= iov->iov_len; 619 uio->uio_offset += iov->iov_len; 620 iov->iov_len = 0; 621 return (0); 622 } 623 624 /*ARGSUSED*/ 625 enpr_ioctl(dev, cmd, data) 626 dev_t dev; 627 caddr_t data; 628 { 629 register unit = ENPUNIT(dev); 630 struct enpdevice *addr; 631 632 addr = (struct enpdevice *)enpinfo[unit]->ui_addr; 633 switch(cmd) { 634 635 case ENPIOGO: 636 ENPSETLONG(&addr->enp_base, addr); 637 addr->enp_intrvec = enp_softc[unit].es_ivec; 638 ENP_GO(addr, ENPSTART); 639 DELAY(200000); 640 enpinit(unit); 641 /* 642 * Fetch Ethernet address after link level 643 * is booted (firmware copies manufacturer's 644 * address from on-board ROM). 645 */ 646 enpgetaddr(unit, addr); 647 addr->enp_state = S_ENPRUN; 648 break; 649 650 case ENPIORESET: 651 RESET_ENP(addr); 652 addr->enp_state = S_ENPRESET; 653 DELAY(100000); 654 break; 655 default: 656 return (EINVAL); 657 } 658 return (0); 659 } 660 #endif 661