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