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