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.
30
//***************************************************************************
34
// This file contains the function definitions for the dptConnection_C
37
//Author: Doug Anderson
45
//***************************************************************************
48
//Include Files -------------------------------------------------------------
50
#include "allfiles.hpp" // All engine include files
53
#if !defined _DPT_UNIX && !defined _DPT_NETWARE && !defined _DPT_DOS
55
void osdTargetOffline(uLONG HbaNum, uLONG Channel, uLONG TargetId, uLONG LUN);
58
void osdTargetOffline(uLONG HbaNum, uLONG Channel, uLONG TargetId, uLONG LUN);
62
//Function - dptConnection_C::newMgrZero() - start
63
//===========================================================================
67
// This function allocates a new absent driver manager as manager zero.
73
//Global Variables Affected:
75
//Remarks: (Side effects, Assumptions, Warnings...)
78
//---------------------------------------------------------------------------
80
dptCoreMgr_C * dptConnection_C::newMgrZero()
83
// Create a SCSI driver
84
dptManager_C *mgr_P = new dptDriver_C;
85
// If an I/O method is supported...
86
if ((mgr_P!=NULL) && (ioMethod!=DPT_IO_NONE))
88
mgr_P->status.flags |= FLG_STAT_REAL;
93
//dptConnection_C::newMgrZero() - end
96
//Function - dptConnection_C::acquireCCB() - start
97
//===========================================================================
101
// This function returns a pointer to an engine CCB. A pointer to the
102
//first CCB not in use is returned. If all CCBs are in use, a new CCB is
103
//created and added to the end of the CCB list.
109
//Global Variables Affected:
111
//Remarks: (Side effects, Assumptions, Warnings...)
114
//---------------------------------------------------------------------------
116
engCCB_C * dptConnection_C::acquireCCB()
122
// Get the first available CCB
123
ccb_P = (engCCB_C *) ccbList.reset();
124
while ((ccb_P!=NULL) && !found) {
125
// Check if the CCB is in use
126
if (!ccb_P->isInUse()) {
127
// Indicate that the CCB is in use
129
// Indicate that an available CCB was found
134
ccb_P = (engCCB_C *) ccbList.next();
139
// Allocate a new CCB
140
ccb_P = (engCCB_C *) osdAlloc(sizeof(engCCB_C));
142
// Allocate a new CCB
143
ccb_P = new engCCB_C;
146
// Initialize the CCB
148
// Indicate that the CCB is in use
150
// Add the new CCB to the end of the HBA's CCB list
151
if (!ccbList.addEnd(ccb_P)) {
164
// Re-initialize the CCB
170
//dptConnection_C::acquireCCB() - end
173
//Function - dptConnection_C::reserveEndOfDisks() - start
174
//===========================================================================
178
// This function attempts to reserve space at the end of all non-
179
//removeable DASD devices. This space is used by DPT to store
180
//configuration information, downloaded FW code...
186
//Global Variables Affected:
188
//Remarks: (Side effects, Assumptions, Warnings...)
190
// 1. This function assumes that partition information has been obtained
192
//---------------------------------------------------------------------------
194
void dptConnection_C::reserveEndOfDisks()
200
DEBUG_BEGIN(1, dptConnection_C::reserveEndOfDisks());
202
dptObject_C *obj_P = (dptObject_C *) objectList.reset();
203
while (obj_P!=NULL) {
204
if (obj_P->isDevice()) {
205
dev_P = (dptDevice_C *) obj_P;
206
// If a non-removeable HBA physical DASD device...
207
if ((dev_P->getLevel()==2) && (dev_P->getObjType()==DPT_SCSI_DASD) &&
208
!dev_P->isComponent() && !dev_P->isRemoveable()) {
210
// Determine how much space is currently reserved
211
spaceReserved = dev_P->getMaxPhyLBA() - dev_P->getLastLBA();
214
// SNI: To keep compatibility with other HBAs (Adaptec, Symbios ..)
215
// we reserve only 1 block on normal SCSI disks.
216
// More space is reserved on LSU creation.
217
// See reserveTempSpace() and enableTempSpace().
218
if (spaceReserved != 1) {
219
dev_P->reserveEndOfDisk(1);
220
DEBUG(1, PRT_DADDR(dev_P) << " RESERVED: old=" << spaceReserved << " new=" << \
221
(int) (dev_P->getMaxPhyLBA() - dev_P->getLastLBA()));
223
// At this place osdGetLBA() is called only to get the "MP.." name.
224
// The spaceReserved value of SDI is ignored here. - michiz.
225
dptHBA_C *hba_P = obj_P->myHBA_P();
227
osdGetLBA(hba_P->getDrvrNum(), dev_P->getChan(), dev_P->getID(), &spaceReserved, dev_P->userBuff, (uLONG) dev_P->getMaxPhyLBA());
229
// If insufficient blocks have been reserved...
230
if (spaceReserved < RESERVED_SPACE_DISK) {
231
// Determine how much space is not used by a valid
233
uLONG availableSpace = dev_P->getMaxPhyLBA() - dev_P->getLastPartBlk();
235
uSHORT spaceToReserve = 0;
236
// If more space can be reserved...
237
if (availableSpace > spaceReserved) {
238
// Reserve up to RESERVED_SPACE_DISK blocks
239
spaceToReserve = (availableSpace > RESERVED_SPACE_DISK) ? RESERVED_SPACE_DISK : (uSHORT) availableSpace;
241
dev_P->reserveEndOfDisk(spaceToReserve);
244
// tell the user how much space was reserved at the end of the disk for DPT stuff
245
DEBUG(1, PRT_DADDR(dev_P) << " RESERVED: " << spaceToReserve);
250
obj_P = (dptObject_C *) objectList.next();
254
//dptConnection_C::reserveEndOfDisks() - end
257
//Function - dptConnection_C::zapPartitions() - start
258
//===========================================================================
262
// This function destroys the partition table on all devices that
263
//are flagged for partition table zapping.
269
//Global Variables Affected:
271
//Remarks: (Side effects, Assumptions, Warnings...)
274
//---------------------------------------------------------------------------
276
DPT_RTN_T dptConnection_C::zapPartitions()
279
DPT_RTN_T retVal = MSG_RTN_COMPLETED;
282
dptObject_C *obj_P = (dptObject_C *) objectList.reset();
283
while (obj_P!=NULL) {
284
// If this object is a device...
285
if (obj_P->isDevice()) {
286
dev_P = (dptDevice_C *) obj_P;
288
// If the device is marked for partition zapping...
289
if (dev_P->isPartitionMarked() && !dev_P->isComponent()) {
290
// If a new SW array on a 4th Gen board...
291
if ((dev_P->getRAIDtype()==0) && (dev_P->getLevel()==0) && !dev_P->myHBA_P()->isI2O())
292
// Clear the component device partitions
293
dev_P->zapCompPartitions();
295
// Clear the partition table sector
296
dev_P->zapPartition();
299
// Clear the partition table zap indicator
300
dev_P->clrPartitionZap();
301
// Clear the new RAID-0 indicator
302
dev_P->clrNewRAID0();
304
obj_P = (dptObject_C *) objectList.next();
310
//dptConnection_C::zapPartitions() - end
313
//Function - dptConnection_C::genMagicNum() - start
314
//===========================================================================
317
// This function generates a unique magic number and guarantees
318
//that no other object in this connection has the same magic number.
320
//---------------------------------------------------------------------------
322
uLONG dptConnection_C::genMagicNum()
327
uLONG newMagicNum = 0x12345678L;
334
// Assume no duplicates until one is found
336
// Create the magic number
337
newMagicNum = rand() & 0x7fff; // Bit #31 reserved by F/W
339
newMagicNum |= rand() & 0xffff;
341
// Insure the new magic number is unique
342
dptObject_C *obj_P = (dptObject_C *) objectList.reset();
344
if (newMagicNum == obj_P->getMagicNum()) {
348
obj_P = (dptObject_C *) objectList.next();
351
} while (duplicateFound);
353
return (newMagicNum);
356
//dptConnection_C::genMagicNum() - end
359
//Function - dptConnection_C::setPrevOsVisibles() - start
360
//===========================================================================
362
// This function sets all devices flagged as OS visible to previously
364
//---------------------------------------------------------------------------
366
void dptConnection_C::setPrevOsVisibles()
371
dptObject_C *obj_P = (dptObject_C *) objectList.reset();
372
while (obj_P!=NULL) {
373
if (obj_P->isDevice()) {
374
dev_P = (dptDevice_C *) obj_P;
375
if (dev_P->isOsVisible()) {
376
dev_P->clrOsVisible();
377
dev_P->setPrevOsVisible();
380
dev_P->clrPrevOsVisible();
383
obj_P = (dptObject_C *) objectList.next();
387
//dptConnection_C::setPrevOsVisibles() - end
390
//Function - dptConnection_C::lsuOffline() - start
391
//===========================================================================
393
// This function sets all devices flagged as OS visible to previously
395
//---------------------------------------------------------------------------
397
void dptConnection_C::lsuOffline()
402
dptObject_C *obj_P = (dptObject_C *) objectList.reset();
403
while (obj_P!=NULL) {
404
if (obj_P->isDevice()) {
405
dev_P = (dptDevice_C *) obj_P;
406
if (!dev_P->isOsVisible() && dev_P->isPrevOsVisible()) {
407
// Prepare the LSU to go offline
408
osdTargetOffline((uLONG)dev_P->myHBA_P()->getDrvrNum(), (uLONG)dev_P->getChan(), (uLONG)dev_P->getID(), (uLONG)dev_P->getLUN());
411
obj_P = (dptObject_C *) objectList.next();
415
//dptConnection_C::lsuOffline() - end
418
//Function - dptConnection_C::~dptConnection_C() - start
419
//===========================================================================
423
// This function is the destructor for the dptConnection_C class.
429
//Global Variables Affected:
431
//Remarks: (Side effects, Assumptions, Warnings...)
434
//---------------------------------------------------------------------------
436
dptConnection_C::~dptConnection_C()
439
// If this connection is capable of I/O
440
if (ioMethod!=DPT_IO_NONE)
441
// Let the OS dependent layer know that the connection has
443
osdDisconnected(ioMethod);
447
engCCB_C *ccb_P = (engCCB_C *) ccbList.reset();
448
while (ccb_P!=NULL) {
450
ccb_P = (engCCB_C *) ccbList.next();
457
//dptConnection_C::~dptConnection_C() - end