scsi_targ_bh.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 723 行 · 第 1/2 页

C
723
字号
	struct ccb_accept_tio* atio;	struct ccb_hdr *ccb_h;	softc = (struct targbh_softc *)periph->softc;	if ((softc->flags & TARGBH_FLAG_LUN_ENABLED) == 0)		return CAM_REQ_CMP;	/* XXX Block for Continue I/O completion */	/* Kill off all ACCECPT and IMMEDIATE CCBs */	while ((atio = softc->accept_tio_list) != NULL) {				softc->accept_tio_list =		    ((struct targbh_cmd_desc*)atio->ccb_h.ccb_descr)->atio_link;		xpt_setup_ccb(&ccb.cab.ccb_h, periph->path, /*priority*/1);		ccb.cab.ccb_h.func_code = XPT_ABORT;		ccb.cab.abort_ccb = (union ccb *)atio;		xpt_action(&ccb);	}	while ((ccb_h = SLIST_FIRST(&softc->immed_notify_slist)) != NULL) {		SLIST_REMOVE_HEAD(&softc->immed_notify_slist, periph_links.sle);		xpt_setup_ccb(&ccb.cab.ccb_h, periph->path, /*priority*/1);		ccb.cab.ccb_h.func_code = XPT_ABORT;		ccb.cab.abort_ccb = (union ccb *)ccb_h;		xpt_action(&ccb);	}	/*	 * Dissable this lun.	 */	xpt_setup_ccb(&ccb.cel.ccb_h, periph->path, /*priority*/1);	ccb.cel.ccb_h.func_code = XPT_EN_LUN;	ccb.cel.enable = 0;	xpt_action(&ccb);	if (ccb.cel.ccb_h.status != CAM_REQ_CMP)		printf("targbhdislun - Disabling lun on controller failed "		       "with status 0x%x\n", ccb.cel.ccb_h.status);	else 		softc->flags &= ~TARGBH_FLAG_LUN_ENABLED;	return (ccb.cel.ccb_h.status);}static cam_statustargbhctor(struct cam_periph *periph, void *arg){	struct ccb_pathinq *cpi;	struct targbh_softc *softc;	cpi = (struct ccb_pathinq *)arg;	/* Allocate our per-instance private storage */	softc = (struct targbh_softc *)malloc(sizeof(*softc),					      M_DEVBUF, M_NOWAIT);	if (softc == NULL) {		printf("targctor: unable to malloc softc\n");		return (CAM_REQ_CMP_ERR);	}	bzero(softc, sizeof(softc));	TAILQ_INIT(&softc->pending_queue);	TAILQ_INIT(&softc->work_queue);	softc->accept_tio_list = NULL;	SLIST_INIT(&softc->immed_notify_slist);	softc->state = TARGBH_STATE_NORMAL;	periph->softc = softc;	softc->init_level++;	return (targbhenlun(periph));}static voidtargbhdtor(struct cam_periph *periph){	struct targbh_softc *softc;	softc = (struct targbh_softc *)periph->softc;	softc->state = TARGBH_STATE_TEARDOWN;	targbhdislun(periph);	switch (softc->init_level) {	default:		/* FALLTHROUGH */	case 1:		free(softc, M_DEVBUF);		break;	case 0:		panic("targdtor - impossible init level");;	}}static voidtargbhstart(struct cam_periph *periph, union ccb *start_ccb){	struct targbh_softc *softc;	struct ccb_hdr *ccbh;	struct ccb_accept_tio *atio;	struct targbh_cmd_desc *desc;	struct ccb_scsiio *csio;	ccb_flags flags;	int    s;	softc = (struct targbh_softc *)periph->softc;		s = splbio();	ccbh = TAILQ_FIRST(&softc->work_queue);	if (periph->immediate_priority <= periph->pinfo.priority) {		start_ccb->ccb_h.ccb_type = TARGBH_CCB_WAITING;					SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,				  periph_links.sle);		periph->immediate_priority = CAM_PRIORITY_NONE;		splx(s);		wakeup(&periph->ccb_list);	} else if (ccbh == NULL) {		splx(s);		xpt_release_ccb(start_ccb);		} else {		TAILQ_REMOVE(&softc->work_queue, ccbh, periph_links.tqe);		TAILQ_INSERT_HEAD(&softc->pending_queue, ccbh,				  periph_links.tqe);		splx(s);			atio = (struct ccb_accept_tio*)ccbh;		desc = (struct targbh_cmd_desc *)atio->ccb_h.ccb_descr;		/* Is this a tagged request? */		flags = atio->ccb_h.flags & (CAM_TAG_ACTION_VALID|CAM_DIR_MASK);		/*		 * If we are done with the transaction, tell the		 * controller to send status and perform a CMD_CMPLT.		 */		if (desc->data_resid == desc->data_increment)			flags |= CAM_SEND_STATUS;		csio = &start_ccb->csio;		cam_fill_ctio(csio,			      /*retries*/2,			      targbhdone,			      flags,			      /*tag_action*/MSG_SIMPLE_Q_TAG,			      atio->tag_id,			      atio->init_id,			      desc->status,			      /*data_ptr*/desc->data_increment == 0					  ? NULL : desc->data,			      /*dxfer_len*/desc->data_increment,			      /*timeout*/desc->timeout);		/* Override our wildcard attachment */		start_ccb->ccb_h.target_id = atio->ccb_h.target_id;		start_ccb->ccb_h.target_lun = atio->ccb_h.target_lun;		start_ccb->ccb_h.ccb_type = TARGBH_CCB_WORKQ;		start_ccb->ccb_h.ccb_atio = atio;		CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,			  ("Sending a CTIO\n"));		xpt_action(start_ccb);		s = splbio();		ccbh = TAILQ_FIRST(&softc->work_queue);		splx(s);	}	if (ccbh != NULL)		xpt_schedule(periph, /*priority*/1);}static voidtargbhdone(struct cam_periph *periph, union ccb *done_ccb){	struct targbh_softc *softc;	softc = (struct targbh_softc *)periph->softc;	if (done_ccb->ccb_h.ccb_type == TARGBH_CCB_WAITING) {		/* Caller will release the CCB */		wakeup(&done_ccb->ccb_h.cbfcnp);		return;	}	switch (done_ccb->ccb_h.func_code) {	case XPT_ACCEPT_TARGET_IO:	{		struct ccb_accept_tio *atio;		struct targbh_cmd_desc *descr;		u_int8_t *cdb;		atio = &done_ccb->atio;		descr = (struct targbh_cmd_desc*)atio->ccb_h.ccb_descr;		cdb = atio->cdb_io.cdb_bytes;		if (softc->state == TARGBH_STATE_TEARDOWN		 || atio->ccb_h.status == CAM_REQ_ABORTED) {			targbhfreedescr(descr);			free(done_ccb, M_DEVBUF);			return;		}		/*		 * Determine the type of incoming command and		 * setup our buffer for a response.		 */		switch (cdb[0]) {		case INQUIRY:		{			struct scsi_inquiry *inq;			inq = (struct scsi_inquiry *)cdb;			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,				  ("Saw an inquiry!\n"));			/*			 * Validate the command.  We don't			 * support any VPD pages, so complain			 * if EVPD is set.			 */			if ((inq->byte2 & SI_EVPD) != 0			 || inq->page_code != 0) {				atio->ccb_h.flags &= ~CAM_DIR_MASK;				atio->ccb_h.flags |= CAM_DIR_NONE;				descr->data_resid = 0;				descr->data_increment = 0;				descr->status = SCSI_STATUS_CHECK_COND;				break;			}			/*			 * Direction is always relative			 * to the initator.			 */			atio->ccb_h.flags &= ~CAM_DIR_MASK;			atio->ccb_h.flags |= CAM_DIR_IN;			descr->data = &no_lun_inq_data;			descr->data_resid = MIN(sizeof(no_lun_inq_data),						inq->length);			descr->data_increment = descr->data_resid;			descr->timeout = 5 * 1000;			descr->status = SCSI_STATUS_OK;			break;		}		case REQUEST_SENSE:		{			struct scsi_request_sense *rsense;			rsense = (struct scsi_request_sense *)cdb;			/* Refer to static sense data */			atio->ccb_h.flags &= ~CAM_DIR_MASK;			atio->ccb_h.flags |= CAM_DIR_IN;			descr->data = &no_lun_sense_data;			descr->data_resid = request_sense_size;			descr->data_resid = MIN(descr->data_resid,						rsense->length);			descr->data_increment = descr->data_resid;			descr->timeout = 5 * 1000;			descr->status = SCSI_STATUS_OK;			break;		}		default:			/* Constant CA, tell initiator */			/* Direction is always relative to the initator */			atio->ccb_h.flags &= ~CAM_DIR_MASK;			atio->ccb_h.flags |= CAM_DIR_NONE;			descr->data_resid = 0;			descr->data_increment = 0;			descr->timeout = 5 * 1000;			descr->status = SCSI_STATUS_CHECK_COND;			break;		}		/* Queue us up to receive a Continue Target I/O ccb. */		TAILQ_INSERT_TAIL(&softc->work_queue, &atio->ccb_h,				  periph_links.tqe);		xpt_schedule(periph, /*priority*/1);		break;	}	case XPT_CONT_TARGET_IO:	{		struct ccb_accept_tio *atio;		struct targbh_cmd_desc *desc;		CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,			  ("Received completed CTIO\n"));		atio = (struct ccb_accept_tio*)done_ccb->ccb_h.ccb_atio;		desc = (struct targbh_cmd_desc *)atio->ccb_h.ccb_descr;		TAILQ_REMOVE(&softc->pending_queue, &atio->ccb_h,			     periph_links.tqe);		/* XXX Check for errors */		desc->data_resid -= desc->data_increment;		xpt_release_ccb(done_ccb);		if (softc->state != TARGBH_STATE_TEARDOWN) {			/*			 * Send the original accept TIO back to the			 * controller to handle more work.			 */			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,				  ("Returning ATIO to target\n"));			/* Restore wildcards */			atio->ccb_h.target_id = CAM_TARGET_WILDCARD;			atio->ccb_h.target_lun = CAM_LUN_WILDCARD;			xpt_action((union ccb *)atio);			break;		} else {			targbhfreedescr(desc);			free(atio, M_DEVBUF);		}		break;	}	case XPT_IMMED_NOTIFY:	{		if (softc->state == TARGBH_STATE_TEARDOWN		 || done_ccb->ccb_h.status == CAM_REQ_ABORTED) {			printf("Freed an immediate notify\n");			free(done_ccb, M_DEVBUF);		}		break;	}	default:		panic("targbhdone: Unexpected ccb opcode");		break;	}}#ifdef NOTYETstatic inttargbherror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags){	return 0;}#endifstatic struct targbh_cmd_desc*targbhallocdescr(){	struct targbh_cmd_desc* descr;	/* Allocate the targbh_descr structure */	descr = (struct targbh_cmd_desc *)malloc(sizeof(*descr),					       M_DEVBUF, M_NOWAIT);	if (descr == NULL)		return (NULL);	bzero(descr, sizeof(*descr));	/* Allocate buffer backing store */	descr->backing_store = malloc(MAX_BUF_SIZE, M_DEVBUF, M_NOWAIT);	if (descr->backing_store == NULL) {		free(descr, M_DEVBUF);		return (NULL);	}	descr->max_size = MAX_BUF_SIZE;	return (descr);}static voidtargbhfreedescr(struct targbh_cmd_desc *descr){	free(descr->backing_store, M_DEVBUF);	free(descr, M_DEVBUF);}

⌨️ 快捷键说明

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