📄 ide-floppy.c
字号:
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 u16 mask,i; char buffer[80];#endif /* IDEFLOPPY_DEBUG_INFO */ *((u16 *) &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;}#ifdef CONFIG_IDE_PROC_FSstatic void idefloppy_add_settings(ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data;/* * drive setting name read/write data type min max mul_factor div_factor data pointer set function */ ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL);}#elsestatic inline void idefloppy_add_settings(ide_drive_t *drive) { ; }#endif/* * Driver initialization. */static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy){ struct idefloppy_id_gcw gcw; *((u16 *) &gcw) = drive->id->config; 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 (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) { set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags); /* This value will be visible in the /proc/ide/hdx/settings */ floppy->ticks = IDEFLOPPY_TICKS_DELAY; blk_queue_max_sectors(drive->queue, 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 (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) { blk_queue_max_sectors(drive->queue, 64); set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); } (void) idefloppy_get_capacity(drive); idefloppy_add_settings(drive);}static void ide_floppy_remove(ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; struct gendisk *g = floppy->disk; ide_proc_unregister_driver(drive, floppy->driver); del_gendisk(g); ide_floppy_put(floppy);}static void ide_floppy_release(struct kref *kref){ struct ide_floppy_obj *floppy = to_ide_floppy(kref); ide_drive_t *drive = floppy->drive; struct gendisk *g = floppy->disk; drive->driver_data = NULL; g->private_data = NULL; put_disk(g); kfree(floppy);}#ifdef CONFIG_IDE_PROC_FSstatic int proc_idefloppy_read_capacity (char *page, char **start, off_t off, int count, int *eof, void *data){ ide_drive_t*drive = (ide_drive_t *)data; int len; len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive)); PROC_IDE_READ_RETURN(page,start,off,count,eof,len);}static ide_proc_entry_t idefloppy_proc[] = { { "capacity", S_IFREG|S_IRUGO, proc_idefloppy_read_capacity, NULL }, { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL }};#endif /* CONFIG_IDE_PROC_FS */static int ide_floppy_probe(ide_drive_t *);static ide_driver_t idefloppy_driver = { .gen_driver = { .owner = THIS_MODULE, .name = "ide-floppy", .bus = &ide_bus_type, }, .probe = ide_floppy_probe, .remove = ide_floppy_remove, .version = IDEFLOPPY_VERSION, .media = ide_floppy, .supports_dsc_overlap = 0, .do_request = idefloppy_do_request, .end_request = idefloppy_do_end_request, .error = __ide_error, .abort = __ide_abort,#ifdef CONFIG_IDE_PROC_FS .proc = idefloppy_proc,#endif};static int idefloppy_open(struct inode *inode, struct file *filp){ struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_floppy_obj *floppy; ide_drive_t *drive; idefloppy_pc_t pc; int ret = 0; debug_log(KERN_INFO "Reached idefloppy_open\n"); if (!(floppy = ide_floppy_get(disk))) return -ENXIO; drive = floppy->drive; floppy->openers++; if (floppy->openers == 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 */ ) { ret = -EIO; goto out_put_floppy; } if (floppy->wp && (filp->f_mode & 2)) { ret = -EROFS; goto out_put_floppy; } 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_bdev); } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) { ret = -EBUSY; goto out_put_floppy; } return 0;out_put_floppy: floppy->openers--; ide_floppy_put(floppy); return ret;}static int idefloppy_release(struct inode *inode, struct file *filp){ struct gendisk *disk = inode->i_bdev->bd_disk; struct ide_floppy_obj *floppy = ide_floppy_g(disk); ide_drive_t *drive = floppy->drive; idefloppy_pc_t pc; debug_log(KERN_INFO "Reached idefloppy_release\n"); if (floppy->openers == 1) { /* 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); } floppy->openers--; ide_floppy_put(floppy); return 0;}static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo){ struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); ide_drive_t *drive = floppy->drive; geo->heads = drive->bios_head; geo->sectors = drive->bios_sect; geo->cylinders = (u16)drive->bios_cyl; /* truncate */ return 0;}static int idefloppy_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct block_device *bdev = inode->i_bdev; struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); ide_drive_t *drive = floppy->drive; void __user *argp = (void __user *)arg; int err; int prevent = (arg) ? 1 : 0; idefloppy_pc_t pc; switch (cmd) { case CDROMEJECT: prevent = 0; /* fall through */ case CDROM_LOCKDOOR: if (floppy->openers > 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, argp); case IDEFLOPPY_IOCTL_FORMAT_START: if (!(file->f_mode & 2)) return -EPERM; if (floppy->openers > 1) { /* Don't format if someone is using the disk */ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); return -EBUSY; } set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); err = idefloppy_begin_format(drive, argp); if (err) clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); return err; /* ** 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, argp); } /* * skip SCSI_IOCTL_SEND_COMMAND (deprecated) * and CDROM_SEND_PACKET (legacy) ioctls */ if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND) err = scsi_cmd_ioctl(file, bdev->bd_disk->queue, bdev->bd_disk, cmd, argp); else err
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -