blob: 652668d76a8a56786c95875f5ee49fe3a0997e62 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/block/floppy.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 * Copyright (C) 1993, 1994 Alain Knaff
6 * Copyright (C) 1998 Alan Cox
7 */
Jesper Juhl06f748c2007-10-16 23:30:57 -07008
Linus Torvalds1da177e2005-04-16 15:20:36 -07009/*
10 * 02.12.91 - Changed to static variables to indicate need for reset
11 * and recalibrate. This makes some things easier (output_byte reset
12 * checking etc), and means less interrupt jumping in case of errors,
13 * so the code is hopefully easier to understand.
14 */
15
16/*
17 * This file is certainly a mess. I've tried my best to get it working,
18 * but I don't like programming floppies, and I have only one anyway.
19 * Urgel. I should check for more errors, and do more graceful error
20 * recovery. Seems there are problems with several drives. I've tried to
21 * correct them. No promises.
22 */
23
24/*
25 * As with hd.c, all routines within this file can (and will) be called
26 * by interrupts, so extreme caution is needed. A hardware interrupt
27 * handler may not sleep, or a kernel panic will happen. Thus I cannot
28 * call "floppy-on" directly, but have to set a special timer interrupt
29 * etc.
30 */
31
32/*
33 * 28.02.92 - made track-buffering routines, based on the routines written
34 * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus.
35 */
36
37/*
38 * Automatic floppy-detection and formatting written by Werner Almesberger
39 * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with
40 * the floppy-change signal detection.
41 */
42
43/*
44 * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed
45 * FDC data overrun bug, added some preliminary stuff for vertical
46 * recording support.
47 *
48 * 1992/9/17: Added DMA allocation & DMA functions. -- hhb.
49 *
50 * TODO: Errors are still not counted properly.
51 */
52
53/* 1992/9/20
54 * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl)
55 * modeled after the freeware MS-DOS program fdformat/88 V1.8 by
56 * Christoph H. Hochst\"atter.
57 * I have fixed the shift values to the ones I always use. Maybe a new
58 * ioctl() should be created to be able to modify them.
59 * There is a bug in the driver that makes it impossible to format a
60 * floppy as the first thing after bootup.
61 */
62
63/*
64 * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and
65 * this helped the floppy driver as well. Much cleaner, and still seems to
66 * work.
67 */
68
69/* 1994/6/24 --bbroad-- added the floppy table entries and made
70 * minor modifications to allow 2.88 floppies to be run.
71 */
72
73/* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more
74 * disk types.
75 */
76
77/*
78 * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger
79 * format bug fixes, but unfortunately some new bugs too...
80 */
81
82/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write
83 * errors to allow safe writing by specialized programs.
84 */
85
86/* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks
87 * by defining bit 1 of the "stretch" parameter to mean put sectors on the
88 * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's
89 * drives are "upside-down").
90 */
91
92/*
93 * 1995/8/26 -- Andreas Busse -- added Mips support.
94 */
95
96/*
97 * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent
98 * features to asm/floppy.h.
99 */
100
101/*
James Nelsonb88b0982005-11-08 16:52:12 +0100102 * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
103 */
104
105/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of
107 * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting &
108 * use of '0' for NULL.
109 */
110
111/*
112 * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation
113 * failures.
114 */
115
116/*
117 * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives.
118 */
119
120/*
121 * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24
122 * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were
123 * being used to store jiffies, which are unsigned longs).
124 */
125
126/*
127 * 2000/08/28 -- Arnaldo Carvalho de Melo <acme@conectiva.com.br>
128 * - get rid of check_region
129 * - s/suser/capable/
130 */
131
132/*
133 * 2001/08/26 -- Paul Gortmaker - fix insmod oops on machines with no
134 * floppy controller (lingering task on list after module is gone... boom.)
135 */
136
137/*
138 * 2002/02/07 -- Anton Altaparmakov - Fix io ports reservation to correct range
139 * (0x3f2-0x3f5, 0x3f7). This fix is a bit of a hack but the proper fix
140 * requires many non-obvious changes in arch dependent code.
141 */
142
143/* 2003/07/28 -- Daniele Bellucci <bellucda@tiscali.it>.
144 * Better audit of register_blkdev.
145 */
146
147#define FLOPPY_SANITY_CHECK
148#undef FLOPPY_SILENT_DCL_CLEAR
149
150#define REALLY_SLOW_IO
151
152#define DEBUGT 2
Joe Perches48c8cee2010-03-10 15:20:45 -0800153#define DCL_DEBUG /* debug disk change line */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
155/* do print messages for unexpected interrupts */
156static int print_unex = 1;
157#include <linux/module.h>
158#include <linux/sched.h>
159#include <linux/fs.h>
160#include <linux/kernel.h>
161#include <linux/timer.h>
162#include <linux/workqueue.h>
163#define FDPATCHES
164#include <linux/fdreg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165#include <linux/fd.h>
166#include <linux/hdreg.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167#include <linux/errno.h>
168#include <linux/slab.h>
169#include <linux/mm.h>
170#include <linux/bio.h>
171#include <linux/string.h>
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -0800172#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173#include <linux/fcntl.h>
174#include <linux/delay.h>
175#include <linux/mc146818rtc.h> /* CMOS defines */
176#include <linux/ioport.h>
177#include <linux/interrupt.h>
178#include <linux/init.h>
Russell Kingd052d1b2005-10-29 19:07:23 +0100179#include <linux/platform_device.h>
Scott James Remnant83f9ef42009-04-02 16:56:47 -0700180#include <linux/mod_devicetable.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181#include <linux/buffer_head.h> /* for invalidate_buffers() */
Jes Sorensenb1c82b52006-03-23 03:00:26 -0800182#include <linux/mutex.h>
Joe Perchesd4937542010-03-10 15:20:44 -0800183#include <linux/io.h>
184#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
186/*
187 * PS/2 floppies have much slower step rates than regular floppies.
188 * It's been recommended that take about 1/4 of the default speed
189 * in some more extreme cases.
190 */
191static int slow_floppy;
192
193#include <asm/dma.h>
194#include <asm/irq.h>
195#include <asm/system.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197static int FLOPPY_IRQ = 6;
198static int FLOPPY_DMA = 2;
199static int can_use_virtual_dma = 2;
200/* =======
201 * can use virtual DMA:
202 * 0 = use of virtual DMA disallowed by config
203 * 1 = use of virtual DMA prescribed by config
204 * 2 = no virtual DMA preference configured. By default try hard DMA,
205 * but fall back on virtual DMA when not enough memory available
206 */
207
208static int use_virtual_dma;
209/* =======
210 * use virtual DMA
211 * 0 using hard DMA
212 * 1 using virtual DMA
213 * This variable is set to virtual when a DMA mem problem arises, and
214 * reset back in floppy_grab_irq_and_dma.
215 * It is not safe to reset it in other circumstances, because the floppy
216 * driver may have several buffers in use at once, and we do currently not
217 * record each buffers capabilities
218 */
219
220static DEFINE_SPINLOCK(floppy_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
222static unsigned short virtual_dma_port = 0x3f0;
David Howells7d12e782006-10-05 14:55:46 +0100223irqreturn_t floppy_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224static int set_dor(int fdc, char mask, char data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226#define K_64 0x10000 /* 64KB */
227
228/* the following is the mask of allowed drives. By default units 2 and
229 * 3 of both floppy controllers are disabled, because switching on the
230 * motor of these drives causes system hangs on some PCI computers. drive
231 * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
232 * a drive is allowed.
233 *
234 * NOTE: This must come before we include the arch floppy header because
235 * some ports reference this variable from there. -DaveM
236 */
237
238static int allowed_drive_mask = 0x33;
239
240#include <asm/floppy.h>
241
242static int irqdma_allocated;
243
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244#define DEVICE_NAME "floppy"
245
246#include <linux/blkdev.h>
247#include <linux/blkpg.h>
248#include <linux/cdrom.h> /* for the compatibility eject ioctl */
249#include <linux/completion.h>
250
251static struct request *current_req;
252static struct request_queue *floppy_queue;
Joe Perches48c8cee2010-03-10 15:20:45 -0800253static void do_fd_request(struct request_queue *q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255#ifndef fd_get_dma_residue
256#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
257#endif
258
259/* Dma Memory related stuff */
260
261#ifndef fd_dma_mem_free
262#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
263#endif
264
265#ifndef fd_dma_mem_alloc
Joe Perches48c8cee2010-03-10 15:20:45 -0800266#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267#endif
268
269static inline void fallback_on_nodma_alloc(char **addr, size_t l)
270{
271#ifdef FLOPPY_CAN_FALLBACK_ON_NODMA
272 if (*addr)
273 return; /* we have the memory */
274 if (can_use_virtual_dma != 2)
275 return; /* no fallback allowed */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700276 printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 *addr = (char *)nodma_mem_alloc(l);
278#else
279 return;
280#endif
281}
282
283/* End dma memory related stuff */
284
285static unsigned long fake_change;
286static int initialising = 1;
287
Joe Perches48c8cee2010-03-10 15:20:45 -0800288#define ITYPE(x) (((x) >> 2) & 0x1f)
289#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
290#define UNIT(x) ((x) & 0x03) /* drive on fdc */
291#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700292 /* reverse mapping from unit and fdc to drive */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Joe Perches48c8cee2010-03-10 15:20:45 -0800295#define DP (&drive_params[current_drive])
296#define DRS (&drive_state[current_drive])
297#define DRWE (&write_errors[current_drive])
298#define FDCS (&fdc_state[fdc])
299#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags)
300#define SETF(x) set_bit(x##_BIT, &DRS->flags)
301#define TESTF(x) test_bit(x##_BIT, &DRS->flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Joe Perches48c8cee2010-03-10 15:20:45 -0800303#define UDP (&drive_params[drive])
304#define UDRS (&drive_state[drive])
305#define UDRWE (&write_errors[drive])
306#define UFDCS (&fdc_state[FDC(drive)])
307#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags)
308#define USETF(x) set_bit(x##_BIT, &UDRS->flags)
309#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Joe Perches48c8cee2010-03-10 15:20:45 -0800311#define DPRINT(format, args...) \
312 printk(DEVICE_NAME "%d: " format, current_drive, ##args)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
Joe Perches48c8cee2010-03-10 15:20:45 -0800314#define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2)
315#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
316
317#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318
319/* read/write */
Joe Perches48c8cee2010-03-10 15:20:45 -0800320#define COMMAND (raw_cmd->cmd[0])
321#define DR_SELECT (raw_cmd->cmd[1])
322#define TRACK (raw_cmd->cmd[2])
323#define HEAD (raw_cmd->cmd[3])
324#define SECTOR (raw_cmd->cmd[4])
325#define SIZECODE (raw_cmd->cmd[5])
326#define SECT_PER_TRACK (raw_cmd->cmd[6])
327#define GAP (raw_cmd->cmd[7])
328#define SIZECODE2 (raw_cmd->cmd[8])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329#define NR_RW 9
330
331/* format */
Joe Perches48c8cee2010-03-10 15:20:45 -0800332#define F_SIZECODE (raw_cmd->cmd[2])
333#define F_SECT_PER_TRACK (raw_cmd->cmd[3])
334#define F_GAP (raw_cmd->cmd[4])
335#define F_FILL (raw_cmd->cmd[5])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336#define NR_F 6
337
338/*
Joe Perches48c8cee2010-03-10 15:20:45 -0800339 * Maximum disk size (in kilobytes).
340 * This default is used whenever the current disk size is unknown.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 * [Now it is rather a minimum]
342 */
343#define MAX_DISK_SIZE 4 /* 3984 */
344
345/*
346 * globals used by 'result()'
347 */
348#define MAX_REPLIES 16
349static unsigned char reply_buffer[MAX_REPLIES];
350static int inr; /* size of reply buffer, when called from interrupt */
Joe Perches48c8cee2010-03-10 15:20:45 -0800351#define ST0 (reply_buffer[0])
352#define ST1 (reply_buffer[1])
353#define ST2 (reply_buffer[2])
354#define ST3 (reply_buffer[0]) /* result of GETSTATUS */
355#define R_TRACK (reply_buffer[3])
356#define R_HEAD (reply_buffer[4])
357#define R_SECTOR (reply_buffer[5])
358#define R_SIZECODE (reply_buffer[6])
359
360#define SEL_DLY (2 * HZ / 100)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
362/*
363 * this struct defines the different floppy drive types.
364 */
365static struct {
366 struct floppy_drive_params params;
367 const char *name; /* name printed while booting */
368} default_drive_params[] = {
369/* NOTE: the time values in jiffies should be in msec!
370 CMOS drive type
371 | Maximum data rate supported by drive type
372 | | Head load time, msec
373 | | | Head unload time, msec (not used)
374 | | | | Step rate interval, usec
375 | | | | | Time needed for spinup time (jiffies)
376 | | | | | | Timeout for spinning down (jiffies)
377 | | | | | | | Spindown offset (where disk stops)
378 | | | | | | | | Select delay
379 | | | | | | | | | RPS
380 | | | | | | | | | | Max number of tracks
381 | | | | | | | | | | | Interrupt timeout
382 | | | | | | | | | | | | Max nonintlv. sectors
383 | | | | | | | | | | | | | -Max Errors- flags */
384{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0,
385 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
386
387{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0,
388 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
389
390{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0,
391 0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
392
393{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
394 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
395
396{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
397 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
398
399{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
400 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
401
402{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
403 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
404/* | --autodetected formats--- | | |
405 * read_track | | Name printed when booting
406 * | Native format
407 * Frequency of disk change checks */
408};
409
410static struct floppy_drive_params drive_params[N_DRIVE];
411static struct floppy_drive_struct drive_state[N_DRIVE];
412static struct floppy_write_errors write_errors[N_DRIVE];
413static struct timer_list motor_off_timer[N_DRIVE];
414static struct gendisk *disks[N_DRIVE];
415static struct block_device *opened_bdev[N_DRIVE];
Jes Sorensenb1c82b52006-03-23 03:00:26 -0800416static DEFINE_MUTEX(open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
418
419/*
420 * This struct defines the different floppy types.
421 *
422 * Bit 0 of 'stretch' tells if the tracks need to be doubled for some
423 * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch'
424 * tells if the disk is in Commodore 1581 format, which means side 0 sectors
425 * are located on side 1 of the disk but with a side 0 ID, and vice-versa.
426 * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the
427 * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
428 * side 0 is on physical side 0 (but with the misnamed sector IDs).
429 * 'stretch' should probably be renamed to something more general, like
Keith Wansbrough9e491842008-09-22 14:57:17 -0700430 * 'options'.
431 *
432 * Bits 2 through 9 of 'stretch' tell the number of the first sector.
433 * The LSB (bit 2) is flipped. For most disks, the first sector
434 * is 1 (represented by 0x00<<2). For some CP/M and music sampler
435 * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2).
436 * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2).
437 *
438 * Other parameters should be self-explanatory (see also setfdprm(8)).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 */
440/*
441 Size
442 | Sectors per track
443 | | Head
444 | | | Tracks
445 | | | | Stretch
446 | | | | | Gap 1 size
447 | | | | | | Data rate, | 0x40 for perp
448 | | | | | | | Spec1 (stepping rate, head unload
449 | | | | | | | | /fmt gap (gap2) */
450static struct floppy_struct floppy_type[32] = {
451 { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */
452 { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */
453 { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */
454 { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */
455 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */
456 { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */
457 { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */
458 { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */
459 { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */
460 { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */
461
462 { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */
463 { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */
464 { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */
465 { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */
466 { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */
467 { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */
468 { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */
469 { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */
470 { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */
471 { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */
472
473 { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
474 { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */
475 { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */
476 { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */
477 { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */
478 { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */
479 { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
480 { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
481 { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
485 { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
486};
487
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488#define SECTSIZE (_FD_SECTSIZE(*floppy))
489
490/* Auto-detection: Disk type used until the next media change occurs. */
491static struct floppy_struct *current_type[N_DRIVE];
492
493/*
494 * User-provided type information. current_type points to
495 * the respective entry of this array.
496 */
497static struct floppy_struct user_params[N_DRIVE];
498
499static sector_t floppy_sizes[256];
500
Hannes Reinecke94fd0db2005-07-15 10:09:25 +0200501static char floppy_device_name[] = "floppy";
502
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503/*
504 * The driver is trying to determine the correct media format
505 * while probing is set. rw_interrupt() clears it after a
506 * successful access.
507 */
508static int probing;
509
510/* Synchronization of FDC access. */
Joe Perches48c8cee2010-03-10 15:20:45 -0800511#define FD_COMMAND_NONE -1
512#define FD_COMMAND_ERROR 2
513#define FD_COMMAND_OKAY 3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515static volatile int command_status = FD_COMMAND_NONE;
516static unsigned long fdc_busy;
517static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
518static DECLARE_WAIT_QUEUE_HEAD(command_done);
519
520#define NO_SIGNAL (!interruptible || !signal_pending(current))
Joe Perches48c8cee2010-03-10 15:20:45 -0800521#define CALL(x) if ((x) == -EINTR) return -EINTR
522#define ECALL(x) if ((ret = (x))) return ret;
523#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
524#define WAIT(x) _WAIT((x),interruptible)
525#define IWAIT(x) _WAIT((x),1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
527/* Errors during formatting are counted here. */
528static int format_errors;
529
530/* Format request descriptor. */
531static struct format_descr format_req;
532
533/*
534 * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
535 * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
536 * H is head unload time (1=16ms, 2=32ms, etc)
537 */
538
539/*
540 * Track buffer
541 * Because these are written to by the DMA controller, they must
542 * not contain a 64k byte boundary crossing, or data will be
543 * corrupted/lost.
544 */
545static char *floppy_track_buffer;
546static int max_buffer_sectors;
547
548static int *errors;
Jesper Juhl06f748c2007-10-16 23:30:57 -0700549typedef void (*done_f)(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550static struct cont_t {
Joe Perches48c8cee2010-03-10 15:20:45 -0800551 void (*interrupt)(void);
552 /* this is called after the interrupt of the
553 * main command */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700554 void (*redo)(void); /* this is called to retry the operation */
555 void (*error)(void); /* this is called to tally an error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 done_f done; /* this is called to say if the operation has
557 * succeeded/failed */
558} *cont;
559
560static void floppy_ready(void);
561static void floppy_start(void);
562static void process_fd_request(void);
563static void recalibrate_floppy(void);
564static void floppy_shutdown(unsigned long);
565
Philippe De Muyter5a74db02009-02-18 14:48:36 -0800566static int floppy_request_regions(int);
567static void floppy_release_regions(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568static int floppy_grab_irq_and_dma(void);
569static void floppy_release_irq_and_dma(void);
570
571/*
572 * The "reset" variable should be tested whenever an interrupt is scheduled,
573 * after the commands have been sent. This is to ensure that the driver doesn't
574 * get wedged when the interrupt doesn't come because of a failed command.
575 * reset doesn't need to be tested before sending commands, because
576 * output_byte is automatically disabled when reset is set.
577 */
578#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
579static void reset_fdc(void);
580
581/*
582 * These are global variables, as that's the easiest way to give
583 * information to interrupts. They are the data used for the current
584 * request.
585 */
Joe Perches48c8cee2010-03-10 15:20:45 -0800586#define NO_TRACK -1
587#define NEED_1_RECAL -2
588#define NEED_2_RECAL -3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590static int usage_count;
591
592/* buffer related variables */
593static int buffer_track = -1;
594static int buffer_drive = -1;
595static int buffer_min = -1;
596static int buffer_max = -1;
597
598/* fdc related variables, should end up in a struct */
599static struct floppy_fdc_state fdc_state[N_FDC];
600static int fdc; /* current fdc */
601
602static struct floppy_struct *_floppy = floppy_type;
603static unsigned char current_drive;
604static long current_count_sectors;
605static unsigned char fsector_t; /* sector in track */
606static unsigned char in_sector_offset; /* offset within physical sector,
607 * expressed in units of 512 bytes */
608
609#ifndef fd_eject
610static inline int fd_eject(int drive)
611{
612 return -EINVAL;
613}
614#endif
615
616/*
617 * Debugging
618 * =========
619 */
620#ifdef DEBUGT
621static long unsigned debugtimer;
622
623static inline void set_debugt(void)
624{
625 debugtimer = jiffies;
626}
627
628static inline void debugt(const char *message)
629{
630 if (DP->flags & DEBUGT)
631 printk("%s dtime=%lu\n", message, jiffies - debugtimer);
632}
633#else
634static inline void set_debugt(void) { }
635static inline void debugt(const char *message) { }
636#endif /* DEBUGT */
637
638typedef void (*timeout_fn) (unsigned long);
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700639static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641static const char *timeout_message;
642
643#ifdef FLOPPY_SANITY_CHECK
644static void is_alive(const char *message)
645{
646 /* this routine checks whether the floppy driver is "alive" */
647 if (test_bit(0, &fdc_busy) && command_status < 2
648 && !timer_pending(&fd_timeout)) {
649 DPRINT("timeout handler died: %s\n", message);
650 }
651}
652#endif
653
Joe Perches48c8cee2010-03-10 15:20:45 -0800654static void (*do_floppy)(void) = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
656#ifdef FLOPPY_SANITY_CHECK
657
658#define OLOGSIZE 20
659
Joe Perches48c8cee2010-03-10 15:20:45 -0800660static void (*lasthandler)(void);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661static unsigned long interruptjiffies;
662static unsigned long resultjiffies;
663static int resultsize;
664static unsigned long lastredo;
665
666static struct output_log {
667 unsigned char data;
668 unsigned char status;
669 unsigned long jiffies;
670} output_log[OLOGSIZE];
671
672static int output_log_pos;
673#endif
674
675#define current_reqD -1
676#define MAXTIMEOUT -2
677
678static void __reschedule_timeout(int drive, const char *message, int marg)
679{
680 if (drive == current_reqD)
681 drive = current_drive;
682 del_timer(&fd_timeout);
Eric Sesterhenn / Snakebyte4acb3e22007-05-23 13:58:15 -0700683 if (drive < 0 || drive >= N_DRIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 fd_timeout.expires = jiffies + 20UL * HZ;
685 drive = 0;
686 } else
687 fd_timeout.expires = jiffies + UDP->timeout;
688 add_timer(&fd_timeout);
689 if (UDP->flags & FD_DEBUG) {
690 DPRINT("reschedule timeout ");
691 printk(message, marg);
692 printk("\n");
693 }
694 timeout_message = message;
695}
696
697static void reschedule_timeout(int drive, const char *message, int marg)
698{
699 unsigned long flags;
700
701 spin_lock_irqsave(&floppy_lock, flags);
702 __reschedule_timeout(drive, message, marg);
703 spin_unlock_irqrestore(&floppy_lock, flags);
704}
705
Joe Perches48c8cee2010-03-10 15:20:45 -0800706#define INFBOUND(a, b) (a) = max_t(int, a, b)
707#define SUPBOUND(a, b) (a) = min_t(int, a, b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709/*
710 * Bottom half floppy driver.
711 * ==========================
712 *
713 * This part of the file contains the code talking directly to the hardware,
714 * and also the main service loop (seek-configure-spinup-command)
715 */
716
717/*
718 * disk change.
719 * This routine is responsible for maintaining the FD_DISK_CHANGE flag,
720 * and the last_checked date.
721 *
722 * last_checked is the date of the last check which showed 'no disk change'
723 * FD_DISK_CHANGE is set under two conditions:
724 * 1. The floppy has been changed after some i/o to that floppy already
725 * took place.
726 * 2. No floppy disk is in the drive. This is done in order to ensure that
727 * requests are quickly flushed in case there is no disk in the drive. It
728 * follows that FD_DISK_CHANGE can only be cleared if there is a disk in
729 * the drive.
730 *
731 * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
732 * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
733 * each seek. If a disk is present, the disk change line should also be
734 * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
735 * change line is set, this means either that no disk is in the drive, or
736 * that it has been removed since the last seek.
737 *
738 * This means that we really have a third possibility too:
739 * The floppy has been changed after the last seek.
740 */
741
742static int disk_change(int drive)
743{
744 int fdc = FDC(drive);
Jesper Juhl06f748c2007-10-16 23:30:57 -0700745
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746#ifdef FLOPPY_SANITY_CHECK
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -0800747 if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 DPRINT("WARNING disk change called early\n");
749 if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
750 (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
751 DPRINT("probing disk change on unselected drive\n");
752 DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive),
753 (unsigned int)FDCS->dor);
754 }
755#endif
756
757#ifdef DCL_DEBUG
758 if (UDP->flags & FD_DEBUG) {
759 DPRINT("checking disk change line for drive %d\n", drive);
760 DPRINT("jiffies=%lu\n", jiffies);
761 DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
762 DPRINT("flags=%lx\n", UDRS->flags);
763 }
764#endif
765 if (UDP->flags & FD_BROKEN_DCL)
766 return UTESTF(FD_DISK_CHANGED);
767 if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) {
768 USETF(FD_VERIFY); /* verify write protection */
769 if (UDRS->maxblock) {
770 /* mark it changed */
771 USETF(FD_DISK_CHANGED);
772 }
773
774 /* invalidate its geometry */
775 if (UDRS->keep_data >= 0) {
776 if ((UDP->flags & FTD_MSG) &&
777 current_type[drive] != NULL)
778 DPRINT("Disk type is undefined after "
779 "disk change\n");
780 current_type[drive] = NULL;
781 floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
782 }
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 return 1;
785 } else {
786 UDRS->last_checked = jiffies;
787 UCLEARF(FD_DISK_NEWCHANGE);
788 }
789 return 0;
790}
791
792static inline int is_selected(int dor, int unit)
793{
794 return ((dor & (0x10 << unit)) && (dor & 3) == unit);
795}
796
797static int set_dor(int fdc, char mask, char data)
798{
Jesper Juhlfdc1ca82007-10-16 23:30:58 -0700799 unsigned char unit;
800 unsigned char drive;
801 unsigned char newdor;
802 unsigned char olddor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
804 if (FDCS->address == -1)
805 return -1;
806
807 olddor = FDCS->dor;
808 newdor = (olddor & mask) | data;
809 if (newdor != olddor) {
810 unit = olddor & 0x3;
811 if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
812 drive = REVDRIVE(fdc, unit);
813#ifdef DCL_DEBUG
814 if (UDP->flags & FD_DEBUG) {
815 DPRINT("calling disk change from set_dor\n");
816 }
817#endif
818 disk_change(drive);
819 }
820 FDCS->dor = newdor;
821 fd_outb(newdor, FD_DOR);
822
823 unit = newdor & 0x3;
824 if (!is_selected(olddor, unit) && is_selected(newdor, unit)) {
825 drive = REVDRIVE(fdc, unit);
826 UDRS->select_date = jiffies;
827 }
828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return olddor;
830}
831
832static void twaddle(void)
833{
834 if (DP->select_delay)
835 return;
836 fd_outb(FDCS->dor & ~(0x10 << UNIT(current_drive)), FD_DOR);
837 fd_outb(FDCS->dor, FD_DOR);
838 DRS->select_date = jiffies;
839}
840
841/* reset all driver information about the current fdc. This is needed after
842 * a reset, and after a raw command. */
843static void reset_fdc_info(int mode)
844{
845 int drive;
846
847 FDCS->spec1 = FDCS->spec2 = -1;
848 FDCS->need_configure = 1;
849 FDCS->perp_mode = 1;
850 FDCS->rawcmd = 0;
851 for (drive = 0; drive < N_DRIVE; drive++)
852 if (FDC(drive) == fdc && (mode || UDRS->track != NEED_1_RECAL))
853 UDRS->track = NEED_2_RECAL;
854}
855
856/* selects the fdc and drive, and enables the fdc's input/dma. */
857static void set_fdc(int drive)
858{
859 if (drive >= 0 && drive < N_DRIVE) {
860 fdc = FDC(drive);
861 current_drive = drive;
862 }
863 if (fdc != 1 && fdc != 0) {
864 printk("bad fdc value\n");
865 return;
866 }
867 set_dor(fdc, ~0, 8);
868#if N_FDC > 1
869 set_dor(1 - fdc, ~8, 0);
870#endif
871 if (FDCS->rawcmd == 2)
872 reset_fdc_info(1);
873 if (fd_inb(FD_STATUS) != STATUS_READY)
874 FDCS->reset = 1;
875}
876
877/* locks the driver */
878static int _lock_fdc(int drive, int interruptible, int line)
879{
880 if (!usage_count) {
881 printk(KERN_ERR
882 "Trying to lock fdc while usage count=0 at line %d\n",
883 line);
884 return -1;
885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 if (test_and_set_bit(0, &fdc_busy)) {
888 DECLARE_WAITQUEUE(wait, current);
889 add_wait_queue(&fdc_wait, &wait);
890
891 for (;;) {
892 set_current_state(TASK_INTERRUPTIBLE);
893
894 if (!test_and_set_bit(0, &fdc_busy))
895 break;
896
897 schedule();
898
899 if (!NO_SIGNAL) {
900 remove_wait_queue(&fdc_wait, &wait);
901 return -EINTR;
902 }
903 }
904
905 set_current_state(TASK_RUNNING);
906 remove_wait_queue(&fdc_wait, &wait);
Ingo Molnar3e541a42006-07-03 00:24:23 -0700907 flush_scheduled_work();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 }
909 command_status = FD_COMMAND_NONE;
910
911 __reschedule_timeout(drive, "lock fdc", 0);
912 set_fdc(drive);
913 return 0;
914}
915
Joe Perches48c8cee2010-03-10 15:20:45 -0800916#define lock_fdc(drive, interruptible) \
917 _lock_fdc(drive, interruptible, __LINE__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
Joe Perches48c8cee2010-03-10 15:20:45 -0800919#define LOCK_FDC(drive, interruptible) \
920 if (lock_fdc(drive, interruptible)) \
921 return -EINTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
923/* unlocks the driver */
924static inline void unlock_fdc(void)
925{
926 unsigned long flags;
927
928 raw_cmd = NULL;
929 if (!test_bit(0, &fdc_busy))
930 DPRINT("FDC access conflict!\n");
931
932 if (do_floppy)
933 DPRINT("device interrupt still active at FDC release: %p!\n",
934 do_floppy);
935 command_status = FD_COMMAND_NONE;
936 spin_lock_irqsave(&floppy_lock, flags);
937 del_timer(&fd_timeout);
938 cont = NULL;
939 clear_bit(0, &fdc_busy);
Tejun Heo9934c8c2009-05-08 11:54:16 +0900940 if (current_req || blk_peek_request(floppy_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 do_fd_request(floppy_queue);
942 spin_unlock_irqrestore(&floppy_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 wake_up(&fdc_wait);
944}
945
946/* switches the motor off after a given timeout */
947static void motor_off_callback(unsigned long nr)
948{
949 unsigned char mask = ~(0x10 << UNIT(nr));
950
951 set_dor(FDC(nr), mask, 0);
952}
953
954/* schedules motor off */
955static void floppy_off(unsigned int drive)
956{
957 unsigned long volatile delta;
Jesper Juhlfdc1ca82007-10-16 23:30:58 -0700958 int fdc = FDC(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960 if (!(FDCS->dor & (0x10 << UNIT(drive))))
961 return;
962
963 del_timer(motor_off_timer + drive);
964
965 /* make spindle stop in a position which minimizes spinup time
966 * next time */
967 if (UDP->rps) {
968 delta = jiffies - UDRS->first_read_date + HZ -
969 UDP->spindown_offset;
970 delta = ((delta * UDP->rps) % HZ) / UDP->rps;
971 motor_off_timer[drive].expires =
972 jiffies + UDP->spindown - delta;
973 }
974 add_timer(motor_off_timer + drive);
975}
976
977/*
978 * cycle through all N_DRIVE floppy drives, for disk change testing.
979 * stopping at current drive. This is done before any long operation, to
980 * be sure to have up to date disk change information.
981 */
982static void scandrives(void)
983{
Jesper Juhl06f748c2007-10-16 23:30:57 -0700984 int i;
985 int drive;
986 int saved_drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
988 if (DP->select_delay)
989 return;
990
991 saved_drive = current_drive;
992 for (i = 0; i < N_DRIVE; i++) {
993 drive = (saved_drive + i + 1) % N_DRIVE;
994 if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
995 continue; /* skip closed drives */
996 set_fdc(drive);
997 if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) &
998 (0x10 << UNIT(drive))))
999 /* switch the motor off again, if it was off to
1000 * begin with */
1001 set_dor(fdc, ~(0x10 << UNIT(drive)), 0);
1002 }
1003 set_fdc(saved_drive);
1004}
1005
1006static void empty(void)
1007{
1008}
1009
David Howells65f27f32006-11-22 14:55:48 +00001010static DECLARE_WORK(floppy_work, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Joe Perches48c8cee2010-03-10 15:20:45 -08001012static void schedule_bh(void (*handler)(void))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013{
David Howells65f27f32006-11-22 14:55:48 +00001014 PREPARE_WORK(&floppy_work, (work_func_t)handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 schedule_work(&floppy_work);
1016}
1017
Ingo Molnar8d06afa2005-09-09 13:10:40 -07001018static DEFINE_TIMER(fd_timer, NULL, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020static void cancel_activity(void)
1021{
1022 unsigned long flags;
1023
1024 spin_lock_irqsave(&floppy_lock, flags);
1025 do_floppy = NULL;
David Howells65f27f32006-11-22 14:55:48 +00001026 PREPARE_WORK(&floppy_work, (work_func_t)empty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 del_timer(&fd_timer);
1028 spin_unlock_irqrestore(&floppy_lock, flags);
1029}
1030
1031/* this function makes sure that the disk stays in the drive during the
1032 * transfer */
1033static void fd_watchdog(void)
1034{
1035#ifdef DCL_DEBUG
1036 if (DP->flags & FD_DEBUG) {
1037 DPRINT("calling disk change from watchdog\n");
1038 }
1039#endif
1040
1041 if (disk_change(current_drive)) {
1042 DPRINT("disk removed during i/o\n");
1043 cancel_activity();
1044 cont->done(0);
1045 reset_fdc();
1046 } else {
1047 del_timer(&fd_timer);
1048 fd_timer.function = (timeout_fn) fd_watchdog;
1049 fd_timer.expires = jiffies + HZ / 10;
1050 add_timer(&fd_timer);
1051 }
1052}
1053
1054static void main_command_interrupt(void)
1055{
1056 del_timer(&fd_timer);
1057 cont->interrupt();
1058}
1059
1060/* waits for a delay (spinup or select) to pass */
1061static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
1062{
1063 if (FDCS->reset) {
1064 reset_fdc(); /* do the reset during sleep to win time
1065 * if we don't need to sleep, it's a good
1066 * occasion anyways */
1067 return 1;
1068 }
1069
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001070 if (time_before(jiffies, delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 del_timer(&fd_timer);
1072 fd_timer.function = function;
1073 fd_timer.expires = delay;
1074 add_timer(&fd_timer);
1075 return 1;
1076 }
1077 return 0;
1078}
1079
1080static DEFINE_SPINLOCK(floppy_hlt_lock);
1081static int hlt_disabled;
1082static void floppy_disable_hlt(void)
1083{
1084 unsigned long flags;
1085
1086 spin_lock_irqsave(&floppy_hlt_lock, flags);
1087 if (!hlt_disabled) {
1088 hlt_disabled = 1;
1089#ifdef HAVE_DISABLE_HLT
1090 disable_hlt();
1091#endif
1092 }
1093 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1094}
1095
1096static void floppy_enable_hlt(void)
1097{
1098 unsigned long flags;
1099
1100 spin_lock_irqsave(&floppy_hlt_lock, flags);
1101 if (hlt_disabled) {
1102 hlt_disabled = 0;
1103#ifdef HAVE_DISABLE_HLT
1104 enable_hlt();
1105#endif
1106 }
1107 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1108}
1109
1110static void setup_DMA(void)
1111{
1112 unsigned long f;
1113
1114#ifdef FLOPPY_SANITY_CHECK
1115 if (raw_cmd->length == 0) {
1116 int i;
1117
1118 printk("zero dma transfer size:");
1119 for (i = 0; i < raw_cmd->cmd_count; i++)
1120 printk("%x,", raw_cmd->cmd[i]);
1121 printk("\n");
1122 cont->done(0);
1123 FDCS->reset = 1;
1124 return;
1125 }
1126 if (((unsigned long)raw_cmd->kernel_data) % 512) {
1127 printk("non aligned address: %p\n", raw_cmd->kernel_data);
1128 cont->done(0);
1129 FDCS->reset = 1;
1130 return;
1131 }
1132#endif
1133 f = claim_dma_lock();
1134 fd_disable_dma();
1135#ifdef fd_dma_setup
1136 if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length,
1137 (raw_cmd->flags & FD_RAW_READ) ?
1138 DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) {
1139 release_dma_lock(f);
1140 cont->done(0);
1141 FDCS->reset = 1;
1142 return;
1143 }
1144 release_dma_lock(f);
1145#else
1146 fd_clear_dma_ff();
1147 fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
1148 fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ) ?
1149 DMA_MODE_READ : DMA_MODE_WRITE);
1150 fd_set_dma_addr(raw_cmd->kernel_data);
1151 fd_set_dma_count(raw_cmd->length);
1152 virtual_dma_port = FDCS->address;
1153 fd_enable_dma();
1154 release_dma_lock(f);
1155#endif
1156 floppy_disable_hlt();
1157}
1158
1159static void show_floppy(void);
1160
1161/* waits until the fdc becomes ready */
1162static int wait_til_ready(void)
1163{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001164 int status;
1165 int counter;
1166
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 if (FDCS->reset)
1168 return -1;
1169 for (counter = 0; counter < 10000; counter++) {
1170 status = fd_inb(FD_STATUS);
1171 if (status & STATUS_READY)
1172 return status;
1173 }
1174 if (!initialising) {
1175 DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc);
1176 show_floppy();
1177 }
1178 FDCS->reset = 1;
1179 return -1;
1180}
1181
1182/* sends a command byte to the fdc */
1183static int output_byte(char byte)
1184{
1185 int status;
1186
1187 if ((status = wait_til_ready()) < 0)
1188 return -1;
1189 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) {
1190 fd_outb(byte, FD_DATA);
1191#ifdef FLOPPY_SANITY_CHECK
1192 output_log[output_log_pos].data = byte;
1193 output_log[output_log_pos].status = status;
1194 output_log[output_log_pos].jiffies = jiffies;
1195 output_log_pos = (output_log_pos + 1) % OLOGSIZE;
1196#endif
1197 return 0;
1198 }
1199 FDCS->reset = 1;
1200 if (!initialising) {
1201 DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
1202 byte, fdc, status);
1203 show_floppy();
1204 }
1205 return -1;
1206}
1207
1208#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
1209
1210/* gets the response from the fdc */
1211static int result(void)
1212{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001213 int i;
1214 int status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
1216 for (i = 0; i < MAX_REPLIES; i++) {
1217 if ((status = wait_til_ready()) < 0)
1218 break;
1219 status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
1220 if ((status & ~STATUS_BUSY) == STATUS_READY) {
1221#ifdef FLOPPY_SANITY_CHECK
1222 resultjiffies = jiffies;
1223 resultsize = i;
1224#endif
1225 return i;
1226 }
1227 if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
1228 reply_buffer[i] = fd_inb(FD_DATA);
1229 else
1230 break;
1231 }
1232 if (!initialising) {
1233 DPRINT
1234 ("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
1235 fdc, status, i);
1236 show_floppy();
1237 }
1238 FDCS->reset = 1;
1239 return -1;
1240}
1241
1242#define MORE_OUTPUT -2
1243/* does the fdc need more output? */
1244static int need_more_output(void)
1245{
1246 int status;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001247
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 if ((status = wait_til_ready()) < 0)
1249 return -1;
1250 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
1251 return MORE_OUTPUT;
1252 return result();
1253}
1254
1255/* Set perpendicular mode as required, based on data rate, if supported.
1256 * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
1257 */
1258static inline void perpendicular_mode(void)
1259{
1260 unsigned char perp_mode;
1261
1262 if (raw_cmd->rate & 0x40) {
1263 switch (raw_cmd->rate & 3) {
1264 case 0:
1265 perp_mode = 2;
1266 break;
1267 case 3:
1268 perp_mode = 3;
1269 break;
1270 default:
1271 DPRINT("Invalid data rate for perpendicular mode!\n");
1272 cont->done(0);
1273 FDCS->reset = 1; /* convenient way to return to
1274 * redo without to much hassle (deep
1275 * stack et al. */
1276 return;
1277 }
1278 } else
1279 perp_mode = 0;
1280
1281 if (FDCS->perp_mode == perp_mode)
1282 return;
1283 if (FDCS->version >= FDC_82077_ORIG) {
1284 output_byte(FD_PERPENDICULAR);
1285 output_byte(perp_mode);
1286 FDCS->perp_mode = perp_mode;
1287 } else if (perp_mode) {
1288 DPRINT("perpendicular mode not supported by this FDC.\n");
1289 }
1290} /* perpendicular_mode */
1291
1292static int fifo_depth = 0xa;
1293static int no_fifo;
1294
1295static int fdc_configure(void)
1296{
1297 /* Turn on FIFO */
1298 output_byte(FD_CONFIGURE);
1299 if (need_more_output() != MORE_OUTPUT)
1300 return 0;
1301 output_byte(0);
1302 output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf));
1303 output_byte(0); /* pre-compensation from track
1304 0 upwards */
1305 return 1;
1306}
1307
1308#define NOMINAL_DTR 500
1309
1310/* Issue a "SPECIFY" command to set the step rate time, head unload time,
1311 * head load time, and DMA disable flag to values needed by floppy.
1312 *
1313 * The value "dtr" is the data transfer rate in Kbps. It is needed
1314 * to account for the data rate-based scaling done by the 82072 and 82077
1315 * FDC types. This parameter is ignored for other types of FDCs (i.e.
1316 * 8272a).
1317 *
1318 * Note that changing the data transfer rate has a (probably deleterious)
1319 * effect on the parameters subject to scaling for 82072/82077 FDCs, so
1320 * fdc_specify is called again after each data transfer rate
1321 * change.
1322 *
1323 * srt: 1000 to 16000 in microseconds
1324 * hut: 16 to 240 milliseconds
1325 * hlt: 2 to 254 milliseconds
1326 *
1327 * These values are rounded up to the next highest available delay time.
1328 */
1329static void fdc_specify(void)
1330{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001331 unsigned char spec1;
1332 unsigned char spec2;
1333 unsigned long srt;
1334 unsigned long hlt;
1335 unsigned long hut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 unsigned long dtr = NOMINAL_DTR;
1337 unsigned long scale_dtr = NOMINAL_DTR;
1338 int hlt_max_code = 0x7f;
1339 int hut_max_code = 0xf;
1340
1341 if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
1342 fdc_configure();
1343 FDCS->need_configure = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 }
1345
1346 switch (raw_cmd->rate & 0x03) {
1347 case 3:
1348 dtr = 1000;
1349 break;
1350 case 1:
1351 dtr = 300;
1352 if (FDCS->version >= FDC_82078) {
1353 /* chose the default rate table, not the one
1354 * where 1 = 2 Mbps */
1355 output_byte(FD_DRIVESPEC);
1356 if (need_more_output() == MORE_OUTPUT) {
1357 output_byte(UNIT(current_drive));
1358 output_byte(0xc0);
1359 }
1360 }
1361 break;
1362 case 2:
1363 dtr = 250;
1364 break;
1365 }
1366
1367 if (FDCS->version >= FDC_82072) {
1368 scale_dtr = dtr;
1369 hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */
1370 hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */
1371 }
1372
1373 /* Convert step rate from microseconds to milliseconds and 4 bits */
Julia Lawall061837b2008-09-22 14:57:16 -07001374 srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 if (slow_floppy) {
1376 srt = srt / 4;
1377 }
1378 SUPBOUND(srt, 0xf);
1379 INFBOUND(srt, 0);
1380
Julia Lawall061837b2008-09-22 14:57:16 -07001381 hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 if (hlt < 0x01)
1383 hlt = 0x01;
1384 else if (hlt > 0x7f)
1385 hlt = hlt_max_code;
1386
Julia Lawall061837b2008-09-22 14:57:16 -07001387 hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388 if (hut < 0x1)
1389 hut = 0x1;
1390 else if (hut > 0xf)
1391 hut = hut_max_code;
1392
1393 spec1 = (srt << 4) | hut;
1394 spec2 = (hlt << 1) | (use_virtual_dma & 1);
1395
1396 /* If these parameters did not change, just return with success */
1397 if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) {
1398 /* Go ahead and set spec1 and spec2 */
1399 output_byte(FD_SPECIFY);
1400 output_byte(FDCS->spec1 = spec1);
1401 output_byte(FDCS->spec2 = spec2);
1402 }
1403} /* fdc_specify */
1404
1405/* Set the FDC's data transfer rate on behalf of the specified drive.
1406 * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue
1407 * of the specify command (i.e. using the fdc_specify function).
1408 */
1409static int fdc_dtr(void)
1410{
1411 /* If data rate not already set to desired value, set it. */
1412 if ((raw_cmd->rate & 3) == FDCS->dtr)
1413 return 0;
1414
1415 /* Set dtr */
1416 fd_outb(raw_cmd->rate & 3, FD_DCR);
1417
1418 /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
1419 * need a stabilization period of several milliseconds to be
1420 * enforced after data rate changes before R/W operations.
1421 * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
1422 */
1423 FDCS->dtr = raw_cmd->rate & 3;
1424 return (fd_wait_for_completion(jiffies + 2UL * HZ / 100,
1425 (timeout_fn) floppy_ready));
1426} /* fdc_dtr */
1427
1428static void tell_sector(void)
1429{
1430 printk(": track %d, head %d, sector %d, size %d",
1431 R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
1432} /* tell_sector */
1433
1434/*
1435 * OK, this error interpreting routine is called after a
1436 * DMA read/write has succeeded
1437 * or failed, so we check the results, and copy any buffers.
1438 * hhb: Added better error reporting.
1439 * ak: Made this into a separate routine.
1440 */
1441static int interpret_errors(void)
1442{
1443 char bad;
1444
1445 if (inr != 7) {
1446 DPRINT("-- FDC reply error");
1447 FDCS->reset = 1;
1448 return 1;
1449 }
1450
1451 /* check IC to find cause of interrupt */
1452 switch (ST0 & ST0_INTR) {
1453 case 0x40: /* error occurred during command execution */
1454 if (ST1 & ST1_EOC)
1455 return 0; /* occurs with pseudo-DMA */
1456 bad = 1;
1457 if (ST1 & ST1_WP) {
1458 DPRINT("Drive is write protected\n");
1459 CLEARF(FD_DISK_WRITABLE);
1460 cont->done(0);
1461 bad = 2;
1462 } else if (ST1 & ST1_ND) {
1463 SETF(FD_NEED_TWADDLE);
1464 } else if (ST1 & ST1_OR) {
1465 if (DP->flags & FTD_MSG)
1466 DPRINT("Over/Underrun - retrying\n");
1467 bad = 0;
1468 } else if (*errors >= DP->max_errors.reporting) {
1469 DPRINT("");
1470 if (ST0 & ST0_ECE) {
1471 printk("Recalibrate failed!");
1472 } else if (ST2 & ST2_CRC) {
1473 printk("data CRC error");
1474 tell_sector();
1475 } else if (ST1 & ST1_CRC) {
1476 printk("CRC error");
1477 tell_sector();
1478 } else if ((ST1 & (ST1_MAM | ST1_ND))
1479 || (ST2 & ST2_MAM)) {
1480 if (!probing) {
1481 printk("sector not found");
1482 tell_sector();
1483 } else
1484 printk("probe failed...");
1485 } else if (ST2 & ST2_WC) { /* seek error */
1486 printk("wrong cylinder");
1487 } else if (ST2 & ST2_BC) { /* cylinder marked as bad */
1488 printk("bad cylinder");
1489 } else {
1490 printk
1491 ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
1492 ST0, ST1, ST2);
1493 tell_sector();
1494 }
1495 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 }
1497 if (ST2 & ST2_WC || ST2 & ST2_BC)
1498 /* wrong cylinder => recal */
1499 DRS->track = NEED_2_RECAL;
1500 return bad;
1501 case 0x80: /* invalid command given */
1502 DPRINT("Invalid FDC command given!\n");
1503 cont->done(0);
1504 return 2;
1505 case 0xc0:
1506 DPRINT("Abnormal termination caused by polling\n");
1507 cont->error();
1508 return 2;
1509 default: /* (0) Normal command termination */
1510 return 0;
1511 }
1512}
1513
1514/*
1515 * This routine is called when everything should be correctly set up
1516 * for the transfer (i.e. floppy motor is on, the correct floppy is
1517 * selected, and the head is sitting on the right track).
1518 */
1519static void setup_rw_floppy(void)
1520{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001521 int i;
1522 int r;
1523 int flags;
1524 int dflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 unsigned long ready_date;
1526 timeout_fn function;
1527
1528 flags = raw_cmd->flags;
1529 if (flags & (FD_RAW_READ | FD_RAW_WRITE))
1530 flags |= FD_RAW_INTR;
1531
1532 if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)) {
1533 ready_date = DRS->spinup_date + DP->spinup;
1534 /* If spinup will take a long time, rerun scandrives
1535 * again just before spinup completion. Beware that
1536 * after scandrives, we must again wait for selection.
1537 */
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001538 if (time_after(ready_date, jiffies + DP->select_delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 ready_date -= DP->select_delay;
1540 function = (timeout_fn) floppy_start;
1541 } else
1542 function = (timeout_fn) setup_rw_floppy;
1543
1544 /* wait until the floppy is spinning fast enough */
1545 if (fd_wait_for_completion(ready_date, function))
1546 return;
1547 }
1548 dflags = DRS->flags;
1549
1550 if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
1551 setup_DMA();
1552
1553 if (flags & FD_RAW_INTR)
1554 do_floppy = main_command_interrupt;
1555
1556 r = 0;
1557 for (i = 0; i < raw_cmd->cmd_count; i++)
1558 r |= output_byte(raw_cmd->cmd[i]);
1559
1560 debugt("rw_command: ");
1561
1562 if (r) {
1563 cont->error();
1564 reset_fdc();
1565 return;
1566 }
1567
1568 if (!(flags & FD_RAW_INTR)) {
1569 inr = result();
1570 cont->interrupt();
1571 } else if (flags & FD_RAW_NEED_DISK)
1572 fd_watchdog();
1573}
1574
1575static int blind_seek;
1576
1577/*
1578 * This is the routine called after every seek (or recalibrate) interrupt
1579 * from the floppy controller.
1580 */
1581static void seek_interrupt(void)
1582{
1583 debugt("seek interrupt:");
1584 if (inr != 2 || (ST0 & 0xF8) != 0x20) {
1585 DPRINT("seek failed\n");
1586 DRS->track = NEED_2_RECAL;
1587 cont->error();
1588 cont->redo();
1589 return;
1590 }
1591 if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) {
1592#ifdef DCL_DEBUG
1593 if (DP->flags & FD_DEBUG) {
1594 DPRINT
1595 ("clearing NEWCHANGE flag because of effective seek\n");
1596 DPRINT("jiffies=%lu\n", jiffies);
1597 }
1598#endif
1599 CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
1600 DRS->select_date = jiffies;
1601 }
1602 DRS->track = ST1;
1603 floppy_ready();
1604}
1605
1606static void check_wp(void)
1607{
1608 if (TESTF(FD_VERIFY)) {
1609 /* check write protection */
1610 output_byte(FD_GETSTATUS);
1611 output_byte(UNIT(current_drive));
1612 if (result() != 1) {
1613 FDCS->reset = 1;
1614 return;
1615 }
1616 CLEARF(FD_VERIFY);
1617 CLEARF(FD_NEED_TWADDLE);
1618#ifdef DCL_DEBUG
1619 if (DP->flags & FD_DEBUG) {
1620 DPRINT("checking whether disk is write protected\n");
1621 DPRINT("wp=%x\n", ST3 & 0x40);
1622 }
1623#endif
1624 if (!(ST3 & 0x40))
1625 SETF(FD_DISK_WRITABLE);
1626 else
1627 CLEARF(FD_DISK_WRITABLE);
1628 }
1629}
1630
1631static void seek_floppy(void)
1632{
1633 int track;
1634
1635 blind_seek = 0;
1636
1637#ifdef DCL_DEBUG
1638 if (DP->flags & FD_DEBUG) {
1639 DPRINT("calling disk change from seek\n");
1640 }
1641#endif
1642
1643 if (!TESTF(FD_DISK_NEWCHANGE) &&
1644 disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) {
1645 /* the media changed flag should be cleared after the seek.
1646 * If it isn't, this means that there is really no disk in
1647 * the drive.
1648 */
1649 SETF(FD_DISK_CHANGED);
1650 cont->done(0);
1651 cont->redo();
1652 return;
1653 }
1654 if (DRS->track <= NEED_1_RECAL) {
1655 recalibrate_floppy();
1656 return;
1657 } else if (TESTF(FD_DISK_NEWCHANGE) &&
1658 (raw_cmd->flags & FD_RAW_NEED_DISK) &&
1659 (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
1660 /* we seek to clear the media-changed condition. Does anybody
1661 * know a more elegant way, which works on all drives? */
1662 if (raw_cmd->track)
1663 track = raw_cmd->track - 1;
1664 else {
1665 if (DP->flags & FD_SILENT_DCL_CLEAR) {
1666 set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0);
1667 blind_seek = 1;
1668 raw_cmd->flags |= FD_RAW_NEED_SEEK;
1669 }
1670 track = 1;
1671 }
1672 } else {
1673 check_wp();
1674 if (raw_cmd->track != DRS->track &&
1675 (raw_cmd->flags & FD_RAW_NEED_SEEK))
1676 track = raw_cmd->track;
1677 else {
1678 setup_rw_floppy();
1679 return;
1680 }
1681 }
1682
1683 do_floppy = seek_interrupt;
1684 output_byte(FD_SEEK);
1685 output_byte(UNIT(current_drive));
1686 LAST_OUT(track);
1687 debugt("seek command:");
1688}
1689
1690static void recal_interrupt(void)
1691{
1692 debugt("recal interrupt:");
1693 if (inr != 2)
1694 FDCS->reset = 1;
1695 else if (ST0 & ST0_ECE) {
1696 switch (DRS->track) {
1697 case NEED_1_RECAL:
1698 debugt("recal interrupt need 1 recal:");
1699 /* after a second recalibrate, we still haven't
1700 * reached track 0. Probably no drive. Raise an
1701 * error, as failing immediately might upset
1702 * computers possessed by the Devil :-) */
1703 cont->error();
1704 cont->redo();
1705 return;
1706 case NEED_2_RECAL:
1707 debugt("recal interrupt need 2 recal:");
1708 /* If we already did a recalibrate,
1709 * and we are not at track 0, this
1710 * means we have moved. (The only way
1711 * not to move at recalibration is to
1712 * be already at track 0.) Clear the
1713 * new change flag */
1714#ifdef DCL_DEBUG
1715 if (DP->flags & FD_DEBUG) {
1716 DPRINT
1717 ("clearing NEWCHANGE flag because of second recalibrate\n");
1718 }
1719#endif
1720
1721 CLEARF(FD_DISK_NEWCHANGE);
1722 DRS->select_date = jiffies;
1723 /* fall through */
1724 default:
1725 debugt("recal interrupt default:");
1726 /* Recalibrate moves the head by at
1727 * most 80 steps. If after one
1728 * recalibrate we don't have reached
1729 * track 0, this might mean that we
1730 * started beyond track 80. Try
1731 * again. */
1732 DRS->track = NEED_1_RECAL;
1733 break;
1734 }
1735 } else
1736 DRS->track = ST1;
1737 floppy_ready();
1738}
1739
1740static void print_result(char *message, int inr)
1741{
1742 int i;
1743
1744 DPRINT("%s ", message);
1745 if (inr >= 0)
1746 for (i = 0; i < inr; i++)
1747 printk("repl[%d]=%x ", i, reply_buffer[i]);
1748 printk("\n");
1749}
1750
1751/* interrupt handler. Note that this can be called externally on the Sparc */
David Howells7d12e782006-10-05 14:55:46 +01001752irqreturn_t floppy_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 int do_print;
1755 unsigned long f;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001756 void (*handler)(void) = do_floppy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758 lasthandler = handler;
1759 interruptjiffies = jiffies;
1760
1761 f = claim_dma_lock();
1762 fd_disable_dma();
1763 release_dma_lock(f);
1764
1765 floppy_enable_hlt();
1766 do_floppy = NULL;
1767 if (fdc >= N_FDC || FDCS->address == -1) {
1768 /* we don't even know which FDC is the culprit */
1769 printk("DOR0=%x\n", fdc_state[0].dor);
1770 printk("floppy interrupt on bizarre fdc %d\n", fdc);
1771 printk("handler=%p\n", handler);
1772 is_alive("bizarre fdc");
1773 return IRQ_NONE;
1774 }
1775
1776 FDCS->reset = 0;
1777 /* We have to clear the reset flag here, because apparently on boxes
1778 * with level triggered interrupts (PS/2, Sparc, ...), it is needed to
1779 * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the
1780 * emission of the SENSEI's.
1781 * It is OK to emit floppy commands because we are in an interrupt
1782 * handler here, and thus we have to fear no interference of other
1783 * activity.
1784 */
1785
1786 do_print = !handler && print_unex && !initialising;
1787
1788 inr = result();
1789 if (do_print)
1790 print_result("unexpected interrupt", inr);
1791 if (inr == 0) {
1792 int max_sensei = 4;
1793 do {
1794 output_byte(FD_SENSEI);
1795 inr = result();
1796 if (do_print)
1797 print_result("sensei", inr);
1798 max_sensei--;
1799 } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2
1800 && max_sensei);
1801 }
1802 if (!handler) {
1803 FDCS->reset = 1;
1804 return IRQ_NONE;
1805 }
1806 schedule_bh(handler);
1807 is_alive("normal interrupt end");
1808
1809 /* FIXME! Was it really for us? */
1810 return IRQ_HANDLED;
1811}
1812
1813static void recalibrate_floppy(void)
1814{
1815 debugt("recalibrate floppy:");
1816 do_floppy = recal_interrupt;
1817 output_byte(FD_RECALIBRATE);
1818 LAST_OUT(UNIT(current_drive));
1819}
1820
1821/*
1822 * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
1823 */
1824static void reset_interrupt(void)
1825{
1826 debugt("reset interrupt:");
1827 result(); /* get the status ready for set_fdc */
1828 if (FDCS->reset) {
1829 printk("reset set in interrupt, calling %p\n", cont->error);
1830 cont->error(); /* a reset just after a reset. BAD! */
1831 }
1832 cont->redo();
1833}
1834
1835/*
1836 * reset is done by pulling bit 2 of DOR low for a while (old FDCs),
1837 * or by setting the self clearing bit 7 of STATUS (newer FDCs)
1838 */
1839static void reset_fdc(void)
1840{
1841 unsigned long flags;
1842
1843 do_floppy = reset_interrupt;
1844 FDCS->reset = 0;
1845 reset_fdc_info(0);
1846
1847 /* Pseudo-DMA may intercept 'reset finished' interrupt. */
1848 /* Irrelevant for systems with true DMA (i386). */
1849
1850 flags = claim_dma_lock();
1851 fd_disable_dma();
1852 release_dma_lock(flags);
1853
1854 if (FDCS->version >= FDC_82072A)
1855 fd_outb(0x80 | (FDCS->dtr & 3), FD_STATUS);
1856 else {
1857 fd_outb(FDCS->dor & ~0x04, FD_DOR);
1858 udelay(FD_RESET_DELAY);
1859 fd_outb(FDCS->dor, FD_DOR);
1860 }
1861}
1862
1863static void show_floppy(void)
1864{
1865 int i;
1866
1867 printk("\n");
1868 printk("floppy driver state\n");
1869 printk("-------------------\n");
1870 printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
1871 jiffies, interruptjiffies, jiffies - interruptjiffies,
1872 lasthandler);
1873
1874#ifdef FLOPPY_SANITY_CHECK
1875 printk("timeout_message=%s\n", timeout_message);
1876 printk("last output bytes:\n");
1877 for (i = 0; i < OLOGSIZE; i++)
1878 printk("%2x %2x %lu\n",
1879 output_log[(i + output_log_pos) % OLOGSIZE].data,
1880 output_log[(i + output_log_pos) % OLOGSIZE].status,
1881 output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
1882 printk("last result at %lu\n", resultjiffies);
1883 printk("last redo_fd_request at %lu\n", lastredo);
1884 for (i = 0; i < resultsize; i++) {
1885 printk("%2x ", reply_buffer[i]);
1886 }
1887 printk("\n");
1888#endif
1889
1890 printk("status=%x\n", fd_inb(FD_STATUS));
1891 printk("fdc_busy=%lu\n", fdc_busy);
1892 if (do_floppy)
1893 printk("do_floppy=%p\n", do_floppy);
David Howells365970a2006-11-22 14:54:49 +00001894 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895 printk("floppy_work.func=%p\n", floppy_work.func);
1896 if (timer_pending(&fd_timer))
1897 printk("fd_timer.function=%p\n", fd_timer.function);
1898 if (timer_pending(&fd_timeout)) {
1899 printk("timer_function=%p\n", fd_timeout.function);
1900 printk("expires=%lu\n", fd_timeout.expires - jiffies);
1901 printk("now=%lu\n", jiffies);
1902 }
1903 printk("cont=%p\n", cont);
1904 printk("current_req=%p\n", current_req);
1905 printk("command_status=%d\n", command_status);
1906 printk("\n");
1907}
1908
1909static void floppy_shutdown(unsigned long data)
1910{
1911 unsigned long flags;
1912
1913 if (!initialising)
1914 show_floppy();
1915 cancel_activity();
1916
1917 floppy_enable_hlt();
1918
1919 flags = claim_dma_lock();
1920 fd_disable_dma();
1921 release_dma_lock(flags);
1922
1923 /* avoid dma going to a random drive after shutdown */
1924
1925 if (!initialising)
1926 DPRINT("floppy timeout called\n");
1927 FDCS->reset = 1;
1928 if (cont) {
1929 cont->done(0);
1930 cont->redo(); /* this will recall reset when needed */
1931 } else {
1932 printk("no cont in shutdown!\n");
1933 process_fd_request();
1934 }
1935 is_alive("floppy shutdown");
1936}
1937
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938/* start motor, check media-changed condition and write protection */
Jesper Juhl06f748c2007-10-16 23:30:57 -07001939static int start_motor(void (*function)(void))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001941 int mask;
1942 int data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943
1944 mask = 0xfc;
1945 data = UNIT(current_drive);
1946 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)) {
1947 if (!(FDCS->dor & (0x10 << UNIT(current_drive)))) {
1948 set_debugt();
1949 /* no read since this drive is running */
1950 DRS->first_read_date = 0;
1951 /* note motor start time if motor is not yet running */
1952 DRS->spinup_date = jiffies;
1953 data |= (0x10 << UNIT(current_drive));
1954 }
1955 } else if (FDCS->dor & (0x10 << UNIT(current_drive)))
1956 mask &= ~(0x10 << UNIT(current_drive));
1957
1958 /* starts motor and selects floppy */
1959 del_timer(motor_off_timer + current_drive);
1960 set_dor(fdc, mask, data);
1961
1962 /* wait_for_completion also schedules reset if needed. */
1963 return (fd_wait_for_completion(DRS->select_date + DP->select_delay,
1964 (timeout_fn) function));
1965}
1966
1967static void floppy_ready(void)
1968{
1969 CHECK_RESET;
1970 if (start_motor(floppy_ready))
1971 return;
1972 if (fdc_dtr())
1973 return;
1974
1975#ifdef DCL_DEBUG
1976 if (DP->flags & FD_DEBUG) {
1977 DPRINT("calling disk change from floppy_ready\n");
1978 }
1979#endif
1980 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
1981 disk_change(current_drive) && !DP->select_delay)
1982 twaddle(); /* this clears the dcl on certain drive/controller
1983 * combinations */
1984
1985#ifdef fd_chose_dma_mode
1986 if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) {
1987 unsigned long flags = claim_dma_lock();
1988 fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length);
1989 release_dma_lock(flags);
1990 }
1991#endif
1992
1993 if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)) {
1994 perpendicular_mode();
1995 fdc_specify(); /* must be done here because of hut, hlt ... */
1996 seek_floppy();
1997 } else {
1998 if ((raw_cmd->flags & FD_RAW_READ) ||
1999 (raw_cmd->flags & FD_RAW_WRITE))
2000 fdc_specify();
2001 setup_rw_floppy();
2002 }
2003}
2004
2005static void floppy_start(void)
2006{
2007 reschedule_timeout(current_reqD, "floppy start", 0);
2008
2009 scandrives();
2010#ifdef DCL_DEBUG
2011 if (DP->flags & FD_DEBUG) {
2012 DPRINT("setting NEWCHANGE in floppy_start\n");
2013 }
2014#endif
2015 SETF(FD_DISK_NEWCHANGE);
2016 floppy_ready();
2017}
2018
2019/*
2020 * ========================================================================
2021 * here ends the bottom half. Exported routines are:
2022 * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
2023 * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
2024 * Initialization also uses output_byte, result, set_dor, floppy_interrupt
2025 * and set_dor.
2026 * ========================================================================
2027 */
2028/*
2029 * General purpose continuations.
2030 * ==============================
2031 */
2032
2033static void do_wakeup(void)
2034{
2035 reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
2036 cont = NULL;
2037 command_status += 2;
2038 wake_up(&command_done);
2039}
2040
2041static struct cont_t wakeup_cont = {
2042 .interrupt = empty,
2043 .redo = do_wakeup,
2044 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002045 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046};
2047
2048static struct cont_t intr_cont = {
2049 .interrupt = empty,
2050 .redo = process_fd_request,
2051 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002052 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053};
2054
Jesper Juhl06f748c2007-10-16 23:30:57 -07002055static int wait_til_done(void (*handler)(void), int interruptible)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056{
2057 int ret;
2058
2059 schedule_bh(handler);
2060
2061 if (command_status < 2 && NO_SIGNAL) {
2062 DECLARE_WAITQUEUE(wait, current);
2063
2064 add_wait_queue(&command_done, &wait);
2065 for (;;) {
2066 set_current_state(interruptible ?
2067 TASK_INTERRUPTIBLE :
2068 TASK_UNINTERRUPTIBLE);
2069
2070 if (command_status >= 2 || !NO_SIGNAL)
2071 break;
2072
2073 is_alive("wait_til_done");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074 schedule();
2075 }
2076
2077 set_current_state(TASK_RUNNING);
2078 remove_wait_queue(&command_done, &wait);
2079 }
2080
2081 if (command_status < 2) {
2082 cancel_activity();
2083 cont = &intr_cont;
2084 reset_fdc();
2085 return -EINTR;
2086 }
2087
2088 if (FDCS->reset)
2089 command_status = FD_COMMAND_ERROR;
2090 if (command_status == FD_COMMAND_OKAY)
2091 ret = 0;
2092 else
2093 ret = -EIO;
2094 command_status = FD_COMMAND_NONE;
2095 return ret;
2096}
2097
2098static void generic_done(int result)
2099{
2100 command_status = result;
2101 cont = &wakeup_cont;
2102}
2103
2104static void generic_success(void)
2105{
2106 cont->done(1);
2107}
2108
2109static void generic_failure(void)
2110{
2111 cont->done(0);
2112}
2113
2114static void success_and_wakeup(void)
2115{
2116 generic_success();
2117 cont->redo();
2118}
2119
2120/*
2121 * formatting and rw support.
2122 * ==========================
2123 */
2124
2125static int next_valid_format(void)
2126{
2127 int probed_format;
2128
2129 probed_format = DRS->probed_format;
2130 while (1) {
2131 if (probed_format >= 8 || !DP->autodetect[probed_format]) {
2132 DRS->probed_format = 0;
2133 return 1;
2134 }
2135 if (floppy_type[DP->autodetect[probed_format]].sect) {
2136 DRS->probed_format = probed_format;
2137 return 0;
2138 }
2139 probed_format++;
2140 }
2141}
2142
2143static void bad_flp_intr(void)
2144{
2145 int err_count;
2146
2147 if (probing) {
2148 DRS->probed_format++;
2149 if (!next_valid_format())
2150 return;
2151 }
2152 err_count = ++(*errors);
2153 INFBOUND(DRWE->badness, err_count);
2154 if (err_count > DP->max_errors.abort)
2155 cont->done(0);
2156 if (err_count > DP->max_errors.reset)
2157 FDCS->reset = 1;
2158 else if (err_count > DP->max_errors.recal)
2159 DRS->track = NEED_2_RECAL;
2160}
2161
2162static void set_floppy(int drive)
2163{
2164 int type = ITYPE(UDRS->fd_device);
Jesper Juhl06f748c2007-10-16 23:30:57 -07002165
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 if (type)
2167 _floppy = floppy_type + type;
2168 else
2169 _floppy = current_type[drive];
2170}
2171
2172/*
2173 * formatting support.
2174 * ===================
2175 */
2176static void format_interrupt(void)
2177{
2178 switch (interpret_errors()) {
2179 case 1:
2180 cont->error();
2181 case 2:
2182 break;
2183 case 0:
2184 cont->done(1);
2185 }
2186 cont->redo();
2187}
2188
2189#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
Joe Perches48c8cee2010-03-10 15:20:45 -08002190#define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191#define CT(x) ((x) | 0xc0)
Joe Perches48c8cee2010-03-10 15:20:45 -08002192
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193static void setup_format_params(int track)
2194{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002195 int n;
2196 int il;
2197 int count;
2198 int head_shift;
2199 int track_shift;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 struct fparm {
2201 unsigned char track, head, sect, size;
2202 } *here = (struct fparm *)floppy_track_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
2204 raw_cmd = &default_raw_cmd;
2205 raw_cmd->track = track;
2206
Joe Perches48c8cee2010-03-10 15:20:45 -08002207 raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
2208 FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 raw_cmd->rate = _floppy->rate & 0x43;
2210 raw_cmd->cmd_count = NR_F;
2211 COMMAND = FM_MODE(_floppy, FD_FORMAT);
2212 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, format_req.head);
2213 F_SIZECODE = FD_SIZECODE(_floppy);
2214 F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE;
2215 F_GAP = _floppy->fmt_gap;
2216 F_FILL = FD_FILL_BYTE;
2217
2218 raw_cmd->kernel_data = floppy_track_buffer;
2219 raw_cmd->length = 4 * F_SECT_PER_TRACK;
2220
2221 /* allow for about 30ms for data transport per track */
2222 head_shift = (F_SECT_PER_TRACK + 5) / 6;
2223
2224 /* a ``cylinder'' is two tracks plus a little stepping time */
2225 track_shift = 2 * head_shift + 3;
2226
2227 /* position of logical sector 1 on this track */
2228 n = (track_shift * format_req.track + head_shift * format_req.head)
2229 % F_SECT_PER_TRACK;
2230
2231 /* determine interleave */
2232 il = 1;
2233 if (_floppy->fmt_gap < 0x22)
2234 il++;
2235
2236 /* initialize field */
2237 for (count = 0; count < F_SECT_PER_TRACK; ++count) {
2238 here[count].track = format_req.track;
2239 here[count].head = format_req.head;
2240 here[count].sect = 0;
2241 here[count].size = F_SIZECODE;
2242 }
2243 /* place logical sectors */
2244 for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
2245 here[n].sect = count;
2246 n = (n + il) % F_SECT_PER_TRACK;
2247 if (here[n].sect) { /* sector busy, find next free sector */
2248 ++n;
2249 if (n >= F_SECT_PER_TRACK) {
2250 n -= F_SECT_PER_TRACK;
2251 while (here[n].sect)
2252 ++n;
2253 }
2254 }
2255 }
Keith Wansbrough9e491842008-09-22 14:57:17 -07002256 if (_floppy->stretch & FD_SECTBASEMASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 for (count = 0; count < F_SECT_PER_TRACK; count++)
Keith Wansbrough9e491842008-09-22 14:57:17 -07002258 here[count].sect += FD_SECTBASE(_floppy) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 }
2260}
2261
2262static void redo_format(void)
2263{
2264 buffer_track = -1;
2265 setup_format_params(format_req.track << STRETCH(_floppy));
2266 floppy_start();
2267 debugt("queue format request");
2268}
2269
2270static struct cont_t format_cont = {
2271 .interrupt = format_interrupt,
2272 .redo = redo_format,
2273 .error = bad_flp_intr,
2274 .done = generic_done
2275};
2276
2277static int do_format(int drive, struct format_descr *tmp_format_req)
2278{
2279 int ret;
2280
2281 LOCK_FDC(drive, 1);
2282 set_floppy(drive);
2283 if (!_floppy ||
2284 _floppy->track > DP->tracks ||
2285 tmp_format_req->track >= _floppy->track ||
2286 tmp_format_req->head >= _floppy->head ||
2287 (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) ||
2288 !_floppy->fmt_gap) {
2289 process_fd_request();
2290 return -EINVAL;
2291 }
2292 format_req = *tmp_format_req;
2293 format_errors = 0;
2294 cont = &format_cont;
2295 errors = &format_errors;
2296 IWAIT(redo_format);
2297 process_fd_request();
2298 return ret;
2299}
2300
2301/*
2302 * Buffer read/write and support
2303 * =============================
2304 */
2305
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002306static void floppy_end_request(struct request *req, int error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307{
2308 unsigned int nr_sectors = current_count_sectors;
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002309 unsigned int drive = (unsigned long)req->rq_disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
2311 /* current_count_sectors can be zero if transfer failed */
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002312 if (error)
Tejun Heo83096eb2009-05-07 22:24:39 +09002313 nr_sectors = blk_rq_cur_sectors(req);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002314 if (__blk_end_request(req, error, nr_sectors << 9))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316
2317 /* We're done with the request */
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002318 floppy_off(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 current_req = NULL;
2320}
2321
2322/* new request_done. Can handle physical sectors which are smaller than a
2323 * logical buffer */
2324static void request_done(int uptodate)
2325{
2326 struct request_queue *q = floppy_queue;
2327 struct request *req = current_req;
2328 unsigned long flags;
2329 int block;
2330
2331 probing = 0;
2332 reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
2333
2334 if (!req) {
2335 printk("floppy.c: no request in request_done\n");
2336 return;
2337 }
2338
2339 if (uptodate) {
2340 /* maintain values for invalidation on geometry
2341 * change */
Tejun Heo83096eb2009-05-07 22:24:39 +09002342 block = current_count_sectors + blk_rq_pos(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343 INFBOUND(DRS->maxblock, block);
2344 if (block > _floppy->sect)
2345 DRS->maxtrack = 1;
2346
2347 /* unlock chained buffers */
2348 spin_lock_irqsave(q->queue_lock, flags);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002349 floppy_end_request(req, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 spin_unlock_irqrestore(q->queue_lock, flags);
2351 } else {
2352 if (rq_data_dir(req) == WRITE) {
2353 /* record write error information */
2354 DRWE->write_errors++;
2355 if (DRWE->write_errors == 1) {
Tejun Heo83096eb2009-05-07 22:24:39 +09002356 DRWE->first_error_sector = blk_rq_pos(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 DRWE->first_error_generation = DRS->generation;
2358 }
Tejun Heo83096eb2009-05-07 22:24:39 +09002359 DRWE->last_error_sector = blk_rq_pos(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 DRWE->last_error_generation = DRS->generation;
2361 }
2362 spin_lock_irqsave(q->queue_lock, flags);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002363 floppy_end_request(req, -EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 spin_unlock_irqrestore(q->queue_lock, flags);
2365 }
2366}
2367
2368/* Interrupt handler evaluating the result of the r/w operation */
2369static void rw_interrupt(void)
2370{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002371 int eoc;
2372 int ssize;
2373 int heads;
2374 int nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
2376 if (R_HEAD >= 2) {
2377 /* some Toshiba floppy controllers occasionnally seem to
2378 * return bogus interrupts after read/write operations, which
2379 * can be recognized by a bad head number (>= 2) */
2380 return;
2381 }
2382
2383 if (!DRS->first_read_date)
2384 DRS->first_read_date = jiffies;
2385
2386 nr_sectors = 0;
2387 CODE2SIZE;
2388
2389 if (ST1 & ST1_EOC)
2390 eoc = 1;
2391 else
2392 eoc = 0;
2393
2394 if (COMMAND & 0x80)
2395 heads = 2;
2396 else
2397 heads = 1;
2398
2399 nr_sectors = (((R_TRACK - TRACK) * heads +
2400 R_HEAD - HEAD) * SECT_PER_TRACK +
2401 R_SECTOR - SECTOR + eoc) << SIZECODE >> 2;
2402
2403#ifdef FLOPPY_SANITY_CHECK
2404 if (nr_sectors / ssize >
Julia Lawall061837b2008-09-22 14:57:16 -07002405 DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 DPRINT("long rw: %x instead of %lx\n",
2407 nr_sectors, current_count_sectors);
2408 printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
2409 printk("rh=%d h=%d\n", R_HEAD, HEAD);
2410 printk("rt=%d t=%d\n", R_TRACK, TRACK);
2411 printk("heads=%d eoc=%d\n", heads, eoc);
2412 printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
2413 fsector_t, ssize);
2414 printk("in_sector_offset=%d\n", in_sector_offset);
2415 }
2416#endif
2417
2418 nr_sectors -= in_sector_offset;
2419 INFBOUND(nr_sectors, 0);
2420 SUPBOUND(current_count_sectors, nr_sectors);
2421
2422 switch (interpret_errors()) {
2423 case 2:
2424 cont->redo();
2425 return;
2426 case 1:
2427 if (!current_count_sectors) {
2428 cont->error();
2429 cont->redo();
2430 return;
2431 }
2432 break;
2433 case 0:
2434 if (!current_count_sectors) {
2435 cont->redo();
2436 return;
2437 }
2438 current_type[current_drive] = _floppy;
2439 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2440 break;
2441 }
2442
2443 if (probing) {
2444 if (DP->flags & FTD_MSG)
2445 DPRINT("Auto-detected floppy type %s in fd%d\n",
2446 _floppy->name, current_drive);
2447 current_type[current_drive] = _floppy;
2448 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2449 probing = 0;
2450 }
2451
2452 if (CT(COMMAND) != FD_READ ||
2453 raw_cmd->kernel_data == current_req->buffer) {
2454 /* transfer directly from buffer */
2455 cont->done(1);
2456 } else if (CT(COMMAND) == FD_READ) {
2457 buffer_track = raw_cmd->track;
2458 buffer_drive = current_drive;
2459 INFBOUND(buffer_max, nr_sectors + fsector_t);
2460 }
2461 cont->redo();
2462}
2463
2464/* Compute maximal contiguous buffer size. */
2465static int buffer_chain_size(void)
2466{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 struct bio_vec *bv;
NeilBrown5705f702007-09-25 12:35:59 +02002468 int size;
2469 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 char *base;
2471
2472 base = bio_data(current_req->bio);
2473 size = 0;
2474
NeilBrown5705f702007-09-25 12:35:59 +02002475 rq_for_each_segment(bv, current_req, iter) {
2476 if (page_address(bv->bv_page) + bv->bv_offset != base + size)
2477 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
NeilBrown5705f702007-09-25 12:35:59 +02002479 size += bv->bv_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 }
2481
2482 return size >> 9;
2483}
2484
2485/* Compute the maximal transfer size */
2486static int transfer_size(int ssize, int max_sector, int max_size)
2487{
2488 SUPBOUND(max_sector, fsector_t + max_size);
2489
2490 /* alignment */
2491 max_sector -= (max_sector % _floppy->sect) % ssize;
2492
2493 /* transfer size, beginning not aligned */
2494 current_count_sectors = max_sector - fsector_t;
2495
2496 return max_sector;
2497}
2498
2499/*
2500 * Move data from/to the track buffer to/from the buffer cache.
2501 */
2502static void copy_buffer(int ssize, int max_sector, int max_sector_2)
2503{
2504 int remaining; /* number of transferred 512-byte sectors */
2505 struct bio_vec *bv;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002506 char *buffer;
2507 char *dma_buffer;
NeilBrown5705f702007-09-25 12:35:59 +02002508 int size;
2509 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510
2511 max_sector = transfer_size(ssize,
2512 min(max_sector, max_sector_2),
Tejun Heo83096eb2009-05-07 22:24:39 +09002513 blk_rq_sectors(current_req));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
2515 if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
Tejun Heo83096eb2009-05-07 22:24:39 +09002516 buffer_max > fsector_t + blk_rq_sectors(current_req))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 current_count_sectors = min_t(int, buffer_max - fsector_t,
Tejun Heo83096eb2009-05-07 22:24:39 +09002518 blk_rq_sectors(current_req));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519
2520 remaining = current_count_sectors << 9;
2521#ifdef FLOPPY_SANITY_CHECK
Tejun Heo1011c1b2009-05-07 22:24:45 +09002522 if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 DPRINT("in copy buffer\n");
2524 printk("current_count_sectors=%ld\n", current_count_sectors);
2525 printk("remaining=%d\n", remaining >> 9);
Tejun Heo83096eb2009-05-07 22:24:39 +09002526 printk("current_req->nr_sectors=%u\n",
2527 blk_rq_sectors(current_req));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 printk("current_req->current_nr_sectors=%u\n",
Tejun Heo83096eb2009-05-07 22:24:39 +09002529 blk_rq_cur_sectors(current_req));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 printk("max_sector=%d\n", max_sector);
2531 printk("ssize=%d\n", ssize);
2532 }
2533#endif
2534
2535 buffer_max = max(max_sector, buffer_max);
2536
2537 dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
2538
Tejun Heo1011c1b2009-05-07 22:24:45 +09002539 size = blk_rq_cur_bytes(current_req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
NeilBrown5705f702007-09-25 12:35:59 +02002541 rq_for_each_segment(bv, current_req, iter) {
2542 if (!remaining)
2543 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
NeilBrown5705f702007-09-25 12:35:59 +02002545 size = bv->bv_len;
2546 SUPBOUND(size, remaining);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
NeilBrown5705f702007-09-25 12:35:59 +02002548 buffer = page_address(bv->bv_page) + bv->bv_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549#ifdef FLOPPY_SANITY_CHECK
NeilBrown5705f702007-09-25 12:35:59 +02002550 if (dma_buffer + size >
2551 floppy_track_buffer + (max_buffer_sectors << 10) ||
2552 dma_buffer < floppy_track_buffer) {
2553 DPRINT("buffer overrun in copy buffer %d\n",
2554 (int)((floppy_track_buffer -
2555 dma_buffer) >> 9));
2556 printk("fsector_t=%d buffer_min=%d\n",
2557 fsector_t, buffer_min);
2558 printk("current_count_sectors=%ld\n",
2559 current_count_sectors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 if (CT(COMMAND) == FD_READ)
NeilBrown5705f702007-09-25 12:35:59 +02002561 printk("read\n");
2562 if (CT(COMMAND) == FD_WRITE)
2563 printk("write\n");
2564 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 }
NeilBrown5705f702007-09-25 12:35:59 +02002566 if (((unsigned long)buffer) % 512)
2567 DPRINT("%p buffer not aligned\n", buffer);
2568#endif
2569 if (CT(COMMAND) == FD_READ)
2570 memcpy(buffer, dma_buffer, size);
2571 else
2572 memcpy(dma_buffer, buffer, size);
2573
2574 remaining -= size;
2575 dma_buffer += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 }
2577#ifdef FLOPPY_SANITY_CHECK
2578 if (remaining) {
2579 if (remaining > 0)
2580 max_sector -= remaining >> 9;
2581 DPRINT("weirdness: remaining %d\n", remaining >> 9);
2582 }
2583#endif
2584}
2585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586/* work around a bug in pseudo DMA
2587 * (on some FDCs) pseudo DMA does not stop when the CPU stops
2588 * sending data. Hence we need a different way to signal the
2589 * transfer length: We use SECT_PER_TRACK. Unfortunately, this
2590 * does not work with MT, hence we can only transfer one head at
2591 * a time
2592 */
2593static void virtualdmabug_workaround(void)
2594{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002595 int hard_sectors;
2596 int end_sector;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
2598 if (CT(COMMAND) == FD_WRITE) {
2599 COMMAND &= ~0x80; /* switch off multiple track mode */
2600
2601 hard_sectors = raw_cmd->length >> (7 + SIZECODE);
2602 end_sector = SECTOR + hard_sectors - 1;
2603#ifdef FLOPPY_SANITY_CHECK
2604 if (end_sector > SECT_PER_TRACK) {
2605 printk("too many sectors %d > %d\n",
2606 end_sector, SECT_PER_TRACK);
2607 return;
2608 }
2609#endif
Joe Perches48c8cee2010-03-10 15:20:45 -08002610 SECT_PER_TRACK = end_sector;
2611 /* make sure SECT_PER_TRACK
2612 * points to end of transfer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 }
2614}
2615
2616/*
2617 * Formulate a read/write request.
2618 * this routine decides where to load the data (directly to buffer, or to
2619 * tmp floppy area), how much data to load (the size of the buffer, the whole
2620 * track, or a single sector)
2621 * All floppy_track_buffer handling goes in here. If we ever add track buffer
2622 * allocation on the fly, it should be done here. No other part should need
2623 * modification.
2624 */
2625
2626static int make_raw_rw_request(void)
2627{
2628 int aligned_sector_t;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002629 int max_sector;
2630 int max_size;
2631 int tracksize;
2632 int ssize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
2634 if (max_buffer_sectors == 0) {
2635 printk("VFS: Block I/O scheduled on unopened device\n");
2636 return 0;
2637 }
2638
2639 set_fdc((long)current_req->rq_disk->private_data);
2640
2641 raw_cmd = &default_raw_cmd;
2642 raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
2643 FD_RAW_NEED_SEEK;
2644 raw_cmd->cmd_count = NR_RW;
2645 if (rq_data_dir(current_req) == READ) {
2646 raw_cmd->flags |= FD_RAW_READ;
2647 COMMAND = FM_MODE(_floppy, FD_READ);
2648 } else if (rq_data_dir(current_req) == WRITE) {
2649 raw_cmd->flags |= FD_RAW_WRITE;
2650 COMMAND = FM_MODE(_floppy, FD_WRITE);
2651 } else {
2652 DPRINT("make_raw_rw_request: unknown command\n");
2653 return 0;
2654 }
2655
2656 max_sector = _floppy->sect * _floppy->head;
2657
Tejun Heo83096eb2009-05-07 22:24:39 +09002658 TRACK = (int)blk_rq_pos(current_req) / max_sector;
2659 fsector_t = (int)blk_rq_pos(current_req) % max_sector;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 if (_floppy->track && TRACK >= _floppy->track) {
Tejun Heo83096eb2009-05-07 22:24:39 +09002661 if (blk_rq_cur_sectors(current_req) & 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 current_count_sectors = 1;
2663 return 1;
2664 } else
2665 return 0;
2666 }
2667 HEAD = fsector_t / _floppy->sect;
2668
Keith Wansbrough9e491842008-09-22 14:57:17 -07002669 if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
2671 max_sector = _floppy->sect;
2672
2673 /* 2M disks have phantom sectors on the first track */
2674 if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)) {
2675 max_sector = 2 * _floppy->sect / 3;
2676 if (fsector_t >= max_sector) {
2677 current_count_sectors =
2678 min_t(int, _floppy->sect - fsector_t,
Tejun Heo83096eb2009-05-07 22:24:39 +09002679 blk_rq_sectors(current_req));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 return 1;
2681 }
2682 SIZECODE = 2;
2683 } else
2684 SIZECODE = FD_SIZECODE(_floppy);
2685 raw_cmd->rate = _floppy->rate & 0x43;
2686 if ((_floppy->rate & FD_2M) && (TRACK || HEAD) && raw_cmd->rate == 2)
2687 raw_cmd->rate = 1;
2688
2689 if (SIZECODE)
2690 SIZECODE2 = 0xff;
2691 else
2692 SIZECODE2 = 0x80;
2693 raw_cmd->track = TRACK << STRETCH(_floppy);
2694 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD);
2695 GAP = _floppy->gap;
2696 CODE2SIZE;
2697 SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
2698 SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
Keith Wansbrough9e491842008-09-22 14:57:17 -07002699 FD_SECTBASE(_floppy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700
2701 /* tracksize describes the size which can be filled up with sectors
2702 * of size ssize.
2703 */
2704 tracksize = _floppy->sect - _floppy->sect % ssize;
2705 if (tracksize < _floppy->sect) {
2706 SECT_PER_TRACK++;
2707 if (tracksize <= fsector_t % _floppy->sect)
2708 SECTOR--;
2709
2710 /* if we are beyond tracksize, fill up using smaller sectors */
2711 while (tracksize <= fsector_t % _floppy->sect) {
2712 while (tracksize + ssize > _floppy->sect) {
2713 SIZECODE--;
2714 ssize >>= 1;
2715 }
2716 SECTOR++;
2717 SECT_PER_TRACK++;
2718 tracksize += ssize;
2719 }
2720 max_sector = HEAD * _floppy->sect + tracksize;
2721 } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) {
2722 max_sector = _floppy->sect;
2723 } else if (!HEAD && CT(COMMAND) == FD_WRITE) {
2724 /* for virtual DMA bug workaround */
2725 max_sector = _floppy->sect;
2726 }
2727
2728 in_sector_offset = (fsector_t % _floppy->sect) % ssize;
2729 aligned_sector_t = fsector_t - in_sector_offset;
Tejun Heo83096eb2009-05-07 22:24:39 +09002730 max_size = blk_rq_sectors(current_req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 if ((raw_cmd->track == buffer_track) &&
2732 (current_drive == buffer_drive) &&
2733 (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
2734 /* data already in track buffer */
2735 if (CT(COMMAND) == FD_READ) {
2736 copy_buffer(1, max_sector, buffer_max);
2737 return 1;
2738 }
Tejun Heo83096eb2009-05-07 22:24:39 +09002739 } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 if (CT(COMMAND) == FD_WRITE) {
Tejun Heo83096eb2009-05-07 22:24:39 +09002741 if (fsector_t + blk_rq_sectors(current_req) > ssize &&
2742 fsector_t + blk_rq_sectors(current_req) < ssize + ssize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 max_size = ssize + ssize;
2744 else
2745 max_size = ssize;
2746 }
2747 raw_cmd->flags &= ~FD_RAW_WRITE;
2748 raw_cmd->flags |= FD_RAW_READ;
2749 COMMAND = FM_MODE(_floppy, FD_READ);
2750 } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
2751 unsigned long dma_limit;
2752 int direct, indirect;
2753
2754 indirect =
2755 transfer_size(ssize, max_sector,
2756 max_buffer_sectors * 2) - fsector_t;
2757
2758 /*
2759 * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
2760 * on a 64 bit machine!
2761 */
2762 max_size = buffer_chain_size();
2763 dma_limit =
2764 (MAX_DMA_ADDRESS -
2765 ((unsigned long)current_req->buffer)) >> 9;
2766 if ((unsigned long)max_size > dma_limit) {
2767 max_size = dma_limit;
2768 }
2769 /* 64 kb boundaries */
2770 if (CROSS_64KB(current_req->buffer, max_size << 9))
2771 max_size = (K_64 -
2772 ((unsigned long)current_req->buffer) %
2773 K_64) >> 9;
2774 direct = transfer_size(ssize, max_sector, max_size) - fsector_t;
2775 /*
2776 * We try to read tracks, but if we get too many errors, we
2777 * go back to reading just one sector at a time.
2778 *
2779 * This means we should be able to read a sector even if there
2780 * are other bad sectors on this track.
2781 */
2782 if (!direct ||
2783 (indirect * 2 > direct * 3 &&
Jesper Juhlaee90412007-10-16 23:30:58 -07002784 *errors < DP->max_errors.read_track && ((!probing
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 || (DP->read_track & (1 << DRS->probed_format)))))) {
Tejun Heo83096eb2009-05-07 22:24:39 +09002786 max_size = blk_rq_sectors(current_req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 } else {
2788 raw_cmd->kernel_data = current_req->buffer;
2789 raw_cmd->length = current_count_sectors << 9;
2790 if (raw_cmd->length == 0) {
2791 DPRINT
2792 ("zero dma transfer attempted from make_raw_request\n");
2793 DPRINT("indirect=%d direct=%d fsector_t=%d",
2794 indirect, direct, fsector_t);
2795 return 0;
2796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 virtualdmabug_workaround();
2798 return 2;
2799 }
2800 }
2801
2802 if (CT(COMMAND) == FD_READ)
2803 max_size = max_sector; /* unbounded */
2804
2805 /* claim buffer track if needed */
2806 if (buffer_track != raw_cmd->track || /* bad track */
2807 buffer_drive != current_drive || /* bad drive */
2808 fsector_t > buffer_max ||
2809 fsector_t < buffer_min ||
2810 ((CT(COMMAND) == FD_READ ||
Tejun Heo83096eb2009-05-07 22:24:39 +09002811 (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 max_sector > 2 * max_buffer_sectors + buffer_min &&
2813 max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
2814 /* not enough space */
2815 ) {
2816 buffer_track = -1;
2817 buffer_drive = current_drive;
2818 buffer_max = buffer_min = aligned_sector_t;
2819 }
2820 raw_cmd->kernel_data = floppy_track_buffer +
2821 ((aligned_sector_t - buffer_min) << 9);
2822
2823 if (CT(COMMAND) == FD_WRITE) {
2824 /* copy write buffer to track buffer.
2825 * if we get here, we know that the write
2826 * is either aligned or the data already in the buffer
2827 * (buffer will be overwritten) */
2828#ifdef FLOPPY_SANITY_CHECK
2829 if (in_sector_offset && buffer_track == -1)
2830 DPRINT("internal error offset !=0 on write\n");
2831#endif
2832 buffer_track = raw_cmd->track;
2833 buffer_drive = current_drive;
2834 copy_buffer(ssize, max_sector,
2835 2 * max_buffer_sectors + buffer_min);
2836 } else
2837 transfer_size(ssize, max_sector,
2838 2 * max_buffer_sectors + buffer_min -
2839 aligned_sector_t);
2840
2841 /* round up current_count_sectors to get dma xfer size */
2842 raw_cmd->length = in_sector_offset + current_count_sectors;
2843 raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
2844 raw_cmd->length <<= 9;
2845#ifdef FLOPPY_SANITY_CHECK
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 if ((raw_cmd->length < current_count_sectors << 9) ||
2847 (raw_cmd->kernel_data != current_req->buffer &&
2848 CT(COMMAND) == FD_WRITE &&
2849 (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
2850 aligned_sector_t < buffer_min)) ||
2851 raw_cmd->length % (128 << SIZECODE) ||
2852 raw_cmd->length <= 0 || current_count_sectors <= 0) {
2853 DPRINT("fractionary current count b=%lx s=%lx\n",
2854 raw_cmd->length, current_count_sectors);
2855 if (raw_cmd->kernel_data != current_req->buffer)
2856 printk("addr=%d, length=%ld\n",
2857 (int)((raw_cmd->kernel_data -
2858 floppy_track_buffer) >> 9),
2859 current_count_sectors);
2860 printk("st=%d ast=%d mse=%d msi=%d\n",
2861 fsector_t, aligned_sector_t, max_sector, max_size);
2862 printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
2863 printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
2864 COMMAND, SECTOR, HEAD, TRACK);
2865 printk("buffer drive=%d\n", buffer_drive);
2866 printk("buffer track=%d\n", buffer_track);
2867 printk("buffer_min=%d\n", buffer_min);
2868 printk("buffer_max=%d\n", buffer_max);
2869 return 0;
2870 }
2871
2872 if (raw_cmd->kernel_data != current_req->buffer) {
2873 if (raw_cmd->kernel_data < floppy_track_buffer ||
2874 current_count_sectors < 0 ||
2875 raw_cmd->length < 0 ||
2876 raw_cmd->kernel_data + raw_cmd->length >
2877 floppy_track_buffer + (max_buffer_sectors << 10)) {
2878 DPRINT("buffer overrun in schedule dma\n");
2879 printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
2880 fsector_t, buffer_min, raw_cmd->length >> 9);
2881 printk("current_count_sectors=%ld\n",
2882 current_count_sectors);
2883 if (CT(COMMAND) == FD_READ)
2884 printk("read\n");
2885 if (CT(COMMAND) == FD_WRITE)
2886 printk("write\n");
2887 return 0;
2888 }
Tejun Heo1011c1b2009-05-07 22:24:45 +09002889 } else if (raw_cmd->length > blk_rq_bytes(current_req) ||
Tejun Heo83096eb2009-05-07 22:24:39 +09002890 current_count_sectors > blk_rq_sectors(current_req)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 DPRINT("buffer overrun in direct transfer\n");
2892 return 0;
2893 } else if (raw_cmd->length < current_count_sectors << 9) {
2894 DPRINT("more sectors than bytes\n");
2895 printk("bytes=%ld\n", raw_cmd->length >> 9);
2896 printk("sectors=%ld\n", current_count_sectors);
2897 }
2898 if (raw_cmd->length == 0) {
2899 DPRINT("zero dma transfer attempted from make_raw_request\n");
2900 return 0;
2901 }
2902#endif
2903
2904 virtualdmabug_workaround();
2905 return 2;
2906}
2907
2908static void redo_fd_request(void)
2909{
2910#define REPEAT {request_done(0); continue; }
2911 int drive;
2912 int tmp;
2913
2914 lastredo = jiffies;
2915 if (current_drive < N_DRIVE)
2916 floppy_off(current_drive);
2917
2918 for (;;) {
2919 if (!current_req) {
2920 struct request *req;
2921
2922 spin_lock_irq(floppy_queue->queue_lock);
Tejun Heo9934c8c2009-05-08 11:54:16 +09002923 req = blk_fetch_request(floppy_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 spin_unlock_irq(floppy_queue->queue_lock);
2925 if (!req) {
2926 do_floppy = NULL;
2927 unlock_fdc();
2928 return;
2929 }
2930 current_req = req;
2931 }
2932 drive = (long)current_req->rq_disk->private_data;
2933 set_fdc(drive);
2934 reschedule_timeout(current_reqD, "redo fd request", 0);
2935
2936 set_floppy(drive);
2937 raw_cmd = &default_raw_cmd;
2938 raw_cmd->flags = 0;
2939 if (start_motor(redo_fd_request))
2940 return;
2941 disk_change(current_drive);
2942 if (test_bit(current_drive, &fake_change) ||
2943 TESTF(FD_DISK_CHANGED)) {
2944 DPRINT("disk absent or changed during operation\n");
2945 REPEAT;
2946 }
2947 if (!_floppy) { /* Autodetection */
2948 if (!probing) {
2949 DRS->probed_format = 0;
2950 if (next_valid_format()) {
2951 DPRINT("no autodetectable formats\n");
2952 _floppy = NULL;
2953 REPEAT;
2954 }
2955 }
2956 probing = 1;
2957 _floppy =
2958 floppy_type + DP->autodetect[DRS->probed_format];
2959 } else
2960 probing = 0;
2961 errors = &(current_req->errors);
2962 tmp = make_raw_rw_request();
2963 if (tmp < 2) {
2964 request_done(tmp);
2965 continue;
2966 }
2967
2968 if (TESTF(FD_NEED_TWADDLE))
2969 twaddle();
2970 schedule_bh(floppy_start);
2971 debugt("queue fd request");
2972 return;
2973 }
2974#undef REPEAT
2975}
2976
2977static struct cont_t rw_cont = {
2978 .interrupt = rw_interrupt,
2979 .redo = redo_fd_request,
2980 .error = bad_flp_intr,
2981 .done = request_done
2982};
2983
2984static void process_fd_request(void)
2985{
2986 cont = &rw_cont;
2987 schedule_bh(redo_fd_request);
2988}
2989
Jens Axboe165125e2007-07-24 09:28:11 +02002990static void do_fd_request(struct request_queue * q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991{
2992 if (max_buffer_sectors == 0) {
2993 printk("VFS: do_fd_request called on non-open device\n");
2994 return;
2995 }
2996
2997 if (usage_count == 0) {
2998 printk("warning: usage count=0, current_req=%p exiting\n",
2999 current_req);
Tejun Heo83096eb2009-05-07 22:24:39 +09003000 printk("sect=%ld type=%x flags=%x\n",
3001 (long)blk_rq_pos(current_req), current_req->cmd_type,
3002 current_req->cmd_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 return;
3004 }
3005 if (test_bit(0, &fdc_busy)) {
3006 /* fdc busy, this new request will be treated when the
3007 current one is done */
3008 is_alive("do fd request, old request running");
3009 return;
3010 }
3011 lock_fdc(MAXTIMEOUT, 0);
3012 process_fd_request();
3013 is_alive("do fd request");
3014}
3015
3016static struct cont_t poll_cont = {
3017 .interrupt = success_and_wakeup,
3018 .redo = floppy_ready,
3019 .error = generic_failure,
3020 .done = generic_done
3021};
3022
3023static int poll_drive(int interruptible, int flag)
3024{
3025 int ret;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003026
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 /* no auto-sense, just clear dcl */
3028 raw_cmd = &default_raw_cmd;
3029 raw_cmd->flags = flag;
3030 raw_cmd->track = 0;
3031 raw_cmd->cmd_count = 0;
3032 cont = &poll_cont;
3033#ifdef DCL_DEBUG
3034 if (DP->flags & FD_DEBUG) {
3035 DPRINT("setting NEWCHANGE in poll_drive\n");
3036 }
3037#endif
3038 SETF(FD_DISK_NEWCHANGE);
3039 WAIT(floppy_ready);
3040 return ret;
3041}
3042
3043/*
3044 * User triggered reset
3045 * ====================
3046 */
3047
3048static void reset_intr(void)
3049{
3050 printk("weird, reset interrupt called\n");
3051}
3052
3053static struct cont_t reset_cont = {
3054 .interrupt = reset_intr,
3055 .redo = success_and_wakeup,
3056 .error = generic_failure,
3057 .done = generic_done
3058};
3059
3060static int user_reset_fdc(int drive, int arg, int interruptible)
3061{
3062 int ret;
3063
3064 ret = 0;
3065 LOCK_FDC(drive, interruptible);
3066 if (arg == FD_RESET_ALWAYS)
3067 FDCS->reset = 1;
3068 if (FDCS->reset) {
3069 cont = &reset_cont;
3070 WAIT(reset_fdc);
3071 }
3072 process_fd_request();
3073 return ret;
3074}
3075
3076/*
3077 * Misc Ioctl's and support
3078 * ========================
3079 */
3080static inline int fd_copyout(void __user *param, const void *address,
3081 unsigned long size)
3082{
3083 return copy_to_user(param, address, size) ? -EFAULT : 0;
3084}
3085
Joe Perches48c8cee2010-03-10 15:20:45 -08003086static inline int fd_copyin(void __user *param, void *address,
3087 unsigned long size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088{
3089 return copy_from_user(address, param, size) ? -EFAULT : 0;
3090}
3091
Joe Perches48c8cee2010-03-10 15:20:45 -08003092#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) \
3093 ? -EFAULT : 0)
3094#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) \
3095 ? -EFAULT : 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
Joe Perches48c8cee2010-03-10 15:20:45 -08003097#define COPYOUT(x) ECALL(_COPYOUT(x))
3098#define COPYIN(x) ECALL(_COPYIN(x))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
3100static inline const char *drive_name(int type, int drive)
3101{
3102 struct floppy_struct *floppy;
3103
3104 if (type)
3105 floppy = floppy_type + type;
3106 else {
3107 if (UDP->native_format)
3108 floppy = floppy_type + UDP->native_format;
3109 else
3110 return "(null)";
3111 }
3112 if (floppy->name)
3113 return floppy->name;
3114 else
3115 return "(null)";
3116}
3117
3118/* raw commands */
3119static void raw_cmd_done(int flag)
3120{
3121 int i;
3122
3123 if (!flag) {
3124 raw_cmd->flags |= FD_RAW_FAILURE;
3125 raw_cmd->flags |= FD_RAW_HARDFAILURE;
3126 } else {
3127 raw_cmd->reply_count = inr;
3128 if (raw_cmd->reply_count > MAX_REPLIES)
3129 raw_cmd->reply_count = 0;
3130 for (i = 0; i < raw_cmd->reply_count; i++)
3131 raw_cmd->reply[i] = reply_buffer[i];
3132
3133 if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3134 unsigned long flags;
3135 flags = claim_dma_lock();
3136 raw_cmd->length = fd_get_dma_residue();
3137 release_dma_lock(flags);
3138 }
3139
3140 if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
3141 (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
3142 raw_cmd->flags |= FD_RAW_FAILURE;
3143
3144 if (disk_change(current_drive))
3145 raw_cmd->flags |= FD_RAW_DISK_CHANGE;
3146 else
3147 raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
3148 if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
3149 motor_off_callback(current_drive);
3150
3151 if (raw_cmd->next &&
3152 (!(raw_cmd->flags & FD_RAW_FAILURE) ||
3153 !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
3154 ((raw_cmd->flags & FD_RAW_FAILURE) ||
3155 !(raw_cmd->flags & FD_RAW_STOP_IF_SUCCESS))) {
3156 raw_cmd = raw_cmd->next;
3157 return;
3158 }
3159 }
3160 generic_done(flag);
3161}
3162
3163static struct cont_t raw_cmd_cont = {
3164 .interrupt = success_and_wakeup,
3165 .redo = floppy_start,
3166 .error = generic_failure,
3167 .done = raw_cmd_done
3168};
3169
3170static inline int raw_cmd_copyout(int cmd, char __user *param,
3171 struct floppy_raw_cmd *ptr)
3172{
3173 int ret;
3174
3175 while (ptr) {
3176 COPYOUT(*ptr);
3177 param += sizeof(struct floppy_raw_cmd);
3178 if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) {
3179 if (ptr->length >= 0
3180 && ptr->length <= ptr->buffer_length)
3181 ECALL(fd_copyout
3182 (ptr->data, ptr->kernel_data,
3183 ptr->buffer_length - ptr->length));
3184 }
3185 ptr = ptr->next;
3186 }
3187 return 0;
3188}
3189
3190static void raw_cmd_free(struct floppy_raw_cmd **ptr)
3191{
Jesper Juhl06f748c2007-10-16 23:30:57 -07003192 struct floppy_raw_cmd *next;
3193 struct floppy_raw_cmd *this;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
3195 this = *ptr;
3196 *ptr = NULL;
3197 while (this) {
3198 if (this->buffer_length) {
3199 fd_dma_mem_free((unsigned long)this->kernel_data,
3200 this->buffer_length);
3201 this->buffer_length = 0;
3202 }
3203 next = this->next;
3204 kfree(this);
3205 this = next;
3206 }
3207}
3208
3209static inline int raw_cmd_copyin(int cmd, char __user *param,
3210 struct floppy_raw_cmd **rcmd)
3211{
3212 struct floppy_raw_cmd *ptr;
3213 int ret;
3214 int i;
3215
3216 *rcmd = NULL;
3217 while (1) {
3218 ptr = (struct floppy_raw_cmd *)
3219 kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
3220 if (!ptr)
3221 return -ENOMEM;
3222 *rcmd = ptr;
3223 COPYIN(*ptr);
3224 ptr->next = NULL;
3225 ptr->buffer_length = 0;
3226 param += sizeof(struct floppy_raw_cmd);
3227 if (ptr->cmd_count > 33)
3228 /* the command may now also take up the space
3229 * initially intended for the reply & the
3230 * reply count. Needed for long 82078 commands
3231 * such as RESTORE, which takes ... 17 command
3232 * bytes. Murphy's law #137: When you reserve
3233 * 16 bytes for a structure, you'll one day
3234 * discover that you really need 17...
3235 */
3236 return -EINVAL;
3237
3238 for (i = 0; i < 16; i++)
3239 ptr->reply[i] = 0;
3240 ptr->resultcode = 0;
3241 ptr->kernel_data = NULL;
3242
3243 if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3244 if (ptr->length <= 0)
3245 return -EINVAL;
3246 ptr->kernel_data =
3247 (char *)fd_dma_mem_alloc(ptr->length);
3248 fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
3249 if (!ptr->kernel_data)
3250 return -ENOMEM;
3251 ptr->buffer_length = ptr->length;
3252 }
3253 if (ptr->flags & FD_RAW_WRITE)
3254 ECALL(fd_copyin(ptr->data, ptr->kernel_data,
3255 ptr->length));
3256 rcmd = &(ptr->next);
3257 if (!(ptr->flags & FD_RAW_MORE))
3258 return 0;
3259 ptr->rate &= 0x43;
3260 }
3261}
3262
3263static int raw_cmd_ioctl(int cmd, void __user *param)
3264{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 struct floppy_raw_cmd *my_raw_cmd;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003266 int drive;
3267 int ret2;
3268 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
3270 if (FDCS->rawcmd <= 1)
3271 FDCS->rawcmd = 1;
3272 for (drive = 0; drive < N_DRIVE; drive++) {
3273 if (FDC(drive) != fdc)
3274 continue;
3275 if (drive == current_drive) {
3276 if (UDRS->fd_ref > 1) {
3277 FDCS->rawcmd = 2;
3278 break;
3279 }
3280 } else if (UDRS->fd_ref) {
3281 FDCS->rawcmd = 2;
3282 break;
3283 }
3284 }
3285
3286 if (FDCS->reset)
3287 return -EIO;
3288
3289 ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
3290 if (ret) {
3291 raw_cmd_free(&my_raw_cmd);
3292 return ret;
3293 }
3294
3295 raw_cmd = my_raw_cmd;
3296 cont = &raw_cmd_cont;
3297 ret = wait_til_done(floppy_start, 1);
3298#ifdef DCL_DEBUG
3299 if (DP->flags & FD_DEBUG) {
3300 DPRINT("calling disk change from raw_cmd ioctl\n");
3301 }
3302#endif
3303
3304 if (ret != -EINTR && FDCS->reset)
3305 ret = -EIO;
3306
3307 DRS->track = NO_TRACK;
3308
3309 ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
3310 if (!ret)
3311 ret = ret2;
3312 raw_cmd_free(&my_raw_cmd);
3313 return ret;
3314}
3315
3316static int invalidate_drive(struct block_device *bdev)
3317{
3318 /* invalidate the buffer track to force a reread */
3319 set_bit((long)bdev->bd_disk->private_data, &fake_change);
3320 process_fd_request();
3321 check_disk_change(bdev);
3322 return 0;
3323}
3324
3325static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
3326 int drive, int type, struct block_device *bdev)
3327{
3328 int cnt;
3329
3330 /* sanity checking for parameters. */
3331 if (g->sect <= 0 ||
3332 g->head <= 0 ||
3333 g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
3334 /* check if reserved bits are set */
Keith Wansbrough9e491842008-09-22 14:57:17 -07003335 (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 return -EINVAL;
3337 if (type) {
3338 if (!capable(CAP_SYS_ADMIN))
3339 return -EPERM;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003340 mutex_lock(&open_lock);
Jiri Slaby8516a502009-06-30 11:41:44 -07003341 if (lock_fdc(drive, 1)) {
3342 mutex_unlock(&open_lock);
3343 return -EINTR;
3344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 floppy_type[type] = *g;
3346 floppy_type[type].name = "user format";
3347 for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
3348 floppy_sizes[cnt] = floppy_sizes[cnt + 0x80] =
3349 floppy_type[type].size + 1;
3350 process_fd_request();
3351 for (cnt = 0; cnt < N_DRIVE; cnt++) {
3352 struct block_device *bdev = opened_bdev[cnt];
3353 if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
3354 continue;
Christoph Hellwig2ef41632005-05-05 16:15:59 -07003355 __invalidate_device(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003357 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 } else {
3359 int oldStretch;
3360 LOCK_FDC(drive, 1);
3361 if (cmd != FDDEFPRM)
3362 /* notice a disk change immediately, else
3363 * we lose our settings immediately*/
3364 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3365 oldStretch = g->stretch;
3366 user_params[drive] = *g;
3367 if (buffer_drive == drive)
3368 SUPBOUND(buffer_max, user_params[drive].sect);
3369 current_type[drive] = &user_params[drive];
3370 floppy_sizes[drive] = user_params[drive].size;
3371 if (cmd == FDDEFPRM)
3372 DRS->keep_data = -1;
3373 else
3374 DRS->keep_data = 1;
3375 /* invalidation. Invalidate only when needed, i.e.
3376 * when there are already sectors in the buffer cache
3377 * whose number will change. This is useful, because
3378 * mtools often changes the geometry of the disk after
3379 * looking at the boot block */
3380 if (DRS->maxblock > user_params[drive].sect ||
3381 DRS->maxtrack ||
3382 ((user_params[drive].sect ^ oldStretch) &
Keith Wansbrough9e491842008-09-22 14:57:17 -07003383 (FD_SWAPSIDES | FD_SECTBASEMASK)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384 invalidate_drive(bdev);
3385 else
3386 process_fd_request();
3387 }
3388 return 0;
3389}
3390
3391/* handle obsolete ioctl's */
3392static int ioctl_table[] = {
3393 FDCLRPRM,
3394 FDSETPRM,
3395 FDDEFPRM,
3396 FDGETPRM,
3397 FDMSGON,
3398 FDMSGOFF,
3399 FDFMTBEG,
3400 FDFMTTRK,
3401 FDFMTEND,
3402 FDSETEMSGTRESH,
3403 FDFLUSH,
3404 FDSETMAXERRS,
3405 FDGETMAXERRS,
3406 FDGETDRVTYP,
3407 FDSETDRVPRM,
3408 FDGETDRVPRM,
3409 FDGETDRVSTAT,
3410 FDPOLLDRVSTAT,
3411 FDRESET,
3412 FDGETFDCSTAT,
3413 FDWERRORCLR,
3414 FDWERRORGET,
3415 FDRAWCMD,
3416 FDEJECT,
3417 FDTWADDLE
3418};
3419
3420static inline int normalize_ioctl(int *cmd, int *size)
3421{
3422 int i;
3423
3424 for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) {
3425 if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)) {
3426 *size = _IOC_SIZE(*cmd);
3427 *cmd = ioctl_table[i];
3428 if (*size > _IOC_SIZE(*cmd)) {
3429 printk("ioctl not yet supported\n");
3430 return -EFAULT;
3431 }
3432 return 0;
3433 }
3434 }
3435 return -EINVAL;
3436}
3437
3438static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
3439{
3440 if (type)
3441 *g = &floppy_type[type];
3442 else {
3443 LOCK_FDC(drive, 0);
3444 CALL(poll_drive(0, 0));
3445 process_fd_request();
3446 *g = current_type[drive];
3447 }
3448 if (!*g)
3449 return -ENODEV;
3450 return 0;
3451}
3452
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08003453static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3454{
3455 int drive = (long)bdev->bd_disk->private_data;
3456 int type = ITYPE(drive_state[drive].fd_device);
3457 struct floppy_struct *g;
3458 int ret;
3459
3460 ret = get_floppy_geometry(drive, type, &g);
3461 if (ret)
3462 return ret;
3463
3464 geo->heads = g->head;
3465 geo->sectors = g->sect;
3466 geo->cylinders = g->track;
3467 return 0;
3468}
3469
Al Viroa4af9b42008-03-02 09:27:55 -05003470static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471 unsigned long param)
3472{
Al Viroa4af9b42008-03-02 09:27:55 -05003473#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474#define OUT(c,x) case c: outparam = (const char *) (x); break
3475#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
3476
Al Viroa4af9b42008-03-02 09:27:55 -05003477 int drive = (long)bdev->bd_disk->private_data;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003478 int type = ITYPE(UDRS->fd_device);
3479 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003480 int ret;
3481 int size;
3482 union inparam {
3483 struct floppy_struct g; /* geometry */
3484 struct format_descr f;
3485 struct floppy_max_errors max_errors;
3486 struct floppy_drive_params dp;
3487 } inparam; /* parameters coming from user space */
3488 const char *outparam; /* parameters passed back to user space */
3489
3490 /* convert compatibility eject ioctls into floppy eject ioctl.
3491 * We do this in order to provide a means to eject floppy disks before
3492 * installing the new fdutils package */
3493 if (cmd == CDROMEJECT || /* CD-ROM eject */
3494 cmd == 0x6470 /* SunOS floppy eject */ ) {
3495 DPRINT("obsolete eject ioctl\n");
3496 DPRINT("please use floppycontrol --eject\n");
3497 cmd = FDEJECT;
3498 }
3499
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 /* convert the old style command into a new style command */
3501 if ((cmd & 0xff00) == 0x0200) {
3502 ECALL(normalize_ioctl(&cmd, &size));
3503 } else
3504 return -EINVAL;
3505
3506 /* permission checks */
3507 if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
3508 ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
3509 return -EPERM;
3510
Arjan van de Ven2886a8b2009-12-14 18:00:11 -08003511 if (WARN_ON(size < 0 || size > sizeof(inparam)))
3512 return -EINVAL;
3513
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 /* copyin */
3515 CLEARSTRUCT(&inparam);
3516 if (_IOC_DIR(cmd) & _IOC_WRITE)
3517 ECALL(fd_copyin((void __user *)param, &inparam, size))
3518
3519 switch (cmd) {
3520 case FDEJECT:
3521 if (UDRS->fd_ref != 1)
3522 /* somebody else has this drive open */
3523 return -EBUSY;
3524 LOCK_FDC(drive, 1);
3525
3526 /* do the actual eject. Fails on
3527 * non-Sparc architectures */
3528 ret = fd_eject(UNIT(drive));
3529
3530 USETF(FD_DISK_CHANGED);
3531 USETF(FD_VERIFY);
3532 process_fd_request();
3533 return ret;
3534 case FDCLRPRM:
3535 LOCK_FDC(drive, 1);
3536 current_type[drive] = NULL;
3537 floppy_sizes[drive] = MAX_DISK_SIZE << 1;
3538 UDRS->keep_data = 0;
Al Viroa4af9b42008-03-02 09:27:55 -05003539 return invalidate_drive(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540 case FDSETPRM:
3541 case FDDEFPRM:
3542 return set_geometry(cmd, &inparam.g,
Al Viroa4af9b42008-03-02 09:27:55 -05003543 drive, type, bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 case FDGETPRM:
3545 ECALL(get_floppy_geometry(drive, type,
3546 (struct floppy_struct **)
3547 &outparam));
3548 break;
3549
3550 case FDMSGON:
3551 UDP->flags |= FTD_MSG;
3552 return 0;
3553 case FDMSGOFF:
3554 UDP->flags &= ~FTD_MSG;
3555 return 0;
3556
3557 case FDFMTBEG:
3558 LOCK_FDC(drive, 1);
3559 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3560 ret = UDRS->flags;
3561 process_fd_request();
3562 if (ret & FD_VERIFY)
3563 return -ENODEV;
3564 if (!(ret & FD_DISK_WRITABLE))
3565 return -EROFS;
3566 return 0;
3567 case FDFMTTRK:
3568 if (UDRS->fd_ref != 1)
3569 return -EBUSY;
3570 return do_format(drive, &inparam.f);
3571 case FDFMTEND:
3572 case FDFLUSH:
3573 LOCK_FDC(drive, 1);
Al Viroa4af9b42008-03-02 09:27:55 -05003574 return invalidate_drive(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003575
3576 case FDSETEMSGTRESH:
3577 UDP->max_errors.reporting =
3578 (unsigned short)(param & 0x0f);
3579 return 0;
3580 OUT(FDGETMAXERRS, &UDP->max_errors);
3581 IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
3582
3583 case FDGETDRVTYP:
3584 outparam = drive_name(type, drive);
3585 SUPBOUND(size, strlen(outparam) + 1);
3586 break;
3587
3588 IN(FDSETDRVPRM, UDP, dp);
3589 OUT(FDGETDRVPRM, UDP);
3590
3591 case FDPOLLDRVSTAT:
3592 LOCK_FDC(drive, 1);
3593 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3594 process_fd_request();
3595 /* fall through */
3596 OUT(FDGETDRVSTAT, UDRS);
3597
3598 case FDRESET:
3599 return user_reset_fdc(drive, (int)param, 1);
3600
3601 OUT(FDGETFDCSTAT, UFDCS);
3602
3603 case FDWERRORCLR:
3604 CLEARSTRUCT(UDRWE);
3605 return 0;
3606 OUT(FDWERRORGET, UDRWE);
3607
3608 case FDRAWCMD:
3609 if (type)
3610 return -EINVAL;
3611 LOCK_FDC(drive, 1);
3612 set_floppy(drive);
3613 CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
3614 process_fd_request();
3615 return i;
3616
3617 case FDTWADDLE:
3618 LOCK_FDC(drive, 1);
3619 twaddle();
3620 process_fd_request();
3621 return 0;
3622
3623 default:
3624 return -EINVAL;
3625 }
3626
3627 if (_IOC_DIR(cmd) & _IOC_READ)
3628 return fd_copyout((void __user *)param, outparam, size);
3629 else
3630 return 0;
3631#undef OUT
3632#undef IN
3633}
3634
3635static void __init config_types(void)
3636{
3637 int first = 1;
3638 int drive;
3639
3640 /* read drive info out of physical CMOS */
3641 drive = 0;
3642 if (!UDP->cmos)
3643 UDP->cmos = FLOPPY0_TYPE;
3644 drive = 1;
3645 if (!UDP->cmos && FLOPPY1_TYPE)
3646 UDP->cmos = FLOPPY1_TYPE;
3647
Jesper Juhl06f748c2007-10-16 23:30:57 -07003648 /* FIXME: additional physical CMOS drive detection should go here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649
3650 for (drive = 0; drive < N_DRIVE; drive++) {
3651 unsigned int type = UDP->cmos;
3652 struct floppy_drive_params *params;
3653 const char *name = NULL;
3654 static char temparea[32];
3655
Tobias Klauser945f3902006-01-08 01:05:11 -08003656 if (type < ARRAY_SIZE(default_drive_params)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657 params = &default_drive_params[type].params;
3658 if (type) {
3659 name = default_drive_params[type].name;
3660 allowed_drive_mask |= 1 << drive;
3661 } else
3662 allowed_drive_mask &= ~(1 << drive);
3663 } else {
3664 params = &default_drive_params[0].params;
3665 sprintf(temparea, "unknown type %d (usb?)", type);
3666 name = temparea;
3667 }
3668 if (name) {
3669 const char *prepend = ",";
3670 if (first) {
3671 prepend = KERN_INFO "Floppy drive(s):";
3672 first = 0;
3673 }
3674 printk("%s fd%d is %s", prepend, drive, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 }
3676 *UDP = *params;
3677 }
3678 if (!first)
3679 printk("\n");
3680}
3681
Al Viroa4af9b42008-03-02 09:27:55 -05003682static int floppy_release(struct gendisk *disk, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683{
Al Viroa4af9b42008-03-02 09:27:55 -05003684 int drive = (long)disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003686 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 if (UDRS->fd_ref < 0)
3688 UDRS->fd_ref = 0;
3689 else if (!UDRS->fd_ref--) {
3690 DPRINT("floppy_release with fd_ref == 0");
3691 UDRS->fd_ref = 0;
3692 }
3693 if (!UDRS->fd_ref)
3694 opened_bdev[drive] = NULL;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003695 mutex_unlock(&open_lock);
Ingo Molnar3e541a42006-07-03 00:24:23 -07003696
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697 return 0;
3698}
3699
3700/*
3701 * floppy_open check for aliasing (/dev/fd0 can be the same as
3702 * /dev/PS0 etc), and disallows simultaneous access to the same
3703 * drive with different device numbers.
3704 */
Al Viroa4af9b42008-03-02 09:27:55 -05003705static int floppy_open(struct block_device *bdev, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706{
Al Viroa4af9b42008-03-02 09:27:55 -05003707 int drive = (long)bdev->bd_disk->private_data;
3708 int old_dev, new_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 int try;
3710 int res = -EBUSY;
3711 char *tmp;
3712
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003713 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 old_dev = UDRS->fd_device;
Al Viroa4af9b42008-03-02 09:27:55 -05003715 if (opened_bdev[drive] && opened_bdev[drive] != bdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 goto out2;
3717
3718 if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
3719 USETF(FD_DISK_CHANGED);
3720 USETF(FD_VERIFY);
3721 }
3722
Al Viroa4af9b42008-03-02 09:27:55 -05003723 if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 goto out2;
3725
Al Viroa4af9b42008-03-02 09:27:55 -05003726 if (mode & FMODE_EXCL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 UDRS->fd_ref = -1;
3728 else
3729 UDRS->fd_ref++;
3730
Al Viroa4af9b42008-03-02 09:27:55 -05003731 opened_bdev[drive] = bdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732
3733 res = -ENXIO;
3734
3735 if (!floppy_track_buffer) {
3736 /* if opening an ED drive, reserve a big buffer,
3737 * else reserve a small one */
3738 if ((UDP->cmos == 6) || (UDP->cmos == 5))
3739 try = 64; /* Only 48 actually useful */
3740 else
3741 try = 32; /* Only 24 actually useful */
3742
3743 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3744 if (!tmp && !floppy_track_buffer) {
3745 try >>= 1; /* buffer only one side */
3746 INFBOUND(try, 16);
3747 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3748 }
3749 if (!tmp && !floppy_track_buffer) {
3750 fallback_on_nodma_alloc(&tmp, 2048 * try);
3751 }
3752 if (!tmp && !floppy_track_buffer) {
3753 DPRINT("Unable to allocate DMA memory\n");
3754 goto out;
3755 }
3756 if (floppy_track_buffer) {
3757 if (tmp)
3758 fd_dma_mem_free((unsigned long)tmp, try * 1024);
3759 } else {
3760 buffer_min = buffer_max = -1;
3761 floppy_track_buffer = tmp;
3762 max_buffer_sectors = try;
3763 }
3764 }
3765
Al Viroa4af9b42008-03-02 09:27:55 -05003766 new_dev = MINOR(bdev->bd_dev);
3767 UDRS->fd_device = new_dev;
3768 set_capacity(disks[drive], floppy_sizes[new_dev]);
3769 if (old_dev != -1 && old_dev != new_dev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770 if (buffer_drive == drive)
3771 buffer_track = -1;
3772 }
3773
Linus Torvalds1da177e2005-04-16 15:20:36 -07003774 if (UFDCS->rawcmd == 1)
3775 UFDCS->rawcmd = 2;
3776
Al Viroa4af9b42008-03-02 09:27:55 -05003777 if (!(mode & FMODE_NDELAY)) {
3778 if (mode & (FMODE_READ|FMODE_WRITE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 UDRS->last_checked = 0;
Al Viroa4af9b42008-03-02 09:27:55 -05003780 check_disk_change(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 if (UTESTF(FD_DISK_CHANGED))
3782 goto out;
3783 }
3784 res = -EROFS;
Al Viroa4af9b42008-03-02 09:27:55 -05003785 if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786 goto out;
3787 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003788 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789 return 0;
3790out:
3791 if (UDRS->fd_ref < 0)
3792 UDRS->fd_ref = 0;
3793 else
3794 UDRS->fd_ref--;
3795 if (!UDRS->fd_ref)
3796 opened_bdev[drive] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797out2:
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003798 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799 return res;
3800}
3801
3802/*
3803 * Check if the disk has been changed or if a change has been faked.
3804 */
3805static int check_floppy_change(struct gendisk *disk)
3806{
3807 int drive = (long)disk->private_data;
3808
3809 if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
3810 return 1;
3811
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08003812 if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 lock_fdc(drive, 0);
3814 poll_drive(0, 0);
3815 process_fd_request();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 }
3817
3818 if (UTESTF(FD_DISK_CHANGED) ||
3819 UTESTF(FD_VERIFY) ||
3820 test_bit(drive, &fake_change) ||
3821 (!ITYPE(UDRS->fd_device) && !current_type[drive]))
3822 return 1;
3823 return 0;
3824}
3825
3826/*
3827 * This implements "read block 0" for floppy_revalidate().
3828 * Needed for format autodetection, checking whether there is
3829 * a disk in the drive, and whether that disk is writable.
3830 */
3831
NeilBrown6712ecf2007-09-27 12:47:43 +02003832static void floppy_rb0_complete(struct bio *bio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833 int err)
3834{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835 complete((struct completion *)bio->bi_private);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836}
3837
3838static int __floppy_read_block_0(struct block_device *bdev)
3839{
3840 struct bio bio;
3841 struct bio_vec bio_vec;
3842 struct completion complete;
3843 struct page *page;
3844 size_t size;
3845
3846 page = alloc_page(GFP_NOIO);
3847 if (!page) {
3848 process_fd_request();
3849 return -ENOMEM;
3850 }
3851
3852 size = bdev->bd_block_size;
3853 if (!size)
3854 size = 1024;
3855
3856 bio_init(&bio);
3857 bio.bi_io_vec = &bio_vec;
3858 bio_vec.bv_page = page;
3859 bio_vec.bv_len = size;
3860 bio_vec.bv_offset = 0;
3861 bio.bi_vcnt = 1;
3862 bio.bi_idx = 0;
3863 bio.bi_size = size;
3864 bio.bi_bdev = bdev;
3865 bio.bi_sector = 0;
3866 init_completion(&complete);
3867 bio.bi_private = &complete;
3868 bio.bi_end_io = floppy_rb0_complete;
3869
3870 submit_bio(READ, &bio);
3871 generic_unplug_device(bdev_get_queue(bdev));
3872 process_fd_request();
3873 wait_for_completion(&complete);
3874
3875 __free_page(page);
3876
3877 return 0;
3878}
3879
3880/* revalidate the floppy disk, i.e. trigger format autodetection by reading
3881 * the bootblock (block 0). "Autodetection" is also needed to check whether
3882 * there is a disk in the drive at all... Thus we also do it for fixed
3883 * geometry formats */
3884static int floppy_revalidate(struct gendisk *disk)
3885{
3886 int drive = (long)disk->private_data;
3887#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
3888 int cf;
3889 int res = 0;
3890
3891 if (UTESTF(FD_DISK_CHANGED) ||
3892 UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) {
3893 if (usage_count == 0) {
3894 printk("VFS: revalidate called on non-open device.\n");
3895 return -EFAULT;
3896 }
3897 lock_fdc(drive, 0);
3898 cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
3899 if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
3900 process_fd_request(); /*already done by another thread */
3901 return 0;
3902 }
3903 UDRS->maxblock = 0;
3904 UDRS->maxtrack = 0;
3905 if (buffer_drive == drive)
3906 buffer_track = -1;
3907 clear_bit(drive, &fake_change);
3908 UCLEARF(FD_DISK_CHANGED);
3909 if (cf)
3910 UDRS->generation++;
3911 if (NO_GEOM) {
3912 /* auto-sensing */
3913 res = __floppy_read_block_0(opened_bdev[drive]);
3914 } else {
3915 if (cf)
3916 poll_drive(0, FD_RAW_NEED_DISK);
3917 process_fd_request();
3918 }
3919 }
3920 set_capacity(disk, floppy_sizes[UDRS->fd_device]);
3921 return res;
3922}
3923
Alexey Dobriyan83d5cde2009-09-21 17:01:13 -07003924static const struct block_device_operations floppy_fops = {
Jesper Juhl06f748c2007-10-16 23:30:57 -07003925 .owner = THIS_MODULE,
Al Viroa4af9b42008-03-02 09:27:55 -05003926 .open = floppy_open,
3927 .release = floppy_release,
3928 .locked_ioctl = fd_ioctl,
Jesper Juhl06f748c2007-10-16 23:30:57 -07003929 .getgeo = fd_getgeo,
3930 .media_changed = check_floppy_change,
3931 .revalidate_disk = floppy_revalidate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003933
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934/*
3935 * Floppy Driver initialization
3936 * =============================
3937 */
3938
3939/* Determine the floppy disk controller type */
3940/* This routine was written by David C. Niemi */
3941static char __init get_fdc_version(void)
3942{
3943 int r;
3944
3945 output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */
3946 if (FDCS->reset)
3947 return FDC_NONE;
3948 if ((r = result()) <= 0x00)
3949 return FDC_NONE; /* No FDC present ??? */
3950 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3951 printk(KERN_INFO "FDC %d is an 8272A\n", fdc);
3952 return FDC_8272A; /* 8272a/765 don't know DUMPREGS */
3953 }
3954 if (r != 10) {
3955 printk
3956 ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
3957 fdc, r);
3958 return FDC_UNKNOWN;
3959 }
3960
3961 if (!fdc_configure()) {
3962 printk(KERN_INFO "FDC %d is an 82072\n", fdc);
3963 return FDC_82072; /* 82072 doesn't know CONFIGURE */
3964 }
3965
3966 output_byte(FD_PERPENDICULAR);
3967 if (need_more_output() == MORE_OUTPUT) {
3968 output_byte(0);
3969 } else {
3970 printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
3971 return FDC_82072A; /* 82072A as found on Sparcs. */
3972 }
3973
3974 output_byte(FD_UNLOCK);
3975 r = result();
3976 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3977 printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc);
3978 return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know
3979 * LOCK/UNLOCK */
3980 }
3981 if ((r != 1) || (reply_buffer[0] != 0x00)) {
3982 printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
3983 fdc, r);
3984 return FDC_UNKNOWN;
3985 }
3986 output_byte(FD_PARTID);
3987 r = result();
3988 if (r != 1) {
3989 printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
3990 fdc, r);
3991 return FDC_UNKNOWN;
3992 }
3993 if (reply_buffer[0] == 0x80) {
3994 printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc);
3995 return FDC_82077; /* Revised 82077AA passes all the tests */
3996 }
3997 switch (reply_buffer[0] >> 5) {
3998 case 0x0:
3999 /* Either a 82078-1 or a 82078SL running at 5Volt */
4000 printk(KERN_INFO "FDC %d is an 82078.\n", fdc);
4001 return FDC_82078;
4002 case 0x1:
4003 printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc);
4004 return FDC_82078;
4005 case 0x2:
4006 printk(KERN_INFO "FDC %d is a S82078B\n", fdc);
4007 return FDC_S82078B;
4008 case 0x3:
4009 printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n",
4010 fdc);
4011 return FDC_87306;
4012 default:
4013 printk(KERN_INFO
4014 "FDC %d init: 82078 variant with unknown PARTID=%d.\n",
4015 fdc, reply_buffer[0] >> 5);
4016 return FDC_82078_UNKN;
4017 }
4018} /* get_fdc_version */
4019
4020/* lilo configuration */
4021
4022static void __init floppy_set_flags(int *ints, int param, int param2)
4023{
4024 int i;
4025
4026 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4027 if (param)
4028 default_drive_params[i].params.flags |= param2;
4029 else
4030 default_drive_params[i].params.flags &= ~param2;
4031 }
4032 DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param);
4033}
4034
4035static void __init daring(int *ints, int param, int param2)
4036{
4037 int i;
4038
4039 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4040 if (param) {
4041 default_drive_params[i].params.select_delay = 0;
4042 default_drive_params[i].params.flags |=
4043 FD_SILENT_DCL_CLEAR;
4044 } else {
4045 default_drive_params[i].params.select_delay =
4046 2 * HZ / 100;
4047 default_drive_params[i].params.flags &=
4048 ~FD_SILENT_DCL_CLEAR;
4049 }
4050 }
4051 DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken");
4052}
4053
4054static void __init set_cmos(int *ints, int dummy, int dummy2)
4055{
4056 int current_drive = 0;
4057
4058 if (ints[0] != 2) {
4059 DPRINT("wrong number of parameters for CMOS\n");
4060 return;
4061 }
4062 current_drive = ints[1];
4063 if (current_drive < 0 || current_drive >= 8) {
4064 DPRINT("bad drive for set_cmos\n");
4065 return;
4066 }
4067#if N_FDC > 1
4068 if (current_drive >= 4 && !FDC2)
4069 FDC2 = 0x370;
4070#endif
4071 DP->cmos = ints[2];
4072 DPRINT("setting CMOS code to %d\n", ints[2]);
4073}
4074
4075static struct param_table {
4076 const char *name;
4077 void (*fn) (int *ints, int param, int param2);
4078 int *var;
4079 int def_param;
4080 int param2;
4081} config_params[] __initdata = {
4082 {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4083 {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4084 {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0},
4085 {"irq", NULL, &FLOPPY_IRQ, 6, 0},
4086 {"dma", NULL, &FLOPPY_DMA, 2, 0},
4087 {"daring", daring, NULL, 1, 0},
4088#if N_FDC > 1
4089 {"two_fdc", NULL, &FDC2, 0x370, 0},
4090 {"one_fdc", NULL, &FDC2, 0, 0},
4091#endif
4092 {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL},
4093 {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL},
4094 {"messages", floppy_set_flags, NULL, 1, FTD_MSG},
4095 {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR},
4096 {"debug", floppy_set_flags, NULL, 1, FD_DEBUG},
4097 {"nodma", NULL, &can_use_virtual_dma, 1, 0},
4098 {"omnibook", NULL, &can_use_virtual_dma, 1, 0},
4099 {"yesdma", NULL, &can_use_virtual_dma, 0, 0},
4100 {"fifo_depth", NULL, &fifo_depth, 0xa, 0},
4101 {"nofifo", NULL, &no_fifo, 0x20, 0},
4102 {"usefifo", NULL, &no_fifo, 0, 0},
4103 {"cmos", set_cmos, NULL, 0, 0},
4104 {"slow", NULL, &slow_floppy, 1, 0},
4105 {"unexpected_interrupts", NULL, &print_unex, 1, 0},
4106 {"no_unexpected_interrupts", NULL, &print_unex, 0, 0},
4107 {"L40SX", NULL, &print_unex, 0, 0}
4108
4109 EXTRA_FLOPPY_PARAMS
4110};
4111
4112static int __init floppy_setup(char *str)
4113{
4114 int i;
4115 int param;
4116 int ints[11];
4117
4118 str = get_options(str, ARRAY_SIZE(ints), ints);
4119 if (str) {
4120 for (i = 0; i < ARRAY_SIZE(config_params); i++) {
4121 if (strcmp(str, config_params[i].name) == 0) {
4122 if (ints[0])
4123 param = ints[1];
4124 else
4125 param = config_params[i].def_param;
4126 if (config_params[i].fn)
4127 config_params[i].
4128 fn(ints, param,
4129 config_params[i].param2);
4130 if (config_params[i].var) {
4131 DPRINT("%s=%d\n", str, param);
4132 *config_params[i].var = param;
4133 }
4134 return 1;
4135 }
4136 }
4137 }
4138 if (str) {
4139 DPRINT("unknown floppy option [%s]\n", str);
4140
4141 DPRINT("allowed options are:");
4142 for (i = 0; i < ARRAY_SIZE(config_params); i++)
4143 printk(" %s", config_params[i].name);
4144 printk("\n");
4145 } else
4146 DPRINT("botched floppy option\n");
Randy Dunlap31c00fc2008-11-13 21:33:24 +00004147 DPRINT("Read Documentation/blockdev/floppy.txt\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148 return 0;
4149}
4150
4151static int have_no_fdc = -ENODEV;
4152
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004153static ssize_t floppy_cmos_show(struct device *dev,
4154 struct device_attribute *attr, char *buf)
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004155{
Eric Miao71b3e0c2009-01-31 22:47:44 +08004156 struct platform_device *p = to_platform_device(dev);
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004157 int drive;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004158
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004159 drive = p->id;
4160 return sprintf(buf, "%X\n", UDP->cmos);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004161}
Joe Perches48c8cee2010-03-10 15:20:45 -08004162
4163DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004164
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165static void floppy_device_release(struct device *dev)
4166{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167}
4168
Frans Popc90cd332009-07-25 22:24:54 +02004169static int floppy_resume(struct device *dev)
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004170{
4171 int fdc;
4172
4173 for (fdc = 0; fdc < N_FDC; fdc++)
4174 if (FDCS->address != -1)
4175 user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
4176
4177 return 0;
4178}
4179
Alexey Dobriyan47145212009-12-14 18:00:08 -08004180static const struct dev_pm_ops floppy_pm_ops = {
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004181 .resume = floppy_resume,
Frans Popc90cd332009-07-25 22:24:54 +02004182 .restore = floppy_resume,
4183};
4184
4185static struct platform_driver floppy_driver = {
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004186 .driver = {
4187 .name = "floppy",
Frans Popc90cd332009-07-25 22:24:54 +02004188 .pm = &floppy_pm_ops,
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004189 },
4190};
4191
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004192static struct platform_device floppy_device[N_DRIVE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193
4194static struct kobject *floppy_find(dev_t dev, int *part, void *data)
4195{
4196 int drive = (*part & 3) | ((*part & 0x80) >> 5);
4197 if (drive >= N_DRIVE ||
4198 !(allowed_drive_mask & (1 << drive)) ||
4199 fdc_state[FDC(drive)].version == FDC_NONE)
4200 return NULL;
Tobias Klauser945f3902006-01-08 01:05:11 -08004201 if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202 return NULL;
4203 *part = 0;
4204 return get_disk(disks[drive]);
4205}
4206
4207static int __init floppy_init(void)
4208{
4209 int i, unit, drive;
4210 int err, dr;
4211
Kumar Gala68e1ee62008-09-22 14:41:31 -07004212#if defined(CONFIG_PPC)
Olaf Heringef16b512006-08-31 21:27:41 -07004213 if (check_legacy_ioport(FDC1))
4214 return -ENODEV;
4215#endif
4216
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 raw_cmd = NULL;
4218
4219 for (dr = 0; dr < N_DRIVE; dr++) {
4220 disks[dr] = alloc_disk(1);
4221 if (!disks[dr]) {
4222 err = -ENOMEM;
4223 goto out_put_disk;
4224 }
4225
4226 disks[dr]->major = FLOPPY_MAJOR;
4227 disks[dr]->first_minor = TOMINOR(dr);
4228 disks[dr]->fops = &floppy_fops;
4229 sprintf(disks[dr]->disk_name, "fd%d", dr);
4230
4231 init_timer(&motor_off_timer[dr]);
4232 motor_off_timer[dr].data = dr;
4233 motor_off_timer[dr].function = motor_off_callback;
4234 }
4235
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236 err = register_blkdev(FLOPPY_MAJOR, "fd");
4237 if (err)
Greg Kroah-Hartman8ab5e4c2005-06-20 21:15:16 -07004238 goto out_put_disk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004240 err = platform_driver_register(&floppy_driver);
4241 if (err)
4242 goto out_unreg_blkdev;
4243
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
4245 if (!floppy_queue) {
4246 err = -ENOMEM;
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004247 goto out_unreg_driver;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 }
Martin K. Petersen086fa5f2010-02-26 00:20:38 -05004249 blk_queue_max_hw_sectors(floppy_queue, 64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
4251 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
4252 floppy_find, NULL, NULL);
4253
4254 for (i = 0; i < 256; i++)
4255 if (ITYPE(i))
4256 floppy_sizes[i] = floppy_type[ITYPE(i)].size;
4257 else
4258 floppy_sizes[i] = MAX_DISK_SIZE << 1;
4259
4260 reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
4261 config_types();
4262
4263 for (i = 0; i < N_FDC; i++) {
4264 fdc = i;
4265 CLEARSTRUCT(FDCS);
4266 FDCS->dtr = -1;
4267 FDCS->dor = 0x4;
4268#if defined(__sparc__) || defined(__mc68000__)
4269 /*sparcs/sun3x don't have a DOR reset which we can fall back on to */
4270#ifdef __mc68000__
4271 if (MACH_IS_SUN3X)
4272#endif
4273 FDCS->version = FDC_82072A;
4274#endif
4275 }
4276
4277 use_virtual_dma = can_use_virtual_dma & 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278 fdc_state[0].address = FDC1;
4279 if (fdc_state[0].address == -1) {
4280 del_timer(&fd_timeout);
4281 err = -ENODEV;
4282 goto out_unreg_region;
4283 }
4284#if N_FDC > 1
4285 fdc_state[1].address = FDC2;
4286#endif
4287
4288 fdc = 0; /* reset fdc in case of unexpected interrupt */
4289 err = floppy_grab_irq_and_dma();
4290 if (err) {
4291 del_timer(&fd_timeout);
4292 err = -EBUSY;
4293 goto out_unreg_region;
4294 }
4295
4296 /* initialise drive state */
4297 for (drive = 0; drive < N_DRIVE; drive++) {
4298 CLEARSTRUCT(UDRS);
4299 CLEARSTRUCT(UDRWE);
4300 USETF(FD_DISK_NEWCHANGE);
4301 USETF(FD_DISK_CHANGED);
4302 USETF(FD_VERIFY);
4303 UDRS->fd_device = -1;
4304 floppy_track_buffer = NULL;
4305 max_buffer_sectors = 0;
4306 }
4307 /*
4308 * Small 10 msec delay to let through any interrupt that
4309 * initialization might have triggered, to not
4310 * confuse detection:
4311 */
4312 msleep(10);
4313
4314 for (i = 0; i < N_FDC; i++) {
4315 fdc = i;
4316 FDCS->driver_version = FD_DRIVER_VERSION;
4317 for (unit = 0; unit < 4; unit++)
4318 FDCS->track[unit] = 0;
4319 if (FDCS->address == -1)
4320 continue;
4321 FDCS->rawcmd = 2;
4322 if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
4323 /* free ioports reserved by floppy_grab_irq_and_dma() */
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004324 floppy_release_regions(fdc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325 FDCS->address = -1;
4326 FDCS->version = FDC_NONE;
4327 continue;
4328 }
4329 /* Try to determine the floppy controller type */
4330 FDCS->version = get_fdc_version();
4331 if (FDCS->version == FDC_NONE) {
4332 /* free ioports reserved by floppy_grab_irq_and_dma() */
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004333 floppy_release_regions(fdc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 FDCS->address = -1;
4335 continue;
4336 }
4337 if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
4338 can_use_virtual_dma = 0;
4339
4340 have_no_fdc = 0;
4341 /* Not all FDCs seem to be able to handle the version command
4342 * properly, so force a reset for the standard FDC clones,
4343 * to avoid interrupt garbage.
4344 */
4345 user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
4346 }
4347 fdc = 0;
4348 del_timer(&fd_timeout);
4349 current_drive = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 initialising = 0;
4351 if (have_no_fdc) {
4352 DPRINT("no floppy controllers found\n");
4353 err = have_no_fdc;
4354 goto out_flush_work;
4355 }
4356
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357 for (drive = 0; drive < N_DRIVE; drive++) {
4358 if (!(allowed_drive_mask & (1 << drive)))
4359 continue;
4360 if (fdc_state[FDC(drive)].version == FDC_NONE)
4361 continue;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004362
4363 floppy_device[drive].name = floppy_device_name;
4364 floppy_device[drive].id = drive;
4365 floppy_device[drive].dev.release = floppy_device_release;
4366
4367 err = platform_device_register(&floppy_device[drive]);
4368 if (err)
4369 goto out_flush_work;
4370
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004371 err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
4372 if (err)
4373 goto out_unreg_platform_dev;
4374
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375 /* to be cleaned up... */
4376 disks[drive]->private_data = (void *)(long)drive;
4377 disks[drive]->queue = floppy_queue;
4378 disks[drive]->flags |= GENHD_FL_REMOVABLE;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004379 disks[drive]->driverfs_dev = &floppy_device[drive].dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380 add_disk(disks[drive]);
4381 }
4382
4383 return 0;
4384
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004385out_unreg_platform_dev:
4386 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387out_flush_work:
4388 flush_scheduled_work();
4389 if (usage_count)
4390 floppy_release_irq_and_dma();
4391out_unreg_region:
4392 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4393 blk_cleanup_queue(floppy_queue);
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004394out_unreg_driver:
4395 platform_driver_unregister(&floppy_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396out_unreg_blkdev:
4397 unregister_blkdev(FLOPPY_MAJOR, "fd");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398out_put_disk:
4399 while (dr--) {
4400 del_timer(&motor_off_timer[dr]);
4401 put_disk(disks[dr]);
4402 }
4403 return err;
4404}
4405
4406static DEFINE_SPINLOCK(floppy_usage_lock);
4407
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004408static const struct io_region {
4409 int offset;
4410 int size;
4411} io_regions[] = {
4412 { 2, 1 },
4413 /* address + 3 is sometimes reserved by pnp bios for motherboard */
4414 { 4, 2 },
4415 /* address + 6 is reserved, and may be taken by IDE.
4416 * Unfortunately, Adaptec doesn't know this :-(, */
4417 { 7, 1 },
4418};
4419
4420static void floppy_release_allocated_regions(int fdc, const struct io_region *p)
4421{
4422 while (p != io_regions) {
4423 p--;
4424 release_region(FDCS->address + p->offset, p->size);
4425 }
4426}
4427
4428#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)]))
4429
4430static int floppy_request_regions(int fdc)
4431{
4432 const struct io_region *p;
4433
4434 for (p = io_regions; p < ARRAY_END(io_regions); p++) {
4435 if (!request_region(FDCS->address + p->offset, p->size, "floppy")) {
4436 DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset);
4437 floppy_release_allocated_regions(fdc, p);
4438 return -EBUSY;
4439 }
4440 }
4441 return 0;
4442}
4443
4444static void floppy_release_regions(int fdc)
4445{
4446 floppy_release_allocated_regions(fdc, ARRAY_END(io_regions));
4447}
4448
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449static int floppy_grab_irq_and_dma(void)
4450{
4451 unsigned long flags;
4452
4453 spin_lock_irqsave(&floppy_usage_lock, flags);
4454 if (usage_count++) {
4455 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4456 return 0;
4457 }
4458 spin_unlock_irqrestore(&floppy_usage_lock, flags);
Ingo Molnar6dc659d2006-03-26 01:36:54 -08004459
4460 /*
4461 * We might have scheduled a free_irq(), wait it to
4462 * drain first:
4463 */
4464 flush_scheduled_work();
4465
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466 if (fd_request_irq()) {
4467 DPRINT("Unable to grab IRQ%d for the floppy driver\n",
4468 FLOPPY_IRQ);
4469 spin_lock_irqsave(&floppy_usage_lock, flags);
4470 usage_count--;
4471 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4472 return -1;
4473 }
4474 if (fd_request_dma()) {
4475 DPRINT("Unable to grab DMA%d for the floppy driver\n",
4476 FLOPPY_DMA);
Jan Beulich2e9c47c2007-10-16 23:27:32 -07004477 if (can_use_virtual_dma & 2)
4478 use_virtual_dma = can_use_virtual_dma = 1;
4479 if (!(can_use_virtual_dma & 1)) {
4480 fd_free_irq();
4481 spin_lock_irqsave(&floppy_usage_lock, flags);
4482 usage_count--;
4483 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4484 return -1;
4485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486 }
4487
4488 for (fdc = 0; fdc < N_FDC; fdc++) {
4489 if (FDCS->address != -1) {
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004490 if (floppy_request_regions(fdc))
4491 goto cleanup;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492 }
4493 }
4494 for (fdc = 0; fdc < N_FDC; fdc++) {
4495 if (FDCS->address != -1) {
4496 reset_fdc_info(1);
4497 fd_outb(FDCS->dor, FD_DOR);
4498 }
4499 }
4500 fdc = 0;
4501 set_dor(0, ~0, 8); /* avoid immediate interrupt */
4502
4503 for (fdc = 0; fdc < N_FDC; fdc++)
4504 if (FDCS->address != -1)
4505 fd_outb(FDCS->dor, FD_DOR);
4506 /*
Jesper Juhl06f748c2007-10-16 23:30:57 -07004507 * The driver will try and free resources and relies on us
4508 * to know if they were allocated or not.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509 */
4510 fdc = 0;
4511 irqdma_allocated = 1;
4512 return 0;
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004513cleanup:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514 fd_free_irq();
4515 fd_free_dma();
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004516 while (--fdc >= 0)
4517 floppy_release_regions(fdc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004518 spin_lock_irqsave(&floppy_usage_lock, flags);
4519 usage_count--;
4520 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4521 return -1;
4522}
4523
4524static void floppy_release_irq_and_dma(void)
4525{
4526 int old_fdc;
4527#ifdef FLOPPY_SANITY_CHECK
4528#ifndef __sparc__
4529 int drive;
4530#endif
4531#endif
4532 long tmpsize;
4533 unsigned long tmpaddr;
4534 unsigned long flags;
4535
4536 spin_lock_irqsave(&floppy_usage_lock, flags);
4537 if (--usage_count) {
4538 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4539 return;
4540 }
4541 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4542 if (irqdma_allocated) {
4543 fd_disable_dma();
4544 fd_free_dma();
Ingo Molnar3e541a42006-07-03 00:24:23 -07004545 fd_free_irq();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546 irqdma_allocated = 0;
4547 }
4548 set_dor(0, ~0, 8);
4549#if N_FDC > 1
4550 set_dor(1, ~8, 0);
4551#endif
4552 floppy_enable_hlt();
4553
4554 if (floppy_track_buffer && max_buffer_sectors) {
4555 tmpsize = max_buffer_sectors * 1024;
4556 tmpaddr = (unsigned long)floppy_track_buffer;
4557 floppy_track_buffer = NULL;
4558 max_buffer_sectors = 0;
4559 buffer_min = buffer_max = -1;
4560 fd_dma_mem_free(tmpaddr, tmpsize);
4561 }
4562#ifdef FLOPPY_SANITY_CHECK
4563#ifndef __sparc__
4564 for (drive = 0; drive < N_FDC * 4; drive++)
4565 if (timer_pending(motor_off_timer + drive))
4566 printk("motor off timer %d still active\n", drive);
4567#endif
4568
4569 if (timer_pending(&fd_timeout))
4570 printk("floppy timer still active:%s\n", timeout_message);
4571 if (timer_pending(&fd_timer))
4572 printk("auxiliary floppy timer still active\n");
David Howells365970a2006-11-22 14:54:49 +00004573 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004574 printk("work still pending\n");
4575#endif
4576 old_fdc = fdc;
4577 for (fdc = 0; fdc < N_FDC; fdc++)
Philippe De Muyter5a74db02009-02-18 14:48:36 -08004578 if (FDCS->address != -1)
4579 floppy_release_regions(fdc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 fdc = old_fdc;
4581}
4582
4583#ifdef MODULE
4584
4585static char *floppy;
4586
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587static void __init parse_floppy_cfg_string(char *cfg)
4588{
4589 char *ptr;
4590
4591 while (*cfg) {
4592 for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ;
4593 if (*cfg) {
4594 *cfg = '\0';
4595 cfg++;
4596 }
4597 if (*ptr)
4598 floppy_setup(ptr);
4599 }
4600}
4601
Jon Schindler7afea3b2008-04-29 00:59:21 -07004602static int __init floppy_module_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004603{
4604 if (floppy)
4605 parse_floppy_cfg_string(floppy);
4606 return floppy_init();
4607}
Jon Schindler7afea3b2008-04-29 00:59:21 -07004608module_init(floppy_module_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609
Jon Schindler7afea3b2008-04-29 00:59:21 -07004610static void __exit floppy_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004611{
4612 int drive;
4613
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4615 unregister_blkdev(FLOPPY_MAJOR, "fd");
Ondrej Zary5e50b9e2009-06-10 12:57:09 -07004616 platform_driver_unregister(&floppy_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617
4618 for (drive = 0; drive < N_DRIVE; drive++) {
4619 del_timer_sync(&motor_off_timer[drive]);
4620
4621 if ((allowed_drive_mask & (1 << drive)) &&
4622 fdc_state[FDC(drive)].version != FDC_NONE) {
4623 del_gendisk(disks[drive]);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004624 device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
4625 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004626 }
4627 put_disk(disks[drive]);
4628 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629
4630 del_timer_sync(&fd_timeout);
4631 del_timer_sync(&fd_timer);
4632 blk_cleanup_queue(floppy_queue);
4633
4634 if (usage_count)
4635 floppy_release_irq_and_dma();
4636
4637 /* eject disk, if any */
4638 fd_eject(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004639}
Joe Perches48c8cee2010-03-10 15:20:45 -08004640
Jon Schindler7afea3b2008-04-29 00:59:21 -07004641module_exit(floppy_module_exit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
4643module_param(floppy, charp, 0);
4644module_param(FLOPPY_IRQ, int, 0);
4645module_param(FLOPPY_DMA, int, 0);
4646MODULE_AUTHOR("Alain L. Knaff");
4647MODULE_SUPPORTED_DEVICE("fd");
4648MODULE_LICENSE("GPL");
4649
Scott James Remnant83f9ef42009-04-02 16:56:47 -07004650/* This doesn't actually get used other than for module information */
4651static const struct pnp_device_id floppy_pnpids[] = {
Joe Perches48c8cee2010-03-10 15:20:45 -08004652 {"PNP0700", 0},
4653 {}
Scott James Remnant83f9ef42009-04-02 16:56:47 -07004654};
Joe Perches48c8cee2010-03-10 15:20:45 -08004655
Scott James Remnant83f9ef42009-04-02 16:56:47 -07004656MODULE_DEVICE_TABLE(pnp, floppy_pnpids);
4657
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658#else
4659
4660__setup("floppy=", floppy_setup);
4661module_init(floppy_init)
4662#endif
4663
4664MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);