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