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
26 * $FreeBSD: src/sys/dev/hptmv/ioctl.c,v 1.9 2009/04/07 16:38:25 delphij Exp $
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>
40 #include <dev/raid/hptmv/global.h>
41 #include <dev/raid/hptmv/hptintf.h>
42 #include <dev/raid/hptmv/osbsd.h>
43 #include <dev/raid/hptmv/access601.h>
47 typedef struct _HPT_REBUILD_PARAM
52 } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
57 static HPT_EVENT hpt_event_queue[MAX_EVENTS];
58 static int event_queue_head=0, event_queue_tail=0;
60 static int hpt_get_event(PHPT_EVENT pEvent);
61 static int hpt_set_array_state(DEVICEID idArray, DWORD state);
62 static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter);
63 static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
64 static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
65 FPSCAT_GATH pSgTable, int logical);
68 get_disk_location(PDevice pDev, int *controller, int *channel)
70 IAL_ADAPTER_T *pAdapTemp;
73 *controller = *channel = 0;
75 for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
76 for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
77 if (pDev == &pAdapTemp->VDevices[j].u.disk) {
87 event_queue_add(PHPT_EVENT pEvent)
90 p = (event_queue_tail + 1) % MAX_EVENTS;
91 if (p==event_queue_head)
95 hpt_event_queue[event_queue_tail] = *pEvent;
101 event_queue_remove(PHPT_EVENT pEvent)
103 if (event_queue_head != event_queue_tail)
105 *pEvent = hpt_event_queue[event_queue_head];
107 event_queue_head %= MAX_EVENTS;
114 ioctl_ReportEvent(UCHAR event, PVOID param)
117 ZeroMemory(&e, sizeof(e));
121 case ET_INITIALIZE_ABORTED:
122 case ET_INITIALIZE_FAILED:
123 memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
124 case ET_INITIALIZE_STARTED:
125 case ET_INITIALIZE_FINISHED:
127 case ET_REBUILD_STARTED:
128 case ET_REBUILD_ABORTED:
129 case ET_REBUILD_FAILED:
130 case ET_REBUILD_FINISHED:
132 case ET_VERIFY_STARTED:
133 case ET_VERIFY_ABORTED:
134 case ET_VERIFY_FAILED:
135 case ET_VERIFY_FINISHED:
136 case ET_VERIFY_DATA_ERROR:
138 case ET_SPARE_TOOK_OVER:
139 case ET_DEVICE_REMOVED:
140 case ET_DEVICE_PLUGGED:
141 case ET_DEVICE_ERROR:
142 e.DeviceID = VDEV_TO_ID((PVDevice)param);
149 if (event==ET_DEVICE_REMOVED) {
150 int controller, channel;
151 get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
152 hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
157 hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
159 PVDevice pArray = ID_TO_VDEV(id);
160 BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
164 if ((id==0) || check_VDevice_valid(pArray))
167 if(!mIsArray(pArray)) return -1;
169 if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
170 pArray->u.array.rf_initializing)
173 for(i=0; i<pArray->u.array.bArnMember; i++) {
174 pa = pArray->u.array.pMember[i];
175 if (pa && mIsArray(pa)) {
176 if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
177 pa->u.array.rf_initializing)
182 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
183 fDeleteArray(_VBUS_P pArray, del_block0);
188 /* just to prevent driver from sending more commands */
189 static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
192 lock_driver_idle(IAL_ADAPTER_T *pAdapter)
195 _VBUS_INST(&pAdapter->VBus)
196 oldspl = lock_driver();
197 while (pAdapter->outstandingCommands) {
198 KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
199 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
200 unlock_driver(oldspl);
202 tsleep(lock_driver_idle, 0, "switch", 1);
203 oldspl = lock_driver();
205 CheckIdleCall(_VBUS_P0);
209 int Kernel_DeviceIoControl(_VBUS_ARG
210 DWORD dwIoControlCode, /* operation control code */
211 PVOID lpInBuffer, /* input data buffer */
212 DWORD nInBufferSize, /* size of input data buffer */
213 PVOID lpOutBuffer, /* output data buffer */
214 DWORD nOutBufferSize, /* size of output data buffer */
215 PDWORD lpBytesReturned /* byte count */
218 IAL_ADAPTER_T *pAdapter;
220 switch(dwIoControlCode) {
221 case HPT_IOCTL_DELETE_ARRAY:
228 struct cam_periph *periph = NULL;
230 if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
231 if (nOutBufferSize!=sizeof(int)) return -1;
232 idArray = *(DEVICEID *)lpInBuffer;
234 pArray = ID_TO_VDEV(idArray);
236 if((idArray == 0) || check_VDevice_valid(pArray))
239 if(!mIsArray(pArray))
242 _vbus_p=pArray->pVBus;
243 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
245 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
246 if(pArray == _vbus_p->pVDevice[i])
248 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
249 if (periph != NULL && periph->refcount >= 1)
251 hpt_printk(("Can not delete a mounted device.\n"));
255 /* the Mounted Disk isn't delete */
258 iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
260 *(int*)lpOutBuffer = iSuccess;
267 case HPT_IOCTL_GET_EVENT:
271 if (nInBufferSize!=0) return -1;
272 if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
274 pInfo = (PHPT_EVENT)lpOutBuffer;
276 if (hpt_get_event(pInfo)!=0)
281 case HPT_IOCTL_SET_ARRAY_STATE:
286 if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
287 if (nOutBufferSize!=0) return -1;
289 idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
290 state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
292 if(hpt_set_array_state(idArray, state)!=0)
297 case HPT_IOCTL_RESCAN_DEVICES:
299 if (nInBufferSize!=0) return -1;
300 if (nOutBufferSize!=0) return -1;
303 /* stop buzzer if user perform rescan */
304 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
305 if (pAdapter->beeping) {
306 pAdapter->beeping = 0;
307 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
320 switch(dwIoControlCode) {
321 /* read-only ioctl functions can be called directly. */
322 case HPT_IOCTL_GET_VERSION:
323 case HPT_IOCTL_GET_CONTROLLER_IDS:
324 case HPT_IOCTL_GET_CONTROLLER_COUNT:
325 case HPT_IOCTL_GET_CONTROLLER_INFO:
326 case HPT_IOCTL_GET_CHANNEL_INFO:
327 case HPT_IOCTL_GET_LOGICAL_DEVICES:
328 case HPT_IOCTL_GET_DEVICE_INFO:
329 case HPT_IOCTL_GET_DEVICE_INFO_V2:
330 case HPT_IOCTL_GET_EVENT:
331 case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
332 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
333 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
338 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
339 * wrong for second controller.
341 switch(dwIoControlCode) {
342 case HPT_IOCTL_CREATE_ARRAY:
343 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
344 case HPT_IOCTL_CREATE_ARRAY_V2:
345 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
346 case HPT_IOCTL_SET_ARRAY_INFO:
347 pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
348 case HPT_IOCTL_SET_DEVICE_INFO:
349 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
350 case HPT_IOCTL_SET_DEVICE_INFO_V2:
351 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
352 case HPT_IOCTL_SET_BOOT_MARK:
353 case HPT_IOCTL_ADD_SPARE_DISK:
354 case HPT_IOCTL_REMOVE_SPARE_DISK:
355 pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
356 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
357 pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
362 if (pVDev && !check_VDevice_valid(pVDev)){
363 _vbus_p = pVDev->pVBus;
365 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
367 * create_array, and other functions can't be executed while channel is
368 * perform I/O commands. Wait until driver is idle.
370 oldspl = lock_driver_idle(pAdapter);
371 if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
372 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
373 unlock_driver(oldspl);
376 unlock_driver(oldspl);
384 switch(dwIoControlCode)
386 case HPT_IOCTL_CREATE_ARRAY:
388 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
389 oldspl = lock_driver();
390 if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
392 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
393 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
395 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
397 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
399 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
401 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
403 unlock_driver(oldspl);
408 case HPT_IOCTL_CREATE_ARRAY_V2:
410 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
411 oldspl = lock_driver();
412 if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
413 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
414 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
415 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
416 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
417 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
418 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
420 unlock_driver(oldspl);
423 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
425 PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
426 pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
427 if(pArray->u.array.rf_rebuilding == 0)
430 oldspl = lock_driver();
431 pArray->u.array.rf_auto_rebuild = 0;
432 pArray->u.array.rf_abort_rebuild = 0;
433 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
434 unlock_driver(oldspl);
435 while (!pArray->u.array.rf_rebuilding)
437 tsleep((caddr_t)Kernel_DeviceIoControl, 0, "pause", 1);
438 if ( timeout >= hz*3)
452 *lpBytesReturned = nOutBufferSize;
457 hpt_get_event(PHPT_EVENT pEvent)
459 intrmask_t oldspl = lock_driver();
460 int ret = event_queue_remove(pEvent);
461 unlock_driver(oldspl);
466 hpt_set_array_state(DEVICEID idArray, DWORD state)
468 IAL_ADAPTER_T *pAdapter;
469 PVDevice pVDevice = ID_TO_VDEV(idArray);
474 if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
475 if(!mIsArray(pVDevice))
477 if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
479 pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
483 case MIRROR_REBUILD_START:
485 if (pVDevice->u.array.rf_rebuilding ||
486 pVDevice->u.array.rf_verifying ||
487 pVDevice->u.array.rf_initializing)
490 oldspl = lock_driver();
492 pVDevice->u.array.rf_auto_rebuild = 0;
493 pVDevice->u.array.rf_abort_rebuild = 0;
495 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
496 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
498 unlock_driver(oldspl);
500 while (!pVDevice->u.array.rf_rebuilding)
502 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
503 if ( timeout >= hz*20)
511 case MIRROR_REBUILD_ABORT:
513 for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
514 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
515 hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
518 if(pVDevice->u.array.rf_rebuilding != 1)
521 oldspl = lock_driver();
522 pVDevice->u.array.rf_abort_rebuild = 1;
523 unlock_driver(oldspl);
525 while (pVDevice->u.array.rf_abort_rebuild)
527 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
528 if ( timeout >= hz*20)
535 case AS_VERIFY_START:
537 /*if(pVDevice->u.array.rf_verifying)
539 if (pVDevice->u.array.rf_rebuilding ||
540 pVDevice->u.array.rf_verifying ||
541 pVDevice->u.array.rf_initializing)
544 oldspl = lock_driver();
545 pVDevice->u.array.RebuildSectors = 0;
546 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
547 unlock_driver(oldspl);
549 while (!pVDevice->u.array.rf_verifying)
551 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
552 if ( timeout >= hz*20)
559 case AS_VERIFY_ABORT:
561 if(pVDevice->u.array.rf_verifying != 1)
564 oldspl = lock_driver();
565 pVDevice->u.array.rf_abort_rebuild = 1;
566 unlock_driver(oldspl);
568 while (pVDevice->u.array.rf_abort_rebuild)
570 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
571 if ( timeout >= hz*80)
578 case AS_INITIALIZE_START:
580 if (pVDevice->u.array.rf_rebuilding ||
581 pVDevice->u.array.rf_verifying ||
582 pVDevice->u.array.rf_initializing)
585 oldspl = lock_driver();
586 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
587 unlock_driver(oldspl);
589 while (!pVDevice->u.array.rf_initializing)
591 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
592 if ( timeout >= hz*80)
599 case AS_INITIALIZE_ABORT:
601 if(pVDevice->u.array.rf_initializing != 1)
604 oldspl = lock_driver();
605 pVDevice->u.array.rf_abort_rebuild = 1;
606 unlock_driver(oldspl);
608 while (pVDevice->u.array.rf_abort_rebuild)
610 tsleep((caddr_t)hpt_set_array_state, 0, "pause", 1);
611 if ( timeout >= hz*80)
626 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
628 ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
629 if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
632 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
633 pSgTable->wSgSize = (USHORT)bufferSize;
634 pSgTable->wSgFlag = SG_FLAG_EOT;
637 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */
638 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
642 v = pCmd->uCmd.R1Control.Buffer;
643 dataPointer = (ADDRESS)fOsPhysicalAddress(v);
645 if ((ULONG_PTR)dataPointer & 0x1)
648 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
649 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
652 if (idx >= MAX_SG_DESCRIPTORS) return FALSE;
654 pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
656 currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
660 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
661 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
663 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
664 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
666 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
667 nextvaddr = nextpage;
671 currvaddr = nextvaddr;
672 currphypage = nextphypage;
675 length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
677 bufferSize -= length;
679 pSgTable[idx].wSgSize = (USHORT)length;
680 pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
688 static int End_Job=0;
690 thread_io_done(_VBUS_ARG PCommand pCmd)
693 wakeup((caddr_t)pCmd);
697 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
700 ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
703 int needsync=0, retry=0, needdelete=0;
707 _VBUS_INST(&pAdapter->VBus)
709 if (pArray->u.array.rf_broken==1 ||
710 pArray->u.array.RebuildSectors>=capacity)
713 oldspl = lock_driver();
719 if(pArray->u.array.rf_rebuilding == 0)
721 pArray->u.array.rf_rebuilding = 1;
722 hpt_printk(("Rebuilding started.\n"));
723 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
728 if(pArray->u.array.rf_initializing == 0)
730 pArray->u.array.rf_initializing = 1;
731 hpt_printk(("Initializing started.\n"));
732 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
737 if(pArray->u.array.rf_verifying == 0)
739 pArray->u.array.rf_verifying = 1;
740 hpt_printk(("Verifying started.\n"));
741 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
747 pCmd = AllocateCommand(_VBUS_P0);
749 pCmd->cf_control = 1;
752 if (pArray->VDeviceType==VD_RAID_1)
754 #define MAX_REBUILD_SECTORS 0x40
756 /* take care for discontinuous buffer in R1ControlSgl */
757 unlock_driver(oldspl);
758 buffer = kmalloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
759 oldspl = lock_driver();
761 FreeCommand(_VBUS_P pCmd);
762 hpt_printk(("can't allocate rebuild buffer\n"));
768 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
769 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
773 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
774 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
778 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
779 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
783 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
785 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
786 pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
788 pCmd->uCmd.R1Control.Buffer = buffer;
789 pCmd->pfnBuildSgl = R1ControlSgl;
791 else if (pArray->VDeviceType==VD_RAID_5)
797 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
799 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
801 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
803 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
808 pCmd->pVDevice = pArray;
809 pCmd->pfnCompletion = thread_io_done;
810 pArray->pfnSendCommand(_VBUS_P pCmd);
811 CheckPendingCall(_VBUS_P0);
814 unlock_driver(oldspl);
816 tsleep((caddr_t)pCmd, 0, "pause", hz);
817 if (timeout++>60) break;
819 oldspl = lock_driver();
821 hpt_printk(("timeout, reset\n"));
822 fResetVBus(_VBUS_P0);
826 result = pCmd->Result;
827 FreeCommand(_VBUS_P pCmd);
828 unlock_driver(oldspl);
829 if (buffer) kfree(buffer, M_DEVBUF);
830 oldspl = lock_driver();
831 KdPrintI(("cmd finished %d", result));
836 if (!pArray->u.array.rf_abort_rebuild)
838 if(pArray->u.array.RebuildSectors < capacity)
840 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
849 pArray->u.array.rf_rebuilding = 0;
850 pArray->u.array.rf_need_rebuild = 0;
851 pArray->u.array.CriticalMembers = 0;
852 pArray->u.array.RebuildSectors = MAX_LBA_T;
853 pArray->u.array.rf_duplicate_and_create = 0;
854 hpt_printk(("Rebuilding finished.\n"));
855 ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
859 pArray->u.array.rf_initializing = 0;
860 pArray->u.array.rf_need_rebuild = 0;
861 pArray->u.array.RebuildSectors = MAX_LBA_T;
862 hpt_printk(("Initializing finished.\n"));
863 ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
866 pArray->u.array.rf_verifying = 0;
867 hpt_printk(("Verifying finished.\n"));
868 ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
875 pArray->u.array.rf_abort_rebuild = 0;
876 if (pArray->u.array.rf_rebuilding)
878 hpt_printk(("Abort rebuilding.\n"));
879 pArray->u.array.rf_rebuilding = 0;
880 pArray->u.array.rf_duplicate_and_create = 0;
881 ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
883 else if (pArray->u.array.rf_verifying)
885 hpt_printk(("Abort verifying.\n"));
886 pArray->u.array.rf_verifying = 0;
887 ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
889 else if (pArray->u.array.rf_initializing)
891 hpt_printk(("Abort initializing.\n"));
892 pArray->u.array.rf_initializing = 0;
893 ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
899 case RETURN_DATA_ERROR:
903 pArray->u.array.rf_verifying = 0;
904 pArray->u.array.rf_need_rebuild = 1;
905 hpt_printk(("Verifying failed: found inconsistency\n"));
906 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
907 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
909 if (!pArray->vf_online || pArray->u.array.rf_broken) break;
911 pArray->u.array.rf_auto_rebuild = 0;
912 pArray->u.array.rf_abort_rebuild = 0;
913 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
914 (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
919 hpt_printk(("command failed with error %d\n", result));
922 hpt_printk(("retry (%d)\n", retry));
926 pArray->u.array.rf_abort_rebuild = 0;
932 pArray->u.array.rf_rebuilding = 0;
933 pArray->u.array.rf_duplicate_and_create = 0;
934 hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
935 ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
940 pArray->u.array.rf_initializing = 0;
941 hpt_printk(("Initializing failed.\n"));
942 ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
947 pArray->u.array.rf_verifying = 0;
948 hpt_printk(("Verifying failed.\n"));
949 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
955 while (pAdapter->outstandingCommands)
957 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
958 /* put this to have driver stop processing system commands quickly */
959 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
960 unlock_driver(oldspl);
962 tsleep(hpt_rebuild_data_block, 0, "switch", 1);
963 oldspl = lock_driver();
966 if (needsync) SyncArrayInfo(pArray);
967 if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
968 fDeleteArray(_VBUS_P pArray, TRUE);
970 Check_Idle_Call(pAdapter);
971 unlock_driver(oldspl);