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

📄 ide-cd.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Now we wait for another interrupt. */	ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD);}static void cdrom_do_pc_continuation (ide_drive_t *drive){	struct request *rq = HWGROUP(drive)->rq;	struct packet_command *pc = (struct packet_command *)rq->buffer;	/* Send the command to the drive and return. */	cdrom_transfer_packet_command (drive, pc->c,				       sizeof (pc->c), &cdrom_pc_intr);}static void cdrom_do_packet_command (ide_drive_t *drive){	int len;	struct request *rq = HWGROUP(drive)->rq;	struct packet_command *pc = (struct packet_command *)rq->buffer;	len = pc->buflen;	if (len < 0) len = -len;	pc->stat = 0;	/* Start sending the command to the drive. */	cdrom_start_packet_command (drive, len, cdrom_do_pc_continuation);}#ifndef MACH/* Sleep for TIME jiffies.   Not to be called from an interrupt handler. */staticvoid cdrom_sleep (int time){	current->state = TASK_INTERRUPTIBLE;	current->timeout = jiffies + time;	schedule ();}#endifstaticint cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc){	struct atapi_request_sense my_reqbuf;	int retries = 10;	struct request req;	/* If our caller has not provided a place to stick any sense data,	   use our own area. */	if (pc->sense_data == NULL)		pc->sense_data = &my_reqbuf;	pc->sense_data->sense_key = 0;	/* Start of retry loop. */	do {		ide_init_drive_cmd (&req);		req.cmd = PACKET_COMMAND;		req.buffer = (char *)pc;		(void) ide_do_drive_cmd (drive, &req, ide_wait);		if (pc->stat != 0) {			/* The request failed.  Retry if it was due to a unit			   attention status			   (usually means media was changed). */			struct atapi_request_sense *reqbuf = pc->sense_data;			if (reqbuf->sense_key == UNIT_ATTENTION)				;			else if (reqbuf->sense_key == NOT_READY &&				 reqbuf->asc == 4) {				/* The drive is in the process of loading				   a disk.  Retry, but wait a little to give				   the drive time to complete the load. */				cdrom_sleep (HZ);			} else				/* Otherwise, don't retry. */				retries = 0;			--retries;		}		/* End of retry loop. */	} while (pc->stat != 0 && retries >= 0);	/* Return an error if the command failed. */	if (pc->stat != 0)		return -EIO;	else {		/* The command succeeded.  If it was anything other than		   a request sense, eject, or door lock command,		   and we think that the door is presently, lock it again.		   (The door was probably unlocked via an explicit		   CDROMEJECT ioctl.) */		if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&		    (pc->c[0] != REQUEST_SENSE &&		     pc->c[0] != ALLOW_MEDIUM_REMOVAL &&		     pc->c[0] != START_STOP)) {			(void) cdrom_lockdoor (drive, 1, NULL);		}		return 0;	}}/**************************************************************************** * cdrom driver request routine. */void ide_do_rw_cdrom (ide_drive_t *drive, unsigned long block){	struct request *rq = HWGROUP(drive)->rq;	if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND)		cdrom_do_packet_command (drive);	else if (rq -> cmd == RESET_DRIVE_COMMAND) {		cdrom_end_request (1, drive);		ide_do_reset (drive);		return;	} else if (rq -> cmd != READ) {		printk ("ide-cd: bad cmd %d\n", rq -> cmd);		cdrom_end_request (0, drive);	} else		cdrom_start_read (drive, block);}/**************************************************************************** * Ioctl handling. * * Routines which queue packet commands take as a final argument a pointer * to an atapi_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_BLOCK_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_BLOCK_OFFSET;}static intcdrom_check_status (ide_drive_t  *drive,		    struct atapi_request_sense *reqbuf){	struct packet_command pc;	memset (&pc, 0, sizeof (pc));	pc.sense_data = reqbuf;	pc.c[0] = TEST_UNIT_READY;        /* 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] = CDROM_STATE_FLAGS (drive)->sanyo_slot % 3;	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 atapi_request_sense *reqbuf){	struct atapi_request_sense my_reqbuf;	int stat;	struct packet_command pc;	if (reqbuf == NULL)		reqbuf = &my_reqbuf;	/* 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_data = reqbuf;		pc.c[0] = ALLOW_MEDIUM_REMOVAL;		pc.c[4] = (lockflag != 0);		stat = cdrom_queue_packet_command (drive, &pc);	}	if (stat == 0)		CDROM_STATE_FLAGS (drive)->door_locked = lockflag;	else {		/* If we got an illegal field error, the drive		   probably cannot lock the door. */		if (reqbuf->sense_key == ILLEGAL_REQUEST &&		    (reqbuf->asc == 0x24 || reqbuf->asc == 0x20)) {			printk ("%s: door locking not supported\n",				drive->name);			CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;			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 intcdrom_eject (ide_drive_t *drive, int ejectflag,	     struct atapi_request_sense *reqbuf){	struct packet_command pc;	memset (&pc, 0, sizeof (pc));	pc.sense_data = reqbuf;	pc.c[0] = START_STOP;	pc.c[4] = 2 + (ejectflag != 0);	return cdrom_queue_packet_command (drive, &pc);}static intcdrom_pause (ide_drive_t *drive, int pauseflag,	     struct atapi_request_sense *reqbuf){	struct packet_command pc;	memset (&pc, 0, sizeof (pc));	pc.sense_data = reqbuf;	pc.c[0] = SCMD_PAUSE_RESUME;	pc.c[8] = !pauseflag;	return cdrom_queue_packet_command (drive, &pc);}static intcdrom_startstop (ide_drive_t *drive, int startflag,		 struct atapi_request_sense *reqbuf){	struct packet_command pc;	memset (&pc, 0, sizeof (pc));	pc.sense_data = reqbuf;	pc.c[0] = START_STOP;	pc.c[1] = 1;	pc.c[4] = startflag;	return cdrom_queue_packet_command (drive, &pc);}static intcdrom_read_capacity (ide_drive_t *drive, unsigned *capacity,		     struct atapi_request_sense *reqbuf){	struct {		unsigned lba;		unsigned blocklen;	} capbuf;	int stat;	struct packet_command pc;	memset (&pc, 0, sizeof (pc));	pc.sense_data = reqbuf;	pc.c[0] = READ_CAPACITY;	pc.buffer = (char *)&capbuf;	pc.buflen = sizeof (capbuf);	stat = cdrom_queue_packet_command (drive, &pc);	if (stat == 0)		*capacity = ntohl (capbuf.lba);	return stat;}static intcdrom_read_tocentry (ide_drive_t *drive, int trackno, int msf_flag,                     int format, char *buf, int buflen,		     struct atapi_request_sense *reqbuf){	struct packet_command pc;	memset (&pc, 0, sizeof (pc));	pc.sense_data = reqbuf;	pc.buffer =  buf;	pc.buflen = buflen;	pc.c[0] = SCMD_READ_TOC;	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 intcdrom_read_toc (ide_drive_t *drive,		struct atapi_request_sense *reqbuf){	int stat, ntracks, i;	struct atapi_toc *toc = drive->cdrom_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);		drive->cdrom_info.toc = toc;	}	if (toc == NULL) {		printk ("%s: No cdrom TOC buffer!\n", drive->name);		return -EIO;	}	/* Check to see if the existing data is still valid.	   If it is, just return. */	if (CDROM_STATE_FLAGS (drive)->toc_valid)		(void) cdrom_check_status (drive, NULL);	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) +				    sizeof (struct atapi_toc_entry),				    reqbuf);	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, 0, 1, 0, (char *)&toc->hdr,				    sizeof (struct atapi_toc_header) +				    (ntracks+1) *				      sizeof (struct atapi_toc_entry),				    reqbuf);	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. */	stat = cdrom_read_tocentry (drive, 0, 1, 1,				    (char *)&ms_tmp, sizeof (ms_tmp),				    reqbuf);	if (stat) return stat;#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. */	stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);	if (stat) toc->capacity = 0x1fffff;	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]		= toc->capacity * SECTORS_PER_FRAME;	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;

⌨️ 快捷键说明

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