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

📄 ide-cd.c

📁 ep9315平台下硬盘驱动的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* End of retry loop. */	} while (pc->stat != 0 && retries >= 0);	/* Return an error if the command failed. */	return pc->stat ? -EIO : 0;}/* * Write handling */static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason){	/* Two notes about IDE interrupt reason here - 0 means that	 * the drive wants to receive data from us, 2 means that	 * the drive is expecting data from us.	 */	ireason &= 3;	if (ireason == 2) {		/* Whoops... The drive wants to send data. */		printk("%s: cdrom_write_intr: wrong transfer direction!\n",			drive->name);		/* Throw some data at the drive so it doesn't hang		   and quit this request. */		while (len > 0) {			int dum = 0;			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum));			len -= sizeof(dum);		}	} else {		/* Drive wants a command packet, or invalid ireason... */		printk("%s: cdrom_write_intr: bad interrupt reason %d\n",			drive->name, ireason);	}	cdrom_end_request(drive, 0);	return 1;}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 i, dma_error = 0, dma = info->dma;	u8 lowcyl = 0, highcyl = 0;	ide_startstop_t startstop;	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");			HWIF(drive)->ide_dma_off(drive);		}	}	if (cdrom_decode_status(&startstop, drive, 0, &stat)) {		printk("ide-cd: write_intr decode_status bad\n");		return startstop;	} 	/*	 * using dma, transfer is complete now	 */	if (dma) {		if (dma_error)			return DRIVER(drive)->error(drive, "dma error", stat);		rq = HWGROUP(drive)->rq;		for (i = rq->nr_sectors; i > 0;) {			i -= rq->current_nr_sectors;			ide_cdrom_end_request(drive, 1);		}		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 (%ld 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 (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) {			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, 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(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	 */	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) {				int stat = HWIF(drive)->INB(IDE_STATUS_REG);				if ((stat & SEEK_STAT) != SEEK_STAT) {					if (time_before(jiffies, info->start_seek + 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;		}		case PACKET_COMMAND:		case REQUEST_SENSE_COMMAND: {			return cdrom_do_packet_command(drive);		}		case RESET_DRIVE_COMMAND: {			cdrom_end_request(drive, 1);			return ide_do_reset(drive);		}		default: {			printk("ide-cd: bad cmd %d\n", rq->cmd);			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 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;	str

⌨️ 快捷键说明

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