示例#1
0
void HPTLIBAPI
ioctl_ReportEvent(UCHAR event, PVOID param)
{
	HPT_EVENT e;
	ZeroMemory(&e, sizeof(e));
	e.EventType = event;
	switch(event)
	{
		case ET_INITIALIZE_ABORTED:
		case ET_INITIALIZE_FAILED:
			memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME);
		case ET_INITIALIZE_STARTED:
		case ET_INITIALIZE_FINISHED:

		case ET_REBUILD_STARTED:
		case ET_REBUILD_ABORTED:
		case ET_REBUILD_FAILED:
		case ET_REBUILD_FINISHED:
		
		case ET_VERIFY_STARTED:
		case ET_VERIFY_ABORTED:
		case ET_VERIFY_FAILED:
		case ET_VERIFY_FINISHED:
		case ET_VERIFY_DATA_ERROR:

		case ET_SPARE_TOOK_OVER:
		case ET_DEVICE_REMOVED:
		case ET_DEVICE_PLUGGED:
		case ET_DEVICE_ERROR:
			e.DeviceID = VDEV_TO_ID((PVDevice)param);
			break;

		default:
			break;
	}
	event_queue_add(&e);
	if (event==ET_DEVICE_REMOVED) {
		int controller, channel;
		get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel);
		hpt_printk(("Device removed: controller %d channel %d\n", controller, channel));
	}
	wakeup(param);
}
示例#2
0
文件: hptproc.c 项目: coyizumi/cs111
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;
}
示例#3
0
void
hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags)
{
    ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1);
    PCommand pCmd;
	UINT result;
	int needsync=0, retry=0, needdelete=0;
	void *buffer = NULL;

	_VBUS_INST(&pAdapter->VBus)

	if (pArray->u.array.rf_broken==1 ||
    	pArray->u.array.RebuildSectors>=capacity)
		return;

	mtx_lock(&pAdapter->lock);
	
	switch(flags)
	{
		case DUPLICATE:
		case REBUILD_PARITY:
			if(pArray->u.array.rf_rebuilding == 0)
			{
				pArray->u.array.rf_rebuilding = 1;
				hpt_printk(("Rebuilding started.\n"));
				ioctl_ReportEvent(ET_REBUILD_STARTED, pArray);
			}
			break;

		case INITIALIZE:
			if(pArray->u.array.rf_initializing == 0)
			{
				pArray->u.array.rf_initializing = 1;
				hpt_printk(("Initializing started.\n"));
				ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray);
			}
			break;

		case VERIFY:
			if(pArray->u.array.rf_verifying == 0)
			{
				pArray->u.array.rf_verifying = 1;
				hpt_printk(("Verifying started.\n"));
				ioctl_ReportEvent(ET_VERIFY_STARTED, pArray);
			}
			break;
	}
	
retry_cmd:
	pCmd = AllocateCommand(_VBUS_P0);
	HPT_ASSERT(pCmd);
	pCmd->cf_control = 1;
	End_Job = 0;

	if (pArray->VDeviceType==VD_RAID_1) 
	{
		#define MAX_REBUILD_SECTORS 0x40

		/* take care for discontinuous buffer in R1ControlSgl */
		buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT);
		if(!buffer) {
			FreeCommand(_VBUS_P pCmd);
			hpt_printk(("can't allocate rebuild buffer\n"));
			goto fail;
		}
		switch(flags) 
		{
			case DUPLICATE:
				pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD;
				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
				break;

			case VERIFY:
				pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY;
				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2;
				break;

			case INITIALIZE:
				pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 
				pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS;
				break;
		}

		pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors;

		if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors)
			pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors;

		pCmd->uCmd.R1Control.Buffer = buffer;
		pCmd->pfnBuildSgl = R1ControlSgl;
	}
	else if (pArray->VDeviceType==VD_RAID_5)
	{
		switch(flags)
		{
			case DUPLICATE:
			case REBUILD_PARITY:
				pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break;
			case VERIFY:
				pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break;
			case INITIALIZE:
				pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break;
		}
		pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift;
	}
	else
示例#4
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;
}