0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 #include <linux/module.h>
0058 #include <linux/slab.h>
0059
0060 #include <linux/fd.h>
0061 #include <linux/hdreg.h>
0062 #include <linux/delay.h>
0063 #include <linux/init.h>
0064 #include <linux/major.h>
0065 #include <linux/mutex.h>
0066 #include <linux/fs.h>
0067 #include <linux/blk-mq.h>
0068 #include <linux/interrupt.h>
0069 #include <linux/platform_device.h>
0070
0071 #include <asm/setup.h>
0072 #include <linux/uaccess.h>
0073 #include <asm/amigahw.h>
0074 #include <asm/amigaints.h>
0075 #include <asm/irq.h>
0076
0077 #undef DEBUG
0078
0079 #define RAW_IOCTL
0080 #ifdef RAW_IOCTL
0081 #define IOCTL_RAW_TRACK 0x5254524B
0082 #endif
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 #define DSKRDY (0x1<<5)
0093 #define DSKTRACK0 (0x1<<4)
0094 #define DSKPROT (0x1<<3)
0095 #define DSKCHANGE (0x1<<2)
0096
0097
0098
0099
0100
0101 #define DSKMOTOR (0x1<<7)
0102 #define DSKSEL3 (0x1<<6)
0103 #define DSKSEL2 (0x1<<5)
0104 #define DSKSEL1 (0x1<<4)
0105 #define DSKSEL0 (0x1<<3)
0106 #define DSKSIDE (0x1<<2)
0107 #define DSKDIREC (0x1<<1)
0108 #define DSKSTEP (0x1)
0109
0110
0111
0112
0113
0114 #define DSKBYT (1<<15)
0115 #define DMAON (1<<14)
0116 #define DISKWRITE (1<<13)
0117 #define WORDEQUAL (1<<12)
0118
0119
0120
0121
0122
0123
0124 #ifndef SETCLR
0125 #define ADK_SETCLR (1<<15)
0126 #endif
0127 #define ADK_PRECOMP1 (1<<14)
0128 #define ADK_PRECOMP0 (1<<13)
0129 #define ADK_MFMPREC (1<<12)
0130 #define ADK_WORDSYNC (1<<10)
0131 #define ADK_MSBSYNC (1<<9)
0132 #define ADK_FAST (1<<8)
0133
0134
0135
0136
0137
0138 #define DSKLEN_DMAEN (1<<15)
0139 #define DSKLEN_WRITE (1<<14)
0140
0141
0142
0143
0144
0145 #define DSKINDEX (0x1<<4)
0146
0147
0148
0149
0150
0151 #define MFM_SYNC 0x4489
0152
0153
0154 #define FD_RECALIBRATE 0x07
0155 #define FD_SEEK 0x0F
0156 #define FD_READ 0xE6
0157 #define FD_WRITE 0xC5
0158 #define FD_SENSEI 0x08
0159 #define FD_SPECIFY 0x03
0160 #define FD_FORMAT 0x4D
0161 #define FD_VERSION 0x10
0162 #define FD_CONFIGURE 0x13
0163 #define FD_PERPENDICULAR 0x12
0164
0165 #define FD_MAX_UNITS 4
0166 #define FLOPPY_MAX_SECTORS 22
0167
0168 struct fd_data_type {
0169 char *name;
0170 int sects;
0171 int (*read_fkt)(int);
0172 void (*write_fkt)(int);
0173 };
0174
0175 struct fd_drive_type {
0176 unsigned long code;
0177 char *name;
0178 unsigned int tracks;
0179 unsigned int heads;
0180 unsigned int read_size;
0181 unsigned int write_size;
0182 unsigned int sect_mult;
0183 unsigned int precomp1;
0184 unsigned int precomp2;
0185 unsigned int step_delay;
0186 unsigned int settle_time;
0187 unsigned int side_time;
0188 };
0189
0190 struct amiga_floppy_struct {
0191 struct fd_drive_type *type;
0192 struct fd_data_type *dtype;
0193 int track;
0194 unsigned char *trackbuf;
0195
0196 int blocks;
0197
0198 int changed;
0199 int disk;
0200 int motor;
0201 int busy;
0202 int dirty;
0203 int status;
0204 struct gendisk *gendisk[2];
0205 struct blk_mq_tag_set tag_set;
0206 };
0207
0208
0209
0210
0211 #define FD_OK 0
0212 #define FD_ERROR -1
0213 #define FD_NOUNIT 1
0214 #define FD_UNITBUSY 2
0215 #define FD_NOTACTIVE 3
0216 #define FD_NOTREADY 4
0217
0218 #define MFM_NOSYNC 1
0219 #define MFM_HEADER 2
0220 #define MFM_DATA 3
0221 #define MFM_TRACK 4
0222
0223
0224
0225
0226 #define FD_NODRIVE 0x00000000
0227 #define FD_DD_3 0xffffffff
0228 #define FD_HD_3 0x55555555
0229 #define FD_DD_5 0xaaaaaaaa
0230
0231 static DEFINE_MUTEX(amiflop_mutex);
0232 static unsigned long int fd_def_df0 = FD_DD_3;
0233
0234 module_param(fd_def_df0, ulong, 0);
0235 MODULE_LICENSE("GPL");
0236
0237
0238
0239
0240 #define MOTOR_ON (ciab.prb &= ~DSKMOTOR)
0241 #define MOTOR_OFF (ciab.prb |= DSKMOTOR)
0242 #define SELECT(mask) (ciab.prb &= ~mask)
0243 #define DESELECT(mask) (ciab.prb |= mask)
0244 #define SELMASK(drive) (1 << (3 + (drive & 3)))
0245
0246 static struct fd_drive_type drive_types[] = {
0247
0248
0249 { FD_DD_3, "DD 3.5", 80, 2, 14716, 13630, 1, 80,161, 3, 18, 1},
0250 { FD_HD_3, "HD 3.5", 80, 2, 28344, 27258, 2, 80,161, 3, 18, 1},
0251 { FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2},
0252 { FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
0253 };
0254 static int num_dr_types = ARRAY_SIZE(drive_types);
0255
0256 static int amiga_read(int), dos_read(int);
0257 static void amiga_write(int), dos_write(int);
0258 static struct fd_data_type data_types[] = {
0259 { "Amiga", 11 , amiga_read, amiga_write},
0260 { "MS-Dos", 9, dos_read, dos_write}
0261 };
0262
0263
0264 static struct amiga_floppy_struct unit[FD_MAX_UNITS];
0265
0266 static struct timer_list flush_track_timer[FD_MAX_UNITS];
0267 static struct timer_list post_write_timer;
0268 static unsigned long post_write_timer_drive;
0269 static struct timer_list motor_on_timer;
0270 static struct timer_list motor_off_timer[FD_MAX_UNITS];
0271 static int on_attempts;
0272
0273
0274
0275 static volatile int fdc_busy = -1;
0276 static volatile int fdc_nested;
0277 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
0278
0279 static DECLARE_COMPLETION(motor_on_completion);
0280
0281 static volatile int selected = -1;
0282
0283 static int writepending;
0284 static int writefromint;
0285 static char *raw_buf;
0286
0287 static DEFINE_SPINLOCK(amiflop_lock);
0288
0289 #define RAW_BUF_SIZE 30000
0290
0291
0292
0293
0294
0295
0296 static volatile char block_flag;
0297 static DECLARE_WAIT_QUEUE_HEAD(wait_fd_block);
0298
0299
0300 static unsigned char mfmencode[16]={
0301 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15,
0302 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55
0303 };
0304 static unsigned char mfmdecode[128];
0305
0306
0307 static DECLARE_COMPLETION(ms_wait_completion);
0308 #define MS_TICKS ((amiga_eclock+50)/1000)
0309
0310
0311
0312
0313
0314
0315 #define MAX_ERRORS 12
0316
0317 #define custom amiga_custom
0318
0319
0320 static int fd_ref[4] = { 0,0,0,0 };
0321 static int fd_device[4] = { 0, 0, 0, 0 };
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 static irqreturn_t ms_isr(int irq, void *dummy)
0332 {
0333 complete(&ms_wait_completion);
0334 return IRQ_HANDLED;
0335 }
0336
0337
0338
0339 static void ms_delay(int ms)
0340 {
0341 int ticks;
0342 static DEFINE_MUTEX(mutex);
0343
0344 if (ms > 0) {
0345 mutex_lock(&mutex);
0346 ticks = MS_TICKS*ms-1;
0347 ciaa.tblo=ticks%256;
0348 ciaa.tbhi=ticks/256;
0349 ciaa.crb=0x19;
0350 wait_for_completion(&ms_wait_completion);
0351 mutex_unlock(&mutex);
0352 }
0353 }
0354
0355
0356
0357
0358 static inline int try_fdc(int drive)
0359 {
0360 drive &= 3;
0361 return ((fdc_busy < 0) || (fdc_busy == drive));
0362 }
0363
0364 static void get_fdc(int drive)
0365 {
0366 unsigned long flags;
0367
0368 drive &= 3;
0369 #ifdef DEBUG
0370 printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
0371 #endif
0372 local_irq_save(flags);
0373 wait_event(fdc_wait, try_fdc(drive));
0374 fdc_busy = drive;
0375 fdc_nested++;
0376 local_irq_restore(flags);
0377 }
0378
0379 static inline void rel_fdc(void)
0380 {
0381 #ifdef DEBUG
0382 if (fdc_nested == 0)
0383 printk("fd: unmatched rel_fdc\n");
0384 printk("rel_fdc: fdc_busy %d fdc_nested %d\n",fdc_busy,fdc_nested);
0385 #endif
0386 fdc_nested--;
0387 if (fdc_nested == 0) {
0388 fdc_busy = -1;
0389 wake_up(&fdc_wait);
0390 }
0391 }
0392
0393 static void fd_select (int drive)
0394 {
0395 unsigned char prb = ~0;
0396
0397 drive&=3;
0398 #ifdef DEBUG
0399 printk("selecting %d\n",drive);
0400 #endif
0401 if (drive == selected)
0402 return;
0403 get_fdc(drive);
0404 selected = drive;
0405
0406 if (unit[drive].track % 2 != 0)
0407 prb &= ~DSKSIDE;
0408 if (unit[drive].motor == 1)
0409 prb &= ~DSKMOTOR;
0410 ciab.prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3));
0411 ciab.prb = prb;
0412 prb &= ~SELMASK(drive);
0413 ciab.prb = prb;
0414 rel_fdc();
0415 }
0416
0417 static void fd_deselect (int drive)
0418 {
0419 unsigned char prb;
0420 unsigned long flags;
0421
0422 drive&=3;
0423 #ifdef DEBUG
0424 printk("deselecting %d\n",drive);
0425 #endif
0426 if (drive != selected) {
0427 printk(KERN_WARNING "Deselecting drive %d while %d was selected!\n",drive,selected);
0428 return;
0429 }
0430
0431 get_fdc(drive);
0432 local_irq_save(flags);
0433
0434 selected = -1;
0435
0436 prb = ciab.prb;
0437 prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3));
0438 ciab.prb = prb;
0439
0440 local_irq_restore (flags);
0441 rel_fdc();
0442
0443 }
0444
0445 static void motor_on_callback(struct timer_list *unused)
0446 {
0447 if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
0448 complete_all(&motor_on_completion);
0449 } else {
0450 motor_on_timer.expires = jiffies + HZ/10;
0451 add_timer(&motor_on_timer);
0452 }
0453 }
0454
0455 static int fd_motor_on(int nr)
0456 {
0457 nr &= 3;
0458
0459 del_timer(motor_off_timer + nr);
0460
0461 if (!unit[nr].motor) {
0462 unit[nr].motor = 1;
0463 fd_select(nr);
0464
0465 reinit_completion(&motor_on_completion);
0466 mod_timer(&motor_on_timer, jiffies + HZ/2);
0467
0468 on_attempts = 10;
0469 wait_for_completion(&motor_on_completion);
0470 fd_deselect(nr);
0471 }
0472
0473 if (on_attempts == 0) {
0474 on_attempts = -1;
0475 #if 0
0476 printk (KERN_ERR "motor_on failed, turning motor off\n");
0477 fd_motor_off (motor_off_timer + nr);
0478 return 0;
0479 #else
0480 printk (KERN_WARNING "DSKRDY not set after 1.5 seconds - assuming drive is spinning notwithstanding\n");
0481 #endif
0482 }
0483
0484 return 1;
0485 }
0486
0487 static void fd_motor_off(struct timer_list *timer)
0488 {
0489 unsigned long drive = ((unsigned long)timer -
0490 (unsigned long)&motor_off_timer[0]) /
0491 sizeof(motor_off_timer[0]);
0492
0493 drive&=3;
0494 if (!try_fdc(drive)) {
0495
0496 timer->expires = jiffies + 1;
0497 add_timer(timer);
0498 return;
0499 }
0500 unit[drive].motor = 0;
0501 fd_select(drive);
0502 udelay (1);
0503 fd_deselect(drive);
0504 }
0505
0506 static void floppy_off (unsigned int nr)
0507 {
0508 int drive;
0509
0510 drive = nr & 3;
0511 mod_timer(motor_off_timer + drive, jiffies + 3*HZ);
0512 }
0513
0514 static int fd_calibrate(int drive)
0515 {
0516 unsigned char prb;
0517 int n;
0518
0519 drive &= 3;
0520 get_fdc(drive);
0521 if (!fd_motor_on (drive))
0522 return 0;
0523 fd_select (drive);
0524 prb = ciab.prb;
0525 prb |= DSKSIDE;
0526 prb &= ~DSKDIREC;
0527 ciab.prb = prb;
0528 for (n = unit[drive].type->tracks/2; n != 0; --n) {
0529 if (ciaa.pra & DSKTRACK0)
0530 break;
0531 prb &= ~DSKSTEP;
0532 ciab.prb = prb;
0533 prb |= DSKSTEP;
0534 udelay (2);
0535 ciab.prb = prb;
0536 ms_delay(unit[drive].type->step_delay);
0537 }
0538 ms_delay (unit[drive].type->settle_time);
0539 prb |= DSKDIREC;
0540 n = unit[drive].type->tracks + 20;
0541 for (;;) {
0542 prb &= ~DSKSTEP;
0543 ciab.prb = prb;
0544 prb |= DSKSTEP;
0545 udelay (2);
0546 ciab.prb = prb;
0547 ms_delay(unit[drive].type->step_delay + 1);
0548 if ((ciaa.pra & DSKTRACK0) == 0)
0549 break;
0550 if (--n == 0) {
0551 printk (KERN_ERR "fd%d: calibrate failed, turning motor off\n", drive);
0552 fd_motor_off (motor_off_timer + drive);
0553 unit[drive].track = -1;
0554 rel_fdc();
0555 return 0;
0556 }
0557 }
0558 unit[drive].track = 0;
0559 ms_delay(unit[drive].type->settle_time);
0560
0561 rel_fdc();
0562 fd_deselect(drive);
0563 return 1;
0564 }
0565
0566 static int fd_seek(int drive, int track)
0567 {
0568 unsigned char prb;
0569 int cnt;
0570
0571 #ifdef DEBUG
0572 printk("seeking drive %d to track %d\n",drive,track);
0573 #endif
0574 drive &= 3;
0575 get_fdc(drive);
0576 if (unit[drive].track == track) {
0577 rel_fdc();
0578 return 1;
0579 }
0580 if (!fd_motor_on(drive)) {
0581 rel_fdc();
0582 return 0;
0583 }
0584 if (unit[drive].track < 0 && !fd_calibrate(drive)) {
0585 rel_fdc();
0586 return 0;
0587 }
0588
0589 fd_select (drive);
0590 cnt = unit[drive].track/2 - track/2;
0591 prb = ciab.prb;
0592 prb |= DSKSIDE | DSKDIREC;
0593 if (track % 2 != 0)
0594 prb &= ~DSKSIDE;
0595 if (cnt < 0) {
0596 cnt = - cnt;
0597 prb &= ~DSKDIREC;
0598 }
0599 ciab.prb = prb;
0600 if (track % 2 != unit[drive].track % 2)
0601 ms_delay (unit[drive].type->side_time);
0602 unit[drive].track = track;
0603 if (cnt == 0) {
0604 rel_fdc();
0605 fd_deselect(drive);
0606 return 1;
0607 }
0608 do {
0609 prb &= ~DSKSTEP;
0610 ciab.prb = prb;
0611 prb |= DSKSTEP;
0612 udelay (1);
0613 ciab.prb = prb;
0614 ms_delay (unit[drive].type->step_delay);
0615 } while (--cnt != 0);
0616 ms_delay (unit[drive].type->settle_time);
0617
0618 rel_fdc();
0619 fd_deselect(drive);
0620 return 1;
0621 }
0622
0623 static unsigned long fd_get_drive_id(int drive)
0624 {
0625 int i;
0626 ulong id = 0;
0627
0628 drive&=3;
0629 get_fdc(drive);
0630
0631 MOTOR_ON;
0632 udelay(2);
0633 SELECT(SELMASK(drive));
0634 udelay(2);
0635 DESELECT(SELMASK(drive));
0636 udelay(2);
0637 MOTOR_OFF;
0638 udelay(2);
0639 SELECT(SELMASK(drive));
0640 udelay(2);
0641 DESELECT(SELMASK(drive));
0642 udelay(2);
0643
0644
0645 for (i=0; i<32; i++) {
0646 SELECT(SELMASK(drive));
0647 udelay(2);
0648
0649
0650 id <<= 1;
0651 id |= (ciaa.pra & DSKRDY) ? 0 : 1;
0652
0653 DESELECT(SELMASK(drive));
0654 }
0655
0656 rel_fdc();
0657
0658
0659
0660
0661
0662
0663
0664 if(drive == 0 && id == FD_NODRIVE)
0665 {
0666 id = fd_def_df0;
0667 printk(KERN_NOTICE "fd: drive 0 didn't identify, setting default %08lx\n", (ulong)fd_def_df0);
0668 }
0669
0670 return (id);
0671 }
0672
0673 static irqreturn_t fd_block_done(int irq, void *dummy)
0674 {
0675 if (block_flag)
0676 custom.dsklen = 0x4000;
0677
0678 if (block_flag == 2) {
0679 writepending = 2;
0680 post_write_timer.expires = jiffies + 1;
0681 post_write_timer_drive = selected;
0682 add_timer(&post_write_timer);
0683 }
0684 else {
0685 block_flag = 0;
0686 wake_up (&wait_fd_block);
0687 }
0688 return IRQ_HANDLED;
0689 }
0690
0691 static void raw_read(int drive)
0692 {
0693 drive&=3;
0694 get_fdc(drive);
0695 wait_event(wait_fd_block, !block_flag);
0696 fd_select(drive);
0697
0698 custom.adkcon = ADK_MSBSYNC;
0699 custom.adkcon = ADK_SETCLR|ADK_WORDSYNC|ADK_FAST;
0700
0701 custom.dsksync = MFM_SYNC;
0702
0703 custom.dsklen = 0;
0704 custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf);
0705 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN;
0706 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN;
0707
0708 block_flag = 1;
0709
0710 wait_event(wait_fd_block, !block_flag);
0711
0712 custom.dsklen = 0;
0713 fd_deselect(drive);
0714 rel_fdc();
0715 }
0716
0717 static int raw_write(int drive)
0718 {
0719 ushort adk;
0720
0721 drive&=3;
0722 get_fdc(drive);
0723 if ((ciaa.pra & DSKPROT) == 0) {
0724 rel_fdc();
0725 return 0;
0726 }
0727 wait_event(wait_fd_block, !block_flag);
0728 fd_select(drive);
0729
0730 custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
0731
0732 adk = ADK_SETCLR|ADK_FAST;
0733 if ((ulong)unit[drive].track >= unit[drive].type->precomp2)
0734 adk |= ADK_PRECOMP1;
0735 else if ((ulong)unit[drive].track >= unit[drive].type->precomp1)
0736 adk |= ADK_PRECOMP0;
0737 custom.adkcon = adk;
0738
0739 custom.dsklen = DSKLEN_WRITE;
0740 custom.dskptr = (u_char *)ZTWO_PADDR((u_char *)raw_buf);
0741 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE;
0742 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE;
0743
0744 block_flag = 2;
0745 return 1;
0746 }
0747
0748
0749
0750
0751
0752 static void post_write (unsigned long drive)
0753 {
0754 #ifdef DEBUG
0755 printk("post_write for drive %ld\n",drive);
0756 #endif
0757 drive &= 3;
0758 custom.dsklen = 0;
0759 block_flag = 0;
0760 writepending = 0;
0761 writefromint = 0;
0762 unit[drive].dirty = 0;
0763 wake_up(&wait_fd_block);
0764 fd_deselect(drive);
0765 rel_fdc();
0766 }
0767
0768 static void post_write_callback(struct timer_list *timer)
0769 {
0770 post_write(post_write_timer_drive);
0771 }
0772
0773
0774
0775
0776
0777
0778
0779 static unsigned long scan_sync(unsigned long raw, unsigned long end)
0780 {
0781 ushort *ptr = (ushort *)raw, *endp = (ushort *)end;
0782
0783 while (ptr < endp && *ptr++ != 0x4489)
0784 ;
0785 if (ptr < endp) {
0786 while (*ptr == 0x4489 && ptr < endp)
0787 ptr++;
0788 return (ulong)ptr;
0789 }
0790 return 0;
0791 }
0792
0793 static inline unsigned long checksum(unsigned long *addr, int len)
0794 {
0795 unsigned long csum = 0;
0796
0797 len /= sizeof(*addr);
0798 while (len-- > 0)
0799 csum ^= *addr++;
0800 csum = ((csum>>1) & 0x55555555) ^ (csum & 0x55555555);
0801
0802 return csum;
0803 }
0804
0805 static unsigned long decode (unsigned long *data, unsigned long *raw,
0806 int len)
0807 {
0808 ulong *odd, *even;
0809
0810
0811 len >>= 2;
0812 odd = raw;
0813 even = odd + len;
0814
0815
0816 raw += len * 2;
0817
0818 do {
0819 *data++ = ((*odd++ & 0x55555555) << 1) | (*even++ & 0x55555555);
0820 } while (--len != 0);
0821
0822 return (ulong)raw;
0823 }
0824
0825 struct header {
0826 unsigned char magic;
0827 unsigned char track;
0828 unsigned char sect;
0829 unsigned char ord;
0830 unsigned char labels[16];
0831 unsigned long hdrchk;
0832 unsigned long datachk;
0833 };
0834
0835 static int amiga_read(int drive)
0836 {
0837 unsigned long raw;
0838 unsigned long end;
0839 int scnt;
0840 unsigned long csum;
0841 struct header hdr;
0842
0843 drive&=3;
0844 raw = (long) raw_buf;
0845 end = raw + unit[drive].type->read_size;
0846
0847 for (scnt = 0;scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {
0848 if (!(raw = scan_sync(raw, end))) {
0849 printk (KERN_INFO "can't find sync for sector %d\n", scnt);
0850 return MFM_NOSYNC;
0851 }
0852
0853 raw = decode ((ulong *)&hdr.magic, (ulong *)raw, 4);
0854 raw = decode ((ulong *)&hdr.labels, (ulong *)raw, 16);
0855 raw = decode ((ulong *)&hdr.hdrchk, (ulong *)raw, 4);
0856 raw = decode ((ulong *)&hdr.datachk, (ulong *)raw, 4);
0857 csum = checksum((ulong *)&hdr,
0858 (char *)&hdr.hdrchk-(char *)&hdr);
0859
0860 #ifdef DEBUG
0861 printk ("(%x,%d,%d,%d) (%lx,%lx,%lx,%lx) %lx %lx\n",
0862 hdr.magic, hdr.track, hdr.sect, hdr.ord,
0863 *(ulong *)&hdr.labels[0], *(ulong *)&hdr.labels[4],
0864 *(ulong *)&hdr.labels[8], *(ulong *)&hdr.labels[12],
0865 hdr.hdrchk, hdr.datachk);
0866 #endif
0867
0868 if (hdr.hdrchk != csum) {
0869 printk(KERN_INFO "MFM_HEADER: %08lx,%08lx\n", hdr.hdrchk, csum);
0870 return MFM_HEADER;
0871 }
0872
0873
0874 if (hdr.track != unit[drive].track) {
0875 printk(KERN_INFO "MFM_TRACK: %d, %d\n", hdr.track, unit[drive].track);
0876 return MFM_TRACK;
0877 }
0878
0879 raw = decode ((ulong *)(unit[drive].trackbuf + hdr.sect*512),
0880 (ulong *)raw, 512);
0881 csum = checksum((ulong *)(unit[drive].trackbuf + hdr.sect*512), 512);
0882
0883 if (hdr.datachk != csum) {
0884 printk(KERN_INFO "MFM_DATA: (%x:%d:%d:%d) sc=%d %lx, %lx\n",
0885 hdr.magic, hdr.track, hdr.sect, hdr.ord, scnt,
0886 hdr.datachk, csum);
0887 printk (KERN_INFO "data=(%lx,%lx,%lx,%lx)\n",
0888 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[0],
0889 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[1],
0890 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[2],
0891 ((ulong *)(unit[drive].trackbuf+hdr.sect*512))[3]);
0892 return MFM_DATA;
0893 }
0894 }
0895
0896 return 0;
0897 }
0898
0899 static void encode(unsigned long data, unsigned long *dest)
0900 {
0901 unsigned long data2;
0902
0903 data &= 0x55555555;
0904 data2 = data ^ 0x55555555;
0905 data |= ((data2 >> 1) | 0x80000000) & (data2 << 1);
0906
0907 if (*(dest - 1) & 0x00000001)
0908 data &= 0x7FFFFFFF;
0909
0910 *dest = data;
0911 }
0912
0913 static void encode_block(unsigned long *dest, unsigned long *src, int len)
0914 {
0915 int cnt, to_cnt = 0;
0916 unsigned long data;
0917
0918
0919 for (cnt = 0; cnt < len / 4; cnt++) {
0920 data = src[cnt] >> 1;
0921 encode(data, dest + to_cnt++);
0922 }
0923
0924
0925 for (cnt = 0; cnt < len / 4; cnt++) {
0926 data = src[cnt];
0927 encode(data, dest + to_cnt++);
0928 }
0929 }
0930
0931 static unsigned long *putsec(int disk, unsigned long *raw, int cnt)
0932 {
0933 struct header hdr;
0934 int i;
0935
0936 disk&=3;
0937 *raw = (raw[-1]&1) ? 0x2AAAAAAA : 0xAAAAAAAA;
0938 raw++;
0939 *raw++ = 0x44894489;
0940
0941 hdr.magic = 0xFF;
0942 hdr.track = unit[disk].track;
0943 hdr.sect = cnt;
0944 hdr.ord = unit[disk].dtype->sects * unit[disk].type->sect_mult - cnt;
0945 for (i = 0; i < 16; i++)
0946 hdr.labels[i] = 0;
0947 hdr.hdrchk = checksum((ulong *)&hdr,
0948 (char *)&hdr.hdrchk-(char *)&hdr);
0949 hdr.datachk = checksum((ulong *)(unit[disk].trackbuf+cnt*512), 512);
0950
0951 encode_block(raw, (ulong *)&hdr.magic, 4);
0952 raw += 2;
0953 encode_block(raw, (ulong *)&hdr.labels, 16);
0954 raw += 8;
0955 encode_block(raw, (ulong *)&hdr.hdrchk, 4);
0956 raw += 2;
0957 encode_block(raw, (ulong *)&hdr.datachk, 4);
0958 raw += 2;
0959 encode_block(raw, (ulong *)(unit[disk].trackbuf+cnt*512), 512);
0960 raw += 256;
0961
0962 return raw;
0963 }
0964
0965 static void amiga_write(int disk)
0966 {
0967 unsigned int cnt;
0968 unsigned long *ptr = (unsigned long *)raw_buf;
0969
0970 disk&=3;
0971
0972 for (cnt = 0; cnt < 415 * unit[disk].type->sect_mult; cnt++)
0973 *ptr++ = 0xaaaaaaaa;
0974
0975
0976 for (cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)
0977 ptr = putsec (disk, ptr, cnt);
0978 *(ushort *)ptr = (ptr[-1]&1) ? 0x2AA8 : 0xAAA8;
0979 }
0980
0981
0982 struct dos_header {
0983 unsigned char track,
0984 side,
0985 sec,
0986 len_desc;
0987 unsigned short crc;
0988
0989
0990
0991 unsigned char gap1[22];
0992 };
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049 static ushort dos_crc(void * data_a3, int data_d0, int data_d1, int data_d3)
1050 {
1051 static unsigned char CRCTable1[] = {
1052 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1,
1053 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62,0x93,0x83,0xb3,0xa3,0xd3,0xc3,0xf3,0xe3,
1054 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54,0xa5,0xb5,0x85,0x95,0xe5,0xf5,0xc5,0xd5,
1055 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46,0xb7,0xa7,0x97,0x87,0xf7,0xe7,0xd7,0xc7,
1056 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38,0xc9,0xd9,0xe9,0xf9,0x89,0x99,0xa9,0xb9,
1057 0x5a,0x4a,0x7a,0x6a,0x1a,0x0a,0x3a,0x2a,0xdb,0xcb,0xfb,0xeb,0x9b,0x8b,0xbb,0xab,
1058 0x6c,0x7c,0x4c,0x5c,0x2c,0x3c,0x0c,0x1c,0xed,0xfd,0xcd,0xdd,0xad,0xbd,0x8d,0x9d,
1059 0x7e,0x6e,0x5e,0x4e,0x3e,0x2e,0x1e,0x0e,0xff,0xef,0xdf,0xcf,0xbf,0xaf,0x9f,0x8f,
1060 0x91,0x81,0xb1,0xa1,0xd1,0xc1,0xf1,0xe1,0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60,
1061 0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3,0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72,
1062 0xb5,0xa5,0x95,0x85,0xf5,0xe5,0xd5,0xc5,0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44,
1063 0xa7,0xb7,0x87,0x97,0xe7,0xf7,0xc7,0xd7,0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56,
1064 0xd9,0xc9,0xf9,0xe9,0x99,0x89,0xb9,0xa9,0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28,
1065 0xcb,0xdb,0xeb,0xfb,0x8b,0x9b,0xab,0xbb,0x4a,0x5a,0x6a,0x7a,0x0a,0x1a,0x2a,0x3a,
1066 0xfd,0xed,0xdd,0xcd,0xbd,0xad,0x9d,0x8d,0x7c,0x6c,0x5c,0x4c,0x3c,0x2c,0x1c,0x0c,
1067 0xef,0xff,0xcf,0xdf,0xaf,0xbf,0x8f,0x9f,0x6e,0x7e,0x4e,0x5e,0x2e,0x3e,0x0e,0x1e
1068 };
1069
1070 static unsigned char CRCTable2[] = {
1071 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7,0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef,
1072 0x31,0x10,0x73,0x52,0xb5,0x94,0xf7,0xd6,0x39,0x18,0x7b,0x5a,0xbd,0x9c,0xff,0xde,
1073 0x62,0x43,0x20,0x01,0xe6,0xc7,0xa4,0x85,0x6a,0x4b,0x28,0x09,0xee,0xcf,0xac,0x8d,
1074 0x53,0x72,0x11,0x30,0xd7,0xf6,0x95,0xb4,0x5b,0x7a,0x19,0x38,0xdf,0xfe,0x9d,0xbc,
1075 0xc4,0xe5,0x86,0xa7,0x40,0x61,0x02,0x23,0xcc,0xed,0x8e,0xaf,0x48,0x69,0x0a,0x2b,
1076 0xf5,0xd4,0xb7,0x96,0x71,0x50,0x33,0x12,0xfd,0xdc,0xbf,0x9e,0x79,0x58,0x3b,0x1a,
1077 0xa6,0x87,0xe4,0xc5,0x22,0x03,0x60,0x41,0xae,0x8f,0xec,0xcd,0x2a,0x0b,0x68,0x49,
1078 0x97,0xb6,0xd5,0xf4,0x13,0x32,0x51,0x70,0x9f,0xbe,0xdd,0xfc,0x1b,0x3a,0x59,0x78,
1079 0x88,0xa9,0xca,0xeb,0x0c,0x2d,0x4e,0x6f,0x80,0xa1,0xc2,0xe3,0x04,0x25,0x46,0x67,
1080 0xb9,0x98,0xfb,0xda,0x3d,0x1c,0x7f,0x5e,0xb1,0x90,0xf3,0xd2,0x35,0x14,0x77,0x56,
1081 0xea,0xcb,0xa8,0x89,0x6e,0x4f,0x2c,0x0d,0xe2,0xc3,0xa0,0x81,0x66,0x47,0x24,0x05,
1082 0xdb,0xfa,0x99,0xb8,0x5f,0x7e,0x1d,0x3c,0xd3,0xf2,0x91,0xb0,0x57,0x76,0x15,0x34,
1083 0x4c,0x6d,0x0e,0x2f,0xc8,0xe9,0x8a,0xab,0x44,0x65,0x06,0x27,0xc0,0xe1,0x82,0xa3,
1084 0x7d,0x5c,0x3f,0x1e,0xf9,0xd8,0xbb,0x9a,0x75,0x54,0x37,0x16,0xf1,0xd0,0xb3,0x92,
1085 0x2e,0x0f,0x6c,0x4d,0xaa,0x8b,0xe8,0xc9,0x26,0x07,0x64,0x45,0xa2,0x83,0xe0,0xc1,
1086 0x1f,0x3e,0x5d,0x7c,0x9b,0xba,0xd9,0xf8,0x17,0x36,0x55,0x74,0x93,0xb2,0xd1,0xf0
1087 };
1088
1089
1090 register int i;
1091 register unsigned char *CRCT1, *CRCT2, *data, c, crch, crcl;
1092
1093 CRCT1=CRCTable1;
1094 CRCT2=CRCTable2;
1095 data=data_a3;
1096 crcl=data_d1;
1097 crch=data_d0;
1098 for (i=data_d3; i>=0; i--) {
1099 c = (*data++) ^ crch;
1100 crch = CRCT1[c] ^ crcl;
1101 crcl = CRCT2[c];
1102 }
1103 return (crch<<8)|crcl;
1104 }
1105
1106 static inline ushort dos_hdr_crc (struct dos_header *hdr)
1107 {
1108 return dos_crc(&(hdr->track), 0xb2, 0x30, 3);
1109 }
1110
1111 static inline ushort dos_data_crc(unsigned char *data)
1112 {
1113 return dos_crc(data, 0xe2, 0x95 ,511);
1114 }
1115
1116 static inline unsigned char dos_decode_byte(ushort word)
1117 {
1118 register ushort w2;
1119 register unsigned char byte;
1120 register unsigned char *dec = mfmdecode;
1121
1122 w2=word;
1123 w2>>=8;
1124 w2&=127;
1125 byte = dec[w2];
1126 byte <<= 4;
1127 w2 = word & 127;
1128 byte |= dec[w2];
1129 return byte;
1130 }
1131
1132 static unsigned long dos_decode(unsigned char *data, unsigned short *raw, int len)
1133 {
1134 int i;
1135
1136 for (i = 0; i < len; i++)
1137 *data++=dos_decode_byte(*raw++);
1138 return ((ulong)raw);
1139 }
1140
1141 #ifdef DEBUG
1142 static void dbg(unsigned long ptr)
1143 {
1144 printk("raw data @%08lx: %08lx, %08lx ,%08lx, %08lx\n", ptr,
1145 ((ulong *)ptr)[0], ((ulong *)ptr)[1],
1146 ((ulong *)ptr)[2], ((ulong *)ptr)[3]);
1147 }
1148 #endif
1149
1150 static int dos_read(int drive)
1151 {
1152 unsigned long end;
1153 unsigned long raw;
1154 int scnt;
1155 unsigned short crc,data_crc[2];
1156 struct dos_header hdr;
1157
1158 drive&=3;
1159 raw = (long) raw_buf;
1160 end = raw + unit[drive].type->read_size;
1161
1162 for (scnt=0; scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) {
1163 do {
1164 if (!(raw = scan_sync (raw, end))) {
1165 printk(KERN_INFO "dos_read: no hdr sync on "
1166 "track %d, unit %d for sector %d\n",
1167 unit[drive].track,drive,scnt);
1168 return MFM_NOSYNC;
1169 }
1170 #ifdef DEBUG
1171 dbg(raw);
1172 #endif
1173 } while (*((ushort *)raw)!=0x5554);
1174 raw+=2;
1175 raw = dos_decode((unsigned char *)&hdr,(ushort *) raw,8);
1176 crc = dos_hdr_crc(&hdr);
1177
1178 #ifdef DEBUG
1179 printk("(%3d,%d,%2d,%d) %x\n", hdr.track, hdr.side,
1180 hdr.sec, hdr.len_desc, hdr.crc);
1181 #endif
1182
1183 if (crc != hdr.crc) {
1184 printk(KERN_INFO "dos_read: MFM_HEADER %04x,%04x\n",
1185 hdr.crc, crc);
1186 return MFM_HEADER;
1187 }
1188 if (hdr.track != unit[drive].track/unit[drive].type->heads) {
1189 printk(KERN_INFO "dos_read: MFM_TRACK %d, %d\n",
1190 hdr.track,
1191 unit[drive].track/unit[drive].type->heads);
1192 return MFM_TRACK;
1193 }
1194
1195 if (hdr.side != unit[drive].track%unit[drive].type->heads) {
1196 printk(KERN_INFO "dos_read: MFM_SIDE %d, %d\n",
1197 hdr.side,
1198 unit[drive].track%unit[drive].type->heads);
1199 return MFM_TRACK;
1200 }
1201
1202 if (hdr.len_desc != 2) {
1203 printk(KERN_INFO "dos_read: unknown sector len "
1204 "descriptor %d\n", hdr.len_desc);
1205 return MFM_DATA;
1206 }
1207 #ifdef DEBUG
1208 printk("hdr accepted\n");
1209 #endif
1210 if (!(raw = scan_sync (raw, end))) {
1211 printk(KERN_INFO "dos_read: no data sync on track "
1212 "%d, unit %d for sector%d, disk sector %d\n",
1213 unit[drive].track, drive, scnt, hdr.sec);
1214 return MFM_NOSYNC;
1215 }
1216 #ifdef DEBUG
1217 dbg(raw);
1218 #endif
1219
1220 if (*((ushort *)raw)!=0x5545) {
1221 printk(KERN_INFO "dos_read: no data mark after "
1222 "sync (%d,%d,%d,%d) sc=%d\n",
1223 hdr.track,hdr.side,hdr.sec,hdr.len_desc,scnt);
1224 return MFM_NOSYNC;
1225 }
1226
1227 raw+=2;
1228 raw = dos_decode((unsigned char *)(unit[drive].trackbuf + (hdr.sec - 1) * 512), (ushort *) raw, 512);
1229 raw = dos_decode((unsigned char *)data_crc,(ushort *) raw,4);
1230 crc = dos_data_crc(unit[drive].trackbuf + (hdr.sec - 1) * 512);
1231
1232 if (crc != data_crc[0]) {
1233 printk(KERN_INFO "dos_read: MFM_DATA (%d,%d,%d,%d) "
1234 "sc=%d, %x %x\n", hdr.track, hdr.side,
1235 hdr.sec, hdr.len_desc, scnt,data_crc[0], crc);
1236 printk(KERN_INFO "data=(%lx,%lx,%lx,%lx,...)\n",
1237 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[0],
1238 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[1],
1239 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[2],
1240 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[3]);
1241 return MFM_DATA;
1242 }
1243 }
1244 return 0;
1245 }
1246
1247 static inline ushort dos_encode_byte(unsigned char byte)
1248 {
1249 register unsigned char *enc, b2, b1;
1250 register ushort word;
1251
1252 enc=mfmencode;
1253 b1=byte;
1254 b2=b1>>4;
1255 b1&=15;
1256 word=enc[b2] <<8 | enc [b1];
1257 return (word|((word&(256|64)) ? 0: 128));
1258 }
1259
1260 static void dos_encode_block(ushort *dest, unsigned char *src, int len)
1261 {
1262 int i;
1263
1264 for (i = 0; i < len; i++) {
1265 *dest=dos_encode_byte(*src++);
1266 *dest|=((dest[-1]&1)||(*dest&0x4000))? 0: 0x8000;
1267 dest++;
1268 }
1269 }
1270
1271 static unsigned long *ms_putsec(int drive, unsigned long *raw, int cnt)
1272 {
1273 static struct dos_header hdr={0,0,0,2,0,
1274 {78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78}};
1275 int i;
1276 static ushort crc[2]={0,0x4e4e};
1277
1278 drive&=3;
1279
1280
1281 for(i=0;i<6;i++)
1282 *raw++=0xaaaaaaaa;
1283
1284 *raw++=0x44894489;
1285 *raw++=0x44895554;
1286
1287
1288 hdr.track=unit[drive].track/unit[drive].type->heads;
1289 hdr.side=unit[drive].track%unit[drive].type->heads;
1290 hdr.sec=cnt+1;
1291 hdr.crc=dos_hdr_crc(&hdr);
1292
1293
1294 dos_encode_block((ushort *)raw,(unsigned char *) &hdr.track,28);
1295 raw+=14;
1296
1297
1298 for(i=0;i<6;i++)
1299 *raw++=0xaaaaaaaa;
1300
1301
1302 *raw++=0x44894489;
1303 *raw++=0x44895545;
1304
1305
1306 dos_encode_block((ushort *)raw,
1307 (unsigned char *)unit[drive].trackbuf+cnt*512,512);
1308 raw+=256;
1309
1310
1311 crc[0]=dos_data_crc(unit[drive].trackbuf+cnt*512);
1312 dos_encode_block((ushort *) raw,(unsigned char *)crc,4);
1313 raw+=2;
1314
1315
1316 for(i=0;i<38;i++)
1317 *raw++=0x92549254;
1318
1319 return raw;
1320 }
1321
1322 static void dos_write(int disk)
1323 {
1324 int cnt;
1325 unsigned long raw = (unsigned long) raw_buf;
1326 unsigned long *ptr=(unsigned long *)raw;
1327
1328 disk&=3;
1329
1330 for (cnt=0;cnt<425;cnt++)
1331 *ptr++=0x92549254;
1332
1333
1334 if (unit[disk].type->sect_mult==2)
1335 for(cnt=0;cnt<473;cnt++)
1336 *ptr++=0x92549254;
1337
1338
1339 for (cnt=0;cnt<20;cnt++)
1340 *ptr++=0x92549254;
1341 for (cnt=0;cnt<6;cnt++)
1342 *ptr++=0xaaaaaaaa;
1343 *ptr++=0x52245224;
1344 *ptr++=0x52245552;
1345 for (cnt=0;cnt<20;cnt++)
1346 *ptr++=0x92549254;
1347
1348
1349 for(cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++)
1350 ptr=ms_putsec(disk,ptr,cnt);
1351
1352 *(ushort *)ptr = 0xaaa8;
1353 }
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 static void flush_track_callback(struct timer_list *timer)
1366 {
1367 unsigned long nr = ((unsigned long)timer -
1368 (unsigned long)&flush_track_timer[0]) /
1369 sizeof(flush_track_timer[0]);
1370
1371 nr&=3;
1372 writefromint = 1;
1373 if (!try_fdc(nr)) {
1374
1375 flush_track_timer[nr].expires = jiffies + 1;
1376 add_timer(flush_track_timer + nr);
1377 return;
1378 }
1379 get_fdc(nr);
1380 (*unit[nr].dtype->write_fkt)(nr);
1381 if (!raw_write(nr)) {
1382 printk (KERN_NOTICE "floppy disk write protected\n");
1383 writefromint = 0;
1384 writepending = 0;
1385 }
1386 rel_fdc();
1387 }
1388
1389 static int non_int_flush_track (unsigned long nr)
1390 {
1391 unsigned long flags;
1392
1393 nr&=3;
1394 writefromint = 0;
1395 del_timer(&post_write_timer);
1396 get_fdc(nr);
1397 if (!fd_motor_on(nr)) {
1398 writepending = 0;
1399 rel_fdc();
1400 return 0;
1401 }
1402 local_irq_save(flags);
1403 if (writepending != 2) {
1404 local_irq_restore(flags);
1405 (*unit[nr].dtype->write_fkt)(nr);
1406 if (!raw_write(nr)) {
1407 printk (KERN_NOTICE "floppy disk write protected "
1408 "in write!\n");
1409 writepending = 0;
1410 return 0;
1411 }
1412 wait_event(wait_fd_block, block_flag != 2);
1413 }
1414 else {
1415 local_irq_restore(flags);
1416 ms_delay(2);
1417 post_write(nr);
1418 }
1419 rel_fdc();
1420 return 1;
1421 }
1422
1423 static int get_track(int drive, int track)
1424 {
1425 int error, errcnt;
1426
1427 drive&=3;
1428 if (unit[drive].track == track)
1429 return 0;
1430 get_fdc(drive);
1431 if (!fd_motor_on(drive)) {
1432 rel_fdc();
1433 return -1;
1434 }
1435
1436 if (unit[drive].dirty == 1) {
1437 del_timer (flush_track_timer + drive);
1438 non_int_flush_track (drive);
1439 }
1440 errcnt = 0;
1441 while (errcnt < MAX_ERRORS) {
1442 if (!fd_seek(drive, track))
1443 return -1;
1444 raw_read(drive);
1445 error = (*unit[drive].dtype->read_fkt)(drive);
1446 if (error == 0) {
1447 rel_fdc();
1448 return 0;
1449 }
1450
1451 unit[drive].track = -1;
1452 errcnt++;
1453 }
1454 rel_fdc();
1455 return -1;
1456 }
1457
1458 static blk_status_t amiflop_rw_cur_segment(struct amiga_floppy_struct *floppy,
1459 struct request *rq)
1460 {
1461 int drive = floppy - unit;
1462 unsigned int cnt, block, track, sector;
1463 char *data;
1464
1465 for (cnt = 0; cnt < blk_rq_cur_sectors(rq); cnt++) {
1466 #ifdef DEBUG
1467 printk("fd: sector %ld + %d requested for %s\n",
1468 blk_rq_pos(rq), cnt,
1469 (rq_data_dir(rq) == READ) ? "read" : "write");
1470 #endif
1471 block = blk_rq_pos(rq) + cnt;
1472 track = block / (floppy->dtype->sects * floppy->type->sect_mult);
1473 sector = block % (floppy->dtype->sects * floppy->type->sect_mult);
1474 data = bio_data(rq->bio) + 512 * cnt;
1475 #ifdef DEBUG
1476 printk("access to track %d, sector %d, with buffer at "
1477 "0x%08lx\n", track, sector, data);
1478 #endif
1479
1480 if (get_track(drive, track) == -1)
1481 return BLK_STS_IOERR;
1482
1483 if (rq_data_dir(rq) == READ) {
1484 memcpy(data, floppy->trackbuf + sector * 512, 512);
1485 } else {
1486 memcpy(floppy->trackbuf + sector * 512, data, 512);
1487
1488
1489 if (!fd_motor_on(drive))
1490 return BLK_STS_IOERR;
1491
1492
1493
1494
1495 floppy->dirty = 1;
1496
1497 mod_timer (flush_track_timer + drive, jiffies + 1);
1498 }
1499 }
1500
1501 return BLK_STS_OK;
1502 }
1503
1504 static blk_status_t amiflop_queue_rq(struct blk_mq_hw_ctx *hctx,
1505 const struct blk_mq_queue_data *bd)
1506 {
1507 struct request *rq = bd->rq;
1508 struct amiga_floppy_struct *floppy = rq->q->disk->private_data;
1509 blk_status_t err;
1510
1511 if (!spin_trylock_irq(&amiflop_lock))
1512 return BLK_STS_DEV_RESOURCE;
1513
1514 blk_mq_start_request(rq);
1515
1516 do {
1517 err = amiflop_rw_cur_segment(floppy, rq);
1518 } while (blk_update_request(rq, err, blk_rq_cur_bytes(rq)));
1519 blk_mq_end_request(rq, err);
1520
1521 spin_unlock_irq(&amiflop_lock);
1522 return BLK_STS_OK;
1523 }
1524
1525 static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1526 {
1527 int drive = MINOR(bdev->bd_dev) & 3;
1528
1529 geo->heads = unit[drive].type->heads;
1530 geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult;
1531 geo->cylinders = unit[drive].type->tracks;
1532 return 0;
1533 }
1534
1535 static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode,
1536 unsigned int cmd, unsigned long param)
1537 {
1538 struct amiga_floppy_struct *p = bdev->bd_disk->private_data;
1539 int drive = p - unit;
1540 static struct floppy_struct getprm;
1541 void __user *argp = (void __user *)param;
1542
1543 switch(cmd){
1544 case FDFMTBEG:
1545 get_fdc(drive);
1546 if (fd_ref[drive] > 1) {
1547 rel_fdc();
1548 return -EBUSY;
1549 }
1550 fsync_bdev(bdev);
1551 if (fd_motor_on(drive) == 0) {
1552 rel_fdc();
1553 return -ENODEV;
1554 }
1555 if (fd_calibrate(drive) == 0) {
1556 rel_fdc();
1557 return -ENXIO;
1558 }
1559 floppy_off(drive);
1560 rel_fdc();
1561 break;
1562 case FDFMTTRK:
1563 if (param < p->type->tracks * p->type->heads)
1564 {
1565 get_fdc(drive);
1566 if (fd_seek(drive,param) != 0){
1567 memset(p->trackbuf, FD_FILL_BYTE,
1568 p->dtype->sects * p->type->sect_mult * 512);
1569 non_int_flush_track(drive);
1570 }
1571 floppy_off(drive);
1572 rel_fdc();
1573 }
1574 else
1575 return -EINVAL;
1576 break;
1577 case FDFMTEND:
1578 floppy_off(drive);
1579 invalidate_bdev(bdev);
1580 break;
1581 case FDGETPRM:
1582 memset((void *)&getprm, 0, sizeof (getprm));
1583 getprm.track=p->type->tracks;
1584 getprm.head=p->type->heads;
1585 getprm.sect=p->dtype->sects * p->type->sect_mult;
1586 getprm.size=p->blocks;
1587 if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct)))
1588 return -EFAULT;
1589 break;
1590 case FDSETPRM:
1591 case FDDEFPRM:
1592 return -EINVAL;
1593 case FDFLUSH:
1594 del_timer (flush_track_timer + drive);
1595 non_int_flush_track(drive);
1596 break;
1597 #ifdef RAW_IOCTL
1598 case IOCTL_RAW_TRACK:
1599 if (copy_to_user(argp, raw_buf, p->type->read_size))
1600 return -EFAULT;
1601 else
1602 return p->type->read_size;
1603 #endif
1604 default:
1605 return -ENOSYS;
1606 }
1607 return 0;
1608 }
1609
1610 static int fd_ioctl(struct block_device *bdev, fmode_t mode,
1611 unsigned int cmd, unsigned long param)
1612 {
1613 int ret;
1614
1615 mutex_lock(&amiflop_mutex);
1616 ret = fd_locked_ioctl(bdev, mode, cmd, param);
1617 mutex_unlock(&amiflop_mutex);
1618
1619 return ret;
1620 }
1621
1622 static void fd_probe(int dev)
1623 {
1624 unsigned long code;
1625 int type;
1626 int drive;
1627
1628 drive = dev & 3;
1629 code = fd_get_drive_id(drive);
1630
1631
1632 for (type = 0; type < num_dr_types; type++)
1633 if (drive_types[type].code == code)
1634 break;
1635
1636 if (type >= num_dr_types) {
1637 printk(KERN_WARNING "fd_probe: unsupported drive type "
1638 "%08lx found\n", code);
1639 unit[drive].type = &drive_types[num_dr_types-1];
1640 return;
1641 }
1642
1643 unit[drive].type = drive_types + type;
1644 unit[drive].track = -1;
1645
1646 unit[drive].disk = -1;
1647 unit[drive].motor = 0;
1648 unit[drive].busy = 0;
1649 unit[drive].status = -1;
1650 }
1651
1652
1653
1654
1655
1656
1657 static int floppy_open(struct block_device *bdev, fmode_t mode)
1658 {
1659 int drive = MINOR(bdev->bd_dev) & 3;
1660 int system = (MINOR(bdev->bd_dev) & 4) >> 2;
1661 int old_dev;
1662 unsigned long flags;
1663
1664 mutex_lock(&amiflop_mutex);
1665 old_dev = fd_device[drive];
1666
1667 if (fd_ref[drive] && old_dev != system) {
1668 mutex_unlock(&amiflop_mutex);
1669 return -EBUSY;
1670 }
1671
1672 if (unit[drive].type->code == FD_NODRIVE) {
1673 mutex_unlock(&amiflop_mutex);
1674 return -ENXIO;
1675 }
1676
1677 if (mode & (FMODE_READ|FMODE_WRITE)) {
1678 bdev_check_media_change(bdev);
1679 if (mode & FMODE_WRITE) {
1680 int wrprot;
1681
1682 get_fdc(drive);
1683 fd_select (drive);
1684 wrprot = !(ciaa.pra & DSKPROT);
1685 fd_deselect (drive);
1686 rel_fdc();
1687
1688 if (wrprot) {
1689 mutex_unlock(&amiflop_mutex);
1690 return -EROFS;
1691 }
1692 }
1693 }
1694
1695 local_irq_save(flags);
1696 fd_ref[drive]++;
1697 fd_device[drive] = system;
1698 local_irq_restore(flags);
1699
1700 unit[drive].dtype=&data_types[system];
1701 unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
1702 data_types[system].sects*unit[drive].type->sect_mult;
1703 set_capacity(unit[drive].gendisk[system], unit[drive].blocks);
1704
1705 printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive,
1706 unit[drive].type->name, data_types[system].name);
1707
1708 mutex_unlock(&amiflop_mutex);
1709 return 0;
1710 }
1711
1712 static void floppy_release(struct gendisk *disk, fmode_t mode)
1713 {
1714 struct amiga_floppy_struct *p = disk->private_data;
1715 int drive = p - unit;
1716
1717 mutex_lock(&amiflop_mutex);
1718 if (unit[drive].dirty == 1) {
1719 del_timer (flush_track_timer + drive);
1720 non_int_flush_track (drive);
1721 }
1722
1723 if (!fd_ref[drive]--) {
1724 printk(KERN_CRIT "floppy_release with fd_ref == 0");
1725 fd_ref[drive] = 0;
1726 }
1727 #ifdef MODULE
1728 floppy_off (drive);
1729 #endif
1730 mutex_unlock(&amiflop_mutex);
1731 }
1732
1733
1734
1735
1736
1737
1738
1739 static unsigned amiga_check_events(struct gendisk *disk, unsigned int clearing)
1740 {
1741 struct amiga_floppy_struct *p = disk->private_data;
1742 int drive = p - unit;
1743 int changed;
1744 static int first_time = 1;
1745
1746 if (first_time)
1747 changed = first_time--;
1748 else {
1749 get_fdc(drive);
1750 fd_select (drive);
1751 changed = !(ciaa.pra & DSKCHANGE);
1752 fd_deselect (drive);
1753 rel_fdc();
1754 }
1755
1756 if (changed) {
1757 fd_probe(drive);
1758 p->track = -1;
1759 p->dirty = 0;
1760 writepending = 0;
1761 writefromint = 0;
1762 return DISK_EVENT_MEDIA_CHANGE;
1763 }
1764 return 0;
1765 }
1766
1767 static const struct block_device_operations floppy_fops = {
1768 .owner = THIS_MODULE,
1769 .open = floppy_open,
1770 .release = floppy_release,
1771 .ioctl = fd_ioctl,
1772 .getgeo = fd_getgeo,
1773 .check_events = amiga_check_events,
1774 };
1775
1776 static const struct blk_mq_ops amiflop_mq_ops = {
1777 .queue_rq = amiflop_queue_rq,
1778 };
1779
1780 static int fd_alloc_disk(int drive, int system)
1781 {
1782 struct gendisk *disk;
1783 int err;
1784
1785 disk = blk_mq_alloc_disk(&unit[drive].tag_set, NULL);
1786 if (IS_ERR(disk))
1787 return PTR_ERR(disk);
1788
1789 disk->major = FLOPPY_MAJOR;
1790 disk->first_minor = drive + system;
1791 disk->minors = 1;
1792 disk->fops = &floppy_fops;
1793 disk->flags |= GENHD_FL_NO_PART;
1794 disk->events = DISK_EVENT_MEDIA_CHANGE;
1795 if (system)
1796 sprintf(disk->disk_name, "fd%d_msdos", drive);
1797 else
1798 sprintf(disk->disk_name, "fd%d", drive);
1799 disk->private_data = &unit[drive];
1800 set_capacity(disk, 880 * 2);
1801
1802 unit[drive].gendisk[system] = disk;
1803 err = add_disk(disk);
1804 if (err)
1805 put_disk(disk);
1806 return err;
1807 }
1808
1809 static int fd_alloc_drive(int drive)
1810 {
1811 unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL);
1812 if (!unit[drive].trackbuf)
1813 goto out;
1814
1815 memset(&unit[drive].tag_set, 0, sizeof(unit[drive].tag_set));
1816 unit[drive].tag_set.ops = &amiflop_mq_ops;
1817 unit[drive].tag_set.nr_hw_queues = 1;
1818 unit[drive].tag_set.nr_maps = 1;
1819 unit[drive].tag_set.queue_depth = 2;
1820 unit[drive].tag_set.numa_node = NUMA_NO_NODE;
1821 unit[drive].tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
1822 if (blk_mq_alloc_tag_set(&unit[drive].tag_set))
1823 goto out_cleanup_trackbuf;
1824
1825 pr_cont(" fd%d", drive);
1826
1827 if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1))
1828 goto out_cleanup_tagset;
1829 return 0;
1830
1831 out_cleanup_tagset:
1832 blk_mq_free_tag_set(&unit[drive].tag_set);
1833 out_cleanup_trackbuf:
1834 kfree(unit[drive].trackbuf);
1835 out:
1836 unit[drive].type->code = FD_NODRIVE;
1837 return -ENOMEM;
1838 }
1839
1840 static int __init fd_probe_drives(void)
1841 {
1842 int drive,drives,nomem;
1843
1844 pr_info("FD: probing units\nfound");
1845 drives=0;
1846 nomem=0;
1847 for(drive=0;drive<FD_MAX_UNITS;drive++) {
1848 fd_probe(drive);
1849 if (unit[drive].type->code == FD_NODRIVE)
1850 continue;
1851
1852 if (fd_alloc_drive(drive) < 0) {
1853 pr_cont(" no mem for fd%d", drive);
1854 nomem = 1;
1855 continue;
1856 }
1857 drives++;
1858 }
1859 if ((drives > 0) || (nomem == 0)) {
1860 if (drives == 0)
1861 pr_cont(" no drives");
1862 pr_cont("\n");
1863 return drives;
1864 }
1865 pr_cont("\n");
1866 return -ENOMEM;
1867 }
1868
1869 static int __init amiga_floppy_probe(struct platform_device *pdev)
1870 {
1871 int i, ret;
1872
1873 if (register_blkdev(FLOPPY_MAJOR,"fd"))
1874 return -EBUSY;
1875
1876 ret = -ENOMEM;
1877 raw_buf = amiga_chip_alloc(RAW_BUF_SIZE, "Floppy");
1878 if (!raw_buf) {
1879 printk("fd: cannot get chip mem buffer\n");
1880 goto out_blkdev;
1881 }
1882
1883 ret = -EBUSY;
1884 if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) {
1885 printk("fd: cannot get irq for dma\n");
1886 goto out_irq;
1887 }
1888
1889 if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) {
1890 printk("fd: cannot get irq for timer\n");
1891 goto out_irq2;
1892 }
1893
1894 ret = -ENODEV;
1895 if (fd_probe_drives() < 1)
1896 goto out_probe;
1897
1898
1899 timer_setup(&motor_on_timer, motor_on_callback, 0);
1900 motor_on_timer.expires = 0;
1901 for (i = 0; i < FD_MAX_UNITS; i++) {
1902 timer_setup(&motor_off_timer[i], fd_motor_off, 0);
1903 motor_off_timer[i].expires = 0;
1904 timer_setup(&flush_track_timer[i], flush_track_callback, 0);
1905 flush_track_timer[i].expires = 0;
1906
1907 unit[i].track = -1;
1908 }
1909
1910 timer_setup(&post_write_timer, post_write_callback, 0);
1911 post_write_timer.expires = 0;
1912
1913 for (i = 0; i < 128; i++)
1914 mfmdecode[i]=255;
1915 for (i = 0; i < 16; i++)
1916 mfmdecode[mfmencode[i]]=i;
1917
1918
1919 custom.dmacon = DMAF_SETCLR | DMAF_DISK;
1920
1921
1922 ciaa.crb = 8;
1923 return 0;
1924
1925 out_probe:
1926 free_irq(IRQ_AMIGA_CIAA_TB, NULL);
1927 out_irq2:
1928 free_irq(IRQ_AMIGA_DSKBLK, NULL);
1929 out_irq:
1930 amiga_chip_free(raw_buf);
1931 out_blkdev:
1932 unregister_blkdev(FLOPPY_MAJOR,"fd");
1933 return ret;
1934 }
1935
1936 static struct platform_driver amiga_floppy_driver = {
1937 .driver = {
1938 .name = "amiga-floppy",
1939 },
1940 };
1941
1942 static int __init amiga_floppy_init(void)
1943 {
1944 return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe);
1945 }
1946
1947 module_init(amiga_floppy_init);
1948
1949 #ifndef MODULE
1950 static int __init amiga_floppy_setup (char *str)
1951 {
1952 int n;
1953 if (!MACH_IS_AMIGA)
1954 return 0;
1955 if (!get_option(&str, &n))
1956 return 0;
1957 printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n);
1958 fd_def_df0 = n;
1959 return 1;
1960 }
1961
1962 __setup("floppy=", amiga_floppy_setup);
1963 #endif
1964
1965 MODULE_ALIAS("platform:amiga-floppy");