v2.4.8 -> v2.4.8.1
[opensuse: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/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 BLKGETSIZE:
1212                 return put_user (mfm[minor].nr_sects, (long *)arg);
1213
1214         case BLKFRASET:
1215                 if (!capable(CAP_SYS_ADMIN))
1216                         return -EACCES;
1217                 max_readahead[major][minor] = arg;
1218                 return 0;
1219
1220         case BLKFRAGET:
1221                 return put_user(max_readahead[major][minor], (long *) arg);
1222
1223         case BLKSECTGET:
1224                 return put_user(max_sectors[major][minor], (long *) arg);
1225
1226         case BLKRRPART:
1227                 if (!capable(CAP_SYS_ADMIN))
1228                         return -EACCES;
1229                 return mfm_reread_partitions(dev);
1230
1231         case BLKFLSBUF:
1232         case BLKROSET:
1233         case BLKROGET:
1234         case BLKRASET:
1235         case BLKRAGET:
1236         case BLKPG:
1237                 return blk_ioctl(dev, cmd, arg);
1238
1239         default:
1240                 return -EINVAL;
1241         }
1242 }
1243
1244 static int mfm_open(struct inode *inode, struct file *file)
1245 {
1246         int dev = DEVICE_NR(MINOR(inode->i_rdev));
1247
1248         if (dev >= mfm_drives)
1249                 return -ENODEV;
1250
1251         MOD_INC_USE_COUNT;
1252         while (mfm_info[dev].busy)
1253                 sleep_on (&mfm_wait_open);
1254
1255         mfm_info[dev].access_count++;
1256         return 0;
1257 }
1258
1259 /*
1260  * Releasing a block device means we sync() it, so that it can safely
1261  * be forgotten about...
1262  */
1263 static int mfm_release(struct inode *inode, struct file *file)
1264 {
1265         mfm_info[DEVICE_NR(MINOR(inode->i_rdev))].access_count--;
1266         MOD_DEC_USE_COUNT;
1267         return 0;
1268 }
1269
1270 /*
1271  * This is to handle various kernel command line parameters
1272  * specific to this driver.
1273  */
1274 void mfm_setup(char *str, int *ints)
1275 {
1276         return;
1277 }
1278
1279 /*
1280  * Set the CHS from the ADFS boot block if it is present.  This is not ideal
1281  * since if there are any non-ADFS partitions on the disk, this won't work!
1282  * Hence, I want to get rid of this...
1283  */
1284 void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
1285                      unsigned long discsize, unsigned int secsize)
1286 {
1287         int drive = MINOR(dev) >> 6;
1288
1289         if (mfm_info[drive].cylinders == 1) {
1290                 mfm_info[drive].sectors = secsptrack;
1291                 mfm_info[drive].heads = heads;
1292                 mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);
1293
1294                 if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {
1295                         printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + (dev >> 6));
1296
1297                         /* These values are fairly arbitary, but are there so that if your
1298                          * lucky you can pick apart your disc to find out what is going on -
1299                          * I reckon these figures won't hurt MOST drives
1300                          */
1301                         mfm_info[drive].sectors = 32;
1302                         mfm_info[drive].heads = 4;
1303                         mfm_info[drive].cylinders = 512;
1304                 }
1305                 if (raw_cmd.dev == drive)
1306                         mfm_specify ();
1307                 mfm_geometry (drive);
1308                 mfm[drive << 6].start_sect = 0;
1309                 mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;
1310         }
1311 }
1312
1313 static struct gendisk mfm_gendisk = {
1314         MAJOR_NR,               /* Major number */
1315         "mfm",                  /* Major name */
1316         6,                      /* Bits to shift to get real from partition */
1317         1 << 6,                 /* Number of partitions per real */
1318         mfm,                    /* hd struct */
1319         mfm_sizes,              /* block sizes */
1320         0,                      /* number */
1321         (void *) mfm_info,      /* internal */
1322         NULL                    /* next */
1323 };
1324
1325 static struct block_device_operations mfm_fops =
1326 {
1327         open:           mfm_open,
1328         release:        mfm_release,
1329         ioctl:          mfm_ioctl,
1330 };
1331
1332 static void mfm_geninit (void)
1333 {
1334         int i;
1335
1336         for (i = 0; i < (MFM_MAXDRIVES << 6); i++) {
1337                 /* Can't increase this - if you do all hell breaks loose */
1338                 mfm_blocksizes[i] = 1024;
1339                 mfm_sectsizes[i] = 512;
1340         }
1341         blksize_size[MAJOR_NR] = mfm_blocksizes;
1342         hardsect_size[MAJOR_NR] = mfm_sectsizes;
1343
1344         mfm_drives = mfm_initdrives();
1345
1346         printk("mfm: detected %d hard drive%s\n", mfm_drives,
1347                                 mfm_drives == 1 ? "" : "s");
1348         mfm_gendisk.nr_real = mfm_drives;
1349
1350         if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
1351                 printk("mfm: unable to get IRQ%d\n", mfm_irq);
1352
1353         if (mfm_irqenable)
1354                 outw(0x80, mfm_irqenable);      /* Required to enable IRQs from MFM podule */
1355
1356         for (i = 0; i < mfm_drives; i++) {
1357                 mfm_geometry (i);
1358                 register_disk(&mfm_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6,
1359                                 &mfm_fops,
1360                                 mfm_info[i].cylinders * mfm_info[i].heads *
1361                                 mfm_info[i].sectors / 2);
1362         }
1363 }
1364
1365 static struct expansion_card *ecs;
1366
1367 /*
1368  * See if there is a controller at the address presently at mfm_addr
1369  *
1370  * We check to see if the controller is busy - if it is, we abort it first,
1371  * and check that the chip is no longer busy after at least 180 clock cycles.
1372  * We then issue a command and check that the BSY or CPR bits are set.
1373  */
1374 static int mfm_probecontroller (unsigned int mfm_addr)
1375 {
1376         if (check_region (mfm_addr, 10))
1377                 return 0;
1378
1379         if (inw (MFM_STATUS) & STAT_BSY) {
1380                 outw (CMD_ABT, MFM_COMMAND);
1381                 udelay (50);
1382                 if (inw (MFM_STATUS) & STAT_BSY)
1383                         return 0;
1384         }
1385
1386         if (inw (MFM_STATUS) & STAT_CED)
1387                 outw (CMD_RCAL, MFM_COMMAND);
1388
1389         outw (CMD_SEK, MFM_COMMAND);
1390
1391         if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) {
1392                 unsigned int count = 2000;
1393                 while (inw (MFM_STATUS) & STAT_BSY) {
1394                         udelay (500);
1395                         if (!--count)
1396                                 return 0;
1397                 }
1398
1399                 outw (CMD_RCAL, MFM_COMMAND);
1400         }
1401         return 1;
1402 }
1403
1404 /*
1405  * Look for a MFM controller - first check the motherboard, then the podules
1406  * The podules have an extra interrupt enable that needs to be played with
1407  *
1408  * The HDC is accessed at MEDIUM IOC speeds.
1409  */
1410 int mfm_init (void)
1411 {
1412         unsigned char irqmask;
1413
1414         if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
1415                 mfm_addr        = ONBOARD_MFM_ADDRESS;
1416                 mfm_IRQPollLoc  = IOC_IRQSTATB;
1417                 mfm_irqenable   = 0;
1418                 mfm_irq         = IRQ_HARDDISK;
1419                 irqmask         = 0x08;                 /* IL3 pin */
1420         } else {
1421                 ecs = ecard_find(0, mfm_cids);
1422                 if (!ecs) {
1423                         mfm_addr = 0;
1424                         return -1;
1425                 }
1426
1427                 mfm_addr        = ecard_address(ecs, ECARD_IOC, ECARD_MEDIUM) + 0x800;
1428                 mfm_IRQPollLoc  = ioaddr(mfm_addr + 0x400);
1429                 mfm_irqenable   = mfm_IRQPollLoc;
1430                 mfm_irq         = ecs->irq;
1431                 irqmask         = 0x08;
1432
1433                 ecard_claim(ecs);
1434         }
1435
1436         if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
1437                 printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
1438                 ecard_release(ecs);
1439                 return -1;
1440         }
1441
1442         printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
1443         request_region (mfm_addr, 10, "mfm");
1444
1445         /* Stuff for the assembler routines to get to */
1446         hdc63463_baseaddress    = ioaddr(mfm_addr);
1447         hdc63463_irqpolladdress = mfm_IRQPollLoc;
1448         hdc63463_irqpollmask    = irqmask;
1449
1450         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1451         read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB?) read ahread */
1452
1453 #ifndef MODULE
1454         mfm_gendisk.next = gendisk_head;
1455         gendisk_head = &mfm_gendisk;
1456 #endif
1457
1458         Busy = 0;
1459         lastspecifieddrive = -1;
1460
1461         mfm_geninit();
1462         return 0;
1463 }
1464
1465 /*
1466  * This routine is called to flush all partitions and partition tables
1467  * for a changed MFM disk, and then re-read the new partition table.
1468  * If we are revalidating due to an ioctl, we have USAGE == 1.
1469  */
1470 static int mfm_reread_partitions(kdev_t dev)
1471 {
1472         unsigned int start, i, maxp, target = DEVICE_NR(MINOR(dev));
1473         unsigned long flags;
1474
1475         save_flags_cli(flags);
1476         if (mfm_info[target].busy || mfm_info[target].access_count > 1) {
1477                 restore_flags (flags);
1478                 return -EBUSY;
1479         }
1480         mfm_info[target].busy = 1;
1481         restore_flags (flags);
1482
1483         maxp = mfm_gendisk.max_p;
1484         start = target << mfm_gendisk.minor_shift;
1485
1486         for (i = maxp - 1; i >= 0; i--) {
1487                 int minor = start + i;
1488                 invalidate_device (MKDEV(MAJOR_NR, minor), 1);
1489                 mfm_gendisk.part[minor].start_sect = 0;
1490                 mfm_gendisk.part[minor].nr_sects = 0;
1491         }
1492
1493         /* Divide by 2, since sectors are 2 times smaller than usual ;-) */
1494
1495         grok_partitions(&mfm_gendisk, target, 1<<6, mfm_info[target].heads *
1496                     mfm_info[target].cylinders * mfm_info[target].sectors / 2);
1497
1498         mfm_info[target].busy = 0;
1499         wake_up (&mfm_wait_open);
1500         return 0;
1501 }
1502
1503 #ifdef MODULE
1504 int init_module(void)
1505 {
1506         return mfm_init();
1507 }
1508
1509 void cleanup_module(void)
1510 {
1511         if (ecs && mfm_irqenable)
1512                 outw (0, mfm_irqenable);        /* Required to enable IRQs from MFM podule */
1513         free_irq(mfm_irq, NULL);
1514         unregister_blkdev(MAJOR_NR, "mfm");
1515         if (ecs)
1516                 ecard_release(ecs);
1517         if (mfm_addr)
1518                 release_region(mfm_addr, 10);
1519 }
1520 #endif