blob: c6416f841131ab5a5ba840d600fb26d26d2c85f6 [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
771 /*USETF(FD_DISK_NEWCHANGE); */
772 return 1;
773 } else {
774 UDRS->last_checked = jiffies;
775 UCLEARF(FD_DISK_NEWCHANGE);
776 }
777 return 0;
778}
779
780static inline int is_selected(int dor, int unit)
781{
782 return ((dor & (0x10 << unit)) && (dor & 3) == unit);
783}
784
785static int set_dor(int fdc, char mask, char data)
786{
787 register unsigned char drive, unit, newdor, olddor;
788
789 if (FDCS->address == -1)
790 return -1;
791
792 olddor = FDCS->dor;
793 newdor = (olddor & mask) | data;
794 if (newdor != olddor) {
795 unit = olddor & 0x3;
796 if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
797 drive = REVDRIVE(fdc, unit);
798#ifdef DCL_DEBUG
799 if (UDP->flags & FD_DEBUG) {
800 DPRINT("calling disk change from set_dor\n");
801 }
802#endif
803 disk_change(drive);
804 }
805 FDCS->dor = newdor;
806 fd_outb(newdor, FD_DOR);
807
808 unit = newdor & 0x3;
809 if (!is_selected(olddor, unit) && is_selected(newdor, unit)) {
810 drive = REVDRIVE(fdc, unit);
811 UDRS->select_date = jiffies;
812 }
813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 return olddor;
815}
816
817static void twaddle(void)
818{
819 if (DP->select_delay)
820 return;
821 fd_outb(FDCS->dor & ~(0x10 << UNIT(current_drive)), FD_DOR);
822 fd_outb(FDCS->dor, FD_DOR);
823 DRS->select_date = jiffies;
824}
825
826/* reset all driver information about the current fdc. This is needed after
827 * a reset, and after a raw command. */
828static void reset_fdc_info(int mode)
829{
830 int drive;
831
832 FDCS->spec1 = FDCS->spec2 = -1;
833 FDCS->need_configure = 1;
834 FDCS->perp_mode = 1;
835 FDCS->rawcmd = 0;
836 for (drive = 0; drive < N_DRIVE; drive++)
837 if (FDC(drive) == fdc && (mode || UDRS->track != NEED_1_RECAL))
838 UDRS->track = NEED_2_RECAL;
839}
840
841/* selects the fdc and drive, and enables the fdc's input/dma. */
842static void set_fdc(int drive)
843{
844 if (drive >= 0 && drive < N_DRIVE) {
845 fdc = FDC(drive);
846 current_drive = drive;
847 }
848 if (fdc != 1 && fdc != 0) {
849 printk("bad fdc value\n");
850 return;
851 }
852 set_dor(fdc, ~0, 8);
853#if N_FDC > 1
854 set_dor(1 - fdc, ~8, 0);
855#endif
856 if (FDCS->rawcmd == 2)
857 reset_fdc_info(1);
858 if (fd_inb(FD_STATUS) != STATUS_READY)
859 FDCS->reset = 1;
860}
861
862/* locks the driver */
863static int _lock_fdc(int drive, int interruptible, int line)
864{
865 if (!usage_count) {
866 printk(KERN_ERR
867 "Trying to lock fdc while usage count=0 at line %d\n",
868 line);
869 return -1;
870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872 if (test_and_set_bit(0, &fdc_busy)) {
873 DECLARE_WAITQUEUE(wait, current);
874 add_wait_queue(&fdc_wait, &wait);
875
876 for (;;) {
877 set_current_state(TASK_INTERRUPTIBLE);
878
879 if (!test_and_set_bit(0, &fdc_busy))
880 break;
881
882 schedule();
883
884 if (!NO_SIGNAL) {
885 remove_wait_queue(&fdc_wait, &wait);
886 return -EINTR;
887 }
888 }
889
890 set_current_state(TASK_RUNNING);
891 remove_wait_queue(&fdc_wait, &wait);
Ingo Molnar3e541a42006-07-03 00:24:23 -0700892 flush_scheduled_work();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 }
894 command_status = FD_COMMAND_NONE;
895
896 __reschedule_timeout(drive, "lock fdc", 0);
897 set_fdc(drive);
898 return 0;
899}
900
901#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__)
902
903#define LOCK_FDC(drive,interruptible) \
904if (lock_fdc(drive,interruptible)) return -EINTR;
905
906/* unlocks the driver */
907static inline void unlock_fdc(void)
908{
909 unsigned long flags;
910
911 raw_cmd = NULL;
912 if (!test_bit(0, &fdc_busy))
913 DPRINT("FDC access conflict!\n");
914
915 if (do_floppy)
916 DPRINT("device interrupt still active at FDC release: %p!\n",
917 do_floppy);
918 command_status = FD_COMMAND_NONE;
919 spin_lock_irqsave(&floppy_lock, flags);
920 del_timer(&fd_timeout);
921 cont = NULL;
922 clear_bit(0, &fdc_busy);
923 if (elv_next_request(floppy_queue))
924 do_fd_request(floppy_queue);
925 spin_unlock_irqrestore(&floppy_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 wake_up(&fdc_wait);
927}
928
929/* switches the motor off after a given timeout */
930static void motor_off_callback(unsigned long nr)
931{
932 unsigned char mask = ~(0x10 << UNIT(nr));
933
934 set_dor(FDC(nr), mask, 0);
935}
936
937/* schedules motor off */
938static void floppy_off(unsigned int drive)
939{
940 unsigned long volatile delta;
941 register int fdc = FDC(drive);
942
943 if (!(FDCS->dor & (0x10 << UNIT(drive))))
944 return;
945
946 del_timer(motor_off_timer + drive);
947
948 /* make spindle stop in a position which minimizes spinup time
949 * next time */
950 if (UDP->rps) {
951 delta = jiffies - UDRS->first_read_date + HZ -
952 UDP->spindown_offset;
953 delta = ((delta * UDP->rps) % HZ) / UDP->rps;
954 motor_off_timer[drive].expires =
955 jiffies + UDP->spindown - delta;
956 }
957 add_timer(motor_off_timer + drive);
958}
959
960/*
961 * cycle through all N_DRIVE floppy drives, for disk change testing.
962 * stopping at current drive. This is done before any long operation, to
963 * be sure to have up to date disk change information.
964 */
965static void scandrives(void)
966{
Jesper Juhl06f748c2007-10-16 23:30:57 -0700967 int i;
968 int drive;
969 int saved_drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
971 if (DP->select_delay)
972 return;
973
974 saved_drive = current_drive;
975 for (i = 0; i < N_DRIVE; i++) {
976 drive = (saved_drive + i + 1) % N_DRIVE;
977 if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
978 continue; /* skip closed drives */
979 set_fdc(drive);
980 if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) &
981 (0x10 << UNIT(drive))))
982 /* switch the motor off again, if it was off to
983 * begin with */
984 set_dor(fdc, ~(0x10 << UNIT(drive)), 0);
985 }
986 set_fdc(saved_drive);
987}
988
989static void empty(void)
990{
991}
992
David Howells65f27f32006-11-22 14:55:48 +0000993static DECLARE_WORK(floppy_work, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
995static void schedule_bh(void (*handler) (void))
996{
David Howells65f27f32006-11-22 14:55:48 +0000997 PREPARE_WORK(&floppy_work, (work_func_t)handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 schedule_work(&floppy_work);
999}
1000
Ingo Molnar8d06afa2005-09-09 13:10:40 -07001001static DEFINE_TIMER(fd_timer, NULL, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
1003static void cancel_activity(void)
1004{
1005 unsigned long flags;
1006
1007 spin_lock_irqsave(&floppy_lock, flags);
1008 do_floppy = NULL;
David Howells65f27f32006-11-22 14:55:48 +00001009 PREPARE_WORK(&floppy_work, (work_func_t)empty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 del_timer(&fd_timer);
1011 spin_unlock_irqrestore(&floppy_lock, flags);
1012}
1013
1014/* this function makes sure that the disk stays in the drive during the
1015 * transfer */
1016static void fd_watchdog(void)
1017{
1018#ifdef DCL_DEBUG
1019 if (DP->flags & FD_DEBUG) {
1020 DPRINT("calling disk change from watchdog\n");
1021 }
1022#endif
1023
1024 if (disk_change(current_drive)) {
1025 DPRINT("disk removed during i/o\n");
1026 cancel_activity();
1027 cont->done(0);
1028 reset_fdc();
1029 } else {
1030 del_timer(&fd_timer);
1031 fd_timer.function = (timeout_fn) fd_watchdog;
1032 fd_timer.expires = jiffies + HZ / 10;
1033 add_timer(&fd_timer);
1034 }
1035}
1036
1037static void main_command_interrupt(void)
1038{
1039 del_timer(&fd_timer);
1040 cont->interrupt();
1041}
1042
1043/* waits for a delay (spinup or select) to pass */
1044static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
1045{
1046 if (FDCS->reset) {
1047 reset_fdc(); /* do the reset during sleep to win time
1048 * if we don't need to sleep, it's a good
1049 * occasion anyways */
1050 return 1;
1051 }
1052
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001053 if (time_before(jiffies, delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 del_timer(&fd_timer);
1055 fd_timer.function = function;
1056 fd_timer.expires = delay;
1057 add_timer(&fd_timer);
1058 return 1;
1059 }
1060 return 0;
1061}
1062
1063static DEFINE_SPINLOCK(floppy_hlt_lock);
1064static int hlt_disabled;
1065static void floppy_disable_hlt(void)
1066{
1067 unsigned long flags;
1068
1069 spin_lock_irqsave(&floppy_hlt_lock, flags);
1070 if (!hlt_disabled) {
1071 hlt_disabled = 1;
1072#ifdef HAVE_DISABLE_HLT
1073 disable_hlt();
1074#endif
1075 }
1076 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1077}
1078
1079static void floppy_enable_hlt(void)
1080{
1081 unsigned long flags;
1082
1083 spin_lock_irqsave(&floppy_hlt_lock, flags);
1084 if (hlt_disabled) {
1085 hlt_disabled = 0;
1086#ifdef HAVE_DISABLE_HLT
1087 enable_hlt();
1088#endif
1089 }
1090 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1091}
1092
1093static void setup_DMA(void)
1094{
1095 unsigned long f;
1096
1097#ifdef FLOPPY_SANITY_CHECK
1098 if (raw_cmd->length == 0) {
1099 int i;
1100
1101 printk("zero dma transfer size:");
1102 for (i = 0; i < raw_cmd->cmd_count; i++)
1103 printk("%x,", raw_cmd->cmd[i]);
1104 printk("\n");
1105 cont->done(0);
1106 FDCS->reset = 1;
1107 return;
1108 }
1109 if (((unsigned long)raw_cmd->kernel_data) % 512) {
1110 printk("non aligned address: %p\n", raw_cmd->kernel_data);
1111 cont->done(0);
1112 FDCS->reset = 1;
1113 return;
1114 }
1115#endif
1116 f = claim_dma_lock();
1117 fd_disable_dma();
1118#ifdef fd_dma_setup
1119 if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length,
1120 (raw_cmd->flags & FD_RAW_READ) ?
1121 DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) {
1122 release_dma_lock(f);
1123 cont->done(0);
1124 FDCS->reset = 1;
1125 return;
1126 }
1127 release_dma_lock(f);
1128#else
1129 fd_clear_dma_ff();
1130 fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
1131 fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ) ?
1132 DMA_MODE_READ : DMA_MODE_WRITE);
1133 fd_set_dma_addr(raw_cmd->kernel_data);
1134 fd_set_dma_count(raw_cmd->length);
1135 virtual_dma_port = FDCS->address;
1136 fd_enable_dma();
1137 release_dma_lock(f);
1138#endif
1139 floppy_disable_hlt();
1140}
1141
1142static void show_floppy(void);
1143
1144/* waits until the fdc becomes ready */
1145static int wait_til_ready(void)
1146{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001147 int status;
1148 int counter;
1149
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 if (FDCS->reset)
1151 return -1;
1152 for (counter = 0; counter < 10000; counter++) {
1153 status = fd_inb(FD_STATUS);
1154 if (status & STATUS_READY)
1155 return status;
1156 }
1157 if (!initialising) {
1158 DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc);
1159 show_floppy();
1160 }
1161 FDCS->reset = 1;
1162 return -1;
1163}
1164
1165/* sends a command byte to the fdc */
1166static int output_byte(char byte)
1167{
1168 int status;
1169
1170 if ((status = wait_til_ready()) < 0)
1171 return -1;
1172 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) {
1173 fd_outb(byte, FD_DATA);
1174#ifdef FLOPPY_SANITY_CHECK
1175 output_log[output_log_pos].data = byte;
1176 output_log[output_log_pos].status = status;
1177 output_log[output_log_pos].jiffies = jiffies;
1178 output_log_pos = (output_log_pos + 1) % OLOGSIZE;
1179#endif
1180 return 0;
1181 }
1182 FDCS->reset = 1;
1183 if (!initialising) {
1184 DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
1185 byte, fdc, status);
1186 show_floppy();
1187 }
1188 return -1;
1189}
1190
1191#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
1192
1193/* gets the response from the fdc */
1194static int result(void)
1195{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001196 int i;
1197 int status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
1199 for (i = 0; i < MAX_REPLIES; i++) {
1200 if ((status = wait_til_ready()) < 0)
1201 break;
1202 status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
1203 if ((status & ~STATUS_BUSY) == STATUS_READY) {
1204#ifdef FLOPPY_SANITY_CHECK
1205 resultjiffies = jiffies;
1206 resultsize = i;
1207#endif
1208 return i;
1209 }
1210 if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
1211 reply_buffer[i] = fd_inb(FD_DATA);
1212 else
1213 break;
1214 }
1215 if (!initialising) {
1216 DPRINT
1217 ("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
1218 fdc, status, i);
1219 show_floppy();
1220 }
1221 FDCS->reset = 1;
1222 return -1;
1223}
1224
1225#define MORE_OUTPUT -2
1226/* does the fdc need more output? */
1227static int need_more_output(void)
1228{
1229 int status;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001230
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 if ((status = wait_til_ready()) < 0)
1232 return -1;
1233 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
1234 return MORE_OUTPUT;
1235 return result();
1236}
1237
1238/* Set perpendicular mode as required, based on data rate, if supported.
1239 * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
1240 */
1241static inline void perpendicular_mode(void)
1242{
1243 unsigned char perp_mode;
1244
1245 if (raw_cmd->rate & 0x40) {
1246 switch (raw_cmd->rate & 3) {
1247 case 0:
1248 perp_mode = 2;
1249 break;
1250 case 3:
1251 perp_mode = 3;
1252 break;
1253 default:
1254 DPRINT("Invalid data rate for perpendicular mode!\n");
1255 cont->done(0);
1256 FDCS->reset = 1; /* convenient way to return to
1257 * redo without to much hassle (deep
1258 * stack et al. */
1259 return;
1260 }
1261 } else
1262 perp_mode = 0;
1263
1264 if (FDCS->perp_mode == perp_mode)
1265 return;
1266 if (FDCS->version >= FDC_82077_ORIG) {
1267 output_byte(FD_PERPENDICULAR);
1268 output_byte(perp_mode);
1269 FDCS->perp_mode = perp_mode;
1270 } else if (perp_mode) {
1271 DPRINT("perpendicular mode not supported by this FDC.\n");
1272 }
1273} /* perpendicular_mode */
1274
1275static int fifo_depth = 0xa;
1276static int no_fifo;
1277
1278static int fdc_configure(void)
1279{
1280 /* Turn on FIFO */
1281 output_byte(FD_CONFIGURE);
1282 if (need_more_output() != MORE_OUTPUT)
1283 return 0;
1284 output_byte(0);
1285 output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf));
1286 output_byte(0); /* pre-compensation from track
1287 0 upwards */
1288 return 1;
1289}
1290
1291#define NOMINAL_DTR 500
1292
1293/* Issue a "SPECIFY" command to set the step rate time, head unload time,
1294 * head load time, and DMA disable flag to values needed by floppy.
1295 *
1296 * The value "dtr" is the data transfer rate in Kbps. It is needed
1297 * to account for the data rate-based scaling done by the 82072 and 82077
1298 * FDC types. This parameter is ignored for other types of FDCs (i.e.
1299 * 8272a).
1300 *
1301 * Note that changing the data transfer rate has a (probably deleterious)
1302 * effect on the parameters subject to scaling for 82072/82077 FDCs, so
1303 * fdc_specify is called again after each data transfer rate
1304 * change.
1305 *
1306 * srt: 1000 to 16000 in microseconds
1307 * hut: 16 to 240 milliseconds
1308 * hlt: 2 to 254 milliseconds
1309 *
1310 * These values are rounded up to the next highest available delay time.
1311 */
1312static void fdc_specify(void)
1313{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001314 unsigned char spec1;
1315 unsigned char spec2;
1316 unsigned long srt;
1317 unsigned long hlt;
1318 unsigned long hut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 unsigned long dtr = NOMINAL_DTR;
1320 unsigned long scale_dtr = NOMINAL_DTR;
1321 int hlt_max_code = 0x7f;
1322 int hut_max_code = 0xf;
1323
1324 if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
1325 fdc_configure();
1326 FDCS->need_configure = 0;
1327 /*DPRINT("FIFO enabled\n"); */
1328 }
1329
1330 switch (raw_cmd->rate & 0x03) {
1331 case 3:
1332 dtr = 1000;
1333 break;
1334 case 1:
1335 dtr = 300;
1336 if (FDCS->version >= FDC_82078) {
1337 /* chose the default rate table, not the one
1338 * where 1 = 2 Mbps */
1339 output_byte(FD_DRIVESPEC);
1340 if (need_more_output() == MORE_OUTPUT) {
1341 output_byte(UNIT(current_drive));
1342 output_byte(0xc0);
1343 }
1344 }
1345 break;
1346 case 2:
1347 dtr = 250;
1348 break;
1349 }
1350
1351 if (FDCS->version >= FDC_82072) {
1352 scale_dtr = dtr;
1353 hlt_max_code = 0x00; /* 0==256msec*dtr0/dtr (not linear!) */
1354 hut_max_code = 0x0; /* 0==256msec*dtr0/dtr (not linear!) */
1355 }
1356
1357 /* Convert step rate from microseconds to milliseconds and 4 bits */
1358 srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR;
1359 if (slow_floppy) {
1360 srt = srt / 4;
1361 }
1362 SUPBOUND(srt, 0xf);
1363 INFBOUND(srt, 0);
1364
1365 hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR;
1366 if (hlt < 0x01)
1367 hlt = 0x01;
1368 else if (hlt > 0x7f)
1369 hlt = hlt_max_code;
1370
1371 hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR;
1372 if (hut < 0x1)
1373 hut = 0x1;
1374 else if (hut > 0xf)
1375 hut = hut_max_code;
1376
1377 spec1 = (srt << 4) | hut;
1378 spec2 = (hlt << 1) | (use_virtual_dma & 1);
1379
1380 /* If these parameters did not change, just return with success */
1381 if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) {
1382 /* Go ahead and set spec1 and spec2 */
1383 output_byte(FD_SPECIFY);
1384 output_byte(FDCS->spec1 = spec1);
1385 output_byte(FDCS->spec2 = spec2);
1386 }
1387} /* fdc_specify */
1388
1389/* Set the FDC's data transfer rate on behalf of the specified drive.
1390 * NOTE: with 82072/82077 FDCs, changing the data rate requires a reissue
1391 * of the specify command (i.e. using the fdc_specify function).
1392 */
1393static int fdc_dtr(void)
1394{
1395 /* If data rate not already set to desired value, set it. */
1396 if ((raw_cmd->rate & 3) == FDCS->dtr)
1397 return 0;
1398
1399 /* Set dtr */
1400 fd_outb(raw_cmd->rate & 3, FD_DCR);
1401
1402 /* TODO: some FDC/drive combinations (C&T 82C711 with TEAC 1.2MB)
1403 * need a stabilization period of several milliseconds to be
1404 * enforced after data rate changes before R/W operations.
1405 * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
1406 */
1407 FDCS->dtr = raw_cmd->rate & 3;
1408 return (fd_wait_for_completion(jiffies + 2UL * HZ / 100,
1409 (timeout_fn) floppy_ready));
1410} /* fdc_dtr */
1411
1412static void tell_sector(void)
1413{
1414 printk(": track %d, head %d, sector %d, size %d",
1415 R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
1416} /* tell_sector */
1417
1418/*
1419 * OK, this error interpreting routine is called after a
1420 * DMA read/write has succeeded
1421 * or failed, so we check the results, and copy any buffers.
1422 * hhb: Added better error reporting.
1423 * ak: Made this into a separate routine.
1424 */
1425static int interpret_errors(void)
1426{
1427 char bad;
1428
1429 if (inr != 7) {
1430 DPRINT("-- FDC reply error");
1431 FDCS->reset = 1;
1432 return 1;
1433 }
1434
1435 /* check IC to find cause of interrupt */
1436 switch (ST0 & ST0_INTR) {
1437 case 0x40: /* error occurred during command execution */
1438 if (ST1 & ST1_EOC)
1439 return 0; /* occurs with pseudo-DMA */
1440 bad = 1;
1441 if (ST1 & ST1_WP) {
1442 DPRINT("Drive is write protected\n");
1443 CLEARF(FD_DISK_WRITABLE);
1444 cont->done(0);
1445 bad = 2;
1446 } else if (ST1 & ST1_ND) {
1447 SETF(FD_NEED_TWADDLE);
1448 } else if (ST1 & ST1_OR) {
1449 if (DP->flags & FTD_MSG)
1450 DPRINT("Over/Underrun - retrying\n");
1451 bad = 0;
1452 } else if (*errors >= DP->max_errors.reporting) {
1453 DPRINT("");
1454 if (ST0 & ST0_ECE) {
1455 printk("Recalibrate failed!");
1456 } else if (ST2 & ST2_CRC) {
1457 printk("data CRC error");
1458 tell_sector();
1459 } else if (ST1 & ST1_CRC) {
1460 printk("CRC error");
1461 tell_sector();
1462 } else if ((ST1 & (ST1_MAM | ST1_ND))
1463 || (ST2 & ST2_MAM)) {
1464 if (!probing) {
1465 printk("sector not found");
1466 tell_sector();
1467 } else
1468 printk("probe failed...");
1469 } else if (ST2 & ST2_WC) { /* seek error */
1470 printk("wrong cylinder");
1471 } else if (ST2 & ST2_BC) { /* cylinder marked as bad */
1472 printk("bad cylinder");
1473 } else {
1474 printk
1475 ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
1476 ST0, ST1, ST2);
1477 tell_sector();
1478 }
1479 printk("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 }
1481 if (ST2 & ST2_WC || ST2 & ST2_BC)
1482 /* wrong cylinder => recal */
1483 DRS->track = NEED_2_RECAL;
1484 return bad;
1485 case 0x80: /* invalid command given */
1486 DPRINT("Invalid FDC command given!\n");
1487 cont->done(0);
1488 return 2;
1489 case 0xc0:
1490 DPRINT("Abnormal termination caused by polling\n");
1491 cont->error();
1492 return 2;
1493 default: /* (0) Normal command termination */
1494 return 0;
1495 }
1496}
1497
1498/*
1499 * This routine is called when everything should be correctly set up
1500 * for the transfer (i.e. floppy motor is on, the correct floppy is
1501 * selected, and the head is sitting on the right track).
1502 */
1503static void setup_rw_floppy(void)
1504{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001505 int i;
1506 int r;
1507 int flags;
1508 int dflags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 unsigned long ready_date;
1510 timeout_fn function;
1511
1512 flags = raw_cmd->flags;
1513 if (flags & (FD_RAW_READ | FD_RAW_WRITE))
1514 flags |= FD_RAW_INTR;
1515
1516 if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)) {
1517 ready_date = DRS->spinup_date + DP->spinup;
1518 /* If spinup will take a long time, rerun scandrives
1519 * again just before spinup completion. Beware that
1520 * after scandrives, we must again wait for selection.
1521 */
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001522 if (time_after(ready_date, jiffies + DP->select_delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 ready_date -= DP->select_delay;
1524 function = (timeout_fn) floppy_start;
1525 } else
1526 function = (timeout_fn) setup_rw_floppy;
1527
1528 /* wait until the floppy is spinning fast enough */
1529 if (fd_wait_for_completion(ready_date, function))
1530 return;
1531 }
1532 dflags = DRS->flags;
1533
1534 if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
1535 setup_DMA();
1536
1537 if (flags & FD_RAW_INTR)
1538 do_floppy = main_command_interrupt;
1539
1540 r = 0;
1541 for (i = 0; i < raw_cmd->cmd_count; i++)
1542 r |= output_byte(raw_cmd->cmd[i]);
1543
1544 debugt("rw_command: ");
1545
1546 if (r) {
1547 cont->error();
1548 reset_fdc();
1549 return;
1550 }
1551
1552 if (!(flags & FD_RAW_INTR)) {
1553 inr = result();
1554 cont->interrupt();
1555 } else if (flags & FD_RAW_NEED_DISK)
1556 fd_watchdog();
1557}
1558
1559static int blind_seek;
1560
1561/*
1562 * This is the routine called after every seek (or recalibrate) interrupt
1563 * from the floppy controller.
1564 */
1565static void seek_interrupt(void)
1566{
1567 debugt("seek interrupt:");
1568 if (inr != 2 || (ST0 & 0xF8) != 0x20) {
1569 DPRINT("seek failed\n");
1570 DRS->track = NEED_2_RECAL;
1571 cont->error();
1572 cont->redo();
1573 return;
1574 }
1575 if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) {
1576#ifdef DCL_DEBUG
1577 if (DP->flags & FD_DEBUG) {
1578 DPRINT
1579 ("clearing NEWCHANGE flag because of effective seek\n");
1580 DPRINT("jiffies=%lu\n", jiffies);
1581 }
1582#endif
1583 CLEARF(FD_DISK_NEWCHANGE); /* effective seek */
1584 DRS->select_date = jiffies;
1585 }
1586 DRS->track = ST1;
1587 floppy_ready();
1588}
1589
1590static void check_wp(void)
1591{
1592 if (TESTF(FD_VERIFY)) {
1593 /* check write protection */
1594 output_byte(FD_GETSTATUS);
1595 output_byte(UNIT(current_drive));
1596 if (result() != 1) {
1597 FDCS->reset = 1;
1598 return;
1599 }
1600 CLEARF(FD_VERIFY);
1601 CLEARF(FD_NEED_TWADDLE);
1602#ifdef DCL_DEBUG
1603 if (DP->flags & FD_DEBUG) {
1604 DPRINT("checking whether disk is write protected\n");
1605 DPRINT("wp=%x\n", ST3 & 0x40);
1606 }
1607#endif
1608 if (!(ST3 & 0x40))
1609 SETF(FD_DISK_WRITABLE);
1610 else
1611 CLEARF(FD_DISK_WRITABLE);
1612 }
1613}
1614
1615static void seek_floppy(void)
1616{
1617 int track;
1618
1619 blind_seek = 0;
1620
1621#ifdef DCL_DEBUG
1622 if (DP->flags & FD_DEBUG) {
1623 DPRINT("calling disk change from seek\n");
1624 }
1625#endif
1626
1627 if (!TESTF(FD_DISK_NEWCHANGE) &&
1628 disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) {
1629 /* the media changed flag should be cleared after the seek.
1630 * If it isn't, this means that there is really no disk in
1631 * the drive.
1632 */
1633 SETF(FD_DISK_CHANGED);
1634 cont->done(0);
1635 cont->redo();
1636 return;
1637 }
1638 if (DRS->track <= NEED_1_RECAL) {
1639 recalibrate_floppy();
1640 return;
1641 } else if (TESTF(FD_DISK_NEWCHANGE) &&
1642 (raw_cmd->flags & FD_RAW_NEED_DISK) &&
1643 (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
1644 /* we seek to clear the media-changed condition. Does anybody
1645 * know a more elegant way, which works on all drives? */
1646 if (raw_cmd->track)
1647 track = raw_cmd->track - 1;
1648 else {
1649 if (DP->flags & FD_SILENT_DCL_CLEAR) {
1650 set_dor(fdc, ~(0x10 << UNIT(current_drive)), 0);
1651 blind_seek = 1;
1652 raw_cmd->flags |= FD_RAW_NEED_SEEK;
1653 }
1654 track = 1;
1655 }
1656 } else {
1657 check_wp();
1658 if (raw_cmd->track != DRS->track &&
1659 (raw_cmd->flags & FD_RAW_NEED_SEEK))
1660 track = raw_cmd->track;
1661 else {
1662 setup_rw_floppy();
1663 return;
1664 }
1665 }
1666
1667 do_floppy = seek_interrupt;
1668 output_byte(FD_SEEK);
1669 output_byte(UNIT(current_drive));
1670 LAST_OUT(track);
1671 debugt("seek command:");
1672}
1673
1674static void recal_interrupt(void)
1675{
1676 debugt("recal interrupt:");
1677 if (inr != 2)
1678 FDCS->reset = 1;
1679 else if (ST0 & ST0_ECE) {
1680 switch (DRS->track) {
1681 case NEED_1_RECAL:
1682 debugt("recal interrupt need 1 recal:");
1683 /* after a second recalibrate, we still haven't
1684 * reached track 0. Probably no drive. Raise an
1685 * error, as failing immediately might upset
1686 * computers possessed by the Devil :-) */
1687 cont->error();
1688 cont->redo();
1689 return;
1690 case NEED_2_RECAL:
1691 debugt("recal interrupt need 2 recal:");
1692 /* If we already did a recalibrate,
1693 * and we are not at track 0, this
1694 * means we have moved. (The only way
1695 * not to move at recalibration is to
1696 * be already at track 0.) Clear the
1697 * new change flag */
1698#ifdef DCL_DEBUG
1699 if (DP->flags & FD_DEBUG) {
1700 DPRINT
1701 ("clearing NEWCHANGE flag because of second recalibrate\n");
1702 }
1703#endif
1704
1705 CLEARF(FD_DISK_NEWCHANGE);
1706 DRS->select_date = jiffies;
1707 /* fall through */
1708 default:
1709 debugt("recal interrupt default:");
1710 /* Recalibrate moves the head by at
1711 * most 80 steps. If after one
1712 * recalibrate we don't have reached
1713 * track 0, this might mean that we
1714 * started beyond track 80. Try
1715 * again. */
1716 DRS->track = NEED_1_RECAL;
1717 break;
1718 }
1719 } else
1720 DRS->track = ST1;
1721 floppy_ready();
1722}
1723
1724static void print_result(char *message, int inr)
1725{
1726 int i;
1727
1728 DPRINT("%s ", message);
1729 if (inr >= 0)
1730 for (i = 0; i < inr; i++)
1731 printk("repl[%d]=%x ", i, reply_buffer[i]);
1732 printk("\n");
1733}
1734
1735/* interrupt handler. Note that this can be called externally on the Sparc */
David Howells7d12e782006-10-05 14:55:46 +01001736irqreturn_t floppy_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 int do_print;
1739 unsigned long f;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001740 void (*handler)(void) = do_floppy;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
1742 lasthandler = handler;
1743 interruptjiffies = jiffies;
1744
1745 f = claim_dma_lock();
1746 fd_disable_dma();
1747 release_dma_lock(f);
1748
1749 floppy_enable_hlt();
1750 do_floppy = NULL;
1751 if (fdc >= N_FDC || FDCS->address == -1) {
1752 /* we don't even know which FDC is the culprit */
1753 printk("DOR0=%x\n", fdc_state[0].dor);
1754 printk("floppy interrupt on bizarre fdc %d\n", fdc);
1755 printk("handler=%p\n", handler);
1756 is_alive("bizarre fdc");
1757 return IRQ_NONE;
1758 }
1759
1760 FDCS->reset = 0;
1761 /* We have to clear the reset flag here, because apparently on boxes
1762 * with level triggered interrupts (PS/2, Sparc, ...), it is needed to
1763 * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the
1764 * emission of the SENSEI's.
1765 * It is OK to emit floppy commands because we are in an interrupt
1766 * handler here, and thus we have to fear no interference of other
1767 * activity.
1768 */
1769
1770 do_print = !handler && print_unex && !initialising;
1771
1772 inr = result();
1773 if (do_print)
1774 print_result("unexpected interrupt", inr);
1775 if (inr == 0) {
1776 int max_sensei = 4;
1777 do {
1778 output_byte(FD_SENSEI);
1779 inr = result();
1780 if (do_print)
1781 print_result("sensei", inr);
1782 max_sensei--;
1783 } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2
1784 && max_sensei);
1785 }
1786 if (!handler) {
1787 FDCS->reset = 1;
1788 return IRQ_NONE;
1789 }
1790 schedule_bh(handler);
1791 is_alive("normal interrupt end");
1792
1793 /* FIXME! Was it really for us? */
1794 return IRQ_HANDLED;
1795}
1796
1797static void recalibrate_floppy(void)
1798{
1799 debugt("recalibrate floppy:");
1800 do_floppy = recal_interrupt;
1801 output_byte(FD_RECALIBRATE);
1802 LAST_OUT(UNIT(current_drive));
1803}
1804
1805/*
1806 * Must do 4 FD_SENSEIs after reset because of ``drive polling''.
1807 */
1808static void reset_interrupt(void)
1809{
1810 debugt("reset interrupt:");
1811 result(); /* get the status ready for set_fdc */
1812 if (FDCS->reset) {
1813 printk("reset set in interrupt, calling %p\n", cont->error);
1814 cont->error(); /* a reset just after a reset. BAD! */
1815 }
1816 cont->redo();
1817}
1818
1819/*
1820 * reset is done by pulling bit 2 of DOR low for a while (old FDCs),
1821 * or by setting the self clearing bit 7 of STATUS (newer FDCs)
1822 */
1823static void reset_fdc(void)
1824{
1825 unsigned long flags;
1826
1827 do_floppy = reset_interrupt;
1828 FDCS->reset = 0;
1829 reset_fdc_info(0);
1830
1831 /* Pseudo-DMA may intercept 'reset finished' interrupt. */
1832 /* Irrelevant for systems with true DMA (i386). */
1833
1834 flags = claim_dma_lock();
1835 fd_disable_dma();
1836 release_dma_lock(flags);
1837
1838 if (FDCS->version >= FDC_82072A)
1839 fd_outb(0x80 | (FDCS->dtr & 3), FD_STATUS);
1840 else {
1841 fd_outb(FDCS->dor & ~0x04, FD_DOR);
1842 udelay(FD_RESET_DELAY);
1843 fd_outb(FDCS->dor, FD_DOR);
1844 }
1845}
1846
1847static void show_floppy(void)
1848{
1849 int i;
1850
1851 printk("\n");
1852 printk("floppy driver state\n");
1853 printk("-------------------\n");
1854 printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
1855 jiffies, interruptjiffies, jiffies - interruptjiffies,
1856 lasthandler);
1857
1858#ifdef FLOPPY_SANITY_CHECK
1859 printk("timeout_message=%s\n", timeout_message);
1860 printk("last output bytes:\n");
1861 for (i = 0; i < OLOGSIZE; i++)
1862 printk("%2x %2x %lu\n",
1863 output_log[(i + output_log_pos) % OLOGSIZE].data,
1864 output_log[(i + output_log_pos) % OLOGSIZE].status,
1865 output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
1866 printk("last result at %lu\n", resultjiffies);
1867 printk("last redo_fd_request at %lu\n", lastredo);
1868 for (i = 0; i < resultsize; i++) {
1869 printk("%2x ", reply_buffer[i]);
1870 }
1871 printk("\n");
1872#endif
1873
1874 printk("status=%x\n", fd_inb(FD_STATUS));
1875 printk("fdc_busy=%lu\n", fdc_busy);
1876 if (do_floppy)
1877 printk("do_floppy=%p\n", do_floppy);
David Howells365970a2006-11-22 14:54:49 +00001878 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 printk("floppy_work.func=%p\n", floppy_work.func);
1880 if (timer_pending(&fd_timer))
1881 printk("fd_timer.function=%p\n", fd_timer.function);
1882 if (timer_pending(&fd_timeout)) {
1883 printk("timer_function=%p\n", fd_timeout.function);
1884 printk("expires=%lu\n", fd_timeout.expires - jiffies);
1885 printk("now=%lu\n", jiffies);
1886 }
1887 printk("cont=%p\n", cont);
1888 printk("current_req=%p\n", current_req);
1889 printk("command_status=%d\n", command_status);
1890 printk("\n");
1891}
1892
1893static void floppy_shutdown(unsigned long data)
1894{
1895 unsigned long flags;
1896
1897 if (!initialising)
1898 show_floppy();
1899 cancel_activity();
1900
1901 floppy_enable_hlt();
1902
1903 flags = claim_dma_lock();
1904 fd_disable_dma();
1905 release_dma_lock(flags);
1906
1907 /* avoid dma going to a random drive after shutdown */
1908
1909 if (!initialising)
1910 DPRINT("floppy timeout called\n");
1911 FDCS->reset = 1;
1912 if (cont) {
1913 cont->done(0);
1914 cont->redo(); /* this will recall reset when needed */
1915 } else {
1916 printk("no cont in shutdown!\n");
1917 process_fd_request();
1918 }
1919 is_alive("floppy shutdown");
1920}
1921
1922/*typedef void (*timeout_fn)(unsigned long);*/
1923
1924/* start motor, check media-changed condition and write protection */
Jesper Juhl06f748c2007-10-16 23:30:57 -07001925static int start_motor(void (*function)(void))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001927 int mask;
1928 int data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929
1930 mask = 0xfc;
1931 data = UNIT(current_drive);
1932 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)) {
1933 if (!(FDCS->dor & (0x10 << UNIT(current_drive)))) {
1934 set_debugt();
1935 /* no read since this drive is running */
1936 DRS->first_read_date = 0;
1937 /* note motor start time if motor is not yet running */
1938 DRS->spinup_date = jiffies;
1939 data |= (0x10 << UNIT(current_drive));
1940 }
1941 } else if (FDCS->dor & (0x10 << UNIT(current_drive)))
1942 mask &= ~(0x10 << UNIT(current_drive));
1943
1944 /* starts motor and selects floppy */
1945 del_timer(motor_off_timer + current_drive);
1946 set_dor(fdc, mask, data);
1947
1948 /* wait_for_completion also schedules reset if needed. */
1949 return (fd_wait_for_completion(DRS->select_date + DP->select_delay,
1950 (timeout_fn) function));
1951}
1952
1953static void floppy_ready(void)
1954{
1955 CHECK_RESET;
1956 if (start_motor(floppy_ready))
1957 return;
1958 if (fdc_dtr())
1959 return;
1960
1961#ifdef DCL_DEBUG
1962 if (DP->flags & FD_DEBUG) {
1963 DPRINT("calling disk change from floppy_ready\n");
1964 }
1965#endif
1966 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
1967 disk_change(current_drive) && !DP->select_delay)
1968 twaddle(); /* this clears the dcl on certain drive/controller
1969 * combinations */
1970
1971#ifdef fd_chose_dma_mode
1972 if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) {
1973 unsigned long flags = claim_dma_lock();
1974 fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length);
1975 release_dma_lock(flags);
1976 }
1977#endif
1978
1979 if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)) {
1980 perpendicular_mode();
1981 fdc_specify(); /* must be done here because of hut, hlt ... */
1982 seek_floppy();
1983 } else {
1984 if ((raw_cmd->flags & FD_RAW_READ) ||
1985 (raw_cmd->flags & FD_RAW_WRITE))
1986 fdc_specify();
1987 setup_rw_floppy();
1988 }
1989}
1990
1991static void floppy_start(void)
1992{
1993 reschedule_timeout(current_reqD, "floppy start", 0);
1994
1995 scandrives();
1996#ifdef DCL_DEBUG
1997 if (DP->flags & FD_DEBUG) {
1998 DPRINT("setting NEWCHANGE in floppy_start\n");
1999 }
2000#endif
2001 SETF(FD_DISK_NEWCHANGE);
2002 floppy_ready();
2003}
2004
2005/*
2006 * ========================================================================
2007 * here ends the bottom half. Exported routines are:
2008 * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
2009 * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
2010 * Initialization also uses output_byte, result, set_dor, floppy_interrupt
2011 * and set_dor.
2012 * ========================================================================
2013 */
2014/*
2015 * General purpose continuations.
2016 * ==============================
2017 */
2018
2019static void do_wakeup(void)
2020{
2021 reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
2022 cont = NULL;
2023 command_status += 2;
2024 wake_up(&command_done);
2025}
2026
2027static struct cont_t wakeup_cont = {
2028 .interrupt = empty,
2029 .redo = do_wakeup,
2030 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002031 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032};
2033
2034static struct cont_t intr_cont = {
2035 .interrupt = empty,
2036 .redo = process_fd_request,
2037 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002038 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039};
2040
Jesper Juhl06f748c2007-10-16 23:30:57 -07002041static int wait_til_done(void (*handler)(void), int interruptible)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042{
2043 int ret;
2044
2045 schedule_bh(handler);
2046
2047 if (command_status < 2 && NO_SIGNAL) {
2048 DECLARE_WAITQUEUE(wait, current);
2049
2050 add_wait_queue(&command_done, &wait);
2051 for (;;) {
2052 set_current_state(interruptible ?
2053 TASK_INTERRUPTIBLE :
2054 TASK_UNINTERRUPTIBLE);
2055
2056 if (command_status >= 2 || !NO_SIGNAL)
2057 break;
2058
2059 is_alive("wait_til_done");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060 schedule();
2061 }
2062
2063 set_current_state(TASK_RUNNING);
2064 remove_wait_queue(&command_done, &wait);
2065 }
2066
2067 if (command_status < 2) {
2068 cancel_activity();
2069 cont = &intr_cont;
2070 reset_fdc();
2071 return -EINTR;
2072 }
2073
2074 if (FDCS->reset)
2075 command_status = FD_COMMAND_ERROR;
2076 if (command_status == FD_COMMAND_OKAY)
2077 ret = 0;
2078 else
2079 ret = -EIO;
2080 command_status = FD_COMMAND_NONE;
2081 return ret;
2082}
2083
2084static void generic_done(int result)
2085{
2086 command_status = result;
2087 cont = &wakeup_cont;
2088}
2089
2090static void generic_success(void)
2091{
2092 cont->done(1);
2093}
2094
2095static void generic_failure(void)
2096{
2097 cont->done(0);
2098}
2099
2100static void success_and_wakeup(void)
2101{
2102 generic_success();
2103 cont->redo();
2104}
2105
2106/*
2107 * formatting and rw support.
2108 * ==========================
2109 */
2110
2111static int next_valid_format(void)
2112{
2113 int probed_format;
2114
2115 probed_format = DRS->probed_format;
2116 while (1) {
2117 if (probed_format >= 8 || !DP->autodetect[probed_format]) {
2118 DRS->probed_format = 0;
2119 return 1;
2120 }
2121 if (floppy_type[DP->autodetect[probed_format]].sect) {
2122 DRS->probed_format = probed_format;
2123 return 0;
2124 }
2125 probed_format++;
2126 }
2127}
2128
2129static void bad_flp_intr(void)
2130{
2131 int err_count;
2132
2133 if (probing) {
2134 DRS->probed_format++;
2135 if (!next_valid_format())
2136 return;
2137 }
2138 err_count = ++(*errors);
2139 INFBOUND(DRWE->badness, err_count);
2140 if (err_count > DP->max_errors.abort)
2141 cont->done(0);
2142 if (err_count > DP->max_errors.reset)
2143 FDCS->reset = 1;
2144 else if (err_count > DP->max_errors.recal)
2145 DRS->track = NEED_2_RECAL;
2146}
2147
2148static void set_floppy(int drive)
2149{
2150 int type = ITYPE(UDRS->fd_device);
Jesper Juhl06f748c2007-10-16 23:30:57 -07002151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 if (type)
2153 _floppy = floppy_type + type;
2154 else
2155 _floppy = current_type[drive];
2156}
2157
2158/*
2159 * formatting support.
2160 * ===================
2161 */
2162static void format_interrupt(void)
2163{
2164 switch (interpret_errors()) {
2165 case 1:
2166 cont->error();
2167 case 2:
2168 break;
2169 case 0:
2170 cont->done(1);
2171 }
2172 cont->redo();
2173}
2174
2175#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
2176#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
2177#define CT(x) ((x) | 0xc0)
2178static void setup_format_params(int track)
2179{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002180 int n;
2181 int il;
2182 int count;
2183 int head_shift;
2184 int track_shift;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 struct fparm {
2186 unsigned char track, head, sect, size;
2187 } *here = (struct fparm *)floppy_track_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188
2189 raw_cmd = &default_raw_cmd;
2190 raw_cmd->track = track;
2191
2192 raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
2193 FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
2194 raw_cmd->rate = _floppy->rate & 0x43;
2195 raw_cmd->cmd_count = NR_F;
2196 COMMAND = FM_MODE(_floppy, FD_FORMAT);
2197 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, format_req.head);
2198 F_SIZECODE = FD_SIZECODE(_floppy);
2199 F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE;
2200 F_GAP = _floppy->fmt_gap;
2201 F_FILL = FD_FILL_BYTE;
2202
2203 raw_cmd->kernel_data = floppy_track_buffer;
2204 raw_cmd->length = 4 * F_SECT_PER_TRACK;
2205
2206 /* allow for about 30ms for data transport per track */
2207 head_shift = (F_SECT_PER_TRACK + 5) / 6;
2208
2209 /* a ``cylinder'' is two tracks plus a little stepping time */
2210 track_shift = 2 * head_shift + 3;
2211
2212 /* position of logical sector 1 on this track */
2213 n = (track_shift * format_req.track + head_shift * format_req.head)
2214 % F_SECT_PER_TRACK;
2215
2216 /* determine interleave */
2217 il = 1;
2218 if (_floppy->fmt_gap < 0x22)
2219 il++;
2220
2221 /* initialize field */
2222 for (count = 0; count < F_SECT_PER_TRACK; ++count) {
2223 here[count].track = format_req.track;
2224 here[count].head = format_req.head;
2225 here[count].sect = 0;
2226 here[count].size = F_SIZECODE;
2227 }
2228 /* place logical sectors */
2229 for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
2230 here[n].sect = count;
2231 n = (n + il) % F_SECT_PER_TRACK;
2232 if (here[n].sect) { /* sector busy, find next free sector */
2233 ++n;
2234 if (n >= F_SECT_PER_TRACK) {
2235 n -= F_SECT_PER_TRACK;
2236 while (here[n].sect)
2237 ++n;
2238 }
2239 }
2240 }
2241 if (_floppy->stretch & FD_ZEROBASED) {
2242 for (count = 0; count < F_SECT_PER_TRACK; count++)
2243 here[count].sect--;
2244 }
2245}
2246
2247static void redo_format(void)
2248{
2249 buffer_track = -1;
2250 setup_format_params(format_req.track << STRETCH(_floppy));
2251 floppy_start();
2252 debugt("queue format request");
2253}
2254
2255static struct cont_t format_cont = {
2256 .interrupt = format_interrupt,
2257 .redo = redo_format,
2258 .error = bad_flp_intr,
2259 .done = generic_done
2260};
2261
2262static int do_format(int drive, struct format_descr *tmp_format_req)
2263{
2264 int ret;
2265
2266 LOCK_FDC(drive, 1);
2267 set_floppy(drive);
2268 if (!_floppy ||
2269 _floppy->track > DP->tracks ||
2270 tmp_format_req->track >= _floppy->track ||
2271 tmp_format_req->head >= _floppy->head ||
2272 (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) ||
2273 !_floppy->fmt_gap) {
2274 process_fd_request();
2275 return -EINVAL;
2276 }
2277 format_req = *tmp_format_req;
2278 format_errors = 0;
2279 cont = &format_cont;
2280 errors = &format_errors;
2281 IWAIT(redo_format);
2282 process_fd_request();
2283 return ret;
2284}
2285
2286/*
2287 * Buffer read/write and support
2288 * =============================
2289 */
2290
2291static void floppy_end_request(struct request *req, int uptodate)
2292{
2293 unsigned int nr_sectors = current_count_sectors;
2294
2295 /* current_count_sectors can be zero if transfer failed */
2296 if (!uptodate)
2297 nr_sectors = req->current_nr_sectors;
2298 if (end_that_request_first(req, uptodate, nr_sectors))
2299 return;
2300 add_disk_randomness(req->rq_disk);
2301 floppy_off((long)req->rq_disk->private_data);
2302 blkdev_dequeue_request(req);
Tejun Heo8ffdc652006-01-06 09:49:03 +01002303 end_that_request_last(req, uptodate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
2305 /* We're done with the request */
2306 current_req = NULL;
2307}
2308
2309/* new request_done. Can handle physical sectors which are smaller than a
2310 * logical buffer */
2311static void request_done(int uptodate)
2312{
2313 struct request_queue *q = floppy_queue;
2314 struct request *req = current_req;
2315 unsigned long flags;
2316 int block;
2317
2318 probing = 0;
2319 reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
2320
2321 if (!req) {
2322 printk("floppy.c: no request in request_done\n");
2323 return;
2324 }
2325
2326 if (uptodate) {
2327 /* maintain values for invalidation on geometry
2328 * change */
2329 block = current_count_sectors + req->sector;
2330 INFBOUND(DRS->maxblock, block);
2331 if (block > _floppy->sect)
2332 DRS->maxtrack = 1;
2333
2334 /* unlock chained buffers */
2335 spin_lock_irqsave(q->queue_lock, flags);
2336 floppy_end_request(req, 1);
2337 spin_unlock_irqrestore(q->queue_lock, flags);
2338 } else {
2339 if (rq_data_dir(req) == WRITE) {
2340 /* record write error information */
2341 DRWE->write_errors++;
2342 if (DRWE->write_errors == 1) {
2343 DRWE->first_error_sector = req->sector;
2344 DRWE->first_error_generation = DRS->generation;
2345 }
2346 DRWE->last_error_sector = req->sector;
2347 DRWE->last_error_generation = DRS->generation;
2348 }
2349 spin_lock_irqsave(q->queue_lock, flags);
2350 floppy_end_request(req, 0);
2351 spin_unlock_irqrestore(q->queue_lock, flags);
2352 }
2353}
2354
2355/* Interrupt handler evaluating the result of the r/w operation */
2356static void rw_interrupt(void)
2357{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002358 int eoc;
2359 int ssize;
2360 int heads;
2361 int nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
2363 if (R_HEAD >= 2) {
2364 /* some Toshiba floppy controllers occasionnally seem to
2365 * return bogus interrupts after read/write operations, which
2366 * can be recognized by a bad head number (>= 2) */
2367 return;
2368 }
2369
2370 if (!DRS->first_read_date)
2371 DRS->first_read_date = jiffies;
2372
2373 nr_sectors = 0;
2374 CODE2SIZE;
2375
2376 if (ST1 & ST1_EOC)
2377 eoc = 1;
2378 else
2379 eoc = 0;
2380
2381 if (COMMAND & 0x80)
2382 heads = 2;
2383 else
2384 heads = 1;
2385
2386 nr_sectors = (((R_TRACK - TRACK) * heads +
2387 R_HEAD - HEAD) * SECT_PER_TRACK +
2388 R_SECTOR - SECTOR + eoc) << SIZECODE >> 2;
2389
2390#ifdef FLOPPY_SANITY_CHECK
2391 if (nr_sectors / ssize >
2392 (in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
2393 DPRINT("long rw: %x instead of %lx\n",
2394 nr_sectors, current_count_sectors);
2395 printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
2396 printk("rh=%d h=%d\n", R_HEAD, HEAD);
2397 printk("rt=%d t=%d\n", R_TRACK, TRACK);
2398 printk("heads=%d eoc=%d\n", heads, eoc);
2399 printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
2400 fsector_t, ssize);
2401 printk("in_sector_offset=%d\n", in_sector_offset);
2402 }
2403#endif
2404
2405 nr_sectors -= in_sector_offset;
2406 INFBOUND(nr_sectors, 0);
2407 SUPBOUND(current_count_sectors, nr_sectors);
2408
2409 switch (interpret_errors()) {
2410 case 2:
2411 cont->redo();
2412 return;
2413 case 1:
2414 if (!current_count_sectors) {
2415 cont->error();
2416 cont->redo();
2417 return;
2418 }
2419 break;
2420 case 0:
2421 if (!current_count_sectors) {
2422 cont->redo();
2423 return;
2424 }
2425 current_type[current_drive] = _floppy;
2426 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2427 break;
2428 }
2429
2430 if (probing) {
2431 if (DP->flags & FTD_MSG)
2432 DPRINT("Auto-detected floppy type %s in fd%d\n",
2433 _floppy->name, current_drive);
2434 current_type[current_drive] = _floppy;
2435 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2436 probing = 0;
2437 }
2438
2439 if (CT(COMMAND) != FD_READ ||
2440 raw_cmd->kernel_data == current_req->buffer) {
2441 /* transfer directly from buffer */
2442 cont->done(1);
2443 } else if (CT(COMMAND) == FD_READ) {
2444 buffer_track = raw_cmd->track;
2445 buffer_drive = current_drive;
2446 INFBOUND(buffer_max, nr_sectors + fsector_t);
2447 }
2448 cont->redo();
2449}
2450
2451/* Compute maximal contiguous buffer size. */
2452static int buffer_chain_size(void)
2453{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 struct bio_vec *bv;
NeilBrown5705f702007-09-25 12:35:59 +02002455 int size;
2456 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 char *base;
2458
2459 base = bio_data(current_req->bio);
2460 size = 0;
2461
NeilBrown5705f702007-09-25 12:35:59 +02002462 rq_for_each_segment(bv, current_req, iter) {
2463 if (page_address(bv->bv_page) + bv->bv_offset != base + size)
2464 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
NeilBrown5705f702007-09-25 12:35:59 +02002466 size += bv->bv_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 }
2468
2469 return size >> 9;
2470}
2471
2472/* Compute the maximal transfer size */
2473static int transfer_size(int ssize, int max_sector, int max_size)
2474{
2475 SUPBOUND(max_sector, fsector_t + max_size);
2476
2477 /* alignment */
2478 max_sector -= (max_sector % _floppy->sect) % ssize;
2479
2480 /* transfer size, beginning not aligned */
2481 current_count_sectors = max_sector - fsector_t;
2482
2483 return max_sector;
2484}
2485
2486/*
2487 * Move data from/to the track buffer to/from the buffer cache.
2488 */
2489static void copy_buffer(int ssize, int max_sector, int max_sector_2)
2490{
2491 int remaining; /* number of transferred 512-byte sectors */
2492 struct bio_vec *bv;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002493 char *buffer;
2494 char *dma_buffer;
NeilBrown5705f702007-09-25 12:35:59 +02002495 int size;
2496 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
2498 max_sector = transfer_size(ssize,
2499 min(max_sector, max_sector_2),
2500 current_req->nr_sectors);
2501
2502 if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
2503 buffer_max > fsector_t + current_req->nr_sectors)
2504 current_count_sectors = min_t(int, buffer_max - fsector_t,
2505 current_req->nr_sectors);
2506
2507 remaining = current_count_sectors << 9;
2508#ifdef FLOPPY_SANITY_CHECK
2509 if ((remaining >> 9) > current_req->nr_sectors &&
2510 CT(COMMAND) == FD_WRITE) {
2511 DPRINT("in copy buffer\n");
2512 printk("current_count_sectors=%ld\n", current_count_sectors);
2513 printk("remaining=%d\n", remaining >> 9);
2514 printk("current_req->nr_sectors=%ld\n",
2515 current_req->nr_sectors);
2516 printk("current_req->current_nr_sectors=%u\n",
2517 current_req->current_nr_sectors);
2518 printk("max_sector=%d\n", max_sector);
2519 printk("ssize=%d\n", ssize);
2520 }
2521#endif
2522
2523 buffer_max = max(max_sector, buffer_max);
2524
2525 dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
2526
2527 size = current_req->current_nr_sectors << 9;
2528
NeilBrown5705f702007-09-25 12:35:59 +02002529 rq_for_each_segment(bv, current_req, iter) {
2530 if (!remaining)
2531 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
NeilBrown5705f702007-09-25 12:35:59 +02002533 size = bv->bv_len;
2534 SUPBOUND(size, remaining);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002535
NeilBrown5705f702007-09-25 12:35:59 +02002536 buffer = page_address(bv->bv_page) + bv->bv_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537#ifdef FLOPPY_SANITY_CHECK
NeilBrown5705f702007-09-25 12:35:59 +02002538 if (dma_buffer + size >
2539 floppy_track_buffer + (max_buffer_sectors << 10) ||
2540 dma_buffer < floppy_track_buffer) {
2541 DPRINT("buffer overrun in copy buffer %d\n",
2542 (int)((floppy_track_buffer -
2543 dma_buffer) >> 9));
2544 printk("fsector_t=%d buffer_min=%d\n",
2545 fsector_t, buffer_min);
2546 printk("current_count_sectors=%ld\n",
2547 current_count_sectors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 if (CT(COMMAND) == FD_READ)
NeilBrown5705f702007-09-25 12:35:59 +02002549 printk("read\n");
2550 if (CT(COMMAND) == FD_WRITE)
2551 printk("write\n");
2552 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553 }
NeilBrown5705f702007-09-25 12:35:59 +02002554 if (((unsigned long)buffer) % 512)
2555 DPRINT("%p buffer not aligned\n", buffer);
2556#endif
2557 if (CT(COMMAND) == FD_READ)
2558 memcpy(buffer, dma_buffer, size);
2559 else
2560 memcpy(dma_buffer, buffer, size);
2561
2562 remaining -= size;
2563 dma_buffer += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 }
2565#ifdef FLOPPY_SANITY_CHECK
2566 if (remaining) {
2567 if (remaining > 0)
2568 max_sector -= remaining >> 9;
2569 DPRINT("weirdness: remaining %d\n", remaining >> 9);
2570 }
2571#endif
2572}
2573
2574#if 0
2575static inline int check_dma_crossing(char *start,
2576 unsigned long length, char *message)
2577{
2578 if (CROSS_64KB(start, length)) {
2579 printk("DMA xfer crosses 64KB boundary in %s %p-%p\n",
2580 message, start, start + length);
2581 return 1;
2582 } else
2583 return 0;
2584}
2585#endif
2586
2587/* work around a bug in pseudo DMA
2588 * (on some FDCs) pseudo DMA does not stop when the CPU stops
2589 * sending data. Hence we need a different way to signal the
2590 * transfer length: We use SECT_PER_TRACK. Unfortunately, this
2591 * does not work with MT, hence we can only transfer one head at
2592 * a time
2593 */
2594static void virtualdmabug_workaround(void)
2595{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002596 int hard_sectors;
2597 int end_sector;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
2599 if (CT(COMMAND) == FD_WRITE) {
2600 COMMAND &= ~0x80; /* switch off multiple track mode */
2601
2602 hard_sectors = raw_cmd->length >> (7 + SIZECODE);
2603 end_sector = SECTOR + hard_sectors - 1;
2604#ifdef FLOPPY_SANITY_CHECK
2605 if (end_sector > SECT_PER_TRACK) {
2606 printk("too many sectors %d > %d\n",
2607 end_sector, SECT_PER_TRACK);
2608 return;
2609 }
2610#endif
2611 SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points
2612 * to end of transfer */
2613 }
2614}
2615
2616/*
2617 * Formulate a read/write request.
2618 * this routine decides where to load the data (directly to buffer, or to
2619 * tmp floppy area), how much data to load (the size of the buffer, the whole
2620 * track, or a single sector)
2621 * All floppy_track_buffer handling goes in here. If we ever add track buffer
2622 * allocation on the fly, it should be done here. No other part should need
2623 * modification.
2624 */
2625
2626static int make_raw_rw_request(void)
2627{
2628 int aligned_sector_t;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002629 int max_sector;
2630 int max_size;
2631 int tracksize;
2632 int ssize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
2634 if (max_buffer_sectors == 0) {
2635 printk("VFS: Block I/O scheduled on unopened device\n");
2636 return 0;
2637 }
2638
2639 set_fdc((long)current_req->rq_disk->private_data);
2640
2641 raw_cmd = &default_raw_cmd;
2642 raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
2643 FD_RAW_NEED_SEEK;
2644 raw_cmd->cmd_count = NR_RW;
2645 if (rq_data_dir(current_req) == READ) {
2646 raw_cmd->flags |= FD_RAW_READ;
2647 COMMAND = FM_MODE(_floppy, FD_READ);
2648 } else if (rq_data_dir(current_req) == WRITE) {
2649 raw_cmd->flags |= FD_RAW_WRITE;
2650 COMMAND = FM_MODE(_floppy, FD_WRITE);
2651 } else {
2652 DPRINT("make_raw_rw_request: unknown command\n");
2653 return 0;
2654 }
2655
2656 max_sector = _floppy->sect * _floppy->head;
2657
2658 TRACK = (int)current_req->sector / max_sector;
2659 fsector_t = (int)current_req->sector % max_sector;
2660 if (_floppy->track && TRACK >= _floppy->track) {
2661 if (current_req->current_nr_sectors & 1) {
2662 current_count_sectors = 1;
2663 return 1;
2664 } else
2665 return 0;
2666 }
2667 HEAD = fsector_t / _floppy->sect;
2668
2669 if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
2670 TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
2671 max_sector = _floppy->sect;
2672
2673 /* 2M disks have phantom sectors on the first track */
2674 if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)) {
2675 max_sector = 2 * _floppy->sect / 3;
2676 if (fsector_t >= max_sector) {
2677 current_count_sectors =
2678 min_t(int, _floppy->sect - fsector_t,
2679 current_req->nr_sectors);
2680 return 1;
2681 }
2682 SIZECODE = 2;
2683 } else
2684 SIZECODE = FD_SIZECODE(_floppy);
2685 raw_cmd->rate = _floppy->rate & 0x43;
2686 if ((_floppy->rate & FD_2M) && (TRACK || HEAD) && raw_cmd->rate == 2)
2687 raw_cmd->rate = 1;
2688
2689 if (SIZECODE)
2690 SIZECODE2 = 0xff;
2691 else
2692 SIZECODE2 = 0x80;
2693 raw_cmd->track = TRACK << STRETCH(_floppy);
2694 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD);
2695 GAP = _floppy->gap;
2696 CODE2SIZE;
2697 SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
2698 SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
2699 ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1);
2700
2701 /* tracksize describes the size which can be filled up with sectors
2702 * of size ssize.
2703 */
2704 tracksize = _floppy->sect - _floppy->sect % ssize;
2705 if (tracksize < _floppy->sect) {
2706 SECT_PER_TRACK++;
2707 if (tracksize <= fsector_t % _floppy->sect)
2708 SECTOR--;
2709
2710 /* if we are beyond tracksize, fill up using smaller sectors */
2711 while (tracksize <= fsector_t % _floppy->sect) {
2712 while (tracksize + ssize > _floppy->sect) {
2713 SIZECODE--;
2714 ssize >>= 1;
2715 }
2716 SECTOR++;
2717 SECT_PER_TRACK++;
2718 tracksize += ssize;
2719 }
2720 max_sector = HEAD * _floppy->sect + tracksize;
2721 } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) {
2722 max_sector = _floppy->sect;
2723 } else if (!HEAD && CT(COMMAND) == FD_WRITE) {
2724 /* for virtual DMA bug workaround */
2725 max_sector = _floppy->sect;
2726 }
2727
2728 in_sector_offset = (fsector_t % _floppy->sect) % ssize;
2729 aligned_sector_t = fsector_t - in_sector_offset;
2730 max_size = current_req->nr_sectors;
2731 if ((raw_cmd->track == buffer_track) &&
2732 (current_drive == buffer_drive) &&
2733 (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
2734 /* data already in track buffer */
2735 if (CT(COMMAND) == FD_READ) {
2736 copy_buffer(1, max_sector, buffer_max);
2737 return 1;
2738 }
2739 } else if (in_sector_offset || current_req->nr_sectors < ssize) {
2740 if (CT(COMMAND) == FD_WRITE) {
2741 if (fsector_t + current_req->nr_sectors > ssize &&
2742 fsector_t + current_req->nr_sectors < ssize + ssize)
2743 max_size = ssize + ssize;
2744 else
2745 max_size = ssize;
2746 }
2747 raw_cmd->flags &= ~FD_RAW_WRITE;
2748 raw_cmd->flags |= FD_RAW_READ;
2749 COMMAND = FM_MODE(_floppy, FD_READ);
2750 } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
2751 unsigned long dma_limit;
2752 int direct, indirect;
2753
2754 indirect =
2755 transfer_size(ssize, max_sector,
2756 max_buffer_sectors * 2) - fsector_t;
2757
2758 /*
2759 * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
2760 * on a 64 bit machine!
2761 */
2762 max_size = buffer_chain_size();
2763 dma_limit =
2764 (MAX_DMA_ADDRESS -
2765 ((unsigned long)current_req->buffer)) >> 9;
2766 if ((unsigned long)max_size > dma_limit) {
2767 max_size = dma_limit;
2768 }
2769 /* 64 kb boundaries */
2770 if (CROSS_64KB(current_req->buffer, max_size << 9))
2771 max_size = (K_64 -
2772 ((unsigned long)current_req->buffer) %
2773 K_64) >> 9;
2774 direct = transfer_size(ssize, max_sector, max_size) - fsector_t;
2775 /*
2776 * We try to read tracks, but if we get too many errors, we
2777 * go back to reading just one sector at a time.
2778 *
2779 * This means we should be able to read a sector even if there
2780 * are other bad sectors on this track.
2781 */
2782 if (!direct ||
2783 (indirect * 2 > direct * 3 &&
2784 *errors < DP->max_errors.read_track &&
2785 /*!TESTF(FD_NEED_TWADDLE) && */
2786 ((!probing
2787 || (DP->read_track & (1 << DRS->probed_format)))))) {
2788 max_size = current_req->nr_sectors;
2789 } else {
2790 raw_cmd->kernel_data = current_req->buffer;
2791 raw_cmd->length = current_count_sectors << 9;
2792 if (raw_cmd->length == 0) {
2793 DPRINT
2794 ("zero dma transfer attempted from make_raw_request\n");
2795 DPRINT("indirect=%d direct=%d fsector_t=%d",
2796 indirect, direct, fsector_t);
2797 return 0;
2798 }
Jesper Juhl06f748c2007-10-16 23:30:57 -07002799/* check_dma_crossing(raw_cmd->kernel_data,
2800 raw_cmd->length,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 "end of make_raw_request [1]");*/
2802
2803 virtualdmabug_workaround();
2804 return 2;
2805 }
2806 }
2807
2808 if (CT(COMMAND) == FD_READ)
2809 max_size = max_sector; /* unbounded */
2810
2811 /* claim buffer track if needed */
2812 if (buffer_track != raw_cmd->track || /* bad track */
2813 buffer_drive != current_drive || /* bad drive */
2814 fsector_t > buffer_max ||
2815 fsector_t < buffer_min ||
2816 ((CT(COMMAND) == FD_READ ||
2817 (!in_sector_offset && current_req->nr_sectors >= ssize)) &&
2818 max_sector > 2 * max_buffer_sectors + buffer_min &&
2819 max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
2820 /* not enough space */
2821 ) {
2822 buffer_track = -1;
2823 buffer_drive = current_drive;
2824 buffer_max = buffer_min = aligned_sector_t;
2825 }
2826 raw_cmd->kernel_data = floppy_track_buffer +
2827 ((aligned_sector_t - buffer_min) << 9);
2828
2829 if (CT(COMMAND) == FD_WRITE) {
2830 /* copy write buffer to track buffer.
2831 * if we get here, we know that the write
2832 * is either aligned or the data already in the buffer
2833 * (buffer will be overwritten) */
2834#ifdef FLOPPY_SANITY_CHECK
2835 if (in_sector_offset && buffer_track == -1)
2836 DPRINT("internal error offset !=0 on write\n");
2837#endif
2838 buffer_track = raw_cmd->track;
2839 buffer_drive = current_drive;
2840 copy_buffer(ssize, max_sector,
2841 2 * max_buffer_sectors + buffer_min);
2842 } else
2843 transfer_size(ssize, max_sector,
2844 2 * max_buffer_sectors + buffer_min -
2845 aligned_sector_t);
2846
2847 /* round up current_count_sectors to get dma xfer size */
2848 raw_cmd->length = in_sector_offset + current_count_sectors;
2849 raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
2850 raw_cmd->length <<= 9;
2851#ifdef FLOPPY_SANITY_CHECK
2852 /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length,
2853 "end of make_raw_request"); */
2854 if ((raw_cmd->length < current_count_sectors << 9) ||
2855 (raw_cmd->kernel_data != current_req->buffer &&
2856 CT(COMMAND) == FD_WRITE &&
2857 (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
2858 aligned_sector_t < buffer_min)) ||
2859 raw_cmd->length % (128 << SIZECODE) ||
2860 raw_cmd->length <= 0 || current_count_sectors <= 0) {
2861 DPRINT("fractionary current count b=%lx s=%lx\n",
2862 raw_cmd->length, current_count_sectors);
2863 if (raw_cmd->kernel_data != current_req->buffer)
2864 printk("addr=%d, length=%ld\n",
2865 (int)((raw_cmd->kernel_data -
2866 floppy_track_buffer) >> 9),
2867 current_count_sectors);
2868 printk("st=%d ast=%d mse=%d msi=%d\n",
2869 fsector_t, aligned_sector_t, max_sector, max_size);
2870 printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
2871 printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
2872 COMMAND, SECTOR, HEAD, TRACK);
2873 printk("buffer drive=%d\n", buffer_drive);
2874 printk("buffer track=%d\n", buffer_track);
2875 printk("buffer_min=%d\n", buffer_min);
2876 printk("buffer_max=%d\n", buffer_max);
2877 return 0;
2878 }
2879
2880 if (raw_cmd->kernel_data != current_req->buffer) {
2881 if (raw_cmd->kernel_data < floppy_track_buffer ||
2882 current_count_sectors < 0 ||
2883 raw_cmd->length < 0 ||
2884 raw_cmd->kernel_data + raw_cmd->length >
2885 floppy_track_buffer + (max_buffer_sectors << 10)) {
2886 DPRINT("buffer overrun in schedule dma\n");
2887 printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
2888 fsector_t, buffer_min, raw_cmd->length >> 9);
2889 printk("current_count_sectors=%ld\n",
2890 current_count_sectors);
2891 if (CT(COMMAND) == FD_READ)
2892 printk("read\n");
2893 if (CT(COMMAND) == FD_WRITE)
2894 printk("write\n");
2895 return 0;
2896 }
2897 } else if (raw_cmd->length > current_req->nr_sectors << 9 ||
2898 current_count_sectors > current_req->nr_sectors) {
2899 DPRINT("buffer overrun in direct transfer\n");
2900 return 0;
2901 } else if (raw_cmd->length < current_count_sectors << 9) {
2902 DPRINT("more sectors than bytes\n");
2903 printk("bytes=%ld\n", raw_cmd->length >> 9);
2904 printk("sectors=%ld\n", current_count_sectors);
2905 }
2906 if (raw_cmd->length == 0) {
2907 DPRINT("zero dma transfer attempted from make_raw_request\n");
2908 return 0;
2909 }
2910#endif
2911
2912 virtualdmabug_workaround();
2913 return 2;
2914}
2915
2916static void redo_fd_request(void)
2917{
2918#define REPEAT {request_done(0); continue; }
2919 int drive;
2920 int tmp;
2921
2922 lastredo = jiffies;
2923 if (current_drive < N_DRIVE)
2924 floppy_off(current_drive);
2925
2926 for (;;) {
2927 if (!current_req) {
2928 struct request *req;
2929
2930 spin_lock_irq(floppy_queue->queue_lock);
2931 req = elv_next_request(floppy_queue);
2932 spin_unlock_irq(floppy_queue->queue_lock);
2933 if (!req) {
2934 do_floppy = NULL;
2935 unlock_fdc();
2936 return;
2937 }
2938 current_req = req;
2939 }
2940 drive = (long)current_req->rq_disk->private_data;
2941 set_fdc(drive);
2942 reschedule_timeout(current_reqD, "redo fd request", 0);
2943
2944 set_floppy(drive);
2945 raw_cmd = &default_raw_cmd;
2946 raw_cmd->flags = 0;
2947 if (start_motor(redo_fd_request))
2948 return;
2949 disk_change(current_drive);
2950 if (test_bit(current_drive, &fake_change) ||
2951 TESTF(FD_DISK_CHANGED)) {
2952 DPRINT("disk absent or changed during operation\n");
2953 REPEAT;
2954 }
2955 if (!_floppy) { /* Autodetection */
2956 if (!probing) {
2957 DRS->probed_format = 0;
2958 if (next_valid_format()) {
2959 DPRINT("no autodetectable formats\n");
2960 _floppy = NULL;
2961 REPEAT;
2962 }
2963 }
2964 probing = 1;
2965 _floppy =
2966 floppy_type + DP->autodetect[DRS->probed_format];
2967 } else
2968 probing = 0;
2969 errors = &(current_req->errors);
2970 tmp = make_raw_rw_request();
2971 if (tmp < 2) {
2972 request_done(tmp);
2973 continue;
2974 }
2975
2976 if (TESTF(FD_NEED_TWADDLE))
2977 twaddle();
2978 schedule_bh(floppy_start);
2979 debugt("queue fd request");
2980 return;
2981 }
2982#undef REPEAT
2983}
2984
2985static struct cont_t rw_cont = {
2986 .interrupt = rw_interrupt,
2987 .redo = redo_fd_request,
2988 .error = bad_flp_intr,
2989 .done = request_done
2990};
2991
2992static void process_fd_request(void)
2993{
2994 cont = &rw_cont;
2995 schedule_bh(redo_fd_request);
2996}
2997
Jens Axboe165125e2007-07-24 09:28:11 +02002998static void do_fd_request(struct request_queue * q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999{
3000 if (max_buffer_sectors == 0) {
3001 printk("VFS: do_fd_request called on non-open device\n");
3002 return;
3003 }
3004
3005 if (usage_count == 0) {
3006 printk("warning: usage count=0, current_req=%p exiting\n",
3007 current_req);
Jens Axboe4aff5e22006-08-10 08:44:47 +02003008 printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
3009 current_req->cmd_type, current_req->cmd_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 return;
3011 }
3012 if (test_bit(0, &fdc_busy)) {
3013 /* fdc busy, this new request will be treated when the
3014 current one is done */
3015 is_alive("do fd request, old request running");
3016 return;
3017 }
3018 lock_fdc(MAXTIMEOUT, 0);
3019 process_fd_request();
3020 is_alive("do fd request");
3021}
3022
3023static struct cont_t poll_cont = {
3024 .interrupt = success_and_wakeup,
3025 .redo = floppy_ready,
3026 .error = generic_failure,
3027 .done = generic_done
3028};
3029
3030static int poll_drive(int interruptible, int flag)
3031{
3032 int ret;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003033
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 /* no auto-sense, just clear dcl */
3035 raw_cmd = &default_raw_cmd;
3036 raw_cmd->flags = flag;
3037 raw_cmd->track = 0;
3038 raw_cmd->cmd_count = 0;
3039 cont = &poll_cont;
3040#ifdef DCL_DEBUG
3041 if (DP->flags & FD_DEBUG) {
3042 DPRINT("setting NEWCHANGE in poll_drive\n");
3043 }
3044#endif
3045 SETF(FD_DISK_NEWCHANGE);
3046 WAIT(floppy_ready);
3047 return ret;
3048}
3049
3050/*
3051 * User triggered reset
3052 * ====================
3053 */
3054
3055static void reset_intr(void)
3056{
3057 printk("weird, reset interrupt called\n");
3058}
3059
3060static struct cont_t reset_cont = {
3061 .interrupt = reset_intr,
3062 .redo = success_and_wakeup,
3063 .error = generic_failure,
3064 .done = generic_done
3065};
3066
3067static int user_reset_fdc(int drive, int arg, int interruptible)
3068{
3069 int ret;
3070
3071 ret = 0;
3072 LOCK_FDC(drive, interruptible);
3073 if (arg == FD_RESET_ALWAYS)
3074 FDCS->reset = 1;
3075 if (FDCS->reset) {
3076 cont = &reset_cont;
3077 WAIT(reset_fdc);
3078 }
3079 process_fd_request();
3080 return ret;
3081}
3082
3083/*
3084 * Misc Ioctl's and support
3085 * ========================
3086 */
3087static inline int fd_copyout(void __user *param, const void *address,
3088 unsigned long size)
3089{
3090 return copy_to_user(param, address, size) ? -EFAULT : 0;
3091}
3092
3093static inline int fd_copyin(void __user *param, void *address, unsigned long size)
3094{
3095 return copy_from_user(address, param, size) ? -EFAULT : 0;
3096}
3097
3098#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0)
3099#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0)
3100
3101#define COPYOUT(x) ECALL(_COPYOUT(x))
3102#define COPYIN(x) ECALL(_COPYIN(x))
3103
3104static inline const char *drive_name(int type, int drive)
3105{
3106 struct floppy_struct *floppy;
3107
3108 if (type)
3109 floppy = floppy_type + type;
3110 else {
3111 if (UDP->native_format)
3112 floppy = floppy_type + UDP->native_format;
3113 else
3114 return "(null)";
3115 }
3116 if (floppy->name)
3117 return floppy->name;
3118 else
3119 return "(null)";
3120}
3121
3122/* raw commands */
3123static void raw_cmd_done(int flag)
3124{
3125 int i;
3126
3127 if (!flag) {
3128 raw_cmd->flags |= FD_RAW_FAILURE;
3129 raw_cmd->flags |= FD_RAW_HARDFAILURE;
3130 } else {
3131 raw_cmd->reply_count = inr;
3132 if (raw_cmd->reply_count > MAX_REPLIES)
3133 raw_cmd->reply_count = 0;
3134 for (i = 0; i < raw_cmd->reply_count; i++)
3135 raw_cmd->reply[i] = reply_buffer[i];
3136
3137 if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3138 unsigned long flags;
3139 flags = claim_dma_lock();
3140 raw_cmd->length = fd_get_dma_residue();
3141 release_dma_lock(flags);
3142 }
3143
3144 if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
3145 (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
3146 raw_cmd->flags |= FD_RAW_FAILURE;
3147
3148 if (disk_change(current_drive))
3149 raw_cmd->flags |= FD_RAW_DISK_CHANGE;
3150 else
3151 raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
3152 if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
3153 motor_off_callback(current_drive);
3154
3155 if (raw_cmd->next &&
3156 (!(raw_cmd->flags & FD_RAW_FAILURE) ||
3157 !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
3158 ((raw_cmd->flags & FD_RAW_FAILURE) ||
3159 !(raw_cmd->flags & FD_RAW_STOP_IF_SUCCESS))) {
3160 raw_cmd = raw_cmd->next;
3161 return;
3162 }
3163 }
3164 generic_done(flag);
3165}
3166
3167static struct cont_t raw_cmd_cont = {
3168 .interrupt = success_and_wakeup,
3169 .redo = floppy_start,
3170 .error = generic_failure,
3171 .done = raw_cmd_done
3172};
3173
3174static inline int raw_cmd_copyout(int cmd, char __user *param,
3175 struct floppy_raw_cmd *ptr)
3176{
3177 int ret;
3178
3179 while (ptr) {
3180 COPYOUT(*ptr);
3181 param += sizeof(struct floppy_raw_cmd);
3182 if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) {
3183 if (ptr->length >= 0
3184 && ptr->length <= ptr->buffer_length)
3185 ECALL(fd_copyout
3186 (ptr->data, ptr->kernel_data,
3187 ptr->buffer_length - ptr->length));
3188 }
3189 ptr = ptr->next;
3190 }
3191 return 0;
3192}
3193
3194static void raw_cmd_free(struct floppy_raw_cmd **ptr)
3195{
Jesper Juhl06f748c2007-10-16 23:30:57 -07003196 struct floppy_raw_cmd *next;
3197 struct floppy_raw_cmd *this;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198
3199 this = *ptr;
3200 *ptr = NULL;
3201 while (this) {
3202 if (this->buffer_length) {
3203 fd_dma_mem_free((unsigned long)this->kernel_data,
3204 this->buffer_length);
3205 this->buffer_length = 0;
3206 }
3207 next = this->next;
3208 kfree(this);
3209 this = next;
3210 }
3211}
3212
3213static inline int raw_cmd_copyin(int cmd, char __user *param,
3214 struct floppy_raw_cmd **rcmd)
3215{
3216 struct floppy_raw_cmd *ptr;
3217 int ret;
3218 int i;
3219
3220 *rcmd = NULL;
3221 while (1) {
3222 ptr = (struct floppy_raw_cmd *)
3223 kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
3224 if (!ptr)
3225 return -ENOMEM;
3226 *rcmd = ptr;
3227 COPYIN(*ptr);
3228 ptr->next = NULL;
3229 ptr->buffer_length = 0;
3230 param += sizeof(struct floppy_raw_cmd);
3231 if (ptr->cmd_count > 33)
3232 /* the command may now also take up the space
3233 * initially intended for the reply & the
3234 * reply count. Needed for long 82078 commands
3235 * such as RESTORE, which takes ... 17 command
3236 * bytes. Murphy's law #137: When you reserve
3237 * 16 bytes for a structure, you'll one day
3238 * discover that you really need 17...
3239 */
3240 return -EINVAL;
3241
3242 for (i = 0; i < 16; i++)
3243 ptr->reply[i] = 0;
3244 ptr->resultcode = 0;
3245 ptr->kernel_data = NULL;
3246
3247 if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3248 if (ptr->length <= 0)
3249 return -EINVAL;
3250 ptr->kernel_data =
3251 (char *)fd_dma_mem_alloc(ptr->length);
3252 fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
3253 if (!ptr->kernel_data)
3254 return -ENOMEM;
3255 ptr->buffer_length = ptr->length;
3256 }
3257 if (ptr->flags & FD_RAW_WRITE)
3258 ECALL(fd_copyin(ptr->data, ptr->kernel_data,
3259 ptr->length));
3260 rcmd = &(ptr->next);
3261 if (!(ptr->flags & FD_RAW_MORE))
3262 return 0;
3263 ptr->rate &= 0x43;
3264 }
3265}
3266
3267static int raw_cmd_ioctl(int cmd, void __user *param)
3268{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 struct floppy_raw_cmd *my_raw_cmd;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003270 int drive;
3271 int ret2;
3272 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
3274 if (FDCS->rawcmd <= 1)
3275 FDCS->rawcmd = 1;
3276 for (drive = 0; drive < N_DRIVE; drive++) {
3277 if (FDC(drive) != fdc)
3278 continue;
3279 if (drive == current_drive) {
3280 if (UDRS->fd_ref > 1) {
3281 FDCS->rawcmd = 2;
3282 break;
3283 }
3284 } else if (UDRS->fd_ref) {
3285 FDCS->rawcmd = 2;
3286 break;
3287 }
3288 }
3289
3290 if (FDCS->reset)
3291 return -EIO;
3292
3293 ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
3294 if (ret) {
3295 raw_cmd_free(&my_raw_cmd);
3296 return ret;
3297 }
3298
3299 raw_cmd = my_raw_cmd;
3300 cont = &raw_cmd_cont;
3301 ret = wait_til_done(floppy_start, 1);
3302#ifdef DCL_DEBUG
3303 if (DP->flags & FD_DEBUG) {
3304 DPRINT("calling disk change from raw_cmd ioctl\n");
3305 }
3306#endif
3307
3308 if (ret != -EINTR && FDCS->reset)
3309 ret = -EIO;
3310
3311 DRS->track = NO_TRACK;
3312
3313 ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
3314 if (!ret)
3315 ret = ret2;
3316 raw_cmd_free(&my_raw_cmd);
3317 return ret;
3318}
3319
3320static int invalidate_drive(struct block_device *bdev)
3321{
3322 /* invalidate the buffer track to force a reread */
3323 set_bit((long)bdev->bd_disk->private_data, &fake_change);
3324 process_fd_request();
3325 check_disk_change(bdev);
3326 return 0;
3327}
3328
3329static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
3330 int drive, int type, struct block_device *bdev)
3331{
3332 int cnt;
3333
3334 /* sanity checking for parameters. */
3335 if (g->sect <= 0 ||
3336 g->head <= 0 ||
3337 g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
3338 /* check if reserved bits are set */
3339 (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0)
3340 return -EINVAL;
3341 if (type) {
3342 if (!capable(CAP_SYS_ADMIN))
3343 return -EPERM;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003344 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345 LOCK_FDC(drive, 1);
3346 floppy_type[type] = *g;
3347 floppy_type[type].name = "user format";
3348 for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
3349 floppy_sizes[cnt] = floppy_sizes[cnt + 0x80] =
3350 floppy_type[type].size + 1;
3351 process_fd_request();
3352 for (cnt = 0; cnt < N_DRIVE; cnt++) {
3353 struct block_device *bdev = opened_bdev[cnt];
3354 if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
3355 continue;
Christoph Hellwig2ef41632005-05-05 16:15:59 -07003356 __invalidate_device(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003358 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359 } else {
3360 int oldStretch;
3361 LOCK_FDC(drive, 1);
3362 if (cmd != FDDEFPRM)
3363 /* notice a disk change immediately, else
3364 * we lose our settings immediately*/
3365 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3366 oldStretch = g->stretch;
3367 user_params[drive] = *g;
3368 if (buffer_drive == drive)
3369 SUPBOUND(buffer_max, user_params[drive].sect);
3370 current_type[drive] = &user_params[drive];
3371 floppy_sizes[drive] = user_params[drive].size;
3372 if (cmd == FDDEFPRM)
3373 DRS->keep_data = -1;
3374 else
3375 DRS->keep_data = 1;
3376 /* invalidation. Invalidate only when needed, i.e.
3377 * when there are already sectors in the buffer cache
3378 * whose number will change. This is useful, because
3379 * mtools often changes the geometry of the disk after
3380 * looking at the boot block */
3381 if (DRS->maxblock > user_params[drive].sect ||
3382 DRS->maxtrack ||
3383 ((user_params[drive].sect ^ oldStretch) &
3384 (FD_SWAPSIDES | FD_ZEROBASED)))
3385 invalidate_drive(bdev);
3386 else
3387 process_fd_request();
3388 }
3389 return 0;
3390}
3391
3392/* handle obsolete ioctl's */
3393static int ioctl_table[] = {
3394 FDCLRPRM,
3395 FDSETPRM,
3396 FDDEFPRM,
3397 FDGETPRM,
3398 FDMSGON,
3399 FDMSGOFF,
3400 FDFMTBEG,
3401 FDFMTTRK,
3402 FDFMTEND,
3403 FDSETEMSGTRESH,
3404 FDFLUSH,
3405 FDSETMAXERRS,
3406 FDGETMAXERRS,
3407 FDGETDRVTYP,
3408 FDSETDRVPRM,
3409 FDGETDRVPRM,
3410 FDGETDRVSTAT,
3411 FDPOLLDRVSTAT,
3412 FDRESET,
3413 FDGETFDCSTAT,
3414 FDWERRORCLR,
3415 FDWERRORGET,
3416 FDRAWCMD,
3417 FDEJECT,
3418 FDTWADDLE
3419};
3420
3421static inline int normalize_ioctl(int *cmd, int *size)
3422{
3423 int i;
3424
3425 for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) {
3426 if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)) {
3427 *size = _IOC_SIZE(*cmd);
3428 *cmd = ioctl_table[i];
3429 if (*size > _IOC_SIZE(*cmd)) {
3430 printk("ioctl not yet supported\n");
3431 return -EFAULT;
3432 }
3433 return 0;
3434 }
3435 }
3436 return -EINVAL;
3437}
3438
3439static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
3440{
3441 if (type)
3442 *g = &floppy_type[type];
3443 else {
3444 LOCK_FDC(drive, 0);
3445 CALL(poll_drive(0, 0));
3446 process_fd_request();
3447 *g = current_type[drive];
3448 }
3449 if (!*g)
3450 return -ENODEV;
3451 return 0;
3452}
3453
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08003454static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3455{
3456 int drive = (long)bdev->bd_disk->private_data;
3457 int type = ITYPE(drive_state[drive].fd_device);
3458 struct floppy_struct *g;
3459 int ret;
3460
3461 ret = get_floppy_geometry(drive, type, &g);
3462 if (ret)
3463 return ret;
3464
3465 geo->heads = g->head;
3466 geo->sectors = g->sect;
3467 geo->cylinders = g->track;
3468 return 0;
3469}
3470
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
3472 unsigned long param)
3473{
3474#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
3475#define OUT(c,x) case c: outparam = (const char *) (x); break
3476#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
3477
3478 int drive = (long)inode->i_bdev->bd_disk->private_data;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003479 int type = ITYPE(UDRS->fd_device);
3480 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481 int ret;
3482 int size;
3483 union inparam {
3484 struct floppy_struct g; /* geometry */
3485 struct format_descr f;
3486 struct floppy_max_errors max_errors;
3487 struct floppy_drive_params dp;
3488 } inparam; /* parameters coming from user space */
3489 const char *outparam; /* parameters passed back to user space */
3490
3491 /* convert compatibility eject ioctls into floppy eject ioctl.
3492 * We do this in order to provide a means to eject floppy disks before
3493 * installing the new fdutils package */
3494 if (cmd == CDROMEJECT || /* CD-ROM eject */
3495 cmd == 0x6470 /* SunOS floppy eject */ ) {
3496 DPRINT("obsolete eject ioctl\n");
3497 DPRINT("please use floppycontrol --eject\n");
3498 cmd = FDEJECT;
3499 }
3500
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 /* convert the old style command into a new style command */
3502 if ((cmd & 0xff00) == 0x0200) {
3503 ECALL(normalize_ioctl(&cmd, &size));
3504 } else
3505 return -EINVAL;
3506
3507 /* permission checks */
3508 if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
3509 ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
3510 return -EPERM;
3511
3512 /* copyin */
3513 CLEARSTRUCT(&inparam);
3514 if (_IOC_DIR(cmd) & _IOC_WRITE)
3515 ECALL(fd_copyin((void __user *)param, &inparam, size))
3516
3517 switch (cmd) {
3518 case FDEJECT:
3519 if (UDRS->fd_ref != 1)
3520 /* somebody else has this drive open */
3521 return -EBUSY;
3522 LOCK_FDC(drive, 1);
3523
3524 /* do the actual eject. Fails on
3525 * non-Sparc architectures */
3526 ret = fd_eject(UNIT(drive));
3527
3528 USETF(FD_DISK_CHANGED);
3529 USETF(FD_VERIFY);
3530 process_fd_request();
3531 return ret;
3532 case FDCLRPRM:
3533 LOCK_FDC(drive, 1);
3534 current_type[drive] = NULL;
3535 floppy_sizes[drive] = MAX_DISK_SIZE << 1;
3536 UDRS->keep_data = 0;
3537 return invalidate_drive(inode->i_bdev);
3538 case FDSETPRM:
3539 case FDDEFPRM:
3540 return set_geometry(cmd, &inparam.g,
3541 drive, type, inode->i_bdev);
3542 case FDGETPRM:
3543 ECALL(get_floppy_geometry(drive, type,
3544 (struct floppy_struct **)
3545 &outparam));
3546 break;
3547
3548 case FDMSGON:
3549 UDP->flags |= FTD_MSG;
3550 return 0;
3551 case FDMSGOFF:
3552 UDP->flags &= ~FTD_MSG;
3553 return 0;
3554
3555 case FDFMTBEG:
3556 LOCK_FDC(drive, 1);
3557 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3558 ret = UDRS->flags;
3559 process_fd_request();
3560 if (ret & FD_VERIFY)
3561 return -ENODEV;
3562 if (!(ret & FD_DISK_WRITABLE))
3563 return -EROFS;
3564 return 0;
3565 case FDFMTTRK:
3566 if (UDRS->fd_ref != 1)
3567 return -EBUSY;
3568 return do_format(drive, &inparam.f);
3569 case FDFMTEND:
3570 case FDFLUSH:
3571 LOCK_FDC(drive, 1);
3572 return invalidate_drive(inode->i_bdev);
3573
3574 case FDSETEMSGTRESH:
3575 UDP->max_errors.reporting =
3576 (unsigned short)(param & 0x0f);
3577 return 0;
3578 OUT(FDGETMAXERRS, &UDP->max_errors);
3579 IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
3580
3581 case FDGETDRVTYP:
3582 outparam = drive_name(type, drive);
3583 SUPBOUND(size, strlen(outparam) + 1);
3584 break;
3585
3586 IN(FDSETDRVPRM, UDP, dp);
3587 OUT(FDGETDRVPRM, UDP);
3588
3589 case FDPOLLDRVSTAT:
3590 LOCK_FDC(drive, 1);
3591 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3592 process_fd_request();
3593 /* fall through */
3594 OUT(FDGETDRVSTAT, UDRS);
3595
3596 case FDRESET:
3597 return user_reset_fdc(drive, (int)param, 1);
3598
3599 OUT(FDGETFDCSTAT, UFDCS);
3600
3601 case FDWERRORCLR:
3602 CLEARSTRUCT(UDRWE);
3603 return 0;
3604 OUT(FDWERRORGET, UDRWE);
3605
3606 case FDRAWCMD:
3607 if (type)
3608 return -EINVAL;
3609 LOCK_FDC(drive, 1);
3610 set_floppy(drive);
3611 CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
3612 process_fd_request();
3613 return i;
3614
3615 case FDTWADDLE:
3616 LOCK_FDC(drive, 1);
3617 twaddle();
3618 process_fd_request();
3619 return 0;
3620
3621 default:
3622 return -EINVAL;
3623 }
3624
3625 if (_IOC_DIR(cmd) & _IOC_READ)
3626 return fd_copyout((void __user *)param, outparam, size);
3627 else
3628 return 0;
3629#undef OUT
3630#undef IN
3631}
3632
3633static void __init config_types(void)
3634{
3635 int first = 1;
3636 int drive;
3637
3638 /* read drive info out of physical CMOS */
3639 drive = 0;
3640 if (!UDP->cmos)
3641 UDP->cmos = FLOPPY0_TYPE;
3642 drive = 1;
3643 if (!UDP->cmos && FLOPPY1_TYPE)
3644 UDP->cmos = FLOPPY1_TYPE;
3645
Jesper Juhl06f748c2007-10-16 23:30:57 -07003646 /* FIXME: additional physical CMOS drive detection should go here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
3648 for (drive = 0; drive < N_DRIVE; drive++) {
3649 unsigned int type = UDP->cmos;
3650 struct floppy_drive_params *params;
3651 const char *name = NULL;
3652 static char temparea[32];
3653
Tobias Klauser945f3902006-01-08 01:05:11 -08003654 if (type < ARRAY_SIZE(default_drive_params)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 params = &default_drive_params[type].params;
3656 if (type) {
3657 name = default_drive_params[type].name;
3658 allowed_drive_mask |= 1 << drive;
3659 } else
3660 allowed_drive_mask &= ~(1 << drive);
3661 } else {
3662 params = &default_drive_params[0].params;
3663 sprintf(temparea, "unknown type %d (usb?)", type);
3664 name = temparea;
3665 }
3666 if (name) {
3667 const char *prepend = ",";
3668 if (first) {
3669 prepend = KERN_INFO "Floppy drive(s):";
3670 first = 0;
3671 }
3672 printk("%s fd%d is %s", prepend, drive, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 }
3674 *UDP = *params;
3675 }
3676 if (!first)
3677 printk("\n");
3678}
3679
3680static int floppy_release(struct inode *inode, struct file *filp)
3681{
3682 int drive = (long)inode->i_bdev->bd_disk->private_data;
3683
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003684 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 if (UDRS->fd_ref < 0)
3686 UDRS->fd_ref = 0;
3687 else if (!UDRS->fd_ref--) {
3688 DPRINT("floppy_release with fd_ref == 0");
3689 UDRS->fd_ref = 0;
3690 }
3691 if (!UDRS->fd_ref)
3692 opened_bdev[drive] = NULL;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003693 mutex_unlock(&open_lock);
Ingo Molnar3e541a42006-07-03 00:24:23 -07003694
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695 return 0;
3696}
3697
3698/*
3699 * floppy_open check for aliasing (/dev/fd0 can be the same as
3700 * /dev/PS0 etc), and disallows simultaneous access to the same
3701 * drive with different device numbers.
3702 */
3703static int floppy_open(struct inode *inode, struct file *filp)
3704{
3705 int drive = (long)inode->i_bdev->bd_disk->private_data;
3706 int old_dev;
3707 int try;
3708 int res = -EBUSY;
3709 char *tmp;
3710
3711 filp->private_data = (void *)0;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003712 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003713 old_dev = UDRS->fd_device;
3714 if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
3715 goto out2;
3716
3717 if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
3718 USETF(FD_DISK_CHANGED);
3719 USETF(FD_VERIFY);
3720 }
3721
3722 if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
3723 goto out2;
3724
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 if (filp->f_flags & O_EXCL)
3726 UDRS->fd_ref = -1;
3727 else
3728 UDRS->fd_ref++;
3729
3730 opened_bdev[drive] = inode->i_bdev;
3731
3732 res = -ENXIO;
3733
3734 if (!floppy_track_buffer) {
3735 /* if opening an ED drive, reserve a big buffer,
3736 * else reserve a small one */
3737 if ((UDP->cmos == 6) || (UDP->cmos == 5))
3738 try = 64; /* Only 48 actually useful */
3739 else
3740 try = 32; /* Only 24 actually useful */
3741
3742 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3743 if (!tmp && !floppy_track_buffer) {
3744 try >>= 1; /* buffer only one side */
3745 INFBOUND(try, 16);
3746 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3747 }
3748 if (!tmp && !floppy_track_buffer) {
3749 fallback_on_nodma_alloc(&tmp, 2048 * try);
3750 }
3751 if (!tmp && !floppy_track_buffer) {
3752 DPRINT("Unable to allocate DMA memory\n");
3753 goto out;
3754 }
3755 if (floppy_track_buffer) {
3756 if (tmp)
3757 fd_dma_mem_free((unsigned long)tmp, try * 1024);
3758 } else {
3759 buffer_min = buffer_max = -1;
3760 floppy_track_buffer = tmp;
3761 max_buffer_sectors = try;
3762 }
3763 }
3764
3765 UDRS->fd_device = iminor(inode);
3766 set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
3767 if (old_dev != -1 && old_dev != iminor(inode)) {
3768 if (buffer_drive == drive)
3769 buffer_track = -1;
3770 }
3771
3772 /* Allow ioctls if we have write-permissions even if read-only open.
3773 * Needed so that programs such as fdrawcmd still can work on write
3774 * protected disks */
Christoph Hellwig8c744fb2005-11-08 21:35:04 -08003775 if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776 filp->private_data = (void *)8;
3777
3778 if (UFDCS->rawcmd == 1)
3779 UFDCS->rawcmd = 2;
3780
3781 if (!(filp->f_flags & O_NDELAY)) {
3782 if (filp->f_mode & 3) {
3783 UDRS->last_checked = 0;
3784 check_disk_change(inode->i_bdev);
3785 if (UTESTF(FD_DISK_CHANGED))
3786 goto out;
3787 }
3788 res = -EROFS;
3789 if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
3790 goto out;
3791 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003792 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 return 0;
3794out:
3795 if (UDRS->fd_ref < 0)
3796 UDRS->fd_ref = 0;
3797 else
3798 UDRS->fd_ref--;
3799 if (!UDRS->fd_ref)
3800 opened_bdev[drive] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801out2:
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003802 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 return res;
3804}
3805
3806/*
3807 * Check if the disk has been changed or if a change has been faked.
3808 */
3809static int check_floppy_change(struct gendisk *disk)
3810{
3811 int drive = (long)disk->private_data;
3812
3813 if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
3814 return 1;
3815
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08003816 if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 lock_fdc(drive, 0);
3818 poll_drive(0, 0);
3819 process_fd_request();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 }
3821
3822 if (UTESTF(FD_DISK_CHANGED) ||
3823 UTESTF(FD_VERIFY) ||
3824 test_bit(drive, &fake_change) ||
3825 (!ITYPE(UDRS->fd_device) && !current_type[drive]))
3826 return 1;
3827 return 0;
3828}
3829
3830/*
3831 * This implements "read block 0" for floppy_revalidate().
3832 * Needed for format autodetection, checking whether there is
3833 * a disk in the drive, and whether that disk is writable.
3834 */
3835
NeilBrown6712ecf2007-09-27 12:47:43 +02003836static void floppy_rb0_complete(struct bio *bio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837 int err)
3838{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839 complete((struct completion *)bio->bi_private);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840}
3841
3842static int __floppy_read_block_0(struct block_device *bdev)
3843{
3844 struct bio bio;
3845 struct bio_vec bio_vec;
3846 struct completion complete;
3847 struct page *page;
3848 size_t size;
3849
3850 page = alloc_page(GFP_NOIO);
3851 if (!page) {
3852 process_fd_request();
3853 return -ENOMEM;
3854 }
3855
3856 size = bdev->bd_block_size;
3857 if (!size)
3858 size = 1024;
3859
3860 bio_init(&bio);
3861 bio.bi_io_vec = &bio_vec;
3862 bio_vec.bv_page = page;
3863 bio_vec.bv_len = size;
3864 bio_vec.bv_offset = 0;
3865 bio.bi_vcnt = 1;
3866 bio.bi_idx = 0;
3867 bio.bi_size = size;
3868 bio.bi_bdev = bdev;
3869 bio.bi_sector = 0;
3870 init_completion(&complete);
3871 bio.bi_private = &complete;
3872 bio.bi_end_io = floppy_rb0_complete;
3873
3874 submit_bio(READ, &bio);
3875 generic_unplug_device(bdev_get_queue(bdev));
3876 process_fd_request();
3877 wait_for_completion(&complete);
3878
3879 __free_page(page);
3880
3881 return 0;
3882}
3883
3884/* revalidate the floppy disk, i.e. trigger format autodetection by reading
3885 * the bootblock (block 0). "Autodetection" is also needed to check whether
3886 * there is a disk in the drive at all... Thus we also do it for fixed
3887 * geometry formats */
3888static int floppy_revalidate(struct gendisk *disk)
3889{
3890 int drive = (long)disk->private_data;
3891#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
3892 int cf;
3893 int res = 0;
3894
3895 if (UTESTF(FD_DISK_CHANGED) ||
3896 UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) {
3897 if (usage_count == 0) {
3898 printk("VFS: revalidate called on non-open device.\n");
3899 return -EFAULT;
3900 }
3901 lock_fdc(drive, 0);
3902 cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
3903 if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
3904 process_fd_request(); /*already done by another thread */
3905 return 0;
3906 }
3907 UDRS->maxblock = 0;
3908 UDRS->maxtrack = 0;
3909 if (buffer_drive == drive)
3910 buffer_track = -1;
3911 clear_bit(drive, &fake_change);
3912 UCLEARF(FD_DISK_CHANGED);
3913 if (cf)
3914 UDRS->generation++;
3915 if (NO_GEOM) {
3916 /* auto-sensing */
3917 res = __floppy_read_block_0(opened_bdev[drive]);
3918 } else {
3919 if (cf)
3920 poll_drive(0, FD_RAW_NEED_DISK);
3921 process_fd_request();
3922 }
3923 }
3924 set_capacity(disk, floppy_sizes[UDRS->fd_device]);
3925 return res;
3926}
3927
3928static struct block_device_operations floppy_fops = {
Jesper Juhl06f748c2007-10-16 23:30:57 -07003929 .owner = THIS_MODULE,
3930 .open = floppy_open,
3931 .release = floppy_release,
3932 .ioctl = fd_ioctl,
3933 .getgeo = fd_getgeo,
3934 .media_changed = check_floppy_change,
3935 .revalidate_disk = floppy_revalidate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938/*
3939 * Floppy Driver initialization
3940 * =============================
3941 */
3942
3943/* Determine the floppy disk controller type */
3944/* This routine was written by David C. Niemi */
3945static char __init get_fdc_version(void)
3946{
3947 int r;
3948
3949 output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */
3950 if (FDCS->reset)
3951 return FDC_NONE;
3952 if ((r = result()) <= 0x00)
3953 return FDC_NONE; /* No FDC present ??? */
3954 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3955 printk(KERN_INFO "FDC %d is an 8272A\n", fdc);
3956 return FDC_8272A; /* 8272a/765 don't know DUMPREGS */
3957 }
3958 if (r != 10) {
3959 printk
3960 ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
3961 fdc, r);
3962 return FDC_UNKNOWN;
3963 }
3964
3965 if (!fdc_configure()) {
3966 printk(KERN_INFO "FDC %d is an 82072\n", fdc);
3967 return FDC_82072; /* 82072 doesn't know CONFIGURE */
3968 }
3969
3970 output_byte(FD_PERPENDICULAR);
3971 if (need_more_output() == MORE_OUTPUT) {
3972 output_byte(0);
3973 } else {
3974 printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
3975 return FDC_82072A; /* 82072A as found on Sparcs. */
3976 }
3977
3978 output_byte(FD_UNLOCK);
3979 r = result();
3980 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3981 printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc);
3982 return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know
3983 * LOCK/UNLOCK */
3984 }
3985 if ((r != 1) || (reply_buffer[0] != 0x00)) {
3986 printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
3987 fdc, r);
3988 return FDC_UNKNOWN;
3989 }
3990 output_byte(FD_PARTID);
3991 r = result();
3992 if (r != 1) {
3993 printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
3994 fdc, r);
3995 return FDC_UNKNOWN;
3996 }
3997 if (reply_buffer[0] == 0x80) {
3998 printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc);
3999 return FDC_82077; /* Revised 82077AA passes all the tests */
4000 }
4001 switch (reply_buffer[0] >> 5) {
4002 case 0x0:
4003 /* Either a 82078-1 or a 82078SL running at 5Volt */
4004 printk(KERN_INFO "FDC %d is an 82078.\n", fdc);
4005 return FDC_82078;
4006 case 0x1:
4007 printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc);
4008 return FDC_82078;
4009 case 0x2:
4010 printk(KERN_INFO "FDC %d is a S82078B\n", fdc);
4011 return FDC_S82078B;
4012 case 0x3:
4013 printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n",
4014 fdc);
4015 return FDC_87306;
4016 default:
4017 printk(KERN_INFO
4018 "FDC %d init: 82078 variant with unknown PARTID=%d.\n",
4019 fdc, reply_buffer[0] >> 5);
4020 return FDC_82078_UNKN;
4021 }
4022} /* get_fdc_version */
4023
4024/* lilo configuration */
4025
4026static void __init floppy_set_flags(int *ints, int param, int param2)
4027{
4028 int i;
4029
4030 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4031 if (param)
4032 default_drive_params[i].params.flags |= param2;
4033 else
4034 default_drive_params[i].params.flags &= ~param2;
4035 }
4036 DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param);
4037}
4038
4039static void __init daring(int *ints, int param, int param2)
4040{
4041 int i;
4042
4043 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4044 if (param) {
4045 default_drive_params[i].params.select_delay = 0;
4046 default_drive_params[i].params.flags |=
4047 FD_SILENT_DCL_CLEAR;
4048 } else {
4049 default_drive_params[i].params.select_delay =
4050 2 * HZ / 100;
4051 default_drive_params[i].params.flags &=
4052 ~FD_SILENT_DCL_CLEAR;
4053 }
4054 }
4055 DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken");
4056}
4057
4058static void __init set_cmos(int *ints, int dummy, int dummy2)
4059{
4060 int current_drive = 0;
4061
4062 if (ints[0] != 2) {
4063 DPRINT("wrong number of parameters for CMOS\n");
4064 return;
4065 }
4066 current_drive = ints[1];
4067 if (current_drive < 0 || current_drive >= 8) {
4068 DPRINT("bad drive for set_cmos\n");
4069 return;
4070 }
4071#if N_FDC > 1
4072 if (current_drive >= 4 && !FDC2)
4073 FDC2 = 0x370;
4074#endif
4075 DP->cmos = ints[2];
4076 DPRINT("setting CMOS code to %d\n", ints[2]);
4077}
4078
4079static struct param_table {
4080 const char *name;
4081 void (*fn) (int *ints, int param, int param2);
4082 int *var;
4083 int def_param;
4084 int param2;
4085} config_params[] __initdata = {
4086 {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4087 {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4088 {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0},
4089 {"irq", NULL, &FLOPPY_IRQ, 6, 0},
4090 {"dma", NULL, &FLOPPY_DMA, 2, 0},
4091 {"daring", daring, NULL, 1, 0},
4092#if N_FDC > 1
4093 {"two_fdc", NULL, &FDC2, 0x370, 0},
4094 {"one_fdc", NULL, &FDC2, 0, 0},
4095#endif
4096 {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL},
4097 {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL},
4098 {"messages", floppy_set_flags, NULL, 1, FTD_MSG},
4099 {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR},
4100 {"debug", floppy_set_flags, NULL, 1, FD_DEBUG},
4101 {"nodma", NULL, &can_use_virtual_dma, 1, 0},
4102 {"omnibook", NULL, &can_use_virtual_dma, 1, 0},
4103 {"yesdma", NULL, &can_use_virtual_dma, 0, 0},
4104 {"fifo_depth", NULL, &fifo_depth, 0xa, 0},
4105 {"nofifo", NULL, &no_fifo, 0x20, 0},
4106 {"usefifo", NULL, &no_fifo, 0, 0},
4107 {"cmos", set_cmos, NULL, 0, 0},
4108 {"slow", NULL, &slow_floppy, 1, 0},
4109 {"unexpected_interrupts", NULL, &print_unex, 1, 0},
4110 {"no_unexpected_interrupts", NULL, &print_unex, 0, 0},
4111 {"L40SX", NULL, &print_unex, 0, 0}
4112
4113 EXTRA_FLOPPY_PARAMS
4114};
4115
4116static int __init floppy_setup(char *str)
4117{
4118 int i;
4119 int param;
4120 int ints[11];
4121
4122 str = get_options(str, ARRAY_SIZE(ints), ints);
4123 if (str) {
4124 for (i = 0; i < ARRAY_SIZE(config_params); i++) {
4125 if (strcmp(str, config_params[i].name) == 0) {
4126 if (ints[0])
4127 param = ints[1];
4128 else
4129 param = config_params[i].def_param;
4130 if (config_params[i].fn)
4131 config_params[i].
4132 fn(ints, param,
4133 config_params[i].param2);
4134 if (config_params[i].var) {
4135 DPRINT("%s=%d\n", str, param);
4136 *config_params[i].var = param;
4137 }
4138 return 1;
4139 }
4140 }
4141 }
4142 if (str) {
4143 DPRINT("unknown floppy option [%s]\n", str);
4144
4145 DPRINT("allowed options are:");
4146 for (i = 0; i < ARRAY_SIZE(config_params); i++)
4147 printk(" %s", config_params[i].name);
4148 printk("\n");
4149 } else
4150 DPRINT("botched floppy option\n");
4151 DPRINT("Read Documentation/floppy.txt\n");
4152 return 0;
4153}
4154
4155static int have_no_fdc = -ENODEV;
4156
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004157static ssize_t floppy_cmos_show(struct device *dev,
4158 struct device_attribute *attr, char *buf)
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004159{
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004160 struct platform_device *p;
4161 int drive;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004162
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004163 p = container_of(dev, struct platform_device,dev);
4164 drive = p->id;
4165 return sprintf(buf, "%X\n", UDP->cmos);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004166}
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004167DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
4168
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169static void floppy_device_release(struct device *dev)
4170{
4171 complete(&device_release);
4172}
4173
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004174static struct platform_device floppy_device[N_DRIVE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175
4176static struct kobject *floppy_find(dev_t dev, int *part, void *data)
4177{
4178 int drive = (*part & 3) | ((*part & 0x80) >> 5);
4179 if (drive >= N_DRIVE ||
4180 !(allowed_drive_mask & (1 << drive)) ||
4181 fdc_state[FDC(drive)].version == FDC_NONE)
4182 return NULL;
Tobias Klauser945f3902006-01-08 01:05:11 -08004183 if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 return NULL;
4185 *part = 0;
4186 return get_disk(disks[drive]);
4187}
4188
4189static int __init floppy_init(void)
4190{
4191 int i, unit, drive;
4192 int err, dr;
4193
Olaf Heringef16b512006-08-31 21:27:41 -07004194#if defined(CONFIG_PPC_MERGE)
4195 if (check_legacy_ioport(FDC1))
4196 return -ENODEV;
4197#endif
4198
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 raw_cmd = NULL;
4200
4201 for (dr = 0; dr < N_DRIVE; dr++) {
4202 disks[dr] = alloc_disk(1);
4203 if (!disks[dr]) {
4204 err = -ENOMEM;
4205 goto out_put_disk;
4206 }
4207
4208 disks[dr]->major = FLOPPY_MAJOR;
4209 disks[dr]->first_minor = TOMINOR(dr);
4210 disks[dr]->fops = &floppy_fops;
4211 sprintf(disks[dr]->disk_name, "fd%d", dr);
4212
4213 init_timer(&motor_off_timer[dr]);
4214 motor_off_timer[dr].data = dr;
4215 motor_off_timer[dr].function = motor_off_callback;
4216 }
4217
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218 err = register_blkdev(FLOPPY_MAJOR, "fd");
4219 if (err)
Greg Kroah-Hartman8ab5e4c2005-06-20 21:15:16 -07004220 goto out_put_disk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221
4222 floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
4223 if (!floppy_queue) {
4224 err = -ENOMEM;
4225 goto out_unreg_blkdev;
4226 }
4227 blk_queue_max_sectors(floppy_queue, 64);
4228
4229 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
4230 floppy_find, NULL, NULL);
4231
4232 for (i = 0; i < 256; i++)
4233 if (ITYPE(i))
4234 floppy_sizes[i] = floppy_type[ITYPE(i)].size;
4235 else
4236 floppy_sizes[i] = MAX_DISK_SIZE << 1;
4237
4238 reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
4239 config_types();
4240
4241 for (i = 0; i < N_FDC; i++) {
4242 fdc = i;
4243 CLEARSTRUCT(FDCS);
4244 FDCS->dtr = -1;
4245 FDCS->dor = 0x4;
4246#if defined(__sparc__) || defined(__mc68000__)
4247 /*sparcs/sun3x don't have a DOR reset which we can fall back on to */
4248#ifdef __mc68000__
4249 if (MACH_IS_SUN3X)
4250#endif
4251 FDCS->version = FDC_82072A;
4252#endif
4253 }
4254
4255 use_virtual_dma = can_use_virtual_dma & 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 fdc_state[0].address = FDC1;
4257 if (fdc_state[0].address == -1) {
4258 del_timer(&fd_timeout);
4259 err = -ENODEV;
4260 goto out_unreg_region;
4261 }
4262#if N_FDC > 1
4263 fdc_state[1].address = FDC2;
4264#endif
4265
4266 fdc = 0; /* reset fdc in case of unexpected interrupt */
4267 err = floppy_grab_irq_and_dma();
4268 if (err) {
4269 del_timer(&fd_timeout);
4270 err = -EBUSY;
4271 goto out_unreg_region;
4272 }
4273
4274 /* initialise drive state */
4275 for (drive = 0; drive < N_DRIVE; drive++) {
4276 CLEARSTRUCT(UDRS);
4277 CLEARSTRUCT(UDRWE);
4278 USETF(FD_DISK_NEWCHANGE);
4279 USETF(FD_DISK_CHANGED);
4280 USETF(FD_VERIFY);
4281 UDRS->fd_device = -1;
4282 floppy_track_buffer = NULL;
4283 max_buffer_sectors = 0;
4284 }
4285 /*
4286 * Small 10 msec delay to let through any interrupt that
4287 * initialization might have triggered, to not
4288 * confuse detection:
4289 */
4290 msleep(10);
4291
4292 for (i = 0; i < N_FDC; i++) {
4293 fdc = i;
4294 FDCS->driver_version = FD_DRIVER_VERSION;
4295 for (unit = 0; unit < 4; unit++)
4296 FDCS->track[unit] = 0;
4297 if (FDCS->address == -1)
4298 continue;
4299 FDCS->rawcmd = 2;
4300 if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
4301 /* free ioports reserved by floppy_grab_irq_and_dma() */
4302 release_region(FDCS->address + 2, 4);
4303 release_region(FDCS->address + 7, 1);
4304 FDCS->address = -1;
4305 FDCS->version = FDC_NONE;
4306 continue;
4307 }
4308 /* Try to determine the floppy controller type */
4309 FDCS->version = get_fdc_version();
4310 if (FDCS->version == FDC_NONE) {
4311 /* free ioports reserved by floppy_grab_irq_and_dma() */
4312 release_region(FDCS->address + 2, 4);
4313 release_region(FDCS->address + 7, 1);
4314 FDCS->address = -1;
4315 continue;
4316 }
4317 if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
4318 can_use_virtual_dma = 0;
4319
4320 have_no_fdc = 0;
4321 /* Not all FDCs seem to be able to handle the version command
4322 * properly, so force a reset for the standard FDC clones,
4323 * to avoid interrupt garbage.
4324 */
4325 user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
4326 }
4327 fdc = 0;
4328 del_timer(&fd_timeout);
4329 current_drive = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 initialising = 0;
4331 if (have_no_fdc) {
4332 DPRINT("no floppy controllers found\n");
4333 err = have_no_fdc;
4334 goto out_flush_work;
4335 }
4336
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337 for (drive = 0; drive < N_DRIVE; drive++) {
4338 if (!(allowed_drive_mask & (1 << drive)))
4339 continue;
4340 if (fdc_state[FDC(drive)].version == FDC_NONE)
4341 continue;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004342
4343 floppy_device[drive].name = floppy_device_name;
4344 floppy_device[drive].id = drive;
4345 floppy_device[drive].dev.release = floppy_device_release;
4346
4347 err = platform_device_register(&floppy_device[drive]);
4348 if (err)
4349 goto out_flush_work;
4350
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004351 err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
4352 if (err)
4353 goto out_unreg_platform_dev;
4354
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355 /* to be cleaned up... */
4356 disks[drive]->private_data = (void *)(long)drive;
4357 disks[drive]->queue = floppy_queue;
4358 disks[drive]->flags |= GENHD_FL_REMOVABLE;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004359 disks[drive]->driverfs_dev = &floppy_device[drive].dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360 add_disk(disks[drive]);
4361 }
4362
4363 return 0;
4364
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004365out_unreg_platform_dev:
4366 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367out_flush_work:
4368 flush_scheduled_work();
4369 if (usage_count)
4370 floppy_release_irq_and_dma();
4371out_unreg_region:
4372 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4373 blk_cleanup_queue(floppy_queue);
4374out_unreg_blkdev:
4375 unregister_blkdev(FLOPPY_MAJOR, "fd");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376out_put_disk:
4377 while (dr--) {
4378 del_timer(&motor_off_timer[dr]);
4379 put_disk(disks[dr]);
4380 }
4381 return err;
4382}
4383
4384static DEFINE_SPINLOCK(floppy_usage_lock);
4385
4386static int floppy_grab_irq_and_dma(void)
4387{
4388 unsigned long flags;
4389
4390 spin_lock_irqsave(&floppy_usage_lock, flags);
4391 if (usage_count++) {
4392 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4393 return 0;
4394 }
4395 spin_unlock_irqrestore(&floppy_usage_lock, flags);
Ingo Molnar6dc659d2006-03-26 01:36:54 -08004396
4397 /*
4398 * We might have scheduled a free_irq(), wait it to
4399 * drain first:
4400 */
4401 flush_scheduled_work();
4402
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403 if (fd_request_irq()) {
4404 DPRINT("Unable to grab IRQ%d for the floppy driver\n",
4405 FLOPPY_IRQ);
4406 spin_lock_irqsave(&floppy_usage_lock, flags);
4407 usage_count--;
4408 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4409 return -1;
4410 }
4411 if (fd_request_dma()) {
4412 DPRINT("Unable to grab DMA%d for the floppy driver\n",
4413 FLOPPY_DMA);
Jan Beulich2e9c47c2007-10-16 23:27:32 -07004414 if (can_use_virtual_dma & 2)
4415 use_virtual_dma = can_use_virtual_dma = 1;
4416 if (!(can_use_virtual_dma & 1)) {
4417 fd_free_irq();
4418 spin_lock_irqsave(&floppy_usage_lock, flags);
4419 usage_count--;
4420 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4421 return -1;
4422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 }
4424
4425 for (fdc = 0; fdc < N_FDC; fdc++) {
4426 if (FDCS->address != -1) {
4427 if (!request_region(FDCS->address + 2, 4, "floppy")) {
4428 DPRINT("Floppy io-port 0x%04lx in use\n",
4429 FDCS->address + 2);
4430 goto cleanup1;
4431 }
4432 if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
4433 DPRINT("Floppy io-port 0x%04lx in use\n",
4434 FDCS->address + 7);
4435 goto cleanup2;
4436 }
4437 /* address + 6 is reserved, and may be taken by IDE.
4438 * Unfortunately, Adaptec doesn't know this :-(, */
4439 }
4440 }
4441 for (fdc = 0; fdc < N_FDC; fdc++) {
4442 if (FDCS->address != -1) {
4443 reset_fdc_info(1);
4444 fd_outb(FDCS->dor, FD_DOR);
4445 }
4446 }
4447 fdc = 0;
4448 set_dor(0, ~0, 8); /* avoid immediate interrupt */
4449
4450 for (fdc = 0; fdc < N_FDC; fdc++)
4451 if (FDCS->address != -1)
4452 fd_outb(FDCS->dor, FD_DOR);
4453 /*
Jesper Juhl06f748c2007-10-16 23:30:57 -07004454 * The driver will try and free resources and relies on us
4455 * to know if they were allocated or not.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 */
4457 fdc = 0;
4458 irqdma_allocated = 1;
4459 return 0;
4460cleanup2:
4461 release_region(FDCS->address + 2, 4);
4462cleanup1:
4463 fd_free_irq();
4464 fd_free_dma();
4465 while (--fdc >= 0) {
4466 release_region(FDCS->address + 2, 4);
4467 release_region(FDCS->address + 7, 1);
4468 }
4469 spin_lock_irqsave(&floppy_usage_lock, flags);
4470 usage_count--;
4471 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4472 return -1;
4473}
4474
4475static void floppy_release_irq_and_dma(void)
4476{
4477 int old_fdc;
4478#ifdef FLOPPY_SANITY_CHECK
4479#ifndef __sparc__
4480 int drive;
4481#endif
4482#endif
4483 long tmpsize;
4484 unsigned long tmpaddr;
4485 unsigned long flags;
4486
4487 spin_lock_irqsave(&floppy_usage_lock, flags);
4488 if (--usage_count) {
4489 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4490 return;
4491 }
4492 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4493 if (irqdma_allocated) {
4494 fd_disable_dma();
4495 fd_free_dma();
Ingo Molnar3e541a42006-07-03 00:24:23 -07004496 fd_free_irq();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497 irqdma_allocated = 0;
4498 }
4499 set_dor(0, ~0, 8);
4500#if N_FDC > 1
4501 set_dor(1, ~8, 0);
4502#endif
4503 floppy_enable_hlt();
4504
4505 if (floppy_track_buffer && max_buffer_sectors) {
4506 tmpsize = max_buffer_sectors * 1024;
4507 tmpaddr = (unsigned long)floppy_track_buffer;
4508 floppy_track_buffer = NULL;
4509 max_buffer_sectors = 0;
4510 buffer_min = buffer_max = -1;
4511 fd_dma_mem_free(tmpaddr, tmpsize);
4512 }
4513#ifdef FLOPPY_SANITY_CHECK
4514#ifndef __sparc__
4515 for (drive = 0; drive < N_FDC * 4; drive++)
4516 if (timer_pending(motor_off_timer + drive))
4517 printk("motor off timer %d still active\n", drive);
4518#endif
4519
4520 if (timer_pending(&fd_timeout))
4521 printk("floppy timer still active:%s\n", timeout_message);
4522 if (timer_pending(&fd_timer))
4523 printk("auxiliary floppy timer still active\n");
David Howells365970a2006-11-22 14:54:49 +00004524 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525 printk("work still pending\n");
4526#endif
4527 old_fdc = fdc;
4528 for (fdc = 0; fdc < N_FDC; fdc++)
4529 if (FDCS->address != -1) {
4530 release_region(FDCS->address + 2, 4);
4531 release_region(FDCS->address + 7, 1);
4532 }
4533 fdc = old_fdc;
4534}
4535
4536#ifdef MODULE
4537
4538static char *floppy;
4539
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540static void __init parse_floppy_cfg_string(char *cfg)
4541{
4542 char *ptr;
4543
4544 while (*cfg) {
4545 for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ;
4546 if (*cfg) {
4547 *cfg = '\0';
4548 cfg++;
4549 }
4550 if (*ptr)
4551 floppy_setup(ptr);
4552 }
4553}
4554
Sam Ravnborg1efa6462006-03-25 03:07:13 -08004555int __init init_module(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556{
4557 if (floppy)
4558 parse_floppy_cfg_string(floppy);
4559 return floppy_init();
4560}
4561
4562void cleanup_module(void)
4563{
4564 int drive;
4565
4566 init_completion(&device_release);
4567 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4568 unregister_blkdev(FLOPPY_MAJOR, "fd");
4569
4570 for (drive = 0; drive < N_DRIVE; drive++) {
4571 del_timer_sync(&motor_off_timer[drive]);
4572
4573 if ((allowed_drive_mask & (1 << drive)) &&
4574 fdc_state[FDC(drive)].version != FDC_NONE) {
4575 del_gendisk(disks[drive]);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004576 device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
4577 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004578 }
4579 put_disk(disks[drive]);
4580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581
4582 del_timer_sync(&fd_timeout);
4583 del_timer_sync(&fd_timer);
4584 blk_cleanup_queue(floppy_queue);
4585
4586 if (usage_count)
4587 floppy_release_irq_and_dma();
4588
4589 /* eject disk, if any */
4590 fd_eject(0);
4591
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592 wait_for_completion(&device_release);
4593}
4594
4595module_param(floppy, charp, 0);
4596module_param(FLOPPY_IRQ, int, 0);
4597module_param(FLOPPY_DMA, int, 0);
4598MODULE_AUTHOR("Alain L. Knaff");
4599MODULE_SUPPORTED_DEVICE("fd");
4600MODULE_LICENSE("GPL");
4601
4602#else
4603
4604__setup("floppy=", floppy_setup);
4605module_init(floppy_init)
4606#endif
4607
4608MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);