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