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