cbioLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:70k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* cbioLib.c - Cached Block I/O library */
  2. /* Copyright 1999-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01y,03jun02,jkf  fixed SPR#78162, cbioLib has INTERNAL comment visable
  8. 01x,29apr02,jkf  SPR#76013, blkWrapBlkRWbuf() shall semGive what it semTake's,
  9.                  also removed cbioWrapBlkDev check for bytesPerBlk since the 
  10.                  media may not be present at cdromFs mount time; improved 
  11.                  error message to mention the BLK_DEV * value that fails.
  12. 01w,14jan02,jkf  SPR#72533, added cbioRdyChk(), which is used in cbioShow().
  13. 01v,12dec01,jkf  fixing diab build warnings.
  14. 01u,10dec01,jkf  SPR#72039, cbioShow should use strcmp.
  15. 01t,09dec01,jkf  SPR#71637, fix for SPR#68387 caused ready changed bugs.
  16. 01s,15nov01,jkf  SPR#71720, avoid unaligned pointer access.
  17. 01r,20sep01,jkf  SPR#69031, common code for both AE & 5.x.
  18. 01q,01aug01,jyo  Fixed SPR#68387: readyChanged bit is not correctly checked to
  19.                  verify the change in the media, SPR#69411: Change in media's
  20.                  readyChanged bit is not being propogated appropriately to the
  21.                  layers above.
  22. 01p,14jun01,jyo  Fixed SPR#67729 and SPR#68150: Media's state information is
  23.                  read correctly from the lowest layer and tidied the code to
  24.                  use the new member subDev instead of pDc of CBIO_DEV
  25.                  structure.
  26. 01o,08sep00,nrj  Fixed SPR#33934,33925: avoid using cbioBlkDevPtrLimit
  27. 01n,19apr00,dat  doc fixup
  28. 01m,07dec99,jkf  changed OBJ_CORE to HANDLE, KHEAP_ALLOC, made mode int
  29.                  changes for cbioDevVerify(), cbioWrapBlkDev().
  30. 01l,15sep99,jkf  changes for public CBIO API.
  31. 01k,31jul99,jkf  T2 merge, tidiness, & spelling.
  32. 01j,14dec98,lrn  make pointer range limit configurable (SPR#23977)
  33. 01i,22nov98,lrn  added statusChk verification after reset
  34. 01h,04nov98,lrn  refined error handling with Floppy
  35. 01g,29oct98,lrn  fixed BLK_DEV replacement for PCMCIA, w/ CBIO_RESET 3rd arg   
  36. 01f,20oct98,lrn  removed the previous mode because of non-ATA block drivers.
  37. 01e,20oct98,lrn  added capacity adjustment to work around ATA driver bug
  38. 01d,20oct98,lrn  fixed SPR#22553, SPR#22731
  39. 01c,10sep98,lrn  add CBIO_RESET for blk dev replacement, add error handling
  40. 01b,03sep98,lrn  add block device wrapper
  41. 01a,15jan98,lrn  written, preliminary
  42. */
  43. /*
  44. DESCRIPTION
  45. This library provides the Cached Block Input Output Application 
  46. Programmers Interface (CBIO API).  Libraries such as dosFsLib, 
  47. rawFsLib, and usrFdiskPartLib use the CBIO API for I/O operations 
  48. to underlying devices.
  49. This library also provides generic services for CBIO modules.  
  50. The libraries dpartCbio, dcacheCbio, and ramDiskCbio are examples 
  51. of CBIO modules that make use of these generic services.
  52. This library also provides a CBIO module that converts blkIo driver 
  53. BLK_DEV (blkIo.h) interface into CBIO API compliant interface using
  54. minimal memory overhead.  This lean module is known as the basic 
  55. BLK_DEV to CBIO wrapper module.   
  56. CBIO MODULES AND DEVICES
  57. A CBIO module contains code for supporting CBIO devices.  
  58. The libraries cbioLib, dcacheCbio, dpartCbio, and ramDiskCbio 
  59. are examples of CBIO modules.   
  60. A CBIO device is a software layer that provide its master control
  61. of I/O to it subordinate.  CBIO device layers typicaly reside 
  62. logically below a file system and above a storage device.  CBIO 
  63. devices conform to the CBIO API on their master (upper) interface.
  64. CBIO modules provide a CBIO device creation routine used to instantiate 
  65. a CBIO device.  The CBIO modules device creation routine returns 
  66. a CBIO_DEV_ID handle.  The CBIO_DEV_ID handle is used to uniquely 
  67. identify the CBIO device layer instance.  The user of the CBIO device 
  68. passes this handle to the CBIO API routines when accessing the device.
  69. The libraries dosFsLib, rawFsLib, and usrFdiskPartLib are considered 
  70. users of CBIO devices because they use the CBIO API on their subordinate
  71. (lower) interface.  They do not conform to the CBIO API on their master 
  72. interface, therefore they are not CBIO modules.  They are users of CBIO 
  73. devices and always reside above CBIO devices in the logical stack.
  74. TYPES OF CBIO DEVICES 
  75. A "CBIO to CBIO device" uses the CBIO API for both its master and its 
  76. subordinate interface.  Typically, some type of module specific I/O 
  77. processing occurs during the interface between the master and subordinate
  78. layers.  The libraries dpartCbio and dcacheCbio are examples of CBIO to 
  79. CBIO devices.   CBIO to CBIO device layers are stackable.   Care should be 
  80. taken to assemble the stack properly.  Refer to each modules reference 
  81. manual entry for recommendations about the optimum stacking order. 
  82. A "CBIO API device driver" is a device driver which provides the CBIO
  83. API as the interface between the hardware and its upper layer.  The 
  84. ramDiskCbio.c RAM DISK driver is an example of a simple CBIO API 
  85. device driver.
  86. A "basic BLK_DEV to CBIO wrapper device" wraps a subordinate BLK_DEV 
  87. layer with a CBIO API compatible layer.  The wrapper is provided via 
  88. the cbioWrapBlkDev() function.
  89. The logical layers of a typical system using a CBIO RAM DISK appear:
  90. .CS
  91.          +--------------------+
  92.          | Application module | 
  93.          +--------------------+ <-- read(), write(), ioctl()
  94.                    |
  95.          +--------------------+
  96.          | VxWorks I/O System | 
  97.          +--------------------+ <-- IOS layer iosRead,Write,ioctl
  98.                    |                (iosDrvInstall rtns from dosFsLib)
  99.       +--------------- -----------+
  100.       | File System (DOSFS/RAWFS) | 
  101.       +---------------------------+ <-- CBIO API (cbioBlkRW, cbioIoctl, etc.)
  102.                    |
  103. +----------------------------------------------+
  104. | CBIO API device driver module (ramDiskCbio.c)|
  105. +----------------------------------------------+
  106.                    |
  107.               +----------+
  108.               | Hardware |
  109.               +----------+
  110. .CE
  111. The logical layers of a typical system with a fixed disk
  112. using CBIO partitioning layer and a CBIO caching layer appears:
  113. .CS
  114.             +--------------------+
  115.             | Application module |
  116.             +--------------------+ <-- read(), write(), ioctl()
  117.                       |
  118.             +-------------------+
  119.             | VxWorks IO System |
  120.             +-------------------+ <-- IOS layer Read,Write, ioctl
  121.                       |               (iosDrvInstall rtns from dosFsLib)
  122.          +---------------------------+
  123.          | File System (DOSFS/RAWFS) |
  124.          +---------------------------+ <-- CBIO API RTNS (cbioLib.h)
  125.                       |
  126.       +---------------------------------+
  127.       | CBIO to CBIO device (dpartCbio) |
  128.       +---------------------------------+ <-- CBIO API RTNS
  129.                       |
  130.      +----------------------------------+
  131.      | CBIO to CBIO device (dcacheCbio) |
  132.      +----------------------------------+ <-- CBIO API RTNS 
  133.                       |
  134.   +------------------------------------------------+
  135.   | basic CBIO to BLK_DEV wrapper device (cbioLib) |
  136.   +------------------------------------------------+ <-- BLK_DEV (blkIo.h)
  137.                       |
  138. +-------------------------------------------------------+
  139. | BLK_DEV API device driver. scsiLib, ataDrv, fdDrv,etc | 
  140. +-------------------------------------------------------+
  141.                       |
  142.           +-------------------------+
  143.           | Storage Device Hardware |
  144.           +-------------------------+
  145. .CE
  146. PUBLIC CBIO API
  147. The CBIO API provides user access to CBIO devices.  Users of CBIO 
  148. devices are typically either file systems or other CBIO devices.  
  149. The CBIO API is exposed via cbioLib.h.  Users of CBIO modules include 
  150. the cbioLib.h header file.  The libraries dosFsLib, dosFsFat, dosVDirLib, 
  151. dosDirOldLib, usrFdiskPartLib, and rawFsLib all use the CBIO API to access 
  152. CBIO modules beneath them.    
  153. The following functions make up the public CBIO API:
  154. .IP
  155. cbioLibInit() - Library initialization routine 
  156. .IP
  157. cbioBlkRW() - Transfer blocks (sectors) from/to a memory buffer
  158. .IP
  159. cbioBytesRW() - Transfer bytes from/to a memory buffer
  160. .IP
  161. cbioBlkCopy() - Copy directly from block to block (sector to sector)
  162. .IP
  163. cbioIoctl() - Perform I/O control operations on the CBIO device
  164. .IP
  165. cbioModeGet() - Get the CBIO device mode (O_RDONLY, O_WRONLY, or O_RDWR)
  166. .IP
  167. cbioModeSet() - Set the CBIO device mode (O_RDONLY, O_WRONLY, or O_RDWR)
  168. .IP
  169. cbioRdyChgdGet() - Determine the CBIO device ready status state
  170. .IP
  171. cbioRdyChgdSet() - Force a change in the CBIO device ready status state 
  172. .IP
  173. cbioLock() - Obtain exclusive ownership of the CBIO device 
  174. .IP
  175. cbioUnlock() - Release exclusive ownership of the CBIO device 
  176. .IP
  177. cbioParamsGet() - Fill a CBIO_PARAMS structure with data from the CBIO device
  178. .IP
  179. cbioDevVerify() - Verify valid CBIO device 
  180. .IP
  181. cbioWrapBlkDev() - Create CBIO wrapper atop a BLK_DEV 
  182. .IP
  183. cbioShow() - Display information about a CBIO device
  184. .LP
  185. These CBIO API functions (except cbioLibInit()) are passed a CBIO_DEV_ID 
  186. handle in the first argument.   This handle (obtained from the subordinate 
  187. CBIO modules device creation routine) is used by the routine to verify the
  188. the CBIO device is valid and then to perform the requested operation
  189. on the specific CBIO device.
  190. When the CBIO_DEV_ID passed to the CBIO API routine is not a valid CBIO 
  191. handle, ERROR will be returned with the errno set to 
  192. S_cbioLib_INVALID_CBIO_DEV_ID (cbioLib.h).   
  193. Refer to the individual manual entries for each function for a complete 
  194. description.
  195. THE BASIC CBIO TO BLK_DEV WRAPPER MODULE
  196. The basic CBIO to BLK_DEV wrapper is a minimized disk cache using 
  197. simplified algorithms.   It is used to convert a legacy BLK_DEV 
  198. device into as CBIO device.  It may be used standalone with solid 
  199. state disks which do not have mechanical seek and rotational latency 
  200. delays, such flash cards.  It may also be used in conjunction with
  201. the dpartCbio and dcacheCbio libraries.  The DOS file system 
  202. dosFsDevCreate routine will call cbioWrapBlkDev() internally, so the file 
  203. system may be installed directly on top of a block driver BLK_DEV
  204. or it can be used with cache and partitioning support. 
  205. The function cbioWrapBlkDev() is used to create the CBIO wrapper atop
  206. a BLK_DEV device.
  207. The functions dcacheDevCreate and dpartDevCreate also both interally use 
  208. cbioDevVerify() and cbioWrapBlkDev() to either stack the new CBIO device 
  209. atop a validated CBIO device or to create a basic CBIO to BLK_DEV wrapper 
  210. as needed.  The user typically never needs to manually invoke the 
  211. cbioWrapBlkDev() or cbioDevVerify() functions.
  212. Please note that the basic CBIO BLK_DEV wrapper is inappropriate 
  213. for rotational media without the disk caching layer.  The services 
  214. provided by the dcacheCbio module are more appropriate for use on 
  215. rotational disk devices and will yeild superior performance
  216. when used.
  217. SEE ALSO
  218. .I "VxWorks Programmers Guide: I/O System"
  219. INCLUDE FILES
  220. cbioLib.h
  221. INTERNAL
  222. CBIO module internal implementation details
  223. This section describes information concerning CBIO modules themselves.
  224. Users of CBIO modules use only the public CBIO API.  It is not recommend 
  225. that the information presented in this section be used to circumvent 
  226. the public CBIO API.  All the private data structures presented herein 
  227. are private and are indeed subject to change without notice.
  228. Refer to the source file src/usr/ramDiskCbio.c for an implementation 
  229. example of a CBIO module.  
  230. The CBIO_DEV structure (PRIVATE)
  231. The common fundamental component of every CBIO device is its CBIO_DEV 
  232. structure.   The CBIO_DEV_ID is a pointer to a CBIO_DEV structure.  
  233. The CBIO_DEV is defined in the WRS private cbioLibP.h header file.
  234. Every instance of a CBIO device has its own CBIO_DEV structure.
  235. Every CBIO module has code for creating a CBIO device.  This code
  236. returns a pointer to the CBIO_DEV structure, ie a CBIO_DEV_ID handle.
  237. A CBIO_DEV structure contains the following members:
  238. VxWorks objects
  239. .CS
  240.     HANDLE cbioHandle;
  241. .CE
  242. This is used for handle verification of the CBIO device.  
  243. See also handleLibP.h.
  244. .CS
  245.     SEMAPHORE cbioMutex;
  246. .CE
  247. This is the semaphore provided by semMLib which will be used 
  248. provide mutual exclusion for the CBIO device.  
  249. Functions
  250. .CS
  251.     CBIO_FUNCS * pFuncs;
  252. .CE
  253. This member of the CBIO_DEV structure is a pointer to a 
  254. CBIO_FUNCS structure.  The CBIO_FUNCS structure is also
  255. a private data structure.   The CBIO_FUNCS structure
  256. contains the following members:
  257. .CS
  258.     STATUS (* cbioDevBlkRW)
  259. .CE
  260. Address of the block (sector) read and write routine for the CBIO device.
  261. .CS
  262.     STATUS (* cbioDevBytesRW)
  263. .CE
  264. Address of the byte oriented read and write routine for the CBIO device.
  265. .CS
  266.     STATUS (* cbioDevBlkCopy)
  267. .CE
  268. Address of the block to block copy routine for the CBIO device.
  269. .CS
  270.     STATUS (* cbioDevIoctl)
  271. .CE
  272. Address of the ioctl() routine for the CBIO device.
  273. One CBIO_FUNCS structure is typically statically allocated
  274. for each CBIO module.  Refer to ramDiskCbio.c for an example.
  275. Attributes
  276. .CS
  277.     char * cbioDesc;
  278. .CE
  279. This member of the CBIO_DEV structure is a pointer to a 
  280. printable descriptive character string for the CBIO device.
  281. .CS
  282.     short cbioMode;
  283. .CE
  284. Indicates the access permissions to the CBIO device. 
  285. Valid modes are O_RDONLY, O_WRONLY, and O_RDWR.
  286. .CS
  287.     BOOL readyChanged;
  288. .CE
  289. TRUE if the device ready status has changed, and the device 
  290. needs to be remounted (disk insertion).  FALSE if the device 
  291. ready status has not changed.
  292. .CS
  293.     CBIO_PARAMS     cbioParams;
  294. .CE
  295. The next CBIO_DEV member is a CBIO_PARAMS (cbioLib.h) structure.   
  296. This contains physical information about the device.  The members 
  297. of the CBIO_PARAMS structure are:
  298. .CS
  299.     BOOL cbioParams.cbioRemovable;
  300. .CE
  301. TRUE if the device is removable, FALSE if the device is not removable.
  302. .CS
  303.     block_t cbioParams.nBlocks;
  304. .CE
  305. Total number of blocks on this CBIO device
  306. .CS
  307.     size_t bytesPerBlk;
  308. .CE
  309. The number of bytes in a block.  512 is a typical value.
  310. .CS
  311.     size_t blockOffset;
  312. .CE
  313. The number of blocks offset from block zero on the subordinate device. 
  314. .CS
  315.     short cbioParams.blocksPerTrack;
  316. .CE
  317. The number of blocks per track on this device.
  318. .CS
  319.     short nHeads;
  320. .CE
  321. The number of heads on this device.
  322. .CS
  323.     short retryCnt;
  324. .CE
  325. A counter indicating the total number of retries that
  326. have occurred since creating this device.
  327. .CS
  328.     block_t cbioParams.lastErrBlk;
  329. .CE
  330. The block number of the last error that occurred.
  331. .CS
  332.     int lastErrno;
  333. .CE
  334. The error code of the last encountered error.
  335. Implementation defined CBIO_DEV attributes
  336. .CS
  337.     caddr_t cbioMemBase;
  338.     size_t cbioMemSize;
  339. .CE
  340. These represent the base address and size of any memory 
  341. pool supplied to the CBIO module.
  342. .CS
  343.     u_long cbioPriv0; /@ Implementation defined @/
  344.     u_long cbioPriv1; /@ Implementation defined @/
  345.     u_long cbioPriv2; /@ Implementation defined @/
  346.     u_long cbioPriv3; /@ Implementation defined @/
  347.     u_long cbioPriv4; /@ Implementation defined @/
  348.     u_long cbioPriv5; /@ Implementation defined @/
  349.     u_long cbioPriv6; /@ Implementation defined @/
  350.     u_long cbioPriv7; /@ Implementation defined @/
  351.     CBIO_DEV_EXTRA * pDc ; /@ Implementation defined structure @/
  352. .CE
  353. These fields are implementation defined.
  354. Some developers may wish to create their own modules using the CBIO API.  
  355. The guidelines herein should be followed regardless of CBIO module type
  356. being designed.  The source file ramDiskCbio.c may be used as an 
  357. implementation example.
  358. CBIO modules have a CBIO device creation routine.   The routine 
  359. creates a CBIO_DEV structure and initializes all its fields.  
  360. Un-used function members are initialized to NULL.  CBIO modules 
  361. do not perform an iosDevAdd() call, and are akin to block device 
  362. drivers in that respect.  The creation routine returns a CBIO 
  363. handle of type CBIO_DEV_ID.
  364. CBIO modules have a block transfer routine. This routine transfers 
  365. between a user buffer and the lower layer (hardware, subordinate 
  366. CBIO, or BLK_DEV).  It is optimized for block transfers.  This 
  367. routine returns OK or ERROR and may otherwise set errno.
  368. This routine is declared:
  369. .CS
  370. STATUS xxCbioBlkRW /@ Read/Write blocks @/
  371.     (
  372.     CBIO_DEV_ID     dev,
  373.     block_t         startBlock,
  374.     block_t         numBlocks,
  375.     addr_t          buffer,
  376.     CBIO_RW         rw,
  377.     cookie_t *      pCookie
  378.     );
  379. .CE
  380. .IP
  381. dev - the CBIO handle of the device being accessed (from creation routine)
  382. .IP
  383. startBlock - the starting block of the transfer operation
  384. .IP
  385. numBlocks - the total number of blocks to transfer
  386. .IP
  387. buffer - address of the memory buffer used for the transfer
  388. .IP
  389. rw - indicates the direction of transfer up or down (READ/WRITE)
  390. .IP
  391. *pCookie - pointer to cookie used by upper layer such as dosFsLib(),
  392. it should be preserved.
  393. .LP
  394. CBIO modules have a byte transfer routine. This routine transfers 
  395. between a user buffer and the lower layer (hardware, subordinate CBIO,
  396. or BLK_DEV).  It is optimized for byte transfers.  This routine returns
  397. OK or ERROR and may otherwise set errno.
  398. This routine is declared:
  399. .CS
  400. LOCAL STATUS xxCbioBytesRW        /@ Read/Write bytes @/
  401.     (
  402.     CBIO_DEV_ID  dev,
  403.     block_t startBlock,
  404.     off_t offset,
  405.     addr_t buffer,
  406.     size_t nBytes,
  407.     CBIO_RW             rw,
  408.     cookie_t *          pCookie
  409.     );
  410. .CE
  411. .IP
  412. dev - the CBIO handle of the device being accessed (from creation routine)
  413. .IP
  414. startBlock - the starting block of the transfer operation
  415. .IP
  416. offset - offset in bytes from the beginning of the starting block
  417. .IP
  418. buffer - address of the memory buffer used for the transfer
  419. .IP
  420. nBytes - number of bytes to transfer
  421. .IP
  422. rw - indicates the direction of transfer up or down (READ/WRITE)
  423. .IP
  424. *pCookie - pointer to cookie used by upper layer such as dosFsLib(),
  425. it should be preserved.
  426. .LP
  427. CBIO modules have a block to block copy routine. This makes
  428. copies of one or more blocks on the lower layer (hardware, 
  429. subordinate CBIO, or BLK_DEV).   It is optimized for block
  430. copies on the subordinate layer.  This routine returns
  431. OK or ERROR and may otherwise set errno.
  432. This routine is declared:
  433. .CS
  434. LOCAL STATUS xxCbioBlkCopy  /@ Copy sectors @/
  435.     (
  436.     CBIO_DEV_ID        dev,
  437.     block_t         srcBlock,
  438.     block_t         dstBlock,
  439.     block_t         numBlocks
  440.     );
  441. .CE
  442. .IP
  443. dev - the CBIO handle of the device being accessed (from creation routine)
  444. .IP
  445. srcBlock - source start block of the copy
  446. .IP
  447. dstBlock - destination start block of the copy
  448. .IP
  449. num_block - number of blocks to copy
  450. .LP
  451. CBIO modules have an ioctl() routine. This performs the requested
  452. ioctl() operation.
  453. CBIO modules can expect the following ioctl() codes from cbioLib.h:
  454. .IP
  455. CBIO_RESET - reset the CBIO device.   When the third argument to the 
  456. CBIO_RESET ioctl is NULL, the code verifies that the disk is inserted 
  457. and is ready, after getting it to a known state.   When the 3rd argument 
  458. is a non-zero, it is assumed to be a BLK_DEV pointer and CBIO_RESET will 
  459. install a new subordinate block device.    This work is performed at the 
  460. BLK_DEV to CBIO layer, and all layers shall account for it.  A CBIO_RESET i
  461. indicates a possible change in device geometry, and the CBIO_PARAMS members 
  462. will be reinitialized after a CBIO_RESET.
  463. .IP
  464. CBIO_STATUS_CHK - check device status of CBIO device and lower layer
  465. .IP
  466. CBIO_DEVICE_LOCK - Prevent disk removal 
  467. .IP
  468. CBIO_DEVICE_UNLOCK - Allow disk removal
  469. .IP
  470. CBIO_DEVICE_EJECT - Unmount and eject device
  471. .IP
  472. CBIO_CACHE_FLUSH - Flush any dirty cached data
  473. .IP
  474. CBIO_CACHE_INVAL - Flush & Invalidate all cached data
  475. .IP
  476. CBIO_CACHE_NEWBLK - Allocate scratch block
  477. .LP
  478. The CBIO module may also implement other codes.  CBIO modules pass all 
  479. ioctl() requests to the lower layer also passing the argument before 
  480. performing the requested I/O operation.  This rule ensures changes in 
  481. device geometry (if any occur) etc. are reflected in the upper layer.  
  482. This routine returns OK or ERROR and may otherwise set errno.
  483. This routine is declared:
  484. .CS
  485. LOCAL STATUS xxCbioIoctl        /@ Misc control operations @/
  486.     (
  487.     CBIO_DEV_ID         dev,
  488.     UINT32              command,
  489.     addr_t              arg
  490.     );
  491. .CE
  492. .IP
  493. dev - the CBIO handle of the device being accessed (from creation routine)
  494. .IP
  495. command - ioctl() command being issued
  496. .IP
  497. arg - specific to the particular ioctl() function requested or un-used.
  498. .LP
  499. Need to add WV instrumentation.
  500. Need to beef up docs
  501. Need to add cbioDevDelete routine.
  502. */
  503. /* includes */
  504. #include "vxWorks.h"
  505. #include "private/dosFsVerP.h"
  506. #include "stdlib.h"
  507. #include "stdio.h"
  508. #include "semLib.h"
  509. #include "ioLib.h"
  510. #include "errno.h"
  511. #include "string.h"
  512. #include "tickLib.h"
  513. #include "sysLib.h"
  514. #include "taskLib.h"
  515. #include "logLib.h"
  516. #include "blkIo.h"
  517. #include "assert.h"
  518. #include "dosFsLib.h"
  519. #include "private/cbioLibP.h"
  520. /* defines */
  521. #undef DEBUG  /* define to debug cbioLib */
  522. #ifdef DEBUG
  523. #undef NDEBUG
  524. BOOL cbioDebug = FALSE ;
  525. #else
  526. #define NDEBUG
  527. #endif /* DEBUG */
  528. /* implementation defined fields for Wrapper use */
  529. #define cbioBlkShift cbioPriv0
  530. #define cbioDirtyMask cbioPriv1
  531. #define cbioBlkNo cbioPriv2
  532. /* Globals & Statics */
  533. LOCAL BOOL cbioInstalled ;
  534. LOCAL CBIO_DEV_ID cbioRecentDev = NULL ;
  535. #ifndef _WRS_DOSFS2_VXWORKS_AE
  536. OBJ_CLASS cbioClass ;
  537. CLASS_ID cbioClassId = &cbioClass ;
  538. #endif /* _WRS_DOSFS2_VXWORKS_AE */
  539. int  cbioMutexSemOptions = 
  540. (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
  541. /* forward declarations */
  542. STATUS cbioShow (CBIO_DEV_ID dev);
  543. int cbioRdyChk (CBIO_DEV_ID dev);
  544. LOCAL STATUS cbioWrapOk ();
  545. LOCAL STATUS blkWrapBytesRW( CBIO_DEV_ID dev, block_t startBlock,
  546. off_t offset, addr_t buffer, size_t nBytes,
  547. CBIO_RW rw, cookie_t *pCookie);
  548. LOCAL STATUS blkWrapBlkRW( CBIO_DEV_ID dev, block_t startBlock,
  549. block_t numBlocks, addr_t buffer, CBIO_RW rw, cookie_t * pCookie);
  550. LOCAL STATUS blkWrapBlkRWbuf( CBIO_DEV_ID dev, block_t startBlock,
  551. block_t numBlocks, addr_t buffer, CBIO_RW rw, cookie_t * pCookie);
  552. LOCAL STATUS blkWrapBlkCopy( CBIO_DEV_ID dev, block_t srcBlock,
  553. block_t dstBlock, block_t numBlocks);
  554. LOCAL STATUS blkWrapIoctl( CBIO_DEV_ID dev, UINT32  command, addr_t arg);
  555. LOCAL int shiftCalc (u_long mask);
  556. /* CBIO_FUNCS, one per CBIO module */
  557. LOCAL CBIO_FUNCS cbioFuncs = {(FUNCPTR) blkWrapBlkRW,
  558.       (FUNCPTR) blkWrapBytesRW,
  559.       (FUNCPTR) blkWrapBlkCopy,
  560.       (FUNCPTR) blkWrapIoctl};
  561. #ifdef __unused__
  562. LOCAL void blkWrapDiskSizeAdjust ( CBIO_DEV_ID dev);
  563. #endif /*__unused__*/
  564. /*******************************************************************************
  565. *
  566. * cbioLibInit - Initialize CBIO Library
  567. *
  568. * This function initializes the CBIO library, and will be called
  569. * when the first CBIO device is created, hence it does not need to
  570. * be called during system initialization.  It can be called mulitple
  571. * times, but will do nothing after the first call.
  572. *
  573. * RETURNS: OK or ERROR 
  574. *
  575. */
  576. STATUS cbioLibInit( void )
  577.     {
  578.     STATUS stat;
  579.     if( cbioInstalled )
  580. return OK;
  581. #ifdef _WRS_DOSFS2_VXWORKS_AE
  582.     /* Setup handle show routine. */
  583.     stat = handleShowConnect( handleTypeCbioHdl, (FUNCPTR) cbioShow );
  584. #else /* else, using VxWorks 5.x */
  585.     /* Allocate object space for CBIO_DEV and CBIO_FUNCS */
  586.     stat = classInit( cbioClassId,
  587.                 sizeof(CBIO_DEV),
  588.                 OFFSET( CBIO_DEV,objCore),
  589.                 (FUNCPTR) cbioDevCreate,        /* Create Routine */
  590.                 (FUNCPTR) NULL,         /* Init routine */
  591.                 (FUNCPTR) NULL                  /* Destroy routine */
  592.                 ) ;
  593.     classShowConnect( cbioClassId, (FUNCPTR) cbioShow );
  594. #endif /* _WRS_DOSFS2_VXWORKS_AE */
  595.     if (ERROR == stat)
  596. return (ERROR);
  597.     if( stat == OK )
  598. cbioInstalled = TRUE ;
  599.     return( stat );
  600.     }
  601. /*******************************************************************************
  602. *
  603. * cbioBlkRW - transfer blocks to or from memory
  604. * This routine verifies the CBIO device is valid and if so calls the devices 
  605. * block transfer routine.  The CBIO device performs block transfers 
  606. * between the device and memory.  
  607. *
  608. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  609. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  610. *
  611. * RETURNS OK if sucessful or ERROR if the handle is invalid, or if the
  612. * CBIO device routine returns ERROR.
  613. *
  614. */
  615. STATUS cbioBlkRW
  616.     (
  617.     CBIO_DEV_ID dev,  /* CBIO handle */
  618.     block_t startBlock, /* starting block of transfer */
  619.     block_t numBlocks,  /* number of blocks to transfer */
  620.     addr_t buffer, /* address of the memory buffer */
  621.     CBIO_RW rw, /* direction of transfer R/W */
  622.     cookie_t *   pCookie /* pointer to cookie */
  623.     )
  624.     {
  625.     if( OK != cbioDevVerify (dev))
  626. {
  627. return ERROR;
  628. }
  629.     return (dev->pFuncs->cbioDevBlkRW (dev,startBlock,
  630.                                      numBlocks,buffer, 
  631.                                      rw, pCookie));
  632.     }
  633. /*******************************************************************************
  634. *
  635. * cbioBytesRW - transfer bytes to or from memory
  636. * This routine verifies the CBIO device is valid and if so calls the devices
  637. * byte tranfer routine which transfers between a user buffer and the lower 
  638. * layer (hardware, subordinate CBIO, or BLK_DEV).  It is optimized for byte 
  639. * transfers.  
  640. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  641. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  642. *
  643. * RETURNS OK if sucessful or ERROR if the handle is invalid, or if the
  644. * CBIO device routine returns ERROR.
  645. *
  646. */
  647. STATUS cbioBytesRW
  648.     (
  649.     CBIO_DEV_ID  dev, /* CBIO handle */
  650.     block_t startBlock, /* starting block of the transfer */
  651.     off_t offset, /* offset into block in bytes */
  652.     addr_t buffer, /* address of data buffer */
  653.     size_t nBytes, /* number of bytes to transfer */
  654.     CBIO_RW rw, /* direction of transfer R/W */
  655.     cookie_t * pCookie /* pointer to cookie */
  656.     )
  657.     {
  658.     if( OK != cbioDevVerify (dev))
  659. {
  660. return ERROR;
  661. }
  662.     return (dev->pFuncs->cbioDevBytesRW(dev, startBlock,
  663.       offset, buffer,
  664.          nBytes, rw, pCookie));
  665.     }
  666. /*******************************************************************************
  667. *
  668. * cbioBlkCopy - block to block (sector to sector) tranfer routine
  669. *
  670. * This routine verifies the CBIO device is valid and if so calls the devices
  671. * block to block tranfer routine which makes copies of one or more blocks on 
  672. * the lower layer (hardware, subordinate CBIO, or BLK_DEV).   It is optimized 
  673. * for block to block copies on the subordinate layer.  
  674. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  675. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  676. *
  677. * RETURNS OK if sucessful or ERROR if the handle is invalid, or if the
  678. * CBIO device routine returns ERROR.
  679. *
  680. */
  681. STATUS cbioBlkCopy
  682.     (
  683.     CBIO_DEV_ID  dev, /* CBIO handle */
  684.     block_t srcBlock, /* source start block */
  685.     block_t dstBlock,  /* destination start block */
  686.     block_t numBlocks /* number of blocks to copy */
  687.     )
  688.     {
  689.     if( OK != cbioDevVerify (dev))
  690. {
  691. return ERROR;
  692. }
  693.     return (dev->pFuncs->cbioDevBlkCopy(dev, srcBlock,
  694.         dstBlock, numBlocks));
  695.     }
  696. /*******************************************************************************
  697. *
  698. * cbioIoctl - perform ioctl operation on device
  699. *
  700. * This routine verifies the CBIO device is valid and if so calls the devices
  701. * I/O control operation routine.
  702. * CBIO modules expect the following ioctl() codes:
  703. * .IP
  704. * CBIO_RESET - reset the CBIO device.   When the third argument to the ioctl
  705. * call accompaning CBIO_RESET is NULL, the code verifies that the disk is 
  706. * inserted and is ready, after getting it to a known state.   When the 3rd 
  707. * argument is a non-zero, it is assumed to be a BLK_DEV pointer and 
  708. * CBIO_RESET will install a new subordinate block device.    This work
  709. * is performed at the BLK_DEV to CBIO layer, and all layers shall account
  710. * for it.  A CBIO_RESET indicates a possible change in device geometry, 
  711. * and the CBIO_PARAMS members will be reinitialized after a CBIO_RESET.
  712. * .IP
  713. * CBIO_STATUS_CHK - check device status of CBIO device and lower layer
  714. * .IP
  715. * CBIO_DEVICE_LOCK - Prevent disk removal 
  716. * .IP
  717. * CBIO_DEVICE_UNLOCK - Allow disk removal
  718. * .IP
  719. * CBIO_DEVICE_EJECT - Unmount and eject device
  720. * .IP
  721. * CBIO_CACHE_FLUSH - Flush any dirty cached data
  722. * .IP
  723. * CBIO_CACHE_INVAL - Flush & Invalidate all cached data
  724. * .IP
  725. * CBIO_CACHE_NEWBLK - Allocate scratch block
  726. * .LP
  727. *
  728. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  729. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  730. *
  731. * RETURNS OK if sucessful or ERROR if the handle is invalid, or if the
  732. * CBIO device routine returns ERROR.
  733. */
  734. STATUS cbioIoctl
  735.     (
  736.     CBIO_DEV_ID dev, /* CBIO handle */
  737.     int command, /* ioctl command to be issued */
  738.     addr_t arg /* arg - specific to ioctl */
  739.     )
  740.     {
  741.     if( OK != cbioDevVerify (dev))
  742. {
  743. return ERROR;
  744. }
  745.     return (dev->pFuncs->cbioDevIoctl(dev, command, arg));
  746.     }
  747. /*******************************************************************************
  748. *
  749. * cbioModeGet - return the mode setting for CBIO device
  750. *
  751. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  752. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  753. * This routine is not protected by a semaphore.
  754. *
  755. * This routine confirms if the current layer is a CBIO to BLKDEV wrapper 
  756. * or a CBIO to CBIO layer. Depending on the current layer it either 
  757. * returns the mode from BLK_DEV or calls cbioModeGet() recursively.
  758. *
  759. * RETURNS  O_RDONLY, O_WRONLY, or O_RDWR or ERROR 
  760. */
  761. int cbioModeGet
  762.     (
  763.     CBIO_DEV_ID dev /* CBIO handle */
  764.     )
  765.     {
  766.     BLK_DEV *pBd;
  767.     if( OK != cbioDevVerify (dev))
  768. {
  769. return ERROR;
  770. }
  771.     /*
  772.      * SPR#67729: isDriver is TRUE for a CBIO to BLKDEV layer and ramDiskCbio.
  773.      * In case of ramDiskCbio the blkSubDev is set to NULL since it is a CBIO 
  774.      * layer. There should be some reference to the sub devices, either 
  775.      * blkSubDev or cbioSubDev. 
  776.      */
  777.     if((dev->blkSubDev != NULL) || (dev->cbioSubDev != NULL))       
  778.      {                      
  779. if( dev->isDriver == TRUE) /* Boolean identifying the current layer */
  780.     {
  781.             if(dev->blkSubDev == NULL) 
  782.         {
  783. return(CBIO_MODE (dev)); /* For ramDiskCbio */
  784.         }
  785.     else
  786. {
  787.         pBd = dev->blkSubDev;
  788.         return (pBd->bd_mode);
  789. }
  790.     }    
  791. else
  792.     return ( cbioModeGet(dev->cbioSubDev)); /* For CBIO to CBIO */
  793. }
  794.     
  795.     return (ERROR);
  796.     }
  797. /*******************************************************************************
  798. *
  799. * cbioModeSet - set mode for CBIO device
  800. * Valid modes are O_RDONLY, O_WRONLY, or O_RDWR.
  801. *
  802. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  803. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  804. * This routine is not protected by a semaphore.
  805. * This routine confirms if the current layer is a CBIO to BLKDEV wrapper 
  806. * or a CBIO to CBIO layer. Depending on the current layer it either 
  807. * sets the mode of the BLK_DEV or calls cbioModeSet() recursively.
  808. *
  809. * RETURNS  OK or ERROR if mode is not set.
  810. *
  811. */
  812. STATUS cbioModeSet
  813.     (
  814.     CBIO_DEV_ID dev,  /* CBIO handle */
  815.     int mode /* O_RDONLY, O_WRONLY, or O_RDWR */
  816.     )
  817.     {
  818.     BLK_DEV *pBd;
  819.     if( OK != cbioDevVerify (dev))
  820. {
  821. return ERROR;
  822. }
  823.     /*
  824.      * SPR#67729: isDriver is TRUE for a CBIO to BLKDEV layer and ramDiskCbio.
  825.      * In case of ramDiskCbio the blkSubDev is set to NULL since it is a CBIO
  826.      * layer. There should be some reference to the sub devices, either 
  827.      * blkSubDev or cbioSubDev.
  828.      */
  829.     if((dev->blkSubDev != NULL) || (dev->cbioSubDev != NULL))
  830. {
  831.         if(dev->isDriver == TRUE)  /* Boolean identifying the current layer */ 
  832.     {
  833.     if(dev->blkSubDev == NULL)
  834.         {
  835. CBIO_MODE(dev) = mode; /* For ramDiskCbio */
  836.         return (OK);
  837.         }
  838.     else
  839. {
  840.         pBd = dev->blkSubDev;
  841.         pBd->bd_mode = mode;
  842.                 CBIO_MODE (dev) = mode;
  843.         return (OK);
  844. }
  845.     }
  846. else       
  847.             return (cbioModeSet (dev->cbioSubDev, mode)); /* For CBIO to CBIO */
  848. }
  849.     return (ERROR);
  850.     }
  851. /*******************************************************************************
  852. *
  853. * cbioRdyChgdGet - determine ready status of CBIO device
  854. *
  855. * For example 
  856. * .CS
  857. *    switch (cbioRdyChgdGet (cbioDeviceId)) 
  858. *        {
  859. *        case TRUE:
  860. *            printf ("Disk changed.n");
  861. *            break;
  862. *        case FALSE:
  863. *            printf ("Disk has not changed.n");
  864. *            break;
  865. *        case ERROR:
  866. *            printf ("Not a valid CBIO device.n");
  867. *            break;
  868. *        default:
  869. *        break;
  870. *        }
  871. * .CE
  872. *
  873. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  874. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  875. * This routine is not protected by a semaphore.
  876. *
  877. * This routine will check down to the driver layer to see if any lower
  878. * layer has its ready changed bit set to TRUE.  If so, this routine returns
  879. * TRUE.  If no lower layer has its ready changed bit set to TRUE, this layer
  880. * returns FALSE.
  881. *
  882. * RETURNS  TRUE if device ready status has changed, else FALSE if 
  883. * the ready status has not changed, else ERROR if the CBIO_DEV_ID is invalid.
  884. *
  885. */
  886. int cbioRdyChgdGet
  887.     (
  888.     CBIO_DEV_ID dev /* CBIO handle */
  889.     )
  890.     {
  891.     if( OK != cbioDevVerify (dev))
  892. {
  893. return (ERROR);
  894. }
  895.     /* check the current layers (dev) ready changed setting */
  896.     if (TRUE == CBIO_READYCHANGED(dev))
  897.         {
  898.         /* this CBIO device's ready changed bit is set, return TRUE */
  899.         return (TRUE);
  900.         }
  901.     /*
  902.      * isDriver is TRUE for a CBIO to BLKDEV layer and ramDiskCbio.
  903.      * In case of ramDiskCbio the blkSubDev is set to NULL since it is a CBIO
  904.      * layer. There should be some reference to the sub devices, either
  905.      * blkSubDev or cbioSubDev.
  906.      */
  907.     if((dev->blkSubDev != NULL) || (dev->cbioSubDev != NULL))
  908.         {
  909.         if(TRUE == dev->isDriver) /* Boolean identifying the current layer */
  910.             {
  911.             if(NULL == dev->blkSubDev)
  912.                 {
  913. /* 
  914.  * This is a CBIO driver (no subordinate CBIO present).
  915.  * Above, we have already checked for the 'dev' ready 
  916.  * changed bit being TRUE, so we may return FALSE.
  917.  */
  918.                 return (FALSE); /* For ramDiskCbio */
  919.                 }
  920.             else
  921.                 {
  922. /* 
  923.  * This is a CBIO to BLK_DEV layer, so there is a BLK_DEV 
  924.  * device below this CBIO device.  Return TRUE or FALSE 
  925.  * depending upon the BLK_DEV's ready changed bit setting.
  926.  */
  927.                 return (((BLK_DEV *)(dev->blkSubDev))->bd_readyChanged);
  928.                         
  929.                 }
  930.             }
  931.         else
  932.             {
  933.             /* 
  934.      * This is a CBIO to CBIO layer,  and it doesn't have
  935.      * its ready changed bit set, however a layer below us
  936.      * may have its bit set, so we recurse down a layer. 
  937.      */
  938.             return (cbioRdyChgdGet(dev->cbioSubDev)); 
  939.             }
  940.         }
  941.     /* should never get here */
  942. #ifdef DEBUG
  943.         logMsg("cbioRdyChgdGet: bad device 0x%08lxn",
  944. (long unsigned int)dev,0,0,0,0,0);
  945. #endif
  946.     return (ERROR);
  947.     }
  948. /*******************************************************************************
  949. *
  950. * cbioRdyChgdSet - force a change in ready status of CBIO device
  951. *
  952. * Pass TRUE in status to force READY status change.
  953. *
  954. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  955. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  956. * If status is not passed as TRUE or FALSE, ERROR is returned.
  957. * This routine is not protected by a semaphore.
  958. *
  959. * This routine sets readyChanged bit of passed CBIO_DEV.
  960. *
  961. * RETURNS  OK or ERROR if the device is invalid or status is not TRUE or FALSE.
  962. *
  963. */
  964. STATUS cbioRdyChgdSet
  965.     (
  966.     CBIO_DEV_ID dev, /* CBIO handle */
  967.     BOOL status /* TRUE/FALSE */
  968.     )
  969.     {
  970.     if((OK != cbioDevVerify (dev)) || (TRUE != status && FALSE != status))
  971. {
  972. return ERROR;
  973. }
  974.     CBIO_READYCHANGED(dev) = status; /* For ramDiskCbio */
  975.     return (OK);
  976.     }
  977. /*******************************************************************************
  978. *
  979. * cbioLock - obtain CBIO device semaphore.
  980. *
  981. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  982. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  983. *
  984. * RETURNS: OK or ERROR if the CBIO handle is invalid or semTake fails.
  985. */
  986. STATUS cbioLock
  987.     (
  988.     CBIO_DEV_ID dev, /* CBIO handle */
  989.     int timeout /* timeout in ticks */
  990.     )
  991.     {
  992.     if( OK != cbioDevVerify (dev))
  993. {
  994. return ERROR;
  995. }
  996.     return (semTake(dev->cbioMutex, timeout));
  997.     } 
  998.     
  999. /*******************************************************************************
  1000. *
  1001. * cbioUnlock - release CBIO device semaphore.
  1002. *
  1003. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  1004. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  1005. *
  1006. * RETURNS: OK or ERROR if the CBIO handle is invalid or the semGive fails.
  1007. */
  1008. STATUS cbioUnlock
  1009.     (
  1010.     CBIO_DEV_ID dev  /* CBIO handle */
  1011.     )
  1012.     {
  1013.     if( OK != cbioDevVerify (dev))
  1014. {
  1015. return ERROR;
  1016. }
  1017.     return (semGive(dev->cbioMutex));
  1018.     }
  1019. /*******************************************************************************
  1020. *
  1021. * cbioParamsGet - fill in CBIO_PARAMS structure with CBIO device parameters
  1022. *
  1023. * If the CBIO_DEV_ID passed to this routine is not a valid CBIO handle,
  1024. * ERROR will be returned with errno set to S_cbioLib_INVALID_CBIO_DEV_ID
  1025. *
  1026. * RETURNS: OK or ERROR if the CBIO handle is invalid.
  1027. */
  1028. STATUS cbioParamsGet
  1029.     (
  1030.     CBIO_DEV_ID dev, /* CBIO handle */
  1031.     CBIO_PARAMS * pCbioParams /* pointer to CBIO_PARAMS */
  1032.     )
  1033.     {
  1034.     if( OK != cbioDevVerify (dev))
  1035. {
  1036. return ERROR;
  1037. }
  1038.     *pCbioParams = dev->cbioParams;
  1039.     return (OK);
  1040.     }
  1041. /*******************************************************************************
  1042. *
  1043. * cbioRdyChk - print ready changed setting of CBIO layer and its subordinates
  1044. *
  1045. * NOMANUAL
  1046. */
  1047. int cbioRdyChk
  1048.     (
  1049.     CBIO_DEV_ID dev             /* CBIO handle */
  1050.     )
  1051.     {
  1052.     if( OK != cbioDevVerify (dev))
  1053.         {
  1054.         printf ("tCBIO_DEV_ID 0x%08lx is invalid per cbioDevVerify.n", 
  1055.                 (unsigned long) dev);
  1056.         return (ERROR);
  1057.         }
  1058.     /* check the current layers (dev) readyChanged bit setting */
  1059.     printf ("tCBIO_DEV_ID 0x%08lx ready changed is %d.n", 
  1060.                 (unsigned long) dev, CBIO_READYCHANGED (dev));
  1061.     /*
  1062.      * isDriver is TRUE for a CBIO to BLKDEV layer and ramDiskCbio.
  1063.      * In case of ramDiskCbio the blkSubDev is set to NULL since it is a CBIO
  1064.      * layer. There should be some reference to the sub devices, either
  1065.      * blkSubDev or cbioSubDev.
  1066.      */
  1067.     if((dev->blkSubDev != NULL) || (dev->cbioSubDev != NULL))
  1068.         {
  1069.         if(TRUE == dev->isDriver) /* Boolean identifying the current layer */
  1070.             {
  1071.             if(NULL == dev->blkSubDev)
  1072.                 {
  1073.                 /*
  1074.                  * This is a CBIO driver (no subordinate CBIO present).
  1075.                  * Above, we have already displayed the 'dev' ready
  1076.                  * changed bit,  so we may return.
  1077.                  */
  1078.                 return (OK); /* For ramDiskCbio */
  1079.                 }
  1080.             else
  1081.                 {
  1082.                 /*
  1083.                  * This is a CBIO to BLK_DEV layer, so there is a BLK_DEV
  1084.                  * device below this CBIO device.  Return TRUE or FALSE,
  1085.                  * depending upon the BLK_DEV's ready changed bit setting.
  1086.                  */
  1087.                 printf ("tBLK_DEV ptr 0x%08lx ready changed is %d.n", 
  1088.                             (unsigned long) dev->blkSubDev,  
  1089.                             dev->blkSubDev->bd_readyChanged );
  1090.                 return (OK);
  1091.                 }
  1092.             }
  1093.         else
  1094.             {
  1095.             /*
  1096.              * This is a CBIO to CBIO layer,  and it doesn't have
  1097.              * its ready changed bit set, however a layer below us
  1098.              * may have its bit set, so we recurse down a layer.
  1099.              */
  1100.             return (cbioRdyChk (dev->cbioSubDev));
  1101.             }
  1102.         }
  1103.     /* should never get here */
  1104. #ifdef DEBUG
  1105.         logMsg("cbioRdyChk: bad device 0x%08lxn",
  1106.                 (long unsigned int)dev,0,0,0,0,0);
  1107. #endif
  1108.     return (ERROR);
  1109.     }
  1110. /*******************************************************************************
  1111. *
  1112. * cbioShow - print information about a CBIO device
  1113. *
  1114. * This function will display on standard output all information which
  1115. * is generic for all CBIO devices.
  1116. * See the CBIO modules particular device show routines for displaying
  1117. * implementation-specific information.
  1118. *
  1119. * It takes two arguments:
  1120. *
  1121. * A CBIO_DEV_ID which is the CBIO handle to display or NULL for 
  1122. * the most recent device.
  1123. *
  1124. * RETURNS OK or ERROR if no valid CBIO_DEV is found.
  1125. *
  1126. * SEE ALSO: dcacheShow(), dpartShow()
  1127. *
  1128. */
  1129. STATUS cbioShow
  1130.     (
  1131.     CBIO_DEV_ID dev /* CBIO handle */
  1132.     )
  1133.     {
  1134.     unsigned long size, factor = 1 ;
  1135.     char * units ;
  1136.     if( dev == NULL )
  1137. dev = cbioRecentDev;
  1138.     if( dev == NULL )
  1139. {
  1140. errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1141. return ERROR;
  1142. }
  1143.     if( OK != cbioDevVerify (dev))
  1144. {
  1145. return ERROR;
  1146. }
  1147.     if( dev->cbioParams.bytesPerBlk == 0 )
  1148. {
  1149. errno = EINVAL;
  1150. return ERROR;
  1151. }
  1152.     printf("Cached Block I/O Device, handle=%#lxn", (u_long)dev);
  1153.     printf("tDescription: %sn", dev->cbioDesc);
  1154.     /* calculate disk size, while avoiding 64-bit arithmetic */
  1155.     if( dev->cbioParams.bytesPerBlk < 1024 )
  1156. {
  1157. factor = 1024 / dev->cbioParams.bytesPerBlk ;
  1158. size = dev->cbioParams.nBlocks / factor ;
  1159. units = "Kbytes" ;
  1160. }
  1161.     else /* if( dev->cbioParams.bytesPerBlk >= 1024 ) */
  1162. {
  1163. factor = dev->cbioParams.bytesPerBlk / 1024 ;
  1164. size = (dev->cbioParams.nBlocks / 1024) * factor ;
  1165. units = "Mbytes" ;
  1166. }
  1167.     if(( size > 10000 ) && (0 == strcmp (units,"Kbytes")))
  1168. {
  1169. units = "Mbytes" ;
  1170. size /= 1024 ;
  1171. }
  1172.     if(( size > 10000 ) && (0 == strcmp(units, "Mbytes")))
  1173. {
  1174.         units = "Gbytes" ;
  1175. size /= 1024 ;
  1176. }
  1177.     printf("tDisk size %ld %s, RAM Size %d bytesn",
  1178. size, units, (int) dev->cbioMemSize );
  1179.     printf("tBlock size %d, heads %d, blocks/track %d, # of blocks %ldn",
  1180. (int) dev->cbioParams.bytesPerBlk, 
  1181.         dev->cbioParams.nHeads, dev->cbioParams.blocksPerTrack,
  1182. (block_t) dev->cbioParams.nBlocks );
  1183.     printf("tpartition offset %ld blocks, type %s, Media changed %sn",
  1184. (block_t) dev->cbioParams.blockOffset, 
  1185. (dev->cbioParams.cbioRemovable) ? "Removable" : "Fixed",
  1186. ((TRUE == CBIO_READYCHANGED(dev)) ? "Yes" : "No" ));
  1187.     if( dev->cbioParams.lastErrno != 0)
  1188. printf("tLast error errno=%x, block=%ldn",
  1189.     dev->cbioParams.lastErrno, dev->cbioParams.lastErrBlk );
  1190.     printf ("n   Current ready changed bit"
  1191.             " for this layer and all subordinates:n");
  1192.     cbioRdyChk (dev);
  1193.     /* TBD: embedded objects */
  1194.     return (OK);
  1195.     }
  1196. /*******************************************************************************
  1197. *
  1198. * cbioDevVerify - verify CBIO_DEV_ID 
  1199. *
  1200. * The purpose of this function is to determine if the device complies with the 
  1201. * CBIO interface.  It can be used to verify a CBIO handle before it is passed 
  1202. * to dosFsLib, rawFsLib, usrFdiskPartLib, or other CBIO modules which expect a 
  1203. * valid CBIO interface.  
  1204. *
  1205. * The device handle provided to this function, <device> is verified to be a 
  1206. * CBIO device.  If <device> is not a CBIO device ERROR is returned with errno 
  1207. * set to S_cbioLib_INVALID_CBIO_DEV_ID
  1208. *
  1209. * The dcacheCbio and dpartCbio CBIO modules (and dosFsLib) use this function 
  1210. * internally, and therefore this function need not be otherwise invoked when 
  1211. * using compliant CBIO modules.
  1212. *
  1213. * RETURNS: OK or ERROR if not a CBIO device, if passed a NULL address, or 
  1214. * if the check could cause an unaligned access. 
  1215. *
  1216. * SEE ALSO: dosFsLib, dcacheCbio, dpartCbio
  1217. */
  1218. STATUS cbioDevVerify
  1219.     (
  1220.     CBIO_DEV_ID device /* CBIO_DEV_ID to be verified */
  1221.     )
  1222.     {
  1223.     /* SPR#71720, avoid NULL access */ 
  1224.     if (NULL == device)
  1225. {
  1226.         errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1227. return(ERROR);
  1228. }
  1229.     /* SPR#71720, avoid causing unaligned pointer access. */
  1230.     if (FALSE == (_WRS_ALIGN_CHECK(device,CBIO_DEV)))
  1231. {
  1232.         errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1233. return(ERROR);
  1234. }
  1235. #ifdef _WRS_DOSFS2_VXWORKS_AE
  1236.     /* if the input is a valid CBIO device, return it */
  1237.     if( OK == HANDLE_VERIFY( &device->cbioHandle, handleTypeCbioHdl ))
  1238. {
  1239. return( OK );
  1240. }
  1241. #else
  1242.     if(OK == OBJ_VERIFY( device, cbioClassId ) )
  1243. {
  1244. return (OK);
  1245. }
  1246. #endif /* _WRS_DOSFS2_VXWORKS_AE */
  1247.     else 
  1248. {
  1249. #ifdef DEBUG
  1250.         logMsg("cbioDevVerify: device 0x%08lx is not a CBIO pointern",
  1251. (long unsigned int)device,0,0,0,0,0);
  1252. #endif
  1253.         errno = S_cbioLib_INVALID_CBIO_DEV_ID;
  1254. return (ERROR);
  1255. }
  1256.     }
  1257. /*******************************************************************************
  1258. *
  1259. * cbioWrapBlkDev - create CBIO wrapper atop a BLK_DEV device
  1260. *
  1261. * The purpose of this function is to make a blkIo (BLK_DEV) device comply 
  1262. * with the CBIO interface via a wrapper.  
  1263. *
  1264. * The device handle provided to this function, <device> is verified to 
  1265. * be a blkIo device.  A lean CBIO to BLK_DEV wrapper is then created for 
  1266. * a valid blkIo device.  The returned CBIO_DEV_ID device handle may be 
  1267. * used with dosFsDevCreate(), dcacheDevCreate(), and any other routine 
  1268. * expecting a valid CBIO_DEV_ID handle.
  1269. *
  1270. * To verify a blkIo pointer we see that all mandatory functions
  1271. * are not NULL.
  1272. *
  1273. * Note that if a valid CBIO_DEV_ID is passed to this function, it will 
  1274. * simply be returned without modification.
  1275. *
  1276. * The dosFsLib, dcacheCbio, and dpartCbio CBIO modules use this function 
  1277. * internally, and therefore this function need not be otherwise invoked 
  1278. * when using those CBIO modules.
  1279. *
  1280. * RETURNS: a CBIO device pointer, or NULL if not a blkIo device
  1281. *
  1282. * SEE ALSO: dosFsLib, dcacheCbio, dpartCbio
  1283. *
  1284. */
  1285. CBIO_DEV_ID cbioWrapBlkDev
  1286.     (
  1287.     BLK_DEV * pDevice /* BLK_DEV * device pointer */
  1288.     )
  1289.     {
  1290.     CBIO_DEV * pDev = NULL ;
  1291.     BLK_DEV * pBd = pDevice ;
  1292.     u_char shift ;
  1293.     cbioLibInit(); /* just in case */
  1294.     if (NULL == pDevice)
  1295. {
  1296. goto bad_blkIo ;
  1297. }
  1298.     /* simply return any valid CBIO_DEV_ID as is */
  1299.     if (OK == cbioDevVerify((CBIO_DEV_ID)pDevice))
  1300. {
  1301. return ((CBIO_DEV_ID) pDevice);
  1302. }
  1303.     /* blkIo has no clear mechanism for verification, improvise (HELP)*/
  1304.     if( (pBd->bd_blkRd == NULL) || (pBd->bd_blkWrt == NULL) ||
  1305. (pBd->bd_ioctl == NULL) ) 
  1306. goto bad_blkIo ;
  1307.     shift = shiftCalc( pBd->bd_bytesPerBlk );
  1308.     /* we place a dummy function if statusChk is not provided */
  1309.     if( pBd->bd_statusChk == NULL )
  1310. pBd->bd_statusChk = cbioWrapOk ;
  1311.     /* create our CBIO handle, no cache memory (yet) */
  1312.     pDev = (CBIO_DEV_ID) cbioDevCreate ( NULL, 0 );
  1313.     if( pDev == NULL )
  1314. return( NULL );
  1315.     pDev->pDc = pBd ;
  1316.     pDev->cbioDesc = "CBIO to BLK_DEV Wrapper" ;
  1317.     pDev->cbioParams.cbioRemovable = pBd->bd_removable ;
  1318.     pDev->readyChanged = pBd->bd_readyChanged ;
  1319.     pDev->cbioParams.nBlocks = pBd->bd_nBlocks ;
  1320.     pDev->cbioParams.bytesPerBlk = pBd->bd_bytesPerBlk ;
  1321.     pDev->cbioParams.blocksPerTrack = pBd->bd_blksPerTrack ;
  1322.     pDev->cbioParams.nHeads = pBd->bd_nHeads ;
  1323.     pDev->cbioParams.blockOffset = 0;
  1324.     pDev->cbioMode = pBd->bd_mode ;
  1325.     pDev->cbioParams.lastErrBlk = NONE ;
  1326.     pDev->cbioParams.lastErrno = 0 ;
  1327.     pDev->cbioBlkNo = NONE;
  1328.     pDev->cbioDirtyMask = 0;
  1329.     pDev->cbioBlkShift = shift ;
  1330.     pDev->pFuncs = &cbioFuncs;
  1331.     /* SPR#67729: Fill in the members subDev and isDriver appropriately */
  1332.     pDev->blkSubDev                     = pBd; /* Pointer to lower BlkDev */
  1333.     pDev->cbioSubDev                    = NULL; /* Pointer to lower BlkDev */
  1334.     pDev->isDriver                      = TRUE;/* ==TRUE since this is a  */
  1335.                                               /* CBIO to BLKDEV layer */
  1336.     return (pDev) ;
  1337. bad_blkIo:
  1338.     logMsg("cbioWrapBlkDev: BLK_DEV pointer 0x%08lx appears invalid.n", 
  1339.            (unsigned long) pDevice,0,0,0,0,0);
  1340.     return (NULL) ;
  1341.     }
  1342. /*******************************************************************************
  1343. *
  1344. * cbioDevCreate - Initialize a CBIO device (Generic)
  1345. *
  1346. * This routine will create an empty CBIO_DEV structure and
  1347. * return a handle to that structure (CBIO_DEV_ID).   
  1348. * This routine is intended to be used by CBIO modules only.
  1349. * See cbioLibP.h
  1350. *
  1351. * RETURNS CBIO_DEV_ID or NULL if ERROR.
  1352. */
  1353. CBIO_DEV_ID cbioDevCreate
  1354.     (
  1355.     caddr_t   ramAddr,  /* where it is in memory (0 = KHEAP_ALLOC) */
  1356.     size_t ramSize /* pool size */
  1357.     )
  1358.     {
  1359.     CBIO_DEV * pDev = NULL ;
  1360.     caddr_t pBase = NULL ;
  1361.     if( !cbioInstalled )
  1362. if( cbioLibInit() == ERROR )
  1363.      goto error;
  1364.     if (ramSize != 0)
  1365. {
  1366. if( ramAddr == NULL )
  1367.     pBase = KHEAP_ALLOC(ramSize);
  1368. else
  1369.     pBase = ramAddr ;
  1370. if( pBase == NULL )
  1371.     goto error ;
  1372. }
  1373.     /* allocate and initialize the device control structure */
  1374. #ifdef _WRS_DOSFS2_VXWORKS_AE
  1375.     pDev = (CBIO_DEV *) KHEAP_ALLOC((sizeof (CBIO_DEV)));
  1376. #else
  1377.     pDev = (CBIO_DEV *) objAlloc(cbioClassId);
  1378. #endif /* _WRS_DOSFS2_VXWORKS_AE */
  1379.     if( pDev == NULL )
  1380. goto error;
  1381.     /* init Common fields */
  1382.     pDev->cbioMutex = semMCreate (cbioMutexSemOptions);
  1383.     if( NULL == pDev->cbioMutex )
  1384. {
  1385. goto error ;
  1386. }
  1387.     pDev->readyChanged = FALSE ;
  1388.     pDev->cbioParams.lastErrBlk = NONE ;
  1389.     pDev->cbioParams.lastErrno = 0 ;
  1390.     pDev->cbioMemBase = pBase ;
  1391.     pDev->cbioMemSize = ramSize ;
  1392.     /* pointer to method functions needs to be filled later */
  1393.     pDev->pFuncs = NULL ;
  1394.     /* init the handle */
  1395. #ifdef _WRS_DOSFS2_VXWORKS_AE
  1396.     handleInit (&pDev->cbioHandle, handleTypeCbioHdl);
  1397. #else
  1398.     /* make this object belong to its class */
  1399.     objCoreInit (&pDev->objCore, cbioClassId);
  1400. #endif /* _WRS_DOSFS2_VXWORKS_AE */
  1401.     cbioRecentDev = pDev ;
  1402.     /* return device handle */
  1403.     return( (CBIO_DEV_ID) pDev );
  1404. error:
  1405.     if( pBase != NULL )
  1406. KHEAP_FREE(pBase);
  1407.     if( pDev != NULL )
  1408. KHEAP_FREE((char *)pDev);
  1409.     return ( NULL );
  1410.     }
  1411. /*******************************************************************************
  1412. *
  1413. * shiftCalc - calculate how many shift bits
  1414. *
  1415. * How many shifts <N> are needed such that <mask> == 1 << <N>
  1416. * This is very useful for replacing multiplication with shifts,
  1417. * where it is known a priori that the multiplier is 2^k.
  1418. *
  1419. * RETURNS: Number of shifts.
  1420. */
  1421. LOCAL int shiftCalc
  1422.     (
  1423.     u_long mask
  1424.     )
  1425.     {
  1426.     int i;
  1427.     for (i=0; i<32; i++)
  1428. {
  1429. if (mask & 1)
  1430.     break ;
  1431. mask = mask >> 1 ;
  1432. }
  1433.     return( i );
  1434.     }
  1435. /*******************************************************************************
  1436. *
  1437. * cbioWrapOk - dummy function returning OK
  1438. *
  1439. */
  1440. LOCAL STATUS cbioWrapOk ()
  1441.     {
  1442.     return OK;
  1443.     }
  1444. /*******************************************************************************
  1445. *
  1446. * cbioBlkWrapBufCreate - create the local block buffer
  1447. *
  1448. */
  1449. LOCAL STATUS cbioBlkWrapBufCreate ( CBIO_DEV_ID pDev )
  1450.     {
  1451.     if( pDev->cbioMemBase != NULL &&
  1452. pDev->cbioMemSize != pDev->cbioParams.bytesPerBlk )
  1453. {
  1454. /* block size may have changed */
  1455. KHEAP_FREE(pDev->cbioMemBase);
  1456. pDev->cbioMemBase = 0;
  1457. pDev->cbioMemSize = 0;
  1458. }
  1459.     if( pDev->cbioMemBase == NULL && pDev->cbioMemSize == 0 )
  1460. {
  1461. pDev->cbioMemSize = pDev->cbioParams.bytesPerBlk ;
  1462. pDev->cbioMemBase = KHEAP_ALLOC(pDev->cbioMemSize);
  1463. if( pDev->cbioMemBase == NULL )
  1464.     {
  1465.     return ERROR;
  1466.     }
  1467. /* Overload the block I/O function, better own the mutex here */
  1468. pDev->pFuncs->cbioDevBlkRW = blkWrapBlkRWbuf ;
  1469. /* empty block */
  1470. pDev->cbioBlkNo = (u_long)NONE ;
  1471. pDev->cbioDirtyMask = 0;
  1472. return (OK);
  1473. }
  1474.     else 
  1475. {
  1476. errno = EINVAL;
  1477. return (ERROR);
  1478. }
  1479.     }
  1480. /*******************************************************************************
  1481. *
  1482. * blkWrapBlkRW - Read/Write blocks
  1483. *
  1484. * Wrapper block Read/Write function calls the blkIo functions
  1485. * directly, It does not deal with the tiny cache, and is used
  1486. * only when there is no Tiny cache for by byte-wise operations.
  1487. * When a tiny cache is installed, this function is overloaded
  1488. * with the blkWrapBlkRWbuf function, which deals with Tiny cache
  1489. * coherency and call this function subsequently.
  1490. *
  1491. * This routine transfers between a user buffer and the lower layer 
  1492. * BLK_DEV. It is optimized for block transfers.  
  1493. *
  1494. * RETURNS OK or ERROR and may otherwise set errno.
  1495. */
  1496. LOCAL STATUS blkWrapBlkRW
  1497.     (
  1498.     CBIO_DEV_ID dev,
  1499.     block_t startBlock,
  1500.     block_t numBlocks,
  1501.     addr_t buffer,
  1502.     CBIO_RW rw,
  1503.     cookie_t * pCookie
  1504.     )
  1505.     {
  1506.     CBIO_DEV * pDev = (void *) dev ;
  1507.     BLK_DEV * pBd = pDev->blkSubDev ;
  1508.     STATUS stat = ERROR;
  1509.     int retryCount = 0 ;
  1510. retryLoop:
  1511.     if (TRUE == pBd->bd_readyChanged || TRUE == CBIO_READYCHANGED(dev))
  1512. {
  1513. errno = S_ioLib_DISK_NOT_PRESENT ;
  1514. return (ERROR);
  1515. }
  1516.     if( startBlock > pDev->cbioParams.nBlocks ||
  1517. (startBlock+numBlocks) > pDev->cbioParams.nBlocks )
  1518. {
  1519. errno = EINVAL;
  1520. return (ERROR);
  1521. }
  1522.     switch( rw )
  1523. {
  1524. case CBIO_READ:
  1525.     stat = pBd->bd_blkRd( pBd, startBlock, numBlocks, buffer);
  1526.     break;
  1527. case CBIO_WRITE:
  1528.     stat = pBd->bd_blkWrt( pBd, startBlock, numBlocks, buffer);
  1529.     break;
  1530. default:
  1531.     errno = S_ioLib_UNKNOWN_REQUEST;
  1532.     return (ERROR);
  1533. }
  1534.     /* record error if any */
  1535.     if( stat == ERROR )
  1536. {
  1537. pDev->cbioParams.lastErrBlk = startBlock;
  1538. pDev->cbioParams.lastErrno = errno ;
  1539. if( errno == S_ioLib_DISK_NOT_PRESENT )
  1540.              {
  1541.      CBIO_READYCHANGED (dev) = TRUE;
  1542.              }
  1543. /* some block drivers dont do retires relying on dosFs1 for that */
  1544. if( (blkWrapIoctl( pDev, CBIO_STATUS_CHK, 0) == OK) &&
  1545.     ( retryCount++ < pBd->bd_retry ))
  1546.     {
  1547.     int tick = tickGet();
  1548.     /* if device was not obviously replaced, try to reset it */
  1549.     if( !(pBd->bd_readyChanged || CBIO_READYCHANGED(dev)) )
  1550. {
  1551. if( pBd->bd_reset != NULL )
  1552.     pBd->bd_reset( pBd );
  1553. do
  1554.     {
  1555.     if( blkWrapIoctl( pDev, CBIO_STATUS_CHK, 0) == OK)
  1556. goto retryLoop;
  1557.     taskDelay(5);
  1558.     } while( tickGet() < (UINT32) tick+sysClkRateGet() ) ;
  1559. }
  1560.     }
  1561. }
  1562.     return stat;
  1563.     }
  1564. /*******************************************************************************
  1565. *
  1566. * blkWrapBlkRWbuf - wrapper block I/O for coherency with tiny cache
  1567. *
  1568. * This routine transfers between a user buffer and the lower layer BLK_DEV
  1569. * It is optimized for block transfers.  
  1570. *
  1571. * RETURNS OK or ERROR and may otherwise set errno.
  1572. */
  1573. LOCAL STATUS blkWrapBlkRWbuf
  1574.     (
  1575.     CBIO_DEV_ID     dev,
  1576.     block_t         startBlock,
  1577.     block_t         numBlocks,
  1578.     addr_t          buffer,
  1579.     CBIO_RW         rw,
  1580.     cookie_t *      pCookie
  1581.     )
  1582.     {
  1583.     FAST CBIO_DEV * pDev = dev ;
  1584.     STATUS stat = OK ;
  1585.     if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR )
  1586. return ERROR;
  1587.     /* verify that there is a block buffer, if not, allocate one */
  1588.     if( pDev->cbioMemBase == NULL)
  1589. {
  1590. if( cbioBlkWrapBufCreate( pDev) == ERROR )
  1591.     {
  1592.     semGive(pDev->cbioMutex);
  1593.     return ERROR;
  1594.     }
  1595. }
  1596.     /* see if Tiny Cache contains a valid block */
  1597.     if( pDev->cbioBlkNo != (u_long) NONE )
  1598. {
  1599. /* see if the range touches the cached block */
  1600. if( (pDev->cbioBlkNo >= startBlock) &&
  1601.     (pDev->cbioBlkNo < startBlock+numBlocks) )
  1602.     {
  1603.     /* flush the current contents of the block buffer if dirty */
  1604.     if( pDev->cbioDirtyMask != 0 )
  1605. {
  1606. block_t cachedBlock = pDev->cbioBlkNo ;
  1607. pDev->cbioBlkNo = NONE ;
  1608. pDev->cbioDirtyMask = 0;
  1609. stat = blkWrapBlkRW(  pDev, cachedBlock, 1,
  1610.     pDev->cbioMemBase, CBIO_WRITE, NULL);
  1611. }
  1612.     else
  1613. {
  1614. /* else just forget about it */
  1615. pDev->cbioBlkNo = NONE ;
  1616. }
  1617.     }
  1618. }
  1619.     if( stat == ERROR )
  1620.         {
  1621.         semGive(pDev->cbioMutex); /* added semGive to fix SPR#76103 */
  1622.         return (ERROR);
  1623.         }                  
  1624.     stat = blkWrapBlkRW (dev, startBlock, numBlocks, buffer, rw, pCookie) ;
  1625.     semGive(pDev->cbioMutex);
  1626.     return stat ;
  1627.     }
  1628. /*******************************************************************************
  1629. *
  1630. * blkWrapBytesRW - Read/Write bytes
  1631. *
  1632. * In order to implement the byte-wise read/write operation, a tiny
  1633. * cache is implemented, which is used to store block data on which
  1634. * byte operations are performed.
  1635. *
  1636. * The tiny cache is a single disk block sized buffer at this time
  1637. * which should suffice for solid-state (e.g. Flash) disks to be used
  1638. * without the real disk cache, meaning dosFsLib directly on top of
  1639. * this wrapper.
  1640. *
  1641. * This routine transfers between a user buffer and the lower layer BLK_DEV
  1642. * It is optimized for byte transfers.  
  1643. *
  1644. * RETURNS OK or ERROR and may otherwise set errno.
  1645. */
  1646. LOCAL STATUS blkWrapBytesRW
  1647.     (
  1648.     CBIO_DEV_ID  dev,
  1649.     block_t startBlock,
  1650.     off_t offset,
  1651.     addr_t buffer,
  1652.     size_t nBytes,
  1653.     CBIO_RW rw,
  1654.     cookie_t * pCookie
  1655.     )
  1656.     {
  1657.     CBIO_DEV *  pDev = dev ;
  1658.     BLK_DEV * pBd = pDev->blkSubDev;
  1659.     STATUS stat = OK ;
  1660.     caddr_t  pStart;
  1661.     if( pBd->bd_readyChanged || CBIO_READYCHANGED (dev))
  1662. {
  1663. cbioRdyChgdSet(dev, TRUE);
  1664. errno = S_ioLib_DISK_NOT_PRESENT ;
  1665. return ERROR;
  1666. }
  1667.     if( startBlock >= pDev->cbioParams.nBlocks )
  1668. {
  1669. errno = EINVAL;
  1670. return ERROR;
  1671. }
  1672.     /* verify that all bytes are within one block range */
  1673.     if (((offset + nBytes) > pDev->cbioParams.bytesPerBlk ) ||
  1674. (offset <0) || (nBytes <=0))
  1675. {
  1676. errno = EINVAL;
  1677. return ERROR;
  1678. }
  1679.     if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR )
  1680. return ERROR;
  1681.     /* verify that there is a block buffer, if not, allocate one */
  1682.     if( pDev->cbioMemBase == NULL)
  1683. {
  1684. if( cbioBlkWrapBufCreate( pDev) == ERROR )
  1685.     {
  1686.     semGive(pDev->cbioMutex);
  1687.     return ERROR;
  1688.     }
  1689. }
  1690.     /* flush the current contents of the block buffer if needed */
  1691.     if( pDev->cbioBlkNo != (u_long)NONE &&
  1692.  pDev->cbioBlkNo != startBlock &&
  1693.  pDev->cbioDirtyMask != 0 )
  1694. {
  1695. block_t cachedBlock = pDev->cbioBlkNo ;
  1696. pDev->cbioBlkNo = NONE ;
  1697. pDev->cbioDirtyMask = 0;
  1698. stat = blkWrapBlkRW( pDev, cachedBlock, 1,
  1699.     pDev->cbioMemBase, CBIO_WRITE, NULL);
  1700. if( stat == ERROR )
  1701.     {
  1702.     semGive(pDev->cbioMutex);
  1703.     return ERROR;
  1704.     }
  1705. }
  1706.     /* get the requested block into cache */
  1707.     if( startBlock != pDev->cbioBlkNo && pDev->cbioDirtyMask == 0 )
  1708. {
  1709. stat = blkWrapBlkRW( pDev, startBlock, 1,
  1710.     pDev->cbioMemBase, CBIO_READ, NULL);
  1711. if( stat == ERROR )
  1712.     {
  1713.     semGive(pDev->cbioMutex);
  1714.     return ERROR;
  1715.     }
  1716. pDev->cbioBlkNo = startBlock ;
  1717. pDev->cbioDirtyMask = 0;
  1718. }
  1719.     assert( startBlock == pDev->cbioBlkNo );
  1720.     /* calculate actual memory address of data */
  1721.     pStart = pDev->cbioMemBase + offset ;
  1722. #ifdef DEBUG
  1723.     if(cbioDebug > 1)
  1724. logMsg("blkWrapBytesRW: blk %d + %d # %d bytes -> addr %x, %x bytesn",
  1725.     startBlock, offset, nBytes, (int) pStart, nBytes, 0);
  1726. #endif
  1727.     switch( rw )
  1728. {
  1729. case CBIO_READ:
  1730.     bcopy( pStart, buffer, nBytes );
  1731.     break;
  1732. case CBIO_WRITE:
  1733.     bcopy( buffer, pStart,  nBytes );
  1734.     pDev->cbioDirtyMask = 1;
  1735.     break;
  1736. }
  1737.     semGive(pDev->cbioMutex);
  1738.     return (OK);
  1739.     }
  1740. /*******************************************************************************
  1741. *
  1742. * blkWrapBlkCopy - Copy sectors 
  1743. *
  1744. * This routine makes copies of one or more blocks on the lower layer BLK_DEV.
  1745. * It is optimized for block copies on the subordinate layer.  
  1746. * RETURNS OK or ERROR and may otherwise set errno.
  1747. */
  1748. LOCAL STATUS blkWrapBlkCopy
  1749.     (
  1750.     CBIO_DEV_ID  dev,
  1751.     block_t srcBlock,
  1752.     block_t dstBlock,
  1753.     block_t numBlocks
  1754.     )
  1755.     {
  1756.     CBIO_DEV *pDev = (void *) dev ;
  1757.     BLK_DEV * pBd = pDev->blkSubDev;
  1758.     STATUS stat = OK;
  1759.     if( pBd->bd_readyChanged || CBIO_READYCHANGED(dev))
  1760. {
  1761. CBIO_READYCHANGED(dev) = TRUE;
  1762. errno = S_ioLib_DISK_NOT_PRESENT ;
  1763. return (ERROR);
  1764. }
  1765.     if( (srcBlock) > pDev->cbioParams.nBlocks ||
  1766. (dstBlock) > pDev->cbioParams.nBlocks )
  1767. {
  1768. errno = EINVAL;
  1769. return ERROR;
  1770. }
  1771.     if( (srcBlock+numBlocks) > pDev->cbioParams.nBlocks ||
  1772. (dstBlock+numBlocks) > pDev->cbioParams.nBlocks )
  1773. {
  1774. errno = EINVAL;
  1775. return ERROR;
  1776. }
  1777.     if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR )
  1778. return ERROR;
  1779.     /* verify that there is a block buffer, if not, allocate one */
  1780.     if( pDev->cbioMemBase == NULL)
  1781. {
  1782. if( cbioBlkWrapBufCreate( pDev) == ERROR )
  1783.     {
  1784.     semGive(pDev->cbioMutex);
  1785.     return ERROR;
  1786.     }
  1787. }
  1788.     /* flush the current contents of the block buffer if needed */
  1789.     if( pDev->cbioBlkNo != (u_long)NONE && 
  1790.          pDev->cbioDirtyMask != (u_long)0 )
  1791. {
  1792. block_t cachedBlock = pDev->cbioBlkNo ;
  1793. stat = blkWrapBlkRW( pDev, cachedBlock, 1,
  1794.     pDev->cbioMemBase, CBIO_WRITE, NULL);
  1795. if( stat == ERROR )
  1796.     {
  1797.     semGive(pDev->cbioMutex);
  1798.     return ERROR;
  1799.     }
  1800. }
  1801.     pDev->cbioBlkNo = NONE ; /* invalidate buffer contents */
  1802.     pDev->cbioDirtyMask = 0;
  1803.     /* because tiny cache is one block size, copy blocks one at a time */
  1804.     for(; numBlocks > 0; numBlocks -- )
  1805. {
  1806. stat = blkWrapBlkRW( pDev, srcBlock, 1,
  1807.     pDev->cbioMemBase, CBIO_READ, NULL);
  1808. if( stat == ERROR)
  1809.     break;
  1810. stat = blkWrapBlkRW( pDev, dstBlock, 1,
  1811.     pDev->cbioMemBase, CBIO_WRITE, NULL);
  1812. if( stat == ERROR)
  1813.     break;
  1814. srcBlock ++;
  1815. dstBlock ++;
  1816. }
  1817.     semGive(pDev->cbioMutex);
  1818.     return stat;
  1819.     }
  1820. /*******************************************************************************
  1821. *
  1822. * blkWrapIoctl - Misc control operations 
  1823. *
  1824. * This performs the requested ioctl() operation.
  1825. * CBIO modules can expect the following ioctl() codes from cbioLib.h:
  1826. * .IP
  1827. * CBIO_RESET - reset the CBIO device.   When the third argument to the ioctl
  1828. * call accompaning CBIO_RESET is NULL, the code verifies that the disk is 
  1829. * inserted and is ready, after getting it to a known state.   When the 3rd 
  1830. * argument is a non-zero, it is assumed to be a BLK_DEV pointer and 
  1831. * CBIO_RESET will install a new subordinate block device.    This work
  1832. * is performed at the BLK_DEV to CBIO layer, and all layers shall account
  1833. * for it.  A CBIO_RESET indicates a possible change in device geometry, 
  1834. * and the CBIO_PARAMS members will be reinitialized after a CBIO_RESET.
  1835. * .IP
  1836. * CBIO_STATUS_CHK - check device status of CBIO device and lower layer
  1837. * .IP
  1838. * CBIO_DEVICE_LOCK - Prevent disk removal 
  1839. * .IP
  1840. * CBIO_DEVICE_UNLOCK - Allow disk removal
  1841. * .IP
  1842. * CBIO_DEVICE_EJECT - Unmount and eject device
  1843. * .IP
  1844. * CBIO_CACHE_FLUSH - Flush any dirty cached data
  1845. * .IP
  1846. * CBIO_CACHE_INVAL - Flush & Invalidate all cached data
  1847. * .IP
  1848. * CBIO_CACHE_NEWBLK - Allocate scratch block
  1849. * .LP
  1850. *
  1851. * RETURNS OK or ERROR and may otherwise set errno.
  1852. */
  1853. LOCAL STATUS blkWrapIoctl
  1854.     (
  1855.     CBIO_DEV_ID dev,
  1856.     UINT32 command,
  1857.     addr_t arg
  1858.     )
  1859.     {
  1860.     FAST CBIO_DEV_ID  pDev = dev ;
  1861.     FAST BLK_DEV * pBd = pDev->blkSubDev ;
  1862.     STATUS stat = OK ;
  1863.     if( semTake( pDev->cbioMutex, WAIT_FOREVER) == ERROR )
  1864. return ERROR;
  1865.     /*
  1866.      * CBIO_RESET may be optionally used to 
  1867.      * install a new subordinate block device
  1868.      * if 3rd argument is non-zero, it is expected to be
  1869.      * a new BLK_DEV pointer.
  1870.      */
  1871.     if( command == (int)CBIO_RESET  && arg != NULL )
  1872. {
  1873. BLK_DEV * pBd = (void *) arg ;
  1874. int tmp;
  1875. /*
  1876.  * here we must verify BLK_DEV in much the same way as in
  1877.  * cbioWrapBlkDev()
  1878.  */
  1879. stat = ERROR ;
  1880. errno = EINVAL ;
  1881. /* if the input is already a valid CBIO device, ignore it */
  1882. if (OK == cbioDevVerify ((CBIO_DEV_ID)pBd))
  1883.     {
  1884.     goto ioctl_exit ; 
  1885.     }
  1886. /* blkIo has no mechanism for verification, improvise */
  1887. else if( (pBd->bd_blkRd == NULL) || (pBd->bd_blkWrt == NULL) ||
  1888. (pBd->bd_ioctl == NULL) )
  1889.     goto ioctl_exit ;
  1890. else
  1891.     {
  1892.     /* check that bytesPerBlk is 2^n */
  1893.     tmp = shiftCalc( pBd->bd_bytesPerBlk );
  1894.     if( pBd->bd_bytesPerBlk != (ULONG)( 1 << tmp ) )
  1895. goto ioctl_exit ;
  1896.     /* 
  1897.      * for simplicity, we place a dummy function
  1898.      * if statusChk is not provided
  1899.      */
  1900.     if( pBd->bd_statusChk == NULL )
  1901. pBd->bd_statusChk = cbioWrapOk ;
  1902.     stat = OK ;
  1903.     errno = 0;
  1904.     }
  1905. /* this means that RESET will be later issued and reset all fields */
  1906. CBIO_READYCHANGED(dev) = TRUE;
  1907. dev->blkSubDev = (void *) pBd ;
  1908. dev->pDc = (void *) pBd ;
  1909. semGive(pDev->cbioMutex);
  1910. return (stat);
  1911. }
  1912.     /* End of CBIO_RESET for BLK_DEV replacement handling */
  1913.     /*
  1914.      * CBIO_RESET - 3rd arg is NULL:
  1915.      * verify that the disk is inserted and is ready,
  1916.      * after getting it to a known state for good measure
  1917.      * and reset readyChanged if indeed the disk is ready to roll.
  1918.      */
  1919.     if( command == (int)CBIO_RESET )
  1920. {
  1921. stat = OK; 
  1922.         errno = OK;
  1923. /* if the Block's got a reset function, call it */
  1924. if( pBd->bd_reset != NULL )
  1925.             {
  1926.             stat = pBd->bd_reset( pBd );
  1927.             }
  1928. /* 
  1929.  * for simplicity, we place a dummy function
  1930.  * if statusChk is not provided
  1931.  */
  1932. if( pBd->bd_statusChk == NULL )
  1933.     pBd->bd_statusChk = cbioWrapOk ;
  1934. /*
  1935.  * the drive's got a status check function,
  1936.  * use it to find out if all is cool and dandy, and
  1937.  * determine current state from status check result
  1938.  */
  1939. stat = pBd->bd_statusChk( pBd );
  1940.         CBIO_READYCHANGED(dev) = (ERROR == stat) ? TRUE : FALSE;
  1941. /* since the block size may have changed, we must re-init */
  1942. if( FALSE == CBIO_READYCHANGED (dev) )
  1943.     {
  1944.     pBd->bd_readyChanged = FALSE ; /* HELP - FDC hack */
  1945.     pDev->cbioParams.nBlocks = pBd->bd_nBlocks ;
  1946.     pDev->cbioParams.bytesPerBlk = pBd->bd_bytesPerBlk ;
  1947.     pDev->cbioParams.blocksPerTrack = pBd->bd_blksPerTrack ;
  1948.     pDev->cbioParams.nHeads = pBd->bd_nHeads ;
  1949.     pDev->cbioParams.blockOffset = 0 ;
  1950.     pDev->cbioMode = pBd->bd_mode ;
  1951.     if( pDev->cbioMemBase != NULL &&
  1952. pDev->cbioMemSize != pBd->bd_bytesPerBlk )
  1953. {
  1954. KHEAP_FREE(pDev->cbioMemBase);
  1955. pDev->cbioMemBase = NULL ;
  1956. pDev->cbioMemSize = 0;
  1957. pDev->pFuncs->cbioDevBlkRW = blkWrapBlkRW ;
  1958. }
  1959. #ifdef __unused__
  1960.     blkWrapDiskSizeAdjust( pDev) ;
  1961. #endif /*__unused__*/
  1962.     pDev->cbioParams.lastErrBlk = NONE ;
  1963.     pDev->cbioParams.lastErrno  = 0 ;
  1964.     }
  1965. if( stat == ERROR && errno == OK )
  1966.     errno = S_ioLib_DISK_NOT_PRESENT ;
  1967.  
  1968. semGive(pDev->cbioMutex);
  1969. return (stat);
  1970. }
  1971.     /* all other commands, except RESET, wont work if disk is not there */
  1972.     if( pBd->bd_readyChanged || CBIO_READYCHANGED(dev) )
  1973. {
  1974. CBIO_READYCHANGED(dev) = TRUE;
  1975. errno = S_ioLib_DISK_NOT_PRESENT;
  1976. semGive(pDev->cbioMutex);
  1977. return ERROR;
  1978. }
  1979.     switch ( command )
  1980. {
  1981. case CBIO_STATUS_CHK : 
  1982.     stat = pBd->bd_statusChk( pBd );
  1983.             /* 
  1984.              * SPR#68387: readyChanged bit of the BLK_DEV 
  1985.              * should be checked to verify the change 
  1986.              * in the media. If there is a change in the 
  1987.              * media then update the cache layer's data structures.
  1988.              */
  1989.             if( pBd->bd_readyChanged || CBIO_READYCHANGED(dev) )
  1990.                 {
  1991.         pDev->cbioParams.nBlocks  = pBd->bd_nBlocks ;
  1992.         pDev->cbioParams.bytesPerBlk  = pBd->bd_bytesPerBlk ;
  1993.         pDev->cbioParams.blocksPerTrack = pBd->bd_blksPerTrack ;
  1994.         pDev->cbioParams.nHeads  = pBd->bd_nHeads ;
  1995.         pDev->cbioParams.blockOffset  = 0 ;
  1996.         pDev->cbioMode           = pBd->bd_mode ;
  1997.                 pDev->cbioParams.cbioRemovable  = pBd->bd_removable ;
  1998. if( pDev->cbioMemBase != NULL && 
  1999. pDev->cbioMemSize != pBd->bd_bytesPerBlk )
  2000.       {
  2001.       KHEAP_FREE ( pDev->cbioMemBase );
  2002.       pDev->cbioMemBase = NULL ;
  2003.       pDev->cbioMemSize = 0;
  2004.       pDev->pFuncs->cbioDevBlkRW = blkWrapBlkRW ;
  2005.       }
  2006.                 }  
  2007.     break;
  2008. case CBIO_CACHE_FLUSH :
  2009. case CBIO_CACHE_INVAL :
  2010. case CBIO_CACHE_NEWBLK:
  2011.     if( pDev->cbioMemBase != NULL &&
  2012. pDev->cbioBlkNo != (u_long)NONE && 
  2013.                 pDev->cbioDirtyMask != (u_long)0 )
  2014. {
  2015. block_t cachedBlock = pDev->cbioBlkNo ;
  2016. stat = blkWrapBlkRW( pDev, cachedBlock, 1,
  2017.     pDev->cbioMemBase, CBIO_WRITE, NULL);
  2018. }
  2019.     if( pDev->cbioMemBase != (u_long)NULL && 
  2020.                 command == (int)CBIO_CACHE_NEWBLK )
  2021. {
  2022. bzero( pDev->cbioMemBase, pDev->cbioMemSize);
  2023. pDev->cbioBlkNo = (block_t) arg ;
  2024. pDev->cbioDirtyMask = 1;
  2025. }
  2026.     else
  2027. {
  2028. pDev->cbioBlkNo = NONE ;
  2029. pDev->cbioDirtyMask = 0;
  2030. }
  2031.     break;
  2032. default:
  2033.     stat = pBd->bd_ioctl( pBd, command, arg );
  2034.     break ;
  2035. case CBIO_RESET : /* dealt with above, for switch completeness */
  2036. case CBIO_DEVICE_LOCK : /* unimplemented commands */
  2037. case CBIO_DEVICE_UNLOCK :
  2038. case CBIO_DEVICE_EJECT :
  2039.     errno = S_ioLib_UNKNOWN_REQUEST;
  2040.     stat = ERROR;
  2041.     break;
  2042. }
  2043.     ioctl_exit:
  2044.     semGive(pDev->cbioMutex);
  2045.     return stat;
  2046.     }
  2047. #ifdef __unused__
  2048. /*******************************************************************************
  2049. *
  2050. * blkWrapDiskSizeAdjust - adjust true disk size
  2051. *
  2052. * Some block drivers report incorrect disk capacity in bd_nBlocks field.
  2053. * This function will experimentally discover the true size of the disk,
  2054. * by reading blocks until an error is returned by the driver.
  2055. * In order to overcome driver's sanity checks, the bd_nBlocks will
  2056. * be adjusted each time a call is made to read blocks beyond the
  2057. * previously reported capacity.
  2058. * There is a time limit on these attempts, so the final result may
  2059. * be still inaccurate if the capacity reported by the driver
  2060. * is significantly different from the actual disk capacity.
  2061. *
  2062. * RETURNS: N/A
  2063. */
  2064. LOCAL void blkWrapDiskSizeAdjust
  2065.     (
  2066.     CBIO_DEV_ID  dev  /* CBIO device handle */
  2067.     )
  2068.     {
  2069.     FAST CBIO_DEV * pDev = (void *) dev ;
  2070.     FAST BLK_DEV * pBd = pDev->blkSubDev;
  2071.     STATUS stat = OK ;
  2072.     int timeout = tickGet() + 2 * sysClkRateGet(); /* 2 sec timeout */
  2073.     int orig_nBlocks, secPerCyl ;
  2074.     caddr_t tmpBuf ;
  2075.     orig_nBlocks = pBd->bd_nBlocks ;
  2076.     secPerCyl = pBd->bd_blksPerTrack * pBd->bd_nHeads ;
  2077.     tmpBuf = KHEAP_ALLOC(pBd->bd_bytesPerBlk);
  2078.     if (NULL == tmpBuf)
  2079. {
  2080. }
  2081.     /* increment capacity by one cylinder and test readability */
  2082.     while( (tickGet()<=timeout) && (stat == OK ) )
  2083. {
  2084. /* read last block in current capacity */
  2085. stat = pBd->bd_blkRd( pBd, pBd->bd_nBlocks-1, 1, tmpBuf );
  2086. /* if OK, try to read end of next cyl, if failed, go back and break */
  2087. if( stat == OK )
  2088.     pBd->bd_nBlocks += secPerCyl;
  2089. else
  2090.     pBd->bd_nBlocks -= secPerCyl;
  2091. }
  2092.     /* refresh timeout */
  2093.     timeout = tickGet() + (2 * sysClkRateGet()); /* 2 sec timeout */
  2094.     stat = OK ;
  2095.     /* increment capacity by one sector and test readability */
  2096.     while( (tickGet() <= timeout) && (stat == OK ) )
  2097. {
  2098. /* read last block in current capacity */
  2099. stat = pBd->bd_blkRd( pBd, pBd->bd_nBlocks-1, 1, tmpBuf );
  2100. if( stat == OK )
  2101.     pBd->bd_nBlocks ++ ;
  2102. else
  2103.     pBd->bd_nBlocks -- ;
  2104. }
  2105. #ifdef DEBUG
  2106. if(cbioDebug > 0 && tickGet()> timeout )
  2107.     logMsg("blkWrapDiskSizeAdjust: timeout %d exceededn",
  2108. timeout,0,0,0,0,0);
  2109. #endif
  2110.     /* if all goes well, the last read operation should have succeeded */
  2111.     if( (stat = pBd->bd_blkRd( pBd, pBd->bd_nBlocks-1, 1, tmpBuf )) == OK)
  2112. {
  2113. #ifdef DEBUG
  2114. if(cbioDebug > 0)
  2115.     logMsg("blkWrapDiskSizeAdjust: capacity increased by %d blocksn",
  2116. pBd->bd_nBlocks - orig_nBlocks, 0,0,0,0,0);
  2117. #endif
  2118. /* make it official */
  2119. pDev->cbioParams.nBlocks = pBd->bd_nBlocks ;
  2120. }
  2121.     else
  2122. {
  2123. /* something is weird, put it back where it was */
  2124. #ifdef DEBUG
  2125. if(cbioDebug > 0)
  2126.     logMsg("blkWrapDiskSizeAdjust: failed to adjustn",
  2127. 0,0,0,0,0,0);
  2128. #endif
  2129. pDev->cbioParams.nBlocks = pBd->bd_nBlocks = orig_nBlocks ;
  2130. }
  2131.     KHEAP_FREE(tmpBuf);
  2132.     }
  2133. #endif /*__unused__*/
  2134. /* End of File */