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

📄 adwcam.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					s = splsoftvm();					error =					    bus_dmamap_load(adw->buffer_dmat,							    acb->dmamap,							    csio->data_ptr,							    csio->dxfer_len,							    adwexecuteacb,							    acb, /*flags*/0);					if (error == EINPROGRESS) {						/*						 * So as to maintain ordering,						 * freeze the controller queue						 * until our mapping is						 * returned.						 */						xpt_freeze_simq(sim, 1);						acb->state |= 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;					adwexecuteacb(acb, &seg, 1, 0);				}			} else {				struct bus_dma_segment *segs;				if ((ccbh->flags & CAM_DATA_PHYS) != 0)					panic("adw_action - Physical "					      "segment pointers "					      "unsupported");				if ((ccbh->flags&CAM_SG_LIST_PHYS)==0)					panic("adw_action - Virtual "					      "segment addresses "					      "unsupported");				/* Just use the segments provided */				segs = (struct bus_dma_segment *)csio->data_ptr;				adwexecuteacb(acb, segs, csio->sglist_cnt,					      (csio->sglist_cnt < ADW_SGSIZE)					      ? 0 : EFBIG);			}		} else {			adwexecuteacb(acb, NULL, 0, 0);		}		break;	}	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */	{		adw_idle_cmd_status_t status;		adw_idle_cmd_send(adw, ADW_IDLE_CMD_DEVICE_RESET,				  ccb->ccb_h.target_id);		status = adw_idle_cmd_wait(adw);		if (status == ADW_IDLE_CMD_SUCCESS) {			ccb->ccb_h.status = CAM_REQ_CMP;			if (bootverbose) {				xpt_print_path(ccb->ccb_h.path);				printf("BDR Delivered\n");			}		} else			ccb->ccb_h.status = CAM_REQ_CMP_ERR;		xpt_done(ccb);		break;	}	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:	{		struct	  ccb_trans_settings *cts;		u_int	  target_mask;		int	  s;		cts = &ccb->cts;		target_mask = 0x01 << ccb->ccb_h.target_id;		s = splcam();		if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) {			if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {				u_int discenb;				discenb =				    adw_lram_read_16(adw, ADW_MC_DISC_ENABLE);				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)					discenb |= target_mask;				else					discenb &= ~target_mask;				adw_lram_write_16(adw, ADW_MC_DISC_ENABLE,						  discenb);			}					if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)					adw->tagenb |= target_mask;				else					adw->tagenb &= ~target_mask;			}				if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) {				u_int wdtrenb_orig;				u_int wdtrenb;				u_int wdtrdone;				wdtrenb_orig =				    adw_lram_read_16(adw, ADW_MC_WDTR_ABLE);				wdtrenb = wdtrenb_orig;				wdtrdone = adw_lram_read_16(adw,							    ADW_MC_WDTR_DONE);				switch (cts->bus_width) {				case MSG_EXT_WDTR_BUS_32_BIT:				case MSG_EXT_WDTR_BUS_16_BIT:					wdtrenb |= target_mask;					break;				case MSG_EXT_WDTR_BUS_8_BIT:				default:					wdtrenb &= ~target_mask;					break;				}				if (wdtrenb != wdtrenb_orig) {					adw_lram_write_16(adw,							  ADW_MC_WDTR_ABLE,							  wdtrenb);					wdtrdone &= ~target_mask;					adw_lram_write_16(adw,							  ADW_MC_WDTR_DONE,							  wdtrdone);				}			}			if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)			 || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {				u_int sdtrenb_orig;				u_int sdtrenb;				u_int ultraenb_orig;				u_int ultraenb;				u_int sdtrdone;				sdtrenb_orig =				    adw_lram_read_16(adw, ADW_MC_SDTR_ABLE);				sdtrenb = sdtrenb_orig;				ultraenb_orig =				    adw_lram_read_16(adw, ADW_MC_ULTRA_ABLE);				ultraenb = ultraenb_orig;				sdtrdone = adw_lram_read_16(adw,							    ADW_MC_SDTR_DONE);				if ((cts->valid				   & CCB_TRANS_SYNC_RATE_VALID) != 0) {					if (cts->sync_period == 0) {						sdtrenb &= ~target_mask;					} else if (cts->sync_period > 12) {						ultraenb &= ~target_mask;						sdtrenb |= target_mask;					} else {						ultraenb |= target_mask;						sdtrenb |= target_mask;					}				}									if ((cts->valid				   & CCB_TRANS_SYNC_OFFSET_VALID) != 0) {					if (cts->sync_offset == 0)						sdtrenb &= ~target_mask;				}				if (sdtrenb != sdtrenb_orig				 || ultraenb != ultraenb_orig) {					adw_lram_write_16(adw, ADW_MC_SDTR_ABLE,							  sdtrenb);					adw_lram_write_16(adw,							  ADW_MC_ULTRA_ABLE,							  ultraenb);					sdtrdone &= ~target_mask;					adw_lram_write_16(adw, ADW_MC_SDTR_DONE,							  sdtrdone);				}			} 		}		splx(s);		ccb->ccb_h.status = CAM_REQ_CMP;		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 ((adw->user_discenb & target_mask) != 0)				cts->flags |= CCB_TRANS_DISC_ENB;			if ((adw->user_tagenb & target_mask) != 0)				cts->flags |= CCB_TRANS_TAG_ENB;			if ((adw->user_wdtr & target_mask) != 0)				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;			else				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;			if ((adw->user_sdtr & target_mask) != 0) {				if ((adw->user_ultra & target_mask) != 0)					cts->sync_period = 12; /* 20MHz */				else					cts->sync_period = 25; /* 10MHz */				cts->sync_offset = 15; /* XXX ??? */			}			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;			ccb->ccb_h.status = CAM_REQ_CMP;		} else {			u_int targ_tinfo;			cts->flags = 0;			if ((adw_lram_read_16(adw, ADW_MC_DISC_ENABLE)			  & target_mask) != 0)				cts->flags |= CCB_TRANS_DISC_ENB;			if ((adw->tagenb & target_mask) != 0)				cts->flags |= CCB_TRANS_TAG_ENB;			targ_tinfo =			    adw_lram_read_16(adw,					     ADW_MC_DEVICE_HSHK_CFG_TABLE					     + (2 * ccb->ccb_h.target_id));			if ((targ_tinfo & ADW_HSHK_CFG_WIDE_XFR) != 0)				cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT;			else				cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;			cts->sync_period =			    ADW_HSHK_CFG_PERIOD_FACTOR(targ_tinfo);			cts->sync_offset = targ_tinfo & ADW_HSHK_CFG_OFFSET;			if (cts->sync_period == 0)				cts->sync_offset = 0;			if (cts->sync_offset == 0)				cts->sync_period = 0;		}		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;		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;		int	  extended;		/*		 * XXX Use Adaptec translation until I find out how to		 *     get this information from the card.		 */		ccg = &ccb->ccg;		size_mb = ccg->volume_size			/ ((1024L * 1024L) / ccg->block_size);		extended = 1;				if (size_mb > 1024 && extended) {			ccg->heads = 255;			ccg->secs_per_track = 63;		} 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 */	{		adw_idle_cmd_status_t status;		adw_idle_cmd_send(adw, ADW_IDLE_CMD_SCSI_RESET, /*param*/0);		status = adw_idle_cmd_wait(adw);		if (status == ADW_IDLE_CMD_SUCCESS) {			ccb->ccb_h.status = CAM_REQ_CMP;			if (bootverbose) {				xpt_print_path(adw->path);				printf("Bus Reset Delivered\n");			}		} else			ccb->ccb_h.status = CAM_REQ_CMP_ERR;		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;		cpi->hba_inquiry = PI_WIDE_16|PI_SDTR_ABLE|PI_TAG_ABLE;		cpi->target_sprt = 0;		cpi->hba_misc = 0;		cpi->hba_eng_cnt = 0;		cpi->max_target = ADW_MAX_TID;		cpi->max_lun = ADW_MAX_LUN;		cpi->initiator_id = adw->initiator_id;		cpi->bus_id = cam_sim_bus(sim);		cpi->base_transfer_speed = 3300;		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);		strncpy(cpi->hba_vid, "AdvanSys", 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 voidadw_poll(struct cam_sim *sim){	adw_intr(cam_sim_softc(sim));}static voidadw_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg){}struct adw_softc *adw_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh){	struct	 adw_softc *adw;	int	 i;   	/*	 * Allocate a storage area for us	 */	adw = malloc(sizeof(struct adw_softc), M_DEVBUF, M_NOWAIT);	if (adw == NULL) {		printf("adw%d: cannot malloc!\n", unit);		return NULL;	}	bzero(adw, sizeof(struct adw_softc));	LIST_INIT(&adw->pending_ccbs);	SLIST_INIT(&adw->sg_maps);	adw->unit = unit;	adw->tag = tag;	adw->bsh = bsh;	i = adw->unit / 10;	adw->name = malloc(sizeof("adw") + i + 1, M_DEVBUF, M_NOWAIT);	if (adw->name == NULL) {		printf("adw%d: cannot malloc name!\n", unit);		free(adw, M_DEVBUF);		return NULL;	}	sprintf(adw->name, "adw%d", adw->unit);	return(adw);}voidadw_free(struct adw_softc *adw){	switch (adw->init_level) {	case 6:	{		struct sg_map_node *sg_map;		while ((sg_map = SLIST_FIRST(&adw->sg_maps)) != NULL) {			SLIST_REMOVE_HEAD(&adw->sg_maps, links);			bus_dmamap_unload(adw->sg_dmat,					  sg_map->sg_dmamap);			bus_dmamem_free(adw->sg_dmat, sg_map->sg_vaddr,					sg_map->sg_dmamap);			free(sg_map, M_DEVBUF);		}		bus_dma_tag_destroy(adw->sg_dmat);	}	case 5:		bus_dmamap_unload(adw->acb_dmat, adw->acb_dmamap);	case 4:		bus_dmamem_free(adw->acb_dmat, adw->acbs,				adw->acb_dmamap);		bus_dmamap_destroy(adw->acb_dmat, adw->acb_dmamap);	case 3:		bus_dma_tag_destroy(adw->acb_dmat);	case 2:		bus_dma_tag_destroy(adw->buffer_dmat);	case 1:		bus_dma_tag_destroy(adw->parent_dmat);	case 0:		break;	}	free(adw->name, M_DEVBUF);	free(adw, M_DEVBUF);}intadw_init(struct adw_softc *adw){	struct	  adw_eeprom eep_config;	u_int16_t checksum;	u_int16_t scsicfg1;	adw_reset_chip(adw);	checksum = adw_eeprom_read(adw, &eep_config);	bcopy(eep_config.serial_number, adw->serial_number,	      sizeof(adw->serial_number));	if (checksum != eep_config.checksum) {		u_int16_t serial_number[3];		printf("%s: EEPROM checksum failed.  Restoring Defaults\n",		       adw_name(adw));	        /*		 * Restore the default EEPROM settings.		 * Assume the 6 byte board serial number that was read		 * from EEPROM is correct even if the EEPROM checksum		 * failed.		 */		bcopy(&adw_default_eeprom, &eep_config, sizeof(eep_config));		bcopy(adw->serial_number, eep_config.serial_number,		      sizeof(serial_number));

⌨️ 快捷键说明

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