|
|
1.1 root 1: /*
2: * Copyright (c) 1998-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) 1998-1999 by Apple Computer, Inc., All rights reserved.
24: *
25: * Implementation for hardware dependent (relatively) code
26: * for the BMac Ethernet controller.
27: *
28: * HISTORY
29: *
30: */
31:
32: #include <IOKit/assert.h>
33: #include <IOKit/system.h>
34:
35: #include "BMacEnetPrivate.h"
36: #include <IOKit/IOLib.h>
37:
38: /*****************************************************************************
39: *
40: * Hacks.
41: */
42:
43: typedef unsigned long long ns_time_t; /* nanoseconds! */
44:
45: #define NSEC_PER_SEC 1000000000
46:
47: static void
48: _IOGetTimestamp(ns_time_t *nsp)
49: {
50: mach_timespec_t now;
51:
52: IOGetTime(&now);
53: *nsp = ((ns_time_t)now.tv_sec * NSEC_PER_SEC) + now.tv_nsec;
54: }
55:
56: /*
57: * Find a physical address (if any) for the specified virtual address.
58: *
59: * Note: what about vm_offset_t kvtophys(vm_offset_t va)
60: */
61: static IOReturn _IOPhysicalFromVirtual(
62: vm_address_t virtualAddress,
63: unsigned *physicalAddress)
64: {
65: *physicalAddress = pmap_extract(kernel_pmap, virtualAddress);
66: if(*physicalAddress == 0) {
67: return kIOReturnBadArgument;
68: }
69: else {
70: return kIOReturnSuccess;
71: }
72: }
73:
74: /****************************************************************************/
75:
76:
77: extern kern_return_t kmem_alloc_wired();
78:
79: static IODBDMADescriptor dbdmaCmd_Nop;
80: static IODBDMADescriptor dbdmaCmd_NopWInt;
81: static IODBDMADescriptor dbdmaCmd_LoadInt;
82: static IODBDMADescriptor dbdmaCmd_LoadIntWInt;
83: static IODBDMADescriptor dbdmaCmd_Stop;
84: static IODBDMADescriptor dbdmaCmd_Branch;
85:
86: static u_int8_t reverseBitOrder(u_int8_t data )
87: {
88: u_int8_t val = 0;
89: int i;
90:
91: for ( i=0; i < 8; i++ )
92: {
93: val <<= 1;
94: if (data & 1) val |= 1;
95: data >>= 1;
96: }
97: return( val );
98: }
99:
100: /*
101: * Function: IOMallocPage
102: *
103: * Purpose:
104: * Returns a pointer to a page-aligned memory block of size >= PAGE_SIZE
105: *
106: * Return:
107: * Actual pointer and size of block returned in actual_ptr and actual_size.
108: * Use these as arguments to kfree: kfree(*actual_ptr, *actual_size);
109: */
110: static void *
111: IOMallocPage(int request_size, void ** actual_ptr, u_int * actual_size)
112: {
113: void * mem_ptr;
114:
115: *actual_size = round_page(request_size) + PAGE_SIZE;
116: mem_ptr = IOMalloc(*actual_size);
117: if (mem_ptr == NULL)
118: return NULL;
119: *actual_ptr = mem_ptr;
120: return ((void *)round_page(mem_ptr));
121: }
122:
123: /*
124: * Private functions
125: */
126: bool BMacEnet::_allocateMemory()
127: {
128: u_int32_t i, n;
129: unsigned char * virtAddr;
130: u_int32_t physBase;
131: u_int32_t physAddr;
132: u_int32_t dbdmaSize;
133:
134: /*
135: * Calculate total space for DMA channel commands
136: */
137: dbdmaSize = round_page(
138: RX_RING_LENGTH * sizeof(enet_dma_cmd_t) +
139: TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) +
140: 2 * sizeof(IODBDMADescriptor) );
141:
142: /*
143: * Allocate required memory
144: */
145: dmaMemory.size = dbdmaSize;
146: dmaMemory.ptr = (void *)IOMallocPage(
147: dmaMemory.size,
148: &dmaMemory.ptrReal,
149: &dmaMemory.sizeReal
150: );
151:
152: dmaCommands = (unsigned char *) dmaMemory.ptr;
153: if (dmaCommands == NULL) {
154: IOLog( "Ethernet(BMac): Cant allocate channel DBDMA commands\n\r" );
155: return false;
156: }
157:
158: /*
159: * If we needed more than one page, then make sure we received
160: * contiguous memory.
161: */
162: n = (dbdmaSize - PAGE_SIZE) / PAGE_SIZE;
163: _IOPhysicalFromVirtual( (vm_address_t) dmaCommands, &physBase );
164:
165: virtAddr = (unsigned char *) dmaCommands;
166: for( i=0; i < n; i++, virtAddr += PAGE_SIZE )
167: {
168: _IOPhysicalFromVirtual( (vm_address_t) virtAddr, &physAddr );
169: if (physAddr != (physBase + i * PAGE_SIZE) )
170: {
171: IOLog( "Ethernet(BMac): Cannot allocate contiguous memory"
172: " for DBDMA commands\n\r" );
173: return false;
174: }
175: }
176:
177: /*
178: * Setup the receive ring pointers
179: */
180: rxDMACommands = (enet_dma_cmd_t *)dmaCommands;
181: rxMaxCommand = RX_RING_LENGTH;
182:
183: /*
184: * Setup the transmit ring pointers
185: */
186: txDMACommands = (enet_txdma_cmd_t *)(dmaCommands +
187: RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + sizeof(IODBDMADescriptor));
188: txMaxCommand = TX_RING_LENGTH;
189:
190: /*
191: * Setup pre-initialized DBDMA commands
192: */
193: IOMakeDBDMADescriptor( (&dbdmaCmd_Nop),
194: kdbdmaNop,
195: kdbdmaKeyStream0,
196: kdbdmaIntNever,
197: kdbdmaBranchNever,
198: kdbdmaWaitNever,
199: 0,
200: 0);
201:
202: IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt),
203: kdbdmaNop,
204: kdbdmaKeyStream0,
205: kdbdmaIntAlways,
206: kdbdmaBranchNever,
207: kdbdmaWaitNever,
208: 0,
209: 0);
210:
211: UInt32 ioBaseEnetPhys = maps[MEMORY_MAP_ENET_INDEX]->getPhysicalAddress();
212:
213: IOMakeDBDMADescriptor( (&dbdmaCmd_LoadInt),
214: kdbdmaLoadQuad,
215: kdbdmaKeySystem,
216: kdbdmaIntNever,
217: kdbdmaBranchNever,
218: kdbdmaWaitNever,
219: 2,
220: ((int)ioBaseEnetPhys + kSTAT) );
221:
222: IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntWInt),
223: kdbdmaLoadQuad,
224: kdbdmaKeySystem,
225: kdbdmaIntAlways,
226: kdbdmaBranchNever,
227: kdbdmaWaitNever,
228: 2,
229: ((int)ioBaseEnetPhys + kSTAT) );
230:
231: IOMakeDBDMADescriptor( (&dbdmaCmd_Stop),
232: kdbdmaStop,
233: kdbdmaKeyStream0,
234: kdbdmaIntNever,
235: kdbdmaBranchNever,
236: kdbdmaWaitNever,
237: 0,
238: 0);
239:
240: IOMakeDBDMADescriptor( (&dbdmaCmd_Branch),
241: kdbdmaNop,
242: kdbdmaKeyStream0,
243: kdbdmaIntNever,
244: kdbdmaBranchAlways,
245: kdbdmaWaitNever,
246: 0,
247: 0);
248:
249: return true;
250: }
251:
252: /*-------------------------------------------------------------------------
253: *
254: * Setup the Transmit Ring
255: * -----------------------
256: * Each transmit ring entry consists of two words to transmit data from buffer
257: * segments (possibly) spanning a page boundary. This is followed by two DMA
258: * commands which read transmit frame status and interrupt status from the Bmac
259: * chip. The last DMA command in each transmit ring entry generates a host
260: * interrupt. The last entry in the ring is followed by a DMA branch to the
261: * first entry.
262: *-------------------------------------------------------------------------*/
263:
264: bool BMacEnet::_initTxRing()
265: {
266: bool kr;
267: u_int32_t i;
268: IODBDMADescriptor dbdmaCmd, dbdmaCmdInt;
269:
270: /*
271: * Clear the transmit DMA command memory
272: */
273: bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand);
274: txCommandHead = 0;
275: txCommandTail = 0;
276:
277: /*
278: * DMA Channel commands 2 are the same for all DBDMA entries on transmit.
279: * Initialize them now.
280: */
281:
282: dbdmaCmd = ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? dbdmaCmd_Nop : dbdmaCmd_LoadInt;
283: dbdmaCmdInt = ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? dbdmaCmd_NopWInt : dbdmaCmd_LoadIntWInt;
284:
285: for( i=0; i < txMaxCommand; i++ )
286: {
287: txDMACommands[i].desc_seg[2] = ( (i+1) % TX_PKTS_PER_INT ) ? dbdmaCmd : dbdmaCmdInt;
288: }
289:
290: /*
291: * Put a DMA Branch command after the last entry in the transmit ring.
292: * Set the branch address to the physical address of the start of the
293: * transmit ring.
294: */
295: txDMACommands[txMaxCommand].desc_seg[0] = dbdmaCmd_Branch;
296:
297: kr = _IOPhysicalFromVirtual( (vm_address_t) txDMACommands,
298: (u_int32_t *)&txDMACommandsPhys );
299: if ( kr != kIOReturnSuccess )
300: {
301: IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r",
302: (u_int32_t)txDMACommands );
303: }
304: IOSetCCCmdDep( &txDMACommands[txMaxCommand].desc_seg[0],
305: txDMACommandsPhys );
306:
307: /*
308: * Set the Transmit DMA Channel pointer to the first entry in the
309: * transmit ring.
310: */
311: IOSetDBDMACommandPtr( ioBaseEnetTxDMA, txDMACommandsPhys );
312:
313: return true;
314: }
315:
316: /*-------------------------------------------------------------------------
317: *
318: * Setup the Receive ring
319: * ----------------------
320: * Each receive ring entry consists of two DMA commands to receive data
321: * into a network buffer (possibly) spanning a page boundary. The second
322: * DMA command in each entry generates a host interrupt.
323: * The last entry in the ring is followed by a DMA branch to the first
324: * entry.
325: *
326: *-------------------------------------------------------------------------*/
327:
328: bool BMacEnet::_initRxRing()
329: {
330: u_int32_t i;
331: bool status;
332: IOReturn kr;
333:
334: /*
335: * Clear the receive DMA command memory
336: */
337: bzero((void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand);
338:
339: kr = _IOPhysicalFromVirtual( (vm_address_t) rxDMACommands,
340: (u_int32_t *)&rxDMACommandsPhys );
341: if ( kr != kIOReturnSuccess )
342: {
343: IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r",
344: (u_int32_t)rxDMACommands );
345: return false;
346: }
347:
348: /*
349: * Allocate a receive buffer for each entry in the Receive ring
350: */
351: for (i = 0; i < rxMaxCommand-1; i++)
352: {
353: if (rxMbuf[i] == NULL)
354: {
355: rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE);
356: if (!rxMbuf[i])
357: {
358: IOLog("Ethernet(BMac): allocatePacket failed\n");
359: return false;
360: }
361: }
362:
363: /*
364: * Set the DMA commands for the ring entry to transfer data to the
365: * mbuf.
366: */
367: status = _updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true);
368: if (status == false)
369: {
370: IOLog("Ethernet(BMac): cannot map mbuf to physical memory in"
371: " _initRxRing\n\r");
372: return false;
373: }
374: }
375:
376: /*
377: * Set the receive queue head to point to the first entry in the ring.
378: * Set the receive queue tail to point to a DMA Stop command after the
379: * last ring entry
380: */
381: rxCommandHead = 0;
382: rxCommandTail = i;
383:
384: rxDMACommands[i].desc_seg[0] = dbdmaCmd_Stop;
385: rxDMACommands[i].desc_seg[1] = dbdmaCmd_Nop;
386:
387: /*
388: * Setup a DMA branch command after the stop command
389: */
390: i++;
391: rxDMACommands[i].desc_seg[0] = dbdmaCmd_Branch;
392:
393: IOSetCCCmdDep( &rxDMACommands[i].desc_seg[0], rxDMACommandsPhys );
394:
395: /*
396: * Set DMA command pointer to first receive entry
397: */
398: IOSetDBDMACommandPtr (ioBaseEnetRxDMA, rxDMACommandsPhys);
399:
400: return true;
401: }
402:
403: /*-------------------------------------------------------------------------
404: *
405: *
406: *
407: *-------------------------------------------------------------------------*/
408:
409: void BMacEnet::_startChip()
410: {
411: u_int16_t oldConfig;
412:
413: IODBDMAContinue( ioBaseEnetRxDMA );
414:
415: // turn on rx plus any other bits already on (promiscuous possibly)
416: oldConfig = ReadBigMacRegister(ioBaseEnet, kRXCFG);
417: WriteBigMacRegister(ioBaseEnet, kRXCFG, oldConfig | kRxMACEnable );
418:
419: oldConfig = ReadBigMacRegister(ioBaseEnet, kTXCFG);
420: WriteBigMacRegister(ioBaseEnet, kTXCFG, oldConfig | kTxMACEnable );
421: }
422:
423: /*-------------------------------------------------------------------------
424: *
425: *
426: *
427: *-------------------------------------------------------------------------*/
428:
429: void BMacEnet::_resetChip()
430: {
431: volatile u_int32_t *heathrowFCR;
432: u_int32_t fcrValue;
433: u_int16_t *pPhyType;
434:
435: IODBDMAReset( ioBaseEnetRxDMA );
436: IODBDMAReset( ioBaseEnetTxDMA );
437:
438: IOSetDBDMAWaitSelect( ioBaseEnetTxDMA,
439: IOSetDBDMAChannelControlBits( kdbdmaS5 ) );
440:
441: IOSetDBDMABranchSelect( ioBaseEnetRxDMA,
442: IOSetDBDMAChannelControlBits( kdbdmaS6 ) );
443:
444: IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA,
445: IOSetDBDMAChannelControlBits( kdbdmaS6 ) );
446:
447: heathrowFCR = (u_int32_t *)((u_int8_t *)ioBaseHeathrow + kHeathrowFCR);
448:
449: fcrValue = *heathrowFCR;
450: eieio();
451:
452: fcrValue = OSReadSwapInt32( &fcrValue, 0 );
453:
454: /*
455: * Enable the ethernet transceiver/clocks
456: */
457: fcrValue |= kEnetEnabledBits;
458: fcrValue &= ~kResetEnetCell;
459:
460: *heathrowFCR = OSReadSwapInt32( &fcrValue, 0 );
461: eieio();
462: IOSleep( 100 );
463:
464: /*
465: * Determine if PHY chip is configured. Reset and enable it (if present).
466: */
467: if ( phyId == 0xff )
468: {
469: phyMIIDelay = 20;
470: if ( miiFindPHY(&phyId) == true )
471: {
472: miiResetPHY(phyId);
473:
474: pPhyType = (u_int16_t *)&phyType;
475: miiReadWord(pPhyType, MII_ID0, phyId);
476: miiReadWord(pPhyType+1, MII_ID1, phyId);
477:
478: if ( (phyType & MII_ST10040_MASK) == MII_ST10040_ID )
479: {
480: phyMIIDelay = MII_ST10040_DELAY;
481: }
482: else if ( (phyType & MII_DP83843_MASK) == MII_DP83843_ID )
483: {
484: phyMIIDelay = MII_DP83843_DELAY;
485: }
486: }
487: }
488:
489: /*
490: * Reset the reset the ethernet cell
491: */
492: fcrValue |= kResetEnetCell;
493: *heathrowFCR = OSReadSwapInt32( &fcrValue, 0 );
494: eieio();
495: IOSleep( 10 );
496:
497: fcrValue &= ~kResetEnetCell;
498: *heathrowFCR = OSReadSwapInt32( &fcrValue, 0 );
499: eieio();
500: IOSleep( 10 );
501:
502: chipId = ReadBigMacRegister(ioBaseEnet, kCHIPID) & 0xFF;
503: }
504:
505: /*-------------------------------------------------------------------------
506: *
507: *
508: *
509: *-------------------------------------------------------------------------*/
510:
511: bool BMacEnet::_initChip()
512: {
513: volatile u_int16_t regValue;
514: ns_time_t timeStamp;
515: u_int16_t *pWord16;
516:
517: WriteBigMacRegister(ioBaseEnet, kTXRST, kTxResetBit);
518:
519: do
520: {
521: // wait for reset to clear..acknowledge
522: regValue = ReadBigMacRegister(ioBaseEnet, kTXRST);
523: }
524: while( regValue & kTxResetBit );
525:
526: WriteBigMacRegister(ioBaseEnet, kRXRST, kRxResetValue);
527:
528: if ( phyId == 0xff )
529: {
530: WriteBigMacRegister(ioBaseEnet, kXCVRIF,
531: kClkBit | kSerialMode | kCOLActiveLow);
532: }
533:
534: _IOGetTimestamp(&timeStamp);
535: WriteBigMacRegister(ioBaseEnet, kRSEED, (u_int16_t) timeStamp );
536:
537: regValue = ReadBigMacRegister(ioBaseEnet, kXIFC);
538: regValue |= kTxOutputEnable;
539: WriteBigMacRegister(ioBaseEnet, kXIFC, regValue);
540:
541: ReadBigMacRegister(ioBaseEnet, kPAREG);
542:
543: // set collision counters to 0
544: WriteBigMacRegister(ioBaseEnet, kNCCNT, 0);
545: WriteBigMacRegister(ioBaseEnet, kNTCNT, 0);
546: WriteBigMacRegister(ioBaseEnet, kEXCNT, 0);
547: WriteBigMacRegister(ioBaseEnet, kLTCNT, 0);
548:
549: // set rx counters to 0
550: WriteBigMacRegister(ioBaseEnet, kFRCNT, 0);
551: WriteBigMacRegister(ioBaseEnet, kLECNT, 0);
552: WriteBigMacRegister(ioBaseEnet, kAECNT, 0);
553: WriteBigMacRegister(ioBaseEnet, kFECNT, 0);
554: WriteBigMacRegister(ioBaseEnet, kRXCV, 0);
555:
556: // set tx fifo information
557: // 255 octets before tx starts
558: WriteBigMacRegister(ioBaseEnet, kTXTH, 0xff);
559:
560: // first disable txFIFO
561: WriteBigMacRegister(ioBaseEnet, kTXFIFOCSR, 0);
562: WriteBigMacRegister(ioBaseEnet, kTXFIFOCSR, kTxFIFOEnable );
563:
564: // set rx fifo information
565: // first disable rxFIFO
566: WriteBigMacRegister(ioBaseEnet, kRXFIFOCSR, 0);
567: WriteBigMacRegister(ioBaseEnet, kRXFIFOCSR, kRxFIFOEnable );
568:
569: // kTxNeverGiveUp maybe later
570: //WriteBigMacRegister(ioBaseEnet, kTXCFG, kTxMACEnable);
571: ReadBigMacRegister(ioBaseEnet, kSTAT); // read it just to clear it
572:
573: // zero out the chip Hash Filter registers
574: WriteBigMacRegister(ioBaseEnet, kHASH3, hashTableMask[0]); // bits 15 - 0
575: WriteBigMacRegister(ioBaseEnet, kHASH2, hashTableMask[1]); // bits 31 - 16
576: WriteBigMacRegister(ioBaseEnet, kHASH1, hashTableMask[2]); // bits 47 - 32
577: WriteBigMacRegister(ioBaseEnet, kHASH0, hashTableMask[3]); // bits 63 - 48
578:
579: pWord16 = (u_int16_t *)&myAddress.ea_byte[0];
580: WriteBigMacRegister(ioBaseEnet, kMADD0, *pWord16++);
581: WriteBigMacRegister(ioBaseEnet, kMADD1, *pWord16++);
582: WriteBigMacRegister(ioBaseEnet, kMADD2, *pWord16);
583:
584: WriteBigMacRegister(ioBaseEnet, kRXCFG,
585: kRxCRCEnable | kRxHashFilterEnable | kRxRejectOwnPackets);
586:
587: return true;
588: }
589:
590: /*-------------------------------------------------------------------------
591: *
592: *
593: *
594: *-------------------------------------------------------------------------*/
595:
596: void BMacEnet::_disableAdapterInterrupts()
597: {
598: WriteBigMacRegister( ioBaseEnet, kINTDISABLE, kNoEventsMask );
599: }
600:
601: /*-------------------------------------------------------------------------
602: *
603: *
604: *
605: *-------------------------------------------------------------------------*/
606:
607: void BMacEnet::_enableAdapterInterrupts()
608: {
609: WriteBigMacRegister( ioBaseEnet,
610: kINTDISABLE,
611: ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ?
612: kNoEventsMask: kNormalIntEvents );
613: }
614:
615: /*-------------------------------------------------------------------------
616: *
617: *
618: *
619: *-------------------------------------------------------------------------*/
620:
621: void BMacEnet::_setDuplexMode(bool duplexMode)
622: {
623: u_int16_t txCFGVal;
624:
625: isFullDuplex = duplexMode;
626:
627: txCFGVal = ReadBigMacRegister( ioBaseEnet, kTXCFG);
628:
629: WriteBigMacRegister( ioBaseEnet, kTXCFG, txCFGVal & ~kTxMACEnable );
630: while( ReadBigMacRegister(ioBaseEnet, kTXCFG) & kTxMACEnable )
631: ;
632:
633: if ( isFullDuplex )
634: {
635: txCFGVal |= (kTxIgnoreCollision | kTxFullDuplex);
636: }
637: else
638: {
639: txCFGVal &= ~(kTxIgnoreCollision | kTxFullDuplex);
640: }
641:
642: WriteBigMacRegister( ioBaseEnet, kTXCFG, txCFGVal );
643: }
644:
645: /*-------------------------------------------------------------------------
646: *
647: *
648: *
649: *-------------------------------------------------------------------------*/
650:
651: void BMacEnet::_restartTransmitter()
652: {
653: u_int16_t regValue;
654:
655: /*
656: * Shutdown DMA channel
657: */
658: _stopTransmitDMA();
659:
660: /*
661: * Get the silicon's attention
662: */
663: WriteBigMacRegister( ioBaseEnet, kTXFIFOCSR, 0 );
664: WriteBigMacRegister( ioBaseEnet, kTXFIFOCSR, kTxFIFOEnable);
665:
666: ReadBigMacRegister( ioBaseEnet, kSTAT );
667:
668: regValue = ReadBigMacRegister(ioBaseEnet, kTXCFG);
669: WriteBigMacRegister(ioBaseEnet, kTXCFG, regValue | kTxMACEnable );
670:
671: /*
672: * Restart transmit DMA
673: */
674: IODBDMAContinue( ioBaseEnetTxDMA );
675: }
676:
677: /*-------------------------------------------------------------------------
678: *
679: *
680: *
681: *-------------------------------------------------------------------------*/
682:
683: void BMacEnet::_restartReceiver()
684: {
685: u_int16_t oldConfig;
686:
687: /*
688: * Shutdown DMA channel
689: */
690: _stopReceiveDMA();
691:
692: /*
693: * Get the silicon's attention
694: */
695: WriteBigMacRegister( ioBaseEnet, kRXFIFOCSR, 0 );
696: WriteBigMacRegister( ioBaseEnet, kRXFIFOCSR, kRxFIFOEnable);
697:
698: oldConfig = ReadBigMacRegister(ioBaseEnet, kRXCFG);
699: WriteBigMacRegister(ioBaseEnet, kRXCFG, oldConfig | kRxMACEnable );
700:
701: /*
702: * Restart receive DMA
703: */
704: IODBDMAContinue( ioBaseEnetRxDMA );
705: }
706:
707: /*-------------------------------------------------------------------------
708: *
709: * Orderly stop of receive DMA.
710: *
711: *
712: *-------------------------------------------------------------------------*/
713:
714: void BMacEnet::_stopReceiveDMA()
715: {
716: u_int32_t dmaCmdPtr;
717: u_int8_t rxCFGVal;
718:
719: /*
720: * Stop the receiver and allow any frame receive in progress to complete.
721: */
722: rxCFGVal = ReadBigMacRegister(ioBaseEnet, kRXCFG);
723: WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGVal & ~kRxMACEnable );
724: IODelay( RECEIVE_QUIESCE_uS );
725:
726: IODBDMAReset( ioBaseEnetRxDMA );
727:
728: dmaCmdPtr = rxDMACommandsPhys + rxCommandHead * sizeof(enet_dma_cmd_t);
729: IOSetDBDMACommandPtr( ioBaseEnetRxDMA, dmaCmdPtr );
730: }
731:
732: /*-------------------------------------------------------------------------
733: *
734: *
735: *
736: *-------------------------------------------------------------------------*/
737:
738: void BMacEnet::_stopTransmitDMA()
739: {
740: u_int32_t dmaCmdPtr;
741: u_int8_t txCFGVal;
742:
743: /*
744: * Stop the transmitter and allow any frame transmit in progress to abort
745: */
746: txCFGVal = ReadBigMacRegister(ioBaseEnet, kTXCFG);
747: WriteBigMacRegister(ioBaseEnet, kTXCFG, txCFGVal & ~kTxMACEnable );
748:
749: IODelay( TRANSMIT_QUIESCE_uS );
750:
751: IODBDMAReset( ioBaseEnetTxDMA );
752:
753: dmaCmdPtr = txDMACommandsPhys + txCommandHead * sizeof(enet_txdma_cmd_t);
754: IOSetDBDMACommandPtr( ioBaseEnetTxDMA, dmaCmdPtr );
755: }
756:
757: /*-------------------------------------------------------------------------
758: *
759: *
760: *
761: *-------------------------------------------------------------------------*/
762:
763: bool BMacEnet::_transmitPacket(struct mbuf *packet)
764: {
765: enet_dma_cmd_t tmpCommand;
766: u_int32_t i;
767:
768: /*
769: * Check for room on the transmit ring. There should always be space
770: * since it is the responsibility of the caller to verify this before
771: * calling _transmitPacket.
772: *
773: * Get a copy of the DMA transfer commands in a temporary buffer.
774: * The new DMA command is written into the channel program so that the
775: * command word for the old Stop command is overwritten last. This prevents
776: * the DMA engine from executing a partially written channel command.
777: */
778: i = txCommandTail + 1;
779: if ( i >= txMaxCommand ) i = 0;
780:
781: if ( (i == txCommandHead) ||
782: !_updateDescriptorFromMbuf(packet, &tmpCommand, false) )
783: {
784: IOLog("Ethernet(BMac): Freeing transmit packet eh?\n\r");
785: if (packet != txDebuggerPkt)
786: freePacket(packet);
787: return false;
788: }
789:
790: /*
791: * txCommandTail points to the current DMA Stop command for the channel.
792: * We are now creating a new DMA Stop command in the next slot in the
793: * transmit ring. The previous DMA Stop command will be overwritten with
794: * the DMA commands to transfer the new mbuf.
795: */
796: txDMACommands[i].desc_seg[0] = dbdmaCmd_Stop;
797: txDMACommands[i].desc_seg[1] = dbdmaCmd_Nop;
798:
799: bcopy( ((u_int32_t *)&tmpCommand)+1,
800: ((u_int32_t *)&txDMACommands[txCommandTail])+1,
801: sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) );
802:
803: txMbuf[txCommandTail] = packet;
804: txDMACommands[txCommandTail].desc_seg[0].operation =
805: tmpCommand.desc_seg[0].operation;
806:
807: /*
808: * Set the transmit tail to the new stop command.
809: */
810: txCommandTail = i;
811:
812: /*
813: * Tap the DMA channel to wake it up
814: */
815: IODBDMAContinue( ioBaseEnetTxDMA );
816:
817: return true;
818: }
819:
820: /*-------------------------------------------------------------------------
821: * _receivePacket
822: * --------------
823: * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger.
824: *
825: * The _receivePackets allocate NetBufs and pass them up the stack. The kernel
826: * debugger interface passes a buffer into us. To reconsile the two interfaces,
827: * we allow the receive routine to continue to allocate its own buffers and
828: * transfer any received data to the passed-in buffer. This is handled by
829: * _receivePacket calling _packetToDebugger.
830: *-------------------------------------------------------------------------*/
831:
832: void BMacEnet::_receivePacket(void *pkt, unsigned int *pkt_len,
833: unsigned int timeout)
834: {
835: ns_time_t startTime;
836: ns_time_t currentTime;
837: u_int32_t elapsedTimeMS;
838:
839: if (!ready || !pkt || !pkt_len)
840: return;
841:
842: *pkt_len = 0;
843:
844: debuggerPkt = pkt;
845: debuggerPktSize = 0;
846:
847: _IOGetTimestamp(&startTime);
848: do
849: {
850: _receivePackets(true);
851: _IOGetTimestamp(¤tTime);
852: elapsedTimeMS = (currentTime - startTime) / (1000*1000);
853: }
854: while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) );
855:
856: *pkt_len = debuggerPktSize;
857: }
858:
859: /*-------------------------------------------------------------------------
860: * _packetToDebugger
861: * -----------------
862: * This is called by _receivePackets when we are polling for kernel debugger
863: * packets. It copies the NetBuf contents to the buffer passed by the debugger.
864: * It also sets the var debuggerPktSize which will break the polling loop.
865: *-------------------------------------------------------------------------*/
866:
867: void BMacEnet::_packetToDebugger(struct mbuf * packet, u_int size)
868: {
869: debuggerPktSize = size;
870: bcopy( mtod(packet, char *), debuggerPkt, size );
871: }
872:
873: /*-------------------------------------------------------------------------
874: * _sendPacket
875: * -----------
876: *
877: * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger.
878: *
879: *-------------------------------------------------------------------------*/
880:
881: void BMacEnet::_sendPacket(void *pkt, unsigned int pkt_len)
882: {
883: ns_time_t startTime;
884: ns_time_t currentTime;
885: u_int32_t elapsedTimeMS;
886:
887: if (!ready || !pkt || (pkt_len > ETHERMAXPACKET))
888: return;
889:
890: /*
891: * Wait for the transmit ring to empty
892: */
893: _IOGetTimestamp(&startTime);
894: do
895: {
896: _debugTransmitInterruptOccurred();
897: _IOGetTimestamp(¤tTime);
898: elapsedTimeMS = (currentTime - startTime) / (1000*1000);
899: }
900: while ( (txCommandHead != txCommandTail) &&
901: (elapsedTimeMS < TX_KDB_TIMEOUT) );
902:
903: if ( txCommandHead != txCommandTail )
904: {
905: IOLog( "Ethernet(BMac): Polled tranmit timeout - 1\n\r");
906: return;
907: }
908:
909: /*
910: * Allocate a NetBuf and copy the debugger transmit data into it.
911: *
912: * jliu - no allocation, just recycle the same buffer dedicated to
913: * KDB transmit.
914: */
915: txDebuggerPkt->m_next = 0;
916: txDebuggerPkt->m_data = (caddr_t) pkt;
917: txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len;
918:
919: /*
920: * Send the debugger packet. txDebuggerPkt must not be freed by
921: * the transmit routine.
922: */
923: _transmitPacket(txDebuggerPkt);
924:
925: /*
926: * Poll waiting for the transmit ring to empty again
927: */
928: do
929: {
930: _debugTransmitInterruptOccurred();
931: _IOGetTimestamp(¤tTime);
932: elapsedTimeMS = (currentTime - startTime) / (1000*1000);
933: }
934: while ( (txCommandHead != txCommandTail) &&
935: (elapsedTimeMS < TX_KDB_TIMEOUT) );
936:
937: if ( txCommandHead != txCommandTail )
938: {
939: IOLog( "Ethernet(BMac): Polled tranmit timeout - 2\n\r");
940: }
941:
942: return;
943: }
944:
945: /*-------------------------------------------------------------------------
946: * _sendDummyPacket
947: * ----------------
948: * The BMac receiver seems to be locked until we send our first packet.
949: *
950: *-------------------------------------------------------------------------*/
951: void BMacEnet::_sendDummyPacket()
952: {
953: union
954: {
955: u_int8_t bytes[64];
956: enet_addr_t enet_addr[2];
957: } dummyPacket;
958:
959: bzero( &dummyPacket, sizeof(dummyPacket) );
960: dummyPacket.enet_addr[0] = myAddress;
961: dummyPacket.enet_addr[1] = myAddress;
962: _sendPacket((void *)dummyPacket.bytes, sizeof(dummyPacket));
963: IOSleep(50);
964: }
965:
966: /*-------------------------------------------------------------------------
967: *
968: *
969: *
970: *-------------------------------------------------------------------------*/
971:
972: bool BMacEnet::_receiveInterruptOccurred()
973: {
974: return _receivePackets(false);
975: }
976:
977: /*-------------------------------------------------------------------------
978: * Work around a hardware bug where the controller will receive
979: * unicast packets not directed to the station. The hardware is
980: * erroneously using the hash table to qualify the unicast address.
981: * This routine will check that the packet is unicast, and if so,
982: * makes sure that the unicast address matches the station's address.
983: * Thus function returns true if the packet should be rejected.
984: *-------------------------------------------------------------------------*/
985:
986: bool BMacEnet::_rejectBadUnicastPacket(ether_header_t * etherHeader)
987: {
988: bool rejectPacket = false;
989:
990: if ( useUnicastFilter &&
991: (etherHeader->ether_dhost[EA_GROUP_BYTE] & EA_GROUP_BIT) == 0) {
992: //
993: // Destination Ethernet address is not multicast nor broadcast.
994: // Then it must be addresses to the station MAC address,
995: // otherwise reject the packet.
996: //
997: if (bcmp(etherHeader->ether_dhost, &myAddress, NUM_EN_ADDR_BYTES) != 0)
998: rejectPacket = true;
999: }
1000:
1001: return rejectPacket;
1002: }
1003:
1004: /*-------------------------------------------------------------------------
1005: *
1006: *
1007: *
1008: *-------------------------------------------------------------------------*/
1009:
1010: bool BMacEnet::_receivePackets(bool fDebugger)
1011: {
1012: enet_dma_cmd_t tmpCommand;
1013: struct mbuf * packet;
1014: u_int32_t i, j, last;
1015: int receivedFrameSize = 0;
1016: u_int32_t dmaCount[2], dmaResid[2], dmaStatus[2];
1017: u_int32_t dmaChnlStatus;
1018: u_int16_t rxPktStatus = 0;
1019: u_int32_t badFrameCount;
1020: bool reusePkt;
1021: bool status;
1022: bool useNetif = !fDebugger && netifClient;
1023: bool doFlushQueue = false;
1024: u_int32_t nextDesc;
1025: static const u_int32_t lastResetValue = (u_int32_t)(-1);
1026:
1027: last = lastResetValue;
1028: i = rxCommandHead;
1029:
1030: while ( 1 )
1031: {
1032: reusePkt = false;
1033:
1034: /*
1035: * Collect the DMA residual counts/status for the two
1036: * buffer segments.
1037: */
1038: for ( j = 0; j < 2; j++ )
1039: {
1040: dmaResid[j] = IOGetCCResult( &rxDMACommands[i].desc_seg[j] );
1041: dmaStatus[j] = dmaResid[j] >> 16;
1042: dmaResid[j] &= 0x0000ffff;
1043: dmaCount[j] = IOGetCCOperation( &rxDMACommands[i].desc_seg[j] )
1044: & kdbdmaReqCountMask;
1045: }
1046:
1047: #if 0
1048: IOLog("Ethernet(BMac): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r",
1049: i, (int)nb_map(rxNetbuf[i]), dmaResid[0], dmaStatus[0], dmaResid[1], dmaStatus[1] );
1050: #endif
1051:
1052: /*
1053: * If the current entry has not been written, then stop at this entry
1054: */
1055: if ( !((dmaStatus[0] & kdbdmaBt) || (dmaStatus[1] & kdbdmaActive)) )
1056: {
1057: break;
1058: }
1059:
1060: /*
1061: * The BMac Ethernet controller appends two bytes to each receive
1062: * buffer containing the buffer
1063: * size and receive frame status.
1064: * We locate these bytes by using the DMA residual counts.
1065: */
1066: receivedFrameSize = dmaCount[0] - dmaResid[0] + dmaCount[1] -
1067: ((dmaStatus[0] & kdbdmaBt) ? dmaCount[1] : dmaResid[1]);
1068:
1069: if ( ( receivedFrameSize >= 2 ) &&
1070: ( receivedFrameSize <= NETWORK_BUFSIZE ) )
1071: {
1072: /*
1073: * Get the receive frame size as reported by the BMac controller
1074: */
1075: rxPktStatus = *(u_int16_t *)(mtod(rxMbuf[i], u_int32_t) +
1076: receivedFrameSize - 2);
1077: receivedFrameSize = rxPktStatus & kRxLengthMask;
1078: }
1079:
1080: /*
1081: * Reject packets that are runts or that have other mutations.
1082: */
1083: if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) ||
1084: receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) ||
1085: rxPktStatus & kRxAbortBit ||
1086: _rejectBadUnicastPacket(mtod(rxMbuf[i], ether_header_t *))
1087: )
1088: {
1089: if (useNetif) netStats->inputErrors++;
1090: reusePkt = true;
1091: }
1092: else if ( useNetif == false )
1093: {
1094: /*
1095: * Always reuse packets in debugger mode. We also refuse to
1096: * pass anything up the stack unless the driver is open. The
1097: * hardware is enabled before the stack has opened us, to
1098: * allow earlier debug interface registration. But we must
1099: * not pass any packets up.
1100: */
1101: reusePkt = true;
1102: if (fDebugger)
1103: _packetToDebugger(rxMbuf[i], receivedFrameSize);
1104: }
1105:
1106: /*
1107: * Before we pass this packet up the networking stack. Make sure we
1108: * can get a replacement. Otherwise, hold on to the current packet and
1109: * increment the input error count.
1110: * Thanks Justin!
1111: */
1112:
1113: packet = 0;
1114:
1115: if ( reusePkt == false )
1116: {
1117: bool replaced;
1118:
1119: packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize,
1120: &replaced);
1121:
1122: reusePkt = true;
1123:
1124: if (packet && replaced)
1125: {
1126: status = _updateDescriptorFromMbuf(rxMbuf[i],
1127: &rxDMACommands[i], true);
1128:
1129: if (status)
1130: {
1131: reusePkt = false;
1132: }
1133: else
1134: {
1135: // Assume descriptor has not been corrupted.
1136: freePacket(rxMbuf[i]); // release new packet.
1137: rxMbuf[i] = packet; // get the old packet back.
1138: packet = 0; // pass up nothing.
1139: IOLog("Ethernet(BMac): _updateDescriptorFromMbuf error\n");
1140: }
1141: }
1142:
1143: if (packet == 0)
1144: netStats->inputErrors++;
1145: }
1146:
1147: /*
1148: * If we are reusing the existing mbuf, then refurbish the existing
1149: * DMA command \ descriptors by clearing the status/residual count
1150: * fields.
1151: */
1152: if ( reusePkt )
1153: {
1154: for ( j=0; j < sizeof(enet_dma_cmd_t)/sizeof(IODBDMADescriptor);
1155: j++ )
1156: {
1157: IOSetCCResult( &rxDMACommands[i].desc_seg[j], 0 );
1158: }
1159: }
1160:
1161: /*
1162: * Keep track of the last receive descriptor processed
1163: */
1164: last = i;
1165:
1166: /*
1167: * Implement ring wrap-around
1168: */
1169: if (++i >= rxMaxCommand) i = 0;
1170:
1171: if (fDebugger)
1172: {
1173: break;
1174: }
1175:
1176: /*
1177: * Transfer received packet to network
1178: */
1179: if (packet)
1180: {
1181: KERNEL_DEBUG(DBG_BMAC_RXCOMPLETE | DBG_FUNC_NONE, (int) packet,
1182: (int)receivedFrameSize, 0, 0, 0 );
1183:
1184: networkInterface->inputPacket(packet, receivedFrameSize, true);
1185: doFlushQueue = true;
1186: netStats->inputPackets++;
1187: }
1188: }
1189:
1190: /*
1191: * OK...this is a little messy
1192: *
1193: * We just processed a bunch of DMA receive descriptors. We are going to
1194: * exchange the current DMA stop command (rxCommandTail) with the last
1195: * receive descriptor we processed (last). This will make these list of
1196: * descriptors we just processed available. If we processed no receive
1197: * descriptors on this call then skip this exchange.
1198: */
1199:
1200: #if 0
1201: IOLog( "Ethernet(BMac): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last );
1202: #endif
1203:
1204: if ( last != lastResetValue )
1205: {
1206: /*
1207: * Save the contents of the last receive descriptor processed.
1208: */
1209: packet = rxMbuf[last];
1210: tmpCommand = rxDMACommands[last];
1211:
1212: /*
1213: * Write a DMA stop command into this descriptor slot
1214: */
1215: rxDMACommands[last].desc_seg[0] = dbdmaCmd_Stop;
1216: rxDMACommands[last].desc_seg[1] = dbdmaCmd_Nop;
1217: rxMbuf[last] = 0;
1218:
1219: /*
1220: * Replace the previous DMA stop command with the last receive
1221: * descriptor processed.
1222: *
1223: * The new DMA command is written into the channel program so that the
1224: * command word for the old Stop command is overwritten last. This
1225: * prevents the DMA engine from executing a partially written channel
1226: * command.
1227: *
1228: * Note: When relocating the descriptor, we must update its branch
1229: * field to reflect its new location.
1230: */
1231: nextDesc = rxDMACommandsPhys +
1232: (int) &rxDMACommands[rxCommandTail + 1] - (int)rxDMACommands;
1233: IOSetCCCmdDep( &tmpCommand.desc_seg[0], nextDesc );
1234:
1235: bcopy( (u_int32_t *) &tmpCommand + 1,
1236: (u_int32_t *) &rxDMACommands[rxCommandTail] + 1,
1237: sizeof(enet_dma_cmd_t) - sizeof(u_int32_t) );
1238:
1239: rxMbuf[rxCommandTail] = packet;
1240:
1241: rxDMACommands[rxCommandTail].desc_seg[0].operation =
1242: tmpCommand.desc_seg[0].operation;
1243:
1244: /*
1245: * Update rxCommmandTail to point to the new Stop command. Update
1246: * rxCommandHead to point to the next slot in the ring past the Stop
1247: * command
1248: */
1249: rxCommandTail = last;
1250: rxCommandHead = i;
1251: }
1252:
1253: /*
1254: * Update receive error statistics
1255: */
1256: badFrameCount = ReadBigMacRegister(ioBaseEnet, kFECNT)
1257: + ReadBigMacRegister(ioBaseEnet, kAECNT)
1258: + ReadBigMacRegister(ioBaseEnet, kLECNT);
1259:
1260: /*
1261: * Clear Hardware counters
1262: */
1263: WriteBigMacRegister(ioBaseEnet, kFECNT, 0);
1264: WriteBigMacRegister(ioBaseEnet, kAECNT, 0);
1265: WriteBigMacRegister(ioBaseEnet, kLECNT, 0);
1266:
1267: if (badFrameCount && useNetif)
1268: netStats->inputErrors += badFrameCount;
1269:
1270: /*
1271: * Check for error conditions that may cause the receiver to stall
1272: */
1273: dmaChnlStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA );
1274:
1275: if ( dmaChnlStatus & kdbdmaDead )
1276: {
1277: if (useNetif) netStats->inputErrors++;
1278: IOLog( "Ethernet(BMac): Rx DMA Error - Status = %04x\n\r",
1279: dmaChnlStatus );
1280: _restartReceiver();
1281: }
1282: else
1283: {
1284: /*
1285: * Tap the DMA to wake it up
1286: */
1287: IODBDMAContinue( ioBaseEnetRxDMA );
1288: }
1289:
1290: #if 0
1291: IOLog( "Ethernet(BMac): New - Rx Head = %2d Rx Tail = %2d\n\r", rxCommandHead, rxCommandTail );
1292: #endif
1293:
1294: return doFlushQueue;
1295: }
1296:
1297: /*-------------------------------------------------------------------------
1298: *
1299: *
1300: *
1301: *-------------------------------------------------------------------------*/
1302:
1303: bool BMacEnet::_transmitInterruptOccurred()
1304: {
1305: u_int32_t dmaStatus;
1306: u_int32_t collisionCount;
1307: u_int32_t badFrameCount;
1308: bool fServiced = false;
1309:
1310: while ( 1 )
1311: {
1312: /*
1313: * Check the status of the last descriptor in this entry to see if
1314: * the DMA engine completed this entry.
1315: */
1316: dmaStatus = IOGetCCResult(
1317: &(txDMACommands[txCommandHead].desc_seg[1])) >> 16;
1318:
1319: if ( !(dmaStatus & kdbdmaActive) )
1320: {
1321: break;
1322: }
1323:
1324: if (netifClient) netStats->outputPackets++;
1325:
1326: fServiced = true;
1327:
1328: KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE | DBG_FUNC_NONE,
1329: (int)txMbuf[txCommandHead],
1330: (int)txMbuf[txCommandHead]->m_pkthdr.len, 0, 0, 0 );
1331:
1332: /*
1333: * Free the mbuf we just transmitted.
1334: *
1335: * If it is the debugger packet, just remove it from the ring.
1336: * and reuse the same packet for the next sendPacket() request.
1337: */
1338: if (txMbuf[txCommandHead] != txDebuggerPkt)
1339: {
1340: freePacket( txMbuf[txCommandHead] );
1341: }
1342: txMbuf[txCommandHead] = NULL;
1343:
1344: if ( ++(txCommandHead) >= txMaxCommand )
1345: txCommandHead = 0;
1346: }
1347:
1348: /*
1349: * Increment transmit error statistics
1350: */
1351: collisionCount = ReadBigMacRegister(ioBaseEnet, kNCCNT );
1352:
1353: WriteBigMacRegister( ioBaseEnet, kNCCNT, 0 );
1354:
1355: badFrameCount = ReadBigMacRegister(ioBaseEnet, kEXCNT )
1356: + ReadBigMacRegister(ioBaseEnet, kLTCNT );
1357:
1358: WriteBigMacRegister( ioBaseEnet, kEXCNT, 0 );
1359: WriteBigMacRegister( ioBaseEnet, kLTCNT, 0 );
1360:
1361: if (netifClient) {
1362: netStats->collisions += collisionCount;
1363: netStats->outputErrors += badFrameCount;
1364: }
1365:
1366: /*
1367: * Check for error conditions that may cause the transmitter to stall
1368: */
1369: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA );
1370:
1371: if ( dmaStatus & kdbdmaDead )
1372: {
1373: if (netifClient) netStats->outputErrors++;
1374: IOLog( "Ethernet(BMac): Tx DMA Error - Status = %04x\n\r", dmaStatus );
1375: _restartTransmitter();
1376: fServiced = true;
1377: }
1378:
1379: return fServiced;
1380: }
1381:
1382: /*-------------------------------------------------------------------------
1383: *
1384: *
1385: *
1386: *-------------------------------------------------------------------------*/
1387:
1388: bool BMacEnet::_debugTransmitInterruptOccurred()
1389: {
1390: u_int32_t dmaStatus;
1391: u_int32_t badFrameCount;
1392: bool fServiced = false;
1393:
1394: // Set the debugTxPoll flag to indicate the debugger was active
1395: // and some cleanup may be needed when the driver returns to
1396: // normal operation.
1397: //
1398: debugTxPoll = true;
1399:
1400: while ( 1 )
1401: {
1402: /*
1403: * Check the status of the last descriptor in this entry to see if
1404: * the DMA engine completed this entry.
1405: */
1406: dmaStatus = IOGetCCResult(
1407: &(txDMACommands[txCommandHead].desc_seg[1])) >> 16;
1408:
1409: if ( !(dmaStatus & kdbdmaActive) )
1410: {
1411: break;
1412: }
1413:
1414: fServiced = true;
1415:
1416: KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE | DBG_FUNC_NONE,
1417: (int)txMbuf[txCommandHead],
1418: (int)txMbuf[txCommandHead]->m_pkthdr.len, 0, 0, 0 );
1419:
1420: /*
1421: * Free the mbuf we just transmitted.
1422: *
1423: * If it is the debugger packet, just remove it from the ring.
1424: * and reuse the same packet for the next sendPacket() request.
1425: */
1426: if (txMbuf[txCommandHead] != txDebuggerPkt) {
1427: //
1428: // While in debugger mode, do not touch the mbuf pool.
1429: // Queue any used mbufs to a local queue. This queue
1430: // will get flushed after we exit from debugger mode.
1431: //
1432: // During continuous debugger transmission and
1433: // interrupt polling, we expect only the txDebuggerPkt
1434: // to show up on the transmit mbuf ring.
1435: //
1436: debugQueue->enqueue( txMbuf[txCommandHead] );
1437: }
1438: txMbuf[txCommandHead] = NULL;
1439:
1440: if ( ++(txCommandHead) >= txMaxCommand )
1441: txCommandHead = 0;
1442: }
1443:
1444: /*
1445: * Clear transmit error statistics
1446: */
1447: badFrameCount = ReadBigMacRegister(ioBaseEnet, kNCCNT );
1448: WriteBigMacRegister( ioBaseEnet, kNCCNT, 0 );
1449:
1450: badFrameCount = ReadBigMacRegister(ioBaseEnet, kEXCNT )
1451: + ReadBigMacRegister(ioBaseEnet, kLTCNT );
1452: WriteBigMacRegister( ioBaseEnet, kEXCNT, 0 );
1453: WriteBigMacRegister( ioBaseEnet, kLTCNT, 0 );
1454:
1455: /*
1456: * Check for error conditions that may cause the transmitter to stall
1457: */
1458: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA );
1459:
1460: if ( dmaStatus & kdbdmaDead )
1461: {
1462: IOLog( "Ethernet(BMac): Tx DMA Error - Status = %04x\n\r", dmaStatus );
1463: _restartTransmitter();
1464: fServiced = true;
1465: }
1466:
1467: return fServiced;
1468: }
1469:
1470: /*-------------------------------------------------------------------------
1471: *
1472: *
1473: *
1474: *-------------------------------------------------------------------------*/
1475:
1476: bool
1477: BMacEnet::_updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc,
1478: bool isReceive)
1479: {
1480: u_int32_t nextDesc = 0;
1481: u_int32_t waitMask = 0;
1482: int segments;
1483: struct IOPhysicalSegment segVector[2];
1484:
1485: segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector);
1486:
1487: if ((!segments) || (segments > 2)) {
1488: IOLog("BMac: _updateDescriptorFromMbuf error, %d segments\n",
1489: segments);
1490: return false;
1491: }
1492:
1493: // IOLog("segments: %d\n", segments);
1494:
1495: if ( isReceive || chipId >= kCHIPID_PaddingtonXmitStreaming )
1496: {
1497: waitMask = kdbdmaWaitNever;
1498: }
1499: else
1500: {
1501: waitMask = kdbdmaWaitIfFalse;
1502: }
1503:
1504: if ( segments == 1 )
1505: {
1506: IOMakeDBDMADescriptor( (&desc->desc_seg[0]),
1507: ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast),
1508: (kdbdmaKeyStream0),
1509: (kdbdmaIntNever),
1510: (kdbdmaBranchNever),
1511: (waitMask),
1512: (segVector[0].length),
1513: (segVector[0].location) );
1514:
1515: desc->desc_seg[1] = (isReceive) ? dbdmaCmd_NopWInt : dbdmaCmd_Nop;
1516: }
1517: else
1518: {
1519: if ( isReceive )
1520: {
1521: nextDesc = rxDMACommandsPhys + (int)desc - (int)rxDMACommands +
1522: sizeof(enet_dma_cmd_t);
1523: }
1524:
1525: IOMakeDBDMADescriptorDep( (&desc->desc_seg[0]),
1526: ((isReceive) ? kdbdmaInputMore : kdbdmaOutputMore),
1527: (kdbdmaKeyStream0),
1528: ((isReceive) ? kdbdmaIntIfTrue : kdbdmaIntNever),
1529: ((isReceive) ? kdbdmaBranchIfTrue :
1530: kdbdmaBranchNever),
1531: (kdbdmaWaitNever),
1532: (segVector[0].length),
1533: (segVector[0].location),
1534: nextDesc );
1535:
1536: IOMakeDBDMADescriptor( (&desc->desc_seg[1]),
1537: ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast),
1538: (kdbdmaKeyStream0),
1539: ((isReceive) ? kdbdmaIntAlways : kdbdmaIntNever),
1540: (kdbdmaBranchNever),
1541: (waitMask),
1542: (segVector[1].length),
1543: (segVector[1].location) );
1544: }
1545:
1546: return true;
1547: }
1548:
1549: #ifdef DEBUG
1550: /*
1551: * Useful for testing.
1552: */
1553: void BMacEnet::_dump_srom()
1554: {
1555: unsigned short data;
1556: int i;
1557:
1558: for (i = 0; i < 128; i++)
1559: {
1560: reset_and_select_srom(ioBaseEnet);
1561: data = read_srom(ioBaseEnet, i, sromAddressBits);
1562: IOLog("Ethernet(BMac): %x = %x ", i, data);
1563: if (i % 10 == 0) IOLog("\n");
1564: }
1565: }
1566:
1567: void BMacEnet::_dumpDesc(void * addr, u_int32_t size)
1568: {
1569: u_int32_t i;
1570: unsigned long *p;
1571: vm_offset_t paddr;
1572:
1573: _IOPhysicalFromVirtual( (vm_offset_t) addr, (vm_offset_t *)&paddr );
1574:
1575: p = (unsigned long *)addr;
1576:
1577: for ( i=0; i < size/sizeof(IODBDMADescriptor); i++, p+=4,
1578: paddr+=sizeof(IODBDMADescriptor) )
1579: {
1580: IOLog("Ethernet(BMac): %08x(v) %08x(p): %08x %08x %08x %08x\n\r",
1581: (int)p,
1582: (int)paddr,
1583: (int)OSReadSwapInt32(p, 0), (int)OSReadSwapInt32(p, 4),
1584: (int)OSReadSwapInt32(p, 8), (int)OSReadSwapInt32(p, 12) );
1585: }
1586: }
1587:
1588: void BMacEnet::_dumpRegisters()
1589: {
1590: u_int16_t dataValue;
1591:
1592: IOLog("\nEthernet(BMac): IO Address = %08x", (int)ioBaseEnet );
1593:
1594: dataValue = ReadBigMacRegister(ioBaseEnet, kXIFC);
1595: IOLog("\nEthernet(BMac): Read Register %04x Transceiver I/F = %04x", kXIFC, dataValue );
1596:
1597: dataValue = ReadBigMacRegister(ioBaseEnet, kSTAT);
1598: IOLog("\nEthernet(BMac): Read Register %04x Int Events = %04x", kSTAT, dataValue );
1599:
1600: dataValue = ReadBigMacRegister(ioBaseEnet, kINTDISABLE);
1601: IOLog("\nEthernet(BMac): Read Register %04x Int Disable = %04x", kINTDISABLE, dataValue );
1602:
1603: dataValue = ReadBigMacRegister(ioBaseEnet, kTXRST);
1604: IOLog("\nEthernet(BMac): Read Register %04x Tx Reset = %04x", kTXRST, dataValue );
1605:
1606: dataValue = ReadBigMacRegister(ioBaseEnet, kTXCFG);
1607: IOLog("\nEthernet(BMac): Read Register %04x Tx Config = %04x", kTXCFG, dataValue );
1608: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1609:
1610: dataValue = ReadBigMacRegister(ioBaseEnet, kIPG1);
1611: IOLog("\nEthernet(BMac): Read Register %04x IPG1 = %04x", kIPG1, dataValue );
1612:
1613: dataValue = ReadBigMacRegister(ioBaseEnet, kIPG2);
1614: IOLog("\nEthernet(BMac): Read Register %04x IPG2 = %04x", kIPG2, dataValue );
1615:
1616: dataValue = ReadBigMacRegister(ioBaseEnet, kALIMIT);
1617: IOLog("\nEthernet(BMac): Read Register %04x Attempt Limit = %04x", kALIMIT, dataValue );
1618:
1619: dataValue = ReadBigMacRegister(ioBaseEnet, kSLOT);
1620: IOLog("\nEthernet(BMac): Read Register %04x Slot Time = %04x", kSLOT, dataValue );
1621:
1622: dataValue = ReadBigMacRegister(ioBaseEnet, kPALEN);
1623: IOLog("\nEthernet(BMac): Read Register %04x Preamble Length = %04x", kPALEN, dataValue );
1624:
1625: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1626: dataValue = ReadBigMacRegister(ioBaseEnet, kPAPAT);
1627: IOLog("\nEthernet(BMac): Read Register %04x Preamble Pattern = %04x", kPAPAT, dataValue );
1628:
1629: dataValue = ReadBigMacRegister(ioBaseEnet, kTXSFD);
1630: IOLog("\nEthernet(BMac): Read Register %04x Tx Start Frame Delimeter = %04x", kTXSFD, dataValue );
1631:
1632: dataValue = ReadBigMacRegister(ioBaseEnet, kJAM);
1633: IOLog("\nEthernet(BMac): Read Register %04x Jam Size = %04x", kJAM, dataValue );
1634:
1635: dataValue = ReadBigMacRegister(ioBaseEnet, kTXMAX);
1636: IOLog("\nEthernet(BMac): Read Register %04x Tx Max Size = %04x", kTXMAX, dataValue );
1637:
1638: dataValue = ReadBigMacRegister(ioBaseEnet, kTXMIN);
1639: IOLog("\nEthernet(BMac): Read Register %04x Tx Min Size = %04x", kTXMIN, dataValue );
1640: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1641:
1642: dataValue = ReadBigMacRegister(ioBaseEnet, kPAREG);
1643: IOLog("\nEthernet(BMac): Read Register %04x Peak Attempts = %04x", kPAREG, dataValue );
1644:
1645: dataValue = ReadBigMacRegister(ioBaseEnet, kDCNT);
1646: IOLog("\nEthernet(BMac): Read Register %04x Defer Timer = %04x", kDCNT, dataValue );
1647:
1648: dataValue = ReadBigMacRegister(ioBaseEnet, kNCCNT);
1649: IOLog("\nEthernet(BMac): Read Register %04x Normal Collision Count = %04x", kNCCNT, dataValue );
1650:
1651: dataValue = ReadBigMacRegister(ioBaseEnet, kNTCNT);
1652: IOLog("\nEthernet(BMac): Read Register %04x Network Collision Count = %04x", kNTCNT, dataValue );
1653:
1654: dataValue = ReadBigMacRegister(ioBaseEnet, kEXCNT);
1655: IOLog("\nEthernet(BMac): Read Register %04x Excessive Coll Count = %04x", kEXCNT, dataValue );
1656: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1657:
1658: dataValue = ReadBigMacRegister(ioBaseEnet, kLTCNT);
1659: IOLog("\nEthernet(BMac): Read Register %04x Late Collision Count = %04x", kLTCNT, dataValue );
1660:
1661: dataValue = ReadBigMacRegister(ioBaseEnet, kRSEED);
1662: IOLog("\nEthernet(BMac): Read Register %04x Random Seed = %04x", kRSEED, dataValue );
1663:
1664: dataValue = ReadBigMacRegister(ioBaseEnet, kTXSM);
1665: IOLog("\nEthernet(BMac): Read Register %04x Tx State Machine = %04x", kTXSM, dataValue );
1666:
1667: dataValue = ReadBigMacRegister(ioBaseEnet, kRXRST);
1668: IOLog("\nEthernet(BMac): Read Register %04x Rx Reset = %04x", kRXRST, dataValue );
1669:
1670: dataValue = ReadBigMacRegister(ioBaseEnet, kRXCFG);
1671: IOLog("\nEthernet(BMac): Read Register %04x Rx Config = %04x", kRXCFG, dataValue );
1672: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1673:
1674: dataValue = ReadBigMacRegister(ioBaseEnet, kRXMAX);
1675: IOLog("\nEthernet(BMac): Read Register %04x Rx Max Size = %04x", kRXMAX, dataValue );
1676:
1677: dataValue = ReadBigMacRegister(ioBaseEnet, kRXMIN);
1678: IOLog("\nEthernet(BMac): Read Register %04x Rx Min Size = %04x", kRXMIN, dataValue );
1679:
1680: dataValue = ReadBigMacRegister(ioBaseEnet, kMADD2);
1681: IOLog("\nEthernet(BMac): Read Register %04x Mac Address 2 = %04x", kMADD2, dataValue );
1682:
1683: dataValue = ReadBigMacRegister(ioBaseEnet, kMADD1);
1684: IOLog("\nEthernet(BMac): Read Register %04x Mac Address 1 = %04x", kMADD1, dataValue );
1685:
1686: dataValue = ReadBigMacRegister(ioBaseEnet, kMADD0);
1687: IOLog("\nEthernet(BMac): Read Register %04x Mac Address 0 = %04x", kMADD0, dataValue );
1688: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1689:
1690: dataValue = ReadBigMacRegister(ioBaseEnet, kFRCNT);
1691: IOLog("\nEthernet(BMac): Read Register %04x Rx Frame Counter = %04x", kFRCNT, dataValue );
1692:
1693: dataValue = ReadBigMacRegister(ioBaseEnet, kLECNT);
1694: IOLog("\nEthernet(BMac): Read Register %04x Rx Length Error Cnt = %04x", kLECNT, dataValue );
1695:
1696: dataValue = ReadBigMacRegister(ioBaseEnet, kAECNT);
1697: IOLog("\nEthernet(BMac): Read Register %04x Alignment Error Cnt = %04x", kAECNT, dataValue );
1698:
1699: dataValue = ReadBigMacRegister(ioBaseEnet, kFECNT);
1700: IOLog("\nEthernet(BMac): Read Register %04x FCS Error Cnt = %04x", kFECNT, dataValue );
1701:
1702: dataValue = ReadBigMacRegister(ioBaseEnet, kRXSM);
1703: IOLog("\nEthernet(BMac): Read Register %04x Rx State Machine = %04x", kRXSM, dataValue );
1704: IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1705:
1706: dataValue = ReadBigMacRegister(ioBaseEnet, kRXCV);
1707: IOLog("\nEthernet(BMac): Read Register %04x Rx Code Violation = %04x", kRXCV, dataValue );
1708:
1709: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH3);
1710: IOLog("\nEthernet(BMac): Read Register %04x Hash 3 = %04x", kHASH3, dataValue );
1711:
1712: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH2);
1713: IOLog("\nEthernet(BMac): Read Register %04x Hash 2 = %04x", kHASH2, dataValue );
1714:
1715: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH1);
1716: IOLog("\nEthernet(BMac): Read Register %04x Hash 1 = %04x", kHASH1, dataValue );
1717:
1718: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH0);
1719: IOLog("\nEthernet(BMac): Read Register %04x Hash 0 = %04x", kHASH0, dataValue );
1720: IOLog("\n-------------------------------------------------------" );
1721:
1722: dataValue = ReadBigMacRegister(ioBaseEnet, kAFR2);
1723: IOLog("\nEthernet(BMac): Read Register %04x Address Filter 2 = %04x", kAFR2, dataValue );
1724:
1725: dataValue = ReadBigMacRegister(ioBaseEnet, kAFR1);
1726: IOLog("\nEthernet(BMac): Read Register %04x Address Filter 1 = %04x", kAFR1, dataValue );
1727:
1728: dataValue = ReadBigMacRegister(ioBaseEnet, kAFR0);
1729: IOLog("\nEthernet(BMac): Read Register %04x Address Filter 0 = %04x", kAFR0, dataValue );
1730:
1731: dataValue = ReadBigMacRegister(ioBaseEnet, kAFCR);
1732: IOLog("\nEthernet(BMac): Read Register %04x Adress Filter Mask = %04x", kAFCR, dataValue );
1733:
1734: dataValue = ReadBigMacRegister(ioBaseEnet, kTXFIFOCSR);
1735: IOLog("\nEthernet(BMac): Read Register %04x Tx FIFO CSR = %04x", kTXFIFOCSR, dataValue );
1736: IOLog("\n-------------------------------------------------------" );
1737:
1738: dataValue = ReadBigMacRegister(ioBaseEnet, kTXTH);
1739: IOLog("\nEthernet(BMac): Read Register %04x Tx Threshold = %04x", kTXTH, dataValue );
1740:
1741: dataValue = ReadBigMacRegister(ioBaseEnet, kRXFIFOCSR);
1742: IOLog("\nEthernet(BMac): Read Register %04x Rx FIFO CSR = %04x", kRXFIFOCSR, dataValue );
1743:
1744: dataValue = ReadBigMacRegister(ioBaseEnet, kMEMADD);
1745: IOLog("\nEthernet(BMac): Read Register %04x Mem Addr = %04x", kMEMADD, dataValue );
1746:
1747: dataValue = ReadBigMacRegister(ioBaseEnet, kMEMDATAHI);
1748: IOLog("\nEthernet(BMac): Read Register %04x Mem Data High = %04x", kMEMDATAHI, dataValue );
1749:
1750: dataValue = ReadBigMacRegister(ioBaseEnet, kMEMDATALO);
1751: IOLog("\nEthernet(BMac): Read Register %04x Mem Data Low = %04x", kMEMDATALO, dataValue );
1752: IOLog("\n-------------------------------------------------------" );
1753:
1754: dataValue = ReadBigMacRegister(ioBaseEnet, kXCVRIF);
1755: IOLog("\nEthernet(BMac): Read Register %04x Transceiver IF Control = %04x", kXCVRIF, dataValue );
1756:
1757: dataValue = ReadBigMacRegister(ioBaseEnet, kCHIPID);
1758: IOLog("\nEthernet(BMac): Read Register %04x Chip ID = %04x", kCHIPID, dataValue );
1759:
1760: dataValue = ReadBigMacRegister(ioBaseEnet, kMIFCSR);
1761: IOLog("\nEthernet(BMac): Read Register %04x MII CSR = %04x", kMIFCSR, dataValue );
1762:
1763: dataValue = ReadBigMacRegister(ioBaseEnet, kSROMCSR);
1764: IOLog("\nEthernet(BMac): Read Register %04x SROM CSR = %04x", kSROMCSR, dataValue );
1765:
1766: dataValue = ReadBigMacRegister(ioBaseEnet, kTXPNTR);
1767: IOLog("\nEthernet(BMac): Read Register %04x Tx Pointer = %04x", kTXPNTR, dataValue );
1768:
1769: dataValue = ReadBigMacRegister(ioBaseEnet, kRXPNTR);
1770: IOLog("\nEthernet(BMac): Read Register %04x Rx Pointer = %04x", kRXPNTR, dataValue );
1771: IOLog("\nEthernet(BMac): -------------------------------------------------------\n" );
1772: }
1773: #endif DEBUG
1774:
1775:
1776: /*-------------------------------------------------------------------------
1777: *
1778: *
1779: *
1780: *-------------------------------------------------------------------------*/
1781:
1782: IOReturn BMacEnet::getHardwareAddress(enet_addr_t *ea)
1783: {
1784: int i;
1785: unsigned short data;
1786:
1787: for (i = 0; i < (unsigned short)sizeof(*ea)/2; i++)
1788: {
1789: reset_and_select_srom(ioBaseEnet);
1790: data = read_srom(ioBaseEnet, i + enetAddressOffset/2, sromAddressBits);
1791: ea->ea_byte[2*i] = reverseBitOrder(data & 0x0ff);
1792: ea->ea_byte[2*i+1] = reverseBitOrder((data >> 8) & 0x0ff);
1793: }
1794:
1795: return kIOReturnSuccess;
1796: }
1797:
1798: /*-------------------------------------------------------------------------
1799: *
1800: *
1801: *
1802: *-------------------------------------------------------------------------*/
1803:
1804: #define ENET_CRCPOLY 0x04c11db7
1805:
1806: /* Real fast bit-reversal algorithm, 6-bit values */
1807: static int reverse6[] =
1808: { 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
1809: 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,
1810: 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,
1811: 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,
1812: 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,
1813: 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,
1814: 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,
1815: 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f
1816: };
1817:
1818: static u_int32_t crc416(unsigned int current, unsigned short nxtval )
1819: {
1820: register unsigned int counter;
1821: register int highCRCBitSet, lowDataBitSet;
1822:
1823: /* Swap bytes */
1824: nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8);
1825:
1826: /* Compute bit-by-bit */
1827: for (counter = 0; counter != 16; ++counter)
1828: { /* is high CRC bit set? */
1829: if ((current & 0x80000000) == 0)
1830: highCRCBitSet = 0;
1831: else
1832: highCRCBitSet = 1;
1833:
1834: current = current << 1;
1835:
1836: if ((nxtval & 0x0001) == 0)
1837: lowDataBitSet = 0;
1838: else
1839: lowDataBitSet = 1;
1840:
1841: nxtval = nxtval >> 1;
1842:
1843: /* do the XOR */
1844: if (highCRCBitSet ^ lowDataBitSet)
1845: current = current ^ ENET_CRCPOLY;
1846: }
1847:
1848: return current;
1849: }
1850:
1851: /*-------------------------------------------------------------------------
1852: *
1853: *
1854: *
1855: *-------------------------------------------------------------------------*/
1856:
1857: static u_int32_t mace_crc(unsigned short *address)
1858: {
1859: register u_int32_t newcrc;
1860:
1861: newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */
1862: newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */
1863: newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */
1864:
1865: return(newcrc);
1866: }
1867:
1868: /*
1869: * Clear the hash table filter.
1870: *
1871: */
1872: void BMacEnet::_resetHashTableMask()
1873: {
1874: bzero(hashTableUseCount, sizeof(hashTableUseCount));
1875: bzero(hashTableMask, sizeof(hashTableMask));
1876: }
1877:
1878: /*
1879: * Add requested mcast addr to BMac's hash table filter.
1880: *
1881: */
1882: void BMacEnet::_addToHashTableMask(u_int8_t *addr)
1883: {
1884: u_int32_t crc;
1885: u_int16_t mask;
1886:
1887: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */
1888: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */
1889: if (hashTableUseCount[crc]++)
1890: return; /* This bit is already set */
1891: mask = crc % 16;
1892: mask = (unsigned short)1 << mask;
1893: hashTableMask[crc/16] |= mask;
1894: }
1895:
1896: /*-------------------------------------------------------------------------
1897: *
1898: *
1899: *
1900: *-------------------------------------------------------------------------*/
1901:
1902: void BMacEnet::_removeFromHashTableMask(u_int8_t *addr)
1903: {
1904: unsigned int crc;
1905: u_int16_t mask;
1906:
1907: /* Now, delete the address from the filter copy, as indicated */
1908: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */
1909: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */
1910: if (hashTableUseCount[crc] == 0)
1911: return; /* That bit wasn't in use! */
1912:
1913: if (--hashTableUseCount[crc])
1914: return; /* That bit is still in use */
1915:
1916: mask = crc % 16;
1917: mask = (u_int16_t)1 << mask; /* To turn off bit */
1918: hashTableMask[crc/16] &= ~mask;
1919: }
1920:
1921: /*
1922: * Sync the adapter with the software copy of the multicast mask
1923: * (logical address filter).
1924: */
1925: void BMacEnet::_updateBMacHashTableMask()
1926: {
1927: u_int16_t rxCFGReg;
1928:
1929: rxCFGReg = ReadBigMacRegister(ioBaseEnet, kRXCFG);
1930: WriteBigMacRegister(ioBaseEnet, kRXCFG,
1931: rxCFGReg & ~(kRxMACEnable | kRxHashFilterEnable) );
1932:
1933: while ( ReadBigMacRegister(ioBaseEnet, kRXCFG) &
1934: (kRxMACEnable | kRxHashFilterEnable) )
1935: ;
1936:
1937: WriteBigMacRegister(ioBaseEnet, kHASH0, hashTableMask[0]); // bits 15 - 0
1938: WriteBigMacRegister(ioBaseEnet, kHASH1, hashTableMask[1]); // bits 31 - 16
1939: WriteBigMacRegister(ioBaseEnet, kHASH2, hashTableMask[2]); // bits 47 - 32
1940: WriteBigMacRegister(ioBaseEnet, kHASH3, hashTableMask[3]); // bits 63 - 48
1941:
1942: rxCFGReg |= kRxHashFilterEnable;
1943: WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGReg );
1944: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.