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