ia64/linux-2.6.18-xen.hg

view drivers/block/ataflop.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
1 /*
2 * drivers/block/ataflop.c
3 *
4 * Copyright (C) 1993 Greg Harp
5 * Atari Support by Bjoern Brauel, Roman Hodek
6 *
7 * Big cleanup Sep 11..14 1994 Roman Hodek:
8 * - Driver now works interrupt driven
9 * - Support for two drives; should work, but I cannot test that :-(
10 * - Reading is done in whole tracks and buffered to speed up things
11 * - Disk change detection and drive deselecting after motor-off
12 * similar to TOS
13 * - Autodetection of disk format (DD/HD); untested yet, because I
14 * don't have an HD drive :-(
15 *
16 * Fixes Nov 13 1994 Martin Schaller:
17 * - Autodetection works now
18 * - Support for 5 1/4'' disks
19 * - Removed drive type (unknown on atari)
20 * - Do seeks with 8 Mhz
21 *
22 * Changes by Andreas Schwab:
23 * - After errors in multiple read mode try again reading single sectors
24 * (Feb 1995):
25 * - Clean up error handling
26 * - Set blk_size for proper size checking
27 * - Initialize track register when testing presence of floppy
28 * - Implement some ioctl's
29 *
30 * Changes by Torsten Lang:
31 * - When probing the floppies we should add the FDCCMDADD_H flag since
32 * the FDC will otherwise wait forever when no disk is inserted...
33 *
34 * ++ Freddi Aschwanden (fa) 20.9.95 fixes for medusa:
35 * - MFPDELAY() after each FDC access -> atari
36 * - more/other disk formats
37 * - DMA to the block buffer directly if we have a 32bit DMA
38 * - for medusa, the step rate is always 3ms
39 * - on medusa, use only cache_push()
40 * Roman:
41 * - Make disk format numbering independent from minors
42 * - Let user set max. supported drive type (speeds up format
43 * detection, saves buffer space)
44 *
45 * Roman 10/15/95:
46 * - implement some more ioctls
47 * - disk formatting
48 *
49 * Andreas 95/12/12:
50 * - increase gap size at start of track for HD/ED disks
51 *
52 * Michael (MSch) 11/07/96:
53 * - implemented FDSETPRM and FDDEFPRM ioctl
54 *
55 * Andreas (97/03/19):
56 * - implemented missing BLK* ioctls
57 *
58 * Things left to do:
59 * - Formatting
60 * - Maybe a better strategy for disk change detection (does anyone
61 * know one?)
62 */
64 #include <linux/module.h>
66 #include <linux/fd.h>
67 #include <linux/delay.h>
68 #include <linux/init.h>
69 #include <linux/blkdev.h>
71 #include <asm/atafd.h>
72 #include <asm/atafdreg.h>
73 #include <asm/atariints.h>
74 #include <asm/atari_stdma.h>
75 #include <asm/atari_stram.h>
77 #define FD_MAX_UNITS 2
79 #undef DEBUG
81 static struct request_queue *floppy_queue;
83 #define QUEUE (floppy_queue)
84 #define CURRENT elv_next_request(floppy_queue)
86 /* Disk types: DD, HD, ED */
87 static struct atari_disk_type {
88 const char *name;
89 unsigned spt; /* sectors per track */
90 unsigned blocks; /* total number of blocks */
91 unsigned fdc_speed; /* fdc_speed setting */
92 unsigned stretch; /* track doubling ? */
93 } disk_type[] = {
94 { "d360", 9, 720, 0, 0}, /* 0: 360kB diskette */
95 { "D360", 9, 720, 0, 1}, /* 1: 360kb in 720k or 1.2MB drive */
96 { "D720", 9,1440, 0, 0}, /* 2: 720kb in 720k or 1.2MB drive */
97 { "D820", 10,1640, 0, 0}, /* 3: DD disk with 82 tracks/10 sectors */
98 /* formats above are probed for type DD */
99 #define MAX_TYPE_DD 3
100 { "h1200",15,2400, 3, 0}, /* 4: 1.2MB diskette */
101 { "H1440",18,2880, 3, 0}, /* 5: 1.4 MB diskette (HD) */
102 { "H1640",20,3280, 3, 0}, /* 6: 1.64MB diskette (fat HD) 82 tr 20 sec */
103 /* formats above are probed for types DD and HD */
104 #define MAX_TYPE_HD 6
105 { "E2880",36,5760, 3, 0}, /* 7: 2.8 MB diskette (ED) */
106 { "E3280",40,6560, 3, 0}, /* 8: 3.2 MB diskette (fat ED) 82 tr 40 sec */
107 /* formats above are probed for types DD, HD and ED */
108 #define MAX_TYPE_ED 8
109 /* types below are never autoprobed */
110 { "H1680",21,3360, 3, 0}, /* 9: 1.68MB diskette (fat HD) 80 tr 21 sec */
111 { "h410",10,820, 0, 1}, /* 10: 410k diskette 41 tr 10 sec, stretch */
112 { "h1476",18,2952, 3, 0}, /* 11: 1.48MB diskette 82 tr 18 sec */
113 { "H1722",21,3444, 3, 0}, /* 12: 1.72MB diskette 82 tr 21 sec */
114 { "h420",10,840, 0, 1}, /* 13: 420k diskette 42 tr 10 sec, stretch */
115 { "H830",10,1660, 0, 0}, /* 14: 820k diskette 83 tr 10 sec */
116 { "h1494",18,2952, 3, 0}, /* 15: 1.49MB diskette 83 tr 18 sec */
117 { "H1743",21,3486, 3, 0}, /* 16: 1.74MB diskette 83 tr 21 sec */
118 { "h880",11,1760, 0, 0}, /* 17: 880k diskette 80 tr 11 sec */
119 { "D1040",13,2080, 0, 0}, /* 18: 1.04MB diskette 80 tr 13 sec */
120 { "D1120",14,2240, 0, 0}, /* 19: 1.12MB diskette 80 tr 14 sec */
121 { "h1600",20,3200, 3, 0}, /* 20: 1.60MB diskette 80 tr 20 sec */
122 { "H1760",22,3520, 3, 0}, /* 21: 1.76MB diskette 80 tr 22 sec */
123 { "H1920",24,3840, 3, 0}, /* 22: 1.92MB diskette 80 tr 24 sec */
124 { "E3200",40,6400, 3, 0}, /* 23: 3.2MB diskette 80 tr 40 sec */
125 { "E3520",44,7040, 3, 0}, /* 24: 3.52MB diskette 80 tr 44 sec */
126 { "E3840",48,7680, 3, 0}, /* 25: 3.84MB diskette 80 tr 48 sec */
127 { "H1840",23,3680, 3, 0}, /* 26: 1.84MB diskette 80 tr 23 sec */
128 { "D800",10,1600, 0, 0}, /* 27: 800k diskette 80 tr 10 sec */
129 };
131 static int StartDiskType[] = {
132 MAX_TYPE_DD,
133 MAX_TYPE_HD,
134 MAX_TYPE_ED
135 };
137 #define TYPE_DD 0
138 #define TYPE_HD 1
139 #define TYPE_ED 2
141 static int DriveType = TYPE_HD;
143 static DEFINE_SPINLOCK(ataflop_lock);
145 /* Array for translating minors into disk formats */
146 static struct {
147 int index;
148 unsigned drive_types;
149 } minor2disktype[] = {
150 { 0, TYPE_DD }, /* 1: d360 */
151 { 4, TYPE_HD }, /* 2: h1200 */
152 { 1, TYPE_DD }, /* 3: D360 */
153 { 2, TYPE_DD }, /* 4: D720 */
154 { 1, TYPE_DD }, /* 5: h360 = D360 */
155 { 2, TYPE_DD }, /* 6: h720 = D720 */
156 { 5, TYPE_HD }, /* 7: H1440 */
157 { 7, TYPE_ED }, /* 8: E2880 */
158 /* some PC formats :-) */
159 { 8, TYPE_ED }, /* 9: E3280 <- was "CompaQ" == E2880 for PC */
160 { 5, TYPE_HD }, /* 10: h1440 = H1440 */
161 { 9, TYPE_HD }, /* 11: H1680 */
162 { 10, TYPE_DD }, /* 12: h410 */
163 { 3, TYPE_DD }, /* 13: H820 <- == D820, 82x10 */
164 { 11, TYPE_HD }, /* 14: h1476 */
165 { 12, TYPE_HD }, /* 15: H1722 */
166 { 13, TYPE_DD }, /* 16: h420 */
167 { 14, TYPE_DD }, /* 17: H830 */
168 { 15, TYPE_HD }, /* 18: h1494 */
169 { 16, TYPE_HD }, /* 19: H1743 */
170 { 17, TYPE_DD }, /* 20: h880 */
171 { 18, TYPE_DD }, /* 21: D1040 */
172 { 19, TYPE_DD }, /* 22: D1120 */
173 { 20, TYPE_HD }, /* 23: h1600 */
174 { 21, TYPE_HD }, /* 24: H1760 */
175 { 22, TYPE_HD }, /* 25: H1920 */
176 { 23, TYPE_ED }, /* 26: E3200 */
177 { 24, TYPE_ED }, /* 27: E3520 */
178 { 25, TYPE_ED }, /* 28: E3840 */
179 { 26, TYPE_HD }, /* 29: H1840 */
180 { 27, TYPE_DD }, /* 30: D800 */
181 { 6, TYPE_HD }, /* 31: H1640 <- was H1600 == h1600 for PC */
182 };
184 #define NUM_DISK_MINORS ARRAY_SIZE(minor2disktype)
186 /*
187 * Maximum disk size (in kilobytes). This default is used whenever the
188 * current disk size is unknown.
189 */
190 #define MAX_DISK_SIZE 3280
192 /*
193 * MSch: User-provided type information. 'drive' points to
194 * the respective entry of this array. Set by FDSETPRM ioctls.
195 */
196 static struct atari_disk_type user_params[FD_MAX_UNITS];
198 /*
199 * User-provided permanent type information. 'drive' points to
200 * the respective entry of this array. Set by FDDEFPRM ioctls,
201 * restored upon disk change by floppy_revalidate() if valid (as seen by
202 * default_params[].blocks > 0 - a bit in unit[].flags might be used for this?)
203 */
204 static struct atari_disk_type default_params[FD_MAX_UNITS];
206 /* current info on each unit */
207 static struct atari_floppy_struct {
208 int connected; /* !=0 : drive is connected */
209 int autoprobe; /* !=0 : do autoprobe */
211 struct atari_disk_type *disktype; /* current type of disk */
213 int track; /* current head position or -1 if
214 unknown */
215 unsigned int steprate; /* steprate setting */
216 unsigned int wpstat; /* current state of WP signal (for
217 disk change detection) */
218 int flags; /* flags */
219 struct gendisk *disk;
220 int ref;
221 int type;
222 } unit[FD_MAX_UNITS];
224 #define UD unit[drive]
225 #define UDT unit[drive].disktype
226 #define SUD unit[SelectedDrive]
227 #define SUDT unit[SelectedDrive].disktype
230 #define FDC_READ(reg) ({ \
231 /* unsigned long __flags; */ \
232 unsigned short __val; \
233 /* local_irq_save(__flags); */ \
234 dma_wd.dma_mode_status = 0x80 | (reg); \
235 udelay(25); \
236 __val = dma_wd.fdc_acces_seccount; \
237 MFPDELAY(); \
238 /* local_irq_restore(__flags); */ \
239 __val & 0xff; \
240 })
242 #define FDC_WRITE(reg,val) \
243 do { \
244 /* unsigned long __flags; */ \
245 /* local_irq_save(__flags); */ \
246 dma_wd.dma_mode_status = 0x80 | (reg); \
247 udelay(25); \
248 dma_wd.fdc_acces_seccount = (val); \
249 MFPDELAY(); \
250 /* local_irq_restore(__flags); */ \
251 } while(0)
254 /* Buffering variables:
255 * First, there is a DMA buffer in ST-RAM that is used for floppy DMA
256 * operations. Second, a track buffer is used to cache a whole track
257 * of the disk to save read operations. These are two separate buffers
258 * because that allows write operations without clearing the track buffer.
259 */
261 static int MaxSectors[] = {
262 11, 22, 44
263 };
264 static int BufferSize[] = {
265 15*512, 30*512, 60*512
266 };
268 #define BUFFER_SIZE (BufferSize[DriveType])
270 unsigned char *DMABuffer; /* buffer for writes */
271 static unsigned long PhysDMABuffer; /* physical address */
273 static int UseTrackbuffer = -1; /* Do track buffering? */
274 module_param(UseTrackbuffer, int, 0);
276 unsigned char *TrackBuffer; /* buffer for reads */
277 static unsigned long PhysTrackBuffer; /* physical address */
278 static int BufferDrive, BufferSide, BufferTrack;
279 static int read_track; /* non-zero if we are reading whole tracks */
281 #define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
282 #define IS_BUFFERED(drive,side,track) \
283 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
285 /*
286 * These are global variables, as that's the easiest way to give
287 * information to interrupts. They are the data used for the current
288 * request.
289 */
290 static int SelectedDrive = 0;
291 static int ReqCmd, ReqBlock;
292 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
293 static int HeadSettleFlag = 0;
294 static unsigned char *ReqData, *ReqBuffer;
295 static int MotorOn = 0, MotorOffTrys;
296 static int IsFormatting = 0, FormatError;
298 static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
299 module_param_array(UserSteprate, int, NULL, 0);
301 /* Synchronization of FDC access. */
302 static volatile int fdc_busy = 0;
303 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
304 static DECLARE_WAIT_QUEUE_HEAD(format_wait);
306 static unsigned long changed_floppies = 0xff, fake_change = 0;
307 #define CHECK_CHANGE_DELAY HZ/2
309 #define FD_MOTOR_OFF_DELAY (3*HZ)
310 #define FD_MOTOR_OFF_MAXTRY (10*20)
312 #define FLOPPY_TIMEOUT (6*HZ)
313 #define RECALIBRATE_ERRORS 4 /* After this many errors the drive
314 * will be recalibrated. */
315 #define MAX_ERRORS 8 /* After this many errors the driver
316 * will give up. */
319 /*
320 * The driver is trying to determine the correct media format
321 * while Probing is set. fd_rwsec_done() clears it after a
322 * successful access.
323 */
324 static int Probing = 0;
326 /* This flag is set when a dummy seek is necessary to make the WP
327 * status bit accessible.
328 */
329 static int NeedSeek = 0;
332 #ifdef DEBUG
333 #define DPRINT(a) printk a
334 #else
335 #define DPRINT(a)
336 #endif
338 /***************************** Prototypes *****************************/
340 static void fd_select_side( int side );
341 static void fd_select_drive( int drive );
342 static void fd_deselect( void );
343 static void fd_motor_off_timer( unsigned long dummy );
344 static void check_change( unsigned long dummy );
345 static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp);
346 static void fd_error( void );
347 static int do_format(int drive, int type, struct atari_format_descr *desc);
348 static void do_fd_action( int drive );
349 static void fd_calibrate( void );
350 static void fd_calibrate_done( int status );
351 static void fd_seek( void );
352 static void fd_seek_done( int status );
353 static void fd_rwsec( void );
354 static void fd_readtrack_check( unsigned long dummy );
355 static void fd_rwsec_done( int status );
356 static void fd_rwsec_done1(int status);
357 static void fd_writetrack( void );
358 static void fd_writetrack_done( int status );
359 static void fd_times_out( unsigned long dummy );
360 static void finish_fdc( void );
361 static void finish_fdc_done( int dummy );
362 static void setup_req_params( int drive );
363 static void redo_fd_request( void);
364 static int fd_ioctl( struct inode *inode, struct file *filp, unsigned int
365 cmd, unsigned long param);
366 static void fd_probe( int drive );
367 static int fd_test_drive_present( int drive );
368 static void config_types( void );
369 static int floppy_open( struct inode *inode, struct file *filp );
370 static int floppy_release( struct inode * inode, struct file * filp );
372 /************************* End of Prototypes **************************/
374 static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
375 static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
376 static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
377 static DEFINE_TIMER(fd_timer, check_change, 0, 0);
379 static inline void start_motor_off_timer(void)
380 {
381 mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY);
382 MotorOffTrys = 0;
383 }
385 static inline void start_check_change_timer( void )
386 {
387 mod_timer(&fd_timer, jiffies + CHECK_CHANGE_DELAY);
388 }
390 static inline void start_timeout(void)
391 {
392 mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT);
393 }
395 static inline void stop_timeout(void)
396 {
397 del_timer(&timeout_timer);
398 }
400 /* Select the side to use. */
402 static void fd_select_side( int side )
403 {
404 unsigned long flags;
406 /* protect against various other ints mucking around with the PSG */
407 local_irq_save(flags);
409 sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
410 sound_ym.wd_data = (side == 0) ? sound_ym.rd_data_reg_sel | 0x01 :
411 sound_ym.rd_data_reg_sel & 0xfe;
413 local_irq_restore(flags);
414 }
417 /* Select a drive, update the FDC's track register and set the correct
418 * clock speed for this disk's type.
419 */
421 static void fd_select_drive( int drive )
422 {
423 unsigned long flags;
424 unsigned char tmp;
426 if (drive == SelectedDrive)
427 return;
429 /* protect against various other ints mucking around with the PSG */
430 local_irq_save(flags);
431 sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
432 tmp = sound_ym.rd_data_reg_sel;
433 sound_ym.wd_data = (tmp | DSKDRVNONE) & ~(drive == 0 ? DSKDRV0 : DSKDRV1);
434 atari_dont_touch_floppy_select = 1;
435 local_irq_restore(flags);
437 /* restore track register to saved value */
438 FDC_WRITE( FDCREG_TRACK, UD.track );
439 udelay(25);
441 /* select 8/16 MHz */
442 if (UDT)
443 if (ATARIHW_PRESENT(FDCSPEED))
444 dma_wd.fdc_speed = UDT->fdc_speed;
446 SelectedDrive = drive;
447 }
450 /* Deselect both drives. */
452 static void fd_deselect( void )
453 {
454 unsigned long flags;
456 /* protect against various other ints mucking around with the PSG */
457 local_irq_save(flags);
458 atari_dont_touch_floppy_select = 0;
459 sound_ym.rd_data_reg_sel=14; /* Select PSG Port A */
460 sound_ym.wd_data = (sound_ym.rd_data_reg_sel |
461 (MACH_IS_FALCON ? 3 : 7)); /* no drives selected */
462 /* On Falcon, the drive B select line is used on the printer port, so
463 * leave it alone... */
464 SelectedDrive = -1;
465 local_irq_restore(flags);
466 }
469 /* This timer function deselects the drives when the FDC switched the
470 * motor off. The deselection cannot happen earlier because the FDC
471 * counts the index signals, which arrive only if one drive is selected.
472 */
474 static void fd_motor_off_timer( unsigned long dummy )
475 {
476 unsigned char status;
478 if (SelectedDrive < 0)
479 /* no drive selected, needn't deselect anyone */
480 return;
482 if (stdma_islocked())
483 goto retry;
485 status = FDC_READ( FDCREG_STATUS );
487 if (!(status & 0x80)) {
488 /* motor already turned off by FDC -> deselect drives */
489 MotorOn = 0;
490 fd_deselect();
491 return;
492 }
493 /* not yet off, try again */
495 retry:
496 /* Test again later; if tested too often, it seems there is no disk
497 * in the drive and the FDC will leave the motor on forever (or,
498 * at least until a disk is inserted). So we'll test only twice
499 * per second from then on...
500 */
501 mod_timer(&motor_off_timer,
502 jiffies + (MotorOffTrys++ < FD_MOTOR_OFF_MAXTRY ? HZ/20 : HZ/2));
503 }
506 /* This function is repeatedly called to detect disk changes (as good
507 * as possible) and keep track of the current state of the write protection.
508 */
510 static void check_change( unsigned long dummy )
511 {
512 static int drive = 0;
514 unsigned long flags;
515 unsigned char old_porta;
516 int stat;
518 if (++drive > 1 || !UD.connected)
519 drive = 0;
521 /* protect against various other ints mucking around with the PSG */
522 local_irq_save(flags);
524 if (!stdma_islocked()) {
525 sound_ym.rd_data_reg_sel = 14;
526 old_porta = sound_ym.rd_data_reg_sel;
527 sound_ym.wd_data = (old_porta | DSKDRVNONE) &
528 ~(drive == 0 ? DSKDRV0 : DSKDRV1);
529 stat = !!(FDC_READ( FDCREG_STATUS ) & FDCSTAT_WPROT);
530 sound_ym.wd_data = old_porta;
532 if (stat != UD.wpstat) {
533 DPRINT(( "wpstat[%d] = %d\n", drive, stat ));
534 UD.wpstat = stat;
535 set_bit (drive, &changed_floppies);
536 }
537 }
538 local_irq_restore(flags);
540 start_check_change_timer();
541 }
544 /* Handling of the Head Settling Flag: This flag should be set after each
545 * seek operation, because we don't use seeks with verify.
546 */
548 static inline void set_head_settle_flag(void)
549 {
550 HeadSettleFlag = FDCCMDADD_E;
551 }
553 static inline int get_head_settle_flag(void)
554 {
555 int tmp = HeadSettleFlag;
556 HeadSettleFlag = 0;
557 return( tmp );
558 }
560 static inline void copy_buffer(void *from, void *to)
561 {
562 ulong *p1 = (ulong *)from, *p2 = (ulong *)to;
563 int cnt;
565 for (cnt = 512/4; cnt; cnt--)
566 *p2++ = *p1++;
567 }
572 /* General Interrupt Handling */
574 static void (*FloppyIRQHandler)( int status ) = NULL;
576 static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp)
577 {
578 unsigned char status;
579 void (*handler)( int );
581 handler = xchg(&FloppyIRQHandler, NULL);
583 if (handler) {
584 nop();
585 status = FDC_READ( FDCREG_STATUS );
586 DPRINT(("FDC irq, status = %02x handler = %08lx\n",status,(unsigned long)handler));
587 handler( status );
588 }
589 else {
590 DPRINT(("FDC irq, no handler\n"));
591 }
592 return IRQ_HANDLED;
593 }
596 /* Error handling: If some error happened, retry some times, then
597 * recalibrate, then try again, and fail after MAX_ERRORS.
598 */
600 static void fd_error( void )
601 {
602 if (IsFormatting) {
603 IsFormatting = 0;
604 FormatError = 1;
605 wake_up( &format_wait );
606 return;
607 }
609 if (!CURRENT)
610 return;
612 CURRENT->errors++;
613 if (CURRENT->errors >= MAX_ERRORS) {
614 printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
615 end_request(CURRENT, 0);
616 }
617 else if (CURRENT->errors == RECALIBRATE_ERRORS) {
618 printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
619 if (SelectedDrive != -1)
620 SUD.track = -1;
621 }
622 redo_fd_request();
623 }
627 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
630 /* ---------- Formatting ---------- */
632 #define FILL(n,val) \
633 do { \
634 memset( p, val, n ); \
635 p += n; \
636 } while(0)
638 static int do_format(int drive, int type, struct atari_format_descr *desc)
639 {
640 unsigned char *p;
641 int sect, nsect;
642 unsigned long flags;
644 DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
645 drive, desc->track, desc->head, desc->sect_offset ));
647 local_irq_save(flags);
648 while( fdc_busy ) sleep_on( &fdc_wait );
649 fdc_busy = 1;
650 stdma_lock(floppy_irq, NULL);
651 atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
652 local_irq_restore(flags);
654 if (type) {
655 if (--type >= NUM_DISK_MINORS ||
656 minor2disktype[type].drive_types > DriveType) {
657 redo_fd_request();
658 return -EINVAL;
659 }
660 type = minor2disktype[type].index;
661 UDT = &disk_type[type];
662 }
664 if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
665 redo_fd_request();
666 return -EINVAL;
667 }
669 nsect = UDT->spt;
670 p = TrackBuffer;
671 /* The track buffer is used for the raw track data, so its
672 contents become invalid! */
673 BufferDrive = -1;
674 /* stop deselect timer */
675 del_timer( &motor_off_timer );
677 FILL( 60 * (nsect / 9), 0x4e );
678 for( sect = 0; sect < nsect; ++sect ) {
679 FILL( 12, 0 );
680 FILL( 3, 0xf5 );
681 *p++ = 0xfe;
682 *p++ = desc->track;
683 *p++ = desc->head;
684 *p++ = (nsect + sect - desc->sect_offset) % nsect + 1;
685 *p++ = 2;
686 *p++ = 0xf7;
687 FILL( 22, 0x4e );
688 FILL( 12, 0 );
689 FILL( 3, 0xf5 );
690 *p++ = 0xfb;
691 FILL( 512, 0xe5 );
692 *p++ = 0xf7;
693 FILL( 40, 0x4e );
694 }
695 FILL( TrackBuffer+BUFFER_SIZE-p, 0x4e );
697 IsFormatting = 1;
698 FormatError = 0;
699 ReqTrack = desc->track;
700 ReqSide = desc->head;
701 do_fd_action( drive );
703 sleep_on( &format_wait );
705 redo_fd_request();
706 return( FormatError ? -EIO : 0 );
707 }
710 /* do_fd_action() is the general procedure for a fd request: All
711 * required parameter settings (drive select, side select, track
712 * position) are checked and set if needed. For each of these
713 * parameters and the actual reading or writing exist two functions:
714 * one that starts the setting (or skips it if possible) and one
715 * callback for the "done" interrupt. Each done func calls the next
716 * set function to propagate the request down to fd_rwsec_done().
717 */
719 static void do_fd_action( int drive )
720 {
721 DPRINT(("do_fd_action\n"));
723 if (UseTrackbuffer && !IsFormatting) {
724 repeat:
725 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
726 if (ReqCmd == READ) {
727 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
728 if (++ReqCnt < CURRENT->current_nr_sectors) {
729 /* read next sector */
730 setup_req_params( drive );
731 goto repeat;
732 }
733 else {
734 /* all sectors finished */
735 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
736 CURRENT->sector += CURRENT->current_nr_sectors;
737 end_request(CURRENT, 1);
738 redo_fd_request();
739 return;
740 }
741 }
742 else {
743 /* cmd == WRITE, pay attention to track buffer
744 * consistency! */
745 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
746 }
747 }
748 }
750 if (SelectedDrive != drive)
751 fd_select_drive( drive );
753 if (UD.track == -1)
754 fd_calibrate();
755 else if (UD.track != ReqTrack << UDT->stretch)
756 fd_seek();
757 else if (IsFormatting)
758 fd_writetrack();
759 else
760 fd_rwsec();
761 }
764 /* Seek to track 0 if the current track is unknown */
766 static void fd_calibrate( void )
767 {
768 if (SUD.track >= 0) {
769 fd_calibrate_done( 0 );
770 return;
771 }
773 if (ATARIHW_PRESENT(FDCSPEED))
774 dma_wd.fdc_speed = 0; /* always seek with 8 Mhz */;
775 DPRINT(("fd_calibrate\n"));
776 SET_IRQ_HANDLER( fd_calibrate_done );
777 /* we can't verify, since the speed may be incorrect */
778 FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | SUD.steprate );
780 NeedSeek = 1;
781 MotorOn = 1;
782 start_timeout();
783 /* wait for IRQ */
784 }
787 static void fd_calibrate_done( int status )
788 {
789 DPRINT(("fd_calibrate_done()\n"));
790 stop_timeout();
792 /* set the correct speed now */
793 if (ATARIHW_PRESENT(FDCSPEED))
794 dma_wd.fdc_speed = SUDT->fdc_speed;
795 if (status & FDCSTAT_RECNF) {
796 printk(KERN_ERR "fd%d: restore failed\n", SelectedDrive );
797 fd_error();
798 }
799 else {
800 SUD.track = 0;
801 fd_seek();
802 }
803 }
806 /* Seek the drive to the requested track. The drive must have been
807 * calibrated at some point before this.
808 */
810 static void fd_seek( void )
811 {
812 if (SUD.track == ReqTrack << SUDT->stretch) {
813 fd_seek_done( 0 );
814 return;
815 }
817 if (ATARIHW_PRESENT(FDCSPEED)) {
818 dma_wd.fdc_speed = 0; /* always seek witch 8 Mhz */
819 MFPDELAY();
820 }
822 DPRINT(("fd_seek() to track %d\n",ReqTrack));
823 FDC_WRITE( FDCREG_DATA, ReqTrack << SUDT->stretch);
824 udelay(25);
825 SET_IRQ_HANDLER( fd_seek_done );
826 FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK | SUD.steprate );
828 MotorOn = 1;
829 set_head_settle_flag();
830 start_timeout();
831 /* wait for IRQ */
832 }
835 static void fd_seek_done( int status )
836 {
837 DPRINT(("fd_seek_done()\n"));
838 stop_timeout();
840 /* set the correct speed */
841 if (ATARIHW_PRESENT(FDCSPEED))
842 dma_wd.fdc_speed = SUDT->fdc_speed;
843 if (status & FDCSTAT_RECNF) {
844 printk(KERN_ERR "fd%d: seek error (to track %d)\n",
845 SelectedDrive, ReqTrack );
846 /* we don't know exactly which track we are on now! */
847 SUD.track = -1;
848 fd_error();
849 }
850 else {
851 SUD.track = ReqTrack << SUDT->stretch;
852 NeedSeek = 0;
853 if (IsFormatting)
854 fd_writetrack();
855 else
856 fd_rwsec();
857 }
858 }
861 /* This does the actual reading/writing after positioning the head
862 * over the correct track.
863 */
865 static int MultReadInProgress = 0;
868 static void fd_rwsec( void )
869 {
870 unsigned long paddr, flags;
871 unsigned int rwflag, old_motoron;
872 unsigned int track;
874 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' ));
875 if (ReqCmd == WRITE) {
876 if (ATARIHW_PRESENT(EXTD_DMA)) {
877 paddr = virt_to_phys(ReqData);
878 }
879 else {
880 copy_buffer( ReqData, DMABuffer );
881 paddr = PhysDMABuffer;
882 }
883 dma_cache_maintenance( paddr, 512, 1 );
884 rwflag = 0x100;
885 }
886 else {
887 if (read_track)
888 paddr = PhysTrackBuffer;
889 else
890 paddr = ATARIHW_PRESENT(EXTD_DMA) ?
891 virt_to_phys(ReqData) : PhysDMABuffer;
892 rwflag = 0;
893 }
895 fd_select_side( ReqSide );
897 /* Start sector of this operation */
898 FDC_WRITE( FDCREG_SECTOR, read_track ? 1 : ReqSector );
899 MFPDELAY();
900 /* Cheat for track if stretch != 0 */
901 if (SUDT->stretch) {
902 track = FDC_READ( FDCREG_TRACK);
903 MFPDELAY();
904 FDC_WRITE( FDCREG_TRACK, track >> SUDT->stretch);
905 }
906 udelay(25);
908 /* Setup DMA */
909 local_irq_save(flags);
910 dma_wd.dma_lo = (unsigned char)paddr;
911 MFPDELAY();
912 paddr >>= 8;
913 dma_wd.dma_md = (unsigned char)paddr;
914 MFPDELAY();
915 paddr >>= 8;
916 if (ATARIHW_PRESENT(EXTD_DMA))
917 st_dma_ext_dmahi = (unsigned short)paddr;
918 else
919 dma_wd.dma_hi = (unsigned char)paddr;
920 MFPDELAY();
921 local_irq_restore(flags);
923 /* Clear FIFO and switch DMA to correct mode */
924 dma_wd.dma_mode_status = 0x90 | rwflag;
925 MFPDELAY();
926 dma_wd.dma_mode_status = 0x90 | (rwflag ^ 0x100);
927 MFPDELAY();
928 dma_wd.dma_mode_status = 0x90 | rwflag;
929 MFPDELAY();
931 /* How many sectors for DMA */
932 dma_wd.fdc_acces_seccount = read_track ? SUDT->spt : 1;
934 udelay(25);
936 /* Start operation */
937 dma_wd.dma_mode_status = FDCSELREG_STP | rwflag;
938 udelay(25);
939 SET_IRQ_HANDLER( fd_rwsec_done );
940 dma_wd.fdc_acces_seccount =
941 (get_head_settle_flag() |
942 (rwflag ? FDCCMD_WRSEC : (FDCCMD_RDSEC | (read_track ? FDCCMDADD_M : 0))));
944 old_motoron = MotorOn;
945 MotorOn = 1;
946 NeedSeek = 1;
947 /* wait for interrupt */
949 if (read_track) {
950 /* If reading a whole track, wait about one disk rotation and
951 * then check if all sectors are read. The FDC will even
952 * search for the first non-existent sector and need 1 sec to
953 * recognise that it isn't present :-(
954 */
955 MultReadInProgress = 1;
956 mod_timer(&readtrack_timer,
957 /* 1 rot. + 5 rot.s if motor was off */
958 jiffies + HZ/5 + (old_motoron ? 0 : HZ));
959 }
960 start_timeout();
961 }
964 static void fd_readtrack_check( unsigned long dummy )
965 {
966 unsigned long flags, addr, addr2;
968 local_irq_save(flags);
970 if (!MultReadInProgress) {
971 /* This prevents a race condition that could arise if the
972 * interrupt is triggered while the calling of this timer
973 * callback function takes place. The IRQ function then has
974 * already cleared 'MultReadInProgress' when flow of control
975 * gets here.
976 */
977 local_irq_restore(flags);
978 return;
979 }
981 /* get the current DMA address */
982 /* ++ f.a. read twice to avoid being fooled by switcher */
983 addr = 0;
984 do {
985 addr2 = addr;
986 addr = dma_wd.dma_lo & 0xff;
987 MFPDELAY();
988 addr |= (dma_wd.dma_md & 0xff) << 8;
989 MFPDELAY();
990 if (ATARIHW_PRESENT( EXTD_DMA ))
991 addr |= (st_dma_ext_dmahi & 0xffff) << 16;
992 else
993 addr |= (dma_wd.dma_hi & 0xff) << 16;
994 MFPDELAY();
995 } while(addr != addr2);
997 if (addr >= PhysTrackBuffer + SUDT->spt*512) {
998 /* already read enough data, force an FDC interrupt to stop
999 * the read operation
1000 */
1001 SET_IRQ_HANDLER( NULL );
1002 MultReadInProgress = 0;
1003 local_irq_restore(flags);
1004 DPRINT(("fd_readtrack_check(): done\n"));
1005 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1006 udelay(25);
1008 /* No error until now -- the FDC would have interrupted
1009 * otherwise!
1010 */
1011 fd_rwsec_done1(0);
1013 else {
1014 /* not yet finished, wait another tenth rotation */
1015 local_irq_restore(flags);
1016 DPRINT(("fd_readtrack_check(): not yet finished\n"));
1017 mod_timer(&readtrack_timer, jiffies + HZ/5/10);
1022 static void fd_rwsec_done( int status )
1024 DPRINT(("fd_rwsec_done()\n"));
1026 if (read_track) {
1027 del_timer(&readtrack_timer);
1028 if (!MultReadInProgress)
1029 return;
1030 MultReadInProgress = 0;
1032 fd_rwsec_done1(status);
1035 static void fd_rwsec_done1(int status)
1037 unsigned int track;
1039 stop_timeout();
1041 /* Correct the track if stretch != 0 */
1042 if (SUDT->stretch) {
1043 track = FDC_READ( FDCREG_TRACK);
1044 MFPDELAY();
1045 FDC_WRITE( FDCREG_TRACK, track << SUDT->stretch);
1048 if (!UseTrackbuffer) {
1049 dma_wd.dma_mode_status = 0x90;
1050 MFPDELAY();
1051 if (!(dma_wd.dma_mode_status & 0x01)) {
1052 printk(KERN_ERR "fd%d: DMA error\n", SelectedDrive );
1053 goto err_end;
1056 MFPDELAY();
1058 if (ReqCmd == WRITE && (status & FDCSTAT_WPROT)) {
1059 printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
1060 goto err_end;
1062 if ((status & FDCSTAT_RECNF) &&
1063 /* RECNF is no error after a multiple read when the FDC
1064 searched for a non-existent sector! */
1065 !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) {
1066 if (Probing) {
1067 if (SUDT > disk_type) {
1068 if (SUDT[-1].blocks > ReqBlock) {
1069 /* try another disk type */
1070 SUDT--;
1071 set_capacity(unit[SelectedDrive].disk,
1072 SUDT->blocks);
1073 } else
1074 Probing = 0;
1076 else {
1077 if (SUD.flags & FTD_MSG)
1078 printk(KERN_INFO "fd%d: Auto-detected floppy type %s\n",
1079 SelectedDrive, SUDT->name );
1080 Probing=0;
1082 } else {
1083 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
1084 if (SUD.autoprobe) {
1085 SUDT = disk_type + StartDiskType[DriveType];
1086 set_capacity(unit[SelectedDrive].disk,
1087 SUDT->blocks);
1088 Probing = 1;
1091 if (Probing) {
1092 if (ATARIHW_PRESENT(FDCSPEED)) {
1093 dma_wd.fdc_speed = SUDT->fdc_speed;
1094 MFPDELAY();
1096 setup_req_params( SelectedDrive );
1097 BufferDrive = -1;
1098 do_fd_action( SelectedDrive );
1099 return;
1102 printk(KERN_ERR "fd%d: sector %d not found (side %d, track %d)\n",
1103 SelectedDrive, FDC_READ (FDCREG_SECTOR), ReqSide, ReqTrack );
1104 goto err_end;
1106 if (status & FDCSTAT_CRC) {
1107 printk(KERN_ERR "fd%d: CRC error (side %d, track %d, sector %d)\n",
1108 SelectedDrive, ReqSide, ReqTrack, FDC_READ (FDCREG_SECTOR) );
1109 goto err_end;
1111 if (status & FDCSTAT_LOST) {
1112 printk(KERN_ERR "fd%d: lost data (side %d, track %d, sector %d)\n",
1113 SelectedDrive, ReqSide, ReqTrack, FDC_READ (FDCREG_SECTOR) );
1114 goto err_end;
1117 Probing = 0;
1119 if (ReqCmd == READ) {
1120 if (!read_track) {
1121 void *addr;
1122 addr = ATARIHW_PRESENT( EXTD_DMA ) ? ReqData : DMABuffer;
1123 dma_cache_maintenance( virt_to_phys(addr), 512, 0 );
1124 if (!ATARIHW_PRESENT( EXTD_DMA ))
1125 copy_buffer (addr, ReqData);
1126 } else {
1127 dma_cache_maintenance( PhysTrackBuffer, MaxSectors[DriveType] * 512, 0 );
1128 BufferDrive = SelectedDrive;
1129 BufferSide = ReqSide;
1130 BufferTrack = ReqTrack;
1131 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1135 if (++ReqCnt < CURRENT->current_nr_sectors) {
1136 /* read next sector */
1137 setup_req_params( SelectedDrive );
1138 do_fd_action( SelectedDrive );
1140 else {
1141 /* all sectors finished */
1142 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1143 CURRENT->sector += CURRENT->current_nr_sectors;
1144 end_request(CURRENT, 1);
1145 redo_fd_request();
1147 return;
1149 err_end:
1150 BufferDrive = -1;
1151 fd_error();
1155 static void fd_writetrack( void )
1157 unsigned long paddr, flags;
1158 unsigned int track;
1160 DPRINT(("fd_writetrack() Tr=%d Si=%d\n", ReqTrack, ReqSide ));
1162 paddr = PhysTrackBuffer;
1163 dma_cache_maintenance( paddr, BUFFER_SIZE, 1 );
1165 fd_select_side( ReqSide );
1167 /* Cheat for track if stretch != 0 */
1168 if (SUDT->stretch) {
1169 track = FDC_READ( FDCREG_TRACK);
1170 MFPDELAY();
1171 FDC_WRITE(FDCREG_TRACK,track >> SUDT->stretch);
1173 udelay(40);
1175 /* Setup DMA */
1176 local_irq_save(flags);
1177 dma_wd.dma_lo = (unsigned char)paddr;
1178 MFPDELAY();
1179 paddr >>= 8;
1180 dma_wd.dma_md = (unsigned char)paddr;
1181 MFPDELAY();
1182 paddr >>= 8;
1183 if (ATARIHW_PRESENT( EXTD_DMA ))
1184 st_dma_ext_dmahi = (unsigned short)paddr;
1185 else
1186 dma_wd.dma_hi = (unsigned char)paddr;
1187 MFPDELAY();
1188 local_irq_restore(flags);
1190 /* Clear FIFO and switch DMA to correct mode */
1191 dma_wd.dma_mode_status = 0x190;
1192 MFPDELAY();
1193 dma_wd.dma_mode_status = 0x90;
1194 MFPDELAY();
1195 dma_wd.dma_mode_status = 0x190;
1196 MFPDELAY();
1198 /* How many sectors for DMA */
1199 dma_wd.fdc_acces_seccount = BUFFER_SIZE/512;
1200 udelay(40);
1202 /* Start operation */
1203 dma_wd.dma_mode_status = FDCSELREG_STP | 0x100;
1204 udelay(40);
1205 SET_IRQ_HANDLER( fd_writetrack_done );
1206 dma_wd.fdc_acces_seccount = FDCCMD_WRTRA | get_head_settle_flag();
1208 MotorOn = 1;
1209 start_timeout();
1210 /* wait for interrupt */
1214 static void fd_writetrack_done( int status )
1216 DPRINT(("fd_writetrack_done()\n"));
1218 stop_timeout();
1220 if (status & FDCSTAT_WPROT) {
1221 printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
1222 goto err_end;
1224 if (status & FDCSTAT_LOST) {
1225 printk(KERN_ERR "fd%d: lost data (side %d, track %d)\n",
1226 SelectedDrive, ReqSide, ReqTrack );
1227 goto err_end;
1230 wake_up( &format_wait );
1231 return;
1233 err_end:
1234 fd_error();
1237 static void fd_times_out( unsigned long dummy )
1239 atari_disable_irq( IRQ_MFP_FDC );
1240 if (!FloppyIRQHandler) goto end; /* int occurred after timer was fired, but
1241 * before we came here... */
1243 SET_IRQ_HANDLER( NULL );
1244 /* If the timeout occurred while the readtrack_check timer was
1245 * active, we need to cancel it, else bad things will happen */
1246 if (UseTrackbuffer)
1247 del_timer( &readtrack_timer );
1248 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1249 udelay( 25 );
1251 printk(KERN_ERR "floppy timeout\n" );
1252 fd_error();
1253 end:
1254 atari_enable_irq( IRQ_MFP_FDC );
1258 /* The (noop) seek operation here is needed to make the WP bit in the
1259 * FDC status register accessible for check_change. If the last disk
1260 * operation would have been a RDSEC, this bit would always read as 0
1261 * no matter what :-( To save time, the seek goes to the track we're
1262 * already on.
1263 */
1265 static void finish_fdc( void )
1267 if (!NeedSeek) {
1268 finish_fdc_done( 0 );
1270 else {
1271 DPRINT(("finish_fdc: dummy seek started\n"));
1272 FDC_WRITE (FDCREG_DATA, SUD.track);
1273 SET_IRQ_HANDLER( finish_fdc_done );
1274 FDC_WRITE (FDCREG_CMD, FDCCMD_SEEK);
1275 MotorOn = 1;
1276 start_timeout();
1277 /* we must wait for the IRQ here, because the ST-DMA
1278 is released immediately afterwards and the interrupt
1279 may be delivered to the wrong driver. */
1284 static void finish_fdc_done( int dummy )
1286 unsigned long flags;
1288 DPRINT(("finish_fdc_done entered\n"));
1289 stop_timeout();
1290 NeedSeek = 0;
1292 if (timer_pending(&fd_timer) && time_before(fd_timer.expires, jiffies + 5))
1293 /* If the check for a disk change is done too early after this
1294 * last seek command, the WP bit still reads wrong :-((
1295 */
1296 mod_timer(&fd_timer, jiffies + 5);
1297 else
1298 start_check_change_timer();
1299 start_motor_off_timer();
1301 local_irq_save(flags);
1302 stdma_release();
1303 fdc_busy = 0;
1304 wake_up( &fdc_wait );
1305 local_irq_restore(flags);
1307 DPRINT(("finish_fdc() finished\n"));
1310 /* The detection of disk changes is a dark chapter in Atari history :-(
1311 * Because the "Drive ready" signal isn't present in the Atari
1312 * hardware, one has to rely on the "Write Protect". This works fine,
1313 * as long as no write protected disks are used. TOS solves this
1314 * problem by introducing tri-state logic ("maybe changed") and
1315 * looking at the serial number in block 0. This isn't possible for
1316 * Linux, since the floppy driver can't make assumptions about the
1317 * filesystem used on the disk and thus the contents of block 0. I've
1318 * chosen the method to always say "The disk was changed" if it is
1319 * unsure whether it was. This implies that every open or mount
1320 * invalidates the disk buffers if you work with write protected
1321 * disks. But at least this is better than working with incorrect data
1322 * due to unrecognised disk changes.
1323 */
1325 static int check_floppy_change(struct gendisk *disk)
1327 struct atari_floppy_struct *p = disk->private_data;
1328 unsigned int drive = p - unit;
1329 if (test_bit (drive, &fake_change)) {
1330 /* simulated change (e.g. after formatting) */
1331 return 1;
1333 if (test_bit (drive, &changed_floppies)) {
1334 /* surely changed (the WP signal changed at least once) */
1335 return 1;
1337 if (UD.wpstat) {
1338 /* WP is on -> could be changed: to be sure, buffers should be
1339 * invalidated...
1340 */
1341 return 1;
1344 return 0;
1347 static int floppy_revalidate(struct gendisk *disk)
1349 struct atari_floppy_struct *p = disk->private_data;
1350 unsigned int drive = p - unit;
1352 if (test_bit(drive, &changed_floppies) ||
1353 test_bit(drive, &fake_change) ||
1354 p->disktype == 0) {
1355 if (UD.flags & FTD_MSG)
1356 printk(KERN_ERR "floppy: clear format %p!\n", UDT);
1357 BufferDrive = -1;
1358 clear_bit(drive, &fake_change);
1359 clear_bit(drive, &changed_floppies);
1360 /* MSch: clearing geometry makes sense only for autoprobe
1361 formats, for 'permanent user-defined' parameter:
1362 restore default_params[] here if flagged valid! */
1363 if (default_params[drive].blocks == 0)
1364 UDT = NULL;
1365 else
1366 UDT = &default_params[drive];
1368 return 0;
1372 /* This sets up the global variables describing the current request. */
1374 static void setup_req_params( int drive )
1376 int block = ReqBlock + ReqCnt;
1378 ReqTrack = block / UDT->spt;
1379 ReqSector = block - ReqTrack * UDT->spt + 1;
1380 ReqSide = ReqTrack & 1;
1381 ReqTrack >>= 1;
1382 ReqData = ReqBuffer + 512 * ReqCnt;
1384 if (UseTrackbuffer)
1385 read_track = (ReqCmd == READ && CURRENT->errors == 0);
1386 else
1387 read_track = 0;
1389 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n",ReqSide,
1390 ReqTrack, ReqSector, (unsigned long)ReqData ));
1394 static void redo_fd_request(void)
1396 int drive, type;
1397 struct atari_floppy_struct *floppy;
1399 DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n",
1400 CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "",
1401 CURRENT ? CURRENT->sector : 0 ));
1403 IsFormatting = 0;
1405 repeat:
1407 if (!CURRENT)
1408 goto the_end;
1410 floppy = CURRENT->rq_disk->private_data;
1411 drive = floppy - unit;
1412 type = floppy->type;
1414 if (!UD.connected) {
1415 /* drive not connected */
1416 printk(KERN_ERR "Unknown Device: fd%d\n", drive );
1417 end_request(CURRENT, 0);
1418 goto repeat;
1421 if (type == 0) {
1422 if (!UDT) {
1423 Probing = 1;
1424 UDT = disk_type + StartDiskType[DriveType];
1425 set_capacity(floppy->disk, UDT->blocks);
1426 UD.autoprobe = 1;
1429 else {
1430 /* user supplied disk type */
1431 if (--type >= NUM_DISK_MINORS) {
1432 printk(KERN_WARNING "fd%d: invalid disk format", drive );
1433 end_request(CURRENT, 0);
1434 goto repeat;
1436 if (minor2disktype[type].drive_types > DriveType) {
1437 printk(KERN_WARNING "fd%d: unsupported disk format", drive );
1438 end_request(CURRENT, 0);
1439 goto repeat;
1441 type = minor2disktype[type].index;
1442 UDT = &disk_type[type];
1443 set_capacity(floppy->disk, UDT->blocks);
1444 UD.autoprobe = 0;
1447 if (CURRENT->sector + 1 > UDT->blocks) {
1448 end_request(CURRENT, 0);
1449 goto repeat;
1452 /* stop deselect timer */
1453 del_timer( &motor_off_timer );
1455 ReqCnt = 0;
1456 ReqCmd = rq_data_dir(CURRENT);
1457 ReqBlock = CURRENT->sector;
1458 ReqBuffer = CURRENT->buffer;
1459 setup_req_params( drive );
1460 do_fd_action( drive );
1462 return;
1464 the_end:
1465 finish_fdc();
1469 void do_fd_request(request_queue_t * q)
1471 unsigned long flags;
1473 DPRINT(("do_fd_request for pid %d\n",current->pid));
1474 while( fdc_busy ) sleep_on( &fdc_wait );
1475 fdc_busy = 1;
1476 stdma_lock(floppy_irq, NULL);
1478 atari_disable_irq( IRQ_MFP_FDC );
1479 local_save_flags(flags); /* The request function is called with ints
1480 local_irq_disable(); * disabled... so must save the IPL for later */
1481 redo_fd_request();
1482 local_irq_restore(flags);
1483 atari_enable_irq( IRQ_MFP_FDC );
1486 static int fd_ioctl(struct inode *inode, struct file *filp,
1487 unsigned int cmd, unsigned long param)
1489 struct gendisk *disk = inode->i_bdev->bd_disk;
1490 struct atari_floppy_struct *floppy = disk->private_data;
1491 int drive = floppy - unit;
1492 int type = floppy->type;
1493 struct atari_format_descr fmt_desc;
1494 struct atari_disk_type *dtp;
1495 struct floppy_struct getprm;
1496 int settype;
1497 struct floppy_struct setprm;
1498 void __user *argp = (void __user *)param;
1500 switch (cmd) {
1501 case FDGETPRM:
1502 if (type) {
1503 if (--type >= NUM_DISK_MINORS)
1504 return -ENODEV;
1505 if (minor2disktype[type].drive_types > DriveType)
1506 return -ENODEV;
1507 type = minor2disktype[type].index;
1508 dtp = &disk_type[type];
1509 if (UD.flags & FTD_MSG)
1510 printk (KERN_ERR "floppy%d: found dtp %p name %s!\n",
1511 drive, dtp, dtp->name);
1513 else {
1514 if (!UDT)
1515 return -ENXIO;
1516 else
1517 dtp = UDT;
1519 memset((void *)&getprm, 0, sizeof(getprm));
1520 getprm.size = dtp->blocks;
1521 getprm.sect = dtp->spt;
1522 getprm.head = 2;
1523 getprm.track = dtp->blocks/dtp->spt/2;
1524 getprm.stretch = dtp->stretch;
1525 if (copy_to_user(argp, &getprm, sizeof(getprm)))
1526 return -EFAULT;
1527 return 0;
1529 switch (cmd) {
1530 case FDSETPRM:
1531 case FDDEFPRM:
1532 /*
1533 * MSch 7/96: simple 'set geometry' case: just set the
1534 * 'default' device params (minor == 0).
1535 * Currently, the drive geometry is cleared after each
1536 * disk change and subsequent revalidate()! simple
1537 * implementation of FDDEFPRM: save geometry from a
1538 * FDDEFPRM call and restore it in floppy_revalidate() !
1539 */
1541 /* get the parameters from user space */
1542 if (floppy->ref != 1 && floppy->ref != -1)
1543 return -EBUSY;
1544 if (copy_from_user(&setprm, argp, sizeof(setprm)))
1545 return -EFAULT;
1546 /*
1547 * first of all: check for floppy change and revalidate,
1548 * or the next access will revalidate - and clear UDT :-(
1549 */
1551 if (check_floppy_change(disk))
1552 floppy_revalidate(disk);
1554 if (UD.flags & FTD_MSG)
1555 printk (KERN_INFO "floppy%d: setting size %d spt %d str %d!\n",
1556 drive, setprm.size, setprm.sect, setprm.stretch);
1558 /* what if type > 0 here? Overwrite specified entry ? */
1559 if (type) {
1560 /* refuse to re-set a predefined type for now */
1561 redo_fd_request();
1562 return -EINVAL;
1565 /*
1566 * type == 0: first look for a matching entry in the type list,
1567 * and set the UD.disktype field to use the perdefined entry.
1568 * TODO: add user-defined format to head of autoprobe list ?
1569 * Useful to include the user-type for future autodetection!
1570 */
1572 for (settype = 0; settype < NUM_DISK_MINORS; settype++) {
1573 int setidx = 0;
1574 if (minor2disktype[settype].drive_types > DriveType) {
1575 /* skip this one, invalid for drive ... */
1576 continue;
1578 setidx = minor2disktype[settype].index;
1579 dtp = &disk_type[setidx];
1581 /* found matching entry ?? */
1582 if ( dtp->blocks == setprm.size
1583 && dtp->spt == setprm.sect
1584 && dtp->stretch == setprm.stretch ) {
1585 if (UD.flags & FTD_MSG)
1586 printk (KERN_INFO "floppy%d: setting %s %p!\n",
1587 drive, dtp->name, dtp);
1588 UDT = dtp;
1589 set_capacity(floppy->disk, UDT->blocks);
1591 if (cmd == FDDEFPRM) {
1592 /* save settings as permanent default type */
1593 default_params[drive].name = dtp->name;
1594 default_params[drive].spt = dtp->spt;
1595 default_params[drive].blocks = dtp->blocks;
1596 default_params[drive].fdc_speed = dtp->fdc_speed;
1597 default_params[drive].stretch = dtp->stretch;
1600 return 0;
1605 /* no matching disk type found above - setting user_params */
1607 if (cmd == FDDEFPRM) {
1608 /* set permanent type */
1609 dtp = &default_params[drive];
1610 } else
1611 /* set user type (reset by disk change!) */
1612 dtp = &user_params[drive];
1614 dtp->name = "user format";
1615 dtp->blocks = setprm.size;
1616 dtp->spt = setprm.sect;
1617 if (setprm.sect > 14)
1618 dtp->fdc_speed = 3;
1619 else
1620 dtp->fdc_speed = 0;
1621 dtp->stretch = setprm.stretch;
1623 if (UD.flags & FTD_MSG)
1624 printk (KERN_INFO "floppy%d: blk %d spt %d str %d!\n",
1625 drive, dtp->blocks, dtp->spt, dtp->stretch);
1627 /* sanity check */
1628 if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 ||
1629 setprm.head != 2) {
1630 redo_fd_request();
1631 return -EINVAL;
1634 UDT = dtp;
1635 set_capacity(floppy->disk, UDT->blocks);
1637 return 0;
1638 case FDMSGON:
1639 UD.flags |= FTD_MSG;
1640 return 0;
1641 case FDMSGOFF:
1642 UD.flags &= ~FTD_MSG;
1643 return 0;
1644 case FDSETEMSGTRESH:
1645 return -EINVAL;
1646 case FDFMTBEG:
1647 return 0;
1648 case FDFMTTRK:
1649 if (floppy->ref != 1 && floppy->ref != -1)
1650 return -EBUSY;
1651 if (copy_from_user(&fmt_desc, argp, sizeof(fmt_desc)))
1652 return -EFAULT;
1653 return do_format(drive, type, &fmt_desc);
1654 case FDCLRPRM:
1655 UDT = NULL;
1656 /* MSch: invalidate default_params */
1657 default_params[drive].blocks = 0;
1658 set_capacity(floppy->disk, MAX_DISK_SIZE * 2);
1659 case FDFMTEND:
1660 case FDFLUSH:
1661 /* invalidate the buffer track to force a reread */
1662 BufferDrive = -1;
1663 set_bit(drive, &fake_change);
1664 check_disk_change(inode->i_bdev);
1665 return 0;
1666 default:
1667 return -EINVAL;
1672 /* Initialize the 'unit' variable for drive 'drive' */
1674 static void __init fd_probe( int drive )
1676 UD.connected = 0;
1677 UDT = NULL;
1679 if (!fd_test_drive_present( drive ))
1680 return;
1682 UD.connected = 1;
1683 UD.track = 0;
1684 switch( UserSteprate[drive] ) {
1685 case 2:
1686 UD.steprate = FDCSTEP_2;
1687 break;
1688 case 3:
1689 UD.steprate = FDCSTEP_3;
1690 break;
1691 case 6:
1692 UD.steprate = FDCSTEP_6;
1693 break;
1694 case 12:
1695 UD.steprate = FDCSTEP_12;
1696 break;
1697 default: /* should be -1 for "not set by user" */
1698 if (ATARIHW_PRESENT( FDCSPEED ) || MACH_IS_MEDUSA)
1699 UD.steprate = FDCSTEP_3;
1700 else
1701 UD.steprate = FDCSTEP_6;
1702 break;
1704 MotorOn = 1; /* from probe restore operation! */
1708 /* This function tests the physical presence of a floppy drive (not
1709 * whether a disk is inserted). This is done by issuing a restore
1710 * command, waiting max. 2 seconds (that should be enough to move the
1711 * head across the whole disk) and looking at the state of the "TR00"
1712 * signal. This should now be raised if there is a drive connected
1713 * (and there is no hardware failure :-) Otherwise, the drive is
1714 * declared absent.
1715 */
1717 static int __init fd_test_drive_present( int drive )
1719 unsigned long timeout;
1720 unsigned char status;
1721 int ok;
1723 if (drive >= (MACH_IS_FALCON ? 1 : 2)) return( 0 );
1724 fd_select_drive( drive );
1726 /* disable interrupt temporarily */
1727 atari_turnoff_irq( IRQ_MFP_FDC );
1728 FDC_WRITE (FDCREG_TRACK, 0xff00);
1729 FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 );
1731 timeout = jiffies + 2*HZ+HZ/2;
1732 while (time_before(jiffies, timeout))
1733 if (!(mfp.par_dt_reg & 0x20))
1734 break;
1736 status = FDC_READ( FDCREG_STATUS );
1737 ok = (status & FDCSTAT_TR00) != 0;
1739 /* force interrupt to abort restore operation (FDC would try
1740 * about 50 seconds!) */
1741 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1742 udelay(500);
1743 status = FDC_READ( FDCREG_STATUS );
1744 udelay(20);
1746 if (ok) {
1747 /* dummy seek command to make WP bit accessible */
1748 FDC_WRITE( FDCREG_DATA, 0 );
1749 FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK );
1750 while( mfp.par_dt_reg & 0x20 )
1752 status = FDC_READ( FDCREG_STATUS );
1755 atari_turnon_irq( IRQ_MFP_FDC );
1756 return( ok );
1760 /* Look how many and which kind of drives are connected. If there are
1761 * floppies, additionally start the disk-change and motor-off timers.
1762 */
1764 static void __init config_types( void )
1766 int drive, cnt = 0;
1768 /* for probing drives, set the FDC speed to 8 MHz */
1769 if (ATARIHW_PRESENT(FDCSPEED))
1770 dma_wd.fdc_speed = 0;
1772 printk(KERN_INFO "Probing floppy drive(s):\n");
1773 for( drive = 0; drive < FD_MAX_UNITS; drive++ ) {
1774 fd_probe( drive );
1775 if (UD.connected) {
1776 printk(KERN_INFO "fd%d\n", drive);
1777 ++cnt;
1781 if (FDC_READ( FDCREG_STATUS ) & FDCSTAT_BUSY) {
1782 /* If FDC is still busy from probing, give it another FORCI
1783 * command to abort the operation. If this isn't done, the FDC
1784 * will interrupt later and its IRQ line stays low, because
1785 * the status register isn't read. And this will block any
1786 * interrupts on this IRQ line :-(
1787 */
1788 FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
1789 udelay(500);
1790 FDC_READ( FDCREG_STATUS );
1791 udelay(20);
1794 if (cnt > 0) {
1795 start_motor_off_timer();
1796 if (cnt == 1) fd_select_drive( 0 );
1797 start_check_change_timer();
1801 /*
1802 * floppy_open check for aliasing (/dev/fd0 can be the same as
1803 * /dev/PS0 etc), and disallows simultaneous access to the same
1804 * drive with different device numbers.
1805 */
1807 static int floppy_open( struct inode *inode, struct file *filp )
1809 struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
1810 int type = iminor(inode) >> 2;
1812 DPRINT(("fd_open: type=%d\n",type));
1813 if (p->ref && p->type != type)
1814 return -EBUSY;
1816 if (p->ref == -1 || (p->ref && filp->f_flags & O_EXCL))
1817 return -EBUSY;
1819 if (filp->f_flags & O_EXCL)
1820 p->ref = -1;
1821 else
1822 p->ref++;
1824 p->type = type;
1826 if (filp->f_flags & O_NDELAY)
1827 return 0;
1829 if (filp->f_mode & 3) {
1830 check_disk_change(inode->i_bdev);
1831 if (filp->f_mode & 2) {
1832 if (p->wpstat) {
1833 if (p->ref < 0)
1834 p->ref = 0;
1835 else
1836 p->ref--;
1837 floppy_release(inode, filp);
1838 return -EROFS;
1842 return 0;
1846 static int floppy_release( struct inode * inode, struct file * filp )
1848 struct atari_floppy_struct *p = inode->i_bdev->bd_disk->private_data;
1849 if (p->ref < 0)
1850 p->ref = 0;
1851 else if (!p->ref--) {
1852 printk(KERN_ERR "floppy_release with fd_ref == 0");
1853 p->ref = 0;
1855 return 0;
1858 static struct block_device_operations floppy_fops = {
1859 .owner = THIS_MODULE,
1860 .open = floppy_open,
1861 .release = floppy_release,
1862 .ioctl = fd_ioctl,
1863 .media_changed = check_floppy_change,
1864 .revalidate_disk= floppy_revalidate,
1865 };
1867 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
1869 int drive = *part & 3;
1870 int type = *part >> 2;
1871 if (drive >= FD_MAX_UNITS || type > NUM_DISK_MINORS)
1872 return NULL;
1873 *part = 0;
1874 return get_disk(unit[drive].disk);
1877 static int __init atari_floppy_init (void)
1879 int i;
1881 if (!MACH_IS_ATARI)
1882 /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
1883 return -ENXIO;
1885 if (MACH_IS_HADES)
1886 /* Hades doesn't have Atari-compatible floppy */
1887 return -ENXIO;
1889 if (register_blkdev(FLOPPY_MAJOR,"fd"))
1890 return -EBUSY;
1892 for (i = 0; i < FD_MAX_UNITS; i++) {
1893 unit[i].disk = alloc_disk(1);
1894 if (!unit[i].disk)
1895 goto Enomem;
1898 if (UseTrackbuffer < 0)
1899 /* not set by user -> use default: for now, we turn
1900 track buffering off for all Medusas, though it
1901 could be used with ones that have a counter
1902 card. But the test is too hard :-( */
1903 UseTrackbuffer = !MACH_IS_MEDUSA;
1905 /* initialize variables */
1906 SelectedDrive = -1;
1907 BufferDrive = -1;
1909 DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop");
1910 if (!DMABuffer) {
1911 printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
1912 goto Enomem;
1914 TrackBuffer = DMABuffer + 512;
1915 PhysDMABuffer = virt_to_phys(DMABuffer);
1916 PhysTrackBuffer = virt_to_phys(TrackBuffer);
1917 BufferDrive = BufferSide = BufferTrack = -1;
1919 floppy_queue = blk_init_queue(do_fd_request, &ataflop_lock);
1920 if (!floppy_queue)
1921 goto Enomem;
1923 for (i = 0; i < FD_MAX_UNITS; i++) {
1924 unit[i].track = -1;
1925 unit[i].flags = 0;
1926 unit[i].disk->major = FLOPPY_MAJOR;
1927 unit[i].disk->first_minor = i;
1928 sprintf(unit[i].disk->disk_name, "fd%d", i);
1929 unit[i].disk->fops = &floppy_fops;
1930 unit[i].disk->private_data = &unit[i];
1931 unit[i].disk->queue = floppy_queue;
1932 set_capacity(unit[i].disk, MAX_DISK_SIZE * 2);
1933 add_disk(unit[i].disk);
1936 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
1937 floppy_find, NULL, NULL);
1939 printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
1940 DriveType == 0 ? 'D' : DriveType == 1 ? 'H' : 'E',
1941 UseTrackbuffer ? "" : "no ");
1942 config_types();
1944 return 0;
1945 Enomem:
1946 while (i--)
1947 put_disk(unit[i].disk);
1948 if (floppy_queue)
1949 blk_cleanup_queue(floppy_queue);
1950 unregister_blkdev(FLOPPY_MAJOR, "fd");
1951 return -ENOMEM;
1954 #ifndef MODULE
1955 static int __init atari_floppy_setup(char *str)
1957 int ints[3 + FD_MAX_UNITS];
1958 int i;
1960 if (!MACH_IS_ATARI)
1961 return 0;
1963 str = get_options(str, 3 + FD_MAX_UNITS, ints);
1965 if (ints[0] < 1) {
1966 printk(KERN_ERR "ataflop_setup: no arguments!\n" );
1967 return 0;
1969 else if (ints[0] > 2+FD_MAX_UNITS) {
1970 printk(KERN_ERR "ataflop_setup: too many arguments\n" );
1973 if (ints[1] < 0 || ints[1] > 2)
1974 printk(KERN_ERR "ataflop_setup: bad drive type\n" );
1975 else
1976 DriveType = ints[1];
1978 if (ints[0] >= 2)
1979 UseTrackbuffer = (ints[2] > 0);
1981 for( i = 3; i <= ints[0] && i-3 < FD_MAX_UNITS; ++i ) {
1982 if (ints[i] != 2 && ints[i] != 3 && ints[i] != 6 && ints[i] != 12)
1983 printk(KERN_ERR "ataflop_setup: bad steprate\n" );
1984 else
1985 UserSteprate[i-3] = ints[i];
1987 return 1;
1990 __setup("floppy=", atari_floppy_setup);
1991 #endif
1993 static void __exit atari_floppy_exit(void)
1995 int i;
1996 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
1997 for (i = 0; i < FD_MAX_UNITS; i++) {
1998 del_gendisk(unit[i].disk);
1999 put_disk(unit[i].disk);
2001 unregister_blkdev(FLOPPY_MAJOR, "fd");
2003 blk_cleanup_queue(floppy_queue);
2004 del_timer_sync(&fd_timer);
2005 atari_stram_free( DMABuffer );
2008 module_init(atari_floppy_init)
2009 module_exit(atari_floppy_exit)
2011 MODULE_LICENSE("GPL");