📄 cbiolib.c
字号:
semGive(&pDev->cbio_mutex); return OK; }/********************************************************************************* blkWrapBlkCopy - Copy sectors ** This routine makes copies of one or more blocks on the lower layer BLK_DEV.* 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 blkWrapBlkCopy ( CBIO_DEV_ID dev, block_t src_block, block_t dst_block, block_t num_blocks ) { CBIO_DEV *pDev = (void *) dev ; BLK_DEV * pBd = pDev->pDc ; STATUS stat = OK;#ifdef DEBUG if( OBJ_VERIFY( dev, cbioClassId ) != OK) { INFO_MSG("blkWrapBlkCopy: invalid handle\n",0,0,0,0,0,0); errno = S_objLib_OBJ_ID_ERROR; return ERROR; }#endif if( pBd->bd_readyChanged || dev->cbio_readyChanged ) { dev->cbio_readyChanged = TRUE ; 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; } if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR ) return ERROR; /* verify that there is a block buffer, if not, allocate one */ if( pDev->cbio_memBase == NULL) { if( cbioBufCreate( pDev) == ERROR ) { semGive(&pDev->cbio_mutex); return ERROR; } } /* flush the current contents of the block buffer if needed */ if( pDev->cbio_blkNo != (u_long)NONE && pDev->cbio_dirtyMask != (u_long)0 ) { block_t cachedBlock = pDev->cbio_blkNo ; stat = blkWrapBlkRW( pDev, cachedBlock, 1, pDev->cbio_memBase, CBIO_WRITE, NULL); if( stat == ERROR ) { semGive(&pDev->cbio_mutex); return ERROR; } } pDev->cbio_blkNo = NONE ; /* invalidate buffer contents */ pDev->cbio_dirtyMask = 0; /* because tiny cache is one block size, copy blocks one at a time */ for(; num_blocks > 0; num_blocks -- ) { stat = blkWrapBlkRW( pDev, src_block, 1, pDev->cbio_memBase, CBIO_READ, NULL); if( stat == ERROR) break; stat = blkWrapBlkRW( pDev, dst_block, 1, pDev->cbio_memBase, CBIO_WRITE, NULL); if( stat == ERROR) break; src_block ++; dst_block ++; } semGive(&pDev->cbio_mutex); return stat; }/********************************************************************************* blkWrapIoctl - Misc control operations ** This performs the requested ioctl() operation.* * CBIO modules can expect the following ioctl() codes from cbioLib.h:* .IP* CBIO_RESET - reset the CBIO device. When the third argument to the ioctl* call accompaning CBIO_RESET is NULL, the code verifies that the disk is * inserted and is ready, after getting it to a known state. When the 3rd * argument is a non-zero, it is assumed to be a BLK_DEV pointer and * CBIO_RESET will install a new subordinate block device. This work* is performed at the BLK_DEV to CBIO layer, and all layers shall account* for it. A CBIO_RESET indicates a possible change in device geometry, * and the CBIO_PARAMS members will be reinitialized after a CBIO_RESET.* .IP* CBIO_STATUS_CHK - check device status of CBIO device and lower layer* .IP* CBIO_DEVICE_LOCK - Prevent disk removal * .IP* CBIO_DEVICE_UNLOCK - Allow disk removal* .IP* CBIO_DEVICE_EJECT - Unmount and eject device* .IP* CBIO_CACHE_FLUSH - Flush any dirty cached data* .IP* CBIO_CACHE_INVAL - Flush & Invalidate all cached data* .IP* CBIO_CACHE_NEWBLK - Allocate scratch block* .LP** Arguments are:* .IP* dev - the CBIO handle of the device being accessed (from creation routine)* .IP * command - ioctl() command being issued* .IP * arg - specific to the particular ioctl() function requested or un-used.* .LP** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS blkWrapIoctl ( CBIO_DEV_ID dev, int command, addr_t arg ) { FAST CBIO_DEV * pDev = (void *) dev ; FAST BLK_DEV * pBd = pDev->pDc ; STATUS stat = OK ; if( OBJ_VERIFY( pDev, cbioClassId ) != OK) { errno = S_objLib_OBJ_ID_ERROR; return ERROR; } if( semTake( &pDev->cbio_mutex, WAIT_FOREVER) == ERROR ) return ERROR; /* * CBIO_RESET may be optionally used to * install a new subordinate block device * if 3rd argument is non-zero, it is expected to be * a new BLK_DEV pointer. */ if( command == (int)CBIO_RESET && arg != NULL ) { BLK_DEV * pBd = (void *) arg ; int tmp, limit = cbioBlkDevPtrLimit ; /* * here we must verify BLK_DEV in much the same way as in * cbioDevVerify() */ stat = ERROR ; errno = EINVAL ; /* if the input is a valid CBIO device, ignore it */ if( OBJ_VERIFY( (void *) pBd, cbioClassId ) == OK) goto ioctl_exit ; /* blkIo has no mechanism for verification, improvise */ else if( (pBd->bd_blkRd == NULL) || (pBd->bd_blkWrt == NULL) || (pBd->bd_ioctl == NULL) ) goto ioctl_exit ; else { tmp = (long) pBd->bd_blkRd ; if( abs((long)pBd->bd_blkWrt - tmp) > limit || abs((long)pBd->bd_ioctl - tmp) > limit ) goto ioctl_exit ; if( (pBd->bd_statusChk != NULL ) && abs((long)pBd->bd_statusChk - tmp) > limit ) goto ioctl_exit ; /* check that bytesPerBlk is 2^n */ tmp = shiftCalc( pBd->bd_bytesPerBlk ); if( pBd->bd_bytesPerBlk != (ULONG)( 1 << tmp ) ) goto ioctl_exit ; /* * for simplicity, we place a dummy function * if statusChk is not provided */ if( pBd->bd_statusChk == NULL ) pBd->bd_statusChk = cbioWrapOk ; stat = OK ; errno = 0; } /* this means that RESET will be later issued and reset all fields */ dev->cbio_readyChanged = TRUE ; dev->pDc = (void *) pBd ; semGive(&pDev->cbio_mutex); return stat; } /* End of CBIO_RESET for BLK_DEV replacement handling */ /* * CBIO_RESET - 3rd arg is NULL: * verify that the disk is inserted and is ready, * after getting it to a known state for good measure * and reset readyChanged if indeed the disk is ready to roll. */ if( command == (int)CBIO_RESET ) { stat = OK; errno = OK ; /* if the Block's got a reset function, call it */ if( pBd->bd_reset != NULL ) stat = pBd->bd_reset( pBd ); /* * for simplicity, we place a dummy function * if statusChk is not provided */ if( pBd->bd_statusChk == NULL ) pBd->bd_statusChk = cbioWrapOk ; /* * the drive's got a status check function, * use it to find out if all is cool and dandy, and * determine current state from status check result */ stat = pBd->bd_statusChk( pBd ); pDev->cbio_readyChanged = (stat == ERROR) ? TRUE : FALSE ; /* since the block size may have changed, we must re-init */ if( FALSE == pDev->cbio_readyChanged ) { pBd->bd_readyChanged = FALSE ;/* XXX- FDC hack */ pDev->params.cbio_nBlocks = pBd->bd_nBlocks ; pDev->params.cbio_bytesPerBlk = pBd->bd_bytesPerBlk ; pDev->params.cbio_blksPerTrack = pBd->bd_blksPerTrack ; pDev->params.cbio_nHeads = pBd->bd_nHeads ; pDev->params.cbio_offset = 0 ; pDev->cbio_mode = pBd->bd_mode ; if( pDev->cbio_memBase != NULL && pDev->cbio_memSize != pBd->bd_bytesPerBlk ) { free( pDev->cbio_memBase ); pDev->cbio_memBase = NULL ; pDev->cbio_memSize = 0; pDev->pFuncs->cbio_blkRW = blkWrapBlkRW ; }#ifdef __unused__ blkWrapDiskSizeAdjust( pDev) ;#endif /*__unused__*/ pDev->params.cbio_lastErrBlk = NONE ; pDev->params.cbio_lastErrno = 0 ; } if( stat == ERROR && errno == OK ) errno = S_ioLib_DISK_NOT_PRESENT ; semGive(&pDev->cbio_mutex); return stat; } /* all other commands, except RESET, wont work if disk is not there */ if( pBd->bd_readyChanged || pDev->cbio_readyChanged ) { pDev->cbio_readyChanged = TRUE ; errno = S_ioLib_DISK_NOT_PRESENT ; semGive(&pDev->cbio_mutex); return ERROR; } switch ( command ) { case CBIO_STATUS_CHK : stat = pBd->bd_statusChk( pBd ); pDev->cbio_readyChanged = (stat == ERROR) ? TRUE : FALSE ; pBd->bd_readyChanged = FALSE ;/* XXX- FDC hack */ break; case CBIO_CACHE_FLUSH : case CBIO_CACHE_INVAL : case CBIO_CACHE_NEWBLK: if( pDev->cbio_memBase != NULL && pDev->cbio_blkNo != (u_long)NONE && pDev->cbio_dirtyMask != (u_long)0 ) { block_t cachedBlock = pDev->cbio_blkNo ; stat = blkWrapBlkRW( pDev, cachedBlock, 1, pDev->cbio_memBase, CBIO_WRITE, NULL); } if( pDev->cbio_memBase != (u_long)NULL && command == (int)CBIO_CACHE_NEWBLK ) { bzero( pDev->cbio_memBase, pDev->cbio_memSize); pDev->cbio_blkNo = (block_t) arg ; pDev->cbio_dirtyMask = 1; } else { pDev->cbio_blkNo = NONE ; pDev->cbio_dirtyMask = 0; } break; default: stat = pBd->bd_ioctl( pBd, command, arg ); break ; case CBIO_RESET : /* dealt with above, for switch completeness */ case CBIO_DEVICE_LOCK : /* unimplemented commands */ case CBIO_DEVICE_UNLOCK : case CBIO_DEVICE_EJECT : errno = S_ioLib_UNKNOWN_REQUEST; stat = ERROR; break; } ioctl_exit: semGive(&pDev->cbio_mutex); return stat; }#ifdef __unused__/********************************************************************************* blkWrapDiskSizeAdjust - adjust true disk size** Some block drivers report incorrect disk capacity in bd_nBlocks field.* This function will experimentally discover the true size of the disk,* by reading blocks until an error is returned by the driver.* In order to overcome driver's sanity checks, the bd_nBlocks will* be adjusted each time a call is made to read blocks beyond the* previously reported capacity.* There is a time limit on these attempts, so the final result may* be still inaccurate if the capacity reported by the driver* is significantly different from the actual disk capacity.** RETURNS: N/A*/LOCAL void blkWrapDiskSizeAdjust ( CBIO_DEV_ID dev /* CBIO device handle */ ) { FAST CBIO_DEV * pDev = (void *) dev ; FAST BLK_DEV * pBd = pDev->pDc ; STATUS stat = OK ; int timeout = tickGet() + 2 * sysClkRateGet(); /* 2 sec timeout */ int orig_nBlocks, secPerCyl ; caddr_t tmpBuf ; orig_nBlocks = pBd->bd_nBlocks ; secPerCyl = pBd->bd_blksPerTrack * pBd->bd_nHeads ; tmpBuf = malloc( pBd->bd_bytesPerBlk ); /* increment capacity by one cylinder and test readability */ while( (tickGet()<=timeout) && (stat == OK ) ) { /* read last block in current capacity */ stat = pBd->bd_blkRd( pBd, pBd->bd_nBlocks-1, 1, tmpBuf ); /* if OK, try to read end of next cyl, if failed, go back and break */ if( stat == OK ) pBd->bd_nBlocks += secPerCyl; else pBd->bd_nBlocks -= secPerCyl; } /* refresh timeout */ timeout = tickGet() + (2 * sysClkRateGet()); /* 2 sec timeout */ stat = OK ; /* increment capacity by one sector and test readability */ while( (tickGet() <= timeout) && (stat == OK ) ) { /* read last block in current capacity */ stat = pBd->bd_blkRd( pBd, pBd->bd_nBlocks-1, 1, tmpBuf ); if( stat == OK ) pBd->bd_nBlocks ++ ; else pBd->bd_nBlocks -- ; }#ifdef DEBUG if(cbioDebug > 0 && tickGet()> timeout ) logMsg("blkWrapDiskSizeAdjust: timeout %d exceeded\n", timeout,0,0,0,0,0);#endif /* if all goes well, the last read operation should have succeeded */ if( (stat = pBd->bd_blkRd( pBd, pBd->bd_nBlocks-1, 1, tmpBuf )) == OK) {#ifdef DEBUG if(cbioDebug > 0) logMsg("blkWrapDiskSizeAdjust: capacity increased by %d blocks\n", pBd->bd_nBlocks - orig_nBlocks, 0,0,0,0,0);#endif /* make it official */ pDev->params.cbio_nBlocks = pBd->bd_nBlocks ; } else { /* something is weird, put it back where it was */#ifdef DEBUG if(cbioDebug > 0) logMsg("blkWrapDiskSizeAdjust: failed to adjust\n", 0,0,0,0,0,0);#endif pDev->params.cbio_nBlocks = pBd->bd_nBlocks = orig_nBlocks ; } free( tmpBuf ); }#endif /*__unused__*//* End of File */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -