blob: 32c79a55511bd174f3effd63af4e5bd7bc594b68 [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
Jesper Juhl06f748c2007-10-16 23:30:57 -0700153#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>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180#include <linux/buffer_head.h> /* for invalidate_buffers() */
Jes Sorensenb1c82b52006-03-23 03:00:26 -0800181#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183/*
184 * PS/2 floppies have much slower step rates than regular floppies.
185 * It's been recommended that take about 1/4 of the default speed
186 * in some more extreme cases.
187 */
188static int slow_floppy;
189
190#include <asm/dma.h>
191#include <asm/irq.h>
192#include <asm/system.h>
193#include <asm/io.h>
194#include <asm/uaccess.h>
195
196static int FLOPPY_IRQ = 6;
197static int FLOPPY_DMA = 2;
198static int can_use_virtual_dma = 2;
199/* =======
200 * can use virtual DMA:
201 * 0 = use of virtual DMA disallowed by config
202 * 1 = use of virtual DMA prescribed by config
203 * 2 = no virtual DMA preference configured. By default try hard DMA,
204 * but fall back on virtual DMA when not enough memory available
205 */
206
207static int use_virtual_dma;
208/* =======
209 * use virtual DMA
210 * 0 using hard DMA
211 * 1 using virtual DMA
212 * This variable is set to virtual when a DMA mem problem arises, and
213 * reset back in floppy_grab_irq_and_dma.
214 * It is not safe to reset it in other circumstances, because the floppy
215 * driver may have several buffers in use at once, and we do currently not
216 * record each buffers capabilities
217 */
218
219static DEFINE_SPINLOCK(floppy_lock);
220static struct completion device_release;
221
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;
Jens Axboe165125e2007-07-24 09:28:11 +0200253static 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
266#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
267#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
288#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#define DP (&drive_params[current_drive])
295#define DRS (&drive_state[current_drive])
296#define DRWE (&write_errors[current_drive])
297#define FDCS (&fdc_state[fdc])
Ralf Baechle7b8f8502007-02-20 13:57:45 -0800298#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags)
299#define SETF(x) set_bit(x##_BIT, &DRS->flags)
300#define TESTF(x) test_bit(x##_BIT, &DRS->flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
302#define UDP (&drive_params[drive])
303#define UDRS (&drive_state[drive])
304#define UDRWE (&write_errors[drive])
305#define UFDCS (&fdc_state[FDC(drive)])
Ralf Baechle7b8f8502007-02-20 13:57:45 -0800306#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags)
307#define USETF(x) set_bit(x##_BIT, &UDRS->flags)
308#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
310#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
311
312#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
313#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
314
315#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
316
317/* read/write */
318#define COMMAND raw_cmd->cmd[0]
319#define DR_SELECT raw_cmd->cmd[1]
320#define TRACK raw_cmd->cmd[2]
321#define HEAD raw_cmd->cmd[3]
322#define SECTOR raw_cmd->cmd[4]
323#define SIZECODE raw_cmd->cmd[5]
324#define SECT_PER_TRACK raw_cmd->cmd[6]
325#define GAP raw_cmd->cmd[7]
326#define SIZECODE2 raw_cmd->cmd[8]
327#define NR_RW 9
328
329/* format */
330#define F_SIZECODE raw_cmd->cmd[2]
331#define F_SECT_PER_TRACK raw_cmd->cmd[3]
332#define F_GAP raw_cmd->cmd[4]
333#define F_FILL raw_cmd->cmd[5]
334#define NR_F 6
335
336/*
337 * Maximum disk size (in kilobytes). This default is used whenever the
338 * current disk size is unknown.
339 * [Now it is rather a minimum]
340 */
341#define MAX_DISK_SIZE 4 /* 3984 */
342
343/*
344 * globals used by 'result()'
345 */
346#define MAX_REPLIES 16
347static unsigned char reply_buffer[MAX_REPLIES];
348static int inr; /* size of reply buffer, when called from interrupt */
349#define ST0 (reply_buffer[0])
350#define ST1 (reply_buffer[1])
351#define ST2 (reply_buffer[2])
352#define ST3 (reply_buffer[0]) /* result of GETSTATUS */
353#define R_TRACK (reply_buffer[3])
354#define R_HEAD (reply_buffer[4])
355#define R_SECTOR (reply_buffer[5])
356#define R_SIZECODE (reply_buffer[6])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357#define SEL_DLY (2*HZ/100)
358
359/*
360 * this struct defines the different floppy drive types.
361 */
362static struct {
363 struct floppy_drive_params params;
364 const char *name; /* name printed while booting */
365} default_drive_params[] = {
366/* NOTE: the time values in jiffies should be in msec!
367 CMOS drive type
368 | Maximum data rate supported by drive type
369 | | Head load time, msec
370 | | | Head unload time, msec (not used)
371 | | | | Step rate interval, usec
372 | | | | | Time needed for spinup time (jiffies)
373 | | | | | | Timeout for spinning down (jiffies)
374 | | | | | | | Spindown offset (where disk stops)
375 | | | | | | | | Select delay
376 | | | | | | | | | RPS
377 | | | | | | | | | | Max number of tracks
378 | | | | | | | | | | | Interrupt timeout
379 | | | | | | | | | | | | Max nonintlv. sectors
380 | | | | | | | | | | | | | -Max Errors- flags */
381{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0,
382 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
383
384{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0,
385 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
386
387{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0,
388 0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
389
390{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
391 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
392
393{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
394 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
395
396{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
397 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
398
399{{6, 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" } /*3 1/2 ED*/
401/* | --autodetected formats--- | | |
402 * read_track | | Name printed when booting
403 * | Native format
404 * Frequency of disk change checks */
405};
406
407static struct floppy_drive_params drive_params[N_DRIVE];
408static struct floppy_drive_struct drive_state[N_DRIVE];
409static struct floppy_write_errors write_errors[N_DRIVE];
410static struct timer_list motor_off_timer[N_DRIVE];
411static struct gendisk *disks[N_DRIVE];
412static struct block_device *opened_bdev[N_DRIVE];
Jes Sorensenb1c82b52006-03-23 03:00:26 -0800413static DEFINE_MUTEX(open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
415
416/*
417 * This struct defines the different floppy types.
418 *
419 * Bit 0 of 'stretch' tells if the tracks need to be doubled for some
420 * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch'
421 * tells if the disk is in Commodore 1581 format, which means side 0 sectors
422 * are located on side 1 of the disk but with a side 0 ID, and vice-versa.
423 * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the
424 * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
425 * side 0 is on physical side 0 (but with the misnamed sector IDs).
426 * 'stretch' should probably be renamed to something more general, like
427 * 'options'. Other parameters should be self-explanatory (see also
428 * setfdprm(8)).
429 */
430/*
431 Size
432 | Sectors per track
433 | | Head
434 | | | Tracks
435 | | | | Stretch
436 | | | | | Gap 1 size
437 | | | | | | Data rate, | 0x40 for perp
438 | | | | | | | Spec1 (stepping rate, head unload
439 | | | | | | | | /fmt gap (gap2) */
440static struct floppy_struct floppy_type[32] = {
441 { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */
442 { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */
443 { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */
444 { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */
445 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */
446 { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */
447 { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */
448 { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */
449 { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */
450 { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */
451
452 { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */
453 { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */
454 { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */
455 { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */
456 { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */
457 { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */
458 { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */
459 { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */
460 { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */
461 { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */
462
463 { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
464 { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */
465 { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */
466 { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */
467 { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */
468 { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */
469 { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
470 { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
471 { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700473
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
475 { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
476};
477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478#define SECTSIZE (_FD_SECTSIZE(*floppy))
479
480/* Auto-detection: Disk type used until the next media change occurs. */
481static struct floppy_struct *current_type[N_DRIVE];
482
483/*
484 * User-provided type information. current_type points to
485 * the respective entry of this array.
486 */
487static struct floppy_struct user_params[N_DRIVE];
488
489static sector_t floppy_sizes[256];
490
Hannes Reinecke94fd0db2005-07-15 10:09:25 +0200491static char floppy_device_name[] = "floppy";
492
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493/*
494 * The driver is trying to determine the correct media format
495 * while probing is set. rw_interrupt() clears it after a
496 * successful access.
497 */
498static int probing;
499
500/* Synchronization of FDC access. */
501#define FD_COMMAND_NONE -1
502#define FD_COMMAND_ERROR 2
503#define FD_COMMAND_OKAY 3
504
505static volatile int command_status = FD_COMMAND_NONE;
506static unsigned long fdc_busy;
507static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
508static DECLARE_WAIT_QUEUE_HEAD(command_done);
509
510#define NO_SIGNAL (!interruptible || !signal_pending(current))
511#define CALL(x) if ((x) == -EINTR) return -EINTR
512#define ECALL(x) if ((ret = (x))) return ret;
513#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
514#define WAIT(x) _WAIT((x),interruptible)
515#define IWAIT(x) _WAIT((x),1)
516
517/* Errors during formatting are counted here. */
518static int format_errors;
519
520/* Format request descriptor. */
521static struct format_descr format_req;
522
523/*
524 * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
525 * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
526 * H is head unload time (1=16ms, 2=32ms, etc)
527 */
528
529/*
530 * Track buffer
531 * Because these are written to by the DMA controller, they must
532 * not contain a 64k byte boundary crossing, or data will be
533 * corrupted/lost.
534 */
535static char *floppy_track_buffer;
536static int max_buffer_sectors;
537
538static int *errors;
Jesper Juhl06f748c2007-10-16 23:30:57 -0700539typedef void (*done_f)(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540static struct cont_t {
Jesper Juhl06f748c2007-10-16 23:30:57 -0700541 void (*interrupt)(void); /* this is called after the interrupt of the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 * main command */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700543 void (*redo)(void); /* this is called to retry the operation */
544 void (*error)(void); /* this is called to tally an error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 done_f done; /* this is called to say if the operation has
546 * succeeded/failed */
547} *cont;
548
549static void floppy_ready(void);
550static void floppy_start(void);
551static void process_fd_request(void);
552static void recalibrate_floppy(void);
553static void floppy_shutdown(unsigned long);
554
555static int floppy_grab_irq_and_dma(void);
556static void floppy_release_irq_and_dma(void);
557
558/*
559 * The "reset" variable should be tested whenever an interrupt is scheduled,
560 * after the commands have been sent. This is to ensure that the driver doesn't
561 * get wedged when the interrupt doesn't come because of a failed command.
562 * reset doesn't need to be tested before sending commands, because
563 * output_byte is automatically disabled when reset is set.
564 */
565#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
566static void reset_fdc(void);
567
568/*
569 * These are global variables, as that's the easiest way to give
570 * information to interrupts. They are the data used for the current
571 * request.
572 */
573#define NO_TRACK -1
574#define NEED_1_RECAL -2
575#define NEED_2_RECAL -3
576
577static int usage_count;
578
579/* buffer related variables */
580static int buffer_track = -1;
581static int buffer_drive = -1;
582static int buffer_min = -1;
583static int buffer_max = -1;
584
585/* fdc related variables, should end up in a struct */
586static struct floppy_fdc_state fdc_state[N_FDC];
587static int fdc; /* current fdc */
588
589static struct floppy_struct *_floppy = floppy_type;
590static unsigned char current_drive;
591static long current_count_sectors;
592static unsigned char fsector_t; /* sector in track */
593static unsigned char in_sector_offset; /* offset within physical sector,
594 * expressed in units of 512 bytes */
595
596#ifndef fd_eject
597static inline int fd_eject(int drive)
598{
599 return -EINVAL;
600}
601#endif
602
603/*
604 * Debugging
605 * =========
606 */
607#ifdef DEBUGT
608static long unsigned debugtimer;
609
610static inline void set_debugt(void)
611{
612 debugtimer = jiffies;
613}
614
615static inline void debugt(const char *message)
616{
617 if (DP->flags & DEBUGT)
618 printk("%s dtime=%lu\n", message, jiffies - debugtimer);
619}
620#else
621static inline void set_debugt(void) { }
622static inline void debugt(const char *message) { }
623#endif /* DEBUGT */
624
625typedef void (*timeout_fn) (unsigned long);
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700626static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628static const char *timeout_message;
629
630#ifdef FLOPPY_SANITY_CHECK
631static void is_alive(const char *message)
632{
633 /* this routine checks whether the floppy driver is "alive" */
634 if (test_bit(0, &fdc_busy) && command_status < 2
635 && !timer_pending(&fd_timeout)) {
636 DPRINT("timeout handler died: %s\n", message);
637 }
638}
639#endif
640
641static void (*do_floppy) (void) = NULL;
642
643#ifdef FLOPPY_SANITY_CHECK
644
645#define OLOGSIZE 20
646
647static void (*lasthandler) (void);
648static unsigned long interruptjiffies;
649static unsigned long resultjiffies;
650static int resultsize;
651static unsigned long lastredo;
652
653static struct output_log {
654 unsigned char data;
655 unsigned char status;
656 unsigned long jiffies;
657} output_log[OLOGSIZE];
658
659static int output_log_pos;
660#endif
661
662#define current_reqD -1
663#define MAXTIMEOUT -2
664
665static void __reschedule_timeout(int drive, const char *message, int marg)
666{
667 if (drive == current_reqD)
668 drive = current_drive;
669 del_timer(&fd_timeout);
Eric Sesterhenn / Snakebyte4acb3e22007-05-23 13:58:15 -0700670 if (drive < 0 || drive >= N_DRIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 fd_timeout.expires = jiffies + 20UL * HZ;
672 drive = 0;
673 } else
674 fd_timeout.expires = jiffies + UDP->timeout;
675 add_timer(&fd_timeout);
676 if (UDP->flags & FD_DEBUG) {
677 DPRINT("reschedule timeout ");
678 printk(message, marg);
679 printk("\n");
680 }
681 timeout_message = message;
682}
683
684static void reschedule_timeout(int drive, const char *message, int marg)
685{
686 unsigned long flags;
687
688 spin_lock_irqsave(&floppy_lock, flags);
689 __reschedule_timeout(drive, message, marg);
690 spin_unlock_irqrestore(&floppy_lock, flags);
691}
692
693#define INFBOUND(a,b) (a)=max_t(int, a, b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694#define SUPBOUND(a,b) (a)=min_t(int, a, b)
695
696/*
697 * Bottom half floppy driver.
698 * ==========================
699 *
700 * This part of the file contains the code talking directly to the hardware,
701 * and also the main service loop (seek-configure-spinup-command)
702 */
703
704/*
705 * disk change.
706 * This routine is responsible for maintaining the FD_DISK_CHANGE flag,
707 * and the last_checked date.
708 *
709 * last_checked is the date of the last check which showed 'no disk change'
710 * FD_DISK_CHANGE is set under two conditions:
711 * 1. The floppy has been changed after some i/o to that floppy already
712 * took place.
713 * 2. No floppy disk is in the drive. This is done in order to ensure that
714 * requests are quickly flushed in case there is no disk in the drive. It
715 * follows that FD_DISK_CHANGE can only be cleared if there is a disk in
716 * the drive.
717 *
718 * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
719 * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
720 * each seek. If a disk is present, the disk change line should also be
721 * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
722 * change line is set, this means either that no disk is in the drive, or
723 * that it has been removed since the last seek.
724 *
725 * This means that we really have a third possibility too:
726 * The floppy has been changed after the last seek.
727 */
728
729static int disk_change(int drive)
730{
731 int fdc = FDC(drive);
Jesper Juhl06f748c2007-10-16 23:30:57 -0700732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733#ifdef FLOPPY_SANITY_CHECK
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -0800734 if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 DPRINT("WARNING disk change called early\n");
736 if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
737 (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
738 DPRINT("probing disk change on unselected drive\n");
739 DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive),
740 (unsigned int)FDCS->dor);
741 }
742#endif
743
744#ifdef DCL_DEBUG
745 if (UDP->flags & FD_DEBUG) {
746 DPRINT("checking disk change line for drive %d\n", drive);
747 DPRINT("jiffies=%lu\n", jiffies);
748 DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
749 DPRINT("flags=%lx\n", UDRS->flags);
750 }
751#endif
752 if (UDP->flags & FD_BROKEN_DCL)
753 return UTESTF(FD_DISK_CHANGED);
754 if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) {
755 USETF(FD_VERIFY); /* verify write protection */
756 if (UDRS->maxblock) {
757 /* mark it changed */
758 USETF(FD_DISK_CHANGED);
759 }
760
761 /* invalidate its geometry */
762 if (UDRS->keep_data >= 0) {
763 if ((UDP->flags & FTD_MSG) &&
764 current_type[drive] != NULL)
765 DPRINT("Disk type is undefined after "
766 "disk change\n");
767 current_type[drive] = NULL;
768 floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
769 }
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return 1;
772 } else {
773 UDRS->last_checked = jiffies;
774 UCLEARF(FD_DISK_NEWCHANGE);
775 }
776 return 0;
777}
778
779static inline int is_selected(int dor, int unit)
780{
781 return ((dor & (0x10 << unit)) && (dor & 3) == unit);
782}
783
784static int set_dor(int fdc, char mask, char data)
785{
Jesper Juhlfdc1ca82007-10-16 23:30:58 -0700786 unsigned char unit;
787 unsigned char drive;
788 unsigned char newdor;
789 unsigned char olddor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 if (FDCS->address == -1)
792 return -1;
793
794 olddor = FDCS->dor;
795 newdor = (olddor & mask) | data;
796 if (newdor != olddor) {
797 unit = olddor & 0x3;
798 if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
799 drive = REVDRIVE(fdc, unit);
800#ifdef DCL_DEBUG
801 if (UDP->flags & FD_DEBUG) {
802 DPRINT("calling disk change from set_dor\n");
803 }
804#endif
805 disk_change(drive);
806 }
807 FDCS->dor = newdor;
808 fd_outb(newdor, FD_DOR);
809
810 unit = newdor & 0x3;
811 if (!is_selected(olddor, unit) && is_selected(newdor, unit)) {
812 drive = REVDRIVE(fdc, unit);
813 UDRS->select_date = jiffies;
814 }
815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 return olddor;
817}
818
819static void twaddle(void)
820{
821 if (DP->select_delay)
822 return;
823 fd_outb(FDCS->dor & ~(0x10 << UNIT(current_drive)), FD_DOR);
824 fd_outb(FDCS->dor, FD_DOR);
825 DRS->select_date = jiffies;
826}
827
828/* reset all driver information about the current fdc. This is needed after
829 * a reset, and after a raw command. */
830static void reset_fdc_info(int mode)
831{
832 int drive;
833
834 FDCS->spec1 = FDCS->spec2 = -1;
835 FDCS->need_configure = 1;
836 FDCS->perp_mode = 1;
837 FDCS->rawcmd = 0;
838 for (drive = 0; drive < N_DRIVE; drive++)
839 if (FDC(drive) == fdc && (mode || UDRS->track != NEED_1_RECAL))
840 UDRS->track = NEED_2_RECAL;
841}
842
843/* selects the fdc and drive, and enables the fdc's input/dma. */
844static void set_fdc(int drive)
845{
846 if (drive >= 0 && drive < N_DRIVE) {
847 fdc = FDC(drive);
848 current_drive = drive;
849 }
850 if (fdc != 1 && fdc != 0) {
851 printk("bad fdc value\n");
852 return;
853 }
854 set_dor(fdc, ~0, 8);
855#if N_FDC > 1
856 set_dor(1 - fdc, ~8, 0);
857#endif
858 if (FDCS->rawcmd == 2)
859 reset_fdc_info(1);
860 if (fd_inb(FD_STATUS) != STATUS_READY)
861 FDCS->reset = 1;
862}
863
864/* locks the driver */
865static int _lock_fdc(int drive, int interruptible, int line)
866{
867 if (!usage_count) {
868 printk(KERN_ERR
869 "Trying to lock fdc while usage count=0 at line %d\n",
870 line);
871 return -1;
872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
874 if (test_and_set_bit(0, &fdc_busy)) {
875 DECLARE_WAITQUEUE(wait, current);
876 add_wait_queue(&fdc_wait, &wait);
877
878 for (;;) {
879 set_current_state(TASK_INTERRUPTIBLE);
880
881 if (!test_and_set_bit(0, &fdc_busy))
882 break;
883
884 schedule();
885
886 if (!NO_SIGNAL) {
887 remove_wait_queue(&fdc_wait, &wait);
888 return -EINTR;
889 }
890 }
891
892 set_current_state(TASK_RUNNING);
893 remove_wait_queue(&fdc_wait, &wait);
Ingo Molnar3e541a42006-07-03 00:24:23 -0700894 flush_scheduled_work();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 }
896 command_status = FD_COMMAND_NONE;
897
898 __reschedule_timeout(drive, "lock fdc", 0);
899 set_fdc(drive);
900 return 0;
901}
902
903#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__)
904
905#define LOCK_FDC(drive,interruptible) \
906if (lock_fdc(drive,interruptible)) return -EINTR;
907
908/* unlocks the driver */
909static inline void unlock_fdc(void)
910{
911 unsigned long flags;
912
913 raw_cmd = NULL;
914 if (!test_bit(0, &fdc_busy))
915 DPRINT("FDC access conflict!\n");
916
917 if (do_floppy)
918 DPRINT("device interrupt still active at FDC release: %p!\n",
919 do_floppy);
920 command_status = FD_COMMAND_NONE;
921 spin_lock_irqsave(&floppy_lock, flags);
922 del_timer(&fd_timeout);
923 cont = NULL;
924 clear_bit(0, &fdc_busy);
925 if (elv_next_request(floppy_queue))
926 do_fd_request(floppy_queue);
927 spin_unlock_irqrestore(&floppy_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 wake_up(&fdc_wait);
929}
930
931/* switches the motor off after a given timeout */
932static void motor_off_callback(unsigned long nr)
933{
934 unsigned char mask = ~(0x10 << UNIT(nr));
935
936 set_dor(FDC(nr), mask, 0);
937}
938
939/* schedules motor off */
940static void floppy_off(unsigned int drive)
941{
942 unsigned long volatile delta;
Jesper Juhlfdc1ca82007-10-16 23:30:58 -0700943 int fdc = FDC(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
945 if (!(FDCS->dor & (0x10 << UNIT(drive))))
946 return;
947
948 del_timer(motor_off_timer + drive);
949
950 /* make spindle stop in a position which minimizes spinup time
951 * next time */
952 if (UDP->rps) {
953 delta = jiffies - UDRS->first_read_date + HZ -
954 UDP->spindown_offset;
955 delta = ((delta * UDP->rps) % HZ) / UDP->rps;
956 motor_off_timer[drive].expires =
957 jiffies + UDP->spindown - delta;
958 }
959 add_timer(motor_off_timer + drive);
960}
961
962/*
963 * cycle through all N_DRIVE floppy drives, for disk change testing.
964 * stopping at current drive. This is done before any long operation, to
965 * be sure to have up to date disk change information.
966 */
967static void scandrives(void)
968{
Jesper Juhl06f748c2007-10-16 23:30:57 -0700969 int i;
970 int drive;
971 int saved_drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
973 if (DP->select_delay)
974 return;
975
976 saved_drive = current_drive;
977 for (i = 0; i < N_DRIVE; i++) {
978 drive = (saved_drive + i + 1) % N_DRIVE;
979 if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
980 continue; /* skip closed drives */
981 set_fdc(drive);
982 if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) &
983 (0x10 << UNIT(drive))))
984 /* switch the motor off again, if it was off to
985 * begin with */
986 set_dor(fdc, ~(0x10 << UNIT(drive)), 0);
987 }
988 set_fdc(saved_drive);
989}
990
991static void empty(void)
992{
993}
994
David Howells65f27f32006-11-22 14:55:48 +0000995static DECLARE_WORK(floppy_work, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997static void schedule_bh(void (*handler) (void))
998{
David Howells65f27f32006-11-22 14:55:48 +0000999 PREPARE_WORK(&floppy_work, (work_func_t)handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 schedule_work(&floppy_work);
1001}
1002
Ingo Molnar8d06afa2005-09-09 13:10:40 -07001003static DEFINE_TIMER(fd_timer, NULL, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
1005static void cancel_activity(void)
1006{
1007 unsigned long flags;
1008
1009 spin_lock_irqsave(&floppy_lock, flags);
1010 do_floppy = NULL;
David Howells65f27f32006-11-22 14:55:48 +00001011 PREPARE_WORK(&floppy_work, (work_func_t)empty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 del_timer(&fd_timer);
1013 spin_unlock_irqrestore(&floppy_lock, flags);
1014}
1015
1016/* this function makes sure that the disk stays in the drive during the
1017 * transfer */
1018static void fd_watchdog(void)
1019{
1020#ifdef DCL_DEBUG
1021 if (DP->flags & FD_DEBUG) {
1022 DPRINT("calling disk change from watchdog\n");
1023 }
1024#endif
1025
1026 if (disk_change(current_drive)) {
1027 DPRINT("disk removed during i/o\n");
1028 cancel_activity();
1029 cont->done(0);
1030 reset_fdc();
1031 } else {
1032 del_timer(&fd_timer);
1033 fd_timer.function = (timeout_fn) fd_watchdog;
1034 fd_timer.expires = jiffies + HZ / 10;
1035 add_timer(&fd_timer);
1036 }
1037}
1038
1039static void main_command_interrupt(void)
1040{
1041 del_timer(&fd_timer);
1042 cont->interrupt();
1043}
1044
1045/* waits for a delay (spinup or select) to pass */
1046static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
1047{
1048 if (FDCS->reset) {
1049 reset_fdc(); /* do the reset during sleep to win time
1050 * if we don't need to sleep, it's a good
1051 * occasion anyways */
1052 return 1;
1053 }
1054
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001055 if (time_before(jiffies, delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 del_timer(&fd_timer);
1057 fd_timer.function = function;
1058 fd_timer.expires = delay;
1059 add_timer(&fd_timer);
1060 return 1;
1061 }
1062 return 0;
1063}
1064
1065static DEFINE_SPINLOCK(floppy_hlt_lock);
1066static int hlt_disabled;
1067static void floppy_disable_hlt(void)
1068{
1069 unsigned long flags;
1070
1071 spin_lock_irqsave(&floppy_hlt_lock, flags);
1072 if (!hlt_disabled) {
1073 hlt_disabled = 1;
1074#ifdef HAVE_DISABLE_HLT
1075 disable_hlt();
1076#endif
1077 }
1078 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1079}
1080
1081static void floppy_enable_hlt(void)
1082{
1083 unsigned long flags;
1084
1085 spin_lock_irqsave(&floppy_hlt_lock, flags);
1086 if (hlt_disabled) {
1087 hlt_disabled = 0;
1088#ifdef HAVE_DISABLE_HLT
1089 enable_hlt();
1090#endif
1091 }
1092 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1093}
1094
1095static void setup_DMA(void)
1096{
1097 unsigned long f;
1098
1099#ifdef FLOPPY_SANITY_CHECK
1100 if (raw_cmd->length == 0) {
1101 int i;
1102
1103 printk("zero dma transfer size:");
1104 for (i = 0; i < raw_cmd->cmd_count; i++)
1105 printk("%x,", raw_cmd->cmd[i]);
1106 printk("\n");
1107 cont->done(0);
1108 FDCS->reset = 1;
1109 return;
1110 }
1111 if (((unsigned long)raw_cmd->kernel_data) % 512) {
1112 printk("non aligned address: %p\n", raw_cmd->kernel_data);
1113 cont->done(0);
1114 FDCS->reset = 1;
1115 return;
1116 }
1117#endif
1118 f = claim_dma_lock();
1119 fd_disable_dma();
1120#ifdef fd_dma_setup
1121 if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length,
1122 (raw_cmd->flags & FD_RAW_READ) ?
1123 DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) {
1124 release_dma_lock(f);
1125 cont->done(0);
1126 FDCS->reset = 1;
1127 return;
1128 }
1129 release_dma_lock(f);
1130#else
1131 fd_clear_dma_ff();
1132 fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
1133 fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ) ?
1134 DMA_MODE_READ : DMA_MODE_WRITE);
1135 fd_set_dma_addr(raw_cmd->kernel_data);
1136 fd_set_dma_count(raw_cmd->length);
1137 virtual_dma_port = FDCS->address;
1138 fd_enable_dma();
1139 release_dma_lock(f);
1140#endif
1141 floppy_disable_hlt();
1142}
1143
1144static void show_floppy(void);
1145
1146/* waits until the fdc becomes ready */
1147static int wait_til_ready(void)
1148{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001149 int status;
1150 int counter;
1151
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 if (FDCS->reset)
1153 return -1;
1154 for (counter = 0; counter < 10000; counter++) {
1155 status = fd_inb(FD_STATUS);
1156 if (status & STATUS_READY)
1157 return status;
1158 }
1159 if (!initialising) {
1160 DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc);
1161 show_floppy();
1162 }
1163 FDCS->reset = 1;
1164 return -1;
1165}
1166
1167/* sends a command byte to the fdc */
1168static int output_byte(char byte)
1169{
1170 int status;
1171
1172 if ((status = wait_til_ready()) < 0)
1173 return -1;
1174 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) {
1175 fd_outb(byte, FD_DATA);
1176#ifdef FLOPPY_SANITY_CHECK
1177 output_log[output_log_pos].data = byte;
1178 output_log[output_log_pos].status = status;
1179 output_log[output_log_pos].jiffies = jiffies;
1180 output_log_pos = (output_log_pos + 1) % OLOGSIZE;
1181#endif
1182 return 0;
1183 }
1184 FDCS->reset = 1;
1185 if (!initialising) {
1186 DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
1187 byte, fdc, status);
1188 show_floppy();
1189 }
1190 return -1;
1191}
1192
1193#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
1194
1195/* gets the response from the fdc */
1196static int result(void)
1197{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001198 int i;
1199 int status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
1201 for (i = 0; i < MAX_REPLIES; i++) {
1202 if ((status = wait_til_ready()) < 0)
1203 break;
1204 status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
1205 if ((status & ~STATUS_BUSY) == STATUS_READY) {
1206#ifdef FLOPPY_SANITY_CHECK
1207 resultjiffies = jiffies;
1208 resultsize = i;
1209#endif
1210 return i;
1211 }
1212 if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
1213 reply_buffer[i] = fd_inb(FD_DATA);
1214 else
1215 break;
1216 }
1217 if (!initialising) {
1218 DPRINT
1219 ("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
1220 fdc, status, i);
1221 show_floppy();
1222 }
1223 FDCS->reset = 1;
1224 return -1;
1225}
1226
1227#define MORE_OUTPUT -2
1228/* does the fdc need more output? */
1229static int need_more_output(void)
1230{
1231 int status;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001232
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 if ((status = wait_til_ready()) < 0)
1234 return -1;
1235 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
1236 return MORE_OUTPUT;
1237 return result();
1238}
1239
1240/* Set perpendicular mode as required, based on data rate, if supported.
1241 * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
1242 */
1243static inline void perpendicular_mode(void)
1244{
1245 unsigned char perp_mode;
1246
1247 if (raw_cmd->rate & 0x40) {
1248 switch (raw_cmd->rate & 3) {
1249 case 0:
1250 perp_mode = 2;
1251 break;
1252 case 3:
1253 perp_mode = 3;
1254 break;
1255 default:
1256 DPRINT("Invalid data rate for perpendicular mode!\n");
1257 cont->done(0);
1258 FDCS->reset = 1; /* convenient way to return to
1259 * redo without to much hassle (deep
1260 * stack et al. */
1261 return;
1262 }
1263 } else
1264 perp_mode = 0;
1265
1266 if (FDCS->perp_mode == perp_mode)
1267 return;
1268 if (FDCS->version >= FDC_82077_ORIG) {
1269 output_byte(FD_PERPENDICULAR);
1270 output_byte(perp_mode);
1271 FDCS->perp_mode = perp_mode;
1272 } else if (perp_mode) {
1273 DPRINT("perpendicular mode not supported by this FDC.\n");
1274 }
1275} /* perpendicular_mode */
1276
1277static int fifo_depth = 0xa;
1278static int no_fifo;
1279
1280static int fdc_configure(void)
1281{
1282 /* Turn on FIFO */
1283 output_byte(FD_CONFIGURE);
1284 if (need_more_output() != MORE_OUTPUT)
1285 return 0;
1286 output_byte(0);
1287 output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf));
1288 output_byte(0); /* pre-compensation from track
1289 0 upwards */
1290 return 1;
1291}
1292
1293#define NOMINAL_DTR 500
1294
1295/* Issue a "SPECIFY" command to set the step rate time, head unload time,
1296 * head load time, and DMA disable flag to values needed by floppy.
1297 *
1298 * The value "dtr" is the data transfer rate in Kbps. It is needed
1299 * to account for the data rate-based scaling done by the 82072 and 82077
1300 * FDC types. This parameter is ignored for other types of FDCs (i.e.
1301 * 8272a).
1302 *
1303 * Note that changing the data transfer rate has a (probably deleterious)
1304 * effect on the parameters subject to scaling for 82072/82077 FDCs, so
1305 * fdc_specify is called again after each data transfer rate
1306 * change.
1307 *
1308 * srt: 1000 to 16000 in microseconds
1309 * hut: 16 to 240 milliseconds
1310 * hlt: 2 to 254 milliseconds
1311 *
1312 * These values are rounded up to the next highest available delay time.
1313 */
1314static void fdc_specify(void)
1315{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001316 unsigned char spec1;
1317 unsigned char spec2;
1318 unsigned long srt;
1319 unsigned long hlt;
1320 unsigned long hut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 unsigned long dtr = NOMINAL_DTR;
1322 unsigned long scale_dtr = NOMINAL_DTR;
1323 int hlt_max_code = 0x7f;
1324 int hut_max_code = 0xf;
1325
1326 if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
1327 fdc_configure();
1328 FDCS->need_configure = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 }
1330
1331 switch (raw_cmd->rate & 0x03) {
1332 case 3:
1333 dtr = 1000;
1334 break;
1335 case 1:
1336 dtr = 300;
1337 if (FDCS->version >= FDC_82078) {
1338 /* chose the default rate table, not the one
1339 * where 1 = 2 Mbps */
1340 output_byte(FD_DRIVESPEC);
1341 if (need_more_output() == MORE_OUTPUT) {
1342 output_byte(UNIT(current_drive));
1343 output_byte(0xc0);
1344 }
1345 }
1346 break;
1347 case 2:
1348 dtr = 250;
1349 break;
1350 }
1351
1352 if (FDCS->version >= FDC_82072) {
1353 scale_dtr = dtr;
1354 hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */
1355 hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */
1356 }
1357
1358 /* Convert step rate from microseconds to milliseconds and 4 bits */
1359 srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR;
1360 if (slow_floppy) {
1361 srt = srt / 4;
1362 }
1363 SUPBOUND(srt, 0xf);
1364 INFBOUND(srt, 0);
1365
1366 hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR;
1367 if (hlt < 0x01)
1368 hlt = 0x01;
1369 else if (hlt > 0x7f)
1370 hlt = hlt_max_code;
1371
1372 hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR;
1373 if (hut < 0x1)
1374 hut = 0x1;
1375 else if (hut > 0xf)
1376 hut = hut_max_code;
1377
1378 spec1 = (srt << 4) | hut;
1379 spec2 = (hlt << 1) | (use_virtual_dma & 1);
1380
1381 /* If these parameters did not change, just return with success */
1382 if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) {
1383 /* Go ahead and set spec1 and spec2 */
1384 output_byte(FD_SPECIFY);
1385 output_byte(FDCS->spec1 = spec1);
1386 output_byte(FDCS->spec2 = spec2);
1387 }
1388} /* fdc_specify */
1389
1390/* Set the FDC's data transfer rate on behalf of the specified drive.
1391 * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue
1392 * of the specify command (i.e. using the fdc_specify function).
1393 */
1394static int fdc_dtr(void)
1395{
1396 /* If data rate not already set to desired value, set it. */
1397 if ((raw_cmd->rate & 3) == FDCS->dtr)
1398 return 0;
1399
1400 /* Set dtr */
1401 fd_outb(raw_cmd->rate & 3, FD_DCR);
1402
1403 /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
1404 * need a stabilization period of several milliseconds to be
1405 * enforced after data rate changes before R/W operations.
1406 * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
1407 */
1408 FDCS->dtr = raw_cmd->rate & 3;
1409 return (fd_wait_for_completion(jiffies + 2UL * HZ / 100,
1410 (timeout_fn) floppy_ready));
1411} /* fdc_dtr */
1412
1413static void tell_sector(void)
1414{
1415 printk(": track %d, head %d, sector %d, size %d",
1416 R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
1417} /* tell_sector */
1418
1419/*
1420 * OK, this error interpreting routine is called after a
1421 * DMA read/write has succeeded
1422 * or failed, so we check the results, and copy any buffers.
1423 * hhb: Added better error reporting.
1424 * ak: Made this into a separate routine.
1425 */
1426static int interpret_errors(void)
1427{
1428 char bad;
1429
1430 if (inr != 7) {
1431 DPRINT("-- FDC reply error");
1432 FDCS->reset = 1;
1433 return 1;
1434 }
1435
1436 /* check IC to find cause of interrupt */
1437 switch (ST0 & ST0_INTR) {
1438 case 0x40: /* error occurred during command execution */
1439 if (ST1 & ST1_EOC)
1440 return 0; /* occurs with pseudo-DMA */
1441 bad = 1;
1442 if (ST1 & ST1_WP) {
1443 DPRINT("Drive is write protected\n");
1444 CLEARF(FD_DISK_WRITABLE);
1445 cont->done(0);
1446 bad = 2;
1447 } else if (ST1 & ST1_ND) {
1448 SETF(FD_NEED_TWADDLE);
1449 } else if (ST1 & ST1_OR) {
1450 if (DP->flags & FTD_MSG)
1451 DPRINT("Over/Underrun - retrying\n");
1452 bad = 0;
1453 } else if (*errors >= DP->max_errors.reporting) {
1454 DPRINT("");
1455 if (ST0 & ST0_ECE) {
1456 printk("Recalibrate failed!");
1457 } else if (ST2 & ST2_CRC) {
1458 printk("data CRC error");
1459 tell_sector();
1460 } else if (ST1 & ST1_CRC) {
1461 printk("CRC error");
1462 tell_sector();
1463 } else if ((ST1 & (ST1_MAM | ST1_ND))
1464 || (ST2 & ST2_MAM)) {
1465 if (!probing) {
1466 printk("sector not found");
1467 tell_sector();
1468 } else
1469 printk("probe failed...");
1470 } else if (ST2 & ST2_WC) { /* seek error */
1471 printk("wrong cylinder");
1472 } else if (ST2 & ST2_BC) { /* cylinder marked as bad */
1473 printk("bad cylinder");
1474 } else {
1475 printk
1476 ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
1477 ST0, ST1, ST2);
1478 tell_sector();
1479 }
1480 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 }
1482 if (ST2 & ST2_WC || ST2 & ST2_BC)
1483 /* wrong cylinder => recal */
1484 DRS->track = NEED_2_RECAL;
1485 return bad;
1486 case 0x80: /* invalid command given */
1487 DPRINT("Invalid FDC command given!\n");
1488 cont->done(0);
1489 return 2;
1490 case 0xc0:
1491 DPRINT("Abnormal termination caused by polling\n");
1492 cont->error();
1493 return 2;
1494 default: /* (0) Normal command termination */
1495 return 0;
1496 }
1497}
1498
1499/*
1500 * This routine is called when everything should be correctly set up
1501 * for the transfer (i.e. floppy motor is on, the correct floppy is
1502 * selected, and the head is sitting on the right track).
1503 */
1504static void setup_rw_floppy(void)
1505{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001506 int i;
1507 int r;
1508 int flags;
1509 int dflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 unsigned long ready_date;
1511 timeout_fn function;
1512
1513 flags = raw_cmd->flags;
1514 if (flags & (FD_RAW_READ | FD_RAW_WRITE))
1515 flags |= FD_RAW_INTR;
1516
1517 if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)) {
1518 ready_date = DRS->spinup_date + DP->spinup;
1519 /* If spinup will take a long time, rerun scandrives
1520 * again just before spinup completion. Beware that
1521 * after scandrives, we must again wait for selection.
1522 */
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001523 if (time_after(ready_date, jiffies + DP->select_delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 ready_date -= DP->select_delay;
1525 function = (timeout_fn) floppy_start;
1526 } else
1527 function = (timeout_fn) setup_rw_floppy;
1528
1529 /* wait until the floppy is spinning fast enough */
1530 if (fd_wait_for_completion(ready_date, function))
1531 return;
1532 }
1533 dflags = DRS->flags;
1534
1535 if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
1536 setup_DMA();
1537
1538 if (flags & FD_RAW_INTR)
1539 do_floppy = main_command_interrupt;
1540
1541 r = 0;
1542 for (i = 0; i < raw_cmd->cmd_count; i++)
1543 r |= output_byte(raw_cmd->cmd[i]);
1544
1545 debugt("rw_command: ");
1546
1547 if (r) {
1548 cont->error();
1549 reset_fdc();
1550 return;
1551 }
1552
1553 if (!(flags & FD_RAW_INTR)) {
1554 inr = result();
1555 cont->interrupt();
1556 } else if (flags & FD_RAW_NEED_DISK)
1557 fd_watchdog();
1558}
1559
1560static int blind_seek;
1561
1562/*
1563 * This is the routine called after every seek (or recalibrate) interrupt
1564 * from the floppy controller.
1565 */
1566static void seek_interrupt(void)
1567{
1568 debugt("seek interrupt:");
1569 if (inr != 2 || (ST0 & 0xF8) != 0x20) {
1570 DPRINT("seek failed\n");
1571 DRS->track = NEED_2_RECAL;
1572 cont->error();
1573 cont->redo();
1574 return;
1575 }
1576 if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) {
1577#ifdef DCL_DEBUG
1578 if (DP->flags & FD_DEBUG) {
1579 DPRINT
1580 ("clearing NEWCHANGE flag because of effective seek\n");
1581 DPRINT("jiffies=%lu\n", jiffies);
1582 }
1583#endif
1584 CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
1585 DRS->select_date = jiffies;
1586 }
1587 DRS->track = ST1;
1588 floppy_ready();
1589}
1590
1591static void check_wp(void)
1592{
1593 if (TESTF(FD_VERIFY)) {
1594 /* check write protection */
1595 output_byte(FD_GETSTATUS);
1596 output_byte(UNIT(current_drive));
1597 if (result() != 1) {
1598 FDCS->reset = 1;
1599 return;
1600 }
1601 CLEARF(FD_VERIFY);
1602 CLEARF(FD_NEED_TWADDLE);
1603#ifdef DCL_DEBUG
1604 if (DP->flags & FD_DEBUG) {
1605 DPRINT("checking whether disk is write protected\n");
1606 DPRINT("wp=%x\n", ST3 & 0x40);
1607 }
1608#endif
1609 if (!(ST3 & 0x40))
1610 SETF(FD_DISK_WRITABLE);
1611 else
1612 CLEARF(FD_DISK_WRITABLE);
1613 }
1614}
1615
1616static void seek_floppy(void)
1617{
1618 int track;
1619
1620 blind_seek = 0;
1621
1622#ifdef DCL_DEBUG
1623 if (DP->flags & FD_DEBUG) {
1624 DPRINT("calling disk change from seek\n");
1625 }
1626#endif
1627
1628 if (!TESTF(FD_DISK_NEWCHANGE) &&
1629 disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) {
1630 /* the media changed flag should be cleared after the seek.
1631 * If it isn't, this means that there is really no disk in
1632 * the drive.
1633 */
1634 SETF(FD_DISK_CHANGED);
1635 cont->done(0);
1636 cont->redo();
1637 return;
1638 }
1639 if (DRS->track <= NEED_1_RECAL) {
1640 recalibrate_floppy();
1641 return;
1642 } else if (TESTF(FD_DISK_NEWCHANGE) &&
1643 (raw_cmd->flags & FD_RAW_NEED_DISK) &&
1644 (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
1645 /* we seek to clear the media-changed condition. Does anybody
1646 * know a more elegant way, which works on all drives? */
1647 if (raw_cmd->track)
1648 track = raw_cmd->track - 1;
1649 else {
1650 if (DP->flags & FD_SILENT_DCL_CLEAR) {
1651 set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0);
1652 blind_seek = 1;
1653 raw_cmd->flags |= FD_RAW_NEED_SEEK;
1654 }
1655 track = 1;
1656 }
1657 } else {
1658 check_wp();
1659 if (raw_cmd->track != DRS->track &&
1660 (raw_cmd->flags & FD_RAW_NEED_SEEK))
1661 track = raw_cmd->track;
1662 else {
1663 setup_rw_floppy();
1664 return;
1665 }
1666 }
1667
1668 do_floppy = seek_interrupt;
1669 output_byte(FD_SEEK);
1670 output_byte(UNIT(current_drive));
1671 LAST_OUT(track);
1672 debugt("seek command:");
1673}
1674
1675static void recal_interrupt(void)
1676{
1677 debugt("recal interrupt:");
1678 if (inr != 2)
1679 FDCS->reset = 1;
1680 else if (ST0 & ST0_ECE) {
1681 switch (DRS->track) {
1682 case NEED_1_RECAL:
1683 debugt("recal interrupt need 1 recal:");
1684 /* after a second recalibrate, we still haven't
1685 * reached track 0. Probably no drive. Raise an
1686 * error, as failing immediately might upset
1687 * computers possessed by the Devil :-) */
1688 cont->error();
1689 cont->redo();
1690 return;
1691 case NEED_2_RECAL:
1692 debugt("recal interrupt need 2 recal:");
1693 /* If we already did a recalibrate,
1694 * and we are not at track 0, this
1695 * means we have moved. (The only way
1696 * not to move at recalibration is to
1697 * be already at track 0.) Clear the
1698 * new change flag */
1699#ifdef DCL_DEBUG
1700 if (DP->flags & FD_DEBUG) {
1701 DPRINT
1702 ("clearing NEWCHANGE flag because of second recalibrate\n");
1703 }
1704#endif
1705
1706 CLEARF(FD_DISK_NEWCHANGE);
1707 DRS->select_date = jiffies;
1708 /* fall through */
1709 default:
1710 debugt("recal interrupt default:");
1711 /* Recalibrate moves the head by at
1712 * most 80 steps. If after one
1713 * recalibrate we don't have reached
1714 * track 0, this might mean that we
1715 * started beyond track 80. Try
1716 * again. */
1717 DRS->track = NEED_1_RECAL;
1718 break;
1719 }
1720 } else
1721 DRS->track = ST1;
1722 floppy_ready();
1723}
1724
1725static void print_result(char *message, int inr)
1726{
1727 int i;
1728
1729 DPRINT("%s ", message);
1730 if (inr >= 0)
1731 for (i = 0; i < inr; i++)
1732 printk("repl[%d]=%x ", i, reply_buffer[i]);
1733 printk("\n");
1734}
1735
1736/* interrupt handler. Note that this can be called externally on the Sparc */
David Howells7d12e782006-10-05 14:55:46 +01001737irqreturn_t floppy_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 int do_print;
1740 unsigned long f;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001741 void (*handler)(void) = do_floppy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742
1743 lasthandler = handler;
1744 interruptjiffies = jiffies;
1745
1746 f = claim_dma_lock();
1747 fd_disable_dma();
1748 release_dma_lock(f);
1749
1750 floppy_enable_hlt();
1751 do_floppy = NULL;
1752 if (fdc >= N_FDC || FDCS->address == -1) {
1753 /* we don't even know which FDC is the culprit */
1754 printk("DOR0=%x\n", fdc_state[0].dor);
1755 printk("floppy interrupt on bizarre fdc %d\n", fdc);
1756 printk("handler=%p\n", handler);
1757 is_alive("bizarre fdc");
1758 return IRQ_NONE;
1759 }
1760
1761 FDCS->reset = 0;
1762 /* We have to clear the reset flag here, because apparently on boxes
1763 * with level triggered interrupts (PS/2, Sparc, ...), it is needed to
1764 * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the
1765 * emission of the SENSEI's.
1766 * It is OK to emit floppy commands because we are in an interrupt
1767 * handler here, and thus we have to fear no interference of other
1768 * activity.
1769 */
1770
1771 do_print = !handler && print_unex && !initialising;
1772
1773 inr = result();
1774 if (do_print)
1775 print_result("unexpected interrupt", inr);
1776 if (inr == 0) {
1777 int max_sensei = 4;
1778 do {
1779 output_byte(FD_SENSEI);
1780 inr = result();
1781 if (do_print)
1782 print_result("sensei", inr);
1783 max_sensei--;
1784 } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2
1785 && max_sensei);
1786 }
1787 if (!handler) {
1788 FDCS->reset = 1;
1789 return IRQ_NONE;
1790 }
1791 schedule_bh(handler);
1792 is_alive("normal interrupt end");
1793
1794 /* FIXME! Was it really for us? */
1795 return IRQ_HANDLED;
1796}
1797
1798static void recalibrate_floppy(void)
1799{
1800 debugt("recalibrate floppy:");
1801 do_floppy = recal_interrupt;
1802 output_byte(FD_RECALIBRATE);
1803 LAST_OUT(UNIT(current_drive));
1804}
1805
1806/*
1807 * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
1808 */
1809static void reset_interrupt(void)
1810{
1811 debugt("reset interrupt:");
1812 result(); /* get the status ready for set_fdc */
1813 if (FDCS->reset) {
1814 printk("reset set in interrupt, calling %p\n", cont->error);
1815 cont->error(); /* a reset just after a reset. BAD! */
1816 }
1817 cont->redo();
1818}
1819
1820/*
1821 * reset is done by pulling bit 2 of DOR low for a while (old FDCs),
1822 * or by setting the self clearing bit 7 of STATUS (newer FDCs)
1823 */
1824static void reset_fdc(void)
1825{
1826 unsigned long flags;
1827
1828 do_floppy = reset_interrupt;
1829 FDCS->reset = 0;
1830 reset_fdc_info(0);
1831
1832 /* Pseudo-DMA may intercept 'reset finished' interrupt. */
1833 /* Irrelevant for systems with true DMA (i386). */
1834
1835 flags = claim_dma_lock();
1836 fd_disable_dma();
1837 release_dma_lock(flags);
1838
1839 if (FDCS->version >= FDC_82072A)
1840 fd_outb(0x80 | (FDCS->dtr & 3), FD_STATUS);
1841 else {
1842 fd_outb(FDCS->dor & ~0x04, FD_DOR);
1843 udelay(FD_RESET_DELAY);
1844 fd_outb(FDCS->dor, FD_DOR);
1845 }
1846}
1847
1848static void show_floppy(void)
1849{
1850 int i;
1851
1852 printk("\n");
1853 printk("floppy driver state\n");
1854 printk("-------------------\n");
1855 printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
1856 jiffies, interruptjiffies, jiffies - interruptjiffies,
1857 lasthandler);
1858
1859#ifdef FLOPPY_SANITY_CHECK
1860 printk("timeout_message=%s\n", timeout_message);
1861 printk("last output bytes:\n");
1862 for (i = 0; i < OLOGSIZE; i++)
1863 printk("%2x %2x %lu\n",
1864 output_log[(i + output_log_pos) % OLOGSIZE].data,
1865 output_log[(i + output_log_pos) % OLOGSIZE].status,
1866 output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
1867 printk("last result at %lu\n", resultjiffies);
1868 printk("last redo_fd_request at %lu\n", lastredo);
1869 for (i = 0; i < resultsize; i++) {
1870 printk("%2x ", reply_buffer[i]);
1871 }
1872 printk("\n");
1873#endif
1874
1875 printk("status=%x\n", fd_inb(FD_STATUS));
1876 printk("fdc_busy=%lu\n", fdc_busy);
1877 if (do_floppy)
1878 printk("do_floppy=%p\n", do_floppy);
David Howells365970a2006-11-22 14:54:49 +00001879 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880 printk("floppy_work.func=%p\n", floppy_work.func);
1881 if (timer_pending(&fd_timer))
1882 printk("fd_timer.function=%p\n", fd_timer.function);
1883 if (timer_pending(&fd_timeout)) {
1884 printk("timer_function=%p\n", fd_timeout.function);
1885 printk("expires=%lu\n", fd_timeout.expires - jiffies);
1886 printk("now=%lu\n", jiffies);
1887 }
1888 printk("cont=%p\n", cont);
1889 printk("current_req=%p\n", current_req);
1890 printk("command_status=%d\n", command_status);
1891 printk("\n");
1892}
1893
1894static void floppy_shutdown(unsigned long data)
1895{
1896 unsigned long flags;
1897
1898 if (!initialising)
1899 show_floppy();
1900 cancel_activity();
1901
1902 floppy_enable_hlt();
1903
1904 flags = claim_dma_lock();
1905 fd_disable_dma();
1906 release_dma_lock(flags);
1907
1908 /* avoid dma going to a random drive after shutdown */
1909
1910 if (!initialising)
1911 DPRINT("floppy timeout called\n");
1912 FDCS->reset = 1;
1913 if (cont) {
1914 cont->done(0);
1915 cont->redo(); /* this will recall reset when needed */
1916 } else {
1917 printk("no cont in shutdown!\n");
1918 process_fd_request();
1919 }
1920 is_alive("floppy shutdown");
1921}
1922
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923/* start motor, check media-changed condition and write protection */
Jesper Juhl06f748c2007-10-16 23:30:57 -07001924static int start_motor(void (*function)(void))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001926 int mask;
1927 int data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928
1929 mask = 0xfc;
1930 data = UNIT(current_drive);
1931 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)) {
1932 if (!(FDCS->dor & (0x10 << UNIT(current_drive)))) {
1933 set_debugt();
1934 /* no read since this drive is running */
1935 DRS->first_read_date = 0;
1936 /* note motor start time if motor is not yet running */
1937 DRS->spinup_date = jiffies;
1938 data |= (0x10 << UNIT(current_drive));
1939 }
1940 } else if (FDCS->dor & (0x10 << UNIT(current_drive)))
1941 mask &= ~(0x10 << UNIT(current_drive));
1942
1943 /* starts motor and selects floppy */
1944 del_timer(motor_off_timer + current_drive);
1945 set_dor(fdc, mask, data);
1946
1947 /* wait_for_completion also schedules reset if needed. */
1948 return (fd_wait_for_completion(DRS->select_date + DP->select_delay,
1949 (timeout_fn) function));
1950}
1951
1952static void floppy_ready(void)
1953{
1954 CHECK_RESET;
1955 if (start_motor(floppy_ready))
1956 return;
1957 if (fdc_dtr())
1958 return;
1959
1960#ifdef DCL_DEBUG
1961 if (DP->flags & FD_DEBUG) {
1962 DPRINT("calling disk change from floppy_ready\n");
1963 }
1964#endif
1965 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
1966 disk_change(current_drive) && !DP->select_delay)
1967 twaddle(); /* this clears the dcl on certain drive/controller
1968 * combinations */
1969
1970#ifdef fd_chose_dma_mode
1971 if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) {
1972 unsigned long flags = claim_dma_lock();
1973 fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length);
1974 release_dma_lock(flags);
1975 }
1976#endif
1977
1978 if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)) {
1979 perpendicular_mode();
1980 fdc_specify(); /* must be done here because of hut, hlt ... */
1981 seek_floppy();
1982 } else {
1983 if ((raw_cmd->flags & FD_RAW_READ) ||
1984 (raw_cmd->flags & FD_RAW_WRITE))
1985 fdc_specify();
1986 setup_rw_floppy();
1987 }
1988}
1989
1990static void floppy_start(void)
1991{
1992 reschedule_timeout(current_reqD, "floppy start", 0);
1993
1994 scandrives();
1995#ifdef DCL_DEBUG
1996 if (DP->flags & FD_DEBUG) {
1997 DPRINT("setting NEWCHANGE in floppy_start\n");
1998 }
1999#endif
2000 SETF(FD_DISK_NEWCHANGE);
2001 floppy_ready();
2002}
2003
2004/*
2005 * ========================================================================
2006 * here ends the bottom half. Exported routines are:
2007 * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
2008 * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
2009 * Initialization also uses output_byte, result, set_dor, floppy_interrupt
2010 * and set_dor.
2011 * ========================================================================
2012 */
2013/*
2014 * General purpose continuations.
2015 * ==============================
2016 */
2017
2018static void do_wakeup(void)
2019{
2020 reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
2021 cont = NULL;
2022 command_status += 2;
2023 wake_up(&command_done);
2024}
2025
2026static struct cont_t wakeup_cont = {
2027 .interrupt = empty,
2028 .redo = do_wakeup,
2029 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002030 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031};
2032
2033static struct cont_t intr_cont = {
2034 .interrupt = empty,
2035 .redo = process_fd_request,
2036 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002037 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038};
2039
Jesper Juhl06f748c2007-10-16 23:30:57 -07002040static int wait_til_done(void (*handler)(void), int interruptible)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041{
2042 int ret;
2043
2044 schedule_bh(handler);
2045
2046 if (command_status < 2 && NO_SIGNAL) {
2047 DECLARE_WAITQUEUE(wait, current);
2048
2049 add_wait_queue(&command_done, &wait);
2050 for (;;) {
2051 set_current_state(interruptible ?
2052 TASK_INTERRUPTIBLE :
2053 TASK_UNINTERRUPTIBLE);
2054
2055 if (command_status >= 2 || !NO_SIGNAL)
2056 break;
2057
2058 is_alive("wait_til_done");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 schedule();
2060 }
2061
2062 set_current_state(TASK_RUNNING);
2063 remove_wait_queue(&command_done, &wait);
2064 }
2065
2066 if (command_status < 2) {
2067 cancel_activity();
2068 cont = &intr_cont;
2069 reset_fdc();
2070 return -EINTR;
2071 }
2072
2073 if (FDCS->reset)
2074 command_status = FD_COMMAND_ERROR;
2075 if (command_status == FD_COMMAND_OKAY)
2076 ret = 0;
2077 else
2078 ret = -EIO;
2079 command_status = FD_COMMAND_NONE;
2080 return ret;
2081}
2082
2083static void generic_done(int result)
2084{
2085 command_status = result;
2086 cont = &wakeup_cont;
2087}
2088
2089static void generic_success(void)
2090{
2091 cont->done(1);
2092}
2093
2094static void generic_failure(void)
2095{
2096 cont->done(0);
2097}
2098
2099static void success_and_wakeup(void)
2100{
2101 generic_success();
2102 cont->redo();
2103}
2104
2105/*
2106 * formatting and rw support.
2107 * ==========================
2108 */
2109
2110static int next_valid_format(void)
2111{
2112 int probed_format;
2113
2114 probed_format = DRS->probed_format;
2115 while (1) {
2116 if (probed_format >= 8 || !DP->autodetect[probed_format]) {
2117 DRS->probed_format = 0;
2118 return 1;
2119 }
2120 if (floppy_type[DP->autodetect[probed_format]].sect) {
2121 DRS->probed_format = probed_format;
2122 return 0;
2123 }
2124 probed_format++;
2125 }
2126}
2127
2128static void bad_flp_intr(void)
2129{
2130 int err_count;
2131
2132 if (probing) {
2133 DRS->probed_format++;
2134 if (!next_valid_format())
2135 return;
2136 }
2137 err_count = ++(*errors);
2138 INFBOUND(DRWE->badness, err_count);
2139 if (err_count > DP->max_errors.abort)
2140 cont->done(0);
2141 if (err_count > DP->max_errors.reset)
2142 FDCS->reset = 1;
2143 else if (err_count > DP->max_errors.recal)
2144 DRS->track = NEED_2_RECAL;
2145}
2146
2147static void set_floppy(int drive)
2148{
2149 int type = ITYPE(UDRS->fd_device);
Jesper Juhl06f748c2007-10-16 23:30:57 -07002150
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 if (type)
2152 _floppy = floppy_type + type;
2153 else
2154 _floppy = current_type[drive];
2155}
2156
2157/*
2158 * formatting support.
2159 * ===================
2160 */
2161static void format_interrupt(void)
2162{
2163 switch (interpret_errors()) {
2164 case 1:
2165 cont->error();
2166 case 2:
2167 break;
2168 case 0:
2169 cont->done(1);
2170 }
2171 cont->redo();
2172}
2173
2174#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
2175#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
2176#define CT(x) ((x) | 0xc0)
2177static void setup_format_params(int track)
2178{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002179 int n;
2180 int il;
2181 int count;
2182 int head_shift;
2183 int track_shift;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 struct fparm {
2185 unsigned char track, head, sect, size;
2186 } *here = (struct fparm *)floppy_track_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187
2188 raw_cmd = &default_raw_cmd;
2189 raw_cmd->track = track;
2190
2191 raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
2192 FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
2193 raw_cmd->rate = _floppy->rate & 0x43;
2194 raw_cmd->cmd_count = NR_F;
2195 COMMAND = FM_MODE(_floppy, FD_FORMAT);
2196 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, format_req.head);
2197 F_SIZECODE = FD_SIZECODE(_floppy);
2198 F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE;
2199 F_GAP = _floppy->fmt_gap;
2200 F_FILL = FD_FILL_BYTE;
2201
2202 raw_cmd->kernel_data = floppy_track_buffer;
2203 raw_cmd->length = 4 * F_SECT_PER_TRACK;
2204
2205 /* allow for about 30ms for data transport per track */
2206 head_shift = (F_SECT_PER_TRACK + 5) / 6;
2207
2208 /* a ``cylinder'' is two tracks plus a little stepping time */
2209 track_shift = 2 * head_shift + 3;
2210
2211 /* position of logical sector 1 on this track */
2212 n = (track_shift * format_req.track + head_shift * format_req.head)
2213 % F_SECT_PER_TRACK;
2214
2215 /* determine interleave */
2216 il = 1;
2217 if (_floppy->fmt_gap < 0x22)
2218 il++;
2219
2220 /* initialize field */
2221 for (count = 0; count < F_SECT_PER_TRACK; ++count) {
2222 here[count].track = format_req.track;
2223 here[count].head = format_req.head;
2224 here[count].sect = 0;
2225 here[count].size = F_SIZECODE;
2226 }
2227 /* place logical sectors */
2228 for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
2229 here[n].sect = count;
2230 n = (n + il) % F_SECT_PER_TRACK;
2231 if (here[n].sect) { /* sector busy, find next free sector */
2232 ++n;
2233 if (n >= F_SECT_PER_TRACK) {
2234 n -= F_SECT_PER_TRACK;
2235 while (here[n].sect)
2236 ++n;
2237 }
2238 }
2239 }
2240 if (_floppy->stretch & FD_ZEROBASED) {
2241 for (count = 0; count < F_SECT_PER_TRACK; count++)
2242 here[count].sect--;
2243 }
2244}
2245
2246static void redo_format(void)
2247{
2248 buffer_track = -1;
2249 setup_format_params(format_req.track << STRETCH(_floppy));
2250 floppy_start();
2251 debugt("queue format request");
2252}
2253
2254static struct cont_t format_cont = {
2255 .interrupt = format_interrupt,
2256 .redo = redo_format,
2257 .error = bad_flp_intr,
2258 .done = generic_done
2259};
2260
2261static int do_format(int drive, struct format_descr *tmp_format_req)
2262{
2263 int ret;
2264
2265 LOCK_FDC(drive, 1);
2266 set_floppy(drive);
2267 if (!_floppy ||
2268 _floppy->track > DP->tracks ||
2269 tmp_format_req->track >= _floppy->track ||
2270 tmp_format_req->head >= _floppy->head ||
2271 (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) ||
2272 !_floppy->fmt_gap) {
2273 process_fd_request();
2274 return -EINVAL;
2275 }
2276 format_req = *tmp_format_req;
2277 format_errors = 0;
2278 cont = &format_cont;
2279 errors = &format_errors;
2280 IWAIT(redo_format);
2281 process_fd_request();
2282 return ret;
2283}
2284
2285/*
2286 * Buffer read/write and support
2287 * =============================
2288 */
2289
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002290static void floppy_end_request(struct request *req, int error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291{
2292 unsigned int nr_sectors = current_count_sectors;
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002293 unsigned int drive = (unsigned long)req->rq_disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
2295 /* current_count_sectors can be zero if transfer failed */
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002296 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 nr_sectors = req->current_nr_sectors;
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002298 if (__blk_end_request(req, error, nr_sectors << 9))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
2301 /* We're done with the request */
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002302 floppy_off(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 current_req = NULL;
2304}
2305
2306/* new request_done. Can handle physical sectors which are smaller than a
2307 * logical buffer */
2308static void request_done(int uptodate)
2309{
2310 struct request_queue *q = floppy_queue;
2311 struct request *req = current_req;
2312 unsigned long flags;
2313 int block;
2314
2315 probing = 0;
2316 reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
2317
2318 if (!req) {
2319 printk("floppy.c: no request in request_done\n");
2320 return;
2321 }
2322
2323 if (uptodate) {
2324 /* maintain values for invalidation on geometry
2325 * change */
2326 block = current_count_sectors + req->sector;
2327 INFBOUND(DRS->maxblock, block);
2328 if (block > _floppy->sect)
2329 DRS->maxtrack = 1;
2330
2331 /* unlock chained buffers */
2332 spin_lock_irqsave(q->queue_lock, flags);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002333 floppy_end_request(req, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 spin_unlock_irqrestore(q->queue_lock, flags);
2335 } else {
2336 if (rq_data_dir(req) == WRITE) {
2337 /* record write error information */
2338 DRWE->write_errors++;
2339 if (DRWE->write_errors == 1) {
2340 DRWE->first_error_sector = req->sector;
2341 DRWE->first_error_generation = DRS->generation;
2342 }
2343 DRWE->last_error_sector = req->sector;
2344 DRWE->last_error_generation = DRS->generation;
2345 }
2346 spin_lock_irqsave(q->queue_lock, flags);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002347 floppy_end_request(req, -EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 spin_unlock_irqrestore(q->queue_lock, flags);
2349 }
2350}
2351
2352/* Interrupt handler evaluating the result of the r/w operation */
2353static void rw_interrupt(void)
2354{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002355 int eoc;
2356 int ssize;
2357 int heads;
2358 int nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
2360 if (R_HEAD >= 2) {
2361 /* some Toshiba floppy controllers occasionnally seem to
2362 * return bogus interrupts after read/write operations, which
2363 * can be recognized by a bad head number (>= 2) */
2364 return;
2365 }
2366
2367 if (!DRS->first_read_date)
2368 DRS->first_read_date = jiffies;
2369
2370 nr_sectors = 0;
2371 CODE2SIZE;
2372
2373 if (ST1 & ST1_EOC)
2374 eoc = 1;
2375 else
2376 eoc = 0;
2377
2378 if (COMMAND & 0x80)
2379 heads = 2;
2380 else
2381 heads = 1;
2382
2383 nr_sectors = (((R_TRACK - TRACK) * heads +
2384 R_HEAD - HEAD) * SECT_PER_TRACK +
2385 R_SECTOR - SECTOR + eoc) << SIZECODE >> 2;
2386
2387#ifdef FLOPPY_SANITY_CHECK
2388 if (nr_sectors / ssize >
2389 (in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
2390 DPRINT("long rw: %x instead of %lx\n",
2391 nr_sectors, current_count_sectors);
2392 printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
2393 printk("rh=%d h=%d\n", R_HEAD, HEAD);
2394 printk("rt=%d t=%d\n", R_TRACK, TRACK);
2395 printk("heads=%d eoc=%d\n", heads, eoc);
2396 printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
2397 fsector_t, ssize);
2398 printk("in_sector_offset=%d\n", in_sector_offset);
2399 }
2400#endif
2401
2402 nr_sectors -= in_sector_offset;
2403 INFBOUND(nr_sectors, 0);
2404 SUPBOUND(current_count_sectors, nr_sectors);
2405
2406 switch (interpret_errors()) {
2407 case 2:
2408 cont->redo();
2409 return;
2410 case 1:
2411 if (!current_count_sectors) {
2412 cont->error();
2413 cont->redo();
2414 return;
2415 }
2416 break;
2417 case 0:
2418 if (!current_count_sectors) {
2419 cont->redo();
2420 return;
2421 }
2422 current_type[current_drive] = _floppy;
2423 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2424 break;
2425 }
2426
2427 if (probing) {
2428 if (DP->flags & FTD_MSG)
2429 DPRINT("Auto-detected floppy type %s in fd%d\n",
2430 _floppy->name, current_drive);
2431 current_type[current_drive] = _floppy;
2432 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2433 probing = 0;
2434 }
2435
2436 if (CT(COMMAND) != FD_READ ||
2437 raw_cmd->kernel_data == current_req->buffer) {
2438 /* transfer directly from buffer */
2439 cont->done(1);
2440 } else if (CT(COMMAND) == FD_READ) {
2441 buffer_track = raw_cmd->track;
2442 buffer_drive = current_drive;
2443 INFBOUND(buffer_max, nr_sectors + fsector_t);
2444 }
2445 cont->redo();
2446}
2447
2448/* Compute maximal contiguous buffer size. */
2449static int buffer_chain_size(void)
2450{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 struct bio_vec *bv;
NeilBrown5705f702007-09-25 12:35:59 +02002452 int size;
2453 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 char *base;
2455
2456 base = bio_data(current_req->bio);
2457 size = 0;
2458
NeilBrown5705f702007-09-25 12:35:59 +02002459 rq_for_each_segment(bv, current_req, iter) {
2460 if (page_address(bv->bv_page) + bv->bv_offset != base + size)
2461 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
NeilBrown5705f702007-09-25 12:35:59 +02002463 size += bv->bv_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 }
2465
2466 return size >> 9;
2467}
2468
2469/* Compute the maximal transfer size */
2470static int transfer_size(int ssize, int max_sector, int max_size)
2471{
2472 SUPBOUND(max_sector, fsector_t + max_size);
2473
2474 /* alignment */
2475 max_sector -= (max_sector % _floppy->sect) % ssize;
2476
2477 /* transfer size, beginning not aligned */
2478 current_count_sectors = max_sector - fsector_t;
2479
2480 return max_sector;
2481}
2482
2483/*
2484 * Move data from/to the track buffer to/from the buffer cache.
2485 */
2486static void copy_buffer(int ssize, int max_sector, int max_sector_2)
2487{
2488 int remaining; /* number of transferred 512-byte sectors */
2489 struct bio_vec *bv;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002490 char *buffer;
2491 char *dma_buffer;
NeilBrown5705f702007-09-25 12:35:59 +02002492 int size;
2493 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
2495 max_sector = transfer_size(ssize,
2496 min(max_sector, max_sector_2),
2497 current_req->nr_sectors);
2498
2499 if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
2500 buffer_max > fsector_t + current_req->nr_sectors)
2501 current_count_sectors = min_t(int, buffer_max - fsector_t,
2502 current_req->nr_sectors);
2503
2504 remaining = current_count_sectors << 9;
2505#ifdef FLOPPY_SANITY_CHECK
2506 if ((remaining >> 9) > current_req->nr_sectors &&
2507 CT(COMMAND) == FD_WRITE) {
2508 DPRINT("in copy buffer\n");
2509 printk("current_count_sectors=%ld\n", current_count_sectors);
2510 printk("remaining=%d\n", remaining >> 9);
2511 printk("current_req->nr_sectors=%ld\n",
2512 current_req->nr_sectors);
2513 printk("current_req->current_nr_sectors=%u\n",
2514 current_req->current_nr_sectors);
2515 printk("max_sector=%d\n", max_sector);
2516 printk("ssize=%d\n", ssize);
2517 }
2518#endif
2519
2520 buffer_max = max(max_sector, buffer_max);
2521
2522 dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
2523
2524 size = current_req->current_nr_sectors << 9;
2525
NeilBrown5705f702007-09-25 12:35:59 +02002526 rq_for_each_segment(bv, current_req, iter) {
2527 if (!remaining)
2528 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529
NeilBrown5705f702007-09-25 12:35:59 +02002530 size = bv->bv_len;
2531 SUPBOUND(size, remaining);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
NeilBrown5705f702007-09-25 12:35:59 +02002533 buffer = page_address(bv->bv_page) + bv->bv_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534#ifdef FLOPPY_SANITY_CHECK
NeilBrown5705f702007-09-25 12:35:59 +02002535 if (dma_buffer + size >
2536 floppy_track_buffer + (max_buffer_sectors << 10) ||
2537 dma_buffer < floppy_track_buffer) {
2538 DPRINT("buffer overrun in copy buffer %d\n",
2539 (int)((floppy_track_buffer -
2540 dma_buffer) >> 9));
2541 printk("fsector_t=%d buffer_min=%d\n",
2542 fsector_t, buffer_min);
2543 printk("current_count_sectors=%ld\n",
2544 current_count_sectors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 if (CT(COMMAND) == FD_READ)
NeilBrown5705f702007-09-25 12:35:59 +02002546 printk("read\n");
2547 if (CT(COMMAND) == FD_WRITE)
2548 printk("write\n");
2549 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 }
NeilBrown5705f702007-09-25 12:35:59 +02002551 if (((unsigned long)buffer) % 512)
2552 DPRINT("%p buffer not aligned\n", buffer);
2553#endif
2554 if (CT(COMMAND) == FD_READ)
2555 memcpy(buffer, dma_buffer, size);
2556 else
2557 memcpy(dma_buffer, buffer, size);
2558
2559 remaining -= size;
2560 dma_buffer += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 }
2562#ifdef FLOPPY_SANITY_CHECK
2563 if (remaining) {
2564 if (remaining > 0)
2565 max_sector -= remaining >> 9;
2566 DPRINT("weirdness: remaining %d\n", remaining >> 9);
2567 }
2568#endif
2569}
2570
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571/* work around a bug in pseudo DMA
2572 * (on some FDCs) pseudo DMA does not stop when the CPU stops
2573 * sending data. Hence we need a different way to signal the
2574 * transfer length: We use SECT_PER_TRACK. Unfortunately, this
2575 * does not work with MT, hence we can only transfer one head at
2576 * a time
2577 */
2578static void virtualdmabug_workaround(void)
2579{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002580 int hard_sectors;
2581 int end_sector;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
2583 if (CT(COMMAND) == FD_WRITE) {
2584 COMMAND &= ~0x80; /* switch off multiple track mode */
2585
2586 hard_sectors = raw_cmd->length >> (7 + SIZECODE);
2587 end_sector = SECTOR + hard_sectors - 1;
2588#ifdef FLOPPY_SANITY_CHECK
2589 if (end_sector > SECT_PER_TRACK) {
2590 printk("too many sectors %d > %d\n",
2591 end_sector, SECT_PER_TRACK);
2592 return;
2593 }
2594#endif
2595 SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points
2596 * to end of transfer */
2597 }
2598}
2599
2600/*
2601 * Formulate a read/write request.
2602 * this routine decides where to load the data (directly to buffer, or to
2603 * tmp floppy area), how much data to load (the size of the buffer, the whole
2604 * track, or a single sector)
2605 * All floppy_track_buffer handling goes in here. If we ever add track buffer
2606 * allocation on the fly, it should be done here. No other part should need
2607 * modification.
2608 */
2609
2610static int make_raw_rw_request(void)
2611{
2612 int aligned_sector_t;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002613 int max_sector;
2614 int max_size;
2615 int tracksize;
2616 int ssize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617
2618 if (max_buffer_sectors == 0) {
2619 printk("VFS: Block I/O scheduled on unopened device\n");
2620 return 0;
2621 }
2622
2623 set_fdc((long)current_req->rq_disk->private_data);
2624
2625 raw_cmd = &default_raw_cmd;
2626 raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
2627 FD_RAW_NEED_SEEK;
2628 raw_cmd->cmd_count = NR_RW;
2629 if (rq_data_dir(current_req) == READ) {
2630 raw_cmd->flags |= FD_RAW_READ;
2631 COMMAND = FM_MODE(_floppy, FD_READ);
2632 } else if (rq_data_dir(current_req) == WRITE) {
2633 raw_cmd->flags |= FD_RAW_WRITE;
2634 COMMAND = FM_MODE(_floppy, FD_WRITE);
2635 } else {
2636 DPRINT("make_raw_rw_request: unknown command\n");
2637 return 0;
2638 }
2639
2640 max_sector = _floppy->sect * _floppy->head;
2641
2642 TRACK = (int)current_req->sector / max_sector;
2643 fsector_t = (int)current_req->sector % max_sector;
2644 if (_floppy->track && TRACK >= _floppy->track) {
2645 if (current_req->current_nr_sectors & 1) {
2646 current_count_sectors = 1;
2647 return 1;
2648 } else
2649 return 0;
2650 }
2651 HEAD = fsector_t / _floppy->sect;
2652
2653 if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
2654 TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
2655 max_sector = _floppy->sect;
2656
2657 /* 2M disks have phantom sectors on the first track */
2658 if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)) {
2659 max_sector = 2 * _floppy->sect / 3;
2660 if (fsector_t >= max_sector) {
2661 current_count_sectors =
2662 min_t(int, _floppy->sect - fsector_t,
2663 current_req->nr_sectors);
2664 return 1;
2665 }
2666 SIZECODE = 2;
2667 } else
2668 SIZECODE = FD_SIZECODE(_floppy);
2669 raw_cmd->rate = _floppy->rate & 0x43;
2670 if ((_floppy->rate & FD_2M) && (TRACK || HEAD) && raw_cmd->rate == 2)
2671 raw_cmd->rate = 1;
2672
2673 if (SIZECODE)
2674 SIZECODE2 = 0xff;
2675 else
2676 SIZECODE2 = 0x80;
2677 raw_cmd->track = TRACK << STRETCH(_floppy);
2678 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD);
2679 GAP = _floppy->gap;
2680 CODE2SIZE;
2681 SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
2682 SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
2683 ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1);
2684
2685 /* tracksize describes the size which can be filled up with sectors
2686 * of size ssize.
2687 */
2688 tracksize = _floppy->sect - _floppy->sect % ssize;
2689 if (tracksize < _floppy->sect) {
2690 SECT_PER_TRACK++;
2691 if (tracksize <= fsector_t % _floppy->sect)
2692 SECTOR--;
2693
2694 /* if we are beyond tracksize, fill up using smaller sectors */
2695 while (tracksize <= fsector_t % _floppy->sect) {
2696 while (tracksize + ssize > _floppy->sect) {
2697 SIZECODE--;
2698 ssize >>= 1;
2699 }
2700 SECTOR++;
2701 SECT_PER_TRACK++;
2702 tracksize += ssize;
2703 }
2704 max_sector = HEAD * _floppy->sect + tracksize;
2705 } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) {
2706 max_sector = _floppy->sect;
2707 } else if (!HEAD && CT(COMMAND) == FD_WRITE) {
2708 /* for virtual DMA bug workaround */
2709 max_sector = _floppy->sect;
2710 }
2711
2712 in_sector_offset = (fsector_t % _floppy->sect) % ssize;
2713 aligned_sector_t = fsector_t - in_sector_offset;
2714 max_size = current_req->nr_sectors;
2715 if ((raw_cmd->track == buffer_track) &&
2716 (current_drive == buffer_drive) &&
2717 (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
2718 /* data already in track buffer */
2719 if (CT(COMMAND) == FD_READ) {
2720 copy_buffer(1, max_sector, buffer_max);
2721 return 1;
2722 }
2723 } else if (in_sector_offset || current_req->nr_sectors < ssize) {
2724 if (CT(COMMAND) == FD_WRITE) {
2725 if (fsector_t + current_req->nr_sectors > ssize &&
2726 fsector_t + current_req->nr_sectors < ssize + ssize)
2727 max_size = ssize + ssize;
2728 else
2729 max_size = ssize;
2730 }
2731 raw_cmd->flags &= ~FD_RAW_WRITE;
2732 raw_cmd->flags |= FD_RAW_READ;
2733 COMMAND = FM_MODE(_floppy, FD_READ);
2734 } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
2735 unsigned long dma_limit;
2736 int direct, indirect;
2737
2738 indirect =
2739 transfer_size(ssize, max_sector,
2740 max_buffer_sectors * 2) - fsector_t;
2741
2742 /*
2743 * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
2744 * on a 64 bit machine!
2745 */
2746 max_size = buffer_chain_size();
2747 dma_limit =
2748 (MAX_DMA_ADDRESS -
2749 ((unsigned long)current_req->buffer)) >> 9;
2750 if ((unsigned long)max_size > dma_limit) {
2751 max_size = dma_limit;
2752 }
2753 /* 64 kb boundaries */
2754 if (CROSS_64KB(current_req->buffer, max_size << 9))
2755 max_size = (K_64 -
2756 ((unsigned long)current_req->buffer) %
2757 K_64) >> 9;
2758 direct = transfer_size(ssize, max_sector, max_size) - fsector_t;
2759 /*
2760 * We try to read tracks, but if we get too many errors, we
2761 * go back to reading just one sector at a time.
2762 *
2763 * This means we should be able to read a sector even if there
2764 * are other bad sectors on this track.
2765 */
2766 if (!direct ||
2767 (indirect * 2 > direct * 3 &&
Jesper Juhlaee90412007-10-16 23:30:58 -07002768 *errors < DP->max_errors.read_track && ((!probing
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 || (DP->read_track & (1 << DRS->probed_format)))))) {
2770 max_size = current_req->nr_sectors;
2771 } else {
2772 raw_cmd->kernel_data = current_req->buffer;
2773 raw_cmd->length = current_count_sectors << 9;
2774 if (raw_cmd->length == 0) {
2775 DPRINT
2776 ("zero dma transfer attempted from make_raw_request\n");
2777 DPRINT("indirect=%d direct=%d fsector_t=%d",
2778 indirect, direct, fsector_t);
2779 return 0;
2780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 virtualdmabug_workaround();
2782 return 2;
2783 }
2784 }
2785
2786 if (CT(COMMAND) == FD_READ)
2787 max_size = max_sector; /* unbounded */
2788
2789 /* claim buffer track if needed */
2790 if (buffer_track != raw_cmd->track || /* bad track */
2791 buffer_drive != current_drive || /* bad drive */
2792 fsector_t > buffer_max ||
2793 fsector_t < buffer_min ||
2794 ((CT(COMMAND) == FD_READ ||
2795 (!in_sector_offset && current_req->nr_sectors >= ssize)) &&
2796 max_sector > 2 * max_buffer_sectors + buffer_min &&
2797 max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
2798 /* not enough space */
2799 ) {
2800 buffer_track = -1;
2801 buffer_drive = current_drive;
2802 buffer_max = buffer_min = aligned_sector_t;
2803 }
2804 raw_cmd->kernel_data = floppy_track_buffer +
2805 ((aligned_sector_t - buffer_min) << 9);
2806
2807 if (CT(COMMAND) == FD_WRITE) {
2808 /* copy write buffer to track buffer.
2809 * if we get here, we know that the write
2810 * is either aligned or the data already in the buffer
2811 * (buffer will be overwritten) */
2812#ifdef FLOPPY_SANITY_CHECK
2813 if (in_sector_offset && buffer_track == -1)
2814 DPRINT("internal error offset !=0 on write\n");
2815#endif
2816 buffer_track = raw_cmd->track;
2817 buffer_drive = current_drive;
2818 copy_buffer(ssize, max_sector,
2819 2 * max_buffer_sectors + buffer_min);
2820 } else
2821 transfer_size(ssize, max_sector,
2822 2 * max_buffer_sectors + buffer_min -
2823 aligned_sector_t);
2824
2825 /* round up current_count_sectors to get dma xfer size */
2826 raw_cmd->length = in_sector_offset + current_count_sectors;
2827 raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
2828 raw_cmd->length <<= 9;
2829#ifdef FLOPPY_SANITY_CHECK
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830 if ((raw_cmd->length < current_count_sectors << 9) ||
2831 (raw_cmd->kernel_data != current_req->buffer &&
2832 CT(COMMAND) == FD_WRITE &&
2833 (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
2834 aligned_sector_t < buffer_min)) ||
2835 raw_cmd->length % (128 << SIZECODE) ||
2836 raw_cmd->length <= 0 || current_count_sectors <= 0) {
2837 DPRINT("fractionary current count b=%lx s=%lx\n",
2838 raw_cmd->length, current_count_sectors);
2839 if (raw_cmd->kernel_data != current_req->buffer)
2840 printk("addr=%d, length=%ld\n",
2841 (int)((raw_cmd->kernel_data -
2842 floppy_track_buffer) >> 9),
2843 current_count_sectors);
2844 printk("st=%d ast=%d mse=%d msi=%d\n",
2845 fsector_t, aligned_sector_t, max_sector, max_size);
2846 printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
2847 printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
2848 COMMAND, SECTOR, HEAD, TRACK);
2849 printk("buffer drive=%d\n", buffer_drive);
2850 printk("buffer track=%d\n", buffer_track);
2851 printk("buffer_min=%d\n", buffer_min);
2852 printk("buffer_max=%d\n", buffer_max);
2853 return 0;
2854 }
2855
2856 if (raw_cmd->kernel_data != current_req->buffer) {
2857 if (raw_cmd->kernel_data < floppy_track_buffer ||
2858 current_count_sectors < 0 ||
2859 raw_cmd->length < 0 ||
2860 raw_cmd->kernel_data + raw_cmd->length >
2861 floppy_track_buffer + (max_buffer_sectors << 10)) {
2862 DPRINT("buffer overrun in schedule dma\n");
2863 printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
2864 fsector_t, buffer_min, raw_cmd->length >> 9);
2865 printk("current_count_sectors=%ld\n",
2866 current_count_sectors);
2867 if (CT(COMMAND) == FD_READ)
2868 printk("read\n");
2869 if (CT(COMMAND) == FD_WRITE)
2870 printk("write\n");
2871 return 0;
2872 }
2873 } else if (raw_cmd->length > current_req->nr_sectors << 9 ||
2874 current_count_sectors > current_req->nr_sectors) {
2875 DPRINT("buffer overrun in direct transfer\n");
2876 return 0;
2877 } else if (raw_cmd->length < current_count_sectors << 9) {
2878 DPRINT("more sectors than bytes\n");
2879 printk("bytes=%ld\n", raw_cmd->length >> 9);
2880 printk("sectors=%ld\n", current_count_sectors);
2881 }
2882 if (raw_cmd->length == 0) {
2883 DPRINT("zero dma transfer attempted from make_raw_request\n");
2884 return 0;
2885 }
2886#endif
2887
2888 virtualdmabug_workaround();
2889 return 2;
2890}
2891
2892static void redo_fd_request(void)
2893{
2894#define REPEAT {request_done(0); continue; }
2895 int drive;
2896 int tmp;
2897
2898 lastredo = jiffies;
2899 if (current_drive < N_DRIVE)
2900 floppy_off(current_drive);
2901
2902 for (;;) {
2903 if (!current_req) {
2904 struct request *req;
2905
2906 spin_lock_irq(floppy_queue->queue_lock);
2907 req = elv_next_request(floppy_queue);
2908 spin_unlock_irq(floppy_queue->queue_lock);
2909 if (!req) {
2910 do_floppy = NULL;
2911 unlock_fdc();
2912 return;
2913 }
2914 current_req = req;
2915 }
2916 drive = (long)current_req->rq_disk->private_data;
2917 set_fdc(drive);
2918 reschedule_timeout(current_reqD, "redo fd request", 0);
2919
2920 set_floppy(drive);
2921 raw_cmd = &default_raw_cmd;
2922 raw_cmd->flags = 0;
2923 if (start_motor(redo_fd_request))
2924 return;
2925 disk_change(current_drive);
2926 if (test_bit(current_drive, &fake_change) ||
2927 TESTF(FD_DISK_CHANGED)) {
2928 DPRINT("disk absent or changed during operation\n");
2929 REPEAT;
2930 }
2931 if (!_floppy) { /* Autodetection */
2932 if (!probing) {
2933 DRS->probed_format = 0;
2934 if (next_valid_format()) {
2935 DPRINT("no autodetectable formats\n");
2936 _floppy = NULL;
2937 REPEAT;
2938 }
2939 }
2940 probing = 1;
2941 _floppy =
2942 floppy_type + DP->autodetect[DRS->probed_format];
2943 } else
2944 probing = 0;
2945 errors = &(current_req->errors);
2946 tmp = make_raw_rw_request();
2947 if (tmp < 2) {
2948 request_done(tmp);
2949 continue;
2950 }
2951
2952 if (TESTF(FD_NEED_TWADDLE))
2953 twaddle();
2954 schedule_bh(floppy_start);
2955 debugt("queue fd request");
2956 return;
2957 }
2958#undef REPEAT
2959}
2960
2961static struct cont_t rw_cont = {
2962 .interrupt = rw_interrupt,
2963 .redo = redo_fd_request,
2964 .error = bad_flp_intr,
2965 .done = request_done
2966};
2967
2968static void process_fd_request(void)
2969{
2970 cont = &rw_cont;
2971 schedule_bh(redo_fd_request);
2972}
2973
Jens Axboe165125e2007-07-24 09:28:11 +02002974static void do_fd_request(struct request_queue * q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975{
2976 if (max_buffer_sectors == 0) {
2977 printk("VFS: do_fd_request called on non-open device\n");
2978 return;
2979 }
2980
2981 if (usage_count == 0) {
2982 printk("warning: usage count=0, current_req=%p exiting\n",
2983 current_req);
Jens Axboe4aff5e22006-08-10 08:44:47 +02002984 printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
2985 current_req->cmd_type, current_req->cmd_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 return;
2987 }
2988 if (test_bit(0, &fdc_busy)) {
2989 /* fdc busy, this new request will be treated when the
2990 current one is done */
2991 is_alive("do fd request, old request running");
2992 return;
2993 }
2994 lock_fdc(MAXTIMEOUT, 0);
2995 process_fd_request();
2996 is_alive("do fd request");
2997}
2998
2999static struct cont_t poll_cont = {
3000 .interrupt = success_and_wakeup,
3001 .redo = floppy_ready,
3002 .error = generic_failure,
3003 .done = generic_done
3004};
3005
3006static int poll_drive(int interruptible, int flag)
3007{
3008 int ret;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003009
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 /* no auto-sense, just clear dcl */
3011 raw_cmd = &default_raw_cmd;
3012 raw_cmd->flags = flag;
3013 raw_cmd->track = 0;
3014 raw_cmd->cmd_count = 0;
3015 cont = &poll_cont;
3016#ifdef DCL_DEBUG
3017 if (DP->flags & FD_DEBUG) {
3018 DPRINT("setting NEWCHANGE in poll_drive\n");
3019 }
3020#endif
3021 SETF(FD_DISK_NEWCHANGE);
3022 WAIT(floppy_ready);
3023 return ret;
3024}
3025
3026/*
3027 * User triggered reset
3028 * ====================
3029 */
3030
3031static void reset_intr(void)
3032{
3033 printk("weird, reset interrupt called\n");
3034}
3035
3036static struct cont_t reset_cont = {
3037 .interrupt = reset_intr,
3038 .redo = success_and_wakeup,
3039 .error = generic_failure,
3040 .done = generic_done
3041};
3042
3043static int user_reset_fdc(int drive, int arg, int interruptible)
3044{
3045 int ret;
3046
3047 ret = 0;
3048 LOCK_FDC(drive, interruptible);
3049 if (arg == FD_RESET_ALWAYS)
3050 FDCS->reset = 1;
3051 if (FDCS->reset) {
3052 cont = &reset_cont;
3053 WAIT(reset_fdc);
3054 }
3055 process_fd_request();
3056 return ret;
3057}
3058
3059/*
3060 * Misc Ioctl's and support
3061 * ========================
3062 */
3063static inline int fd_copyout(void __user *param, const void *address,
3064 unsigned long size)
3065{
3066 return copy_to_user(param, address, size) ? -EFAULT : 0;
3067}
3068
3069static inline int fd_copyin(void __user *param, void *address, unsigned long size)
3070{
3071 return copy_from_user(address, param, size) ? -EFAULT : 0;
3072}
3073
3074#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0)
3075#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0)
3076
3077#define COPYOUT(x) ECALL(_COPYOUT(x))
3078#define COPYIN(x) ECALL(_COPYIN(x))
3079
3080static inline const char *drive_name(int type, int drive)
3081{
3082 struct floppy_struct *floppy;
3083
3084 if (type)
3085 floppy = floppy_type + type;
3086 else {
3087 if (UDP->native_format)
3088 floppy = floppy_type + UDP->native_format;
3089 else
3090 return "(null)";
3091 }
3092 if (floppy->name)
3093 return floppy->name;
3094 else
3095 return "(null)";
3096}
3097
3098/* raw commands */
3099static void raw_cmd_done(int flag)
3100{
3101 int i;
3102
3103 if (!flag) {
3104 raw_cmd->flags |= FD_RAW_FAILURE;
3105 raw_cmd->flags |= FD_RAW_HARDFAILURE;
3106 } else {
3107 raw_cmd->reply_count = inr;
3108 if (raw_cmd->reply_count > MAX_REPLIES)
3109 raw_cmd->reply_count = 0;
3110 for (i = 0; i < raw_cmd->reply_count; i++)
3111 raw_cmd->reply[i] = reply_buffer[i];
3112
3113 if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3114 unsigned long flags;
3115 flags = claim_dma_lock();
3116 raw_cmd->length = fd_get_dma_residue();
3117 release_dma_lock(flags);
3118 }
3119
3120 if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
3121 (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
3122 raw_cmd->flags |= FD_RAW_FAILURE;
3123
3124 if (disk_change(current_drive))
3125 raw_cmd->flags |= FD_RAW_DISK_CHANGE;
3126 else
3127 raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
3128 if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
3129 motor_off_callback(current_drive);
3130
3131 if (raw_cmd->next &&
3132 (!(raw_cmd->flags & FD_RAW_FAILURE) ||
3133 !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
3134 ((raw_cmd->flags & FD_RAW_FAILURE) ||
3135 !(raw_cmd->flags & FD_RAW_STOP_IF_SUCCESS))) {
3136 raw_cmd = raw_cmd->next;
3137 return;
3138 }
3139 }
3140 generic_done(flag);
3141}
3142
3143static struct cont_t raw_cmd_cont = {
3144 .interrupt = success_and_wakeup,
3145 .redo = floppy_start,
3146 .error = generic_failure,
3147 .done = raw_cmd_done
3148};
3149
3150static inline int raw_cmd_copyout(int cmd, char __user *param,
3151 struct floppy_raw_cmd *ptr)
3152{
3153 int ret;
3154
3155 while (ptr) {
3156 COPYOUT(*ptr);
3157 param += sizeof(struct floppy_raw_cmd);
3158 if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) {
3159 if (ptr->length >= 0
3160 && ptr->length <= ptr->buffer_length)
3161 ECALL(fd_copyout
3162 (ptr->data, ptr->kernel_data,
3163 ptr->buffer_length - ptr->length));
3164 }
3165 ptr = ptr->next;
3166 }
3167 return 0;
3168}
3169
3170static void raw_cmd_free(struct floppy_raw_cmd **ptr)
3171{
Jesper Juhl06f748c2007-10-16 23:30:57 -07003172 struct floppy_raw_cmd *next;
3173 struct floppy_raw_cmd *this;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174
3175 this = *ptr;
3176 *ptr = NULL;
3177 while (this) {
3178 if (this->buffer_length) {
3179 fd_dma_mem_free((unsigned long)this->kernel_data,
3180 this->buffer_length);
3181 this->buffer_length = 0;
3182 }
3183 next = this->next;
3184 kfree(this);
3185 this = next;
3186 }
3187}
3188
3189static inline int raw_cmd_copyin(int cmd, char __user *param,
3190 struct floppy_raw_cmd **rcmd)
3191{
3192 struct floppy_raw_cmd *ptr;
3193 int ret;
3194 int i;
3195
3196 *rcmd = NULL;
3197 while (1) {
3198 ptr = (struct floppy_raw_cmd *)
3199 kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
3200 if (!ptr)
3201 return -ENOMEM;
3202 *rcmd = ptr;
3203 COPYIN(*ptr);
3204 ptr->next = NULL;
3205 ptr->buffer_length = 0;
3206 param += sizeof(struct floppy_raw_cmd);
3207 if (ptr->cmd_count > 33)
3208 /* the command may now also take up the space
3209 * initially intended for the reply & the
3210 * reply count. Needed for long 82078 commands
3211 * such as RESTORE, which takes ... 17 command
3212 * bytes. Murphy's law #137: When you reserve
3213 * 16 bytes for a structure, you'll one day
3214 * discover that you really need 17...
3215 */
3216 return -EINVAL;
3217
3218 for (i = 0; i < 16; i++)
3219 ptr->reply[i] = 0;
3220 ptr->resultcode = 0;
3221 ptr->kernel_data = NULL;
3222
3223 if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3224 if (ptr->length <= 0)
3225 return -EINVAL;
3226 ptr->kernel_data =
3227 (char *)fd_dma_mem_alloc(ptr->length);
3228 fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
3229 if (!ptr->kernel_data)
3230 return -ENOMEM;
3231 ptr->buffer_length = ptr->length;
3232 }
3233 if (ptr->flags & FD_RAW_WRITE)
3234 ECALL(fd_copyin(ptr->data, ptr->kernel_data,
3235 ptr->length));
3236 rcmd = &(ptr->next);
3237 if (!(ptr->flags & FD_RAW_MORE))
3238 return 0;
3239 ptr->rate &= 0x43;
3240 }
3241}
3242
3243static int raw_cmd_ioctl(int cmd, void __user *param)
3244{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245 struct floppy_raw_cmd *my_raw_cmd;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003246 int drive;
3247 int ret2;
3248 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
3250 if (FDCS->rawcmd <= 1)
3251 FDCS->rawcmd = 1;
3252 for (drive = 0; drive < N_DRIVE; drive++) {
3253 if (FDC(drive) != fdc)
3254 continue;
3255 if (drive == current_drive) {
3256 if (UDRS->fd_ref > 1) {
3257 FDCS->rawcmd = 2;
3258 break;
3259 }
3260 } else if (UDRS->fd_ref) {
3261 FDCS->rawcmd = 2;
3262 break;
3263 }
3264 }
3265
3266 if (FDCS->reset)
3267 return -EIO;
3268
3269 ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
3270 if (ret) {
3271 raw_cmd_free(&my_raw_cmd);
3272 return ret;
3273 }
3274
3275 raw_cmd = my_raw_cmd;
3276 cont = &raw_cmd_cont;
3277 ret = wait_til_done(floppy_start, 1);
3278#ifdef DCL_DEBUG
3279 if (DP->flags & FD_DEBUG) {
3280 DPRINT("calling disk change from raw_cmd ioctl\n");
3281 }
3282#endif
3283
3284 if (ret != -EINTR && FDCS->reset)
3285 ret = -EIO;
3286
3287 DRS->track = NO_TRACK;
3288
3289 ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
3290 if (!ret)
3291 ret = ret2;
3292 raw_cmd_free(&my_raw_cmd);
3293 return ret;
3294}
3295
3296static int invalidate_drive(struct block_device *bdev)
3297{
3298 /* invalidate the buffer track to force a reread */
3299 set_bit((long)bdev->bd_disk->private_data, &fake_change);
3300 process_fd_request();
3301 check_disk_change(bdev);
3302 return 0;
3303}
3304
3305static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
3306 int drive, int type, struct block_device *bdev)
3307{
3308 int cnt;
3309
3310 /* sanity checking for parameters. */
3311 if (g->sect <= 0 ||
3312 g->head <= 0 ||
3313 g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
3314 /* check if reserved bits are set */
3315 (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0)
3316 return -EINVAL;
3317 if (type) {
3318 if (!capable(CAP_SYS_ADMIN))
3319 return -EPERM;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003320 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 LOCK_FDC(drive, 1);
3322 floppy_type[type] = *g;
3323 floppy_type[type].name = "user format";
3324 for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
3325 floppy_sizes[cnt] = floppy_sizes[cnt + 0x80] =
3326 floppy_type[type].size + 1;
3327 process_fd_request();
3328 for (cnt = 0; cnt < N_DRIVE; cnt++) {
3329 struct block_device *bdev = opened_bdev[cnt];
3330 if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
3331 continue;
Christoph Hellwig2ef41632005-05-05 16:15:59 -07003332 __invalidate_device(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003334 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 } else {
3336 int oldStretch;
3337 LOCK_FDC(drive, 1);
3338 if (cmd != FDDEFPRM)
3339 /* notice a disk change immediately, else
3340 * we lose our settings immediately*/
3341 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3342 oldStretch = g->stretch;
3343 user_params[drive] = *g;
3344 if (buffer_drive == drive)
3345 SUPBOUND(buffer_max, user_params[drive].sect);
3346 current_type[drive] = &user_params[drive];
3347 floppy_sizes[drive] = user_params[drive].size;
3348 if (cmd == FDDEFPRM)
3349 DRS->keep_data = -1;
3350 else
3351 DRS->keep_data = 1;
3352 /* invalidation. Invalidate only when needed, i.e.
3353 * when there are already sectors in the buffer cache
3354 * whose number will change. This is useful, because
3355 * mtools often changes the geometry of the disk after
3356 * looking at the boot block */
3357 if (DRS->maxblock > user_params[drive].sect ||
3358 DRS->maxtrack ||
3359 ((user_params[drive].sect ^ oldStretch) &
3360 (FD_SWAPSIDES | FD_ZEROBASED)))
3361 invalidate_drive(bdev);
3362 else
3363 process_fd_request();
3364 }
3365 return 0;
3366}
3367
3368/* handle obsolete ioctl's */
3369static int ioctl_table[] = {
3370 FDCLRPRM,
3371 FDSETPRM,
3372 FDDEFPRM,
3373 FDGETPRM,
3374 FDMSGON,
3375 FDMSGOFF,
3376 FDFMTBEG,
3377 FDFMTTRK,
3378 FDFMTEND,
3379 FDSETEMSGTRESH,
3380 FDFLUSH,
3381 FDSETMAXERRS,
3382 FDGETMAXERRS,
3383 FDGETDRVTYP,
3384 FDSETDRVPRM,
3385 FDGETDRVPRM,
3386 FDGETDRVSTAT,
3387 FDPOLLDRVSTAT,
3388 FDRESET,
3389 FDGETFDCSTAT,
3390 FDWERRORCLR,
3391 FDWERRORGET,
3392 FDRAWCMD,
3393 FDEJECT,
3394 FDTWADDLE
3395};
3396
3397static inline int normalize_ioctl(int *cmd, int *size)
3398{
3399 int i;
3400
3401 for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) {
3402 if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)) {
3403 *size = _IOC_SIZE(*cmd);
3404 *cmd = ioctl_table[i];
3405 if (*size > _IOC_SIZE(*cmd)) {
3406 printk("ioctl not yet supported\n");
3407 return -EFAULT;
3408 }
3409 return 0;
3410 }
3411 }
3412 return -EINVAL;
3413}
3414
3415static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
3416{
3417 if (type)
3418 *g = &floppy_type[type];
3419 else {
3420 LOCK_FDC(drive, 0);
3421 CALL(poll_drive(0, 0));
3422 process_fd_request();
3423 *g = current_type[drive];
3424 }
3425 if (!*g)
3426 return -ENODEV;
3427 return 0;
3428}
3429
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08003430static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3431{
3432 int drive = (long)bdev->bd_disk->private_data;
3433 int type = ITYPE(drive_state[drive].fd_device);
3434 struct floppy_struct *g;
3435 int ret;
3436
3437 ret = get_floppy_geometry(drive, type, &g);
3438 if (ret)
3439 return ret;
3440
3441 geo->heads = g->head;
3442 geo->sectors = g->sect;
3443 geo->cylinders = g->track;
3444 return 0;
3445}
3446
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
3448 unsigned long param)
3449{
3450#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
3451#define OUT(c,x) case c: outparam = (const char *) (x); break
3452#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
3453
3454 int drive = (long)inode->i_bdev->bd_disk->private_data;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003455 int type = ITYPE(UDRS->fd_device);
3456 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457 int ret;
3458 int size;
3459 union inparam {
3460 struct floppy_struct g; /* geometry */
3461 struct format_descr f;
3462 struct floppy_max_errors max_errors;
3463 struct floppy_drive_params dp;
3464 } inparam; /* parameters coming from user space */
3465 const char *outparam; /* parameters passed back to user space */
3466
3467 /* convert compatibility eject ioctls into floppy eject ioctl.
3468 * We do this in order to provide a means to eject floppy disks before
3469 * installing the new fdutils package */
3470 if (cmd == CDROMEJECT || /* CD-ROM eject */
3471 cmd == 0x6470 /* SunOS floppy eject */ ) {
3472 DPRINT("obsolete eject ioctl\n");
3473 DPRINT("please use floppycontrol --eject\n");
3474 cmd = FDEJECT;
3475 }
3476
Linus Torvalds1da177e2005-04-16 15:20:36 -07003477 /* convert the old style command into a new style command */
3478 if ((cmd & 0xff00) == 0x0200) {
3479 ECALL(normalize_ioctl(&cmd, &size));
3480 } else
3481 return -EINVAL;
3482
3483 /* permission checks */
3484 if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
3485 ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
3486 return -EPERM;
3487
3488 /* copyin */
3489 CLEARSTRUCT(&inparam);
3490 if (_IOC_DIR(cmd) & _IOC_WRITE)
3491 ECALL(fd_copyin((void __user *)param, &inparam, size))
3492
3493 switch (cmd) {
3494 case FDEJECT:
3495 if (UDRS->fd_ref != 1)
3496 /* somebody else has this drive open */
3497 return -EBUSY;
3498 LOCK_FDC(drive, 1);
3499
3500 /* do the actual eject. Fails on
3501 * non-Sparc architectures */
3502 ret = fd_eject(UNIT(drive));
3503
3504 USETF(FD_DISK_CHANGED);
3505 USETF(FD_VERIFY);
3506 process_fd_request();
3507 return ret;
3508 case FDCLRPRM:
3509 LOCK_FDC(drive, 1);
3510 current_type[drive] = NULL;
3511 floppy_sizes[drive] = MAX_DISK_SIZE << 1;
3512 UDRS->keep_data = 0;
3513 return invalidate_drive(inode->i_bdev);
3514 case FDSETPRM:
3515 case FDDEFPRM:
3516 return set_geometry(cmd, &inparam.g,
3517 drive, type, inode->i_bdev);
3518 case FDGETPRM:
3519 ECALL(get_floppy_geometry(drive, type,
3520 (struct floppy_struct **)
3521 &outparam));
3522 break;
3523
3524 case FDMSGON:
3525 UDP->flags |= FTD_MSG;
3526 return 0;
3527 case FDMSGOFF:
3528 UDP->flags &= ~FTD_MSG;
3529 return 0;
3530
3531 case FDFMTBEG:
3532 LOCK_FDC(drive, 1);
3533 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3534 ret = UDRS->flags;
3535 process_fd_request();
3536 if (ret & FD_VERIFY)
3537 return -ENODEV;
3538 if (!(ret & FD_DISK_WRITABLE))
3539 return -EROFS;
3540 return 0;
3541 case FDFMTTRK:
3542 if (UDRS->fd_ref != 1)
3543 return -EBUSY;
3544 return do_format(drive, &inparam.f);
3545 case FDFMTEND:
3546 case FDFLUSH:
3547 LOCK_FDC(drive, 1);
3548 return invalidate_drive(inode->i_bdev);
3549
3550 case FDSETEMSGTRESH:
3551 UDP->max_errors.reporting =
3552 (unsigned short)(param & 0x0f);
3553 return 0;
3554 OUT(FDGETMAXERRS, &UDP->max_errors);
3555 IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
3556
3557 case FDGETDRVTYP:
3558 outparam = drive_name(type, drive);
3559 SUPBOUND(size, strlen(outparam) + 1);
3560 break;
3561
3562 IN(FDSETDRVPRM, UDP, dp);
3563 OUT(FDGETDRVPRM, UDP);
3564
3565 case FDPOLLDRVSTAT:
3566 LOCK_FDC(drive, 1);
3567 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3568 process_fd_request();
3569 /* fall through */
3570 OUT(FDGETDRVSTAT, UDRS);
3571
3572 case FDRESET:
3573 return user_reset_fdc(drive, (int)param, 1);
3574
3575 OUT(FDGETFDCSTAT, UFDCS);
3576
3577 case FDWERRORCLR:
3578 CLEARSTRUCT(UDRWE);
3579 return 0;
3580 OUT(FDWERRORGET, UDRWE);
3581
3582 case FDRAWCMD:
3583 if (type)
3584 return -EINVAL;
3585 LOCK_FDC(drive, 1);
3586 set_floppy(drive);
3587 CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
3588 process_fd_request();
3589 return i;
3590
3591 case FDTWADDLE:
3592 LOCK_FDC(drive, 1);
3593 twaddle();
3594 process_fd_request();
3595 return 0;
3596
3597 default:
3598 return -EINVAL;
3599 }
3600
3601 if (_IOC_DIR(cmd) & _IOC_READ)
3602 return fd_copyout((void __user *)param, outparam, size);
3603 else
3604 return 0;
3605#undef OUT
3606#undef IN
3607}
3608
3609static void __init config_types(void)
3610{
3611 int first = 1;
3612 int drive;
3613
3614 /* read drive info out of physical CMOS */
3615 drive = 0;
3616 if (!UDP->cmos)
3617 UDP->cmos = FLOPPY0_TYPE;
3618 drive = 1;
3619 if (!UDP->cmos && FLOPPY1_TYPE)
3620 UDP->cmos = FLOPPY1_TYPE;
3621
Jesper Juhl06f748c2007-10-16 23:30:57 -07003622 /* FIXME: additional physical CMOS drive detection should go here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623
3624 for (drive = 0; drive < N_DRIVE; drive++) {
3625 unsigned int type = UDP->cmos;
3626 struct floppy_drive_params *params;
3627 const char *name = NULL;
3628 static char temparea[32];
3629
Tobias Klauser945f3902006-01-08 01:05:11 -08003630 if (type < ARRAY_SIZE(default_drive_params)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631 params = &default_drive_params[type].params;
3632 if (type) {
3633 name = default_drive_params[type].name;
3634 allowed_drive_mask |= 1 << drive;
3635 } else
3636 allowed_drive_mask &= ~(1 << drive);
3637 } else {
3638 params = &default_drive_params[0].params;
3639 sprintf(temparea, "unknown type %d (usb?)", type);
3640 name = temparea;
3641 }
3642 if (name) {
3643 const char *prepend = ",";
3644 if (first) {
3645 prepend = KERN_INFO "Floppy drive(s):";
3646 first = 0;
3647 }
3648 printk("%s fd%d is %s", prepend, drive, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 }
3650 *UDP = *params;
3651 }
3652 if (!first)
3653 printk("\n");
3654}
3655
3656static int floppy_release(struct inode *inode, struct file *filp)
3657{
3658 int drive = (long)inode->i_bdev->bd_disk->private_data;
3659
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003660 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661 if (UDRS->fd_ref < 0)
3662 UDRS->fd_ref = 0;
3663 else if (!UDRS->fd_ref--) {
3664 DPRINT("floppy_release with fd_ref == 0");
3665 UDRS->fd_ref = 0;
3666 }
3667 if (!UDRS->fd_ref)
3668 opened_bdev[drive] = NULL;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003669 mutex_unlock(&open_lock);
Ingo Molnar3e541a42006-07-03 00:24:23 -07003670
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671 return 0;
3672}
3673
3674/*
3675 * floppy_open check for aliasing (/dev/fd0 can be the same as
3676 * /dev/PS0 etc), and disallows simultaneous access to the same
3677 * drive with different device numbers.
3678 */
3679static int floppy_open(struct inode *inode, struct file *filp)
3680{
3681 int drive = (long)inode->i_bdev->bd_disk->private_data;
3682 int old_dev;
3683 int try;
3684 int res = -EBUSY;
3685 char *tmp;
3686
3687 filp->private_data = (void *)0;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003688 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689 old_dev = UDRS->fd_device;
3690 if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
3691 goto out2;
3692
3693 if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
3694 USETF(FD_DISK_CHANGED);
3695 USETF(FD_VERIFY);
3696 }
3697
3698 if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
3699 goto out2;
3700
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701 if (filp->f_flags & O_EXCL)
3702 UDRS->fd_ref = -1;
3703 else
3704 UDRS->fd_ref++;
3705
3706 opened_bdev[drive] = inode->i_bdev;
3707
3708 res = -ENXIO;
3709
3710 if (!floppy_track_buffer) {
3711 /* if opening an ED drive, reserve a big buffer,
3712 * else reserve a small one */
3713 if ((UDP->cmos == 6) || (UDP->cmos == 5))
3714 try = 64; /* Only 48 actually useful */
3715 else
3716 try = 32; /* Only 24 actually useful */
3717
3718 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3719 if (!tmp && !floppy_track_buffer) {
3720 try >>= 1; /* buffer only one side */
3721 INFBOUND(try, 16);
3722 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3723 }
3724 if (!tmp && !floppy_track_buffer) {
3725 fallback_on_nodma_alloc(&tmp, 2048 * try);
3726 }
3727 if (!tmp && !floppy_track_buffer) {
3728 DPRINT("Unable to allocate DMA memory\n");
3729 goto out;
3730 }
3731 if (floppy_track_buffer) {
3732 if (tmp)
3733 fd_dma_mem_free((unsigned long)tmp, try * 1024);
3734 } else {
3735 buffer_min = buffer_max = -1;
3736 floppy_track_buffer = tmp;
3737 max_buffer_sectors = try;
3738 }
3739 }
3740
3741 UDRS->fd_device = iminor(inode);
3742 set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
3743 if (old_dev != -1 && old_dev != iminor(inode)) {
3744 if (buffer_drive == drive)
3745 buffer_track = -1;
3746 }
3747
3748 /* Allow ioctls if we have write-permissions even if read-only open.
3749 * Needed so that programs such as fdrawcmd still can work on write
3750 * protected disks */
Christoph Hellwig8c744fb2005-11-08 21:35:04 -08003751 if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752 filp->private_data = (void *)8;
3753
3754 if (UFDCS->rawcmd == 1)
3755 UFDCS->rawcmd = 2;
3756
3757 if (!(filp->f_flags & O_NDELAY)) {
3758 if (filp->f_mode & 3) {
3759 UDRS->last_checked = 0;
3760 check_disk_change(inode->i_bdev);
3761 if (UTESTF(FD_DISK_CHANGED))
3762 goto out;
3763 }
3764 res = -EROFS;
3765 if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
3766 goto out;
3767 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003768 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 return 0;
3770out:
3771 if (UDRS->fd_ref < 0)
3772 UDRS->fd_ref = 0;
3773 else
3774 UDRS->fd_ref--;
3775 if (!UDRS->fd_ref)
3776 opened_bdev[drive] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003777out2:
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003778 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 return res;
3780}
3781
3782/*
3783 * Check if the disk has been changed or if a change has been faked.
3784 */
3785static int check_floppy_change(struct gendisk *disk)
3786{
3787 int drive = (long)disk->private_data;
3788
3789 if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
3790 return 1;
3791
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08003792 if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 lock_fdc(drive, 0);
3794 poll_drive(0, 0);
3795 process_fd_request();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 }
3797
3798 if (UTESTF(FD_DISK_CHANGED) ||
3799 UTESTF(FD_VERIFY) ||
3800 test_bit(drive, &fake_change) ||
3801 (!ITYPE(UDRS->fd_device) && !current_type[drive]))
3802 return 1;
3803 return 0;
3804}
3805
3806/*
3807 * This implements "read block 0" for floppy_revalidate().
3808 * Needed for format autodetection, checking whether there is
3809 * a disk in the drive, and whether that disk is writable.
3810 */
3811
NeilBrown6712ecf2007-09-27 12:47:43 +02003812static void floppy_rb0_complete(struct bio *bio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813 int err)
3814{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815 complete((struct completion *)bio->bi_private);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816}
3817
3818static int __floppy_read_block_0(struct block_device *bdev)
3819{
3820 struct bio bio;
3821 struct bio_vec bio_vec;
3822 struct completion complete;
3823 struct page *page;
3824 size_t size;
3825
3826 page = alloc_page(GFP_NOIO);
3827 if (!page) {
3828 process_fd_request();
3829 return -ENOMEM;
3830 }
3831
3832 size = bdev->bd_block_size;
3833 if (!size)
3834 size = 1024;
3835
3836 bio_init(&bio);
3837 bio.bi_io_vec = &bio_vec;
3838 bio_vec.bv_page = page;
3839 bio_vec.bv_len = size;
3840 bio_vec.bv_offset = 0;
3841 bio.bi_vcnt = 1;
3842 bio.bi_idx = 0;
3843 bio.bi_size = size;
3844 bio.bi_bdev = bdev;
3845 bio.bi_sector = 0;
3846 init_completion(&complete);
3847 bio.bi_private = &complete;
3848 bio.bi_end_io = floppy_rb0_complete;
3849
3850 submit_bio(READ, &bio);
3851 generic_unplug_device(bdev_get_queue(bdev));
3852 process_fd_request();
3853 wait_for_completion(&complete);
3854
3855 __free_page(page);
3856
3857 return 0;
3858}
3859
3860/* revalidate the floppy disk, i.e. trigger format autodetection by reading
3861 * the bootblock (block 0). "Autodetection" is also needed to check whether
3862 * there is a disk in the drive at all... Thus we also do it for fixed
3863 * geometry formats */
3864static int floppy_revalidate(struct gendisk *disk)
3865{
3866 int drive = (long)disk->private_data;
3867#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
3868 int cf;
3869 int res = 0;
3870
3871 if (UTESTF(FD_DISK_CHANGED) ||
3872 UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) {
3873 if (usage_count == 0) {
3874 printk("VFS: revalidate called on non-open device.\n");
3875 return -EFAULT;
3876 }
3877 lock_fdc(drive, 0);
3878 cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
3879 if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
3880 process_fd_request(); /*already done by another thread */
3881 return 0;
3882 }
3883 UDRS->maxblock = 0;
3884 UDRS->maxtrack = 0;
3885 if (buffer_drive == drive)
3886 buffer_track = -1;
3887 clear_bit(drive, &fake_change);
3888 UCLEARF(FD_DISK_CHANGED);
3889 if (cf)
3890 UDRS->generation++;
3891 if (NO_GEOM) {
3892 /* auto-sensing */
3893 res = __floppy_read_block_0(opened_bdev[drive]);
3894 } else {
3895 if (cf)
3896 poll_drive(0, FD_RAW_NEED_DISK);
3897 process_fd_request();
3898 }
3899 }
3900 set_capacity(disk, floppy_sizes[UDRS->fd_device]);
3901 return res;
3902}
3903
3904static struct block_device_operations floppy_fops = {
Jesper Juhl06f748c2007-10-16 23:30:57 -07003905 .owner = THIS_MODULE,
3906 .open = floppy_open,
3907 .release = floppy_release,
3908 .ioctl = fd_ioctl,
3909 .getgeo = fd_getgeo,
3910 .media_changed = check_floppy_change,
3911 .revalidate_disk = floppy_revalidate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914/*
3915 * Floppy Driver initialization
3916 * =============================
3917 */
3918
3919/* Determine the floppy disk controller type */
3920/* This routine was written by David C. Niemi */
3921static char __init get_fdc_version(void)
3922{
3923 int r;
3924
3925 output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */
3926 if (FDCS->reset)
3927 return FDC_NONE;
3928 if ((r = result()) <= 0x00)
3929 return FDC_NONE; /* No FDC present ??? */
3930 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3931 printk(KERN_INFO "FDC %d is an 8272A\n", fdc);
3932 return FDC_8272A; /* 8272a/765 don't know DUMPREGS */
3933 }
3934 if (r != 10) {
3935 printk
3936 ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
3937 fdc, r);
3938 return FDC_UNKNOWN;
3939 }
3940
3941 if (!fdc_configure()) {
3942 printk(KERN_INFO "FDC %d is an 82072\n", fdc);
3943 return FDC_82072; /* 82072 doesn't know CONFIGURE */
3944 }
3945
3946 output_byte(FD_PERPENDICULAR);
3947 if (need_more_output() == MORE_OUTPUT) {
3948 output_byte(0);
3949 } else {
3950 printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
3951 return FDC_82072A; /* 82072A as found on Sparcs. */
3952 }
3953
3954 output_byte(FD_UNLOCK);
3955 r = result();
3956 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3957 printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc);
3958 return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know
3959 * LOCK/UNLOCK */
3960 }
3961 if ((r != 1) || (reply_buffer[0] != 0x00)) {
3962 printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
3963 fdc, r);
3964 return FDC_UNKNOWN;
3965 }
3966 output_byte(FD_PARTID);
3967 r = result();
3968 if (r != 1) {
3969 printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
3970 fdc, r);
3971 return FDC_UNKNOWN;
3972 }
3973 if (reply_buffer[0] == 0x80) {
3974 printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc);
3975 return FDC_82077; /* Revised 82077AA passes all the tests */
3976 }
3977 switch (reply_buffer[0] >> 5) {
3978 case 0x0:
3979 /* Either a 82078-1 or a 82078SL running at 5Volt */
3980 printk(KERN_INFO "FDC %d is an 82078.\n", fdc);
3981 return FDC_82078;
3982 case 0x1:
3983 printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc);
3984 return FDC_82078;
3985 case 0x2:
3986 printk(KERN_INFO "FDC %d is a S82078B\n", fdc);
3987 return FDC_S82078B;
3988 case 0x3:
3989 printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n",
3990 fdc);
3991 return FDC_87306;
3992 default:
3993 printk(KERN_INFO
3994 "FDC %d init: 82078 variant with unknown PARTID=%d.\n",
3995 fdc, reply_buffer[0] >> 5);
3996 return FDC_82078_UNKN;
3997 }
3998} /* get_fdc_version */
3999
4000/* lilo configuration */
4001
4002static void __init floppy_set_flags(int *ints, int param, int param2)
4003{
4004 int i;
4005
4006 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4007 if (param)
4008 default_drive_params[i].params.flags |= param2;
4009 else
4010 default_drive_params[i].params.flags &= ~param2;
4011 }
4012 DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param);
4013}
4014
4015static void __init daring(int *ints, int param, int param2)
4016{
4017 int i;
4018
4019 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4020 if (param) {
4021 default_drive_params[i].params.select_delay = 0;
4022 default_drive_params[i].params.flags |=
4023 FD_SILENT_DCL_CLEAR;
4024 } else {
4025 default_drive_params[i].params.select_delay =
4026 2 * HZ / 100;
4027 default_drive_params[i].params.flags &=
4028 ~FD_SILENT_DCL_CLEAR;
4029 }
4030 }
4031 DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken");
4032}
4033
4034static void __init set_cmos(int *ints, int dummy, int dummy2)
4035{
4036 int current_drive = 0;
4037
4038 if (ints[0] != 2) {
4039 DPRINT("wrong number of parameters for CMOS\n");
4040 return;
4041 }
4042 current_drive = ints[1];
4043 if (current_drive < 0 || current_drive >= 8) {
4044 DPRINT("bad drive for set_cmos\n");
4045 return;
4046 }
4047#if N_FDC > 1
4048 if (current_drive >= 4 && !FDC2)
4049 FDC2 = 0x370;
4050#endif
4051 DP->cmos = ints[2];
4052 DPRINT("setting CMOS code to %d\n", ints[2]);
4053}
4054
4055static struct param_table {
4056 const char *name;
4057 void (*fn) (int *ints, int param, int param2);
4058 int *var;
4059 int def_param;
4060 int param2;
4061} config_params[] __initdata = {
4062 {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4063 {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4064 {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0},
4065 {"irq", NULL, &FLOPPY_IRQ, 6, 0},
4066 {"dma", NULL, &FLOPPY_DMA, 2, 0},
4067 {"daring", daring, NULL, 1, 0},
4068#if N_FDC > 1
4069 {"two_fdc", NULL, &FDC2, 0x370, 0},
4070 {"one_fdc", NULL, &FDC2, 0, 0},
4071#endif
4072 {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL},
4073 {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL},
4074 {"messages", floppy_set_flags, NULL, 1, FTD_MSG},
4075 {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR},
4076 {"debug", floppy_set_flags, NULL, 1, FD_DEBUG},
4077 {"nodma", NULL, &can_use_virtual_dma, 1, 0},
4078 {"omnibook", NULL, &can_use_virtual_dma, 1, 0},
4079 {"yesdma", NULL, &can_use_virtual_dma, 0, 0},
4080 {"fifo_depth", NULL, &fifo_depth, 0xa, 0},
4081 {"nofifo", NULL, &no_fifo, 0x20, 0},
4082 {"usefifo", NULL, &no_fifo, 0, 0},
4083 {"cmos", set_cmos, NULL, 0, 0},
4084 {"slow", NULL, &slow_floppy, 1, 0},
4085 {"unexpected_interrupts", NULL, &print_unex, 1, 0},
4086 {"no_unexpected_interrupts", NULL, &print_unex, 0, 0},
4087 {"L40SX", NULL, &print_unex, 0, 0}
4088
4089 EXTRA_FLOPPY_PARAMS
4090};
4091
4092static int __init floppy_setup(char *str)
4093{
4094 int i;
4095 int param;
4096 int ints[11];
4097
4098 str = get_options(str, ARRAY_SIZE(ints), ints);
4099 if (str) {
4100 for (i = 0; i < ARRAY_SIZE(config_params); i++) {
4101 if (strcmp(str, config_params[i].name) == 0) {
4102 if (ints[0])
4103 param = ints[1];
4104 else
4105 param = config_params[i].def_param;
4106 if (config_params[i].fn)
4107 config_params[i].
4108 fn(ints, param,
4109 config_params[i].param2);
4110 if (config_params[i].var) {
4111 DPRINT("%s=%d\n", str, param);
4112 *config_params[i].var = param;
4113 }
4114 return 1;
4115 }
4116 }
4117 }
4118 if (str) {
4119 DPRINT("unknown floppy option [%s]\n", str);
4120
4121 DPRINT("allowed options are:");
4122 for (i = 0; i < ARRAY_SIZE(config_params); i++)
4123 printk(" %s", config_params[i].name);
4124 printk("\n");
4125 } else
4126 DPRINT("botched floppy option\n");
4127 DPRINT("Read Documentation/floppy.txt\n");
4128 return 0;
4129}
4130
4131static int have_no_fdc = -ENODEV;
4132
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004133static ssize_t floppy_cmos_show(struct device *dev,
4134 struct device_attribute *attr, char *buf)
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004135{
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004136 struct platform_device *p;
4137 int drive;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004138
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004139 p = container_of(dev, struct platform_device,dev);
4140 drive = p->id;
4141 return sprintf(buf, "%X\n", UDP->cmos);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004142}
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004143DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
4144
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145static void floppy_device_release(struct device *dev)
4146{
4147 complete(&device_release);
4148}
4149
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004150static struct platform_device floppy_device[N_DRIVE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
4152static struct kobject *floppy_find(dev_t dev, int *part, void *data)
4153{
4154 int drive = (*part & 3) | ((*part & 0x80) >> 5);
4155 if (drive >= N_DRIVE ||
4156 !(allowed_drive_mask & (1 << drive)) ||
4157 fdc_state[FDC(drive)].version == FDC_NONE)
4158 return NULL;
Tobias Klauser945f3902006-01-08 01:05:11 -08004159 if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004160 return NULL;
4161 *part = 0;
4162 return get_disk(disks[drive]);
4163}
4164
4165static int __init floppy_init(void)
4166{
4167 int i, unit, drive;
4168 int err, dr;
4169
Olaf Heringef16b512006-08-31 21:27:41 -07004170#if defined(CONFIG_PPC_MERGE)
4171 if (check_legacy_ioport(FDC1))
4172 return -ENODEV;
4173#endif
4174
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 raw_cmd = NULL;
4176
4177 for (dr = 0; dr < N_DRIVE; dr++) {
4178 disks[dr] = alloc_disk(1);
4179 if (!disks[dr]) {
4180 err = -ENOMEM;
4181 goto out_put_disk;
4182 }
4183
4184 disks[dr]->major = FLOPPY_MAJOR;
4185 disks[dr]->first_minor = TOMINOR(dr);
4186 disks[dr]->fops = &floppy_fops;
4187 sprintf(disks[dr]->disk_name, "fd%d", dr);
4188
4189 init_timer(&motor_off_timer[dr]);
4190 motor_off_timer[dr].data = dr;
4191 motor_off_timer[dr].function = motor_off_callback;
4192 }
4193
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 err = register_blkdev(FLOPPY_MAJOR, "fd");
4195 if (err)
Greg Kroah-Hartman8ab5e4c2005-06-20 21:15:16 -07004196 goto out_put_disk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
4198 floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
4199 if (!floppy_queue) {
4200 err = -ENOMEM;
4201 goto out_unreg_blkdev;
4202 }
4203 blk_queue_max_sectors(floppy_queue, 64);
4204
4205 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
4206 floppy_find, NULL, NULL);
4207
4208 for (i = 0; i < 256; i++)
4209 if (ITYPE(i))
4210 floppy_sizes[i] = floppy_type[ITYPE(i)].size;
4211 else
4212 floppy_sizes[i] = MAX_DISK_SIZE << 1;
4213
4214 reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
4215 config_types();
4216
4217 for (i = 0; i < N_FDC; i++) {
4218 fdc = i;
4219 CLEARSTRUCT(FDCS);
4220 FDCS->dtr = -1;
4221 FDCS->dor = 0x4;
4222#if defined(__sparc__) || defined(__mc68000__)
4223 /*sparcs/sun3x don't have a DOR reset which we can fall back on to */
4224#ifdef __mc68000__
4225 if (MACH_IS_SUN3X)
4226#endif
4227 FDCS->version = FDC_82072A;
4228#endif
4229 }
4230
4231 use_virtual_dma = can_use_virtual_dma & 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 fdc_state[0].address = FDC1;
4233 if (fdc_state[0].address == -1) {
4234 del_timer(&fd_timeout);
4235 err = -ENODEV;
4236 goto out_unreg_region;
4237 }
4238#if N_FDC > 1
4239 fdc_state[1].address = FDC2;
4240#endif
4241
4242 fdc = 0; /* reset fdc in case of unexpected interrupt */
4243 err = floppy_grab_irq_and_dma();
4244 if (err) {
4245 del_timer(&fd_timeout);
4246 err = -EBUSY;
4247 goto out_unreg_region;
4248 }
4249
4250 /* initialise drive state */
4251 for (drive = 0; drive < N_DRIVE; drive++) {
4252 CLEARSTRUCT(UDRS);
4253 CLEARSTRUCT(UDRWE);
4254 USETF(FD_DISK_NEWCHANGE);
4255 USETF(FD_DISK_CHANGED);
4256 USETF(FD_VERIFY);
4257 UDRS->fd_device = -1;
4258 floppy_track_buffer = NULL;
4259 max_buffer_sectors = 0;
4260 }
4261 /*
4262 * Small 10 msec delay to let through any interrupt that
4263 * initialization might have triggered, to not
4264 * confuse detection:
4265 */
4266 msleep(10);
4267
4268 for (i = 0; i < N_FDC; i++) {
4269 fdc = i;
4270 FDCS->driver_version = FD_DRIVER_VERSION;
4271 for (unit = 0; unit < 4; unit++)
4272 FDCS->track[unit] = 0;
4273 if (FDCS->address == -1)
4274 continue;
4275 FDCS->rawcmd = 2;
4276 if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
4277 /* free ioports reserved by floppy_grab_irq_and_dma() */
4278 release_region(FDCS->address + 2, 4);
4279 release_region(FDCS->address + 7, 1);
4280 FDCS->address = -1;
4281 FDCS->version = FDC_NONE;
4282 continue;
4283 }
4284 /* Try to determine the floppy controller type */
4285 FDCS->version = get_fdc_version();
4286 if (FDCS->version == FDC_NONE) {
4287 /* free ioports reserved by floppy_grab_irq_and_dma() */
4288 release_region(FDCS->address + 2, 4);
4289 release_region(FDCS->address + 7, 1);
4290 FDCS->address = -1;
4291 continue;
4292 }
4293 if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
4294 can_use_virtual_dma = 0;
4295
4296 have_no_fdc = 0;
4297 /* Not all FDCs seem to be able to handle the version command
4298 * properly, so force a reset for the standard FDC clones,
4299 * to avoid interrupt garbage.
4300 */
4301 user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
4302 }
4303 fdc = 0;
4304 del_timer(&fd_timeout);
4305 current_drive = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 initialising = 0;
4307 if (have_no_fdc) {
4308 DPRINT("no floppy controllers found\n");
4309 err = have_no_fdc;
4310 goto out_flush_work;
4311 }
4312
Linus Torvalds1da177e2005-04-16 15:20:36 -07004313 for (drive = 0; drive < N_DRIVE; drive++) {
4314 if (!(allowed_drive_mask & (1 << drive)))
4315 continue;
4316 if (fdc_state[FDC(drive)].version == FDC_NONE)
4317 continue;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004318
4319 floppy_device[drive].name = floppy_device_name;
4320 floppy_device[drive].id = drive;
4321 floppy_device[drive].dev.release = floppy_device_release;
4322
4323 err = platform_device_register(&floppy_device[drive]);
4324 if (err)
4325 goto out_flush_work;
4326
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004327 err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
4328 if (err)
4329 goto out_unreg_platform_dev;
4330
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331 /* to be cleaned up... */
4332 disks[drive]->private_data = (void *)(long)drive;
4333 disks[drive]->queue = floppy_queue;
4334 disks[drive]->flags |= GENHD_FL_REMOVABLE;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004335 disks[drive]->driverfs_dev = &floppy_device[drive].dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336 add_disk(disks[drive]);
4337 }
4338
4339 return 0;
4340
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004341out_unreg_platform_dev:
4342 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343out_flush_work:
4344 flush_scheduled_work();
4345 if (usage_count)
4346 floppy_release_irq_and_dma();
4347out_unreg_region:
4348 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4349 blk_cleanup_queue(floppy_queue);
4350out_unreg_blkdev:
4351 unregister_blkdev(FLOPPY_MAJOR, "fd");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352out_put_disk:
4353 while (dr--) {
4354 del_timer(&motor_off_timer[dr]);
4355 put_disk(disks[dr]);
4356 }
4357 return err;
4358}
4359
4360static DEFINE_SPINLOCK(floppy_usage_lock);
4361
4362static int floppy_grab_irq_and_dma(void)
4363{
4364 unsigned long flags;
4365
4366 spin_lock_irqsave(&floppy_usage_lock, flags);
4367 if (usage_count++) {
4368 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4369 return 0;
4370 }
4371 spin_unlock_irqrestore(&floppy_usage_lock, flags);
Ingo Molnar6dc659d2006-03-26 01:36:54 -08004372
4373 /*
4374 * We might have scheduled a free_irq(), wait it to
4375 * drain first:
4376 */
4377 flush_scheduled_work();
4378
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379 if (fd_request_irq()) {
4380 DPRINT("Unable to grab IRQ%d for the floppy driver\n",
4381 FLOPPY_IRQ);
4382 spin_lock_irqsave(&floppy_usage_lock, flags);
4383 usage_count--;
4384 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4385 return -1;
4386 }
4387 if (fd_request_dma()) {
4388 DPRINT("Unable to grab DMA%d for the floppy driver\n",
4389 FLOPPY_DMA);
Jan Beulich2e9c47c2007-10-16 23:27:32 -07004390 if (can_use_virtual_dma & 2)
4391 use_virtual_dma = can_use_virtual_dma = 1;
4392 if (!(can_use_virtual_dma & 1)) {
4393 fd_free_irq();
4394 spin_lock_irqsave(&floppy_usage_lock, flags);
4395 usage_count--;
4396 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4397 return -1;
4398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399 }
4400
4401 for (fdc = 0; fdc < N_FDC; fdc++) {
4402 if (FDCS->address != -1) {
4403 if (!request_region(FDCS->address + 2, 4, "floppy")) {
4404 DPRINT("Floppy io-port 0x%04lx in use\n",
4405 FDCS->address + 2);
4406 goto cleanup1;
4407 }
4408 if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
4409 DPRINT("Floppy io-port 0x%04lx in use\n",
4410 FDCS->address + 7);
4411 goto cleanup2;
4412 }
4413 /* address + 6 is reserved, and may be taken by IDE.
4414 * Unfortunately, Adaptec doesn't know this :-(, */
4415 }
4416 }
4417 for (fdc = 0; fdc < N_FDC; fdc++) {
4418 if (FDCS->address != -1) {
4419 reset_fdc_info(1);
4420 fd_outb(FDCS->dor, FD_DOR);
4421 }
4422 }
4423 fdc = 0;
4424 set_dor(0, ~0, 8); /* avoid immediate interrupt */
4425
4426 for (fdc = 0; fdc < N_FDC; fdc++)
4427 if (FDCS->address != -1)
4428 fd_outb(FDCS->dor, FD_DOR);
4429 /*
Jesper Juhl06f748c2007-10-16 23:30:57 -07004430 * The driver will try and free resources and relies on us
4431 * to know if they were allocated or not.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432 */
4433 fdc = 0;
4434 irqdma_allocated = 1;
4435 return 0;
4436cleanup2:
4437 release_region(FDCS->address + 2, 4);
4438cleanup1:
4439 fd_free_irq();
4440 fd_free_dma();
4441 while (--fdc >= 0) {
4442 release_region(FDCS->address + 2, 4);
4443 release_region(FDCS->address + 7, 1);
4444 }
4445 spin_lock_irqsave(&floppy_usage_lock, flags);
4446 usage_count--;
4447 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4448 return -1;
4449}
4450
4451static void floppy_release_irq_and_dma(void)
4452{
4453 int old_fdc;
4454#ifdef FLOPPY_SANITY_CHECK
4455#ifndef __sparc__
4456 int drive;
4457#endif
4458#endif
4459 long tmpsize;
4460 unsigned long tmpaddr;
4461 unsigned long flags;
4462
4463 spin_lock_irqsave(&floppy_usage_lock, flags);
4464 if (--usage_count) {
4465 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4466 return;
4467 }
4468 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4469 if (irqdma_allocated) {
4470 fd_disable_dma();
4471 fd_free_dma();
Ingo Molnar3e541a42006-07-03 00:24:23 -07004472 fd_free_irq();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473 irqdma_allocated = 0;
4474 }
4475 set_dor(0, ~0, 8);
4476#if N_FDC > 1
4477 set_dor(1, ~8, 0);
4478#endif
4479 floppy_enable_hlt();
4480
4481 if (floppy_track_buffer && max_buffer_sectors) {
4482 tmpsize = max_buffer_sectors * 1024;
4483 tmpaddr = (unsigned long)floppy_track_buffer;
4484 floppy_track_buffer = NULL;
4485 max_buffer_sectors = 0;
4486 buffer_min = buffer_max = -1;
4487 fd_dma_mem_free(tmpaddr, tmpsize);
4488 }
4489#ifdef FLOPPY_SANITY_CHECK
4490#ifndef __sparc__
4491 for (drive = 0; drive < N_FDC * 4; drive++)
4492 if (timer_pending(motor_off_timer + drive))
4493 printk("motor off timer %d still active\n", drive);
4494#endif
4495
4496 if (timer_pending(&fd_timeout))
4497 printk("floppy timer still active:%s\n", timeout_message);
4498 if (timer_pending(&fd_timer))
4499 printk("auxiliary floppy timer still active\n");
David Howells365970a2006-11-22 14:54:49 +00004500 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 printk("work still pending\n");
4502#endif
4503 old_fdc = fdc;
4504 for (fdc = 0; fdc < N_FDC; fdc++)
4505 if (FDCS->address != -1) {
4506 release_region(FDCS->address + 2, 4);
4507 release_region(FDCS->address + 7, 1);
4508 }
4509 fdc = old_fdc;
4510}
4511
4512#ifdef MODULE
4513
4514static char *floppy;
4515
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516static void __init parse_floppy_cfg_string(char *cfg)
4517{
4518 char *ptr;
4519
4520 while (*cfg) {
4521 for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ;
4522 if (*cfg) {
4523 *cfg = '\0';
4524 cfg++;
4525 }
4526 if (*ptr)
4527 floppy_setup(ptr);
4528 }
4529}
4530
Sam Ravnborg1efa6462006-03-25 03:07:13 -08004531int __init init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532{
4533 if (floppy)
4534 parse_floppy_cfg_string(floppy);
4535 return floppy_init();
4536}
4537
4538void cleanup_module(void)
4539{
4540 int drive;
4541
4542 init_completion(&device_release);
4543 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4544 unregister_blkdev(FLOPPY_MAJOR, "fd");
4545
4546 for (drive = 0; drive < N_DRIVE; drive++) {
4547 del_timer_sync(&motor_off_timer[drive]);
4548
4549 if ((allowed_drive_mask & (1 << drive)) &&
4550 fdc_state[FDC(drive)].version != FDC_NONE) {
4551 del_gendisk(disks[drive]);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004552 device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
4553 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554 }
4555 put_disk(disks[drive]);
4556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557
4558 del_timer_sync(&fd_timeout);
4559 del_timer_sync(&fd_timer);
4560 blk_cleanup_queue(floppy_queue);
4561
4562 if (usage_count)
4563 floppy_release_irq_and_dma();
4564
4565 /* eject disk, if any */
4566 fd_eject(0);
4567
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568 wait_for_completion(&device_release);
4569}
4570
4571module_param(floppy, charp, 0);
4572module_param(FLOPPY_IRQ, int, 0);
4573module_param(FLOPPY_DMA, int, 0);
4574MODULE_AUTHOR("Alain L. Knaff");
4575MODULE_SUPPORTED_DEVICE("fd");
4576MODULE_LICENSE("GPL");
4577
4578#else
4579
4580__setup("floppy=", floppy_setup);
4581module_init(floppy_init)
4582#endif
4583
4584MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);