Annotation of kernel/bsd/dev/ppc/drvDECchip21040/DECchip2104xPrivate.m, revision 1.1

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 DECchip 21040 and 21041. 
        !            30:  *
        !            31:  * HISTORY
        !            32:  *
        !            33:  * 26-Apr-95   Rakesh Dubey (rdubey) at NeXT 
        !            34:  *     Created.
        !            35:  * 11-Oct-95   Dieter Siegmund (dieter) at NeXT
        !            36:  *     Added performance hooks; changed transmit interrupt
        !            37:  *     to only interrupt every N / 2 times, where N is the
        !            38:  *     number of transmit descriptors.  This reduces the
        !            39:  *      number of interrupts taken, and the amount of CPU
        !            40:  *     used by the driver.
        !            41:  * 02-Nov-95   Rakesh Dubey (rdubey) at NeXT 
        !            42:  *     Added support for 21041 based adapters.
        !            43:  *        -- serial ROM for station address
        !            44:  *        -- new network interface selection scheme
        !            45:  * 11-Dec-95   Dieter Siegmund (dieter) at NeXT
        !            46:  *     Split out 21040 and 21041 connector auto-detect logic.
        !            47:  * 07-Feb-96   Dieter Siegmund (dieter) at NeXT
        !            48:  *     Fixed multicast.
        !            49:  * 25-Jun-96   Dieter Siegmund (dieter) at NeXT
        !            50:  *     Added kernel debugger support.
        !            51:  * 05-Aug-97   Joe Liu at Apple
        !            52:  *     Made kernel debugger support more robust.
        !            53:  */
        !            54: 
        !            55: #import "DECchip2104x.h"
        !            56: #import "DECchip2104xPrivate.h"
        !            57: 
        !            58: #import <machdep/ppc/proc_reg.h>
        !            59: #import <mach/vm_param.h>                      // PAGE_SIZE
        !            60: 
        !            61: extern void                     *kernel_map;
        !            62: extern kern_return_t            kmem_alloc_wired();
        !            63: 
        !            64: //#define DEBUG
        !            65: 
        !            66: #import "DECchip2104xInline.h"
        !            67: 
        !            68: #ifdef DEBUG
        !            69: static void IOBreak()
        !            70: {
        !            71:     //IOBreakToDebugger();
        !            72:     return;
        !            73: }
        !            74: 
        !            75: static void printDesc(void *descriptorStruct)
        !            76: {
        !            77:     txDescriptorStruct *desc = (txDescriptorStruct *)descriptorStruct;
        !            78:     
        !            79:     IOLog("DESC: ");
        !            80:     IOLog("%x (%x) ", (unsigned int)&desc->status.data, desc->status.data);
        !            81:     IOLog("%x (%x: %x %x) ", (unsigned int)&desc->control.data, desc->control.data, desc->control.reg.byteCountBuffer1, desc->control.reg.byteCountBuffer2);
        !            82:     IOLog("%x (%x) ", (unsigned int)&desc->bufferAddress1, desc->bufferAddress1);
        !            83:     IOLog("%x (%x) ", (unsigned int)&desc->bufferAddress2, desc->bufferAddress2);
        !            84:     IOLog("\n");
        !            85:     
        !            86: }
        !            87: #endif DEBUG
        !            88: 
        !            89: /*
        !            90:  * Breaks up an ethernet data buffer into two physical chunks. We know that
        !            91:  * the buffer can't straddle more than two pages. If the content of paddr2 is
        !            92:  * zero this means that all of the buffer lies in one physical page. Note
        !            93:  * that we use the fact that tx and rx descriptors have the same size and
        !            94:  * same layout of relevent fields (data address and count). 
        !            95:  */
        !            96: static BOOL 
        !            97: IOUpdateDescriptorFromNetBuf(netbuf_t nb, void *desc, BOOL isReceive)
        !            98: {
        !            99:     IOReturn           result;
        !           100:     vm_address_t       pageBreak;
        !           101:     unsigned int       len;
        !           102:     vm_address_t       vaddr;
        !           103:     unsigned int       *paddr1, *paddr2;
        !           104:     
        !           105:     struct _descriptorStruct {
        !           106:        unsigned int status;
        !           107:        union   {
        !           108:            struct {
        !           109:                unsigned int
        !           110:                    rsvd                :10,
        !           111:                    byteCountBuffer2    :11,
        !           112:                    byteCountBuffer1    :11;
        !           113:            } reg;
        !           114:            unsigned int data;
        !           115:        } control;
        !           116:        unsigned int bufferAddress1;
        !           117:        unsigned int bufferAddress2;
        !           118:     } *descriptorStruct;
        !           119:     
        !           120:     
        !           121:     descriptorStruct = (struct _descriptorStruct *)desc;
        !           122:     len = isReceive ? NETWORK_BUFSIZE : nb_size(nb);
        !           123:     
        !           124:     vaddr = (vm_address_t)nb_map(nb);
        !           125:     paddr1 = &descriptorStruct->bufferAddress1;
        !           126:     paddr2 = &descriptorStruct->bufferAddress2;
        !           127:     
        !           128:     /* Assume contiguity */
        !           129:     *paddr2 = 0;
        !           130:     descriptorStruct->control.reg.byteCountBuffer2 = 0;
        !           131:     descriptorStruct->control.reg.byteCountBuffer1 = len;
        !           132:     
        !           133:     result = IOPhysicalFromVirtual(IOVmTaskSelf(), vaddr, paddr1);
        !           134:     if (result != IO_R_SUCCESS) {
        !           135:        return NO;
        !           136:     }
        !           137:     
        !           138:     /*
        !           139:      * Now check if this memory block crosses a page boundary. 
        !           140:      */
        !           141:     if (trunc_page(vaddr) == trunc_page(vaddr+len))    {
        !           142:        return YES;
        !           143:     }
        !           144:     
        !           145:     /* Nice try... */
        !           146:     pageBreak = round_page(vaddr);
        !           147:     descriptorStruct->control.reg.byteCountBuffer1 = pageBreak - vaddr;
        !           148:     descriptorStruct->control.reg.byteCountBuffer2 = len - (pageBreak - vaddr);
        !           149:     
        !           150:     result = IOPhysicalFromVirtual(IOVmTaskSelf(), pageBreak, paddr2);
        !           151:     if (result != IO_R_SUCCESS) {
        !           152:        return NO;
        !           153:     }
        !           154:     
        !           155:     return YES;
        !           156: }
        !           157: 
        !           158: 
        !           159: @implementation DECchip2104x (Private)
        !           160: 
        !           161: /*
        !           162:  * Private functions
        !           163:  */
        !           164: - (BOOL)_allocateMemory
        !           165: {
        !           166:     int                        i;
        !           167:     IOReturn           result;
        !           168: 
        !           169: //kprintf("[DECchip2104x _allocateMemory]\n");
        !           170: 
        !           171:     memorySize = sizeof(rxDescriptorStruct) * DEC_21X40_RX_RING_LENGTH
        !           172:        + sizeof(txDescriptorStruct) * DEC_21X40_TX_RING_LENGTH
        !           173:        + DEC_21X40_DESCRIPTOR_ALIGNMENT * 2
        !           174:        + sizeof(setupBuffer_t) + DEC_21X40_DESCRIPTOR_ALIGNMENT;
        !           175:     if (memorySize > PAGE_SIZE) {
        !           176:        IOLog("%s: 1 page limit exceeded for descriptor memory\n",[self name]);
        !           177:        return NO;
        !           178:     }
        !           179: 
        !           180:     /*
        !           181:      * We need one page of contiguous memory.
        !           182:      */
        !           183:     result = kmem_alloc_wired(kernel_map,(vm_offset_t *)&memoryPtr,memorySize);
        !           184:     if (result != KERN_SUCCESS) {
        !           185:         IOLog ("%s: can't allocate 0x%x bytes of memory\n",
        !           186:               [self name], memorySize);
        !           187:        return NO;
        !           188:     }
        !           189: 
        !           190:     rxRing = (rxDescriptorStruct *)memoryPtr;
        !           191:     if (!IOIsAligned(rxRing, DEC_21X40_DESCRIPTOR_ALIGNMENT))
        !           192:        rxRing = IOAlign(rxDescriptorStruct *, rxRing, 
        !           193:            DEC_21X40_DESCRIPTOR_ALIGNMENT);
        !           194:     for (i = 0 ; i < DEC_21X40_RX_RING_LENGTH ; i++) {
        !           195:        bzero((void *)&rxRing[i], sizeof(rxDescriptorStruct));
        !           196:        rxNetbuf[i] = NULL;
        !           197:     }
        !           198:     
        !           199:     txRing = (txDescriptorStruct *)(rxRing + DEC_21X40_RX_RING_LENGTH);
        !           200:     if (!IOIsAligned(txRing, DEC_21X40_DESCRIPTOR_ALIGNMENT))
        !           201:        txRing = IOAlign(txDescriptorStruct *, txRing, 
        !           202:            DEC_21X40_DESCRIPTOR_ALIGNMENT);
        !           203:     for (i = 0 ; i < DEC_21X40_TX_RING_LENGTH ; i++) {
        !           204:        bzero((void *)&txRing[i], sizeof(txDescriptorStruct));
        !           205:        txNetbuf[i] = NULL;
        !           206:     }
        !           207:     
        !           208:     setupBuffer = (setupBuffer_t *)(txRing + DEC_21X40_TX_RING_LENGTH);
        !           209:     if (!IOIsAligned(setupBuffer, DEC_21X40_DESCRIPTOR_ALIGNMENT))
        !           210:        setupBuffer = IOAlign(setupBuffer_t *, 
        !           211:                setupBuffer, DEC_21X40_DESCRIPTOR_ALIGNMENT);
        !           212:     result = IOPhysicalFromVirtual(IOVmTaskSelf(),
        !           213:        (vm_address_t)setupBuffer, (unsigned *)&setupBufferPhysical);
        !           214:     if (result != IO_R_SUCCESS) {
        !           215:         IOLog("%s: Invalid shared memory address\n", [self name]);
        !           216:         return NO;
        !           217:     }
        !           218:     
        !           219:     return YES;
        !           220: }
        !           221: 
        !           222: #ifdef DEBUG
        !           223: - (void)_dumpRegisters
        !           224: {
        !           225:     int i;
        !           226:     
        !           227:     return;
        !           228:     IOLog("%s: Regs: ", [self name]);
        !           229:     for (i = 0; i <= 15; i++) {
        !           230:        IOLog("%02d: %x ", i, readCsr(ioBase, 8*i));
        !           231:     }
        !           232:     IOLog("\n");
        !           233: }
        !           234: #endif DEBUG
        !           235: 
        !           236: #ifdef DEBUG
        !           237: - (void)_dumpDescriptor:(void *)ds
        !           238: {
        !           239:     txDescriptorStruct *desc = (txDescriptorStruct *)ds;
        !           240:     
        !           241:     IOLog("%s: Desc: ", [self name]);
        !           242:     IOLog("%x  ", *(unsigned int *)&desc->status);
        !           243:     IOLog("%x  ", *(unsigned int *)&desc->control);
        !           244:     IOLog("%x  ", *(unsigned int *)&desc->bufferAddress1);
        !           245:     IOLog("%x  ", *(unsigned int *)&desc->bufferAddress2);
        !           246:     IOLog("\n");
        !           247: }
        !           248: #endif DEBUG
        !           249: 
        !           250: - (BOOL)_initTxRing
        !           251: {
        !           252:     unsigned int i;
        !           253: 
        !           254: //kprintf("[DECchip2104x _initTxRing]\n");
        !           255:     
        !           256:     for (i = 0; i < DEC_21X40_TX_RING_LENGTH; i++) {
        !           257:        bzero((void *)&txRing[i], sizeof(txDescriptorStruct));
        !           258:        txRing[i].status.reg.own = DEC_21X40_DESC_OWNED_BY_HOST;
        !           259:        if (txNetbuf[i]) {
        !           260:            nb_free(txNetbuf[i]);
        !           261:            txNetbuf[i] = NULL;
        !           262:        }
        !           263:     }
        !           264:     txRing[DEC_21X40_TX_RING_LENGTH-1].control.reg.ter = YES;
        !           265:      
        !           266:     txPutIndex = 0;
        !           267:     txDoneIndex = 0;
        !           268:     txNumFree = DEC_21X40_TX_RING_LENGTH;
        !           269:     txIntCount = 0;
        !           270: 
        !           271:     /* Init the transmit queue. */
        !           272:     if (transmitQueue) {
        !           273:        [transmitQueue free];
        !           274:     }
        !           275:     transmitQueue = [[IONetbufQueue alloc] 
        !           276:                        initWithMaxCount:TRANSMIT_QUEUE_SIZE];
        !           277:     if (!transmitQueue)        {
        !           278:         IOPanic("_initTxRing");
        !           279:     }
        !           280:     
        !           281:     return YES;
        !           282: }
        !           283: 
        !           284: - (BOOL)_initRxRing
        !           285: {
        !           286:     int        i;
        !           287:     BOOL       status;
        !           288: 
        !           289: //kprintf("[DECchip2104x _initRxRing]\n");
        !           290: 
        !           291:     for (i = 0; i < DEC_21X40_RX_RING_LENGTH; i++) {
        !           292:        bzero((void *)&rxRing[i], sizeof(rxDescriptorStruct));
        !           293:        rxRing[i].status.reg.own = DEC_21X40_DESC_OWNED_BY_HOST;
        !           294:        if (rxNetbuf[i] == NULL)        {
        !           295:            rxNetbuf[i] = [self allocateNetbuf];
        !           296:            if (rxNetbuf[i] == NULL)    {
        !           297:                IOPanic("allocateNetbuf returned NULL in _initRxRing");
        !           298:            }
        !           299:        }
        !           300:        status = IOUpdateDescriptorFromNetBuf(rxNetbuf[i], 
        !           301:                        (void *)&rxRing[i], YES);
        !           302:        if (status == NO)
        !           303:            IOPanic("_initRxRing");
        !           304:        rxRing[i].status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           305:     }
        !           306:     
        !           307:     rxRing[DEC_21X40_RX_RING_LENGTH-1].control.reg.rer = YES;
        !           308: 
        !           309:     rxDoneIndex = 0;
        !           310:     
        !           311:     return YES;
        !           312: }
        !           313: 
        !           314: 
        !           315: - (BOOL) _initChip
        !           316: {
        !           317: 
        !           318: //kprintf("[DECchip2104x _initChip]\n");
        !           319: 
        !           320:     [self _initRegisters];
        !           321:     [self _startTransmit];
        !           322: 
        !           323:     /*
        !           324:      * Set up station, broadcast, and multicast addresses
        !           325:      */
        !           326:     if (![self _setAddressFiltering:YES])
        !           327:        return NO;
        !           328: 
        !           329:     [self selectInterface];
        !           330: 
        !           331: #ifdef DEBUG
        !           332:     [self _dumpRegisters];
        !           333: #endif DEBUG
        !           334:     
        !           335:     return YES;
        !           336: }
        !           337: 
        !           338: - (void)_resetChip
        !           339: {
        !           340:     csrRegUnion reg;
        !           341: 
        !           342: //kprintf("[DECchip2104x _resetChip]\n");
        !           343:     
        !           344:     reg.data = 0;
        !           345:     reg.csr0.swr = 1;                  /* reset */
        !           346:     writeCsr(ioBase, DEC_21X40_CSR0, reg.data);
        !           347:     IODelay(100);
        !           348:     reg.csr0.swr = 0;                  /* deassert */
        !           349:     writeCsr(ioBase, DEC_21X40_CSR0, reg.data);
        !           350:     
        !           351:     IOSleep(1);                                /* >= 100 PCI bus cycles */
        !           352: }
        !           353: 
        !           354: - (void)_startTransmit
        !           355: {
        !           356: 
        !           357: //kprintf("[DECchip2104x _startTransmit]\n");
        !           358: 
        !           359:     operationMode.csr6.st = YES;
        !           360:     writeCsr(ioBase, DEC_21X40_CSR6, operationMode.data);
        !           361: }
        !           362: 
        !           363: - (void)_startReceive
        !           364: {
        !           365: 
        !           366: //kprintf("[DECchip2104x _startReceive]\n");
        !           367: 
        !           368:     operationMode.csr6.sr = YES;
        !           369:     writeCsr(ioBase, DEC_21X40_CSR6, operationMode.data);
        !           370: }
        !           371: 
        !           372: - (void)_initRegisters
        !           373: {
        !           374:     IOReturn   result;
        !           375:     csrRegUnion reg;
        !           376:    
        !           377:     unsigned int paddr;
        !           378: 
        !           379: //kprintf("[DECchip2104x _initRegisters]\n");
        !           380:     
        !           381:     [self _resetChip];
        !           382:     
        !           383:     reg.data = 0;
        !           384:     reg.csr0.dbo = 1;           /* Big Endian Descriptors */
        !           385: //    reg.csr0.ble = 1;           /* Big Endian Buffers */   
        !           386:     reg.csr0.pbl = 16;         /* errata: don't set to 0 or 32 */
        !           387:     reg.csr0.cal = 1;          /* depends upon NETWORK_BUFALIGNMENT */
        !           388:     writeCsr(ioBase, DEC_21X40_CSR0, reg.data);                /* bus mode */
        !           389:     
        !           390:     result = IOPhysicalFromVirtual(IOVmTaskSelf(),
        !           391:        (vm_address_t)rxRing, (unsigned int *)&paddr);
        !           392:     if (result != IO_R_SUCCESS) {
        !           393:         IOLog("%s: Invalid shared memory address\n", [self name]);
        !           394:         return;
        !           395:     }
        !           396:     reg.data = 0;
        !           397:     reg.csr3.rdlba = (unsigned int)paddr;
        !           398:     writeCsr(ioBase, DEC_21X40_CSR3, reg.data);        /* receive list base */
        !           399:     
        !           400:     result = IOPhysicalFromVirtual(IOVmTaskSelf(),
        !           401:        (vm_address_t)txRing, (unsigned int *)&paddr);
        !           402:     if (result != IO_R_SUCCESS) {
        !           403:         IOLog("%s: Invalid shared memory address\n", [self name]);
        !           404:         return;
        !           405:     }
        !           406:     reg.data = 0;
        !           407:     reg.csr4.tdlba = (unsigned int)paddr;
        !           408:     writeCsr(ioBase, DEC_21X40_CSR4, reg.data);        /* transmit list base */
        !           409: 
        !           410:     reg.data = 0;      /* FIXME -- choose appropriate values */
        !           411:     writeCsr(ioBase, DEC_21X40_CSR6, reg.data);        /* operations mode */
        !           412:     operationMode.data = reg.data;
        !           413:     
        !           414:     reg.data = 0;
        !           415:     reg.csr7.tim = reg.csr7.rim = reg.csr7.tjm = 1;
        !           416:     reg.csr7.nim = 1;
        !           417: #ifdef DEBUG    
        !           418:     reg.csr7.tim = reg.csr7.tsm = reg.csr7.tum = reg.csr7.tjm = 1;
        !           419:     reg.csr7.unm = reg.csr7.rim = reg.csr7.rum = 1;
        !           420:     reg.csr7.atm = 1;
        !           421:     reg.csr7.lfm = reg.csr7.sem = reg.csr7.aim = 1;
        !           422: #endif DEBUG
        !           423:     interruptMask.data = reg.data;
        !           424:     
        !           425:     writeCsr(ioBase, DEC_21X40_CSR11, 0);      /* no full duplex */
        !           426: }
        !           427: 
        !           428: - (void)_transmitPacket:(netbuf_t)packet
        !           429: {
        !           430:     csrRegUnion                reg;
        !           431:     txDescriptorStruct *desc;
        !           432:     BOOL               status;
        !           433: 
        !           434: //kprintf("[DECchip2104x _transmitPacket]\n");
        !           435:     
        !           436:     [self performLoopback:packet];
        !           437: 
        !           438:     [self reserveDebuggerLock];
        !           439: 
        !           440:     if (txNumFree == 0) {
        !           441:        [self releaseDebuggerLock];
        !           442:        nb_free(packet);
        !           443:        return;
        !           444:     }
        !           445:     
        !           446:     desc = &txRing[txPutIndex];
        !           447:     txNetbuf[txPutIndex] = packet;
        !           448:     
        !           449:     if (desc->control.reg.ter == 1) {
        !           450:        desc->control.data = 0;
        !           451:        desc->control.reg.ter = 1;
        !           452:     } 
        !           453:     else
        !           454:        desc->control.data = 0;
        !           455: 
        !           456:     status = IOUpdateDescriptorFromNetBuf(packet, (void *)desc, NO);
        !           457:     if (status == NO)  {
        !           458:        [self releaseDebuggerLock];
        !           459:        IOLog("%s: _transmitPacket: IOUpdateDescriptorFromNetBuf failed\n",
        !           460:                [self name]);
        !           461:        nb_free(packet);                /* this is the best we can do here */
        !           462:        return;
        !           463:     }
        !           464:                
        !           465:     desc->control.reg.fs = YES;
        !           466:     desc->control.reg.ls = YES;
        !           467:     if (++txIntCount == (DEC_21X40_TX_RING_LENGTH / 2)) {
        !           468:        desc->control.reg.ic = YES;
        !           469:        txIntCount = 0;
        !           470:     }
        !           471:     else
        !           472:        desc->control.reg.ic = NO;
        !           473: 
        !           474:     desc->status.data = 0;
        !           475:     desc->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           476:     
        !           477:     // txPutIndex = (txPutIndex + 1) % DEC_21X40_TX_RING_LENGTH;
        !           478:     if (++txPutIndex == DEC_21X40_TX_RING_LENGTH)
        !           479:        txPutIndex = 0;
        !           480:     --txNumFree;
        !           481: 
        !           482:     /*  
        !           483:      * Make the chip poll immediately.  
        !           484:      */
        !           485:     reg.data = 0;
        !           486:     reg.csr1.tpd = YES;
        !           487:     writeCsr(ioBase, DEC_21X40_CSR1, reg.data);
        !           488: 
        !           489:     [self releaseDebuggerLock];
        !           490: 
        !           491:     return;
        !           492: }
        !           493: 
        !           494: /*
        !           495:  * Method: receivePacket
        !           496:  *
        !           497:  * Purpose:
        !           498:  *   Part of kerneldebugger protocol.
        !           499:  */
        !           500: - (void)receivePacket:(void *)pkt length:(unsigned int *)pkt_len
        !           501:     timeout:(unsigned int)timeout
        !           502: {
        !           503:     *pkt_len = 0;
        !           504:     timeout *= 1000;
        !           505: 
        !           506:     if (resetAndEnabled == NO)
        !           507:        return;
        !           508: 
        !           509:     while (1) {
        !           510:        if (rxRing[rxDoneIndex].status.reg.own  
        !           511:            == DEC_21X40_DESC_OWNED_BY_HOST) {
        !           512:            rxDescriptorStruct *        rds;
        !           513: 
        !           514:            rds = &rxRing[rxDoneIndex];
        !           515:            if (rds->status.reg.es 
        !           516:                || (!rds->status.reg.fs || !rds->status.reg.ls) 
        !           517:                || (rds->status.reg.fl < ETHERMINPACKET)) {
        !           518:                rxRing[rxDoneIndex].status.reg.own 
        !           519:                    = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           520:                // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH;
        !           521:                if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH)
        !           522:                    rxDoneIndex = 0;
        !           523:            }
        !           524:            else
        !           525:                break;
        !           526:        }
        !           527:        else {
        !           528:            if ((int)timeout <= 0)
        !           529:                return;
        !           530:            IODelay(50);
        !           531:            timeout -= 50;
        !           532:        }
        !           533:     }
        !           534:     {
        !           535:        rxDescriptorStruct *    rds;
        !           536: 
        !           537:        rds = &rxRing[rxDoneIndex];
        !           538:        *pkt_len = rds->status.reg.fl - ETHERCRC;
        !           539:        bcopy(nb_map(rxNetbuf[rxDoneIndex]), pkt, *pkt_len);
        !           540: 
        !           541:        rds->status.data = 0;
        !           542:        rds->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           543:        // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH;
        !           544:        if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH)
        !           545:            rxDoneIndex = 0;
        !           546:     }
        !           547:     return;
        !           548: }
        !           549: /*
        !           550:  * Method: sendPacket
        !           551:  *
        !           552:  * Purpose:
        !           553:  *   Part of kerneldebugger protocol.
        !           554:  */
        !           555: - (void)sendPacket:(void *)pkt length:(unsigned int)pkt_len
        !           556: {
        !           557:     int                                        size;
        !           558:     volatile txDescriptorStruct        *       desc;
        !           559:     csrRegUnion                                reg;
        !           560:     BOOL                               status;
        !           561: 
        !           562:        if (resetAndEnabled == NO)
        !           563:                return; /* can't transmit right now */
        !           564:        
        !           565:        [self _transmitInterruptOccurred];
        !           566:        
        !           567:     if (txNumFree == 0) {
        !           568:                IOLog("%s: _sendPacket: No free tx descriptors\n", [self name]);
        !           569:                return; /* can't transmit right now */
        !           570:        }
        !           571:        
        !           572:     desc = &txRing[txPutIndex];
        !           573:     txNetbuf[txPutIndex] = NULL;
        !           574:     
        !           575:     bcopy(pkt, nb_map(KDB_txBuf), pkt_len);
        !           576:     size = nb_size(KDB_txBuf);
        !           577:     nb_shrink_bot(KDB_txBuf, size - pkt_len);
        !           578: 
        !           579:     if (desc->control.reg.ter == 1) {
        !           580:        desc->control.data = 0;
        !           581:        desc->control.reg.ter = 1;
        !           582:     } 
        !           583:     else
        !           584:        desc->control.data = 0;
        !           585: 
        !           586:     status = IOUpdateDescriptorFromNetBuf(KDB_txBuf, (void *)desc, NO);
        !           587:     if (status == NO)  {
        !           588:        IOLog("%s: _sendPacket: IOUpdateDescriptorFromNetBuf failed\n",
        !           589:              [self name]);
        !           590:        return;
        !           591:     }
        !           592:                
        !           593:     desc->control.reg.fs = YES;
        !           594:     desc->control.reg.ls = YES;
        !           595:     desc->control.reg.ic = NO;
        !           596:     desc->status.data = 0;
        !           597:     desc->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           598:     
        !           599:     // txPutIndex = (txPutIndex + 1) % DEC_21X40_TX_RING_LENGTH;
        !           600:     if (++txPutIndex == DEC_21X40_TX_RING_LENGTH)
        !           601:        txPutIndex = 0;
        !           602:     --txNumFree;
        !           603: 
        !           604:     /*  
        !           605:      * Make the chip poll immediately.  
        !           606:      */
        !           607:     reg.data = 0;
        !           608:     reg.csr1.tpd = YES;
        !           609:     writeCsr(ioBase, DEC_21X40_CSR1, reg.data);
        !           610:     
        !           611:     { /* poll for completion */
        !           612:        int i;
        !           613:        for (i = 0; 
        !           614:             i < 10000 && desc->status.reg.own == DEC_21X40_DESC_OWNED_BY_CTRL;
        !           615:             i++) {
        !           616:            IODelay(500);
        !           617:        }
        !           618:     }
        !           619:     if (desc->status.reg.own == DEC_21X40_DESC_OWNED_BY_CTRL)
        !           620:        IOLog("%s: _sendPacket: polling timed out\n", [self name]);
        !           621: 
        !           622:     /* restore the actual size of the buffer */
        !           623:     nb_grow_bot(KDB_txBuf, size - pkt_len);
        !           624: 
        !           625:     return;
        !           626: }
        !           627: 
        !           628: - (BOOL)_receiveInterruptOccurred
        !           629: {
        !           630:     netbuf_t                   packet;
        !           631:     BOOL                       passPacketUp;
        !           632:     rxDescriptorStruct *       rds;
        !           633:     unsigned int               receivedFrameSize;
        !           634:     BOOL                       status;
        !           635: 
        !           636: //kprintf("[DECchip2104x _receiveInterruptOccurred]\n");
        !           637:     
        !           638:     [self reserveDebuggerLock];
        !           639:     
        !           640:     while (rxRing[rxDoneIndex].status.reg.own
        !           641:           == DEC_21X40_DESC_OWNED_BY_HOST) {
        !           642:        passPacketUp = NO;
        !           643:        rds = &rxRing[rxDoneIndex];
        !           644:        receivedFrameSize = rds->status.reg.fl - ETHERCRC;
        !           645:        
        !           646:        /*
        !           647:         * Bad packet. Just leave the netbuf in place.  
        !           648:         */
        !           649:        if (rds->status.reg.es
        !           650:            || (!rds->status.reg.fs || !rds->status.reg.ls) 
        !           651:            || (receivedFrameSize < (ETHERMINPACKET - ETHERCRC))) {
        !           652:            [networkInterface incrementInputErrors];
        !           653:            rxRing[rxDoneIndex].status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           654:            // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH;
        !           655:            if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH)
        !           656:                rxDoneIndex = 0;
        !           657:            continue;
        !           658:        }
        !           659:        
        !           660:        /*  Toss packets not in our multicast address-space.  */
        !           661:        packet = rxNetbuf[rxDoneIndex];
        !           662:        if (isPromiscuous 
        !           663:            || rds->status.reg.mf == NO 
        !           664:            || [super isUnwantedMulticastPacket:
        !           665:                (ether_header_t *)nb_map(packet)] == NO) {
        !           666:            netbuf_t newPacket;
        !           667: 
        !           668:            newPacket = [self allocateNetbuf];
        !           669:            if (newPacket != NULL)      {
        !           670:                rxNetbuf[rxDoneIndex] = newPacket;
        !           671:                passPacketUp = YES;
        !           672:                status = 
        !           673:                    IOUpdateDescriptorFromNetBuf(rxNetbuf[rxDoneIndex], 
        !           674:                                                 (void *)&rxRing[rxDoneIndex], 
        !           675:                                                 YES);
        !           676:                if (status == NO) {
        !           677:                    IOPanic("DECchip21040: IOUpdateDescriptorFromNetBuf\n"); 
        !           678:                }
        !           679:                /*  Adjust to size received */
        !           680:                nb_shrink_bot(packet, nb_size(packet) - receivedFrameSize);
        !           681:            } 
        !           682:        }
        !           683:        rds->status.data = 0;
        !           684:        rds->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           685:        
        !           686:        // rxDoneIndex = (rxDoneIndex + 1) % DEC_21X40_RX_RING_LENGTH;
        !           687:        if (++rxDoneIndex == DEC_21X40_RX_RING_LENGTH)
        !           688:            rxDoneIndex = 0;
        !           689:        if (passPacketUp) {
        !           690:            passPacketUp = NO;
        !           691:            [self releaseDebuggerLock];
        !           692:            [networkInterface handleInputPacket:packet extra:0];
        !           693:            [self reserveDebuggerLock];
        !           694:        }
        !           695:     }
        !           696: 
        !           697:     [self releaseDebuggerLock];
        !           698:     
        !           699:     return YES;
        !           700: }
        !           701: 
        !           702: - (BOOL)_transmitInterruptOccurred
        !           703: {
        !           704:     txDescriptorStruct         *tds;
        !           705: 
        !           706: //kprintf("[DECchip2104x _transmitInterruptOccurred]\n");
        !           707:     
        !           708:     while (txNumFree < DEC_21X40_TX_RING_LENGTH) { 
        !           709:        tds = &txRing[txDoneIndex];
        !           710:        if (tds->status.reg.own == DEC_21X40_DESC_OWNED_BY_CTRL)
        !           711:            break;
        !           712:        
        !           713:        if (tds->control.reg.set == 1)  {
        !           714:            //IOLog("TX interrupt: Ignoring set up packet\n");
        !           715:            // txDoneIndex = (txDoneIndex + 1) % DEC_21X40_TX_RING_LENGTH;
        !           716:            if (++txDoneIndex == DEC_21X40_TX_RING_LENGTH)
        !           717:                txDoneIndex = 0;
        !           718:            ++txNumFree;
        !           719:            continue;
        !           720:        }
        !           721: 
        !           722:        if (tds->status.reg.uf || tds->status.reg.ec
        !           723:                || tds->status.reg.lc || tds->status.reg.nc 
        !           724:                || tds->status.reg.to)
        !           725:            [networkInterface incrementOutputErrors];
        !           726:        else
        !           727:            [networkInterface incrementOutputPackets];
        !           728:        
        !           729:        if (tds->status.reg.ec)
        !           730:            [networkInterface incrementCollisionsBy:16];
        !           731:        else if (tds->status.reg.cc)
        !           732:            [networkInterface incrementCollisionsBy:tds->status.reg.cc];
        !           733:        if (tds->status.reg.lc && !tds->status.reg.uf)
        !           734:            [networkInterface incrementCollisions];
        !           735:            
        !           736:         if (txNetbuf[txDoneIndex] != NULL) {
        !           737:            nb_free(txNetbuf[txDoneIndex]);
        !           738:            txNetbuf[txDoneIndex] = NULL;
        !           739:        }
        !           740:        // txDoneIndex = (txDoneIndex + 1) % DEC_21X40_TX_RING_LENGTH;
        !           741:        if (++txDoneIndex == DEC_21X40_TX_RING_LENGTH)
        !           742:            txDoneIndex = 0;
        !           743:        ++txNumFree;
        !           744:     }
        !           745:     
        !           746:     return YES;
        !           747: }
        !           748: 
        !           749: #define DEC_21X40_SETUP_TIMEOUT        10000
        !           750: 
        !           751: - (BOOL)_loadSetupFilter:(BOOL)pollingMode
        !           752: {
        !           753:     txDescriptorStruct         *setupDescriptor;
        !           754:     unsigned int       time = DEC_21X40_SETUP_TIMEOUT;
        !           755:     csrRegUnion                reg;
        !           756: 
        !           757: //kprintf("[DECchip2104x _loadSetupFilter]\n");
        !           758:     
        !           759:     /*
        !           760:      * Make sure that we have a descriptor for setup frame
        !           761:      */
        !           762:     if (txNumFree == 0)
        !           763:        return NO;
        !           764: 
        !           765:     setupDescriptor = &txRing[txPutIndex];
        !           766:     // txPutIndex = (txPutIndex + 1) % DEC_21X40_TX_RING_LENGTH;
        !           767:     if (++txPutIndex == DEC_21X40_TX_RING_LENGTH)
        !           768:        txPutIndex = 0;
        !           769:     --txNumFree;
        !           770: 
        !           771:     /*
        !           772:      * Initialize the Setup descriptor
        !           773:      */
        !           774:     if (setupDescriptor->control.reg.ter == YES)       {
        !           775:        setupDescriptor->control.data = 0;
        !           776:        setupDescriptor->control.reg.ter = YES;
        !           777:     } else {
        !           778:        setupDescriptor->control.data = 0;
        !           779:     }
        !           780:     
        !           781:     setupDescriptor->control.reg.set = YES;
        !           782:     setupDescriptor->control.reg.ic = YES;
        !           783:     setupDescriptor->control.reg.byteCountBuffer1 = 
        !           784:                sizeof(setupBuffer_t);
        !           785:     setupDescriptor->control.reg.byteCountBuffer2 = 0;
        !           786: 
        !           787:     setupDescriptor->bufferAddress1 = setupBufferPhysical;
        !           788:     setupDescriptor->bufferAddress2 = 0;
        !           789: 
        !           790:     setupDescriptor->status.data = 0;
        !           791:     setupDescriptor->status.reg.own = DEC_21X40_DESC_OWNED_BY_CTRL;
        !           792: 
        !           793:     /* tell the chip about this setup command */
        !           794:     reg.data = 0;
        !           795:     reg.csr1.tpd = YES;
        !           796:     writeCsr(ioBase, DEC_21X40_CSR1, reg.data);
        !           797:     
        !           798:     if (pollingMode) {
        !           799:        while (time--) {
        !           800:            IODelay(5);
        !           801:            reg.data = readCsr(ioBase, DEC_21X40_CSR5);
        !           802:            if (reg.csr5.tu) {
        !           803:                writeCsr(ioBase, DEC_21X40_CSR5, reg.data);
        !           804:                break;
        !           805:            }
        !           806:        }
        !           807: 
        !           808:        // txDoneIndex = (txDoneIndex + 1) % DEC_21X40_TX_RING_LENGTH;
        !           809:        if (++txDoneIndex == DEC_21X40_TX_RING_LENGTH)
        !           810:            txDoneIndex = 0;
        !           811:        ++txNumFree;
        !           812:     }
        !           813:     
        !           814:     return YES;
        !           815: }
        !           816: 
        !           817: - (BOOL)_setAddressFiltering:(BOOL)pollingMode 
        !           818: {
        !           819:     int                        i;
        !           820:     BOOL               status = YES;                           
        !           821:     unsigned           q_count;        
        !           822:     unsigned short     *address;
        !           823: 
        !           824: //kprintf("[DECchip2104x _setAddressFiltering]\n");
        !           825: 
        !           826:     /*
        !           827:      * Copy station address into the first entry.  Note that the
        !           828:      * upper 2 bytes of all longwords in the setup frame are don't
        !           829:      * cares for perfect filtering.
        !           830:      */
        !           831:     address = (unsigned short *)&myAddress;
        !           832:     for (i = 0 ; i < 3; i++) {
        !           833:       unsigned short addr = (unsigned short)*address++;
        !           834:       setupBuffer->physicalAddress[0][i] = (addr << 16);
        !           835:     }
        !           836: 
        !           837:     /*
        !           838:      * Load the broadcast address in the second entry
        !           839:      */
        !           840:     for (i = 0 ; i < 3; i++) {
        !           841:          setupBuffer->physicalAddress[1][i] = 0xffffffff;
        !           842:     }
        !           843: 
        !           844:     /*
        !           845:      * Skip over the first 2 entries
        !           846:      */
        !           847:     q_count = 2;
        !           848:         
        !           849:     if (multicastEnabled) {
        !           850:         enetMulti_t             *multiAddr;
        !           851:         queue_head_t            *multiQueue = [super multicastQueue];
        !           852: 
        !           853:         if (!queue_empty(multiQueue)) {
        !           854:             /*
        !           855:              * Fill in the addresses
        !           856:              */
        !           857:             queue_iterate(multiQueue, multiAddr, enetMulti_t *, link) {
        !           858:                union {
        !           859:                      unsigned char     bytes[4];
        !           860:                      unsigned long     word;
        !           861:                } typeConvert; 
        !           862: 
        !           863:                typeConvert.word = 0;
        !           864: 
        !           865:                for (i = 0; i < 3; i++) {
        !           866:                    typeConvert.bytes[0] = multiAddr->address.ea_byte[i*2];
        !           867:                    typeConvert.bytes[1] = multiAddr->address.ea_byte[i*2+1];
        !           868:                    setupBuffer->physicalAddress[q_count][i] = 
        !           869:                        typeConvert.word;
        !           870:                }
        !           871:                if (++q_count >= DEC_21X40_SETUP_PERFECT_ENTRIES) {
        !           872:                    IOLog("%s: %d multicast address limit exceeded\n",
        !           873:                        [self name], DEC_21X40_SETUP_PERFECT_MCAST_ENTRIES);
        !           874:                    break;
        !           875:                }
        !           876:            }
        !           877:        }
        !           878:     }
        !           879:     
        !           880:     /* 
        !           881:      * Duplicate station address for remaining entries
        !           882:      */
        !           883:     for (; q_count < DEC_21X40_SETUP_PERFECT_ENTRIES; ++q_count) {
        !           884:        bcopy(setupBuffer->physicalAddress[0], 
        !           885:            setupBuffer->physicalAddress[q_count], 
        !           886:            3 * sizeof (long));
        !           887:     }
        !           888: 
        !           889:     if (![self _loadSetupFilter:pollingMode])
        !           890:        status = NO;
        !           891: 
        !           892:     return status;
        !           893: }
        !           894: 
        !           895: 
        !           896: @end
        !           897: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.