patch-2.1.17 linux/drivers/block/ataflop.c
Next file: linux/drivers/block/ez.c
Previous file: linux/drivers/block/amiflop.c
Back to the patch index
Back to the overall index
- Lines: 297
- Date:
Fri Dec 20 11:20:00 1996
- Orig file:
v2.1.16/linux/drivers/block/ataflop.c
- Orig date:
Wed Oct 16 10:48:07 1996
diff -u --recursive --new-file v2.1.16/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
@@ -49,6 +49,9 @@
* Andreas 95/12/12:
* - increase gap size at start of track for HD/ED disks
*
+ * Michael (MSch) 11/07/96:
+ * - implemented FDSETPRM and FDDEFPRM ioctl
+ *
* Things left to do:
* - Formatting
* - Maybe a better strategy for disk change detection (does anyone
@@ -70,12 +73,13 @@
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <asm/setup.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
+#include <asm/uaccess.h>
-#include <asm/bootinfo.h>
#include <asm/atafd.h>
#include <asm/atafdreg.h>
#include <asm/atarihw.h>
@@ -193,6 +197,21 @@
*/
#define MAX_DISK_SIZE 3280
+/*
+ * MSch: User-provided type information. 'drive' points to
+ * the respective entry of this array. Set by FDSETPRM ioctls.
+ */
+static struct atari_disk_type user_params[FD_MAX_UNITS];
+
+/*
+ * User-provided permanent type information. 'drive' points to
+ * the respective entry of this array. Set by FDDEFPRM ioctls,
+ * restored upon disk change by floppy_revalidate() if valid (as seen by
+ * default_params[].blocks > 0 - a bit in unit[].flags might be used for this?)
+ */
+static struct atari_disk_type default_params[FD_MAX_UNITS] = {
+ { NULL, 0, 0, 0, 0}, };
+
static int floppy_sizes[256];
static int floppy_blocksizes[256] = { 0, };
@@ -359,7 +378,7 @@
static void check_change( void );
static __inline__ void set_head_settle_flag( void );
static __inline__ int get_head_settle_flag( void );
-static void floppy_irq (int irq, struct pt_regs *fp, void *dummy);
+static void floppy_irq (int irq, void *dummy, struct pt_regs *fp);
static void fd_error( void );
static int do_format(kdev_t drive, struct atari_format_descr *desc);
static void do_fd_action( int drive );
@@ -572,7 +591,7 @@
static void (*FloppyIRQHandler)( int status ) = NULL;
-static void floppy_irq (int irq, struct pt_regs *fp, void *dummy)
+static void floppy_irq (int irq, void *dummy, struct pt_regs *fp)
{
unsigned char status;
void (*handler)( int );
@@ -1065,9 +1084,12 @@
!(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) {
if (Probing) {
if (SUDT > disk_type) {
+ if (SUDT[-1].blocks > ReqBlock) {
/* try another disk type */
SUDT--;
floppy_sizes[SelectedDrive] = SUDT->blocks >> 1;
+ } else
+ Probing = 0;
}
else {
if (SUD.flags & FTD_MSG)
@@ -1308,8 +1330,8 @@
/* Prevent "aliased" accesses. */
-static fd_ref[4] = { 0,0,0,0 };
-static fd_device[4] = { 0,0,0,0 };
+static int fd_ref[4] = { 0,0,0,0 };
+static int fd_device[4] = { 0,0,0,0 };
/*
* Current device number. Taken either from the block header or from the
@@ -1374,10 +1396,20 @@
if (test_bit (drive, &changed_floppies) || test_bit (drive, &fake_change)
|| unit[drive].disktype == 0)
{
+ if (UD.flags & FTD_MSG)
+ printk (KERN_ERR "floppy: clear format %p!\n", UDT);
BufferDrive = -1;
clear_bit (drive, &fake_change);
clear_bit (drive, &changed_floppies);
+ /*
+ * MSch: clearing geometry makes sense only for autoprobe formats,
+ * for 'permanent user-defined' parameter: restore default_params[]
+ * here if flagged valid!
+ */
+ if (default_params[drive].blocks == 0)
UDT = 0;
+ else
+ UDT = &default_params[drive];
}
return 0;
}
@@ -1532,13 +1564,14 @@
#define IOCTL_MODE_BIT 8
#define OPEN_WRITE_BIT 16
#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
-#define COPYIN(x) (copy_from_user( &(x), (void *) param, sizeof(x)))
- int drive, type, error;
+ int drive, type;
kdev_t device;
struct atari_format_descr fmt_desc;
struct atari_disk_type *dtp;
struct floppy_struct getprm;
+ int settype;
+ struct floppy_struct setprm;
device = inode->i_rdev;
switch (cmd) {
@@ -1556,6 +1589,9 @@
return -ENODEV;
type = minor2disktype[type].index;
dtp = &disk_type[type];
+ if (UD.flags & FTD_MSG)
+ printk (KERN_ERR "floppy%d: found dtp %p name %s!\n",
+ drive, dtp, dtp->name);
}
else {
if (!UDT)
@@ -1563,17 +1599,14 @@
else
dtp = UDT;
}
- error = verify_area(VERIFY_WRITE, (void *)param,
- sizeof(struct floppy_struct));
- if (error)
- return( error );
memset((void *)&getprm, 0, sizeof(getprm));
getprm.size = dtp->blocks;
getprm.sect = dtp->spt;
getprm.head = 2;
getprm.track = dtp->blocks/dtp->spt/2;
getprm.stretch = dtp->stretch;
- copy_to_user((void *)param, &getprm, sizeof(struct floppy_struct));
+ if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
+ return -EFAULT;
return 0;
}
if (!IOCTL_ALLOWED)
@@ -1581,7 +1614,112 @@
switch (cmd) {
case FDSETPRM:
case FDDEFPRM:
+ /*
+ * MSch 7/96: simple 'set geometry' case: just set the
+ * 'default' device params (minor == 0).
+ * Currently, the drive geometry is cleared after each
+ * disk change and subsequent revalidate()! simple
+ * implementation of FDDEFPRM: save geometry from a
+ * FDDEFPRM call and restore it in floppy_revalidate() !
+ */
+
+ /* get the parameters from user space */
+ if (fd_ref[drive] != 1 && fd_ref[drive] != -1)
+ return -EBUSY;
+ if (copy_from_user(&setprm, (void *) param, sizeof(setprm)))
+ return -EFAULT;
+ /*
+ * first of all: check for floppy change and revalidate,
+ * or the next access will revalidate - and clear UDT :-(
+ */
+
+ if (check_floppy_change(device))
+ floppy_revalidate(device);
+
+ if (UD.flags & FTD_MSG)
+ printk (KERN_INFO "floppy%d: setting size %d spt %d str %d!\n",
+ drive, setprm.size, setprm.sect, setprm.stretch);
+
+ /* what if type > 0 here? Overwrite specified entry ? */
+ if (type) {
+ /* refuse to re-set a predefined type for now */
+ redo_fd_request();
+ return -EINVAL;
+ }
+
+ /*
+ * type == 0: first look for a matching entry in the type list,
+ * and set the UD.disktype field to use the perdefined entry.
+ * TODO: add user-defined format to head of autoprobe list ?
+ * Useful to include the user-type for future autodetection!
+ */
+
+ for (settype = 0; settype < NUM_DISK_MINORS; settype++) {
+ int setidx = 0;
+ if (minor2disktype[settype].drive_types > DriveType) {
+ /* skip this one, invalid for drive ... */
+ continue;
+ }
+ setidx = minor2disktype[settype].index;
+ dtp = &disk_type[setidx];
+
+ /* found matching entry ?? */
+ if ( dtp->blocks == setprm.size
+ && dtp->spt == setprm.sect
+ && dtp->stretch == setprm.stretch ) {
+ if (UD.flags & FTD_MSG)
+ printk (KERN_INFO "floppy%d: setting %s %p!\n",
+ drive, dtp->name, dtp);
+ UDT = dtp;
+ floppy_sizes[drive] = UDT->blocks >> 1;
+
+ if (cmd == FDDEFPRM) {
+ /* save settings as permanent default type */
+ default_params[drive].name = dtp->name;
+ default_params[drive].spt = dtp->spt;
+ default_params[drive].blocks = dtp->blocks;
+ default_params[drive].fdc_speed = dtp->fdc_speed;
+ default_params[drive].stretch = dtp->stretch;
+ }
+
+ return 0;
+ }
+
+ }
+
+ /* no matching disk type found above - setting user_params */
+
+ if (cmd == FDDEFPRM) {
+ /* set permanent type */
+ dtp = &default_params[drive];
+ } else
+ /* set user type (reset by disk change!) */
+ dtp = &user_params[drive];
+
+ dtp->name = "user format";
+ dtp->blocks = setprm.size;
+ dtp->spt = setprm.sect;
+ if (setprm.sect > 14)
+ dtp->fdc_speed = 3;
+ else
+ dtp->fdc_speed = 0;
+ dtp->stretch = setprm.stretch;
+
+ if (UD.flags & FTD_MSG)
+ printk (KERN_INFO "floppy%d: blk %d spt %d str %d!\n",
+ drive, dtp->blocks, dtp->spt, dtp->stretch);
+
+ /* sanity check */
+ if (!dtp || setprm.track != dtp->blocks/dtp->spt/2
+ || setprm.head != 2) {
+ redo_fd_request();
return -EINVAL;
+ }
+
+ UDT = dtp;
+ floppy_sizes[drive] = UDT->blocks >> 1;
+
+ return 0;
case FDMSGON:
UD.flags |= FTD_MSG;
return 0;
@@ -1595,13 +1733,13 @@
case FDFMTTRK:
if (fd_ref[drive] != 1 && fd_ref[drive] != -1)
return -EBUSY;
- if ((error = verify_area(VERIFY_READ, (void *)param,
- sizeof(struct atari_format_descr) )))
- return( error );
- COPYIN( fmt_desc );
+ if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
+ return -EFAULT;
return do_format(device, &fmt_desc);
case FDCLRPRM:
UDT = NULL;
+ /* MSch: invalidate default_params */
+ default_params[drive].blocks = 0;
floppy_sizes[drive] = MAX_DISK_SIZE;
return invalidate_drive (device);
case FDFMTEND:
@@ -1761,7 +1899,7 @@
drive = MINOR (inode->i_rdev) & 3;
type = MINOR(inode->i_rdev) >> 2;
DPRINT(("fd_open: type=%d\n",type));
- if (type > NUM_DISK_MINORS)
+ if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
return -ENXIO;
old_dev = fd_device[drive];
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov