Annotation of XNU/iokit/Drivers/network/drvIntel82557/i82557Private.cpp, revision 1.1.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.