blob: 395f8ea7981c54f2fc5b6dfec3cf99acfd83e1ff [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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
221static unsigned short virtual_dma_port = 0x3f0;
David Howells7d12e782006-10-05 14:55:46 +0100222irqreturn_t floppy_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223static int set_dor(int fdc, char mask, char data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
225#define K_64 0x10000 /* 64KB */
226
227/* the following is the mask of allowed drives. By default units 2 and
228 * 3 of both floppy controllers are disabled, because switching on the
229 * motor of these drives causes system hangs on some PCI computers. drive
230 * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
231 * a drive is allowed.
232 *
233 * NOTE: This must come before we include the arch floppy header because
234 * some ports reference this variable from there. -DaveM
235 */
236
237static int allowed_drive_mask = 0x33;
238
239#include <asm/floppy.h>
240
241static int irqdma_allocated;
242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243#define DEVICE_NAME "floppy"
244
245#include <linux/blkdev.h>
246#include <linux/blkpg.h>
247#include <linux/cdrom.h> /* for the compatibility eject ioctl */
248#include <linux/completion.h>
249
250static struct request *current_req;
251static struct request_queue *floppy_queue;
Jens Axboe165125e2007-07-24 09:28:11 +0200252static void do_fd_request(struct request_queue * q);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
254#ifndef fd_get_dma_residue
255#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
256#endif
257
258/* Dma Memory related stuff */
259
260#ifndef fd_dma_mem_free
261#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
262#endif
263
264#ifndef fd_dma_mem_alloc
265#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
266#endif
267
268static inline void fallback_on_nodma_alloc(char **addr, size_t l)
269{
270#ifdef FLOPPY_CAN_FALLBACK_ON_NODMA
271 if (*addr)
272 return; /* we have the memory */
273 if (can_use_virtual_dma != 2)
274 return; /* no fallback allowed */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700275 printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 *addr = (char *)nodma_mem_alloc(l);
277#else
278 return;
279#endif
280}
281
282/* End dma memory related stuff */
283
284static unsigned long fake_change;
285static int initialising = 1;
286
287#define ITYPE(x) (((x)>>2) & 0x1f)
288#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
289#define UNIT(x) ((x) & 0x03) /* drive on fdc */
290#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700291 /* reverse mapping from unit and fdc to drive */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293#define DP (&drive_params[current_drive])
294#define DRS (&drive_state[current_drive])
295#define DRWE (&write_errors[current_drive])
296#define FDCS (&fdc_state[fdc])
Ralf Baechle7b8f8502007-02-20 13:57:45 -0800297#define CLEARF(x) clear_bit(x##_BIT, &DRS->flags)
298#define SETF(x) set_bit(x##_BIT, &DRS->flags)
299#define TESTF(x) test_bit(x##_BIT, &DRS->flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301#define UDP (&drive_params[drive])
302#define UDRS (&drive_state[drive])
303#define UDRWE (&write_errors[drive])
304#define UFDCS (&fdc_state[FDC(drive)])
Ralf Baechle7b8f8502007-02-20 13:57:45 -0800305#define UCLEARF(x) clear_bit(x##_BIT, &UDRS->flags)
306#define USETF(x) set_bit(x##_BIT, &UDRS->flags)
307#define UTESTF(x) test_bit(x##_BIT, &UDRS->flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
309#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
310
311#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
312#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
313
314#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
315
316/* read/write */
317#define COMMAND raw_cmd->cmd[0]
318#define DR_SELECT raw_cmd->cmd[1]
319#define TRACK raw_cmd->cmd[2]
320#define HEAD raw_cmd->cmd[3]
321#define SECTOR raw_cmd->cmd[4]
322#define SIZECODE raw_cmd->cmd[5]
323#define SECT_PER_TRACK raw_cmd->cmd[6]
324#define GAP raw_cmd->cmd[7]
325#define SIZECODE2 raw_cmd->cmd[8]
326#define NR_RW 9
327
328/* format */
329#define F_SIZECODE raw_cmd->cmd[2]
330#define F_SECT_PER_TRACK raw_cmd->cmd[3]
331#define F_GAP raw_cmd->cmd[4]
332#define F_FILL raw_cmd->cmd[5]
333#define NR_F 6
334
335/*
336 * Maximum disk size (in kilobytes). This default is used whenever the
337 * current disk size is unknown.
338 * [Now it is rather a minimum]
339 */
340#define MAX_DISK_SIZE 4 /* 3984 */
341
342/*
343 * globals used by 'result()'
344 */
345#define MAX_REPLIES 16
346static unsigned char reply_buffer[MAX_REPLIES];
347static int inr; /* size of reply buffer, when called from interrupt */
348#define ST0 (reply_buffer[0])
349#define ST1 (reply_buffer[1])
350#define ST2 (reply_buffer[2])
351#define ST3 (reply_buffer[0]) /* result of GETSTATUS */
352#define R_TRACK (reply_buffer[3])
353#define R_HEAD (reply_buffer[4])
354#define R_SECTOR (reply_buffer[5])
355#define R_SIZECODE (reply_buffer[6])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356#define SEL_DLY (2*HZ/100)
357
358/*
359 * this struct defines the different floppy drive types.
360 */
361static struct {
362 struct floppy_drive_params params;
363 const char *name; /* name printed while booting */
364} default_drive_params[] = {
365/* NOTE: the time values in jiffies should be in msec!
366 CMOS drive type
367 | Maximum data rate supported by drive type
368 | | Head load time, msec
369 | | | Head unload time, msec (not used)
370 | | | | Step rate interval, usec
371 | | | | | Time needed for spinup time (jiffies)
372 | | | | | | Timeout for spinning down (jiffies)
373 | | | | | | | Spindown offset (where disk stops)
374 | | | | | | | | Select delay
375 | | | | | | | | | RPS
376 | | | | | | | | | | Max number of tracks
377 | | | | | | | | | | | Interrupt timeout
378 | | | | | | | | | | | | Max nonintlv. sectors
379 | | | | | | | | | | | | | -Max Errors- flags */
380{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0,
381 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" },
382
383{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0,
384 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/
385
386{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0,
387 0, { 2, 5, 6,23,10,20,12, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/
388
389{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
390 0, { 4,22,21,30, 3, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/
391
392{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0,
393 0, { 7, 4,25,22,31,21,29,11}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/
394
395{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
396 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/
397
398{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0,
399 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/
400/* | --autodetected formats--- | | |
401 * read_track | | Name printed when booting
402 * | Native format
403 * Frequency of disk change checks */
404};
405
406static struct floppy_drive_params drive_params[N_DRIVE];
407static struct floppy_drive_struct drive_state[N_DRIVE];
408static struct floppy_write_errors write_errors[N_DRIVE];
409static struct timer_list motor_off_timer[N_DRIVE];
410static struct gendisk *disks[N_DRIVE];
411static struct block_device *opened_bdev[N_DRIVE];
Jes Sorensenb1c82b52006-03-23 03:00:26 -0800412static DEFINE_MUTEX(open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
414
415/*
416 * This struct defines the different floppy types.
417 *
418 * Bit 0 of 'stretch' tells if the tracks need to be doubled for some
419 * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch'
420 * tells if the disk is in Commodore 1581 format, which means side 0 sectors
421 * are located on side 1 of the disk but with a side 0 ID, and vice-versa.
422 * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the
423 * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
424 * side 0 is on physical side 0 (but with the misnamed sector IDs).
425 * 'stretch' should probably be renamed to something more general, like
426 * 'options'. Other parameters should be self-explanatory (see also
427 * setfdprm(8)).
428 */
429/*
430 Size
431 | Sectors per track
432 | | Head
433 | | | Tracks
434 | | | | Stretch
435 | | | | | Gap 1 size
436 | | | | | | Data rate, | 0x40 for perp
437 | | | | | | | Spec1 (stepping rate, head unload
438 | | | | | | | | /fmt gap (gap2) */
439static struct floppy_struct floppy_type[32] = {
440 { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */
441 { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */
442 { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */
443 { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */
444 { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */
445 { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */
446 { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */
447 { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */
448 { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */
449 { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */
450
451 { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */
452 { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */
453 { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */
454 { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */
455 { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */
456 { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */
457 { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */
458 { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */
459 { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */
460 { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */
461
462 { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */
463 { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */
464 { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */
465 { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */
466 { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */
467 { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */
468 { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */
469 { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */
470 { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700472
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */
474 { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */
475};
476
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477#define SECTSIZE (_FD_SECTSIZE(*floppy))
478
479/* Auto-detection: Disk type used until the next media change occurs. */
480static struct floppy_struct *current_type[N_DRIVE];
481
482/*
483 * User-provided type information. current_type points to
484 * the respective entry of this array.
485 */
486static struct floppy_struct user_params[N_DRIVE];
487
488static sector_t floppy_sizes[256];
489
Hannes Reinecke94fd0db2005-07-15 10:09:25 +0200490static char floppy_device_name[] = "floppy";
491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492/*
493 * The driver is trying to determine the correct media format
494 * while probing is set. rw_interrupt() clears it after a
495 * successful access.
496 */
497static int probing;
498
499/* Synchronization of FDC access. */
500#define FD_COMMAND_NONE -1
501#define FD_COMMAND_ERROR 2
502#define FD_COMMAND_OKAY 3
503
504static volatile int command_status = FD_COMMAND_NONE;
505static unsigned long fdc_busy;
506static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
507static DECLARE_WAIT_QUEUE_HEAD(command_done);
508
509#define NO_SIGNAL (!interruptible || !signal_pending(current))
510#define CALL(x) if ((x) == -EINTR) return -EINTR
511#define ECALL(x) if ((ret = (x))) return ret;
512#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
513#define WAIT(x) _WAIT((x),interruptible)
514#define IWAIT(x) _WAIT((x),1)
515
516/* Errors during formatting are counted here. */
517static int format_errors;
518
519/* Format request descriptor. */
520static struct format_descr format_req;
521
522/*
523 * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps
524 * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc),
525 * H is head unload time (1=16ms, 2=32ms, etc)
526 */
527
528/*
529 * Track buffer
530 * Because these are written to by the DMA controller, they must
531 * not contain a 64k byte boundary crossing, or data will be
532 * corrupted/lost.
533 */
534static char *floppy_track_buffer;
535static int max_buffer_sectors;
536
537static int *errors;
Jesper Juhl06f748c2007-10-16 23:30:57 -0700538typedef void (*done_f)(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539static struct cont_t {
Jesper Juhl06f748c2007-10-16 23:30:57 -0700540 void (*interrupt)(void); /* this is called after the interrupt of the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 * main command */
Jesper Juhl06f748c2007-10-16 23:30:57 -0700542 void (*redo)(void); /* this is called to retry the operation */
543 void (*error)(void); /* this is called to tally an error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 done_f done; /* this is called to say if the operation has
545 * succeeded/failed */
546} *cont;
547
548static void floppy_ready(void);
549static void floppy_start(void);
550static void process_fd_request(void);
551static void recalibrate_floppy(void);
552static void floppy_shutdown(unsigned long);
553
554static int floppy_grab_irq_and_dma(void);
555static void floppy_release_irq_and_dma(void);
556
557/*
558 * The "reset" variable should be tested whenever an interrupt is scheduled,
559 * after the commands have been sent. This is to ensure that the driver doesn't
560 * get wedged when the interrupt doesn't come because of a failed command.
561 * reset doesn't need to be tested before sending commands, because
562 * output_byte is automatically disabled when reset is set.
563 */
564#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
565static void reset_fdc(void);
566
567/*
568 * These are global variables, as that's the easiest way to give
569 * information to interrupts. They are the data used for the current
570 * request.
571 */
572#define NO_TRACK -1
573#define NEED_1_RECAL -2
574#define NEED_2_RECAL -3
575
576static int usage_count;
577
578/* buffer related variables */
579static int buffer_track = -1;
580static int buffer_drive = -1;
581static int buffer_min = -1;
582static int buffer_max = -1;
583
584/* fdc related variables, should end up in a struct */
585static struct floppy_fdc_state fdc_state[N_FDC];
586static int fdc; /* current fdc */
587
588static struct floppy_struct *_floppy = floppy_type;
589static unsigned char current_drive;
590static long current_count_sectors;
591static unsigned char fsector_t; /* sector in track */
592static unsigned char in_sector_offset; /* offset within physical sector,
593 * expressed in units of 512 bytes */
594
595#ifndef fd_eject
596static inline int fd_eject(int drive)
597{
598 return -EINVAL;
599}
600#endif
601
602/*
603 * Debugging
604 * =========
605 */
606#ifdef DEBUGT
607static long unsigned debugtimer;
608
609static inline void set_debugt(void)
610{
611 debugtimer = jiffies;
612}
613
614static inline void debugt(const char *message)
615{
616 if (DP->flags & DEBUGT)
617 printk("%s dtime=%lu\n", message, jiffies - debugtimer);
618}
619#else
620static inline void set_debugt(void) { }
621static inline void debugt(const char *message) { }
622#endif /* DEBUGT */
623
624typedef void (*timeout_fn) (unsigned long);
Ingo Molnar8d06afa2005-09-09 13:10:40 -0700625static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627static const char *timeout_message;
628
629#ifdef FLOPPY_SANITY_CHECK
630static void is_alive(const char *message)
631{
632 /* this routine checks whether the floppy driver is "alive" */
633 if (test_bit(0, &fdc_busy) && command_status < 2
634 && !timer_pending(&fd_timeout)) {
635 DPRINT("timeout handler died: %s\n", message);
636 }
637}
638#endif
639
640static void (*do_floppy) (void) = NULL;
641
642#ifdef FLOPPY_SANITY_CHECK
643
644#define OLOGSIZE 20
645
646static void (*lasthandler) (void);
647static unsigned long interruptjiffies;
648static unsigned long resultjiffies;
649static int resultsize;
650static unsigned long lastredo;
651
652static struct output_log {
653 unsigned char data;
654 unsigned char status;
655 unsigned long jiffies;
656} output_log[OLOGSIZE];
657
658static int output_log_pos;
659#endif
660
661#define current_reqD -1
662#define MAXTIMEOUT -2
663
664static void __reschedule_timeout(int drive, const char *message, int marg)
665{
666 if (drive == current_reqD)
667 drive = current_drive;
668 del_timer(&fd_timeout);
Eric Sesterhenn / Snakebyte4acb3e22007-05-23 13:58:15 -0700669 if (drive < 0 || drive >= N_DRIVE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 fd_timeout.expires = jiffies + 20UL * HZ;
671 drive = 0;
672 } else
673 fd_timeout.expires = jiffies + UDP->timeout;
674 add_timer(&fd_timeout);
675 if (UDP->flags & FD_DEBUG) {
676 DPRINT("reschedule timeout ");
677 printk(message, marg);
678 printk("\n");
679 }
680 timeout_message = message;
681}
682
683static void reschedule_timeout(int drive, const char *message, int marg)
684{
685 unsigned long flags;
686
687 spin_lock_irqsave(&floppy_lock, flags);
688 __reschedule_timeout(drive, message, marg);
689 spin_unlock_irqrestore(&floppy_lock, flags);
690}
691
692#define INFBOUND(a,b) (a)=max_t(int, a, b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693#define SUPBOUND(a,b) (a)=min_t(int, a, b)
694
695/*
696 * Bottom half floppy driver.
697 * ==========================
698 *
699 * This part of the file contains the code talking directly to the hardware,
700 * and also the main service loop (seek-configure-spinup-command)
701 */
702
703/*
704 * disk change.
705 * This routine is responsible for maintaining the FD_DISK_CHANGE flag,
706 * and the last_checked date.
707 *
708 * last_checked is the date of the last check which showed 'no disk change'
709 * FD_DISK_CHANGE is set under two conditions:
710 * 1. The floppy has been changed after some i/o to that floppy already
711 * took place.
712 * 2. No floppy disk is in the drive. This is done in order to ensure that
713 * requests are quickly flushed in case there is no disk in the drive. It
714 * follows that FD_DISK_CHANGE can only be cleared if there is a disk in
715 * the drive.
716 *
717 * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
718 * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
719 * each seek. If a disk is present, the disk change line should also be
720 * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
721 * change line is set, this means either that no disk is in the drive, or
722 * that it has been removed since the last seek.
723 *
724 * This means that we really have a third possibility too:
725 * The floppy has been changed after the last seek.
726 */
727
728static int disk_change(int drive)
729{
730 int fdc = FDC(drive);
Jesper Juhl06f748c2007-10-16 23:30:57 -0700731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732#ifdef FLOPPY_SANITY_CHECK
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -0800733 if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 DPRINT("WARNING disk change called early\n");
735 if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
736 (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
737 DPRINT("probing disk change on unselected drive\n");
738 DPRINT("drive=%d fdc=%d dor=%x\n", drive, FDC(drive),
739 (unsigned int)FDCS->dor);
740 }
741#endif
742
743#ifdef DCL_DEBUG
744 if (UDP->flags & FD_DEBUG) {
745 DPRINT("checking disk change line for drive %d\n", drive);
746 DPRINT("jiffies=%lu\n", jiffies);
747 DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
748 DPRINT("flags=%lx\n", UDRS->flags);
749 }
750#endif
751 if (UDP->flags & FD_BROKEN_DCL)
752 return UTESTF(FD_DISK_CHANGED);
753 if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) {
754 USETF(FD_VERIFY); /* verify write protection */
755 if (UDRS->maxblock) {
756 /* mark it changed */
757 USETF(FD_DISK_CHANGED);
758 }
759
760 /* invalidate its geometry */
761 if (UDRS->keep_data >= 0) {
762 if ((UDP->flags & FTD_MSG) &&
763 current_type[drive] != NULL)
764 DPRINT("Disk type is undefined after "
765 "disk change\n");
766 current_type[drive] = NULL;
767 floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
768 }
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return 1;
771 } else {
772 UDRS->last_checked = jiffies;
773 UCLEARF(FD_DISK_NEWCHANGE);
774 }
775 return 0;
776}
777
778static inline int is_selected(int dor, int unit)
779{
780 return ((dor & (0x10 << unit)) && (dor & 3) == unit);
781}
782
783static int set_dor(int fdc, char mask, char data)
784{
Jesper Juhlfdc1ca82007-10-16 23:30:58 -0700785 unsigned char unit;
786 unsigned char drive;
787 unsigned char newdor;
788 unsigned char olddor;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 if (FDCS->address == -1)
791 return -1;
792
793 olddor = FDCS->dor;
794 newdor = (olddor & mask) | data;
795 if (newdor != olddor) {
796 unit = olddor & 0x3;
797 if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
798 drive = REVDRIVE(fdc, unit);
799#ifdef DCL_DEBUG
800 if (UDP->flags & FD_DEBUG) {
801 DPRINT("calling disk change from set_dor\n");
802 }
803#endif
804 disk_change(drive);
805 }
806 FDCS->dor = newdor;
807 fd_outb(newdor, FD_DOR);
808
809 unit = newdor & 0x3;
810 if (!is_selected(olddor, unit) && is_selected(newdor, unit)) {
811 drive = REVDRIVE(fdc, unit);
812 UDRS->select_date = jiffies;
813 }
814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 return olddor;
816}
817
818static void twaddle(void)
819{
820 if (DP->select_delay)
821 return;
822 fd_outb(FDCS->dor & ~(0x10 << UNIT(current_drive)), FD_DOR);
823 fd_outb(FDCS->dor, FD_DOR);
824 DRS->select_date = jiffies;
825}
826
827/* reset all driver information about the current fdc. This is needed after
828 * a reset, and after a raw command. */
829static void reset_fdc_info(int mode)
830{
831 int drive;
832
833 FDCS->spec1 = FDCS->spec2 = -1;
834 FDCS->need_configure = 1;
835 FDCS->perp_mode = 1;
836 FDCS->rawcmd = 0;
837 for (drive = 0; drive < N_DRIVE; drive++)
838 if (FDC(drive) == fdc && (mode || UDRS->track != NEED_1_RECAL))
839 UDRS->track = NEED_2_RECAL;
840}
841
842/* selects the fdc and drive, and enables the fdc's input/dma. */
843static void set_fdc(int drive)
844{
845 if (drive >= 0 && drive < N_DRIVE) {
846 fdc = FDC(drive);
847 current_drive = drive;
848 }
849 if (fdc != 1 && fdc != 0) {
850 printk("bad fdc value\n");
851 return;
852 }
853 set_dor(fdc, ~0, 8);
854#if N_FDC > 1
855 set_dor(1 - fdc, ~8, 0);
856#endif
857 if (FDCS->rawcmd == 2)
858 reset_fdc_info(1);
859 if (fd_inb(FD_STATUS) != STATUS_READY)
860 FDCS->reset = 1;
861}
862
863/* locks the driver */
864static int _lock_fdc(int drive, int interruptible, int line)
865{
866 if (!usage_count) {
867 printk(KERN_ERR
868 "Trying to lock fdc while usage count=0 at line %d\n",
869 line);
870 return -1;
871 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
873 if (test_and_set_bit(0, &fdc_busy)) {
874 DECLARE_WAITQUEUE(wait, current);
875 add_wait_queue(&fdc_wait, &wait);
876
877 for (;;) {
878 set_current_state(TASK_INTERRUPTIBLE);
879
880 if (!test_and_set_bit(0, &fdc_busy))
881 break;
882
883 schedule();
884
885 if (!NO_SIGNAL) {
886 remove_wait_queue(&fdc_wait, &wait);
887 return -EINTR;
888 }
889 }
890
891 set_current_state(TASK_RUNNING);
892 remove_wait_queue(&fdc_wait, &wait);
Ingo Molnar3e541a42006-07-03 00:24:23 -0700893 flush_scheduled_work();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 }
895 command_status = FD_COMMAND_NONE;
896
897 __reschedule_timeout(drive, "lock fdc", 0);
898 set_fdc(drive);
899 return 0;
900}
901
902#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__)
903
904#define LOCK_FDC(drive,interruptible) \
905if (lock_fdc(drive,interruptible)) return -EINTR;
906
907/* unlocks the driver */
908static inline void unlock_fdc(void)
909{
910 unsigned long flags;
911
912 raw_cmd = NULL;
913 if (!test_bit(0, &fdc_busy))
914 DPRINT("FDC access conflict!\n");
915
916 if (do_floppy)
917 DPRINT("device interrupt still active at FDC release: %p!\n",
918 do_floppy);
919 command_status = FD_COMMAND_NONE;
920 spin_lock_irqsave(&floppy_lock, flags);
921 del_timer(&fd_timeout);
922 cont = NULL;
923 clear_bit(0, &fdc_busy);
924 if (elv_next_request(floppy_queue))
925 do_fd_request(floppy_queue);
926 spin_unlock_irqrestore(&floppy_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 wake_up(&fdc_wait);
928}
929
930/* switches the motor off after a given timeout */
931static void motor_off_callback(unsigned long nr)
932{
933 unsigned char mask = ~(0x10 << UNIT(nr));
934
935 set_dor(FDC(nr), mask, 0);
936}
937
938/* schedules motor off */
939static void floppy_off(unsigned int drive)
940{
941 unsigned long volatile delta;
Jesper Juhlfdc1ca82007-10-16 23:30:58 -0700942 int fdc = FDC(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
944 if (!(FDCS->dor & (0x10 << UNIT(drive))))
945 return;
946
947 del_timer(motor_off_timer + drive);
948
949 /* make spindle stop in a position which minimizes spinup time
950 * next time */
951 if (UDP->rps) {
952 delta = jiffies - UDRS->first_read_date + HZ -
953 UDP->spindown_offset;
954 delta = ((delta * UDP->rps) % HZ) / UDP->rps;
955 motor_off_timer[drive].expires =
956 jiffies + UDP->spindown - delta;
957 }
958 add_timer(motor_off_timer + drive);
959}
960
961/*
962 * cycle through all N_DRIVE floppy drives, for disk change testing.
963 * stopping at current drive. This is done before any long operation, to
964 * be sure to have up to date disk change information.
965 */
966static void scandrives(void)
967{
Jesper Juhl06f748c2007-10-16 23:30:57 -0700968 int i;
969 int drive;
970 int saved_drive;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 if (DP->select_delay)
973 return;
974
975 saved_drive = current_drive;
976 for (i = 0; i < N_DRIVE; i++) {
977 drive = (saved_drive + i + 1) % N_DRIVE;
978 if (UDRS->fd_ref == 0 || UDP->select_delay != 0)
979 continue; /* skip closed drives */
980 set_fdc(drive);
981 if (!(set_dor(fdc, ~3, UNIT(drive) | (0x10 << UNIT(drive))) &
982 (0x10 << UNIT(drive))))
983 /* switch the motor off again, if it was off to
984 * begin with */
985 set_dor(fdc, ~(0x10 << UNIT(drive)), 0);
986 }
987 set_fdc(saved_drive);
988}
989
990static void empty(void)
991{
992}
993
David Howells65f27f32006-11-22 14:55:48 +0000994static DECLARE_WORK(floppy_work, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
996static void schedule_bh(void (*handler) (void))
997{
David Howells65f27f32006-11-22 14:55:48 +0000998 PREPARE_WORK(&floppy_work, (work_func_t)handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 schedule_work(&floppy_work);
1000}
1001
Ingo Molnar8d06afa2005-09-09 13:10:40 -07001002static DEFINE_TIMER(fd_timer, NULL, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004static void cancel_activity(void)
1005{
1006 unsigned long flags;
1007
1008 spin_lock_irqsave(&floppy_lock, flags);
1009 do_floppy = NULL;
David Howells65f27f32006-11-22 14:55:48 +00001010 PREPARE_WORK(&floppy_work, (work_func_t)empty);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 del_timer(&fd_timer);
1012 spin_unlock_irqrestore(&floppy_lock, flags);
1013}
1014
1015/* this function makes sure that the disk stays in the drive during the
1016 * transfer */
1017static void fd_watchdog(void)
1018{
1019#ifdef DCL_DEBUG
1020 if (DP->flags & FD_DEBUG) {
1021 DPRINT("calling disk change from watchdog\n");
1022 }
1023#endif
1024
1025 if (disk_change(current_drive)) {
1026 DPRINT("disk removed during i/o\n");
1027 cancel_activity();
1028 cont->done(0);
1029 reset_fdc();
1030 } else {
1031 del_timer(&fd_timer);
1032 fd_timer.function = (timeout_fn) fd_watchdog;
1033 fd_timer.expires = jiffies + HZ / 10;
1034 add_timer(&fd_timer);
1035 }
1036}
1037
1038static void main_command_interrupt(void)
1039{
1040 del_timer(&fd_timer);
1041 cont->interrupt();
1042}
1043
1044/* waits for a delay (spinup or select) to pass */
1045static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
1046{
1047 if (FDCS->reset) {
1048 reset_fdc(); /* do the reset during sleep to win time
1049 * if we don't need to sleep, it's a good
1050 * occasion anyways */
1051 return 1;
1052 }
1053
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08001054 if (time_before(jiffies, delay)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 del_timer(&fd_timer);
1056 fd_timer.function = function;
1057 fd_timer.expires = delay;
1058 add_timer(&fd_timer);
1059 return 1;
1060 }
1061 return 0;
1062}
1063
1064static DEFINE_SPINLOCK(floppy_hlt_lock);
1065static int hlt_disabled;
1066static void floppy_disable_hlt(void)
1067{
1068 unsigned long flags;
1069
1070 spin_lock_irqsave(&floppy_hlt_lock, flags);
1071 if (!hlt_disabled) {
1072 hlt_disabled = 1;
1073#ifdef HAVE_DISABLE_HLT
1074 disable_hlt();
1075#endif
1076 }
1077 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1078}
1079
1080static void floppy_enable_hlt(void)
1081{
1082 unsigned long flags;
1083
1084 spin_lock_irqsave(&floppy_hlt_lock, flags);
1085 if (hlt_disabled) {
1086 hlt_disabled = 0;
1087#ifdef HAVE_DISABLE_HLT
1088 enable_hlt();
1089#endif
1090 }
1091 spin_unlock_irqrestore(&floppy_hlt_lock, flags);
1092}
1093
1094static void setup_DMA(void)
1095{
1096 unsigned long f;
1097
1098#ifdef FLOPPY_SANITY_CHECK
1099 if (raw_cmd->length == 0) {
1100 int i;
1101
1102 printk("zero dma transfer size:");
1103 for (i = 0; i < raw_cmd->cmd_count; i++)
1104 printk("%x,", raw_cmd->cmd[i]);
1105 printk("\n");
1106 cont->done(0);
1107 FDCS->reset = 1;
1108 return;
1109 }
1110 if (((unsigned long)raw_cmd->kernel_data) % 512) {
1111 printk("non aligned address: %p\n", raw_cmd->kernel_data);
1112 cont->done(0);
1113 FDCS->reset = 1;
1114 return;
1115 }
1116#endif
1117 f = claim_dma_lock();
1118 fd_disable_dma();
1119#ifdef fd_dma_setup
1120 if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length,
1121 (raw_cmd->flags & FD_RAW_READ) ?
1122 DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) {
1123 release_dma_lock(f);
1124 cont->done(0);
1125 FDCS->reset = 1;
1126 return;
1127 }
1128 release_dma_lock(f);
1129#else
1130 fd_clear_dma_ff();
1131 fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length);
1132 fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ) ?
1133 DMA_MODE_READ : DMA_MODE_WRITE);
1134 fd_set_dma_addr(raw_cmd->kernel_data);
1135 fd_set_dma_count(raw_cmd->length);
1136 virtual_dma_port = FDCS->address;
1137 fd_enable_dma();
1138 release_dma_lock(f);
1139#endif
1140 floppy_disable_hlt();
1141}
1142
1143static void show_floppy(void);
1144
1145/* waits until the fdc becomes ready */
1146static int wait_til_ready(void)
1147{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001148 int status;
1149 int counter;
1150
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 if (FDCS->reset)
1152 return -1;
1153 for (counter = 0; counter < 10000; counter++) {
1154 status = fd_inb(FD_STATUS);
1155 if (status & STATUS_READY)
1156 return status;
1157 }
1158 if (!initialising) {
1159 DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc);
1160 show_floppy();
1161 }
1162 FDCS->reset = 1;
1163 return -1;
1164}
1165
1166/* sends a command byte to the fdc */
1167static int output_byte(char byte)
1168{
1169 int status;
1170
1171 if ((status = wait_til_ready()) < 0)
1172 return -1;
1173 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) {
1174 fd_outb(byte, FD_DATA);
1175#ifdef FLOPPY_SANITY_CHECK
1176 output_log[output_log_pos].data = byte;
1177 output_log[output_log_pos].status = status;
1178 output_log[output_log_pos].jiffies = jiffies;
1179 output_log_pos = (output_log_pos + 1) % OLOGSIZE;
1180#endif
1181 return 0;
1182 }
1183 FDCS->reset = 1;
1184 if (!initialising) {
1185 DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
1186 byte, fdc, status);
1187 show_floppy();
1188 }
1189 return -1;
1190}
1191
1192#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
1193
1194/* gets the response from the fdc */
1195static int result(void)
1196{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001197 int i;
1198 int status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
1200 for (i = 0; i < MAX_REPLIES; i++) {
1201 if ((status = wait_til_ready()) < 0)
1202 break;
1203 status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
1204 if ((status & ~STATUS_BUSY) == STATUS_READY) {
1205#ifdef FLOPPY_SANITY_CHECK
1206 resultjiffies = jiffies;
1207 resultsize = i;
1208#endif
1209 return i;
1210 }
1211 if (status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
1212 reply_buffer[i] = fd_inb(FD_DATA);
1213 else
1214 break;
1215 }
1216 if (!initialising) {
1217 DPRINT
1218 ("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
1219 fdc, status, i);
1220 show_floppy();
1221 }
1222 FDCS->reset = 1;
1223 return -1;
1224}
1225
1226#define MORE_OUTPUT -2
1227/* does the fdc need more output? */
1228static int need_more_output(void)
1229{
1230 int status;
Jesper Juhl06f748c2007-10-16 23:30:57 -07001231
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 if ((status = wait_til_ready()) < 0)
1233 return -1;
1234 if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
1235 return MORE_OUTPUT;
1236 return result();
1237}
1238
1239/* Set perpendicular mode as required, based on data rate, if supported.
1240 * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
1241 */
1242static inline void perpendicular_mode(void)
1243{
1244 unsigned char perp_mode;
1245
1246 if (raw_cmd->rate & 0x40) {
1247 switch (raw_cmd->rate & 3) {
1248 case 0:
1249 perp_mode = 2;
1250 break;
1251 case 3:
1252 perp_mode = 3;
1253 break;
1254 default:
1255 DPRINT("Invalid data rate for perpendicular mode!\n");
1256 cont->done(0);
1257 FDCS->reset = 1; /* convenient way to return to
1258 * redo without to much hassle (deep
1259 * stack et al. */
1260 return;
1261 }
1262 } else
1263 perp_mode = 0;
1264
1265 if (FDCS->perp_mode == perp_mode)
1266 return;
1267 if (FDCS->version >= FDC_82077_ORIG) {
1268 output_byte(FD_PERPENDICULAR);
1269 output_byte(perp_mode);
1270 FDCS->perp_mode = perp_mode;
1271 } else if (perp_mode) {
1272 DPRINT("perpendicular mode not supported by this FDC.\n");
1273 }
1274} /* perpendicular_mode */
1275
1276static int fifo_depth = 0xa;
1277static int no_fifo;
1278
1279static int fdc_configure(void)
1280{
1281 /* Turn on FIFO */
1282 output_byte(FD_CONFIGURE);
1283 if (need_more_output() != MORE_OUTPUT)
1284 return 0;
1285 output_byte(0);
1286 output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf));
1287 output_byte(0); /* pre-compensation from track
1288 0 upwards */
1289 return 1;
1290}
1291
1292#define NOMINAL_DTR 500
1293
1294/* Issue a "SPECIFY" command to set the step rate time, head unload time,
1295 * head load time, and DMA disable flag to values needed by floppy.
1296 *
1297 * The value "dtr" is the data transfer rate in Kbps. It is needed
1298 * to account for the data rate-based scaling done by the 82072 and 82077
1299 * FDC types. This parameter is ignored for other types of FDCs (i.e.
1300 * 8272a).
1301 *
1302 * Note that changing the data transfer rate has a (probably deleterious)
1303 * effect on the parameters subject to scaling for 82072/82077 FDCs, so
1304 * fdc_specify is called again after each data transfer rate
1305 * change.
1306 *
1307 * srt: 1000 to 16000 in microseconds
1308 * hut: 16 to 240 milliseconds
1309 * hlt: 2 to 254 milliseconds
1310 *
1311 * These values are rounded up to the next highest available delay time.
1312 */
1313static void fdc_specify(void)
1314{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001315 unsigned char spec1;
1316 unsigned char spec2;
1317 unsigned long srt;
1318 unsigned long hlt;
1319 unsigned long hut;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 unsigned long dtr = NOMINAL_DTR;
1321 unsigned long scale_dtr = NOMINAL_DTR;
1322 int hlt_max_code = 0x7f;
1323 int hut_max_code = 0xf;
1324
1325 if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
1326 fdc_configure();
1327 FDCS->need_configure = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 }
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
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922/* start motor, check media-changed condition and write protection */
Jesper Juhl06f748c2007-10-16 23:30:57 -07001923static int start_motor(void (*function)(void))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924{
Jesper Juhl06f748c2007-10-16 23:30:57 -07001925 int mask;
1926 int data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001927
1928 mask = 0xfc;
1929 data = UNIT(current_drive);
1930 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR)) {
1931 if (!(FDCS->dor & (0x10 << UNIT(current_drive)))) {
1932 set_debugt();
1933 /* no read since this drive is running */
1934 DRS->first_read_date = 0;
1935 /* note motor start time if motor is not yet running */
1936 DRS->spinup_date = jiffies;
1937 data |= (0x10 << UNIT(current_drive));
1938 }
1939 } else if (FDCS->dor & (0x10 << UNIT(current_drive)))
1940 mask &= ~(0x10 << UNIT(current_drive));
1941
1942 /* starts motor and selects floppy */
1943 del_timer(motor_off_timer + current_drive);
1944 set_dor(fdc, mask, data);
1945
1946 /* wait_for_completion also schedules reset if needed. */
1947 return (fd_wait_for_completion(DRS->select_date + DP->select_delay,
1948 (timeout_fn) function));
1949}
1950
1951static void floppy_ready(void)
1952{
1953 CHECK_RESET;
1954 if (start_motor(floppy_ready))
1955 return;
1956 if (fdc_dtr())
1957 return;
1958
1959#ifdef DCL_DEBUG
1960 if (DP->flags & FD_DEBUG) {
1961 DPRINT("calling disk change from floppy_ready\n");
1962 }
1963#endif
1964 if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
1965 disk_change(current_drive) && !DP->select_delay)
1966 twaddle(); /* this clears the dcl on certain drive/controller
1967 * combinations */
1968
1969#ifdef fd_chose_dma_mode
1970 if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) {
1971 unsigned long flags = claim_dma_lock();
1972 fd_chose_dma_mode(raw_cmd->kernel_data, raw_cmd->length);
1973 release_dma_lock(flags);
1974 }
1975#endif
1976
1977 if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)) {
1978 perpendicular_mode();
1979 fdc_specify(); /* must be done here because of hut, hlt ... */
1980 seek_floppy();
1981 } else {
1982 if ((raw_cmd->flags & FD_RAW_READ) ||
1983 (raw_cmd->flags & FD_RAW_WRITE))
1984 fdc_specify();
1985 setup_rw_floppy();
1986 }
1987}
1988
1989static void floppy_start(void)
1990{
1991 reschedule_timeout(current_reqD, "floppy start", 0);
1992
1993 scandrives();
1994#ifdef DCL_DEBUG
1995 if (DP->flags & FD_DEBUG) {
1996 DPRINT("setting NEWCHANGE in floppy_start\n");
1997 }
1998#endif
1999 SETF(FD_DISK_NEWCHANGE);
2000 floppy_ready();
2001}
2002
2003/*
2004 * ========================================================================
2005 * here ends the bottom half. Exported routines are:
2006 * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
2007 * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
2008 * Initialization also uses output_byte, result, set_dor, floppy_interrupt
2009 * and set_dor.
2010 * ========================================================================
2011 */
2012/*
2013 * General purpose continuations.
2014 * ==============================
2015 */
2016
2017static void do_wakeup(void)
2018{
2019 reschedule_timeout(MAXTIMEOUT, "do wakeup", 0);
2020 cont = NULL;
2021 command_status += 2;
2022 wake_up(&command_done);
2023}
2024
2025static struct cont_t wakeup_cont = {
2026 .interrupt = empty,
2027 .redo = do_wakeup,
2028 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002029 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030};
2031
2032static struct cont_t intr_cont = {
2033 .interrupt = empty,
2034 .redo = process_fd_request,
2035 .error = empty,
Jesper Juhl06f748c2007-10-16 23:30:57 -07002036 .done = (done_f)empty
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037};
2038
Jesper Juhl06f748c2007-10-16 23:30:57 -07002039static int wait_til_done(void (*handler)(void), int interruptible)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040{
2041 int ret;
2042
2043 schedule_bh(handler);
2044
2045 if (command_status < 2 && NO_SIGNAL) {
2046 DECLARE_WAITQUEUE(wait, current);
2047
2048 add_wait_queue(&command_done, &wait);
2049 for (;;) {
2050 set_current_state(interruptible ?
2051 TASK_INTERRUPTIBLE :
2052 TASK_UNINTERRUPTIBLE);
2053
2054 if (command_status >= 2 || !NO_SIGNAL)
2055 break;
2056
2057 is_alive("wait_til_done");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058 schedule();
2059 }
2060
2061 set_current_state(TASK_RUNNING);
2062 remove_wait_queue(&command_done, &wait);
2063 }
2064
2065 if (command_status < 2) {
2066 cancel_activity();
2067 cont = &intr_cont;
2068 reset_fdc();
2069 return -EINTR;
2070 }
2071
2072 if (FDCS->reset)
2073 command_status = FD_COMMAND_ERROR;
2074 if (command_status == FD_COMMAND_OKAY)
2075 ret = 0;
2076 else
2077 ret = -EIO;
2078 command_status = FD_COMMAND_NONE;
2079 return ret;
2080}
2081
2082static void generic_done(int result)
2083{
2084 command_status = result;
2085 cont = &wakeup_cont;
2086}
2087
2088static void generic_success(void)
2089{
2090 cont->done(1);
2091}
2092
2093static void generic_failure(void)
2094{
2095 cont->done(0);
2096}
2097
2098static void success_and_wakeup(void)
2099{
2100 generic_success();
2101 cont->redo();
2102}
2103
2104/*
2105 * formatting and rw support.
2106 * ==========================
2107 */
2108
2109static int next_valid_format(void)
2110{
2111 int probed_format;
2112
2113 probed_format = DRS->probed_format;
2114 while (1) {
2115 if (probed_format >= 8 || !DP->autodetect[probed_format]) {
2116 DRS->probed_format = 0;
2117 return 1;
2118 }
2119 if (floppy_type[DP->autodetect[probed_format]].sect) {
2120 DRS->probed_format = probed_format;
2121 return 0;
2122 }
2123 probed_format++;
2124 }
2125}
2126
2127static void bad_flp_intr(void)
2128{
2129 int err_count;
2130
2131 if (probing) {
2132 DRS->probed_format++;
2133 if (!next_valid_format())
2134 return;
2135 }
2136 err_count = ++(*errors);
2137 INFBOUND(DRWE->badness, err_count);
2138 if (err_count > DP->max_errors.abort)
2139 cont->done(0);
2140 if (err_count > DP->max_errors.reset)
2141 FDCS->reset = 1;
2142 else if (err_count > DP->max_errors.recal)
2143 DRS->track = NEED_2_RECAL;
2144}
2145
2146static void set_floppy(int drive)
2147{
2148 int type = ITYPE(UDRS->fd_device);
Jesper Juhl06f748c2007-10-16 23:30:57 -07002149
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 if (type)
2151 _floppy = floppy_type + type;
2152 else
2153 _floppy = current_type[drive];
2154}
2155
2156/*
2157 * formatting support.
2158 * ===================
2159 */
2160static void format_interrupt(void)
2161{
2162 switch (interpret_errors()) {
2163 case 1:
2164 cont->error();
2165 case 2:
2166 break;
2167 case 0:
2168 cont->done(1);
2169 }
2170 cont->redo();
2171}
2172
2173#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
2174#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
2175#define CT(x) ((x) | 0xc0)
2176static void setup_format_params(int track)
2177{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002178 int n;
2179 int il;
2180 int count;
2181 int head_shift;
2182 int track_shift;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183 struct fparm {
2184 unsigned char track, head, sect, size;
2185 } *here = (struct fparm *)floppy_track_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186
2187 raw_cmd = &default_raw_cmd;
2188 raw_cmd->track = track;
2189
2190 raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
2191 FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
2192 raw_cmd->rate = _floppy->rate & 0x43;
2193 raw_cmd->cmd_count = NR_F;
2194 COMMAND = FM_MODE(_floppy, FD_FORMAT);
2195 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, format_req.head);
2196 F_SIZECODE = FD_SIZECODE(_floppy);
2197 F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE;
2198 F_GAP = _floppy->fmt_gap;
2199 F_FILL = FD_FILL_BYTE;
2200
2201 raw_cmd->kernel_data = floppy_track_buffer;
2202 raw_cmd->length = 4 * F_SECT_PER_TRACK;
2203
2204 /* allow for about 30ms for data transport per track */
2205 head_shift = (F_SECT_PER_TRACK + 5) / 6;
2206
2207 /* a ``cylinder'' is two tracks plus a little stepping time */
2208 track_shift = 2 * head_shift + 3;
2209
2210 /* position of logical sector 1 on this track */
2211 n = (track_shift * format_req.track + head_shift * format_req.head)
2212 % F_SECT_PER_TRACK;
2213
2214 /* determine interleave */
2215 il = 1;
2216 if (_floppy->fmt_gap < 0x22)
2217 il++;
2218
2219 /* initialize field */
2220 for (count = 0; count < F_SECT_PER_TRACK; ++count) {
2221 here[count].track = format_req.track;
2222 here[count].head = format_req.head;
2223 here[count].sect = 0;
2224 here[count].size = F_SIZECODE;
2225 }
2226 /* place logical sectors */
2227 for (count = 1; count <= F_SECT_PER_TRACK; ++count) {
2228 here[n].sect = count;
2229 n = (n + il) % F_SECT_PER_TRACK;
2230 if (here[n].sect) { /* sector busy, find next free sector */
2231 ++n;
2232 if (n >= F_SECT_PER_TRACK) {
2233 n -= F_SECT_PER_TRACK;
2234 while (here[n].sect)
2235 ++n;
2236 }
2237 }
2238 }
2239 if (_floppy->stretch & FD_ZEROBASED) {
2240 for (count = 0; count < F_SECT_PER_TRACK; count++)
2241 here[count].sect--;
2242 }
2243}
2244
2245static void redo_format(void)
2246{
2247 buffer_track = -1;
2248 setup_format_params(format_req.track << STRETCH(_floppy));
2249 floppy_start();
2250 debugt("queue format request");
2251}
2252
2253static struct cont_t format_cont = {
2254 .interrupt = format_interrupt,
2255 .redo = redo_format,
2256 .error = bad_flp_intr,
2257 .done = generic_done
2258};
2259
2260static int do_format(int drive, struct format_descr *tmp_format_req)
2261{
2262 int ret;
2263
2264 LOCK_FDC(drive, 1);
2265 set_floppy(drive);
2266 if (!_floppy ||
2267 _floppy->track > DP->tracks ||
2268 tmp_format_req->track >= _floppy->track ||
2269 tmp_format_req->head >= _floppy->head ||
2270 (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) ||
2271 !_floppy->fmt_gap) {
2272 process_fd_request();
2273 return -EINVAL;
2274 }
2275 format_req = *tmp_format_req;
2276 format_errors = 0;
2277 cont = &format_cont;
2278 errors = &format_errors;
2279 IWAIT(redo_format);
2280 process_fd_request();
2281 return ret;
2282}
2283
2284/*
2285 * Buffer read/write and support
2286 * =============================
2287 */
2288
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002289static void floppy_end_request(struct request *req, int error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290{
2291 unsigned int nr_sectors = current_count_sectors;
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002292 unsigned int drive = (unsigned long)req->rq_disk->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
2294 /* current_count_sectors can be zero if transfer failed */
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002295 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 nr_sectors = req->current_nr_sectors;
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002297 if (__blk_end_request(req, error, nr_sectors << 9))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
2300 /* We're done with the request */
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002301 floppy_off(drive);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 current_req = NULL;
2303}
2304
2305/* new request_done. Can handle physical sectors which are smaller than a
2306 * logical buffer */
2307static void request_done(int uptodate)
2308{
2309 struct request_queue *q = floppy_queue;
2310 struct request *req = current_req;
2311 unsigned long flags;
2312 int block;
2313
2314 probing = 0;
2315 reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
2316
2317 if (!req) {
2318 printk("floppy.c: no request in request_done\n");
2319 return;
2320 }
2321
2322 if (uptodate) {
2323 /* maintain values for invalidation on geometry
2324 * change */
2325 block = current_count_sectors + req->sector;
2326 INFBOUND(DRS->maxblock, block);
2327 if (block > _floppy->sect)
2328 DRS->maxtrack = 1;
2329
2330 /* unlock chained buffers */
2331 spin_lock_irqsave(q->queue_lock, flags);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002332 floppy_end_request(req, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 spin_unlock_irqrestore(q->queue_lock, flags);
2334 } else {
2335 if (rq_data_dir(req) == WRITE) {
2336 /* record write error information */
2337 DRWE->write_errors++;
2338 if (DRWE->write_errors == 1) {
2339 DRWE->first_error_sector = req->sector;
2340 DRWE->first_error_generation = DRS->generation;
2341 }
2342 DRWE->last_error_sector = req->sector;
2343 DRWE->last_error_generation = DRS->generation;
2344 }
2345 spin_lock_irqsave(q->queue_lock, flags);
Kiyoshi Ueda1c5093b2008-01-28 10:36:21 +01002346 floppy_end_request(req, -EIO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 spin_unlock_irqrestore(q->queue_lock, flags);
2348 }
2349}
2350
2351/* Interrupt handler evaluating the result of the r/w operation */
2352static void rw_interrupt(void)
2353{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002354 int eoc;
2355 int ssize;
2356 int heads;
2357 int nr_sectors;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 if (R_HEAD >= 2) {
2360 /* some Toshiba floppy controllers occasionnally seem to
2361 * return bogus interrupts after read/write operations, which
2362 * can be recognized by a bad head number (>= 2) */
2363 return;
2364 }
2365
2366 if (!DRS->first_read_date)
2367 DRS->first_read_date = jiffies;
2368
2369 nr_sectors = 0;
2370 CODE2SIZE;
2371
2372 if (ST1 & ST1_EOC)
2373 eoc = 1;
2374 else
2375 eoc = 0;
2376
2377 if (COMMAND & 0x80)
2378 heads = 2;
2379 else
2380 heads = 1;
2381
2382 nr_sectors = (((R_TRACK - TRACK) * heads +
2383 R_HEAD - HEAD) * SECT_PER_TRACK +
2384 R_SECTOR - SECTOR + eoc) << SIZECODE >> 2;
2385
2386#ifdef FLOPPY_SANITY_CHECK
2387 if (nr_sectors / ssize >
2388 (in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
2389 DPRINT("long rw: %x instead of %lx\n",
2390 nr_sectors, current_count_sectors);
2391 printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
2392 printk("rh=%d h=%d\n", R_HEAD, HEAD);
2393 printk("rt=%d t=%d\n", R_TRACK, TRACK);
2394 printk("heads=%d eoc=%d\n", heads, eoc);
2395 printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
2396 fsector_t, ssize);
2397 printk("in_sector_offset=%d\n", in_sector_offset);
2398 }
2399#endif
2400
2401 nr_sectors -= in_sector_offset;
2402 INFBOUND(nr_sectors, 0);
2403 SUPBOUND(current_count_sectors, nr_sectors);
2404
2405 switch (interpret_errors()) {
2406 case 2:
2407 cont->redo();
2408 return;
2409 case 1:
2410 if (!current_count_sectors) {
2411 cont->error();
2412 cont->redo();
2413 return;
2414 }
2415 break;
2416 case 0:
2417 if (!current_count_sectors) {
2418 cont->redo();
2419 return;
2420 }
2421 current_type[current_drive] = _floppy;
2422 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2423 break;
2424 }
2425
2426 if (probing) {
2427 if (DP->flags & FTD_MSG)
2428 DPRINT("Auto-detected floppy type %s in fd%d\n",
2429 _floppy->name, current_drive);
2430 current_type[current_drive] = _floppy;
2431 floppy_sizes[TOMINOR(current_drive)] = _floppy->size;
2432 probing = 0;
2433 }
2434
2435 if (CT(COMMAND) != FD_READ ||
2436 raw_cmd->kernel_data == current_req->buffer) {
2437 /* transfer directly from buffer */
2438 cont->done(1);
2439 } else if (CT(COMMAND) == FD_READ) {
2440 buffer_track = raw_cmd->track;
2441 buffer_drive = current_drive;
2442 INFBOUND(buffer_max, nr_sectors + fsector_t);
2443 }
2444 cont->redo();
2445}
2446
2447/* Compute maximal contiguous buffer size. */
2448static int buffer_chain_size(void)
2449{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 struct bio_vec *bv;
NeilBrown5705f702007-09-25 12:35:59 +02002451 int size;
2452 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 char *base;
2454
2455 base = bio_data(current_req->bio);
2456 size = 0;
2457
NeilBrown5705f702007-09-25 12:35:59 +02002458 rq_for_each_segment(bv, current_req, iter) {
2459 if (page_address(bv->bv_page) + bv->bv_offset != base + size)
2460 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
NeilBrown5705f702007-09-25 12:35:59 +02002462 size += bv->bv_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 }
2464
2465 return size >> 9;
2466}
2467
2468/* Compute the maximal transfer size */
2469static int transfer_size(int ssize, int max_sector, int max_size)
2470{
2471 SUPBOUND(max_sector, fsector_t + max_size);
2472
2473 /* alignment */
2474 max_sector -= (max_sector % _floppy->sect) % ssize;
2475
2476 /* transfer size, beginning not aligned */
2477 current_count_sectors = max_sector - fsector_t;
2478
2479 return max_sector;
2480}
2481
2482/*
2483 * Move data from/to the track buffer to/from the buffer cache.
2484 */
2485static void copy_buffer(int ssize, int max_sector, int max_sector_2)
2486{
2487 int remaining; /* number of transferred 512-byte sectors */
2488 struct bio_vec *bv;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002489 char *buffer;
2490 char *dma_buffer;
NeilBrown5705f702007-09-25 12:35:59 +02002491 int size;
2492 struct req_iterator iter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
2494 max_sector = transfer_size(ssize,
2495 min(max_sector, max_sector_2),
2496 current_req->nr_sectors);
2497
2498 if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
2499 buffer_max > fsector_t + current_req->nr_sectors)
2500 current_count_sectors = min_t(int, buffer_max - fsector_t,
2501 current_req->nr_sectors);
2502
2503 remaining = current_count_sectors << 9;
2504#ifdef FLOPPY_SANITY_CHECK
2505 if ((remaining >> 9) > current_req->nr_sectors &&
2506 CT(COMMAND) == FD_WRITE) {
2507 DPRINT("in copy buffer\n");
2508 printk("current_count_sectors=%ld\n", current_count_sectors);
2509 printk("remaining=%d\n", remaining >> 9);
2510 printk("current_req->nr_sectors=%ld\n",
2511 current_req->nr_sectors);
2512 printk("current_req->current_nr_sectors=%u\n",
2513 current_req->current_nr_sectors);
2514 printk("max_sector=%d\n", max_sector);
2515 printk("ssize=%d\n", ssize);
2516 }
2517#endif
2518
2519 buffer_max = max(max_sector, buffer_max);
2520
2521 dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
2522
2523 size = current_req->current_nr_sectors << 9;
2524
NeilBrown5705f702007-09-25 12:35:59 +02002525 rq_for_each_segment(bv, current_req, iter) {
2526 if (!remaining)
2527 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
NeilBrown5705f702007-09-25 12:35:59 +02002529 size = bv->bv_len;
2530 SUPBOUND(size, remaining);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531
NeilBrown5705f702007-09-25 12:35:59 +02002532 buffer = page_address(bv->bv_page) + bv->bv_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533#ifdef FLOPPY_SANITY_CHECK
NeilBrown5705f702007-09-25 12:35:59 +02002534 if (dma_buffer + size >
2535 floppy_track_buffer + (max_buffer_sectors << 10) ||
2536 dma_buffer < floppy_track_buffer) {
2537 DPRINT("buffer overrun in copy buffer %d\n",
2538 (int)((floppy_track_buffer -
2539 dma_buffer) >> 9));
2540 printk("fsector_t=%d buffer_min=%d\n",
2541 fsector_t, buffer_min);
2542 printk("current_count_sectors=%ld\n",
2543 current_count_sectors);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 if (CT(COMMAND) == FD_READ)
NeilBrown5705f702007-09-25 12:35:59 +02002545 printk("read\n");
2546 if (CT(COMMAND) == FD_WRITE)
2547 printk("write\n");
2548 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 }
NeilBrown5705f702007-09-25 12:35:59 +02002550 if (((unsigned long)buffer) % 512)
2551 DPRINT("%p buffer not aligned\n", buffer);
2552#endif
2553 if (CT(COMMAND) == FD_READ)
2554 memcpy(buffer, dma_buffer, size);
2555 else
2556 memcpy(dma_buffer, buffer, size);
2557
2558 remaining -= size;
2559 dma_buffer += size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 }
2561#ifdef FLOPPY_SANITY_CHECK
2562 if (remaining) {
2563 if (remaining > 0)
2564 max_sector -= remaining >> 9;
2565 DPRINT("weirdness: remaining %d\n", remaining >> 9);
2566 }
2567#endif
2568}
2569
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570/* work around a bug in pseudo DMA
2571 * (on some FDCs) pseudo DMA does not stop when the CPU stops
2572 * sending data. Hence we need a different way to signal the
2573 * transfer length: We use SECT_PER_TRACK. Unfortunately, this
2574 * does not work with MT, hence we can only transfer one head at
2575 * a time
2576 */
2577static void virtualdmabug_workaround(void)
2578{
Jesper Juhl06f748c2007-10-16 23:30:57 -07002579 int hard_sectors;
2580 int end_sector;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581
2582 if (CT(COMMAND) == FD_WRITE) {
2583 COMMAND &= ~0x80; /* switch off multiple track mode */
2584
2585 hard_sectors = raw_cmd->length >> (7 + SIZECODE);
2586 end_sector = SECTOR + hard_sectors - 1;
2587#ifdef FLOPPY_SANITY_CHECK
2588 if (end_sector > SECT_PER_TRACK) {
2589 printk("too many sectors %d > %d\n",
2590 end_sector, SECT_PER_TRACK);
2591 return;
2592 }
2593#endif
2594 SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points
2595 * to end of transfer */
2596 }
2597}
2598
2599/*
2600 * Formulate a read/write request.
2601 * this routine decides where to load the data (directly to buffer, or to
2602 * tmp floppy area), how much data to load (the size of the buffer, the whole
2603 * track, or a single sector)
2604 * All floppy_track_buffer handling goes in here. If we ever add track buffer
2605 * allocation on the fly, it should be done here. No other part should need
2606 * modification.
2607 */
2608
2609static int make_raw_rw_request(void)
2610{
2611 int aligned_sector_t;
Jesper Juhl06f748c2007-10-16 23:30:57 -07002612 int max_sector;
2613 int max_size;
2614 int tracksize;
2615 int ssize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
2617 if (max_buffer_sectors == 0) {
2618 printk("VFS: Block I/O scheduled on unopened device\n");
2619 return 0;
2620 }
2621
2622 set_fdc((long)current_req->rq_disk->private_data);
2623
2624 raw_cmd = &default_raw_cmd;
2625 raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
2626 FD_RAW_NEED_SEEK;
2627 raw_cmd->cmd_count = NR_RW;
2628 if (rq_data_dir(current_req) == READ) {
2629 raw_cmd->flags |= FD_RAW_READ;
2630 COMMAND = FM_MODE(_floppy, FD_READ);
2631 } else if (rq_data_dir(current_req) == WRITE) {
2632 raw_cmd->flags |= FD_RAW_WRITE;
2633 COMMAND = FM_MODE(_floppy, FD_WRITE);
2634 } else {
2635 DPRINT("make_raw_rw_request: unknown command\n");
2636 return 0;
2637 }
2638
2639 max_sector = _floppy->sect * _floppy->head;
2640
2641 TRACK = (int)current_req->sector / max_sector;
2642 fsector_t = (int)current_req->sector % max_sector;
2643 if (_floppy->track && TRACK >= _floppy->track) {
2644 if (current_req->current_nr_sectors & 1) {
2645 current_count_sectors = 1;
2646 return 1;
2647 } else
2648 return 0;
2649 }
2650 HEAD = fsector_t / _floppy->sect;
2651
2652 if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
2653 TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
2654 max_sector = _floppy->sect;
2655
2656 /* 2M disks have phantom sectors on the first track */
2657 if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)) {
2658 max_sector = 2 * _floppy->sect / 3;
2659 if (fsector_t >= max_sector) {
2660 current_count_sectors =
2661 min_t(int, _floppy->sect - fsector_t,
2662 current_req->nr_sectors);
2663 return 1;
2664 }
2665 SIZECODE = 2;
2666 } else
2667 SIZECODE = FD_SIZECODE(_floppy);
2668 raw_cmd->rate = _floppy->rate & 0x43;
2669 if ((_floppy->rate & FD_2M) && (TRACK || HEAD) && raw_cmd->rate == 2)
2670 raw_cmd->rate = 1;
2671
2672 if (SIZECODE)
2673 SIZECODE2 = 0xff;
2674 else
2675 SIZECODE2 = 0x80;
2676 raw_cmd->track = TRACK << STRETCH(_floppy);
2677 DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy, HEAD);
2678 GAP = _floppy->gap;
2679 CODE2SIZE;
2680 SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
2681 SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
2682 ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1);
2683
2684 /* tracksize describes the size which can be filled up with sectors
2685 * of size ssize.
2686 */
2687 tracksize = _floppy->sect - _floppy->sect % ssize;
2688 if (tracksize < _floppy->sect) {
2689 SECT_PER_TRACK++;
2690 if (tracksize <= fsector_t % _floppy->sect)
2691 SECTOR--;
2692
2693 /* if we are beyond tracksize, fill up using smaller sectors */
2694 while (tracksize <= fsector_t % _floppy->sect) {
2695 while (tracksize + ssize > _floppy->sect) {
2696 SIZECODE--;
2697 ssize >>= 1;
2698 }
2699 SECTOR++;
2700 SECT_PER_TRACK++;
2701 tracksize += ssize;
2702 }
2703 max_sector = HEAD * _floppy->sect + tracksize;
2704 } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) {
2705 max_sector = _floppy->sect;
2706 } else if (!HEAD && CT(COMMAND) == FD_WRITE) {
2707 /* for virtual DMA bug workaround */
2708 max_sector = _floppy->sect;
2709 }
2710
2711 in_sector_offset = (fsector_t % _floppy->sect) % ssize;
2712 aligned_sector_t = fsector_t - in_sector_offset;
2713 max_size = current_req->nr_sectors;
2714 if ((raw_cmd->track == buffer_track) &&
2715 (current_drive == buffer_drive) &&
2716 (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
2717 /* data already in track buffer */
2718 if (CT(COMMAND) == FD_READ) {
2719 copy_buffer(1, max_sector, buffer_max);
2720 return 1;
2721 }
2722 } else if (in_sector_offset || current_req->nr_sectors < ssize) {
2723 if (CT(COMMAND) == FD_WRITE) {
2724 if (fsector_t + current_req->nr_sectors > ssize &&
2725 fsector_t + current_req->nr_sectors < ssize + ssize)
2726 max_size = ssize + ssize;
2727 else
2728 max_size = ssize;
2729 }
2730 raw_cmd->flags &= ~FD_RAW_WRITE;
2731 raw_cmd->flags |= FD_RAW_READ;
2732 COMMAND = FM_MODE(_floppy, FD_READ);
2733 } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
2734 unsigned long dma_limit;
2735 int direct, indirect;
2736
2737 indirect =
2738 transfer_size(ssize, max_sector,
2739 max_buffer_sectors * 2) - fsector_t;
2740
2741 /*
2742 * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
2743 * on a 64 bit machine!
2744 */
2745 max_size = buffer_chain_size();
2746 dma_limit =
2747 (MAX_DMA_ADDRESS -
2748 ((unsigned long)current_req->buffer)) >> 9;
2749 if ((unsigned long)max_size > dma_limit) {
2750 max_size = dma_limit;
2751 }
2752 /* 64 kb boundaries */
2753 if (CROSS_64KB(current_req->buffer, max_size << 9))
2754 max_size = (K_64 -
2755 ((unsigned long)current_req->buffer) %
2756 K_64) >> 9;
2757 direct = transfer_size(ssize, max_sector, max_size) - fsector_t;
2758 /*
2759 * We try to read tracks, but if we get too many errors, we
2760 * go back to reading just one sector at a time.
2761 *
2762 * This means we should be able to read a sector even if there
2763 * are other bad sectors on this track.
2764 */
2765 if (!direct ||
2766 (indirect * 2 > direct * 3 &&
Jesper Juhlaee90412007-10-16 23:30:58 -07002767 *errors < DP->max_errors.read_track && ((!probing
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 || (DP->read_track & (1 << DRS->probed_format)))))) {
2769 max_size = current_req->nr_sectors;
2770 } else {
2771 raw_cmd->kernel_data = current_req->buffer;
2772 raw_cmd->length = current_count_sectors << 9;
2773 if (raw_cmd->length == 0) {
2774 DPRINT
2775 ("zero dma transfer attempted from make_raw_request\n");
2776 DPRINT("indirect=%d direct=%d fsector_t=%d",
2777 indirect, direct, fsector_t);
2778 return 0;
2779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 virtualdmabug_workaround();
2781 return 2;
2782 }
2783 }
2784
2785 if (CT(COMMAND) == FD_READ)
2786 max_size = max_sector; /* unbounded */
2787
2788 /* claim buffer track if needed */
2789 if (buffer_track != raw_cmd->track || /* bad track */
2790 buffer_drive != current_drive || /* bad drive */
2791 fsector_t > buffer_max ||
2792 fsector_t < buffer_min ||
2793 ((CT(COMMAND) == FD_READ ||
2794 (!in_sector_offset && current_req->nr_sectors >= ssize)) &&
2795 max_sector > 2 * max_buffer_sectors + buffer_min &&
2796 max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
2797 /* not enough space */
2798 ) {
2799 buffer_track = -1;
2800 buffer_drive = current_drive;
2801 buffer_max = buffer_min = aligned_sector_t;
2802 }
2803 raw_cmd->kernel_data = floppy_track_buffer +
2804 ((aligned_sector_t - buffer_min) << 9);
2805
2806 if (CT(COMMAND) == FD_WRITE) {
2807 /* copy write buffer to track buffer.
2808 * if we get here, we know that the write
2809 * is either aligned or the data already in the buffer
2810 * (buffer will be overwritten) */
2811#ifdef FLOPPY_SANITY_CHECK
2812 if (in_sector_offset && buffer_track == -1)
2813 DPRINT("internal error offset !=0 on write\n");
2814#endif
2815 buffer_track = raw_cmd->track;
2816 buffer_drive = current_drive;
2817 copy_buffer(ssize, max_sector,
2818 2 * max_buffer_sectors + buffer_min);
2819 } else
2820 transfer_size(ssize, max_sector,
2821 2 * max_buffer_sectors + buffer_min -
2822 aligned_sector_t);
2823
2824 /* round up current_count_sectors to get dma xfer size */
2825 raw_cmd->length = in_sector_offset + current_count_sectors;
2826 raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
2827 raw_cmd->length <<= 9;
2828#ifdef FLOPPY_SANITY_CHECK
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829 if ((raw_cmd->length < current_count_sectors << 9) ||
2830 (raw_cmd->kernel_data != current_req->buffer &&
2831 CT(COMMAND) == FD_WRITE &&
2832 (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max ||
2833 aligned_sector_t < buffer_min)) ||
2834 raw_cmd->length % (128 << SIZECODE) ||
2835 raw_cmd->length <= 0 || current_count_sectors <= 0) {
2836 DPRINT("fractionary current count b=%lx s=%lx\n",
2837 raw_cmd->length, current_count_sectors);
2838 if (raw_cmd->kernel_data != current_req->buffer)
2839 printk("addr=%d, length=%ld\n",
2840 (int)((raw_cmd->kernel_data -
2841 floppy_track_buffer) >> 9),
2842 current_count_sectors);
2843 printk("st=%d ast=%d mse=%d msi=%d\n",
2844 fsector_t, aligned_sector_t, max_sector, max_size);
2845 printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
2846 printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
2847 COMMAND, SECTOR, HEAD, TRACK);
2848 printk("buffer drive=%d\n", buffer_drive);
2849 printk("buffer track=%d\n", buffer_track);
2850 printk("buffer_min=%d\n", buffer_min);
2851 printk("buffer_max=%d\n", buffer_max);
2852 return 0;
2853 }
2854
2855 if (raw_cmd->kernel_data != current_req->buffer) {
2856 if (raw_cmd->kernel_data < floppy_track_buffer ||
2857 current_count_sectors < 0 ||
2858 raw_cmd->length < 0 ||
2859 raw_cmd->kernel_data + raw_cmd->length >
2860 floppy_track_buffer + (max_buffer_sectors << 10)) {
2861 DPRINT("buffer overrun in schedule dma\n");
2862 printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
2863 fsector_t, buffer_min, raw_cmd->length >> 9);
2864 printk("current_count_sectors=%ld\n",
2865 current_count_sectors);
2866 if (CT(COMMAND) == FD_READ)
2867 printk("read\n");
2868 if (CT(COMMAND) == FD_WRITE)
2869 printk("write\n");
2870 return 0;
2871 }
2872 } else if (raw_cmd->length > current_req->nr_sectors << 9 ||
2873 current_count_sectors > current_req->nr_sectors) {
2874 DPRINT("buffer overrun in direct transfer\n");
2875 return 0;
2876 } else if (raw_cmd->length < current_count_sectors << 9) {
2877 DPRINT("more sectors than bytes\n");
2878 printk("bytes=%ld\n", raw_cmd->length >> 9);
2879 printk("sectors=%ld\n", current_count_sectors);
2880 }
2881 if (raw_cmd->length == 0) {
2882 DPRINT("zero dma transfer attempted from make_raw_request\n");
2883 return 0;
2884 }
2885#endif
2886
2887 virtualdmabug_workaround();
2888 return 2;
2889}
2890
2891static void redo_fd_request(void)
2892{
2893#define REPEAT {request_done(0); continue; }
2894 int drive;
2895 int tmp;
2896
2897 lastredo = jiffies;
2898 if (current_drive < N_DRIVE)
2899 floppy_off(current_drive);
2900
2901 for (;;) {
2902 if (!current_req) {
2903 struct request *req;
2904
2905 spin_lock_irq(floppy_queue->queue_lock);
2906 req = elv_next_request(floppy_queue);
2907 spin_unlock_irq(floppy_queue->queue_lock);
2908 if (!req) {
2909 do_floppy = NULL;
2910 unlock_fdc();
2911 return;
2912 }
2913 current_req = req;
2914 }
2915 drive = (long)current_req->rq_disk->private_data;
2916 set_fdc(drive);
2917 reschedule_timeout(current_reqD, "redo fd request", 0);
2918
2919 set_floppy(drive);
2920 raw_cmd = &default_raw_cmd;
2921 raw_cmd->flags = 0;
2922 if (start_motor(redo_fd_request))
2923 return;
2924 disk_change(current_drive);
2925 if (test_bit(current_drive, &fake_change) ||
2926 TESTF(FD_DISK_CHANGED)) {
2927 DPRINT("disk absent or changed during operation\n");
2928 REPEAT;
2929 }
2930 if (!_floppy) { /* Autodetection */
2931 if (!probing) {
2932 DRS->probed_format = 0;
2933 if (next_valid_format()) {
2934 DPRINT("no autodetectable formats\n");
2935 _floppy = NULL;
2936 REPEAT;
2937 }
2938 }
2939 probing = 1;
2940 _floppy =
2941 floppy_type + DP->autodetect[DRS->probed_format];
2942 } else
2943 probing = 0;
2944 errors = &(current_req->errors);
2945 tmp = make_raw_rw_request();
2946 if (tmp < 2) {
2947 request_done(tmp);
2948 continue;
2949 }
2950
2951 if (TESTF(FD_NEED_TWADDLE))
2952 twaddle();
2953 schedule_bh(floppy_start);
2954 debugt("queue fd request");
2955 return;
2956 }
2957#undef REPEAT
2958}
2959
2960static struct cont_t rw_cont = {
2961 .interrupt = rw_interrupt,
2962 .redo = redo_fd_request,
2963 .error = bad_flp_intr,
2964 .done = request_done
2965};
2966
2967static void process_fd_request(void)
2968{
2969 cont = &rw_cont;
2970 schedule_bh(redo_fd_request);
2971}
2972
Jens Axboe165125e2007-07-24 09:28:11 +02002973static void do_fd_request(struct request_queue * q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974{
2975 if (max_buffer_sectors == 0) {
2976 printk("VFS: do_fd_request called on non-open device\n");
2977 return;
2978 }
2979
2980 if (usage_count == 0) {
2981 printk("warning: usage count=0, current_req=%p exiting\n",
2982 current_req);
Jens Axboe4aff5e22006-08-10 08:44:47 +02002983 printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
2984 current_req->cmd_type, current_req->cmd_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 return;
2986 }
2987 if (test_bit(0, &fdc_busy)) {
2988 /* fdc busy, this new request will be treated when the
2989 current one is done */
2990 is_alive("do fd request, old request running");
2991 return;
2992 }
2993 lock_fdc(MAXTIMEOUT, 0);
2994 process_fd_request();
2995 is_alive("do fd request");
2996}
2997
2998static struct cont_t poll_cont = {
2999 .interrupt = success_and_wakeup,
3000 .redo = floppy_ready,
3001 .error = generic_failure,
3002 .done = generic_done
3003};
3004
3005static int poll_drive(int interruptible, int flag)
3006{
3007 int ret;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003008
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 /* no auto-sense, just clear dcl */
3010 raw_cmd = &default_raw_cmd;
3011 raw_cmd->flags = flag;
3012 raw_cmd->track = 0;
3013 raw_cmd->cmd_count = 0;
3014 cont = &poll_cont;
3015#ifdef DCL_DEBUG
3016 if (DP->flags & FD_DEBUG) {
3017 DPRINT("setting NEWCHANGE in poll_drive\n");
3018 }
3019#endif
3020 SETF(FD_DISK_NEWCHANGE);
3021 WAIT(floppy_ready);
3022 return ret;
3023}
3024
3025/*
3026 * User triggered reset
3027 * ====================
3028 */
3029
3030static void reset_intr(void)
3031{
3032 printk("weird, reset interrupt called\n");
3033}
3034
3035static struct cont_t reset_cont = {
3036 .interrupt = reset_intr,
3037 .redo = success_and_wakeup,
3038 .error = generic_failure,
3039 .done = generic_done
3040};
3041
3042static int user_reset_fdc(int drive, int arg, int interruptible)
3043{
3044 int ret;
3045
3046 ret = 0;
3047 LOCK_FDC(drive, interruptible);
3048 if (arg == FD_RESET_ALWAYS)
3049 FDCS->reset = 1;
3050 if (FDCS->reset) {
3051 cont = &reset_cont;
3052 WAIT(reset_fdc);
3053 }
3054 process_fd_request();
3055 return ret;
3056}
3057
3058/*
3059 * Misc Ioctl's and support
3060 * ========================
3061 */
3062static inline int fd_copyout(void __user *param, const void *address,
3063 unsigned long size)
3064{
3065 return copy_to_user(param, address, size) ? -EFAULT : 0;
3066}
3067
3068static inline int fd_copyin(void __user *param, void *address, unsigned long size)
3069{
3070 return copy_from_user(address, param, size) ? -EFAULT : 0;
3071}
3072
3073#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0)
3074#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0)
3075
3076#define COPYOUT(x) ECALL(_COPYOUT(x))
3077#define COPYIN(x) ECALL(_COPYIN(x))
3078
3079static inline const char *drive_name(int type, int drive)
3080{
3081 struct floppy_struct *floppy;
3082
3083 if (type)
3084 floppy = floppy_type + type;
3085 else {
3086 if (UDP->native_format)
3087 floppy = floppy_type + UDP->native_format;
3088 else
3089 return "(null)";
3090 }
3091 if (floppy->name)
3092 return floppy->name;
3093 else
3094 return "(null)";
3095}
3096
3097/* raw commands */
3098static void raw_cmd_done(int flag)
3099{
3100 int i;
3101
3102 if (!flag) {
3103 raw_cmd->flags |= FD_RAW_FAILURE;
3104 raw_cmd->flags |= FD_RAW_HARDFAILURE;
3105 } else {
3106 raw_cmd->reply_count = inr;
3107 if (raw_cmd->reply_count > MAX_REPLIES)
3108 raw_cmd->reply_count = 0;
3109 for (i = 0; i < raw_cmd->reply_count; i++)
3110 raw_cmd->reply[i] = reply_buffer[i];
3111
3112 if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3113 unsigned long flags;
3114 flags = claim_dma_lock();
3115 raw_cmd->length = fd_get_dma_residue();
3116 release_dma_lock(flags);
3117 }
3118
3119 if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) &&
3120 (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0)))
3121 raw_cmd->flags |= FD_RAW_FAILURE;
3122
3123 if (disk_change(current_drive))
3124 raw_cmd->flags |= FD_RAW_DISK_CHANGE;
3125 else
3126 raw_cmd->flags &= ~FD_RAW_DISK_CHANGE;
3127 if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER)
3128 motor_off_callback(current_drive);
3129
3130 if (raw_cmd->next &&
3131 (!(raw_cmd->flags & FD_RAW_FAILURE) ||
3132 !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) &&
3133 ((raw_cmd->flags & FD_RAW_FAILURE) ||
3134 !(raw_cmd->flags & FD_RAW_STOP_IF_SUCCESS))) {
3135 raw_cmd = raw_cmd->next;
3136 return;
3137 }
3138 }
3139 generic_done(flag);
3140}
3141
3142static struct cont_t raw_cmd_cont = {
3143 .interrupt = success_and_wakeup,
3144 .redo = floppy_start,
3145 .error = generic_failure,
3146 .done = raw_cmd_done
3147};
3148
3149static inline int raw_cmd_copyout(int cmd, char __user *param,
3150 struct floppy_raw_cmd *ptr)
3151{
3152 int ret;
3153
3154 while (ptr) {
3155 COPYOUT(*ptr);
3156 param += sizeof(struct floppy_raw_cmd);
3157 if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) {
3158 if (ptr->length >= 0
3159 && ptr->length <= ptr->buffer_length)
3160 ECALL(fd_copyout
3161 (ptr->data, ptr->kernel_data,
3162 ptr->buffer_length - ptr->length));
3163 }
3164 ptr = ptr->next;
3165 }
3166 return 0;
3167}
3168
3169static void raw_cmd_free(struct floppy_raw_cmd **ptr)
3170{
Jesper Juhl06f748c2007-10-16 23:30:57 -07003171 struct floppy_raw_cmd *next;
3172 struct floppy_raw_cmd *this;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173
3174 this = *ptr;
3175 *ptr = NULL;
3176 while (this) {
3177 if (this->buffer_length) {
3178 fd_dma_mem_free((unsigned long)this->kernel_data,
3179 this->buffer_length);
3180 this->buffer_length = 0;
3181 }
3182 next = this->next;
3183 kfree(this);
3184 this = next;
3185 }
3186}
3187
3188static inline int raw_cmd_copyin(int cmd, char __user *param,
3189 struct floppy_raw_cmd **rcmd)
3190{
3191 struct floppy_raw_cmd *ptr;
3192 int ret;
3193 int i;
3194
3195 *rcmd = NULL;
3196 while (1) {
3197 ptr = (struct floppy_raw_cmd *)
3198 kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER);
3199 if (!ptr)
3200 return -ENOMEM;
3201 *rcmd = ptr;
3202 COPYIN(*ptr);
3203 ptr->next = NULL;
3204 ptr->buffer_length = 0;
3205 param += sizeof(struct floppy_raw_cmd);
3206 if (ptr->cmd_count > 33)
3207 /* the command may now also take up the space
3208 * initially intended for the reply & the
3209 * reply count. Needed for long 82078 commands
3210 * such as RESTORE, which takes ... 17 command
3211 * bytes. Murphy's law #137: When you reserve
3212 * 16 bytes for a structure, you'll one day
3213 * discover that you really need 17...
3214 */
3215 return -EINVAL;
3216
3217 for (i = 0; i < 16; i++)
3218 ptr->reply[i] = 0;
3219 ptr->resultcode = 0;
3220 ptr->kernel_data = NULL;
3221
3222 if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
3223 if (ptr->length <= 0)
3224 return -EINVAL;
3225 ptr->kernel_data =
3226 (char *)fd_dma_mem_alloc(ptr->length);
3227 fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
3228 if (!ptr->kernel_data)
3229 return -ENOMEM;
3230 ptr->buffer_length = ptr->length;
3231 }
3232 if (ptr->flags & FD_RAW_WRITE)
3233 ECALL(fd_copyin(ptr->data, ptr->kernel_data,
3234 ptr->length));
3235 rcmd = &(ptr->next);
3236 if (!(ptr->flags & FD_RAW_MORE))
3237 return 0;
3238 ptr->rate &= 0x43;
3239 }
3240}
3241
3242static int raw_cmd_ioctl(int cmd, void __user *param)
3243{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 struct floppy_raw_cmd *my_raw_cmd;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003245 int drive;
3246 int ret2;
3247 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
3249 if (FDCS->rawcmd <= 1)
3250 FDCS->rawcmd = 1;
3251 for (drive = 0; drive < N_DRIVE; drive++) {
3252 if (FDC(drive) != fdc)
3253 continue;
3254 if (drive == current_drive) {
3255 if (UDRS->fd_ref > 1) {
3256 FDCS->rawcmd = 2;
3257 break;
3258 }
3259 } else if (UDRS->fd_ref) {
3260 FDCS->rawcmd = 2;
3261 break;
3262 }
3263 }
3264
3265 if (FDCS->reset)
3266 return -EIO;
3267
3268 ret = raw_cmd_copyin(cmd, param, &my_raw_cmd);
3269 if (ret) {
3270 raw_cmd_free(&my_raw_cmd);
3271 return ret;
3272 }
3273
3274 raw_cmd = my_raw_cmd;
3275 cont = &raw_cmd_cont;
3276 ret = wait_til_done(floppy_start, 1);
3277#ifdef DCL_DEBUG
3278 if (DP->flags & FD_DEBUG) {
3279 DPRINT("calling disk change from raw_cmd ioctl\n");
3280 }
3281#endif
3282
3283 if (ret != -EINTR && FDCS->reset)
3284 ret = -EIO;
3285
3286 DRS->track = NO_TRACK;
3287
3288 ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd);
3289 if (!ret)
3290 ret = ret2;
3291 raw_cmd_free(&my_raw_cmd);
3292 return ret;
3293}
3294
3295static int invalidate_drive(struct block_device *bdev)
3296{
3297 /* invalidate the buffer track to force a reread */
3298 set_bit((long)bdev->bd_disk->private_data, &fake_change);
3299 process_fd_request();
3300 check_disk_change(bdev);
3301 return 0;
3302}
3303
3304static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
3305 int drive, int type, struct block_device *bdev)
3306{
3307 int cnt;
3308
3309 /* sanity checking for parameters. */
3310 if (g->sect <= 0 ||
3311 g->head <= 0 ||
3312 g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
3313 /* check if reserved bits are set */
3314 (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0)
3315 return -EINVAL;
3316 if (type) {
3317 if (!capable(CAP_SYS_ADMIN))
3318 return -EPERM;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003319 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320 LOCK_FDC(drive, 1);
3321 floppy_type[type] = *g;
3322 floppy_type[type].name = "user format";
3323 for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
3324 floppy_sizes[cnt] = floppy_sizes[cnt + 0x80] =
3325 floppy_type[type].size + 1;
3326 process_fd_request();
3327 for (cnt = 0; cnt < N_DRIVE; cnt++) {
3328 struct block_device *bdev = opened_bdev[cnt];
3329 if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
3330 continue;
Christoph Hellwig2ef41632005-05-05 16:15:59 -07003331 __invalidate_device(bdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003333 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334 } else {
3335 int oldStretch;
3336 LOCK_FDC(drive, 1);
3337 if (cmd != FDDEFPRM)
3338 /* notice a disk change immediately, else
3339 * we lose our settings immediately*/
3340 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3341 oldStretch = g->stretch;
3342 user_params[drive] = *g;
3343 if (buffer_drive == drive)
3344 SUPBOUND(buffer_max, user_params[drive].sect);
3345 current_type[drive] = &user_params[drive];
3346 floppy_sizes[drive] = user_params[drive].size;
3347 if (cmd == FDDEFPRM)
3348 DRS->keep_data = -1;
3349 else
3350 DRS->keep_data = 1;
3351 /* invalidation. Invalidate only when needed, i.e.
3352 * when there are already sectors in the buffer cache
3353 * whose number will change. This is useful, because
3354 * mtools often changes the geometry of the disk after
3355 * looking at the boot block */
3356 if (DRS->maxblock > user_params[drive].sect ||
3357 DRS->maxtrack ||
3358 ((user_params[drive].sect ^ oldStretch) &
3359 (FD_SWAPSIDES | FD_ZEROBASED)))
3360 invalidate_drive(bdev);
3361 else
3362 process_fd_request();
3363 }
3364 return 0;
3365}
3366
3367/* handle obsolete ioctl's */
3368static int ioctl_table[] = {
3369 FDCLRPRM,
3370 FDSETPRM,
3371 FDDEFPRM,
3372 FDGETPRM,
3373 FDMSGON,
3374 FDMSGOFF,
3375 FDFMTBEG,
3376 FDFMTTRK,
3377 FDFMTEND,
3378 FDSETEMSGTRESH,
3379 FDFLUSH,
3380 FDSETMAXERRS,
3381 FDGETMAXERRS,
3382 FDGETDRVTYP,
3383 FDSETDRVPRM,
3384 FDGETDRVPRM,
3385 FDGETDRVSTAT,
3386 FDPOLLDRVSTAT,
3387 FDRESET,
3388 FDGETFDCSTAT,
3389 FDWERRORCLR,
3390 FDWERRORGET,
3391 FDRAWCMD,
3392 FDEJECT,
3393 FDTWADDLE
3394};
3395
3396static inline int normalize_ioctl(int *cmd, int *size)
3397{
3398 int i;
3399
3400 for (i = 0; i < ARRAY_SIZE(ioctl_table); i++) {
3401 if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)) {
3402 *size = _IOC_SIZE(*cmd);
3403 *cmd = ioctl_table[i];
3404 if (*size > _IOC_SIZE(*cmd)) {
3405 printk("ioctl not yet supported\n");
3406 return -EFAULT;
3407 }
3408 return 0;
3409 }
3410 }
3411 return -EINVAL;
3412}
3413
3414static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
3415{
3416 if (type)
3417 *g = &floppy_type[type];
3418 else {
3419 LOCK_FDC(drive, 0);
3420 CALL(poll_drive(0, 0));
3421 process_fd_request();
3422 *g = current_type[drive];
3423 }
3424 if (!*g)
3425 return -ENODEV;
3426 return 0;
3427}
3428
Christoph Hellwiga885c8c2006-01-08 01:02:50 -08003429static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
3430{
3431 int drive = (long)bdev->bd_disk->private_data;
3432 int type = ITYPE(drive_state[drive].fd_device);
3433 struct floppy_struct *g;
3434 int ret;
3435
3436 ret = get_floppy_geometry(drive, type, &g);
3437 if (ret)
3438 return ret;
3439
3440 geo->heads = g->head;
3441 geo->sectors = g->sect;
3442 geo->cylinders = g->track;
3443 return 0;
3444}
3445
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
3447 unsigned long param)
3448{
3449#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
3450#define OUT(c,x) case c: outparam = (const char *) (x); break
3451#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
3452
3453 int drive = (long)inode->i_bdev->bd_disk->private_data;
Jesper Juhl06f748c2007-10-16 23:30:57 -07003454 int type = ITYPE(UDRS->fd_device);
3455 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456 int ret;
3457 int size;
3458 union inparam {
3459 struct floppy_struct g; /* geometry */
3460 struct format_descr f;
3461 struct floppy_max_errors max_errors;
3462 struct floppy_drive_params dp;
3463 } inparam; /* parameters coming from user space */
3464 const char *outparam; /* parameters passed back to user space */
3465
3466 /* convert compatibility eject ioctls into floppy eject ioctl.
3467 * We do this in order to provide a means to eject floppy disks before
3468 * installing the new fdutils package */
3469 if (cmd == CDROMEJECT || /* CD-ROM eject */
3470 cmd == 0x6470 /* SunOS floppy eject */ ) {
3471 DPRINT("obsolete eject ioctl\n");
3472 DPRINT("please use floppycontrol --eject\n");
3473 cmd = FDEJECT;
3474 }
3475
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 /* convert the old style command into a new style command */
3477 if ((cmd & 0xff00) == 0x0200) {
3478 ECALL(normalize_ioctl(&cmd, &size));
3479 } else
3480 return -EINVAL;
3481
3482 /* permission checks */
3483 if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
3484 ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
3485 return -EPERM;
3486
3487 /* copyin */
3488 CLEARSTRUCT(&inparam);
3489 if (_IOC_DIR(cmd) & _IOC_WRITE)
3490 ECALL(fd_copyin((void __user *)param, &inparam, size))
3491
3492 switch (cmd) {
3493 case FDEJECT:
3494 if (UDRS->fd_ref != 1)
3495 /* somebody else has this drive open */
3496 return -EBUSY;
3497 LOCK_FDC(drive, 1);
3498
3499 /* do the actual eject. Fails on
3500 * non-Sparc architectures */
3501 ret = fd_eject(UNIT(drive));
3502
3503 USETF(FD_DISK_CHANGED);
3504 USETF(FD_VERIFY);
3505 process_fd_request();
3506 return ret;
3507 case FDCLRPRM:
3508 LOCK_FDC(drive, 1);
3509 current_type[drive] = NULL;
3510 floppy_sizes[drive] = MAX_DISK_SIZE << 1;
3511 UDRS->keep_data = 0;
3512 return invalidate_drive(inode->i_bdev);
3513 case FDSETPRM:
3514 case FDDEFPRM:
3515 return set_geometry(cmd, &inparam.g,
3516 drive, type, inode->i_bdev);
3517 case FDGETPRM:
3518 ECALL(get_floppy_geometry(drive, type,
3519 (struct floppy_struct **)
3520 &outparam));
3521 break;
3522
3523 case FDMSGON:
3524 UDP->flags |= FTD_MSG;
3525 return 0;
3526 case FDMSGOFF:
3527 UDP->flags &= ~FTD_MSG;
3528 return 0;
3529
3530 case FDFMTBEG:
3531 LOCK_FDC(drive, 1);
3532 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3533 ret = UDRS->flags;
3534 process_fd_request();
3535 if (ret & FD_VERIFY)
3536 return -ENODEV;
3537 if (!(ret & FD_DISK_WRITABLE))
3538 return -EROFS;
3539 return 0;
3540 case FDFMTTRK:
3541 if (UDRS->fd_ref != 1)
3542 return -EBUSY;
3543 return do_format(drive, &inparam.f);
3544 case FDFMTEND:
3545 case FDFLUSH:
3546 LOCK_FDC(drive, 1);
3547 return invalidate_drive(inode->i_bdev);
3548
3549 case FDSETEMSGTRESH:
3550 UDP->max_errors.reporting =
3551 (unsigned short)(param & 0x0f);
3552 return 0;
3553 OUT(FDGETMAXERRS, &UDP->max_errors);
3554 IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
3555
3556 case FDGETDRVTYP:
3557 outparam = drive_name(type, drive);
3558 SUPBOUND(size, strlen(outparam) + 1);
3559 break;
3560
3561 IN(FDSETDRVPRM, UDP, dp);
3562 OUT(FDGETDRVPRM, UDP);
3563
3564 case FDPOLLDRVSTAT:
3565 LOCK_FDC(drive, 1);
3566 CALL(poll_drive(1, FD_RAW_NEED_DISK));
3567 process_fd_request();
3568 /* fall through */
3569 OUT(FDGETDRVSTAT, UDRS);
3570
3571 case FDRESET:
3572 return user_reset_fdc(drive, (int)param, 1);
3573
3574 OUT(FDGETFDCSTAT, UFDCS);
3575
3576 case FDWERRORCLR:
3577 CLEARSTRUCT(UDRWE);
3578 return 0;
3579 OUT(FDWERRORGET, UDRWE);
3580
3581 case FDRAWCMD:
3582 if (type)
3583 return -EINVAL;
3584 LOCK_FDC(drive, 1);
3585 set_floppy(drive);
3586 CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
3587 process_fd_request();
3588 return i;
3589
3590 case FDTWADDLE:
3591 LOCK_FDC(drive, 1);
3592 twaddle();
3593 process_fd_request();
3594 return 0;
3595
3596 default:
3597 return -EINVAL;
3598 }
3599
3600 if (_IOC_DIR(cmd) & _IOC_READ)
3601 return fd_copyout((void __user *)param, outparam, size);
3602 else
3603 return 0;
3604#undef OUT
3605#undef IN
3606}
3607
3608static void __init config_types(void)
3609{
3610 int first = 1;
3611 int drive;
3612
3613 /* read drive info out of physical CMOS */
3614 drive = 0;
3615 if (!UDP->cmos)
3616 UDP->cmos = FLOPPY0_TYPE;
3617 drive = 1;
3618 if (!UDP->cmos && FLOPPY1_TYPE)
3619 UDP->cmos = FLOPPY1_TYPE;
3620
Jesper Juhl06f748c2007-10-16 23:30:57 -07003621 /* FIXME: additional physical CMOS drive detection should go here */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
3623 for (drive = 0; drive < N_DRIVE; drive++) {
3624 unsigned int type = UDP->cmos;
3625 struct floppy_drive_params *params;
3626 const char *name = NULL;
3627 static char temparea[32];
3628
Tobias Klauser945f3902006-01-08 01:05:11 -08003629 if (type < ARRAY_SIZE(default_drive_params)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 params = &default_drive_params[type].params;
3631 if (type) {
3632 name = default_drive_params[type].name;
3633 allowed_drive_mask |= 1 << drive;
3634 } else
3635 allowed_drive_mask &= ~(1 << drive);
3636 } else {
3637 params = &default_drive_params[0].params;
3638 sprintf(temparea, "unknown type %d (usb?)", type);
3639 name = temparea;
3640 }
3641 if (name) {
3642 const char *prepend = ",";
3643 if (first) {
3644 prepend = KERN_INFO "Floppy drive(s):";
3645 first = 0;
3646 }
3647 printk("%s fd%d is %s", prepend, drive, name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 }
3649 *UDP = *params;
3650 }
3651 if (!first)
3652 printk("\n");
3653}
3654
3655static int floppy_release(struct inode *inode, struct file *filp)
3656{
3657 int drive = (long)inode->i_bdev->bd_disk->private_data;
3658
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003659 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 if (UDRS->fd_ref < 0)
3661 UDRS->fd_ref = 0;
3662 else if (!UDRS->fd_ref--) {
3663 DPRINT("floppy_release with fd_ref == 0");
3664 UDRS->fd_ref = 0;
3665 }
3666 if (!UDRS->fd_ref)
3667 opened_bdev[drive] = NULL;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003668 mutex_unlock(&open_lock);
Ingo Molnar3e541a42006-07-03 00:24:23 -07003669
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 return 0;
3671}
3672
3673/*
3674 * floppy_open check for aliasing (/dev/fd0 can be the same as
3675 * /dev/PS0 etc), and disallows simultaneous access to the same
3676 * drive with different device numbers.
3677 */
3678static int floppy_open(struct inode *inode, struct file *filp)
3679{
3680 int drive = (long)inode->i_bdev->bd_disk->private_data;
3681 int old_dev;
3682 int try;
3683 int res = -EBUSY;
3684 char *tmp;
3685
3686 filp->private_data = (void *)0;
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003687 mutex_lock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 old_dev = UDRS->fd_device;
3689 if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
3690 goto out2;
3691
3692 if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
3693 USETF(FD_DISK_CHANGED);
3694 USETF(FD_VERIFY);
3695 }
3696
3697 if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
3698 goto out2;
3699
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700 if (filp->f_flags & O_EXCL)
3701 UDRS->fd_ref = -1;
3702 else
3703 UDRS->fd_ref++;
3704
3705 opened_bdev[drive] = inode->i_bdev;
3706
3707 res = -ENXIO;
3708
3709 if (!floppy_track_buffer) {
3710 /* if opening an ED drive, reserve a big buffer,
3711 * else reserve a small one */
3712 if ((UDP->cmos == 6) || (UDP->cmos == 5))
3713 try = 64; /* Only 48 actually useful */
3714 else
3715 try = 32; /* Only 24 actually useful */
3716
3717 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3718 if (!tmp && !floppy_track_buffer) {
3719 try >>= 1; /* buffer only one side */
3720 INFBOUND(try, 16);
3721 tmp = (char *)fd_dma_mem_alloc(1024 * try);
3722 }
3723 if (!tmp && !floppy_track_buffer) {
3724 fallback_on_nodma_alloc(&tmp, 2048 * try);
3725 }
3726 if (!tmp && !floppy_track_buffer) {
3727 DPRINT("Unable to allocate DMA memory\n");
3728 goto out;
3729 }
3730 if (floppy_track_buffer) {
3731 if (tmp)
3732 fd_dma_mem_free((unsigned long)tmp, try * 1024);
3733 } else {
3734 buffer_min = buffer_max = -1;
3735 floppy_track_buffer = tmp;
3736 max_buffer_sectors = try;
3737 }
3738 }
3739
3740 UDRS->fd_device = iminor(inode);
3741 set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
3742 if (old_dev != -1 && old_dev != iminor(inode)) {
3743 if (buffer_drive == drive)
3744 buffer_track = -1;
3745 }
3746
3747 /* Allow ioctls if we have write-permissions even if read-only open.
3748 * Needed so that programs such as fdrawcmd still can work on write
3749 * protected disks */
Christoph Hellwig8c744fb2005-11-08 21:35:04 -08003750 if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751 filp->private_data = (void *)8;
3752
3753 if (UFDCS->rawcmd == 1)
3754 UFDCS->rawcmd = 2;
3755
3756 if (!(filp->f_flags & O_NDELAY)) {
3757 if (filp->f_mode & 3) {
3758 UDRS->last_checked = 0;
3759 check_disk_change(inode->i_bdev);
3760 if (UTESTF(FD_DISK_CHANGED))
3761 goto out;
3762 }
3763 res = -EROFS;
3764 if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
3765 goto out;
3766 }
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003767 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768 return 0;
3769out:
3770 if (UDRS->fd_ref < 0)
3771 UDRS->fd_ref = 0;
3772 else
3773 UDRS->fd_ref--;
3774 if (!UDRS->fd_ref)
3775 opened_bdev[drive] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776out2:
Jes Sorensenb1c82b52006-03-23 03:00:26 -08003777 mutex_unlock(&open_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778 return res;
3779}
3780
3781/*
3782 * Check if the disk has been changed or if a change has been faked.
3783 */
3784static int check_floppy_change(struct gendisk *disk)
3785{
3786 int drive = (long)disk->private_data;
3787
3788 if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
3789 return 1;
3790
Marcelo Feitoza Parisi50297cb2006-03-28 01:56:44 -08003791 if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792 lock_fdc(drive, 0);
3793 poll_drive(0, 0);
3794 process_fd_request();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 }
3796
3797 if (UTESTF(FD_DISK_CHANGED) ||
3798 UTESTF(FD_VERIFY) ||
3799 test_bit(drive, &fake_change) ||
3800 (!ITYPE(UDRS->fd_device) && !current_type[drive]))
3801 return 1;
3802 return 0;
3803}
3804
3805/*
3806 * This implements "read block 0" for floppy_revalidate().
3807 * Needed for format autodetection, checking whether there is
3808 * a disk in the drive, and whether that disk is writable.
3809 */
3810
NeilBrown6712ecf2007-09-27 12:47:43 +02003811static void floppy_rb0_complete(struct bio *bio,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812 int err)
3813{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 complete((struct completion *)bio->bi_private);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815}
3816
3817static int __floppy_read_block_0(struct block_device *bdev)
3818{
3819 struct bio bio;
3820 struct bio_vec bio_vec;
3821 struct completion complete;
3822 struct page *page;
3823 size_t size;
3824
3825 page = alloc_page(GFP_NOIO);
3826 if (!page) {
3827 process_fd_request();
3828 return -ENOMEM;
3829 }
3830
3831 size = bdev->bd_block_size;
3832 if (!size)
3833 size = 1024;
3834
3835 bio_init(&bio);
3836 bio.bi_io_vec = &bio_vec;
3837 bio_vec.bv_page = page;
3838 bio_vec.bv_len = size;
3839 bio_vec.bv_offset = 0;
3840 bio.bi_vcnt = 1;
3841 bio.bi_idx = 0;
3842 bio.bi_size = size;
3843 bio.bi_bdev = bdev;
3844 bio.bi_sector = 0;
3845 init_completion(&complete);
3846 bio.bi_private = &complete;
3847 bio.bi_end_io = floppy_rb0_complete;
3848
3849 submit_bio(READ, &bio);
3850 generic_unplug_device(bdev_get_queue(bdev));
3851 process_fd_request();
3852 wait_for_completion(&complete);
3853
3854 __free_page(page);
3855
3856 return 0;
3857}
3858
3859/* revalidate the floppy disk, i.e. trigger format autodetection by reading
3860 * the bootblock (block 0). "Autodetection" is also needed to check whether
3861 * there is a disk in the drive at all... Thus we also do it for fixed
3862 * geometry formats */
3863static int floppy_revalidate(struct gendisk *disk)
3864{
3865 int drive = (long)disk->private_data;
3866#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device))
3867 int cf;
3868 int res = 0;
3869
3870 if (UTESTF(FD_DISK_CHANGED) ||
3871 UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) {
3872 if (usage_count == 0) {
3873 printk("VFS: revalidate called on non-open device.\n");
3874 return -EFAULT;
3875 }
3876 lock_fdc(drive, 0);
3877 cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
3878 if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
3879 process_fd_request(); /*already done by another thread */
3880 return 0;
3881 }
3882 UDRS->maxblock = 0;
3883 UDRS->maxtrack = 0;
3884 if (buffer_drive == drive)
3885 buffer_track = -1;
3886 clear_bit(drive, &fake_change);
3887 UCLEARF(FD_DISK_CHANGED);
3888 if (cf)
3889 UDRS->generation++;
3890 if (NO_GEOM) {
3891 /* auto-sensing */
3892 res = __floppy_read_block_0(opened_bdev[drive]);
3893 } else {
3894 if (cf)
3895 poll_drive(0, FD_RAW_NEED_DISK);
3896 process_fd_request();
3897 }
3898 }
3899 set_capacity(disk, floppy_sizes[UDRS->fd_device]);
3900 return res;
3901}
3902
3903static struct block_device_operations floppy_fops = {
Jesper Juhl06f748c2007-10-16 23:30:57 -07003904 .owner = THIS_MODULE,
3905 .open = floppy_open,
3906 .release = floppy_release,
3907 .ioctl = fd_ioctl,
3908 .getgeo = fd_getgeo,
3909 .media_changed = check_floppy_change,
3910 .revalidate_disk = floppy_revalidate,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913/*
3914 * Floppy Driver initialization
3915 * =============================
3916 */
3917
3918/* Determine the floppy disk controller type */
3919/* This routine was written by David C. Niemi */
3920static char __init get_fdc_version(void)
3921{
3922 int r;
3923
3924 output_byte(FD_DUMPREGS); /* 82072 and better know DUMPREGS */
3925 if (FDCS->reset)
3926 return FDC_NONE;
3927 if ((r = result()) <= 0x00)
3928 return FDC_NONE; /* No FDC present ??? */
3929 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3930 printk(KERN_INFO "FDC %d is an 8272A\n", fdc);
3931 return FDC_8272A; /* 8272a/765 don't know DUMPREGS */
3932 }
3933 if (r != 10) {
3934 printk
3935 ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
3936 fdc, r);
3937 return FDC_UNKNOWN;
3938 }
3939
3940 if (!fdc_configure()) {
3941 printk(KERN_INFO "FDC %d is an 82072\n", fdc);
3942 return FDC_82072; /* 82072 doesn't know CONFIGURE */
3943 }
3944
3945 output_byte(FD_PERPENDICULAR);
3946 if (need_more_output() == MORE_OUTPUT) {
3947 output_byte(0);
3948 } else {
3949 printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
3950 return FDC_82072A; /* 82072A as found on Sparcs. */
3951 }
3952
3953 output_byte(FD_UNLOCK);
3954 r = result();
3955 if ((r == 1) && (reply_buffer[0] == 0x80)) {
3956 printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc);
3957 return FDC_82077_ORIG; /* Pre-1991 82077, doesn't know
3958 * LOCK/UNLOCK */
3959 }
3960 if ((r != 1) || (reply_buffer[0] != 0x00)) {
3961 printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
3962 fdc, r);
3963 return FDC_UNKNOWN;
3964 }
3965 output_byte(FD_PARTID);
3966 r = result();
3967 if (r != 1) {
3968 printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
3969 fdc, r);
3970 return FDC_UNKNOWN;
3971 }
3972 if (reply_buffer[0] == 0x80) {
3973 printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc);
3974 return FDC_82077; /* Revised 82077AA passes all the tests */
3975 }
3976 switch (reply_buffer[0] >> 5) {
3977 case 0x0:
3978 /* Either a 82078-1 or a 82078SL running at 5Volt */
3979 printk(KERN_INFO "FDC %d is an 82078.\n", fdc);
3980 return FDC_82078;
3981 case 0x1:
3982 printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc);
3983 return FDC_82078;
3984 case 0x2:
3985 printk(KERN_INFO "FDC %d is a S82078B\n", fdc);
3986 return FDC_S82078B;
3987 case 0x3:
3988 printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n",
3989 fdc);
3990 return FDC_87306;
3991 default:
3992 printk(KERN_INFO
3993 "FDC %d init: 82078 variant with unknown PARTID=%d.\n",
3994 fdc, reply_buffer[0] >> 5);
3995 return FDC_82078_UNKN;
3996 }
3997} /* get_fdc_version */
3998
3999/* lilo configuration */
4000
4001static void __init floppy_set_flags(int *ints, int param, int param2)
4002{
4003 int i;
4004
4005 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4006 if (param)
4007 default_drive_params[i].params.flags |= param2;
4008 else
4009 default_drive_params[i].params.flags &= ~param2;
4010 }
4011 DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param);
4012}
4013
4014static void __init daring(int *ints, int param, int param2)
4015{
4016 int i;
4017
4018 for (i = 0; i < ARRAY_SIZE(default_drive_params); i++) {
4019 if (param) {
4020 default_drive_params[i].params.select_delay = 0;
4021 default_drive_params[i].params.flags |=
4022 FD_SILENT_DCL_CLEAR;
4023 } else {
4024 default_drive_params[i].params.select_delay =
4025 2 * HZ / 100;
4026 default_drive_params[i].params.flags &=
4027 ~FD_SILENT_DCL_CLEAR;
4028 }
4029 }
4030 DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken");
4031}
4032
4033static void __init set_cmos(int *ints, int dummy, int dummy2)
4034{
4035 int current_drive = 0;
4036
4037 if (ints[0] != 2) {
4038 DPRINT("wrong number of parameters for CMOS\n");
4039 return;
4040 }
4041 current_drive = ints[1];
4042 if (current_drive < 0 || current_drive >= 8) {
4043 DPRINT("bad drive for set_cmos\n");
4044 return;
4045 }
4046#if N_FDC > 1
4047 if (current_drive >= 4 && !FDC2)
4048 FDC2 = 0x370;
4049#endif
4050 DP->cmos = ints[2];
4051 DPRINT("setting CMOS code to %d\n", ints[2]);
4052}
4053
4054static struct param_table {
4055 const char *name;
4056 void (*fn) (int *ints, int param, int param2);
4057 int *var;
4058 int def_param;
4059 int param2;
4060} config_params[] __initdata = {
4061 {"allowed_drive_mask", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4062 {"all_drives", NULL, &allowed_drive_mask, 0xff, 0}, /* obsolete */
4063 {"asus_pci", NULL, &allowed_drive_mask, 0x33, 0},
4064 {"irq", NULL, &FLOPPY_IRQ, 6, 0},
4065 {"dma", NULL, &FLOPPY_DMA, 2, 0},
4066 {"daring", daring, NULL, 1, 0},
4067#if N_FDC > 1
4068 {"two_fdc", NULL, &FDC2, 0x370, 0},
4069 {"one_fdc", NULL, &FDC2, 0, 0},
4070#endif
4071 {"thinkpad", floppy_set_flags, NULL, 1, FD_INVERTED_DCL},
4072 {"broken_dcl", floppy_set_flags, NULL, 1, FD_BROKEN_DCL},
4073 {"messages", floppy_set_flags, NULL, 1, FTD_MSG},
4074 {"silent_dcl_clear", floppy_set_flags, NULL, 1, FD_SILENT_DCL_CLEAR},
4075 {"debug", floppy_set_flags, NULL, 1, FD_DEBUG},
4076 {"nodma", NULL, &can_use_virtual_dma, 1, 0},
4077 {"omnibook", NULL, &can_use_virtual_dma, 1, 0},
4078 {"yesdma", NULL, &can_use_virtual_dma, 0, 0},
4079 {"fifo_depth", NULL, &fifo_depth, 0xa, 0},
4080 {"nofifo", NULL, &no_fifo, 0x20, 0},
4081 {"usefifo", NULL, &no_fifo, 0, 0},
4082 {"cmos", set_cmos, NULL, 0, 0},
4083 {"slow", NULL, &slow_floppy, 1, 0},
4084 {"unexpected_interrupts", NULL, &print_unex, 1, 0},
4085 {"no_unexpected_interrupts", NULL, &print_unex, 0, 0},
4086 {"L40SX", NULL, &print_unex, 0, 0}
4087
4088 EXTRA_FLOPPY_PARAMS
4089};
4090
4091static int __init floppy_setup(char *str)
4092{
4093 int i;
4094 int param;
4095 int ints[11];
4096
4097 str = get_options(str, ARRAY_SIZE(ints), ints);
4098 if (str) {
4099 for (i = 0; i < ARRAY_SIZE(config_params); i++) {
4100 if (strcmp(str, config_params[i].name) == 0) {
4101 if (ints[0])
4102 param = ints[1];
4103 else
4104 param = config_params[i].def_param;
4105 if (config_params[i].fn)
4106 config_params[i].
4107 fn(ints, param,
4108 config_params[i].param2);
4109 if (config_params[i].var) {
4110 DPRINT("%s=%d\n", str, param);
4111 *config_params[i].var = param;
4112 }
4113 return 1;
4114 }
4115 }
4116 }
4117 if (str) {
4118 DPRINT("unknown floppy option [%s]\n", str);
4119
4120 DPRINT("allowed options are:");
4121 for (i = 0; i < ARRAY_SIZE(config_params); i++)
4122 printk(" %s", config_params[i].name);
4123 printk("\n");
4124 } else
4125 DPRINT("botched floppy option\n");
4126 DPRINT("Read Documentation/floppy.txt\n");
4127 return 0;
4128}
4129
4130static int have_no_fdc = -ENODEV;
4131
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004132static ssize_t floppy_cmos_show(struct device *dev,
4133 struct device_attribute *attr, char *buf)
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004134{
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004135 struct platform_device *p;
4136 int drive;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004137
Andrew Morton9a8af6b2005-07-27 17:37:34 -07004138 p = container_of(dev, struct platform_device,dev);
4139 drive = p->id;
4140 return sprintf(buf, "%X\n", UDP->cmos);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004141}
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004142DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
4143
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144static void floppy_device_release(struct device *dev)
4145{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146}
4147
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004148static struct platform_device floppy_device[N_DRIVE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
4150static struct kobject *floppy_find(dev_t dev, int *part, void *data)
4151{
4152 int drive = (*part & 3) | ((*part & 0x80) >> 5);
4153 if (drive >= N_DRIVE ||
4154 !(allowed_drive_mask & (1 << drive)) ||
4155 fdc_state[FDC(drive)].version == FDC_NONE)
4156 return NULL;
Tobias Klauser945f3902006-01-08 01:05:11 -08004157 if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004158 return NULL;
4159 *part = 0;
4160 return get_disk(disks[drive]);
4161}
4162
4163static int __init floppy_init(void)
4164{
4165 int i, unit, drive;
4166 int err, dr;
4167
Olaf Heringef16b512006-08-31 21:27:41 -07004168#if defined(CONFIG_PPC_MERGE)
4169 if (check_legacy_ioport(FDC1))
4170 return -ENODEV;
4171#endif
4172
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 raw_cmd = NULL;
4174
4175 for (dr = 0; dr < N_DRIVE; dr++) {
4176 disks[dr] = alloc_disk(1);
4177 if (!disks[dr]) {
4178 err = -ENOMEM;
4179 goto out_put_disk;
4180 }
4181
4182 disks[dr]->major = FLOPPY_MAJOR;
4183 disks[dr]->first_minor = TOMINOR(dr);
4184 disks[dr]->fops = &floppy_fops;
4185 sprintf(disks[dr]->disk_name, "fd%d", dr);
4186
4187 init_timer(&motor_off_timer[dr]);
4188 motor_off_timer[dr].data = dr;
4189 motor_off_timer[dr].function = motor_off_callback;
4190 }
4191
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192 err = register_blkdev(FLOPPY_MAJOR, "fd");
4193 if (err)
Greg Kroah-Hartman8ab5e4c2005-06-20 21:15:16 -07004194 goto out_put_disk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
4196 floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
4197 if (!floppy_queue) {
4198 err = -ENOMEM;
4199 goto out_unreg_blkdev;
4200 }
4201 blk_queue_max_sectors(floppy_queue, 64);
4202
4203 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
4204 floppy_find, NULL, NULL);
4205
4206 for (i = 0; i < 256; i++)
4207 if (ITYPE(i))
4208 floppy_sizes[i] = floppy_type[ITYPE(i)].size;
4209 else
4210 floppy_sizes[i] = MAX_DISK_SIZE << 1;
4211
4212 reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
4213 config_types();
4214
4215 for (i = 0; i < N_FDC; i++) {
4216 fdc = i;
4217 CLEARSTRUCT(FDCS);
4218 FDCS->dtr = -1;
4219 FDCS->dor = 0x4;
4220#if defined(__sparc__) || defined(__mc68000__)
4221 /*sparcs/sun3x don't have a DOR reset which we can fall back on to */
4222#ifdef __mc68000__
4223 if (MACH_IS_SUN3X)
4224#endif
4225 FDCS->version = FDC_82072A;
4226#endif
4227 }
4228
4229 use_virtual_dma = can_use_virtual_dma & 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 fdc_state[0].address = FDC1;
4231 if (fdc_state[0].address == -1) {
4232 del_timer(&fd_timeout);
4233 err = -ENODEV;
4234 goto out_unreg_region;
4235 }
4236#if N_FDC > 1
4237 fdc_state[1].address = FDC2;
4238#endif
4239
4240 fdc = 0; /* reset fdc in case of unexpected interrupt */
4241 err = floppy_grab_irq_and_dma();
4242 if (err) {
4243 del_timer(&fd_timeout);
4244 err = -EBUSY;
4245 goto out_unreg_region;
4246 }
4247
4248 /* initialise drive state */
4249 for (drive = 0; drive < N_DRIVE; drive++) {
4250 CLEARSTRUCT(UDRS);
4251 CLEARSTRUCT(UDRWE);
4252 USETF(FD_DISK_NEWCHANGE);
4253 USETF(FD_DISK_CHANGED);
4254 USETF(FD_VERIFY);
4255 UDRS->fd_device = -1;
4256 floppy_track_buffer = NULL;
4257 max_buffer_sectors = 0;
4258 }
4259 /*
4260 * Small 10 msec delay to let through any interrupt that
4261 * initialization might have triggered, to not
4262 * confuse detection:
4263 */
4264 msleep(10);
4265
4266 for (i = 0; i < N_FDC; i++) {
4267 fdc = i;
4268 FDCS->driver_version = FD_DRIVER_VERSION;
4269 for (unit = 0; unit < 4; unit++)
4270 FDCS->track[unit] = 0;
4271 if (FDCS->address == -1)
4272 continue;
4273 FDCS->rawcmd = 2;
4274 if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
4275 /* free ioports reserved by floppy_grab_irq_and_dma() */
4276 release_region(FDCS->address + 2, 4);
4277 release_region(FDCS->address + 7, 1);
4278 FDCS->address = -1;
4279 FDCS->version = FDC_NONE;
4280 continue;
4281 }
4282 /* Try to determine the floppy controller type */
4283 FDCS->version = get_fdc_version();
4284 if (FDCS->version == FDC_NONE) {
4285 /* free ioports reserved by floppy_grab_irq_and_dma() */
4286 release_region(FDCS->address + 2, 4);
4287 release_region(FDCS->address + 7, 1);
4288 FDCS->address = -1;
4289 continue;
4290 }
4291 if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
4292 can_use_virtual_dma = 0;
4293
4294 have_no_fdc = 0;
4295 /* Not all FDCs seem to be able to handle the version command
4296 * properly, so force a reset for the standard FDC clones,
4297 * to avoid interrupt garbage.
4298 */
4299 user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
4300 }
4301 fdc = 0;
4302 del_timer(&fd_timeout);
4303 current_drive = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304 initialising = 0;
4305 if (have_no_fdc) {
4306 DPRINT("no floppy controllers found\n");
4307 err = have_no_fdc;
4308 goto out_flush_work;
4309 }
4310
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 for (drive = 0; drive < N_DRIVE; drive++) {
4312 if (!(allowed_drive_mask & (1 << drive)))
4313 continue;
4314 if (fdc_state[FDC(drive)].version == FDC_NONE)
4315 continue;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004316
4317 floppy_device[drive].name = floppy_device_name;
4318 floppy_device[drive].id = drive;
4319 floppy_device[drive].dev.release = floppy_device_release;
4320
4321 err = platform_device_register(&floppy_device[drive]);
4322 if (err)
4323 goto out_flush_work;
4324
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004325 err = device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
4326 if (err)
4327 goto out_unreg_platform_dev;
4328
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 /* to be cleaned up... */
4330 disks[drive]->private_data = (void *)(long)drive;
4331 disks[drive]->queue = floppy_queue;
4332 disks[drive]->flags |= GENHD_FL_REMOVABLE;
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004333 disks[drive]->driverfs_dev = &floppy_device[drive].dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 add_disk(disks[drive]);
4335 }
4336
4337 return 0;
4338
Dmitriy Monakhov4ea1b0f2007-05-08 00:25:58 -07004339out_unreg_platform_dev:
4340 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341out_flush_work:
4342 flush_scheduled_work();
4343 if (usage_count)
4344 floppy_release_irq_and_dma();
4345out_unreg_region:
4346 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4347 blk_cleanup_queue(floppy_queue);
4348out_unreg_blkdev:
4349 unregister_blkdev(FLOPPY_MAJOR, "fd");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350out_put_disk:
4351 while (dr--) {
4352 del_timer(&motor_off_timer[dr]);
4353 put_disk(disks[dr]);
4354 }
4355 return err;
4356}
4357
4358static DEFINE_SPINLOCK(floppy_usage_lock);
4359
4360static int floppy_grab_irq_and_dma(void)
4361{
4362 unsigned long flags;
4363
4364 spin_lock_irqsave(&floppy_usage_lock, flags);
4365 if (usage_count++) {
4366 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4367 return 0;
4368 }
4369 spin_unlock_irqrestore(&floppy_usage_lock, flags);
Ingo Molnar6dc659d2006-03-26 01:36:54 -08004370
4371 /*
4372 * We might have scheduled a free_irq(), wait it to
4373 * drain first:
4374 */
4375 flush_scheduled_work();
4376
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 if (fd_request_irq()) {
4378 DPRINT("Unable to grab IRQ%d for the floppy driver\n",
4379 FLOPPY_IRQ);
4380 spin_lock_irqsave(&floppy_usage_lock, flags);
4381 usage_count--;
4382 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4383 return -1;
4384 }
4385 if (fd_request_dma()) {
4386 DPRINT("Unable to grab DMA%d for the floppy driver\n",
4387 FLOPPY_DMA);
Jan Beulich2e9c47c2007-10-16 23:27:32 -07004388 if (can_use_virtual_dma & 2)
4389 use_virtual_dma = can_use_virtual_dma = 1;
4390 if (!(can_use_virtual_dma & 1)) {
4391 fd_free_irq();
4392 spin_lock_irqsave(&floppy_usage_lock, flags);
4393 usage_count--;
4394 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4395 return -1;
4396 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397 }
4398
4399 for (fdc = 0; fdc < N_FDC; fdc++) {
4400 if (FDCS->address != -1) {
4401 if (!request_region(FDCS->address + 2, 4, "floppy")) {
4402 DPRINT("Floppy io-port 0x%04lx in use\n",
4403 FDCS->address + 2);
4404 goto cleanup1;
4405 }
4406 if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
4407 DPRINT("Floppy io-port 0x%04lx in use\n",
4408 FDCS->address + 7);
4409 goto cleanup2;
4410 }
4411 /* address + 6 is reserved, and may be taken by IDE.
4412 * Unfortunately, Adaptec doesn't know this :-(, */
4413 }
4414 }
4415 for (fdc = 0; fdc < N_FDC; fdc++) {
4416 if (FDCS->address != -1) {
4417 reset_fdc_info(1);
4418 fd_outb(FDCS->dor, FD_DOR);
4419 }
4420 }
4421 fdc = 0;
4422 set_dor(0, ~0, 8); /* avoid immediate interrupt */
4423
4424 for (fdc = 0; fdc < N_FDC; fdc++)
4425 if (FDCS->address != -1)
4426 fd_outb(FDCS->dor, FD_DOR);
4427 /*
Jesper Juhl06f748c2007-10-16 23:30:57 -07004428 * The driver will try and free resources and relies on us
4429 * to know if they were allocated or not.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 */
4431 fdc = 0;
4432 irqdma_allocated = 1;
4433 return 0;
4434cleanup2:
4435 release_region(FDCS->address + 2, 4);
4436cleanup1:
4437 fd_free_irq();
4438 fd_free_dma();
4439 while (--fdc >= 0) {
4440 release_region(FDCS->address + 2, 4);
4441 release_region(FDCS->address + 7, 1);
4442 }
4443 spin_lock_irqsave(&floppy_usage_lock, flags);
4444 usage_count--;
4445 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4446 return -1;
4447}
4448
4449static void floppy_release_irq_and_dma(void)
4450{
4451 int old_fdc;
4452#ifdef FLOPPY_SANITY_CHECK
4453#ifndef __sparc__
4454 int drive;
4455#endif
4456#endif
4457 long tmpsize;
4458 unsigned long tmpaddr;
4459 unsigned long flags;
4460
4461 spin_lock_irqsave(&floppy_usage_lock, flags);
4462 if (--usage_count) {
4463 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4464 return;
4465 }
4466 spin_unlock_irqrestore(&floppy_usage_lock, flags);
4467 if (irqdma_allocated) {
4468 fd_disable_dma();
4469 fd_free_dma();
Ingo Molnar3e541a42006-07-03 00:24:23 -07004470 fd_free_irq();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 irqdma_allocated = 0;
4472 }
4473 set_dor(0, ~0, 8);
4474#if N_FDC > 1
4475 set_dor(1, ~8, 0);
4476#endif
4477 floppy_enable_hlt();
4478
4479 if (floppy_track_buffer && max_buffer_sectors) {
4480 tmpsize = max_buffer_sectors * 1024;
4481 tmpaddr = (unsigned long)floppy_track_buffer;
4482 floppy_track_buffer = NULL;
4483 max_buffer_sectors = 0;
4484 buffer_min = buffer_max = -1;
4485 fd_dma_mem_free(tmpaddr, tmpsize);
4486 }
4487#ifdef FLOPPY_SANITY_CHECK
4488#ifndef __sparc__
4489 for (drive = 0; drive < N_FDC * 4; drive++)
4490 if (timer_pending(motor_off_timer + drive))
4491 printk("motor off timer %d still active\n", drive);
4492#endif
4493
4494 if (timer_pending(&fd_timeout))
4495 printk("floppy timer still active:%s\n", timeout_message);
4496 if (timer_pending(&fd_timer))
4497 printk("auxiliary floppy timer still active\n");
David Howells365970a2006-11-22 14:54:49 +00004498 if (work_pending(&floppy_work))
Linus Torvalds1da177e2005-04-16 15:20:36 -07004499 printk("work still pending\n");
4500#endif
4501 old_fdc = fdc;
4502 for (fdc = 0; fdc < N_FDC; fdc++)
4503 if (FDCS->address != -1) {
4504 release_region(FDCS->address + 2, 4);
4505 release_region(FDCS->address + 7, 1);
4506 }
4507 fdc = old_fdc;
4508}
4509
4510#ifdef MODULE
4511
4512static char *floppy;
4513
Linus Torvalds1da177e2005-04-16 15:20:36 -07004514static void __init parse_floppy_cfg_string(char *cfg)
4515{
4516 char *ptr;
4517
4518 while (*cfg) {
4519 for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ;
4520 if (*cfg) {
4521 *cfg = '\0';
4522 cfg++;
4523 }
4524 if (*ptr)
4525 floppy_setup(ptr);
4526 }
4527}
4528
Jon Schindler7afea3b2008-04-29 00:59:21 -07004529static int __init floppy_module_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530{
4531 if (floppy)
4532 parse_floppy_cfg_string(floppy);
4533 return floppy_init();
4534}
Jon Schindler7afea3b2008-04-29 00:59:21 -07004535module_init(floppy_module_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536
Jon Schindler7afea3b2008-04-29 00:59:21 -07004537static void __exit floppy_module_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538{
4539 int drive;
4540
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
4542 unregister_blkdev(FLOPPY_MAJOR, "fd");
4543
4544 for (drive = 0; drive < N_DRIVE; drive++) {
4545 del_timer_sync(&motor_off_timer[drive]);
4546
4547 if ((allowed_drive_mask & (1 << drive)) &&
4548 fdc_state[FDC(drive)].version != FDC_NONE) {
4549 del_gendisk(disks[drive]);
Hannes Reinecke94fd0db2005-07-15 10:09:25 +02004550 device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
4551 platform_device_unregister(&floppy_device[drive]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552 }
4553 put_disk(disks[drive]);
4554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555
4556 del_timer_sync(&fd_timeout);
4557 del_timer_sync(&fd_timer);
4558 blk_cleanup_queue(floppy_queue);
4559
4560 if (usage_count)
4561 floppy_release_irq_and_dma();
4562
4563 /* eject disk, if any */
4564 fd_eject(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565}
Jon Schindler7afea3b2008-04-29 00:59:21 -07004566module_exit(floppy_module_exit);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567
4568module_param(floppy, charp, 0);
4569module_param(FLOPPY_IRQ, int, 0);
4570module_param(FLOPPY_DMA, int, 0);
4571MODULE_AUTHOR("Alain L. Knaff");
4572MODULE_SUPPORTED_DEVICE("fd");
4573MODULE_LICENSE("GPL");
4574
4575#else
4576
4577__setup("floppy=", floppy_setup);
4578module_init(floppy_init)
4579#endif
4580
4581MODULE_ALIAS_BLOCKDEV_MAJOR(FLOPPY_MAJOR);