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

📄 sr.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
{	check_disk_change(cdi->dev);	if (MINOR(cdi->dev) >= sr_template.dev_max	    || !scsi_CDs[MINOR(cdi->dev)].device) {		return -ENXIO;	/* No such device */	}	/*	 * If the device is in error recovery, wait until it is done.	 * If the device is offline, then disallow any access to it.	 */	if (!scsi_block_when_processing_errors(scsi_CDs[MINOR(cdi->dev)].device)) {		return -ENXIO;	}	scsi_CDs[MINOR(cdi->dev)].device->access_count++;	if (scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module)		__MOD_INC_USE_COUNT(scsi_CDs[MINOR(cdi->dev)].device->host->hostt->module);	if (sr_template.module)		__MOD_INC_USE_COUNT(sr_template.module);	/* If this device did not have media in the drive at boot time, then	 * we would have been unable to get the sector size.  Check to see if	 * this is the case, and try again.	 */	if (scsi_CDs[MINOR(cdi->dev)].needs_sector_size)		get_sectorsize(MINOR(cdi->dev));	return 0;}/* * do_sr_request() is the request handler function for the sr driver. * Its function in life is to take block device requests, and * translate them to SCSI commands. */static int sr_detect(Scsi_Device * SDp){	if (SDp->type != TYPE_ROM && SDp->type != TYPE_WORM)		return 0;	printk("Detected scsi CD-ROM sr%d at scsi%d, channel %d, id %d, lun %d\n",	       sr_template.dev_noticed++,	       SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);	return 1;}static int sr_attach(Scsi_Device * SDp){	Scsi_CD *cpnt;	int i;	if (SDp->type != TYPE_ROM && SDp->type != TYPE_WORM)		return 1;	if (sr_template.nr_dev >= sr_template.dev_max) {		SDp->attached--;		return 1;	}	for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++)		if (!cpnt->device)			break;	if (i >= sr_template.dev_max)		panic("scsi_devices corrupt (sr)");	scsi_CDs[i].device = SDp;	sr_template.nr_dev++;	if (sr_template.nr_dev > sr_template.dev_max)		panic("scsi_devices corrupt (sr)");	return 0;}void get_sectorsize(int i){	unsigned char cmd[10];	unsigned char *buffer;	int the_result, retries;	int sector_size;	Scsi_Request *SRpnt;	buffer = (unsigned char *) scsi_malloc(512);	SRpnt = scsi_allocate_request(scsi_CDs[i].device);		if(buffer == NULL || SRpnt == NULL)	{		scsi_CDs[i].capacity = 0x1fffff;		sector_size = 2048;	/* A guess, just in case */		scsi_CDs[i].needs_sector_size = 1;		if(buffer)			scsi_free(buffer, 512);		if(SRpnt)			scsi_release_request(SRpnt);		return;	}		retries = 3;	do {		cmd[0] = READ_CAPACITY;		cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0;		memset((void *) &cmd[2], 0, 8);		SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;	/* Mark as really busy */		SRpnt->sr_cmd_len = 0;		memset(buffer, 0, 8);		/* Do the command and wait.. */		SRpnt->sr_data_direction = SCSI_DATA_READ;		scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,			      8, SR_TIMEOUT, MAX_RETRIES);		the_result = SRpnt->sr_result;		retries--;	} while (the_result && retries);	scsi_release_request(SRpnt);	SRpnt = NULL;	if (the_result) {		scsi_CDs[i].capacity = 0x1fffff;		sector_size = 2048;	/* A guess, just in case */		scsi_CDs[i].needs_sector_size = 1;	} else {#if 0		if (cdrom_get_last_written(MKDEV(MAJOR_NR, i),					 (long *) &scsi_CDs[i].capacity))#endif			scsi_CDs[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];		switch (sector_size) {			/*			 * HP 4020i CD-Recorder reports 2340 byte sectors			 * Philips CD-Writers report 2352 byte sectors			 *			 * Use 2k sectors for them..			 */		case 0:		case 2340:		case 2352:			sector_size = 2048;			/* fall through */		case 2048:			scsi_CDs[i].capacity *= 4;			/* fall through */		case 512:			break;		default:			printk("sr%d: unsupported sector size %d.\n",			       i, sector_size);			scsi_CDs[i].capacity = 0;			scsi_CDs[i].needs_sector_size = 1;		}		scsi_CDs[i].device->sector_size = sector_size;		/*		 * Add this so that we have the ability to correctly gauge		 * what the device is capable of.		 */		scsi_CDs[i].needs_sector_size = 0;		sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);	};	scsi_free(buffer, 512);}void get_capabilities(int i){	unsigned char cmd[6];	unsigned char *buffer;	int rc, n;	static char *loadmech[] =	{		"caddy",		"tray",		"pop-up",		"",		"changer",		"cartridge changer",		"",		""	};	buffer = (unsigned char *) scsi_malloc(512);	cmd[0] = MODE_SENSE;	cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0;	cmd[2] = 0x2a;	cmd[4] = 128;	cmd[3] = cmd[5] = 0;	rc = sr_do_ioctl(i, cmd, buffer, 128, 1, SCSI_DATA_READ, NULL);	if (-EINVAL == rc) {		/* failed, drive has'nt this mode page */		scsi_CDs[i].cdi.speed = 1;		/* disable speed select, drive probably can't do this either */		scsi_CDs[i].cdi.mask |= CDC_SELECT_SPEED;		scsi_free(buffer, 512);		return;	}	n = buffer[3] + 4;	scsi_CDs[i].cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;	scsi_CDs[i].readcd_known = 1;	scsi_CDs[i].readcd_cdda = buffer[n + 5] & 0x01;	/* print some capability bits */	printk("sr%i: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", i,	       ((buffer[n + 14] << 8) + buffer[n + 15]) / 176,	       scsi_CDs[i].cdi.speed,	       buffer[n + 3] & 0x01 ? "writer " : "",	/* CD Writer */	       buffer[n + 3] & 0x20 ? "dvd-ram " : "",	       buffer[n + 2] & 0x02 ? "cd/rw " : "",	/* can read rewriteable */	       buffer[n + 4] & 0x20 ? "xa/form2 " : "",		/* can read xa/from2 */	       buffer[n + 5] & 0x01 ? "cdda " : "",	/* can read audio data */	       loadmech[buffer[n + 6] >> 5]);	if ((buffer[n + 6] >> 5) == 0)		/* caddy drives can't close tray... */		scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY;	if ((buffer[n + 2] & 0x8) == 0)		/* not a DVD drive */		scsi_CDs[i].cdi.mask |= CDC_DVD;	if ((buffer[n + 3] & 0x20) == 0) {		/* can't write DVD-RAM media */		scsi_CDs[i].cdi.mask |= CDC_DVD_RAM;	} else {		scsi_CDs[i].device->writeable = 1;	}	if ((buffer[n + 3] & 0x10) == 0)		/* can't write DVD-R media */		scsi_CDs[i].cdi.mask |= CDC_DVD_R;	if ((buffer[n + 3] & 0x2) == 0)		/* can't write CD-RW media */		scsi_CDs[i].cdi.mask |= CDC_CD_RW;	if ((buffer[n + 3] & 0x1) == 0)		/* can't write CD-R media */		scsi_CDs[i].cdi.mask |= CDC_CD_R;	if ((buffer[n + 6] & 0x8) == 0)		/* can't eject */		scsi_CDs[i].cdi.mask |= CDC_OPEN_TRAY;	if ((buffer[n + 6] >> 5) == mechtype_individual_changer ||	    (buffer[n + 6] >> 5) == mechtype_cartridge_changer)		scsi_CDs[i].cdi.capacity =		    cdrom_number_of_slots(&(scsi_CDs[i].cdi));	if (scsi_CDs[i].cdi.capacity <= 1)		/* not a changer */		scsi_CDs[i].cdi.mask |= CDC_SELECT_DISC;	/*else    I don't think it can close its tray	   scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */	scsi_free(buffer, 512);}/* * sr_packet() is the entry point for the generic commands generated * by the Uniform CD-ROM layer.  */static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc){	Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;	/* set the LUN */	cgc->cmd[1] |= device->lun << 5;	cgc->stat = sr_do_ioctl(MINOR(cdi->dev), cgc->cmd, cgc->buffer, cgc->buflen, cgc->quiet, cgc->data_direction, cgc->sense);	return cgc->stat;}static int sr_registered;static int sr_init(){	int i;	if (sr_template.dev_noticed == 0)		return 0;	if (!sr_registered) {		if (devfs_register_blkdev(MAJOR_NR, "sr", &cdrom_fops)) {			printk("Unable to get major %d for SCSI-CD\n", MAJOR_NR);			return 1;		}		sr_registered++;	}	if (scsi_CDs)		return 0;	sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS;	scsi_CDs = kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);	if (!scsi_CDs)		goto cleanup_devfs;	memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD));	sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);	if (!sr_sizes)		goto cleanup_cds;	memset(sr_sizes, 0, sr_template.dev_max * sizeof(int));	sr_blocksizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);	if (!sr_blocksizes)		goto cleanup_sizes;	sr_hardsizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);	if (!sr_hardsizes)		goto cleanup_blocksizes;	/*	 * These are good guesses for the time being.	 */	for (i = 0; i < sr_template.dev_max; i++) {		sr_blocksizes[i] = 2048;		sr_hardsizes[i] = 2048;        }	blksize_size[MAJOR_NR] = sr_blocksizes;        hardsect_size[MAJOR_NR] = sr_hardsizes;	return 0;cleanup_blocksizes:	kfree(sr_blocksizes);cleanup_sizes:	kfree(sr_sizes);cleanup_cds:	kfree(scsi_CDs);cleanup_devfs:	devfs_unregister_blkdev(MAJOR_NR, "sr");	sr_registered--;	return 1;}void sr_finish(){	int i;	char name[6];	blk_dev[MAJOR_NR].queue = sr_find_queue;	blk_size[MAJOR_NR] = sr_sizes;	for (i = 0; i < sr_template.nr_dev; ++i) {		/* If we have already seen this, then skip it.  Comes up		 * with loadable modules. */		if (scsi_CDs[i].capacity)			continue;		scsi_CDs[i].capacity = 0x1fffff;		scsi_CDs[i].device->sector_size = 2048;		/* A guess, just in case */		scsi_CDs[i].needs_sector_size = 1;		scsi_CDs[i].device->changed = 1;	/* force recheck CD type */#if 0		/* seems better to leave this for later */		get_sectorsize(i);		printk("Scd sectorsize = %d bytes.\n", scsi_CDs[i].sector_size);#endif		scsi_CDs[i].use = 1;		scsi_CDs[i].device->ten = 1;		scsi_CDs[i].device->remap = 1;		scsi_CDs[i].readcd_known = 0;		scsi_CDs[i].readcd_cdda = 0;		sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);		scsi_CDs[i].cdi.ops = &sr_dops;		scsi_CDs[i].cdi.handle = &scsi_CDs[i];		scsi_CDs[i].cdi.dev = MKDEV(MAJOR_NR, i);		scsi_CDs[i].cdi.mask = 0;		scsi_CDs[i].cdi.capacity = 1;		get_capabilities(i);		sr_vendor_init(i);		sprintf(name, "sr%d", i);		strcpy(scsi_CDs[i].cdi.name, name);                scsi_CDs[i].cdi.de =                    devfs_register (scsi_CDs[i].device->de, "cd",                                    DEVFS_FL_DEFAULT, MAJOR_NR, i,                                    S_IFBLK | S_IRUGO | S_IWUGO,                                    &cdrom_fops, NULL);		register_cdrom(&scsi_CDs[i].cdi);	}	/* If our host adapter is capable of scatter-gather, then we increase	 * the read-ahead to 16 blocks (32 sectors).  If not, we use	 * a two block (4 sector) read ahead. */	if (scsi_CDs[0].device && scsi_CDs[0].device->host->sg_tablesize)		read_ahead[MAJOR_NR] = 32;	/* 32 sector read-ahead.  Always removable. */	else		read_ahead[MAJOR_NR] = 4;	/* 4 sector read-ahead */	return;}static void sr_detach(Scsi_Device * SDp){	Scsi_CD *cpnt;	int i;	for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++)		if (cpnt->device == SDp) {			kdev_t devi = MKDEV(MAJOR_NR, i);			struct super_block *sb = get_super(devi);			/*			 * Since the cdrom is read-only, no need to sync the device.			 * We should be kind to our buffer cache, however.			 */			if (sb)				invalidate_inodes(sb);			invalidate_buffers(devi);			/*			 * Reset things back to a sane state so that one can re-load a new			 * driver (perhaps the same one).			 */			unregister_cdrom(&(cpnt->cdi));			cpnt->device = NULL;			cpnt->capacity = 0;			SDp->attached--;			sr_template.nr_dev--;			sr_template.dev_noticed--;			sr_sizes[i] = 0;			return;		}	return;}static int __init init_sr(void){	sr_template.module = THIS_MODULE;	return scsi_register_module(MODULE_SCSI_DEV, &sr_template);}static void __exit exit_sr(void){	scsi_unregister_module(MODULE_SCSI_DEV, &sr_template);	devfs_unregister_blkdev(MAJOR_NR, "sr");	sr_registered--;	if (scsi_CDs != NULL) {		kfree(scsi_CDs);		kfree(sr_sizes);		sr_sizes = NULL;		kfree(sr_blocksizes);		sr_blocksizes = NULL;		kfree(sr_hardsizes);		sr_hardsizes = NULL;	}	blksize_size[MAJOR_NR] = NULL;        hardsect_size[MAJOR_NR] = NULL;	blk_size[MAJOR_NR] = NULL;	read_ahead[MAJOR_NR] = 0;	sr_template.dev_max = 0;}module_init(init_sr);module_exit(exit_sr);

⌨️ 快捷键说明

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