示例#1
0
int
csc_intr(void *arg)
{
	struct sfas_softc *dev = arg;
	csc_regmap_p	      rp;
	int		      quickints;

	rp = (csc_regmap_p)dev->sc_fas;
	
	if (*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING) {
		quickints = 16;
		do {
			dev->sc_status = *rp->FAS216.sfas_status;
			dev->sc_interrupt = *rp->FAS216.sfas_interrupt;
	  
			if (dev->sc_interrupt & SFAS_INT_RESELECTED) {
				dev->sc_resel[0] = *rp->FAS216.sfas_fifo;
				dev->sc_resel[1] = *rp->FAS216.sfas_fifo;
			}
			sfasintr(dev);

		} while((*rp->FAS216.sfas_status & SFAS_STAT_INTERRUPT_PENDING)
			&& --quickints);
	}

	return(0);	/* Pass interrupt on down the chain */
}
示例#2
0
文件: sfas.c 项目: ryo/netbsd-src
/*
 * Actually select the unit, whereby the whole scsi-process is started.
 */
void
sfas_donextcmd(struct sfas_softc *dev, struct sfas_pending *pendp)
{
	int	s;

/*
 * Special case for scsi unit reset. I think this is waterproof. We first
 * select the unit during splbio. We then cycle through the generated
 * interrupts until the interrupt routine signals that the unit has
 * acknowledged the reset. After that we have to wait a reset to select
 * delay before anything else can happend.
 */
	if (pendp->xs->xs_control & XS_CTL_RESET) {
		struct nexus	*nexus;

		s = splbio();
		while(!sfasselect(dev, pendp, 0, 0, 0, 0, SFAS_SELECT_K)) {
			splx(s);
			delay(10);
			s = splbio();
		}

		nexus = dev->sc_cur_nexus;
		while(nexus->flags & SFAS_NF_UNIT_BUSY) {
			sfasiwait(dev);
			sfasintr(dev);
		}

		nexus->flags |= SFAS_NF_UNIT_BUSY;
		splx(s);

		sfasreset(dev, 0);

		s = splbio();
		nexus->flags &= ~SFAS_NF_UNIT_BUSY;
		splx(s);
	}

/*
 * If we are polling, go to splbio and perform the command, else we poke
 * the scsi-bus via sfasgo to get the interrupt machine going.
 */
	if (pendp->xs->xs_control & XS_CTL_POLL) {
		s = splbio();
		sfasicmd(dev, pendp);
		TAILQ_INSERT_TAIL(&dev->sc_xs_free, pendp, link);
		splx(s);
	} else {
		sfasgo(dev, pendp);
	}
}
示例#3
0
文件: sfas.c 项目: ryo/netbsd-src
/*
 * Transfer info to/from device. sfas_ixfer uses polled IO+sfasiwait so the
 * rules that apply to sfasiwait also applies here.
 */
void
sfas_ixfer(void *v, int polling)
{
	struct sfas_softc *dev = v;
	sfas_regmap_p	 rp;
	u_char		*buf;
	int		 len, mode, phase;

	rp = dev->sc_fas;
	buf = dev->sc_buf;
	len = dev->sc_len;

/*
 * Decode the scsi phase to determine whether we are reading or writing.
 * mode == 1 => READ, mode == 0 => WRITE
 */
	phase = dev->sc_status & SFAS_STAT_PHASE_MASK;
	mode = (phase == SFAS_PHASE_DATA_IN);

	while(len && ((dev->sc_status & SFAS_STAT_PHASE_MASK) == phase))
		if (mode) {
			*rp->sfas_command = SFAS_CMD_TRANSFER_INFO;

			sfasiwait(dev);

			*buf++ = *rp->sfas_fifo;
			len--;
		} else {
			len--;
			*rp->sfas_fifo = *buf++;
			*rp->sfas_command = SFAS_CMD_TRANSFER_INFO;

			sfasiwait(dev);
		}

/* Update buffer pointers to reflect the sent/received data. */
	dev->sc_buf = buf;
	dev->sc_len = len;

/*
 * Since the last sfasiwait will be a phase-change, we can't wait for it
 * again later, so we have to signal that.
 * Since this may be called from an interrupt initiated routine then we
 * must call sfasintr again to avoid losing an interrupt. Phew!
 */
	if(polling)
		dev->sc_flags |= SFAS_DONT_WAIT;
	else
		sfasintr(dev);
}
示例#4
0
文件: sfas.c 项目: ryo/netbsd-src
/*
 * sfasicmd is used to perform IO when we can't use interrupts. sfasicmd
 * emulates the normal environment by waiting for the chip and calling
 * sfasintr.
 */
void
sfasicmd(struct sfas_softc *dev, struct sfas_pending *pendp)
{
	struct nexus	*nexus;

	nexus = &dev->sc_nexus[pendp->xs->xs_periph->periph_target];

	if (!sfasselect(dev, pendp, (char *)pendp->xs->cmd, pendp->xs->cmdlen,
			(char *)pendp->xs->data, pendp->xs->datalen,
			SFAS_SELECT_I))
		panic("sfasicmd: Couldn't select unit");

	while(nexus->state != SFAS_NS_FINISHED) {
		sfasiwait(dev);
		sfasintr(dev);
	}

	nexus->flags &= ~SFAS_NF_SYNC_TESTED;
}