⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcachecbio.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 5 页
字号:
    pDesc = (DCACHE_DESC *) DLL_FIRST( & pDc->dc_LRU );    while( pDesc != NULL )	{	if( pDesc->block == block )	    {	    goto found ;	    }	pDesc = (DCACHE_DESC *) DLL_NEXT(& pDesc->lruList );	}    return NULL;found:    return (pDesc );    }/********************************************************************************* dcacheBlockGet - get a disc block in a cache block** This function is code which is common for reading and writing bytewise* as well as reading blockwise.* NOTE: The cbio_mutex must already be taken when entering this function.*/LOCAL DCACHE_DESC * dcacheBlockGet( CBIO_DEV_ID dev, block_t block,	cookie_t *cookie, BOOL readData )    {    DCACHE_DESC *pDesc = NULL ;    BOOL allocated = FALSE ;    STATUS stat;    /* First, verify that cookie is valid, otherwise destroy it */    if( cookie != NULL )	if( *cookie != 0)	    {	    /* these sanity tests are not needed after debugging is complete */	    assert( ((caddr_t) *cookie >= dev->cbio_memBase) &&		  ((caddr_t) *cookie < (dev->cbio_memBase+dev->cbio_memSize)));	    }    /* entering this internal function, we should already own the mutex */    assert( dev->cbio_mutex.semOwner == (void *) taskIdSelf() );        /* try to locate block by cookie if valid */    if( cookie != NULL )	if( *cookie != 0)	    {	    pDesc = (void *) *cookie ;	    if( pDesc->block != block )		{		dev->pDc->dc_cookieMisses ++ ;		pDesc = NULL;		}	    else		{		dev->pDc->dc_cookieHits ++ ;		return(pDesc);		/* 		 * we omitted here making this block MRU,		 * cookie references should be very fast,		 * at a minimal risk of loosing this block		 * earlier then it normally would happened.		 */		}	    }    /* locate block in LRU list */    if( pDesc == NULL)	pDesc = dcacheBlockLocate(dev, block);    /* block not found, allocate one */    if( pDesc == NULL)	{	dev->pDc->dc_lruMisses ++ ;	allocated = TRUE ;	pDesc = dcacheBlockAllocate(dev, block);	/* if that failed, something is basically wrong here */	if (pDesc == NULL )	    {	    return NULL ;	    }	}    else	{	dev->pDc->dc_lruHits ++ ;	}    /* if this is a write-only operation,  -> DIRTY shortcut */    if( ! readData )	{	if( pDesc->state != CB_STATE_DIRTY )	    dev->pDc->dc_dirtyCount ++ ;	pDesc->state = CB_STATE_DIRTY ;	}    if( cookie != NULL )	{	*((void * *)cookie) = (void *) pDesc ;	}    /* fill block with data from disk if needed */    if ( readData && allocated )	{	stat = dcacheBlockFill( dev, pDesc );	if( stat == ERROR)	    {	    dcacheHashRemove(dev, pDesc);	    /* the disk may have been removed */	    return NULL ;	    }	assert(pDesc->state == CB_STATE_CLEAN);	}    /* make this block MRU */    dllRemove( & dev->pDc->dc_LRU, &pDesc->lruList );    dllInsert( & dev->pDc->dc_LRU, NULL, &pDesc->lruList );    if( (pDesc->block == block) )	{	return (pDesc);	}    else	{	/* this should never happen, unless tunable params are out of sanity */	INFO_MSG("dcacheCbio: dev=%#x cache internal error - starvation %d\n",		(u_int) dev, pDesc->block, 0, 0, 0, 0);	errno = EAGAIN;	return(NULL);	}    }/********************************************************************************* dcacheBlkRW	- Read/Write blocks** This routine transfers between a user buffer and the lower layer CBIO* It is optimized for block transfers.  ** dev - the CBIO handle of the device being accessed (from creation routine)* * start_block - the starting block of the transfer operation* * num_blocks - the total number of blocks to transfer* * buffer - address of the memory buffer used for the transfer* * rw - indicates the direction of transfer up or down (READ/WRITE)* * *cookie - pointer to cookie used by upper layer such as dosFsLib(),* it should be preserved.** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS dcacheBlkRW    (    CBIO_DEV_ID		dev,    block_t		start_block,    block_t		num_blocks,    addr_t		buffer,    enum cbio_rw	rw,    cookie_t		*cookie    )    {    CBIO_DEV *	pDev = (void *) dev ;    DCACHE_DESC *pDesc;    STATUS stat = OK ;    if( TRUE == dev->cbio_readyChanged )	{	errno = S_ioLib_DISK_NOT_PRESENT ;	return ERROR;	}    if( (start_block) > pDev->params.cbio_nBlocks ||    	(start_block+num_blocks) > pDev->params.cbio_nBlocks )	{	errno = EINVAL;	return ERROR;	}    start_block += pDev->params.cbio_offset;    DEBUG_MSG("dcacheBlkRW: blk %d num blocks %d\n",	start_block, num_blocks, 0,0,0,0 );    if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR )	return ERROR;    /* by-pass cache for large transfers */    if( num_blocks > pDev->pDc->dc_bypassCount ) 	{	BOOL doFlush = (rw == CBIO_READ)? TRUE : FALSE ;	BOOL doInval = (rw == CBIO_WRITE)? TRUE : FALSE ;	/* BEGIN - Hidden write handling */	if( dev->pDc->dc_lastAccBlock < start_block )	    {	    stat = dcacheManyFlushInval( dev,			dev->pDc->dc_lastAccBlock,			start_block,			TRUE, FALSE,			& dev->pDc->dc_writesHidden );	    }	if( stat == ERROR)	    goto read_error;	/* END   - Hidden write handling */	stat = dcacheManyFlushInval( dev, start_block,			start_block + num_blocks -1 ,			doFlush, doInval, & pDev->pDc->dc_writesHidden );	if( stat == OK )	    {	    stat = dcacheBlkBypassRW( dev, start_block, num_blocks, buffer, rw);	    semGive(&pDev->cbio_mutex);	    return( stat ) ;	    }	}    for( ; num_blocks > 0; num_blocks-- )	/* For each block req'ed */	{	/* skip reading back the data if writing entire blocks */	BOOL readData = (rw == CBIO_READ)? TRUE : FALSE ;	CB_STATE saveState ;	/* get that block */	pDesc = dcacheBlockGet(pDev, start_block, cookie, readData);	if( pDesc == NULL )	    goto read_error ;	/* Debug: make sure the block still has got the data */	assert(  (pDesc->state == CB_STATE_CLEAN) ||		 (pDesc->state == CB_STATE_DIRTY) );	/* move data between the cached block and caller's buffer */	switch( rw )	    {	    case CBIO_READ:		bcopy( pDesc->data, buffer, pDev->params.cbio_bytesPerBlk );		break;	    case CBIO_WRITE:		saveState = pDesc->state ;		pDesc->state = CB_STATE_UNSTABLE ;		bcopy( buffer, pDesc->data, pDev->params.cbio_bytesPerBlk );		/* in case it was already CLEAN, we mark it DIRTY,		 * so that it will be written to disk again.		 */		if( saveState != CB_STATE_DIRTY )		    dev->pDc->dc_dirtyCount ++ ;		pDesc->state = CB_STATE_DIRTY ;		break;	    } /* switch */	start_block ++ ;	/* prepare for next */	buffer += pDev->params.cbio_bytesPerBlk ;	}	/* end of: For each block req'ed */    if( dev->pDc->dc_dirtyCount > dev->pDc->dc_dirtyMax )	stat = dcacheManyFlushInval( pDev, 0, NONE, TRUE, FALSE,			& pDev->pDc->dc_writesForeground );    semGive(&pDev->cbio_mutex);    return stat;read_error:    semGive(&pDev->cbio_mutex);    return ERROR;    }/********************************************************************************* dcacheBytesRW - Read/Write bytes** This routine transfers between a user buffer and the lower layer hardware* It is optimized for byte transfers.  ** dev - the CBIO handle of the device being accessed (from creation routine)* * start_block - the starting block of the transfer operation* * offset - offset in bytes from the beginning of the starting block* * buffer - address of the memory buffer used for the transfer* * nBytes - number of bytes to transfer* * rw - indicates the direction of transfer up or down (READ/WRITE)* * *cookie - pointer to cookie used by upper layer such as dosFsLib(),* it should be preserved.* * RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS dcacheBytesRW    (    CBIO_DEV_ID 	dev,    block_t		start_block,    off_t		offset,    addr_t		buffer,    size_t		nBytes,    enum cbio_rw	rw,    cookie_t		*cookie    )    {    FAST CBIO_DEV *	pDev = (void *) dev ;    FAST struct dcache_ctrl * pDc = dev->pDc ;    FAST DCACHE_DESC *	pDesc;    BOOL readData = TRUE;	/* read data from disk, always */    STATUS stat = OK ;    CB_STATE saveState ;    if( TRUE == pDev->cbio_readyChanged )	{	errno = S_ioLib_DISK_NOT_PRESENT ;	return ERROR;	}    if( (start_block) > pDev->params.cbio_nBlocks )	{	errno = EINVAL;	return ERROR;	}    /* verify that all bytes are within one block range */    if (((offset + nBytes) > pDev->params.cbio_bytesPerBlk ) ||	(offset <0) || (nBytes <=0))	{	errno = EINVAL;	return ERROR;	}    start_block += pDev->params.cbio_offset;    DEBUG_MSG("dcacheBytesRW: blk %d num bytes %d, offset %d\n",	start_block, nBytes, offset, 0,0,0 );    if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR )	return ERROR;    /* get that block */    pDesc = dcacheBlockGet(pDev, start_block, cookie, readData);    if( pDesc == NULL )	goto _error ;    /* Debug: make sure the block still has got the data */    assert(  (pDesc->state == CB_STATE_CLEAN) ||	     (pDesc->state == CB_STATE_DIRTY) );    /* move data between the cached block and caller's buffer */    switch( rw )	{	case CBIO_READ:	    bcopy( pDesc->data+offset, buffer, nBytes);	    break;	case CBIO_WRITE:	    saveState = pDesc->state ;	    pDesc->state = CB_STATE_UNSTABLE ;	    bcopy( buffer, pDesc->data+offset, nBytes);	    if( saveState != CB_STATE_DIRTY )		pDc->dc_dirtyCount ++ ;	    pDesc->state = CB_STATE_DIRTY;	    break;	} /* switch */    if( pDc->dc_dirtyCount > pDc->dc_dirtyMax )	stat = dcacheManyFlushInval( pDev, 0, NONE, TRUE, FALSE,		& pDev->pDc->dc_writesForeground );    semGive(&pDev->cbio_mutex);    return stat;_error:    semGive(&pDev->cbio_mutex);    return ERROR;    }/********************************************************************************* dcacheBlkCopy - Copy sectors ** This function will be mainly used to write backup copies of FAT,* hence we may assume the the source blocks are in the cache anyway,* and we assume the requests are never too big.** This routine makes copies of one or more blocks on the lower layer CBIO* It is optimized for block copies on the subordinate layer.  * dev - the CBIO handle of the device being accessed (from creation routine)* * src_block - source start block of the copy* * dst_block - destination start block of the copy* * num_block - number of blocks to copy** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS dcacheBlkCopy    (    CBIO_DEV_ID 	dev,    block_t		src_block,    block_t		dst_block,    block_t		num_blocks    )    {    CBIO_DEV	*pDev = (void *) dev ;    DCACHE_DESC *pDescSrc, *pDescDst ;    CB_STATE saveState ;    if( TRUE == dev->cbio_readyChanged )	{	errno = S_ioLib_DISK_NOT_PRESENT ;	return ERROR;	}    if( (src_block) > pDev->params.cbio_nBlocks ||        (dst_block) > pDev->params.cbio_nBlocks )	{	errno = EINVAL;	return ERROR;	}    if( (src_block+num_blocks) > pDev->params.cbio_nBlocks ||        (dst_block+num_blocks) > pDev->params.cbio_nBlocks )	{	errno = EINVAL;	return ERROR;	}    src_block += pDev->params.cbio_offset;    dst_block += pDev->params.cbio_offset;    DEBUG_MSG("dcacheBlkCopy: blk %d to %d # %d blocks\n",	src_block, dst_block, num_blocks, 0, 0,0 );    if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR )	return ERROR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -