The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hptmv/gui_lib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * 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 AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  * $FreeBSD$
   29  */
   30 /*
   31  * gui_lib.c
   32  * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved.
   33  *
   34  *  Platform independent ioctl interface implementation.
   35  *  The platform dependent part may reuse this function and/or use it own 
   36  *  implementation for each ioctl function.
   37  *
   38  *  This implementation doesn't use any synchronization; the caller must
   39  *  assure the proper context when calling these functions.
   40  */
   41  
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/malloc.h>
   46 
   47 #ifndef __KERNEL__
   48 #define __KERNEL__
   49 #endif
   50 
   51 #include <dev/hptmv/global.h>
   52 #include <dev/hptmv/hptintf.h>
   53 #include <dev/hptmv/osbsd.h>
   54 #include <dev/hptmv/access601.h>
   55 
   56 static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap);
   57 static int hpt_get_controller_count(void);
   58 static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
   59 static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
   60 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
   61 static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
   62 static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo);
   63 static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
   64 static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam);
   65 static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
   66 static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
   67 static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
   68 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
   69 static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo);
   70 
   71 int
   72 check_VDevice_valid(PVDevice p)
   73 {
   74         int i;
   75         PVDevice pVDevice;
   76         PVBus    _vbus_p;
   77         IAL_ADAPTER_T *pAdapter = gIal_Adapter;
   78         
   79         while(pAdapter != NULL)
   80         {
   81                 for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
   82                         if(&(pAdapter->VDevices[i]) == p)  return 0;
   83                 pAdapter = pAdapter->next;
   84         }
   85 
   86 #ifdef SUPPORT_ARRAY
   87         pAdapter = gIal_Adapter;
   88         while(pAdapter != NULL)
   89         {
   90                 _vbus_p = &pAdapter->VBus;
   91                 for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 
   92                 {
   93                         pVDevice=ArrayTables(i);
   94                         if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
   95                                 return 0;
   96                 }
   97                 pAdapter = pAdapter->next;
   98         }
   99 #endif
  100 
  101         return -1;
  102 }
  103 
  104 #ifdef SUPPORT_ARRAY
  105 
  106 static UCHAR get_vdev_type(PVDevice pVDevice)
  107         {
  108         switch (pVDevice->VDeviceType) {
  109                 case VD_RAID_0: return AT_RAID0;
  110                 case VD_RAID_1: return AT_RAID1;
  111                 case VD_JBOD:   return AT_JBOD;
  112                 case VD_RAID_5: return AT_RAID5;
  113                 default:        return AT_UNKNOWN;
  114         }
  115         }
  116 
  117 static DWORD get_array_flag(PVDevice pVDevice)
  118 {
  119         int i;
  120         DWORD f = 0;
  121 
  122         /* The array is disabled */
  123         if(!pVDevice->vf_online)        {
  124                 f |= ARRAY_FLAG_DISABLED;
  125                 /* Ignore other info */
  126                 return f;
  127         }
  128 
  129         /* array need synchronizing */
  130         if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
  131                 f |= ARRAY_FLAG_NEEDBUILDING;
  132 
  133         /* array is in rebuilding process */
  134         if(pVDevice->u.array.rf_rebuilding)
  135                 f |= ARRAY_FLAG_REBUILDING;
  136 
  137         /* array is being verified */
  138         if(pVDevice->u.array.rf_verifying)
  139                 f |= ARRAY_FLAG_VERIFYING;
  140 
  141         /* array is being initialized */
  142         if(pVDevice->u.array.rf_initializing)
  143                 f |= ARRAY_FLAG_INITIALIZING;
  144 
  145         /* broken but may still working */
  146         if(pVDevice->u.array.rf_broken)
  147                 f |= ARRAY_FLAG_BROKEN;
  148 
  149         /* array has a active partition */
  150         if(pVDevice->vf_bootable)
  151                 f |= ARRAY_FLAG_BOOTDISK;
  152 
  153         /* a newly created array */
  154         if(pVDevice->u.array.rf_newly_created)
  155                 f |= ARRAY_FLAG_NEWLY_CREATED;
  156 
  157         /* array has boot mark set */
  158         if(pVDevice->vf_bootmark)
  159                 f |= ARRAY_FLAG_BOOTMARK;
  160 
  161         /* auto-rebuild should start */
  162         if(pVDevice->u.array.rf_auto_rebuild)
  163                 f |= ARRAY_FLAG_NEED_AUTOREBUILD;
  164 
  165         for(i = 0; i < pVDevice->u.array.bArnMember; i++)
  166         {
  167                 PVDevice pMember = pVDevice->u.array.pMember[i];
  168                 if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
  169                         continue;
  170 
  171                 /* array need synchronizing */
  172                 if(pMember->u.array.rf_need_rebuild && 
  173                    !pMember->u.array.rf_duplicate_and_create)
  174                         f |= ARRAY_FLAG_NEEDBUILDING;
  175 
  176                 /* array is in rebuilding process */
  177                 if(pMember->u.array.rf_rebuilding)
  178                         f |= ARRAY_FLAG_REBUILDING;
  179                 
  180                 /* array is being verified */   
  181                 if(pMember->u.array.rf_verifying)
  182                         f |= ARRAY_FLAG_VERIFYING;
  183                         
  184                 /* array is being initialized */
  185                 if(pMember->u.array.rf_initializing)
  186                         f |= ARRAY_FLAG_INITIALIZING;
  187 
  188                 /* broken but may still working */
  189                 if(pMember->u.array.rf_broken)
  190                         f |= ARRAY_FLAG_BROKEN;
  191 
  192                 /* a newly created array */
  193                 if(pMember->u.array.rf_newly_created)
  194                         f |= ARRAY_FLAG_NEWLY_CREATED;
  195 
  196                 /* auto-rebuild should start */
  197                 if(pMember->u.array.rf_auto_rebuild)
  198                         f |= ARRAY_FLAG_NEED_AUTOREBUILD;
  199         }
  200 
  201         return f;
  202 }
  203 
  204 static DWORD calc_rebuild_progress(PVDevice pVDevice)
  205 {
  206         int i;
  207         DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 /
  208                 (ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
  209 
  210         for(i = 0; i < pVDevice->u.array.bArnMember; i++)
  211         {
  212                 PVDevice pMember = pVDevice->u.array.pMember[i];
  213                 if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
  214                         continue;
  215 
  216                 /* for RAID1/0 case */
  217                 if (pMember->u.array.rf_rebuilding || 
  218                         pMember->u.array.rf_verifying ||
  219                         pMember->u.array.rf_initializing)
  220                 {
  221                         DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 /
  222                                 (ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
  223                         if (result==0 || result>percent)
  224                                 result = percent;
  225                 }
  226                 }
  227 
  228         if (result>10000) result = 10000;
  229         return result;
  230         }
  231         
  232 static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo)
  233 {
  234         int     i;
  235 
  236         memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
  237         pArrayInfo->ArrayType = get_vdev_type(pVDevice);
  238         pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
  239         pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors;
  240         pArrayInfo->Flags = get_array_flag(pVDevice);
  241         pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
  242 
  243         pArrayInfo->nDisk = 0;
  244 
  245         for(i = 0; i < pVDevice->u.array.bArnMember; i++)
  246                 if(pVDevice->u.array.pMember[i] != NULL)
  247                         pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
  248 
  249         for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS; i++)
  250                 pArrayInfo->Members[i] = INVALID_DEVICEID;
  251         }
  252 
  253 static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
  254 {
  255         int     i;
  256 
  257         memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN);
  258         pArrayInfo->ArrayType = get_vdev_type(pVDevice);
  259         pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
  260         pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors;
  261         pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0;
  262         pArrayInfo->Flags = get_array_flag(pVDevice);
  263         pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
  264 
  265         pArrayInfo->nDisk = 0;
  266 
  267         for(i = 0; i < pVDevice->u.array.bArnMember; i++)
  268                 if(pVDevice->u.array.pMember[i] != NULL)
  269                         pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
  270 
  271         for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS_V2; i++)
  272                 pArrayInfo->Members[i] = INVALID_DEVICEID;
  273 }
  274 #endif
  275 
  276 static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo)
  277 {
  278         MV_SATA_ADAPTER *pSataAdapter;
  279         MV_SATA_CHANNEL *pSataChannel;
  280         IAL_ADAPTER_T   *pAdapter;
  281         MV_CHANNEL              *channelInfo;
  282         char *p;
  283         int i;
  284 
  285         /* device location */
  286         pSataChannel = pVDevice->u.disk.mv;
  287         if(pSataChannel == NULL)        return -1;      
  288         pDiskInfo->TargetId = 0;
  289         pSataAdapter = pSataChannel->mvSataAdapter;
  290         if(pSataAdapter == NULL)        return -1;
  291 
  292         pAdapter = pSataAdapter->IALData;
  293 
  294         pDiskInfo->PathId = pSataChannel->channelNumber;
  295         pDiskInfo->ControllerId = (UCHAR)pSataAdapter->adapterId;
  296 
  297 /*GUI uses DeviceModeSetting to display to users
  298 (1) if users select a mode, GUI/BIOS should display that mode.
  299 (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied.
  300 (3) display real mode if case (1)&&(2) not satisfied.
  301 */
  302         if (pVDevice->u.disk.df_user_mode_set)
  303                 pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
  304         else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2)
  305                 pDiskInfo->DeviceModeSetting = 15;
  306         else {
  307                 p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
  308                 if (*(WORD*)p==(0x5354) /*'ST'*/ &&
  309                         (*(WORD*)(p+8)==(0x4153)/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
  310                         pDiskInfo->DeviceModeSetting = 15;
  311                 else
  312                         pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
  313         }
  314                 
  315         pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode;
  316 
  317         pDiskInfo->DeviceType = PDT_HARDDISK;
  318 
  319         pDiskInfo->Flags = 0x0;
  320 
  321         /* device is disabled */
  322         if(!pVDevice->u.disk.df_on_line)
  323                 pDiskInfo->Flags |= DEVICE_FLAG_DISABLED;
  324 
  325         /* disk has a active partition */
  326         if(pVDevice->vf_bootable)
  327                 pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK;
  328 
  329         /* disk has boot mark set */
  330         if(pVDevice->vf_bootmark)
  331                 pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK;
  332 
  333         pDiskInfo->Flags |= DEVICE_FLAG_SATA;
  334 
  335         /* is a spare disk */
  336         if(pVDevice->VDeviceType == VD_SPARE)
  337                 pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE;
  338 
  339         memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
  340         p = (char *)&pDiskInfo->IdentifyData.ModelNumber;
  341         for (i = 0; i < 20; i++)
  342                 ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
  343         p[39] = '\0';
  344 
  345         channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber];
  346         pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported;
  347         pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled;
  348         pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported;
  349         pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled;
  350         pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0;
  351         pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED;
  352         pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) &&
  353                 (pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100));
  354         pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING;
  355         return 0;
  356 }
  357 
  358 int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)
  359 {
  360         ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES));
  361         cap->dwSize = sizeof(DRIVER_CAPABILITIES);
  362         cap->MaximumControllers = MAX_VBUS;
  363 
  364         /* cap->SupportCrossControllerRAID = 0; */
  365         /* take care for various OSes! */
  366         cap->SupportCrossControllerRAID = 0;
  367 
  368 
  369         cap->MinimumBlockSizeShift = MinBlockSizeShift;
  370         cap->MaximumBlockSizeShift = MaxBlockSizeShift;
  371         cap->SupportDiskModeSetting = 0;
  372         cap->SupportSparePool = 1;              
  373         cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1;
  374         cap->SupportDedicatedSpare = 0;
  375         
  376 
  377 #ifdef SUPPORT_ARRAY
  378         /* Stripe */
  379         cap->SupportedRAIDTypes[0] = AT_RAID0;
  380         cap->MaximumArrayMembers[0] = MAX_MEMBERS;
  381         /* Mirror */
  382         cap->SupportedRAIDTypes[1] = AT_RAID1;
  383         cap->MaximumArrayMembers[1] = 2;
  384         /* Mirror + Stripe */
  385 #ifdef ARRAY_V2_ONLY
  386         cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */
  387 #else 
  388         cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */
  389 #endif
  390         cap->MaximumArrayMembers[2] = MAX_MEMBERS;
  391         /* Jbod */
  392         cap->SupportedRAIDTypes[3] = AT_JBOD;
  393         cap->MaximumArrayMembers[3] = MAX_MEMBERS;
  394         /* RAID5 */
  395 #if SUPPORT_RAID5
  396         cap->SupportedRAIDTypes[4] = AT_RAID5;
  397         cap->MaximumArrayMembers[4] = MAX_MEMBERS;
  398 #endif
  399 #endif
  400         return 0;
  401 }
  402 
  403 int hpt_get_controller_count(void)
  404 {
  405         IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
  406         int iControllerCount = 0;
  407         
  408         while(pAdapTemp != NULL)
  409         {                
  410                 iControllerCount++;
  411                 pAdapTemp = pAdapTemp->next;
  412         }
  413         
  414         return iControllerCount;
  415 }
  416 
  417 int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
  418 {
  419         IAL_ADAPTER_T    *pAdapTemp;
  420         int iControllerCount = 0;
  421 
  422         for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
  423                 if (iControllerCount++==id) {
  424                         pInfo->InterruptLevel = 0;
  425                         pInfo->ChipType = 0;
  426                         pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100;
  427                         strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc.");
  428 #ifdef GUI_CONTROLLER_NAME
  429 #ifdef FORCE_ATA150_DISPLAY
  430                         /* show "Bus Type: ATA/150" in GUI for SATA controllers */
  431                         pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150;
  432 #endif
  433                         strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME);
  434 #define _set_product_id(x)
  435 #else 
  436 #define _set_product_id(x) strcpy(pInfo->szProductID, x)
  437 #endif
  438                         _set_product_id("RocketRAID 18xx SATA Controller");                     
  439                         pInfo->NumBuses = 8;
  440                         pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
  441                         return 0;
  442                 }
  443         }
  444         return -1;
  445 }
  446 
  447 
  448 int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo)
  449 {
  450         IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
  451         int i,iControllerCount = 0;
  452 
  453         while(pAdapTemp != NULL)
  454         {
  455                 if (iControllerCount++==id) 
  456                         goto found;
  457                 pAdapTemp = pAdapTemp->next;
  458         }
  459         return -1;
  460 
  461 found:
  462         
  463         pInfo->IoPort = 0;
  464         pInfo->ControlPort = 0;
  465         
  466         for (i=0; i<2 ;i++)
  467         {
  468                 pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
  469         }
  470 
  471         if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
  472                 pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
  473         else
  474                 pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
  475 
  476         return 0;
  477         
  478 
  479 }
  480 
  481 int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
  482 {
  483         int count = 0;
  484         int     i,j;
  485         PVDevice pPhysical, pLogical;
  486         IAL_ADAPTER_T    *pAdapTemp;
  487 
  488         for(i = 0; i < nMaxCount; i++)
  489                 pIds[i] = INVALID_DEVICEID;
  490 
  491         /* append the arrays not registered on VBus */
  492         for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
  493                 for(i = 0; i < MV_SATA_CHANNELS_NUM; i++)
  494                 {
  495                         pPhysical = &pAdapTemp->VDevices[i];
  496                         pLogical = pPhysical;
  497                         
  498                         while (pLogical->pParent) pLogical = pLogical->pParent;
  499                         if (pLogical->VDeviceType==VD_SPARE)
  500                                 continue;
  501                         
  502                         for (j=0; j<count; j++)
  503                                 if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
  504                         pIds[count++] = VDEV_TO_ID(pLogical);
  505                         if (count>=nMaxCount) goto done;
  506                         next:;
  507                 }
  508         }
  509 
  510 done:
  511         return count;
  512 }
  513 
  514 int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
  515 {
  516         PVDevice pVDevice = ID_TO_VDEV(id);
  517 
  518         if((id == 0) || check_VDevice_valid(pVDevice))
  519                 return -1;
  520 
  521 #ifdef SUPPORT_ARRAY
  522         if (mIsArray(pVDevice)) {
  523                 pInfo->Type = LDT_ARRAY;
  524                 pInfo->Capacity = pVDevice->VDeviceCapacity;
  525                 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
  526                 get_array_info(pVDevice, &pInfo->u.array);
  527                 return 0;
  528         }
  529 #endif
  530 
  531         pInfo->Type = LDT_DEVICE;
  532         pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
  533         /* report real capacity to be compatible with old arrays */
  534         pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
  535         return get_disk_info(pVDevice, &pInfo->u.device);
  536 }
  537 
  538 int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo)
  539 {
  540         PVDevice pVDevice = ID_TO_VDEV(id);
  541 
  542         if((id == 0) || check_VDevice_valid(pVDevice))
  543                 return -1;
  544 
  545 #ifdef SUPPORT_ARRAY
  546         if (mIsArray(pVDevice)) {
  547                 pInfo->Type = LDT_ARRAY;
  548                 pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity;
  549                 pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0;
  550                 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
  551                 get_array_info_v2(pVDevice, &pInfo->u.array);
  552         return 0;
  553 }
  554 #endif
  555 
  556         pInfo->Type = LDT_DEVICE;
  557         pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
  558         /* report real capacity to be compatible with old arrays */
  559         pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity;
  560         pInfo->Capacity.hi32 = 0;
  561         return get_disk_info(pVDevice, &pInfo->u.device);
  562 }
  563 
  564 #ifdef SUPPORT_ARRAY
  565 DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)
  566 {
  567         ULONG Stamp = GetStamp();
  568         int     i,j;
  569         LBA_T  capacity = MAX_LBA_T;
  570         PVDevice pArray,pChild;
  571         int             Loca = -1;
  572 
  573         if (pParam->nDisk > MAX_MEMBERS)
  574                 return INVALID_DEVICEID;
  575 /* check in verify_vd
  576         for(i = 0; i < pParam->nDisk; i++)
  577         {
  578                 PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
  579                 if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID;
  580                 if (mIsArray(pVDev)) return INVALID_DEVICEID;
  581                 if (!pVDev->vf_online) return INVALID_DEVICEID;
  582                 if (!_vbus_p)
  583                         _vbus_p = pVDev->u.disk.pVBus;
  584                 else if (_vbus_p != pVDev->u.disk.pVBus)
  585                         return INVALID_DEVICEID;
  586         }
  587 */
  588         _vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus;
  589         if (!_vbus_p) return INVALID_DEVICEID;
  590 
  591         mArGetArrayTable(pArray);
  592         if(!pArray)     return INVALID_DEVICEID;
  593 
  594         switch (pParam->ArrayType)
  595         {
  596                 case AT_JBOD:
  597                         pArray->VDeviceType = VD_JBOD;
  598                         goto simple;
  599 
  600                 case AT_RAID0:
  601                         if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
  602                                 goto error;
  603                         pArray->VDeviceType = VD_RAID_0;
  604                         goto simple;
  605 
  606                 case AT_RAID5:
  607                         if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
  608                                 goto error;
  609                         pArray->VDeviceType = VD_RAID_5;
  610                         /* only "no build" R5 is not critical after creation. */
  611                         if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0)
  612                                 pArray->u.array.rf_need_rebuild = 1;
  613                         goto simple;
  614 
  615                 case AT_RAID1:
  616                         if(pParam->nDisk <= 2)
  617                         {
  618                                 pArray->VDeviceType = VD_RAID_1;
  619 simple:
  620                                 pArray->u.array.bArnMember = pParam->nDisk;
  621                                 pArray->u.array.bArRealnMember = pParam->nDisk;
  622                                 pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
  623                                 pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
  624                                 pArray->u.array.dArStamp = Stamp;
  625 
  626                                 pArray->u.array.rf_need_sync = 1;
  627                                 pArray->u.array.rf_newly_created = 1;
  628 
  629                                 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && 
  630                                         (pArray->VDeviceType == VD_RAID_1))
  631                                 {
  632                                         pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */
  633                                         pArray->u.array.rf_need_rebuild = 1;
  634                                         pArray->u.array.rf_auto_rebuild = 1;
  635                                         pArray->u.array.rf_duplicate_and_create = 1;
  636 
  637                                         for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
  638                                                 if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0]))
  639                                                         Loca = i;
  640                                 }
  641                                 
  642                                 pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T;
  643 
  644                                 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
  645 
  646                                 for(i = 0; i < pParam->nDisk; i++)
  647                                 {
  648                                         pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]);
  649                                         pArray->u.array.pMember[i]->bSerialNumber = i;
  650                                         pArray->u.array.pMember[i]->pParent = pArray;
  651 
  652                                         /* don't unregister source disk for duplicate RAID1 */
  653                                         if (i ||
  654                                                 pArray->VDeviceType!=VD_RAID_1 ||
  655                                                 (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0)
  656                                                 UnregisterVDevice(pArray->u.array.pMember[i]);
  657 
  658                                         if(pArray->VDeviceType == VD_RAID_5)
  659                                                 pArray->u.array.pMember[i]->vf_cache_disk = 1;
  660                                 }
  661                         }
  662                         else
  663                         {
  664                                 for(i = 0; i < (pParam->nDisk / 2); i++)
  665                                 {
  666                                         mArGetArrayTable(pChild);
  667                                         pChild->VDeviceType = VD_RAID_1;
  668 
  669                                         pChild->u.array.bArnMember = 2;
  670                                         pChild->u.array.bArRealnMember = 2;
  671                                         pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
  672                                         pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
  673                                         pChild->u.array.dArStamp = Stamp;
  674 
  675                                         pChild->u.array.rf_need_sync = 1;
  676                                         pChild->u.array.rf_newly_created = 1;
  677 
  678                                         pChild->u.array.RebuildSectors = MAX_LBA_T;     
  679                                         
  680                                         memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
  681 
  682                                         for(j = 0; j < 2; j++)
  683                                         {
  684                                                 pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]);
  685                                                 pChild->u.array.pMember[j]->bSerialNumber = j;
  686                                                 pChild->u.array.pMember[j]->pParent = pChild;
  687                                                 pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType];
  688                                                 UnregisterVDevice(pChild->u.array.pMember[j]);
  689                                         }
  690 
  691                                         pArray->u.array.pMember[i] = pChild;
  692 
  693                                         pChild->vf_online = 1;
  694                                         pChild->bSerialNumber = i;
  695                                         pChild->pParent = pArray;
  696                                         pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity,
  697                                                 pChild->u.array.pMember[1]->VDeviceCapacity);
  698 
  699                                         pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType];
  700                                         pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0];
  701                                 }
  702 
  703                                 pArray->VDeviceType = VD_RAID_0;
  704 
  705                                 pArray->u.array.bArnMember = pParam->nDisk / 2;
  706                                 pArray->u.array.bArRealnMember = pParam->nDisk / 2;
  707                                 pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
  708                                 pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
  709                                 pArray->u.array.dArStamp = Stamp;
  710 
  711                                 pArray->u.array.rf_need_sync = 1;
  712                                 pArray->u.array.rf_newly_created = 1;
  713 
  714                                 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
  715                         }
  716                         break;
  717 
  718                 default:
  719                         goto error;
  720         }
  721 
  722         for(i = 0; i < pArray->u.array.bArnMember; i++)
  723                 pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
  724 
  725         if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && 
  726                 (pArray->VDeviceType == VD_RAID_1))
  727         {
  728                 pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark;
  729                 pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable;
  730                 pArray->u.array.pMember[0]->vf_bootable = 0;
  731                 pArray->u.array.pMember[0]->vf_bootmark = 0;
  732                 if (Loca>=0) {
  733                         _vbus_p->pVDevice[Loca] = pArray;
  734                         /* to comfort OS */
  735                         pArray->u.array.rf_duplicate_and_created = 1;
  736                         pArray->pVBus = _vbus_p;
  737                 }
  738         }
  739         else {
  740                 UCHAR TempBuffer[512];
  741                 ZeroMemory(TempBuffer, 512);
  742                 for(i = 0; i < pParam->nDisk; i++)
  743                 {
  744                         PVDevice        pDisk = ID_TO_VDEV(pParam->Members[i]);
  745                         pDisk->vf_bootmark = pDisk->vf_bootable = 0;
  746                         fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer);
  747                 }
  748         }
  749 
  750         pArray->vf_online = 1;
  751         pArray->pParent = NULL;
  752 
  753         switch(pArray->VDeviceType)
  754         {
  755                 case VD_RAID_0:
  756                         for(i = 0; i < pArray->u.array.bArnMember; i++)
  757                                 if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
  758                                         capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
  759 #ifdef ARRAY_V2_ONLY
  760                         capacity -= 10;
  761 #endif
  762                         capacity &= ~(pArray->u.array.bStripeWitch - 1);
  763                         /* shrink member capacity for RAID 1/0 */
  764                         for(i = 0; i < pArray->u.array.bArnMember; i++)
  765                                 if (mIsArray(pArray->u.array.pMember[i]))
  766                                         pArray->u.array.pMember[i]->VDeviceCapacity = capacity;
  767                         pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember;
  768                         break;
  769 
  770                 case VD_RAID_1:
  771                         pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity,
  772                                                 pArray->u.array.pMember[1]->VDeviceCapacity);
  773                         break;
  774 
  775                 case VD_JBOD:
  776                         for(i = 0; i < pArray->u.array.bArnMember; i++)
  777                                 pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity
  778 #ifdef ARRAY_V2_ONLY
  779                                 -10
  780 #endif
  781                                 ;
  782                         break;
  783 
  784                 case VD_RAID_5:
  785                         for(i = 0; i < pArray->u.array.bArnMember; i++)
  786                                 if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
  787                                         capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
  788                         pArray->VDeviceCapacity = rounddown2(capacity, pArray->u.array.bStripeWitch) *
  789                             (pArray->u.array.bArnMember - 1);
  790                         break;
  791 
  792                 default:
  793                         goto error;
  794         }
  795 
  796         pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
  797         pArray->pfnDeviceFailed = fOsDiskFailed;
  798         SyncArrayInfo(pArray);
  799 
  800         if (!pArray->u.array.rf_duplicate_and_created)
  801                 RegisterVDevice(pArray);
  802         return VDEV_TO_ID(pArray);
  803 
  804 error:
  805         for(i = 0; i < pArray->u.array.bArnMember; i++)
  806         {
  807                 pChild = pArray->u.array.pMember[i];
  808                 if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
  809                         mArFreeArrayTable(pChild);
  810         }
  811         mArFreeArrayTable(pArray);
  812         return INVALID_DEVICEID;
  813 }
  814 
  815 DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
  816 {
  817         CREATE_ARRAY_PARAMS_V2 param2;
  818         param2.ArrayType = pParam->ArrayType;
  819         param2.nDisk = pParam->nDisk;
  820         param2.BlockSizeShift = pParam->BlockSizeShift;
  821         param2.CreateFlags = pParam->CreateFlags;
  822         param2.CreateTime = pParam->CreateTime;
  823         memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName));
  824         memcpy(param2.Description, pParam->Description, sizeof(param2.Description));
  825         memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager));
  826         param2.Capacity.lo32 = param2.Capacity.hi32 = 0;
  827         memcpy(param2.Members, pParam->Members, sizeof(pParam->Members));
  828         return hpt_create_array_v2(_VBUS_P &param2);
  829 }
  830 
  831 #ifdef SUPPORT_OLD_ARRAY
  832 /* this is only for old RAID 0/1 */
  833 int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
  834 {
  835         PVDevice pArray1 = ID_TO_VDEV(idArray);
  836         PVDevice pArray2 = 0;
  837         PVDevice pDisk  = ID_TO_VDEV(idDisk);
  838         int     i;
  839         IAL_ADAPTER_T *pAdapter = gIal_Adapter;
  840 
  841         if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
  842         
  843         if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2))
  844                 return -1;
  845                 
  846         pArray2 = pArray1->u.array.pMember[1];
  847         if(pArray2 == NULL)     {
  848                 /* create a Stripe */           
  849                 mArGetArrayTable(pArray2);
  850                 pArray2->VDeviceType = VD_RAID_0;
  851                 pArray2->u.array.dArStamp = GetStamp();
  852                 pArray2->vf_format_v2 = 1;      
  853                 pArray2->u.array.rf_broken = 1; 
  854                 pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift;
  855                 pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift);
  856                 pArray2->u.array.bArnMember = 2;
  857                 pArray2->VDeviceCapacity = pArray1->VDeviceCapacity;
  858                 pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType];
  859                 pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType];
  860                 memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME);                 
  861                 pArray2->pParent = pArray1;
  862                 pArray2->bSerialNumber = 1;
  863                 pArray1->u.array.pMember[1] = pArray2;                  
  864                 pArray1->u.array.bArRealnMember++;                                              
  865         }
  866         
  867         for(i = 0; i < pArray2->u.array.bArnMember; i++)
  868                 if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online)
  869                 {
  870                         if(pArray2->u.array.pMember[i] != NULL)
  871                                 pArray2->u.array.pMember[i]->pParent = NULL;
  872                         pArray2->u.array.pMember[i] = pDisk;
  873                         goto find;
  874                 }
  875         return -1;
  876         
  877 find:
  878         UnregisterVDevice(pDisk);
  879         pDisk->VDeviceType = VD_SINGLE_DISK;
  880         pDisk->bSerialNumber = i;
  881         pDisk->pParent = pArray2;
  882         pDisk->vf_format_v2 = 1;        
  883         pDisk->u.disk.dDeHiddenLba = i? 10 : 0;
  884         pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
  885         pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType];
  886 
  887         pArray2->u.array.bArRealnMember++;
  888         if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){                             
  889                 pArray2->vf_online = 1;
  890                 pArray2->u.array.rf_broken = 0;
  891         }       
  892         
  893         if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){
  894                 pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember;
  895                 pArray1->u.array.rf_broken = 0;
  896                 pArray1->u.array.rf_need_rebuild = 1;           
  897                 pArray1->u.array.rf_auto_rebuild = 1;
  898                 
  899         }
  900         pArray1->u.array.RebuildSectors = 0;
  901         pArray1->u.array.dArStamp = GetStamp();
  902         SyncArrayInfo(pArray1);
  903         return 1;       
  904 }
  905 #endif
  906 
  907 int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
  908 {
  909         int     i;
  910 
  911         LBA_T Capacity;
  912         PVDevice pArray = ID_TO_VDEV(idArray);
  913         PVDevice pDisk  = ID_TO_VDEV(idDisk);
  914 
  915         if((idArray == 0) || (idDisk == 0))     return -1;
  916         if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk))   return -1;
  917         if(!pArray->u.array.rf_broken)  return -1;
  918 
  919         if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
  920                 return -1;
  921         if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE))
  922                 return -1;
  923 
  924 #ifdef SUPPORT_OLD_ARRAY
  925         /* RAID 0 + 1 */
  926         if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 && 
  927                 pArray->u.array.pMember[0] &&
  928                 mIsArray(pArray->u.array.pMember[0]))
  929         {
  930                 if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk))
  931                         return 0;
  932                 else 
  933                         return -1;
  934         }
  935 #endif
  936 
  937         Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
  938 
  939         if (pArray->vf_format_v2) {
  940                 if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1;
  941         }
  942         else
  943                 if(pDisk->VDeviceCapacity < Capacity) return -1;
  944         
  945         if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
  946 
  947         for(i = 0; i < pArray->u.array.bArnMember; i++)
  948                 if((pArray->u.array.pMember[i] == 0) || !pArray->u.array.pMember[i]->vf_online)
  949                 {
  950                         if(pArray->u.array.pMember[i] != NULL)
  951                                 pArray->u.array.pMember[i]->pParent = NULL;
  952                         pArray->u.array.pMember[i] = pDisk;
  953                         goto find;
  954                 }
  955         return -1;
  956 
  957 find:
  958         UnregisterVDevice(pDisk);
  959         pDisk->VDeviceType = VD_SINGLE_DISK;
  960         pDisk->bSerialNumber = i;
  961         pDisk->pParent = pArray;
  962         if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1;
  963         pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
  964         if (pArray->vf_format_v2) {
  965                 pDisk->vf_format_v2 = 1;
  966                 pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
  967         }
  968 
  969         pArray->u.array.bArRealnMember++;
  970         if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember)
  971         {
  972                 pArray->u.array.rf_need_rebuild = 1;
  973                 pArray->u.array.RebuildSectors = 0;
  974                 pArray->u.array.rf_auto_rebuild = 1;
  975                 pArray->u.array.rf_broken = 0;
  976         }
  977         pArray->u.array.RebuildSectors = 0;
  978 
  979         /* sync the whole array */
  980         while (pArray->pParent) pArray = pArray->pParent;
  981         pArray->u.array.dArStamp = GetStamp();
  982         SyncArrayInfo(pArray);
  983         return 0;
  984 }
  985 
  986 int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)
  987 {
  988         PVDevice pVDevice = ID_TO_VDEV(idDisk);
  989         DECLARE_BUFFER(PUCHAR, pbuffer);
  990 
  991         if(idDisk == 0 || check_VDevice_valid(pVDevice))        return -1;
  992         if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent)
  993                 return -1;
  994 
  995         if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
  996 
  997         UnregisterVDevice(pVDevice);
  998         pVDevice->VDeviceType = VD_SPARE;
  999         pVDevice->vf_bootmark = 0;
 1000 
 1001         ZeroMemory((char *)pbuffer, 512);
 1002         fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer);
 1003         SyncArrayInfo(pVDevice);
 1004         return 0;
 1005 }
 1006 
 1007 int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)
 1008 {
 1009         PVDevice pVDevice = ID_TO_VDEV(idDisk);
 1010 
 1011         if(idDisk == 0 || check_VDevice_valid(pVDevice))        return -1;
 1012 
 1013         if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
 1014 
 1015         pVDevice->VDeviceType = VD_SINGLE_DISK;
 1016 
 1017         SyncArrayInfo(pVDevice);
 1018         RegisterVDevice(pVDevice);
 1019         return 0;
 1020 }
 1021 
 1022 int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
 1023 {
 1024         PVDevice pVDevice = ID_TO_VDEV(idArray);
 1025 
 1026         if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
 1027         if (!mIsArray(pVDevice)) return -1;
 1028 
 1029         /* if the pVDevice isn't a top level, return -1; */
 1030         if(pVDevice->pParent != NULL) return -1;
 1031 
 1032         if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
 1033 
 1034         if (pInfo->ValidFields & AAIF_NAME) {
 1035                 memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME);
 1036                 memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name));
 1037                 pVDevice->u.array.rf_need_sync = 1;
 1038         }
 1039 
 1040         if (pInfo->ValidFields & AAIF_DESCRIPTION) {
 1041                 memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description));
 1042                 pVDevice->u.array.rf_need_sync = 1;
 1043         }
 1044 
 1045         if (pVDevice->u.array.rf_need_sync)
 1046                 SyncArrayInfo(pVDevice);
 1047         return 0;
 1048 }
 1049 
 1050 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
 1051 {
 1052         PVDevice pVDevice = ID_TO_VDEV(idDisk);
 1053 
 1054         if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
 1055         if (mIsArray(pVDevice))
 1056                 return -1;
 1057 
 1058         if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
 1059 
 1060         /* TODO */
 1061                 return 0;
 1062         }
 1063         
 1064 static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo)
 1065 {
 1066         PVDevice pVDevice = ID_TO_VDEV(idDisk);
 1067         int sync = 0;
 1068 
 1069         if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1;
 1070         if (mIsArray(pVDevice))
 1071                 return -1;
 1072 
 1073         if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
 1074 
 1075         if (pInfo->ValidFields & ADIF_MODE) {
 1076                 pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
 1077                 pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
 1078                 pVDevice->u.disk.df_user_mode_set = 1;
 1079                 fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
 1080                 sync = 1;
 1081 }
 1082 
 1083         if (pInfo->ValidFields & ADIF_TCQ) {
 1084                 if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) {
 1085                         pVDevice->u.disk.df_tcq_set = 1;
 1086                         pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0;
 1087                         sync = 1;
 1088 }
 1089         }
 1090 
 1091         if (pInfo->ValidFields & ADIF_NCQ) {
 1092                 if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) {
 1093                         pVDevice->u.disk.df_ncq_set = 1;
 1094                         pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0;
 1095                         sync = 1;
 1096         }
 1097         }
 1098 
 1099         if (pInfo->ValidFields & ADIF_WRITE_CACHE) {
 1100                 if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) {
 1101                         pVDevice->u.disk.df_write_cache_set = 1;
 1102                         pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0;
 1103                         sync = 1;
 1104         }
 1105         }
 1106                 
 1107         if (pInfo->ValidFields & ADIF_READ_AHEAD) {
 1108                 if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) {
 1109                         pVDevice->u.disk.df_read_ahead_set = 1;
 1110                         pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0;
 1111                         sync = 1;
 1112                 }
 1113         }
 1114 
 1115         if (sync)
 1116                 SyncArrayInfo(pVDevice);
 1117         return 0;
 1118 }
 1119 
 1120 #endif
 1121 
 1122 /* hpt_default_ioctl()
 1123  *  This is a default implementation. The platform dependent part
 1124  *  may reuse this function and/or use it own implementation for
 1125  *  each ioctl function.
 1126  */
 1127 int hpt_default_ioctl(_VBUS_ARG
 1128                                                         DWORD dwIoControlCode,          /* operation control code */
 1129                                                         PVOID lpInBuffer,               /* input data buffer */
 1130                                                         DWORD nInBufferSize,            /* size of input data buffer */
 1131                                                         PVOID lpOutBuffer,              /* output data buffer */
 1132                                                         DWORD nOutBufferSize,           /* size of output data buffer */
 1133                                                         PDWORD lpBytesReturned          /* byte count */
 1134                                         )
 1135 {
 1136         switch(dwIoControlCode) {
 1137 
 1138         case HPT_IOCTL_GET_VERSION:
 1139 
 1140                 if (nInBufferSize != 0) return -1;
 1141                 if (nOutBufferSize != sizeof(DWORD)) return -1;
 1142                 *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION;
 1143                 break;
 1144 
 1145         case HPT_IOCTL_GET_CONTROLLER_COUNT:
 1146 
 1147                 if (nOutBufferSize!=sizeof(DWORD)) return -1;
 1148                 *(PDWORD)lpOutBuffer = hpt_get_controller_count();
 1149                 break;
 1150 
 1151         case HPT_IOCTL_GET_CONTROLLER_INFO:
 1152                 {
 1153                         int id;
 1154                         PCONTROLLER_INFO pInfo;
 1155         
 1156                         if (nInBufferSize!=sizeof(DWORD)) return -1;
 1157                         if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1;
 1158         
 1159                         id = *(DWORD *)lpInBuffer;
 1160                         pInfo = (PCONTROLLER_INFO)lpOutBuffer;
 1161                         if (hpt_get_controller_info(id, pInfo)!=0)
 1162                                 return -1;
 1163                 }
 1164                 break;
 1165 
 1166         case HPT_IOCTL_GET_CHANNEL_INFO:
 1167                 {
 1168                         int id, bus;
 1169                         PCHANNEL_INFO pInfo;
 1170 
 1171                         if (nInBufferSize!=8) return -1;
 1172                         if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1;
 1173 
 1174                         id = *(DWORD *)lpInBuffer;
 1175                         bus = ((DWORD *)lpInBuffer)[1];
 1176                         pInfo = (PCHANNEL_INFO)lpOutBuffer;
 1177 
 1178                         if (hpt_get_channel_info(id, bus, pInfo)!=0)
 1179                                 return -1;
 1180                 }
 1181                 break;
 1182 
 1183         case HPT_IOCTL_GET_LOGICAL_DEVICES:
 1184                 {
 1185                         DWORD nMax;
 1186                         DEVICEID *pIds;
 1187 
 1188                         if (nInBufferSize!=sizeof(DWORD)) return -1;
 1189                         nMax = *(DWORD *)lpInBuffer;
 1190                         if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1;
 1191 
 1192                         pIds = ((DEVICEID *)lpOutBuffer)+1;
 1193                         *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax);
 1194                 }
 1195                 break;
 1196 
 1197         case HPT_IOCTL_GET_DEVICE_INFO:
 1198                 {
 1199                         DEVICEID id;
 1200                         PLOGICAL_DEVICE_INFO pInfo;
 1201 
 1202                         if (nInBufferSize!=sizeof(DEVICEID)) return -1;
 1203                         if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1;
 1204 
 1205                         id = *(DWORD *)lpInBuffer;
 1206                         if (id == INVALID_DEVICEID)     return -1;
 1207 
 1208                         pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer;
 1209                         memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO));
 1210 
 1211                         if (hpt_get_device_info(id, pInfo)!=0)
 1212                                 return -1;
 1213                 }
 1214                 break;
 1215 
 1216         case HPT_IOCTL_GET_DEVICE_INFO_V2:
 1217                 {
 1218                         DEVICEID id;
 1219                         PLOGICAL_DEVICE_INFO_V2 pInfo;
 1220 
 1221                         if (nInBufferSize!=sizeof(DEVICEID)) return -1;
 1222                         if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1;
 1223 
 1224                         id = *(DWORD *)lpInBuffer;
 1225                         if (id == INVALID_DEVICEID)     return -1;
 1226 
 1227                         pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer;
 1228                         memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2));
 1229 
 1230                         if (hpt_get_device_info_v2(id, pInfo)!=0)
 1231                                 return -1;
 1232                 }
 1233                 break;
 1234 
 1235 #ifdef SUPPORT_ARRAY
 1236         case HPT_IOCTL_CREATE_ARRAY:
 1237                 {
 1238                         if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
 1239                         if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
 1240 
 1241                         *(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer);
 1242 
 1243                         if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
 1244                                 return -1;
 1245                 }
 1246                 break;
 1247 
 1248         case HPT_IOCTL_CREATE_ARRAY_V2:
 1249                 {
 1250                         if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1;
 1251                         if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
 1252 
 1253                         *(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer);
 1254 
 1255                         if (*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
 1256                                 return -1;
 1257                 }
 1258                 break;
 1259 
 1260         case HPT_IOCTL_SET_ARRAY_INFO:
 1261                 {
 1262                         DEVICEID idArray;
 1263                         PALTERABLE_ARRAY_INFO pInfo;
 1264 
 1265                         if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1;
 1266                         if (nOutBufferSize!=0) return -1;
 1267 
 1268                         idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray;
 1269                         pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info;
 1270 
 1271                         if(hpt_set_array_info(_VBUS_P idArray,  pInfo))
 1272                                 return -1;
 1273                 }
 1274                 break;
 1275 
 1276         case HPT_IOCTL_SET_DEVICE_INFO:
 1277                 {
 1278                         DEVICEID idDisk;
 1279                         PALTERABLE_DEVICE_INFO pInfo;
 1280 
 1281                         if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1;
 1282                         if (nOutBufferSize!=0) return -1;
 1283 
 1284                         idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk;
 1285                         pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info;
 1286                         if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0)
 1287                                 return -1;
 1288                 }
 1289                 break;
 1290 
 1291         case HPT_IOCTL_SET_DEVICE_INFO_V2:
 1292                 {
 1293                         DEVICEID idDisk;
 1294                         PALTERABLE_DEVICE_INFO_V2 pInfo;
 1295 
 1296                         if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1;
 1297                         if (nOutBufferSize!=0) return -1;
 1298 
 1299                         idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk;
 1300                         pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info;
 1301                         if(hpt_set_device_info_v2(_VBUS_P idDisk, pInfo) != 0)
 1302                                 return -1;
 1303                 }
 1304                 break;
 1305 
 1306         case HPT_IOCTL_SET_BOOT_MARK:
 1307                 {
 1308                         DEVICEID id;
 1309                         PVDevice pTop;
 1310                         int i;
 1311                         IAL_ADAPTER_T *pAdapter = gIal_Adapter;
 1312                         PVBus pVBus;
 1313 
 1314                         if (nInBufferSize!=sizeof(DEVICEID)) return -1;
 1315                         id = *(DEVICEID *)lpInBuffer;
 1316                         while(pAdapter != 0)
 1317                         {
 1318                                 pVBus = &pAdapter->VBus;
 1319                                 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
 1320                                 {
 1321                                         if(!(pTop = pVBus->pVDevice[i])) continue;
 1322                                         if (pTop->pVBus!=_vbus_p) return -1;
 1323                                         while (pTop->pParent) pTop = pTop->pParent;
 1324                                         if (id==0 && pTop->vf_bootmark)
 1325                                                 pTop->vf_bootmark = 0;
 1326                                         else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark)
 1327                                                 pTop->vf_bootmark = 1;
 1328                                         else
 1329                                                 continue;
 1330                                         SyncArrayInfo(pTop);
 1331                                         break;
 1332                                 }
 1333                                 pAdapter = pAdapter->next;
 1334                         }
 1335                 }
 1336                 break;
 1337 
 1338         case HPT_IOCTL_ADD_SPARE_DISK:
 1339                 {
 1340                         DEVICEID id;
 1341 
 1342                         if (nInBufferSize!=sizeof(DEVICEID)) return -1;
 1343                         if (nOutBufferSize!=0) return -1;
 1344 
 1345                         id = *(DEVICEID *)lpInBuffer;
 1346 
 1347                         if(hpt_add_spare_disk(_VBUS_P id))
 1348                                 return -1;
 1349                 }
 1350                 break;
 1351 
 1352         case HPT_IOCTL_REMOVE_SPARE_DISK:
 1353                 {
 1354                         DEVICEID id;
 1355 
 1356                         if (nInBufferSize!=sizeof(DEVICEID)) return -1;
 1357                         if (nOutBufferSize!=0) return -1;
 1358 
 1359                         id = *(DEVICEID *)lpInBuffer;
 1360 
 1361                         if(hpt_remove_spare_disk(_VBUS_P id))
 1362                                 return -1;
 1363                 }
 1364                 break;
 1365 
 1366         case HPT_IOCTL_ADD_DISK_TO_ARRAY:
 1367                 {
 1368                         DEVICEID id1,id2;
 1369                         id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray;
 1370                         id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk;
 1371 
 1372                         if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1;
 1373                         if (nOutBufferSize != 0) return -1;
 1374 
 1375                         if(hpt_add_disk_to_array(_VBUS_P id1, id2))
 1376                                 return -1;
 1377                 }
 1378                 break;
 1379 #endif
 1380         case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
 1381                 {
 1382                         PDRIVER_CAPABILITIES cap;
 1383                         if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
 1384                         cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
 1385 
 1386                         if(hpt_get_driver_capabilities(cap))
 1387                                 return -1;
 1388                 }
 1389                 break;
 1390 
 1391         case HPT_IOCTL_GET_CONTROLLER_VENID:
 1392                 {
 1393                         DWORD id = ((DWORD*)lpInBuffer)[0];
 1394                         IAL_ADAPTER_T *pAdapTemp;
 1395                         int iControllerCount = 0;
 1396 
 1397                         for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
 1398                                 if (iControllerCount++==id)
 1399                                         break;
 1400                         
 1401                         if (!pAdapTemp)
 1402                                 return -1;
 1403                                 
 1404                         if (nOutBufferSize < 4)
 1405                                 return -1;
 1406                                 
 1407                         *(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB;
 1408                         return 0;
 1409                 }
 1410 
 1411         case HPT_IOCTL_EPROM_IO:
 1412                 {
 1413                         DWORD id           = ((DWORD*)lpInBuffer)[0];
 1414                         DWORD offset       = ((DWORD*)lpInBuffer)[1];
 1415                         DWORD direction    = ((DWORD*)lpInBuffer)[2];
 1416                         DWORD length       = ((DWORD*)lpInBuffer)[3];
 1417                         IAL_ADAPTER_T *pAdapTemp;
 1418                         int iControllerCount = 0;
 1419 
 1420                         for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
 1421                                 if (iControllerCount++==id)
 1422                                         break;
 1423                         
 1424                         if (!pAdapTemp)
 1425                                 return -1;
 1426                                 
 1427                         if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) ||
 1428                                 nOutBufferSize < (direction? 0 : length))
 1429                                 return -1;
 1430 
 1431                         if (direction == 0) /* read */
 1432                                 sx508x_flash_access(&pAdapTemp->mvSataAdapter,
 1433                                         offset, lpOutBuffer, length, 1);
 1434                         else
 1435                                 sx508x_flash_access(&pAdapTemp->mvSataAdapter,
 1436                                         offset, (char *)lpInBuffer + 16, length, 0);
 1437 
 1438                         return 0;
 1439                 }
 1440                 break;
 1441 
 1442         default:
 1443                 return -1;
 1444         }
 1445 
 1446         if (lpBytesReturned)
 1447                 *lpBytesReturned = nOutBufferSize;
 1448         return 0;
 1449 }

Cache object: 474ee584174ee5937afb1d6d6595c011


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.