📄 fd1772.c
字号:
goto repeat; } if (type == 0) { if (!floppy->disktype) { Probing = 1; floppy->disktype = disk_type + NUM_DISK_TYPES - 1; floppy_sizes[drive] = floppy->disktype->blocks >> 1; floppy->autoprobe = 1; } } else { /* user supplied disk type */ --type; if (type >= NUM_DISK_TYPES) { printk("fd%d: invalid disk format", drive); end_request(0); goto repeat; } floppy->disktype = &disk_type[type]; floppy_sizes[drive] = disk_type[type].blocks >> 1; floppy->autoprobe = 0; } if (CURRENT->sector + 1 > floppy->disktype->blocks) { end_request(0); goto repeat; } /* stop deselect timer */ del_timer(&motor_off_timer); ReqCnt = 0; ReqCmd = CURRENT->cmd; ReqBlock = CURRENT->sector; ReqBuffer = CURRENT->buffer; setup_req_params(drive); do_fd_action(drive); return; the_end: finish_fdc();}static void fd1772_checkint(void){ extern int fdc1772_bytestogo; /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/ if (fdc1772_fdc_int_done) floppy_irqconsequencehandler(); if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0); if (fdc_busy) { queue_task(&fd1772_tq,&tq_immediate); mark_bh(IMMEDIATE_BH); };};void do_fd_request(void){ unsigned long flags; DPRINT(("do_fd_request for pid %d\n", current->pid)); if (fdc_busy) return; save_flags(flags); cli(); while (fdc_busy) sleep_on(&fdc_wait); fdc_busy = 1; ENABLE_IRQ(); restore_flags(flags); fdc1772_fdc_int_done = 0; redo_fd_request(); queue_task(&fd1772_tq,&tq_immediate); mark_bh(IMMEDIATE_BH);}static int invalidate_drive(int rdev){ /* invalidate the buffer track to force a reread */#ifdef TRACKBUFFER BufferDrive = -1;#endif set_bit(rdev & 3, &fake_change); check_disk_change(rdev); return 0;}static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long param){#define IOCTL_MODE_BIT 8#define OPEN_WRITE_BIT 16#define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT)) int drive, device; device = inode->i_rdev; switch (cmd) { RO_IOCTLS(inode->i_rdev, param); } drive = MINOR(device); if (!IOCTL_ALLOWED) return -EPERM; switch (cmd) { case FDFMTBEG: return 0; /* case FDC1772LRPRM: ??? DAG what does this do?? unit[drive].disktype = NULL; floppy_sizes[drive] = MAX_DISK_SIZE; return invalidate_drive (device); */ case FDFMTEND: case FDFLUSH: return invalidate_drive(drive); } if (!suser()) return -EPERM; if (drive < 0 || drive > 3) return -EINVAL; switch (cmd) { default: return -EINVAL; } return 0;}/* Initialize the 'unit' variable for drive 'drive' */static void fd_probe(int drive){ unit[drive].connected = 0; unit[drive].disktype = NULL; if (!fd_test_drive_present(drive)) return; unit[drive].connected = 1; unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */ unit[drive].steprate = FDC1772STEP_6; MotorOn = 1; /* from probe restore operation! */}/* This function tests the physical presence of a floppy drive (not * whether a disk is inserted). This is done by issuing a restore * command, waiting max. 2 seconds (that should be enough to move the * head across the whole disk) and looking at the state of the "TR00" * signal. This should now be raised if there is a drive connected * (and there is no hardware failure :-) Otherwise, the drive is * declared absent. */static int fd_test_drive_present(int drive){ unsigned long timeout; unsigned char status; int ok; printk("fd_test_drive_present %d\n", drive); if (drive > 1) return (0); return (1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */ fd_select_drive(drive); /* disable interrupt temporarily */ DISABLE_IRQ(); FDC1772_WRITE(FDC1772REG_TRACK, 0x00); /* was ff00 why? */ FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6); /*printk("fd_test_drive_present: Going into timeout loop\n"); */ for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; jiffies < timeout;) { /* What does this piece of atariism do? - query for an interrupt? */ /* if (!(mfp.par_dt_reg & 0x20)) break; */ /* Well this is my nearest guess - quit when we get an FDC interrupt */ if (IOC_FIQSTAT & 2) break; } /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */ status = FDC1772_READ(FDC1772REG_STATUS); ok = (status & FDC1772STAT_TR00) != 0; /*printk("fd_test_drive_present: ok=%d\n",ok); */ /* force interrupt to abort restore operation (FDC1772 would try * about 50 seconds!) */ FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); udelay(500); status = FDC1772_READ(FDC1772REG_STATUS); udelay(20); /*printk("fd_test_drive_present: just before OK code %d\n",ok); */ if (ok) { /* dummy seek command to make WP bit accessible */ FDC1772_WRITE(FDC1772REG_DATA, 0); FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK); printk("fd_test_drive_present: just before wait for int\n"); /* DAG: Guess means wait for interrupt */ while (!(IOC_FIQSTAT & 2)); printk("fd_test_drive_present: just after wait for int\n"); status = FDC1772_READ(FDC1772REG_STATUS); } printk("fd_test_drive_present: just before ENABLE_IRQ\n"); ENABLE_IRQ(); printk("fd_test_drive_present: about to return\n"); return (ok);}/* Look how many and which kind of drives are connected. If there are * floppies, additionally start the disk-change and motor-off timers. */static void config_types(void){ int drive, cnt = 0; printk("Probing floppy drive(s):\n"); for (drive = 0; drive < FD_MAX_UNITS; drive++) { fd_probe(drive); if (unit[drive].connected) { printk("fd%d\n", drive); ++cnt; } } if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) { /* If FDC1772 is still busy from probing, give it another FORCI * command to abort the operation. If this isn't done, the FDC1772 * will interrupt later and its IRQ line stays low, because * the status register isn't read. And this will block any * interrupts on this IRQ line :-( */ FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); udelay(500); FDC1772_READ(FDC1772REG_STATUS); udelay(20); } if (cnt > 0) { START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY); if (cnt == 1) fd_select_drive(0); /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ }}/* * floppy_open check for aliasing (/dev/fd0 can be the same as * /dev/PS0 etc), and disallows simultaneous access to the same * drive with different device numbers. */static int floppy_open(struct inode *inode, struct file *filp){ int drive; int old_dev; if (!filp) { DPRINT(("Weird, open called with filp=0\n")); return -EIO; } drive = MINOR(inode->i_rdev) & 3; if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES) return -ENXIO; old_dev = fd_device[drive]; if (fd_ref[drive]) if (old_dev != inode->i_rdev) return -EBUSY; if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL)) return -EBUSY; if (filp->f_flags & O_EXCL) fd_ref[drive] = -1; else fd_ref[drive]++; fd_device[drive] = inode->i_rdev; if (old_dev && old_dev != inode->i_rdev) invalidate_buffers(old_dev); /* Allow ioctls if we have write-permissions even if read-only open */ if (filp->f_mode & 2 || permission(inode, 2) == 0) filp->f_mode |= IOCTL_MODE_BIT; if (filp->f_mode & 2) filp->f_mode |= OPEN_WRITE_BIT; if (filp->f_flags & O_NDELAY) return 0; if (filp->f_mode & 3) { check_disk_change(inode->i_rdev); if (filp->f_mode & 2) { if (unit[drive].wpstat) { floppy_release(inode, filp); return -EROFS; } } } return 0;}static void floppy_release(struct inode *inode, struct file *filp){ int drive; drive = inode->i_rdev & 3; if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT))) /* if the file is mounted OR (writable now AND writable at open time) Linus: Does this cover all cases? */ block_fsync(inode, filp); if (fd_ref[drive] < 0) fd_ref[drive] = 0; else if (!fd_ref[drive]--) { printk("floppy_release with fd_ref == 0"); fd_ref[drive] = 0; }}static struct file_operations floppy_fops ={ NULL, /* lseek - default */ block_read, /* read - general block-dev read */ block_write, /* write - general block-dev write */ NULL, /* readdir - bad */ NULL, /* select */ fd_ioctl, /* ioctl */ NULL, /* mmap */ floppy_open, /* open */ floppy_release, /* release */ block_fsync, /* fsync */ NULL, /* fasync */ check_floppy_change, /* media_change */ floppy_revalidate, /* revalidate */};int floppy_init(void){ int i; if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { printk("Unable to get major %d for floppy\n", MAJOR_NR); return 1; } if (request_dma(FLOPPY_DMA, "fd1772")) { printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA); return 1; }; if (request_dma(FIQ_FD1772, "fd1772 end")) { printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772); free_dma(FLOPPY_DMA); return 1; }; enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */ /* initialize variables */ SelectedDrive = -1;#ifdef TRACKBUFFER BufferDrive = -1;#endif /* initialize check_change timer */ timer_table[FLOPPY_TIMER].fn = check_change; timer_active &= ~(1 << FLOPPY_TIMER);#ifdef TRACKBUFFER DMABuffer = (char *)kmalloc((MAX_SECTORS+1)*512,GFP_KERNEL); /* Atari uses 512 - I want to eventually cope with 1K sectors */ TrackBuffer = DMABuffer + 512;#else /* Allocate memory for the DMAbuffer - on the Atari this takes it out of some special memory... */ DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */#endif#ifdef TRACKBUFFER BufferDrive = BufferSide = BufferTrack = -1;#endif for (i = 0; i < FD_MAX_UNITS; i++) { unit[i].track = -1; } for (i = 0; i < 256; i++) if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES) floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1; else floppy_sizes[i] = MAX_DISK_SIZE; blk_size[MAJOR_NR] = floppy_sizes; blksize_size[MAJOR_NR] = floppy_blocksizes; blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; config_types(); return 0;}/* Just a dummy at the moment */void floppy_setup(char *str, int *ints){}void floppy_eject(void) {}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -