11713e81bSScott Long /* 2d2bd3ab9SScott Long * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 31713e81bSScott Long * All rights reserved. 41713e81bSScott Long * 51713e81bSScott Long * Redistribution and use in source and binary forms, with or without 61713e81bSScott Long * modification, are permitted provided that the following conditions 71713e81bSScott Long * are met: 81713e81bSScott Long * 1. Redistributions of source code must retain the above copyright 91713e81bSScott Long * notice, this list of conditions and the following disclaimer. 101713e81bSScott Long * 2. Redistributions in binary form must reproduce the above copyright 111713e81bSScott Long * notice, this list of conditions and the following disclaimer in the 121713e81bSScott Long * documentation and/or other materials provided with the distribution. 131713e81bSScott Long * 141713e81bSScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151713e81bSScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161713e81bSScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171713e81bSScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181713e81bSScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191713e81bSScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201713e81bSScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211713e81bSScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221713e81bSScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231713e81bSScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241713e81bSScott Long * SUCH DAMAGE. 25d38d9c9eSScott Long * 26d38d9c9eSScott Long * $FreeBSD$ 271713e81bSScott Long */ 281713e81bSScott Long /* 291713e81bSScott Long * ioctl.c ioctl interface implementation 301713e81bSScott Long */ 311713e81bSScott Long #include <sys/param.h> 321713e81bSScott Long #include <sys/systm.h> 331713e81bSScott Long #include <sys/kernel.h> 341713e81bSScott Long #include <sys/malloc.h> 351713e81bSScott Long 36d2bd3ab9SScott Long #ifndef __KERNEL__ 37d2bd3ab9SScott Long #define __KERNEL__ 38d2bd3ab9SScott Long #endif 39d2bd3ab9SScott Long 401713e81bSScott Long #include <dev/hptmv/global.h> 411713e81bSScott Long #include <dev/hptmv/hptintf.h> 421713e81bSScott Long #include <dev/hptmv/osbsd.h> 43f7f3900bSScott Long #include <dev/hptmv/access601.h> 441713e81bSScott Long 451713e81bSScott Long #pragma pack(1) 461713e81bSScott Long 471713e81bSScott Long typedef struct _HPT_REBUILD_PARAM 481713e81bSScott Long { 491713e81bSScott Long DEVICEID idMirror; 501713e81bSScott Long DWORD Lba; 511713e81bSScott Long UCHAR nSector; 521713e81bSScott Long } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM; 531713e81bSScott Long 541713e81bSScott Long #pragma pack() 551713e81bSScott Long 561713e81bSScott Long #define MAX_EVENTS 10 571713e81bSScott Long static HPT_EVENT hpt_event_queue[MAX_EVENTS]; 581713e81bSScott Long static int event_queue_head=0, event_queue_tail=0; 591713e81bSScott Long 601713e81bSScott Long static int hpt_get_event(PHPT_EVENT pEvent); 611713e81bSScott Long static int hpt_set_array_state(DEVICEID idArray, DWORD state); 6249b3fc40SJohn Baldwin static void lock_driver_idle(IAL_ADAPTER_T *pAdapter); 631713e81bSScott Long static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); 641713e81bSScott Long static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, 651713e81bSScott Long FPSCAT_GATH pSgTable, int logical); 661713e81bSScott Long 67d2bd3ab9SScott Long static void 68d2bd3ab9SScott Long get_disk_location(PDevice pDev, int *controller, int *channel) 691713e81bSScott Long { 701713e81bSScott Long IAL_ADAPTER_T *pAdapTemp; 711713e81bSScott Long int i, j; 721713e81bSScott Long 73b8fdb7f9SMatt Jacob *controller = *channel = 0; 74b8fdb7f9SMatt Jacob 751713e81bSScott Long for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) { 76b8fdb7f9SMatt Jacob for (j=0; j<MV_SATA_CHANNELS_NUM; j++) { 771713e81bSScott Long if (pDev == &pAdapTemp->VDevices[j].u.disk) { 781713e81bSScott Long *controller = i; 791713e81bSScott Long *channel = j; 801713e81bSScott Long return; 811713e81bSScott Long } 821713e81bSScott Long } 831713e81bSScott Long } 84b8fdb7f9SMatt Jacob } 851713e81bSScott Long 86d2bd3ab9SScott Long static int 87d2bd3ab9SScott Long event_queue_add(PHPT_EVENT pEvent) 881713e81bSScott Long { 891713e81bSScott Long int p; 901713e81bSScott Long p = (event_queue_tail + 1) % MAX_EVENTS; 911713e81bSScott Long if (p==event_queue_head) 921713e81bSScott Long { 931713e81bSScott Long return -1; 941713e81bSScott Long } 951713e81bSScott Long hpt_event_queue[event_queue_tail] = *pEvent; 961713e81bSScott Long event_queue_tail = p; 971713e81bSScott Long return 0; 981713e81bSScott Long } 991713e81bSScott Long 100d2bd3ab9SScott Long static int 101d2bd3ab9SScott Long event_queue_remove(PHPT_EVENT pEvent) 1021713e81bSScott Long { 1031713e81bSScott Long if (event_queue_head != event_queue_tail) 1041713e81bSScott Long { 1051713e81bSScott Long *pEvent = hpt_event_queue[event_queue_head]; 1061713e81bSScott Long event_queue_head++; 1071713e81bSScott Long event_queue_head %= MAX_EVENTS; 1081713e81bSScott Long return 0; 1091713e81bSScott Long } 1101713e81bSScott Long return -1; 1111713e81bSScott Long } 1121713e81bSScott Long 113d2bd3ab9SScott Long void HPTLIBAPI 114d2bd3ab9SScott Long ioctl_ReportEvent(UCHAR event, PVOID param) 1151713e81bSScott Long { 1161713e81bSScott Long HPT_EVENT e; 1171713e81bSScott Long ZeroMemory(&e, sizeof(e)); 1181713e81bSScott Long e.EventType = event; 1191713e81bSScott Long switch(event) 1201713e81bSScott Long { 1211713e81bSScott Long case ET_INITIALIZE_ABORTED: 1221713e81bSScott Long case ET_INITIALIZE_FAILED: 1231713e81bSScott Long memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME); 1241713e81bSScott Long case ET_INITIALIZE_STARTED: 1251713e81bSScott Long case ET_INITIALIZE_FINISHED: 1261713e81bSScott Long 1271713e81bSScott Long case ET_REBUILD_STARTED: 1281713e81bSScott Long case ET_REBUILD_ABORTED: 1291713e81bSScott Long case ET_REBUILD_FAILED: 1301713e81bSScott Long case ET_REBUILD_FINISHED: 1311713e81bSScott Long 1321713e81bSScott Long case ET_VERIFY_STARTED: 1331713e81bSScott Long case ET_VERIFY_ABORTED: 1341713e81bSScott Long case ET_VERIFY_FAILED: 1351713e81bSScott Long case ET_VERIFY_FINISHED: 1361713e81bSScott Long case ET_VERIFY_DATA_ERROR: 1371713e81bSScott Long 1381713e81bSScott Long case ET_SPARE_TOOK_OVER: 1391713e81bSScott Long case ET_DEVICE_REMOVED: 1401713e81bSScott Long case ET_DEVICE_PLUGGED: 1411713e81bSScott Long case ET_DEVICE_ERROR: 1421713e81bSScott Long e.DeviceID = VDEV_TO_ID((PVDevice)param); 1431713e81bSScott Long break; 1441713e81bSScott Long 1451713e81bSScott Long default: 1461713e81bSScott Long break; 1471713e81bSScott Long } 1481713e81bSScott Long event_queue_add(&e); 1491713e81bSScott Long if (event==ET_DEVICE_REMOVED) { 150b8fdb7f9SMatt Jacob int controller, channel; 1511713e81bSScott Long get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel); 1521713e81bSScott Long hpt_printk(("Device removed: controller %d channel %d\n", controller, channel)); 1531713e81bSScott Long } 15449b3fc40SJohn Baldwin wakeup(param); 1551713e81bSScott Long } 1561713e81bSScott Long 157d2bd3ab9SScott Long static int 158d2bd3ab9SScott Long hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) 1591713e81bSScott Long { 1601713e81bSScott Long PVDevice pArray = ID_TO_VDEV(id); 1611713e81bSScott Long BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; 1621713e81bSScott Long int i; 1631713e81bSScott Long PVDevice pa; 1641713e81bSScott Long 165d2bd3ab9SScott Long if ((id==0) || check_VDevice_valid(pArray)) 1661713e81bSScott Long return -1; 1671713e81bSScott Long 1681713e81bSScott Long if(!mIsArray(pArray)) return -1; 1691713e81bSScott Long 1701713e81bSScott Long if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying || 1711713e81bSScott Long pArray->u.array.rf_initializing) 1721713e81bSScott Long return -1; 1731713e81bSScott Long 1741713e81bSScott Long for(i=0; i<pArray->u.array.bArnMember; i++) { 1751713e81bSScott Long pa = pArray->u.array.pMember[i]; 1761713e81bSScott Long if (pa && mIsArray(pa)) { 1771713e81bSScott Long if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 1781713e81bSScott Long pa->u.array.rf_initializing) 1791713e81bSScott Long return -1; 1801713e81bSScott Long } 1811713e81bSScott Long } 1821713e81bSScott Long 1831713e81bSScott Long if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 1841713e81bSScott Long fDeleteArray(_VBUS_P pArray, del_block0); 1851713e81bSScott Long return 0; 1861713e81bSScott Long 1871713e81bSScott Long } 1881713e81bSScott Long 1891713e81bSScott Long /* just to prevent driver from sending more commands */ 1901713e81bSScott Long static void HPTLIBAPI nothing(_VBUS_ARG void *notused){} 1911713e81bSScott Long 19249b3fc40SJohn Baldwin void 193d2bd3ab9SScott Long lock_driver_idle(IAL_ADAPTER_T *pAdapter) 1941713e81bSScott Long { 1951713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 19649b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 1971713e81bSScott Long while (pAdapter->outstandingCommands) { 1981713e81bSScott Long KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); 1991713e81bSScott Long if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 20049b3fc40SJohn Baldwin mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0); 2011713e81bSScott Long } 2021713e81bSScott Long CheckIdleCall(_VBUS_P0); 2031713e81bSScott Long } 2041713e81bSScott Long 2051713e81bSScott Long int Kernel_DeviceIoControl(_VBUS_ARG 2061713e81bSScott Long DWORD dwIoControlCode, /* operation control code */ 2071713e81bSScott Long PVOID lpInBuffer, /* input data buffer */ 2081713e81bSScott Long DWORD nInBufferSize, /* size of input data buffer */ 2091713e81bSScott Long PVOID lpOutBuffer, /* output data buffer */ 2101713e81bSScott Long DWORD nOutBufferSize, /* size of output data buffer */ 2111713e81bSScott Long PDWORD lpBytesReturned /* byte count */ 2121713e81bSScott Long ) 2131713e81bSScott Long { 2141713e81bSScott Long IAL_ADAPTER_T *pAdapter; 2151713e81bSScott Long 2161713e81bSScott Long switch(dwIoControlCode) { 2171713e81bSScott Long case HPT_IOCTL_DELETE_ARRAY: 2181713e81bSScott Long { 2191713e81bSScott Long DEVICEID idArray; 2201713e81bSScott Long int iSuccess; 2211713e81bSScott Long int i; 2221713e81bSScott Long PVDevice pArray; 2231713e81bSScott Long PVBus _vbus_p; 2241713e81bSScott Long struct cam_periph *periph = NULL; 2251713e81bSScott Long 2261713e81bSScott Long if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; 2271713e81bSScott Long if (nOutBufferSize!=sizeof(int)) return -1; 2281713e81bSScott Long idArray = *(DEVICEID *)lpInBuffer; 2291713e81bSScott Long 2301713e81bSScott Long pArray = ID_TO_VDEV(idArray); 2311713e81bSScott Long 232d2bd3ab9SScott Long if((idArray == 0) || check_VDevice_valid(pArray)) 2331713e81bSScott Long return -1; 2341713e81bSScott Long 2351713e81bSScott Long if(!mIsArray(pArray)) 2361713e81bSScott Long return -1; 2371713e81bSScott Long 2381713e81bSScott Long _vbus_p=pArray->pVBus; 2391713e81bSScott Long pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 2401713e81bSScott Long 2411713e81bSScott Long for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { 2421713e81bSScott Long if(pArray == _vbus_p->pVDevice[i]) 2431713e81bSScott Long { 2441713e81bSScott Long periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 245d2bd3ab9SScott Long if (periph != NULL && periph->refcount >= 1) 2461713e81bSScott Long { 2471713e81bSScott Long hpt_printk(("Can not delete a mounted device.\n")); 2481713e81bSScott Long return -1; 2491713e81bSScott Long } 2501713e81bSScott Long } 2511713e81bSScott Long /* the Mounted Disk isn't delete */ 2521713e81bSScott Long } 2531713e81bSScott Long 2541713e81bSScott Long iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); 2551713e81bSScott Long 2561713e81bSScott Long *(int*)lpOutBuffer = iSuccess; 2571713e81bSScott Long 2581713e81bSScott Long if(iSuccess != 0) 2591713e81bSScott Long return -1; 2601713e81bSScott Long break; 2611713e81bSScott Long } 2621713e81bSScott Long 2631713e81bSScott Long case HPT_IOCTL_GET_EVENT: 2641713e81bSScott Long { 2651713e81bSScott Long PHPT_EVENT pInfo; 2661713e81bSScott Long 2671713e81bSScott Long if (nInBufferSize!=0) return -1; 2681713e81bSScott Long if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; 2691713e81bSScott Long 2701713e81bSScott Long pInfo = (PHPT_EVENT)lpOutBuffer; 2711713e81bSScott Long 2721713e81bSScott Long if (hpt_get_event(pInfo)!=0) 2731713e81bSScott Long return -1; 2741713e81bSScott Long } 2751713e81bSScott Long break; 2761713e81bSScott Long 2771713e81bSScott Long case HPT_IOCTL_SET_ARRAY_STATE: 2781713e81bSScott Long { 2791713e81bSScott Long DEVICEID idArray; 2801713e81bSScott Long DWORD state; 2811713e81bSScott Long 2821713e81bSScott Long if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; 2831713e81bSScott Long if (nOutBufferSize!=0) return -1; 2841713e81bSScott Long 2851713e81bSScott Long idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; 2861713e81bSScott Long state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; 2871713e81bSScott Long 2881713e81bSScott Long if(hpt_set_array_state(idArray, state)!=0) 2891713e81bSScott Long return -1; 2901713e81bSScott Long } 2911713e81bSScott Long break; 2921713e81bSScott Long 2931713e81bSScott Long case HPT_IOCTL_RESCAN_DEVICES: 2941713e81bSScott Long { 2951713e81bSScott Long if (nInBufferSize!=0) return -1; 2961713e81bSScott Long if (nOutBufferSize!=0) return -1; 2971713e81bSScott Long 2981713e81bSScott Long #ifndef FOR_DEMO 2991713e81bSScott Long /* stop buzzer if user perform rescan */ 3001713e81bSScott Long for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 3011713e81bSScott Long if (pAdapter->beeping) { 3021713e81bSScott Long pAdapter->beeping = 0; 3031713e81bSScott Long BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 3041713e81bSScott Long } 3051713e81bSScott Long } 3061713e81bSScott Long #endif 3071713e81bSScott Long } 3081713e81bSScott Long break; 3091713e81bSScott Long 3101713e81bSScott Long default: 3111713e81bSScott Long { 3121713e81bSScott Long PVDevice pVDev; 31349b3fc40SJohn Baldwin 3141713e81bSScott Long switch(dwIoControlCode) { 3151713e81bSScott Long /* read-only ioctl functions can be called directly. */ 3161713e81bSScott Long case HPT_IOCTL_GET_VERSION: 3171713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_IDS: 3181713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_COUNT: 3191713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_INFO: 3201713e81bSScott Long case HPT_IOCTL_GET_CHANNEL_INFO: 3211713e81bSScott Long case HPT_IOCTL_GET_LOGICAL_DEVICES: 3221713e81bSScott Long case HPT_IOCTL_GET_DEVICE_INFO: 32364470755SXin LI case HPT_IOCTL_GET_DEVICE_INFO_V2: 3241713e81bSScott Long case HPT_IOCTL_GET_EVENT: 3251713e81bSScott Long case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 3261713e81bSScott Long if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 3271713e81bSScott Long lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; 3281713e81bSScott Long break; 3291713e81bSScott Long 3301713e81bSScott Long default: 3311713e81bSScott Long /* 3321713e81bSScott Long * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 3331713e81bSScott Long * wrong for second controller. 3341713e81bSScott Long */ 3351713e81bSScott Long switch(dwIoControlCode) { 3361713e81bSScott Long case HPT_IOCTL_CREATE_ARRAY: 3371713e81bSScott Long pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; 33864470755SXin LI case HPT_IOCTL_CREATE_ARRAY_V2: 33964470755SXin LI pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break; 3401713e81bSScott Long case HPT_IOCTL_SET_ARRAY_INFO: 3411713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; 3421713e81bSScott Long case HPT_IOCTL_SET_DEVICE_INFO: 3431713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; 34464470755SXin LI case HPT_IOCTL_SET_DEVICE_INFO_V2: 34564470755SXin LI pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break; 3461713e81bSScott Long case HPT_IOCTL_SET_BOOT_MARK: 3471713e81bSScott Long case HPT_IOCTL_ADD_SPARE_DISK: 3481713e81bSScott Long case HPT_IOCTL_REMOVE_SPARE_DISK: 3491713e81bSScott Long pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; 3501713e81bSScott Long case HPT_IOCTL_ADD_DISK_TO_ARRAY: 3511713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; 3521713e81bSScott Long default: 3531713e81bSScott Long pVDev = 0; 3541713e81bSScott Long } 3551713e81bSScott Long 3561713e81bSScott Long if (pVDev && !check_VDevice_valid(pVDev)){ 3571713e81bSScott Long _vbus_p = pVDev->pVBus; 3581713e81bSScott Long 3591713e81bSScott Long pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 3601713e81bSScott Long /* 3611713e81bSScott Long * create_array, and other functions can't be executed while channel is 3621713e81bSScott Long * perform I/O commands. Wait until driver is idle. 3631713e81bSScott Long */ 36449b3fc40SJohn Baldwin lock_driver_idle(pAdapter); 3651713e81bSScott Long if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 3661713e81bSScott Long lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { 36749b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 3681713e81bSScott Long return -1; 3691713e81bSScott Long } 37049b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 3711713e81bSScott Long } 3721713e81bSScott Long else 3731713e81bSScott Long return -1; 3741713e81bSScott Long break; 3751713e81bSScott Long } 3761713e81bSScott Long 3771713e81bSScott Long #ifdef SUPPORT_ARRAY 3781713e81bSScott Long switch(dwIoControlCode) 3791713e81bSScott Long { 3801713e81bSScott Long case HPT_IOCTL_CREATE_ARRAY: 3811713e81bSScott Long { 3821713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 38349b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 3841713e81bSScott Long if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) 3851713e81bSScott Long { 3861713e81bSScott Long (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 3871713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 3881713e81bSScott Long } 3891713e81bSScott Long else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) 3901713e81bSScott Long { 3911713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 3921713e81bSScott Long } 3931713e81bSScott Long else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) 3941713e81bSScott Long { 3951713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 3961713e81bSScott Long } 39749b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 3981713e81bSScott Long break; 3991713e81bSScott Long } 4001713e81bSScott Long 40164470755SXin LI 40264470755SXin LI case HPT_IOCTL_CREATE_ARRAY_V2: 40364470755SXin LI { 40464470755SXin LI pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 40549b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 40664470755SXin LI if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) { 40764470755SXin LI (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 40864470755SXin LI hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 40964470755SXin LI } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) { 41064470755SXin LI hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 41164470755SXin LI } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) { 41264470755SXin LI hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 41364470755SXin LI } 41449b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 41564470755SXin LI break; 41664470755SXin LI } 4171713e81bSScott Long case HPT_IOCTL_ADD_DISK_TO_ARRAY: 4181713e81bSScott Long { 4191713e81bSScott Long PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); 4201713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; 421d2bd3ab9SScott Long if(pArray->u.array.rf_rebuilding == 0) 4221713e81bSScott Long { 42349b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 4241713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0; 4251713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 4261713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 4271713e81bSScott Long while (!pArray->u.array.rf_rebuilding) 4281713e81bSScott Long { 42949b3fc40SJohn Baldwin if (mtx_sleep(pArray, &pAdapter->lock, 0, "hptwait", hz * 3) != 0) 4301713e81bSScott Long break; 4311713e81bSScott Long } 43249b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 4331713e81bSScott Long } 4341713e81bSScott Long break; 4351713e81bSScott Long } 4361713e81bSScott Long } 4371713e81bSScott Long #endif 4381713e81bSScott Long return 0; 4391713e81bSScott Long } 4401713e81bSScott Long } 4411713e81bSScott Long 4421713e81bSScott Long if (lpBytesReturned) 4431713e81bSScott Long *lpBytesReturned = nOutBufferSize; 4441713e81bSScott Long return 0; 4451713e81bSScott Long } 4461713e81bSScott Long 447d2bd3ab9SScott Long static int 448d2bd3ab9SScott Long hpt_get_event(PHPT_EVENT pEvent) 4491713e81bSScott Long { 4501713e81bSScott Long int ret = event_queue_remove(pEvent); 4511713e81bSScott Long return ret; 4521713e81bSScott Long } 4531713e81bSScott Long 454d2bd3ab9SScott Long static int 455d2bd3ab9SScott Long hpt_set_array_state(DEVICEID idArray, DWORD state) 4561713e81bSScott Long { 4571713e81bSScott Long IAL_ADAPTER_T *pAdapter; 4581713e81bSScott Long PVDevice pVDevice = ID_TO_VDEV(idArray); 4591713e81bSScott Long int i; 4601713e81bSScott Long 461d2bd3ab9SScott Long if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; 4621713e81bSScott Long if(!mIsArray(pVDevice)) 4631713e81bSScott Long return -1; 4641713e81bSScott Long if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; 4651713e81bSScott Long 4661713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt; 4671713e81bSScott Long 4681713e81bSScott Long switch(state) 4691713e81bSScott Long { 4701713e81bSScott Long case MIRROR_REBUILD_START: 4711713e81bSScott Long { 47249b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 4731713e81bSScott Long if (pVDevice->u.array.rf_rebuilding || 4741713e81bSScott Long pVDevice->u.array.rf_verifying || 47549b3fc40SJohn Baldwin pVDevice->u.array.rf_initializing) { 47649b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 4771713e81bSScott Long return -1; 47849b3fc40SJohn Baldwin } 4791713e81bSScott Long 4801713e81bSScott Long pVDevice->u.array.rf_auto_rebuild = 0; 4811713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 0; 4821713e81bSScott Long 4831713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 4841713e81bSScott Long (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 4851713e81bSScott Long 4861713e81bSScott Long while (!pVDevice->u.array.rf_rebuilding) 4871713e81bSScott Long { 48849b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0, 48949b3fc40SJohn Baldwin "hptwait", hz * 20) != 0) 4901713e81bSScott Long break; 4911713e81bSScott Long } 49249b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 4931713e81bSScott Long } 4941713e81bSScott Long 4951713e81bSScott Long break; 4961713e81bSScott Long 4971713e81bSScott Long case MIRROR_REBUILD_ABORT: 4981713e81bSScott Long { 4991713e81bSScott Long for(i = 0; i < pVDevice->u.array.bArnMember; i++) { 500d2bd3ab9SScott Long if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) 5011713e81bSScott Long hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); 5021713e81bSScott Long } 5031713e81bSScott Long 50449b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 50549b3fc40SJohn Baldwin if(pVDevice->u.array.rf_rebuilding != 1) { 50649b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5071713e81bSScott Long return -1; 50849b3fc40SJohn Baldwin } 5091713e81bSScott Long 5101713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1; 5111713e81bSScott Long 5121713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild) 5131713e81bSScott Long { 51449b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0, 51549b3fc40SJohn Baldwin "hptabrt", hz * 20) != 0) 5161713e81bSScott Long break; 5171713e81bSScott Long } 51849b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5191713e81bSScott Long } 5201713e81bSScott Long break; 5211713e81bSScott Long 5221713e81bSScott Long case AS_VERIFY_START: 5231713e81bSScott Long { 5241713e81bSScott Long /*if(pVDevice->u.array.rf_verifying) 5251713e81bSScott Long return -1;*/ 52649b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 5271713e81bSScott Long if (pVDevice->u.array.rf_rebuilding || 5281713e81bSScott Long pVDevice->u.array.rf_verifying || 52949b3fc40SJohn Baldwin pVDevice->u.array.rf_initializing) { 53049b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5311713e81bSScott Long return -1; 53249b3fc40SJohn Baldwin } 5331713e81bSScott Long 5341713e81bSScott Long pVDevice->u.array.RebuildSectors = 0; 5351713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 5361713e81bSScott Long 5371713e81bSScott Long while (!pVDevice->u.array.rf_verifying) 5381713e81bSScott Long { 53949b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0, 54049b3fc40SJohn Baldwin "hptvrfy", hz * 20) != 0) 5411713e81bSScott Long break; 5421713e81bSScott Long } 54349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5441713e81bSScott Long } 5451713e81bSScott Long break; 5461713e81bSScott Long 5471713e81bSScott Long case AS_VERIFY_ABORT: 5481713e81bSScott Long { 54949b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 55049b3fc40SJohn Baldwin if(pVDevice->u.array.rf_verifying != 1) { 55149b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5521713e81bSScott Long return -1; 55349b3fc40SJohn Baldwin } 5541713e81bSScott Long 5551713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1; 5561713e81bSScott Long 5571713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild) 5581713e81bSScott Long { 55949b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0, 56049b3fc40SJohn Baldwin "hptvrfy", hz * 80) != 0) 5611713e81bSScott Long break; 5621713e81bSScott Long } 56349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5641713e81bSScott Long } 5651713e81bSScott Long break; 5661713e81bSScott Long 5671713e81bSScott Long case AS_INITIALIZE_START: 5681713e81bSScott Long { 56949b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 5701713e81bSScott Long if (pVDevice->u.array.rf_rebuilding || 5711713e81bSScott Long pVDevice->u.array.rf_verifying || 57249b3fc40SJohn Baldwin pVDevice->u.array.rf_initializing) { 57349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5741713e81bSScott Long return -1; 57549b3fc40SJohn Baldwin } 5761713e81bSScott Long 5771713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 5781713e81bSScott Long 5791713e81bSScott Long while (!pVDevice->u.array.rf_initializing) 5801713e81bSScott Long { 58149b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0, 58249b3fc40SJohn Baldwin "hptinit", hz * 80) != 0) 5831713e81bSScott Long break; 5841713e81bSScott Long } 58549b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5861713e81bSScott Long } 5871713e81bSScott Long break; 5881713e81bSScott Long 5891713e81bSScott Long case AS_INITIALIZE_ABORT: 5901713e81bSScott Long { 59149b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 59249b3fc40SJohn Baldwin if(pVDevice->u.array.rf_initializing != 1) { 59349b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 5941713e81bSScott Long return -1; 59549b3fc40SJohn Baldwin } 5961713e81bSScott Long 5971713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1; 5981713e81bSScott Long 5991713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild) 6001713e81bSScott Long { 60149b3fc40SJohn Baldwin if (mtx_sleep(pVDevice, &pAdapter->lock, 0, 60249b3fc40SJohn Baldwin "hptinit", hz * 80) != 0) 6031713e81bSScott Long break; 6041713e81bSScott Long } 60549b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 6061713e81bSScott Long } 6071713e81bSScott Long break; 6081713e81bSScott Long 6091713e81bSScott Long default: 6101713e81bSScott Long return -1; 6111713e81bSScott Long } 6121713e81bSScott Long 6131713e81bSScott Long return 0; 6141713e81bSScott Long } 6151713e81bSScott Long 616d2bd3ab9SScott Long int HPTLIBAPI 617d2bd3ab9SScott Long R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) 6181713e81bSScott Long { 6191713e81bSScott Long ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); 6201713e81bSScott Long if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) 6211713e81bSScott Long bufferSize<<=1; 6221713e81bSScott Long if (logical) { 6231713e81bSScott Long pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; 6241713e81bSScott Long pSgTable->wSgSize = (USHORT)bufferSize; 6251713e81bSScott Long pSgTable->wSgFlag = SG_FLAG_EOT; 6261713e81bSScott Long } 6271713e81bSScott Long else { 6281713e81bSScott Long /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ 6291713e81bSScott Long ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; 6301713e81bSScott Long ULONG length; 6311713e81bSScott Long int idx = 0; 6321713e81bSScott Long 6331713e81bSScott Long v = pCmd->uCmd.R1Control.Buffer; 6341713e81bSScott Long dataPointer = (ADDRESS)fOsPhysicalAddress(v); 6351713e81bSScott Long 6361713e81bSScott Long if ((ULONG_PTR)dataPointer & 0x1) 6371713e81bSScott Long return FALSE; 6381713e81bSScott Long 6391713e81bSScott Long #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) 6401713e81bSScott Long #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) 6411713e81bSScott Long 6421713e81bSScott Long do { 6431713e81bSScott Long if (idx >= MAX_SG_DESCRIPTORS) return FALSE; 6441713e81bSScott Long 6451713e81bSScott Long pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); 6461713e81bSScott Long currvaddr = v; 6471713e81bSScott Long currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); 6481713e81bSScott Long 6491713e81bSScott Long 6501713e81bSScott Long do { 6511713e81bSScott Long nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); 6521713e81bSScott Long nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); 6531713e81bSScott Long 6541713e81bSScott Long if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; 6551713e81bSScott Long nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); 6561713e81bSScott Long 6571713e81bSScott Long if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { 6581713e81bSScott Long nextvaddr = nextpage; 6591713e81bSScott Long break; 6601713e81bSScott Long } 6611713e81bSScott Long 6621713e81bSScott Long currvaddr = nextvaddr; 6631713e81bSScott Long currphypage = nextphypage; 6641713e81bSScott Long }while (1); 6651713e81bSScott Long 6661713e81bSScott Long length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; 6671713e81bSScott Long v = nextvaddr; 6681713e81bSScott Long bufferSize -= length; 6691713e81bSScott Long 6701713e81bSScott Long pSgTable[idx].wSgSize = (USHORT)length; 6711713e81bSScott Long pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; 6721713e81bSScott Long idx++; 6731713e81bSScott Long 6741713e81bSScott Long }while (bufferSize); 6751713e81bSScott Long } 6761713e81bSScott Long return 1; 6771713e81bSScott Long } 6781713e81bSScott Long 6791713e81bSScott Long static int End_Job=0; 680d2bd3ab9SScott Long void HPTLIBAPI 681d2bd3ab9SScott Long thread_io_done(_VBUS_ARG PCommand pCmd) 6821713e81bSScott Long { 6831713e81bSScott Long End_Job = 1; 6841713e81bSScott Long wakeup((caddr_t)pCmd); 6851713e81bSScott Long } 6861713e81bSScott Long 687d2bd3ab9SScott Long void 688d2bd3ab9SScott Long hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) 6891713e81bSScott Long { 6901713e81bSScott Long ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); 6911713e81bSScott Long PCommand pCmd; 6921713e81bSScott Long UINT result; 6931713e81bSScott Long int needsync=0, retry=0, needdelete=0; 694*4d24901aSPedro F. Giffuni void *buffer = NULL; 6951713e81bSScott Long 6961713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 6971713e81bSScott Long 6981713e81bSScott Long if (pArray->u.array.rf_broken==1 || 6991713e81bSScott Long pArray->u.array.RebuildSectors>=capacity) 7001713e81bSScott Long return; 7011713e81bSScott Long 70249b3fc40SJohn Baldwin mtx_lock(&pAdapter->lock); 7031713e81bSScott Long 7041713e81bSScott Long switch(flags) 7051713e81bSScott Long { 7061713e81bSScott Long case DUPLICATE: 7071713e81bSScott Long case REBUILD_PARITY: 7081713e81bSScott Long if(pArray->u.array.rf_rebuilding == 0) 7091713e81bSScott Long { 7101713e81bSScott Long pArray->u.array.rf_rebuilding = 1; 7111713e81bSScott Long hpt_printk(("Rebuilding started.\n")); 7121713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); 7131713e81bSScott Long } 7141713e81bSScott Long break; 7151713e81bSScott Long 7161713e81bSScott Long case INITIALIZE: 7171713e81bSScott Long if(pArray->u.array.rf_initializing == 0) 7181713e81bSScott Long { 7191713e81bSScott Long pArray->u.array.rf_initializing = 1; 7201713e81bSScott Long hpt_printk(("Initializing started.\n")); 7211713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); 7221713e81bSScott Long } 7231713e81bSScott Long break; 7241713e81bSScott Long 7251713e81bSScott Long case VERIFY: 7261713e81bSScott Long if(pArray->u.array.rf_verifying == 0) 7271713e81bSScott Long { 7281713e81bSScott Long pArray->u.array.rf_verifying = 1; 7291713e81bSScott Long hpt_printk(("Verifying started.\n")); 7301713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); 7311713e81bSScott Long } 7321713e81bSScott Long break; 7331713e81bSScott Long } 7341713e81bSScott Long 7351713e81bSScott Long retry_cmd: 7361713e81bSScott Long pCmd = AllocateCommand(_VBUS_P0); 7371713e81bSScott Long HPT_ASSERT(pCmd); 7381713e81bSScott Long pCmd->cf_control = 1; 7391713e81bSScott Long End_Job = 0; 7401713e81bSScott Long 7411713e81bSScott Long if (pArray->VDeviceType==VD_RAID_1) 7421713e81bSScott Long { 7431713e81bSScott Long #define MAX_REBUILD_SECTORS 0x40 7441713e81bSScott Long 7451713e81bSScott Long /* take care for discontinuous buffer in R1ControlSgl */ 7461713e81bSScott Long buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); 7471713e81bSScott Long if(!buffer) { 7481713e81bSScott Long FreeCommand(_VBUS_P pCmd); 7491713e81bSScott Long hpt_printk(("can't allocate rebuild buffer\n")); 7501713e81bSScott Long goto fail; 7511713e81bSScott Long } 7521713e81bSScott Long switch(flags) 7531713e81bSScott Long { 7541713e81bSScott Long case DUPLICATE: 7551713e81bSScott Long pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 7561713e81bSScott Long pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 7571713e81bSScott Long break; 7581713e81bSScott Long 7591713e81bSScott Long case VERIFY: 7601713e81bSScott Long pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; 7611713e81bSScott Long pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; 7621713e81bSScott Long break; 7631713e81bSScott Long 7641713e81bSScott Long case INITIALIZE: 7651713e81bSScott Long pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 7661713e81bSScott Long pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 7671713e81bSScott Long break; 7681713e81bSScott Long } 7691713e81bSScott Long 7701713e81bSScott Long pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; 7711713e81bSScott Long 7721713e81bSScott Long if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) 7731713e81bSScott Long pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; 7741713e81bSScott Long 7751713e81bSScott Long pCmd->uCmd.R1Control.Buffer = buffer; 7761713e81bSScott Long pCmd->pfnBuildSgl = R1ControlSgl; 7771713e81bSScott Long } 7781713e81bSScott Long else if (pArray->VDeviceType==VD_RAID_5) 7791713e81bSScott Long { 7801713e81bSScott Long switch(flags) 7811713e81bSScott Long { 7821713e81bSScott Long case DUPLICATE: 7831713e81bSScott Long case REBUILD_PARITY: 7841713e81bSScott Long pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; 7851713e81bSScott Long case VERIFY: 7861713e81bSScott Long pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; 7871713e81bSScott Long case INITIALIZE: 7881713e81bSScott Long pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; 7891713e81bSScott Long } 7901713e81bSScott Long pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; 7911713e81bSScott Long } 7921713e81bSScott Long else 7931713e81bSScott Long HPT_ASSERT(0); 7941713e81bSScott Long 7951713e81bSScott Long pCmd->pVDevice = pArray; 7961713e81bSScott Long pCmd->pfnCompletion = thread_io_done; 7971713e81bSScott Long pArray->pfnSendCommand(_VBUS_P pCmd); 7981713e81bSScott Long CheckPendingCall(_VBUS_P0); 7991713e81bSScott Long 8001713e81bSScott Long if (!End_Job) { 80149b3fc40SJohn Baldwin mtx_sleep(pCmd, &pAdapter->lock, 0, "hptrbld", hz * 60); 8021713e81bSScott Long if (!End_Job) { 8031713e81bSScott Long hpt_printk(("timeout, reset\n")); 8041713e81bSScott Long fResetVBus(_VBUS_P0); 8051713e81bSScott Long } 8061713e81bSScott Long } 8071713e81bSScott Long 8081713e81bSScott Long result = pCmd->Result; 8091713e81bSScott Long FreeCommand(_VBUS_P pCmd); 810d2bd3ab9SScott Long if (buffer) free(buffer, M_DEVBUF); 8111713e81bSScott Long KdPrintI(("cmd finished %d", result)); 8121713e81bSScott Long 8131713e81bSScott Long switch(result) 8141713e81bSScott Long { 8151713e81bSScott Long case RETURN_SUCCESS: 8161713e81bSScott Long if (!pArray->u.array.rf_abort_rebuild) 8171713e81bSScott Long { 8181713e81bSScott Long if(pArray->u.array.RebuildSectors < capacity) 8191713e81bSScott Long { 8201713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); 8211713e81bSScott Long } 8221713e81bSScott Long else 8231713e81bSScott Long { 8241713e81bSScott Long switch (flags) 8251713e81bSScott Long { 8261713e81bSScott Long case DUPLICATE: 8271713e81bSScott Long case REBUILD_PARITY: 8281713e81bSScott Long needsync = 1; 8291713e81bSScott Long pArray->u.array.rf_rebuilding = 0; 8301713e81bSScott Long pArray->u.array.rf_need_rebuild = 0; 8311713e81bSScott Long pArray->u.array.CriticalMembers = 0; 8321713e81bSScott Long pArray->u.array.RebuildSectors = MAX_LBA_T; 8331713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0; 8341713e81bSScott Long hpt_printk(("Rebuilding finished.\n")); 8351713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); 8361713e81bSScott Long break; 8371713e81bSScott Long case INITIALIZE: 8381713e81bSScott Long needsync = 1; 8391713e81bSScott Long pArray->u.array.rf_initializing = 0; 8401713e81bSScott Long pArray->u.array.rf_need_rebuild = 0; 8411713e81bSScott Long pArray->u.array.RebuildSectors = MAX_LBA_T; 8421713e81bSScott Long hpt_printk(("Initializing finished.\n")); 8431713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); 8441713e81bSScott Long break; 8451713e81bSScott Long case VERIFY: 8461713e81bSScott Long pArray->u.array.rf_verifying = 0; 8471713e81bSScott Long hpt_printk(("Verifying finished.\n")); 8481713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); 8491713e81bSScott Long break; 8501713e81bSScott Long } 8511713e81bSScott Long } 8521713e81bSScott Long } 8531713e81bSScott Long else 8541713e81bSScott Long { 8551713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 8561713e81bSScott Long if (pArray->u.array.rf_rebuilding) 8571713e81bSScott Long { 8581713e81bSScott Long hpt_printk(("Abort rebuilding.\n")); 8591713e81bSScott Long pArray->u.array.rf_rebuilding = 0; 8601713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0; 8611713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); 8621713e81bSScott Long } 8631713e81bSScott Long else if (pArray->u.array.rf_verifying) 8641713e81bSScott Long { 8651713e81bSScott Long hpt_printk(("Abort verifying.\n")); 8661713e81bSScott Long pArray->u.array.rf_verifying = 0; 8671713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); 8681713e81bSScott Long } 8691713e81bSScott Long else if (pArray->u.array.rf_initializing) 8701713e81bSScott Long { 8711713e81bSScott Long hpt_printk(("Abort initializing.\n")); 8721713e81bSScott Long pArray->u.array.rf_initializing = 0; 8731713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); 8741713e81bSScott Long } 8751713e81bSScott Long needdelete=1; 8761713e81bSScott Long } 8771713e81bSScott Long break; 8781713e81bSScott Long 8791713e81bSScott Long case RETURN_DATA_ERROR: 8801713e81bSScott Long if (flags==VERIFY) 8811713e81bSScott Long { 8821713e81bSScott Long needsync = 1; 8831713e81bSScott Long pArray->u.array.rf_verifying = 0; 8841713e81bSScott Long pArray->u.array.rf_need_rebuild = 1; 8851713e81bSScott Long hpt_printk(("Verifying failed: found inconsistency\n")); 8861713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); 8871713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 8881713e81bSScott Long 8891713e81bSScott Long if (!pArray->vf_online || pArray->u.array.rf_broken) break; 8901713e81bSScott Long 8911713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0; 8921713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 8931713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 8941713e81bSScott Long (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); 8951713e81bSScott Long } 8961713e81bSScott Long break; 8971713e81bSScott Long 8981713e81bSScott Long default: 8991713e81bSScott Long hpt_printk(("command failed with error %d\n", result)); 9001713e81bSScott Long if (++retry<3) 9011713e81bSScott Long { 9021713e81bSScott Long hpt_printk(("retry (%d)\n", retry)); 9031713e81bSScott Long goto retry_cmd; 9041713e81bSScott Long } 9051713e81bSScott Long fail: 9061713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 9071713e81bSScott Long switch (flags) 9081713e81bSScott Long { 9091713e81bSScott Long case DUPLICATE: 9101713e81bSScott Long case REBUILD_PARITY: 9111713e81bSScott Long needsync = 1; 9121713e81bSScott Long pArray->u.array.rf_rebuilding = 0; 9131713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0; 9141713e81bSScott Long hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); 9151713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); 9161713e81bSScott Long break; 9171713e81bSScott Long 9181713e81bSScott Long case INITIALIZE: 9191713e81bSScott Long needsync = 1; 9201713e81bSScott Long pArray->u.array.rf_initializing = 0; 9211713e81bSScott Long hpt_printk(("Initializing failed.\n")); 9221713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); 9231713e81bSScott Long break; 9241713e81bSScott Long 9251713e81bSScott Long case VERIFY: 9261713e81bSScott Long needsync = 1; 9271713e81bSScott Long pArray->u.array.rf_verifying = 0; 9281713e81bSScott Long hpt_printk(("Verifying failed.\n")); 9291713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 9301713e81bSScott Long break; 9311713e81bSScott Long } 9321713e81bSScott Long needdelete=1; 9331713e81bSScott Long } 9341713e81bSScott Long 9351713e81bSScott Long while (pAdapter->outstandingCommands) 9361713e81bSScott Long { 9371713e81bSScott Long KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); 9381713e81bSScott Long /* put this to have driver stop processing system commands quickly */ 9391713e81bSScott Long if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 94049b3fc40SJohn Baldwin mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0); 9411713e81bSScott Long } 9421713e81bSScott Long 9431713e81bSScott Long if (needsync) SyncArrayInfo(pArray); 9441713e81bSScott Long if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) 9451713e81bSScott Long fDeleteArray(_VBUS_P pArray, TRUE); 9461713e81bSScott Long 9471713e81bSScott Long Check_Idle_Call(pAdapter); 94849b3fc40SJohn Baldwin mtx_unlock(&pAdapter->lock); 9491713e81bSScott Long } 950