📄 sd.c
字号:
start_lba >>= 3; break; default: /* Print something here with limiting frequency. */ goto out; break; } /* This computation should always be done in terms of * the resolution of the device's medium. */ good_bytes = (bad_lba - start_lba)*SCpnt->device->sector_size; break; case RECOVERED_ERROR: case NO_SENSE: /* Inform the user, but make sure that it's not treated * as a hard error. */ scsi_print_sense("sd", SCpnt); SCpnt->result = 0; memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); good_bytes = xfer_size; break; case ILLEGAL_REQUEST: if (SCpnt->device->use_10_for_rw && (SCpnt->cmnd[0] == READ_10 || SCpnt->cmnd[0] == WRITE_10)) SCpnt->device->use_10_for_rw = 0; if (SCpnt->device->use_10_for_ms && (SCpnt->cmnd[0] == MODE_SENSE_10 || SCpnt->cmnd[0] == MODE_SELECT_10)) SCpnt->device->use_10_for_ms = 0; break; default: break; } out: return good_bytes;}static int media_not_present(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr){ if (!scsi_sense_valid(sshdr)) return 0; /* not invoked for commands that could return deferred errors */ if (sshdr->sense_key != NOT_READY && sshdr->sense_key != UNIT_ATTENTION) return 0; if (sshdr->asc != 0x3A) /* medium not present */ return 0; set_media_not_present(sdkp); return 1;}/* * spinup disk - called only in sd_revalidate_disk() */static voidsd_spinup_disk(struct scsi_disk *sdkp){ unsigned char cmd[10]; unsigned long spintime_expire = 0; int retries, spintime; unsigned int the_result; struct scsi_sense_hdr sshdr; int sense_valid = 0; spintime = 0; /* Spin up drives, as required. Only do this at boot time */ /* Spinup needs to be done for module loads too. */ do { retries = 0; do { cmd[0] = TEST_UNIT_READY; memset((void *) &cmd[1], 0, 9); the_result = scsi_execute_req(sdkp->device, cmd, DMA_NONE, NULL, 0, &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); /* * If the drive has indicated to us that it * doesn't have any media in it, don't bother * with any more polling. */ if (media_not_present(sdkp, &sshdr)) return; if (the_result) sense_valid = scsi_sense_valid(&sshdr); retries++; } while (retries < 3 && (!scsi_status_is_good(the_result) || ((driver_byte(the_result) & DRIVER_SENSE) && sense_valid && sshdr.sense_key == UNIT_ATTENTION))); if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { /* no sense, TUR either succeeded or failed * with a status error */ if(!spintime && !scsi_status_is_good(the_result)) { sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n"); sd_print_result(sdkp, the_result); } break; } /* * The device does not want the automatic start to be issued. */ if (sdkp->device->no_start_on_add) { break; } /* * If manual intervention is required, or this is an * absent USB storage device, a spinup is meaningless. */ if (sense_valid && sshdr.sense_key == NOT_READY && sshdr.asc == 4 && sshdr.ascq == 3) { break; /* manual intervention required */ /* * Issue command to spin up drive when not ready */ } else if (sense_valid && sshdr.sense_key == NOT_READY) { if (!spintime) { sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); cmd[0] = START_STOP; cmd[1] = 1; /* Return immediately */ memset((void *) &cmd[2], 0, 8); cmd[4] = 1; /* Start spin cycle */ scsi_execute_req(sdkp->device, cmd, DMA_NONE, NULL, 0, &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); spintime_expire = jiffies + 100 * HZ; spintime = 1; } /* Wait 1 second for next try */ msleep(1000); printk("."); /* * Wait for USB flash devices with slow firmware. * Yes, this sense key/ASC combination shouldn't * occur here. It's characteristic of these devices. */ } else if (sense_valid && sshdr.sense_key == UNIT_ATTENTION && sshdr.asc == 0x28) { if (!spintime) { spintime_expire = jiffies + 5 * HZ; spintime = 1; } /* Wait 1 second for next try */ msleep(1000); } else { /* we don't understand the sense code, so it's * probably pointless to loop */ if(!spintime) { sd_printk(KERN_NOTICE, sdkp, "Unit Not Ready\n"); sd_print_sense_hdr(sdkp, &sshdr); } break; } } while (spintime && time_before_eq(jiffies, spintime_expire)); if (spintime) { if (scsi_status_is_good(the_result)) printk("ready\n"); else printk("not responding...\n"); }}/* * read disk capacity */static voidsd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer){ unsigned char cmd[16]; int the_result, retries; int sector_size = 0; int longrc = 0; struct scsi_sense_hdr sshdr; int sense_valid = 0; struct scsi_device *sdp = sdkp->device;repeat: retries = 3; do { if (longrc) { memset((void *) cmd, 0, 16); cmd[0] = SERVICE_ACTION_IN; cmd[1] = SAI_READ_CAPACITY_16; cmd[13] = 12; memset((void *) buffer, 0, 12); } else { cmd[0] = READ_CAPACITY; memset((void *) &cmd[1], 0, 9); memset((void *) buffer, 0, 8); } the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, buffer, longrc ? 12 : 8, &sshdr, SD_TIMEOUT, SD_MAX_RETRIES); if (media_not_present(sdkp, &sshdr)) return; if (the_result) sense_valid = scsi_sense_valid(&sshdr); retries--; } while (the_result && retries); if (the_result && !longrc) { sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n"); sd_print_result(sdkp, the_result); if (driver_byte(the_result) & DRIVER_SENSE) sd_print_sense_hdr(sdkp, &sshdr); else sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n"); /* Set dirty bit for removable devices if not ready - * sometimes drives will not report this properly. */ if (sdp->removable && sense_valid && sshdr.sense_key == NOT_READY) sdp->changed = 1; /* Either no media are present but the drive didn't tell us, or they are present but the read capacity command fails */ /* sdkp->media_present = 0; -- not always correct */ sdkp->capacity = 0; /* unknown mapped to zero - as usual */ return; } else if (the_result && longrc) { /* READ CAPACITY(16) has been failed */ sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n"); sd_print_result(sdkp, the_result); sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n"); sdkp->capacity = 1 + (sector_t) 0xffffffff; goto got_data; } if (!longrc) { sector_size = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; if (buffer[0] == 0xff && buffer[1] == 0xff && buffer[2] == 0xff && buffer[3] == 0xff) { if(sizeof(sdkp->capacity) > 4) { sd_printk(KERN_NOTICE, sdkp, "Very big device. " "Trying to use READ CAPACITY(16).\n"); longrc = 1; goto repeat; } sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use " "a kernel compiled with support for large " "block devices.\n"); sdkp->capacity = 0; goto got_data; } sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); } else { sdkp->capacity = 1 + (((u64)buffer[0] << 56) | ((u64)buffer[1] << 48) | ((u64)buffer[2] << 40) | ((u64)buffer[3] << 32) | ((sector_t)buffer[4] << 24) | ((sector_t)buffer[5] << 16) | ((sector_t)buffer[6] << 8) | (sector_t)buffer[7]); sector_size = (buffer[8] << 24) | (buffer[9] << 16) | (buffer[10] << 8) | buffer[11]; } /* Some devices return the total number of sectors, not the * highest sector number. Make the necessary adjustment. */ if (sdp->fix_capacity) { --sdkp->capacity; /* Some devices have version which report the correct sizes * and others which do not. We guess size according to a heuristic * and err on the side of lowering the capacity. */ } else { if (sdp->guess_capacity) if (sdkp->capacity & 0x01) /* odd sizes are odd */ --sdkp->capacity; }got_data: if (sector_size == 0) { sector_size = 512; sd_printk(KERN_NOTICE, sdkp, "Sector size 0 reported, " "assuming 512.\n"); } if (sector_size != 512 && sector_size != 1024 && sector_size != 2048 && sector_size != 4096 && sector_size != 256) { sd_printk(KERN_NOTICE, sdkp, "Unsupported sector size %d.\n", sector_size); /* * The user might want to re-format the drive with * a supported sectorsize. Once this happens, it * would be relatively trivial to set the thing up. * For this reason, we leave the thing in the table. */ sdkp->capacity = 0; /* * set a bogus sector size so the normal read/write * logic in the block layer will eventually refuse any * request on this device without tripping over power * of two sector size assumptions */ sector_size = 512; } { /* * The msdos fs needs to know the hardware sector size * So I have created this table. See ll_rw_blk.c * Jacques Gelinas (Jacques@solucorp.qc.ca) */ int hard_sector = sector_size; sector_t sz = (sdkp->capacity/2) * (hard_sector/256); struct request_queue *queue = sdp->request_queue; sector_t mb = sz; blk_queue_hardsect_size(queue, hard_sector); /* avoid 64-bit division on 32-bit platforms */ sector_div(sz, 625); mb -= sz - 974; sector_div(mb, 1950); sd_printk(KERN_NOTICE, sdkp, "%llu %d-byte hardware sectors (%llu MB)\n", (unsigned long long)sdkp->capacity, hard_sector, (unsigned long long)mb); } /* Rescale capacity to 512-byte units */ if (sector_size == 4096) sdkp->capacity <<= 3; else if (sector_size == 2048) sdkp->capacity <<= 2; else if (sector_size == 1024) sdkp->capacity <<= 1; else if (sector_size == 256) sdkp->capacity >>= 1; sdkp->device->sector_size = sector_size;}/* called with buffer of length 512 */static inline intsd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage, unsigned char *buffer, int len, struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr){ return scsi_mode_sense(sdp, dbd, modepage, buffer, len, SD_TIMEOUT, SD_MAX_RETRIES, data, sshdr);}/* * read write protect setting, if possible - called only in sd_revalidate_disk() * called with buffer of length SD_BUF_SIZE */static voidsd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer){ int res; struct scsi_device *sdp = sdkp->device; struct scsi_mode_data data; set_disk_ro(sdkp->disk, 0); if (sdp->skip_ms_page_3f) { sd_printk(KERN_NOTICE, sdkp, "Assuming Write Enabled\n"); return; } if (sdp->use_192_bytes_for_3f) { res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL); } else { /* * First attempt: ask for all pages (0x3F), but only 4 bytes. * We have to start carefully: some devices hang if we ask * for more than is available. */ res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL); /* * Second attempt: ask for page 0 When only page 0 is * implemented, a request for page 3F may return Sense Key * 5: Illegal Request, Sense Code 24: Invalid field in * CDB. */ if (!scsi_status_is_good(res)) res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL); /* * Third attempt: ask 255 bytes, as we did earlier. */ if (!scsi_status_is_good(res)) res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255, &data, NULL); } if (!scsi_status_is_good(res)) { sd_printk(KERN_WARNING, sdkp, "Test WP failed, assume Write Enabled\n"); } else { sdkp->write_prot = ((data.device_specific & 0x80) != 0); set_disk_ro(sdkp->disk, sdkp->write_prot); sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", sdkp->write_prot ? "on" : "off"); sd_printk(KERN_DEBUG, sdkp, "Mode Sense: %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3]); }}/* * sd_read_cache_type - called only from sd_revalidate_disk() * called with buffer of length SD_BUF_SIZE */static voidsd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer){ int len = 0, res; struct scsi_device *sdp = sdkp->device; int dbd; int modepage; struct scsi_mode_data data; struct scsi_sense_hdr sshdr; if (sdp->skip_ms_page_8) goto defaults; if (sdp->type == TYPE_RBC) { modepage = 6; dbd = 8; } else { modepage = 8; dbd = 0; } /* cautiously ask */ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); if (!scsi_status_is_good(res)) goto bad_sense; if (!data.header_length) { modepage = 6; sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); } /* that went OK, now ask for the proper length */ len = data.length; /* * We're only interested in the first three bytes, actually. * But the data cache page is defined for the first 20. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -