|
|
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: * Copyright (c) 1994-1996 NeXT Software, Inc. All rights reserved.
27: * Copyright 1997 Apple Computer Inc. All Rights Reserved.
28: * @author Martin Minow mailto:[email protected]
29: * @revision 1997.02.13 Initial conversion from AMDPCSCSIDriver sources.
30: *
31: * Apple96SCSI.h - top-level API for Apple 53C96 (Curio/DBDMA) SCSI adaptor.
32: * Apple96SCSI is closely based on Doug Mitchell's AMD 53C974/79C974 driver.
33: *
34: * Edit History
35: * 1997.02.13 MM Initial conversion from AMDPCSCSIDriver sources.
36: * 1997.03.24 MM Normalized against AppleMeshSCSI.h
37: * 1997.11.12 MM Added support for scatter-gather lists.
38: */
39: #define APPLE96_ALWAYS_ASSERT 0
40: #define APPLE96_ENABLE_GET_SET 1
41: #define VERY_SERIOUS_DEBUGGING 0 /* Log each method entry and exit */
42: #define SERIOUS_DEBUGGING 0 /* Log command, buffer, etc operation */
43: #define LOG_COMMAND_AND_RESULT 0 /* Log command and results */
44: #define LOG_ERROR_RECOVERY 0 /* Log during error recovery */
45: #define LOG_RESULT_ON_ERROR 0 /* Log all errors, even expected ones */
46: #define DUMP_USER_BUFFER 0 /* Set to buffer length to dump */
47: #define TIMESTAMP_AT_IOCOMPLETE 0
48: /*
49: * Radar 2005639. Tell SCSIDisk how many threads to create.
50: */
51: #define MAX_CLIENT_THREADS 1 /* Ask SCSIDisk to create threads */
52: #define ENABLE_DISCONNECT FALSE /* TEMP TEMP TEMP */
53: #define ENABLE_TAGGED_QUEUEING FALSE /* TEMP TEMP TEMP */
54: // #define USE_CURIO_METHODS 1 /* TEMP TEMP TEMP */
55: #define USE_CURIO_METHODS 0 /* Default to inline */
56: #define WRITE_CHIP_OPERATION_INTO_TIMESTAMP_LOG 1
57: #define APPLE96_ENABLE_GET_SET 1 /* Enable management ioctl's */
58: #ifndef VERY_SERIOUS_DEBUGGING
59: #define VERY_SERIOUS_DEBUGGING 0
60: #endif
61: #ifndef USE_CURIO_METHODS
62: #define USE_CURIO_METHODS 0
63: #endif
64: #ifndef WRITE_CHIP_OPERATION_INTO_TIMESTAMP_LOG
65: #define WRITE_CHIP_OPERATION_INTO_TIMESTAMP_LOG 0
66: #endif
67: #ifndef APPLE96_ALWAYS_ASSERT
68: #define APPLE96_ALWAYS_ASSERT 0
69: #endif
70: #if VERY_SERIOUS_DEBUGGING
71: #undef SERIOUS_DEBUGGING
72: #define SERIOUS_DEBUGGING 1
73: #endif
74: #ifndef SERIOUS_DEBUGGING
75: #define SERIOUS_DEBUGGING 0
76: #endif
77: #ifndef LOG_COMMAND_AND_RESULT
78: #define LOG_COMMAND_AND_RESULT 0
79: #endif
80: #ifndef LOG_ERROR_RECOVERY
81: #define LOG_ERROR_RECOVERY 0
82: #endif
83: #ifndef TIMESTAMP_AT_IOCOMPLETE
84: #define TIMESTAMP_AT_IOCOMPLETE 0
85: #endif
86: #ifndef MAX_CLIENT_THREADS
87: #define MAX_CLIENT_THREADS 6 /* Radar 2005639 */
88: #endif
89:
90: #undef NDEBUG /* Enable ASSERT macro */
91:
92: #import <driverkit/IODirectDevice.h>
93: #import <driverkit/IOSCSIController.h>
94: #import <driverkit/scsiTypes.h>
95: #import <driverkit/IOPower.h>
96: #import "Apple96Types.h"
97: #import "Apple96Curio.h"
98: #import "Apple96DBDMADefs.h"
99: #import "Timestamp.h"
100: #import "Apple96DDM.h"
101:
102: @interface Apple96_SCSI : IOSCSIController <IOPower>
103: {
104: /*
105: * These globals locate the hardware interface registers in logical and physical
106: * address spaces.
107: */
108: PhysicalAddress gSCSIPhysicalAddress; /* -> NCR registers (physical) */
109: volatile UInt8 *gSCSILogicalAddress; /* -> NCR registers (logical) */
110: UInt32 gSCSIRegisterLength; /* == Size of NCR registers */
111:
112: PhysicalAddress gDBDMAPhysicalAddress; /* -> DBDMA registers (physical) */
113: DBDMAChannelRegisters *gDBDMALogicalAddress; /* -> DBDMA registers (logical) */
114: UInt32 gDBDMARegisterLength; /* == Size of DBDMA registers */
115:
116: PhysicalAddress gDBDMAChannelAddress; /* -> DBDMA channel area (physical) */
117: DBDMADescriptor *gChannelCommandArea; /* -> DBDMA channel area (logical) */
118: UInt32 gChannelCommandAreaSize; /* == DBDMA channel allocated size */
119: UInt32 gDBDMADescriptorMax; /* Number of DATA descriptors */
120:
121: UInt32 gPageSize; /* Logical page size */
122: UInt32 gPageMask; /* Logical page size - 1 */
123:
124: /*
125: * Autosense I/O requests write into this permanently-allocated area. Then, we copy
126: * the sense data to the caller's SCSI command parameter block. The autosense area
127: * is at the end of the descriptor area.
128: */
129: esense_reply_t *gAutosenseArea; /* -> Autosense area (logical) */
130: PhysicalAddress gAutosenseAddress; /* Used to autosense DMA */
131:
132: /*
133: * This is the message port that the kernel uses to signal hardware interrupts.
134: */
135: port_t gKernelInterruptPort;
136:
137: /*
138: * Commands are passed from exported methods to the I/O thread
139: * via gIncomingCommandQueue, which is protected by gIncomingCommandLock.
140: *
141: * Commands which are disconnected but not complete are kept
142: * in gDisconnectedCommandQueue.
143: *
144: * Commands which have been dequeued from gIncomingCommandQueue by the
145: * I/O thread but which have not been started because a command is currently
146: * active on the bus are kept in gPendingCommandQueue. This queue also
147: * holds commands pushed back when we lose arbitration.
148: *
149: * The currently active command, if any, is kept in gActiveCommand.
150: * Only commandBufs with op == kCommandExecute are ever placed in
151: * gActiveCommand.
152: */
153: queue_head_t gIncomingCommandQueue;
154: id gIncomingCommandLock; /* NXLock for gIncomingCommandQueue */
155: queue_head_t gPendingCommandQueue;
156: queue_head_t gDisconnectedCommandQueue;
157: /*
158: * This is the command we're currently execution. If NULL, the Macintosh is idle
159: * (or all commands are disconnected). Normally, gCurrentTarget and gCurrentLUN
160: * track the values in the active command's associated SCSI request. They are set
161: * to kInvalidTarget and kInvalidLUN at initialization, command deactivation,
162: * command complete, and command disconnect. They are set to valid values (with no
163: * active command) during reselection. This is tricky, so look carefully at the code.
164: */
165: CommandBuffer *gActiveCommand; /* -> The currently executing command */
166: UInt32 gCurrentTarget; /* == The current target bus ID */
167: UInt32 gCurrentLUN; /* == The current target LUN */
168:
169: /*
170: * Global option flags, accessible via instance table or setIntValues. Note: some of
171: * these are intended for debugging. However, users may need to disable command
172: * queuing, synchronous, or fast to handle device or bus limitations. The
173: * architecture-specific initialization "looks" at the device to determine whether
174: * specific features (such as synchronous) are supported.
175: * gOptionAutoSenseEnable Debug only, normally set
176: * gOptionCmdQueueEnable Enable tagged queuing.
177: * gOptionSyncModeEnable Enable synchronous transfers (clear if problems)
178: * gOptionFastModeEnable Enable fast transfers (clear if problems)
179: * gOptionDisconnectEnable Debug only, normally set.
180: * gOptionExtendTiming Extended selection timing (debug, unused)
181: * gOptionSyncModeSupportedByHardware Set if this NCR chip supports synchronous.
182: * gOptionFastModeSupportedByHardware Set if this NCR chip supports fast mode.
183: * gFlagIOThreadRunning Set when I/O thread is initialized. Needed
184: * for shutdown.
185: * gFlagBusBusy Set in the state machine when we are apparently
186: * connected to a target (even for target selection).
187: * Cleared in the interrupt service routine on
188: * a disconnected or bus reset interrupt state.
189: * gFlagCheckForAnotherInterrupt Set in the interrupt service routine on
190: * entrance to the bus finite-state automaton.
191: * Automaton functions clear this to force an
192: * exit from the ISR when it expects a long bus
193: * operation.
194: */
195: unsigned gOptionAutoSenseEnable : 1,
196: gOptionCmdQueueEnable : 1,
197: gOptionSyncModeEnable : 1,
198: gOptionFastModeEnable : 1,
199: gOptionExtendTiming : 1,
200: gOptionDisconnectEnable : 1,
201: gOptionSyncModeSupportedByHardware : 1,
202: gOptionFastModeSupportedByHardware : 1,
203: gFlagIOThreadRunning : 1, /* Set at init */
204: gFlagBusBusy : 1,
205: gFlagCheckForAnotherInterrupt : 1, /* Loop through ISR */
206: gFlagNeedAnotherInterrupt : 1, /* mikej */
207: pad : 20;
208: UInt32 scsiClockRate; /* in MHz */
209:
210: /*
211: * Array of active I/O counters, one counter per lun per target. If command
212: * queueing is disabled, the max value of each counter is 1. gActiveCount is
213: * the sum of all elements in activeArray.
214: */
215: UInt8 gActiveArray[SCSI_NTARGETS][SCSI_NLUNS];
216: UInt32 gActiveCount;
217:
218: /*
219: * These variables change during SCSI I/O operation.
220: */
221: BusState gBusState; /* The overall state automaton */
222: /*
223: * These variables manage Message In bus phase. Because the message in handler
224: * uses programmed I/O, gMsgInCount, gMsgInIndex, and gMsgInState are actually
225: * local variables to the message reader, and are here for debugging convenience.
226: */
227: signed int gMsgInCount; /* Message bytes still to read */
228: MsgInState gMsgInState; /* How are we handling messages */
229: UInt32 gMsgInIndex; /* -> free spot in gMsgInBuffer */
230: UInt8 gMsgInBuffer[kMessageInBufferLength];
231: /*
232: * These variables manage Message Out bus phase. To send a message,
233: * write it into the buffer, starting at gMsgOutSendIndex and set ATN.
234: * When the target enters Message Out phase, write the bytes into the
235: * NCR fifo starting at gMsgOutStoreIndex. When the transfer completes
236: * with MSG parity error, use the residual count to "back up" gMsgOutSendIndex
237: * to resend the message.
238: */
239: UInt8 *gMsgOutPtr; /* -> free spot in gMsgOutBuffer */
240: UInt8 *gMsgPutPtr; /* -> next byte to send */
241: UInt8 gMsgOutBuffer[kMessageOutBufferLength];
242: UInt8 gLastMsgOut[2]; /* Has last message out specifier */
243: /*
244: * Hardware related variables
245: */
246: UInt8 gInitiatorID; /* Our SCSI ID */
247: UInt8 gInitiatorIDMask; /* BusID bitmask for selection */
248: // UInt8 gSelectionTimeout; /* In MESH 10 msec units */
249: UInt32 gClockFrequency; /* For selection timeout */
250:
251: /*
252: * commandBuf->queueTag for next I/O. This is never zero; for all requests
253: * involving a T/L/Q nexus, a queue tag of zero indicates a nontagged command.
254: */
255: UInt8 gNextQueueTag;
256:
257: /*
258: * Shadow current chip values.
259: * gSaveStatus rSTA register at last interrupt.
260: * gSaveSeqStep rSQS register at last interrupt
261: * gSaveInterrupt rINT register at last interrupt.
262: * gCurrentBusPhase The last bus phase (for error recovery)
263: * gLastSelectionTimeout Last selection timeout we stored in Curio
264: * gLastSynchronousOffset Last synchronous offset we stored in Curio.
265: * gLastSynchronousPeriod Last synchronous perioud we stored in Curio.
266: */
267: UInt8 gSaveStatus;
268: UInt8 gSaveSeqStep;
269: UInt8 gSaveInterrupt;
270: UInt8 gCurrentBusPhase; /* Last known SCSI phase */
271: UInt8 gLastSelectionTimeout; /* Chip selection timeout */
272: UInt8 gLastSynchronousOffset; /* Synchronous transfer offset */
273: UInt8 gLastSynchronousPeriod; /* Synchronous period shadow */
274: /*
275: * Per-target information.
276: */
277: PerTargetData gPerTargetData[SCSI_NTARGETS];
278:
279: /*
280: * Statistics support.
281: */
282: UInt32 gMaxQueueLen;
283: UInt32 gQueueLenTotal;
284: UInt32 gTotalCommands;
285: }
286:
287: /**
288: * Public methods
289: */
290: /**
291: * Initialize the SCSI driver.
292: */
293: + (Boolean) probe : deviceDescription;
294: /**
295: * Shutdown the driver.
296: */
297: - free;
298:
299: /*
300: * Execute a SCSI request using a single logical address range.
301: * This is compatible with earlier DriverKit implementations.
302: * @param scsiReq The SCSI request command record, including the
303: * target device and LUN, the command to execute,
304: * and various control flags.
305: * @param buffer The data buffer, if any. This may be NULL if
306: * no data phase is expected.
307: * @param client The client task that "owns" the memory buffer.
308: * @return Return a bus adaptor specific error status.
309: */
310: - (sc_status_t) executeRequest : (IOSCSIRequest *) scsiReq
311: buffer : (void *) buffer
312: client : (vm_task_t) client;
313:
314: /*
315: * Execute a SCSI request using an IOMemoryDescriptor. This allows callers to
316: * provide (kernel-resident) logical scatter-gather lists. For compatibility
317: * with existing implementations, the low-level SCSI device driver must first
318: * ensure that executeRequest:ioMemoryDescriptor is supported by executing:
319: * [controller respondsToSelector : executeRequest:ioMemoryDescriptor]
320: * @param scsiReq The SCSI request command record, including the
321: * target device and LUN, the command to execute,
322: * and various control flags.
323: * @param ioMemoryDescriptor The data buffer(s), if any. This may be NULL if
324: * no data phase is expected.
325: * @param client The client task that "owns" the memory buffer.
326: * @return Return a bus adaptor specific error status.
327: */
328: - (sc_status_t) executeRequest
329: : (IOSCSIRequest *) scsiReq
330: ioMemoryDescriptor : (IOMemoryDescriptor *) ioMemoryDescriptor;
331:
332: - (sc_status_t) resetSCSIBus;
333:
334: /**
335: * Reset the SCSI bus.
336: */
337: - (sc_status_t) resetSCSIBus;
338: /**
339: * Reset statistics buffers.
340: */
341: - (void) resetStats;
342:
343: - (unsigned) numQueueSamples;
344:
345: - (unsigned) sumQueueLengths;
346:
347: - (unsigned) maxQueueLength;
348:
349: /**
350: * interruptOccurred is a public method called by the I/O
351: * thread in IODirectDevice when an interrupt occurs.
352: */
353: - (void) interruptOccurred;
354:
355: /**
356: * timeoutOccurred is a public method called by the I/O
357: * thread in IODirectDevice when it receives a timeout
358: * message.
359: */
360: - (void) timeoutOccurred;
361:
362: #if APPLE96_ENABLE_GET_SET
363:
364: - (IOReturn) setIntValues : (unsigned *)parameterArray
365: forParameter : (IOParameterName)parameterName
366: count : (unsigned)count;
367: - (IOReturn) getIntValues : (unsigned *)parameterArray
368: forParameter : (IOParameterName)parameterName
369: count : (unsigned *)count; // in/out
370: /*
371: * get/setIntValues parameters.
372: */
373: #define APPLE96_AUTOSENSE "AutoSense"
374: #define APPLE96_CMD_QUEUE "CmdQueue"
375: #define APPLE96_SYNC "Synchronous"
376: #define APPLE96_FAST_SCSI "FastSCSI"
377: #define APPLE96_RESET_TARGETS "ResetTargets"
378: #define APPLE96_RESET_TIMESTAMP "ResetTimestamp"
379: #define APPLE96_ENABLE_TIMESTAMP "EnableTimestamp"
380: #define APPLE96_DISABLE_TIMESTAMP "DisableTimestamp"
381: #define APPLE96_PRESERVE_FIRST_TIMESTAMP "PreserveFirstTimestamp"
382: #define APPLE96_PRESERVE_LAST_TIMESTAMP "PreserveLastTimestamp"
383: #define APPLE96_READ_TIMESTAMP "ReadTimestamp"
384: #define APPLE96_STORE_TIMESTAMP "StoreTimestamp"
385: /*
386: * Radar 2005639. Tell SCSIDisk how many threads to create.
387: * Allow access to the enable disconnect option.
388: */
389: #define APPLE96_ENABLE_DISCONNECT "EnableDisconnect"
390: #define APPLE_MAX_THREADS "ClientThreads"
391:
392: /*
393: * Recording and setting timestamps may be done using getIntValues (this permits
394: * access from non-privileged tasks.
395: * ResetTimestamp Clear the timestamp vector - do this before starting
396: * a sequence (no parameters)
397: * EnableTimestamp Start recording (no parameters) (default)
398: * DisableTimestamp Stop recording (no parameters)
399: * PreserveFirstTimestamp Stop recording when the buffer fills (until it is emptied)
400: * PreserveLastTimestamp Discard old values when new arrive (default)
401: * ReadTimestamp Read a vector of timestamps (see sample below)
402: * StoreTimestamp Store a timestamp (from user mode) (see sample below)
403: * ReadTimestamp copies timestamps from the internal database to user-specified vector.
404: * Because getIntValues parameters are defined in int units, the code is slighthly
405: * non-obvious:
406: * TimestampDataRecord myTimestamps[123];
407: * unsigned count;
408: * count = sizeof (myTimestamps) / sizeof (unsigned);
409: * [scsiDevice getIntValues
410: * : (unsigned int *) myTimestamps
411: * forParameter : APPLE96_READ_TIMESTAMP
412: * count : &count
413: * ];
414: * count = (count * sizeof (unsigned)) / sizeof (TimestampDataRecord);
415: * for (i = 0; i < count; i++) {
416: * Process(myTimestamps[i]);
417: * }
418: * Applications can store timestamps using one of three parameter formats:
419: * unsigned paramVector[4];
420: * Tag only -- the library will supply the event time
421: * paramVector[0] = kMyTagValue;
422: * [scsiDevice getIntValues
423: * : paramVector
424: * forParameter : "StoreTimestamp"
425: * count : 1
426: * ];
427: * Tag plus value:
428: * paramVector[0] = kMyTagValue;
429: * paramVector[1] = 123456;
430: * [scsiDevice getIntValues
431: * : paramVector
432: * forParameter : "StoreTimestamp"
433: * count : 2
434: * ];
435: * Tag plus value + time:
436: * paramVector[0] = kMyTagValue;
437: * paramVector[1] = 123456;
438: * IOGetTimestamp((ns_time_t *) ¶mVector[2]);
439: * [scsiDevice getIntValues
440: * : paramVector
441: * forParameter : "StoreTimestamp"
442: * count : 4
443: * ];
444: * Note that you can combine tag only with tag plus value plus time to measure
445: * user->device latency.
446: */
447:
448: #endif /* APPLE96_ENABLE_GET_SET */
449:
450: @end
451:
452:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.