📄 ide-floppy.c
字号:
/* Else assume format_unit has finished, and we're ** at 0x10000 */ } else { idefloppy_status_reg_t status; unsigned long flags; __save_flags(flags); __cli(); status.all=GET_STAT(); __restore_flags(flags); progress_indication= !status.b.dsc ? 0:0x10000; } if (put_user(progress_indication, arg)) return (-EFAULT); return (0);}/* * Our special ide-floppy ioctl's. * * Currently there aren't any ioctl's. */static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ idefloppy_pc_t pc; idefloppy_floppy_t *floppy = drive->driver_data; int prevent = (arg) ? 1 : 0; switch (cmd) { case CDROMEJECT: prevent = 0; /* fall through */ case CDROM_LOCKDOOR: if (drive->usage > 1) return -EBUSY; /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, prevent); (void) idefloppy_queue_pc_tail (drive, &pc); } if (cmd == CDROMEJECT) { idefloppy_create_start_stop_cmd (&pc, 2); (void) idefloppy_queue_pc_tail (drive, &pc); } return 0; case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED: return (0); case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY: return (idefloppy_get_format_capacities(drive, inode, file, (int *)arg)); case IDEFLOPPY_IOCTL_FORMAT_START: if (!(file->f_mode & 2)) return (-EPERM); { idefloppy_floppy_t *floppy = drive->driver_data; if (drive->usage > 1) { /* Don't format if someone is using the disk */ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); return -EBUSY; } else { int rc; set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); rc=idefloppy_begin_format(drive, inode, file, (int *)arg); if (rc) clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); return (rc); /* ** Note, the bit will be cleared when the device is ** closed. This is the cleanest way to handle the ** situation where the drive does not support ** format progress reporting. */ } } case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS: return (idefloppy_get_format_progress(drive, inode, file, (int *)arg)); } return -EIO;}/* * Our open/release functions */static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Reached idefloppy_open\n");#endif /* IDEFLOPPY_DEBUG_LOG */ MOD_INC_USE_COUNT; if (drive->usage == 1) { clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); /* Just in case */ idefloppy_create_test_unit_ready_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { idefloppy_create_start_stop_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); } if (idefloppy_get_capacity (drive) && (filp->f_flags & O_NDELAY) == 0 /* ** Allow O_NDELAY to open a drive without a disk, or with ** an unreadable disk, so that we can get the format ** capacity of the drive or begin the format - Sam */ ) { drive->usage--; MOD_DEC_USE_COUNT; return -EIO; } if (floppy->wp && (filp->f_mode & 2)) { drive->usage--; MOD_DEC_USE_COUNT; return -EROFS; } set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); } check_disk_change(inode->i_rdev); } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { drive->usage--; MOD_DEC_USE_COUNT; return -EBUSY; } return 0;}static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive){ idefloppy_pc_t pc; #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Reached idefloppy_release\n");#endif /* IDEFLOPPY_DEBUG_LOG */ if (!drive->usage) { idefloppy_floppy_t *floppy = drive->driver_data; invalidate_bdev (inode->i_bdev, 0); /* IOMEGA Clik! drives do not support lock/unlock commands */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); } clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); } MOD_DEC_USE_COUNT;}/* * Check media change. Use a simple algorithm for now. */static int idefloppy_media_change (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);}/* * Revalidate the new media. Should set blk_size[] */static void idefloppy_revalidate (ide_drive_t *drive){ grok_partitions(HWIF(drive)->gd, drive->select.b.unit, 1<<PARTN_BITS, current_capacity(drive));}/* * Return the current floppy capacity to ide.c. */static unsigned long idefloppy_capacity (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; unsigned long capacity = floppy->blocks * floppy->bs_factor; return capacity;}/* * idefloppy_identify_device checks if we can support a drive, * based on the ATAPI IDENTIFY command results. */static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id){ struct idefloppy_id_gcw gcw;#if IDEFLOPPY_DEBUG_INFO unsigned short mask,i; char buffer[80];#endif /* IDEFLOPPY_DEBUG_INFO */ *((unsigned short *) &gcw) = id->config;#ifdef CONFIG_PPC /* kludge for Apple PowerBook internal zip */ if ((gcw.device_type == 5) && !strstr(id->model, "CD-ROM") && strstr(id->model, "ZIP")) gcw.device_type = 0; #endif#if IDEFLOPPY_DEBUG_INFO printk (KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n"); switch (gcw.protocol) { case 0: case 1: sprintf (buffer, "ATA");break; case 2: sprintf (buffer, "ATAPI");break; case 3: sprintf (buffer, "Reserved (Unknown to ide-floppy)");break; } printk (KERN_INFO "Protocol Type: %s\n", buffer); switch (gcw.device_type) { case 0: sprintf (buffer, "Direct-access Device");break; case 1: sprintf (buffer, "Streaming Tape Device");break; case 2: case 3: case 4: sprintf (buffer, "Reserved");break; case 5: sprintf (buffer, "CD-ROM Device");break; case 6: sprintf (buffer, "Reserved"); case 7: sprintf (buffer, "Optical memory Device");break; case 0x1f: sprintf (buffer, "Unknown or no Device type");break; default: sprintf (buffer, "Reserved"); } printk (KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer); printk (KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No"); switch (gcw.drq_type) { case 0: sprintf (buffer, "Microprocessor DRQ");break; case 1: sprintf (buffer, "Interrupt DRQ");break; case 2: sprintf (buffer, "Accelerated DRQ");break; case 3: sprintf (buffer, "Reserved");break; } printk (KERN_INFO "Command Packet DRQ Type: %s\n", buffer); switch (gcw.packet_size) { case 0: sprintf (buffer, "12 bytes");break; case 1: sprintf (buffer, "16 bytes");break; default: sprintf (buffer, "Reserved");break; } printk (KERN_INFO "Command Packet Size: %s\n", buffer); printk (KERN_INFO "Model: %.40s\n",id->model); printk (KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev); printk (KERN_INFO "Serial Number: %.20s\n",id->serial_no); printk (KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512); printk (KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n"); printk (KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n"); printk (KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n"); printk (KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n"); printk (KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n"); printk (KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO); printk (KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA); printk (KERN_INFO "Single Word DMA supported modes:\n"); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_1word & mask) printk (KERN_INFO " Mode %d%s\n", i, (id->dma_1word & (mask << 8)) ? " (active)" : ""); } printk (KERN_INFO "Multi Word DMA supported modes:\n"); for (i=0,mask=1;i<8;i++,mask=mask << 1) { if (id->dma_mword & mask) printk (KERN_INFO " Mode %d%s\n", i, (id->dma_mword & (mask << 8)) ? " (active)" : ""); } if (id->field_valid & 0x0002) { printk (KERN_INFO "Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None"); if (id->eide_dma_min == 0) sprintf (buffer, "Not supported"); else sprintf (buffer, "%d ns",id->eide_dma_min); printk (KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer); if (id->eide_dma_time == 0) sprintf (buffer, "Not supported"); else sprintf (buffer, "%d ns",id->eide_dma_time); printk (KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer); if (id->eide_pio == 0) sprintf (buffer, "Not supported"); else sprintf (buffer, "%d ns",id->eide_pio); printk (KERN_INFO "Minimum PIO cycle without IORDY: %s\n", buffer); if (id->eide_pio_iordy == 0) sprintf (buffer, "Not supported"); else sprintf (buffer, "%d ns",id->eide_pio_iordy); printk (KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer); } else printk (KERN_INFO "According to the device, fields 64-70 are not valid.\n");#endif /* IDEFLOPPY_DEBUG_INFO */ if (gcw.protocol != 2) printk (KERN_ERR "ide-floppy: Protocol is not ATAPI\n"); else if (gcw.device_type != 0) printk (KERN_ERR "ide-floppy: Device type is not set to floppy\n"); else if (!gcw.removable) printk (KERN_ERR "ide-floppy: The removable flag is not set\n"); else if (gcw.drq_type == 3) { printk (KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type); } else if (gcw.packet_size != 0) { printk (KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n"); } else return 1; return 0;}static void idefloppy_add_settings(ide_drive_t *drive){ int major = HWIF(drive)->major; int minor = drive->select.b.unit << PARTN_BITS; ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);}/* * Driver initialization. */static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy){ struct idefloppy_id_gcw gcw; int major = HWIF(drive)->major, i; int minor = drive->select.b.unit << PARTN_BITS; *((unsigned short *) &gcw) = drive->id->config; drive->driver_data = floppy; drive->ready_stat = 0; memset (floppy, 0, sizeof (idefloppy_floppy_t)); floppy->drive = drive; floppy->pc = floppy->pc_stack; if (gcw.drq_type == 1) set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags); /* * We used to check revisions here. At this point however * I'm giving up. Just assume they are all broken, its easier. * * The actual reason for the workarounds was likely * a driver bug after all rather than a firmware bug, * and the workaround below used to hide it. It should * be fixed as of version 1.9, but to be on the safe side * we'll leave the limitation below for the 2.2.x tree. */ if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0) { for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } /* * Guess what? The IOMEGA Clik! drive also needs the * above fix. It makes nasty clicking noises without * it, so please don't remove this. */ if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) { for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); } /* * Guess what? The IOMEGA Clik! drive also needs the * above fix. It makes nasty clicking noises witho
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -