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/raid/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  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: src/sys/dev/hptmv/ioctl.c,v 1.9 2009/04/07 16:38:25 delphij Exp $
   27  */
   28 /*
   29  * ioctl.c   ioctl interface implementation
   30  */
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 
   36 #ifndef __KERNEL__
   37 #define __KERNEL__
   38 #endif
   39 
   40 #include <dev/raid/hptmv/global.h>
   41 #include <dev/raid/hptmv/hptintf.h>
   42 #include <dev/raid/hptmv/osbsd.h>
   43 #include <dev/raid/hptmv/access601.h>
   44 
   45 #pragma pack(1)
   46 
   47 typedef struct _HPT_REBUILD_PARAM
   48 {
   49         DEVICEID idMirror;
   50         DWORD Lba;
   51         UCHAR nSector;
   52 } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
   53 
   54 #pragma pack()
   55 
   56 #define MAX_EVENTS 10
   57 static HPT_EVENT hpt_event_queue[MAX_EVENTS];
   58 static int event_queue_head=0, event_queue_tail=0;
   59 
   60 static int hpt_get_event(PHPT_EVENT pEvent);
   61 static int hpt_set_array_state(DEVICEID idArray, DWORD state);
   62 static void lock_driver_idle(IAL_ADAPTER_T *pAdapter);
   63 static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
   64 static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
   65     FPSCAT_GATH pSgTable, int logical);
   66 
   67 static void
   68 get_disk_location(PDevice pDev, int *controller, int *channel)
   69 {
   70         IAL_ADAPTER_T *pAdapTemp;
   71         int i, j;
   72 
   73         *controller = *channel = 0;
   74 
   75         for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
   76                 for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
   77                         if (pDev == &pAdapTemp->VDevices[j].u.disk) {
   78                                 *controller = i;
   79                                 *channel = j;
   80                                 return;
   81                         }
   82                 }
   83         }
   84 }
   85 
   86 static int
   87 event_queue_add(PHPT_EVENT pEvent)
   88 {
   89         int p;
   90         p = (event_queue_tail + 1) % MAX_EVENTS;
   91         if (p==event_queue_head)
   92         {
   93                 return -1;
   94         }
   95         hpt_event_queue[event_queue_tail] = *pEvent;
   96         event_queue_tail = p;
   97         return 0;
   98 }
   99 
  100 static int
  101 event_queue_remove(PHPT_EVENT pEvent)
  102 {
  103         if (event_queue_head != event_queue_tail)
  104         {
  105                 *pEvent = hpt_event_queue[event_queue_head];
  106                 event_queue_head++;
  107                 event_queue_head %= MAX_EVENTS;
  108                 return 0;
  109         }
  110         return -1;
  111 }
  112 
  113 void HPTLIBAPI
  114 ioctl_ReportEvent(UCHAR event, PVOID param)
  115 {
  116         HPT_EVENT e;
  117         ZeroMemory(&e, sizeof(e));
  118         e.EventType = event;
  119         switch(event)
  120         {
  121                 case ET_INITIALIZE_ABORTED:
  122                 case ET_INITIALIZE_FAILED:
  123                         memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
  124                 case ET_INITIALIZE_STARTED:
  125                 case ET_INITIALIZE_FINISHED:
  126 
  127                 case ET_REBUILD_STARTED:
  128                 case ET_REBUILD_ABORTED:
  129                 case ET_REBUILD_FAILED:
  130                 case ET_REBUILD_FINISHED:
  131 
  132                 case ET_VERIFY_STARTED:
  133                 case ET_VERIFY_ABORTED:
  134                 case ET_VERIFY_FAILED:
  135                 case ET_VERIFY_FINISHED:
  136                 case ET_VERIFY_DATA_ERROR:
  137 
  138                 case ET_SPARE_TOOK_OVER:
  139                 case ET_DEVICE_REMOVED:
  140                 case ET_DEVICE_PLUGGED:
  141                 case ET_DEVICE_ERROR:
  142                         e.DeviceID = VDEV_TO_ID((PVDevice)param);
  143                         break;
  144 
  145                 default:
  146                         break;
  147         }
  148         event_queue_add(&e);
  149         if (event==ET_DEVICE_REMOVED) {
  150                 int controller, channel;
  151                 get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
  152                 hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
  153         }
  154 }
  155 
  156 static int
  157 hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
  158 {
  159         PVDevice        pArray = ID_TO_VDEV(id);
  160         BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
  161         int i;
  162         PVDevice pa;
  163 
  164         if ((id==0) || check_VDevice_valid(pArray))
  165                 return -1;
  166 
  167         if(!mIsArray(pArray)) return -1;
  168 
  169         if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
  170                 pArray->u.array.rf_initializing)
  171                 return -1;
  172 
  173         for(i=0; i<pArray->u.array.bArnMember; i++) {
  174                 pa = pArray->u.array.pMember[i];
  175                 if (pa && mIsArray(pa)) {
  176                         if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
  177                                 pa->u.array.rf_initializing)
  178                                 return -1;
  179                 }
  180         }
  181 
  182         if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
  183         fDeleteArray(_VBUS_P pArray, del_block0);
  184         return 0;
  185 
  186 }
  187 
  188 /* just to prevent driver from sending more commands */
  189 static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
  190 
  191 void
  192 lock_driver_idle(IAL_ADAPTER_T *pAdapter)
  193 {
  194         _VBUS_INST(&pAdapter->VBus)
  195         lock_driver();
  196         while (pAdapter->outstandingCommands) {
  197                 KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
  198                 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
  199                 unlock_driver();
  200 /*Schedule out*/
  201                 tsleep(lock_driver_idle, 0, "switch", 1);
  202                 lock_driver();
  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                         switch(dwIoControlCode) {
  316                         /* read-only ioctl functions can be called directly. */
  317                         case HPT_IOCTL_GET_VERSION:
  318                         case HPT_IOCTL_GET_CONTROLLER_IDS:
  319                         case HPT_IOCTL_GET_CONTROLLER_COUNT:
  320                         case HPT_IOCTL_GET_CONTROLLER_INFO:
  321                         case HPT_IOCTL_GET_CHANNEL_INFO:
  322                         case HPT_IOCTL_GET_LOGICAL_DEVICES:
  323                         case HPT_IOCTL_GET_DEVICE_INFO:
  324                         case HPT_IOCTL_GET_DEVICE_INFO_V2:
  325                         case HPT_IOCTL_GET_EVENT:
  326                         case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
  327                                 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
  328                                         lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
  329                                 break;
  330 
  331                         default:
  332                                 /*
  333                                  * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
  334                                  * wrong for second controller.
  335                                  */
  336                                 switch(dwIoControlCode) {
  337                                 case HPT_IOCTL_CREATE_ARRAY:
  338                                         pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
  339                                 case HPT_IOCTL_CREATE_ARRAY_V2:
  340                                         pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
  341                                 case HPT_IOCTL_SET_ARRAY_INFO:
  342                                         pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
  343                                 case HPT_IOCTL_SET_DEVICE_INFO:
  344                                         pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
  345                                 case HPT_IOCTL_SET_DEVICE_INFO_V2:
  346                                         pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
  347                                 case HPT_IOCTL_SET_BOOT_MARK:
  348                                 case HPT_IOCTL_ADD_SPARE_DISK:
  349                                 case HPT_IOCTL_REMOVE_SPARE_DISK:
  350                                         pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
  351                                 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
  352                                         pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
  353                                 default:
  354                                         pVDev = 0;
  355                                 }
  356 
  357                                 if (pVDev && !check_VDevice_valid(pVDev)){
  358                                         _vbus_p = pVDev->pVBus;
  359 
  360                                         pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
  361                                         /*
  362                                          * create_array, and other functions can't be executed while channel is
  363                                          * perform I/O commands. Wait until driver is idle.
  364                                          */
  365                                         lock_driver_idle(pAdapter);
  366                                         if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
  367                                                 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
  368                                                 unlock_driver();
  369                                                 return -1;
  370                                         }
  371                                         unlock_driver();
  372                                 }
  373                                 else
  374                                         return -1;
  375                                 break;
  376                         }
  377 
  378 #ifdef SUPPORT_ARRAY
  379                         switch(dwIoControlCode)
  380                         {
  381                                 case HPT_IOCTL_CREATE_ARRAY:
  382                                 {
  383                                         pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
  384                                         lock_driver();
  385                     if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
  386                                     {
  387                                                   (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
  388                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
  389                                         }
  390                                         else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
  391                                     {
  392                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
  393                                         }
  394                                         else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
  395                                     {
  396                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
  397                                         }
  398                                         unlock_driver();
  399                     break;
  400                                 }
  401 
  402 
  403                                 case HPT_IOCTL_CREATE_ARRAY_V2:
  404                                 {
  405                                         pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
  406                                         lock_driver();
  407                                              if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
  408                                                   (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
  409                                                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
  410                                         } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
  411                                                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
  412                                         } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
  413                                                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
  414                                         }
  415                                         unlock_driver();
  416                                         break;
  417                                 }
  418                                 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
  419                                 {
  420                                         PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
  421                                         pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
  422                                         if(pArray->u.array.rf_rebuilding == 0)
  423                                         {
  424                                                 DWORD timeout = 0;
  425                                                 lock_driver();
  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                                                 unlock_driver();
  430                                                 while (!pArray->u.array.rf_rebuilding)
  431                                                 {
  432                                                         tsleep((caddr_t)Kernel_DeviceIoControl, 0, "pause", 1);
  433                                                         if ( timeout >= hz*3)
  434                                                                 break;
  435                                                         timeout ++;
  436                                                 }
  437                                         }
  438                                         break;
  439                                 }
  440                         }
  441 #endif
  442             return 0;
  443                 }
  444         }
  445 
  446         if (lpBytesReturned)
  447                 *lpBytesReturned = nOutBufferSize;
  448         return 0;
  449 }
  450 
  451 static int
  452 hpt_get_event(PHPT_EVENT pEvent)
  453 {
  454         lock_driver();
  455         int ret = event_queue_remove(pEvent);
  456         unlock_driver();
  457         return ret;
  458 }
  459 
  460 static int
  461 hpt_set_array_state(DEVICEID idArray, DWORD state)
  462 {
  463         IAL_ADAPTER_T *pAdapter;
  464         PVDevice pVDevice = ID_TO_VDEV(idArray);
  465         int     i;
  466         DWORD timeout = 0;
  467 
  468         if(idArray == 0 || check_VDevice_valid(pVDevice))       return -1;
  469         if(!mIsArray(pVDevice))
  470                 return -1;
  471         if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
  472 
  473         pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
  474 
  475         switch(state)
  476         {
  477                 case MIRROR_REBUILD_START:
  478                 {
  479                         if (pVDevice->u.array.rf_rebuilding ||
  480                                 pVDevice->u.array.rf_verifying ||
  481                                 pVDevice->u.array.rf_initializing)
  482                                 return -1;
  483 
  484                         lock_driver();
  485 
  486                         pVDevice->u.array.rf_auto_rebuild = 0;
  487                         pVDevice->u.array.rf_abort_rebuild = 0;
  488 
  489                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
  490                                 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
  491 
  492                         unlock_driver();
  493 
  494                         while (!pVDevice->u.array.rf_rebuilding)
  495                         {
  496                                 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
  497                                 if ( timeout >= hz*20)
  498                                         break;
  499                                 timeout ++;
  500                         }
  501                 }
  502 
  503                 break;
  504 
  505                 case MIRROR_REBUILD_ABORT:
  506                 {
  507                         for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
  508                                 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
  509                                         hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
  510                         }
  511 
  512                         if(pVDevice->u.array.rf_rebuilding != 1)
  513                                 return -1;
  514 
  515                         lock_driver();
  516                         pVDevice->u.array.rf_abort_rebuild = 1;
  517                         unlock_driver();
  518 
  519                         while (pVDevice->u.array.rf_abort_rebuild)
  520                         {
  521                                 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
  522                                 if ( timeout >= hz*20)
  523                                         break;
  524                                 timeout ++;
  525                         }
  526                 }
  527                 break;
  528 
  529                 case AS_VERIFY_START:
  530                 {
  531                         /*if(pVDevice->u.array.rf_verifying)
  532                                 return -1;*/
  533                         if (pVDevice->u.array.rf_rebuilding ||
  534                                 pVDevice->u.array.rf_verifying ||
  535                                 pVDevice->u.array.rf_initializing)
  536                                 return -1;
  537 
  538                         lock_driver();
  539             pVDevice->u.array.RebuildSectors = 0;
  540                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
  541                         unlock_driver();
  542 
  543                         while (!pVDevice->u.array.rf_verifying)
  544                         {
  545                                 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
  546                                 if ( timeout >= hz*20)
  547                                         break;
  548                                 timeout ++;
  549                         }
  550                 }
  551                 break;
  552 
  553                 case AS_VERIFY_ABORT:
  554                 {
  555                         if(pVDevice->u.array.rf_verifying != 1)
  556                                 return -1;
  557 
  558                         lock_driver();
  559                         pVDevice->u.array.rf_abort_rebuild = 1;
  560                         unlock_driver();
  561 
  562                         while (pVDevice->u.array.rf_abort_rebuild)
  563                         {
  564                                 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
  565                                 if ( timeout >= hz*80)
  566                                         break;
  567                                 timeout ++;
  568                         }
  569                 }
  570                 break;
  571 
  572                 case AS_INITIALIZE_START:
  573                 {
  574                         if (pVDevice->u.array.rf_rebuilding ||
  575                                 pVDevice->u.array.rf_verifying ||
  576                                 pVDevice->u.array.rf_initializing)
  577                                 return -1;
  578 
  579                         lock_driver();
  580                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
  581                         unlock_driver();
  582 
  583                         while (!pVDevice->u.array.rf_initializing)
  584                         {
  585                                 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
  586                                 if ( timeout >= hz*80)
  587                                         break;
  588                                 timeout ++;
  589                         }
  590                 }
  591                 break;
  592 
  593                 case AS_INITIALIZE_ABORT:
  594                 {
  595                         if(pVDevice->u.array.rf_initializing != 1)
  596                                 return -1;
  597 
  598                         lock_driver();
  599                         pVDevice->u.array.rf_abort_rebuild = 1;
  600                         unlock_driver();
  601 
  602                         while (pVDevice->u.array.rf_abort_rebuild)
  603                         {
  604                                 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
  605                                 if ( timeout >= hz*80)
  606                                         break;
  607                                 timeout ++;
  608                         }
  609                 }
  610                 break;
  611 
  612                 default:
  613                         return -1;
  614         }
  615 
  616         return 0;
  617 }
  618 
  619 int HPTLIBAPI
  620 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
  621 {
  622         ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
  623         if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
  624                 bufferSize<<=1;
  625         if (logical) {
  626                 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
  627                 pSgTable->wSgSize = (USHORT)bufferSize;
  628                 pSgTable->wSgFlag = SG_FLAG_EOT;
  629         }
  630         else {
  631                 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
  632                 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
  633                 ULONG length;
  634                 int idx = 0;
  635 
  636                 v = pCmd->uCmd.R1Control.Buffer;
  637                 dataPointer = (ADDRESS)fOsPhysicalAddress(v);
  638 
  639                 if ((ULONG_PTR)dataPointer & 0x1)
  640                         return FALSE;
  641 
  642                 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
  643                 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
  644 
  645                 do {
  646                         if (idx >= MAX_SG_DESCRIPTORS)  return FALSE;
  647 
  648                         pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
  649                         currvaddr = v;
  650                         currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
  651 
  652 
  653                         do {
  654                                 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
  655                                 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
  656 
  657                                 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
  658                                 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
  659 
  660                                 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
  661                                         nextvaddr = nextpage;
  662                                         break;
  663                                 }
  664 
  665                                 currvaddr = nextvaddr;
  666                                 currphypage = nextphypage;
  667                         }while (1);
  668 
  669                         length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
  670                         v = nextvaddr;
  671                         bufferSize -= length;
  672 
  673                         pSgTable[idx].wSgSize = (USHORT)length;
  674                         pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
  675                         idx++;
  676 
  677                 }while (bufferSize);
  678         }
  679         return 1;
  680 }
  681 
  682 static int End_Job=0;
  683 void HPTLIBAPI
  684 thread_io_done(_VBUS_ARG PCommand pCmd)
  685 {
  686         End_Job = 1;
  687         wakeup((caddr_t)pCmd);
  688 }
  689 
  690 void
  691 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
  692 {
  693         DWORD timeout = 0;
  694     ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
  695     PCommand pCmd;
  696         UINT result;
  697         int needsync=0, retry=0, needdelete=0;
  698         void *buffer = NULL;
  699 
  700         _VBUS_INST(&pAdapter->VBus)
  701 
  702         if (pArray->u.array.rf_broken==1 ||
  703         pArray->u.array.RebuildSectors>=capacity)
  704                 return;
  705 
  706         lock_driver();
  707 
  708         switch(flags)
  709         {
  710                 case DUPLICATE:
  711                 case REBUILD_PARITY:
  712                         if(pArray->u.array.rf_rebuilding == 0)
  713                         {
  714                                 pArray->u.array.rf_rebuilding = 1;
  715                                 hpt_printk(("Rebuilding started.\n"));
  716                                 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
  717                         }
  718                         break;
  719 
  720                 case INITIALIZE:
  721                         if(pArray->u.array.rf_initializing == 0)
  722                         {
  723                                 pArray->u.array.rf_initializing = 1;
  724                                 hpt_printk(("Initializing started.\n"));
  725                                 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
  726                         }
  727                         break;
  728 
  729                 case VERIFY:
  730                         if(pArray->u.array.rf_verifying == 0)
  731                         {
  732                                 pArray->u.array.rf_verifying = 1;
  733                                 hpt_printk(("Verifying started.\n"));
  734                                 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
  735                         }
  736                         break;
  737         }
  738 
  739 retry_cmd:
  740         pCmd = AllocateCommand(_VBUS_P0);
  741         HPT_ASSERT(pCmd);
  742         pCmd->cf_control = 1;
  743         End_Job = 0;
  744 
  745         if (pArray->VDeviceType==VD_RAID_1)
  746         {
  747                 #define MAX_REBUILD_SECTORS 0x40
  748 
  749                 /* take care for discontinuous buffer in R1ControlSgl */
  750                 unlock_driver();
  751                 buffer = kmalloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
  752                 lock_driver();
  753                 if(!buffer) {
  754                         FreeCommand(_VBUS_P pCmd);
  755                         hpt_printk(("can't allocate rebuild buffer\n"));
  756                         goto fail;
  757                 }
  758                 switch(flags)
  759                 {
  760                         case DUPLICATE:
  761                                 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
  762                                 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
  763                                 break;
  764 
  765                         case VERIFY:
  766                                 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
  767                                 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
  768                                 break;
  769 
  770                         case INITIALIZE:
  771                                 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
  772                                 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
  773                                 break;
  774                 }
  775 
  776                 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
  777 
  778                 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
  779                         pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
  780 
  781                 pCmd->uCmd.R1Control.Buffer = buffer;
  782                 pCmd->pfnBuildSgl = R1ControlSgl;
  783         }
  784         else if (pArray->VDeviceType==VD_RAID_5)
  785         {
  786                 switch(flags)
  787                 {
  788                         case DUPLICATE:
  789                         case REBUILD_PARITY:
  790                                 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
  791                         case VERIFY:
  792                                 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
  793                         case INITIALIZE:
  794                                 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
  795                 }
  796                 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
  797         }
  798         else
  799                 HPT_ASSERT(0);
  800 
  801         pCmd->pVDevice = pArray;
  802         pCmd->pfnCompletion = thread_io_done;
  803         pArray->pfnSendCommand(_VBUS_P pCmd);
  804         CheckPendingCall(_VBUS_P0);
  805 
  806         if (!End_Job) {
  807                 unlock_driver();
  808                 while (!End_Job) {
  809                         tsleep((caddr_t)pCmd, 0, "pause", hz);
  810                         if (timeout++>60) break;
  811                 }
  812                 lock_driver();
  813                 if (!End_Job) {
  814                         hpt_printk(("timeout, reset\n"));
  815                         fResetVBus(_VBUS_P0);
  816                 }
  817         }
  818 
  819         result = pCmd->Result;
  820         FreeCommand(_VBUS_P pCmd);
  821         unlock_driver();
  822         if (buffer) kfree(buffer, M_DEVBUF);
  823         lock_driver();
  824         KdPrintI(("cmd finished %d", result));
  825 
  826         switch(result)
  827         {
  828                 case RETURN_SUCCESS:
  829                         if (!pArray->u.array.rf_abort_rebuild)
  830                         {
  831                                 if(pArray->u.array.RebuildSectors < capacity)
  832                                 {
  833                                         hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
  834                                 }
  835                                 else
  836                                 {
  837                                         switch (flags)
  838                                         {
  839                                                 case DUPLICATE:
  840                                                 case REBUILD_PARITY:
  841                                                         needsync = 1;
  842                                                         pArray->u.array.rf_rebuilding = 0;
  843                                                         pArray->u.array.rf_need_rebuild = 0;
  844                                                         pArray->u.array.CriticalMembers = 0;
  845                                                         pArray->u.array.RebuildSectors = MAX_LBA_T;
  846                                                         pArray->u.array.rf_duplicate_and_create = 0;
  847                                                         hpt_printk(("Rebuilding finished.\n"));
  848                                                         ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
  849                                                         break;
  850                                                 case INITIALIZE:
  851                                                         needsync = 1;
  852                                                         pArray->u.array.rf_initializing = 0;
  853                                                         pArray->u.array.rf_need_rebuild = 0;
  854                                                         pArray->u.array.RebuildSectors = MAX_LBA_T;
  855                                                         hpt_printk(("Initializing finished.\n"));
  856                                                         ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
  857                                                         break;
  858                                                 case VERIFY:
  859                                                         pArray->u.array.rf_verifying = 0;
  860                                                         hpt_printk(("Verifying finished.\n"));
  861                                                         ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
  862                                                         break;
  863                                         }
  864                                 }
  865                         }
  866                         else
  867                         {
  868                                 pArray->u.array.rf_abort_rebuild = 0;
  869                                 if (pArray->u.array.rf_rebuilding)
  870                                 {
  871                                         hpt_printk(("Abort rebuilding.\n"));
  872                                         pArray->u.array.rf_rebuilding = 0;
  873                                         pArray->u.array.rf_duplicate_and_create = 0;
  874                                         ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
  875                                 }
  876                                 else if (pArray->u.array.rf_verifying)
  877                                 {
  878                                         hpt_printk(("Abort verifying.\n"));
  879                                         pArray->u.array.rf_verifying = 0;
  880                                         ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
  881                                 }
  882                                 else if (pArray->u.array.rf_initializing)
  883                                 {
  884                                         hpt_printk(("Abort initializing.\n"));
  885                                         pArray->u.array.rf_initializing = 0;
  886                                         ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
  887                                 }
  888                                 needdelete=1;
  889                         }
  890                         break;
  891 
  892                 case RETURN_DATA_ERROR:
  893                         if (flags==VERIFY)
  894                         {
  895                                 needsync = 1;
  896                                 pArray->u.array.rf_verifying = 0;
  897                                 pArray->u.array.rf_need_rebuild = 1;
  898                                 hpt_printk(("Verifying failed: found inconsistency\n"));
  899                                 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
  900                                 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
  901 
  902                                 if (!pArray->vf_online || pArray->u.array.rf_broken) break;
  903 
  904                                 pArray->u.array.rf_auto_rebuild = 0;
  905                                 pArray->u.array.rf_abort_rebuild = 0;
  906                                 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
  907                                         (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
  908                         }
  909                         break;
  910 
  911                 default:
  912                         hpt_printk(("command failed with error %d\n", result));
  913                         if (++retry<3)
  914                         {
  915                                 hpt_printk(("retry (%d)\n", retry));
  916                                 goto retry_cmd;
  917                         }
  918 fail:
  919                         pArray->u.array.rf_abort_rebuild = 0;
  920                         switch (flags)
  921                         {
  922                                 case DUPLICATE:
  923                                 case REBUILD_PARITY:
  924                                         needsync = 1;
  925                                         pArray->u.array.rf_rebuilding = 0;
  926                                         pArray->u.array.rf_duplicate_and_create = 0;
  927                                         hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
  928                                         ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
  929                                         break;
  930 
  931                                 case INITIALIZE:
  932                                         needsync = 1;
  933                                         pArray->u.array.rf_initializing = 0;
  934                                         hpt_printk(("Initializing failed.\n"));
  935                                         ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
  936                                         break;
  937 
  938                                 case VERIFY:
  939                                         needsync = 1;
  940                                         pArray->u.array.rf_verifying = 0;
  941                                         hpt_printk(("Verifying failed.\n"));
  942                                         ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
  943                                         break;
  944                         }
  945                         needdelete=1;
  946         }
  947 
  948         while (pAdapter->outstandingCommands)
  949         {
  950                 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
  951                 /* put this to have driver stop processing system commands quickly */
  952                 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
  953                 unlock_driver();
  954                 /*Schedule out*/
  955                 tsleep(hpt_rebuild_data_block, 0, "switch", 1);
  956                 lock_driver();
  957         }
  958 
  959         if (needsync) SyncArrayInfo(pArray);
  960         if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
  961                 fDeleteArray(_VBUS_P pArray, TRUE);
  962 
  963         Check_Idle_Call(pAdapter);
  964         unlock_driver();
  965 }

Cache object: af769eaac0d4e40bb0c52754d88d8d0b


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