📄 cbiolib.c
字号:
if( pBd->bd_reset != NULL ) pBd->bd_reset( pBd ); do { if( blkWrapIoctl( pDev, CBIO_STATUS_CHK, 0) == OK) goto retryLoop; taskDelay(5); } while( tickGet() < (UINT32) tick+sysClkRateGet() ) ; } } } return stat; }/********************************************************************************* blkWrapBlkRWbuf - wrapper block I/O for coherency with tiny cache** This routine transfers between a user buffer and the lower layer BLK_DEV* It is optimized for block transfers. ** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS blkWrapBlkRWbuf ( CBIO_DEV_ID dev, block_t startBlock, block_t numBlocks, addr_t buffer, CBIO_RW rw, cookie_t * pCookie ) { FAST CBIO_DEV * pDev = dev ; STATUS stat = OK ; if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR ) return ERROR; /* verify that there is a block buffer, if not, allocate one */ if( pDev->cbioMemBase == NULL) { if( cbioBlkWrapBufCreate( pDev) == ERROR ) { semGive(pDev->cbioMutex); return ERROR; } } /* see if Tiny Cache contains a valid block */ if( pDev->cbioBlkNo != (u_long) NONE ) { /* see if the range touches the cached block */ if( (pDev->cbioBlkNo >= startBlock) && (pDev->cbioBlkNo < startBlock+numBlocks) ) { /* flush the current contents of the block buffer if dirty */ if( pDev->cbioDirtyMask != 0 ) { block_t cachedBlock = pDev->cbioBlkNo ; pDev->cbioBlkNo = NONE ; pDev->cbioDirtyMask = 0; stat = blkWrapBlkRW( pDev, cachedBlock, 1, pDev->cbioMemBase, CBIO_WRITE, NULL); } else { /* else just forget about it */ pDev->cbioBlkNo = NONE ; } } } if( stat == ERROR ) { semGive(pDev->cbioMutex); /* added semGive to fix SPR#76103 */ return (ERROR); } stat = blkWrapBlkRW (dev, startBlock, numBlocks, buffer, rw, pCookie) ; semGive(pDev->cbioMutex); return stat ; }/********************************************************************************* blkWrapBytesRW - Read/Write bytes** In order to implement the byte-wise read/write operation, a tiny* cache is implemented, which is used to store block data on which* byte operations are performed.** The tiny cache is a single disk block sized buffer at this time* which should suffice for solid-state (e.g. Flash) disks to be used* without the real disk cache, meaning dosFsLib directly on top of* this wrapper.** This routine transfers between a user buffer and the lower layer BLK_DEV* It is optimized for byte transfers. ** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS blkWrapBytesRW ( CBIO_DEV_ID dev, block_t startBlock, off_t offset, addr_t buffer, size_t nBytes, CBIO_RW rw, cookie_t * pCookie ) { CBIO_DEV * pDev = dev ; BLK_DEV * pBd = pDev->blkSubDev; STATUS stat = OK ; caddr_t pStart; if( pBd->bd_readyChanged || CBIO_READYCHANGED (dev)) { cbioRdyChgdSet(dev, TRUE); errno = S_ioLib_DISK_NOT_PRESENT ; return ERROR; } if( startBlock >= pDev->cbioParams.nBlocks ) { errno = EINVAL; return ERROR; } /* verify that all bytes are within one block range */ if (((offset + nBytes) > pDev->cbioParams.bytesPerBlk ) || (offset <0) || (nBytes <=0)) { errno = EINVAL; return ERROR; } if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR ) return ERROR; /* verify that there is a block buffer, if not, allocate one */ if( pDev->cbioMemBase == NULL) { if( cbioBlkWrapBufCreate( pDev) == ERROR ) { semGive(pDev->cbioMutex); return ERROR; } } /* flush the current contents of the block buffer if needed */ if( pDev->cbioBlkNo != (u_long)NONE && pDev->cbioBlkNo != startBlock && pDev->cbioDirtyMask != 0 ) { block_t cachedBlock = pDev->cbioBlkNo ; pDev->cbioBlkNo = NONE ; pDev->cbioDirtyMask = 0; stat = blkWrapBlkRW( pDev, cachedBlock, 1, pDev->cbioMemBase, CBIO_WRITE, NULL); if( stat == ERROR ) { semGive(pDev->cbioMutex); return ERROR; } } /* get the requested block into cache */ if( startBlock != pDev->cbioBlkNo && pDev->cbioDirtyMask == 0 ) { stat = blkWrapBlkRW( pDev, startBlock, 1, pDev->cbioMemBase, CBIO_READ, NULL); if( stat == ERROR ) { semGive(pDev->cbioMutex); return ERROR; } pDev->cbioBlkNo = startBlock ; pDev->cbioDirtyMask = 0; } assert( startBlock == pDev->cbioBlkNo ); /* calculate actual memory address of data */ pStart = pDev->cbioMemBase + offset ;#ifdef DEBUG if(cbioDebug > 1) logMsg("blkWrapBytesRW: blk %d + %d # %d bytes -> addr %x, %x bytes\n", startBlock, offset, nBytes, (int) pStart, nBytes, 0);#endif switch( rw ) { case CBIO_READ: bcopy( pStart, buffer, nBytes ); break; case CBIO_WRITE: bcopy( buffer, pStart, nBytes ); pDev->cbioDirtyMask = 1; break; } semGive(pDev->cbioMutex); 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. * * RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS blkWrapBlkCopy ( CBIO_DEV_ID dev, block_t srcBlock, block_t dstBlock, block_t numBlocks ) { CBIO_DEV *pDev = (void *) dev ; BLK_DEV * pBd = pDev->blkSubDev; STATUS stat = OK; if( pBd->bd_readyChanged || CBIO_READYCHANGED(dev)) { CBIO_READYCHANGED(dev) = TRUE; errno = S_ioLib_DISK_NOT_PRESENT ; return (ERROR); } if( (srcBlock) > pDev->cbioParams.nBlocks || (dstBlock) > pDev->cbioParams.nBlocks ) { errno = EINVAL; return ERROR; } if( (srcBlock+numBlocks) > pDev->cbioParams.nBlocks || (dstBlock+numBlocks) > pDev->cbioParams.nBlocks ) { errno = EINVAL; return ERROR; } if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR ) return ERROR; /* verify that there is a block buffer, if not, allocate one */ if( pDev->cbioMemBase == NULL) { if( cbioBlkWrapBufCreate( pDev) == ERROR ) { semGive(pDev->cbioMutex); return ERROR; } } /* flush the current contents of the block buffer if needed */ if( pDev->cbioBlkNo != (u_long)NONE && pDev->cbioDirtyMask != (u_long)0 ) { block_t cachedBlock = pDev->cbioBlkNo ; stat = blkWrapBlkRW( pDev, cachedBlock, 1, pDev->cbioMemBase, CBIO_WRITE, NULL); if( stat == ERROR ) { semGive(pDev->cbioMutex); return ERROR; } } pDev->cbioBlkNo = NONE ; /* invalidate buffer contents */ pDev->cbioDirtyMask = 0; /* because tiny cache is one block size, copy blocks one at a time */ for(; numBlocks > 0; numBlocks -- ) { stat = blkWrapBlkRW( pDev, srcBlock, 1, pDev->cbioMemBase, CBIO_READ, NULL); if( stat == ERROR) break; stat = blkWrapBlkRW( pDev, dstBlock, 1, pDev->cbioMemBase, CBIO_WRITE, NULL); if( stat == ERROR) break; srcBlock ++; dstBlock ++; } semGive(pDev->cbioMutex); 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** RETURNS OK or ERROR and may otherwise set errno.*/LOCAL STATUS blkWrapIoctl ( CBIO_DEV_ID dev, UINT32 command, addr_t arg ) { FAST CBIO_DEV_ID pDev = dev ; FAST BLK_DEV * pBd = pDev->blkSubDev ; STATUS stat = OK ; if( semTake( pDev->cbioMutex, 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; /* * here we must verify BLK_DEV in much the same way as in * cbioWrapBlkDev() */ stat = ERROR ; errno = EINVAL ; /* if the input is already a valid CBIO device, ignore it */ if (OK == cbioDevVerify ((CBIO_DEV_ID)pBd)) { 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 { /* 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 */ CBIO_READYCHANGED(dev) = TRUE; dev->blkSubDev = (void *) pBd ; dev->pDc = (void *) pBd ; semGive(pDev->cbioMutex); 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 ); CBIO_READYCHANGED(dev) = (ERROR == stat) ? TRUE : FALSE; /* since the block size may have changed, we must re-init */ if( FALSE == CBIO_READYCHANGED (dev) ) { pBd->bd_readyChanged = FALSE ; /* HELP - FDC hack */ pDev->cbioParams.nBlocks = pBd->bd_nBlocks ; pDev->cbioParams.bytesPerBlk = pBd->bd_bytesPerBlk ; pDev->cbioParams.blocksPerTrack = pBd->bd_blksPerTrack ; pDev->cbioParams.nHeads = pBd-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -