コード例 #1
0
ファイル: stb03xxx.c プロジェクト: leonsh/eldk30ppc
ide_startstop_t redwood_ide_intr (ide_drive_t *drive)
{
	int i;
	byte dma_stat;
	unsigned int nsect;
	ide_hwgroup_t *hwgroup = HWGROUP(drive);
	struct request *rq = hwgroup->rq;
	unsigned long block,b1,b2,b3,b4;

	nsect = rq->current_nr_sectors;

	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);

	rq->sector += nsect;
	rq->buffer += nsect<<9;
	rq->errors = 0;
	i = (rq->nr_sectors -= nsect);
	ide_end_request(1, HWGROUP(drive));
	if (i > 0) {
		b1 = IN_BYTE(IDE_SECTOR_REG);
		b2 = IN_BYTE(IDE_LCYL_REG);
		b3 = IN_BYTE(IDE_HCYL_REG);
		b4 = IN_BYTE(IDE_SELECT_REG);
		block = ((b4 & 0x0f) << 24) + (b3 << 16) + (b2 << 8) + (b1);
		block++;
		if (drive->select.b.lba) {
			OUT_BYTE(block,IDE_SECTOR_REG);
			OUT_BYTE(block>>=8,IDE_LCYL_REG);
			OUT_BYTE(block>>=8,IDE_HCYL_REG);
			OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
		} else {
コード例 #2
0
ファイル: ide-iops.c プロジェクト: JBTech/ralink_rt5350
/*
 * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms
 * during an atapi drive reset operation. If the drive has not yet responded,
 * and we have not yet hit our maximum waiting time, then the timer is restarted
 * for another 50ms.
 */
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
{
	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
	ide_hwif_t *hwif	= HWIF(drive);
	u8 stat;

	SELECT_DRIVE(drive);
	udelay (10);

	if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
		printk("%s: ATAPI reset complete\n", drive->name);
	} else {
		if (time_before(jiffies, hwgroup->poll_timeout)) {
			if (HWGROUP(drive)->handler != NULL)
				BUG();
			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
			/* continue polling */
			return ide_started;
		}
		/* end of polling */
		hwgroup->poll_timeout = 0;
		printk("%s: ATAPI reset timed-out, status=0x%02x\n",
				drive->name, stat);
		/* do it the old fashioned way */
		return do_reset1(drive, 1);
	}
	/* done polling */
	hwgroup->poll_timeout = 0;
	return ide_stopped;
}
コード例 #3
0
ファイル: ide-pmac.c プロジェクト: liexusong/Linux-2.4.16
static void idepmac_wake_device(ide_drive_t *drive, int used_dma)
 {
	/* We force the IDE subdriver to check for a media change
	 * This must be done first or we may lost the condition
	 *
	 * Problem: This can schedule. I moved the block device
	 * wakeup almost late by priority because of that.
	 */
	if (DRIVER(drive) && DRIVER(drive)->media_change)
		DRIVER(drive)->media_change(drive);

	/* We kick the VFS too (see fix in ide.c revalidate) */
	check_disk_change(MKDEV(HWIF(drive)->major, (drive->select.b.unit) << PARTN_BITS));
	
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
	/* We re-enable DMA on the drive if it was active. */
	/* This doesn't work with the CD-ROM in the media-bay, probably
	 * because of a pending unit attention. The problem if that if I
	 * clear the error, the filesystem dies.
	 */
	if (used_dma && !ide_spin_wait_hwgroup(drive)) {
		/* Lock HW group */
		HWGROUP(drive)->busy = 1;
		pmac_ide_check_dma(drive);
		HWGROUP(drive)->busy = 0;
		spin_unlock_irq(&io_request_lock);
	}
#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
}
コード例 #4
0
int ide_end_request (ide_drive_t *drive, int uptodate)
{
	struct request *rq;
	unsigned long flags;
	int ret = 1;

	spin_lock_irqsave(&io_request_lock, flags);
	rq = HWGROUP(drive)->rq;

	/*
	 * decide whether to reenable DMA -- 3 is a random magic for now,
	 * if we DMA timeout more than 3 times, just stay in PIO
	 */
	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
		drive->state = 0;
		HWGROUP(drive)->hwif->ide_dma_on(drive);
	}

	if (!end_that_request_first(rq, uptodate, drive->name)) {
		add_blkdev_randomness(MAJOR(rq->rq_dev));
		blkdev_dequeue_request(rq);
		HWGROUP(drive)->rq = NULL;
		end_that_request_last(rq);
		ret = 0;
	}

	spin_unlock_irqrestore(&io_request_lock, flags);
	return ret;
}
コード例 #5
0
ファイル: ide-iops.c プロジェクト: JBTech/ralink_rt5350
/*
 * reset_pollfunc() gets invoked to poll the interface for completion every 50ms
 * during an ide reset operation. If the drives have not yet responded,
 * and we have not yet hit our maximum waiting time, then the timer is restarted
 * for another 50ms.
 */
static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
{
	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
	ide_hwif_t *hwif	= HWIF(drive);
	u8 tmp;

	if (hwif->reset_poll != NULL) {
		if (hwif->reset_poll(drive)) {
			printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
				hwif->name, drive->name);
			return ide_stopped;
		}
	}

	if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
		if (time_before(jiffies, hwgroup->poll_timeout)) {
			if (HWGROUP(drive)->handler != NULL)
				BUG();
			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
			/* continue polling */
			return ide_started;
		}
		printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
		drive->failures++;
	} else  {
		printk("%s: reset: ", hwif->name);
		if ((tmp = hwif->INB(IDE_ERROR_REG)) == 1) {
			printk("success\n");
			drive->failures = 0;
		} else {
			drive->failures++;
#if FANCY_STATUS_DUMPS
			printk("master: ");
			switch (tmp & 0x7f) {
				case 1: printk("passed");
					break;
				case 2: printk("formatter device error");
					break;
				case 3: printk("sector buffer error");
					break;
				case 4: printk("ECC circuitry error");
					break;
				case 5: printk("controlling MPU error");
					break;
				default:printk("error (0x%02x?)", tmp);
			}
			if (tmp & 0x80)
				printk("; slave: failed");
			printk("\n");
#else
			printk("failed\n");
#endif /* FANCY_STATUS_DUMPS */
		}
	}
	hwgroup->poll_timeout = 0;	/* done polling */
	return ide_stopped;
}
コード例 #6
0
ファイル: pdc4030.c プロジェクト: chinnyannieb/empeg-hijack
/*
 * promise_read_intr() is the handler for disk read/multread interrupts
 */
static ide_startstop_t promise_read_intr (ide_drive_t *drive)
{
	byte stat;
	int i;
	unsigned int sectors_left, sectors_avail, nsect;
	struct request *rq;

	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
		return ide_error(drive, "promise_read_intr", stat);
	}

read_again:
	do {
	    sectors_left = IN_BYTE(IDE_NSECTOR_REG);
	    IN_BYTE(IDE_SECTOR_REG);
	} while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);
	rq = HWGROUP(drive)->rq;
	sectors_avail = rq->nr_sectors - sectors_left;

read_next:
	rq = HWGROUP(drive)->rq;
	if ((nsect = rq->current_nr_sectors) > sectors_avail)
		nsect = sectors_avail;
	sectors_avail -= nsect;
	ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
#ifdef DEBUG
	printk("%s:  promise_read: sectors(%ld-%ld), buffer=0x%08lx, "
	       "remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, 
	       (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
#endif
	rq->sector += nsect;
	rq->buffer += nsect<<9;
	rq->errors = 0;
	i = (rq->nr_sectors -= nsect);
	if ((rq->current_nr_sectors -= nsect) <= 0)
		ide_end_request(1, HWGROUP(drive));
	if (i > 0) {
		if (sectors_avail)
		    goto read_next;
		stat = GET_STAT();
		if(stat & DRQ_STAT)
		    goto read_again;
		if(stat & BUSY_STAT) {
		    ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL);
		    return ide_started;
		}
		printk("Ah! promise read intr: sectors left !DRQ !BUSY\n");
		return ide_error(drive, "promise read intr", stat);
	}
	return ide_stopped;
}
コード例 #7
0
ファイル: ide-io.c プロジェクト: masbog/iphonelinux-kernel
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat)
{
	struct request *rq;
	u8 err;

	err = ide_dump_status(drive, msg, stat);

	if ((rq = HWGROUP(drive)->rq) == NULL)
		return ide_stopped;

	/* retry only "normal" I/O: */
	if (!blk_fs_request(rq)) {
		rq->errors = 1;
		ide_end_drive_cmd(drive, stat, err);
		return ide_stopped;
	}

	if (rq->rq_disk) {
		ide_driver_t *drv;

		drv = *(ide_driver_t **)rq->rq_disk->private_data;
		return drv->error(drive, rq, stat, err);
	} else
		return __ide_error(drive, rq, stat, err);
}
コード例 #8
0
ファイル: ide-io.c プロジェクト: gizm0n/wl500g
int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
{
	unsigned int nr_bytes = nr_sectors << 9;
	struct request *rq = HWGROUP(drive)->rq;
	int rc, error = 0;

	if (!nr_bytes) {
		if (blk_pc_request(rq))
			nr_bytes = rq->data_len;
		else
			nr_bytes = rq->hard_cur_sectors << 9;
	}

	/*
	 * if failfast is set on a request, override number of sectors
	 * and complete the whole request right now
	 */
	if (blk_noretry_request(rq) && uptodate <= 0)
		nr_bytes = rq->hard_nr_sectors << 9;

	if (blk_fs_request(rq) == 0 && uptodate <= 0 && rq->errors == 0)
		rq->errors = -EIO;

	if (uptodate <= 0)
		error = uptodate ? uptodate : -EIO;

	rc = ide_end_rq(drive, rq, error, nr_bytes);
	if (rc == 0)
		drive->hwif->hwgroup->rq = NULL;

	return rc;
}
コード例 #9
0
static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
{
	idescsi_scsi_t *scsi = drive_to_idescsi(drive);
	struct request *rq = HWGROUP(drive)->rq;
	struct ide_atapi_pc *pc = (struct ide_atapi_pc *) rq->special;
	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
	struct Scsi_Host *host;
	int errors = rq->errors;
	unsigned long flags;

	if (!blk_special_request(rq) && !blk_sense_request(rq)) {
		ide_end_request(drive, uptodate, nrsecs);
		return 0;
	}
	ide_end_drive_cmd (drive, 0, 0);
	if (blk_sense_request(rq)) {
		struct ide_atapi_pc *opc = (struct ide_atapi_pc *) rq->buffer;
		if (log) {
			printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
			ide_scsi_hex_dump(pc->buf, 16);
		}
		memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buf,
			SCSI_SENSE_BUFFERSIZE);
		kfree(pc->buf);
		kfree(pc);
		blk_put_request(rq);
		pc = opc;
		rq = pc->rq;
		pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
				(((pc->flags & PC_FLAG_TIMEDOUT) ?
				  DID_TIME_OUT :
				  DID_OK) << 16);
	} else if (pc->flags & PC_FLAG_TIMEDOUT) {
		if (log)
			printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
					drive->name, pc->scsi_cmd->serial_number);
		pc->scsi_cmd->result = DID_TIME_OUT << 16;
	} else if (errors >= ERROR_MAX) {
		pc->scsi_cmd->result = DID_ERROR << 16;
		if (log)
			printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
	} else if (errors) {
		if (log)
			printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
		if (!idescsi_check_condition(drive, rq))
			/* we started a request sense, so we'll be back, exit for now */
			return 0;
		pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
	} else {
		pc->scsi_cmd->result = DID_OK << 16;
	}
	host = pc->scsi_cmd->device->host;
	spin_lock_irqsave(host->host_lock, flags);
	pc->done(pc->scsi_cmd);
	spin_unlock_irqrestore(host->host_lock, flags);
	kfree(pc);
	blk_put_request(rq);
	scsi->pc = NULL;
	return 0;
}
コード例 #10
0
ファイル: sgiioc4.c プロジェクト: BackupTheBerlios/arp2-svn
static int sgiioc4_ide_dma_setup(ide_drive_t *drive)
{
	struct request *rq = HWGROUP(drive)->rq;
	unsigned int count = 0;
	int ddir;

	if (rq_data_dir(rq))
		ddir = PCI_DMA_TODEVICE;
	else
		ddir = PCI_DMA_FROMDEVICE;

	if (!(count = sgiioc4_build_dma_table(drive, rq, ddir))) {
		/* try PIO instead of DMA */
		ide_map_sg(drive, rq);
		return 1;
	}

	if (rq_data_dir(rq))
		/* Writes TO the IOC4 FROM Main Memory */
		ddir = IOC4_DMA_READ;
	else
		/* Writes FROM the IOC4 TO Main Memory */
		ddir = IOC4_DMA_WRITE;

	sgiioc4_configure_for_dma(ddir, drive);

	return 0;
}
コード例 #11
0
static int scc_dma_setup(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	struct request *rq = HWGROUP(drive)->rq;
	unsigned int reading;
	u8 dma_stat;

	if (rq_data_dir(rq))
		reading = 0;
	else
		reading = 1 << 3;

	/* fall back to pio! */
	if (!ide_build_dmatable(drive, rq)) {
		ide_map_sg(drive, rq);
		return 1;
	}

	/* PRD table */
	out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);

	/* specify r/w */
	out_be32((void __iomem *)hwif->dma_base, reading);

	/* read DMA status for INTR & ERROR flags */
	dma_stat = in_be32((void __iomem *)(hwif->dma_base + 4));

	/* clear INTR & ERROR flags */
	out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
	drive->waiting_for_dma = 1;
	return 0;
}
コード例 #12
0
ファイル: ide-iops.c プロジェクト: JBTech/ralink_rt5350
void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry)
{
	unsigned long flags;
	ide_hwgroup_t *hwgroup = HWGROUP(drive);
	ide_hwif_t *hwif = HWIF(drive);
	
	spin_lock_irqsave(&io_request_lock, flags);
	
	if(hwgroup->handler)
		BUG();
	hwgroup->handler	= handler;
	hwgroup->expiry		= expiry;
	hwgroup->timer.expires	= jiffies + timeout;
	add_timer(&hwgroup->timer);
	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
	/* Drive takes 400nS to respond, we must avoid the IRQ being
	   serviced before that. 
	   
	   FIXME: we could skip this delay with care on non shared
	   devices 
	   
	   For DMA transfers highpoint have a neat trick we could
	   use. When they take an IRQ they check STS but also that
	   the DMA count is not zero (see hpt's own driver)
	*/
	ndelay(400);
	spin_unlock_irqrestore(&io_request_lock, flags);
}
コード例 #13
0
ファイル: ide-io.c プロジェクト: Tigrouzen/k1099
int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
{
	unsigned int nr_bytes = nr_sectors << 9;
	struct request *rq;
	unsigned long flags;
	int ret = 1;

	/*
	 * room for locking improvements here, the calls below don't
	 * need the queue lock held at all
	 */
	spin_lock_irqsave(&ide_lock, flags);
	rq = HWGROUP(drive)->rq;

	if (!nr_bytes) {
		if (blk_pc_request(rq))
			nr_bytes = rq->data_len;
		else
			nr_bytes = rq->hard_cur_sectors << 9;
	}

	ret = __ide_end_request(drive, rq, uptodate, nr_bytes, 1);

	spin_unlock_irqrestore(&ide_lock, flags);
	return ret;
}
コード例 #14
0
/*
 * Handler for command with PIO data-in phase (Read/Read Multiple).
 */
static ide_startstop_t task_in_intr(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	struct request *rq = HWGROUP(drive)->rq;
	u8 stat = ide_read_status(drive);

	/* Error? */
	if (stat & ERR_STAT)
		return task_error(drive, rq, __func__, stat);

	/* Didn't want any data? Odd. */
	if (!(stat & DRQ_STAT))
		return task_in_unexpected(drive, rq, stat);

	ide_pio_datablock(drive, rq, 0);

	/* Are we done? Check status and finish transfer. */
	if (!hwif->nleft) {
		stat = wait_drive_not_busy(drive);
		if (!OK_STAT(stat, 0, BAD_STAT))
			return task_error(drive, rq, __func__, stat);
		task_end_request(drive, rq, stat);
		return ide_stopped;
	}

	/* Still data left to transfer. */
	ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);

	return ide_started;
}
コード例 #15
0
ファイル: triton.c プロジェクト: openmach/openmach
/*
 * build_dmatable() prepares a dma request.
 * Returns 0 if all went okay, returns 1 otherwise.
 */
static int build_dmatable (ide_drive_t *drive)
{
	struct request *rq = HWGROUP(drive)->rq;
	struct buffer_head *bh = rq->bh;
	unsigned long size, addr, *table = HWIF(drive)->dmatable;
	unsigned int count = 0;

	do {
		/*
		 * Determine addr and size of next buffer area.  We assume that
		 * individual virtual buffers are always composed linearly in
		 * physical memory.  For example, we assume that any 8kB buffer
		 * is always composed of two adjacent physical 4kB pages rather
		 * than two possibly non-adjacent physical 4kB pages.
		 */
		if (bh == NULL) {  /* paging and tape requests have (rq->bh == NULL) */
			addr = virt_to_bus (rq->buffer);
#ifdef CONFIG_BLK_DEV_IDETAPE
			if (drive->media == ide_tape)
				size = drive->tape.pc->request_transfer;
			else
#endif /* CONFIG_BLK_DEV_IDETAPE */	
			size = rq->nr_sectors << 9;
		} else {
			/* group sequential buffers into one large buffer */
			addr = virt_to_bus (bh->b_data);
			size = bh->b_size;
			while ((bh = bh->b_reqnext) != NULL) {
				if ((addr + size) != virt_to_bus (bh->b_data))
					break;
				size += bh->b_size;
			}
		}

		/*
		 * Fill in the dma table, without crossing any 64kB boundaries.
		 * We assume 16-bit alignment of all blocks.
		 */
		while (size) {
			if (++count >= PRD_ENTRIES) {
				printk("%s: DMA table too small\n", drive->name);
				return 1; /* revert to PIO for this request */
			} else {
				unsigned long bcount = 0x10000 - (addr & 0xffff);
				if (bcount > size)
					bcount = size;
				*table++ = addr;
				*table++ = bcount;
				addr += bcount;
				size -= bcount;
			}
		}
	} while (bh != NULL);
	if (count) {
		*--table |= 0x80000000;	/* set End-Of-Table (EOT) bit */
		return 0;
	}
	printk("%s: empty DMA table?\n", drive->name);
	return 1;	/* let the PIO routines handle this weirdness */
}
コード例 #16
0
ファイル: pdc4030.c プロジェクト: chinnyannieb/empeg-hijack
/*
 * do_pdc4030_io() is called from do_rw_disk, having had the block number
 * already set up. It issues a READ or WRITE command to the Promise
 * controller, assuming LBA has been used to set up the block number.
 */
ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
{
	unsigned long timeout;
	byte stat;

	if (rq->cmd == READ) {
	    ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
	    OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
/* The card's behaviour is odd at this point. If the data is
   available, DRQ will be true, and no interrupt will be
   generated by the card. If this is the case, we need to simulate
   an interrupt. Ugh! Otherwise, if an interrupt will occur, bit0
   of the SELECT register will be high, so we can just return and
   be interrupted.*/
	    timeout = jiffies + HZ/20; /* 50ms wait */
	    do {
		stat=GET_STAT();
		if(stat & DRQ_STAT) {
                    disable_irq(HWIF(drive)->irq);
		    ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
                    enable_irq(HWIF(drive)->irq);
		    return ide_stopped;
		}
		if(IN_BYTE(IDE_SELECT_REG) & 0x01)
		    return ide_started;
		udelay(1);
	    } while (time_before(jiffies, timeout));
	    printk("%s: reading: No DRQ and not waiting - Odd!\n",
		   drive->name);
	    return ide_started;
	}
	if (rq->cmd == WRITE) {
	    ide_startstop_t startstop;
	    OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
	    if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
		printk("%s: no DRQ after issuing PROMISE_WRITE\n", drive->name);
		return startstop;
	    }
	    if (!drive->unmask)
		__cli();	/* local CPU only */
	    HWGROUP(drive)->wrq = *rq; /* scratchpad */
	    return promise_write(drive);
	}
	printk("%s: bad command: %d\n", drive->name, rq->cmd);
	ide_end_request(0, HWGROUP(drive));
	return ide_stopped;
}
コード例 #17
0
static int idescsi_eh_abort (struct scsi_cmnd *cmd)
{
	idescsi_scsi_t *scsi  = scsihost_to_idescsi(cmd->device->host);
	ide_drive_t    *drive = scsi->drive;
	int		busy;
	int             ret   = FAILED;

	/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */

	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
		printk (KERN_WARNING "ide-scsi: abort called for %lu\n", cmd->serial_number);

	if (!drive) {
		printk (KERN_WARNING "ide-scsi: Drive not set in idescsi_eh_abort\n");
		WARN_ON(1);
		goto no_drive;
	}

	/* First give it some more time, how much is "right" is hard to say :-( */

	busy = ide_wait_not_busy(HWIF(drive), 100);	/* FIXME - uses mdelay which causes latency? */
	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
		printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");

	spin_lock_irq(&ide_lock);

	/* If there is no pc running we're done (our interrupt took care of it) */
	if (!scsi->pc) {
		ret = SUCCESS;
		goto ide_unlock;
	}

	/* It's somewhere in flight. Does ide subsystem agree? */
	if (scsi->pc->scsi_cmd->serial_number == cmd->serial_number && !busy &&
	    elv_queue_empty(drive->queue) && HWGROUP(drive)->rq != scsi->pc->rq) {
		/*
		 * FIXME - not sure this condition can ever occur
		 */
		printk (KERN_ERR "ide-scsi: cmd aborted!\n");

		if (blk_sense_request(scsi->pc->rq))
			kfree(scsi->pc->buf);
		/* we need to call blk_put_request twice. */
		blk_put_request(scsi->pc->rq);
		blk_put_request(scsi->pc->rq);
		kfree(scsi->pc);
		scsi->pc = NULL;

		ret = SUCCESS;
	}

ide_unlock:
	spin_unlock_irq(&ide_lock);
no_drive:
	if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
		printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");

	return ret;
}
コード例 #18
0
ファイル: ide-io.c プロジェクト: masbog/iphonelinux-kernel
void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
{
	unsigned long flags;
	struct request *rq;

	spin_lock_irqsave(&ide_lock, flags);
	rq = HWGROUP(drive)->rq;
	spin_unlock_irqrestore(&ide_lock, flags);

	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
		ide_task_t *task = (ide_task_t *)rq->special;

		if (rq->errors == 0)
			rq->errors = !OK_STAT(stat, ATA_DRDY, BAD_STAT);

		if (task) {
			struct ide_taskfile *tf = &task->tf;

			tf->error = err;
			tf->status = stat;

			drive->hwif->tp_ops->tf_read(drive, task);

			if (task->tf_flags & IDE_TFLAG_DYN)
				kfree(task);
		}
	} else if (blk_pm_request(rq)) {
		struct request_pm_state *pm = rq->data;

		ide_complete_power_step(drive, rq);
		if (pm->pm_step == IDE_PM_COMPLETED)
			ide_complete_pm_request(drive, rq);
		return;
	}

	spin_lock_irqsave(&ide_lock, flags);
	HWGROUP(drive)->rq = NULL;
	rq->errors = err;
	if (unlikely(__blk_end_request(rq, (rq->errors ? -EIO : 0),
				       blk_rq_bytes(rq))))
		BUG();
	spin_unlock_irqrestore(&ide_lock, flags);
}
コード例 #19
0
int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
					  int nr_sectors)
{
	int ret = 1;

	BUG_ON(!(rq->flags & REQ_STARTED));

	/*
	 * if failfast is set on a request, override number of sectors and
	 * complete the whole request right now
	 */
	if (blk_noretry_request(rq) && end_io_error(uptodate))
		nr_sectors = rq->hard_nr_sectors;

	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
 		rq->errors = -EIO;
	/*
	 * decide whether to reenable DMA -- 3 is a random magic for now,
	 * if we DMA timeout more than 3 times, just stay in PIO
	 */
	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
		drive->state = 0;
		HWGROUP(drive)->hwif->ide_dma_on(drive);
	}

	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
		add_disk_randomness(rq->rq_disk);

		if (blk_rq_tagged(rq))
			blk_queue_end_tag(drive->queue, rq);

		blkdev_dequeue_request(rq);
		HWGROUP(drive)->rq = NULL;
		end_that_request_last(rq);
		ret = 0;
	}
	return ret;
}
コード例 #20
0
ファイル: ide-io.c プロジェクト: gizm0n/wl500g
int ide_end_rq(ide_drive_t *drive, struct request *rq, int error,
	       unsigned int nr_bytes)
{
	/*
	 * decide whether to reenable DMA -- 3 is a random magic for now,
	 * if we DMA timeout more than 3 times, just stay in PIO
	 */
	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
		drive->state = 0;
		HWGROUP(drive)->hwif->ide_dma_on(drive);
	}

	return blk_end_request(rq, error, nr_bytes);
}
コード例 #21
0
/*
 * dma_intr() is the handler for disk read/write DMA interrupts
 */
void ide_dma_intr (ide_drive_t *drive)
{
	int i;
	byte stat, dma_stat;

	DPRINT("ide_dma_intr\n");
	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
	stat = GET_STAT();			/* get drive status */
	DPRINT("stat=%02x\n", stat);
	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
		if (!dma_stat) {
			struct request *rq = HWGROUP(drive)->rq;
			rq = HWGROUP(drive)->rq;
			for (i = rq->nr_sectors; i > 0;) {
				i -= rq->current_nr_sectors;
				ide_end_request(1, HWGROUP(drive));
			}
			return;
		}
		printk("%s: dma_intr: bad DMA status\n", drive->name);
	}
	ide__sti();	/* local CPU only */
	ide_error(drive, "dma_intr", stat);
}
コード例 #22
0
static int
sgiioc4_ide_dma_read(ide_drive_t * drive)
{
	struct request *rq = HWGROUP(drive)->rq;
	unsigned int count = 0;

	if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_FROMDEVICE))) {
		/* try PIO instead of DMA */
		return 1;
	}
	/* Writes FROM the IOC4 TO Main Memory */
	sgiioc4_configure_for_dma(IOC4_DMA_WRITE, drive);

	return 0;
}
コード例 #23
0
ファイル: triton.c プロジェクト: openmach/openmach
/*
 * dma_intr() is the handler for disk read/write DMA interrupts
 */
static void dma_intr (ide_drive_t *drive)
{
	byte stat, dma_stat;
	int i;
	struct request *rq = HWGROUP(drive)->rq;
	unsigned short dma_base = HWIF(drive)->dma_base;

	dma_stat = inb(dma_base+2);		/* get DMA status */
	outb(inb(dma_base)&~1, dma_base);	/* stop DMA operation */
	stat = GET_STAT();			/* get drive status */
	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
		if ((dma_stat & 7) == 4) {	/* verify good DMA status */
			rq = HWGROUP(drive)->rq;
			for (i = rq->nr_sectors; i > 0;) {
				i -= rq->current_nr_sectors;
				ide_end_request(1, HWGROUP(drive));
			}
			return;
		}
		printk("%s: bad DMA status: 0x%02x\n", drive->name, dma_stat);
	}
	sti();
	ide_error(drive, "dma_intr", stat);
}
コード例 #24
0
ファイル: ide-iops.c プロジェクト: Dronevery/JetsonTK1-kernel
/*
 * This should get invoked any time we exit the driver to
 * wait for an interrupt response from a drive.  handler() points
 * at the appropriate code to handle the next interrupt, and a
 * timer is started to prevent us from waiting forever in case
 * something goes wrong (see the ide_timer_expiry() handler later on).
 *
 * See also ide_execute_command
 */
static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler,
		      unsigned int timeout, ide_expiry_t *expiry)
{
	ide_hwgroup_t *hwgroup = HWGROUP(drive);

	if (hwgroup->handler != NULL) {
		printk(KERN_CRIT "%s: ide_set_handler: handler not null; "
			"old=%p, new=%p\n",
			drive->name, hwgroup->handler, handler);
	}
	hwgroup->handler	= handler;
	hwgroup->expiry		= expiry;
	hwgroup->timer.expires	= jiffies + timeout;
	add_timer(&hwgroup->timer);
}
コード例 #25
0
ファイル: siimage.c プロジェクト: BackupTheBerlios/wl530g-svn
static int siimage_reset_poll (ide_drive_t *drive)
{
	if (SATA_STATUS_REG) {
		ide_hwif_t *hwif	= HWIF(drive);

		if ((hwif->INL(SATA_STATUS_REG) & 0x03) != 0x03) {
			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
				hwif->name, hwif->INL(SATA_STATUS_REG));
			HWGROUP(drive)->poll_timeout = 0;
			return ide_started;
		}
		return 0;
	} else {
		return 0;
	}
}
コード例 #26
0
static int
sgiioc4_ide_dma_write(ide_drive_t * drive)
{
	struct request *rq = HWGROUP(drive)->rq;
	unsigned int count = 0;

	if (!(count = sgiioc4_build_dma_table(drive, rq, PCI_DMA_TODEVICE))) {
		/* try PIO instead of DMA */
		return 1;
	}

	sgiioc4_configure_for_dma(IOC4_DMA_READ, drive);
	/* Writes TO the IOC4 FROM Main Memory */

	return 0;
}
コード例 #27
0
ファイル: tc86c001.c プロジェクト: E-LLP/n900
/*
 * HACKITY HACK
 *
 * This is a workaround for the limitation 5 of the TC86C001 IDE controller:
 * if a DMA transfer terminates prematurely, the controller leaves the device's
 * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or
 * set the interrupt bit in the DMA status register), thus no PCI interrupt
 * will occur until a DMA transfer has been successfully completed.
 *
 * We work around this by initiating dummy, zero-length DMA transfer on
 * a DMA timeout expiration. I found no better way to do this with the current
 * IDE core than to temporarily replace a higher level driver's timer expiry
 * handler with our own backing up to that handler in case our recovery fails.
 */
static int tc86c001_timer_expiry(ide_drive_t *drive)
{
	ide_hwif_t *hwif	= HWIF(drive);
	ide_expiry_t *expiry	= ide_get_hwifdata(hwif);
	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
	u8 dma_stat		= inb(hwif->dma_base + ATA_DMA_STATUS);

	/* Restore a higher level driver's expiry handler first. */
	hwgroup->expiry	= expiry;

	if ((dma_stat & 5) == 1) {	/* DMA active and no interrupt */
		unsigned long sc_base	= hwif->config_data;
		unsigned long twcr_port	= sc_base + (drive->dn ? 0x06 : 0x04);
		u8 dma_cmd		= inb(hwif->dma_base + ATA_DMA_CMD);

		printk(KERN_WARNING "%s: DMA interrupt possibly stuck, "
		       "attempting recovery...\n", drive->name);

		/* Stop DMA */
		outb(dma_cmd & ~0x01, hwif->dma_base + ATA_DMA_CMD);

		/* Setup the dummy DMA transfer */
		outw(0, sc_base + 0x0a);	/* Sector Count */
		outw(0, twcr_port);	/* Transfer Word Count 1 or 2 */

		/* Start the dummy DMA transfer */

		/* clear R_OR_WCTR for write */
		outb(0x00, hwif->dma_base + ATA_DMA_CMD);
		/* set START_STOPBM */
		outb(0x01, hwif->dma_base + ATA_DMA_CMD);

		/*
		 * If an interrupt was pending, it should come thru shortly.
		 * If not, a higher level driver's expiry handler should
		 * eventually cause some kind of recovery from the DMA stall.
		 */
		return WAIT_MIN_SLEEP;
	}

	/* Chain to the restored expiry handler if DMA wasn't active. */
	if (likely(expiry != NULL))
		return expiry(drive);

	/* If there was no handler, "emulate" that for ide_timer_expiry()... */
	return -1;
}
コード例 #28
0
/*
 * Handler for commands without a data phase
 */
static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
{
	ide_task_t *args	= HWGROUP(drive)->rq->special;
	u8 stat;

	local_irq_enable_in_hardirq();
	stat = ide_read_status(drive);

	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
		return ide_error(drive, "task_no_data_intr", stat);
		/* calls ide_end_drive_cmd */

	if (args)
		ide_end_drive_cmd(drive, stat, ide_read_error(drive));

	return ide_stopped;
}
コード例 #29
0
ファイル: siimage.c プロジェクト: liuxueyang/Linux-Unix
static int siimage_mmio_ide_dma_count (ide_drive_t *drive)
{
#ifdef SIIMAGE_VIRTUAL_DMAPIO
	struct request *rq	= HWGROUP(drive)->rq;
	ide_hwif_t *hwif	= HWIF(drive);
	u32 count		= (rq->nr_sectors * SECTOR_SIZE);
	u32 rcount		= 0;

	hwif->OUTL(count, SELADDR(0x1C));
	rcount = hwif->INL(SELADDR(0x1C));

	printk("\n%s: count = %d, rcount = %d, nr_sectors = %lu\n",
		drive->name, count, rcount, rq->nr_sectors);

#endif /* SIIMAGE_VIRTUAL_DMAPIO */
	return __ide_dma_count(drive);
}
コード例 #30
0
/*
 * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
 */
static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
{
	int retries = 5;
	u8 stat;

	while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
		udelay(10);

	if (OK_STAT(stat, READY_STAT, BAD_STAT))
		return ide_stopped;

	if (stat & (ERR_STAT|DRQ_STAT))
		return ide_error(drive, "set_geometry_intr", stat);

	BUG_ON(HWGROUP(drive)->handler != NULL);
	ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
	return ide_started;
}