/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by Olaf Barthel & MXM * * Name .....: OldFormat.c * Created ..: Wednesday 29-May-91 17:06 * Revision .: 1 * * Date Author Comment * ========= ======== ==================== * 29-May-91 Olsen Created this file! * **************************************************************************** * * This file contains disk initialization routines written for * Kickstart 1.2 and 1.3. They will probably work with Kickstart 2.0 * and above and require that the approriate filing system is * `inhibited' before any write access takes place. Manx and Arp * have different routines to pass the the approriate Dos packet, * so this part of the formatting process is omitted. * * The main routine (EraseDisk) is extensively documented, the rest * lacks a decent description. Nevertheless, these routines work * like the Format dos.library call available under Kickstart 2.0 * * $Revision Header ********************************************************/ #include #include #include #include #include #include #include struct BitmapBlock { ULONG Checksum; ULONG Bitmap[127]; }; struct BitmapExtension { ULONG BitmapPointers[127]; ULONG BitmapExtension; }; struct RootDirectory { ULONG PrimaryType; ULONG HeaderKey; ULONG WhoKnows0; ULONG HashTableSize; ULONG WhoKnows1; ULONG Checksum; ULONG HashTable[72]; ULONG BitmapFlag; ULONG BitmapPointers[25]; ULONG BitmapExtension; struct DateStamp LastRootChange; UBYTE DiskName[32]; ULONG WhoKnows2[2]; struct DateStamp LastDiskChange; struct DateStamp CreationDate; ULONG NextHash; ULONG ParentDir; ULONG WhoKnows3; ULONG SecondaryType; }; STATIC UBYTE Local2Upper(UBYTE c) { return((UBYTE)((((c) >= 224 && (c) <= 254) || ((c) >= 'a' && (c) <= 'z')) ? (c) - 32 : (c))); } STATIC LONG StrCmp(UBYTE *a,UBYTE *b) { for( ; Local2Upper(*a) == Local2Upper(*b) ; a++, b++) { if(!(*a)) return(0); } return((LONG)(Local2Upper(*a) - Local2Upper(*b))); } STATIC struct FileSysStartupMsg * FindDevice(UBYTE *DevName) { extern struct DosLibrary *DOSBase; UBYTE *Pointer,i,Name[40]; struct DeviceNode *DevInfo; Forbid(); DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo); while(DevInfo) { if(DevInfo -> dn_Type == DLT_DEVICE) { Pointer = (UBYTE *)BADDR(DevInfo -> dn_Name); for(i = 0 ; i < Pointer[0] ; i++) Name[i] = Pointer[i + 1]; Name[Pointer[0] ] = ':'; Name[Pointer[0] + 1] = 0; if(!StrCmp(Name,DevName)) { Permit(); return(BADDR(DevInfo -> dn_Startup)); } } DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next); } Permit(); return(NULL); } STATIC ULONG Checksum(ULONG *DiskSector) { ULONG Sum; SHORT i; for(Sum = 0, i = 0 ; i < (TD_SECTOR >> 2) ; i++) Sum += DiskSector[i]; return(Sum); } STATIC LONG WriteBlock(struct IOExtTD *DevRequest,APTR Buffer,ULONG Offset) { DevRequest -> iotd_Req . io_Command = CMD_WRITE; DevRequest -> iotd_Req . io_Data = Buffer; DevRequest -> iotd_Req . io_Length = TD_SECTOR; DevRequest -> iotd_Req . io_Offset = Offset * TD_SECTOR; return((LONG)DoIO(DevRequest)); } STATIC LONG EraseDisk(UBYTE *DiskName,struct IOExtTD *DevRequest,ULONG FirstBlock,ULONG Blocks,ULONG Reserved,ULONG DosType) { STATIC ULONG Bits[32] = { 0xFFFFFFFE,0xFFFFFFFD,0xFFFFFFFB,0xFFFFFFF7, 0xFFFFFFEF,0xFFFFFFDF,0xFFFFFFBF,0xFFFFFF7F, 0xFFFFFEFF,0xFFFFFDFF,0xFFFFFBFF,0xFFFFF7FF, 0xFFFFEFFF,0xFFFFDFFF,0xFFFFBFFF,0xFFFF7FFF, 0xFFFEFFFF,0xFFFDFFFF,0xFFFBFFFF,0xFFF7FFFF, 0xFFEFFFFF,0xFFDFFFFF,0xFFBFFFFF,0xFF7FFFFF, 0xFEFFFFFF,0xFDFFFFFF,0xFBFFFFFF,0xF7FFFFFF, 0xEFFFFFFF,0xDFFFFFFF,0xBFFFFFFF,0x7FFFFFFF }; ULONG *Bitmap,AllocSize; APTR Buffer; struct BitmapBlock *BitmapBlock; struct BitmapExtension *BitmapExtension; struct RootDirectory *RootDirectory; LONG i,Count,Root,Len; LONG BitmapCount,BitmapBlocks; LONG ExtensionCount,ExtensionBlocks = 0; LONG Error; /* Number of long words to allocate for the bitmap. */ AllocSize = (Blocks - Reserved + 31) / 32; /* Allocate a block-sized buffer. */ if(Buffer = AllocMem(TD_SECTOR,MEMF_PUBLIC|MEMF_CHIP)) { /* Clear the buffer. */ memset(Buffer,0,TD_SECTOR); /* Enough space to write the boot block? */ if(Reserved) { /* Put the DOS type field into the first longword. */ *(ULONG *)Buffer = DosType; /* And write it. */ if(Error = WriteBlock(DevRequest,Buffer,0 + FirstBlock)) return(Error); memset(Buffer,0,TD_SECTOR); /* Clear the rest. */ for(i = 1 ; i < Reserved ; i++) { if(Error = WriteBlock(DevRequest,Buffer,FirstBlock + i)) return(Error); } } /* Allocate space for the bitmap. */ if(Bitmap = (ULONG *)AllocMem(sizeof(ULONG) * AllocSize,MEMF_PUBLIC)) { /* Mark all blocks as `unused'. */ for(i = 0 ; i < AllocSize ; i++) Bitmap[i] = ~0; /* Determine number of bitmap blocks. */ Count = BitmapBlocks = (AllocSize + 126) / 127; /* If there are more than 25 bitmap blocks to create, * we will need at least one bitmap extension block. */ if(Count > 25) { /* The old filing system doesn't support bitmap * extension blocks. */ if(DosType == ID_DOS_DISK) return(-1); /* Subtract 25 blocks since they will fit into the * root block. */ Count -= 25; /* Add the extension blocks. */ do { ExtensionBlocks++; /* Subtract the blocks that will fit into the * extension block. */ if(Count > 127) Count -= 127; else Count = 0; } while(Count); } /* Calculate the root block offset. */ Root = Blocks >> 1; RootDirectory = Buffer; memset(RootDirectory,0,TD_SECTOR); /* Fill in the root directory data. */ RootDirectory -> PrimaryType = 2; RootDirectory -> HashTableSize = 128 - 56; RootDirectory -> BitmapFlag = DOSTRUE; DateStamp(&RootDirectory -> LastRootChange); if((Len = strlen(DiskName)) > 31) Len = 31; RootDirectory -> DiskName[0] = Len; CopyMem(DiskName,&RootDirectory -> DiskName[1],Len); DateStamp(&RootDirectory -> LastDiskChange); DateStamp(&RootDirectory -> CreationDate); RootDirectory -> SecondaryType = 1; /* Fill in the bitmap block pointers. */ for(i = 0 ; i < BitmapBlocks ; i++) { if(i == 25) break; else RootDirectory -> BitmapPointers[i] = Root + 1 + i + FirstBlock; } /* If there are more than 25 bitmap blocks, fill in the * pointer to the first bitmap extension block. */ if(BitmapBlocks > 25) RootDirectory -> BitmapExtension = Root + 1 + 25 + FirstBlock; /* Calculate the block checksum. */ RootDirectory -> Checksum = - Checksum((ULONG *)RootDirectory); /* And write the block. */ if(Error = WriteBlock(DevRequest,RootDirectory,Root + FirstBlock)) return(Error); /* The blocks to be occupied by the root block, the bitmap * blocks and the extension blocks are to be marked as * being `in use'. */ for(i = Root - Reserved ; i < Root - Reserved + 1 + BitmapBlocks + ExtensionBlocks ; i++) Bitmap[i / 32] &= Bits[i % 32]; BitmapBlock = Buffer; /* The root block has been written, now continue with the * bitmap blocks. */ for(i = 0 ; i < BitmapBlocks ; i++) { /* Copy the bitmap data. */ CopyMem(&Bitmap[127 * i],&BitmapBlock -> Bitmap[0],127 * sizeof(ULONG)); /* Calculate the block checksum. */ BitmapBlock -> Checksum = 0; BitmapBlock -> Checksum = - Checksum((ULONG *)BitmapBlock); /* And write the block. */ if(Error = WriteBlock(DevRequest,BitmapBlock,Root + 1 + i + FirstBlock)) return(Error); } BitmapExtension = Buffer; /* If there are any bitmap extension blocks, create them. */ if(ExtensionBlocks) { /* Remember the first blocks to deal with. */ BitmapCount = Root + 1 + FirstBlock; ExtensionCount = BitmapCount + BitmapBlocks; /* Subtract the first 25 blocks. */ BitmapBlocks -= 25; /* As long as there are any blocks, put them into * the extension blocks. */ while(BitmapBlocks) { memset(BitmapExtension,0,TD_SECTOR); /* Fill in the bitmap pointers. */ for(i = 0 ; i < (BitmapBlocks < 127 ? BitmapBlocks : 127) ; i++) BitmapExtension -> BitmapPointers[i] = BitmapCount++; /* Subtract the bitmap blocks bound to the extension * block. */ if(BitmapBlocks > 127) BitmapBlocks -= 127; else BitmapBlocks = 0; /* If there are any bitmap blocks left, chain * this bitmap extension block to the next one. */ if(BitmapBlocks) BitmapExtension -> BitmapExtension = ExtensionCount + 1; /* And write it. */ if(Error = WriteBlock(DevRequest,BitmapExtension,ExtensionCount++)) return(Error); } } /* Free the data. */ FreeMem(Bitmap,sizeof(ULONG) * AllocSize); FreeMem(Buffer,TD_SECTOR); return(0); } FreeMem(Buffer,TD_SECTOR); } return(-1); } LONG Format(UBYTE *Drive,UBYTE *Name,ULONG DosType) { struct FileSysStartupMsg *Startup; struct DosEnvec *DosEnvec; LONG Success = FALSE; if(Startup = FindDevice(Drive)) { struct IOExtTD *DevRequest; struct MsgPort *DevPort; if(DevPort = CreatePort(NULL,0)) { if(DevRequest = (struct IOExtTD *)CreateExtIO(DevPort,sizeof(struct IOExtTD))) { if(!OpenDevice(&((UBYTE *)BADDR(Startup -> fssm_Device))[1],Startup -> fssm_Unit,DevRequest,Startup -> fssm_Flags)) { DosEnvec = (struct DosEnvec *)BADDR(Startup -> fssm_Environ); DevRequest -> iotd_Req . io_Command = TD_MOTOR; DevRequest -> iotd_Req . io_Length = 1; DoIO(DevRequest); if(!EraseDisk(Name,DevRequest,DosEnvec -> de_LowCyl * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces,(DosEnvec -> de_HighCyl - DosEnvec -> de_LowCyl + 1) * DosEnvec -> de_BlocksPerTrack * DosEnvec -> de_Surfaces,DosEnvec -> de_Reserved,DosType)) Success = TRUE; DevRequest -> iotd_Req . io_Command = TD_MOTOR; DevRequest -> iotd_Req . io_Length = 0; DoIO(DevRequest); CloseDevice(DevRequest); } DeleteExtIO(DevRequest); } DeletePort(DevPort); } } return(Success); }