|
|
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*)¶mVector[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 /* )) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.