Annotation of kernel/bsd/dev/ppc/drvUSBCMD/driverservices.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:        File:           DriverServices.c
        !            27: 
        !            28:        Contains:       Native Driver support code for Device Manager
        !            29: 
        !            30:        Version:        xxx put version here xxx
        !            31: 
        !            32:        Written by:     Tom Saulpaugh
        !            33: 
        !            34:        Copyright:      � 1994-1997 by Apple Computer, Inc., all rights reserved.
        !            35: 
        !            36:        File Ownership:
        !            37: 
        !            38:                DRI:                            xxx put dri here xxx
        !            39: 
        !            40:                Other Contact:          xxx put other contact here xxx
        !            41: 
        !            42:                Technology:                     xxx put technology here xxx
        !            43: 
        !            44:        Writers:
        !            45: 
        !            46:                (JM3)   Jim Murphy
        !            47:                (CSS)   Chas Spillar
        !            48:                (KW)    Kevin Williams
        !            49:                (MRN)   Matthew Nelson
        !            50: 
        !            51:        Change History (most recent first):
        !            52: 
        !            53:                <63>   18-Jun-97        JM3             Updated for cleaned up NanoKernelPriv/PPCInfoRecordsPriv.
        !            54:                <62>     5/30/97        CSS             Delay() now takes an unsigned long * instead of a long * as its
        !            55:                                                                        second parameter.
        !            56:                <61>     3/18/97        KW              DelayFor Hardware was just looking at 5FFF EF80 to get the
        !            57:                                                                        Processor Info structure. Now use the pointer located  at
        !            58:                                                                        ProcessorInfo Ptr to get the pointer to the structure
        !            59:                <60>      8/6/96        MRN             Changes to stop using private copy of 64 bit math routines and
        !            60:                                                                        instead link against the real shipping version of the Math64Lib.
        !            61:                <59>    10/30/95        MRN             Get rid of C version of SynchronizeIO that moved to
        !            62:                                                                        DriverServices.s, and make file buildable with MrC.
        !            63:                <58>     4/15/95        tjm             #1238020 - Fix DelayForHardware to handle 601 correctly. Moved
        !            64:                                                                        fix back into DSL.m4
        !            65:                <57>     4/14/95        tjm             #1238020 - Fix DelayForHardware to handle 601 correctly.
        !            66:                <56>     4/10/95        TS              Fix bug in PBEnqueueLast
        !            67:                <55>     4/10/95        TS              Optimize PBEnqueueLast for a queue of 1 or less elements
        !            68:                <54>      4/6/95        TS              Fix PBDequeue
        !            69:                <53>      4/5/95        TS              Rewrite PBEnqueueLast (Bug #1236338)
        !            70:                <52>     3/31/95        TS              Bump preallocated data numbers and comment out debugging names
        !            71:                                                                        before ROM freezes.
        !            72:                <51>     3/30/95        TS              Retry CompareAndSwap in PBDequeue if element is at head of queue
        !            73:                <50>     3/30/95        TS              Add OSTypes to each Globals Struct and reserve some space here
        !            74:                                                                        as well.
        !            75:                <49>     3/29/95        TS              Return last element in PBDequeueLast (Optimized path)
        !            76:                <48>     3/28/95        TS              Optimize PBDequeue and PBDequeueLast for the first element
        !            77:                <47>     3/27/95        TS              Fix bug #1232734 (IOCommandIsComplete return value)
        !            78:                <46>     3/22/95        TS              Optimize fix for bug #1228034
        !            79:                <45>     3/14/95        tjm             #1227300 - Insure that PStrNCmp works with all equal strings.
        !            80:                <44>     3/14/95        tjm             #1228034 - insure that queueing functions are safe from
        !            81:                                                                        interrupts
        !            82:                <43>     2/21/95        tjm             #1220575 - Correct PStrNCat to handle strings > 255.
        !            83:                <42>     2/20/95        tjm             #1220560 - Fix PStrCat to correctly handle dest strings > 128.
        !            84:                <41>     1/27/95        tjm             #1214980 - PStrNCmp does not return correct value with null
        !            85:                                                                        strings.
        !            86:                <40>     1/25/95        tjm             #1214207 - Fix PBDequeueLast to delete if only one item in
        !            87:                                                                        queue.
        !            88:                <39>     1/25/95        tjm             #1214730 - Fix PStrCat to only Cat up to 255 chars.
        !            89:                <38>     1/19/95        tjm             Break out DSLInit routine to aid in debugging
        !            90:                <37>     1/19/95        tjm             #1211193 - Allow Dequeuing from head.
        !            91:                <36>     1/18/95        tjm             #1212320 - Insure PBEnqueueLast is re-entrant.
        !            92:                <35>     1/18/95        tjm             #1203060 - Make a Global Data Lib for the DSL.
        !            93:                <34>     1/16/95        tjm             #1203145 - Add DelayForHardware so drivers can call delay
        !            94:                                                                        routine at InterruptTime.
        !            95:                <33>     1/10/95        tjm             #1210156 - Make sure PBQueueDelete correctly deallocated
        !            96:                                                                        preallocated qHdrs.
        !            97:                <32>     1/10/95        tjm             #1210154 - return noErr for unaligned qHdr allocation.
        !            98:                <31>     1/10/95        tjm             #1207351 - Make sure PStrLen returns correct value.
        !            99:                <30>     1/10/95        tjm             #1207081 - Fix the PStr functions to handle lengths correctly
        !           100:                <29>      1/9/95        tjm             #1208049 - return paramErr if CSI fails.
        !           101:                <28>      1/9/95        tjm             #1209423 - correctly handle empty qHdr when it is empty
        !           102:                <27>      1/9/95        MN              Add a call to UpTime in the CFM initialization function to
        !           103:                                                                        initialize the timebase variable in the new timing functions.
        !           104:                <26>    12/21/94        MN              Restore checkins 18 through 24 and include the fixes checked
        !           105:                                                                        into 25.
        !           106:                <25>    12/21/94        MN              Added alignment support to PBQueueCreate and PBQueueDelete for Marconi_v16c2
        !           107:                                                                        which would have checked in over the top of checkins 18 through 24.
        !           108:                <24>    12/20/94        tjm             #1206624 - Fix PBDequeueLastSync to correctly dequeue item.
        !           109:                <23>    12/19/94        tjm             #1204196 - fix this again.
        !           110:                <22>    12/16/94        tjm             #1206622 - eliminate reentrantcy problem with PBDequeueSync.
        !           111:                <21>    12/16/94        tjm             #1203051 - added PBEnqueueLast function
        !           112:                <20>    12/15/94        tjm             #1204196 - call PBQueueInit when PBQueueCreate is successful.
        !           113:                <19>    12/15/94        tjm             #1204193 - initialize qFlags in qHeader of PBQueueInit.
        !           114:                <18>    12/15/94        tjm             #1203057 - increment the number of SWI's to 32
        !           115:                <17>     12/5/94        tjm             #1202888 - Fix PBDequeue to not corrupt queue with 2 elements
        !           116:                <16>     12/5/94        tjm             #1202776 - Fix PBDequeue to return qErr for nonexistant element.
        !           117:                <15>     12/5/94        tjm             #1201314 - correctly queue secondary interrupts
        !           118:                <14>    11/15/94        tjm             #1195428 - Fix function prototypes to correctly define src ptrs
        !           119:                                                                        as const.
        !           120:                <13>     11/3/94        tjm             fix DelayFor to use low end of 64 bit divide, ID#1197350
        !           121:                <12>    10/25/94        tjm             Call TimerInitialize, SIHInitialize, and MemoryInitialze to fix
        !           122:                                                                        #1192590
        !           123:                <11>     9/15/94        MN              Add call in DSL_Init to startup Interrupt Manager and change
        !           124:                                                                        PBQueueInit to return an error code;
        !           125:                <10>     8/31/94        TS              Make the DSL_Init check for failures
        !           126:                 <9>     8/29/94        TS              Add a call to the CFM init routine to calculate physical RAM
        !           127:                                                                        size using the ROM physical space table
        !           128:                 <8>     8/25/94        TS              Add DelayFor and Move BlockCopy to MemoryManagement.c
        !           129:                 <7>     8/24/94        TS              Add in checks for correct execution levels
        !           130:                 <6>     8/24/94        TS              Make DSL_Init return noErr to library will load
        !           131:                 <5>     8/24/94        TS              Build ExecutionLevel Func
        !           132:                 <4>     8/23/94        TS              Implement SoftwareInterrupts
        !           133:                 <3>     8/18/94        TS              Add more queue functions
        !           134:                 <2>     8/17/94        JF              Changes from PCI developer kitchen
        !           135:                 <1>      8/5/94        JF              first checked in
        !           136: 
        !           137: */
        !           138: 
        !           139: 
        !           140: 
        !           141: //
        !           142: // Source to the NuDriver Support Services Library
        !           143: //
        !           144: 
        !           145: //#include <Types.h>
        !           146: //#include <Strings.h>
        !           147: //#include <Files.h>
        !           148: //#include <MixedMode.h>
        !           149: //#include <LowMem.h>
        !           150: //#include <Math64.h>
        !           151: 
        !           152: // Get Prototypes of the Exported Services First,...
        !           153: 
        !           154: #include "driverservices.h"
        !           155: #include "driverservicespriv.h"
        !           156: #include "PPCInfoRecordsPriv.h"
        !           157: #include "rhap_local.h"
        !           158: 
        !           159: // The Driver Services Follow,...
        !           160: 
        !           161: 
        !           162: OSErr InitSwis (void);
        !           163: 
        !           164: /////////////////////////////////////////////////////////////////////////////////
        !           165: //
        !           166: //     Command Processing
        !           167: //
        !           168: //
        !           169: 
        !           170: /*-------------------------------------------------------------------------------
        !           171: 
        !           172: Routine:       IOCommandIsComplete     -       Marks I/O Command as Done.
        !           173: 
        !           174: Function:      Returns IODone result from Device Manager
        !           175: 
        !           176: Input:         theID           - ID of the in-progress I/O command.
        !           177:                        theResult       - the result value of the command. (Low 16-bits are placed in IOPB)
        !           178: 
        !           179: Result:                noErr   or 
        !           180: -------------------------------------------------------------------------------*/
        !           181: /*naga
        !           182: enum {
        !           183:        uppIODoneProcInfo =             kRegisterBased
        !           184:                                                |       REGISTER_ROUTINE_PARAMETER(1,kRegisterA1,kFourByteCode)
        !           185:                                                |       REGISTER_ROUTINE_PARAMETER(2,kRegisterD0,kFourByteCode)
        !           186: };
        !           187: 
        !           188: 
        !           189: OSErr  IOCommandIsComplete             (       IOCommandID             theID,
        !           190:                                                                        OSErr                   theResult)
        !           191: {
        !           192:        ParmBlkPtr       The_Pb         = (ParmBlkPtr)theID;
        !           193:        OSErr           *The_Result = (OSErr *)(&The_Pb -> ioParam.ioCmdAddr);
        !           194:        
        !           195:        if (theID == nil)
        !           196:                return paramErr;
        !           197: 
        !           198:        *The_Result = theResult;
        !           199:        
        !           200:        (void)CallUniversalProc (       LMGetJIODone(),
        !           201:                                                                uppIODoneProcInfo,
        !           202:                                                                The_Pb,
        !           203:                                                                1 );
        !           204:        return noErr;
        !           205: }
        !           206: naga */
        !           207: /*-------------------------------------------------------------------------------
        !           208: 
        !           209: Routine:       GetIOCommandInfo        -       Returns info about an in-progress I/O command.
        !           210: 
        !           211: Function:      Returns IOCommandContents, IOCommandCode, and IOCommandKind.
        !           212: 
        !           213: Input:         theID   - ID of the in-progress I/O command.
        !           214: 
        !           215: Output:                theContents             - pointer to the IOPB or Initialize/Finalize Contents.
        !           216:                        theCommand              - the command code
        !           217:                        theKind                 - the kind of I/O (Sync, Async, or Immed)
        !           218:                        
        !           219: Result:                noErr   
        !           220: -------------------------------------------------------------------------------*/
        !           221: /*naga
        !           222: OSErr  GetIOCommandInfo                (       IOCommandID                             theID,
        !           223:                                                                    IOCommandContents   *       theContents,
        !           224:                                                                        IOCommandCode           *       theCommand,
        !           225:                                                                        IOCommandKind           *       theKind )
        !           226: {
        !           227:        IOCommandContents       The_Contents;
        !           228:        ParmBlkPtr                      The_Pb          = (ParmBlkPtr)theID;
        !           229: 
        !           230:        if (theID == nil)
        !           231:                return paramErr;
        !           232: 
        !           233:        The_Contents . pb = The_Pb;
        !           234:        
        !           235:        *theContents = The_Contents;
        !           236:        *theCommand  = (The_Pb  -> ioParam.ioTrap & 0x00ff);
        !           237:        *theKind         = ((The_Pb -> ioParam.ioTrap & 0xff00) >> 8);
        !           238:        
        !           239:        return noErr;
        !           240: }
        !           241: */
        !           242: 
        !           243: /////////////////////////////////////////////////////////////////////////////////
        !           244: //
        !           245: //     Queues
        !           246: //
        !           247: //
        !           248: 
        !           249: /*-------------------------------------------------------------------------------
        !           250: 
        !           251: Routine:       PBQueueInit     -       Initialize a Queue (@ NON-Interrupt-lvl and SIH-lvl)
        !           252: 
        !           253: -------------------------------------------------------------------------------*/
        !           254: 
        !           255: OSErr PBQueueInit(QHdrPtr qHeader)
        !           256: {
        !           257:        qHeader -> qHead = nil;
        !           258:        qHeader -> qTail = nil;
        !           259:        qHeader -> qFlags = 0x0000;
        !           260:        
        !           261:        return noErr;
        !           262: }
        !           263: 
        !           264: /*-------------------------------------------------------------------------------
        !           265: 
        !           266: Routine:       PBQueueCreate   -       Initialize a Queue (@ NON-Interrupt lvl)
        !           267: 
        !           268: -------------------------------------------------------------------------------*/
        !           269: 
        !           270: OSErr PBQueueCreate(QHdrPtr *qHeader)
        !           271: {
        !           272:        Ptr **theQueue;
        !           273:        
        !           274:        if (CurrentExecutionLevel() != kTaskLevel)
        !           275:        {
        !           276:                // SysDebugStr ((StringPtr)"\pPBQueueCreate not called at Task Level!");
        !           277:                // 11/30/98 Adam return -1;
        !           278:        }
        !           279:        
        !           280:        *qHeader = nil;
        !           281:        theQueue = (Ptr **)PoolAllocateResident (sizeof(QHdr)+sizeof(short)+sizeof(Ptr),true);
        !           282:        if (theQueue != nil)
        !           283:        {
        !           284:                // Store orig ptr in first 4 bytes.
        !           285:                *theQueue = (Ptr *)theQueue;
        !           286:                theQueue++;
        !           287:                
        !           288:                // Are we not aligned?
        !           289:                if ( ((UInt32)theQueue & 3) == 0 )
        !           290:                {
        !           291:                        short *pattern = (short *)theQueue;
        !           292:                        
        !           293:                        *pattern++      = 0x4D4E;
        !           294:                        *qHeader        = (QHdrPtr)pattern;
        !           295:                        return noErr;
        !           296:                }
        !           297:                else
        !           298:                {
        !           299:                        *qHeader        = (QHdrPtr)theQueue;
        !           300:                        return noErr;
        !           301:                }
        !           302:        }
        !           303:        else
        !           304:                return mFulErr;
        !           305: }
        !           306: 
        !           307: /*-------------------------------------------------------------------------------
        !           308: 
        !           309: Routine:       PBQueueDelete   -       Finalize a Queue (@ NON-Interrupt lvl)
        !           310: 
        !           311: -------------------------------------------------------------------------------*/
        !           312: 
        !           313: OSErr PBQueueDelete(QHdrPtr qHeader)
        !           314: {
        !           315:        Ptr       **theMemory;
        !           316:        UInt16 *pattern = (UInt16 *)qHeader;
        !           317:        
        !           318:        if (CurrentExecutionLevel() != kTaskLevel)
        !           319:        {
        !           320:                // SysDebugStr ((StringPtr)"\pPBQueueDelete not called at Task Level!");
        !           321:                return -1;
        !           322:        }
        !           323:        
        !           324:        if (*--pattern == 0x4D4E)
        !           325:                qHeader = (QHdrPtr)((UInt32)(qHeader) - sizeof(UInt16));
        !           326:                
        !           327:        theMemory = (Ptr **)qHeader;
        !           328:        theMemory--;
        !           329:        
        !           330:        if (*theMemory != (Ptr *)theMemory)
        !           331:        {
        !           332:                // SysDebugStr ((StringPtr)"\pPBQueueDelete not a Queue Header!");
        !           333:                return -1;
        !           334:        }
        !           335: 
        !           336:        (void)PoolDeallocate(theMemory);
        !           337:        return noErr;
        !           338: }
        !           339: 
        !           340: /*-------------------------------------------------------------------------------
        !           341: 
        !           342: Routine:       PBEnqueueLast   -       Add an IOPB to the end of a Request Queue. (@ Any Exec-lvl)
        !           343:                                                                (Optimized for queue size of 1 or less)
        !           344: 
        !           345: -------------------------------------------------------------------------------*/
        !           346: 
        !           347: OSErr PBEnqueueLast(QElemPtr qElement, QHdrPtr qHeader)
        !           348: {
        !           349:        QElemPtr currElemPtr;
        !           350:        UInt16 sr;
        !           351:        
        !           352:        // New element will be at end of queue.
        !           353:        qElement -> qLink = nil;
        !           354: 
        !           355:        // Currently an empty queue?
        !           356:        while ( qHeader -> qHead == nil )
        !           357:        {
        !           358:                if (CompareAndSwap ((UInt32) nil, (UInt32) qElement, (UInt32 *) &qHeader->qHead))
        !           359:                        return noErr;
        !           360:        }
        !           361:        
        !           362:        // Multi-element queue,...
        !           363:        
        !           364:        // Do it the sure, but slow way.
        !           365:        sr = Disable68kInterrupts();
        !           366: 
        !           367:        // Entire queue empty?
        !           368:        if ( qHeader -> qHead == nil )
        !           369:        {
        !           370:                // Add at head of queue
        !           371:                qHeader -> qHead = qElement;
        !           372:        }
        !           373:        else
        !           374:        {
        !           375:                // Else, Get first element in queue.
        !           376:                currElemPtr     = (QElemPtr)qHeader->qHead;
        !           377:                
        !           378:                // Move toward the end of the queue,...
        !           379:                while ( currElemPtr -> qLink != nil )
        !           380:                {       
        !           381:                        currElemPtr     = currElemPtr -> qLink;
        !           382:                }
        !           383:        
        !           384:                currElemPtr -> qLink = qElement;
        !           385:        }
        !           386:        
        !           387:        Restore68kInterrupts(sr);
        !           388:        return noErr;
        !           389: }
        !           390: 
        !           391: /*-------------------------------------------------------------------------------
        !           392: 
        !           393: Routine:       PBEnqueue       -       Add an IOPB to Head of Request Queue. (@ Any Exec-lvl)
        !           394: 
        !           395: Function:      Returns (nothing)
        !           396:                        
        !           397: Result:                void    
        !           398: -------------------------------------------------------------------------------*/
        !           399: 
        !           400: void PBEnqueue(QElemPtr qElement, QHdrPtr qHeader)
        !           401: {
        !           402:        do {
        !           403:                qElement -> qLink = qHeader->qHead;
        !           404:        } while (CompareAndSwap ((UInt32) qElement->qLink, (UInt32) qElement,
        !           405:                                                                                        (UInt32 *) &qHeader->qHead) == false);
        !           406: }
        !           407: 
        !           408: 
        !           409: /*-------------------------------------------------------------------------------
        !           410: 
        !           411: Routine:       PBDequeue       -       Remove an IOPB from a Request Queue.  (@ Any Exec-lvl)
        !           412: 
        !           413: Function:      Returns (nothing)
        !           414:                        
        !           415: Result:                void    
        !           416: -------------------------------------------------------------------------------*/
        !           417: 
        !           418: static OSErr PBDequeueSync(QElemPtr qElement, QHdrPtr qHeader)
        !           419: {
        !           420:        QElemPtr prevElemPtr, currElemPtr;
        !           421:        OSErr    result = noErr;
        !           422:        UInt16  sr;
        !           423:        
        !           424:        // Validate params.
        !           425:        if ( (qElement == nil) || (qHeader == nil) )
        !           426:                return paramErr;
        !           427:                
        !           428:        sr = Disable68kInterrupts();
        !           429:        
        !           430:        currElemPtr = (QElemPtr)qHeader->qHead;
        !           431:        prevElemPtr = nil;
        !           432:        
        !           433:        // Find the one we want.
        !           434:        while ( currElemPtr && (currElemPtr != qElement) )
        !           435:        {
        !           436:                // Advance the cause.
        !           437:                prevElemPtr = currElemPtr;
        !           438:                currElemPtr = currElemPtr -> qLink;
        !           439:        }
        !           440:        
        !           441:        // We find it?
        !           442:        if ( currElemPtr )
        !           443:        {
        !           444:                // Middle of the queue somewhere?
        !           445:                if ( prevElemPtr )
        !           446:                        prevElemPtr -> qLink = currElemPtr ->qLink;
        !           447:                else
        !           448:                        qHeader->qHead = currElemPtr ->qLink;
        !           449:                
        !           450:                currElemPtr -> qLink = nil;
        !           451:        }
        !           452:        else
        !           453:                result = qErr; // not on the list.
        !           454:        
        !           455:        Restore68kInterrupts(sr);
        !           456:        return result;
        !           457: }
        !           458: 
        !           459: 
        !           460: OSErr PBDequeue(QElemPtr qElement, QHdrPtr qHeader)
        !           461: {
        !           462:        // Optimize for common case of 1 element on the queue.
        !           463:        
        !           464:        // First one on the queue?
        !           465:        while ( qHeader -> qHead == qElement )
        !           466:        {
        !           467:                // If the element is still at the head of the queue,... Remove it, and we are done.
        !           468:                if (CompareAndSwap ((UInt32) qElement,
        !           469:                                                        (UInt32) qElement -> qLink,
        !           470:                                                        (UInt32 *) &qHeader->qHead) == true)
        !           471:                {
        !           472:                        qElement -> qLink = nil;
        !           473: 
        !           474:                        return noErr;
        !           475:                }
        !           476:        }
        !           477:        
        !           478:        // Multiple elements on the queue.
        !           479:        return PBDequeueSync (qElement, qHeader);
        !           480: }
        !           481: 
        !           482: /*-------------------------------------------------------------------------------
        !           483: 
        !           484: Routine:       PBDequeueFirst  -       Remove First Element on a Queue  (@ Any Exec-lvl)
        !           485: 
        !           486: Result:                noErr or qErr
        !           487: -------------------------------------------------------------------------------*/
        !           488: 
        !           489: OSErr PBDequeueFirst(QHdrPtr qHeader, QElemPtr *theFirstqElem)
        !           490: {
        !           491:        QElemPtr qElement;
        !           492: 
        !           493:        do {
        !           494:                // Get Queue Head Ptr
        !           495:                qElement = qHeader -> qHead;
        !           496:                
        !           497:                // Empty Queue?
        !           498:                if ( qElement == nil )
        !           499:                {
        !           500:                        if ( theFirstqElem )
        !           501:                                *theFirstqElem = nil;
        !           502:                                
        !           503:                        return qErr;    
        !           504:                }
        !           505:                
        !           506:                // If the element is still at the head of the queue,... Remove it, and we are done.
        !           507:                if (CompareAndSwap ((UInt32) qElement,
        !           508:                                                        (UInt32) qElement -> qLink,
        !           509:                                                        (UInt32 *) &qHeader->qHead) == true)
        !           510:                {
        !           511:                        if ( theFirstqElem )
        !           512:                                *theFirstqElem = qElement;
        !           513:                                
        !           514:                        qElement -> qLink = nil;
        !           515: 
        !           516:                        return noErr;
        !           517:                }
        !           518:        } while (1);
        !           519: }
        !           520: 
        !           521: /*-------------------------------------------------------------------------------
        !           522: 
        !           523: Routine:       PBDequeueLast   -       Remove Last Element on a Queue  (@ Any Exec-lvl)
        !           524: 
        !           525: Result:                noErr or qErr
        !           526: -------------------------------------------------------------------------------*/
        !           527: 
        !           528: OSErr PBDequeueLast(QHdrPtr qHeader, QElemPtr *theLastqElem)
        !           529: {
        !           530:        QElemPtr currElemPtr, prevElemPtr;
        !           531:        OSErr   result = noErr;
        !           532:        UInt16 sr;
        !           533:        
        !           534:        if ( theLastqElem )
        !           535:                *theLastqElem = nil;
        !           536:                
        !           537:        sr = Disable68kInterrupts();
        !           538: 
        !           539:        // Get Queue Head Ptr and our initial previous ptr
        !           540:        if ((prevElemPtr = qHeader -> qHead) == nil)
        !           541:                result = qErr; // q is empty
        !           542:        else
        !           543:        {
        !           544:                // Get head of queue
        !           545:                currElemPtr     = (QElemPtr)qHeader->qHead;
        !           546:                
        !           547:                // Move toward the end of the queue,...
        !           548:                while ( currElemPtr -> qLink != nil )
        !           549:                {       
        !           550:                        prevElemPtr     = currElemPtr;
        !           551:                        currElemPtr     = currElemPtr ->qLink;
        !           552:                }
        !           553:        
        !           554:                // Remove last one from the queue.
        !           555:                prevElemPtr->qLink = nil;
        !           556:                
        !           557:                // If last was also the first, nil out qheader.
        !           558:                if ( currElemPtr == qHeader -> qHead )
        !           559:                        qHeader -> qHead = nil;
        !           560:        
        !           561:                // Return last element to caller.
        !           562:                if ( theLastqElem )
        !           563:                        *theLastqElem = currElemPtr;
        !           564:        }
        !           565:        
        !           566:        Restore68kInterrupts(sr);
        !           567:        return result;
        !           568: }
        !           569: 
        !           570: /////////////////////////////////////////////////////////////////////////////////
        !           571: //
        !           572: //     Strings
        !           573: //
        !           574: //
        !           575: 
        !           576: /*-------------------------------------------------------------------------------
        !           577: 
        !           578: Routine:       CStrCopy        -       Copy string of chars from src to dst.
        !           579: 
        !           580: Function:      Copies characters upto and including the null character from 'src' to
        !           581:                        'dst' char strings.
        !           582: 
        !           583: Note:          This routine assumes the two strings do not overlap. It would be bad.
        !           584:                        
        !           585: Input:         src             - pointer to the source string of char's to copy.
        !           586: 
        !           587: Output:                dst             - pointer to the destination string of char's.
        !           588:                        
        !           589: Result:                dst             - a pointer to the destination string is returned.
        !           590: -------------------------------------------------------------------------------*/
        !           591: 
        !           592: char   *CStrCopy       (char *dst,     const char      *src)
        !           593: {
        !           594:        char    *pos = dst;
        !           595:        
        !           596:        while ( (*pos++ = *src++) != 0)                         // copy src to dst
        !           597:                ;
        !           598:                
        !           599:        return dst;
        !           600: }
        !           601: 
        !           602: 
        !           603: /*-------------------------------------------------------------------------------
        !           604: 
        !           605: Routine:       PStrCopy        -       Copy string of chars from src to dst.
        !           606: 
        !           607: Function:      Copies characters upto and including the null character from 'src' to
        !           608:                        'dst' char strings.
        !           609: 
        !           610: Note:          This routine assumes the two strings do not overlap. It would be bad.
        !           611:                        
        !           612: Input:         src             - pointer to the source string of char's to copy.
        !           613: 
        !           614: Output:                dst             - pointer to the destination string of char's.
        !           615:                        
        !           616: Result:                dst             - a pointer to the destination string is returned.
        !           617: -------------------------------------------------------------------------------*/
        !           618: 
        !           619: StringPtr      PStrCopy        (StringPtr dst, ConstStr255Param src)
        !           620: {
        !           621:        UInt8     len;
        !           622:        char     *s,*d;
        !           623:        
        !           624:        s               = (char *)src;
        !           625:        d               = (char *)dst;
        !           626:        len             = *src;
        !           627:        
        !           628:        *d++ = *s++;
        !           629:        while (len-- != 0)
        !           630:                *d++ = *s++;
        !           631:        
        !           632:        return dst;
        !           633: }
        !           634: 
        !           635: 
        !           636: /*-------------------------------------------------------------------------------
        !           637: 
        !           638: Routine:       CStrNCopy       -       Copy at most n characters.
        !           639: 
        !           640: Function:      Copies upto 'max' characters from 'src' to 'dst' char strings.
        !           641:                        If 'src' string is shorter than 'max', the 'dst string will be
        !           642:                        padded with null characters. If 'src' string is longer than 'max'
        !           643:                        the 'dst' string will NOT be null terminated.
        !           644:                        
        !           645:                        See ANSI X3.159-1989 p.106 - "strncpy"
        !           646: 
        !           647: 
        !           648: Input:         src             - pointer to the source string of char's to copy.
        !           649:                        max             - maximum number of characters to copy.
        !           650:                        
        !           651: 
        !           652: Output:                dst             - pointer to the destination string of char's.
        !           653:                        
        !           654: Result:                dst             - a pointer to the destination string is returned.
        !           655: -------------------------------------------------------------------------------*/
        !           656: 
        !           657: char   *CStrNCopy      (char *dst,     const char      *src,   UInt32  max)
        !           658: {
        !           659:        char    *pos = dst;
        !           660:        
        !           661:        max++;                                                                  // bump up max so we can predecrement in tests
        !           662:        do {                                                                    // copy upto max chars to dst
        !           663:                if (--max == 0)         return dst;             // exit if we've copied max chars
        !           664:        } while ( (*pos++ = *src++) != 0);                              // copy char & test
        !           665: 
        !           666:        while ( --max ) *pos++ = 0;                             // pad remainder of string with nulls
        !           667:                                                                                        // unless we have already reached max.
        !           668:        return dst;
        !           669: }
        !           670: 
        !           671: 
        !           672: 
        !           673: /*-------------------------------------------------------------------------------
        !           674: 
        !           675: Routine:       PStrNCopy       -       Copy string of chars from src to dst.
        !           676: 
        !           677: Function:      Copies max characters from 'src' to 'dst' char strings.
        !           678: 
        !           679: Input:         src             - pointer to the source string of char's to copy.
        !           680: 
        !           681: Output:                dst             - pointer to the destination string of char's.
        !           682:                        
        !           683: Result:                dst             - a pointer to the destination string is returned.
        !           684: -------------------------------------------------------------------------------*/
        !           685: 
        !           686: StringPtr      PStrNCopy       (StringPtr dst, ConstStr255Param src, UInt32    max)
        !           687: {
        !           688:        UInt8   len;
        !           689:        char    *s,*d;
        !           690:        char    count = 0;
        !           691:        
        !           692:        s               = (char *)src;
        !           693:        d               = (char *)dst;
        !           694:        len             = *s;
        !           695:        
        !           696:        do {                                                    
        !           697:                if ( (max-- == 0) || (len-- == 0))
        !           698:                        break;                          
        !           699: 
        !           700:                *++d = *++s;
        !           701:                count += 1;
        !           702: 
        !           703:        } while ( 1 );
        !           704:        
        !           705:        if ( count )
        !           706:                *dst = count;
        !           707:                
        !           708:        return dst;
        !           709: }
        !           710: 
        !           711: 
        !           712: /*-------------------------------------------------------------------------------
        !           713: 
        !           714: Routine:       CStrCat -       Append 'src' char string onto 'dst'.
        !           715: 
        !           716: Function:      Appends characters from 'src' to 'dst' char strings.
        !           717:                        The initial character of 'src' overwrites the null character at
        !           718:                        the end of 'dst'. A terminating null character is ALWAYS appended.
        !           719:                        
        !           720: 
        !           721: Input:         src             - pointer to the source string of char's to append.
        !           722: 
        !           723: Output:                dst             - pointer to the destination string of char's.
        !           724:                        
        !           725:                        
        !           726: Result:                dst             - a pointer to the destination string is returned.
        !           727: -------------------------------------------------------------------------------*/
        !           728: 
        !           729: char   *CStrCat        (char *dst,     const char *src)
        !           730: {
        !           731:        char    *pos = dst;
        !           732:        
        !           733:        while ( *pos++ )                                                // find the end of dst string
        !           734:                ;
        !           735:                
        !           736:        --pos;                                                                  // backup to point to null word
        !           737: 
        !           738:        while ( (*pos++ = *src++) != 0)                 // copy src to dst      
        !           739:                ;
        !           740:                
        !           741:        return dst;
        !           742: }
        !           743: 
        !           744: 
        !           745: 
        !           746: 
        !           747: /*-------------------------------------------------------------------------------
        !           748: 
        !           749: Routine:       PStrCat -       Append 'src' char string onto 'dst'.
        !           750: 
        !           751: Function:      Appends characters from 'src' to 'dst' char strings.                    
        !           752: 
        !           753: Input:         src             - pointer to the source string of char's to append.
        !           754: 
        !           755: Output:                dst             - pointer to the destination string of char's.
        !           756:                        
        !           757:                        
        !           758: Result:                dst             - a pointer to the destination string is returned.
        !           759: -------------------------------------------------------------------------------*/
        !           760: 
        !           761: StringPtr PStrCat      (StringPtr dst, ConstStr255Param src)
        !           762: {
        !           763:        UInt8   *pos = (UInt8 *)dst;
        !           764:        UInt8   *d       = (UInt8 *)dst;
        !           765:        UInt8   *s       = (UInt8 *)src;
        !           766:        UInt8   len  = *s++;
        !           767:        UInt8   dlen  = *d;
        !           768: 
        !           769: 
        !           770:        if (((UInt32)len + (UInt32)dlen) > (UInt32)255)
        !           771:        {
        !           772:                len = 255 - dlen;
        !           773:        }
        !           774:        pos += (*pos) + 1;                                              // pos at end of string.
        !           775:        
        !           776:        while ( len-- != 0 )
        !           777:        {
        !           778:                *pos++ = *s++;                                          // car src to dst       
        !           779:                (*d) += 1;                                                      // dump new string length
        !           780:        }
        !           781:        
        !           782:        return dst;
        !           783: }
        !           784: 
        !           785: 
        !           786: 
        !           787: /*-------------------------------------------------------------------------------
        !           788: 
        !           789: Routine:       CStrNCat        -       Append at most n characters.
        !           790: 
        !           791: Function:      Appends upto 'max' characters from 'src' to 'dst' char strings.
        !           792:                        The initial character of 'src' overwrites the null character at
        !           793:                        the end of 'dst'. A terminating null character is ALWAYS appended.
        !           794:                        Thus, the maximum length of 'dst' could be CStrLen(dst)+max+1.
        !           795:                        
        !           796:                        See ANSI X3.159-1989 p.164 - "strncat"
        !           797: 
        !           798: 
        !           799: Input:         src             - pointer to the source string of char's to append.
        !           800:                        max             - maximum number of characters to append.
        !           801:                        
        !           802: 
        !           803: Output:                dst             - pointer to the destination string of char's.
        !           804:                        
        !           805:                        
        !           806: Result:                dst             - a pointer to the destination string is returned.
        !           807: -------------------------------------------------------------------------------*/
        !           808: 
        !           809: char   *CStrNCat       (char *dst,     const char *src,        UInt32  max)
        !           810: {
        !           811:        char    *pos = dst;
        !           812:        
        !           813:        while ( *pos++ )                                                // find the end of dst string
        !           814:                ;
        !           815:                
        !           816:        --pos;                                                                  // backup to point to null char
        !           817:        ++max;                                                                  // bump up max so we can predecrement test
        !           818:        while ( --max && ( (*pos++ = *src++) != 0))     // append upto max chars to dst
        !           819:                ;
        !           820:                
        !           821:        if (max == 0)                                                   // if we reached max chars
        !           822:                *pos = 0;                                                       // append null character
        !           823:                
        !           824:        return dst;
        !           825: }
        !           826: 
        !           827: 
        !           828: 
        !           829: /*-------------------------------------------------------------------------------
        !           830: 
        !           831: Routine:       PStrNCat        -       Append 'src' char string onto 'dst'.
        !           832: 
        !           833: Function:      Appends characters from 'src' to 'dst' char strings.                    
        !           834: 
        !           835: Input:         src             - pointer to the source string of char's to append.
        !           836: 
        !           837: Output:                dst             - pointer to the destination string of char's.
        !           838:                        
        !           839:                        
        !           840: Result:                dst             - a pointer to the destination string is returned.
        !           841: -------------------------------------------------------------------------------*/
        !           842: 
        !           843: StringPtr PStrNCat     (StringPtr dst, ConstStr255Param src, UInt32    max)
        !           844: {
        !           845:        UInt8   *pos = (UInt8 *)dst;
        !           846:        UInt8   *d       = (UInt8 *)dst;
        !           847:        UInt8   *s       = (UInt8 *)src;
        !           848:        UInt8   len  = *s++;
        !           849:        
        !           850: 
        !           851:        len = (((UInt32)*src + (UInt32)*dst) < (UInt32)255) ? (UInt32)*src : (UInt32)255 - (UInt32)*dst;
        !           852:        
        !           853:        pos += (*pos) + 1;                                              // pos at end of string.
        !           854: 
        !           855:        while ( (max-- != 0) && (len-- != 0) )
        !           856:        {
        !           857:                *pos++ = *s++;                                          // car src to dst       
        !           858:                (*d) += 1;                                                      // dump new string length
        !           859:        }
        !           860:        
        !           861:        return dst;
        !           862: }
        !           863: 
        !           864: 
        !           865: /*-------------------------------------------------------------------------------
        !           866: 
        !           867: Routine:       PStrToCStr      -       convert Pascal string 'src' to char string 'dst'.
        !           868: 
        !           869: Function:      Converts 1 byte Pascal string chars to 2 byte char string by prefixing
        !           870:                        the ASCII byte with 0x00. The char string is terminated with a 2 byte
        !           871:                        null character, 0x0000.
        !           872:                        
        !           873: 
        !           874: Input:         src             - pointer to the Pascal source string.
        !           875: 
        !           876: Output:                dst             - pointer to the destination string of char's.
        !           877: -------------------------------------------------------------------------------*/
        !           878: 
        !           879: void   PStrToCStr      (char   *dst,   ConstStr255Param src)
        !           880: {
        !           881:        unsigned char   len;
        !           882:        
        !           883:        len = 1 + *src++;                                                       // add 1 so we can predecrement
        !           884:        while (--len)                                                           // for each char in src...
        !           885:        {
        !           886:                *dst++ = (char) *src++;                                 // cast & copy chars
        !           887:        }
        !           888:        
        !           889:        *dst = 0;                                                                       // append null char
        !           890: }
        !           891: 
        !           892: 
        !           893: 
        !           894: /*-------------------------------------------------------------------------------
        !           895: 
        !           896: Routine:       CStrToPStr      -       convert char string 'src' to Pascal string 'dst'.
        !           897: 
        !           898: Function:      Converts 2 byte char string chars to 1 byte Pascal string by lopping
        !           899:                        off the high byte. This is NOT considered sound foreign policy, and we
        !           900:                        will have to accomodate our international brethren lest they be displeased
        !           901:                        with us. But, it is useful for development and debugging.
        !           902:                        
        !           903: 
        !           904: Input:         src             - pointer to the char source string.
        !           905: 
        !           906: Output:                dst             - pointer to the Pascal destination string.
        !           907: -------------------------------------------------------------------------------*/
        !           908: 
        !           909: void   CStrToPStr      (Str255         dst,    const char      *src)
        !           910: {
        !           911:        UInt32                   len    = 0;
        !           912:        const char      *s2     = src;
        !           913:        
        !           914:        while (*src++)                                                  // how long is it?
        !           915:                ++len;
        !           916:        
        !           917:        if (len > 255)  len = 255;                              // truncate to 255 chars
        !           918:        
        !           919:        *dst++ = (unsigned char) len++;                 // stuff length byte &
        !           920:                                                                                        // increment so we can predecrement
        !           921:        while (--len)
        !           922:                *dst++ = *s2++;                                         // copy len chars
        !           923: }
        !           924: 
        !           925: 
        !           926: 
        !           927: /////////////////////////////// Compare Routines ////////////////////////////////
        !           928: 
        !           929: 
        !           930: /*-------------------------------------------------------------------------------
        !           931: 
        !           932: Routine:       CStrCmp -       Compare two char strings.
        !           933: 
        !           934: Function:      Compares the char strings s1 and s2 by comparing the values of
        !           935:                        corresponding characters in each string. It does NOT take into
        !           936:                        consideration case, diacriticals, or other localization requirements.
        !           937: 
        !           938: 
        !           939: Input:         s1              - pointer to char string.
        !           940:                        s2              - pointer to char string.
        !           941: 
        !           942:                        
        !           943: Result:                -1              - s1 < s2
        !           944:                         0              - s1 = s2
        !           945:                         1              - s1 > s2
        !           946: -------------------------------------------------------------------------------*/
        !           947: 
        !           948: short  CStrCmp (const char *s1,        const char      *s2)
        !           949: {
        !           950:        char            chr;
        !           951:        
        !           952:        while ( (chr = *s1++) != 0)
        !           953:        { 
        !           954:                if ( *s2++ != chr )
        !           955:                {
        !           956:                        if ( chr < *--s2 )
        !           957:                                return -1;
        !           958:                        return 1;
        !           959:                }
        !           960:        }
        !           961:                                                // here chr==0 and s2 has not advanced
        !           962:        if(*s2 == 0)
        !           963:                return 0;
        !           964:        return -1;
        !           965: }
        !           966: 
        !           967: 
        !           968: 
        !           969: /*-------------------------------------------------------------------------------
        !           970: 
        !           971: Routine:       PStrCmp -       Compare two char strings.
        !           972: 
        !           973: Function:      Compares the char strings s1 and s2 by comparing the values of
        !           974:                        corresponding characters in each string. It does NOT take into
        !           975:                        consideration case, diacriticals, or other localization requirements.
        !           976: 
        !           977: 
        !           978: Input:         s1              - pointer to Pascal string.
        !           979:                        s2              - pointer to Pascal string.
        !           980: 
        !           981:                        
        !           982: Result:                -1              - s1 < s2
        !           983:                         0              - s1 = s2
        !           984:                         1              - s1 > s2
        !           985: -------------------------------------------------------------------------------*/
        !           986: 
        !           987: short  PStrCmp (ConstStr255Param str1, ConstStr255Param str2)
        !           988: {
        !           989:        UInt8           s1len,s2len;
        !           990:        char            chr, *s1, *s2;
        !           991:        
        !           992:        s1              = (char *)str1;
        !           993:        s2              = (char *)str2;
        !           994:        s1len   = *s1++;
        !           995:        s2len   = *s2++;
        !           996:        
        !           997:        while (s1len && s2len)
        !           998:        { 
        !           999:                s1len--; s2len--;
        !          1000:                chr = *s1++;
        !          1001:                if ( *s2++ != chr )
        !          1002:                {
        !          1003:                        if ( chr < *--s2 )
        !          1004:                                return -1;
        !          1005:                        return 1;
        !          1006:                }
        !          1007:        }
        !          1008:                                                
        !          1009:        if((s2len == 0) && (s1len == 0))
        !          1010:                return 0;
        !          1011: 
        !          1012:        if(s1len)
        !          1013:                return 1;
        !          1014:        return -1;
        !          1015: }
        !          1016: 
        !          1017: 
        !          1018: 
        !          1019: /*-------------------------------------------------------------------------------
        !          1020: 
        !          1021: Routine:       CStrNCmp        -       Compare the first N characters of two char strings.
        !          1022: 
        !          1023: Function:      Compares the first N char strings s1 and s2 by comparing the values
        !          1024:                        of corresponding characters in each string. It does NOT take into
        !          1025:                        consideration case, diacriticals, or other localization requirements.
        !          1026: 
        !          1027: 
        !          1028: Input:         s1              - pointer to char string.
        !          1029:                        s2              - pointer to char string.
        !          1030:                        max             - the number of characters to compare.
        !          1031: 
        !          1032:                        
        !          1033: Result:                -1              - s1 < s2
        !          1034:                         0              - s1 = s2
        !          1035:                         1              - s1 > s3
        !          1036: -------------------------------------------------------------------------------*/
        !          1037: 
        !          1038: short  CStrNCmp        (const char *s1,        const char      *s2,    UInt32  max)
        !          1039: {
        !          1040:        register char c1, c2;           /* s1[] may be shorter s2[] or
        !          1041:                                                                                  their length may be equal */
        !          1042: 
        !          1043:        while (max--)
        !          1044:        { 
        !          1045:                c1 = *s1++;
        !          1046:                c2 = *s2++;
        !          1047: 
        !          1048:                if ( c1 != c2 )
        !          1049:                {       
        !          1050:                        if ( c1 < c2 )  return -1;
        !          1051:                        else                    return  1;
        !          1052:                }
        !          1053: 
        !          1054:                if(c1 == 0)             return  0;
        !          1055:        }
        !          1056:        
        !          1057:        return  0;
        !          1058: }
        !          1059: 
        !          1060: 
        !          1061: 
        !          1062: /*-------------------------------------------------------------------------------
        !          1063: 
        !          1064: Routine:       PStrNCmp        -       Compare two char strings.
        !          1065: 
        !          1066: Function:      Compare the first N characters of two char strings.
        !          1067: 
        !          1068: 
        !          1069: Input:         s1              - pointer to Pascal string.
        !          1070:                        s2              - pointer to Pascal string.
        !          1071:                        max             - N chars to compare
        !          1072: 
        !          1073:                        
        !          1074: Result:                -1              - s1 < s2
        !          1075:                         0              - s1 = s2
        !          1076:                         1              - s1 > s2
        !          1077: -------------------------------------------------------------------------------*/
        !          1078: 
        !          1079: short  PStrNCmp        (ConstStr255Param str1, ConstStr255Param str2, UInt32   max)
        !          1080: {
        !          1081:        char c1, c2;            
        !          1082:        UInt8 l1, l2;
        !          1083:        char *s1,*s2;
        !          1084: 
        !          1085:        l1 = str1[0]; s1 = (char *)str1; s1++;
        !          1086:        l2 = str2[0]; s2 = (char *)str2; s2++;
        !          1087:        
        !          1088:        if ((l1 == 0) && (l2 == 0))
        !          1089:                return  0;
        !          1090:                
        !          1091:        while (max && l1 && l2)
        !          1092:        { 
        !          1093:                max--; l1--; l2--;
        !          1094:                c1 = *s1++;
        !          1095:                c2 = *s2++;
        !          1096: 
        !          1097:                if ( c1 != c2 )
        !          1098:                {       
        !          1099:                        if ( c1 < c2 )  return -1;
        !          1100:                        else                    return  1;
        !          1101:                }
        !          1102:        }
        !          1103:        
        !          1104:        if ((max == 0) || ((l1 == 0) && (l2 == 0)))
        !          1105:                return  0;
        !          1106:                
        !          1107:        if (l1)
        !          1108:                return 1;
        !          1109:        return -1;
        !          1110: }
        !          1111: 
        !          1112: 
        !          1113: /*-------------------------------------------------------------------------------
        !          1114: 
        !          1115: Routine:       CStrLen -       returns length of char string in characters.
        !          1116: 
        !          1117: Function:      Returns the length of char string 'src' in characters. This does
        !          1118:                        NOT include the terminating null character.
        !          1119: 
        !          1120: 
        !          1121: Input:         src             - pointer to a char string.
        !          1122:                        
        !          1123: Result:                number of characters in char string 'src'
        !          1124: 
        !          1125: -------------------------------------------------------------------------------*/
        !          1126: 
        !          1127: UInt32 CStrLen (const char     *src)
        !          1128: {
        !          1129:        UInt32 len = 0;
        !          1130:        
        !          1131:        while (*src++)
        !          1132:                ++len;
        !          1133:                
        !          1134:        return len;
        !          1135: }
        !          1136: 
        !          1137: /*-------------------------------------------------------------------------------
        !          1138: 
        !          1139: Routine:       PStrLen -       returns length of Pascal string in characters.
        !          1140: 
        !          1141: Function:      Returns the length of Pascal string 'src' in characters.
        !          1142: 
        !          1143: Input:         src             - pointer to a Pascal string.
        !          1144:                        
        !          1145: Result:                number of characters in Pascal string 'src'
        !          1146: 
        !          1147: -------------------------------------------------------------------------------*/
        !          1148: 
        !          1149: UInt32 PStrLen (ConstStr255Param src)
        !          1150: {
        !          1151:        UInt8   strlen;
        !          1152:        char    *s = (char *)src;
        !          1153:        
        !          1154:        strlen = *s;
        !          1155:        
        !          1156:        return (UInt32)strlen;
        !          1157: }
        !          1158: 
        !          1159: 
        !          1160: /////////////////////////////////////////////////////////////////////////////////
        !          1161: //
        !          1162: //     Software Interrupts
        !          1163: //
        !          1164: //
        !          1165: 
        !          1166: OSErr InitSwis (void)
        !          1167: {
        !          1168:        long    i;
        !          1169:        Swi_Information *swi;
        !          1170:        
        !          1171:        PBQueueCreate (&CreatedSwis);
        !          1172:        
        !          1173:        PBQueueCreate (&AvailableSwis);
        !          1174:        
        !          1175:        AllSwis = PoolAllocateResident( sizeof(Swi_Information) * N_SWIS, true );
        !          1176:        if ( !AllSwis )
        !          1177:                return memFullErr;
        !          1178:        
        !          1179:        swi = AllSwis;  
        !          1180:        for (i=0;i<N_SWIS;i++)
        !          1181:        {
        !          1182:                // swi->Name = 'SWI!';
        !          1183:                PBEnqueue ( &swi->Link, AvailableSwis);
        !          1184:                swi++;
        !          1185:        }
        !          1186:                
        !          1187:        return noErr;
        !          1188: }
        !          1189: 
        !          1190: /*-------------------------------------------------------------------------------
        !          1191: 
        !          1192: Routine:       CurrentTaskID   -       Returns ID of the Current Task. (@NON-Int Lvl)
        !          1193: 
        !          1194: -------------------------------------------------------------------------------*/
        !          1195: 
        !          1196: TaskID CurrentTaskID (void)
        !          1197: {
        !          1198:        if (CurrentExecutionLevel() != kTaskLevel)
        !          1199:        {
        !          1200:                // SysDebugStr ((StringPtr)"\pCurrentTaskID not called at Task Level!");
        !          1201:                return (TaskID)-1;
        !          1202:        }
        !          1203:        
        !          1204:        return (TaskID)0;
        !          1205: }
        !          1206: 
        !          1207: /*-------------------------------------------------------------------------------
        !          1208: 
        !          1209: Routine:       DelayFor        -       Block Current Task for a Duration. (@NON-Int Lvl)
        !          1210: 
        !          1211: -------------------------------------------------------------------------------*/
        !          1212: /*naga
        !          1213: OSStatus DelayFor ( Duration expirationTime )
        !          1214: {
        !          1215:        AbsoluteTime    abt;
        !          1216:        Nanoseconds             nano;
        !          1217:        SInt64                  divisor;
        !          1218:        SInt64                  remainder;
        !          1219:        SInt64                  numTicks;
        !          1220:        unsigned long   finalTicks;
        !          1221:        
        !          1222:        if (CurrentExecutionLevel() != kTaskLevel)
        !          1223:        {
        !          1224:                // SysDebugStr ((StringPtr)"\pDelayFor not called at Task Level!");
        !          1225:                return -1;
        !          1226:        }
        !          1227:        
        !          1228:        abt             = DurationToAbsolute    ( expirationTime );
        !          1229:        nano    = AbsoluteToNanoseconds ( abt );
        !          1230:        
        !          1231:        divisor.hi = 0;
        !          1232:        divisor.lo = 16666666;
        !          1233: 
        !          1234:        numTicks = S64Divide( *(SInt64*)(&nano), divisor, &remainder );
        !          1235:        
        !          1236:        Delay ( numTicks.lo, &finalTicks );
        !          1237:        
        !          1238:        return noErr;
        !          1239: }
        !          1240: naga */
        !          1241: #if 0   //naga
        !          1242: /*-------------------------------------------------------------------------------
        !          1243: 
        !          1244: Routine:       DelayForHardware        -       Delay for an AbsoluteTime. (Int Lvl)
        !          1245: 
        !          1246: -------------------------------------------------------------------------------*/
        !          1247: 
        !          1248: OSStatus DelayForHardware ( AbsoluteTime absoluteTime )
        !          1249: {
        !          1250:        // Obtain the NanoKernel's private pointer to the ProcessorInfo structure.
        !          1251:        // This pointer is contained in the location defined by the private enum
        !          1252:        // 'ProcessorInfoPtr'
        !          1253:        NKProcessorInfo *processorInfo = *((NKProcessorInfo **) nkProcessorInfoPtr);
        !          1254: 
        !          1255:        if (gDelayForHdwrProc == nil)
        !          1256:        {
        !          1257:                
        !          1258:                // First Time Initialization
        !          1259:                
        !          1260:                if ((processorInfo->ProcessorVersionReg >> 16) == 0x0001)
        !          1261:                {
        !          1262:                        // PowerPC 601 Chip (Use RTC, not TimeBase)
        !          1263:                        
        !          1264:                        gDelayForHdwrProc = DelayForHardware601;
        !          1265:                }
        !          1266:                else
        !          1267:                {
        !          1268:                        // Non-PowerPC 601 (Use TimeBase, not RTC)
        !          1269:                        
        !          1270:                        gDelayForHdwrProc = DelayForHardwarePPC;
        !          1271:                }
        !          1272:        }
        !          1273:        
        !          1274:        return gDelayForHdwrProc(absoluteTime);
        !          1275: }
        !          1276: #endif
        !          1277: /*-------------------------------------------------------------------------------
        !          1278: 
        !          1279: Routine:       CreateSoftwareInterrupt -       Makes a SWI. (@any exec-Lvl)
        !          1280: 
        !          1281: -------------------------------------------------------------------------------*/
        !          1282: 
        !          1283: OSStatus CreateSoftwareInterrupt       (       SoftwareInterruptHandler        theHandler,
        !          1284:                                                                                TaskID                                          theTask,
        !          1285:                                                                                void                    *                       theParameter,
        !          1286:                                                                                Boolean                                         persistent,
        !          1287:                                                                                SoftwareInterruptID *           theSoftwareInterrupt)
        !          1288: {
        !          1289:        Swi_Info        aSwi;
        !          1290:        
        !          1291:        if ( PBDequeueFirst (AvailableSwis, (QElemPtr *)&aSwi) != noErr )
        !          1292:                return paramErr;
        !          1293:                
        !          1294:        aSwi -> Handler         = theHandler;
        !          1295:        aSwi -> The_Id          = (SoftwareInterruptID)aSwi;
        !          1296:        aSwi -> The_Task        = theTask;
        !          1297:        aSwi -> Temporary       = !persistent;
        !          1298:        aSwi -> Sent            = false;
        !          1299:        aSwi -> P1                      = (void *)theParameter;
        !          1300:        
        !          1301:        if (theSoftwareInterrupt != nil)
        !          1302:                *theSoftwareInterrupt = (SoftwareInterruptID)aSwi;
        !          1303:                
        !          1304:        PBEnqueue ( &aSwi->Link, CreatedSwis);
        !          1305:        
        !          1306:        return noErr;
        !          1307: }
        !          1308: 
        !          1309: 
        !          1310: /*-------------------------------------------------------------------------------
        !          1311: 
        !          1312: Routine:       SendSoftwareInterrupt   -       Runs a SWI. (@any exec-Lvl)
        !          1313: 
        !          1314: -------------------------------------------------------------------------------*/
        !          1315: 
        !          1316: OSStatus SendSoftwareInterrupt         (       SoftwareInterruptID                     theSoftwareInterrupt,
        !          1317:                                                                                void                    *                       theParameter)
        !          1318: {
        !          1319:        Swi_Info        aSwi;
        !          1320:        SoftwareInterruptHandler handler;
        !          1321:        Boolean         temp;
        !          1322:        void            *p1;
        !          1323:        OSErr           Result = PBDequeue ( (QElemPtr)theSoftwareInterrupt, CreatedSwis);
        !          1324:        
        !          1325:        if (Result != noErr)
        !          1326:                return (OSStatus)Result;
        !          1327:                
        !          1328:        aSwi = (Swi_Info)theSoftwareInterrupt;
        !          1329:        
        !          1330:        // Store away swi info in locals.
        !          1331:        handler = aSwi -> Handler;
        !          1332:        p1              = aSwi -> P1;
        !          1333:        temp    = aSwi -> Temporary;
        !          1334:        
        !          1335:        // Return temp swis now.
        !          1336:        if ( temp )
        !          1337:                PBEnqueue ( &aSwi->Link, AvailableSwis );
        !          1338:                
        !          1339:        // Call the handler
        !          1340:        (*handler) (p1, (void *)theParameter);
        !          1341:        
        !          1342:        // Return persistant swis later.
        !          1343:        if ( !temp )
        !          1344:                PBEnqueue ( &aSwi->Link, CreatedSwis );
        !          1345:                
        !          1346:        return noErr;
        !          1347: }
        !          1348: 
        !          1349: /*-------------------------------------------------------------------------------
        !          1350: 
        !          1351: Routine:       DeleteSoftwareInterrupt -       Destroys a SWI. (@any exec-Lvl)
        !          1352: 
        !          1353: -------------------------------------------------------------------------------*/
        !          1354: 
        !          1355: OSStatus DeleteSoftwareInterrupt       ( SoftwareInterruptID theSoftwareInterrupt )
        !          1356: {
        !          1357:        Swi_Info        aSwi;
        !          1358:        OSErr           Result = PBDequeue ( (QElemPtr)theSoftwareInterrupt, CreatedSwis);
        !          1359: 
        !          1360:        if (Result != noErr)
        !          1361:                return (OSStatus)Result;
        !          1362:                
        !          1363:        aSwi = (Swi_Info)theSoftwareInterrupt;
        !          1364:        
        !          1365:        PBEnqueue ( &aSwi->Link, AvailableSwis );
        !          1366:        
        !          1367:        return noErr;
        !          1368: }
        !          1369: 
        !          1370: 

unix.superglobalmegacorp.com

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