2 Include file for ISA Floppy Driver
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #ifndef _ISA_FLOPPY_H_
16 #define _ISA_FLOPPY_H_
20 #include <Protocol/BlockIo.h>
21 #include <Protocol/IsaIo.h>
22 #include <Protocol/DevicePath.h>
23 #include <Guid/StatusCodeDataTypeId.h>
25 #include <Library/TimerLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/UefiDriverEntryPoint.h>
28 #include <Library/BaseLib.h>
29 #include <Library/UefiLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/UefiBootServicesTableLib.h>
33 #include <Library/ReportStatusCodeLib.h>
34 #include <Library/PcdLib.h>
36 extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver
;
38 #define STALL_1_SECOND 1000000
39 #define STALL_1_MSECOND 1000
47 // Internal Data Structures
49 #define FDC_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('F', 'B', 'I', 'O')
50 #define FLOPPY_CONTROLLER_CONTEXT_SIGNATURE SIGNATURE_32 ('F', 'D', 'C', 'C')
61 BOOLEAN FddResetPerformed
;
62 EFI_STATUS FddResetStatus
;
63 BOOLEAN NeedRecalibrate
;
66 } FLOPPY_CONTROLLER_CONTEXT
;
71 EFI_BLOCK_IO_PROTOCOL BlkIo
;
72 EFI_BLOCK_IO_MEDIA BlkMedia
;
74 EFI_ISA_IO_PROTOCOL
*IsaIo
;
79 UINT8 PresentCylinderNumber
;
83 EFI_UNICODE_STRING_TABLE
*ControllerNameTable
;
84 FLOPPY_CONTROLLER_CONTEXT
*ControllerState
;
86 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
89 #include "ComponentName.h"
91 #define FDD_BLK_IO_FROM_THIS(a) CR (a, FDC_BLK_IO_DEV, BlkIo, FDC_BLK_IO_DEV_SIGNATURE)
92 #define FLOPPY_CONTROLLER_FROM_LIST_ENTRY(a) \
94 FLOPPY_CONTROLLER_CONTEXT, \
96 FLOPPY_CONTROLLER_CONTEXT_SIGNATURE \
99 #define DISK_1440K_EOT 0x12
100 #define DISK_1440K_GPL 0x1b
101 #define DISK_1440K_DTL 0xff
102 #define DISK_1440K_NUMBER 0x02
103 #define DISK_1440K_MAXTRACKNUM 0x4f
104 #define DISK_1440K_BYTEPERSECTOR 512
116 } FDD_COMMAND_PACKET1
;
121 } FDD_COMMAND_PACKET2
;
160 // Digital Output Register address offset
162 #define FDC_REGISTER_DOR 2
165 // Main Status Register address offset
167 #define FDC_REGISTER_MSR 4
170 // Data Register address offset
172 #define FDC_REGISTER_DTR 5
175 // Configuration Control Register(data rate select) address offset
177 #define FDC_REGISTER_CCR 7
180 // Digital Input Register(diskchange) address offset
182 #define FDC_REGISTER_DIR 7
186 // FDC Register Bit Definitions
189 // Digital Out Register(WO)
192 // Select Drive: 0=A 1=B
194 #define SELECT_DRV BIT0
199 #define RESET_FDC BIT2
204 #define INT_DMA_ENABLE BIT3
207 // Turn On Drive A Motor
209 #define DRVA_MOTOR_ON BIT4
212 // Turn On Drive B Motor
214 #define DRVB_MOTOR_ON BIT5
217 // Main Status Register(RO)
245 // Request For Master
250 // Configuration Control Register(WO)
255 #define CCR_DRC (BIT0 | BIT1)
258 // Digital Input Register(RO)
265 // #define CCR_DCL BIT7 // Diskette change
269 #define DRC_500KBS 0x0
274 #define DRC_300KBS 0x01
279 #define DRC_250KBS 0x02
284 #define READ_DATA_CMD 0x06
285 #define WRITE_DATA_CMD 0x05
286 #define WRITE_DEL_DATA_CMD 0x09
287 #define READ_DEL_DATA_CMD 0x0C
288 #define READ_TRACK_CMD 0x02
289 #define READ_ID_CMD 0x0A
290 #define FORMAT_TRACK_CMD 0x0D
291 #define SCAN_EQU_CMD 0x11
292 #define SCAN_LOW_EQU_CMD 0x19
293 #define SCAN_HIGH_EQU_CMD 0x1D
294 #define SEEK_CMD 0x0F
295 #define RECALIBRATE_CMD 0x07
296 #define SENSE_INT_STATUS_CMD 0x08
297 #define SPECIFY_CMD 0x03
298 #define SENSE_DRV_STATUS_CMD 0x04
301 // CMD_MT: Multi_Track Selector
302 // when set , this flag selects the multi-track operating mode.
303 // In this mode, the FDC treats a complete cylinder under head0 and 1
309 // CMD_MFM: MFM/FM Mode Selector
310 // A one selects the double density(MFM) mode
311 // A zero selects single density (FM) mode
317 // When set to 1, sectors containing a deleted data address mark will
318 // automatically be skipped during the execution of Read Data.
319 // When set to 0, the sector is read or written the same as the read and
325 // FDC Status Register Bit Definitions
333 #define STS0_IC (BIT7 | BIT6)
336 // Seek End: the FDC completed a seek or recalibrate command
346 // Not Ready(unused), this bit is always 0
351 // Head Address: the current head address
356 // STS0_US1 & STS0_US0: Drive Select(the current selected drive)
361 #define STS0_US1 BIT1
366 #define STS0_US0 BIT0
380 // Data Error: The FDC detected a CRC error in either the ID field or
381 // data field of a sector
386 // Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service
387 // within the required time interval
405 // Missing Address Mark
415 // Data Error in Data Field: The FDC detected a CRC error in the data field
420 // Wrong Cylinder: The track address from sector ID field is different from
421 // the track address maintained inside FDC
431 // Missing Address Mark in Data Field
451 // STS3_US1 & STS3_US0 : Drive Select
453 #define STS3_US1 BIT1
454 #define STS3_US0 BIT0
457 // Status Register 0 Interrupt Code Description
460 // Normal Termination of Command
465 // Abnormal Termination of Command
475 // Abnormal Termination caused by Polling
480 // EFI Driver Binding Protocol Functions
484 Test controller is a floppy disk drive device
486 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
487 @param[in] Controller The handle of the controller to test.
488 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
490 @retval EFI_SUCCESS The device is supported by this driver.
491 @retval EFI_ALREADY_STARTED The device is already being managed by this driver.
492 @retval EFI_ACCESS_DENIED The device is already being managed by a different driver
493 or an application that requires exclusive access.
497 FdcControllerDriverSupported (
498 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
499 IN EFI_HANDLE Controller
,
500 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
504 Start this driver on Controller.
506 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
507 @param[in] ControllerHandle The handle of the controller to start. This handle
508 must support a protocol interface that supplies
509 an I/O abstraction to the driver.
510 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
511 This parameter is ignored by device drivers, and is optional for bus drivers.
513 @retval EFI_SUCCESS The device was started.
514 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
515 Currently not implemented.
516 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
517 @retval Others The driver failded to start the device.
521 FdcControllerDriverStart (
522 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
523 IN EFI_HANDLE Controller
,
524 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
528 Stop this driver on ControllerHandle.
530 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
531 @param[in] ControllerHandle A handle to the device being stopped. The handle must
532 support a bus specific I/O protocol for the driver
533 to use to stop the device.
534 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
535 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
536 if NumberOfChildren is 0.
538 @retval EFI_SUCCESS The device was stopped.
539 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
543 FdcControllerDriverStop (
544 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
545 IN EFI_HANDLE Controller
,
546 IN UINTN NumberOfChildren
,
547 IN EFI_HANDLE
*ChildHandleBuffer
551 // EFI Block I/O Protocol Functions
555 Reset the Floppy Logic Drive, call the FddReset function.
557 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
558 @param ExtendedVerification BOOLEAN: Indicate that the driver may perform a more
559 exhaustive verification operation of the device during
560 reset, now this par is ignored in this driver
561 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
562 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly
569 IN EFI_BLOCK_IO_PROTOCOL
*This
,
570 IN BOOLEAN ExtendedVerification
574 Flush block via fdd controller.
576 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
583 IN EFI_BLOCK_IO_PROTOCOL
*This
587 Read the requested number of blocks from the device.
589 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
590 @param MediaId UINT32: The media id that the read request is for
591 @param Lba EFI_LBA: The starting logic block address to read from on the device
592 @param BufferSize UINTN: The size of the Buffer in bytes
593 @param Buffer VOID *: A pointer to the destination buffer for the data
595 @retval EFI_SUCCESS: The data was read correctly from the device
596 @retval EFI_DEVICE_ERROR:The device reported an error while attempting to perform
598 @retval EFI_NO_MEDIA: There is no media in the device
599 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
600 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
601 intrinsic block size of the device
602 @retval EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid,
603 or the buffer is not on proper alignment
609 IN EFI_BLOCK_IO_PROTOCOL
*This
,
617 Write a specified number of blocks to the device.
619 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
620 @param MediaId UINT32: The media id that the write request is for
621 @param Lba EFI_LBA: The starting logic block address to be written
622 @param BufferSize UINTN: The size in bytes in Buffer
623 @param Buffer VOID *: A pointer to the source buffer for the data
625 @retval EFI_SUCCESS: The data were written correctly to the device
626 @retval EFI_WRITE_PROTECTED: The device can not be written to
627 @retval EFI_NO_MEDIA: There is no media in the device
628 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
629 @retval EFI_DEVICE_ERROR: The device reported an error while attempting to perform
631 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
632 intrinsic block size of the device
633 @retval EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid,
634 or the buffer is not on proper alignment
639 IN EFI_BLOCK_IO_PROTOCOL
*This
,
647 // Prototypes of internal functions
651 Detect the floppy drive is presented or not.
653 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
654 @retval EFI_SUCCESS Drive is presented
655 @retval EFI_NOT_FOUND Drive is not presented
660 IN FDC_BLK_IO_DEV
*FdcDev
665 Do recalibrate and see the drive is presented or not.
666 Set the media parameters.
668 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
669 @return the drive is presented or not
674 IN FDC_BLK_IO_DEV
*FdcDev
679 Reset the Floppy Logic Drive.
681 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
683 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
684 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and
690 IN FDC_BLK_IO_DEV
*FdcDev
695 Turn the drive's motor on.
696 The drive's motor must be on before any command can be executed.
698 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
700 @retval EFI_SUCCESS: Turn the drive's motor on successfully
701 @retval EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on
702 @retval EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer)
707 IN FDC_BLK_IO_DEV
*FdcDev
712 Set a Timer and when Timer goes off, turn the motor off.
715 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
717 @retval EFI_SUCCESS: Set the Timer successfully
718 @retval EFI_INVALID_PARAMETER: Fail to Set the timer
723 IN FDC_BLK_IO_DEV
*FdcDev
727 Detect the disk in the drive is changed or not.
730 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
732 @retval EFI_SUCCESS: No disk media change
733 @retval EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation
734 @retval EFI_NO_MEDIA: No disk in the drive
735 @retval EFI_MEDIA_CHANGED: There is a new disk in the drive
739 IN FDC_BLK_IO_DEV
*FdcDev
743 Do the Specify command, this command sets DMA operation
744 and the initial values for each of the three internal
745 times: HUT, SRT and HLT.
747 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
749 @retval EFI_SUCCESS: Execute the Specify command successfully
750 @retval EFI_DEVICE_ERROR: Fail to execute the command
755 IN FDC_BLK_IO_DEV
*FdcDev
759 Set the head of floppy drive to track 0.
761 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
762 @retval EFI_SUCCESS: Execute the Recalibrate operation successfully
763 @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation
768 IN FDC_BLK_IO_DEV
*FdcDev
772 Set the head of floppy drive to the new cylinder.
774 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
775 @param Lba EFI_LBA : The logic block address want to seek
777 @retval EFI_SUCCESS: Execute the Seek operation successfully
778 @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation
783 IN FDC_BLK_IO_DEV
*FdcDev
,
788 Do the Sense Interrupt Status command, this command resets the interrupt signal.
790 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
791 @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC
792 @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number
795 @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully
796 @retval EFI_DEVICE_ERROR: Fail to execute the command
801 IN FDC_BLK_IO_DEV
*FdcDev
,
802 IN OUT UINT8
*StatusRegister0
,
803 IN OUT UINT8
*PresentCylinderNumber
807 Do the Sense Drive Status command.
809 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
810 @param Lba EFI_LBA : Logic block address
812 @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully
813 @retval EFI_DEVICE_ERROR: Fail to execute the command
814 @retval EFI_WRITE_PROTECTED:The disk is write protected
819 IN FDC_BLK_IO_DEV
*FdcDev
,
824 Update the disk media properties and if necessary reinstall Block I/O interface.
826 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
828 @retval EFI_SUCCESS: Do the operation successfully
829 @retval EFI_DEVICE_ERROR: Fail to the operation
834 IN FDC_BLK_IO_DEV
*FdcDev
838 Set the data rate and so on.
840 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
842 @retval EFI_SUCCESS success to set the data rate
846 IN FDC_BLK_IO_DEV
*FdcDev
850 Read or Write a number of blocks in the same cylinder.
852 @param FdcDev A pointer to Data Structure FDC_BLK_IO_DEV
853 @param HostAddress device address
854 @param Lba The starting logic block address to read from on the device
855 @param NumberOfBlocks The number of block wanted to be read or write
856 @param Read Operation type: read or write
858 @retval EFI_SUCCESS Success operate
862 ReadWriteDataSector (
863 IN FDC_BLK_IO_DEV
*FdcDev
,
864 IN VOID
*HostAddress
,
866 IN UINTN NumberOfBlocks
,
871 Fill in FDD command's parameter.
873 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
874 @param Lba The starting logic block address to read from on the device
875 @param Command FDD command
880 IN FDC_BLK_IO_DEV
*FdcDev
,
882 IN FDD_COMMAND_PACKET1
*Command
886 Read result byte from Data Register of FDC.
888 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
889 @param Pointer Buffer to store the byte read from FDC
891 @retval EFI_SUCCESS Read result byte from FDC successfully
892 @retval EFI_DEVICE_ERROR The FDC is not ready to be read
897 IN FDC_BLK_IO_DEV
*FdcDev
,
902 Write command byte to Data Register of FDC.
904 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
905 @param Pointer Be used to save command byte written to FDC
907 @retval EFI_SUCCESS: Write command byte to FDC successfully
908 @retval EFI_DEVICE_ERROR: The FDC is not ready to be written
913 IN FDC_BLK_IO_DEV
*FdcDev
,
918 Detect the specified floppy logic drive is busy or not within a period of time.
920 @param FdcDev Indicate it is drive A or drive B
921 @param Timeout The time period for waiting
923 @retval EFI_SUCCESS: The drive and command are not busy
924 @retval EFI_TIMEOUT: The drive or command is still busy after a period time that
930 IN FDC_BLK_IO_DEV
*FdcDev
,
935 Determine whether FDC is ready to write or read.
937 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
938 @param Dio BOOLEAN: Indicate the FDC is waiting to write or read
939 @param Timeout The time period for waiting
941 @retval EFI_SUCCESS: FDC is ready to write or read
942 @retval EFI_NOT_READY: FDC is not ready within the specified time period
947 IN FDC_BLK_IO_DEV
*FdcDev
,
953 Set FDC control structure's attribute according to result.
955 @param Result Point to result structure
956 @param FdcDev FDC control structure
958 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
959 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
960 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
961 @retval EFI_SUCCESS - GC_TODO: Add description for return value
966 IN FDD_RESULT_PACKET
*Result
,
967 IN OUT FDC_BLK_IO_DEV
*FdcDev
971 Check the drive status information.
973 @param StatusRegister3 the value of Status Register 3
975 @retval EFI_SUCCESS The disk is not write protected
976 @retval EFI_WRITE_PROTECTED: The disk is write protected
981 IN UINT8 StatusRegister3
985 Calculate the number of block in the same cylinder according to Lba.
987 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
988 @param Lba EFI_LBA: The starting logic block address
989 @param NumberOfBlocks UINTN: The number of blocks
991 @return The number of blocks in the same cylinder which the starting
992 logic block address is Lba
996 GetTransferBlockCount (
997 IN FDC_BLK_IO_DEV
*FdcDev
,
999 IN UINTN NumberOfBlocks
1003 When the Timer(2s) off, turn the drive's motor off.
1005 @param Event EFI_EVENT: Event(the timer) whose notification function is being
1007 @param Context VOID *: Pointer to the notification function's context
1018 Read I/O port for FDC.
1020 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1021 @param Offset The offset address of port
1026 IN FDC_BLK_IO_DEV
*FdcDev
,
1031 Write I/O port for FDC.
1033 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1034 @param Offset The offset address of port
1035 @param Data Value written to port
1040 IN FDC_BLK_IO_DEV
*FdcDev
,
1046 Read or Write a number of blocks to floppy device.
1048 @param This Pointer to instance of EFI_BLOCK_IO_PROTOCOL
1049 @param MediaId The media id of read/write request
1050 @param Lba The starting logic block address to read from on the device
1051 @param BufferSize The size of the Buffer in bytes
1052 @param Operation - GC_TODO: add argument description
1053 @param Buffer - GC_TODO: add argument description
1055 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1056 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1057 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1058 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1059 @retval EFI_NO_MEDIA - GC_TODO: Add description for return value
1060 @retval EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
1061 @retval EFI_WRITE_PROTECTED - GC_TODO: Add description for return value
1062 @retval EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value
1063 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1064 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1065 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1066 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1067 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1068 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1072 FddReadWriteBlocks (
1073 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1076 IN UINTN BufferSize
,
1077 IN BOOLEAN Operation
,
1082 Common interface for free cache.
1084 @param FdcDev Pointer of FDC_BLK_IO_DEV instance
1089 IN FDC_BLK_IO_DEV
*FdcDev