int smsa_vwrite( SMSA_VIRTUAL_ADDRESS addr, uint32_t len, unsigned char *buf )  {


	//all of the following variables are used so that we know
	//where the write should take place. These variables will
	//form a type of "bounds" for our write, and help us progress
	//through various loops so that the write can be completed
	SMSA_DRUM_ID drumStart, drumEnd, currentDrum;
	SMSA_BLOCK_ID blockStart, blockEnd, currentBlock;
	uint32_t byteStart, byteEnd, upperBound, lowerBound;
	

	unsigned char *temp;		//variable to hold the value at the current block
	unsigned char *cacheLine;
	int bufferIndex = 0;			//holds the current index of the buffer that we are reading from


	ERROR_SOURCE err = 0;		 	//holds return values of function calls to checkForErrors
       	
		
	//get the start and stop positions of the drum, block, and byte
	err = getDiskBlockParameters ( addr, len, &drumStart, &blockStart, &drumEnd, &blockEnd, &byteStart, &byteEnd );
	

	//current drum and block allow us to move through
	//the while loop. Set them to the starting positions
	currentDrum = drumStart;
	currentBlock = blockStart;
	
	if ( DEBUG )
		logMessage ( LOG_INFO_LEVEL,"Initialized currentDrum and currentBlock Initialized To drumStart %d, and blockStart %d", drumStart, blockStart );


	//since during the while loop below, the drumHead won't 
	//necessarily be set on the first run through, we must set
	//it here to ensure it is set to the correct position
	err = seekIfNeedTo ( currentDrum, currentBlock );	

	
	//this loop continues while we have not reached the end of (addr + len)
	//which is the place where the write will extend to. The conditions will
	//stop the loop, after the last block has been written too
	while( !( ( currentDrum == drumEnd && currentBlock == blockEnd+1 )
	    		|| ( currentDrum == drumEnd + 1 && currentBlock == 0 ) ) ) {
	
			
		//In order for the memory to be presevered through multiple calls of v
		//v_read/v_write, we must allocate the memory so that it remains on the stack
		//rather than vanishing when the function returns.		
		temp = (unsigned char*) malloc ( SMSA_BLOCK_SIZE * sizeof ( char ) );		
	
		if ( DEBUG )
			logMessage ( LOG_INFO_LEVEL, "Successfully Malloced [%d] Bytes of Data To temp", SMSA_BLOCK_SIZE*sizeof( char ) );
						
		//This is where we decide the specific bytes ( letters ) 
		//from the current block values that should be overwritten
		//this function sets the lowerBound and upperBound to the appropriate
		//values. 
		err = findMemCpyBounds ( drumStart, blockStart, byteStart, drumEnd, blockEnd, byteEnd, currentDrum, currentBlock, &lowerBound, &upperBound );
		

		//in order to handle a write, sometimes, we must
		//write only some of a given block. Therefore, we 
		//have to first read whats currently at the block
		//and then overwrite the part of that block that we 
		//need too using memcpy below. Don't want to waste
		//time reading if we are writing the entire block. If
		//we are writing the whole block, read will be skipped 
		if ( !( lowerBound == 0 && upperBound == SMSA_BLOCK_SIZE) ) {
			
			//check cache first	
			cacheLine = smsa_get_cache_line ( currentDrum, currentBlock );
					
			if ( cacheLine == NULL )  { //if not in cache perform read	
				
				//cache miss. read disk.
				err = readLowLevel ( temp );
				
				//performance stats
				disk_reads++;
			}
			else {			//otherwise copy the cache line into our temp 

				//Now cacheLine contains the block that we were looking for
				//so set temp equal to it
				temp = cacheLine;
		
				//performance stats	
				cache_hits++;
			}
		}
		
		//If we are writing only part of a block, then first we 
		//need to read whats at that block currently. Then we 
		//have to overwrite the intended bytes of what is currently
		//in the block. Which bytes must be overwritten is dependent
		//on findMemCpyBounds above. finally at the end, we write this 
		//new, partially modified, version of the block to the same address. 
		//If the whole block should be overwriten, the bounds will have 
		//been set to completely overwrite temp with buf.
		memcpy ( &temp[lowerBound], &buf[bufferIndex], upperBound - lowerBound );


		if ( DEBUG )
			logMessage ( LOG_INFO_LEVEL, "Memcpy ( temp[%d], buf[%d], %d )", bufferIndex, lowerBound, upperBound-lowerBound );
					
		//now that we have copied (upperBound-lowerBound) amount of
		//bytes into temp, we must make sure that we choose the correct
		//data to write to the block after this one. That means we need 
		//to increase the position that getting our data from to just 
		//after where we just took from.
		bufferIndex += upperBound - lowerBound;
			
		if ( DEBUG )
			logMessage ( LOG_INFO_LEVEL, "BufferIndex Set From [%d] to [%d]", bufferIndex-(upperBound-lowerBound), bufferIndex);

		//since the block was incremented in the previous 
		//smsa_operation (read) call, we need to set it back
		//to the desired write postion
		err = setBlockHead ( currentBlock );

		//in all scenarios we write temp back to the current block
		//location. If only part of the current block should be
		//overwritten, then temp will contain the partially
		//modified version. If all of the current block should
		//be overwritten, then temp will contain 255 characters
		//from the buffer
		err = writeLowLevel ( temp );
		
		//update the cache so that it contains our new block
		err = smsa_put_cache_line ( currentDrum, currentBlock, temp );

		//check for errors during the loop, and at the end. This will allow us
		//to find where the errors occur, since were checking throughout the 
		//entire process. However, we don't want to stop the program unless
		//a error was found. So, we will return 1, only if checkForErrors results in 
		//one
		if ( checkForErrors ( err, "_vwrite", addr, len, drumStart, blockStart, currentDrum, currentBlock, drumEnd, blockEnd ) )
			return 1; 
		
		
		//increment the block
		currentBlock++;

		//if the current block is out of the bounds for the 
		//disk size, then set the current block to zero, 
		//and start reading the next disk
		if ( currentBlock == 256 ) {
			currentDrum++;
			currentBlock = 0;
		}

		//make sure the drum and block heads are properly set
		err = seekIfNeedTo( currentDrum, currentBlock );

			
	}

	
	//if checkForErrors finds that err is non-zero, it will return 1. 
	//see smsa_driver.h for error enum definition
	return ( checkForErrors ( err, "_vmount", DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, 
						DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE ) );

}
Example #2
0
int smsa_vread( SMSA_VIRTUAL_ADDRESS addr, uint32_t len, unsigned char *buf ) {
    /* First check if the length is 0 */
    // Write nothing and return if so
    if(len == 0) {
        return 0;
    }

    /* Initialize variables */
    int i = 0;
    int err = 0;
    int read_bytes = 0;
    uint32_t offset;
    SMSA_DRUM_ID drum;
    SMSA_BLOCK_ID block;
    SMSA_BLOCK_ID block_orig;
    unsigned char *smsa_vread_buffer = NULL;

    drum = find_drum(addr);
    block = find_block(addr);
    block_orig = block;
    offset = addr & 0xff;
    seek_if_i_must(drum, block);

    // Loop to iterate through blocks
    do {
        /* Bounds checking */
         // Check if drum is in bounds
        if( (drum > SMSA_DISK_ARRAY_SIZE) || (drum < 0) ) {
            logMessage( LOG_ERROR_LEVEL, "The drum is out of bounds [%d]\n", drum );
            return -1;
        }

        // Check if block is in bounds
        if( (block > SMSA_MAX_BLOCK_ID) || (block < 0) ) {
            logMessage( LOG_ERROR_LEVEL, "The block is out of bounds [%d]\n", block );
            return -1;
        }

        /* Is it the original block? */
        // Yes  - begin reading from offset
        // No   - begin reading from beginning
        if( block  == block_orig ) {
            i = offset;
        } else { i = 0; }

        /* Is it last block in the drum? */
        if( block == SMSA_BLOCK_SIZE) {
            // Seek to the beginning of next drum
            block=0;
            curBlock = 0;
            drum++;
            seek_if_i_must(drum, block);
        }

        /* Is it in the cache? */
        logMessage(LOG_INFO_LEVEL, "Asking cache at: drum[%d]\tblock[%d]\n", drum, block);
        smsa_vread_buffer = smsa_get_cache_line(drum, block);
        // If yes
        if(smsa_vread_buffer != NULL) {
            // Read into buf
            do {
                buf[read_bytes] = smsa_vread_buffer[i];
                read_bytes++;
                i++;
            } while( (i<SMSA_BLOCK_SIZE) && (read_bytes<len) );
            // seek next block
            block++;
            curBlock++;
            smsa_operation( SEEK_BLOCK, NULL );
        }
        // If no
        else {
            // Allocate temp buffer
            smsa_vread_buffer = (unsigned char *) malloc(SMSA_BLOCK_SIZE * sizeof(unsigned char));
            // Read from disk
            smsa_operation( DISK_READ, smsa_vread_buffer );
            // Put into buf bit by bit
            do {
                buf[read_bytes] = smsa_vread_buffer[i];
                read_bytes++;
                i++;
            } while( (i<SMSA_BLOCK_SIZE) && (read_bytes<len) );
            // Add temp buffer into cache line
            logMessage(LOG_INFO_LEVEL, "Finding a place to put the cache entry...\n");
            err = smsa_put_cache_line(drum, block, smsa_vread_buffer);
            block++;
            curBlock++;
        }
        if(err) {
            logMessage(LOG_ERROR_LEVEL, "Something bad happened in the cache :/\n");
            return -1;
        }
    } while(read_bytes<len);

    return 0;
}
int smsa_vread( SMSA_VIRTUAL_ADDRESS addr, uint32_t len, unsigned char *buf ) {
	

	//all of the following variables are used so that we know
	//where the read should take place. These variables will
	//form a type of "bounds" for our read, and help us progress
	//through various loops so that the write can be completed
	SMSA_DRUM_ID drumStart, drumEnd, currentDrum;
	SMSA_BLOCK_ID blockStart, blockEnd, currentBlock;
	uint32_t byteStart, byteEnd, upperBound, lowerBound;


	unsigned char *temp;	
	unsigned char *cacheLine;		//variable to hold the value at the current block
	
	int bufferIndex = 0;			//holds the current index of the buffer that we are reading from
	
	ERROR_SOURCE err = 0;		 	//holds return values of function calls to checkForErrors	
	

	//get the start and stop positions of the drum, block and byte
	err = getDiskBlockParameters ( addr, len, &drumStart, &blockStart, &drumEnd, &blockEnd, &byteStart, &byteEnd );

	//current drum and block allow us to move through
	//the while loop. Set them to the starting positions
	currentDrum = drumStart;
	currentBlock = blockStart;

	if ( DEBUG )
		logMessage ( LOG_INFO_LEVEL,"Initialized currentDrum and currentBlock Tnitialized To drumStart %d, and blockStart %d", drumStart, blockStart );


	//since during the while loop below, the drumHead won't 
	//necessarily be set on the first run through, we must set
	//it here to ensure it is set to the correct position
	err = seekIfNeedTo ( currentDrum, currentBlock );


	//this loop continues while we have not reached the end of (addr + len)
	//which is the place where the read will extend to. The conditions will
	//stop the loop, after the last block has been read
	while( !( ( currentDrum == drumEnd && currentBlock == blockEnd+1 )
	    		|| ( currentDrum == drumEnd + 1 && currentBlock == 0 ) ) ) {


		//In order for the memory to be presevered through multiple calls of v
		//v_read/v_write, we must allocate the memory so that it remains on the stack
		//rather than vanishing when the function returns.		
		temp = (unsigned char*) malloc ( SMSA_BLOCK_SIZE * sizeof ( char ) );		

		if ( DEBUG )
			logMessage ( LOG_INFO_LEVEL, "Successfully Malloced [%d] Bytes of Data To temp", SMSA_BLOCK_SIZE*sizeof( char ) );
		
		//check cache first
		cacheLine = smsa_get_cache_line ( currentDrum, currentBlock );

		//Since we don't know if the entire block should be 
		//stored in buf, we need to put the entire contents
		//of the block in a temp, then we can decide which 
		//bytes to copy to bu
		if ( cacheLine == NULL ) {
		
			//Cache miss, now read disk
			err = readLowLevel ( temp ) ;

			//Now that this is the most recently used block of memory, we 
			//need to make sure that it is in the cache.
			err = smsa_put_cache_line ( currentDrum, currentBlock, temp );	
			
			//performance stats
			disk_reads++;
		}
		else {
		
			//cacheLine contains the block line we are looking for,
			//so assign this to temp for further use in teh function
			temp = cacheLine;
			
			//performance stats
			cache_hits++;
		}	

	
		//now is where we decide the specific bytes ( letters ) 
		//from the current block values that should be overwritten.
		//After this function call, lowerBound, and upperBound will be 
		//set to the proper values in order for the memcpy to work
		err = findMemCpyBounds ( drumStart, blockStart, byteStart, drumEnd, blockEnd, byteEnd, currentDrum, currentBlock, &lowerBound, &upperBound );

		//memcopy will copy all of the desired temp to buf.
		//This is all based on the lower and upper bounds which was
		//determined by the findMemCpyBounds above. The bufferIndex 
		//will increase throughout each iteration of the while loop 
		//in order to get a buffer of "len" size. How much of the 
		//temp goes into the buffer is determined by the findMemCpyBounds
		//function above 	
		memcpy ( &buf[bufferIndex], &temp[lowerBound], upperBound - lowerBound );


		if ( DEBUG )
			logMessage ( LOG_INFO_LEVEL, "Memcpy ( buf[%d], temp[%d], %d )", bufferIndex, lowerBound, upperBound-lowerBound );


		//now that we have copied (upperBound-lowerBound) amount of
		//bytes into buf, we must make sure that we do not overwrite
		//this data when we attempt to copy bytes from the next block.
		//That means we need to increase the position that were copying to,
		//to just after where we copied.	
		bufferIndex += upperBound - lowerBound;

		if ( DEBUG )
			logMessage ( LOG_INFO_LEVEL, "BufferIndex Set From [%d] to [%d]", bufferIndex-(upperBound-lowerBound), bufferIndex);

		//check for errors during the loop, and at the end. This will allow us
		//to find where the errors occur, since were checking throughout the 
		//entire process. However, we don't want to stop the program unless
		//a error was found. So, we will return 1, only if checkForErrors results
		//in one
		if ( checkForErrors ( err, "_smsa_vread", addr, len, drumStart, blockStart, currentDrum, currentBlock, drumEnd, blockEnd ) )
			return 1; 
	
		
		//increment the block
		currentBlock++;

		//if the current block is out of the bounds for the 
		//disk size (currentBlock > 256), then set the current 
		//block to zero, and start reading the next disk
		if ( currentBlock == SMSA_BLOCK_SIZE ) {
			currentDrum++;
			currentBlock = 0;
		}

		//adjust the block and drum head if neccessary	
		err = seekIfNeedTo ( currentDrum, currentBlock );	


		
	}
	
		
	
	//if checkForErrors finds that err is non-zero, it will return 1. 
	//see smsa_driver.h for error enum definition
	return ( checkForErrors ( err, "_vread", DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, 
						DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE ) );

}
Example #4
0
int smsa_vwrite( SMSA_VIRTUAL_ADDRESS addr, uint32_t len, unsigned char *buf )  {
    // First check if the length is 0
    // Write nothing and return if so
    if(len == 0) {
        return 0;
    }

    /* Initialize variables */
    int i;
    int err = 0;
    int read_bytes = 0;
    uint32_t offset;
    SMSA_DRUM_ID drum;
    SMSA_BLOCK_ID block;
    SMSA_BLOCK_ID block_orig;
    unsigned char *smsa_vwrite_buffer = NULL;

    drum = find_drum(addr);
    block = find_block(addr);
    block_orig = block;
    offset = addr & 0xff;
    seek_if_i_must(drum, block);
    
    // Loop to iterate through blocks
    do {
        /* Bounds Check */
        // Check if drum is in bounds
        if( (drum > SMSA_DISK_ARRAY_SIZE) || (drum < 0) ) {
            logMessage( LOG_ERROR_LEVEL, "The drum is out of bounds [%d]\n", drum );
            return -1;
        }

        // Check if block is in bounds
        if( (block > SMSA_MAX_BLOCK_ID) || (block < 0) ) {
            logMessage( LOG_ERROR_LEVEL, "The block is out of bounds [%d]\n", block );
            return -1;
        }
        
        // Check if original block
        if( block == block_orig ) {
            i = offset;
        } else { i = 0; }

        // If last block
        if( (block == SMSA_BLOCK_SIZE) ) { 
            block = 0; 
            curBlock = 0;
            drum++;
            seek_if_i_must(drum, block);
        }

        /* Is it in the cache? */
        logMessage(LOG_INFO_LEVEL, "Asking cache at: drum[%d]\tblock[%d]\n", drum, block);
        smsa_vwrite_buffer = smsa_get_cache_line(drum, block);
        // If Yes
        if(smsa_vwrite_buffer != NULL) {
            do {
                smsa_vwrite_buffer[i] = buf[read_bytes];
                read_bytes++;
                i++;
            } while( (i<SMSA_BLOCK_SIZE) && (read_bytes<len) );
            block++;
            curBlock++;
            /* smsa_operation( SEEK_BLOCK, NULL ); */
        }
        // If No
        else {
            smsa_vwrite_buffer = (unsigned char *) malloc(SMSA_BLOCK_SIZE * sizeof(unsigned char));
            // Read from disk
            smsa_operation( DISK_READ, smsa_vwrite_buffer);

            // Loop to write into buffer
            do {
                smsa_vwrite_buffer[i] = buf[read_bytes];
                read_bytes++;
                i++;
            } while( (i<SMSA_BLOCK_SIZE) && (read_bytes<len) );

            // Put into cache
            logMessage(LOG_INFO_LEVEL, "Finding a place to put the cache entry...\n");
            err = smsa_put_cache_line(drum, block, smsa_vwrite_buffer);
            block++;
            curBlock++;
        }
        if(err) {
            logMessage(LOG_ERROR_LEVEL, "Something bad happened in the cache :/\n");
            return -1;
        }

        // Write to disk
        smsa_operation( SEEK_PREVIOUS_BLOCK, NULL );
        /* if(block == 0) { */
        /*     smsa_put_cache_line(drum-1, 255, smsa_vwrite_buffer); */
        /* } else { */
        /*     smsa_put_cache_line(drum, block-1, smsa_vwrite_buffer); */
        /* } */
        smsa_operation( DISK_WRITE, smsa_vwrite_buffer );
    } while(read_bytes<len);

    return 0;
}