|
|
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.18 Initial conversion from AMDPCSCSIDriver sources.
30: *
31: * Apple96SCSI.h - "Main" public methods for the 53C96 PCI SCSI interface.
32: * Apple96SCSI is closely based on Doug Mitchell's AMD 53C974/79C974 driver.
33: *
34: * Hmm, these methods are probably common to all SCSI implementations.
35: *
36: * Edit History
37: * 1998.07.29 MM Disable logRegisters on command timeout.
38: * 1997.02.13 MM Initial conversion from AMDPCSCSIDriver sources.
39: * 1997.11.12 MM Added support for scatter-gather lists.
40: */
41: #import "Apple96SCSI.h"
42: #import "Apple96SCSIPrivate.h"
43: #import "Apple96CurioPrivate.h"
44: #import "Apple96CurioPublic.h"
45: #import "Apple96CurioDBDMA.h"
46: #import "Apple96Hardware.h"
47: #import "Apple96HWPrivate.h"
48: #import "Apple96ISR.h"
49: #import "bringup.h"
50: #import <mach/message.h>
51: #import <driverkit/generalFuncs.h>
52: #import <driverkit/interruptMsg.h>
53: #import <driverkit/align.h>
54: #import <driverkit/kernelDriver.h>
55: #import <kernserv/prototypes.h>
56: #import <driverkit/IOSimpleMemoryDescriptor.h>
57: /* string.h defines bzero */
58: #import <string.h>
59:
60:
61: @implementation Apple96_SCSI
62:
63: /*
64: * Create and initialize one instance of Apple96_SCSI. The work is done by
65: * architecture- and chip-specific modules.
66: */
67: + (Boolean) probe : deviceDescription
68: {
69: Apple96_SCSI *inst = [self alloc];
70: Boolean result;
71:
72: ENTRY("Spr probe");
73: MakeTimestampRecord(512); /* TBS: contitionally compile */
74: /*
75: * Perform device-specific initialization -- free the instance
76: * on failure.
77: */
78: if ([inst hardwareInitialization : deviceDescription] == nil) {
79: result = NO;
80: }
81: else {
82: result = YES;
83: }
84: RESULT(result);
85: return (result);
86: }
87:
88: - free
89: {
90: CommandBuffer cmdBuf;
91:
92: ENTRY("Sfr free");
93: /*
94: * First kill the I/O thread if running.
95: */
96: if (gFlagIOThreadRunning) {
97: cmdBuf.op = kCommandAbortRequest;
98: cmdBuf.scsiReq = NULL;
99: [self executeCmdBuf:&cmdBuf];
100: }
101: if (gIncomingCommandLock != NULL) {
102: [gIncomingCommandLock free];
103: }
104: [self dbdmaTerminate]; /* Free up DBDMA memory */
105: EXIT();
106: return [super free];
107: }
108:
109:
110: /*
111: * Return required DMA alignment for current architecture.
112: */
113: - (void)getDMAAlignment : (IODMAAlignment *)alignment;
114: {
115: alignment->readStart = DBDMA_ReadStartAlignment;
116: alignment->writeStart = DBDMA_WriteStartAlignment;
117: alignment->readLength = DBDMA_ReadLengthAlignment;
118: alignment->writeLength = DBDMA_WriteLengthAlignment;
119: }
120:
121: /*
122: * Statistics support.
123: */
124: - (unsigned int) numQueueSamples
125: {
126: return (gTotalCommands);
127: }
128:
129:
130: - (unsigned int) sumQueueLengths
131: {
132: return (gQueueLenTotal);
133: }
134:
135:
136: - (unsigned int) maxQueueLength
137: {
138: return (gMaxQueueLen);
139: }
140:
141:
142: - (void)resetStats
143: {
144: gTotalCommands = 0;
145: gQueueLenTotal = 0;
146: gMaxQueueLen = 0;
147: }
148:
149: /**
150: * Do a SCSI command, as specified by an IOSCSIRequest. All the
151: * work is done by the I/O thread.
152: * @param scsiReq The request to execute
153: * @param buffer The data buffer to transfer to/from, if any
154: * @param client The data buffer owner task (for VM munging)
155: *
156: * This method is called from IOSCSIDevice
157: */
158: - (sc_status_t) executeRequest
159: : (IOSCSIRequest *) scsiReq
160: buffer : (void *) buffer
161: client : (vm_task_t) client
162: {
163: IOMemoryDescriptor *mem = NULL;
164: sc_status_t scsiStatus = SR_IOST_GOOD; /* Fool compiler */
165:
166: ENTRY("Ser executeRequest");
167: /*
168: * Create a simple I/O memory descriptor for this client,
169: * then toss it to the common method.
170: */
171: if (buffer != NULL) {
172: mem = [[IOSimpleMemoryDescriptor alloc]
173: initWithAddress : (void *) buffer
174: length : scsiReq->maxTransfer
175: ];
176: [mem setClient : client];
177: }
178: scsiStatus = [self executeRequest
179: : scsiReq
180: ioMemoryDescriptor : mem
181: ];
182: if (mem != NULL) {
183: [mem release];
184: }
185: RESULT(scsiReq->bytesTransferred);
186: return (scsiStatus);
187: }
188:
189: /*
190: * Execute a SCSI request using an IOMemoryDescriptor. This allows callers to
191: * provide (kernel-resident) logical scatter-gather lists. For compatibility
192: * with existing implementations, the low-level SCSI device driver must first
193: * ensure that executeRequest:ioMemoryDescriptor is supported by executing:
194: * [controller respondsToSelector : executeRequest:ioMemoryDescriptor]
195: */
196: - (sc_status_t) executeRequest
197: : (IOSCSIRequest *) scsiReq
198: ioMemoryDescriptor : (IOMemoryDescriptor *) ioMemoryDescriptor
199: {
200: CommandBuffer commandBuffer;
201:
202: ENTRY("Sem executeRequest (IOMemoryDescriptor)");
203: TAG("Ser", scsiReq->maxTransfer);
204: ddmExported("executeRequest: cmdBuf 0x%x maxTransfer 0x%x\n",
205: &commandBuffer,
206: scsiReq->maxTransfer,
207: 3,4,5
208: );
209: if (ioMemoryDescriptor != NULL) {
210: [ioMemoryDescriptor setMaxSegmentCount : kMaxDMATransfer];
211: [ioMemoryDescriptor state : &commandBuffer.savedDataState];
212: }
213: bzero(&commandBuffer, sizeof(CommandBuffer));
214: commandBuffer.op = kCommandExecute;
215: commandBuffer.scsiReq = scsiReq;
216: commandBuffer.mem = ioMemoryDescriptor;
217: scsiReq->driverStatus = SR_IOST_INVALID; /* "In progress" */
218: [self executeCmdBuf : &commandBuffer];
219: ddmExported("executeRequest: cmdBuf 0x%x complete; driverStatus %s\n",
220: &commandBuffer,
221: IOFindNameForValue(scsiReq->driverStatus, IOScStatusStrings),
222: 3,4,5
223: );
224: RESULT(commandBuffer.scsiReq->bytesTransferred);
225: #if TIMESTAMP_AT_IOCOMPLETE
226: [self logTimestamp : "I/O complete"]; /* After RETURN macro */
227: #endif
228: return (commandBuffer.scsiReq->driverStatus);
229: }
230:
231: /**
232: * Reset the SCSI bus. All the work is done by the I/O thread.
233: */
234: - (sc_status_t) resetSCSIBus
235: {
236: CommandBuffer commandBuffer;
237:
238: ENTRY("Sre resetSCSIBus");
239: ddmExported("resetSCSIBus: cmdBuf 0x%x\n",
240: &commandBuffer,
241: 2, 3,4,5
242: );
243:
244: commandBuffer.op = kCommandResetBus;
245: commandBuffer.scsiReq = NULL;
246:
247: [self executeCmdBuf:&commandBuffer];
248: ddmExported("resetSCSIBus: cmdBuf 0x%x DONE\n",
249: &commandBuffer,
250: 2, 3,4,5
251: );
252: RESULT(SR_IOST_GOOD);
253: return (SR_IOST_GOOD); /* can not fail */
254: }
255:
256: /*
257: * The following 6 methods are all called from the I/O thread in IODirectDevice.
258: */
259:
260: /*
261: * Called from the I/O thread when it receives an interrupt message.
262: * Currently all work is done by chip-specific module; maybe we should
263: * put this method there....
264: */
265: - (void) interruptOccurred
266: {
267: ENTRY("Sin interruptOccurred");
268: /*
269: * Note: the following compiles because ENTRY ends with "do {"
270: */
271: #if DDM_DEBUG
272: {
273: /*
274: * calculate interrupt service time if enabled.
275: */
276: ns_time_t startTime;
277: unsigned elapsedNSec = 0;
278:
279: if (IODDMMasks[APPLE96_DDM_INDEX] & DDM_INTR) {
280: IOGetTimestamp(&startTime);
281: }
282: ddmInterrupt("interruptOccurred: TOP\n", 1,2,3,4,5);
283: #endif DDM_DEBUG
284: [self hardwareInterrupt];
285: #if DDM_DEBUG
286: if (IODDMMasks[APPLE96_DDM_INDEX] & DDM_INTR) {
287: ns_time_t endTime;
288:
289: IOGetTimestamp(&endTime);
290: elapsedNSec = (unsigned) (endTime - startTime);
291: }
292: ddmInterrupt("interruptOccurred: DONE; elapsed time %d.%03d us\n",
293: elapsedNSec / 1000U,
294: elapsedNSec - ((elapsedNSec / 1000U) * 1000U),
295: 3,4,5
296: );
297: }
298: #endif DDM_DEBUG
299: // [self enableInterrupt:0];
300: // [self enableAllInterrupts ];
301: EXIT();
302: }
303:
304: /*
305: * These three should not occur; they are here as error traps. All three are
306: * called out from the I/O thread upon receipt of messages which it should
307: * not be seeing.
308: */
309: - (void)interruptOccurredAt:(int)localNum
310: {
311: IOLog("%s: interruptOccurredAt:%d\n", [self name], localNum);
312: }
313:
314: - (void)otherOccurred:(int)id
315: {
316: IOLog("%s: otherOccurred:%d\n", [self name], id);
317: }
318:
319: - (void)receiveMsg
320: {
321: IOLog("%s: receiveMsg\n", [self name]);
322:
323: /*
324: * We have to let IODirectDevice take care of this (i.e., dequeue the
325: * bogus message).
326: */
327: [super receiveMsg];
328: }
329:
330: /*
331: * Used in -timeoutOccurred to determine if specified cmdBuf has timed out.
332: * Returns YES if timeout, else NO.
333: */
334: static inline Boolean
335: isCmdTimedOut(
336: CommandBuffer *cmdBuf,
337: ns_time_t now
338: )
339: {
340: IOSCSIRequest *scsiReq;
341: ns_time_t expire;
342: Boolean result;
343:
344: ENTRY("Sit isCmdTimedOut");
345: scsiReq = cmdBuf->scsiReq;
346: expire = cmdBuf->startTime +
347: (1000000000ULL * (unsigned long long) scsiReq->timeoutLength);
348: result = (now > expire);
349: #if 0
350: if (result) {
351: IOLog("%s: command timeout, target %d exceeded %d\n"
352: "drvApple96SCSI", /* Can't use [self name] here */
353: (int) scsiReq->target,
354: (int) scsiReq->timeoutLength
355: );
356: }
357: #endif
358: RESULT(result);
359: return (result);
360: }
361:
362: /*
363: * Called from the I/O thread when it receives a timeout
364: * message. We send these messages ourself from serviceTimeoutInterrupt().
365: */
366: - (void) timeoutOccurred
367: {
368: ns_time_t now;
369: Boolean cmdTimedOut = NO;
370: CommandBuffer *cmdBuf = gActiveCommand;
371: CommandBuffer *nextCmdBuf;
372:
373: ENTRY("Sto timeoutOccurred");
374: ddmThread("timeoutOccurred: TOP\n", 1,2,3,4,5);
375: IOGetTimestamp(&now);
376: #if 0 /* Disable. Part of Radar 2261237 */
377: [self logRegisters : TRUE reason : "TimeoutOccurred"];
378: #endif /* Disable. Part of Radar 2261237 */
379: // ** ** **
380: // ** ** ** Umm, is there a race-condition here? Can gActiveCommand be changed
381: // ** ** ** out from under us by an interrupt or does the O.S. ensure that
382: // ** ** ** these methods are single-threaded? Also, note that the bus
383: // ** ** ** is likely to be stuck if there is a very slow device
384: // ** ** ** such as a Format or Tape Rewind ongoing. This needs to be
385: // ** ** ** updated to use the Copland (and/or SCSI Manager 4.3) algorithms.
386: // ** ** **
387: /*
388: * Scan gActiveCommand and disconnectQ looking for tardy I/Os.
389: */
390: if (cmdBuf != NULL) {
391: if (isCmdTimedOut(cmdBuf, now)) {
392: ddmThread("gActiveCommand TIMEOUT, cmd 0x%x\n",
393: cmdBuf, 2,3,4,5);
394: gActiveCommand = NULL;
395: /*
396: * ** ** ** Umm, what about abort commands?
397: */
398: ASSERT(cmdBuf->scsiReq != NULL);
399: [self ioComplete
400: : cmdBuf
401: finalStatus : SR_IOST_IOTO
402: ];
403: cmdTimedOut = YES;
404: }
405: }
406: /*
407: * ** ** **
408: * ** ** ** Umm, disconnected commands should timeout only
409: * ** ** ** when the bus is idle. Otherwise, we can timeout
410: * ** ** ** a command whose only fault is that other commands
411: * ** ** ** saturated the bus.
412: */
413: cmdBuf = (CommandBuffer *) queue_first(&gDisconnectedCommandQueue);
414: while (queue_end(&gDisconnectedCommandQueue, (queue_entry_t) cmdBuf) == 0) {
415: if (isCmdTimedOut(cmdBuf, now)) {
416: ddmThread("disconnected cmd timeout, cmd 0x%x\n", cmdBuf, 2,3,4,5);
417:
418: /*
419: * Remove cmdBuf from disconnectQ and complete it.
420: */
421: nextCmdBuf = (CommandBuffer *) queue_next(&cmdBuf->link);
422: queue_remove(&gDisconnectedCommandQueue, cmdBuf, CommandBuffer *, link);
423: ASSERT(cmdBuf->scsiReq != NULL);
424: [self ioComplete
425: : cmdBuf
426: finalStatus : SR_IOST_IOTO
427: ];
428: cmdBuf = nextCmdBuf;
429: cmdTimedOut = YES;
430: }
431: else {
432: cmdBuf = (CommandBuffer *) queue_next(&cmdBuf->link);
433: }
434: }
435: /*
436: * ** ** **
437: * ** ** ** This is a really big hammer -- and will cause problems
438: * ** ** ** with tape drives. It may also cause data loss.
439: * ** ** **
440: * Reset bus. This also completes all I/Os in disconnectQ with
441: * status CS_Reset.
442: */
443: if (cmdTimedOut) {
444: [self logRegisters : TRUE reason : "Command timeout"];
445: [self threadResetBus:NULL];
446: }
447: ddmThread("timeoutOccurred: DONE\n", 1,2,3,4,5);
448: EXIT();
449: }
450:
451: /*
452: * Process all commands in gIncomingCommandQueue. At most one of these will become
453: * gActiveCommand. The remainder of kCommandExecute commands go to gPendingCommandQueue. Other
454: * types of commands (such as bus reset) are executed immediately.
455: *
456: * This method is called from IODirectDevice.
457: * ** ** **
458: * ** ** ** Note that we don't have a concept of frozen queue.
459: * ** ** **
460: */
461: - (void) commandRequestOccurred
462: {
463: CommandBuffer *cmdBuf;
464: CommandBuffer *pendCmd;
465:
466: ENTRY("Sco commandRequestOccurred");
467: ddmThread("commandRequestOccurred: top\n", 1,2,3,4,5);
468: [gIncomingCommandLock lock];
469: while (queue_empty(&gIncomingCommandQueue) == FALSE) {
470: cmdBuf = (CommandBuffer *) queue_first(&gIncomingCommandQueue);
471: queue_remove(&gIncomingCommandQueue, cmdBuf, CommandBuffer *, link);
472: [gIncomingCommandLock unlock];
473: switch (cmdBuf->op) {
474: case kCommandResetBus:
475: /*
476: * Note all active and disconnected commands will
477: * be terminted.
478: */
479: [self threadResetBus : "Reset Command Received"];
480: [self ioComplete
481: : cmdBuf
482: finalStatus : SR_IOST_RESET
483: ];
484: break;
485: case kCommandAbortRequest:
486: /*
487: * 1. Abort all active, pending, and disconnected
488: * commands.
489: * 2. Notify caller of completion.
490: * 3. Self-terminate.
491: */
492: [self abortAllCommands : SR_IOST_INT];
493: pendCmd = (CommandBuffer *) queue_first(&gPendingCommandQueue);
494: while (queue_end(&gPendingCommandQueue, (queue_entry_t) pendCmd) == FALSE) {
495: [self ioComplete
496: : pendCmd
497: finalStatus : SR_IOST_INT
498: ];
499: pendCmd = (CommandBuffer *) queue_next(&pendCmd->link);
500: }
501: [cmdBuf->cmdLock lock];
502: [cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
503: ddmEntry("-Method: commandRequestOccurred", 1, 2, 3, 4, 5);
504: IOExitThread();
505: /* not reached */
506: case kCommandExecute:
507: [self threadExecuteRequest:cmdBuf];
508: break;
509:
510: }
511: [gIncomingCommandLock lock];
512: }
513: [gIncomingCommandLock unlock];
514: ddmThread("commandRequestOccurred: DONE\n", 1,2,3,4,5);
515: EXIT();
516: }
517:
518:
519: /*
520: * Power management methods. All we care about is power off, when we must
521: * reset the SCSI bus due to the Compaq BIOS's lack of a SCSI reset, which
522: * causes a hang if we have set up targets for sync data transfer mode.
523: */
524: - (IOReturn) getPowerState : (PMPowerState *) state_p
525: {
526: ddmExported("getPowerState called\n", 1,2,3,4,5);
527: return IO_R_UNSUPPORTED;
528: }
529:
530: - (IOReturn) setPowerState : (PMPowerState) state
531: {
532: #ifdef DEBUG
533: IOLog("%s: received setPowerState: with %x\n", [self name],
534: (unsigned)state);
535: #endif DEBUG
536: if (state == PM_OFF) {
537: // [self scsiReset];
538: // ** ** ** TBS: [self powerDown];
539: return IO_R_SUCCESS;
540: }
541: return IO_R_UNSUPPORTED;
542: }
543:
544: - (IOReturn) getPowerManagement : (PMPowerManagementState *) state_p
545: {
546: ddmExported("getPowerManagement called\n", 1,2,3,4,5);
547: return IO_R_UNSUPPORTED;
548: }
549:
550: - (IOReturn) setPowerManagement : (PMPowerManagementState) state
551: {
552: ddmExported("setPowerManagement called\n", 1,2,3,4,5);
553: return IO_R_UNSUPPORTED;
554: }
555:
556: #if APPLE96_ENABLE_GET_SET
557:
558: /**
559: * Called by clients (and user-interaction) to configure the device.
560: */
561: - (IOReturn) setIntValues
562: : (unsigned *) parameterArray
563: forParameter : (IOParameterName) parameterName
564: count : (unsigned int) count
565: {
566: IOReturn ioReturn = IO_R_INVALID_ARG;
567:
568: /* Radar 1670762 ENTRY("Ssi setIntValues"); */
569: ddmExported("setIntValues %s, count %u\n",
570: parameterName,
571: count,
572: 3, 4, 5
573: );
574: if (strcmp(parameterName, APPLE96_AUTOSENSE) == 0) {
575: if (count == 1) {
576: gOptionAutoSenseEnable = (parameterArray[0] ? 1 : 0);
577: IOLog("%s: autoSense %s\n", [self name],
578: (gOptionAutoSenseEnable ? "Enabled" : "Disabled"));
579: ioReturn = IO_R_SUCCESS;
580: }
581: }
582: else if (strcmp(parameterName, APPLE96_ENABLE_DISCONNECT) == 0) { /* Radar 2005639 */
583: if (count == 1) {
584: gOptionDisconnectEnable = (parameterArray[0] ? 1 : 0);
585: IOLog("%s: disconnect %s\n", [self name],
586: (gOptionDisconnectEnable ? "Enabled" : "Disabled"));
587: ioReturn = IO_R_SUCCESS;
588: }
589: }
590: else if (strcmp(parameterName, APPLE96_CMD_QUEUE) == 0) {
591: if (count == 1) {
592: gOptionCmdQueueEnable = (parameterArray[0] ? 1 : 0);
593: IOLog("%s: cmdQueue %s\n", [self name],
594: (gOptionCmdQueueEnable ? "Enabled" : "Disabled"));
595: ioReturn = IO_R_SUCCESS;
596: }
597: }
598: else if (strcmp(parameterName, APPLE96_SYNC) == 0) {
599: if (count == 1) {
600: gOptionSyncModeEnable = (parameterArray[0] ? 1 : 0);
601: IOLog("%s: syncMode %s\n", [self name],
602: (gOptionSyncModeEnable ? "Enabled" : "Disabled"));
603: ioReturn = IO_R_SUCCESS;
604: }
605: }
606: else if (strcmp(parameterName, APPLE96_FAST_SCSI) == 0) {
607: if (count == 1) {
608: gOptionFastModeEnable = (parameterArray[0] ? 1 : 0);
609: IOLog("%s: fastMode %s\n", [self name],
610: (gOptionFastModeEnable ? "Enabled" : "Disabled"));
611: ioReturn = IO_R_SUCCESS;
612: }
613: }
614: else if (strcmp(parameterName, APPLE96_RESET_TARGETS) == 0) {
615: if (count == 0) {
616: int target;
617:
618: /*
619: * Re-enable sync and command queueing. The
620: * disable bits persist after a reset.
621: */
622: for (target = 0; target < SCSI_NTARGETS; target++) {
623: PerTargetData *perTargetPtr;
624:
625: perTargetPtr = &gPerTargetData[target];
626: perTargetPtr->cmdQueueDisable = FALSE;
627: perTargetPtr->selectATNDisable = FALSE;
628: perTargetPtr->maxQueue = 0;
629: }
630: IOLog("%s: Per Target disable flags cleared\n", [self name]);
631: ioReturn = IO_R_SUCCESS;
632: }
633: }
634: else if (strcmp(parameterName, APPLE96_RESET_TIMESTAMP) == 0) {
635: ResetTimestampIndex();
636: ioReturn = IO_R_SUCCESS;
637: }
638: else if (strcmp(parameterName, APPLE96_ENABLE_TIMESTAMP) == 0) {
639: EnableTimestamp(TRUE);
640: ioReturn = IO_R_SUCCESS;
641: }
642: else if (strcmp(parameterName, APPLE96_DISABLE_TIMESTAMP) == 0) {
643: EnableTimestamp(FALSE);
644: ioReturn = IO_R_SUCCESS;
645: }
646: else if (strcmp(parameterName, APPLE96_PRESERVE_FIRST_TIMESTAMP) == 0) {
647: PreserveTimestamp(TRUE);
648: ioReturn = IO_R_SUCCESS;
649: }
650: else if (strcmp(parameterName, APPLE96_PRESERVE_LAST_TIMESTAMP) == 0) {
651: PreserveTimestamp(FALSE);
652: ioReturn = IO_R_SUCCESS;
653: }
654: else {
655: ioReturn = [super setIntValues
656: : parameterArray
657: forParameter : parameterName
658: count : count
659: ];
660: }
661: /* Radar 1670762 RESULT(ioReturn); */
662: return (ioReturn);
663: }
664:
665: /**
666: * Called by clients and user-interaction to retrieve information from
667: * the device. Note that non-privileged clients can call getIntValues
668: * and it may be used to *set* timestamp parameters.
669: */
670: - (IOReturn) getIntValues
671: : (unsigned *) parameterArray
672: forParameter : (IOParameterName) parameterName
673: count : (unsigned *) count; /* in/out */
674: {
675: IOReturn ioReturn = IO_R_INVALID_ARG;
676:
677: /* Radar 1670762 ENTRY("Sgi getIntValues"); */
678: if (strcmp(parameterName, APPLE96_AUTOSENSE) == 0) {
679: if (*count == 1) {
680: parameterArray[0] = gOptionAutoSenseEnable;
681: ioReturn = IO_R_SUCCESS;
682: }
683: }
684: else if (strcmp(parameterName, APPLE96_CMD_QUEUE) == 0) {
685: if (*count == 1) {
686: parameterArray[0] = gOptionCmdQueueEnable;
687: ioReturn = IO_R_SUCCESS;
688: }
689: }
690: else if (strcmp(parameterName, APPLE96_SYNC) == 0) {
691: if (*count == 1) {
692: parameterArray[0] = gOptionSyncModeEnable;
693: ioReturn = IO_R_SUCCESS;
694: }
695: }
696: else if (strcmp(parameterName, APPLE96_FAST_SCSI) == 0) {
697: if (*count == 1) {
698: parameterArray[0] = gOptionFastModeEnable;
699: ioReturn = IO_R_SUCCESS;
700: }
701: }
702: else if (strcmp(parameterName, APPLE96_ENABLE_DISCONNECT) == 0) { /* Radar 2005639 */
703: if (*count == 1) {
704: parameterArray[0] = gOptionDisconnectEnable;
705: ioReturn = IO_R_SUCCESS;
706: }
707: }
708: else if (strcmp(parameterName, APPLE_MAX_THREADS) == 0) { /* Radar 2005639 */
709: if (*count == 1) {
710: parameterArray[0] = MAX_CLIENT_THREADS;
711: ioReturn = IO_R_SUCCESS;
712: }
713: }
714: else if (strcmp(parameterName, APPLE96_RESET_TIMESTAMP) == 0) {
715: ResetTimestampIndex();
716: ioReturn = IO_R_SUCCESS;
717: }
718: else if (strcmp(parameterName, APPLE96_ENABLE_TIMESTAMP) == 0) {
719: EnableTimestamp(TRUE);
720: ioReturn = IO_R_SUCCESS;
721: }
722: else if (strcmp(parameterName, APPLE96_DISABLE_TIMESTAMP) == 0) {
723: EnableTimestamp(FALSE);
724: ioReturn = IO_R_SUCCESS;
725: }
726: else if (strcmp(parameterName, APPLE96_PRESERVE_FIRST_TIMESTAMP) == 0) {
727: PreserveTimestamp(TRUE);
728: ioReturn = IO_R_SUCCESS;
729: }
730: else if (strcmp(parameterName, APPLE96_PRESERVE_LAST_TIMESTAMP) == 0) {
731: PreserveTimestamp(FALSE);
732: ioReturn = IO_R_SUCCESS;
733: }
734: else if (strcmp(parameterName, APPLE96_STORE_TIMESTAMP) == 0) {
735: /*
736: * Count
737: * 1: tag, <zero>, current time
738: * 2: tag, value, current time
739: * 4: tag, value, user's time
740: */
741: switch (*count) {
742: case 1:
743: StoreTimestamp(parameterArray[0], 0);
744: ioReturn = IO_R_SUCCESS;
745: break;
746: case 2:
747: StoreTimestamp(parameterArray[0], parameterArray[1]);
748: ioReturn = IO_R_SUCCESS;
749: break;
750: case 4:
751: StoreNSecTimestamp(
752: parameterArray[0],
753: parameterArray[1],
754: *((ns_time_t *) ¶meterArray[2])
755: );
756: ioReturn = IO_R_SUCCESS;
757: break;
758: default:
759: break; /* Failure */
760: }
761: }
762: else if (strcmp(parameterName, APPLE96_READ_TIMESTAMP) == 0) {
763: /*
764: * Read the timestamp array:
765: * parameterArray -> result buffer (TimestampDataRecord vector)
766: * count -> maximum number of integers to return
767: * <- set to the actual number of integers returned.
768: * Note that, because count is a number of integers, clients should
769: * call this as follows:
770: * TimestampDataRecord myTimestamps[123];
771: * unsigned count;
772: * count = sizeof (myTimestamps) / sizeof (unsigned);
773: * [scsiDevice getIntValues
774: * : (unsigned int *) myTimestamps
775: * forParameter : APPLE96_READ_TIMESTAMP
776: * count : &count
777: * ];
778: * count = (count * sizeof (unsigned)) / sizeof (TimestampDataRecord);
779: * for (i = 0; i < count; i++) {
780: * Process(myTimestamps[i]);
781: * }
782: */
783: unsigned vectorSize = ((*count) * sizeof(unsigned))
784: / sizeof (TimestampDataRecord);
785: ReadTimestampVector((TimestampDataPtr) parameterArray, &vectorSize);
786: *count = (vectorSize * sizeof (TimestampDataRecord))
787: / sizeof (unsigned);
788: ioReturn = IO_R_SUCCESS;
789: }
790: else {
791: ioReturn = [super getIntValues : parameterArray
792: forParameter : parameterName
793: count : count];
794: }
795: /* RESULT(ioReturn); */
796: return (ioReturn);
797: }
798:
799:
800: #endif /* APPLE96_ENABLE_GET_SET */
801:
802: @end /* Apple96_SCSI */
803:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.