Ejemplo n.º 1
0
static int
hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length)
{
	int orig_length = length+4;
	PVBus _vbus_p = &pAdapter->VBus;
	PVDevice	 pArray;
	PVDevice pSubArray, pVDev;
	UINT	i, iarray, ichan;
	struct cam_periph *periph = NULL;
	intrmask_t oldspl;

#ifdef SUPPORT_ARRAY	
	if (length>=8 && strncmp(buffer, "rebuild ", 8)==0) 
	{
		buffer+=8;
		length-=8;
		if (length>=5 && strncmp(buffer, "start", 5)==0) 
		{
			oldspl = lock_driver();
			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
					continue; 
				else{
					if (pArray->u.array.rf_need_rebuild && !pArray->u.array.rf_rebuilding)
	                    hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 
							(UCHAR)((pArray->u.array.CriticalMembers || pArray->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY));
				}
			unlock_driver(oldspl);
			return orig_length;
		}
		else if (length>=4 && strncmp(buffer, "stop", 4)==0) 
		{
			oldspl = lock_driver();
			for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
				if ((pArray=ArrayTables(i))->u.array.dArStamp==0)
					continue; 
				else{
					if (pArray->u.array.rf_rebuilding)
					    pArray->u.array.rf_abort_rebuild = 1;
				}
			unlock_driver(oldspl);
			return orig_length;
		}	
		else if (length>=3 && buffer[1]==','&& buffer[0]>='1'&& buffer[2]>='1')	
		{
			iarray = buffer[0]-'1';
	        ichan = buffer[2]-'1';

            if(iarray >= MAX_VDEVICE_PER_VBUS || ichan >= MV_SATA_CHANNELS_NUM) return -EINVAL;

			pArray = _vbus_p->pVDevice[iarray];
	        if (!pArray || (pArray->vf_online == 0)) return -EINVAL;

            for (i=0;i<MV_SATA_CHANNELS_NUM;i++)
				if(i == ichan)
				    goto rebuild;

	        return -EINVAL;

rebuild:
	        pVDev = &pAdapter->VDevices[ichan];
	        if(!pVDev->u.disk.df_on_line || pVDev->pParent) return -EINVAL;

	        /* Not allow to use a mounted disk ??? test*/
			for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
			    if(pVDev == _vbus_p->pVDevice[i])
			    {
					periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i);
					if (periph != NULL && periph->refcount >= 1)
					{
						hpt_printk(("Can not use disk used by OS!\n"));
	                    return -EINVAL;	
					}
					/* the Mounted Disk isn't delete */
				} 
			
			switch(pArray->VDeviceType)
			{
				case VD_RAID_1:
				case VD_RAID_5:
				{
					pSubArray = pArray;
loop:
					oldspl = lock_driver();
					if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) {
						unlock_driver(oldspl);
						return -EINVAL;
					}
					pSubArray->u.array.rf_auto_rebuild = 0;
					pSubArray->u.array.rf_abort_rebuild = 0;
					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pSubArray, DUPLICATE);
					unlock_driver(oldspl);
					break;
				}
				case VD_RAID_0:
					for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) 
						if(pArray->u.array.pMember[i] && mIsArray(pArray->u.array.pMember[i]) &&
						   (pArray->u.array.pMember[i]->u.array.rf_broken == 1))
						{
							  pSubArray = pArray->u.array.pMember[i];
							  goto loop;
						}
				default:
					return -EINVAL;
			}
			return orig_length;
		}
	}
	else if (length>=7 && strncmp(buffer, "verify ", 7)==0)
	{
		buffer+=7;
		length-=7;
        if (length>=6 && strncmp(buffer, "start ", 6)==0) 
		{
            buffer+=6;
		    length-=6;
            if (length>=1 && *buffer>='1') 
			{
				iarray = *buffer-'1';
				if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL;

				pArray = _vbus_p->pVDevice[iarray];
				if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
				
				if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
					return -EINVAL;

				if (!(pArray->u.array.rf_need_rebuild ||
					pArray->u.array.rf_rebuilding ||
					pArray->u.array.rf_verifying ||
					pArray->u.array.rf_initializing))
				{
					oldspl = lock_driver();
					pArray->u.array.RebuildSectors = 0;
					hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY);
					unlock_driver(oldspl);
				}
                return orig_length;
			}
		}
		else if (length>=5 && strncmp(buffer, "stop ", 5)==0)
		{
			buffer+=5;
		    length-=5;
            if (length>=1 && *buffer>='1') 
			{
				iarray = *buffer-'1';
				if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL;

				pArray = _vbus_p->pVDevice[iarray];
				if (!pArray || (pArray->vf_online == 0)) return -EINVAL;
				if(pArray->u.array.rf_verifying) 
				{
					oldspl = lock_driver();
				    pArray->u.array.rf_abort_rebuild = 1;
				    unlock_driver(oldspl);
				}
			    return orig_length;
			}
		}
	}
	else
#ifdef _RAID5N_
	if (length>=10 && strncmp(buffer, "writeback ", 10)==0) {
	    	buffer+=10;
		length-=10;
		if (length>=1 && *buffer>='0' && *buffer<='1') {
			_vbus_(r5.enable_write_back) = *buffer-'0';
			if (_vbus_(r5.enable_write_back))
				hpt_printk(("RAID5 write back enabled"));
			return orig_length;
		}
	}
	else
#endif
#endif
	if (0) {} /* just to compile */
#ifdef DEBUG
	else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) {
	    	buffer+=9;
		length-=9;
		if (length>=1 && *buffer>='0' && *buffer<='3') {
			hpt_dbg_level = *buffer-'0';
			return orig_length;
		}
	}
	else if (length>=8 && strncmp(buffer, "disable ", 8)==0) {
		/* TO DO */
	}
#endif

	return -EINVAL;
}
Ejemplo n.º 2
0
int Kernel_DeviceIoControl(_VBUS_ARG
							DWORD dwIoControlCode,       	/* operation control code */
							PVOID lpInBuffer,            	/* input data buffer */
							DWORD nInBufferSize,         	/* size of input data buffer */
							PVOID lpOutBuffer,           	/* output data buffer */
							DWORD nOutBufferSize,        	/* size of output data buffer */
							PDWORD lpBytesReturned      	/* byte count */
						)
{
	IAL_ADAPTER_T *pAdapter;

	switch(dwIoControlCode)	{
		case HPT_IOCTL_DELETE_ARRAY:
		{
			DEVICEID idArray;
			int iSuccess;			
	        int i;
			PVDevice pArray;
			PVBus _vbus_p;
			struct cam_periph *periph = NULL;

			if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1;
			if (nOutBufferSize!=sizeof(int)) return -1;
			idArray = *(DEVICEID *)lpInBuffer;

			pArray = ID_TO_VDEV(idArray);

			if((idArray == 0) || check_VDevice_valid(pArray))	
		       	return -1;
		
        	if(!mIsArray(pArray))
			return -1;

			_vbus_p=pArray->pVBus;
			pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;

	        for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) {
				if(pArray == _vbus_p->pVDevice[i])
				{
					periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i);
					if (periph != NULL && periph->refcount >= 1)
					{
						hpt_printk(("Can not delete a mounted device.\n"));
	                    return -1;	
					}
				}
				/* the Mounted Disk isn't delete */
			} 

			iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1));

			*(int*)lpOutBuffer = iSuccess;

			if(iSuccess != 0)
				return -1;
			break;
		}

		case HPT_IOCTL_GET_EVENT:
		{
			PHPT_EVENT pInfo;

			if (nInBufferSize!=0) return -1;
			if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1;

			pInfo = (PHPT_EVENT)lpOutBuffer;

			if (hpt_get_event(pInfo)!=0)
				return -1;
		}
		break;

		case HPT_IOCTL_SET_ARRAY_STATE:
		{
			DEVICEID idArray;
			DWORD state;

			if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1;
			if (nOutBufferSize!=0) return -1;

			idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray;
			state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state;

			if(hpt_set_array_state(idArray, state)!=0)
				return -1;
		}
		break;

		case HPT_IOCTL_RESCAN_DEVICES:
		{
			if (nInBufferSize!=0) return -1;
			if (nOutBufferSize!=0) return -1;

#ifndef FOR_DEMO
			/* stop buzzer if user perform rescan */
			for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
				if (pAdapter->beeping) {
					pAdapter->beeping = 0;
					BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
				}
			}
#endif
		}
		break;

		default:
		{
			PVDevice pVDev;

			switch(dwIoControlCode) {
			/* read-only ioctl functions can be called directly. */
			case HPT_IOCTL_GET_VERSION:
			case HPT_IOCTL_GET_CONTROLLER_IDS:
			case HPT_IOCTL_GET_CONTROLLER_COUNT:
			case HPT_IOCTL_GET_CONTROLLER_INFO:
			case HPT_IOCTL_GET_CHANNEL_INFO:
			case HPT_IOCTL_GET_LOGICAL_DEVICES:
			case HPT_IOCTL_GET_DEVICE_INFO:
			case HPT_IOCTL_GET_DEVICE_INFO_V2:				
			case HPT_IOCTL_GET_EVENT:
			case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
				if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 
					lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1;
				break;

			default:
				/* 
				 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 
				 * wrong for second controller. 
				 */
				switch(dwIoControlCode) {
				case HPT_IOCTL_CREATE_ARRAY:
					pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
				case HPT_IOCTL_CREATE_ARRAY_V2:
					pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
				case HPT_IOCTL_SET_ARRAY_INFO:
					pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
				case HPT_IOCTL_SET_DEVICE_INFO:
					pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
				case HPT_IOCTL_SET_DEVICE_INFO_V2:
					pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
				case HPT_IOCTL_SET_BOOT_MARK:
				case HPT_IOCTL_ADD_SPARE_DISK:
				case HPT_IOCTL_REMOVE_SPARE_DISK:
					pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break;
				case HPT_IOCTL_ADD_DISK_TO_ARRAY:
					pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break;
				default:
					pVDev = 0;
				}
				
				if (pVDev && !check_VDevice_valid(pVDev)){
					_vbus_p = pVDev->pVBus;

					pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt;
					/* 
					 * create_array, and other functions can't be executed while channel is 
					 * perform I/O commands. Wait until driver is idle.
					 */
					lock_driver_idle(pAdapter);
					if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 
						lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) {
						mtx_unlock(&pAdapter->lock);
						return -1;
					}
					mtx_unlock(&pAdapter->lock);
				}
				else
					return -1;
				break;
			}
			
#ifdef SUPPORT_ARRAY
			switch(dwIoControlCode)
			{
				case HPT_IOCTL_CREATE_ARRAY:
				{
					pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
					mtx_lock(&pAdapter->lock);
                    if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE)
				    {
						  (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
					}
					else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT)
				    {
                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
					}
					else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY)
				    {
                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
					}
					mtx_unlock(&pAdapter->lock);
                    break;
				}


				case HPT_IOCTL_CREATE_ARRAY_V2:
				{
					pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
					mtx_lock(&pAdapter->lock);
				             if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
						  (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
				                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
					} else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
				                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
					} else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
				                          hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
					}
					mtx_unlock(&pAdapter->lock);
					break;
				}
				case HPT_IOCTL_ADD_DISK_TO_ARRAY:
				{
					PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
					pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt;
					if(pArray->u.array.rf_rebuilding == 0)
					{		
						mtx_lock(&pAdapter->lock);
						pArray->u.array.rf_auto_rebuild = 0;
						pArray->u.array.rf_abort_rebuild = 0;
						hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE);
						while (!pArray->u.array.rf_rebuilding)
						{
							if (mtx_sleep(pArray, &pAdapter->lock, 0, "hptwait", hz * 3) != 0)
								break;
						}
						mtx_unlock(&pAdapter->lock);
					}
					break;
				}
			}
#endif
            return 0;
		}
	}

	if (lpBytesReturned)
		*lpBytesReturned = nOutBufferSize;
	return 0;
}