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

📄 sm.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	  case SC_WRITE_VERIFY:		smsnap->sync_chk = SM_SEND_DATA;		break;	    default:		smsnap->sync_chk = SM_NO_DATA;	}	/* clear some status */	smsnap->cur_err = (smsnap->scsi_status = ZERO); 	smsnap->cur_retry = ZERO;        smsnap->cur_state = STATE_SEL_REQ;       		ESP_WR.timeout = DEF_TIMEOUT;    	ESP_WR.busid = h_sip->unit;	/* target SCSI ID */	DPRINTF1("smdoit: selecting target= %x\n", h_sip->unit);    	DEBUG_DELAY(1000000);	toutcnt = LOOP_CMDTOUT;			ESP_WR.cmd = CMD_SEL_NOATN; 	/* NO identify message */    	while ((--toutcnt) && (smsnap->cur_err == ZERO) &&	       (smsnap->cur_state != STATE_FREE)) {		/* poll on ESP_INT thru DVMA status reg */		if (dvma->ctl_stat & DVMA_INTPEND)  {			sm_intr(h_sip);			toutcnt = LOOP_CMDTOUT;			}	    	}	DPRINTF2("smdoit: err= %x, state= %x\n", 		smsnap->cur_err, smsnap->cur_state);	DPRINTF2("smdoit: resid= %x, status= %x\n", 		h_sip->cc, smsnap->esp_stat);	cp = (u_char *)scb;	*cp = smsnap->scsi_status;	/* return scsi bus status */	DPRINTF1("smdoit: done, bus_status= %x\n", smsnap->scsi_status);        DEBUG_DELAY(1000000);	if ((toutcnt == ZERO) || (smsnap->cur_err))  {	   EPRINTF2("sm_cmd: CMD_TIMED-OUT, err= %x, toutcnt= %x\n", 		smsnap->cur_err, toutcnt);	   EPRINTF2("sm_cmd: cmd= %x, esp_stat= %x\n", 		cdb->scc_cmd, ESP_RD.stat);	   EPRINTF2("sm_cmd: state= %x, cc= %x\n", 		smsnap->cur_state, h_sip->cc);	   EPRINTF2("sm_cmd: dma_stat= %x, dma_addr= %x\n", 		dvma->ctl_stat, dvma->dma_addr);           DEBUG_DELAY(1000000);           return(FAIL);	}	return (h_sip->cc);		/* successful */}static intsm_dma_setup(h_sip)	register struct host_saioreq *h_sip;{       	register struct scsi_sm_reg *smr;	register struct udc_table *dvma;	register struct sm_snap *smsnap = &smreg_info;#ifdef SMDEBUG	u_char *ptr;	int	i;#endif SMDEBUG	if ((h_sip->cc == ZERO) || (smsnap->sync_chk == SM_NO_DATA)) {		DPRINTF1("sm_dma_setup: return due to xfr_cnt= %x\n",			h_sip->cc);		return;	}	/* get to scsi control logic registers */	smr = (struct scsi_sm_reg *)h_sip->devaddr;	dvma = (struct udc_table *)h_sip->dmaaddr;	#ifdef SMDEBUG	DPRINTF1("sm_dma_setup: ORG_addr= %x, data= ", h_sip->ma);        ptr = (u_char *)h_sip->ma;        for (i = 0; i < 20; i++, ptr++) {                DPRINTF1(" %x ", *ptr);        }	DPRINTF1("\nsm_dma_setup: ORG_cnt= %x\n", h_sip->cc);#endif SMDEBUG		dvma->dma_addr = (u_long)h_sip->ma;	/* set dma address */	ESP_WR.xcnt_lo = (u_char)h_sip->cc;	ESP_WR.xcnt_hi = (u_char)(h_sip->cc >> 8);	ESP_WR.cmd = CMD_NOP | CMD_DMA;		/* NOP needed */	DPRINTF2("sm_dma_setup: xcnt_lo= %x, xcnt_hi= %x\n", 		ESP_RD.xcnt_lo, ESP_RD.xcnt_hi);	/* enable DMA */	if (smsnap->sync_chk == SM_SEND_DATA) {	        DPRINTF("sm_cmd: setting a write to SCSI\n");               	dvma->ctl_stat |= DVMA_ENDVMA;			dvma->ctl_stat &= ~DVMA_WRITE;	}		else {	        DPRINTF("sm_cmd: setting a read to SCSI\n");		dvma->ctl_stat |= DVMA_ENDVMA | DVMA_WRITE;	}	DEBUG_DELAY(1000000);}/* * Reset some register information after a dma operation. */static intsm_dma_cleanup(h_sip, espstat)	register struct host_saioreq *h_sip;	u_char espstat;{	register struct scsi_sm_reg *smr;	register struct udc_table *dvma;	register struct sm_snap *smsnap = &smreg_info;	register int i;	u_long	toutcnt;	u_short dma_cnt, esp_cnt, xfrcnt, fifo_cnt, req_cnt;#ifdef SMDEBUG	u_char *ptr; 	DPRINTF1("sm_dma_cleanup: ORG_addr= %x, NEW_data= ", h_sip->ma);        ptr = (u_char *)h_sip->ma;        for (i = 0; i < 20; i++, ptr++) {                DPRINTF1(" %x ", *ptr);        }	DPRINTF1("\nsm_dma_cleanup: ORG_cnt= %x\n", h_sip->cc);#endif SMDEBUG	req_cnt = h_sip->cc;		if ((req_cnt == ZERO) || (smsnap->sync_chk == SM_NO_DATA)) {		DPRINTF2("sm_dma_setup: return, xfr_cnt= %x, stat= %x\n", 			req_cnt, espstat);		return(ZERO);	}	/* get to scsi control logic registers */	smr = (struct scsi_sm_reg *)h_sip->devaddr;		/* get to scsi control logic registers */	smr = (struct scsi_sm_reg *)h_sip->devaddr;	dvma = (struct udc_table *)h_sip->dmaaddr;		dvma->ctl_stat &= ~DVMA_ENDVMA;		toutcnt = dvma->ctl_stat;	DPRINTF2("sm_dma_cleanup: dvma_stat= %x, addr= %x\n",                toutcnt, dvma->dma_addr);        DEBUG_DELAY(1000000);  	if (toutcnt & DVMA_REQPEND) {                toutcnt = LOOP_4SEC;    /* must be over 2sec */                while ((dvma->ctl_stat & DVMA_REQPEND) && (--toutcnt)) ;                if (toutcnt == ZERO) {		 EPRINTF1("sm_dma_cleanup: DVMA-scsi REQ_PEND struck, stat= %x\n",                                dvma->ctl_stat);                        smsnap->cur_err = SE_REQPEND;                        return(1);                }        }	if (smsnap->sync_chk == SM_RECV_DATA) {	    DPRINTF("sm_dma_cleanup: send DVMA_drain\n");            DEBUG_DELAY(1000000);            dvma->ctl_stat |= DVMA_DRAIN; /* send DRAIN anyway */            i = LOOP_2MSEC;            while ((dvma->ctl_stat & DVMA_DRAIN) && (--i));            if (i == ZERO) {                EPRINTF1("sm_dma_cleanup: DVMA-scsi drain stuck, stat= %x\n",                        dvma->ctl_stat);                smsnap->cur_err = SE_DVMAERR;		dvma->ctl_stat |= DVMA_FLUSH;		dvma->ctl_stat &= ~(DVMA_ENDVMA | DVMA_WRITE);                return(1);             }	} 	DEBUG_DELAY(1000000);        dvma->ctl_stat |= DVMA_FLUSH; /* self-clear */        /* disable DVMA_xfr */        dvma->ctl_stat &= ~(DVMA_ENDVMA | DVMA_WRITE);        /* see how much DVMA xfr'd */	DPRINTF2("sm_dma_cleanup: ORIG addr= %x, cnt= %x\n", h_sip->ma, req_cnt);        toutcnt = dvma->dma_addr;	DPRINTF2("sm_dma_cleanup: espstat= %x, DVMA_addr= %x\n", espstat, toutcnt);        dma_cnt = (u_short)toutcnt - (u_short)h_sip->ma;        /* see how much ESP xfr'd */	fifo_cnt = ESP_RD.fifo_flag & KEEP_5BITS;	DPRINTF2("sm_dma_cleanup: fifo_cnt= %x, dma_cnt= %x\n",                fifo_cnt, dma_cnt);        /* Figure out how much the esp chip may have xferred         * If the XZERO bit is set, we can assume that the         * ESP xferred all we asked for.  */        if (espstat & ESP_STAT_XZERO)                esp_cnt = req_cnt - fifo_cnt;        else  {                xfrcnt = ESP_RD.xcnt_hi << 8;                xfrcnt |= ((u_short)ESP_RD.xcnt_lo & KEEP_LBYTE);                esp_cnt = req_cnt - xfrcnt;	DPRINTF1("sm_dma_cleanup: ESP_cntr= %x\n", xfrcnt);                /* correct ESP xfr_cnt reported error */                if ((esp_cnt == 0) && (dma_cnt > 16)) {                        esp_cnt = dma_cnt & (0xf);                }                esp_cnt -= fifo_cnt;        }        /* If we were sending out the scsi bus, then we believe the         * (possibly faked) transfer count register, since the esp         * chip may have prefetched to fill it's fifo.  */	DPRINTF2("sm_dma_cleanup: dir= %x, espcnt= %x\n",                smsnap->sync_chk, esp_cnt);	if (smsnap->sync_chk == SM_SEND_DATA)                xfrcnt = esp_cnt;        else {                /* Else, if we were coming from the scsi bus, we only count                 * that which got pumped through the dma engine.  */                xfrcnt = dma_cnt;        }        DPRINTF2("sm_dma_cleanup: dir= %x, xfrcnt= %x\n",                smsnap->sync_chk, xfrcnt);	/* updated dma_count. NOTE: different from OS-> update the count */	/* to remaining bytes; while HERE = return to upper level with */	/* exact amount of bytes transferred */	h_sip->cc = xfrcnt;	#ifdef notdef	/* skip updating the addr, upper level driver might reuse the address */	/* without restoring to the original value (expecting NO change) */	h_sip->ma += xfrcnt;	#endif notdef	DPRINTF2("sm_dma_cleanup: FINAL addr= %x, cnt= %x\n",                h_sip->ma, h_sip->cc);        smsnap->sync_chk = SM_NO_DATA;        if (fifo_cnt) 		ESP_WR.cmd = CMD_FLUSH;	return(ZERO);}/* * Reset SCSI control logic. */static intsm_reset(h_sip, cond)	register struct host_saioreq *h_sip;	int	cond;{	register struct scsi_sm_reg *smr;	register struct udc_table *dvma;	register struct sm_snap *smsnap = &smreg_info;	register int i;	u_long	toutcnt;	/* get to scsi control logic registers */	smr = (struct scsi_sm_reg *)h_sip->devaddr;	dvma = (struct udc_table *)h_sip->dmaaddr;		DPRINTF2("sm_reset: state= %x, dma_stat= %x\n", 		smsnap->cur_state, dvma->ctl_stat);	DEBUG_DELAY(1000000);        if (dvma->ctl_stat & DVMA_REQPEND)                smsnap->cur_state = STATE_DVMA_STUCK;	ESP_WR.conf = ESP_CONF_DISRINT;		/* disable reset INT */	/* for hard reset, cur_state must be STATE_RESET */        switch (cond) {           case RESET_EXT_ONLY:                DPRINTF("sm_reset: reset ESP/SCSI bus only\n");                ESP_WR.cmd = CMD_RESET_ESP;     /* hard-reset ESP chip */                ESP_WR.cmd = CMD_NOP;           /* needed for ESP bug */                ESP_WR.cmd = CMD_RESET_SCSI;                ESP_WR.cmd = CMD_NOP;           /* NOP needed for ESP bug */		for (toutcnt = ZERO; toutcnt < LOOP_4SEC; toutcnt++);	        i = ESP_RD.intr;        /* read to clear reset interrupt */#ifdef linti = i;#endif lint                break;           case RESET_INT_ONLY:                DPRINTF("sm_reset: reset ESP only\n");                /* DVMA_EN = ZERO, INTEN=ZERO, FLUSH=1 */                dvma->ctl_stat = DVMA_FLUSH;    /* soft dvma clear */                DELAY(100);                dvma->ctl_stat = ZERO;          /* clear it */                /* NO ints */                ESP_WR.cmd = CMD_RESET_ESP;     /* hard-reset ESP chip */                ESP_WR.cmd = CMD_NOP;           /* needed for ESP bug */		break;           case RESET_ALL_SCSI:           default:                DPRINTF("sm_reset: reset DVMA/ESP/SCSI bus\n");                /* implied a reset to both ESP and SCSI bus */                dvma->ctl_stat = DVMA_RESET;    /* hard DVMA reset */                DPRINTF1("sm_reset: dvma_stat= %x\n", dvma->ctl_stat);                DELAY(100);                dvma->ctl_stat = ZERO;          /* clear reset */                ESP_WR.cmd = CMD_RESET_SCSI;                ESP_WR.cmd = CMD_NOP;           /* NOP needed for ESP bug */		/* allow more than 2 second for scsi reset to settle */		/* Give reset scsi devices time to recover (> 2 Sec) */		for (toutcnt = ZERO; toutcnt < LOOP_4SEC; toutcnt++);       	 	i = ESP_RD.intr;        /* read to clear reset interrupt */#ifdef linti = i;#endif lint	}	/* enable parity, enable reset_int, and set host bus_id */	ESP_WR.clock_conv = DEF_CLK_CONV; 	ESP_WR.timeout = DEF_TIMEOUT;            ESP_WR.sync_offset = ZERO;         /* async */#ifdef notdef	/* ignore parity enable for backward campatibilty with old shoebox */	ESP_WR.conf = ESP_CONF_PAREN | DEF_ESP_HOSTID;#endif 	ESP_WR.conf = DEF_ESP_HOSTID;	DPRINTF1("sm_reset: esp_conf= %x\n", ESP_RD.conf);        DEBUG_DELAY(1000000);	/* set up some default sm_snap */        /* "cur_err, cur_retry, and scsi_status" */	/* will be cleared in "sm_cmd() */  	smsnap->cur_state = STATE_FREE;        smsnap->scsi_message = SC_COMMAND_COMPLETE;	/* dvam's ctl_stat is ZERO, which means no INTEN; */        DPRINTF1("sm_reset: done, DVMA_stat= %x\n", dvma->ctl_stat);}/* * Handle a scsi interrupt. */sm_intr(h_sip)	struct host_saioreq *h_sip;{	register struct scsi_sm_reg *smr;	register struct sm_snap *smsnap = &smreg_info;	register struct udc_table *dvma;	register int i, s;	u_long toutcnt;	u_char	espstat;	/* get to scsi control logic registers */	smr = (struct scsi_sm_reg *)h_sip->devaddr;	dvma = (struct udc_table *)h_sip->dmaaddr;		s = dvma->ctl_stat;	DPRINTF1("sm_intr: dma_stat: %x\n", s);	/* check dvma's req_pend, err_pend, and int_pend */        /* should only have int_pend set, if NO error */        if ((s & DVMA_INT_MASK) == ZERO) {	   	DPRINTF1("sm_intr: DVMA *NO* int_pend, stat: %x\n", s);	   	goto INTR_CHK_ERR;	}	/* Do not read ESP reg_interrupt before reading status and step reg */	/* after reading ESP reg_interrupt, ESP's INT will get cleared */	smsnap->esp_step = ESP_RD.step;	smsnap->esp_stat = ESP_RD.stat;	espstat = smsnap->esp_stat;	smsnap->esp_intr = ESP_RD.intr;		/* clear INT */	DPRINTF2("sm_intr: state= %x, int= %x\n", 		smsnap->cur_state, smsnap->esp_intr);	DPRINTF2("sm_intr: step= %x, stat= %x\n", 		smsnap->esp_step, espstat); 	if (smsnap->cur_state == STATE_DATA_REQ) {	   s = dvma->ctl_stat;	   DPRINTF1("sm_intr: dma_stat: %x\n", s);	   smsnap->cur_retry++;	   if (s & DVMA_CHK_MASK) {

⌨️ 快捷键说明

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