135878b55SSascha Wildner /* 235878b55SSascha Wildner * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 335878b55SSascha Wildner * All rights reserved. 435878b55SSascha Wildner * 535878b55SSascha Wildner * Redistribution and use in source and binary forms, with or without 635878b55SSascha Wildner * modification, are permitted provided that the following conditions 735878b55SSascha Wildner * are met: 835878b55SSascha Wildner * 1. Redistributions of source code must retain the above copyright 935878b55SSascha Wildner * notice, this list of conditions and the following disclaimer. 1035878b55SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 1135878b55SSascha Wildner * notice, this list of conditions and the following disclaimer in the 1235878b55SSascha Wildner * documentation and/or other materials provided with the distribution. 1335878b55SSascha Wildner * 1435878b55SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1535878b55SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1635878b55SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1735878b55SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1835878b55SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1935878b55SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2035878b55SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2135878b55SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2235878b55SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2335878b55SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2435878b55SSascha Wildner * SUCH DAMAGE. 2535878b55SSascha Wildner * 2635878b55SSascha Wildner * $FreeBSD: src/sys/dev/hptmv/ioctl.c,v 1.9 2009/04/07 16:38:25 delphij Exp $ 2735878b55SSascha Wildner */ 2835878b55SSascha Wildner /* 2935878b55SSascha Wildner * ioctl.c ioctl interface implementation 3035878b55SSascha Wildner */ 3135878b55SSascha Wildner #include <sys/param.h> 3235878b55SSascha Wildner #include <sys/systm.h> 3335878b55SSascha Wildner #include <sys/kernel.h> 3435878b55SSascha Wildner #include <sys/malloc.h> 3535878b55SSascha Wildner 3635878b55SSascha Wildner #ifndef __KERNEL__ 3735878b55SSascha Wildner #define __KERNEL__ 3835878b55SSascha Wildner #endif 3935878b55SSascha Wildner 4035878b55SSascha Wildner #include <dev/raid/hptmv/global.h> 4135878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h> 4235878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h> 4335878b55SSascha Wildner #include <dev/raid/hptmv/access601.h> 4435878b55SSascha Wildner 4535878b55SSascha Wildner #pragma pack(1) 4635878b55SSascha Wildner 4735878b55SSascha Wildner typedef struct _HPT_REBUILD_PARAM 4835878b55SSascha Wildner { 4935878b55SSascha Wildner DEVICEID idMirror; 5035878b55SSascha Wildner DWORD Lba; 5135878b55SSascha Wildner UCHAR nSector; 5235878b55SSascha Wildner } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM; 5335878b55SSascha Wildner 5435878b55SSascha Wildner #pragma pack() 5535878b55SSascha Wildner 5635878b55SSascha Wildner #define MAX_EVENTS 10 5735878b55SSascha Wildner static HPT_EVENT hpt_event_queue[MAX_EVENTS]; 5835878b55SSascha Wildner static int event_queue_head=0, event_queue_tail=0; 5935878b55SSascha Wildner 6035878b55SSascha Wildner static int hpt_get_event(PHPT_EVENT pEvent); 6135878b55SSascha Wildner static int hpt_set_array_state(DEVICEID idArray, DWORD state); 62*c898d682SSascha Wildner static void lock_driver_idle(IAL_ADAPTER_T *pAdapter); 6335878b55SSascha Wildner static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); 6435878b55SSascha Wildner static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, 6535878b55SSascha Wildner FPSCAT_GATH pSgTable, int logical); 6635878b55SSascha Wildner 6735878b55SSascha Wildner static void 6835878b55SSascha Wildner get_disk_location(PDevice pDev, int *controller, int *channel) 6935878b55SSascha Wildner { 7035878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 7135878b55SSascha Wildner int i, j; 7235878b55SSascha Wildner 7335878b55SSascha Wildner *controller = *channel = 0; 7435878b55SSascha Wildner 7535878b55SSascha Wildner for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) { 7635878b55SSascha Wildner for (j=0; j<MV_SATA_CHANNELS_NUM; j++) { 7735878b55SSascha Wildner if (pDev == &pAdapTemp->VDevices[j].u.disk) { 7835878b55SSascha Wildner *controller = i; 7935878b55SSascha Wildner *channel = j; 8035878b55SSascha Wildner return; 8135878b55SSascha Wildner } 8235878b55SSascha Wildner } 8335878b55SSascha Wildner } 8435878b55SSascha Wildner } 8535878b55SSascha Wildner 8635878b55SSascha Wildner static int 8735878b55SSascha Wildner event_queue_add(PHPT_EVENT pEvent) 8835878b55SSascha Wildner { 8935878b55SSascha Wildner int p; 9035878b55SSascha Wildner p = (event_queue_tail + 1) % MAX_EVENTS; 9135878b55SSascha Wildner if (p==event_queue_head) 9235878b55SSascha Wildner { 9335878b55SSascha Wildner return -1; 9435878b55SSascha Wildner } 9535878b55SSascha Wildner hpt_event_queue[event_queue_tail] = *pEvent; 9635878b55SSascha Wildner event_queue_tail = p; 9735878b55SSascha Wildner return 0; 9835878b55SSascha Wildner } 9935878b55SSascha Wildner 10035878b55SSascha Wildner static int 10135878b55SSascha Wildner event_queue_remove(PHPT_EVENT pEvent) 10235878b55SSascha Wildner { 10335878b55SSascha Wildner if (event_queue_head != event_queue_tail) 10435878b55SSascha Wildner { 10535878b55SSascha Wildner *pEvent = hpt_event_queue[event_queue_head]; 10635878b55SSascha Wildner event_queue_head++; 10735878b55SSascha Wildner event_queue_head %= MAX_EVENTS; 10835878b55SSascha Wildner return 0; 10935878b55SSascha Wildner } 11035878b55SSascha Wildner return -1; 11135878b55SSascha Wildner } 11235878b55SSascha Wildner 11335878b55SSascha Wildner void HPTLIBAPI 11435878b55SSascha Wildner ioctl_ReportEvent(UCHAR event, PVOID param) 11535878b55SSascha Wildner { 11635878b55SSascha Wildner HPT_EVENT e; 11735878b55SSascha Wildner ZeroMemory(&e, sizeof(e)); 11835878b55SSascha Wildner e.EventType = event; 11935878b55SSascha Wildner switch(event) 12035878b55SSascha Wildner { 12135878b55SSascha Wildner case ET_INITIALIZE_ABORTED: 12235878b55SSascha Wildner case ET_INITIALIZE_FAILED: 12335878b55SSascha Wildner memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME); 12435878b55SSascha Wildner case ET_INITIALIZE_STARTED: 12535878b55SSascha Wildner case ET_INITIALIZE_FINISHED: 12635878b55SSascha Wildner 12735878b55SSascha Wildner case ET_REBUILD_STARTED: 12835878b55SSascha Wildner case ET_REBUILD_ABORTED: 12935878b55SSascha Wildner case ET_REBUILD_FAILED: 13035878b55SSascha Wildner case ET_REBUILD_FINISHED: 13135878b55SSascha Wildner 13235878b55SSascha Wildner case ET_VERIFY_STARTED: 13335878b55SSascha Wildner case ET_VERIFY_ABORTED: 13435878b55SSascha Wildner case ET_VERIFY_FAILED: 13535878b55SSascha Wildner case ET_VERIFY_FINISHED: 13635878b55SSascha Wildner case ET_VERIFY_DATA_ERROR: 13735878b55SSascha Wildner 13835878b55SSascha Wildner case ET_SPARE_TOOK_OVER: 13935878b55SSascha Wildner case ET_DEVICE_REMOVED: 14035878b55SSascha Wildner case ET_DEVICE_PLUGGED: 14135878b55SSascha Wildner case ET_DEVICE_ERROR: 14235878b55SSascha Wildner e.DeviceID = VDEV_TO_ID((PVDevice)param); 14335878b55SSascha Wildner break; 14435878b55SSascha Wildner 14535878b55SSascha Wildner default: 14635878b55SSascha Wildner break; 14735878b55SSascha Wildner } 14835878b55SSascha Wildner event_queue_add(&e); 14935878b55SSascha Wildner if (event==ET_DEVICE_REMOVED) { 15035878b55SSascha Wildner int controller, channel; 15135878b55SSascha Wildner get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel); 15235878b55SSascha Wildner hpt_printk(("Device removed: controller %d channel %d\n", controller, channel)); 15335878b55SSascha Wildner } 15435878b55SSascha Wildner } 15535878b55SSascha Wildner 15635878b55SSascha Wildner static int 15735878b55SSascha Wildner hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) 15835878b55SSascha Wildner { 15935878b55SSascha Wildner PVDevice pArray = ID_TO_VDEV(id); 16035878b55SSascha Wildner BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; 16135878b55SSascha Wildner int i; 16235878b55SSascha Wildner PVDevice pa; 16335878b55SSascha Wildner 16435878b55SSascha Wildner if ((id==0) || check_VDevice_valid(pArray)) 16535878b55SSascha Wildner return -1; 16635878b55SSascha Wildner 16735878b55SSascha Wildner if(!mIsArray(pArray)) return -1; 16835878b55SSascha Wildner 16935878b55SSascha Wildner if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying || 17035878b55SSascha Wildner pArray->u.array.rf_initializing) 17135878b55SSascha Wildner return -1; 17235878b55SSascha Wildner 17335878b55SSascha Wildner for(i=0; i<pArray->u.array.bArnMember; i++) { 17435878b55SSascha Wildner pa = pArray->u.array.pMember[i]; 17535878b55SSascha Wildner if (pa && mIsArray(pa)) { 17635878b55SSascha Wildner if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 17735878b55SSascha Wildner pa->u.array.rf_initializing) 17835878b55SSascha Wildner return -1; 17935878b55SSascha Wildner } 18035878b55SSascha Wildner } 18135878b55SSascha Wildner 18235878b55SSascha Wildner if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 18335878b55SSascha Wildner fDeleteArray(_VBUS_P pArray, del_block0); 18435878b55SSascha Wildner return 0; 18535878b55SSascha Wildner 18635878b55SSascha Wildner } 18735878b55SSascha Wildner 18835878b55SSascha Wildner /* just to prevent driver from sending more commands */ 18935878b55SSascha Wildner static void HPTLIBAPI nothing(_VBUS_ARG void *notused){} 19035878b55SSascha Wildner 191*c898d682SSascha Wildner void 19235878b55SSascha Wildner lock_driver_idle(IAL_ADAPTER_T *pAdapter) 19335878b55SSascha Wildner { 19435878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 195*c898d682SSascha Wildner lock_driver(); 19635878b55SSascha Wildner while (pAdapter->outstandingCommands) { 19735878b55SSascha Wildner KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); 19835878b55SSascha Wildner if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 199*c898d682SSascha Wildner unlock_driver(); 20035878b55SSascha Wildner /*Schedule out*/ 20135878b55SSascha Wildner tsleep(lock_driver_idle, 0, "switch", 1); 202*c898d682SSascha Wildner lock_driver(); 20335878b55SSascha Wildner } 20435878b55SSascha Wildner CheckIdleCall(_VBUS_P0); 20535878b55SSascha Wildner } 20635878b55SSascha Wildner 20735878b55SSascha Wildner int Kernel_DeviceIoControl(_VBUS_ARG 20835878b55SSascha Wildner DWORD dwIoControlCode, /* operation control code */ 20935878b55SSascha Wildner PVOID lpInBuffer, /* input data buffer */ 21035878b55SSascha Wildner DWORD nInBufferSize, /* size of input data buffer */ 21135878b55SSascha Wildner PVOID lpOutBuffer, /* output data buffer */ 21235878b55SSascha Wildner DWORD nOutBufferSize, /* size of output data buffer */ 21335878b55SSascha Wildner PDWORD lpBytesReturned /* byte count */ 21435878b55SSascha Wildner ) 21535878b55SSascha Wildner { 21635878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 21735878b55SSascha Wildner 21835878b55SSascha Wildner switch(dwIoControlCode) { 21935878b55SSascha Wildner case HPT_IOCTL_DELETE_ARRAY: 22035878b55SSascha Wildner { 22135878b55SSascha Wildner DEVICEID idArray; 22235878b55SSascha Wildner int iSuccess; 22335878b55SSascha Wildner int i; 22435878b55SSascha Wildner PVDevice pArray; 22535878b55SSascha Wildner PVBus _vbus_p; 22635878b55SSascha Wildner struct cam_periph *periph = NULL; 22735878b55SSascha Wildner 22835878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; 22935878b55SSascha Wildner if (nOutBufferSize!=sizeof(int)) return -1; 23035878b55SSascha Wildner idArray = *(DEVICEID *)lpInBuffer; 23135878b55SSascha Wildner 23235878b55SSascha Wildner pArray = ID_TO_VDEV(idArray); 23335878b55SSascha Wildner 23435878b55SSascha Wildner if((idArray == 0) || check_VDevice_valid(pArray)) 23535878b55SSascha Wildner return -1; 23635878b55SSascha Wildner 23735878b55SSascha Wildner if(!mIsArray(pArray)) 23835878b55SSascha Wildner return -1; 23935878b55SSascha Wildner 24035878b55SSascha Wildner _vbus_p=pArray->pVBus; 24135878b55SSascha Wildner pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 24235878b55SSascha Wildner 24335878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { 24435878b55SSascha Wildner if(pArray == _vbus_p->pVDevice[i]) 24535878b55SSascha Wildner { 24635878b55SSascha Wildner periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 24735878b55SSascha Wildner if (periph != NULL && periph->refcount >= 1) 24835878b55SSascha Wildner { 24935878b55SSascha Wildner hpt_printk(("Can not delete a mounted device.\n")); 25035878b55SSascha Wildner return -1; 25135878b55SSascha Wildner } 25235878b55SSascha Wildner } 25335878b55SSascha Wildner /* the Mounted Disk isn't delete */ 25435878b55SSascha Wildner } 25535878b55SSascha Wildner 25635878b55SSascha Wildner iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); 25735878b55SSascha Wildner 25835878b55SSascha Wildner *(int*)lpOutBuffer = iSuccess; 25935878b55SSascha Wildner 26035878b55SSascha Wildner if(iSuccess != 0) 26135878b55SSascha Wildner return -1; 26235878b55SSascha Wildner break; 26335878b55SSascha Wildner } 26435878b55SSascha Wildner 26535878b55SSascha Wildner case HPT_IOCTL_GET_EVENT: 26635878b55SSascha Wildner { 26735878b55SSascha Wildner PHPT_EVENT pInfo; 26835878b55SSascha Wildner 26935878b55SSascha Wildner if (nInBufferSize!=0) return -1; 27035878b55SSascha Wildner if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; 27135878b55SSascha Wildner 27235878b55SSascha Wildner pInfo = (PHPT_EVENT)lpOutBuffer; 27335878b55SSascha Wildner 27435878b55SSascha Wildner if (hpt_get_event(pInfo)!=0) 27535878b55SSascha Wildner return -1; 27635878b55SSascha Wildner } 27735878b55SSascha Wildner break; 27835878b55SSascha Wildner 27935878b55SSascha Wildner case HPT_IOCTL_SET_ARRAY_STATE: 28035878b55SSascha Wildner { 28135878b55SSascha Wildner DEVICEID idArray; 28235878b55SSascha Wildner DWORD state; 28335878b55SSascha Wildner 28435878b55SSascha Wildner if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; 28535878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 28635878b55SSascha Wildner 28735878b55SSascha Wildner idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; 28835878b55SSascha Wildner state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; 28935878b55SSascha Wildner 29035878b55SSascha Wildner if(hpt_set_array_state(idArray, state)!=0) 29135878b55SSascha Wildner return -1; 29235878b55SSascha Wildner } 29335878b55SSascha Wildner break; 29435878b55SSascha Wildner 29535878b55SSascha Wildner case HPT_IOCTL_RESCAN_DEVICES: 29635878b55SSascha Wildner { 29735878b55SSascha Wildner if (nInBufferSize!=0) return -1; 29835878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 29935878b55SSascha Wildner 30035878b55SSascha Wildner #ifndef FOR_DEMO 30135878b55SSascha Wildner /* stop buzzer if user perform rescan */ 30235878b55SSascha Wildner for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 30335878b55SSascha Wildner if (pAdapter->beeping) { 30435878b55SSascha Wildner pAdapter->beeping = 0; 30535878b55SSascha Wildner BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 30635878b55SSascha Wildner } 30735878b55SSascha Wildner } 30835878b55SSascha Wildner #endif 30935878b55SSascha Wildner } 31035878b55SSascha Wildner break; 31135878b55SSascha Wildner 31235878b55SSascha Wildner default: 31335878b55SSascha Wildner { 31435878b55SSascha Wildner PVDevice pVDev; 31535878b55SSascha Wildner switch(dwIoControlCode) { 31635878b55SSascha Wildner /* read-only ioctl functions can be called directly. */ 31735878b55SSascha Wildner case HPT_IOCTL_GET_VERSION: 31835878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_IDS: 31935878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_COUNT: 32035878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_INFO: 32135878b55SSascha Wildner case HPT_IOCTL_GET_CHANNEL_INFO: 32235878b55SSascha Wildner case HPT_IOCTL_GET_LOGICAL_DEVICES: 32335878b55SSascha Wildner case HPT_IOCTL_GET_DEVICE_INFO: 32435878b55SSascha Wildner case HPT_IOCTL_GET_DEVICE_INFO_V2: 32535878b55SSascha Wildner case HPT_IOCTL_GET_EVENT: 32635878b55SSascha Wildner case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 32735878b55SSascha Wildner if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 32835878b55SSascha Wildner lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; 32935878b55SSascha Wildner break; 33035878b55SSascha Wildner 33135878b55SSascha Wildner default: 33235878b55SSascha Wildner /* 33335878b55SSascha Wildner * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 33435878b55SSascha Wildner * wrong for second controller. 33535878b55SSascha Wildner */ 33635878b55SSascha Wildner switch(dwIoControlCode) { 33735878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY: 33835878b55SSascha Wildner pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; 33935878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY_V2: 34035878b55SSascha Wildner pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break; 34135878b55SSascha Wildner case HPT_IOCTL_SET_ARRAY_INFO: 34235878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; 34335878b55SSascha Wildner case HPT_IOCTL_SET_DEVICE_INFO: 34435878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; 34535878b55SSascha Wildner case HPT_IOCTL_SET_DEVICE_INFO_V2: 34635878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break; 34735878b55SSascha Wildner case HPT_IOCTL_SET_BOOT_MARK: 34835878b55SSascha Wildner case HPT_IOCTL_ADD_SPARE_DISK: 34935878b55SSascha Wildner case HPT_IOCTL_REMOVE_SPARE_DISK: 35035878b55SSascha Wildner pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; 35135878b55SSascha Wildner case HPT_IOCTL_ADD_DISK_TO_ARRAY: 35235878b55SSascha Wildner pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; 35335878b55SSascha Wildner default: 35435878b55SSascha Wildner pVDev = 0; 35535878b55SSascha Wildner } 35635878b55SSascha Wildner 35735878b55SSascha Wildner if (pVDev && !check_VDevice_valid(pVDev)){ 35835878b55SSascha Wildner _vbus_p = pVDev->pVBus; 35935878b55SSascha Wildner 36035878b55SSascha Wildner pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 36135878b55SSascha Wildner /* 36235878b55SSascha Wildner * create_array, and other functions can't be executed while channel is 36335878b55SSascha Wildner * perform I/O commands. Wait until driver is idle. 36435878b55SSascha Wildner */ 365*c898d682SSascha Wildner lock_driver_idle(pAdapter); 36635878b55SSascha Wildner if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 36735878b55SSascha Wildner lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { 368*c898d682SSascha Wildner unlock_driver(); 36935878b55SSascha Wildner return -1; 37035878b55SSascha Wildner } 371*c898d682SSascha Wildner unlock_driver(); 37235878b55SSascha Wildner } 37335878b55SSascha Wildner else 37435878b55SSascha Wildner return -1; 37535878b55SSascha Wildner break; 37635878b55SSascha Wildner } 37735878b55SSascha Wildner 37835878b55SSascha Wildner #ifdef SUPPORT_ARRAY 37935878b55SSascha Wildner switch(dwIoControlCode) 38035878b55SSascha Wildner { 38135878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY: 38235878b55SSascha Wildner { 38335878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 384*c898d682SSascha Wildner lock_driver(); 38535878b55SSascha Wildner if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) 38635878b55SSascha Wildner { 38735878b55SSascha Wildner (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 38835878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 38935878b55SSascha Wildner } 39035878b55SSascha Wildner else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) 39135878b55SSascha Wildner { 39235878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 39335878b55SSascha Wildner } 39435878b55SSascha Wildner else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) 39535878b55SSascha Wildner { 39635878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 39735878b55SSascha Wildner } 398*c898d682SSascha Wildner unlock_driver(); 39935878b55SSascha Wildner break; 40035878b55SSascha Wildner } 40135878b55SSascha Wildner 40235878b55SSascha Wildner 40335878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY_V2: 40435878b55SSascha Wildner { 40535878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 406*c898d682SSascha Wildner lock_driver(); 40735878b55SSascha Wildner if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) { 40835878b55SSascha Wildner (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 40935878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 41035878b55SSascha Wildner } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) { 41135878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 41235878b55SSascha Wildner } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) { 41335878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 41435878b55SSascha Wildner } 415*c898d682SSascha Wildner unlock_driver(); 41635878b55SSascha Wildner break; 41735878b55SSascha Wildner } 41835878b55SSascha Wildner case HPT_IOCTL_ADD_DISK_TO_ARRAY: 41935878b55SSascha Wildner { 42035878b55SSascha Wildner PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); 42135878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; 42235878b55SSascha Wildner if(pArray->u.array.rf_rebuilding == 0) 42335878b55SSascha Wildner { 42435878b55SSascha Wildner DWORD timeout = 0; 425*c898d682SSascha Wildner lock_driver(); 42635878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 0; 42735878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0; 42835878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 429*c898d682SSascha Wildner unlock_driver(); 43035878b55SSascha Wildner while (!pArray->u.array.rf_rebuilding) 43135878b55SSascha Wildner { 43235878b55SSascha Wildner tsleep((caddr_t)Kernel_DeviceIoControl, 0, "pause", 1); 43335878b55SSascha Wildner if ( timeout >= hz*3) 43435878b55SSascha Wildner break; 43535878b55SSascha Wildner timeout ++; 43635878b55SSascha Wildner } 43735878b55SSascha Wildner } 43835878b55SSascha Wildner break; 43935878b55SSascha Wildner } 44035878b55SSascha Wildner } 44135878b55SSascha Wildner #endif 44235878b55SSascha Wildner return 0; 44335878b55SSascha Wildner } 44435878b55SSascha Wildner } 44535878b55SSascha Wildner 44635878b55SSascha Wildner if (lpBytesReturned) 44735878b55SSascha Wildner *lpBytesReturned = nOutBufferSize; 44835878b55SSascha Wildner return 0; 44935878b55SSascha Wildner } 45035878b55SSascha Wildner 45135878b55SSascha Wildner static int 45235878b55SSascha Wildner hpt_get_event(PHPT_EVENT pEvent) 45335878b55SSascha Wildner { 454*c898d682SSascha Wildner lock_driver(); 45535878b55SSascha Wildner int ret = event_queue_remove(pEvent); 456*c898d682SSascha Wildner unlock_driver(); 45735878b55SSascha Wildner return ret; 45835878b55SSascha Wildner } 45935878b55SSascha Wildner 46035878b55SSascha Wildner static int 46135878b55SSascha Wildner hpt_set_array_state(DEVICEID idArray, DWORD state) 46235878b55SSascha Wildner { 46335878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 46435878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idArray); 46535878b55SSascha Wildner int i; 46635878b55SSascha Wildner DWORD timeout = 0; 46735878b55SSascha Wildner 46835878b55SSascha Wildner if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; 46935878b55SSascha Wildner if(!mIsArray(pVDevice)) 47035878b55SSascha Wildner return -1; 47135878b55SSascha Wildner if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; 47235878b55SSascha Wildner 47335878b55SSascha Wildner pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt; 47435878b55SSascha Wildner 47535878b55SSascha Wildner switch(state) 47635878b55SSascha Wildner { 47735878b55SSascha Wildner case MIRROR_REBUILD_START: 47835878b55SSascha Wildner { 47935878b55SSascha Wildner if (pVDevice->u.array.rf_rebuilding || 48035878b55SSascha Wildner pVDevice->u.array.rf_verifying || 48135878b55SSascha Wildner pVDevice->u.array.rf_initializing) 48235878b55SSascha Wildner return -1; 48335878b55SSascha Wildner 484*c898d682SSascha Wildner lock_driver(); 48535878b55SSascha Wildner 48635878b55SSascha Wildner pVDevice->u.array.rf_auto_rebuild = 0; 48735878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 0; 48835878b55SSascha Wildner 48935878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 49035878b55SSascha Wildner (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 49135878b55SSascha Wildner 492*c898d682SSascha Wildner unlock_driver(); 49335878b55SSascha Wildner 49435878b55SSascha Wildner while (!pVDevice->u.array.rf_rebuilding) 49535878b55SSascha Wildner { 49635878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1); 49735878b55SSascha Wildner if ( timeout >= hz*20) 49835878b55SSascha Wildner break; 49935878b55SSascha Wildner timeout ++; 50035878b55SSascha Wildner } 50135878b55SSascha Wildner } 50235878b55SSascha Wildner 50335878b55SSascha Wildner break; 50435878b55SSascha Wildner 50535878b55SSascha Wildner case MIRROR_REBUILD_ABORT: 50635878b55SSascha Wildner { 50735878b55SSascha Wildner for(i = 0; i < pVDevice->u.array.bArnMember; i++) { 50835878b55SSascha Wildner if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) 50935878b55SSascha Wildner hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); 51035878b55SSascha Wildner } 51135878b55SSascha Wildner 51235878b55SSascha Wildner if(pVDevice->u.array.rf_rebuilding != 1) 51335878b55SSascha Wildner return -1; 51435878b55SSascha Wildner 515*c898d682SSascha Wildner lock_driver(); 51635878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 1; 517*c898d682SSascha Wildner unlock_driver(); 51835878b55SSascha Wildner 51935878b55SSascha Wildner while (pVDevice->u.array.rf_abort_rebuild) 52035878b55SSascha Wildner { 52135878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1); 52235878b55SSascha Wildner if ( timeout >= hz*20) 52335878b55SSascha Wildner break; 52435878b55SSascha Wildner timeout ++; 52535878b55SSascha Wildner } 52635878b55SSascha Wildner } 52735878b55SSascha Wildner break; 52835878b55SSascha Wildner 52935878b55SSascha Wildner case AS_VERIFY_START: 53035878b55SSascha Wildner { 53135878b55SSascha Wildner /*if(pVDevice->u.array.rf_verifying) 53235878b55SSascha Wildner return -1;*/ 53335878b55SSascha Wildner if (pVDevice->u.array.rf_rebuilding || 53435878b55SSascha Wildner pVDevice->u.array.rf_verifying || 53535878b55SSascha Wildner pVDevice->u.array.rf_initializing) 53635878b55SSascha Wildner return -1; 53735878b55SSascha Wildner 538*c898d682SSascha Wildner lock_driver(); 53935878b55SSascha Wildner pVDevice->u.array.RebuildSectors = 0; 54035878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 541*c898d682SSascha Wildner unlock_driver(); 54235878b55SSascha Wildner 54335878b55SSascha Wildner while (!pVDevice->u.array.rf_verifying) 54435878b55SSascha Wildner { 54535878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1); 54635878b55SSascha Wildner if ( timeout >= hz*20) 54735878b55SSascha Wildner break; 54835878b55SSascha Wildner timeout ++; 54935878b55SSascha Wildner } 55035878b55SSascha Wildner } 55135878b55SSascha Wildner break; 55235878b55SSascha Wildner 55335878b55SSascha Wildner case AS_VERIFY_ABORT: 55435878b55SSascha Wildner { 55535878b55SSascha Wildner if(pVDevice->u.array.rf_verifying != 1) 55635878b55SSascha Wildner return -1; 55735878b55SSascha Wildner 558*c898d682SSascha Wildner lock_driver(); 55935878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 1; 560*c898d682SSascha Wildner unlock_driver(); 56135878b55SSascha Wildner 56235878b55SSascha Wildner while (pVDevice->u.array.rf_abort_rebuild) 56335878b55SSascha Wildner { 56435878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1); 56535878b55SSascha Wildner if ( timeout >= hz*80) 56635878b55SSascha Wildner break; 56735878b55SSascha Wildner timeout ++; 56835878b55SSascha Wildner } 56935878b55SSascha Wildner } 57035878b55SSascha Wildner break; 57135878b55SSascha Wildner 57235878b55SSascha Wildner case AS_INITIALIZE_START: 57335878b55SSascha Wildner { 57435878b55SSascha Wildner if (pVDevice->u.array.rf_rebuilding || 57535878b55SSascha Wildner pVDevice->u.array.rf_verifying || 57635878b55SSascha Wildner pVDevice->u.array.rf_initializing) 57735878b55SSascha Wildner return -1; 57835878b55SSascha Wildner 579*c898d682SSascha Wildner lock_driver(); 58035878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 581*c898d682SSascha Wildner unlock_driver(); 58235878b55SSascha Wildner 58335878b55SSascha Wildner while (!pVDevice->u.array.rf_initializing) 58435878b55SSascha Wildner { 58535878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1); 58635878b55SSascha Wildner if ( timeout >= hz*80) 58735878b55SSascha Wildner break; 58835878b55SSascha Wildner timeout ++; 58935878b55SSascha Wildner } 59035878b55SSascha Wildner } 59135878b55SSascha Wildner break; 59235878b55SSascha Wildner 59335878b55SSascha Wildner case AS_INITIALIZE_ABORT: 59435878b55SSascha Wildner { 59535878b55SSascha Wildner if(pVDevice->u.array.rf_initializing != 1) 59635878b55SSascha Wildner return -1; 59735878b55SSascha Wildner 598*c898d682SSascha Wildner lock_driver(); 59935878b55SSascha Wildner pVDevice->u.array.rf_abort_rebuild = 1; 600*c898d682SSascha Wildner unlock_driver(); 60135878b55SSascha Wildner 60235878b55SSascha Wildner while (pVDevice->u.array.rf_abort_rebuild) 60335878b55SSascha Wildner { 60435878b55SSascha Wildner tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1); 60535878b55SSascha Wildner if ( timeout >= hz*80) 60635878b55SSascha Wildner break; 60735878b55SSascha Wildner timeout ++; 60835878b55SSascha Wildner } 60935878b55SSascha Wildner } 61035878b55SSascha Wildner break; 61135878b55SSascha Wildner 61235878b55SSascha Wildner default: 61335878b55SSascha Wildner return -1; 61435878b55SSascha Wildner } 61535878b55SSascha Wildner 61635878b55SSascha Wildner return 0; 61735878b55SSascha Wildner } 61835878b55SSascha Wildner 61935878b55SSascha Wildner int HPTLIBAPI 62035878b55SSascha Wildner R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) 62135878b55SSascha Wildner { 62235878b55SSascha Wildner ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); 62335878b55SSascha Wildner if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) 62435878b55SSascha Wildner bufferSize<<=1; 62535878b55SSascha Wildner if (logical) { 62635878b55SSascha Wildner pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; 62735878b55SSascha Wildner pSgTable->wSgSize = (USHORT)bufferSize; 62835878b55SSascha Wildner pSgTable->wSgFlag = SG_FLAG_EOT; 62935878b55SSascha Wildner } 63035878b55SSascha Wildner else { 63135878b55SSascha Wildner /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ 63235878b55SSascha Wildner ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; 63335878b55SSascha Wildner ULONG length; 63435878b55SSascha Wildner int idx = 0; 63535878b55SSascha Wildner 63635878b55SSascha Wildner v = pCmd->uCmd.R1Control.Buffer; 63735878b55SSascha Wildner dataPointer = (ADDRESS)fOsPhysicalAddress(v); 63835878b55SSascha Wildner 63935878b55SSascha Wildner if ((ULONG_PTR)dataPointer & 0x1) 64035878b55SSascha Wildner return FALSE; 64135878b55SSascha Wildner 64235878b55SSascha Wildner #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) 64335878b55SSascha Wildner #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) 64435878b55SSascha Wildner 64535878b55SSascha Wildner do { 64635878b55SSascha Wildner if (idx >= MAX_SG_DESCRIPTORS) return FALSE; 64735878b55SSascha Wildner 64835878b55SSascha Wildner pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); 64935878b55SSascha Wildner currvaddr = v; 65035878b55SSascha Wildner currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); 65135878b55SSascha Wildner 65235878b55SSascha Wildner 65335878b55SSascha Wildner do { 65435878b55SSascha Wildner nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); 65535878b55SSascha Wildner nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); 65635878b55SSascha Wildner 65735878b55SSascha Wildner if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; 65835878b55SSascha Wildner nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); 65935878b55SSascha Wildner 66035878b55SSascha Wildner if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { 66135878b55SSascha Wildner nextvaddr = nextpage; 66235878b55SSascha Wildner break; 66335878b55SSascha Wildner } 66435878b55SSascha Wildner 66535878b55SSascha Wildner currvaddr = nextvaddr; 66635878b55SSascha Wildner currphypage = nextphypage; 66735878b55SSascha Wildner }while (1); 66835878b55SSascha Wildner 66935878b55SSascha Wildner length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; 67035878b55SSascha Wildner v = nextvaddr; 67135878b55SSascha Wildner bufferSize -= length; 67235878b55SSascha Wildner 67335878b55SSascha Wildner pSgTable[idx].wSgSize = (USHORT)length; 67435878b55SSascha Wildner pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; 67535878b55SSascha Wildner idx++; 67635878b55SSascha Wildner 67735878b55SSascha Wildner }while (bufferSize); 67835878b55SSascha Wildner } 67935878b55SSascha Wildner return 1; 68035878b55SSascha Wildner } 68135878b55SSascha Wildner 68235878b55SSascha Wildner static int End_Job=0; 68335878b55SSascha Wildner void HPTLIBAPI 68435878b55SSascha Wildner thread_io_done(_VBUS_ARG PCommand pCmd) 68535878b55SSascha Wildner { 68635878b55SSascha Wildner End_Job = 1; 68735878b55SSascha Wildner wakeup((caddr_t)pCmd); 68835878b55SSascha Wildner } 68935878b55SSascha Wildner 69035878b55SSascha Wildner void 69135878b55SSascha Wildner hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) 69235878b55SSascha Wildner { 69335878b55SSascha Wildner DWORD timeout = 0; 69435878b55SSascha Wildner ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); 69535878b55SSascha Wildner PCommand pCmd; 69635878b55SSascha Wildner UINT result; 69735878b55SSascha Wildner int needsync=0, retry=0, needdelete=0; 69835878b55SSascha Wildner void *buffer = 0; 69935878b55SSascha Wildner 70035878b55SSascha Wildner _VBUS_INST(&pAdapter->VBus) 70135878b55SSascha Wildner 70235878b55SSascha Wildner if (pArray->u.array.rf_broken==1 || 70335878b55SSascha Wildner pArray->u.array.RebuildSectors>=capacity) 70435878b55SSascha Wildner return; 70535878b55SSascha Wildner 706*c898d682SSascha Wildner lock_driver(); 70735878b55SSascha Wildner 70835878b55SSascha Wildner switch(flags) 70935878b55SSascha Wildner { 71035878b55SSascha Wildner case DUPLICATE: 71135878b55SSascha Wildner case REBUILD_PARITY: 71235878b55SSascha Wildner if(pArray->u.array.rf_rebuilding == 0) 71335878b55SSascha Wildner { 71435878b55SSascha Wildner pArray->u.array.rf_rebuilding = 1; 71535878b55SSascha Wildner hpt_printk(("Rebuilding started.\n")); 71635878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); 71735878b55SSascha Wildner } 71835878b55SSascha Wildner break; 71935878b55SSascha Wildner 72035878b55SSascha Wildner case INITIALIZE: 72135878b55SSascha Wildner if(pArray->u.array.rf_initializing == 0) 72235878b55SSascha Wildner { 72335878b55SSascha Wildner pArray->u.array.rf_initializing = 1; 72435878b55SSascha Wildner hpt_printk(("Initializing started.\n")); 72535878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); 72635878b55SSascha Wildner } 72735878b55SSascha Wildner break; 72835878b55SSascha Wildner 72935878b55SSascha Wildner case VERIFY: 73035878b55SSascha Wildner if(pArray->u.array.rf_verifying == 0) 73135878b55SSascha Wildner { 73235878b55SSascha Wildner pArray->u.array.rf_verifying = 1; 73335878b55SSascha Wildner hpt_printk(("Verifying started.\n")); 73435878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); 73535878b55SSascha Wildner } 73635878b55SSascha Wildner break; 73735878b55SSascha Wildner } 73835878b55SSascha Wildner 73935878b55SSascha Wildner retry_cmd: 74035878b55SSascha Wildner pCmd = AllocateCommand(_VBUS_P0); 74135878b55SSascha Wildner HPT_ASSERT(pCmd); 74235878b55SSascha Wildner pCmd->cf_control = 1; 74335878b55SSascha Wildner End_Job = 0; 74435878b55SSascha Wildner 74535878b55SSascha Wildner if (pArray->VDeviceType==VD_RAID_1) 74635878b55SSascha Wildner { 74735878b55SSascha Wildner #define MAX_REBUILD_SECTORS 0x40 74835878b55SSascha Wildner 74935878b55SSascha Wildner /* take care for discontinuous buffer in R1ControlSgl */ 750*c898d682SSascha Wildner unlock_driver(); 75135878b55SSascha Wildner buffer = kmalloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); 752*c898d682SSascha Wildner lock_driver(); 75335878b55SSascha Wildner if(!buffer) { 75435878b55SSascha Wildner FreeCommand(_VBUS_P pCmd); 75535878b55SSascha Wildner hpt_printk(("can't allocate rebuild buffer\n")); 75635878b55SSascha Wildner goto fail; 75735878b55SSascha Wildner } 75835878b55SSascha Wildner switch(flags) 75935878b55SSascha Wildner { 76035878b55SSascha Wildner case DUPLICATE: 76135878b55SSascha Wildner pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 76235878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 76335878b55SSascha Wildner break; 76435878b55SSascha Wildner 76535878b55SSascha Wildner case VERIFY: 76635878b55SSascha Wildner pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; 76735878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; 76835878b55SSascha Wildner break; 76935878b55SSascha Wildner 77035878b55SSascha Wildner case INITIALIZE: 77135878b55SSascha Wildner pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 77235878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 77335878b55SSascha Wildner break; 77435878b55SSascha Wildner } 77535878b55SSascha Wildner 77635878b55SSascha Wildner pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; 77735878b55SSascha Wildner 77835878b55SSascha Wildner if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) 77935878b55SSascha Wildner pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; 78035878b55SSascha Wildner 78135878b55SSascha Wildner pCmd->uCmd.R1Control.Buffer = buffer; 78235878b55SSascha Wildner pCmd->pfnBuildSgl = R1ControlSgl; 78335878b55SSascha Wildner } 78435878b55SSascha Wildner else if (pArray->VDeviceType==VD_RAID_5) 78535878b55SSascha Wildner { 78635878b55SSascha Wildner switch(flags) 78735878b55SSascha Wildner { 78835878b55SSascha Wildner case DUPLICATE: 78935878b55SSascha Wildner case REBUILD_PARITY: 79035878b55SSascha Wildner pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; 79135878b55SSascha Wildner case VERIFY: 79235878b55SSascha Wildner pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; 79335878b55SSascha Wildner case INITIALIZE: 79435878b55SSascha Wildner pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; 79535878b55SSascha Wildner } 79635878b55SSascha Wildner pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; 79735878b55SSascha Wildner } 79835878b55SSascha Wildner else 79935878b55SSascha Wildner HPT_ASSERT(0); 80035878b55SSascha Wildner 80135878b55SSascha Wildner pCmd->pVDevice = pArray; 80235878b55SSascha Wildner pCmd->pfnCompletion = thread_io_done; 80335878b55SSascha Wildner pArray->pfnSendCommand(_VBUS_P pCmd); 80435878b55SSascha Wildner CheckPendingCall(_VBUS_P0); 80535878b55SSascha Wildner 80635878b55SSascha Wildner if (!End_Job) { 807*c898d682SSascha Wildner unlock_driver(); 80835878b55SSascha Wildner while (!End_Job) { 80935878b55SSascha Wildner tsleep((caddr_t)pCmd, 0, "pause", hz); 81035878b55SSascha Wildner if (timeout++>60) break; 81135878b55SSascha Wildner } 812*c898d682SSascha Wildner lock_driver(); 81335878b55SSascha Wildner if (!End_Job) { 81435878b55SSascha Wildner hpt_printk(("timeout, reset\n")); 81535878b55SSascha Wildner fResetVBus(_VBUS_P0); 81635878b55SSascha Wildner } 81735878b55SSascha Wildner } 81835878b55SSascha Wildner 81935878b55SSascha Wildner result = pCmd->Result; 82035878b55SSascha Wildner FreeCommand(_VBUS_P pCmd); 821*c898d682SSascha Wildner unlock_driver(); 82235878b55SSascha Wildner if (buffer) kfree(buffer, M_DEVBUF); 823*c898d682SSascha Wildner lock_driver(); 82435878b55SSascha Wildner KdPrintI(("cmd finished %d", result)); 82535878b55SSascha Wildner 82635878b55SSascha Wildner switch(result) 82735878b55SSascha Wildner { 82835878b55SSascha Wildner case RETURN_SUCCESS: 82935878b55SSascha Wildner if (!pArray->u.array.rf_abort_rebuild) 83035878b55SSascha Wildner { 83135878b55SSascha Wildner if(pArray->u.array.RebuildSectors < capacity) 83235878b55SSascha Wildner { 83335878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); 83435878b55SSascha Wildner } 83535878b55SSascha Wildner else 83635878b55SSascha Wildner { 83735878b55SSascha Wildner switch (flags) 83835878b55SSascha Wildner { 83935878b55SSascha Wildner case DUPLICATE: 84035878b55SSascha Wildner case REBUILD_PARITY: 84135878b55SSascha Wildner needsync = 1; 84235878b55SSascha Wildner pArray->u.array.rf_rebuilding = 0; 84335878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 0; 84435878b55SSascha Wildner pArray->u.array.CriticalMembers = 0; 84535878b55SSascha Wildner pArray->u.array.RebuildSectors = MAX_LBA_T; 84635878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 0; 84735878b55SSascha Wildner hpt_printk(("Rebuilding finished.\n")); 84835878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); 84935878b55SSascha Wildner break; 85035878b55SSascha Wildner case INITIALIZE: 85135878b55SSascha Wildner needsync = 1; 85235878b55SSascha Wildner pArray->u.array.rf_initializing = 0; 85335878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 0; 85435878b55SSascha Wildner pArray->u.array.RebuildSectors = MAX_LBA_T; 85535878b55SSascha Wildner hpt_printk(("Initializing finished.\n")); 85635878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); 85735878b55SSascha Wildner break; 85835878b55SSascha Wildner case VERIFY: 85935878b55SSascha Wildner pArray->u.array.rf_verifying = 0; 86035878b55SSascha Wildner hpt_printk(("Verifying finished.\n")); 86135878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); 86235878b55SSascha Wildner break; 86335878b55SSascha Wildner } 86435878b55SSascha Wildner } 86535878b55SSascha Wildner } 86635878b55SSascha Wildner else 86735878b55SSascha Wildner { 86835878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0; 86935878b55SSascha Wildner if (pArray->u.array.rf_rebuilding) 87035878b55SSascha Wildner { 87135878b55SSascha Wildner hpt_printk(("Abort rebuilding.\n")); 87235878b55SSascha Wildner pArray->u.array.rf_rebuilding = 0; 87335878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 0; 87435878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); 87535878b55SSascha Wildner } 87635878b55SSascha Wildner else if (pArray->u.array.rf_verifying) 87735878b55SSascha Wildner { 87835878b55SSascha Wildner hpt_printk(("Abort verifying.\n")); 87935878b55SSascha Wildner pArray->u.array.rf_verifying = 0; 88035878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); 88135878b55SSascha Wildner } 88235878b55SSascha Wildner else if (pArray->u.array.rf_initializing) 88335878b55SSascha Wildner { 88435878b55SSascha Wildner hpt_printk(("Abort initializing.\n")); 88535878b55SSascha Wildner pArray->u.array.rf_initializing = 0; 88635878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); 88735878b55SSascha Wildner } 88835878b55SSascha Wildner needdelete=1; 88935878b55SSascha Wildner } 89035878b55SSascha Wildner break; 89135878b55SSascha Wildner 89235878b55SSascha Wildner case RETURN_DATA_ERROR: 89335878b55SSascha Wildner if (flags==VERIFY) 89435878b55SSascha Wildner { 89535878b55SSascha Wildner needsync = 1; 89635878b55SSascha Wildner pArray->u.array.rf_verifying = 0; 89735878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 1; 89835878b55SSascha Wildner hpt_printk(("Verifying failed: found inconsistency\n")); 89935878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); 90035878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 90135878b55SSascha Wildner 90235878b55SSascha Wildner if (!pArray->vf_online || pArray->u.array.rf_broken) break; 90335878b55SSascha Wildner 90435878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 0; 90535878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0; 90635878b55SSascha Wildner hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 90735878b55SSascha Wildner (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); 90835878b55SSascha Wildner } 90935878b55SSascha Wildner break; 91035878b55SSascha Wildner 91135878b55SSascha Wildner default: 91235878b55SSascha Wildner hpt_printk(("command failed with error %d\n", result)); 91335878b55SSascha Wildner if (++retry<3) 91435878b55SSascha Wildner { 91535878b55SSascha Wildner hpt_printk(("retry (%d)\n", retry)); 91635878b55SSascha Wildner goto retry_cmd; 91735878b55SSascha Wildner } 91835878b55SSascha Wildner fail: 91935878b55SSascha Wildner pArray->u.array.rf_abort_rebuild = 0; 92035878b55SSascha Wildner switch (flags) 92135878b55SSascha Wildner { 92235878b55SSascha Wildner case DUPLICATE: 92335878b55SSascha Wildner case REBUILD_PARITY: 92435878b55SSascha Wildner needsync = 1; 92535878b55SSascha Wildner pArray->u.array.rf_rebuilding = 0; 92635878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 0; 92735878b55SSascha Wildner hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); 92835878b55SSascha Wildner ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); 92935878b55SSascha Wildner break; 93035878b55SSascha Wildner 93135878b55SSascha Wildner case INITIALIZE: 93235878b55SSascha Wildner needsync = 1; 93335878b55SSascha Wildner pArray->u.array.rf_initializing = 0; 93435878b55SSascha Wildner hpt_printk(("Initializing failed.\n")); 93535878b55SSascha Wildner ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); 93635878b55SSascha Wildner break; 93735878b55SSascha Wildner 93835878b55SSascha Wildner case VERIFY: 93935878b55SSascha Wildner needsync = 1; 94035878b55SSascha Wildner pArray->u.array.rf_verifying = 0; 94135878b55SSascha Wildner hpt_printk(("Verifying failed.\n")); 94235878b55SSascha Wildner ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 94335878b55SSascha Wildner break; 94435878b55SSascha Wildner } 94535878b55SSascha Wildner needdelete=1; 94635878b55SSascha Wildner } 94735878b55SSascha Wildner 94835878b55SSascha Wildner while (pAdapter->outstandingCommands) 94935878b55SSascha Wildner { 95035878b55SSascha Wildner KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); 95135878b55SSascha Wildner /* put this to have driver stop processing system commands quickly */ 95235878b55SSascha Wildner if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 953*c898d682SSascha Wildner unlock_driver(); 95435878b55SSascha Wildner /*Schedule out*/ 95535878b55SSascha Wildner tsleep(hpt_rebuild_data_block, 0, "switch", 1); 956*c898d682SSascha Wildner lock_driver(); 95735878b55SSascha Wildner } 95835878b55SSascha Wildner 95935878b55SSascha Wildner if (needsync) SyncArrayInfo(pArray); 96035878b55SSascha Wildner if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) 96135878b55SSascha Wildner fDeleteArray(_VBUS_P pArray, TRUE); 96235878b55SSascha Wildner 96335878b55SSascha Wildner Check_Idle_Call(pAdapter); 964*c898d682SSascha Wildner unlock_driver(); 96535878b55SSascha Wildner } 966