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

📄 ide-cd.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * check which way to transfer data	 */	if (rq_data_dir(rq) == WRITE) {		/*		 * write to drive		 */		if (cdrom_write_check_ireason(drive, len, ireason))			return ide_stopped;		xferfunc = HWIF(drive)->atapi_output_bytes;	} else  {		/*		 * read from drive		 */		if (cdrom_read_check_ireason(drive, len, ireason))			return ide_stopped;		xferfunc = HWIF(drive)->atapi_input_bytes;	}	/*	 * transfer data	 */	while (thislen > 0) {		int blen = blen = rq->data_len;		char *ptr = rq->data;		/*		 * bio backed?		 */		if (rq->bio) {			ptr = bio_data(rq->bio);			blen = bio_iovec(rq->bio)->bv_len;		}		if (!ptr) {			printk("%s: confused, missing data\n", drive->name);			break;		}		if (blen > thislen)			blen = thislen;		xferfunc(drive, ptr, blen);		thislen -= blen;		len -= blen;		rq->data_len -= blen;		if (rq->bio)			end_that_request_chunk(rq, 1, blen);		else			rq->data += blen;	}	/*	 * pad, if necessary	 */	if (len > 0) {		while (len > 0) {			int pad = 0;			xferfunc(drive, &pad, sizeof(pad));			len -= sizeof(pad);		}	}	if (HWGROUP(drive)->handler != NULL)		BUG();	ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);	return ide_started;end_request:	if (!rq->data_len)		post_transform_command(rq);	spin_lock_irqsave(&ide_lock, flags);	blkdev_dequeue_request(rq);	end_that_request_last(rq);	HWGROUP(drive)->rq = NULL;	spin_unlock_irqrestore(&ide_lock, flags);	return ide_stopped;}static ide_startstop_t cdrom_write_intr(ide_drive_t *drive){	int stat, ireason, len, sectors_to_transfer, uptodate;	struct cdrom_info *info = drive->driver_data;	int dma_error = 0, dma = info->dma;	u8 lowcyl = 0, highcyl = 0;	struct request *rq = HWGROUP(drive)->rq;	/* Check for errors. */	if (dma) {		info->dma = 0;		if ((dma_error = HWIF(drive)->ide_dma_end(drive))) {			printk("ide-cd: write dma error\n");			__ide_dma_off(drive);		}	}	if (cdrom_decode_status(drive, 0, &stat))		return ide_stopped;	/*	 * using dma, transfer is complete now	 */	if (dma) {		if (dma_error)			return DRIVER(drive)->error(drive, "dma error", stat);		ide_end_request(drive, 1, rq->nr_sectors);		return ide_stopped;	}	/* Read the interrupt reason and the transfer length. */	ireason = HWIF(drive)->INB(IDE_IREASON_REG);	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);	len = lowcyl + (256 * highcyl);	/* 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 (%d blocks)\n",			drive->name, rq->current_nr_sectors);			uptodate = 0;		}		cdrom_end_request(drive, uptodate);		return ide_stopped;	}	/* Check that the drive is expecting to do the same thing we are. */	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_t(int, sectors_to_transfer, rq->current_nr_sectors);		while (this_transfer > 0) {			HWIF(drive)->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(drive, 1);	}	/* re-arm handler */	ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);	return ide_started;}static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive){	struct request *rq = HWGROUP(drive)->rq;#if 0	/* the immediate bit */	rq->cmd[1] = 1 << 3;#endif	rq->timeout = ATAPI_WAIT_PC;	return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);}static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq){	struct cdrom_info *info = drive->driver_data;	struct gendisk *g = drive->disk;	unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;	/*	 * writes *must* be hardware frame aligned	 */	if ((rq->nr_sectors & (sectors_per_frame - 1)) ||	    (rq->sector & (sectors_per_frame - 1))) {		cdrom_end_request(drive, 0);		return ide_stopped;	}	/*	 * disk has become write protected	 */	if (g->policy) {		cdrom_end_request(drive, 0);		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	 */	blk_attempt_remerge(drive->queue, 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!) frame aligned */	info->dma = drive->using_dma ? 1 : 0;	info->cmd = WRITE;	/* Start sending the write request to the drive. */	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);}static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive){	struct request *rq = HWGROUP(drive)->rq;	if (!rq->timeout)		rq->timeout = ATAPI_WAIT_PC;	return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);}static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq){	struct cdrom_info *info = drive->driver_data;	rq->flags |= REQ_QUIET;	info->dma = 0;	info->cmd = 0;	/*	 * sg request	 */	if (rq->bio) {		int mask = drive->queue->dma_alignment;		unsigned long addr = (unsigned long) page_address(bio_page(rq->bio));		info->cmd = rq_data_dir(rq);		info->dma = drive->using_dma;		/*		 * check if dma is safe		 */		if ((rq->data_len & mask) || (addr & mask))			info->dma = 0;	}	/* Start sending the command to the drive. */	return cdrom_start_packet_command(drive, rq->data_len, cdrom_do_newpc_cont);}/**************************************************************************** * cdrom driver request routine. */static ide_startstop_tide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block){	ide_startstop_t action;	struct cdrom_info *info = drive->driver_data;	if (blk_fs_request(rq)) {		if (CDROM_CONFIG_FLAGS(drive)->seeking) {			unsigned long elapsed = jiffies - info->start_seek;			int stat = HWIF(drive)->INB(IDE_STATUS_REG);			if ((stat & SEEK_STAT) != SEEK_STAT) {				if (elapsed < 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_data_dir(rq) == READ)				action = cdrom_start_read(drive, block);			else				action = cdrom_start_write(drive, rq);		}		info->last_block = block;		return action;	} else if (rq->flags & (REQ_PC | REQ_SENSE)) {		return cdrom_do_packet_command(drive);	} else if (rq->flags & REQ_BLOCK_PC) {		return cdrom_do_block_pc(drive, rq);	} else if (rq->flags & REQ_SPECIAL) {		/*		 * right now this can only be a reset...		 */		cdrom_end_request(drive, 1);		return ide_stopped;	}	blk_dump_rq_flags(rq, "ide-cd bad flags");	cdrom_end_request(drive, 0);	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 request req;	struct cdrom_info *info = drive->driver_data;	struct cdrom_device_info *cdi = &info->devinfo;	cdrom_prepare_request(&req);	req.sense = sense;	req.cmd[0] = GPCMD_TEST_UNIT_READY;	req.flags |= REQ_QUIET;#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   */	req.cmd[7] = cdi->sanyo_slot % 3;#endif /* not STANDARD_ATAPI */	return cdrom_queue_packet_command(drive, &req);}/* 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 request req;	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 {		cdrom_prepare_request(&req);		req.sense = sense;		req.cmd[0] = GPCMD_PREVENT_ALLOW_MED

⌨️ 快捷键说明

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