Annotation of XNU/iokit/Drivers/network/drvIntel82557/i82557Private.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1996 NeXT Software, Inc.  All rights reserved. 
        !            24:  *
        !            25:  * i82557Private.cpp
        !            26:  *
        !            27:  */
        !            28: 
        !            29: #include "i82557.h"
        !            30: 
        !            31: extern "C" {
        !            32: #include <sys/param.h>
        !            33: #include <sys/mbuf.h>
        !            34: #include <string.h>
        !            35: }
        !            36: 
        !            37: //---------------------------------------------------------------------------
        !            38: // Function: IOPhysicalFromVirtual
        !            39: //
        !            40: // Hack, remove ASAP.
        !            41: 
        !            42: static inline IOReturn
        !            43: IOPhysicalFromVirtual(vm_address_t vaddr, IOPhysicalAddress * paddr)
        !            44: {
        !            45:        *paddr = pmap_extract(kernel_pmap, vaddr);
        !            46:        return (*paddr == 0) ? kIOReturnBadArgument : kIOReturnSuccess;
        !            47: }
        !            48: 
        !            49: //---------------------------------------------------------------------------
        !            50: // Function: _intrACK
        !            51: //
        !            52: // Purpose:
        !            53: //   Acknowledge all of the pending interrupt sources.
        !            54: //
        !            55: // Returns:
        !            56: //   Return the interrupt status.
        !            57: //
        !            58: // CSR usage:
        !            59: //   Read/Write: SCB status
        !            60: 
        !            61: static inline scb_status_t _intrACK(CSR_t * CSR_p)
        !            62: {
        !            63:        scb_status_t stat_irq = OSReadLE16(&CSR_p->status) & SCB_STATUS_INT_MASK;
        !            64:        if (stat_irq)
        !            65:                OSWriteLE16(&CSR_p->status, stat_irq);  // ack pending interrupts.
        !            66:     return (stat_irq);
        !            67: }
        !            68: 
        !            69: //---------------------------------------------------------------------------
        !            70: // Function: _waitSCBCommandClear
        !            71: //
        !            72: // Purpose:
        !            73: //   Wait for the SCB Command field to clear.  Ensures that we don't
        !            74: //   overrun the NIC's command unit.
        !            75: //
        !            76: // Returns:
        !            77: //   true  if the SCB command field was cleared.
        !            78: //   false if the SCB command field was not cleared.
        !            79: //
        !            80: // CSR usage:
        !            81: //   Read: SCB command
        !            82: 
        !            83: static inline bool
        !            84: _waitSCBCommandClear(CSR_t * CSR_p)
        !            85: {
        !            86:     for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !            87:                if (!OSReadLE8(&CSR_p->command))
        !            88:                return true;
        !            89:                IODelay(SPIN_COUNT);
        !            90:     }
        !            91:     return false;      // hardware is not responding.
        !            92: }
        !            93: 
        !            94: //---------------------------------------------------------------------------
        !            95: // Function: _waitCUNonActive
        !            96: //
        !            97: // Purpose:
        !            98: //   Waits for the Command Unit to become inactive.
        !            99: //
        !           100: // Returns:
        !           101: //   true  if the CU has become inactive.
        !           102: //   false if the CU remains active.
        !           103: //
        !           104: // CSR usage:
        !           105: //   Read: SCB status
        !           106: 
        !           107: static inline bool
        !           108: _waitCUNonActive(CSR_t * CSR_p)
        !           109: {
        !           110:     for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !           111:                if (CSR_VALUE(SCB_STATUS_CUS, OSReadLE16(&CSR_p->status)) != 
        !           112:                        SCB_CUS_ACTIVE)
        !           113:                        return true;
        !           114:                IODelay(SPIN_COUNT);
        !           115:        }
        !           116:        return false;
        !           117: }
        !           118: 
        !           119: //---------------------------------------------------------------------------
        !           120: // Function: _polledCommand:WithAddress
        !           121: //
        !           122: // Purpose:
        !           123: //   Issue a polled command to the NIC.
        !           124: 
        !           125: bool Intel82557::_polledCommand(cbHeader_t * hdr_p, IOPhysicalAddress paddr)
        !           126: {
        !           127:     if (!_waitSCBCommandClear(CSR_p)) {
        !           128:                IOLog("%s: _polledCommand:(%s): _waitSCBCommandClear failed\n",
        !           129:                        CUCommandString(CSR_VALUE(CB_CMD, OSReadLE16(&hdr_p->command))),
        !           130:                        getName());
        !           131:                return false;
        !           132:     }
        !           133: 
        !           134:     if (!_waitCUNonActive(CSR_p)) {
        !           135:                IOLog("%s: _polledCommand:(%s): _waitCUNonActive failed\n",
        !           136:                        CUCommandString(CSR_VALUE(CB_CMD, OSReadLE16(&hdr_p->command))),
        !           137:                        getName());
        !           138:                return false;
        !           139:     }
        !           140: 
        !           141:        // Set the physical address of the command block, and issue a
        !           142:        // command unit start.
        !           143:        //
        !           144:        OSWriteLE32(&CSR_p->pointer, paddr);
        !           145:        OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_START));
        !           146: 
        !           147:        prevCUCommand = SCB_CUC_START;
        !           148: 
        !           149:     for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !           150:                if (OSReadLE16(&hdr_p->status) & CB_STATUS_C)
        !           151:                        return true;
        !           152:                IODelay(SPIN_COUNT);
        !           153:     }
        !           154:     return false;
        !           155: }
        !           156: 
        !           157: //---------------------------------------------------------------------------
        !           158: // Function: _abortReceive
        !           159: //
        !           160: // Purpose:
        !           161: //   Abort the receive unit.
        !           162: 
        !           163: bool Intel82557::_abortReceive()
        !           164: {
        !           165:     if (!_waitSCBCommandClear(CSR_p)) {
        !           166:                IOLog("%s: _abortReceive: _waitSCBCommandClear failed\n", getName());
        !           167:                return false;
        !           168:     }
        !           169: 
        !           170:        OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_RUC, SCB_RUC_ABORT));
        !           171: 
        !           172:     for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !           173:                if (CSR_VALUE(SCB_STATUS_RUS, OSReadLE16(&CSR_p->status)) == 
        !           174:                        SCB_RUS_IDLE)
        !           175:                        return true;
        !           176:                IODelay(SPIN_COUNT);
        !           177:     }
        !           178: 
        !           179:        IOLog("%s: _abortReceive: timeout\n", getName());       
        !           180:     return false;
        !           181: }
        !           182: 
        !           183: //---------------------------------------------------------------------------
        !           184: // Function: _startReceive
        !           185: //
        !           186: // Purpose:
        !           187: //   Start the receive unit
        !           188: 
        !           189: bool Intel82557::_startReceive()
        !           190: {
        !           191:     if (!_waitSCBCommandClear(CSR_p)) {
        !           192:                IOLog("%s: _startReceive: _waitSCBCommandClear failed\n", getName());
        !           193:                return false;
        !           194:     }
        !           195: 
        !           196:        // Make sure the initial RFD has a link to its RBD
        !           197:        OSWriteLE32(&headRfd->rbdAddr, headRfd->_rbd._paddr);
        !           198: 
        !           199:        OSWriteLE32(&CSR_p->pointer, headRfd->_paddr);
        !           200:        OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_RUC, SCB_RUC_START));
        !           201: 
        !           202:     for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !           203:                if (CSR_VALUE(SCB_STATUS_RUS, OSReadLE16(&CSR_p->status)) == 
        !           204:                        SCB_RUS_READY)
        !           205:                        return true;
        !           206:                IODelay(SPIN_COUNT);
        !           207:     }
        !           208: 
        !           209:        IOLog("%s: _startReceive: timeout\n", getName());               
        !           210:     return false;
        !           211: }
        !           212: 
        !           213: //---------------------------------------------------------------------------
        !           214: // Function: _resetChip
        !           215: //
        !           216: // Purpose:
        !           217: //   Issue a selective reset then a full reset.
        !           218: //   This is done to avoid a PCI bus hang if the 82557 is in the midst of
        !           219: //   a PCI bus cycle. The selective reset pauses the transmit and receive
        !           220: //   engines.
        !           221: //
        !           222: void Intel82557::_resetChip()
        !           223: {
        !           224:     int i = 0;
        !           225: 
        !           226:        sendPortCommand(portSelectiveReset_e, 0);
        !           227:     do {
        !           228:                IOSleep(1);
        !           229:     } while (OSReadLE32(&CSR_p->port) && ++i < 100);
        !           230: 
        !           231:        sendPortCommand(portReset_e, 0);
        !           232:     IOSleep(1);
        !           233:     return;
        !           234: }
        !           235: 
        !           236: //---------------------------------------------------------------------------
        !           237: // Function: issueReset
        !           238: //
        !           239: // Purpose:
        !           240: //   Shut down the chip, and issue a reset.
        !           241: 
        !           242: void Intel82557::issueReset()
        !           243: {
        !           244:     IOLog("%s: resetting adapter\n", getName());
        !           245: 
        !           246:        etherStats->dot3RxExtraEntry.resets++;
        !           247: 
        !           248:        setAdapterLevel(kAdapterLevel0);
        !           249:        if (!setAdapterLevel(currentLevel)) {
        !           250:                IOLog("%s: Reset attempt unsuccessful\n", getName());
        !           251:        }
        !           252: }
        !           253: 
        !           254: //---------------------------------------------------------------------------
        !           255: // Function: updateRFDFromMbuf
        !           256: //
        !           257: // Purpose:
        !           258: //   Updated a RFD/RBD in order to attach it to a cluster mbuf.
        !           259: //   XXX - assume cluster will never cross page boundary.
        !           260: 
        !           261: bool Intel82557::updateRFDFromMbuf(rfd_t * rfd_p, struct mbuf * m)
        !           262: {
        !           263:        struct IOPhysicalSegment vector;
        !           264:        UInt count;
        !           265: 
        !           266:        count = rxMbufCursor->getPhysicalSegments(m, &vector, 1);
        !           267:        if (!count)
        !           268:                return false;
        !           269:        
        !           270:        // Start modifying RFD
        !           271:        //
        !           272:        rfd_p->_rbd.buffer = vector.location;   // cursor is little-endian
        !           273: //     OSWriteLE32(&rfd_p->_rbd.size, CSR_FIELD(RBD_SIZE, vector.length));
        !           274: 
        !           275:        rfd_p->_rbd._mbuf = m;
        !           276:        
        !           277:     return true;
        !           278: }
        !           279: 
        !           280: //---------------------------------------------------------------------------
        !           281: // Function: _initTcbQ
        !           282: //
        !           283: // Purpose:
        !           284: //   Initialize the transmit control block queue.  Create a circularly
        !           285: //   linked list of tcbs.
        !           286: 
        !           287: bool Intel82557::_initTcbQ(bool enable = false)
        !           288: {
        !           289:     int i;
        !           290: 
        !           291:     tcbQ.numFree = tcbQ.numTcbs = NUM_TRANSMIT_FRAMES;
        !           292:     tcbQ.activeHead_p = tcbQ.activeTail_p = tcbQ.freeHead_p = tcbList_p;
        !           293: 
        !           294:     for (i = 0; i < tcbQ.numTcbs; i++) { /* free up buffers */
        !           295:                if (tcbList_p[i]._mbuf) {
        !           296:                        freePacket(tcbList_p[i]._mbuf);
        !           297:                        tcbList_p[i]._mbuf = 0;
        !           298:                }
        !           299:     }
        !           300:     bzero(tcbList_p, sizeof(tcb_t) * tcbQ.numTcbs);
        !           301: 
        !           302:        if (!enable)
        !           303:                return true;
        !           304: 
        !           305:     for (i = 0; i < tcbQ.numTcbs; i++) {
        !           306:                IOPhysicalAddress paddr;
        !           307:                
        !           308:                IOReturn result = IOPhysicalFromVirtual((vm_address_t) &tcbList_p[i],
        !           309:                                                 &tcbList_p[i]._paddr);
        !           310:                if (result != kIOReturnSuccess) {
        !           311:                        IOLog("i82557(tcbQ): Invalid TCB address\n");
        !           312:                        return false;
        !           313:                }
        !           314: 
        !           315:                result = IOPhysicalFromVirtual((vm_address_t) &tcbList_p[i]._tbds,
        !           316:                                        &paddr);
        !           317:                if (result != kIOReturnSuccess) {
        !           318:                        IOLog("i82557(tcbQ): Invalid TBD address\n");
        !           319:                        return false;
        !           320:                }
        !           321:                OSWriteLE32(&tcbList_p[i].tbdAddr, paddr);
        !           322: 
        !           323:                if (i == (tcbQ.numTcbs - 1))
        !           324:                        tcbList_p[i]._next = &tcbList_p[0];
        !           325:                else
        !           326:                        tcbList_p[i]._next = &tcbList_p[i + 1];
        !           327:     }
        !           328:     for (i = 0; i < tcbQ.numTcbs; i++) /* make physical links */
        !           329:                OSWriteLE32(&tcbList_p[i].link, tcbList_p[i]._next->_paddr);
        !           330:        
        !           331:        return true;
        !           332: }
        !           333: 
        !           334: //---------------------------------------------------------------------------
        !           335: // Function: _setupRfd
        !           336: 
        !           337: static void _setupRfd(rfd_t * rfdList_p)
        !           338: {
        !           339:     for (int i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           340:                if (i == (NUM_RECEIVE_FRAMES - 1)) {
        !           341:                        /* mark tails and link the lists circularly */
        !           342:                        OSSetLE16(&rfdList_p[i].command, RFD_COMMAND_EL);
        !           343:                        rfdList_p[i]._next = &rfdList_p[0];
        !           344:                        OSSetLE32(&rfdList_p[i]._rbd.size, RBD_SIZE_EL);
        !           345:                        rfdList_p[i]._rbd._next = &rfdList_p[0]._rbd;
        !           346:                }
        !           347:                else {
        !           348:                        rfdList_p[i]._next = &rfdList_p[i + 1];
        !           349:                        rfdList_p[i]._rbd._next = &rfdList_p[i + 1]._rbd;
        !           350:                }
        !           351: 
        !           352:                OSWriteLE32(&rfdList_p[i].link, rfdList_p[i]._next->_paddr);
        !           353:                OSWriteLE32(&rfdList_p[i].rbdAddr,
        !           354:                     (i == 0) ? rfdList_p[0]._rbd._paddr : C_NULL);
        !           355:                
        !           356:                OSWriteLE32(&rfdList_p[i]._rbd.link, rfdList_p[i]._rbd._next->_paddr);
        !           357:                OSSetLE32(&rfdList_p[i]._rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE));
        !           358:        }
        !           359: }
        !           360: 
        !           361: //---------------------------------------------------------------------------
        !           362: // Function: _initRfdList
        !           363: //
        !           364: // Purpose:
        !           365: //   Create a circularly linked list of receive frame descriptors, and 
        !           366: //   populate them with receive buffers allocated from our special pool.
        !           367: 
        !           368: bool Intel82557::_initRfdList(bool enable = false)
        !           369: {
        !           370:     int                        i;
        !           371:     IOReturn   result;
        !           372: 
        !           373:     /* free allocated packet buffers */
        !           374:        for (i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           375:                if (rfdList_p[i]._rbd._mbuf) {
        !           376:                        freePacket(rfdList_p[i]._rbd._mbuf);
        !           377: //                     rfdList_p[i]._rbd._mbuf = 0;
        !           378:                }
        !           379:        }
        !           380: 
        !           381:     /* zero out the entire structure, and re-create it */
        !           382:     bzero(rfdList_p, sizeof(rfd_t) * NUM_RECEIVE_FRAMES);
        !           383: 
        !           384:        if (!enable)
        !           385:                return true;
        !           386: 
        !           387:        for (i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           388:                OSSetLE16(&rfdList_p[i].command, RFD_COMMAND_SF);
        !           389:                
        !           390:                result = IOPhysicalFromVirtual((vm_address_t) &rfdList_p[i],
        !           391:                                                       &rfdList_p[i]._paddr);
        !           392:                if (result != kIOReturnSuccess) {
        !           393:                        IOLog("%s: Invalid RFD address\n", getName());
        !           394:                        return false;
        !           395:                }
        !           396:                result = IOPhysicalFromVirtual((vm_address_t) &rfdList_p[i]._rbd,
        !           397:                                        &rfdList_p[i]._rbd._paddr);
        !           398:                if (result != kIOReturnSuccess) {
        !           399:                        IOLog("%s: Invalid RBD address\n", getName());
        !           400:                        return false;
        !           401:                }
        !           402:     }
        !           403: 
        !           404:        _setupRfd(rfdList_p);
        !           405: 
        !           406:     for (i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           407:                // Pre-load the receive ring with max size mbuf packets.
        !           408:                //              
        !           409:                struct mbuf * m = allocatePacket(MAX_BUF_SIZE);
        !           410:                if (!m)
        !           411:                        return false;
        !           412:                
        !           413:                if (updateRFDFromMbuf(&rfdList_p[i], m) == false) {
        !           414:                        IOLog("%s: updateRFDFromMbuf() error\n", getName());
        !           415:                        freePacket(m);
        !           416:                        return false;
        !           417:                }
        !           418:     }
        !           419: 
        !           420:     headRfd = rfdList_p;
        !           421:     tailRfd = rfdList_p + NUM_RECEIVE_FRAMES - 1;
        !           422: 
        !           423:     return true;
        !           424: }
        !           425: 
        !           426: //---------------------------------------------------------------------------
        !           427: // Function: _resetRfdList
        !           428: //
        !           429: // Purpose:
        !           430: //   Reset the RFD list before the receiver engine is restarted after
        !           431: //   a resource shortage.
        !           432: 
        !           433: bool Intel82557::_resetRfdList()
        !           434: {
        !           435:     int                i;
        !           436: 
        !           437:        struct _cache {
        !           438:                IOPhysicalAddress rbd_buffer;
        !           439:                struct mbuf *     rbd_mbuf;
        !           440:                IOPhysicalAddress rfd_paddr;
        !           441:                IOPhysicalAddress rbd_paddr;
        !           442:        } * cache_p = (struct _cache *) KDB_buf_p;
        !           443: 
        !           444:        if ((sizeof(struct _cache) * NUM_RECEIVE_FRAMES) > ETHERMAXPACKET) {
        !           445:                IOLog("%s: no space for cache data\n", getName());
        !           446:                return false;
        !           447:        }
        !           448:        
        !           449:     /* cache allocated packet buffers */
        !           450:        for (i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           451:                cache_p[i].rbd_mbuf   = rfdList_p[i]._rbd._mbuf;
        !           452:                cache_p[i].rbd_buffer = rfdList_p[i]._rbd.buffer;
        !           453:                cache_p[i].rfd_paddr  = rfdList_p[i]._paddr;
        !           454:                cache_p[i].rbd_paddr  = rfdList_p[i]._rbd._paddr;
        !           455:        }
        !           456: 
        !           457:     /* zero out the entire structure, and re-create it */
        !           458:     bzero(rfdList_p, sizeof(rfd_t) * NUM_RECEIVE_FRAMES);
        !           459: 
        !           460:        for (i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           461:                OSSetLE16(&rfdList_p[i].command, RFD_COMMAND_SF);
        !           462:                rfdList_p[i]._paddr = cache_p[i].rfd_paddr;
        !           463:                rfdList_p[i]._rbd._paddr = cache_p[i].rbd_paddr;
        !           464:     }
        !           465: 
        !           466:        _setupRfd(rfdList_p);
        !           467: 
        !           468:     for (i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !           469:                rfdList_p[i]._rbd.buffer = cache_p[i].rbd_buffer;
        !           470:                rfdList_p[i]._rbd._mbuf  = cache_p[i].rbd_mbuf;
        !           471:        }
        !           472: 
        !           473:     headRfd = rfdList_p;
        !           474:     tailRfd = rfdList_p + NUM_RECEIVE_FRAMES - 1;
        !           475: 
        !           476:     return true;
        !           477: }
        !           478: 
        !           479: //---------------------------------------------------------------------------
        !           480: // Function: _mdiReadPHY:Register:Data
        !           481: //
        !           482: // Purpose:
        !           483: //   Read the specified MDI register and return the results.
        !           484: 
        !           485: bool
        !           486: Intel82557::_mdiReadPHY(UInt8 phyAddress, UInt8 regAddress, UInt16 * data_p)
        !           487: {
        !           488:     mdi_control_t mdi;
        !           489: 
        !           490:        mdi = CSR_FIELD(MDI_CONTROL_PHYADDR, phyAddress) |
        !           491:              CSR_FIELD(MDI_CONTROL_REGADDR, regAddress) |
        !           492:                  CSR_FIELD(MDI_CONTROL_OPCODE,  MDI_CONTROL_OP_READ);
        !           493:        
        !           494:        OSWriteLE32(&CSR_p->mdiControl, mdi);
        !           495:        IODelay(20);
        !           496:     
        !           497:        bool ready = false;
        !           498:        for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !           499:                if (OSReadLE32(&CSR_p->mdiControl) & MDI_CONTROL_READY) {
        !           500:                        ready = true;
        !           501:                        break;
        !           502:                }
        !           503:            IODelay(20);
        !           504:        }
        !           505:        if (ready == false) {
        !           506:            IOLog("%s: _mdiReadPHYRegisterSuccess timeout\n", getName());
        !           507:            return false;
        !           508:        }
        !           509: 
        !           510:        *data_p = CSR_VALUE(MDI_CONTROL_DATA, OSReadLE32(&CSR_p->mdiControl));
        !           511:     return true;
        !           512: }
        !           513: 
        !           514: //---------------------------------------------------------------------------
        !           515: // Function: _mdiWritePHY:Register:Data
        !           516: //
        !           517: // Purpose:
        !           518: //   Write the specified MDI register with the given data.
        !           519: 
        !           520: bool Intel82557::_mdiWritePHY(UInt8 phyAddress, UInt8 regAddress, UInt16 data)
        !           521: {
        !           522:     mdi_control_t mdi;
        !           523: 
        !           524:        mdi = CSR_FIELD(MDI_CONTROL_PHYADDR, phyAddress) |
        !           525:              CSR_FIELD(MDI_CONTROL_REGADDR, regAddress) |
        !           526:                  CSR_FIELD(MDI_CONTROL_OPCODE,  MDI_CONTROL_OP_WRITE) |
        !           527:                  CSR_FIELD(MDI_CONTROL_DATA,    data);
        !           528: 
        !           529:     OSWriteLE32(&CSR_p->mdiControl, mdi);
        !           530:     IODelay(20);
        !           531: 
        !           532:        bool ready = false;
        !           533:        for (int i = 0; i < SPIN_TIMEOUT; i++) {
        !           534:                if (OSReadLE32(&CSR_p->mdiControl) & MDI_CONTROL_READY) {
        !           535:                        ready = true;
        !           536:                        break;
        !           537:                }
        !           538:            IODelay(20);
        !           539:        }
        !           540:        if (ready == false) {
        !           541:            IOLog("%s: _mdiWritePHYRegisterData timeout\n", getName());
        !           542:            return false;
        !           543:        }
        !           544:     return true;
        !           545: }
        !           546: 
        !           547: //---------------------------------------------------------------------------
        !           548: // Function: nop
        !           549: //
        !           550: // Purpose:
        !           551: //   Issue a polled NOP command to the NIC.
        !           552: 
        !           553: bool Intel82557::nop()
        !           554: {
        !           555:        cbHeader_t * nop_p = &overlay_p->nop;
        !           556: 
        !           557:     bzero(nop_p, sizeof(*nop_p));
        !           558:        OSWriteLE16(&nop_p->command, CSR_FIELD(CB_CMD, CB_CMD_NOP) | CB_EL);
        !           559:        OSWriteLE32(&nop_p->link, C_NULL);
        !           560: 
        !           561:     return _polledCommand(nop_p, overlay_paddr);
        !           562: }
        !           563: 
        !           564: //---------------------------------------------------------------------------
        !           565: // Function: config
        !           566: //
        !           567: // Purpose:
        !           568: //   Issue a polled CONFIGURE command to the NIC.
        !           569: 
        !           570: bool Intel82557::config()
        !           571: {
        !           572:     UInt8 *    cb_p;    
        !           573:        cb_configure_t * cfg_p = &overlay_p->configure;
        !           574:        
        !           575:     /*
        !           576:      * Fill the configure command block
        !           577:      */
        !           578:     bzero(cfg_p, sizeof(*cfg_p));
        !           579:        
        !           580:        OSWriteLE16(&cfg_p->header.command,
        !           581:                CSR_FIELD(CB_CMD, CB_CMD_CONFIGURE) | CB_EL);
        !           582:        OSWriteLE32(&cfg_p->header.link, C_NULL);
        !           583:        
        !           584:        cb_p = cfg_p->byte;
        !           585:        cb_p[0] = CSR_FIELD(CB_CB0_BYTE_COUNT, CB_CONFIG_BYTE_COUNT);
        !           586:        
        !           587:        cb_p[1] = CSR_FIELD(CB_CB1_TX_FIFO_LIMIT, CB_CB1_TX_FIFO_0) |
        !           588:               CSR_FIELD(CB_CB1_RX_FIFO_LIMIT, CB_CB1_RX_FIFO_64);
        !           589: 
        !           590:        cb_p[3] = CB_CB3_MWI_ENABLE;    // enable PCI-MWI on 82558 devices
        !           591:        
        !           592:        cb_p[4] = 0;                                    // disable PCI transfer limits
        !           593:        cb_p[5] = 0;
        !           594:        
        !           595:        cb_p[6] = CB_CB6_NON_DIRECT_DMA | CB_CB6_STD_TCB | CB_CB6_STD_STATS;
        !           596: 
        !           597:        cb_p[7] = CSR_FIELD(CB_CB7_UNDERRUN_RETRY, CB_CB7_UNDERRUN_RETRY_1) |
        !           598:               CB_CB7_DISC_SHORT_FRAMES;
        !           599: 
        !           600:     if ((eeprom->getContents()->controllerType != I82558_CONTROLLER_TYPE) &&
        !           601:                (phyAddr != PHY_ADDRESS_I82503))
        !           602:                cb_p[8] = CB_CB8_CSMA_EN;
        !           603: 
        !           604:        cb_p[10] = CSR_FIELD(CB_CB10_PREAMBLE, CB_CB10_PREAMBLE_7_BYTES) |
        !           605:                           CB_CB10_NSAI;
        !           606: 
        !           607:        cb_p[12] = CSR_FIELD(CB_CB12_IFS, CB_CB12_IFS_96_BIT_TIMES);
        !           608: 
        !           609:        cb_p[13] = CSR_FIELD(CB_CB13_FC_TYPE_LSB, CB_CB13_FC_TYPE_LSB_DEF);
        !           610:        cb_p[14] = CSR_FIELD(CB_CB14_FC_TYPE_MSB, CB_CB14_FC_TYPE_MSB_DEF);
        !           611: 
        !           612:        cb_p[15] = ((cb_p[8] & CB_CB8_CSMA_EN) ? 0 : CB_CB15_CRS_CDT) |
        !           613:                 (promiscuousEnabled ? CB_CB15_PROMISCUOUS : 0);
        !           614:        
        !           615:        cb_p[16] = CSR_FIELD(CB_CB16_FC_DELAY_LSB, CB_CB16_FC_DELAY_LSB_DEF);
        !           616:        cb_p[17] = CSR_FIELD(CB_CB17_FC_DELAY_MSB, CB_CB17_FC_DELAY_MSB_DEF);
        !           617:        
        !           618:        cb_p[18] = CB_CB18_PADDING | CB_CB18_STRIPPING;
        !           619: 
        !           620: #if 0  // XXX - need to fix this
        !           621:     /* 
        !           622:      * Force full duplex if there is a user override, or we are using Phy 0
        !           623:      * and full duplex mode is enabled.  The FDX# pin is wired to Phy 1, 
        !           624:      * which means that the 82557 can't autodetect the setting correctly.
        !           625:      */
        !           626:     if (forceFullDuplex || (phyAddr == PHY_ADDRESS_0 && fullDuplexMode))
        !           627:                cb_p[19] = CB_CB19_FORCE_FDX;
        !           628: #endif
        !           629: 
        !           630:        cb_p[19] = CB_CB19_AUTO_FDX;
        !           631:        if (flowControl) {
        !           632:                cb_p[19] |= ( CB_CB19_TX_FC         |
        !           633:                       CB_CB19_RX_FC_RESTOP  |
        !           634:                                      CB_CB19_RX_FC_RESTART |
        !           635:                                      CB_CB19_REJECT_FC );
        !           636:        }
        !           637: 
        !           638:        cb_p[20] = CSR_FIELD(CB_CB20_FC_ADDR_LSB, CB_CB20_FC_ADDR_LSB_DEF);
        !           639: 
        !           640:        IOSync();
        !           641: 
        !           642:     return _polledCommand((cbHeader_t *) cfg_p, overlay_paddr);
        !           643: }
        !           644: 
        !           645: //---------------------------------------------------------------------------
        !           646: // Function: iaSetup
        !           647: //
        !           648: // Purpose:
        !           649: //   Issue a polled IndividualAddressSETUP command to the NIC.
        !           650: //
        !           651: bool Intel82557::iaSetup()
        !           652: {
        !           653:        cb_iasetup_t * iaSetup_p = &overlay_p->iasetup;
        !           654: 
        !           655:     /*
        !           656:      * Fill the IA-setup command block
        !           657:      */
        !           658:     bzero(iaSetup_p, sizeof(*iaSetup_p));
        !           659: 
        !           660:     OSWriteLE16(&iaSetup_p->header.command, CSR_FIELD(CB_CMD, CB_CMD_IASETUP) | 
        !           661:                                                CB_EL);
        !           662:        OSWriteLE32(&iaSetup_p->header.link, C_NULL);
        !           663:     iaSetup_p->addr = myAddress;
        !           664: 
        !           665:     return _polledCommand((cbHeader_t *) iaSetup_p, overlay_paddr);
        !           666: }
        !           667: 
        !           668: //---------------------------------------------------------------------------
        !           669: // Function: mcSetup
        !           670: //
        !           671: // Purpose:
        !           672: //   Issue a polled MultiCastSETUP command to the NIC. If 'fromData' is
        !           673: //   true, then we ignore the addrs/count arguments and instead use the
        !           674: //   multicast address list property in our interface client object.
        !           675: 
        !           676: bool Intel82557::mcSetup(enet_addr_t * addrs,
        !           677:                          UInt          count,
        !           678:                          bool          fromData = false)
        !           679: {
        !           680:        cb_mcsetup_t *      mcSetup_p;
        !           681:     bool                cmdResult;
        !           682:     IOReturn            result;
        !           683:     IOPhysicalAddress  mcSetup_paddr;
        !           684: 
        !           685:        if (fromData) {
        !           686:                // mcSetup() was not called by the setMulticastList() function.
        !           687:                // We should get the multicast list stored in the interface
        !           688:                // object's property table.
        !           689:                //
        !           690:                // mcSetup() is always executed by the default workloop thread,
        !           691:                // thus we don't have to worry about the address list being
        !           692:                // changed while we go through it.
        !           693:                //
        !           694:                addrs = 0;
        !           695:                count = 0;
        !           696:        
        !           697:                if (netif) {
        !           698:                        OSData * mcData = OSDynamicCast(OSData, 
        !           699:                              netif->getProperty(kIOMulticastAddresses));
        !           700:                        if (mcData) {
        !           701:                                addrs = (enet_addr_t *) mcData->getBytesNoCopy();
        !           702:                                count = mcData->getLength() / sizeof(enet_addr_t);
        !           703:                                assert(addrs && count);
        !           704:                        }
        !           705:                }
        !           706:        }
        !           707: 
        !           708:     mcSetup_p = (cb_mcsetup_t *) IOMallocAligned(PAGE_SIZE, PAGE_SIZE);
        !           709:     if (!mcSetup_p) {
        !           710:                IOLog("%s: mcSetup:IOMallocAligned return NULL\n", getName());
        !           711:                return false;
        !           712:     }
        !           713: 
        !           714:        reserveDebuggerLock();
        !           715: 
        !           716:        do {
        !           717:                cmdResult = false;
        !           718: 
        !           719:                OSWriteLE16(&mcSetup_p->header.status, 0);
        !           720:                OSWriteLE16(&mcSetup_p->header.command,
        !           721:                            CSR_FIELD(CB_CMD, CB_CMD_MCSETUP) | CB_EL);
        !           722:                OSWriteLE32(&mcSetup_p->header.link, C_NULL);
        !           723: 
        !           724:                /* fill in the addresses (count may be zero) */
        !           725:                for (UInt i = 0; i < count; i++)
        !           726:                        mcSetup_p->addrs[i] = addrs[i];
        !           727:        
        !           728:                /* Set the number of bytes in the MC list, if the count is zero,
        !           729:                 * it is equivalent to disabling the multicast filtering mechanism.
        !           730:                 */
        !           731:                OSWriteLE16(&mcSetup_p->count, count * sizeof(enet_addr_t));
        !           732:        
        !           733:                result = IOPhysicalFromVirtual((vm_address_t) mcSetup_p,
        !           734:                                                                           &mcSetup_paddr);
        !           735:                if (result != kIOReturnSuccess) {
        !           736:                        IOLog("%s: Invalid MC-setup command block address\n", getName());
        !           737:                        break;
        !           738:        }
        !           739: 
        !           740:                if (!_polledCommand((cbHeader_t *) mcSetup_p, mcSetup_paddr)) {
        !           741:                        IOLog("%s: MC-setup command failed 0x%x\n", getName(),
        !           742:                              OSReadLE16(&mcSetup_p->header.status));
        !           743:                        break;
        !           744:                }
        !           745: 
        !           746:                cmdResult = (OSReadLE16(&mcSetup_p->header.status) & CB_STATUS_OK) ?
        !           747:                     true : false;
        !           748:        } while (0);
        !           749:        
        !           750:        releaseDebuggerLock();
        !           751: 
        !           752:     IOFreeAligned(mcSetup_p, PAGE_SIZE);
        !           753: 
        !           754:     return cmdResult;
        !           755: }
        !           756: 
        !           757: //---------------------------------------------------------------------------
        !           758: // Function: _selfTest
        !           759: //
        !           760: // Purpose:
        !           761: //   Issue a PORT self test command to the NIC and verify the results.
        !           762: 
        !           763: bool Intel82557::_selfTest()
        !           764: {
        !           765:     port_selftest_t * test_p = (port_selftest_t *) overlay_p;
        !           766:        UInt32  results;
        !           767: 
        !           768:     OSWriteLE32(&test_p->signature, 0);
        !           769:     OSWriteLE32(&test_p->results, ~0);
        !           770:        sendPortCommand(portSelfTest_e, overlay_paddr);
        !           771:     IOSleep(20);
        !           772:     if (OSReadLE32(&test_p->signature) == 0) {
        !           773:                IOLog("%s: Self test timed out\n", getName());
        !           774:                return false;
        !           775:     }
        !           776: 
        !           777:        results = OSReadLE32(&test_p->results);
        !           778:     if (results) {             /* report errors from self test */
        !           779:        if (results & PORT_SELFTEST_ROM)
        !           780:                IOLog("%s: Self test reports invalid ROM contents\n",
        !           781:                        getName());
        !           782:        if (results & PORT_SELFTEST_REGISTER)
        !           783:                        IOLog("%s: Self test reports internal register failure\n", 
        !           784:                        getName());
        !           785:                if (results & PORT_SELFTEST_DIAGNOSE)
        !           786:                        IOLog("%s: Self test reports serial subsystem failure\n", 
        !           787:                        getName());
        !           788:                if (results & PORT_SELFTEST_GENERAL)
        !           789:                        IOLog("%s: Self test failed\n", getName());
        !           790:                        return false;
        !           791:        }
        !           792:     return true;
        !           793: }
        !           794: 
        !           795: //---------------------------------------------------------------------------
        !           796: // Function: sendPortCommand
        !           797: //
        !           798: // Purpose:
        !           799: //   Issue an 82557 PORT command.
        !           800: //
        !           801: void Intel82557::sendPortCommand(port_command_t command, UInt arg)
        !           802: {
        !           803:        OSWriteLE32(&CSR_p->port, (arg & PORT_ADDRESS_MASK) |
        !           804:                               CSR_FIELD(PORT_FUNCTION, command));
        !           805:     return;
        !           806: }
        !           807: 
        !           808: //---------------------------------------------------------------------------
        !           809: // Function: enableAdapterInterrupts, disableAdapterInterrupts
        !           810: //
        !           811: // Purpose:
        !           812: //   Turn on/off interrupts at the adapter.
        !           813: 
        !           814: void Intel82557::enableAdapterInterrupts()
        !           815: {
        !           816:        /*
        !           817:         * For 82558, mask (disable) the ER and FCP interrupts.
        !           818:         */
        !           819:        UInt8   interruptByte;
        !           820:        interruptByte = SCB_INTERRUPT_ER | SCB_INTERRUPT_FCP;
        !           821:     OSWriteLE8(&CSR_p->interrupt, interruptByte);
        !           822:        interruptEnabled = true;
        !           823:     return;
        !           824: }
        !           825: 
        !           826: void Intel82557::disableAdapterInterrupts()
        !           827: {
        !           828:        UInt8   interruptByte;
        !           829:        interruptByte = SCB_INTERRUPT_M;
        !           830:        OSWriteLE8(&CSR_p->interrupt, interruptByte);
        !           831:        interruptEnabled = false;
        !           832:     return;
        !           833: }
        !           834: 
        !           835: //---------------------------------------------------------------------------
        !           836: // Function: _logCounters
        !           837: //
        !           838: // Purpose:
        !           839: //   If Verbose is defined as yes, log extra information about errors that
        !           840: //   have occurred.
        !           841: 
        !           842: static inline void
        !           843: _logCounters(errorCounters_t * errorCounters_p)
        !           844: {
        !           845:     if (errorCounters_p->tx_good_frames)
        !           846:                IOLog("tx_good_frames %ld\n",
        !           847:                        OSReadLE32(&errorCounters_p->tx_good_frames));
        !           848:     if (errorCounters_p->tx_maxcol_errors)
        !           849:                IOLog("tx_maxcol_errors %ld\n",
        !           850:                        OSReadLE32(&errorCounters_p->tx_maxcol_errors));
        !           851:     if (errorCounters_p->tx_late_collision_errors)
        !           852:                IOLog("tx_late_collision_errors %ld\n", 
        !           853:                        OSReadLE32(&errorCounters_p->tx_late_collision_errors));
        !           854:     if (errorCounters_p->tx_underrun_errors)
        !           855:                IOLog("tx_underrun_errors %ld\n",
        !           856:                        OSReadLE32(&errorCounters_p->tx_underrun_errors));
        !           857:     if (errorCounters_p->tx_lost_carrier_sense_errors)
        !           858:                IOLog("tx_lost_carrier_sense_errors %ld\n", 
        !           859:                        OSReadLE32(&errorCounters_p->tx_lost_carrier_sense_errors));
        !           860:     if (errorCounters_p->tx_deferred)
        !           861:                IOLog("tx_deferred %ld\n", OSReadLE32(&errorCounters_p->tx_deferred));
        !           862:     if (errorCounters_p->tx_single_collisions)
        !           863:                IOLog("tx_single_collisions %ld\n", 
        !           864:                        OSReadLE32(&errorCounters_p->tx_single_collisions));
        !           865:     if (errorCounters_p->tx_multiple_collisions)
        !           866:                IOLog("tx_multiple_collisions %ld\n", 
        !           867:                        OSReadLE32(&errorCounters_p->tx_multiple_collisions));
        !           868:     if (errorCounters_p->tx_total_collisions)
        !           869:                IOLog("tx_total_collisions %ld\n", 
        !           870:                        OSReadLE32(&errorCounters_p->tx_total_collisions));
        !           871:        if (errorCounters_p->rx_good_frames)
        !           872:                IOLog("rx_good_frames %ld\n", 
        !           873:                        OSReadLE32(&errorCounters_p->rx_good_frames));
        !           874:        if (errorCounters_p->rx_crc_errors)
        !           875:                IOLog("rx_crc_errors %ld\n",
        !           876:                        OSReadLE32(&errorCounters_p->rx_crc_errors));
        !           877:        if (errorCounters_p->rx_alignment_errors)
        !           878:                IOLog("rx_alignment_errors %ld\n", 
        !           879:                        OSReadLE32(&errorCounters_p->rx_alignment_errors));
        !           880:        if (errorCounters_p->rx_resource_errors)
        !           881:                IOLog("rx_resource_errors %ld\n",
        !           882:                        OSReadLE32(&errorCounters_p->rx_resource_errors));
        !           883:        if (errorCounters_p->rx_overrun_errors)
        !           884:                IOLog("rx_overrun_errors %ld\n",
        !           885:                        OSReadLE32(&errorCounters_p->rx_overrun_errors));
        !           886:        if (errorCounters_p->rx_collision_detect_errors)
        !           887:                IOLog("rx_collision_detect_errors %ld\n", 
        !           888:                        OSReadLE32(&errorCounters_p->rx_collision_detect_errors));
        !           889:        if (errorCounters_p->rx_short_frame_errors)
        !           890:                IOLog("rx_short_frame_errors %ld\n", 
        !           891:                        OSReadLE32(&errorCounters_p->rx_short_frame_errors));
        !           892:     return;
        !           893: }
        !           894: 
        !           895: //---------------------------------------------------------------------------
        !           896: // Function: _dumpStatistics
        !           897: //
        !           898: // Purpose:
        !           899: //   _dumpStatistics issues a new statistics dump command.  Every few seconds,
        !           900: //   _updateStatistics is called from timeoutOccurred to check for updated
        !           901: //   statistics.  If complete, update our counters, and issue a new dump
        !           902: //   command.
        !           903: 
        !           904: bool Intel82557::_dumpStatistics()
        !           905: {
        !           906:        reserveDebuggerLock();
        !           907: 
        !           908:     if (!_waitSCBCommandClear(CSR_p)) {
        !           909:                IOLog("%s: _dumpStatistics: _waitSCBCommandClear failed\n", getName());
        !           910:                return false;
        !           911:     }
        !           912: 
        !           913:        OSWriteLE8(&CSR_p->command,
        !           914:                   CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_DUMP_RESET_STAT));
        !           915: 
        !           916:        prevCUCommand = SCB_CUC_DUMP_RESET_STAT;
        !           917: 
        !           918:        releaseDebuggerLock();
        !           919: 
        !           920:     return true;
        !           921: }
        !           922: 
        !           923: //---------------------------------------------------------------------------
        !           924: // Function: _updateStatistics
        !           925: //
        !           926: // Purpose:
        !           927: //   Gather statistics information from the adapter at regular intervals.
        !           928: 
        !           929: void Intel82557::_updateStatistics()
        !           930: {
        !           931:     if (OSReadLE32(&errorCounters_p->_status) != DUMP_STATUS) {
        !           932:                if (verbose)
        !           933:                        _logCounters(errorCounters_p);
        !           934: 
        !           935:                // Ethernet transmitter stats.
        !           936:                //
        !           937:                etherStats->dot3StatsEntry.singleCollisionFrames += 
        !           938:                        OSReadLE32(&errorCounters_p->tx_single_collisions);
        !           939:                
        !           940:                etherStats->dot3StatsEntry.multipleCollisionFrames += 
        !           941:                        OSReadLE32(&errorCounters_p->tx_multiple_collisions);
        !           942:                
        !           943:                etherStats->dot3StatsEntry.lateCollisions += 
        !           944:                        OSReadLE32(&errorCounters_p->tx_late_collision_errors);
        !           945:                
        !           946:                etherStats->dot3StatsEntry.excessiveCollisions += 
        !           947:                        OSReadLE32(&errorCounters_p->tx_maxcol_errors);
        !           948: 
        !           949:                etherStats->dot3StatsEntry.deferredTransmissions += 
        !           950:                        OSReadLE32(&errorCounters_p->tx_deferred);
        !           951: 
        !           952:                etherStats->dot3StatsEntry.carrierSenseErrors += 
        !           953:                        OSReadLE32(&errorCounters_p->tx_lost_carrier_sense_errors);
        !           954: 
        !           955:                etherStats->dot3TxExtraEntry.underruns += 
        !           956:                        OSReadLE32(&errorCounters_p->tx_underrun_errors);
        !           957: 
        !           958:                // Ethernet receiver stats.
        !           959:                //
        !           960:                etherStats->dot3StatsEntry.alignmentErrors += 
        !           961:                        OSReadLE32(&errorCounters_p->rx_alignment_errors);
        !           962: 
        !           963:                etherStats->dot3StatsEntry.fcsErrors += 
        !           964:                        OSReadLE32(&errorCounters_p->rx_crc_errors);
        !           965: 
        !           966:                etherStats->dot3RxExtraEntry.resourceErrors += 
        !           967:                        OSReadLE32(&errorCounters_p->rx_resource_errors);
        !           968: 
        !           969:                etherStats->dot3RxExtraEntry.overruns += 
        !           970:                        OSReadLE32(&errorCounters_p->rx_overrun_errors);
        !           971: 
        !           972:                etherStats->dot3RxExtraEntry.collisionErrors += 
        !           973:                        OSReadLE32(&errorCounters_p->rx_collision_detect_errors);                       
        !           974: 
        !           975:                etherStats->dot3RxExtraEntry.frameTooShorts += 
        !           976:                        OSReadLE32(&errorCounters_p->rx_short_frame_errors);                    
        !           977:                
        !           978:                // Generic network stats. For the error counters, we assume
        !           979:                // the Ethernet stats will never be cleared. Thus we derive the
        !           980:                // error counters by summing the appropriate Ethernet error fields.
        !           981:                //
        !           982:                netStats->outputErrors =
        !           983:                        ( etherStats->dot3StatsEntry.lateCollisions
        !           984:                        + etherStats->dot3StatsEntry.excessiveCollisions
        !           985:                        + etherStats->dot3StatsEntry.carrierSenseErrors
        !           986:                        + etherStats->dot3TxExtraEntry.underruns
        !           987:                        + etherStats->dot3TxExtraEntry.resourceErrors);
        !           988: 
        !           989:                netStats->inputErrors =
        !           990:                        ( etherStats->dot3StatsEntry.fcsErrors
        !           991:                        + etherStats->dot3StatsEntry.alignmentErrors
        !           992:                        + etherStats->dot3RxExtraEntry.resourceErrors
        !           993:                        + etherStats->dot3RxExtraEntry.overruns
        !           994:                        + etherStats->dot3RxExtraEntry.collisionErrors
        !           995:                        + etherStats->dot3RxExtraEntry.frameTooShorts);
        !           996: 
        !           997:                netStats->collisions += 
        !           998:                        OSReadLE32(&errorCounters_p->tx_total_collisions);
        !           999: 
        !          1000:                OSWriteLE32(&errorCounters_p->_status, DUMP_STATUS);
        !          1001:                _dumpStatistics();
        !          1002:     }
        !          1003: }
        !          1004: 
        !          1005: //---------------------------------------------------------------------------
        !          1006: // Function: _allocateMemPage
        !          1007: //
        !          1008: // Purpose:
        !          1009: //   Allocate a page of memory.
        !          1010: 
        !          1011: bool Intel82557::_allocateMemPage(pageBlock_t * p)
        !          1012: {
        !          1013:     p->memSize = PAGE_SIZE;
        !          1014:     p->memPtr  = IOMallocAligned(p->memSize, PAGE_SIZE);
        !          1015: 
        !          1016:     if (!p->memPtr)
        !          1017:                return false;
        !          1018: 
        !          1019:        bzero(p->memPtr, p->memSize);
        !          1020:        p->memAllocPtr = p->memPtr;             /* initialize for allocation routine */
        !          1021:        p->memAvail    = p->memSize;
        !          1022: 
        !          1023:        return true;
        !          1024: }
        !          1025: 
        !          1026: //---------------------------------------------------------------------------
        !          1027: // Function: _freeMemPage
        !          1028: //
        !          1029: // Purpose:
        !          1030: //   Deallocate a page of memory.
        !          1031: //
        !          1032: void Intel82557::_freeMemPage(pageBlock_t * p)
        !          1033: {
        !          1034:        IOFreeAligned(p->memPtr, p->memSize);
        !          1035: }
        !          1036: 
        !          1037: //---------------------------------------------------------------------------
        !          1038: // Function: hwInit
        !          1039: //
        !          1040: // Purpose:
        !          1041: //   Reset/configure the chip, detect the PHY.
        !          1042: 
        !          1043: bool Intel82557::hwInit()
        !          1044: {
        !          1045:        disableAdapterInterrupts();
        !          1046:        _resetChip();
        !          1047:        disableAdapterInterrupts();
        !          1048: 
        !          1049:        /* disable early RX interrupt */
        !          1050:        OSWriteLE8(&CSR_p->earlyRxInterrupt, 0);
        !          1051: 
        !          1052:     /* load command unit base address */
        !          1053:     if (!_waitSCBCommandClear(CSR_p)) {
        !          1054:                IOLog("%s: hwInit: CU _waitSCBCommandClear failed\n", getName());
        !          1055:                return false;
        !          1056:     }
        !          1057:     OSWriteLE32(&CSR_p->pointer, 0);   
        !          1058:        OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_LOAD_BASE));
        !          1059:        prevCUCommand = SCB_CUC_LOAD_BASE;
        !          1060: 
        !          1061:     /* load receive unit base address */
        !          1062:     if (!_waitSCBCommandClear(CSR_p)) {
        !          1063:                IOLog("%s: hwInit: RU _waitSCBCommandClear failed\n", getName());
        !          1064:                return false;
        !          1065:     }
        !          1066:     OSWriteLE32(&CSR_p->pointer, 0);   
        !          1067:        OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_RUC, SCB_RUC_LOAD_BASE));
        !          1068: 
        !          1069:     if (!_waitSCBCommandClear(CSR_p)) {
        !          1070:                IOLog("%s: hwInit: before LOAD_DUMP_COUNTERS_ADDRESS:"
        !          1071:                        " _waitSCBCommandClear failed\n", getName());
        !          1072:                return false;
        !          1073:     }
        !          1074:     OSWriteLE32(&errorCounters_p->_status, DUMP_STATUS);
        !          1075:        OSWriteLE32(&CSR_p->pointer, errorCounters_paddr);      
        !          1076:        OSWriteLE8(&CSR_p->command,
        !          1077:                CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_LOAD_DUMP_ADDR));
        !          1078:        prevCUCommand = SCB_CUC_LOAD_DUMP_ADDR;
        !          1079: 
        !          1080:     if (!_waitSCBCommandClear(CSR_p)) {
        !          1081:                IOLog("%s: hwInit: before intrACK _waitSCBCommandClear failed\n",
        !          1082:                        getName());
        !          1083:                return false;
        !          1084:     }
        !          1085: 
        !          1086:        /* Setup flow-control threshold */
        !          1087:        OSWriteLE8(&CSR_p->flowControlThreshold,
        !          1088:                   CSR_FIELD(FC_THRESHOLD, FC_THRESHOLD_512));
        !          1089: 
        !          1090:        _intrACK(CSR_p); /* ack any pending interrupts */
        !          1091: 
        !          1092:        _phyProbe();
        !          1093: 
        !          1094:        phyID = _phyGetID();
        !          1095:     VPRINT("%s: PHY model id is 0x%08lx\n", getName(), phyID);
        !          1096:     phyID &= PHY_MODEL_MASK;
        !          1097: 
        !          1098:     if (!config())
        !          1099:                return false;
        !          1100:     IOSleep(500);
        !          1101: 
        !          1102:     if (!iaSetup())
        !          1103:                return false;
        !          1104: 
        !          1105:        _intrACK(CSR_p); /* ack any pending interrupts */
        !          1106: 
        !          1107:     return true;
        !          1108: }
        !          1109: 
        !          1110: //---------------------------------------------------------------------------
        !          1111: // Function: _memAlloc
        !          1112: //
        !          1113: // Purpose:
        !          1114: //   Return the next aligned chunk of memory in our shared memory page.
        !          1115: 
        !          1116: void * Intel82557::_memAllocFrom(pageBlock_t * p, UInt allocSize, UInt align)
        !          1117: {
        !          1118:     void *     allocPtr;
        !          1119:        UInt    sizeReal;
        !          1120: 
        !          1121:        if (align == 0)
        !          1122:                return 0;
        !          1123:        
        !          1124:        // Advance allocPtr to next aligned boundary.
        !          1125:        allocPtr =
        !          1126:        (void *)((UInt)((UInt) p->memAllocPtr + (align - 1)) & (~(align - 1)));
        !          1127:        
        !          1128:        // Actual size of required storage. We need to take the alignment padding
        !          1129:        // into account.
        !          1130:        sizeReal = allocSize + ((UInt) allocPtr - (UInt) p->memAllocPtr);
        !          1131: 
        !          1132:     if (sizeReal > p->memAvail)
        !          1133:                return 0;
        !          1134:        
        !          1135:     p->memAllocPtr = (void *)((UInt) p->memAllocPtr + sizeReal);
        !          1136:     p->memAvail = p->memSize - ((UInt) p->memAllocPtr - (UInt) p->memPtr);
        !          1137:     return allocPtr;
        !          1138: }
        !          1139: 
        !          1140: //---------------------------------------------------------------------------
        !          1141: // Function: coldInit
        !          1142: //
        !          1143: // Purpose:
        !          1144: //   One-time initialization code. This is called by start(), before we
        !          1145: //   attach any client objects.
        !          1146: 
        !          1147: bool Intel82557::coldInit()
        !          1148: {
        !          1149:     IOReturn                   result;
        !          1150:        IOPhysicalAddress       paddr;
        !          1151: 
        !          1152:        disableAdapterInterrupts();
        !          1153: 
        !          1154:     /* allocate and initialize shared memory pointers */
        !          1155:        if (!_allocateMemPage(&shared)) {
        !          1156:                IOLog("%s: Can't allocate shared memory page\n", getName());
        !          1157:                return false;
        !          1158:     }
        !          1159:        if (!_allocateMemPage(&txRing)) {
        !          1160:                IOLog("%s: Can't allocate memory page for TX ring\n", getName());
        !          1161:                return false;
        !          1162:     }
        !          1163:        if (!_allocateMemPage(&rxRing)) {
        !          1164:                IOLog("%s: Can't allocate memory page for RX ring\n", getName());
        !          1165:                return false;
        !          1166:     }
        !          1167: 
        !          1168:     /* allocate memory for shared data structures
        !          1169:         * self test needs to be
        !          1170:         * 16 byte aligned
        !          1171:         */      
        !          1172:     overlay_p = (overlay_t *) _memAllocFrom(&shared, sizeof(overlay_t), 
        !          1173:                                             PARAGRAPH_ALIGNMENT);
        !          1174:        if (!overlay_p)
        !          1175:                return false;
        !          1176:     result = IOPhysicalFromVirtual((vm_address_t) overlay_p, &overlay_paddr);
        !          1177:     if (result != kIOReturnSuccess) {
        !          1178:        IOLog("%s: Invalid command block address\n", getName());
        !          1179:                return false;
        !          1180:     }
        !          1181: 
        !          1182:     tcbList_p = (tcb_t *) _memAllocFrom(&txRing,
        !          1183:                                         sizeof(tcb_t) * NUM_TRANSMIT_FRAMES,
        !          1184:                                         CACHE_ALIGNMENT);
        !          1185:        if (!tcbList_p)
        !          1186:                return false;
        !          1187: 
        !          1188:        KDB_tcb_p = (tcb_t *) _memAllocFrom(&shared,
        !          1189:                                         sizeof(tcb_t),
        !          1190:                                         CACHE_ALIGNMENT);
        !          1191:        if (!KDB_tcb_p)
        !          1192:                return false;
        !          1193:     result = IOPhysicalFromVirtual((vm_address_t) KDB_tcb_p,
        !          1194:                                                   &KDB_tcb_p->_paddr);
        !          1195:     if (result != kIOReturnSuccess) {
        !          1196:                IOLog("%s: Invalid TCB address\n", getName());
        !          1197:                return false;
        !          1198:     }
        !          1199:     
        !          1200:        result = IOPhysicalFromVirtual((vm_address_t) &KDB_tcb_p->_tbds, &paddr);
        !          1201:     if (result != kIOReturnSuccess) {
        !          1202:                IOLog("%s: Invalid TCB->_TBD address\n", getName());
        !          1203:                return false;
        !          1204:     }
        !          1205:        OSWriteLE32(&KDB_tcb_p->tbdAddr, paddr);
        !          1206:        
        !          1207:     KDB_buf_p = _memAllocFrom(&shared, ETHERMAXPACKET, DWORD_ALIGNMENT);
        !          1208:        if (!KDB_buf_p)
        !          1209:                return false;
        !          1210:     result = IOPhysicalFromVirtual((vm_address_t) KDB_buf_p,  &KDB_buf_paddr);
        !          1211:     if (result != kIOReturnSuccess) {
        !          1212:                IOLog("%s: Invalid address\n", getName());
        !          1213:                return false;
        !          1214:     }
        !          1215: 
        !          1216:     errorCounters_p = (errorCounters_t *) _memAllocFrom(&shared, 
        !          1217:                                              sizeof(errorCounters_t),
        !          1218:                                              DWORD_ALIGNMENT);
        !          1219:        if (!errorCounters_p)
        !          1220:                return false;
        !          1221:     result = IOPhysicalFromVirtual((vm_address_t) errorCounters_p,
        !          1222:                                    &errorCounters_paddr);
        !          1223:     if (result != kIOReturnSuccess) {
        !          1224:        IOLog("%s: Invalid errorCounters address\n", getName());
        !          1225:                return false;
        !          1226:     }
        !          1227: 
        !          1228:     rfdList_p = (rfd_t *) _memAllocFrom(&rxRing,
        !          1229:                                         sizeof(rfd_t) * NUM_RECEIVE_FRAMES,
        !          1230:                                         CACHE_ALIGNMENT);
        !          1231:        if (!rfdList_p)
        !          1232:                return false;
        !          1233: 
        !          1234:     if (!_selfTest())
        !          1235:                return false;
        !          1236: 
        !          1237:     myAddress = eeprom->getContents()->addr;
        !          1238: 
        !          1239:     return true;
        !          1240: }
        !          1241: 
        !          1242: //---------------------------------------------------------------------------
        !          1243: // Function: receiveInterruptOccurred
        !          1244: //
        !          1245: // Purpose:
        !          1246: //   Hand up rceived frames.
        !          1247: 
        !          1248: bool Intel82557::receiveInterruptOccurred()
        !          1249: {
        !          1250:        bool packetsQueued = false;
        !          1251: 
        !          1252:     while (OSReadLE16(&headRfd->status) & RFD_STATUS_C) {
        !          1253:                rbd_count_t rbd_count = OSReadLE32(&headRfd->_rbd.count);
        !          1254: 
        !          1255:                // rxCount does NOT include the Ethernet CRC (FCS).
        !          1256:                //
        !          1257:                UInt rxCount = CSR_VALUE(RBD_COUNT, rbd_count);
        !          1258: 
        !          1259: #if 0
        !          1260:                // When the receive unit runs out of resources, it will
        !          1261:                // skip over RFD/RBD, making them as complete, but the RBD will
        !          1262:                // have zero bytes and the EOF bit will not be set.
        !          1263:                // We just skip over those and allow them to be recycled.
        !          1264:                //
        !          1265:                // In those cases, the RFD->status word will be 0x8220.
        !          1266: 
        !          1267:                /* should have exactly 1 rbd per rfd */
        !          1268:                if (!(rbd_count & RBD_COUNT_EOF)) {
        !          1269:                IOLog("%s: more than 1 rbd, frame size %d\n", getName(), rxCount);
        !          1270:                        
        !          1271:                        IOLog("%s: RFD status: %04x\n", getName(), 
        !          1272:                                OSReadLE16(&headRfd->status));
        !          1273:                        
        !          1274:                        issueReset();
        !          1275:                        return;
        !          1276:                }
        !          1277: #endif
        !          1278: 
        !          1279:                if ((!(OSReadLE16(&headRfd->status) & RFD_STATUS_OK)) ||
        !          1280:                        (rxCount < (ETHERMINPACKET - ETHERCRC)) ||
        !          1281:                        !enabledForNetif) {
        !          1282:                        ; /* bad or unwanted packet */
        !          1283:                }
        !          1284:                else {
        !          1285:                struct mbuf * m = headRfd->_rbd._mbuf;
        !          1286:                        struct mbuf * m_in = 0; // packet to pass up to inputPacket()
        !          1287:                        bool replaced;
        !          1288: 
        !          1289:                        packetsReceived = true;
        !          1290: 
        !          1291:                        m_in = replaceOrCopyPacket(&m, rxCount, &replaced);
        !          1292:                        if (!m_in) {
        !          1293:                                etherStats->dot3RxExtraEntry.resourceErrors++;
        !          1294:                                goto RX_INTR_ABORT;
        !          1295:                        }
        !          1296: 
        !          1297:                        if (replaced && (updateRFDFromMbuf(headRfd, m) == false)) {
        !          1298:                                freePacket(m);  // free the new replacement mbuf.
        !          1299:                                m_in = 0;               // pass up nothing.
        !          1300:                                etherStats->dot3RxExtraEntry.resourceErrors++;
        !          1301:                                IOLog("%s: updateRFDFromMbuf() error\n", getName());
        !          1302:                                goto RX_INTR_ABORT;
        !          1303:                        }
        !          1304: 
        !          1305:                        netif->inputPacket(m_in, rxCount, true);
        !          1306:                        packetsQueued = true;
        !          1307:                        netStats->inputPackets++;
        !          1308:            }
        !          1309: 
        !          1310: RX_INTR_ABORT:
        !          1311:                /* clear fields in rfd */
        !          1312:                OSWriteLE16(&headRfd->status, 0);
        !          1313:                OSWriteLE16(&headRfd->command, (RFD_COMMAND_SF | RFD_COMMAND_EL));
        !          1314:                OSWriteLE32(&headRfd->rbdAddr, C_NULL);
        !          1315:                OSWriteLE32(&headRfd->misc, 0);
        !          1316: 
        !          1317:                /* clear fields in rbd */
        !          1318:                OSWriteLE32(&headRfd->_rbd.count, 0);
        !          1319:                OSWriteLE32(&headRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE) | 
        !          1320:                                                 RBD_SIZE_EL);
        !          1321: 
        !          1322:                /* adjust tail markers */
        !          1323:                OSWriteLE32(&tailRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE));
        !          1324:                OSWriteLE16(&tailRfd->command, RFD_COMMAND_SF);
        !          1325: 
        !          1326:                tailRfd = headRfd;                      // new tail
        !          1327:                headRfd = headRfd->_next;       // new head
        !          1328:     } /* while */
        !          1329: 
        !          1330:     return packetsQueued;
        !          1331: }
        !          1332: 
        !          1333: //---------------------------------------------------------------------------
        !          1334: // Function: transmitInterruptOccurred
        !          1335: //
        !          1336: // Purpose:
        !          1337: //   Free up packets associated with any completed TCB's.
        !          1338: 
        !          1339: void Intel82557::transmitInterruptOccurred()
        !          1340: {
        !          1341:        tcbQ_t * tcbQ_p = &tcbQ;
        !          1342:        tcb_t *  head;
        !          1343: 
        !          1344:        head = tcbQ_p->activeHead_p;
        !          1345:     while (tcbQ_p->numFree < tcbQ_p->numTcbs &&
        !          1346:           (OSReadLE16(&head->status) & TCB_STATUS_C))
        !          1347:        {
        !          1348:                OSWriteLE16(&head->status, 0);
        !          1349:                if (head->_mbuf) {
        !          1350:                freePacket(head->_mbuf);
        !          1351:                head->_mbuf = 0;
        !          1352:                }
        !          1353:                head = tcbQ_p->activeHead_p = head->_next;
        !          1354:                tcbQ_p->numFree++;
        !          1355:     }
        !          1356: 
        !          1357:     return;
        !          1358: }
        !          1359: 
        !          1360: //---------------------------------------------------------------------------
        !          1361: // Function: checkForInterrupt
        !          1362: //
        !          1363: // Purpose:
        !          1364: //   A filtering function for the IOFilterInterruptEventSource. We use
        !          1365: //   this because otherwise interrupts will cause a hard hang on i386.
        !          1366: 
        !          1367: #ifdef USE_FILTER_INTERRUPT_EVENT_SRC
        !          1368: bool
        !          1369: Intel82557::checkForInterrupt(IOFilterInterruptEventSource * src)
        !          1370: {
        !          1371:        UInt8   interruptByte;
        !          1372: 
        !          1373:        // I386 hack! Turn off all hardware interrupt sources.
        !          1374:        //
        !          1375:        interruptByte = SCB_INTERRUPT_M;
        !          1376:        OSWriteLE8(&CSR_p->interrupt, interruptByte);
        !          1377:        
        !          1378:        return true;    // go ahead and call interruptOccurred()
        !          1379: }
        !          1380: #endif
        !          1381: 
        !          1382: //---------------------------------------------------------------------------
        !          1383: // Function: interruptOccurred
        !          1384: //
        !          1385: // Purpose:
        !          1386: //   Field an interrupt.
        !          1387: 
        !          1388: void Intel82557::interruptOccurred(IOInterruptEventSource * src, int /*count*/)
        !          1389: {
        !          1390:        scb_status_t  status;
        !          1391:        bool          flushInputQ = false;
        !          1392:        bool          doService   = false;
        !          1393: 
        !          1394:        reserveDebuggerLock();
        !          1395: 
        !          1396:        if (interruptEnabled == false) {
        !          1397:                _intrACK(CSR_p);
        !          1398:                releaseDebuggerLock();
        !          1399:                IOLog("%s: unexpected interrupt\n", getName());
        !          1400:                return;
        !          1401:        }
        !          1402: 
        !          1403:        /*
        !          1404:         * Loop until the interrupt line becomes deasserted.
        !          1405:         */
        !          1406:        while (1) {
        !          1407:                if ((status = _intrACK(CSR_p)) == 0)
        !          1408:                        break;
        !          1409: 
        !          1410:                /*
        !          1411:                 * RX interrupt.
        !          1412:                 */
        !          1413:                if (status & (SCB_STATUS_FR | SCB_STATUS_RNR)) {
        !          1414:                
        !          1415:                        flushInputQ = receiveInterruptOccurred() || flushInputQ;
        !          1416: 
        !          1417:                        etherStats->dot3RxExtraEntry.interrupts++;
        !          1418: 
        !          1419:                        if (status & SCB_STATUS_RNR) {
        !          1420:                                etherStats->dot3RxExtraEntry.resets++;
        !          1421: 
        !          1422:                                _abortReceive();
        !          1423:                                _resetRfdList();
        !          1424: 
        !          1425:                                if (!_startReceive()) {
        !          1426:                                        IOLog("%s: Unable to restart receiver\n", getName());
        !          1427:                                        // issueReset();        /* shouldn't need to do this. */
        !          1428:                                }
        !          1429:                        }
        !          1430:                }
        !          1431: 
        !          1432:                /*
        !          1433:                 * TX interrupt.
        !          1434:                 */
        !          1435:                if (status & (SCB_STATUS_CX | SCB_STATUS_CNA)) {
        !          1436:                        transmitInterruptOccurred();
        !          1437:                        etherStats->dot3TxExtraEntry.interrupts++;
        !          1438:                        doService = true;
        !          1439:                }
        !          1440:        }
        !          1441: 
        !          1442: #ifdef USE_FILTER_INTERRUPT_EVENT_SRC
        !          1443:        enableAdapterInterrupts();      // I386 hack! - turn interrupts back on
        !          1444: #endif
        !          1445: 
        !          1446:        releaseDebuggerLock();
        !          1447: 
        !          1448:        if (enabledForNetif) {
        !          1449:                // Flush all packets received and pass them to the network stack.
        !          1450:                //
        !          1451:                if (flushInputQ)
        !          1452:                        netif->flushInputQueue();
        !          1453: 
        !          1454:                // Call service() without holding the debugger lock to prevent a
        !          1455:                // deadlock when service() calls our outputPacket() function.
        !          1456:                //
        !          1457:                if (doService)
        !          1458:                        transmitQueue->service();
        !          1459:        }
        !          1460: }
        !          1461: 
        !          1462: //---------------------------------------------------------------------------
        !          1463: // Function: updateTCBForMbuf
        !          1464: //
        !          1465: // Update the TxCB pointed by tcb_p to point to the mbuf chain 'm'.
        !          1466: // Returns the mbuf encoded onto the TxCB.
        !          1467: 
        !          1468: struct mbuf *
        !          1469: Intel82557::updateTCBForMbuf(tcb_t * tcb_p, struct mbuf * m)
        !          1470: {
        !          1471:        // Set the invariant TCB fields.
        !          1472:        //
        !          1473:        OSWriteLE16(&tcb_p->status, 0);
        !          1474: 
        !          1475:     if (++txCount == TRANSMIT_INT_DELAY) {
        !          1476:                OSWriteLE16(&tcb_p->command, CSR_FIELD(TCB_COMMAND, CB_CMD_TRANSMIT) |
        !          1477:                      TCB_COMMAND_S  |
        !          1478:                      TCB_COMMAND_SF |
        !          1479:                                         TCB_COMMAND_I);
        !          1480:                txCount = 0;
        !          1481:     }
        !          1482:        else
        !          1483:                OSWriteLE16(&tcb_p->command, CSR_FIELD(TCB_COMMAND, CB_CMD_TRANSMIT) |
        !          1484:                      TCB_COMMAND_S  |
        !          1485:                      TCB_COMMAND_SF);
        !          1486: 
        !          1487:        OSWriteLE8(&tcb_p->threshold, TCB_TX_THRESHOLD);
        !          1488:        OSWriteLE16(&tcb_p->count, 0);  // all data are in the TBD's, none in TxCB
        !          1489: 
        !          1490:        // Since the format of a TBD closely matches the structure of an
        !          1491:        // 'struct IOPhysicalSegment', we shall have the cursor update the TBD list
        !          1492:        // directly.
        !          1493:        //
        !          1494:        UInt segments = txMbufCursor->getPhysicalSegmentsWithCoalesce(m,
        !          1495:                     (struct IOPhysicalSegment *) &tcb_p->_tbds[0],
        !          1496:                     TBDS_PER_TCB);
        !          1497: 
        !          1498:        if (!segments) {
        !          1499:                IOLog("%s: getPhysicalSegments error, pkt len = %d\n",
        !          1500:                        getName(), m->m_pkthdr.len);
        !          1501:                return 0;
        !          1502:        }
        !          1503: 
        !          1504:        // Update the TBD array size count.
        !          1505:        //
        !          1506:        OSWriteLE8(&tcb_p->number, segments);
        !          1507: 
        !          1508:        return m;
        !          1509: }
        !          1510: 
        !          1511: //---------------------------------------------------------------------------
        !          1512: // Function: outputPacket <IONetworkController>
        !          1513: //
        !          1514: // Purpose:
        !          1515: //   Transmit the packet handed by our IOOutputQueue.
        !          1516: //   TCBs have the suspend bit set, so that the CU goes into the suspend
        !          1517: //   state when done.  We use the CU_RESUME optimization that allows us to
        !          1518: //   issue CU_RESUMES without waiting for SCB command to clear.
        !          1519: //
        !          1520: UInt32 Intel82557::outputPacket(struct mbuf * m)
        !          1521: {
        !          1522:        tcb_t * tcb_p;
        !          1523:        
        !          1524:     if (!enabledForNetif) {            // drop the packet.
        !          1525:                freePacket(m);
        !          1526:                return kIOOQReturnDropped;
        !          1527:        }
        !          1528: 
        !          1529:        reserveDebuggerLock();
        !          1530: 
        !          1531:        if (tcbQ.numFree == 0) {        // retry when more space is available.
        !          1532:                releaseDebuggerLock();
        !          1533:                return kIOOQReturnStall;
        !          1534:        }
        !          1535: 
        !          1536:     packetsTransmitted = true; 
        !          1537:        netStats->outputPackets++;
        !          1538: 
        !          1539:     tcb_p = tcbQ.freeHead_p;
        !          1540: 
        !          1541:        tcb_p->_mbuf = updateTCBForMbuf(tcb_p, m);
        !          1542:        if (tcb_p->_mbuf == 0) {
        !          1543:                etherStats->dot3TxExtraEntry.resourceErrors++;
        !          1544:                goto fail;
        !          1545:        }
        !          1546:        
        !          1547:     /* update the queue */
        !          1548:     tcbQ.numFree--;
        !          1549:     tcbQ.freeHead_p = tcbQ.freeHead_p->_next;
        !          1550: 
        !          1551:        /* The TCB is already setup and the suspend bit set. Now clear the
        !          1552:         * suspend bit of the previous TCB.
        !          1553:         */
        !          1554:     if (tcbQ.activeTail_p != tcb_p)
        !          1555:                OSClearLE16(&tcbQ.activeTail_p->command, TCB_COMMAND_S);
        !          1556:     tcbQ.activeTail_p = tcb_p;
        !          1557: 
        !          1558:     /*
        !          1559:      * CUC_RESUME is optimized such that it is unnecessary to wait
        !          1560:      * for the CU to clear the SCB command word if the previous command
        !          1561:      * was a resume and the CU state is not idle.
        !          1562:      */
        !          1563:        if (CSR_VALUE(SCB_STATUS_CUS, OSReadLE16(&CSR_p->status)) == SCB_CUS_IDLE) 
        !          1564:        {
        !          1565:                if (!_waitSCBCommandClear(CSR_p)) {
        !          1566:                IOLog("%s: outputPacket: _waitSCBCommandClear error\n", getName());
        !          1567:                        etherStats->dot3TxExtraEntry.timeouts++;
        !          1568:                goto fail;
        !          1569:                }
        !          1570:                OSWriteLE32(&CSR_p->pointer, tcb_p->_paddr);
        !          1571:                OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_START));
        !          1572:                prevCUCommand = SCB_CUC_START;
        !          1573:     }
        !          1574:     else {
        !          1575:                if (prevCUCommand != SCB_CUC_RESUME) {
        !          1576:                if (!_waitSCBCommandClear(CSR_p)) {
        !          1577:                                IOLog("%s: outputPacket: _waitSCBCommandClear error\n",
        !          1578:                                        getName());
        !          1579:                                etherStats->dot3TxExtraEntry.timeouts++;
        !          1580:                                goto fail;
        !          1581:                }
        !          1582:                }
        !          1583:                OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC,SCB_CUC_RESUME));
        !          1584:                prevCUCommand = SCB_CUC_RESUME;
        !          1585:     }
        !          1586:        releaseDebuggerLock();
        !          1587:     return kIOOQReturnSuccess;
        !          1588: 
        !          1589: fail:
        !          1590:     freePacket(m);
        !          1591:     tcb_p->_mbuf = 0;
        !          1592:        releaseDebuggerLock();
        !          1593:     return kIOOQReturnDropped;
        !          1594: }
        !          1595: 
        !          1596: //---------------------------------------------------------------------------
        !          1597: // Function: _receivePacket
        !          1598: //
        !          1599: // Purpose:
        !          1600: //   Part of kerneldebugger protocol.
        !          1601: //   Returns true if a packet was received successfully.
        !          1602: //
        !          1603: bool Intel82557::_receivePacket(void * pkt, UInt * len, UInt timeout)
        !          1604: {
        !          1605:        bool          processPacket = true;
        !          1606:        bool          ret           = false;
        !          1607:        scb_status_t  status;
        !          1608: 
        !          1609:     timeout *= 1000;
        !          1610: 
        !          1611:     while ((OSReadLE16(&headRfd->status) & RFD_STATUS_C) == 0) {
        !          1612:                if ((int) timeout <= 0) {
        !          1613:                        processPacket = false;
        !          1614:                        break;
        !          1615:                }
        !          1616:                IODelay(50);
        !          1617:                timeout -= 50;
        !          1618:     }
        !          1619: 
        !          1620:        if (processPacket) {
        !          1621:                if ((OSReadLE16(&headRfd->status) & RFD_STATUS_OK) &&
        !          1622:                    (OSReadLE32(&headRfd->_rbd.count) & RBD_COUNT_EOF))
        !          1623:            {
        !          1624:                        // Pass up good frames.
        !          1625:                        //
        !          1626:                        *len = CSR_VALUE(RBD_COUNT, OSReadLE32(&headRfd->_rbd.count));
        !          1627:                        *len = MIN(*len, ETHERMAXPACKET);
        !          1628:                        bcopy(mtod(headRfd->_rbd._mbuf, void *), pkt, *len);
        !          1629:                        ret = true;
        !          1630:                }
        !          1631: 
        !          1632:                /* the head becomes the new tail */
        !          1633:                /* clear fields in rfd */
        !          1634:                OSWriteLE16(&headRfd->status, 0);
        !          1635:                OSWriteLE16(&headRfd->command, (RFD_COMMAND_SF | RFD_COMMAND_EL));
        !          1636:                OSWriteLE32(&headRfd->rbdAddr, C_NULL);
        !          1637:                OSWriteLE32(&headRfd->misc, 0);
        !          1638:        
        !          1639:                /* clear fields in rbd */
        !          1640:                OSWriteLE32(&headRfd->_rbd.count, 0);
        !          1641:                OSWriteLE32(&headRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE) | 
        !          1642:                                                 RBD_SIZE_EL);
        !          1643: 
        !          1644:                /* adjust tail markers */
        !          1645:                OSWriteLE32(&tailRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE));
        !          1646:                OSWriteLE16(&tailRfd->command, RFD_COMMAND_SF);
        !          1647: 
        !          1648:                tailRfd = headRfd;                      // new tail
        !          1649:                headRfd = headRfd->_next;       // new head
        !          1650:        }
        !          1651: 
        !          1652:        status = OSReadLE16(&CSR_p->status) & SCB_STATUS_RNR;
        !          1653:        if (status) {
        !          1654:                OSWriteLE16(&CSR_p->status, status);    // ack RNR interrupt
        !          1655: 
        !          1656:                IOLog("Intel82557::%s restarting receiver\n", __FUNCTION__);
        !          1657: 
        !          1658:                IOLog("%s::%s RUS:0x%x Index:%d\n", getName(), __FUNCTION__, 
        !          1659:                          CSR_VALUE(SCB_STATUS_RUS, OSReadLE16(&CSR_p->status)),
        !          1660:                          tailRfd - rfdList_p);
        !          1661:                
        !          1662:                _abortReceive();
        !          1663: 
        !          1664: #if 0  // Display RFD/RBD fields
        !          1665:                for (int i = 0; i < NUM_RECEIVE_FRAMES; i++) {
        !          1666:                        IOLog("   %02d: %04x %04x - %08x %08x\n", i,
        !          1667:                                OSReadLE16(&rfdList_p[i].command),
        !          1668:                                OSReadLE16(&rfdList_p[i].status),
        !          1669:                                OSReadLE32(&rfdList_p[i]._rbd.size),
        !          1670:                                OSReadLE32(&rfdList_p[i].misc));
        !          1671:                }
        !          1672: #endif
        !          1673: 
        !          1674:                _resetRfdList();
        !          1675:                _startReceive();
        !          1676:     }
        !          1677: 
        !          1678:     return ret;
        !          1679: }
        !          1680: 
        !          1681: //---------------------------------------------------------------------------
        !          1682: // Function: _sendPacket
        !          1683: //
        !          1684: // Purpose:
        !          1685: //   Part of kerneldebugger protocol.
        !          1686: //   Returns true if the packet was sent successfully.
        !          1687: 
        !          1688: bool Intel82557::_sendPacket(void * pkt, UInt len)
        !          1689: {
        !          1690:        tbd_t * tbd_p;
        !          1691: 
        !          1692:     // Set up the TCB and issue the command
        !          1693:        //
        !          1694:     OSWriteLE16(&KDB_tcb_p->status, 0);
        !          1695:        OSWriteLE32(&KDB_tcb_p->link, C_NULL);
        !          1696:        OSWriteLE8(&KDB_tcb_p->threshold, TCB_TX_THRESHOLD);
        !          1697:        OSWriteLE16(&KDB_tcb_p->command, CSR_FIELD(TCB_COMMAND, CB_CMD_TRANSMIT) |
        !          1698:                 TCB_COMMAND_EL |
        !          1699:                 TCB_COMMAND_SF );
        !          1700:        OSWriteLE16(&KDB_tcb_p->count, 0);      // all data are in the TBD's.
        !          1701:        OSWriteLE8(&KDB_tcb_p->number, 1);      // 1 TBD only.
        !          1702: 
        !          1703:        // Copy the debugger packet to the pre-allocated buffer area.
        !          1704:        //
        !          1705:     len = MIN(len, ETHERMAXPACKET);
        !          1706:     len = MAX(len, ETHERMINPACKET);
        !          1707:     bcopy(pkt, KDB_buf_p, len);
        !          1708: 
        !          1709:        // Update the TBD.
        !          1710:        //
        !          1711:        tbd_p = &KDB_tcb_p->_tbds[0];
        !          1712:        OSWriteLE32(&tbd_p->addr, KDB_buf_paddr);
        !          1713:        OSWriteLE32(&tbd_p->size, CSR_FIELD(TBD_SIZE, len));
        !          1714: 
        !          1715:        // Start up the command unit to send the packet.
        !          1716:        //
        !          1717:        return _polledCommand((cbHeader_t *) KDB_tcb_p, KDB_tcb_p->_paddr);
        !          1718: }

unix.superglobalmegacorp.com

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