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/ioctl.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  * ioctl.c   ioctl interface implementation
   32  */
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 
   38 #ifndef __KERNEL__
   39 #define __KERNEL__
   40 #endif
   41 
   42 #include <dev/hptmv/global.h>
   43 #include <dev/hptmv/hptintf.h>
   44 #include <dev/hptmv/osbsd.h>
   45 #include <dev/hptmv/access601.h>
   46 
   47 #pragma pack(1)
   48 
   49 typedef struct _HPT_REBUILD_PARAM
   50 {
   51         DEVICEID idMirror;
   52         DWORD Lba;
   53         UCHAR nSector;
   54 } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
   55 
   56 #pragma pack()
   57 
   58 #define MAX_EVENTS 10
   59 static HPT_EVENT hpt_event_queue[MAX_EVENTS];
   60 static int event_queue_head=0, event_queue_tail=0;
   61 
   62 static int hpt_get_event(PHPT_EVENT pEvent);
   63 static int hpt_set_array_state(DEVICEID idArray, DWORD state);
   64 static void lock_driver_idle(IAL_ADAPTER_T *pAdapter);
   65 static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
   66 static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
   67     FPSCAT_GATH pSgTable, int logical);
   68 
   69 static void
   70 get_disk_location(PDevice pDev, int *controller, int *channel)
   71 {
   72         IAL_ADAPTER_T *pAdapTemp;
   73         int i, j;
   74 
   75         *controller = *channel = 0;
   76 
   77         for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
   78                 for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
   79                         if (pDev == &pAdapTemp->VDevices[j].u.disk) {
   80                                 *controller = i;
   81                                 *channel = j;
   82                                 return;
   83                         }
   84                 }
   85         }
   86 }
   87 
   88 static int
   89 event_queue_add(PHPT_EVENT pEvent)
   90 {
   91         int p;
   92         p = (event_queue_tail + 1) % MAX_EVENTS;
   93         if (p==event_queue_head)
   94         {
   95                 return -1;
   96         }
   97         hpt_event_queue[event_queue_tail] = *pEvent;
   98         event_queue_tail = p;
   99         return 0;
  100 }
  101 
  102 static int
  103 event_queue_remove(PHPT_EVENT pEvent)
  104 {
  105         if (event_queue_head != event_queue_tail)
  106         {
  107                 *pEvent = hpt_event_queue[event_queue_head];
  108                 event_queue_head++;
  109                 event_queue_head %= MAX_EVENTS;
  110                 return 0;
  111         }
  112         return -1;
  113 }
  114 
  115 void HPTLIBAPI
  116 ioctl_ReportEvent(UCHAR event, PVOID param)
  117 {
  118         HPT_EVENT e;
  119         ZeroMemory(&e, sizeof(e));
  120         e.EventType = event;
  121         switch(event)
  122         {
  123                 case ET_INITIALIZE_ABORTED:
  124                 case ET_INITIALIZE_FAILED:
  125                         memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
  126                 case ET_INITIALIZE_STARTED:
  127                 case ET_INITIALIZE_FINISHED:
  128 
  129                 case ET_REBUILD_STARTED:
  130                 case ET_REBUILD_ABORTED:
  131                 case ET_REBUILD_FAILED:
  132                 case ET_REBUILD_FINISHED:
  133                 
  134                 case ET_VERIFY_STARTED:
  135                 case ET_VERIFY_ABORTED:
  136                 case ET_VERIFY_FAILED:
  137                 case ET_VERIFY_FINISHED:
  138                 case ET_VERIFY_DATA_ERROR:
  139 
  140                 case ET_SPARE_TOOK_OVER:
  141                 case ET_DEVICE_REMOVED:
  142                 case ET_DEVICE_PLUGGED:
  143                 case ET_DEVICE_ERROR:
  144                         e.DeviceID = VDEV_TO_ID((PVDevice)param);
  145                         break;
  146 
  147                 default:
  148                         break;
  149         }
  150         event_queue_add(&e);
  151         if (event==ET_DEVICE_REMOVED) {
  152                 int controller, channel;
  153                 get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
  154                 hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
  155         }
  156         wakeup(param);
  157 }
  158 
  159 static int
  160 hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
  161 {
  162         PVDevice        pArray = ID_TO_VDEV(id);
  163         BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
  164         int i;
  165         PVDevice pa;
  166 
  167         if ((id==0) || check_VDevice_valid(pArray))
  168                 return -1;
  169 
  170         if(!mIsArray(pArray)) return -1;
  171         
  172         if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
  173                 pArray->u.array.rf_initializing)
  174                 return -1;
  175 
  176         for(i=0; i<pArray->u.array.bArnMember; i++) {
  177                 pa = pArray->u.array.pMember[i];
  178                 if (pa && mIsArray(pa)) {
  179                         if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 
  180                                 pa->u.array.rf_initializing)
  181                                 return -1;
  182                 }
  183         }
  184 
  185         if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
  186         fDeleteArray(_VBUS_P pArray, del_block0);
  187         return 0;
  188 
  189 }
  190 
  191 /* just to prevent driver from sending more commands */
  192 static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
  193 
  194 void
  195 lock_driver_idle(IAL_ADAPTER_T *pAdapter)
  196 {
  197         _VBUS_INST(&pAdapter->VBus)
  198         mtx_lock(&pAdapter->lock);
  199         while (pAdapter->outstandingCommands) {
  200                 KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
  201                 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
  202                 mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
  203         }
  204         CheckIdleCall(_VBUS_P0);
  205 }
  206 
  207 int Kernel_DeviceIoControl(_VBUS_ARG
  208                                                         DWORD dwIoControlCode,          /* operation control code */
  209                                                         PVOID lpInBuffer,               /* input data buffer */
  210                                                         DWORD nInBufferSize,            /* size of input data buffer */
  211                                                         PVOID lpOutBuffer,              /* output data buffer */
  212                                                         DWORD nOutBufferSize,           /* size of output data buffer */
  213                                                         PDWORD lpBytesReturned          /* byte count */
  214                                                 )
  215 {
  216         IAL_ADAPTER_T *pAdapter;
  217 
  218         switch(dwIoControlCode) {
  219                 case HPT_IOCTL_DELETE_ARRAY:
  220                 {
  221                         DEVICEID idArray;
  222                         int iSuccess;                   
  223                 int i;
  224                         PVDevice pArray;
  225                         PVBus _vbus_p;
  226                         struct cam_periph *periph = NULL;
  227 
  228                         if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
  229                         if (nOutBufferSize!=sizeof(int)) return -1;
  230                         idArray = *(DEVICEID *)lpInBuffer;
  231 
  232                         pArray = ID_TO_VDEV(idArray);
  233 
  234                         if((idArray == 0) || check_VDevice_valid(pArray))       
  235                         return -1;
  236                 
  237                 if(!mIsArray(pArray))
  238                                 return -1;
  239 
  240                         _vbus_p=pArray->pVBus;
  241                         pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
  242 
  243                 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
  244                                 if(pArray == _vbus_p->pVDevice[i])
  245                                 {
  246                                         periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
  247                                         if (periph != NULL && periph->refcount >= 1)
  248                                         {
  249                                                 hpt_printk(("Can not delete a mounted device.\n"));
  250                             return -1;  
  251                                         }
  252                                 }
  253                                 /* the Mounted Disk isn't delete */
  254                         } 
  255 
  256                         iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
  257 
  258                         *(int*)lpOutBuffer = iSuccess;
  259 
  260                         if(iSuccess != 0)
  261                                 return -1;
  262                         break;
  263                 }
  264 
  265                 case HPT_IOCTL_GET_EVENT:
  266                 {
  267                         PHPT_EVENT pInfo;
  268 
  269                         if (nInBufferSize!=0) return -1;
  270                         if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
  271 
  272                         pInfo = (PHPT_EVENT)lpOutBuffer;
  273 
  274                         if (hpt_get_event(pInfo)!=0)
  275                                 return -1;
  276                 }
  277                 break;
  278 
  279                 case HPT_IOCTL_SET_ARRAY_STATE:
  280                 {
  281                         DEVICEID idArray;
  282                         DWORD state;
  283 
  284                         if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
  285                         if (nOutBufferSize!=0) return -1;
  286 
  287                         idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
  288                         state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
  289 
  290                         if(hpt_set_array_state(idArray, state)!=0)
  291                                 return -1;
  292                 }
  293                 break;
  294 
  295                 case HPT_IOCTL_RESCAN_DEVICES:
  296                 {
  297                         if (nInBufferSize!=0) return -1;
  298                         if (nOutBufferSize!=0) return -1;
  299 
  300 #ifndef FOR_DEMO
  301                         /* stop buzzer if user perform rescan */
  302                         for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
  303                                 if (pAdapter->beeping) {
  304                                         pAdapter->beeping = 0;
  305                                         BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
  306                                 }
  307                         }
  308 #endif
  309                 }
  310                 break;
  311 
  312                 default:
  313                 {
  314                         PVDevice pVDev;
  315 
  316                         switch(dwIoControlCode) {
  317                         /* read-only ioctl functions can be called directly. */
  318                         case HPT_IOCTL_GET_VERSION:
  319                         case HPT_IOCTL_GET_CONTROLLER_IDS:
  320                         case HPT_IOCTL_GET_CONTROLLER_COUNT:
  321                         case HPT_IOCTL_GET_CONTROLLER_INFO:
  322                         case HPT_IOCTL_GET_CHANNEL_INFO:
  323                         case HPT_IOCTL_GET_LOGICAL_DEVICES:
  324                         case HPT_IOCTL_GET_DEVICE_INFO:
  325                         case HPT_IOCTL_GET_DEVICE_INFO_V2:                              
  326                         case HPT_IOCTL_GET_EVENT:
  327                         case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
  328                                 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 
  329                                         lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
  330                                 break;
  331 
  332                         default:
  333                                 /* 
  334                                  * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 
  335                                  * wrong for second controller. 
  336                                  */
  337                                 switch(dwIoControlCode) {
  338                                 case HPT_IOCTL_CREATE_ARRAY:
  339                                         pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
  340                                 case HPT_IOCTL_CREATE_ARRAY_V2:
  341                                         pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
  342                                 case HPT_IOCTL_SET_ARRAY_INFO:
  343                                         pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
  344                                 case HPT_IOCTL_SET_DEVICE_INFO:
  345                                         pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
  346                                 case HPT_IOCTL_SET_DEVICE_INFO_V2:
  347                                         pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
  348                                 case HPT_IOCTL_SET_BOOT_MARK:
  349                                 case HPT_IOCTL_ADD_SPARE_DISK:
  350                                 case HPT_IOCTL_REMOVE_SPARE_DISK:
  351                                         pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
  352                                 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
  353                                         pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
  354                                 default:
  355                                         pVDev = 0;
  356                                 }
  357                                 
  358                                 if (pVDev && !check_VDevice_valid(pVDev)){
  359                                         _vbus_p = pVDev->pVBus;
  360 
  361                                         pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
  362                                         /* 
  363                                          * create_array, and other functions can't be executed while channel is 
  364                                          * perform I/O commands. Wait until driver is idle.
  365                                          */
  366                                         lock_driver_idle(pAdapter);
  367                                         if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 
  368                                                 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
  369                                                 mtx_unlock(&pAdapter->lock);
  370                                                 return -1;
  371                                         }
  372                                         mtx_unlock(&pAdapter->lock);
  373                                 }
  374                                 else
  375                                         return -1;
  376                                 break;
  377                         }
  378                         
  379 #ifdef SUPPORT_ARRAY
  380                         switch(dwIoControlCode)
  381                         {
  382                                 case HPT_IOCTL_CREATE_ARRAY:
  383                                 {
  384                                         pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
  385                                         mtx_lock(&pAdapter->lock);
  386                     if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
  387                                     {
  388                                                   (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
  389                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
  390                                         }
  391                                         else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
  392                                     {
  393                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
  394                                         }
  395                                         else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
  396                                     {
  397                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
  398                                         }
  399                                         mtx_unlock(&pAdapter->lock);
  400                     break;
  401                                 }
  402 
  403 
  404                                 case HPT_IOCTL_CREATE_ARRAY_V2:
  405                                 {
  406                                         pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
  407                                         mtx_lock(&pAdapter->lock);
  408                                              if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
  409                                                   (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
  410                                                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
  411                                         } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
  412                                                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
  413                                         } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
  414                                                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
  415                                         }
  416                                         mtx_unlock(&pAdapter->lock);
  417                                         break;
  418                                 }
  419                                 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
  420                                 {
  421                                         PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
  422                                         pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
  423                                         if(pArray->u.array.rf_rebuilding == 0)
  424                                         {               
  425                                                 mtx_lock(&pAdapter->lock);
  426                                                 pArray->u.array.rf_auto_rebuild = 0;
  427                                                 pArray->u.array.rf_abort_rebuild = 0;
  428                                                 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
  429                                                 while (!pArray->u.array.rf_rebuilding)
  430                                                 {
  431                                                         if (mtx_sleep(pArray, &pAdapter->lock, 0, "hptwait", hz * 3) != 0)
  432                                                                 break;
  433                                                 }
  434                                                 mtx_unlock(&pAdapter->lock);
  435                                         }
  436                                         break;
  437                                 }
  438                         }
  439 #endif
  440             return 0;
  441                 }
  442         }
  443 
  444         if (lpBytesReturned)
  445                 *lpBytesReturned = nOutBufferSize;
  446         return 0;
  447 }
  448 
  449 static int
  450 hpt_get_event(PHPT_EVENT pEvent)
  451 {
  452         int ret = event_queue_remove(pEvent);
  453         return ret;
  454 }
  455 
  456 static int
  457 hpt_set_array_state(DEVICEID idArray, DWORD state)
  458 {
  459         IAL_ADAPTER_T *pAdapter;
  460         PVDevice pVDevice = ID_TO_VDEV(idArray);
  461         int     i;
  462 
  463         if(idArray == 0 || check_VDevice_valid(pVDevice))       return -1;
  464         if(!mIsArray(pVDevice))
  465                 return -1;
  466         if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
  467 
  468         pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
  469         
  470         switch(state)
  471         {
  472                 case MIRROR_REBUILD_START:
  473                 {
  474                         mtx_lock(&pAdapter->lock);
  475                         if (pVDevice->u.array.rf_rebuilding ||
  476                                 pVDevice->u.array.rf_verifying ||
  477                                 pVDevice->u.array.rf_initializing) {
  478                                 mtx_unlock(&pAdapter->lock);
  479                                 return -1;
  480                         }
  481                         
  482                         pVDevice->u.array.rf_auto_rebuild = 0;
  483                         pVDevice->u.array.rf_abort_rebuild = 0;
  484 
  485                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 
  486                                 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
  487 
  488                         while (!pVDevice->u.array.rf_rebuilding)
  489                         {
  490                                 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
  491                                     "hptwait", hz * 20) != 0)
  492                                         break;
  493                         }
  494                         mtx_unlock(&pAdapter->lock);
  495                 }
  496 
  497                 break;
  498 
  499                 case MIRROR_REBUILD_ABORT:
  500                 {
  501                         for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
  502                                 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
  503                                         hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
  504                         }
  505 
  506                         mtx_lock(&pAdapter->lock);
  507                         if(pVDevice->u.array.rf_rebuilding != 1) {
  508                                 mtx_unlock(&pAdapter->lock);
  509                                 return -1;
  510                         }
  511                         
  512                         pVDevice->u.array.rf_abort_rebuild = 1;
  513                         
  514                         while (pVDevice->u.array.rf_abort_rebuild)
  515                         {
  516                                 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
  517                                     "hptabrt", hz * 20) != 0)
  518                                         break;
  519                         }
  520                         mtx_unlock(&pAdapter->lock);
  521                 }
  522                 break;
  523 
  524                 case AS_VERIFY_START:
  525                 {
  526                         /*if(pVDevice->u.array.rf_verifying)
  527                                 return -1;*/
  528                         mtx_lock(&pAdapter->lock);
  529                         if (pVDevice->u.array.rf_rebuilding ||
  530                                 pVDevice->u.array.rf_verifying ||
  531                                 pVDevice->u.array.rf_initializing) {
  532                                 mtx_unlock(&pAdapter->lock);
  533                                 return -1;
  534                         }
  535 
  536             pVDevice->u.array.RebuildSectors = 0;
  537                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
  538                         
  539                         while (!pVDevice->u.array.rf_verifying)
  540                         {
  541                                 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
  542                                     "hptvrfy", hz * 20) != 0)
  543                                         break;
  544                         }
  545                         mtx_unlock(&pAdapter->lock);
  546                 }
  547                 break;
  548 
  549                 case AS_VERIFY_ABORT:
  550                 {
  551                         mtx_lock(&pAdapter->lock);
  552                         if(pVDevice->u.array.rf_verifying != 1) {
  553                                 mtx_unlock(&pAdapter->lock);
  554                                 return -1;
  555                         }
  556                                 
  557                         pVDevice->u.array.rf_abort_rebuild = 1;
  558                         
  559                         while (pVDevice->u.array.rf_abort_rebuild)
  560                         {
  561                                 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
  562                                     "hptvrfy", hz * 80) != 0)
  563                                         break;
  564                         }
  565                         mtx_unlock(&pAdapter->lock);
  566                 }
  567                 break;
  568 
  569                 case AS_INITIALIZE_START:
  570                 {
  571                         mtx_lock(&pAdapter->lock);
  572                         if (pVDevice->u.array.rf_rebuilding ||
  573                                 pVDevice->u.array.rf_verifying ||
  574                                 pVDevice->u.array.rf_initializing) {
  575                                 mtx_unlock(&pAdapter->lock);
  576                                 return -1;
  577                         }
  578 
  579                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
  580                         
  581                         while (!pVDevice->u.array.rf_initializing)
  582                         {
  583                                 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
  584                                     "hptinit", hz * 80) != 0)
  585                                         break;
  586                         }
  587                         mtx_unlock(&pAdapter->lock);
  588                 }
  589                 break;
  590 
  591                 case AS_INITIALIZE_ABORT:
  592                 {
  593                         mtx_lock(&pAdapter->lock);
  594                         if(pVDevice->u.array.rf_initializing != 1) {
  595                                 mtx_unlock(&pAdapter->lock);
  596                                 return -1;
  597                         }
  598                                 
  599                         pVDevice->u.array.rf_abort_rebuild = 1;
  600                         
  601                         while (pVDevice->u.array.rf_abort_rebuild)
  602                         {
  603                                 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
  604                                     "hptinit", hz * 80) != 0)
  605                                         break;
  606                         }
  607                         mtx_unlock(&pAdapter->lock);
  608                 }
  609                 break;
  610 
  611                 default:
  612                         return -1;
  613         }
  614 
  615         return 0;
  616 }
  617 
  618 int HPTLIBAPI
  619 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
  620 {
  621         ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
  622         if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
  623                 bufferSize<<=1;
  624         if (logical) {
  625                 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
  626                 pSgTable->wSgSize = (USHORT)bufferSize;
  627                 pSgTable->wSgFlag = SG_FLAG_EOT;
  628         }
  629         else {
  630                 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
  631                 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
  632                 ULONG length;
  633                 int idx = 0;
  634 
  635                 v = pCmd->uCmd.R1Control.Buffer;
  636                 dataPointer = (ADDRESS)fOsPhysicalAddress(v);
  637 
  638                 if ((ULONG_PTR)dataPointer & 0x1)
  639                         return FALSE;
  640 
  641                 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
  642                 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
  643 
  644                 do {
  645                         if (idx >= MAX_SG_DESCRIPTORS)  return FALSE;
  646 
  647                         pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
  648                         currvaddr = v;
  649                         currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
  650 
  651 
  652                         do {
  653                                 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
  654                                 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
  655 
  656                                 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
  657                                 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
  658 
  659                                 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
  660                                         nextvaddr = nextpage;
  661                                         break;
  662                                 }
  663 
  664                                 currvaddr = nextvaddr;
  665                                 currphypage = nextphypage;
  666                         }while (1);
  667 
  668                         length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
  669                         v = nextvaddr;
  670                         bufferSize -= length;
  671 
  672                         pSgTable[idx].wSgSize = (USHORT)length;
  673                         pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
  674                         idx++;
  675 
  676                 }while (bufferSize);
  677         }
  678         return 1;
  679 }
  680 
  681 static int End_Job=0;
  682 void HPTLIBAPI
  683 thread_io_done(_VBUS_ARG PCommand pCmd)
  684 {
  685         End_Job = 1;
  686         wakeup((caddr_t)pCmd);
  687 }
  688 
  689 void
  690 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
  691 {
  692     ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
  693     PCommand pCmd;
  694         UINT result;
  695         int needsync=0, retry=0, needdelete=0;
  696         void *buffer = NULL;
  697 
  698         _VBUS_INST(&pAdapter->VBus)
  699 
  700         if (pArray->u.array.rf_broken==1 ||
  701         pArray->u.array.RebuildSectors>=capacity)
  702                 return;
  703 
  704         mtx_lock(&pAdapter->lock);
  705         
  706         switch(flags)
  707         {
  708                 case DUPLICATE:
  709                 case REBUILD_PARITY:
  710                         if(pArray->u.array.rf_rebuilding == 0)
  711                         {
  712                                 pArray->u.array.rf_rebuilding = 1;
  713                                 hpt_printk(("Rebuilding started.\n"));
  714                                 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
  715                         }
  716                         break;
  717 
  718                 case INITIALIZE:
  719                         if(pArray->u.array.rf_initializing == 0)
  720                         {
  721                                 pArray->u.array.rf_initializing = 1;
  722                                 hpt_printk(("Initializing started.\n"));
  723                                 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
  724                         }
  725                         break;
  726 
  727                 case VERIFY:
  728                         if(pArray->u.array.rf_verifying == 0)
  729                         {
  730                                 pArray->u.array.rf_verifying = 1;
  731                                 hpt_printk(("Verifying started.\n"));
  732                                 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
  733                         }
  734                         break;
  735         }
  736         
  737 retry_cmd:
  738         pCmd = AllocateCommand(_VBUS_P0);
  739         HPT_ASSERT(pCmd);
  740         pCmd->cf_control = 1;
  741         End_Job = 0;
  742 
  743         if (pArray->VDeviceType==VD_RAID_1) 
  744         {
  745                 #define MAX_REBUILD_SECTORS 0x40
  746 
  747                 /* take care for discontinuous buffer in R1ControlSgl */
  748                 buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
  749                 if(!buffer) {
  750                         FreeCommand(_VBUS_P pCmd);
  751                         hpt_printk(("can't allocate rebuild buffer\n"));
  752                         goto fail;
  753                 }
  754                 switch(flags) 
  755                 {
  756                         case DUPLICATE:
  757                                 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
  758                                 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
  759                                 break;
  760 
  761                         case VERIFY:
  762                                 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
  763                                 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
  764                                 break;
  765 
  766                         case INITIALIZE:
  767                                 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 
  768                                 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
  769                                 break;
  770                 }
  771 
  772                 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
  773 
  774                 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
  775                         pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
  776 
  777                 pCmd->uCmd.R1Control.Buffer = buffer;
  778                 pCmd->pfnBuildSgl = R1ControlSgl;
  779         }
  780         else if (pArray->VDeviceType==VD_RAID_5)
  781         {
  782                 switch(flags)
  783                 {
  784                         case DUPLICATE:
  785                         case REBUILD_PARITY:
  786                                 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
  787                         case VERIFY:
  788                                 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
  789                         case INITIALIZE:
  790                                 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
  791                 }
  792                 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
  793         }
  794         else
  795                 HPT_ASSERT(0);
  796 
  797         pCmd->pVDevice = pArray;
  798         pCmd->pfnCompletion = thread_io_done;
  799         pArray->pfnSendCommand(_VBUS_P pCmd);
  800         CheckPendingCall(_VBUS_P0);
  801 
  802         if (!End_Job) {
  803                 mtx_sleep(pCmd, &pAdapter->lock, 0, "hptrbld", hz * 60);
  804                 if (!End_Job) {
  805                         hpt_printk(("timeout, reset\n"));
  806                         fResetVBus(_VBUS_P0);
  807                 }
  808         }
  809 
  810         result = pCmd->Result;
  811         FreeCommand(_VBUS_P pCmd);
  812         if (buffer) free(buffer, M_DEVBUF);
  813         KdPrintI(("cmd finished %d", result));
  814 
  815         switch(result)
  816         {
  817                 case RETURN_SUCCESS:
  818                         if (!pArray->u.array.rf_abort_rebuild)
  819                         {
  820                                 if(pArray->u.array.RebuildSectors < capacity)
  821                                 {
  822                                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
  823                                 }
  824                                 else
  825                                 {
  826                                         switch (flags)
  827                                         {
  828                                                 case DUPLICATE:
  829                                                 case REBUILD_PARITY:
  830                                                         needsync = 1;
  831                                                         pArray->u.array.rf_rebuilding = 0;
  832                                                         pArray->u.array.rf_need_rebuild = 0;
  833                                                         pArray->u.array.CriticalMembers = 0;
  834                                                         pArray->u.array.RebuildSectors = MAX_LBA_T;
  835                                                         pArray->u.array.rf_duplicate_and_create = 0;
  836                                                         hpt_printk(("Rebuilding finished.\n"));
  837                                                         ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
  838                                                         break;
  839                                                 case INITIALIZE:
  840                                                         needsync = 1;
  841                                                         pArray->u.array.rf_initializing = 0;
  842                                                         pArray->u.array.rf_need_rebuild = 0;
  843                                                         pArray->u.array.RebuildSectors = MAX_LBA_T;
  844                                                         hpt_printk(("Initializing finished.\n"));
  845                                                         ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
  846                                                         break;
  847                                                 case VERIFY:
  848                                                         pArray->u.array.rf_verifying = 0;
  849                                                         hpt_printk(("Verifying finished.\n"));
  850                                                         ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
  851                                                         break;
  852                                         }
  853                                 }
  854                         }
  855                         else
  856                         {
  857                                 pArray->u.array.rf_abort_rebuild = 0;
  858                                 if (pArray->u.array.rf_rebuilding) 
  859                                 {
  860                                         hpt_printk(("Abort rebuilding.\n"));
  861                                         pArray->u.array.rf_rebuilding = 0;
  862                                         pArray->u.array.rf_duplicate_and_create = 0;
  863                                         ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
  864                                 }
  865                                 else if (pArray->u.array.rf_verifying) 
  866                                 {
  867                                         hpt_printk(("Abort verifying.\n"));
  868                                         pArray->u.array.rf_verifying = 0;
  869                                         ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
  870                                 }
  871                                 else if (pArray->u.array.rf_initializing) 
  872                                 {
  873                                         hpt_printk(("Abort initializing.\n"));
  874                                         pArray->u.array.rf_initializing = 0;
  875                                         ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
  876                                 }
  877                                 needdelete=1;
  878                         }
  879                         break;
  880 
  881                 case RETURN_DATA_ERROR:
  882                         if (flags==VERIFY)
  883                         {
  884                                 needsync = 1;
  885                                 pArray->u.array.rf_verifying = 0;
  886                                 pArray->u.array.rf_need_rebuild = 1;
  887                                 hpt_printk(("Verifying failed: found inconsistency\n"));
  888                                 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
  889                                 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
  890 
  891                                 if (!pArray->vf_online || pArray->u.array.rf_broken) break;
  892 
  893                                 pArray->u.array.rf_auto_rebuild = 0;
  894                                 pArray->u.array.rf_abort_rebuild = 0;
  895                                 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
  896                                         (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
  897                         }
  898                         break;
  899 
  900                 default:
  901                         hpt_printk(("command failed with error %d\n", result));
  902                         if (++retry<3)
  903                         {
  904                                 hpt_printk(("retry (%d)\n", retry));
  905                                 goto retry_cmd;
  906                         }
  907 fail:
  908                         pArray->u.array.rf_abort_rebuild = 0;
  909                         switch (flags)
  910                         {
  911                                 case DUPLICATE:
  912                                 case REBUILD_PARITY:
  913                                         needsync = 1;
  914                                         pArray->u.array.rf_rebuilding = 0;
  915                                         pArray->u.array.rf_duplicate_and_create = 0;
  916                                         hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
  917                                         ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
  918                                         break;
  919 
  920                                 case INITIALIZE:
  921                                         needsync = 1;
  922                                         pArray->u.array.rf_initializing = 0;
  923                                         hpt_printk(("Initializing failed.\n"));
  924                                         ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
  925                                         break;
  926 
  927                                 case VERIFY:
  928                                         needsync = 1;
  929                                         pArray->u.array.rf_verifying = 0;
  930                                         hpt_printk(("Verifying failed.\n"));
  931                                         ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
  932                                         break;
  933                         }
  934                         needdelete=1;
  935         }
  936 
  937         while (pAdapter->outstandingCommands) 
  938         {
  939                 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
  940                 /* put this to have driver stop processing system commands quickly */
  941                 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
  942                 mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
  943         }
  944                 
  945         if (needsync) SyncArrayInfo(pArray);
  946         if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
  947                 fDeleteArray(_VBUS_P pArray, TRUE);
  948 
  949         Check_Idle_Call(pAdapter);
  950         mtx_unlock(&pAdapter->lock);
  951 }

Cache object: 63f12a9a13e833d9d8fa007aaf164685


[ 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.