1136849Sscottl/* 2149871Sscottl * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 3136849Sscottl * All rights reserved. 4136849Sscottl * 5136849Sscottl * Redistribution and use in source and binary forms, with or without 6136849Sscottl * modification, are permitted provided that the following conditions 7136849Sscottl * are met: 8136849Sscottl * 1. Redistributions of source code must retain the above copyright 9136849Sscottl * notice, this list of conditions and the following disclaimer. 10136849Sscottl * 2. Redistributions in binary form must reproduce the above copyright 11136849Sscottl * notice, this list of conditions and the following disclaimer in the 12136849Sscottl * documentation and/or other materials provided with the distribution. 13136849Sscottl * 14136849Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15136849Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16136849Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17136849Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18136849Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19136849Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20136849Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21136849Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22136849Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23136849Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24136849Sscottl * SUCH DAMAGE. 25142988Sscottl * 26142988Sscottl * $FreeBSD: releng/10.3/sys/dev/hptmv/ioctl.c 190809 2009-04-07 16:38:25Z delphij $ 27136849Sscottl */ 28136849Sscottl/* 29136849Sscottl * ioctl.c ioctl interface implementation 30136849Sscottl */ 31136849Sscottl#include <sys/param.h> 32136849Sscottl#include <sys/systm.h> 33136849Sscottl#include <sys/kernel.h> 34136849Sscottl#include <sys/malloc.h> 35136849Sscottl 36149871Sscottl#if (__FreeBSD_version < 500000) 37149871Sscottl#include <sys/proc.h> 38149871Sscottl#include <sys/kthread.h> 39149871Sscottl#include <sys/wait.h> 40149871Sscottl#include <sys/sysproto.h> 41149871Sscottl#endif 42149871Sscottl 43149871Sscottl#ifndef __KERNEL__ 44149871Sscottl#define __KERNEL__ 45149871Sscottl#endif 46149871Sscottl 47136849Sscottl#include <dev/hptmv/global.h> 48136849Sscottl#include <dev/hptmv/hptintf.h> 49136849Sscottl#include <dev/hptmv/osbsd.h> 50143039Sscottl#include <dev/hptmv/access601.h> 51136849Sscottl 52136849Sscottl#pragma pack(1) 53136849Sscottl 54136849Sscottltypedef struct _HPT_REBUILD_PARAM 55136849Sscottl{ 56136849Sscottl DEVICEID idMirror; 57136849Sscottl DWORD Lba; 58136849Sscottl UCHAR nSector; 59136849Sscottl} HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM; 60136849Sscottl 61136849Sscottl#pragma pack() 62136849Sscottl 63136849Sscottl#define MAX_EVENTS 10 64136849Sscottlstatic HPT_EVENT hpt_event_queue[MAX_EVENTS]; 65136849Sscottlstatic int event_queue_head=0, event_queue_tail=0; 66136849Sscottl 67136849Sscottlstatic int hpt_get_event(PHPT_EVENT pEvent); 68136849Sscottlstatic int hpt_set_array_state(DEVICEID idArray, DWORD state); 69136849Sscottlstatic intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter); 70136849Sscottlstatic void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); 71136849Sscottlstatic int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, 72136849Sscottl FPSCAT_GATH pSgTable, int logical); 73136849Sscottl 74149871Sscottlstatic void 75149871Sscottlget_disk_location(PDevice pDev, int *controller, int *channel) 76136849Sscottl{ 77136849Sscottl IAL_ADAPTER_T *pAdapTemp; 78136849Sscottl int i, j; 79136849Sscottl 80169823Smjacob *controller = *channel = 0; 81169823Smjacob 82169823Smjacob for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) { 83169823Smjacob for (j=0; j<MV_SATA_CHANNELS_NUM; j++) { 84169823Smjacob if (pDev == &pAdapTemp->VDevices[j].u.disk) { 85169823Smjacob *controller = i; 86169823Smjacob *channel = j; 87169823Smjacob return; 88169823Smjacob } 89169823Smjacob } 90136849Sscottl } 91136849Sscottl} 92136849Sscottl 93149871Sscottlstatic int 94149871Sscottlevent_queue_add(PHPT_EVENT pEvent) 95136849Sscottl{ 96136849Sscottl int p; 97136849Sscottl p = (event_queue_tail + 1) % MAX_EVENTS; 98136849Sscottl if (p==event_queue_head) 99136849Sscottl { 100136849Sscottl return -1; 101136849Sscottl } 102136849Sscottl hpt_event_queue[event_queue_tail] = *pEvent; 103136849Sscottl event_queue_tail = p; 104136849Sscottl return 0; 105136849Sscottl} 106136849Sscottl 107149871Sscottlstatic int 108149871Sscottlevent_queue_remove(PHPT_EVENT pEvent) 109136849Sscottl{ 110136849Sscottl if (event_queue_head != event_queue_tail) 111136849Sscottl { 112136849Sscottl *pEvent = hpt_event_queue[event_queue_head]; 113136849Sscottl event_queue_head++; 114136849Sscottl event_queue_head %= MAX_EVENTS; 115136849Sscottl return 0; 116136849Sscottl } 117136849Sscottl return -1; 118136849Sscottl} 119136849Sscottl 120149871Sscottlvoid HPTLIBAPI 121149871Sscottlioctl_ReportEvent(UCHAR event, PVOID param) 122136849Sscottl{ 123136849Sscottl HPT_EVENT e; 124136849Sscottl ZeroMemory(&e, sizeof(e)); 125136849Sscottl e.EventType = event; 126136849Sscottl switch(event) 127136849Sscottl { 128136849Sscottl case ET_INITIALIZE_ABORTED: 129136849Sscottl case ET_INITIALIZE_FAILED: 130136849Sscottl memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME); 131136849Sscottl case ET_INITIALIZE_STARTED: 132136849Sscottl case ET_INITIALIZE_FINISHED: 133136849Sscottl 134136849Sscottl case ET_REBUILD_STARTED: 135136849Sscottl case ET_REBUILD_ABORTED: 136136849Sscottl case ET_REBUILD_FAILED: 137136849Sscottl case ET_REBUILD_FINISHED: 138136849Sscottl 139136849Sscottl case ET_VERIFY_STARTED: 140136849Sscottl case ET_VERIFY_ABORTED: 141136849Sscottl case ET_VERIFY_FAILED: 142136849Sscottl case ET_VERIFY_FINISHED: 143136849Sscottl case ET_VERIFY_DATA_ERROR: 144136849Sscottl 145136849Sscottl case ET_SPARE_TOOK_OVER: 146136849Sscottl case ET_DEVICE_REMOVED: 147136849Sscottl case ET_DEVICE_PLUGGED: 148136849Sscottl case ET_DEVICE_ERROR: 149136849Sscottl e.DeviceID = VDEV_TO_ID((PVDevice)param); 150136849Sscottl break; 151136849Sscottl 152136849Sscottl default: 153136849Sscottl break; 154136849Sscottl } 155136849Sscottl event_queue_add(&e); 156136849Sscottl if (event==ET_DEVICE_REMOVED) { 157169823Smjacob int controller, channel; 158136849Sscottl get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel); 159136849Sscottl hpt_printk(("Device removed: controller %d channel %d\n", controller, channel)); 160136849Sscottl } 161136849Sscottl} 162136849Sscottl 163149871Sscottlstatic int 164149871Sscottlhpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) 165136849Sscottl{ 166136849Sscottl PVDevice pArray = ID_TO_VDEV(id); 167136849Sscottl BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; 168136849Sscottl int i; 169136849Sscottl PVDevice pa; 170136849Sscottl 171149871Sscottl if ((id==0) || check_VDevice_valid(pArray)) 172136849Sscottl return -1; 173136849Sscottl 174136849Sscottl if(!mIsArray(pArray)) return -1; 175136849Sscottl 176136849Sscottl if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying || 177136849Sscottl pArray->u.array.rf_initializing) 178136849Sscottl return -1; 179136849Sscottl 180136849Sscottl for(i=0; i<pArray->u.array.bArnMember; i++) { 181136849Sscottl pa = pArray->u.array.pMember[i]; 182136849Sscottl if (pa && mIsArray(pa)) { 183136849Sscottl if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 184136849Sscottl pa->u.array.rf_initializing) 185136849Sscottl return -1; 186136849Sscottl } 187136849Sscottl } 188136849Sscottl 189136849Sscottl if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 190136849Sscottl fDeleteArray(_VBUS_P pArray, del_block0); 191136849Sscottl return 0; 192136849Sscottl 193136849Sscottl} 194136849Sscottl 195136849Sscottl/* just to prevent driver from sending more commands */ 196136849Sscottlstatic void HPTLIBAPI nothing(_VBUS_ARG void *notused){} 197136849Sscottl 198149871Sscottlintrmask_t 199149871Sscottllock_driver_idle(IAL_ADAPTER_T *pAdapter) 200136849Sscottl{ 201136849Sscottl intrmask_t oldspl; 202136849Sscottl _VBUS_INST(&pAdapter->VBus) 203136849Sscottl oldspl = lock_driver(); 204136849Sscottl while (pAdapter->outstandingCommands) { 205136849Sscottl KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); 206136849Sscottl if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 207136849Sscottl unlock_driver(oldspl); 208149871Sscottl/*Schedule out*/ 209149871Sscottl#if (__FreeBSD_version < 500000) 210149871Sscottl YIELD_THREAD; 211149871Sscottl#else 212190809Sdelphij#if (__FreeBSD_version > 700033) 213167086Sjhb pause("switch", 1); 214190809Sdelphij#else 215190809Sdelphij tsleep(lock_driver_idle, PPAUSE, "switch", 1); 216149871Sscottl#endif 217190809Sdelphij#endif 218136849Sscottl oldspl = lock_driver(); 219136849Sscottl } 220136849Sscottl CheckIdleCall(_VBUS_P0); 221136849Sscottl return oldspl; 222136849Sscottl} 223136849Sscottl 224136849Sscottlint Kernel_DeviceIoControl(_VBUS_ARG 225136849Sscottl DWORD dwIoControlCode, /* operation control code */ 226136849Sscottl PVOID lpInBuffer, /* input data buffer */ 227136849Sscottl DWORD nInBufferSize, /* size of input data buffer */ 228136849Sscottl PVOID lpOutBuffer, /* output data buffer */ 229136849Sscottl DWORD nOutBufferSize, /* size of output data buffer */ 230136849Sscottl PDWORD lpBytesReturned /* byte count */ 231136849Sscottl ) 232136849Sscottl{ 233136849Sscottl IAL_ADAPTER_T *pAdapter; 234136849Sscottl 235136849Sscottl switch(dwIoControlCode) { 236136849Sscottl case HPT_IOCTL_DELETE_ARRAY: 237136849Sscottl { 238136849Sscottl DEVICEID idArray; 239136849Sscottl int iSuccess; 240136849Sscottl int i; 241136849Sscottl PVDevice pArray; 242136849Sscottl PVBus _vbus_p; 243136849Sscottl struct cam_periph *periph = NULL; 244136849Sscottl 245136849Sscottl if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; 246136849Sscottl if (nOutBufferSize!=sizeof(int)) return -1; 247136849Sscottl idArray = *(DEVICEID *)lpInBuffer; 248136849Sscottl 249136849Sscottl pArray = ID_TO_VDEV(idArray); 250136849Sscottl 251149871Sscottl if((idArray == 0) || check_VDevice_valid(pArray)) 252136849Sscottl return -1; 253136849Sscottl 254136849Sscottl if(!mIsArray(pArray)) 255136849Sscottl return -1; 256136849Sscottl 257136849Sscottl _vbus_p=pArray->pVBus; 258136849Sscottl pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 259136849Sscottl 260136849Sscottl for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { 261136849Sscottl if(pArray == _vbus_p->pVDevice[i]) 262136849Sscottl { 263136849Sscottl periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 264149871Sscottl if (periph != NULL && periph->refcount >= 1) 265136849Sscottl { 266136849Sscottl hpt_printk(("Can not delete a mounted device.\n")); 267136849Sscottl return -1; 268136849Sscottl } 269136849Sscottl } 270136849Sscottl /* the Mounted Disk isn't delete */ 271136849Sscottl } 272136849Sscottl 273136849Sscottl iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); 274136849Sscottl 275136849Sscottl *(int*)lpOutBuffer = iSuccess; 276136849Sscottl 277136849Sscottl if(iSuccess != 0) 278136849Sscottl return -1; 279136849Sscottl break; 280136849Sscottl } 281136849Sscottl 282136849Sscottl case HPT_IOCTL_GET_EVENT: 283136849Sscottl { 284136849Sscottl PHPT_EVENT pInfo; 285136849Sscottl 286136849Sscottl if (nInBufferSize!=0) return -1; 287136849Sscottl if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; 288136849Sscottl 289136849Sscottl pInfo = (PHPT_EVENT)lpOutBuffer; 290136849Sscottl 291136849Sscottl if (hpt_get_event(pInfo)!=0) 292136849Sscottl return -1; 293136849Sscottl } 294136849Sscottl break; 295136849Sscottl 296136849Sscottl case HPT_IOCTL_SET_ARRAY_STATE: 297136849Sscottl { 298136849Sscottl DEVICEID idArray; 299136849Sscottl DWORD state; 300136849Sscottl 301136849Sscottl if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; 302136849Sscottl if (nOutBufferSize!=0) return -1; 303136849Sscottl 304136849Sscottl idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; 305136849Sscottl state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; 306136849Sscottl 307136849Sscottl if(hpt_set_array_state(idArray, state)!=0) 308136849Sscottl return -1; 309136849Sscottl } 310136849Sscottl break; 311136849Sscottl 312136849Sscottl case HPT_IOCTL_RESCAN_DEVICES: 313136849Sscottl { 314136849Sscottl if (nInBufferSize!=0) return -1; 315136849Sscottl if (nOutBufferSize!=0) return -1; 316136849Sscottl 317136849Sscottl#ifndef FOR_DEMO 318136849Sscottl /* stop buzzer if user perform rescan */ 319136849Sscottl for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 320136849Sscottl if (pAdapter->beeping) { 321136849Sscottl pAdapter->beeping = 0; 322136849Sscottl BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 323136849Sscottl } 324136849Sscottl } 325136849Sscottl#endif 326136849Sscottl } 327136849Sscottl break; 328136849Sscottl 329136849Sscottl default: 330136849Sscottl { 331136849Sscottl PVDevice pVDev; 332136849Sscottl#ifdef SUPPORT_ARRAY 333136849Sscottl intrmask_t oldspl; 334136849Sscottl#endif 335136849Sscottl switch(dwIoControlCode) { 336136849Sscottl /* read-only ioctl functions can be called directly. */ 337136849Sscottl case HPT_IOCTL_GET_VERSION: 338136849Sscottl case HPT_IOCTL_GET_CONTROLLER_IDS: 339136849Sscottl case HPT_IOCTL_GET_CONTROLLER_COUNT: 340136849Sscottl case HPT_IOCTL_GET_CONTROLLER_INFO: 341136849Sscottl case HPT_IOCTL_GET_CHANNEL_INFO: 342136849Sscottl case HPT_IOCTL_GET_LOGICAL_DEVICES: 343136849Sscottl case HPT_IOCTL_GET_DEVICE_INFO: 344190809Sdelphij case HPT_IOCTL_GET_DEVICE_INFO_V2: 345136849Sscottl case HPT_IOCTL_GET_EVENT: 346136849Sscottl case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 347136849Sscottl if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 348136849Sscottl lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; 349136849Sscottl break; 350136849Sscottl 351136849Sscottl default: 352136849Sscottl /* 353136849Sscottl * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 354136849Sscottl * wrong for second controller. 355136849Sscottl */ 356136849Sscottl switch(dwIoControlCode) { 357136849Sscottl case HPT_IOCTL_CREATE_ARRAY: 358136849Sscottl pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; 359190809Sdelphij case HPT_IOCTL_CREATE_ARRAY_V2: 360190809Sdelphij pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break; 361136849Sscottl case HPT_IOCTL_SET_ARRAY_INFO: 362136849Sscottl pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; 363136849Sscottl case HPT_IOCTL_SET_DEVICE_INFO: 364136849Sscottl pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; 365190809Sdelphij case HPT_IOCTL_SET_DEVICE_INFO_V2: 366190809Sdelphij pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break; 367136849Sscottl case HPT_IOCTL_SET_BOOT_MARK: 368136849Sscottl case HPT_IOCTL_ADD_SPARE_DISK: 369136849Sscottl case HPT_IOCTL_REMOVE_SPARE_DISK: 370136849Sscottl pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; 371136849Sscottl case HPT_IOCTL_ADD_DISK_TO_ARRAY: 372136849Sscottl pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; 373136849Sscottl default: 374136849Sscottl pVDev = 0; 375136849Sscottl } 376136849Sscottl 377136849Sscottl if (pVDev && !check_VDevice_valid(pVDev)){ 378136849Sscottl _vbus_p = pVDev->pVBus; 379136849Sscottl 380136849Sscottl pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 381136849Sscottl /* 382136849Sscottl * create_array, and other functions can't be executed while channel is 383136849Sscottl * perform I/O commands. Wait until driver is idle. 384136849Sscottl */ 385136849Sscottl oldspl = lock_driver_idle(pAdapter); 386136849Sscottl if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 387136849Sscottl lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { 388136849Sscottl unlock_driver(oldspl); 389136849Sscottl return -1; 390136849Sscottl } 391136849Sscottl unlock_driver(oldspl); 392136849Sscottl } 393136849Sscottl else 394136849Sscottl return -1; 395136849Sscottl break; 396136849Sscottl } 397136849Sscottl 398136849Sscottl#ifdef SUPPORT_ARRAY 399136849Sscottl switch(dwIoControlCode) 400136849Sscottl { 401136849Sscottl case HPT_IOCTL_CREATE_ARRAY: 402136849Sscottl { 403136849Sscottl pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 404136849Sscottl oldspl = lock_driver(); 405136849Sscottl if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) 406136849Sscottl { 407136849Sscottl (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 408136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 409136849Sscottl } 410136849Sscottl else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) 411136849Sscottl { 412136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 413136849Sscottl } 414136849Sscottl else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) 415136849Sscottl { 416136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 417136849Sscottl } 418136849Sscottl unlock_driver(oldspl); 419136849Sscottl break; 420136849Sscottl } 421136849Sscottl 422190809Sdelphij 423190809Sdelphij case HPT_IOCTL_CREATE_ARRAY_V2: 424190809Sdelphij { 425190809Sdelphij pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 426190809Sdelphij oldspl = lock_driver(); 427190809Sdelphij if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) { 428190809Sdelphij (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 429190809Sdelphij hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 430190809Sdelphij } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) { 431190809Sdelphij hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 432190809Sdelphij } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) { 433190809Sdelphij hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 434190809Sdelphij } 435190809Sdelphij unlock_driver(oldspl); 436190809Sdelphij break; 437190809Sdelphij } 438136849Sscottl case HPT_IOCTL_ADD_DISK_TO_ARRAY: 439136849Sscottl { 440136849Sscottl PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); 441136849Sscottl pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; 442149871Sscottl if(pArray->u.array.rf_rebuilding == 0) 443136849Sscottl { 444136849Sscottl DWORD timeout = 0; 445136849Sscottl oldspl = lock_driver(); 446136849Sscottl pArray->u.array.rf_auto_rebuild = 0; 447136849Sscottl pArray->u.array.rf_abort_rebuild = 0; 448136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 449136849Sscottl unlock_driver(oldspl); 450136849Sscottl while (!pArray->u.array.rf_rebuilding) 451136849Sscottl { 452190809Sdelphij#if (__FreeBSD_version > 700033) 453167086Sjhb pause("pause", 1); 454190809Sdelphij#else 455190809Sdelphij tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1); 456190809Sdelphij#endif 457136849Sscottl if ( timeout >= hz*3) 458136849Sscottl break; 459136849Sscottl timeout ++; 460136849Sscottl } 461136849Sscottl } 462136849Sscottl break; 463136849Sscottl } 464136849Sscottl } 465136849Sscottl#endif 466136849Sscottl return 0; 467136849Sscottl } 468136849Sscottl } 469136849Sscottl 470136849Sscottl if (lpBytesReturned) 471136849Sscottl *lpBytesReturned = nOutBufferSize; 472136849Sscottl return 0; 473136849Sscottl} 474136849Sscottl 475149871Sscottlstatic int 476149871Sscottlhpt_get_event(PHPT_EVENT pEvent) 477136849Sscottl{ 478136849Sscottl intrmask_t oldspl = lock_driver(); 479136849Sscottl int ret = event_queue_remove(pEvent); 480136849Sscottl unlock_driver(oldspl); 481136849Sscottl return ret; 482136849Sscottl} 483136849Sscottl 484149871Sscottlstatic int 485149871Sscottlhpt_set_array_state(DEVICEID idArray, DWORD state) 486136849Sscottl{ 487136849Sscottl IAL_ADAPTER_T *pAdapter; 488136849Sscottl PVDevice pVDevice = ID_TO_VDEV(idArray); 489136849Sscottl int i; 490136849Sscottl DWORD timeout = 0; 491136849Sscottl intrmask_t oldspl; 492136849Sscottl 493149871Sscottl if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; 494136849Sscottl if(!mIsArray(pVDevice)) 495136849Sscottl return -1; 496136849Sscottl if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; 497136849Sscottl 498136849Sscottl pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt; 499136849Sscottl 500136849Sscottl switch(state) 501136849Sscottl { 502136849Sscottl case MIRROR_REBUILD_START: 503136849Sscottl { 504136849Sscottl if (pVDevice->u.array.rf_rebuilding || 505136849Sscottl pVDevice->u.array.rf_verifying || 506136849Sscottl pVDevice->u.array.rf_initializing) 507136849Sscottl return -1; 508136849Sscottl 509136849Sscottl oldspl = lock_driver(); 510136849Sscottl 511136849Sscottl pVDevice->u.array.rf_auto_rebuild = 0; 512136849Sscottl pVDevice->u.array.rf_abort_rebuild = 0; 513136849Sscottl 514136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 515136849Sscottl (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 516136849Sscottl 517136849Sscottl unlock_driver(oldspl); 518136849Sscottl 519136849Sscottl while (!pVDevice->u.array.rf_rebuilding) 520136849Sscottl { 521190809Sdelphij#if (__FreeBSD_version > 700033) 522167086Sjhb pause("pause", 1); 523190809Sdelphij#else 524190809Sdelphij tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 525190809Sdelphij#endif 526136849Sscottl if ( timeout >= hz*20) 527136849Sscottl break; 528136849Sscottl timeout ++; 529136849Sscottl } 530136849Sscottl } 531136849Sscottl 532136849Sscottl break; 533136849Sscottl 534136849Sscottl case MIRROR_REBUILD_ABORT: 535136849Sscottl { 536136849Sscottl for(i = 0; i < pVDevice->u.array.bArnMember; i++) { 537149871Sscottl if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) 538136849Sscottl hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); 539136849Sscottl } 540136849Sscottl 541136849Sscottl if(pVDevice->u.array.rf_rebuilding != 1) 542136849Sscottl return -1; 543136849Sscottl 544136849Sscottl oldspl = lock_driver(); 545136849Sscottl pVDevice->u.array.rf_abort_rebuild = 1; 546136849Sscottl unlock_driver(oldspl); 547136849Sscottl 548136849Sscottl while (pVDevice->u.array.rf_abort_rebuild) 549136849Sscottl { 550190809Sdelphij#if (__FreeBSD_version > 700033) 551167086Sjhb pause("pause", 1); 552190809Sdelphij#else 553190809Sdelphij tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 554190809Sdelphij#endif 555136849Sscottl if ( timeout >= hz*20) 556136849Sscottl break; 557136849Sscottl timeout ++; 558136849Sscottl } 559136849Sscottl } 560136849Sscottl break; 561136849Sscottl 562136849Sscottl case AS_VERIFY_START: 563136849Sscottl { 564136849Sscottl /*if(pVDevice->u.array.rf_verifying) 565136849Sscottl return -1;*/ 566136849Sscottl if (pVDevice->u.array.rf_rebuilding || 567136849Sscottl pVDevice->u.array.rf_verifying || 568136849Sscottl pVDevice->u.array.rf_initializing) 569136849Sscottl return -1; 570136849Sscottl 571136849Sscottl oldspl = lock_driver(); 572136849Sscottl pVDevice->u.array.RebuildSectors = 0; 573136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 574136849Sscottl unlock_driver(oldspl); 575136849Sscottl 576136849Sscottl while (!pVDevice->u.array.rf_verifying) 577136849Sscottl { 578190809Sdelphij#if (__FreeBSD_version > 700033) 579167086Sjhb pause("pause", 1); 580190809Sdelphij#else 581190809Sdelphij tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 582190809Sdelphij#endif 583136849Sscottl if ( timeout >= hz*20) 584136849Sscottl break; 585136849Sscottl timeout ++; 586136849Sscottl } 587136849Sscottl } 588136849Sscottl break; 589136849Sscottl 590136849Sscottl case AS_VERIFY_ABORT: 591136849Sscottl { 592136849Sscottl if(pVDevice->u.array.rf_verifying != 1) 593136849Sscottl return -1; 594136849Sscottl 595136849Sscottl oldspl = lock_driver(); 596136849Sscottl pVDevice->u.array.rf_abort_rebuild = 1; 597136849Sscottl unlock_driver(oldspl); 598136849Sscottl 599136849Sscottl while (pVDevice->u.array.rf_abort_rebuild) 600136849Sscottl { 601190809Sdelphij#if (__FreeBSD_version > 700033) 602167086Sjhb pause("pause", 1); 603190809Sdelphij#else 604190809Sdelphij tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 605190809Sdelphij#endif 606136849Sscottl if ( timeout >= hz*80) 607136849Sscottl break; 608136849Sscottl timeout ++; 609136849Sscottl } 610136849Sscottl } 611136849Sscottl break; 612136849Sscottl 613136849Sscottl case AS_INITIALIZE_START: 614136849Sscottl { 615136849Sscottl if (pVDevice->u.array.rf_rebuilding || 616136849Sscottl pVDevice->u.array.rf_verifying || 617136849Sscottl pVDevice->u.array.rf_initializing) 618136849Sscottl return -1; 619136849Sscottl 620136849Sscottl oldspl = lock_driver(); 621136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 622136849Sscottl unlock_driver(oldspl); 623136849Sscottl 624136849Sscottl while (!pVDevice->u.array.rf_initializing) 625136849Sscottl { 626190809Sdelphij#if (__FreeBSD_version > 700033) 627167086Sjhb pause("pause", 1); 628190809Sdelphij#else 629190809Sdelphij tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 630190809Sdelphij#endif 631136849Sscottl if ( timeout >= hz*80) 632136849Sscottl break; 633136849Sscottl timeout ++; 634136849Sscottl } 635136849Sscottl } 636136849Sscottl break; 637136849Sscottl 638136849Sscottl case AS_INITIALIZE_ABORT: 639136849Sscottl { 640136849Sscottl if(pVDevice->u.array.rf_initializing != 1) 641136849Sscottl return -1; 642136849Sscottl 643136849Sscottl oldspl = lock_driver(); 644136849Sscottl pVDevice->u.array.rf_abort_rebuild = 1; 645136849Sscottl unlock_driver(oldspl); 646136849Sscottl 647136849Sscottl while (pVDevice->u.array.rf_abort_rebuild) 648136849Sscottl { 649190809Sdelphij#if (__FreeBSD_version > 700033) 650167086Sjhb pause("pause", 1); 651190809Sdelphij#else 652190809Sdelphij tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 653190809Sdelphij#endif 654136849Sscottl if ( timeout >= hz*80) 655136849Sscottl break; 656136849Sscottl timeout ++; 657136849Sscottl } 658136849Sscottl } 659136849Sscottl break; 660136849Sscottl 661136849Sscottl default: 662136849Sscottl return -1; 663136849Sscottl } 664136849Sscottl 665136849Sscottl return 0; 666136849Sscottl} 667136849Sscottl 668149871Sscottlint HPTLIBAPI 669149871SscottlR1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) 670136849Sscottl{ 671136849Sscottl ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); 672136849Sscottl if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) 673136849Sscottl bufferSize<<=1; 674136849Sscottl if (logical) { 675136849Sscottl pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; 676136849Sscottl pSgTable->wSgSize = (USHORT)bufferSize; 677136849Sscottl pSgTable->wSgFlag = SG_FLAG_EOT; 678136849Sscottl } 679136849Sscottl else { 680136849Sscottl /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ 681136849Sscottl ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; 682136849Sscottl ULONG length; 683136849Sscottl int idx = 0; 684136849Sscottl 685136849Sscottl v = pCmd->uCmd.R1Control.Buffer; 686136849Sscottl dataPointer = (ADDRESS)fOsPhysicalAddress(v); 687136849Sscottl 688136849Sscottl if ((ULONG_PTR)dataPointer & 0x1) 689136849Sscottl return FALSE; 690136849Sscottl 691136849Sscottl #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) 692136849Sscottl #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) 693136849Sscottl 694136849Sscottl do { 695136849Sscottl if (idx >= MAX_SG_DESCRIPTORS) return FALSE; 696136849Sscottl 697136849Sscottl pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); 698136849Sscottl currvaddr = v; 699136849Sscottl currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); 700136849Sscottl 701136849Sscottl 702136849Sscottl do { 703136849Sscottl nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); 704136849Sscottl nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); 705136849Sscottl 706136849Sscottl if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; 707136849Sscottl nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); 708136849Sscottl 709136849Sscottl if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { 710136849Sscottl nextvaddr = nextpage; 711136849Sscottl break; 712136849Sscottl } 713136849Sscottl 714136849Sscottl currvaddr = nextvaddr; 715136849Sscottl currphypage = nextphypage; 716136849Sscottl }while (1); 717136849Sscottl 718136849Sscottl length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; 719136849Sscottl v = nextvaddr; 720136849Sscottl bufferSize -= length; 721136849Sscottl 722136849Sscottl pSgTable[idx].wSgSize = (USHORT)length; 723136849Sscottl pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; 724136849Sscottl idx++; 725136849Sscottl 726136849Sscottl }while (bufferSize); 727136849Sscottl } 728136849Sscottl return 1; 729136849Sscottl} 730136849Sscottl 731136849Sscottlstatic int End_Job=0; 732149871Sscottlvoid HPTLIBAPI 733149871Sscottlthread_io_done(_VBUS_ARG PCommand pCmd) 734136849Sscottl{ 735136849Sscottl End_Job = 1; 736136849Sscottl wakeup((caddr_t)pCmd); 737136849Sscottl} 738136849Sscottl 739149871Sscottlvoid 740149871Sscottlhpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) 741136849Sscottl{ 742136849Sscottl DWORD timeout = 0; 743136849Sscottl ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); 744136849Sscottl PCommand pCmd; 745136849Sscottl UINT result; 746136849Sscottl int needsync=0, retry=0, needdelete=0; 747136849Sscottl void *buffer = 0; 748136849Sscottl intrmask_t oldspl; 749136849Sscottl 750136849Sscottl _VBUS_INST(&pAdapter->VBus) 751136849Sscottl 752136849Sscottl if (pArray->u.array.rf_broken==1 || 753136849Sscottl pArray->u.array.RebuildSectors>=capacity) 754136849Sscottl return; 755136849Sscottl 756136849Sscottl oldspl = lock_driver(); 757136849Sscottl 758136849Sscottl switch(flags) 759136849Sscottl { 760136849Sscottl case DUPLICATE: 761136849Sscottl case REBUILD_PARITY: 762136849Sscottl if(pArray->u.array.rf_rebuilding == 0) 763136849Sscottl { 764136849Sscottl pArray->u.array.rf_rebuilding = 1; 765136849Sscottl hpt_printk(("Rebuilding started.\n")); 766136849Sscottl ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); 767136849Sscottl } 768136849Sscottl break; 769136849Sscottl 770136849Sscottl case INITIALIZE: 771136849Sscottl if(pArray->u.array.rf_initializing == 0) 772136849Sscottl { 773136849Sscottl pArray->u.array.rf_initializing = 1; 774136849Sscottl hpt_printk(("Initializing started.\n")); 775136849Sscottl ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); 776136849Sscottl } 777136849Sscottl break; 778136849Sscottl 779136849Sscottl case VERIFY: 780136849Sscottl if(pArray->u.array.rf_verifying == 0) 781136849Sscottl { 782136849Sscottl pArray->u.array.rf_verifying = 1; 783136849Sscottl hpt_printk(("Verifying started.\n")); 784136849Sscottl ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); 785136849Sscottl } 786136849Sscottl break; 787136849Sscottl } 788136849Sscottl 789136849Sscottlretry_cmd: 790136849Sscottl pCmd = AllocateCommand(_VBUS_P0); 791136849Sscottl HPT_ASSERT(pCmd); 792136849Sscottl pCmd->cf_control = 1; 793136849Sscottl End_Job = 0; 794136849Sscottl 795136849Sscottl if (pArray->VDeviceType==VD_RAID_1) 796136849Sscottl { 797136849Sscottl #define MAX_REBUILD_SECTORS 0x40 798136849Sscottl 799136849Sscottl /* take care for discontinuous buffer in R1ControlSgl */ 800149871Sscottl unlock_driver(oldspl); 801136849Sscottl buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); 802149871Sscottl oldspl = lock_driver(); 803136849Sscottl if(!buffer) { 804136849Sscottl FreeCommand(_VBUS_P pCmd); 805136849Sscottl hpt_printk(("can't allocate rebuild buffer\n")); 806136849Sscottl goto fail; 807136849Sscottl } 808136849Sscottl switch(flags) 809136849Sscottl { 810136849Sscottl case DUPLICATE: 811136849Sscottl pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 812136849Sscottl pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 813136849Sscottl break; 814136849Sscottl 815136849Sscottl case VERIFY: 816136849Sscottl pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; 817136849Sscottl pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; 818136849Sscottl break; 819136849Sscottl 820136849Sscottl case INITIALIZE: 821136849Sscottl pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 822136849Sscottl pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 823136849Sscottl break; 824136849Sscottl } 825136849Sscottl 826136849Sscottl pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; 827136849Sscottl 828136849Sscottl if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) 829136849Sscottl pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; 830136849Sscottl 831136849Sscottl pCmd->uCmd.R1Control.Buffer = buffer; 832136849Sscottl pCmd->pfnBuildSgl = R1ControlSgl; 833136849Sscottl } 834136849Sscottl else if (pArray->VDeviceType==VD_RAID_5) 835136849Sscottl { 836136849Sscottl switch(flags) 837136849Sscottl { 838136849Sscottl case DUPLICATE: 839136849Sscottl case REBUILD_PARITY: 840136849Sscottl pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; 841136849Sscottl case VERIFY: 842136849Sscottl pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; 843136849Sscottl case INITIALIZE: 844136849Sscottl pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; 845136849Sscottl } 846136849Sscottl pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; 847136849Sscottl } 848136849Sscottl else 849136849Sscottl HPT_ASSERT(0); 850136849Sscottl 851136849Sscottl pCmd->pVDevice = pArray; 852136849Sscottl pCmd->pfnCompletion = thread_io_done; 853136849Sscottl pArray->pfnSendCommand(_VBUS_P pCmd); 854136849Sscottl CheckPendingCall(_VBUS_P0); 855136849Sscottl 856136849Sscottl if (!End_Job) { 857136849Sscottl unlock_driver(oldspl); 858136849Sscottl while (!End_Job) { 859136849Sscottl tsleep((caddr_t)pCmd, PPAUSE, "pause", hz); 860136849Sscottl if (timeout++>60) break; 861136849Sscottl } 862136849Sscottl oldspl = lock_driver(); 863136849Sscottl if (!End_Job) { 864136849Sscottl hpt_printk(("timeout, reset\n")); 865136849Sscottl fResetVBus(_VBUS_P0); 866136849Sscottl } 867136849Sscottl } 868136849Sscottl 869136849Sscottl result = pCmd->Result; 870136849Sscottl FreeCommand(_VBUS_P pCmd); 871149871Sscottl unlock_driver(oldspl); 872149871Sscottl if (buffer) free(buffer, M_DEVBUF); 873149871Sscottl oldspl = lock_driver(); 874136849Sscottl KdPrintI(("cmd finished %d", result)); 875136849Sscottl 876136849Sscottl switch(result) 877136849Sscottl { 878136849Sscottl case RETURN_SUCCESS: 879136849Sscottl if (!pArray->u.array.rf_abort_rebuild) 880136849Sscottl { 881136849Sscottl if(pArray->u.array.RebuildSectors < capacity) 882136849Sscottl { 883136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); 884136849Sscottl } 885136849Sscottl else 886136849Sscottl { 887136849Sscottl switch (flags) 888136849Sscottl { 889136849Sscottl case DUPLICATE: 890136849Sscottl case REBUILD_PARITY: 891136849Sscottl needsync = 1; 892136849Sscottl pArray->u.array.rf_rebuilding = 0; 893136849Sscottl pArray->u.array.rf_need_rebuild = 0; 894136849Sscottl pArray->u.array.CriticalMembers = 0; 895136849Sscottl pArray->u.array.RebuildSectors = MAX_LBA_T; 896136849Sscottl pArray->u.array.rf_duplicate_and_create = 0; 897136849Sscottl hpt_printk(("Rebuilding finished.\n")); 898136849Sscottl ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); 899136849Sscottl break; 900136849Sscottl case INITIALIZE: 901136849Sscottl needsync = 1; 902136849Sscottl pArray->u.array.rf_initializing = 0; 903136849Sscottl pArray->u.array.rf_need_rebuild = 0; 904136849Sscottl pArray->u.array.RebuildSectors = MAX_LBA_T; 905136849Sscottl hpt_printk(("Initializing finished.\n")); 906136849Sscottl ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); 907136849Sscottl break; 908136849Sscottl case VERIFY: 909136849Sscottl pArray->u.array.rf_verifying = 0; 910136849Sscottl hpt_printk(("Verifying finished.\n")); 911136849Sscottl ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); 912136849Sscottl break; 913136849Sscottl } 914136849Sscottl } 915136849Sscottl } 916136849Sscottl else 917136849Sscottl { 918136849Sscottl pArray->u.array.rf_abort_rebuild = 0; 919136849Sscottl if (pArray->u.array.rf_rebuilding) 920136849Sscottl { 921136849Sscottl hpt_printk(("Abort rebuilding.\n")); 922136849Sscottl pArray->u.array.rf_rebuilding = 0; 923136849Sscottl pArray->u.array.rf_duplicate_and_create = 0; 924136849Sscottl ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); 925136849Sscottl } 926136849Sscottl else if (pArray->u.array.rf_verifying) 927136849Sscottl { 928136849Sscottl hpt_printk(("Abort verifying.\n")); 929136849Sscottl pArray->u.array.rf_verifying = 0; 930136849Sscottl ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); 931136849Sscottl } 932136849Sscottl else if (pArray->u.array.rf_initializing) 933136849Sscottl { 934136849Sscottl hpt_printk(("Abort initializing.\n")); 935136849Sscottl pArray->u.array.rf_initializing = 0; 936136849Sscottl ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); 937136849Sscottl } 938136849Sscottl needdelete=1; 939136849Sscottl } 940136849Sscottl break; 941136849Sscottl 942136849Sscottl case RETURN_DATA_ERROR: 943136849Sscottl if (flags==VERIFY) 944136849Sscottl { 945136849Sscottl needsync = 1; 946136849Sscottl pArray->u.array.rf_verifying = 0; 947136849Sscottl pArray->u.array.rf_need_rebuild = 1; 948136849Sscottl hpt_printk(("Verifying failed: found inconsistency\n")); 949136849Sscottl ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); 950136849Sscottl ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 951136849Sscottl 952136849Sscottl if (!pArray->vf_online || pArray->u.array.rf_broken) break; 953136849Sscottl 954136849Sscottl pArray->u.array.rf_auto_rebuild = 0; 955136849Sscottl pArray->u.array.rf_abort_rebuild = 0; 956136849Sscottl hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 957136849Sscottl (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); 958136849Sscottl } 959136849Sscottl break; 960136849Sscottl 961136849Sscottl default: 962136849Sscottl hpt_printk(("command failed with error %d\n", result)); 963136849Sscottl if (++retry<3) 964136849Sscottl { 965136849Sscottl hpt_printk(("retry (%d)\n", retry)); 966136849Sscottl goto retry_cmd; 967136849Sscottl } 968136849Sscottlfail: 969136849Sscottl pArray->u.array.rf_abort_rebuild = 0; 970136849Sscottl switch (flags) 971136849Sscottl { 972136849Sscottl case DUPLICATE: 973136849Sscottl case REBUILD_PARITY: 974136849Sscottl needsync = 1; 975136849Sscottl pArray->u.array.rf_rebuilding = 0; 976136849Sscottl pArray->u.array.rf_duplicate_and_create = 0; 977136849Sscottl hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); 978136849Sscottl ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); 979136849Sscottl break; 980136849Sscottl 981136849Sscottl case INITIALIZE: 982136849Sscottl needsync = 1; 983136849Sscottl pArray->u.array.rf_initializing = 0; 984136849Sscottl hpt_printk(("Initializing failed.\n")); 985136849Sscottl ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); 986136849Sscottl break; 987136849Sscottl 988136849Sscottl case VERIFY: 989136849Sscottl needsync = 1; 990136849Sscottl pArray->u.array.rf_verifying = 0; 991136849Sscottl hpt_printk(("Verifying failed.\n")); 992136849Sscottl ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 993136849Sscottl break; 994136849Sscottl } 995136849Sscottl needdelete=1; 996136849Sscottl } 997136849Sscottl 998136849Sscottl while (pAdapter->outstandingCommands) 999136849Sscottl { 1000136849Sscottl KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); 1001136849Sscottl /* put this to have driver stop processing system commands quickly */ 1002136849Sscottl if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 1003136849Sscottl unlock_driver(oldspl); 1004149871Sscottl /*Schedule out*/ 1005149871Sscottl#if (__FreeBSD_version < 500000) 1006149871Sscottl YIELD_THREAD; 1007149871Sscottl#else 1008190809Sdelphij#if (__FreeBSD_version > 700033) 1009167086Sjhb pause("switch", 1); 1010190809Sdelphij#else 1011190809Sdelphij tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1); 1012149871Sscottl#endif 1013190809Sdelphij#endif 1014136849Sscottl oldspl = lock_driver(); 1015136849Sscottl } 1016136849Sscottl 1017136849Sscottl if (needsync) SyncArrayInfo(pArray); 1018136849Sscottl if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) 1019136849Sscottl fDeleteArray(_VBUS_P pArray, TRUE); 1020136849Sscottl 1021136849Sscottl Check_Idle_Call(pAdapter); 1022136849Sscottl unlock_driver(oldspl); 1023136849Sscottl} 1024