欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

sd.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 3 页
字号:
		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) {				printk(KERN_NOTICE "%s : very big device. try to use"				       " READ CAPACITY(16).\n", diskname);				longrc = 1;				goto repeat;			} else {				printk(KERN_ERR "%s: too big for kernel.  Assuming maximum 2Tb\n", diskname);			}		}		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];	}	got_data:	if (sector_size == 0) {		sector_size = 512;		printk(KERN_NOTICE "%s : sector size 0 reported, "		       "assuming 512.\n", diskname);	}	if (sector_size != 512 &&	    sector_size != 1024 &&	    sector_size != 2048 &&	    sector_size != 4096 &&	    sector_size != 256) {		printk(KERN_NOTICE "%s : unsupported sector size "		       "%d.\n", diskname, 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;	}	{		/*		 * 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 * (hard_sector/256);		request_queue_t *queue = sdp->request_queue;		sector_t mb;		blk_queue_hardsect_size(queue, hard_sector);		/* avoid 64-bit division on 32-bit platforms */		mb = sz >> 1;		sector_div(sz, 1250);		mb -= sz - 974;		sector_div(mb, 1950);		printk(KERN_NOTICE "SCSI device %s: "		       "%llu %d-byte hdwr sectors (%llu MB)\n",		       diskname, (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_request *SRpnt, int dbd, int modepage,		 unsigned char *buffer, int len, struct scsi_mode_data *data){	return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len,				 SD_TIMEOUT, SD_MAX_RETRIES, data);}/* * read write protect setting, if possible - called only in sd_revalidate_disk() * called with buffer of length 512 */static voidsd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,		   struct scsi_request *SRpnt, unsigned char *buffer) {	int res;	struct scsi_mode_data data;	set_disk_ro(sdkp->disk, 0);	if (sdkp->device->skip_ms_page_3f) {		printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname);		return;	}	if (sdkp->device->use_192_bytes_for_3f) {		res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data);	} 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(SRpnt, 0, 0x3F, buffer, 4, &data);		/*		 * 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(SRpnt, 0, 0, buffer, 4, &data);		/*		 * Third attempt: ask 255 bytes, as we did earlier.		 */		if (!scsi_status_is_good(res))			res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255,					       &data);	}	if (!scsi_status_is_good(res)) {		printk(KERN_WARNING		       "%s: test WP failed, assume Write Enabled\n", diskname);	} else {		sdkp->write_prot = ((data.device_specific & 0x80) != 0);		set_disk_ro(sdkp->disk, sdkp->write_prot);		printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname,		       sdkp->write_prot ? "on" : "off");		printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n",		       diskname, buffer[0], buffer[1], buffer[2], buffer[3]);	}}/* * sd_read_cache_type - called only from sd_revalidate_disk() * called with buffer of length 512 */static voidsd_read_cache_type(struct scsi_disk *sdkp, char *diskname,		   struct scsi_request *SRpnt, unsigned char *buffer) {	int len = 0, res;	const int dbd = 0;	   /* DBD */	const int modepage = 0x08; /* current values, cache page */	struct scsi_mode_data data;	if (sdkp->device->skip_ms_page_8)		goto defaults;	/* cautiously ask */	res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);	if (!scsi_status_is_good(res))		goto bad_sense;	/* 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.	 */	if (len < 3)		goto bad_sense;	if (len > 20)		len = 20;	/* Take headers and block descriptors into account */	len += data.header_length + data.block_descriptor_length;	/* Get the data */	res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data);	if (scsi_status_is_good(res)) {		const char *types[] = {			"write through", "none", "write back",			"write back, no read (daft)"		};		int ct = 0;		int offset = data.header_length +			data.block_descriptor_length + 2;		sdkp->WCE = ((buffer[offset] & 0x04) != 0);		sdkp->RCD = ((buffer[offset] & 0x01) != 0);		ct =  sdkp->RCD + 2*sdkp->WCE;		printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n",		       diskname, types[ct]);		return;	}bad_sense:	if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70	     && (SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST	     /* ASC 0x24 ASCQ 0x00: Invalid field in CDB */	     && SRpnt->sr_sense_buffer[12] == 0x24	     && SRpnt->sr_sense_buffer[13] == 0x00) {		printk(KERN_NOTICE "%s: cache data unavailable\n",		       diskname);	} else {		printk(KERN_ERR "%s: asking for cache data failed\n",		       diskname);	}defaults:	printk(KERN_ERR "%s: assuming drive cache: write through\n",	       diskname);	sdkp->WCE = 0;	sdkp->RCD = 0;}/** *	sd_revalidate_disk - called the first time a new disk is seen, *	performs disk spin up, read_capacity, etc. *	@disk: struct gendisk we care about **/static int sd_revalidate_disk(struct gendisk *disk){	struct scsi_disk *sdkp = scsi_disk(disk);	struct scsi_device *sdp = sdkp->device;	struct scsi_request *sreq;	unsigned char *buffer;	SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name));	/*	 * If the device is offline, don't try and read capacity or any	 * of the other niceties.	 */	if (!scsi_device_online(sdp))		goto out;	sreq = scsi_allocate_request(sdp, GFP_KERNEL);	if (!sreq) {		printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation "		       "failure.\n");		goto out;	}	buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA);	if (!buffer) {		printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation "		       "failure.\n");		goto out_release_request;	}	/* defaults, until the device tells us otherwise */	sdp->sector_size = 512;	sdkp->capacity = 0;	sdkp->media_present = 1;	sdkp->write_prot = 0;	sdkp->WCE = 0;	sdkp->RCD = 0;	sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer);	/*	 * Without media there is no reason to ask; moreover, some devices	 * react badly if we do.	 */	if (sdkp->media_present) {		sd_read_capacity(sdkp, disk->disk_name, sreq, buffer);		if (sdp->removable)			sd_read_write_protect_flag(sdkp, disk->disk_name,					sreq, buffer);		sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer);	}			set_capacity(disk, sdkp->capacity);	kfree(buffer); out_release_request: 	scsi_release_request(sreq); out:	return 0;}/** *	sd_probe - called during driver initialization and whenever a *	new scsi device is attached to the system. It is called once *	for each scsi device (not just disks) present. *	@dev: pointer to device object * *	Returns 0 if successful (or not interested in this scsi device  *	(e.g. scanner)); 1 when there is an error. * *	Note: this function is invoked from the scsi mid-level. *	This function sets up the mapping between a given  *	<host,channel,id,lun> (found in sdp) and new device name  *	(e.g. /dev/sda). More precisely it is the block device major  *	and minor number that is chosen here. * *	Assume sd_attach is not re-entrant (for time being) *	Also think about sd_attach() and sd_remove() running coincidentally. **/static int sd_probe(struct device *dev){	struct scsi_device *sdp = to_scsi_device(dev);	struct scsi_disk *sdkp;	struct gendisk *gd;	u32 index;	int error;	error = -ENODEV;	if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))		goto out;	SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", 			 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));	error = -ENOMEM;	sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL);	if (!sdkp)		goto out;	memset (sdkp, 0, sizeof(*sdkp));	kref_init(&sdkp->kref);	gd = alloc_disk(16);	if (!gd)		goto out_free;	if (!idr_pre_get(&sd_index_idr, GFP_KERNEL))		goto out_put;	spin_lock(&sd_index_lock);	error = idr_get_new(&sd_index_idr, NULL, &index);	spin_unlock(&sd_index_lock);	if (index >= SD_MAX_DISKS)		error = -EBUSY;	if (error)		goto out_put;	sdkp->device = sdp;	sdkp->driver = &sd_template;	sdkp->disk = gd;	sdkp->index = index;	sdkp->openers = 0;	if (!sdp->timeout) {		if (sdp->type == TYPE_DISK)			sdp->timeout = SD_TIMEOUT;		else			sdp->timeout = SD_MOD_TIMEOUT;	}	gd->major = sd_major((index & 0xf0) >> 4);	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);	gd->minors = 16;	gd->fops = &sd_fops;	if (index < 26) {		sprintf(gd->disk_name, "sd%c", 'a' + index % 26);	} else if (index < (26 + 1) * 26) {		sprintf(gd->disk_name, "sd%c%c",			'a' + index / 26 - 1,'a' + index % 26);	} else {		const unsigned int m1 = (index / 26 - 1) / 26 - 1;		const unsigned int m2 = (index / 26 - 1) % 26;		const unsigned int m3 =  index % 26;		sprintf(gd->disk_name, "sd%c%c%c",			'a' + m1, 'a' + m2, 'a' + m3);	}	strcpy(gd->devfs_name, sdp->devfs_name);	gd->private_data = &sdkp->driver;	sd_revalidate_disk(gd);	gd->driverfs_dev = &sdp->sdev_gendev;	gd->flags = GENHD_FL_DRIVERFS;	if (sdp->removable)		gd->flags |= GENHD_FL_REMOVABLE;	gd->queue = sdkp->device->request_queue;	dev_set_drvdata(dev, sdkp);	add_disk(gd);	printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "	       "id %d, lun %d\n", sdp->removable ? "removable " : "",	       gd->disk_name, sdp->host->host_no, sdp->channel,	       sdp->id, sdp->lun);	return 0;out_put:	put_disk(gd);out_free:	kfree(sdkp);out:	return error;}/** *	sd_remove - called whenever a scsi disk (previously recognized by *	sd_probe) is detached from the system. It is called (potentially *	multiple times) during sd module unload. *	@sdp: pointer to mid level scsi device object * *	Note: this function is invoked from the scsi mid-level. *	This function potentially frees up a device name (e.g. /dev/sdc) *	that could be re-used by a subsequent sd_probe(). *	This function is not called when the built-in sd driver is "exit-ed". **/static int sd_remove(struct device *dev){	struct scsi_disk *sdkp = dev_get_drvdata(dev);	del_gendisk(sdkp->disk);	sd_shutdown(dev);	down(&sd_ref_sem);	kref_put(&sdkp->kref, scsi_disk_release);	up(&sd_ref_sem);	return 0;}/** *	scsi_disk_release - Called to free the scsi_disk structure *	@kref: pointer to embedded kref * *	sd_ref_sem must be held entering this routine.  Because it is *	called on last put, you should always use the scsi_disk_get() *	scsi_disk_put() helpers which manipulate the semaphore directly *	and never do a direct kref_put(). **/static void scsi_disk_release(struct kref *kref){	struct scsi_disk *sdkp = to_scsi_disk(kref);	struct gendisk *disk = sdkp->disk;		spin_lock(&sd_index_lock);	idr_remove(&sd_index_idr, sdkp->index);	spin_unlock(&sd_index_lock);	disk->private_data = NULL;	put_disk(disk);	kfree(sdkp);}/* * Send a SYNCHRONIZE CACHE instruction down to the device through * the normal SCSI command structure.  Wait for the command to * complete. */static void sd_shutdown(struct device *dev){	struct scsi_device *sdp = to_scsi_device(dev);	struct scsi_disk *sdkp = dev_get_drvdata(dev);	if (!sdkp)		return;         /* this can happen */	if (!sdkp->WCE)		return;	printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",			sdkp->disk->disk_name);	sd_sync_cache(sdp);}	/** *	init_sd - entry point for this driver (both when built in or when *	a module). * *	Note: this function registers this driver with the scsi mid-level. **/static int __init init_sd(void){	int majors = 0, i;	SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));	for (i = 0; i < SD_MAJORS; i++)		if (register_blkdev(sd_major(i), "sd") == 0)			majors++;	if (!majors)		return -ENODEV;	return scsi_register_driver(&sd_template.gendrv);}/** *	exit_sd - exit point for this driver (when it is a module). * *	Note: this function unregisters this driver from the scsi mid-level. **/static void __exit exit_sd(void){	int i;	SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));	scsi_unregister_driver(&sd_template.gendrv);	for (i = 0; i < SD_MAJORS; i++)		unregister_blkdev(sd_major(i), "sd");}MODULE_LICENSE("GPL");MODULE_AUTHOR("Eric Youngdale");MODULE_DESCRIPTION("SCSI disk (sd) driver");module_init(init_sd);module_exit(exit_sd);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -