Annotation of kernel/bsd/dev/ppc/drvAppleMesh_SCSI/MESH_DBDMA.h, 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: /**
        !            27:  * Copyright (c) 1994-1996 NeXT Software, Inc.  All rights reserved.
        !            28:  * Copyright � 1997 Apple Computer Inc. All Rights Reserved.
        !            29:  * @author   Martin Minow   mailto:[email protected]
        !            30:  * @revision    1997.02.13  Initial conversion from AMDPCSCSIDriver sources.
        !            31:  *
        !            32:  * Set tabs every 4 characters.
        !            33:  *
        !            34:  * Edit History
        !            35:  * 1997.02.13   MM      Initial conversion from AMDPCSCSIDriver sources.
        !            36:  */
        !            37: 
        !            38: 
        !            39: #define AUTO_SENSE_ENABLE    1
        !            40: 
        !            41:     /* These are accessible by SCSIInspector:   */
        !            42: 
        !            43: #define SYNC_ENABLE         "Synchronous"
        !            44: #define FAST_ENABLE         "Fast SCSI"
        !            45: #define CMD_QUEUE_ENABLE    "Cmd Queueing"
        !            46: 
        !            47:     /* These are only accessible by Configure's Expert mode:    */
        !            48: 
        !            49: #define EXTENDED_TIMING     "Extended Timing"
        !            50: #define SCSI_CLOCK_RATE     "SCSI Clock Rate"   /* in MHz */
        !            51: 
        !            52: 
        !            53: #define USE_ELG FALSE
        !            54: #define CustomMiniMon FALSE
        !            55: //#define CustomMiniMon TRUE
        !            56: //#define USE_ELG   TRUE
        !            57: #define kEvLogSize  (4096*16)   // 16 pages = 64K = 4096 events
        !            58: 
        !            59: #if USE_ELG /* (( */
        !            60: #define ELG(A,B,ASCI,STRING)    EvLog( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING )
        !            61: #define PAUSE(A,B,ASCI,STRING)  Pause( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING )
        !            62: #else /* ) not USE_ELG: (   */
        !            63: #define ELG(A,B,ASCI,S)
        !            64: #define PAUSE(A,B,ASCI,S)
        !            65: #define CKSTOP(A,E,ASCI,S)
        !            66: #endif /* USE_ELG )) */
        !            67: 
        !            68: #define TIMESTAMP_AT_IOCOMPLETE     0
        !            69: 
        !            70: #ifndef TIMESTAMP_AT_IOCOMPLETE
        !            71: #define TIMESTAMP_AT_IOCOMPLETE     0
        !            72: #endif
        !            73: 
        !            74: 
        !            75: #ifndef TIMESTAMP
        !            76: #define TIMESTAMP  0    // mlj - linking problems with Curio
        !            77: #endif
        !            78: 
        !            79:     /* These types will ultimately be moved to an implementation-wide header file*/
        !            80: #ifndef __APPLE_TYPES_DEFINED__
        !            81: #define __APPLE_TYPES_DEFINED__ 1
        !            82:     typedef unsigned char   UInt8;              /* An unsigned 8-bit value  */
        !            83:     typedef unsigned int    UInt32;             /* An unsigned integer      */
        !            84:     typedef signed int      SInt32;             /* An explicitly signed int */
        !            85:     typedef void            *LogicalAddress;    /* A virtual address        */
        !            86:     typedef UInt32          PhysicalAddress;    /* A hardware address       */
        !            87:     typedef UInt32          ByteCount;          /* A transfer length count  */
        !            88:     typedef UInt32          ItemCount;          /* An index or counter      */
        !            89:     typedef UInt32          Boolean;            /* A true/false value       */
        !            90: #ifndef TRUE
        !            91: #define TRUE    1
        !            92: #define FALSE   0
        !            93: #endif
        !            94: #endif /* __APPLE_TYPES_DEFINED__ */
        !            95:     typedef signed char     SInt8;
        !            96:     typedef UInt32          OSType;
        !            97: 
        !            98: #ifndef SynchronizeIO
        !            99: #define SynchronizeIO()     eieio()     /* TEMP */
        !           100: #endif /* SynchronizeIO */
        !           101: 
        !           102: 
        !           103:     enum
        !           104:     {   DBDMA_ReadStartAlignment    = 8,    // mlj ???
        !           105:         DBDMA_WriteStartAlignment   = 8
        !           106:     };
        !           107: 
        !           108:         /* Operation flags and options: */
        !           109: 
        !           110:     typedef enum BusPhase   /* These are the real SCSI bus phases (from busStatus0):   */
        !           111:     {
        !           112:         kBusPhaseDATO   = 0,
        !           113:         kBusPhaseDATI,
        !           114:         kBusPhaseCMD,
        !           115:         kBusPhaseSTS,
        !           116:         kBusPhaseReserved1,
        !           117:         kBusPhaseReserved2,
        !           118:         kBusPhaseMSGO,
        !           119:         kBusPhaseMSGI,
        !           120:         kBusPhaseBusFree
        !           121:     } BusPhase;
        !           122: 
        !           123:         /* Command to be executed by IO thread.                     */
        !           124:         /* These are ultimately derived from ioctl control values.  */
        !           125: 
        !           126:     typedef enum
        !           127:     {   kCommandExecute,            /* Execute IOSCSIRequest    */
        !           128:         kCommandResetBus,           /* Reset bus                */
        !           129:         kCommandAbortRequest        /* Abort IO thread          */
        !           130:     } CommandOperation;
        !           131: 
        !           132:         /* We read target messages using a simple state machine.    */
        !           133:         /* On entrance to MSGI phase, gMsgInState = kMsgInInit.     */
        !           134:         /* Continue reading messages until either                   */
        !           135:         /* gMsgInState == kMsgInReady or the target changes phase   */
        !           136:         /* (which is an error).                                     */
        !           137:     typedef enum MsgInState
        !           138:     {
        !           139:         kMsgInInit = 0,     /*  0 Not reading a message (must be zero)      */
        !           140:         kMsgInReading,      /*  1 MSG input state: reading counted data     */
        !           141:         kMsgInCounting,     /*  2 MSG input state: reading count byte       */
        !           142:         kMsgInReady         /*  3 MSG input state: a msg is now available   */
        !           143:     } MsgInState;
        !           144: 
        !           145: 
        !           146:         /* This is the maximum number of bytes to be transferred            */
        !           147:         /* in an autosense request. It is, by inspection, less than 256.    */
        !           148:     enum { kMaxAutosenseByteCount = sizeof( esense_reply_t ) };
        !           149: 
        !           150:         /* These values are stored in gCurrentTarget and gCurrentLUN    */
        !           151:         /* when there is no active request.                             */
        !           152:     enum
        !           153:     {   kInvalidTarget          = 0xFFFF,
        !           154:         kInvalidLUN             = 0xFFFF
        !           155:     };
        !           156: 
        !           157:         /* The default initiator bus ID (needs to be fetched from NVRAM).    */
        !           158:     enum { kInitiatorIDDefault = 7 };
        !           159: #define APPLE_SCSI_RESET_DELAY  250 /* Msec */
        !           160: 
        !           161:     /* Command struct passed to IO thread.                  */
        !           162:     /* One of these are created for each active IO request. */
        !           163: 
        !           164: typedef struct CommandBuffer
        !           165: {
        !           166:         /* Fields valid when commandBuf is passed to IO thread. */
        !           167:     CommandOperation    op;         /* kCommandExecute, etc.                */
        !           168: 
        !           169:         /* The following 3 fields are only valid if op == kCommandExecute.  */
        !           170:         /* They are passed into the SCSI driver by executeRequest.          */
        !           171: 
        !           172:     IOSCSIRequest       *scsiReq;   /* -> The SCSI command parameter block  */
        !           173:     IOMemoryDescriptor  *mem;       /* -> Memory to transfer, if any        */
        !           174:     vm_task_t           client;     /* == The client task (for vm mapping)  */
        !           175: 
        !           176:         /* These fields are used by the IO thread to manage the IO request: */
        !           177:         /*  cmdLock         Wait for the command to complete                */
        !           178:         /*  link            Queue link for the command, disconnect, and     */
        !           179:         /*                  pending queues.                                 */
        !           180:         /*  timeoutPort     Port for timeout messages                       */
        !           181:         /*  queueTag        SCSI tagged request if not QUEUE_TAG_NONTAGGED  */
        !           182: 
        !           183:     NXConditionLock *cmdLock;       /* client waits on this             */
        !           184:     queue_chain_t   link;           /* for enqueueing on commandQ       */
        !           185: //  port_t          timeoutPort;    /* for timeout messages             */
        !           186:     UInt8           queueTag;       /* QUEUE_TAG_NONTAGGED or queue tag */
        !           187:     UInt8           cdbLength;      /* Actual length of this command    */
        !           188: 
        !           189:         /* SCSI bus state variables. Note that currentDataIndex can exceed    */
        !           190:         /* scsiReq->maxTransfer if the device sends (receives) more data than */
        !           191:         /* we can receive (send). These values are NOT used for autosense.    */
        !           192:         /* The first byte to transfer is at logical address                   */
        !           193:         /*  gActiveCommand->buffer + currentDataIndex.                        */
        !           194: 
        !           195:     UInt32     currentDataIndex;    /* Where we are in the DATA transfer    */
        !           196:     UInt32     savedDataIndex;      /* For SaveDataPointers                 */
        !           197: 
        !           198:     IOMemoryDescriptorState savedDataState;/* saved index for IOMemoryDescriptor*/
        !           199: 
        !           200:         /* Request management flags                                         */
        !           201:         /*  flagActive                                                      */
        !           202:         /*      Set if we're in the active array and active count           */
        !           203:         /*      reflects our existance. Managed by [ self activateCmd ]     */
        !           204:         /*      and [ self deactivateCmd : cmdBuf ].                        */
        !           205:         /*      and that IOScheduleFunc() has been called.                  */
        !           206:         /*  flagRequestSelectOK                                             */
        !           207:         /*      Arbitration/selection succeeded for this request.           */
        !           208:         /*  flagIsAutosense                                                 */
        !           209:         /*      Set if we are executing an internally-generated             */
        !           210:         /*      Request Sense command. If this is an autosense,             */
        !           211:         /*      the operation is modified as follows:                       */
        !           212:         /*          Arb/Select: Disable disconnects. Re-establish           */
        !           213:         /*                      synchronous and fast for this target,       */
        !           214:         /*                      use the current tag, if any.                */
        !           215:         /*          Command:    Use an internally-generated Request Sense.  */
        !           216:         /*          Data:       Read into our wired-down sense buffer.      */
        !           217:         /*                      Do not touch the data index and transfer    */
        !           218:         /*                      count variables. On completion, copy        */
        !           219:         /*                      from our wired-down buffer to the caller's  */
        !           220:         /*                      sense array.                                */
        !           221:         /*          Completion: Good status, return SR_IOST_CHKSV to client.*/
        !           222:         /*                      Bad status: never set isAutosense. Driver   */
        !           223:         /*                      return SR_IOST_CHKSNV.                      */
        !           224: 
        !           225:     UInt32      flagActive:1,           /* We're in activeArray and activeCount */
        !           226:                 flagRequestSelectOK:1,  /* Did arbitration/selection succeed?   */
        !           227:                 flagIsAutosense:1,      /* Set if THIS is an autosense command  */
        !           228:                 pad:29;
        !           229:         /* This is set by autosense Status phase.  */
        !           230:     UInt8       autosenseStatus;    /* Did autosense complete ok?           */
        !           231:         /* Statistics support.  */
        !           232:     ns_time_t   startTime;          /* time cmd started                     */
        !           233:     ns_time_t   disconnectTime;     /* time of last disconnect              */
        !           234: 
        !           235: } CommandBuffer;
        !           236: 
        !           237:         /* Condition variable states for commandBuf.cmdLock.    */
        !           238: 
        !           239:     enum { CMD_PENDING = 0, CMD_COMPLETE };
        !           240: 
        !           241:     /* Value of queueTag for nontagged commands.                    */
        !           242:     /* This value is never used for the tag for tagged commands.    */
        !           243: 
        !           244:     enum { QUEUE_TAG_NONTAGGED  = 0 };
        !           245: 
        !           246:         /* Per-target info.                                                             */
        !           247:         /*                                                                              */
        !           248:         /* maxQueue is set to a non-zero value when we reach a target's queue size      */
        !           249:         /* limit, detected by a STAT_QUEUE_FULL status. A value of zero means we        */
        !           250:         /* have not reached the target's limit and we are free to queue additional      */
        !           251:         /* commands (if allowed by the overall cmdQueueEnable flag).                    */
        !           252:         /*                                                                              */
        !           253:         /* syncXferPeriod and syncXferOffset are set to non-zero during sync            */
        !           254:         /* transfer negotiation. Units of syncXferPeriod is NANOSECONDS, which          */
        !           255:         /* differs from both the chip's register format (dependent on clock             */
        !           256:         /* frequency and fast SCSI/fast clock enables) and the SCSI bus's format        */
        !           257:         /* (which is 4 ns per unit).                                                    */
        !           258:         /*                                                                              */
        !           259:         /* cmdQueueDisable and syncDisable have a default (initial) value of            */
        !           260:         /* zero regardless of the driver's overall cmdQueueEnable and syncModeEnable    */
        !           261:         /* flags. They are set to one when a target explicitly tells us that the        */
        !           262:         /* indicated feature is unsupported.                                            */
        !           263:         /*                                                                              */
        !           264:         /* negotiateSDTR        has one of the following values (defined in             */
        !           265:         /*                      AppleMeshDefinitions.h):                                */
        !           266:         /*          kSyncParmsAsync     Async with min period                           */
        !           267:         /*          kSyncParmsFast      Offset = 15, period = Fast (10 MB/s)            */
        !           268:         /* syncParms            Shadow of MESH syncParms register.                      */
        !           269: 
        !           270:     typedef struct
        !           271:     {
        !           272:         UInt8   maxQueue;           /* Max queue depth for this target  */
        !           273:         UInt8   negotiateSDTR;      /* Synchronous negotiation control  */
        !           274:         UInt8   syncParms;          /* Synchronous period and offset    */
        !           275:         UInt8   inquiry_7;          /* 7th byte peeked fm Inquiry data  */
        !           276:         UInt8   syncDisable;        /* No synchronous for this target   */
        !           277:     } PerTargetData;
        !           278: 
        !           279:     typedef struct MeshRegister     /* Mesh registers:  */
        !           280:     {
        !           281:         volatile UInt8      transferCount0;     UInt8   pad00[ 0x0F ];
        !           282:         volatile UInt8      transferCount1;     UInt8   pad01[ 0x0F ];
        !           283:         volatile UInt8      xFIFO;              UInt8   pad02[ 0x0F ];
        !           284:         volatile UInt8      sequence;           UInt8   pad03[ 0x0F ];
        !           285:         volatile UInt8      busStatus0;         UInt8   pad04[ 0x0F ];
        !           286:         volatile UInt8      busStatus1;         UInt8   pad05[ 0x0F ];
        !           287:         volatile UInt8      FIFOCount;          UInt8   pad06[ 0x0F ];
        !           288:         volatile UInt8      exception;          UInt8   pad07[ 0x0F ];
        !           289:         volatile UInt8      error;              UInt8   pad08[ 0x0F ];
        !           290:         volatile UInt8      interruptMask;      UInt8   pad09[ 0x0F ];
        !           291:         volatile UInt8      interrupt;          UInt8   pad10[ 0x0F ];
        !           292:         volatile UInt8      sourceID;           UInt8   pad11[ 0x0F ];
        !           293:         volatile UInt8      destinationID;      UInt8   pad12[ 0x0F ];
        !           294:         volatile UInt8      syncParms;          UInt8   pad13[ 0x0F ];
        !           295:         volatile UInt8      MESHID;             UInt8   pad14[ 0x0F ];
        !           296:         volatile UInt8      selectionTimeOut;
        !           297:     } MeshRegister;
        !           298: 
        !           299:         /* The following structure shadows the MESH chip registers: */
        !           300: 
        !           301:     typedef union MESHShadow
        !           302:     {   UInt32      longWord[ 3 ];      /* for debugging ease.                  */
        !           303:         struct
        !           304:         {   UInt8   interrupt;          /* Interrupt                            */
        !           305:             UInt8   error;              /* Error register                       */
        !           306:             UInt8   exception;          /* Exception register                   */
        !           307:             UInt8   FIFOCount;          /* FIFO count                           */
        !           308: 
        !           309:             UInt8   busStatus0;         /* Bus phase + REQ, ACK, & ATN signals  */
        !           310:             UInt8   busStatus1;         /* RST, BSY, SEL                        */
        !           311:             UInt8   interruptMask;      /* Interrupt mask for debugging         */
        !           312:             UInt8   transferCount0;     /* low  order byte of transfer count    */
        !           313: 
        !           314:             UInt8   transferCount1;     /* high order byte of transfer count    */
        !           315:             UInt8   sequence;           /* Sequence register                    */
        !           316:             UInt8   syncParms;          /* syncParms for debugging              */
        !           317:             UInt8   destinationID;      /* Target ID                            */
        !           318:         } mesh;
        !           319:     } MESHShadow;
        !           320: 
        !           321:         /* Mesh Register set offsets    */
        !           322: 
        !           323:     enum
        !           324:     {
        !           325:         kMeshTransferCount0 =   0x00,
        !           326:         kMeshTransferCount1 =   0x10,
        !           327:         kMeshFIFO           =   0x20,
        !           328:         kMeshSequence       =   0x30,
        !           329:         kMeshBusStatus0     =   0x40,
        !           330:         kMeshBusStatus1     =   0x50,
        !           331:         kMeshFIFOCount      =   0x60,
        !           332:         kMeshException      =   0x70,
        !           333:         kMeshError          =   0x80,
        !           334:         kMeshInterruptMask  =   0x90,
        !           335:         kMeshInterrupt      =   0xA0,
        !           336:         kMeshSourceID       =   0xB0,
        !           337:         kMeshDestinationID  =   0xC0,
        !           338:         kMeshSyncParms      =   0xD0,
        !           339:         kMeshMESHID         =   0xE0,
        !           340:         kMeshSelTimeOut     =   0xF0
        !           341:     };
        !           342: 
        !           343:     enum { kMeshMESHID_Value    =   0x02 };     /* Read value of kMESHID lowest 5 bits only */
        !           344: 
        !           345: 
        !           346:         /* MESH commands & modifiers for sequence register: */
        !           347: 
        !           348:     typedef enum
        !           349:     {
        !           350:         kMeshNoOpCmd            =   0x00,
        !           351: 
        !           352:         kMeshArbitrateCmd       =   0x01,
        !           353:         kMeshSelectCmd          =   0x02,
        !           354:         kMeshCommandCmd         =   0x03,
        !           355:         kMeshStatusCmd          =   0x04,
        !           356:         kMeshDataOutCmd         =   0x05,
        !           357:         kMeshDataInCmd          =   0x06,
        !           358:         kMeshMessageOutCmd      =   0x07,
        !           359:         kMeshMessageInCmd       =   0x08,
        !           360:         kMeshBusFreeCmd         =   0x09,
        !           361:             /* non interrupting:    */
        !           362:         kMeshEnableParity       =   0x0A,
        !           363:         kMeshDisableParity      =   0x0B,
        !           364:         kMeshEnableReselect     =   0x0C,
        !           365:         kMeshDisableReselect    =   0x0D,
        !           366:         kMeshResetMESH          =   0x0E,
        !           367:         kMeshFlushFIFO          =   0x0F,
        !           368:             /* Sequence command modifier bits:  */
        !           369:         kMeshSeqDMA     =   0x80,   /* Data Xfer for this command will use DMA  */
        !           370:         kMeshSeqTMode   =   0x40,   /* Target mode - unused                     */
        !           371:         kMeshSeqAtn     =   0x20    /* ATN is to be asserted after command      */
        !           372:     } MeshCommand;
        !           373: 
        !           374:         /* The bus Status Registers 0 & 1 have the actual   */
        !           375:         /* bus signals WHEN READ.                           */
        !           376: 
        !           377:     enum                        /* bus Status Register 0 bits:  */
        !           378:     {
        !           379:         kMeshIO     =   0x01,   /* phase bit    */
        !           380:         kMeshCD     =   0x02,   /* phase bit    */
        !           381:         kMeshMsg    =   0x04,   /* phase bit    */
        !           382:         kMeshAtn    =   0x08,   /* Attention signal */
        !           383:         kMeshAck    =   0x10,   /* Ack signal       */
        !           384:         kMeshReq    =   0x20,   /* Request signal   */
        !           385:         kMeshAck32  =   0x40,   /* unused - 32 bit bus  */
        !           386:         kMeshReq32  =   0x80    /* unused - 32 bit bus  */
        !           387:     };
        !           388: 
        !           389:     enum { kMeshPhaseMask   =   (kMeshMsg + kMeshCD + kMeshIO)   };
        !           390: 
        !           391:     enum                        /* bus Status Register 1 bits:  */
        !           392:     {
        !           393:         kMeshSel    =   0x20,   /* Select signal    */
        !           394:         kMeshBsy    =   0x40,   /* Busy signal      */
        !           395:         kMeshRst    =   0x80    /* Reset signal     */
        !           396:     };
        !           397: 
        !           398:     enum                                 /* Exception Register bits:   */
        !           399:     {
        !           400:         kMeshExcSelTO           =   0x01,   /* Selection timeout    */
        !           401:         kMeshExcPhaseMM         =   0x02,   /* Phase mismatch       */
        !           402:         kMeshExcArbLost         =   0x04,   /* lost arbitration     */
        !           403:         kMeshExcResel           =   0x08,   /* reselection occurred */
        !           404:         kMeshExcSelected        =   0x10,
        !           405:         kMeshExcSelectedWAtn    =   0x20
        !           406:     };
        !           407: 
        !           408:     enum                                    /* Error Register bits:     */
        !           409:     {
        !           410:         kMeshErrParity0         =   0x01,   /* parity error             */
        !           411:         kMeshErrParity1         =   0x02,   /* unused - 32 bit bus      */
        !           412:         kMeshErrParity2         =   0x04,   /* unused - 32 bit bus      */
        !           413:         kMeshErrParity3         =   0x08,   /* unused - 32 bit bus      */
        !           414:         kMeshErrSequence        =   0x10,   /* Sequence error           */
        !           415:         kMeshErrSCSIRst         =   0x20,   /* Reset signal asserted    */
        !           416:         kMeshErrDisconnected    =   0x40    /* unexpected disconnect    */
        !           417:     };
        !           418: 
        !           419:     enum                                    /* Interrupt Register bits: */
        !           420:     {
        !           421:         kMeshIntrCmdDone    =   0x01,       /* command done             */
        !           422:         kMeshIntrException  =   0x02,       /* exception occurred       */
        !           423:         kMeshIntrError      =   0x04,       /* error     occurred       */
        !           424:         kMeshIntrMask       =   (kMeshIntrCmdDone | kMeshIntrException | kMeshIntrError)
        !           425:     };
        !           426: 
        !           427: 
        !           428:     enum        /* Values for SyncParms MESH register:      */
        !           429:     {           /* 1st nibble is offset, 2nd is period.     */
        !           430:                 /* Zero offset means async.                 */
        !           431:         kSyncParmsAsync = 0x02, /* Async with min period = 2            */
        !           432:         kSyncParmsFast  = 0xF0  /* offset = 15, period = Fast (10 MB/s) */
        !           433:     };
        !           434: 
        !           435:         /* The following are specific to the MESH CCL               */
        !           436:         /* Stage Names. (These were originally 'xxxx' identifiers,  */
        !           437:         /* which is convenient for debugging, but results in many   */
        !           438:         /* warning messages from the NeXT compiler.                 */
        !           439:     enum
        !           440:     {
        !           441:         kcclStageIdle   = 0,        /*  0 - Idle    */
        !           442:         kcclStageInit,              /*  1 - 'Init'  */
        !           443:         kcclStageCCLx,              /*  2 - 'CCL~'  */
        !           444:         kcclStageArb,               /*  3 - ' Arb'  */
        !           445:         kcclStageSelA,              /*  4 - 'SelA'  */
        !           446:         kcclStageMsgO,              /*  5 - 'MsgO'  */
        !           447:         kcclStageCmdO,              /*  6 - 'CmdO'  */
        !           448:         kcclStageXfer,              /*  7 - 'Xfer'  */
        !           449:         kcclStageBucket,            /*  8 - 'Buck'  */
        !           450:         kcclStageSyncHack,          /*  9 - 'Hack'  */
        !           451:         kcclStageStat,              /*  A - ' Sta'  */
        !           452:         kcclStageMsgI,              /*  B - 'MsgI'  */
        !           453:         kcclStageFree,              /*  C - 'Free'  */
        !           454:         kcclStageGood,              /*  D - 'Good'  */
        !           455:         kcclStageStop,              /*  E - '++++'  */
        !           456:         kcclTerminatorWithoutComma
        !           457:     };
        !           458: 
        !           459:     /* offsets into the Channel Command List page:  */
        !           460: 
        !           461: #define kcclProblem     0x00    // Interrupt & Stop channel commands for anomalies
        !           462: #define kcclCMDOdata    0x20    // reserve for 6, 10, 12 byte commands
        !           463: #define kcclMSGOdata    0x30    // reserve for Identify, Tag stuff
        !           464: #define kcclMSGOLast    0x3F    // reserve for last or only msg0ut byte
        !           465: #define kcclMSGIdata    0x40    // reserve for Message In data
        !           466: #define kcclBucket      0x48    // Bit Bucket
        !           467: #define kcclStatusData  0x4F    // reserve for Status byte
        !           468: #define kcclSenseCDB    0x50    // CDB for (auto) Sense
        !           469: #define kcclBatchSize   0x60    // Current MESH batch size
        !           470: #define kcclStageLabel  0x6C    // storage for label of last stage entered.
        !           471: #define kcclSense       0x70    // Channel Commands for (Auto)Sense
        !           472: #define kcclPrototype   0xC0    // Prototype MESH 4-command Transfer sequence
        !           473: #define kcclStart       0x120   // Channel Program starts here with Arbitrate
        !           474: #define kcclBrProblem   0x140   // channel command to wait for cmdDone & Br if problem
        !           475: #define kcclMsgoStage   0x190   // Branch to single byte Message-Out
        !           476: #define kcclMsgoBranch  0x1B0   // Branch to single byte Message-Out
        !           477: #define kcclMsgoMTC     0x1D8   // MESH Transfer Count for MSGO (low order only)
        !           478: #define kcclMsgoDTC     0x1F0   // DMA  Transfer Count for MSGO (low order only)
        !           479: #define kcclLastMsgo    0x210   // Channel commands to put last/only byte of Message-Out
        !           480: #define kcclCmdoStage   0x290   // Start of Command phase
        !           481: #define kcclCmdoMTC     0x2C8   // MESH Transfer Count for CMDO (low order only)
        !           482: #define kcclCmdoDTC     0x2E0   // DMA  Transfer Count for CMDO (low order only)
        !           483: #define kcclReselect    0x2F0   // Reselect enters CCL here - Branch to xfer data
        !           484: #define kcclOverrun     0x320   // data overrun - dump the excess in the bit bucket
        !           485: #define kcclOverrunMESH 0x370   // data overrun - patch the MESH Seq Reg I/O
        !           486: #define kcclOverrunDBDMA 0x380  // data overrun - patch the DBDMA I/O
        !           487: #define kcclSyncCleanUp 0x3B0   // clean up at end of Sync xfer
        !           488: #define kcclGetStatus   0x3D0   // Finish up with Status, Message In, and Bus Free
        !           489: #define kcclMESHintr    0x4D0   // transaction done or going well
        !           490: #define kcclSenseBuffer 0x500   // Buffer for Autosense data
        !           491: #define kcclDataXfer    0x600   // INPUT or OUTPUT channel commands for data
        !           492: #define kcclSenseResult 0x63C   // Result field in Sense INPUT channel command
        !           493: 
        !           494: 
        !           495:     /* generic relocation types:    */
        !           496: 
        !           497: #define kRelNone    0x00    /* default - no relocation                      */
        !           498: #define kRelMESH    0x01    /* Relocate to MESH register area               */
        !           499: #define kRelCP      0x02    /* Relocate to Channel Program area             */
        !           500: #define kRelCPdata  0x03    /* Relocate to Channel Program data structure   */
        !           501: #define kRelPhys    0x04    /* Relocate to user Physical address space      */
        !           502: #define kRelNoSwap  0x05    /* don't relocate or swap (Label)               */
        !           503: 
        !           504:     /* Relocatable ADDRESS types:   */
        !           505: 
        !           506: #define kRelAddress         0xFF        <<8 /* relocatable address mask         */
        !           507: #define kRelAddressMESH     kRelMESH    <<8 /* MESH physical address            */
        !           508: #define kRelAddressCP       kRelCP      <<8 /* Channel Program Physical address */
        !           509: #define kRelAddressPhys     kRelPhys    <<8 /* User data Physical address       */
        !           510: 
        !           511:     /* Relocatable COMMAND-DEPENDENT types: */
        !           512: 
        !           513: #define kRelCmdDep      0xFF        /* relocatable command-dependent mask           */
        !           514: #define kRelCmdDepCP    kRelCP      /* Channel Program command-dependent (branch)   */
        !           515: #define kRelCmdDepLabel kRelNoSwap  /* Channel Program label - don't swap           */
        !           516: 
        !           517: 
        !           518:     /* Channel Program macros:  */
        !           519: 
        !           520: #define STAGE(v)        STORE_QUAD  | KEY_SYSTEM    | 4, kcclStageLabel, v, kRelAddressCP | kRelCmdDepLabel
        !           521: #define CLEAR_CMD_DONE  STORE_QUAD  | KEY_SYSTEM    | 1, kMeshInterrupt, kMeshIntrCmdDone, kRelAddressMESH
        !           522: #define CLEAR_INT_REG   STORE_QUAD  | KEY_SYSTEM    | 1, kMeshInterrupt, kMeshIntrMask, kRelAddressMESH
        !           523: #define CLR_PHASEMM     STORE_QUAD  | KEY_SYSTEM    | 1, kMeshInterrupt, kMeshIntrCmdDone | kMeshIntrException, kRelAddressMESH
        !           524: #define MOVE_1(a,v,r)   STORE_QUAD  | KEY_SYSTEM    | 1, a, v, r
        !           525: #define MOVE_4(a,v,r)   STORE_QUAD  | KEY_SYSTEM    | 4, a, v, r
        !           526: #define MESH_REG(a,v)   STORE_QUAD  | KEY_SYSTEM    | 1, a, v, kRelAddressMESH
        !           527: #define MESH_REG_WAIT(a,v)  STORE_QUAD  | KEY_SYSTEM | kWaitIfTrue | 1, a, v, kRelAddressMESH
        !           528: 
        !           529: #define SENSE(c)        INPUT_LAST  | kBranchIfFalse | kWaitIfTrue | c, kcclSenseBuffer,  kcclProblem, kRelAddressCP   | kRelCmdDepCP
        !           530: #define MSGO(a,c)       OUTPUT_LAST | kBranchIfFalse | kWaitIfTrue | c, a,                kcclProblem, kRelAddressCP   | kRelCmdDepCP
        !           531: #define CMDO(c)         OUTPUT_LAST | kBranchIfFalse | kWaitIfTrue | c, kcclCMDOdata,     kcclProblem, kRelAddressCP   | kRelCmdDepCP
        !           532: #define MSGI(c)         INPUT_LAST  | kBranchIfFalse | kWaitIfTrue | c, kcclMSGIdata,     kcclProblem, kRelAddressCP   | kRelCmdDepCP
        !           533: #define STATUS_IN       INPUT_LAST  | kBranchIfFalse | kWaitIfTrue | 1, kcclStatusData,   kcclProblem, kRelAddressCP   | kRelCmdDepCP
        !           534: #define BUCKET          INPUT_LAST  | kBranchIfFalse               | 8, kcclBucket,       kcclProblem, kRelAddressCP   | kRelCmdDepCP
        !           535: 
        !           536: #define BRANCH(a)        NOP_CMD | kBranchAlways,                0, a, kRelCmdDepCP
        !           537: #define BR_IF_PROBLEM    NOP_CMD | kBranchIfFalse | kWaitIfTrue, 0, kcclProblem, kRelCmdDepCP
        !           538: #define BR_NO_PROBLEM(a) NOP_CMD | kBranchIfTrue               , 0, a, kRelCmdDepCP
        !           539: #define STOP(L)          STOP_CMD,                               0, L, kRelCmdDepLabel
        !           540: #define INTERRUPT(a)     NOP_CMD | kIntAlways, 0, a, 0
        !           541: #define RESERVE          0xCEFECEFE, 0xCEFECEFE, 0xCEFECEFE, 0xCEFECEFE
        !           542: #define WAIT_4_CMDDONE   NOP_CMD | kWaitIfTrue, 0, 0, 0
        !           543: 
        !           544: //#define SWAP(x) (UInt32)EndianSwap32Bit( (UInt32)( x ) )
        !           545: #define SWAP(x) (UInt32)EndianSwap32( (UInt32)( x ) )
        !           546: 
        !           547: 
        !           548:     /* Return values from hardwareStart.    */
        !           549: 
        !           550:     typedef enum
        !           551:     {   kHardwareStartOK,           /* command started successfully         */
        !           552:         kHardwareStartRejected,     /* command rejected, try another        */
        !           553:         kHardwareStartBusy          /* hardware not ready for command       */
        !           554:     } HardwareStartResult;
        !           555: 
        !           556:          /* This structure defines the DBDMA Channel Command descriptor.    */
        !           557:          /***** WARNING:    Endian-ness issues must be considered when  *****/
        !           558:          /***** performing load/store!                                  *****/
        !           559:          /***** DBDMA specifies memory organization as quadlets so it   *****/
        !           560:          /***** is not correct to think of either the operation or      *****/
        !           561:          /***** result field as two 16-bit fields. This would have      *****/
        !           562:          /***** undesirable effects on the byte ordering within their   *****/
        !           563:          /***** respective quadlets. Use the accessor macros provided   *****/
        !           564:          /***** below.                                                  *****/
        !           565: 
        !           566:     struct DBDMADescriptor
        !           567:     {
        !           568:         UInt32  operation;       /* cmd || key || i || b || w || reqCount   */
        !           569:         UInt32  address;
        !           570:         UInt32  cmdDep;
        !           571:         UInt32  result;         /* xferStatus || resCount   */
        !           572:     };
        !           573:     typedef struct DBDMADescriptor  DBDMADescriptor;
        !           574: 
        !           575:     typedef DBDMADescriptor *DBDMADescriptorPtr;
        !           576: 
        !           577:         /* These constants define the DBDMA channel command operations and modifiers.*/
        !           578: 
        !           579:     enum        /* Command.cmd operations   */
        !           580:     {
        !           581:         OUTPUT_MORE     = 0x00000000,
        !           582:         OUTPUT_LAST     = 0x10000000,
        !           583:         INPUT_MORE      = 0x20000000,
        !           584:         INPUT_LAST      = 0x30000000,
        !           585:         STORE_QUAD      = 0x40000000,
        !           586:         LOAD_QUAD       = 0x50000000,
        !           587:         NOP_CMD         = 0x60000000,
        !           588:         STOP_CMD        = 0x70000000,
        !           589:         kdbdmaCmdMask   = 0xF0000000
        !           590:     };
        !           591: 
        !           592: 
        !           593:     enum
        !           594:     {       /* Command.key modifiers                            */
        !           595:             /* (choose one for INPUT, OUTPUT, LOAD, and STORE)  */
        !           596:         KEY_STREAM0         = 0x00000000,   /* default modifier*/
        !           597:         KEY_STREAM1         = 0x01000000,
        !           598:         KEY_STREAM2         = 0x02000000,
        !           599:         KEY_STREAM3         = 0x03000000,
        !           600:         KEY_REGS            = 0x05000000,
        !           601:         KEY_SYSTEM          = 0x06000000,
        !           602:         KEY_DEVICE          = 0x07000000,
        !           603:         kdbdmaKeyMask       = 0x07000000,   /* Command.i modifiers (choose one for INPUT, OUTPUT, LOAD, STORE, and NOP)*/
        !           604:         kIntNever           = 0x00000000,   /* default modifier     */
        !           605:         kIntIfTrue          = 0x00100000,
        !           606:         kIntIfFalse         = 0x00200000,
        !           607:         kIntAlways          = 0x00300000,
        !           608:         kdbdmaIMask         = 0x00300000,   /* Command.b modifiers (choose one for INPUT, OUTPUT, and NOP)*/
        !           609:         kBranchNever        = 0x00000000,   /* default modifier     */
        !           610:         kBranchIfTrue       = 0x00040000,
        !           611:         kBranchIfFalse      = 0x00080000,
        !           612:         kBranchAlways       = 0x000C0000,
        !           613:         kdbdmaBMask         = 0x000C0000,   /* Command.w modifiers (choose one for INPUT, OUTPUT, LOAD, STORE, and NOP)*/
        !           614:         kWaitNever          = 0x00000000,   /* default modifier     */
        !           615:         kWaitIfTrue         = 0x00010000,
        !           616:         kWaitIfFalse        = 0x00020000,
        !           617:         kWaitAlways         = 0x00030000,
        !           618:         kdbdmaWMask         = 0x00030000,    /* operation masks     */
        !           619:     };
        !           620: 
        !           621: 
        !           622:         /* This is a temporary implementation of EndianSwap32Bit    */
        !           623:         /* until the correct library/method is made available.      */
        !           624:         /*  @param  value       The value to change                 */
        !           625:         /*  @result The value endian-swapped.                       */
        !           626: 
        !           627: #ifdef CRAP
        !           628:     static inline unsigned EndianSwap32Bit( unsigned value )
        !           629:     {
        !           630:         register unsigned   temp;
        !           631: 
        !           632:         temp  = ((value & 0xFF000000) >> 24);
        !           633:         temp |= ((value & 0x00FF0000) >>  8);
        !           634:         temp |= ((value & 0x0000FF00) <<  8);
        !           635:         temp |= ((value & 0x000000FF) << 24);
        !           636:         return temp;
        !           637:     }
        !           638: #else
        !           639:     static __inline__ UInt32     EndianSwap32( UInt32 y )
        !           640:     {
        !           641:         UInt32              result;
        !           642:         volatile UInt32   x;
        !           643: 
        !           644:         x = y;
        !           645:         __asm__ volatile("lwbrx %0, 0, %1" : "=r" (result) : "r" (&x) : "r0");
        !           646:         return result;
        !           647:     }
        !           648: #endif /* CRAP */
        !           649: 
        !           650: 
        !           651:     typedef struct globals      /* Globals for this module (not per instance)   */
        !           652:     {
        !           653:         UInt32       evLogFlag; // debugging only
        !           654:         UInt8       *evLogBuf;
        !           655:         UInt8       *evLogBufe;
        !           656:         UInt8       *evLogBufp;
        !           657:         UInt8       intLevel;
        !           658: 
        !           659:         MESHShadow  shadow; // move to per instance??? /* Last MESH register state      */
        !           660: 
        !           661:         UInt32      cclLogAddr,     cclPhysAddr;    // for debugging/miniMon ease
        !           662:         UInt32      meshAddr;                       // for debugging/miniMon ease
        !           663:     } globals;
        !           664: 
        !           665: 
        !           666:     /* "Global" data for each instance of the MESH Host Bus Adapter:   */
        !           667: 
        !           668: @interface AppleMesh_SCSI : IOSCSIController < IOPower >
        !           669: {
        !           670:         /* These globals locate the hardware interfaces in  */
        !           671:         /* logical and physical address spaces.             */
        !           672: 
        !           673:     MeshRegister    *meshAddr;              /* -> Mesh registers (logical)      */
        !           674:     PhysicalAddress gMESHPhysAddr;          /* -> Mesh registers (physical)     */
        !           675: 
        !           676:     dbdma_regmap_t  *dbdmaAddr;             /* -> DBDMA registers (logical)     */
        !           677:     PhysicalAddress dbdmaAddrPhys;          /* -> DBDMA registers (physical)    */
        !           678: 
        !           679:     PhysicalAddress cclPhysAddr;            /* -> DBDMA channel area (physical) */
        !           680:     DBDMADescriptor *cclLogAddr;            /* -> DBDMA channel area (logical)  */
        !           681:     UInt32          cclLogAddrSize;         /* == DBDMA channel allocated size  */
        !           682:     UInt32          gDBDMADescriptorMax;    /* Number of DATA descriptors       */
        !           683: 
        !           684: 
        !           685:         /* There are 3 queues: incomingCmdQ, pendingCmdQ, disconnectedCmdQ.     */
        !           686:         /* Commands are passed from exported methods to the IO thread via       */
        !           687:         /* incomingCmdQ, which is protected by incomingCmdLock.                 */
        !           688:         /* Commands which are disconnected but not complete are kept in         */
        !           689:         /* disconnectedCmdQ.                                                    */
        !           690:         /* Commands which have been dequeued from incomingCmdQ by the IO thread */
        !           691:         /* but which have not been started because a command is currently active*/
        !           692:         /* on the bus are kept in pendingCmdQ. This queue also holds commands   */
        !           693:         /* pushed back when we lose arbitration.                                */
        !           694: 
        !           695:         /* The currently active command, if any, is kept in gActiveCommand.     */
        !           696:         /* Only commandBufs with op == kCommandExecute are ever placed in       */
        !           697:         /* gActiveCommand.                                                      */
        !           698:     id              incomingCmdLock;           /* NXLock for incomingCmdQ       */
        !           699:     queue_head_t    incomingCmdQ;
        !           700:     queue_head_t    pendingCmdQ;
        !           701:     queue_head_t    disconnectedCmdQ;
        !           702:     queue_head_t    abortCmdQ;
        !           703: 
        !           704:         /* This is the command we're currently execution. If NULL, the Mac      */
        !           705:         /* is idle (or all commands are disconnected). Normally, gCurrentTarget */
        !           706:         /* and gCurrentLUN track the values in the active command's associated  */
        !           707:         /* SCSI request. They are set to kInvalidTarget and kInvalidLUN at      */
        !           708:         /* initialization, command deactivation, command complete, and command  */
        !           709:         /* disconnect. They are set to valid values (with no active command)    */
        !           710:         /* during reselection. This is tricky, so look carefully at the code.   */
        !           711:     CommandBuffer   *gActiveCommand;        /* -> The currently executing command   */
        !           712:     UInt32          gCurrentTarget;         /* == The current target bus ID         */
        !           713:     UInt32          gCurrentLUN;            /* == The current target LUN            */
        !           714: 
        !           715:         /* Global option flags, accessible via instance table or setIntValues. Note: some of
        !           716:          * these are intended for debugging. However, users may need to disable command
        !           717:          * queuing, synchronous, or fast to handle device or bus limitations. The
        !           718:          * architecture-specific initialization "looks" at the device to determine whether
        !           719:          * specific features (such as synchronous) are supported.
        !           720:          *  gOptionAutoSenseEnable      Debug only, normally set
        !           721:          *  gOptionCmdQueueEnable       Enable tagged queuing.
        !           722:          *  gOptionSyncModeEnable       Enable synchronous transfers (clear if problems)
        !           723:          *  gOptionFastModeEnable       Enable fast transfers (clear if problems)
        !           724:          *  gOptionExtendTiming         Extended selection timing (debug, unused)
        !           725:          *  gFlagIOThreadRunning        Set when IO thread is initialized. Needed
        !           726:          *                              for shutdown.
        !           727:          *  gFlagIncompleteDBDMA        Set in the data transfer setup if there was
        !           728:          *                              so much data that the entire transfer could not
        !           729:          *                              be stored in the CCL area. If so, the interrupt
        !           730:          *                              service routine ("good completion") will restart
        !           731:          *                              the data transfer operation.
        !           732:          */
        !           733:     UInt32      gOptionAutoSenseEnable      : 1,
        !           734:                 gOptionCmdQueueEnable       : 1,
        !           735:                 gOptionSyncModeEnable       : 1,
        !           736:                 gOptionFastModeEnable       : 1,
        !           737:                 gOptionExtendTiming         : 1,
        !           738:                 gFlagIOThreadRunning        : 1,    /* Set at init              */
        !           739:                 gFlagIncompleteDBDMA        : 1,    /* Need more DMA            */
        !           740:                 gFlagReselecting            : 1,    /* Reselection in progress  */
        !           741:                 pad                         : 24;
        !           742: 
        !           743:         /* Array of active IO counters, one counter per LUN per target.         */
        !           744:         /* If command queueing is disabled, the max value of each counter is 1. */
        !           745:         /* gActiveCount is the sum of all elements in activeArray.              */
        !           746: 
        !           747:     UInt8       gActiveArray[ SCSI_NTARGETS ][ SCSI_NLUNS ];
        !           748:     UInt32      gActiveCount;
        !           749: 
        !           750:         /* These variables change during SCSI IO operation.                 */
        !           751:         /*  msgOutPtr       Points to the next free byte in the MSGO buffer */
        !           752:         /*                  in the shared CCL area.                         */
        !           753: 
        !           754:     UInt8       *msgOutPtr;             /* ptr to message-out data  */
        !           755: 
        !           756:         /* These variables manage Message-In bus phase. Because the */
        !           757:         /* Message-In handler uses programmed IO, gMsgInCount and   */
        !           758:         /* gMsgInState are actually local variables to the message  */
        !           759:         /* reader, and are here for debugging convenience.          */
        !           760: 
        !           761:     UInt8       gMsgInBuffer[ 16 ];
        !           762:     SInt8       gMsgInCount;            /* Message bytes still to read  */
        !           763:     MsgInState  gMsgInState;            /* How are we handling messages */
        !           764: 
        !           765: #define kFlagMsgIn_Reject       0x01
        !           766: #define kFlagMsgIn_Disconnect   0x02
        !           767:     UInt8       gMsgInFlag;
        !           768: 
        !           769: #define kFlagMsgOut_SDTR        0x01
        !           770: #define kFlagMsgOut_Queuing     0x02
        !           771:     UInt8       gMsgOutFlag;
        !           772: 
        !           773:         /* These variables are used during reselection to select the correct   */
        !           774:         /* (tagged) command. msgInTagType is the last Tagged Queue message     */
        !           775:         /* received from a target during reselection. msgInTag is the          */
        !           776:         /* tag value. Currently, we should only see a Simple Queue Tag.        */
        !           777:     UInt8       msgInTagType;           /* Last tag type                */
        !           778:     UInt8       msgInTag;               /* Last tag value               */
        !           779: 
        !           780:         /* Hardware related variables:  */
        !           781: 
        !           782:     UInt8       gInitiatorID;           /* Our SCSI ID                  */
        !           783:     UInt8       gInitiatorIDMask;       /* BusID bitmask for selection  */
        !           784:     UInt8       gSelectionTimeout;      /* In MESH 10 msec units        */
        !           785: 
        !           786:         /* commandBuf->queueTag for next IO. This is never zero;    */
        !           787:         /* for all requests involving a T/L/Q nexus, a queue tag    */
        !           788:         /* of zero indicates a nontagged command.                   */
        !           789:     UInt8       gNextQueueTag;
        !           790: 
        !           791:     PerTargetData   gPerTargetData[ SCSI_NTARGETS ];
        !           792: 
        !           793:         /* Statistics support:  */
        !           794: 
        !           795:     UInt32      gMaxQueueLen;
        !           796:     UInt32      gQueueLenTotal;
        !           797:     UInt32      gTotalCommands;
        !           798: }
        !           799: 
        !           800:     /* Public methods (called by higher-level driver functions) */
        !           801: 
        !           802: + (Boolean) probe  : deviceDescription;     /* Initialize the SCSI driver.  */
        !           803: - free;                                     /* Shutdown the driver.         */
        !           804: 
        !           805: 
        !           806: - (sc_status_t) executeRequest                  /* Execute a SCSI IO request    */
        !           807:                                 : (IOSCSIRequest*)  scsiReq
        !           808:                         buffer  : (void*)           buffer
        !           809:                         client  : (vm_task_t)       client;
        !           810: 
        !           811:     /* Execute a SCSI request using an IOMemoryDescriptor.                      */
        !           812:     /* This allows callers to provide (kernel-resident) logical scatter-gather  */
        !           813:     /* lists. For compatibility with existing implementations, the low-level    */
        !           814:     /* SCSI device driver must first ensure that                                */
        !           815:     /* executeRequest:ioMemoryDescriptor is supported by executing:             */
        !           816:     /*  [controller respondsToSelector : executeRequest:ioMemoryDescriptor]     */
        !           817:     /* @param scsiReq   The SCSI request command record, including the          */
        !           818:     /* target device and LUN, the command to execute, and various control flags.*/
        !           819:     /* @param ioMemoryDescriptor The data buffer(s), if any. This may be NULL   */
        !           820:     /* if no data phase is expected.                                            */
        !           821:     /* @param client   The client task that "owns" the memory buffer.           */
        !           822:     /* @return      Return a bus adaptor specific error status.                 */
        !           823: - (sc_status_t) executeRequest  : (IOSCSIRequest*)scsiReq 
        !           824:             ioMemoryDescriptor  : (IOMemoryDescriptor*)ioMemoryDescriptor;
        !           825: 
        !           826: - (sc_status_t) resetSCSIBus;                   /* Reset the SCSI bus           */
        !           827: - (void)        resetStatistics;                /* Reset statistics buffers     */
        !           828: - (unsigned)    numQueueSamples;
        !           829: - (unsigned)    sumQueueLengths;
        !           830: - (unsigned)    maxQueueLength;
        !           831: 
        !           832:     /* interruptOccurred is a public method called by the       */
        !           833:     /* IO thread in IODirectDevice when an interrupt occurs.    */
        !           834: - (void)        interruptOccurred;
        !           835: 
        !           836:     /* timeoutOccurred is a public method called by the */
        !           837:     /* IO thread in IODirectDevice when it receives a   */
        !           838:     /* timeout message.                                 */
        !           839: 
        !           840: - (void)       timeoutOccurred;
        !           841: 
        !           842: #if APPLE_MESH_ENABLE_GET_SET
        !           843: 
        !           844: - (IOReturn)    setIntValues    : (unsigned*)       parameterArray
        !           845:                 forParameter    : (IOParameterName) parameterName
        !           846:                 count           : (unsigned)        count;
        !           847: 
        !           848: - (IOReturn)    getIntValues    : (unsigned*)       parameterArray
        !           849:                 forParameter    : (IOParameterName) parameterName
        !           850:                 count           : (unsigned*)       count;          /* in/out */
        !           851: 
        !           852:     /* get/setIntValues parameters: */
        !           853: 
        !           854: #define APPLE_MESH_AUTOSENSE                "AutoSense"
        !           855: #define APPLE_MESH_CMD_QUEUE                "CmdQueue"
        !           856: #define APPLE_MESH_SYNC                     "Synchronous"
        !           857: #define APPLE_MESH_FAST_SCSI                "FastSCSI"
        !           858: #define APPLE_MESH_RESET_TARGETS            "ResetTargets"
        !           859: #define APPLE_MESH_RESET_TIMESTAMP          "ResetTimestamp"
        !           860: #define APPLE_MESH_ENABLE_TIMESTAMP         "EnableTimestamp"
        !           861: #define APPLE_MESH_DISABLE_TIMESTAMP        "DisableTimestamp"
        !           862: #define APPLE_MESH_PRESERVE_FIRST_TIMESTAMP "PreserveFirstTimestamp"
        !           863: #define APPLE_MESH_PRESERVE_LAST_TIMESTAMP  "PreserveLastTimestamp"
        !           864: #define APPLE_MESH_READ_TIMESTAMP           "ReadTimestamp"
        !           865: #define APPLE_MESH_STORE_TIMESTAMP          "StoreTimestamp"
        !           866: 
        !           867:     /*
        !           868:      * Recording and setting timestamps may be done using getIntValues (this permits
        !           869:      * access from non-privileged tasks.
        !           870:      *      ResetTimestamp          Clear the timestamp vector - do this before starting
        !           871:      *                              a sequence (no parameters)
        !           872:      *      EnableTimestamp         Start recording (no parameters) (default)
        !           873:      *      DisableTimestamp        Stop recording (no parameters)
        !           874:      *      PreserveFirstTimestamp  Stop recording when the buffer fills (until it is emptied)
        !           875:      *      PreserveLastTimestamp   Discard old values when new arrive (default)
        !           876:      *      ReadTimestamp           Read a vector of timestamps (see sample below)
        !           877:      *      StoreTimestamp          Store a timestamp (from user mode) (see sample below)
        !           878:      * ReadTimestamp copies timestamps from the internal database to user-specified vector.
        !           879:      * Because getIntValues parameters are defined in int units, the code is slighthly
        !           880:      * non-obvious:
        !           881:      *      TimestampDataRecord     myTimestamps[ 123 ];
        !           882:      *      unsigned                count;
        !           883:      *      count = sizeof (myTimestamps) / sizeof (unsigned);
        !           884:      *      [scsiDevice getIntValues
        !           885:      *                          : (unsigned int *) myTimestamps
        !           886:      *          forParameter    : APPLE_MESH_READ_TIMESTAMP
        !           887:      *          count           : &count
        !           888:      *      ];
        !           889:      *      count = (count * sizeof (unsigned)) / sizeof (TimestampDataRecord);
        !           890:      *      for (i = 0; i < count; i++) {
        !           891:      *          Process(myTimestamps[i]);
        !           892:      *      }
        !           893:      * Applications can store timestamps using one of three parameter formats:
        !           894:      *      unsigned               paramVector[4];
        !           895:      * Tag only -- the library will supply the event time
        !           896:      *      paramVector[0] = kMyTagValue;
        !           897:      *      [scsiDevice getIntValues
        !           898:      *                          : paramVector
        !           899:      *          forParameter    : "StoreTimestamp"
        !           900:      *          count           : 1
        !           901:      *      ];
        !           902:      * Tag plus value:
        !           903:      *      paramVector[0] = kMyTagValue;
        !           904:      *      paramVector[1] = 123456;
        !           905:      *      [scsiDevice getIntValues
        !           906:      *                          : paramVector
        !           907:      *          forParameter    : "StoreTimestamp"
        !           908:      *          count           : 2
        !           909:      *      ];
        !           910:      * Tag plus value + time:
        !           911:      *      paramVector[0] = kMyTagValue;
        !           912:      *      paramVector[1] = 123456;
        !           913:      *      IOGetTimestamp( (ns_time_t*)&paramVector[2] );
        !           914:      *      [scsiDevice getIntValues
        !           915:      *                          : paramVector
        !           916:      *          forParameter    : "StoreTimestamp"
        !           917:      *          count           : 4
        !           918:      *      ];
        !           919:      * Note that you can combine tag only with tag plus value plus time to measure
        !           920:      * user->device latency.
        !           921:      */
        !           922: 
        !           923: #endif APPLE_MESH_ENABLE_GET_SET
        !           924: 
        !           925: @end
        !           926: 
        !           927: 
        !           928: 
        !           929: @interface AppleMesh_SCSI( Hardware )
        !           930: 
        !           931: -                       InitializeHardware : deviceDescription;
        !           932: - (IOReturn)            ResetHardware      : (Boolean)resetSCSIBus;
        !           933: - (HardwareStartResult) hardwareStart      : (CommandBuffer*)cmdBuf;
        !           934: 
        !           935: @end
        !           936: 
        !           937: 
        !           938:     /* These macros are used to access words (32 bit) and bytes (8 bit) in  */
        !           939:     /* the channel command area. They may be used as source or destination. */
        !           940:     /* CCLDescriptor is aligned to a descriptor start, CCLAddress is just   */
        !           941:     /* an address pointer.                                                  */
        !           942: #define CCLAddress(offset)      (((UInt8*)cclLogAddr) + (offset))
        !           943: #define CCLDescriptor(offset)   ((DBDMADescriptor*)CCLAddress(offset))
        !           944: #define CCLWord(offset)         (*((UInt32*)CCLAddress(offset)))
        !           945: #define CCLByte(offset)         (*((UInt8*)CCLAddress(offset)))
        !           946: 
        !           947: @interface AppleMesh_SCSI ( HardwarePrivate )
        !           948: 
        !           949: - (IOReturn) AllocHdwAndChanMem : deviceDescription;
        !           950: - (void) InitAutosenseCCL;
        !           951: - (void) UpdateCP : (Boolean) reselecting;
        !           952: - (void) StartBucket;
        !           953: - (void) SetupMsgO;
        !           954: - (void) ClearCPResults;
        !           955: - (void) InitCP;
        !           956: 
        !           957: @end
        !           958: 
        !           959: @interface AppleMesh_SCSI( MeshInterrupt )
        !           960: 
        !           961: - (void) DoHardwareInterrupt;       /* Respond to an Interrupt Service message. */
        !           962: - (void) ProcessInterrupt;
        !           963: - (void)    DoInterruptStageArb;
        !           964: - (void)    DoInterruptStageSelA;
        !           965: - (void)    DoInterruptStageMsgO;
        !           966: - (void)    DoInterruptStageCmdO;
        !           967: - (void)    DoInterruptStageXfer;
        !           968: - (void)    DoInterruptStageXferAutosense;
        !           969: - (void)    DoInterruptStageGood;
        !           970: - (IOReturn)    DoMessageInPhase;           /* Handle MSGI phase.   */
        !           971: - (void)        ProcessMSGI;
        !           972: - (void)        HandleReselectionInterrupt; /* Process a reselection interrupt. */
        !           973: - (Boolean)     getReselectionTargetID;
        !           974: 
        !           975: @end
        !           976: 
        !           977: 
        !           978:     /* SCSI command status (from status phase)  */
        !           979: 
        !           980: #define kScsiStatusGood             0x00    /* Normal completion        */
        !           981: #define kScsiStatusCheckCondition   0x02    /* Need GetExtendedStatus   */
        !           982: #define kScsiStatusConditionMet     0x04
        !           983: #define kScsiStatusBusy             0x08    /* Device busy (self-test?) */
        !           984: #define kScsiStatusIntermediate     0x10    /* Intermediate status      */
        !           985: #define kScsiStatusIntermediateMet  0x14    /* Intermediate cond. met   */
        !           986: #define kScsiStatusResConflict      0x18    /* Reservation conflict     */
        !           987: #define kScsiStatusTerminated       0x22    /* Command Terminated       */
        !           988: #define kScsiStatusQueueFull        0x28    /* Target can't do command  */
        !           989: #define kScsiStatusReservedMask     0x3E    /* Vendor specific?         */
        !           990: 
        !           991:     /* SCSI command codes. Commands defined as ...6, ...10, ...12, are          */
        !           992:     /* six-byte, ten-byte, and twelve-byte variants of the indicated command.   */
        !           993: 
        !           994:     /* These commands are supported for all devices.   */
        !           995: 
        !           996: #define kScsiCmdChangeDefinition    0x40
        !           997: #define kScsiCmdCompare             0x39
        !           998: #define kScsiCmdCopy                0x18
        !           999: #define kScsiCmdCopyAndVerify       0x3A
        !          1000: #define kScsiCmdInquiry             0x12
        !          1001: #define kScsiCmdLogSelect           0x4C
        !          1002: #define kScsiCmdLogSense            0x4D
        !          1003: #define kScsiCmdModeSelect12        0x55
        !          1004: #define kScsiCmdModeSelect6         0x15
        !          1005: #define kScsiCmdModeSense12         0x5A
        !          1006: #define kScsiCmdModeSense6          0x1A
        !          1007: #define kScsiCmdReadBuffer          0x3C
        !          1008: #define kScsiCmdRecvDiagResult      0x1C
        !          1009: #define kScsiCmdRequestSense        0x03
        !          1010: #define kScsiCmdSendDiagnostic      0x1D
        !          1011: #define kScsiCmdTestUnitReady       0x00
        !          1012: #define kScsiCmdWriteBuffer         0x3B
        !          1013: 
        !          1014:     /* These commands are supported by direct-access devices only:   */
        !          1015: 
        !          1016: #define kScsiCmdFormatUnit          0x04
        !          1017: #define kSCSICmdCopy                0x18
        !          1018: #define kSCSICmdCopyAndVerify       0x3A
        !          1019: #define kScsiCmdLockUnlockCache     0x36
        !          1020: #define kScsiCmdPrefetch            0x34
        !          1021: #define kScsiCmdPreventAllowRemoval 0x1E
        !          1022: #define kScsiCmdRead6               0x08
        !          1023: #define kScsiCmdRead10              0x28
        !          1024: #define kScsiCmdReadCapacity        0x25
        !          1025: #define kScsiCmdReadDefectData      0x37
        !          1026: #define kScsiCmdReadLong            0x3E
        !          1027: #define kScsiCmdReassignBlocks      0x07
        !          1028: #define kScsiCmdRelease             0x17
        !          1029: #define kScsiCmdReserve             0x16
        !          1030: #define kScsiCmdRezeroUnit          0x01
        !          1031: #define kScsiCmdSearchDataEql       0x31
        !          1032: #define kScsiCmdSearchDataHigh      0x30
        !          1033: #define kScsiCmdSearchDataLow       0x32
        !          1034: #define kScsiCmdSeek6               0x0B
        !          1035: #define kScsiCmdSeek10              0x2B
        !          1036: #define kScsiCmdSetLimits           0x33
        !          1037: #define kScsiCmdStartStopUnit       0x1B
        !          1038: #define kScsiCmdSynchronizeCache    0x35
        !          1039: #define kScsiCmdVerify              0x2F
        !          1040: #define kScsiCmdWrite6              0x0A
        !          1041: #define kScsiCmdWrite10             0x2A
        !          1042: #define kScsiCmdWriteAndVerify      0x2E
        !          1043: #define kScsiCmdWriteLong           0x3F
        !          1044: #define kScsiCmdWriteSame           0x41
        !          1045: 
        !          1046:     /* These commands are supported by sequential devices:  */
        !          1047: 
        !          1048: #define kScsiCmdRewind              0x01
        !          1049: #define kScsiCmdWriteFilemarks      0x10
        !          1050: #define kScsiCmdSpace               0x11
        !          1051: #define kScsiCmdLoadUnload          0x1B
        !          1052: 
        !          1053:     /* ANSI SCSI-II for CD-ROM devices. */
        !          1054: #define kScsiCmdReadCDTableOfContents   0x43
        !          1055: 
        !          1056:     /* Message codes (for Msg In and Msg Out phases).   */
        !          1057: 
        !          1058: #define kScsiMsgAbort                   0x06
        !          1059: #define kScsiMsgAbortTag                0x0D
        !          1060: #define kScsiMsgBusDeviceReset          0x0C
        !          1061: #define kScsiMsgClearQueue              0x0E
        !          1062: #define kScsiMsgCmdComplete             0x00
        !          1063: #define kScsiMsgDisconnect              0x04
        !          1064: #define kScsiMsgIdentify                0x80
        !          1065: #define kScsiMsgIdentifyLUNMask         0x07    /* LUN bits in Identify message */
        !          1066: #define kScsiMsgIgnoreWideResdue        0x23
        !          1067: #define kScsiMsgInitiateRecovery        0x0F
        !          1068: #define kScsiMsgInitiatorDetectedErr    0x05
        !          1069: #define kScsiMsgLinkedCmdComplete       0x0A
        !          1070: #define kScsiMsgLinkedCmdCompleteFlag   0x0B
        !          1071: #define kScsiMsgParityErr               0x09
        !          1072: #define kScsiMsgRejectMsg               0x07
        !          1073: #define kScsiMsgModifyDataPtr           0x00    /* Extended msg     */
        !          1074: #define kScsiMsgNop                     0x08
        !          1075: #define kScsiMsgHeadOfQueueTag          0x21    /* Two byte msg     */
        !          1076: #define kScsiMsgOrderedQueueTag         0x22    /* Two byte msg     */
        !          1077: #define kScsiMsgSimpleQueueTag          0x20    /* Two byte msg     */
        !          1078: #define kScsiMsgReleaseRecovery         0x10
        !          1079: #define kScsiMsgRestorePointers         0x03
        !          1080: #define kScsiMsgSaveDataPointers        0x02
        !          1081: #define kScsiMsgSyncXferReq             0x01    /* Extended msg     */
        !          1082: #define kScsiMsgWideDataXferReq         0x03    /* Extended msg     */
        !          1083: #define kScsiMsgTerminateIOP            0x11
        !          1084: #define kScsiMsgExtended                0x01
        !          1085: #define kScsiMsgEnableDisconnectMask    0x40
        !          1086: 
        !          1087: #define kScsiMsgOneByteMin          0x02
        !          1088: #define kScsiMsgOneByteMax          0x1F
        !          1089: #define kScsiMsgTwoByteMin          0x20
        !          1090: #define kScsiMsgTwoByteMax          0x2F
        !          1091: 
        !          1092: 
        !          1093: 
        !          1094:     /* These methods bang on the MESH chip.         */
        !          1095:     /* Many should be redone as inline functions.   */
        !          1096: 
        !          1097: @interface AppleMesh_SCSI( Mesh )
        !          1098: 
        !          1099: - (IOReturn) ResetMESH  : (Boolean) resetSCSIBus;
        !          1100: - (IOReturn) DoHBASelfTest;
        !          1101: - (IOReturn) WaitForMesh : (Boolean) clearInterrupts;
        !          1102: - (IOReturn) WaitForReq;
        !          1103: - (void) SetSeqReg : (MeshCommand) meshCommand;
        !          1104: - (void) RunDBDMA : (UInt32) offset     stageLabel  : (UInt32) stageLabel;
        !          1105: - (void) GetHBARegsAndClear : (Boolean) clearInts;
        !          1106: - (void) SetIntMask : (UInt8) interruptMask;
        !          1107: - (void) AbortActiveCommand;
        !          1108: - (void) AbortDisconnectedCommand;
        !          1109: 
        !          1110: - (void) logTimestamp   : (const char*) reason;
        !          1111: 
        !          1112: @end
        !          1113: 
        !          1114: 
        !          1115: @interface AppleMesh_SCSI( Private )
        !          1116: 
        !          1117:     /* Send a command to the controller thread, and wait for its completion.    */
        !          1118:     /* Only invoked by publicly exported methods in SCSIController.m.           */
        !          1119: 
        !          1120: - (IOReturn) executeCmdBuf : (CommandBuffer*) cmdBuf;
        !          1121: 
        !          1122:     /* Abort all active and disconnected commands with specified status.    */
        !          1123:     /* No hardware action. Used by threadResetBus and during processing     */
        !          1124:     /* of a kCommandAbortRequest command.                                   */
        !          1125: - (void) abortAllCommands : (sc_status_t) status;
        !          1126: 
        !          1127:     /* IO thread version of resetSCSIBus and executeRequest.   */
        !          1128: - (void) threadResetBus : (const char*) reason;
        !          1129: 
        !          1130: 
        !          1131: - (void) threadExecuteRequest : (CommandBuffer*) cmdBuf;
        !          1132: 
        !          1133:     /* Methods called by other modules in this driver:  */
        !          1134: 
        !          1135:     /* Called when a transaction associated with cmdBuf is complete. Notify
        !          1136:      * waiting thread. If cmdBuf->scsiReq exists (i.e., this is not a reset
        !          1137:      * or an abort), scsiReq->driverStatus must be valid. If cmdBuf is activeCmd,
        !          1138:      * caller must remove from activeCmd.
        !          1139:      */
        !          1140: - (void) ioComplete : (CommandBuffer*) cmdBuf;
        !          1141: 
        !          1142:     /* A target reported a full queue. Push this command back on the pending
        !          1143:      * queue and try it again, later. (Return SR_IOST_GOOD if successful,
        !          1144:      * SR_IOST_BADST on failure.
        !          1145:      */
        !          1146: - (sc_status_t) pushbackFullTargetQueue : (CommandBuffer*) cmdBuf;
        !          1147: 
        !          1148:     /* A command couldn't be issued (because a target is trying to reselect
        !          1149:      * us or we lost arbitration for some other reason). Push this request
        !          1150:      * onto the front of the pending request queue.
        !          1151:      */
        !          1152: - (void) pushbackCurrentRequest : (CommandBuffer*) cmdBuf;
        !          1153: 
        !          1154:     /* A command can't be continued. Perhaps there is no target.    */
        !          1155: - (void) killCurrentRequest;
        !          1156: 
        !          1157:     /* IO associated with activeCmd has disconnected. Place it  */
        !          1158:     /* on disconnectQ and enable another transaction.           */
        !          1159: - (void) disconnect;
        !          1160: 
        !          1161:     /* Specified target, lun, and queueTag is trying to reselect. If we have
        !          1162:      * a CommandBuffer for this TLQ nexus on disconnectQ, remove it, make it the
        !          1163:      * current activeCmd, and return YES. Else return NO.
        !          1164:      * A value of zero for queueTag indicates a nontagged command (zero is never
        !          1165:      * used as the queue tag value for a tagged command).
        !          1166:      */
        !          1167: - (IOReturn) reselectNexus  : (UInt8) target
        !          1168:                 lun         : (UInt8) lun
        !          1169:                 queueTag    : (UInt8) queueTag;
        !          1170: - (Boolean) commandCanBeStarted : (CommandBuffer*) cmdBuf;
        !          1171: - (void) selectNextRequest; /* Choose the next request that can be started. */
        !          1172: - (void) killActiveCommand : (sc_status_t) status;  // mlj added
        !          1173: - (void) activateCommand : (CommandBuffer*) cmdBuf;
        !          1174: - (void) deactivateCmd : (CommandBuffer*) cmdBuf;
        !          1175: 
        !          1176:     /* Kill everything in the indicated queue. Called after bus reset.  */
        !          1177: - (void) killQueue : (queue_head_t*)queuePtr  finalStatus : (sc_status_t)scsiStatus;
        !          1178: - (void) UpdateCurrentIndex;
        !          1179: 
        !          1180: @end
        !          1181: 
        !          1182: #if USE_ELG && CustomMiniMon
        !          1183:             /* for debugging:   */
        !          1184:     extern void     EvLog( UInt32 a, UInt32 b, UInt32 ascii, char* str );
        !          1185:     extern void     Pause( UInt32 a, UInt32 b, UInt32 ascii, char* str );
        !          1186:     extern void     AllocateEventLog( UInt32 ); // defined in miniMon
        !          1187: #endif /* NotMiniMon */
        !          1188:     extern void     call_kdp();     // for debugging
        !          1189: 
        !          1190: 
        !          1191:     /* Usage:
        !          1192:      *  1.  In the makefile (or elsewhere), define TIMESTAMP non-zero. If zero, this
        !          1193:      *      code will be stubbed out.
        !          1194:      *  2.  In your initialization routine, call MakeTimestampRecord() to create a
        !          1195:      *      timestamp record. This will be stored in a static, private, variable.
        !          1196:      *  3.  When you want to time something, call StoreTimestamp() as follows:
        !          1197:      *          {
        !          1198:      *              ns_time_t       eventTime;
        !          1199:      *              IOGetTimestamp(&eventTime);
        !          1200:      *              StoreTimestamp(timestampTag, timestampValue, eventTime);
        !          1201:      *          }
        !          1202:      *      Where timestampTag and timestampValue are 32-bit unsigned integers
        !          1203:      *      that are not otherwise interpreted by the Timestamp library. By
        !          1204:      *      convention, timestampTag contains a 4-byte character (Macintosh OSType)
        !          1205:      *      that distinguishes timing events. The OSType and OSTag macros
        !          1206:      *      can be used to construct tag values. OSTag is useful for recording
        !          1207:      *      elapsed time:
        !          1208:      *          StoreTimestamp(OSTag('+', "foo"), 0, startTime);
        !          1209:      *          ...
        !          1210:      *          StoreTimestamp(OSTag('-', "foo"), 0, endTime);
        !          1211:      */
        !          1212: 
        !          1213: 
        !          1214: //#ifndef TIMESTAMP
        !          1215: #define TIMESTAMP   0   // mlj - resolve dup symbols with Curio     /* TEMP TEMP TEMP */
        !          1216: //#endif
        !          1217: 
        !          1218:     /* Construct an OSType from four characters.     */
        !          1219: #define OSType(c0, c1, c2, c3) ( \
        !          1220:         (   ((c0) << 24)        \
        !          1221:          |  ((c1) << 16)        \
        !          1222:          |  ((c2) <<  8)        \
        !          1223:          |  ((c3) <<  0) ))
        !          1224:     /* Construct an OSType from a single character and the  */
        !          1225:     /* first three characters from a given string.          */
        !          1226: #define OSTag(where, what)  (OSType((where), (what)[0], (what)[1], (what)[2]))
        !          1227: 
        !          1228:         /*  ._______________________________________________________________________________.
        !          1229:             | Each timestamp entry contains the following information:                      |
        !          1230:             |   timestampTag    A user-specified OSType that identifies this timestamp      |
        !          1231:             |   timestampValue  A user-specified additional value                           |
        !          1232:             |   eventTime       The system UpTime value at the time the data was collected. |
        !          1233:             ._______________________________________________________________________________.
        !          1234:         */
        !          1235:     struct TimestampDataRecord
        !          1236:     {
        !          1237:         OSType          timestampTag;       /* Caller's tag parameter       */
        !          1238:         UInt32          timestampValue;     /* Caller's value parameter     */
        !          1239:         ns_time_t       eventTime;          /* UpTime() at Timestamp call   */
        !          1240:     };
        !          1241:     typedef struct TimestampDataRecord  TimestampDataRecord, *TimestampDataPtr;
        !          1242: 
        !          1243: #if TIMESTAMP  /* (( */
        !          1244:     void    MakeTimestampRecord( UInt32 nEntries );
        !          1245:     void    StoreTimestamp( OSType      timestampTag,
        !          1246:                             UInt32      timestampValue,
        !          1247:                             ns_time_t   timestampEvent );
        !          1248:         /**
        !          1249:          * Returns the next timestamp, if any, in resultData.
        !          1250:          * @param   resultData      Where to store the data
        !          1251:          * @return  TRUE            Valid data returned
        !          1252:          *          FALSE           No data is available.
        !          1253:          */
        !          1254:     Boolean  ReadTimestamp( TimestampDataPtr resultData );
        !          1255:         /**
        !          1256:          * Return a vector of timestamps.
        !          1257:          * @param   resultVector    Where to store the data
        !          1258:          * @param   count           On entrance, this has the maximum number of elements
        !          1259:          *                          to return. On exit, this will have the actual number
        !          1260:          *                          of elements that were returned.
        !          1261:          * Note that, if the semaphore is blocked, ReadTimestampVector will not return any
        !          1262:          * data. Data cannot be collected while ReadTimestampVector is copying data
        !          1263:          * to the user's buffer. Note that, since the user's buffer will typically be
        !          1264:          * in pageable memory, pageing I/O that might otherwise be timestamped will
        !          1265:          * be lost.
        !          1266:          */
        !          1267:     void    ReadTimestampVector( TimestampDataPtr resultVector, UInt32 *count );        /* -> Max count, <-actual   */
        !          1268:     Boolean EnableTimestamp( Boolean enableTimestamp );
        !          1269:     Boolean PreserveTimestamp( Boolean preserveFirst );
        !          1270:     void    ResetTimestampIndex(void);
        !          1271:     UInt32  GetTimestampSemaphoreLostCounter( void );
        !          1272: #else  /* )( not TIMESTAMP: */
        !          1273: #define MakeTimestampRecord( nEntries ) /* Nothing */
        !          1274: #define StoreTimestamp( timestampTag, timestampValue, timestampEvent )  /* Nothing  */
        !          1275: #define ReadTimestamp(resultData)   (0)                                 /* Fails    */
        !          1276: #define ReadTimestampVector(resultVector, count)    \
        !          1277:     do { if ( count ) { *(count) = 0; }  } while (0)
        !          1278: #define EnableTimestamp( enableTimestamp )  (enableTimestamp)
        !          1279: #define PreserveTimestamp( preserveFirst )  (preserveFirst)
        !          1280: #define ResetTimestampIndex()                                           /* Nothing  */
        !          1281: #define GetTimestampSemaphoreLostCount()    (0)
        !          1282: #endif /* )) */

unix.superglobalmegacorp.com

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