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

📄 bt.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
					if ((ccbh->flags & CAM_DATA_PHYS)==0) {						int s;						int error;						s = splsoftvm();						error = bus_dmamap_load(						    bt->buffer_dmat,						    bccb->dmamap,						    csio->data_ptr,						    csio->dxfer_len,						    btexecuteccb,						    bccb,						    /*flags*/0);						if (error == EINPROGRESS) {							/*							 * So as to maintain							 * ordering, freeze the							 * controller queue							 * until our mapping is							 * returned.							 */							xpt_freeze_simq(bt->sim,									1);							csio->ccb_h.status |=							    CAM_RELEASE_SIMQ;						}						splx(s);					} else {						struct bus_dma_segment seg; 						/* Pointer to physical buffer */						seg.ds_addr =						    (bus_addr_t)csio->data_ptr;						seg.ds_len = csio->dxfer_len;						btexecuteccb(bccb, &seg, 1, 0);					}				} else {					struct bus_dma_segment *segs;					if ((ccbh->flags & CAM_DATA_PHYS) != 0)						panic("btaction - Physical "						      "segment pointers "						      "unsupported");					if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)						panic("btaction - Virtual "						      "segment addresses "						      "unsupported");					/* Just use the segments provided */					segs = (struct bus_dma_segment *)					    csio->data_ptr;					btexecuteccb(bccb, segs,						     csio->sglist_cnt, 0);				}			} else {				btexecuteccb(bccb, NULL, 0, 0);			}		} else {			hccb->opcode = INITIATOR_BUS_DEV_RESET;			/* No data transfer */			hccb->datain = TRUE;			hccb->dataout = TRUE;			hccb->cmd_len = 0;			hccb->sense_len = 0;			hccb->tag_enable = FALSE;			hccb->tag_type = 0;			btexecuteccb(bccb, NULL, 0, 0);		}		break;	}	case XPT_EN_LUN:		/* Enable LUN as a target */	case XPT_TARGET_IO:		/* Execute target I/O request */	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/	case XPT_ABORT:			/* Abort the specified CCB */		/* XXX Implement */		ccb->ccb_h.status = CAM_REQ_INVALID;		xpt_done(ccb);		break;	case XPT_SET_TRAN_SETTINGS:	{		/* XXX Implement */		ccb->ccb_h.status = CAM_PROVIDE_FAIL;		xpt_done(ccb);		break;	}	case XPT_GET_TRAN_SETTINGS:	/* Get default/user set transfer settings for the target */	{		struct	ccb_trans_settings *cts;		u_int	target_mask;		cts = &ccb->cts;		target_mask = 0x01 << ccb->ccb_h.target_id;		if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {			cts->flags = 0;			if ((bt->disc_permitted & target_mask) != 0)				cts->flags |= CCB_TRANS_DISC_ENB;			if ((bt->tags_permitted & target_mask) != 0)				cts->flags |= CCB_TRANS_TAG_ENB;			if ((bt->wide_permitted & target_mask) != 0)				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;			else				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;			if ((bt->ultra_permitted & target_mask) != 0)				cts->sync_period = 12;			else if ((bt->fast_permitted & target_mask) != 0)				cts->sync_period = 25;			else if ((bt->sync_permitted & target_mask) != 0)				cts->sync_period = 50;			else				cts->sync_period = 0;			if (cts->sync_period != 0)				cts->sync_offset = 15;			cts->valid = CCB_TRANS_SYNC_RATE_VALID				   | CCB_TRANS_SYNC_OFFSET_VALID				   | CCB_TRANS_BUS_WIDTH_VALID				   | CCB_TRANS_DISC_VALID				   | CCB_TRANS_TQ_VALID;		} else {			btfetchtransinfo(bt, cts);		}		ccb->ccb_h.status = CAM_REQ_CMP;		xpt_done(ccb);		break;	}	case XPT_CALC_GEOMETRY:	{		struct	  ccb_calc_geometry *ccg;		u_int32_t size_mb;		u_int32_t secs_per_cylinder;		ccg = &ccb->ccg;		size_mb = ccg->volume_size			/ ((1024L * 1024L) / ccg->block_size);				if (size_mb >= 1024 && (bt->extended_trans != 0)) {			if (size_mb >= 2048) {				ccg->heads = 255;				ccg->secs_per_track = 63;			} else {				ccg->heads = 128;				ccg->secs_per_track = 32;			}		} else {			ccg->heads = 64;			ccg->secs_per_track = 32;		}		secs_per_cylinder = ccg->heads * ccg->secs_per_track;		ccg->cylinders = ccg->volume_size / secs_per_cylinder;		ccb->ccb_h.status = CAM_REQ_CMP;		xpt_done(ccb);		break;	}	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */	{		btreset(bt, /*hardreset*/TRUE);		ccb->ccb_h.status = CAM_REQ_CMP;		xpt_done(ccb);		break;	}	case XPT_TERM_IO:		/* Terminate the I/O process */		/* XXX Implement */		ccb->ccb_h.status = CAM_REQ_INVALID;		xpt_done(ccb);		break;	case XPT_PATH_INQ:		/* Path routing inquiry */	{		struct ccb_pathinq *cpi = &ccb->cpi;				cpi->version_num = 1; /* XXX??? */		cpi->hba_inquiry = PI_SDTR_ABLE;		if (bt->tag_capable != 0)			cpi->hba_inquiry |= PI_TAG_ABLE;		if (bt->wide_bus != 0)			cpi->hba_inquiry |= PI_WIDE_16;		cpi->target_sprt = 0;		cpi->hba_misc = 0;		cpi->hba_eng_cnt = 0;		cpi->max_target = bt->wide_bus ? 15 : 7;		cpi->max_lun = 7;		cpi->initiator_id = bt->scsi_id;		cpi->bus_id = cam_sim_bus(sim);		cpi->base_transfer_speed = 3300;		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);		strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN);		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);		cpi->unit_number = cam_sim_unit(sim);		cpi->ccb_h.status = CAM_REQ_CMP;		xpt_done(ccb);		break;	}	default:		ccb->ccb_h.status = CAM_REQ_INVALID;		xpt_done(ccb);		break;	}}static voidbtexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error){	struct	 bt_ccb *bccb;	union	 ccb *ccb;	struct	 bt_softc *bt;	int	 s;	bccb = (struct bt_ccb *)arg;	ccb = bccb->ccb;	bt = (struct bt_softc *)ccb->ccb_h.ccb_bt_ptr;	if (error != 0) {		if (error != EFBIG)			printf("%s: Unexepected error 0x%x returned from "			       "bus_dmamap_load\n", bt_name(bt), error);		if (ccb->ccb_h.status == CAM_REQ_INPROG) {			xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);			ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;		}		btfreeccb(bt, bccb);		xpt_done(ccb);		return;	}			if (nseg != 0) {		bt_sg_t *sg;		bus_dma_segment_t *end_seg;		bus_dmasync_op_t op;		end_seg = dm_segs + nseg;		/* Copy the segments into our SG list */		sg = bccb->sg_list;		while (dm_segs < end_seg) {			sg->len = dm_segs->ds_len;			sg->addr = dm_segs->ds_addr;			sg++;			dm_segs++;		}		if (nseg > 1) {			bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID;			bccb->hccb.data_len = sizeof(bt_sg_t) * nseg;			bccb->hccb.data_addr = bccb->sg_list_phys;		} else {			bccb->hccb.data_len = bccb->sg_list->len;			bccb->hccb.data_addr = bccb->sg_list->addr;		}		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)			op = BUS_DMASYNC_PREREAD;		else			op = BUS_DMASYNC_PREWRITE;		bus_dmamap_sync(bt->buffer_dmat, bccb->dmamap, op);	} else {		bccb->hccb.opcode = INITIATOR_CCB;		bccb->hccb.data_len = 0;		bccb->hccb.data_addr = 0;	}	s = splcam();	/*	 * Last time we need to check if this CCB needs to	 * be aborted.	 */	if (ccb->ccb_h.status != CAM_REQ_INPROG) {		if (nseg != 0)			bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);		btfreeccb(bt, bccb);		xpt_done(ccb);		splx(s);		return;	}			bccb->flags = BCCB_ACTIVE;	ccb->ccb_h.status |= CAM_SIM_QUEUED;	LIST_INSERT_HEAD(&bt->pending_ccbs, &ccb->ccb_h, sim_links.le);	ccb->ccb_h.timeout_ch =	    timeout(bttimeout, (caddr_t)bccb,		    (ccb->ccb_h.timeout * hz) / 1000);	/* Tell the adapter about this command */	bt->cur_outbox->ccb_addr = btccbvtop(bt, bccb);	if (bt->cur_outbox->action_code != BMBO_FREE) {		/*		 * We should never encounter a busy mailbox.		 * If we do, warn the user, and treat it as		 * a resource shortage.  If the controller is		 * hung, one of the pending transactions will		 * timeout causing us to start recovery operations.		 */		printf("%s: Encountered busy mailbox with %d out of %d "		       "commands active!!!\n", bt_name(bt), bt->active_ccbs,		       bt->max_ccbs);		untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);		if (nseg != 0)			bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);		btfreeccb(bt, bccb);		bt->resource_shortage = TRUE;		xpt_freeze_simq(bt->sim, /*count*/1);		ccb->ccb_h.status = CAM_REQUEUE_REQ;		xpt_done(ccb);		return;	}	bt->cur_outbox->action_code = BMBO_START;		bt_outb(bt, COMMAND_REG, BOP_START_MBOX);	btnextoutbox(bt);	splx(s);}voidbt_intr(void *arg){	struct	bt_softc *bt;	u_int	intstat;	bt = (struct bt_softc *)arg;	while (((intstat = bt_inb(bt, INTSTAT_REG)) & INTR_PENDING) != 0) {		if ((intstat & CMD_COMPLETE) != 0) {			bt->latched_status = bt_inb(bt, STATUS_REG);			bt->command_cmp = TRUE;		}		bt_outb(bt, CONTROL_REG, RESET_INTR);		if ((intstat & IMB_LOADED) != 0) {			while (bt->cur_inbox->comp_code != BMBI_FREE) {				btdone(bt,				       btccbptov(bt, bt->cur_inbox->ccb_addr),				       bt->cur_inbox->comp_code);				bt->cur_inbox->comp_code = BMBI_FREE;				btnextinbox(bt);			}		}		if ((intstat & SCSI_BUS_RESET) != 0) {			btreset(bt, /*hardreset*/FALSE);		}	}}static voidbtdone(struct bt_softc *bt, struct bt_ccb *bccb, bt_mbi_comp_code_t comp_code){	union  ccb	  *ccb;	struct ccb_scsiio *csio;	ccb = bccb->ccb;	csio = &bccb->ccb->csio;	if ((bccb->flags & BCCB_ACTIVE) == 0) {		printf("%s: btdone - Attempt to free non-active BCCB %p\n",		       bt_name(bt), (void *)bccb);		return;	}	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(bt->buffer_dmat, bccb->dmamap, op);		bus_dmamap_unload(bt->buffer_dmat, bccb->dmamap);	}	if (bccb == bt->recovery_bccb) {		/*		 * The recovery BCCB does not have a CCB associated		 * with it, so short circuit the normal error handling.		 * We now traverse our list of pending CCBs and process		 * any that were terminated by the recovery CCBs action.		 * We also reinstate timeouts for all remaining, pending,		 * CCBs.		 */		struct cam_path *path;		struct ccb_hdr *ccb_h;		cam_status error;		/* Notify all clients that a BDR occured */		error = xpt_create_path(&path, /*periph*/NULL,					cam_sim_path(bt->sim),					bccb->hccb.target_id,					CAM_LUN_WILDCARD);				if (error == CAM_REQ_CMP)			xpt_async(AC_SENT_BDR, path, NULL);		ccb_h = LIST_FIRST(&bt->pending_ccbs);		while (ccb_h != NULL) {			struct bt_ccb *pending_bccb;			pending_bccb = (struct bt_ccb *)ccb_h->ccb_bccb_ptr;			if (pending_bccb->hccb.target_id			 == bccb->hccb.target_id) {				pending_bccb->hccb.btstat = BTSTAT_HA_BDR;				ccb_h = LIST_NEXT(ccb_h, sim_links.le);				btdone(bt, pending_bccb, BMBI_ERROR);			} else {				ccb_h->timeout_ch =				    timeout(bttimeout, (caddr_t)pending_bccb,					    (ccb_h->timeout * hz) / 1000);				ccb_h = LIST_NEXT(ccb_h, sim_links.le);			}		}		printf("%s: No longer in timeout\n", bt_name(bt));		return;	}	untimeout(bttimeout, bccb, ccb->ccb_h.timeout_ch);	switch (comp_code) {	case BMBI_FREE:		printf("%s: btdone - CCB completed with free status!\n",		       bt_name(bt));		break;	case BMBI_NOT_FOUND:		printf("%s: btdone - CCB Abort failed to find CCB\n",		       bt_name(bt));		break;	case BMBI_ABORT:	case BMBI_ERROR:		if (bootverbose) {			printf("bt: ccb %p - error %x occured.  "			       "btstat = %x, sdstat = %x\n",			       (void *)bccb, comp_code, bccb->hccb.btstat,			       bccb->hccb.sdstat);		}		/* An error occured */		switch(bccb->hccb.btstat) {		case BTSTAT_DATARUN_ERROR:			if (bccb->hccb.data_len == 0) {				/*				 * At least firmware 4.22, does this				 * for a QUEUE FULL condition.				 */				bccb->hccb.sdstat = SCSI_STATUS_QUEUE_FULL;			} else if (bccb->hccb.data_len < 0) {				csio->ccb_h.status = CAM_DATA_RUN_ERR;				break;			}			/* FALLTHROUGH */		case BTSTAT_NOERROR:		case BTSTAT_LINKED_CMD_COMPLETE:		case BTSTAT_LINKED_CMD_FLAG_COMPLETE:		case BTSTAT_DATAUNDERUN_ERROR:			csio->scsi_status = bccb->hccb.sdstat;			csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;			switch(csio->scsi_status) {			case SCSI_STATUS_CHECK_COND:			case SCSI_STATUS_CMD_TERMINATED:				csio->ccb_h.status |= CAM_AUTOSNS_VALID;				/* Bounce sense back if necessary */				if (bt->sense_buffers != NULL) {					csio->sense_data =					    *btsensevaddr(bt, bccb);				}				break;			default:				break;			case SCSI_STATUS_OK:				csio->ccb_h.status = CAM_REQ_CMP;				break;			}			csio->resid = bccb->hccb.data_len;			break;		case BTSTAT_SELTIMEOUT:			csio->ccb_h.status = CAM_SEL_TIMEOUT;			break;		case BTSTAT_UNEXPECTED_BUSFREE:			csio->ccb_h.status = CAM_UNEXP_BUSFREE;			break;		case BTSTAT_INVALID_PHASE:			csio->ccb_h.status = CAM_SEQUENCE_FAIL;			break;		case BTSTAT_INVALID_ACTION_CODE:			panic("%s: Inavlid Action code", bt_name(bt));			break;		case BTSTAT_INVALID_OPCODE:			panic("%s: Inavlid CCB Opcode code", bt_name(bt));			break;		case BTSTAT_LINKED_CCB_LUN_MISMATCH:			/* We don't even support linked commands... */			panic("%s: Linked CCB Lun Mismatch", bt_name(bt));			break;		case BTSTAT_INVALID_CCB_OR_SG_PARAM:			panic("%s: Invalid CCB or SG list", bt_name(bt));			break;		case BTSTAT_AUTOSENSE_FAILED:			csio->ccb_h.status = CAM_AUTOSENSE_FAIL;			break;		case BTSTAT_TAGGED_MSG_REJECTED:		{			struct ccb_trans_settings neg;  			xpt_print_path(csio->ccb_h.path);			printf("refuses tagged commands.  Performing "			       "non-tagged I/O\n");			neg.flags = 0;			neg.valid = CCB_TRANS_TQ_VALID;			xpt_setup_ccb(&neg.ccb_h, csio->ccb_h.path,				      /*priority*/1); 			xpt_async(AC_TRANSFER_NEG, csio->ccb_h.path, &neg);			bt->tags_permitted &= ~(0x01 << csio->ccb_h.target_id);			csio->ccb_h.status = CAM_MSG_REJECT_REC;			break;		}		case BTSTAT_UNSUPPORTED_MSG_RECEIVED:			/*			 * XXX You would think that this is			 *     a recoverable error... Hmmm.			 */			csio->ccb_h.status = CAM_REQ_CMP_ERR;			break;		case BTSTAT_HA_SOFTWARE_ERROR:		case BTSTAT_HA_WATCHDOG_ERROR:		case BTSTAT_HARDWARE_FAILURE:			/* Hardware reset ??? Can we recover ??? */			csio->ccb_h.status = CAM_NO_HBA;			break;		case BTSTAT_TARGET_IGNORED_ATN:		case BTSTAT_OTHER_SCSI_BUS_RESET:		case BTSTAT_HA_SCSI_BUS_RESET:			if ((csio->ccb_h.status & CAM_STATUS_MASK)			 != CAM_CMD_TIMEOUT)				csio->ccb_h.status = CAM_SCSI_BUS_RESET;			break;		case BTSTAT_HA_BDR:			if ((bccb->flags & BCCB_DEVICE_RESET) == 0)				csio->ccb_h.status = CAM_BDR_SENT;			else				csio->ccb_h.status = CAM_CMD_TIMEOUT;			break;		case BTSTAT_INVALID_RECONNECT:		case BTSTAT_ABORT_QUEUE_GENERATED:			csio->ccb_h.status = CAM_REQ_TERMIO;			break;		case BTSTAT_SCSI_PERROR_DETECTED:			csio->ccb_h.status = CAM_UNCOR_PARITY;			break;		}		if (csio->ccb_h.status != CAM_REQ_CMP) {			xpt_freeze_devq(csio->ccb_h.path, /*count*/1);			csio->ccb_h.status |= CAM_DEV_QFRZN;		}		if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;		btfreeccb(bt, bccb);		xpt_done(ccb);		break;	case BMBI_OK:		/* All completed without incident */		ccb->ccb_h.status |= CAM_REQ_CMP;		if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0)			ccb->ccb_h.status |= CAM_RELEASE_SIMQ;		btfreeccb(bt, bccb);		xpt_done(ccb);		break;	}}static intbtreset(struct bt_softc* bt, int hard_reset){	struct	 ccb_hdr *ccb_h;	u_int	 status;	u_int	 timeout;	u_int8_t reset_type;	if (hard_reset != 0)		reset_type = HARD_RESET;	else		reset_type = SOFT_RESET;	bt_outb(bt, CONTROL_REG, reset_type);	/* Wait 5sec. for Diagnostic start */

⌨️ 快捷键说明

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