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

📄 advansys.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Generic driver for the Advanced Systems Inc. SCSI controllers * Product specific probe and attach routines can be found in: *  * i386/isa/adv_isa.c	ABP5140, ABP542, ABP5150, ABP842, ABP852 * i386/eisa/adv_eisa.c	ABP742, ABP752 * pci/adv_pci.c	ABP920, ABP930, ABP930U, ABP930UA, ABP940, ABP940U, *			ABP940UA, ABP950, ABP960, ABP960U, ABP960UA, *			ABP970, ABP970U * * Copyright (c) 1996-1998 Justin Gibbs. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions, and the following disclaimer, *    without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *      $Id: advansys.c,v 1.7.2.3 1999/05/07 00:43:19 ken Exp $ *//* * Ported from: * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters *      * Copyright (c) 1995-1997 Advanced System Products, Inc. * All Rights Reserved. *    * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that redistributions of source * code retain the above copyright notice and this comment without * modification. */ #include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <sys/buf.h>#include <sys/kernel.h>#include <machine/bus_pio.h>#include <machine/bus.h>#include <machine/clock.h>#include <cam/cam.h>#include <cam/cam_ccb.h>#include <cam/cam_sim.h>#include <cam/cam_xpt_sim.h>#include <cam/cam_xpt_periph.h>#include <cam/cam_debug.h>#include <cam/scsi/scsi_all.h>#include <cam/scsi/scsi_message.h>#include <vm/vm.h>#include <vm/vm_param.h>#include <vm/pmap.h>#include <dev/advansys/advansys.h>u_long adv_unit;static void	adv_action(struct cam_sim *sim, union ccb *ccb);static void	adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,				int nsegments, int error);static void	adv_poll(struct cam_sim *sim);static void	adv_run_doneq(struct adv_softc *adv);static struct adv_ccb_info *		adv_alloc_ccb_info(struct adv_softc *adv);static void	adv_destroy_ccb_info(struct adv_softc *adv,				     struct adv_ccb_info *cinfo); static __inline struct adv_ccb_info *		adv_get_ccb_info(struct adv_softc *adv);static __inline void adv_free_ccb_info(struct adv_softc *adv,				       struct adv_ccb_info *cinfo);struct adv_softc *advsoftcs[NADV];   /* XXX Config should handle this */static __inline struct adv_ccb_info *adv_get_ccb_info(struct adv_softc *adv){	struct adv_ccb_info *cinfo;	int opri;	opri = splcam();	if ((cinfo = SLIST_FIRST(&adv->free_ccb_infos)) != NULL) {		SLIST_REMOVE_HEAD(&adv->free_ccb_infos, links);	} else {		cinfo = adv_alloc_ccb_info(adv);	}	splx(opri);	return (cinfo);}static __inline voidadv_free_ccb_info(struct adv_softc *adv, struct adv_ccb_info *cinfo){       	int opri;	opri = splcam();	cinfo->state = ACCB_FREE;	SLIST_INSERT_HEAD(&adv->free_ccb_infos, cinfo, links);	splx(opri);}void     adv_map(void *arg, bus_dma_segment_t *segs, int nseg, int error){	bus_addr_t* physaddr; 	physaddr = (bus_addr_t*)arg;	*physaddr = segs->ds_addr;}char *adv_name(struct adv_softc *adv){	static char name[10];	snprintf(name, sizeof(name), "adv%d", adv->unit);	return (name);}static voidadv_action(struct cam_sim *sim, union ccb *ccb){	struct adv_softc *adv;	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("adv_action\n"));	adv = (struct adv_softc *)cam_sim_softc(sim);	switch (ccb->ccb_h.func_code) {	/* Common cases first */	case XPT_SCSI_IO:	/* Execute the requested I/O operation */	{		struct	ccb_hdr *ccb_h;		struct	ccb_scsiio *csio;		struct	adv_ccb_info *cinfo;		ccb_h = &ccb->ccb_h;		csio = &ccb->csio;		cinfo = adv_get_ccb_info(adv);		if (cinfo == NULL)			panic("XXX Handle CCB info error!!!");		ccb_h->ccb_cinfo_ptr = cinfo;		/* Only use S/G if there is a transfer */		if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {			if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {				/*				 * We've been given a pointer				 * to a single buffer				 */				if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {					int s;					int error;					s = splsoftvm();					error =					    bus_dmamap_load(adv->buffer_dmat,							    cinfo->dmamap,							    csio->data_ptr,							    csio->dxfer_len,							    adv_execute_ccb,							    csio, /*flags*/0);					if (error == EINPROGRESS) {						/*						 * So as to maintain ordering,						 * freeze the controller queue						 * until our mapping is						 * returned.						 */						xpt_freeze_simq(adv->sim,								/*count*/1);						cinfo->state |=						    ACCB_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;					adv_execute_ccb(csio, &seg, 1, 0);				}			} else {				struct bus_dma_segment *segs;				if ((ccb_h->flags & CAM_DATA_PHYS) != 0)					panic("adv_setup_data - Physical "					      "segment pointers unsupported");				if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0)					panic("adv_setup_data - Virtual "					      "segment addresses unsupported");				/* Just use the segments provided */				segs = (struct bus_dma_segment *)csio->data_ptr;				adv_execute_ccb(ccb, segs, csio->sglist_cnt, 0);			}		} else {			adv_execute_ccb(ccb, NULL, 0, 0);		}		break;	}	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */	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_EN_LUN:		/* Enable LUN as a target */	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;		target_bit_vector targ_mask;		struct adv_transinfo *tconf;		u_int	 update_type;		int	 s;		cts = &ccb->cts;		targ_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);		update_type = 0;		/*		 * The user must specify which type of settings he wishes		 * to change.		 */		if (((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)		 && ((cts->flags & CCB_TRANS_USER_SETTINGS) == 0)) {			tconf = &adv->tinfo[cts->ccb_h.target_id].current;			update_type |= ADV_TRANS_GOAL;		} else if (((cts->flags & CCB_TRANS_USER_SETTINGS) != 0)			&& ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0)) {			tconf = &adv->tinfo[cts->ccb_h.target_id].user;			update_type |= ADV_TRANS_USER;		} else {			ccb->ccb_h.status = CAM_REQ_INVALID;			break;		}				s = splcam();		if ((update_type & ADV_TRANS_GOAL) != 0) {			if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)					adv->disc_enable |= targ_mask;				else					adv->disc_enable &= ~targ_mask;				adv_write_lram_8(adv, ADVV_DISC_ENABLE_B,						 adv->disc_enable); 			}			if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)					adv->cmd_qng_enabled |= targ_mask;				else					adv->cmd_qng_enabled &= ~targ_mask;			}		}		if ((update_type & ADV_TRANS_USER) != 0) {			if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {				if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)					adv->user_disc_enable |= targ_mask;				else					adv->user_disc_enable &= ~targ_mask;			}			if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {				if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)					adv->user_cmd_qng_enabled |= targ_mask;				else					adv->user_cmd_qng_enabled &= ~targ_mask;			}		}				/*		 * If the user specifies either the sync rate, or offset,		 * but not both, the unspecified parameter defaults to its		 * current value in transfer negotiations.		 */		if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)		 || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {			/*			 * If the user provided a sync rate but no offset,			 * use the current offset.			 */			if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0)				cts->sync_offset = tconf->offset;			/*			 * If the user provided an offset but no sync rate,			 * use the current sync rate.			 */			if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0)				cts->sync_period = tconf->period;			adv_period_offset_to_sdtr(adv, &cts->sync_period,						  &cts->sync_offset,						  cts->ccb_h.target_id);						adv_set_syncrate(adv, /*struct cam_path */NULL,					 cts->ccb_h.target_id, cts->sync_period,					 cts->sync_offset, update_type);		}		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;		struct adv_transinfo *tconf;		target_bit_vector target_mask;		int s;		cts = &ccb->cts;		target_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);		cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);		s = splcam();		if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) {			tconf = &adv->tinfo[cts->ccb_h.target_id].current;			if ((adv->disc_enable & target_mask) != 0)				cts->flags |= CCB_TRANS_DISC_ENB;			if ((adv->cmd_qng_enabled & target_mask) != 0)				cts->flags |= CCB_TRANS_TAG_ENB;		} else {			tconf = &adv->tinfo[cts->ccb_h.target_id].user;			if ((adv->user_disc_enable & target_mask) != 0)				cts->flags |= CCB_TRANS_DISC_ENB;			if ((adv->user_cmd_qng_enabled & target_mask) != 0)				cts->flags |= CCB_TRANS_TAG_ENB;		}		cts->sync_period = tconf->period;		cts->sync_offset = tconf->offset;		splx(s);		cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT;		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;		ccg = &ccb->ccg;		size_mb = ccg->volume_size			/ ((1024L * 1024L) / ccg->block_size);		extended = (adv->control & ADV_CNTL_BIOS_GT_1GB) != 0;				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 */	{		int s;		s = splcam();		adv_stop_execution(adv);		adv_reset_bus(adv);		adv_start_execution(adv);		splx(s);		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|PI_TAG_ABLE;		cpi->target_sprt = 0;		cpi->hba_misc = 0;		cpi->hba_eng_cnt = 0;		cpi->max_target = 7;		cpi->max_lun = 7;		cpi->initiator_id = adv->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, "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;	}}/*

⌨️ 快捷键说明

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