|
|
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: #include <mach/boolean.h> ! 64: #include <mach/exception_types.h> ! 65: #include <mach/mach_types.h> ! 66: ! 67: #include <ppc/proc_reg.h> ! 68: #include <ppc/pmap.h> ! 69: #include <pexpert/ppc/powermac.h> ! 70: #include <pexpert/ppc/dbdma.h> ! 71: #include <kdp/kdp_en_debugger.h> ! 72: #include <kdp/kdp_udp.h> ! 73: ! 74: #include "kdp_mace.h" ! 75: ! 76: struct kdp_mace_copy_desc { ! 77: int * len; ! 78: char * data; ! 79: }; ! 80: static mace_t mace; ! 81: ! 82: #define MACE_DMA_AREA_SIZE \ ! 83: (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE) ! 84: static unsigned long ! 85: mace_rx_dma_area[(MACE_DMA_AREA_SIZE + ! 86: sizeof(long))/sizeof(long)]; ! 87: static unsigned long ! 88: mace_tx_dma_area[(ETHERNET_BUF_SIZE + PG_SIZE + ! 89: sizeof(long))/sizeof(long)]; ! 90: ! 91: #ifdef MACE_DEBUG ! 92: static unsigned char testBuffer[PG_SIZE * 4]; ! 93: static unsigned char testMsg[] = "mace ethernet interface test"; ! 94: #endif ! 95: ! 96: static void polled_send_pkt(char * data, int len); ! 97: static void polled_receive_pkt(char *data, int *len, int timeout_ms); ! 98: ! 99: void kdp_mace_reset(mace_t *); ! 100: void kdp_mace_geteh(unsigned char *); ! 101: void kdp_mace_setup_dbdma(void); ! 102: boolean_t kdp_mace_init(void * baseAddresses[3], unsigned char * netAddr); ! 103: #ifdef MACE_DEBUG ! 104: static void printContiguousEtherPacket(u_char *, int); ! 105: static void send_test_packet(void); ! 106: #endif ! 107: ! 108: typedef int (*funcptr)(char *, int, void *); ! 109: int kdp_mace_recv_pkt(funcptr , void *); ! 110: ! 111: #ifdef MACE_DEBUG ! 112: static int ! 113: macAddrsEqual(unsigned char * one, unsigned char * two) ! 114: { ! 115: int i; ! 116: ! 117: for (i = 0; i < NUM_EN_ADDR_BYTES; i++) ! 118: if (*one++ != *two++) ! 119: return 0; ! 120: return 1; ! 121: } ! 122: ! 123: static __inline__ int ! 124: isprint(unsigned char c) ! 125: { ! 126: return (c >= 0x20 && c <= 0x7e); ! 127: } ! 128: ! 129: static void ! 130: printEtherHeader(enet_addr_t * dh, enet_addr_t * sh, u_short etype) ! 131: { ! 132: u_char * dhost = dh->ether_addr_octet; ! 133: u_char * shost = sh->ether_addr_octet; ! 134: ! 135: printf("Dst: %x:%x:%x:%x:%x:%x Src: %x:%x:%x:%x:%x:%x Type: 0x%x\n", ! 136: dhost[0], dhost[1], dhost[2], dhost[3], dhost[4], dhost[5], ! 137: shost[0], shost[1], shost[2], shost[3], shost[4], shost[5], ! 138: etype); ! 139: } ! 140: ! 141: static void ! 142: printData(u_char * data_p, int n_bytes) ! 143: { ! 144: #define CHARS_PER_LINE 16 ! 145: char line_buf[CHARS_PER_LINE + 1]; ! 146: int line_pos; ! 147: int offset; ! 148: ! 149: for (line_pos = 0, offset = 0; offset < n_bytes; offset++, data_p++) { ! 150: if (line_pos == 0) { ! 151: printf("%04d ", offset); ! 152: } ! 153: ! 154: line_buf[line_pos] = isprint(*data_p) ? *data_p : '.'; ! 155: printf(" %02x", *data_p); ! 156: line_pos++; ! 157: if (line_pos == CHARS_PER_LINE) { ! 158: line_buf[CHARS_PER_LINE] = '\0'; ! 159: printf(" %s\n", line_buf); ! 160: line_pos = 0; ! 161: } ! 162: } ! 163: if (line_pos) { /* need to finish up the line */ ! 164: for (; line_pos < CHARS_PER_LINE; line_pos++) { ! 165: printf(" "); ! 166: line_buf[line_pos] = ' '; ! 167: } ! 168: line_buf[CHARS_PER_LINE] = '\0'; ! 169: printf(" %s\n", line_buf); ! 170: } ! 171: } ! 172: ! 173: static void ! 174: printEtherPacket(enet_addr_t * dhost, enet_addr_t * shost, u_short type, ! 175: u_char * data_p, int n_bytes) ! 176: { ! 177: printEtherHeader(dhost, shost, type); ! 178: printData(data_p, n_bytes); ! 179: } ! 180: ! 181: static void ! 182: printContiguousEtherPacket(u_char * data_p, int n_bytes) ! 183: { ! 184: printEtherPacket((enet_addr_t *)data_p, ! 185: (enet_addr_t *)(data_p + NUM_EN_ADDR_BYTES), ! 186: *((u_short *)(data_p + (NUM_EN_ADDR_BYTES * 2))), ! 187: data_p, n_bytes); ! 188: } ! 189: #endif ! 190: ! 191: ! 192: /* ! 193: * kdp_mace_reset ! 194: * ! 195: * Reset the board.. ! 196: */ ! 197: void ! 198: kdp_mace_reset(mace_t * m) ! 199: { ! 200: dbdma_reset(m->rv_dbdma); ! 201: dbdma_reset(m->tx_dbdma); ! 202: } ! 203: ! 204: ! 205: /* ! 206: * kdp_mace_geteh: ! 207: * ! 208: * This function gets the ethernet address (array of 6 unsigned ! 209: * bytes) from the MACE board registers. ! 210: * ! 211: */ ! 212: void ! 213: kdp_mace_geteh(unsigned char *ep) ! 214: { ! 215: int i; ! 216: unsigned char ep_temp; ! 217: ! 218: mace.ereg->iac = IAC_PHYADDR; eieio(); ! 219: ! 220: for (i = 0; i < ETHER_ADD_SIZE; i++) { ! 221: ep_temp = mace.ereg->padr; eieio(); ! 222: *ep++ = ep_temp; ! 223: } ! 224: } ! 225: ! 226: /* ! 227: * mace_seteh: ! 228: * ! 229: * This function sets the ethernet address (array of 6 unsigned ! 230: * bytes) on the MACE board. ! 231: */ ! 232: static void ! 233: mace_seteh(unsigned char *ep) ! 234: { ! 235: int i; ! 236: unsigned char status; ! 237: ! 238: if (mace.chip_id != MACE_REVISION_A2) { ! 239: mace.ereg->iac = IAC_ADDRCHG|IAC_PHYADDR; eieio(); ! 240: ! 241: while ((status = mace.ereg->iac)) { ! 242: if ((status & IAC_ADDRCHG) == 0) { ! 243: eieio(); ! 244: break; ! 245: } ! 246: eieio(); ! 247: } ! 248: } ! 249: else { ! 250: /* start to load the address.. */ ! 251: mace.ereg->iac = IAC_PHYADDR; eieio(); ! 252: } ! 253: ! 254: for (i = 0; i < NUM_EN_ADDR_BYTES; i++) { ! 255: mace.ereg->padr = *(ep+i); eieio(); ! 256: } ! 257: return; ! 258: } ! 259: ! 260: /* ! 261: * kdp_mace_setup_dbdma ! 262: * ! 263: * Setup various dbdma pointers. ! 264: */ ! 265: void ! 266: kdp_mace_setup_dbdma() ! 267: { ! 268: mace_t * m = &mace; ! 269: int i; ! 270: dbdma_command_t * d; ! 271: vm_offset_t address; ! 272: dbdma_regmap_t * regmap; ! 273: ! 274: #define ALIGN_MASK 0xfffffffcUL ! 275: if (m->rv_dma_area == 0) { ! 276: m->rv_dma_area = (unsigned char *) ! 277: ((((unsigned long)mace_rx_dma_area) + 3) & ALIGN_MASK); ! 278: m->rv_dma = dbdma_alloc(ETHER_RX_NUM_DBDMA_BUFS + 2); ! 279: m->tx_dma = dbdma_alloc(TX_NUM_DBDMA); ! 280: m->tx_dma_area = (unsigned char *) ! 281: ((((unsigned long)mace_tx_dma_area) + 3) & ALIGN_MASK); ! 282: } ! 283: ! 284: /* set up a ring of buffers */ ! 285: d = m->rv_dma; ! 286: for (i = 0; i < ETHER_RX_NUM_DBDMA_BUFS; i++, d++) { ! 287: address = (vm_offset_t) kvtophys((vm_offset_t)&m->rv_dma_area[i*ETHERNET_BUF_SIZE]); ! 288: DBDMA_BUILD(d, DBDMA_CMD_IN_LAST, 0, ETHERNET_BUF_SIZE, ! 289: address, DBDMA_INT_ALWAYS, ! 290: DBDMA_WAIT_NEVER, ! 291: DBDMA_BRANCH_NEVER); ! 292: } ! 293: ! 294: /* stop when we hit the end of the list */ ! 295: DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, DBDMA_INT_ALWAYS, ! 296: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 297: d++; ! 298: ! 299: /* branch to command at "address" ie. element 0 of the "array" */ ! 300: DBDMA_BUILD(d, DBDMA_CMD_NOP, 0, 0, 0, DBDMA_INT_NEVER, ! 301: DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS); ! 302: address = (vm_offset_t) kvtophys((vm_offset_t)m->rv_dma); ! 303: dbdma_st4_endian(&d->d_cmddep, address); ! 304: ! 305: m->rv_head = 0; ! 306: m->rv_tail = ETHER_RX_NUM_DBDMA_BUFS; /* always contains DBDMA_CMD_STOP */ ! 307: regmap = m->rv_dbdma; ! 308: ! 309: /* stop/init/restart dma channel */ ! 310: dbdma_reset(regmap); ! 311: dbdma_reset(m->tx_dbdma); ! 312: ! 313: /* Set the wait value.. */ ! 314: dbdma_st4_endian(®map->d_wait, DBDMA_SET_CNTRL(0x00)); ! 315: ! 316: /* Set the tx wait value */ ! 317: regmap = m->tx_dbdma; ! 318: dbdma_st4_endian(®map->d_wait, DBDMA_SET_CNTRL(0x20)); ! 319: ! 320: flush_dcache((vm_offset_t)m->rv_dma, ! 321: sizeof(dbdma_command_t) * (ETHER_RX_NUM_DBDMA_BUFS + 2), ! 322: FALSE); ! 323: /* start receiving */ ! 324: dbdma_start(m->rv_dbdma, m->rv_dma); ! 325: } ! 326: ! 327: #ifdef MACE_DEBUG ! 328: static void ! 329: send_test_packet() ! 330: { ! 331: unsigned char * tp; ! 332: ! 333: bzero((char *)testBuffer, sizeof(testBuffer)); ! 334: ! 335: tp = testBuffer; ! 336: ! 337: /* send self-addressed packet */ ! 338: bcopy((char *)&mace.macaddr[0], (char *)tp, NUM_EN_ADDR_BYTES); ! 339: tp += NUM_EN_ADDR_BYTES; ! 340: bcopy((char *)&mace.macaddr[0], (char *)tp, NUM_EN_ADDR_BYTES); ! 341: tp += NUM_EN_ADDR_BYTES; ! 342: *tp++ = 0; ! 343: *tp++ = 0; ! 344: bcopy((char *)testMsg, (char *)tp, sizeof(testMsg)); ! 345: polled_send_pkt((char *)testBuffer, 80); ! 346: return; ! 347: } ! 348: #endif ! 349: ! 350: /* ! 351: * Function: kdp_mace_init ! 352: * ! 353: * Purpose: ! 354: * Called early on, initializes the adapter and readies it for ! 355: * kdb kernel debugging. ! 356: */ ! 357: boolean_t ! 358: kdp_mace_init(void * baseAddresses[3], unsigned char * netAddr) ! 359: { ! 360: unsigned char status; ! 361: mace_t * m = &mace; ! 362: struct mace_board * ereg; ! 363: int mpc = 0; ! 364: int i; ! 365: ! 366: bzero((char *)&mace, sizeof(mace)); ! 367: ! 368: /* get the ethernet registers' mapped address */ ! 369: ereg = m->ereg ! 370: = (struct mace_board *) baseAddresses[0]; ! 371: m->tx_dbdma = (dbdma_regmap_t *) baseAddresses[1]; ! 372: m->rv_dbdma = (dbdma_regmap_t *) baseAddresses[2]; ! 373: ! 374: for (i = 0; i < NUM_EN_ADDR_BYTES; i++) ! 375: m->macaddr[i] = netAddr[i]; ! 376: ! 377: /* Reset the board & AMIC.. */ ! 378: kdp_mace_reset(m); ! 379: ! 380: /* grab the MACE chip rev */ ! 381: m->chip_id = (ereg->chipid2 << 8 | ereg->chipid1); ! 382: ! 383: /* don't auto-strip for 802.3 */ ! 384: m->ereg->rcvfc &= ~(RCVFC_ASTRPRCV); ! 385: ! 386: /* set the ethernet address */ ! 387: mace_seteh(mace.macaddr); ! 388: { ! 389: unsigned char macaddr[NUM_EN_ADDR_BYTES]; ! 390: kdp_mace_geteh(macaddr); ! 391: printf("mace ethernet [%02x:%02x:%02x:%02x:%02x:%02x]\n", ! 392: macaddr[0], macaddr[1], macaddr[2], ! 393: macaddr[3], macaddr[4], macaddr[5]); ! 394: } ! 395: ! 396: /* Now clear the Multicast filter */ ! 397: if (m->chip_id != MACE_REVISION_A2) { ! 398: ereg->iac = IAC_ADDRCHG|IAC_LOGADDR; eieio(); ! 399: ! 400: while ((status = ereg->iac)) { ! 401: if ((status & IAC_ADDRCHG) == 0) ! 402: break; ! 403: eieio(); ! 404: } ! 405: eieio(); ! 406: } ! 407: else { ! 408: ereg->iac = IAC_LOGADDR; eieio(); ! 409: } ! 410: { ! 411: int i; ! 412: ! 413: for (i=0; i < 8; i++) ! 414: { ereg->ladrf = 0; ! 415: eieio(); ! 416: } ! 417: } ! 418: ! 419: /* register interrupt routines */ ! 420: kdp_mace_setup_dbdma(); ! 421: ! 422: /* Start the chip... */ ! 423: m->ereg->maccc = MACCC_ENXMT|MACCC_ENRCV; eieio(); ! 424: { ! 425: volatile char ch = mace.ereg->ir; eieio(); ! 426: } ! 427: ! 428: delay(500); /* paranoia */ ! 429: mace.ereg->imr = 0xfe; eieio(); ! 430: ! 431: /* register our debugger routines */ ! 432: kdp_register_send_receive((kdp_send_t)polled_send_pkt, ! 433: (kdp_receive_t)polled_receive_pkt); ! 434: ! 435: #ifdef MACE_DEBUG ! 436: printf("Testing 1 2 3\n"); ! 437: send_test_packet(); ! 438: printf("Testing 1 2 3\n"); ! 439: send_test_packet(); ! 440: printf("Testing 1 2 3\n"); ! 441: send_test_packet(); ! 442: do { ! 443: static unsigned char buf[ETHERNET_BUF_SIZE]; ! 444: int len; ! 445: int nmpc = mace.ereg->mpc; eieio(); ! 446: ! 447: if (nmpc > mpc) { ! 448: mpc = nmpc; ! 449: printf("mpc %d\n", mpc); ! 450: } ! 451: polled_receive_pkt((char *)buf, &len, 100); ! 452: if (len > 0) { ! 453: printf("rx %d\n", len); ! 454: printContiguousEtherPacket(buf, len); ! 455: } ! 456: } while(1); ! 457: #endif ! 458: ! 459: return TRUE; ! 460: } ! 461: ! 462: #ifdef MACE_DEBUG ! 463: static void ! 464: kdp_mace_txstatus(char * msg) ! 465: { ! 466: dbdma_regmap_t * dmap = mace.tx_dbdma; ! 467: volatile unsigned long status; ! 468: volatile unsigned long intr; ! 469: volatile unsigned long branch; ! 470: volatile unsigned long wait; ! 471: ! 472: status = dbdma_ld4_endian(&dmap->d_status); eieio(); ! 473: intr = dbdma_ld4_endian(&dmap->d_intselect); eieio(); ! 474: branch = dbdma_ld4_endian(&dmap->d_branch); eieio(); ! 475: wait = dbdma_ld4_endian(&dmap->d_wait); eieio(); ! 476: printf("(%s s=0x%x i=0x%x b=0x%x w=0x%x)", msg, status, intr, branch, ! 477: wait); ! 478: return; ! 479: } ! 480: #endif ! 481: ! 482: static void ! 483: kdp_mace_tx_dbdma(char * data, int len) ! 484: { ! 485: unsigned long count; ! 486: dbdma_command_t * d; ! 487: unsigned long page; ! 488: ! 489: d = mace.tx_dma; ! 490: page = ((unsigned long) data) & PG_MASK; ! 491: if ((page + len) <= PG_SIZE) { /* one piece dma */ ! 492: DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0, ! 493: len, ! 494: (vm_offset_t) kvtophys((vm_offset_t) data), ! 495: DBDMA_INT_NEVER, ! 496: DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER); ! 497: } ! 498: else { /* two piece dma */ ! 499: count = PG_SIZE - page; ! 500: DBDMA_BUILD(d, DBDMA_CMD_OUT_MORE, DBDMA_KEY_STREAM0, ! 501: count, ! 502: (vm_offset_t)kvtophys((vm_offset_t) data), ! 503: DBDMA_INT_NEVER, ! 504: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 505: d++; ! 506: DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0, ! 507: len - count, (vm_offset_t) ! 508: kvtophys((vm_offset_t)((unsigned char *)data + count)), ! 509: DBDMA_INT_NEVER, ! 510: DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER); ! 511: } ! 512: d++; ! 513: DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM, ! 514: 1, kvtophys((vm_offset_t) &mace.ereg->xmtfs),DBDMA_INT_NEVER, ! 515: // 1, &mace.ereg->xmtfs,DBDMA_INT_NEVER, ! 516: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 517: d++; ! 518: DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM, ! 519: 1, kvtophys((vm_offset_t) &mace.ereg->ir), DBDMA_INT_ALWAYS, ! 520: // 1, &mace.ereg->ir, DBDMA_INT_ALWAYS, ! 521: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 522: d++; ! 523: DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, 0, 0, 0); ! 524: ! 525: flush_dcache((vm_offset_t)mace.tx_dma, ! 526: sizeof(dbdma_command_t) * TX_NUM_DBDMA, ! 527: FALSE); ! 528: dbdma_start(mace.tx_dbdma, mace.tx_dma); ! 529: return; ! 530: ! 531: } ! 532: ! 533: static void ! 534: waitForDBDMADone(char * msg) ! 535: { ! 536: { ! 537: /* wait for tx dma completion */ ! 538: dbdma_regmap_t * dmap = mace.tx_dbdma; ! 539: int i; ! 540: volatile unsigned long val; ! 541: ! 542: i = 0; ! 543: do { ! 544: val = dbdma_ld4_endian(&dmap->d_status); eieio(); ! 545: delay(50); ! 546: i++; ! 547: } while ((i < 100000) && (val & DBDMA_CNTRL_ACTIVE)); ! 548: if (i == 100000) ! 549: printf("mace(%s): kdp_mace_tx_dbdma poll timed out 0x%x", msg, val); ! 550: } ! 551: } ! 552: ! 553: int ! 554: kdp_mace_recv_pkt(funcptr pktfunc, void * p) ! 555: { ! 556: vm_offset_t address; ! 557: struct mace_board * board; ! 558: long bytes; ! 559: int done = 0; ! 560: int doContinue = 0; ! 561: mace_t * m; ! 562: unsigned long resid; ! 563: unsigned short status; ! 564: int tail; ! 565: ! 566: m = &mace; ! 567: board = m->ereg; ! 568: ! 569: /* remember where the tail was */ ! 570: tail = m->rv_tail; ! 571: for (done = 0; (done == 0) && (m->rv_head != tail);) { ! 572: dbdma_command_t * dmaHead; ! 573: ! 574: dmaHead = &m->rv_dma[m->rv_head]; ! 575: resid = dbdma_ld4_endian(&dmaHead->d_status_resid); ! 576: status = (resid >> 16); ! 577: bytes = resid & 0xffff; ! 578: bytes = ETHERNET_BUF_SIZE - bytes - 8; /* strip off FCS/CRC */ ! 579: ! 580: if ((status & DBDMA_ETHERNET_EOP) == 0) { ! 581: /* no packets are ready yet */ ! 582: break; ! 583: } ! 584: doContinue = 1; ! 585: /* if the packet is good, pass it up */ ! 586: if (bytes >= (ETHER_MIN_PACKET - 4)) { ! 587: char * dmaPacket; ! 588: dmaPacket = (char *)&m->rv_dma_area[m->rv_head * ETHERNET_BUF_SIZE]; ! 589: done = (*pktfunc)(dmaPacket, bytes, p); ! 590: } ! 591: /* mark the head as the new tail in the dma channel command list */ ! 592: DBDMA_BUILD(dmaHead, DBDMA_CMD_STOP, 0, 0, 0, DBDMA_INT_ALWAYS, ! 593: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER); ! 594: flush_dcache((vm_offset_t)dmaHead, ! 595: sizeof(*dmaHead), ! 596: FALSE); ! 597: eieio(); ! 598: ! 599: /* make the tail an available dma'able entry */ ! 600: { ! 601: dbdma_command_t * dmaTail; ! 602: dmaTail = &m->rv_dma[m->rv_tail]; ! 603: address = kvtophys((vm_offset_t) ! 604: &m->rv_dma_area[m->rv_tail*ETHERNET_BUF_SIZE]); ! 605: // this command is live so write it carefully ! 606: DBDMA_ST4_ENDIAN(&dmaTail->d_address, address); ! 607: dmaTail->d_status_resid = 0; ! 608: dmaTail->d_cmddep = 0; ! 609: eieio(); ! 610: DBDMA_ST4_ENDIAN(&dmaTail->d_cmd_count, ! 611: ((DBDMA_CMD_IN_LAST) << 28) | ((0) << 24) | ! 612: ((DBDMA_INT_ALWAYS) << 20) | ! 613: ((DBDMA_BRANCH_NEVER) << 18) | ((DBDMA_WAIT_NEVER) << 16) | ! 614: (ETHERNET_BUF_SIZE)); ! 615: eieio(); ! 616: flush_dcache((vm_offset_t)dmaTail, ! 617: sizeof(*dmaTail), ! 618: FALSE); ! 619: } ! 620: /* head becomes the tail */ ! 621: m->rv_tail = m->rv_head; ! 622: ! 623: /* advance the head */ ! 624: m->rv_head++; ! 625: if (m->rv_head == (ETHER_RX_NUM_DBDMA_BUFS + 1)) ! 626: m->rv_head = 0; ! 627: } ! 628: if (doContinue) { ! 629: sync(); ! 630: dbdma_continue(m->rv_dbdma); ! 631: } ! 632: return (done); ! 633: } ! 634: ! 635: static int ! 636: kdp_mace_copy(char * pktBuf, int len, void * p) ! 637: { ! 638: struct kdp_mace_copy_desc * cp = (struct kdp_mace_copy_desc *)p; ! 639: ! 640: bcopy((char *)pktBuf, (char *)cp->data, len); ! 641: *cp->len = len; ! 642: return (1); /* signal that we're done */ ! 643: } ! 644: ! 645: /* kdb debugger routines */ ! 646: static void ! 647: polled_send_pkt(char * data, int len) ! 648: { ! 649: waitForDBDMADone("mace: polled_send_pkt start"); ! 650: kdp_mace_tx_dbdma(data, len); ! 651: waitForDBDMADone("mace: polled_send_pkt end"); ! 652: return; ! 653: } ! 654: ! 655: static void ! 656: polled_receive_pkt(char *data, int *len, int timeout_ms) ! 657: { ! 658: struct kdp_mace_copy_desc cp; ! 659: ! 660: cp.len = len; ! 661: cp.data = data; ! 662: ! 663: timeout_ms *= 1000; ! 664: *len = 0; ! 665: while (kdp_mace_recv_pkt(kdp_mace_copy, (void *)&cp) == 0) { ! 666: if (timeout_ms <= 0) ! 667: break; ! 668: delay(50); ! 669: timeout_ms -= 50; ! 670: } ! 671: return; ! 672: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.