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