The files /dev/f* and /dev/rf* are entries for the floppy-disk driver fd. Each entry is assigned major device number 4, is accessed as a block-special device, and has a corresponding character-special device entry. fd handles up to four 5.25-inch floppy-disk drives, each in one of several formats.
The least-significant four bits of an entry's minor device number identify the type of drive. The next least- significant two bits identify the drive.
The following table summarizes the name, minor device number, sectors per track, partition sector size, characteristics, and addressing method for each device entry of floppy-disk drive 0.
_9 _s_e_c_t_o_r_s_/_t_r_a_c_k ffqqaa00 13 9 1440 DSQD cylinder (3.25 inch -- 720K) ff99aa00 12 9 720 DSDD cylinder (5.25 inch -- 360K)
_1_5 _s_e_c_t_o_r_s_/_t_r_a_c_k ffhhaa00 14 15 2400 DSHD cylinder (5.25 inch -- 1.2MB)
_1_8 _s_e_c_t_o_r_s_/_t_r_a_c_k ffvvaa00 15 18 2880 DSHD cylinder (3.5 inch -- 1.44MB
Prefixing an r to a device name given above gives the name of the corresponding character-device entry. Corresponding device entries for drives 1, 2, and 3 have minor numbers with offsets of 16, 32, and 48 from the minor numbers given above, and have 1, 2, or 3 in place of 0 in the names given above.
For device entries whose minor number's fourth least- significant bit is zero (minor numbers 0 through 7 for drive 0), the driver uses surface addressing rather than cylinder addressing. This means that it increments tracks before heads when computing sector addresses and the first surface is used completely before the second surface is accessed. For devices whose minor number's fourth least significant bit is 1 (minor numbers 8 through 15 for drive 0), the driver uses cylinder addressing.
For a floppy disk to be accessible from the COHERENT system, a device file must be present in directory /dev with the appropriate type, major and minor device numbers, and permissions. The command mknod creates a special file for a device.
The following table gives the all floppy-disk devices that COHERENT recognizes, by minor number. Note that some specialized devices skip the first cylinder on the disk, to support some third-party program that requires this feature:
_M_i_n_o_r _N_u_m_b_e_r _D_r_i_v_e _D_i_a_m_e_t_e_r _D_e_n_s_i_t_y _C_y_l_i_n_d_e_r_s 0 0 Both Any 1-39/79 1 0 Both Any 0-39/79 4 0 5.25'' 360KB 1-39 5 0 3.5'' 720KB 1-79 6 0 5.25'' 1.2MB 1-79 7 0 3.5'' 1.44MB 1-79 12 0 5.25'' 360KB 0-39 13 0 3.5'' 720KB 0-79 14 0 5.25'' 1.2MB 0-79 15 0 3.5'' 1.44MB 0-79 16 1 Both Any 1-39/79 17 1 Both Any 0-39/79 20 1 5.25'' 360KB 1-39 21 1 3.5'' 720KB 1-79 22 1 5.25'' 1.2MB 1-79 23 1 3.5'' 1.44MB 1-79 28 1 5.25'' 360KB 0-39 29 1 3.5'' 720KB 0-79 30 1 5.25'' 1.2MB 0-79 31 1 3.5'' 1.44MB 0-79
#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h>
#define BLOCK 512
struct FDATA {
int fd_size; /* Blocks per diskette */
int fd_nhds; /* Heads per drive */
int fd_trks; /* Tracks per side */
int fd_offs; /* Sector base */
int fd_nspt; /* Sectors per track */
char fd_GPL[4]; /* Controller gap param (indexed by rate) */
char fd_N; /* Controller size param */
char fd_FGPL; /* Format gap length */
};
/* Parameters for each kind of format */
struct FDATA fdata [] = {
/* 8 sectors per track, surface by surface seek. */
{ 320, 1, 40, 0, 8, { 0x00, 0x20, 0x20 }, 2, 0x58 }, /* Single sided */
{ 640, 2, 40, 0, 8, { 0x00, 0x20, 0x20 }, 2, 0x58 }, /* Double sided */
{ 1280, 2, 80, 0, 8, { 0x00, 0x20, 0x20 }, 2, 0x58 }, /* Quad density */
/* 9 sectors per track, surface by surface seek. */
{ 360, 1, 40, 0, 9, { 0x00, 0x20, 0x20 }, 2, 0x50 }, /* Single sided */
{ 720, 2, 40, 0, 9, { 0x00, 0x20, 0x20 }, 2, 0x50 }, /* Double sided */
{ 1440, 2, 80, 0, 9, { 0x00, 0x20, 0x20 }, 2, 0x50 }, /* Quad density */
/* 15 sectors per track, surface by surface seek. */
{ 2400, 2, 80, 0, 15, { 0x1B, 0x00, 0x00 }, 2, 0x54 }, /* High capacity */
/* 18 sectors per track, surface by surface seek. */
{ 2880, 2, 80, 0, 18, { 0x1B, 0x00, 0x00 }, 2, 0x6C }/* 1.44 3.5" */
};
#define funit(x) (minor(x) >> 4) /* Unit/drive number */ #define fkind(x) (minor(x) & 0x7) /* Kind of format */
static int ctrl;
int main(argc, argv)
int argc; char **argv;
{
int size;
struct stat sbuf;
struct FDATA *fdp;
if (argc!=2) {
fprintf(stderr, "usage : %s /dev/fd...\n",argv[0]);
exit(EXIT_FAILURE);
}
if (strcmp(argv[1], "conv")==0) {
/*special case*/
size = getchar() + getchar() * 256;
printf("%ld\n", (long)((long)size * (long)512) );
return (EXIT_SUCCESS);
}
if (ctrl = stat(argv[1], &sbuf)) {
fprintf (stderr,"%s : error stating %s.\n", argv[0], argv[1]);
exit(EXIT_FAILURE);
}
fdp = & fdata [fkind (sbuf.st_rdev)];
printf("%ld\n", (long)((long)fdp->fd_size * (long)512) );
return (EXIT_SUCCESS);
}
A fd assumes that the disk is formatted with eight, nine, 15, or 18 sectors of 512 bytes each per track, depending upon the //ddeevv entry. Cylinder addressing is the norm for COHERENT.
A Programs that use the raw device interface must read whole sectors into buffers that do not straddle DMA boundaries.