inf2007@vax.rz.uni-wuerzburg.dbp.de (inf2007) (01/17/90)
Here is a format program for Minix running with the BOOT menue. It's algorithm is derived from Aubrey McIntosh. It creates only the sectors, no filesystem, so you must use mkfs to use the disk under minix. (You also can make DOS filesystems by dd ing the data from an empty dos disk: dd if=/dev/fd0 of=/dev/fd1 count=5 for 360 K ) It can handle all floppies except 1.44 M ( I don't know the gap_len). The program is NOT tested on AT's ! Cdiffs for fsck are also included, different for 1.3 and 1.5 You will find further Information in USAGE #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: format.c necio.c dma.c format1.s fsck.cdif.1.3 # fsck.cdif.1.5 # Wrapped by regn@sunny on Tue Jan 16 16:22:19 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'format.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'format.c'\" else echo shar: Extracting \"'format.c'\" \(8666 characters\) sed "s/^X//" >'format.c' <<'END_OF_FILE' X/* X * AUTHOR X * Copyright 1990 by Robert Regn. X * mail: regn@uniwue.uucp or regn@uniwue.unido.mcvax.uunet X * or ... uunet!mcvax!unido!uniwue!regn X * or ... uunet!mcsun!unido!uniwue!regn X * Permission granted to make derivative work, and to distribute X * for any reasons, provided that this notice remains intact, X * derivations are identified by author(s), and original works X * can be identified. X * No charge may be made other than resonable charges for reproduction. X * It may not be sold for profit. X * X * VERSION X * 1.0 15. 1. 1990 X * X * USAGE X * This program can be included to the standalone fsck. X * compile with -DBIOS X * link with fsck1.s fsck.c necio.c dma.c and format1.s X * change fsck to make a call format(drive) when X * 'f' is typed in the Minix boot menue X * Only useful with -DBIOS: X * with -DAUTO the program reads the model Byte and determines the X * drive type. X * with -DTWODRIVES you can choose the 2nd drive (not with AUTO ) X * X * without -DBIOS you get a version intended for Minix, but X * !!! It don't work !!!! X * I'm assuming that you cannot use DMA if interrupting is disabled X * X * PROBLEMS X * This program is slow. DOS - Format and the Format0 from aubrey McIntosh X * (running under DOS) are about 4 times faster. I don't know why. X * It seems that returning from DoSeek - immediate before the Head number X * is printed - comes very late - about 1 sec after you heard X * the head motion. X * X * FUTURE WORK NEEDED X * X * Recognize bad sectors !! X * Add command line switches for: X * 1) Drive type. X */ X X#define MT 0x80 /* The multi track bit command (PD7265 only) */ X#define MFM 0x40 X#define SK 0x20 X /*These are listed here as they are introduced X *on page 6-6 in the NEC literature. I don't see the pattern. X */ X#define ReadATrack 0x2 /* 00010 */ X#define Specify 0x3 /* 00011 */ X#define SenseDriveStatus 0x4 /* 00100 */ X#define WriteData 0x5 /* 00101 */ X#define ReadData 0x6 /* 00110 */ X#define RECALIBRATE 0x7 /* 00111 */ X#define SenseInterruptStatus 0x8 /* 01000 */ X#define WriteDeleted 0x9 /* 01001 */ X#define ReadId 0xA /* 01010 */ X#define FormatATrack 0xD /* 01101 */ X#define ReadDeleted 0xC /* 01100 */ X#define Seek 0xF /* 01111 */ X#define ScanEqual 0x11 /* 10001 */ X#define ScanLowerEqual 0x19 /* 11001 */ X#define ScanHighEqual 0x1D /* 11101 */ X#define FDC_SENSE 0x08 /* command the controller to tell its status */ X#define ST0_BITS 0xF8 /* check top 5 bits of seek status */ X#define SEEK_ST0 0x20 /* top 5 bits of ST0 for SEEK */ X X#ifdef STANDALONE /* This version should linked to fsck */ X#define BIOS X#endif X /* some globals */ Xunsigned gap_len = 0x2A; /* see format */ Xunsigned steps_p_cyl = 1; X X XRecalibrate(drive) Xunsigned drive; X{ X unsigned results[2]; X X fdc_out( RECALIBRATE ); X fdc_out( drive ); X seekStatus ("Recalibrate"); X X sense_int_status(results, 2 ); X if ((results[0] & ST0_BITS) != SEEK_ST0 ) X printf("recalibrate status %x\n", results[0]); X if ((results[1] & ST0_BITS) != 0 ) X printf("reg 1 error %x\n", results[1]); X} X X XDoSeek(Head, NCN, drive) Xunsigned Head; Xunsigned NCN; Xunsigned drive; X{ X unsigned results[2]; X fdc_out( Seek ); X fdc_out( (Head << 2) | drive ); X fdc_out( NCN * steps_p_cyl); X seekStatus ("DoSeek"); X X sense_int_status(results, 2 ); X if ((results[0] & ST0_BITS) != SEEK_ST0 ) X printf("seek status %x\n", results[0]); X if (results[1] != NCN * steps_p_cyl) X printf("reg 1 error %x\n", results[1]); X} X X Xsense_int_status(results, num ) Xunsigned *results; Xunsigned num; X{ X int r; X fdc_out(FDC_SENSE); /* probe FDC to make it return status */ X if ( r=fdc_results( results,num)) X printf("error results in senseintstate %d\n", r); X} X XDoFormatATrack(Head, Bytes, Sectors) Xunsigned Head; Xunsigned Bytes; Xunsigned Sectors; X{ X /*The DMA should be armed before this is called.*/ X unsigned res[7]; X int r; X X fdc_out( MFM + FormatATrack ); X fdc_out( Head <<2); X fdc_out( Bytes ); X fdc_out( Sectors ); X fdc_out( gap_len ); X fdc_out( 0 ); X X /*relinquish*/ X seekStatus("FormataTrack"); X if (r=fdc_results (res, 7)) X printf("error results in formatAT %d\n", r); X#ifdef DEBUG X printf(" %x %x %x Cyl: %d %d %d %d\n", res[0],res[1],res[2],res[3],res[4],res[5],res[6]); X#endif X} X X XseekStatus(proc_name) Xchar *proc_name; X{ X#ifdef BIOS X unsigned k = 40000; /* on an AT possible more */ X while (!( 128 & peek(0x40, 0x3E)) && --k > 0) X ; X if (k=0) X {printf("Timeout in %s %x\n", proc_name, peek(0x40, 0x3E)); X exit(-1); X } X exclude7(0x40, 0x3E); X#else X /* without BIOS i don't know how i can see when nec is ready with the job */ X sleep(1); /* nobody writes to 40:3E */ X#endif X} X X X X /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ X X#define MAX_SECTORS 18 X#define Bytes 2 /* 512 -- Note: this is ln2(size)-7 NOT size/128 */ X#define Sides 2 X#define OUT 1 X#define DMA2enable 0x8 X#define RST765 0x4 X Xint motor_mask = RST765| DMA2enable; X X /*This is byte packed -- 4 bytes long*/ Xstruct { X unsigned CH, RN; X } CHRN [MAX_SECTORS]; X Xnow_format(drive, Sectors, Tracks) Xunsigned drive; Xunsigned Sectors; Xunsigned Tracks; X{ X unsigned track; X unsigned sector; X unsigned side; X X for(sector = 0; sector < Sectors; sector++) X CHRN[sector].RN = (sector + 1) + (Bytes<<8); X MotorOn(drive); X Recalibrate(drive); X for(track = 0; track < Tracks; track++) X { X if (track % 9 == 8) X MotorOn(drive); /* I'm not shure if repeating is neccessary*/ X printf("\rCylinder %d ", track); X for(side = 0; side < Sides; side++) X { X DoSeek(side, track, drive); X printf("\b\b\b\b\b\bHead %d", side); X for(sector = 0; sector < Sectors; sector++) X CHRN[sector].CH = track + (side<<8); X X SetupDMA( OUT, (char *) CHRN, Sectors *sizeof(CHRN[0])); X DoFormatATrack(side, Bytes, Sectors); X } X } X MotorOff(drive); X} X X X#ifdef BIOS Xprintf(fmt, args) /* go to fsck print utils */ Xchar *fmt; /* printf from fsck is defined to printk !! */ X{ X unsigned i; X doprnt(fmt, &args); X#ifdef DEBUG X for (i=0; i < 40000; i++) X ; /*delay */ X#endif X} X X#ifdef AUTO Xformat(drive) Xint drive; X{ /* try to set the parameters correctly */ X /* Tracks: 40 or 80 X * Sectors: 9 or 15 X * gaplen: see minix floppy.c X * and if you will format a smaller size, also steps_p_cyl X */ X printf ("Modell - ID: %x: ", peek(0xF000, 0xFFFE)); X switch (peek(0xF000, 0xFFFE)) { X case 0xFF: X case 0xFE: /* PC or XT */ X case 0xFD: /* PC jr. */ X default: X gap_len = 0x2A; X steps_p_cyl = 1; X now_format(drive, 9, 40); X break; X case 0xFC: /* AT */ X case 0xF8: /* AT or PS/2 >30 ???? */ X gap_len = 0x1B; X steps_p_cyl = 1; X now_format(drive, 15, 80); X break; X case 0xFA: /* PS/2 30 */ X gap_len = 0x54; /* x54 got from Aubrey */ X steps_p_cyl = 1; X now_format(drive, 9, 80); X break; X case 0x0: /* Olivetti M24 */ X gap_len = 0x2A; X steps_p_cyl = 2; X now_format(drive, 9, 40); X break; X } X} X#else Xformat(drive) Xint drive; X{ X int type, fmt; X char ask[80]; X strcpy(ask, "\nPlease choice diskette format:"); X#ifdef TWODRIVES X drive = get_digit("\nPlease choice drive number 0 or 1: "); X if (drive > 1) X exit (-1); X#endif X type = get_digit("\nPlease enter drive type: 3: 360 K, 7: 720 K, 1: 1.2 M, 6: 720 K 3 1/2\" "); X switch (type) { X case 1: type = 12; /* my code for 1.2M drives is 12*/ X strcat(ask, " 1: 1.2 M,"); X case 7: strcat(ask, " 3: 360 K, 7: 720 K "); X fmt = get_digit(ask); X if (fmt == 1) fmt = 12; X break; X case 6: X case 3: fmt = type; X break; X default: printf("wrong value"); X exit(-1); X } X /* now set parameters */ X if (type > fmt && fmt ==3) X steps_p_cyl = 2; /* for 40 tracks on 80 track drive */ X else steps_p_cyl = 1; X if (type == 12) X gap_len = fmt == 12 ? 0x1B : 0x23; X else if (type == 6) X gap_len = 0x54; X else gap_len = 0x2A; X now_format(drive, fmt == 12 ? 15 : 9, fmt > 3 ? 80 : 40); X} X X Xget_digit(text) Xchar *text; X{ X /* Ask for a number and wait for it. */ X /* can possibly joined with get_partition in fsck.c */ X char chr; X int digit= -1; X while (1) { X printf(text); X while (1) { X chr = getc(); X printf("%c", chr); X if (chr == '\r') { X printf("\n"); X if (digit >= 0) X return digit; X else X break; X } else { X if (digit >= 0) break; X } X digit = chr - '0'; X } X digit = -1; X } X} X#endif /* AUTO */ X X#else Xmain() X{ /* suggested flags - if eventally the minix version works: */ X /* -h HD X * -l 360 K requested only on > 360K drives X * -q quad density requested only on AT's */ X motor_mask = RST765; X now_format( 0, 9, 40); /* use flags for set these values */ X printf("\n"); X} X#endif END_OF_FILE if test 8666 -ne `wc -c <'format.c'`; then echo shar: \"'format.c'\" unpacked with wrong size! fi # end of 'format.c' fi if test -f 'necio.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'necio.c'\" else echo shar: Extracting \"'necio.c'\" \(3733 characters\) sed "s/^X//" >'necio.c' <<'END_OF_FILE' X /* Page 6-4 of 1984 NEC data book. X * Primitive I/O support for the 765. X * X * This module should support anything that the NEC765 will do, X * and could be made into a separate module and submitted to a X * library. X */ X#define FDC_STATUS 0x3F4 /* floppy disk controller status register */ X#define FDC_DATA 0x3F5 /* floppy disk controller data register */ X#define MASTER 0x80 /* used to see who is master */ X#define DIRECTION 0x40 /* is FDC trying to read or write? */ X#define CTL_BUSY 0x10 /* used to see when controller is busy */ X#define CTL_ACCEPTING 0x80 /* bit pattern FDC gives when idle */ X#define MAX_RESULTS 8 /* max number of bytes controller returns */ X#define MAX_FDC_RETRY 100 /* max # times to try to output to FDC */ X#define RATE 0x3F7 /* not on XT */ X#define TRUE 0 X#define FALSE 1 X#define BYTE 0xFF X/*===========================================================================* X * fdc_out * X *===========================================================================*/ Xfdc_out(val) Xunsigned val; /* write this byte to floppy disk controller */ X{ X/* Output a byte to the controller. This is not entirely trivial, since you X * can only write to it when it is listening, and it decides when to listen. X */ X X int retries, r, rsv; X X retries = 25; X X /* It may take several tries to get the FDC to accept a command. */ X while (retries-- > 0) { X port_in(FDC_STATUS, &r); X rsv = r; X r &= (MASTER | DIRECTION); /* just look at bits 6 and 7 */ X if (r != CTL_ACCEPTING) continue; /* FDC is not listening */ X port_out(FDC_DATA, val); X return; X } X printf("fdc_out fails for %x, %x ", val, rsv); X} X X X/*===========================================================================* X * fdc_results * X *========================================================================*/ Xint fdc_results(field, max_results) Xunsigned field[]; Xunsigned max_results; X{ X/* Extract results from the controller after an operation. */ X X int i, j, status, ready; X X /* Loop, extracting bytes from FDC until it says it has no more. */ X for (i = 0; i <= max_results; i++) { X ready = FALSE; X for (j = 0; j < MAX_FDC_RETRY; j++) { X port_in(FDC_STATUS, &status); X X if (status & MASTER) { X ready = TRUE; X break; X } X } X if (ready == FALSE) printf("status %x ", status); X if (ready == FALSE) return(1); /* time out */ X X if ((status & CTL_BUSY) == 0) return(0); X if ((status & DIRECTION) == 0) return(2); X port_in(FDC_DATA, &status); X field[i] = status & BYTE; X } X X /* FDC is giving back too many results. */ X return(3); X} X X X /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ X /* X * This is board designer stuff, and the nec765 module (should be| X * is purely) applicable to the NEC765 and has no board designer X * modifications in it. X * X * I read the schematics in the IBM Technical Reference, X * pn 6025008, Revised Edition, July 1982. The various values X * agree with that schematic, the NEC 765 Data sheet, and floppy.c X * X */ X X X /* IBM-PC magic I/O addresses. X * Resolved with floppy.c, BIOS, and schematic. X */ X#define DOR 0x3F2 /* motor drive control bits */ X#define DMA2enable 0x8 X#define RST765 0x4 X#define ENABLEINT 0xC X Xextern motor_mask; X XMotorOn(drive) X{ X port_out( DOR, motor_mask ); X port_out( DOR, 1 << (drive +4) | motor_mask | drive ); X} X X XMotorOff(drive) X{ X port_out( DOR, 0 ); X} X X Xpanic( msg ) Xchar *msg; X{ X printf(msg); X exit(-1); X} END_OF_FILE if test 3733 -ne `wc -c <'necio.c'`; then echo shar: \"'necio.c'\" unpacked with wrong size! fi # end of 'necio.c' fi if test -f 'dma.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dma.c'\" else echo shar: Extracting \"'dma.c'\" \(1441 characters\) sed "s/^X//" >'dma.c' <<'END_OF_FILE' X#define DMAWRITE 0x4A X#define DMAREAD 0x46 X#define DMAStatus 0x0B X#define DMAINIT 0x0A X#define DMA_ADDR 0x004 /* port for low 16 bits of DMA address */ X#define DMA_TOP 0x081 /* port for top 4 bits of 20-bit DMA addr */ X#define DMA_COUNT 0x005 /* port for DMA count (count = bytes - 1) */ X#define BYTE 0xFF X XSetupDMA( dmaout , buffer, count) Xchar *buffer; X{ X unsigned low_addr, high_addr, top_addr, offset, segment; X long phys_bytes; X X segment = getdsegaddr(); /* compute address of the buffer */ X offset = (unsigned) buffer; X X phys_bytes = ((long) segment <<4) + offset; X low_addr = (int) (phys_bytes >> 0) & BYTE; X high_addr = (int) (phys_bytes >> 8) & BYTE; X top_addr = (int) (phys_bytes >> 16) & BYTE; X X if (0xFFFF - count <= (phys_bytes & 0xFFFF)) X panic ( "Can't set up DMA - crossing 64K boundaries." ); X /*For some reason Minix sends the status command to X *two DMA channels. So does the ROM bios listing. X *I don't comprehend why. I don't do it. The code works. X * X *What if I'm using DMA for some other device also? X */ X X port_out( DMAStatus, dmaout ? DMAWRITE : DMAREAD ); X port_out(DMA_ADDR, low_addr); /* output low-order 8 bits */ X port_out(DMA_ADDR, high_addr); /* output next 8 bits */ X port_out(DMA_TOP, top_addr); /* output highest 4 bits */ X port_out( DMA_COUNT, count & BYTE ); X port_out( DMA_COUNT, count >>8 ); X port_out( DMAINIT, 2 ); X} END_OF_FILE if test 1441 -ne `wc -c <'dma.c'`; then echo shar: \"'dma.c'\" unpacked with wrong size! fi # end of 'dma.c' fi if test -f 'format1.s' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'format1.s'\" else echo shar: Extracting \"'format1.s'\" \(225 characters\) sed "s/^X//" >'format1.s' <<'END_OF_FILE' X.define _getdsegaddr, _exclude7 X X_getdsegaddr: X mov ax, ds X ret X X X_exclude7: X push bp X mov bp,sp X push es X mov es,4(bp) X mov bx,6(bp) X seg es X movb al,(bx) X andb al,*127 X seg es X movb (bx),al X xorb ah,ah X pop es X pop bp X ret END_OF_FILE if test 225 -ne `wc -c <'format1.s'`; then echo shar: \"'format1.s'\" unpacked with wrong size! fi # end of 'format1.s' fi if test -f 'fsck.cdif.1.3' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fsck.cdif.1.3'\" else echo shar: Extracting \"'fsck.cdif.1.3'\" \(2312 characters\) sed "s/^X//" >'fsck.cdif.1.3' <<'END_OF_FILE' X*** /usr/src/minix/tools/fsck.c Wed Aug 30 09:58:43 1989 X--- fsck.c Thu Jan 11 17:17:08 1990 X*************** X*** 1814,1824 **** X prog = "fsck"; X printf("\n\n\n\n"); X for (;;) { X printf("\nHit key as follows:\n\n"); X printf(" = start MINIX (root file system in drive 0)\n"); X printf(" u start MINIX on PS/2 Model 30, U.S. keyboard (root file sys in drive 0)\n"); X printf(" d start MINIX on PS/2 Model 30, Dutch keyboard (root file sys in drive 0)\n"); X! printf(" f check the file system (first insert any file system diskette)\n"); X printf(" l check and list file system (first insert any file system diskette)\n"); X printf(" m make an (empty) file system (first insert blank, formatted diskette)\n"); X printf(" h check hard disk file system\n"); X--- 1814,1825 ---- X prog = "fsck"; X printf("\n\n\n\n"); X for (;;) { X printf("\nHit key as follows:\n\n"); X printf(" = start MINIX (root file system in drive 0)\n"); X printf(" u start MINIX on PS/2 Model 30, U.S. keyboard (root file sys in drive 0)\n"); X printf(" d start MINIX on PS/2 Model 30, Dutch keyboard (root file sys in drive 0)\n"); X! printf(" c check the file system (first insert any file system diskette)\n"); X! printf(" f format a diskette (first insert a new diskette)\n"); X printf(" l check and list file system (first insert any file system diskette)\n"); X printf(" m make an (empty) file system (first insert blank, formatted diskette)\n"); X printf(" h check hard disk file system\n"); X*************** X*** 1836,1841 **** X c = getc(); X command = c & 0xFF; X printf("%c\n", command); X part_offset = 0; X partition = 0; X drive = 0; X--- 1827,1832 ---- X*************** X*** 1854,1860 **** X break; X X X! case 'f': X printf("Checking diskette. %s\n", answer); X disktype(); /* init tracksiz & cylsiz */ X repair = 1; X--- 1844,1850 ---- X break; X X X! case 'c': X printf("Checking diskette. %s\n", answer); X disktype(); /* init tracksiz & cylsiz */ X repair = 1; X*************** X*** 1876,1879 **** X inode_ct = 255; X } X break; X! X--- 1866,1873 ---- X inode_ct = 255; X } X break; X! X! case 'f': X! format(0); X! exit(0); /* causes reiterate fsck */ X! END_OF_FILE if test 2312 -ne `wc -c <'fsck.cdif.1.3'`; then echo shar: \"'fsck.cdif.1.3'\" unpacked with wrong size! fi # end of 'fsck.cdif.1.3' fi if test -f 'fsck.cdif.1.5' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'fsck.cdif.1.5'\" else echo shar: Extracting \"'fsck.cdif.1.5'\" \(1814 characters\) sed "s/^X//" >'fsck.cdif.1.5' <<'END_OF_FILE' X*** ../1.5/tools/fsck.c Tue Jan 16 10:40:44 1990 X--- fsck.c Tue Jan 16 12:33:10 1990 X*************** X*** 1848,1854 **** X " (real size is from RAM image)" : ""); X printf(" p set limit on processor type (now %u)\n\n", X boot_parameters.bp_processor); X! printf(" f check the file system (first insert any file system diskette)\n"); X printf(" l check and list file system (first insert any file system diskette)\n"); X printf(" m make an (empty) file system (first insert blank, formatted diskette)\n"); X printf(" h check hard disk file system\n"); X--- 1848,1855 ---- X " (real size is from RAM image)" : ""); X printf(" p set limit on processor type (now %u)\n\n", X boot_parameters.bp_processor); X! printf(" c check the file system (first insert any file system diskette)\n"); X! printf(" f format a diskette (first insert a new diskette)\n"); X printf(" l check and list file system (first insert any file system diskette)\n"); X printf(" m make an (empty) file system (first insert blank, formatted diskette)\n"); X printf(" h check hard disk file system\n"); X*************** X*** 1873,1879 **** X break; X X X! case 'f': X printf("Checking diskette. %s\n", answer); X disktype(); /* init tracksiz & cylsiz */ X repair = 1; X--- 1874,1880 ---- X break; X X X! case 'c': X printf("Checking diskette. %s\n", answer); X disktype(); /* init tracksiz & cylsiz */ X repair = 1; X*************** X*** 1895,1901 **** X inode_ct = 255; X } X break; X! X case '=': X case 'u': X case 'd': X--- 1896,1906 ---- X inode_ct = 255; X } X break; X! X! case 'f': X! format(0); X! exit(0); /* causes reiterate fsck */ X! X case '=': X case 'u': X case 'd': END_OF_FILE if test 1814 -ne `wc -c <'fsck.cdif.1.5'`; then echo shar: \"'fsck.cdif.1.5'\" unpacked with wrong size! fi # end of 'fsck.cdif.1.5' fi echo shar: End of shell archive. exit 0