|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1997 Apple Computer, Inc. ! 24: * ! 25: * ethernet driver for mace on-board ethernet ! 26: * ! 27: * HISTORY ! 28: * ! 29: * Dieter Siegmund ([email protected]) Thu Feb 27 18:25:33 PST 1997 ! 30: * - ripped off code from MK/LINUX, turned it into a polled-mode ! 31: * driver for the PCI (8500) class machines ! 32: * ! 33: * Dieter Siegmund ([email protected]) Fri Mar 21 12:41:29 PST 1997 ! 34: * - reworked to support a BSD-style interface, and to support kdb polled ! 35: * interface and interrupt-driven interface concurrently ! 36: * ! 37: * Justin Walker ([email protected]) Tue May 20 10:29:29 PDT 1997 ! 38: * - Added multicast support ! 39: * ! 40: * Dieter Siegmund ([email protected]) Thu May 29 15:02:29 PDT 1997 ! 41: * - fixed problem with sending arp packets for ip address 0.0.0.0 ! 42: * - use kdp_register_send_receive() instead of defining ! 43: * en_send_pkt/en_recv_pkt routines to avoid name space ! 44: * collisions with IOEthernetDebugger and allow these routines to be ! 45: * overridden by a driverkit-style driver ! 46: * ! 47: * Dieter Siegmund ([email protected]) Tue Jun 24 18:29:15 PDT 1997 ! 48: * - don't let the adapter auto-strip 802.3 receive frames, it messes ! 49: * up the frame size logic ! 50: * ! 51: * Dieter Siegmund ([email protected]) Tue Aug 5 16:24:52 PDT 1997 ! 52: * - handle multicast address deletion correctly ! 53: */ ! 54: #ifdef MACE_DEBUG ! 55: /* ! 56: * Caveat: MACE_DEBUG delimits some code that is getting kind of ! 57: * stale. Before blindly turning on MACE_DEBUG for your ! 58: * testing, take a look at the code enabled by it to check ! 59: * that it is reasonably sane. ! 60: */ ! 61: #endif ! 62: ! 63: #import <machdep/ppc/dbdma.h> ! 64: #import <kern/kdp_en_debugger.h> ! 65: ! 66: #define RECEIVE_INT DBDMA_INT_ALWAYS ! 67: ! 68: #import <sys/types.h> ! 69: #import <sys/systm.h> ! 70: #import <sys/param.h> ! 71: #import <sys/errno.h> ! 72: #import <sys/socket.h> ! 73: #import <net/if.h> ! 74: #import <net/etherdefs.h> ! 75: #import <netinet/if_ether.h> ! 76: #import <sys/sockio.h> ! 77: #import <netinet/in_var.h> ! 78: #import <netinet/in.h> ! 79: #import <sys/mbuf.h> ! 80: #import <mach/mach_types.h> ! 81: #import <ppc/powermac.h> ! 82: #import <ppc/interrupts.h> ! 83: #import <ppc/proc_reg.h> ! 84: #import <libkern/libkern.h> ! 85: #import <kern/thread_call.h> ! 86: #import "if_en.h" ! 87: #import "mace.h" ! 88: ! 89: extern int kdp_flag; ! 90: ! 91: #if NBPFILTER > 0 ! 92: #import <net/bpf.h> ! 93: #endif ! 94: ! 95: static void polled_send_pkt(char * data, int len); ! 96: static void polled_receive_pkt(char *data, int *len, int timeout_ms); ! 97: void mace_dbdma_rx_intr(int unit, void *, void *); ! 98: void mace_dbdma_tx_intr(int, void *, void *); ! 99: void mace_pci_intr(int, void *); ! 100: void mace_service_queue(struct ifnet * ifp); ! 101: ! 102: #ifdef MACE_DEBUG ! 103: static int mace_watchdog(); ! 104: #endif ! 105: ! 106: static __inline__ vm_offset_t ! 107: KVTOPHYS(vm_offset_t v) ! 108: { ! 109: return (v); ! 110: } ! 111: ! 112: typedef int (*funcptr)(char *, int, void *); ! 113: ! 114: #ifdef MACE_DEBUG ! 115: static int ! 116: macAddrsEqual(unsigned char * one, unsigned char * two) ! 117: { ! 118: int i; ! 119: ! 120: for (i = 0; i < NUM_EN_ADDR_BYTES; i++) ! 121: if (*one++ != *two++) ! 122: return 0; ! 123: return 1; ! 124: } ! 125: #endif ! 126: ! 127: static __inline__ int ! 128: isprint(unsigned char c) ! 129: { ! 130: return (c >= 0x20 && c <= 0x7e); ! 131: } ! 132: ! 133: static void ! 134: printEtherHeader(enet_addr_t * dh, enet_addr_t * sh, u_short etype) ! 135: { ! 136: u_char * dhost = dh->ether_addr_octet; ! 137: u_char * shost = sh->ether_addr_octet; ! 138: ! 139: printf("Dst: %x:%x:%x:%x:%x:%x Src: %x:%x:%x:%x:%x:%x Type: 0x%x\n", ! 140: dhost[0], dhost[1], dhost[2], dhost[3], dhost[4], dhost[5], ! 141: shost[0], shost[1], shost[2], shost[3], shost[4], shost[5], ! 142: etype); ! 143: } ! 144: ! 145: static void ! 146: printData(u_char * data_p, int n_bytes) ! 147: { ! 148: #define CHARS_PER_LINE 16 ! 149: char line_buf[CHARS_PER_LINE + 1]; ! 150: int line_pos; ! 151: int offset; ! 152: ! 153: for (line_pos = 0, offset = 0; offset < n_bytes; offset++, data_p++) { ! 154: if (line_pos == 0) { ! 155: printf("%04d ", offset); ! 156: } ! 157: ! 158: line_buf[line_pos] = isprint(*data_p) ? *data_p : '.'; ! 159: printf(" %02x", *data_p); ! 160: line_pos++; ! 161: if (line_pos == CHARS_PER_LINE) { ! 162: line_buf[CHARS_PER_LINE] = '\0'; ! 163: printf(" %s\n", line_buf); ! 164: line_pos = 0; ! 165: } ! 166: } ! 167: if (line_pos) { /* need to finish up the line */ ! 168: for (; line_pos < CHARS_PER_LINE; line_pos++) { ! 169: printf(" "); ! 170: line_buf[line_pos] = ' '; ! 171: } ! 172: line_buf[CHARS_PER_LINE] = '\0'; ! 173: printf(" %s\n", line_buf); ! 174: } ! 175: } ! 176: ! 177: static void ! 178: printEtherPacket(enet_addr_t * dhost, enet_addr_t * shost, u_short type, ! 179: u_char * data_p, int n_bytes) ! 180: { ! 181: printEtherHeader(dhost, shost, type); ! 182: printData(data_p, n_bytes); ! 183: } ! 184: ! 185: void ! 186: printContiguousEtherPacket(u_char * data_p, int n_bytes) ! 187: { ! 188: printEtherPacket((enet_addr_t *)data_p, ! 189: (enet_addr_t *)(data_p + NUM_EN_ADDR_BYTES), ! 190: *((u_short *)(data_p + (NUM_EN_ADDR_BYTES * 2))), ! 191: data_p, n_bytes); ! 192: } ! 193: ! 194: mace_t mace; ! 195: ! 196: #define MACE_DMA_AREA_SIZE (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE) ! 197: static unsigned long mace_rx_dma_area[(MACE_DMA_AREA_SIZE + sizeof(long))/sizeof(long)]; ! 198: ! 199: static unsigned long mace_tx_dma_area[(ETHERNET_BUF_SIZE + PG_SIZE + sizeof(long))/sizeof(long)]; ! 200: ! 201: /* ! 202: * mace_get_hwid ! 203: * ! 204: * This function computes the Ethernet Hardware address ! 205: * from PROM. (Its best not to ask how this is done.) ! 206: */ ! 207: ! 208: unsigned char ! 209: mace_swapbits(unsigned char bits) ! 210: { ! 211: unsigned char mask = 0x1, i, newbits = 0; ! 212: ! 213: for (i = 0x80; i; mask <<= 1, i >>=1) { ! 214: if (bits & mask) ! 215: newbits |= i; ! 216: } ! 217: ! 218: return newbits; ! 219: } ! 220: ! 221: void ! 222: mace_get_hwid(unsigned char *hwid_addr, mace_t * m) ! 223: { ! 224: int i; ! 225: ! 226: for (i = 0; i < NUM_EN_ADDR_BYTES; i++, hwid_addr += 16) { ! 227: m->macaddr[i] = mace_swapbits(*hwid_addr); ! 228: } ! 229: } ! 230: ! 231: /* ! 232: * mace_reset ! 233: * ! 234: * Reset the board.. ! 235: */ ! 236: ! 237: void ! 238: mace_reset() ! 239: { ! 240: dbdma_reset(DBDMA_ETHERNET_RV); ! 241: dbdma_reset(DBDMA_ETHERNET_TX); ! 242: } ! 243: ! 244: ! 245: /* ! 246: * mace_geteh: ! 247: * ! 248: * This function gets the ethernet address (array of 6 unsigned ! 249: * bytes) from the MACE board registers. ! 250: * ! 251: */ ! 252: ! 253: void ! 254: mace_geteh(char *ep) ! 255: { ! 256: int i; ! 257: unsigned char ep_temp; ! 258: ! 259: mace.ereg->iac = IAC_PHYADDR; eieio(); ! 260: ! 261: for (i = 0; i < ETHER_ADD_SIZE; i++) { ! 262: ep_temp = mace.ereg->padr; eieio(); ! 263: *ep++ = ep_temp; ! 264: } ! 265: } ! 266: ! 267: /* ! 268: * mace_seteh: ! 269: * ! 270: * This function sets the ethernet address (array of 6 unsigned ! 271: * bytes) on the MACE board. ! 272: */ ! 273: ! 274: static void ! 275: mace_seteh(char *ep) ! 276: { ! 277: int i; ! 278: unsigned char status; ! 279: ! 280: if (mace.chip_id != MACE_REVISION_A2) { ! 281: mace.ereg->iac = IAC_ADDRCHG|IAC_PHYADDR; eieio(); ! 282: ! 283: while ((status = mace.ereg->iac)) { ! 284: if ((status & IAC_ADDRCHG) == 0) { ! 285: eieio(); ! 286: break; ! 287: } ! 288: eieio(); ! 289: } ! 290: } ! 291: else { ! 292: /* start to load the address.. */ ! 293: mace.ereg->iac = IAC_PHYADDR; eieio(); ! 294: } ! 295: ! 296: for (i = 0; i < NUM_EN_ADDR_BYTES; i++) { ! 297: mace.ereg->padr = *(ep+i); eieio(); ! 298: } ! 299: return; ! 300: } ! 301: ! 302: /* ! 303: * mace_setup_dbdma ! 304: * ! 305: * Setup various dbdma pointers. ! 306: */ ! 307: ! 308: void ! 309: mace_setup_dbdma() ! 310: { ! 311: mace_t * m = &mace; ! 312: int i; ! 313: dbdma_command_t * d; ! 314: vm_offset_t address; ! 315: dbdma_regmap_t * regmap; ! 316: ! 317: #define ALIGN_MASK 0xfffffffcUL ! 318: if (m->rv_dma_area == 0) { ! 319: m->rv_dma_area = (unsigned char *) ! 320: ((((unsigned long)mace_rx_dma_area) + 3) & ALIGN_MASK); ! 321: m->rv_dma = dbdma_alloc(ETHER_RX_NUM_DBDMA_BUFS + 2); ! 322: m->tx_dma = dbdma_alloc(TX_NUM_DBDMA); ! 323: m->tx_dma_area = (unsigned char *) ! 324: ((((unsigned long)mace_tx_dma_area) + 3) & ALIGN_MASK); ! 325: } ! 326: ! 327: /* set up a ring of buffers */ ! 328: d = m->rv_dma; ! 329: for (i = 0; i < ETHER_RX_NUM_DBDMA_BUFS; i++, d++) { ! 330: address = (vm_offset_t) KVTOPHYS((vm_offset_t)&m->rv_dma_area[i*ETHERNET_BUF_SIZE]); ! 331: DBDMA_BUILD(d, DBDMA_CMD_IN_LAST, 0, ETHERNET_BUF_SIZE, ! 332: address, RECEIVE_INT, ! 333: DBDMA_WAIT_NEVER, ! 334: DBDMA_BRANCH_NEVER); ! 335: } ! 336: ! 337: /* stop when we hit the end of the list */ ! 338: DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, RECEIVE_INT, ! 339: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 340: d++; ! 341: ! 342: /* branch to command at "address" ie. element 0 of the "array" */ ! 343: DBDMA_BUILD(d, DBDMA_CMD_NOP, 0, 0, 0, DBDMA_INT_NEVER, ! 344: DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS); ! 345: address = (vm_offset_t) KVTOPHYS((vm_offset_t)m->rv_dma); ! 346: dbdma_st4_endian(&d->d_cmddep, address); ! 347: ! 348: m->rv_head = 0; ! 349: m->rv_tail = ETHER_RX_NUM_DBDMA_BUFS; /* always contains DBDMA_CMD_STOP */ ! 350: ! 351: /* stop/init/restart dma channel */ ! 352: dbdma_reset(DBDMA_ETHERNET_RV); ! 353: dbdma_reset(DBDMA_ETHERNET_TX); ! 354: ! 355: /* Set the wait value.. */ ! 356: regmap = DBDMA_REGMAP(DBDMA_ETHERNET_RV); ! 357: dbdma_st4_endian(®map->d_wait, DBDMA_SET_CNTRL(0x00)); ! 358: ! 359: /* Set the tx wait value */ ! 360: regmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX); ! 361: dbdma_st4_endian(®map->d_wait, DBDMA_SET_CNTRL(0x20)); ! 362: ! 363: flush_cache_v((vm_offset_t)m->rv_dma, ! 364: sizeof(dbdma_command_t) * (ETHER_RX_NUM_DBDMA_BUFS + 2)); ! 365: /* start receiving */ ! 366: dbdma_start(DBDMA_ETHERNET_RV, m->rv_dma); ! 367: } ! 368: ! 369: #ifdef MACE_DEBUG ! 370: static unsigned char testBuffer[PG_SIZE * 4]; ! 371: static unsigned char testMsg[] = "mace ethernet interface test"; ! 372: ! 373: static void ! 374: send_test_packet() ! 375: { ! 376: unsigned char * tp; ! 377: ! 378: bzero(testBuffer, sizeof(testBuffer)); ! 379: ! 380: tp = testBuffer; ! 381: ! 382: /* send self-addressed packet */ ! 383: bcopy(&mace.macaddr[0], tp, NUM_EN_ADDR_BYTES); ! 384: tp += NUM_EN_ADDR_BYTES; ! 385: bcopy(&mace.macaddr[0], tp, NUM_EN_ADDR_BYTES); ! 386: tp += NUM_EN_ADDR_BYTES; ! 387: *tp++ = 0; ! 388: *tp++ = 0; ! 389: bcopy(testMsg, tp, sizeof(testMsg)); ! 390: polled_send_pkt(testBuffer, 80); ! 391: return; ! 392: } ! 393: #endif ! 394: ! 395: /* ! 396: * Function: init_mace ! 397: * ! 398: * Purpose: ! 399: * Called early on, initializes the adapter and readies it for ! 400: * kdb kernel debugging. ! 401: */ ! 402: void ! 403: init_mace() ! 404: { ! 405: unsigned char status; ! 406: mace_t * m = &mace; ! 407: struct mace_board * ereg; ! 408: int mpc = 0; ! 409: ! 410: /* ! 411: * Only use in-kernel driver for early debugging (bootargs: kdp=1 or kdp=3) ! 412: */ ! 413: if ( (kdp_flag & 1) == 0 ) ! 414: { ! 415: return; ! 416: } ! 417: ! 418: bzero(&mace, sizeof(mace)); ! 419: ! 420: /* get the ethernet registers' mapped address */ ! 421: ereg = m->ereg ! 422: = (struct mace_board *) POWERMAC_IO(PCI_ETHERNET_BASE_PHYS); ! 423: mace_get_hwid((unsigned char *)POWERMAC_IO(PCI_ETHERNET_ADDR_PHYS), m); ! 424: ! 425: /* Reset the board & AMIC.. */ ! 426: mace_reset(); ! 427: ! 428: /* grab the MACE chip rev */ ! 429: m->chip_id = (ereg->chipid2 << 8 | ereg->chipid1); ! 430: ! 431: /* don't auto-strip for 802.3 */ ! 432: m->ereg->rcvfc &= ~(RCVFC_ASTRPRCV); ! 433: ! 434: /* set the ethernet address */ ! 435: mace_seteh(mace.macaddr); ! 436: { ! 437: unsigned char macaddr[NUM_EN_ADDR_BYTES]; ! 438: mace_geteh(macaddr); ! 439: printf("mace ethernet [%02x:%02x:%02x:%02x:%02x:%02x]\n", ! 440: macaddr[0], macaddr[1], macaddr[2], ! 441: macaddr[3], macaddr[4], macaddr[5]); ! 442: } ! 443: ! 444: /* Now clear the Multicast filter */ ! 445: if (m->chip_id != MACE_REVISION_A2) { ! 446: ereg->iac = IAC_ADDRCHG|IAC_LOGADDR; eieio(); ! 447: ! 448: while ((status = ereg->iac)) { ! 449: if ((status & IAC_ADDRCHG) == 0) ! 450: break; ! 451: eieio(); ! 452: } ! 453: eieio(); ! 454: } ! 455: else { ! 456: ereg->iac = IAC_LOGADDR; eieio(); ! 457: } ! 458: { ! 459: int i; ! 460: ! 461: for (i=0; i < 8; i++) ! 462: { ereg->ladrf = 0; ! 463: eieio(); ! 464: } ! 465: } ! 466: ! 467: /* register interrupt routines */ ! 468: mace_setup_dbdma(); ! 469: ! 470: /* Start the chip... */ ! 471: m->ereg->maccc = MACCC_ENXMT|MACCC_ENRCV; eieio(); ! 472: { ! 473: volatile char ch = mace.ereg->ir; eieio(); ! 474: } ! 475: ! 476: delay(500); /* paranoia */ ! 477: mace.ereg->imr = 0xfe; eieio(); ! 478: ! 479: /* register our debugger routines */ ! 480: kdp_register_send_receive((kdp_send_t)polled_send_pkt, ! 481: (kdp_receive_t)polled_receive_pkt); ! 482: ! 483: #if 0 ! 484: printf("Testing 1 2 3\n"); ! 485: send_test_packet(); ! 486: printf("Testing 1 2 3\n"); ! 487: send_test_packet(); ! 488: printf("Testing 1 2 3\n"); ! 489: send_test_packet(); ! 490: do { ! 491: static unsigned char buf[ETHERNET_BUF_SIZE]; ! 492: int len; ! 493: int nmpc = mace.ereg->mpc; eieio(); ! 494: ! 495: if (nmpc > mpc) { ! 496: mpc = nmpc; ! 497: printf("mpc %d\n", mpc); ! 498: } ! 499: polled_receive_pkt(buf, &len, 100); ! 500: if (len > 0) { ! 501: printf("rx %d\n", len); ! 502: printContiguousEtherPacket(buf, len); ! 503: } ! 504: } while(1); ! 505: #endif ! 506: ! 507: return; ! 508: } ! 509: ! 510: #ifdef MACE_DEBUG ! 511: static void ! 512: txstatus(char * msg) ! 513: { ! 514: volatile dbdma_regmap_t * dmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX); ! 515: volatile unsigned long status; ! 516: volatile unsigned long intr; ! 517: volatile unsigned long branch; ! 518: volatile unsigned long wait; ! 519: ! 520: status = dbdma_ld4_endian(&dmap->d_status); eieio(); ! 521: intr = dbdma_ld4_endian(&dmap->d_intselect); eieio(); ! 522: branch = dbdma_ld4_endian(&dmap->d_branch); eieio(); ! 523: wait = dbdma_ld4_endian(&dmap->d_wait); eieio(); ! 524: printf("(%s s=0x%x i=0x%x b=0x%x w=0x%x)", msg, status, intr, branch, ! 525: wait); ! 526: return; ! 527: } ! 528: #endif ! 529: ! 530: static void ! 531: tx_dbdma(char * data, int len) ! 532: { ! 533: unsigned long count; ! 534: dbdma_command_t * d; ! 535: unsigned long page; ! 536: ! 537: d = mace.tx_dma; ! 538: page = ((unsigned long) data) & PG_MASK; ! 539: if ((page + len) <= PG_SIZE) { /* one piece dma */ ! 540: DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0, ! 541: len, ! 542: (vm_offset_t) KVTOPHYS((vm_offset_t) data), ! 543: DBDMA_INT_NEVER, ! 544: DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER); ! 545: } ! 546: else { /* two piece dma */ ! 547: count = PG_SIZE - page; ! 548: DBDMA_BUILD(d, DBDMA_CMD_OUT_MORE, DBDMA_KEY_STREAM0, ! 549: count, ! 550: (vm_offset_t)KVTOPHYS((vm_offset_t) data), ! 551: DBDMA_INT_NEVER, ! 552: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 553: d++; ! 554: DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0, ! 555: len - count, (vm_offset_t) ! 556: KVTOPHYS((vm_offset_t)((unsigned char *)data + count)), ! 557: DBDMA_INT_NEVER, ! 558: DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER); ! 559: } ! 560: d++; ! 561: DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM, ! 562: 1, KVTOPHYS((vm_offset_t) &mace.ereg->xmtfs),DBDMA_INT_NEVER, ! 563: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 564: d++; ! 565: DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM, ! 566: 1, KVTOPHYS((vm_offset_t) &mace.ereg->ir), DBDMA_INT_ALWAYS, ! 567: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 568: d++; ! 569: DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, 0, 0, 0); ! 570: flush_cache_v((vm_offset_t)mace.tx_dma, sizeof(dbdma_command_t) * TX_NUM_DBDMA); ! 571: dbdma_start(DBDMA_ETHERNET_TX, mace.tx_dma); ! 572: return; ! 573: ! 574: } ! 575: ! 576: static void ! 577: waitForDBDMADone(char * msg) ! 578: { ! 579: { ! 580: /* wait for tx dma completion */ ! 581: volatile dbdma_regmap_t * dmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX); ! 582: int i; ! 583: volatile unsigned long val; ! 584: ! 585: i = 0; ! 586: do { ! 587: val = dbdma_ld4_endian(&dmap->d_status); eieio(); ! 588: delay(50); ! 589: i++; ! 590: } while ((i < 100000) && (val & DBDMA_CNTRL_ACTIVE)); ! 591: if (i == 100000) ! 592: printf("mace(%s): tx_dbdma poll timed out 0x%x", msg, val); ! 593: } ! 594: } ! 595: ! 596: void ! 597: mace_service_queue(struct ifnet * ifp) ! 598: { ! 599: unsigned char * buf_p; ! 600: struct mbuf * m; ! 601: struct mbuf * mp; ! 602: int len; ! 603: ! 604: if (mace.tx_busy) { /* transmit in progress? */ ! 605: return; ! 606: } ! 607: ! 608: IF_DEQUEUE(&(ifp->if_snd), m); ! 609: if (m == 0) { ! 610: return; ! 611: } ! 612: ! 613: len = m->m_pkthdr.len; ! 614: ! 615: if (len > ETHERMAXPACKET) { ! 616: printf("mace_start: packet too big (%d), dropping\n", len); ! 617: m_freem(m); ! 618: return; ! 619: ! 620: } ! 621: buf_p = mace.tx_dma_area; ! 622: if (m->m_nextpkt) { ! 623: printf("mace: sending more than one mbuf\n"); ! 624: } ! 625: for (mp = m; mp; mp = mp->m_next) { ! 626: if (mp->m_len == 0) ! 627: continue; ! 628: bcopy(mtod(mp, caddr_t), buf_p, min(mp->m_len, len)); ! 629: len -= mp->m_len; ! 630: buf_p += mp->m_len; ! 631: } ! 632: m_freem(m); ! 633: ! 634: #if NBPFILTER > 0 ! 635: if (ifp->if_bpf) ! 636: BPF_TAP(ifp->if_bpf, mace.tx_dma_area, m->m_pkthdr.len); ! 637: #endif ! 638: ! 639: #if 0 ! 640: printf("tx packet %d\n", m->m_pkthdr.len); ! 641: printContiguousEtherPacket(mace.tx_dma_area, m->m_pkthdr.len); ! 642: #endif ! 643: ! 644: /* fill in the dbdma records and kick off the dma */ ! 645: tx_dbdma(mace.tx_dma_area, m->m_pkthdr.len); ! 646: mace.tx_busy = 1; ! 647: return; ! 648: } ! 649: ! 650: #ifdef MACE_DEBUG ! 651: static int ! 652: mace_watchdog() ! 653: { ! 654: struct ifnet * ifp = &mace.en_arpcom.ac_if; ! 655: int s; ! 656: ! 657: mace.txwatchdog++; ! 658: s = splnet(); ! 659: if (mace.rxintr == 0) { ! 660: printf("rx is hung up\n"); ! 661: rx_intr(); ! 662: } ! 663: mace.rxintr = 0; ! 664: #if 0 ! 665: if (mace.txintr == 0 && ifp->if_snd.ifq_head) { ! 666: if (mace.tx_busy) ! 667: dbdma_stop(DBDMA_ETHERNET_TX); ! 668: mace.tx_busy = 0; ! 669: mace_service_queue(ifp); ! 670: } ! 671: mace.txintr = 0; ! 672: #endif ! 673: timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */ ! 674: return (0); ! 675: } ! 676: #endif /* MACE_DEBUG */ ! 677: ! 678: static int ! 679: mace_start(struct ifnet * ifp) ! 680: { ! 681: // int i = mace.tx_busy; ! 682: ! 683: // printf("mace_start %s\n", mace.tx_busy ? "(txBusy)" : ""); ! 684: mace_service_queue(ifp); ! 685: ! 686: // if (mace.tx_busy && !i) ! 687: // printf("(txStarted)\n"); ! 688: return 0; ! 689: } ! 690: ! 691: int ! 692: mace_recv_pkt(funcptr pktfunc, void * p) ! 693: { ! 694: vm_offset_t address; ! 695: struct mace_board * board; ! 696: long bytes; ! 697: int done = 0; ! 698: int doContinue = 0; ! 699: mace_t * m; ! 700: unsigned long resid; ! 701: unsigned short status; ! 702: int tail; ! 703: ! 704: m = &mace; ! 705: board = m->ereg; ! 706: ! 707: /* remember where the tail was */ ! 708: tail = m->rv_tail; ! 709: for (done = 0; (done == 0) && (m->rv_head != tail);) { ! 710: dbdma_command_t * dmaHead; ! 711: ! 712: dmaHead = &m->rv_dma[m->rv_head]; ! 713: resid = dbdma_ld4_endian(&dmaHead->d_status_resid); ! 714: status = (resid >> 16); ! 715: bytes = resid & 0xffff; ! 716: bytes = ETHERNET_BUF_SIZE - bytes - 8; /* strip off FCS/CRC */ ! 717: ! 718: if ((status & DBDMA_ETHERNET_EOP) == 0) { ! 719: /* no packets are ready yet */ ! 720: break; ! 721: } ! 722: doContinue = 1; ! 723: /* if the packet is good, pass it up */ ! 724: if (bytes >= (ETHER_MIN_PACKET - 4)) { ! 725: char * dmaPacket; ! 726: dmaPacket = &m->rv_dma_area[m->rv_head * ETHERNET_BUF_SIZE]; ! 727: done = (*pktfunc)(dmaPacket, bytes, p); ! 728: } ! 729: /* mark the head as the new tail in the dma channel command list */ ! 730: DBDMA_BUILD(dmaHead, DBDMA_CMD_STOP, 0, 0, 0, RECEIVE_INT, ! 731: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 732: flush_cache_v((vm_offset_t)dmaHead, sizeof(*dmaHead)); ! 733: eieio(); ! 734: ! 735: /* make the tail an available dma'able entry */ ! 736: { ! 737: dbdma_command_t * dmaTail; ! 738: dmaTail = &m->rv_dma[m->rv_tail]; ! 739: address = KVTOPHYS((vm_offset_t) ! 740: &m->rv_dma_area[m->rv_tail*ETHERNET_BUF_SIZE]); ! 741: // this command is live so write it carefully ! 742: DBDMA_ST4_ENDIAN(&dmaTail->d_address, address); ! 743: dmaTail->d_status_resid = 0; ! 744: dmaTail->d_cmddep = 0; ! 745: eieio(); ! 746: DBDMA_ST4_ENDIAN(&dmaTail->d_cmd_count, ! 747: ((DBDMA_CMD_IN_LAST) << 28) | ((0) << 24) | ! 748: ((RECEIVE_INT) << 20) | ! 749: ((DBDMA_BRANCH_NEVER) << 18) | ((DBDMA_WAIT_NEVER) << 16) | ! 750: (ETHERNET_BUF_SIZE)); ! 751: eieio(); ! 752: flush_cache_v((vm_offset_t)dmaTail, sizeof(*dmaTail)); ! 753: } ! 754: /* head becomes the tail */ ! 755: m->rv_tail = m->rv_head; ! 756: ! 757: /* advance the head */ ! 758: m->rv_head++; ! 759: if (m->rv_head == (ETHER_RX_NUM_DBDMA_BUFS + 1)) ! 760: m->rv_head = 0; ! 761: } ! 762: if (doContinue) { ! 763: sync(); ! 764: dbdma_continue(DBDMA_ETHERNET_RV); ! 765: } ! 766: return (done); ! 767: } ! 768: ! 769: /* kdb handle buffer routines */ ! 770: struct kdbCopy { ! 771: int * len; ! 772: char * data; ! 773: }; ! 774: ! 775: static int ! 776: kdb_copy(char * pktBuf, int len, void * p) ! 777: { ! 778: struct kdbCopy * cp = (struct kdbCopy *)p; ! 779: ! 780: bcopy(pktBuf, cp->data, len); ! 781: *cp->len = len; ! 782: return (1); /* signal that we're done */ ! 783: } ! 784: ! 785: /* kdb debugger routines */ ! 786: static void ! 787: polled_send_pkt(char * data, int len) ! 788: { ! 789: waitForDBDMADone("mace: polled_send_pkt start"); ! 790: tx_dbdma(data, len); ! 791: waitForDBDMADone("mace: polled_send_pkt end"); ! 792: return; ! 793: } ! 794: ! 795: static void ! 796: polled_receive_pkt(char *data, int *len, int timeout_ms) ! 797: { ! 798: struct kdbCopy cp; ! 799: ! 800: cp.len = len; ! 801: cp.data = data; ! 802: ! 803: timeout_ms *= 1000; ! 804: *len = 0; ! 805: while (mace_recv_pkt(kdb_copy, (void *)&cp) == 0) { ! 806: if (timeout_ms <= 0) ! 807: break; ! 808: delay(50); ! 809: timeout_ms -= 50; ! 810: } ! 811: return; ! 812: } ! 813: ! 814: /* Bump to force ethernet data to be 4-byte aligned ! 815: * (since the ethernet header is 14 bytes, and the 802.3 header is ! 816: * 22 = 14+8 bytes). This assumes that m_data is word-aligned ! 817: * (which it is). ! 818: */ ! 819: #define ETHER_DATA_ALIGN 2 ! 820: ! 821: /* ! 822: * Function: rxpkt ! 823: * ! 824: * Purpose: ! 825: * Called from within mace_recv_pkt to deal with a packet of data. ! 826: * rxpkt() allocates an mbuf(+cluser) and passes it up to the stacks. ! 827: * Returns: ! 828: * 0 if the packet was copied to an mbuf, 1 otherwise ! 829: */ ! 830: static int ! 831: rxpkt(char * data, int len, void * p) ! 832: { ! 833: struct ether_header * eh_p = (struct ether_header *)data; ! 834: struct ifnet * ifp = &mace.en_arpcom.ac_if; ! 835: struct mbuf * m; ! 836: ! 837: int interesting; ! 838: ! 839: mace.rxintr++; ! 840: ! 841: /* mcast, bcast -- we're interested in either */ ! 842: interesting = eh_p->ether_dhost[0] & 1; ! 843: ! 844: #if NBPFILTER > 0 ! 845: /* ! 846: * Check if there's a bpf filter listening on this interface. ! 847: * If so, hand off the raw packet to bpf_tap(). ! 848: */ ! 849: if (ifp->if_bpf) { ! 850: BPF_TAP(ifp->if_bpf, data, len); ! 851: ! 852: /* ! 853: * Keep the packet if it's a broadcast or has our ! 854: * physical ethernet address (or if we support ! 855: * multicast and it's one). ! 856: */ ! 857: if ((interesting == 0) && bcmp(eh_p->ether_dhost, mace.macaddr, ! 858: sizeof(eh_p->ether_dhost)) != 0) { ! 859: return (1); ! 860: } ! 861: } ! 862: #endif ! 863: ! 864: /* ! 865: * We "know" a full-sized packet fits in one cluster. Set up the ! 866: * packet header, and if the length is sufficient, attempt to allocate ! 867: * a cluster. If that fails, fall back to the old way (m_devget()). ! 868: * Here, we take the simple approach of cluster vs. single mbuf. ! 869: */ ! 870: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 871: if (m == 0) { ! 872: #ifdef MACE_DEBUG ! 873: printf("mget failed\n"); ! 874: #endif ! 875: return (1); ! 876: } ! 877: ! 878: if (len > (MHLEN - ETHER_DATA_ALIGN)) ! 879: { MCLGET(m, M_DONTWAIT); ! 880: if (m->m_flags&M_EXT) /* MCLGET succeeded */ ! 881: { m->m_data += ETHER_DATA_ALIGN; ! 882: bcopy(data, mtod(m, caddr_t), (unsigned)len); ! 883: } else ! 884: { ! 885: #ifdef MACE_DEBUG ! 886: printf("no clusters\n"); ! 887: #endif ! 888: m_free(m); ! 889: m = (struct mbuf *)m_devget(data, len, 0, ifp, 0); ! 890: if (m == 0) ! 891: return (1); ! 892: } ! 893: } else ! 894: { m->m_data += ETHER_DATA_ALIGN; ! 895: bcopy(data, mtod(m, caddr_t), (unsigned)len); ! 896: } ! 897: ! 898: /* ! 899: * Current code up the line assumes that the media header's been ! 900: * stripped, but we'd like to preserve it, just in case someone ! 901: * wants to peek. ! 902: */ ! 903: m->m_pkthdr.len = len; ! 904: m->m_len = len; ! 905: m->m_pkthdr.rcvif = ifp; ! 906: m->m_data += sizeof(*eh_p); ! 907: m->m_len -= sizeof (*eh_p); ! 908: m->m_pkthdr.len -= sizeof(*eh_p); ! 909: ether_input(ifp, eh_p, m); ! 910: ! 911: return (0); ! 912: } ! 913: ! 914: ! 915: static void ! 916: rx_intr() ! 917: { ! 918: mace_recv_pkt(rxpkt, 0); ! 919: } ! 920: ! 921: void ! 922: mace_dbdma_rx_intr(int unit, void *ignored, void * arp) ! 923: { ! 924: if (!mace.ready) ! 925: return; ! 926: ! 927: thread_call_func((thread_call_func_t)rx_intr, 0, TRUE); ! 928: } ! 929: ! 930: ! 931: int ! 932: mace_ioctl(struct ifnet * ifp,u_long cmd, caddr_t data) ! 933: { ! 934: struct arpcom * ar; ! 935: unsigned error = 0; ! 936: struct ifaddr * ifa = (struct ifaddr *)data; ! 937: struct ifreq * ifr = (struct ifreq *)data; ! 938: struct sockaddr_in * sin; ! 939: ! 940: sin = (struct sockaddr_in *)(&((struct ifreq *)data)->ifr_addr); ! 941: ar = (struct arpcom *)ifp; ! 942: ! 943: switch (cmd) { ! 944: case SIOCAUTOADDR: ! 945: error = in_bootp(ifp, sin, &mace.en_arpcom.ac_enaddr); ! 946: break; ! 947: ! 948: case SIOCSIFADDR: ! 949: #if NeXT ! 950: ifp->if_flags |= (IFF_UP | IFF_RUNNING); ! 951: #else ! 952: ifp->if_flags |= IFF_UP; ! 953: #endif ! 954: switch (ifa->ifa_addr->sa_family) { ! 955: case AF_INET: ! 956: /* ! 957: * See if another station has *our* IP address. ! 958: * i.e.: There is an address conflict! If a ! 959: * conflict exists, a message is sent to the ! 960: * console. ! 961: */ ! 962: if (IA_SIN(ifa)->sin_addr.s_addr != 0) { /* don't bother for 0.0.0.0 */ ! 963: ar->ac_ipaddr = IA_SIN(ifa)->sin_addr; ! 964: arpwhohas(ar, &IA_SIN(ifa)->sin_addr); ! 965: } ! 966: break; ! 967: default: ! 968: break; ! 969: } ! 970: break; ! 971: ! 972: case SIOCSIFFLAGS: ! 973: /* ! 974: * If interface is marked down and it is running, then stop it ! 975: */ ! 976: if ((ifp->if_flags & IFF_UP) == 0 && ! 977: (ifp->if_flags & IFF_RUNNING) != 0) { ! 978: /* ! 979: * If interface is marked down and it is running, then ! 980: * stop it. ! 981: */ ! 982: ifp->if_flags &= ~IFF_RUNNING; ! 983: } else if ((ifp->if_flags & IFF_UP) != 0 && ! 984: (ifp->if_flags & IFF_RUNNING) == 0) { ! 985: /* ! 986: * If interface is marked up and it is stopped, then ! 987: * start it. ! 988: */ ! 989: ifp->if_flags |= IFF_RUNNING; ! 990: } ! 991: ! 992: /* ! 993: * If the state of the promiscuous bit changes, the ! 994: * interface must be reset to effect the change. ! 995: */ ! 996: if (((ifp->if_flags ^ mace.promisc) & IFF_PROMISC) && ! 997: (ifp->if_flags & IFF_RUNNING)) { ! 998: mace.promisc = ifp->if_flags & IFF_PROMISC; ! 999: mace_sync_promisc(ifp); ! 1000: } ! 1001: ! 1002: break; ! 1003: ! 1004: case SIOCADDMULTI: ! 1005: if ((error = ether_addmulti(ifr, ar)) == ENETRESET) ! 1006: { if ((error = mace_addmulti(ifr, ar)) != 0) ! 1007: { error = 0; ! 1008: mace_sync_mcast(ifp); ! 1009: } ! 1010: } ! 1011: break; ! 1012: ! 1013: case SIOCDELMULTI: ! 1014: { ! 1015: struct ether_addr enaddr[2]; /* [0] - addrlo, [1] - addrhi */ ! 1016: ! 1017: if ((error = ether_delmulti(ifr, ar, enaddr)) == ENETRESET) { ! 1018: if ((error = mace_delmulti(ifr, ar, enaddr)) != 0) { ! 1019: error = 0; ! 1020: mace_sync_mcast(ifp); ! 1021: } ! 1022: } ! 1023: } ! 1024: break; ! 1025: ! 1026: default: ! 1027: error = EINVAL; ! 1028: break; ! 1029: } ! 1030: return (error); ! 1031: } ! 1032: ! 1033: void ! 1034: mace_init() ! 1035: { ! 1036: struct ifnet * ifp = &mace.en_arpcom.ac_if; ! 1037: ! 1038: /* ! 1039: * Only use in-kernel driver for early debugging (bootargs: kdp=1|3) ! 1040: */ ! 1041: if ( (kdp_flag & 1) == 0 ) ! 1042: { ! 1043: return; ! 1044: } ! 1045: ! 1046: mace.tx_busy = 0; ! 1047: mace.txintr = 0; ! 1048: mace.promisc = 0; ! 1049: ! 1050: bzero((caddr_t)ifp, sizeof(struct ifnet)); ! 1051: bcopy(&mace.macaddr, &mace.en_arpcom.ac_enaddr, NUM_EN_ADDR_BYTES); ! 1052: ! 1053: ifp->if_name = "en"; ! 1054: ifp->if_unit = 0; ! 1055: ifp->if_private = 0; ! 1056: ifp->if_ioctl = mace_ioctl; ! 1057: ifp->if_start = mace_start; ! 1058: ifp->if_flags = ! 1059: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; ! 1060: #if NBPFILTER > 0 ! 1061: bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); ! 1062: #endif ! 1063: if_attach(ifp); ! 1064: ether_ifattach(ifp); ! 1065: ! 1066: mace.rxintr = 0; ! 1067: ! 1068: /* wire in the interrupt routines */ ! 1069: pmac_register_int(PMAC_DMA_ETHERNET_RX, SPLNET, ! 1070: mace_dbdma_rx_intr, 0); ! 1071: pmac_register_int(PMAC_DMA_ETHERNET_TX, SPLNET, ! 1072: mace_dbdma_tx_intr, 0); ! 1073: ! 1074: // pmac_register_int(PMAC_DEV_ETHERNET, SPLNET, mace_pci_intr); ! 1075: mace.ready = 1; ! 1076: #ifdef MACE_DEBUG ! 1077: timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */ ! 1078: #endif ! 1079: return; ! 1080: } ! 1081: ! 1082: /* ! 1083: * mace_pci_intr ! 1084: * ! 1085: * Service MACE interrupt ! 1086: */ ! 1087: ! 1088: void ! 1089: mace_pci_intr(int device, void *ssp) ! 1090: { ! 1091: unsigned char ir, retry, frame, packet, length; ! 1092: ! 1093: ir = mace.ereg->ir; eieio(); /* Clear Interrupt */ ! 1094: packet = mace.ereg->mpc; eieio(); ! 1095: length = mace.ereg->rntpc; eieio(); ! 1096: ! 1097: printf("(txI)"); ! 1098: ! 1099: if (ir & IR_XMTINT) { ! 1100: retry = mace.ereg->xmtrc; eieio(); /* Grab transmit retry count */ ! 1101: frame = mace.ereg->xmtfs; eieio(); ! 1102: // if (mace.ready) ! 1103: // mace_dbdma_tx_intr(device, ssp); ! 1104: } ! 1105: return; ! 1106: } ! 1107: ! 1108: static void ! 1109: tx_intr() ! 1110: { ! 1111: mace.txintr++; ! 1112: mace.tx_busy = 0; ! 1113: mace_service_queue(&mace.en_arpcom.ac_if); ! 1114: } ! 1115: ! 1116: /* ! 1117: * mace_dbdma_tx_intr ! 1118: * ! 1119: * DBDMA interrupt routine ! 1120: */ ! 1121: void ! 1122: mace_dbdma_tx_intr(int unit, void *ignored, void * arg) ! 1123: { ! 1124: if (!mace.ready) ! 1125: return; ! 1126: ! 1127: thread_call_func((thread_call_func_t)tx_intr, 0, TRUE); ! 1128: return; ! 1129: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.