Lines Matching +full:ld +full:- +full:pulse +full:- +full:delay +full:- +full:us
1 // SPDX-License-Identifier: GPL-2.0-only
9 * - now no bugs(?) any more for both HD & DD
10 * - added support for 40 Track 5.25" drives, 80-track hopefully behaves
11 * like 3.5" dd (no way to test - are there any 5.25" drives out there
13 * - wrote formatting routine (maybe dirty, but works)
15 * june/july 1995 added ms-dos support by Joerg Dorchain
17 * - currently only 9 and 18 sector disks
19 * - fixed a bug with the internal trackbuffer when using multiple
21 * - made formatting a bit safer
22 * - added command line and machine based default for "silent" df0
25 * - works but I think it's inefficient. (look in redo_fd_request)
29 * - usage ioctl(d, RAW_TRACK, ptr); the raw track buffer (MFM-encoded data
31 * done - 30K is currently sufficient). return the actual size of the
33 * - replaced udelays() by a timer (CIAA timer B) for the waits
37 * - both got broken the first time I tampered with the driver :-(
38 * - still not safe, but better than before
41 * - Minor changes to accept the kdev_t.
42 * - Replaced some more udelays with ms_delays. Udelay is just a loop,
43 * and so the delay will be different depending on the given
44 * processor :-(
45 * - The driver could use a major cleanup because of the new
51 * - Fixed Bug accessing multiple disks
52 * - some code cleanup
53 * - added trackbuffer for each drive to speed things up
54 * - fixed some race conditions (who finds the next may send it to me ;-)
62 #include <linux/delay.h>
66 #include <linux/blk-mq.h>
108 #define DSKSTEP (0x1) /* pulse low to step head 1 track */
118 /* bits 7-0 are data */
132 #define ADK_FAST (1<<8) /* bit cell: 0=2us (GCR), 1=1us (MFM) */
185 unsigned int step_delay; /* time (in ms) for delay after step */
193 int track; /* current track (-1 == unknown) */
199 int disk; /* disk in drive (-1 == unknown) */
212 #define FD_ERROR -1 /* general error (seek, read, write, etc) */
227 #define FD_DD_3 0xffffffff /* double-density 3.5" (880K) drive */
228 #define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */
229 #define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */
260 { "MS-Dos", 9, dos_read, dos_write}
275 static volatile int fdc_busy = -1;
281 static volatile int selected = -1; /* currently selected drive */
299 /* MS-Dos MFM Coding tables (should go quick and easy) */
312 * max X times - some types of errors increase the errorcount by 2 or
346 ticks = MS_TICKS*ms-1; in ms_delay()
349 ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */ in ms_delay()
386 fdc_nested--; in rel_fdc()
388 fdc_busy = -1; in rel_fdc()
434 selected = -1; in fd_deselect()
447 if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) { in motor_on_callback()
474 on_attempts = -1; in fd_motor_on()
480 …printk (KERN_WARNING "DSKRDY not set after 1.5 seconds - assuming drive is spinning notwithstandin… in fd_motor_on()
489 unsigned long drive = ((unsigned long)timer - in fd_motor_off()
496 timer->expires = jiffies + 1; in fd_motor_off()
528 for (n = unit[drive].type->tracks/2; n != 0; --n) { in fd_calibrate()
536 ms_delay(unit[drive].type->step_delay); in fd_calibrate()
538 ms_delay (unit[drive].type->settle_time); in fd_calibrate()
540 n = unit[drive].type->tracks + 20; in fd_calibrate()
547 ms_delay(unit[drive].type->step_delay + 1); in fd_calibrate()
550 if (--n == 0) { in fd_calibrate()
553 unit[drive].track = -1; in fd_calibrate()
559 ms_delay(unit[drive].type->settle_time); in fd_calibrate()
590 cnt = unit[drive].track/2 - track/2; in fd_seek()
596 cnt = - cnt; in fd_seek()
601 ms_delay (unit[drive].type->side_time); in fd_seek()
614 ms_delay (unit[drive].type->step_delay); in fd_seek()
615 } while (--cnt != 0); in fd_seek()
616 ms_delay (unit[drive].type->settle_time); in fd_seek()
651 id |= (ciaa.pra & DSKRDY) ? 0 : 1; /* cia regs are low-active! */ in fd_get_drive_id()
705 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN; in raw_read()
706 custom.dsklen = unit[drive].type->read_size/sizeof(short) | DSKLEN_DMAEN; in raw_read()
733 if ((ulong)unit[drive].track >= unit[drive].type->precomp2) in raw_write()
735 else if ((ulong)unit[drive].track >= unit[drive].type->precomp1) in raw_write()
741 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE; in raw_write()
742 custom.dsklen = unit[drive].type->write_size/sizeof(short) | DSKLEN_DMAEN|DSKLEN_WRITE; in raw_write()
755 printk("post_write for drive %ld\n",drive); in post_write()
776 * (Add other formats here ;-))
798 while (len-- > 0) in checksum()
820 } while (--len != 0); in decode()
845 end = raw + unit[drive].type->read_size; in amiga_read()
847 for (scnt = 0;scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) { in amiga_read()
858 (char *)&hdr.hdrchk-(char *)&hdr); in amiga_read()
907 if (*(dest - 1) & 0x00000001) in encode()
937 *raw = (raw[-1]&1) ? 0x2AAAAAAA : 0xAAAAAAAA; in putsec()
944 hdr.ord = unit[disk].dtype->sects * unit[disk].type->sect_mult - cnt; in putsec()
948 (char *)&hdr.hdrchk-(char *)&hdr); in putsec()
972 for (cnt = 0; cnt < 415 * unit[disk].type->sect_mult; cnt++) in amiga_write()
976 for (cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++) in amiga_write()
978 *(ushort *)ptr = (ptr[-1]&1) ? 0x2AA8 : 0xAAA8; in amiga_write()
983 unsigned char track, /* 0-80 */
984 side, /* 0-1 */
985 sec, /* 0-...*/
991 unsigned char gap1[22]; /* for longword-alignedness (0x4e) */
994 /* crc routines are borrowed from the messydos-handler */
996 /* excerpt from the messydos-device
998 ; the SYNC mark (3 * $a1) and the 'ID/DATA - Address Mark' ($fe/$fb).
1006 ; polynomials. We calculate with these polynomials in modulo-2
1008 ; exclusive-or. Now, we modify our data (a very long polynomial) in
1009 ; such a way that it becomes divisible by the CCITT-standard 16-bit
1024 ; The following algorithm does this for us:
1089 /* look at the asm-code - what looks in C a bit strange is almost as good as handmade */ in dos_crc()
1098 for (i=data_d3; i>=0; i--) { in dos_crc()
1108 return dos_crc(&(hdr->track), 0xb2, 0x30, 3); /* precomputed magic */ in dos_hdr_crc()
1160 end = raw + unit[drive].type->read_size; in dos_read()
1162 for (scnt=0; scnt < unit[drive].dtype->sects * unit[drive].type->sect_mult; scnt++) { in dos_read()
1163 do { /* search for the right sync of each sec-hdr */ in dos_read()
1188 if (hdr.track != unit[drive].track/unit[drive].type->heads) { in dos_read()
1191 unit[drive].track/unit[drive].type->heads); in dos_read()
1195 if (hdr.side != unit[drive].track%unit[drive].type->heads) { in dos_read()
1198 unit[drive].track%unit[drive].type->heads); in dos_read()
1228 …raw = dos_decode((unsigned char *)(unit[drive].trackbuf + (hdr.sec - 1) * 512), (ushort *) raw, 51… in dos_read()
1230 crc = dos_data_crc(unit[drive].trackbuf + (hdr.sec - 1) * 512); in dos_read()
1237 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[0], in dos_read()
1238 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[1], in dos_read()
1239 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[2], in dos_read()
1240 ((ulong *)(unit[drive].trackbuf+(hdr.sec-1)*512))[3]); in dos_read()
1266 *dest|=((dest[-1]&1)||(*dest&0x4000))? 0: 0x8000; in dos_encode_block()
1288 hdr.track=unit[drive].track/unit[drive].type->heads; in ms_putsec()
1289 hdr.side=unit[drive].track%unit[drive].type->heads; in ms_putsec()
1310 /*data crc + jd's special gap (long words :-/) */ in ms_putsec()
1334 if (unit[disk].type->sect_mult==2) /* check for HD-Disks */ in dos_write()
1349 for(cnt = 0; cnt < unit[disk].dtype->sects * unit[disk].type->sect_mult; cnt++) in dos_write()
1362 /* FIXME: this assumes the drive is still spinning -
1367 unsigned long nr = ((unsigned long)timer - in flush_track_callback()
1380 (*unit[nr].dtype->write_fkt)(nr); in flush_track_callback()
1405 (*unit[nr].dtype->write_fkt)(nr); in non_int_flush_track()
1416 ms_delay(2); /* 2 ms post_write delay */ in non_int_flush_track()
1433 return -1; in get_track()
1443 return -1; in get_track()
1445 error = (*unit[drive].dtype->read_fkt)(drive); in get_track()
1451 unit[drive].track = -1; in get_track()
1455 return -1; in get_track()
1461 int drive = floppy - unit; in amiflop_rw_cur_segment()
1467 printk("fd: sector %ld + %d requested for %s\n", in amiflop_rw_cur_segment()
1472 track = block / (floppy->dtype->sects * floppy->type->sect_mult); in amiflop_rw_cur_segment()
1473 sector = block % (floppy->dtype->sects * floppy->type->sect_mult); in amiflop_rw_cur_segment()
1474 data = bio_data(rq->bio) + 512 * cnt; in amiflop_rw_cur_segment()
1480 if (get_track(drive, track) == -1) in amiflop_rw_cur_segment()
1484 memcpy(data, floppy->trackbuf + sector * 512, 512); in amiflop_rw_cur_segment()
1486 memcpy(floppy->trackbuf + sector * 512, data, 512); in amiflop_rw_cur_segment()
1493 * after a short (1 tick) delay. in amiflop_rw_cur_segment()
1495 floppy->dirty = 1; in amiflop_rw_cur_segment()
1507 struct request *rq = bd->rq; in amiflop_queue_rq()
1508 struct amiga_floppy_struct *floppy = rq->rq_disk->private_data; in amiflop_queue_rq()
1527 int drive = MINOR(bdev->bd_dev) & 3; in fd_getgeo()
1529 geo->heads = unit[drive].type->heads; in fd_getgeo()
1530 geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; in fd_getgeo()
1531 geo->cylinders = unit[drive].type->tracks; in fd_getgeo()
1538 struct amiga_floppy_struct *p = bdev->bd_disk->private_data; in fd_locked_ioctl()
1539 int drive = p - unit; in fd_locked_ioctl()
1548 return -EBUSY; in fd_locked_ioctl()
1553 return -ENODEV; in fd_locked_ioctl()
1557 return -ENXIO; in fd_locked_ioctl()
1563 if (param < p->type->tracks * p->type->heads) in fd_locked_ioctl()
1567 memset(p->trackbuf, FD_FILL_BYTE, in fd_locked_ioctl()
1568 p->dtype->sects * p->type->sect_mult * 512); in fd_locked_ioctl()
1575 return -EINVAL; in fd_locked_ioctl()
1583 getprm.track=p->type->tracks; in fd_locked_ioctl()
1584 getprm.head=p->type->heads; in fd_locked_ioctl()
1585 getprm.sect=p->dtype->sects * p->type->sect_mult; in fd_locked_ioctl()
1586 getprm.size=p->blocks; in fd_locked_ioctl()
1588 return -EFAULT; in fd_locked_ioctl()
1592 return -EINVAL; in fd_locked_ioctl()
1599 if (copy_to_user(argp, raw_buf, p->type->read_size)) in fd_locked_ioctl()
1600 return -EFAULT; in fd_locked_ioctl()
1602 return p->type->read_size; in fd_locked_ioctl()
1605 return -ENOSYS; in fd_locked_ioctl()
1639 unit[drive].type = &drive_types[num_dr_types-1]; /* FD_NODRIVE */ in fd_probe()
1644 unit[drive].track = -1; in fd_probe()
1646 unit[drive].disk = -1; in fd_probe()
1649 unit[drive].status = -1; in fd_probe()
1659 int drive = MINOR(bdev->bd_dev) & 3; in floppy_open()
1660 int system = (MINOR(bdev->bd_dev) & 4) >> 2; in floppy_open()
1669 return -EBUSY; in floppy_open()
1685 return -EROFS; in floppy_open()
1696 unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* in floppy_open()
1697 data_types[system].sects*unit[drive].type->sect_mult; in floppy_open()
1700 printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, in floppy_open()
1701 unit[drive].type->name, data_types[system].name); in floppy_open()
1709 struct amiga_floppy_struct *p = disk->private_data; in floppy_release()
1710 int drive = p - unit; in floppy_release()
1718 if (!fd_ref[drive]--) { in floppy_release()
1730 * here, sleep etc. Note that floppy-on tries to set current_DOR to point
1736 struct amiga_floppy_struct *p = disk->private_data; in amiga_check_events()
1737 int drive = p - unit; in amiga_check_events()
1742 changed = first_time--; in amiga_check_events()
1753 p->track = -1; in amiga_check_events()
1754 p->dirty = 0; in amiga_check_events()
1783 disk->queue = blk_mq_init_sq_queue(&unit[drive].tag_set, &amiflop_mq_ops, in fd_alloc_disk()
1785 if (IS_ERR(disk->queue)) { in fd_alloc_disk()
1786 disk->queue = NULL; in fd_alloc_disk()
1797 blk_cleanup_queue(disk->queue); in fd_alloc_disk()
1798 disk->queue = NULL; in fd_alloc_disk()
1803 unit[drive].type->code = FD_NODRIVE; in fd_alloc_disk()
1817 if (unit[drive].type->code == FD_NODRIVE) in fd_probe_drives()
1830 disk->major = FLOPPY_MAJOR; in fd_probe_drives()
1831 disk->first_minor = drive; in fd_probe_drives()
1832 disk->fops = &floppy_fops; in fd_probe_drives()
1833 disk->events = DISK_EVENT_MEDIA_CHANGE; in fd_probe_drives()
1834 sprintf(disk->disk_name, "fd%d", drive); in fd_probe_drives()
1835 disk->private_data = &unit[drive]; in fd_probe_drives()
1846 return -ENOMEM; in fd_probe_drives()
1852 if (unit[drive].type->code == FD_NODRIVE) in floppy_find()
1863 return -EBUSY; in amiga_floppy_probe()
1865 ret = -ENOMEM; in amiga_floppy_probe()
1872 ret = -EBUSY; in amiga_floppy_probe()
1883 ret = -ENODEV; in amiga_floppy_probe()
1899 unit[i].track = -1; in amiga_floppy_probe()
1914 ciaa.crb = 8; /* one-shot, stop */ in amiga_floppy_probe()
1930 .name = "amiga-floppy",
1957 MODULE_ALIAS("platform:amiga-floppy");