home *** CD-ROM | disk | FTP | other *** search
- /* ReSizeable RAMDisk - disk formatting
- ** Copyright (c) 1992 Marko Kohtala
- */
-
- #include "srdisk.h"
- #include <stdio.h>
- #include <string.h>
- #include <dos.h>
-
- /*
- ** Format printing
- */
-
- char *stringisize_flags(int flags)
- {
- static char _string[60];
- _string[0] = 0;
- if (!flags) {
- return " NONE";
- } else {
- if (flags & C_APPENDED) strcat(_string, " APPENDED");
- if (flags & C_MULTIPLE) strcat(_string, " MULTIPLE");
- if (flags & C_32BITSEC) strcat(_string, " 32BITSEC");
- if (flags & C_NOALLOC) strcat(_string, " NOALLOC");
- if (flags & C_UNKNOWN) strcat(_string, " unknown");
- }
- return _string;
- }
-
- void print_format(struct format_s *f)
- {
- printf("\n"
- "Drive %c:\n"
- " Disk size: %luK\n"
- " Cluster size: %d bytes\n"
- " Sector size: %d bytes\n"
- " Directory entries: %d\n"
- " FAT copies: %d\n"
- " Bytes available: %ld\n"
- " Write protection: %s\n"
- ,drive
- ,f->size
- ,f->cluster_size
- ,f->bps
- ,f->dir_entries
- ,f->FATs
- ,f->clusters*f->cluster_size
- ,((f->RW_access & WRITE_ACCESS) ? "OFF" : "ON")
- );
- if (verbose > 3)
- printf(" Sectors: %lu\n"
- " Reserved sectors: %d\n"
- " FAT sectors: %d\n"
- " Directory sectors: %d\n"
- " Sectors per cluster: %d\n"
- " Clusters: %lu\n"
- " FAT type: %u bit\n"
- " Max size: %luK\n"
- ,f->sectors
- ,f->reserved
- ,f->FAT_sectors
- ,f->dir_sectors
- ,f->spc
- ,f->clusters
- ,f->FAT_type
- ,f->max_size
- );
- }
-
- /*
- ** Count the files in root directory
- */
-
- static int count_root(void)
- {
- byte *sp;
- int si;
- dword sector = f.dir_start;
- int entries = f.dir_entries;
- int files = 0;
-
- sp = xalloc(f.bps);
-
- while(entries) {
- read_sector(1, sector, sp);
- for(si = 0; si < f.bps && entries; si += 32) {
- if (sp[si] == 0) goto end; /* Unused, end of directory */
- if (sp[si] != 0xE5 /* Not deleted */
- && !(sp[si+11] & 8)) /* and not label */
- files++; /* so it is a file (or directory) */
- entries--;
- }
- sector++;
- }
-
- end:
- free(sp);
- return files;
- }
-
- /*
- ** PERMISSION TO DELETE DATA
- */
-
- int licence_to_kill(void)
- {
- if (!force_f && count_root() > 0) {
- printf("\n\aAbout to destroy all files on drive %c!\n\a"
- "Continue (Y/N) ? ", drive);
- if (!getYN()) {
- printf("\nOperation aborted\n");
- return 0;
- }
- }
- return 1;
- }
-
- /*
- ** COUNT MAX KBYTES FOR DRIVERS IN CHAIN
- */
-
- static void count_maxK(void)
- {
- int i;
- int changed = 0;
-
- for (i = MAX_CHAINED_DRIVERS; i >= f.chain_len; i--)
- if (newf.subconf[i].userdef) {
- error("Too many /M values");
- return;
- }
-
- newf.max_size = 0;
- for (i = 0; i < MAX_CHAINED_DRIVERS; i++)
- {
- if (!newf.subconf[i].userdef)
- newf.subconf[i].maxK = f.subconf[i].maxK;
- else if (newf.subconf[i].maxK != f.subconf[i].maxK)
- changed++;
- newf.max_size += newf.subconf[i].maxK;
- }
- if (!changed) changed_format &= ~MAX_PART_SIZES;
- }
-
- /*
- ** FILL AND ADJUST THE newf
- **
- ** Fills newf fields with the user specified data
- */
-
- static void make_newf(void)
- {
- int suggest_bps, suggest_bpc, suggest_dir, suggest_FATs;
-
- newf.chain_len = f.chain_len;
- newf.reserved = 1;
-
- #define dochange(change,new,old,default) \
- if (!(changed_format & (change))) \
- (new) = (default); \
- else if ((new) == (old)) \
- changed_format &= ~(change);
-
- /* Make values for the fields the user did not supply */
- if (!(changed_format & DISK_SIZE))
- newf.size = f.size;
- if (!(changed_format & MEDIA))
- newf.media = 0xFA;
- if (!(changed_format & SEC_PER_TRACK))
- newf.sec_per_track = 1;
- if (!(changed_format & SIDES))
- newf.sides = 1;
- if (!(changed_format & WRITE_PROTECTION))
- newf.RW_access = WRITE_ACCESS;
-
- count_maxK();
-
- if (use_old_format_f) {
- suggest_bps = f.bps;
- suggest_bpc = f.cluster_size;
- suggest_dir = f.dir_entries;
- suggest_FATs = f.FATs;
- }
- else {
- if (!(changed_format & SECTOR_SIZE)) {
- if (changed_format & CLUSTER_SIZE && newf.cluster_size < max_bps)
- suggest_bps = newf.cluster_size;
- else
- suggest_bps = max_bps;
- }
- else
- suggest_bps = newf.bps;
- if (!(changed_format & CLUSTER_SIZE)) {
- /* !!!! Make better estimate */
- suggest_bpc = newf.size <= 1536L ? 512 :
- newf.size <= 30000L ? 1024 : 2048;
- }
- if (!(changed_format & DIR_ENTRIES)) {
- if (newf.size > 16*512)
- suggest_dir = 512;
- else {
- int entries_per_sec;
- suggest_dir = (int)(newf.size / 16);
- entries_per_sec = suggest_bps / 32;
- suggest_dir += entries_per_sec - suggest_dir % entries_per_sec;
- }
- }
- if (!(changed_format & NO_OF_FATS))
- suggest_FATs = 1;
- }
-
- dochange(SECTOR_SIZE, newf.bps, f.bps, suggest_bps)
- dochange(CLUSTER_SIZE, newf.cluster_size, f.cluster_size, suggest_bpc)
- dochange(DIR_ENTRIES, newf.dir_entries, f.dir_entries, suggest_dir)
- dochange(NO_OF_FATS, newf.FATs, f.FATs, suggest_FATs)
- #undef dochange
- }
-
- static int count_new_format(void)
- {
- newf.FAT_type = 12; /* By default try to use 12 bit FAT */
-
- /* Make sure sectors are big enough for the disk */
- while((newf.sectors = newf.size * 1024 / newf.bps) >
- ((conf->flags & C_32BITSEC) ? 0x7FFFFFL : 0xFFFFL) )
- newf.bps <<= 1;
- if (newf.bps > 512)
- warning("Sector size larger than 512 bytes, may crash DOS");
-
- if (newf.cluster_size < newf.bps)
- newf.cluster_size = newf.bps;
-
- { div_t divr;
- divr = div(newf.dir_entries * 32, newf.bps);
- newf.dir_sectors = divr.quot + (divr.rem ? 1 : 0);
- }
-
- count_clusters:
- newf.system_sectors = newf.reserved + newf.dir_sectors;
- newf.data_sectors = max(newf.sectors - newf.system_sectors, 0);
-
- newf.spc = newf.cluster_size / newf.bps;
-
- { ldiv_t divr;
- long spFAT;
- divr = ldiv(((long)newf.data_sectors + 2 * newf.spc) * newf.FAT_type,
- (long)8 * newf.cluster_size + newf.FATs * newf.FAT_type);
- spFAT = divr.quot + (divr.rem ? 1 : 0);
- if (spFAT > 0xFFFF) {
- if (newf.bps < 512) {
- newf.bps <<= 1;
- if (newf.cluster_size < newf.bps)
- newf.cluster_size = newf.bps;
- }
- else
- newf.cluster_size <<= 1;
- goto count_clusters;
- }
- newf.spFAT = (word)spFAT;
- }
-
- newf.FAT_sectors = newf.spFAT * newf.FATs;
- newf.system_sectors += newf.FAT_sectors;
- newf.data_sectors = max(newf.data_sectors - newf.FAT_sectors, 0);
-
- newf.clusters = newf.data_sectors / newf.spc;
-
- /* Make sure we use the right FAT type */
- if (newf.FAT_type < 16 && newf.clusters > 4077) {
- newf.FAT_type = 16;
- goto count_clusters;
- }
- if (newf.FAT_type > 12 && newf.clusters < 4088 || newf.clusters > 65518L) {
- newf.FAT_type = 12;
- newf.cluster_size <<= 1;
- goto count_clusters;
- }
-
- newf.dir_start = newf.reserved + newf.FAT_sectors;
-
- /* If Disk will be disabled */
- if (!newf.size) {
- newf.data_sectors = 0;
- newf.clusters = 0;
- return 1;
- }
-
- if (newf.sectors <= newf.system_sectors || !newf.clusters)
- return 0;
-
- return 1;
- }
-
- /*
- ** CONFIGURE DRIVE FOR FORMAT newf
- **
- ** Disable drive and configure it. RW_access must be set by caller.
- **
- ** Return 0 if format is impossible
- */
-
- int configure_drive(void)
- {
- long Kleft = newf.size;
- struct config_s far *subconf;
- dword alloc, lastalloc;
- int err = 0;
- int i;
-
- conf->RW_access = 0; /* Disable DOS access to drive */
-
- if (changed_format & MAX_PART_SIZES) {
- for (subconf = conf, i = 0; subconf; subconf = conf_ptr(subconf->next), i++)
- subconf->maxK = newf.subconf[i].maxK;
- if (verbose > 1) {
- printf("\nAdjusted max allocation sizes");
- if (!format_f) printf(" - reformat disk to enable change");
- puts("");
- }
- }
-
- if (newf.size != f.current_size || changed_format & MAX_PART_SIZES) {
- for(subconf = conf; subconf; subconf = conf_ptr(subconf->next)) {
- alloc = max(min(subconf->maxK, Kleft), 0);
- lastalloc = disk_alloc(subconf, alloc);
- if (lastalloc != alloc && (err = !lastalloc) != 0) break;
- subconf->size = lastalloc;
-
- Kleft -= lastalloc;
- }
-
- if (Kleft > 0) { /* If not enough memory could be allocated */
- err = 1;
- if (!conf->next) { /* If single drive, try to preserve it */
- if (disk_alloc(conf, f.current_size) == f.current_size) {
- conf->size = f.current_size; /* Fix back what was changed */
- conf->sectors = (long)f.current_size * 1024 / f.bps;
- conf->RW_access = f.RW_access; /* Enable the disk */
- error("Failed to allocate memory");
- return 0; /* Return failure */
- }
- }
- /* Free all memory */
- for (subconf = conf; subconf; subconf = conf_ptr(subconf->next)) {
- if (!disk_alloc(subconf, 0)) {
- subconf->size = 0;
- subconf->sectors = 0;
- }
- }
- newf.size = 0;
- newf.sectors = 0;
- error("Failed to allocate memory - disk disabled");
- }
-
- if (Kleft < 0 && verbose > 1)
- printf("\n%ldKbytes extra allocated,\n"
- "Perhaps you should make your disk that much larger.\n"
- ,-Kleft);
- }
-
- for(subconf = conf; subconf; subconf = conf_ptr(subconf->next)) {
- subconf->sectors = subconf->size * 1024 / newf.bps;
- subconf->BPB_bps = newf.bps;
- }
-
- conf->BPB_spc = newf.spc;
- conf->BPB_reserved = newf.reserved;
- conf->BPB_FATs = newf.FATs;
- conf->BPB_dir = newf.dir_entries;
- conf->BPB_sectors = (conf->flags & C_32BITSEC && newf.sectors > 0xFFFEL) ?
- 0 : newf.sectors;
- conf->BPB_media = newf.media;
- conf->BPB_FATsectors = newf.spFAT;
- conf->BPB_spt = newf.sec_per_track;
- conf->BPB_heads = newf.sides;
- conf->BPB_hidden = 0L;
- conf->BPB_tsectors = newf.sectors;
- conf->tsize = newf.size;
- conf->open_files = 0;
- if (format_f) conf->media_change = -1;
-
- return !err;
- }
-
- void format_disk(void)
- {
- int Fsec;
- int i;
- byte *sector;
-
- make_newf();
-
- if (!format_f) {
- warning("No change in format - disk remains untouched");
- return;
- }
-
- if (newf.size > newf.max_size) {
- error("Not enough memory for disk available");
- return;
- }
-
- if (!force_f && conf->open_files) {
- error("Files open on drive");
- return;
- }
-
- if (!count_new_format())
- {
- error("Impossible format for disk");
- return;
- }
-
- root_files = f.size ? count_root() : 0;
-
- /* If Disk will be disabled */
- if (!newf.size) {
- if (!f.size) {
- /* If was disabled also before */
- configure_drive();
- if (verbose > 1) printf("\nNew configuration saved for later use\n");
- } else {
- /* If disk now get's disabled */
- if (!licence_to_kill()) return;
- configure_drive();
- if (verbose > 1) printf("\nRAMDisk disabled\n");
- }
- return;
- }
- if (verbose > 1) {
- printf("\nNew disk configuration:\n");
- print_format(&newf);
- }
-
- if (f.size && !licence_to_kill()) return;
-
- /* Request the new disk space and configure the driver(s) */
- if (!configure_drive()) return;
-
- sector = xalloc(newf.bps);
-
- /* Write the new disk */
-
- /* Make the boot sector */
- memset(sector, 0, newf.bps);
- { struct boot_s {
- word jump;
- byte nop;
- char oem[8];
- word bps;
- byte spc;
- word reserved;
- byte FATs;
- word dir_entries;
- word sectors;
- byte media;
- word spFAT;
- word spt;
- word sides;
- dword hidden;
- dword sectors32;
- byte physical;
- byte :8;
- byte signature;
- dword serial;
- char label[11];
- char filesystem[8];
- word bootcode;
- } *b = (struct boot_s*)sector;
-
- b->jump = 0x3CEB; /* Boot record JMP instruction */
- b->nop = 0x90; /* NOP instruction */
- memcpy(&b->oem, "SRD "VERSION, 8); /* OEM code and version */
- b->bps = newf.bps;
- b->spc = newf.spc;
- b->reserved = newf.reserved;
- b->FATs = newf.FATs;
- b->dir_entries = newf.dir_entries;
- b->sectors = (conf->flags & C_32BITSEC && newf.sectors > 0xFFFEL) ?
- 0 : newf.sectors;
- b->media = newf.media; /* Media */
- b->spFAT = newf.spFAT;
- b->spt = newf.sec_per_track; /* Sectors per track */
- b->sides = newf.sides; /* Sides */
- b->hidden = 0; /* Hidden sectors */
- b->sectors32 = newf.sectors; /* Total number of sectors */
- b->physical = -1; /* Physical drive number */
- b->signature = 0x29; /* Signature byte */
- b->serial = time(NULL); /* Serial number */
- _fmemcpy(&b->label,
- ((struct dev_hdr far *)MK_FP(FP_SEG(conf), 0))->u.volume,
- 11); /* Volume label */
- memcpy(&b->filesystem, newf.FAT_type == 12 ? "FAT12 " :
- newf.FAT_type == 16 ? "FAT16 " : " "
- ,8);
- b->bootcode = 0xFEEB; /* Boot code (JMP $) */
- }
- *(word *)(sector+newf.bps-2) = 0xAA55; /* Validity code */
- write_sector(1, 0, sector); /* Write boot sector */
-
- for (i = 0; i < newf.FATs; i++) {
- word sector_n =
- newf.reserved + newf.spFAT * i;
- /* Write 1st FAT sector */
- memset(sector, 0, newf.bps); /* Make 1st FAT sector */
- ((word *)sector)[0] = newf.media | 0xFF00;
- ((word *)sector)[1] = newf.FAT_type == 12 ? 0xFF : 0xFFFF;
- write_sector(1, sector_n++, sector);
-
- /* Write FAT sectors from 2nd to last */
- *(dword *)sector = 0L;
- for (Fsec = 1; Fsec < newf.spFAT; Fsec++)
- write_sector(1, sector_n++, sector);
- }
-
- /* Write 1st directory sector */
- newf.dir_start = newf.reserved + newf.FAT_sectors;
- _fmemcpy(sector, ((struct dev_hdr far *)MK_FP(FP_SEG(conf), 0))->u.volume, 11);
- sector[11] = FA_LABEL;
- *(dword *)(sector+22) = DOS_time(time(NULL));
- write_sector(1, newf.dir_start, sector);
-
- /* Write directory sectors from 2nd to last */
- memset(sector, 0, 32);
- for (Fsec = 1; Fsec < newf.dir_sectors; Fsec++)
- write_sector(1, newf.dir_start+Fsec, sector);
-
- conf->RW_access = READ_ACCESS | newf.RW_access;
-
- free(sector);
-
- if (verbose > 1) printf("\nDisk formatted\n");
- }
-
-
-