1 /*****************************************************************************/
5 /* Direct Disk I/O Demo Program */
9 /* (C) Copyright 2005, Oliver Schmidt, <ol.sc@web.de> */
12 /* This software is provided 'as-is', without any expressed or implied */
13 /* warranty. In no event will the authors be held liable for any damages */
14 /* arising from the use of this software. */
16 /* Permission is granted to anyone to use this software for any purpose, */
17 /* including commercial applications, and to alter it and redistribute it */
18 /* freely, subject to the following restrictions: */
20 /* 1. The origin of this software must not be misrepresented; you must not */
21 /* claim that you wrote the original software. If you use this software */
22 /* in a product, an acknowledgment in the product documentation would be */
23 /* appreciated but is not required. */
24 /* 2. Altered source versions must be plainly marked as such, and must not */
25 /* be misrepresented as being the original software. */
26 /* 3. This notice may not be removed or altered from any source */
29 /*****************************************************************************/
43 #define MAX_CHUNKS 10 /* Maximum acceptable number of chunks */
46 static unsigned char ScreenX;
47 static unsigned char ScreenY;
50 static void ClearLine (void)
51 /* Clear the screen line the cursor is on */
58 static unsigned char AskForDrive (const char* Name)
59 /* Ask for a drive id and return it */
61 unsigned char Drive = 0;
64 cprintf ("\r\n%s Drive ID ? ", Name);
71 Drive = Drive * 10 + Char - '0';
73 } while (Char != CH_ENTER);
80 static void AskForDisk (const char* Name, unsigned char Drive)
81 /* Ask the user to insert a specific disk */
84 cprintf ("\rInsert %s Disk into Drive %d !", Name, Drive);
90 static char* AllocBuffer (unsigned int SectSize, unsigned int SectCount, unsigned int* ChunkCount)
91 /* Allocate a copy buffer on the heap and return a pointer to it */
94 unsigned long BufferSize;
95 unsigned int Chunks = 1;
97 /* Increase number of chunks resp. decrease size */
98 /* of one chunk until buffer allocation succeeds */
100 *ChunkCount = (unsigned int) ((SectCount + Chunks - 1) / Chunks);
101 BufferSize = *ChunkCount * (unsigned long) SectSize;
102 if (BufferSize < UINT_MAX) {
103 Buffer = malloc ((size_t) BufferSize);
105 } while (Buffer == NULL && ++Chunks <= MAX_CHUNKS);
111 int main (int argc, const char* argv[])
113 unsigned char SourceId;
114 unsigned char TargetId;
115 dhandle_t Source = NULL;
116 dhandle_t Target = NULL;
117 unsigned int SectSize;
118 unsigned int SectCount;
121 unsigned int ChunkCount;
122 unsigned int ChunkOffset = 0;
125 screensize (&ScreenX, &ScreenY);
127 /* Allow user to read exit messages */
128 if (doesclrscrafterexit ()) {
129 atexit ((void (*)) cgetc);
132 cputs ("Floppy Disk Copy\r\n");
136 /* Get source and target drive id (which may very well be identical) */
139 SourceId = AskForDrive ("Source");
140 TargetId = AskForDrive ("Target");
145 SourceId = TargetId = atoi (argv[1]);
149 SourceId = atoi (argv[1]);
150 TargetId = atoi (argv[2]);
154 cprintf ("\r\nToo many arguments\r\n");
161 /* Check for single drive copy or inital iteration */
162 if (SourceId == TargetId || Source == NULL) {
163 AskForDisk ("Source", SourceId);
166 /* Check for initial iteration */
167 if (Source == NULL) {
169 /* Open source drive */
170 Source = dio_open (SourceId);
171 if (Source == NULL) {
172 cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, SourceId);
176 SectSize = dio_query_sectsize (Source);
177 SectCount = dio_query_sectcount (Source);
179 /* Allocate buffer */
180 Buffer = AllocBuffer (SectSize, SectCount, &ChunkCount);
181 if (Buffer == NULL) {
182 cputs ("\r\n\nError on allocating Buffer\r\n");
189 /* Read one chunk of sectors into buffer */
190 for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) {
191 cprintf ("\rReading Sector %d of %d", Sector + 1, SectCount);
193 /* Read one sector */
194 if (dio_read (Source, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) {
195 cprintf ("\r\n\nError %d on reading from Drive %d\r\n", (int) _oserror, SourceId);
200 /* Check for single drive copy or inital iteration */
201 if (TargetId == SourceId || Target == NULL) {
202 AskForDisk ("Target", TargetId);
205 /* Open target drive on initial iteration */
206 if (Target == NULL) {
207 Target = dio_open (TargetId);
208 if (Target == NULL) {
209 cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, TargetId);
213 /* Check for compatible drives */
214 if (dio_query_sectsize (Target) != SectSize ||
215 dio_query_sectcount (Target) != SectCount) {
216 cputs ("\r\n\nFormat mismatch between Drives\r\n");
223 /* Write one chunk of sectors from buffer */
224 for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) {
225 cprintf ("\rWriting Sector %d of %d", Sector + 1, SectCount);
227 /* Write one sector */
228 if (dio_write (Target, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) {
229 cprintf ("\r\n\nError %d on writing to Drive %d\r\n", (int) _oserror, TargetId);
234 /* Advance to next chunk */
235 ChunkOffset += ChunkCount;
237 } while (Sector < SectCount);
240 cprintf ("\rSuccessfully copied %d Sectors\r\n", SectCount);