Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.34-rc5 1842 lines 47 kB view raw
1/* 2 * linux/amiga/amiflop.c 3 * 4 * Copyright (C) 1993 Greg Harp 5 * Portions of this driver are based on code contributed by Brad Pepers 6 * 7 * revised 28.5.95 by Joerg Dorchain 8 * - now no bugs(?) any more for both HD & DD 9 * - added support for 40 Track 5.25" drives, 80-track hopefully behaves 10 * like 3.5" dd (no way to test - are there any 5.25" drives out there 11 * that work on an A4000?) 12 * - wrote formatting routine (maybe dirty, but works) 13 * 14 * june/july 1995 added ms-dos support by Joerg Dorchain 15 * (portions based on messydos.device and various contributors) 16 * - currently only 9 and 18 sector disks 17 * 18 * - fixed a bug with the internal trackbuffer when using multiple 19 * disks the same time 20 * - made formatting a bit safer 21 * - added command line and machine based default for "silent" df0 22 * 23 * december 1995 adapted for 1.2.13pl4 by Joerg Dorchain 24 * - works but I think it's inefficient. (look in redo_fd_request) 25 * But the changes were very efficient. (only three and a half lines) 26 * 27 * january 1996 added special ioctl for tracking down read/write problems 28 * - usage ioctl(d, RAW_TRACK, ptr); the raw track buffer (MFM-encoded data 29 * is copied to area. (area should be large enough since no checking is 30 * done - 30K is currently sufficient). return the actual size of the 31 * trackbuffer 32 * - replaced udelays() by a timer (CIAA timer B) for the waits 33 * needed for the disk mechanic. 34 * 35 * february 1996 fixed error recovery and multiple disk access 36 * - both got broken the first time I tampered with the driver :-( 37 * - still not safe, but better than before 38 * 39 * revised Marts 3rd, 1996 by Jes Sorensen for use in the 1.3.28 kernel. 40 * - Minor changes to accept the kdev_t. 41 * - Replaced some more udelays with ms_delays. Udelay is just a loop, 42 * and so the delay will be different depending on the given 43 * processor :-( 44 * - The driver could use a major cleanup because of the new 45 * major/minor handling that came with kdev_t. It seems to work for 46 * the time being, but I can't guarantee that it will stay like 47 * that when we start using 16 (24?) bit minors. 48 * 49 * restructured jan 1997 by Joerg Dorchain 50 * - Fixed Bug accessing multiple disks 51 * - some code cleanup 52 * - added trackbuffer for each drive to speed things up 53 * - fixed some race conditions (who finds the next may send it to me ;-) 54 */ 55 56#include <linux/module.h> 57#include <linux/slab.h> 58 59#include <linux/fd.h> 60#include <linux/hdreg.h> 61#include <linux/delay.h> 62#include <linux/init.h> 63#include <linux/amifdreg.h> 64#include <linux/amifd.h> 65#include <linux/buffer_head.h> 66#include <linux/blkdev.h> 67#include <linux/elevator.h> 68#include <linux/interrupt.h> 69 70#include <asm/setup.h> 71#include <asm/uaccess.h> 72#include <asm/amigahw.h> 73#include <asm/amigaints.h> 74#include <asm/irq.h> 75 76#undef DEBUG /* print _LOTS_ of infos */ 77 78#define RAW_IOCTL 79#ifdef RAW_IOCTL 80#define IOCTL_RAW_TRACK 0x5254524B /* 'RTRK' */ 81#endif 82 83/* 84 * Defines 85 */ 86 87/* 88 * Error codes 89 */ 90#define FD_OK 0 /* operation succeeded */ 91#define FD_ERROR -1 /* general error (seek, read, write, etc) */ 92#define FD_NOUNIT 1 /* unit does not exist */ 93#define FD_UNITBUSY 2 /* unit already active */ 94#define FD_NOTACTIVE 3 /* unit is not active */ 95#define FD_NOTREADY 4 /* unit is not ready (motor not on/no disk) */ 96 97#define MFM_NOSYNC 1 98#define MFM_HEADER 2 99#define MFM_DATA 3 100#define MFM_TRACK 4 101 102/* 103 * Floppy ID values 104 */ 105#define FD_NODRIVE 0x00000000 /* response when no unit is present */ 106#define FD_DD_3 0xffffffff /* double-density 3.5" (880K) drive */ 107#define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */ 108#define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */ 109 110static unsigned long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */ 111 112module_param(fd_def_df0, ulong, 0); 113MODULE_LICENSE("GPL"); 114 115static struct request_queue *floppy_queue; 116 117/* 118 * Macros 119 */ 120#define MOTOR_ON (ciab.prb &= ~DSKMOTOR) 121#define MOTOR_OFF (ciab.prb |= DSKMOTOR) 122#define SELECT(mask) (ciab.prb &= ~mask) 123#define DESELECT(mask) (ciab.prb |= mask) 124#define SELMASK(drive) (1 << (3 + (drive & 3))) 125 126static struct fd_drive_type drive_types[] = { 127/* code name tr he rdsz wrsz sm pc1 pc2 sd st st*/ 128/* warning: times are now in milliseconds (ms) */ 129{ FD_DD_3, "DD 3.5", 80, 2, 14716, 13630, 1, 80,161, 3, 18, 1}, 130{ FD_HD_3, "HD 3.5", 80, 2, 28344, 27258, 2, 80,161, 3, 18, 1}, 131{ FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2}, 132{ FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 133}; 134static int num_dr_types = ARRAY_SIZE(drive_types); 135 136static int amiga_read(int), dos_read(int); 137static void amiga_write(int), dos_write(int); 138static struct fd_data_type data_types[] = { 139 { "Amiga", 11 , amiga_read, amiga_write}, 140 { "MS-Dos", 9, dos_read, dos_write} 141}; 142 143/* current info on each unit */ 144static struct amiga_floppy_struct unit[FD_MAX_UNITS]; 145 146static struct timer_list flush_track_timer[FD_MAX_UNITS]; 147static struct timer_list post_write_timer; 148static struct timer_list motor_on_timer; 149static struct timer_list motor_off_timer[FD_MAX_UNITS]; 150static int on_attempts; 151 152/* Synchronization of FDC access */ 153/* request loop (trackbuffer) */ 154static volatile int fdc_busy = -1; 155static volatile int fdc_nested; 156static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); 157 158static DECLARE_COMPLETION(motor_on_completion); 159 160static volatile int selected = -1; /* currently selected drive */ 161 162static int writepending; 163static int writefromint; 164static char *raw_buf; 165 166static DEFINE_SPINLOCK(amiflop_lock); 167 168#define RAW_BUF_SIZE 30000 /* size of raw disk data */ 169 170/* 171 * These are global variables, as that's the easiest way to give 172 * information to interrupts. They are the data used for the current 173 * request. 174 */ 175static volatile char block_flag; 176static DECLARE_WAIT_QUEUE_HEAD(wait_fd_block); 177 178/* MS-Dos MFM Coding tables (should go quick and easy) */ 179static unsigned char mfmencode[16]={ 180 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, 181 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55 182}; 183static unsigned char mfmdecode[128]; 184 185/* floppy internal millisecond timer stuff */ 186static DECLARE_COMPLETION(ms_wait_completion); 187#define MS_TICKS ((amiga_eclock+50)/1000) 188 189/* 190 * Note that MAX_ERRORS=X doesn't imply that we retry every bad read 191 * max X times - some types of errors increase the errorcount by 2 or 192 * even 3, so we might actually retry only X/2 times before giving up. 193 */ 194#define MAX_ERRORS 12 195 196#define custom amiga_custom 197 198/* Prevent "aliased" accesses. */ 199static int fd_ref[4] = { 0,0,0,0 }; 200static int fd_device[4] = { 0, 0, 0, 0 }; 201 202/* 203 * Here come the actual hardware access and helper functions. 204 * They are not reentrant and single threaded because all drives 205 * share the same hardware and the same trackbuffer. 206 */ 207 208/* Milliseconds timer */ 209 210static irqreturn_t ms_isr(int irq, void *dummy) 211{ 212 complete(&ms_wait_completion); 213 return IRQ_HANDLED; 214} 215 216/* all waits are queued up 217 A more generic routine would do a schedule a la timer.device */ 218static void ms_delay(int ms) 219{ 220 int ticks; 221 static DEFINE_MUTEX(mutex); 222 223 if (ms > 0) { 224 mutex_lock(&mutex); 225 ticks = MS_TICKS*ms-1; 226 ciaa.tblo=ticks%256; 227 ciaa.tbhi=ticks/256; 228 ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */ 229 wait_for_completion(&ms_wait_completion); 230 mutex_unlock(&mutex); 231 } 232} 233 234/* Hardware semaphore */ 235 236/* returns true when we would get the semaphore */ 237static inline int try_fdc(int drive) 238{ 239 drive &= 3; 240 return ((fdc_busy < 0) || (fdc_busy == drive)); 241} 242 243static void get_fdc(int drive) 244{ 245 unsigned long flags; 246 247 drive &= 3; 248#ifdef DEBUG 249 printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested); 250#endif 251 local_irq_save(flags); 252 wait_event(fdc_wait, try_fdc(drive)); 253 fdc_busy = drive; 254 fdc_nested++; 255 local_irq_restore(flags); 256} 257 258static inline void rel_fdc(void) 259{ 260#ifdef DEBUG 261 if (fdc_nested == 0) 262 printk("fd: unmatched rel_fdc\n"); 263 printk("rel_fdc: fdc_busy %d fdc_nested %d\n",fdc_busy,fdc_nested); 264#endif 265 fdc_nested--; 266 if (fdc_nested == 0) { 267 fdc_busy = -1; 268 wake_up(&fdc_wait); 269 } 270} 271 272static void fd_select (int drive) 273{ 274 unsigned char prb = ~0; 275 276 drive&=3; 277#ifdef DEBUG 278 printk("selecting %d\n",drive); 279#endif 280 if (drive == selected) 281 return; 282 get_fdc(drive); 283 selected = drive; 284 285 if (unit[drive].track % 2 != 0) 286 prb &= ~DSKSIDE; 287 if (unit[drive].motor == 1) 288 prb &= ~DSKMOTOR; 289 ciab.prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3)); 290 ciab.prb = prb; 291 prb &= ~SELMASK(drive); 292 ciab.prb = prb; 293 rel_fdc(); 294} 295 296static void fd_deselect (int drive) 297{ 298 unsigned char prb; 299 unsigned long flags; 300 301 drive&=3; 302#ifdef DEBUG 303 printk("deselecting %d\n",drive); 304#endif 305 if (drive != selected) { 306 printk(KERN_WARNING "Deselecting drive %d while %d was selected!\n",drive,selected); 307 return; 308 } 309 310 get_fdc(drive); 311 local_irq_save(flags); 312 313 selected = -1; 314 315 prb = ciab.prb; 316 prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3)); 317 ciab.prb = prb; 318 319 local_irq_restore (flags); 320 rel_fdc(); 321 322} 323 324static void motor_on_callback(unsigned long nr) 325{ 326 if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) { 327 complete_all(&motor_on_completion); 328 } else { 329 motor_on_timer.expires = jiffies + HZ/10; 330 add_timer(&motor_on_timer); 331 } 332} 333 334static int fd_motor_on(int nr) 335{ 336 nr &= 3; 337 338 del_timer(motor_off_timer + nr); 339 340 if (!unit[nr].motor) { 341 unit[nr].motor = 1; 342 fd_select(nr); 343 344 INIT_COMPLETION(motor_on_completion); 345 motor_on_timer.data = nr; 346 mod_timer(&motor_on_timer, jiffies + HZ/2); 347 348 on_attempts = 10; 349 wait_for_completion(&motor_on_completion); 350 fd_deselect(nr); 351 } 352 353 if (on_attempts == 0) { 354 on_attempts = -1; 355#if 0 356 printk (KERN_ERR "motor_on failed, turning motor off\n"); 357 fd_motor_off (nr); 358 return 0; 359#else 360 printk (KERN_WARNING "DSKRDY not set after 1.5 seconds - assuming drive is spinning notwithstanding\n"); 361#endif 362 } 363 364 return 1; 365} 366 367static void fd_motor_off(unsigned long drive) 368{ 369 long calledfromint; 370#ifdef MODULE 371 long decusecount; 372 373 decusecount = drive & 0x40000000; 374#endif 375 calledfromint = drive & 0x80000000; 376 drive&=3; 377 if (calledfromint && !try_fdc(drive)) { 378 /* We would be blocked in an interrupt, so try again later */ 379 motor_off_timer[drive].expires = jiffies + 1; 380 add_timer(motor_off_timer + drive); 381 return; 382 } 383 unit[drive].motor = 0; 384 fd_select(drive); 385 udelay (1); 386 fd_deselect(drive); 387} 388 389static void floppy_off (unsigned int nr) 390{ 391 int drive; 392 393 drive = nr & 3; 394 /* called this way it is always from interrupt */ 395 motor_off_timer[drive].data = nr | 0x80000000; 396 mod_timer(motor_off_timer + drive, jiffies + 3*HZ); 397} 398 399static int fd_calibrate(int drive) 400{ 401 unsigned char prb; 402 int n; 403 404 drive &= 3; 405 get_fdc(drive); 406 if (!fd_motor_on (drive)) 407 return 0; 408 fd_select (drive); 409 prb = ciab.prb; 410 prb |= DSKSIDE; 411 prb &= ~DSKDIREC; 412 ciab.prb = prb; 413 for (n = unit[drive].type->tracks/2; n != 0; --n) { 414 if (ciaa.pra & DSKTRACK0) 415 break; 416 prb &= ~DSKSTEP; 417 ciab.prb = prb; 418 prb |= DSKSTEP; 419 udelay (2); 420 ciab.prb = prb; 421 ms_delay(unit[drive].type->step_delay); 422 } 423 ms_delay (unit[drive].type->settle_time); 424 prb |= DSKDIREC; 425 n = unit[drive].type->tracks + 20; 426 for (;;) { 427 prb &= ~DSKSTEP; 428 ciab.prb = prb; 429 prb |= DSKSTEP; 430 udelay (2); 431 ciab.prb = prb; 432 ms_delay(unit[drive].type->step_delay + 1); 433 if ((ciaa.pra & DSKTRACK0) == 0) 434 break; 435 if (--n == 0) { 436 printk (KERN_ERR "fd%d: calibrate failed, turning motor off\n", drive); 437 fd_motor_off (drive); 438 unit[drive].track = -1; 439 rel_fdc(); 440 return 0; 441 } 442 } 443 unit[drive].track = 0; 444 ms_delay(unit[drive].type->settle_time); 445 446 rel_fdc(); 447 fd_deselect(drive); 448 return 1; 449} 450 451static int fd_seek(int drive, int track) 452{ 453 unsigned char prb; 454 int cnt; 455 456#ifdef DEBUG 457 printk("seeking drive %d to track %d\n",drive,track); 458#endif 459 drive &= 3; 460 get_fdc(drive); 461 if (unit[drive].track == track) { 462 rel_fdc(); 463 return 1; 464 } 465 if (!fd_motor_on(drive)) { 466 rel_fdc(); 467 return 0; 468 } 469 if (unit[drive].track < 0 && !fd_calibrate(drive)) { 470 rel_fdc(); 471 return 0; 472 } 473 474 fd_select (drive); 475 cnt = unit[drive].track/2 - track/2; 476 prb = ciab.prb; 477 prb |= DSKSIDE | DSKDIREC; 478 if (track % 2 != 0) 479 prb &= ~DSKSIDE; 480 if (cnt < 0) { 481 cnt = - cnt; 482 prb &= ~DSKDIREC; 483 } 484 ciab.prb = prb; 485 if (track % 2 != unit[drive].track % 2) 486 ms_delay (unit[drive].type->side_time); 487 unit[drive].track = track; 488 if (cnt == 0) { 489 rel_fdc(); 490 fd_deselect(drive); 491 return 1; 492 } 493 do { 494 prb &= ~DSKSTEP; 495 ciab.prb = prb; 496 prb |= DSKSTEP; 497 udelay (1); 498 ciab.prb = prb; 499 ms_delay (unit[drive].type->step_delay); 500 } while (--cnt != 0); 501 ms_delay (unit[drive].type->settle_time); 502 503 rel_fdc(); 504 fd_deselect(drive); 505 return 1; 506} 507 508static unsigned long fd_get_drive_id(int drive) 509{ 510 int i; 511 ulong id = 0; 512 513 drive&=3; 514 get_fdc(drive); 515 /* set up for ID */ 516 MOTOR_ON; 517 udelay(2); 518 SELECT(SELMASK(drive)); 519 udelay(2); 520 DESELECT(SELMASK(drive)); 521 udelay(2); 522 MOTOR_OFF; 523 udelay(2); 524 SELECT(SELMASK(drive)); 525 udelay(2); 526 DESELECT(SELMASK(drive)); 527 udelay(2); 528 529 /* loop and read disk ID */ 530 for (i=0; i<32; i++) { 531 SELECT(SELMASK(drive)); 532 udelay(2); 533 534 /* read and store value of DSKRDY */ 535 id <<= 1; 536 id |= (ciaa.pra & DSKRDY) ? 0 : 1; /* cia regs are low-active! */ 537 538 DESELECT(SELMASK(drive)); 539 } 540 541 rel_fdc(); 542 543 /* 544 * RB: At least A500/A2000's df0: don't identify themselves. 545 * As every (real) Amiga has at least a 3.5" DD drive as df0: 546 * we default to that if df0: doesn't identify as a certain 547 * type. 548 */ 549 if(drive == 0 && id == FD_NODRIVE) 550 { 551 id = fd_def_df0; 552 printk(KERN_NOTICE "fd: drive 0 didn't identify, setting default %08lx\n", (ulong)fd_def_df0); 553 } 554 /* return the ID value */ 555 return (id); 556} 557 558static irqreturn_t fd_block_done(int irq, void *dummy) 559{ 560 if (block_flag) 561 custom.dsklen = 0x4000; 562 563 if (block_flag == 2) { /* writing */ 564 writepending = 2; 565 post_write_timer.expires = jiffies + 1; /* at least 2 ms */ 566 post_write_timer.data = selected; 567 add_timer(&post_write_timer); 568 } 569 else { /* reading */ 570 block_flag = 0; 571 wake_up (&wait_fd_block); 572 } 573 return IRQ_HANDLED; 574} 575 576static void raw_read(int drive) 577{ 578 drive&=3; 579 get_fdc(drive); 580 wait_event(wait_fd_block, !block_flag); 581 fd_select(drive); 582 /* setup adkcon bits correctly */ 583 custom.adkcon = ADK_MSBSYNC; 584 custom.adkcon = ADK_SETCLR|ADK_WORDSYNC|ADK_FAST; 585 586 custom.dsksync = MFM_SYNC; 587 588 custom.dsklen = 0; 589 custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf); 590 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN; 591 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN; 592 593 block_flag = 1; 594 595 wait_event(wait_fd_block, !block_flag); 596 597 custom.dsklen = 0; 598 fd_deselect(drive); 599 rel_fdc(); 600} 601 602static int raw_write(int drive) 603{ 604 ushort adk; 605 606 drive&=3; 607 get_fdc(drive); /* corresponds to rel_fdc() in post_write() */ 608 if ((ciaa.pra & DSKPROT) == 0) { 609 rel_fdc(); 610 return 0; 611 } 612 wait_event(wait_fd_block, !block_flag); 613 fd_select(drive); 614 /* clear adkcon bits */ 615 custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC; 616 /* set appropriate adkcon bits */ 617 adk = ADK_SETCLR|ADK_FAST; 618 if ((ulong)unit[drive].track >= unit[drive].type->precomp2) 619 adk |= ADK_PRECOMP1; 620 else if ((ulong)unit[drive].track >= unit[drive].type->precomp1) 621 adk |= ADK_PRECOMP0; 622 custom.adkcon = adk; 623 624 custom.dsklen = DSKLEN_WRITE; 625 custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf); 626 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE; 627 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE; 628 629 block_flag = 2; 630 return 1; 631} 632 633/* 634 * to be called at least 2ms after the write has finished but before any 635 * other access to the hardware. 636 */ 637static void post_write (unsigned long drive) 638{ 639#ifdef DEBUG 640 printk("post_write for drive %ld\n",drive); 641#endif 642 drive &= 3; 643 custom.dsklen = 0; 644 block_flag = 0; 645 writepending = 0; 646 writefromint = 0; 647 unit[drive].dirty = 0; 648 wake_up(&wait_fd_block); 649 fd_deselect(drive); 650 rel_fdc(); /* corresponds to get_fdc() in raw_write */ 651} 652 653 654/* 655 * The following functions are to convert the block contents into raw data 656 * written to disk and vice versa. 657 * (Add other formats here ;-)) 658 */ 659 660static unsigned long scan_sync(unsigned long raw, unsigned long end) 661{ 662 ushort *ptr = (ushort *)raw, *endp = (ushort *)end; 663 664 while (ptr < endp && *ptr++ != 0x4489) 665 ; 666 if (ptr < endp) { 667 while (*ptr == 0x4489 && ptr < endp) 668 ptr++; 669 return (ulong)ptr; 670 } 671 return 0; 672} 673 674static inline unsigned long checksum(unsigned long *addr, int len) 675{ 676 unsigned long csum = 0; 677 678 len /= sizeof(*addr); 679 while (len-- > 0) 680 csum ^= *addr++; 681 csum = ((csum>>1) & 0x55555555) ^ (csum & 0x55555555); 682 683 return csum; 684} 685 686static unsigned long decode (unsigned long *data, unsigned long *raw, 687 int len) 688{ 689 ulong *odd, *even; 690 691 /* convert length from bytes to longwords */ 692 len >>= 2; 693 odd = raw; 694 even = odd + len; 695 696 /* prepare return pointer */ 697 raw += len * 2; 698 699 do { 700 *data++ = ((*odd++ & 0x55555555) << 1) | (*even++ & 0x55555555); 701 } while (--len != 0); 702 703 return (ulong)raw; 704} 705 706struct header { 707 unsigned char magic; 708 unsigned char track; 709 unsigned char sect; 710 unsigned char ord; 711 unsigned char labels[16]; 712 unsigned long hdrchk; 713 unsigned long datachk; 714}; 715 716static int amiga_read(int drive) 717{ 718 unsigned long raw; 719 unsigned long end; 720 int scnt; 721 unsigned long csum; 722 struct header hdr; 723 724 drive&=3; 725 raw = (long) raw_buf; 726 end = raw + unit[drive].type->read_size; 727 728 for (scnt = 0;scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) { 729 if (!(raw = scan_sync(raw, end))) { 730 printk (KERN_INFO "can't find sync for sector %d\n", scnt); 731 return MFM_NOSYNC; 732 } 733 734 raw = decode ((ulong *)&hdr.magic, (ulong *)raw, 4); 735 raw = decode ((ulong *)&hdr.labels, (ulong *)raw, 16); 736 raw = decode ((ulong *)&hdr.hdrchk, (ulong *)raw, 4); 737 raw = decode ((ulong *)&hdr.datachk, (ulong *)raw, 4); 738 csum = checksum((ulong *)&hdr, 739 (char *)&hdr.hdrchk-(char *)&hdr); 740 741#ifdef DEBUG 742 printk ("(%x,%d,%d,%d) (%lx,%lx,%lx,%lx) %lx %lx\n", 743 hdr.magic, hdr.track, hdr.sect, hdr.ord, 744 *(ulong *)&hdr.labels[0], *(ulong *)&hdr.labels[4], 745 *(ulong *)&hdr.labels[8], *(ulong *)&hdr.labels[12], 746 hdr.hdrchk, hdr.datachk); 747#endif 748 749 if (hdr.hdrchk != csum) { 750 printk(KERN_INFO "MFM_HEADER: %08lx,%08lx\n", hdr.hdrchk, csum); 751 return MFM_HEADER; 752 } 753 754 /* verify track */ 755 if (hdr.track != unit[drive].track) { 756 printk(KERN_INFO "MFM_TRACK: %d, %d\n", hdr.track, unit[drive].track); 757 return MFM_TRACK; 758 } 759 760 raw = decode ((ulong *)(unit[drive].trackbuf + hdr.sect*512), 761 (ulong *)raw, 512); 762 csum = checksum((ulong *)(unit[drive].trackbuf + hdr.sect*512), 512); 763 764 if (hdr.datachk != csum) { 765 printk(KERN_INFO "MFM_DATA: (%x:%d:%d:%d) sc=%d %lx, %lx\n", 766 hdr.magic, hdr.track, hdr.sect, hdr.ord, scnt, 767 hdr.datachk, csum); 768 printk (KERN_INFO "data=(%lx,%lx,%lx,%lx)\n", 769 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[0], 770 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[1], 771 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[2], 772 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[3]); 773 return MFM_DATA; 774 } 775 } 776 777 return 0; 778} 779 780static void encode(unsigned long data, unsigned long *dest) 781{ 782 unsigned long data2; 783 784 data &= 0x55555555; 785 data2 = data ^ 0x55555555; 786 data |= ((data2 >> 1) | 0x80000000) & (data2 << 1); 787 788 if (*(dest - 1) & 0x00000001) 789 data &= 0x7FFFFFFF; 790 791 *dest = data; 792} 793 794static void encode_block(unsigned long *dest, unsigned long *src, int len) 795{ 796 int cnt, to_cnt = 0; 797 unsigned long data; 798 799 /* odd bits */ 800 for (cnt = 0; cnt < len / 4; cnt++) { 801 data = src[cnt] >> 1; 802 encode(data, dest + to_cnt++); 803 } 804 805 /* even bits */ 806 for (cnt = 0; cnt < len / 4; cnt++) { 807 data = src[cnt]; 808 encode(data, dest + to_cnt++); 809 } 810} 811 812static unsigned long *putsec(int disk, unsigned long *raw, int cnt) 813{ 814 struct header hdr; 815 int i; 816 817 disk&=3; 818 *raw = (raw[-1]&1) ? 0x2AAAAAAA : 0xAAAAAAAA; 819 raw++; 820 *raw++ = 0x44894489; 821 822 hdr.magic = 0xFF; 823 hdr.track = unit[disk].track; 824 hdr.sect = cnt; 825 hdr.ord = unit[disk].dtype->sects * unit[disk].type->sect_mult - cnt; 826 for (i = 0; i < 16; i++) 827 hdr.labels[i] = 0; 828 hdr.hdrchk = checksum((ulong *)&hdr, 829 (char *)&hdr.hdrchk-(char *)&hdr); 830 hdr.datachk = checksum((ulong *)(unit[disk].trackbuf+cnt*512), 512); 831 832 encode_block(raw, (ulong *)&hdr.magic, 4); 833 raw += 2; 834 encode_block(raw, (ulong *)&hdr.labels, 16); 835 raw += 8; 836 encode_block(raw, (ulong *)&hdr.hdrchk, 4); 837 raw += 2; 838 encode_block(raw, (ulong *)&hdr.datachk, 4); 839 raw += 2; 840 encode_block(raw, (ulong *)(unit[disk].trackbuf+cnt*512), 512); 841 raw += 256; 842 843 return raw; 844} 845 846static void amiga_write(int disk) 847{ 848 unsigned int cnt; 849 unsigned long *ptr = (unsigned long *)raw_buf; 850 851 disk&=3; 852 /* gap space */ 853 for (cnt = 0; cnt < 415 * unit[disk].type->sect_mult; cnt++) 854 *ptr++ = 0xaaaaaaaa; 855 856 /* sectors */ 857 for (cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++) 858 ptr = putsec (disk, ptr, cnt); 859 *(ushort *)ptr = (ptr[-1]&1) ? 0x2AA8 : 0xAAA8; 860} 861 862 863struct dos_header { 864 unsigned char track, /* 0-80 */ 865 side, /* 0-1 */ 866 sec, /* 0-...*/ 867 len_desc;/* 2 */ 868 unsigned short crc; /* on 68000 we got an alignment problem, 869 but this compiler solves it by adding silently 870 adding a pad byte so data won't fit 871 and this took about 3h to discover.... */ 872 unsigned char gap1[22]; /* for longword-alignedness (0x4e) */ 873}; 874 875/* crc routines are borrowed from the messydos-handler */ 876 877/* excerpt from the messydos-device 878; The CRC is computed not only over the actual data, but including 879; the SYNC mark (3 * $a1) and the 'ID/DATA - Address Mark' ($fe/$fb). 880; As we don't read or encode these fields into our buffers, we have to 881; preload the registers containing the CRC with the values they would have 882; after stepping over these fields. 883; 884; How CRCs "really" work: 885; 886; First, you should regard a bitstring as a series of coefficients of 887; polynomials. We calculate with these polynomials in modulo-2 888; arithmetic, in which both add and subtract are done the same as 889; exclusive-or. Now, we modify our data (a very long polynomial) in 890; such a way that it becomes divisible by the CCITT-standard 16-bit 891; 16 12 5 892; polynomial: x + x + x + 1, represented by $11021. The easiest 893; way to do this would be to multiply (using proper arithmetic) our 894; datablock with $11021. So we have: 895; data * $11021 = 896; data * ($10000 + $1021) = 897; data * $10000 + data * $1021 898; The left part of this is simple: Just add two 0 bytes. But then 899; the right part (data $1021) remains difficult and even could have 900; a carry into the left part. The solution is to use a modified 901; multiplication, which has a result that is not correct, but with 902; a difference of any multiple of $11021. We then only need to keep 903; the 16 least significant bits of the result. 904; 905; The following algorithm does this for us: 906; 907; unsigned char *data, c, crclo, crchi; 908; while (not done) { 909; c = *data++ + crchi; 910; crchi = (@ c) >> 8 + crclo; 911; crclo = @ c; 912; } 913; 914; Remember, + is done with EOR, the @ operator is in two tables (high 915; and low byte separately), which is calculated as 916; 917; $1021 * (c & $F0) 918; xor $1021 * (c & $0F) 919; xor $1021 * (c >> 4) (* is regular multiplication) 920; 921; 922; Anyway, the end result is the same as the remainder of the division of 923; the data by $11021. I am afraid I need to study theory a bit more... 924 925 926my only works was to code this from manx to C.... 927 928*/ 929 930static ushort dos_crc(void * data_a3, int data_d0, int data_d1, int data_d3) 931{ 932 static unsigned char CRCTable1[] = { 933 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1, 934 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62,0x93,0x83,0xb3,0xa3,0xd3,0xc3,0xf3,0xe3, 935 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54,0xa5,0xb5,0x85,0x95,0xe5,0xf5,0xc5,0xd5, 936 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46,0xb7,0xa7,0x97,0x87,0xf7,0xe7,0xd7,0xc7, 937 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38,0xc9,0xd9,0xe9,0xf9,0x89,0x99,0xa9,0xb9, 938 0x5a,0x4a,0x7a,0x6a,0x1a,0x0a,0x3a,0x2a,0xdb,0xcb,0xfb,0xeb,0x9b,0x8b,0xbb,0xab, 939 0x6c,0x7c,0x4c,0x5c,0x2c,0x3c,0x0c,0x1c,0xed,0xfd,0xcd,0xdd,0xad,0xbd,0x8d,0x9d, 940 0x7e,0x6e,0x5e,0x4e,0x3e,0x2e,0x1e,0x0e,0xff,0xef,0xdf,0xcf,0xbf,0xaf,0x9f,0x8f, 941 0x91,0x81,0xb1,0xa1,0xd1,0xc1,0xf1,0xe1,0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60, 942 0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3,0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72, 943 0xb5,0xa5,0x95,0x85,0xf5,0xe5,0xd5,0xc5,0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44, 944 0xa7,0xb7,0x87,0x97,0xe7,0xf7,0xc7,0xd7,0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56, 945 0xd9,0xc9,0xf9,0xe9,0x99,0x89,0xb9,0xa9,0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28, 946 0xcb,0xdb,0xeb,0xfb,0x8b,0x9b,0xab,0xbb,0x4a,0x5a,0x6a,0x7a,0x0a,0x1a,0x2a,0x3a, 947 0xfd,0xed,0xdd,0xcd,0xbd,0xad,0x9d,0x8d,0x7c,0x6c,0x5c,0x4c,0x3c,0x2c,0x1c,0x0c, 948 0xef,0xff,0xcf,0xdf,0xaf,0xbf,0x8f,0x9f,0x6e,0x7e,0x4e,0x5e,0x2e,0x3e,0x0e,0x1e 949 }; 950 951 static unsigned char CRCTable2[] = { 952 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7,0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef, 953 0x31,0x10,0x73,0x52,0xb5,0x94,0xf7,0xd6,0x39,0x18,0x7b,0x5a,0xbd,0x9c,0xff,0xde, 954 0x62,0x43,0x20,0x01,0xe6,0xc7,0xa4,0x85,0x6a,0x4b,0x28,0x09,0xee,0xcf,0xac,0x8d, 955 0x53,0x72,0x11,0x30,0xd7,0xf6,0x95,0xb4,0x5b,0x7a,0x19,0x38,0xdf,0xfe,0x9d,0xbc, 956 0xc4,0xe5,0x86,0xa7,0x40,0x61,0x02,0x23,0xcc,0xed,0x8e,0xaf,0x48,0x69,0x0a,0x2b, 957 0xf5,0xd4,0xb7,0x96,0x71,0x50,0x33,0x12,0xfd,0xdc,0xbf,0x9e,0x79,0x58,0x3b,0x1a, 958 0xa6,0x87,0xe4,0xc5,0x22,0x03,0x60,0x41,0xae,0x8f,0xec,0xcd,0x2a,0x0b,0x68,0x49, 959 0x97,0xb6,0xd5,0xf4,0x13,0x32,0x51,0x70,0x9f,0xbe,0xdd,0xfc,0x1b,0x3a,0x59,0x78, 960 0x88,0xa9,0xca,0xeb,0x0c,0x2d,0x4e,0x6f,0x80,0xa1,0xc2,0xe3,0x04,0x25,0x46,0x67, 961 0xb9,0x98,0xfb,0xda,0x3d,0x1c,0x7f,0x5e,0xb1,0x90,0xf3,0xd2,0x35,0x14,0x77,0x56, 962 0xea,0xcb,0xa8,0x89,0x6e,0x4f,0x2c,0x0d,0xe2,0xc3,0xa0,0x81,0x66,0x47,0x24,0x05, 963 0xdb,0xfa,0x99,0xb8,0x5f,0x7e,0x1d,0x3c,0xd3,0xf2,0x91,0xb0,0x57,0x76,0x15,0x34, 964 0x4c,0x6d,0x0e,0x2f,0xc8,0xe9,0x8a,0xab,0x44,0x65,0x06,0x27,0xc0,0xe1,0x82,0xa3, 965 0x7d,0x5c,0x3f,0x1e,0xf9,0xd8,0xbb,0x9a,0x75,0x54,0x37,0x16,0xf1,0xd0,0xb3,0x92, 966 0x2e,0x0f,0x6c,0x4d,0xaa,0x8b,0xe8,0xc9,0x26,0x07,0x64,0x45,0xa2,0x83,0xe0,0xc1, 967 0x1f,0x3e,0x5d,0x7c,0x9b,0xba,0xd9,0xf8,0x17,0x36,0x55,0x74,0x93,0xb2,0xd1,0xf0 968 }; 969 970/* look at the asm-code - what looks in C a bit strange is almost as good as handmade */ 971 register int i; 972 register unsigned char *CRCT1, *CRCT2, *data, c, crch, crcl; 973 974 CRCT1=CRCTable1; 975 CRCT2=CRCTable2; 976 data=data_a3; 977 crcl=data_d1; 978 crch=data_d0; 979 for (i=data_d3; i>=0; i--) { 980 c = (*data++) ^ crch; 981 crch = CRCT1[c] ^ crcl; 982 crcl = CRCT2[c]; 983 } 984 return (crch<<8)|crcl; 985} 986 987static inline ushort dos_hdr_crc (struct dos_header *hdr) 988{ 989 return dos_crc(&(hdr->track), 0xb2, 0x30, 3); /* precomputed magic */ 990} 991 992static inline ushort dos_data_crc(unsigned char *data) 993{ 994 return dos_crc(data, 0xe2, 0x95 ,511); /* precomputed magic */ 995} 996 997static inline unsigned char dos_decode_byte(ushort word) 998{ 999 register ushort w2; 1000 register unsigned char byte; 1001 register unsigned char *dec = mfmdecode; 1002 1003 w2=word; 1004 w2>>=8; 1005 w2&=127; 1006 byte = dec[w2]; 1007 byte <<= 4; 1008 w2 = word & 127; 1009 byte |= dec[w2]; 1010 return byte; 1011} 1012 1013static unsigned long dos_decode(unsigned char *data, unsigned short *raw, int len) 1014{ 1015 int i; 1016 1017 for (i = 0; i < len; i++) 1018 *data++=dos_decode_byte(*raw++); 1019 return ((ulong)raw); 1020} 1021 1022#ifdef DEBUG 1023static void dbg(unsigned long ptr) 1024{ 1025 printk("raw data @%08lx: %08lx, %08lx ,%08lx, %08lx\n", ptr, 1026 ((ulong *)ptr)[0], ((ulong *)ptr)[1], 1027 ((ulong *)ptr)[2], ((ulong *)ptr)[3]); 1028} 1029#endif 1030 1031static int dos_read(int drive) 1032{ 1033 unsigned long end; 1034 unsigned long raw; 1035 int scnt; 1036 unsigned short crc,data_crc[2]; 1037 struct dos_header hdr; 1038 1039 drive&=3; 1040 raw = (long) raw_buf; 1041 end = raw + unit[drive].type->read_size; 1042 1043 for (scnt=0; scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) { 1044 do { /* search for the right sync of each sec-hdr */ 1045 if (!(raw = scan_sync (raw, end))) { 1046 printk(KERN_INFO "dos_read: no hdr sync on " 1047 "track %d, unit %d for sector %d\n", 1048 unit[drive].track,drive,scnt); 1049 return MFM_NOSYNC; 1050 } 1051#ifdef DEBUG 1052 dbg(raw); 1053#endif 1054 } while (*((ushort *)raw)!=0x5554); /* loop usually only once done */ 1055 raw+=2; /* skip over headermark */ 1056 raw = dos_decode((unsigned char *)&hdr,(ushort *) raw,8); 1057 crc = dos_hdr_crc(&hdr); 1058 1059#ifdef DEBUG 1060 printk("(%3d,%d,%2d,%d) %x\n", hdr.track, hdr.side, 1061 hdr.sec, hdr.len_desc, hdr.crc); 1062#endif 1063 1064 if (crc != hdr.crc) { 1065 printk(KERN_INFO "dos_read: MFM_HEADER %04x,%04x\n", 1066 hdr.crc, crc); 1067 return MFM_HEADER; 1068 } 1069 if (hdr.track != unit[drive].track/unit[drive].type->heads) { 1070 printk(KERN_INFO "dos_read: MFM_TRACK %d, %d\n", 1071 hdr.track, 1072 unit[drive].track/unit[drive].type->heads); 1073 return MFM_TRACK; 1074 } 1075 1076 if (hdr.side != unit[drive].track%unit[drive].type->heads) { 1077 printk(KERN_INFO "dos_read: MFM_SIDE %d, %d\n", 1078 hdr.side, 1079 unit[drive].track%unit[drive].type->heads); 1080 return MFM_TRACK; 1081 } 1082 1083 if (hdr.len_desc != 2) { 1084 printk(KERN_INFO "dos_read: unknown sector len " 1085 "descriptor %d\n", hdr.len_desc); 1086 return MFM_DATA; 1087 } 1088#ifdef DEBUG 1089 printk("hdr accepted\n"); 1090#endif 1091 if (!(raw = scan_sync (raw, end))) { 1092 printk(KERN_INFO "dos_read: no data sync on track " 1093 "%d, unit %d for sector%d, disk sector %d\n", 1094 unit[drive].track, drive, scnt, hdr.sec); 1095 return MFM_NOSYNC; 1096 } 1097#ifdef DEBUG 1098 dbg(raw); 1099#endif 1100 1101 if (*((ushort *)raw)!=0x5545) { 1102 printk(KERN_INFO "dos_read: no data mark after " 1103 "sync (%d,%d,%d,%d) sc=%d\n", 1104 hdr.track,hdr.side,hdr.sec,hdr.len_desc,scnt); 1105 return MFM_NOSYNC; 1106 } 1107 1108 raw+=2; /* skip data mark (included in checksum) */ 1109 raw = dos_decode((unsigned char *)(unit[drive].trackbuf + (hdr.sec - 1) * 512), (ushort *) raw, 512); 1110 raw = dos_decode((unsigned char *)data_crc,(ushort *) raw,4); 1111 crc = dos_data_crc(unit[drive].trackbuf + (hdr.sec - 1) * 512); 1112 1113 if (crc != data_crc[0]) { 1114 printk(KERN_INFO "dos_read: MFM_DATA (%d,%d,%d,%d) " 1115 "sc=%d, %x %x\n", hdr.track, hdr.side, 1116 hdr.sec, hdr.len_desc, scnt,data_crc[0], crc); 1117 printk(KERN_INFO "data=(%lx,%lx,%lx,%lx,...)\n", 1118 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[0], 1119 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[1], 1120 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[2], 1121 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[3]); 1122 return MFM_DATA; 1123 } 1124 } 1125 return 0; 1126} 1127 1128static inline ushort dos_encode_byte(unsigned char byte) 1129{ 1130 register unsigned char *enc, b2, b1; 1131 register ushort word; 1132 1133 enc=mfmencode; 1134 b1=byte; 1135 b2=b1>>4; 1136 b1&=15; 1137 word=enc[b2] <<8 | enc [b1]; 1138 return (word|((word&(256|64)) ? 0: 128)); 1139} 1140 1141static void dos_encode_block(ushort *dest, unsigned char *src, int len) 1142{ 1143 int i; 1144 1145 for (i = 0; i < len; i++) { 1146 *dest=dos_encode_byte(*src++); 1147 *dest|=((dest[-1]&1)||(*dest&0x4000))? 0: 0x8000; 1148 dest++; 1149 } 1150} 1151 1152static unsigned long *ms_putsec(int drive, unsigned long *raw, int cnt) 1153{ 1154 static struct dos_header hdr={0,0,0,2,0, 1155 {78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78}}; 1156 int i; 1157 static ushort crc[2]={0,0x4e4e}; 1158 1159 drive&=3; 1160/* id gap 1 */ 1161/* the MFM word before is always 9254 */ 1162 for(i=0;i<6;i++) 1163 *raw++=0xaaaaaaaa; 1164/* 3 sync + 1 headermark */ 1165 *raw++=0x44894489; 1166 *raw++=0x44895554; 1167 1168/* fill in the variable parts of the header */ 1169 hdr.track=unit[drive].track/unit[drive].type->heads; 1170 hdr.side=unit[drive].track%unit[drive].type->heads; 1171 hdr.sec=cnt+1; 1172 hdr.crc=dos_hdr_crc(&hdr); 1173 1174/* header (without "magic") and id gap 2*/ 1175 dos_encode_block((ushort *)raw,(unsigned char *) &hdr.track,28); 1176 raw+=14; 1177 1178/*id gap 3 */ 1179 for(i=0;i<6;i++) 1180 *raw++=0xaaaaaaaa; 1181 1182/* 3 syncs and 1 datamark */ 1183 *raw++=0x44894489; 1184 *raw++=0x44895545; 1185 1186/* data */ 1187 dos_encode_block((ushort *)raw, 1188 (unsigned char *)unit[drive].trackbuf+cnt*512,512); 1189 raw+=256; 1190 1191/*data crc + jd's special gap (long words :-/) */ 1192 crc[0]=dos_data_crc(unit[drive].trackbuf+cnt*512); 1193 dos_encode_block((ushort *) raw,(unsigned char *)crc,4); 1194 raw+=2; 1195 1196/* data gap */ 1197 for(i=0;i<38;i++) 1198 *raw++=0x92549254; 1199 1200 return raw; /* wrote 652 MFM words */ 1201} 1202 1203static void dos_write(int disk) 1204{ 1205 int cnt; 1206 unsigned long raw = (unsigned long) raw_buf; 1207 unsigned long *ptr=(unsigned long *)raw; 1208 1209 disk&=3; 1210/* really gap4 + indexgap , but we write it first and round it up */ 1211 for (cnt=0;cnt<425;cnt++) 1212 *ptr++=0x92549254; 1213 1214/* the following is just guessed */ 1215 if (unit[disk].type->sect_mult==2) /* check for HD-Disks */ 1216 for(cnt=0;cnt<473;cnt++) 1217 *ptr++=0x92549254; 1218 1219/* now the index marks...*/ 1220 for (cnt=0;cnt<20;cnt++) 1221 *ptr++=0x92549254; 1222 for (cnt=0;cnt<6;cnt++) 1223 *ptr++=0xaaaaaaaa; 1224 *ptr++=0x52245224; 1225 *ptr++=0x52245552; 1226 for (cnt=0;cnt<20;cnt++) 1227 *ptr++=0x92549254; 1228 1229/* sectors */ 1230 for(cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++) 1231 ptr=ms_putsec(disk,ptr,cnt); 1232 1233 *(ushort *)ptr = 0xaaa8; /* MFM word before is always 0x9254 */ 1234} 1235 1236/* 1237 * Here comes the high level stuff (i.e. the filesystem interface) 1238 * and helper functions. 1239 * Normally this should be the only part that has to be adapted to 1240 * different kernel versions. 1241 */ 1242 1243/* FIXME: this assumes the drive is still spinning - 1244 * which is only true if we complete writing a track within three seconds 1245 */ 1246static void flush_track_callback(unsigned long nr) 1247{ 1248 nr&=3; 1249 writefromint = 1; 1250 if (!try_fdc(nr)) { 1251 /* we might block in an interrupt, so try again later */ 1252 flush_track_timer[nr].expires = jiffies + 1; 1253 add_timer(flush_track_timer + nr); 1254 return; 1255 } 1256 get_fdc(nr); 1257 (*unit[nr].dtype->write_fkt)(nr); 1258 if (!raw_write(nr)) { 1259 printk (KERN_NOTICE "floppy disk write protected\n"); 1260 writefromint = 0; 1261 writepending = 0; 1262 } 1263 rel_fdc(); 1264} 1265 1266static int non_int_flush_track (unsigned long nr) 1267{ 1268 unsigned long flags; 1269 1270 nr&=3; 1271 writefromint = 0; 1272 del_timer(&post_write_timer); 1273 get_fdc(nr); 1274 if (!fd_motor_on(nr)) { 1275 writepending = 0; 1276 rel_fdc(); 1277 return 0; 1278 } 1279 local_irq_save(flags); 1280 if (writepending != 2) { 1281 local_irq_restore(flags); 1282 (*unit[nr].dtype->write_fkt)(nr); 1283 if (!raw_write(nr)) { 1284 printk (KERN_NOTICE "floppy disk write protected " 1285 "in write!\n"); 1286 writepending = 0; 1287 return 0; 1288 } 1289 wait_event(wait_fd_block, block_flag != 2); 1290 } 1291 else { 1292 local_irq_restore(flags); 1293 ms_delay(2); /* 2 ms post_write delay */ 1294 post_write(nr); 1295 } 1296 rel_fdc(); 1297 return 1; 1298} 1299 1300static int get_track(int drive, int track) 1301{ 1302 int error, errcnt; 1303 1304 drive&=3; 1305 if (unit[drive].track == track) 1306 return 0; 1307 get_fdc(drive); 1308 if (!fd_motor_on(drive)) { 1309 rel_fdc(); 1310 return -1; 1311 } 1312 1313 if (unit[drive].dirty == 1) { 1314 del_timer (flush_track_timer + drive); 1315 non_int_flush_track (drive); 1316 } 1317 errcnt = 0; 1318 while (errcnt < MAX_ERRORS) { 1319 if (!fd_seek(drive, track)) 1320 return -1; 1321 raw_read(drive); 1322 error = (*unit[drive].dtype->read_fkt)(drive); 1323 if (error == 0) { 1324 rel_fdc(); 1325 return 0; 1326 } 1327 /* Read Error Handling: recalibrate and try again */ 1328 unit[drive].track = -1; 1329 errcnt++; 1330 } 1331 rel_fdc(); 1332 return -1; 1333} 1334 1335static void redo_fd_request(void) 1336{ 1337 struct request *rq; 1338 unsigned int cnt, block, track, sector; 1339 int drive; 1340 struct amiga_floppy_struct *floppy; 1341 char *data; 1342 unsigned long flags; 1343 int err; 1344 1345next_req: 1346 rq = blk_fetch_request(floppy_queue); 1347 if (!rq) { 1348 /* Nothing left to do */ 1349 return; 1350 } 1351 1352 floppy = rq->rq_disk->private_data; 1353 drive = floppy - unit; 1354 1355next_segment: 1356 /* Here someone could investigate to be more efficient */ 1357 for (cnt = 0, err = 0; cnt < blk_rq_cur_sectors(rq); cnt++) { 1358#ifdef DEBUG 1359 printk("fd: sector %ld + %d requested for %s\n", 1360 blk_rq_pos(rq), cnt, 1361 (rq_data_dir(rq) == READ) ? "read" : "write"); 1362#endif 1363 block = blk_rq_pos(rq) + cnt; 1364 if ((int)block > floppy->blocks) { 1365 err = -EIO; 1366 break; 1367 } 1368 1369 track = block / (floppy->dtype->sects * floppy->type->sect_mult); 1370 sector = block % (floppy->dtype->sects * floppy->type->sect_mult); 1371 data = rq->buffer + 512 * cnt; 1372#ifdef DEBUG 1373 printk("access to track %d, sector %d, with buffer at " 1374 "0x%08lx\n", track, sector, data); 1375#endif 1376 1377 if (get_track(drive, track) == -1) { 1378 err = -EIO; 1379 break; 1380 } 1381 1382 if (rq_data_dir(rq) == READ) { 1383 memcpy(data, floppy->trackbuf + sector * 512, 512); 1384 } else { 1385 memcpy(floppy->trackbuf + sector * 512, data, 512); 1386 1387 /* keep the drive spinning while writes are scheduled */ 1388 if (!fd_motor_on(drive)) { 1389 err = -EIO; 1390 break; 1391 } 1392 /* 1393 * setup a callback to write the track buffer 1394 * after a short (1 tick) delay. 1395 */ 1396 local_irq_save(flags); 1397 1398 floppy->dirty = 1; 1399 /* reset the timer */ 1400 mod_timer (flush_track_timer + drive, jiffies + 1); 1401 local_irq_restore(flags); 1402 } 1403 } 1404 1405 if (__blk_end_request_cur(rq, err)) 1406 goto next_segment; 1407 goto next_req; 1408} 1409 1410static void do_fd_request(struct request_queue * q) 1411{ 1412 redo_fd_request(); 1413} 1414 1415static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) 1416{ 1417 int drive = MINOR(bdev->bd_dev) & 3; 1418 1419 geo->heads = unit[drive].type->heads; 1420 geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; 1421 geo->cylinders = unit[drive].type->tracks; 1422 return 0; 1423} 1424 1425static int fd_ioctl(struct block_device *bdev, fmode_t mode, 1426 unsigned int cmd, unsigned long param) 1427{ 1428 struct amiga_floppy_struct *p = bdev->bd_disk->private_data; 1429 int drive = p - unit; 1430 static struct floppy_struct getprm; 1431 void __user *argp = (void __user *)param; 1432 1433 switch(cmd){ 1434 case FDFMTBEG: 1435 get_fdc(drive); 1436 if (fd_ref[drive] > 1) { 1437 rel_fdc(); 1438 return -EBUSY; 1439 } 1440 fsync_bdev(bdev); 1441 if (fd_motor_on(drive) == 0) { 1442 rel_fdc(); 1443 return -ENODEV; 1444 } 1445 if (fd_calibrate(drive) == 0) { 1446 rel_fdc(); 1447 return -ENXIO; 1448 } 1449 floppy_off(drive); 1450 rel_fdc(); 1451 break; 1452 case FDFMTTRK: 1453 if (param < p->type->tracks * p->type->heads) 1454 { 1455 get_fdc(drive); 1456 if (fd_seek(drive,param) != 0){ 1457 memset(p->trackbuf, FD_FILL_BYTE, 1458 p->dtype->sects * p->type->sect_mult * 512); 1459 non_int_flush_track(drive); 1460 } 1461 floppy_off(drive); 1462 rel_fdc(); 1463 } 1464 else 1465 return -EINVAL; 1466 break; 1467 case FDFMTEND: 1468 floppy_off(drive); 1469 invalidate_bdev(bdev); 1470 break; 1471 case FDGETPRM: 1472 memset((void *)&getprm, 0, sizeof (getprm)); 1473 getprm.track=p->type->tracks; 1474 getprm.head=p->type->heads; 1475 getprm.sect=p->dtype->sects * p->type->sect_mult; 1476 getprm.size=p->blocks; 1477 if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct))) 1478 return -EFAULT; 1479 break; 1480 case FDSETPRM: 1481 case FDDEFPRM: 1482 return -EINVAL; 1483 case FDFLUSH: /* unconditionally, even if not needed */ 1484 del_timer (flush_track_timer + drive); 1485 non_int_flush_track(drive); 1486 break; 1487#ifdef RAW_IOCTL 1488 case IOCTL_RAW_TRACK: 1489 if (copy_to_user(argp, raw_buf, p->type->read_size)) 1490 return -EFAULT; 1491 else 1492 return p->type->read_size; 1493#endif 1494 default: 1495 printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.", 1496 cmd, drive); 1497 return -ENOSYS; 1498 } 1499 return 0; 1500} 1501 1502static void fd_probe(int dev) 1503{ 1504 unsigned long code; 1505 int type; 1506 int drive; 1507 1508 drive = dev & 3; 1509 code = fd_get_drive_id(drive); 1510 1511 /* get drive type */ 1512 for (type = 0; type < num_dr_types; type++) 1513 if (drive_types[type].code == code) 1514 break; 1515 1516 if (type >= num_dr_types) { 1517 printk(KERN_WARNING "fd_probe: unsupported drive type " 1518 "%08lx found\n", code); 1519 unit[drive].type = &drive_types[num_dr_types-1]; /* FD_NODRIVE */ 1520 return; 1521 } 1522 1523 unit[drive].type = drive_types + type; 1524 unit[drive].track = -1; 1525 1526 unit[drive].disk = -1; 1527 unit[drive].motor = 0; 1528 unit[drive].busy = 0; 1529 unit[drive].status = -1; 1530} 1531 1532/* 1533 * floppy_open check for aliasing (/dev/fd0 can be the same as 1534 * /dev/PS0 etc), and disallows simultaneous access to the same 1535 * drive with different device numbers. 1536 */ 1537static int floppy_open(struct block_device *bdev, fmode_t mode) 1538{ 1539 int drive = MINOR(bdev->bd_dev) & 3; 1540 int system = (MINOR(bdev->bd_dev) & 4) >> 2; 1541 int old_dev; 1542 unsigned long flags; 1543 1544 old_dev = fd_device[drive]; 1545 1546 if (fd_ref[drive] && old_dev != system) 1547 return -EBUSY; 1548 1549 if (mode & (FMODE_READ|FMODE_WRITE)) { 1550 check_disk_change(bdev); 1551 if (mode & FMODE_WRITE) { 1552 int wrprot; 1553 1554 get_fdc(drive); 1555 fd_select (drive); 1556 wrprot = !(ciaa.pra & DSKPROT); 1557 fd_deselect (drive); 1558 rel_fdc(); 1559 1560 if (wrprot) 1561 return -EROFS; 1562 } 1563 } 1564 1565 local_irq_save(flags); 1566 fd_ref[drive]++; 1567 fd_device[drive] = system; 1568 local_irq_restore(flags); 1569 1570 unit[drive].dtype=&data_types[system]; 1571 unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* 1572 data_types[system].sects*unit[drive].type->sect_mult; 1573 set_capacity(unit[drive].gendisk, unit[drive].blocks); 1574 1575 printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, 1576 unit[drive].type->name, data_types[system].name); 1577 1578 return 0; 1579} 1580 1581static int floppy_release(struct gendisk *disk, fmode_t mode) 1582{ 1583 struct amiga_floppy_struct *p = disk->private_data; 1584 int drive = p - unit; 1585 1586 if (unit[drive].dirty == 1) { 1587 del_timer (flush_track_timer + drive); 1588 non_int_flush_track (drive); 1589 } 1590 1591 if (!fd_ref[drive]--) { 1592 printk(KERN_CRIT "floppy_release with fd_ref == 0"); 1593 fd_ref[drive] = 0; 1594 } 1595#ifdef MODULE 1596/* the mod_use counter is handled this way */ 1597 floppy_off (drive | 0x40000000); 1598#endif 1599 return 0; 1600} 1601 1602/* 1603 * floppy-change is never called from an interrupt, so we can relax a bit 1604 * here, sleep etc. Note that floppy-on tries to set current_DOR to point 1605 * to the desired drive, but it will probably not survive the sleep if 1606 * several floppies are used at the same time: thus the loop. 1607 */ 1608static int amiga_floppy_change(struct gendisk *disk) 1609{ 1610 struct amiga_floppy_struct *p = disk->private_data; 1611 int drive = p - unit; 1612 int changed; 1613 static int first_time = 1; 1614 1615 if (first_time) 1616 changed = first_time--; 1617 else { 1618 get_fdc(drive); 1619 fd_select (drive); 1620 changed = !(ciaa.pra & DSKCHANGE); 1621 fd_deselect (drive); 1622 rel_fdc(); 1623 } 1624 1625 if (changed) { 1626 fd_probe(drive); 1627 p->track = -1; 1628 p->dirty = 0; 1629 writepending = 0; /* if this was true before, too bad! */ 1630 writefromint = 0; 1631 return 1; 1632 } 1633 return 0; 1634} 1635 1636static const struct block_device_operations floppy_fops = { 1637 .owner = THIS_MODULE, 1638 .open = floppy_open, 1639 .release = floppy_release, 1640 .locked_ioctl = fd_ioctl, 1641 .getgeo = fd_getgeo, 1642 .media_changed = amiga_floppy_change, 1643}; 1644 1645static int __init fd_probe_drives(void) 1646{ 1647 int drive,drives,nomem; 1648 1649 printk(KERN_INFO "FD: probing units\nfound "); 1650 drives=0; 1651 nomem=0; 1652 for(drive=0;drive<FD_MAX_UNITS;drive++) { 1653 struct gendisk *disk; 1654 fd_probe(drive); 1655 if (unit[drive].type->code == FD_NODRIVE) 1656 continue; 1657 disk = alloc_disk(1); 1658 if (!disk) { 1659 unit[drive].type->code = FD_NODRIVE; 1660 continue; 1661 } 1662 unit[drive].gendisk = disk; 1663 drives++; 1664 if ((unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL)) == NULL) { 1665 printk("no mem for "); 1666 unit[drive].type = &drive_types[num_dr_types - 1]; /* FD_NODRIVE */ 1667 drives--; 1668 nomem = 1; 1669 } 1670 printk("fd%d ",drive); 1671 disk->major = FLOPPY_MAJOR; 1672 disk->first_minor = drive; 1673 disk->fops = &floppy_fops; 1674 sprintf(disk->disk_name, "fd%d", drive); 1675 disk->private_data = &unit[drive]; 1676 disk->queue = floppy_queue; 1677 set_capacity(disk, 880*2); 1678 add_disk(disk); 1679 } 1680 if ((drives > 0) || (nomem == 0)) { 1681 if (drives == 0) 1682 printk("no drives"); 1683 printk("\n"); 1684 return drives; 1685 } 1686 printk("\n"); 1687 return -ENOMEM; 1688} 1689 1690static struct kobject *floppy_find(dev_t dev, int *part, void *data) 1691{ 1692 int drive = *part & 3; 1693 if (unit[drive].type->code == FD_NODRIVE) 1694 return NULL; 1695 *part = 0; 1696 return get_disk(unit[drive].gendisk); 1697} 1698 1699static int __init amiga_floppy_init(void) 1700{ 1701 int i, ret; 1702 1703 if (!MACH_IS_AMIGA) 1704 return -ENODEV; 1705 1706 if (!AMIGAHW_PRESENT(AMI_FLOPPY)) 1707 return -ENODEV; 1708 1709 if (register_blkdev(FLOPPY_MAJOR,"fd")) 1710 return -EBUSY; 1711 1712 /* 1713 * We request DSKPTR, DSKLEN and DSKDATA only, because the other 1714 * floppy registers are too spreaded over the custom register space 1715 */ 1716 ret = -EBUSY; 1717 if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { 1718 printk("fd: cannot get floppy registers\n"); 1719 goto out_blkdev; 1720 } 1721 1722 ret = -ENOMEM; 1723 if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == 1724 NULL) { 1725 printk("fd: cannot get chip mem buffer\n"); 1726 goto out_memregion; 1727 } 1728 1729 ret = -EBUSY; 1730 if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) { 1731 printk("fd: cannot get irq for dma\n"); 1732 goto out_irq; 1733 } 1734 1735 if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) { 1736 printk("fd: cannot get irq for timer\n"); 1737 goto out_irq2; 1738 } 1739 1740 ret = -ENOMEM; 1741 floppy_queue = blk_init_queue(do_fd_request, &amiflop_lock); 1742 if (!floppy_queue) 1743 goto out_queue; 1744 1745 ret = -ENODEV; 1746 if (fd_probe_drives() < 1) /* No usable drives */ 1747 goto out_probe; 1748 1749 blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, 1750 floppy_find, NULL, NULL); 1751 1752 /* initialize variables */ 1753 init_timer(&motor_on_timer); 1754 motor_on_timer.expires = 0; 1755 motor_on_timer.data = 0; 1756 motor_on_timer.function = motor_on_callback; 1757 for (i = 0; i < FD_MAX_UNITS; i++) { 1758 init_timer(&motor_off_timer[i]); 1759 motor_off_timer[i].expires = 0; 1760 motor_off_timer[i].data = i|0x80000000; 1761 motor_off_timer[i].function = fd_motor_off; 1762 init_timer(&flush_track_timer[i]); 1763 flush_track_timer[i].expires = 0; 1764 flush_track_timer[i].data = i; 1765 flush_track_timer[i].function = flush_track_callback; 1766 1767 unit[i].track = -1; 1768 } 1769 1770 init_timer(&post_write_timer); 1771 post_write_timer.expires = 0; 1772 post_write_timer.data = 0; 1773 post_write_timer.function = post_write; 1774 1775 for (i = 0; i < 128; i++) 1776 mfmdecode[i]=255; 1777 for (i = 0; i < 16; i++) 1778 mfmdecode[mfmencode[i]]=i; 1779 1780 /* make sure that disk DMA is enabled */ 1781 custom.dmacon = DMAF_SETCLR | DMAF_DISK; 1782 1783 /* init ms timer */ 1784 ciaa.crb = 8; /* one-shot, stop */ 1785 return 0; 1786 1787out_probe: 1788 blk_cleanup_queue(floppy_queue); 1789out_queue: 1790 free_irq(IRQ_AMIGA_CIAA_TB, NULL); 1791out_irq2: 1792 free_irq(IRQ_AMIGA_DSKBLK, NULL); 1793out_irq: 1794 amiga_chip_free(raw_buf); 1795out_memregion: 1796 release_mem_region(CUSTOM_PHYSADDR+0x20, 8); 1797out_blkdev: 1798 unregister_blkdev(FLOPPY_MAJOR,"fd"); 1799 return ret; 1800} 1801 1802module_init(amiga_floppy_init); 1803#ifdef MODULE 1804 1805#if 0 /* not safe to unload */ 1806void cleanup_module(void) 1807{ 1808 int i; 1809 1810 for( i = 0; i < FD_MAX_UNITS; i++) { 1811 if (unit[i].type->code != FD_NODRIVE) { 1812 del_gendisk(unit[i].gendisk); 1813 put_disk(unit[i].gendisk); 1814 kfree(unit[i].trackbuf); 1815 } 1816 } 1817 blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); 1818 free_irq(IRQ_AMIGA_CIAA_TB, NULL); 1819 free_irq(IRQ_AMIGA_DSKBLK, NULL); 1820 custom.dmacon = DMAF_DISK; /* disable DMA */ 1821 amiga_chip_free(raw_buf); 1822 blk_cleanup_queue(floppy_queue); 1823 release_mem_region(CUSTOM_PHYSADDR+0x20, 8); 1824 unregister_blkdev(FLOPPY_MAJOR, "fd"); 1825} 1826#endif 1827 1828#else 1829static int __init amiga_floppy_setup (char *str) 1830{ 1831 int n; 1832 if (!MACH_IS_AMIGA) 1833 return 0; 1834 if (!get_option(&str, &n)) 1835 return 0; 1836 printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n); 1837 fd_def_df0 = n; 1838 return 1; 1839} 1840 1841__setup("floppy=", amiga_floppy_setup); 1842#endif