示例#1
0
command_t
makeBaseCommand(command_t command, char *input, char *output)
{
  if (!command) {
    command = AllocateCommand();
  }

  command->input = input;
  command->output = output;

  return command;
}
示例#2
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
IOReturn
SATSMARTUserClient::ReadDataThresholds (UInt32 * dataOut,
                                        IOByteCount * outputSize)
{
    
    IOReturn status  = kIOReturnSuccess;
    IOSATCommand *                  command = NULL;
    IOMemoryDescriptor *    buffer  = NULL;
    DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__);
    
    if (!dataOut || !outputSize || *outputSize != sizeof ( ATASMARTDataThresholds ) ) {
        return kIOReturnBadArgument;
    }
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseProvider;
        
    }
    
    buffer = IOMemoryDescriptor::withAddress(dataOut, sizeof ( ATASMARTDataThresholds ), kIODirectionIn);
    
    if ( buffer == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseCommand;
        
    }
    
    status = buffer->prepare ( );
    if ( status != kIOReturnSuccess )
    {
        
        goto ReleaseBuffer;
        
    }
    
    command->setBuffer                      ( buffer );
    command->setByteCount           ( sizeof ( ATASMARTDataThresholds ) );
    command->setFeatures            ( kFeaturesRegisterReadDataThresholds );
    command->setOpcode                      ( kATAFnExecIO );
    command->setTimeoutMS           ( kATAThirtySecondTimeoutInMS );
    command->setCylLo                       ( kSMARTMagicCylinderLoValue );
    command->setCylHi                       ( kSMARTMagicCylinderHiValue );
    command->setCommand                     ( kATAcmdSMART );
    command->setFlags                       ( mATAFlagIORead );
    
    status = SendSMARTCommand ( command );
    if ( status == kIOReturnIOError )
    {
        
        if ( command->getEndErrorReg ( ) & 0x04 )
        {
            
            ERROR_LOG ( "ReadDataThresholds unsupported\n" );
            status = kIOReturnUnsupported;
            
        }
        
        if ( command->getEndErrorReg ( ) & 0x10 )
        {
            
            ERROR_LOG ( "ReadDataThresholds Not readable\n" );
            status = kIOReturnNotReadable;
            
        }
        
    }
    
    *outputSize = buffer->getLength();
    
    buffer->complete ( );
    
    
ReleaseBuffer:
    
    
    buffer->release ( );
    buffer = NULL;
    
    
ReleaseCommand:
    
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
IOReturn
SATSMARTUserClient::ExecuteOfflineImmediate ( UInt32 extendedTest )
{
    
    IOReturn status  = kIOReturnSuccess;
    IOSATCommand *  command = NULL;
    DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__);
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseProvider;
        
    }
    
    command->setFeatures            ( kFeaturesRegisterExecuteOfflineImmed );
    command->setOpcode                      ( kATAFnExecIO );
    command->setTimeoutMS           ( kATAThirtySecondTimeoutInMS );
    command->setSectorNumber        ( ( extendedTest == 0 ) ? 0x01 : 0x02 );
    command->setCylLo                       ( kSMARTMagicCylinderLoValue );
    command->setCylHi                       ( kSMARTMagicCylinderHiValue );
    command->setCommand                     ( kATAcmdSMART );
    
    status = SendSMARTCommand ( command );
    if ( status == kIOReturnIOError )
    {
        
        if ( command->getEndErrorReg ( ) & 0x04 )
        {
            
            ERROR_LOG ( "Execute Offline Immediate unsupported\n" );
            status = kIOReturnUnsupported;
            
        }
        
    }
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
IOReturn
SATSMARTUserClient::ReturnStatus ( UInt32 * exceededCondition )
{
    
    IOReturn status  = kIOReturnSuccess;
    IOSATCommand *  command = NULL;
    UInt8 lbaMid  = kSMARTMagicCylinderLoValue;
    UInt8 lbaHigh = kSMARTMagicCylinderHiValue;
    DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__);
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseProvider;
        
    }
    
    command->setFeatures    ( kFeaturesRegisterReturnStatus );
    command->setOpcode              ( kATAFnExecIO );
    command->setTimeoutMS   ( kATAThirtySecondTimeoutInMS );
    command->setCylLo               ( lbaMid );
    command->setCylHi               ( lbaHigh );
    command->setCommand             ( kATAcmdSMART );
    command->setRegMask             ( ( ataRegMask ) ( mATACylinderHiValid | mATACylinderLoValid ) );
    command->setFlags               ( mATAFlagTFAccessResult );
    
    status = SendSMARTCommand ( command );
    
    lbaMid  = command->getCylLo ( );
    lbaHigh = command->getCylHi ( );
    
    if ( status == kIOReturnSuccess )
    {
        
        // Check if threshold exceeded
        if ( ( lbaMid == kSMARTReturnStatusValidLoValue ) &&
            ( lbaHigh == kSMARTReturnStatusValidHiValue ) )
        {
            *exceededCondition = 1;
        }
        
        else
        {
            *exceededCondition = 0;
        }
        
    }
    
    if ( status == kIOReturnIOError )
    {
        
        if ( command->getEndErrorReg ( ) & 0x04 )
        {
            
            ERROR_LOG ( "Return Status unsupported\n" );
            status = kIOReturnUnsupported;
            
        }
        
    }
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
IOReturn
SATSMARTUserClient::EnableDisableAutoSave ( UInt32 enable )
{
    
    IOReturn status = kIOReturnSuccess;
    IOSATCommand *  command;
    DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__);
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseProvider;
        
    }
    
    if ( enable == 0 )
    {
        
        // They want to disable SMART autosave operations.
        command->setSectorCount ( kSMARTAutoSaveDisable );
        
    }
    
    else
    {
        
        // They want to enable SMART autosave operations.
        command->setSectorCount ( kSMARTAutoSaveEnable );
        
    }
    
    command->setFeatures    ( kFeaturesRegisterEnableDisableAutoSave );
    command->setOpcode              ( kATAFnExecIO );
    command->setTimeoutMS   ( kATAThirtySecondTimeoutInMS );
    command->setCylLo               ( kSMARTMagicCylinderLoValue );
    command->setCylHi               ( kSMARTMagicCylinderHiValue );
    command->setCommand             ( kATAcmdSMART );
    
    status = SendSMARTCommand ( command );
    if ( status == kIOReturnIOError )
    {
        
        if ( command->getEndErrorReg ( ) & 0x04 )
        {
            
            ERROR_LOG ( "Enable/Disable autosave unsupported\n" );
            status = kIOReturnUnsupported;
            
        }
        
    }
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
IOReturn
SATSMARTUserClient::GetIdentifyData (UInt32 * dataOut,
				     IOByteCount * outputSize)
{
    
    IOReturn status                  = kIOReturnSuccess;
    IOSATCommand *                          command                 = NULL;
    IOMemoryDescriptor *      buffer                  = NULL;
    DEBUG_LOG("%s[%p]::%s %p(%ld)\n", getClassName(), this, __FUNCTION__, dataOut, (long)(outputSize));
    
    if (!dataOut || !outputSize || *outputSize < kATADefaultSectorSize ) {
        return kIOReturnBadArgument;
    }
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseProvider;
        
    }
    
    buffer = IOMemoryDescriptor::withAddress(dataOut, kATADefaultSectorSize, kIODirectionIn);
    if ( buffer == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseCommand;
        
    }
    
    status = buffer->prepare ( );
    if ( status != kIOReturnSuccess )
    {
        
        goto ReleaseBuffer;
        
    }
    
    command->setBuffer                              ( buffer );
    command->setByteCount                   ( kATADefaultSectorSize );
    command->setTransferChunkSize   ( kATADefaultSectorSize );
    command->setOpcode                              ( kATAFnExecIO );
    command->setTimeoutMS                   ( kATAThirtySecondTimeoutInMS );
    command->setCommand                             ( kATAcmdDriveIdentify );
    command->setFlags                               ( mATAFlagIORead );
    command->setRegMask                             ( ( ataRegMask ) ( mATAErrFeaturesValid | mATAStatusCmdValid ) );
    
    status = SendSMARTCommand ( command );
    if ( status == kIOReturnSuccess )
    {
        
#if defined(__BIG_ENDIAN__)
        UInt8 *         bufferToCopy = identifyDataPtr;
        
        // The identify device info needs to be byte-swapped on big-endian (ppc)
        // systems becuase it is data that is produced by the drive, read across a
        // 16-bit little-endian PCI interface, directly into a big-endian system.
        // Regular data doesn't need to be byte-swapped because it is written and
        // read from the host and is intrinsically byte-order correct.
        
        IOByteCount index;
        UInt8 temp;
        UInt8 *                 firstBytePtr;
        UInt8 *                 identifyDataPtr = ( UInt8 * )dataOut;
        
        for ( index = 0; index < buffer->getLength ( ); index += 2 )
        {
            
            firstBytePtr            = identifyDataPtr;                          // save pointer
            temp                            = *identifyDataPtr++;               // Save Byte0, point to Byte1
            *firstBytePtr           = *identifyDataPtr;                         // Byte0 = Byte1
            *identifyDataPtr++      = temp;                                             // Byte1 = Byte0
            
        }
        
#endif
        
        *outputSize = buffer->getLength ( );
        DEBUG_LOG("%s[%p]::%s cpy %p %p\n", getClassName(), this,  __FUNCTION__, (void*)*outputSize, (void*)buffer->getLength());
    }
    
    
ReleaseBufferPrepared:
    
    buffer->complete ( );
    
    
ReleaseBuffer:
    
    
    buffer->release ( );
    buffer = NULL;
    
    
ReleaseCommand:
    
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %x\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
IOReturn
SATSMARTUserClient::WriteLogAtAddress ( ATASMARTWriteLogStruct *        writeLogData,
                                       UInt32 inStructSize )
{
    
    IOReturn status                  = kIOReturnSuccess;
    IOSATCommand *                  command                 = NULL;
    IOMemoryDescriptor *    buffer                  = NULL;
    DEBUG_LOG("%s[%p]::%s\n", getClassName(), this, __FUNCTION__);
    
    if ( inStructSize != sizeof ( ATASMARTWriteLogStruct ) || writeLogData->numSectors > 16 || writeLogData->data_length > kSATMaxDataSize) {
        return kIOReturnBadArgument;
    }
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        status = kIOReturnNoResources;
        goto ReleaseProvider;
    }
    
    //buffer = IOMemoryDescriptor::withAddress(writeLogData->buffer, writeLogData->bufferSize, kIODirectionOut);
    buffer = IOMemoryDescriptor::withAddressRange(writeLogData->data_pointer, writeLogData->data_length, kIODirectionOut, fTask);
    
    if ( buffer == NULL )
    {
        status = kIOReturnVMError;
        goto ReleaseCommand;
    }
    
    status = buffer->prepare ( );
    if ( status != kIOReturnSuccess )
    {
        goto ReleaseBuffer;
    }
    
    command->setBuffer                      ( buffer );
    command->setByteCount           ( writeLogData->data_length );
    command->setFeatures            ( kFeaturesRegisterWriteLogAtAddress );
    command->setOpcode                      ( kATAFnExecIO );
    command->setTimeoutMS           ( kATAThirtySecondTimeoutInMS );
    command->setSectorCount         ( writeLogData->numSectors );
    command->setSectorNumber        ( writeLogData->logAddress );
    command->setCylLo                       ( kSMARTMagicCylinderLoValue );
    command->setCylHi                       ( kSMARTMagicCylinderHiValue );
    command->setCommand                     ( kATAcmdSMART );
    command->setFlags                       ( mATAFlagIOWrite );
    
    status = SendSMARTCommand ( command );
    if ( status == kIOReturnIOError )
    {
        
        if ( command->getEndErrorReg ( ) & 0x04 )
        {
            
            ERROR_LOG ( "WriteLogAtAddress %d unsupported\n", writeLogData->logAddress );
            status = kIOReturnUnsupported;
            
        }
        
        if ( command->getEndErrorReg ( ) & 0x10 )
        {
            
            ERROR_LOG ( "WriteLogAtAddress %d unwriteable\n", writeLogData->logAddress );
            status = kIOReturnNotWritable;
            
        }
        
    }
    
    buffer->complete ( );
    
    
ReleaseBuffer:
    
    
    buffer->release ( );
    buffer = NULL;
    
    
ReleaseCommand:
    
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
IOReturn
SATSMARTUserClient::ReadLogAtAddress ( ATASMARTReadLogStruct * structIn,
                                      void * structOut,
                                      IOByteCount inStructSize,
                                      IOByteCount *outStructSize)
{
    
    IOReturn status                  = kIOReturnSuccess;
    IOSATCommand *                  command                 = NULL;
    IOMemoryDescriptor *    buffer                  = NULL;
    DEBUG_LOG("%s[%p]::%s %p(%ld) %p(%ld)\n", getClassName(), this, __FUNCTION__, structIn, (long)inStructSize, structOut, (long)(outStructSize));
    
    if ( inStructSize != sizeof ( ATASMARTReadLogStruct )  || !outStructSize || *outStructSize < 1) {
        return kIOReturnBadArgument;
    }
    
    fOutstandingCommands++;
    
    if ( isInactive ( ) )
    {
        
        status = kIOReturnNoDevice;
        goto ErrorExit;
        
    }
    
    fProvider->retain ( );
    
    command = AllocateCommand ( );
    if ( command == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseProvider;
        
    }
    
    buffer = IOMemoryDescriptor::withAddress (structOut,  *outStructSize, kIODirectionIn);
    if ( buffer == NULL )
    {
        
        status = kIOReturnNoResources;
        goto ReleaseCommand;
        
    }
    
    status = buffer->prepare ( );
    DEBUG_LOG("%s[%p]::%s status %x\n", getClassName(), this, __FUNCTION__, status);
    if ( status != kIOReturnSuccess )
    {
        
        goto ReleaseBuffer;
        
    }
    
    command->setBuffer                      ( buffer );
    command->setByteCount           ( buffer->getLength());
    command->setFeatures            ( kFeaturesRegisterReadLogAtAddress );
    command->setOpcode                      ( kATAFnExecIO );
    command->setTimeoutMS           ( kATAThirtySecondTimeoutInMS );
    command->setSectorCount         ( structIn->numSectors );
    command->setSectorNumber        ( structIn->logAddress );
    command->setCylLo                       ( kSMARTMagicCylinderLoValue );
    command->setCylHi                       ( kSMARTMagicCylinderHiValue );
    command->setCommand                     ( kATAcmdSMART );
    command->setFlags                       ( mATAFlagIORead );
    
    status = SendSMARTCommand ( command );
    if ( status == kIOReturnIOError )
    {
        
        if ( command->getEndErrorReg ( ) & 0x04 )
        {
            
            ERROR_LOG ( "ReadLogAtAddress %d unsupported\n", structIn->logAddress );
            status = kIOReturnUnsupported;
            
        }
        
        if ( command->getEndErrorReg ( ) & 0x10 )
        {
            
            ERROR_LOG ( "ReadLogAtAddress %d unreadable\n", structIn->logAddress );
            status = kIOReturnNotReadable;
            
        }
        
    }
    
    *outStructSize = buffer->getLength();
    
    buffer->complete ( );
    
    
    
ReleaseBuffer:
    
    
    buffer->release ( );
    buffer = NULL;
    
    
ReleaseCommand:
    
    
    DeallocateCommand ( command );
    command = NULL;
    
    
ReleaseProvider:
    
    
    fProvider->release ( );
    
    
ErrorExit:
    
    
    fOutstandingCommands--;
    
    DEBUG_LOG("%s[%p]::%s result %d\n", getClassName(), this,  __FUNCTION__, status);
    return status;
    
}
示例#10
0
command_t
makeCommandStreamUtil(int (*get_next_byte) (void *),
		      void *get_next_byte_argument,
		      STATE *state)
{
  char **tokenPTR = checked_malloc(sizeof(char**));
  char *token = NULL;
  int len = 0;
  TOKENTYPE type;
  command_t command = NULL;
  char *input = NULL, *output = NULL;

  type = readNextToken(tokenPTR, &len, get_next_byte, get_next_byte_argument);
  if (type == NOT_DEFINED) {
    free(tokenPTR);
    return NULL;
  } else if (type == O_PAR) {
    token = "(";
  } else {
    token = *tokenPTR;
  }

  command = AllocateCommand();
  if (!command) {
    return NULL;
  }


  if (!strncmp(token, "then", 4)) {
    if (!(pop() == IF)) {
      printErr();
    }
    push(THEN);
    *state = THEN;
    goto ret_null;
  } else if (!strncmp(token, "done", 4)) {
    if (!(pop() == DO)) {
      printErr();
    }
    *state = DONE;
    CScount--;
    goto ret_null;
  } else if (!strncmp(token, "do", 4)) {
    STATE tmp = pop();
    if (!((tmp == WHILE) || (tmp == UNTIL))) {
      printErr();
    }
    push(DO);
    *state = DO;
    goto ret_null;
  } else if (!strncmp(token, "else", 4)) {
    if (!(pop() == THEN)) {
      printErr();
    }
    push(ELSE);
    *state = ELSE;
    goto ret_null;
  } else if (!strncmp(token, "fi", 4)) {
    STATE tmp = pop();
    if (!((tmp == THEN) || (tmp == ELSE))) {
      printErr();
    }
    CScount--;
    *state = FI;
    goto ret_null;
  } else if (!strncmp(token, ")", 1)) {
    CScount--;
    *state = CLOSE_PAR;
    goto ret_null;
  } else if (!strncmp(token, "if", 2)) {
    push(IF);
    CScount++;
    command = makeCommand(command, NULL, IF_COMMAND, input, output);
    free(tokenPTR);
    command->u.command[0] = makeCommandStreamUtil(get_next_byte,
						  get_next_byte_argument,
						  state);
    while (*state != THEN) {
      if (!makeCommandStreamUtil(get_next_byte,
				 get_next_byte_argument,
				 state)) {
	type = NOT_DEFINED;
	break;
      }
    }

    if (type == NOT_DEFINED && *state != THEN) {
      return NULL;
    }

    command->u.command[1] = makeCommandStreamUtil(get_next_byte,
						  get_next_byte_argument,
						  state);
    if (*state != ELSE && *state != FI) {
      // HANDLE error;
      ;
    } else if (*state == ELSE || (*state == FI && CScount)) {
	command->u.command[2] = makeCommandStreamUtil(get_next_byte,
						      get_next_byte_argument,
						      state);
    } else {
      command->u.command[2] = NULL;
    }
  } else if (!strncmp(token, "while", 5)) {
    push(WHILE);
    (CScount)++;
    command = makeCommand(command, NULL, WHILE_COMMAND, input, output);
    free(tokenPTR);
    command->u.command[0] = makeCommandStreamUtil(get_next_byte,
						  get_next_byte_argument,
						  state);
    if (*state != DO) {
      // Handle Error
      ;
    }
    command->u.command[1] = makeCommandStreamUtil(get_next_byte,
						  get_next_byte_argument,
						  state);
    if (*state != DONE) {
      // HANDLE error;
      ;
    } else if (*state == DONE) {
      if (checkRedirection(get_next_byte, get_next_byte_argument)) {
	fillRedirectionOperands(&command->input, &command->output,
				get_next_byte, get_next_byte_argument);
      }

      command->u.command[2] = makeCommandStreamUtil(get_next_byte,
      						    get_next_byte_argument,
      						    state);
      /* if (command->u.command[2]) { */
      /* 	command_t newCommand = makeCommand(NULL, NULL, SEQUENCE_COMMAND, */
      /* 					   NULL, NULL); */
      /* 	newCommand->u.command[0] = command->u.command[1]; */
      /* 	newCommand->u.command[1] = command->u.command[2]; */
      /* 	command->u.command[1] = newCommand; */
      /* 	command->u.command[2] = NULL; */
      /* } */

    } else {
      command->u.command[2] = NULL;
    }    
  } else if (!strncmp(token, "until", 5)) {
    push(UNTIL);
    (CScount)++;
    command = makeCommand(command, NULL, UNTIL_COMMAND, input, output);
    free(tokenPTR);
    command->u.command[0] = makeCommandStreamUtil(get_next_byte,
						  get_next_byte_argument,
						  state);
    if (*state != DO) {
      // Handle Error
      ;
    }
    command->u.command[1] = makeCommandStreamUtil(get_next_byte,
						  get_next_byte_argument,
						  state);
    if (*state != DONE) {
      // HANDLE error;
      ;
    } else if (*state == DONE) {
      if (checkRedirection(get_next_byte, get_next_byte_argument)) {
	fillRedirectionOperands(&command->input, &command->output,
				get_next_byte, get_next_byte_argument);
      }
      command->u.command[2] = makeCommandStreamUtil(get_next_byte,
      						    get_next_byte_argument,
      						    state);
      /* if (command->u.command[2]) { */
      /* 	command_t newCommand = makeCommand(NULL, NULL, SEQUENCE_COMMAND, */
      /* 					   NULL, NULL); */
      /* 	newCommand->u.command[0] = command->u.command[1]; */
      /* 	newCommand->u.command[1] = command->u.command[2]; */
      /* 	command->u.command[1] = newCommand; */
      /* 	command->u.command[2] = NULL; */
      /* } */
    } else {
      command->u.command[2] = NULL;
    }    

  } else if (!strncmp(token, "(", 1)) {
    CScount++;
    command = makeCommand(command, NULL, SUBSHELL_COMMAND, input, output);
    free(tokenPTR);
    command->u.command[0] =  makeCommandStreamUtil(get_next_byte,
              get_next_byte_argument,
              state);
    if (*state != CLOSE_PAR) {
      // Handle Error
    } else if (*state == CLOSE_PAR && CScount) {
      command->u.command[0] = makeCommandStreamUtil(get_next_byte,
                get_next_byte_argument,
                state);
    } 
  } else {
    // SIMPLE_COMMAND
    while (1) {
      STATE prevState = *state;
      if (isKeyWordUpdate(token, state) && (prevState == COMMAND)) {
         	removeWhiteSpace(token);
        	command = makeSimpleCommand(command, tokenPTR, input, output);
        	break;
      }
      if (type == REDIRECTION1 || type == REDIRECTION2) {
	type = fillRedirectionOperands(&input,
				       &output,
				       get_next_byte,
				       get_next_byte_argument);

	//	command = makeSimpleCommand(command, tokenPTR, input, output);
	//        break;
	//	type = readNextToken(tokenPTR, &len, get_next_byte, get_next_byte_argument);
      } else if (type == SPACE) {
	appendChar(token, ' ');
	type = readNextToken(tokenPTR, &len, get_next_byte, get_next_byte_argument);
      } else if (type == NEWLINE && !CScount) {
      	command = makeSimpleCommand(command, tokenPTR, input, output);
      	break;
      } else if (type == PIPE || type == SEMICOLON || type == NEWLINE) {
	removeWhiteSpace(token);
	if (((type == PIPE) || (type == SEMICOLON)) && !strlen(token)) {
	  printErr();
	}
	command = makeCommand(command, tokenPTR, 
			      type == PIPE ? PIPE_COMMAND : SEQUENCE_COMMAND,
			      input, output);
	command->u.command[1] = makeCommandStreamUtil(get_next_byte,
						      get_next_byte_argument,
						      state);
	if (!command->u.command[1]) {
	  command = convertToSimple(command);
	}
	break;
      }
      *state = COMMAND;
    }
  }

  return command;
ret_null:
  free(command);
  free(tokenPTR);
  return NULL;
}