2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * ioctl.c ioctl interface implementation
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
42 #include <dev/hptmv/global.h>
43 #include <dev/hptmv/hptintf.h>
44 #include <dev/hptmv/osbsd.h>
45 #include <dev/hptmv/access601.h>
49 typedef struct _HPT_REBUILD_PARAM
54 } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
59 static HPT_EVENT hpt_event_queue[MAX_EVENTS];
60 static int event_queue_head=0, event_queue_tail=0;
62 static int hpt_get_event(PHPT_EVENT pEvent);
63 static int hpt_set_array_state(DEVICEID idArray, DWORD state);
64 static void lock_driver_idle(IAL_ADAPTER_T *pAdapter);
65 static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
66 static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
67 FPSCAT_GATH pSgTable, int logical);
70 get_disk_location(PDevice pDev, int *controller, int *channel)
72 IAL_ADAPTER_T *pAdapTemp;
75 *controller = *channel = 0;
77 for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
78 for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
79 if (pDev == &pAdapTemp->VDevices[j].u.disk) {
89 event_queue_add(PHPT_EVENT pEvent)
92 p = (event_queue_tail + 1) % MAX_EVENTS;
93 if (p==event_queue_head)
97 hpt_event_queue[event_queue_tail] = *pEvent;
103 event_queue_remove(PHPT_EVENT pEvent)
105 if (event_queue_head != event_queue_tail)
107 *pEvent = hpt_event_queue[event_queue_head];
109 event_queue_head %= MAX_EVENTS;
116 ioctl_ReportEvent(UCHAR event, PVOID param)
119 ZeroMemory(&e, sizeof(e));
123 case ET_INITIALIZE_ABORTED:
124 case ET_INITIALIZE_FAILED:
125 memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
126 case ET_INITIALIZE_STARTED:
127 case ET_INITIALIZE_FINISHED:
129 case ET_REBUILD_STARTED:
130 case ET_REBUILD_ABORTED:
131 case ET_REBUILD_FAILED:
132 case ET_REBUILD_FINISHED:
134 case ET_VERIFY_STARTED:
135 case ET_VERIFY_ABORTED:
136 case ET_VERIFY_FAILED:
137 case ET_VERIFY_FINISHED:
138 case ET_VERIFY_DATA_ERROR:
140 case ET_SPARE_TOOK_OVER:
141 case ET_DEVICE_REMOVED:
142 case ET_DEVICE_PLUGGED:
143 case ET_DEVICE_ERROR:
144 e.DeviceID = VDEV_TO_ID((PVDevice)param);
151 if (event==ET_DEVICE_REMOVED) {
152 int controller, channel;
153 get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
154 hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
160 hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
162 PVDevice pArray = ID_TO_VDEV(id);
163 BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
167 if ((id==0) || check_VDevice_valid(pArray))
170 if(!mIsArray(pArray)) return -1;
172 if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
173 pArray->u.array.rf_initializing)
176 for(i=0; i<pArray->u.array.bArnMember; i++) {
177 pa = pArray->u.array.pMember[i];
178 if (pa && mIsArray(pa)) {
179 if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
180 pa->u.array.rf_initializing)
185 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
186 fDeleteArray(_VBUS_P pArray, del_block0);
191 /* just to prevent driver from sending more commands */
192 static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
195 lock_driver_idle(IAL_ADAPTER_T *pAdapter)
197 _VBUS_INST(&pAdapter->VBus)
198 mtx_lock(&pAdapter->lock);
199 while (pAdapter->outstandingCommands) {
200 KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
201 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
202 mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
204 CheckIdleCall(_VBUS_P0);
207 int Kernel_DeviceIoControl(_VBUS_ARG
208 DWORD dwIoControlCode, /* operation control code */
209 PVOID lpInBuffer, /* input data buffer */
210 DWORD nInBufferSize, /* size of input data buffer */
211 PVOID lpOutBuffer, /* output data buffer */
212 DWORD nOutBufferSize, /* size of output data buffer */
213 PDWORD lpBytesReturned /* byte count */
216 IAL_ADAPTER_T *pAdapter;
218 switch(dwIoControlCode) {
219 case HPT_IOCTL_DELETE_ARRAY:
226 struct cam_periph *periph = NULL;
228 if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
229 if (nOutBufferSize!=sizeof(int)) return -1;
230 idArray = *(DEVICEID *)lpInBuffer;
232 pArray = ID_TO_VDEV(idArray);
234 if((idArray == 0) || check_VDevice_valid(pArray))
237 if(!mIsArray(pArray))
240 _vbus_p=pArray->pVBus;
241 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
243 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
244 if(pArray == _vbus_p->pVDevice[i])
246 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
247 if (periph != NULL && periph->refcount >= 1)
249 hpt_printk(("Can not delete a mounted device.\n"));
253 /* the Mounted Disk isn't delete */
256 iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
258 *(int*)lpOutBuffer = iSuccess;
265 case HPT_IOCTL_GET_EVENT:
269 if (nInBufferSize!=0) return -1;
270 if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
272 pInfo = (PHPT_EVENT)lpOutBuffer;
274 if (hpt_get_event(pInfo)!=0)
279 case HPT_IOCTL_SET_ARRAY_STATE:
284 if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
285 if (nOutBufferSize!=0) return -1;
287 idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
288 state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
290 if(hpt_set_array_state(idArray, state)!=0)
295 case HPT_IOCTL_RESCAN_DEVICES:
297 if (nInBufferSize!=0) return -1;
298 if (nOutBufferSize!=0) return -1;
301 /* stop buzzer if user perform rescan */
302 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
303 if (pAdapter->beeping) {
304 pAdapter->beeping = 0;
305 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
316 switch(dwIoControlCode) {
317 /* read-only ioctl functions can be called directly. */
318 case HPT_IOCTL_GET_VERSION:
319 case HPT_IOCTL_GET_CONTROLLER_IDS:
320 case HPT_IOCTL_GET_CONTROLLER_COUNT:
321 case HPT_IOCTL_GET_CONTROLLER_INFO:
322 case HPT_IOCTL_GET_CHANNEL_INFO:
323 case HPT_IOCTL_GET_LOGICAL_DEVICES:
324 case HPT_IOCTL_GET_DEVICE_INFO:
325 case HPT_IOCTL_GET_DEVICE_INFO_V2:
326 case HPT_IOCTL_GET_EVENT:
327 case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
328 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
329 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
334 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
335 * wrong for second controller.
337 switch(dwIoControlCode) {
338 case HPT_IOCTL_CREATE_ARRAY:
339 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
340 case HPT_IOCTL_CREATE_ARRAY_V2:
341 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
342 case HPT_IOCTL_SET_ARRAY_INFO:
343 pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
344 case HPT_IOCTL_SET_DEVICE_INFO:
345 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
346 case HPT_IOCTL_SET_DEVICE_INFO_V2:
347 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
348 case HPT_IOCTL_SET_BOOT_MARK:
349 case HPT_IOCTL_ADD_SPARE_DISK:
350 case HPT_IOCTL_REMOVE_SPARE_DISK:
351 pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
352 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
353 pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
358 if (pVDev && !check_VDevice_valid(pVDev)){
359 _vbus_p = pVDev->pVBus;
361 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
363 * create_array, and other functions can't be executed while channel is
364 * perform I/O commands. Wait until driver is idle.
366 lock_driver_idle(pAdapter);
367 if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
368 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
369 mtx_unlock(&pAdapter->lock);
372 mtx_unlock(&pAdapter->lock);
380 switch(dwIoControlCode)
382 case HPT_IOCTL_CREATE_ARRAY:
384 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
385 mtx_lock(&pAdapter->lock);
386 if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
388 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
389 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
391 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
393 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
395 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
397 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
399 mtx_unlock(&pAdapter->lock);
404 case HPT_IOCTL_CREATE_ARRAY_V2:
406 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
407 mtx_lock(&pAdapter->lock);
408 if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
409 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
410 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
411 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
412 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
413 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
414 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
416 mtx_unlock(&pAdapter->lock);
419 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
421 PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
422 pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
423 if(pArray->u.array.rf_rebuilding == 0)
425 mtx_lock(&pAdapter->lock);
426 pArray->u.array.rf_auto_rebuild = 0;
427 pArray->u.array.rf_abort_rebuild = 0;
428 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
429 while (!pArray->u.array.rf_rebuilding)
431 if (mtx_sleep(pArray, &pAdapter->lock, 0, "hptwait", hz * 3) != 0)
434 mtx_unlock(&pAdapter->lock);
445 *lpBytesReturned = nOutBufferSize;
450 hpt_get_event(PHPT_EVENT pEvent)
452 int ret = event_queue_remove(pEvent);
457 hpt_set_array_state(DEVICEID idArray, DWORD state)
459 IAL_ADAPTER_T *pAdapter;
460 PVDevice pVDevice = ID_TO_VDEV(idArray);
463 if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
464 if(!mIsArray(pVDevice))
466 if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
468 pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
472 case MIRROR_REBUILD_START:
474 mtx_lock(&pAdapter->lock);
475 if (pVDevice->u.array.rf_rebuilding ||
476 pVDevice->u.array.rf_verifying ||
477 pVDevice->u.array.rf_initializing) {
478 mtx_unlock(&pAdapter->lock);
482 pVDevice->u.array.rf_auto_rebuild = 0;
483 pVDevice->u.array.rf_abort_rebuild = 0;
485 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
486 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
488 while (!pVDevice->u.array.rf_rebuilding)
490 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
491 "hptwait", hz * 20) != 0)
494 mtx_unlock(&pAdapter->lock);
499 case MIRROR_REBUILD_ABORT:
501 for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
502 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
503 hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
506 mtx_lock(&pAdapter->lock);
507 if(pVDevice->u.array.rf_rebuilding != 1) {
508 mtx_unlock(&pAdapter->lock);
512 pVDevice->u.array.rf_abort_rebuild = 1;
514 while (pVDevice->u.array.rf_abort_rebuild)
516 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
517 "hptabrt", hz * 20) != 0)
520 mtx_unlock(&pAdapter->lock);
524 case AS_VERIFY_START:
526 /*if(pVDevice->u.array.rf_verifying)
528 mtx_lock(&pAdapter->lock);
529 if (pVDevice->u.array.rf_rebuilding ||
530 pVDevice->u.array.rf_verifying ||
531 pVDevice->u.array.rf_initializing) {
532 mtx_unlock(&pAdapter->lock);
536 pVDevice->u.array.RebuildSectors = 0;
537 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
539 while (!pVDevice->u.array.rf_verifying)
541 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
542 "hptvrfy", hz * 20) != 0)
545 mtx_unlock(&pAdapter->lock);
549 case AS_VERIFY_ABORT:
551 mtx_lock(&pAdapter->lock);
552 if(pVDevice->u.array.rf_verifying != 1) {
553 mtx_unlock(&pAdapter->lock);
557 pVDevice->u.array.rf_abort_rebuild = 1;
559 while (pVDevice->u.array.rf_abort_rebuild)
561 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
562 "hptvrfy", hz * 80) != 0)
565 mtx_unlock(&pAdapter->lock);
569 case AS_INITIALIZE_START:
571 mtx_lock(&pAdapter->lock);
572 if (pVDevice->u.array.rf_rebuilding ||
573 pVDevice->u.array.rf_verifying ||
574 pVDevice->u.array.rf_initializing) {
575 mtx_unlock(&pAdapter->lock);
579 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
581 while (!pVDevice->u.array.rf_initializing)
583 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
584 "hptinit", hz * 80) != 0)
587 mtx_unlock(&pAdapter->lock);
591 case AS_INITIALIZE_ABORT:
593 mtx_lock(&pAdapter->lock);
594 if(pVDevice->u.array.rf_initializing != 1) {
595 mtx_unlock(&pAdapter->lock);
599 pVDevice->u.array.rf_abort_rebuild = 1;
601 while (pVDevice->u.array.rf_abort_rebuild)
603 if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
604 "hptinit", hz * 80) != 0)
607 mtx_unlock(&pAdapter->lock);
619 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
621 ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
622 if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
625 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
626 pSgTable->wSgSize = (USHORT)bufferSize;
627 pSgTable->wSgFlag = SG_FLAG_EOT;
630 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
631 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
635 v = pCmd->uCmd.R1Control.Buffer;
636 dataPointer = (ADDRESS)fOsPhysicalAddress(v);
638 if ((ULONG_PTR)dataPointer & 0x1)
641 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
642 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
645 if (idx >= MAX_SG_DESCRIPTORS) return FALSE;
647 pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
649 currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
653 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
654 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
656 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
657 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
659 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
660 nextvaddr = nextpage;
664 currvaddr = nextvaddr;
665 currphypage = nextphypage;
668 length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
670 bufferSize -= length;
672 pSgTable[idx].wSgSize = (USHORT)length;
673 pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
681 static int End_Job=0;
683 thread_io_done(_VBUS_ARG PCommand pCmd)
686 wakeup((caddr_t)pCmd);
690 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
692 ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
695 int needsync=0, retry=0, needdelete=0;
698 _VBUS_INST(&pAdapter->VBus)
700 if (pArray->u.array.rf_broken==1 ||
701 pArray->u.array.RebuildSectors>=capacity)
704 mtx_lock(&pAdapter->lock);
710 if(pArray->u.array.rf_rebuilding == 0)
712 pArray->u.array.rf_rebuilding = 1;
713 hpt_printk(("Rebuilding started.\n"));
714 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
719 if(pArray->u.array.rf_initializing == 0)
721 pArray->u.array.rf_initializing = 1;
722 hpt_printk(("Initializing started.\n"));
723 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
728 if(pArray->u.array.rf_verifying == 0)
730 pArray->u.array.rf_verifying = 1;
731 hpt_printk(("Verifying started.\n"));
732 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
738 pCmd = AllocateCommand(_VBUS_P0);
740 pCmd->cf_control = 1;
743 if (pArray->VDeviceType==VD_RAID_1)
745 #define MAX_REBUILD_SECTORS 0x40
747 /* take care for discontinuous buffer in R1ControlSgl */
748 buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
750 FreeCommand(_VBUS_P pCmd);
751 hpt_printk(("can't allocate rebuild buffer\n"));
757 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
758 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
762 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
763 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
767 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
768 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
772 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
774 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
775 pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
777 pCmd->uCmd.R1Control.Buffer = buffer;
778 pCmd->pfnBuildSgl = R1ControlSgl;
780 else if (pArray->VDeviceType==VD_RAID_5)
786 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
788 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
790 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
792 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
797 pCmd->pVDevice = pArray;
798 pCmd->pfnCompletion = thread_io_done;
799 pArray->pfnSendCommand(_VBUS_P pCmd);
800 CheckPendingCall(_VBUS_P0);
803 mtx_sleep(pCmd, &pAdapter->lock, 0, "hptrbld", hz * 60);
805 hpt_printk(("timeout, reset\n"));
806 fResetVBus(_VBUS_P0);
810 result = pCmd->Result;
811 FreeCommand(_VBUS_P pCmd);
812 if (buffer) free(buffer, M_DEVBUF);
813 KdPrintI(("cmd finished %d", result));
818 if (!pArray->u.array.rf_abort_rebuild)
820 if(pArray->u.array.RebuildSectors < capacity)
822 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
831 pArray->u.array.rf_rebuilding = 0;
832 pArray->u.array.rf_need_rebuild = 0;
833 pArray->u.array.CriticalMembers = 0;
834 pArray->u.array.RebuildSectors = MAX_LBA_T;
835 pArray->u.array.rf_duplicate_and_create = 0;
836 hpt_printk(("Rebuilding finished.\n"));
837 ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
841 pArray->u.array.rf_initializing = 0;
842 pArray->u.array.rf_need_rebuild = 0;
843 pArray->u.array.RebuildSectors = MAX_LBA_T;
844 hpt_printk(("Initializing finished.\n"));
845 ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
848 pArray->u.array.rf_verifying = 0;
849 hpt_printk(("Verifying finished.\n"));
850 ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
857 pArray->u.array.rf_abort_rebuild = 0;
858 if (pArray->u.array.rf_rebuilding)
860 hpt_printk(("Abort rebuilding.\n"));
861 pArray->u.array.rf_rebuilding = 0;
862 pArray->u.array.rf_duplicate_and_create = 0;
863 ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
865 else if (pArray->u.array.rf_verifying)
867 hpt_printk(("Abort verifying.\n"));
868 pArray->u.array.rf_verifying = 0;
869 ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
871 else if (pArray->u.array.rf_initializing)
873 hpt_printk(("Abort initializing.\n"));
874 pArray->u.array.rf_initializing = 0;
875 ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
881 case RETURN_DATA_ERROR:
885 pArray->u.array.rf_verifying = 0;
886 pArray->u.array.rf_need_rebuild = 1;
887 hpt_printk(("Verifying failed: found inconsistency\n"));
888 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
889 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
891 if (!pArray->vf_online || pArray->u.array.rf_broken) break;
893 pArray->u.array.rf_auto_rebuild = 0;
894 pArray->u.array.rf_abort_rebuild = 0;
895 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
896 (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
901 hpt_printk(("command failed with error %d\n", result));
904 hpt_printk(("retry (%d)\n", retry));
908 pArray->u.array.rf_abort_rebuild = 0;
914 pArray->u.array.rf_rebuilding = 0;
915 pArray->u.array.rf_duplicate_and_create = 0;
916 hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
917 ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
922 pArray->u.array.rf_initializing = 0;
923 hpt_printk(("Initializing failed.\n"));
924 ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
929 pArray->u.array.rf_verifying = 0;
930 hpt_printk(("Verifying failed.\n"));
931 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
937 while (pAdapter->outstandingCommands)
939 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
940 /* put this to have driver stop processing system commands quickly */
941 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
942 mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
945 if (needsync) SyncArrayInfo(pArray);
946 if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
947 fDeleteArray(_VBUS_P pArray, TRUE);
949 Check_Idle_Call(pAdapter);
950 mtx_unlock(&pAdapter->lock);