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 #if (__FreeBSD_version < 500000) 37d2bd3ab9SScott Long #include <sys/proc.h> 38d2bd3ab9SScott Long #include <sys/kthread.h> 39d2bd3ab9SScott Long #include <sys/wait.h> 40d2bd3ab9SScott Long #include <sys/sysproto.h> 41d2bd3ab9SScott Long #endif 42d2bd3ab9SScott Long 43d2bd3ab9SScott Long #ifndef __KERNEL__ 44d2bd3ab9SScott Long #define __KERNEL__ 45d2bd3ab9SScott Long #endif 46d2bd3ab9SScott Long 471713e81bSScott Long #include <dev/hptmv/global.h> 481713e81bSScott Long #include <dev/hptmv/hptintf.h> 491713e81bSScott Long #include <dev/hptmv/osbsd.h> 50f7f3900bSScott Long #include <dev/hptmv/access601.h> 511713e81bSScott Long 521713e81bSScott Long #pragma pack(1) 531713e81bSScott Long 541713e81bSScott Long typedef struct _HPT_REBUILD_PARAM 551713e81bSScott Long { 561713e81bSScott Long DEVICEID idMirror; 571713e81bSScott Long DWORD Lba; 581713e81bSScott Long UCHAR nSector; 591713e81bSScott Long } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM; 601713e81bSScott Long 611713e81bSScott Long #pragma pack() 621713e81bSScott Long 631713e81bSScott Long #define MAX_EVENTS 10 641713e81bSScott Long static HPT_EVENT hpt_event_queue[MAX_EVENTS]; 651713e81bSScott Long static int event_queue_head=0, event_queue_tail=0; 661713e81bSScott Long 671713e81bSScott Long static int hpt_get_event(PHPT_EVENT pEvent); 681713e81bSScott Long static int hpt_set_array_state(DEVICEID idArray, DWORD state); 691713e81bSScott Long static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter); 701713e81bSScott Long static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); 711713e81bSScott Long static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, 721713e81bSScott Long FPSCAT_GATH pSgTable, int logical); 731713e81bSScott Long 74d2bd3ab9SScott Long static void 75d2bd3ab9SScott Long get_disk_location(PDevice pDev, int *controller, int *channel) 761713e81bSScott Long { 771713e81bSScott Long IAL_ADAPTER_T *pAdapTemp; 781713e81bSScott Long int i, j; 791713e81bSScott Long 801713e81bSScott Long for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) { 811713e81bSScott Long for (j=0; j<MV_SATA_CHANNELS_NUM; j++) 821713e81bSScott Long if (pDev==&pAdapTemp->VDevices[j].u.disk) { 831713e81bSScott Long *controller = i; 841713e81bSScott Long *channel = j; 851713e81bSScott Long return; 861713e81bSScott Long } 871713e81bSScott Long } 881713e81bSScott Long } 891713e81bSScott Long 90d2bd3ab9SScott Long static int 91d2bd3ab9SScott Long event_queue_add(PHPT_EVENT pEvent) 921713e81bSScott Long { 931713e81bSScott Long int p; 941713e81bSScott Long p = (event_queue_tail + 1) % MAX_EVENTS; 951713e81bSScott Long if (p==event_queue_head) 961713e81bSScott Long { 971713e81bSScott Long return -1; 981713e81bSScott Long } 991713e81bSScott Long hpt_event_queue[event_queue_tail] = *pEvent; 1001713e81bSScott Long event_queue_tail = p; 1011713e81bSScott Long return 0; 1021713e81bSScott Long } 1031713e81bSScott Long 104d2bd3ab9SScott Long static int 105d2bd3ab9SScott Long event_queue_remove(PHPT_EVENT pEvent) 1061713e81bSScott Long { 1071713e81bSScott Long if (event_queue_head != event_queue_tail) 1081713e81bSScott Long { 1091713e81bSScott Long *pEvent = hpt_event_queue[event_queue_head]; 1101713e81bSScott Long event_queue_head++; 1111713e81bSScott Long event_queue_head %= MAX_EVENTS; 1121713e81bSScott Long return 0; 1131713e81bSScott Long } 1141713e81bSScott Long return -1; 1151713e81bSScott Long } 1161713e81bSScott Long 117d2bd3ab9SScott Long void HPTLIBAPI 118d2bd3ab9SScott Long ioctl_ReportEvent(UCHAR event, PVOID param) 1191713e81bSScott Long { 1201713e81bSScott Long HPT_EVENT e; 1211713e81bSScott Long ZeroMemory(&e, sizeof(e)); 1221713e81bSScott Long e.EventType = event; 1231713e81bSScott Long switch(event) 1241713e81bSScott Long { 1251713e81bSScott Long case ET_INITIALIZE_ABORTED: 1261713e81bSScott Long case ET_INITIALIZE_FAILED: 1271713e81bSScott Long memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME); 1281713e81bSScott Long case ET_INITIALIZE_STARTED: 1291713e81bSScott Long case ET_INITIALIZE_FINISHED: 1301713e81bSScott Long 1311713e81bSScott Long case ET_REBUILD_STARTED: 1321713e81bSScott Long case ET_REBUILD_ABORTED: 1331713e81bSScott Long case ET_REBUILD_FAILED: 1341713e81bSScott Long case ET_REBUILD_FINISHED: 1351713e81bSScott Long 1361713e81bSScott Long case ET_VERIFY_STARTED: 1371713e81bSScott Long case ET_VERIFY_ABORTED: 1381713e81bSScott Long case ET_VERIFY_FAILED: 1391713e81bSScott Long case ET_VERIFY_FINISHED: 1401713e81bSScott Long case ET_VERIFY_DATA_ERROR: 1411713e81bSScott Long 1421713e81bSScott Long case ET_SPARE_TOOK_OVER: 1431713e81bSScott Long case ET_DEVICE_REMOVED: 1441713e81bSScott Long case ET_DEVICE_PLUGGED: 1451713e81bSScott Long case ET_DEVICE_ERROR: 1461713e81bSScott Long e.DeviceID = VDEV_TO_ID((PVDevice)param); 1471713e81bSScott Long break; 1481713e81bSScott Long 1491713e81bSScott Long default: 1501713e81bSScott Long break; 1511713e81bSScott Long } 1521713e81bSScott Long event_queue_add(&e); 1531713e81bSScott Long if (event==ET_DEVICE_REMOVED) { 1541713e81bSScott Long int controller, channel; 1551713e81bSScott Long get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel); 1561713e81bSScott Long hpt_printk(("Device removed: controller %d channel %d\n", controller, channel)); 1571713e81bSScott Long } 1581713e81bSScott Long } 1591713e81bSScott Long 160d2bd3ab9SScott Long static int 161d2bd3ab9SScott Long hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) 1621713e81bSScott Long { 1631713e81bSScott Long PVDevice pArray = ID_TO_VDEV(id); 1641713e81bSScott Long BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; 1651713e81bSScott Long int i; 1661713e81bSScott Long PVDevice pa; 1671713e81bSScott Long 168d2bd3ab9SScott Long if ((id==0) || check_VDevice_valid(pArray)) 1691713e81bSScott Long return -1; 1701713e81bSScott Long 1711713e81bSScott Long if(!mIsArray(pArray)) return -1; 1721713e81bSScott Long 1731713e81bSScott Long if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying || 1741713e81bSScott Long pArray->u.array.rf_initializing) 1751713e81bSScott Long return -1; 1761713e81bSScott Long 1771713e81bSScott Long for(i=0; i<pArray->u.array.bArnMember; i++) { 1781713e81bSScott Long pa = pArray->u.array.pMember[i]; 1791713e81bSScott Long if (pa && mIsArray(pa)) { 1801713e81bSScott Long if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 1811713e81bSScott Long pa->u.array.rf_initializing) 1821713e81bSScott Long return -1; 1831713e81bSScott Long } 1841713e81bSScott Long } 1851713e81bSScott Long 1861713e81bSScott Long if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 1871713e81bSScott Long fDeleteArray(_VBUS_P pArray, del_block0); 1881713e81bSScott Long return 0; 1891713e81bSScott Long 1901713e81bSScott Long } 1911713e81bSScott Long 1921713e81bSScott Long /* just to prevent driver from sending more commands */ 1931713e81bSScott Long static void HPTLIBAPI nothing(_VBUS_ARG void *notused){} 1941713e81bSScott Long 195d2bd3ab9SScott Long intrmask_t 196d2bd3ab9SScott Long lock_driver_idle(IAL_ADAPTER_T *pAdapter) 1971713e81bSScott Long { 1981713e81bSScott Long intrmask_t oldspl; 1991713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 2001713e81bSScott Long oldspl = lock_driver(); 2011713e81bSScott Long while (pAdapter->outstandingCommands) { 2021713e81bSScott Long KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); 2031713e81bSScott Long if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 2041713e81bSScott Long unlock_driver(oldspl); 205d2bd3ab9SScott Long /*Schedule out*/ 206d2bd3ab9SScott Long #if (__FreeBSD_version < 500000) 207d2bd3ab9SScott Long YIELD_THREAD; 208d2bd3ab9SScott Long #else 209d2bd3ab9SScott Long tsleep(lock_driver_idle, PPAUSE, "switch", 1); 210d2bd3ab9SScott Long #endif 2111713e81bSScott Long oldspl = lock_driver(); 2121713e81bSScott Long } 2131713e81bSScott Long CheckIdleCall(_VBUS_P0); 2141713e81bSScott Long return oldspl; 2151713e81bSScott Long } 2161713e81bSScott Long 2171713e81bSScott Long int Kernel_DeviceIoControl(_VBUS_ARG 2181713e81bSScott Long DWORD dwIoControlCode, /* operation control code */ 2191713e81bSScott Long PVOID lpInBuffer, /* input data buffer */ 2201713e81bSScott Long DWORD nInBufferSize, /* size of input data buffer */ 2211713e81bSScott Long PVOID lpOutBuffer, /* output data buffer */ 2221713e81bSScott Long DWORD nOutBufferSize, /* size of output data buffer */ 2231713e81bSScott Long PDWORD lpBytesReturned /* byte count */ 2241713e81bSScott Long ) 2251713e81bSScott Long { 2261713e81bSScott Long IAL_ADAPTER_T *pAdapter; 2271713e81bSScott Long 2281713e81bSScott Long switch(dwIoControlCode) { 2291713e81bSScott Long case HPT_IOCTL_DELETE_ARRAY: 2301713e81bSScott Long { 2311713e81bSScott Long DEVICEID idArray; 2321713e81bSScott Long int iSuccess; 2331713e81bSScott Long int i; 2341713e81bSScott Long PVDevice pArray; 2351713e81bSScott Long PVBus _vbus_p; 2361713e81bSScott Long struct cam_periph *periph = NULL; 2371713e81bSScott Long 2381713e81bSScott Long if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; 2391713e81bSScott Long if (nOutBufferSize!=sizeof(int)) return -1; 2401713e81bSScott Long idArray = *(DEVICEID *)lpInBuffer; 2411713e81bSScott Long 2421713e81bSScott Long pArray = ID_TO_VDEV(idArray); 2431713e81bSScott Long 244d2bd3ab9SScott Long if((idArray == 0) || check_VDevice_valid(pArray)) 2451713e81bSScott Long return -1; 2461713e81bSScott Long 2471713e81bSScott Long if(!mIsArray(pArray)) 2481713e81bSScott Long return -1; 2491713e81bSScott Long 2501713e81bSScott Long _vbus_p=pArray->pVBus; 2511713e81bSScott Long pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 2521713e81bSScott Long 2531713e81bSScott Long for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { 2541713e81bSScott Long if(pArray == _vbus_p->pVDevice[i]) 2551713e81bSScott Long { 2561713e81bSScott Long periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 257d2bd3ab9SScott Long if (periph != NULL && periph->refcount >= 1) 2581713e81bSScott Long { 2591713e81bSScott Long hpt_printk(("Can not delete a mounted device.\n")); 2601713e81bSScott Long return -1; 2611713e81bSScott Long } 2621713e81bSScott Long } 2631713e81bSScott Long /* the Mounted Disk isn't delete */ 2641713e81bSScott Long } 2651713e81bSScott Long 2661713e81bSScott Long iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); 2671713e81bSScott Long 2681713e81bSScott Long *(int*)lpOutBuffer = iSuccess; 2691713e81bSScott Long 2701713e81bSScott Long if(iSuccess != 0) 2711713e81bSScott Long return -1; 2721713e81bSScott Long break; 2731713e81bSScott Long } 2741713e81bSScott Long 2751713e81bSScott Long case HPT_IOCTL_GET_EVENT: 2761713e81bSScott Long { 2771713e81bSScott Long PHPT_EVENT pInfo; 2781713e81bSScott Long 2791713e81bSScott Long if (nInBufferSize!=0) return -1; 2801713e81bSScott Long if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; 2811713e81bSScott Long 2821713e81bSScott Long pInfo = (PHPT_EVENT)lpOutBuffer; 2831713e81bSScott Long 2841713e81bSScott Long if (hpt_get_event(pInfo)!=0) 2851713e81bSScott Long return -1; 2861713e81bSScott Long } 2871713e81bSScott Long break; 2881713e81bSScott Long 2891713e81bSScott Long case HPT_IOCTL_SET_ARRAY_STATE: 2901713e81bSScott Long { 2911713e81bSScott Long DEVICEID idArray; 2921713e81bSScott Long DWORD state; 2931713e81bSScott Long 2941713e81bSScott Long if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; 2951713e81bSScott Long if (nOutBufferSize!=0) return -1; 2961713e81bSScott Long 2971713e81bSScott Long idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; 2981713e81bSScott Long state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; 2991713e81bSScott Long 3001713e81bSScott Long if(hpt_set_array_state(idArray, state)!=0) 3011713e81bSScott Long return -1; 3021713e81bSScott Long } 3031713e81bSScott Long break; 3041713e81bSScott Long 3051713e81bSScott Long case HPT_IOCTL_RESCAN_DEVICES: 3061713e81bSScott Long { 3071713e81bSScott Long if (nInBufferSize!=0) return -1; 3081713e81bSScott Long if (nOutBufferSize!=0) return -1; 3091713e81bSScott Long 3101713e81bSScott Long #ifndef FOR_DEMO 3111713e81bSScott Long /* stop buzzer if user perform rescan */ 3121713e81bSScott Long for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 3131713e81bSScott Long if (pAdapter->beeping) { 3141713e81bSScott Long pAdapter->beeping = 0; 3151713e81bSScott Long BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 3161713e81bSScott Long } 3171713e81bSScott Long } 3181713e81bSScott Long #endif 3191713e81bSScott Long } 3201713e81bSScott Long break; 3211713e81bSScott Long 3221713e81bSScott Long default: 3231713e81bSScott Long { 3241713e81bSScott Long PVDevice pVDev; 3251713e81bSScott Long #ifdef SUPPORT_ARRAY 3261713e81bSScott Long intrmask_t oldspl; 3271713e81bSScott Long #endif 3281713e81bSScott Long switch(dwIoControlCode) { 3291713e81bSScott Long /* read-only ioctl functions can be called directly. */ 3301713e81bSScott Long case HPT_IOCTL_GET_VERSION: 3311713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_IDS: 3321713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_COUNT: 3331713e81bSScott Long case HPT_IOCTL_GET_CONTROLLER_INFO: 3341713e81bSScott Long case HPT_IOCTL_GET_CHANNEL_INFO: 3351713e81bSScott Long case HPT_IOCTL_GET_LOGICAL_DEVICES: 3361713e81bSScott Long case HPT_IOCTL_GET_DEVICE_INFO: 3371713e81bSScott Long case HPT_IOCTL_GET_EVENT: 3381713e81bSScott Long case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 3391713e81bSScott Long if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 3401713e81bSScott Long lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; 3411713e81bSScott Long break; 3421713e81bSScott Long 3431713e81bSScott Long default: 3441713e81bSScott Long /* 3451713e81bSScott Long * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 3461713e81bSScott Long * wrong for second controller. 3471713e81bSScott Long */ 3481713e81bSScott Long switch(dwIoControlCode) { 3491713e81bSScott Long case HPT_IOCTL_CREATE_ARRAY: 3501713e81bSScott Long pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; 3511713e81bSScott Long case HPT_IOCTL_SET_ARRAY_INFO: 3521713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; 3531713e81bSScott Long case HPT_IOCTL_SET_DEVICE_INFO: 3541713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; 3551713e81bSScott Long case HPT_IOCTL_SET_BOOT_MARK: 3561713e81bSScott Long case HPT_IOCTL_ADD_SPARE_DISK: 3571713e81bSScott Long case HPT_IOCTL_REMOVE_SPARE_DISK: 3581713e81bSScott Long pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; 3591713e81bSScott Long case HPT_IOCTL_ADD_DISK_TO_ARRAY: 3601713e81bSScott Long pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; 3611713e81bSScott Long default: 3621713e81bSScott Long pVDev = 0; 3631713e81bSScott Long } 3641713e81bSScott Long 3651713e81bSScott Long if (pVDev && !check_VDevice_valid(pVDev)){ 3661713e81bSScott Long _vbus_p = pVDev->pVBus; 3671713e81bSScott Long 3681713e81bSScott Long pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 3691713e81bSScott Long /* 3701713e81bSScott Long * create_array, and other functions can't be executed while channel is 3711713e81bSScott Long * perform I/O commands. Wait until driver is idle. 3721713e81bSScott Long */ 3731713e81bSScott Long oldspl = lock_driver_idle(pAdapter); 3741713e81bSScott Long if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 3751713e81bSScott Long lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { 3761713e81bSScott Long unlock_driver(oldspl); 3771713e81bSScott Long return -1; 3781713e81bSScott Long } 3791713e81bSScott Long unlock_driver(oldspl); 3801713e81bSScott Long } 3811713e81bSScott Long else 3821713e81bSScott Long return -1; 3831713e81bSScott Long break; 3841713e81bSScott Long } 3851713e81bSScott Long 3861713e81bSScott Long #ifdef SUPPORT_ARRAY 3871713e81bSScott Long switch(dwIoControlCode) 3881713e81bSScott Long { 3891713e81bSScott Long case HPT_IOCTL_CREATE_ARRAY: 3901713e81bSScott Long { 3911713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 3921713e81bSScott Long oldspl = lock_driver(); 3931713e81bSScott Long if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) 3941713e81bSScott Long { 3951713e81bSScott Long (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 3961713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 3971713e81bSScott Long } 3981713e81bSScott Long else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) 3991713e81bSScott Long { 4001713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 4011713e81bSScott Long } 4021713e81bSScott Long else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) 4031713e81bSScott Long { 4041713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 4051713e81bSScott Long } 4061713e81bSScott Long unlock_driver(oldspl); 4071713e81bSScott Long break; 4081713e81bSScott Long } 4091713e81bSScott Long 4101713e81bSScott Long case HPT_IOCTL_ADD_DISK_TO_ARRAY: 4111713e81bSScott Long { 4121713e81bSScott Long PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); 4131713e81bSScott Long pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; 414d2bd3ab9SScott Long if(pArray->u.array.rf_rebuilding == 0) 4151713e81bSScott Long { 4161713e81bSScott Long DWORD timeout = 0; 4171713e81bSScott Long oldspl = lock_driver(); 4181713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0; 4191713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 4201713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 4211713e81bSScott Long unlock_driver(oldspl); 4221713e81bSScott Long while (!pArray->u.array.rf_rebuilding) 4231713e81bSScott Long { 4241713e81bSScott Long tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1); 4251713e81bSScott Long if ( timeout >= hz*3) 4261713e81bSScott Long break; 4271713e81bSScott Long timeout ++; 4281713e81bSScott Long } 4291713e81bSScott Long } 4301713e81bSScott Long break; 4311713e81bSScott Long } 4321713e81bSScott Long } 4331713e81bSScott Long #endif 4341713e81bSScott Long return 0; 4351713e81bSScott Long } 4361713e81bSScott Long } 4371713e81bSScott Long 4381713e81bSScott Long if (lpBytesReturned) 4391713e81bSScott Long *lpBytesReturned = nOutBufferSize; 4401713e81bSScott Long return 0; 4411713e81bSScott Long } 4421713e81bSScott Long 443d2bd3ab9SScott Long static int 444d2bd3ab9SScott Long hpt_get_event(PHPT_EVENT pEvent) 4451713e81bSScott Long { 4461713e81bSScott Long intrmask_t oldspl = lock_driver(); 4471713e81bSScott Long int ret = event_queue_remove(pEvent); 4481713e81bSScott Long unlock_driver(oldspl); 4491713e81bSScott Long return ret; 4501713e81bSScott Long } 4511713e81bSScott Long 452d2bd3ab9SScott Long static int 453d2bd3ab9SScott Long hpt_set_array_state(DEVICEID idArray, DWORD state) 4541713e81bSScott Long { 4551713e81bSScott Long IAL_ADAPTER_T *pAdapter; 4561713e81bSScott Long PVDevice pVDevice = ID_TO_VDEV(idArray); 4571713e81bSScott Long int i; 4581713e81bSScott Long DWORD timeout = 0; 4591713e81bSScott Long intrmask_t oldspl; 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 { 4721713e81bSScott Long if (pVDevice->u.array.rf_rebuilding || 4731713e81bSScott Long pVDevice->u.array.rf_verifying || 4741713e81bSScott Long pVDevice->u.array.rf_initializing) 4751713e81bSScott Long return -1; 4761713e81bSScott Long 4771713e81bSScott Long oldspl = lock_driver(); 4781713e81bSScott Long 4791713e81bSScott Long pVDevice->u.array.rf_auto_rebuild = 0; 4801713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 0; 4811713e81bSScott Long 4821713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 4831713e81bSScott Long (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 4841713e81bSScott Long 4851713e81bSScott Long unlock_driver(oldspl); 4861713e81bSScott Long 4871713e81bSScott Long while (!pVDevice->u.array.rf_rebuilding) 4881713e81bSScott Long { 4891713e81bSScott Long tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 4901713e81bSScott Long if ( timeout >= hz*20) 4911713e81bSScott Long break; 4921713e81bSScott Long timeout ++; 4931713e81bSScott Long } 4941713e81bSScott Long } 4951713e81bSScott Long 4961713e81bSScott Long break; 4971713e81bSScott Long 4981713e81bSScott Long case MIRROR_REBUILD_ABORT: 4991713e81bSScott Long { 5001713e81bSScott Long for(i = 0; i < pVDevice->u.array.bArnMember; i++) { 501d2bd3ab9SScott Long if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) 5021713e81bSScott Long hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); 5031713e81bSScott Long } 5041713e81bSScott Long 5051713e81bSScott Long if(pVDevice->u.array.rf_rebuilding != 1) 5061713e81bSScott Long return -1; 5071713e81bSScott Long 5081713e81bSScott Long oldspl = lock_driver(); 5091713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1; 5101713e81bSScott Long unlock_driver(oldspl); 5111713e81bSScott Long 5121713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild) 5131713e81bSScott Long { 5141713e81bSScott Long tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 5151713e81bSScott Long if ( timeout >= hz*20) 5161713e81bSScott Long break; 5171713e81bSScott Long timeout ++; 5181713e81bSScott Long } 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;*/ 5261713e81bSScott Long if (pVDevice->u.array.rf_rebuilding || 5271713e81bSScott Long pVDevice->u.array.rf_verifying || 5281713e81bSScott Long pVDevice->u.array.rf_initializing) 5291713e81bSScott Long return -1; 5301713e81bSScott Long 5311713e81bSScott Long oldspl = lock_driver(); 5321713e81bSScott Long pVDevice->u.array.RebuildSectors = 0; 5331713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 5341713e81bSScott Long unlock_driver(oldspl); 5351713e81bSScott Long 5361713e81bSScott Long while (!pVDevice->u.array.rf_verifying) 5371713e81bSScott Long { 5381713e81bSScott Long tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 5391713e81bSScott Long if ( timeout >= hz*20) 5401713e81bSScott Long break; 5411713e81bSScott Long timeout ++; 5421713e81bSScott Long } 5431713e81bSScott Long } 5441713e81bSScott Long break; 5451713e81bSScott Long 5461713e81bSScott Long case AS_VERIFY_ABORT: 5471713e81bSScott Long { 5481713e81bSScott Long if(pVDevice->u.array.rf_verifying != 1) 5491713e81bSScott Long return -1; 5501713e81bSScott Long 5511713e81bSScott Long oldspl = lock_driver(); 5521713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1; 5531713e81bSScott Long unlock_driver(oldspl); 5541713e81bSScott Long 5551713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild) 5561713e81bSScott Long { 5571713e81bSScott Long tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 5581713e81bSScott Long if ( timeout >= hz*80) 5591713e81bSScott Long break; 5601713e81bSScott Long timeout ++; 5611713e81bSScott Long } 5621713e81bSScott Long } 5631713e81bSScott Long break; 5641713e81bSScott Long 5651713e81bSScott Long case AS_INITIALIZE_START: 5661713e81bSScott Long { 5671713e81bSScott Long if (pVDevice->u.array.rf_rebuilding || 5681713e81bSScott Long pVDevice->u.array.rf_verifying || 5691713e81bSScott Long pVDevice->u.array.rf_initializing) 5701713e81bSScott Long return -1; 5711713e81bSScott Long 5721713e81bSScott Long oldspl = lock_driver(); 5731713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 5741713e81bSScott Long unlock_driver(oldspl); 5751713e81bSScott Long 5761713e81bSScott Long while (!pVDevice->u.array.rf_initializing) 5771713e81bSScott Long { 5781713e81bSScott Long tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 5791713e81bSScott Long if ( timeout >= hz*80) 5801713e81bSScott Long break; 5811713e81bSScott Long timeout ++; 5821713e81bSScott Long } 5831713e81bSScott Long } 5841713e81bSScott Long break; 5851713e81bSScott Long 5861713e81bSScott Long case AS_INITIALIZE_ABORT: 5871713e81bSScott Long { 5881713e81bSScott Long if(pVDevice->u.array.rf_initializing != 1) 5891713e81bSScott Long return -1; 5901713e81bSScott Long 5911713e81bSScott Long oldspl = lock_driver(); 5921713e81bSScott Long pVDevice->u.array.rf_abort_rebuild = 1; 5931713e81bSScott Long unlock_driver(oldspl); 5941713e81bSScott Long 5951713e81bSScott Long while (pVDevice->u.array.rf_abort_rebuild) 5961713e81bSScott Long { 5971713e81bSScott Long tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 5981713e81bSScott Long if ( timeout >= hz*80) 5991713e81bSScott Long break; 6001713e81bSScott Long timeout ++; 6011713e81bSScott Long } 6021713e81bSScott Long } 6031713e81bSScott Long break; 6041713e81bSScott Long 6051713e81bSScott Long default: 6061713e81bSScott Long return -1; 6071713e81bSScott Long } 6081713e81bSScott Long 6091713e81bSScott Long return 0; 6101713e81bSScott Long } 6111713e81bSScott Long 612d2bd3ab9SScott Long int HPTLIBAPI 613d2bd3ab9SScott Long R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) 6141713e81bSScott Long { 6151713e81bSScott Long ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); 6161713e81bSScott Long if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) 6171713e81bSScott Long bufferSize<<=1; 6181713e81bSScott Long if (logical) { 6191713e81bSScott Long pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; 6201713e81bSScott Long pSgTable->wSgSize = (USHORT)bufferSize; 6211713e81bSScott Long pSgTable->wSgFlag = SG_FLAG_EOT; 6221713e81bSScott Long } 6231713e81bSScott Long else { 6241713e81bSScott Long /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ 6251713e81bSScott Long ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; 6261713e81bSScott Long ULONG length; 6271713e81bSScott Long int idx = 0; 6281713e81bSScott Long 6291713e81bSScott Long v = pCmd->uCmd.R1Control.Buffer; 6301713e81bSScott Long dataPointer = (ADDRESS)fOsPhysicalAddress(v); 6311713e81bSScott Long 6321713e81bSScott Long if ((ULONG_PTR)dataPointer & 0x1) 6331713e81bSScott Long return FALSE; 6341713e81bSScott Long 6351713e81bSScott Long #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) 6361713e81bSScott Long #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) 6371713e81bSScott Long 6381713e81bSScott Long do { 6391713e81bSScott Long if (idx >= MAX_SG_DESCRIPTORS) return FALSE; 6401713e81bSScott Long 6411713e81bSScott Long pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); 6421713e81bSScott Long currvaddr = v; 6431713e81bSScott Long currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); 6441713e81bSScott Long 6451713e81bSScott Long 6461713e81bSScott Long do { 6471713e81bSScott Long nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); 6481713e81bSScott Long nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); 6491713e81bSScott Long 6501713e81bSScott Long if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; 6511713e81bSScott Long nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); 6521713e81bSScott Long 6531713e81bSScott Long if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { 6541713e81bSScott Long nextvaddr = nextpage; 6551713e81bSScott Long break; 6561713e81bSScott Long } 6571713e81bSScott Long 6581713e81bSScott Long currvaddr = nextvaddr; 6591713e81bSScott Long currphypage = nextphypage; 6601713e81bSScott Long }while (1); 6611713e81bSScott Long 6621713e81bSScott Long length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; 6631713e81bSScott Long v = nextvaddr; 6641713e81bSScott Long bufferSize -= length; 6651713e81bSScott Long 6661713e81bSScott Long pSgTable[idx].wSgSize = (USHORT)length; 6671713e81bSScott Long pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; 6681713e81bSScott Long idx++; 6691713e81bSScott Long 6701713e81bSScott Long }while (bufferSize); 6711713e81bSScott Long } 6721713e81bSScott Long return 1; 6731713e81bSScott Long } 6741713e81bSScott Long 6751713e81bSScott Long static int End_Job=0; 676d2bd3ab9SScott Long void HPTLIBAPI 677d2bd3ab9SScott Long thread_io_done(_VBUS_ARG PCommand pCmd) 6781713e81bSScott Long { 6791713e81bSScott Long End_Job = 1; 6801713e81bSScott Long wakeup((caddr_t)pCmd); 6811713e81bSScott Long } 6821713e81bSScott Long 683d2bd3ab9SScott Long void 684d2bd3ab9SScott Long hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) 6851713e81bSScott Long { 6861713e81bSScott Long DWORD timeout = 0; 6871713e81bSScott Long ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); 6881713e81bSScott Long PCommand pCmd; 6891713e81bSScott Long UINT result; 6901713e81bSScott Long int needsync=0, retry=0, needdelete=0; 6911713e81bSScott Long void *buffer = 0; 6921713e81bSScott Long intrmask_t oldspl; 6931713e81bSScott Long 6941713e81bSScott Long _VBUS_INST(&pAdapter->VBus) 6951713e81bSScott Long 6961713e81bSScott Long if (pArray->u.array.rf_broken==1 || 6971713e81bSScott Long pArray->u.array.RebuildSectors>=capacity) 6981713e81bSScott Long return; 6991713e81bSScott Long 7001713e81bSScott Long oldspl = lock_driver(); 7011713e81bSScott Long 7021713e81bSScott Long switch(flags) 7031713e81bSScott Long { 7041713e81bSScott Long case DUPLICATE: 7051713e81bSScott Long case REBUILD_PARITY: 7061713e81bSScott Long if(pArray->u.array.rf_rebuilding == 0) 7071713e81bSScott Long { 7081713e81bSScott Long pArray->u.array.rf_rebuilding = 1; 7091713e81bSScott Long hpt_printk(("Rebuilding started.\n")); 7101713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); 7111713e81bSScott Long } 7121713e81bSScott Long break; 7131713e81bSScott Long 7141713e81bSScott Long case INITIALIZE: 7151713e81bSScott Long if(pArray->u.array.rf_initializing == 0) 7161713e81bSScott Long { 7171713e81bSScott Long pArray->u.array.rf_initializing = 1; 7181713e81bSScott Long hpt_printk(("Initializing started.\n")); 7191713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); 7201713e81bSScott Long } 7211713e81bSScott Long break; 7221713e81bSScott Long 7231713e81bSScott Long case VERIFY: 7241713e81bSScott Long if(pArray->u.array.rf_verifying == 0) 7251713e81bSScott Long { 7261713e81bSScott Long pArray->u.array.rf_verifying = 1; 7271713e81bSScott Long hpt_printk(("Verifying started.\n")); 7281713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); 7291713e81bSScott Long } 7301713e81bSScott Long break; 7311713e81bSScott Long } 7321713e81bSScott Long 7331713e81bSScott Long retry_cmd: 7341713e81bSScott Long pCmd = AllocateCommand(_VBUS_P0); 7351713e81bSScott Long HPT_ASSERT(pCmd); 7361713e81bSScott Long pCmd->cf_control = 1; 7371713e81bSScott Long End_Job = 0; 7381713e81bSScott Long 7391713e81bSScott Long if (pArray->VDeviceType==VD_RAID_1) 7401713e81bSScott Long { 7411713e81bSScott Long #define MAX_REBUILD_SECTORS 0x40 7421713e81bSScott Long 7431713e81bSScott Long /* take care for discontinuous buffer in R1ControlSgl */ 744d2bd3ab9SScott Long unlock_driver(oldspl); 7451713e81bSScott Long buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); 746d2bd3ab9SScott Long oldspl = lock_driver(); 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) { 8011713e81bSScott Long unlock_driver(oldspl); 8021713e81bSScott Long while (!End_Job) { 8031713e81bSScott Long tsleep((caddr_t)pCmd, PPAUSE, "pause", hz); 8041713e81bSScott Long if (timeout++>60) break; 8051713e81bSScott Long } 8061713e81bSScott Long oldspl = lock_driver(); 8071713e81bSScott Long if (!End_Job) { 8081713e81bSScott Long hpt_printk(("timeout, reset\n")); 8091713e81bSScott Long fResetVBus(_VBUS_P0); 8101713e81bSScott Long } 8111713e81bSScott Long } 8121713e81bSScott Long 8131713e81bSScott Long result = pCmd->Result; 8141713e81bSScott Long FreeCommand(_VBUS_P pCmd); 815d2bd3ab9SScott Long unlock_driver(oldspl); 816d2bd3ab9SScott Long if (buffer) free(buffer, M_DEVBUF); 817d2bd3ab9SScott Long oldspl = lock_driver(); 8181713e81bSScott Long KdPrintI(("cmd finished %d", result)); 8191713e81bSScott Long 8201713e81bSScott Long switch(result) 8211713e81bSScott Long { 8221713e81bSScott Long case RETURN_SUCCESS: 8231713e81bSScott Long if (!pArray->u.array.rf_abort_rebuild) 8241713e81bSScott Long { 8251713e81bSScott Long if(pArray->u.array.RebuildSectors < capacity) 8261713e81bSScott Long { 8271713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); 8281713e81bSScott Long } 8291713e81bSScott Long else 8301713e81bSScott Long { 8311713e81bSScott Long switch (flags) 8321713e81bSScott Long { 8331713e81bSScott Long case DUPLICATE: 8341713e81bSScott Long case REBUILD_PARITY: 8351713e81bSScott Long needsync = 1; 8361713e81bSScott Long pArray->u.array.rf_rebuilding = 0; 8371713e81bSScott Long pArray->u.array.rf_need_rebuild = 0; 8381713e81bSScott Long pArray->u.array.CriticalMembers = 0; 8391713e81bSScott Long pArray->u.array.RebuildSectors = MAX_LBA_T; 8401713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0; 8411713e81bSScott Long hpt_printk(("Rebuilding finished.\n")); 8421713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); 8431713e81bSScott Long break; 8441713e81bSScott Long case INITIALIZE: 8451713e81bSScott Long needsync = 1; 8461713e81bSScott Long pArray->u.array.rf_initializing = 0; 8471713e81bSScott Long pArray->u.array.rf_need_rebuild = 0; 8481713e81bSScott Long pArray->u.array.RebuildSectors = MAX_LBA_T; 8491713e81bSScott Long hpt_printk(("Initializing finished.\n")); 8501713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); 8511713e81bSScott Long break; 8521713e81bSScott Long case VERIFY: 8531713e81bSScott Long pArray->u.array.rf_verifying = 0; 8541713e81bSScott Long hpt_printk(("Verifying finished.\n")); 8551713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); 8561713e81bSScott Long break; 8571713e81bSScott Long } 8581713e81bSScott Long } 8591713e81bSScott Long } 8601713e81bSScott Long else 8611713e81bSScott Long { 8621713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 8631713e81bSScott Long if (pArray->u.array.rf_rebuilding) 8641713e81bSScott Long { 8651713e81bSScott Long hpt_printk(("Abort rebuilding.\n")); 8661713e81bSScott Long pArray->u.array.rf_rebuilding = 0; 8671713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0; 8681713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); 8691713e81bSScott Long } 8701713e81bSScott Long else if (pArray->u.array.rf_verifying) 8711713e81bSScott Long { 8721713e81bSScott Long hpt_printk(("Abort verifying.\n")); 8731713e81bSScott Long pArray->u.array.rf_verifying = 0; 8741713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); 8751713e81bSScott Long } 8761713e81bSScott Long else if (pArray->u.array.rf_initializing) 8771713e81bSScott Long { 8781713e81bSScott Long hpt_printk(("Abort initializing.\n")); 8791713e81bSScott Long pArray->u.array.rf_initializing = 0; 8801713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); 8811713e81bSScott Long } 8821713e81bSScott Long needdelete=1; 8831713e81bSScott Long } 8841713e81bSScott Long break; 8851713e81bSScott Long 8861713e81bSScott Long case RETURN_DATA_ERROR: 8871713e81bSScott Long if (flags==VERIFY) 8881713e81bSScott Long { 8891713e81bSScott Long needsync = 1; 8901713e81bSScott Long pArray->u.array.rf_verifying = 0; 8911713e81bSScott Long pArray->u.array.rf_need_rebuild = 1; 8921713e81bSScott Long hpt_printk(("Verifying failed: found inconsistency\n")); 8931713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); 8941713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 8951713e81bSScott Long 8961713e81bSScott Long if (!pArray->vf_online || pArray->u.array.rf_broken) break; 8971713e81bSScott Long 8981713e81bSScott Long pArray->u.array.rf_auto_rebuild = 0; 8991713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 9001713e81bSScott Long hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 9011713e81bSScott Long (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); 9021713e81bSScott Long } 9031713e81bSScott Long break; 9041713e81bSScott Long 9051713e81bSScott Long default: 9061713e81bSScott Long hpt_printk(("command failed with error %d\n", result)); 9071713e81bSScott Long if (++retry<3) 9081713e81bSScott Long { 9091713e81bSScott Long hpt_printk(("retry (%d)\n", retry)); 9101713e81bSScott Long goto retry_cmd; 9111713e81bSScott Long } 9121713e81bSScott Long fail: 9131713e81bSScott Long pArray->u.array.rf_abort_rebuild = 0; 9141713e81bSScott Long switch (flags) 9151713e81bSScott Long { 9161713e81bSScott Long case DUPLICATE: 9171713e81bSScott Long case REBUILD_PARITY: 9181713e81bSScott Long needsync = 1; 9191713e81bSScott Long pArray->u.array.rf_rebuilding = 0; 9201713e81bSScott Long pArray->u.array.rf_duplicate_and_create = 0; 9211713e81bSScott Long hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); 9221713e81bSScott Long ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); 9231713e81bSScott Long break; 9241713e81bSScott Long 9251713e81bSScott Long case INITIALIZE: 9261713e81bSScott Long needsync = 1; 9271713e81bSScott Long pArray->u.array.rf_initializing = 0; 9281713e81bSScott Long hpt_printk(("Initializing failed.\n")); 9291713e81bSScott Long ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); 9301713e81bSScott Long break; 9311713e81bSScott Long 9321713e81bSScott Long case VERIFY: 9331713e81bSScott Long needsync = 1; 9341713e81bSScott Long pArray->u.array.rf_verifying = 0; 9351713e81bSScott Long hpt_printk(("Verifying failed.\n")); 9361713e81bSScott Long ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 9371713e81bSScott Long break; 9381713e81bSScott Long } 9391713e81bSScott Long needdelete=1; 9401713e81bSScott Long } 9411713e81bSScott Long 9421713e81bSScott Long while (pAdapter->outstandingCommands) 9431713e81bSScott Long { 9441713e81bSScott Long KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); 9451713e81bSScott Long /* put this to have driver stop processing system commands quickly */ 9461713e81bSScott Long if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 9471713e81bSScott Long unlock_driver(oldspl); 948d2bd3ab9SScott Long /*Schedule out*/ 949d2bd3ab9SScott Long #if (__FreeBSD_version < 500000) 950d2bd3ab9SScott Long YIELD_THREAD; 951d2bd3ab9SScott Long #else 952d2bd3ab9SScott Long tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1); 953d2bd3ab9SScott Long #endif 9541713e81bSScott Long oldspl = lock_driver(); 9551713e81bSScott Long } 9561713e81bSScott Long 9571713e81bSScott Long if (needsync) SyncArrayInfo(pArray); 9581713e81bSScott Long if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) 9591713e81bSScott Long fDeleteArray(_VBUS_P pArray, TRUE); 9601713e81bSScott Long 9611713e81bSScott Long Check_Idle_Call(pAdapter); 9621713e81bSScott Long unlock_driver(oldspl); 9631713e81bSScott Long } 964