xref: /freebsd/sys/dev/hptmv/ioctl.c (revision 95ee2897)
1718cf2ccSPedro F. Giffuni /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4d2bd3ab9SScott Long  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
51713e81bSScott Long  * All rights reserved.
61713e81bSScott Long  *
71713e81bSScott Long  * Redistribution and use in source and binary forms, with or without
81713e81bSScott Long  * modification, are permitted provided that the following conditions
91713e81bSScott Long  * are met:
101713e81bSScott Long  * 1. Redistributions of source code must retain the above copyright
111713e81bSScott Long  *    notice, this list of conditions and the following disclaimer.
121713e81bSScott Long  * 2. Redistributions in binary form must reproduce the above copyright
131713e81bSScott Long  *    notice, this list of conditions and the following disclaimer in the
141713e81bSScott Long  *    documentation and/or other materials provided with the distribution.
151713e81bSScott Long  *
161713e81bSScott Long  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171713e81bSScott Long  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181713e81bSScott Long  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191713e81bSScott Long  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201713e81bSScott Long  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211713e81bSScott Long  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221713e81bSScott Long  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231713e81bSScott Long  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241713e81bSScott Long  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251713e81bSScott Long  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261713e81bSScott Long  * SUCH DAMAGE.
271713e81bSScott Long  */
281713e81bSScott Long /*
291713e81bSScott Long  * ioctl.c   ioctl interface implementation
301713e81bSScott Long  */
311713e81bSScott Long #include <sys/param.h>
321713e81bSScott Long #include <sys/systm.h>
331713e81bSScott Long #include <sys/kernel.h>
341713e81bSScott Long #include <sys/malloc.h>
351713e81bSScott Long 
36d2bd3ab9SScott Long #ifndef __KERNEL__
37d2bd3ab9SScott Long #define __KERNEL__
38d2bd3ab9SScott Long #endif
39d2bd3ab9SScott Long 
401713e81bSScott Long #include <dev/hptmv/global.h>
411713e81bSScott Long #include <dev/hptmv/hptintf.h>
421713e81bSScott Long #include <dev/hptmv/osbsd.h>
43f7f3900bSScott Long #include <dev/hptmv/access601.h>
441713e81bSScott Long 
451713e81bSScott Long #pragma pack(1)
461713e81bSScott Long 
471713e81bSScott Long typedef struct _HPT_REBUILD_PARAM
481713e81bSScott Long {
491713e81bSScott Long 	DEVICEID idMirror;
501713e81bSScott Long 	DWORD Lba;
511713e81bSScott Long 	UCHAR nSector;
521713e81bSScott Long } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
531713e81bSScott Long 
541713e81bSScott Long #pragma pack()
551713e81bSScott Long 
561713e81bSScott Long #define MAX_EVENTS 10
571713e81bSScott Long static HPT_EVENT hpt_event_queue[MAX_EVENTS];
581713e81bSScott Long static int event_queue_head=0, event_queue_tail=0;
591713e81bSScott Long 
601713e81bSScott Long static int hpt_get_event(PHPT_EVENT pEvent);
611713e81bSScott Long static int hpt_set_array_state(DEVICEID idArray, DWORD state);
6249b3fc40SJohn Baldwin static void lock_driver_idle(IAL_ADAPTER_T *pAdapter);
631713e81bSScott Long static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
641713e81bSScott Long static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
651713e81bSScott Long     FPSCAT_GATH pSgTable, int logical);
661713e81bSScott Long 
67d2bd3ab9SScott Long static void
get_disk_location(PDevice pDev,int * controller,int * channel)68d2bd3ab9SScott Long get_disk_location(PDevice pDev, int *controller, int *channel)
691713e81bSScott Long {
701713e81bSScott Long 	IAL_ADAPTER_T *pAdapTemp;
711713e81bSScott Long 	int i, j;
721713e81bSScott Long 
73b8fdb7f9SMatt Jacob 	*controller = *channel = 0;
74b8fdb7f9SMatt Jacob 
751713e81bSScott Long 	for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
76b8fdb7f9SMatt Jacob 		for (j=0; j<MV_SATA_CHANNELS_NUM; j++) {
771713e81bSScott Long 			if (pDev == &pAdapTemp->VDevices[j].u.disk) {
781713e81bSScott Long 				*controller = i;
791713e81bSScott Long 				*channel = j;
801713e81bSScott Long 				return;
811713e81bSScott Long 			}
821713e81bSScott Long 		}
831713e81bSScott Long 	}
84b8fdb7f9SMatt Jacob }
851713e81bSScott Long 
86d2bd3ab9SScott Long static int
event_queue_add(PHPT_EVENT pEvent)87d2bd3ab9SScott Long event_queue_add(PHPT_EVENT pEvent)
881713e81bSScott Long {
891713e81bSScott Long 	int p;
901713e81bSScott Long 	p = (event_queue_tail + 1) % MAX_EVENTS;
911713e81bSScott Long 	if (p==event_queue_head)
921713e81bSScott Long 	{
931713e81bSScott Long 		return -1;
941713e81bSScott Long 	}
951713e81bSScott Long 	hpt_event_queue[event_queue_tail] = *pEvent;
961713e81bSScott Long 	event_queue_tail = p;
971713e81bSScott Long 	return 0;
981713e81bSScott Long }
991713e81bSScott Long 
100d2bd3ab9SScott Long static int
event_queue_remove(PHPT_EVENT pEvent)101d2bd3ab9SScott Long event_queue_remove(PHPT_EVENT pEvent)
1021713e81bSScott Long {
1031713e81bSScott Long 	if (event_queue_head != event_queue_tail)
1041713e81bSScott Long 	{
1051713e81bSScott Long 		*pEvent = hpt_event_queue[event_queue_head];
1061713e81bSScott Long 		event_queue_head++;
1071713e81bSScott Long 		event_queue_head %= MAX_EVENTS;
1081713e81bSScott Long 		return 0;
1091713e81bSScott Long 	}
1101713e81bSScott Long 	return -1;
1111713e81bSScott Long }
1121713e81bSScott Long 
113d2bd3ab9SScott Long void HPTLIBAPI
ioctl_ReportEvent(UCHAR event,PVOID param)114d2bd3ab9SScott Long ioctl_ReportEvent(UCHAR event, PVOID param)
1151713e81bSScott Long {
1161713e81bSScott Long 	HPT_EVENT e;
1171713e81bSScott Long 	ZeroMemory(&e, sizeof(e));
1181713e81bSScott Long 	e.EventType = event;
1191713e81bSScott Long 	switch(event)
1201713e81bSScott Long 	{
1211713e81bSScott Long 		case ET_INITIALIZE_ABORTED:
1221713e81bSScott Long 		case ET_INITIALIZE_FAILED:
1231713e81bSScott Long 			memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
1241713e81bSScott Long 		case ET_INITIALIZE_STARTED:
1251713e81bSScott Long 		case ET_INITIALIZE_FINISHED:
1261713e81bSScott Long 
1271713e81bSScott Long 		case ET_REBUILD_STARTED:
1281713e81bSScott Long 		case ET_REBUILD_ABORTED:
1291713e81bSScott Long 		case ET_REBUILD_FAILED:
1301713e81bSScott Long 		case ET_REBUILD_FINISHED:
1311713e81bSScott Long 
1321713e81bSScott Long 		case ET_VERIFY_STARTED:
1331713e81bSScott Long 		case ET_VERIFY_ABORTED:
1341713e81bSScott Long 		case ET_VERIFY_FAILED:
1351713e81bSScott Long 		case ET_VERIFY_FINISHED:
1361713e81bSScott Long 		case ET_VERIFY_DATA_ERROR:
1371713e81bSScott Long 
1381713e81bSScott Long 		case ET_SPARE_TOOK_OVER:
1391713e81bSScott Long 		case ET_DEVICE_REMOVED:
1401713e81bSScott Long 		case ET_DEVICE_PLUGGED:
1411713e81bSScott Long 		case ET_DEVICE_ERROR:
1421713e81bSScott Long 			e.DeviceID = VDEV_TO_ID((PVDevice)param);
1431713e81bSScott Long 			break;
1441713e81bSScott Long 
1451713e81bSScott Long 		default:
1461713e81bSScott Long 			break;
1471713e81bSScott Long 	}
1481713e81bSScott Long 	event_queue_add(&e);
1491713e81bSScott Long 	if (event==ET_DEVICE_REMOVED) {
150b8fdb7f9SMatt Jacob 		int controller, channel;
1511713e81bSScott Long 		get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
1521713e81bSScott Long 		hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
1531713e81bSScott Long 	}
15449b3fc40SJohn Baldwin 	wakeup(param);
1551713e81bSScott Long }
1561713e81bSScott Long 
157d2bd3ab9SScott Long static int
hpt_delete_array(_VBUS_ARG DEVICEID id,DWORD options)158d2bd3ab9SScott Long hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
1591713e81bSScott Long {
1601713e81bSScott Long 	PVDevice	pArray = ID_TO_VDEV(id);
1611713e81bSScott Long 	BOOLEAN	del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
1621713e81bSScott Long 	int i;
1631713e81bSScott Long 	PVDevice pa;
1641713e81bSScott Long 
165d2bd3ab9SScott Long 	if ((id==0) || check_VDevice_valid(pArray))
1661713e81bSScott Long 		return -1;
1671713e81bSScott Long 
1681713e81bSScott Long 	if(!mIsArray(pArray)) return -1;
1691713e81bSScott Long 
1701713e81bSScott Long 	if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
1711713e81bSScott Long 		pArray->u.array.rf_initializing)
1721713e81bSScott Long 		return -1;
1731713e81bSScott Long 
1741713e81bSScott Long 	for(i=0; i<pArray->u.array.bArnMember; i++) {
1751713e81bSScott Long 		pa = pArray->u.array.pMember[i];
1761713e81bSScott Long 		if (pa && mIsArray(pa)) {
1771713e81bSScott Long 			if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
1781713e81bSScott Long 				pa->u.array.rf_initializing)
1791713e81bSScott Long 				return -1;
1801713e81bSScott Long 		}
1811713e81bSScott Long 	}
1821713e81bSScott Long 
1831713e81bSScott Long 	if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
1841713e81bSScott Long 	fDeleteArray(_VBUS_P pArray, del_block0);
1851713e81bSScott Long 	return 0;
1861713e81bSScott Long 
1871713e81bSScott Long }
1881713e81bSScott Long 
1891713e81bSScott Long /* just to prevent driver from sending more commands */
nothing(_VBUS_ARG void * notused)1901713e81bSScott Long static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
1911713e81bSScott Long 
19249b3fc40SJohn Baldwin void
lock_driver_idle(IAL_ADAPTER_T * pAdapter)193d2bd3ab9SScott Long lock_driver_idle(IAL_ADAPTER_T *pAdapter)
1941713e81bSScott Long {
1951713e81bSScott Long 	_VBUS_INST(&pAdapter->VBus)
19649b3fc40SJohn Baldwin 	mtx_lock(&pAdapter->lock);
1971713e81bSScott Long 	while (pAdapter->outstandingCommands) {
1981713e81bSScott Long 		KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
1991713e81bSScott Long 		if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
20049b3fc40SJohn Baldwin 		mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
2011713e81bSScott Long 	}
2021713e81bSScott Long 	CheckIdleCall(_VBUS_P0);
2031713e81bSScott Long }
2041713e81bSScott Long 
Kernel_DeviceIoControl(_VBUS_ARG DWORD dwIoControlCode,PVOID lpInBuffer,DWORD nInBufferSize,PVOID lpOutBuffer,DWORD nOutBufferSize,PDWORD lpBytesReturned)2051713e81bSScott Long int Kernel_DeviceIoControl(_VBUS_ARG
2061713e81bSScott Long 							DWORD dwIoControlCode,       	/* operation control code */
2071713e81bSScott Long 							PVOID lpInBuffer,            	/* input data buffer */
2081713e81bSScott Long 							DWORD nInBufferSize,         	/* size of input data buffer */
2091713e81bSScott Long 							PVOID lpOutBuffer,           	/* output data buffer */
2101713e81bSScott Long 							DWORD nOutBufferSize,        	/* size of output data buffer */
2111713e81bSScott Long 							PDWORD lpBytesReturned      	/* byte count */
2121713e81bSScott Long 						)
2131713e81bSScott Long {
2141713e81bSScott Long 	IAL_ADAPTER_T *pAdapter;
2151713e81bSScott Long 
2161713e81bSScott Long 	switch(dwIoControlCode)	{
2171713e81bSScott Long 		case HPT_IOCTL_DELETE_ARRAY:
2181713e81bSScott Long 		{
2191713e81bSScott Long 			DEVICEID idArray;
2201713e81bSScott Long 			int iSuccess;
2211713e81bSScott Long 	        int i;
2221713e81bSScott Long 			PVDevice pArray;
2231713e81bSScott Long 			PVBus _vbus_p;
2241713e81bSScott Long 			struct cam_periph *periph = NULL;
2251713e81bSScott Long 
2261713e81bSScott Long 			if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
2271713e81bSScott Long 			if (nOutBufferSize!=sizeof(int)) return -1;
2281713e81bSScott Long 			idArray = *(DEVICEID *)lpInBuffer;
2291713e81bSScott Long 
2301713e81bSScott Long 			pArray = ID_TO_VDEV(idArray);
2311713e81bSScott Long 
232d2bd3ab9SScott Long 			if((idArray == 0) || check_VDevice_valid(pArray))
2331713e81bSScott Long 		       	return -1;
2341713e81bSScott Long 
2351713e81bSScott Long         	if(!mIsArray(pArray))
2361713e81bSScott Long 				return -1;
2371713e81bSScott Long 
2381713e81bSScott Long 			_vbus_p=pArray->pVBus;
2391713e81bSScott Long 			pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
2401713e81bSScott Long 
2411713e81bSScott Long 	        for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
2421713e81bSScott Long 				if(pArray == _vbus_p->pVDevice[i])
2431713e81bSScott Long 				{
2441713e81bSScott Long 					periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
245d2bd3ab9SScott Long 					if (periph != NULL && periph->refcount >= 1)
2461713e81bSScott Long 					{
2471713e81bSScott Long 						hpt_printk(("Can not delete a mounted device.\n"));
2481713e81bSScott Long 	                    return -1;
2491713e81bSScott Long 					}
2501713e81bSScott Long 				}
2511713e81bSScott Long 				/* the Mounted Disk isn't delete */
2521713e81bSScott Long 			}
2531713e81bSScott Long 
2541713e81bSScott Long 			iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
2551713e81bSScott Long 
2561713e81bSScott Long 			*(int*)lpOutBuffer = iSuccess;
2571713e81bSScott Long 
2581713e81bSScott Long 			if(iSuccess != 0)
2591713e81bSScott Long 				return -1;
2601713e81bSScott Long 			break;
2611713e81bSScott Long 		}
2621713e81bSScott Long 
2631713e81bSScott Long 		case HPT_IOCTL_GET_EVENT:
2641713e81bSScott Long 		{
2651713e81bSScott Long 			PHPT_EVENT pInfo;
2661713e81bSScott Long 
2671713e81bSScott Long 			if (nInBufferSize!=0) return -1;
2681713e81bSScott Long 			if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
2691713e81bSScott Long 
2701713e81bSScott Long 			pInfo = (PHPT_EVENT)lpOutBuffer;
2711713e81bSScott Long 
2721713e81bSScott Long 			if (hpt_get_event(pInfo)!=0)
2731713e81bSScott Long 				return -1;
2741713e81bSScott Long 		}
2751713e81bSScott Long 		break;
2761713e81bSScott Long 
2771713e81bSScott Long 		case HPT_IOCTL_SET_ARRAY_STATE:
2781713e81bSScott Long 		{
2791713e81bSScott Long 			DEVICEID idArray;
2801713e81bSScott Long 			DWORD state;
2811713e81bSScott Long 
2821713e81bSScott Long 			if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
2831713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
2841713e81bSScott Long 
2851713e81bSScott Long 			idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
2861713e81bSScott Long 			state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
2871713e81bSScott Long 
2881713e81bSScott Long 			if(hpt_set_array_state(idArray, state)!=0)
2891713e81bSScott Long 				return -1;
2901713e81bSScott Long 		}
2911713e81bSScott Long 		break;
2921713e81bSScott Long 
2931713e81bSScott Long 		case HPT_IOCTL_RESCAN_DEVICES:
2941713e81bSScott Long 		{
2951713e81bSScott Long 			if (nInBufferSize!=0) return -1;
2961713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
2971713e81bSScott Long 
2981713e81bSScott Long #ifndef FOR_DEMO
2991713e81bSScott Long 			/* stop buzzer if user perform rescan */
3001713e81bSScott Long 			for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
3011713e81bSScott Long 				if (pAdapter->beeping) {
3021713e81bSScott Long 					pAdapter->beeping = 0;
3031713e81bSScott Long 					BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
3041713e81bSScott Long 				}
3051713e81bSScott Long 			}
3061713e81bSScott Long #endif
3071713e81bSScott Long 		}
3081713e81bSScott Long 		break;
3091713e81bSScott Long 
3101713e81bSScott Long 		default:
3111713e81bSScott Long 		{
3121713e81bSScott Long 			PVDevice pVDev;
31349b3fc40SJohn Baldwin 
3141713e81bSScott Long 			switch(dwIoControlCode) {
3151713e81bSScott Long 			/* read-only ioctl functions can be called directly. */
3161713e81bSScott Long 			case HPT_IOCTL_GET_VERSION:
3171713e81bSScott Long 			case HPT_IOCTL_GET_CONTROLLER_IDS:
3181713e81bSScott Long 			case HPT_IOCTL_GET_CONTROLLER_COUNT:
3191713e81bSScott Long 			case HPT_IOCTL_GET_CONTROLLER_INFO:
3201713e81bSScott Long 			case HPT_IOCTL_GET_CHANNEL_INFO:
3211713e81bSScott Long 			case HPT_IOCTL_GET_LOGICAL_DEVICES:
3221713e81bSScott Long 			case HPT_IOCTL_GET_DEVICE_INFO:
32364470755SXin LI 			case HPT_IOCTL_GET_DEVICE_INFO_V2:
3241713e81bSScott Long 			case HPT_IOCTL_GET_EVENT:
3251713e81bSScott Long 			case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
3261713e81bSScott Long 				if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
3271713e81bSScott Long 					lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
3281713e81bSScott Long 				break;
3291713e81bSScott Long 
3301713e81bSScott Long 			default:
3311713e81bSScott Long 				/*
3321713e81bSScott Long 				 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
3331713e81bSScott Long 				 * wrong for second controller.
3341713e81bSScott Long 				 */
3351713e81bSScott Long 				switch(dwIoControlCode) {
3361713e81bSScott Long 				case HPT_IOCTL_CREATE_ARRAY:
3371713e81bSScott Long 					pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
33864470755SXin LI 				case HPT_IOCTL_CREATE_ARRAY_V2:
33964470755SXin LI 					pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
3401713e81bSScott Long 				case HPT_IOCTL_SET_ARRAY_INFO:
3411713e81bSScott Long 					pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
3421713e81bSScott Long 				case HPT_IOCTL_SET_DEVICE_INFO:
3431713e81bSScott Long 					pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
34464470755SXin LI 				case HPT_IOCTL_SET_DEVICE_INFO_V2:
34564470755SXin LI 					pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
3461713e81bSScott Long 				case HPT_IOCTL_SET_BOOT_MARK:
3471713e81bSScott Long 				case HPT_IOCTL_ADD_SPARE_DISK:
3481713e81bSScott Long 				case HPT_IOCTL_REMOVE_SPARE_DISK:
3491713e81bSScott Long 					pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
3501713e81bSScott Long 				case HPT_IOCTL_ADD_DISK_TO_ARRAY:
3511713e81bSScott Long 					pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
3521713e81bSScott Long 				default:
3531713e81bSScott Long 					pVDev = 0;
3541713e81bSScott Long 				}
3551713e81bSScott Long 
3561713e81bSScott Long 				if (pVDev && !check_VDevice_valid(pVDev)){
3571713e81bSScott Long 					_vbus_p = pVDev->pVBus;
3581713e81bSScott Long 
3591713e81bSScott Long 					pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
3601713e81bSScott Long 					/*
3611713e81bSScott Long 					 * create_array, and other functions can't be executed while channel is
3621713e81bSScott Long 					 * perform I/O commands. Wait until driver is idle.
3631713e81bSScott Long 					 */
36449b3fc40SJohn Baldwin 					lock_driver_idle(pAdapter);
3651713e81bSScott Long 					if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
3661713e81bSScott Long 						lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
36749b3fc40SJohn Baldwin 						mtx_unlock(&pAdapter->lock);
3681713e81bSScott Long 						return -1;
3691713e81bSScott Long 					}
37049b3fc40SJohn Baldwin 					mtx_unlock(&pAdapter->lock);
3711713e81bSScott Long 				}
3721713e81bSScott Long 				else
3731713e81bSScott Long 					return -1;
3741713e81bSScott Long 				break;
3751713e81bSScott Long 			}
3761713e81bSScott Long 
3771713e81bSScott Long #ifdef SUPPORT_ARRAY
3781713e81bSScott Long 			switch(dwIoControlCode)
3791713e81bSScott Long 			{
3801713e81bSScott Long 				case HPT_IOCTL_CREATE_ARRAY:
3811713e81bSScott Long 				{
3821713e81bSScott Long 					pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
38349b3fc40SJohn Baldwin 					mtx_lock(&pAdapter->lock);
3841713e81bSScott Long                     if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
3851713e81bSScott Long 				    {
3861713e81bSScott Long 						  (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
3871713e81bSScott Long                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
3881713e81bSScott Long 					}
3891713e81bSScott Long 					else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
3901713e81bSScott Long 				    {
3911713e81bSScott Long                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
3921713e81bSScott Long 					}
3931713e81bSScott Long 					else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
3941713e81bSScott Long 				    {
3951713e81bSScott Long                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
3961713e81bSScott Long 					}
39749b3fc40SJohn Baldwin 					mtx_unlock(&pAdapter->lock);
3981713e81bSScott Long                     break;
3991713e81bSScott Long 				}
4001713e81bSScott Long 
40164470755SXin LI 
40264470755SXin LI 				case HPT_IOCTL_CREATE_ARRAY_V2:
40364470755SXin LI 				{
40464470755SXin LI 					pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
40549b3fc40SJohn Baldwin 					mtx_lock(&pAdapter->lock);
40664470755SXin LI 				             if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
40764470755SXin LI 						  (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
40864470755SXin LI 				                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
40964470755SXin LI 					} else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
41064470755SXin LI 				                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
41164470755SXin LI 					} else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
41264470755SXin LI 				                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
41364470755SXin LI 					}
41449b3fc40SJohn Baldwin 					mtx_unlock(&pAdapter->lock);
41564470755SXin LI 					break;
41664470755SXin LI 				}
4171713e81bSScott Long 				case HPT_IOCTL_ADD_DISK_TO_ARRAY:
4181713e81bSScott Long 				{
4191713e81bSScott Long 					PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
4201713e81bSScott Long 					pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
421d2bd3ab9SScott Long 					if(pArray->u.array.rf_rebuilding == 0)
4221713e81bSScott Long 					{
42349b3fc40SJohn Baldwin 						mtx_lock(&pAdapter->lock);
4241713e81bSScott Long 						pArray->u.array.rf_auto_rebuild = 0;
4251713e81bSScott Long 						pArray->u.array.rf_abort_rebuild = 0;
4261713e81bSScott Long 						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
4271713e81bSScott Long 						while (!pArray->u.array.rf_rebuilding)
4281713e81bSScott Long 						{
42949b3fc40SJohn Baldwin 							if (mtx_sleep(pArray, &pAdapter->lock, 0, "hptwait", hz * 3) != 0)
4301713e81bSScott Long 								break;
4311713e81bSScott Long 						}
43249b3fc40SJohn Baldwin 						mtx_unlock(&pAdapter->lock);
4331713e81bSScott Long 					}
4341713e81bSScott Long 					break;
4351713e81bSScott Long 				}
4361713e81bSScott Long 			}
4371713e81bSScott Long #endif
4381713e81bSScott Long             return 0;
4391713e81bSScott Long 		}
4401713e81bSScott Long 	}
4411713e81bSScott Long 
4421713e81bSScott Long 	if (lpBytesReturned)
4431713e81bSScott Long 		*lpBytesReturned = nOutBufferSize;
4441713e81bSScott Long 	return 0;
4451713e81bSScott Long }
4461713e81bSScott Long 
447d2bd3ab9SScott Long static int
hpt_get_event(PHPT_EVENT pEvent)448d2bd3ab9SScott Long hpt_get_event(PHPT_EVENT pEvent)
4491713e81bSScott Long {
4501713e81bSScott Long 	int ret = event_queue_remove(pEvent);
4511713e81bSScott Long 	return ret;
4521713e81bSScott Long }
4531713e81bSScott Long 
454d2bd3ab9SScott Long static int
hpt_set_array_state(DEVICEID idArray,DWORD state)455d2bd3ab9SScott Long hpt_set_array_state(DEVICEID idArray, DWORD state)
4561713e81bSScott Long {
4571713e81bSScott Long 	IAL_ADAPTER_T *pAdapter;
4581713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(idArray);
4591713e81bSScott Long 	int	i;
4601713e81bSScott Long 
461d2bd3ab9SScott Long 	if(idArray == 0 || check_VDevice_valid(pVDevice))	return -1;
4621713e81bSScott Long 	if(!mIsArray(pVDevice))
4631713e81bSScott Long 		return -1;
4641713e81bSScott Long 	if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1;
4651713e81bSScott Long 
4661713e81bSScott Long 	pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt;
4671713e81bSScott Long 
4681713e81bSScott Long 	switch(state)
4691713e81bSScott Long 	{
4701713e81bSScott Long 		case MIRROR_REBUILD_START:
4711713e81bSScott Long 		{
47249b3fc40SJohn Baldwin 			mtx_lock(&pAdapter->lock);
4731713e81bSScott Long 			if (pVDevice->u.array.rf_rebuilding ||
4741713e81bSScott Long 				pVDevice->u.array.rf_verifying ||
47549b3fc40SJohn Baldwin 				pVDevice->u.array.rf_initializing) {
47649b3fc40SJohn Baldwin 				mtx_unlock(&pAdapter->lock);
4771713e81bSScott Long 				return -1;
47849b3fc40SJohn Baldwin 			}
4791713e81bSScott Long 
4801713e81bSScott Long 			pVDevice->u.array.rf_auto_rebuild = 0;
4811713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 0;
4821713e81bSScott Long 
4831713e81bSScott Long 			hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
4841713e81bSScott Long 				(UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
4851713e81bSScott Long 
4861713e81bSScott Long 			while (!pVDevice->u.array.rf_rebuilding)
4871713e81bSScott Long 			{
48849b3fc40SJohn Baldwin 				if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
48949b3fc40SJohn Baldwin 				    "hptwait", hz * 20) != 0)
4901713e81bSScott Long 					break;
4911713e81bSScott Long 			}
49249b3fc40SJohn Baldwin 			mtx_unlock(&pAdapter->lock);
4931713e81bSScott Long 		}
4941713e81bSScott Long 
4951713e81bSScott Long 		break;
4961713e81bSScott Long 
4971713e81bSScott Long 		case MIRROR_REBUILD_ABORT:
4981713e81bSScott Long 		{
4991713e81bSScott Long 			for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
500d2bd3ab9SScott Long 				if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
5011713e81bSScott Long 					hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
5021713e81bSScott Long 			}
5031713e81bSScott Long 
50449b3fc40SJohn Baldwin 			mtx_lock(&pAdapter->lock);
50549b3fc40SJohn Baldwin 			if(pVDevice->u.array.rf_rebuilding != 1) {
50649b3fc40SJohn Baldwin 				mtx_unlock(&pAdapter->lock);
5071713e81bSScott Long 				return -1;
50849b3fc40SJohn Baldwin 			}
5091713e81bSScott Long 
5101713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 1;
5111713e81bSScott Long 
5121713e81bSScott Long 			while (pVDevice->u.array.rf_abort_rebuild)
5131713e81bSScott Long 			{
51449b3fc40SJohn Baldwin 				if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
51549b3fc40SJohn Baldwin 				    "hptabrt", hz * 20) != 0)
5161713e81bSScott Long 					break;
5171713e81bSScott Long 			}
51849b3fc40SJohn Baldwin 			mtx_unlock(&pAdapter->lock);
5191713e81bSScott Long 		}
5201713e81bSScott Long 		break;
5211713e81bSScott Long 
5221713e81bSScott Long 		case AS_VERIFY_START:
5231713e81bSScott Long 		{
5241713e81bSScott Long 			/*if(pVDevice->u.array.rf_verifying)
5251713e81bSScott Long 				return -1;*/
52649b3fc40SJohn Baldwin 			mtx_lock(&pAdapter->lock);
5271713e81bSScott Long 			if (pVDevice->u.array.rf_rebuilding ||
5281713e81bSScott Long 				pVDevice->u.array.rf_verifying ||
52949b3fc40SJohn Baldwin 				pVDevice->u.array.rf_initializing) {
53049b3fc40SJohn Baldwin 				mtx_unlock(&pAdapter->lock);
5311713e81bSScott Long 				return -1;
53249b3fc40SJohn Baldwin 			}
5331713e81bSScott Long 
5341713e81bSScott Long             pVDevice->u.array.RebuildSectors = 0;
5351713e81bSScott Long 			hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
5361713e81bSScott Long 
5371713e81bSScott Long 			while (!pVDevice->u.array.rf_verifying)
5381713e81bSScott Long 			{
53949b3fc40SJohn Baldwin 				if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
54049b3fc40SJohn Baldwin 				    "hptvrfy", hz * 20) != 0)
5411713e81bSScott Long 					break;
5421713e81bSScott Long 			}
54349b3fc40SJohn Baldwin 			mtx_unlock(&pAdapter->lock);
5441713e81bSScott Long 		}
5451713e81bSScott Long 		break;
5461713e81bSScott Long 
5471713e81bSScott Long 		case AS_VERIFY_ABORT:
5481713e81bSScott Long 		{
54949b3fc40SJohn Baldwin 			mtx_lock(&pAdapter->lock);
55049b3fc40SJohn Baldwin 			if(pVDevice->u.array.rf_verifying != 1) {
55149b3fc40SJohn Baldwin 				mtx_unlock(&pAdapter->lock);
5521713e81bSScott Long 				return -1;
55349b3fc40SJohn Baldwin 			}
5541713e81bSScott Long 
5551713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 1;
5561713e81bSScott Long 
5571713e81bSScott Long 			while (pVDevice->u.array.rf_abort_rebuild)
5581713e81bSScott Long 			{
55949b3fc40SJohn Baldwin 				if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
56049b3fc40SJohn Baldwin 				    "hptvrfy", hz * 80) != 0)
5611713e81bSScott Long 					break;
5621713e81bSScott Long 			}
56349b3fc40SJohn Baldwin 			mtx_unlock(&pAdapter->lock);
5641713e81bSScott Long 		}
5651713e81bSScott Long 		break;
5661713e81bSScott Long 
5671713e81bSScott Long 		case AS_INITIALIZE_START:
5681713e81bSScott Long 		{
56949b3fc40SJohn Baldwin 			mtx_lock(&pAdapter->lock);
5701713e81bSScott Long 			if (pVDevice->u.array.rf_rebuilding ||
5711713e81bSScott Long 				pVDevice->u.array.rf_verifying ||
57249b3fc40SJohn Baldwin 				pVDevice->u.array.rf_initializing) {
57349b3fc40SJohn Baldwin 				mtx_unlock(&pAdapter->lock);
5741713e81bSScott Long 				return -1;
57549b3fc40SJohn Baldwin 			}
5761713e81bSScott Long 
5771713e81bSScott Long 			hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
5781713e81bSScott Long 
5791713e81bSScott Long 			while (!pVDevice->u.array.rf_initializing)
5801713e81bSScott Long 			{
58149b3fc40SJohn Baldwin 				if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
58249b3fc40SJohn Baldwin 				    "hptinit", hz * 80) != 0)
5831713e81bSScott Long 					break;
5841713e81bSScott Long 			}
58549b3fc40SJohn Baldwin 			mtx_unlock(&pAdapter->lock);
5861713e81bSScott Long 		}
5871713e81bSScott Long 		break;
5881713e81bSScott Long 
5891713e81bSScott Long 		case AS_INITIALIZE_ABORT:
5901713e81bSScott Long 		{
59149b3fc40SJohn Baldwin 			mtx_lock(&pAdapter->lock);
59249b3fc40SJohn Baldwin 			if(pVDevice->u.array.rf_initializing != 1) {
59349b3fc40SJohn Baldwin 				mtx_unlock(&pAdapter->lock);
5941713e81bSScott Long 				return -1;
59549b3fc40SJohn Baldwin 			}
5961713e81bSScott Long 
5971713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 1;
5981713e81bSScott Long 
5991713e81bSScott Long 			while (pVDevice->u.array.rf_abort_rebuild)
6001713e81bSScott Long 			{
60149b3fc40SJohn Baldwin 				if (mtx_sleep(pVDevice, &pAdapter->lock, 0,
60249b3fc40SJohn Baldwin 				    "hptinit", hz * 80) != 0)
6031713e81bSScott Long 					break;
6041713e81bSScott Long 			}
60549b3fc40SJohn Baldwin 			mtx_unlock(&pAdapter->lock);
6061713e81bSScott Long 		}
6071713e81bSScott Long 		break;
6081713e81bSScott Long 
6091713e81bSScott Long 		default:
6101713e81bSScott Long 			return -1;
6111713e81bSScott Long 	}
6121713e81bSScott Long 
6131713e81bSScott Long 	return 0;
6141713e81bSScott Long }
6151713e81bSScott Long 
616d2bd3ab9SScott Long int HPTLIBAPI
R1ControlSgl(_VBUS_ARG PCommand pCmd,FPSCAT_GATH pSgTable,int logical)617d2bd3ab9SScott Long R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
6181713e81bSScott Long {
6191713e81bSScott Long 	ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
6201713e81bSScott Long 	if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
6211713e81bSScott Long 		bufferSize<<=1;
6221713e81bSScott Long 	if (logical) {
6231713e81bSScott Long 		pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
6241713e81bSScott Long 		pSgTable->wSgSize = (USHORT)bufferSize;
6251713e81bSScott Long 		pSgTable->wSgFlag = SG_FLAG_EOT;
6261713e81bSScott Long 	}
6271713e81bSScott Long 	else {
6281713e81bSScott Long 		/* build physical SG table for pCmd->uCmd.R1Control.Buffer */
6291713e81bSScott Long 		ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
6301713e81bSScott Long 		ULONG length;
6311713e81bSScott Long 		int idx = 0;
6321713e81bSScott Long 
6331713e81bSScott Long 		v = pCmd->uCmd.R1Control.Buffer;
6341713e81bSScott Long 		dataPointer = (ADDRESS)fOsPhysicalAddress(v);
6351713e81bSScott Long 
6361713e81bSScott Long 		if ((ULONG_PTR)dataPointer & 0x1)
6371713e81bSScott Long 			return FALSE;
6381713e81bSScott Long 
6391713e81bSScott Long 		#define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
6401713e81bSScott Long 		#define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
6411713e81bSScott Long 
6421713e81bSScott Long 		do {
6431713e81bSScott Long 			if (idx >= MAX_SG_DESCRIPTORS)  return FALSE;
6441713e81bSScott Long 
6451713e81bSScott Long 			pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
6461713e81bSScott Long 			currvaddr = v;
6471713e81bSScott Long 			currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
6481713e81bSScott Long 
6491713e81bSScott Long 
6501713e81bSScott Long 			do {
6511713e81bSScott Long 				nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
6521713e81bSScott Long 				nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
6531713e81bSScott Long 
6541713e81bSScott Long 				if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
6551713e81bSScott Long 				nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
6561713e81bSScott Long 
6571713e81bSScott Long 				if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
6581713e81bSScott Long 					nextvaddr = nextpage;
6591713e81bSScott Long 					break;
6601713e81bSScott Long 				}
6611713e81bSScott Long 
6621713e81bSScott Long 				currvaddr = nextvaddr;
6631713e81bSScott Long 				currphypage = nextphypage;
6641713e81bSScott Long 			}while (1);
6651713e81bSScott Long 
6661713e81bSScott Long 			length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
6671713e81bSScott Long 			v = nextvaddr;
6681713e81bSScott Long 			bufferSize -= length;
6691713e81bSScott Long 
6701713e81bSScott Long 			pSgTable[idx].wSgSize = (USHORT)length;
6711713e81bSScott Long 			pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
6721713e81bSScott Long 			idx++;
6731713e81bSScott Long 
6741713e81bSScott Long 		}while (bufferSize);
6751713e81bSScott Long 	}
6761713e81bSScott Long 	return 1;
6771713e81bSScott Long }
6781713e81bSScott Long 
6791713e81bSScott Long static int End_Job=0;
680d2bd3ab9SScott Long void HPTLIBAPI
thread_io_done(_VBUS_ARG PCommand pCmd)681d2bd3ab9SScott Long thread_io_done(_VBUS_ARG PCommand pCmd)
6821713e81bSScott Long {
6831713e81bSScott Long 	End_Job = 1;
6841713e81bSScott Long 	wakeup((caddr_t)pCmd);
6851713e81bSScott Long }
6861713e81bSScott Long 
687d2bd3ab9SScott Long void
hpt_rebuild_data_block(IAL_ADAPTER_T * pAdapter,PVDevice pArray,UCHAR flags)688d2bd3ab9SScott Long hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
6891713e81bSScott Long {
6901713e81bSScott Long     ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
6911713e81bSScott Long     PCommand pCmd;
6921713e81bSScott Long 	UINT result;
6931713e81bSScott Long 	int needsync=0, retry=0, needdelete=0;
6944d24901aSPedro F. Giffuni 	void *buffer = NULL;
6951713e81bSScott Long 
6961713e81bSScott Long 	_VBUS_INST(&pAdapter->VBus)
6971713e81bSScott Long 
6981713e81bSScott Long 	if (pArray->u.array.rf_broken==1 ||
6991713e81bSScott Long     	pArray->u.array.RebuildSectors>=capacity)
7001713e81bSScott Long 		return;
7011713e81bSScott Long 
70249b3fc40SJohn Baldwin 	mtx_lock(&pAdapter->lock);
7031713e81bSScott Long 
7041713e81bSScott Long 	switch(flags)
7051713e81bSScott Long 	{
7061713e81bSScott Long 		case DUPLICATE:
7071713e81bSScott Long 		case REBUILD_PARITY:
7081713e81bSScott Long 			if(pArray->u.array.rf_rebuilding == 0)
7091713e81bSScott Long 			{
7101713e81bSScott Long 				pArray->u.array.rf_rebuilding = 1;
7111713e81bSScott Long 				hpt_printk(("Rebuilding started.\n"));
7121713e81bSScott Long 				ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
7131713e81bSScott Long 			}
7141713e81bSScott Long 			break;
7151713e81bSScott Long 
7161713e81bSScott Long 		case INITIALIZE:
7171713e81bSScott Long 			if(pArray->u.array.rf_initializing == 0)
7181713e81bSScott Long 			{
7191713e81bSScott Long 				pArray->u.array.rf_initializing = 1;
7201713e81bSScott Long 				hpt_printk(("Initializing started.\n"));
7211713e81bSScott Long 				ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
7221713e81bSScott Long 			}
7231713e81bSScott Long 			break;
7241713e81bSScott Long 
7251713e81bSScott Long 		case VERIFY:
7261713e81bSScott Long 			if(pArray->u.array.rf_verifying == 0)
7271713e81bSScott Long 			{
7281713e81bSScott Long 				pArray->u.array.rf_verifying = 1;
7291713e81bSScott Long 				hpt_printk(("Verifying started.\n"));
7301713e81bSScott Long 				ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
7311713e81bSScott Long 			}
7321713e81bSScott Long 			break;
7331713e81bSScott Long 	}
7341713e81bSScott Long 
7351713e81bSScott Long retry_cmd:
7361713e81bSScott Long 	pCmd = AllocateCommand(_VBUS_P0);
7371713e81bSScott Long 	HPT_ASSERT(pCmd);
7381713e81bSScott Long 	pCmd->cf_control = 1;
7391713e81bSScott Long 	End_Job = 0;
7401713e81bSScott Long 
7411713e81bSScott Long 	if (pArray->VDeviceType==VD_RAID_1)
7421713e81bSScott Long 	{
7431713e81bSScott Long 		#define MAX_REBUILD_SECTORS 0x40
7441713e81bSScott Long 
7451713e81bSScott Long 		/* take care for discontinuous buffer in R1ControlSgl */
7461713e81bSScott Long 		buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
7471713e81bSScott Long 		if(!buffer) {
7481713e81bSScott Long 			FreeCommand(_VBUS_P pCmd);
7491713e81bSScott Long 			hpt_printk(("can't allocate rebuild buffer\n"));
7501713e81bSScott Long 			goto fail;
7511713e81bSScott Long 		}
7521713e81bSScott Long 		switch(flags)
7531713e81bSScott Long 		{
7541713e81bSScott Long 			case DUPLICATE:
7551713e81bSScott Long 				pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
7561713e81bSScott Long 				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
7571713e81bSScott Long 				break;
7581713e81bSScott Long 
7591713e81bSScott Long 			case VERIFY:
7601713e81bSScott Long 				pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
7611713e81bSScott Long 				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
7621713e81bSScott Long 				break;
7631713e81bSScott Long 
7641713e81bSScott Long 			case INITIALIZE:
7651713e81bSScott Long 				pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
7661713e81bSScott Long 				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
7671713e81bSScott Long 				break;
7681713e81bSScott Long 		}
7691713e81bSScott Long 
7701713e81bSScott Long 		pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;
7711713e81bSScott Long 
7721713e81bSScott Long 		if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
7731713e81bSScott Long 			pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;
7741713e81bSScott Long 
7751713e81bSScott Long 		pCmd->uCmd.R1Control.Buffer = buffer;
7761713e81bSScott Long 		pCmd->pfnBuildSgl = R1ControlSgl;
7771713e81bSScott Long 	}
7781713e81bSScott Long 	else if (pArray->VDeviceType==VD_RAID_5)
7791713e81bSScott Long 	{
7801713e81bSScott Long 		switch(flags)
7811713e81bSScott Long 		{
7821713e81bSScott Long 			case DUPLICATE:
7831713e81bSScott Long 			case REBUILD_PARITY:
7841713e81bSScott Long 				pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
7851713e81bSScott Long 			case VERIFY:
7861713e81bSScott Long 				pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
7871713e81bSScott Long 			case INITIALIZE:
7881713e81bSScott Long 				pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
7891713e81bSScott Long 		}
7901713e81bSScott Long 		pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
7911713e81bSScott Long 	}
7921713e81bSScott Long 	else
7931713e81bSScott Long 		HPT_ASSERT(0);
7941713e81bSScott Long 
7951713e81bSScott Long 	pCmd->pVDevice = pArray;
7961713e81bSScott Long 	pCmd->pfnCompletion = thread_io_done;
7971713e81bSScott Long 	pArray->pfnSendCommand(_VBUS_P pCmd);
7981713e81bSScott Long 	CheckPendingCall(_VBUS_P0);
7991713e81bSScott Long 
8001713e81bSScott Long 	if (!End_Job) {
80149b3fc40SJohn Baldwin 		mtx_sleep(pCmd, &pAdapter->lock, 0, "hptrbld", hz * 60);
8021713e81bSScott Long 		if (!End_Job) {
8031713e81bSScott Long 			hpt_printk(("timeout, reset\n"));
8041713e81bSScott Long 			fResetVBus(_VBUS_P0);
8051713e81bSScott Long 		}
8061713e81bSScott Long 	}
8071713e81bSScott Long 
8081713e81bSScott Long 	result = pCmd->Result;
8091713e81bSScott Long 	FreeCommand(_VBUS_P pCmd);
810d2bd3ab9SScott Long 	if (buffer) free(buffer, M_DEVBUF);
8111713e81bSScott Long 	KdPrintI(("cmd finished %d", result));
8121713e81bSScott Long 
8131713e81bSScott Long 	switch(result)
8141713e81bSScott Long 	{
8151713e81bSScott Long 		case RETURN_SUCCESS:
8161713e81bSScott Long 			if (!pArray->u.array.rf_abort_rebuild)
8171713e81bSScott Long 			{
8181713e81bSScott Long 				if(pArray->u.array.RebuildSectors < capacity)
8191713e81bSScott Long 				{
8201713e81bSScott Long 					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
8211713e81bSScott Long 				}
8221713e81bSScott Long 				else
8231713e81bSScott Long 				{
8241713e81bSScott Long 					switch (flags)
8251713e81bSScott Long 					{
8261713e81bSScott Long 						case DUPLICATE:
8271713e81bSScott Long 						case REBUILD_PARITY:
8281713e81bSScott Long 							needsync = 1;
8291713e81bSScott Long 							pArray->u.array.rf_rebuilding = 0;
8301713e81bSScott Long 							pArray->u.array.rf_need_rebuild = 0;
8311713e81bSScott Long 							pArray->u.array.CriticalMembers = 0;
8321713e81bSScott Long 							pArray->u.array.RebuildSectors = MAX_LBA_T;
8331713e81bSScott Long 							pArray->u.array.rf_duplicate_and_create = 0;
8341713e81bSScott Long 							hpt_printk(("Rebuilding finished.\n"));
8351713e81bSScott Long 							ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
8361713e81bSScott Long 							break;
8371713e81bSScott Long 						case INITIALIZE:
8381713e81bSScott Long 							needsync = 1;
8391713e81bSScott Long 							pArray->u.array.rf_initializing = 0;
8401713e81bSScott Long 							pArray->u.array.rf_need_rebuild = 0;
8411713e81bSScott Long 							pArray->u.array.RebuildSectors = MAX_LBA_T;
8421713e81bSScott Long 							hpt_printk(("Initializing finished.\n"));
8431713e81bSScott Long 							ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
8441713e81bSScott Long 							break;
8451713e81bSScott Long 						case VERIFY:
8461713e81bSScott Long 							pArray->u.array.rf_verifying = 0;
8471713e81bSScott Long 							hpt_printk(("Verifying finished.\n"));
8481713e81bSScott Long 							ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
8491713e81bSScott Long 							break;
8501713e81bSScott Long 					}
8511713e81bSScott Long 				}
8521713e81bSScott Long 			}
8531713e81bSScott Long 			else
8541713e81bSScott Long 			{
8551713e81bSScott Long 				pArray->u.array.rf_abort_rebuild = 0;
8561713e81bSScott Long 				if (pArray->u.array.rf_rebuilding)
8571713e81bSScott Long 				{
8581713e81bSScott Long 					hpt_printk(("Abort rebuilding.\n"));
8591713e81bSScott Long 					pArray->u.array.rf_rebuilding = 0;
8601713e81bSScott Long 					pArray->u.array.rf_duplicate_and_create = 0;
8611713e81bSScott Long 					ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
8621713e81bSScott Long 				}
8631713e81bSScott Long 				else if (pArray->u.array.rf_verifying)
8641713e81bSScott Long 				{
8651713e81bSScott Long 					hpt_printk(("Abort verifying.\n"));
8661713e81bSScott Long 					pArray->u.array.rf_verifying = 0;
8671713e81bSScott Long 					ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
8681713e81bSScott Long 				}
8691713e81bSScott Long 				else if (pArray->u.array.rf_initializing)
8701713e81bSScott Long 				{
8711713e81bSScott Long 					hpt_printk(("Abort initializing.\n"));
8721713e81bSScott Long 					pArray->u.array.rf_initializing = 0;
8731713e81bSScott Long 					ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
8741713e81bSScott Long 				}
8751713e81bSScott Long 				needdelete=1;
8761713e81bSScott Long 			}
8771713e81bSScott Long 			break;
8781713e81bSScott Long 
8791713e81bSScott Long 		case RETURN_DATA_ERROR:
8801713e81bSScott Long 			if (flags==VERIFY)
8811713e81bSScott Long 			{
8821713e81bSScott Long 				needsync = 1;
8831713e81bSScott Long 				pArray->u.array.rf_verifying = 0;
8841713e81bSScott Long 				pArray->u.array.rf_need_rebuild = 1;
8851713e81bSScott Long 				hpt_printk(("Verifying failed: found inconsistency\n"));
8861713e81bSScott Long 				ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
8871713e81bSScott Long 				ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
8881713e81bSScott Long 
8891713e81bSScott Long 				if (!pArray->vf_online || pArray->u.array.rf_broken) break;
8901713e81bSScott Long 
8911713e81bSScott Long 				pArray->u.array.rf_auto_rebuild = 0;
8921713e81bSScott Long 				pArray->u.array.rf_abort_rebuild = 0;
8931713e81bSScott Long 				hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
8941713e81bSScott Long 					(pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
8951713e81bSScott Long 			}
8961713e81bSScott Long 			break;
8971713e81bSScott Long 
8981713e81bSScott Long 		default:
8991713e81bSScott Long 			hpt_printk(("command failed with error %d\n", result));
9001713e81bSScott Long 			if (++retry<3)
9011713e81bSScott Long 			{
9021713e81bSScott Long 				hpt_printk(("retry (%d)\n", retry));
9031713e81bSScott Long 				goto retry_cmd;
9041713e81bSScott Long 			}
9051713e81bSScott Long fail:
9061713e81bSScott Long 			pArray->u.array.rf_abort_rebuild = 0;
9071713e81bSScott Long 			switch (flags)
9081713e81bSScott Long 			{
9091713e81bSScott Long 				case DUPLICATE:
9101713e81bSScott Long 				case REBUILD_PARITY:
9111713e81bSScott Long 					needsync = 1;
9121713e81bSScott Long 					pArray->u.array.rf_rebuilding = 0;
9131713e81bSScott Long 					pArray->u.array.rf_duplicate_and_create = 0;
9141713e81bSScott Long 					hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
9151713e81bSScott Long 					ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
9161713e81bSScott Long 					break;
9171713e81bSScott Long 
9181713e81bSScott Long 				case INITIALIZE:
9191713e81bSScott Long 					needsync = 1;
9201713e81bSScott Long 					pArray->u.array.rf_initializing = 0;
9211713e81bSScott Long 					hpt_printk(("Initializing failed.\n"));
9221713e81bSScott Long 					ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
9231713e81bSScott Long 					break;
9241713e81bSScott Long 
9251713e81bSScott Long 				case VERIFY:
9261713e81bSScott Long 					needsync = 1;
9271713e81bSScott Long 					pArray->u.array.rf_verifying = 0;
9281713e81bSScott Long 					hpt_printk(("Verifying failed.\n"));
9291713e81bSScott Long 					ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
9301713e81bSScott Long 					break;
9311713e81bSScott Long 			}
9321713e81bSScott Long 			needdelete=1;
9331713e81bSScott Long 	}
9341713e81bSScott Long 
9351713e81bSScott Long 	while (pAdapter->outstandingCommands)
9361713e81bSScott Long 	{
9371713e81bSScott Long 		KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
9381713e81bSScott Long 		/* put this to have driver stop processing system commands quickly */
9391713e81bSScott Long 		if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
94049b3fc40SJohn Baldwin 		mtx_sleep(pAdapter, &pAdapter->lock, 0, "hptidle", 0);
9411713e81bSScott Long 	}
9421713e81bSScott Long 
9431713e81bSScott Long 	if (needsync) SyncArrayInfo(pArray);
9441713e81bSScott Long 	if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
9451713e81bSScott Long 		fDeleteArray(_VBUS_P pArray, TRUE);
9461713e81bSScott Long 
9471713e81bSScott Long 	Check_Idle_Call(pAdapter);
94849b3fc40SJohn Baldwin 	mtx_unlock(&pAdapter->lock);
9491713e81bSScott Long }
950