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