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

📄 sd.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	SDev = rscsi_disks[target].device;	/*	 * It is possible that the disk changing stuff resulted in the device	 * being taken offline.  If this is the case, report this to the user,	 * and don't pretend that	 * the open actually succeeded.	 */	if (!SDev->online) {		return -ENXIO;	}	/*	 * See if we are requesting a non-existent partition.  Do this	 * after checking for disk change.	 */	if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0)		return -ENXIO;	if (SDev->removable)		if (!SDev->access_count)			if (scsi_block_when_processing_errors(SDev))				scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);	SDev->access_count++;	if (SDev->host->hostt->module)		__MOD_INC_USE_COUNT(SDev->host->hostt->module);	if (sd_template.module)		__MOD_INC_USE_COUNT(sd_template.module);	return 0;}static int sd_release(struct inode *inode, struct file *file){	int target;	Scsi_Device * SDev;	target = DEVICE_NR(inode->i_rdev);	SDev = rscsi_disks[target].device;	SDev->access_count--;	if (SDev->removable) {		if (!SDev->access_count)			if (scsi_block_when_processing_errors(SDev))				scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL);	}	if (SDev->host->hostt->module)		__MOD_DEC_USE_COUNT(SDev->host->hostt->module);	if (sd_template.module)		__MOD_DEC_USE_COUNT(sd_template.module);	return 0;}static struct block_device_operations sd_fops ={	open:			sd_open,	release:		sd_release,	ioctl:			sd_ioctl,	check_media_change:	check_scsidisk_media_change,	revalidate:		fop_revalidate_scsidisk};/* *    If we need more than one SCSI disk major (i.e. more than *      16 SCSI disks), we'll have to kmalloc() more gendisks later. */static struct gendisk sd_gendisk ={	SCSI_DISK0_MAJOR,	/* Major number */	"sd",			/* Major name */	4,			/* Bits to shift to get real from partition */	1 << 4,			/* Number of partitions per real */	NULL,			/* hd struct */	NULL,			/* block sizes */	0,			/* number */	NULL,			/* internal */	NULL,			/* next */        &sd_fops,		/* file operations */};static struct gendisk *sd_gendisks = &sd_gendisk;#define SD_GENDISK(i)    sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]#define LAST_SD_GENDISK  sd_gendisks[N_USED_SD_MAJORS - 1]/* * rw_intr is the interrupt routine for the device driver. * It will be notified on the end of a SCSI read / write, and * will take one of several actions based on success or failure. */static void rw_intr(Scsi_Cmnd * SCpnt){	int result = SCpnt->result;#if CONFIG_SCSI_LOGGING	char nbuff[6];#endif	int this_count = SCpnt->bufflen >> 9;	int good_sectors = (result == 0 ? this_count : 0);	int block_sectors = 1;	SCSI_LOG_HLCOMPLETE(1, sd_devname(DEVICE_NR(SCpnt->request.rq_dev), nbuff));	SCSI_LOG_HLCOMPLETE(1, printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff,				      SCpnt->host->host_no,				      result,				      SCpnt->sense_buffer[0],				      SCpnt->sense_buffer[2]));	/*	   Handle MEDIUM ERRORs that indicate partial success.  Since this is a	   relatively rare error condition, no care is taken to avoid	   unnecessary additional work such as memcpy's that could be avoided.	 */	/* An error occurred */	if (driver_byte(result) != 0) {		/* Sense data is valid */		if (SCpnt->sense_buffer[0] == 0xF0 && SCpnt->sense_buffer[2] == MEDIUM_ERROR) {			long error_sector = (SCpnt->sense_buffer[3] << 24) |			(SCpnt->sense_buffer[4] << 16) |			(SCpnt->sense_buffer[5] << 8) |			SCpnt->sense_buffer[6];			if (SCpnt->request.bh != NULL)				block_sectors = SCpnt->request.bh->b_size >> 9;			switch (SCpnt->device->sector_size) {			case 1024:				error_sector <<= 1;				if (block_sectors < 2)					block_sectors = 2;				break;			case 2048:				error_sector <<= 2;				if (block_sectors < 4)					block_sectors = 4;				break;			case 4096:				error_sector <<=3;				if (block_sectors < 8)					block_sectors = 8;				break;			case 256:				error_sector >>= 1;				break;			default:				break;			}			error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect;			error_sector &= ~(block_sectors - 1);			good_sectors = error_sector - SCpnt->request.sector;			if (good_sectors < 0 || good_sectors >= this_count)				good_sectors = 0;		}		if (SCpnt->sense_buffer[2] == ILLEGAL_REQUEST) {			if (SCpnt->device->ten == 1) {				if (SCpnt->cmnd[0] == READ_10 ||				    SCpnt->cmnd[0] == WRITE_10)					SCpnt->device->ten = 0;			}		}	}	/*	 * This calls the generic completion function, now that we know	 * how many actual sectors finished, and how many sectors we need	 * to say have failed.	 */	scsi_io_completion(SCpnt, good_sectors, block_sectors);}/* * requeue_sd_request() is the request handler function for the sd driver. * Its function in life is to take block device requests, and translate * them to SCSI commands. */static int check_scsidisk_media_change(kdev_t full_dev){	int retval;	int target;	int flag = 0;	Scsi_Device * SDev;	target = DEVICE_NR(full_dev);	SDev = rscsi_disks[target].device;	if (target >= sd_template.dev_max || !SDev) {		printk("SCSI disk request error: invalid device.\n");		return 0;	}	if (!SDev->removable)		return 0;	/*	 * If the device is offline, don't send any commands - just pretend as	 * if the command failed.  If the device ever comes back online, we	 * can deal with it then.  It is only because of unrecoverable errors	 * that we would ever take a device offline in the first place.	 */	if (SDev->online == FALSE) {		rscsi_disks[target].ready = 0;		SDev->changed = 1;		return 1;	/* This will force a flush, if called from				 * check_disk_change */	}	/* Using Start/Stop enables differentiation between drive with	 * no cartridge loaded - NOT READY, drive with changed cartridge -	 * UNIT ATTENTION, or with same cartridge - GOOD STATUS.	 * This also handles drives that auto spin down. eg iomega jaz 1GB	 * as this will spin up the drive.	 */	retval = -ENODEV;	if (scsi_block_when_processing_errors(SDev))		retval = scsi_ioctl(SDev, SCSI_IOCTL_START_UNIT, NULL);	if (retval) {		/* Unable to test, unit probably not ready.				 * This usually means there is no disc in the				 * drive.  Mark as changed, and we will figure				 * it out later once the drive is available				 * again.  */		rscsi_disks[target].ready = 0;		SDev->changed = 1;		return 1;	/* This will force a flush, if called from				 * check_disk_change */	}	/*	 * for removable scsi disk ( FLOPTICAL ) we have to recognise the	 * presence of disk in the drive. This is kept in the Scsi_Disk	 * struct and tested at open !  Daniel Roche ( dan@lectra.fr )	 */	rscsi_disks[target].ready = 1;	/* FLOPTICAL */	retval = SDev->changed;	if (!flag)		SDev->changed = 0;	return retval;}static int sd_init_onedisk(int i){	unsigned char cmd[10];	char nbuff[6];	unsigned char *buffer;	unsigned long spintime_value = 0;	int the_result, retries, spintime;	int sector_size;	Scsi_Request *SRpnt;	/*	 * Get the name of the disk, in case we need to log it somewhere.	 */	sd_devname(i, nbuff);	/*	 * If the device is offline, don't try and read capacity or any	 * of the other niceties.	 */	if (rscsi_disks[i].device->online == FALSE)		return i;	/*	 * We need to retry the READ_CAPACITY because a UNIT_ATTENTION is	 * considered a fatal error, and many devices report such an error	 * just after a scsi bus reset.	 */	SRpnt = scsi_allocate_request(rscsi_disks[i].device);	buffer = (unsigned char *) scsi_malloc(512);	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;		while (retries < 3) {			cmd[0] = TEST_UNIT_READY;			cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;			memset((void *) &cmd[2], 0, 8);			SRpnt->sr_cmd_len = 0;			SRpnt->sr_sense_buffer[0] = 0;			SRpnt->sr_sense_buffer[2] = 0;			SRpnt->sr_data_direction = SCSI_DATA_READ;			scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer,				0/*512*/, SD_TIMEOUT, MAX_RETRIES);			the_result = SRpnt->sr_result;			retries++;			if (the_result == 0			    || SRpnt->sr_sense_buffer[2] != UNIT_ATTENTION)				break;		}		/*		 * If the drive has indicated to us that it doesn't have		 * any media in it, don't bother with any of the rest of		 * this crap.		 */		if( the_result != 0		    && ((driver_byte(the_result) & DRIVER_SENSE) != 0)		    && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION		    && SRpnt->sr_sense_buffer[12] == 0x3A ) {			rscsi_disks[i].capacity = 0x1fffff;			sector_size = 512;			rscsi_disks[i].device->changed = 1;			rscsi_disks[i].ready = 0;			break;		}		/* Look for non-removable devices that return NOT_READY.		 * Issue command to spin up drive for these cases. */		if (the_result && !rscsi_disks[i].device->removable &&		    SRpnt->sr_sense_buffer[2] == NOT_READY) {			unsigned long time1;			if (!spintime) {				printk("%s: Spinning up disk...", nbuff);				cmd[0] = START_STOP;				cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;				cmd[1] |= 1;	/* Return immediately */				memset((void *) &cmd[2], 0, 8);				cmd[4] = 1;	/* Start spin cycle */				SRpnt->sr_cmd_len = 0;				SRpnt->sr_sense_buffer[0] = 0;				SRpnt->sr_sense_buffer[2] = 0;				SRpnt->sr_data_direction = SCSI_DATA_READ;				scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,					    0/*512*/, SD_TIMEOUT, MAX_RETRIES);			}			spintime = 1;			spintime_value = jiffies;			time1 = HZ;			/* Wait 1 second for next try */			do {				current->state = TASK_UNINTERRUPTIBLE;				time1 = schedule_timeout(time1);			} while(time1);			printk(".");		}	} while (the_result && spintime &&		 time_after(spintime_value + 100 * HZ, jiffies));	if (spintime) {		if (the_result)			printk("not responding...\n");		else			printk("ready\n");	}	retries = 3;	do {		cmd[0] = READ_CAPACITY;		cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;		memset((void *) &cmd[2], 0, 8);		memset((void *) buffer, 0, 8);		SRpnt->sr_cmd_len = 0;		SRpnt->sr_sense_buffer[0] = 0;		SRpnt->sr_sense_buffer[2] = 0;		SRpnt->sr_data_direction = SCSI_DATA_READ;		scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,			    8, SD_TIMEOUT, MAX_RETRIES);		the_result = SRpnt->sr_result;		retries--;	} while (the_result && retries);	/*	 * The SCSI standard says:	 * "READ CAPACITY is necessary for self configuring software"	 *  While not mandatory, support of READ CAPACITY is strongly	 *  encouraged.	 *  We used to die if we couldn't successfully do a READ CAPACITY.	 *  But, now we go on about our way.  The side effects of this are	 *	 *  1. We can't know block size with certainty. I have said	 *     "512 bytes is it" as this is most common.	 *	 *  2. Recovery from when someone attempts to read past the	 *     end of the raw device will be slower.	 */	if (the_result) {		printk("%s : READ CAPACITY failed.\n"		       "%s : status = %x, message = %02x, host = %d, driver = %02x \n",		       nbuff, nbuff,		       status_byte(the_result),		       msg_byte(the_result),		       host_byte(the_result),		       driver_byte(the_result)		    );		if (driver_byte(the_result) & DRIVER_SENSE)			printk("%s : extended sense code = %1x \n",			       nbuff, SRpnt->sr_sense_buffer[2] & 0xf);		else			printk("%s : sense not available. \n", nbuff);		printk("%s : block size assumed to be 512 bytes, disk size 1GB.  \n",		       nbuff);		rscsi_disks[i].capacity = 0x1fffff;		sector_size = 512;		/* Set dirty bit for removable devices if not ready -		 * sometimes drives will not report this properly. */		if (rscsi_disks[i].device->removable &&		    SRpnt->sr_sense_buffer[2] == NOT_READY)			rscsi_disks[i].device->changed = 1;	} else {		/*		 * FLOPTICAL, if read_capa is ok, drive is assumed to be ready		 */		rscsi_disks[i].ready = 1;		rscsi_disks[i].capacity = 1 + ((buffer[0] << 24) |					       (buffer[1] << 16) |					       (buffer[2] << 8) |					       buffer[3]);		sector_size = (buffer[4] << 24) |		    (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];		if (sector_size == 0) {			sector_size = 512;			printk("%s : sector size 0 reported, assuming 512.\n",			       nbuff);		}		if (sector_size != 512 &&		    sector_size != 1024 &&		    sector_size != 2048 &&		    sector_size != 4096 &&		    sector_size != 256) {			printk("%s : unsupported sector size %d.\n",			       nbuff, 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.			 */			rscsi_disks[i].capacity = 0;		}		if (sector_size > 1024) {			int m;			/*			 * We must fix the sd_blocksizes and sd_hardsizes			 * to allow us to read the partition tables.			 * The disk reading code does not allow for reading			 * of partial sectors.			 */			for (m = i << 4; m < ((i + 1) << 4); m++) {				sd_blocksizes[m] = sector_size;			}		} {			/*			 * 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 m;

⌨️ 快捷键说明

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