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

📄 aic7xxx_osm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	return (bp);}/* * Queue an SCB to the controller. */static intahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *)){	struct	 ahc_softc *ahc;	struct	 ahc_linux_device *dev = scsi_transport_device_data(cmd->device);	int rtn = SCSI_MLQUEUE_HOST_BUSY;	unsigned long flags;	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;	ahc_lock(ahc, &flags);	if (ahc->platform_data->qfrozen == 0) {		cmd->scsi_done = scsi_done;		cmd->result = CAM_REQ_INPROG << 16;		rtn = ahc_linux_run_command(ahc, dev, cmd);	}	ahc_unlock(ahc, &flags);	return rtn;}static inline struct scsi_target **ahc_linux_target_in_softc(struct scsi_target *starget){	struct	ahc_softc *ahc =		*((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);	unsigned int target_offset;	target_offset = starget->id;	if (starget->channel != 0)		target_offset += 8;	return &ahc->platform_data->starget[target_offset];}static intahc_linux_target_alloc(struct scsi_target *starget){	struct	ahc_softc *ahc =		*((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);	struct seeprom_config *sc = ahc->seep_config;	unsigned long flags;	struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);	struct ahc_linux_target *targ = scsi_transport_target_data(starget);	unsigned short scsirate;	struct ahc_devinfo devinfo;	struct ahc_initiator_tinfo *tinfo;	struct ahc_tmode_tstate *tstate;	char channel = starget->channel + 'A';	unsigned int our_id = ahc->our_id;	unsigned int target_offset;	target_offset = starget->id;	if (starget->channel != 0)		target_offset += 8;	  	if (starget->channel)		our_id = ahc->our_id_b;	ahc_lock(ahc, &flags);	BUG_ON(*ahc_targp != NULL);	*ahc_targp = starget;	memset(targ, 0, sizeof(*targ));	if (sc) {		int maxsync = AHC_SYNCRATE_DT;		int ultra = 0;		int flags = sc->device_flags[target_offset];		if (ahc->flags & AHC_NEWEEPROM_FMT) {		    if (flags & CFSYNCHISULTRA)			ultra = 1;		} else if (flags & CFULTRAEN)			ultra = 1;		/* AIC nutcase; 10MHz appears as ultra = 1, CFXFER = 0x04		 * change it to ultra=0, CFXFER = 0 */		if(ultra && (flags & CFXFER) == 0x04) {			ultra = 0;			flags &= ~CFXFER;		}	    		if ((ahc->features & AHC_ULTRA2) != 0) {			scsirate = (flags & CFXFER) | (ultra ? 0x8 : 0);		} else {			scsirate = (flags & CFXFER) << 4;			maxsync = ultra ? AHC_SYNCRATE_ULTRA : 				AHC_SYNCRATE_FAST;		}		spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;		if (!(flags & CFSYNCH))			spi_max_offset(starget) = 0;		spi_min_period(starget) = 			ahc_find_period(ahc, scsirate, maxsync);		tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,					    starget->id, &tstate);	}	ahc_compile_devinfo(&devinfo, our_id, starget->id,			    CAM_LUN_WILDCARD, channel,			    ROLE_INITIATOR);	ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,			 AHC_TRANS_GOAL, /*paused*/FALSE);	ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,		      AHC_TRANS_GOAL, /*paused*/FALSE);	ahc_unlock(ahc, &flags);	return 0;}static voidahc_linux_target_destroy(struct scsi_target *starget){	struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);	*ahc_targp = NULL;}static intahc_linux_slave_alloc(struct scsi_device *sdev){	struct	ahc_softc *ahc =		*((struct ahc_softc **)sdev->host->hostdata);	struct scsi_target *starget = sdev->sdev_target;	struct ahc_linux_target *targ = scsi_transport_target_data(starget);	struct ahc_linux_device *dev;	if (bootverbose)		printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id);	BUG_ON(targ->sdev[sdev->lun] != NULL);	dev = scsi_transport_device_data(sdev);	memset(dev, 0, sizeof(*dev));	/*	 * We start out life using untagged	 * transactions of which we allow one.	 */	dev->openings = 1;	/*	 * Set maxtags to 0.  This will be changed if we	 * later determine that we are dealing with	 * a tagged queuing capable device.	 */	dev->maxtags = 0;		targ->sdev[sdev->lun] = sdev;	spi_period(starget) = 0;	return 0;}static intahc_linux_slave_configure(struct scsi_device *sdev){	struct	ahc_softc *ahc;	ahc = *((struct ahc_softc **)sdev->host->hostdata);	if (bootverbose)		sdev_printk(KERN_INFO, sdev, "Slave Configure\n");	ahc_linux_device_queue_depth(sdev);	/* Initial Domain Validation */	if (!spi_initial_dv(sdev->sdev_target))		spi_dv_device(sdev);	return 0;}static voidahc_linux_slave_destroy(struct scsi_device *sdev){	struct	ahc_softc *ahc;	struct	ahc_linux_device *dev = scsi_transport_device_data(sdev);	struct	ahc_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);	ahc = *((struct ahc_softc **)sdev->host->hostdata);	if (bootverbose)		printf("%s: Slave Destroy %d\n", ahc_name(ahc), sdev->id);	BUG_ON(dev->active);	targ->sdev[sdev->lun] = NULL;}#if defined(__i386__)/* * Return the disk geometry for the given SCSI device. */static intahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,		    sector_t capacity, int geom[]){	uint8_t *bh;	int	 heads;	int	 sectors;	int	 cylinders;	int	 ret;	int	 extended;	struct	 ahc_softc *ahc;	u_int	 channel;	ahc = *((struct ahc_softc **)sdev->host->hostdata);	channel = sdev_channel(sdev);	bh = scsi_bios_ptable(bdev);	if (bh) {		ret = scsi_partsize(bh, capacity,				    &geom[2], &geom[0], &geom[1]);		kfree(bh);		if (ret != -1)			return (ret);	}	heads = 64;	sectors = 32;	cylinders = aic_sector_div(capacity, heads, sectors);	if (aic7xxx_extended != 0)		extended = 1;	else if (channel == 0)		extended = (ahc->flags & AHC_EXTENDED_TRANS_A) != 0;	else		extended = (ahc->flags & AHC_EXTENDED_TRANS_B) != 0;	if (extended && cylinders >= 1024) {		heads = 255;		sectors = 63;		cylinders = aic_sector_div(capacity, heads, sectors);	}	geom[0] = heads;	geom[1] = sectors;	geom[2] = cylinders;	return (0);}#endif/* * Abort the current SCSI command(s). */static intahc_linux_abort(struct scsi_cmnd *cmd){	int error;	error = ahc_linux_queue_recovery_cmd(cmd, SCB_ABORT);	if (error != 0)		printf("aic7xxx_abort returns 0x%x\n", error);	return (error);}/* * Attempt to send a target reset message to the device that timed out. */static intahc_linux_dev_reset(struct scsi_cmnd *cmd){	int error;	error = ahc_linux_queue_recovery_cmd(cmd, SCB_DEVICE_RESET);	if (error != 0)		printf("aic7xxx_dev_reset returns 0x%x\n", error);	return (error);}/* * Reset the SCSI bus. */static intahc_linux_bus_reset(struct scsi_cmnd *cmd){	struct ahc_softc *ahc;	int    found;	unsigned long flags;	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;	ahc_lock(ahc, &flags);	found = ahc_reset_channel(ahc, scmd_channel(cmd) + 'A',				  /*initiate reset*/TRUE);	ahc_unlock(ahc, &flags);	if (bootverbose)		printf("%s: SCSI bus reset delivered. "		       "%d SCBs aborted.\n", ahc_name(ahc), found);	return SUCCESS;}struct scsi_host_template aic7xxx_driver_template = {	.module			= THIS_MODULE,	.name			= "aic7xxx",	.proc_name		= "aic7xxx",	.proc_info		= ahc_linux_proc_info,	.info			= ahc_linux_info,	.queuecommand		= ahc_linux_queue,	.eh_abort_handler	= ahc_linux_abort,	.eh_device_reset_handler = ahc_linux_dev_reset,	.eh_bus_reset_handler	= ahc_linux_bus_reset,#if defined(__i386__)	.bios_param		= ahc_linux_biosparam,#endif	.can_queue		= AHC_MAX_QUEUE,	.this_id		= -1,	.cmd_per_lun		= 2,	.use_clustering		= ENABLE_CLUSTERING,	.slave_alloc		= ahc_linux_slave_alloc,	.slave_configure	= ahc_linux_slave_configure,	.slave_destroy		= ahc_linux_slave_destroy,	.target_alloc		= ahc_linux_target_alloc,	.target_destroy		= ahc_linux_target_destroy,};/**************************** Tasklet Handler *********************************//******************************** Macros **************************************/#define BUILD_SCSIID(ahc, cmd)						    \	((((cmd)->device->id << TID_SHIFT) & TID)			    \	| (((cmd)->device->channel == 0) ? (ahc)->our_id : (ahc)->our_id_b) \	| (((cmd)->device->channel == 0) ? 0 : TWIN_CHNLB))/******************************** Bus DMA *************************************/intahc_dma_tag_create(struct ahc_softc *ahc, bus_dma_tag_t parent,		   bus_size_t alignment, bus_size_t boundary,		   dma_addr_t lowaddr, dma_addr_t highaddr,		   bus_dma_filter_t *filter, void *filterarg,		   bus_size_t maxsize, int nsegments,		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag){	bus_dma_tag_t dmat;	dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);	if (dmat == NULL)		return (ENOMEM);	/*	 * Linux is very simplistic about DMA memory.  For now don't	 * maintain all specification information.  Once Linux supplies	 * better facilities for doing these operations, or the	 * needs of this particular driver change, we might need to do	 * more here.	 */	dmat->alignment = alignment;	dmat->boundary = boundary;	dmat->maxsize = maxsize;	*ret_tag = dmat;	return (0);}voidahc_dma_tag_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat){	free(dmat, M_DEVBUF);}intahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr,		 int flags, bus_dmamap_t *mapp){	*vaddr = pci_alloc_consistent(ahc->dev_softc,				      dmat->maxsize, mapp);	if (*vaddr == NULL)		return ENOMEM;	return 0;}voidahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat,		void* vaddr, bus_dmamap_t map){	pci_free_consistent(ahc->dev_softc, dmat->maxsize,			    vaddr, map);}intahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,		void *cb_arg, int flags){	/*	 * Assume for now that this will only be used during	 * initialization and not for per-transaction buffer mapping.	 */	bus_dma_segment_t stack_sg;	stack_sg.ds_addr = map;	stack_sg.ds_len = dmat->maxsize;	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);	return (0);}voidahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map){}intahc_dmamap_unload(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map){	/* Nothing to do */	return (0);}static voidahc_linux_setup_tag_info_global(char *p){	int tags, i, j;	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;	printf("Setting Global Tags= %d\n", tags);	for (i = 0; i < NUM_ELEMENTS(aic7xxx_tag_info); i++) {		for (j = 0; j < AHC_NUM_TARGETS; j++) {			aic7xxx_tag_info[i].tag_commands[j] = tags;		}	}}static voidahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value){	if ((instance >= 0) && (targ >= 0)	 && (instance < NUM_ELEMENTS(aic7xxx_tag_info))	 && (targ < AHC_NUM_TARGETS)) {		aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff;		if (bootverbose)			printf("tag_info[%d:%d] = %d\n", instance, targ, value);	}}static char *ahc_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,		       void (*callback)(u_long, int, int, int32_t),		       u_long callback_arg){	char	*tok_end;	char	*tok_end2;	int      i;	int      instance;	int	 targ;	int	 done;	char	 tok_list[] = {'.', ',', '{', '}', '\0'};	/* All options use a ':' name/arg separator */	if (*opt_arg != ':')		return (opt_arg);	opt_arg++;	instance = -1;	targ = -1;	done = FALSE;	/*	 * Restore separator that may be in	 * the middle of our option argument.	 */	tok_end = strchr(opt_arg, '\0');

⌨️ 快捷键说明

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