- Update stm32f7_discovery target description
[AROS.git] / workbench / system / BHFormat / main.c
blob76310eec9c45940fe64012c3b487de36eb9cb1b8
1 /*
2 * Format -- disk formatting and file-system creation program
3 * Copyright (C) 1999 Ben Hutchings <womble@zzumbouk.demon.co.uk>
4 * Copyright (C) 2008 Pavel Fedin <sonic_amiga@rambler.ru>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <devices/trackdisk.h>
22 #include <devices/newstyle.h>
23 #include <dos/dos.h>
24 #include <dos/dosextens.h>
25 #include <dos/filehandler.h>
26 #include <exec/devices.h>
27 #include <exec/errors.h>
28 #include <exec/io.h>
29 #include <exec/libraries.h>
30 #include <exec/memory.h>
31 #include <exec/resident.h>
32 #include <graphics/gfxbase.h>
33 #include <intuition/intuition.h>
34 #include <workbench/workbench.h>
35 #include <stdlib.h>
36 #include <string.h>
38 #include <proto/dos.h>
39 #include <proto/exec.h>
40 #include <proto/icon.h>
41 #include <proto/intuition.h>
43 #include "format.h"
44 #include "locale.h"
46 #ifndef AROS_BSTR_ADDR
47 #define AROS_BSTR_ADDR(x) (char *)BADDR(x) + 1
48 #endif
50 static void WordWrapSz( char * psz );
51 static BOOL bTransferCylinder(
52 APTR pBuffer, ULONG icyl, UWORD cmd64, UWORD cmd32 );
54 char szDosDevice[MAX_FS_NAME_LEN+2];
55 char * pchDosDeviceColon;
56 ULLONG ibyStart, ibyEnd;
57 IPTR MaxTransfer;
58 IPTR LowCyl, HighCyl;
59 ULONG DosType;
61 static char szVolume[MAX_FS_NAME_LEN+2] __attribute__((aligned (4)));
62 static char * pszExecDevice;
63 static ULONG ExecUnit, ExecDeviceFlags;
64 static ULONG BufMemType;
65 static ULONG fstCurrent;
66 static BOOL bFstSet;
67 static ULONG devfCurrent;
68 static BOOL bDevfSet;
69 static struct FileSysStartupMsg * pfssm;
70 static ULLONG cbyTrack, cbyCylinder;
71 static struct MsgPort * pmpDiskIO;
72 static struct IOStdReq * piosDisk;
73 static BOOL bExecDevOpen;
74 static BOOL bSuspectIDE = FALSE;
75 static BOOL bInhibited;
76 static ULONG * paulWriteBuffer, * paulReadBuffer;
77 static ULONG cbyTransfer;
80 const char szVersion[] = "$VER: BHFormat 43.8 (" ADATE ")";
82 int main(void)
84 int rc = _WBenchMsg ? rcGuiMain() : rcCliMain();
85 FreeAll();
86 return rc;
90 void ReportErrSz( ErrorType ert, LONG err, const char * pszMessage, ... )
92 static const char * apszErrorTypes[3];
93 apszErrorTypes[0] = _(MSG_ERRORS_WARNING);
94 apszErrorTypes[1] = _(MSG_ERRORS_ERROR);
95 apszErrorTypes[2] = _(MSG_ERRORS_FAILURE);
97 char szSysMessage[FAULT_MAX];
98 char szFormat[256];
99 static char szOutput[1024];
100 va_list args;
102 va_start(args, pszMessage);
103 szSysMessage[0] = 0;
104 if( err != -1 )
105 (void) Fault( err ? err : IoErr(),
106 (_WBenchMsg && !pszMessage) ? 0 : "",
107 szSysMessage, FAULT_MAX );
109 strcpy( szFormat, _(MSG_FORMAT) );
110 strcat( szFormat, apszErrorTypes[ert] );
112 if(!_WBenchMsg)
114 if(pszMessage)
116 strcat( szFormat, " - " );
117 strcat( szFormat, pszMessage );
119 strcat( szFormat, szSysMessage );
120 strcat( szFormat, "\n" );
121 RawDoVFmtSz( szOutput, szFormat, args );
122 WordWrapSz(szOutput);
123 (void) FPuts( bpfhStdErr, szOutput );
125 else if(IntuitionBase)
127 struct EasyStruct es;
129 char * pszBodyFormat = szFormat + strlen(szFormat) + 1;
130 *pszBodyFormat = 0;
131 if(pszMessage)
132 strcpy( pszBodyFormat, pszMessage );
133 strcat( pszBodyFormat, szSysMessage );
135 es.es_StructSize = sizeof(struct EasyStruct);
136 es.es_Flags = 0;
137 es.es_Title = szFormat;
138 es.es_TextFormat = "%s";
139 es.es_GadgetFormat = (ert == ertFailure) ? _(MSG_CANCEL) : _(MSG_OK);
140 RawDoVFmtSz( szOutput, pszBodyFormat, args );
141 WordWrapSz(szOutput);
142 (void) EasyRequest( 0, &es, 0, (IPTR)szOutput );
144 /* else we can't report the error */
145 va_end(args);
148 static void WordWrapSz( char * psz )
150 char * pszLine, * pchSpace, * pchLastSpace;
151 pszLine = psz;
152 pchLastSpace = pszLine-1;
153 while( (pchSpace = strchr( pchLastSpace+1, ' ' )) != 0 )
155 size_t cch = pchSpace - pszLine;
157 if( cch >= 60 )
159 if( cch == 60 || pchLastSpace < pszLine )
160 pchLastSpace = pchSpace;
162 *pchLastSpace = '\n';
163 pszLine = pchLastSpace+1;
166 pchLastSpace = pchSpace;
171 BOOL bSetSzDosDeviceFromSz( const char * pszDevice )
173 /* Check the length of the device name - it may be followed by a
174 colon, and possibly some junk which we must ignore */
175 char * pszEnd = strchr( pszDevice, ':' );
176 size_t cch = pszEnd ? (pszEnd - pszDevice) : strlen(pszDevice);
178 if( cch != 0 && cch <= MAX_FS_NAME_LEN )
180 /* Make a copy, without the colon */
181 strncpy( szDosDevice, pszDevice, cch );
182 pchDosDeviceColon = &szDosDevice[cch]; /* need to put it back later */
183 *pchDosDeviceColon = 0;
184 *(pchDosDeviceColon+1) = 0;
185 return TRUE;
188 ReportErrSz( ertError, ERROR_INVALID_COMPONENT_NAME, 0 );
189 return FALSE;
193 BOOL bSetSzVolumeFromSz( const char * pszVolume )
195 /* Check the length and validity of the volume name */
196 size_t cch = strlen(pszVolume);
198 if( cch != 0 && cch <= MAX_FS_NAME_LEN && strpbrk( pszVolume, ":/" ) == 0 )
200 /* Make a copy with a length prefix because v36 Format function
201 incorrectly expects a BSTR */
202 szVolume[0] = cch;
203 strcpy( &szVolume[1], pszVolume );
204 return TRUE;
207 ReportErrSz( ertError, ERROR_INVALID_COMPONENT_NAME, 0 );
208 return FALSE;
212 BOOL bSetFstFromSz( const char * pszFileSysType )
214 char * pszEnd;
215 ULONG ub;
216 size_t cub;
218 if( *pszFileSysType == 0 )
220 bFstSet = FALSE;
221 return TRUE;
224 /* Look for a C-style number as used in Mountlists. */
225 fstCurrent = strtoul( pszFileSysType, &pszEnd, 0 );
226 if( *pszEnd == 0 )
228 bFstSet = TRUE;
229 return TRUE;
232 /* Look for a type in the standard-ish format of text with
233 \-escaped numbers. These numbers normally have only one
234 digit, so it's a bit hard to decide what base they are
235 in. I have specified 8 here because that's what C uses
236 for \-escaped character numbers. */
237 cub = 0;
238 fstCurrent = 0;
239 while( (ub = (unsigned char)*pszFileSysType++) != 0 )
241 if( ub == (unsigned char)'\\' )
243 ub = strtoul( pszFileSysType, (char **)&pszFileSysType, 8 );
244 if( ub >= 0x100 )
246 cub = 0;
247 break;
250 fstCurrent = (fstCurrent << 8) + ub;
251 ++cub;
253 if( cub == 4 )
255 bFstSet = TRUE;
256 return TRUE;
259 ReportErrSz( ertError, -1, _(MSG_ERROR_INVALID_DOSTYPE) );
260 return FALSE;
264 BOOL bSetDevfFromSz( const char * pszDevFlags )
266 if( *pszDevFlags == 0 )
268 bDevfSet = FALSE;
269 return TRUE;
272 devfCurrent = strtoul( pszDevFlags, (char **)&pszDevFlags, 0 );
273 if( *pszDevFlags == 0 )
275 bDevfSet = TRUE;
276 return TRUE;
279 ReportErrSz( ertError, ERROR_BAD_NUMBER, 0 );
280 return FALSE;
284 BOOL bGetDosDevice(struct DosList *pdlDevice, ULONG flags)
286 struct DosList *pdlList;
287 struct DosEnvec * pdenDevice;
289 if (!pdlDevice) {
290 flags = LDF_DEVICES|LDF_READ;
291 pdlList = LockDosList(flags);
292 D(Printf( "LockDosList( LDF_DEVICES | LDF_READ ) = 0x%08lx\n", (ULONG)pdlList ));
293 *pchDosDeviceColon = 0;
294 pdlDevice = FindDosEntry( pdlList, szDosDevice, LDF_DEVICES );
295 D(Printf("FindDosEntry( 0x%08lx, \"%s\", LDF_DEVICES ) = 0x%08lx\n",
296 (ULONG)pdlList, (ULONG)szDosDevice, (ULONG)pdlDevice ));
297 if( pdlDevice == 0 )
299 UnLockDosList(flags);
300 ReportErrSz( ertError, ERROR_DEVICE_NOT_MOUNTED, 0 );
301 return FALSE;
305 /* Find startup message and verify file-system settings. Use
306 TypeOfMem to protect against devices that use integer or string
307 startup values. */
308 if( (pfssm = (struct FileSysStartupMsg *)
309 BADDR(pdlDevice->dol_misc.dol_handler.dol_Startup)) == 0
310 || TypeOfMem(pfssm) == 0
311 || pfssm->fssm_Device == 0
312 || (pdenDevice = (struct DosEnvec *)BADDR(pfssm->fssm_Environ)) == 0
313 || TypeOfMem(pdenDevice) == 0
314 || pdenDevice->de_TableSize < DE_DOSTYPE
315 /* Check that parameters that should always be 0, are */
316 || pdenDevice->de_SecOrg != 0
317 || pdenDevice->de_Interleave != 0 )
319 UnLockDosList(flags);
320 ReportErrSz( ertError, ERROR_OBJECT_WRONG_TYPE, 0 );
321 return FALSE;
324 /* Get the device name with the original correct case */
325 RawDoFmtSz( szDosDevice, "%b", pdlDevice->dol_Name );
327 /* Unlike most BCPL strings, this one is guaranteed to be null-
328 terminated. */
329 pszExecDevice = AROS_BSTR_ADDR(pfssm->fssm_Device);
330 ExecUnit = pfssm->fssm_Unit;
331 ExecDeviceFlags = pfssm->fssm_Flags;
332 MaxTransfer = pdenDevice->de_MaxTransfer;
333 BufMemType = pdenDevice->de_BufMemType;
334 LowCyl = pdenDevice->de_LowCyl;
335 HighCyl = pdenDevice->de_HighCyl;
336 DosType = pdenDevice->de_DosType;
338 cbyTrack = (ULLONG)pdenDevice->de_BlocksPerTrack * (ULLONG)(pdenDevice->de_SizeBlock * sizeof(LONG));
339 cbyCylinder = cbyTrack * pdenDevice->de_Surfaces;
341 ibyStart = pdenDevice->de_LowCyl * cbyCylinder;
342 ibyEnd = (pdenDevice->de_HighCyl + 1) * cbyCylinder;
344 #if defined(__mc68000) && !defined(__AROS__)
345 /* If the device has a native Amiga file-system, we can check for
346 various limitations and also apply the various command-line
347 flags that specify which variant to use for the new volume. */
349 if( pdenDevice->de_DosType >= 0x444F5300
350 && pdenDevice->de_DosType <= 0x444F5305 )
352 const struct Resident * prt;
353 UWORD verFS;
355 /* I'd prefer to do this properly by reading the segment size
356 and going through the segment list, but the fake ROM
357 "segment lists" don't have valid segment sizes set so that
358 would be a bit pointless. Perhaps I should use TypeOfMem
359 to decide whether the segment is in ROM or RAM first? */
361 prt = (struct Resident *)((char *)BADDR(
362 pdlDevice->dol_misc.dol_handler.dol_SegList) + 4);
363 while( prt->rt_MatchWord != RTC_MATCHWORD
364 || prt->rt_MatchTag != prt )
365 prt = (struct Resident *)((UWORD *)prt + 1);
366 verFS = prt->rt_Version;
367 D(Printf( "found RomTag at 0x%08lx; rt_Version = %lu\n",
368 (ULONG)prt, (ULONG)verFS ));
370 /* check that the fs can handle this device correctly */
372 if( ibyEnd - ibyStart > 0x100000000ULL
373 && verFS <= 43 ) /* perhaps v44 will change this? ;-) */
375 UnLockDosList(flags);
376 ReportErrSz(
377 ertError,
379 _(MSG_ERROR_TOO_LARGE_1) );
380 return FALSE;
382 if( ibyEnd > 0x100000000ULL && verFS < 43 )
384 UnLockDosList(flags);
385 ReportErrSz(
386 ertError,
388 _(MSG_ERROR_TOO_LARGE_2) );
389 return FALSE;
392 if( ibyEnd - ibyStart > 0x80000000ULL && verFS < 40 )
394 UnLockDosList( LDF_DEVICES | LDF_READ );
395 ReportErrSz(
396 ertError,
398 _(MSG_ERROR_TOO_LARGE_3) );
399 return FALSE;
402 #endif
404 UnLockDosList(flags);
406 #ifndef __MORPHOS__
407 /* Certain documentation says MEMF_PUBLIC doesn't matter, and
408 certain progams don't bother setting it by default. They
409 are wrong and should be fixed!
410 Unfortunately MorphOS mounts builtin filesystems without
411 this flag and this can't be changed. So we disable this check
412 under MorphOS */
413 if( !(BufMemType & MEMF_PUBLIC) )
415 ReportErrSz(
416 ertWarning,
418 _(MSG_ERROR_TOO_LARGE_4) );
419 BufMemType |= MEMF_PUBLIC;
421 #endif
423 return TRUE;
427 void FreeDosDevice(void)
429 if(bInhibited)
431 *pchDosDeviceColon = ':';
432 D(Printf( "Inhibit( \"%s\", DOSFALSE );\n", (ULONG)szDosDevice ));
433 (void) Inhibit( szDosDevice, DOSFALSE );
434 bInhibited = FALSE;
439 BOOL bGetExecDevice( BOOL bWillVerify )
441 *pchDosDeviceColon = ':';
442 D(Printf( "Inhibit( \"%s\", DOSTRUE );\n", (ULONG)szDosDevice ));
443 if(!Inhibit( szDosDevice, DOSTRUE ))
445 /* This is a bit stupid, but compatible with v40 Format */
446 ReportErrSz( ertFailure, ERROR_OBJECT_WRONG_TYPE, 0 );
447 return FALSE;
449 bInhibited = TRUE;
451 if( (pmpDiskIO = CreateMsgPort()) == 0
452 || (piosDisk = (struct IOStdReq *)
453 CreateIORequest( pmpDiskIO, sizeof(struct IOStdReq) )) == 0 )
455 D(Printf("pmpDiskIO = 0x%08lX, piosDisk = 0x%08lX\n", pmpDiskIO, piosDisk));
456 ReportErrSz( ertFailure, ERROR_NO_FREE_STORE, 0 );
457 return FALSE;
461 BYTE derr = OpenDevice( pszExecDevice,
462 ExecUnit,
463 (struct IORequest *)piosDisk,
464 bDevfSet ? devfCurrent : ExecDeviceFlags );
465 if( derr != 0 )
467 ReportErrSz(
468 ertFailure, -1, _(MSG_ERROR_DEVICE), (ULONG)derr );
469 return FALSE;
471 bExecDevOpen = TRUE;
474 #ifdef __mc68000
476 /* This is an attempt to spot a scsi.device that is really an
477 IDE driver. If we have a card slot (A600/A1200) or AGA
478 (A1200/A4000/A4000T/CD32/clones) then it probably is. If
479 the version number is lower than 40 then it does not limit
480 transfers to 128 blocks as required for correct operation
481 of some drives. */
482 struct GfxBase * GfxBase = (struct GfxBase *)
483 OpenLibrary( "graphics.library", 39 );
484 if( !strcmp( pszExecDevice, "scsi.device" )
485 && piosDisk->io_Device->dd_Library.lib_Version < 40
486 && (OpenResource("card.resource")
487 || (GfxBase && (GfxBase->ChipRevBits0 & GFXF_AA_ALICE)) ))
489 bSuspectIDE = TRUE;
490 if( MaxTransfer > 0x10000 )
492 MaxTransfer = 0x10000;
493 ReportErrSz(
494 ertWarning,
496 _(MSG_ERROR_IDE) );
499 if(GfxBase)
500 CloseLibrary((struct Library *)GfxBase);
502 #endif
504 if( ibyEnd > 0x100000000ULL )
506 static struct NSDeviceQueryResult nsdqr; /* must be in public memory */
507 BYTE derr;
508 BOOL bDoes64Bit = FALSE;
510 piosDisk->io_Command = NSCMD_DEVICEQUERY;
511 piosDisk->io_Data = &nsdqr;
512 piosDisk->io_Length = sizeof(nsdqr);
513 nsdqr.DevQueryFormat = 0;
514 nsdqr.SizeAvailable = 0;
516 switch( derr = DoIO((struct IORequest *)piosDisk) )
518 case 0:
519 if( piosDisk->io_Actual == sizeof(nsdqr) )
521 if( nsdqr.DeviceType == NSDEVTYPE_TRACKDISK )
523 /* Look for 64-bit trackdisk commands - any one will
524 do, as drivers must implement all or none of them. */
525 UWORD * pcmd;
526 for( pcmd = nsdqr.SupportedCommands; *pcmd != 0; ++pcmd )
527 if( *pcmd == NSCMD_TD_READ64 )
528 bDoes64Bit = TRUE;
530 else
532 /* How odd... it's not trackdisk-like */
533 ReportErrSz( ertError, ERROR_OBJECT_WRONG_TYPE, 0 );
534 return FALSE;
537 break;
539 case IOERR_NOCMD:
540 break;
542 default:
543 ReportErrSz(
544 ertFailure,
546 _(MSG_ERROR_DEVICE_QUERY),
547 (ULONG)derr );
548 return FALSE;
551 if(!bDoes64Bit)
553 ReportErrSz(
554 ertError,
556 _(MSG_ERROR_64BIT) );
557 return FALSE;
561 /* We need two buffers - one for writing and one for reading back to
562 verify the write */
563 D(Printf("Allocating buffers, size %lu bytes\n", cbyCylinder));
564 if( (paulWriteBuffer = AllocMem( cbyCylinder,
565 BufMemType )) == 0
566 || (bWillVerify
567 && (paulReadBuffer = AllocMem( cbyCylinder, BufMemType )) == 0) )
569 ReportErrSz( ertFailure, ERROR_NO_FREE_STORE, 0 );
570 return FALSE;
574 /* Fill a buffer with junk, just like the official Format
575 does. Perhaps this is meant to make the verification a
576 harder test. */
577 ULONG * pulFill = paulWriteBuffer;
578 ULONG * pulLimit = (ULONG *)((char *)paulWriteBuffer + cbyCylinder);
579 while( pulFill < pulLimit )
581 int i, j;
582 for( i = 0; i < 16 && pulFill < pulLimit; ++i )
584 ULONG ul = 0x444F5300 + ((i >> 2) << 10);
585 for( j = 0; j < 256 && pulFill < pulLimit; ++j )
586 *pulFill++ = ul++;
591 /* For most drives, the geometry is totally fake and the drive can
592 never be formatted by the user. The driver will really treat
593 TD_FORMAT the same as CMD_READ. However, for some drives, we
594 will be doing a real format using the real geometry. In that
595 case we *must* write a whole track at a time. So what if
596 MaxTransfer is smaller than one track?
598 * MaxTransfer happens to be useful for working round firmware
599 bugs in some IDE drives which scsi.device versions < 40
600 didn't work around, but that's not its purpose. We've
601 already spotted problematic drivers and we know that they
602 don't really format the disk, so we should apply the limit
603 in that case.
605 * As far as I can see, MaxTransfer is really there to limit the
606 time that the I/O bus may be tied up with DMA transfers. If
607 we have to write more than that to format the disk, so be it.
609 Ideally, we want to write whole cylinders at once, since longer
610 transfers are fastest. We do this if the length of a cylinder
611 is less than or equal to MaxTransfer.
612 Otherwise, we write a track each time, unless we have a suspect
613 IDE drive and the length of a track is greater than MaxTransfer
614 - in which case we write at most MaxTransfer each time. */
616 cbyTransfer = (cbyCylinder <= MaxTransfer) ?
617 cbyCylinder :
618 ((!bSuspectIDE || cbyTrack <= MaxTransfer) ?
619 cbyTrack : MaxTransfer);
621 return TRUE;
625 void FreeExecDevice(void)
627 if(paulWriteBuffer)
629 FreeMem( paulWriteBuffer, cbyCylinder );
630 paulWriteBuffer = 0;
632 if(paulReadBuffer)
634 FreeMem( paulReadBuffer, cbyCylinder );
635 paulReadBuffer = 0;
637 if(bExecDevOpen)
639 CloseDevice((struct IORequest *)piosDisk);
640 bExecDevOpen = FALSE;
642 if(piosDisk)
644 DeleteIORequest((struct IORequest *)piosDisk);
645 piosDisk = 0;
647 if(pmpDiskIO)
649 DeleteMsgPort(pmpDiskIO);
650 pmpDiskIO = 0;
655 BOOL bFormatCylinder( ULONG icyl )
657 BYTE derr;
659 /* put a "BAD\0" marker at the beginning in case format is aborted */
660 /* put normal "DOS\0" marker at the beginning of other cylinders */
661 paulWriteBuffer[0] =
662 (icyl == LowCyl) ? 0x42414400 : 0x444F5300;
664 if( !bTransferCylinder( paulWriteBuffer, icyl,
665 NSCMD_TD_FORMAT64, TD_FORMAT ) )
666 return FALSE;
668 /* Write out and invalidate the track buffer */
669 piosDisk->io_Command = CMD_UPDATE;
670 derr = DoIO((struct IORequest *)piosDisk);
671 if( derr == 0 )
673 piosDisk->io_Command = CMD_CLEAR;
674 derr = DoIO((struct IORequest *)piosDisk);
675 if( derr == 0 )
676 return TRUE;
679 ReportErrSz( ertFailure, -1,
680 _(MSG_ERROR_DEVICE_RETURN),
681 (piosDisk->io_Command == CMD_UPDATE) ?
682 _(MSG_ERROR_FLUSH) : _(MSG_ERROR_INVALIDATE),
683 (ULONG)derr );
684 return FALSE;
688 BOOL bVerifyCylinder( ULONG icyl )
690 if( !bTransferCylinder( paulReadBuffer, icyl,
691 NSCMD_TD_READ64, CMD_READ ) )
692 return FALSE;
694 if( memcmp( paulWriteBuffer, paulReadBuffer, cbyCylinder ) != 0 )
696 ReportErrSz( ertFailure, -1, _(MSG_ERROR_VERIFY) );
697 return FALSE;
700 return TRUE;
704 static BOOL bTransferCylinder(
705 APTR pBuffer, ULONG icyl, UWORD cmd64, UWORD cmd32 )
707 ULLONG ibyOffset = (ULLONG)icyl * (ULLONG)cbyCylinder;
708 ULLONG cbyLeft = cbyCylinder;
712 ULONG cbyLength = (cbyTransfer <= cbyLeft) ? cbyTransfer : cbyLeft;
714 if( ibyOffset + cbyLength >= 0x100000000ULL )
716 piosDisk->io_Command = cmd64;
717 piosDisk->io_Actual = ibyOffset >> 32;
719 else
720 piosDisk->io_Command = cmd32;
722 piosDisk->io_Offset = ibyOffset;
723 piosDisk->io_Length = cbyLength;
724 piosDisk->io_Data = pBuffer;
726 D(Printf( "DoIO() Cmd=%2lu Act=0x%08lx Len=0x%08lx "
727 "Data=0x%08lx Off=0x%08lx\n",
728 piosDisk->io_Command,
729 piosDisk->io_Actual,
730 piosDisk->io_Length,
731 (ULONG)piosDisk->io_Data,
732 piosDisk->io_Offset ));
734 if( DoIO((struct IORequest *)piosDisk) != 0 )
736 const char * pszCommand = NULL;
737 switch(piosDisk->io_Command)
739 case NSCMD_TD_FORMAT64:
740 pszCommand = _(MSG_COMMAND_FORMAT64); break;
741 case TD_FORMAT:
742 pszCommand = _(MSG_COMMAND_FORMAT); break;
743 case NSCMD_TD_READ64:
744 pszCommand = _(MSG_COMMAND_READ64); break;
745 case CMD_READ:
746 pszCommand = _(MSG_COMMAND_READ); break;
748 ReportErrSz( ertFailure, -1,
749 _(MSG_ERROR_DEVICE_RETURN),
750 pszCommand, (ULONG)piosDisk->io_Error );
751 return FALSE;
754 ibyOffset += cbyLength;
755 pBuffer = (char *)pBuffer + cbyLength;
756 cbyLeft -= cbyLength;
758 while( cbyLeft != 0 );
760 return TRUE;
764 BOOL bMakeFileSys( BOOL bFFS, BOOL bOFS, BOOL bIntl, BOOL bNoIntl,
765 BOOL bDirCache, BOOL bNoDirCache )
767 if(!bFstSet)
769 fstCurrent = DosType;
771 if( fstCurrent >= 0x444F5300 && fstCurrent <= 0x444F5305 )
773 /* Adjust the file-system type according to command-line
774 switches or check-boxes (this exactly matches the logic of the
775 official version 40 Format command). */
777 if(bFFS) fstCurrent |= 1;
778 if(bOFS) fstCurrent &= ~1;
779 if( !(fstCurrent & 2) )
781 if(bDirCache) fstCurrent |= 4;
782 if(bNoDirCache) fstCurrent &= ~4;
784 if( !(fstCurrent & 4) )
786 if(bIntl) fstCurrent |= 2;
787 if(bNoIntl) fstCurrent &= ~2;
789 } /* if( fstCurrent >= 0x444F5300 && fstCurrent <= 0x444F5305 ) */
790 } /* if(!bFstSet) */
792 if(!bInhibited)
794 *pchDosDeviceColon = ':';
795 D(Printf( "Inhibit( \"%s\", DOSTRUE );\n", (ULONG)szDosDevice ));
796 if(!Inhibit( szDosDevice, DOSTRUE ))
798 /* This is a bit stupid, but compatible with v40 Format */
799 ReportErrSz( ertFailure, ERROR_OBJECT_WRONG_TYPE, 0 );
800 return FALSE;
802 bInhibited = TRUE;
805 D(Printf( "Format( \"%s\", \"%s\", 0x%08lx );\n",
806 (ULONG)szDosDevice, (ULONG)(szVolume + 1), fstCurrent ));
807 if( !Format( szDosDevice,
808 (DOSBase->dl_lib.lib_Version == 36) ?
809 (char *)MKBADDR(szVolume) : szVolume + 1,
810 fstCurrent ) )
812 ReportErrSz( ertFailure, 0, 0 );
813 return FALSE;
816 return TRUE;
820 BOOL bMakeFiles( BOOL bDiskIcon )
822 struct Library * IconBase;
823 BOOL bSuccess = FALSE;
825 /* We have to unlock the DOS list and uninhibit the device before we
826 can write files to the new volume! */
827 FreeDosDevice();
829 if( (IconBase = OpenLibrary( "icon.library", 36 )) != 0 )
831 BPTR bpflRoot;
832 *pchDosDeviceColon = ':';
833 if( (bpflRoot = Lock( szDosDevice, SHARED_LOCK )) != 0 )
835 BPTR bpflOldCD = CurrentDir(bpflRoot);
836 BPTR bpflTrash = CreateDir("Trashcan");
838 if(bpflTrash)
840 struct DiskObject * pdo;
841 UnLock(bpflTrash);
842 pdo = GetDefDiskObject(WBGARBAGE);
844 if(pdo)
846 if( PutDiskObject( "Trashcan", pdo ) )
847 bSuccess = TRUE;
848 FreeDiskObject(pdo);
852 if(!bSuccess)
853 ReportErrSz( ertFailure,
855 _(MSG_ERROR_TRASHCAN),
856 (IPTR)(szVolume + 1) );
857 else if( bDiskIcon )
859 struct DiskObject * pdo;
860 char szDefDiskIcon[12+MAX_FS_NAME_LEN+4+1];
862 bSuccess = FALSE; /* always assume the worst */
864 /* Try to get the icon that DefIcons would use -
865 first, look for a device-specific one; if that
866 fails look for a file-system-specific one; if that
867 fails then get the standard default disk icon. */
868 *pchDosDeviceColon = 0;
869 RawDoFmtSz( szDefDiskIcon, "ENV:sys/def_%sdisk", szDosDevice );
870 if( (pdo = GetDiskObject(szDefDiskIcon)) == 0 )
872 int i;
873 strcpy( szDefDiskIcon, "ENV:sys/def_ disk" );
874 for( i = 0; i < 4; ++i )
876 char chFSType = ((char *)&fstCurrent)[i];
877 szDefDiskIcon[12+i] =
878 (chFSType < 10) ? ('0' + chFSType) : chFSType;
880 if( (pdo = GetDiskObject(szDefDiskIcon)) == 0 )
881 pdo = GetDefDiskObject(WBDISK);
883 if(pdo)
885 if( PutDiskObject( "Disk", pdo ) )
886 bSuccess = TRUE;
887 FreeDiskObject(pdo);
890 if(!bSuccess)
891 ReportErrSz( ertFailure,
893 _(MSG_ERROR_ICON),
894 (IPTR)(szVolume + 1) );
897 CurrentDir(bpflOldCD);
898 UnLock(bpflRoot);
900 CloseLibrary(IconBase);
902 else /* IconBase == 0 */
903 ReportErrSz( ertFailure, ERROR_INVALID_RESIDENT_LIBRARY, 0 );
905 return bSuccess;
909 void FreeAll(void)
911 FreeExecDevice();
912 FreeDosDevice();
915 #ifndef HAVE_NEWRAWDOFMT
916 #ifdef __mc68000
917 static const UWORD AddChSz[] = {0x16C0, 0x4E75}; /* move.l d0,(a3)+ : rts */
919 void RawDoFmtSz( char * pszBuffer, const char * pszFormat, ... )
921 RawDoFmt( (char *)pszFormat, (APTR)(&pszFormat+1),
922 (void (*)())AddChSz, pszBuffer );
925 void RawDoVFmtSz( char * pszBuffer, const char * pszFormat, APTR pData )
927 RawDoFmt( (char *)pszFormat, pData, (void (*)())AddChSz, pszBuffer );
929 #else
930 #error CPU is not supported
931 #endif
932 #endif