|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * IOSCSIParallelDevice.cpp
24: *
25: */
26:
27: #include <IOKit/IOSyncer.h>
28: #include <IOKit/scsi/IOSCSIParallelInterface.h>
29:
30: #undef super
31: #define super IOSCSIDevice
32:
33: #ifndef MIN
34: #define MIN(a,b) ((a <= b) ? a : b)
35: #endif
36:
37: OSDefineMetaClassAndAbstractStructors( IOCDBDevice, IOService )
38: OSDefineMetaClassAndAbstractStructors( IOSCSIDevice, IOCDBDevice )
39: OSDefineMetaClassAndStructors( IOSCSIParallelDevice, IOSCSIDevice )
40:
41: /*
42: *
43: *
44: *
45: */
46: bool IOSCSIParallelDevice::init( IOSCSIParallelController *forController, SCSITargetLun forTargetLun )
47: {
48: SCSICDBInfo scsiCDB;
49:
50: controller = forController;
51: targetLun = forTargetLun;
52:
53: target = &controller->targets[targetLun.target];
54:
55: queue_init( &deviceList );
56: queue_init( &bypassList );
57: queue_init( &activeList );
58: queue_init( &abortList );
59: queue_init( &cancelList );
60:
61: clientSem = IORWLockAlloc();
62: if ( clientSem == 0 )
63: {
64: return false;
65: }
66:
67: if ( super::init() == false )
68: {
69: return false;
70: }
71:
72: if ( controller->controllerInfo.lunPrivateDataSize != 0 )
73: {
74: devicePrivateData = IOMallocContiguous( controller->controllerInfo.lunPrivateDataSize, 16, 0 );
75: if ( devicePrivateData == 0 )
76: {
77: return false;
78: }
79: }
80:
81: bzero( &scsiCDB, sizeof(scsiCDB) );
82:
83: abortCmd = allocCommand(kIOSCSIParallelDevice, 0);
84: if ( abortCmd == 0 )
85: {
86: return false;
87: }
88: abortCmd->setTimeout( kSCSIAbortTimeoutmS );
89:
90: cancelCmd = allocCommand(kIOSCSIParallelDevice, 0);
91: if ( cancelCmd == 0 )
92: {
93: return false;
94: }
95: cancelCmd->setTimeout( 0 );
96: cancelCmd->cmdType = kSCSICommandCancel;
97:
98: reqSenseCmd = allocCommand(kIOSCSIParallelDevice, 0);
99: if ( reqSenseCmd == 0 )
100: {
101: return false;
102: }
103: scsiCDB.cdbLength = 6;
104: scsiCDB.cdb[0] = kSCSICmdRequestSense;
105: scsiCDB.cdb[1] = targetLun.lun << 4;
106: scsiCDB.cdbTag = (UInt32) -1;
107:
108: reqSenseCmd->setTimeout( kSCSIReqSenseTimeoutmS );
109: reqSenseCmd->cmdType = kSCSICommandReqSense;
110: reqSenseCmd->setCDB( &scsiCDB );
111:
112: if ( controller->controllerInfo.tagAllocationMethod == kTagAllocationPerLun )
113: {
114: tagArray = (UInt32 *)IOMalloc( controller->tagArraySize );
115: bzero( tagArray, controller->tagArraySize );
116: }
117:
118: deviceGate = IOCommandGate::commandGate( this, (IOCommandGate::Action) &IOSCSIParallelDevice::receiveCommand );
119: if ( deviceGate == 0 )
120: {
121: return false;
122: }
123:
124: if ( controller->workLoop->addEventSource( deviceGate ) != kIOReturnSuccess )
125: {
126: return false;
127: }
128:
129: commandLimitSave = commandLimit = controller->controllerInfo.maxCommandsPerLun;
130:
131: idleNotifyActive = false;
132:
133: normalQHeld = false;
134: bypassQHeld = false;
135:
136: return true;
137: }
138:
139: /*
140: *
141: *
142: *
143: */
144: IOReturn IOSCSIParallelDevice::probeTargetLun()
145: {
146: SCSICDBInfo cdb;
147: SCSIResults result;
148: IOReturn rc;
149: IOMemoryDescriptor *desc = 0;
150: SCSIInquiry *inqData = 0;
151: UInt32 size = 0;
152: OSDictionary *propTable;
153:
154: probeCmd = allocCommand(kIOSCSIParallelDevice, 0);
155:
156: if ( probeCmd == 0 )
157: {
158: rc = kIOReturnNoMemory;
159: goto probeError;
160: }
161:
162: size = kDefaultInquirySize;
163:
164: if ( !(inqData = (SCSIInquiry *)IOMalloc(size)) )
165: {
166: rc = kIOReturnNoMemory;
167: goto probeError;
168: }
169:
170: desc = IOMemoryDescriptor::withAddress( (void *)inqData, size, kIODirectionIn );
171: if ( desc == 0 )
172: {
173: rc = kIOReturnNoMemory;
174: goto probeError;
175: }
176:
177: if ( open( this ) == false )
178: {
179: rc = kIOReturnError;
180: goto probeError;
181: }
182:
183: bzero( (void *)&cdb, sizeof(cdb) );
184:
185: cdb.cdbLength = 6;
186: cdb.cdb[0] = kSCSICmdInquiry;
187: cdb.cdb[4] = size;
188: probeCmd->setCDB( &cdb );
189:
190: probeCmd->setPointers( desc, size, false );
191:
192: probeCmd->setTimeout( kSCSIProbeTimeoutmS );
193: probeCmd->setCallback();
194:
195: probeCmd->execute();
196:
197: rc = probeCmd->getResults( &result );
198:
199: switch ( rc )
200: {
201: case kIOReturnSuccess:
202: break;
203:
204: case kIOReturnUnderrun:
205: rc = kIOReturnSuccess;
206: break;
207:
208: default:
209: goto probeError;
210: }
211:
212: if ( result.bytesTransferred <= (UInt32)(&inqData->flags - &inqData->devType) )
213: {
214: rc = kIOReturnDeviceError;
215: goto probeError;
216: }
217:
218: switch ( inqData->devType & kSCSIDevTypeQualifierMask )
219: {
220: case kSCSIDevTypeQualifierConnected:
221: case kSCSIDevTypeQualifierNotConnected:
222: break;
223: case kSCSIDevTypeQualifierReserved:
224: case kSCSIDevTypeQualifierMissing:
225: rc = kIOReturnNotAttached;
226: break;
227: default:
228: break;
229: }
230:
231: if ( rc != kIOReturnSuccess )
232: {
233: goto probeError;
234: }
235:
236: inquiryData = inqData;
237: inquiryDataSize = result.bytesTransferred;
238:
239: propTable = createProperties();
240: if ( !propTable ) goto probeError;
241:
242: setPropertyTable( propTable );
243:
244: propTable->release();
245:
246: probeError: ;
247:
248: if ( desc )
249: {
250: desc->release();
251: }
252:
253: if ( inqData )
254: {
255: if ( rc != kIOReturnSuccess )
256: {
257: IOFree( inqData, size );
258: }
259: }
260:
261: return rc;
262: }
263:
264: /*
265: *
266: *
267: *
268: */
269: void IOSCSIParallelDevice::setupTarget()
270: {
271: SCSITargetParms targetParms;
272: UInt32 transferWidth;
273:
274: if ( targetLun.lun != 0 )
275: {
276: close( this );
277: return;
278: }
279:
280: bzero( &targetParms, sizeof(SCSITargetParms) );
281:
282: if ( inquiryData->flags & kSCSIDevCapSync )
283: {
284: targetParms.transferPeriodpS = controller->controllerInfo.minTransferPeriodpS;
285: targetParms.transferOffset = controller->controllerInfo.maxTransferOffset;
286: }
287:
288: if ( inquiryData->flags & kSCSIDevCapWBus32 )
289: {
290: transferWidth = 4;
291: }
292: else if ( inquiryData->flags & kSCSIDevCapWBus16 )
293: {
294: transferWidth = 2;
295: }
296: else
297: {
298: transferWidth = 1;
299: }
300:
301: targetParms.transferWidth = MIN( transferWidth, controller->controllerInfo.maxTransferWidth );
302:
303: if ( inquiryData->flags & kSCSIDevCapCmdQue )
304: {
305: targetParms.enableTagQueuing = true;
306: }
307:
308: setTargetParms( &targetParms );
309:
310: close( this );
311: }
312:
313: /*
314: *
315: *
316: *
317: */
318: void IOSCSIParallelDevice::getInquiryData( void *clientBuf, UInt32 clientBufSize, UInt32 *clientDataSize )
319: {
320: UInt32 len;
321:
322: bzero( clientBuf, clientBufSize );
323:
324: len = MIN( clientBufSize, inquiryDataSize );
325:
326: bcopy( inquiryData, clientBuf, len );
327:
328: *clientDataSize = len;
329: }
330:
331: /*
332: *
333: *
334: *
335: */
336: void IOSCSIParallelDevice::abort()
337: {
338: submitCommand( kSCSICommandAbortAll, 0 );
339: }
340:
341: /*
342: *
343: *
344: *
345: */
346: void IOSCSIParallelDevice::reset()
347: {
348: submitCommand( kSCSICommandDeviceReset, 0 );
349: }
350:
351: /*
352: *
353: *
354: *
355: */
356: void IOSCSIParallelDevice::holdQueue( UInt32 queueType )
357: {
358: if ( getWorkLoop()->inGate() == false )
359: {
360: IOPanic( "IOSCSIParallelDevice::holdQueue() - must be called from workloop!!\n\r");
361: }
362:
363: if ( queueType == kQTypeBypassQ )
364: {
365: bypassQHeld = true;
366: }
367: else if ( queueType == kQTypeNormalQ )
368: {
369: normalQHeld = true;
370: }
371: }
372:
373: /*
374: *
375: *
376: *
377: */
378: void IOSCSIParallelDevice::releaseQueue( UInt32 queueType )
379: {
380: if ( getWorkLoop()->inGate() == false )
381: {
382: IOPanic( "IOSCSIParallelDevice::releaseQueue() - must be called from workloop!!\n\r");
383: }
384:
385: if ( queueType == kQTypeBypassQ )
386: {
387: bypassQHeld = false;
388: }
389: else if ( queueType == kQTypeNormalQ )
390: {
391: normalQHeld = false;
392: }
393:
394: dispatchRequest();
395: }
396:
397: /*
398: *
399: *
400: *
401: */
402: void IOSCSIParallelDevice::notifyIdle( void *target = 0, CallbackFn callback = 0, void *refcon = 0 )
403: {
404: if ( getWorkLoop()->inGate() == false )
405: {
406: IOPanic( "IOSCSIParallelDevice:::notifyIdle() - must be called from workloop!!\n\r");
407: }
408:
409: if ( callback == 0 )
410: {
411: idleNotifyActive = false;
412: return;
413: }
414:
415: if ( idleNotifyActive == true )
416: {
417: IOPanic( "IOSCSIParallelDevice:::notifyIdle() - only one idle notify may be active\n\r");
418: }
419:
420: idleNotifyActive = true;
421: idleNotifyTarget = target;
422: idleNotifyCallback = callback;
423: idleNotifyRefcon = refcon;
424:
425: checkIdleNotify();
426: }
427:
428:
429: /*
430: *
431: *
432: *
433: */
434: void IOSCSIParallelDevice::submitCommand( UInt32 cmdType, IOSCSIParallelCommand *scsiCmd, UInt32 cmdSequenceNumber )
435: {
436: deviceGate->runCommand( (void *)cmdType, (void *)scsiCmd, (void *) cmdSequenceNumber, (void *) 0 );
437: }
438:
439: /*
440: *
441: *
442: *
443: */
444: void IOSCSIParallelDevice::receiveCommand( UInt32 cmdType, IOSCSIParallelCommand *scsiCmd, UInt32 cmdSequenceNumber, void *p3 )
445: {
446: queue_head_t *queue;
447:
448: switch ( cmdType )
449: {
450: case kSCSICommandExecute:
451: scsiCmd->cmdType = (SCSICommandType) cmdType;
452:
453: scsiCmd->scsiCmd.cdbFlags &= (kCDBFNoDisconnect);
454:
455: queue = (scsiCmd->queueType == kQTypeBypassQ) ? &bypassList : &deviceList;
456:
457: if ( scsiCmd->queuePosition == kQPositionHead )
458: {
459: stackCommand( queue, scsiCmd );
460: }
461: else
462: {
463: addCommand( queue, scsiCmd );
464: }
465:
466: dispatchRequest();
467: break;
468:
469: case kSCSICommandAbortAll:
470: abortAllCommands( kSCSICommandAbortAll );
471: break;
472:
473: case kSCSICommandAbort:
474: abortCommand( scsiCmd, cmdSequenceNumber );
475: break;
476:
477: case kSCSICommandDeviceReset:
478: abortAllCommands( kSCSICommandDeviceReset );
479: break;
480:
481: default:
482: /* ??? */
483: break;
484: }
485: }
486:
487: /*
488: *
489: *
490: *
491: */
492: void IOSCSIParallelDevice::abortCommand( IOSCSIParallelCommand *scsiCmd, UInt32 sequenceNumber )
493: {
494: if ( scsiCmd->list == (queue_head_t *)deviceGate )
495: {
496: if ( scsiCmd->sequenceNumber != sequenceNumber )
497: {
498: return;
499: }
500: scsiCmd->results.returnCode = kIOReturnAborted;
501: }
502: else if ( scsiCmd->list == &deviceList )
503: {
504: if ( scsiCmd->sequenceNumber != sequenceNumber )
505: {
506: return;
507: }
508:
509: deleteCommand( &deviceList, scsiCmd );
510: scsiCmd->results.returnCode = kIOReturnAborted;
511: finishCommand( scsiCmd );
512: }
513: else if ( scsiCmd->list == &activeList )
514: {
515: if ( scsiCmd->sequenceNumber != sequenceNumber )
516: {
517: return;
518: }
519:
520: moveCommand( &activeList, &abortList, scsiCmd );
521:
522: dispatchRequest();
523: }
524: }
525:
526:
527: /*
528: *
529: *
530: *
531: */
532: void IOSCSIParallelDevice::abortAllCommands( SCSICommandType cmdType )
533: {
534: IOSCSIParallelDevice *abortDev;
535:
536: abortCmdPending = cmdType;
537:
538: if ( abortCmdPending == kSCSICommandAbortAll )
539: {
540: if ( client != 0 )
541: {
542: client->message( kSCSIClientMsgDeviceAbort, this );
543: }
544: }
545: else if ( abortCmdPending == kSCSICommandDeviceReset )
546: {
547: queue_iterate( &target->deviceList, abortDev, IOSCSIParallelDevice *, nextDevice )
548: {
549: if ( abortDev->client != 0 )
550: {
551: abortDev->client->message( kSCSIClientMsgDeviceReset, abortDev );
552: }
553: }
554: }
555:
556: dispatchRequest();
557: }
558:
559: /*
560: *
561: *
562: *
563: */
564: void IOSCSIParallelDevice::resetOccurred( SCSIClientMessage clientMsg )
565: {
566: if ( client != 0 && clientMsg != kSCSIClientMsgNone )
567: {
568: client->message( clientMsg, this );
569: }
570:
571: moveAllCommands( &activeList, &cancelList, kIOReturnAborted );
572: moveAllCommands( &abortList, &cancelList, kIOReturnAborted );
573:
574: abortState = kStateIdle;
575: reqSenseState = kStateIdle;
576: commandLimit = commandLimitSave;
577: negotiateState = kStateIdle;
578:
579: dispatchRequest();
580: }
581:
582: void IOSCSIParallelDevice::resetComplete()
583: {
584: if ( client != 0 )
585: {
586: client->message( kSCSIClientMsgBusReset | kSCSIClientMsgDone, this );
587: }
588: }
589:
590:
591: /*
592: *
593: *
594: *
595: */
596: bool IOSCSIParallelDevice::checkAbortQueue()
597: {
598: IOSCSIParallelCommand *origCmd;
599:
600: if ( abortState == kStateActive )
601: {
602: return true;
603: }
604:
605: if ( abortCmdPending != kSCSICommandNone )
606: {
607: abortCmd->origCommand = 0;
608:
609: abortCmd->scsiCmd.cdbTagMsg = 0;
610: abortCmd->scsiCmd.cdbTag = (UInt32) -1;
611:
612:
613: abortCmd->cmdType = abortCmdPending;
614: abortCmd->scsiCmd.cdbAbortMsg = (abortCmdPending == kSCSICommandAbortAll)
615: ? kSCSIMsgAbort : kSCSIMsgBusDeviceReset;
616:
617: if ( disableDisconnect == true )
618: {
619: abortCmd->scsiCmd.cdbFlags |= kCDBFlagsNoDisconnect;
620: }
621: else
622: {
623: abortCmd->scsiCmd.cdbFlags &= ~kCDBFlagsNoDisconnect;
624: }
625:
626:
627: abortCmd->timer = ( abortCmd->timeout != 0 ) ?
628: abortCmd->timeout / kSCSITimerIntervalmS + 1 : 0;
629:
630: bzero( &abortCmd->results, sizeof(SCSIResults) );
631:
632: abortCmdPending = kSCSICommandNone;
633: abortState = kStateActive;
634:
635: addCommand( &activeList, abortCmd );
636: controller->executeCommand( abortCmd );
637: }
638: else if ( queue_empty( &abortList ) == false )
639: {
640: origCmd = (IOSCSIParallelCommand *)queue_first( &abortList );
641: abortCmd->origCommand = origCmd;
642:
643: abortCmd->cmdType = kSCSICommandAbort;
644: abortCmd->scsiCmd.cdbTagMsg = origCmd->scsiCmd.cdbTagMsg;
645: abortCmd->scsiCmd.cdbTag = origCmd->scsiCmd.cdbTag;
646: abortCmd->scsiCmd.cdbAbortMsg = (abortCmd->scsiCmd.cdbTagMsg != 0)
647: ? kSCSIMsgAbortTag : kSCSIMsgAbort;
648:
649: abortCmd->timer = ( abortCmd->timeout != 0 ) ?
650: abortCmd->timeout / kSCSITimerIntervalmS + 1 : 0;
651:
652: bzero( &abortCmd->results, sizeof(SCSIResults) );
653:
654: abortState = kStateActive;
655:
656: addCommand( &activeList, abortCmd );
657: controller->executeCommand( abortCmd );
658: }
659: else
660: {
661: return false;
662: }
663:
664: return true;
665: }
666:
667: /*
668: *
669: *
670: *
671: */
672: void IOSCSIParallelDevice::checkCancelQueue()
673: {
674: if ( cancelState != kStateIdle )
675: {
676: return;
677: }
678:
679: if ( queue_empty( &cancelList ) == true )
680: {
681: return;
682: }
683:
684: if ( controller->controllerInfo.disableCancelCommands == true )
685: {
686: return;
687: }
688:
689: cancelCmd->origCommand = (IOSCSIParallelCommand *)queue_first( &cancelList );
690: bzero( &cancelCmd->results, sizeof(SCSIResults) );
691:
692: cancelState = kStateActive;
693: controller->cancelCommand( cancelCmd );
694: }
695:
696: /*
697: *
698: *
699: *
700: */
701: bool IOSCSIParallelDevice::checkReqSense()
702: {
703: IOMemoryDescriptor *senseData;
704: UInt32 senseLength;
705: SCSITargetParms *tpCur;
706:
707: if ( target->reqSenseState == kStateActive )
708: {
709: return true;
710: }
711:
712: if ( reqSenseState == kStateIssue )
713: {
714: reqSenseCmd->origCommand = reqSenseOrigCmd;
715: bzero( &reqSenseCmd->results, sizeof(SCSIResults) );
716:
717: reqSenseOrigCmd->getPointers( &senseData, &senseLength, 0, true );
718: reqSenseCmd->setPointers( senseData, senseLength, false );
719:
720: reqSenseCmd->scsiCmd.cdbFlags = 0;
721:
722: if ( disableDisconnect == true )
723: {
724: reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNoDisconnect;
725: }
726: else
727: {
728: reqSenseCmd->scsiCmd.cdbFlags &= ~kCDBFlagsNoDisconnect;
729: }
730:
731: tpCur = &target->targetParmsCurrent;
732:
733: if ( tpCur->transferWidth != 1 )
734: {
735: reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateWDTR;
736: }
737:
738: if ( tpCur->transferOffset != 0 )
739: {
740: reqSenseCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateSDTR;
741: }
742:
743: reqSenseCmd->timer = ( reqSenseCmd->timeout != 0 ) ?
744: reqSenseCmd->timeout / kSCSITimerIntervalmS + 1 : 0;
745:
746: reqSenseCmd->scsiCmd.cdb[3] = (senseLength >> 8) & 0xff;
747: reqSenseCmd->scsiCmd.cdb[4] = senseLength & 0xff;
748:
749: reqSenseState = kStatePending;
750: }
751:
752: if ( reqSenseState == kStatePending )
753: {
754: target->reqSenseState = reqSenseState = kStateActive;
755:
756: addCommand( &activeList, reqSenseCmd );
757:
758: controller->executeCommand( reqSenseCmd );
759: }
760:
761: return (target->reqSenseCount > 0);
762: }
763:
764:
765: /*
766: *
767: *
768: *
769: */
770: bool IOSCSIParallelDevice::checkDeviceQueue( UInt32 *dispatchAction )
771: {
772: IOSCSIParallelCommand *scsiCmd = 0;
773: queue_head_t *queue;
774: UInt32 i;
775: bool rc = true;
776: bool queueHeld;
777:
778: do
779: {
780: if ( controller->commandCount >= controller->commandLimit )
781: {
782: *dispatchAction = kDispatchStop;
783: break;
784: }
785:
786: if ( target->commandCount >= target->commandLimit )
787: {
788: *dispatchAction = kDispatchNextTarget;
789: break;
790: }
791:
792: *dispatchAction = kDispatchNextLun;
793:
794: if ( commandCount >= commandLimit )
795: {
796: break;
797: }
798:
799: for ( i=0; i < 2; i++ )
800: {
801: queueHeld = (i == 0) ? bypassQHeld : normalQHeld;
802: queue = (i == 0) ? &bypassList : &deviceList;
803:
804: if ( queueHeld == true )
805: {
806: continue;
807: }
808:
809: scsiCmd = checkCommand( queue );
810: if ( scsiCmd != 0 )
811: {
812: *dispatchAction = kDispatchNextCommand;
813: break;
814: }
815: }
816:
817: if ( i == 2 )
818: {
819: rc = false;
820: break;
821: }
822:
823: if ( disableDisconnect == true || (scsiCmd->scsiCmd.cdbFlags & kCDBFNoDisconnect) )
824: {
825: scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsNoDisconnect;
826:
827: if ( controller->commandCount != 0 )
828: {
829: *dispatchAction = kDispatchNextLun;
830: break;
831: }
832:
833: controller->noDisconnectCmd = scsiCmd;
834: controller->commandLimitSave = controller->commandLimit;
835: controller->commandLimit = 1;
836: }
837:
838: else if ( checkTag( scsiCmd ) == false )
839: {
840: switch ( controller->controllerInfo.tagAllocationMethod )
841: {
842: case kTagAllocationPerTarget:
843: *dispatchAction = kDispatchNextTarget;
844: break;
845: case kTagAllocationPerController:
846: *dispatchAction = kDispatchStop;
847: break;
848: case kTagAllocationPerLun:
849: ;
850: default:
851: *dispatchAction = kDispatchNextLun;
852: }
853: break;
854: }
855:
856: getCommand( queue );
857:
858: checkNegotiate( scsiCmd );
859:
860: scsiCmd->timer = ( scsiCmd->timeout != 0 ) ? scsiCmd->timeout / kSCSITimerIntervalmS + 1 : 0;
861:
862: commandCount++;
863: target->commandCount++;
864: controller->commandCount++;
865:
866: addCommand( &activeList, scsiCmd );
867:
868: controller->executeCommand( scsiCmd );
869:
870: } while ( 0 );
871:
872: return rc;
873: }
874:
875: /*
876: *
877: *
878: *
879: */
880: void IOSCSIParallelDevice::rescheduleCommand( IOSCSIParallelCommand *scsiCmd )
881: {
882: if ( scsiCmd->list != &activeList )
883: {
884: IOLog( "IOSCSIParallelController::rescheduleCommand() - Command not active. Cmd = %08x\n\r", (int)scsiCmd );
885: return;
886: }
887:
888: deleteCommand( &activeList, scsiCmd );
889:
890: switch ( scsiCmd->cmdType )
891: {
892: case kSCSICommandExecute:
893: if ( scsiCmd->scsiCmd.cdbTagMsg != 0 )
894: {
895: freeTag( scsiCmd->scsiCmd.cdbTag );
896: scsiCmd->scsiCmd.cdbTag = (UInt32) -1;
897: }
898:
899: stackCommand( &deviceList, scsiCmd );
900:
901: if ( scsiCmd->scsiCmd.cdbFlags & kCDBFlagsNoDisconnect )
902: {
903: controller->commandLimit = controller->commandLimitSave;
904: controller->noDisconnectCmd = 0;
905: }
906:
907: controller->commandCount--;
908: target->commandCount--;
909: commandCount--;
910: break;
911:
912: case kSCSICommandReqSense:
913: reqSenseState = kStatePending;
914: target->reqSenseState = kStateIdle;
915: break;
916:
917: case kSCSICommandAbortAll:
918: case kSCSICommandDeviceReset:
919: abortCmdPending = scsiCmd->cmdType;
920:
921: case kSCSICommandAbort:
922: abortState = kStateIdle;
923: break;
924:
925: default:
926: ;
927: }
928:
929: dispatchRequest();
930:
931: }
932:
933: /*
934: *
935: *
936: *
937: */
938: bool IOSCSIParallelDevice::setTargetParms( SCSITargetParms *targetParms )
939: {
940: IOSCSIParallelCommand *scsiCmd;
941: SCSICDBInfo scsiCDB;
942: bool fTagEnable;
943: bool rc = true;
944:
945: IOMemoryDescriptor *senseDesc;
946: UInt8 senseBuffer[14];
947:
948:
949: if ( getWorkLoop()->inGate() == true )
950: {
951: IOPanic( "IOSCSIParallelDevice:::setTargetParms() - must not be called from workloop!!\n\r");
952: }
953:
954: IOWriteLock( target->clientSem );
955:
956: target->targetParmsNew = *targetParms;
957:
958: target->commandLimit = 1;
959:
960: fTagEnable = (targetParms->enableTagQueuing == true)
961: && (controller->controllerInfo.tagAllocationMethod != kTagAllocationNone)
962: && (controller->controllerInfo.maxTags != 0);
963:
964: if ( fTagEnable == true )
965: {
966: target->commandLimitSave = controller->controllerInfo.maxCommandsPerTarget;
967: }
968: else
969: {
970: target->commandLimitSave = 1;
971: target->targetParmsNew.enableTagQueuing = false;
972: }
973:
974: scsiCmd = allocCommand(kIOSCSIParallelDevice, 0);
975:
976: bzero( &scsiCDB, sizeof( SCSICDBInfo ) );
977:
978: scsiCDB.cdbLength = 6;
979: scsiCDB.cdb[0] = kSCSICmdTestUnitReady;
980: scsiCDB.cdb[1] = targetLun.lun << 4;
981: scsiCmd->setCDB( &scsiCDB );
982:
983:
984: senseDesc = IOMemoryDescriptor::withAddress(senseBuffer, sizeof(senseBuffer), kIODirectionIn);
985: if ( senseDesc == 0 ) return false;
986: scsiCmd->setPointers( senseDesc, sizeof(senseBuffer), false, true );
987:
988: IOWriteLock( target->targetSem );
989:
990: target->negotiateState = kStateIssue;
991:
992: scsiCmd->execute();
993:
994: IOWriteLock( target->targetSem );
995: IORWUnlock( target->targetSem );
996:
997: scsiCmd->release();
998: senseDesc->release();
999:
1000: rc = (target->negotiateResult == kIOReturnSuccess);
1001:
1002: IORWUnlock( target->clientSem );
1003:
1004: return rc;
1005: }
1006:
1007: /*
1008: *
1009: *
1010: *
1011: */
1012: void IOSCSIParallelDevice::getTargetParms( SCSITargetParms *targetParms )
1013: {
1014: *targetParms = target->targetParmsCurrent;
1015: }
1016:
1017: /*
1018: *
1019: *
1020: *
1021: */
1022: bool IOSCSIParallelDevice::setLunParms( SCSILunParms *lunParms )
1023: {
1024: IOSCSIParallelCommand *scsiCmd;
1025: SCSICDBInfo scsiCDB;
1026:
1027: IOMemoryDescriptor *senseDesc;
1028: UInt8 senseBuffer[14];
1029:
1030: if ( getWorkLoop()->inGate() == true )
1031: {
1032: IOPanic( "IOSCSIParallelDevice:::setLunParms() - must not be called from workloop!!\n\r");
1033: }
1034:
1035: IOWriteLock( clientSem );
1036:
1037: lunParmsNew = *lunParms;
1038: commandLimitSave = commandLimit;
1039: commandLimit = 1;
1040:
1041: scsiCmd = allocCommand(kIOSCSIParallelDevice, 0);
1042:
1043: bzero( &scsiCDB, sizeof( SCSICDBInfo ) );
1044:
1045: scsiCDB.cdbLength = 6;
1046: scsiCDB.cdb[0] = kSCSICmdTestUnitReady;
1047: scsiCDB.cdb[1] = targetLun.lun << 4;
1048: scsiCmd->setCDB( &scsiCDB );
1049:
1050: senseDesc = IOMemoryDescriptor::withAddress(senseBuffer, sizeof(senseBuffer), kIODirectionIn);
1051: if ( senseDesc == 0 ) return false;
1052: scsiCmd->setPointers( senseDesc, sizeof(senseBuffer), false, true );
1053:
1054: negotiateState = kStateIssue;
1055:
1056: scsiCmd->execute();
1057:
1058: scsiCmd->release();
1059: senseDesc->release();
1060:
1061: while ( negotiateState != kStateIdle )
1062: {
1063: IOSleep( 100 );
1064: }
1065:
1066: IORWUnlock( clientSem );
1067:
1068: return true;
1069: }
1070:
1071: /*
1072: *
1073: *
1074: *
1075: */
1076: void IOSCSIParallelDevice::getLunParms( SCSILunParms *lunParms )
1077: {
1078: lunParms->disableDisconnect = disableDisconnect;
1079: }
1080:
1081: /*
1082: *
1083: *
1084: *
1085: */
1086: void IOSCSIParallelDevice::checkNegotiate( IOSCSIParallelCommand *scsiCmd )
1087: {
1088: SCSITargetParms *tpCur, *tpNew;
1089:
1090: if ( target->negotiateState == kStateIssue )
1091: {
1092: if ( target->commandCount == 0 )
1093: {
1094: tpNew = &target->targetParmsNew;
1095: tpCur = &target->targetParmsCurrent;
1096:
1097: target->negotiateResult = kIOReturnSuccess;
1098:
1099: if ( tpCur->transferPeriodpS != tpNew->transferPeriodpS || tpCur->transferOffset != tpNew->transferOffset )
1100: {
1101: scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateSDTR;
1102: target->negotiateState = kStateActive;
1103: }
1104:
1105: if ( tpCur->transferWidth != tpNew->transferWidth )
1106: {
1107: scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsNegotiateWDTR;
1108: target->negotiateState = kStateActive;
1109: }
1110:
1111: if ( tpCur->enableTagQueuing != tpNew->enableTagQueuing )
1112: {
1113: scsiCmd->scsiCmd.cdbFlags |= kCDBFlagsEnableTagQueuing;
1114: target->negotiateState = kStateActive;
1115: }
1116:
1117: if ( target->negotiateState != kStateActive )
1118: {
1119: IORWUnlock( target->targetSem );
1120: target->negotiateState = kStateIdle;
1121: target->commandLimit = target->commandLimitSave;
1122: }
1123:
1124: *tpCur = *tpNew;
1125: }
1126: }
1127:
1128: if ( negotiateState == kStateIssue )
1129: {
1130: if ( commandCount == 0 )
1131: {
1132: disableDisconnect = lunParmsNew.disableDisconnect;
1133: negotiateState = kStateIdle;
1134: }
1135: }
1136: }
1137:
1138: /*
1139: *
1140: *
1141: *
1142: */
1143: bool IOSCSIParallelDevice::checkTag( IOSCSIParallelCommand *scsiCmd )
1144: {
1145: SCSICDBInfo scsiCDB;
1146: bool rc = true;
1147:
1148: scsiCmd->getCDB( &scsiCDB );
1149:
1150: scsiCDB.cdbTagMsg = 0;
1151: scsiCDB.cdbTag = (UInt32)-1;
1152:
1153: do
1154: {
1155: if ( scsiCmd->device->target->targetParmsCurrent.enableTagQueuing == false )
1156: {
1157: break;
1158: }
1159:
1160: if ( allocTag( &scsiCDB.cdbTag ) == false )
1161: {
1162: rc = false;
1163: break;
1164: }
1165:
1166: if ( scsiCDB.cdbTagMsg == 0 )
1167: {
1168: scsiCDB.cdbTagMsg = kSCSIMsgSimpleQueueTag;
1169: }
1170: }
1171: while ( 0 );
1172:
1173: scsiCmd->setCDB( &scsiCDB );
1174:
1175: return rc;
1176: }
1177:
1178: /*
1179: *
1180: *
1181: *
1182: */
1183: bool IOSCSIParallelDevice::allocTag( UInt32 *tagId )
1184: {
1185: UInt32 i;
1186: UInt32 tagIndex;
1187: UInt32 tagMask;
1188: UInt32 *tags = 0;
1189:
1190: switch ( controller->controllerInfo.tagAllocationMethod )
1191: {
1192: case kTagAllocationPerLun:
1193: tags = tagArray;
1194: break;
1195: case kTagAllocationPerTarget:
1196: tags = target->tagArray;
1197: break;
1198: case kTagAllocationPerController:
1199: tags = controller->tagArray;
1200: break;
1201: default:
1202: ;
1203: }
1204:
1205: if ( tags == 0 ) return false;
1206:
1207: for ( i = 0; i < controller->controllerInfo.maxTags; i++ )
1208: {
1209: tagIndex = i / 32;
1210: tagMask = 1 << (i % 32);
1211: if ( !(tags[tagIndex] & tagMask) )
1212: {
1213: tags[tagIndex] |= tagMask;
1214: *tagId = i;
1215: return true;
1216: }
1217: }
1218: return false;
1219: }
1220:
1221: /*
1222: *
1223: *
1224: *
1225: */
1226: void IOSCSIParallelDevice::freeTag( UInt32 tagId )
1227: {
1228: UInt32 *tags = 0;
1229:
1230: switch ( controller->controllerInfo.tagAllocationMethod )
1231: {
1232: case kTagAllocationPerLun:
1233: tags = tagArray;
1234: break;
1235: case kTagAllocationPerTarget:
1236: tags = target->tagArray;
1237: break;
1238: case kTagAllocationPerController:
1239: tags = controller->tagArray;
1240: break;
1241: default:
1242: ;
1243: }
1244:
1245: if ( tags == 0 ) return;
1246:
1247: tags[tagId/32] &= ~(1 << (tagId % 32));
1248: }
1249:
1250: /*
1251: *
1252: *
1253: *
1254: */
1255: IOSCSIParallelCommand *IOSCSIParallelDevice::findCommandWithNexus( UInt32 tagValue )
1256: {
1257: IOSCSIParallelCommand *scsiCmd;
1258:
1259: queue_iterate( &activeList, scsiCmd, IOSCSIParallelCommand *, nextCommand )
1260: {
1261: switch ( scsiCmd->cmdType )
1262: {
1263: case kSCSICommandExecute:
1264: case kSCSICommandReqSense:
1265: if ( scsiCmd->scsiCmd.cdbTag == tagValue )
1266: {
1267: return scsiCmd;
1268: }
1269: break;
1270: default:
1271: ;
1272: }
1273: }
1274:
1275: queue_iterate( &abortList, scsiCmd, IOSCSIParallelCommand *, nextCommand )
1276: {
1277: switch ( scsiCmd->cmdType )
1278: {
1279: case kSCSICommandExecute:
1280: case kSCSICommandReqSense:
1281: if ( scsiCmd->scsiCmd.cdbTag == tagValue )
1282: {
1283: return scsiCmd;
1284: }
1285: break;
1286: default:
1287: ;
1288: }
1289: }
1290:
1291: return 0;
1292: }
1293:
1294: /*
1295: *
1296: *
1297: *
1298: */
1299: void IOSCSIParallelDevice::timer()
1300: {
1301: IOSCSIParallelCommand *scsiCmd, *tmp = 0;
1302: SCSITargetLun scsiTargetLun;
1303:
1304: queue_iterate( &activeList, scsiCmd, IOSCSIParallelCommand *, nextCommand )
1305: {
1306: tmp = (IOSCSIParallelCommand *)queue_prev( &scsiCmd->nextCommand );
1307:
1308: if ( scsiCmd->timer )
1309: {
1310: if ( !--scsiCmd->timer )
1311: {
1312: scsiCmd->getTargetLun( &scsiTargetLun );
1313: IOLog("Timeout: T/L = %d:%d Cmd = %08x Cmd Type = %d\n\r",
1314: scsiTargetLun.target, scsiTargetLun.lun, (int)scsiCmd, scsiCmd->cmdType );
1315:
1316: switch ( scsiCmd->cmdType )
1317: {
1318: case kSCSICommandExecute:
1319: moveCommand( &activeList, &abortList, scsiCmd, kIOReturnTimeout );
1320: scsiCmd = tmp;
1321: break;
1322:
1323: case kSCSICommandReqSense:
1324: reqSenseState = kStateIdle;
1325: moveCommand( &activeList, &abortList, scsiCmd, kIOReturnTimeout );
1326: scsiCmd = tmp;
1327: break;
1328:
1329: case kSCSICommandAbort:
1330: case kSCSICommandAbortAll:
1331: case kSCSICommandDeviceReset:
1332: controller->busResetState = kStateIssue;
1333: break;
1334:
1335: default:
1336: ;
1337: }
1338:
1339: dispatchRequest();
1340: }
1341: }
1342:
1343: if ( queue_end( &activeList, (queue_head_t *)scsiCmd ) == true )
1344: {
1345: break;
1346: }
1347: }
1348: }
1349:
1350: /*
1351: *
1352: *
1353: *
1354: */
1355: void IOSCSIParallelDevice::dispatchRequest()
1356: {
1357: target->state = kStateActive;
1358: controller->dispatchRequest();
1359: }
1360:
1361: /*
1362: *
1363: *
1364: *
1365: */
1366: bool IOSCSIParallelDevice::dispatch( UInt32 *dispatchAction )
1367: {
1368: bool rc;
1369:
1370: checkCancelQueue();
1371:
1372: if ( controller->checkBusReset() == true )
1373: {
1374: *dispatchAction = kDispatchStop;
1375: return true;
1376: }
1377:
1378: if ( (rc = controller->commandDisable) == true )
1379: {
1380: *dispatchAction = kDispatchNextTarget;
1381: return true;
1382: }
1383:
1384: if ( checkAbortQueue() == true )
1385: {
1386: *dispatchAction = kDispatchNextTarget;
1387: return true;
1388: }
1389:
1390: do
1391: {
1392: if ( (rc = controller->commandDisable) == true )
1393: {
1394: *dispatchAction = kDispatchStop;
1395: break;
1396: }
1397:
1398: if ( (rc = checkReqSense()) == true )
1399: {
1400: *dispatchAction = kDispatchNextTarget;
1401: break;
1402: }
1403:
1404: rc = checkDeviceQueue( dispatchAction );
1405:
1406: } while ( *dispatchAction == kDispatchNextCommand );
1407:
1408: return rc;
1409: }
1410:
1411:
1412: /*
1413: *
1414: *
1415: *
1416: */
1417: void IOSCSIParallelDevice::completeCommand( IOSCSIParallelCommand *scsiCmd )
1418: {
1419: SCSICommandType cmdType;
1420:
1421: cmdType = scsiCmd->cmdType;
1422: switch ( cmdType )
1423: {
1424: case kSCSICommandExecute:
1425: executeCommandDone( scsiCmd );
1426: break;
1427:
1428: case kSCSICommandReqSense:
1429: executeReqSenseDone( scsiCmd );
1430: break;
1431:
1432: case kSCSICommandAbort:
1433: case kSCSICommandAbortAll:
1434: case kSCSICommandDeviceReset:
1435: abortCommandDone( scsiCmd );
1436: break;
1437:
1438: case kSCSICommandCancel:
1439: cancelCommandDone( scsiCmd );
1440: break;
1441:
1442: default:
1443: ;
1444: }
1445:
1446: checkIdleNotify();
1447:
1448: dispatchRequest();
1449: }
1450:
1451: /*
1452: *
1453: *
1454: *
1455: */
1456: void IOSCSIParallelDevice::checkIdleNotify()
1457: {
1458: if ( idleNotifyActive == false )
1459: {
1460: return;
1461: }
1462:
1463: if ( (queue_empty( &activeList ) == true)
1464: && (queue_empty( &abortList ) == true)
1465: && (queue_empty( &cancelList ) == true)
1466: && (target->reqSenseCount == 0) )
1467: {
1468: idleNotifyActive = false;
1469: (idleNotifyCallback)( idleNotifyTarget, idleNotifyRefcon );
1470: }
1471: }
1472:
1473: /*
1474: *
1475: *
1476: *
1477: */
1478: void IOSCSIParallelDevice::flushQueue( UInt32 queueType, IOReturn rc )
1479: {
1480: queue_head_t *queue;
1481:
1482: queue = (queueType == kQTypeBypassQ) ? &bypassList : &deviceList;
1483: purgeAllCommands( queue, rc );
1484: }
1485:
1486: /*
1487: *
1488: *
1489: *
1490: */
1491: void IOSCSIParallelDevice::executeCommandDone( IOSCSIParallelCommand *scsiCmd )
1492: {
1493: deleteCommand( scsiCmd->list, scsiCmd );
1494:
1495: commandCount--;
1496: controller->commandCount--;
1497: target->commandCount--;
1498:
1499: if ( scsiCmd->scsiCmd.cdbTagMsg != 0 )
1500: {
1501: freeTag( scsiCmd->scsiCmd.cdbTag );
1502: scsiCmd->scsiCmd.cdbTag = (UInt32) -1;
1503: }
1504:
1505: if ( scsiCmd->scsiCmd.cdbFlags & (kCDBFlagsNegotiateSDTR | kCDBFlagsNegotiateWDTR | kCDBFlagsEnableTagQueuing) )
1506: {
1507: target->negotiateState = kStateIdle;
1508: target->commandLimit = target->commandLimitSave;
1509:
1510: if ( scsiCmd->results.adapterStatus != kSCSIAdapterStatusSuccess )
1511: {
1512: target->negotiateResult = kIOReturnIOError;
1513:
1514: target->targetParmsNew.transferWidth = 1;
1515: target->targetParmsNew.transferOffset = 0;
1516: target->targetParmsNew.transferPeriodpS = 0;
1517: target->targetParmsNew.enableTagQueuing = false;
1518:
1519: target->commandLimitSave = target->commandLimit = 1;
1520:
1521: target->negotiateState = kStateIssue;
1522: }
1523:
1524: IORWUnlock( target->targetSem );
1525: }
1526:
1527: if ( scsiCmd->scsiCmd.cdbFlags & kCDBFlagsNoDisconnect )
1528: {
1529: controller->commandLimit = controller->commandLimitSave;
1530: controller->noDisconnectCmd = 0;
1531: }
1532:
1533: if ( scsiCmd->results.scsiStatus == kSCSIStatusCheckCondition
1534: && scsiCmd->results.requestSenseDone == false
1535: && scsiCmd->senseData != 0 )
1536: {
1537: reqSenseOrigCmd = scsiCmd;
1538: reqSenseState = kStateIssue;
1539: target->reqSenseCount++;
1540: return;
1541: }
1542:
1543: if ( scsiCmd->results.scsiStatus == kSCSIStatusQueueFull )
1544: {
1545: if ( commandCount > 4 )
1546: {
1547: // IOLog( "IOSCSI: Q-full - commandCount = %d commandLimit = %d\n\r", commandCount, commandLimit );
1548: commandLimit = commandCount;
1549: }
1550:
1551: stackCommand( &deviceList, scsiCmd );
1552: return;
1553: }
1554:
1555: finishCommand( scsiCmd );
1556: }
1557:
1558: /*
1559: *
1560: *
1561: *
1562: */
1563: void IOSCSIParallelDevice::executeReqSenseDone( IOSCSIParallelCommand *scsiCmd )
1564: {
1565: IOSCSIParallelCommand *origCommand;
1566:
1567: deleteCommand( scsiCmd->list, scsiCmd );
1568:
1569: target->reqSenseState = reqSenseState = kStateIdle;
1570: target->reqSenseCount--;
1571:
1572: reqSenseOrigCmd = 0;
1573:
1574: origCommand = scsiCmd->origCommand;
1575:
1576: if ( (scsiCmd->results.returnCode == kIOReturnSuccess) || (scsiCmd->results.returnCode == kIOReturnUnderrun) )
1577: {
1578: origCommand->results.requestSenseDone = true;
1579: origCommand->results.requestSenseLength = scsiCmd->results.bytesTransferred;
1580: }
1581: else
1582: {
1583: origCommand->results.requestSenseDone = false;
1584: origCommand->results.requestSenseLength = 0;
1585: }
1586:
1587: finishCommand( scsiCmd->origCommand );
1588: }
1589:
1590: /*
1591: *
1592: *
1593: *
1594: */
1595: void IOSCSIParallelDevice::abortCommandDone( IOSCSIParallelCommand *scsiCmd )
1596: {
1597: IOSCSIParallelCommand *origSCSICmd;
1598: IOSCSIParallelDevice *abortDev;
1599:
1600: deleteCommand( scsiCmd->list, scsiCmd );
1601:
1602: if ( scsiCmd->cmdType == kSCSICommandAbortAll )
1603: {
1604: if ( client != 0 )
1605: {
1606: client->message( kSCSIClientMsgDeviceAbort | kSCSIClientMsgDone, this );
1607: }
1608: }
1609: if ( scsiCmd->cmdType == kSCSICommandDeviceReset )
1610: {
1611: target->commandLimit = target->commandLimitSave;
1612: target->reqSenseCount = 0;
1613: target->reqSenseState = kStateIdle;
1614: target->negotiateState = kStateIssue;
1615:
1616: target->targetParmsCurrent.transferPeriodpS = 0;
1617: target->targetParmsCurrent.transferOffset = 0;
1618: target->targetParmsCurrent.transferWidth = 1;
1619:
1620: queue_iterate( &target->deviceList, abortDev, IOSCSIParallelDevice *, nextDevice )
1621: {
1622: abortDev->resetOccurred( (SCSIClientMessage)(kSCSIClientMsgDeviceReset | kSCSIClientMsgDone) );
1623: }
1624: }
1625: else if ( scsiCmd->cmdType == kSCSICommandAbort )
1626: {
1627: origSCSICmd = scsiCmd->origCommand;
1628:
1629: if ( findCommand( &abortList, origSCSICmd ) == true )
1630: {
1631: moveCommand( &abortList, &cancelList, origSCSICmd, kIOReturnAborted );
1632: }
1633: abortState = kStateIdle;
1634: }
1635:
1636: return;
1637: }
1638:
1639: /*
1640: *
1641: *
1642: *
1643: */
1644: void IOSCSIParallelDevice::cancelCommandDone( IOSCSIParallelCommand *scsiCmd )
1645: {
1646: IOSCSIParallelCommand *origSCSICmd;
1647:
1648: cancelState = kStateIdle;
1649:
1650: origSCSICmd = scsiCmd->origCommand;
1651:
1652: if ( findCommand( &cancelList, origSCSICmd ) == true )
1653: {
1654: IOLog( "IOSCSIParallelDevice::cancelCommandDone - Cancelled command not completed - scsiCmd = %08x\n\r", (int)origSCSICmd );
1655: deleteCommand( &cancelList, origSCSICmd );
1656: }
1657: }
1658:
1659: /*
1660: *
1661: *
1662: *
1663: */
1664: void IOSCSIParallelDevice::finishCommand( IOSCSIParallelCommand *scsiCmd )
1665: {
1666: if ( scsiCmd->completionInfo.async.callback )
1667: {
1668: (*scsiCmd->completionInfo.async.callback)( scsiCmd->completionInfo.async.target,
1669: scsiCmd->completionInfo.async.refcon );
1670: }
1671: else
1672: {
1673: scsiCmd->completionInfo.sync.lock->signal();
1674: }
1675: }
1676:
1677:
1678: /*
1679: *
1680: *
1681: */
1682: OSDictionary *IOSCSIParallelDevice::createProperties()
1683: {
1684: OSDictionary *propTable = 0;
1685: OSObject *regObj;
1686: char tmpbuf[81];
1687: char *d;
1688:
1689:
1690: propTable = OSDictionary::withCapacity(kSCSIMaxProperties);
1691: if ( propTable == NULL )
1692: {
1693: return NULL;
1694: }
1695:
1696: regObj = (OSObject *)OSNumber::withNumber(targetLun.target,32);
1697: if ( addToRegistry( propTable, regObj, kSCSIPropertyTarget ) != true )
1698: {
1699: goto createprop_error;
1700: }
1701:
1702: regObj = (OSObject *)OSNumber::withNumber(targetLun.target,32);
1703: if ( addToRegistry( propTable, regObj, kSCSIPropertyIOUnit ) != true )
1704: {
1705: goto createprop_error;
1706: }
1707:
1708: regObj = (OSObject *)OSNumber::withNumber(targetLun.lun,32);
1709: if ( addToRegistry( propTable, regObj, kSCSIPropertyLun ) != true )
1710: {
1711: goto createprop_error;
1712: }
1713:
1714: d= tmpbuf;
1715:
1716: stripBlanks( d, (char *)inquiryData->vendorName, sizeof(inquiryData->vendorName) );
1717: regObj = (OSObject *)OSString::withCString( d );
1718: if ( addToRegistry( propTable, regObj, kSCSIPropertyVendorName ) != true )
1719: {
1720: goto createprop_error;
1721: }
1722:
1723: stripBlanks( d, (char *)inquiryData->productName, sizeof(inquiryData->productName) );
1724: regObj = (OSObject *)OSString::withCString( d );
1725: if ( addToRegistry( propTable, regObj, kSCSIPropertyProductName ) != true )
1726: {
1727: goto createprop_error;
1728: }
1729:
1730: stripBlanks( d, (char *)inquiryData->productRevision, sizeof(inquiryData->productRevision) );
1731: regObj = (OSObject *)OSString::withCString( d );
1732: if ( addToRegistry( propTable, regObj, kSCSIPropertyProductRevision ) != true )
1733: {
1734: goto createprop_error;
1735: }
1736:
1737: return propTable;
1738:
1739: createprop_error: ;
1740: propTable->release();
1741: return NULL;
1742: }
1743:
1744:
1745: /*
1746: *
1747: *
1748: */
1749: bool IOSCSIParallelDevice::addToRegistry( OSDictionary *propTable, OSObject *regObj, char *key )
1750: {
1751: bool rc;
1752:
1753: if ( regObj == NULL )
1754: {
1755: return false;
1756: }
1757:
1758: rc = propTable->setObject( key, regObj );
1759:
1760: return rc;
1761: }
1762:
1763:
1764: /*
1765: *
1766: *
1767: *
1768: */
1769: bool IOSCSIParallelDevice::matchPropertyTable(OSDictionary * table)
1770: {
1771: bool match;
1772:
1773: if ( (match = compareProperty(table, kSCSIPropertyIOUnit)) )
1774: match = super::matchPropertyTable(table);
1775:
1776: return match;
1777: }
1778:
1779:
1780: /*
1781: *
1782: *
1783: *
1784: */
1785: IOService *IOSCSIParallelDevice::matchLocation(IOService * client)
1786: {
1787: return this;
1788: }
1789:
1790:
1791: /*
1792: *
1793: *
1794: *
1795: */
1796: void IOSCSIParallelDevice::stripBlanks( char *d, char *s, UInt32 l )
1797: {
1798: char *p, c;
1799:
1800: for ( p = d, c = *s; l && c ; l--)
1801: {
1802: c = (*d++ = *s++);
1803: if ( c != ' ' )
1804: {
1805: p = d;
1806: }
1807: }
1808: *p = 0;
1809: }
1810:
1811: /*
1812: *
1813: *
1814: *
1815: */
1816: IOSCSICommand *IOSCSIParallelDevice::allocCommand( IOSCSIDevice *, UInt32 clientDataSize )
1817: {
1818: IOSCSIParallelCommand *cmd;
1819:
1820: if ( (cmd = controller->allocCommand( clientDataSize )) )
1821: {
1822: cmd->device = this;
1823: }
1824: return (IOSCSICommand *)cmd;
1825: }
1826:
1827: IOSCSIParallelCommand *IOSCSIParallelDevice::allocCommand( IOSCSIParallelDevice *, UInt32 clientDataSize )
1828: {
1829: return (IOSCSIParallelCommand *) allocCommand( kIOSCSIDevice, clientDataSize );
1830: }
1831:
1832: IOCDBCommand *IOSCSIParallelDevice::allocCommand( IOCDBDevice *, UInt32 clientDataSize )
1833: {
1834: return (IOCDBCommand *) allocCommand( kIOSCSIDevice, clientDataSize );
1835: }
1836:
1837:
1838: /*
1839: *
1840: *
1841: */
1842: IOWorkLoop *IOSCSIParallelDevice::getWorkLoop() const
1843: {
1844: return controller->workLoop;
1845: }
1846:
1847:
1848: /*
1849: *
1850: *
1851: *
1852: */
1853: bool IOSCSIParallelDevice::open( IOService *forClient, IOOptionBits options, void *arg )
1854: {
1855: if ( client != 0 ) return false;
1856:
1857: client = forClient;
1858:
1859: return super::open( forClient, options, arg );
1860: }
1861:
1862: /*
1863: *
1864: *
1865: *
1866: */
1867: void IOSCSIParallelDevice::close( IOService *forClient, IOOptionBits options )
1868: {
1869: client = 0;
1870:
1871: return super::close( forClient, options );
1872: }
1873:
1874: /*
1875: *
1876: *
1877: *
1878: */
1879: IOReturn IOSCSIParallelDevice::message( UInt32 forMsg, IOService *forProvider, void *forArg )
1880: {
1881: IOReturn rc = kIOReturnSuccess;
1882: SCSIClientMessage clientMsg;
1883:
1884: clientMsg = (SCSIClientMessage) forMsg;
1885:
1886: // IOLog( "IOSCSIParallelDevice::message() - clientMsg = %08x\n\r", clientMsg );
1887:
1888: switch( clientMsg )
1889: {
1890: case kSCSIClientMsgBusReset:
1891: holdQueue( kQTypeNormalQ );
1892: break;
1893: case kSCSIClientMsgBusReset | kSCSIClientMsgDone:
1894: releaseQueue( kQTypeNormalQ );
1895: break;
1896: default:
1897: rc = super::message( clientMsg, forProvider, forArg );
1898: }
1899:
1900: return rc;
1901: }
1902:
1903: /*
1904: *
1905: *
1906: *
1907: */
1908: void IOSCSIParallelDevice::free()
1909: {
1910: if ( deviceGate != 0 )
1911: {
1912: controller->workLoop->removeEventSource( deviceGate );
1913: deviceGate->release();
1914: }
1915:
1916: if ( reqSenseCmd != 0 ) reqSenseCmd->release();
1917: if ( abortCmd != 0 ) abortCmd->release();
1918: if ( cancelCmd != 0 ) cancelCmd->release();
1919: if ( probeCmd != 0 ) probeCmd->release();
1920:
1921: if ( tagArray != 0 ) IOFree( tagArray, controller->tagArraySize );
1922: if ( inquiryData != 0 ) IOFree( inquiryData, inquiryDataSize );
1923: if ( devicePrivateData != 0 ) IOFreeContiguous( devicePrivateData, controller->controllerInfo.lunPrivateDataSize );
1924: if ( clientSem != 0 ) IORWLockFree( clientSem );
1925:
1926: super::free();
1927: }
1928:
1929:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.