2 * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * ioctl.c ioctl interface implementation
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
36 #if (__FreeBSD_version < 500000)
38 #include <sys/kthread.h>
40 #include <sys/sysproto.h>
47 #include <dev/hptmv/global.h>
48 #include <dev/hptmv/hptintf.h>
49 #include <dev/hptmv/osbsd.h>
50 #include <dev/hptmv/access601.h>
54 typedef struct _HPT_REBUILD_PARAM
59 } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
64 static HPT_EVENT hpt_event_queue[MAX_EVENTS];
65 static int event_queue_head=0, event_queue_tail=0;
67 static int hpt_get_event(PHPT_EVENT pEvent);
68 static int hpt_set_array_state(DEVICEID idArray, DWORD state);
69 static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter);
70 static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
71 static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
72 FPSCAT_GATH pSgTable, int logical);
75 get_disk_location(PDevice pDev, int *controller, int *channel)
77 IAL_ADAPTER_T *pAdapTemp;
80 *controller = *channel = 0;
82 for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
83 for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
84 if (pDev == &pAdapTemp->VDevices[j].u.disk) {
94 event_queue_add(PHPT_EVENT pEvent)
97 p = (event_queue_tail + 1) % MAX_EVENTS;
98 if (p==event_queue_head)
102 hpt_event_queue[event_queue_tail] = *pEvent;
103 event_queue_tail = p;
108 event_queue_remove(PHPT_EVENT pEvent)
110 if (event_queue_head != event_queue_tail)
112 *pEvent = hpt_event_queue[event_queue_head];
114 event_queue_head %= MAX_EVENTS;
121 ioctl_ReportEvent(UCHAR event, PVOID param)
124 ZeroMemory(&e, sizeof(e));
128 case ET_INITIALIZE_ABORTED:
129 case ET_INITIALIZE_FAILED:
130 memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
131 case ET_INITIALIZE_STARTED:
132 case ET_INITIALIZE_FINISHED:
134 case ET_REBUILD_STARTED:
135 case ET_REBUILD_ABORTED:
136 case ET_REBUILD_FAILED:
137 case ET_REBUILD_FINISHED:
139 case ET_VERIFY_STARTED:
140 case ET_VERIFY_ABORTED:
141 case ET_VERIFY_FAILED:
142 case ET_VERIFY_FINISHED:
143 case ET_VERIFY_DATA_ERROR:
145 case ET_SPARE_TOOK_OVER:
146 case ET_DEVICE_REMOVED:
147 case ET_DEVICE_PLUGGED:
148 case ET_DEVICE_ERROR:
149 e.DeviceID = VDEV_TO_ID((PVDevice)param);
156 if (event==ET_DEVICE_REMOVED) {
157 int controller, channel;
158 get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
159 hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
164 hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
166 PVDevice pArray = ID_TO_VDEV(id);
167 BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
171 if ((id==0) || check_VDevice_valid(pArray))
174 if(!mIsArray(pArray)) return -1;
176 if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
177 pArray->u.array.rf_initializing)
180 for(i=0; i<pArray->u.array.bArnMember; i++) {
181 pa = pArray->u.array.pMember[i];
182 if (pa && mIsArray(pa)) {
183 if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
184 pa->u.array.rf_initializing)
189 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
190 fDeleteArray(_VBUS_P pArray, del_block0);
195 /* just to prevent driver from sending more commands */
196 static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
199 lock_driver_idle(IAL_ADAPTER_T *pAdapter)
202 _VBUS_INST(&pAdapter->VBus)
203 oldspl = lock_driver();
204 while (pAdapter->outstandingCommands) {
205 KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
206 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
207 unlock_driver(oldspl);
209 #if (__FreeBSD_version < 500000)
212 #if (__FreeBSD_version > 700033)
215 tsleep(lock_driver_idle, PPAUSE, "switch", 1);
218 oldspl = lock_driver();
220 CheckIdleCall(_VBUS_P0);
224 int Kernel_DeviceIoControl(_VBUS_ARG
225 DWORD dwIoControlCode, /* operation control code */
226 PVOID lpInBuffer, /* input data buffer */
227 DWORD nInBufferSize, /* size of input data buffer */
228 PVOID lpOutBuffer, /* output data buffer */
229 DWORD nOutBufferSize, /* size of output data buffer */
230 PDWORD lpBytesReturned /* byte count */
233 IAL_ADAPTER_T *pAdapter;
235 switch(dwIoControlCode) {
236 case HPT_IOCTL_DELETE_ARRAY:
243 struct cam_periph *periph = NULL;
245 if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
246 if (nOutBufferSize!=sizeof(int)) return -1;
247 idArray = *(DEVICEID *)lpInBuffer;
249 pArray = ID_TO_VDEV(idArray);
251 if((idArray == 0) || check_VDevice_valid(pArray))
254 if(!mIsArray(pArray))
257 _vbus_p=pArray->pVBus;
258 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
260 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
261 if(pArray == _vbus_p->pVDevice[i])
263 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
264 if (periph != NULL && periph->refcount >= 1)
266 hpt_printk(("Can not delete a mounted device.\n"));
270 /* the Mounted Disk isn't delete */
273 iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
275 *(int*)lpOutBuffer = iSuccess;
282 case HPT_IOCTL_GET_EVENT:
286 if (nInBufferSize!=0) return -1;
287 if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
289 pInfo = (PHPT_EVENT)lpOutBuffer;
291 if (hpt_get_event(pInfo)!=0)
296 case HPT_IOCTL_SET_ARRAY_STATE:
301 if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
302 if (nOutBufferSize!=0) return -1;
304 idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
305 state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
307 if(hpt_set_array_state(idArray, state)!=0)
312 case HPT_IOCTL_RESCAN_DEVICES:
314 if (nInBufferSize!=0) return -1;
315 if (nOutBufferSize!=0) return -1;
318 /* stop buzzer if user perform rescan */
319 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
320 if (pAdapter->beeping) {
321 pAdapter->beeping = 0;
322 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
335 switch(dwIoControlCode) {
336 /* read-only ioctl functions can be called directly. */
337 case HPT_IOCTL_GET_VERSION:
338 case HPT_IOCTL_GET_CONTROLLER_IDS:
339 case HPT_IOCTL_GET_CONTROLLER_COUNT:
340 case HPT_IOCTL_GET_CONTROLLER_INFO:
341 case HPT_IOCTL_GET_CHANNEL_INFO:
342 case HPT_IOCTL_GET_LOGICAL_DEVICES:
343 case HPT_IOCTL_GET_DEVICE_INFO:
344 case HPT_IOCTL_GET_DEVICE_INFO_V2:
345 case HPT_IOCTL_GET_EVENT:
346 case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
347 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
348 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
353 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
354 * wrong for second controller.
356 switch(dwIoControlCode) {
357 case HPT_IOCTL_CREATE_ARRAY:
358 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
359 case HPT_IOCTL_CREATE_ARRAY_V2:
360 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
361 case HPT_IOCTL_SET_ARRAY_INFO:
362 pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
363 case HPT_IOCTL_SET_DEVICE_INFO:
364 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
365 case HPT_IOCTL_SET_DEVICE_INFO_V2:
366 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
367 case HPT_IOCTL_SET_BOOT_MARK:
368 case HPT_IOCTL_ADD_SPARE_DISK:
369 case HPT_IOCTL_REMOVE_SPARE_DISK:
370 pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
371 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
372 pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
377 if (pVDev && !check_VDevice_valid(pVDev)){
378 _vbus_p = pVDev->pVBus;
380 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
382 * create_array, and other functions can't be executed while channel is
383 * perform I/O commands. Wait until driver is idle.
385 oldspl = lock_driver_idle(pAdapter);
386 if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
387 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
388 unlock_driver(oldspl);
391 unlock_driver(oldspl);
399 switch(dwIoControlCode)
401 case HPT_IOCTL_CREATE_ARRAY:
403 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
404 oldspl = lock_driver();
405 if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
407 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
408 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
410 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
412 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
414 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
416 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
418 unlock_driver(oldspl);
423 case HPT_IOCTL_CREATE_ARRAY_V2:
425 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
426 oldspl = lock_driver();
427 if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
428 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
429 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
430 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
431 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
432 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
433 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
435 unlock_driver(oldspl);
438 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
440 PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
441 pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
442 if(pArray->u.array.rf_rebuilding == 0)
445 oldspl = lock_driver();
446 pArray->u.array.rf_auto_rebuild = 0;
447 pArray->u.array.rf_abort_rebuild = 0;
448 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
449 unlock_driver(oldspl);
450 while (!pArray->u.array.rf_rebuilding)
452 #if (__FreeBSD_version > 700033)
455 tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1);
457 if ( timeout >= hz*3)
471 *lpBytesReturned = nOutBufferSize;
476 hpt_get_event(PHPT_EVENT pEvent)
478 intrmask_t oldspl = lock_driver();
479 int ret = event_queue_remove(pEvent);
480 unlock_driver(oldspl);
485 hpt_set_array_state(DEVICEID idArray, DWORD state)
487 IAL_ADAPTER_T *pAdapter;
488 PVDevice pVDevice = ID_TO_VDEV(idArray);
493 if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
494 if(!mIsArray(pVDevice))
496 if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
498 pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
502 case MIRROR_REBUILD_START:
504 if (pVDevice->u.array.rf_rebuilding ||
505 pVDevice->u.array.rf_verifying ||
506 pVDevice->u.array.rf_initializing)
509 oldspl = lock_driver();
511 pVDevice->u.array.rf_auto_rebuild = 0;
512 pVDevice->u.array.rf_abort_rebuild = 0;
514 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
515 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
517 unlock_driver(oldspl);
519 while (!pVDevice->u.array.rf_rebuilding)
521 #if (__FreeBSD_version > 700033)
524 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
526 if ( timeout >= hz*20)
534 case MIRROR_REBUILD_ABORT:
536 for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
537 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
538 hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
541 if(pVDevice->u.array.rf_rebuilding != 1)
544 oldspl = lock_driver();
545 pVDevice->u.array.rf_abort_rebuild = 1;
546 unlock_driver(oldspl);
548 while (pVDevice->u.array.rf_abort_rebuild)
550 #if (__FreeBSD_version > 700033)
553 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
555 if ( timeout >= hz*20)
562 case AS_VERIFY_START:
564 /*if(pVDevice->u.array.rf_verifying)
566 if (pVDevice->u.array.rf_rebuilding ||
567 pVDevice->u.array.rf_verifying ||
568 pVDevice->u.array.rf_initializing)
571 oldspl = lock_driver();
572 pVDevice->u.array.RebuildSectors = 0;
573 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
574 unlock_driver(oldspl);
576 while (!pVDevice->u.array.rf_verifying)
578 #if (__FreeBSD_version > 700033)
581 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
583 if ( timeout >= hz*20)
590 case AS_VERIFY_ABORT:
592 if(pVDevice->u.array.rf_verifying != 1)
595 oldspl = lock_driver();
596 pVDevice->u.array.rf_abort_rebuild = 1;
597 unlock_driver(oldspl);
599 while (pVDevice->u.array.rf_abort_rebuild)
601 #if (__FreeBSD_version > 700033)
604 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
606 if ( timeout >= hz*80)
613 case AS_INITIALIZE_START:
615 if (pVDevice->u.array.rf_rebuilding ||
616 pVDevice->u.array.rf_verifying ||
617 pVDevice->u.array.rf_initializing)
620 oldspl = lock_driver();
621 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
622 unlock_driver(oldspl);
624 while (!pVDevice->u.array.rf_initializing)
626 #if (__FreeBSD_version > 700033)
629 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
631 if ( timeout >= hz*80)
638 case AS_INITIALIZE_ABORT:
640 if(pVDevice->u.array.rf_initializing != 1)
643 oldspl = lock_driver();
644 pVDevice->u.array.rf_abort_rebuild = 1;
645 unlock_driver(oldspl);
647 while (pVDevice->u.array.rf_abort_rebuild)
649 #if (__FreeBSD_version > 700033)
652 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
654 if ( timeout >= hz*80)
669 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
671 ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
672 if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
675 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
676 pSgTable->wSgSize = (USHORT)bufferSize;
677 pSgTable->wSgFlag = SG_FLAG_EOT;
680 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
681 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
685 v = pCmd->uCmd.R1Control.Buffer;
686 dataPointer = (ADDRESS)fOsPhysicalAddress(v);
688 if ((ULONG_PTR)dataPointer & 0x1)
691 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
692 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
695 if (idx >= MAX_SG_DESCRIPTORS) return FALSE;
697 pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
699 currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
703 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
704 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
706 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
707 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
709 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
710 nextvaddr = nextpage;
714 currvaddr = nextvaddr;
715 currphypage = nextphypage;
718 length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
720 bufferSize -= length;
722 pSgTable[idx].wSgSize = (USHORT)length;
723 pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
731 static int End_Job=0;
733 thread_io_done(_VBUS_ARG PCommand pCmd)
736 wakeup((caddr_t)pCmd);
740 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
743 ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
746 int needsync=0, retry=0, needdelete=0;
750 _VBUS_INST(&pAdapter->VBus)
752 if (pArray->u.array.rf_broken==1 ||
753 pArray->u.array.RebuildSectors>=capacity)
756 oldspl = lock_driver();
762 if(pArray->u.array.rf_rebuilding == 0)
764 pArray->u.array.rf_rebuilding = 1;
765 hpt_printk(("Rebuilding started.\n"));
766 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
771 if(pArray->u.array.rf_initializing == 0)
773 pArray->u.array.rf_initializing = 1;
774 hpt_printk(("Initializing started.\n"));
775 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
780 if(pArray->u.array.rf_verifying == 0)
782 pArray->u.array.rf_verifying = 1;
783 hpt_printk(("Verifying started.\n"));
784 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
790 pCmd = AllocateCommand(_VBUS_P0);
792 pCmd->cf_control = 1;
795 if (pArray->VDeviceType==VD_RAID_1)
797 #define MAX_REBUILD_SECTORS 0x40
799 /* take care for discontinuous buffer in R1ControlSgl */
800 unlock_driver(oldspl);
801 buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
802 oldspl = lock_driver();
804 FreeCommand(_VBUS_P pCmd);
805 hpt_printk(("can't allocate rebuild buffer\n"));
811 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
812 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
816 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
817 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
821 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
822 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
826 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
828 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
829 pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
831 pCmd->uCmd.R1Control.Buffer = buffer;
832 pCmd->pfnBuildSgl = R1ControlSgl;
834 else if (pArray->VDeviceType==VD_RAID_5)
840 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
842 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
844 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
846 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
851 pCmd->pVDevice = pArray;
852 pCmd->pfnCompletion = thread_io_done;
853 pArray->pfnSendCommand(_VBUS_P pCmd);
854 CheckPendingCall(_VBUS_P0);
857 unlock_driver(oldspl);
859 tsleep((caddr_t)pCmd, PPAUSE, "pause", hz);
860 if (timeout++>60) break;
862 oldspl = lock_driver();
864 hpt_printk(("timeout, reset\n"));
865 fResetVBus(_VBUS_P0);
869 result = pCmd->Result;
870 FreeCommand(_VBUS_P pCmd);
871 unlock_driver(oldspl);
872 if (buffer) free(buffer, M_DEVBUF);
873 oldspl = lock_driver();
874 KdPrintI(("cmd finished %d", result));
879 if (!pArray->u.array.rf_abort_rebuild)
881 if(pArray->u.array.RebuildSectors < capacity)
883 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
892 pArray->u.array.rf_rebuilding = 0;
893 pArray->u.array.rf_need_rebuild = 0;
894 pArray->u.array.CriticalMembers = 0;
895 pArray->u.array.RebuildSectors = MAX_LBA_T;
896 pArray->u.array.rf_duplicate_and_create = 0;
897 hpt_printk(("Rebuilding finished.\n"));
898 ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
902 pArray->u.array.rf_initializing = 0;
903 pArray->u.array.rf_need_rebuild = 0;
904 pArray->u.array.RebuildSectors = MAX_LBA_T;
905 hpt_printk(("Initializing finished.\n"));
906 ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
909 pArray->u.array.rf_verifying = 0;
910 hpt_printk(("Verifying finished.\n"));
911 ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
918 pArray->u.array.rf_abort_rebuild = 0;
919 if (pArray->u.array.rf_rebuilding)
921 hpt_printk(("Abort rebuilding.\n"));
922 pArray->u.array.rf_rebuilding = 0;
923 pArray->u.array.rf_duplicate_and_create = 0;
924 ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
926 else if (pArray->u.array.rf_verifying)
928 hpt_printk(("Abort verifying.\n"));
929 pArray->u.array.rf_verifying = 0;
930 ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
932 else if (pArray->u.array.rf_initializing)
934 hpt_printk(("Abort initializing.\n"));
935 pArray->u.array.rf_initializing = 0;
936 ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
942 case RETURN_DATA_ERROR:
946 pArray->u.array.rf_verifying = 0;
947 pArray->u.array.rf_need_rebuild = 1;
948 hpt_printk(("Verifying failed: found inconsistency\n"));
949 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
950 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
952 if (!pArray->vf_online || pArray->u.array.rf_broken) break;
954 pArray->u.array.rf_auto_rebuild = 0;
955 pArray->u.array.rf_abort_rebuild = 0;
956 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
957 (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
962 hpt_printk(("command failed with error %d\n", result));
965 hpt_printk(("retry (%d)\n", retry));
969 pArray->u.array.rf_abort_rebuild = 0;
975 pArray->u.array.rf_rebuilding = 0;
976 pArray->u.array.rf_duplicate_and_create = 0;
977 hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
978 ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
983 pArray->u.array.rf_initializing = 0;
984 hpt_printk(("Initializing failed.\n"));
985 ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
990 pArray->u.array.rf_verifying = 0;
991 hpt_printk(("Verifying failed.\n"));
992 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
998 while (pAdapter->outstandingCommands)
1000 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
1001 /* put this to have driver stop processing system commands quickly */
1002 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
1003 unlock_driver(oldspl);
1005 #if (__FreeBSD_version < 500000)
1008 #if (__FreeBSD_version > 700033)
1011 tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1);
1014 oldspl = lock_driver();
1017 if (needsync) SyncArrayInfo(pArray);
1018 if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
1019 fDeleteArray(_VBUS_P pArray, TRUE);
1021 Check_Idle_Call(pAdapter);
1022 unlock_driver(oldspl);