1
/* Copyright (c) 1996-2004, Adaptec Corporation
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* - Redistributions of source code must retain the above copyright notice, this
8
* list of conditions and the following disclaimer.
9
* - Redistributions in binary form must reproduce the above copyright notice,
10
* this list of conditions and the following disclaimer in the documentation
11
* and/or other materials provided with the distribution.
12
* - Neither the name of the Adaptec Corporation nor the names of its
13
* contributors may be used to endorse or promote products derived from this
14
* software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
* POSSIBILITY OF SUCH DAMAGE.
29
/****************************************************************************
33
*****************************************************************************
35
* File Name: DeletRad.cpp
37
* Contributors: Lee Page
44
*****************************************************************************/
47
#include "deletrad.hpp"
49
#include "ctlr_map.hpp"
50
#include "intlist.hpp"
56
/*** EXTERNAL DATA ***/
57
extern int FID_RESET_OUTBUFF;
58
extern uSHORT LOG_LIST_SIZE;
63
/****************************************************************************
65
* Function Name: Delete_Raid(), Created:7/30/98
67
* Description: This deletes the logicals listed. If null is passed in, then
68
ALL logicals will be deleted.
72
* Notes: ALL LOGICALS WILL BE DELETED IF NULL IS PASSED IN!
74
*****************************************************************************/
76
Delete_Raid::Delete_Raid(
77
SCSI_Addr_List *which_Raids,
79
: raids_to_Del( which_Raids ),
80
delete_Hiddens( del_Hiddens )
82
ENTER( "Delete_Raid::Delete_Raid(" );
87
Delete_Raid::Delete_Raid( const Delete_Raid &del_Raid ): delete_Hiddens( del_Raid.delete_Hiddens )
89
ENTER( "Delete_Raid::Delete_Raid( const Delete_Raid &del_Raid ): delete_Hiddens( del_Raid.delete_Hiddens )" );
90
if( del_Raid.raids_to_Del )
92
raids_to_Del = new SCSI_Addr_List( *del_Raid.raids_to_Del );
101
Delete_Raid::~Delete_Raid()
103
ENTER( "Delete_Raid::~Delete_Raid()" );
108
Command::Dpt_Error Delete_Raid::execute( String_List **output )
110
ENTER( "Command::Dpt_Error Delete_Raid::execute( String_List **output )" );
112
Dpt_Error err = Dpt_Error::DPT_CMD_ERR_NO_ERROR;
113
extern void add_Unique_Item( Int_List *component_List, DPT_TAG_T component_Tag );
115
Int_List raid_List_dual;
117
*output = out = new String_List();
123
Make_Address_List_of_All_Logicals( &raids_to_Del );
126
while( raids_to_Del->num_Left() )
128
bool more_Devs_Left = true;
129
bool tag_Valid; //kds
130
SCSI_Address trash_addr; //kds
131
SCSI_Address raid_Address = raids_to_Del->get_Next_Item();
132
// get this raid's tag
133
for (int dev_Index = 0; more_Devs_Left; dev_Index++)
135
get_Devs_Type devs_Type;
137
DPT_TAG_T raid_Tag = Get_Address_by_Index( raid_Address,
138
dev_Index, &more_Devs_Left, &devs_Type );
139
if ( !more_Devs_Left )
146
case GET_RAID_HOT_SPARE:
147
case GET_RAID_REDIRECT:
152
if ((devs_Type == GET_RAID_HOT_SPARE) ^ (delete_Hiddens == 0))
154
trash_addr = DPT_Tag_to_Address (raid_Tag, &tag_Valid);
155
// if dual level array, put in one list
156
if (trash_addr.level >= 2)
157
add_Unique_Item ( &raid_List_dual, raid_Tag);
158
// otherwise put in other
160
add_Unique_Item( &raid_List, raid_Tag );
165
raid_List_dual.reset_Next_Index();
166
raid_List.reset_Next_Index();
168
// invalid if target not found -kds
169
if ((raid_List_dual.num_Left() == 0) &&
170
(raid_List.num_Left() == 0))
172
err = Dpt_Error::DPT_CMD_ERR_CANT_FIND_COMPONENT;
173
out->add_Item( (char *) err );
178
// get rid of parents and their children first
179
if (raid_List_dual.num_Left())
181
while( raid_List_dual.num_Left() )
183
Dpt_Error this_err = Delete_Raid_and_Children(
184
raid_List_dual.get_Next_Item(), out );
185
if( this_err.Is_Error() )
188
// output intermediate errors, but don't stop
190
out->add_Item( (char *) this_err );
194
// now get rid of orphans
195
if (raid_List.num_Left())
197
while( raid_List.num_Left() )
199
Dpt_Error this_err = Delete_Raid_and_Children(
200
raid_List.get_Next_Item(), out );
201
// this was already deleted in if (dual) above
202
if (this_err == Dpt_Error::DPT_ERR_INVALID_TGT_TAG)
203
this_err = Dpt_Error::DPT_CMD_ERR_NO_ERROR;
204
// other errors are really errors
205
if( this_err.Is_Error() )
208
// output intermediate errors, but don't stop
210
out->add_Item( (char *) this_err );
223
/****************************************************************************
225
* Function Name: Make_Address_List_of_All_Logicals(), Created:7/30/98
227
* Description: This fetches a list of all logicals, whether they be parent
230
* Return: SCSI_Addr_List
232
* Notes: The caller must deallocate the object returned.
234
*****************************************************************************/
236
void Delete_Raid::Make_Address_List_of_All_Logicals( SCSI_Addr_List **ret_List )
238
ENTER( "void Delete_Raid::Make_Address_List_of_All_Logicals( SCSI_Addr_List **ret_List )" );
239
SCSI_Addr_List *addr_List;
241
bool index_Found = true; // force it to succeed the first time through
244
addr_List = new SCSI_Addr_List();
246
for( dev_Index = 0; index_Found; dev_Index++ )
248
SCSI_Address this_Logicals_Address;
249
DPT_TAG_T this_Logicals_Tag;
251
this_Logicals_Tag = Get_Log_Dev_by_Index( dev_Index, (bool)false, &index_Found );
254
this_Logicals_Address = DPT_Tag_to_Address( this_Logicals_Tag, &index_Found );
258
addr_List->add_Item( this_Logicals_Address );
263
*ret_List = addr_List;
267
Command::Dpt_Error Delete_Raid::Delete_Raid_and_Children(
271
ENTER( "Command::Dpt_Error Delete_Raid::Delete_Raid_and_Children(" );
272
Dpt_Error err, busy_err;
275
Int_List component_List;
276
bool raid_Component_Found = TRUE;
278
// collect all the children
279
for( component_Index = 0; raid_Component_Found; component_Index++ )
281
DPT_TAG_T component_Tag;
282
get_Devs_Type comp_Type;
284
// find the nth *logical* (not physical) owned by this logical
285
component_Tag = Get_Component( raid_Tag,
287
&raid_Component_Found,
290
if( raid_Component_Found && ( comp_Type != GET_SCSI_DASD ))
292
component_List.add_Item( component_Tag );
296
// delete this top-level raid
298
err = engine->Send( MSG_GET_INFO, raid_Tag );
300
// Checks to see if there are any reserved devices that are trying to be deleted
301
if ((engine->devInfo_P->flags3 & FLG_DEV_RES_CONFLICT) && (!(engine->devInfo_P->raidType == RAID_HOT_SPARE)) ){
302
out->add_Item( EventStrings[STR_RESCONFLICT] );
306
else if( !err.Is_Error() )
309
SCSI_Address raid_Address;
310
switch( engine->devInfo_P->raidType )
315
case RAID_HOT_SPARE :
318
/*******start of device busy section**********/
320
busy_err |= engine->Send(MSG_CHECK_BUSY, raid_Tag);
322
// If busy_err = MSG_RTN_IGNORED, then the engine does not
323
// support this command. Simply treat as not busy.
324
if ((busy_err.Is_Error()) &&
325
(busy_err != Dpt_Error::DPT_MSG_RTN_IGNORED))
329
engine->Extract(&devStatus, sizeof(uLONG));
331
// If 1, then this device is busy, otherwise
332
// the device is considered NOT busy.
335
err = Dpt_Error::DPT_CMD_ERR_COMPONENT_BUSY;
338
/*******end of device busy section**********/
340
// delete all logicals (not physicals) owned by this logical
343
raid_Address = DPT_Tag_to_Address(raid_Tag, &tag_Valid);
344
// get the tag for the corresponding physical device
345
DPT_TAG_T newComponent;
346
bool compFound = false;
347
get_Devs_Type comp_Type;
348
for (int cmpIdx = 0; !compFound; ++cmpIdx)
350
newComponent = Get_Component(raid_Tag, cmpIdx,
351
&compFound, &comp_Type);
353
// err = engine->Send(MSG_GET_INFO, newComponent);
354
// if (compFound && (comp_Type == GET_SCSI_DASD))
359
err = engine->Send(MSG_DELETE, raid_Tag);
360
// check to see if this made it unintentionally suppressed
361
CheckForSuppressed(newComponent);
365
DPTControllerMap * map = new DPTControllerMap;
366
char * String = map->getTargetString(
367
raid_Address.hba, raid_Address.bus, raid_Address.id, raid_Address.lun );
368
out->add_Item( String );
371
out->add_Item( "\n" );
377
component_List.reset_Next_Index();
378
while ( component_List.num_Left() )
380
// delete all logicals (not physicals) owned by this logical
381
err |= (Dpt_Error)Delete_Raid_and_Children( component_List.get_Next_Item(), out );
389
// check to see if this made it unintentionally suppressed
390
// if so, the new id will be the lowest chan/id available
391
Command::Dpt_Error Delete_Raid::CheckForSuppressed (DPT_TAG_T tag)
393
Dpt_Error err = Dpt_Error::DPT_CMD_ERR_NO_ERROR;
394
const int MAX_CHANNELS = 4;
395
const int NUMBER_OF_IDS = 16;
396
const int NOT_IN_USE = 0;
397
const int IN_USE = 1;
399
err = engine->Send(MSG_GET_INFO, tag);
400
if ((engine->devInfo_P->flags & FLG_DEV_SUPPRESSED) &&
401
(!(engine->devInfo_P->flags & FLG_DEV_SUP_DESIRED)))
403
dptID_S *loglist = new dptID_S[LOG_LIST_SIZE];
404
int devChannel; // channel number of this device
405
int availIDs [MAX_CHANNELS];
406
char ids [MAX_CHANNELS][NUMBER_OF_IDS]; // array of IDs
408
// Get the information about this device
409
DPT_TAG_T newIDhba = engine->devInfo_P->hbaTag;
410
devChannel = engine->devInfo_P->addr.chan;
412
///////////////////////////////////////////
413
// We need to find out which IDs are legal
414
///////////////////////////////////////////
416
// first mark all IDs as NOT-IN-USE
417
for(int i = 0; i < MAX_CHANNELS; i++)
418
for(int j = 0; j < NUMBER_OF_IDS; j++)
419
ids[i][j] = NOT_IN_USE;
421
// mark the HBAs ID as IN-USE on all channels
422
if(engine->devInfo_P->level != 0)
424
err = engine->Send(MSG_GET_INFO, newIDhba);
425
// assume that it is an HBA for now
426
for(int j = 0; j < MAX_CHANNELS; j++)
427
ids[j][engine->hbaInfo_P->addr.id] = IN_USE;
430
// mark off the IDs that are out-of-range for the HBA as IN-USE
431
for(int k = 0; k < MAX_CHANNELS; k++)
433
for(int l = 0; l < NUMBER_OF_IDS; l++)
435
if((l > engine->hbaInfo_P->maxAddr.id) ||
436
(k > engine->hbaInfo_P->maxAddr.chan))
441
// loop through the logicals of this guy's manager and
442
// mark off the ids that are in use
443
int numLogs = EngineFindIDs(FID_RESET_OUTBUFF,MSG_ID_LOGICALS,newIDhba,loglist, LOG_LIST_SIZE);
444
for(int m = 0; m < numLogs; m++)
446
err = engine->Send(MSG_GET_INFO, loglist[m].tag);
447
ids[engine->devInfo_P->addr.chan][engine->devInfo_P->addr.id] = IN_USE;
450
// Figure out the maximum number of IDs available on any bus
451
// and how many buses have IDs available
452
for(int n = 0; n < MAX_CHANNELS; n++)
457
for(int p = 0; p < MAX_CHANNELS; p++)
459
for(int q = 0; q < NUMBER_OF_IDS; q++)
461
if(ids[p][q] == NOT_IN_USE)
464
// remember the lowest available ID
473
int maxAvail = 0; // max. number of IDs available on any channel
474
int chansWithAvail = 0; // number of channels with available IDs
475
for(int r = 0; r < MAX_CHANNELS; r++)
477
if(availIDs[r] > maxAvail) maxAvail = availIDs[r];
478
if(availIDs[r]) chansWithAvail++;
481
// Make sure there are IDs available to redirect this drive to
484
err = Dpt_Error::DPT_ERR_ABS_NO_MORE_IDS;
492
memset(&rh, 0, sizeof(raidHeader_S));
493
rh.refNum = RAID_REDIRECT;
495
rh.addr.chan = newChan;
496
rh.control = FLG_RCTL_ADDR;
498
raidCompList_S component;
500
engine->Insert (&rh, sizeof(raidHeader_S));
501
engine->Insert (&component, sizeof(raidCompList_S));
502
engine->Send (MSG_RAID_NEW, newIDhba);
508
Command &Delete_Raid::Clone() const
510
ENTER( "Command &Delete_Raid::Clone() const" );
512
return( *new Delete_Raid( *this ) );
515
/*** END OF FILE ***/