|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: ! 23: /** ! 24: * Copyright � 1997-2000 Apple Computer Inc. All Rights Reserved. ! 25: * @author Mike Johnson ! 26: * ! 27: * Set tabs every 4 characters. ! 28: * ! 29: * Edit History ! 30: * 25feb99 mlj Initial conversion from banana. ! 31: */ ! 32: ! 33: ! 34: ! 35: /***** For fans of kprintf, IOLog and debugging infrastructure of the *****/ ! 36: /***** string ilk, please modify the ELG and PAUSE macros or their *****/ ! 37: /***** associated EvLog and Pause functions to suit your taste. These *****/ ! 38: /***** macros currently are set up to log events to a wraparound *****/ ! 39: /***** buffer with minimal performance impact. They take 2 UInt32 *****/ ! 40: /***** parameters so that when the buffer is dumped 16 bytes per line, *****/ ! 41: /***** time stamps (~1 microsecond) run down the left side while *****/ ! 42: /***** unique 4-byte ASCII codes can be read down the right side. *****/ ! 43: /***** Preserving this convention facilitates different maintainers *****/ ! 44: /***** using different debugging styles with minimal code clutter. *****/ ! 45: ! 46: #define USE_ELG false // for debugging ! 47: #define kEvLogSize (4096*16) // 16 pages = 64K = 4096 events ! 48: ! 49: #if USE_ELG /* (( */ ! 50: #define ELG(A,B,ASCI,STRING) EvLog( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING ) ! 51: #define PAUSE(A,B,ASCI,STRING) Pause( (UInt32)(A), (UInt32)(B), (UInt32)(ASCI), STRING ) ! 52: #else /* ) not USE_ELG: ( */ ! 53: #define ELG(A,B,ASCI,S) ! 54: #define PAUSE(A,B,ASCI,STRING) IOLog( "MESH: %8x %8x " STRING "\n", (unsigned int)(A), (unsigned int)(B) ) ! 55: #endif /* USE_ELG )) */ ! 56: ! 57: ! 58: #ifndef SynchronizeIO ! 59: #define SynchronizeIO() eieio() /* TEMP */ ! 60: #endif /* SynchronizeIO */ ! 61: ! 62: enum { kMaxAutosenseByteCount = 255 }; ! 63: ! 64: enum ! 65: { ! 66: kMESHRegisterBase = 0, ! 67: kDBDMARegisterBase = 1, ! 68: kNumberRegisters = 2 ! 69: }; ! 70: ! 71: /* Operation flags and options: */ ! 72: ! 73: typedef enum BusPhase /* These are the real SCSI bus phases (from busStatus0): */ ! 74: { ! 75: kBusPhaseDATO = 0, ! 76: kBusPhaseDATI, ! 77: kBusPhaseCMD, ! 78: kBusPhaseSTS, ! 79: kBusPhaseReserved1, ! 80: kBusPhaseReserved2, ! 81: kBusPhaseMSGO, ! 82: kBusPhaseMSGI ! 83: } BusPhase; ! 84: ! 85: /* Command to be executed by IO thread. */ ! 86: /* These are ultimately derived from ioctl control values. */ ! 87: ! 88: typedef enum ! 89: { kCommandExecute, /* Execute IOSCSIRequest */ ! 90: kCommandResetBus, /* Reset bus */ ! 91: kCommandAbortRequest /* Abort IO thread */ ! 92: } CommandOperation; ! 93: ! 94: /* We read target messages using a simple state machine. */ ! 95: /* On entrance to MSGI phase, fMsgInState = kMsgInInit. */ ! 96: /* Continue reading messages until either */ ! 97: /* fMsgInState == kMsgInReady or the target changes phase */ ! 98: /* (which is an error). */ ! 99: typedef enum MsgInState ! 100: { ! 101: kMsgInInit = 0, /* 0 Not reading a message (must be zero) */ ! 102: kMsgInReading, /* 1 MSG input state: reading counted data */ ! 103: kMsgInCounting, /* 2 MSG input state: reading count byte */ ! 104: kMsgInReady /* 3 MSG input state: a msg is now available */ ! 105: } MsgInState; ! 106: ! 107: /* These values represent no active request: */ ! 108: enum ! 109: { kInvalidTarget = 0xFF, ! 110: kInvalidLUN = 0xFF, ! 111: kInvalidTag = 0xFFFFFFFF ! 112: }; ! 113: ! 114: /* The default initiator bus ID (needs to be fetched from NVRAM). */ ! 115: enum ! 116: { ! 117: kInitiatorIDDefault = 7, ! 118: kMaxTargetID = 8, ! 119: kMaxDMATransfer = 0xF000ul, ! 120: kMaxMemCursorSegs = 15 ! 121: }; ! 122: #define APPLE_SCSI_RESET_DELAY 250 /* Msec */ ! 123: ! 124: ! 125: ! 126: ! 127: typedef struct MeshRegister /* Mesh registers: */ ! 128: { ! 129: volatile UInt8 transferCount0; UInt8 pad00[ 0x0F ]; ! 130: volatile UInt8 transferCount1; UInt8 pad01[ 0x0F ]; ! 131: volatile UInt8 xFIFO; UInt8 pad02[ 0x0F ]; ! 132: volatile UInt8 sequence; UInt8 pad03[ 0x0F ]; ! 133: volatile UInt8 busStatus0; UInt8 pad04[ 0x0F ]; ! 134: volatile UInt8 busStatus1; UInt8 pad05[ 0x0F ]; ! 135: volatile UInt8 FIFOCount; UInt8 pad06[ 0x0F ]; ! 136: volatile UInt8 exception; UInt8 pad07[ 0x0F ]; ! 137: volatile UInt8 error; UInt8 pad08[ 0x0F ]; ! 138: volatile UInt8 interruptMask; UInt8 pad09[ 0x0F ]; ! 139: volatile UInt8 interrupt; UInt8 pad10[ 0x0F ]; ! 140: volatile UInt8 sourceID; UInt8 pad11[ 0x0F ]; ! 141: volatile UInt8 destinationID; UInt8 pad12[ 0x0F ]; ! 142: volatile UInt8 syncParms; UInt8 pad13[ 0x0F ]; ! 143: volatile UInt8 MESHID; UInt8 pad14[ 0x0F ]; ! 144: volatile UInt8 selectionTimeOut; ! 145: } MeshRegister; ! 146: ! 147: /* The following structure shadows the MESH chip registers: */ ! 148: ! 149: typedef union MESHShadow ! 150: { UInt32 longWord[ 3 ]; /* for debugging ease. */ ! 151: struct ! 152: { UInt8 interrupt; /* Interrupt */ ! 153: UInt8 error; /* Error register */ ! 154: UInt8 exception; /* Exception register */ ! 155: UInt8 FIFOCount; /* FIFO count */ ! 156: ! 157: UInt8 busStatus0; /* Bus phase + REQ, ACK, & ATN signals */ ! 158: UInt8 busStatus1; /* RST, BSY, SEL */ ! 159: UInt8 interruptMask; /* Interrupt mask for debugging */ ! 160: UInt8 transferCount0; /* low order byte of transfer count */ ! 161: ! 162: UInt8 transferCount1; /* high order byte of transfer count */ ! 163: UInt8 sequence; /* Sequence register */ ! 164: UInt8 syncParms; /* syncParms for debugging */ ! 165: UInt8 destinationID; /* Target ID */ ! 166: } mesh; ! 167: } MESHShadow; ! 168: ! 169: /* MESH Register set offsets */ ! 170: ! 171: enum ! 172: { ! 173: kMeshTransferCount0 = 0x00, ! 174: kMeshTransferCount1 = 0x10, ! 175: kMeshFIFO = 0x20, ! 176: kMeshSequence = 0x30, ! 177: kMeshBusStatus0 = 0x40, ! 178: kMeshBusStatus1 = 0x50, ! 179: kMeshFIFOCount = 0x60, ! 180: kMeshException = 0x70, ! 181: kMeshError = 0x80, ! 182: kMeshInterruptMask = 0x90, ! 183: kMeshInterrupt = 0xA0, ! 184: kMeshSourceID = 0xB0, ! 185: kMeshDestinationID = 0xC0, ! 186: kMeshSyncParms = 0xD0, ! 187: kMeshMESHID = 0xE0, ! 188: kMeshSelTimeOut = 0xF0 ! 189: }; ! 190: ! 191: enum { kMeshMESHID_Value = 0x02 }; /* Read value of kMESHID lo 5 bits only */ ! 192: ! 193: ! 194: /* MESH commands & modifiers for Sequence register: */ ! 195: ! 196: typedef enum ! 197: { ! 198: kMeshNoOpCmd = 0x00, ! 199: kMeshArbitrateCmd = 0x01, ! 200: kMeshSelectCmd = 0x02, ! 201: kMeshCommandCmd = 0x03, ! 202: kMeshStatusCmd = 0x04, ! 203: kMeshDataOutCmd = 0x05, ! 204: kMeshDataInCmd = 0x06, ! 205: kMeshMessageOutCmd = 0x07, ! 206: kMeshMessageInCmd = 0x08, ! 207: kMeshBusFreeCmd = 0x09, ! 208: /* non interrupting: */ ! 209: kMeshEnableParity = 0x0A, ! 210: kMeshDisableParity = 0x0B, ! 211: kMeshEnableReselect = 0x0C, ! 212: kMeshDisableReselect = 0x0D, ! 213: kMeshResetMESH = 0x0E, ! 214: kMeshFlushFIFO = 0x0F, ! 215: /* Sequence command modifier bits: */ ! 216: kMeshSeqDMA = 0x80, /* Data Xfer for this command will use DMA */ ! 217: kMeshSeqTMode = 0x40, /* Target mode - unused */ ! 218: kMeshSeqAtn = 0x20 /* ATN is to be asserted after command */ ! 219: } MeshCommand; ! 220: ! 221: /* The bus Status Registers 0 & 1 have the actual */ ! 222: /* bus signals AT TIME OF READ. */ ! 223: ! 224: enum /* bus Status Register 0 bits: */ ! 225: { ! 226: kMeshIO = 0x01, /* phase bit */ ! 227: kMeshCD = 0x02, /* phase bit */ ! 228: kMeshMsg = 0x04, /* phase bit */ ! 229: kMeshAtn = 0x08, /* Attention signal */ ! 230: kMeshAck = 0x10, /* Ack signal */ ! 231: kMeshReq = 0x20, /* Request signal */ ! 232: kMeshAck32 = 0x40, /* unused - 32 bit bus */ ! 233: kMeshReq32 = 0x80 /* unused - 32 bit bus */ ! 234: }; ! 235: ! 236: enum { kMeshPhaseMask = (kMeshMsg + kMeshCD + kMeshIO) }; ! 237: ! 238: enum /* bus Status Register 1 bits: */ ! 239: { ! 240: kMeshSel = 0x20, /* Select signal */ ! 241: kMeshBsy = 0x40, /* Busy signal */ ! 242: kMeshRst = 0x80 /* Reset signal */ ! 243: }; ! 244: ! 245: enum /* Exception Register bits: */ ! 246: { ! 247: kMeshExcSelTO = 0x01, /* Selection timeout */ ! 248: kMeshExcPhaseMM = 0x02, /* Phase mismatch */ ! 249: kMeshExcArbLost = 0x04, /* lost arbitration */ ! 250: kMeshExcResel = 0x08, /* reselection occurred */ ! 251: kMeshExcSelected = 0x10, ! 252: kMeshExcSelectedWAtn = 0x20 ! 253: }; ! 254: ! 255: enum /* Error Register bits: */ ! 256: { ! 257: kMeshErrParity0 = 0x01, /* parity error */ ! 258: kMeshErrParity1 = 0x02, /* unused - 32 bit bus */ ! 259: kMeshErrParity2 = 0x04, /* unused - 32 bit bus */ ! 260: kMeshErrParity3 = 0x08, /* unused - 32 bit bus */ ! 261: kMeshErrSequence = 0x10, /* Sequence error */ ! 262: kMeshErrSCSIRst = 0x20, /* Reset signal asserted */ ! 263: kMeshErrDisconnected = 0x40 /* unexpected disconnect */ ! 264: }; ! 265: ! 266: enum /* Interrupt Register bits: */ ! 267: { ! 268: kMeshIntrCmdDone = 0x01, /* command done */ ! 269: kMeshIntrException = 0x02, /* exception occurred */ ! 270: kMeshIntrError = 0x04, /* error occurred */ ! 271: kMeshIntrMask = (kMeshIntrCmdDone | kMeshIntrException | kMeshIntrError) ! 272: }; ! 273: ! 274: ! 275: enum /* Values for SyncParms MESH register: */ ! 276: { /* 1st nibble is offset, 2nd is period. */ ! 277: /* Zero offset means async. */ ! 278: kSyncParmsAsync = 0x02, /* Async with min period = 2 */ ! 279: kSyncParmsFast = 0xF0 /* offset = 15, period = Fast (10 MB/s) */ ! 280: }; ! 281: ! 282: /* The following are specific to the MESH CCL */ ! 283: /* Stage Names. (These were originally 'xxxx' identifiers, */ ! 284: /* which is convenient for debugging, but results in many */ ! 285: /* warning messages from the NeXT compiler. */ ! 286: enum ! 287: { /* kcclStageLabel: */ ! 288: kcclStageIdle = 0, /* 0 - 'Idle' */ ! 289: kcclStageInit, /* 1 - 'Init' */ ! 290: kcclStageCCLx, /* 2 - 'CCL~' */ ! 291: kcclStageArb, /* 3 - ' Arb' */ ! 292: kcclStageSelA, /* 4 - 'SelA' */ ! 293: kcclStageMsgO, /* 5 - 'MsgO' */ ! 294: kcclStageCmdO, /* 6 - 'CmdO' */ ! 295: kcclStageXfer, /* 7 - 'Xfer' */ ! 296: kcclStageBucket, /* 8 - 'Buck' */ ! 297: kcclStageSyncHack, /* 9 - 'Hack' */ ! 298: kcclStageStat, /* A - ' Sta' */ ! 299: kcclStageMsgI, /* B - 'MsgI' */ ! 300: kcclStageFree, /* C - 'Free' */ ! 301: kcclStageGood, /* D - 'Good' */ ! 302: kcclStageStop, /* E - '++++' */ ! 303: kcclTerminatorWithoutComma ! 304: }; ! 305: ! 306: /* offsets into the Channel Command List page: */ ! 307: ! 308: #define kcclProblem 0x00 // Interrupt & Stop channel commands for anomalies ! 309: #define kcclCMDOdata 0x20 // reserve for 6, 10, 12 byte commands ! 310: #define kcclMSGOdata 0x30 // reserve for Identify, Tag stuff ! 311: #define kcclMSGOLast 0x3F // reserve for last or only msg0ut byte ! 312: #define kcclMSGIdata 0x40 // reserve for Message In data ! 313: #define kcclBucket 0x48 // Bit Bucket ! 314: #define kcclStatusData 0x4F // reserve for Status byte ! 315: #define kcclSenseCDB 0x50 // CDB for (auto) Sense ! 316: #define kcclBatchSize 0x60 // Current MESH batch size ! 317: #define kcclStageLabel 0x6C // storage for label of last stage entered. ! 318: #define kcclSense 0x70 // Channel Commands for (Auto)Sense ! 319: #define kcclPrototype 0xC0 // Prototype MESH 4-command Transfer sequence ! 320: #define kcclReadBuf8 0x100 // Buffer for non-8-byte-aligned reads ! 321: #define kcclStart 0x120 // Channel Program starts here with Arbitrate ! 322: #define kcclBrProblem 0x140 // channel command to wait for cmdDone & Br if problem ! 323: #define kcclMsgoStage 0x190 // Branch to single byte Message-Out ! 324: #define kcclMsgoBranch 0x1B0 // Branch to single byte Message-Out ! 325: #define kcclMsgoMTC 0x1D8 // MESH Transfer Count for MSGO (low order only) ! 326: #define kcclMsgoDTC 0x1F0 // DMA Transfer Count for MSGO (low order only) ! 327: #define kcclLastMsgo 0x210 // Channel commands to put last/only byte of Message-Out ! 328: #define kcclCmdoStage 0x290 // Start of Command phase ! 329: #define kcclCmdoMTC 0x2C8 // MESH Transfer Count for CMDO (low order only) ! 330: #define kcclCmdoDTC 0x2E0 // DMA Transfer Count for CMDO (low order only) ! 331: #define kcclReselect 0x2F0 // Reselect enters CCL here - Branch to xfer data ! 332: #define kcclOverrun 0x320 // data overrun - dump the excess in the bit bucket ! 333: #define kcclOverrunMESH 0x370 // data overrun - patch the MESH Seq Reg I/O ! 334: #define kcclOverrunDBDMA 0x380 // data overrun - patch the DBDMA I/O ! 335: #define kcclSyncCleanUp 0x3B0 // clean up at end of Sync xfer ! 336: #define kcclGetStatus 0x3D0 // Finish up with Status, Message In, and Bus Free ! 337: #define kcclMESHintr 0x4D0 // transaction done or going well ! 338: #define kcclSenseBuffer 0x500 // Buffer for Autosense data ! 339: #define kcclDataXfer 0x600 // INPUT or OUTPUT channel commands for data ! 340: #define kcclSenseResult 0x63C // Result field in Sense INPUT channel command ! 341: ! 342: ! 343: /* generic relocation types: */ ! 344: ! 345: #define kRelNone 0x00 /* default - no relocation */ ! 346: #define kRelMESH 0x01 /* Relocate to MESH register area */ ! 347: #define kRelCP 0x02 /* Relocate to Channel Program area */ ! 348: #define kRelCPdata 0x03 /* Relocate to Channel Program data structure */ ! 349: #define kRelPhys 0x04 /* Relocate to user Physical address space */ ! 350: #define kRelNoSwap 0x05 /* don't relocate or swap (Label) */ ! 351: ! 352: /* Relocatable ADDRESS types: */ ! 353: ! 354: #define kRelAddress 0xFF <<8 /* relocatable address mask */ ! 355: #define kRelAddressMESH kRelMESH <<8 /* MESH physical address */ ! 356: #define kRelAddressCP kRelCP <<8 /* Channel Program Physical address */ ! 357: #define kRelAddressPhys kRelPhys <<8 /* User data Physical address */ ! 358: ! 359: /* Relocatable COMMAND-DEPENDENT types: */ ! 360: ! 361: #define kRelCmdDep 0xFF /* relocatable command-dependent mask */ ! 362: #define kRelCmdDepCP kRelCP /* Channel Program command-dependent (branch) */ ! 363: #define kRelCmdDepLabel kRelNoSwap /* Channel Program label - don't swap */ ! 364: ! 365: ! 366: /* Channel Program macros: */ ! 367: ! 368: #define STAGE(v) STORE_QUAD | KEY_SYSTEM | 4, kcclStageLabel, v, kRelAddressCP | kRelCmdDepLabel ! 369: #define CLEAR_CMD_DONE STORE_QUAD | KEY_SYSTEM | 1, kMeshInterrupt, kMeshIntrCmdDone, kRelAddressMESH ! 370: #define CLEAR_INT_REG STORE_QUAD | KEY_SYSTEM | 1, kMeshInterrupt, kMeshIntrMask, kRelAddressMESH ! 371: #define CLR_PHASEMM STORE_QUAD | KEY_SYSTEM | 1, kMeshInterrupt, kMeshIntrCmdDone | kMeshIntrException, kRelAddressMESH ! 372: #define MOVE_1(a,v,r) STORE_QUAD | KEY_SYSTEM | 1, a, v, r ! 373: #define MOVE_4(a,v,r) STORE_QUAD | KEY_SYSTEM | 4, a, v, r ! 374: #define MESH_REG(a,v) STORE_QUAD | KEY_SYSTEM | 1, a, v, kRelAddressMESH ! 375: #define MESH_REG_WAIT(a,v) STORE_QUAD | KEY_SYSTEM | kWaitIfTrue | 1, a, v, kRelAddressMESH ! 376: ! 377: #define SENSE(c) INPUT_LAST | kBranchIfFalse | kWaitIfTrue | c, kcclSenseBuffer, kcclProblem, kRelAddressCP | kRelCmdDepCP ! 378: #define MSGO(a,c) OUTPUT_LAST | kBranchIfFalse | kWaitIfTrue | c, a, kcclProblem, kRelAddressCP | kRelCmdDepCP ! 379: #define CMDO(c) OUTPUT_LAST | kBranchIfFalse | kWaitIfTrue | c, kcclCMDOdata, kcclProblem, kRelAddressCP | kRelCmdDepCP ! 380: #define MSGI(c) INPUT_LAST | kBranchIfFalse | kWaitIfTrue | c, kcclMSGIdata, kcclProblem, kRelAddressCP | kRelCmdDepCP ! 381: #define STATUS_IN INPUT_LAST | kBranchIfFalse | kWaitIfTrue | 1, kcclStatusData, kcclProblem, kRelAddressCP | kRelCmdDepCP ! 382: #define BUCKET INPUT_LAST | kBranchIfFalse | 8, kcclBucket, kcclProblem, kRelAddressCP | kRelCmdDepCP ! 383: ! 384: #define BRANCH(a) NOP_CMD | kBranchAlways, 0, a, kRelCmdDepCP ! 385: #define BR_IF_PROBLEM NOP_CMD | kBranchIfFalse | kWaitIfTrue, 0, kcclProblem, kRelCmdDepCP ! 386: #define BR_NO_PROBLEM(a) NOP_CMD | kBranchIfTrue , 0, a, kRelCmdDepCP ! 387: #define STOP(L) STOP_CMD, 0, L, kRelCmdDepLabel ! 388: #define INTERRUPT(a) NOP_CMD | kIntAlways, 0, a, 0 ! 389: #define RESERVE 0xCEFECEFE, 0xCEFECEFE, 0xCEFECEFE, 0xCEFECEFE ! 390: #define WAIT_4_CMDDONE NOP_CMD | kWaitIfTrue, 0, 0, 0 ! 391: ! 392: #define SWAP(x) (UInt32)OSSwapInt32( (UInt32)(x) ) ! 393: ! 394: ! 395: /* Return values from startCommand: */ ! 396: ! 397: enum ! 398: { kHardwareStartOK, /* command started successfully */ ! 399: kHardwareStartBusy ! 400: }; ! 401: ! 402: ! 403: ! 404: /**** THESE NEED TO BE VOLATILE *****/ ! 405: struct DBDMAChannelRegisters /* DBDMA channel registers: */ ! 406: { ! 407: volatile UInt32 channelControl; ! 408: volatile UInt32 channelStatus; ! 409: volatile UInt32 commandPtrHi; /* implementation optional */ ! 410: volatile UInt32 commandPtrLo; ! 411: volatile UInt32 interruptSelect; ! 412: volatile UInt32 branchSelect; ! 413: volatile UInt32 waitSelect; ! 414: volatile UInt32 transferModes; ! 415: volatile UInt32 data2PtrHi; /* implementation optional */ ! 416: volatile UInt32 data2PtrLo; /* implementation optional */ ! 417: ! 418: volatile UInt32 reserved1; ! 419: volatile UInt32 addressHi; /* implementation optional */ ! 420: volatile UInt32 reserved2[4]; ! 421: }; ! 422: typedef struct DBDMAChannelRegisters DBDMAChannelRegisters; ! 423: ! 424: ! 425: struct DBDMADescriptor /* Define the DBDMA Channel Command descriptor. */ ! 426: { ! 427: UInt32 operation; /* cmd | key | i | b | w | reqCount */ ! 428: UInt32 address; ! 429: UInt32 cmdDep; ! 430: UInt32 result; /* xferStatus | resCount */ ! 431: }; ! 432: typedef struct DBDMADescriptor DBDMADescriptor; ! 433: ! 434: /* Define the DBDMA channel command operations and modifiers: */ ! 435: ! 436: enum /* Command.cmd operations */ ! 437: { ! 438: OUTPUT_MORE = 0x00000000, ! 439: OUTPUT_LAST = 0x10000000, ! 440: INPUT_MORE = 0x20000000, ! 441: INPUT_LAST = 0x30000000, ! 442: STORE_QUAD = 0x40000000, ! 443: LOAD_QUAD = 0x50000000, ! 444: NOP_CMD = 0x60000000, ! 445: STOP_CMD = 0x70000000, ! 446: kdbdmaCmdMask = 0xF0000000 ! 447: }; ! 448: ! 449: ! 450: enum ! 451: { /* Command.key modifiers */ ! 452: /* (choose one for INPUT, OUTPUT, LOAD, and STORE) */ ! 453: KEY_STREAM0 = 0x00000000, /* default modifier*/ ! 454: KEY_STREAM1 = 0x01000000, ! 455: KEY_STREAM2 = 0x02000000, ! 456: KEY_STREAM3 = 0x03000000, ! 457: KEY_REGS = 0x05000000, ! 458: KEY_SYSTEM = 0x06000000, ! 459: KEY_DEVICE = 0x07000000, ! 460: kdbdmaKeyMask = 0x07000000, /* Command.i modifiers (choose one for INPUT, OUTPUT, LOAD, STORE, and NOP)*/ ! 461: kIntNever = 0x00000000, /* default modifier */ ! 462: kIntIfTrue = 0x00100000, ! 463: kIntIfFalse = 0x00200000, ! 464: kIntAlways = 0x00300000, ! 465: kdbdmaIMask = 0x00300000, /* Command.b modifiers (choose one for INPUT, OUTPUT, and NOP)*/ ! 466: kBranchNever = 0x00000000, /* default modifier */ ! 467: kBranchIfTrue = 0x00040000, ! 468: kBranchIfFalse = 0x00080000, ! 469: kBranchAlways = 0x000C0000, ! 470: kdbdmaBMask = 0x000C0000, /* Command.w modifiers (choose one for INPUT, OUTPUT, LOAD, STORE, and NOP)*/ ! 471: kWaitNever = 0x00000000, /* default modifier */ ! 472: kWaitIfTrue = 0x00010000, ! 473: kWaitIfFalse = 0x00020000, ! 474: kWaitAlways = 0x00030000, ! 475: kdbdmaWMask = 0x00030000, /* operation masks */ ! 476: }; ! 477: ! 478: ! 479: class meshSCSIController; ! 480: ! 481: typedef struct globals /* Globals for this module (not per instance) */ ! 482: { ! 483: UInt32 evLogFlag; // debugging only ! 484: UInt8 *evLogBuf; ! 485: UInt8 *evLogBufe; ! 486: UInt8 *evLogBufp; ! 487: UInt8 intLevel; ! 488: ! 489: MESHShadow shadow; // move to per instance??? /* Last MESH register state */ ! 490: ! 491: UInt32 cclLogAddr, cclPhysAddr; // for debugging/miniMon ease ! 492: UInt32 meshAddr; // for debugging/miniMon ease ! 493: class meshSCSIController *meshInstance; ! 494: } globals; ! 495: ! 496: ! 497: typedef struct PrivCmdData ! 498: { ! 499: IOMemoryDescriptor *mdp; /* Memory Descriptor Pointer */ ! 500: UInt32 xferCount; ! 501: UInt32 savedDataPosition; /* getPosition at disconnect */ ! 502: SCSIResults results; ! 503: bool isWrite; ! 504: } PrivCmdData; ! 505: ! 506: ! 507: class meshSCSIController : public IOSCSIParallelController ! 508: { ! 509: OSDeclareDefaultStructors( meshSCSIController ) /* Constructor & Destructor stuff */ ! 510: ! 511: protected: ! 512: ! 513: bool configure( IOService *provider, SCSIControllerInfo *controllerDataSize ); ! 514: void executeCommand( IOSCSICommand* ); ! 515: void cancelCommand( IOSCSICommand* ); ! 516: void resetCommand( IOSCSICommand* ); ! 517: void free(); ! 518: ! 519: private: ! 520: ! 521: IOReturn initializeHardware(); ! 522: IOReturn getHardwareMemoryMaps(); ! 523: IOReturn allocHdwAndChanMem(); ! 524: IOReturn doHBASelfTest(); ! 525: void initCP(); ! 526: ! 527: void interruptOccurred( IOInterruptEventSource *ies, int intCount ); ! 528: void doHardwareInterrupt(); ! 529: void processInterrupt(); ! 530: ! 531: UInt8 startCommand(); ! 532: void setupMsgO(); ! 533: void clearCPResults(); ! 534: void updateCP( bool reselecting ); ! 535: void runDBDMA ( UInt32 offset, UInt32 stageLabel ); ! 536: void completeCommand(); ! 537: ! 538: void disconnect(); ! 539: void updateCurrentIndex(); ! 540: void handleReselectionInterrupt(); /* Process a reselection interrupt. */ ! 541: bool getReselectionTargetID(); ! 542: IOReturn reselectNexus(); ! 543: ! 544: /// void initAutosenseCCL(); ! 545: void startBucket(); ! 546: ! 547: void setSeqReg( MeshCommand meshCommand ); ! 548: void getHBARegsAndClear( bool clearInts ); ! 549: void setIntMask( UInt8 interruptMask ); ! 550: IOReturn resetBus(); ! 551: IOReturn waitForMesh( bool clearInterrupts ); ! 552: ! 553: void abortActiveCommand(); ! 554: void abortDisconnectedCommand(); ! 555: ! 556: void doInterruptStageArb(); ! 557: void doInterruptStageSelA(); ! 558: void doInterruptStageMsgO(); ! 559: void doInterruptStageCmdO(); ! 560: void doInterruptStageXfer(); ! 561: /// void doInterruptStageXferAutosense(); ! 562: void doInterruptStageGood(); ! 563: ! 564: IOReturn DoMessageInPhase(); /* Handle MSGI phase. */ ! 565: void ProcessMSGI(); ! 566: ! 567: private: ! 568: ! 569: IOService *fProvider; ! 570: IOSCSICommand *fCmd; ! 571: PrivCmdData *fCmdData; ! 572: IOMemoryMap *fIOMap; ! 573: IOInterruptEventSource *fInterruptEvent; ! 574: ! 575: IOMemoryMap *fSCSIMemoryMap; ! 576: MeshRegister *fMESHAddr; /* MESH registers (logical) */ ! 577: UInt32 fMESHPhysAddr; /* MESH registers (physical) */ ! 578: ! 579: IOMemoryMap *fDBDMAMemoryMap; ! 580: UInt8 *dbdmaAddr; /* DBDMA registers (logical) */ ! 581: IOPhysicalAddress dbdmaAddrPhys; /* DBDMA registers (physical) */ ! 582: ! 583: IOPhysicalAddress fCCLPhysAddr; /* Channel Command List (physical) */ ! 584: UInt8 *fCCL; /* Channel Command List (logical) */ ! 585: UInt32 fCCLSize; /* Channel Command List size */ ! 586: UInt32 fDBDMADescriptorMax; /* max # Channel Commands */ ! 587: ! 588: IOBigMemoryCursor *fMemoryCursor; // pointer to Big-endian memory Cursor ! 589: ! 590: UInt32 fReadAlignmentCount; // hack for DBDMA bug at start of ! 591: UInt32 fReadAlignmentIndex; // Read when buffer is misaligned ! 592: ! 593: SCSITargetLun fCurrentTargetLun; ! 594: UInt32 fTag; /* Last tag value */ ! 595: UInt8 fTagType; /* Last tag type - simple queue... */ ! 596: UInt8 fNegotiatingSDTR; ! 597: UInt8 fSyncParms[ 8 ]; ! 598: ! 599: UInt8 *fMsgOutPtr; /* ptr to message-out data */ ! 600: ! 601: /* These variables manage Message-In bus phase. Because the */ ! 602: /* Message-In handler uses programmed IO, fMsgInCount and */ ! 603: /* fMsgInState are actually local variables to the message */ ! 604: /* reader, and are here for debugging convenience. */ ! 605: ! 606: UInt8 fMsgInBuffer[ 16 ]; ! 607: SInt8 fMsgInCount; /* Message bytes still to read */ ! 608: MsgInState fMsgInState; /* How are we handling messages */ ! 609: ! 610: #define kFlagMsgIn_Reject 0x01 ! 611: #define kFlagMsgIn_Disconnect 0x02 ! 612: UInt8 fMsgInFlag; ! 613: ! 614: #define kFlagMsgOut_SDTR 0x01 ! 615: #define kFlagMsgOut_Queuing 0x02 ! 616: UInt8 fMsgOutFlag; ! 617: ! 618: UInt8 fInitiatorID; /* Our SCSI ID */ ! 619: UInt8 fInitiatorIDMask; /* BusID bitmask for selection */ ! 620: UInt8 fSelectionTimeout; /* In MESH 10 msec units */ ! 621: ! 622: UInt8 fFlagIncompleteDBDMA; /* Need more DMA */ ! 623: UInt8 fFlagReselecting; /* Reselection in progress */ ! 624: ! 625: };/* end class MESH */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.