|
|
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: * Hardware independent (relatively) code for the Mace Ethernet Controller
29: *
30: * HISTORY
31: *
32: * dd-mmm-yy
33: * Created.
34: *
35: */
36:
37: #import "MaceEnetPrivate.h"
38:
39: @implementation MaceEnet
40:
41: /*
42: * Public Factory Methods
43: */
44:
45: + (BOOL)probe:(IODeviceDescription *)devDesc
46: {
47: MaceEnet *MaceEnetInstance;
48: extern int kdp_flag;
49:
50: /*
51: * If bootargs: kdp bit 0 using in-kernel mace driver for early debugging,
52: * Don't probe this driver.
53: */
54: if( kdp_flag & 1)
55: {
56: return nil;
57: }
58:
59: MaceEnetInstance = [self alloc];
60: return [MaceEnetInstance initFromDeviceDescription:devDesc] != nil;
61: }
62:
63: /*
64: * Public Instance Methods
65: */
66:
67: /*-------------------------------------------------------------------------
68: *
69: *
70: *
71: *-------------------------------------------------------------------------*/
72:
73: - initFromDeviceDescription:(IOTreeDevice *)devDesc
74: {
75: IORange *ioRangeMace;
76:
77: if ([super initFromDeviceDescription:devDesc] == nil)
78: {
79: IOLog( "Ethernet(Mace): [super initFromDeviceDescription] failed\n");
80: return nil;
81: }
82:
83: if ( [devDesc numMemoryRanges] < 3 )
84: {
85: IOLog( "Ethernet(Mace): Incorrect deviceDescription - 1\n\r");
86: return nil;
87: }
88:
89: ioRangeMace = [devDesc memoryRangeList];
90:
91: ioBaseEnet = (IOPPCAddress) ioRangeMace[0].start;
92: ioBaseEnetTxDMA = (IOPPCAddress) ioRangeMace[1].start;
93: ioBaseEnetRxDMA = (IOPPCAddress) ioRangeMace[2].start;
94:
95: ioBaseEnetROM = (IOPPCAddress) (((unsigned int) ioBaseEnet & ~0xffff) | kControllerROMOffset);
96:
97: if ( ![self resetAndEnable:NO] )
98: {
99: [self free];
100: return nil;
101: }
102:
103: [self _getStationAddress:&myAddress];
104:
105: if ([self _allocateMemory] == NO)
106: {
107: [self free];
108: return nil;
109: }
110:
111: if ( ![self resetAndEnable:YES] )
112: {
113: [self free];
114: return nil;
115: }
116:
117: isPromiscuous = NO;
118: multicastEnabled = NO;
119:
120: networkInterface = [super attachToNetworkWithAddress:myAddress];
121:
122: return self;
123: }
124:
125:
126: /*-------------------------------------------------------------------------
127: *
128: *
129: *
130: *-------------------------------------------------------------------------*/
131:
132: - free
133: {
134: int i;
135:
136: [self clearTimeout];
137:
138: [self _resetChip];
139:
140: if (networkInterface)
141: [networkInterface free];
142:
143: for (i = 0; i < rxMaxCommand; i++)
144: if (rxNetbuf[i]) nb_free(rxNetbuf[i]);
145:
146: for (i = 0; i < txMaxCommand; i++)
147: if (txNetbuf[i]) nb_free(txNetbuf[i]);
148:
149: return [super free];
150: }
151:
152: /*-------------------------------------------------------------------------
153: *
154: *
155: *
156: *-------------------------------------------------------------------------*/
157: - (void) interruptOccurredAt:(int)irqNum
158: {
159:
160: [self reserveDebuggerLock];
161:
162: // kprintf("IRQ = %d\n",irqNum );
163:
164: switch ( irqNum )
165: {
166: case kIRQEnetTxDMA:
167: txWDInterrupts++;
168: KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 );
169: [self _transmitInterruptOccurred];
170: KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 );
171: [self enableInterrupt:kIRQEnetTxDMA];
172: [self serviceTransmitQueue];
173: break;
174: case kIRQEnetRxDMA:
175: KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 );
176: [self _receiveInterruptOccurred];
177: KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 );
178: [self enableInterrupt:kIRQEnetRxDMA];
179: break;
180: }
181:
182: [self releaseDebuggerLock];
183: }
184:
185:
186: /*-------------------------------------------------------------------------
187: *
188: *
189: *
190: *-------------------------------------------------------------------------*/
191:
192: - (void) serviceTransmitQueue
193: {
194: netbuf_t packet;
195: u_int32_t i;
196:
197: while ( 1 )
198: {
199: if ( ![transmitQueue count] )
200: {
201: break;
202: }
203:
204: i = txCommandTail + 1;
205: if ( i >= txMaxCommand ) i = 0;
206: if ( i == txCommandHead )
207: {
208: break;
209: }
210: packet = [transmitQueue dequeue];
211: [self _transmitPacket:packet];
212: }
213:
214: }
215:
216: /*-------------------------------------------------------------------------
217: *
218: *
219: *
220: *-------------------------------------------------------------------------*/
221:
222: - (void)transmit:(netbuf_t)pkt
223: {
224: u_int32_t i;
225: u_int32_t n;
226: u_int8_t regValue;
227:
228: KERNEL_DEBUG(DBG_MACE_TXQUEUE | DBG_FUNC_NONE, (int) pkt, (int) nb_size(pkt), 0, 0, 0 );
229:
230: /*
231: * Hold the debugger lock so the debugger can't interrupt us
232: */
233: [self reserveDebuggerLock];
234:
235: do
236: {
237: /*
238: * Someone is turning off the receiver before the first transmit.
239: * Dont know who yet!
240: */
241: regValue = ReadMaceRegister( ioBaseEnet, kMacCC );
242: regValue |= kMacCCEnRcv;
243: WriteMaceRegister( ioBaseEnet, kMacCC, regValue );
244:
245: /*
246: * Preliminary sanity checks
247: */
248: if (!pkt)
249: {
250: IOLog("EtherNet(Mace): transmit received NULL netbuf\n");
251: continue;
252: }
253: if ( ![self isRunning] )
254: {
255: nb_free(pkt);
256: continue;
257: }
258:
259: /*
260: * Remove any completed packets from the Tx ring
261: */
262: [self _transmitInterruptOccurred];
263:
264: /*
265: * Refill the Tx ring from the Transmit waiting list
266: */
267: [self serviceTransmitQueue];
268:
269: /*
270: * If the Transmit waiting list is not empty or the Tx ring is
271: * full, add the new packet to the waiting list.
272: */
273: n = [transmitQueue count];
274: if ( n > 0 )
275: {
276: if ( n >= [transmitQueue maxCount] )
277: {
278: IOLog("Ethernet(Mace) Transmit queue overflow\n");
279: }
280:
281: [transmitQueue enqueue:pkt];
282: continue;
283: }
284: i = txCommandTail + 1;
285: if ( i >= txMaxCommand ) i = 0;
286: if ( i == txCommandHead )
287: {
288: [transmitQueue enqueue:pkt];
289: continue;
290: }
291:
292: /*
293: * If there is space on the Tx ring, add the packet directly to the
294: * ring
295: */
296: [self _transmitPacket:pkt];
297: }
298: while( 0 );
299:
300: [self releaseDebuggerLock];
301:
302: }
303:
304: /*-------------------------------------------------------------------------
305: *
306: *
307: *
308: *-------------------------------------------------------------------------*/
309:
310: - (int) transmitQueueSize
311: {
312: return (TRANSMIT_QUEUE_SIZE);
313: }
314:
315: - (int) transmitQueueCount
316: {
317: return ([transmitQueue count]);
318: }
319: /*-------------------------------------------------------------------------
320: *
321: *
322: *
323: *-------------------------------------------------------------------------*/
324:
325: - (BOOL)resetAndEnable:(BOOL)enable
326: {
327: resetAndEnabled = NO;
328: [self clearTimeout];
329: [self disableAllInterrupts];
330: [self _resetChip];
331:
332: if (enable)
333: {
334: if ( ![self _initRxRing] || ![self _initTxRing] || ![self _initChip] )
335: {
336: [self setRunning:NO];
337: return NO;
338: }
339:
340: [self _startChip];
341:
342: [self setRelativeTimeout: WATCHDOG_TIMER_MS];
343:
344: [self enableInterrupt:kIRQEnetRxDMA];
345: [self enableInterrupt:kIRQEnetTxDMA];
346: [self _enableAdapterInterrupts];
347:
348: resetAndEnabled = YES;
349: }
350:
351: [self setRunning:enable];
352:
353: return YES;
354: }
355:
356: /*-------------------------------------------------------------------------
357: *
358: *
359: *
360: *-------------------------------------------------------------------------*/
361:
362: - (void)timeoutOccurred
363: {
364: u_int32_t dmaStatus;
365:
366: if ( ![self isRunning] )
367: {
368: return;
369: }
370:
371: [self reserveDebuggerLock];
372:
373: /*
374: * Check for DMA shutdown on receive channel
375: */
376: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA );
377: if ( !(dmaStatus & kdbdmaActive) )
378: {
379: IOLog( "Ethernet(Mace): Checking for timeout - RxHead = %d RxTail = %d\n\r", rxCommandHead, rxCommandTail);
380: #if 0
381: IOLog( "Ethernet(Mace): Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) );
382: [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)];
383: #endif
384: [self _receiveInterruptOccurred];
385: }
386:
387: /*
388: * If there are pending entries on the Tx ring
389: */
390: if ( txCommandHead != txCommandTail )
391: {
392: /*
393: * If we did not service the Tx ring during the last timeout interval,
394: * then force servicing of the Tx ring.
395: * If we have more than one timeout interval without any transmit interrupts,
396: * then force the transmitter to reset.
397: */
398: if ( txWDInterrupts == 0 )
399: {
400: if ( ++txWDTimeouts > 1 ) txWDForceReset = YES;
401:
402: IOLog( "Ethernet(Mace): Checking for timeout - TxHead = %d TxTail = %d\n\r", txCommandHead, txCommandTail);
403: [self _transmitInterruptOccurred];
404: }
405: else
406: {
407: txWDTimeouts = 0;
408: txWDInterrupts = 0;
409: }
410: }
411: else
412: {
413: txWDTimeouts = 0;
414: txWDInterrupts = 0;
415: }
416:
417: /*
418: * Restart the watchdog timer
419: */
420: [self setRelativeTimeout: WATCHDOG_TIMER_MS];
421:
422: [self releaseDebuggerLock];
423:
424: }
425:
426: /*-------------------------------------------------------------------------
427: *
428: *
429: *
430: *-------------------------------------------------------------------------*/
431:
432: - (netbuf_t)allocateNetbuf
433: {
434: netbuf_t packet;
435:
436: packet = nb_alloc(NETWORK_BUFSIZE);
437: if (!packet)
438: {
439: IOLog("nb_alloc() returned NULL\n");
440: }
441:
442: return packet;
443: }
444:
445: /*-------------------------------------------------------------------------
446: *
447: *
448: *
449: *-------------------------------------------------------------------------*/
450:
451: - (BOOL)enablePromiscuousMode
452: {
453: u_int8_t regVal;
454:
455: isPromiscuous = YES;
456:
457: [self reserveDebuggerLock];
458:
459: regVal = ReadMaceRegister( ioBaseEnet, kMacCC );
460: WriteMaceRegister( ioBaseEnet, kMacCC, regVal & ~kMacCCEnRcv );
461: regVal |= kMacCCProm;
462: WriteMaceRegister( ioBaseEnet, kMacCC, regVal );
463:
464: [self releaseDebuggerLock];
465:
466: return YES;
467: }
468:
469: - (void)disablePromiscuousMode
470: {
471: u_int8_t regVal;
472:
473: isPromiscuous = NO;
474:
475: [self reserveDebuggerLock];
476:
477: regVal = ReadMaceRegister(ioBaseEnet, kMacCC);
478: WriteMaceRegister( ioBaseEnet, kMacCC, regVal & ~kMacCCEnRcv );
479: regVal &= ~kMacCCProm;
480: WriteMaceRegister( ioBaseEnet, kMacCC, regVal );
481:
482: [self releaseDebuggerLock];
483:
484: }
485:
486: - (BOOL)enableMulticastMode
487: {
488: multicastEnabled = YES;
489: return YES;
490: }
491:
492: - (void)disableMulticastMode
493: {
494: multicastEnabled = NO;
495: }
496:
497: - (void)addMulticastAddress:(enet_addr_t *)addr
498: {
499: multicastEnabled = YES;
500: [self reserveDebuggerLock];
501: [self _addToHashTableMask:addr->ea_byte];
502: [self _updateHashTableMask];
503: [self releaseDebuggerLock];
504: }
505:
506: - (void)removeMulticastAddress:(enet_addr_t *)addr
507: {
508: [self reserveDebuggerLock];
509: [self _removeFromHashTableMask:addr->ea_byte];
510: [self _updateHashTableMask];
511: [self releaseDebuggerLock];
512: }
513:
514: /*
515: * Kernel Debugger Support
516: */
517: - (void)sendPacket:(void *)pkt length:(unsigned int)pkt_len
518: {
519: [self _sendPacket:(void *)pkt length:(unsigned int)pkt_len];
520: }
521:
522: - (void)receivePacket:(void *)pkt length:(unsigned int *)pkt_len timeout:(unsigned int)timeout
523: {
524: [self _receivePacket:(void *)pkt length:(unsigned int *)pkt_len timeout:(unsigned int)timeout];
525: }
526:
527: /*
528: * Power management methods.
529: */
530: - (IOReturn)getPowerState:(PMPowerState *)state_p
531: {
532: return IO_R_UNSUPPORTED;
533: }
534:
535: - (IOReturn)setPowerState:(PMPowerState)state
536: {
537: if (state == PM_OFF) {
538: resetAndEnabled = NO;
539: [self _resetChip];
540: return IO_R_SUCCESS;
541: }
542: return IO_R_UNSUPPORTED;
543: }
544:
545: - (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p
546: {
547: return IO_R_UNSUPPORTED;
548: }
549:
550: - (IOReturn)setPowerManagement:(PMPowerManagementState)state
551: {
552: return IO_R_UNSUPPORTED;
553: }
554:
555: @end
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.