📄 ide-floppy.c
字号:
drive->using_dma ? ", DMA":""); } floppy->capacity = *descriptor; if (!length || length % 512) printk (KERN_ERR "%s: %d bytes block size not supported\n", drive->name, length); else { floppy->blocks = blocks; floppy->block_size = length; if ((floppy->bs_factor = length / 512) != 1) printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name); rc = 0; } }#if IDEFLOPPY_DEBUG_INFO if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc); printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length);#endif /* IDEFLOPPY_DEBUG_INFO */ } (void) idefloppy_get_flexible_disk_page (drive); drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; return rc;}/* * 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; if (cmd == CDROMEJECT) { if (drive->usage > 1) return -EBUSY; idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); idefloppy_create_start_stop_cmd (&pc, 2); (void) idefloppy_queue_pc_tail (drive, &pc); return 0; } 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) { 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)) { 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); idefloppy_create_prevent_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); check_disk_change(inode->i_rdev); } 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) { invalidate_buffers (inode->i_rdev); idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); } 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; } (void) idefloppy_get_capacity (drive); idefloppy_add_settings(drive); for (i = 0; i < MAX_DRIVES; ++i) { ide_hwif_t *hwif = HWIF(drive); if (drive != &hwif->drives[i]) continue; hwif->gd->de_arr[i] = drive->de; if (drive->removable) hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; break; }}static int idefloppy_cleanup (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; if (ide_unregister_subdriver (drive)) return 1; drive->driver_data = NULL; kfree (floppy); return 0;}#ifdef CONFIG_PROC_FSstatic ide_proc_entry_t idefloppy_proc[] = { { "geometry", S_IFREG|S_IRUGO, proc_ide_read_geometry, NULL }, { NULL, 0, NULL, NULL }};#else#define idefloppy_proc NULL#endif /* CONFIG_PROC_FS *//* * IDE subdriver functions, registered with ide.c */static ide_driver_t idefloppy_driver = { "ide-floppy", /* name */ IDEFLOPPY_VERSION, /* version */ ide_floppy, /* media */ 0, /* busy */ 1, /* supports_dma */ 0, /* supports_dsc_overlap */ idefloppy_cleanup, /* cleanup */ idefloppy_do_request, /* do_request */ idefloppy_end_request, /* end_request */ idefloppy_ioctl, /* ioctl */ idefloppy_open, /* open */ idefloppy_release, /* release */ idefloppy_media_change, /* media_change */ idefloppy_revalidate, /* media_change */ NULL, /* pre_reset */ idefloppy_capacity, /* capacity */ NULL, /* special */ idefloppy_proc /* proc */};int idefloppy_init (void);static ide_module_t idefloppy_module = { IDE_DRIVER_MODULE, idefloppy_init, &idefloppy_driver, NULL};/* * idefloppy_init will register the driver for each floppy. */int idefloppy_init (void){ ide_drive_t *drive; idefloppy_floppy_t *floppy; int failed = 0; MOD_INC_USE_COUNT; while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, NULL, failed++)) != NULL) { if (!idefloppy_identify_device (drive, drive->id)) { printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name); continue; } if (drive->scsi) { printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); continue; } if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); continue; } if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); kfree (floppy); continue; } idefloppy_setup (drive, floppy); failed--; } ide_register_module(&idefloppy_module); MOD_DEC_USE_COUNT; return 0;}#ifdef MODULEint init_module (void){ return idefloppy_init ();}void cleanup_module (void){ ide_drive_t *drive; int failed = 0; while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) { if (idefloppy_cleanup (drive)) { printk ("%s: cleanup_module() called while still busy\n", drive->name); failed++; } /* We must remove proc entries defined in this module. Otherwise we oops while accessing these entries */ if (drive->proc) ide_remove_proc_entries(drive->proc, idefloppy_proc); } ide_unregister_module(&idefloppy_module);}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -