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

📄 ide-cd.c

📁 em85xx的大硬盘修正代码包
💻 C
📖 第 1 页 / 共 5 页
字号:
	} 	/*	 * using dma, transfer is complete now	 */	if (dma) {		if (dma_error)			return ide_error(drive, "dma error", stat);		rq = HWGROUP(drive)->rq;		for (i = rq->nr_sectors; i > 0;) {			i -= rq->current_nr_sectors;			ide_end_request(1, HWGROUP(drive));		}		return ide_stopped;	}	/* Read the interrupt reason and the transfer length. */	ireason = IN_BYTE(IDE_NSECTOR_REG);	len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG);	/* If DRQ is clear, the command has completed. */	if ((stat & DRQ_STAT) == 0) {		/* If we're not done writing, complain.		 * Otherwise, complete the command normally.		 */		uptodate = 1;		if (rq->current_nr_sectors > 0) {			printk("%s: write_intr: data underrun (%ld blocks)\n",			drive->name, rq->current_nr_sectors);			uptodate = 0;		}		cdrom_end_request(uptodate, drive);		return ide_stopped;	}	/* Check that the drive is expecting to do the same thing we are. */	if (ireason & 3)		if (cdrom_write_check_ireason(drive, len, ireason))			return ide_stopped;	sectors_to_transfer = len / SECTOR_SIZE;	/*	 * now loop and write out the data	 */	while (sectors_to_transfer > 0) {		int this_transfer;		if (!rq->current_nr_sectors) {			printk("ide-cd: write_intr: oops\n");			break;		}		/*		 * Figure out how many sectors we can transfer		 */		this_transfer = MIN(sectors_to_transfer,rq->current_nr_sectors);		while (this_transfer > 0) {			atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);			rq->buffer += SECTOR_SIZE;			--rq->nr_sectors;			--rq->current_nr_sectors;			++rq->sector;			--this_transfer;			--sectors_to_transfer;		}		/*		 * current buffer complete, move on		 */		if (rq->current_nr_sectors == 0 && rq->nr_sectors)			cdrom_end_request (1, drive);	}	/* re-arm handler */	ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL);	return ide_started;}static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive){	struct packet_command pc;	/* packet_command_t pc; */	struct request *rq = HWGROUP(drive)->rq;	unsigned nframes, frame;	nframes = rq->nr_sectors >> 2;	frame = rq->sector >> 2;	memset(&pc.c, 0, sizeof(pc.c));	/*	 * we might as well use WRITE_12, but none of the device I have	 * support the streaming feature anyway, so who cares.	 */	pc.c[0] = GPCMD_WRITE_10;#if 0	/* the immediate bit */	pc.c[1] = 1 << 3;#endif	pc.c[7] = (nframes >> 8) & 0xff;	pc.c[8] = nframes & 0xff;	put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]);	pc.timeout = 2 * WAIT_CMD;	return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);}static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq){	struct cdrom_info *info = drive->driver_data;	/*	 * writes *must* be 2kB frame aligned	 */	if ((rq->nr_sectors & 3) || (rq->sector & 3)) {		cdrom_end_request(0, drive);		return ide_stopped;	}	/*	 * for dvd-ram and such media, it's a really big deal to get	 * big writes all the time. so scour the queue and attempt to	 * remerge requests, often the plugging will not have had time	 * to do this properly	 */	cdrom_attempt_remerge(drive, rq);	info->nsectors_buffered = 0;        /* use dma, if possible. we don't need to check more, since we	 * know that the transfer is always (at least!) 2KB aligned */	info->dma = drive->using_dma ? 1 : 0;	info->cmd = WRITE;	/* Start sending the read request to the drive. */	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);}/**************************************************************************** * cdrom driver request routine. */static ide_startstop_tide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block){	ide_startstop_t action;	struct cdrom_info *info = drive->driver_data;	switch (rq->cmd) {		case WRITE:		case READ: {			if (CDROM_CONFIG_FLAGS(drive)->seeking) {				unsigned long elpased = jiffies - info->start_seek;				int stat = GET_STAT();				if ((stat & SEEK_STAT) != SEEK_STAT) {					if (elpased < IDECD_SEEK_TIMEOUT) {						ide_stall_queue(drive, IDECD_SEEK_TIMER);						return ide_stopped;					}					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, rq);			}			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 long *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.quiet = 1;	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 se

⌨️ 快捷键说明

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