xref: /freebsd/sys/dev/hptmv/ioctl.c (revision d2bd3ab995038214fa00f73d4a88cd891d0afe34)
11713e81bSScott Long /*
2d2bd3ab9SScott Long  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
31713e81bSScott Long  * All rights reserved.
41713e81bSScott Long  *
51713e81bSScott Long  * Redistribution and use in source and binary forms, with or without
61713e81bSScott Long  * modification, are permitted provided that the following conditions
71713e81bSScott Long  * are met:
81713e81bSScott Long  * 1. Redistributions of source code must retain the above copyright
91713e81bSScott Long  *    notice, this list of conditions and the following disclaimer.
101713e81bSScott Long  * 2. Redistributions in binary form must reproduce the above copyright
111713e81bSScott Long  *    notice, this list of conditions and the following disclaimer in the
121713e81bSScott Long  *    documentation and/or other materials provided with the distribution.
131713e81bSScott Long  *
141713e81bSScott Long  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151713e81bSScott Long  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161713e81bSScott Long  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171713e81bSScott Long  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181713e81bSScott Long  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191713e81bSScott Long  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201713e81bSScott Long  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211713e81bSScott Long  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221713e81bSScott Long  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231713e81bSScott Long  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241713e81bSScott Long  * SUCH DAMAGE.
25d38d9c9eSScott Long  *
26d38d9c9eSScott Long  * $FreeBSD$
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 #if (__FreeBSD_version < 500000)
37d2bd3ab9SScott Long #include <sys/proc.h>
38d2bd3ab9SScott Long #include <sys/kthread.h>
39d2bd3ab9SScott Long #include <sys/wait.h>
40d2bd3ab9SScott Long #include <sys/sysproto.h>
41d2bd3ab9SScott Long #endif
42d2bd3ab9SScott Long 
43d2bd3ab9SScott Long #ifndef __KERNEL__
44d2bd3ab9SScott Long #define __KERNEL__
45d2bd3ab9SScott Long #endif
46d2bd3ab9SScott Long 
471713e81bSScott Long #include <dev/hptmv/global.h>
481713e81bSScott Long #include <dev/hptmv/hptintf.h>
491713e81bSScott Long #include <dev/hptmv/osbsd.h>
50f7f3900bSScott Long #include <dev/hptmv/access601.h>
511713e81bSScott Long 
521713e81bSScott Long #pragma pack(1)
531713e81bSScott Long 
541713e81bSScott Long typedef struct _HPT_REBUILD_PARAM
551713e81bSScott Long {
561713e81bSScott Long 	DEVICEID idMirror;
571713e81bSScott Long 	DWORD Lba;
581713e81bSScott Long 	UCHAR nSector;
591713e81bSScott Long } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM;
601713e81bSScott Long 
611713e81bSScott Long #pragma pack()
621713e81bSScott Long 
631713e81bSScott Long #define MAX_EVENTS 10
641713e81bSScott Long static HPT_EVENT hpt_event_queue[MAX_EVENTS];
651713e81bSScott Long static int event_queue_head=0, event_queue_tail=0;
661713e81bSScott Long 
671713e81bSScott Long static int hpt_get_event(PHPT_EVENT pEvent);
681713e81bSScott Long static int hpt_set_array_state(DEVICEID idArray, DWORD state);
691713e81bSScott Long static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter);
701713e81bSScott Long static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd);
711713e81bSScott Long static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd,
721713e81bSScott Long     FPSCAT_GATH pSgTable, int logical);
731713e81bSScott Long 
74d2bd3ab9SScott Long static void
75d2bd3ab9SScott Long get_disk_location(PDevice pDev, int *controller, int *channel)
761713e81bSScott Long {
771713e81bSScott Long 	IAL_ADAPTER_T *pAdapTemp;
781713e81bSScott Long 	int i, j;
791713e81bSScott Long 
801713e81bSScott Long     for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) {
811713e81bSScott Long     	for (j=0; j<MV_SATA_CHANNELS_NUM; j++)
821713e81bSScott Long     		if (pDev==&pAdapTemp->VDevices[j].u.disk) {
831713e81bSScott Long     			*controller = i;
841713e81bSScott Long     			*channel = j;
851713e81bSScott Long     			return;
861713e81bSScott Long     		}
871713e81bSScott Long 	}
881713e81bSScott Long }
891713e81bSScott Long 
90d2bd3ab9SScott Long static int
91d2bd3ab9SScott Long event_queue_add(PHPT_EVENT pEvent)
921713e81bSScott Long {
931713e81bSScott Long 	int p;
941713e81bSScott Long 	p = (event_queue_tail + 1) % MAX_EVENTS;
951713e81bSScott Long 	if (p==event_queue_head)
961713e81bSScott Long 	{
971713e81bSScott Long 		return -1;
981713e81bSScott Long 	}
991713e81bSScott Long 	hpt_event_queue[event_queue_tail] = *pEvent;
1001713e81bSScott Long 	event_queue_tail = p;
1011713e81bSScott Long 	return 0;
1021713e81bSScott Long }
1031713e81bSScott Long 
104d2bd3ab9SScott Long static int
105d2bd3ab9SScott Long event_queue_remove(PHPT_EVENT pEvent)
1061713e81bSScott Long {
1071713e81bSScott Long 	if (event_queue_head != event_queue_tail)
1081713e81bSScott Long 	{
1091713e81bSScott Long 		*pEvent = hpt_event_queue[event_queue_head];
1101713e81bSScott Long 		event_queue_head++;
1111713e81bSScott Long 		event_queue_head %= MAX_EVENTS;
1121713e81bSScott Long 		return 0;
1131713e81bSScott Long 	}
1141713e81bSScott Long 	return -1;
1151713e81bSScott Long }
1161713e81bSScott Long 
117d2bd3ab9SScott Long void HPTLIBAPI
118d2bd3ab9SScott Long ioctl_ReportEvent(UCHAR event, PVOID param)
1191713e81bSScott Long {
1201713e81bSScott Long 	HPT_EVENT e;
1211713e81bSScott Long 	ZeroMemory(&e, sizeof(e));
1221713e81bSScott Long 	e.EventType = event;
1231713e81bSScott Long 	switch(event)
1241713e81bSScott Long 	{
1251713e81bSScott Long 		case ET_INITIALIZE_ABORTED:
1261713e81bSScott Long 		case ET_INITIALIZE_FAILED:
1271713e81bSScott Long 			memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
1281713e81bSScott Long 		case ET_INITIALIZE_STARTED:
1291713e81bSScott Long 		case ET_INITIALIZE_FINISHED:
1301713e81bSScott Long 
1311713e81bSScott Long 		case ET_REBUILD_STARTED:
1321713e81bSScott Long 		case ET_REBUILD_ABORTED:
1331713e81bSScott Long 		case ET_REBUILD_FAILED:
1341713e81bSScott Long 		case ET_REBUILD_FINISHED:
1351713e81bSScott Long 
1361713e81bSScott Long 		case ET_VERIFY_STARTED:
1371713e81bSScott Long 		case ET_VERIFY_ABORTED:
1381713e81bSScott Long 		case ET_VERIFY_FAILED:
1391713e81bSScott Long 		case ET_VERIFY_FINISHED:
1401713e81bSScott Long 		case ET_VERIFY_DATA_ERROR:
1411713e81bSScott Long 
1421713e81bSScott Long 		case ET_SPARE_TOOK_OVER:
1431713e81bSScott Long 		case ET_DEVICE_REMOVED:
1441713e81bSScott Long 		case ET_DEVICE_PLUGGED:
1451713e81bSScott Long 		case ET_DEVICE_ERROR:
1461713e81bSScott Long 			e.DeviceID = VDEV_TO_ID((PVDevice)param);
1471713e81bSScott Long 			break;
1481713e81bSScott Long 
1491713e81bSScott Long 		default:
1501713e81bSScott Long 			break;
1511713e81bSScott Long 	}
1521713e81bSScott Long 	event_queue_add(&e);
1531713e81bSScott Long 	if (event==ET_DEVICE_REMOVED) {
1541713e81bSScott Long 		int controller, channel;
1551713e81bSScott Long 		get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
1561713e81bSScott Long 		hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
1571713e81bSScott Long 	}
1581713e81bSScott Long }
1591713e81bSScott Long 
160d2bd3ab9SScott Long static int
161d2bd3ab9SScott Long hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options)
1621713e81bSScott Long {
1631713e81bSScott Long 	PVDevice	pArray = ID_TO_VDEV(id);
1641713e81bSScott Long 	BOOLEAN	del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1;
1651713e81bSScott Long 	int i;
1661713e81bSScott Long 	PVDevice pa;
1671713e81bSScott Long 
168d2bd3ab9SScott Long 	if ((id==0) || check_VDevice_valid(pArray))
1691713e81bSScott Long 		return -1;
1701713e81bSScott Long 
1711713e81bSScott Long 	if(!mIsArray(pArray)) return -1;
1721713e81bSScott Long 
1731713e81bSScott Long 	if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying ||
1741713e81bSScott Long 		pArray->u.array.rf_initializing)
1751713e81bSScott Long 		return -1;
1761713e81bSScott Long 
1771713e81bSScott Long 	for(i=0; i<pArray->u.array.bArnMember; i++) {
1781713e81bSScott Long 		pa = pArray->u.array.pMember[i];
1791713e81bSScott Long 		if (pa && mIsArray(pa)) {
1801713e81bSScott Long 			if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying ||
1811713e81bSScott Long 				pa->u.array.rf_initializing)
1821713e81bSScott Long 				return -1;
1831713e81bSScott Long 		}
1841713e81bSScott Long 	}
1851713e81bSScott Long 
1861713e81bSScott Long 	if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
1871713e81bSScott Long 	fDeleteArray(_VBUS_P pArray, del_block0);
1881713e81bSScott Long 	return 0;
1891713e81bSScott Long 
1901713e81bSScott Long }
1911713e81bSScott Long 
1921713e81bSScott Long /* just to prevent driver from sending more commands */
1931713e81bSScott Long static void HPTLIBAPI nothing(_VBUS_ARG void *notused){}
1941713e81bSScott Long 
195d2bd3ab9SScott Long intrmask_t
196d2bd3ab9SScott Long lock_driver_idle(IAL_ADAPTER_T *pAdapter)
1971713e81bSScott Long {
1981713e81bSScott Long 	intrmask_t oldspl;
1991713e81bSScott Long 	_VBUS_INST(&pAdapter->VBus)
2001713e81bSScott Long 	oldspl = lock_driver();
2011713e81bSScott Long 	while (pAdapter->outstandingCommands) {
2021713e81bSScott Long 		KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands));
2031713e81bSScott Long 		if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
2041713e81bSScott Long 		unlock_driver(oldspl);
205d2bd3ab9SScott Long /*Schedule out*/
206d2bd3ab9SScott Long #if (__FreeBSD_version < 500000)
207d2bd3ab9SScott Long 		YIELD_THREAD;
208d2bd3ab9SScott Long #else
209d2bd3ab9SScott Long 		tsleep(lock_driver_idle, PPAUSE, "switch", 1);
210d2bd3ab9SScott Long #endif
2111713e81bSScott Long 		oldspl = lock_driver();
2121713e81bSScott Long 	}
2131713e81bSScott Long 	CheckIdleCall(_VBUS_P0);
2141713e81bSScott Long 	return oldspl;
2151713e81bSScott Long }
2161713e81bSScott Long 
2171713e81bSScott Long int Kernel_DeviceIoControl(_VBUS_ARG
2181713e81bSScott Long 							DWORD dwIoControlCode,       	/* operation control code */
2191713e81bSScott Long 							PVOID lpInBuffer,            	/* input data buffer */
2201713e81bSScott Long 							DWORD nInBufferSize,         	/* size of input data buffer */
2211713e81bSScott Long 							PVOID lpOutBuffer,           	/* output data buffer */
2221713e81bSScott Long 							DWORD nOutBufferSize,        	/* size of output data buffer */
2231713e81bSScott Long 							PDWORD lpBytesReturned      	/* byte count */
2241713e81bSScott Long 						)
2251713e81bSScott Long {
2261713e81bSScott Long 	IAL_ADAPTER_T *pAdapter;
2271713e81bSScott Long 
2281713e81bSScott Long 	switch(dwIoControlCode)	{
2291713e81bSScott Long 		case HPT_IOCTL_DELETE_ARRAY:
2301713e81bSScott Long 		{
2311713e81bSScott Long 			DEVICEID idArray;
2321713e81bSScott Long 			int iSuccess;
2331713e81bSScott Long 	        int i;
2341713e81bSScott Long 			PVDevice pArray;
2351713e81bSScott Long 			PVBus _vbus_p;
2361713e81bSScott Long 			struct cam_periph *periph = NULL;
2371713e81bSScott Long 
2381713e81bSScott Long 			if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
2391713e81bSScott Long 			if (nOutBufferSize!=sizeof(int)) return -1;
2401713e81bSScott Long 			idArray = *(DEVICEID *)lpInBuffer;
2411713e81bSScott Long 
2421713e81bSScott Long 			pArray = ID_TO_VDEV(idArray);
2431713e81bSScott Long 
244d2bd3ab9SScott Long 			if((idArray == 0) || check_VDevice_valid(pArray))
2451713e81bSScott Long 		       	return -1;
2461713e81bSScott Long 
2471713e81bSScott Long         	if(!mIsArray(pArray))
2481713e81bSScott Long 			return -1;
2491713e81bSScott Long 
2501713e81bSScott Long 			_vbus_p=pArray->pVBus;
2511713e81bSScott Long 			pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
2521713e81bSScott Long 
2531713e81bSScott Long 	        for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
2541713e81bSScott Long 				if(pArray == _vbus_p->pVDevice[i])
2551713e81bSScott Long 				{
2561713e81bSScott Long 					periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
257d2bd3ab9SScott Long 					if (periph != NULL && periph->refcount >= 1)
2581713e81bSScott Long 					{
2591713e81bSScott Long 						hpt_printk(("Can not delete a mounted device.\n"));
2601713e81bSScott Long 	                    return -1;
2611713e81bSScott Long 					}
2621713e81bSScott Long 				}
2631713e81bSScott Long 				/* the Mounted Disk isn't delete */
2641713e81bSScott Long 			}
2651713e81bSScott Long 
2661713e81bSScott Long 			iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));
2671713e81bSScott Long 
2681713e81bSScott Long 			*(int*)lpOutBuffer = iSuccess;
2691713e81bSScott Long 
2701713e81bSScott Long 			if(iSuccess != 0)
2711713e81bSScott Long 				return -1;
2721713e81bSScott Long 			break;
2731713e81bSScott Long 		}
2741713e81bSScott Long 
2751713e81bSScott Long 		case HPT_IOCTL_GET_EVENT:
2761713e81bSScott Long 		{
2771713e81bSScott Long 			PHPT_EVENT pInfo;
2781713e81bSScott Long 
2791713e81bSScott Long 			if (nInBufferSize!=0) return -1;
2801713e81bSScott Long 			if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;
2811713e81bSScott Long 
2821713e81bSScott Long 			pInfo = (PHPT_EVENT)lpOutBuffer;
2831713e81bSScott Long 
2841713e81bSScott Long 			if (hpt_get_event(pInfo)!=0)
2851713e81bSScott Long 				return -1;
2861713e81bSScott Long 		}
2871713e81bSScott Long 		break;
2881713e81bSScott Long 
2891713e81bSScott Long 		case HPT_IOCTL_SET_ARRAY_STATE:
2901713e81bSScott Long 		{
2911713e81bSScott Long 			DEVICEID idArray;
2921713e81bSScott Long 			DWORD state;
2931713e81bSScott Long 
2941713e81bSScott Long 			if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
2951713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
2961713e81bSScott Long 
2971713e81bSScott Long 			idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
2981713e81bSScott Long 			state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;
2991713e81bSScott Long 
3001713e81bSScott Long 			if(hpt_set_array_state(idArray, state)!=0)
3011713e81bSScott Long 				return -1;
3021713e81bSScott Long 		}
3031713e81bSScott Long 		break;
3041713e81bSScott Long 
3051713e81bSScott Long 		case HPT_IOCTL_RESCAN_DEVICES:
3061713e81bSScott Long 		{
3071713e81bSScott Long 			if (nInBufferSize!=0) return -1;
3081713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
3091713e81bSScott Long 
3101713e81bSScott Long #ifndef FOR_DEMO
3111713e81bSScott Long 			/* stop buzzer if user perform rescan */
3121713e81bSScott Long 			for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
3131713e81bSScott Long 				if (pAdapter->beeping) {
3141713e81bSScott Long 					pAdapter->beeping = 0;
3151713e81bSScott Long 					BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
3161713e81bSScott Long 				}
3171713e81bSScott Long 			}
3181713e81bSScott Long #endif
3191713e81bSScott Long 		}
3201713e81bSScott Long 		break;
3211713e81bSScott Long 
3221713e81bSScott Long 		default:
3231713e81bSScott Long 		{
3241713e81bSScott Long 			PVDevice pVDev;
3251713e81bSScott Long #ifdef SUPPORT_ARRAY
3261713e81bSScott Long 			intrmask_t oldspl;
3271713e81bSScott Long #endif
3281713e81bSScott Long 			switch(dwIoControlCode) {
3291713e81bSScott Long 			/* read-only ioctl functions can be called directly. */
3301713e81bSScott Long 			case HPT_IOCTL_GET_VERSION:
3311713e81bSScott Long 			case HPT_IOCTL_GET_CONTROLLER_IDS:
3321713e81bSScott Long 			case HPT_IOCTL_GET_CONTROLLER_COUNT:
3331713e81bSScott Long 			case HPT_IOCTL_GET_CONTROLLER_INFO:
3341713e81bSScott Long 			case HPT_IOCTL_GET_CHANNEL_INFO:
3351713e81bSScott Long 			case HPT_IOCTL_GET_LOGICAL_DEVICES:
3361713e81bSScott Long 			case HPT_IOCTL_GET_DEVICE_INFO:
3371713e81bSScott Long 			case HPT_IOCTL_GET_EVENT:
3381713e81bSScott Long 			case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
3391713e81bSScott Long 				if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
3401713e81bSScott Long 					lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
3411713e81bSScott Long 				break;
3421713e81bSScott Long 
3431713e81bSScott Long 			default:
3441713e81bSScott Long 				/*
3451713e81bSScott Long 				 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be
3461713e81bSScott Long 				 * wrong for second controller.
3471713e81bSScott Long 				 */
3481713e81bSScott Long 				switch(dwIoControlCode) {
3491713e81bSScott Long 				case HPT_IOCTL_CREATE_ARRAY:
3501713e81bSScott Long 					pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
3511713e81bSScott Long 				case HPT_IOCTL_SET_ARRAY_INFO:
3521713e81bSScott Long 					pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
3531713e81bSScott Long 				case HPT_IOCTL_SET_DEVICE_INFO:
3541713e81bSScott Long 					pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
3551713e81bSScott Long 				case HPT_IOCTL_SET_BOOT_MARK:
3561713e81bSScott Long 				case HPT_IOCTL_ADD_SPARE_DISK:
3571713e81bSScott Long 				case HPT_IOCTL_REMOVE_SPARE_DISK:
3581713e81bSScott Long 					pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
3591713e81bSScott Long 				case HPT_IOCTL_ADD_DISK_TO_ARRAY:
3601713e81bSScott Long 					pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
3611713e81bSScott Long 				default:
3621713e81bSScott Long 					pVDev = 0;
3631713e81bSScott Long 				}
3641713e81bSScott Long 
3651713e81bSScott Long 				if (pVDev && !check_VDevice_valid(pVDev)){
3661713e81bSScott Long 					_vbus_p = pVDev->pVBus;
3671713e81bSScott Long 
3681713e81bSScott Long 					pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
3691713e81bSScott Long 					/*
3701713e81bSScott Long 					 * create_array, and other functions can't be executed while channel is
3711713e81bSScott Long 					 * perform I/O commands. Wait until driver is idle.
3721713e81bSScott Long 					 */
3731713e81bSScott Long 					oldspl = lock_driver_idle(pAdapter);
3741713e81bSScott Long 					if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
3751713e81bSScott Long 						lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
3761713e81bSScott Long 						unlock_driver(oldspl);
3771713e81bSScott Long 						return -1;
3781713e81bSScott Long 					}
3791713e81bSScott Long 					unlock_driver(oldspl);
3801713e81bSScott Long 				}
3811713e81bSScott Long 				else
3821713e81bSScott Long 					return -1;
3831713e81bSScott Long 				break;
3841713e81bSScott Long 			}
3851713e81bSScott Long 
3861713e81bSScott Long #ifdef SUPPORT_ARRAY
3871713e81bSScott Long 			switch(dwIoControlCode)
3881713e81bSScott Long 			{
3891713e81bSScott Long 				case HPT_IOCTL_CREATE_ARRAY:
3901713e81bSScott Long 				{
3911713e81bSScott Long 					pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
3921713e81bSScott Long 					oldspl = lock_driver();
3931713e81bSScott Long                     if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
3941713e81bSScott Long 				    {
3951713e81bSScott Long 						  (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
3961713e81bSScott Long                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
3971713e81bSScott Long 					}
3981713e81bSScott Long 					else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
3991713e81bSScott Long 				    {
4001713e81bSScott Long                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
4011713e81bSScott Long 					}
4021713e81bSScott Long 					else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
4031713e81bSScott Long 				    {
4041713e81bSScott Long                           hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
4051713e81bSScott Long 					}
4061713e81bSScott Long 					unlock_driver(oldspl);
4071713e81bSScott Long                     break;
4081713e81bSScott Long 				}
4091713e81bSScott Long 
4101713e81bSScott Long 				case HPT_IOCTL_ADD_DISK_TO_ARRAY:
4111713e81bSScott Long 				{
4121713e81bSScott Long 					PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
4131713e81bSScott Long 					pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
414d2bd3ab9SScott Long 					if(pArray->u.array.rf_rebuilding == 0)
4151713e81bSScott Long 					{
4161713e81bSScott Long 						DWORD timeout = 0;
4171713e81bSScott Long 						oldspl = lock_driver();
4181713e81bSScott Long 						pArray->u.array.rf_auto_rebuild = 0;
4191713e81bSScott Long 						pArray->u.array.rf_abort_rebuild = 0;
4201713e81bSScott Long 						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
4211713e81bSScott Long 						unlock_driver(oldspl);
4221713e81bSScott Long 						while (!pArray->u.array.rf_rebuilding)
4231713e81bSScott Long 						{
4241713e81bSScott Long 							tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1);
4251713e81bSScott Long 							if ( timeout >= hz*3)
4261713e81bSScott Long 								break;
4271713e81bSScott Long 							timeout ++;
4281713e81bSScott Long 						}
4291713e81bSScott Long 					}
4301713e81bSScott Long 					break;
4311713e81bSScott Long 				}
4321713e81bSScott Long 			}
4331713e81bSScott Long #endif
4341713e81bSScott Long             return 0;
4351713e81bSScott Long 		}
4361713e81bSScott Long 	}
4371713e81bSScott Long 
4381713e81bSScott Long 	if (lpBytesReturned)
4391713e81bSScott Long 		*lpBytesReturned = nOutBufferSize;
4401713e81bSScott Long 	return 0;
4411713e81bSScott Long }
4421713e81bSScott Long 
443d2bd3ab9SScott Long static int
444d2bd3ab9SScott Long hpt_get_event(PHPT_EVENT pEvent)
4451713e81bSScott Long {
4461713e81bSScott Long 	intrmask_t oldspl = lock_driver();
4471713e81bSScott Long 	int ret = event_queue_remove(pEvent);
4481713e81bSScott Long 	unlock_driver(oldspl);
4491713e81bSScott Long 	return ret;
4501713e81bSScott Long }
4511713e81bSScott Long 
452d2bd3ab9SScott Long static int
453d2bd3ab9SScott Long hpt_set_array_state(DEVICEID idArray, DWORD state)
4541713e81bSScott Long {
4551713e81bSScott Long 	IAL_ADAPTER_T *pAdapter;
4561713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(idArray);
4571713e81bSScott Long 	int	i;
4581713e81bSScott Long 	DWORD timeout = 0;
4591713e81bSScott Long 	intrmask_t oldspl;
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 		{
4721713e81bSScott Long 			if (pVDevice->u.array.rf_rebuilding ||
4731713e81bSScott Long 				pVDevice->u.array.rf_verifying ||
4741713e81bSScott Long 				pVDevice->u.array.rf_initializing)
4751713e81bSScott Long 				return -1;
4761713e81bSScott Long 
4771713e81bSScott Long 			oldspl = lock_driver();
4781713e81bSScott Long 
4791713e81bSScott Long 			pVDevice->u.array.rf_auto_rebuild = 0;
4801713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 0;
4811713e81bSScott Long 
4821713e81bSScott Long 			hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice,
4831713e81bSScott Long 				(UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
4841713e81bSScott Long 
4851713e81bSScott Long 			unlock_driver(oldspl);
4861713e81bSScott Long 
4871713e81bSScott Long 			while (!pVDevice->u.array.rf_rebuilding)
4881713e81bSScott Long 			{
4891713e81bSScott Long 				tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
4901713e81bSScott Long 				if ( timeout >= hz*20)
4911713e81bSScott Long 					break;
4921713e81bSScott Long 				timeout ++;
4931713e81bSScott Long 			}
4941713e81bSScott Long 		}
4951713e81bSScott Long 
4961713e81bSScott Long 		break;
4971713e81bSScott Long 
4981713e81bSScott Long 		case MIRROR_REBUILD_ABORT:
4991713e81bSScott Long 		{
5001713e81bSScott Long 			for(i = 0; i < pVDevice->u.array.bArnMember; i++) {
501d2bd3ab9SScott Long 				if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1)
5021713e81bSScott Long 					hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state);
5031713e81bSScott Long 			}
5041713e81bSScott Long 
5051713e81bSScott Long 			if(pVDevice->u.array.rf_rebuilding != 1)
5061713e81bSScott Long 				return -1;
5071713e81bSScott Long 
5081713e81bSScott Long 			oldspl = lock_driver();
5091713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 1;
5101713e81bSScott Long 			unlock_driver(oldspl);
5111713e81bSScott Long 
5121713e81bSScott Long 			while (pVDevice->u.array.rf_abort_rebuild)
5131713e81bSScott Long 			{
5141713e81bSScott Long 				tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
5151713e81bSScott Long 				if ( timeout >= hz*20)
5161713e81bSScott Long 					break;
5171713e81bSScott Long 				timeout ++;
5181713e81bSScott Long 			}
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;*/
5261713e81bSScott Long 			if (pVDevice->u.array.rf_rebuilding ||
5271713e81bSScott Long 				pVDevice->u.array.rf_verifying ||
5281713e81bSScott Long 				pVDevice->u.array.rf_initializing)
5291713e81bSScott Long 				return -1;
5301713e81bSScott Long 
5311713e81bSScott Long 			oldspl = lock_driver();
5321713e81bSScott Long             pVDevice->u.array.RebuildSectors = 0;
5331713e81bSScott Long 			hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
5341713e81bSScott Long 			unlock_driver(oldspl);
5351713e81bSScott Long 
5361713e81bSScott Long 			while (!pVDevice->u.array.rf_verifying)
5371713e81bSScott Long 			{
5381713e81bSScott Long 				tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
5391713e81bSScott Long 				if ( timeout >= hz*20)
5401713e81bSScott Long 					break;
5411713e81bSScott Long 				timeout ++;
5421713e81bSScott Long 			}
5431713e81bSScott Long 		}
5441713e81bSScott Long 		break;
5451713e81bSScott Long 
5461713e81bSScott Long 		case AS_VERIFY_ABORT:
5471713e81bSScott Long 		{
5481713e81bSScott Long 			if(pVDevice->u.array.rf_verifying != 1)
5491713e81bSScott Long 				return -1;
5501713e81bSScott Long 
5511713e81bSScott Long 			oldspl = lock_driver();
5521713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 1;
5531713e81bSScott Long 			unlock_driver(oldspl);
5541713e81bSScott Long 
5551713e81bSScott Long 			while (pVDevice->u.array.rf_abort_rebuild)
5561713e81bSScott Long 			{
5571713e81bSScott Long 				tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
5581713e81bSScott Long 				if ( timeout >= hz*80)
5591713e81bSScott Long 					break;
5601713e81bSScott Long 				timeout ++;
5611713e81bSScott Long 			}
5621713e81bSScott Long 		}
5631713e81bSScott Long 		break;
5641713e81bSScott Long 
5651713e81bSScott Long 		case AS_INITIALIZE_START:
5661713e81bSScott Long 		{
5671713e81bSScott Long 			if (pVDevice->u.array.rf_rebuilding ||
5681713e81bSScott Long 				pVDevice->u.array.rf_verifying ||
5691713e81bSScott Long 				pVDevice->u.array.rf_initializing)
5701713e81bSScott Long 				return -1;
5711713e81bSScott Long 
5721713e81bSScott Long 			oldspl = lock_driver();
5731713e81bSScott Long 			hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY);
5741713e81bSScott Long 			unlock_driver(oldspl);
5751713e81bSScott Long 
5761713e81bSScott Long 			while (!pVDevice->u.array.rf_initializing)
5771713e81bSScott Long 			{
5781713e81bSScott Long 				tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
5791713e81bSScott Long 				if ( timeout >= hz*80)
5801713e81bSScott Long 					break;
5811713e81bSScott Long 				timeout ++;
5821713e81bSScott Long 			}
5831713e81bSScott Long 		}
5841713e81bSScott Long 		break;
5851713e81bSScott Long 
5861713e81bSScott Long 		case AS_INITIALIZE_ABORT:
5871713e81bSScott Long 		{
5881713e81bSScott Long 			if(pVDevice->u.array.rf_initializing != 1)
5891713e81bSScott Long 				return -1;
5901713e81bSScott Long 
5911713e81bSScott Long 			oldspl = lock_driver();
5921713e81bSScott Long 			pVDevice->u.array.rf_abort_rebuild = 1;
5931713e81bSScott Long 			unlock_driver(oldspl);
5941713e81bSScott Long 
5951713e81bSScott Long 			while (pVDevice->u.array.rf_abort_rebuild)
5961713e81bSScott Long 			{
5971713e81bSScott Long 				tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
5981713e81bSScott Long 				if ( timeout >= hz*80)
5991713e81bSScott Long 					break;
6001713e81bSScott Long 				timeout ++;
6011713e81bSScott Long 			}
6021713e81bSScott Long 		}
6031713e81bSScott Long 		break;
6041713e81bSScott Long 
6051713e81bSScott Long 		default:
6061713e81bSScott Long 			return -1;
6071713e81bSScott Long 	}
6081713e81bSScott Long 
6091713e81bSScott Long 	return 0;
6101713e81bSScott Long }
6111713e81bSScott Long 
612d2bd3ab9SScott Long int HPTLIBAPI
613d2bd3ab9SScott Long R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical)
6141713e81bSScott Long {
6151713e81bSScott Long 	ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors);
6161713e81bSScott Long 	if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY)
6171713e81bSScott Long 		bufferSize<<=1;
6181713e81bSScott Long 	if (logical) {
6191713e81bSScott Long 		pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer;
6201713e81bSScott Long 		pSgTable->wSgSize = (USHORT)bufferSize;
6211713e81bSScott Long 		pSgTable->wSgFlag = SG_FLAG_EOT;
6221713e81bSScott Long 	}
6231713e81bSScott Long 	else {
6241713e81bSScott Long 		/* build physical SG table for pCmd->uCmd.R1Control.Buffer */
6251713e81bSScott Long 		ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage;
6261713e81bSScott Long 		ULONG length;
6271713e81bSScott Long 		int idx = 0;
6281713e81bSScott Long 
6291713e81bSScott Long 		v = pCmd->uCmd.R1Control.Buffer;
6301713e81bSScott Long 		dataPointer = (ADDRESS)fOsPhysicalAddress(v);
6311713e81bSScott Long 
6321713e81bSScott Long 		if ((ULONG_PTR)dataPointer & 0x1)
6331713e81bSScott Long 			return FALSE;
6341713e81bSScott Long 
6351713e81bSScott Long 		#define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0)
6361713e81bSScott Long 		#define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE)
6371713e81bSScott Long 
6381713e81bSScott Long 		do {
6391713e81bSScott Long 			if (idx >= MAX_SG_DESCRIPTORS)  return FALSE;
6401713e81bSScott Long 
6411713e81bSScott Long 			pSgTable[idx].dSgAddress = fOsPhysicalAddress(v);
6421713e81bSScott Long 			currvaddr = v;
6431713e81bSScott Long 			currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr));
6441713e81bSScott Long 
6451713e81bSScott Long 
6461713e81bSScott Long 			do {
6471713e81bSScott Long 				nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE));
6481713e81bSScott Long 				nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage));
6491713e81bSScott Long 
6501713e81bSScott Long 				if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break;
6511713e81bSScott Long 				nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage);
6521713e81bSScott Long 
6531713e81bSScott Long 				if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) {
6541713e81bSScott Long 					nextvaddr = nextpage;
6551713e81bSScott Long 					break;
6561713e81bSScott Long 				}
6571713e81bSScott Long 
6581713e81bSScott Long 				currvaddr = nextvaddr;
6591713e81bSScott Long 				currphypage = nextphypage;
6601713e81bSScott Long 			}while (1);
6611713e81bSScott Long 
6621713e81bSScott Long 			length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v;
6631713e81bSScott Long 			v = nextvaddr;
6641713e81bSScott Long 			bufferSize -= length;
6651713e81bSScott Long 
6661713e81bSScott Long 			pSgTable[idx].wSgSize = (USHORT)length;
6671713e81bSScott Long 			pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT;
6681713e81bSScott Long 			idx++;
6691713e81bSScott Long 
6701713e81bSScott Long 		}while (bufferSize);
6711713e81bSScott Long 	}
6721713e81bSScott Long 	return 1;
6731713e81bSScott Long }
6741713e81bSScott Long 
6751713e81bSScott Long static int End_Job=0;
676d2bd3ab9SScott Long void HPTLIBAPI
677d2bd3ab9SScott Long thread_io_done(_VBUS_ARG PCommand pCmd)
6781713e81bSScott Long {
6791713e81bSScott Long 	End_Job = 1;
6801713e81bSScott Long 	wakeup((caddr_t)pCmd);
6811713e81bSScott Long }
6821713e81bSScott Long 
683d2bd3ab9SScott Long void
684d2bd3ab9SScott Long hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
6851713e81bSScott Long {
6861713e81bSScott Long 	DWORD timeout = 0;
6871713e81bSScott Long     ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
6881713e81bSScott Long     PCommand pCmd;
6891713e81bSScott Long 	UINT result;
6901713e81bSScott Long 	int needsync=0, retry=0, needdelete=0;
6911713e81bSScott Long 	void *buffer = 0;
6921713e81bSScott Long 	intrmask_t oldspl;
6931713e81bSScott Long 
6941713e81bSScott Long 	_VBUS_INST(&pAdapter->VBus)
6951713e81bSScott Long 
6961713e81bSScott Long 	if (pArray->u.array.rf_broken==1 ||
6971713e81bSScott Long     	pArray->u.array.RebuildSectors>=capacity)
6981713e81bSScott Long 		return;
6991713e81bSScott Long 
7001713e81bSScott Long 	oldspl = lock_driver();
7011713e81bSScott Long 
7021713e81bSScott Long 	switch(flags)
7031713e81bSScott Long 	{
7041713e81bSScott Long 		case DUPLICATE:
7051713e81bSScott Long 		case REBUILD_PARITY:
7061713e81bSScott Long 			if(pArray->u.array.rf_rebuilding == 0)
7071713e81bSScott Long 			{
7081713e81bSScott Long 				pArray->u.array.rf_rebuilding = 1;
7091713e81bSScott Long 				hpt_printk(("Rebuilding started.\n"));
7101713e81bSScott Long 				ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
7111713e81bSScott Long 			}
7121713e81bSScott Long 			break;
7131713e81bSScott Long 
7141713e81bSScott Long 		case INITIALIZE:
7151713e81bSScott Long 			if(pArray->u.array.rf_initializing == 0)
7161713e81bSScott Long 			{
7171713e81bSScott Long 				pArray->u.array.rf_initializing = 1;
7181713e81bSScott Long 				hpt_printk(("Initializing started.\n"));
7191713e81bSScott Long 				ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
7201713e81bSScott Long 			}
7211713e81bSScott Long 			break;
7221713e81bSScott Long 
7231713e81bSScott Long 		case VERIFY:
7241713e81bSScott Long 			if(pArray->u.array.rf_verifying == 0)
7251713e81bSScott Long 			{
7261713e81bSScott Long 				pArray->u.array.rf_verifying = 1;
7271713e81bSScott Long 				hpt_printk(("Verifying started.\n"));
7281713e81bSScott Long 				ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
7291713e81bSScott Long 			}
7301713e81bSScott Long 			break;
7311713e81bSScott Long 	}
7321713e81bSScott Long 
7331713e81bSScott Long retry_cmd:
7341713e81bSScott Long 	pCmd = AllocateCommand(_VBUS_P0);
7351713e81bSScott Long 	HPT_ASSERT(pCmd);
7361713e81bSScott Long 	pCmd->cf_control = 1;
7371713e81bSScott Long 	End_Job = 0;
7381713e81bSScott Long 
7391713e81bSScott Long 	if (pArray->VDeviceType==VD_RAID_1)
7401713e81bSScott Long 	{
7411713e81bSScott Long 		#define MAX_REBUILD_SECTORS 0x40
7421713e81bSScott Long 
7431713e81bSScott Long 		/* take care for discontinuous buffer in R1ControlSgl */
744d2bd3ab9SScott Long 		unlock_driver(oldspl);
7451713e81bSScott Long 		buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
746d2bd3ab9SScott Long 		oldspl = lock_driver();
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) {
8011713e81bSScott Long 		unlock_driver(oldspl);
8021713e81bSScott Long 		while (!End_Job) {
8031713e81bSScott Long 			tsleep((caddr_t)pCmd, PPAUSE, "pause", hz);
8041713e81bSScott Long 			if (timeout++>60) break;
8051713e81bSScott Long 		}
8061713e81bSScott Long 		oldspl = lock_driver();
8071713e81bSScott Long 		if (!End_Job) {
8081713e81bSScott Long 			hpt_printk(("timeout, reset\n"));
8091713e81bSScott Long 			fResetVBus(_VBUS_P0);
8101713e81bSScott Long 		}
8111713e81bSScott Long 	}
8121713e81bSScott Long 
8131713e81bSScott Long 	result = pCmd->Result;
8141713e81bSScott Long 	FreeCommand(_VBUS_P pCmd);
815d2bd3ab9SScott Long 	unlock_driver(oldspl);
816d2bd3ab9SScott Long 	if (buffer) free(buffer, M_DEVBUF);
817d2bd3ab9SScott Long 	oldspl = lock_driver();
8181713e81bSScott Long 	KdPrintI(("cmd finished %d", result));
8191713e81bSScott Long 
8201713e81bSScott Long 	switch(result)
8211713e81bSScott Long 	{
8221713e81bSScott Long 		case RETURN_SUCCESS:
8231713e81bSScott Long 			if (!pArray->u.array.rf_abort_rebuild)
8241713e81bSScott Long 			{
8251713e81bSScott Long 				if(pArray->u.array.RebuildSectors < capacity)
8261713e81bSScott Long 				{
8271713e81bSScott Long 					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags);
8281713e81bSScott Long 				}
8291713e81bSScott Long 				else
8301713e81bSScott Long 				{
8311713e81bSScott Long 					switch (flags)
8321713e81bSScott Long 					{
8331713e81bSScott Long 						case DUPLICATE:
8341713e81bSScott Long 						case REBUILD_PARITY:
8351713e81bSScott Long 							needsync = 1;
8361713e81bSScott Long 							pArray->u.array.rf_rebuilding = 0;
8371713e81bSScott Long 							pArray->u.array.rf_need_rebuild = 0;
8381713e81bSScott Long 							pArray->u.array.CriticalMembers = 0;
8391713e81bSScott Long 							pArray->u.array.RebuildSectors = MAX_LBA_T;
8401713e81bSScott Long 							pArray->u.array.rf_duplicate_and_create = 0;
8411713e81bSScott Long 							hpt_printk(("Rebuilding finished.\n"));
8421713e81bSScott Long 							ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray);
8431713e81bSScott Long 							break;
8441713e81bSScott Long 						case INITIALIZE:
8451713e81bSScott Long 							needsync = 1;
8461713e81bSScott Long 							pArray->u.array.rf_initializing = 0;
8471713e81bSScott Long 							pArray->u.array.rf_need_rebuild = 0;
8481713e81bSScott Long 							pArray->u.array.RebuildSectors = MAX_LBA_T;
8491713e81bSScott Long 							hpt_printk(("Initializing finished.\n"));
8501713e81bSScott Long 							ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray);
8511713e81bSScott Long 							break;
8521713e81bSScott Long 						case VERIFY:
8531713e81bSScott Long 							pArray->u.array.rf_verifying = 0;
8541713e81bSScott Long 							hpt_printk(("Verifying finished.\n"));
8551713e81bSScott Long 							ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray);
8561713e81bSScott Long 							break;
8571713e81bSScott Long 					}
8581713e81bSScott Long 				}
8591713e81bSScott Long 			}
8601713e81bSScott Long 			else
8611713e81bSScott Long 			{
8621713e81bSScott Long 				pArray->u.array.rf_abort_rebuild = 0;
8631713e81bSScott Long 				if (pArray->u.array.rf_rebuilding)
8641713e81bSScott Long 				{
8651713e81bSScott Long 					hpt_printk(("Abort rebuilding.\n"));
8661713e81bSScott Long 					pArray->u.array.rf_rebuilding = 0;
8671713e81bSScott Long 					pArray->u.array.rf_duplicate_and_create = 0;
8681713e81bSScott Long 					ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray);
8691713e81bSScott Long 				}
8701713e81bSScott Long 				else if (pArray->u.array.rf_verifying)
8711713e81bSScott Long 				{
8721713e81bSScott Long 					hpt_printk(("Abort verifying.\n"));
8731713e81bSScott Long 					pArray->u.array.rf_verifying = 0;
8741713e81bSScott Long 					ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray);
8751713e81bSScott Long 				}
8761713e81bSScott Long 				else if (pArray->u.array.rf_initializing)
8771713e81bSScott Long 				{
8781713e81bSScott Long 					hpt_printk(("Abort initializing.\n"));
8791713e81bSScott Long 					pArray->u.array.rf_initializing = 0;
8801713e81bSScott Long 					ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray);
8811713e81bSScott Long 				}
8821713e81bSScott Long 				needdelete=1;
8831713e81bSScott Long 			}
8841713e81bSScott Long 			break;
8851713e81bSScott Long 
8861713e81bSScott Long 		case RETURN_DATA_ERROR:
8871713e81bSScott Long 			if (flags==VERIFY)
8881713e81bSScott Long 			{
8891713e81bSScott Long 				needsync = 1;
8901713e81bSScott Long 				pArray->u.array.rf_verifying = 0;
8911713e81bSScott Long 				pArray->u.array.rf_need_rebuild = 1;
8921713e81bSScott Long 				hpt_printk(("Verifying failed: found inconsistency\n"));
8931713e81bSScott Long 				ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray);
8941713e81bSScott Long 				ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
8951713e81bSScott Long 
8961713e81bSScott Long 				if (!pArray->vf_online || pArray->u.array.rf_broken) break;
8971713e81bSScott Long 
8981713e81bSScott Long 				pArray->u.array.rf_auto_rebuild = 0;
8991713e81bSScott Long 				pArray->u.array.rf_abort_rebuild = 0;
9001713e81bSScott Long 				hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray,
9011713e81bSScott Long 					(pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY);
9021713e81bSScott Long 			}
9031713e81bSScott Long 			break;
9041713e81bSScott Long 
9051713e81bSScott Long 		default:
9061713e81bSScott Long 			hpt_printk(("command failed with error %d\n", result));
9071713e81bSScott Long 			if (++retry<3)
9081713e81bSScott Long 			{
9091713e81bSScott Long 				hpt_printk(("retry (%d)\n", retry));
9101713e81bSScott Long 				goto retry_cmd;
9111713e81bSScott Long 			}
9121713e81bSScott Long fail:
9131713e81bSScott Long 			pArray->u.array.rf_abort_rebuild = 0;
9141713e81bSScott Long 			switch (flags)
9151713e81bSScott Long 			{
9161713e81bSScott Long 				case DUPLICATE:
9171713e81bSScott Long 				case REBUILD_PARITY:
9181713e81bSScott Long 					needsync = 1;
9191713e81bSScott Long 					pArray->u.array.rf_rebuilding = 0;
9201713e81bSScott Long 					pArray->u.array.rf_duplicate_and_create = 0;
9211713e81bSScott Long 					hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n"));
9221713e81bSScott Long 					ioctl_ReportEvent(ET_REBUILD_FAILED, pArray);
9231713e81bSScott Long 					break;
9241713e81bSScott Long 
9251713e81bSScott Long 				case INITIALIZE:
9261713e81bSScott Long 					needsync = 1;
9271713e81bSScott Long 					pArray->u.array.rf_initializing = 0;
9281713e81bSScott Long 					hpt_printk(("Initializing failed.\n"));
9291713e81bSScott Long 					ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray);
9301713e81bSScott Long 					break;
9311713e81bSScott Long 
9321713e81bSScott Long 				case VERIFY:
9331713e81bSScott Long 					needsync = 1;
9341713e81bSScott Long 					pArray->u.array.rf_verifying = 0;
9351713e81bSScott Long 					hpt_printk(("Verifying failed.\n"));
9361713e81bSScott Long 					ioctl_ReportEvent(ET_VERIFY_FAILED, pArray);
9371713e81bSScott Long 					break;
9381713e81bSScott Long 			}
9391713e81bSScott Long 			needdelete=1;
9401713e81bSScott Long 	}
9411713e81bSScott Long 
9421713e81bSScott Long 	while (pAdapter->outstandingCommands)
9431713e81bSScott Long 	{
9441713e81bSScott Long 		KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands));
9451713e81bSScott Long 		/* put this to have driver stop processing system commands quickly */
9461713e81bSScott Long 		if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0);
9471713e81bSScott Long 		unlock_driver(oldspl);
948d2bd3ab9SScott Long 		/*Schedule out*/
949d2bd3ab9SScott Long #if (__FreeBSD_version < 500000)
950d2bd3ab9SScott Long 		YIELD_THREAD;
951d2bd3ab9SScott Long #else
952d2bd3ab9SScott Long 		tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1);
953d2bd3ab9SScott Long #endif
9541713e81bSScott Long 		oldspl = lock_driver();
9551713e81bSScott Long 	}
9561713e81bSScott Long 
9571713e81bSScott Long 	if (needsync) SyncArrayInfo(pArray);
9581713e81bSScott Long 	if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE)))
9591713e81bSScott Long 		fDeleteArray(_VBUS_P pArray, TRUE);
9601713e81bSScott Long 
9611713e81bSScott Long 	Check_Idle_Call(pAdapter);
9621713e81bSScott Long 	unlock_driver(oldspl);
9631713e81bSScott Long }
964