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