示例#1
0
static int
hcsc_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen,
    uint8_t *data)
{
	struct hcsc_softc *sc = (struct hcsc_softc *)ncr_sc;
	bus_space_tag_t pdmat = sc->sc_pdmat;
	bus_space_handle_t pdmah = sc->sc_pdmah;
	int s, resid, len;

	s = splbio();

	NCR5380_WRITE(ncr_sc, sci_mode,
	    NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
	NCR5380_WRITE(ncr_sc, sci_irecv, 0);

	resid = datalen;
	while (resid > 0) {
		len = min(resid, HCSC_TSIZE_IN);
		if (hcsc_ready(ncr_sc) == 0)
			goto interrupt;
		bus_space_read_multi_1(pdmat, pdmah, 0, data, len);
		data += len;
		resid -= len;
	}

	hcsc_wait_not_req(ncr_sc);

interrupt:
	SCI_CLR_INTR(ncr_sc);
	NCR5380_WRITE(ncr_sc, sci_mode,
	    NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
	splx(s);
	return datalen - resid;
}
示例#2
0
文件: sbc.c 项目: lacombar/netbsd-alc
void
sbc_irq_intr(void *p)
{
	struct ncr5380_softc *ncr_sc = p;
	struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
	int claimed = 0;

	/* How we ever arrive here without IRQ set is a mystery... */
	if (*ncr_sc->sci_csr & SCI_CSR_INT) {
#ifdef SBC_DEBUG
		if (sbc_debug & SBC_DB_INTR)
			decode_5380_intr(ncr_sc);
#endif
		if (!cold)
			claimed = ncr5380_intr(ncr_sc);
		if (!claimed) {
			if (((*ncr_sc->sci_csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT)
			    && ((*ncr_sc->sci_bus_csr & ~SCI_BUS_RST) == 0)) {
				SCI_CLR_INTR(ncr_sc);	/* RST interrupt */
				if (sc->sc_clrintr)
					(*sc->sc_clrintr)(ncr_sc);
			}
#ifdef SBC_DEBUG
			else {
				printf("%s: spurious intr\n",
				    device_xname(ncr_sc->sc_dev));
				SBC_BREAK;
			}
#endif
		}
	}
}
示例#3
0
void 
se_dma_start(struct ncr5380_softc *ncr_sc)
{
	struct se_softc *sc = (struct se_softc *)ncr_sc;
	struct sci_req *sr = ncr_sc->sc_current;
	struct se_dma_handle *dh = sr->sr_dma_hand;
	volatile struct se_regs *se = sc->sc_regs;
	int s, xlen;

	xlen = sc->sc_reqlen;

	/* This MAY be time critical (not sure). */
	s = splhigh();

	se->dma_cntr = (ushort)(xlen & 0xFFFF);

	/*
	 * Acknowledge the phase change.  (After DMA setup!)
	 * Put the SBIC into DMA mode, and start the transfer.
	 */
	if (dh->dh_flags & SIDH_OUT) {
		*ncr_sc->sci_tcmd = PHASE_DATA_OUT;
		SCI_CLR_INTR(ncr_sc);
		*ncr_sc->sci_icmd = SCI_ICMD_DATA;
		*ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
		*ncr_sc->sci_dma_send = 0;	/* start it */
	} else {
		*ncr_sc->sci_tcmd = PHASE_DATA_IN;
		SCI_CLR_INTR(ncr_sc);
		*ncr_sc->sci_icmd = 0;
		*ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
		*ncr_sc->sci_irecv = 0;	/* start it */
	}

	/* Let'er rip! */
	se->se_csr |= SE_CSR_INTR_EN;

	splx(s);
	ncr_sc->sc_state |= NCR_DOINGDMA;

#ifdef	DEBUG
	if (se_debug & 2) {
		printf("%s: started, flags=0x%x\n",
		    __func__, ncr_sc->sc_state);
	}
#endif
}
示例#4
0
文件: sbc.c 项目: lacombar/netbsd-alc
void
sbc_dma_stop(struct ncr5380_softc *ncr_sc)
{
	struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
	struct sci_req *sr = ncr_sc->sc_current;
	struct sbc_pdma_handle *dh = sr->sr_dma_hand;
	int ntrans;

	if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
#ifdef SBC_DEBUG
		if (sbc_debug & SBC_DB_DMA)
			printf("%s: dma_stop: DMA not running\n",
			    device_xname(ncr_sc->sc_dev));
#endif
		return;
	}
	ncr_sc->sc_state &= ~NCR_DOINGDMA;

	if ((ncr_sc->sc_state & NCR_ABORTING) == 0) {
		ntrans = ncr_sc->sc_datalen - dh->dh_len;

#ifdef SBC_DEBUG
		if (sbc_debug & SBC_DB_DMA)
			printf("%s: dma_stop: ntrans=0x%x\n",
			    device_xname(ncr_sc->sc_dev), ntrans);
#endif

		if (ntrans > ncr_sc->sc_datalen)
			panic("sbc_dma_stop: excess transfer");

		/* Adjust data pointer */
		ncr_sc->sc_dataptr += ntrans;
		ncr_sc->sc_datalen -= ntrans;

		/* Clear any pending interrupts. */
		SCI_CLR_INTR(ncr_sc);
		if (sc->sc_clrintr)
			(*sc->sc_clrintr)(ncr_sc);
	}

	/* Put SBIC back into PIO mode. */
	*ncr_sc->sci_mode &= ~SCI_MODE_DMA;
	*ncr_sc->sci_icmd = 0;

#ifdef SBC_DEBUG
	if (sbc_debug & SBC_DB_REG)
		printf("%s: dma_stop: csr=0x%x, bus_csr=0x%x\n",
		    device_xname(ncr_sc->sc_dev), *ncr_sc->sci_csr,
		    *ncr_sc->sci_bus_csr);
#endif
}
示例#5
0
文件: sbc.c 项目: lacombar/netbsd-alc
void
sbc_dma_start(struct ncr5380_softc *ncr_sc)
{
	struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
	struct sci_req *sr = ncr_sc->sc_current;
	struct sbc_pdma_handle *dh = sr->sr_dma_hand;

	/*
	 * Match bus phase, clear pending interrupts, set DMA mode, and
	 * assert data bus (for writing only), then start the transfer.
	 */
	if (dh->dh_flags & SBC_DH_OUT) {
		*ncr_sc->sci_tcmd = PHASE_DATA_OUT;
		SCI_CLR_INTR(ncr_sc);
		if (sc->sc_clrintr)
			(*sc->sc_clrintr)(ncr_sc);
		*ncr_sc->sci_mode |= SCI_MODE_DMA;
		*ncr_sc->sci_icmd = SCI_ICMD_DATA;
		*ncr_sc->sci_dma_send = 0;
	} else {
		*ncr_sc->sci_tcmd = PHASE_DATA_IN;
		SCI_CLR_INTR(ncr_sc);
		if (sc->sc_clrintr)
			(*sc->sc_clrintr)(ncr_sc);
		*ncr_sc->sci_mode |= SCI_MODE_DMA;
		*ncr_sc->sci_icmd = 0;
		*ncr_sc->sci_irecv = 0;
	}
	ncr_sc->sc_state |= NCR_DOINGDMA;

#ifdef SBC_DEBUG
	if (sbc_debug & SBC_DB_DMA)
		printf("%s: PDMA started, va=%p, len=0x%x\n",
		    device_xname(ncr_sc->sc_dev), dh->dh_addr, dh->dh_len);
#endif
}
示例#6
0
文件: oak.c 项目: MarginC/kame
static int
oak_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen,
    u_char *data)
{
	struct oak_softc *sc = (void *)ncr_sc;
	bus_space_tag_t pdmat = sc->sc_pdmat;
	bus_space_handle_t pdmah = sc->sc_pdmah;
	int s, resid, len;

	s = splbio();

	NCR5380_WRITE(ncr_sc, sci_mode,
	    NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
	NCR5380_WRITE(ncr_sc, sci_irecv, 0);

	resid = datalen;
	while (resid > 0) {
		len = min(resid, OAK_TSIZE_IN);
		if (oak_ready(ncr_sc) == 0)
			goto interrupt;
		KASSERT(BUS_SPACE_ALIGNED_POINTER(data, u_int16_t));
		bus_space_read_multi_2(pdmat, pdmah, OAK_PDMA_READ,
		    (u_int16_t *)data, len/2);
		data += len;
		resid -= len;
	}

	oak_wait_not_req(ncr_sc);

interrupt:
	SCI_CLR_INTR(ncr_sc);
	NCR5380_WRITE(ncr_sc, sci_mode,
	    NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
	splx(s);
	return datalen - resid;
}
示例#7
0
文件: sw.c 项目: lacombar/netbsd-alc
static void
sw_reset_adapter(struct ncr5380_softc *ncr_sc)
{

#ifdef	DEBUG
	if (sw_debug) {
		printf("%s\n", __func__);
	}
#endif

	/*
	 * The reset bits in the CSR are active low.
	 */
	SWREG_WRITE(ncr_sc, SWREG_CSR, 0);
	delay(10);
	SWREG_WRITE(ncr_sc, SWREG_CSR, SW_CSR_SCSI_RES);

	SWREG_WRITE(ncr_sc, SWREG_DMA_ADDR, 0);
	SWREG_WRITE(ncr_sc, SWREG_DMA_CNT, 0);
	delay(10);
	SWREG_WRITE(ncr_sc, SWREG_CSR, SW_CSR_SCSI_RES | SW_CSR_INTR_EN);

	SCI_CLR_INTR(ncr_sc);
}
示例#8
0
static int
hcsc_pdma_out(struct ncr5380_softc *ncr_sc, int phase, int datalen,
    uint8_t *data)
{
	struct hcsc_softc *sc = (struct hcsc_softc *)ncr_sc;
	bus_space_tag_t pdmat = sc->sc_pdmat;
	bus_space_handle_t pdmah = sc->sc_pdmah;
	int i, s, icmd, resid;

	s = splbio();
	icmd = NCR5380_READ(ncr_sc, sci_icmd) & SCI_ICMD_RMASK;
	NCR5380_WRITE(ncr_sc, sci_icmd, icmd | SCI_ICMD_DATA);
	NCR5380_WRITE(ncr_sc, sci_mode,
	    NCR5380_READ(ncr_sc, sci_mode) | SCI_MODE_DMA);
	NCR5380_WRITE(ncr_sc, sci_dma_send, 0);

	resid = datalen;
	if (hcsc_ready(ncr_sc) == 0)
		goto interrupt;

	if (resid > HCSC_TSIZE_OUT) {
		/*
		 * Because of the chips DMA prefetch, phase changes
		 * etc, won't be detected until we have written at
		 * least one byte more. We pre-write 4 bytes so
		 * subsequent transfers will be aligned to a 4 byte
		 * boundary. Assuming disconects will only occur on
		 * block boundaries, we then correct for the pre-write
		 * when and if we get a phase change. If the chip had
		 * DMA byte counting hardware, the assumption would not
		 * be necessary.
		 */
		bus_space_write_multi_1(pdmat, pdmah, 0, data, 4);
		data += 4;
		resid -= 4;

		for (; resid >= HCSC_TSIZE_OUT; resid -= HCSC_TSIZE_OUT) {
			if (hcsc_ready(ncr_sc) == 0) {
				resid += 4; /* Overshot */
				goto interrupt;
			}
			bus_space_write_multi_1(pdmat, pdmah, 0, data,
			    HCSC_TSIZE_OUT);
			data += HCSC_TSIZE_OUT;
		}
		if (hcsc_ready(ncr_sc) == 0) {
			resid += 4; /* Overshot */
			goto interrupt;
		}
	}

	if (resid) {
		bus_space_write_multi_1(pdmat, pdmah, 0, data, resid);
		resid = 0;
	}
	for (i = TIMEOUT; i > 0; i--) {
		if ((NCR5380_READ(ncr_sc, sci_csr)
		    & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
		    != SCI_CSR_DREQ)
			break;
	}
	if (i != 0)
		bus_space_write_1(pdmat, pdmah, 0, 0);
	else
		printf("%s: timeout waiting for final SCI_DSR_DREQ.\n",
		    device_xname(ncr_sc->sc_dev));

	hcsc_wait_not_req(ncr_sc);
interrupt:
	SCI_CLR_INTR(ncr_sc);
	NCR5380_WRITE(ncr_sc, sci_mode,
	    NCR5380_READ(ncr_sc, sci_mode) & ~SCI_MODE_DMA);
	NCR5380_WRITE(ncr_sc, sci_icmd, icmd);
	splx(s);
	return datalen - resid;
}
示例#9
0
文件: sbc.c 项目: lacombar/netbsd-alc
int
sbc_pdma_out(struct ncr5380_softc *ncr_sc, int phase, int datalen, u_char *data)
{
	struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
	volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
	volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
	label_t faultbuf;
	int resid, s;
	u_int8_t icmd;

#if 1
	/* Work around lame gcc initialization bug */
	(void)&data;
#endif

	if (datalen < ncr_sc->sc_min_dma_len ||
	    (sc->sc_options & SBC_PDMA) == 0)
		return ncr5380_pio_out(ncr_sc, phase, datalen, data);

	s = splbio();
	if (sbc_wait_busy(ncr_sc)) {
		splx(s);
		return 0;
	}

	icmd = *(ncr_sc->sci_icmd) & SCI_ICMD_RMASK;
	*ncr_sc->sci_icmd = icmd | SCI_ICMD_DATA;
	*ncr_sc->sci_mode |= SCI_MODE_DMA;
	*ncr_sc->sci_dma_send = 0;

	/*
	 * Setup for a possible bus error caused by SCSI controller
	 * switching out of DATA OUT before we're done with the
	 * current transfer.  (See comment before sbc_drq_intr().)
	 */
	nofault = &faultbuf;

	if (setjmp(nofault)) {
		printf("buf = 0x%lx, fault = 0x%lx\n",
		    (u_long)sc->sc_drq_addr, (u_long)m68k_fault_addr);
		panic("Unexpected bus error in sbc_pdma_out()");
	}

#define W1	*byte_data = *(u_int8_t *)data, data += 1
#define W4	*long_data = *(u_int32_t *)data, data += 4
	for (resid = datalen; resid >= 64; resid -= 64) {
		if (sbc_ready(ncr_sc))
			goto interrupt;
		W1;
		if (sbc_ready(ncr_sc))
			goto interrupt;
		W1;
		if (sbc_ready(ncr_sc))
			goto interrupt;
		W1;
		if (sbc_ready(ncr_sc))
			goto interrupt;
		W1;
		if (sbc_ready(ncr_sc))
			goto interrupt;
		W4; W4; W4; W4;
		W4; W4; W4; W4;
		W4; W4; W4; W4;
		W4; W4; W4;
	}
	while (resid) {
		if (sbc_ready(ncr_sc))
			goto interrupt;
		W1;
		resid--;
	}
#undef  W1
#undef  W4
	if (sbc_wait_dreq(ncr_sc))
		printf("%s: timeout waiting for DREQ.\n",
		    device_xname(ncr_sc->sc_dev));

	*byte_data = 0;
	goto done;

interrupt:
	if ((*ncr_sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0) {
		*ncr_sc->sci_icmd = icmd & ~SCI_ICMD_DATA;
		--resid;
	}

done:
	SCI_CLR_INTR(ncr_sc);
	*ncr_sc->sci_mode &= ~SCI_MODE_DMA;
	*ncr_sc->sci_icmd = icmd;
	splx(s);
	return (datalen - resid);
}
示例#10
0
文件: sbc.c 项目: lacombar/netbsd-alc
int
sbc_pdma_in(struct ncr5380_softc *ncr_sc, int phase, int datalen, u_char *data)
{
	struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
	volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
	volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
	label_t faultbuf;
	int resid, s;

	if (datalen < ncr_sc->sc_min_dma_len ||
	    (sc->sc_options & SBC_PDMA) == 0)
		return ncr5380_pio_in(ncr_sc, phase, datalen, data);

	s = splbio();
	if (sbc_wait_busy(ncr_sc)) {
		splx(s);
		return 0;
	}

	*ncr_sc->sci_mode |= SCI_MODE_DMA;
	*ncr_sc->sci_irecv = 0;

	resid = datalen;

	/*
	 * Setup for a possible bus error caused by SCSI controller
	 * switching out of DATA OUT before we're done with the
	 * current transfer.  (See comment before sbc_drq_intr().)
	 */
	nofault = &faultbuf;
	if (setjmp(nofault)) {
		goto interrupt;
	}

#define R4	*(u_int32_t *)data = *long_data, data += 4;
#define R1	*(u_int8_t *)data = *byte_data, data += 1;
	for (; resid >= 128; resid -= 128) {
		if (sbc_ready(ncr_sc))
			goto interrupt;
		R4; R4; R4; R4; R4; R4; R4; R4;
		R4; R4; R4; R4; R4; R4; R4; R4;
		R4; R4; R4; R4; R4; R4; R4; R4;
		R4; R4; R4; R4; R4; R4; R4; R4;		/* 128 */
	}
	while (resid) {
		if (sbc_ready(ncr_sc))
			goto interrupt;
		R1;
		resid--;
	}
#undef R4
#undef R1

interrupt:
	nofault = NULL;
	SCI_CLR_INTR(ncr_sc);
	*ncr_sc->sci_mode &= ~SCI_MODE_DMA;
	*ncr_sc->sci_icmd = 0;
	splx(s);
	return (datalen - resid);
}
示例#11
0
文件: sw.c 项目: lacombar/netbsd-alc
void
sw_dma_start(struct ncr5380_softc *ncr_sc)
{
	struct sw_softc *sc = (struct sw_softc *)ncr_sc;
	struct sci_req *sr = ncr_sc->sc_current;
	struct sw_dma_handle *dh = sr->sr_dma_hand;
	u_long dva;
	int xlen, adj, adjlen;
	u_int mode;
	uint32_t csr;

	/*
	 * Get the DVMA mapping for this segment.
	 */
	dva = (u_long)(dh->dh_dvma);
	if (dva & 1)
		panic("%s: bad dva=0x%lx", __func__, dva);

	xlen = ncr_sc->sc_datalen;
	xlen &= ~1;
	sc->sc_xlen = xlen;	/* XXX: or less... */

#ifdef	DEBUG
	if (sw_debug & 2) {
		printf("%s: dh=%p, dva=0x%lx, xlen=%d\n",
		    __func__, dh, dva, xlen);
	}
#endif

	/*
	 * Set up the DMA controller.
	 * Note that (dh->dh_len < sc_datalen)
	 */

	/* Set direction (send/recv) */
	csr = SWREG_READ(ncr_sc, SWREG_CSR);
	if (dh->dh_flags & SIDH_OUT) {
		csr |= SW_CSR_SEND;
	} else {
		csr &= ~SW_CSR_SEND;
	}
	SWREG_WRITE(ncr_sc, SWREG_CSR, csr);

	/*
	 * The "sw" needs longword aligned transfers.  We
	 * detect a shortword aligned transfer here, and adjust the
	 * DMA transfer by 2 bytes.  These two bytes are read/written
	 * in PIO mode just before the DMA is started.
	 */
	adj = 0;
	if (dva & 2) {
		adj = 2;
#ifdef DEBUG
		if (sw_debug & 2)
			printf("%s: adjusted up %d bytes\n", __func__, adj);
#endif
	}

	/* We have to frob the address on the "sw". */
	dh->dh_startingpa = (dva | 0xF00000);
	SWREG_WRITE(ncr_sc, SWREG_DMA_ADDR, (u_int)(dh->dh_startingpa + adj));
	SWREG_WRITE(ncr_sc, SWREG_DMA_CNT, xlen - adj);

	/*
	 * Acknowledge the phase change.  (After DMA setup!)
	 * Put the SBIC into DMA mode, and start the transfer.
	 */
	if (dh->dh_flags & SIDH_OUT) {
		NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_OUT);
		if (adj) {
			adjlen = ncr5380_pio_out(ncr_sc, PHASE_DATA_OUT,
			    adj, dh->dh_addr);
			if (adjlen != adj)
				printf("%s: bad outgoing adj, %d != %d\n",
				    device_xname(ncr_sc->sc_dev), adjlen, adj);
		}
		SCI_CLR_INTR(ncr_sc);
		NCR5380_WRITE(ncr_sc, sci_icmd, SCI_ICMD_DATA);
		mode = NCR5380_READ(ncr_sc, sci_mode);
		mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
		NCR5380_WRITE(ncr_sc, sci_mode, mode);
		NCR5380_WRITE(ncr_sc, sci_dma_send, 0); 	/* start it */
	} else {
		NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_IN);
		if (adj) {
			adjlen = ncr5380_pio_in(ncr_sc, PHASE_DATA_IN,
			    adj, dh->dh_addr);
			if (adjlen != adj)
				printf("%s: bad incoming adj, %d != %d\n",
				    device_xname(ncr_sc->sc_dev), adjlen, adj);
		}
		SCI_CLR_INTR(ncr_sc);
		NCR5380_WRITE(ncr_sc, sci_icmd, 0);
		mode = NCR5380_READ(ncr_sc, sci_mode);
		mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
		NCR5380_WRITE(ncr_sc, sci_mode, mode);
		NCR5380_WRITE(ncr_sc, sci_irecv, 0); 	/* start it */
	}

	/* Let'er rip! */
	csr |= SW_CSR_DMA_EN;
	SWREG_WRITE(ncr_sc, SWREG_CSR, csr);

	ncr_sc->sc_state |= NCR_DOINGDMA;

#ifdef	DEBUG
	if (sw_debug & 2) {
		printf("%s: started, flags=0x%x\n",
		    __func__, ncr_sc->sc_state);
	}
#endif
}