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

📄 ide-cd.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
					}					printk ("%s: DSC timeout\n", drive->name);				}				CDROM_CONFIG_FLAGS(drive)->seeking = 0;			}			if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)				action = cdrom_start_seek (drive, block);			else {				if (rq->cmd == READ)					action = cdrom_start_read(drive, block);				else					action = cdrom_start_write(drive);			}			info->last_block = block;			return action;		}		case PACKET_COMMAND:		case REQUEST_SENSE_COMMAND: {			return cdrom_do_packet_command(drive);		}		case RESET_DRIVE_COMMAND: {			cdrom_end_request(1, drive);			return ide_do_reset(drive);		}		default: {			printk("ide-cd: bad cmd %d\n", rq->cmd);			cdrom_end_request(0, drive);			return ide_stopped;		}	}}/**************************************************************************** * Ioctl handling. * * Routines which queue packet commands take as a final argument a pointer * to a request_sense struct.  If execution of the command results * in an error with a CHECK CONDITION status, this structure will be filled * with the results of the subsequent request sense command.  The pointer * can also be NULL, in which case no sense information is returned. */#if ! STANDARD_ATAPIstatic inlineint bin2bcd (int x){	return (x%10) | ((x/10) << 4);}static inlineint bcd2bin (int x){	return (x >> 4) * 10 + (x & 0x0f);}staticvoid msf_from_bcd (struct atapi_msf *msf){	msf->minute = bcd2bin (msf->minute);	msf->second = bcd2bin (msf->second);	msf->frame  = bcd2bin (msf->frame);}#endif /* not STANDARD_ATAPI */static inlinevoid lba_to_msf (int lba, byte *m, byte *s, byte *f){	lba += CD_MSF_OFFSET;	lba &= 0xffffff;  /* negative lbas use only 24 bits */	*m = lba / (CD_SECS * CD_FRAMES);	lba %= (CD_SECS * CD_FRAMES);	*s = lba / CD_FRAMES;	*f = lba % CD_FRAMES;}static inlineint msf_to_lba (byte m, byte s, byte f){	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;}static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense){	struct packet_command pc;	struct cdrom_info *info = drive->driver_data;	struct cdrom_device_info *cdi = &info->devinfo;	memset(&pc, 0, sizeof(pc));	pc.sense = sense;	pc.c[0] = GPCMD_TEST_UNIT_READY;#if ! STANDARD_ATAPI        /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to            switch CDs instead of supporting the LOAD_UNLOAD opcode   */        pc.c[7] = cdi->sanyo_slot % 3;#endif /* not STANDARD_ATAPI */	return cdrom_queue_packet_command(drive, &pc);}/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */static intcdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense){	struct request_sense my_sense;	struct packet_command pc;	int stat;	if (sense == NULL)		sense = &my_sense;	/* If the drive cannot lock the door, just pretend. */	if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {		stat = 0;	} else {		memset(&pc, 0, sizeof(pc));		pc.sense = sense;		pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;		pc.c[4] = lockflag ? 1 : 0;		stat = cdrom_queue_packet_command (drive, &pc);	}	/* If we got an illegal field error, the drive	   probably cannot lock the door. */	if (stat != 0 &&	    sense->sense_key == ILLEGAL_REQUEST &&	    (sense->asc == 0x24 || sense->asc == 0x20)) {		printk ("%s: door locking not supported\n",			drive->name);		CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;		stat = 0;	}		/* no medium, that's alright. */	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)		stat = 0;	if (stat == 0)		CDROM_STATE_FLAGS (drive)->door_locked = lockflag;	return stat;}/* Eject the disk if EJECTFLAG is 0.   If EJECTFLAG is 1, try to reload the disk. */static int cdrom_eject(ide_drive_t *drive, int ejectflag,		       struct request_sense *sense){	struct packet_command pc;	if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)		return -EDRIVE_CANT_DO_THIS;		/* reload fails on some drives, if the tray is locked */	if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)		return 0;	memset(&pc, 0, sizeof (pc));	pc.sense = sense;	pc.c[0] = GPCMD_START_STOP_UNIT;	pc.c[4] = 0x02 + (ejectflag != 0);	return cdrom_queue_packet_command (drive, &pc);}static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity,			       struct request_sense *sense){	struct {		__u32 lba;		__u32 blocklen;	} capbuf;	int stat;	struct packet_command pc;	memset(&pc, 0, sizeof(pc));	pc.sense = sense;	pc.c[0] = GPCMD_READ_CDVD_CAPACITY;	pc.buffer = (char *)&capbuf;	pc.buflen = sizeof(capbuf);	stat = cdrom_queue_packet_command(drive, &pc);	if (stat == 0)		*capacity = 1 + be32_to_cpu(capbuf.lba);	return stat;}static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,				int format, char *buf, int buflen,				struct request_sense *sense){	struct packet_command pc;	memset(&pc, 0, sizeof(pc));	pc.sense = sense;	pc.buffer =  buf;	pc.buflen = buflen;	pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;	pc.c[6] = trackno;	pc.c[7] = (buflen >> 8);	pc.c[8] = (buflen & 0xff);	pc.c[9] = (format << 6);	if (msf_flag)		pc.c[1] = 2;	return cdrom_queue_packet_command (drive, &pc);}/* Try to read the entire TOC for the disk into our internal buffer. */static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense){	int minor, stat, ntracks, i;	kdev_t dev;	struct cdrom_info *info = drive->driver_data;	struct atapi_toc *toc = info->toc;	struct {		struct atapi_toc_header hdr;		struct atapi_toc_entry  ent;	} ms_tmp;	if (toc == NULL) {		/* Try to allocate space. */		toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),						    GFP_KERNEL);		info->toc = toc;		if (toc == NULL) {			printk ("%s: No cdrom TOC buffer!\n", drive->name);			return -ENOMEM;		}	}	/* Check to see if the existing data is still valid.	   If it is, just return. */	(void) cdrom_check_status(drive, sense);	if (CDROM_STATE_FLAGS(drive)->toc_valid)		return 0;	/* First read just the header, so we know how long the TOC is. */	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,				    sizeof(struct atapi_toc_header), sense);	if (stat) return stat;#if ! STANDARD_ATAPI	if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {		toc->hdr.first_track = bcd2bin (toc->hdr.first_track);		toc->hdr.last_track  = bcd2bin (toc->hdr.last_track);	}#endif  /* not STANDARD_ATAPI */	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;	if (ntracks <= 0)		return -EIO;	if (ntracks > MAX_TRACKS)		ntracks = MAX_TRACKS;	/* Now read the whole schmeer. */	stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,				  (char *)&toc->hdr,				   sizeof(struct atapi_toc_header) +				   (ntracks + 1) *				   sizeof(struct atapi_toc_entry), sense);	if (stat && toc->hdr.first_track > 1) {		/* Cds with CDI tracks only don't have any TOC entries,		   despite of this the returned values are		   first_track == last_track = number of CDI tracks + 1,		   so that this case is indistinguishable from the same		   layout plus an additional audio track.		   If we get an error for the regular case, we assume		   a CDI without additional audio tracks. In this case		   the readable TOC is empty (CDI tracks are not included)		   and only holds the Leadout entry. Heiko Ei遞eldt */		ntracks = 0;		stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,					   (char *)&toc->hdr,					   sizeof(struct atapi_toc_header) +					   (ntracks + 1) *					   sizeof(struct atapi_toc_entry),					   sense);		if (stat) {			return stat;		}#if ! STANDARD_ATAPI		if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {			toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);			toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);		} else#endif  /* not STANDARD_ATAPI */		{			toc->hdr.first_track = CDROM_LEADOUT;			toc->hdr.last_track = CDROM_LEADOUT;		}	}	if (stat)		return stat;	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);#if ! STANDARD_ATAPI	if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {		toc->hdr.first_track = bcd2bin (toc->hdr.first_track);		toc->hdr.last_track  = bcd2bin (toc->hdr.last_track);	}#endif  /* not STANDARD_ATAPI */	for (i=0; i<=ntracks; i++) {#if ! STANDARD_ATAPI		if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd) {			if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd)				toc->ent[i].track = bcd2bin (toc->ent[i].track);			msf_from_bcd (&toc->ent[i].addr.msf);		}#endif  /* not STANDARD_ATAPI */		toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,						   toc->ent[i].addr.msf.second,						   toc->ent[i].addr.msf.frame);	}	/* Read the multisession information. */	if (toc->hdr.first_track != CDROM_LEADOUT) {		/* Read the multisession information. */		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,					   sizeof(ms_tmp), sense);		if (stat) return stat;	} else {		ms_tmp.ent.addr.msf.minute = 0;		ms_tmp.ent.addr.msf.second = 2;		ms_tmp.ent.addr.msf.frame  = 0;		ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;	}#if ! STANDARD_ATAPI	if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)		msf_from_bcd (&ms_tmp.ent.addr.msf);#endif  /* not STANDARD_ATAPI */	toc->last_session_lba = msf_to_lba (ms_tmp.ent.addr.msf.minute,					    ms_tmp.ent.addr.msf.second,					    ms_tmp.ent.addr.msf.frame);	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);	/* Now try to get the total cdrom capacity. */	minor = (drive->select.b.unit) << PARTN_BITS;	dev = MKDEV(HWIF(drive)->major, minor);	stat = cdrom_get_last_written(dev, (long *)&toc->capacity);	if (stat)		stat = cdrom_read_capacity(drive, &toc->capacity, sense);	if (stat)		toc->capacity = 0x1fffff;	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;	/* Remember that we've read this stuff. */	CDROM_STATE_FLAGS (drive)->toc_valid = 1;	return 0;}static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,				 int buflen, struct request_sense *sense){	struct packet_command pc;	memset(&pc, 0, sizeof(pc));	pc.sense = sense;	pc.buffer = buf;	pc.buflen = buflen;	pc.c[0] = GPCMD_READ_SUBCHANNEL;	pc.c[1] = 2;     /* MSF addressing */	pc.c[2] = 0x40;  /* request subQ data */	pc.c[3] = format;	pc.c[7] = (buflen >> 8);	pc.c[8] = (buflen & 0xff);	return cdrom_queue_packet_command(drive, &pc);}/* ATAPI cdrom drives are free to select the speed you request or any slower   rate :-( Requesting too fast a speed will _not_ produce an error. */static int cdrom_select_spee

⌨️ 快捷键说明

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