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 function definitions for the dptHBA_C class.
36
//Author: Doug Anderson
44
//***************************************************************************
46
#include "allfiles.hpp" // All engine include files
54
void _Cdecl sleep( unsigned __seconds );
59
#include <unistd.h> // sleep()
71
//Watcom 9.5 compiler doesn't do the right thing here and the linker can't resolve
72
//the symbol if it has an extern in front of it
74
unsigned short DPTI_BootFlags;
78
extern unsigned short DPTI_BootFlags;
83
#if !defined _DPT_UNIX && !defined _DPT_NETWARE && !defined _DPT_DOS
85
DPT_RTN_T DPT_EXPORT osdSendMessage(uLONG, PI2O_MESSAGE_FRAME, PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME);
86
uLONG osdTargetBusy(uLONG HbaNum, uLONG Channel, uLONG TargetId, uLONG LUN);
87
DPT_RTN_T osdRescan(uLONG HbaNum, uLONG Operation);
90
DPT_RTN_T DPT_EXPORT osdSendMessage(uLONG, PI2O_MESSAGE_FRAME, PI2O_SCSI_ERROR_REPLY_MESSAGE_FRAME);
91
uLONG osdTargetBusy(uLONG HbaNum, uLONG Channel, uLONG TargetId, uLONG LUN);
92
DPT_RTN_T osdRescan(uLONG HbaNum, uLONG Operation);
95
//Function - dptHBA_C::passCCB() - start
96
//===========================================================================
100
// This function makes adjustments to the CCB and then passes
101
//the send CCB request up the attachment chain.
107
//Global Variables Affected:
109
//Remarks: (Side effects, Assumptions, Warnings...)
112
//---------------------------------------------------------------------------
114
DPT_RTN_T dptHBA_C::passCCB(engCCB_C *ccb_P)
117
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_BLINK_LED_IO;
119
// If the HBA is not in blink LED mode...
121
// Set the nested FW drive bit
124
// If the command came from a physical device...
125
if (ccb_P->isPhy() && !ccb_P->isNoEATAphys())
127
ccb_P->setPhysical();
128
// If the command came from an HBA logical device...
129
else if (ccb_P->isRAIDcmd())
130
// Set the firmware level bits
132
else if (ccb_P->isMgr())
133
// Set the interpret bit
134
ccb_P->setInterpret();
136
// Always physical origin to the next level
139
// Send the CCB to the next level in the attachment chain
140
retVal = myMgr_P()->passCCB(ccb_P);
146
//dptHBA_C::passCCB() - end
149
//Function - dptHBA_C::findMyPhysicals() - start
150
//===========================================================================
154
// This function finds all physical SCSI devices attached to this HBA.
156
//---------------------------------------------------------------------------
158
uSHORT dptHBA_C::findMyPhysicals()
162
uSHORT foundDev,skipToNextID;
165
dptDevice_C *newDev_P;
168
dptSCSIbcd_C *bcd_P = NULL;
169
dptSCSIbcd_C *newBCD_P = NULL;
170
dptDevice_C *prevDev_P = NULL;
172
// If flash command mode or blink LED mode...
173
if (isFlashMode() || isBlinkLED())
179
// Indicate a successful scan
181
// For all supported SCSI channels, ids, & luns
182
for (phyRange.reset();!phyRange.maxedOut();phyRange.incBottomUp()) {
184
// If a new SCSI ID...
185
if (phyRange.cur().lun==0) {
186
// If there was an object at the last SCSI ID
188
// Enter it into the physical device list
190
// There is no bridge controller
192
// There is no previous object at this SCSI ID
197
// Initialize the CCB for a SCSI Inquiry command
199
// Target the CCB for the specified SCSI address
200
ccb_P->target(phyRange.cur(),this,CCB_ORIG_PHY);
201
// Send the CCB to H/W
202
DPT_RTN_T rtnStatus = launchCCB(ccb_P);
203
// If an I/O error occurred...
204
if (rtnStatus == (MSG_RTN_FAILED | ERR_SCSI_IO)) {
205
// If a check condition...
206
if (ccb_P->scsiStatus == 2) {
207
uCHAR *reqSense_P = NULL;
208
// If auto-request sense is active...
209
if (ccb_P->eataCP.flags & CP_REQ_SENSE)
210
reqSense_P = ccb_P->defReqSense;
214
// Target the CCB for the specified SCSI address
215
ccb_P->target(phyRange.cur(),this,CCB_ORIG_PHY);
216
if (launchCCB(ccb_P) == MSG_RTN_COMPLETED)
217
reqSense_P = ccb_P->dataBuff_P;
219
if (reqSense_P != NULL) {
220
// If sense key == Not Ready
221
if (((reqSense_P[2] & 0x0f) == 0x02) && (reqSense_P[12] == 0x04)) {
222
// If format in progress or DPT format clearing phase
223
if ((reqSense_P[13] == 0x04) || (reqSense_P[13] == 0x84)) {
225
devType = DPT_SCSI_DASD;
230
// If a selection timeout...
231
else if (ccb_P->ctlrStatus == 1)
232
// Give other tasks a chance to run
234
//-------------------------------------------------------
235
// Note: By going to the next SCSI ID here, if a drive is
236
// formatting, no further LUNs will be searched. This
237
// will cause the engine not to see devices attached to
238
// a bridge controller if a lower LUN is formatting.
239
//-------------------------------------------------------
240
// Go to the next SCSI ID
243
// If the Inquiry was successful...
244
else if (rtnStatus == MSG_RTN_COMPLETED) {
245
// Cast the default data buffer as SCSI Inquiry data
246
inq_P = (sdInquiry_S *) ccb_P->defData;
247
// Get the peripheral qualifier
248
qualifier = (inq_P->getPeripheral() & 0xe0) >> 5;
250
// If LUN not supported... *** Always check all luns ***
251
//if (qualifier==0x3)
253
// If a device is connected at this ID...
254
//else if ((qualifier==0x00) || (qualifier==0x02)) {
256
if ((qualifier==0x00) || (qualifier==0x02)) {
257
// Get the peripheral device type
258
devType = (inq_P->getPeripheral() & 0x1f);
261
// Most scanners (including HP) return a peripheral
262
// device type of 3 (Processor) instead of scanner
263
// If the unit responds to a Get Window (25h) command,
264
// we will assume that it is a scanner
265
// NOTE: Get Window (25h) is not mandatory for scanner
266
// devices. It is used here because the only scanner
267
// specific SCSI command which are mandatory are SCAN
268
// and Set Window, both of which have major side effects.
272
// A readCapacity is the same opcode as Get Window
273
// Have to use this function because we don't have
274
// access to the dptCDB_S from here
275
ccb_P->readCapacity();
278
// Set the physical bit
279
ccb_P->setPhysical();
281
// Target the CCB for the specified SCSI address
282
ccb_P->target(phyRange.cur(),this,CCB_ORIG_PHY);
283
if(launchCCB(ccb_P) == MSG_RTN_COMPLETED)
287
// Don't look for LUNs on scanners
288
// Some (i.e. Mustek MFS-12000SP) respond to all
289
// LUNs with qualifier == 0
290
if(devType == 6) skipToNextID = 1;
293
// If the device is attached to an NCR type RAID
294
// bridge controller...
296
// Create an NCR type RAID bridge controller
297
newBCD_P = (dptSCSIbcd_C *) newObject(DPT_RAID_BCD);
298
// If the device is at a non-zero lun
299
else if (phyRange.cur().lun!=0)
300
// Create a standard bridge controller
301
newBCD_P = (dptSCSIbcd_C *) newObject(DPT_SCSI_BCD);
304
// If LUN is supported, but no device at this ID
305
else if ((qualifier==0x01) && (bcd_P==NULL)) {
306
// If the device is attached to an NCR type RAID
307
// bridge controller...
309
// Create an NCR type RAID bridge controller
310
newBCD_P = (dptSCSIbcd_C *) newObject(DPT_RAID_BCD);
312
// Create a standard bridge controller
313
newBCD_P = (dptSCSIbcd_C *) newObject(DPT_SCSI_BCD);
315
// If a bridge controller has just been created...
316
if (newBCD_P!=NULL) {
319
// Indicate that this manager is real
320
bcd_P->status.flags |= FLG_STAT_REAL;
321
// Set the manager's address
322
bcd_P->addr = phyRange.cur();
323
// Add the manager to the physical device list
325
// If there was a previous device at this SCSI ID...
326
if (prevDev_P!=NULL) {
328
bcd_P->enterFromHBA(prevDev_P);
332
} // end if (rtnStatus == MSG_RTN_COMPLETED)
334
// If a device was found...
336
// Create a new SCSI device
337
newDev_P = (dptDevice_C *) newObject(devType);
338
if (newDev_P!=NULL) {
339
// Indicate that this is a real device
340
newDev_P->status.flags |= FLG_STAT_REAL;
341
// Set the new device's SCSI address
342
newDev_P->addr = phyRange.cur();
343
// If there is an active bridge controller...
345
// Add the new device to the BCD
346
bcd_P->enterFromHBA(newDev_P);
348
// Set a previous object pointer so the device
349
// can be added to a bridge ctlr or when the scan
350
// moves to the next SCSI ID
351
prevDev_P = newDev_P;
352
} // end if (bcd_P==NULL)
353
} // end if (newDev_P!=NULL)
354
} // end if (foundDev)
359
} // end for (phyRange)
360
// If there was an object at the last SCSI ID
362
// Enter it into the physical device list
366
} // end if (ccb_P!=NULL)
371
//dptHBA_C::findMyPhysicals() - end
374
//Function - dptHBA_C::findMyLogicals() - start
375
//===========================================================================
379
// This function finds all FW logical devices associated with this HBA.
386
//---------------------------------------------------------------------------
388
uSHORT dptHBA_C::findMyLogicals()
393
// If flash command mode or blink LED mode...
394
if (isFlashMode() || isBlinkLED())
397
// If the HBA supports RAID...
398
if (isRAIDcapable()) {
401
engCCB_C *ccb_P = getCCB();
404
// Initialize the CCB to do a log sense
405
ccb_P->logSense(0x36);
406
// Indicate that this is a RAID command
408
// Target the controller
409
ccb_P->target(addr,this,CCB_ORIG_LOG);
410
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
411
// Create logical devices for the SCSI addresses returned
412
newLP36Devices(ccb_P,this);
417
} // end if (ccb_P!=NULL)
418
} // end if (isRAIDcapable())
420
// Check for emulated drives
426
//dptHBA_C::findMyLogicals() - end
429
//Function - dptHBA_C::isRAIDbcd() - start
430
//===========================================================================
434
// This routine checks to see if a device is attached to a hardware
441
//Global Variables Affected:
443
//Remarks: (Side effects, Assumptions, Warnings...)
445
// 1. This function is intended for use in the findPhysObjects() function.
447
//---------------------------------------------------------------------------
449
uSHORT dptHBA_C::isRAIDbcd()
453
hwaHWdata_S *bcdData_P;
456
engCCB_C *ccb_P = getCCB();
458
// Initialize the EATA CP.......................
460
// Initialize the CCB for a SCSI Inquiry command
461
ccb_P->inquiry(0xc0);
462
// Target the CCB for the specified SCSI address
463
ccb_P->target(phyRange.cur(),this,CCB_ORIG_PHY);
464
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
465
// Cast the return data pointer
466
bcdData_P = (hwaHWdata_S *) ccb_P->defData;
467
// Check for the hardware array info signature
468
if (memcmp(bcdData_P->getPageID(),"HWRE",4)==0 )
478
//dptHBA_C::isRAIDbcd() - end
481
//Function - dptHBA_C::findComponent() - start
482
//===========================================================================
486
// This function finds a component device with the specified SCSI
487
//address. The HBA field of the SCSI address is assumed to be set to
494
//Global Variables Affected:
496
//Remarks: (Side effects, Assumptions, Warnings...)
499
//---------------------------------------------------------------------------
501
dptDevice_C * dptHBA_C::findComponent(dptAddr_S inAddr,uSHORT,uLONG inMagicNum, dptCoreList_C *)
504
dptObject_C *obj_P = NULL;
505
dptDevice_C *comp_P = NULL;
506
dptSCSIbcd_C *bcd_P = NULL;
508
// Assume the component is attached to this HBA
509
inAddr.hba = getHBA();
511
// If a magic # was specified...
513
// Search for a device with a matching magic #
514
obj_P = findMagicObject(phyList,inMagicNum);
516
// Search for a device with a matching SCSI address
517
obj_P = findObjectAt(phyList,inAddr);
519
// If an object was found...
521
// If a manager was found...
522
if (obj_P->isManager())
523
bcd_P = (dptSCSIbcd_C *) obj_P;
524
// If a device was found...
526
comp_P = (dptDevice_C *) obj_P;
529
// If no device was found...
531
// Create an absent device
532
comp_P = (dptDevice_C *) newObject(DPT_SCSI_DASD);
534
// Set the device's SCSI address
535
comp_P->addr = inAddr;
536
// Set the devices status to missing
537
comp_P->status.display = DSPLY_STAT_MISSING;
538
// If the device belongs on a bridge controller &
539
// no bridge exists...
540
if ((bcd_P==NULL) && (inAddr.lun!=0)) {
541
// Create a new bridge controller
542
bcd_P = (dptSCSIbcd_C *) newObject(DPT_SCSI_BCD);
544
// Set the device's SCSI address
545
bcd_P->addr = inAddr;
546
// Set the devices status to missing
547
bcd_P->status.display = DSPLY_STAT_MISSING;
548
// Add the manager to the HBA's physical list
549
if (!enterPhy(bcd_P))
552
} // end if (inAddr.lun!=0)
554
// Add the component to the sub-manager's logical list
555
bcd_P->enterFromHBA(comp_P);
557
// Add the component to the HBA's physical list
558
// if this call fails object will be deleted.
559
if (enterPhy(comp_P))
561
} // end if (comp_P!=NULL)
562
} // end if (comp_P!=NULL)
567
//dptHBA_C::findComponent() - end
570
//Function - dptHBA_C::realInit() - start
571
//===========================================================================
575
// This function initializes a real HBA.
581
//Global Variables Affected:
583
//Remarks: (Side effects, Assumptions, Warnings...)
586
//---------------------------------------------------------------------------
588
void dptHBA_C::realInit()
591
// Get the hardware information
594
// Get the info contained in NV RAM
597
// Check for RAID response to RAID command
600
// Get the event log control word
603
// Read the drive size table
604
// (If not supported pointer will remain NULL)
605
readDriveSizeTable();
607
if (driveSizeTable_P != NULL) {
608
dptBuffer_S *buff_P = dptBuffer_S::newBuffer(512);
610
buff_P->insert(temp);
612
buff_P->insert(temp);
614
buff_P->insert(temp);
616
buff_P->insert(temp);
618
buff_P->insert(temp);
619
setArrayDriveSizeTable(buff_P);
622
getArrayDriveSizeTable(buff_P);
623
dptBuffer_S::delBuffer(buff_P);
627
// Fake a drive size table
628
driveSizeTable_S *ds_P = (driveSizeTable_S *) new UCHAR[8+(2*4)];
629
ds_P->setMaxEntries(1);
630
ds_P->setNumEntries(1);
631
ds_P->setEntry(0, 0x40000);
632
useDriveSizeTable(ds_P);
633
delete[] ((uCHAR *) ds_P);
637
//dptHBA_C::realInit() - end
640
//Function - dptHBA_C::getHWinfo() - start
641
//===========================================================================
645
// This function determines what hardware the HBA has.
651
//Global Variables Affected:
653
//Remarks: (Side effects, Assumptions, Warnings...)
656
//---------------------------------------------------------------------------
658
void dptHBA_C::getHWinfo()
662
DEBUG_BEGIN(5, dptHBA_C::getHWinfo());
665
engCCB_C *ccb_P = getCCB();
667
// Initialize the CCB to do a log sense page 0x33
668
// Limit data buffer to 0xff bytes
669
ccb_P->logSense(0x33,0,0xff);
672
// Send the CCB to hardware
673
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
674
uSHORT tempUShort = 0;
676
// Clear all flags except those specified below
677
hbaFlags2 &= FLG_HBA_SCAM | FLG_HBA_I2O;
678
ccb_P->initLogSense();
679
while (ccb_P->log.isValidParam()) {
680
switch (ccb_P->log.code()) {
682
// Check for a RAID Key Card & Cache Module
684
if (ccb_P->log.data_P()[0] & LGS_KEYCARD)
685
modules |= FLG_MOD_DM401X;
686
if (ccb_P->log.data_P()[0] & LGS_CACHEMODULE)
687
modules |= FLG_MOD_CM401X;
688
// Check for DEC storage sub-system H/W on HBA
689
if (ccb_P->log.data_P()[0] & 0x20)
690
hbaFlags2 |= FLG_HBA_SUBSYS_HW;
691
// NV RAM is present on the HBA
692
if (ccb_P->log.data_P()[0] & 0x40)
693
hbaFlags2 |= FLG_HBA_NVRAM;
694
// Auto-termination of narrow SCSI bus supported
695
if (ccb_P->log.data_P()[0] & 0x80)
696
hbaFlags2 |= FLG_HBA_AUTO_TERM;
698
if (ccb_P->log.length() >= 2) {
700
irqNum |= ccb_P->log.data_P()[1];
704
// Get the firmware battery flags and memory parity error flag
706
fwFlags = ccb_P->log.data_P()[0];
709
// Get the total controller memory
711
totalMem = getU4(ccb_P->log.data_P(),0);
712
reverseBytes(totalMem);
715
// Get the total controller memory
719
if (ccb_P->log.data_P()[1] & 0x01) {
720
raidSupport &= ~FLG_RAID_0;
722
if (ccb_P->log.data_P()[1] & 0x02) {
723
raidSupport &= ~FLG_RAID_1;
725
if (ccb_P->log.data_P()[1] & 0x04) {
726
raidSupport &= ~FLG_RAID_5;
728
if (ccb_P->log.data_P()[1] & 0x08) {
729
hbaFlags2 |= FLG_HBA_PREDICTIVE;
734
// Get the Host to HBA bus information
736
if (ccb_P->log.data_P()[0] & 0x40)
737
busType = HBA_BUS_PCI;
738
switch (ccb_P->log.data_P()[0] & 0x3f) {
739
case 1: memcpy(busSpeed,"3.3",4); break;
740
case 2: memcpy(busSpeed,"4.0",4); break;
741
case 3: memcpy(busSpeed,"4.4",4); break;
742
case 4: memcpy(busSpeed,"5.0",4); break;
743
case 5: memcpy(busSpeed,"5.7",4); break;
744
case 6: memcpy(busSpeed,"6.7",4); break;
745
case 7: memcpy(busSpeed,"8.0",4); break;
746
case 8: memcpy(busSpeed," 10",4); break;
747
case 0x10: memcpy(busSpeed," 33",4); break;
748
case 0x11: memcpy(busSpeed," 66",4); break;
749
case 0x12: memcpy(busSpeed,"132",4); break;
750
case 0x13: memcpy(busSpeed,"264",4); break;
752
hostBusInfo = ccb_P->log.data_P()[1];
755
// Get the SCSI bus capabilities
757
switch (ccb_P->log.data_P()[0] & 0x0f) {
758
case 0: scsiBusSpeed = 5; break;
759
case 1: scsiBusSpeed = 10; break;
760
case 2: scsiBusSpeed = 20; break;
762
if (ccb_P->log.data_P()[0] & 0x80) {
763
flags |= FLG_HBA_DIFFERENTIAL;
764
chanInfo[0].flags |= FLG_CHAN_DIFFERENTIAL;
766
if (ccb_P->log.data_P()[0] & 0x40) {
767
flags |= FLG_HBA_WIDE_16;
768
chanInfo[0].flags |= FLG_CHAN_WIDE_16;
771
if (ccb_P->log.data_P()[0] & 0x20) {
772
flags |= FLG_HBA_EXTERNAL;
773
chanInfo[0].flags |= FLG_CHAN_EXTERNAL;
776
if (ccb_P->log.data_P()[0] & 0x10) {
777
hbaFlags2 |= FLG_HBA_ULTRA;
778
chanInfo[0].flags |= FLG_CHAN_ULTRA;
780
chanInfo[0].scsiBusSpeed = scsiBusSpeed;
783
// Get the attached modules
785
if (!(ccb_P->log.data_P()[0] & 0x80))
786
flags |= FLG_HBA_CHIPSET;
787
modules |= ((uSHORT)ccb_P->log.data_P()[0]) << 9;
788
// If a new cache module was detected
789
if (modules & (FLG_MOD_CM4000 | FLG_MOD_CMI))
790
// There can't be an old cache module
791
modules &= ~FLG_MOD_CM401X;
792
// If a new RAID module was detected
793
if (modules & (FLG_MOD_DM4000 | FLG_MOD_DMI))
794
// There can't be an old RAID module
795
modules &= ~FLG_MOD_DM401X;
796
cpuType = ccb_P->log.data_P()[1];
797
cpuSpeed = ccb_P->log.data_P()[2];
798
if (ccb_P->log.data_P()[3] & 0x80)
799
flags |= FLG_HBA_SMARTROM;
800
if (ccb_P->log.data_P()[3] & 0x40)
801
status.flags |= FLG_STAT_ALARM_ON;
802
if (ccb_P->log.data_P()[3] & 0x01)
803
modules |= FLG_MOD_SX1;
804
if (ccb_P->log.data_P()[3] & 0x02)
805
modules |= FLG_MOD_SX2;
806
if (ccb_P->log.data_P()[3] & 0x04)
807
modules |= FLG_MOD_BBU;
808
if (ccb_P->log.data_P()[3] & 0x10) {
809
modules |= FLG_MOD_RC4040;
810
modules &= ~(FLG_MOD_CM401X | FLG_MOD_CM4000 | FLG_MOD_DM401X | FLG_MOD_DM4000);
812
if (ccb_P->log.data_P()[3] & 0x20) {
813
modules |= FLG_MOD_RC4041;
814
modules &= ~(FLG_MOD_CM401X | FLG_MOD_CM4000 | FLG_MOD_DM401X | FLG_MOD_DM4000);
816
if (ccb_P->log.data_P()[3] & 0x08)
817
hbaFlags2 |= FLG_HBA_SC4;
820
// Get the attached memory modules/SIMMs
822
memBank[0] = ccb_P->log.data_P()[0];
823
extMemBank[0] = ccb_P->log.data_P()[0] & 0x7f;
825
modules |= FLG_MOD_MEM_BANK0;
827
memBank[1] = ccb_P->log.data_P()[1];
828
extMemBank[1] = ccb_P->log.data_P()[1] & 0x7f;
830
modules |= FLG_MOD_MEM_BANK1;
832
memBank[2] = ccb_P->log.data_P()[2];
833
extMemBank[2] = ccb_P->log.data_P()[2] & 0x7f;
835
modules |= FLG_MOD_MEM_BANK2;
837
memBank[3] = ccb_P->log.data_P()[3];
838
extMemBank[3] = ccb_P->log.data_P()[3] & 0x7f;
840
modules |= FLG_MOD_MEM_BANK3;
843
if (ccb_P->log.length() >= 0x0c) {
844
tempUShort = getU2(ccb_P->log.data_P(), 4);
845
#ifndef _DPT_BIG_ENDIAN
846
reverseBytes(tempUShort);
849
modules |= FLG_MOD_MEM_BANK0;
850
extMemBank[0] = tempUShort;
853
tempUShort = getU2(ccb_P->log.data_P(), 6);
854
#ifndef _DPT_BIG_ENDIAN
855
reverseBytes(tempUShort);
858
modules |= FLG_MOD_MEM_BANK1;
859
extMemBank[1] = tempUShort;
862
tempUShort = getU2(ccb_P->log.data_P(), 8);
863
#ifndef _DPT_BIG_ENDIAN
864
reverseBytes(tempUShort);
867
modules |= FLG_MOD_MEM_BANK2;
868
extMemBank[2] = tempUShort;
871
tempUShort = getU2(ccb_P->log.data_P(), 10);
872
#ifndef _DPT_BIG_ENDIAN
873
reverseBytes(tempUShort);
876
modules |= FLG_MOD_MEM_BANK3;
877
extMemBank[3] = tempUShort;
884
fwType = *(uSHORT *)(ccb_P->log.data_P()+2);
885
reverseBytes(fwType);
886
// If downloadable FW is supported...
887
if (ccb_P->log.data_P()[0] & 0x0001)
888
// Set the downloadable FW support flag
889
flags |= FLG_HBA_DOWNLOAD_FW;
890
if (ccb_P->log.data_P()[0] & 0x0002)
891
// Indicate that 528 byte block size ECC is supported
892
flags |= FLG_HBA_ECC_ENABLED;
893
if (ccb_P->log.data_P()[0] & 0x0004)
894
// Indicate that F/W supports the "Interpret Format" cmd
895
hbaFlags2 |= FLG_HBA_INTERPRET_FMT;
896
if (ccb_P->log.data_P()[0] & 0x0008)
897
// Indicate that F/W and the board support ECC
898
flags |= FLG_HBA_ECC_SUPPORTED;
899
if (ccb_P->log.data_P()[0] & 0x0010)
900
// Indicate that F/W based diagnostics are supported
901
hbaFlags2 |= FLG_HBA_DIAGNOSTICS;
902
if (ccb_P->log.data_P()[0] & 0x0080)
903
// Indicate that SMART emulation is support
904
hbaFlags2 |= FLG_HBA_SMART_EMULATION;
905
// Indicate array expansion capability
906
if (ccb_P->log.data_P()[1] & 0x01)
907
hbaFlags2 |= FLG_HBA_EXPAND_ARRAY;
908
// does the hba support tuneable drive spinups?
909
if (ccb_P->log.data_P()[1] & 0x02)
910
hbaFlags2 |= FLG_HBA_VAR_SPIN_UP;
912
// 1. The second version of log page 0x36
913
// 2. The second version of the physical array page
914
// 3. Fibre SCSI ID packing
915
// (using the upper 2 channel bits as extended ID bits
916
// if 2 or fewer SCSI buses)
917
if (ccb_P->log.data_P()[1] & 0x04)
918
hbaFlags2 |= FLG_HBA_I2O_VER2;
920
if (ccb_P->log.data_P()[1] & 0x10)
921
hbaFlags2 |= FLG_HBA_NO_ALARM;
923
if (ccb_P->log.data_P()[1] & 0x20) {
924
raidFlags |= FLG_SEG_64;
927
if (ccb_P->log.data_P()[1] & 0x40) {
928
raidFlags |= FLG_SEG_SUPPORTED;
931
// Check for temperature thresholds
932
if (ccb_P->log.length() > 4)
933
if (ccb_P->log.data_P()[4] && ccb_P->log.data_P()[5])
934
hbaFlags2 |= FLG_HBA_TEMP_PROBE;
939
hbaFlags2 |= (uSHORT) ccb_P->log.data_P()[0];
940
// Make the invalid subsystem status flag a valid flag
941
hbaFlags2 ^= FLG_HBA_SUBSYS_VALID;
944
// Per channel info (including SmartRAID signals)
946
updateChannelInfo(&(ccb_P->log));
950
maxArrays = (uSHORT) ccb_P->log.data_P()[0];
951
def_P = getRAIDtdef(0);
953
def_P->maxDrives = (uSHORT) ccb_P->log.data_P()[1];
954
def_P = getRAIDtdef(3);
956
def_P->maxDrives = (uSHORT) ccb_P->log.data_P()[2];
957
def_P = getRAIDtdef(5);
959
def_P->maxDrives = (uSHORT) ccb_P->log.data_P()[2];
962
// Get the default rebuild frequency (if supported by firmware)
963
if (ccb_P->log.data_P()[7] != 0) {
964
rbldFrequency = ccb_P->log.data_P()[7];
968
maxRaidComponents = (uSHORT) ccb_P->log.data_P()[2];
970
if (ccb_P->log.length() >= 0x18) {
971
maxMajorStripe = getU2(ccb_P->log.data_P(), 22);
972
#ifndef _DPT_BIG_ENDIAN
973
reverseBytes(maxMajorStripe);
976
if (ccb_P->log.length() >= 0x1e) {
977
maxRaidDiskEntries = getU2(ccb_P->log.data_P(), 24);
978
maxRaidMemEntries = getU2(ccb_P->log.data_P(), 26);
979
#ifndef _DPT_BIG_ENDIAN
980
reverseBytes(maxRaidDiskEntries);
981
reverseBytes(maxRaidMemEntries);
985
// max # arrays of a certain type
986
DEBUG(5, "HBA " << PRT_ADDR << "maxArrays=" << (int)ccb_P->log.data_P()[0] << \
987
" maxRaid0=" << (int)ccb_P->log.data_P()[1] << \
988
" maxRaid5=" << (int)ccb_P->log.data_P()[2]);
991
// Background task exclusion period
993
excludeStart = ccb_P->log.data_P()[0];
994
excludeEnd = ccb_P->log.data_P()[1];
996
// exclusion period stuff
997
DEBUG(5, "HBA " << PRT_ADDR << "excludeStart=" << \
998
(int)excludeStart << " excludeEnd=" << (int)excludeEnd);
1003
// Get the next log parameter
1006
} // end if (launchCCB()==MSG_RTN_COMPLETED)
1010
} // end if (ccb_P!=NULL)
1014
//dptHBA_C::getHWinfo() - end
1017
//Function - dptHBA_C::getNVinfo() - start
1018
//===========================================================================
1020
// This function reads NV information and sets HBA info accordingly.
1021
//---------------------------------------------------------------------------
1023
void dptHBA_C::getNVinfo()
1026
engCCB_C *ccb_P = getCCB();
1027
if (ccb_P != NULL) {
1028
// Attempt to read the contents of the NV RAM
1029
ccb_P->modeSense(0x2e);
1030
ccb_P->target(this);
1031
if (launchCCB(ccb_P) == MSG_RTN_COMPLETED) {
1032
// If manual JBOD...
1033
if (ccb_P->modeParam_P->getData()[0x31] & 0x01) {
1034
hbaFlags2 |= FLG_HBA_MANUAL_JBOD_ACTIVE;
1036
// If wolfpack cluster mode...
1037
if (ccb_P->modeParam_P->getData()[0x30] & 0x08) {
1038
hbaFlags2 |= FLG_HBA_CLUSTER_MODE;
1047
//dptHBA_C::getNVinfo() - end
1050
//Function - dptHBA_C::updateChannelInfo() - start
1051
//===========================================================================
1055
// This function updates the specified SCSI channel info.
1057
//---------------------------------------------------------------------------
1059
void dptHBA_C::updateChannelInfo(dptSCSIlog_C *log)
1061
// Get the length of the log parameter
1062
uCHAR length = log->length();
1064
uCHAR *data_P = log->data_P();
1066
uSHORT chanIndex = (uSHORT) (*data_P & 0x7);
1067
if (chanIndex < MAX_NUM_CHANS) {
1068
if (chanIndex > phyRange.getMaxChan())
1069
phyRange.setMaxChan((uCHAR)chanIndex);
1071
// Set the channels flags
1072
chanInfo[chanIndex].flags = *(data_P+1);
1073
// If there is another byte of flags, get it
1075
chanInfo[chanIndex].flags += (*(data_P+2) << 8);
1076
// If the channel info has SCAM info, get it
1079
chanInfo[chanIndex].scamIdMap = *(data_P+4) << 8;
1080
chanInfo[chanIndex].scamIdMap += *(data_P+5);
1082
// Make the invalid subsystem status flag a valid flag
1083
chanInfo[chanIndex].flags ^= FLG_CHAN_SUBSYS_VALID;
1086
if (chanInfo[chanIndex].flags & FLG_CHAN_ULTRA_80)
1087
// Set the bus speed
1088
chanInfo[chanIndex].scsiBusSpeed = 80;
1090
else if (chanInfo[chanIndex].flags & FLG_CHAN_ULTRA_40)
1091
// Set the bus speed
1092
chanInfo[chanIndex].scsiBusSpeed = 40;
1094
else if (chanInfo[chanIndex].flags & FLG_CHAN_ULTRA)
1095
// Set the bus speed
1096
chanInfo[chanIndex].scsiBusSpeed = 20;
1098
// Initialize the SCSI bus speed
1099
chanInfo[chanIndex].scsiBusSpeed = 10;
1102
// If 16 bit wide SCSI...
1103
if (chanInfo[chanIndex].flags & FLG_CHAN_WIDE_16) {
1104
// Double the SCSI bus speed
1105
chanInfo[chanIndex].scsiBusSpeed <<= 1;
1106
// Set the maximum SCSI ID for this channel
1107
phyRange.setMaxId((uCHAR)chanIndex, 15);
1110
// If limited due to an external SCSI cable...
1111
if (chanInfo[chanIndex].flags & FLG_CHAN_EXTERNAL)
1112
// Halve the bus speed
1113
chanInfo[chanIndex].scsiBusSpeed >>= 1;
1115
if (chanInfo[chanIndex].flags & FLG_CHAN_FIBRE) {
1116
// Set the maximum SCSI ID for this channel
1117
phyRange.setMaxId((uCHAR)chanIndex, 127);
1118
chanInfo[chanIndex].scsiBusSpeed = 100;
1122
scsiBusSpeed = chanInfo[chanIndex].scsiBusSpeed;
1124
// get the SCSI ID of the HBA for this channel
1125
engCCB_C *ccb_P = getCCB();
1127
ccb_P->target(this);
1128
// Get the firmware information page (vital product data page 0xc1 has the read config in it)
1129
ccb_P->inquiry(0xc1);
1130
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
1132
// pull out the hba SCSI id for this channel
1133
eataRdConfig_S *rdCfg_P = (eataRdConfig_S *) ccb_P->defData;
1134
chanInfo[chanIndex].hbaID = rdCfg_P->getScsiIDs()[3-chanIndex];
1142
//dptHBA_C::updateChannelInfo() - end
1145
//Function - dptHBA_C::checkForRAID() - start
1146
//===========================================================================
1150
// This function checks to see if the HBA responds to RAID commands.
1156
//Global Variables Affected:
1158
//Remarks: (Side effects, Assumptions, Warnings...)
1161
//---------------------------------------------------------------------------
1163
void dptHBA_C::checkForRAID()
1166
// Clear the FW RAID support flag
1167
flags &= ~FLG_HBA_RAID_FW;
1169
// If a RAID module && a cache module or an I2O HBA...
1170
if ((isRAIDmodule() && is512kCache()) || isI2O()) {
1171
engCCB_C *ccb_P = getCCB();
1174
// Set the FW RAID support flag
1175
flags |= FLG_HBA_RAID_FW;
1177
// Initialize the CCB to get the physical array page
1178
ccb_P->modeSense(0x2a);
1180
ccb_P->target(this);
1181
// Indicate that this is a RAID command
1182
ccb_P->setRAIDcmd();
1183
// Send the CCB to hardware
1184
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
1185
// Insure the proper mode page was returned
1186
if ((ccb_P->modeParam_P->getPageCode() & 0x3f)==0x2a)
1187
// Set the FW RAID support flag
1188
flags |= FLG_HBA_RAID_FW;
1192
// If firmware version 7.C1 or higher...
1193
if ((memcmp(descr.revision,"07C0",4) > 0) || isI2O())
1194
// Use the new logical array page (mode page 0x30)
1196
// if this is the special SNI version of FW use LAP 1
1197
else if (memcmp(descr.revision, "0UX2", 4) == 0)
1199
// its <= 7c0 use lap1
1203
// Re-initialize the CCB
1205
// Initialize the CCB to perform a SCSI inquiry
1206
ccb_P->inquiry(0xc0);
1208
ccb_P->target(this);
1209
// Send the CCB to hardware
1210
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
1211
// If RAID-3 is not supported...
1212
if (!(ccb_P->defData[12] & 0x08)) {
1213
// Clear the RAID 3 support flag
1214
raidSupport &= ~FLG_RAID_3;
1215
if (getRAIDtdef(3)!=NULL)
1226
//dptHBA_C::checkForRAID() - end
1229
//Function - dptHBA_C::handleMessage() - start
1230
//===========================================================================
1234
// This routine handles DPT events for the dptRAIDmgr_C class.
1240
//Global Variables Affected:
1242
//Remarks: (Side effects, Assumptions, Warnings...)
1245
//---------------------------------------------------------------------------
1247
DPT_RTN_T dptHBA_C::handleMessage(DPT_MSG_T message,
1248
dptBuffer_S *fromEng_P,
1249
dptBuffer_S *toEng_P
1253
DPT_RTN_T retVal = MSG_RTN_IGNORED;
1257
// Turns the HBA's alarm on
1260
retVal = sendMFC(MFC_ALARM_ON);
1263
// Turns the HBA's alarm off
1266
retVal = sendMFC(MFC_ALARM_OFF);
1269
// Stops all activity on this HBA so that a physical device may
1272
retVal = quietBus(toEng_P);
1275
// Resumes activity on this HBA after a quiet command has been issued
1277
retVal = sendMFC(MFC_UNQUIET);
1280
// Re-reads the RAID tables on the drives and configures the system
1282
case MSG_RELOCK_DRIVES:
1283
retVal = sendMFC(MFC_READ_RAID_TBL);
1286
// Update the HBA's status
1287
case MSG_UPDATE_STATUS:
1288
retVal = updateStatus(fromEng_P);
1291
// Get the HBA's time
1293
retVal = getTime(fromEng_P);
1296
// Set the HBA's time
1298
retVal = setTime(toEng_P);
1301
// Return the HBA's event log
1303
retVal = rtnEventLog(toEng_P,fromEng_P);
1306
// Clear the HBA event log
1308
retVal = clearEventLog();
1311
// Set the HBA event log control word
1312
case MSG_LOG_SET_HBA_FILTER:
1313
retVal = setEventCtl(toEng_P);
1316
// Return global HBA read/write statistics information
1317
case MSG_GET_IO_STATS:
1318
retVal = rtnIOstats(fromEng_P,1);
1321
// Clear global HBA read/write statistics information
1322
case MSG_CLEAR_IO_STATS:
1323
retVal = rtnIOstats(NULL,0);
1326
// Return HBA specific statistics information
1327
case MSG_GET_HBA_STATS:
1328
retVal = rtnHBAstats(fromEng_P,1);
1331
// Clear HBA specific statistics information
1332
case MSG_CLEAR_HBA_STATS:
1333
retVal = rtnHBAstats(NULL,0);
1336
// Set an HBA data field to a specified value
1338
retVal = setDataField(toEng_P);
1341
// Return the contents of the HBA's NV RAM
1342
case MSG_GET_NV_INFO:
1343
retVal = readNV_RAM(fromEng_P);
1346
// Write the contents of the HBA's NV RAM
1347
case MSG_SET_NV_INFO:
1348
retVal = writeNV_RAM(toEng_P);
1351
// Attempts to switch from operational mode into flash mode
1352
case MSG_FLASH_SWITCH_INTO:
1353
retVal = flashSwitchInto();
1356
// Attempts to switch from flash mode into operational mode
1357
case MSG_FLASH_SWITCH_OUT_OF:
1358
// If a non-zero input byte was specified...
1359
if ((toEng_P->writeIndex) && *toEng_P->data)
1360
// Skip the flash checksum test
1361
retVal = flashSwitchOutOf(1);
1363
// Perform the flash checksum test
1364
retVal = flashSwitchOutOf(0);
1367
// Writes to the HBA's flash memory
1368
case MSG_FLASH_WRITE:
1369
retVal = flashWrite(toEng_P);
1372
// Writes to the HBA's flash memory without verification
1373
case MSG_FLASH_WR_NO_VERIFY:
1374
retVal = flashWrite(toEng_P,0);
1377
// Causes F/W to compute flash memory checksums...
1378
case MSG_FLASH_WRITE_DONE:
1379
if ((toEng_P->writeIndex) && *toEng_P->data)
1380
// Skip the flash checksum test
1381
retVal = flashWriteDone(0);
1383
retVal = flashWriteDone(1);
1386
// Reads from the HBA's flash memory
1387
case MSG_FLASH_READ:
1388
retVal = flashRead(toEng_P,fromEng_P);
1391
// Returns detailed status information about the HBA's flash memory
1392
case MSG_FLASH_STATUS:
1393
retVal = flashStatus(fromEng_P);
1396
// Sets the region offset to be flashed
1397
case MSG_FLASH_SET_REGION:
1398
retVal = flashSetRegion(toEng_P);
1402
// Sets the HBA's exclusion period (no diags, rebuilds, verifies)
1403
case MSG_DIAG_EXCLUDE:
1404
// If F/W diagnostics are supported
1405
if (isFWdiagCapable())
1406
retVal = setExclusion(toEng_P);
1409
// Return the HBA's array limits
1410
case MSG_RAID_GET_LIMITS:
1411
retVal = getArrayLimits(fromEng_P);
1415
case MSG_STATS_LOG_READ:
1416
case MSG_STATS_LOG_CLEAR:
1417
case MSG_STATS_LOG_GET_STATUS:
1418
case MSG_STATS_LOG_SET_STATUS:
1419
// Send to the statistics logger
1420
retVal = osdLoggerCmd(message,
1422
(dptData_S*)fromEng_P,
1423
(uSHORT)myConn_P()->getIOmethod(),
1425
(uLONG)getRAIDid());
1428
case MSG_SET_ACCESS_RIGHTS:
1429
retVal = SetAccessRights(fromEng_P, toEng_P);
1432
case MSG_GET_ACCESS_RIGHTS:
1433
retVal = GetAccessRights(fromEng_P);
1436
case MSG_GET_ENVIRON_INFO:
1437
retVal = GetEnvironInfo(fromEng_P);
1440
case MSG_SET_ENVIRON_INFO:
1441
retVal = SetEnvironInfo(toEng_P);
1444
// Get backup battery info
1445
case MSG_GET_BATTERY_INFO:
1446
retVal = getBatteryInfo(toEng_P, fromEng_P);
1449
// Set backup battery thresholds
1450
case MSG_SET_BATTERY_THRESHOLDS:
1451
retVal = setBatteryThresholds(toEng_P);
1454
// Calibrate the backup battery
1455
case MSG_CALIBRATE_BATTERY:
1456
retVal = calibrateBattery(toEng_P);
1459
// Perform a DMA test on the controller
1460
case MSG_I2O_DMA_TEST:
1461
retVal = i2oDiagTest(toEng_P,fromEng_P, 0x07);
1464
// Perform a RAM test on the controller
1465
case MSG_I2O_RAM_TEST:
1466
retVal = i2oDiagTest(toEng_P,fromEng_P, 0x06);
1469
// Initiate the controller's built-in-self-test
1471
retVal = i2oDiagTest(toEng_P,fromEng_P, 0x08);
1474
// Initialize the device busy logic
1475
case MSG_CHECK_BUSY:
1476
retVal = initBusyLogic(fromEng_P);
1479
// Set the array drive size table
1480
case MSG_SET_ARRAY_DRIVE_SIZES:
1481
retVal = setArrayDriveSizeTable(toEng_P);
1484
// Return the array drive size table
1485
case MSG_GET_ARRAY_DRIVE_SIZES:
1486
retVal = getArrayDriveSizeTable(fromEng_P);
1489
// Return the array drive size table
1490
case MSG_I2O_RESYNC:
1491
retVal = resetHba(toEng_P);
1494
// Send an I2O pass-through message
1495
case MSG_I2O_SEND_MESSAGE:
1496
retVal = sendI2OMessage(fromEng_P, toEng_P);
1499
// Return detailed channel information
1500
case MSG_GET_CHAN_INFO:
1501
retVal = getChanInfo(fromEng_P);
1505
// Call base class event handler
1506
retVal = dptRAIDhba_C::handleMessage(message,fromEng_P,toEng_P);
1514
//dptHBA_C::handleMessage() - end
1517
//Function - dptHBA_C::getChanInfo() - start
1518
//===========================================================================
1519
// This function returns detailed information about each I/O channel/
1520
//---------------------------------------------------------------------------
1522
DPT_RTN_T dptHBA_C::getChanInfo(dptBuffer_S *fromEng_P)
1525
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
1528
engCCB_C *ccb_P = getCCB();
1532
dptChanInfo2_S rtnInfo;
1534
// Read NVRAM to get the HBA ID for each channel
1535
ccb_P->modeSense(0x2e);
1536
ccb_P->target(this);
1537
retVal = launchCCB(ccb_P);
1538
if (retVal == MSG_RTN_COMPLETED) {
1539
hbaId_A[0] = ccb_P->modeParam_P->getData()[0x08];
1540
hbaId_A[1] = ccb_P->modeParam_P->getData()[0x09];
1541
hbaId_A[2] = ccb_P->modeParam_P->getData()[0x0a];
1542
hbaId_A[3] = ccb_P->modeParam_P->getData()[0x19];
1547
// Get log page 0x33
1548
ccb_P->logSense(0x33,0,0xff);
1549
ccb_P->target(this);
1550
retVal = launchCCB(ccb_P);
1551
if (retVal ==MSG_RTN_COMPLETED) {
1552
uLONG numChannels = 0;
1553
uLONG *numChannels_P = (uLONG *) fromEng_P->data;
1554
fromEng_P->insert(numChannels);
1556
ccb_P->initLogSense();
1557
while (ccb_P->log.isValidParam()) {
1558
if (ccb_P->log.code() == 0x0d) {
1560
memset(&rtnInfo, 0, sizeof(dptChanInfo2_S));
1561
rtnInfo.chanNum = ccb_P->log.data_P()[0];
1562
rtnInfo.length = sizeof(dptChanInfo2_S);
1563
rtnInfo.pc13Flags1 = ccb_P->log.data_P()[1];
1564
rtnInfo.pc13Flags2 = ccb_P->log.data_P()[2];
1565
rtnInfo.pc13Speed = ccb_P->log.data_P()[3];
1566
rtnInfo.pc13ScamIdMap1 = ccb_P->log.data_P()[4];
1567
rtnInfo.pc13ScamIdMap2 = ccb_P->log.data_P()[5];
1568
if (ccb_P->log.length() >= 8) {
1569
rtnInfo.pc13Flags3 = ccb_P->log.data_P()[6];
1570
rtnInfo.pc13Flags4 = ccb_P->log.data_P()[7];
1572
if (rtnInfo.chanNum < 4) {
1573
rtnInfo.hbaId = hbaId_A[rtnInfo.chanNum];
1574
rtnInfo.maxXfrSpeed = chanInfo[rtnInfo.chanNum].scsiBusSpeed;
1575
if (rtnInfo.pc13Flags4 & FLG_CHAN2_ULTR320) {
1576
rtnInfo.maxXfrSpeed = 640;
1578
else if (rtnInfo.pc13Flags4 & FLG_CHAN2_ULTR160) {
1579
rtnInfo.maxXfrSpeed = 320;
1583
if (!fromEng_P->insert(&rtnInfo, sizeof(dptChanInfo2_S))) {
1584
retVal = MSG_RTN_DATA_OVERFLOW;
1587
// Get the next log parameter
1591
*numChannels_P = numChannels;
1593
} // end if (launchCCB())
1598
} // end if (ccb_P!=NULL)
1603
//dptHBA_C::getChanInfo() - end
1606
//Function - dptHBA_C::resetHba() - start
1607
//===========================================================================
1609
// This function attempts to reset the HBA
1610
//---------------------------------------------------------------------------
1612
DPT_RTN_T dptHBA_C::sendI2OMessage(dptBuffer_S *fromEng_P, dptBuffer_S *toEng_P)
1615
DPT_RTN_T retVal = MSG_RTN_IGNORED;
1622
//dptHBA_C::sendI2OMessage() - end
1625
//Function - dptHBA_C::resetHba() - start
1626
//===========================================================================
1628
// This function attempts to reset the HBA
1629
//---------------------------------------------------------------------------
1631
DPT_RTN_T dptHBA_C::resetHba(dptBuffer_S *toEng_P)
1634
DPT_RTN_T retVal = MSG_RTN_IGNORED;
1637
uLONG rescanFlags = 0;
1638
retVal = MSG_RTN_DATA_UNDERFLOW;
1639
if (toEng_P->extract(rescanFlags)) {
1640
retVal = osdRescan(getDrvrNum(), rescanFlags);
1641
if (retVal != MSG_RTN_IGNORED) {
1643
engCCB_C *ccb_P = getCCB();
1645
retVal = ERR_GET_CCB;
1648
// Get the inquiry data
1650
ccb_P->target(this);
1651
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
1652
inquiryInit((sdInquiry_S *)ccb_P->defData);
1656
// Get the H/W page etc.
1666
//dptHBA_C::resetHba()
1669
//Function - dptHBA_C::setArrayDriveSizeTable() - start
1670
//===========================================================================
1672
// This function sets the array drive size table.
1673
//---------------------------------------------------------------------------
1675
DPT_RTN_T dptHBA_C::setArrayDriveSizeTable(dptBuffer_S *toEng_P)
1679
DPT_RTN_T retVal = MSG_RTN_COMPLETED;
1680
uLONG saveTable = 0;
1681
uLONG numEntries = 0;
1683
toEng_P->extract(saveTable);
1684
if (!toEng_P->extract(numEntries))
1685
retVal = MSG_RTN_DATA_UNDERFLOW;
1686
else if (((numEntries<<2)+8) > toEng_P->writeIndex)
1687
retVal = MSG_RTN_DATA_UNDERFLOW;
1688
else if (numEntries > MAX_DRIVE_SIZE_ENTRIES)
1689
retVal = ERR_DRIVE_SIZE_TABLE_MAX;
1691
if (driveSizeTable_P != NULL) {
1692
if (numEntries > driveSizeTable_P->getMaxEntries()) {
1693
retVal = ERR_DRIVE_SIZE_TABLE_MAX;
1696
if (retVal == MSG_RTN_COMPLETED) {
1697
driveSizeTable_S *ds_P = (driveSizeTable_S *) toEng_P->data;
1698
if (driveSizeTable_P != NULL) {
1699
ds_P->setMaxEntries(driveSizeTable_P->getMaxEntries());
1702
ds_P->setMaxEntries(MAX_DRIVE_SIZE_ENTRIES);
1704
useDriveSizeTable(ds_P);
1706
retVal = writeDriveSizeTable();
1714
//dptHBA_C::setArrayDriveSizeTable()
1717
//Function - dptHBA_C::getArrayDriveSizeTable() - start
1718
//===========================================================================
1720
// This function returns the array drive size table.
1721
//---------------------------------------------------------------------------
1723
DPT_RTN_T dptHBA_C::getArrayDriveSizeTable(dptBuffer_S *fromEng_P)
1727
DPT_RTN_T retVal = MSG_RTN_COMPLETED;
1728
uLONG maxEntries = 0;
1729
uLONG numEntries = 0;
1731
if (driveSizeTable_P == NULL) {
1732
fromEng_P->insert(maxEntries);
1733
if (!fromEng_P->insert(numEntries)) {
1734
retVal = MSG_RTN_DATA_OVERFLOW;
1738
if (!fromEng_P->insert(driveSizeTable_P, 8+(driveSizeTable_P->getNumEntries()<<2))) {
1739
retVal = MSG_RTN_DATA_OVERFLOW;
1746
//dptHBA_C::getArrayDriveSizeTable()
1749
//Function - dptHBA_C::initBusyLogic() - start
1750
//===========================================================================
1752
// This function initializes the device busy checking code.
1753
//---------------------------------------------------------------------------
1755
DPT_RTN_T dptHBA_C::initBusyLogic(dptBuffer_S *fromEng_P)
1759
DPT_RTN_T retVal = MSG_RTN_IGNORED;
1761
uLONG busyStatus = osdTargetBusy(0, 0, 0, 0);
1762
if (busyStatus & 0x80000000) {
1763
retVal = ERR_BUSY_CHECK_FAILED;
1765
else if (busyStatus != 2) {
1766
retVal = (fromEng_P->insert(busyStatus)) ? MSG_RTN_COMPLETED : MSG_RTN_DATA_OVERFLOW;
1772
//dptHBA_C::initBusyLogic()
1775
//Function - dptHBA_C::i2oDiagTest() - start
1776
//===========================================================================
1778
// This function starts a commanded diagnostic on an I2O controller.
1779
//---------------------------------------------------------------------------
1781
DPT_RTN_T dptHBA_C::i2oDiagTest(dptBuffer_S *toEng_P, dptBuffer_S *fromEng_P, uSHORT fnCode)
1785
DPT_RTN_T retVal = MSG_RTN_IGNORED;
1790
retVal = ERR_MEM_ALLOC;
1791
char *buff_P = new char[4096];
1793
retVal = MSG_RTN_IGNORED;
1794
// Inititialize the message and data pointers
1795
memset(buff_P, 0, 4096);
1796
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *request_P = (PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *)buff_P;
1797
I2O_SINGLE_REPLY_MESSAGE_FRAME *reply_P = (I2O_SINGLE_REPLY_MESSAGE_FRAME *) (buff_P + 1024);
1798
char *data_P = buff_P + 2048;
1800
// Initialize the request message to issue a DPT private SCSI command
1802
if (toEng_P->allocSize < 516)
1803
retVal = MSG_RTN_DATA_UNDERFLOW;
1804
else if (fromEng_P->allocSize < 536)
1805
retVal = MSG_RTN_DATA_OVERFLOW;
1807
i2oInitDmaTest(buff_P, (char *)toEng_P->data+4, (char *)fromEng_P->data);
1810
i2oInitPrivateScsi(buff_P, 0x01, 2048, data_P);
1813
request_P->CDBLength = 6;
1814
request_P->CDB[0] = 0x12;
1815
request_P->CDB[4] = 0xff;
1817
else if (retVal == MSG_RTN_IGNORED) {
1818
request_P->CDBLength = 16;
1819
request_P->CDB[0] = 0xc2;
1820
request_P->CDB[2] = 0x01; // Function version
1821
request_P->CDB[3] = 0x01; // Function category = hardware
1822
setU2(request_P->CDB, 4, fnCode); // Function code
1823
#ifndef _DPT_BIG_ENDIAN
1824
osdSwap2((uSHORT *)(request_P->CDB+4));
1828
if (fnCode == 0x07) {
1830
uCHAR tempFlags = 0;
1832
uCHAR defSourceByte = 0xaa;
1833
uCHAR defDestByte = 0x55;
1835
toEng_P->extract(tempFlags);
1836
toEng_P->extract(defFlags);
1837
toEng_P->extract(defSourceByte);
1838
toEng_P->extract(defDestByte);
1840
// Copy the "source data" if specified
1841
if (toEng_P->skip(512))
1843
// Copy the "destination data" if specified
1844
if (toEng_P->extract(fromEng_P->data+8, 512))
1847
// If the "source data" should be set to a specified value...
1848
if (defFlags & 0x01)
1849
memset(toEng_P->data+4, defSourceByte, 512);
1850
// If the "destination data" should be set to a specified value...
1851
if (defFlags & 0x02)
1852
memset(fromEng_P->data+8, defDestByte, 512);
1854
memset(fromEng_P->data, 0x00, 8); // Initial the CQC header to zero
1855
memset(fromEng_P->data+520, 0x00, 16); // Initial teh ECC data to zero
1857
request_P->CDB[14] = tempFlags;
1860
else if (fnCode == 0x06) {
1862
uCHAR tempFlags = 0;
1863
if (!toEng_P->extract(tempFlags))
1864
retVal = MSG_RTN_DATA_UNDERFLOW;
1866
request_P->CDB[6] = tempFlags;
1869
else if (fnCode == 0x08) {
1874
if (retVal == MSG_RTN_IGNORED) {
1875
retVal = osdSendMessage(drvrRefNum, (I2O_MESSAGE_FRAME *) request_P, (I2O_SCSI_ERROR_REPLY_MESSAGE_FRAME *) reply_P);
1876
if (retVal == MSG_RTN_COMPLETED) {
1877
if (I2O_SINGLE_REPLY_MESSAGE_FRAME_getReqStatus(reply_P) == I2O_REPLY_STATUS_SUCCESS) {
1879
fromEng_P->setExtractSize(536);
1882
if (!fromEng_P->insert(data_P+8, rtnSize))
1883
retVal = MSG_RTN_DATA_OVERFLOW;
1885
else if (!fromEng_P->insert(data_P, 64)) {
1886
retVal = MSG_RTN_DATA_OVERFLOW;
1890
retVal = ERR_I2O_REPLY_FAILURE;
1895
} // (buff_P != NULL)
1896
} // end if (isI2O())
1901
//dptHBA_C::i2oDiagTest()
1904
//Function - dptHBA_C::i2oInitPrivateScsi() - start
1905
//===========================================================================
1907
// This function initializes an I2O request message to send a DPT
1908
//private SCSI pass-through command.
1909
//---------------------------------------------------------------------------
1911
void dptHBA_C::i2oInitPrivateScsi(char *buff_P,
1916
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *privScsi_P = (PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *) buff_P;
1917
I2O_PRIVATE_MESSAGE_FRAME *privI2o_P = &privScsi_P->PrivateMessageFrame;
1918
I2O_MESSAGE_FRAME *i2oMsg_P = &privI2o_P->StdMessageFrame;
1919
uCHAR versionOffset = 0x01;
1921
// Initialize the request message to perform a DPT private SCSI command
1922
I2O_MESSAGE_FRAME_setFunction(i2oMsg_P, I2O_PRIVATE_MESSAGE);
1923
I2O_MESSAGE_FRAME_setInitiatorAddress(i2oMsg_P, 0x01);
1925
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE | I2O_SCB_FLAG_ENABLE_DISCONNECT);
1927
I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode(privI2o_P, I2O_SCSI_SCB_EXEC);
1928
I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(privI2o_P, DPT_ORGANIZATION_ID);
1930
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(privScsi_P, 0x01);
1932
uLONG msgSize = sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT) - 4;
1934
msgSize += 4; // "ByteCount" field
1936
versionOffset |= (msgSize << 2) & 0xf0;
1938
I2O_SGE_SIMPLE_ELEMENT *sg_P = (I2O_SGE_SIMPLE_ELEMENT *)(buff_P + msgSize);
1939
I2O_FLAGS_COUNT *flagsCount_P = &sg_P->FlagsCount;
1940
if (dataDir == 1) { // data in
1941
I2O_FLAGS_COUNT_setFlags(flagsCount_P, (I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER | I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT));
1942
uSHORT scbFlags = PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getSCBFlags(privScsi_P);
1943
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, scbFlags | I2O_SCB_FLAG_XFER_FROM_DEVICE);
1946
I2O_FLAGS_COUNT_setFlags(flagsCount_P, (I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER | I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | I2O_SGL_FLAGS_DIR));
1947
uSHORT scbFlags = PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getSCBFlags(privScsi_P);
1948
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, scbFlags | I2O_SCB_FLAG_XFER_TO_DEVICE);
1950
I2O_FLAGS_COUNT_setCount(flagsCount_P, dataSize);
1951
I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg_P, (uLONG) data_P);
1953
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(privScsi_P, dataSize);
1954
msgSize += sizeof(I2O_SGE_SIMPLE_ELEMENT); // SG element
1957
I2O_MESSAGE_FRAME_setMessageSize(i2oMsg_P, (uSHORT)(msgSize >> 2));
1959
I2O_MESSAGE_FRAME_setVersionOffset(i2oMsg_P, versionOffset);
1964
//dptHBA_C::i2oInitPrivateScsi() - end
1967
//Function - dptHBA_C::i2oInitDmaTest() - start
1968
//===========================================================================
1970
// This function initializes an I2O request message to send a DPT
1971
//private SCSI pass-through command.
1972
//---------------------------------------------------------------------------
1974
void dptHBA_C::i2oInitDmaTest(char *buff_P, char *source_P, char *dest_P)
1976
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *privScsi_P = (PRIVATE_SCSI_SCB_EXECUTE_MESSAGE *) buff_P;
1977
I2O_PRIVATE_MESSAGE_FRAME *privI2o_P = &privScsi_P->PrivateMessageFrame;
1978
I2O_MESSAGE_FRAME *i2oMsg_P = &privI2o_P->StdMessageFrame;
1979
uCHAR versionOffset = 0x01;
1981
// Initialize the request message to perform a DPT private SCSI command
1982
I2O_MESSAGE_FRAME_setFunction(i2oMsg_P, I2O_PRIVATE_MESSAGE);
1983
I2O_MESSAGE_FRAME_setInitiatorAddress(i2oMsg_P, 0x01);
1985
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE | I2O_SCB_FLAG_ENABLE_DISCONNECT);
1987
I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode(privI2o_P, I2O_SCSI_SCB_EXEC);
1988
I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(privI2o_P, DPT_ORGANIZATION_ID);
1990
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(privScsi_P, 0x01);
1992
uLONG msgSize = sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT);
1994
versionOffset |= (msgSize << 2) & 0xf0;
1996
// Initialize the scatter/gather entry for the source buffer
1997
I2O_SGE_SIMPLE_ELEMENT *sg_P = (I2O_SGE_SIMPLE_ELEMENT *)(buff_P + msgSize);
1998
I2O_FLAGS_COUNT *flagsCount_P = &sg_P->FlagsCount;
1999
I2O_FLAGS_COUNT_setFlags(flagsCount_P, (I2O_SGL_FLAGS_END_OF_BUFFER | I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | I2O_SGL_FLAGS_DIR));
2000
uSHORT scbFlags = PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getSCBFlags(privScsi_P);
2001
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, scbFlags | I2O_SCB_FLAG_XFER_TO_DEVICE);
2002
I2O_FLAGS_COUNT_setCount(flagsCount_P, 512);
2003
I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg_P, (uLONG) source_P);
2004
msgSize += sizeof(I2O_SGE_SIMPLE_ELEMENT); // SG element
2006
// Initialize the scatter/gather entry for the destination buffer
2007
sg_P = (I2O_SGE_SIMPLE_ELEMENT *)(buff_P + msgSize);
2008
flagsCount_P = &sg_P->FlagsCount;
2009
I2O_FLAGS_COUNT_setFlags(flagsCount_P, (I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER | I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT));
2010
scbFlags = PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_getSCBFlags(privScsi_P);
2011
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, scbFlags | I2O_SCB_FLAG_XFER_FROM_DEVICE);
2012
I2O_FLAGS_COUNT_setCount(flagsCount_P, 536);
2013
I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg_P, (uLONG) dest_P);
2014
msgSize += sizeof(I2O_SGE_SIMPLE_ELEMENT); // SG element
2016
// Set the byte count to the size of the largest buffer
2017
PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(privScsi_P, 536);
2019
I2O_MESSAGE_FRAME_setMessageSize(i2oMsg_P, (uSHORT)(msgSize >> 2));
2021
I2O_MESSAGE_FRAME_setVersionOffset(i2oMsg_P, versionOffset);
2026
//dptHBA_C::i2oInitDmaTest() - end
2029
//Function - dptHBA_C::getBatteryInfo() - start
2030
//===========================================================================
2032
// This function returns the backup battery information structure.
2033
//---------------------------------------------------------------------------
2035
DPT_RTN_T dptHBA_C::getBatteryInfo(dptBuffer_S *toEng_P, dptBuffer_S *fromEng_P)
2039
DPT_RTN_T retVal = MSG_RTN_IGNORED;
2041
if (isBatteryUnit()) {
2042
uCHAR pageControl = 0;
2044
if (toEng_P->extract(pageType)) {
2046
pageControl = 0x02; // Default values
2050
engCCB_C *ccb_P = getCCB();
2052
retVal = ERR_GET_CCB;
2054
// Mode page 0x3A - battery info
2055
ccb_P->modeSense(0x3A, pageControl);
2057
ccb_P->target(this);
2059
// Send the CCB to hardware
2060
retVal=launchCCB(ccb_P);
2062
if (retVal==MSG_RTN_COMPLETED) {
2066
struct tm *tm_P = NULL; // pointer to the static structure returned by localtime()
2068
dptBatteryModePage_S *info_P = (dptBatteryModePage_S *) ccb_P->modeParam_P->getData();
2071
tempLong = info_P->getStatus();
2072
fromEng_P->insert(tempLong);
2073
tempLong = info_P->getCurrent();
2074
fromEng_P->insert(tempLong);
2075
tempLong = info_P->getVoltage();
2076
fromEng_P->insert(tempLong);
2077
tempLong = info_P->getDesignCapacity();
2078
fromEng_P->insert(tempLong);
2079
tempLong = info_P->getFullChargeCapacity();
2080
fromEng_P->insert(tempLong);
2081
tempLong = info_P->getRemainingCapacity();
2082
fromEng_P->insert(tempLong);
2083
tempLong = info_P->getRemainingTime();
2084
fromEng_P->insert(tempLong);
2085
tempLong = info_P->getMaxRemainingTime();
2086
fromEng_P->insert(tempLong);
2087
tempLong = info_P->getTemperature();
2088
fromEng_P->insert(tempLong);
2089
tempLong = info_P->getMaintenanceCycleCount();
2090
fromEng_P->insert(tempLong);
2091
tempLong = info_P->getHwDesignVersion();
2092
fromEng_P->insert(tempLong);
2094
// Manufacture date fields
2095
tempLong = info_P->getManufactureDate();
2096
tempChar = (uCHAR) (tempLong & 0x1f);
2097
fromEng_P->insert(tempChar); // Day of month
2098
tempChar = (uCHAR) ((tempLong >> 5) & 0xf);
2099
fromEng_P->insert(tempChar); // Month
2100
tempChar = (uCHAR) ((tempLong >> 9) & 0x7f);
2101
fromEng_P->insert(tempChar); // Year (biased by 1980)
2102
tempChar = info_P->getFlags();
2103
fromEng_P->insert(tempChar); // reserved byte
2106
tempLong = info_P->getWriteThruThreshold();
2107
fromEng_P->insert(tempLong);
2108
tempLong = info_P->getPredictiveFailureThreshold();
2109
fromEng_P->insert(tempLong);
2110
tempLong = 0; // used to be "normal threshold" now it's reserved
2111
fromEng_P->insert(tempLong);
2112
tempLong = info_P->getThresholdEnable();
2113
fromEng_P->insert(tempLong);
2115
// Date of last maintenance calibration
2116
tempLong = info_P->getMaintenanceDate();
2118
tm_P = localtime((const time_t *)&tempLong);
2121
fromEng_P->insert(tempLong);
2124
tempChar = tm_P->tm_mday;
2125
fromEng_P->insert(tempChar); // Day of month
2126
tempChar = tm_P->tm_mon + 1;
2127
fromEng_P->insert(tempChar); // Month
2128
tempChar = tm_P->tm_year - 80; // Year is already biased by 1900 so we only need to take out another 80
2129
fromEng_P->insert(tempChar); // Year
2131
fromEng_P->insert(tempChar); // reserved byte
2135
fromEng_P->insert(tempLong);
2137
// Date of last initial calibration
2138
tempLong = info_P->getInitialCalibrationDate();
2140
tm_P = localtime((const time_t *)&tempLong);
2143
fromEng_P->insert(tempLong);
2146
tempChar = tm_P->tm_mday;
2147
fromEng_P->insert(tempChar); // Day of month
2148
tempChar = tm_P->tm_mon + 1;
2149
fromEng_P->insert(tempChar); // Month
2150
tempChar = tm_P->tm_year - 80; // Year is already biased by 1900 so we only need to take out another 80
2151
fromEng_P->insert(tempChar); // Year
2153
fromEng_P->insert(tempChar); // reserved byte
2157
fromEng_P->insert(tempLong);
2160
info_P->getDeviceChemistry()[15] = 0; // ensure NULL terminated
2161
fromEng_P->insert(info_P->getDeviceChemistry(), 16);
2162
info_P->getManufacturerName()[15] = 0; // ensure NULL terminated
2163
fromEng_P->insert(info_P->getManufacturerName(), 16);
2164
info_P->getDeviceName()[15] = 0; // ensure NULL terminated
2165
if (!fromEng_P->insert(info_P->getDeviceName(), 16))
2166
retVal = MSG_RTN_DATA_OVERFLOW;
2168
retVal = MSG_RTN_COMPLETED;
2170
} // launchCCB() - end
2177
} // if (isBatteryUnit())
2182
//dptHBA_C::getBatteryInfo() - end
2185
//Function - dptHBA_C::setBatteryThresholds() - start
2186
//===========================================================================
2188
// This function sets the backup battery threshold levels.
2189
//---------------------------------------------------------------------------
2191
DPT_RTN_T dptHBA_C::setBatteryThresholds(dptBuffer_S *toEng_P)
2195
DPT_RTN_T retVal = MSG_RTN_IGNORED;
2197
if (isBatteryUnit()) {
2199
engCCB_C *ccb_P = getCCB();
2201
retVal = ERR_GET_CCB;
2204
// --- Read the battery info mode page ---
2206
// Mode page 0x3A - battery info
2207
ccb_P->modeSense(0x3A);
2209
ccb_P->target(this);
2210
// Send the CCB to hardware
2211
retVal = launchCCB(ccb_P);
2213
// Send the CCB to hardware
2214
if (retVal==MSG_RTN_COMPLETED) {
2218
dptBatteryModePage_S *info_P = (dptBatteryModePage_S *) ccb_P->modeParam_P->getData();
2220
// --- Write the battery info mode page ---
2222
memset(ccb_P->eataCP.scsiCDB, 0, 12);
2223
ccb_P->modeSelect(0x3A, (uSHORT)(dptBatteryModePage_S::size() + 2));
2224
ccb_P->target(this);
2226
toEng_P->extract(tempLong);
2227
info_P->setWriteThruThreshold((uSHORT)tempLong);
2228
info_P->swapWriteThruThreshold();
2230
toEng_P->extract(tempLong);
2231
info_P->setPredictiveFailureThreshold((uSHORT)tempLong);
2232
info_P->swapPredictiveFailureThreshold();
2234
toEng_P->extract(tempLong); // reserved
2236
if (!toEng_P->extract(tempLong))
2237
retVal = MSG_RTN_DATA_UNDERFLOW;
2239
info_P->setThresholdEnable((uSHORT)tempLong);
2240
info_P->swapThresholdEnable();
2242
// Send the mode select to hardware
2243
retVal = launchCCB(ccb_P);
2246
} // launchCCB() - end
2253
} // end if (ccb_P!=NULL)
2258
//dptHBA_C::setBatteryThresholds() - end
2261
//Function - dptHBA_C::calibrateBattery() - start
2262
//===========================================================================
2264
// This function calibrates the backup battery.
2266
// calibrationType = 0, Perform initial calibration (charge, discharge, recharge)
2267
// calibrationType = 1, Perform maintenance calibration (discharge, charge)
2268
//---------------------------------------------------------------------------
2270
DPT_RTN_T dptHBA_C::calibrateBattery(dptBuffer_S *toEng_P)
2273
DPT_RTN_T retVal = MSG_RTN_IGNORED;
2275
if (isBatteryUnit()) {
2276
uCHAR calibrationType = 0;
2278
// Get the calibration type (initial calibration == 0, maintenance calibration == 1)
2279
if (!toEng_P->extract(calibrationType))
2280
retVal = MSG_RTN_DATA_UNDERFLOW;
2282
retVal = sendMFC(MFC_CALIBRATE_BATTERY, calibrationType);
2288
//dptHBA_C::calibrateBattery() - end
2291
//Function - dptHBA_C::getBatteryStatus() - start
2292
//===========================================================================
2294
// This function returns the backup battery information structure.
2295
//---------------------------------------------------------------------------
2297
DPT_RTN_T dptHBA_C::getBatteryStatus()
2300
DPT_RTN_T retVal = MSG_RTN_IGNORED;
2302
if (isBatteryUnit()) {
2303
uCHAR pageControl = 0;
2305
engCCB_C *ccb_P = getCCB();
2307
retVal = ERR_GET_CCB;
2309
// Mode page 0x3A - battery info
2310
ccb_P->modeSense(0x3A, pageControl);
2312
ccb_P->target(this);
2314
// Send the CCB to hardware
2315
retVal=launchCCB(ccb_P);
2317
if (retVal==MSG_RTN_COMPLETED) {
2318
dptBatteryModePage_S *info_P = (dptBatteryModePage_S *) ccb_P->modeParam_P->getData();
2321
// Update the battery status and flags
2322
batteryStatus = info_P->getStatus();
2323
batteryFlags = info_P->getFlags();
2325
} // launchCCB() - end
2333
} // end if (isBatteryUnit)
2338
//dptHBA_C::getBatteryInfo() - end
2341
//Function - dptHBA_C::getArrayLimits() - start
2342
//===========================================================================
2345
// This function returns the firmware array limit information
2348
//---------------------------------------------------------------------------
2350
DPT_RTN_T dptHBA_C::getArrayLimits(dptBuffer_S *fromEng_P)
2353
DPT_RTN_T retVal = ERR_GET_CCB;
2356
engCCB_C *ccb_P = getCCB();
2358
retVal = MSG_RTN_IGNORED;
2359
// Initialize the CCB to do a log sense page 0x33
2360
// Limit data buffer to 0xff bytes
2361
ccb_P->logSense(0x33,0,0xff);
2363
ccb_P->target(this);
2364
// Send the CCB to hardware
2365
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
2366
// Initialize the log page
2367
ccb_P->initLogSense();
2368
// Find the array limits parameter
2369
if (ccb_P->log.find(0x0e)) {
2370
if (ccb_P->log.length() >= dptArrayLimits_S::size()) {
2372
retVal = MSG_RTN_COMPLETED;
2373
dptArrayLimits_S *limits_P = (dptArrayLimits_S *) ccb_P->log.data_P();
2374
limits_P->scsiSwap();
2375
if (!fromEng_P->insert(limits_P,dptArrayLimits_S::size()))
2376
retVal = MSG_RTN_DATA_OVERFLOW;
2379
retVal = MSG_RTN_IGNORED;
2381
} // end if (launchCCB()==MSG_RTN_COMPLETED)
2385
} // end if (ccb_P!=NULL)
2390
//dptHBA_C::getArrayLimits() - end
2393
//Function - dptHBA_C::setExclusion() - start
2394
//===========================================================================
2398
// This function sets the HBA's background task exclusion period.
2400
//---------------------------------------------------------------------------
2402
DPT_RTN_T dptHBA_C::setExclusion(dptBuffer_S *toEng_P)
2405
DPT_RTN_T retVal = MSG_RTN_DATA_UNDERFLOW;
2406
uCHAR startTime,endTime;
2408
toEng_P->extract(startTime);
2409
if (toEng_P->extract(endTime)) {
2410
// The time cannot be larger than 23 since it is a 24 hour count (0-23)
2411
if ((startTime >= 24) || (endTime >= 24) || (startTime > endTime))
2412
retVal = MSG_RTN_FAILED | ERR_EXCLUSION_TIME;
2414
retVal = sendMFC(MFC_DIAG_EXCLUSION,startTime,endTime);
2415
if (retVal == MSG_RTN_COMPLETED) {
2416
// Update the HBA's background task exclusion period
2417
excludeStart = startTime;
2418
excludeEnd = endTime;
2426
//dptHBA_C::setExclusion() - end
2429
//Function - dptHBA_C::readDriveSizeTable() - start
2430
//===========================================================================
2432
// This function reads the drive size table from the controller.
2433
//---------------------------------------------------------------------------
2435
DPT_RTN_T dptHBA_C::readDriveSizeTable()
2438
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2440
engCCB_C *ccb_P = getCCB();
2442
// Read the controller's drive size table
2443
ccb_P->readDriveSizeTable();
2445
ccb_P->target(this);
2446
// Send the CCB to hardware
2447
retVal = launchCCB(ccb_P);
2448
if (retVal == MSG_RTN_COMPLETED) {
2449
driveSizeTable_S *ds_P = (driveSizeTable_S *) ccb_P->dataBuff_P;
2450
ds_P->swapFromBigEndian();
2451
useDriveSizeTable(ds_P);
2461
//dptHBA_C::readDriveSizeTable() - end
2464
//Function - dptHBA_C::writeDriveSizeTable() - start
2465
//===========================================================================
2467
// This function writes the current drive size table to the controller.
2468
//---------------------------------------------------------------------------
2470
DPT_RTN_T dptHBA_C::writeDriveSizeTable()
2473
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_NO_DRIVE_SIZE_TABLE;
2475
if (driveSizeTable_P != NULL) {
2476
retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2477
engCCB_C *ccb_P = getCCB();
2479
uLONG tableSize = 8+(driveSizeTable_P->getNumEntries()<<2);
2480
// Get the drive size table
2481
ccb_P->writeDriveSizeTable(tableSize);
2483
ccb_P->target(this);
2484
// Copy the current drive size table to the output buffer
2485
memcpy(ccb_P->dataBuff_P, driveSizeTable_P, tableSize);
2486
driveSizeTable_S *ds_P = (driveSizeTable_S *) ccb_P->dataBuff_P;
2487
ds_P->swapToBigEndian();
2489
// Send the CCB to hardware
2490
retVal = launchCCB(ccb_P);
2500
//dptHBA_C::writeDriveSizeTable() - end
2503
//Function - dptHBA_C::useDriveSizeTable() - start
2504
//===========================================================================
2506
// This function sets the current drive size table from the specified
2508
//---------------------------------------------------------------------------
2510
void dptHBA_C::useDriveSizeTable(driveSizeTable_S *ds_P)
2513
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2515
// If a table has not been allocated...
2516
if (driveSizeTable_P == NULL)
2517
driveSizeTable_P = (driveSizeTable_S *) new uCHAR[8+(MAX_DRIVE_SIZE_ENTRIES<<2)];
2519
// Limit the maximum number of entries to the engine's limit
2520
if (ds_P->getMaxEntries() > MAX_DRIVE_SIZE_ENTRIES)
2521
ds_P->setMaxEntries(MAX_DRIVE_SIZE_ENTRIES);
2522
// Limit the current number of entries to the table's limit
2523
if (ds_P->getNumEntries() > ds_P->getMaxEntries())
2524
ds_P->setNumEntries(ds_P->getMaxEntries());
2526
if (driveSizeTable_P) {
2527
// Clear the entire buffer
2528
memset(driveSizeTable_P, 0, 8+(MAX_DRIVE_SIZE_ENTRIES<<2));
2529
// Copy the valid data
2530
memcpy(driveSizeTable_P, ds_P, 8+(ds_P->getNumEntries()<<2));
2535
//dptHBA_C::useDriveSizeTable() - end
2538
//Function - dptHBA_C::sendMFC() - start
2539
//===========================================================================
2543
// This function sends a RAID multi-function command to this HBA.
2545
//---------------------------------------------------------------------------
2547
DPT_RTN_T dptHBA_C::sendMFC(uCHAR inCmd,uCHAR inModifier,uCHAR inParam)
2550
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2552
engCCB_C *ccb_P = getCCB();
2554
// Initialize the CCB for a DPT multi-function command
2555
ccb_P->mfCmd(inCmd,inModifier,inParam);
2557
ccb_P->target(this);
2558
// Send the CCB to hardware
2559
retVal = launchCCB(ccb_P);
2568
//dptHBA_C::sendMFC() - end
2571
//Function - dptHBA_C::sendExtMFC() - start
2572
//===========================================================================
2576
// This function sends an extended multi-function command to this HBA.
2578
//---------------------------------------------------------------------------
2580
DPT_RTN_T dptHBA_C::sendExtMFC(uCHAR inCmd,uCHAR inModifier,
2587
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2589
engCCB_C *ccb_P = getCCB();
2591
// Initialize the CCB for an extended DPT multi-function command
2592
ccb_P->extMfCmd(inCmd,inModifier,inParam1,inParam2,inParam3);
2594
ccb_P->target(this);
2595
// Send the CCB to hardware
2596
retVal = launchCCB(ccb_P);
2605
//dptHBA_C::sendExtMFC() - end
2608
//Function - dptHBA_C::updateStatus() - start
2609
//===========================================================================
2613
// This function updates this HBA's status.
2615
//---------------------------------------------------------------------------
2617
DPT_RTN_T dptHBA_C::updateStatus(dptBuffer_S *fromEng_P)
2620
DPT_RTN_T retVal = MSG_RTN_IGNORED;
2624
retVal = MSG_RTN_COMPLETED;
2625
// If the controller is in a blink LED condition...
2626
if (osdCheckBLED(getDrvrNum(),&LEDpattern)) {
2627
if ((LEDpattern == 0x69) || (LEDpattern == 0x6a)) {
2628
// If not previously in flash mode...
2629
if (status.main != SMAIN_FLASH_MODE)
2630
status.sub = SSUB_FLASH_INIT;
2631
status.main = SMAIN_FLASH_MODE;
2632
status.display = DSPLY_STAT_WARNING;
2635
status.main = SMAIN_BLINK_LED;
2636
status.sub = (uCHAR) LEDpattern;
2637
status.display = DSPLY_STAT_FAILED;
2641
retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2644
status.display = DSPLY_STAT_OPTIMAL;
2646
engCCB_C *ccb_P = getCCB();
2648
// Initialize the CCB to do a log sense page 0x33
2649
// Limit data buffer to 0xff bytes
2650
ccb_P->logSense(0x33,0,0xff);
2652
ccb_P->target(this);
2653
// Send the CCB to hardware
2654
if ((retVal = launchCCB(ccb_P))==MSG_RTN_COMPLETED) {
2655
ccb_P->initLogSense();
2656
// Find parameter #2
2657
if (ccb_P->log.find(0x02)!=NULL) {
2658
fwFlags = ccb_P->log.data_P()[0];
2660
// Find parameter #9
2661
if (ccb_P->log.findNext(0x09)!=NULL) {
2662
// Determine if the alarm is on or off
2663
if (ccb_P->log.data_P()[3] & 0x40)
2664
// Indicate that the alarm is on
2665
status.flags |= FLG_STAT_ALARM_ON;
2667
// Indicate that the alarm is off
2668
status.flags &= ~FLG_STAT_ALARM_ON;
2670
if (ccb_P->log.findNext(0x0c)!=NULL) {
2671
hbaFlags2 &= 0xffffff00;
2672
hbaFlags2 |= ((uSHORT) ccb_P->log.data_P()[0]) & 0xff;
2673
// Make the invalid subsystem status flag a valid flag
2674
hbaFlags2 ^= FLG_HBA_SUBSYS_VALID;
2676
uSHORT notCrazy = 10; // for safety
2677
// Update all channel info
2678
while ((ccb_P->log.findNext(0x0d)!=NULL) && notCrazy--)
2679
updateChannelInfo(&(ccb_P->log));
2681
if(hbaFlags2 & FLG_HBA_TEMP_PROBE)
2683
if (ccb_P->log.findNext(0x10)!=NULL) {
2684
currVoltage = *(uSHORT *)(ccb_P->log.data_P());
2685
currTemperature = *(uSHORT *)(ccb_P->log.data_P()+2);
2686
osdSwap2(&currVoltage);
2687
osdSwap2(&currTemperature);
2689
} // end if (launchCCB())
2693
} // end if (ccb_!=NULL)
2694
} // end if (!blink LED)
2696
// Update the battery status
2699
// If returning the status...
2700
if (fromEng_P != NULL) {
2701
// If not another type of error...
2702
if (!fromEng_P->insert(&status,sizeof(dptStatus_S))) {
2703
if (retVal == MSG_RTN_COMPLETED)
2704
retVal = MSG_RTN_DATA_OVERFLOW;
2707
} // end if (isReal())
2712
//dptHBA_C::updateStatus() - end
2715
//Function - dptHBA_C::getTime() - start
2716
//===========================================================================
2720
// This function reads the time from the HBA.
2726
//Global Variables Affected:
2728
//Remarks: (Side effects, Assumptions, Warnings...)
2731
//---------------------------------------------------------------------------
2733
DPT_RTN_T dptHBA_C::getTime(dptBuffer_S *fromEng_P)
2736
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2739
engCCB_C *ccb_P = getCCB();
2741
// Initialize the CDB to perform a mode sense
2742
ccb_P->modeSense(0x2f);
2744
ccb_P->target(this);
2745
// Send the CCB to hardware
2746
if ((retVal = launchCCB(ccb_P))==MSG_RTN_COMPLETED) {
2747
uLONG inTime = getU4(ccb_P->modeParam_P->getData(),2);
2748
reverseBytes(inTime);
2749
retVal = MSG_RTN_DATA_OVERFLOW;
2750
if (fromEng_P->insert(inTime))
2751
retVal = MSG_RTN_COMPLETED;
2752
} // end if (launchCCB())
2756
} // end if (ccb_P!=NULL)
2761
//dptHBA_C::getTime() - end
2764
//Function - dptHBA_C::setTime() - start
2765
//===========================================================================
2769
// This function sets the HBA time.
2775
//Global Variables Affected:
2777
//Remarks: (Side effects, Assumptions, Warnings...)
2780
//---------------------------------------------------------------------------
2782
DPT_RTN_T dptHBA_C::setTime(dptBuffer_S *toEng_P)
2785
DPT_RTN_T retVal = MSG_RTN_DATA_UNDERFLOW;
2788
// Get the new time value
2789
if (toEng_P->extract(hbaTime)) {
2790
retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2792
engCCB_C *ccb_P = getCCB();
2794
// Zero the data buffer
2796
// Initialize the CCB to do a mode select page 0x2f
2797
ccb_P->modeSelect6(0x2f,0x06+2);
2799
ccb_P->target(this);
2801
uLONG *time_P = (uLONG *) (ccb_P->modeParam_P->getData()+2);
2802
setU4(time_P,0,hbaTime);
2803
reverseBytes(*time_P);
2804
// Send the CCB to hardware
2805
retVal = launchCCB(ccb_P);
2809
} // end if (ccb_P!=NULL)
2815
//dptHBA_C::setTime() - end
2818
//Function - dptHBA_C::checkForEmul() - start
2819
//===========================================================================
2823
// This function checks for emulated drives associated with this HBA.
2829
//Global Variables Affected:
2831
//Remarks: (Side effects, Assumptions, Warnings...)
2834
//---------------------------------------------------------------------------
2836
void dptHBA_C::checkForEmul()
2841
dptDevice_C *dev_P = (dptDevice_C *) logList.reset();
2842
while ((dev_P!=NULL) && !done) {
2843
done = dev_P->checkForEmulation();
2844
dev_P = (dptDevice_C *) logList.next();
2848
//dptHBA_C::checkForEmul() - end
2851
//Function - dptHBA_C::getEventCtl() - start
2852
//===========================================================================
2856
// This function gets the DPT HBA event log control word.
2862
//Global Variables Affected:
2864
//Remarks: (Side effects, Assumptions, Warnings...)
2867
//---------------------------------------------------------------------------
2869
void dptHBA_C::getEventCtl()
2872
engCCB_C *ccb_P = getCCB();
2874
// Initialize the CCB to get the HBA event log control word
2875
ccb_P->modeSense(0x22,0,0,0x60);
2877
ccb_P->target(this);
2878
if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
2879
// Get the event log control word
2880
eventLogCtl = getU4(ccb_P->modeParam_P->getData(),0);
2881
reverseBytes(eventLogCtl);
2889
//dptHBA_C::getEventCtl() - end
2892
//Function - dptHBA_C::setEventCtl() - start
2893
//===========================================================================
2897
// This function sets the DPT HBA event log control word.
2903
//Global Variables Affected:
2905
//Remarks: (Side effects, Assumptions, Warnings...)
2908
//---------------------------------------------------------------------------
2910
DPT_RTN_T dptHBA_C::setEventCtl(dptBuffer_S *toEng_P)
2913
DPT_RTN_T retVal = MSG_RTN_DATA_UNDERFLOW;
2917
// Get the new event control word
2918
if (toEng_P->extract(newEventCtl)) {
2919
retVal = MSG_RTN_FAILED | ERR_GET_CCB;
2920
// Get the save to non-volatile status
2921
if (!toEng_P->extract(saveToNV))
2924
engCCB_C *ccb_P = getCCB();
2926
// Initialize the CCB to get the HBA event log control word
2927
ccb_P->modeSelect(0x22,0x04+2,saveToNV & 0x7f);
2929
ccb_P->target(this);
2930
// Set the event log control word
2931
reverseBytes(newEventCtl);
2932
setU4(ccb_P->modeParam_P->getData(),0,newEventCtl);
2933
// Send the mode select to hardware
2934
retVal = launchCCB(ccb_P);
2935
if (retVal == MSG_RTN_COMPLETED)
2936
eventLogCtl = newEventCtl;
2946
//dptHBA_C::setEventCtl() - end
2949
//Function - dptHBA_C::rtnEventLog() - start
2950
//===========================================================================
2954
// This function returns the event log for this HBA (non-destructively).
2960
//Global Variables Affected:
2962
//Remarks: (Side effects, Assumptions, Warnings...)
2965
//---------------------------------------------------------------------------
2967
DPT_RTN_T dptHBA_C::rtnEventLog(dptBuffer_S *toEng_P,
2968
dptBuffer_S *fromEng_P
2972
DPT_RTN_T retVal = MSG_RTN_IGNORED;
2975
if (is512kCache() || isI2O()) {
2976
if (!toEng_P->extract(offset))
2979
// Get the event log data - Do not clear the event log
2980
retVal = doLogSense(fromEng_P,0x34,1,offset,1);
2982
if (retVal==MSG_RTN_COMPLETED) {
2984
// Initialize the HBA log sense data (reverse byte ordering)
2985
hbaLog.initSense(fromEng_P->data,1);
2992
//dptHBA_C::rtnEventLog() - end
2995
//Function - dptHBA_C::clearEventLog() - start
2996
//===========================================================================
3000
// This function clears the HBA event log.
3006
//Global Variables Affected:
3008
//Remarks: (Side effects, Assumptions, Warnings...)
3011
//---------------------------------------------------------------------------
3013
DPT_RTN_T dptHBA_C::clearEventLog()
3016
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3018
engCCB_C *ccb_P = getCCB();
3021
ccb_P->target(this);
3022
// Indicate that this is an event logger command
3023
ccb_P->setLoggerCmd(0);
3024
// Initialize the CCB to perform a SCSI log sense
3025
ccb_P->logSense(0x34,0,0xff);
3026
// Send the CCB to hardware
3027
retVal = launchCCB(ccb_P);
3036
//dptHBA_C::clearEventLog() - end
3039
//Function - dptHBA_C::rtnHBAstats() - start
3040
//===========================================================================
3044
// Return this HBA's global statistics information.
3050
//Global Variables Affected:
3052
//Remarks: (Side effects, Assumptions, Warnings...)
3055
//---------------------------------------------------------------------------
3057
DPT_RTN_T dptHBA_C::rtnHBAstats(dptBuffer_S *fromEng_P,
3062
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3064
engCCB_C *ccb_P = getCCB();
3066
// Initialize the CCB to get the global statistics page
3067
ccb_P->logSense(0x30,savePage);
3069
ccb_P->target(this);
3070
// Send the CCB to hardware
3071
if ((retVal = launchCCB(ccb_P))==MSG_RTN_COMPLETED) {
3073
retVal = MSG_RTN_DATA_OVERFLOW;
3074
dptHBAstatLog_C hbaStat;
3075
// Initialize the log page data (reverse bytes)
3076
hbaStat.initSense(ccb_P->defData,1);
3077
// Copy the statistics data to the output buffer
3078
if (fromEng_P->insert(hbaStat.data_P(),sizeof(hbaStats_S)))
3079
retVal = MSG_RTN_COMPLETED;
3089
//dptHBA_C::rtnHBAstats() - end
3092
//Function - dptHBA_C::rtnIOstats() - start
3093
//===========================================================================
3097
// Return this HBA's global read/write statistics information.
3103
//Global Variables Affected:
3105
//Remarks: (Side effects, Assumptions, Warnings...)
3108
//---------------------------------------------------------------------------
3110
DPT_RTN_T dptHBA_C::rtnIOstats(dptBuffer_S *fromEng_P,
3115
DPT_RTN_T retVal = MSG_RTN_DATA_OVERFLOW;
3117
// If clear stats data...
3119
// Clear the statistics buffer
3120
retVal = addRWstats(NULL,savePage);
3121
else if (fromEng_P->allocSize>=sizeof(devStats_S)) {
3122
// Initialize the return statistics to zero
3123
memset(fromEng_P->data,0,sizeof(devStats_S));
3124
// Get this device's statistics
3125
retVal = addRWstats((uLONG *)fromEng_P->data,savePage);
3126
// Set the buffer's write indexes
3127
fromEng_P->writeIndex = sizeof(devStats_S);
3133
//dptHBA_C::rtnIOstats() - end
3136
//Function - dptHBA_C::delEmulation() - start
3137
//===========================================================================
3141
// This function deletes all emulated drives associated with this
3148
//Global Variables Affected:
3150
//Remarks: (Side effects, Assumptions, Warnings...)
3153
//---------------------------------------------------------------------------
3155
DPT_RTN_T dptHBA_C::delEmulation()
3158
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3159
dptEmulation_S *emul_P;
3166
engCCB_C *ccb_P = getCCB();
3169
ccb_P->target(this);
3170
// Get the emulated drive mode page
3171
ccb_P->modeSense(0x3d,0,0,0x60);
3172
if ((retVal=launchCCB(ccb_P))==MSG_RTN_COMPLETED) {
3173
// Cast the return data as mode
3174
emul_P = (dptEmulation_S *) ccb_P->modeParam_P->getData();
3175
// Save the status byte
3176
emulStatus = emul_P->getStatus();
3177
// If there are any emulated drives...
3178
if (emul_P->getStatus() & 0x0f) {
3179
// Save the emulated drive SCSI addresses
3180
memcpy(emulAddrs,emul_P->getChanID0_P(),8);
3181
// Zero the output data buffer
3183
for (bitTest=1,i=0;bitTest<=0x08;bitTest<<=1,i+=2) {
3184
if (emulStatus & bitTest) {
3185
// Re-initialize the CCB
3187
// Perform an emulated drive page select
3188
ccb_P->modeSelect(0x3d,0x10);
3189
// Set the emulated drive's SCSI address
3190
devAddr.chan = emulAddrs[i] >> 5;
3191
devAddr.id = emulAddrs[i] & 0x1f;
3192
devAddr.lun = emulAddrs[i+1];
3193
// Target the emulated drive address
3194
ccb_P->target(devAddr,this,CCB_ORIG_MGR);
3195
emul_P->setStatus((uCHAR) bitTest);
3196
// Send the CCB to the HBA
3209
//dptHBA_C::delEmulation() - end
3212
//Function - dptHBA_C::flashWriteInit() - start
3213
//===========================================================================
3217
// This function performs the required initialization to prepare
3218
//the HBA's flash memory to be programmed.
3220
//---------------------------------------------------------------------------
3222
DPT_RTN_T dptHBA_C::flashWriteInit(engCCB_C *ccb_P)
3225
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_FLASH_SWITCH_MODES;
3229
switchToFlashMode(ccb_P);
3230
// If in flash mode...
3232
// kmc 10/02/1998 - Initializing to zero here.
3233
// When using the setregion methods, we have to reset this to 0,
3234
// or else we get the wrong offsets when sending them down with the
3235
// flashcmd in ::flashWrite(...)
3237
retVal = MSG_RTN_COMPLETED;
3238
} else if (isFlashMode()) {
3241
ccb_P->target(this);
3245
ccb_P->flashCmd(FLASH_CMD_ERASE);
3246
if ((retVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
3252
dptBuffer_S *inBuffer_P = dptBuffer_S::newBuffer(1024);
3253
dptBuffer_S *outBuffer_P = dptBuffer_S::newBuffer(1024);
3255
if (inBuffer_P && outBuffer_P && ((post-pre) > 1)) {
3256
inBuffer_P->reset();
3258
retVal += flashStatus(inBuffer_P);
3259
dptFlashStatus_S *status_P = (dptFlashStatus_S *) &inBuffer_P->data[8];
3261
uLONG numFlashBytes = status_P->getBurnSize();
3264
while(curRead < numFlashBytes) {
3266
outBuffer_P->reset();
3267
outBuffer_P->insert(curRead);
3268
outBuffer_P->insert((uLONG) 512);
3269
inBuffer_P->reset();
3271
retVal += flashRead(outBuffer_P,inBuffer_P);
3273
for(int x = 0; x < 512; x++) {
3274
if (inBuffer_P->data[x] != 0xff)
3280
dptBuffer_S::delBuffer(inBuffer_P);
3281
dptBuffer_S::delBuffer(outBuffer_P);
3288
retVal = MSG_RTN_FAILED | ERR_FLASH_ERASE;
3290
status.sub = SSUB_FLASH_WRITE;
3292
retVal = MSG_RTN_COMPLETED;
3296
retVal = MSG_RTN_FAILED | ERR_FLASH_ERASE;
3301
//dptHBA_C::flashWriteInit() - end
3304
//Function - dptHBA_C::flashWrite() - start
3305
//===========================================================================
3309
// This function writes the specified data to the next unwritten
3310
//location in the flash memory.
3312
//---------------------------------------------------------------------------
3314
DPT_RTN_T dptHBA_C::flashWrite(dptBuffer_S *toEng_P,uINT verify)
3318
DEBUG_BEGIN(1, dptHBA_C::flashWrite());
3320
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3322
engCCB_C *ccb_P = getCCB();
3325
// If we're not in flash write mode...
3326
if (isFlashMode() != SSUB_FLASH_WRITE) {
3327
// Try to get into flash write mode
3328
if ((retVal = flashWriteInit(ccb_P)) != MSG_RTN_COMPLETED)
3330
// Indicate that we are prepared to write to the flash
3331
status.sub = SSUB_FLASH_WRITE;
3334
retVal = MSG_RTN_DATA_UNDERFLOW;
3335
if (toEng_P->writeIndex & 0x1ff)
3336
retVal = MSG_RTN_FAILED | ERR_FLASH_WRITE_512;
3338
uLONG bytesWritten = 0;
3339
while (toEng_P->extract(ccb_P->defData,512)) {
3341
ccb_P->target(this);
3342
ccb_P->flashCmd(FLASH_CMD_WRITE,flashWriteCnt + flashRegionOffset);
3343
retVal = launchCCB(ccb_P);
3344
if (verify && (retVal == MSG_RTN_COMPLETED)) {
3347
retVal = MSG_RTN_FAILED | ERR_FLASH_ENG_VERIFY;
3349
ccb_P->target(this);
3350
ccb_P->flashCmd(FLASH_CMD_READ,flashWriteCnt + flashRegionOffset);
3351
if (launchCCB(ccb_P) == MSG_RTN_COMPLETED) {
3352
if (memcmp(toEng_P->data+bytesWritten,ccb_P->defData,512) == 0)
3353
retVal = MSG_RTN_COMPLETED;
3357
// If a failure has occurred...
3358
if (retVal != MSG_RTN_COMPLETED) {
3359
status.sub = SSUB_FLASH_INIT;
3361
DEBUG(1, PRT_ADDR << "FLASH FAILURE - retVal=0x" << hex << retVal);
3365
bytesWritten += 512;
3366
flashWriteCnt += 512;
3368
DEBUG(1, PRT_ADDR << PRT_STAT << (int)flashWriteCnt << "Byte written");
3380
//dptHBA_C::flashWrite() - end
3383
//Function - dptHBA_C::flashWriteDone() - start
3384
//===========================================================================
3388
// This function closes out the flash programming process. This
3389
//function causes the F/W flash code to compute and write the
3392
//---------------------------------------------------------------------------
3394
DPT_RTN_T dptHBA_C::flashWriteDone(uCHAR sendToHW)
3397
// if SM has requested that we reset our pointers and not write
3398
// the checksum in the FW
3399
if (!isI2O() && !sendToHW) {
3400
status.sub = SSUB_FLASH_INIT;
3401
return(MSG_RTN_COMPLETED);
3405
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3407
engCCB_C *ccb_P = getCCB();
3409
// If in flash write mode...
3410
// if (isFlashMode() == SSUB_FLASH_WRITE) {
3411
// Always take out of flash write mode
3412
status.sub = SSUB_FLASH_INIT;
3413
// Send the write done command to firmware
3414
ccb_P->target(this);
3415
ccb_P->flashCmd(FLASH_CMD_WRITE_DONE);
3416
retVal = launchCCB(ccb_P);
3420
// retVal = MSG_RTN_FAILED | ERR_FLASH_INIT_REQ;
3429
//dptHBA_C::flashWriteDone() - end
3432
//Function - dptHBA_C::flashRead() - start
3433
//===========================================================================
3437
// This function reads from the HBA's flash memory. Reading of
3438
//the flash does not require that the HBA be in flash mode.
3440
//---------------------------------------------------------------------------
3442
DPT_RTN_T dptHBA_C::flashRead(dptBuffer_S *toEng_P,dptBuffer_S *fromEng_P)
3445
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3447
engCCB_C *ccb_P = getCCB();
3450
uLONG bytesRequested;
3451
retVal = MSG_RTN_DATA_UNDERFLOW;
3452
toEng_P->extract(flashAddr);
3453
if (toEng_P->extract(bytesRequested)) {
3455
while (bytesRequested) {
3456
bytesToRead = (bytesRequested > 512) ? 512 : bytesRequested;
3457
ccb_P->target(this);
3458
ccb_P->flashCmd(FLASH_CMD_READ,flashAddr + flashRegionOffset,bytesToRead);
3459
retVal = launchCCB(ccb_P);
3460
if (retVal == MSG_RTN_COMPLETED) {
3461
if (!fromEng_P->insert(ccb_P->defData,bytesToRead))
3462
retVal = MSG_RTN_DATA_OVERFLOW;
3466
if (retVal != MSG_RTN_COMPLETED)
3468
flashAddr += bytesToRead;
3469
bytesRequested -= bytesToRead;
3479
//dptHBA_C::flashRead() - end
3482
//Function - dptHBA_C::flashStatus() - start
3483
//===========================================================================
3487
// This function inquires the status of the HBA's flash memory.
3488
//This status command does not require that the HBA be in flash
3491
//---------------------------------------------------------------------------
3493
DPT_RTN_T dptHBA_C::flashStatus(dptBuffer_S *fromEng_P)
3496
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3498
engCCB_C *ccb_P = getCCB();
3500
retVal = MSG_RTN_DATA_OVERFLOW;
3502
fromEng_P->insert(flashWriteCnt + flashRegionOffset);
3503
ccb_P->target(this);
3504
ccb_P->flashCmd(FLASH_CMD_STATUS);
3505
if (launchCCB(ccb_P) == MSG_RTN_COMPLETED) {
3507
fromEng_P->insert(fwStatus);
3508
dptFlashStatus_S *fstat_P = (dptFlashStatus_S *) ccb_P->defData;
3509
fstat_P->scsiSwap();
3510
if (fromEng_P->insert(ccb_P->defData,dptFlashStatus_S::size()))
3511
retVal = MSG_RTN_COMPLETED;
3513
else if (fromEng_P->insert(fwStatus))
3514
retVal = MSG_RTN_COMPLETED;
3525
//dptHBA_C::flashStatus() - end
3528
//Function - dptHBA_C::flashSwitchInto() - start
3529
//===========================================================================
3533
// This function attempts to switch the HBA into flash mode from
3536
//---------------------------------------------------------------------------
3538
DPT_RTN_T dptHBA_C::flashSwitchInto()
3541
DPT_RTN_T retVal = MSG_RTN_IGNORED;
3544
// If in operational mode...
3545
if (!isFlashMode()) {
3546
retVal = ERR_GET_CCB;
3547
engCCB_C *ccb_P = getCCB();
3548
if (ccb_P != NULL) {
3549
// Attempt to switch to flash mode
3550
switchToFlashMode(ccb_P);
3551
// If in flash mode...
3552
retVal = (isFlashMode()) ? MSG_RTN_COMPLETED : ERR_FLASH_SWITCH_MODES;
3562
//dptHBA_C::flashSwitchInto() - end
3565
//Function - dptHBA_C::flashSwitchOutOf() - start
3566
//===========================================================================
3570
// This function attempt to switch the firmware into operational
3571
//mode from flash mode. This function causes the firmware to perform
3574
// a "normal" switch to operational mode is attempted
3576
// a no-checksum switch is attempted for the purposes of
3577
// verifying the functionality newly burned firmware
3579
//---------------------------------------------------------------------------
3581
DPT_RTN_T dptHBA_C::flashSwitchOutOf(uINT skipChecksumTst)
3584
DPT_RTN_T retVal = MSG_RTN_IGNORED;
3586
// Determine how to switch out of flash mode
3587
uCHAR action = (skipChecksumTst) ? FLASH_CMD_TST_RESTART : FLASH_CMD_RESTART;
3590
DEBUG_BEGIN(1, dptHBA_C::flashSwitchOutOf());
3592
DEBUG(1, PRT_DADDR(this) << PRT_STAT);
3595
// If in flash mode...
3596
if (isFlashMode()) {
3597
retVal = ERR_GET_CCB;
3598
// Attempt to switch to operational mode
3599
engCCB_C *ccb_P = getCCB();
3601
ccb_P->target(this);
3602
ccb_P->flashCmd(action);
3603
retVal = launchCCB(ccb_P);
3605
// if we are testing the new flash code, give the F/W a few seconds to do thier
3606
// thing before we start "attacking" them
3607
if (action == FLASH_CMD_TST_RESTART)
3608
#if defined (_DPT_MSDOS) || defined (_DPT_UNIX)
3610
#elif defined (_DPT_WINNT)
3612
#elif defined (_DPT_OS2)
3615
if (retVal == MSG_RTN_COMPLETED)
3616
status.main = status.sub = 0;
3626
//dptHBA_C::flashSwitchOutOf() - end
3629
//Function - dptHBA_C::switchToFlashMode() - start
3630
//===========================================================================
3634
// This function tries to switch the firmware into flash mode.
3635
//In order to switch into flash mode all F/W level diagnostics and
3636
//all RAID builds, rebuilds, and verifies must be stopped, and all
3637
//dirty cache must be flushed. This command will fail if F/W cannot
3638
//switch for any of the reasons mentioned above.
3640
//---------------------------------------------------------------------------
3642
DPT_RTN_T dptHBA_C::switchToFlashMode(engCCB_C *ccb_P)
3646
DEBUG_BEGIN(1, dptHBA_C::switchToFlashMode());
3649
// Try to switch into flash mode
3651
ccb_P->target(this);
3652
ccb_P->flashCmd(FLASH_CMD_FLASH_MODE);
3653
DPT_RTN_T retVal = launchCCB(ccb_P);
3654
if (retVal == MSG_RTN_COMPLETED) {
3656
// sleep for 2 seconds to make sure the FW has dones thier init'ing.
3657
#if defined(_DPT_MSDOS) || defined (_DPT_UNIX)
3659
#elif defined (_DPT_WINNT)
3661
#elif defined (_DPT_OS2)
3664
for (uINT i=0;i<50;i++) {
3666
if (isFlashMode()) {
3668
#if defined(_DPT_MSDOS) || defined (_DPT_UNIX)
3670
#elif defined (_DPT_WINNT)
3672
#elif defined (_DPT_OS2)
3677
ccb_P->target(this);
3681
sdInquiry_S *inq_P = (sdInquiry_S *) ccb_P->defData;
3687
DEBUG(1, PRT_DADDR(this) << "flash in retVal=" << hex << retVal << \
3694
//dptHBA_C::switchToFlashMode() - end
3697
//Function - dptHBA_C::flashSetRegion() - start
3698
//===========================================================================
3704
//---------------------------------------------------------------------------
3706
DPT_RTN_T dptHBA_C::flashSetRegion(dptBuffer_S *toEng_P)
3709
DPT_RTN_T retVal = MSG_RTN_COMPLETED;
3710
uLONG RegionType = 0;
3711
uLONG BootFlags = 0;
3712
uLONG ActualSize = 0;
3713
uINT topAligned = 0;
3716
retVal = MSG_RTN_FAILED;
3719
toEng_P->extract(RegionType);
3720
toEng_P->extract(BootFlags);
3721
toEng_P->extract(ActualSize);
3723
uLONG flashSize = FLASH_REGION_NVRAM_OFFSET + 0x4000L;
3724
uLONG biosOffset = FLASH_REGION_BIOS_OFFSET;
3725
uLONG utilOffset = FLASH_REGION_UTILITY_OFFSET;
3727
// Determine if top or bottom aligned
3728
if (BootFlags & FW_LOAD_TOP) {
3732
engCCB_C *ccb_P = getCCB();
3734
DPTI_BootFlags = (uSHORT)BootFlags;
3735
// Get the flash status to help determine region sizes
3736
ccb_P->target(this);
3737
ccb_P->flashCmd(FLASH_CMD_STATUS);
3738
if (launchCCB(ccb_P) == MSG_RTN_COMPLETED) {
3739
dptFlashStatus_S *fstat_P = (dptFlashStatus_S *) ccb_P->defData;
3740
fstat_P->scsiSwap();
3741
flashSize = fstat_P->getFlashSize();
3742
biosOffset = fstat_P->getBurnSize();
3745
// Read the first 512 bytes of the BIOS region to determine the utility region offset
3746
utilOffset = biosOffset + 0x8000L; // default = BIOS offset + 32k
3748
ccb_P->target(this);
3749
ccb_P->flashCmd(FLASH_CMD_READ, biosOffset, 512);
3750
if (launchCCB(ccb_P) == MSG_RTN_COMPLETED) {
3751
if ((ccb_P->defData[0] == 0x55) && (ccb_P->defData[1] == 0xaa)) {
3752
utilOffset = ccb_P->defData[2];
3754
utilOffset += biosOffset;
3761
switch(RegionType) {
3762
case FLASH_REGION_FIRMWARE:
3763
flashRegionOffset = FLASH_REGION_FIRMWARE_OFFSET;
3764
if (topAligned && (biosOffset > ActualSize)) {
3765
flashRegionOffset = biosOffset - ActualSize; // burnSize - ActualSize
3768
case FLASH_REGION_BIOS:
3769
flashRegionOffset = biosOffset;
3771
case FLASH_REGION_UTILITY:
3772
flashRegionOffset = utilOffset;
3774
case FLASH_REGION_NVRAM:
3775
flashRegionOffset = flashSize - 0x4000L; // flash size - 16k
3777
case FLASH_REGION_SERIAL_NUM:
3778
flashRegionOffset = flashSize - 0x2000L; // flash size - 8k
3781
retVal = MSG_RTN_FAILED;
3789
//dptHBA_C::flashSetRegion() - end
3791
//Function - dptHBA_C::flashStablize() - start
3792
//===========================================================================
3794
//Description: the board is in flash mode, wait until we see the
3795
// bled code before going on
3802
//Global Variables Affected:
3804
//Remarks: (Side effects, Assumptions, Warnings...)
3807
//---------------------------------------------------------------------------
3808
void dptHBA_C::flashStablize()
3810
uSHORT LEDpattern = 0;
3812
if (!isI2O() && status.main == SMAIN_FLASH_MODE) {
3813
while((LEDpattern & 0x00ff) != 0x69)
3814
osdCheckBLED(getDrvrNum(),&LEDpattern);
3819
//Function - dptHBA_C::setDataField() - start
3820
//===========================================================================
3824
// This function sets the specified data field to the specified
3827
//---------------------------------------------------------------------------
3829
DPT_RTN_T dptHBA_C::setDataField(dptBuffer_S *toEng_P)
3832
DPT_RTN_T retVal = MSG_RTN_DATA_UNDERFLOW;
3833
uSHORT dataField,tempShort;
3835
// If a data field was specified...
3836
if (toEng_P->extract(dataField)) {
3837
switch (dataField) {
3838
case DF_RBLD_POLL_FREQ:
3839
if (toEng_P->extract(tempShort)) {
3840
rbldPollFreq = tempShort;
3841
retVal = updateLAPparams();
3844
case DF_RBLD_BOOT_CHECK:
3845
if (toEng_P->extract(tempShort)) {
3847
raidFlags |= FLG_RBLD_BOOT_CHECK;
3849
raidFlags &= ~FLG_RBLD_BOOT_CHECK;
3850
retVal = updateLAPparams();
3853
case DF_SPIN_DOWN_DELAY:
3854
if (toEng_P->extract(tempShort)) {
3855
spinDownDelay = tempShort;
3856
retVal = updateLAPparams();
3861
retVal = dptRAIDhba_C::setDataField(toEng_P);
3863
} // end switch (dataField)
3869
//dptHBA_C::setDataField() - end
3872
//Function - dptHBA_C::readNV_RAM() - start
3873
//===========================================================================
3877
// This function attempts to read the contents of the HBA's
3878
//non-volatile memory.
3880
//---------------------------------------------------------------------------
3882
DPT_RTN_T dptHBA_C::readNV_RAM(dptBuffer_S *fromEng_P)
3885
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3887
engCCB_C *ccb_P = getCCB();
3888
if (ccb_P != NULL) {
3889
// Attempt to read the contents of the NV RAM
3890
ccb_P->modeSense(0x2e);
3891
ccb_P->target(this);
3892
if ((retVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
3893
if (fromEng_P->insert(ccb_P->modeParam_P->getData(),128))
3894
retVal = MSG_RTN_COMPLETED;
3896
retVal = MSG_RTN_DATA_OVERFLOW;
3906
//dptHBA_C::readNV_RAM() - end
3909
//Function - dptHBA_C::writeNV_RAM() - start
3910
//===========================================================================
3914
// This function attempts to write the contents of the HBA's
3915
//non-volatile memory.
3917
//---------------------------------------------------------------------------
3919
DPT_RTN_T dptHBA_C::writeNV_RAM(dptBuffer_S *toEng_P)
3922
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
3924
engCCB_C *ccb_P = getCCB();
3925
if (ccb_P != NULL) {
3927
ccb_P->modeSelect(0x2e,128+2);
3928
ccb_P->target(this);
3929
retVal = MSG_RTN_DATA_UNDERFLOW;
3930
// Insert the data to be written to the NV RAM
3931
if (toEng_P->extract(ccb_P->modeParam_P->getData(),128)) {
3932
// Compute the checksum
3934
char *byte_P = (char *) ccb_P->modeParam_P->getData();
3935
for (uSHORT i=0;i<127;i++)
3936
checksum += *byte_P++;
3937
checksum = -checksum;
3938
ccb_P->modeParam_P->getData()[127] = checksum;
3939
retVal = launchCCB(ccb_P);
3948
//dptHBA_C::writeNV_RAM() - end
3951
//Function - dptHBA_C::quietBus() - start
3952
//===========================================================================
3956
// This function quiets the SCSI bus and optionally blinks the
3957
//LED of this device.
3959
//---------------------------------------------------------------------------
3961
DPT_RTN_T dptHBA_C::quietBus(dptBuffer_S *toEng_P)
3964
uSHORT blinkMode = 1;
3965
uCHAR modifier = 0x80;
3967
if (!toEng_P->extract(blinkMode))
3973
return (sendMFC(MFC_QUIET,modifier));
3976
//dptHBA_C::quietBus() - end
3979
//Function - dptHBA_C::updateLAPparams() - start
3980
//===========================================================================
3984
// This function overrides the dptManager_C::updateLAPparams()
3985
//function and updates the background priority via the extended
3986
//multifunction command if the dptManager_C found no RAID devices
3987
//to which to send the logical array page.
3989
//---------------------------------------------------------------------------
3991
DPT_RTN_T dptHBA_C::updateLAPparams()
3994
// Attempt to update all logical array page data
3995
DPT_RTN_T retVal = dptManager_C::updateLAPparams();
3997
// If the logical array page was not issued to at least 1 device
3998
if (retVal == (MSG_RTN_FAILED | ERR_NO_RAID_DEVICES))
3999
// Try to set the background priority via the multi-function cmd
4000
retVal = sendExtMFC(0x0b,0,0L,rbldAmount,(uCHAR)rbldFrequency);
4005
//dptHBA_C::updateLAPparams() - end
4008
//Function - dptHBA_C::setPhyMagicNums() - start
4009
//===========================================================================
4013
// This function attempts to set the RAID magic number of all
4014
//unarrayed physical DASD devices.
4015
//---------------------------------------------------------------------------
4016
void dptHBA_C::setPhyMagicNums()
4019
dptDevice_C *dev_P = (dptDevice_C *) logList.reset();
4021
// If an unarrayed physical DASD device with no magic number...
4022
if ((dev_P->getLevel()==2) && (dev_P->getObjType()==DPT_SCSI_DASD) &&
4023
!dev_P->isComponent() && !dev_P->isRemoveable() &&
4024
!dev_P->getMagicNum()) {
4026
// Attempt to set the physical device's magic number
4027
dev_P->setPhyMagicNum();
4030
dev_P = (dptDevice_C *) logList.next();
4035
//dptHBA_C::setPhyMagicNums() - end
4038
//Function - dptHBA_C::GetAccessRights - start
4039
//===========================================================================
4043
// This function attempts to get the HBA's access rights
4045
//---------------------------------------------------------------------------
4046
DPT_RTN_T dptHBA_C::GetAccessRights(dptBuffer_S *fromEng_P)
4048
DPT_RTN_T rtnVal = ERR_GET_CCB;
4050
engCCB_C *ccb_P = getCCB();
4054
ccb_P->target(this);
4056
// get the hba's portion of the rights
4057
ccb_P->modeSense(0x2d);
4060
if ((rtnVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
4062
dptMultiInitPage_S page;
4064
// copy the hba's poritons of the access rights
4065
memcpy(&page, ccb_P->modeParam_P->getData(), page.size());
4067
fromEng_P->insert(&page, page.size());
4069
// loop thru all the attached devices, we can look at the physical list
4070
// because the GetAccessRights function will get the RAID parent if any
4071
dptDevice_C *dev_P = (dptDevice_C *) phyList.reset();
4074
rtnVal = dev_P->GetAccessRights(fromEng_P);
4075
dev_P = (dptDevice_C *) phyList.next();
4082
//Function - dptHBA_C::setPhyMagicNums() - start
4083
//===========================================================================
4087
// This function attempts to set the RAID magic number of all
4088
//unarrayed physical DASD devices.
4089
//---------------------------------------------------------------------------
4090
DPT_RTN_T dptHBA_C::SetAccessRights(dptBuffer_S *fromEng_P, dptBuffer_S *toEng_P)
4092
DPT_RTN_T rtnVal = MSG_RTN_DATA_UNDERFLOW;
4095
dptMultiInitPage_S page;
4097
// makw sure we get the data we need
4098
if (toEng_P->extract(&page, page.size())) {
4099
if (toEng_P->writeIndex - toEng_P->readIndex >= dptMultiInitList_S::size() + 1) {
4100
toEng_P->extract(acquire);
4101
rtnVal = MSG_RTN_COMPLETED;
4105
engCCB_C *ccb_P = getCCB();
4109
ccb_P->target(this);
4111
// get the hba's portion of the rights
4112
ccb_P->modeSelect(0x2d, (uSHORT)(2+dptMultiInitPage_S::size()), (acquire >> 1) | 0x80);
4118
memcpy(ccb_P->modeParam_P->getData(), &page, page.size());
4121
if ((rtnVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
4123
// go thru the physical list setting the rights there, the arrays will
4124
// automatically be set as well
4125
dptDevice_C *dev_P = (dptDevice_C *) phyList.reset();
4129
toEng_P->skip(page.size());
4130
DPT_RTN_T devRtn = dev_P->SetAccessRights(fromEng_P, toEng_P);
4132
// a device returned an error, palce its tag in
4134
fromEng_P->insert(dev_P->tag());
4138
dev_P = (dptDevice_C *) phyList.next();
4142
rtnVal = ERR_GET_CCB;
4147
DPT_RTN_T dptHBA_C::GetEnvironInfo(dptBuffer_S *fromEng_P)
4149
DPT_RTN_T rtnVal = MSG_RTN_FAILED;
4150
dptHBAenviron_S info;
4153
//TODO: make something in the logger that make the following events "special" in that
4154
// it keeps track of the count and last triggered
4159
// for now, set it to 0xffffffff
4161
info.setHighTempCount(0xffffffff);
4162
info.setHighTempLast(0xffffffff);
4163
info.setVeryHighTempCount(0xffffffff);
4164
info.setVeryHighTempLast(0xffffffff);
4165
info.setLowVoltCount(0xffffffff);
4166
info.setLowVoltLast(0xffffffff);
4167
info.setHightVoltCount(0xffffffff);
4168
info.setHightVoltLast(0xffffffff);
4170
// this updates the temp and volt
4171
updateStatus(fromEng_P);
4174
if(currVoltage != 0xffff)
4175
info.setCurVolt(currVoltage);
4177
info.setCurVolt(0xffffffff);
4179
if(currTemperature != 0xffff)
4180
info.setCurTemp(currTemperature);
4182
info.setCurTemp(0xffffffff);
4184
// get the temp thresholds
4185
readNV_RAM(fromEng_P);
4186
dptNVRAM_S *nv_P = (dptNVRAM_S *) &fromEng_P->data;
4188
if (nv_P->getHighTemp())
4189
info.setHighTempThresh((uLONG) nv_P->getHighTemp());
4191
info.setHighTempThresh((uLONG) 46);
4193
if (nv_P->getVeryHighTemp())
4194
info.setVeryHighTempThresh((uLONG) nv_P->getVeryHighTemp());
4196
info.setVeryHighTempThresh((uLONG) 60);
4200
// give them the buffer
4201
if (fromEng_P->insert(&info, info.size()))
4202
rtnVal = MSG_RTN_COMPLETED;
4208
DPT_RTN_T dptHBA_C::SetEnvironInfo(dptBuffer_S *toEng_P)
4210
DPT_RTN_T rtnVal = MSG_RTN_FAILED;
4212
dptHBAenviron_S info;
4215
if (toEng_P->extract(&info, info.size())) {
4217
readNV_RAM(toEng_P);
4218
dptNVRAM_S *nv_P = (dptNVRAM_S *) &toEng_P->data;
4219
nv_P->setHighTemp((uCHAR)info.getHighTempThresh());
4220
nv_P->setVeryHighTemp((uCHAR)info.getHighTempThresh());
4221
rtnVal = writeNV_RAM(toEng_P);