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

📄 bt.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	} else {		bt->max_ccbs = 30;		if (bt->firmware_ver[0] == '3'		 && (strcmp(bt->firmware_ver, "3.35") >= 0))			bt->tag_capable = TRUE;		else			bt->tag_capable = FALSE;	}	if (bt->tag_capable != FALSE)		bt->tags_permitted = ALL_TARGETS;	/* Determine Sync/Wide/Disc settings */	if (bt->firmware_ver[0] >= '4') {		auto_scsi_data_t auto_scsi_data;		fetch_lram_params_t fetch_lram_params;		int error;				/*		 * These settings are stored in the		 * AutoSCSI data in LRAM of 'W' and 'C'		 * adapters.		 */		fetch_lram_params.offset = AUTO_SCSI_BYTE_OFFSET;		fetch_lram_params.response_len = sizeof(auto_scsi_data);		error = bt_cmd(bt, BOP_FETCH_LRAM,			       (u_int8_t*)&fetch_lram_params,			       sizeof(fetch_lram_params),			       (u_int8_t*)&auto_scsi_data,			       sizeof(auto_scsi_data), DEFAULT_CMD_TIMEOUT);		if (error != 0) {			printf("%s: bt_fetch_adapter_info - Failed "			       "Get Auto SCSI Info\n", bt_name(bt));			return (error);		}		bt->disc_permitted = auto_scsi_data.low_disc_permitted				   | (auto_scsi_data.high_disc_permitted << 8);		bt->sync_permitted = auto_scsi_data.low_sync_permitted				   | (auto_scsi_data.high_sync_permitted << 8);		bt->fast_permitted = auto_scsi_data.low_fast_permitted				   | (auto_scsi_data.high_fast_permitted << 8);		bt->ultra_permitted = auto_scsi_data.low_ultra_permitted				   | (auto_scsi_data.high_ultra_permitted << 8);		bt->wide_permitted = auto_scsi_data.low_wide_permitted				   | (auto_scsi_data.high_wide_permitted << 8);		if (bt->ultra_scsi == FALSE)			bt->ultra_permitted = 0;		if (bt->wide_bus == FALSE)			bt->wide_permitted = 0;	} else {		/*		 * 'S' and 'A' series have this information in the setup		 * information structure.		 */		setup_data_t	setup_info;		length_param = sizeof(setup_info);		error = bt_cmd(bt, BOP_INQUIRE_SETUP_INFO, &length_param,			       /*paramlen*/1, (u_int8_t*)&setup_info,			       sizeof(setup_info), DEFAULT_CMD_TIMEOUT);		if (error != 0) {			printf("%s: bt_fetch_adapter_info - Failed "			       "Get Setup Info\n", bt_name(bt));			return (error);		}		if (setup_info.initiate_sync != 0) {			bt->sync_permitted = ALL_TARGETS;			if (bt->model[0] == '7') {				if (esetup_info.sync_neg10MB != 0)					bt->fast_permitted = ALL_TARGETS;				if (strcmp(bt->model, "757") == 0)					bt->wide_permitted = ALL_TARGETS;			}		}		bt->disc_permitted = ALL_TARGETS;	}	/* We need as many mailboxes as we can have ccbs */	bt->num_boxes = bt->max_ccbs;	/* Determine our SCSI ID */		error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,		       (u_int8_t*)&config_data, sizeof(config_data),		       DEFAULT_CMD_TIMEOUT);	if (error != 0) {		printf("%s: bt_fetch_adapter_info - Failed Get Config\n",		       bt_name(bt));		return (error);	}	bt->scsi_id = config_data.scsi_id;	return (0);}/* * Start the board, ready for normal operation */intbt_init(struct bt_softc* bt){	/* Announce the Adapter */	printf("%s: BT-%s FW Rev. %s ", bt_name(bt),	       bt->model, bt->firmware_ver);	if (bt->ultra_scsi != 0)		printf("Ultra ");	if (bt->wide_bus != 0)		printf("Wide ");	else		printf("Narrow ");	if (bt->diff_bus != 0)		printf("Diff ");	printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", bt->scsi_id,	       bt->max_ccbs);	/*	 * 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(bt->parent_dmat, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       /*maxsize*/MAXBSIZE, /*nsegments*/BT_NSEG,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/BUS_DMA_ALLOCNOW,			       &bt->buffer_dmat) != 0) {		goto error_exit;	}	bt->init_level++;	/* DMA tag for our mailboxes */	if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       bt->num_boxes * (sizeof(bt_mbox_in_t)					      + sizeof(bt_mbox_out_t)),			       /*nsegments*/1,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/0, &bt->mailbox_dmat) != 0) {		goto error_exit;        }	bt->init_level++;	/* Allocation for our mailboxes */	if (bus_dmamem_alloc(bt->mailbox_dmat, (void **)&bt->out_boxes,			     BUS_DMA_NOWAIT, &bt->mailbox_dmamap) != 0) {		goto error_exit;	}	bt->init_level++;	/* And permanently map them */	bus_dmamap_load(bt->mailbox_dmat, bt->mailbox_dmamap,       			bt->out_boxes,			bt->num_boxes * (sizeof(bt_mbox_in_t)				       + sizeof(bt_mbox_out_t)),			btmapmboxes, bt, /*flags*/0);	bt->init_level++;	bt->in_boxes = (bt_mbox_in_t *)&bt->out_boxes[bt->num_boxes];	btinitmboxes(bt);	/* DMA tag for our ccb structures */	if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       bt->max_ccbs * sizeof(struct bt_ccb),			       /*nsegments*/1,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/0, &bt->ccb_dmat) != 0) {		goto error_exit;        }	bt->init_level++;	/* Allocation for our ccbs */	if (bus_dmamem_alloc(bt->ccb_dmat, (void **)&bt->bt_ccb_array,			     BUS_DMA_NOWAIT, &bt->ccb_dmamap) != 0) {		goto error_exit;	}	bt->init_level++;	/* And permanently map them */	bus_dmamap_load(bt->ccb_dmat, bt->ccb_dmamap,       			bt->bt_ccb_array,			bt->max_ccbs * sizeof(struct bt_ccb),			btmapccbs, bt, /*flags*/0);	bt->init_level++;	/* DMA tag for our S/G structures.  We allocate in page sized chunks */	if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, /*boundary*/0,			       /*lowaddr*/BUS_SPACE_MAXADDR,			       /*highaddr*/BUS_SPACE_MAXADDR,			       /*filter*/NULL, /*filterarg*/NULL,			       PAGE_SIZE, /*nsegments*/1,			       /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,			       /*flags*/0, &bt->sg_dmat) != 0) {		goto error_exit;        }	bt->init_level++;	/* Perform initial CCB allocation */	bzero(bt->bt_ccb_array, bt->max_ccbs * sizeof(struct bt_ccb));	btallocccbs(bt);	if (bt->num_ccbs == 0) {		printf("%s: bt_init - Unable to allocate initial ccbs\n",		       bt_name(bt));		goto error_exit;	}	/*	 * Note that we are going and return (to probe)	 */	return 0;error_exit:	return (ENXIO);}intbt_attach(struct bt_softc *bt){	int tagged_dev_openings;	struct cam_devq *devq;	/*	 * We reserve 1 ccb for error recovery, so don't	 * tell the XPT about it.	 */	if (bt->tag_capable != 0)		tagged_dev_openings = bt->max_ccbs - 1;	else		tagged_dev_openings = 0;	/*	 * Create the device queue for our SIM.	 */	devq = cam_simq_alloc(bt->max_ccbs - 1);	if (devq == NULL)		return (ENOMEM);	/*	 * Construct our SIM entry	 */	bt->sim = cam_sim_alloc(btaction, btpoll, "bt", bt, bt->unit,				2, tagged_dev_openings, devq);	if (bt->sim == NULL) {		cam_simq_free(devq);		return (ENOMEM);	}		if (xpt_bus_register(bt->sim, 0) != CAM_SUCCESS) {		cam_sim_free(bt->sim, /*free_devq*/TRUE);		return (ENXIO);	}		if (xpt_create_path(&bt->path, /*periph*/NULL,			    cam_sim_path(bt->sim), CAM_TARGET_WILDCARD,			    CAM_LUN_WILDCARD) != CAM_REQ_CMP) {		xpt_bus_deregister(cam_sim_path(bt->sim));		cam_sim_free(bt->sim, /*free_devq*/TRUE);		return (ENXIO);	}			return (0);}char *bt_name(struct bt_softc *bt){	static char name[10];	snprintf(name, sizeof(name), "bt%d", bt->unit);	return (name);}intbt_check_probed_iop(u_int ioport){	u_int i;	for (i = 0; i < BT_NUM_ISAPORTS; i++) {		if (bt_isa_ports[i].addr == ioport) {			if (bt_isa_ports[i].probed != 0)				return (1);			else {				return (0);			}		}	}	return (1);}voidbt_mark_probed_bio(isa_compat_io_t port){	if (port < BIO_DISABLED)		bt_mark_probed_iop(bt_board_ports[port]);}voidbt_mark_probed_iop(u_int ioport){	u_int i;	for (i = 0; i < BT_NUM_ISAPORTS; i++) {		if (ioport == bt_isa_ports[i].addr) {			bt_isa_ports[i].probed = 1;			break;		}	}}voidbt_find_probe_range(int ioport, int *port_index, int *max_port_index){	if (ioport > 0) {		int i;		for (i = 0;i < BT_NUM_ISAPORTS; i++)			if (ioport <= bt_isa_ports[i].addr)				break;		if ((i >= BT_NUM_ISAPORTS)		 || (ioport != bt_isa_ports[i].addr)) {			printf("bt_isa_probe: Invalid baseport of 0x%x specified.bt_isa_probe: Nearest valid baseport is 0x%x.bt_isa_probe: Failing probe.\n",			       ioport,			       (i < BT_NUM_ISAPORTS)				    ? bt_isa_ports[i].addr				    : bt_isa_ports[BT_NUM_ISAPORTS - 1].addr);			*port_index = *max_port_index = -1;			return;		}		*port_index = *max_port_index = bt_isa_ports[i].bio;	} else {		*port_index = 0;		*max_port_index = BT_NUM_ISAPORTS - 1;	}}intbt_iop_from_bio(isa_compat_io_t bio_index){	if (bio_index >= 0 && bio_index < BT_NUM_ISAPORTS)		return (bt_board_ports[bio_index]);	return (-1);}static voidbtallocccbs(struct bt_softc *bt){	struct bt_ccb *next_ccb;	struct sg_map_node *sg_map;	bus_addr_t physaddr;	bt_sg_t *segs;	int newcount;	int i;	next_ccb = &bt->bt_ccb_array[bt->num_ccbs];	sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);	if (sg_map == NULL)		return;	/* Allocate S/G space for the next batch of CCBS */	if (bus_dmamem_alloc(bt->sg_dmat, (void **)&sg_map->sg_vaddr,			     BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) {		free(sg_map, M_DEVBUF);		return;	}	SLIST_INSERT_HEAD(&bt->sg_maps, sg_map, links);	bus_dmamap_load(bt->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr,			PAGE_SIZE, btmapsgs, bt, /*flags*/0);		segs = sg_map->sg_vaddr;	physaddr = sg_map->sg_physaddr;	newcount = (PAGE_SIZE / (BT_NSEG * sizeof(bt_sg_t)));	for (i = 0; bt->num_ccbs < bt->max_ccbs && i < newcount; i++) {		int error;		next_ccb->sg_list = segs;		next_ccb->sg_list_phys = physaddr;		next_ccb->flags = BCCB_FREE;		error = bus_dmamap_create(bt->buffer_dmat, /*flags*/0,					  &next_ccb->dmamap);		if (error != 0)			break;		SLIST_INSERT_HEAD(&bt->free_bt_ccbs, next_ccb, links);		segs += BT_NSEG;		physaddr += (BT_NSEG * sizeof(bt_sg_t));		next_ccb++;		bt->num_ccbs++;	}	/* Reserve a CCB for error recovery */	if (bt->recovery_bccb == NULL) {		bt->recovery_bccb = SLIST_FIRST(&bt->free_bt_ccbs);		SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);	}}static __inline voidbtfreeccb(struct bt_softc *bt, struct bt_ccb *bccb){	int s;	s = splcam();	if ((bccb->flags & BCCB_ACTIVE) != 0)		LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le);	if (bt->resource_shortage != 0	 && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {		bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ;		bt->resource_shortage = FALSE;	}	bccb->flags = BCCB_FREE;	SLIST_INSERT_HEAD(&bt->free_bt_ccbs, bccb, links);	bt->active_ccbs--;	splx(s);}static __inline struct bt_ccb*btgetccb(struct bt_softc *bt){	struct	bt_ccb* bccb;	int	s;	s = splcam();	if ((bccb = SLIST_FIRST(&bt->free_bt_ccbs)) != NULL) {		SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);		bt->active_ccbs++;	} else if (bt->num_ccbs < bt->max_ccbs) {		btallocccbs(bt);		bccb = SLIST_FIRST(&bt->free_bt_ccbs);		if (bccb == NULL)			printf("%s: Can't malloc BCCB\n", bt_name(bt));		else {			SLIST_REMOVE_HEAD(&bt->free_bt_ccbs, links);			bt->active_ccbs++;		}	}	splx(s);	return (bccb);}static voidbtaction(struct cam_sim *sim, union ccb *ccb){	struct	bt_softc *bt;	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("btaction\n"));		bt = (struct bt_softc *)cam_sim_softc(sim);		switch (ccb->ccb_h.func_code) {	/* Common cases first */	case XPT_SCSI_IO:	/* Execute the requested I/O operation */	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */	{		struct	bt_ccb	*bccb;		struct	bt_hccb *hccb;		/*		 * get a bccb to use.		 */		if ((bccb = btgetccb(bt)) == NULL) {			int s;			s = splcam();			bt->resource_shortage = TRUE;			splx(s);			xpt_freeze_simq(bt->sim, /*count*/1);			ccb->ccb_h.status = CAM_REQUEUE_REQ;			xpt_done(ccb);			return;		}				hccb = &bccb->hccb;		/*		 * So we can find the BCCB when an abort is requested		 */		bccb->ccb = ccb;		ccb->ccb_h.ccb_bccb_ptr = bccb;		ccb->ccb_h.ccb_bt_ptr = bt;		/*		 * Put all the arguments for the xfer in the bccb		 */		hccb->target_id = ccb->ccb_h.target_id;		hccb->target_lun = ccb->ccb_h.target_lun;		hccb->btstat = 0;		hccb->sdstat = 0;		if (ccb->ccb_h.func_code == XPT_SCSI_IO) {			struct ccb_scsiio *csio;			struct ccb_hdr *ccbh;			csio = &ccb->csio;			ccbh = &csio->ccb_h;			hccb->opcode = INITIATOR_CCB_WRESID;			hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) ? 1 : 0;			hccb->dataout =(ccb->ccb_h.flags & CAM_DIR_OUT) ? 1 : 0;			hccb->cmd_len = csio->cdb_len;			if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {				ccb->ccb_h.status = CAM_REQ_INVALID;				btfreeccb(bt, bccb);				xpt_done(ccb);				return;			}			hccb->sense_len = csio->sense_len;			if ((ccbh->flags & CAM_TAG_ACTION_VALID) != 0			 && ccb->csio.tag_action != CAM_TAG_ACTION_NONE) {				hccb->tag_enable = TRUE;				hccb->tag_type = (ccb->csio.tag_action & 0x3);			} else {				hccb->tag_enable = FALSE;				hccb->tag_type = 0;			}			if ((ccbh->flags & CAM_CDB_POINTER) != 0) {				if ((ccbh->flags & CAM_CDB_PHYS) == 0) {					bcopy(csio->cdb_io.cdb_ptr,					      hccb->scsi_cdb, hccb->cmd_len);				} else {					/* I guess I could map it in... */					ccbh->status = CAM_REQ_INVALID;					btfreeccb(bt, bccb);					xpt_done(ccb);					return;				}			} else {				bcopy(csio->cdb_io.cdb_bytes,				      hccb->scsi_cdb, hccb->cmd_len);			}			/* If need be, bounce our sense buffer */			if (bt->sense_buffers != NULL) {				hccb->sense_addr = btsensepaddr(bt, bccb);			} else {				hccb->sense_addr = vtophys(&csio->sense_data);			}			/*			 * If we have any data to send with this command,			 * map it into bus space.			 */		        /* Only use S/G if there is a transfer */			if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {				if ((ccbh->flags & CAM_SCATTER_VALID) == 0) {					/*					 * We've been given a pointer					 * to a single buffer.					 */

⌨️ 快捷键说明

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