Annotation of kernel/bsd/dev/ppc/drvAppleMesh_SCSI/MESH_DBDMA.h, revision 1.1.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.