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

📄 advansys.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * This allows the kernel driver to make up it's own mind		 * as it sees fit to tag queue instead of having the		 * firmware try and second guess the tag_code settins.		 */		adv_write_lram_8(adv, ADVV_MAX_DVC_QNG_BEG + i,				 adv->max_openings);	}	adv_write_lram_8(adv, ADVV_USE_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET);	adv_write_lram_8(adv, ADVV_CAN_TAGGED_QNG_B, TARGET_BIT_VECTOR_SET);	printf("adv%d: AdvanSys %s Host Adapter, SCSI ID %d, queue depth %d\n",	       adv->unit, (adv->type & ADV_ULTRA) ? "Ultra SCSI" : "SCSI",	       adv->scsi_id, adv->max_openings);	return (0);}voidadv_intr(void *arg){	struct	  adv_softc *adv;	u_int16_t chipstat;	u_int16_t saved_ram_addr;	u_int8_t  ctrl_reg;	u_int8_t  saved_ctrl_reg;	u_int8_t  host_flag;	adv = (struct adv_softc *)arg;	ctrl_reg = ADV_INB(adv, ADV_CHIP_CTRL);	saved_ctrl_reg = ctrl_reg & (~(ADV_CC_SCSI_RESET | ADV_CC_CHIP_RESET |				       ADV_CC_SINGLE_STEP | ADV_CC_DIAG |				       ADV_CC_TEST));	if ((chipstat = ADV_INW(adv, ADV_CHIP_STATUS)) & ADV_CSW_INT_PENDING) {				saved_ram_addr = ADV_INW(adv, ADV_LRAM_ADDR);		host_flag = adv_read_lram_8(adv, ADVV_HOST_FLAG_B);		adv_write_lram_8(adv, ADVV_HOST_FLAG_B,				 host_flag | ADV_HOST_FLAG_IN_ISR);		adv_ack_interrupt(adv);				if ((chipstat & ADV_CSW_HALTED)		    && (ctrl_reg & ADV_CC_SINGLE_STEP)) {			adv_isr_chip_halted(adv);			saved_ctrl_reg &= ~ADV_CC_HALT;		} else {			adv_run_doneq(adv);		}		ADV_OUTW(adv, ADV_LRAM_ADDR, saved_ram_addr);#ifdef DIAGNOSTIC			if (ADV_INW(adv, ADV_LRAM_ADDR) != saved_ram_addr)			panic("adv_intr: Unable to set LRAM addr");#endif			adv_write_lram_8(adv, ADVV_HOST_FLAG_B, host_flag);	}		ADV_OUTB(adv, ADV_CHIP_CTRL, saved_ctrl_reg);}voidadv_run_doneq(struct adv_softc *adv){	struct adv_q_done_info scsiq;	u_int		  doneq_head;	u_int		  done_qno;	doneq_head = adv_read_lram_16(adv, ADVV_DONE_Q_TAIL_W) & 0xFF;	done_qno = adv_read_lram_8(adv, ADV_QNO_TO_QADDR(doneq_head)				   + ADV_SCSIQ_B_FWD);	while (done_qno != ADV_QLINK_END) {		union ccb* ccb;		u_int done_qaddr;		u_int sg_queue_cnt;		int   aborted;		done_qaddr = ADV_QNO_TO_QADDR(done_qno);		/* Pull status from this request */		sg_queue_cnt = adv_copy_lram_doneq(adv, done_qaddr, &scsiq,						   adv->max_dma_count);		/* Mark it as free */		adv_write_lram_8(adv, done_qaddr + ADV_SCSIQ_B_STATUS,				 scsiq.q_status & ~(QS_READY|QS_ABORTED));		/* Process request based on retrieved info */		if ((scsiq.cntl & QC_SG_HEAD) != 0) {			u_int i;			/*			 * S/G based request.  Free all of the queue			 * structures that contained S/G information.			 */			for (i = 0; i < sg_queue_cnt; i++) {				done_qno = adv_read_lram_8(adv, done_qaddr							   + ADV_SCSIQ_B_FWD);#ifdef DIAGNOSTIC								if (done_qno == ADV_QLINK_END) {					panic("adv_qdone: Corrupted SG "					      "list encountered");				}#endif								done_qaddr = ADV_QNO_TO_QADDR(done_qno);				/* Mark SG queue as free */				adv_write_lram_8(adv, done_qaddr						 + ADV_SCSIQ_B_STATUS, QS_FREE);			}		} else 			sg_queue_cnt = 0;#ifdef DIAGNOSTIC		if (adv->cur_active < (sg_queue_cnt + 1))			panic("adv_qdone: Attempting to free more "			      "queues than are active");#endif				adv->cur_active -= sg_queue_cnt + 1;		aborted = (scsiq.q_status & QS_ABORTED) != 0;		if ((scsiq.q_status != QS_DONE)		 && (scsiq.q_status & QS_ABORTED) == 0)			panic("adv_qdone: completed scsiq with unknown status");		scsiq.remain_bytes += scsiq.extra_bytes;					if ((scsiq.d3.done_stat == QD_WITH_ERROR) &&		    (scsiq.d3.host_stat == QHSTA_M_DATA_OVER_RUN)) {			if ((scsiq.cntl & (QC_DATA_IN|QC_DATA_OUT)) == 0) {				scsiq.d3.done_stat = QD_NO_ERROR;				scsiq.d3.host_stat = QHSTA_NO_ERROR;			}		}		ccb = (union ccb *)scsiq.d2.ccb_ptr;		ccb->csio.resid = scsiq.remain_bytes;		adv_done(adv, (union ccb *)scsiq.d2.ccb_ptr,			 scsiq.d3.done_stat, scsiq.d3.host_stat,			 scsiq.d3.scsi_stat, scsiq.q_no);		doneq_head = done_qno;		done_qno = adv_read_lram_8(adv, done_qaddr + ADV_SCSIQ_B_FWD);	}	adv_write_lram_16(adv, ADVV_DONE_Q_TAIL_W, doneq_head);}voidadv_done(struct adv_softc *adv, union ccb *ccb, u_int done_stat,	 u_int host_stat, u_int scsi_status, u_int q_no){	struct	   adv_ccb_info *cinfo;	cinfo = (struct adv_ccb_info *)ccb->ccb_h.ccb_cinfo_ptr;	/*	 * Null this out so that we catch driver bugs that cause a	 * ccb to be completed twice.	 */	ccb->ccb_h.ccb_cinfo_ptr = NULL;	LIST_REMOVE(&ccb->ccb_h, sim_links.le);	untimeout(adv_timeout, ccb, ccb->ccb_h.timeout_ch);	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {		bus_dmasync_op_t op;		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)			op = BUS_DMASYNC_POSTREAD;		else			op = BUS_DMASYNC_POSTWRITE;		bus_dmamap_sync(adv->buffer_dmat, cinfo->dmamap, op);		bus_dmamap_unload(adv->buffer_dmat, cinfo->dmamap);	}	switch (done_stat) {	case QD_NO_ERROR:		if (host_stat == QHSTA_NO_ERROR) {			ccb->ccb_h.status = CAM_REQ_CMP;			break;		}		xpt_print_path(ccb->ccb_h.path);		printf("adv_done - queue done without error, "		       "but host status non-zero(%x)\n", host_stat);		/*FALLTHROUGH*/	case QD_WITH_ERROR:		switch (host_stat) {		case QHSTA_M_TARGET_STATUS_BUSY:		case QHSTA_M_BAD_QUEUE_FULL_OR_BUSY:			/*			 * Assume that if we were a tagged transaction			 * the target reported queue full.  Otherwise,			 * report busy.  The firmware really should just			 * pass the original status back up to us even			 * if it thinks the target was in error for			 * returning this status as no other transactions			 * from this initiator are in effect, but this			 * ignores multi-initiator setups and there is			 * evidence that the firmware gets its per-device			 * transaction counts screwed up occassionally.			 */			ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;			if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0			 && host_stat != QHSTA_M_TARGET_STATUS_BUSY)				scsi_status = SCSI_STATUS_QUEUE_FULL;			else				scsi_status = SCSI_STATUS_BUSY;			adv_abort_ccb(adv, ccb->ccb_h.target_id,				      ccb->ccb_h.target_lun,				      /*ccb*/NULL, CAM_REQUEUE_REQ,				      /*queued_only*/TRUE);			/*FALLTHROUGH*/		case QHSTA_M_NO_AUTO_REQ_SENSE:		case QHSTA_NO_ERROR:			ccb->csio.scsi_status = scsi_status;			switch (scsi_status) {			case SCSI_STATUS_CHECK_COND:			case SCSI_STATUS_CMD_TERMINATED:				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;				/* Structure copy */				ccb->csio.sense_data =				    adv->sense_buffers[q_no - 1];				/* FALLTHROUGH */			case SCSI_STATUS_BUSY:			case SCSI_STATUS_RESERV_CONFLICT:			case SCSI_STATUS_QUEUE_FULL:			case SCSI_STATUS_COND_MET:			case SCSI_STATUS_INTERMED:			case SCSI_STATUS_INTERMED_COND_MET:				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;				break;			case SCSI_STATUS_OK:				ccb->ccb_h.status |= CAM_REQ_CMP;				break;			}			break;		case QHSTA_M_SEL_TIMEOUT:			ccb->ccb_h.status = CAM_SEL_TIMEOUT;			break;		case QHSTA_M_DATA_OVER_RUN:			ccb->ccb_h.status = CAM_DATA_RUN_ERR;			break;		case QHSTA_M_UNEXPECTED_BUS_FREE:			ccb->ccb_h.status = CAM_UNEXP_BUSFREE;			break;		case QHSTA_M_BAD_BUS_PHASE_SEQ:			ccb->ccb_h.status = CAM_SEQUENCE_FAIL;			break;		case QHSTA_M_BAD_CMPL_STATUS_IN:			/* No command complete after a status message */			ccb->ccb_h.status = CAM_SEQUENCE_FAIL;			break;		case QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT:		case QHSTA_M_WTM_TIMEOUT:		case QHSTA_M_HUNG_REQ_SCSI_BUS_RESET:			/* The SCSI bus hung in a phase */			ccb->ccb_h.status = CAM_SEQUENCE_FAIL;			adv_reset_bus(adv);			break;		case QHSTA_M_AUTO_REQ_SENSE_FAIL:			ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;			break;		case QHSTA_D_QDONE_SG_LIST_CORRUPTED:		case QHSTA_D_ASC_DVC_ERROR_CODE_SET:		case QHSTA_D_HOST_ABORT_FAILED:		case QHSTA_D_EXE_SCSI_Q_FAILED:		case QHSTA_D_ASPI_NO_BUF_POOL:		case QHSTA_M_BAD_TAG_CODE:		case QHSTA_D_LRAM_CMP_ERROR:		case QHSTA_M_MICRO_CODE_ERROR_HALT:		default:			panic("%s: Unhandled Host status error %x",			      adv_name(adv), host_stat);			/* NOTREACHED */		}		break;	case QD_ABORTED_BY_HOST:		/* Don't clobber any, more explicit, error codes we've set */		if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)			ccb->ccb_h.status = CAM_REQ_ABORTED;		break;	default:		xpt_print_path(ccb->ccb_h.path);		printf("adv_done - queue done with unknown status %x:%x\n",		       done_stat, host_stat);		ccb->ccb_h.status = CAM_REQ_CMP_ERR;		break;	}	if ((cinfo->state & ACCB_RELEASE_SIMQ) != 0)		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;	else if (adv->openings_needed > 0) {		int openings;		openings = adv->max_openings - adv->cur_active - ADV_MIN_FREE_Q;		if (openings >= adv->openings_needed) {			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;			adv->openings_needed = 0;		}	}	if ((cinfo->state & ACCB_RECOVERY_CCB) != 0) {		/*		 * We now traverse our list of pending CCBs and reinstate		 * their timeouts.		 */		struct ccb_hdr *ccb_h;		ccb_h = LIST_FIRST(&adv->pending_ccbs);		while (ccb_h != NULL) {			ccb_h->timeout_ch =			    timeout(adv_timeout, (caddr_t)ccb_h,					    (ccb_h->timeout * hz) / 1000);			ccb_h = LIST_NEXT(ccb_h, sim_links.le);		}		printf("%s: No longer in timeout\n", adv_name(adv));	}	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP	 && (ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {		xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);		ccb->ccb_h.status |= CAM_DEV_QFRZN;	}	adv_free_ccb_info(adv, cinfo);	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;	xpt_done(ccb);}/* * Function to poll for command completion when * interrupts are disabled (crash dumps) */static voidadv_poll(struct cam_sim *sim){	adv_intr(cam_sim_softc(sim));}/* * Attach all the sub-devices we can find */intadv_attach(adv)	struct adv_softc *adv;{	struct ccb_setasync csa;	struct cam_devq *devq;	/*	 * Create our DMA tags.  These tags define the kinds of device	 * accessable memory allocations and memory mappings we will 	 * need to perform during normal operation.	 *	 * Unless we need to further restrict the allocation, we rely	 * on the restrictions of the parent dmat, hence the common	 * use of MAXADDR and MAXSIZE.	 */	/* DMA tag for mapping buffers into device visible space. */	if (bus_dma_tag_create(adv->parent_dmat, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       /*maxsize*/MAXBSIZE,			       /*nsegments*/ADV_MAX_SG_LIST,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/BUS_DMA_ALLOCNOW,			       &adv->buffer_dmat) != 0) {		goto error_exit;	}	adv->init_level++;	/* DMA tag for our sense buffers */	if (bus_dma_tag_create(adv->parent_dmat, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       sizeof(struct scsi_sense_data)*adv->max_openings,			       /*nsegments*/1,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/0, &adv->sense_dmat) != 0) {		goto error_exit;        }	adv->init_level++;	/* Allocation for our sense buffers */	if (bus_dmamem_alloc(adv->sense_dmat, (void **)&adv->sense_buffers,			     BUS_DMA_NOWAIT, &adv->sense_dmamap) != 0) {		goto error_exit;	}	adv->init_level++;	/* And permanently map them */	bus_dmamap_load(adv->sense_dmat, adv->sense_dmamap,       			adv->sense_buffers,			sizeof(struct scsi_sense_data)*adv->max_openings,			adv_map, &adv->sense_physbase, /*flags*/0);	adv->init_level++;	/*	 * Fire up the chip	 */	if (adv_start_chip(adv) != 1) {		printf("adv%d: Unable to start on board processor. Aborting.\n",		       adv->unit);		return (0);	}	/*	 * Create the device queue for our SIM.	 */	devq = cam_simq_alloc(adv->max_openings);	if (devq == NULL)		return (0);	/*	 * Construct our SIM entry.	 */	adv->sim = cam_sim_alloc(adv_action, adv_poll, "adv", adv, adv->unit,				 1, adv->max_openings, devq);	if (adv->sim == NULL)		return (0);	/*	 * Register the bus.	 *	 * XXX Twin Channel EISA Cards???	 */	if (xpt_bus_register(adv->sim, 0) != CAM_SUCCESS) {		cam_sim_free(adv->sim, /*free devq*/TRUE);		return (0);	}	if (xpt_create_path(&adv->path, /*periph*/NULL, cam_sim_path(adv->sim),			    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)	   == CAM_REQ_CMP) {		xpt_setup_ccb(&csa.ccb_h, adv->path, /*priority*/5);		csa.ccb_h.func_code = XPT_SASYNC_CB;		csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE;		csa.callback = advasync;		csa.callback_arg = adv;		xpt_action((union ccb *)&csa);	}	return (1);error_exit:	return (0);}

⌨️ 快捷键说明

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