4611 lines · 117.0 KB · C
RawDownload
/* *  linux/drivers/block/floppy.c * *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 1993, 1994  Alain Knaff *  Copyright (C) 1998 Alan Cox */ /* * 02.12.91 - Changed to static variables to indicate need for reset * and recalibrate. This makes some things easier (output_byte reset * checking etc), and means less interrupt jumping in case of errors, * so the code is hopefully easier to understand. */ /* * This file is certainly a mess. I've tried my best to get it working, * but I don't like programming floppies, and I have only one anyway. * Urgel. I should check for more errors, and do more graceful error * recovery. Seems there are problems with several drives. I've tried to * correct them. No promises. */ /* * As with hd.c, all routines within this file can (and will) be called * by interrupts, so extreme caution is needed. A hardware interrupt * handler may not sleep, or a kernel panic will happen. Thus I cannot * call "floppy-on" directly, but have to set a special timer interrupt * etc. */ /* * 28.02.92 - made track-buffering routines, based on the routines written * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus. */ /* * Automatic floppy-detection and formatting written by Werner Almesberger * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with * the floppy-change signal detection. */ /* * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed * FDC data overrun bug, added some preliminary stuff for vertical * recording support. * * 1992/9/17: Added DMA allocation & DMA functions. -- hhb. * * TODO: Errors are still not counted properly. */ /* 1992/9/20 * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl) * modeled after the freeware MS-DOS program fdformat/88 V1.8 by * Christoph H. Hochst\"atter. * I have fixed the shift values to the ones I always use. Maybe a new * ioctl() should be created to be able to modify them. * There is a bug in the driver that makes it impossible to format a * floppy as the first thing after bootup. */ /* * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and * this helped the floppy driver as well. Much cleaner, and still seems to * work. */ /* 1994/6/24 --bbroad-- added the floppy table entries and made * minor modifications to allow 2.88 floppies to be run. */ /* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more * disk types. */ /* * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger * format bug fixes, but unfortunately some new bugs too... */ /* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write * errors to allow safe writing by specialized programs. */ /* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks * by defining bit 1 of the "stretch" parameter to mean put sectors on the * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's * drives are "upside-down"). */ /* * 1995/8/26 -- Andreas Busse -- added Mips support. */ /* * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent * features to asm/floppy.h. */ /* * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support */ /* * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting & * use of '0' for NULL. */ /* * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation * failures. */ /* * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives. */ /* * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24 * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were * being used to store jiffies, which are unsigned longs). */ /* * 2000/08/28 -- Arnaldo Carvalho de Melo <acme@conectiva.com.br> * - get rid of check_region * - s/suser/capable/ */ /* * 2001/08/26 -- Paul Gortmaker - fix insmod oops on machines with no * floppy controller (lingering task on list after module is gone... boom.) */ /* * 2002/02/07 -- Anton Altaparmakov - Fix io ports reservation to correct range * (0x3f2-0x3f5, 0x3f7). This fix is a bit of a hack but the proper fix * requires many non-obvious changes in arch dependent code. */ /* 2003/07/28 -- Daniele Bellucci <bellucda@tiscali.it>. * Better audit of register_blkdev. */ #undef  FLOPPY_SILENT_DCL_CLEAR #define REALLY_SLOW_IO #define DEBUGT 2 #define DPRINT(format, args...) \	pr_info("floppy%d: " format, current_drive, ##args) #define DCL_DEBUG		/* debug disk change line */#ifdef DCL_DEBUG#define debug_dcl(test, fmt, args...) \	do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0)#else#define debug_dcl(test, fmt, args...) \	do { if (0) DPRINT(fmt, ##args); } while (0)#endif /* do print messages for unexpected interrupts */static int print_unex = 1;#include <linux/module.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/timer.h>#include <linux/workqueue.h>#define FDPATCHES#include <linux/fdreg.h>#include <linux/fd.h>#include <linux/hdreg.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/bio.h>#include <linux/string.h>#include <linux/jiffies.h>#include <linux/fcntl.h>#include <linux/delay.h>#include <linux/mc146818rtc.h>	/* CMOS defines */#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/platform_device.h>#include <linux/mod_devicetable.h>#include <linux/mutex.h>#include <linux/io.h>#include <linux/uaccess.h>#include <linux/async.h> /* * PS/2 floppies have much slower step rates than regular floppies. * It's been recommended that take about 1/4 of the default speed * in some more extreme cases. */static DEFINE_MUTEX(floppy_mutex);static int slow_floppy; #include <asm/dma.h>#include <asm/irq.h> static int FLOPPY_IRQ = 6;static int FLOPPY_DMA = 2;static int can_use_virtual_dma = 2;/* ======= * can use virtual DMA: * 0 = use of virtual DMA disallowed by config * 1 = use of virtual DMA prescribed by config * 2 = no virtual DMA preference configured.  By default try hard DMA, * but fall back on virtual DMA when not enough memory available */ static int use_virtual_dma;/* ======= * use virtual DMA * 0 using hard DMA * 1 using virtual DMA * This variable is set to virtual when a DMA mem problem arises, and * reset back in floppy_grab_irq_and_dma. * It is not safe to reset it in other circumstances, because the floppy * driver may have several buffers in use at once, and we do currently not * record each buffers capabilities */ static DEFINE_SPINLOCK(floppy_lock); static unsigned short virtual_dma_port = 0x3f0;irqreturn_t floppy_interrupt(int irq, void *dev_id);static int set_dor(int fdc, char mask, char data); #define K_64	0x10000		/* 64KB */ /* the following is the mask of allowed drives. By default units 2 and * 3 of both floppy controllers are disabled, because switching on the * motor of these drives causes system hangs on some PCI computers. drive * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if * a drive is allowed. * * NOTE: This must come before we include the arch floppy header because *       some ports reference this variable from there. -DaveM */ static int allowed_drive_mask = 0x33; #include <asm/floppy.h> static int irqdma_allocated; #include <linux/blkdev.h>#include <linux/blkpg.h>#include <linux/cdrom.h>	/* for the compatibility eject ioctl */#include <linux/completion.h> static struct request *current_req;static void do_fd_request(struct request_queue *q);static int set_next_request(void); #ifndef fd_get_dma_residue#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)#endif /* Dma Memory related stuff */ #ifndef fd_dma_mem_free#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size))#endif #ifndef fd_dma_mem_alloc#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size))#endif static inline void fallback_on_nodma_alloc(char **addr, size_t l){#ifdef FLOPPY_CAN_FALLBACK_ON_NODMA	if (*addr)		return;		/* we have the memory */	if (can_use_virtual_dma != 2)		return;		/* no fallback allowed */	pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n");	*addr = (char *)nodma_mem_alloc(l);#else	return;#endif} /* End dma memory related stuff */ static unsigned long fake_change;static bool initialized; #define ITYPE(x)	(((x) >> 2) & 0x1f)#define TOMINOR(x)	((x & 3) | ((x & 4) << 5))#define UNIT(x)		((x) & 0x03)		/* drive on fdc */#define FDC(x)		(((x) & 0x04) >> 2)	/* fdc of drive */	/* reverse mapping from unit and fdc to drive */#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) #define DP	(&drive_params[current_drive])#define DRS	(&drive_state[current_drive])#define DRWE	(&write_errors[current_drive])#define FDCS	(&fdc_state[fdc]) #define UDP	(&drive_params[drive])#define UDRS	(&drive_state[drive])#define UDRWE	(&write_errors[drive])#define UFDCS	(&fdc_state[FDC(drive)]) #define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2)#define STRETCH(floppy)	((floppy)->stretch & FD_STRETCH) /* read/write */#define COMMAND		(raw_cmd->cmd[0])#define DR_SELECT	(raw_cmd->cmd[1])#define TRACK		(raw_cmd->cmd[2])#define HEAD		(raw_cmd->cmd[3])#define SECTOR		(raw_cmd->cmd[4])#define SIZECODE	(raw_cmd->cmd[5])#define SECT_PER_TRACK	(raw_cmd->cmd[6])#define GAP		(raw_cmd->cmd[7])#define SIZECODE2	(raw_cmd->cmd[8])#define NR_RW 9 /* format */#define F_SIZECODE	(raw_cmd->cmd[2])#define F_SECT_PER_TRACK (raw_cmd->cmd[3])#define F_GAP		(raw_cmd->cmd[4])#define F_FILL		(raw_cmd->cmd[5])#define NR_F 6 /* * Maximum disk size (in kilobytes). * This default is used whenever the current disk size is unknown. * [Now it is rather a minimum] */#define MAX_DISK_SIZE 4		/* 3984 */ /* * globals used by 'result()' */#define MAX_REPLIES 16static unsigned char reply_buffer[MAX_REPLIES];static int inr;		/* size of reply buffer, when called from interrupt */#define ST0		(reply_buffer[0])#define ST1		(reply_buffer[1])#define ST2		(reply_buffer[2])#define ST3		(reply_buffer[0])	/* result of GETSTATUS */#define R_TRACK		(reply_buffer[3])#define R_HEAD		(reply_buffer[4])#define R_SECTOR	(reply_buffer[5])#define R_SIZECODE	(reply_buffer[6]) #define SEL_DLY		(2 * HZ / 100) /* * this struct defines the different floppy drive types. */static struct {	struct floppy_drive_params params;	const char *name;	/* name printed while booting */} default_drive_params[] = {/* NOTE: the time values in jiffies should be in msec! CMOS drive type  |     Maximum data rate supported by drive type  |     |   Head load time, msec  |     |   |   Head unload time, msec (not used)  |     |   |   |     Step rate interval, usec  |     |   |   |     |       Time needed for spinup time (jiffies)  |     |   |   |     |       |      Timeout for spinning down (jiffies)  |     |   |   |     |       |      |   Spindown offset (where disk stops)  |     |   |   |     |       |      |   |     Select delay  |     |   |   |     |       |      |   |     |     RPS  |     |   |   |     |       |      |   |     |     |    Max number of tracks  |     |   |   |     |       |      |   |     |     |    |     Interrupt timeout  |     |   |   |     |       |      |   |     |     |    |     |   Max nonintlv. sectors  |     |   |   |     |       |      |   |     |     |    |     |   | -Max Errors- flags */{{0,  500, 16, 16, 8000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  80, 3*HZ, 20, {3,1,2,0,2}, 0,      0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" }, {{1,  300, 16, 16, 8000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  40, 3*HZ, 17, {3,1,2,0,2}, 0,      0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/ {{2,  500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6,  83, 3*HZ, 17, {3,1,2,0,2}, 0,      0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/ {{3,  250, 16, 16, 3000,    1*HZ, 3*HZ,  0, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,      0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/ {{4,  500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 20, {3,1,2,0,2}, 0,      0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/ {{5, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,      0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/ {{6, 1000, 15,  8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5,  83, 3*HZ, 40, {3,1,2,0,2}, 0,      0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*//*    |  --autodetected formats---    |      |      | *    read_track                      |      |    Name printed when booting *				      |     Native format *	            Frequency of disk change checks */}; static struct floppy_drive_params drive_params[N_DRIVE];static struct floppy_drive_struct drive_state[N_DRIVE];static struct floppy_write_errors write_errors[N_DRIVE];static struct timer_list motor_off_timer[N_DRIVE];static struct gendisk *disks[N_DRIVE];static struct block_device *opened_bdev[N_DRIVE];static DEFINE_MUTEX(open_lock);static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;static int fdc_queue; /* * This struct defines the different floppy types. * * Bit 0 of 'stretch' tells if the tracks need to be doubled for some * types (e.g. 360kB diskette in 1.2MB drive, etc.).  Bit 1 of 'stretch' * tells if the disk is in Commodore 1581 format, which means side 0 sectors * are located on side 1 of the disk but with a side 0 ID, and vice-versa. * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical * side 0 is on physical side 0 (but with the misnamed sector IDs). * 'stretch' should probably be renamed to something more general, like * 'options'. * * Bits 2 through 9 of 'stretch' tell the number of the first sector. * The LSB (bit 2) is flipped. For most disks, the first sector * is 1 (represented by 0x00<<2).  For some CP/M and music sampler * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2). * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2). * * Other parameters should be self-explanatory (see also setfdprm(8)). *//*	    Size	     |  Sectors per track	     |  | Head	     |  | |  Tracks	     |  | |  | Stretch	     |  | |  | |  Gap 1 size	     |  | |  | |    |  Data rate, | 0x40 for perp	     |  | |  | |    |    |  Spec1 (stepping rate, head unload	     |  | |  | |    |    |    |    /fmt gap (gap2) */static struct floppy_struct floppy_type[32] = {	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL    },	/*  0 no testing    */	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360"  }, /*  1 360KB PC      */	{ 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" },	/*  2 1.2MB AT      */	{  720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360"  },	/*  3 360KB SS 3.5" */	{ 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720"  },	/*  4 720KB 3.5"    */	{  720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360"  },	/*  5 360KB AT      */	{ 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720"  },	/*  6 720KB AT      */	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" },	/*  7 1.44MB 3.5"   */	{ 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" },	/*  8 2.88MB 3.5"   */	{ 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" },	/*  9 3.12MB 3.5"   */ 	{ 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25"  */	{ 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5"   */	{  820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410"  },	/* 12 410KB 5.25"   */	{ 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820"  },	/* 13 820KB 3.5"    */	{ 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" },	/* 14 1.48MB 5.25"  */	{ 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" },	/* 15 1.72MB 3.5"   */	{  840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420"  },	/* 16 420KB 5.25"   */	{ 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830"  },	/* 17 830KB 3.5"    */	{ 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" },	/* 18 1.49MB 5.25"  */	{ 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5"  */ 	{ 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880"  }, /* 20 880KB 5.25"   */	{ 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5"   */	{ 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5"   */	{ 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25"   */	{ 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5"   */	{ 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5"   */	{ 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5"   */	{ 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5"   */	{ 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5"   */	{ 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5"   */ 	{ 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800"  },	/* 30 800KB 3.5"    */	{ 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5"    */}; #define SECTSIZE (_FD_SECTSIZE(*floppy)) /* Auto-detection: Disk type used until the next media change occurs. */static struct floppy_struct *current_type[N_DRIVE]; /* * User-provided type information. current_type points to * the respective entry of this array. */static struct floppy_struct user_params[N_DRIVE]; static sector_t floppy_sizes[256]; static char floppy_device_name[] = "floppy"; 

Lines 1–500 of 4611.