1 /*
2  *  linux/kernel/arch/arm/drivers/block/fd1772.c
3  *  Based on ataflop.c in the m68k Linux
4  *  Copyright (C) 1993  Greg Harp
5  *  Atari Support by Bjoern Brauel, Roman Hodek
6  *  Archimedes Support by Dave Gilbert (linux@treblig.org)
7  *
8  *  Big cleanup Sep 11..14 1994 Roman Hodek:
9  *   - Driver now works interrupt driven
10  *   - Support for two drives; should work, but I cannot test that :-(
11  *   - Reading is done in whole tracks and buffered to speed up things
12  *   - Disk change detection and drive deselecting after motor-off
13  *     similar to TOS
14  *   - Autodetection of disk format (DD/HD); untested yet, because I
15  *     don't have an HD drive :-(
16  *
17  *  Fixes Nov 13 1994 Martin Schaller:
18  *   - Autodetection works now
19  *   - Support for 5 1/4" disks
20  *   - Removed drive type (unknown on atari)
21  *   - Do seeks with 8 Mhz
22  *
23  *  Changes by Andreas Schwab:
24  *   - After errors in multiple read mode try again reading single sectors
25  *  (Feb 1995):
26  *   - Clean up error handling
27  *   - Set blk_size for proper size checking
28  *   - Initialize track register when testing presence of floppy
29  *   - Implement some ioctl's
30  *
31  *  Changes by Torsten Lang:
32  *   - When probing the floppies we should add the FDC1772CMDADD_H flag since
33  *     the FDC1772 will otherwise wait forever when no disk is inserted...
34  *
35  *  Things left to do:
36  *   - Formatting
37  *   - Maybe a better strategy for disk change detection (does anyone
38  *     know one?)
39  *   - There are some strange problems left: The strangest one is
40  *     that, at least on my TT (4+4MB), the first 2 Bytes of the last
41  *     page of the TT-Ram (!) change their contents (some bits get
42  *     set) while a floppy DMA is going on. But there are no accesses
43  *     to these memory locations from the kernel... (I tested that by
44  *     making the page read-only). I cannot explain what's going on...
45  *   - Sometimes the drive-change-detection stops to work. The
46  *     function is still called, but the WP bit always reads as 0...
47  *     Maybe a problem with the status reg mode or a timing problem.
48  *     Note 10/12/94: The change detection now seems to work reliably.
49  *     There is no proof, but I've seen no hang for a long time...
50  *
51  * ARCHIMEDES changes: (gilbertd@cs.man.ac.uk)
52  *     26/12/95 - Changed all names starting with FDC to FDC1772
53  *                Removed all references to clock speed of FDC - we're stuck with 8MHz
54  *                Modified disk_type structure to remove HD formats
55  *
56  *      7/ 1/96 - Wrote FIQ code, removed most remaining atariisms
57  *
58  *     13/ 1/96 - Well I think its read a single sector; but there is a problem
59  *                fd_rwsec_done which is called in FIQ mode starts another transfer
60  *                off (in fd_rwsec) while still in FIQ mode.  Because its still in
61  *                FIQ mode it can't service the DMA and loses data. So need to
62  *                heavily restructure.
63  *     14/ 1/96 - Found that the definitions of the register numbers of the
64  *                FDC were multiplied by 2 in the header for the 16bit words
65  *                of the atari so half the writes were going in the wrong place.
66  *                Also realised that the FIQ entry didn't make any attempt to
67  *                preserve registers or return correctly; now in assembler.
68  *
69  *     11/ 2/96 - Hmm - doesn't work on real machine.  Auto detect doesn't
70  *                and hacking that past seems to wait forever - check motor
71  *                being turned on.
72  *
73  *     17/ 2/96 - still having problems - forcing track to -1 when selecting
74  *                new drives seems to allow it to read first few sectors
75  *                but then we get solid hangs at apparently random places
76  *                which change depending what is happening.
77  *
78  *      9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35
79  *                A lot of fiddling in DMA stuff. Having problems with it
80  *                constnatly thinking its timeing out. Ah - its timeout
81  *                was set to (6*HZ) rather than jiffies+(6*HZ).  Now giving
82  *                duff data!
83  *
84  *      5/ 4/96 - Made it use the new IOC_ macros rather than *ioc
85  *                Hmm - giving unexpected FIQ and then timeouts
86  *     18/ 8/96 - Ran through indent -kr -i8
87  *                Some changes to disc change detect; don't know how well it
88  *                works.
89  *     24/ 8/96 - Put all the track buffering code back in from the atari
90  *                code - I wonder if it will still work... No :-)
91  *                Still works if I turn off track buffering.
92  *     25/ 8/96 - Changed the timer expires that I'd added back to be
93  *                jiffies + ....; and it all sprang to life! Got 2.8K/sec
94  *                off a cp -r of a 679K disc (showed 94% cpu usage!)
95  *                (PC gets 14.3K/sec - 0% CPU!) Hmm - hard drive corrupt!
96  *                Also perhaps that compile was with cache off.
97  *                changed cli in fd_readtrack_check to cliIF
98  *                changed vmallocs to kmalloc (whats the difference!!)
99  *                Removed the busy wait loop in do_fd_request and replaced
100  *                by a routine on tq_immediate; only 11% cpu on a dd off the
101  *                raw disc - but the speed is the same.
102  *	1/ 9/96 - Idea (failed!) - set the 'disable spin-up seqeunce'
103  *		  when we read the track if we know the motor is on; didn't
104  *		  help - perhaps we have to do it in stepping as well.
105  *		  Nope. Still doesn't help.
106  *		  Hmm - what seems to be happening is that fd_readtrack_check
107  *		  is never getting called. Its job is to terminate the read
108  *		  just after we think we should have got the data; otherwise
109  *		  the fdc takes 1 second to timeout; which is what's happening
110  *		  Now I can see 'readtrack_timer' being set (which should do the
111  *		  call); but it never seems to be called - hmm!
112  *		  OK - I've moved the check to my tq_immediate code -
113  *		  and it WORKS! 13.95K/second at 19% CPU.
114  *		  I wish I knew why that timer didn't work.....
115  *
116  *     16/11/96 - Fiddled and frigged for 2.0.18
117  *
118  * DAG 30/01/99 - Started frobbing for 2.2.1
119  * DAG 20/06/99 - A little more frobbing:
120  *		  Included include/asm/uaccess.h for get_user/put_user
121  *
122  * DAG  1/09/00 - Dusted off for 2.4.0-test7
123  *                MAX_SECTORS was name clashing so it is now FD1772_...
124  *                Minor parameter, name layouts for 2.4.x differences
125  */
126 
127 #include <linux/sched.h>
128 #include <linux/fs.h>
129 #include <linux/fcntl.h>
130 #include <linux/slab.h>
131 #include <linux/kernel.h>
132 #include <linux/interrupt.h>
133 #include <linux/timer.h>
134 #include <linux/tqueue.h>
135 #include <linux/fd.h>
136 #include <linux/fd1772.h>
137 #include <linux/errno.h>
138 #include <linux/types.h>
139 #include <linux/delay.h>
140 #include <linux/mm.h>
141 
142 #include <asm/arch/oldlatches.h>
143 #include <asm/bitops.h>
144 #include <asm/dma.h>
145 #include <asm/hardware.h>
146 #include <asm/hardware/ioc.h>
147 #include <asm/io.h>
148 #include <asm/irq.h>
149 #include <asm/mach-types.h>
150 #include <asm/pgtable.h>
151 #include <asm/system.h>
152 #include <asm/uaccess.h>
153 
154 
155 #define MAJOR_NR FLOPPY_MAJOR
156 #define FLOPPY_DMA 0
157 #include <linux/blk.h>
158 
159 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
160  * little additional rework in this file). But I'm not yet sure if
161  * some other code depends on the number of floppies... (It is defined
162  * in a public header!)
163  */
164 #if 0
165 #undef FD_MAX_UNITS
166 #define	FD_MAX_UNITS	2
167 #endif
168 
169 /* Ditto worries for Arc - DAG */
170 #define FD_MAX_UNITS 4
171 #define TRACKBUFFER 0
172 /*#define DEBUG*/
173 
174 #ifdef DEBUG
175 #define DPRINT(a)	printk a
176 #else
177 #define DPRINT(a)
178 #endif
179 
180 /* Disk types: DD */
181 static struct archy_disk_type {
182 	const char *name;
183 	unsigned spt;		/* sectors per track */
184 	unsigned blocks;	/* total number of blocks */
185 	unsigned stretch;	/* track doubling ? */
186 } disk_type[] = {
187 
188 	{ "d360", 9, 720, 0 },			/* 360kB diskette */
189 	{ "D360", 9, 720, 1 },			/* 360kb in 720kb drive */
190 	{ "D720", 9, 1440, 0 },			/* 720kb diskette (DD) */
191 	/*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors
192 	                              - DAG - can't see how type detect can distinguish this
193 				      from 720K until it reads block 4 by which time its too late! */
194 };
195 
196 #define	NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
197 
198 /*
199  * Maximum disk size (in kilobytes). This default is used whenever the
200  * current disk size is unknown.
201  */
202 #define MAX_DISK_SIZE 720
203 
204 static int floppy_sizes[256];
205 static int floppy_blocksizes[256];
206 
207 /* current info on each unit */
208 static struct archy_floppy_struct {
209 	int connected;		/* !=0 : drive is connected */
210 	int autoprobe;		/* !=0 : do autoprobe       */
211 
212 	struct archy_disk_type *disktype;	/* current type of disk */
213 
214 	int track;		/* current head position or -1
215 				   * if unknown */
216 	unsigned int steprate;	/* steprate setting */
217 	unsigned int wpstat;	/* current state of WP signal
218 				   * (for disk change detection) */
219 } unit[FD_MAX_UNITS];
220 
221 /* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
222    is an assembler routine */
223 extern void fdc1772_comendhandler(void);	/* Actually doens't have these parameters - see fd1772.S */
224 extern volatile int fdc1772_comendstatus;
225 extern volatile int fdc1772_fdc_int_done;
226 
227 #define FDC1772BASE ((0x210000>>2)|0x80000000)
228 
229 #define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
230 
231 /* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
232    than the #def below - well simple - the #def won't compile - and I
233    don't understand why (__outwc not defined) */
234 /* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
235    with the ST version of fd1772.h */
236 /*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
FDC1772_WRITE(int reg,unsigned char val)237 void FDC1772_WRITE(int reg, unsigned char val)
238 {
239 	if (reg == FDC1772REG_CMD) {
240 		DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
241 		if (fdc1772_fdc_int_done) {
242 			DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
243 			fdc1772_fdc_int_done = 0;
244 		};
245 	};
246 	outb(val, (reg / 2) + FDC1772BASE);
247 };
248 
249 #define	FD1772_MAX_SECTORS	22
250 
251 unsigned char *DMABuffer;	/* buffer for writes */
252 /*static unsigned long PhysDMABuffer; *//* physical address */
253 /* DAG: On Arc we just go straight for the DMA buffer */
254 #define PhysDMABuffer DMABuffer
255 
256 #ifdef TRACKBUFFER
257 unsigned char *TrackBuffer;       /* buffer for reads */
258 #define PhysTrackBuffer TrackBuffer /* physical address */
259 static int BufferDrive, BufferSide, BufferTrack;
260 static int read_track;    /* non-zero if we are reading whole tracks */
261 
262 #define SECTOR_BUFFER(sec)  (TrackBuffer + ((sec)-1)*512)
263 #define IS_BUFFERED(drive,side,track) \
264     (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
265 #endif
266 
267 /*
268  * These are global variables, as that's the easiest way to give
269  * information to interrupts. They are the data used for the current
270  * request.
271  */
272 static int SelectedDrive = 0;
273 static int ReqCmd, ReqBlock;
274 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
275 static int HeadSettleFlag = 0;
276 static unsigned char *ReqData, *ReqBuffer;
277 static int MotorOn = 0, MotorOffTrys;
278 
279 /* Synchronization of FDC1772 access. */
280 static volatile int fdc_busy = 0;
281 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
282 
283 
284 /* long req'd for set_bit --RR */
285 static unsigned long changed_floppies = 0xff, fake_change = 0;
286 #define	CHECK_CHANGE_DELAY	HZ/2
287 
288 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
289 #define	FD_MOTOR_OFF_DELAY	(10*HZ)
290 #define	FD_MOTOR_OFF_MAXTRY	(10*20)
291 
292 #define FLOPPY_TIMEOUT		(6*HZ)
293 #define RECALIBRATE_ERRORS	4	/* After this many errors the drive
294 					 * will be recalibrated. */
295 #define MAX_ERRORS		8	/* After this many errors the driver
296 					 * will give up. */
297 
298 #define	START_MOTOR_OFF_TIMER(delay)				\
299 	do {							\
300 		motor_off_timer.expires = jiffies + (delay);	\
301 		add_timer( &motor_off_timer );			\
302 		MotorOffTrys = 0;				\
303 	} while(0)
304 
305 #define	START_CHECK_CHANGE_TIMER(delay)				\
306 	do {							\
307 	        mod_timer(&fd_timer, jiffies + (delay));	\
308 	} while(0)
309 
310 #define	START_TIMEOUT()						\
311 	do {							\
312 		mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \
313 	} while(0)
314 
315 #define	STOP_TIMEOUT()						\
316 	do {							\
317 		del_timer( &timeout_timer );			\
318 	} while(0)
319 
320 #define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
321 
322 #define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
323 
324 static void fd1772_checkint(void);
325 
326 struct tq_struct fd1772_tq =
327 { 0,0, (void *)fd1772_checkint, 0 };
328 /*
329  * The driver is trying to determine the correct media format
330  * while Probing is set. fd_rwsec_done() clears it after a
331  * successful access.
332  */
333 static int Probing = 0;
334 
335 /* This flag is set when a dummy seek is necesary to make the WP
336  * status bit accessible.
337  */
338 static int NeedSeek = 0;
339 
340 
341 /***************************** Prototypes *****************************/
342 
343 static void fd_select_side(int side);
344 static void fd_select_drive(int drive);
345 static void fd_deselect(void);
346 static void fd_motor_off_timer(unsigned long dummy);
347 static void check_change(unsigned long dummy);
348 static __inline__ void set_head_settle_flag(void);
349 static __inline__ int get_head_settle_flag(void);
350 static void floppy_irqconsequencehandler(void);
351 static void fd_error(void);
352 static void do_fd_action(int drive);
353 static void fd_calibrate(void);
354 static void fd_calibrate_done(int status);
355 static void fd_seek(void);
356 static void fd_seek_done(int status);
357 static void fd_rwsec(void);
358 #ifdef TRACKBUFFER
359 static void fd_readtrack_check( unsigned long dummy );
360 #endif
361 static void fd_rwsec_done(int status);
362 static void fd_times_out(unsigned long dummy);
363 static void finish_fdc(void);
364 static void finish_fdc_done(int dummy);
365 static void floppy_off(unsigned int nr);
366 static __inline__ void copy_buffer(void *from, void *to);
367 static void setup_req_params(int drive);
368 static void redo_fd_request(void);
369 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
370 		    cmd, unsigned long param);
371 static void fd_probe(int drive);
372 static int fd_test_drive_present(int drive);
373 static void config_types(void);
374 static int floppy_open(struct inode *inode, struct file *filp);
375 static int floppy_release(struct inode *inode, struct file *filp);
376 
377 /************************* End of Prototypes **************************/
378 
379 static struct timer_list motor_off_timer = {
380 	function:	fd_motor_off_timer,
381 };
382 
383 #ifdef TRACKBUFFER
384 static struct timer_list readtrack_timer = {
385 	function: 	fd_readtrack_check,
386 };
387 #endif
388 
389 static struct timer_list timeout_timer = {
390 	function:	fd_times_out,
391 };
392 
393 static struct timer_list fd_timer = {
394 	function:	check_change,
395 };
396 
397 /* DAG: Haven't got a clue what this is? */
stdma_islocked(void)398 int stdma_islocked(void)
399 {
400 	return 0;
401 };
402 
403 /* Select the side to use. */
404 
fd_select_side(int side)405 static void fd_select_side(int side)
406 {
407 	oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
408 }
409 
410 
411 /* Select a drive, update the FDC1772's track register
412  */
413 
fd_select_drive(int drive)414 static void fd_select_drive(int drive)
415 {
416 #ifdef DEBUG
417 	printk("fd_select_drive:%d\n", drive);
418 #endif
419 	/* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
420 	oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
421 
422 	if (drive == SelectedDrive)
423 		return;
424 
425 	oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
426 
427 	/* restore track register to saved value */
428 	FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
429 	udelay(25);
430 
431 	SelectedDrive = drive;
432 }
433 
434 
435 /* Deselect both drives. */
436 
fd_deselect(void)437 static void fd_deselect(void)
438 {
439 	unsigned long flags;
440 
441 	DPRINT(("fd_deselect\n"));
442 
443 	oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
444 
445 	SelectedDrive = -1;
446 }
447 
448 
449 /* This timer function deselects the drives when the FDC1772 switched the
450  * motor off. The deselection cannot happen earlier because the FDC1772
451  * counts the index signals, which arrive only if one drive is selected.
452  */
453 
fd_motor_off_timer(unsigned long dummy)454 static void fd_motor_off_timer(unsigned long dummy)
455 {
456 	unsigned long flags;
457 	unsigned char status;
458 	int delay;
459 
460 	del_timer(&motor_off_timer);
461 
462 	if (SelectedDrive < 0)
463 		/* no drive selected, needn't deselect anyone */
464 		return;
465 
466 	save_flags(flags);
467 	cli();
468 
469 	if (fdc_busy)		/* was stdma_islocked */
470 		goto retry;
471 
472 	status = FDC1772_READ(FDC1772REG_STATUS);
473 
474 	if (!(status & 0x80)) {
475 		/*
476 		 * motor already turned off by FDC1772 -> deselect drives
477 		 * In actual fact its this deselection which turns the motor
478 		 * off on the Arc, since the motor control is actually on
479 		 * Latch A
480 		 */
481 		DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
482 		fd_deselect();
483 		MotorOn = 0;
484 		restore_flags(flags);
485 		return;
486 	}
487 	/* not yet off, try again */
488 
489 retry:
490 	restore_flags(flags);
491 	/* Test again later; if tested too often, it seems there is no disk
492 	 * in the drive and the FDC1772 will leave the motor on forever (or,
493 	 * at least until a disk is inserted). So we'll test only twice
494 	 * per second from then on...
495 	 */
496 	delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
497 	    (++MotorOffTrys, HZ / 20) : HZ / 2;
498 	START_MOTOR_OFF_TIMER(delay);
499 }
500 
501 
502 /* This function is repeatedly called to detect disk changes (as good
503  * as possible) and keep track of the current state of the write protection.
504  */
505 
check_change(unsigned long dummy)506 static void check_change(unsigned long dummy)
507 {
508 	static int drive = 0;
509 
510 	unsigned long flags;
511 	int stat;
512 
513 	if (fdc_busy)
514 		return;		/* Don't start poking about if the fdc is busy */
515 
516 	return;			/* let's just forget it for the mo DAG */
517 
518 	if (++drive > 1 || !unit[drive].connected)
519 		drive = 0;
520 
521 	save_flags(flags);
522 	cli();
523 
524 	if (!stdma_islocked()) {
525 		stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
526 
527 		/* The idea here is that if the write protect line has changed then
528 		the disc must have changed */
529 		if (stat != unit[drive].wpstat) {
530 			DPRINT(("wpstat[%d] = %d\n", drive, stat));
531 			unit[drive].wpstat = stat;
532 			set_bit(drive, &changed_floppies);
533 		}
534 	}
535 	restore_flags(flags);
536 
537 	START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
538 }
539 
540 
541 /* Handling of the Head Settling Flag: This flag should be set after each
542  * seek operation, because we don't use seeks with verify.
543  */
544 
set_head_settle_flag(void)545 static __inline__ void set_head_settle_flag(void)
546 {
547 	HeadSettleFlag = FDC1772CMDADD_E;
548 }
549 
get_head_settle_flag(void)550 static __inline__ int get_head_settle_flag(void)
551 {
552 	int tmp = HeadSettleFlag;
553 	HeadSettleFlag = 0;
554 	return (tmp);
555 }
556 
557 
558 
559 
560 /* General Interrupt Handling */
561 
562 static void (*FloppyIRQHandler) (int status) = NULL;
563 
floppy_irqconsequencehandler(void)564 static void floppy_irqconsequencehandler(void)
565 {
566 	unsigned char status;
567 	void (*handler) (int);
568 
569 	fdc1772_fdc_int_done = 0;
570 
571 	handler = FloppyIRQHandler;
572 	FloppyIRQHandler = NULL;
573 
574 	if (handler) {
575 		nop();
576 		status = (unsigned char) fdc1772_comendstatus;
577 		DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
578 		handler(status);
579 	} else {
580 		DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
581 	}
582 	DPRINT(("FDC1772 irq: end of floppy_irq\n"));
583 }
584 
585 
586 /* Error handling: If some error happened, retry some times, then
587  * recalibrate, then try again, and fail after MAX_ERRORS.
588  */
589 
fd_error(void)590 static void fd_error(void)
591 {
592 	printk("FDC1772: fd_error\n");
593 	/*panic("fd1772: fd_error"); *//* DAG tmp */
594 	if (QUEUE_EMPTY)
595 		return;
596 	CURRENT->errors++;
597 	if (CURRENT->errors >= MAX_ERRORS) {
598 		printk("fd%d: too many errors.\n", SelectedDrive);
599 		end_request(0);
600 	} else if (CURRENT->errors == RECALIBRATE_ERRORS) {
601 		printk("fd%d: recalibrating\n", SelectedDrive);
602 		if (SelectedDrive != -1)
603 			unit[SelectedDrive].track = -1;
604 	}
605 	redo_fd_request();
606 }
607 
608 
609 
610 #define	SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
611 
612 
613 /* do_fd_action() is the general procedure for a fd request: All
614  * required parameter settings (drive select, side select, track
615  * position) are checked and set if needed. For each of these
616  * parameters and the actual reading or writing exist two functions:
617  * one that starts the setting (or skips it if possible) and one
618  * callback for the "done" interrupt. Each done func calls the next
619  * set function to propagate the request down to fd_rwsec_done().
620  */
621 
do_fd_action(int drive)622 static void do_fd_action(int drive)
623 {
624 	DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
625 
626 #ifdef TRACKBUFFER
627 repeat:
628 
629 	if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
630 		if (ReqCmd == READ) {
631 			copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
632 			if (++ReqCnt < CURRENT->current_nr_sectors) {
633 				/* read next sector */
634 				setup_req_params( drive );
635 				goto repeat;
636 			} else {
637 				/* all sectors finished */
638 				CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
639 				CURRENT->sector += CURRENT->current_nr_sectors;
640 				end_request( 1 );
641 				redo_fd_request();
642 				return;
643 			}
644 		} else {
645 			/* cmd == WRITE, pay attention to track buffer
646 			 * consistency! */
647 			copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
648 		}
649 	}
650 #endif
651 
652 	if (SelectedDrive != drive) {
653 		/*unit[drive].track = -1; DAG */
654 		fd_select_drive(drive);
655 	};
656 
657 
658 	if (unit[drive].track == -1)
659 		fd_calibrate();
660 	else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
661 		fd_seek();
662 	else
663 		fd_rwsec();
664 }
665 
666 
667 /* Seek to track 0 if the current track is unknown */
668 
fd_calibrate(void)669 static void fd_calibrate(void)
670 {
671 	DPRINT(("fd_calibrate\n"));
672 	if (unit[SelectedDrive].track >= 0) {
673 		fd_calibrate_done(0);
674 		return;
675 	}
676 	DPRINT(("fd_calibrate (after track compare)\n"));
677 	SET_IRQ_HANDLER(fd_calibrate_done);
678 	/* we can't verify, since the speed may be incorrect */
679 	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
680 
681 	NeedSeek = 1;
682 	MotorOn = 1;
683 	START_TIMEOUT();
684 	/* wait for IRQ */
685 }
686 
687 
fd_calibrate_done(int status)688 static void fd_calibrate_done(int status)
689 {
690 	DPRINT(("fd_calibrate_done()\n"));
691 	STOP_TIMEOUT();
692 
693 	/* set the correct speed now */
694 	if (status & FDC1772STAT_RECNF) {
695 		printk("fd%d: restore failed\n", SelectedDrive);
696 		fd_error();
697 	} else {
698 		unit[SelectedDrive].track = 0;
699 		fd_seek();
700 	}
701 }
702 
703 
704 /* Seek the drive to the requested track. The drive must have been
705  * calibrated at some point before this.
706  */
707 
fd_seek(void)708 static void fd_seek(void)
709 {
710 	unsigned long flags;
711 	DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
712 		unit[SelectedDrive].track));
713 	if (unit[SelectedDrive].track == ReqTrack <<
714 	    unit[SelectedDrive].disktype->stretch) {
715 		fd_seek_done(0);
716 		return;
717 	}
718 	FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
719 		      unit[SelectedDrive].disktype->stretch);
720 	udelay(25);
721 	save_flags(flags);
722 	clf();
723 	SET_IRQ_HANDLER(fd_seek_done);
724 	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
725 		/* DAG */
726 		(MotorOn?FDC1772CMDADD_H:0));
727 
728 	restore_flags(flags);
729 	MotorOn = 1;
730 	set_head_settle_flag();
731 	START_TIMEOUT();
732 	/* wait for IRQ */
733 }
734 
735 
fd_seek_done(int status)736 static void fd_seek_done(int status)
737 {
738 	DPRINT(("fd_seek_done()\n"));
739 	STOP_TIMEOUT();
740 
741 	/* set the correct speed */
742 	if (status & FDC1772STAT_RECNF) {
743 		printk("fd%d: seek error (to track %d)\n",
744 		       SelectedDrive, ReqTrack);
745 		/* we don't know exactly which track we are on now! */
746 		unit[SelectedDrive].track = -1;
747 		fd_error();
748 	} else {
749 		unit[SelectedDrive].track = ReqTrack <<
750 		    unit[SelectedDrive].disktype->stretch;
751 		NeedSeek = 0;
752 		fd_rwsec();
753 	}
754 }
755 
756 
757 /* This does the actual reading/writing after positioning the head
758  * over the correct track.
759  */
760 
761 #ifdef TRACKBUFFER
762 static int MultReadInProgress = 0;
763 #endif
764 
765 
fd_rwsec(void)766 static void fd_rwsec(void)
767 {
768 	unsigned long paddr, flags;
769 	unsigned int rwflag, old_motoron;
770 	unsigned int track;
771 
772 	DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
773 	if (ReqCmd == WRITE) {
774 		/*cache_push( (unsigned long)ReqData, 512 ); */
775 		paddr = (unsigned long) ReqData;
776 		rwflag = 0x100;
777 	} else {
778 		paddr = (unsigned long) PhysDMABuffer;
779 #ifdef TRACKBUFFER
780 		if (read_track)
781 			paddr = (unsigned long)PhysTrackBuffer;
782 #endif
783 		rwflag = 0;
784 	}
785 
786 	DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
787 		ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
788 	fd_select_side(ReqSide);
789 
790 	/*DPRINT(("fd_rwsec() before start sector \n")); */
791 	/* Start sector of this operation */
792 #ifdef TRACKBUFFER
793 	FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
794 #else
795 	FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
796 #endif
797 
798 	/* Cheat for track if stretch != 0 */
799 	if (unit[SelectedDrive].disktype->stretch) {
800 		track = FDC1772_READ(FDC1772REG_TRACK);
801 		FDC1772_WRITE(FDC1772REG_TRACK, track >>
802 			      unit[SelectedDrive].disktype->stretch);
803 	}
804 	udelay(25);
805 
806 	DPRINT(("fd_rwsec() before setup DMA \n"));
807 	/* Setup DMA - Heavily modified by DAG */
808 	save_flags(flags);
809 	clf();
810 	disable_dma(FLOPPY_DMA);
811 	set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
812 	set_dma_addr(FLOPPY_DMA, (long) paddr);		/* DAG - changed from Atari specific */
813 #ifdef TRACKBUFFER
814 	set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
815 #else
816 	set_dma_count(FLOPPY_DMA, 512);		/* Block/sector size - going to have to change */
817 #endif
818 	SET_IRQ_HANDLER(fd_rwsec_done);
819 	/* Turn on dma int */
820 	enable_dma(FLOPPY_DMA);
821 	/* Now give it something to do */
822 	FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) :
823 #ifdef TRACKBUFFER
824 	      (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
825 	      /* Hmm - the idea here is to stop the FDC spinning the disc
826 	      up when we know that we already still have it spinning */
827 	      (MotorOn?FDC1772CMDADD_H:0))
828 #else
829 	      FDC1772CMD_RDSEC
830 #endif
831 		));
832 
833 	restore_flags(flags);
834 	DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
835 	/*sti(); *//* DAG - Hmm */
836 	/* Hmm - should do something DAG */
837 	old_motoron = MotorOn;
838 	MotorOn = 1;
839 	NeedSeek = 1;
840 
841 	/* wait for interrupt */
842 
843 #ifdef TRACKBUFFER
844 	if (read_track) {
845 		/*
846 		 * If reading a whole track, wait about one disk rotation and
847 		 * then check if all sectors are read. The FDC will even
848 		 * search for the first non-existant sector and need 1 sec to
849 		 * recognise that it isn't present :-(
850 		 */
851 		/* 1 rot. + 5 rot.s if motor was off  */
852 		mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
853 		DPRINT(("Setting readtrack_timer to %d @ %d\n",
854 			readtrack_timer.expires,jiffies));
855 		MultReadInProgress = 1;
856 	}
857 #endif
858 
859 	/*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
860 	START_TIMEOUT();
861 	/*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
862 }
863 
864 
865 #ifdef TRACKBUFFER
866 
fd_readtrack_check(unsigned long dummy)867 static void fd_readtrack_check(unsigned long dummy)
868 {
869 	unsigned long flags, addr;
870 	extern unsigned char *fdc1772_dataaddr;
871 
872 	DPRINT(("fd_readtrack_check @ %d\n",jiffies));
873 
874 	save_flags(flags);
875 	clf();
876 
877 	del_timer( &readtrack_timer );
878 
879 	if (!MultReadInProgress) {
880 		/* This prevents a race condition that could arise if the
881 		 * interrupt is triggered while the calling of this timer
882 		 * callback function takes place. The IRQ function then has
883 		 * already cleared 'MultReadInProgress'  when control flow
884 		 * gets here.
885 		 */
886 		restore_flags(flags);
887 		return;
888 	}
889 
890 	/* get the current DMA address */
891 	addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */
892 	DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
893 
894 	if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
895 		/* already read enough data, force an FDC interrupt to stop
896 		 * the read operation
897 		 */
898 		SET_IRQ_HANDLER( NULL );
899 		restore_flags(flags);
900 		DPRINT(("fd_readtrack_check(): done\n"));
901 		FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
902 		udelay(25);
903 
904 		/* No error until now -- the FDC would have interrupted
905 		 * otherwise!
906 		 */
907 		fd_rwsec_done( 0 );
908 	} else {
909 		/* not yet finished, wait another tenth rotation */
910 		restore_flags(flags);
911 		DPRINT(("fd_readtrack_check(): not yet finished\n"));
912 		readtrack_timer.expires = jiffies + HZ/5/10;
913 		add_timer( &readtrack_timer );
914 	}
915 }
916 
917 #endif
918 
fd_rwsec_done(int status)919 static void fd_rwsec_done(int status)
920 {
921 	unsigned int track;
922 
923 	DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
924 
925 #ifdef TRACKBUFFER
926 	if (read_track && !MultReadInProgress)
927 		return;
928 
929 	MultReadInProgress = 0;
930 
931 	STOP_TIMEOUT();
932 
933 	if (read_track)
934 		del_timer( &readtrack_timer );
935 #endif
936 
937 
938 	/* Correct the track if stretch != 0 */
939 	if (unit[SelectedDrive].disktype->stretch) {
940 		track = FDC1772_READ(FDC1772REG_TRACK);
941 		FDC1772_WRITE(FDC1772REG_TRACK, track <<
942 			      unit[SelectedDrive].disktype->stretch);
943 	}
944 	if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
945 		printk("fd%d: is write protected\n", SelectedDrive);
946 		goto err_end;
947 	}
948 	if ((status & FDC1772STAT_RECNF)
949 #ifdef TRACKBUFFER
950 	    /* RECNF is no error after a multiple read when the FDC
951 	     * searched for a non-existant sector!
952 	     */
953 	    && !(read_track &&
954 	       FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
955 #endif
956 	    ) {
957 		if (Probing) {
958 			if (unit[SelectedDrive].disktype > disk_type) {
959 				/* try another disk type */
960 				unit[SelectedDrive].disktype--;
961 				floppy_sizes[SelectedDrive]
962 				    = unit[SelectedDrive].disktype->blocks >> 1;
963 			} else
964 				Probing = 0;
965 		} else {
966 			/* record not found, but not probing. Maybe stretch wrong ? Restart probing */
967 			if (unit[SelectedDrive].autoprobe) {
968 				unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
969 				floppy_sizes[SelectedDrive]
970 				    = unit[SelectedDrive].disktype->blocks >> 1;
971 				Probing = 1;
972 			}
973 		}
974 		if (Probing) {
975 			setup_req_params(SelectedDrive);
976 #ifdef TRACKBUFFER
977 			BufferDrive = -1;
978 #endif
979 			do_fd_action(SelectedDrive);
980 			return;
981 		}
982 		printk("fd%d: sector %d not found (side %d, track %d)\n",
983 		       SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
984 		goto err_end;
985 	}
986 	if (status & FDC1772STAT_CRC) {
987 		printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
988 		       SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
989 		goto err_end;
990 	}
991 	if (status & FDC1772STAT_LOST) {
992 		printk("fd%d: lost data (side %d, track %d, sector %d)\n",
993 		       SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
994 		goto err_end;
995 	}
996 	Probing = 0;
997 
998 	if (ReqCmd == READ) {
999 #ifdef TRACKBUFFER
1000 		if (!read_track) {
1001 			/*cache_clear (PhysDMABuffer, 512);*/
1002 			copy_buffer (DMABuffer, ReqData);
1003 		} else {
1004 			/*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/
1005 			BufferDrive = SelectedDrive;
1006 			BufferSide  = ReqSide;
1007 			BufferTrack = ReqTrack;
1008 			copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1009 		}
1010 #else
1011 		/*cache_clear( PhysDMABuffer, 512 ); */
1012 		copy_buffer(DMABuffer, ReqData);
1013 #endif
1014 	}
1015 	if (++ReqCnt < CURRENT->current_nr_sectors) {
1016 		/* read next sector */
1017 		setup_req_params(SelectedDrive);
1018 		do_fd_action(SelectedDrive);
1019 	} else {
1020 		/* all sectors finished */
1021 		CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1022 		CURRENT->sector += CURRENT->current_nr_sectors;
1023 		end_request(1);
1024 		redo_fd_request();
1025 	}
1026 	return;
1027 
1028 err_end:
1029 #ifdef TRACKBUFFER
1030 	BufferDrive = -1;
1031 #endif
1032 
1033 	fd_error();
1034 }
1035 
1036 
fd_times_out(unsigned long dummy)1037 static void fd_times_out(unsigned long dummy)
1038 {
1039 	SET_IRQ_HANDLER(NULL);
1040 	/* If the timeout occurred while the readtrack_check timer was
1041 	 * active, we need to cancel it, else bad things will happen */
1042 	del_timer( &readtrack_timer );
1043 	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1044 	udelay(25);
1045 
1046 	printk("floppy timeout\n");
1047 	STOP_TIMEOUT();		/* hmm - should we do this ? */
1048 	fd_error();
1049 }
1050 
1051 
1052 /* The (noop) seek operation here is needed to make the WP bit in the
1053  * FDC1772 status register accessible for check_change. If the last disk
1054  * operation would have been a RDSEC, this bit would always read as 0
1055  * no matter what :-( To save time, the seek goes to the track we're
1056  * already on.
1057  */
1058 
finish_fdc(void)1059 static void finish_fdc(void)
1060 {
1061 	/* DAG - just try without this dummy seek! */
1062 	finish_fdc_done(0);
1063 	return;
1064 
1065 	if (!NeedSeek) {
1066 		finish_fdc_done(0);
1067 	} else {
1068 		DPRINT(("finish_fdc: dummy seek started\n"));
1069 		FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1070 		SET_IRQ_HANDLER(finish_fdc_done);
1071 		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1072 		MotorOn = 1;
1073 		START_TIMEOUT();
1074 		/* we must wait for the IRQ here, because the ST-DMA is
1075 		 * released immediatly afterwards and the interrupt may be
1076 		 * delivered to the wrong driver.
1077 		 */
1078 	}
1079 }
1080 
1081 
finish_fdc_done(int dummy)1082 static void finish_fdc_done(int dummy)
1083 {
1084 	unsigned long flags;
1085 
1086 	DPRINT(("finish_fdc_done entered\n"));
1087 	STOP_TIMEOUT();
1088 	NeedSeek = 0;
1089 
1090 	if (timer_pending(&fd_timer) &&
1091 	    time_after(jiffies + 5, fd_timer.expires))
1092 		/* If the check for a disk change is done too early after this
1093 		 * last seek command, the WP bit still reads wrong :-((
1094 		 */
1095 		mod_timer(&fd_timer, jiffies + 5);
1096 	else {
1097 		/*      START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1098 	};
1099 	del_timer(&motor_off_timer);
1100 	START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1101 
1102 	save_flags(flags);
1103 	cli();
1104 	/* stdma_release(); - not sure if I should do something DAG  */
1105 	fdc_busy = 0;
1106 	wake_up(&fdc_wait);
1107 	restore_flags(flags);
1108 
1109 	DPRINT(("finish_fdc() finished\n"));
1110 }
1111 
1112 
1113 /* Prevent "aliased" accesses. */
1114 static int fd_ref[4];
1115 static int fd_device[4];
1116 
1117 /*
1118  * Current device number. Taken either from the block header or from the
1119  * format request descriptor.
1120  */
1121 #define CURRENT_DEVICE (CURRENT->rq_dev)
1122 
1123 /* Current error count. */
1124 #define CURRENT_ERRORS (CURRENT->errors)
1125 
1126 
1127 /* dummy for blk.h */
floppy_off(unsigned int nr)1128 static void floppy_off(unsigned int nr)
1129 {
1130 }
1131 
1132 
1133 /* On the old arcs write protect depends on the particular model
1134    of machine.  On the A310, R140, and A440 there is a disc changed
1135    detect, however on the A4x0/1 range there is not.  There
1136    is nothing to tell you which machine your on.
1137    At the moment I'm just marking changed always. I've
1138    left the Atari's 'change on write protect change' code in this
1139    part (but nothing sets it).
1140    RiscOS apparently checks the disc serial number etc. to detect changes
1141    - but if it sees a disc change line go high (?) it flips to using
1142    it. Well  maybe I'll add that in the future (!?)
1143 */
check_floppy_change(dev_t dev)1144 static int check_floppy_change(dev_t dev)
1145 {
1146 	unsigned int drive = (dev & 0x03);
1147 
1148 	if (MAJOR(dev) != MAJOR_NR) {
1149 		printk("floppy_changed: not a floppy\n");
1150 		return 0;
1151 	}
1152 	if (test_bit(drive, &fake_change)) {
1153 		/* simulated change (e.g. after formatting) */
1154 		return 1;
1155 	}
1156 	if (test_bit(drive, &changed_floppies)) {
1157 		/* surely changed (the WP signal changed at least once) */
1158 		return 1;
1159 	}
1160 	if (unit[drive].wpstat) {
1161 		/* WP is on -> could be changed: to be sure, buffers should be
1162 		   * invalidated...
1163 		 */
1164 		return 1;
1165 	}
1166 	return 1; /* DAG - was 0 */
1167 }
1168 
floppy_revalidate(dev_t dev)1169 static int floppy_revalidate(dev_t dev)
1170 {
1171 	int drive = dev & 3;
1172 
1173 	if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1174 	    || unit[drive].disktype == 0) {
1175 #ifdef TRACKBUFFER
1176 		BufferDrive = -1;
1177 #endif
1178 		clear_bit(drive, &fake_change);
1179 		clear_bit(drive, &changed_floppies);
1180 		unit[drive].disktype = 0;
1181 	}
1182 	return 0;
1183 }
1184 
copy_buffer(void * from,void * to)1185 static __inline__ void copy_buffer(void *from, void *to)
1186 {
1187 	ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
1188 	int cnt;
1189 
1190 	for (cnt = 512 / 4; cnt; cnt--)
1191 		*p2++ = *p1++;
1192 }
1193 
1194 
1195 /* This sets up the global variables describing the current request. */
1196 
setup_req_params(int drive)1197 static void setup_req_params(int drive)
1198 {
1199 	int block = ReqBlock + ReqCnt;
1200 
1201 	ReqTrack = block / unit[drive].disktype->spt;
1202 	ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1203 	ReqSide = ReqTrack & 1;
1204 	ReqTrack >>= 1;
1205 	ReqData = ReqBuffer + 512 * ReqCnt;
1206 
1207 #ifdef TRACKBUFFER
1208 	read_track = (ReqCmd == READ && CURRENT_ERRORS == 0);
1209 #endif
1210 
1211 	DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1212 		ReqTrack, ReqSector, (unsigned long) ReqData));
1213 }
1214 
1215 
redo_fd_request(void)1216 static void redo_fd_request(void)
1217 {
1218 	int device, drive, type;
1219 	struct archy_floppy_struct *floppy;
1220 
1221 	DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n",
1222 		(unsigned long) CURRENT, CURRENT ? CURRENT->rq_dev : 0,
1223 		!QUEUE_EMPTY ? CURRENT->sector : 0));
1224 
1225 	if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE)
1226 		goto the_end;
1227 
1228 repeat:
1229 
1230 	if (QUEUE_EMPTY)
1231 		goto the_end;
1232 
1233 	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
1234 		panic(DEVICE_NAME ": request list destroyed");
1235 
1236 	if (CURRENT->bh) {
1237 		if (!buffer_locked(CURRENT->bh))
1238 			panic(DEVICE_NAME ": block not locked");
1239 	}
1240 	device = MINOR(CURRENT_DEVICE);
1241 	drive = device & 3;
1242 	type = device >> 2;
1243 	floppy = &unit[drive];
1244 
1245 	if (!floppy->connected) {
1246 		/* drive not connected */
1247 		printk("Unknown Device: fd%d\n", drive);
1248 		end_request(0);
1249 		goto repeat;
1250 	}
1251 	if (type == 0) {
1252 		if (!floppy->disktype) {
1253 			Probing = 1;
1254 			floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1255 			floppy_sizes[drive] = floppy->disktype->blocks >> 1;
1256 			floppy->autoprobe = 1;
1257 		}
1258 	} else {
1259 		/* user supplied disk type */
1260 		--type;
1261 		if (type >= NUM_DISK_TYPES) {
1262 			printk("fd%d: invalid disk format", drive);
1263 			end_request(0);
1264 			goto repeat;
1265 		}
1266 		floppy->disktype = &disk_type[type];
1267 		floppy_sizes[drive] = disk_type[type].blocks >> 1;
1268 		floppy->autoprobe = 0;
1269 	}
1270 
1271 	if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1272 		end_request(0);
1273 		goto repeat;
1274 	}
1275 	/* stop deselect timer */
1276 	del_timer(&motor_off_timer);
1277 
1278 	ReqCnt = 0;
1279 	ReqCmd = CURRENT->cmd;
1280 	ReqBlock = CURRENT->sector;
1281 	ReqBuffer = CURRENT->buffer;
1282 	setup_req_params(drive);
1283 	do_fd_action(drive);
1284 
1285 	return;
1286 
1287 the_end:
1288 	finish_fdc();
1289 }
1290 
fd1772_checkint(void)1291 static void fd1772_checkint(void)
1292 {
1293 	extern int fdc1772_bytestogo;
1294 
1295 	/*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1296 	if (fdc1772_fdc_int_done)
1297 		floppy_irqconsequencehandler();
1298 	if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1299 	if (fdc_busy) {
1300 		queue_task(&fd1772_tq,&tq_immediate);
1301 		mark_bh(IMMEDIATE_BH);
1302 	}
1303 }
1304 
do_fd_request(request_queue_t * q)1305 void do_fd_request(request_queue_t* q)
1306 {
1307 	unsigned long flags;
1308 
1309 	DPRINT(("do_fd_request for pid %d\n", current->pid));
1310 	if (fdc_busy) return;
1311 	save_flags(flags);
1312 	cli();
1313 	while (fdc_busy)
1314 		sleep_on(&fdc_wait);
1315 	fdc_busy = 1;
1316 	ENABLE_IRQ();
1317 	restore_flags(flags);
1318 
1319 	fdc1772_fdc_int_done = 0;
1320 
1321 	redo_fd_request();
1322 
1323 	queue_task(&fd1772_tq,&tq_immediate);
1324 	mark_bh(IMMEDIATE_BH);
1325 }
1326 
1327 
invalidate_drive(int rdev)1328 static int invalidate_drive(int rdev)
1329 {
1330 	/* invalidate the buffer track to force a reread */
1331 #ifdef TRACKBUFFER
1332 	BufferDrive = -1;
1333 #endif
1334 
1335 	set_bit(rdev & 3, &fake_change);
1336 	check_disk_change(rdev);
1337 	return 0;
1338 }
1339 
fd_ioctl(struct inode * inode,struct file * filp,unsigned int cmd,unsigned long param)1340 static int fd_ioctl(struct inode *inode, struct file *filp,
1341 		    unsigned int cmd, unsigned long param)
1342 {
1343 	int drive, device;
1344 
1345 	device = inode->i_rdev;
1346 	drive = MINOR(device);
1347 	switch (cmd) {
1348 	case FDFMTBEG:
1349 		return 0;
1350 		/* case FDC1772LRPRM:  ??? DAG what does this do??
1351 		   unit[drive].disktype = NULL;
1352 		   floppy_sizes[drive] = MAX_DISK_SIZE;
1353 		   return invalidate_drive (device); */
1354 	case FDFMTEND:
1355 	case FDFLUSH:
1356 		return invalidate_drive(drive);
1357 	}
1358 	if (!capable(CAP_SYS_ADMIN))
1359 		return -EPERM;
1360 	if (drive < 0 || drive > 3)
1361 		return -EINVAL;
1362 	switch (cmd) {
1363 	default:
1364 		return -EINVAL;
1365 	}
1366 	return 0;
1367 }
1368 
1369 
1370 /* Initialize the 'unit' variable for drive 'drive' */
1371 
fd_probe(int drive)1372 static void fd_probe(int drive)
1373 {
1374 	unit[drive].connected = 0;
1375 	unit[drive].disktype = NULL;
1376 
1377 	if (!fd_test_drive_present(drive))
1378 		return;
1379 
1380 	unit[drive].connected = 1;
1381 	unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
1382 	unit[drive].steprate = FDC1772STEP_6;
1383 	MotorOn = 1;		/* from probe restore operation! */
1384 }
1385 
1386 
1387 /* This function tests the physical presence of a floppy drive (not
1388  * whether a disk is inserted). This is done by issuing a restore
1389  * command, waiting max. 2 seconds (that should be enough to move the
1390  * head across the whole disk) and looking at the state of the "TR00"
1391  * signal. This should now be raised if there is a drive connected
1392  * (and there is no hardware failure :-) Otherwise, the drive is
1393  * declared absent.
1394  */
1395 
fd_test_drive_present(int drive)1396 static int fd_test_drive_present(int drive)
1397 {
1398 	unsigned long timeout;
1399 	unsigned char status;
1400 	int ok;
1401 
1402 	printk("fd_test_drive_present %d\n", drive);
1403 	if (drive > 1)
1404 		return (0);
1405 	return (1);		/* Simple hack for the moment - the autodetect doesn't seem to work on arc */
1406 	fd_select_drive(drive);
1407 
1408 	/* disable interrupt temporarily */
1409 	DISABLE_IRQ();
1410 	FDC1772_WRITE(FDC1772REG_TRACK, 0x00);	/* was ff00 why? */
1411 	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1412 
1413 	/*printk("fd_test_drive_present: Going into timeout loop\n"); */
1414 	for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1415 		/*  What does this piece of atariism do? - query for an interrupt? */
1416 		/*  if (!(mfp.par_dt_reg & 0x20))
1417 		   break; */
1418 		/* Well this is my nearest guess - quit when we get an FDC interrupt */
1419 		if (ioc_readb(IOC_FIQSTAT) & 2)
1420 			break;
1421 	}
1422 
1423 	/*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
1424 	status = FDC1772_READ(FDC1772REG_STATUS);
1425 	ok = (status & FDC1772STAT_TR00) != 0;
1426 
1427 	/*printk("fd_test_drive_present: ok=%d\n",ok); */
1428 	/* force interrupt to abort restore operation (FDC1772 would try
1429 	 * about 50 seconds!) */
1430 	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1431 	udelay(500);
1432 	status = FDC1772_READ(FDC1772REG_STATUS);
1433 	udelay(20);
1434 	/*printk("fd_test_drive_present: just before OK code %d\n",ok); */
1435 
1436 	if (ok) {
1437 		/* dummy seek command to make WP bit accessible */
1438 		FDC1772_WRITE(FDC1772REG_DATA, 0);
1439 		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1440 		printk("fd_test_drive_present: just before wait for int\n");
1441 		/* DAG: Guess means wait for interrupt */
1442 		while (!(ioc_readb(IOC_FIQSTAT) & 2));
1443 		printk("fd_test_drive_present: just after wait for int\n");
1444 		status = FDC1772_READ(FDC1772REG_STATUS);
1445 	}
1446 	printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1447 	ENABLE_IRQ();
1448 	printk("fd_test_drive_present: about to return\n");
1449 	return (ok);
1450 }
1451 
1452 
1453 /* Look how many and which kind of drives are connected. If there are
1454  * floppies, additionally start the disk-change and motor-off timers.
1455  */
1456 
config_types(void)1457 static void config_types(void)
1458 {
1459 	int drive, cnt = 0;
1460 
1461 	printk("Probing floppy drive(s):\n");
1462 	for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1463 		fd_probe(drive);
1464 		if (unit[drive].connected) {
1465 			printk("fd%d\n", drive);
1466 			++cnt;
1467 		}
1468 	}
1469 
1470 	if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1471 		/* If FDC1772 is still busy from probing, give it another FORCI
1472 		 * command to abort the operation. If this isn't done, the FDC1772
1473 		 * will interrupt later and its IRQ line stays low, because
1474 		 * the status register isn't read. And this will block any
1475 		 * interrupts on this IRQ line :-(
1476 		 */
1477 		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1478 		udelay(500);
1479 		FDC1772_READ(FDC1772REG_STATUS);
1480 		udelay(20);
1481 	}
1482 	if (cnt > 0) {
1483 		START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1484 		if (cnt == 1)
1485 			fd_select_drive(0);
1486 		/*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1487 	}
1488 }
1489 
1490 /*
1491  * floppy_open check for aliasing (/dev/fd0 can be the same as
1492  * /dev/PS0 etc), and disallows simultaneous access to the same
1493  * drive with different device numbers.
1494  */
1495 
floppy_open(struct inode * inode,struct file * filp)1496 static int floppy_open(struct inode *inode, struct file *filp)
1497 {
1498 	int drive;
1499 	int old_dev;
1500 
1501 	if (!filp) {
1502 		DPRINT(("Weird, open called with filp=0\n"));
1503 		return -EIO;
1504 	}
1505 	drive = MINOR(inode->i_rdev) & 3;
1506 	if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES)
1507 		return -ENXIO;
1508 
1509 	old_dev = fd_device[drive];
1510 
1511 	if (fd_ref[drive])
1512 		if (old_dev != inode->i_rdev)
1513 			return -EBUSY;
1514 
1515 	if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1516 		return -EBUSY;
1517 
1518 	if (filp->f_flags & O_EXCL)
1519 		fd_ref[drive] = -1;
1520 	else
1521 		fd_ref[drive]++;
1522 
1523 	fd_device[drive] = inode->i_rdev;
1524 
1525 	if (old_dev && old_dev != inode->i_rdev)
1526 		invalidate_buffers(old_dev);
1527 
1528 	if (filp->f_flags & O_NDELAY)
1529 		return 0;
1530 
1531 	if (filp->f_mode & 3) {
1532 		check_disk_change(inode->i_rdev);
1533 		if (filp->f_mode & 2) {
1534 			if (unit[drive].wpstat) {
1535 				floppy_release(inode, filp);
1536 				return -EROFS;
1537 			}
1538 		}
1539 	}
1540 	return 0;
1541 }
1542 
1543 
floppy_release(struct inode * inode,struct file * filp)1544 static int floppy_release(struct inode *inode, struct file *filp)
1545 {
1546 	int drive = MINOR(inode->i_rdev) & 3;
1547 
1548 	if (fd_ref[drive] < 0)
1549 		fd_ref[drive] = 0;
1550 	else if (!fd_ref[drive]--) {
1551 		printk("floppy_release with fd_ref == 0");
1552 		fd_ref[drive] = 0;
1553 	}
1554 
1555 	return 0;
1556 }
1557 
1558 static struct block_device_operations floppy_fops =
1559 {
1560 	open:			floppy_open,
1561 	release:		floppy_release,
1562 	ioctl:			fd_ioctl,
1563 	check_media_change:	check_floppy_change,
1564 	revalidate:		floppy_revalidate,
1565 };
1566 
1567 
fd1772_init(void)1568 int fd1772_init(void)
1569 {
1570 	int i, err;
1571 
1572 	if (!machine_is_archimedes())
1573 		return 0;
1574 
1575 	err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
1576 	if (err) {
1577 		printk("Unable to get major %d for floppy\n", MAJOR_NR);
1578 		goto err_out;
1579 	}
1580 
1581 	err = -EBUSY;
1582 	if (request_dma(FLOPPY_DMA, "fd1772")) {
1583 		printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1584 		goto err_blkdev;
1585 	};
1586 
1587 	if (request_dma(FIQ_FD1772, "fd1772 end")) {
1588 		printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1589 		goto err_dma1;
1590 	};
1591 
1592 	/* initialize variables */
1593 	err = -ENOMEM;
1594 	SelectedDrive = -1;
1595 #ifdef TRACKBUFFER
1596 	BufferDrive = BufferSide = BufferTrack = -1;
1597 	/* Atari uses 512 - I want to eventually cope with 1K sectors */
1598 	DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
1599 	TrackBuffer = DMABuffer + 512;
1600 #else
1601 	/* Allocate memory for the DMAbuffer - on the Atari this takes it
1602 	   out of some special memory... */
1603 	DMABuffer = (char *) kmalloc(2048);	/* Copes with pretty large sectors */
1604 #endif
1605 	if (DMABuffer == NULL)
1606 		goto err_dma2;
1607 
1608 	enable_dma(FIQ_FD1772);	/* This inserts a call to our command end routine */
1609 	for (i = 0; i < FD_MAX_UNITS; i++) {
1610 		unit[i].track = -1;
1611 	}
1612 
1613 	for (i = 0; i < 256; i++)
1614 		if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
1615 			floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
1616 		else
1617 			floppy_sizes[i] = MAX_DISK_SIZE;
1618 
1619 	blk_size[MAJOR_NR] = floppy_sizes;
1620 	blksize_size[MAJOR_NR] = floppy_blocksizes;
1621 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1622 
1623 	config_types();
1624 
1625 	return 0;
1626 
1627  err_dma2:
1628 	free_dma(FIQ_FD1772);
1629  err_dma1:
1630 	free_dma(FLOPPY_DMA);
1631  err_blkdev:
1632 	unregister_blkdev(MAJOR_NR, &floppy_fops);
1633  err_out:
1634 	return err;
1635 }
1636