Annotation of XNU/iokit/Families/IOFireWire/IOFWUtils.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) 1999 Apple Computer, Inc.  All rights reserved.
                     24:  *
                     25:  * HISTORY
                     26:  * 3 June 99 wgulland created.
                     27:  *
                     28:  * Useful stuff called from several different FireWire objects.
                     29:  */
                     30: #include <IOKit/assert.h>
                     31: #include <IOKit/IOLib.h>
                     32: #include <IOKit/firewire/IOFWRegs.h>
                     33: #include <IOKit/firewire/IOFireWirePriv.h>
                     34: 
                     35: ////////////////////////////////////////////////////////////////////////////////
                     36: //
                     37: // FWComputeCRC16
                     38: //
                     39: //   This proc computes a CRC 16 check.
                     40: //
                     41: 
                     42: UInt16 FWComputeCRC16(UInt32 *pQuads, UInt32 numQuads)
                     43: {
                     44:     SInt32     shift;
                     45:     UInt32     sum;
                     46:     UInt32     crc16;
                     47:     UInt32     quadNum;
                     48:     UInt32     quad;
                     49: 
                     50:     // Compute CRC 16 over all quads.
                     51:     crc16 = 0;
                     52:     for (quadNum = 0; quadNum < numQuads; quadNum++) {
                     53:         quad = *pQuads++;
                     54:         for (shift = 28; shift >= 0; shift -= 4) {
                     55:             sum = ((crc16 >> 12) ^ (quad >> shift)) & 0x0F;
                     56:             crc16 = (crc16 << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
                     57:         }
                     58:     }
                     59: 
                     60:     return (crc16 & 0xFFFF);
                     61: }
                     62: 
                     63: 
                     64: ////////////////////////////////////////////////////////////////////////////////
                     65: //
                     66: // FWCSRROMInvalidateEntryIDType
                     67: //
                     68: //   Invalidate a CSR ROM entry ID.  This will deallocate any memory allocated
                     69: // for the ID excluding the ID data record itself.
                     70: //
                     71: // Probably only thing needed is to release reference to the ROM.
                     72: //
                     73: 
                     74: void  FWCSRROMInvalidateEntryIDType(CSRROMEntryID csrROMEntryID)
                     75: {
                     76:     CSRROMEntryIDDataPtr               pCSRROMEntryIDData;
                     77: 
                     78:     if (csrROMEntryID != kInvalidCSRROMEntryID)
                     79:     {
                     80:         pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
                     81: 
                     82:         switch (pCSRROMEntryIDData->entryType)
                     83:         {
                     84:                 case kLocalCSRROMEntryIDType :
                     85:                         break;
                     86: 
                     87:                 case kRemoteCSRROMEntryIDType :
                     88: 
                     89:                         break;
                     90: 
                     91:                 default :
                     92:                         break;
                     93:         }
                     94: 
                     95:         // Entry is now invalid.
                     96:         pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType;
                     97:     }
                     98: }
                     99: 
                    100: ////////////////////////////////////////////////////////////////////////////////
                    101: //
                    102: // FWCSRROMCreateEntryID
                    103: //
                    104: //   Allocate memory for a CSR ROM entry ID.
                    105: //zzz could be a little more efficient computing allocation size.
                    106: //
                    107: 
                    108: CSRROMEntryID  FWCSRROMCreateEntryID(void)
                    109: {
                    110:     CSRROMEntryID              csrROMEntryID = kInvalidCSRROMEntryID;
                    111:     CSRROMEntryIDDataPtr       pCSRROMEntryIDData;
                    112:     UInt32                     maxSize;
                    113: 
                    114:     // Determine maximum size of all entry types.
                    115:     // Need enough for local ID type.
                    116:     maxSize = sizeof (CSRROMLocalIDData);
                    117:     if (sizeof (CSRROMRemoteIDData) > maxSize)
                    118:         maxSize = sizeof (CSRROMRemoteIDData);
                    119: 
                    120:     // Allocate the data.
                    121:     pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) IOMalloc (maxSize);
                    122:     if (pCSRROMEntryIDData != NULL) {
                    123:         pCSRROMEntryIDData->entryType = kInvalidCSRROMEntryIDType;
                    124:         csrROMEntryID = (CSRROMEntryID) pCSRROMEntryIDData;
                    125:     }
                    126:     return (csrROMEntryID);
                    127: }
                    128: 
                    129: ////////////////////////////////////////////////////////////////////////////////
                    130: //
                    131: // FWCSRROMDisposeEntryID
                    132: //
                    133: //   Deallocate memory for a CSR ROM entry ID.
                    134: //
                    135: 
                    136: void  FWCSRROMDisposeEntryID(CSRROMEntryID csrROMEntryID)
                    137: {
                    138:     CSRROMEntryIDDataPtr pCSRROMEntryIDData;
                    139: 
                    140:     if (csrROMEntryID != kInvalidCSRROMEntryID) {
                    141:         UInt32 maxSize;
                    142: 
                    143:         // Determine maximum size of all entry types.
                    144:         // Need enough for local ID type.
                    145:         maxSize = sizeof (CSRROMLocalIDData);
                    146:         if (sizeof (CSRROMRemoteIDData) > maxSize)
                    147:             maxSize = sizeof (CSRROMRemoteIDData);
                    148:         pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
                    149: 
                    150:         // Invalidate entry.
                    151:         FWCSRROMInvalidateEntryIDType (csrROMEntryID);
                    152: 
                    153:         // Deallocate entry.
                    154:         IOFree(pCSRROMEntryIDData, maxSize);
                    155:     }
                    156: }
                    157: 
                    158: ////////////////////////////////////////////////////////////////////////////////
                    159: //
                    160: // FWCSRROMCreateRemoteEntryID
                    161: //
                    162: //   Create a remote CSR ROM entry ID.
                    163: //
                    164: 
                    165: static IOReturn        FWCSRROMCreateRemoteEntryID(
                    166:        CSRROMEntryID                   *pCSRROMEntryID,
                    167:        const UInt32 *                  data,
                    168:        UInt32                          *physicalPath,
                    169:        UInt32                          pathSize)
                    170: {
                    171:     CSRROMEntryID                      csrROMEntryID = *pCSRROMEntryID;
                    172:     CSRROMEntryIDDataPtr               pCSRROMEntryIDData;
                    173:     CSRROMRemoteIDDataPtr              pCSRROMRemoteIDData;
                    174: 
                    175:     // Allocate an entry ID if given entry ID is invalid.
                    176:     if (csrROMEntryID == kInvalidCSRROMEntryID) {
                    177:         csrROMEntryID = FWCSRROMCreateEntryID ();
                    178:         // If entry ID is still invalid, there must have been a memory error.
                    179:         if (csrROMEntryID == kInvalidCSRROMEntryID)
                    180:             return kIOReturnNoMemory;
                    181:    }
                    182: 
                    183: 
                    184:     // Get data from ID.
                    185:     pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
                    186:     pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData;
                    187: 
                    188:     // If entry is not a remote type, invalidate its type.
                    189:     if ((pCSRROMEntryIDData->entryType != kRemoteCSRROMEntryIDType) &&
                    190:         (pCSRROMEntryIDData->entryType != kInvalidCSRROMEntryIDType)) {
                    191:         FWCSRROMInvalidateEntryIDType (csrROMEntryID);
                    192:     }
                    193: 
                    194:     // Make entry a remote type.
                    195:     pCSRROMEntryIDData->entryType = kRemoteCSRROMEntryIDType;
                    196: 
                    197: 
                    198:     // Copy directory paths and data pointer
                    199:     pCSRROMRemoteIDData->data = data;
                    200:     bcopy (physicalPath, pCSRROMRemoteIDData->physicalPath, pathSize * sizeof (UInt32));
                    201:     pCSRROMRemoteIDData->pathSize = pathSize;
                    202: 
                    203:     // Return entry ID.
                    204:     *pCSRROMEntryID = csrROMEntryID;
                    205: 
                    206:     return (kIOReturnSuccess);
                    207: }
                    208: 
                    209: ////////////////////////////////////////////////////////////////////////////////
                    210: //
                    211: // FWCSRROMDisposeIterator
                    212: //
                    213: //   Dispose of storage allocated for iterator.
                    214: //
                    215: 
                    216: void FWCSRROMDisposeIterator(CSRROMEntryIterator csrROMIterator)
                    217: {
                    218:     CSRROMEntryIteratorRecPtr  pIteratorRec;
                    219: 
                    220:     // Deallocate if iterator is valid.
                    221:     if (csrROMIterator != kInvalidCSRROMIterator) {
                    222:         // Get iterator record.
                    223:         pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;
                    224: 
                    225:         // Deallocate iterator record.
                    226:         IOFree (pIteratorRec, sizeof (CSRROMEntryIteratorRec));
                    227:     }
                    228: }
                    229: 
                    230: 
                    231: ////////////////////////////////////////////////////////////////////////////////
                    232: //
                    233: // FWCSRROMSetIterator
                    234: //
                    235: //   Set current path and relationship of iterator.
                    236: //zzz should support all entry ID types.
                    237: //zzz should support kIterateRoot
                    238: //
                    239: 
                    240: IOReturn FWCSRROMSetIterator(
                    241:        CSRROMEntryIterator                     csrROMIterator,
                    242:        CSRROMEntryID                           csrROMEntryID,
                    243:        CSRROMIterationOp                       relationship)
                    244: {
                    245:     CSRROMEntryIteratorRecPtr  pIteratorRec;
                    246:     CSRROMEntryIDDataPtr               pCSRROMEntryIDData;
                    247:     CSRROMRemoteIDDataPtr              pCSRROMRemoteIDData;
                    248: 
                    249:     // Get CSR ROM search iterator record.
                    250:     pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;
                    251: 
                    252:     // Set to given entry.
                    253:     if (csrROMEntryID != kInvalidCSRROMEntryID) {
                    254:         // Get entry data from ID.
                    255:         pCSRROMEntryIDData = (CSRROMEntryIDDataPtr) csrROMEntryID;
                    256: 
                    257:         if (pCSRROMEntryIDData->entryType == kRemoteCSRROMEntryIDType) {
                    258:             // Recast entry data.
                    259:             pCSRROMRemoteIDData = (CSRROMRemoteIDDataPtr) pCSRROMEntryIDData;
                    260: 
                    261:             // Copy physical path.
                    262:             bcopy (pCSRROMRemoteIDData->physicalPath,
                    263:                                             pIteratorRec->physicalPath,
                    264:                                             pCSRROMRemoteIDData->pathSize * sizeof (UInt32));
                    265: 
                    266:             // Copy data pointer and path depth
                    267:             pIteratorRec->data = pCSRROMRemoteIDData->data;
                    268:             pIteratorRec->pathSize = pCSRROMRemoteIDData->pathSize;
                    269:         }
                    270:     }
                    271: 
                    272:     // Set to given relationship.
                    273:     if (relationship != kIterateContinue)
                    274:             pIteratorRec->relationship = relationship;
                    275: 
                    276:     return (kIOReturnSuccess);
                    277: }
                    278: 
                    279: 
                    280: ////////////////////////////////////////////////////////////////////////////////
                    281: //
                    282: // FWCSRROMEntrySearch
                    283: //
                    284: //   Search for the next ROM entry that matches the search criteria.
                    285: //zzz need to check the search type in the criteria record and the relationship
                    286: //zzz could be more efficient.  should make and use more defs.
                    287: //zzz need to return information on what exactly was found
                    288: //zzz fill in entry value better
                    289: //zzz should break this up
                    290: //zzz should support all entry ID types.
                    291: //
                    292: 
                    293: // zzz
                    294: // Made a quick fix here so that if we are searching for Unit Directories (key d1)
                    295: // we will ignore any Instance Directories (key d8) because they contain redundant
                    296: // pointers to Unit Directories.  This is almost surely not the best soltution.
                    297: 
                    298: IOReturn FWCSRROMEntrySearch(
                    299:     CSRROMEntryIterator                csrROMIterator,
                    300:     CSRROMIterationOp          relationship,
                    301:     CSRROMEntryID              *pCSRROMEntryID,
                    302:     int                        *pDone,
                    303:     CSRROMSearchCriteriaPtr    pSearchCriteria,
                    304:     UInt8 *                    pEntryValue,
                    305:     UInt32                     *pEntrySize)
                    306: {
                    307:     CSRROMEntryIteratorRecPtr  pIteratorRec;
                    308:     UInt32                             currentAddress, entryValueAddress;
                    309:     UInt32                             pathSize;
                    310:     UInt32                             directoryEnd;
                    311:     UInt32                             address;
                    312:     UInt32                             directoryHeader, directoryEntry;
                    313:     UInt32                             leafEntry;
                    314:     UInt32                             keyType, keyValue;
                    315:     UInt32                             keyTypeBit, keyValueBitHi, keyValueBitLo;
                    316:     UInt32                             returnedEntrySize;
                    317:     bool                               found, done;
                    318:     IOReturn                   status = kIOReturnSuccess;
                    319: 
                    320: //zzz Part of the Instance Directory hack
                    321:     bool                               unitDirSearch;
                    322:     bool                               ignoreInstanceDir;
                    323: 
                    324:     // If we are searching for Unit Directories (in FWExpertLoader.c/FWUpdateDevice)
                    325:     // then just don't go down any Instance Directories (key d8), because we'll find a
                    326:     // redundant pointer to the Unit Directory in there.
                    327: 
                    328:     unitDirSearch = (pSearchCriteria->csrROMSearchType == kCSRROMSearchForKey) &&
                    329:             (pSearchCriteria->keyType == kCSRDirectoryKeyTypeBit) &&
                    330:             (pSearchCriteria->keyHi == kCSRUnitDirectoryKeyHiBit) &&
                    331:             (pSearchCriteria->keyLo == kCSRUnitDirectoryKeyLoBit);
                    332: 
                    333:     // Get CSR ROM search iterator record.
                    334:     pIteratorRec = (CSRROMEntryIteratorRecPtr) csrROMIterator;
                    335: 
                    336:     // Read the current directory length.  First, get base address of current
                    337:     // directory by going up one node in the directory path.  Special case
                    338:     // when we're in the root directory.  Second, read the directory length
                    339:     // at the base address.
                    340:     pathSize = pIteratorRec->pathSize;
                    341:     if (pathSize > 2) {
                    342:         address = pIteratorRec->physicalPath[pathSize - 2];
                    343:         directoryEntry = pIteratorRec->data[address];
                    344:         address += (directoryEntry & 0x00FFFFFF);
                    345:     }
                    346:     else {
                    347:         address = pIteratorRec->physicalPath[0];
                    348:     }
                    349:     directoryHeader = pIteratorRec->data[address];
                    350:     directoryEnd = address + ((directoryHeader >> 16) + 1);
                    351: 
                    352:     // Loop until we've found what we're looking for, or we've searched
                    353:     // everything.
                    354:     found = false;
                    355:     done = false;
                    356:     while ((!found) && (!done)) {
                    357:         // Read our current location.
                    358:         pathSize = pIteratorRec->pathSize;
                    359:         currentAddress = pIteratorRec->physicalPath[pathSize - 1];
                    360: 
                    361:         // Check if search was reset.
                    362:         if (pIteratorRec->reset) {
                    363:             pIteratorRec->reset = false;
                    364:         }
                    365:         else {
                    366:             // Read directory entry at current address.
                    367:             //zzz should have some address defs.
                    368:             directoryEntry = pIteratorRec->data[currentAddress];
                    369:             // If the current directory entry is a directory, add it to
                    370:             // the path.  Otherwise, go to next directory entry.
                    371:             keyType = (directoryEntry & 0xC0000000) >> 30;
                    372: //zzz
                    373: //The Instance Directory hack
                    374:             ignoreInstanceDir = (directoryEntry >> 24) == 0xd8;
                    375: //zzz
                    376:             if ((keyType == kCSRDirectoryKeyType) && !ignoreInstanceDir) {
                    377:                 // Go to and read directory header.
                    378:                 //zzz should do this the right way if offset > 1024.
                    379:                 currentAddress += (directoryEntry & 0x00FFFFFF);
                    380:                 directoryHeader = pIteratorRec->data[currentAddress];
                    381:                 // Add directory to path and set location to first
                    382:                 // entry in directory.
                    383:                 pathSize++;
                    384: 
                    385:                 directoryEnd =
                    386:                         currentAddress + ((directoryHeader >> 16) + 1);
                    387: 
                    388:                 currentAddress += 1;
                    389:             }
                    390:             else {
                    391:                 currentAddress += 1;
                    392:             }
                    393:         }
                    394: 
                    395:         // If we're past the end of the current directory, take it out
                    396:         // of path.
                    397:         while ((currentAddress >= directoryEnd) && (!done)) {
                    398:             pathSize--;
                    399:             currentAddress = pIteratorRec->physicalPath[pathSize - 1] + 1;
                    400: 
                    401:             // Read the current directory length.
                    402:             if (pathSize > 2) {
                    403:                 address = pIteratorRec->physicalPath[pathSize - 2];
                    404:                 directoryEntry = pIteratorRec->data[address];
                    405:                 address += (directoryEntry & 0x00FFFFFF);
                    406:             }
                    407:             else {
                    408:                 address = pIteratorRec->physicalPath[0];
                    409:             }
                    410:             directoryHeader = pIteratorRec->data[address];
                    411:             directoryEnd = address + ((directoryHeader >> 16) + 1);
                    412:             if (pathSize < 2) {
                    413:                 done = true;
                    414:             }
                    415:         }
                    416:         // If we're not done searching, check the current directory entry
                    417:         // against the search criteria.
                    418:         if (!done) {
                    419:             directoryEntry = pIteratorRec->data[currentAddress];
                    420:             // Read key type and value.
                    421:             keyType = (directoryEntry & 0xC0000000) >> 30;
                    422:             keyValue = (directoryEntry & 0x3F000000) >> 24;
                    423: 
                    424:             // Convert to bit flag.
                    425:             keyTypeBit = 1 << keyType;
                    426:             if (keyValue > 31) {
                    427:                 keyValueBitHi = 1 << (keyValue - 32);
                    428:                 keyValueBitLo = 0;
                    429:             }
                    430:             else {
                    431:                 keyValueBitHi = 0;
                    432:                 keyValueBitLo = 1 << keyValue;
                    433:             }
                    434: 
                    435:             // Compare bit flags against search criteria.
                    436: 
                    437:             if ((keyTypeBit & pSearchCriteria->keyType) &&
                    438:                     ((keyValueBitHi & pSearchCriteria->keyHi) ||
                    439:                                 (keyValueBitLo & pSearchCriteria->keyLo))) {
                    440:                 switch (keyType) {
                    441:                     case kCSRImmediateKeyType :
                    442:                         if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
                    443:                                 // Determine size of data.
                    444:                                 if (*pEntrySize < 4)
                    445:                                         returnedEntrySize = *pEntrySize;
                    446:                                 else
                    447:                                         returnedEntrySize = 4;
                    448: 
                    449:                                 // Copy data.//zzz not right.
                    450:                                 //zzz need def here.
                    451:                                 *((UInt32 *) pEntryValue) =
                    452:                                         directoryEntry & 0x00FFFFFF;
                    453: 
                    454:                                 // Return size.
                    455:                                 *pEntrySize = returnedEntrySize;
                    456:                         }
                    457:                         break;
                    458: 
                    459:                     case kCSROffsetKeyType :
                    460:                         if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
                    461:                                 // Determine size of data.
                    462:                                 if (*pEntrySize < 4)
                    463:                                         returnedEntrySize = *pEntrySize;
                    464:                                 else
                    465:                                         returnedEntrySize = 4;
                    466: 
                    467:                                 // Copy data.//zzz not right.
                    468:                                 //zzz need def here.
                    469:                                 *((UInt32 *) pEntryValue) =
                    470:                                         directoryEntry & kCSREntryValue;
                    471: 
                    472:                                 // Return size.
                    473:                                 *pEntrySize = returnedEntrySize;
                    474:                         }
                    475:                         break;
                    476: 
                    477:                     case kCSRLeafKeyType :
                    478:                         if ((pEntrySize != NULL) && (pEntryValue != NULL)) {
                    479:                             // Get address of leaf.
                    480:                             //zzz need to do indirect stuff right.
                    481:                             entryValueAddress = currentAddress + (directoryEntry & kCSREntryValue);
                    482: 
                    483:                             // Get size of leaf.
                    484:                             leafEntry = pIteratorRec->data[entryValueAddress];
                    485:                             returnedEntrySize = (leafEntry >> 16) * sizeof (UInt32);
                    486:                             entryValueAddress += 1;
                    487:                             // Determine size of data.
                    488:                             if (returnedEntrySize > *pEntrySize)
                    489:                                 returnedEntrySize = *pEntrySize;
                    490:                             // Copy data.
                    491:                             bcopy(&pIteratorRec->data[entryValueAddress], pEntryValue, returnedEntrySize);
                    492:                             // Return size.
                    493:                             *pEntrySize = returnedEntrySize;
                    494:                         }
                    495: 
                    496:                         break;
                    497: 
                    498:                     case kCSRDirectoryKeyType ://zzz
                    499:                         break;
                    500: 
                    501:                     default : //zzz
                    502:                         break;
                    503:                 }
                    504: 
                    505:                 found = true;
                    506:             }
                    507:         }
                    508: 
                    509:         // Update current address.
                    510:         pIteratorRec->physicalPath[pathSize - 1] = currentAddress;
                    511:         pIteratorRec->pathSize = pathSize;
                    512:     }
                    513: 
                    514:     // Return CSR ROM entry ID.
                    515:     if (pCSRROMEntryID != NULL) {
                    516:         if (!done) {
                    517:             status = FWCSRROMCreateRemoteEntryID
                    518:                                     (pCSRROMEntryID,
                    519:                                                 pIteratorRec->data,
                    520:                                                 pIteratorRec->physicalPath,
                    521:                                                 pIteratorRec->pathSize);
                    522:         }
                    523:         else {
                    524:             if (*pCSRROMEntryID != kInvalidCSRROMEntryID)
                    525:                     FWCSRROMDisposeEntryID (*pCSRROMEntryID);
                    526:             *pCSRROMEntryID = kInvalidCSRROMEntryID;
                    527:         }
                    528:     }
                    529: 
                    530:     *pDone = done;
                    531:     return (status);
                    532: }
                    533: 
                    534: 

unix.superglobalmegacorp.com

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