⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
			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 + -