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

📄 asc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* setup for this chunk */	len = state->buflen;	if (len > state->dmaBufSize)		len = state->dmaBufSize;	state->dmalen = len;	bcopy(state->buf, state->dmaBufAddr, len);	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);	ASC_TC_PUT(regs, len);#ifdef DEBUG	if (asc_debug > 2)		printf("asc_resume_out: buflen %d, len %d\n", state->buflen,			len);#endif	/* check for next chunk */	state->flags |= DMA_IN_PROGRESS;	if (len != state->buflen) {		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;		readback(regs->asc_cmd);		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];		return (0);	}	return (1);}/* ARGSUSED */static intasc_resume_dma_out(asc, status, ss, ir)	register asc_softc_t asc;	register int status, ss, ir;{	register asc_regmap_t *regs = asc->regs;	register State *state = &asc->st[asc->target];	register int len, off;	/* setup to finish writing this chunk */	len = state->dmaresid;	off = state->dmalen - len;	if (off & 1) {		printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",			state->dmalen, len, off); /* XXX */		regs->asc_fifo = state->dmaBufAddr[off];		off++;		len--;	}	(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_WRITE);	ASC_TC_PUT(regs, len);#ifdef DEBUG	if (asc_debug > 2)		printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",			state->dmalen, state->buflen, len, off);#endif	/* check for next chunk */	state->flags |= DMA_IN_PROGRESS;	if (state->dmalen != state->buflen) {		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;		readback(regs->asc_cmd);		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];		return (0);	}	return (1);}/* ARGSUSED */static intasc_sendsync(asc, status, ss, ir)	register asc_softc_t asc;	register int status, ss, ir;{	register asc_regmap_t *regs = asc->regs;	register State *state = &asc->st[asc->target];	/* send the extended synchronous negotiation message */	regs->asc_fifo = SCSI_EXTENDED_MSG;	MachEmptyWriteBuffer();	regs->asc_fifo = 3;	MachEmptyWriteBuffer();	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;	MachEmptyWriteBuffer();	regs->asc_fifo = SCSI_MIN_PERIOD;	MachEmptyWriteBuffer();	regs->asc_fifo = ASC_MAX_OFFSET;	/* state to resume after we see the sync reply message */	state->script = asc->script + 2;	state->msglen = 0;	return (1);}/* ARGSUSED */static intasc_replysync(asc, status, ss, ir)	register asc_softc_t asc;	register int status, ss, ir;{	register asc_regmap_t *regs = asc->regs;	register State *state = &asc->st[asc->target];#ifdef DEBUG	if (asc_debug > 2)		printf("asc_replysync: %x %x\n",			asc_to_scsi_period[state->sync_period] * asc->tb_ticks,			state->sync_offset);#endif	/* send synchronous transfer in response to a request */	regs->asc_fifo = SCSI_EXTENDED_MSG;	MachEmptyWriteBuffer();	regs->asc_fifo = 3;	MachEmptyWriteBuffer();	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;	MachEmptyWriteBuffer();	regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;	MachEmptyWriteBuffer();	regs->asc_fifo = state->sync_offset;	regs->asc_cmd = ASC_CMD_XFER_INFO;	readback(regs->asc_cmd);	/* return to the appropriate script */	if (!state->script) {#ifdef DEBUG		asc_DumpLog("asc_replsync");#endif		panic("asc_replysync");	}	asc->script = state->script;	state->script = (script_t *)0;	return (0);}/* ARGSUSED */static intasc_msg_in(asc, status, ss, ir)	register asc_softc_t asc;	register int status, ss, ir;{	register asc_regmap_t *regs = asc->regs;	register State *state = &asc->st[asc->target];	register int msg;	int i;	/* read one message byte */	msg = regs->asc_fifo;#ifdef DEBUG	if (asc_logp == asc_log)		asc_log[NLOG - 1].msg = msg;	else		asc_logp[-1].msg = msg;#endif	/* check for multi-byte message */	if (state->msglen != 0) {		/* first byte is the message length */		if (state->msglen < 0) {			state->msglen = msg;			return (1);		}		if (state->msgcnt >= state->msglen)			goto abort;		state->msg_in[state->msgcnt++] = msg;		/* did we just read the last byte of the message? */		if (state->msgcnt != state->msglen)			return (1);		/* process an extended message */#ifdef DEBUG		if (asc_debug > 2)			printf("asc_msg_in: msg %x %x %x\n",				state->msg_in[0],				state->msg_in[1],				state->msg_in[2]);#endif		switch (state->msg_in[0]) {		case SCSI_SYNCHRONOUS_XFER:			state->flags |= DID_SYNC;			state->sync_offset = state->msg_in[2];			/* convert SCSI period to ASC period */			i = state->msg_in[1] / asc->tb_ticks;			if (i < asc->min_period)				i = asc->min_period;			else if (i >= asc->max_period) {				/* can't do sync transfer, period too long */				printf("asc%d: SCSI device %d: sync xfer period too long (%d)\n",					asc - asc_softc, asc->target, i);				i = asc->max_period;				state->sync_offset = 0;			}			if ((i * asc->tb_ticks) != state->msg_in[1])				i++;			state->sync_period = i & 0x1F;			/*			 * If this is a request, check minimums and			 * send back an acknowledge.			 */			if (!(state->flags & TRY_SYNC)) {				regs->asc_cmd = ASC_CMD_SET_ATN;				readback(regs->asc_cmd);				if (state->sync_period < asc->min_period)					state->sync_period =						asc->min_period;				if (state->sync_offset > ASC_MAX_OFFSET)					state->sync_offset =						ASC_MAX_OFFSET;				asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];				regs->asc_syn_p = state->sync_period;				readback(regs->asc_syn_p);				regs->asc_syn_o = state->sync_offset;				readback(regs->asc_syn_o);				regs->asc_cmd = ASC_CMD_MSG_ACPT;				readback(regs->asc_cmd);				return (0);			}			regs->asc_syn_p = state->sync_period;			readback(regs->asc_syn_p);			regs->asc_syn_o = state->sync_offset;			readback(regs->asc_syn_o);			goto done;		default:			printf("asc%d: SCSI device %d: rejecting extended message 0x%x\n",				asc - asc_softc, asc->target,				state->msg_in[0]);			goto reject;		}	}	/* process first byte of a message */#ifdef DEBUG	if (asc_debug > 2)		printf("asc_msg_in: msg %x\n", msg);#endif	switch (msg) {#if 0	case SCSI_MESSAGE_REJECT:		printf(" did not like SYNCH xfer "); /* XXX */		state->flags |= DID_SYNC;		regs->asc_cmd = ASC_CMD_MSG_ACPT;		readback(regs->asc_cmd);		status = asc_wait(regs, ASC_CSR_INT);		ir = regs->asc_intr;		/* some just break out here, some dont */		if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {			regs->asc_fifo = SCSI_ABORT;			regs->asc_cmd = ASC_CMD_XFER_INFO;			readback(regs->asc_cmd);			status = asc_wait(regs, ASC_CSR_INT);			ir = regs->asc_intr;		}		if (ir & ASC_INT_DISC) {			asc_end(asc, status, 0, ir);			return (0);		}		goto status;#endif	case SCSI_EXTENDED_MSG: /* read an extended message */		/* setup to read message length next */		state->msglen = -1;		state->msgcnt = 0;		return (1);	case SCSI_NO_OP:		break;	case SCSI_SAVE_DATA_POINTER:		/* expect another message */		return (1);	case SCSI_RESTORE_POINTERS:		/*		 * Need to do the following if resuming synchonous data in		 * on an odd byte boundary.		regs->asc_cnfg2 |= ASC_CNFG2_RFB;		 */		break;	case SCSI_DISCONNECT:		if (state->flags & DISCONN)			goto abort;		state->flags |= DISCONN;		regs->asc_cmd = ASC_CMD_MSG_ACPT;		readback(regs->asc_cmd);		asc->script = &asc_scripts[SCRIPT_DISCONNECT];		return (0);	default:		printf("asc%d: SCSI device %d: rejecting message 0x%x\n",			asc - asc_softc, asc->target, msg);	reject:		/* request a message out before acknowledging this message */		state->msg_out = SCSI_MESSAGE_REJECT;		regs->asc_cmd = ASC_CMD_SET_ATN;		readback(regs->asc_cmd);	}done:	/* return to original script */	regs->asc_cmd = ASC_CMD_MSG_ACPT;	readback(regs->asc_cmd);	if (!state->script) {	abort:#ifdef DEBUG		asc_DumpLog("asc_msg_in");#endif		panic("asc_msg_in");	}	asc->script = state->script;	state->script = (script_t *)0;	return (0);}/* ARGSUSED */static intasc_disconnect(asc, status, ss, ir)	register asc_softc_t asc;	register int status, ss, ir;{	register State *state = &asc->st[asc->target];#ifdef DIAGNOSTIC	if (!(state->flags & DISCONN)) {		printf("asc_disconnect: device %d: DISCONN not set!\n",			asc->target);	}#endif	asc->target = -1;	asc->state = ASC_STATE_RESEL;	return (1);}/* * DMA handling routines. For a turbochannel device, just set the dmar. * For the I/O ASIC, handle the actual DMA interface. */static voidtb_dma_start(asc, state, cp, flag)	asc_softc_t asc;	State *state;	caddr_t cp;	int flag;{	if (flag == ASCDMA_WRITE)		*asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(cp);	else		*asc->dmar = ASC_DMA_ADDR(cp);}static voidtb_dma_end(asc, state, flag)	asc_softc_t asc;	State *state;	int flag;{}static voidasic_dma_start(asc, state, cp, flag)	asc_softc_t asc;	State *state;	caddr_t cp;	int flag;{	register volatile u_int *ssr = (volatile u_int *)		ASIC_REG_CSR(asic_base);	u_int phys, nphys;	/* stop DMA engine first */	*ssr &= ~ASIC_CSR_DMAEN_SCSI;	*((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;	phys = MACH_CACHED_TO_PHYS(cp);	cp = (caddr_t)pmax_trunc_page(cp + NBPG);	nphys = MACH_CACHED_TO_PHYS(cp);	asc->dma_next = cp;	asc->dma_xfer = state->dmalen - (nphys - phys);	*(volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base) =		ASIC_DMA_ADDR(phys);	*(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =		ASIC_DMA_ADDR(nphys);	if (flag == ASCDMA_READ)		*ssr |= ASIC_CSR_SCSI_DIR | ASIC_CSR_DMAEN_SCSI;	else		*ssr = (*ssr & ~ASIC_CSR_SCSI_DIR) | ASIC_CSR_DMAEN_SCSI;	MachEmptyWriteBuffer();}static voidasic_dma_end(asc, state, flag)	asc_softc_t asc;	State *state;	int flag;{	register volatile u_int *ssr = (volatile u_int *)		ASIC_REG_CSR(asic_base);	register volatile u_int *dmap = (volatile u_int *)		ASIC_REG_SCSI_DMAPTR(asic_base);	register u_short *to;	register int w;	int nb;	*ssr &= ~ASIC_CSR_DMAEN_SCSI;	to = (u_short *)MACH_PHYS_TO_CACHED(*dmap >> 3);	*dmap = -1;	*((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;	MachEmptyWriteBuffer();	if (flag == ASCDMA_READ) {		MachFlushDCache(MACH_PHYS_TO_CACHED(		    MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen);		if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) {			/* pick up last upto6 bytes, sigh. */				/* Last byte really xferred is.. */			w = *(int *)ASIC_REG_SCSI_SDR0(asic_base);			*to++ = w;			if (--nb > 0) {				w >>= 16;				*to++ = w;			}			if (--nb > 0) {				w = *(int *)ASIC_REG_SCSI_SDR1(asic_base);				*to++ = w;			}		}	}}#ifdef notdef/* * Called by asic_intr() for scsi dma pointer update interrupts. */voidasc_dma_intr(){	asc_softc_t asc = &asc_softc[0];	u_int next_phys;	asc->dma_xfer -= NBPG;	if (asc->dma_xfer <= -NBPG) {		volatile u_int *ssr = (volatile u_int *)			ASIC_REG_CSR(asic_base);		*ssr &= ~ASIC_CSR_DMAEN_SCSI;	} else {		asc->dma_next += NBPG;		next_phys = MACH_CACHED_TO_PHYS(asc->dma_next);	}	*(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =		ASIC_DMA_ADDR(next_phys);	MachEmptyWriteBuffer();}#endif#ifdef DEBUGasc_DumpLog(str)	char *str;{	register struct asc_log *lp;	register u_int status;	printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,		asc_debug_bn, asc_debug_sz);	lp = asc_logp;	do {		status = lp->status;		printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",			status >> 24,			lp->target,			(status >> 16) & 0xFF,			(status >> 8) & 0xFF,			status & 0XFF,			lp->state,			asc_scripts[lp->state].condition,			lp->msg, lp->resid);		if (++lp >= &asc_log[NLOG])			lp = asc_log;	} while (lp != asc_logp);}#endif#endif	/* NASC > 0 */

⌨️ 快捷键说明

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