📄 ide-floppy.c
字号:
{ idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD;}static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector){ int block = sector / floppy->bs_factor; int blocks = rq->nr_sectors / floppy->bs_factor; #if IDEFLOPPY_DEBUG_LOG printk ("create_rw1%d_cmd: block == %d, blocks == %d\n", 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks);#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc (pc); if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) { pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD; put_unaligned (htonl (blocks), (unsigned int *) &pc->c[6]); } else { pc->c[0] = rq->cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD; put_unaligned (htons (blocks), (unsigned short *) &pc->c[7]); } put_unaligned (htonl (block), (unsigned int *) &pc->c[2]); pc->callback = &idefloppy_rw_callback; pc->rq = rq; pc->b_data = rq->buffer; pc->b_count = rq->cmd == READ ? 0 : rq->bh->b_size; if (rq->cmd == WRITE) set_bit (PC_WRITING, &pc->flags); pc->buffer = NULL; pc->request_transfer = pc->buffer_size = blocks * floppy->block_size; set_bit (PC_DMA_RECOMMENDED, &pc->flags);}/* * idefloppy_do_request is our request handling function. */static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, unsigned long block){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t *pc;#if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);#endif /* IDEFLOPPY_DEBUG_LOG */ if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc != NULL) printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", drive->name, floppy->failed_pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); else printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); idefloppy_end_request (0, HWGROUP(drive)); return ide_stopped; } switch (rq->cmd) { case READ: case WRITE: if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) { printk ("%s: unsupported r/w request size\n", drive->name); idefloppy_end_request (0, HWGROUP(drive)); return ide_stopped; } pc = idefloppy_next_pc_storage (drive); idefloppy_create_rw_cmd (floppy, pc, rq, block); break; case IDEFLOPPY_PC_RQ: pc = (idefloppy_pc_t *) rq->buffer; break; default: printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd); idefloppy_end_request (0,HWGROUP (drive)); return ide_stopped; } pc->rq = rq; return idefloppy_issue_pc (drive, pc);}/* * idefloppy_queue_pc_tail adds a special packet command request to the * tail of the request queue, and waits for it to be serviced. */static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc){ struct request rq; ide_init_drive_cmd (&rq); rq.buffer = (char *) pc; rq.cmd = IDEFLOPPY_PC_RQ; return ide_do_drive_cmd (drive, &rq, ide_wait);}/* * Look at the flexible disk page parameters. We will ignore the CHS * capacity parameters and use the LBA parameters instead. */static int idefloppy_get_flexible_disk_page (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; idefloppy_mode_parameter_header_t *header; idefloppy_flexible_disk_page_t *page; int capacity, lba_capacity; idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT); if (idefloppy_queue_pc_tail (drive,&pc)) { printk (KERN_ERR "ide-floppy: Can't get flexible disk page parameters\n"); return 1; } header = (idefloppy_mode_parameter_header_t *) pc.buffer; floppy->wp = header->wp; page = (idefloppy_flexible_disk_page_t *) (header + 1); page->transfer_rate = ntohs (page->transfer_rate); page->sector_size = ntohs (page->sector_size); page->cyls = ntohs (page->cyls); page->rpm = ntohs (page->rpm); capacity = page->cyls * page->heads * page->sectors * page->sector_size; if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t))) printk (KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, %d sector size, %d rpm\n", drive->name, capacity / 1024, page->cyls, page->heads, page->sectors, page->transfer_rate / 8, page->sector_size, page->rpm); floppy->flexible_disk_page = *page; drive->bios_cyl = page->cyls; drive->bios_head = page->heads; drive->bios_sect = page->sectors; lba_capacity = floppy->blocks * floppy->block_size; if (capacity < lba_capacity) { printk (KERN_NOTICE "%s: The disk reports a capacity of %d bytes, " "but the drive only handles %d\n", drive->name, lba_capacity, capacity); floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0; } return 0;}static int idefloppy_get_capability_page(ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; idefloppy_mode_parameter_header_t *header; idefloppy_capabilities_page_t *page; floppy->srfp=0; idefloppy_create_mode_sense_cmd (&pc, IDEFLOPPY_CAPABILITIES_PAGE, MODE_SENSE_CURRENT); set_bit(PC_SUPPRESS_ERROR, &pc.flags); if (idefloppy_queue_pc_tail (drive,&pc)) { return 1; } header = (idefloppy_mode_parameter_header_t *) pc.buffer; page= (idefloppy_capabilities_page_t *)(header+1); floppy->srfp=page->srfp; return (0);}/* * Determine if a media is present in the floppy drive, and if so, * its LBA capacity. */static int idefloppy_get_capacity (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; idefloppy_capacity_header_t *header; idefloppy_capacity_descriptor_t *descriptor; int i, descriptors, rc = 1, blocks, length; drive->bios_cyl = 0; drive->bios_head = drive->bios_sect = 0; floppy->blocks = floppy->bs_factor = 0; drive->part[0].nr_sects = 0; idefloppy_create_read_capacity_cmd (&pc); if (idefloppy_queue_pc_tail (drive, &pc)) { printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return 1; } header = (idefloppy_capacity_header_t *) pc.buffer; descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t); descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); for (i = 0; i < descriptors; i++, descriptor++) { blocks = descriptor->blocks = ntohl (descriptor->blocks); length = descriptor->length = ntohs (descriptor->length); if (!i) { switch (descriptor->dc) { case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */ case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length); floppy->capacity = *descriptor; if (!length || length % 512) printk (KERN_NOTICE "%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; } break; case CAPACITY_NO_CARTRIDGE: /* This is a KERN_ERR so it appears on screen for the user to see */ printk (KERN_ERR "%s: No disk in drive\n", drive->name); break; case CAPACITY_INVALID: printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name); break; } } if (!i) { IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc); } IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); } /* Clik! disk does not support get_flexible_disk_page */ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { (void) idefloppy_get_flexible_disk_page (drive); } drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; return rc;}/*** Obtain the list of formattable capacities.** Very similar to idefloppy_get_capacity, except that we push the capacity** descriptors to userland, instead of our own structures.**** Userland gives us the following structure:**** struct idefloppy_format_capacities {** int nformats;** struct {** int nblocks;** int blocksize;** } formats[];** } ;**** userland initializes nformats to the number of allocated formats[]** records. On exit we set nformats to the number of records we've** actually initialized.***/static int idefloppy_get_format_capacities (ide_drive_t *drive, struct inode *inode, struct file *file, int *arg) /* Cheater */{ idefloppy_pc_t pc; idefloppy_capacity_header_t *header; idefloppy_capacity_descriptor_t *descriptor; int i, descriptors, blocks, length; int u_array_size; int u_index; int *argp; if (get_user(u_array_size, arg)) return (-EFAULT); if (u_array_size <= 0) return (-EINVAL); idefloppy_create_read_capacity_cmd (&pc); if (idefloppy_queue_pc_tail (drive, &pc)) { printk (KERN_ERR "ide-floppy: Can't get floppy parameters\n"); return (-EIO); } header = (idefloppy_capacity_header_t *) pc.buffer; descriptors = header->length / sizeof (idefloppy_capacity_descriptor_t); descriptor = (idefloppy_capacity_descriptor_t *) (header + 1); u_index=0; argp=arg+1; /* ** We always skip the first capacity descriptor. That's the ** current capacity. We are interested in the remaining descriptors, ** the formattable capacities. */ for (i=0; i<descriptors; i++, descriptor++) { if (u_index >= u_array_size) break; /* User-supplied buffer too small */ if (i == 0) continue; /* Skip the first descriptor */ blocks = ntohl (descriptor->blocks); length = ntohs (descriptor->length); if (put_user(blocks, argp)) return (-EFAULT); ++argp; if (put_user(length, argp)) return (-EFAULT); ++argp; ++u_index; } if (put_user(u_index, arg)) return (-EFAULT); return (0);}/*** Send ATAPI_FORMAT_UNIT to the drive.**** Userland gives us the following structure:**** struct idefloppy_format_command {** int nblocks;** int blocksize;** int flags;** } ;**** flags is a bitmask, currently, the only defined flag is:**** 0x01 - verify media after format.*/static int idefloppy_begin_format(ide_drive_t *drive, struct inode *inode, struct file *file, int *arg){ int blocks; int length; int flags; idefloppy_pc_t pc; if (get_user(blocks, arg) || get_user(length, arg+1) || get_user(flags, arg+2)) { return (-EFAULT); } (void) idefloppy_get_capability_page (drive); /* Get the SFRP bit */ idefloppy_create_format_unit_cmd(&pc, blocks, length, flags); if (idefloppy_queue_pc_tail (drive, &pc)) { return (-EIO); } return (0);}/*** Get ATAPI_FORMAT_UNIT progress indication.**** Userland gives a pointer to an int. The int is set to a progresss** indicator 0-65536, with 65536=100%.**** If the drive does not support format progress indication, we just check** the dsc bit, and return either 0 or 65536.*/static int idefloppy_get_format_progress(ide_drive_t *drive, struct inode *inode, struct file *file, int *arg){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; int progress_indication=0x10000; if (floppy->srfp) { idefloppy_create_request_sense_cmd(&pc); if (idefloppy_queue_pc_tail (drive, &pc)) { return (-EIO); } if (floppy->sense_key == 2 && floppy->asc == 4 && floppy->ascq == 4) { progress_indication=floppy->progress_indication; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -