|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1998-1999 Apple Computer
24: *
25: * Implementation for hardware dependent (relatively) code
26: * for the Sun GEM Ethernet controller.
27: *
28: * HISTORY
29: *
30: * 10-Sept-97
31: * Created.
32: *
33: */
34: #include "UniNEnetPrivate.h"
35:
36: extern void *kernel_pmap;
37:
38: /*
39: * Private functions
40: */
41: bool UniNEnet::allocateMemory()
42: {
43: UInt32 rxRingSize, txRingSize;
44: UInt32 i, n;
45: UInt8 *virtAddr;
46: UInt32 physBase;
47: UInt32 physAddr;
48: TxQueueElement *txElement;
49:
50: /*
51: * Calculate total space for DMA channel commands
52: */
53: txRingSize = (TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) + 2048 - 1) & ~(2048-1);
54: rxRingSize = (RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + 2048 - 1) & ~(2048-1);
55:
56: dmaCommandsSize = round_page( txRingSize + rxRingSize );
57: /*
58: * Allocate required memory
59: */
60: if ( !dmaCommands )
61: {
62: dmaCommands = (UInt8 *)IOMallocContiguous( dmaCommandsSize, PAGE_SIZE, 0 );
63:
64: if ( dmaCommands == 0 )
65: {
66: IOLog( "Ethernet(UniN): Cant allocate channel dma commands\n\r" );
67: return false;
68: }
69: }
70:
71: /*
72: * If we needed more than one page, then make sure we received contiguous memory.
73: */
74: n = (dmaCommandsSize - PAGE_SIZE) / PAGE_SIZE;
75: physBase = pmap_extract(kernel_pmap, (vm_address_t) dmaCommands);
76:
77: virtAddr = (UInt8 *) dmaCommands;
78: for( i=0; i < n; i++, virtAddr += PAGE_SIZE )
79: {
80: physAddr = pmap_extract(kernel_pmap, (vm_address_t) virtAddr);
81: if (physAddr != (physBase + i * PAGE_SIZE) )
82: {
83: IOLog( "Ethernet(UniN): Cant allocate contiguous memory for dma commands\n\r" );
84: return false;
85: }
86: }
87:
88: /*
89: * Setup the receive ring pointers
90: */
91: rxDMACommands = (enet_dma_cmd_t *)dmaCommands;
92: rxMaxCommand = RX_RING_LENGTH;
93:
94: /*
95: * Setup the transmit ring pointers
96: */
97: txDMACommands = (enet_txdma_cmd_t *)(dmaCommands + rxRingSize);
98: txMaxCommand = TX_RING_LENGTH;
99:
100:
101: queue_init( &txActiveQueue );
102: queue_init( &txFreeQueue );
103:
104: for ( i=0; i < TX_MAX_MBUFS; i++ )
105: {
106: txElement = (TxQueueElement *)IOMalloc( sizeof(TxQueueElement) );
107: if ( txElement == 0 )
108: {
109: return false;
110: }
111:
112: bzero( txElement, sizeof(TxQueueElement) );
113:
114: releaseTxElement( txElement );
115: }
116:
117: return true;
118: }
119:
120: /*-------------------------------------------------------------------------
121: *
122: * Setup the Transmit Ring
123: * -----------------------
124: * Each transmit ring entry consists of two words to transmit data from buffer
125: * segments (possibly) spanning a page boundary. This is followed by two DMA commands
126: * which read transmit frame status and interrupt status from the UniN chip. The last
127: * DMA command in each transmit ring entry generates a host interrupt.
128: * The last entry in the ring is followed by a DMA branch to the first
129: * entry.
130: *-------------------------------------------------------------------------*/
131:
132: bool UniNEnet::initTxRing()
133: {
134: TxQueueElement *txElement;
135: UInt32 i;
136:
137: /*
138: * Clear the transmit DMA command memory
139: */
140: bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand);
141: txCommandHead = 0;
142: txCommandTail = 0;
143:
144:
145: txDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) txDMACommands);
146:
147: if ( txDMACommandsPhys == 0 )
148: {
149: IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", (int)txDMACommands );
150: }
151:
152: for ( i=0; i < TX_RING_LENGTH; i++ )
153: {
154: txElement = txElementPtrs[i];
155:
156: if ( (txElement != 0) && (txElement->list != &txFreeQueue) )
157: {
158: if ( txElement->mbuf != 0 )
159: {
160: freePacket( txElement->mbuf );
161: }
162: bzero( txElement, sizeof(TxQueueElement) );
163: releaseTxElement( txElement );
164: }
165:
166: txElementPtrs[i] = 0;
167: }
168:
169: txCommandsAvail = txMaxCommand - 1;
170:
171: return true;
172: }
173:
174: /*-------------------------------------------------------------------------
175: *
176: * Setup the Receive ring
177: * ----------------------
178: * Each receive ring entry consists of two DMA commands to receive data
179: * into a network buffer (possibly) spanning a page boundary. The second
180: * DMA command in each entry generates a host interrupt.
181: * The last entry in the ring is followed by a DMA branch to the first
182: * entry.
183: *
184: *-------------------------------------------------------------------------*/
185:
186: bool UniNEnet::initRxRing()
187: {
188: UInt32 i;
189: bool status;
190:
191: /*
192: * Clear the receive DMA command memory
193: */
194: bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand);
195:
196: rxDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) rxDMACommands);
197: if ( rxDMACommandsPhys == 0 )
198: {
199: IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", (int)rxDMACommands );
200: return false;
201: }
202:
203: /*
204: * Allocate a receive buffer for each entry in the Receive ring
205: */
206: for (i = 0; i < rxMaxCommand; i++)
207: {
208: if (rxMbuf[i] == NULL)
209: {
210: rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE);
211: if (rxMbuf[i] == NULL)
212: {
213: IOLog("Ethernet(UniN): allocateMbuf returned NULL in _initRxRing\n\r");
214: return false;
215: }
216: }
217:
218: /*
219: * Set the DMA commands for the ring entry to transfer data to the Mbuf.
220: */
221: status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true);
222: if (status == false)
223: {
224: IOLog("Ethernet(UniN): cant map mbuf to physical memory in initRxRing\n\r");
225: return false;
226: }
227: }
228:
229: /*
230: * Set the receive queue head to point to the first entry in the ring. Set the
231: * receive queue tail to point to a DMA Stop command after the last ring entry
232: */
233: i-=4;
234: rxCommandHead = 0;
235: rxCommandTail = i;
236:
237: return true;
238: }
239:
240: /*-------------------------------------------------------------------------
241: *
242: *
243: *
244: *-------------------------------------------------------------------------*/
245:
246: void UniNEnet::startChip()
247: {
248: UInt32 gemReg;
249:
250: // dumpRegisters();
251:
252: gemReg = ReadUniNRegister( ioBaseEnet, kGEMTxConfig );
253: gemReg |= kGEMTxConfig_TxDMAEnable;
254: WriteUniNRegister( ioBaseEnet, kGEMTxConfig, gemReg );
255:
256: IOSleep(20);
257:
258: gemReg = ReadUniNRegister( ioBaseEnet, kGEMRxConfig );
259: gemReg |= kGEMRxConfig_RxDMAEnable;
260: WriteUniNRegister( ioBaseEnet, kGEMRxConfig, gemReg );
261:
262: IOSleep(20);
263:
264: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig );
265: gemReg |= kGEMMacTxMacConfig_TxMacEnable;
266: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, gemReg );
267:
268: IOSleep(20);
269:
270: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacRxMacConfig );
271: gemReg |= kGEMMacRxMacConfig_RxMacEnable;
272: WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, gemReg );
273:
274: // dumpRegisters();
275:
276: }
277:
278: /*-------------------------------------------------------------------------
279: *
280: *
281: *
282: *-------------------------------------------------------------------------*/
283:
284: void UniNEnet::stopChip()
285: {
286: UInt32 gemReg;
287:
288: gemReg = ReadUniNRegister( ioBaseEnet, kGEMTxConfig );
289: gemReg &= ~kGEMTxConfig_TxDMAEnable;
290: WriteUniNRegister( ioBaseEnet, kGEMTxConfig, gemReg );
291:
292: IOSleep(20);
293:
294: gemReg = ReadUniNRegister( ioBaseEnet, kGEMRxConfig );
295: gemReg &= ~kGEMRxConfig_RxDMAEnable;
296: WriteUniNRegister( ioBaseEnet, kGEMRxConfig, gemReg );
297:
298: IOSleep(20);
299:
300: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig );
301: gemReg &= ~kGEMMacTxMacConfig_TxMacEnable;
302: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, gemReg );
303:
304: IOSleep(20);
305:
306: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacRxMacConfig );
307: gemReg &= ~kGEMMacRxMacConfig_RxMacEnable;
308: WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, gemReg );
309: }
310:
311:
312:
313: /*-------------------------------------------------------------------------
314: *
315: *
316: *
317: *-------------------------------------------------------------------------*/
318:
319: bool UniNEnet::resetChip()
320: {
321: UInt8 resetReg;
322: UInt16 *pPhyType;
323: UInt16 phyWord;
324:
325:
326: WriteUniNRegister( ioBaseEnet, kGEMSoftwareReset, kGEMSoftwareReset_TxReset | kGEMSoftwareReset_RxReset );
327:
328: do
329: {
330: resetReg = ReadUniNRegister( ioBaseEnet, kGEMSoftwareReset );
331: }
332: while( resetReg & (kGEMSoftwareReset_TxReset | kGEMSoftwareReset_RxReset) );
333:
334: /*
335: * Determine if PHY chip is configured. Reset and enable it (if present).
336: */
337: if ( phyId == 0xff )
338: {
339: if ( miiFindPHY(&phyId) == true )
340: {
341: miiResetPHY( phyId );
342:
343: pPhyType = (UInt16 *)&phyType;
344: miiReadWord( pPhyType, MII_ID0, phyId );
345: miiReadWord( pPhyType+1, MII_ID1, phyId );
346:
347: if ( (phyType & MII_BCM5400_MASK) == MII_BCM5400_ID )
348: {
349: miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId );
350: phyWord |= MII_BCM5400_AUXCONTROL_PWR10BASET;
351: miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId );
352:
353: miiReadWord( &phyWord, MII_BCM5400_1000BASETCONTROL, phyId );
354: phyWord |= MII_BCM5400_1000BASETCONTROL_FULLDUPLEXCAP;
355: miiWriteWord( phyWord, MII_BCM5400_1000BASETCONTROL, phyId );
356:
357: IODelay(100);
358:
359: miiResetPHY( 0x1F );
360:
361: miiReadWord( &phyWord, MII_BCM5201_MULTIPHY, 0x1F );
362: phyWord |= MII_BCM5201_MULTIPHY_SERIALMODE;
363: miiWriteWord( phyWord, MII_BCM5201_MULTIPHY, 0x1F );
364:
365: miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId );
366: phyWord &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
367: miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId );
368:
369: }
370: }
371: }
372:
373: return true;
374: }
375:
376: /*-------------------------------------------------------------------------
377: *
378: *
379: *
380: *-------------------------------------------------------------------------*/
381:
382: bool UniNEnet::initChip()
383: {
384: UInt32 i, j;
385: mach_timespec_t timeStamp;
386: UInt32 rxFifoSize;
387: UInt32 rxOff;
388: UInt32 rxOn;
389: u_int16_t *p16;
390:
391: if ( phyId == 0xff )
392: {
393: WriteUniNRegister( ioBaseEnet, kGEMPCSDatapathMode, kGEMPCSDatapathMode_ExtSERDESMode );
394:
395: WriteUniNRegister( ioBaseEnet, kGEMPCSSerdesControl, kGEMPCSSerdesControl_DisableLoopback |
396: kGEMPCSSerdesControl_EnableSyncDet );
397:
398: WriteUniNRegister( ioBaseEnet, kGEMPCSAdvert, kGEMPCSAdvert_FullDuplexCap |
399: kGEMPCSAdvert_SymPauseCap );
400:
401: WriteUniNRegister( ioBaseEnet, kGEMPCSControl, kGEMPCSControl_EnableAutoNegot |
402: kGEMPCSControl_RestartAutoNegot );
403:
404: WriteUniNRegister( ioBaseEnet, kGEMPCSConfig, kGEMPCSConfig_Enable );
405:
406: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, kGEMMacXIFConfig_TxMIIOutputEnable |
407: kGEMMacXIFConfig_GMIIMode |
408: kGEMMacXIFConfig_FullDuplexLed );
409: }
410: else
411: {
412: WriteUniNRegister( ioBaseEnet, kGEMPCSDatapathMode, kGEMPCSDatapathMode_GMIIMode );
413:
414: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, kGEMMacXIFConfig_TxMIIOutputEnable |
415: kGEMMacXIFConfig_FullDuplexLed );
416: }
417:
418: WriteUniNRegister( ioBaseEnet, kGEMMacSendPauseCmd, kGEMMacSendPauseCmd_Bit * kGEMMacSendPauseCmd_Default );
419:
420: WriteUniNRegister( ioBaseEnet, kGEMMacControlConfig, kGEMMacControlConfig_ReceivePauseEnable );
421:
422: WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, 0xffffffff );
423:
424: WriteUniNRegister( ioBaseEnet, kGEMMacTxMask, kGEMMacTxMaskDefault );
425:
426: WriteUniNRegister( ioBaseEnet, kGEMMacRxMask, kGEMMacRxMaskDefault );
427:
428: WriteUniNRegister( ioBaseEnet, kGEMMacControlMask, kGEMMacControlMaskDefault );
429:
430: WriteUniNRegister( ioBaseEnet, kGEMConfig, 31*kGEMConfig_TxDMALimitBit |
431: 31*kGEMConfig_RxDMALimitBit |
432: kGEMConfig_InfiniteBurst);
433:
434: WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap0, kGEMMacInterPktGap0_Default );
435: WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap1, kGEMMacInterPktGap1_Default );
436: WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap2, kGEMMacInterPktGap2_Default );
437:
438: WriteUniNRegister( ioBaseEnet, kGEMMacSlotTime, kGEMMacSlotTime_Default );
439:
440: WriteUniNRegister( ioBaseEnet, kGEMMacMinFrameSize, kGEMMacMinFrameSize_Default );
441: WriteUniNRegister( ioBaseEnet, kGEMMacMaxFrameSize, kGEMMacMaxFrameSize_Default );
442:
443: WriteUniNRegister( ioBaseEnet, kGEMMacPASize, kGEMMacPASize_Default );
444:
445: WriteUniNRegister( ioBaseEnet, kGEMMacJamSize, kGEMMacJamSize_Default );
446:
447: WriteUniNRegister( ioBaseEnet, kGEMMacAttemptLimit, kGEMMacAttemptLimit_Default );
448:
449: WriteUniNRegister( ioBaseEnet, kGEMMacTypeControl, kGEMMacTypeControl_Default );
450:
451: /*
452: *
453: */
454: p16 = (u_int16_t *) myAddress.ea_byte;
455: for ( i=0; i < sizeof(enet_addr_t) / 2; i++ )
456: {
457: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + i * 4, p16[2-i] );
458: }
459:
460: for ( i=0; i < 3; i ++ )
461: {
462: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (i+3) * 4, 0 );
463: WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilter + (i+0) * 4, 0 );
464: }
465:
466: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (6*4), kGEMMacAddr6_Default );
467: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (7*4), kGEMMacAddr7_Default );
468: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (8*4), kGEMMacAddr8_Default );
469:
470: WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilterMask1, 0 );
471: WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilterMask0, 0 );
472:
473: for ( i=0; i < 16; i++ )
474: {
475: WriteUniNRegister( ioBaseEnet, kGEMMacHashTable + i * 4, 0 );
476: }
477:
478: /*
479: *
480: */
481: for ( i = kGEMMacCollisions; i <= kGEMMacRxCodeErrors; i+=4 );
482: {
483: WriteUniNRegister( ioBaseEnet, i, 0 );
484: }
485:
486: IOGetTime(&timeStamp);
487: WriteUniNRegister( ioBaseEnet, kGEMMacRandomSeed, (u_int16_t) timeStamp.tv_nsec );
488:
489: /*
490: *
491: */
492: WriteUniNRegister( ioBaseEnet, kGEMTxDescBaseLo, txDMACommandsPhys );
493: WriteUniNRegister( ioBaseEnet, kGEMTxDescBaseHi, 0 );
494:
495: for ( i=0, j=TX_RING_LENGTH / kGEMTxConfig_TxRingSizeMin - 1;
496: (i < 13) && j;
497: i++, j >>= 1 )
498: ;
499:
500: WriteUniNRegister( ioBaseEnet, kGEMTxConfig, (i * kGEMTxConfig_TxDescRingSizeBit) |
501: (kGEMTxConfig_TxFIFOThresholdDefault * kGEMTxConfig_TxFIFOThresholdBit) );
502:
503: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, 0 );
504:
505: setDuplexMode( (phyId == 0xff) ? true : false );
506:
507: /*
508: *
509: */
510: WriteUniNRegister( ioBaseEnet, kGEMRxDescBaseLo, rxDMACommandsPhys );
511: WriteUniNRegister( ioBaseEnet, kGEMRxDescBaseHi, 0 );
512:
513: WriteUniNRegister( ioBaseEnet, kGEMRxKick, RX_RING_LENGTH-4 );
514:
515: for ( i=0, j=RX_RING_LENGTH / kGEMRxConfig_RxRingSizeMin - 1;
516: (i < 13) && j;
517: i++, j >>= 1 )
518: ;
519:
520: WriteUniNRegister( ioBaseEnet, kGEMRxConfig, (i * kGEMRxConfig_RxDescRingSizeBit) |
521: (kGEMRxConfig_RxDMAThresholdDefault * kGEMRxConfig_RxDMAThresholdBit)
522: );
523:
524: WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, 0 );
525:
526: rxFifoSize = ReadUniNRegister( ioBaseEnet, kGEMRxFIFOSize );
527:
528: rxOff = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 2 / kGEMRxPauseThresholds_Units);
529: rxOn = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 3 / kGEMRxPauseThresholds_Units);
530:
531: WriteUniNRegister( ioBaseEnet, kGEMRxPauseThresholds, (rxOff * kGEMRxPauseThresholds_OffBit) |
532: (rxOn * kGEMRxPauseThresholds_OnBit) );
533:
534: i = (ReadUniNRegister(ioBaseEnet, kGEMBIFConfig) & kGEMBIFConfig_66Mhz) ? PCI_PERIOD_66MHz : PCI_PERIOD_33MHz;
535: i = (RX_INT_LATENCY_uS * 1000) / (2048 * i);
536:
537: WriteUniNRegister( ioBaseEnet, kGEMRxIntBlanking, i*kGEMRxIntBlanking_TimeBit | 5*kGEMRxIntBlanking_NumPktBit );
538:
539: return true;
540: }
541:
542: /*-------------------------------------------------------------------------
543: *
544: *
545: *
546: *-------------------------------------------------------------------------*/
547:
548: void UniNEnet::disableAdapterInterrupts()
549: {
550:
551: WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, 0xffffffff );
552: }
553:
554: /*-------------------------------------------------------------------------
555: *
556: *
557: *
558: *-------------------------------------------------------------------------*/
559:
560: void UniNEnet::enableAdapterInterrupts()
561: {
562: UInt32 gemReg;
563:
564: gemReg = ReadUniNRegister( ioBaseEnet, kGEMInterruptMask );
565: gemReg &= ~(kGEMInterruptMask_TxInt | kGEMInterruptMask_RxDone | kGEMInterruptStatus_RxMacInt);
566: WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, gemReg );
567: }
568:
569: /*-------------------------------------------------------------------------
570: *
571: *
572: *
573: *-------------------------------------------------------------------------*/
574:
575: void UniNEnet::setDuplexMode( bool duplexMode )
576: {
577: UInt16 txMacConfig;
578: UInt16 xifConfig;
579:
580: isFullDuplex = duplexMode;
581:
582: txMacConfig = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig );
583:
584: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, txMacConfig & ~kGEMMacTxMacConfig_TxMacEnable );
585: while( ReadUniNRegister(ioBaseEnet, kGEMMacTxMacConfig) & kGEMMacTxMacConfig_TxMacEnable )
586: ;
587:
588: xifConfig = ReadUniNRegister( ioBaseEnet, kGEMMacXIFConfig );
589:
590: if ( isFullDuplex )
591: {
592: txMacConfig |= (kGEMMacTxMacConfig_IgnoreCollsn | kGEMMacTxMacConfig_IgnoreCarrierSense);
593: xifConfig &= ~kGEMMacXIFConfig_DisableEcho;
594: }
595: else
596: {
597: txMacConfig &= ~(kGEMMacTxMacConfig_IgnoreCollsn | kGEMMacTxMacConfig_IgnoreCarrierSense);
598: xifConfig |= kGEMMacXIFConfig_DisableEcho;
599: }
600:
601: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, txMacConfig );
602: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, xifConfig );
603: }
604:
605:
606: /*-------------------------------------------------------------------------
607: *
608: *
609: *
610: *-------------------------------------------------------------------------*/
611:
612: void UniNEnet::restartTransmitter()
613: {
614: }
615:
616: /*-------------------------------------------------------------------------
617: *
618: *
619: *
620: *-------------------------------------------------------------------------*/
621:
622: void UniNEnet::restartReceiver()
623: {
624: }
625:
626: /*-------------------------------------------------------------------------
627: *
628: * Orderly stop of receive DMA.
629: *
630: *
631: *-------------------------------------------------------------------------*/
632:
633: void UniNEnet::stopReceiveDMA()
634: {
635: }
636:
637: /*-------------------------------------------------------------------------
638: *
639: *
640: *
641: *-------------------------------------------------------------------------*/
642:
643: void UniNEnet::stopTransmitDMA()
644: {
645: }
646:
647: /*-------------------------------------------------------------------------
648: *
649: *
650: *
651: *-------------------------------------------------------------------------*/
652:
653: bool UniNEnet::transmitPacket(struct mbuf *packet)
654: {
655: UInt32 i,j,k;
656: struct mbuf *m;
657: TxQueueElement *txElement;
658: UInt32 dataPhys;
659:
660:
661: for ( m = packet, i=1; m->m_next; m=m->m_next, i++ )
662: ;
663:
664:
665: if ( i > txCommandsAvail )
666: {
667: transmitInterruptOccurred();
668:
669: if ( i > txCommandsAvail )
670: {
671: return false;
672: }
673: }
674:
675:
676: if ( (txElement=getTxElement()) == 0 )
677: {
678: transmitInterruptOccurred();
679:
680: if ( (txElement=getTxElement()) == 0 )
681: {
682: return false;
683: }
684: }
685:
686: j = txCommandTail;
687:
688: txElement->mbuf = packet;
689: txElement->slot = j;
690: txElement->count = i;
691:
692: txCommandsAvail -= i;
693:
694: m = packet;
695:
696: do
697: {
698: k = j;
699:
700: txElementPtrs[j] = txElement;
701:
702: dataPhys = (UInt32)mcl_to_paddr( mtod(m, char *) );
703: if ( dataPhys == 0 )
704: {
705: dataPhys = pmap_extract( kernel_pmap, mtod(m, vm_offset_t));
706: }
707:
708: txDMACommands[j].desc_seg[0].bufferAddrLo = EndianSwap32(dataPhys);
709: txDMACommands[j].desc_seg[0].flags0 = EndianSwap32(kGEMTxDescFlags0_BufferSizeBit * m->m_len);
710:
711: j++;
712: if ( j >= txMaxCommand ) j = 0;
713: }
714: while ( (m=m->m_next) != 0 );
715:
716: txDMACommands[k].desc_seg[0].flags0 |= EndianSwap32(kGEMTxDescFlags0_EndOfFrame);
717: txDMACommands[txCommandTail].desc_seg[0].flags0 |= EndianSwap32(kGEMTxDescFlags0_StartOfFrame);
718:
719: txCommandTail = j;
720:
721: WriteUniNRegister( ioBaseEnet, kGEMTxKick, j );
722:
723: return true;
724: }
725:
726:
727: /*-------------------------------------------------------------------------
728: * _receivePacket
729: * --------------
730: * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger.
731: * Don't mess with the interrupt source here that can deadlock in the debugger
732: *
733: * The _receivePackets allocate MBufs and pass them up the stack. The kernel
734: * debugger interface passes a buffer into us. To reconsile the two interfaces,
735: * we allow the receive routine to continue to allocate its own buffers and
736: * transfer any received data to the passed-in buffer. This is handled by
737: * _receivePacket calling _packetToDebugger.
738: *-------------------------------------------------------------------------*/
739:
740: void UniNEnet::receivePacket( void *pkt, unsigned int *pkt_len, unsigned int timeout )
741: {
742: mach_timespec_t startTime;
743: mach_timespec_t currentTime;
744: UInt32 elapsedTimeMS;
745:
746: *pkt_len = 0;
747:
748: if (ready == false)
749: return;
750:
751: debuggerPkt = pkt;
752: debuggerPktSize = 0;
753:
754: IOGetTime(&startTime);
755: do
756: {
757: receivePackets( true );
758: IOGetTime( ¤tTime );
759: elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000);
760: }
761: while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) );
762:
763: *pkt_len = debuggerPktSize;
764:
765: return;
766: }
767:
768: /*-------------------------------------------------------------------------
769: * _packetToDebugger
770: * -----------------
771: * This is called by _receivePackets when we are polling for kernel debugger
772: * packets. It copies the MBuf contents to the buffer passed by the debugger.
773: * It also sets the var debuggerPktSize which will break the polling loop.
774: *-------------------------------------------------------------------------*/
775:
776: void UniNEnet::packetToDebugger( struct mbuf * packet, u_int size )
777: {
778: debuggerPktSize = size;
779: bcopy( mtod(packet, char *), debuggerPkt, size );
780: }
781:
782: /*-------------------------------------------------------------------------
783: * _sendPacket
784: * -----------
785: *
786: * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger.
787: * Don't mess with the interrupt source here that can deadlock in the debugger
788: *
789: *-------------------------------------------------------------------------*/
790:
791: void UniNEnet::sendPacket( void *pkt, unsigned int pkt_len )
792: {
793: mach_timespec_t startTime;
794: mach_timespec_t currentTime;
795: UInt32 elapsedTimeMS;
796:
797: if (!ready || !pkt || (pkt_len > ETHERMAXPACKET))
798: {
799: return;
800: }
801:
802: /*
803: * Wait for the transmit ring to empty
804: */
805: IOGetTime(&startTime);
806: do
807: {
808: debugTransmitInterruptOccurred();
809: IOGetTime(¤tTime);
810: elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000);
811: }
812: while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) );
813:
814: if ( txCommandHead != txCommandTail )
815: {
816: IOLog( "Ethernet(UniN): Polled tranmit timeout - 1\n\r");
817: return;
818: }
819:
820: /*
821: * Allocate a MBuf and copy the debugger transmit data into it.
822: *
823: * jliu - no allocation, just recycle the same buffer dedicated to
824: * KDB transmit.
825: */
826: txDebuggerPkt->m_next = 0;
827: txDebuggerPkt->m_data = (caddr_t) pkt;
828: txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len;
829:
830: /*
831: * Send the debugger packet. txDebuggerPkt must not be freed by
832: * the transmit routine.
833: */
834: transmitPacket(txDebuggerPkt);
835:
836: /*
837: * Poll waiting for the transmit ring to empty again
838: */
839: do
840: {
841: debugTransmitInterruptOccurred();
842: IOGetTime(¤tTime);
843: elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000);
844: }
845: while ( (txCommandHead != txCommandTail) &&
846: (elapsedTimeMS < TX_KDB_TIMEOUT) );
847:
848: if ( txCommandHead != txCommandTail )
849: {
850: IOLog( "Ethernet(UniN): Polled tranmit timeout - 2\n\r");
851: }
852:
853: return;
854: }
855:
856: /*-------------------------------------------------------------------------
857: * _sendDummyPacket
858: * ----------------
859: * The UniN receiver seems to be locked until we send our first packet.
860: *
861: *-------------------------------------------------------------------------*/
862: void UniNEnet::sendDummyPacket()
863: {
864: union
865: {
866: UInt8 bytes[64];
867: enet_addr_t enet_addr[2];
868: } dummyPacket;
869:
870: bzero( &dummyPacket, sizeof(dummyPacket) );
871:
872:
873: dummyPacket.enet_addr[0] = myAddress;
874: dummyPacket.enet_addr[1] = myAddress;
875:
876: sendPacket((void *)dummyPacket.bytes, (unsigned int)sizeof(dummyPacket));
877: }
878:
879:
880:
881: /*-------------------------------------------------------------------------
882: *
883: *
884: *
885: *-------------------------------------------------------------------------*/
886:
887: bool UniNEnet::receiveInterruptOccurred()
888: {
889: return receivePackets(false);
890: }
891:
892: /*-------------------------------------------------------------------------
893: *
894: *
895: *
896: *-------------------------------------------------------------------------*/
897:
898: bool UniNEnet::receivePackets( bool fDebugger )
899: {
900: struct mbuf *packet;
901: UInt32 i,last;
902: int receivedFrameSize = 0;
903: UInt16 dmaFlags;
904: UInt32 rxPktStatus = 0;
905: UInt32 badFrameCount;
906: bool passPacketUp;
907: bool reusePkt;
908: bool status;
909: bool useNetif = !fDebugger && netifClient;
910: bool packetsQueued = false;
911:
912:
913: last = (UInt32)-1;
914: i = rxCommandHead;
915:
916: while ( 1 )
917: {
918: passPacketUp = false;
919: reusePkt = false;
920:
921: dmaFlags = EndianSwap16(rxDMACommands[i].desc_seg[0].frameDataSize);
922:
923: /*
924: * If the current entry has not been written, then stop at this entry
925: */
926: if ( dmaFlags & kGEMRxDescFrameSize_Own )
927: {
928: break;
929: }
930:
931:
932: receivedFrameSize = dmaFlags & kGEMRxDescFrameSize_Mask;
933: rxPktStatus = EndianSwap32(rxDMACommands[i].desc_seg[0].flags);
934:
935:
936: /*
937: * Reject packets that are runts or that have other mutations.
938: */
939: if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) ||
940: receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) ||
941: rxPktStatus & kGEMRxDescFlags_BadCRC )
942: {
943: if (useNetif) netStats->inputErrors++;
944: reusePkt = true;
945: }
946: else if ( useNetif == false )
947: {
948: /*
949: * Always reuse packets in debugger mode. We also refuse to
950: * pass anything up the stack unless the driver is open. The
951: * hardware is enabled before the stack has opened us, to
952: * allow earlier debug interface registration. But we must
953: * not pass any packets up.
954: */
955: reusePkt = true;
956: if (fDebugger)
957: {
958: packetToDebugger(rxMbuf[i], receivedFrameSize);
959: }
960: }
961:
962:
963: /*
964: * Before we pass this packet up the networking stack. Make sure we
965: * can get a replacement. Otherwise, hold on to the current packet and
966: * increment the input error count.
967: * Thanks Justin!
968: */
969:
970: packet = 0;
971:
972: if ( reusePkt == false )
973: {
974: bool replaced;
975:
976: packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, &replaced);
977:
978: reusePkt = true;
979:
980: if (packet && replaced)
981: {
982: status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true);
983:
984: if (status)
985: {
986: reusePkt = false;
987: }
988: else
989: {
990: // Assume descriptor has not been corrupted.
991: freePacket(rxMbuf[i]); // release new packet.
992: rxMbuf[i] = packet; // get the old packet back.
993: packet = 0; // pass up nothing.
994: IOLog("Ethernet(UniN): updateDescriptorFromMbuf error\n");
995: }
996: }
997:
998: if (packet == 0)
999: netStats->inputErrors++;
1000: }
1001:
1002: /*
1003: * Install the new MBuf for the one we're about to pass to the network stack
1004: */
1005:
1006: if ( reusePkt == true )
1007: {
1008: rxDMACommands[i].desc_seg[0].frameDataSize = EndianSwap16(NETWORK_BUFSIZE | kGEMRxDescFrameSize_Own);
1009: rxDMACommands[i].desc_seg[0].flags = 0;
1010: }
1011:
1012: /*
1013: * Keep track of the last receive descriptor processed
1014: */
1015: last = i;
1016:
1017: /*
1018: * Implement ring wrap-around
1019: */
1020: if (++i >= rxMaxCommand) i = 0;
1021:
1022: if (fDebugger)
1023: {
1024: break;
1025: }
1026:
1027: /*
1028: * Transfer received packet to network
1029: */
1030: if (packet)
1031: {
1032: KERNEL_DEBUG(DBG_UniN_RXCOMPLETE | DBG_FUNC_NONE, (int) packet,
1033: (int)receivedFrameSize, 0, 0, 0 );
1034:
1035: networkInterface->inputPacket(packet, receivedFrameSize, true);
1036: netStats->inputPackets++;
1037: packetsQueued = true;
1038: }
1039: }
1040:
1041: /*
1042: *
1043: *
1044: */
1045: #if 0
1046: IOLog( "Ethernet(UniN): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last );
1047: #endif
1048:
1049: if ( last != (UInt32)-1 )
1050: {
1051: rxCommandTail = last;
1052: rxCommandHead = i;
1053: }
1054:
1055: /*
1056: * Tap the DMA to wake it up
1057: */
1058: WriteUniNRegister(ioBaseEnet, kGEMRxKick, rxCommandTail & ~(4-1));
1059:
1060:
1061: /*
1062: * Update receive error statistics
1063: */
1064:
1065: badFrameCount = ReadUniNRegister(ioBaseEnet, kGEMMacRxLengthErrors)
1066: + ReadUniNRegister(ioBaseEnet, kGEMMacRxFCSErrors);
1067:
1068: /*
1069: * Clear Hardware counters
1070: */
1071: WriteUniNRegister(ioBaseEnet, kGEMMacRxLengthErrors, 0);
1072: WriteUniNRegister(ioBaseEnet, kGEMMacRxFCSErrors, 0);
1073:
1074: if (useNetif) netStats->inputErrors += badFrameCount;
1075:
1076:
1077: return packetsQueued;
1078: }
1079:
1080: /*-------------------------------------------------------------------------
1081: *
1082: *
1083: *
1084: *-------------------------------------------------------------------------*/
1085:
1086: bool UniNEnet::transmitInterruptOccurred()
1087: {
1088: UInt32 i;
1089: bool fServiced = false;
1090: UInt32 txHeadOrig, txCompOrig;
1091: TxQueueElement *txElement;
1092:
1093: i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion );
1094:
1095: txHeadOrig = txCommandHead;
1096: txCompOrig = i;
1097:
1098: while ( i != txCommandHead )
1099: {
1100: /*
1101: * Free the MBuf we just transmitted
1102: */
1103: txElement = txElementPtrs[txCommandHead];
1104:
1105: KERNEL_DEBUG(DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE, (int) txElement->mbuf, 0, 0, 0, 0 );
1106:
1107: txElementPtrs[txCommandHead] = 0;
1108: txCommandsAvail++;
1109:
1110: if ( --txElement->count == 0 )
1111: {
1112: freePacket( txElement->mbuf );
1113: releaseTxElement( txElement );
1114: if (netifClient) netStats->outputPackets++;
1115: }
1116:
1117: if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0;
1118:
1119: i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion );
1120:
1121: fServiced = true;
1122: }
1123:
1124: return fServiced;
1125: }
1126:
1127: /*-------------------------------------------------------------------------
1128: *
1129: *
1130: *
1131: *-------------------------------------------------------------------------*/
1132:
1133: bool UniNEnet::debugTransmitInterruptOccurred()
1134: {
1135: bool fServiced = false;
1136: UInt32 i;
1137: TxQueueElement *txElement;
1138:
1139: // Set the debugTxPoll flag to indicate the debugger was active
1140: // and some cleanup may be needed when the driver returns to
1141: // normal operation.
1142: //
1143: debugTxPoll = true;
1144:
1145: i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion );
1146:
1147: while ( i != txCommandHead )
1148: {
1149: fServiced = true;
1150:
1151: /*
1152: * Free the mbuf we just transmitted.
1153: *
1154: * If it is the debugger packet, just remove it from the ring.
1155: * and reuse the same packet for the next sendPacket() request.
1156: */
1157:
1158: /*
1159: * While in debugger mode, do not touch the mbuf pool.
1160: * Queue any used mbufs to a local queue. This queue
1161: * will get flushed after we exit from debugger mode.
1162: *
1163: * During continuous debugger transmission and
1164: * interrupt polling, we expect only the txDebuggerPkt
1165: * to show up on the transmit mbuf ring.
1166: */
1167: txElement = txElementPtrs[txCommandHead];
1168: txElementPtrs[txCommandHead] = 0;
1169: txCommandsAvail++;
1170:
1171: KERNEL_DEBUG(DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE,
1172: (int)txElement->mbuf,
1173: (int)txElement->mbuf->m_pkthdr.len, 0, 0, 0 );
1174:
1175: if ( --txElement->count == 0 )
1176: {
1177: if (txElement->mbuf != txDebuggerPkt)
1178: {
1179: debugQueue->enqueue( txElement->mbuf );
1180: }
1181: releaseTxElement( txElement );
1182: }
1183:
1184: if ( ++(txCommandHead) >= txMaxCommand )
1185: txCommandHead = 0;
1186: }
1187:
1188: return fServiced;
1189: }
1190:
1191: /*-------------------------------------------------------------------------
1192: *
1193: *
1194: *
1195: *-------------------------------------------------------------------------*/
1196:
1197: void UniNEnet::debugTransmitCleanup()
1198: {
1199: // Debugger was active, clear all packets in the debugQueue, and
1200: // issue a start(), just in case the debugger became active while the
1201: // ring was full and the output queue stopped. Since the debugger
1202: // does not restart the output queue, to avoid calling
1203: // semaphore_signal() which may reenable interrupts, we need to
1204: // make sure the output queue is not stalled after the debugger has
1205: // flushed the ring.
1206:
1207: debugQueue->flush();
1208:
1209: transmitQueue->start();
1210: }
1211:
1212:
1213: /*-------------------------------------------------------------------------
1214: *
1215: *
1216: *
1217: *-------------------------------------------------------------------------*/
1218:
1219: static UInt32 txCnt = 1;
1220:
1221: bool UniNEnet::updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc, bool isReceive)
1222: {
1223: struct IOPhysicalSegment segVector[1];
1224: UInt32 segments;
1225:
1226: segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector);
1227:
1228: if ( segments == 0 || segments > 1 )
1229: {
1230: IOLog("Ethernet(UniN): updateDescriptorFromMbuf error, %d segments\n", (int)segments);
1231: return false;
1232: }
1233:
1234: if ( isReceive )
1235: {
1236: enet_dma_cmd_t *rxCmd = (enet_dma_cmd_t *)desc;
1237:
1238: rxCmd->desc_seg[0].bufferAddrLo = EndianSwap32(segVector[0].location);
1239: rxCmd->desc_seg[0].frameDataSize = EndianSwap16(segVector[0].length | kGEMRxDescFrameSize_Own);
1240: rxCmd->desc_seg[0].flags = 0;
1241: }
1242: else
1243: {
1244: enet_txdma_cmd_t *txCmd = (enet_txdma_cmd_t *)desc;
1245:
1246: txCmd->desc_seg[0].bufferAddrLo = EndianSwap32(segVector[0].location);
1247: txCmd->desc_seg[0].flags0 = EndianSwap32( kGEMTxDescFlags0_BufferSizeBit * segVector[0].length |
1248: kGEMTxDescFlags0_StartOfFrame |
1249: kGEMTxDescFlags0_EndOfFrame );
1250:
1251: txCmd->desc_seg[0].flags1 = ((txCnt++ % 64) == 0) ? EndianSwap32(kGEMTxDescFlags1_Int) : 0;
1252: }
1253:
1254: return true;
1255: }
1256:
1257: /*-------------------------------------------------------------------------
1258: *
1259: *
1260: *
1261: *-------------------------------------------------------------------------*/
1262:
1263: TxQueueElement *UniNEnet::getTxElement()
1264: {
1265: TxQueueElement *txElement = 0;
1266:
1267: if ( queue_empty( &txFreeQueue ) == false )
1268: {
1269: queue_remove_first( &txFreeQueue, txElement, TxQueueElement *, next );
1270:
1271: txElement->list = &txActiveQueue;
1272:
1273: queue_enter( txElement->list, txElement, TxQueueElement *, next );
1274: }
1275:
1276: return txElement;
1277: }
1278:
1279: /*-------------------------------------------------------------------------
1280: *
1281: *
1282: *
1283: *-------------------------------------------------------------------------*/
1284:
1285: void UniNEnet::releaseTxElement(TxQueueElement *txElement)
1286: {
1287: if ( txElement->list != 0 )
1288: {
1289: queue_remove( txElement->list, txElement, TxQueueElement *, next );
1290: }
1291:
1292: txElement->list = &txFreeQueue;
1293:
1294: queue_enter( txElement->list, txElement, TxQueueElement *, next);
1295: }
1296:
1297: /*-------------------------------------------------------------------------
1298: *
1299: *
1300: *
1301: *-------------------------------------------------------------------------*/
1302:
1303: void UniNEnet::monitorLinkStatus()
1304: {
1305: UInt16 phyStatus;
1306: UInt16 linkStatus;
1307: UInt16 linkMode;
1308: UInt16 lpAbility;
1309: UInt16 gemReg;
1310: UInt16 phyStatusChange;
1311: bool fullDuplex = false;
1312: UInt8 *linkSpeedTxt;
1313:
1314: if ( phyId == 0xff )
1315: {
1316: phyStatus = ReadUniNRegister( ioBaseEnet, kGEMPCSStatus );
1317: lpAbility = ReadUniNRegister( ioBaseEnet, kGEMPCSLPAbility );
1318: }
1319: else
1320: {
1321: if ( miiReadWord( &phyStatus, MII_STATUS, phyId) != true )
1322: {
1323: return;
1324: }
1325: miiReadWord( &lpAbility, MII_STATUS, phyId);
1326: }
1327:
1328: phyStatusChange = (phyStatusPrev ^ phyStatus) & (MII_STATUS_LINK_STATUS | MII_STATUS_NEGOTIATION_COMPLETE);
1329: if ( phyStatusChange )
1330: {
1331: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacControlConfig );
1332: if ( lpAbility & MII_LPAR_PAUSE )
1333: {
1334: gemReg |= kGEMMacControlConfig_SendPauseEnable;
1335: }
1336: else
1337: {
1338: gemReg &= ~kGEMMacControlConfig_SendPauseEnable;
1339: }
1340: WriteUniNRegister( ioBaseEnet, kGEMMacControlConfig, gemReg );
1341:
1342: if ( (phyStatus & MII_STATUS_LINK_STATUS) && (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE ) )
1343: {
1344: if ( phyId == 0xff )
1345: {
1346: IOLog( "Ethernet(UniN): Link is up at 1Gb - Full Duplex\n\r" );
1347: fullDuplex = true;
1348: }
1349: else if ( (phyType & MII_BCM5201_MASK) == MII_BCM5201_ID )
1350: {
1351: miiReadWord( &linkStatus, MII_BCM5201_AUXSTATUS, phyId );
1352:
1353: fullDuplex = (linkStatus & MII_BCM5201_AUXSTATUS_DUPLEX) ? true : false;
1354:
1355: IOLog( "Ethernet(UniN): Link is up at %sMb - %s Duplex\n\r",
1356: (linkStatus & MII_BCM5201_AUXSTATUS_SPEED) ? "100" : "10",
1357: (fullDuplex) ? "Full" : "Half" );
1358:
1359: }
1360: else if ( (phyType & MII_BCM5400_MASK) == MII_BCM5400_ID )
1361: {
1362: miiReadWord( &linkStatus, MII_BCM5400_AUXSTATUS, phyId );
1363:
1364: linkMode = (linkStatus & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) / MII_BCM5400_AUXSTATUS_LINKMODE_BIT;
1365:
1366: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacXIFConfig );
1367: if ( linkMode < 6 )
1368: {
1369: gemReg &= ~kGEMMacXIFConfig_GMIIMode;
1370: }
1371: else
1372: {
1373: gemReg |= kGEMMacXIFConfig_GMIIMode;
1374: }
1375: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, gemReg );
1376:
1377: if ( linkMode == 0 )
1378: {
1379: linkSpeedTxt = NULL;
1380: }
1381: else if ( linkMode < 3 )
1382: {
1383: linkSpeedTxt = (UInt8 *)"10Mb";
1384: fullDuplex = ( linkMode < 2 ) ? false : true;
1385:
1386: }
1387: else if ( linkMode < 6 )
1388: {
1389: linkSpeedTxt = (UInt8 *)"100Mb";
1390: fullDuplex = ( linkMode < 5 ) ? false : true;
1391: }
1392: else
1393: {
1394: linkSpeedTxt = (UInt8 *)"1Gb";
1395: fullDuplex = true;
1396: }
1397:
1398: if ( linkSpeedTxt )
1399: {
1400: IOLog( "Ethernet(UniN): Link is up at %s - %s Duplex\n\r",
1401: linkSpeedTxt,
1402: (fullDuplex) ? "Full" : "Half" );
1403: }
1404: else
1405: {
1406: IOLog( "Ethernet(UniN): Link is up\n\r" );
1407: }
1408:
1409: }
1410:
1411: if ( fullDuplex != isFullDuplex )
1412: {
1413: setDuplexMode( fullDuplex );
1414: }
1415:
1416: if ( ready == true )
1417: {
1418: startChip();
1419: }
1420:
1421: linkStatusPrev = true;
1422: }
1423: else
1424: {
1425: if ( linkStatusPrev == true )
1426: {
1427: stopChip();
1428: IOLog( "Ethernet(UniN): Link is down.\n\r" );
1429: }
1430: linkStatusPrev = false;
1431: }
1432: phyStatusPrev = phyStatus;
1433: }
1434: }
1435:
1436:
1437: /*-------------------------------------------------------------------------
1438: *
1439: *
1440: *
1441: *-------------------------------------------------------------------------*/
1442:
1443: void UniNEnet::dumpRegisters()
1444: {
1445: UInt32 i;
1446:
1447: struct _regtable
1448: {
1449: UInt32 reg;
1450: char *text;
1451: }
1452: regtable[] =
1453: {
1454: { kGEMSEBState ,"SEBState" },
1455: { kGEMConfig ,"Config" },
1456: { kGEMInterruptStatus ,"InterruptStatus" },
1457: { kGEMInterruptMask ,"InterruptMask" },
1458: { kGEMInterruptAck ,"InterruptAck" },
1459: { kGEMInterruptAltStatus ,"InterruptAltStatus" },
1460: { kGEMPCIErrorStatus ,"PCIErrorStatus" },
1461: { kGEMPCIErrorMask ,"PCIErrorMask" },
1462: { kGEMBIFConfig ,"BIFConfig" },
1463: { kGEMBIFDiagnostic ,"BIFDiagnostic" },
1464: { kGEMSoftwareReset ,"SoftwareReset" },
1465: { kGEMTxKick ,"TxKick" },
1466: { kGEMTxConfig ,"TxConfig" },
1467: { kGEMTxDescBaseLo ,"TxDescBaseLo" },
1468: { kGEMTxDescBaseHi ,"TxDescBaseHi" },
1469: { kGEMTxFIFOWritePtr ,"TxFIFOWritePtr" },
1470: { kGEMTxFIFOShadowWritePtr ,"TxFIFOShadowWritePtr" },
1471: { kGEMTxFIFOReadPtr ,"TxFIFOReadPtr" },
1472: { kGEMTxFIFOShadowReadPtr ,"TxFIFOShadowReadPtr" },
1473: { kGEMTxFIFOPktCounter ,"TxFIFOPktCounter" },
1474: { kGEMTxStateMachine ,"TxStateMachine" },
1475: { kGEMTxDataPtrLo ,"TxDataPtrLo" },
1476: { kGEMTxDataPtrHi ,"TxDataPtrHi" },
1477: { kGEMTxCompletion ,"TxCompletion" },
1478: { kGEMTxFIFOAddr ,"TxFIFOAddr" },
1479: { kGEMTxFIFOTag ,"TxFIFOTag" },
1480: { kGEMTxFIFODataLo ,"TxFIFODataLo" },
1481: { kGEMTxFIFODataHiTag1 ,"TxFIFODataHiTag1" },
1482: { kGEMTxFIFODataHiTag0 ,"TxFIFODataHiTag0" },
1483: { kGEMTxFIFOSize ,"TxFIFOSize" },
1484: { kGEMRxConfig ,"RxConfig" },
1485: { kGEMRxDescBaseLo ,"RxDescBaseLo" },
1486: { kGEMRxDescBaseHi ,"RxDescBaseHi" },
1487: { kGEMRxFIFOWritePtr ,"RxFIFOWritePtr" },
1488: { kGEMRxFIFOShadowWritePtr ,"RxFIFOShadowWritePtr" },
1489: { kGEMRxFIFOReadPtr ,"RxFIFOReadPtr" },
1490: { kGEMRxFIFOPktCounter ,"RxFIFOPktCounter" },
1491: { kGEMRxStateMachine ,"RxStateMachine" },
1492: { kGEMRxPauseThresholds ,"RxPauseThresholds" },
1493: { kGEMRxDataPtrLo ,"RxDataPtrLo" },
1494: { kGEMRxDataPtrHi ,"RxDataPtrHi" },
1495: { kGEMRxKick ,"RxKick" },
1496: { kGEMRxCompletion ,"RxCompletion" },
1497: { kGEMRxIntBlanking ,"RxIntBlanking" },
1498: { kGEMRxFIFOAddr ,"RxFIFOAddr" },
1499: { kGEMRxFIFOTag ,"RxFIFOTag" },
1500: { kGEMRxDataLo ,"RxDataLo" },
1501: { kGEMRxDataHiTag0 ,"RxDataHiTag0" },
1502: { kGEMRxDataHiTag1 ,"RxDataHiTag1" },
1503: { kGEMRxFIFOSize ,"RxFIFOSize" },
1504: { kGEMMacTxResetCmd ,"MacTxResetCmd" },
1505: { kGEMMacRxResetCmd ,"MacRxResetCmd" },
1506: { kGEMMacSendPauseCmd ,"MacSendPauseCmd" },
1507: { kGEMMacTxStatus ,"MacTxStatus" },
1508: { kGEMMacRxStatus ,"MacRxStatus" },
1509: { kGEMMacControlStatus ,"MacControlStatus" },
1510: { kGEMMacTxMask ,"MacTxMask" },
1511: { kGEMMacRxMask ,"MacRxMask" },
1512: { kGEMMacControlMask ,"MacControlMask" },
1513: { kGEMMacTxMacConfig ,"MacTxMacConfig" },
1514: { kGEMMacRxMacConfig ,"MacRxMacConfig" },
1515: { kGEMMacControlConfig ,"MacControlConfig" },
1516: { kGEMMacXIFConfig ,"MacXIFConfig" },
1517: { kGEMMacInterPktGap0 ,"MacInterPktGap0" },
1518: { kGEMMacInterPktGap1 ,"MacInterPktGap1" },
1519: { kGEMMacInterPktGap2 ,"MacInterPktGap2" },
1520: { kGEMMacSlotTime ,"MacSlotTime" },
1521: { kGEMMacMinFrameSize ,"MacMinFrameSize" },
1522: { kGEMMacMaxFrameSize ,"MacMaxFrameSize" },
1523: { kGEMMacPASize ,"MacPASize" },
1524: { kGEMMacJamSize ,"MacJamSize" },
1525: { kGEMMacAttemptLimit ,"MacAttemptLimit" },
1526: { kGEMMacTypeControl ,"MacTypeControl" },
1527: { kGEMMacAddr ,"MacAddr" },
1528: { kGEMMacAddrFilter ,"MacAddrFilter" },
1529: { kGEMMacAddrFilterMask1 ,"MacAddrFilterMask1" },
1530: { kGEMMacAddrFilterMask0 ,"MacAddrFilterMask0" },
1531: { kGEMMacHashTable ,"MacHashTable" },
1532: { kGEMMacCollisions ,"MacCollisions" },
1533: { kGEMMacSingleCollision ,"MacSingleCollision" },
1534: { kGEMMacExcessCollisions ,"MacExcessCollisions" },
1535: { kGEMMacLateCollisions ,"MacLateCollisions" },
1536: { kGEMMacDeferTimer ,"MacDeferTimer" },
1537: { kGEMMacPeakAttempts ,"MacPeakAttempts" },
1538: { kGEMMacRxFrameCounter ,"MacRxFrameCounter" },
1539: { kGEMMacRxLengthErrors ,"MacRxLengthErrors" },
1540: { kGEMMacRxAlignErrors ,"MacRxAlignErrors" },
1541: { kGEMMacRxFCSErrors ,"MacRxFCSErrors" },
1542: { kGEMMacRxCodeErrors ,"MacRxCodeErrors" },
1543: { kGEMMacRandomSeed ,"MacRandomSeed" },
1544: { kGEMMacStateMachine ,"MacStateMachine" },
1545: { kGEMMIFCLock ,"MIFCLock" },
1546: { kGEMMIFData ,"MIFData" },
1547: { kGEMMIFOutputEnable ,"MIFOutputEnable" },
1548: { kGEMMIFFrame ,"MIFFrame" },
1549: { kGEMMIFConfig ,"MIFConfig" },
1550: { kGEMMIFMask ,"MIFMask" },
1551: { kGEMMIFStatus ,"MIFStatus" },
1552: { kGEMMIFStateMachine ,"MIFStateMachine" },
1553: { kGEMPCSControl ,"PCSControl" },
1554: { kGEMPCSStatus ,"PCSStatus" },
1555: { kGEMPCSAdvert ,"PCSAdvert" },
1556: { kGEMPCSLPAbility ,"PCSLPAbility" },
1557: { kGEMPCSConfig ,"PCSConfig" },
1558: { kGEMPCSStateMachine ,"PCSStateMachine" },
1559: { kGEMPCSInterruptStatus ,"PCSInterruptStatus" },
1560: { kGEMPCSDatapathMode ,"PCSDatapathMode" },
1561: { kGEMPCSSerdesControl ,"PCSSerdesControl" },
1562: { kGEMPCSSerdesOutputSelect ,"PCSSerdesOutputSelect"},
1563: { kGEMPCSSerdesState ,"PCSSerdesState" }
1564: };
1565:
1566: IOLog("\nEthernet(UniN): IO Address = %08x\n\r", (int)ioBaseEnet );
1567:
1568: for ( i=0; i < sizeof(regtable)/sizeof(regtable[0]); i++ )
1569: {
1570: switch ( regtable[i].reg >> 16 )
1571: {
1572: case 1:
1573: IOLog( "Ethernet(UniN): %04x: %s = %02x\n\r",
1574: (int)regtable[i].reg & 0xffff,
1575: regtable[i].text,
1576: ReadUniNRegister( ioBaseEnet, regtable[i].reg ) );
1577: break;
1578: case 2:
1579: IOLog( "Ethernet(UniN): %04x: %s = %04x\n\r",
1580: (int)regtable[i].reg & 0xffff,
1581: regtable[i].text,
1582: ReadUniNRegister( ioBaseEnet, regtable[i].reg ) );
1583: break;
1584: case 4:
1585: IOLog( "Ethernet(UniN): %04x: %s = %08x\n\r",
1586: (int)regtable[i].reg & 0xffff,
1587: regtable[i].text,
1588: ReadUniNRegister( ioBaseEnet, regtable[i].reg ) );
1589: break;
1590: }
1591: }
1592: }
1593:
1594:
1595: /*-------------------------------------------------------------------------
1596: *
1597: *
1598: *
1599: *-------------------------------------------------------------------------*/
1600:
1601: IOReturn UniNEnet::getHardwareAddress(enet_addr_t *ea)
1602: {
1603: UInt32 i;
1604: OSData *macEntry;
1605: UInt8 *macAddress;
1606: UInt32 len;
1607:
1608: macEntry = OSDynamicCast( OSData, nub->getProperty( "local-mac-address" ) );
1609: if ( macEntry == 0 )
1610: {
1611: return kIOReturnError;
1612: }
1613:
1614: macAddress = (UInt8 *)macEntry->getBytesNoCopy();
1615: if ( macAddress == 0 )
1616: {
1617: return kIOReturnError;
1618: }
1619:
1620: len = macEntry->getLength();
1621: if ( len != 6 )
1622: {
1623: return kIOReturnError;
1624: }
1625:
1626: for (i = 0; i < sizeof(*ea); i++)
1627: {
1628: ea->ea_byte[i] = macAddress[i];
1629: }
1630: return kIOReturnSuccess;
1631: }
1632:
1633: /*-------------------------------------------------------------------------
1634: *
1635: *
1636: *
1637: *-------------------------------------------------------------------------*/
1638:
1639: #define ENET_CRCPOLY 0x04c11db7
1640:
1641: static UInt32 crc416(UInt32 current, UInt16 nxtval )
1642: {
1643: register UInt32 counter;
1644: register int highCRCBitSet, lowDataBitSet;
1645:
1646: /* Swap bytes */
1647: nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8);
1648:
1649: /* Compute bit-by-bit */
1650: for (counter = 0; counter != 16; ++counter)
1651: { /* is high CRC bit set? */
1652: if ((current & 0x80000000) == 0)
1653: highCRCBitSet = 0;
1654: else
1655: highCRCBitSet = 1;
1656:
1657: current = current << 1;
1658:
1659: if ((nxtval & 0x0001) == 0)
1660: lowDataBitSet = 0;
1661: else
1662: lowDataBitSet = 1;
1663:
1664: nxtval = nxtval >> 1;
1665:
1666: /* do the XOR */
1667: if (highCRCBitSet ^ lowDataBitSet)
1668: current = current ^ ENET_CRCPOLY;
1669: }
1670: return current;
1671: }
1672:
1673: /*-------------------------------------------------------------------------
1674: *
1675: *
1676: *
1677: *-------------------------------------------------------------------------*/
1678:
1679: static UInt32 mace_crc(UInt16 *address)
1680: {
1681: register UInt32 newcrc;
1682:
1683: newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */
1684: newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */
1685: newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */
1686:
1687: return(newcrc);
1688: }
1689:
1690: /*-------------------------------------------------------------------------
1691: *
1692: *
1693: *
1694: *-------------------------------------------------------------------------*/
1695:
1696: /*
1697: * Add requested mcast addr to UniN's hash table filter.
1698: *
1699: */
1700: void UniNEnet::addToHashTableMask(UInt8 *addr)
1701: {
1702: UInt32 i,j;
1703: UInt32 crcBitIndex;
1704: UInt16 mask;
1705:
1706: j = mace_crc((UInt16 *)addr) & 0xFF; /* Big-endian alert! */
1707:
1708: for ( crcBitIndex = i = 0; i < 8; i++ )
1709: {
1710: crcBitIndex >>= 1;
1711: crcBitIndex |= (j & 0x80);
1712: j <<= 1;
1713: }
1714:
1715: crcBitIndex ^= 0xFF;
1716:
1717: if (hashTableUseCount[crcBitIndex]++)
1718: return; /* This bit is already set */
1719: mask = crcBitIndex % 16;
1720: mask = 1 << mask;
1721: hashTableMask[crcBitIndex/16] |= mask;
1722: }
1723:
1724: /*-------------------------------------------------------------------------
1725: *
1726: *
1727: *
1728: *-------------------------------------------------------------------------*/
1729:
1730: void UniNEnet::resetHashTableMask()
1731: {
1732: bzero(hashTableUseCount, sizeof(hashTableUseCount));
1733: bzero(hashTableMask, sizeof(hashTableMask));
1734: }
1735:
1736: /*-------------------------------------------------------------------------
1737: *
1738: *
1739: *
1740: *-------------------------------------------------------------------------*/
1741:
1742: /*
1743: * Sync the adapter with the software copy of the multicast mask
1744: * (logical address filter).
1745: */
1746: void UniNEnet::updateHashTableMask()
1747: {
1748: UInt32 i;
1749: UInt16 rxCFGReg;
1750:
1751: rxCFGReg = ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig);
1752: WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, rxCFGReg & ~(kGEMMacRxMacConfig_RxMacEnable |
1753: kGEMMacRxMacConfig_HashFilterEnable) );
1754:
1755: while ( ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig) & (kGEMMacRxMacConfig_RxMacEnable |
1756: kGEMMacRxMacConfig_HashFilterEnable) )
1757: ;
1758: for (i=0; i<16; i++ )
1759: {
1760: WriteUniNRegister( ioBaseEnet, kGEMMacHashTable + i*4, hashTableMask[15-i] );
1761: }
1762:
1763: rxCFGReg |= kGEMMacRxMacConfig_HashFilterEnable;
1764: WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, rxCFGReg );
1765: }
1766:
1767:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.