1/*
2 * linux/drivers/acorn/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/fs.h>
103#include <linux/interrupt.h>
104#include <linux/kernel.h>
105#include <linux/timer.h>
106#include <linux/mm.h>
107#include <linux/errno.h>
108#include <linux/genhd.h>
109#include <linux/major.h>
110#include <linux/ioport.h>
111#include <linux/delay.h>
112#include <linux/blkpg.h>
113
114#include <asm/system.h>
115#include <asm/io.h>
116#include <asm/irq.h>
117#include <asm/uaccess.h>
118#include <asm/dma.h>
119#include <asm/hardware.h>
120#include <asm/ecard.h>
121#include <asm/hardware/ioc.h>
122
123static void (*do_mfm)(void) = NULL;
124static struct request_queue *mfm_queue;
125static DEFINE_SPINLOCK(mfm_lock);
126
127#define MAJOR_NR	MFM_ACORN_MAJOR
128#define QUEUE (mfm_queue)
129#define CURRENT elv_next_request(mfm_queue)
130
131/*
132 * Configuration section
133 *
134 * This is the maximum number of drives that we accept
135 */
136#define MFM_MAXDRIVES 2
137/*
138 * Linux I/O address of onboard MFM controller or 0 to disable this
139 */
140#define ONBOARD_MFM_ADDRESS ((0x002d0000 >> 2) | 0x80000000)
141/*
142 * Uncomment this to enable debugging in the MFM driver...
143 */
144#ifndef DEBUG
145/*#define DEBUG */
146#endif
147/*
148 * End of configuration
149 */
150
151
152/*
153 * This structure contains all information to do with a particular physical
154 * device.
155 */
156struct mfm_info {
157	unsigned char sectors;
158	unsigned char heads;
159	unsigned short cylinders;
160	unsigned short lowcurrent;
161	unsigned short precomp;
162#define NO_TRACK -1
163#define NEED_1_RECAL -2
164#define NEED_2_RECAL -3
165		 int cylinder;
166	struct {
167		char recal;
168		char report;
169		char abort;
170	} errors;
171} mfm_info[MFM_MAXDRIVES];
172
173#define MFM_DRV_INFO mfm_info[raw_cmd.dev]
174
175/* Stuff from the assembly routines */
176extern unsigned int hdc63463_baseaddress;	/* Controller base address */
177extern unsigned int hdc63463_irqpolladdress;	/* Address to read to test for int */
178extern unsigned int hdc63463_irqpollmask;	/* Mask for irq register */
179extern unsigned int hdc63463_dataptr;	/* Pointer to kernel data space to DMA */
180extern int hdc63463_dataleft;	/* Number of bytes left to transfer */
181
182
183
184
185static int lastspecifieddrive;
186static unsigned Busy;
187
188static unsigned int PartFragRead;	/* The number of sectors which have been read
189					   during a partial read split over two
190					   cylinders.  If 0 it means a partial
191					   read did not occur. */
192
193static unsigned int PartFragRead_RestartBlock;	/* Where to restart on a split access */
194static unsigned int PartFragRead_SectorsLeft;	/* Where to restart on a split access */
195
196static int Sectors256LeftInCurrent;	/* i.e. 256 byte sectors left in current */
197static int SectorsLeftInRequest;	/* i.e. blocks left in the thing mfm_request was called for */
198static int Copy_Sector;		/* The 256 byte sector we are currently at - fragments need to know
199				   where to take over */
200static char *Copy_buffer;
201
202
203static void mfm_seek(void);
204static void mfm_rerequest(void);
205static void mfm_request(void);
206static void mfm_specify (void);
207static void issue_request(unsigned int block, unsigned int nsect,
208			  struct request *req);
209
210static unsigned int mfm_addr;		/* Controller address */
211static unsigned int mfm_IRQPollLoc;	/* Address to read for IRQ information */
212static unsigned int mfm_irqenable;	/* Podule IRQ enable location */
213static unsigned char mfm_irq;		/* Interrupt number */
214static int mfm_drives = 0;		/* drives available */
215static int mfm_status = 0;		/* interrupt status */
216static int *errors;
217
218static struct rawcmd {
219	unsigned int dev;
220	unsigned int cylinder;
221	unsigned int head;
222	unsigned int sector;
223	unsigned int cmdtype;
224	unsigned int cmdcode;
225	unsigned char cmddata[16];
226	unsigned int cmdlen;
227} raw_cmd;
228
229static unsigned char result[16];
230
231static struct cont {
232	void (*interrupt) (void);	/* interrupt handler */
233	void (*error) (void);	/* error handler */
234	void (*redo) (void);	/* redo handler */
235	void (*done) (int st);	/* done handler */
236} *cont = NULL;
237
238
239int number_mfm_drives = 1;
240
241/* ------------------------------------------------------------------------------------------ */
242/*
243 * From the HD63463 data sheet from Hitachi Ltd.
244 */
245
246#define MFM_COMMAND (mfm_addr + 0)
247#define MFM_DATAOUT (mfm_addr + 1)
248#define MFM_STATUS  (mfm_addr + 8)
249#define MFM_DATAIN  (mfm_addr + 9)
250
251#define CMD_ABT		0xF0	/* Abort */
252#define CMD_SPC		0xE8	/* Specify */
253#define CMD_TST		0xE0	/* Test */
254#define CMD_RCLB	0xC8	/* Recalibrate */
255#define CMD_SEK		0xC0	/* Seek */
256#define CMD_WFS		0xAB	/* Write Format Skew */
257#define CMD_WFM		0xA3	/* Write Format */
258#define CMD_MTB		0x90	/* Memory to buffer */
259#define CMD_CMPD	0x88	/* Compare data */
260#define CMD_WD		0x87	/* Write data */
261#define CMD_RED		0x70	/* Read erroneous data */
262#define CMD_RIS		0x68	/* Read ID skew */
263#define CMD_FID		0x61	/* Find ID */
264#define CMD_RID		0x60	/* Read ID */
265#define CMD_BTM		0x50	/* Buffer to memory */
266#define CMD_CKD		0x48	/* Check data */
267#define CMD_RD		0x40	/* Read data */
268#define CMD_OPBW	0x38	/* Open buffer write */
269#define CMD_OPBR	0x30	/* Open buffer read */
270#define CMD_CKV		0x28	/* Check drive */
271#define CMD_CKE		0x20	/* Check ECC */
272#define CMD_POD		0x18	/* Polling disable */
273#define CMD_POL		0x10	/* Polling enable */
274#define CMD_RCAL	0x08	/* Recall */
275
276#define STAT_BSY	0x8000	/* Busy */
277#define STAT_CPR	0x4000	/* Command Parameter Rejection */
278#define STAT_CED	0x2000	/* Command end */
279#define STAT_SED	0x1000	/* Seek end */
280#define STAT_DER	0x0800	/* Drive error */
281#define STAT_ABN	0x0400	/* Abnormal end */
282#define STAT_POL	0x0200	/* Polling */
283
284/* ------------------------------------------------------------------------------------------ */
285#ifdef DEBUG
286static void console_printf(const char *fmt,...)
287{
288	static char buffer[2048];	/* Arbitary! */
289	extern void console_print(const char *);
290	unsigned long flags;
291	va_list ap;
292
293	local_irq_save(flags);
294
295	va_start(ap, fmt);
296	vsprintf(buffer, fmt, ap);
297	console_print(buffer);
298	va_end(fmt);
299
300	local_irq_restore(flags);
301};	/* console_printf */
302
303#define DBG(x...) console_printf(x)
304#else
305#define DBG(x...)
306#endif
307
308static void print_status(void)
309{
310	char *error;
311	static char *errors[] = {
312         "no error",
313	 "command aborted",
314	 "invalid command",
315	 "parameter error",
316	 "not initialised",
317	 "rejected TEST",
318	 "no useld",
319	 "write fault",
320	 "not ready",
321	 "no scp",
322	 "in seek",
323	 "invalid NCA",
324	 "invalid step rate",
325	 "seek error",
326	 "over run",
327	 "invalid PHA",
328	 "data field EEC error",
329	 "data field CRC error",
330	 "error corrected",
331	 "data field fatal error",
332	 "no data am",
333	 "not hit",
334	 "ID field CRC error",
335	 "time over",
336	 "no ID am",
337	 "not writable"
338	};
339	if (result[1] < 0x65)
340		error = errors[result[1] >> 2];
341	else
342		error = "unknown";
343	printk("(");
344	if (mfm_status & STAT_BSY) printk("BSY ");
345	if (mfm_status & STAT_CPR) printk("CPR ");
346	if (mfm_status & STAT_CED) printk("CED ");
347	if (mfm_status & STAT_SED) printk("SED ");
348	if (mfm_status & STAT_DER) printk("DER ");
349	if (mfm_status & STAT_ABN) printk("ABN ");
350	if (mfm_status & STAT_POL) printk("POL ");
351	printk(") SSB = %X (%s)\n", result[1], error);
352
353}
354
355/* ------------------------------------------------------------------------------------- */
356
357static void issue_command(int command, unsigned char *cmdb, int len)
358{
359	int status;
360#ifdef DEBUG
361	int i;
362	console_printf("issue_command: %02X: ", command);
363	for (i = 0; i < len; i++)
364		console_printf("%02X ", cmdb[i]);
365	console_printf("\n");
366#endif
367
368	do {
369		status = inw(MFM_STATUS);
370	} while (status & (STAT_BSY | STAT_POL));
371	DBG("issue_command: status after pol/bsy loop: %02X:\n ", status >> 8);
372
373	if (status & (STAT_CPR | STAT_CED | STAT_SED | STAT_DER | STAT_ABN)) {
374		outw(CMD_RCAL, MFM_COMMAND);
375		while (inw(MFM_STATUS) & STAT_BSY);
376	}
377	status = inw(MFM_STATUS);
378	DBG("issue_command: status before parameter issue: %02X:\n ", status >> 8);
379
380	while (len > 0) {
381		outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT);
382		len -= 2;
383		cmdb += 2;
384	}
385	status = inw(MFM_STATUS);
386	DBG("issue_command: status before command issue: %02X:\n ", status >> 8);
387
388	outw(command, MFM_COMMAND);
389	status = inw(MFM_STATUS);
390	DBG("issue_command: status immediately after command issue: %02X:\n ", status >> 8);
391}
392
393static void wait_for_completion(void)
394{
395	while ((mfm_status = inw(MFM_STATUS)) & STAT_BSY);
396}
397
398static void wait_for_command_end(void)
399{
400	int i;
401
402	while (!((mfm_status = inw(MFM_STATUS)) & STAT_CED));
403
404	for (i = 0; i < 16;) {
405		int in;
406		in = inw(MFM_DATAIN);
407		result[i++] = in >> 8;
408		result[i++] = in;
409	}
410	outw (CMD_RCAL, MFM_COMMAND);
411}
412
413/* ------------------------------------------------------------------------------------- */
414
415static void mfm_rw_intr(void)
416{
417	int old_status;		/* Holds status on entry, we read to see if the command just finished */
418#ifdef DEBUG
419	console_printf("mfm_rw_intr...dataleft=%d\n", hdc63463_dataleft);
420	print_status();
421#endif
422
423  /* Now don't handle the error until BSY drops */
424	if ((mfm_status & (STAT_DER | STAT_ABN)) && ((mfm_status&STAT_BSY)==0)) {
425		/* Something has gone wrong - let's try that again */
426		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
427		if (cont) {
428			DBG("mfm_rw_intr: DER/ABN err\n");
429			cont->error();
430			cont->redo();
431		};
432		return;
433	};
434
435	/* OK so what ever happened it's not an error, now I reckon we are left between
436	   a choice of command end or some data which is ready to be collected */
437	/* I think we have to transfer data while the interrupt line is on and its
438	   not any other type of interrupt */
439	if (CURRENT->cmd == WRITE) {
440		extern void hdc63463_writedma(void);
441		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
442			printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
443			if (cont) {
444				cont->error();
445				cont->redo();
446			};
447			return;
448		};
449		hdc63463_writedma();
450	} else {
451		extern void hdc63463_readdma(void);
452		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
453			printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n");
454			if (cont) {
455				cont->error();
456				cont->redo();
457			};
458			return;
459		};
460		DBG("Going to try read dma..............status=0x%x, buffer=%p\n", mfm_status, hdc63463_dataptr);
461		hdc63463_readdma();
462	};			/* Read */
463
464	if (hdc63463_dataptr != ((unsigned int) Copy_buffer + 256)) {
465		/* If we didn't actually manage to get any data on this interrupt - but why? We got the interrupt */
466		/* Ah - well looking at the status its just when we get command end; so no problem */
467		/*console_printf("mfm: dataptr mismatch. dataptr=0x%08x Copy_buffer+256=0x%08p\n",
468		   hdc63463_dataptr,Copy_buffer+256);
469		   print_status(); */
470	} else {
471		Sectors256LeftInCurrent--;
472		Copy_buffer += 256;
473		Copy_Sector++;
474
475		/* We have come to the end of this request */
476		if (!Sectors256LeftInCurrent) {
477			DBG("mfm: end_request for CURRENT=0x%p CURRENT(sector=%d current_nr_sectors=%d nr_sectors=%d)\n",
478				       CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->nr_sectors);
479
480			CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
481			CURRENT->sector += CURRENT->current_nr_sectors;
482			SectorsLeftInRequest -= CURRENT->current_nr_sectors;
483
484			end_request(CURRENT, 1);
485			if (SectorsLeftInRequest) {
486				hdc63463_dataptr = (unsigned int) CURRENT->buffer;
487				Copy_buffer = CURRENT->buffer;
488				Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
489				errors = &(CURRENT->errors);
490				/* These should match the present calculations of the next logical sector
491				   on the device
492				   Copy_Sector=CURRENT->sector*2; */
493
494				if (Copy_Sector != CURRENT->sector * 2)
495#ifdef DEBUG
496					/*console_printf*/printk("mfm: Copy_Sector mismatch. Copy_Sector=%d CURRENT->sector*2=%d\n",
497					Copy_Sector, CURRENT->sector * 2);
498#else
499					printk("mfm: Copy_Sector mismatch! Eek!\n");
500#endif
501			};	/* CURRENT */
502		};	/* Sectors256LeftInCurrent */
503	};
504
505	old_status = mfm_status;
506	mfm_status = inw(MFM_STATUS);
507	if (mfm_status & (STAT_DER | STAT_ABN)) {
508		/* Something has gone wrong - let's try that again */
509		if (cont) {
510			DBG("mfm_rw_intr: DER/ABN error\n");
511			cont->error();
512			cont->redo();
513		};
514		return;
515	};
516
517	/* If this code wasn't entered due to command_end but there is
518	   now a command end we must read the command results out. If it was
519	   entered like this then mfm_interrupt_handler would have done the
520	   job. */
521	if ((!((old_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) &&
522	    ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) {
523		int len = 0;
524		while (len < 16) {
525			int in;
526			in = inw(MFM_DATAIN);
527			result[len++] = in >> 8;
528			result[len++] = in;
529		};
530	};			/* Result read */
531
532	/*console_printf ("mfm_rw_intr nearexit [%02X]\n", __raw_readb(mfm_IRQPollLoc)); */
533
534	/* If end of command move on */
535	if (mfm_status & (STAT_CED)) {
536		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
537		/* End of command - trigger the next command */
538		if (cont) {
539			cont->done(1);
540		}
541		DBG("mfm_rw_intr: returned from cont->done\n");
542	} else {
543		/* Its going to generate another interrupt */
544		do_mfm = mfm_rw_intr;
545	};
546}
547
548static void mfm_setup_rw(void)
549{
550	DBG("setting up for rw...\n");
551
552	do_mfm = mfm_rw_intr;
553	issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen);
554}
555
556static void mfm_recal_intr(void)
557{
558#ifdef DEBUG
559	console_printf("recal intr - status = ");
560	print_status();
561#endif
562	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
563	if (mfm_status & (STAT_DER | STAT_ABN)) {
564		printk("recal failed\n");
565		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
566		if (cont) {
567			cont->error();
568			cont->redo();
569		}
570		return;
571	}
572	/* Thats seek end - we are finished */
573	if (mfm_status & STAT_SED) {
574		issue_command(CMD_POD, NULL, 0);
575		MFM_DRV_INFO.cylinder = 0;
576		mfm_seek();
577		return;
578	}
579	/* Command end without seek end (see data sheet p.20) for parallel seek
580	   - we have to send a POL command to wait for the seek */
581	if (mfm_status & STAT_CED) {
582		do_mfm = mfm_recal_intr;
583		issue_command(CMD_POL, NULL, 0);
584		return;
585	}
586	printk("recal: unknown status\n");
587}
588
589static void mfm_seek_intr(void)
590{
591#ifdef DEBUG
592	console_printf("seek intr - status = ");
593	print_status();
594#endif
595	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
596	if (mfm_status & (STAT_DER | STAT_ABN)) {
597		printk("seek failed\n");
598		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
599		if (cont) {
600			cont->error();
601			cont->redo();
602		}
603		return;
604	}
605	if (mfm_status & STAT_SED) {
606		issue_command(CMD_POD, NULL, 0);
607		MFM_DRV_INFO.cylinder = raw_cmd.cylinder;
608		mfm_seek();
609		return;
610	}
611	if (mfm_status & STAT_CED) {
612		do_mfm = mfm_seek_intr;
613		issue_command(CMD_POL, NULL, 0);
614		return;
615	}
616	printk("seek: unknown status\n");
617}
618
619/* IDEA2 seems to work better - its what RiscOS sets my
620 * disc to - on its SECOND call to specify!
621 */
622#define IDEA2
623#ifndef IDEA2
624#define SPEC_SL 0x16
625#define SPEC_SH 0xa9		/* Step pulse high=21, Record Length=001 (256 bytes) */
626#else
627#define SPEC_SL 0x00		/* OM2 - SL - step pulse low */
628#define SPEC_SH 0x21		/* Step pulse high=4, Record Length=001 (256 bytes) */
629#endif
630
631static void mfm_setupspecify (int drive, unsigned char *cmdb)
632{
633	cmdb[0]  = 0x1f;		/* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */
634	cmdb[1]  = 0xc3;		/* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */
635	cmdb[2]  = SPEC_SL;		/* OM2 - SL - step pulse low */
636	cmdb[3]  = (number_mfm_drives == 1) ? 0x02 : 0x06;	/* 1 or 2 drives */
637	cmdb[4]  = 0xfc | ((mfm_info[drive].cylinders - 1) >> 8);/* RW time over/high part of number of cylinders */
638	cmdb[5]  = mfm_info[drive].cylinders - 1;		/* low part of number of cylinders */
639	cmdb[6]  = mfm_info[drive].heads - 1;			/* Number of heads */
640	cmdb[7]  = mfm_info[drive].sectors - 1;			/* Number of sectors */
641	cmdb[8]  = SPEC_SH;
642	cmdb[9]  = 0x0a;		/* gap length 1 */
643	cmdb[10] = 0x0d;		/* gap length 2 */
644	cmdb[11] = 0x0c;		/* gap length 3 */
645	cmdb[12] = (mfm_info[drive].precomp - 1) >> 8;	/* pre comp cylinder */
646	cmdb[13] = mfm_info[drive].precomp - 1;
647	cmdb[14] = (mfm_info[drive].lowcurrent - 1) >> 8;	/* Low current cylinder */
648	cmdb[15] = mfm_info[drive].lowcurrent - 1;
649}
650
651static void mfm_specify (void)
652{
653	unsigned char cmdb[16];
654
655	DBG("specify...dev=%d lastspecified=%d\n", raw_cmd.dev, lastspecifieddrive);
656	mfm_setupspecify (raw_cmd.dev, cmdb);
657
658	issue_command (CMD_SPC, cmdb, 16);
659	/* Ensure that we will do another specify if we move to the other drive */
660	lastspecifieddrive = raw_cmd.dev;
661	wait_for_completion();
662}
663
664static void mfm_seek(void)
665{
666	unsigned char cmdb[4];
667
668	DBG("seeking...\n");
669	if (MFM_DRV_INFO.cylinder < 0) {
670		do_mfm = mfm_recal_intr;
671		DBG("mfm_seek: about to call specify\n");
672		mfm_specify ();	/* DAG added this */
673
674		cmdb[0] = raw_cmd.dev + 1;
675		cmdb[1] = 0;
676
677		issue_command(CMD_RCLB, cmdb, 2);
678		return;
679	}
680	if (MFM_DRV_INFO.cylinder != raw_cmd.cylinder) {
681		cmdb[0] = raw_cmd.dev + 1;
682		cmdb[1] = 0;	/* raw_cmd.head; DAG: My data sheet says this should be 0 */
683		cmdb[2] = raw_cmd.cylinder >> 8;
684		cmdb[3] = raw_cmd.cylinder;
685
686		do_mfm = mfm_seek_intr;
687		issue_command(CMD_SEK, cmdb, 4);
688	} else
689		mfm_setup_rw();
690}
691
692static void mfm_initialise(void)
693{
694	DBG("init...\n");
695	mfm_seek();
696}
697
698static void request_done(int uptodate)
699{
700	DBG("mfm:request_done\n");
701	if (uptodate) {
702		unsigned char block[2] = {0, 0};
703
704		/* Apparently worked - let's check bytes left to DMA */
705		if (hdc63463_dataleft != (PartFragRead_SectorsLeft * 256)) {
706			printk("mfm: request_done - dataleft=%d - should be %d - Eek!\n", hdc63463_dataleft, PartFragRead_SectorsLeft * 256);
707			end_request(CURRENT, 0);
708			Busy = 0;
709		};
710		/* Potentially this means that we've done; but we might be doing
711		   a partial access, (over two cylinders) or we may have a number
712		   of fragments in an image file.  First let's deal with partial accesss
713		 */
714		if (PartFragRead) {
715			/* Yep - a partial access */
716
717			/* and issue the remainder */
718			issue_request(PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
719			return;
720		}
721
722		/* ah well - perhaps there is another fragment to go */
723
724		/* Increment pointers/counts to start of next fragment */
725		if (SectorsLeftInRequest > 0) printk("mfm: SectorsLeftInRequest>0 - Eek! Shouldn't happen!\n");
726
727		/* No - its the end of the line */
728		/* end_request's should have happened at the end of sector DMAs */
729		/* Turns Drive LEDs off - may slow it down? */
730		if (!elv_next_request(QUEUE))
731			issue_command(CMD_CKV, block, 2);
732
733		Busy = 0;
734		DBG("request_done: About to mfm_request\n");
735		/* Next one please */
736		mfm_request();	/* Moved from mfm_rw_intr */
737		DBG("request_done: returned from mfm_request\n");
738	} else {
739		printk("mfm:request_done: update=0\n");
740		end_request(CURRENT, 0);
741		Busy = 0;
742	}
743}
744
745static void error_handler(void)
746{
747	printk("error detected... status = ");
748	print_status();
749	(*errors)++;
750	if (*errors > MFM_DRV_INFO.errors.abort)
751		cont->done(0);
752	if (*errors > MFM_DRV_INFO.errors.recal)
753		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
754}
755
756static void rw_interrupt(void)
757{
758	printk("rw_interrupt\n");
759}
760
761static struct cont rw_cont =
762{
763	rw_interrupt,
764	error_handler,
765	mfm_rerequest,
766	request_done
767};
768
769/*
770 * Actually gets round to issuing the request - note everything at this
771 * point is in 256 byte sectors not Linux 512 byte blocks
772 */
773static void issue_request(unsigned int block, unsigned int nsect,
774			  struct request *req)
775{
776	struct gendisk *disk = req->rq_disk;
777	struct mfm_info *p = disk->private_data;
778	int track, start_head, start_sector;
779	int sectors_to_next_cyl;
780	dev = p - mfm_info;
781
782	track = block / p->sectors;
783	start_sector = block % p->sectors;
784	start_head = track % p->heads;
785
786	/* First get the number of whole tracks which are free before the next
787	   track */
788	sectors_to_next_cyl = (p->heads - (start_head + 1)) * p->sectors;
789	/* Then add in the number of sectors left on this track */
790	sectors_to_next_cyl += (p->sectors - start_sector);
791
792	DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", p->sectors, track);
793
794	raw_cmd.dev = dev;
795	raw_cmd.sector = start_sector;
796	raw_cmd.head = start_head;
797	raw_cmd.cylinder = track / p->heads;
798	raw_cmd.cmdtype = CURRENT->cmd;
799	raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
800	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */
801	raw_cmd.cmddata[1] = raw_cmd.head;
802	raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
803	raw_cmd.cmddata[3] = raw_cmd.cylinder;
804	raw_cmd.cmddata[4] = raw_cmd.head;
805	raw_cmd.cmddata[5] = raw_cmd.sector;
806
807	/* Was == and worked - how the heck??? */
808	if (lastspecifieddrive != raw_cmd.dev)
809		mfm_specify ();
810
811	if (nsect <= sectors_to_next_cyl) {
812		raw_cmd.cmddata[6] = nsect >> 8;
813		raw_cmd.cmddata[7] = nsect;
814		PartFragRead = 0;	/* All in one */
815		PartFragRead_SectorsLeft = 0;	/* Must set this - used in DMA calcs */
816	} else {
817		raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8;
818		raw_cmd.cmddata[7] = sectors_to_next_cyl;
819		PartFragRead = sectors_to_next_cyl;	/* only do this many this time */
820		PartFragRead_RestartBlock = block + sectors_to_next_cyl;	/* Where to restart from */
821		PartFragRead_SectorsLeft = nsect - sectors_to_next_cyl;
822	}
823	raw_cmd.cmdlen = 8;
824
825	/* Setup DMA pointers */
826	hdc63463_dataptr = (unsigned int) Copy_buffer;
827	hdc63463_dataleft = nsect * 256;	/* Better way? */
828
829	DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
830	     raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
831		       raw_cmd.cylinder,
832		       raw_cmd.head,
833	    raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
834
835	cont = &rw_cont;
836	errors = &(CURRENT->errors);
837	mfm_initialise();
838}				/* issue_request */
839
840/*
841 * Called when an error has just happened - need to trick mfm_request
842 * into thinking we weren't busy
843 *
844 * Turn off ints - mfm_request expects them this way
845 */
846static void mfm_rerequest(void)
847{
848	DBG("mfm_rerequest\n");
849	cli();
850	Busy = 0;
851	mfm_request();
852}
853
854static struct gendisk *mfm_gendisk[2];
855
856static void mfm_request(void)
857{
858	DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy);
859
860	/* If we are still processing then return; we will get called again */
861	if (Busy) {
862		/* Again seems to be common in 1.3.45 */
863		/*DBG*/printk("mfm_request: Exiting due to busy\n");
864		return;
865	}
866	Busy = 1;
867
868	while (1) {
869		unsigned int block, nsect;
870		struct gendisk *disk;
871
872		DBG("mfm_request: loop start\n");
873		sti();
874
875		DBG("mfm_request: before !CURRENT\n");
876
877		if (!CURRENT) {
878			printk("mfm_request: Exiting due to empty queue (pre)\n");
879			do_mfm = NULL;
880			Busy = 0;
881			return;
882		}
883
884		DBG("mfm_request:                 before arg extraction\n");
885
886		disk = CURRENT->rq_disk;
887		block = CURRENT->sector;
888		nsect = CURRENT->nr_sectors;
889		if (block >= get_capacity(disk) ||
890		    block+nsect > get_capacity(disk)) {
891			printk("%s: bad access: block=%d, count=%d, nr_sects=%ld\n",
892			       disk->disk_name, block, nsect, get_capacity(disk));
893			printk("mfm: continue 1\n");
894			end_request(CURRENT, 0);
895			Busy = 0;
896			continue;
897		}
898
899		/* DAG: Linux doesn't cope with this - even though it has an array telling
900		   it the hardware block size - silly */
901		block <<= 1;	/* Now in 256 byte sectors */
902		nsect <<= 1;	/* Ditto */
903
904		SectorsLeftInRequest = nsect >> 1;
905		Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
906		Copy_buffer = CURRENT->buffer;
907		Copy_Sector = CURRENT->sector << 1;
908
909		DBG("mfm_request: block after offset=%d\n", block);
910
911		if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
912			printk("unknown mfm-command %d\n", CURRENT->cmd);
913			end_request(CURRENT, 0);
914			Busy = 0;
915			printk("mfm: continue 4\n");
916			continue;
917		}
918		issue_request(block, nsect, CURRENT);
919
920		break;
921	}
922	DBG("mfm_request: Dropping out bottom\n");
923}
924
925static void do_mfm_request(request_queue_t *q)
926{
927	DBG("do_mfm_request: about to mfm_request\n");
928	mfm_request();
929}
930
931static void mfm_interrupt_handler(int unused, void *dev_id)
932{
933	void (*handler) (void) = do_mfm;
934
935	do_mfm = NULL;
936
937	DBG("mfm_interrupt_handler (handler=0x%p)\n", handler);
938
939	mfm_status = inw(MFM_STATUS);
940
941	/* If CPR (Command Parameter Reject) and not busy it means that the command
942	   has some return message to give us */
943	if ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR) {
944		int len = 0;
945		while (len < 16) {
946			int in;
947			in = inw(MFM_DATAIN);
948			result[len++] = in >> 8;
949			result[len++] = in;
950		}
951	}
952	if (handler) {
953		handler();
954		return;
955	}
956	outw (CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
957	printk ("mfm: unexpected interrupt - status = ");
958	print_status ();
959	while (1);
960}
961
962
963
964
965
966/*
967 * Tell the user about the drive if we decided it exists.
968 */
969static void mfm_geometry(int drive)
970{
971	struct mfm_info *p = mfm_info + drive;
972	struct gendisk *disk = mfm_gendisk[drive];
973	disk->private_data = p;
974	if (p->cylinders)
975		printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n",
976			disk->disk_name,
977			p->cylinders * p->heads * p->sectors / 4096,
978			p->cylinders, p->heads, p->sectors,
979			p->lowcurrent, p->precomp);
980	set_capacity(disk, p->cylinders * p->heads * p->sectors / 2);
981}
982
983#ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
984/*
985 * Attempt to detect a drive and find its geometry.  The drive has already been
986 * specified...
987 *
988 * We first recalibrate the disk, then try to probe sectors, heads and then
989 * cylinders.  NOTE! the cylinder probe may break drives.  The xd disk driver
990 * does something along these lines, so I assume that most drives are up to
991 * this mistreatment...
992 */
993static int mfm_detectdrive (int drive)
994{
995	unsigned int mingeo[3], maxgeo[3];
996	unsigned int attribute, need_recal = 1;
997	unsigned char cmdb[8];
998
999	memset (mingeo, 0, sizeof (mingeo));
1000	maxgeo[0] = mfm_info[drive].sectors;
1001	maxgeo[1] = mfm_info[drive].heads;
1002	maxgeo[2] = mfm_info[drive].cylinders;
1003
1004	cmdb[0] = drive + 1;
1005	cmdb[6] = 0;
1006	cmdb[7] = 1;
1007	for (attribute = 0; attribute < 3; attribute++) {
1008		while (mingeo[attribute] != maxgeo[attribute]) {
1009			unsigned int variable;
1010
1011			variable = (maxgeo[attribute] + mingeo[attribute]) >> 1;
1012			cmdb[1] = cmdb[2] = cmdb[3] = cmdb[4] = cmdb[5] = 0;
1013
1014			if (need_recal) {
1015				int tries = 5;
1016
1017				do {
1018					issue_command (CMD_RCLB, cmdb, 2);
1019					wait_for_completion ();
1020					wait_for_command_end ();
1021					if  (result[1] == 0x20)
1022						break;
1023				} while (result[1] && --tries);
1024				if (result[1]) {
1025					outw (CMD_RCAL, MFM_COMMAND);
1026					return 0;
1027				}
1028				need_recal = 0;
1029			}
1030
1031			switch (attribute) {
1032			case 0:
1033				cmdb[5] = variable;
1034				issue_command (CMD_CMPD, cmdb, 8);
1035				break;
1036			case 1:
1037				cmdb[1] = variable;
1038				cmdb[4] = variable;
1039				issue_command (CMD_CMPD, cmdb, 8);
1040				break;
1041			case 2:
1042				cmdb[2] = variable >> 8;
1043				cmdb[3] = variable;
1044				issue_command (CMD_SEK, cmdb, 4);
1045				break;
1046			}
1047			wait_for_completion ();
1048			wait_for_command_end ();
1049
1050			switch (result[1]) {
1051			case 0x00:
1052			case 0x50:
1053				mingeo[attribute] = variable + 1;
1054				break;
1055
1056			case 0x20:
1057				outw (CMD_RCAL, MFM_COMMAND);
1058				return 0;
1059
1060			case 0x24:
1061				need_recal = 1;
1062			default:
1063				maxgeo[attribute] = variable;
1064				break;
1065			}
1066		}
1067	}
1068	mfm_info[drive].cylinders  = mingeo[2];
1069	mfm_info[drive].lowcurrent = mingeo[2];
1070	mfm_info[drive].precomp    = mingeo[2] / 2;
1071	mfm_info[drive].heads 	   = mingeo[1];
1072	mfm_info[drive].sectors	   = mingeo[0];
1073	outw (CMD_RCAL, MFM_COMMAND);
1074	return 1;
1075}
1076#endif
1077
1078/*
1079 * Initialise all drive information for this controller.
1080 */
1081static int mfm_initdrives(void)
1082{
1083	int drive;
1084
1085	if (number_mfm_drives > MFM_MAXDRIVES) {
1086		number_mfm_drives = MFM_MAXDRIVES;
1087		printk("No. of ADFS MFM drives is greater than MFM_MAXDRIVES - you can't have that many!\n");
1088	}
1089
1090	for (drive = 0; drive < number_mfm_drives; drive++) {
1091		mfm_info[drive].lowcurrent = 1;
1092		mfm_info[drive].precomp    = 1;
1093		mfm_info[drive].cylinder   = -1;
1094		mfm_info[drive].errors.recal  = 0;
1095		mfm_info[drive].errors.report = 0;
1096		mfm_info[drive].errors.abort  = 4;
1097
1098#ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
1099		mfm_info[drive].cylinders  = 1024;
1100		mfm_info[drive].heads	   = 8;
1101		mfm_info[drive].sectors	   = 64;
1102		{
1103			unsigned char cmdb[16];
1104
1105			mfm_setupspecify (drive, cmdb);
1106			cmdb[1] &= ~0x81;
1107			issue_command (CMD_SPC, cmdb, 16);
1108			wait_for_completion ();
1109			if (!mfm_detectdrive (drive)) {
1110				mfm_info[drive].cylinders = 0;
1111				mfm_info[drive].heads     = 0;
1112				mfm_info[drive].sectors   = 0;
1113			}
1114			cmdb[0] = cmdb[1] = 0;
1115			issue_command (CMD_CKV, cmdb, 2);
1116		}
1117#else
1118		mfm_info[drive].cylinders  = 1;	/* its going to have to figure it out from the partition info */
1119		mfm_info[drive].heads      = 4;
1120		mfm_info[drive].sectors    = 32;
1121#endif
1122	}
1123	return number_mfm_drives;
1124}
1125
1126
1127
1128/*
1129 * The 'front' end of the mfm driver follows...
1130 */
1131
1132static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1133{
1134	struct mfm_info *p = bdev->bd_disk->private_data;
1135
1136	geo->heads = p->heads;
1137	geo->sectors = p->sectors;
1138	geo->cylinders = p->cylinders;
1139	return 0;
1140}
1141
1142/*
1143 * This is to handle various kernel command line parameters
1144 * specific to this driver.
1145 */
1146void mfm_setup(char *str, int *ints)
1147{
1148	return;
1149}
1150
1151/*
1152 * Set the CHS from the ADFS boot block if it is present.  This is not ideal
1153 * since if there are any non-ADFS partitions on the disk, this won't work!
1154 * Hence, I want to get rid of this...
1155 */
1156void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
1157			unsigned char heads, unsigned int secsize)
1158{
1159	struct mfm_info *p = bdev->bd_disk->private_data;
1160	int drive = p - mfm_info;
1161	unsigned long disksize = bdev->bd_inode->i_size;
1162
1163	if (p->cylinders == 1) {
1164		p->sectors = secsptrack;
1165		p->heads = heads;
1166		p->cylinders = discsize / (secsptrack * heads * secsize);
1167
1168		if ((heads < 1) || (p->cylinders > 1024)) {
1169			printk("%s: Insane disc shape! Setting to 512/4/32\n",
1170				bdev->bd_disk->disk_name);
1171
1172			/* These values are fairly arbitary, but are there so that if your
1173			 * lucky you can pick apart your disc to find out what is going on -
1174			 * I reckon these figures won't hurt MOST drives
1175			 */
1176			p->sectors = 32;
1177			p->heads = 4;
1178			p->cylinders = 512;
1179		}
1180		if (raw_cmd.dev == drive)
1181			mfm_specify ();
1182		mfm_geometry (drive);
1183	}
1184}
1185
1186static struct block_device_operations mfm_fops =
1187{
1188	.owner		= THIS_MODULE,
1189	.getgeo		= mfm_getgeo,
1190};
1191
1192/*
1193 * See if there is a controller at the address presently at mfm_addr
1194 *
1195 * We check to see if the controller is busy - if it is, we abort it first,
1196 * and check that the chip is no longer busy after at least 180 clock cycles.
1197 * We then issue a command and check that the BSY or CPR bits are set.
1198 */
1199static int mfm_probecontroller (unsigned int mfm_addr)
1200{
1201	if (inw (MFM_STATUS) & STAT_BSY) {
1202		outw (CMD_ABT, MFM_COMMAND);
1203		udelay (50);
1204		if (inw (MFM_STATUS) & STAT_BSY)
1205			return 0;
1206	}
1207
1208	if (inw (MFM_STATUS) & STAT_CED)
1209		outw (CMD_RCAL, MFM_COMMAND);
1210
1211	outw (CMD_SEK, MFM_COMMAND);
1212
1213	if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) {
1214		unsigned int count = 2000;
1215		while (inw (MFM_STATUS) & STAT_BSY) {
1216			udelay (500);
1217			if (!--count)
1218				return 0;
1219		}
1220
1221		outw (CMD_RCAL, MFM_COMMAND);
1222	}
1223	return 1;
1224}
1225
1226static int mfm_do_init(unsigned char irqmask)
1227{
1228	int i, ret;
1229
1230	printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
1231
1232	ret = -EBUSY;
1233	if (!request_region (mfm_addr, 10, "mfm"))
1234		goto out1;
1235
1236	ret = register_blkdev(MAJOR_NR, "mfm");
1237	if (ret)
1238		goto out2;
1239
1240	/* Stuff for the assembler routines to get to */
1241	hdc63463_baseaddress	= ioaddr(mfm_addr);
1242	hdc63463_irqpolladdress	= mfm_IRQPollLoc;
1243	hdc63463_irqpollmask	= irqmask;
1244
1245	mfm_queue = blk_init_queue(do_mfm_request, &mfm_lock);
1246	if (!mfm_queue)
1247		goto out2a;
1248
1249	Busy = 0;
1250	lastspecifieddrive = -1;
1251
1252	mfm_drives = mfm_initdrives();
1253	if (!mfm_drives) {
1254		ret = -ENODEV;
1255		goto out3;
1256	}
1257
1258	for (i = 0; i < mfm_drives; i++) {
1259		struct gendisk *disk = alloc_disk(64);
1260		if (!disk)
1261			goto Enomem;
1262		disk->major = MAJOR_NR;
1263		disk->first_minor = i << 6;
1264		disk->fops = &mfm_fops;
1265		sprintf(disk->disk_name, "mfm%c", 'a'+i);
1266		mfm_gendisk[i] = disk;
1267	}
1268
1269	printk("mfm: detected %d hard drive%s\n", mfm_drives,
1270				mfm_drives == 1 ? "" : "s");
1271	ret = request_irq(mfm_irq, mfm_interrupt_handler, IRQF_DISABLED, "MFM harddisk", NULL);
1272	if (ret) {
1273		printk("mfm: unable to get IRQ%d\n", mfm_irq);
1274		goto out4;
1275	}
1276
1277	if (mfm_irqenable)
1278		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
1279
1280	for (i = 0; i < mfm_drives; i++) {
1281		mfm_geometry(i);
1282		mfm_gendisk[i]->queue = mfm_queue;
1283		add_disk(mfm_gendisk[i]);
1284	}
1285	return 0;
1286
1287out4:
1288	for (i = 0; i < mfm_drives; i++)
1289		put_disk(mfm_gendisk[i]);
1290out3:
1291	blk_cleanup_queue(mfm_queue);
1292out2a:
1293	unregister_blkdev(MAJOR_NR, "mfm");
1294out2:
1295	release_region(mfm_addr, 10);
1296out1:
1297	return ret;
1298Enomem:
1299	while (i--)
1300		put_disk(mfm_gendisk[i]);
1301	goto out3;
1302}
1303
1304static void mfm_do_exit(void)
1305{
1306	int i;
1307
1308	free_irq(mfm_irq, NULL);
1309	for (i = 0; i < mfm_drives; i++) {
1310		del_gendisk(mfm_gendisk[i]);
1311		put_disk(mfm_gendisk[i]);
1312	}
1313	blk_cleanup_queue(mfm_queue);
1314	unregister_blkdev(MAJOR_NR, "mfm");
1315	if (mfm_addr)
1316		release_region(mfm_addr, 10);
1317}
1318
1319static int __devinit mfm_probe(struct expansion_card *ec, struct ecard_id *id)
1320{
1321	if (mfm_addr)
1322		return -EBUSY;
1323
1324	mfm_addr	= ecard_address(ec, ECARD_IOC, ECARD_MEDIUM) + 0x800;
1325	mfm_IRQPollLoc	= ioaddr(mfm_addr + 0x400);
1326	mfm_irqenable	= mfm_IRQPollLoc;
1327	mfm_irq		= ec->irq;
1328
1329	return mfm_do_init(0x08);
1330}
1331
1332static void __devexit mfm_remove(struct expansion_card *ec)
1333{
1334	outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
1335	mfm_do_exit();
1336}
1337
1338static const struct ecard_id mfm_cids[] = {
1339	{ MANU_ACORN, PROD_ACORN_MFM },
1340	{ 0xffff, 0xffff },
1341};
1342
1343static struct ecard_driver mfm_driver = {
1344	.probe		= mfm_probe,
1345	.remove		= __devexit(mfm_remove),
1346	.id_table	= mfm_cids,
1347	.drv = {
1348		.name	= "mfm",
1349	},
1350};
1351
1352/*
1353 * Look for a MFM controller - first check the motherboard, then the podules
1354 * The podules have an extra interrupt enable that needs to be played with
1355 *
1356 * The HDC is accessed at MEDIUM IOC speeds.
1357 */
1358static int __init mfm_init (void)
1359{
1360	unsigned char irqmask;
1361
1362	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
1363		mfm_addr	= ONBOARD_MFM_ADDRESS;
1364		mfm_IRQPollLoc	= IOC_IRQSTATB;
1365		mfm_irqenable	= 0;
1366		mfm_irq		= IRQ_HARDDISK;
1367		return mfm_do_init(0x08);	/* IL3 pin */
1368	} else {
1369		return ecard_register_driver(&mfm_driver);
1370	}
1371}
1372
1373static void __exit mfm_exit(void)
1374{
1375	if (mfm_addr == ONBOARD_MFM_ADDRESS)
1376		mfm_do_exit();
1377	else
1378		ecard_unregister_driver(&mfm_driver);
1379}
1380
1381module_init(mfm_init)
1382module_exit(mfm_exit)
1383MODULE_LICENSE("GPL");
1384