]> git.saurik.com Git - apple/xnu.git/blame - iokit/Families/IOSCSIParallel/IOSCSIParallelController.cpp
xnu-201.42.3.tar.gz
[apple/xnu.git] / iokit / Families / IOSCSIParallel / IOSCSIParallelController.cpp
CommitLineData
1c79356b
A
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 * IOSCSIParallelController.cpp
24 *
25 */
26
27#include <IOKit/scsi/IOSCSIParallelInterface.h>
28#include <IOKit/IOSyncer.h>
29
30#undef super
31#define super IOService
32
33OSDefineMetaClass( IOSCSIParallelController, IOService )
34OSDefineAbstractStructors( IOSCSIParallelController, IOService );
35
36#define round(x,y) (((int)(x) + (y) - 1) & ~((y)-1))
37
38/*
39 *
40 *
41 */
42bool IOSCSIParallelController::start( IOService *forProvider )
43{
44 provider = forProvider;
45
46 if ( provider->open( this ) != true )
47 {
48 return false;
49 }
50
51 if ( createWorkLoop() != true )
52 {
53 return false;
54 }
55
56 if ( configureController() == false )
57 {
58 provider->close( this );
59 return false;
60 }
61
62 initQueues();
63
64 if ( scanSCSIBus() == false )
65 {
66 provider->close( this );
67 return false;
68 }
69
70 return true;
71}
72
73/*
74 *
75 *
76 *
77 */
78bool IOSCSIParallelController::scanSCSIBus()
79{
80 SCSITargetLun targetLun;
81 UInt32 i;
82
83 targetLun.lun = 0;
84
85 for ( i=0; i < controllerInfo.maxTargetsSupported; i++ )
86 {
87 targetLun.target = i;
88 probeTarget( targetLun );
89 }
90
91 return true;
92}
93
94/*
95 *
96 *
97 *
98 */
99bool IOSCSIParallelController::probeTarget( SCSITargetLun targetLun )
100{
101 IOSCSIParallelDevice *device;
102 UInt32 i;
103
104 if ( targetLun.target == controllerInfo.initiatorId )
105 {
106 return false;
107 }
108
109 if ( initTarget( targetLun ) == false )
110 {
111 releaseTarget( targetLun );
112 return false;
113 }
114
115 for ( i=0; i < controllerInfo.maxLunsSupported; i++ )
116 {
117 targetLun.lun = i;
118
119 device = createDevice();
120 if ( device == 0 )
121 {
122 break;
123 }
124
125 if ( device->init( this, targetLun ) == false )
126 {
127 releaseDevice( device );
128 break;
129 }
130
131 if ( initDevice( device ) == false )
132 {
133 releaseDevice( device );
134 continue;
135 }
136
137 if ( device->probeTargetLun() != kIOReturnSuccess )
138 {
139 releaseDevice( device );
140 if ( i == 0 ) break;
141 }
142 }
143
144 if ( i == 0 )
145 {
146 releaseTarget( targetLun );
147 return false;
148 }
149
150 queue_iterate( &targets[targetLun.target].deviceList, device, IOSCSIParallelDevice *, nextDevice )
151 {
152 device->setupTarget();
153 device->attach( this );
154 device->registerService();
155 }
156
157 return true;
158}
159
160/*
161 *
162 *
163 *
164 */
165bool IOSCSIParallelController::initTargetGated( SCSITargetLun *targetLun )
166{
167 return initTarget( *targetLun );
168}
169
170bool IOSCSIParallelController::initTarget( SCSITargetLun targetLun )
171{
172 SCSITarget *target;
173 UInt32 number;
174
175 if ( getWorkLoop()->inGate() == false )
176 {
177 return controllerGate->runAction( (IOCommandGate::Action)&IOSCSIParallelController::initTargetGated, (void *)&targetLun );
178 }
179
180 target = &targets[targetLun.target];
181
182 target->clientSem = IORWLockAlloc();
183 target->targetSem = IORWLockAlloc();
184 if( (target->targetSem == 0) || (target->clientSem == 0))
185 {
186 return false;
187 }
188 target->commandLimitSave = target->commandLimit = 1;
189
190 target->targetParmsCurrent.transferWidth = 1;
191
192 if ( controllerInfo.targetPrivateDataSize != 0 )
193 {
194 target->targetPrivateData = IOMallocContiguous( controllerInfo.targetPrivateDataSize, 16, 0 );
195 if ( target->targetPrivateData == 0 )
196 {
197 return false;
198 }
199 }
200
201 if ( controllerInfo.tagAllocationMethod == kTagAllocationPerTarget )
202 {
203 target->tagArray = (UInt32 *)IOMalloc( tagArraySize );
204 if ( target->tagArray == 0 )
205 {
206 return false;
207 }
208 bzero( target->tagArray, tagArraySize );
209 }
210
211 number = 0;
212 target->regObjTransferPeriod = OSNumber::withNumber( number, 32 );
213 if ( target->regObjTransferPeriod == 0 )
214 {
215 return false;
216 }
217
218 number = 0;
219 target->regObjTransferOffset = OSNumber::withNumber( number, 32 );
220 if ( target->regObjTransferOffset == 0 )
221 {
222 return false;
223 }
224
225 number = 1;
226 target->regObjTransferWidth = OSNumber::withNumber( number, 32 );
227 if ( target->regObjTransferWidth == 0 )
228 {
229 return false;
230 }
231
232 number = 0;
233 target->regObjTransferOptions = OSNumber::withNumber( number, 32 );
234 if ( target->regObjTransferOptions == 0 )
235 {
236 return false;
237 }
238
239 number = 0;
240 target->regObjCmdQueue = OSNumber::withNumber( number, 32 );
241 if ( target->regObjCmdQueue == 0 )
242 {
243 return false;
244 }
245
246 target->targetAllocated = allocateTarget( targetLun );
247
248 return target->targetAllocated;
249}
250
251/*
252 *
253 *
254 *
255 */
256void IOSCSIParallelController::releaseTargetGated( SCSITargetLun *targetLun )
257{
258 releaseTarget( *targetLun );
259}
260
261void IOSCSIParallelController::releaseTarget( SCSITargetLun targetLun )
262{
263 SCSITarget *target;
264
265 if ( getWorkLoop()->inGate() == false )
266 {
267 controllerGate->runAction( (IOCommandGate::Action)&IOSCSIParallelController::releaseTargetGated, (void *)&targetLun );
268 return;
269 }
270
271 target = &targets[targetLun.target];
272
273 if ( queue_empty( &target->deviceList ) != true )
274 {
275 IOLog("IOSCSIParallelController()::Target %d deleted with lun(s) active!\n\r",
276 targetLun.target );
277 }
278
279 if ( target->targetAllocated == true )
280 {
281 deallocateTarget( targetLun );
282
283 target->targetAllocated = false;
284 }
285
286 if ( target->tagArray != 0 )
287 {
288 IOFree( target->tagArray, tagArraySize );
289 target->tagArray = 0;
290 }
291
292 if ( target->targetPrivateData != 0 )
293 {
294 IOFreeContiguous( target->targetPrivateData, controllerInfo.targetPrivateDataSize );
295 target->targetPrivateData = 0;
296 }
297
298 if ( target->clientSem != 0 )
299 {
300 IORWLockFree( target->clientSem );
301 }
302 if ( target->targetSem != 0 )
303 {
304 IORWLockFree( target->targetSem );
305 }
306
307 if ( target->regObjTransferPeriod != 0 )
308 {
309 target->regObjTransferPeriod->release();
310 target->regObjTransferPeriod = 0;
311 }
312 if ( target->regObjTransferOffset != 0 )
313 {
314 target->regObjTransferOffset->release();
315 target->regObjTransferOffset = 0;
316 }
317 if ( target->regObjTransferWidth != 0 )
318 {
319 target->regObjTransferWidth->release();
320 target->regObjTransferWidth = 0;
321 }
322 if ( target->regObjCmdQueue != 0 )
323 {
324 target->regObjCmdQueue->release();
325 target->regObjCmdQueue = 0;
326 }
327
328}
329
330/*
331 *
332 *
333 *
334 */
335bool IOSCSIParallelController::initDeviceGated( IOSCSIParallelDevice *device )
336{
337 return initDevice( device );
338}
339
340bool IOSCSIParallelController::initDevice( IOSCSIParallelDevice *device )
341{
342 if ( getWorkLoop()->inGate() == false )
343 {
344 return controllerGate->runAction( (IOCommandGate::Action)&IOSCSIParallelController::initDeviceGated, (void *)device );
345 }
346
347 addDevice( device );
348 device->lunAllocated = allocateLun( device->targetLun );
349
350 return device->lunAllocated;
351}
352
353/*
354 *
355 *
356 *
357 */
358void IOSCSIParallelController::releaseDeviceGated( IOSCSIParallelDevice *device )
359{
360 releaseDevice( device );
361 return;
362}
363
364void IOSCSIParallelController::releaseDevice( IOSCSIParallelDevice *device )
365{
366 if ( getWorkLoop()->inGate() == false )
367 {
368 controllerGate->runAction( (IOCommandGate::Action)&IOSCSIParallelController::releaseDeviceGated, (void *)device );
369 return;
370 }
371
372 deleteDevice( device );
373 if ( device->lunAllocated == true )
374 {
375 deallocateLun( device->targetLun );
376 }
377
378 device->release();
379}
380
381
382/*
383 *
384 *
385 *
386 */
387void IOSCSIParallelController::addDevice( IOSCSIParallelDevice *forDevice )
388{
389 UInt32 targetID;
390
391 targetID = forDevice->targetLun.target;
392
393 forDevice->target = &targets[targetID];
394 queue_enter( &targets[targetID].deviceList, forDevice, IOSCSIParallelDevice *, nextDevice );
395}
396
397/*
398 *
399 *
400 *
401 */
402void IOSCSIParallelController::deleteDevice( IOSCSIParallelDevice *forDevice )
403{
404 queue_head_t *deviceList;
405 IOSCSIParallelDevice *device;
406 UInt32 targetID;
407
408 targetID = forDevice->targetLun.target;
409
410 deviceList = &targets[targetID].deviceList;
411
412 queue_iterate( deviceList, device, IOSCSIParallelDevice *, nextDevice )
413 {
414 if ( device == forDevice )
415 {
416 queue_remove( &targets[targetID].deviceList, device, IOSCSIParallelDevice *, nextDevice );
417 break;
418 }
419 }
420}
421
422/*
423 *
424 *
425 *
426 */
427bool IOSCSIParallelController::allocateTarget( SCSITargetLun targetLun )
428{
429 return true;
430}
431
432/*
433 *
434 *
435 *
436 */
437void IOSCSIParallelController::deallocateTarget( SCSITargetLun targetLun )
438{
439}
440
441/*
442 *
443 *
444 *
445 */
446bool IOSCSIParallelController::allocateLun( SCSITargetLun targetLun )
447{
448 return true;
449}
450
451/*
452 *
453 *
454 *
455 */
456void IOSCSIParallelController::deallocateLun( SCSITargetLun targetLun )
457{
458}
459
460
461/*
462 *
463 *
464 *
465 */
466void *IOSCSIParallelController::getTargetData( SCSITargetLun targetLun )
467{
468 return targets[targetLun.target].targetPrivateData;
469}
470
471/*
472 *
473 *
474 *
475 */
476void *IOSCSIParallelController::getLunData( SCSITargetLun targetLun )
477{
478 queue_head_t *deviceList;
479 IOSCSIParallelDevice *device;
480
481 deviceList = &targets[targetLun.target].deviceList;
482
483 queue_iterate( deviceList, device, IOSCSIParallelDevice *, nextDevice )
484 {
485 if ( device->targetLun.lun == targetLun.lun )
486 {
487 return device->devicePrivateData;
488 }
489 }
490 return 0;
491}
492
493
494
495/*
496 *
497 *
498 *
499 */
500IOSCSIParallelDevice *IOSCSIParallelController::createDevice()
501{
502 return new IOSCSIParallelDevice;
503}
504
505
506/*
507 *
508 *
509 *
510 */
511void IOSCSIParallelController::initQueues()
512{
513 UInt32 i;
514
515 for ( i=0; i < controllerInfo.maxTargetsSupported; i++ )
516 {
517 queue_init( &targets[i].deviceList );
518 }
519
520 resetCmd = allocCommand( 0 );
521 resetCmd->cmdType = kSCSICommandBusReset;
522
523 timer( timerEvent );
524}
525
526/*
527 *
528 *
529 *
530 */
531void IOSCSIParallelController::reset()
532{
533 IOSCSIParallelDevice *device;
534 UInt32 i;
535
536 if ( busResetState != kStateIssue )
537 {
538 return;
539 }
540
541 busResetState = kStateActive;
542
543 for (i=0; i < controllerInfo.maxTargetsSupported; i++ )
544 {
545 queue_iterate( &targets[i].deviceList, device, IOSCSIParallelDevice *, nextDevice )
546 {
547 if ( device->client != 0 )
548 {
549 device->client->message( kSCSIClientMsgBusReset, device );
550 }
551 }
552 }
553
554 resetCommand( resetCmd );
555}
556
557/*
558 *
559 *
560 *
561 */
562bool IOSCSIParallelController::checkBusReset()
563{
564 if ( busResetState == kStateIdle )
565 {
566 return false;
567 }
568 if ( busResetState == kStateIssue )
569 {
570 reset();
571 }
572 return true;
573}
574
575
576/*
577 *
578 *
579 *
580 */
581void IOSCSIParallelController::resetOccurred()
582{
583 UInt32 i;
584 IOSCSIParallelDevice *device;
585 SCSITarget *target;
586 SCSIClientMessage clientMsg;
587
588 for (i=0; i < controllerInfo.maxTargetsSupported; i++ )
589 {
590 target = &targets[i];
591
592 target->commandLimit = target->commandLimitSave;
593 target->reqSenseCount = 0;
594 target->reqSenseState = kStateIdle;
595 target->negotiateState = kStateIssue;
596
597 target->targetParmsCurrent.transferPeriodpS = 0;
598 target->targetParmsCurrent.transferOffset = 0;
599 target->targetParmsCurrent.transferWidth = 1;
600
601 noDisconnectCmd = 0;
602
603 clientMsg = ( busResetState != kStateActive ) ? kSCSIClientMsgBusReset : kSCSIClientMsgNone;
604
605 queue_iterate( &target->deviceList, device, IOSCSIParallelDevice *, nextDevice )
606 {
607 device->resetOccurred( clientMsg );
608 }
609 }
610
611 resetTimer = (kSCSIResetIntervalmS / kSCSITimerIntervalmS + 1);
612}
613
614
615/*
616 *
617 *
618 */
619void IOSCSIParallelController::timer( IOTimerEventSource * /* timer */ )
620{
621 UInt32 i;
622 IOSCSIParallelDevice *device;
623
624
625 if ( disableTimer )
626 {
627 if ( !--disableTimer )
628 {
629 disableTimeoutOccurred();
630 }
631 }
632
633 if ( resetTimer )
634 {
635 if ( !--resetTimer )
636 {
637 for (i=0; i < controllerInfo.maxTargetsSupported; i++ )
638 {
639 queue_iterate( &targets[i].deviceList, device, IOSCSIParallelDevice *, nextDevice )
640 {
641 device->resetComplete();
642 }
643 }
644
645 }
646 }
647 else
648 {
649 for (i=0; i < controllerInfo.maxTargetsSupported; i++ )
650 {
651 queue_iterate( &targets[i].deviceList, device, IOSCSIParallelDevice *, nextDevice )
652 {
653 device->timer();
654 }
655 }
656 }
657
658 timerEvent->setTimeoutMS(kSCSITimerIntervalmS);
659}
660
661
662/*
663 *
664 *
665 *
666 */
667void IOSCSIParallelController::completeCommand( IOSCSIParallelCommand *scsiCmd )
668{
669 switch ( scsiCmd->cmdType )
670 {
671 case kSCSICommandBusReset:
672 resetOccurred();
673 busResetState = kStateIdle;
674 break;
675 default:
676 ;
677 }
678}
679
680
681/*
682 *
683 *
684 *
685 */
686bool IOSCSIParallelController::createWorkLoop()
687{
688 workLoop = getWorkLoop();
689 if ( workLoop == 0 )
690 {
691 workLoop = IOWorkLoop::workLoop();
692 if ( workLoop == 0 )
693 {
694 return false;
695 }
696 }
697
698 timerEvent = IOTimerEventSource::timerEventSource( this, (IOTimerEventSource::Action) &IOSCSIParallelController::timer );
699 if ( timerEvent == 0 )
700 {
701 return false;
702 }
703
704 if ( workLoop->addEventSource( timerEvent ) != kIOReturnSuccess )
705 {
706 return false;
707 }
708
709
710 dispatchEvent = IOInterruptEventSource::interruptEventSource( this,
711 (IOInterruptEventAction) &IOSCSIParallelController::dispatch,
712 0 );
713 if ( dispatchEvent == 0 )
714 {
715 return false;
716 }
717
718 if ( workLoop->addEventSource( dispatchEvent ) != kIOReturnSuccess )
719 {
720 return false;
721 }
722
723 controllerGate = IOCommandGate::commandGate( this, (IOCommandGate::Action) 0 );
724 if ( controllerGate == 0 )
725 {
726 return false;
727 }
728
729 if ( workLoop->addEventSource( controllerGate ) != kIOReturnSuccess )
730 {
731 return false;
732 }
733
734 return true;
735}
736
737/*
738 *
739 *
740 *
741 */
742IOSCSIParallelCommand *IOSCSIParallelController::findCommandWithNexus( SCSITargetLun targetLun, UInt32 tagValue = (UInt32)-1 )
743{
744 IOSCSIParallelDevice *device;
745
746 device = findDeviceWithTargetLun( targetLun );
747 if ( device == 0 )
748 {
749 return 0;
750 }
751
752 return device->findCommandWithNexus( tagValue );
753}
754
755
756/*
757 *
758 *
759 *
760 */
761IOSCSIParallelDevice *IOSCSIParallelController::findDeviceWithTargetLun( SCSITargetLun targetLun )
762{
763 IOSCSIParallelDevice *device;
764
765 if ( targetLun.target > controllerInfo.maxTargetsSupported || targetLun.lun > controllerInfo.maxLunsSupported )
766 {
767 return 0;
768 }
769
770 queue_iterate( &targets[targetLun.target].deviceList, device, IOSCSIParallelDevice *, nextDevice )
771 {
772 if ( device->targetLun.lun == targetLun.lun )
773 {
774 return device;
775 }
776 }
777 return 0;
778}
779
780
781/*
782 *
783 *
784 *
785 */
786bool IOSCSIParallelController::configureController()
787{
788 UInt32 targetsSize;
789
790 if ( configure( provider, &controllerInfo ) == false )
791 {
792 return false;
793 }
794
795 controllerInfo.commandPrivateDataSize = round( controllerInfo.commandPrivateDataSize, 16 );
796
797 if ( controllerInfo.maxCommandsPerController == 0 ) controllerInfo.maxCommandsPerController = (UInt32) -1;
798 if ( controllerInfo.maxCommandsPerTarget == 0 ) controllerInfo.maxCommandsPerTarget = (UInt32) -1;
799 if ( controllerInfo.maxCommandsPerLun == 0 ) controllerInfo.maxCommandsPerLun = (UInt32) -1;
800
801 targetsSize = controllerInfo.maxTargetsSupported * sizeof(SCSITarget);
802 targets = (SCSITarget *)IOMalloc( targetsSize );
803 bzero( targets, targetsSize );
804
805 commandLimit = commandLimitSave = controllerInfo.maxCommandsPerController;
806
807 tagArraySize = (controllerInfo.maxTags / 32 + ((controllerInfo.maxTags % 32) ? 1 : 0)) * sizeof(UInt32);
808
809 if ( controllerInfo.tagAllocationMethod == kTagAllocationPerController )
810 {
811 tagArray = (UInt32 *)IOMalloc( tagArraySize );
812 bzero( tagArray, tagArraySize );
813 }
814
815 return true;
816}
817
818/*
819 *
820 *
821 *
822 */
823void IOSCSIParallelController::setCommandLimit( UInt32 newCommandLimit )
824{
825 if ( newCommandLimit == 0 ) controllerInfo.maxCommandsPerController = (UInt32) -1;
826
827 commandLimit = commandLimitSave = controllerInfo.maxCommandsPerController;
828}
829
830/*
831 *
832 *
833 *
834 */
835IOWorkLoop *IOSCSIParallelController::getWorkLoop() const
836{
837 return workLoop;
838}
839
840/*
841 *
842 *
843 *
844 */
845void IOSCSIParallelController::disableCommands( UInt32 disableTimeoutmS )
846{
847 commandDisable = true;
848
849 disableTimer = ( disableTimeoutmS != 0 ) ? (disableTimeoutmS / kSCSITimerIntervalmS + 1) : 0;
850}
851
852
853/*
854 *
855 *
856 *
857 */
858void IOSCSIParallelController::disableCommands()
859{
860 UInt32 disableTimeout;
861
862 commandDisable = true;
863
864 disableTimeout = kSCSIDisableTimeoutmS;
865
866 if ( noDisconnectCmd != 0 )
867 {
868 disableTimeout = noDisconnectCmd->getTimeout();
869 if ( disableTimeout != 0 ) disableTimeout += kSCSIDisableTimeoutmS;
870 }
871
872 disableTimer = ( disableTimeout != 0 ) ? (disableTimeout / kSCSITimerIntervalmS + 1) : 0;
873}
874
875/*
876 *
877 *
878 *
879 */
880void IOSCSIParallelController::disableTimeoutOccurred()
881{
882 busResetState = kStateIssue;
883 dispatchRequest();
884}
885
886/*
887 *
888 *
889 *
890 */
891void IOSCSIParallelController::rescheduleCommand( IOSCSIParallelCommand *forSCSICmd )
892{
893 forSCSICmd->getDevice(kIOSCSIParallelDevice)->rescheduleCommand( forSCSICmd );
894}
895
896/*
897 *
898 *
899 *
900 */
901void IOSCSIParallelController::enableCommands()
902{
903 commandDisable = false;
904
905 disableTimer = 0;
906
907 dispatchRequest();
908}
909
910/*
911 *
912 *
913 *
914 */
915void IOSCSIParallelController::dispatchRequest()
916{
917 dispatchEvent->interruptOccurred(0, 0, 0);
918}
919
920
921/*
922 *
923 *
924 *
925 */
926void IOSCSIParallelController::dispatch()
927{
928 SCSITarget *target;
929 IOSCSIParallelDevice *device;
930 UInt32 dispatchAction;
931 UInt32 lunsActive = 0;
932 UInt32 i;
933
934 if ( !targets || checkBusReset() )
935 {
936 goto dispatch_Exit;
937 }
938
939 for ( i = 0; i < controllerInfo.maxTargetsSupported; i++ )
940 {
941 target = &targets[i];
942
943 if ( target->state == kStateActive )
944 {
945 lunsActive = 0;
946
947 queue_iterate( &target->deviceList, device, IOSCSIParallelDevice *, nextDevice )
948 {
949 if ( device->dispatch( &dispatchAction ) == true )
950 {
951 lunsActive++;
952 }
953
954 switch ( dispatchAction )
955 {
956 case kDispatchNextLun:
957 ;
958 case kDispatchNextTarget:
959 break;
960 case kDispatchStop:
961 goto dispatch_Exit;
962 }
963 }
964 if ( lunsActive == 0 )
965 {
966 target->state = kStateIdle;
967 }
968 }
969 }
970
971dispatch_Exit:
972 ;
973}
974
975/*
976 *
977 *
978 *
979 */
980IOSCSIParallelCommand *IOSCSIParallelController::allocCommand(UInt32 clientDataSize )
981{
982 IOSCSIParallelCommand *cmd;
983 UInt32 size;
984
985 size = controllerInfo.commandPrivateDataSize + round(clientDataSize, 16);
986
987 cmd = new IOSCSIParallelCommand;
988 if ( !cmd )
989 {
990 return 0;
991 }
992 cmd->init();
993
994 if ( size )
995 {
996 cmd->dataArea = (void *)IOMallocContiguous( (vm_size_t)size, 16, 0 );
997 if ( !cmd->dataArea )
998 {
999 cmd->release();
1000 return 0;
1001 }
1002
1003 bzero( cmd->dataArea, size );
1004
1005 cmd->dataSize = size;
1006
1007 if ( controllerInfo.commandPrivateDataSize )
1008 {
1009 cmd->commandPrivateData = cmd->dataArea;
1010 }
1011 if ( clientDataSize )
1012 {
1013 cmd->clientData = (void *)((UInt8 *)cmd->dataArea + controllerInfo.commandPrivateDataSize);
1014 }
1015 }
1016
1017 cmd->controller = this;
1018
1019 return cmd;
1020}
1021
1022/*
1023 *
1024 *
1025 *
1026 */
1027void IOSCSIParallelController::free()
1028{
1029 UInt32 targetsSize;
1030 UInt32 i;
1031
1032 if ( controllerGate != 0 )
1033 {
1034 workLoop->removeEventSource( controllerGate );
1035 controllerGate->release();
1036 }
1037
1038 if ( timerEvent != 0 ) timerEvent->release();
1039
1040 if ( dispatchEvent != 0 ) dispatchEvent->release();
1041
1042 if ( resetCmd != 0 ) resetCmd->release();
1043
1044 if ( workLoop != 0 ) workLoop->release();
1045
1046 if ( targets != 0 )
1047 {
1048 for ( i=0; i < controllerInfo.maxTargetsSupported; i++ )
1049 {
1050 if ( targets[i].targetPrivateData != 0 )
1051 {
1052 IOFreeContiguous( targets[i].targetPrivateData, controllerInfo.targetPrivateDataSize );
1053 }
1054 }
1055
1056 targetsSize = controllerInfo.maxTargetsSupported * sizeof(SCSITarget);
1057 IOFree( targets, targetsSize );
1058 }
1059
1060 if ( tagArray != 0 ) IOFree( tagArray, tagArraySize );
1061
1062 super::free();
1063}
1064
1065/*
1066 *
1067 *
1068 *
1069 */
1070void IOSCSIParallelCommand::free()
1071{
1072 if ( dataArea )
1073 {
1074 IOFreeContiguous( dataArea, dataSize );
1075 }
1076
1077 OSObject::free();
1078}
1079