1 /* $NetBSD: if_netdock_nubus.c,v 1.4 2003/07/15 02:43:23 lukem Exp $ */ 2 3 /* 4 * Copyright (C) 2000,2002 Daishi Kato <daishi@axlight.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Daishi Kato 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Asante NetDock (for Duo series) driver 35 * the chip inside is not known 36 */ 37 38 /* 39 * The author would like to thank Takeo Kuwata <tkuwata@mac.com> for 40 * his help in stabilizing this driver. 41 */ 42 43 /***********************/ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: if_netdock_nubus.c,v 1.4 2003/07/15 02:43:23 lukem Exp $"); 47 48 #include <sys/param.h> 49 #include <sys/device.h> 50 #include <sys/socket.h> 51 #include <sys/systm.h> 52 #include <sys/mbuf.h> 53 #include <sys/ioctl.h> 54 55 #include <net/if.h> 56 #include <net/if_dl.h> 57 #include <net/if_ether.h> 58 59 #include "opt_inet.h" 60 #ifdef INET 61 #include <netinet/in.h> 62 #include <netinet/if_inarp.h> 63 #endif 64 65 #include "bpfilter.h" 66 #if NBPFILTER > 0 67 #include <net/bpf.h> 68 #endif 69 70 #include <machine/bus.h> 71 #include <machine/viareg.h> 72 #include <mac68k/nubus/nubus.h> 73 74 /***********************/ 75 76 #define NETDOCK_DEBUG 77 78 #define NETDOCK_NUBUS_CATEGORY 0x0020 79 #define NETDOCK_NUBUS_TYPE 0x0003 80 #define NETDOCK_NUBUS_DRSW 0x0103 81 #define NETDOCK_NUBUS_DRHW 0x0100 82 83 #define ETHERMICRODOCK_NUBUS_CATEGORY 0x0020 84 #define ETHERMICRODOCK_NUBUS_TYPE 0x0003 85 #define ETHERMICRODOCK_NUBUS_DRSW 0x0102 86 #define ETHERMICRODOCK_NUBUS_DRHW 0x0100 87 88 #define REG_ISR 0x000c 89 #define REG_000E 0x000e 90 #define REG_0000 0x0000 91 #define REG_0002 0x0002 92 #define REG_0004 0x0004 93 #define REG_0006 0x0006 94 #define REG_DATA 0x0008 95 #define REG_EFD00 0xefd00 96 97 #define ISR_ALL 0x3300 98 #define ISR_TX 0x0200 99 #define ISR_RX 0x0100 100 #define ISR_READY 0x0800 101 #define ISR_BIT_0C 0x1000 102 #define ISR_BIT_0D 0x2000 103 #define ISR_MASK 0x0033 104 #define ISR_BIT_03 0x0008 105 106 #define REG_0002_BIT_04 0x0010 107 #define REG_0000_BIT_08 0x0100 108 #define REG_0004_BIT_0F 0x8000 109 #define REG_0004_BIT_07 0x0080 110 #define REG_DATA_BIT_02 0x0004 111 #define REG_DATA_BIT_03 0x0008 112 #define REG_DATA_BIT_04 0x0010 113 #define REG_DATA_BIT_05 0x0020 114 #define REG_DATA_BIT_08 0x0100 115 #define REG_DATA_BIT_07 0x0080 116 #define REG_DATA_BIT_0F 0x8000 117 118 /***********************/ 119 120 typedef struct netdock_softc { 121 struct device sc_dev; 122 struct ethercom sc_ethercom; 123 #define sc_if sc_ethercom.ec_if 124 125 bus_space_tag_t sc_regt; 126 bus_space_handle_t sc_regh; 127 128 u_int8_t sc_enaddr[ETHER_ADDR_LEN]; 129 130 } netdock_softc_t; 131 132 /***********************/ 133 134 static int netdock_nubus_match __P((struct device *, struct cfdata *, 135 void*)); 136 static void netdock_nubus_attach __P((struct device *, struct device *, 137 void *)); 138 static int netdock_nb_get_enaddr __P((bus_space_tag_t, bus_space_handle_t, 139 struct nubus_attach_args *, u_int8_t *)); 140 #ifdef NETDOCK_DEBUG_DRIVER 141 static void netdock_print_driver __P((bus_space_tag_t, bus_space_handle_t, 142 struct nubus_attach_args *)); 143 #endif 144 145 int netdock_setup __P((struct netdock_softc *, u_int8_t *)); 146 void netdock_intr __P((void *)); 147 148 static void netdock_watchdog __P((struct ifnet *)); 149 static int netdock_init __P((struct netdock_softc *)); 150 static int netdock_stop __P((struct netdock_softc *)); 151 static int netdock_ioctl __P((struct ifnet *, u_long, caddr_t)); 152 static void netdock_start __P((struct ifnet *)); 153 static void netdock_reset __P((struct netdock_softc *)); 154 static void netdock_txint __P((struct netdock_softc *)); 155 static void netdock_rxint __P((struct netdock_softc *)); 156 157 static u_int netdock_put __P((struct netdock_softc *, struct mbuf *)); 158 static int netdock_read __P((struct netdock_softc *, int)); 159 static struct mbuf *netdock_get __P((struct netdock_softc *, int)); 160 161 /***********************/ 162 163 #define NIC_GET_1(sc, o) (bus_space_read_1((sc)->sc_regt, \ 164 (sc)->sc_regh, (o))) 165 #define NIC_PUT_1(sc, o, val) (bus_space_write_1((sc)->sc_regt, \ 166 (sc)->sc_regh, (o), (val))) 167 #define NIC_GET_2(sc, o) (bus_space_read_2((sc)->sc_regt, \ 168 (sc)->sc_regh, (o))) 169 #define NIC_PUT_2(sc, o, val) (bus_space_write_2((sc)->sc_regt, \ 170 (sc)->sc_regh, (o), (val))) 171 #define NIC_GET_4(sc, o) (bus_space_read_4((sc)->sc_regt, \ 172 (sc)->sc_regh, (o))) 173 #define NIC_PUT_4(sc, o, val) (bus_space_write_4((sc)->sc_regt, \ 174 (sc)->sc_regh, (o), (val))) 175 176 #define NIC_BSET(sc, o, b) \ 177 __asm__ __volatile("bset %0,%1" : : "di" ((u_short)(b)), \ 178 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o)))) 179 #define NIC_BCLR(sc, o, b) \ 180 __asm__ __volatile("bclr %0,%1" : : "di" ((u_short)(b)), \ 181 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o)))) 182 #define NIC_ANDW(sc, o, b) \ 183 __asm__ __volatile("andw %0,%1" : : "di" ((u_short)(b)), \ 184 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o)))) 185 #define NIC_ORW(sc, o, b) \ 186 __asm__ __volatile("orw %0,%1" : : "di" ((u_short)(b)), \ 187 "g" (*(u_int8_t *)((sc)->sc_regh.base + (o)))) 188 189 190 /***********************/ 191 192 CFATTACH_DECL(netdock_nubus, sizeof(struct netdock_softc), 193 netdock_nubus_match, netdock_nubus_attach, NULL, NULL); 194 195 /***********************/ 196 197 static int 198 netdock_nubus_match(parent, cf, aux) 199 struct device *parent; 200 struct cfdata *cf; 201 void *aux; 202 { 203 struct nubus_attach_args *na = (struct nubus_attach_args *)aux; 204 bus_space_handle_t bsh; 205 int rv; 206 207 if (bus_space_map(na->na_tag, NUBUS_SLOT2PA(na->slot), 208 NBMEMSIZE, 0, &bsh)) 209 return (0); 210 211 rv = 0; 212 213 if (na->category == NETDOCK_NUBUS_CATEGORY && 214 na->type == NETDOCK_NUBUS_TYPE && 215 na->drsw == NETDOCK_NUBUS_DRSW) { 216 /* assuming this IS Asante NetDock */ 217 rv = 1; 218 } 219 220 if (na->category == ETHERMICRODOCK_NUBUS_CATEGORY && 221 na->type == ETHERMICRODOCK_NUBUS_TYPE && 222 na->drsw == ETHERMICRODOCK_NUBUS_DRSW) { 223 /* assuming this IS Newer EtherMicroDock */ 224 rv = 1; 225 } 226 227 bus_space_unmap(na->na_tag, bsh, NBMEMSIZE); 228 229 return rv; 230 } 231 232 static void 233 netdock_nubus_attach(parent, self, aux) 234 struct device *parent, *self; 235 void *aux; 236 { 237 struct netdock_softc *sc = (struct netdock_softc *)self; 238 struct nubus_attach_args *na = (struct nubus_attach_args *)aux; 239 bus_space_tag_t bst; 240 bus_space_handle_t bsh; 241 u_int8_t enaddr[ETHER_ADDR_LEN]; 242 char *cardtype; 243 244 bst = na->na_tag; 245 if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh)) { 246 printf(": failed to map memory space.\n"); 247 return; 248 } 249 250 sc->sc_regt = bst; 251 cardtype = nubus_get_card_name(bst, bsh, na->fmt); 252 253 #ifdef NETDOCK_DEBUG_DRIVER 254 netdock_print_driver(bst, bsh, na); 255 #endif 256 257 if (netdock_nb_get_enaddr(bst, bsh, na, enaddr)) { 258 printf(": can't find MAC address.\n"); 259 bus_space_unmap(bst, bsh, NBMEMSIZE); 260 return; 261 } 262 263 if (bus_space_subregion(bst, bsh, 0xe00300, 0xf0000, &sc->sc_regh)) { 264 printf(": failed to map register space.\n"); 265 bus_space_unmap(bst, bsh, NBMEMSIZE); 266 return; 267 } 268 269 printf(": %s\n", cardtype); 270 271 if (netdock_setup(sc, enaddr)) { 272 bus_space_unmap(bst, bsh, NBMEMSIZE); 273 return; 274 } 275 276 add_nubus_intr(na->slot, netdock_intr, (void *)sc); 277 278 return; 279 } 280 281 static int 282 netdock_nb_get_enaddr(bst, bsh, na, ep) 283 bus_space_tag_t bst; 284 bus_space_handle_t bsh; 285 struct nubus_attach_args *na; 286 u_int8_t *ep; 287 { 288 nubus_dir dir; 289 nubus_dirent dirent; 290 291 /* 292 * these hardwired resource IDs are only for NetDock 293 */ 294 nubus_get_main_dir(na->fmt, &dir); 295 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x81, &dirent) <= 0) 296 return 1; 297 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir); 298 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x80, &dirent) <= 0) 299 return 1; 300 if (nubus_get_ind_data(bst, bsh, na->fmt, &dirent, 301 ep, ETHER_ADDR_LEN) <= 0) 302 return 1; 303 304 return 0; 305 } 306 307 #ifdef NETDOCK_DEBUG_DRIVER 308 static void 309 netdock_print_driver(bst, bsh, na) 310 bus_space_tag_t bst; 311 bus_space_handle_t bsh; 312 struct nubus_attach_args *na; 313 { 314 #define HEADSIZE (8+4) 315 #define CODESIZE (6759-4) 316 unsigned char mydata[HEADSIZE + CODESIZE]; 317 nubus_dir dir; 318 nubus_dirent dirent; 319 int i, rv; 320 321 nubus_get_main_dir(na->fmt, &dir); 322 rv = nubus_find_rsrc(bst, bsh, na->fmt, &dir, 0x81, &dirent); 323 if (rv <= 0) { 324 printf(": can't find sResource.\n"); 325 return; 326 } 327 nubus_get_dir_from_rsrc(na->fmt, &dirent, &dir); 328 if (nubus_find_rsrc(bst, bsh, na->fmt, &dir, NUBUS_RSRC_DRVRDIR, 329 &dirent) <= 0) { 330 printf(": can't find sResource.\n"); 331 return; 332 } 333 if (nubus_get_ind_data(bst, bsh, na->fmt, 334 &dirent, mydata, HEADSIZE+CODESIZE) <= 0) { 335 printf(": can't find indirect data.\n"); 336 return; 337 } 338 printf("\n########## begin driver dir"); 339 for (i = 0; i < HEADSIZE; i++) { 340 if (i % 16 == 0) 341 printf("\n%02x:",i); 342 printf(" %02x", mydata[i]); 343 } 344 printf("\n########## begin driver code"); 345 for (i = 0; i < CODESIZE; i++) { 346 if (i % 16 == 0) 347 printf("\n%02x:",i); 348 printf(" %02x", mydata[i + HEADSIZE]); 349 } 350 #if 0 351 printf("\n########## begin driver code (partial)\n"); 352 #define PARTSIZE 256 353 #define OFFSET 0x1568 354 for (i = OFFSET; i < OFFSET + PARTSIZE; i++) { 355 if ((i - OFFSET) % 16 == 0) 356 printf("\n%02x:",i); 357 printf(" %02x", mydata[i + HEADSIZE]); 358 } 359 #endif 360 printf("\n########## end\n"); 361 } 362 #endif 363 364 365 int 366 netdock_setup(sc, lladdr) 367 struct netdock_softc *sc; 368 u_int8_t *lladdr; 369 { 370 struct ifnet *ifp = &sc->sc_if; 371 372 bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN); 373 printf("%s: Ethernet address %s\n", 374 sc->sc_dev.dv_xname, ether_sprintf(lladdr)); 375 376 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 377 ifp->if_softc = sc; 378 ifp->if_ioctl = netdock_ioctl; 379 ifp->if_start = netdock_start; 380 ifp->if_flags = 381 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 382 ifp->if_watchdog = netdock_watchdog; 383 384 if_attach(ifp); 385 ether_ifattach(ifp, lladdr); 386 387 return (0); 388 } 389 390 static int 391 netdock_ioctl(ifp, cmd, data) 392 struct ifnet *ifp; 393 u_long cmd; 394 caddr_t data; 395 { 396 struct ifaddr *ifa; 397 struct ifreq *ifr; 398 struct netdock_softc *sc = ifp->if_softc; 399 int s = splnet(); 400 int err = 0; 401 int temp; 402 403 switch (cmd) { 404 case SIOCSIFADDR: 405 ifa = (struct ifaddr *)data; 406 ifp->if_flags |= IFF_UP; 407 switch (ifa->ifa_addr->sa_family) { 408 #ifdef INET 409 case AF_INET: 410 (void)netdock_init(sc); 411 arp_ifinit(ifp, ifa); 412 break; 413 #endif 414 default: 415 (void)netdock_init(sc); 416 break; 417 } 418 break; 419 420 case SIOCSIFFLAGS: 421 if ((ifp->if_flags & IFF_UP) == 0 && 422 (ifp->if_flags & IFF_RUNNING) != 0) { 423 netdock_stop(sc); 424 ifp->if_flags &= ~IFF_RUNNING; 425 } else if ((ifp->if_flags & IFF_UP) != 0 && 426 (ifp->if_flags & IFF_RUNNING) == 0) { 427 (void)netdock_init(sc); 428 } else { 429 temp = ifp->if_flags & IFF_UP; 430 netdock_reset(sc); 431 ifp->if_flags |= temp; 432 netdock_start(ifp); 433 } 434 break; 435 436 case SIOCADDMULTI: 437 case SIOCDELMULTI: 438 ifr = (struct ifreq *)data; 439 if (cmd == SIOCADDMULTI) 440 err = ether_addmulti(ifr, &sc->sc_ethercom); 441 else 442 err = ether_delmulti(ifr, &sc->sc_ethercom); 443 444 if (err == ENETRESET) { 445 temp = ifp->if_flags & IFF_UP; 446 netdock_reset(sc); 447 ifp->if_flags |= temp; 448 err = 0; 449 } 450 break; 451 default: 452 err = EINVAL; 453 break; 454 } 455 splx(s); 456 return (err); 457 } 458 459 static void 460 netdock_start(ifp) 461 struct ifnet *ifp; 462 { 463 struct netdock_softc *sc = ifp->if_softc; 464 struct mbuf *m; 465 466 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 467 return; 468 469 while (1) { 470 IF_DEQUEUE(&ifp->if_snd, m); 471 if (m == 0) 472 return; 473 474 if ((m->m_flags & M_PKTHDR) == 0) 475 panic("%s: netdock_start: no header mbuf", 476 sc->sc_dev.dv_xname); 477 478 #if NBPFILTER > 0 479 if (ifp->if_bpf) 480 bpf_mtap(ifp->if_bpf, m); 481 #endif 482 483 if ((netdock_put(sc, m)) == 0) { 484 IF_PREPEND(&ifp->if_snd, m); 485 return; 486 } 487 488 ifp->if_opackets++; 489 } 490 491 } 492 493 static void 494 netdock_reset(sc) 495 struct netdock_softc *sc; 496 { 497 498 netdock_stop(sc); 499 netdock_init(sc); 500 } 501 502 static int 503 netdock_init(sc) 504 struct netdock_softc *sc; 505 { 506 int s; 507 int saveisr; 508 int savetmp; 509 510 if (sc->sc_if.if_flags & IFF_RUNNING) 511 return (0); 512 513 s = splnet(); 514 515 /* 0606 */ 516 NIC_PUT_2(sc, REG_000E, 0x0200); 517 NIC_PUT_2(sc, REG_ISR , 0); 518 NIC_PUT_2(sc, REG_000E, 0); 519 520 NIC_PUT_2(sc, REG_0000, 0x8104); 521 NIC_PUT_2(sc, REG_0004, 0x0043); 522 NIC_PUT_2(sc, REG_000E, 0x0100); 523 NIC_PUT_2(sc, REG_0002, 0x6618); 524 NIC_PUT_2(sc, REG_0000, 0x8010); 525 526 NIC_PUT_1(sc, REG_0004 + 0, sc->sc_enaddr[0]); 527 NIC_PUT_1(sc, REG_0004 + 1, sc->sc_enaddr[1]); 528 NIC_PUT_1(sc, REG_0004 + 2, sc->sc_enaddr[2]); 529 NIC_PUT_1(sc, REG_0004 + 3, sc->sc_enaddr[3]); 530 NIC_PUT_1(sc, REG_0004 + 4, sc->sc_enaddr[4]); 531 NIC_PUT_1(sc, REG_0004 + 5, sc->sc_enaddr[5]); 532 533 NIC_PUT_2(sc, REG_ISR , 0x2008); 534 NIC_PUT_2(sc, REG_000E, 0x0200); 535 NIC_PUT_2(sc, REG_0000, 0x4000); 536 NIC_PUT_2(sc, REG_ISR, ISR_MASK); 537 538 539 /* 1320 */ 540 saveisr = NIC_GET_2(sc, REG_ISR); 541 NIC_PUT_2(sc, REG_ISR , 0); 542 savetmp = NIC_GET_2(sc, REG_000E); 543 NIC_PUT_2(sc, REG_000E, 0x0100); 544 NIC_ANDW(sc, REG_ISR, ~ISR_BIT_03); 545 NIC_PUT_2(sc, REG_000E, savetmp); 546 547 /* 1382 */ 548 savetmp = NIC_GET_2(sc, REG_000E); 549 NIC_PUT_2(sc, REG_000E, 0x0100); 550 NIC_ORW(sc, REG_ISR, ISR_BIT_03); 551 NIC_PUT_2(sc, REG_000E, savetmp); 552 NIC_PUT_2(sc, REG_ISR , saveisr); 553 554 555 sc->sc_if.if_flags |= IFF_RUNNING; 556 sc->sc_if.if_flags &= ~IFF_OACTIVE; 557 558 splx(s); 559 return (0); 560 } 561 562 static int 563 netdock_stop(sc) 564 struct netdock_softc *sc; 565 { 566 int s = splnet(); 567 568 sc->sc_if.if_timer = 0; 569 sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP); 570 571 splx(s); 572 return (0); 573 } 574 575 static void 576 netdock_watchdog(ifp) 577 struct ifnet *ifp; 578 { 579 struct netdock_softc *sc = ifp->if_softc; 580 int tmp; 581 582 printf("netdock_watchdog: resetting chip\n"); 583 tmp = ifp->if_flags & IFF_UP; 584 netdock_reset(sc); 585 ifp->if_flags |= tmp; 586 } 587 588 static u_int 589 netdock_put(sc, m0) 590 struct netdock_softc *sc; 591 struct mbuf *m0; 592 { 593 struct mbuf *m; 594 u_int totlen = 0; 595 u_int tmplen; 596 int isr; 597 int timeout; 598 int tmp; 599 u_int i; 600 601 for (m = m0; m; m = m->m_next) 602 totlen += m->m_len; 603 604 if (totlen >= ETHER_MAX_LEN) 605 panic("%s: netdock_put: packet overflow", sc->sc_dev.dv_xname); 606 607 totlen += 6; 608 tmplen = totlen; 609 tmplen &= 0xff00; 610 tmplen |= 0x2000; 611 NIC_PUT_2(sc, REG_0000, tmplen); 612 613 timeout = 0x3000; 614 while ((((isr = NIC_GET_2(sc, REG_ISR)) & ISR_READY) == 0) && 615 timeout--) { 616 if (isr & ISR_TX) 617 netdock_txint(sc); 618 } 619 if (timeout == 0) 620 return (0); 621 622 tmp = NIC_GET_2(sc, REG_0002); 623 tmp <<= 8; 624 NIC_PUT_2(sc, REG_0002, tmp); 625 NIC_PUT_2(sc, REG_0006, 0x240); 626 NIC_GET_2(sc, REG_ISR); 627 tmplen = ((totlen << 8) & 0xfe00) | ((totlen >> 8) & 0x00ff); 628 NIC_PUT_2(sc, REG_DATA, tmplen); 629 630 for (m = m0; m; m = m->m_next) { 631 u_char *data = mtod(m, u_char *); 632 int len = m->m_len; 633 int len4 = len >> 2; 634 u_int32_t *data4 = (u_int32_t *)data; 635 for (i = 0; i < len4; i++) 636 NIC_PUT_4(sc, REG_DATA, data4[i]); 637 for (i = len4 << 2; i < len; i++) 638 NIC_PUT_1(sc, REG_DATA, data[i]); 639 } 640 641 if (totlen & 0x01) 642 NIC_PUT_2(sc, REG_DATA, 0x2020); 643 else 644 NIC_PUT_2(sc, REG_DATA, 0); 645 646 NIC_PUT_2(sc, REG_0000, 0xc000); 647 648 m_freem(m0); 649 /* sc->sc_if.if_timer = 5; */ 650 return (totlen); 651 } 652 653 void 654 netdock_intr(arg) 655 void *arg; 656 { 657 struct netdock_softc *sc = (struct netdock_softc *)arg; 658 int isr; 659 int tmp; 660 661 NIC_PUT_2(sc, REG_ISR, 0); 662 while ((isr = (NIC_GET_2(sc, REG_ISR) & ISR_ALL)) != 0) { 663 if (isr & ISR_TX) 664 netdock_txint(sc); 665 666 if (isr & ISR_RX) 667 netdock_rxint(sc); 668 669 if (isr & (ISR_BIT_0C | ISR_BIT_0D)) { 670 if (isr & ISR_BIT_0C) { 671 NIC_PUT_2(sc, REG_000E, 0); 672 NIC_BSET(sc, REG_0004, 0x08); 673 NIC_PUT_2(sc, REG_000E, 0x0200); 674 } 675 if (isr & ISR_BIT_0D) { 676 NIC_PUT_2(sc, REG_000E, 0); 677 tmp = NIC_GET_2(sc, REG_0002); 678 if (tmp & REG_0002_BIT_04) 679 NIC_GET_2(sc, REG_0006); 680 tmp = NIC_GET_2(sc, REG_0000); 681 if (tmp & REG_0000_BIT_08) 682 NIC_BSET(sc, REG_0000, 0x08); 683 NIC_PUT_2(sc, REG_000E, 0x0200); 684 } 685 NIC_PUT_2(sc, REG_ISR, isr); 686 } 687 } 688 NIC_PUT_2(sc, REG_ISR, ISR_MASK); 689 } 690 691 static void 692 netdock_txint(sc) 693 struct netdock_softc *sc; 694 { 695 struct ifnet *ifp = &sc->sc_if; 696 int savereg0002; 697 int reg0004; 698 int regdata; 699 700 ifp->if_flags &= ~IFF_OACTIVE; 701 ifp->if_timer = 0; 702 703 savereg0002 = NIC_GET_2(sc, REG_0002); 704 705 while (((reg0004 = NIC_GET_2(sc, REG_0004)) & REG_0004_BIT_0F) == 0) { 706 NIC_PUT_2(sc, REG_0002, reg0004); 707 NIC_PUT_2(sc, REG_0006, 0x0060); 708 NIC_GET_2(sc, REG_ISR); 709 regdata = NIC_GET_2(sc, REG_DATA); 710 if ((regdata & REG_DATA_BIT_08) == 0) { 711 /* ifp->if_collisions++; */ 712 if (regdata & REG_DATA_BIT_07) 713 /* ifp->if_oerrors++; */ 714 NIC_PUT_2(sc, REG_000E, 0); 715 NIC_ORW(sc, REG_0000, 0x0100); 716 NIC_PUT_2(sc, REG_000E, 0x0200); 717 } 718 NIC_GET_2(sc ,REG_DATA); 719 720 if (regdata & REG_DATA_BIT_0F) 721 NIC_GET_4(sc, REG_EFD00); 722 NIC_PUT_2(sc, REG_0000, 0xa000); 723 NIC_PUT_2(sc, REG_ISR, ISR_TX); 724 } 725 726 NIC_PUT_2(sc, REG_0002, savereg0002); 727 NIC_PUT_2(sc, REG_000E, 0); 728 NIC_GET_2(sc, REG_0006); 729 NIC_PUT_2(sc, REG_000E, 0x0200); 730 NIC_PUT_2(sc, REG_0006, 0); 731 } 732 733 static void 734 netdock_rxint(sc) 735 struct netdock_softc *sc; 736 { 737 struct ifnet *ifp = &sc->sc_if; 738 int regdata1; 739 int regdata2; 740 u_int len; 741 int timeout; 742 743 while ((NIC_GET_2(sc, REG_0004) & REG_0004_BIT_07) == 0) { 744 NIC_GET_2(sc, REG_ISR); 745 NIC_PUT_2(sc, REG_0006, 0x00e0); 746 NIC_GET_2(sc, REG_ISR); 747 regdata1 = NIC_GET_2(sc, REG_DATA); 748 regdata2 = NIC_GET_2(sc, REG_DATA); 749 len = ((regdata2 << 8) & 0x0700) | ((regdata2 >> 8) & 0x00ff); 750 751 #if 0 752 printf("netdock_rxint: r1=0x%04x, r2=0x%04x, len=%d\n", 753 regdata1, regdata2, len); 754 #endif 755 756 if ((regdata1 & REG_DATA_BIT_04) == 0) 757 len -= 2; 758 759 if ((regdata1 & 0x00ac) == 0) { 760 if (netdock_read(sc, len)) 761 ifp->if_ipackets++; 762 else 763 ifp->if_ierrors++; 764 } else { 765 ifp->if_ierrors++; 766 767 if (regdata1 & REG_DATA_BIT_02) 768 NIC_GET_4(sc, REG_EFD00); 769 if (regdata1 & REG_DATA_BIT_03) 770 ; 771 if (regdata1 & REG_DATA_BIT_05) 772 NIC_GET_4(sc, REG_EFD00); 773 if (regdata1 & REG_DATA_BIT_07) 774 ; 775 } 776 777 timeout = 0x14; 778 while ((NIC_GET_2(sc, REG_0000) & REG_0000_BIT_08) && timeout--) 779 ; 780 if (timeout == 0) 781 ; 782 783 NIC_PUT_2(sc, REG_0000, 0x8000); 784 } 785 NIC_PUT_2(sc, REG_0006, 0); 786 } 787 788 static int 789 netdock_read(sc, len) 790 struct netdock_softc *sc; 791 int len; 792 { 793 struct ifnet *ifp = &sc->sc_if; 794 struct mbuf *m; 795 796 m = netdock_get(sc, len); 797 if (m == 0) 798 return (0); 799 800 /* the data comes with frame checksum and ethernet header */ 801 m->m_flags |= M_HASFCS; 802 803 #if NBPFILTER > 0 804 if (ifp->if_bpf) 805 bpf_mtap(ifp->if_bpf, m); 806 #endif 807 808 (*ifp->if_input)(ifp, m); 809 810 return (1); 811 } 812 813 static struct mbuf * 814 netdock_get(sc, datalen) 815 struct netdock_softc *sc; 816 int datalen; 817 { 818 struct mbuf *m, *top, **mp; 819 u_char *data; 820 int i; 821 int len; 822 int len4; 823 u_int32_t *data4; 824 825 MGETHDR(m, M_DONTWAIT, MT_DATA); 826 if (m == NULL) 827 return (NULL); 828 m->m_pkthdr.rcvif = &sc->sc_if; 829 m->m_pkthdr.len = datalen; 830 len = MHLEN; 831 top = NULL; 832 mp = ⊤ 833 834 while (datalen > 0) { 835 if (top) { 836 MGET(m, M_DONTWAIT, MT_DATA); 837 if (m == 0) { 838 m_freem(top); 839 return (NULL); 840 } 841 len = MLEN; 842 } 843 if (datalen >= MINCLSIZE) { 844 MCLGET(m, M_DONTWAIT); 845 if ((m->m_flags & M_EXT) == 0) { 846 if (top) 847 m_freem(top); 848 return (NULL); 849 } 850 len = MCLBYTES; 851 } 852 853 if (mp == &top) { 854 caddr_t newdata = (caddr_t) 855 ALIGN(m->m_data + sizeof(struct ether_header)) - 856 sizeof(struct ether_header); 857 len -= newdata - m->m_data; 858 m->m_data = newdata; 859 } 860 861 m->m_len = len = min(datalen, len); 862 863 data = mtod(m, u_char *); 864 len4 = len >> 2; 865 data4 = (u_int32_t *)data; 866 for (i = 0; i < len4; i++) 867 data4[i] = NIC_GET_4(sc, REG_DATA); 868 for (i = len4 << 2; i < len; i++) 869 data[i] = NIC_GET_1(sc, REG_DATA); 870 871 datalen -= len; 872 *mp = m; 873 mp = &m->m_next; 874 } 875 876 return (top); 877 } 878