1 /*
2  * linux/arch/arm/drivers/block/mfmhd.c
3  *
4  * Copyright (C) 1995, 1996 Russell King, Dave Alan Gilbert (gilbertd@cs.man.ac.uk)
5  *
6  * MFM hard drive code [experimental]
7  */
8 
9 /*
10  * Change list:
11  *
12  *  3/2/96:DAG: Started a change list :-)
13  *              Set the hardsect_size pointers up since we are running 256 byte
14  *                sectors
15  *              Added DMA code, put it into the rw_intr
16  *              Moved RCAL out of generic interrupt code - don't want to do it
17  *                while DMA'ing - its now in individual handlers.
18  *              Took interrupt handlers off task queue lists and called
19  *                directly - not sure of implications.
20  *
21  * 18/2/96:DAG: Well its reading OK I think, well enough for image file code
22  *              to find the image file; but now I've discovered that I actually
23  *              have to put some code in for image files.
24  *
25  *              Added stuff for image files; seems to work, but I've not
26  *              got a multisegment image file (I don't think!).
27  *              Put in a hack (yep a real hack) for multiple cylinder reads.
28  *              Not convinced its working.
29  *
30  *  5/4/96:DAG: Added asm/hardware.h and use IOC_ macros
31  *              Rewrote dma code in mfm.S (again!) - now takes a word at a time
32  *              from main RAM for speed; still doesn't feel speedy!
33  *
34  * 20/4/96:DAG: After rewriting mfm.S a heck of a lot of times and speeding
35  *              things up, I've finally figured out why its so damn slow.
36  *              Linux is only reading a block at a time, and so you never
37  *              get more than 1K per disc revoloution ~=60K/second.
38  *
39  * 27/4/96:DAG: On Russell's advice I change ll_rw_blk.c to ask it to
40  *              join adjacent blocks together. Everything falls flat on its
41  *              face.
42  *              Four hours of debugging later; I hadn't realised that
43  *              ll_rw_blk would be so generous as to join blocks whose
44  *              results aren't going into consecutive buffers.
45  *
46  *              OK; severe rehacking of mfm_rw_interrupt; now end_request's
47  *              as soon as its DMA'd each request.  Odd thing is that
48  *              we are sometimes getting interrupts where we are not transferring
49  *              any data; why? Is that what happens when you miss? I doubt
50  *              it; are we too fast? No - its just at command ends. Got 240K/s
51  *              better than before, but RiscOS hits 480K/s
52  *
53  * 25/6/96:RMK: Fixed init code to allow the MFM podule to work.  Increased the
54  *              number of errors for my Miniscribe drive (8425).
55  *
56  * 30/6/96:DAG: Russell suggested that a check drive 0 might turn the LEDs off
57  *              - so in request_done just before it clears Busy it sends a
58  *              check drive 0 - and the LEDs go off!!!!
59  *
60  *              Added test for mainboard controller. - Removes need for separate
61  *              define.
62  *
63  * 13/7/96:DAG: Changed hardware sectore size to 512 in attempt to make
64  *              IM drivers work.
65  * 21/7/96:DAG: Took out old image file stuff (accessing it now produces an IO
66  *              error.)
67  *
68  * 17/8/96:DAG: Ran through indent -kr -i8; evil - all my nice 2 character indents
69  *              gone :-( Hand modified afterwards.
70  *		Took out last remains of the older image map system.
71  *
72  * 22/9/96:DAG:	Changed mfm.S so it will carry on DMA'ing til; BSY is dropped
73  *		Changed mfm_rw_intr so that it doesn't follow the error
74  *		code until BSY is dropped. Nope - still broke. Problem
75  *		may revolve around when it reads the results for the error
76  *		number?
77  *
78  *16/11/96:DAG:	Modified for 2.0.18; request_irq changed
79  *
80  *17/12/96:RMK: Various cleanups, reorganisation, and the changes for new IO system.
81  *		Improved probe for onboard MFM chip - it was hanging on my A5k.
82  *		Added autodetect CHS code such that we don't rely on the presence
83  *		of an ADFS boot block.  Added ioport resource manager calls so
84  *		that we don't clash with already-running hardware (eg. RiscPC Ether
85  *		card slots if someone tries this)!
86  *
87  * 17/1/97:RMK:	Upgraded to 2.1 kernels.
88  *
89  *  4/3/98:RMK:	Changed major number to 21.
90  *
91  * 27/6/98:RMK:	Changed asm/delay.h to linux/delay.h for mdelay().
92  */
93 
94 /*
95  * Possible enhancements:
96  *  Multi-thread the code so that it is possible that while one drive
97  *  is seeking, the other one can be reading data/seeking as well.
98  *  This would be a performance boost with dual drive systems.
99  */
100 
101 #include <linux/module.h>
102 #include <linux/config.h>
103 #include <linux/sched.h>
104 #include <linux/fs.h>
105 #include <linux/interrupt.h>
106 #include <linux/kernel.h>
107 #include <linux/timer.h>
108 #include <linux/tqueue.h>
109 #include <linux/mm.h>
110 #include <linux/errno.h>
111 #include <linux/genhd.h>
112 #include <linux/major.h>
113 #include <linux/ioport.h>
114 #include <linux/delay.h>
115 
116 #define MAJOR_NR	MFM_ACORN_MAJOR
117 #include <linux/blk.h>
118 #include <linux/blkpg.h>
119 
120 #include <asm/system.h>
121 #include <asm/io.h>
122 #include <asm/irq.h>
123 #include <asm/uaccess.h>
124 #include <asm/dma.h>
125 #include <asm/hardware.h>
126 #include <asm/ecard.h>
127 #include <asm/hardware/ioc.h>
128 
129 /*
130  * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
131  */
132 #ifndef HDIO_GETGEO
133 #define HDIO_GETGEO 0x301
134 struct hd_geometry {
135 	unsigned char heads;
136 	unsigned char sectors;
137 	unsigned short cylinders;
138 	unsigned long start;
139 };
140 #endif
141 
142 
143 /*
144  * Configuration section
145  *
146  * This is the maximum number of drives that we accept
147  */
148 #define MFM_MAXDRIVES 2
149 /*
150  * Linux I/O address of onboard MFM controller or 0 to disable this
151  */
152 #define ONBOARD_MFM_ADDRESS ((0x002d0000 >> 2) | 0x80000000)
153 /*
154  * Uncomment this to enable debugging in the MFM driver...
155  */
156 #ifndef DEBUG
157 /*#define DEBUG */
158 #endif
159 /*
160  * List of card types that we recognise
161  */
162 static const card_ids mfm_cids[] = {
163 	{ MANU_ACORN, PROD_ACORN_MFM },
164 	{ 0xffff, 0xffff }
165 };
166 /*
167  * End of configuration
168  */
169 
170 
171 /*
172  * This structure contains all information to do with a particular physical
173  * device.
174  */
175 struct mfm_info {
176 	unsigned char sectors;
177 	unsigned char heads;
178 	unsigned short cylinders;
179 	unsigned short lowcurrent;
180 	unsigned short precomp;
181 #define NO_TRACK -1
182 #define NEED_1_RECAL -2
183 #define NEED_2_RECAL -3
184 		 int cylinder;
185 	unsigned int access_count;
186 	unsigned int busy;
187 	struct {
188 		char recal;
189 		char report;
190 		char abort;
191 	} errors;
192 } mfm_info[MFM_MAXDRIVES];
193 
194 #define MFM_DRV_INFO mfm_info[raw_cmd.dev]
195 
196 static struct hd_struct mfm[MFM_MAXDRIVES << 6];
197 static int mfm_sizes[MFM_MAXDRIVES << 6];
198 static int mfm_blocksizes[MFM_MAXDRIVES << 6];
199 static int mfm_sectsizes[MFM_MAXDRIVES << 6];
200 static DECLARE_WAIT_QUEUE_HEAD(mfm_wait_open);
201 
202 /* Stuff from the assembly routines */
203 extern unsigned int hdc63463_baseaddress;	/* Controller base address */
204 extern unsigned int hdc63463_irqpolladdress;	/* Address to read to test for int */
205 extern unsigned int hdc63463_irqpollmask;	/* Mask for irq register */
206 extern unsigned int hdc63463_dataptr;	/* Pointer to kernel data space to DMA */
207 extern int hdc63463_dataleft;	/* Number of bytes left to transfer */
208 
209 
210 
211 
212 static int lastspecifieddrive;
213 static unsigned Busy;
214 
215 static unsigned int PartFragRead;	/* The number of sectors which have been read
216 					   during a partial read split over two
217 					   cylinders.  If 0 it means a partial
218 					   read did not occur. */
219 
220 static unsigned int PartFragRead_RestartBlock;	/* Where to restart on a split access */
221 static unsigned int PartFragRead_SectorsLeft;	/* Where to restart on a split access */
222 
223 static int Sectors256LeftInCurrent;	/* i.e. 256 byte sectors left in current */
224 static int SectorsLeftInRequest;	/* i.e. blocks left in the thing mfm_request was called for */
225 static int Copy_Sector;		/* The 256 byte sector we are currently at - fragments need to know
226 				   where to take over */
227 static char *Copy_buffer;
228 
229 
230 static void mfm_seek(void);
231 static void mfm_rerequest(void);
232 static void mfm_request(void);
233 static int mfm_reread_partitions(kdev_t dev);
234 static void mfm_specify (void);
235 static void issue_request(int dev, unsigned int block, unsigned int nsect,
236 			  struct request *req);
237 
238 static unsigned int mfm_addr;		/* Controller address */
239 static unsigned int mfm_IRQPollLoc;	/* Address to read for IRQ information */
240 static unsigned int mfm_irqenable;	/* Podule IRQ enable location */
241 static unsigned char mfm_irq;		/* Interrupt number */
242 static int mfm_drives = 0;		/* drives available */
243 static int mfm_status = 0;		/* interrupt status */
244 static int *errors;
245 
246 static struct rawcmd {
247 	unsigned int dev;
248 	unsigned int cylinder;
249 	unsigned int head;
250 	unsigned int sector;
251 	unsigned int cmdtype;
252 	unsigned int cmdcode;
253 	unsigned char cmddata[16];
254 	unsigned int cmdlen;
255 } raw_cmd;
256 
257 static unsigned char result[16];
258 
259 static struct cont {
260 	void (*interrupt) (void);	/* interrupt handler */
261 	void (*error) (void);	/* error handler */
262 	void (*redo) (void);	/* redo handler */
263 	void (*done) (int st);	/* done handler */
264 } *cont = NULL;
265 
266 #if 0
267 static struct tq_struct mfm_tq = {0, 0, (void (*)(void *)) NULL, 0};
268 #endif
269 
270 int number_mfm_drives = 1;
271 
272 /* ------------------------------------------------------------------------------------------ */
273 /*
274  * From the HD63463 data sheet from Hitachi Ltd.
275  */
276 
277 #define MFM_COMMAND (mfm_addr + 0)
278 #define MFM_DATAOUT (mfm_addr + 1)
279 #define MFM_STATUS  (mfm_addr + 8)
280 #define MFM_DATAIN  (mfm_addr + 9)
281 
282 #define CMD_ABT		0xF0	/* Abort */
283 #define CMD_SPC		0xE8	/* Specify */
284 #define CMD_TST		0xE0	/* Test */
285 #define CMD_RCLB	0xC8	/* Recalibrate */
286 #define CMD_SEK		0xC0	/* Seek */
287 #define CMD_WFS		0xAB	/* Write Format Skew */
288 #define CMD_WFM		0xA3	/* Write Format */
289 #define CMD_MTB		0x90	/* Memory to buffer */
290 #define CMD_CMPD	0x88	/* Compare data */
291 #define CMD_WD		0x87	/* Write data */
292 #define CMD_RED		0x70	/* Read erroneous data */
293 #define CMD_RIS		0x68	/* Read ID skew */
294 #define CMD_FID		0x61	/* Find ID */
295 #define CMD_RID		0x60	/* Read ID */
296 #define CMD_BTM		0x50	/* Buffer to memory */
297 #define CMD_CKD		0x48	/* Check data */
298 #define CMD_RD		0x40	/* Read data */
299 #define CMD_OPBW	0x38	/* Open buffer write */
300 #define CMD_OPBR	0x30	/* Open buffer read */
301 #define CMD_CKV		0x28	/* Check drive */
302 #define CMD_CKE		0x20	/* Check ECC */
303 #define CMD_POD		0x18	/* Polling disable */
304 #define CMD_POL		0x10	/* Polling enable */
305 #define CMD_RCAL	0x08	/* Recall */
306 
307 #define STAT_BSY	0x8000	/* Busy */
308 #define STAT_CPR	0x4000	/* Command Parameter Rejection */
309 #define STAT_CED	0x2000	/* Command end */
310 #define STAT_SED	0x1000	/* Seek end */
311 #define STAT_DER	0x0800	/* Drive error */
312 #define STAT_ABN	0x0400	/* Abnormal end */
313 #define STAT_POL	0x0200	/* Polling */
314 
315 /* ------------------------------------------------------------------------------------------ */
316 #ifdef DEBUG
console_printf(const char * fmt,...)317 static void console_printf(const char *fmt,...)
318 {
319 	static char buffer[2048];	/* Arbitary! */
320 	extern void console_print(const char *);
321 	unsigned long flags;
322 	va_list ap;
323 
324 	save_flags_cli(flags);
325 
326 	va_start(ap, fmt);
327 	vsprintf(buffer, fmt, ap);
328 	console_print(buffer);
329 	va_end(fmt);
330 
331 	restore_flags(flags);
332 };	/* console_printf */
333 
334 #define DBG(x...) console_printf(x)
335 #else
336 #define DBG(x...)
337 #endif
338 
print_status(void)339 static void print_status(void)
340 {
341 	char *error;
342 	static char *errors[] = {
343          "no error",
344 	 "command aborted",
345 	 "invalid command",
346 	 "parameter error",
347 	 "not initialised",
348 	 "rejected TEST",
349 	 "no useld",
350 	 "write fault",
351 	 "not ready",
352 	 "no scp",
353 	 "in seek",
354 	 "invalid NCA",
355 	 "invalid step rate",
356 	 "seek error",
357 	 "over run",
358 	 "invalid PHA",
359 	 "data field EEC error",
360 	 "data field CRC error",
361 	 "error corrected",
362 	 "data field fatal error",
363 	 "no data am",
364 	 "not hit",
365 	 "ID field CRC error",
366 	 "time over",
367 	 "no ID am",
368 	 "not writable"
369 	};
370 	if (result[1] < 0x65)
371 		error = errors[result[1] >> 2];
372 	else
373 		error = "unknown";
374 	printk("(");
375 	if (mfm_status & STAT_BSY) printk("BSY ");
376 	if (mfm_status & STAT_CPR) printk("CPR ");
377 	if (mfm_status & STAT_CED) printk("CED ");
378 	if (mfm_status & STAT_SED) printk("SED ");
379 	if (mfm_status & STAT_DER) printk("DER ");
380 	if (mfm_status & STAT_ABN) printk("ABN ");
381 	if (mfm_status & STAT_POL) printk("POL ");
382 	printk(") SSB = %X (%s)\n", result[1], error);
383 
384 }
385 
386 /* ------------------------------------------------------------------------------------- */
387 
issue_command(int command,unsigned char * cmdb,int len)388 static void issue_command(int command, unsigned char *cmdb, int len)
389 {
390 	int status;
391 #ifdef DEBUG
392 	int i;
393 	console_printf("issue_command: %02X: ", command);
394 	for (i = 0; i < len; i++)
395 		console_printf("%02X ", cmdb[i]);
396 	console_printf("\n");
397 #endif
398 
399 	do {
400 		status = inw(MFM_STATUS);
401 	} while (status & (STAT_BSY | STAT_POL));
402 	DBG("issue_command: status after pol/bsy loop: %02X:\n ", status >> 8);
403 
404 	if (status & (STAT_CPR | STAT_CED | STAT_SED | STAT_DER | STAT_ABN)) {
405 		outw(CMD_RCAL, MFM_COMMAND);
406 		while (inw(MFM_STATUS) & STAT_BSY);
407 	}
408 	status = inw(MFM_STATUS);
409 	DBG("issue_command: status before parameter issue: %02X:\n ", status >> 8);
410 
411 	while (len > 0) {
412 		outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT);
413 		len -= 2;
414 		cmdb += 2;
415 	}
416 	status = inw(MFM_STATUS);
417 	DBG("issue_command: status before command issue: %02X:\n ", status >> 8);
418 
419 	outw(command, MFM_COMMAND);
420 	status = inw(MFM_STATUS);
421 	DBG("issue_command: status immediatly after command issue: %02X:\n ", status >> 8);
422 }
423 
wait_for_completion(void)424 static void wait_for_completion(void)
425 {
426 	while ((mfm_status = inw(MFM_STATUS)) & STAT_BSY);
427 }
428 
wait_for_command_end(void)429 static void wait_for_command_end(void)
430 {
431 	int i;
432 
433 	while (!((mfm_status = inw(MFM_STATUS)) & STAT_CED));
434 
435 	for (i = 0; i < 16;) {
436 		int in;
437 		in = inw(MFM_DATAIN);
438 		result[i++] = in >> 8;
439 		result[i++] = in;
440 	}
441 	outw (CMD_RCAL, MFM_COMMAND);
442 }
443 
444 /* ------------------------------------------------------------------------------------- */
445 
mfm_rw_intr(void)446 static void mfm_rw_intr(void)
447 {
448 	int old_status;		/* Holds status on entry, we read to see if the command just finished */
449 #ifdef DEBUG
450 	console_printf("mfm_rw_intr...dataleft=%d\n", hdc63463_dataleft);
451 	print_status();
452 #endif
453 
454   /* Now don't handle the error until BSY drops */
455 	if ((mfm_status & (STAT_DER | STAT_ABN)) && ((mfm_status&STAT_BSY)==0)) {
456 		/* Something has gone wrong - let's try that again */
457 		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
458 		if (cont) {
459 			DBG("mfm_rw_intr: DER/ABN err\n");
460 			cont->error();
461 			cont->redo();
462 		};
463 		return;
464 	};
465 
466 	/* OK so what ever happend its not an error, now I reckon we are left between
467 	   a choice of command end or some data which is ready to be collected */
468 	/* I think we have to transfer data while the interrupt line is on and its
469 	   not any other type of interrupt */
470 	if (CURRENT->cmd == WRITE) {
471 		extern void hdc63463_writedma(void);
472 		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
473 			printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
474 			if (cont) {
475 				cont->error();
476 				cont->redo();
477 			};
478 			return;
479 		};
480 		hdc63463_writedma();
481 	} else {
482 		extern void hdc63463_readdma(void);
483 		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
484 			printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n");
485 			if (cont) {
486 				cont->error();
487 				cont->redo();
488 			};
489 			return;
490 		};
491 		DBG("Going to try read dma..............status=0x%x, buffer=%p\n", mfm_status, hdc63463_dataptr);
492 		hdc63463_readdma();
493 	};			/* Read */
494 
495 	if (hdc63463_dataptr != ((unsigned int) Copy_buffer + 256)) {
496 		/* If we didn't actually manage to get any data on this interrupt - but why? We got the interrupt */
497 		/* Ah - well looking at the status its just when we get command end; so no problem */
498 		/*console_printf("mfm: dataptr mismatch. dataptr=0x%08x Copy_buffer+256=0x%08p\n",
499 		   hdc63463_dataptr,Copy_buffer+256);
500 		   print_status(); */
501 	} else {
502 		Sectors256LeftInCurrent--;
503 		Copy_buffer += 256;
504 		Copy_Sector++;
505 
506 		/* We have come to the end of this request */
507 		if (!Sectors256LeftInCurrent) {
508 			DBG("mfm: end_request for CURRENT=0x%p CURRENT(sector=%d current_nr_sectors=%d nr_sectors=%d)\n",
509 				       CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->nr_sectors);
510 
511 			CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
512 			CURRENT->sector += CURRENT->current_nr_sectors;
513 			SectorsLeftInRequest -= CURRENT->current_nr_sectors;
514 
515 			end_request(1);
516 			if (SectorsLeftInRequest) {
517 				hdc63463_dataptr = (unsigned int) CURRENT->buffer;
518 				Copy_buffer = CURRENT->buffer;
519 				Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
520 				errors = &(CURRENT->errors);
521 				/* These should match the present calculations of the next logical sector
522 				   on the device
523 				   Copy_Sector=CURRENT->sector*2; */
524 
525 				if (Copy_Sector != CURRENT->sector * 2)
526 #ifdef DEBUG
527 					/*console_printf*/printk("mfm: Copy_Sector mismatch. Copy_Sector=%d CURRENT->sector*2=%d\n",
528 					Copy_Sector, CURRENT->sector * 2);
529 #else
530 					printk("mfm: Copy_Sector mismatch! Eek!\n");
531 #endif
532 			};	/* CURRENT */
533 		};	/* Sectors256LeftInCurrent */
534 	};
535 
536 	old_status = mfm_status;
537 	mfm_status = inw(MFM_STATUS);
538 	if (mfm_status & (STAT_DER | STAT_ABN)) {
539 		/* Something has gone wrong - let's try that again */
540 		if (cont) {
541 			DBG("mfm_rw_intr: DER/ABN error\n");
542 			cont->error();
543 			cont->redo();
544 		};
545 		return;
546 	};
547 
548 	/* If this code wasn't entered due to command_end but there is
549 	   now a command end we must read the command results out. If it was
550 	   entered like this then mfm_interrupt_handler would have done the
551 	   job. */
552 	if ((!((old_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) &&
553 	    ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) {
554 		int len = 0;
555 		while (len < 16) {
556 			int in;
557 			in = inw(MFM_DATAIN);
558 			result[len++] = in >> 8;
559 			result[len++] = in;
560 		};
561 	};			/* Result read */
562 
563 	/*console_printf ("mfm_rw_intr nearexit [%02X]\n", __raw_readb(mfm_IRQPollLoc)); */
564 
565 	/* If end of command move on */
566 	if (mfm_status & (STAT_CED)) {
567 		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
568 		/* End of command - trigger the next command */
569 		if (cont) {
570 			cont->done(1);
571 		}
572 		DBG("mfm_rw_intr: returned from cont->done\n");
573 	} else {
574 		/* Its going to generate another interrupt */
575 		SET_INTR(mfm_rw_intr);
576 	};
577 }
578 
mfm_setup_rw(void)579 static void mfm_setup_rw(void)
580 {
581 	DBG("setting up for rw...\n");
582 
583 	SET_INTR(mfm_rw_intr);
584 	issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen);
585 }
586 
mfm_recal_intr(void)587 static void mfm_recal_intr(void)
588 {
589 #ifdef DEBUG
590 	console_printf("recal intr - status = ");
591 	print_status();
592 #endif
593 	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
594 	if (mfm_status & (STAT_DER | STAT_ABN)) {
595 		printk("recal failed\n");
596 		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
597 		if (cont) {
598 			cont->error();
599 			cont->redo();
600 		}
601 		return;
602 	}
603 	/* Thats seek end - we are finished */
604 	if (mfm_status & STAT_SED) {
605 		issue_command(CMD_POD, NULL, 0);
606 		MFM_DRV_INFO.cylinder = 0;
607 		mfm_seek();
608 		return;
609 	}
610 	/* Command end without seek end (see data sheet p.20) for parallel seek
611 	   - we have to send a POL command to wait for the seek */
612 	if (mfm_status & STAT_CED) {
613 		SET_INTR(mfm_recal_intr);
614 		issue_command(CMD_POL, NULL, 0);
615 		return;
616 	}
617 	printk("recal: unknown status\n");
618 }
619 
mfm_seek_intr(void)620 static void mfm_seek_intr(void)
621 {
622 #ifdef DEBUG
623 	console_printf("seek intr - status = ");
624 	print_status();
625 #endif
626 	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
627 	if (mfm_status & (STAT_DER | STAT_ABN)) {
628 		printk("seek failed\n");
629 		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
630 		if (cont) {
631 			cont->error();
632 			cont->redo();
633 		}
634 		return;
635 	}
636 	if (mfm_status & STAT_SED) {
637 		issue_command(CMD_POD, NULL, 0);
638 		MFM_DRV_INFO.cylinder = raw_cmd.cylinder;
639 		mfm_seek();
640 		return;
641 	}
642 	if (mfm_status & STAT_CED) {
643 		SET_INTR(mfm_seek_intr);
644 		issue_command(CMD_POL, NULL, 0);
645 		return;
646 	}
647 	printk("seek: unknown status\n");
648 }
649 
650 /* IDEA2 seems to work better - its what RiscOS sets my
651  * disc to - on its SECOND call to specify!
652  */
653 #define IDEA2
654 #ifndef IDEA2
655 #define SPEC_SL 0x16
656 #define SPEC_SH 0xa9		/* Step pulse high=21, Record Length=001 (256 bytes) */
657 #else
658 #define SPEC_SL 0x00		/* OM2 - SL - step pulse low */
659 #define SPEC_SH 0x21		/* Step pulse high=4, Record Length=001 (256 bytes) */
660 #endif
661 
mfm_setupspecify(int drive,unsigned char * cmdb)662 static void mfm_setupspecify (int drive, unsigned char *cmdb)
663 {
664 	cmdb[0]  = 0x1f;		/* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */
665 	cmdb[1]  = 0xc3;		/* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */
666 	cmdb[2]  = SPEC_SL;		/* OM2 - SL - step pulse low */
667 	cmdb[3]  = (number_mfm_drives == 1) ? 0x02 : 0x06;	/* 1 or 2 drives */
668 	cmdb[4]  = 0xfc | ((mfm_info[drive].cylinders - 1) >> 8);/* RW time over/high part of number of cylinders */
669 	cmdb[5]  = mfm_info[drive].cylinders - 1;		/* low part of number of cylinders */
670 	cmdb[6]  = mfm_info[drive].heads - 1;			/* Number of heads */
671 	cmdb[7]  = mfm_info[drive].sectors - 1;			/* Number of sectors */
672 	cmdb[8]  = SPEC_SH;
673 	cmdb[9]  = 0x0a;		/* gap length 1 */
674 	cmdb[10] = 0x0d;		/* gap length 2 */
675 	cmdb[11] = 0x0c;		/* gap length 3 */
676 	cmdb[12] = (mfm_info[drive].precomp - 1) >> 8;	/* pre comp cylinder */
677 	cmdb[13] = mfm_info[drive].precomp - 1;
678 	cmdb[14] = (mfm_info[drive].lowcurrent - 1) >> 8;	/* Low current cylinder */
679 	cmdb[15] = mfm_info[drive].lowcurrent - 1;
680 }
681 
mfm_specify(void)682 static void mfm_specify (void)
683 {
684 	unsigned char cmdb[16];
685 
686 	DBG("specify...dev=%d lastspecified=%d\n", raw_cmd.dev, lastspecifieddrive);
687 	mfm_setupspecify (raw_cmd.dev, cmdb);
688 
689 	issue_command (CMD_SPC, cmdb, 16);
690 	/* Ensure that we will do another specify if we move to the other drive */
691 	lastspecifieddrive = raw_cmd.dev;
692 	wait_for_completion();
693 }
694 
mfm_seek(void)695 static void mfm_seek(void)
696 {
697 	unsigned char cmdb[4];
698 
699 	DBG("seeking...\n");
700 	if (MFM_DRV_INFO.cylinder < 0) {
701 		SET_INTR(mfm_recal_intr);
702 		DBG("mfm_seek: about to call specify\n");
703 		mfm_specify ();	/* DAG added this */
704 
705 		cmdb[0] = raw_cmd.dev + 1;
706 		cmdb[1] = 0;
707 
708 		issue_command(CMD_RCLB, cmdb, 2);
709 		return;
710 	}
711 	if (MFM_DRV_INFO.cylinder != raw_cmd.cylinder) {
712 		cmdb[0] = raw_cmd.dev + 1;
713 		cmdb[1] = 0;	/* raw_cmd.head; DAG: My data sheet says this should be 0 */
714 		cmdb[2] = raw_cmd.cylinder >> 8;
715 		cmdb[3] = raw_cmd.cylinder;
716 
717 		SET_INTR(mfm_seek_intr);
718 		issue_command(CMD_SEK, cmdb, 4);
719 	} else
720 		mfm_setup_rw();
721 }
722 
mfm_initialise(void)723 static void mfm_initialise(void)
724 {
725 	DBG("init...\n");
726 	mfm_seek();
727 }
728 
request_done(int uptodate)729 static void request_done(int uptodate)
730 {
731 	DBG("mfm:request_done\n");
732 	if (uptodate) {
733 		unsigned char block[2] = {0, 0};
734 
735 		/* Apparently worked - let's check bytes left to DMA */
736 		if (hdc63463_dataleft != (PartFragRead_SectorsLeft * 256)) {
737 			printk("mfm: request_done - dataleft=%d - should be %d - Eek!\n", hdc63463_dataleft, PartFragRead_SectorsLeft * 256);
738 			end_request(0);
739 			Busy = 0;
740 		};
741 		/* Potentially this means that we've done; but we might be doing
742 		   a partial access, (over two cylinders) or we may have a number
743 		   of fragments in an image file.  First let's deal with partial accesss
744 		 */
745 		if (PartFragRead) {
746 			/* Yep - a partial access */
747 
748 			/* and issue the remainder */
749 			issue_request(MINOR(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
750 			return;
751 		}
752 
753 		/* ah well - perhaps there is another fragment to go */
754 
755 		/* Increment pointers/counts to start of next fragment */
756 		if (SectorsLeftInRequest > 0) printk("mfm: SectorsLeftInRequest>0 - Eek! Shouldn't happen!\n");
757 
758 		/* No - its the end of the line */
759 		/* end_request's should have happened at the end of sector DMAs */
760 		/* Turns Drive LEDs off - may slow it down? */
761 		if (QUEUE_EMPTY)
762 			issue_command(CMD_CKV, block, 2);
763 
764 		Busy = 0;
765 		DBG("request_done: About to mfm_request\n");
766 		/* Next one please */
767 		mfm_request();	/* Moved from mfm_rw_intr */
768 		DBG("request_done: returned from mfm_request\n");
769 	} else {
770 		printk("mfm:request_done: update=0\n");
771 		end_request(0);
772 		Busy = 0;
773 	}
774 }
775 
error_handler(void)776 static void error_handler(void)
777 {
778 	printk("error detected... status = ");
779 	print_status();
780 	(*errors)++;
781 	if (*errors > MFM_DRV_INFO.errors.abort)
782 		cont->done(0);
783 	if (*errors > MFM_DRV_INFO.errors.recal)
784 		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
785 }
786 
rw_interrupt(void)787 static void rw_interrupt(void)
788 {
789 	printk("rw_interrupt\n");
790 }
791 
792 static struct cont rw_cont =
793 {
794 	rw_interrupt,
795 	error_handler,
796 	mfm_rerequest,
797 	request_done
798 };
799 
800 /*
801  * Actually gets round to issuing the request - note everything at this
802  * point is in 256 byte sectors not Linux 512 byte blocks
803  */
issue_request(int dev,unsigned int block,unsigned int nsect,struct request * req)804 static void issue_request(int dev, unsigned int block, unsigned int nsect,
805 			  struct request *req)
806 {
807 	int track, start_head, start_sector;
808 	int sectors_to_next_cyl;
809 
810 	dev >>= 6;
811 
812 	track = block / mfm_info[dev].sectors;
813 	start_sector = block % mfm_info[dev].sectors;
814 	start_head = track % mfm_info[dev].heads;
815 
816 	/* First get the number of whole tracks which are free before the next
817 	   track */
818 	sectors_to_next_cyl = (mfm_info[dev].heads - (start_head + 1)) * mfm_info[dev].sectors;
819 	/* Then add in the number of sectors left on this track */
820 	sectors_to_next_cyl += (mfm_info[dev].sectors - start_sector);
821 
822 	DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", mfm_info[dev].sectors, track);
823 
824 	raw_cmd.dev = dev;
825 	raw_cmd.sector = start_sector;
826 	raw_cmd.head = start_head;
827 	raw_cmd.cylinder = track / mfm_info[dev].heads;
828 	raw_cmd.cmdtype = CURRENT->cmd;
829 	raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
830 	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */
831 	raw_cmd.cmddata[1] = raw_cmd.head;
832 	raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
833 	raw_cmd.cmddata[3] = raw_cmd.cylinder;
834 	raw_cmd.cmddata[4] = raw_cmd.head;
835 	raw_cmd.cmddata[5] = raw_cmd.sector;
836 
837 	/* Was == and worked - how the heck??? */
838 	if (lastspecifieddrive != raw_cmd.dev)
839 		mfm_specify ();
840 
841 	if (nsect <= sectors_to_next_cyl) {
842 		raw_cmd.cmddata[6] = nsect >> 8;
843 		raw_cmd.cmddata[7] = nsect;
844 		PartFragRead = 0;	/* All in one */
845 		PartFragRead_SectorsLeft = 0;	/* Must set this - used in DMA calcs */
846 	} else {
847 		raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8;
848 		raw_cmd.cmddata[7] = sectors_to_next_cyl;
849 		PartFragRead = sectors_to_next_cyl;	/* only do this many this time */
850 		PartFragRead_RestartBlock = block + sectors_to_next_cyl;	/* Where to restart from */
851 		PartFragRead_SectorsLeft = nsect - sectors_to_next_cyl;
852 	}
853 	raw_cmd.cmdlen = 8;
854 
855 	/* Setup DMA pointers */
856 	hdc63463_dataptr = (unsigned int) Copy_buffer;
857 	hdc63463_dataleft = nsect * 256;	/* Better way? */
858 
859 	DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
860 	     raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
861 		       raw_cmd.cylinder,
862 		       raw_cmd.head,
863 	    raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
864 
865 	cont = &rw_cont;
866 	errors = &(CURRENT->errors);
867 #if 0
868 	mfm_tq.routine = (void (*)(void *)) mfm_initialise;
869 	queue_task(&mfm_tq, &tq_immediate);
870 	mark_bh(IMMEDIATE_BH);
871 #else
872 	mfm_initialise();
873 #endif
874 }				/* issue_request */
875 
876 /*
877  * Called when an error has just happened - need to trick mfm_request
878  * into thinking we weren't busy
879  *
880  * Turn off ints - mfm_request expects them this way
881  */
mfm_rerequest(void)882 static void mfm_rerequest(void)
883 {
884 	DBG("mfm_rerequest\n");
885 	cli();
886 	Busy = 0;
887 	mfm_request();
888 }
889 
mfm_request(void)890 static void mfm_request(void)
891 {
892 	DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy);
893 
894 	if (QUEUE_EMPTY) {
895 		DBG("mfm_request: Exited due to NULL Current 1\n");
896 		return;
897 	}
898 
899 	if (CURRENT->rq_status == RQ_INACTIVE) {
900 		/* Hmm - seems to be happening a lot on 1.3.45 */
901 		/*console_printf("mfm_request: Exited due to INACTIVE Current\n"); */
902 		return;
903 	}
904 
905 	/* If we are still processing then return; we will get called again */
906 	if (Busy) {
907 		/* Again seems to be common in 1.3.45 */
908 		/*DBG*/printk("mfm_request: Exiting due to busy\n");
909 		return;
910 	}
911 	Busy = 1;
912 
913 	while (1) {
914 		unsigned int dev, block, nsect;
915 
916 		DBG("mfm_request: loop start\n");
917 		sti();
918 
919 		DBG("mfm_request: before INIT_REQUEST\n");
920 
921 		if (QUEUE_EMPTY) {
922 			printk("mfm_request: Exiting due to !CURRENT (pre)\n");
923 			CLEAR_INTR;
924 			Busy = 0;
925 			return;
926 		};
927 
928 		INIT_REQUEST;
929 
930 		DBG("mfm_request:                 before arg extraction\n");
931 
932 		dev = MINOR(CURRENT->rq_dev);
933 		block = CURRENT->sector;
934 		nsect = CURRENT->nr_sectors;
935 #ifdef DEBUG
936 		/*if ((dev>>6)==1) */ console_printf("mfm_request:                                raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);
937 #endif
938 		if (dev >= (mfm_drives << 6) ||
939 		    block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) {
940 			if (dev >= (mfm_drives << 6))
941 				printk("mfm: bad minor number: device=%s\n", kdevname(CURRENT->rq_dev));
942 			else
943 				printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", (dev >> 6)+'a',
944 				       block, nsect, mfm[dev].nr_sects);
945 			printk("mfm: continue 1\n");
946 			end_request(0);
947 			Busy = 0;
948 			continue;
949 		}
950 
951 		block += mfm[dev].start_sect;
952 
953 		/* DAG: Linux doesn't cope with this - even though it has an array telling
954 		   it the hardware block size - silly */
955 		block <<= 1;	/* Now in 256 byte sectors */
956 		nsect <<= 1;	/* Ditto */
957 
958 		SectorsLeftInRequest = nsect >> 1;
959 		Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
960 		Copy_buffer = CURRENT->buffer;
961 		Copy_Sector = CURRENT->sector << 1;
962 
963 		DBG("mfm_request: block after offset=%d\n", block);
964 
965 		if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
966 			printk("unknown mfm-command %d\n", CURRENT->cmd);
967 			end_request(0);
968 			Busy = 0;
969 			printk("mfm: continue 4\n");
970 			continue;
971 		}
972 		issue_request(dev, block, nsect, CURRENT);
973 
974 		break;
975 	}
976 	DBG("mfm_request: Dropping out bottom\n");
977 }
978 
do_mfm_request(request_queue_t * q)979 static void do_mfm_request(request_queue_t *q)
980 {
981 	DBG("do_mfm_request: about to mfm_request\n");
982 	mfm_request();
983 }
984 
mfm_interrupt_handler(int unused,void * dev_id,struct pt_regs * regs)985 static void mfm_interrupt_handler(int unused, void *dev_id, struct pt_regs *regs)
986 {
987 	void (*handler) (void) = DEVICE_INTR;
988 
989 	CLEAR_INTR;
990 
991 	DBG("mfm_interrupt_handler (handler=0x%p)\n", handler);
992 
993 	mfm_status = inw(MFM_STATUS);
994 
995 	/* If CPR (Command Parameter Reject) and not busy it means that the command
996 	   has some return message to give us */
997 	if ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR) {
998 		int len = 0;
999 		while (len < 16) {
1000 			int in;
1001 			in = inw(MFM_DATAIN);
1002 			result[len++] = in >> 8;
1003 			result[len++] = in;
1004 		}
1005 	}
1006 	if (handler) {
1007 		handler();
1008 		return;
1009 	}
1010 	outw (CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
1011 	printk ("mfm: unexpected interrupt - status = ");
1012 	print_status ();
1013 	while (1);
1014 }
1015 
1016 
1017 
1018 
1019 
1020 /*
1021  * Tell the user about the drive if we decided it exists.
1022  */
mfm_geometry(int drive)1023 static void mfm_geometry (int drive)
1024 {
1025 	if (mfm_info[drive].cylinders)
1026 		printk ("mfm%c: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n", 'a' + drive,
1027 			mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 4096,
1028 			mfm_info[drive].cylinders, mfm_info[drive].heads, mfm_info[drive].sectors,
1029 			mfm_info[drive].lowcurrent, mfm_info[drive].precomp);
1030 }
1031 
1032 #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
1033 /*
1034  * Attempt to detect a drive and find its geometry.  The drive has already been
1035  * specified...
1036  *
1037  * We first recalibrate the disk, then try to probe sectors, heads and then
1038  * cylinders.  NOTE! the cylinder probe may break drives.  The xd disk driver
1039  * does something along these lines, so I assume that most drives are up to
1040  * this mistreatment...
1041  */
mfm_detectdrive(int drive)1042 static int mfm_detectdrive (int drive)
1043 {
1044 	unsigned int mingeo[3], maxgeo[3];
1045 	unsigned int attribute, need_recal = 1;
1046 	unsigned char cmdb[8];
1047 
1048 	memset (mingeo, 0, sizeof (mingeo));
1049 	maxgeo[0] = mfm_info[drive].sectors;
1050 	maxgeo[1] = mfm_info[drive].heads;
1051 	maxgeo[2] = mfm_info[drive].cylinders;
1052 
1053 	cmdb[0] = drive + 1;
1054 	cmdb[6] = 0;
1055 	cmdb[7] = 1;
1056 	for (attribute = 0; attribute < 3; attribute++) {
1057 		while (mingeo[attribute] != maxgeo[attribute]) {
1058 			unsigned int variable;
1059 
1060 			variable = (maxgeo[attribute] + mingeo[attribute]) >> 1;
1061 			cmdb[1] = cmdb[2] = cmdb[3] = cmdb[4] = cmdb[5] = 0;
1062 
1063 			if (need_recal) {
1064 				int tries = 5;
1065 
1066 				do {
1067 					issue_command (CMD_RCLB, cmdb, 2);
1068 					wait_for_completion ();
1069 					wait_for_command_end ();
1070 					if  (result[1] == 0x20)
1071 						break;
1072 				} while (result[1] && --tries);
1073 				if (result[1]) {
1074 					outw (CMD_RCAL, MFM_COMMAND);
1075 					return 0;
1076 				}
1077 				need_recal = 0;
1078 			}
1079 
1080 			switch (attribute) {
1081 			case 0:
1082 				cmdb[5] = variable;
1083 				issue_command (CMD_CMPD, cmdb, 8);
1084 				break;
1085 			case 1:
1086 				cmdb[1] = variable;
1087 				cmdb[4] = variable;
1088 				issue_command (CMD_CMPD, cmdb, 8);
1089 				break;
1090 			case 2:
1091 				cmdb[2] = variable >> 8;
1092 				cmdb[3] = variable;
1093 				issue_command (CMD_SEK, cmdb, 4);
1094 				break;
1095 			}
1096 			wait_for_completion ();
1097 			wait_for_command_end ();
1098 
1099 			switch (result[1]) {
1100 			case 0x00:
1101 			case 0x50:
1102 				mingeo[attribute] = variable + 1;
1103 				break;
1104 
1105 			case 0x20:
1106 				outw (CMD_RCAL, MFM_COMMAND);
1107 				return 0;
1108 
1109 			case 0x24:
1110 				need_recal = 1;
1111 			default:
1112 				maxgeo[attribute] = variable;
1113 				break;
1114 			}
1115 		}
1116 	}
1117 	mfm_info[drive].cylinders  = mingeo[2];
1118 	mfm_info[drive].lowcurrent = mingeo[2];
1119 	mfm_info[drive].precomp    = mingeo[2] / 2;
1120 	mfm_info[drive].heads 	   = mingeo[1];
1121 	mfm_info[drive].sectors	   = mingeo[0];
1122 	outw (CMD_RCAL, MFM_COMMAND);
1123 	return 1;
1124 }
1125 #endif
1126 
1127 /*
1128  * Initialise all drive information for this controller.
1129  */
mfm_initdrives(void)1130 static int mfm_initdrives(void)
1131 {
1132 	int drive;
1133 
1134 	if (number_mfm_drives > MFM_MAXDRIVES) {
1135 		number_mfm_drives = MFM_MAXDRIVES;
1136 		printk("No. of ADFS MFM drives is greater than MFM_MAXDRIVES - you can't have that many!\n");
1137 	}
1138 
1139 	for (drive = 0; drive < number_mfm_drives; drive++) {
1140 		mfm_info[drive].lowcurrent = 1;
1141 		mfm_info[drive].precomp    = 1;
1142 		mfm_info[drive].cylinder   = -1;
1143 		mfm_info[drive].errors.recal  = 0;
1144 		mfm_info[drive].errors.report = 0;
1145 		mfm_info[drive].errors.abort  = 4;
1146 
1147 #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
1148 		mfm_info[drive].cylinders  = 1024;
1149 		mfm_info[drive].heads	   = 8;
1150 		mfm_info[drive].sectors	   = 64;
1151 		{
1152 			unsigned char cmdb[16];
1153 
1154 			mfm_setupspecify (drive, cmdb);
1155 			cmdb[1] &= ~0x81;
1156 			issue_command (CMD_SPC, cmdb, 16);
1157 			wait_for_completion ();
1158 			if (!mfm_detectdrive (drive)) {
1159 				mfm_info[drive].cylinders = 0;
1160 				mfm_info[drive].heads     = 0;
1161 				mfm_info[drive].sectors   = 0;
1162 			}
1163 			cmdb[0] = cmdb[1] = 0;
1164 			issue_command (CMD_CKV, cmdb, 2);
1165 		}
1166 #else
1167 		mfm_info[drive].cylinders  = 1;	/* its going to have to figure it out from the partition info */
1168 		mfm_info[drive].heads      = 4;
1169 		mfm_info[drive].sectors    = 32;
1170 #endif
1171 	}
1172 	return number_mfm_drives;
1173 }
1174 
1175 
1176 
1177 /*
1178  * The 'front' end of the mfm driver follows...
1179  */
1180 
mfm_ioctl(struct inode * inode,struct file * file,u_int cmd,u_long arg)1181 static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
1182 {
1183 	struct hd_geometry *geo = (struct hd_geometry *) arg;
1184 	kdev_t dev;
1185 	int device, major, minor, err;
1186 
1187 	if (!inode || !(dev = inode->i_rdev))
1188 		return -EINVAL;
1189 
1190 	major = MAJOR(dev);
1191 	minor = MINOR(dev);
1192 
1193 	device = DEVICE_NR(MINOR(inode->i_rdev)), err;
1194 	if (device >= mfm_drives)
1195 		return -EINVAL;
1196 
1197 	switch (cmd) {
1198 	case HDIO_GETGEO:
1199 		if (!arg)
1200 			return -EINVAL;
1201 		if (put_user (mfm_info[device].heads, &geo->heads))
1202 			return -EFAULT;
1203 		if (put_user (mfm_info[device].sectors, &geo->sectors))
1204 			return -EFAULT;
1205 		if (put_user (mfm_info[device].cylinders, &geo->cylinders))
1206 			return -EFAULT;
1207 		if (put_user (mfm[minor].start_sect, &geo->start))
1208 			return -EFAULT;
1209 		return 0;
1210 
1211 	case BLKFRASET:
1212 		if (!capable(CAP_SYS_ADMIN))
1213 			return -EACCES;
1214 		max_readahead[major][minor] = arg;
1215 		return 0;
1216 
1217 	case BLKFRAGET:
1218 		return put_user(max_readahead[major][minor], (long *) arg);
1219 
1220 	case BLKSECTGET:
1221 		return put_user(max_sectors[major][minor], (long *) arg);
1222 
1223 	case BLKRRPART:
1224 		if (!capable(CAP_SYS_ADMIN))
1225 			return -EACCES;
1226 		return mfm_reread_partitions(dev);
1227 
1228 	case BLKGETSIZE:
1229 	case BLKGETSIZE64:
1230 	case BLKFLSBUF:
1231 	case BLKROSET:
1232 	case BLKROGET:
1233 	case BLKRASET:
1234 	case BLKRAGET:
1235 	case BLKPG:
1236 		return blk_ioctl(dev, cmd, arg);
1237 
1238 	default:
1239 		return -EINVAL;
1240 	}
1241 }
1242 
mfm_open(struct inode * inode,struct file * file)1243 static int mfm_open(struct inode *inode, struct file *file)
1244 {
1245 	int dev = DEVICE_NR(MINOR(inode->i_rdev));
1246 
1247 	if (dev >= mfm_drives)
1248 		return -ENODEV;
1249 
1250 	while (mfm_info[dev].busy)
1251 		sleep_on (&mfm_wait_open);
1252 
1253 	mfm_info[dev].access_count++;
1254 	return 0;
1255 }
1256 
1257 /*
1258  * Releasing a block device means we sync() it, so that it can safely
1259  * be forgotten about...
1260  */
mfm_release(struct inode * inode,struct file * file)1261 static int mfm_release(struct inode *inode, struct file *file)
1262 {
1263 	mfm_info[DEVICE_NR(MINOR(inode->i_rdev))].access_count--;
1264 	return 0;
1265 }
1266 
1267 /*
1268  * This is to handle various kernel command line parameters
1269  * specific to this driver.
1270  */
mfm_setup(char * str,int * ints)1271 void mfm_setup(char *str, int *ints)
1272 {
1273 	return;
1274 }
1275 
1276 /*
1277  * Set the CHS from the ADFS boot block if it is present.  This is not ideal
1278  * since if there are any non-ADFS partitions on the disk, this won't work!
1279  * Hence, I want to get rid of this...
1280  */
xd_set_geometry(kdev_t dev,unsigned char secsptrack,unsigned char heads,unsigned long discsize,unsigned int secsize)1281 void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
1282 		     unsigned long discsize, unsigned int secsize)
1283 {
1284 	int drive = MINOR(dev) >> 6;
1285 
1286 	if (mfm_info[drive].cylinders == 1) {
1287 		mfm_info[drive].sectors = secsptrack;
1288 		mfm_info[drive].heads = heads;
1289 		mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);
1290 
1291 		if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {
1292 			printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + (dev >> 6));
1293 
1294 			/* These values are fairly arbitary, but are there so that if your
1295 			 * lucky you can pick apart your disc to find out what is going on -
1296 			 * I reckon these figures won't hurt MOST drives
1297 			 */
1298 			mfm_info[drive].sectors = 32;
1299 			mfm_info[drive].heads = 4;
1300 			mfm_info[drive].cylinders = 512;
1301 		}
1302 		if (raw_cmd.dev == drive)
1303 			mfm_specify ();
1304 		mfm_geometry (drive);
1305 		mfm[drive << 6].start_sect = 0;
1306 		mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;
1307 	}
1308 }
1309 
1310 static struct gendisk mfm_gendisk = {
1311 	major:		MAJOR_NR,
1312 	major_name:	"mfm",
1313 	minor_shift:	6,
1314 	max_p:		1 << 6,
1315 	part:		mfm,
1316 	sizes:		mfm_sizes,
1317 	real_devices:	(void *)mfm_info,
1318 };
1319 
1320 static struct block_device_operations mfm_fops =
1321 {
1322 	owner:		THIS_MODULE,
1323 	open:		mfm_open,
1324 	release:	mfm_release,
1325 	ioctl:		mfm_ioctl,
1326 };
1327 
mfm_geninit(void)1328 static void mfm_geninit (void)
1329 {
1330 	int i;
1331 
1332 	for (i = 0; i < (MFM_MAXDRIVES << 6); i++) {
1333 		/* Can't increase this - if you do all hell breaks loose */
1334 		mfm_blocksizes[i] = 1024;
1335 		mfm_sectsizes[i] = 512;
1336 	}
1337 	blksize_size[MAJOR_NR] = mfm_blocksizes;
1338 	hardsect_size[MAJOR_NR] = mfm_sectsizes;
1339 
1340 	mfm_drives = mfm_initdrives();
1341 
1342 	printk("mfm: detected %d hard drive%s\n", mfm_drives,
1343 				mfm_drives == 1 ? "" : "s");
1344 	mfm_gendisk.nr_real = mfm_drives;
1345 
1346 	if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
1347 		printk("mfm: unable to get IRQ%d\n", mfm_irq);
1348 
1349 	if (mfm_irqenable)
1350 		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
1351 
1352 	for (i = 0; i < mfm_drives; i++) {
1353 		mfm_geometry (i);
1354 		register_disk(&mfm_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6,
1355 				&mfm_fops,
1356 				mfm_info[i].cylinders * mfm_info[i].heads *
1357 				mfm_info[i].sectors / 2);
1358 	}
1359 }
1360 
1361 static struct expansion_card *ecs;
1362 
1363 /*
1364  * See if there is a controller at the address presently at mfm_addr
1365  *
1366  * We check to see if the controller is busy - if it is, we abort it first,
1367  * and check that the chip is no longer busy after at least 180 clock cycles.
1368  * We then issue a command and check that the BSY or CPR bits are set.
1369  */
mfm_probecontroller(unsigned int mfm_addr)1370 static int mfm_probecontroller (unsigned int mfm_addr)
1371 {
1372 	if (inw (MFM_STATUS) & STAT_BSY) {
1373 		outw (CMD_ABT, MFM_COMMAND);
1374 		udelay (50);
1375 		if (inw (MFM_STATUS) & STAT_BSY)
1376 			return 0;
1377 	}
1378 
1379 	if (inw (MFM_STATUS) & STAT_CED)
1380 		outw (CMD_RCAL, MFM_COMMAND);
1381 
1382 	outw (CMD_SEK, MFM_COMMAND);
1383 
1384 	if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) {
1385 		unsigned int count = 2000;
1386 		while (inw (MFM_STATUS) & STAT_BSY) {
1387 			udelay (500);
1388 			if (!--count)
1389 				return 0;
1390 		}
1391 
1392 		outw (CMD_RCAL, MFM_COMMAND);
1393 	}
1394 	return 1;
1395 }
1396 
1397 /*
1398  * Look for a MFM controller - first check the motherboard, then the podules
1399  * The podules have an extra interrupt enable that needs to be played with
1400  *
1401  * The HDC is accessed at MEDIUM IOC speeds.
1402  */
mfm_init(void)1403 int mfm_init (void)
1404 {
1405 	unsigned char irqmask;
1406 
1407 	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
1408 		mfm_addr	= ONBOARD_MFM_ADDRESS;
1409 		mfm_IRQPollLoc	= IOC_IRQSTATB;
1410 		mfm_irqenable	= 0;
1411 		mfm_irq		= IRQ_HARDDISK;
1412 		irqmask		= 0x08;			/* IL3 pin */
1413 	} else {
1414 		ecs = ecard_find(0, mfm_cids);
1415 		if (!ecs) {
1416 			mfm_addr = 0;
1417 			return -1;
1418 		}
1419 
1420 		mfm_addr	= ecard_address(ecs, ECARD_IOC, ECARD_MEDIUM) + 0x800;
1421 		mfm_IRQPollLoc	= ioaddr(mfm_addr + 0x400);
1422 		mfm_irqenable	= mfm_IRQPollLoc;
1423 		mfm_irq		= ecs->irq;
1424 		irqmask		= 0x08;
1425 
1426 		ecard_claim(ecs);
1427 	}
1428 
1429 	printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
1430 	if (!request_region (mfm_addr, 10, "mfm")) {
1431 		ecard_release(ecs);
1432 		return -1;
1433 	}
1434 
1435 	if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
1436 		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
1437 		ecard_release(ecs);
1438 		release_region(mfm_addr, 10);
1439 		return -1;
1440 	}
1441 
1442 	/* Stuff for the assembler routines to get to */
1443 	hdc63463_baseaddress	= ioaddr(mfm_addr);
1444 	hdc63463_irqpolladdress	= mfm_IRQPollLoc;
1445 	hdc63463_irqpollmask	= irqmask;
1446 
1447 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1448 	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB?) read ahread */
1449 
1450 	add_gendisk(&mfm_gendisk);
1451 
1452 	Busy = 0;
1453 	lastspecifieddrive = -1;
1454 
1455 	mfm_geninit();
1456 	return 0;
1457 }
1458 
1459 /*
1460  * This routine is called to flush all partitions and partition tables
1461  * for a changed MFM disk, and then re-read the new partition table.
1462  * If we are revalidating due to an ioctl, we have USAGE == 1.
1463  */
mfm_reread_partitions(kdev_t dev)1464 static int mfm_reread_partitions(kdev_t dev)
1465 {
1466 	unsigned int start, i, maxp, target = DEVICE_NR(MINOR(dev));
1467 	unsigned long flags;
1468 
1469 	save_flags_cli(flags);
1470 	if (mfm_info[target].busy || mfm_info[target].access_count > 1) {
1471 		restore_flags (flags);
1472 		return -EBUSY;
1473 	}
1474 	mfm_info[target].busy = 1;
1475 	restore_flags (flags);
1476 
1477 	maxp = mfm_gendisk.max_p;
1478 	start = target << mfm_gendisk.minor_shift;
1479 
1480 	for (i = maxp - 1; i >= 0; i--) {
1481 		int minor = start + i;
1482 		invalidate_device (MKDEV(MAJOR_NR, minor), 1);
1483 		mfm_gendisk.part[minor].start_sect = 0;
1484 		mfm_gendisk.part[minor].nr_sects = 0;
1485 	}
1486 
1487 	/* Divide by 2, since sectors are 2 times smaller than usual ;-) */
1488 
1489 	grok_partitions(&mfm_gendisk, target, 1<<6, mfm_info[target].heads *
1490 		    mfm_info[target].cylinders * mfm_info[target].sectors / 2);
1491 
1492 	mfm_info[target].busy = 0;
1493 	wake_up (&mfm_wait_open);
1494 	return 0;
1495 }
1496 
1497 #ifdef MODULE
1498 
1499 EXPORT_NO_SYMBOLS;
1500 MODULE_LICENSE("GPL");
1501 
init_module(void)1502 int init_module(void)
1503 {
1504 	return mfm_init();
1505 }
1506 
cleanup_module(void)1507 void cleanup_module(void)
1508 {
1509 	if (ecs && mfm_irqenable)
1510 		outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
1511 	free_irq(mfm_irq, NULL);
1512 	unregister_blkdev(MAJOR_NR, "mfm");
1513 	del_gendisk(&mfm_gendisk);
1514 	if (ecs)
1515 		ecard_release(ecs);
1516 	if (mfm_addr)
1517 		release_region(mfm_addr, 10);
1518 }
1519 #endif
1520