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

Cache object: 219c9103159ec3f550ff66502ddeab8f


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