Import 2.1.118
[davej-history.git] / drivers / acorn / block / mfmhd.c
blobbec74c62ba220f1d115245b127756f1c41f4ecc0
1 /*
2 * linux/arch/arm/drivers/block/mfmhd.c
4 * Copyright (C) 1995, 1996 Russell King, Dave Alan Gilbert (gilbertd@cs.man.ac.uk)
6 * MFM hard drive code [experimental]
7 */
9 /*
10 * Change list:
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.
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.
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.
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!
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.
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.
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
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).
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!!!!
60 * Added test for mainboard controller. - Removes need for separate
61 * define.
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.)
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.
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?
78 *16/11/96:DAG: Modified for 2.0.18; request_irq changed
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)!
87 * 17/1/97:RMK: Upgraded to 2.1 kernels.
89 * 4/3/98:RMK: Changed major number to 21.
91 * 27/6/98:RMK: Changed asm/delay.h to linux/delay.h for mdelay().
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.
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>
116 #define MAJOR_NR MFM_ACORN_MAJOR
117 #include <linux/blk.h>
119 #include <asm/system.h>
120 #include <asm/io.h>
121 #include <asm/irq.h>
122 #include <asm/uaccess.h>
123 #include <asm/dma.h>
124 #include <asm/hardware.h>
125 #include <asm/ecard.h>
128 * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc
130 #ifndef HDIO_GETGEO
131 #define HDIO_GETGEO 0x301
132 struct hd_geometry {
133 unsigned char heads;
134 unsigned char sectors;
135 unsigned short cylinders;
136 unsigned long start;
138 #endif
142 * Configuration section
144 * This is the maximum number of drives that we accept
146 #define MFM_MAXDRIVES 2
148 * Linux I/O address of onboard MFM controller or 0 to disable this
150 #define ONBOARD_MFM_ADDRESS ((0x002d0000 >> 2) | 0x80000000)
152 * Uncomment this to enable debugging in the MFM driver...
154 #ifndef DEBUG
155 /*#define DEBUG */
156 #endif
158 * List of card types that we recognise
160 static const card_ids mfm_cids[] = {
161 { MANU_ACORN, PROD_ACORN_MFM },
162 { 0xffff, 0xffff }
165 * End of configuration
170 * This structure contains all information to do with a particular physical
171 * device.
173 struct mfm_info {
174 unsigned char sectors;
175 unsigned char heads;
176 unsigned short cylinders;
177 unsigned short lowcurrent;
178 unsigned short precomp;
179 #define NO_TRACK -1
180 #define NEED_1_RECAL -2
181 #define NEED_2_RECAL -3
182 int cylinder;
183 unsigned int access_count;
184 unsigned int busy;
185 struct {
186 char recal;
187 char report;
188 char abort;
189 } errors;
190 } mfm_info[MFM_MAXDRIVES];
192 #define MFM_DRV_INFO mfm_info[raw_cmd.dev]
194 static struct hd_struct mfm[MFM_MAXDRIVES << 6];
195 static int mfm_sizes[MFM_MAXDRIVES << 6];
196 static int mfm_blocksizes[MFM_MAXDRIVES << 6];
197 static int mfm_sectsizes[MFM_MAXDRIVES << 6];
198 static struct wait_queue *mfm_wait_open = NULL;
200 /* Stuff from the assembly routines */
201 extern unsigned int hdc63463_baseaddress; /* Controller base address */
202 extern unsigned int hdc63463_irqpolladdress; /* Address to read to test for int */
203 extern unsigned int hdc63463_irqpollmask; /* Mask for irq register */
204 extern unsigned int hdc63463_dataptr; /* Pointer to kernel data space to DMA */
205 extern int hdc63463_dataleft; /* Number of bytes left to transfer */
210 static int lastspecifieddrive;
211 static unsigned Busy;
213 static unsigned int PartFragRead; /* The number of sectors which have been read
214 during a partial read split over two
215 cylinders. If 0 it means a partial
216 read did not occur. */
218 static unsigned int PartFragRead_RestartBlock; /* Where to restart on a split access */
219 static unsigned int PartFragRead_SectorsLeft; /* Where to restart on a split access */
221 static int Sectors256LeftInCurrent; /* i.e. 256 byte sectors left in current */
222 static int SectorsLeftInRequest; /* i.e. blocks left in the thing mfm_request was called for */
223 static int Copy_Sector; /* The 256 byte sector we are currently at - fragments need to know
224 where to take over */
225 static char *Copy_buffer;
228 static void mfm_seek(void);
229 static void mfm_rerequest(void);
230 static void mfm_request(void);
231 static int mfm_reread_partitions(kdev_t dev);
232 static void mfm_specify (void);
233 static void issue_request(int dev, unsigned int block, unsigned int nsect,
234 struct request *req);
236 static unsigned int mfm_addr; /* Controller address */
237 static unsigned int mfm_IRQPollLoc; /* Address to read for IRQ information */
238 static unsigned int mfm_irqenable; /* Podule IRQ enable location */
239 static unsigned char mfm_irq; /* Interrupt number */
240 static int mfm_drives = 0; /* drives available */
241 static int mfm_status = 0; /* interrupt status */
242 static int *errors;
244 static struct rawcmd {
245 unsigned int dev;
246 unsigned int cylinder;
247 unsigned int head;
248 unsigned int sector;
249 unsigned int cmdtype;
250 unsigned int cmdcode;
251 unsigned char cmddata[16];
252 unsigned int cmdlen;
253 } raw_cmd;
255 static unsigned char result[16];
257 static struct cont {
258 void (*interrupt) (void); /* interrupt handler */
259 void (*error) (void); /* error handler */
260 void (*redo) (void); /* redo handler */
261 void (*done) (int st); /* done handler */
262 } *cont = NULL;
264 static struct tq_struct mfm_tq = {0, 0, (void (*)(void *)) NULL, 0};
266 int number_mfm_drives = 1;
268 /* ------------------------------------------------------------------------------------------ */
270 * From the HD63463 data sheet from Hitachi Ltd.
273 #define MFM_COMMAND (mfm_addr + 0)
274 #define MFM_DATAOUT (mfm_addr + 1)
275 #define MFM_STATUS (mfm_addr + 8)
276 #define MFM_DATAIN (mfm_addr + 9)
278 #define CMD_ABT 0xF0 /* Abort */
279 #define CMD_SPC 0xE8 /* Specify */
280 #define CMD_TST 0xE0 /* Test */
281 #define CMD_RCLB 0xC8 /* Recalibrate */
282 #define CMD_SEK 0xC0 /* Seek */
283 #define CMD_WFS 0xAB /* Write Format Skew */
284 #define CMD_WFM 0xA3 /* Write Format */
285 #define CMD_MTB 0x90 /* Memory to buffer */
286 #define CMD_CMPD 0x88 /* Compare data */
287 #define CMD_WD 0x87 /* Write data */
288 #define CMD_RED 0x70 /* Read erroneous data */
289 #define CMD_RIS 0x68 /* Read ID skew */
290 #define CMD_FID 0x61 /* Find ID */
291 #define CMD_RID 0x60 /* Read ID */
292 #define CMD_BTM 0x50 /* Buffer to memory */
293 #define CMD_CKD 0x48 /* Check data */
294 #define CMD_RD 0x40 /* Read data */
295 #define CMD_OPBW 0x38 /* Open buffer write */
296 #define CMD_OPBR 0x30 /* Open buffer read */
297 #define CMD_CKV 0x28 /* Check drive */
298 #define CMD_CKE 0x20 /* Check ECC */
299 #define CMD_POD 0x18 /* Polling disable */
300 #define CMD_POL 0x10 /* Polling enable */
301 #define CMD_RCAL 0x08 /* Recall */
303 #define STAT_BSY 0x8000 /* Busy */
304 #define STAT_CPR 0x4000 /* Command Parameter Rejection */
305 #define STAT_CED 0x2000 /* Command end */
306 #define STAT_SED 0x1000 /* Seek end */
307 #define STAT_DER 0x0800 /* Drive error */
308 #define STAT_ABN 0x0400 /* Abnormal end */
309 #define STAT_POL 0x0200 /* Polling */
311 /* ------------------------------------------------------------------------------------------ */
312 #ifdef DEBUG
313 static void console_printf(const char *fmt,...)
315 static char buffer[2048]; /* Arbitary! */
316 extern void console_print(const char *);
317 unsigned long flags;
318 va_list ap;
320 save_flags_cli(flags);
322 va_start(ap, fmt);
323 vsprintf(buffer, fmt, ap);
324 console_print(buffer);
325 va_end(fmt);
327 restore_flags(flags);
328 }; /* console_printf */
330 #define DBG(x...) console_printf(x)
331 #else
332 #define DBG(x...)
333 #endif
335 static void print_status(void)
337 char *error;
338 static char *errors[] = {
339 "no error",
340 "command aborted",
341 "invalid command",
342 "parameter error",
343 "not initialised",
344 "rejected TEST",
345 "no useld",
346 "write fault",
347 "not ready",
348 "no scp",
349 "in seek",
350 "invalid NCA",
351 "invalid step rate",
352 "seek error",
353 "over run",
354 "invalid PHA",
355 "data field EEC error",
356 "data field CRC error",
357 "error corrected",
358 "data field fatal error",
359 "no data am",
360 "not hit",
361 "ID field CRC error",
362 "time over",
363 "no ID am",
364 "not writable"
366 if (result[1] < 0x65)
367 error = errors[result[1] >> 2];
368 else
369 error = "unknown";
370 printk("(");
371 if (mfm_status & STAT_BSY) printk("BSY ");
372 if (mfm_status & STAT_CPR) printk("CPR ");
373 if (mfm_status & STAT_CED) printk("CED ");
374 if (mfm_status & STAT_SED) printk("SED ");
375 if (mfm_status & STAT_DER) printk("DER ");
376 if (mfm_status & STAT_ABN) printk("ABN ");
377 if (mfm_status & STAT_POL) printk("POL ");
378 printk(") SSB = %X (%s)\n", result[1], error);
382 /* ------------------------------------------------------------------------------------- */
384 static void issue_command(int command, unsigned char *cmdb, int len)
386 int status;
387 #ifdef DEBUG
388 int i;
389 console_printf("issue_command: %02X: ", command);
390 for (i = 0; i < len; i++)
391 console_printf("%02X ", cmdb[i]);
392 console_printf("\n");
393 #endif
395 do {
396 status = inw(MFM_STATUS);
397 } while (status & (STAT_BSY | STAT_POL));
398 DBG("issue_command: status after pol/bsy loop: %02X:\n ", status >> 8);
400 if (status & (STAT_CPR | STAT_CED | STAT_SED | STAT_DER | STAT_ABN)) {
401 outw(CMD_RCAL, MFM_COMMAND);
402 while (inw(MFM_STATUS) & STAT_BSY);
404 status = inw(MFM_STATUS);
405 DBG("issue_command: status before parameter issue: %02X:\n ", status >> 8);
407 while (len > 0) {
408 outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT);
409 len -= 2;
410 cmdb += 2;
412 status = inw(MFM_STATUS);
413 DBG("issue_command: status before command issue: %02X:\n ", status >> 8);
415 outw(command, MFM_COMMAND);
416 status = inw(MFM_STATUS);
417 DBG("issue_command: status immediatly after command issue: %02X:\n ", status >> 8);
420 static void wait_for_completion(void)
422 while ((mfm_status = inw(MFM_STATUS)) & STAT_BSY);
425 static void wait_for_command_end(void)
427 int i;
429 while (!((mfm_status = inw(MFM_STATUS)) & STAT_CED));
431 for (i = 0; i < 16;) {
432 int in;
433 in = inw(MFM_DATAIN);
434 result[i++] = in >> 8;
435 result[i++] = in;
437 outw (CMD_RCAL, MFM_COMMAND);
440 /* ------------------------------------------------------------------------------------- */
442 static void mfm_rw_intr(void)
444 int old_status; /* Holds status on entry, we read to see if the command just finished */
445 #ifdef DEBUG
446 console_printf("mfm_rw_intr...dataleft=%d\n", hdc63463_dataleft);
447 print_status();
448 #endif
450 /* Now don't handle the error until BSY drops */
451 if ((mfm_status & (STAT_DER | STAT_ABN)) && ((mfm_status&STAT_BSY)==0)) {
452 /* Something has gone wrong - let's try that again */
453 outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */
454 if (cont) {
455 DBG("mfm_rw_intr: DER/ABN err\n");
456 cont->error();
457 cont->redo();
459 return;
462 /* OK so what ever happend its not an error, now I reckon we are left between
463 a choice of command end or some data which is ready to be collected */
464 /* I think we have to transfer data while the interrupt line is on and its
465 not any other type of interrupt */
466 if (CURRENT->cmd == WRITE) {
467 extern void hdc63463_writedma(void);
468 if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
469 printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
470 if (cont) {
471 cont->error();
472 cont->redo();
474 return;
476 hdc63463_writedma();
477 } else {
478 extern void hdc63463_readdma(void);
479 if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
480 printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n");
481 if (cont) {
482 cont->error();
483 cont->redo();
485 return;
487 DBG("Going to try read dma..............status=0x%x, buffer=%p\n", mfm_status, hdc63463_dataptr);
488 hdc63463_readdma();
489 }; /* Read */
491 if (hdc63463_dataptr != ((unsigned int) Copy_buffer + 256)) {
492 /* If we didn't actually manage to get any data on this interrupt - but why? We got the interrupt */
493 /* Ah - well looking at the status its just when we get command end; so no problem */
494 /*console_printf("mfm: dataptr mismatch. dataptr=0x%08x Copy_buffer+256=0x%08p\n",
495 hdc63463_dataptr,Copy_buffer+256);
496 print_status(); */
497 } else {
498 Sectors256LeftInCurrent--;
499 Copy_buffer += 256;
500 Copy_Sector++;
502 /* We have come to the end of this request */
503 if (!Sectors256LeftInCurrent) {
504 DBG("mfm: end_request for CURRENT=0x%p CURRENT(sector=%d current_nr_sectors=%d nr_sectors=%d)\n",
505 CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->nr_sectors);
507 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
508 CURRENT->sector += CURRENT->current_nr_sectors;
509 SectorsLeftInRequest -= CURRENT->current_nr_sectors;
511 end_request(1);
512 if (SectorsLeftInRequest) {
513 hdc63463_dataptr = (unsigned int) CURRENT->buffer;
514 Copy_buffer = CURRENT->buffer;
515 Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
516 errors = &(CURRENT->errors);
517 /* These should match the present calculations of the next logical sector
518 on the device
519 Copy_Sector=CURRENT->sector*2; */
521 if (Copy_Sector != CURRENT->sector * 2)
522 #ifdef DEBUG
523 /*console_printf*/printk("mfm: Copy_Sector mismatch. Copy_Sector=%d CURRENT->sector*2=%d\n",
524 Copy_Sector, CURRENT->sector * 2);
525 #else
526 printk("mfm: Copy_Sector mismatch! Eek!\n");
527 #endif
528 }; /* CURRENT */
529 }; /* Sectors256LeftInCurrent */
532 old_status = mfm_status;
533 mfm_status = inw(MFM_STATUS);
534 if (mfm_status & (STAT_DER | STAT_ABN)) {
535 /* Something has gone wrong - let's try that again */
536 if (cont) {
537 DBG("mfm_rw_intr: DER/ABN error\n");
538 cont->error();
539 cont->redo();
541 return;
544 /* If this code wasn't entered due to command_end but there is
545 now a command end we must read the command results out. If it was
546 entered like this then mfm_interrupt_handler would have done the
547 job. */
548 if ((!((old_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) &&
549 ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) {
550 int len = 0;
551 while (len < 16) {
552 int in;
553 in = inw(MFM_DATAIN);
554 result[len++] = in >> 8;
555 result[len++] = in;
557 }; /* Result read */
559 /*console_printf ("mfm_rw_intr nearexit [%02X]\n", inb(mfm_IRQPollLoc)); */
561 /* If end of command move on */
562 if (mfm_status & (STAT_CED)) {
563 outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */
564 /* End of command - trigger the next command */
565 if (cont) {
566 cont->done(1);
568 DBG("mfm_rw_intr: returned from cont->done\n");
569 } else {
570 /* Its going to generate another interrupt */
571 SET_INTR(mfm_rw_intr);
575 static void mfm_setup_rw(void)
577 DBG("setting up for rw...\n");
579 SET_INTR(mfm_rw_intr);
580 issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen);
583 static void mfm_recal_intr(void)
585 #ifdef DEBUG
586 console_printf("recal intr - status = ");
587 print_status();
588 #endif
589 outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */
590 if (mfm_status & (STAT_DER | STAT_ABN)) {
591 printk("recal failed\n");
592 MFM_DRV_INFO.cylinder = NEED_2_RECAL;
593 if (cont) {
594 cont->error();
595 cont->redo();
597 return;
599 /* Thats seek end - we are finished */
600 if (mfm_status & STAT_SED) {
601 issue_command(CMD_POD, NULL, 0);
602 MFM_DRV_INFO.cylinder = 0;
603 mfm_seek();
604 return;
606 /* Command end without seek end (see data sheet p.20) for parallel seek
607 - we have to send a POL command to wait for the seek */
608 if (mfm_status & STAT_CED) {
609 SET_INTR(mfm_recal_intr);
610 issue_command(CMD_POL, NULL, 0);
611 return;
613 printk("recal: unknown status\n");
616 static void mfm_seek_intr(void)
618 #ifdef DEBUG
619 console_printf("seek intr - status = ");
620 print_status();
621 #endif
622 outw(CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */
623 if (mfm_status & (STAT_DER | STAT_ABN)) {
624 printk("seek failed\n");
625 MFM_DRV_INFO.cylinder = NEED_2_RECAL;
626 if (cont) {
627 cont->error();
628 cont->redo();
630 return;
632 if (mfm_status & STAT_SED) {
633 issue_command(CMD_POD, NULL, 0);
634 MFM_DRV_INFO.cylinder = raw_cmd.cylinder;
635 mfm_seek();
636 return;
638 if (mfm_status & STAT_CED) {
639 SET_INTR(mfm_seek_intr);
640 issue_command(CMD_POL, NULL, 0);
641 return;
643 printk("seek: unknown status\n");
646 /* IDEA2 seems to work better - its what RiscOS sets my
647 * disc to - on its SECOND call to specify!
649 #define IDEA2
650 #ifndef IDEA2
651 #define SPEC_SL 0x16
652 #define SPEC_SH 0xa9 /* Step pulse high=21, Record Length=001 (256 bytes) */
653 #else
654 #define SPEC_SL 0x00 /* OM2 - SL - step pulse low */
655 #define SPEC_SH 0x21 /* Step pulse high=4, Record Length=001 (256 bytes) */
656 #endif
658 static void mfm_setupspecify (int drive, unsigned char *cmdb)
660 cmdb[0] = 0x1f; /* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */
661 cmdb[1] = 0xc3; /* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */
662 cmdb[2] = SPEC_SL; /* OM2 - SL - step pulse low */
663 cmdb[3] = (number_mfm_drives == 1) ? 0x02 : 0x06; /* 1 or 2 drives */
664 cmdb[4] = 0xfc | ((mfm_info[drive].cylinders - 1) >> 8);/* RW time over/high part of number of cylinders */
665 cmdb[5] = mfm_info[drive].cylinders - 1; /* low part of number of cylinders */
666 cmdb[6] = mfm_info[drive].heads - 1; /* Number of heads */
667 cmdb[7] = mfm_info[drive].sectors - 1; /* Number of sectors */
668 cmdb[8] = SPEC_SH;
669 cmdb[9] = 0x0a; /* gap length 1 */
670 cmdb[10] = 0x0d; /* gap length 2 */
671 cmdb[11] = 0x0c; /* gap length 3 */
672 cmdb[12] = (mfm_info[drive].precomp - 1) >> 8; /* pre comp cylinder */
673 cmdb[13] = mfm_info[drive].precomp - 1;
674 cmdb[14] = (mfm_info[drive].lowcurrent - 1) >> 8; /* Low current cylinder */
675 cmdb[15] = mfm_info[drive].lowcurrent - 1;
678 static void mfm_specify (void)
680 unsigned char cmdb[16];
682 DBG("specify...dev=%d lastspecified=%d\n", raw_cmd.dev, lastspecifieddrive);
683 mfm_setupspecify (raw_cmd.dev, cmdb);
685 issue_command (CMD_SPC, cmdb, 16);
686 /* Ensure that we will do another specify if we move to the other drive */
687 lastspecifieddrive = raw_cmd.dev;
688 wait_for_completion();
691 static void mfm_seek(void)
693 unsigned char cmdb[4];
695 DBG("seeking...\n");
696 if (MFM_DRV_INFO.cylinder < 0) {
697 SET_INTR(mfm_recal_intr);
698 DBG("mfm_seek: about to call specify\n");
699 mfm_specify (); /* DAG added this */
701 cmdb[0] = raw_cmd.dev + 1;
702 cmdb[1] = 0;
704 issue_command(CMD_RCLB, cmdb, 2);
705 return;
707 if (MFM_DRV_INFO.cylinder != raw_cmd.cylinder) {
708 cmdb[0] = raw_cmd.dev + 1;
709 cmdb[1] = 0; /* raw_cmd.head; DAG: My data sheet says this should be 0 */
710 cmdb[2] = raw_cmd.cylinder >> 8;
711 cmdb[3] = raw_cmd.cylinder;
713 SET_INTR(mfm_seek_intr);
714 issue_command(CMD_SEK, cmdb, 4);
715 } else
716 mfm_setup_rw();
719 static void mfm_initialise(void)
721 DBG("init...\n");
722 mfm_seek();
725 static void request_done(int uptodate)
727 DBG("mfm:request_done\n");
728 if (uptodate) {
729 unsigned char block[2] = {0, 0};
731 /* Apparently worked - let's check bytes left to DMA */
732 if (hdc63463_dataleft != (PartFragRead_SectorsLeft * 256)) {
733 printk("mfm: request_done - dataleft=%d - should be %d - Eek!\n", hdc63463_dataleft, PartFragRead_SectorsLeft * 256);
734 end_request(0);
735 Busy = 0;
737 /* Potentially this means that we've done; but we might be doing
738 a partial access, (over two cylinders) or we may have a number
739 of fragments in an image file. First let's deal with partial accesss
741 if (PartFragRead) {
742 /* Yep - a partial access */
744 /* and issue the remainder */
745 issue_request(MINOR(CURRENT->rq_dev), PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
746 return;
749 /* ah well - perhaps there is another fragment to go */
751 /* Increment pointers/counts to start of next fragment */
752 if (SectorsLeftInRequest > 0) printk("mfm: SectorsLeftInRequest>0 - Eek! Shouldn't happen!\n");
754 /* No - its the end of the line */
755 /* end_request's should have happened at the end of sector DMAs */
756 /* Turns Drive LEDs off - may slow it down? */
757 if (!CURRENT)
758 issue_command(CMD_CKV, block, 2);
760 Busy = 0;
761 DBG("request_done: About to mfm_request\n");
762 /* Next one please */
763 mfm_request(); /* Moved from mfm_rw_intr */
764 DBG("request_done: returned from mfm_request\n");
765 } else {
766 printk("mfm:request_done: update=0\n");
767 end_request(0);
768 Busy = 0;
772 static void error_handler(void)
774 printk("error detected... status = ");
775 print_status();
776 (*errors)++;
777 if (*errors > MFM_DRV_INFO.errors.abort)
778 cont->done(0);
779 if (*errors > MFM_DRV_INFO.errors.recal)
780 MFM_DRV_INFO.cylinder = NEED_2_RECAL;
783 static void rw_interrupt(void)
785 printk("rw_interrupt\n");
788 static struct cont rw_cont =
790 rw_interrupt,
791 error_handler,
792 mfm_rerequest,
793 request_done
797 * Actually gets round to issuing the request - note everything at this
798 * point is in 256 byte sectors not Linux 512 byte blocks
800 static void issue_request(int dev, unsigned int block, unsigned int nsect,
801 struct request *req)
803 int track, start_head, start_sector;
804 int sectors_to_next_cyl;
806 dev >>= 6;
808 track = block / mfm_info[dev].sectors;
809 start_sector = block % mfm_info[dev].sectors;
810 start_head = track % mfm_info[dev].heads;
812 /* First get the number of whole tracks which are free before the next
813 track */
814 sectors_to_next_cyl = (mfm_info[dev].heads - (start_head + 1)) * mfm_info[dev].sectors;
815 /* Then add in the number of sectors left on this track */
816 sectors_to_next_cyl += (mfm_info[dev].sectors - start_sector);
818 DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", mfm_info[dev].sectors, track);
820 raw_cmd.dev = dev;
821 raw_cmd.sector = start_sector;
822 raw_cmd.head = start_head;
823 raw_cmd.cylinder = track / mfm_info[dev].heads;
824 raw_cmd.cmdtype = CURRENT->cmd;
825 raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
826 raw_cmd.cmddata[0] = dev + 1; /* DAG: +1 to get US */
827 raw_cmd.cmddata[1] = raw_cmd.head;
828 raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
829 raw_cmd.cmddata[3] = raw_cmd.cylinder;
830 raw_cmd.cmddata[4] = raw_cmd.head;
831 raw_cmd.cmddata[5] = raw_cmd.sector;
833 /* Was == and worked - how the heck??? */
834 if (lastspecifieddrive != raw_cmd.dev)
835 mfm_specify ();
837 if (nsect <= sectors_to_next_cyl) {
838 raw_cmd.cmddata[6] = nsect >> 8;
839 raw_cmd.cmddata[7] = nsect;
840 PartFragRead = 0; /* All in one */
841 PartFragRead_SectorsLeft = 0; /* Must set this - used in DMA calcs */
842 } else {
843 raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8;
844 raw_cmd.cmddata[7] = sectors_to_next_cyl;
845 PartFragRead = sectors_to_next_cyl; /* only do this many this time */
846 PartFragRead_RestartBlock = block + sectors_to_next_cyl; /* Where to restart from */
847 PartFragRead_SectorsLeft = nsect - sectors_to_next_cyl;
849 raw_cmd.cmdlen = 8;
851 /* Setup DMA pointers */
852 hdc63463_dataptr = (unsigned int) Copy_buffer;
853 hdc63463_dataleft = nsect * 256; /* Better way? */
855 DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
856 raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
857 raw_cmd.cylinder,
858 raw_cmd.head,
859 raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
861 cont = &rw_cont;
862 errors = &(CURRENT->errors);
863 #if 0
864 mfm_tq.routine = (void (*)(void *)) mfm_initialise;
865 queue_task(&mfm_tq, &tq_immediate);
866 mark_bh(IMMEDIATE_BH);
867 #else
868 mfm_initialise();
869 #endif
870 } /* issue_request */
873 * Called when an error has just happened - need to trick mfm_request
874 * into thinking we weren't busy
876 * Turn off ints - mfm_request expects them this way
878 static void mfm_rerequest(void)
880 DBG("mfm_rerequest\n");
881 cli();
882 Busy = 0;
883 mfm_request();
886 static void mfm_request(void)
888 DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy);
890 if (!CURRENT) {
891 DBG("mfm_request: Exited due to NULL Current 1\n");
892 return;
895 if (CURRENT->rq_status == RQ_INACTIVE) {
896 /* Hmm - seems to be happening a lot on 1.3.45 */
897 /*console_printf("mfm_request: Exited due to INACTIVE Current\n"); */
898 return;
901 /* If we are still processing then return; we will get called again */
902 if (Busy) {
903 /* Again seems to be common in 1.3.45 */
904 /*DBG*/printk("mfm_request: Exiting due to busy\n");
905 return;
907 Busy = 1;
909 while (1) {
910 unsigned int dev, block, nsect;
912 DBG("mfm_request: loop start\n");
913 sti();
915 DBG("mfm_request: before INIT_REQUEST\n");
917 if (!CURRENT) {
918 printk("mfm_request: Exiting due to !CURRENT (pre)\n");
919 CLEAR_INTR;
920 Busy = 0;
921 return;
924 INIT_REQUEST;
926 DBG("mfm_request: before arg extraction\n");
928 dev = MINOR(CURRENT->rq_dev);
929 block = CURRENT->sector;
930 nsect = CURRENT->nr_sectors;
931 #ifdef DEBUG
932 /*if ((dev>>6)==1) */ console_printf("mfm_request: raw vals: dev=%d (block=512 bytes) block=%d nblocks=%d\n", dev, block, nsect);
933 #endif
934 if (dev >= (mfm_drives << 6) ||
935 block >= mfm[dev].nr_sects || ((block+nsect) > mfm[dev].nr_sects)) {
936 if (dev >= (mfm_drives << 6))
937 printk("mfm: bad minor number: device=%s\n", kdevname(CURRENT->rq_dev));
938 else
939 printk("mfm%c: bad access: block=%d, count=%d, nr_sects=%ld\n", (dev >> 6)+'a',
940 block, nsect, mfm[dev].nr_sects);
941 printk("mfm: continue 1\n");
942 end_request(0);
943 Busy = 0;
944 continue;
947 block += mfm[dev].start_sect;
949 /* DAG: Linux doesn't cope with this - even though it has an array telling
950 it the hardware block size - silly */
951 block <<= 1; /* Now in 256 byte sectors */
952 nsect <<= 1; /* Ditto */
954 SectorsLeftInRequest = nsect >> 1;
955 Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
956 Copy_buffer = CURRENT->buffer;
957 Copy_Sector = CURRENT->sector << 1;
959 DBG("mfm_request: block after offset=%d\n", block);
961 if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
962 printk("unknown mfm-command %d\n", CURRENT->cmd);
963 end_request(0);
964 Busy = 0;
965 printk("mfm: continue 4\n");
966 continue;
968 issue_request(dev, block, nsect, CURRENT);
970 break;
972 DBG("mfm_request: Dropping out bottom\n");
975 static void do_mfm_request(void)
977 DBG("do_mfm_request: about to mfm_request\n");
978 mfm_request();
981 static void mfm_interrupt_handler(int unused, void *dev_id, struct pt_regs *regs)
983 void (*handler) (void) = DEVICE_INTR;
985 CLEAR_INTR;
987 DBG("mfm_interrupt_handler (handler=0x%p)\n", handler);
989 mfm_status = inw(MFM_STATUS);
991 /* If CPR (Command Parameter Reject) and not busy it means that the command
992 has some return message to give us */
993 if ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR) {
994 int len = 0;
995 while (len < 16) {
996 int in;
997 in = inw(MFM_DATAIN);
998 result[len++] = in >> 8;
999 result[len++] = in;
1002 if (handler) {
1003 handler();
1004 return;
1006 outw (CMD_RCAL, MFM_COMMAND); /* Clear interrupt condition */
1007 printk ("mfm: unexpected interrupt - status = ");
1008 print_status ();
1009 while (1);
1017 * Tell the user about the drive if we decided it exists. Also,
1018 * set the size of the drive.
1020 static void mfm_geometry (int drive)
1022 if (mfm_info[drive].cylinders)
1023 printk ("mfm%c: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n", 'a' + drive,
1024 mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 4096,
1025 mfm_info[drive].cylinders, mfm_info[drive].heads, mfm_info[drive].sectors,
1026 mfm_info[drive].lowcurrent, mfm_info[drive].precomp);
1027 mfm[drive << 6].start_sect = 0;
1028 mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;
1031 #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
1033 * Attempt to detect a drive and find its geometry. The drive has already been
1034 * specified...
1036 * We first recalibrate the disk, then try to probe sectors, heads and then
1037 * cylinders. NOTE! the cylinder probe may break drives. The xd disk driver
1038 * does something along these lines, so I assume that most drives are up to
1039 * this mistreatment...
1041 static int mfm_detectdrive (int drive)
1043 unsigned int mingeo[3], maxgeo[3];
1044 unsigned int attribute, need_recal = 1;
1045 unsigned char cmdb[8];
1047 memset (mingeo, 0, sizeof (mingeo));
1048 maxgeo[0] = mfm_info[drive].sectors;
1049 maxgeo[1] = mfm_info[drive].heads;
1050 maxgeo[2] = mfm_info[drive].cylinders;
1052 cmdb[0] = drive + 1;
1053 cmdb[6] = 0;
1054 cmdb[7] = 1;
1055 for (attribute = 0; attribute < 3; attribute++) {
1056 while (mingeo[attribute] != maxgeo[attribute]) {
1057 unsigned int variable;
1059 variable = (maxgeo[attribute] + mingeo[attribute]) >> 1;
1060 cmdb[1] = cmdb[2] = cmdb[3] = cmdb[4] = cmdb[5] = 0;
1062 if (need_recal) {
1063 int tries = 5;
1065 do {
1066 issue_command (CMD_RCLB, cmdb, 2);
1067 wait_for_completion ();
1068 wait_for_command_end ();
1069 if (result[1] == 0x20)
1070 break;
1071 } while (result[1] && --tries);
1072 if (result[1]) {
1073 outw (CMD_RCAL, MFM_COMMAND);
1074 return 0;
1076 need_recal = 0;
1079 switch (attribute) {
1080 case 0:
1081 cmdb[5] = variable;
1082 issue_command (CMD_CMPD, cmdb, 8);
1083 break;
1084 case 1:
1085 cmdb[1] = variable;
1086 cmdb[4] = variable;
1087 issue_command (CMD_CMPD, cmdb, 8);
1088 break;
1089 case 2:
1090 cmdb[2] = variable >> 8;
1091 cmdb[3] = variable;
1092 issue_command (CMD_SEK, cmdb, 4);
1093 break;
1095 wait_for_completion ();
1096 wait_for_command_end ();
1098 switch (result[1]) {
1099 case 0x00:
1100 case 0x50:
1101 mingeo[attribute] = variable + 1;
1102 break;
1104 case 0x20:
1105 outw (CMD_RCAL, MFM_COMMAND);
1106 return 0;
1108 case 0x24:
1109 need_recal = 1;
1110 default:
1111 maxgeo[attribute] = variable;
1112 break;
1116 mfm_info[drive].cylinders = mingeo[2];
1117 mfm_info[drive].lowcurrent = mingeo[2];
1118 mfm_info[drive].precomp = mingeo[2] / 2;
1119 mfm_info[drive].heads = mingeo[1];
1120 mfm_info[drive].sectors = mingeo[0];
1121 outw (CMD_RCAL, MFM_COMMAND);
1122 return 1;
1124 #endif
1127 * Initialise all drive information for this controller.
1129 static int mfm_initdrives(void)
1131 int drive;
1133 if (number_mfm_drives > MFM_MAXDRIVES) {
1134 number_mfm_drives = MFM_MAXDRIVES;
1135 printk("No. of ADFS MFM drives is greater than MFM_MAXDRIVES - you can't have that many!\n");
1138 for (drive = 0; drive < number_mfm_drives; drive++) {
1139 mfm_info[drive].lowcurrent = 1;
1140 mfm_info[drive].precomp = 1;
1141 mfm_info[drive].cylinder = -1;
1142 mfm_info[drive].errors.recal = 0;
1143 mfm_info[drive].errors.report = 0;
1144 mfm_info[drive].errors.abort = 4;
1146 #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
1147 mfm_info[drive].cylinders = 1024;
1148 mfm_info[drive].heads = 8;
1149 mfm_info[drive].sectors = 64;
1151 unsigned char cmdb[16];
1153 mfm_setupspecify (drive, cmdb);
1154 cmdb[1] &= ~0x81;
1155 issue_command (CMD_SPC, cmdb, 16);
1156 wait_for_completion ();
1157 if (!mfm_detectdrive (drive)) {
1158 mfm_info[drive].cylinders = 0;
1159 mfm_info[drive].heads = 0;
1160 mfm_info[drive].sectors = 0;
1162 cmdb[0] = cmdb[1] = 0;
1163 issue_command (CMD_CKV, cmdb, 2);
1165 #else
1166 mfm_info[drive].cylinders = 1; /* its going to have to figure it out from the partition info */
1167 mfm_info[drive].heads = 4;
1168 mfm_info[drive].sectors = 32;
1169 #endif
1171 return number_mfm_drives;
1177 * The 'front' end of the mfm driver follows...
1180 static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
1182 struct hd_geometry *geo = (struct hd_geometry *) arg;
1183 kdev_t dev;
1184 int device, major, minor, err;
1186 if (!inode || !(dev = inode->i_rdev))
1187 return -EINVAL;
1189 major = MAJOR(dev);
1190 minor = MINOR(dev);
1192 device = DEVICE_NR(MINOR(inode->i_rdev)), err;
1193 if (device >= mfm_drives)
1194 return -EINVAL;
1196 switch (cmd) {
1197 case HDIO_GETGEO:
1198 if (!arg)
1199 return -EINVAL;
1200 if (put_user (mfm_info[device].heads, &geo->heads))
1201 return -EFAULT;
1202 if (put_user (mfm_info[device].sectors, &geo->sectors))
1203 return -EFAULT;
1204 if (put_user (mfm_info[device].cylinders, &geo->cylinders))
1205 return -EFAULT;
1206 if (put_user (mfm[minor].start_sect, &geo->start))
1207 return -EFAULT;
1208 return 0;
1210 case BLKFLSBUF:
1211 if (!capable(CAP_SYS_ADMIN))
1212 return -EACCES;
1213 fsync_dev(dev);
1214 invalidate_buffers(dev);
1215 return 0;
1217 case BLKRASET:
1218 if (!capable(CAP_SYS_ADMIN))
1219 return -EACCES;
1220 if (arg > 0xff)
1221 return -EINVAL;
1222 read_ahead[major] = arg;
1223 return 0;
1225 case BLKRAGET:
1226 return put_user(read_ahead[major], (long *)arg);
1228 case BLKGETSIZE:
1229 return put_user (mfm[minor].nr_sects, (long *)arg);
1231 case BLKFRASET:
1232 if (!capable(CAP_SYS_ADMIN))
1233 return -EACCES;
1234 max_readahead[major][minor] = arg;
1235 return 0;
1237 case BLKFRAGET:
1238 return put_user(max_readahead[major][minor], (long *) arg);
1240 case BLKSECTGET:
1241 return put_user(max_sectors[major][minor], (long *) arg);
1243 case BLKRRPART:
1244 if (!capable(CAP_SYS_ADMIN))
1245 return -EACCES;
1246 return mfm_reread_partitions(dev);
1248 RO_IOCTLS(dev, arg);
1250 default:
1251 return -EINVAL;
1255 static int mfm_open(struct inode *inode, struct file *file)
1257 int dev = DEVICE_NR(MINOR(inode->i_rdev));
1259 if (dev >= mfm_drives)
1260 return -ENODEV;
1262 MOD_INC_USE_COUNT;
1263 while (mfm_info[dev].busy)
1264 sleep_on (&mfm_wait_open);
1266 mfm_info[dev].access_count++;
1267 return 0;
1271 * Releasing a block device means we sync() it, so that it can safely
1272 * be forgotten about...
1274 static int mfm_release(struct inode *inode, struct file *file)
1276 fsync_dev(inode->i_rdev);
1277 mfm_info[DEVICE_NR(MINOR(inode->i_rdev))].access_count--;
1278 MOD_DEC_USE_COUNT;
1279 return 0;
1283 * This is to handle various kernel command line parameters
1284 * specific to this driver.
1286 void mfm_setup(char *str, int *ints)
1288 return;
1292 * Set the CHS from the ADFS boot block if it is present. This is not ideal
1293 * since if there are any non-ADFS partitions on the disk, this won't work!
1294 * Hence, I want to get rid of this...
1296 void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
1297 unsigned long discsize, unsigned int secsize)
1299 int drive = MINOR(dev) >> 6;
1301 if (mfm_info[drive].cylinders == 1) {
1302 mfm_info[drive].sectors = secsptrack;
1303 mfm_info[drive].heads = heads;
1304 mfm_info[drive].cylinders = discsize / (secsptrack * heads * secsize);
1306 if ((heads < 1) || (mfm_info[drive].cylinders > 1024)) {
1307 printk("mfm%c: Insane disc shape! Setting to 512/4/32\n",'a' + (dev >> 6));
1309 /* These values are fairly arbitary, but are there so that if your
1310 * lucky you can pick apart your disc to find out what is going on -
1311 * I reckon these figures won't hurt MOST drives
1313 mfm_info[drive].sectors = 32;
1314 mfm_info[drive].heads = 4;
1315 mfm_info[drive].cylinders = 512;
1317 if (raw_cmd.dev == drive)
1318 mfm_specify ();
1319 mfm_geometry (drive);
1323 static void mfm_geninit (struct gendisk *gdev);
1325 static struct gendisk mfm_gendisk = {
1326 MAJOR_NR, /* Major number */
1327 "mfm", /* Major name */
1328 6, /* Bits to shift to get real from partition */
1329 1 << 6, /* Number of partitions per real */
1330 MFM_MAXDRIVES, /* maximum number of real */
1331 mfm_geninit, /* init function */
1332 mfm, /* hd struct */
1333 mfm_sizes, /* block sizes */
1334 0, /* number */
1335 (void *) mfm_info, /* internal */
1336 NULL /* next */
1339 static void mfm_geninit (struct gendisk *gdev)
1341 int i;
1343 mfm_drives = mfm_initdrives();
1345 printk("mfm: detected %d hard drive%s\n", mfm_drives, mfm_drives == 1 ? "" : "s");
1346 gdev->nr_real = mfm_drives;
1348 for (i = 0; i < mfm_drives; i++)
1349 mfm_geometry (i);
1351 if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
1352 printk("mfm: unable to get IRQ%d\n", mfm_irq);
1354 if (mfm_irqenable)
1355 outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */
1357 for (i = 0; i < (MFM_MAXDRIVES << 6); i++) {
1358 mfm_blocksizes[i] = 1024; /* Can't increase this - if you do all hell breaks loose */
1359 mfm_sectsizes[i] = 512;
1361 blksize_size[MAJOR_NR] = mfm_blocksizes;
1362 hardsect_size[MAJOR_NR] = mfm_sectsizes;
1365 static struct file_operations mfm_fops =
1367 NULL, /* lseek - default */
1368 block_read, /* read - general block-dev read */
1369 block_write, /* write - general block-dev write */
1370 NULL, /* readdir - bad */
1371 NULL, /* poll */
1372 mfm_ioctl, /* ioctl */
1373 NULL, /* mmap */
1374 mfm_open, /* open */
1375 NULL, /* flush */
1376 mfm_release, /* release */
1377 block_fsync, /* fsync */
1378 NULL, /* fasync */
1379 NULL, /* check_media_change */
1380 NULL /* revalidate */
1384 static struct expansion_card *ecs;
1387 * See if there is a controller at the address presently at mfm_addr
1389 * We check to see if the controller is busy - if it is, we abort it first,
1390 * and check that the chip is no longer busy after at least 180 clock cycles.
1391 * We then issue a command and check that the BSY or CPR bits are set.
1393 static int mfm_probecontroller (unsigned int mfm_addr)
1395 if (check_region (mfm_addr, 10))
1396 return 0;
1398 if (inw (MFM_STATUS) & STAT_BSY) {
1399 outw (CMD_ABT, MFM_COMMAND);
1400 udelay (50);
1401 if (inw (MFM_STATUS) & STAT_BSY)
1402 return 0;
1405 if (inw (MFM_STATUS) & STAT_CED)
1406 outw (CMD_RCAL, MFM_COMMAND);
1408 outw (CMD_SEK, MFM_COMMAND);
1410 if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) {
1411 unsigned int count = 2000;
1412 while (inw (MFM_STATUS) & STAT_BSY) {
1413 udelay (500);
1414 if (!--count)
1415 return 0;
1418 outw (CMD_RCAL, MFM_COMMAND);
1420 return 1;
1424 * Look for a MFM controller - first check the motherboard, then the podules
1425 * The podules have an extra interrupt enable that needs to be played with
1427 * The HDC is accessed at MEDIUM IOC speeds.
1429 int mfm_init (void)
1431 unsigned char irqmask;
1433 if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
1434 printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
1435 return -1;
1438 if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
1439 mfm_addr = ONBOARD_MFM_ADDRESS;
1440 mfm_IRQPollLoc = IOC_IRQSTATB;
1441 mfm_irqenable = 0;
1442 mfm_irq = IRQ_HARDDISK;
1443 irqmask = 0x08; /* IL3 pin */
1444 } else {
1445 ecs = ecard_find(0, mfm_cids);
1446 if (!ecs) {
1447 mfm_addr = 0;
1448 return -1;
1451 mfm_addr = ecard_address(ecs, ECARD_IOC, ECARD_MEDIUM) + 0x800;
1452 mfm_IRQPollLoc = mfm_addr + 0x400;
1453 mfm_irqenable = mfm_IRQPollLoc;
1454 mfm_irq = ecs->irq;
1455 irqmask = 0x08;
1457 ecard_claim(ecs);
1460 printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
1461 request_region (mfm_addr, 10, "mfm");
1463 /* Stuff for the assembler routines to get to */
1464 hdc63463_baseaddress = ioaddr(mfm_addr);
1465 hdc63463_irqpolladdress = ioaddr(mfm_IRQPollLoc);
1466 hdc63463_irqpollmask = irqmask;
1468 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1469 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB?) read ahread */
1471 #ifndef MODULE
1472 mfm_gendisk.next = gendisk_head;
1473 gendisk_head = &mfm_gendisk;
1474 #endif
1476 Busy = 0;
1477 lastspecifieddrive = -1;
1479 return 0;
1483 * This routine is called to flush all partitions and partition tables
1484 * for a changed MFM disk, and then re-read the new partition table.
1485 * If we are revalidating due to an ioctl, we have USAGE == 1.
1487 static int mfm_reread_partitions(kdev_t dev)
1489 unsigned int start, i, maxp, target = DEVICE_NR(MINOR(dev));
1490 unsigned long flags;
1492 save_flags_cli(flags);
1493 if (mfm_info[target].busy || mfm_info[target].access_count > 1) {
1494 restore_flags (flags);
1495 return -EBUSY;
1497 mfm_info[target].busy = 1;
1498 restore_flags (flags);
1500 maxp = mfm_gendisk.max_p;
1501 start = target << mfm_gendisk.minor_shift;
1503 for (i = maxp - 1; i >= 0; i--) {
1504 int minor = start + i;
1505 kdev_t devi = MKDEV(MAJOR_NR, minor);
1506 struct super_block *sb = get_super(devi);
1508 sync_dev (devi);
1509 if (sb)
1510 invalidate_inodes (sb);
1511 invalidate_buffers (devi);
1513 mfm_gendisk.part[minor].start_sect = 0;
1514 mfm_gendisk.part[minor].nr_sects = 0;
1517 mfm_gendisk.part[start].nr_sects = mfm_info[target].heads *
1518 mfm_info[target].cylinders * mfm_info[target].sectors / 2;
1520 resetup_one_dev(&mfm_gendisk, target);
1522 mfm_info[target].busy = 0;
1523 wake_up (&mfm_wait_open);
1524 return 0;
1527 #ifdef MODULE
1528 int init_module(void)
1530 int ret;
1531 ret = mfm_init();
1532 if (!ret)
1533 mfm_geninit(&mfm_gendisk);
1534 return ret;
1537 void cleanup_module(void)
1539 if (ecs && mfm_irqenable)
1540 outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */
1541 free_irq(mfm_irq, NULL);
1542 unregister_blkdev(MAJOR_NR, "mfm");
1543 if (ecs)
1544 ecard_release(ecs);
1545 if (mfm_addr)
1546 release_region(mfm_addr, 10);
1548 #endif