/*********************************************************************** * format.c - quick and dirty format for CDOS 68K on VME/10 * * VERSION DATE WHO CHANGE * ======= ==== === ====== * 1.5 03/24/86 MA Close disk after writing * booter, to avoid media change errors * putting system files. * 1.4 02/24/86 MA Use default drive if none specified. * 1.3 01/23/86 MA First sector in track is now 1, not 0. * This was changed in disk driver, making * previous FORMAT incompatible. ***********************************************************************/ /*********************************************************************** * VME/10 DISK FORMAT (a brief summary) * * 1. TENbug sector 0 (256 bytes) contains information about where * the booter is and where the Disk Configuration area is. * 2. TENbug sector 1 (256 bytes) is the DCA. It contains information * about how big the disk is (i.e. physical format). * 3. On the floppy disk, there are 12 more 128-byte sectors * following the TENbug sectors that aren't used. This fills * up the first track (which is single density). These sectors * are not considered part of the system area by the driver, * i.e. reads/writes of the system area skip over them. * 4. The booter sectors are 16 256-byte sectors (on a hard disk) * or 8 512-byte sectors (on the floppy disk). The first few * bytes of the booter contain a PC-DOS-like BPB (bios parameter * block). Then follows the booter code and data. The first * two long words of the BPB are used by TENbug to set up the * initial SP and PC for the booter. Following the BPB is the * booter code and data. The booter is read from the BOOTER.68K * file. The FORMAT utility fills in the BPB itself. * 5. The FATs follow. Just like DOS. * 6. The root directory follows. Just like DOS. * * NOTES: * 1. The BPB is DOS compatible, so all words are byte swapped to * be like the 8086. This is done so that the driver can read * both VME/10 format disks and IBM PC disks using common * code. * 2. The array of MDB structures, called "mdbs", and the "ncyls" * array, contain all the information about disk formats. To * support new drive capacities and formats, change these two * structures. * 3. There is some inconsistency in the MDBs regarding the SYSSIZE * and HIDDEN sector counts. This is the result of the crazy * floppy format on the VME/10, where track 0 is a different * format from the rest of the disk. ***********************************************************************/ #include "portab.h" #include "stdio.h" EXTERN LONG xopen(),xclose(),xread(); /* in XIO.C */ EXTERN LONG s_read(),s_write(),s_special(); /* in SYSLIB.L68 */ EXTERN LONG s_define(); /* in SYSLIB.L68 */ EXTERN LONG putsys(); /* in PUTSYS.C */ /* SIZE OF SYSTEM AREA: 2*256: two versados sectors for Volume ID and Disk Configuration Area that TENbug needs to boot 8*512: the booter itself */ #define SYSSIZE 0x1200 /* SIZE OF LARGEST POSSIBLE FAT: 22*256: the fatsize for a 40 Meg hard disk */ #define MAXFATSZ 0x1600 /* FORMAT TRACK special parameter block */ struct { BYTE fhead; BYTE fzero1; WORD fcylinder; BYTE fdens; BYTE ffill; WORD fbytesec; WORD fsectrk; WORD fsector; } ftrkpb; /* MDB - media descriptor block - see fig. 8-6 Concurrent System Guide */ #define MDB struct _mdb MDB { WORD msectsize; WORD mfirstsec; LONG mnsectors; WORD msectrk; WORD msecblk; BYTE mnfats; BYTE mfatid; WORD mnfrecs; WORD mdirsize; BYTE mnheads; BYTE mformat; LONG mhidden; LONG msyssize; }; /* MDBs for various kinds of disks. WARNING: mdirsize * 32 must be an exact multiple of msectsize, or code herein will not work right. */ MDB mdbs [5] = { { /* 0 - Floppy disk */ 512, 0, 8*158, 8, 4, 2, 0xff, 1, 224, 2, 1, 16, SYSSIZE }, { /* 1 - 5 Meg hard disk */ 256, 18, 19566L, 32, 8, 2, 0xf8, 15, 512, 2, 1, 0, SYSSIZE }, { /* 2 - 10 Meg hard disk */ 256, 18, 39150L, 32, 16, 2, 0xf8, 15, 512, 4, 1, 0, SYSSIZE }, { /* 3 - 15 Meg hard disk */ 256, 18, 58734L, 32, 16, 2, 0xf8, 22, 512, 6, 1, 0, SYSSIZE }, { /* 4 - 40 Meg hard disk */ 256, 18, 159342L,32, 64, 2, 0xf8, 15, 512, 6, 1, 0, SYSSIZE }}; /* Number of cylinders for the different kinds of disks (not in the MDB) */ WORD ncyls[5] = { 80, 306, 306, 306, 830 }; /* CP/M-68K program header - see chap. 3 CP/M-68K Programmer's Guide */ struct { WORD magic; LONG textsize; LONG datasize; LONG bsssize; LONG symsize; LONG stksize; LONG textstart; WORD reloc; } header; /* command line switches */ #define MAXSWITCH 4 BYTE swboot,swsys,swvol,swzap; /* true if the switch is set */ BYTE *swvar[MAXSWITCH] = { /* pointer to the switch variables */ &swboot, &swsys, &swvol, &swzap } ; BYTE swchar[MAXSWITCH] = { /* the switch characters */ 'B', 'S', 'V', 'Z' } ; /* misc. local variables */ LONG dfnum; /* disk file number */ LONG ret; /* return code from cdos */ BYTE sysarea[0x2000]; /* general purpose buffer */ BYTE fat[MAXFATSZ]; /* buffer for largest possible FAT */ WORD datasect; /* first data sector (after directory) */ WORD type; /* disk type */ MDB mdb; /* copy of our working MDB */ BYTE diskname[16]; /* name of drive being formatted (A:, B:, etc.) */ LONG bfnum; /* booter file number */ LONG bootlen; /* length of booter code+data */ BYTE volume[11]; /* volume name */ BYTE linebuf[80]; /* general purpose input line buffer */ LONG badsize; /* total size of bad areas on disk */ LONG sysfiles; /* total size of system files */ BYTE defdrv[16]; /* default source drive name */ main(argc,argv) WORD argc; BYTE *argv[]; { BYTE *p; WORD argp,i; printf("VME/10 FORMAT V1.5\r\n"); /* check the options on the command line */ for (argp = 1; argp < argc; argp++) { p = argv[argp]; /* point to the argument */ if (*p++ != '-') /* check the switch character */ { /* must be a drive name */ if (diskname[0]) /* drive already specified? */ error("Drive specified more than once."); strcpy(diskname,argv[1]); /* save the drive name */ } else /* must be a switch */ { for (i = 0; i < MAXSWITCH; i++) /* look up the switch */ { if (toupper(*p) == swchar[i]) /* found a match? */ { *swvar[i] = 1; break; } } if (i == MAXSWITCH) /* switch not valid? */ { usage(); s_exit(1L); } } } /* check the drive name for validity */ if (!diskname[0]) /* drive specified? */ getdef(diskname,sizeof(diskname)); /* get default drive name */ diskname[0] = toupper(diskname[0]); if (diskname[0] < 'A' || diskname[0] > 'D' || diskname[1] != ':' || diskname[2] != 0) { printf("Illegal drive: %s",diskname); s_exit(1L); } gettype(); /* get disk type */ getok(); /* ask if they want to destroy disk */ opendisk(); config(); format(); getboot(); putboot(); getvol(); putdir(); closedisk(); if (swsys) sysfiles = putsys(diskname); summary(); s_exit(0L); } /* usage - print a usage summary for this program */ usage() { printf("Usage: format