~ubuntu-branches/ubuntu/intrepid/raidutils/intrepid

« back to all changes in this revision

Viewing changes to raideng/hba.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Barak Pearlmutter
  • Date: 2004-05-18 11:33:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040518113342-tyqavmso5q351xi2
Tags: upstream-0.0.4
ImportĀ upstreamĀ versionĀ 0.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1996-2004, Adaptec Corporation
 
2
 * All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 *
 
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.
 
15
 *
 
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.
 
27
 */
 
28
 
 
29
//File - HBA.CPP
 
30
//***************************************************************************
 
31
//
 
32
//Description:
 
33
//
 
34
//    This file contains function definitions for the dptHBA_C class.
 
35
//
 
36
//Author:       Doug Anderson
 
37
//Date:         4/8/93
 
38
//
 
39
//Editors:
 
40
//
 
41
//Remarks:
 
42
//
 
43
//
 
44
//***************************************************************************
 
45
 
 
46
#include        "allfiles.hpp"  // All engine include files
 
47
#include        "i2omsg.h"
 
48
#include        "i2obscsi.h"
 
49
#include        "i2odpt.h"
 
50
 
 
51
#ifdef _DPT_ERGO
 
52
extern "C" {
 
53
        #ifndef _DPT_SOLARIS
 
54
                void _Cdecl sleep( unsigned __seconds );
 
55
        #endif
 
56
}
 
57
#endif
 
58
#ifdef _DPT_UNIX
 
59
#include <unistd.h>     // sleep()
 
60
#endif
 
61
 
 
62
 
 
63
#include <time.h>
 
64
 
 
65
//TODO: remove
 
66
#include <stdio.h>
 
67
 
 
68
extern "C" {
 
69
#ifdef _DPT_NETWARE
 
70
 
 
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
 
73
 
 
74
unsigned short DPTI_BootFlags;
 
75
 
 
76
#else
 
77
 
 
78
extern unsigned short DPTI_BootFlags;
 
79
 
 
80
#endif
 
81
};
 
82
 
 
83
#if !defined _DPT_UNIX && !defined _DPT_NETWARE && !defined _DPT_DOS
 
84
extern "C" {
 
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);
 
88
}
 
89
#else
 
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);
 
93
#endif // _DPT_UNIX
 
94
 
 
95
//Function - dptHBA_C::passCCB() - start
 
96
//===========================================================================
 
97
//
 
98
//Description:
 
99
//
 
100
//    This function makes adjustments to the CCB and then passes
 
101
//the send CCB request up the attachment chain.
 
102
//
 
103
//Parameters:
 
104
//
 
105
//Return Value:
 
106
//
 
107
//Global Variables Affected:
 
108
//
 
109
//Remarks: (Side effects, Assumptions, Warnings...)
 
110
//
 
111
//
 
112
//---------------------------------------------------------------------------
 
113
 
 
114
DPT_RTN_T       dptHBA_C::passCCB(engCCB_C *ccb_P)
 
115
{
 
116
 
 
117
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_BLINK_LED_IO;
 
118
 
 
119
  // If the HBA is not in blink LED mode...
 
120
if (!isBlinkLED()) {
 
121
        // Set the nested FW drive bit
 
122
   ccb_P->setNFW();
 
123
 
 
124
        // If the command came from a physical device...
 
125
   if (ccb_P->isPhy() && !ccb_P->isNoEATAphys())
 
126
        // Set physical bit
 
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
 
131
         ccb_P->setFW();
 
132
   else if (ccb_P->isMgr())
 
133
        // Set the interpret bit
 
134
         ccb_P->setInterpret();
 
135
 
 
136
        // Always physical origin to the next level
 
137
   ccb_P->setPhy();
 
138
 
 
139
        // Send the CCB to the next level in the attachment chain
 
140
   retVal = myMgr_P()->passCCB(ccb_P);
 
141
}
 
142
 
 
143
return (retVal);
 
144
 
 
145
}
 
146
//dptHBA_C::passCCB() - end
 
147
 
 
148
 
 
149
//Function - dptHBA_C::findMyPhysicals() - start
 
150
//===========================================================================
 
151
//
 
152
//Description:
 
153
//
 
154
//    This function finds all physical SCSI devices attached to this HBA.
 
155
//
 
156
//---------------------------------------------------------------------------
 
157
 
 
158
uSHORT  dptHBA_C::findMyPhysicals()
 
159
{
 
160
 
 
161
   uSHORT               retVal = 0;
 
162
   uSHORT               foundDev,skipToNextID;
 
163
   engCCB_C             *ccb_P;
 
164
   sdInquiry_S          *inq_P;
 
165
   dptDevice_C          *newDev_P;
 
166
   uCHAR                qualifier;
 
167
   uCHAR                devType;
 
168
   dptSCSIbcd_C         *bcd_P = NULL;
 
169
   dptSCSIbcd_C         *newBCD_P = NULL;
 
170
   dptDevice_C          *prevDev_P = NULL;
 
171
 
 
172
  // If flash command mode or blink LED mode...
 
173
if (isFlashMode() || isBlinkLED())
 
174
   return (1);
 
175
 
 
176
  // Get a CCB
 
177
ccb_P = getCCB();
 
178
if (ccb_P!=NULL) {
 
179
        // Indicate a successful scan
 
180
   retVal = 1;
 
181
        // For all supported SCSI channels, ids, & luns
 
182
   for (phyRange.reset();!phyRange.maxedOut();phyRange.incBottomUp()) {
 
183
         skipToNextID = 0;
 
184
        // If a new SCSI ID...
 
185
         if (phyRange.cur().lun==0) {
 
186
           // If there was an object at the last SCSI ID
 
187
         if (prevDev_P!=NULL)
 
188
                 // Enter it into the physical device list
 
189
            enterPhy(prevDev_P);
 
190
           // There is no bridge controller
 
191
         bcd_P = NULL;
 
192
           // There is no previous object at this SCSI ID
 
193
         prevDev_P = NULL;
 
194
                }
 
195
         foundDev = 0;
 
196
         ccb_P->reInit();
 
197
        // Initialize the CCB for a SCSI Inquiry command
 
198
         ccb_P->inquiry();
 
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;
 
211
            else {
 
212
                  ccb_P->reInit();
 
213
                  ccb_P->reqSense();
 
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;
 
218
            }
 
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)) {
 
224
                        foundDev = 2;
 
225
                        devType = DPT_SCSI_DASD;
 
226
                  }
 
227
                  }
 
228
                 }
 
229
         }
 
230
           // If a selection timeout...
 
231
         else if (ccb_P->ctlrStatus == 1)
 
232
                 // Give other tasks a chance to run
 
233
            osdSwitchThreads();
 
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
 
241
         skipToNextID = 1;
 
242
         }
 
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;
 
249
 
 
250
                // If LUN not supported... *** Always check all luns ***
 
251
         //if (qualifier==0x3)
 
252
         //      skipToNextID = 1;
 
253
                // If a device is connected at this ID...
 
254
         //else if ((qualifier==0x00) || (qualifier==0x02)) {
 
255
 
 
256
         if ((qualifier==0x00) || (qualifier==0x02)) {
 
257
                        // Get the peripheral device type
 
258
                 devType = (inq_P->getPeripheral() & 0x1f);
 
259
                 foundDev = 1;
 
260
#if 0
 
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.
 
269
                if(devType == 3)
 
270
                {
 
271
                        ccb_P->reInit();
 
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();
 
276
                        // Data In
 
277
                        ccb_P->input();
 
278
                        // Set the physical bit
 
279
                        ccb_P->setPhysical();
 
280
 
 
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)
 
284
                                devType = 6;
 
285
                }
 
286
#endif
 
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;
 
291
 
 
292
            if (bcd_P == NULL) {
 
293
                 // If the device is attached to an NCR type RAID
 
294
                 // bridge controller...
 
295
                  if (isRAIDbcd())
 
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);
 
302
            }
 
303
         }
 
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...
 
308
            if (isRAIDbcd())
 
309
                 // Create an NCR type RAID bridge controller
 
310
                  newBCD_P = (dptSCSIbcd_C *) newObject(DPT_RAID_BCD);
 
311
            else
 
312
                 // Create a standard bridge controller
 
313
                  newBCD_P = (dptSCSIbcd_C *) newObject(DPT_SCSI_BCD);
 
314
         }
 
315
           // If a bridge controller has just been created...
 
316
         if (newBCD_P!=NULL) {
 
317
            bcd_P       = newBCD_P;
 
318
            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
 
324
            enterPhy(bcd_P);
 
325
                 // If there was a previous device at this SCSI ID...
 
326
            if (prevDev_P!=NULL) {
 
327
                 // Add to the BCD
 
328
                  bcd_P->enterFromHBA(prevDev_P);
 
329
                  prevDev_P = NULL;
 
330
            }
 
331
         }
 
332
         } // end if (rtnStatus == MSG_RTN_COMPLETED)
 
333
 
 
334
        // If a device was found...
 
335
         if (foundDev) {
 
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...
 
344
            if (bcd_P!=NULL)
 
345
                 // Add the new device to the BCD
 
346
                  bcd_P->enterFromHBA(newDev_P);
 
347
            else {
 
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)
 
355
 
 
356
         if (skipToNextID)
 
357
         phyRange.nextID();
 
358
 
 
359
   } // end for (phyRange)
 
360
        // If there was an object at the last SCSI ID
 
361
   if (prevDev_P!=NULL)
 
362
        // Enter it into the physical device list
 
363
         enterPhy(prevDev_P);
 
364
        // Free the CCB
 
365
   ccb_P->clrInUse();
 
366
} // end if (ccb_P!=NULL)
 
367
 
 
368
return (retVal);
 
369
 
 
370
}
 
371
//dptHBA_C::findMyPhysicals() - end
 
372
 
 
373
 
 
374
//Function - dptHBA_C::findMyLogicals() - start
 
375
//===========================================================================
 
376
//
 
377
//Description:
 
378
//
 
379
//    This function finds all FW logical devices associated with this HBA.
 
380
//
 
381
//Return Value:
 
382
//
 
383
//   1 = OK
 
384
//   0 = Failure
 
385
//
 
386
//---------------------------------------------------------------------------
 
387
 
 
388
uSHORT  dptHBA_C::findMyLogicals()
 
389
{
 
390
 
 
391
   uSHORT       retVal = 1;
 
392
 
 
393
  // If flash command mode or blink LED mode...
 
394
if (isFlashMode() || isBlinkLED())
 
395
   return (retVal);
 
396
 
 
397
  // If the HBA supports RAID...
 
398
if (isRAIDcapable()) {
 
399
   retVal = 0;
 
400
        // Get a CCB
 
401
   engCCB_C *ccb_P = getCCB();
 
402
   if (ccb_P!=NULL) {
 
403
         retVal = 1;
 
404
        // Initialize the CCB to do a log sense
 
405
         ccb_P->logSense(0x36);
 
406
        // Indicate that this is a RAID command
 
407
         ccb_P->setRAIDcmd();
 
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);
 
413
         }
 
414
 
 
415
        // Free the CCB
 
416
         ccb_P->clrInUse();
 
417
   } // end if (ccb_P!=NULL)
 
418
} // end if (isRAIDcapable())
 
419
 
 
420
  // Check for emulated drives
 
421
checkForEmul();
 
422
 
 
423
return (retVal);
 
424
 
 
425
}
 
426
//dptHBA_C::findMyLogicals() - end
 
427
 
 
428
 
 
429
//Function - dptHBA_C::isRAIDbcd() - start
 
430
//===========================================================================
 
431
//
 
432
//Description:
 
433
//
 
434
//    This routine checks to see if a device is attached to a hardware
 
435
//array.
 
436
//
 
437
//Parameters:
 
438
//
 
439
//Return Value:
 
440
//
 
441
//Global Variables Affected:
 
442
//
 
443
//Remarks: (Side effects, Assumptions, Warnings...)
 
444
//
 
445
// 1. This function is intended for use in the findPhysObjects() function.
 
446
//
 
447
//---------------------------------------------------------------------------
 
448
 
 
449
uSHORT  dptHBA_C::isRAIDbcd()
 
450
{
 
451
 
 
452
   uSHORT               retVal = 0;
 
453
   hwaHWdata_S          *bcdData_P;
 
454
 
 
455
  // Get a CCB
 
456
engCCB_C *ccb_P = getCCB();
 
457
if (ccb_P!=NULL) {
 
458
  // Initialize the EATA CP.......................
 
459
 
 
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 )
 
469
         retVal = 1;
 
470
   }
 
471
        // Free the CCB
 
472
   ccb_P->clrInUse();
 
473
}
 
474
 
 
475
return (retVal);
 
476
 
 
477
}
 
478
//dptHBA_C::isRAIDbcd() - end
 
479
 
 
480
 
 
481
//Function - dptHBA_C::findComponent() - start
 
482
//===========================================================================
 
483
//
 
484
//Description:
 
485
//
 
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
 
488
//the HBA's index #.
 
489
//
 
490
//Parameters:
 
491
//
 
492
//Return Value:
 
493
//
 
494
//Global Variables Affected:
 
495
//
 
496
//Remarks: (Side effects, Assumptions, Warnings...)
 
497
//
 
498
//
 
499
//---------------------------------------------------------------------------
 
500
 
 
501
dptDevice_C *   dptHBA_C::findComponent(dptAddr_S inAddr,uSHORT,uLONG inMagicNum, dptCoreList_C *)
 
502
{
 
503
 
 
504
   dptObject_C          *obj_P = NULL;
 
505
   dptDevice_C          *comp_P = NULL;
 
506
   dptSCSIbcd_C         *bcd_P = NULL;
 
507
 
 
508
  // Assume the component is attached to this HBA
 
509
inAddr.hba = getHBA();
 
510
 
 
511
  // If a magic # was specified...
 
512
if (inMagicNum)
 
513
        // Search for a device with a matching magic #
 
514
   obj_P = findMagicObject(phyList,inMagicNum);
 
515
else
 
516
        // Search for a device with a matching SCSI address
 
517
   obj_P = findObjectAt(phyList,inAddr);
 
518
 
 
519
  // If an object was found...
 
520
if (obj_P!=NULL) {
 
521
        // If a manager was found...
 
522
   if (obj_P->isManager())
 
523
         bcd_P = (dptSCSIbcd_C *) obj_P;
 
524
        // If a device was found...
 
525
   else
 
526
         comp_P = (dptDevice_C *) obj_P;
 
527
}
 
528
 
 
529
  // If no device was found...
 
530
if (comp_P==NULL) {
 
531
        // Create an absent device
 
532
   comp_P = (dptDevice_C *) newObject(DPT_SCSI_DASD);
 
533
   if (comp_P!=NULL) {
 
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);
 
543
         if (bcd_P!=NULL) {
 
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))
 
550
                    bcd_P = NULL;
 
551
         }
 
552
         } // end if (inAddr.lun!=0)
 
553
         if (bcd_P!=NULL)
 
554
           // Add the component to the sub-manager's logical list
 
555
         bcd_P->enterFromHBA(comp_P);
 
556
         else
 
557
           // Add the component to the HBA's physical list
 
558
                // if this call fails object will be deleted.
 
559
         if (enterPhy(comp_P))
 
560
                comp_P = NULL;
 
561
   } // end if (comp_P!=NULL)
 
562
} // end if (comp_P!=NULL)
 
563
 
 
564
return (comp_P);
 
565
 
 
566
}
 
567
//dptHBA_C::findComponent() - end
 
568
 
 
569
 
 
570
//Function - dptHBA_C::realInit() - start
 
571
//===========================================================================
 
572
//
 
573
//Description:
 
574
//
 
575
//    This function initializes a real HBA.
 
576
//
 
577
//Parameters:
 
578
//
 
579
//Return Value:
 
580
//
 
581
//Global Variables Affected:
 
582
//
 
583
//Remarks: (Side effects, Assumptions, Warnings...)
 
584
//
 
585
//
 
586
//---------------------------------------------------------------------------
 
587
 
 
588
void    dptHBA_C::realInit()
 
589
{
 
590
 
 
591
  // Get the hardware information
 
592
getHWinfo();
 
593
 
 
594
  // Get the info contained in NV RAM
 
595
getNVinfo();
 
596
 
 
597
  // Check for RAID response to RAID command
 
598
checkForRAID();
 
599
 
 
600
  // Get the event log control word
 
601
getEventCtl();
 
602
 
 
603
  // Read the drive size table
 
604
  // (If not supported pointer will remain NULL)
 
605
readDriveSizeTable();
 
606
/* DEBUG code
 
607
if (driveSizeTable_P != NULL) {
 
608
        dptBuffer_S *buff_P = dptBuffer_S::newBuffer(512);
 
609
        uLONG temp = 1;
 
610
        buff_P->insert(temp);
 
611
        temp = 3;
 
612
        buff_P->insert(temp);
 
613
        temp = 0x10000;
 
614
        buff_P->insert(temp);
 
615
        temp = 0x20000;
 
616
        buff_P->insert(temp);
 
617
        temp = 0x40000;
 
618
        buff_P->insert(temp);
 
619
        setArrayDriveSizeTable(buff_P);
 
620
        buff_P->reset();
 
621
        buff_P->clear();
 
622
        getArrayDriveSizeTable(buff_P);
 
623
        dptBuffer_S::delBuffer(buff_P);
 
624
}
 
625
*/
 
626
/* DEBUG code
 
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);
 
634
*/
 
635
 
 
636
}
 
637
//dptHBA_C::realInit() - end
 
638
 
 
639
 
 
640
//Function - dptHBA_C::getHWinfo() - start
 
641
//===========================================================================
 
642
//
 
643
//Description:
 
644
//
 
645
//    This function determines what hardware the HBA has.
 
646
//
 
647
//Parameters:
 
648
//
 
649
//Return Value:
 
650
//
 
651
//Global Variables Affected:
 
652
//
 
653
//Remarks: (Side effects, Assumptions, Warnings...)
 
654
//
 
655
//
 
656
//---------------------------------------------------------------------------
 
657
 
 
658
void    dptHBA_C::getHWinfo()
 
659
{
 
660
 
 
661
 
 
662
DEBUG_BEGIN(5, dptHBA_C::getHWinfo());
 
663
 
 
664
  // Get a CCB
 
665
engCCB_C *ccb_P = getCCB();
 
666
if (ccb_P!=NULL) {
 
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);
 
670
        // Target this HBA
 
671
        ccb_P->target(this);
 
672
        // Send the CCB to hardware
 
673
        if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
 
674
                uSHORT tempUShort = 0;
 
675
                raidDef_S *def_P;
 
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()) {
 
681
 
 
682
                                 // Check for a RAID Key Card & Cache Module
 
683
                                case 1:
 
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;
 
697
 
 
698
                                        if (ccb_P->log.length() >= 2) {
 
699
                                                irqNum &= ~0xff;
 
700
                                                irqNum |= ccb_P->log.data_P()[1];
 
701
                                        }
 
702
                                        break;
 
703
 
 
704
                                 // Get the firmware battery flags and memory parity error flag
 
705
                                case 2:
 
706
                                        fwFlags = ccb_P->log.data_P()[0];
 
707
                                        break;
 
708
 
 
709
                                 // Get the total controller memory
 
710
                                case 4:
 
711
                                        totalMem = getU4(ccb_P->log.data_P(),0);
 
712
                                        reverseBytes(totalMem);
 
713
                                        break;
 
714
 
 
715
                // Get the total controller memory
 
716
                                case 6:
 
717
                                        if(isI2O())
 
718
                                        {
 
719
                                                if (ccb_P->log.data_P()[1] & 0x01) {
 
720
                                                        raidSupport &= ~FLG_RAID_0;
 
721
                                                }
 
722
                                                if (ccb_P->log.data_P()[1] & 0x02) {
 
723
                                                        raidSupport &= ~FLG_RAID_1;
 
724
                                                }
 
725
                                                if (ccb_P->log.data_P()[1] & 0x04) {
 
726
                                                        raidSupport &= ~FLG_RAID_5;
 
727
                                                }
 
728
                                                if (ccb_P->log.data_P()[1] & 0x08) {
 
729
                                                        hbaFlags2 |= FLG_HBA_PREDICTIVE;
 
730
                                                }
 
731
                                        }
 
732
                                        break;
 
733
 
 
734
                                 // Get the Host to HBA bus information
 
735
                                case 7:
 
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;
 
751
                                        }
 
752
                                        hostBusInfo = ccb_P->log.data_P()[1];
 
753
                                        break;
 
754
 
 
755
                                 // Get the SCSI bus capabilities
 
756
                                case 8:
 
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;
 
761
                                        }
 
762
                                        if (ccb_P->log.data_P()[0] & 0x80) {
 
763
                                                flags |= FLG_HBA_DIFFERENTIAL;
 
764
                                                chanInfo[0].flags |= FLG_CHAN_DIFFERENTIAL;
 
765
                                        }
 
766
                                        if (ccb_P->log.data_P()[0] & 0x40) {
 
767
                                                flags |= FLG_HBA_WIDE_16;
 
768
                                                chanInfo[0].flags |= FLG_CHAN_WIDE_16;
 
769
                                                scsiBusSpeed <<= 1;
 
770
                                        }
 
771
                                        if (ccb_P->log.data_P()[0] & 0x20) {
 
772
                                                flags |= FLG_HBA_EXTERNAL;
 
773
                                                chanInfo[0].flags |= FLG_CHAN_EXTERNAL;
 
774
                                                scsiBusSpeed >>= 1;
 
775
                                        }
 
776
                                        if (ccb_P->log.data_P()[0] & 0x10) {
 
777
                                                hbaFlags2 |= FLG_HBA_ULTRA;
 
778
                                                chanInfo[0].flags |= FLG_CHAN_ULTRA;
 
779
                                        }
 
780
                                        chanInfo[0].scsiBusSpeed = scsiBusSpeed;
 
781
                                        break;
 
782
 
 
783
                                 // Get the attached modules
 
784
                                case 9:
 
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);
 
811
                                        }
 
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);
 
815
                                        }
 
816
                                        if (ccb_P->log.data_P()[3] & 0x08)
 
817
                                                hbaFlags2 |= FLG_HBA_SC4;
 
818
                                        break;
 
819
 
 
820
                                 // Get the attached memory modules/SIMMs
 
821
                                case 10:
 
822
                                        memBank[0] = ccb_P->log.data_P()[0];
 
823
                                        extMemBank[0] = ccb_P->log.data_P()[0] & 0x7f;
 
824
                                        if (memBank[0]!=0) {
 
825
                                                modules |= FLG_MOD_MEM_BANK0;
 
826
                                        }
 
827
                                        memBank[1] = ccb_P->log.data_P()[1];
 
828
                                        extMemBank[1] = ccb_P->log.data_P()[1] & 0x7f;
 
829
                                        if (memBank[1]!=0) {
 
830
                                                modules |= FLG_MOD_MEM_BANK1;
 
831
                                        }
 
832
                                        memBank[2] = ccb_P->log.data_P()[2];
 
833
                                        extMemBank[2] = ccb_P->log.data_P()[2] & 0x7f;
 
834
                                        if (memBank[2]!=0) {
 
835
                                                modules |= FLG_MOD_MEM_BANK2;
 
836
                                        }
 
837
                                        memBank[3] = ccb_P->log.data_P()[3];
 
838
                                        extMemBank[3] = ccb_P->log.data_P()[3] & 0x7f;
 
839
                                        if (memBank[3]!=0) {
 
840
                                                modules |= FLG_MOD_MEM_BANK3;
 
841
                                        }
 
842
 
 
843
                                        if (ccb_P->log.length() >= 0x0c) {
 
844
                                                tempUShort = getU2(ccb_P->log.data_P(), 4);
 
845
                                                #ifndef _DPT_BIG_ENDIAN
 
846
                                                        reverseBytes(tempUShort);
 
847
                                                #endif
 
848
                                                if (tempUShort) {
 
849
                                                        modules |= FLG_MOD_MEM_BANK0;
 
850
                                                        extMemBank[0] = tempUShort;
 
851
                                                }
 
852
 
 
853
                                                tempUShort = getU2(ccb_P->log.data_P(), 6);
 
854
                                                #ifndef _DPT_BIG_ENDIAN
 
855
                                                        reverseBytes(tempUShort);
 
856
                                                #endif
 
857
                                                if (tempUShort) {
 
858
                                                        modules |= FLG_MOD_MEM_BANK1;
 
859
                                                        extMemBank[1] = tempUShort;
 
860
                                                }
 
861
 
 
862
                                                tempUShort = getU2(ccb_P->log.data_P(), 8);
 
863
                                                #ifndef _DPT_BIG_ENDIAN
 
864
                                                        reverseBytes(tempUShort);
 
865
                                                #endif
 
866
                                                if (tempUShort) {
 
867
                                                        modules |= FLG_MOD_MEM_BANK2;
 
868
                                                        extMemBank[2] = tempUShort;
 
869
                                                }
 
870
 
 
871
                                                tempUShort = getU2(ccb_P->log.data_P(), 10);
 
872
                                                #ifndef _DPT_BIG_ENDIAN
 
873
                                                        reverseBytes(tempUShort);
 
874
                                                #endif
 
875
                                                if (tempUShort) {
 
876
                                                        modules |= FLG_MOD_MEM_BANK3;
 
877
                                                        extMemBank[3] = tempUShort;
 
878
                                                }
 
879
                                        }
 
880
                                        break;
 
881
 
 
882
                                 // Get the FW type
 
883
                                case 11:
 
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;
 
911
                                        // Firmware supports
 
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;
 
919
 
 
920
                                        if (ccb_P->log.data_P()[1] & 0x10)
 
921
                                                hbaFlags2 |= FLG_HBA_NO_ALARM;
 
922
 
 
923
                                        if (ccb_P->log.data_P()[1] & 0x20) {
 
924
                                                raidFlags |= FLG_SEG_64;
 
925
                                        }
 
926
 
 
927
                                        if (ccb_P->log.data_P()[1] & 0x40) {
 
928
                                                raidFlags |= FLG_SEG_SUPPORTED;
 
929
                                        }
 
930
 
 
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;
 
935
                                        break;
 
936
 
 
937
                                 // SmartRAID signals
 
938
                                case 12:
 
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;
 
942
                                        break;
 
943
 
 
944
                                 // Per channel info (including SmartRAID signals)
 
945
                                case 13:
 
946
                                        updateChannelInfo(&(ccb_P->log));
 
947
                                        break;
 
948
 
 
949
                                case 14:
 
950
                                        maxArrays = (uSHORT) ccb_P->log.data_P()[0];
 
951
                                        def_P = getRAIDtdef(0);
 
952
                                        if (def_P != NULL)
 
953
                                                def_P->maxDrives = (uSHORT) ccb_P->log.data_P()[1];
 
954
                                        def_P = getRAIDtdef(3);
 
955
                                        if (def_P != NULL)
 
956
                                                def_P->maxDrives = (uSHORT) ccb_P->log.data_P()[2];
 
957
                                        def_P = getRAIDtdef(5);
 
958
                                        if (def_P != NULL) {
 
959
                                                def_P->maxDrives = (uSHORT) ccb_P->log.data_P()[2];
 
960
                                        }
 
961
 
 
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];
 
965
                                        }
 
966
 
 
967
 
 
968
                                        maxRaidComponents = (uSHORT) ccb_P->log.data_P()[2];
 
969
 
 
970
                                        if (ccb_P->log.length() >= 0x18) {
 
971
                                                maxMajorStripe = getU2(ccb_P->log.data_P(), 22);
 
972
                                                #ifndef _DPT_BIG_ENDIAN
 
973
                                                        reverseBytes(maxMajorStripe);
 
974
                                                #endif
 
975
                                        }
 
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);
 
982
                                                #endif
 
983
                                        }
 
984
 
 
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]);
 
989
                                        break;
 
990
 
 
991
                                 // Background task exclusion period
 
992
                                case 15:
 
993
                                        excludeStart = ccb_P->log.data_P()[0];
 
994
                                        excludeEnd = ccb_P->log.data_P()[1];
 
995
 
 
996
                                        // exclusion period stuff
 
997
                                        DEBUG(5, "HBA " << PRT_ADDR << "excludeStart=" << \
 
998
                                         (int)excludeStart << " excludeEnd=" <<  (int)excludeEnd);
 
999
 
 
1000
                                        break;
 
1001
 
 
1002
                        } // end switch()
 
1003
                        // Get the next log parameter
 
1004
                        ccb_P->log.next();
 
1005
                } // end while()
 
1006
        } // end if (launchCCB()==MSG_RTN_COMPLETED)
 
1007
 
 
1008
        // Free the CCB
 
1009
        ccb_P->clrInUse();
 
1010
} // end if (ccb_P!=NULL)
 
1011
 
 
1012
 
 
1013
}
 
1014
//dptHBA_C::getHWinfo() - end
 
1015
 
 
1016
 
 
1017
//Function - dptHBA_C::getNVinfo() - start
 
1018
//===========================================================================
 
1019
//Description:
 
1020
//    This function reads NV information and sets HBA info accordingly.
 
1021
//---------------------------------------------------------------------------
 
1022
 
 
1023
void    dptHBA_C::getNVinfo()
 
1024
{
 
1025
 
 
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;
 
1035
                }
 
1036
                // If wolfpack cluster mode...
 
1037
                if (ccb_P->modeParam_P->getData()[0x30] & 0x08) {
 
1038
                        hbaFlags2 |= FLG_HBA_CLUSTER_MODE;
 
1039
                }
 
1040
        }
 
1041
 
 
1042
        // Free the CCB
 
1043
        ccb_P->clrInUse();
 
1044
}
 
1045
 
 
1046
}
 
1047
//dptHBA_C::getNVinfo() - end
 
1048
 
 
1049
 
 
1050
//Function - dptHBA_C::updateChannelInfo() - start
 
1051
//===========================================================================
 
1052
//
 
1053
//Description:
 
1054
//
 
1055
//    This function updates the specified SCSI channel info.
 
1056
//
 
1057
//---------------------------------------------------------------------------
 
1058
 
 
1059
void    dptHBA_C::updateChannelInfo(dptSCSIlog_C *log)
 
1060
{  
 
1061
        // Get the length of the log parameter                 
 
1062
        uCHAR length = log->length();
 
1063
 
 
1064
        uCHAR *data_P = log->data_P();
 
1065
 
 
1066
        uSHORT chanIndex = (uSHORT) (*data_P & 0x7);
 
1067
        if (chanIndex < MAX_NUM_CHANS) {
 
1068
                if (chanIndex > phyRange.getMaxChan())
 
1069
                        phyRange.setMaxChan((uCHAR)chanIndex);
 
1070
 
 
1071
                // Set the channels flags
 
1072
                chanInfo[chanIndex].flags = *(data_P+1);
 
1073
                // If there is another byte of flags, get it
 
1074
                if(length > 2)
 
1075
                        chanInfo[chanIndex].flags += (*(data_P+2) << 8);
 
1076
                // If the channel info has SCAM info, get it
 
1077
                if(length > 4)
 
1078
                {
 
1079
                        chanInfo[chanIndex].scamIdMap = *(data_P+4) << 8;
 
1080
                        chanInfo[chanIndex].scamIdMap += *(data_P+5);
 
1081
                }
 
1082
                // Make the invalid subsystem status flag a valid flag
 
1083
                chanInfo[chanIndex].flags ^= FLG_CHAN_SUBSYS_VALID;
 
1084
 
 
1085
                // If ultra 80
 
1086
                if (chanInfo[chanIndex].flags & FLG_CHAN_ULTRA_80)
 
1087
                        // Set the bus speed
 
1088
                        chanInfo[chanIndex].scsiBusSpeed = 80;
 
1089
                // If ultra 
 
1090
                else if (chanInfo[chanIndex].flags & FLG_CHAN_ULTRA_40)
 
1091
                        // Set the bus speed
 
1092
                        chanInfo[chanIndex].scsiBusSpeed = 40;
 
1093
                // If ultra 40
 
1094
                else if (chanInfo[chanIndex].flags & FLG_CHAN_ULTRA)
 
1095
                        // Set the bus speed
 
1096
                        chanInfo[chanIndex].scsiBusSpeed = 20;
 
1097
                else
 
1098
                        // Initialize the SCSI bus speed
 
1099
                        chanInfo[chanIndex].scsiBusSpeed = 10;
 
1100
 
 
1101
 
 
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);
 
1108
                }
 
1109
 
 
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;
 
1114
 
 
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;
 
1119
                }
 
1120
 
 
1121
                if (chanIndex == 0)
 
1122
                        scsiBusSpeed = chanInfo[chanIndex].scsiBusSpeed;
 
1123
 
 
1124
                // get the SCSI ID of the HBA for this channel
 
1125
                engCCB_C *ccb_P = getCCB();
 
1126
                if(ccb_P) {
 
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) {
 
1131
                                if (ccb_P->ok()) {
 
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];
 
1135
                                }
 
1136
                        }
 
1137
                        // Free the CCB
 
1138
                        ccb_P->clrInUse();
 
1139
                }
 
1140
        }
 
1141
}
 
1142
//dptHBA_C::updateChannelInfo() - end
 
1143
 
 
1144
 
 
1145
//Function - dptHBA_C::checkForRAID() - start
 
1146
//===========================================================================
 
1147
//
 
1148
//Description:
 
1149
//
 
1150
//    This function checks to see if the HBA responds to RAID commands.
 
1151
//
 
1152
//Parameters:
 
1153
//
 
1154
//Return Value:
 
1155
//
 
1156
//Global Variables Affected:
 
1157
//
 
1158
//Remarks: (Side effects, Assumptions, Warnings...)
 
1159
//
 
1160
//
 
1161
//---------------------------------------------------------------------------
 
1162
 
 
1163
void    dptHBA_C::checkForRAID()
 
1164
{
 
1165
 
 
1166
  // Clear the FW RAID support flag
 
1167
flags   &= ~FLG_HBA_RAID_FW;
 
1168
 
 
1169
  // If a RAID module && a cache module or an I2O HBA...
 
1170
if ((isRAIDmodule() && is512kCache()) || isI2O()) {
 
1171
   engCCB_C *ccb_P = getCCB();
 
1172
   if (ccb_P!=NULL) {
 
1173
        if (isI2O())
 
1174
                  // Set the FW RAID support flag
 
1175
                flags |= FLG_HBA_RAID_FW;
 
1176
        else {
 
1177
                // Initialize the CCB to get the physical array page
 
1178
                 ccb_P->modeSense(0x2a);
 
1179
                // Target this HBA
 
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;
 
1189
                 }
 
1190
         }
 
1191
 
 
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)
 
1195
                lapPage = LAP_DPT2;
 
1196
        // if this is the special SNI version of FW use LAP 1
 
1197
        else if (memcmp(descr.revision, "0UX2", 4) == 0)
 
1198
                lapPage = LAP_DPT1;
 
1199
        // its <= 7c0 use lap1
 
1200
        else
 
1201
                lapPage = LAP_DPT1;
 
1202
 
 
1203
        // Re-initialize the CCB
 
1204
         ccb_P->reInit();
 
1205
        // Initialize the CCB to perform a SCSI inquiry
 
1206
         ccb_P->inquiry(0xc0);
 
1207
        // Target this HBA
 
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)
 
1216
                  raidDefList.del();
 
1217
         }
 
1218
         }
 
1219
 
 
1220
        // Free the CCB
 
1221
         ccb_P->clrInUse();
 
1222
   }
 
1223
}
 
1224
 
 
1225
}
 
1226
//dptHBA_C::checkForRAID() - end
 
1227
 
 
1228
 
 
1229
//Function - dptHBA_C::handleMessage() - start
 
1230
//===========================================================================
 
1231
//
 
1232
//Description:
 
1233
//
 
1234
//    This routine handles DPT events for the dptRAIDmgr_C class.
 
1235
//
 
1236
//Parameters:
 
1237
//
 
1238
//Return Value:
 
1239
//
 
1240
//Global Variables Affected:
 
1241
//
 
1242
//Remarks: (Side effects, Assumptions, Warnings...)
 
1243
//
 
1244
//
 
1245
//---------------------------------------------------------------------------
 
1246
 
 
1247
DPT_RTN_T       dptHBA_C::handleMessage(DPT_MSG_T   message,
 
1248
                                                                                dptBuffer_S *fromEng_P,
 
1249
                                                                                dptBuffer_S *toEng_P
 
1250
                                                                           )
 
1251
{
 
1252
 
 
1253
        DPT_RTN_T    retVal = MSG_RTN_IGNORED;
 
1254
 
 
1255
        switch (message) {
 
1256
 
 
1257
                // Turns the HBA's alarm on
 
1258
                case MSG_ALARM_ON:
 
1259
                        if (isRAIDmodule())
 
1260
                                retVal = sendMFC(MFC_ALARM_ON);
 
1261
                        break;
 
1262
 
 
1263
                // Turns the HBA's alarm off
 
1264
                case MSG_ALARM_OFF:
 
1265
                        if (isRAIDmodule())
 
1266
                                retVal = sendMFC(MFC_ALARM_OFF);
 
1267
                        break;
 
1268
 
 
1269
                // Stops all activity on this HBA so that a physical device may
 
1270
                // be changed.
 
1271
                case MSG_QUIET:
 
1272
                        retVal = quietBus(toEng_P);
 
1273
                        break;
 
1274
 
 
1275
                // Resumes activity on this HBA after a quiet command has been issued
 
1276
                case MSG_UNQUIET:
 
1277
                        retVal = sendMFC(MFC_UNQUIET);
 
1278
                        break;
 
1279
 
 
1280
                // Re-reads the RAID tables on the drives and configures the system
 
1281
                // accordingly.
 
1282
                case MSG_RELOCK_DRIVES:
 
1283
                        retVal = sendMFC(MFC_READ_RAID_TBL);
 
1284
                        break;
 
1285
 
 
1286
                // Update the HBA's status
 
1287
                case MSG_UPDATE_STATUS:
 
1288
                        retVal = updateStatus(fromEng_P);
 
1289
                        break;
 
1290
 
 
1291
                // Get the HBA's time
 
1292
                case MSG_GET_TIME:
 
1293
                        retVal = getTime(fromEng_P);
 
1294
                        break;
 
1295
 
 
1296
                // Set the HBA's time
 
1297
                case MSG_SET_TIME:
 
1298
                        retVal = setTime(toEng_P);
 
1299
                        break;
 
1300
 
 
1301
                // Return the HBA's event log
 
1302
                case MSG_LOG_READ:
 
1303
                        retVal = rtnEventLog(toEng_P,fromEng_P);
 
1304
                        break;
 
1305
 
 
1306
                // Clear the HBA event log
 
1307
                case MSG_LOG_CLEAR:
 
1308
                        retVal = clearEventLog();
 
1309
                        break;
 
1310
 
 
1311
                // Set the HBA event log control word
 
1312
                case MSG_LOG_SET_HBA_FILTER:
 
1313
                        retVal = setEventCtl(toEng_P);
 
1314
                        break;
 
1315
 
 
1316
                // Return global HBA read/write statistics information
 
1317
                case MSG_GET_IO_STATS:
 
1318
                        retVal = rtnIOstats(fromEng_P,1);
 
1319
                        break;
 
1320
 
 
1321
                // Clear global HBA read/write statistics information
 
1322
                case MSG_CLEAR_IO_STATS:
 
1323
                        retVal = rtnIOstats(NULL,0);
 
1324
                        break;
 
1325
 
 
1326
                // Return HBA specific statistics information
 
1327
                case MSG_GET_HBA_STATS:
 
1328
                        retVal = rtnHBAstats(fromEng_P,1);
 
1329
                        break;
 
1330
 
 
1331
                // Clear HBA specific statistics information
 
1332
                case MSG_CLEAR_HBA_STATS:
 
1333
                        retVal = rtnHBAstats(NULL,0);
 
1334
                        break;
 
1335
 
 
1336
                // Set an HBA data field to a specified value
 
1337
                case MSG_SET_INFO:
 
1338
                        retVal = setDataField(toEng_P);
 
1339
                        break;
 
1340
 
 
1341
                // Return the contents of the HBA's NV RAM
 
1342
                case MSG_GET_NV_INFO:
 
1343
                        retVal = readNV_RAM(fromEng_P);
 
1344
                        break;
 
1345
 
 
1346
                // Write the contents of the HBA's NV RAM
 
1347
                case MSG_SET_NV_INFO:
 
1348
                        retVal = writeNV_RAM(toEng_P);
 
1349
                        break;
 
1350
 
 
1351
                // Attempts to switch from operational mode into flash mode
 
1352
                case MSG_FLASH_SWITCH_INTO:
 
1353
                        retVal = flashSwitchInto();
 
1354
                        break;
 
1355
 
 
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);
 
1362
                        else
 
1363
                                // Perform the flash checksum test
 
1364
                                retVal = flashSwitchOutOf(0);
 
1365
                        break;
 
1366
 
 
1367
                // Writes to the HBA's flash memory
 
1368
                case MSG_FLASH_WRITE:
 
1369
                        retVal = flashWrite(toEng_P);
 
1370
                        break;
 
1371
 
 
1372
                // Writes to the HBA's flash memory without verification
 
1373
                case MSG_FLASH_WR_NO_VERIFY:
 
1374
                        retVal = flashWrite(toEng_P,0);
 
1375
                        break;
 
1376
 
 
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);
 
1382
                        else
 
1383
                                retVal = flashWriteDone(1);
 
1384
                        break;
 
1385
 
 
1386
                // Reads from the HBA's flash memory
 
1387
                case MSG_FLASH_READ:
 
1388
                        retVal = flashRead(toEng_P,fromEng_P);
 
1389
                        break;
 
1390
 
 
1391
                // Returns detailed status information about the HBA's flash memory
 
1392
                case MSG_FLASH_STATUS:
 
1393
                        retVal = flashStatus(fromEng_P);
 
1394
                        break;
 
1395
 
 
1396
                // Sets the region offset to be flashed
 
1397
                case MSG_FLASH_SET_REGION:
 
1398
                        retVal = flashSetRegion(toEng_P);
 
1399
                        break;
 
1400
 
 
1401
 
 
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);
 
1407
                        break;
 
1408
 
 
1409
                // Return the HBA's array limits
 
1410
                case MSG_RAID_GET_LIMITS:
 
1411
                        retVal = getArrayLimits(fromEng_P);
 
1412
                        break;
 
1413
 
 
1414
                //dz
 
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,
 
1421
                                                                  (void*)toEng_P,
 
1422
                                                                  (dptData_S*)fromEng_P,
 
1423
                                                                  (uSHORT)myConn_P()->getIOmethod(),
 
1424
                                                                  0,
 
1425
                                                                  (uLONG)getRAIDid());
 
1426
                        break;
 
1427
 
 
1428
                case MSG_SET_ACCESS_RIGHTS:
 
1429
                        retVal = SetAccessRights(fromEng_P, toEng_P);
 
1430
                        break;
 
1431
 
 
1432
                case MSG_GET_ACCESS_RIGHTS:
 
1433
                        retVal = GetAccessRights(fromEng_P);
 
1434
                        break;
 
1435
 
 
1436
                case MSG_GET_ENVIRON_INFO:
 
1437
                        retVal = GetEnvironInfo(fromEng_P);
 
1438
                        break;
 
1439
 
 
1440
                case MSG_SET_ENVIRON_INFO:
 
1441
                        retVal = SetEnvironInfo(toEng_P);
 
1442
                        break;
 
1443
 
 
1444
                // Get backup battery info
 
1445
                case MSG_GET_BATTERY_INFO:
 
1446
                        retVal = getBatteryInfo(toEng_P, fromEng_P);
 
1447
                        break;
 
1448
 
 
1449
                // Set backup battery thresholds
 
1450
                case MSG_SET_BATTERY_THRESHOLDS:
 
1451
                        retVal = setBatteryThresholds(toEng_P);
 
1452
                        break;
 
1453
 
 
1454
                // Calibrate the backup battery
 
1455
                case MSG_CALIBRATE_BATTERY:
 
1456
                        retVal = calibrateBattery(toEng_P);
 
1457
                        break;
 
1458
 
 
1459
                // Perform a DMA test on the controller
 
1460
                case MSG_I2O_DMA_TEST:
 
1461
                        retVal = i2oDiagTest(toEng_P,fromEng_P, 0x07);
 
1462
                        break;
 
1463
 
 
1464
                // Perform a RAM test on the controller
 
1465
                case MSG_I2O_RAM_TEST:
 
1466
                        retVal = i2oDiagTest(toEng_P,fromEng_P, 0x06);
 
1467
                        break;
 
1468
 
 
1469
                // Initiate the controller's built-in-self-test
 
1470
                case MSG_I2O_BIST:
 
1471
                        retVal = i2oDiagTest(toEng_P,fromEng_P, 0x08);
 
1472
                        break;
 
1473
 
 
1474
                // Initialize the device busy logic
 
1475
                case MSG_CHECK_BUSY:
 
1476
                        retVal = initBusyLogic(fromEng_P);
 
1477
                        break;
 
1478
 
 
1479
                // Set the array drive size table
 
1480
                case MSG_SET_ARRAY_DRIVE_SIZES:
 
1481
                        retVal = setArrayDriveSizeTable(toEng_P);
 
1482
                        break;
 
1483
 
 
1484
                // Return the array drive size table
 
1485
                case MSG_GET_ARRAY_DRIVE_SIZES:
 
1486
                        retVal = getArrayDriveSizeTable(fromEng_P);
 
1487
                        break;
 
1488
 
 
1489
                // Return the array drive size table
 
1490
                case MSG_I2O_RESYNC:
 
1491
                        retVal = resetHba(toEng_P);
 
1492
                        break;
 
1493
 
 
1494
                // Send an I2O pass-through message
 
1495
                case MSG_I2O_SEND_MESSAGE:
 
1496
                        retVal = sendI2OMessage(fromEng_P, toEng_P);
 
1497
                        break;
 
1498
 
 
1499
                // Return detailed channel information
 
1500
                case MSG_GET_CHAN_INFO:
 
1501
                        retVal = getChanInfo(fromEng_P);
 
1502
                        break;
 
1503
 
 
1504
                default:
 
1505
                        // Call base class event handler
 
1506
                        retVal = dptRAIDhba_C::handleMessage(message,fromEng_P,toEng_P);
 
1507
                        break;
 
1508
 
 
1509
        } // end switch
 
1510
 
 
1511
return (retVal);
 
1512
 
 
1513
}
 
1514
//dptHBA_C::handleMessage() - end
 
1515
 
 
1516
 
 
1517
//Function - dptHBA_C::getChanInfo() - start
 
1518
//===========================================================================
 
1519
//   This function returns detailed information about each I/O channel/
 
1520
//---------------------------------------------------------------------------
 
1521
 
 
1522
DPT_RTN_T       dptHBA_C::getChanInfo(dptBuffer_S *fromEng_P)
 
1523
{
 
1524
 
 
1525
        DPT_RTN_T               retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
1526
 
 
1527
  // Get a CCB
 
1528
engCCB_C *ccb_P = getCCB();
 
1529
if (ccb_P!=NULL) {
 
1530
 
 
1531
        uCHAR   hbaId_A[4];
 
1532
        dptChanInfo2_S  rtnInfo;
 
1533
 
 
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];
 
1543
 
 
1544
 
 
1545
                ccb_P->reInit();
 
1546
 
 
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);
 
1555
 
 
1556
                        ccb_P->initLogSense();
 
1557
                        while (ccb_P->log.isValidParam()) {
 
1558
                                if (ccb_P->log.code() == 0x0d) {
 
1559
                                        numChannels++;
 
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];
 
1571
                                        }
 
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;
 
1577
                                                }
 
1578
                                                else if (rtnInfo.pc13Flags4 & FLG_CHAN2_ULTR160) {
 
1579
                                                        rtnInfo.maxXfrSpeed = 320;
 
1580
                                                }
 
1581
                                        }
 
1582
 
 
1583
                                        if (!fromEng_P->insert(&rtnInfo, sizeof(dptChanInfo2_S))) {
 
1584
                                                retVal = MSG_RTN_DATA_OVERFLOW;
 
1585
                                        }
 
1586
                                }
 
1587
                                // Get the next log parameter
 
1588
                                ccb_P->log.next();
 
1589
                        }
 
1590
 
 
1591
                        *numChannels_P = numChannels;
 
1592
                }
 
1593
        } // end if (launchCCB())
 
1594
 
 
1595
 
 
1596
        // Free the CCB
 
1597
   ccb_P->clrInUse();
 
1598
} // end if (ccb_P!=NULL)
 
1599
 
 
1600
return(retVal);
 
1601
 
 
1602
}
 
1603
//dptHBA_C::getChanInfo() - end
 
1604
 
 
1605
 
 
1606
//Function - dptHBA_C::resetHba() - start
 
1607
//===========================================================================
 
1608
//Description:
 
1609
//   This function attempts to reset the HBA
 
1610
//---------------------------------------------------------------------------
 
1611
 
 
1612
DPT_RTN_T dptHBA_C::sendI2OMessage(dptBuffer_S *fromEng_P, dptBuffer_S *toEng_P)
 
1613
{
 
1614
 
 
1615
        DPT_RTN_T       retVal = MSG_RTN_IGNORED;
 
1616
 
 
1617
        //fromEng_P->data
 
1618
        //toEng_P->data
 
1619
 
 
1620
        return retVal;
 
1621
}
 
1622
//dptHBA_C::sendI2OMessage() - end
 
1623
 
 
1624
 
 
1625
//Function - dptHBA_C::resetHba() - start
 
1626
//===========================================================================
 
1627
//Description:
 
1628
//   This function attempts to reset the HBA
 
1629
//---------------------------------------------------------------------------
 
1630
 
 
1631
DPT_RTN_T dptHBA_C::resetHba(dptBuffer_S *toEng_P)
 
1632
{
 
1633
 
 
1634
        DPT_RTN_T       retVal = MSG_RTN_IGNORED;
 
1635
 
 
1636
        if (isI2O()) {
 
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) {
 
1642
                                  // Get a CCB
 
1643
                                engCCB_C *ccb_P = getCCB();
 
1644
                                if (ccb_P==NULL)
 
1645
                                        retVal = ERR_GET_CCB;
 
1646
                                else {
 
1647
 
 
1648
                                        // Get the inquiry data
 
1649
                                        ccb_P->inquiry();
 
1650
                                        ccb_P->target(this);
 
1651
                                        if (launchCCB(ccb_P)==MSG_RTN_COMPLETED) {
 
1652
                                                inquiryInit((sdInquiry_S *)ccb_P->defData);
 
1653
                                        }
 
1654
                                        ccb_P->clrInUse();
 
1655
 
 
1656
                                        // Get the H/W page etc.
 
1657
                                        realInit();
 
1658
                                }
 
1659
                        }
 
1660
                }
 
1661
        }
 
1662
 
 
1663
        return (retVal);
 
1664
 
 
1665
}
 
1666
//dptHBA_C::resetHba()
 
1667
 
 
1668
 
 
1669
//Function - dptHBA_C::setArrayDriveSizeTable() - start
 
1670
//===========================================================================
 
1671
//Description:
 
1672
//   This function sets the array drive size table.
 
1673
//---------------------------------------------------------------------------
 
1674
 
 
1675
DPT_RTN_T dptHBA_C::setArrayDriveSizeTable(dptBuffer_S *toEng_P)
 
1676
{
 
1677
 
 
1678
 
 
1679
DPT_RTN_T       retVal = MSG_RTN_COMPLETED;
 
1680
uLONG           saveTable = 0;
 
1681
uLONG           numEntries = 0;
 
1682
 
 
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;
 
1690
else {
 
1691
        if (driveSizeTable_P != NULL) {
 
1692
                if (numEntries > driveSizeTable_P->getMaxEntries()) {
 
1693
                        retVal = ERR_DRIVE_SIZE_TABLE_MAX;
 
1694
                }
 
1695
        }
 
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());
 
1700
                }
 
1701
                else {
 
1702
                        ds_P->setMaxEntries(MAX_DRIVE_SIZE_ENTRIES);
 
1703
                }
 
1704
                useDriveSizeTable(ds_P);
 
1705
                if (saveTable) {
 
1706
                        retVal = writeDriveSizeTable();
 
1707
                }
 
1708
        }
 
1709
}
 
1710
 
 
1711
return (retVal);
 
1712
 
 
1713
}
 
1714
//dptHBA_C::setArrayDriveSizeTable()
 
1715
 
 
1716
 
 
1717
//Function - dptHBA_C::getArrayDriveSizeTable() - start
 
1718
//===========================================================================
 
1719
//Description:
 
1720
//   This function returns the array drive size table.
 
1721
//---------------------------------------------------------------------------
 
1722
 
 
1723
DPT_RTN_T dptHBA_C::getArrayDriveSizeTable(dptBuffer_S *fromEng_P)
 
1724
{
 
1725
 
 
1726
 
 
1727
DPT_RTN_T       retVal = MSG_RTN_COMPLETED;
 
1728
uLONG           maxEntries = 0;
 
1729
uLONG           numEntries = 0;
 
1730
 
 
1731
if (driveSizeTable_P == NULL) {
 
1732
        fromEng_P->insert(maxEntries);
 
1733
        if (!fromEng_P->insert(numEntries)) {
 
1734
                retVal = MSG_RTN_DATA_OVERFLOW;
 
1735
        }
 
1736
}
 
1737
else {
 
1738
        if (!fromEng_P->insert(driveSizeTable_P, 8+(driveSizeTable_P->getNumEntries()<<2))) {
 
1739
                retVal = MSG_RTN_DATA_OVERFLOW;
 
1740
        }
 
1741
}
 
1742
 
 
1743
return (retVal);
 
1744
 
 
1745
}
 
1746
//dptHBA_C::getArrayDriveSizeTable()
 
1747
 
 
1748
 
 
1749
//Function - dptHBA_C::initBusyLogic() - start
 
1750
//===========================================================================
 
1751
//Description:
 
1752
//   This function initializes the device busy checking code.
 
1753
//---------------------------------------------------------------------------
 
1754
 
 
1755
DPT_RTN_T dptHBA_C::initBusyLogic(dptBuffer_S *fromEng_P)
 
1756
{
 
1757
 
 
1758
 
 
1759
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
1760
 
 
1761
uLONG busyStatus = osdTargetBusy(0, 0, 0, 0);
 
1762
if (busyStatus & 0x80000000) {
 
1763
        retVal = ERR_BUSY_CHECK_FAILED;
 
1764
}
 
1765
else if (busyStatus != 2) {
 
1766
        retVal =  (fromEng_P->insert(busyStatus)) ? MSG_RTN_COMPLETED : MSG_RTN_DATA_OVERFLOW;
 
1767
}
 
1768
 
 
1769
return (retVal);
 
1770
 
 
1771
}
 
1772
//dptHBA_C::initBusyLogic()
 
1773
 
 
1774
 
 
1775
//Function - dptHBA_C::i2oDiagTest() - start
 
1776
//===========================================================================
 
1777
//Description:
 
1778
//   This function starts a commanded diagnostic on an I2O controller.
 
1779
//---------------------------------------------------------------------------
 
1780
 
 
1781
DPT_RTN_T dptHBA_C::i2oDiagTest(dptBuffer_S *toEng_P, dptBuffer_S *fromEng_P, uSHORT fnCode)
 
1782
{
 
1783
 
 
1784
 
 
1785
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
1786
 
 
1787
if (isI2O()) {
 
1788
        uLONG rtnSize = 0;
 
1789
 
 
1790
        retVal = ERR_MEM_ALLOC;
 
1791
        char *buff_P = new char[4096];
 
1792
        if (buff_P) {
 
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;
 
1799
 
 
1800
                // Initialize the request message to issue a DPT private SCSI command
 
1801
                if (fnCode == 7) {
 
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;
 
1806
                        else
 
1807
                                i2oInitDmaTest(buff_P, (char *)toEng_P->data+4, (char *)fromEng_P->data);
 
1808
                }
 
1809
                else
 
1810
                        i2oInitPrivateScsi(buff_P, 0x01, 2048, data_P);
 
1811
 
 
1812
                if (!fnCode) {
 
1813
                        request_P->CDBLength = 6;
 
1814
                        request_P->CDB[0] = 0x12;
 
1815
                        request_P->CDB[4] = 0xff;
 
1816
                }
 
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));
 
1825
                        #endif
 
1826
 
 
1827
                        // If DMA test...
 
1828
                        if (fnCode == 0x07) {
 
1829
                                rtnSize = 0;
 
1830
                                uCHAR tempFlags = 0;
 
1831
                                uCHAR defFlags = 0;
 
1832
                                uCHAR defSourceByte = 0xaa;
 
1833
                                uCHAR defDestByte = 0x55;
 
1834
 
 
1835
                                toEng_P->extract(tempFlags);
 
1836
                                toEng_P->extract(defFlags);
 
1837
                                toEng_P->extract(defSourceByte);
 
1838
                                toEng_P->extract(defDestByte);
 
1839
 
 
1840
                                // Copy the "source data" if specified
 
1841
                                if (toEng_P->skip(512))
 
1842
                                        defFlags &= ~0x01;
 
1843
                                // Copy the "destination data" if specified
 
1844
                                if (toEng_P->extract(fromEng_P->data+8, 512))
 
1845
                                        defFlags &= ~0x02;
 
1846
 
 
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);
 
1853
 
 
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
 
1856
 
 
1857
                                request_P->CDB[14] = tempFlags;
 
1858
                        }
 
1859
                        // If RAM test...
 
1860
                        else if (fnCode == 0x06) {
 
1861
                                rtnSize = 16;
 
1862
                                uCHAR tempFlags = 0;
 
1863
                                if (!toEng_P->extract(tempFlags))
 
1864
                                        retVal = MSG_RTN_DATA_UNDERFLOW;
 
1865
                                else 
 
1866
                                        request_P->CDB[6] = tempFlags;
 
1867
                        }
 
1868
                        // BIST test...
 
1869
                        else if (fnCode == 0x08) {
 
1870
                                rtnSize = 4;
 
1871
                        }
 
1872
                }
 
1873
 
 
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) {
 
1878
                                        if (fnCode == 7) {
 
1879
                                                fromEng_P->setExtractSize(536);
 
1880
                                        }
 
1881
                                        else if (fnCode) {
 
1882
                                                if (!fromEng_P->insert(data_P+8, rtnSize))
 
1883
                                                        retVal = MSG_RTN_DATA_OVERFLOW;
 
1884
                                        }
 
1885
                                        else if (!fromEng_P->insert(data_P, 64)) {
 
1886
                                                retVal = MSG_RTN_DATA_OVERFLOW;
 
1887
                                        }
 
1888
                                }
 
1889
                                else
 
1890
                                        retVal = ERR_I2O_REPLY_FAILURE;
 
1891
                        }
 
1892
                }
 
1893
 
 
1894
                delete[] buff_P;
 
1895
        } // (buff_P != NULL)
 
1896
} // end if (isI2O())
 
1897
 
 
1898
return (retVal);
 
1899
 
 
1900
}
 
1901
//dptHBA_C::i2oDiagTest()
 
1902
 
 
1903
 
 
1904
//Function - dptHBA_C::i2oInitPrivateScsi() - start
 
1905
//===========================================================================
 
1906
//Description:
 
1907
//   This function initializes an I2O request message to send a DPT
 
1908
//private SCSI pass-through command.
 
1909
//---------------------------------------------------------------------------
 
1910
 
 
1911
void dptHBA_C::i2oInitPrivateScsi(char *buff_P,
 
1912
                                                                  uLONG dataDir,
 
1913
                                                                  uLONG dataSize,
 
1914
                                                                  char *data_P)
 
1915
{
 
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;
 
1920
 
 
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);
 
1924
 
 
1925
        PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE | I2O_SCB_FLAG_ENABLE_DISCONNECT);
 
1926
 
 
1927
        I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode(privI2o_P, I2O_SCSI_SCB_EXEC);
 
1928
        I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(privI2o_P, DPT_ORGANIZATION_ID);
 
1929
 
 
1930
        PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(privScsi_P, 0x01);
 
1931
 
 
1932
        uLONG msgSize = sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT) - 4;
 
1933
        if (dataDir) {
 
1934
                msgSize += 4; // "ByteCount" field
 
1935
 
 
1936
                versionOffset |= (msgSize << 2) & 0xf0;
 
1937
 
 
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);
 
1944
                }
 
1945
                else { // data out
 
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);
 
1949
                }
 
1950
                I2O_FLAGS_COUNT_setCount(flagsCount_P,  dataSize);
 
1951
                I2O_SGE_SIMPLE_ELEMENT_setPhysicalAddress(sg_P, (uLONG) data_P);
 
1952
 
 
1953
                PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(privScsi_P, dataSize);
 
1954
                msgSize += sizeof(I2O_SGE_SIMPLE_ELEMENT); // SG element
 
1955
 
 
1956
        }
 
1957
        I2O_MESSAGE_FRAME_setMessageSize(i2oMsg_P, (uSHORT)(msgSize >> 2));
 
1958
 
 
1959
        I2O_MESSAGE_FRAME_setVersionOffset(i2oMsg_P, versionOffset);
 
1960
 
 
1961
        return;
 
1962
 
 
1963
}
 
1964
//dptHBA_C::i2oInitPrivateScsi() - end
 
1965
 
 
1966
 
 
1967
//Function - dptHBA_C::i2oInitDmaTest() - start
 
1968
//===========================================================================
 
1969
//Description:
 
1970
//   This function initializes an I2O request message to send a DPT
 
1971
//private SCSI pass-through command.
 
1972
//---------------------------------------------------------------------------
 
1973
 
 
1974
void dptHBA_C::i2oInitDmaTest(char *buff_P, char *source_P, char *dest_P)
 
1975
{
 
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;
 
1980
 
 
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);
 
1984
 
 
1985
        PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setSCBFlags(privScsi_P, I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE | I2O_SCB_FLAG_ENABLE_DISCONNECT);
 
1986
 
 
1987
        I2O_PRIVATE_MESSAGE_FRAME_setXFunctionCode(privI2o_P, I2O_SCSI_SCB_EXEC);
 
1988
        I2O_PRIVATE_MESSAGE_FRAME_setOrganizationID(privI2o_P, DPT_ORGANIZATION_ID);
 
1989
 
 
1990
        PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setInterpret(privScsi_P, 0x01);
 
1991
 
 
1992
        uLONG msgSize = sizeof(PRIVATE_SCSI_SCB_EXECUTE_MESSAGE) - sizeof(I2O_SG_ELEMENT);
 
1993
 
 
1994
        versionOffset |= (msgSize << 2) & 0xf0;
 
1995
 
 
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
 
2005
 
 
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
 
2015
 
 
2016
        // Set the byte count to the size of the largest buffer
 
2017
        PRIVATE_SCSI_SCB_EXECUTE_MESSAGE_setByteCount(privScsi_P, 536);
 
2018
 
 
2019
        I2O_MESSAGE_FRAME_setMessageSize(i2oMsg_P, (uSHORT)(msgSize >> 2));
 
2020
 
 
2021
        I2O_MESSAGE_FRAME_setVersionOffset(i2oMsg_P, versionOffset);
 
2022
 
 
2023
        return;
 
2024
 
 
2025
}
 
2026
//dptHBA_C::i2oInitDmaTest() - end
 
2027
 
 
2028
 
 
2029
//Function - dptHBA_C::getBatteryInfo() - start
 
2030
//===========================================================================
 
2031
//Description:
 
2032
//   This function returns the backup battery information structure.
 
2033
//---------------------------------------------------------------------------
 
2034
 
 
2035
DPT_RTN_T dptHBA_C::getBatteryInfo(dptBuffer_S *toEng_P, dptBuffer_S *fromEng_P)
 
2036
{
 
2037
 
 
2038
 
 
2039
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
2040
 
 
2041
if (isBatteryUnit()) {
 
2042
        uCHAR   pageControl = 0;
 
2043
        uCHAR   pageType = 0;
 
2044
        if (toEng_P->extract(pageType)) {
 
2045
                if (pageType)
 
2046
                        pageControl = 0x02; // Default values
 
2047
        }
 
2048
 
 
2049
          // Get a CCB
 
2050
        engCCB_C *ccb_P = getCCB();
 
2051
        if (ccb_P==NULL)
 
2052
                retVal = ERR_GET_CCB;
 
2053
        else {
 
2054
                // Mode page 0x3A - battery info
 
2055
                ccb_P->modeSense(0x3A, pageControl);
 
2056
                // Target this HBA
 
2057
                ccb_P->target(this);
 
2058
 
 
2059
                // Send the CCB to hardware
 
2060
                retVal=launchCCB(ccb_P);
 
2061
                
 
2062
                if (retVal==MSG_RTN_COMPLETED) {
 
2063
 
 
2064
                        uLONG   tempLong = 0;
 
2065
                        uCHAR   tempChar = 0;
 
2066
                        struct tm       *tm_P = NULL;   // pointer to the static structure returned by localtime()
 
2067
 
 
2068
                        dptBatteryModePage_S *info_P = (dptBatteryModePage_S *) ccb_P->modeParam_P->getData();
 
2069
                        info_P->scsiSwap();
 
2070
 
 
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);
 
2093
 
 
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
 
2104
 
 
2105
                        // Thresholds
 
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);
 
2114
 
 
2115
                        // Date of last maintenance calibration
 
2116
                        tempLong = info_P->getMaintenanceDate();
 
2117
                        if (tempLong) {
 
2118
                                tm_P = localtime((const time_t *)&tempLong);
 
2119
                                if (tm_P == NULL) {
 
2120
                                        tempLong = 0;
 
2121
                                        fromEng_P->insert(tempLong);
 
2122
                                }
 
2123
                                else {
 
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
 
2130
                                        tempChar = 0;
 
2131
                                        fromEng_P->insert(tempChar);    // reserved byte
 
2132
                                }
 
2133
                        }
 
2134
                        else
 
2135
                                fromEng_P->insert(tempLong);
 
2136
 
 
2137
                        // Date of last initial calibration
 
2138
                        tempLong = info_P->getInitialCalibrationDate();
 
2139
                        if (tempLong) {
 
2140
                                tm_P = localtime((const time_t *)&tempLong);
 
2141
                                if (tm_P == NULL) {
 
2142
                                        tempLong = 0;
 
2143
                                        fromEng_P->insert(tempLong);
 
2144
                                }
 
2145
                                else {
 
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
 
2152
                                        tempChar = 0;
 
2153
                                        fromEng_P->insert(tempChar);    // reserved byte
 
2154
                                }
 
2155
                        }
 
2156
                        else
 
2157
                                fromEng_P->insert(tempLong);
 
2158
 
 
2159
                        // ASCII fields
 
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;
 
2167
                        else
 
2168
                                retVal = MSG_RTN_COMPLETED;
 
2169
 
 
2170
                } // launchCCB() - end
 
2171
                // Free the CCB
 
2172
                ccb_P->clrInUse();
 
2173
        } // (ccb_P!=NULL)
 
2174
 
 
2175
        return retVal;
 
2176
 
 
2177
} // if (isBatteryUnit())
 
2178
 
 
2179
return (retVal);
 
2180
 
 
2181
}
 
2182
//dptHBA_C::getBatteryInfo() - end
 
2183
 
 
2184
 
 
2185
//Function - dptHBA_C::setBatteryThresholds() - start
 
2186
//===========================================================================
 
2187
//Description:
 
2188
//   This function sets the backup battery threshold levels.
 
2189
//---------------------------------------------------------------------------
 
2190
 
 
2191
DPT_RTN_T dptHBA_C::setBatteryThresholds(dptBuffer_S *toEng_P)
 
2192
{
 
2193
 
 
2194
 
 
2195
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
2196
 
 
2197
if (isBatteryUnit()) {
 
2198
          // Get a CCB
 
2199
        engCCB_C *ccb_P = getCCB();
 
2200
        if (ccb_P==NULL)
 
2201
                retVal = ERR_GET_CCB;
 
2202
        else {
 
2203
 
 
2204
                // --- Read the battery info mode page ---
 
2205
 
 
2206
                // Mode page 0x3A - battery info
 
2207
                ccb_P->modeSense(0x3A);
 
2208
                // Target this HBA
 
2209
                ccb_P->target(this);
 
2210
                // Send the CCB to hardware
 
2211
                retVal = launchCCB(ccb_P);
 
2212
 
 
2213
                // Send the CCB to hardware
 
2214
                if (retVal==MSG_RTN_COMPLETED) {
 
2215
 
 
2216
                        uLONG   tempLong = 0;
 
2217
 
 
2218
                        dptBatteryModePage_S *info_P = (dptBatteryModePage_S *) ccb_P->modeParam_P->getData();
 
2219
 
 
2220
                        // --- Write the battery info mode page ---
 
2221
 
 
2222
                        memset(ccb_P->eataCP.scsiCDB, 0, 12);
 
2223
                        ccb_P->modeSelect(0x3A, (uSHORT)(dptBatteryModePage_S::size() + 2));
 
2224
                        ccb_P->target(this);
 
2225
 
 
2226
                        toEng_P->extract(tempLong);
 
2227
                        info_P->setWriteThruThreshold((uSHORT)tempLong);
 
2228
                        info_P->swapWriteThruThreshold();
 
2229
 
 
2230
                        toEng_P->extract(tempLong);
 
2231
                        info_P->setPredictiveFailureThreshold((uSHORT)tempLong);
 
2232
                        info_P->swapPredictiveFailureThreshold();
 
2233
 
 
2234
                        toEng_P->extract(tempLong); // reserved
 
2235
 
 
2236
                        if (!toEng_P->extract(tempLong))
 
2237
                                retVal = MSG_RTN_DATA_UNDERFLOW;
 
2238
                        else {
 
2239
                                info_P->setThresholdEnable((uSHORT)tempLong);
 
2240
                                info_P->swapThresholdEnable();
 
2241
 
 
2242
                                // Send the mode select to hardware
 
2243
                                retVal = launchCCB(ccb_P);
 
2244
                        }
 
2245
 
 
2246
                } // launchCCB() - end
 
2247
 
 
2248
                // Free the CCB
 
2249
                ccb_P->clrInUse();
 
2250
 
 
2251
        } // (ccb_P!=NULL)
 
2252
 
 
2253
} // end if (ccb_P!=NULL)
 
2254
 
 
2255
return (retVal);
 
2256
 
 
2257
}
 
2258
//dptHBA_C::setBatteryThresholds() - end
 
2259
 
 
2260
 
 
2261
//Function - dptHBA_C::calibrateBattery() - start
 
2262
//===========================================================================
 
2263
//Description:
 
2264
//   This function calibrates the backup battery.
 
2265
//
 
2266
// calibrationType = 0, Perform initial calibration (charge, discharge, recharge)
 
2267
// calibrationType = 1, Perform maintenance calibration (discharge, charge)
 
2268
//---------------------------------------------------------------------------
 
2269
 
 
2270
DPT_RTN_T dptHBA_C::calibrateBattery(dptBuffer_S *toEng_P)
 
2271
{
 
2272
 
 
2273
        DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
2274
 
 
2275
        if (isBatteryUnit()) {
 
2276
                uCHAR   calibrationType = 0;
 
2277
 
 
2278
                // Get the calibration type (initial calibration == 0, maintenance calibration == 1)
 
2279
                if (!toEng_P->extract(calibrationType))
 
2280
                        retVal = MSG_RTN_DATA_UNDERFLOW;
 
2281
                else
 
2282
                        retVal = sendMFC(MFC_CALIBRATE_BATTERY, calibrationType);
 
2283
        }
 
2284
 
 
2285
        return (retVal);
 
2286
 
 
2287
}
 
2288
//dptHBA_C::calibrateBattery() - end
 
2289
 
 
2290
 
 
2291
//Function - dptHBA_C::getBatteryStatus() - start
 
2292
//===========================================================================
 
2293
//Description:
 
2294
//   This function returns the backup battery information structure.
 
2295
//---------------------------------------------------------------------------
 
2296
 
 
2297
DPT_RTN_T dptHBA_C::getBatteryStatus()
 
2298
{
 
2299
 
 
2300
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
2301
 
 
2302
if (isBatteryUnit()) {
 
2303
        uCHAR   pageControl = 0;
 
2304
          // Get a CCB
 
2305
        engCCB_C *ccb_P = getCCB();
 
2306
        if (ccb_P==NULL)
 
2307
                retVal = ERR_GET_CCB;
 
2308
        else {
 
2309
                // Mode page 0x3A - battery info
 
2310
                ccb_P->modeSense(0x3A, pageControl);
 
2311
                // Target this HBA
 
2312
                ccb_P->target(this);
 
2313
 
 
2314
                // Send the CCB to hardware
 
2315
                retVal=launchCCB(ccb_P);
 
2316
                
 
2317
                if (retVal==MSG_RTN_COMPLETED) {
 
2318
                        dptBatteryModePage_S *info_P = (dptBatteryModePage_S *) ccb_P->modeParam_P->getData();
 
2319
                        info_P->scsiSwap();
 
2320
 
 
2321
                        // Update the battery status and flags
 
2322
                        batteryStatus = info_P->getStatus();
 
2323
                        batteryFlags = info_P->getFlags();
 
2324
 
 
2325
                } // launchCCB() - end
 
2326
 
 
2327
                // Free the CCB
 
2328
                ccb_P->clrInUse();
 
2329
        } // (ccb_P!=NULL)
 
2330
 
 
2331
        return retVal;
 
2332
 
 
2333
} // end if (isBatteryUnit)
 
2334
 
 
2335
return (retVal);
 
2336
 
 
2337
}
 
2338
//dptHBA_C::getBatteryInfo() - end
 
2339
 
 
2340
 
 
2341
//Function - dptHBA_C::getArrayLimits() - start
 
2342
//===========================================================================
 
2343
//
 
2344
//Description:
 
2345
//   This function returns the firmware array limit information
 
2346
//for this HBA.
 
2347
//
 
2348
//---------------------------------------------------------------------------
 
2349
 
 
2350
DPT_RTN_T dptHBA_C::getArrayLimits(dptBuffer_S *fromEng_P)
 
2351
{
 
2352
 
 
2353
DPT_RTN_T retVal = ERR_GET_CCB;
 
2354
 
 
2355
  // Get a CCB
 
2356
engCCB_C *ccb_P = getCCB();
 
2357
if (ccb_P!=NULL) {
 
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);
 
2362
        // Target this HBA
 
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()) {
 
2371
                 // Return success
 
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;
 
2377
         }
 
2378
         else
 
2379
            retVal = MSG_RTN_IGNORED;
 
2380
         }
 
2381
   } // end if (launchCCB()==MSG_RTN_COMPLETED)
 
2382
 
 
2383
        // Free the CCB
 
2384
   ccb_P->clrInUse();
 
2385
} // end if (ccb_P!=NULL)
 
2386
 
 
2387
return (retVal);
 
2388
 
 
2389
}
 
2390
//dptHBA_C::getArrayLimits() - end
 
2391
 
 
2392
 
 
2393
//Function - dptHBA_C::setExclusion() - start
 
2394
//===========================================================================
 
2395
//
 
2396
//Description:
 
2397
//
 
2398
//   This function sets the HBA's background task exclusion period.
 
2399
//
 
2400
//---------------------------------------------------------------------------
 
2401
 
 
2402
DPT_RTN_T dptHBA_C::setExclusion(dptBuffer_S *toEng_P)
 
2403
{
 
2404
 
 
2405
DPT_RTN_T retVal = MSG_RTN_DATA_UNDERFLOW;
 
2406
uCHAR          startTime,endTime;
 
2407
 
 
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;
 
2413
   else {
 
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;
 
2419
         }
 
2420
   }
 
2421
}
 
2422
 
 
2423
return (retVal);
 
2424
 
 
2425
}
 
2426
//dptHBA_C::setExclusion() - end
 
2427
 
 
2428
 
 
2429
//Function - dptHBA_C::readDriveSizeTable() - start
 
2430
//===========================================================================
 
2431
//Description:
 
2432
//    This function reads the drive size table from the controller.
 
2433
//---------------------------------------------------------------------------
 
2434
 
 
2435
DPT_RTN_T       dptHBA_C::readDriveSizeTable()
 
2436
{
 
2437
 
 
2438
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2439
 
 
2440
engCCB_C *ccb_P = getCCB();
 
2441
if (ccb_P!=NULL) {
 
2442
        // Read the controller's drive size table
 
2443
        ccb_P->readDriveSizeTable();
 
2444
        // Target this HBA
 
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);
 
2452
        }
 
2453
 
 
2454
        // Free the CCB
 
2455
        ccb_P->clrInUse();
 
2456
}
 
2457
 
 
2458
return (retVal);
 
2459
 
 
2460
}
 
2461
//dptHBA_C::readDriveSizeTable() - end
 
2462
 
 
2463
 
 
2464
//Function - dptHBA_C::writeDriveSizeTable() - start
 
2465
//===========================================================================
 
2466
//Description:
 
2467
//    This function writes the current drive size table to the controller.
 
2468
//---------------------------------------------------------------------------
 
2469
 
 
2470
DPT_RTN_T       dptHBA_C::writeDriveSizeTable()
 
2471
{
 
2472
 
 
2473
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_NO_DRIVE_SIZE_TABLE;
 
2474
 
 
2475
if (driveSizeTable_P != NULL) {
 
2476
        retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2477
        engCCB_C *ccb_P = getCCB();
 
2478
        if (ccb_P!=NULL) {
 
2479
                uLONG tableSize = 8+(driveSizeTable_P->getNumEntries()<<2);
 
2480
                // Get the drive size table
 
2481
                ccb_P->writeDriveSizeTable(tableSize);
 
2482
                // Target this HBA
 
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();
 
2488
 
 
2489
                // Send the CCB to hardware
 
2490
                retVal = launchCCB(ccb_P);
 
2491
 
 
2492
                // Free the CCB
 
2493
                ccb_P->clrInUse();
 
2494
        }
 
2495
}
 
2496
 
 
2497
return (retVal);
 
2498
 
 
2499
}
 
2500
//dptHBA_C::writeDriveSizeTable() - end
 
2501
 
 
2502
 
 
2503
//Function - dptHBA_C::useDriveSizeTable() - start
 
2504
//===========================================================================
 
2505
//Description:
 
2506
//    This function sets the current drive size table from the specified
 
2507
//structure.
 
2508
//---------------------------------------------------------------------------
 
2509
 
 
2510
void    dptHBA_C::useDriveSizeTable(driveSizeTable_S *ds_P)
 
2511
{
 
2512
 
 
2513
        DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2514
 
 
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)];
 
2518
 
 
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());
 
2525
 
 
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));
 
2531
        }
 
2532
 
 
2533
 
 
2534
}
 
2535
//dptHBA_C::useDriveSizeTable() - end
 
2536
 
 
2537
 
 
2538
//Function - dptHBA_C::sendMFC() - start
 
2539
//===========================================================================
 
2540
//
 
2541
//Description:
 
2542
//
 
2543
//    This function sends a RAID multi-function command to this HBA.
 
2544
//
 
2545
//---------------------------------------------------------------------------
 
2546
 
 
2547
DPT_RTN_T       dptHBA_C::sendMFC(uCHAR inCmd,uCHAR inModifier,uCHAR inParam)
 
2548
{
 
2549
 
 
2550
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2551
 
 
2552
engCCB_C *ccb_P = getCCB();
 
2553
if (ccb_P!=NULL) {
 
2554
        // Initialize the CCB for a DPT multi-function command
 
2555
   ccb_P->mfCmd(inCmd,inModifier,inParam);
 
2556
        // Target this HBA
 
2557
   ccb_P->target(this);
 
2558
        // Send the CCB to hardware
 
2559
   retVal = launchCCB(ccb_P);
 
2560
 
 
2561
        // Free the CCB
 
2562
   ccb_P->clrInUse();
 
2563
}
 
2564
 
 
2565
return (retVal);
 
2566
 
 
2567
}
 
2568
//dptHBA_C::sendMFC() - end
 
2569
 
 
2570
 
 
2571
//Function - dptHBA_C::sendExtMFC() - start
 
2572
//===========================================================================
 
2573
//
 
2574
//Description:
 
2575
//
 
2576
//    This function sends an extended multi-function command to this HBA.
 
2577
//
 
2578
//---------------------------------------------------------------------------
 
2579
 
 
2580
DPT_RTN_T       dptHBA_C::sendExtMFC(uCHAR inCmd,uCHAR inModifier,
 
2581
                                        uLONG     inParam1,
 
2582
                                        uSHORT    inParam2,
 
2583
                                        uCHAR     inParam3
 
2584
                                    )
 
2585
{
 
2586
 
 
2587
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2588
 
 
2589
engCCB_C *ccb_P = getCCB();
 
2590
if (ccb_P!=NULL) {
 
2591
        // Initialize the CCB for an extended DPT multi-function command
 
2592
   ccb_P->extMfCmd(inCmd,inModifier,inParam1,inParam2,inParam3);
 
2593
        // Target this HBA
 
2594
   ccb_P->target(this);
 
2595
        // Send the CCB to hardware
 
2596
   retVal = launchCCB(ccb_P);
 
2597
 
 
2598
        // Free the CCB
 
2599
   ccb_P->clrInUse();
 
2600
}
 
2601
 
 
2602
return (retVal);
 
2603
 
 
2604
}
 
2605
//dptHBA_C::sendExtMFC() - end
 
2606
 
 
2607
 
 
2608
//Function - dptHBA_C::updateStatus() - start
 
2609
//===========================================================================
 
2610
//
 
2611
//Description:
 
2612
//
 
2613
//    This function updates this HBA's status.
 
2614
//
 
2615
//---------------------------------------------------------------------------
 
2616
 
 
2617
DPT_RTN_T       dptHBA_C::updateStatus(dptBuffer_S *fromEng_P)
 
2618
{
 
2619
 
 
2620
   DPT_RTN_T    retVal = MSG_RTN_IGNORED;
 
2621
   uSHORT       LEDpattern;
 
2622
 
 
2623
if (isReal()) {
 
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;
 
2633
         }
 
2634
         else {
 
2635
             status.main = SMAIN_BLINK_LED;
 
2636
             status.sub = (uCHAR) LEDpattern;
 
2637
             status.display = DSPLY_STAT_FAILED;
 
2638
         }
 
2639
   }
 
2640
   else {
 
2641
         retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2642
         status.main = 0;
 
2643
         status.sub = 0;
 
2644
         status.display = DSPLY_STAT_OPTIMAL;
 
2645
        // Get a CCB
 
2646
         engCCB_C *ccb_P = getCCB();
 
2647
         if (ccb_P!=NULL) {
 
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);
 
2651
           // Target this HBA
 
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];
 
2659
                }
 
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;
 
2666
                  else
 
2667
                    // Indicate that the alarm is off
 
2668
                  status.flags &= ~FLG_STAT_ALARM_ON;
 
2669
            }
 
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;
 
2675
            }
 
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));
 
2680
            
 
2681
            if(hbaFlags2 & FLG_HBA_TEMP_PROBE)
 
2682
                        ccb_P->log.reset();
 
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);
 
2688
                 }
 
2689
         } // end if (launchCCB())
 
2690
 
 
2691
           // Free the CCB
 
2692
         ccb_P->clrInUse();
 
2693
         } // end if (ccb_!=NULL)
 
2694
   } // end if (!blink LED)
 
2695
 
 
2696
   // Update the battery status
 
2697
   getBatteryStatus();
 
2698
 
 
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;
 
2705
         }
 
2706
   }
 
2707
} // end if (isReal())
 
2708
 
 
2709
return (retVal);
 
2710
 
 
2711
}
 
2712
//dptHBA_C::updateStatus() - end
 
2713
 
 
2714
 
 
2715
//Function - dptHBA_C::getTime() - start
 
2716
//===========================================================================
 
2717
//
 
2718
//Description:
 
2719
//
 
2720
//    This function reads the time from the HBA.
 
2721
//
 
2722
//Parameters:
 
2723
//
 
2724
//Return Value:
 
2725
//
 
2726
//Global Variables Affected:
 
2727
//
 
2728
//Remarks: (Side effects, Assumptions, Warnings...)
 
2729
//
 
2730
//
 
2731
//---------------------------------------------------------------------------
 
2732
 
 
2733
DPT_RTN_T       dptHBA_C::getTime(dptBuffer_S *fromEng_P)
 
2734
{
 
2735
 
 
2736
        DPT_RTN_T               retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2737
 
 
2738
  // Get a CCB
 
2739
engCCB_C *ccb_P = getCCB();
 
2740
if (ccb_P!=NULL) {
 
2741
          // Initialize the CDB to perform a mode sense
 
2742
        ccb_P->modeSense(0x2f);
 
2743
          // Target this HBA
 
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())
 
2753
 
 
2754
        // Free the CCB
 
2755
   ccb_P->clrInUse();
 
2756
} // end if (ccb_P!=NULL)
 
2757
 
 
2758
return(retVal);
 
2759
 
 
2760
}
 
2761
//dptHBA_C::getTime() - end
 
2762
 
 
2763
 
 
2764
//Function - dptHBA_C::setTime() - start
 
2765
//===========================================================================
 
2766
//
 
2767
//Description:
 
2768
//
 
2769
//    This function sets the HBA time.
 
2770
//
 
2771
//Parameters:
 
2772
//
 
2773
//Return Value:
 
2774
//
 
2775
//Global Variables Affected:
 
2776
//
 
2777
//Remarks: (Side effects, Assumptions, Warnings...)
 
2778
//
 
2779
//
 
2780
//---------------------------------------------------------------------------
 
2781
 
 
2782
DPT_RTN_T       dptHBA_C::setTime(dptBuffer_S *toEng_P)
 
2783
{
 
2784
 
 
2785
        DPT_RTN_T               retVal = MSG_RTN_DATA_UNDERFLOW;
 
2786
        uLONG           hbaTime;
 
2787
 
 
2788
  // Get the new time value
 
2789
if (toEng_P->extract(hbaTime)) {
 
2790
        retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
2791
          // Get a CCB
 
2792
        engCCB_C *ccb_P = getCCB();
 
2793
        if (ccb_P!=NULL) {
 
2794
        // Zero the data buffer
 
2795
                ccb_P->clrData();
 
2796
        // Initialize the CCB to do a mode select page 0x2f
 
2797
                ccb_P->modeSelect6(0x2f,0x06+2);
 
2798
        // Target this HBA
 
2799
                ccb_P->target(this);
 
2800
        // Set the time
 
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);
 
2806
 
 
2807
        // Free the CCB
 
2808
                ccb_P->clrInUse();
 
2809
        } // end if (ccb_P!=NULL)
 
2810
}
 
2811
 
 
2812
return(retVal);
 
2813
 
 
2814
}
 
2815
//dptHBA_C::setTime() - end
 
2816
 
 
2817
 
 
2818
//Function - dptHBA_C::checkForEmul() - start
 
2819
//===========================================================================
 
2820
//
 
2821
//Description:
 
2822
//
 
2823
//    This function checks for emulated drives associated with this HBA.
 
2824
//
 
2825
//Parameters:
 
2826
//
 
2827
//Return Value:
 
2828
//
 
2829
//Global Variables Affected:
 
2830
//
 
2831
//Remarks: (Side effects, Assumptions, Warnings...)
 
2832
//
 
2833
//
 
2834
//---------------------------------------------------------------------------
 
2835
 
 
2836
void    dptHBA_C::checkForEmul()
 
2837
{
 
2838
 
 
2839
   uSHORT       done = 0;
 
2840
 
 
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();
 
2845
}
 
2846
 
 
2847
}
 
2848
//dptHBA_C::checkForEmul() - end
 
2849
 
 
2850
 
 
2851
//Function - dptHBA_C::getEventCtl() - start
 
2852
//===========================================================================
 
2853
//
 
2854
//Description:
 
2855
//
 
2856
//    This function gets the DPT HBA event log control word.
 
2857
//
 
2858
//Parameters:
 
2859
//
 
2860
//Return Value:
 
2861
//
 
2862
//Global Variables Affected:
 
2863
//
 
2864
//Remarks: (Side effects, Assumptions, Warnings...)
 
2865
//
 
2866
//
 
2867
//---------------------------------------------------------------------------
 
2868
 
 
2869
void    dptHBA_C::getEventCtl()
 
2870
{
 
2871
 
 
2872
engCCB_C *ccb_P = getCCB();
 
2873
if (ccb_P!=NULL) {
 
2874
          // Initialize the CCB to get the HBA event log control word
 
2875
        ccb_P->modeSense(0x22,0,0,0x60);
 
2876
          // Target this HBA
 
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);
 
2882
   }
 
2883
 
 
2884
        // Free the CCB
 
2885
   ccb_P->clrInUse();
 
2886
}
 
2887
 
 
2888
}
 
2889
//dptHBA_C::getEventCtl() - end
 
2890
 
 
2891
 
 
2892
//Function - dptHBA_C::setEventCtl() - start
 
2893
//===========================================================================
 
2894
//
 
2895
//Description:
 
2896
//
 
2897
//    This function sets the DPT HBA event log control word.
 
2898
//
 
2899
//Parameters:
 
2900
//
 
2901
//Return Value:
 
2902
//
 
2903
//Global Variables Affected:
 
2904
//
 
2905
//Remarks: (Side effects, Assumptions, Warnings...)
 
2906
//
 
2907
//
 
2908
//---------------------------------------------------------------------------
 
2909
 
 
2910
DPT_RTN_T       dptHBA_C::setEventCtl(dptBuffer_S *toEng_P)
 
2911
{
 
2912
 
 
2913
   DPT_RTN_T            retVal = MSG_RTN_DATA_UNDERFLOW;
 
2914
        uLONG           newEventCtl;
 
2915
   uCHAR                saveToNV;
 
2916
 
 
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))
 
2922
         saveToNV = 1;
 
2923
        // Get a CCB
 
2924
   engCCB_C *ccb_P = getCCB();
 
2925
   if (ccb_P!=NULL) {
 
2926
        // Initialize the CCB to get the HBA event log control word
 
2927
         ccb_P->modeSelect(0x22,0x04+2,saveToNV & 0x7f);
 
2928
        // Target this HBA
 
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;
 
2937
 
 
2938
        // Free the CCB
 
2939
         ccb_P->clrInUse();
 
2940
   }
 
2941
}
 
2942
 
 
2943
return (retVal);
 
2944
 
 
2945
}
 
2946
//dptHBA_C::setEventCtl() - end
 
2947
 
 
2948
 
 
2949
//Function - dptHBA_C::rtnEventLog() - start
 
2950
//===========================================================================
 
2951
//
 
2952
//Description:
 
2953
//
 
2954
//    This function returns the event log for this HBA (non-destructively).
 
2955
//
 
2956
//Parameters:
 
2957
//
 
2958
//Return Value:
 
2959
//
 
2960
//Global Variables Affected:
 
2961
//
 
2962
//Remarks: (Side effects, Assumptions, Warnings...)
 
2963
//
 
2964
//
 
2965
//---------------------------------------------------------------------------
 
2966
 
 
2967
DPT_RTN_T       dptHBA_C::rtnEventLog(dptBuffer_S *toEng_P,
 
2968
                                         dptBuffer_S *fromEng_P
 
2969
                                        )
 
2970
{
 
2971
 
 
2972
   DPT_RTN_T            retVal = MSG_RTN_IGNORED;
 
2973
   uLONG                offset = 0;
 
2974
 
 
2975
if (is512kCache() || isI2O()) {
 
2976
   if (!toEng_P->extract(offset))
 
2977
         offset = 0;
 
2978
 
 
2979
        // Get the event log data - Do not clear the event log
 
2980
   retVal = doLogSense(fromEng_P,0x34,1,offset,1);
 
2981
 
 
2982
   if (retVal==MSG_RTN_COMPLETED) {
 
2983
         dptHBAlog_C               hbaLog;
 
2984
        // Initialize the HBA log sense data (reverse byte ordering)
 
2985
         hbaLog.initSense(fromEng_P->data,1);
 
2986
   }
 
2987
}
 
2988
 
 
2989
return (retVal);
 
2990
 
 
2991
}
 
2992
//dptHBA_C::rtnEventLog() - end
 
2993
 
 
2994
 
 
2995
//Function - dptHBA_C::clearEventLog() - start
 
2996
//===========================================================================
 
2997
//
 
2998
//Description:
 
2999
//
 
3000
//    This function clears the HBA event log.
 
3001
//
 
3002
//Parameters:
 
3003
//
 
3004
//Return Value:
 
3005
//
 
3006
//Global Variables Affected:
 
3007
//
 
3008
//Remarks: (Side effects, Assumptions, Warnings...)
 
3009
//
 
3010
//
 
3011
//---------------------------------------------------------------------------
 
3012
 
 
3013
DPT_RTN_T       dptHBA_C::clearEventLog()
 
3014
{
 
3015
 
 
3016
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3017
 
 
3018
engCCB_C *ccb_P = getCCB();
 
3019
if (ccb_P!=NULL) {
 
3020
        // Target this HBA
 
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);
 
3028
 
 
3029
        // Free the CCB
 
3030
   ccb_P->clrInUse();
 
3031
}
 
3032
 
 
3033
return (retVal);
 
3034
 
 
3035
}
 
3036
//dptHBA_C::clearEventLog() - end
 
3037
 
 
3038
 
 
3039
//Function - dptHBA_C::rtnHBAstats() - start
 
3040
//===========================================================================
 
3041
//
 
3042
//Description:
 
3043
//
 
3044
//    Return this HBA's global statistics information.
 
3045
//
 
3046
//Parameters:
 
3047
//
 
3048
//Return Value:
 
3049
//
 
3050
//Global Variables Affected:
 
3051
//
 
3052
//Remarks: (Side effects, Assumptions, Warnings...)
 
3053
//
 
3054
//
 
3055
//---------------------------------------------------------------------------
 
3056
 
 
3057
DPT_RTN_T       dptHBA_C::rtnHBAstats(dptBuffer_S *fromEng_P,
 
3058
                                         uCHAR savePage
 
3059
                                        )
 
3060
{
 
3061
 
 
3062
   DPT_RTN_T    retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3063
 
 
3064
engCCB_C *ccb_P = getCCB();
 
3065
if (ccb_P!=NULL) {
 
3066
        // Initialize the CCB to get the global statistics page
 
3067
   ccb_P->logSense(0x30,savePage);
 
3068
        // Target this HBA
 
3069
   ccb_P->target(this);
 
3070
        // Send the CCB to hardware
 
3071
   if ((retVal = launchCCB(ccb_P))==MSG_RTN_COMPLETED) {
 
3072
         if (savePage) {
 
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;
 
3080
         }
 
3081
   }
 
3082
        // Free the CCB
 
3083
   ccb_P->clrInUse();
 
3084
}
 
3085
 
 
3086
return (retVal);
 
3087
 
 
3088
}
 
3089
//dptHBA_C::rtnHBAstats() - end
 
3090
 
 
3091
 
 
3092
//Function - dptHBA_C::rtnIOstats() - start
 
3093
//===========================================================================
 
3094
//
 
3095
//Description:
 
3096
//
 
3097
//    Return this HBA's global read/write statistics information.
 
3098
//
 
3099
//Parameters:
 
3100
//
 
3101
//Return Value:
 
3102
//
 
3103
//Global Variables Affected:
 
3104
//
 
3105
//Remarks: (Side effects, Assumptions, Warnings...)
 
3106
//
 
3107
//
 
3108
//---------------------------------------------------------------------------
 
3109
 
 
3110
DPT_RTN_T       dptHBA_C::rtnIOstats(dptBuffer_S *fromEng_P,
 
3111
                                        uCHAR savePage
 
3112
                                    )
 
3113
{
 
3114
 
 
3115
   DPT_RTN_T    retVal = MSG_RTN_DATA_OVERFLOW;
 
3116
 
 
3117
  // If clear stats data...
 
3118
if (!savePage)
 
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);
 
3128
}
 
3129
 
 
3130
return (retVal);
 
3131
 
 
3132
}
 
3133
//dptHBA_C::rtnIOstats() - end
 
3134
 
 
3135
 
 
3136
//Function - dptHBA_C::delEmulation() - start
 
3137
//===========================================================================
 
3138
//
 
3139
//Description:
 
3140
//
 
3141
//    This function deletes all emulated drives associated with this
 
3142
//HBA.
 
3143
//
 
3144
//Parameters:
 
3145
//
 
3146
//Return Value:
 
3147
//
 
3148
//Global Variables Affected:
 
3149
//
 
3150
//Remarks: (Side effects, Assumptions, Warnings...)
 
3151
//
 
3152
//
 
3153
//---------------------------------------------------------------------------
 
3154
 
 
3155
DPT_RTN_T       dptHBA_C::delEmulation()
 
3156
{
 
3157
 
 
3158
   DPT_RTN_T            retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3159
   dptEmulation_S       *emul_P;
 
3160
   uSHORT               bitTest;
 
3161
   uSHORT               emulStatus;
 
3162
   dptAddr_S            devAddr;
 
3163
   uSHORT               i;
 
3164
   uCHAR                emulAddrs[8];
 
3165
 
 
3166
engCCB_C *ccb_P = getCCB();
 
3167
if (ccb_P!=NULL) {
 
3168
        // Target this HBA
 
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
 
3182
         ccb_P->clrData();
 
3183
         for (bitTest=1,i=0;bitTest<=0x08;bitTest<<=1,i+=2) {
 
3184
            if (emulStatus & bitTest) {
 
3185
                 // Re-initialize the CCB
 
3186
                  ccb_P->reInit();
 
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
 
3197
                  launchCCB(ccb_P);
 
3198
            }
 
3199
         }
 
3200
         }
 
3201
   }
 
3202
        // Free the CCB
 
3203
   ccb_P->clrInUse();
 
3204
}
 
3205
 
 
3206
return (retVal);
 
3207
 
 
3208
}
 
3209
//dptHBA_C::delEmulation() - end
 
3210
 
 
3211
 
 
3212
//Function - dptHBA_C::flashWriteInit() - start
 
3213
//===========================================================================
 
3214
//
 
3215
//Description:
 
3216
//
 
3217
//    This function performs the required initialization to prepare
 
3218
//the HBA's flash memory to be programmed.
 
3219
//
 
3220
//---------------------------------------------------------------------------
 
3221
 
 
3222
DPT_RTN_T       dptHBA_C::flashWriteInit(engCCB_C *ccb_P)
 
3223
{
 
3224
 
 
3225
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_FLASH_SWITCH_MODES;
 
3226
 
 
3227
        updateStatus();
 
3228
        if (!isFlashMode())
 
3229
                switchToFlashMode(ccb_P);
 
3230
        // If in flash mode...
 
3231
        if (isI2O()) {
 
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(...)
 
3236
                flashWriteCnt = 0;
 
3237
                retVal = MSG_RTN_COMPLETED;
 
3238
        } else if (isFlashMode()) {
 
3239
                // Erase the flash
 
3240
                ccb_P->reInit();
 
3241
                ccb_P->target(this);
 
3242
 
 
3243
                time_t pre, post;
 
3244
                time(&pre);
 
3245
                ccb_P->flashCmd(FLASH_CMD_ERASE);
 
3246
                if ((retVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
 
3247
 
 
3248
                        flashStablize();
 
3249
 
 
3250
                        time(&post);
 
3251
 
 
3252
                        dptBuffer_S *inBuffer_P = dptBuffer_S::newBuffer(1024);
 
3253
                        dptBuffer_S *outBuffer_P = dptBuffer_S::newBuffer(1024);
 
3254
 
 
3255
                        if (inBuffer_P && outBuffer_P && ((post-pre) > 1)) {
 
3256
                                inBuffer_P->reset();
 
3257
 
 
3258
                                retVal += flashStatus(inBuffer_P);
 
3259
                                dptFlashStatus_S *status_P = (dptFlashStatus_S *) &inBuffer_P->data[8];
 
3260
 
 
3261
                                uLONG numFlashBytes = status_P->getBurnSize();
 
3262
                                uLONG curRead = 0;
 
3263
 
 
3264
                                while(curRead < numFlashBytes) {
 
3265
 
 
3266
                                        outBuffer_P->reset();
 
3267
                                        outBuffer_P->insert(curRead);
 
3268
                                        outBuffer_P->insert((uLONG) 512);
 
3269
                                        inBuffer_P->reset();
 
3270
 
 
3271
                                        retVal += flashRead(outBuffer_P,inBuffer_P);
 
3272
 
 
3273
                                        for(int x = 0; x < 512; x++) {
 
3274
                                                if (inBuffer_P->data[x] != 0xff)
 
3275
                                                        retVal++;
 
3276
                                        }
 
3277
                                        curRead += 512;
 
3278
                                }
 
3279
 
 
3280
                                dptBuffer_S::delBuffer(inBuffer_P);
 
3281
                                dptBuffer_S::delBuffer(outBuffer_P);
 
3282
                        }
 
3283
 
 
3284
                }
 
3285
 
 
3286
 
 
3287
                if (retVal)
 
3288
                        retVal = MSG_RTN_FAILED | ERR_FLASH_ERASE;
 
3289
                else {
 
3290
                        status.sub = SSUB_FLASH_WRITE;
 
3291
                        flashWriteCnt = 0;
 
3292
                        retVal = MSG_RTN_COMPLETED;
 
3293
                }
 
3294
 
 
3295
        } else
 
3296
                retVal = MSG_RTN_FAILED | ERR_FLASH_ERASE;
 
3297
 
 
3298
        return (retVal);
 
3299
 
 
3300
}
 
3301
//dptHBA_C::flashWriteInit() - end
 
3302
 
 
3303
 
 
3304
//Function - dptHBA_C::flashWrite() - start
 
3305
//===========================================================================
 
3306
//
 
3307
//Description:
 
3308
//
 
3309
//    This function writes the specified data to the next unwritten
 
3310
//location in the flash memory.
 
3311
//
 
3312
//---------------------------------------------------------------------------
 
3313
 
 
3314
DPT_RTN_T       dptHBA_C::flashWrite(dptBuffer_S *toEng_P,uINT verify)
 
3315
{
 
3316
 
 
3317
 
 
3318
DEBUG_BEGIN(1, dptHBA_C::flashWrite());
 
3319
 
 
3320
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3321
 
 
3322
engCCB_C *ccb_P = getCCB();
 
3323
if (ccb_P!=NULL) {
 
3324
 
 
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)
 
3329
         return (retVal);
 
3330
        // Indicate that we are prepared to write to the flash
 
3331
         status.sub = SSUB_FLASH_WRITE;
 
3332
        }
 
3333
 
 
3334
        retVal = MSG_RTN_DATA_UNDERFLOW;
 
3335
        if (toEng_P->writeIndex & 0x1ff)
 
3336
         retVal = MSG_RTN_FAILED | ERR_FLASH_WRITE_512;
 
3337
        else {
 
3338
         uLONG bytesWritten = 0;
 
3339
         while (toEng_P->extract(ccb_P->defData,512)) {
 
3340
         ccb_P->reInit();
 
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)) {
 
3345
 
 
3346
                 flashStablize();
 
3347
                 retVal = MSG_RTN_FAILED | ERR_FLASH_ENG_VERIFY;
 
3348
                 ccb_P->reInit();
 
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;
 
3354
                 }
 
3355
         }
 
3356
         flashStablize();
 
3357
                // If a failure has occurred...
 
3358
         if (retVal != MSG_RTN_COMPLETED) {
 
3359
                 status.sub = SSUB_FLASH_INIT;
 
3360
 
 
3361
            DEBUG(1, PRT_ADDR << "FLASH FAILURE - retVal=0x" << hex << retVal);
 
3362
 
 
3363
                 break;
 
3364
         }
 
3365
         bytesWritten += 512;
 
3366
         flashWriteCnt += 512;
 
3367
 
 
3368
         DEBUG(1, PRT_ADDR << PRT_STAT << (int)flashWriteCnt << "Byte written");
 
3369
 
 
3370
         }
 
3371
        }
 
3372
 
 
3373
        // Free the CCB
 
3374
        ccb_P->clrInUse();
 
3375
}
 
3376
 
 
3377
return (retVal);
 
3378
 
 
3379
}
 
3380
//dptHBA_C::flashWrite() - end
 
3381
 
 
3382
 
 
3383
//Function - dptHBA_C::flashWriteDone() - start
 
3384
//===========================================================================
 
3385
//
 
3386
//Description:
 
3387
//
 
3388
//    This function closes out the flash programming process.  This
 
3389
//function causes the F/W flash code to compute and write the
 
3390
//flash checksums.
 
3391
//
 
3392
//---------------------------------------------------------------------------
 
3393
 
 
3394
DPT_RTN_T       dptHBA_C::flashWriteDone(uCHAR sendToHW)
 
3395
{
 
3396
 
 
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);
 
3402
}
 
3403
 
 
3404
 
 
3405
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3406
 
 
3407
engCCB_C *ccb_P = getCCB();
 
3408
if (ccb_P!=NULL) {
 
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);
 
3417
         flashStablize();
 
3418
//   }
 
3419
//   else
 
3420
//      retVal = MSG_RTN_FAILED | ERR_FLASH_INIT_REQ;
 
3421
 
 
3422
        // Free the CCB
 
3423
        ccb_P->clrInUse();
 
3424
}
 
3425
 
 
3426
return (retVal);
 
3427
 
 
3428
}
 
3429
//dptHBA_C::flashWriteDone() - end
 
3430
 
 
3431
 
 
3432
//Function - dptHBA_C::flashRead() - start
 
3433
//===========================================================================
 
3434
//
 
3435
//Description:
 
3436
//
 
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.
 
3439
//
 
3440
//---------------------------------------------------------------------------
 
3441
 
 
3442
DPT_RTN_T       dptHBA_C::flashRead(dptBuffer_S *toEng_P,dptBuffer_S *fromEng_P)
 
3443
{
 
3444
 
 
3445
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3446
 
 
3447
engCCB_C *ccb_P = getCCB();
 
3448
if (ccb_P!=NULL) {
 
3449
        uLONG flashAddr;
 
3450
        uLONG bytesRequested;
 
3451
        retVal = MSG_RTN_DATA_UNDERFLOW;
 
3452
        toEng_P->extract(flashAddr);
 
3453
        if (toEng_P->extract(bytesRequested)) {
 
3454
         uLONG bytesToRead;
 
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;
 
3463
         }
 
3464
         flashStablize();
 
3465
 
 
3466
         if (retVal != MSG_RTN_COMPLETED)
 
3467
                 break;
 
3468
         flashAddr += bytesToRead;
 
3469
         bytesRequested -= bytesToRead;
 
3470
         }
 
3471
        }
 
3472
        // Free the CCB
 
3473
        ccb_P->clrInUse();
 
3474
}
 
3475
 
 
3476
return (retVal);
 
3477
 
 
3478
}
 
3479
//dptHBA_C::flashRead() - end
 
3480
 
 
3481
 
 
3482
//Function - dptHBA_C::flashStatus() - start
 
3483
//===========================================================================
 
3484
//
 
3485
//Description:
 
3486
//
 
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
 
3489
//mode.
 
3490
//
 
3491
//---------------------------------------------------------------------------
 
3492
 
 
3493
DPT_RTN_T       dptHBA_C::flashStatus(dptBuffer_S *fromEng_P)
 
3494
{
 
3495
 
 
3496
DPT_RTN_T retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3497
 
 
3498
engCCB_C *ccb_P = getCCB();
 
3499
if (ccb_P!=NULL) {
 
3500
        retVal = MSG_RTN_DATA_OVERFLOW;
 
3501
        uLONG fwStatus = 0;
 
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) {
 
3506
         fwStatus = 1;
 
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;
 
3512
        }
 
3513
        else if (fromEng_P->insert(fwStatus))
 
3514
         retVal = MSG_RTN_COMPLETED;
 
3515
 
 
3516
         flashStablize();
 
3517
 
 
3518
        // Free the CCB
 
3519
        ccb_P->clrInUse();
 
3520
}
 
3521
 
 
3522
return (retVal);
 
3523
 
 
3524
}
 
3525
//dptHBA_C::flashStatus() - end
 
3526
 
 
3527
 
 
3528
//Function - dptHBA_C::flashSwitchInto() - start
 
3529
//===========================================================================
 
3530
//
 
3531
//Description:
 
3532
//
 
3533
//    This function attempts to switch the HBA into flash mode from
 
3534
//operational mode.
 
3535
//
 
3536
//---------------------------------------------------------------------------
 
3537
 
 
3538
DPT_RTN_T       dptHBA_C::flashSwitchInto()
 
3539
{
 
3540
 
 
3541
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
3542
 
 
3543
updateStatus();
 
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;
 
3553
 
 
3554
        // Free the CCB
 
3555
         ccb_P->clrInUse();
 
3556
        }
 
3557
}
 
3558
 
 
3559
return (retVal);
 
3560
 
 
3561
}
 
3562
//dptHBA_C::flashSwitchInto() - end
 
3563
 
 
3564
 
 
3565
//Function - dptHBA_C::flashSwitchOutOf() - start
 
3566
//===========================================================================
 
3567
//
 
3568
//Description:
 
3569
//
 
3570
//    This function attempt to switch the firmware into operational
 
3571
//mode from flash mode.  This function causes the firmware to perform
 
3572
//a "cold" reboot.
 
3573
//    if (method == 0)
 
3574
//       a "normal" switch to operational mode is attempted
 
3575
//    else
 
3576
//       a no-checksum switch is attempted for the purposes of
 
3577
//       verifying the functionality newly burned firmware
 
3578
//
 
3579
//---------------------------------------------------------------------------
 
3580
 
 
3581
DPT_RTN_T       dptHBA_C::flashSwitchOutOf(uINT skipChecksumTst)
 
3582
{
 
3583
 
 
3584
DPT_RTN_T retVal = MSG_RTN_IGNORED;
 
3585
 
 
3586
  // Determine how to switch out of flash mode
 
3587
uCHAR action = (skipChecksumTst) ? FLASH_CMD_TST_RESTART : FLASH_CMD_RESTART;
 
3588
 
 
3589
 
 
3590
DEBUG_BEGIN(1, dptHBA_C::flashSwitchOutOf());
 
3591
updateStatus();
 
3592
DEBUG(1, PRT_DADDR(this) << PRT_STAT);
 
3593
 
 
3594
 
 
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();
 
3600
        if (ccb_P!=NULL) {
 
3601
                ccb_P->target(this);
 
3602
                ccb_P->flashCmd(action);
 
3603
                retVal = launchCCB(ccb_P);
 
3604
 
 
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)
 
3609
                        sleep(5);
 
3610
#elif defined (_DPT_WINNT)
 
3611
                        Sleep(5000);
 
3612
#elif defined (_DPT_OS2)
 
3613
                        DosSleep(5000);
 
3614
#endif
 
3615
                if (retVal == MSG_RTN_COMPLETED)
 
3616
                        status.main = status.sub = 0;
 
3617
 
 
3618
        // Free the CCB
 
3619
                ccb_P->clrInUse();
 
3620
        }
 
3621
}
 
3622
 
 
3623
return (retVal);
 
3624
 
 
3625
}
 
3626
//dptHBA_C::flashSwitchOutOf() - end
 
3627
 
 
3628
 
 
3629
//Function - dptHBA_C::switchToFlashMode() - start
 
3630
//===========================================================================
 
3631
//
 
3632
//Description:
 
3633
//
 
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.
 
3639
//
 
3640
//---------------------------------------------------------------------------
 
3641
 
 
3642
DPT_RTN_T       dptHBA_C::switchToFlashMode(engCCB_C *ccb_P)
 
3643
{
 
3644
 
 
3645
 
 
3646
DEBUG_BEGIN(1, dptHBA_C::switchToFlashMode());
 
3647
 
 
3648
 
 
3649
  // Try to switch into flash mode
 
3650
ccb_P->reInit();
 
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) {
 
3655
 
 
3656
// sleep for 2 seconds to make sure the FW has dones thier init'ing.
 
3657
#if defined(_DPT_MSDOS) || defined (_DPT_UNIX)
 
3658
                        sleep(2);
 
3659
#elif defined (_DPT_WINNT)
 
3660
                        Sleep(2000);
 
3661
#elif defined (_DPT_OS2)
 
3662
                        DosSleep(2000);
 
3663
#endif
 
3664
        for (uINT i=0;i<50;i++) {
 
3665
                updateStatus();
 
3666
                if (isFlashMode()) {
 
3667
 
 
3668
#if defined(_DPT_MSDOS) || defined (_DPT_UNIX)
 
3669
                        sleep(1);
 
3670
#elif defined (_DPT_WINNT)
 
3671
                        Sleep(1000);
 
3672
#elif defined (_DPT_OS2)
 
3673
                        DosSleep(1000);
 
3674
#endif
 
3675
 
 
3676
                        ccb_P->reInit();
 
3677
                        ccb_P->target(this);
 
3678
                        ccb_P->inquiry();
 
3679
                        launchCCB(ccb_P);
 
3680
 
 
3681
                        sdInquiry_S *inq_P = (sdInquiry_S *) ccb_P->defData;
 
3682
 
 
3683
                } break;
 
3684
        }
 
3685
}
 
3686
 
 
3687
DEBUG(1, PRT_DADDR(this) << "flash in retVal=" << hex << retVal <<  \
 
3688
         PRT_STAT);
 
3689
 
 
3690
 
 
3691
return (retVal);
 
3692
 
 
3693
}
 
3694
//dptHBA_C::switchToFlashMode() - end
 
3695
 
 
3696
 
 
3697
//Function - dptHBA_C::flashSetRegion() - start
 
3698
//===========================================================================
 
3699
//
 
3700
//Description:
 
3701
//
 
3702
//    This function 
 
3703
//
 
3704
//---------------------------------------------------------------------------
 
3705
 
 
3706
DPT_RTN_T       dptHBA_C::flashSetRegion(dptBuffer_S *toEng_P)
 
3707
{
 
3708
 
 
3709
        DPT_RTN_T retVal = MSG_RTN_COMPLETED;
 
3710
        uLONG   RegionType = 0;
 
3711
        uLONG   BootFlags = 0;
 
3712
        uLONG   ActualSize = 0;
 
3713
        uINT    topAligned = 0;
 
3714
 
 
3715
        if (!isI2O()) {
 
3716
                retVal = MSG_RTN_FAILED;
 
3717
        }
 
3718
        else {
 
3719
                toEng_P->extract(RegionType);
 
3720
                toEng_P->extract(BootFlags);
 
3721
                toEng_P->extract(ActualSize);
 
3722
           
 
3723
                uLONG flashSize = FLASH_REGION_NVRAM_OFFSET + 0x4000L;
 
3724
                uLONG biosOffset = FLASH_REGION_BIOS_OFFSET;
 
3725
                uLONG utilOffset = FLASH_REGION_UTILITY_OFFSET;
 
3726
 
 
3727
                // Determine if top or bottom aligned
 
3728
                if (BootFlags & FW_LOAD_TOP) {
 
3729
                        topAligned = 1;
 
3730
                }
 
3731
 
 
3732
                engCCB_C *ccb_P = getCCB();
 
3733
                if (ccb_P!=NULL) {
 
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();
 
3743
                        }
 
3744
 
 
3745
                        // Read the first 512 bytes of the BIOS region to determine the utility region offset
 
3746
                        utilOffset = biosOffset + 0x8000L; // default = BIOS offset + 32k
 
3747
                        ccb_P->reInit();
 
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];
 
3753
                                        utilOffset <<= 9;
 
3754
                                        utilOffset += biosOffset;
 
3755
                                }
 
3756
                        }
 
3757
 
 
3758
                        ccb_P->clrInUse();
 
3759
                }
 
3760
 
 
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
 
3766
                                }
 
3767
                                break;
 
3768
                        case FLASH_REGION_BIOS:
 
3769
                                flashRegionOffset = biosOffset;
 
3770
                                break;
 
3771
                        case FLASH_REGION_UTILITY:
 
3772
                                flashRegionOffset = utilOffset;
 
3773
                                break;
 
3774
                        case FLASH_REGION_NVRAM:
 
3775
                                flashRegionOffset = flashSize - 0x4000L; // flash size - 16k
 
3776
                                break;
 
3777
                        case FLASH_REGION_SERIAL_NUM:
 
3778
                                flashRegionOffset = flashSize - 0x2000L; // flash size - 8k
 
3779
                                break;
 
3780
                        default :
 
3781
                                retVal = MSG_RTN_FAILED;
 
3782
                                break;
 
3783
                }
 
3784
        }
 
3785
 
 
3786
return (retVal);
 
3787
 
 
3788
}
 
3789
//dptHBA_C::flashSetRegion() - end
 
3790
 
 
3791
//Function - dptHBA_C::flashStablize()  - start
 
3792
//===========================================================================
 
3793
//
 
3794
//Description: the board is in flash mode, wait until we see the
 
3795
//                       bled code before going on
 
3796
//
 
3797
//
 
3798
//Parameters:
 
3799
//
 
3800
//Return Value:
 
3801
//
 
3802
//Global Variables Affected:
 
3803
//
 
3804
//Remarks: (Side effects, Assumptions, Warnings...)
 
3805
//
 
3806
//
 
3807
//---------------------------------------------------------------------------
 
3808
void dptHBA_C::flashStablize()
 
3809
{
 
3810
        uSHORT LEDpattern = 0;
 
3811
 
 
3812
        if (!isI2O() && status.main == SMAIN_FLASH_MODE) {
 
3813
                while((LEDpattern & 0x00ff) != 0x69)
 
3814
                        osdCheckBLED(getDrvrNum(),&LEDpattern);
 
3815
        }
 
3816
}
 
3817
// - end
 
3818
 
 
3819
//Function - dptHBA_C::setDataField() - start
 
3820
//===========================================================================
 
3821
//
 
3822
//Description:
 
3823
//
 
3824
//    This function sets the specified data field to the specified
 
3825
//value.
 
3826
//
 
3827
//---------------------------------------------------------------------------
 
3828
 
 
3829
DPT_RTN_T       dptHBA_C::setDataField(dptBuffer_S *toEng_P)
 
3830
{
 
3831
 
 
3832
   DPT_RTN_T            retVal = MSG_RTN_DATA_UNDERFLOW;
 
3833
   uSHORT               dataField,tempShort;
 
3834
 
 
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();
 
3842
         }
 
3843
         break;
 
3844
         case DF_RBLD_BOOT_CHECK:
 
3845
         if (toEng_P->extract(tempShort)) {
 
3846
            if (tempShort)
 
3847
                  raidFlags |= FLG_RBLD_BOOT_CHECK;
 
3848
            else
 
3849
                  raidFlags &= ~FLG_RBLD_BOOT_CHECK;
 
3850
            retVal = updateLAPparams();
 
3851
         }
 
3852
         break;
 
3853
         case DF_SPIN_DOWN_DELAY:
 
3854
         if (toEng_P->extract(tempShort)) {
 
3855
            spinDownDelay = tempShort;
 
3856
            retVal = updateLAPparams();
 
3857
         }
 
3858
         break;
 
3859
         default:
 
3860
         toEng_P->replay();
 
3861
         retVal = dptRAIDhba_C::setDataField(toEng_P);
 
3862
         break;
 
3863
   } // end switch (dataField)
 
3864
} //
 
3865
 
 
3866
return (retVal);
 
3867
 
 
3868
}
 
3869
//dptHBA_C::setDataField() - end
 
3870
 
 
3871
 
 
3872
//Function - dptHBA_C::readNV_RAM() - start
 
3873
//===========================================================================
 
3874
//
 
3875
//Description:
 
3876
//
 
3877
//      This function attempts to read the contents of the HBA's
 
3878
//non-volatile memory.
 
3879
//
 
3880
//---------------------------------------------------------------------------
 
3881
 
 
3882
DPT_RTN_T       dptHBA_C::readNV_RAM(dptBuffer_S *fromEng_P)
 
3883
{
 
3884
 
 
3885
DPT_RTN_T       retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3886
 
 
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;
 
3895
         else
 
3896
         retVal = MSG_RTN_DATA_OVERFLOW;
 
3897
   }
 
3898
 
 
3899
        // Free the CCB
 
3900
   ccb_P->clrInUse();
 
3901
}
 
3902
 
 
3903
return (retVal);
 
3904
 
 
3905
}
 
3906
//dptHBA_C::readNV_RAM() - end
 
3907
 
 
3908
 
 
3909
//Function - dptHBA_C::writeNV_RAM() - start
 
3910
//===========================================================================
 
3911
//
 
3912
//Description:
 
3913
//
 
3914
//      This function attempts to write the contents of the HBA's
 
3915
//non-volatile memory.
 
3916
//
 
3917
//---------------------------------------------------------------------------
 
3918
 
 
3919
DPT_RTN_T       dptHBA_C::writeNV_RAM(dptBuffer_S *toEng_P)
 
3920
{
 
3921
 
 
3922
DPT_RTN_T       retVal = MSG_RTN_FAILED | ERR_GET_CCB;
 
3923
 
 
3924
engCCB_C *ccb_P = getCCB();
 
3925
if (ccb_P != NULL) {
 
3926
   ccb_P->clrData();
 
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
 
3933
         char checksum = 0;
 
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);
 
3940
   }
 
3941
        // Free the CCB
 
3942
   ccb_P->clrInUse();
 
3943
}
 
3944
 
 
3945
return (retVal);
 
3946
 
 
3947
}
 
3948
//dptHBA_C::writeNV_RAM() - end
 
3949
 
 
3950
 
 
3951
//Function - dptHBA_C::quietBus() - start
 
3952
//===========================================================================
 
3953
//
 
3954
//Description:
 
3955
//
 
3956
//      This function quiets the SCSI bus and optionally blinks the
 
3957
//LED of this device.
 
3958
//
 
3959
//---------------------------------------------------------------------------
 
3960
 
 
3961
DPT_RTN_T       dptHBA_C::quietBus(dptBuffer_S *toEng_P)
 
3962
{
 
3963
 
 
3964
   uSHORT       blinkMode = 1;
 
3965
   uCHAR        modifier = 0x80;
 
3966
 
 
3967
if (!toEng_P->extract(blinkMode))
 
3968
   blinkMode = 0;
 
3969
 
 
3970
if (blinkMode)
 
3971
   modifier = 0xa0;
 
3972
 
 
3973
return (sendMFC(MFC_QUIET,modifier));
 
3974
 
 
3975
}
 
3976
//dptHBA_C::quietBus() - end
 
3977
 
 
3978
 
 
3979
//Function - dptHBA_C::updateLAPparams() - start
 
3980
//===========================================================================
 
3981
//
 
3982
//Description:
 
3983
//
 
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.
 
3988
//
 
3989
//---------------------------------------------------------------------------
 
3990
 
 
3991
DPT_RTN_T dptHBA_C::updateLAPparams()
 
3992
{
 
3993
 
 
3994
  // Attempt to update all logical array page data
 
3995
DPT_RTN_T retVal = dptManager_C::updateLAPparams();
 
3996
 
 
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);
 
4001
 
 
4002
return (retVal);
 
4003
 
 
4004
}
 
4005
//dptHBA_C::updateLAPparams() - end
 
4006
 
 
4007
 
 
4008
//Function - dptHBA_C::setPhyMagicNums() - start
 
4009
//===========================================================================
 
4010
//
 
4011
//Description:
 
4012
//
 
4013
//    This function attempts to set the RAID magic number of all
 
4014
//unarrayed physical DASD devices.
 
4015
//---------------------------------------------------------------------------
 
4016
void dptHBA_C::setPhyMagicNums()
 
4017
{
 
4018
 
 
4019
dptDevice_C *dev_P = (dptDevice_C *) logList.reset();
 
4020
while (dev_P) {
 
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()) {
 
4025
 
 
4026
        // Attempt to set the physical device's magic number
 
4027
         dev_P->setPhyMagicNum();
 
4028
   }
 
4029
 
 
4030
   dev_P = (dptDevice_C *) logList.next();
 
4031
 
 
4032
}
 
4033
 
 
4034
}
 
4035
//dptHBA_C::setPhyMagicNums() - end
 
4036
 
 
4037
 
 
4038
//Function - dptHBA_C::GetAccessRights - start
 
4039
//===========================================================================
 
4040
//
 
4041
//Description:
 
4042
//
 
4043
//    This function attempts to get the HBA's access rights
 
4044
//
 
4045
//---------------------------------------------------------------------------
 
4046
DPT_RTN_T dptHBA_C::GetAccessRights(dptBuffer_S *fromEng_P)
 
4047
{
 
4048
        DPT_RTN_T rtnVal = ERR_GET_CCB;
 
4049
 
 
4050
        engCCB_C *ccb_P = getCCB();
 
4051
        if (ccb_P) {    
 
4052
 
 
4053
                // target the me
 
4054
                ccb_P->target(this);
 
4055
 
 
4056
                // get the hba's portion of the rights
 
4057
                ccb_P->modeSense(0x2d);
 
4058
 
 
4059
                // send it
 
4060
                if ((rtnVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
 
4061
 
 
4062
                        dptMultiInitPage_S page;
 
4063
 
 
4064
                        // copy the hba's poritons of the access rights
 
4065
                        memcpy(&page, ccb_P->modeParam_P->getData(), page.size());
 
4066
                        page.scsiSwap();
 
4067
                        fromEng_P->insert(&page, page.size());
 
4068
 
 
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();
 
4072
 
 
4073
                        while(dev_P) {
 
4074
                                rtnVal = dev_P->GetAccessRights(fromEng_P);
 
4075
                                dev_P = (dptDevice_C *) phyList.next();
 
4076
                        }
 
4077
                }
 
4078
        }
 
4079
        return rtnVal;
 
4080
}
 
4081
 
 
4082
//Function - dptHBA_C::setPhyMagicNums() - start
 
4083
//===========================================================================
 
4084
//
 
4085
//Description:
 
4086
//
 
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)
 
4091
{
 
4092
        DPT_RTN_T rtnVal = MSG_RTN_DATA_UNDERFLOW;
 
4093
        uCHAR acquire = 0;
 
4094
 
 
4095
        dptMultiInitPage_S page;
 
4096
 
 
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;
 
4102
                }
 
4103
        }
 
4104
 
 
4105
        engCCB_C *ccb_P = getCCB();
 
4106
        if (ccb_P) {    
 
4107
 
 
4108
                // target the me
 
4109
                ccb_P->target(this);
 
4110
 
 
4111
                // get the hba's portion of the rights
 
4112
                ccb_P->modeSelect(0x2d, (uSHORT)(2+dptMultiInitPage_S::size()), (acquire >> 1) | 0x80);
 
4113
 
 
4114
                // scsi swap
 
4115
                page.scsiSwap();
 
4116
 
 
4117
                // copy the data
 
4118
                memcpy(ccb_P->modeParam_P->getData(), &page, page.size());
 
4119
 
 
4120
                // send it
 
4121
                if ((rtnVal = launchCCB(ccb_P)) == MSG_RTN_COMPLETED) {
 
4122
 
 
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();
 
4126
 
 
4127
                        while(dev_P) {
 
4128
                                toEng_P->replay();
 
4129
                                toEng_P->skip(page.size());
 
4130
                                DPT_RTN_T devRtn = dev_P->SetAccessRights(fromEng_P, toEng_P);
 
4131
 
 
4132
                                // a device returned an error, palce its tag in
 
4133
                                if (devRtn) {
 
4134
                                        fromEng_P->insert(dev_P->tag());
 
4135
                                        rtnVal = devRtn;
 
4136
                                }
 
4137
 
 
4138
                                dev_P = (dptDevice_C *) phyList.next();
 
4139
                        }
 
4140
                }
 
4141
        } else
 
4142
                rtnVal = ERR_GET_CCB;
 
4143
 
 
4144
        return rtnVal;
 
4145
}
 
4146
 
 
4147
DPT_RTN_T dptHBA_C::GetEnvironInfo(dptBuffer_S *fromEng_P)
 
4148
{
 
4149
        DPT_RTN_T rtnVal = MSG_RTN_FAILED;
 
4150
        dptHBAenviron_S info;
 
4151
        info.clear();
 
4152
 
 
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
 
4155
        // 0x4014
 
4156
        // 0x4015
 
4157
        // 0x4017
 
4158
        // 0x4018
 
4159
        // for now, set it to 0xffffffff
 
4160
 
 
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);
 
4169
 
 
4170
        // this updates the temp and volt
 
4171
        updateStatus(fromEng_P);
 
4172
        fromEng_P->reset();
 
4173
 
 
4174
        if(currVoltage != 0xffff) 
 
4175
                info.setCurVolt(currVoltage);
 
4176
        else 
 
4177
                info.setCurVolt(0xffffffff);
 
4178
                
 
4179
        if(currTemperature != 0xffff)   
 
4180
                info.setCurTemp(currTemperature);
 
4181
        else
 
4182
                info.setCurTemp(0xffffffff);
 
4183
 
 
4184
        // get the temp thresholds      
 
4185
        readNV_RAM(fromEng_P);
 
4186
        dptNVRAM_S *nv_P = (dptNVRAM_S *) &fromEng_P->data;     
 
4187
 
 
4188
        if (nv_P->getHighTemp())
 
4189
                info.setHighTempThresh((uLONG) nv_P->getHighTemp());
 
4190
        else
 
4191
                info.setHighTempThresh((uLONG) 46);
 
4192
                
 
4193
        if (nv_P->getVeryHighTemp())
 
4194
                info.setVeryHighTempThresh((uLONG) nv_P->getVeryHighTemp());
 
4195
        else
 
4196
                info.setVeryHighTempThresh((uLONG) 60);
 
4197
 
 
4198
        fromEng_P->reset();
 
4199
 
 
4200
        // give them the buffer
 
4201
        if (fromEng_P->insert(&info, info.size()))
 
4202
                rtnVal = MSG_RTN_COMPLETED;
 
4203
 
 
4204
 
 
4205
        return rtnVal;
 
4206
}
 
4207
 
 
4208
DPT_RTN_T dptHBA_C::SetEnvironInfo(dptBuffer_S *toEng_P)
 
4209
{
 
4210
        DPT_RTN_T rtnVal = MSG_RTN_FAILED;
 
4211
 
 
4212
        dptHBAenviron_S info;
 
4213
        info.clear();
 
4214
        
 
4215
        if (toEng_P->extract(&info, info.size())) {
 
4216
 
 
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);
 
4222
        }
 
4223
 
 
4224
        return rtnVal;
 
4225
}