|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1995-1996 NeXT Software, Inc. ! 27: * ! 28: * Implementation for hardware dependent (relatively) code ! 29: * for the DECchip 21040 and 21041. ! 30: * ! 31: * HISTORY ! 32: * ! 33: * 26-Apr-95 Rakesh Dubey (rdubey) at NeXT ! 34: * Created. ! 35: * 11-Oct-95 Dieter Siegmund (dieter) at NeXT ! 36: * Added performance hooks; changed transmit interrupt ! 37: * to only interrupt every N / 2 times, where N is the ! 38: * number of transmit descriptors. This reduces the ! 39: * number of interrupts taken, and the amount of CPU ! 40: * used by the driver. ! 41: * 02-Nov-95 Rakesh Dubey (rdubey) at NeXT ! 42: * Added support for 21041 based adapters. ! 43: * -- serial ROM for station address ! 44: * -- new network interface selection scheme ! 45: * 11-Dec-95 Dieter Siegmund (dieter) at NeXT ! 46: * Split out 21040 and 21041 connector auto-detect logic. ! 47: * 07-Feb-96 Dieter Siegmund (dieter) at NeXT ! 48: * Fixed multicast. ! 49: * 25-Jun-96 Dieter Siegmund (dieter) at NeXT ! 50: * Added kernel debugger support. ! 51: * 05-Aug-97 Joe Liu at Apple ! 52: * Made kernel debugger support more robust. ! 53: */ ! 54: ! 55: #import "DECchip2104x.h" ! 56: #import "DECchip2104xPrivate.h" ! 57: ! 58: #import <machdep/ppc/proc_reg.h> ! 59: #import <mach/vm_param.h> // PAGE_SIZE ! 60: ! 61: extern void *kernel_map; ! 62: extern kern_return_t kmem_alloc_wired(); ! 63: ! 64: //#define DEBUG ! 65: ! 66: #import "DECchip2104xInline.h" ! 67: ! 68: #ifdef DEBUG ! 69: static void IOBreak() ! 70: { ! 71: //IOBreakToDebugger(); ! 72: return; ! 73: } ! 74: ! 75: static void printDesc(void *descriptorStruct) ! 76: { ! 77: txDescriptorStruct *desc = (txDescriptorStruct *)descriptorStruct; ! 78: ! 79: IOLog("DESC: "); ! 80: IOLog("%x (%x) ", (unsigned int)&desc->status.data, desc->status.data); ! 81: IOLog("%x (%x: %x %x) ", (unsigned int)&desc->control.data, desc->control.data, desc->control.reg.byteCountBuffer1, desc->control.reg.byteCountBuffer2); ! 82: IOLog("%x (%x) ", (unsigned int)&desc->bufferAddress1, desc->bufferAddress1); ! 83: IOLog("%x (%x) ", (unsigned int)&desc->bufferAddress2, desc->bufferAddress2); ! 84: IOLog("\n"); ! 85: ! 86: } ! 87: #endif DEBUG ! 88: ! 89: /* ! 90: * Breaks up an ethernet data buffer into two physical chunks. We know that ! 91: * the buffer can't straddle more than two pages. If the content of paddr2 is ! 92: * zero this means that all of the buffer lies in one physical page. Note ! 93: * that we use the fact that tx and rx descriptors have the same size and ! 94: * same layout of relevent fields (data address and count). ! 95: */ ! 96: static BOOL ! 97: IOUpdateDescriptorFromNetBuf(netbuf_t nb, void *desc, BOOL isReceive) ! 98: { ! 99: IOReturn result; ! 100: vm_address_t pageBreak; ! 101: unsigned int len; ! 102: vm_address_t vaddr; ! 103: unsigned int *paddr1, *paddr2; ! 104: ! 105: struct _descriptorStruct { ! 106: unsigned int status; ! 107: union { ! 108: struct { ! 109: unsigned int ! 110: rsvd :10, ! 111: byteCountBuffer2 :11, ! 112: byteCountBuffer1 :11; ! 113: } reg; ! 114: unsigned int data; ! 115: } control; ! 116: unsigned int bufferAddress1; ! 117: unsigned int bufferAddress2; ! 118: } *descriptorStruct; ! 119: ! 120: ! 121: descriptorStruct = (struct _descriptorStruct *)desc; ! 122: len = isReceive ? NETWORK_BUFSIZE : nb_size(nb); ! 123: ! 124: vaddr = (vm_address_t)nb_map(nb); ! 125: paddr1 = &descriptorStruct->bufferAddress1; ! 126: paddr2 = &descriptorStruct->bufferAddress2; ! 127: ! 128: /* Assume contiguity */ ! 129: *paddr2 = 0; ! 130: descriptorStruct->control.reg.byteCountBuffer2 = 0; ! 131: descriptorStruct->control.reg.byteCountBuffer1 = len; ! 132: ! 133: result = IOPhysicalFromVirtual(IOVmTaskSelf(), vaddr, paddr1); ! 134: if (result != IO_R_SUCCESS) { ! 135: return NO; ! 136: } ! 137: ! 138: /* ! 139: * Now check if this memory block crosses a page boundary. ! 140: */ ! 141: if (trunc_page(vaddr) == trunc_page(vaddr+len)) { ! 142: return YES; ! 143: } ! 144: ! 145: /* Nice try... */ ! 146: pageBreak = round_page(vaddr); ! 147: descriptorStruct->control.reg.byteCountBuffer1 = pageBreak - vaddr; ! 148: descriptorStruct->control.reg.byteCountBuffer2 = len - (pageBreak - vaddr); ! 149: ! 150: result = IOPhysicalFromVirtual(IOVmTaskSelf(), pageBreak, paddr2); ! 151: if (result != IO_R_SUCCESS) { ! 152: return NO; ! 153: } ! 154: ! 155: return YES; ! 156: } ! 157: ! 158: ! 159: @implementation DECchip2104x (Private) ! 160: ! 161: /* ! 162: * Private functions ! 163: */ ! 164: - (BOOL)_allocateMemory ! 165: { ! 166: int i; ! 167: IOReturn result; ! 168: ! 169: //kprintf("[DECchip2104x _allocateMemory]\n"); ! 170: ! 171: memorySize = sizeof(rxDescriptorStruct) * DEC_21X40_RX_RING_LENGTH ! 172: + sizeof(txDescriptorStruct) * DEC_21X40_TX_RING_LENGTH ! 173: + DEC_21X40_DESCRIPTOR_ALIGNMENT * 2 ! 174: + sizeof(setupBuffer_t) + DEC_21X40_DESCRIPTOR_ALIGNMENT; ! 175: if (memorySize > PAGE_SIZE) { ! 176: IOLog("%s: 1 page limit exceeded for descriptor memory\n",[self name]); ! 177: return NO; ! 178: } ! 179: ! 180: /* ! 181: * We need one page of contiguous memory. ! 182: */ ! 183: result = kmem_alloc_wired(kernel_map,(vm_offset_t *)&memoryPtr,memorySize); ! 184: if (result != KERN_SUCCESS) { ! 185: IOLog ("%s: can't allocate 0x%x bytes of memory\n", ! 186: [self name], memorySize); ! 187: return NO; ! 188: } ! 189: ! 190: rxRing = (rxDescriptorStruct *)memoryPtr; ! 191: if (!IOIsAligned(rxRing, DEC_21X40_DESCRIPTOR_ALIGNMENT)) ! 192: rxRing = IOAlign(rxDescriptorStruct *, rxRing, ! 193: DEC_21X40_DESCRIPTOR_ALIGNMENT); ! 194: for (i = 0 ; i < DEC_21X40_RX_RING_LENGTH ; i++) { ! 195: bzero((void *)&rxRing[i], sizeof(rxDescriptorStruct)); ! 196: rxNetbuf[i] = NULL; ! 197: } ! 198: ! 199: txRing = (txDescriptorStruct *)(rxRing + DEC_21X40_RX_RING_LENGTH); ! 200: if (!IOIsAligned(txRing, DEC_21X40_DESCRIPTOR_ALIGNMENT)) ! 201: txRing = IOAlign(txDescriptorStruct *, txRing, ! 202: DEC_21X40_DESCRIPTOR_ALIGNMENT); ! 203: for (i = 0 ; i < DEC_21X40_TX_RING_LENGTH ; i++) { ! 204: bzero((void *)&txRing[i], sizeof(txDescriptorStruct)); ! 205: txNetbuf[i] = NULL; ! 206: } ! 207: ! 208: setupBuffer = (setupBuffer_t *)(txRing + DEC_21X40_TX_RING_LENGTH); ! 209: if (!IOIsAligned(setupBuffer, DEC_21X40_DESCRIPTOR_ALIGNMENT)) ! 210: setupBuffer = IOAlign(setupBuffer_t *, ! 211: setupBuffer, DEC_21X40_DESCRIPTOR_ALIGNMENT); ! 212: result = IOPhysicalFromVirtual(IOVmTaskSelf(), ! 213: (vm_address_t)setupBuffer, (unsigned *)&setupBufferPhysical); ! 214: if (result != IO_R_SUCCESS) { ! 215: IOLog("%s: Invalid shared memory address\n", [self name]); ! 216: return NO; ! 217: } ! 218: ! 219: return YES; ! 220: } ! 221: ! 222: #ifdef DEBUG ! 223: - (void)_dumpRegisters ! 224: { ! 225: int i; ! 226: ! 227: return; ! 228: IOLog("%s: Regs: ", [self name]); ! 229: for (i = 0; i <= 15; i++) { ! 230: IOLog("%02d: %x ", i, readCsr(ioBase, 8*i)); ! 231: } ! 232: IOLog("\n"); ! 233: } ! 234: #endif DEBUG ! 235: ! 236: #ifdef DEBUG ! 237: - (void)_dumpDescriptor:(void *)ds ! 238: { ! 239: txDescriptorStruct *desc = (txDescriptorStruct *)ds; ! 240: ! 241: IOLog("%s: Desc: ", [self name]); ! 242: IOLog("%x ", *(unsigned int *)&desc->status); ! 243: IOLog("%x ", *(unsigned int *)&desc->control); ! 244: IOLog("%x ", *(unsigned int *)&desc->bufferAddress1); ! 245: IOLog("%x ", *(unsigned int *)&desc->bufferAddress2); ! 246: IOLog("\n"); ! 247: } ! 248: #endif DEBUG ! 249: ! 250: - (BOOL)_initTxRing ! 251: { ! 252: unsigned int i; ! 253: ! 254: //kprintf("[DECchip2104x _initTxRing]\n"); ! 255: ! 256: for (i = 0; i < DEC_21X40_TX_RING_LENGTH; i++) { ! 257: bzero((void *)&txRing[i], sizeof(txDescriptorStruct)); ! 258: txRing[i].status.reg.own = DEC_21X40_DESC_OWNED_BY_HOST; ! 259: if (txNetbuf[i]) { ! 260: nb_free(txNetbuf[i]); ! 261: txNetbuf[i] = NULL; ! 262: } ! 263: } ! 264: txRing[DEC_21X40_TX_RING_LENGTH-1].control.reg.ter = YES; ! 265: ! 266: txPutIndex = 0; ! 267: txDoneIndex = 0; ! 268: txNumFree = DEC_21X40_TX_RING_LENGTH; ! 269: txIntCount = 0; ! 270: ! 271: /* Init the transmit queue. */ ! 272: if (transmitQueue) { ! 273: [transmitQueue free]; ! 274: } ! 275: transmitQueue = [[IONetbufQueue alloc] ! 276: initWithMaxCount:TRANSMIT_QUEUE_SIZE]; ! 277: if (!transmitQueue) { ! 278: IOPanic("_initTxRing"); ! 279: } ! 280: ! 281: return YES; ! 282: } ! 283: ! 284: - (BOOL)_initRxRing ! 285: { ! 286: int i; ! 287: BOOL status; ! 288: ! 289: //kprintf("[DECchip2104x _initRxRing]\n"); ! 290: ! 291: for (i = 0; i < DEC_21X40_RX_RING_LENGTH; i++) { ! 292: bzero((void *)&rxRing[i], sizeof(rxDescriptorStruct)); ! 293: rxRing[i].status.reg.own = DEC_21X40_DESC_OWNED_BY_HOST; ! 294: if (rxNetbuf[i] == NULL) { ! 295: rxNetbuf[i] = [self allocateNetbuf]; ! 296: if (rxNetbuf[i] == NULL) { ! 297: IOPanic("allocateNetbuf returned NULL in _initRxRing"); ! 298: } ! 299: } ! 300: status = IOUpdateDescriptorFromNetBuf(rxNetbuf[i], ! 301: (void *)&rxRing[i], YES); ! 302: if (status == NO) ! 303: IOPanic("_initRxRing"); ! 304: rxRing[i].status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 305: } ! 306: ! 307: rxRing[DEC_21X40_RX_RING_LENGTH-1].control.reg.rer = YES; ! 308: ! 309: rxDoneIndex = 0; ! 310: ! 311: return YES; ! 312: } ! 313: ! 314: ! 315: - (BOOL) _initChip ! 316: { ! 317: ! 318: //kprintf("[DECchip2104x _initChip]\n"); ! 319: ! 320: [self _initRegisters]; ! 321: [self _startTransmit]; ! 322: ! 323: /* ! 324: * Set up station, broadcast, and multicast addresses ! 325: */ ! 326: if (![self _setAddressFiltering:YES]) ! 327: return NO; ! 328: ! 329: [self selectInterface]; ! 330: ! 331: #ifdef DEBUG ! 332: [self _dumpRegisters]; ! 333: #endif DEBUG ! 334: ! 335: return YES; ! 336: } ! 337: ! 338: - (void)_resetChip ! 339: { ! 340: csrRegUnion reg; ! 341: ! 342: //kprintf("[DECchip2104x _resetChip]\n"); ! 343: ! 344: reg.data = 0; ! 345: reg.csr0.swr = 1; /* reset */ ! 346: writeCsr(ioBase, DEC_21X40_CSR0, reg.data); ! 347: IODelay(100); ! 348: reg.csr0.swr = 0; /* deassert */ ! 349: writeCsr(ioBase, DEC_21X40_CSR0, reg.data); ! 350: ! 351: IOSleep(1); /* >= 100 PCI bus cycles */ ! 352: } ! 353: ! 354: - (void)_startTransmit ! 355: { ! 356: ! 357: //kprintf("[DECchip2104x _startTransmit]\n"); ! 358: ! 359: operationMode.csr6.st = YES; ! 360: writeCsr(ioBase, DEC_21X40_CSR6, operationMode.data); ! 361: } ! 362: ! 363: - (void)_startReceive ! 364: { ! 365: ! 366: //kprintf("[DECchip2104x _startReceive]\n"); ! 367: ! 368: operationMode.csr6.sr = YES; ! 369: writeCsr(ioBase, DEC_21X40_CSR6, operationMode.data); ! 370: } ! 371: ! 372: - (void)_initRegisters ! 373: { ! 374: IOReturn result; ! 375: csrRegUnion reg; ! 376: ! 377: unsigned int paddr; ! 378: ! 379: //kprintf("[DECchip2104x _initRegisters]\n"); ! 380: ! 381: [self _resetChip]; ! 382: ! 383: reg.data = 0; ! 384: reg.csr0.dbo = 1; /* Big Endian Descriptors */ ! 385: // reg.csr0.ble = 1; /* Big Endian Buffers */ ! 386: reg.csr0.pbl = 16; /* errata: don't set to 0 or 32 */ ! 387: reg.csr0.cal = 1; /* depends upon NETWORK_BUFALIGNMENT */ ! 388: writeCsr(ioBase, DEC_21X40_CSR0, reg.data); /* bus mode */ ! 389: ! 390: result = IOPhysicalFromVirtual(IOVmTaskSelf(), ! 391: (vm_address_t)rxRing, (unsigned int *)&paddr); ! 392: if (result != IO_R_SUCCESS) { ! 393: IOLog("%s: Invalid shared memory address\n", [self name]); ! 394: return; ! 395: } ! 396: reg.data = 0; ! 397: reg.csr3.rdlba = (unsigned int)paddr; ! 398: writeCsr(ioBase, DEC_21X40_CSR3, reg.data); /* receive list base */ ! 399: ! 400: result = IOPhysicalFromVirtual(IOVmTaskSelf(), ! 401: (vm_address_t)txRing, (unsigned int *)&paddr); ! 402: if (result != IO_R_SUCCESS) { ! 403: IOLog("%s: Invalid shared memory address\n", [self name]); ! 404: return; ! 405: } ! 406: reg.data = 0; ! 407: reg.csr4.tdlba = (unsigned int)paddr; ! 408: writeCsr(ioBase, DEC_21X40_CSR4, reg.data); /* transmit list base */ ! 409: ! 410: reg.data = 0; /* FIXME -- choose appropriate values */ ! 411: writeCsr(ioBase, DEC_21X40_CSR6, reg.data); /* operations mode */ ! 412: operationMode.data = reg.data; ! 413: ! 414: reg.data = 0; ! 415: reg.csr7.tim = reg.csr7.rim = reg.csr7.tjm = 1; ! 416: reg.csr7.nim = 1; ! 417: #ifdef DEBUG ! 418: reg.csr7.tim = reg.csr7.tsm = reg.csr7.tum = reg.csr7.tjm = 1; ! 419: reg.csr7.unm = reg.csr7.rim = reg.csr7.rum = 1; ! 420: reg.csr7.atm = 1; ! 421: reg.csr7.lfm = reg.csr7.sem = reg.csr7.aim = 1; ! 422: #endif DEBUG ! 423: interruptMask.data = reg.data; ! 424: ! 425: writeCsr(ioBase, DEC_21X40_CSR11, 0); /* no full duplex */ ! 426: } ! 427: ! 428: - (void)_transmitPacket:(netbuf_t)packet ! 429: { ! 430: csrRegUnion reg; ! 431: txDescriptorStruct *desc; ! 432: BOOL status; ! 433: ! 434: //kprintf("[DECchip2104x _transmitPacket]\n"); ! 435: ! 436: [self performLoopback:packet]; ! 437: ! 438: [self reserveDebuggerLock]; ! 439: ! 440: if (txNumFree == 0) { ! 441: [self releaseDebuggerLock]; ! 442: nb_free(packet); ! 443: return; ! 444: } ! 445: ! 446: desc = &txRing[txPutIndex]; ! 447: txNetbuf[txPutIndex] = packet; ! 448: ! 449: if (desc->control.reg.ter == 1) { ! 450: desc->control.data = 0; ! 451: desc->control.reg.ter = 1; ! 452: } ! 453: else ! 454: desc->control.data = 0; ! 455: ! 456: status = IOUpdateDescriptorFromNetBuf(packet, (void *)desc, NO); ! 457: if (status == NO) { ! 458: [self releaseDebuggerLock]; ! 459: IOLog("%s: _transmitPacket: IOUpdateDescriptorFromNetBuf failed\n", ! 460: [self name]); ! 461: nb_free(packet); /* this is the best we can do here */ ! 462: return; ! 463: } ! 464: ! 465: desc->control.reg.fs = YES; ! 466: desc->control.reg.ls = YES; ! 467: if (++txIntCount == (DEC_21X40_TX_RING_LENGTH / 2)) { ! 468: desc->control.reg.ic = YES; ! 469: txIntCount = 0; ! 470: } ! 471: else ! 472: desc->control.reg.ic = NO; ! 473: ! 474: desc->status.data = 0; ! 475: desc->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 476: ! 477: // txPutIndex = (txPutIndex + 1) % DEC_21X40_TX_RING_LENGTH; ! 478: if (++txPutIndex == DEC_21X40_TX_RING_LENGTH) ! 479: txPutIndex = 0; ! 480: --txNumFree; ! 481: ! 482: /* ! 483: * Make the chip poll immediately. ! 484: */ ! 485: reg.data = 0; ! 486: reg.csr1.tpd = YES; ! 487: writeCsr(ioBase, DEC_21X40_CSR1, reg.data); ! 488: ! 489: [self releaseDebuggerLock]; ! 490: ! 491: return; ! 492: } ! 493: ! 494: /* ! 495: * Method: receivePacket ! 496: * ! 497: * Purpose: ! 498: * Part of kerneldebugger protocol. ! 499: */ ! 500: - (void)receivePacket:(void *)pkt length:(unsigned int *)pkt_len ! 501: timeout:(unsigned int)timeout ! 502: { ! 503: *pkt_len = 0; ! 504: timeout *= 1000; ! 505: ! 506: if (resetAndEnabled == NO) ! 507: return; ! 508: ! 509: while (1) { ! 510: if (rxRing[rxDoneIndex].status.reg.own ! 511: == DEC_21X40_DESC_OWNED_BY_HOST) { ! 512: rxDescriptorStruct * rds; ! 513: ! 514: rds = &rxRing[rxDoneIndex]; ! 515: if (rds->status.reg.es ! 516: || (!rds->status.reg.fs || !rds->status.reg.ls) ! 517: || (rds->status.reg.fl < ETHERMINPACKET)) { ! 518: rxRing[rxDoneIndex].status.reg.own ! 519: = DEC_21X40_DESC_OWNED_BY_CTRL; ! 520: // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH; ! 521: if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH) ! 522: rxDoneIndex = 0; ! 523: } ! 524: else ! 525: break; ! 526: } ! 527: else { ! 528: if ((int)timeout <= 0) ! 529: return; ! 530: IODelay(50); ! 531: timeout -= 50; ! 532: } ! 533: } ! 534: { ! 535: rxDescriptorStruct * rds; ! 536: ! 537: rds = &rxRing[rxDoneIndex]; ! 538: *pkt_len = rds->status.reg.fl - ETHERCRC; ! 539: bcopy(nb_map(rxNetbuf[rxDoneIndex]), pkt, *pkt_len); ! 540: ! 541: rds->status.data = 0; ! 542: rds->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 543: // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH; ! 544: if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH) ! 545: rxDoneIndex = 0; ! 546: } ! 547: return; ! 548: } ! 549: /* ! 550: * Method: sendPacket ! 551: * ! 552: * Purpose: ! 553: * Part of kerneldebugger protocol. ! 554: */ ! 555: - (void)sendPacket:(void *)pkt length:(unsigned int)pkt_len ! 556: { ! 557: int size; ! 558: volatile txDescriptorStruct * desc; ! 559: csrRegUnion reg; ! 560: BOOL status; ! 561: ! 562: if (resetAndEnabled == NO) ! 563: return; /* can't transmit right now */ ! 564: ! 565: [self _transmitInterruptOccurred]; ! 566: ! 567: if (txNumFree == 0) { ! 568: IOLog("%s: _sendPacket: No free tx descriptors\n", [self name]); ! 569: return; /* can't transmit right now */ ! 570: } ! 571: ! 572: desc = &txRing[txPutIndex]; ! 573: txNetbuf[txPutIndex] = NULL; ! 574: ! 575: bcopy(pkt, nb_map(KDB_txBuf), pkt_len); ! 576: size = nb_size(KDB_txBuf); ! 577: nb_shrink_bot(KDB_txBuf, size - pkt_len); ! 578: ! 579: if (desc->control.reg.ter == 1) { ! 580: desc->control.data = 0; ! 581: desc->control.reg.ter = 1; ! 582: } ! 583: else ! 584: desc->control.data = 0; ! 585: ! 586: status = IOUpdateDescriptorFromNetBuf(KDB_txBuf, (void *)desc, NO); ! 587: if (status == NO) { ! 588: IOLog("%s: _sendPacket: IOUpdateDescriptorFromNetBuf failed\n", ! 589: [self name]); ! 590: return; ! 591: } ! 592: ! 593: desc->control.reg.fs = YES; ! 594: desc->control.reg.ls = YES; ! 595: desc->control.reg.ic = NO; ! 596: desc->status.data = 0; ! 597: desc->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 598: ! 599: // txPutIndex = (txPutIndex + 1) % DEC_21X40_TX_RING_LENGTH; ! 600: if (++txPutIndex == DEC_21X40_TX_RING_LENGTH) ! 601: txPutIndex = 0; ! 602: --txNumFree; ! 603: ! 604: /* ! 605: * Make the chip poll immediately. ! 606: */ ! 607: reg.data = 0; ! 608: reg.csr1.tpd = YES; ! 609: writeCsr(ioBase, DEC_21X40_CSR1, reg.data); ! 610: ! 611: { /* poll for completion */ ! 612: int i; ! 613: for (i = 0; ! 614: i < 10000 && desc->status.reg.own == DEC_21X40_DESC_OWNED_BY_CTRL; ! 615: i++) { ! 616: IODelay(500); ! 617: } ! 618: } ! 619: if (desc->status.reg.own == DEC_21X40_DESC_OWNED_BY_CTRL) ! 620: IOLog("%s: _sendPacket: polling timed out\n", [self name]); ! 621: ! 622: /* restore the actual size of the buffer */ ! 623: nb_grow_bot(KDB_txBuf, size - pkt_len); ! 624: ! 625: return; ! 626: } ! 627: ! 628: - (BOOL)_receiveInterruptOccurred ! 629: { ! 630: netbuf_t packet; ! 631: BOOL passPacketUp; ! 632: rxDescriptorStruct * rds; ! 633: unsigned int receivedFrameSize; ! 634: BOOL status; ! 635: ! 636: //kprintf("[DECchip2104x _receiveInterruptOccurred]\n"); ! 637: ! 638: [self reserveDebuggerLock]; ! 639: ! 640: while (rxRing[rxDoneIndex].status.reg.own ! 641: == DEC_21X40_DESC_OWNED_BY_HOST) { ! 642: passPacketUp = NO; ! 643: rds = &rxRing[rxDoneIndex]; ! 644: receivedFrameSize = rds->status.reg.fl - ETHERCRC; ! 645: ! 646: /* ! 647: * Bad packet. Just leave the netbuf in place. ! 648: */ ! 649: if (rds->status.reg.es ! 650: || (!rds->status.reg.fs || !rds->status.reg.ls) ! 651: || (receivedFrameSize < (ETHERMINPACKET - ETHERCRC))) { ! 652: [networkInterface incrementInputErrors]; ! 653: rxRing[rxDoneIndex].status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 654: // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH; ! 655: if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH) ! 656: rxDoneIndex = 0; ! 657: continue; ! 658: } ! 659: ! 660: /* Toss packets not in our multicast address-space. */ ! 661: packet = rxNetbuf[rxDoneIndex]; ! 662: if (isPromiscuous ! 663: || rds->status.reg.mf == NO ! 664: || [super isUnwantedMulticastPacket: ! 665: (ether_header_t *)nb_map(packet)] == NO) { ! 666: netbuf_t newPacket; ! 667: ! 668: newPacket = [self allocateNetbuf]; ! 669: if (newPacket != NULL) { ! 670: rxNetbuf[rxDoneIndex] = newPacket; ! 671: passPacketUp = YES; ! 672: status = ! 673: IOUpdateDescriptorFromNetBuf(rxNetbuf[rxDoneIndex], ! 674: (void *)&rxRing[rxDoneIndex], ! 675: YES); ! 676: if (status == NO) { ! 677: IOPanic("DECchip21040: IOUpdateDescriptorFromNetBuf\n"); ! 678: } ! 679: /* Adjust to size received */ ! 680: nb_shrink_bot(packet, nb_size(packet) - receivedFrameSize); ! 681: } ! 682: } ! 683: rds->status.data = 0; ! 684: rds->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 685: ! 686: // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH; ! 687: if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH) ! 688: rxDoneIndex = 0; ! 689: if (passPacketUp) { ! 690: passPacketUp = NO; ! 691: [self releaseDebuggerLock]; ! 692: [networkInterface handleInputPacket:packet extra:0]; ! 693: [self reserveDebuggerLock]; ! 694: } ! 695: } ! 696: ! 697: [self releaseDebuggerLock]; ! 698: ! 699: return YES; ! 700: } ! 701: ! 702: - (BOOL)_transmitInterruptOccurred ! 703: { ! 704: txDescriptorStruct *tds; ! 705: ! 706: //kprintf("[DECchip2104x _transmitInterruptOccurred]\n"); ! 707: ! 708: while (txNumFree < DEC_21X40_TX_RING_LENGTH) { ! 709: tds = &txRing[txDoneIndex]; ! 710: if (tds->status.reg.own == DEC_21X40_DESC_OWNED_BY_CTRL) ! 711: break; ! 712: ! 713: if (tds->control.reg.set == 1) { ! 714: //IOLog("TX interrupt: Ignoring set up packet\n"); ! 715: // txDoneIndex = (txDoneIndex + 1) % DEC_21X40_TX_RING_LENGTH; ! 716: if (++txDoneIndex == DEC_21X40_TX_RING_LENGTH) ! 717: txDoneIndex = 0; ! 718: ++txNumFree; ! 719: continue; ! 720: } ! 721: ! 722: if (tds->status.reg.uf || tds->status.reg.ec ! 723: || tds->status.reg.lc || tds->status.reg.nc ! 724: || tds->status.reg.to) ! 725: [networkInterface incrementOutputErrors]; ! 726: else ! 727: [networkInterface incrementOutputPackets]; ! 728: ! 729: if (tds->status.reg.ec) ! 730: [networkInterface incrementCollisionsBy:16]; ! 731: else if (tds->status.reg.cc) ! 732: [networkInterface incrementCollisionsBy:tds->status.reg.cc]; ! 733: if (tds->status.reg.lc && !tds->status.reg.uf) ! 734: [networkInterface incrementCollisions]; ! 735: ! 736: if (txNetbuf[txDoneIndex] != NULL) { ! 737: nb_free(txNetbuf[txDoneIndex]); ! 738: txNetbuf[txDoneIndex] = NULL; ! 739: } ! 740: // txDoneIndex = (txDoneIndex + 1) % DEC_21X40_TX_RING_LENGTH; ! 741: if (++txDoneIndex == DEC_21X40_TX_RING_LENGTH) ! 742: txDoneIndex = 0; ! 743: ++txNumFree; ! 744: } ! 745: ! 746: return YES; ! 747: } ! 748: ! 749: #define DEC_21X40_SETUP_TIMEOUT 10000 ! 750: ! 751: - (BOOL)_loadSetupFilter:(BOOL)pollingMode ! 752: { ! 753: txDescriptorStruct *setupDescriptor; ! 754: unsigned int time = DEC_21X40_SETUP_TIMEOUT; ! 755: csrRegUnion reg; ! 756: ! 757: //kprintf("[DECchip2104x _loadSetupFilter]\n"); ! 758: ! 759: /* ! 760: * Make sure that we have a descriptor for setup frame ! 761: */ ! 762: if (txNumFree == 0) ! 763: return NO; ! 764: ! 765: setupDescriptor = &txRing[txPutIndex]; ! 766: // txPutIndex = (txPutIndex + 1) % DEC_21X40_TX_RING_LENGTH; ! 767: if (++txPutIndex == DEC_21X40_TX_RING_LENGTH) ! 768: txPutIndex = 0; ! 769: --txNumFree; ! 770: ! 771: /* ! 772: * Initialize the Setup descriptor ! 773: */ ! 774: if (setupDescriptor->control.reg.ter == YES) { ! 775: setupDescriptor->control.data = 0; ! 776: setupDescriptor->control.reg.ter = YES; ! 777: } else { ! 778: setupDescriptor->control.data = 0; ! 779: } ! 780: ! 781: setupDescriptor->control.reg.set = YES; ! 782: setupDescriptor->control.reg.ic = YES; ! 783: setupDescriptor->control.reg.byteCountBuffer1 = ! 784: sizeof(setupBuffer_t); ! 785: setupDescriptor->control.reg.byteCountBuffer2 = 0; ! 786: ! 787: setupDescriptor->bufferAddress1 = setupBufferPhysical; ! 788: setupDescriptor->bufferAddress2 = 0; ! 789: ! 790: setupDescriptor->status.data = 0; ! 791: setupDescriptor->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL; ! 792: ! 793: /* tell the chip about this setup command */ ! 794: reg.data = 0; ! 795: reg.csr1.tpd = YES; ! 796: writeCsr(ioBase, DEC_21X40_CSR1, reg.data); ! 797: ! 798: if (pollingMode) { ! 799: while (time--) { ! 800: IODelay(5); ! 801: reg.data = readCsr(ioBase, DEC_21X40_CSR5); ! 802: if (reg.csr5.tu) { ! 803: writeCsr(ioBase, DEC_21X40_CSR5, reg.data); ! 804: break; ! 805: } ! 806: } ! 807: ! 808: // txDoneIndex = (txDoneIndex + 1) % DEC_21X40_TX_RING_LENGTH; ! 809: if (++txDoneIndex == DEC_21X40_TX_RING_LENGTH) ! 810: txDoneIndex = 0; ! 811: ++txNumFree; ! 812: } ! 813: ! 814: return YES; ! 815: } ! 816: ! 817: - (BOOL)_setAddressFiltering:(BOOL)pollingMode ! 818: { ! 819: int i; ! 820: BOOL status = YES; ! 821: unsigned q_count; ! 822: unsigned short *address; ! 823: ! 824: //kprintf("[DECchip2104x _setAddressFiltering]\n"); ! 825: ! 826: /* ! 827: * Copy station address into the first entry. Note that the ! 828: * upper 2 bytes of all longwords in the setup frame are don't ! 829: * cares for perfect filtering. ! 830: */ ! 831: address = (unsigned short *)&myAddress; ! 832: for (i = 0 ; i < 3; i++) { ! 833: unsigned short addr = (unsigned short)*address++; ! 834: setupBuffer->physicalAddress[0][i] = (addr << 16); ! 835: } ! 836: ! 837: /* ! 838: * Load the broadcast address in the second entry ! 839: */ ! 840: for (i = 0 ; i < 3; i++) { ! 841: setupBuffer->physicalAddress[1][i] = 0xffffffff; ! 842: } ! 843: ! 844: /* ! 845: * Skip over the first 2 entries ! 846: */ ! 847: q_count = 2; ! 848: ! 849: if (multicastEnabled) { ! 850: enetMulti_t *multiAddr; ! 851: queue_head_t *multiQueue = [super multicastQueue]; ! 852: ! 853: if (!queue_empty(multiQueue)) { ! 854: /* ! 855: * Fill in the addresses ! 856: */ ! 857: queue_iterate(multiQueue, multiAddr, enetMulti_t *, link) { ! 858: union { ! 859: unsigned char bytes[4]; ! 860: unsigned long word; ! 861: } typeConvert; ! 862: ! 863: typeConvert.word = 0; ! 864: ! 865: for (i = 0; i < 3; i++) { ! 866: typeConvert.bytes[0] = multiAddr->address.ea_byte[i*2]; ! 867: typeConvert.bytes[1] = multiAddr->address.ea_byte[i*2+1]; ! 868: setupBuffer->physicalAddress[q_count][i] = ! 869: typeConvert.word; ! 870: } ! 871: if (++q_count >= DEC_21X40_SETUP_PERFECT_ENTRIES) { ! 872: IOLog("%s: %d multicast address limit exceeded\n", ! 873: [self name], DEC_21X40_SETUP_PERFECT_MCAST_ENTRIES); ! 874: break; ! 875: } ! 876: } ! 877: } ! 878: } ! 879: ! 880: /* ! 881: * Duplicate station address for remaining entries ! 882: */ ! 883: for (; q_count < DEC_21X40_SETUP_PERFECT_ENTRIES; ++q_count) { ! 884: bcopy(setupBuffer->physicalAddress[0], ! 885: setupBuffer->physicalAddress[q_count], ! 886: 3 * sizeof (long)); ! 887: } ! 888: ! 889: if (![self _loadSetupFilter:pollingMode]) ! 890: status = NO; ! 891: ! 892: return status; ! 893: } ! 894: ! 895: ! 896: @end ! 897:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.