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