Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94f5a86d authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz
Browse files

ide-cd: merge cdrom_read_intr() and cdrom_write_intr()



Add handling of read requests to cdrom_write_intr(), rename it
to cdrom_rw_intr() and remove no longer needed cdrom_read_intr().

There should be no functionality changes caused by this patch.

Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent 64814f23
Loading
Loading
Loading
Loading
+69 −138
Original line number Diff line number Diff line
@@ -738,125 +738,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
	return 1;
}

/*
 * Interrupt routine.  Called when a read request has completed.
 */
static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
{
	int stat;
	int ireason, len, sectors_to_transfer, nskip;
	struct cdrom_info *info = drive->driver_data;
	u8 lowcyl = 0, highcyl = 0;
	int dma = info->dma, dma_error = 0;

	struct request *rq = HWGROUP(drive)->rq;

	/*
	 * handle dma case
	 */
	if (dma) {
		info->dma = 0;
		dma_error = HWIF(drive)->ide_dma_end(drive);
		if (dma_error) {
			printk(KERN_ERR "%s: DMA read error\n", drive->name);
			ide_dma_off(drive);
		}
	}

	if (cdrom_decode_status(drive, 0, &stat))
		return ide_stopped;

	if (dma) {
		if (!dma_error) {
			ide_end_request(drive, 1, rq->nr_sectors);
			return ide_stopped;
		} else
			return ide_error(drive, "dma error", stat);
	}

	/* Read the interrupt reason and the transfer length. */
	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
	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 filling the current buffer, complain.
		   Otherwise, complete the command normally. */
		if (rq->current_nr_sectors > 0) {
			printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
				drive->name, rq->current_nr_sectors);
			rq->cmd_flags |= REQ_FAILED;
			cdrom_end_request(drive, 0);
		} else
			cdrom_end_request(drive, 1);
		return ide_stopped;
	}

	/* Check that the drive is expecting to do the same thing we are. */
	if (cdrom_read_check_ireason (drive, len, ireason))
		return ide_stopped;

	if (ide_cd_check_transfer_size(drive, len)) {
		cdrom_end_request(drive, 0);
		return ide_stopped;
	}

	/* The number of sectors we need to read from the drive. */
	sectors_to_transfer = len / SECTOR_SIZE;

	/* First, figure out if we need to bit-bucket
	   any of the leading sectors. */
	nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer);

	if (nskip > 0) {
		ide_cd_drain_data(drive, nskip);
		rq->current_nr_sectors -= nskip;
		sectors_to_transfer -= nskip;
	}

	/* Now loop while we still have data to read from the drive. */
	while (sectors_to_transfer > 0) {
		int this_transfer;

		/* If we've filled the present buffer but there's another
		   chained buffer after it, move on. */
		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
			cdrom_end_request(drive, 1);

		/* If the buffers are full, cache the rest of the data in our
		   internal buffer. */
		if (rq->current_nr_sectors == 0) {
			cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
			sectors_to_transfer = 0;
		} else {
			/* Transfer data to the buffers.
			   Figure out how many sectors we can transfer
			   to the current buffer. */
			this_transfer = min_t(int, sectors_to_transfer,
					     rq->current_nr_sectors);

			/* Read this_transfer sectors
			   into the current buffer. */
			while (this_transfer > 0) {
				HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
				rq->buffer += SECTOR_SIZE;
				--rq->nr_sectors;
				--rq->current_nr_sectors;
				++rq->sector;
				--this_transfer;
				--sectors_to_transfer;
			}
		}
	}

	/* Done moving data!  Wait for another interrupt. */
	ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
	return ide_started;
}

/*
 * Try to satisfy some of the current read request from our cached data.
 * Returns nonzero if the request has been completed, zero otherwise.
@@ -916,6 +797,8 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
	return 0;
}

static ide_startstop_t cdrom_rw_intr(ide_drive_t *);

/*
 * Routine to send a read packet command to the drive.
 * This is usually called directly from cdrom_start_read.
@@ -954,7 +837,7 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
	rq->timeout = ATAPI_WAIT_PC;

	/* Send the command to the drive and return. */
	return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
	return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr);
}


@@ -1168,7 +1051,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
/*
 * best way to deal with dma that is not sector aligned right now... note
 * that in this path we are not using ->data or ->buffer at all. this irs
 * can replace cdrom_read_intr() and cdrom_write_intr() in the future.
 * can replace cdrom_rw_intr() in the future.
 */
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
@@ -1343,21 +1226,22 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
	return ide_stopped;
}

static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
static ide_startstop_t cdrom_rw_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;
	xfer_func_t *xferfunc;
	int stat, ireason, len, sectors_to_transfer, uptodate, nskip;
	int dma_error = 0, dma = info->dma, write = rq_data_dir(rq) == WRITE;
	u8 lowcyl = 0, highcyl = 0;

	/* Check for errors. */
	if (dma) {
		info->dma = 0;
		dma_error = HWIF(drive)->ide_dma_end(drive);
		if (dma_error) {
			printk(KERN_ERR "%s: DMA write error\n", drive->name);
			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
					write ? "write" : "read");
			ide_dma_off(drive);
		}
	}
@@ -1385,7 +1269,8 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)

	/* If DRQ is clear, the command has completed. */
	if ((stat & DRQ_STAT) == 0) {
		/* If we're not done writing, complain.
		/*
		 * If we're not done reading/writing, complain.
		 * Otherwise, complete the command normally.
		 */
		uptodate = 1;
@@ -1393,26 +1278,72 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
			printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n",
					drive->name, __FUNCTION__,
					rq->current_nr_sectors);
			if (!write)
				rq->cmd_flags |= REQ_FAILED;
			uptodate = 0;
		}
		cdrom_end_request(drive, uptodate);
		return ide_stopped;
	}

	sectors_to_transfer = len / SECTOR_SIZE;

	/* Check that the drive is expecting to do the same thing we are. */
	if (write) {
		if (cdrom_write_check_ireason(drive, len, ireason))
			return ide_stopped;

	sectors_to_transfer = len / SECTOR_SIZE;
		xferfunc = HWIF(drive)->atapi_output_bytes;
	} else {
		if (cdrom_read_check_ireason(drive, len, ireason))
			return ide_stopped;

		if (ide_cd_check_transfer_size(drive, len)) {
			cdrom_end_request(drive, 0);
			return ide_stopped;
		}

		/*
	 * now loop and write out the data
		 * First, figure out if we need to bit-bucket
		 * any of the leading sectors.
		 */
		nskip = min_t(int, rq->current_nr_sectors
				   - bio_cur_sectors(rq->bio),
				   sectors_to_transfer);

		if (nskip > 0) {
			ide_cd_drain_data(drive, nskip);
			rq->current_nr_sectors -= nskip;
			sectors_to_transfer -= nskip;
		}

		xferfunc = HWIF(drive)->atapi_input_bytes;
	}

	/*
	 * now loop and read/write the data
	 */
	while (sectors_to_transfer > 0) {
		int this_transfer;

		/*
		 * If we've filled the present buffer but there's another
		 * chained buffer after it, move on.
		 */
		if (!write && rq->current_nr_sectors == 0 && rq->nr_sectors)
			cdrom_end_request(drive, 1);

		if (!rq->current_nr_sectors) {
			printk(KERN_ERR "%s: %s: confused, missing data\n",
			if (!write)
				/*
				 * If the buffers are full, cache the rest
				 * of the data in our internal buffer.
				 */
				cdrom_buffer_sectors(drive, rq->sector,
						     sectors_to_transfer);
			else
				printk(KERN_ERR "%s: %s: confused, missing "
						"data\n",
						drive->name, __FUNCTION__);
			break;
		}
@@ -1423,7 +1354,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
		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);
			xferfunc(drive, rq->buffer, SECTOR_SIZE);
			rq->buffer += SECTOR_SIZE;
			--rq->nr_sectors;
			--rq->current_nr_sectors;
@@ -1435,12 +1366,12 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
		/*
		 * current buffer complete, move on
		 */
		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
		if (write && 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);
	ide_set_handler(drive, cdrom_rw_intr, ATAPI_WAIT_PC, NULL);
	return ide_started;
}

@@ -1453,7 +1384,7 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
#endif
	rq->timeout = ATAPI_WAIT_PC;

	return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
	return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr);
}

static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)