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

📄 aic79xx_osm.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		dev->openings =  1 - dev->active;	}}intahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,			int lun, u_int tag, role_t role, uint32_t status){	int targ;	int maxtarg;	int maxlun;	int clun;	int count;	if (tag != SCB_LIST_NULL)		return (0);	targ = 0;	if (target != CAM_TARGET_WILDCARD) {		targ = target;		maxtarg = targ + 1;	} else {		maxtarg = (ahd->features & AHD_WIDE) ? 16 : 8;	}	clun = 0;	if (lun != CAM_LUN_WILDCARD) {		clun = lun;		maxlun = clun + 1;	} else {		maxlun = AHD_NUM_LUNS;	}	count = 0;	for (; targ < maxtarg; targ++) {		for (; clun < maxlun; clun++) {			struct ahd_linux_device *dev;			struct ahd_busyq *busyq;			struct ahd_cmd *acmd;			dev = ahd_linux_get_device(ahd, /*chan*/0, targ,						   clun, /*alloc*/FALSE);			if (dev == NULL)				continue;			busyq = &dev->busyq;			while ((acmd = TAILQ_FIRST(busyq)) != NULL) {				Scsi_Cmnd *cmd;				cmd = &acmd_scsi_cmd(acmd);				TAILQ_REMOVE(busyq, acmd,					     acmd_links.tqe);				count++;				cmd->result = status << 16;				ahd_linux_queue_cmd_complete(ahd, cmd);			}		}	}	return (count);}/* * Sets the queue depth for each SCSI device hanging * off the input host adapter. */static voidahd_linux_select_queue_depth(struct Scsi_Host * host,			     Scsi_Device * scsi_devs){	Scsi_Device *device;	struct	ahd_softc *ahd;	u_long	flags;	int	scbnum;	ahd = *((struct ahd_softc **)host->hostdata);	ahd_lock(ahd, &flags);	scbnum = 0;	for (device = scsi_devs; device != NULL; device = device->next) {		if (device->host == host) {			ahd_linux_device_queue_depth(ahd, device);			scbnum += device->queue_depth;		}	}	ahd_unlock(ahd, &flags);}static u_intahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo){	static int warned_user;	u_int tags;	tags = 0;	if ((ahd->user_discenable & devinfo->target_mask) != 0) {		if (warned_user == 0		 && ahd->unit >= NUM_ELEMENTS(aic79xx_tag_info)) {			printf("aic79xx: WARNING, insufficient "			       "tag_info instances for installed "			       "controllers. Using defaults\n");			printf("aic79xx: Please update the "			       "aic79xx_tag_info array in the "			       "aic79xx.c source file.\n");			tags = AHD_MAX_QUEUE;			warned_user++;		} else {			adapter_tag_info_t *tag_info;			tag_info = &aic79xx_tag_info[ahd->unit];			tags = tag_info->tag_commands[devinfo->target_offset];			if (tags > AHD_MAX_QUEUE)				tags = AHD_MAX_QUEUE;		}	}	return (tags);}/* * Determines the queue depth for a given device. */static voidahd_linux_device_queue_depth(struct ahd_softc *ahd, Scsi_Device * device){	struct	ahd_devinfo devinfo;	u_int	tags;	ahd_compile_devinfo(&devinfo,			    ahd->our_id,			    device->id, device->lun,			    device->channel == 0 ? 'A' : 'B',			    ROLE_INITIATOR);	tags = ahd_linux_user_tagdepth(ahd, &devinfo);	if (tags != 0	 && device->tagged_supported != 0) {		device->queue_depth = tags;		ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED);		printf("scsi%d:%c:%d:%d: Tagged Queuing enabled.  Depth %d\n",	       	       ahd->platform_data->host->host_no, devinfo.channel,		       devinfo.target, devinfo.lun, tags);	} else {		/*		 * We allow the OS to queue 2 untagged transactions to		 * us at any time even though we can only execute them		 * serially on the controller/device.  This should remove		 * some latency.		 */		device->queue_depth = 2;	}}/* * Queue an SCB to the controller. */intahd_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *)){	struct	 ahd_softc *ahd;	struct	 ahd_linux_device *dev;	u_long	 flags;	ahd = *(struct ahd_softc **)cmd->host->hostdata;	/*	 * Save the callback on completion function.	 */	cmd->scsi_done = scsi_done;	ahd_lock(ahd, &flags);	dev = ahd_linux_get_device(ahd, cmd->channel, cmd->target,				   cmd->lun, /*alloc*/TRUE);	if (dev == NULL) {		ahd_unlock(ahd, &flags);		printf("aic79xx_linux_queue: Unable to allocate device!\n");		return (-ENOMEM);	}	if (cmd->cmd_len > MAX_CDB_LEN)		return (-EINVAL);	cmd->result = CAM_REQ_INPROG << 16;	TAILQ_INSERT_TAIL(&dev->busyq, (struct ahd_cmd *)cmd, acmd_links.tqe);	if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) {		TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links);		dev->flags |= AHD_DEV_ON_RUN_LIST;		ahd_linux_run_device_queues(ahd);	}	ahd_unlock(ahd, &flags);	return (0);}static voidahd_linux_run_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev){	struct	 ahd_cmd *acmd;	struct	 scsi_cmnd *cmd;	struct	 scb *scb;	struct	 hardware_scb *hscb;	struct	 ahd_initiator_tinfo *tinfo;	struct	 ahd_tmode_tstate *tstate;	uint16_t mask;	if ((dev->flags & AHD_DEV_ON_RUN_LIST) != 0)		panic("running device on run list");	while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL	    && dev->openings > 0 && dev->qfrozen == 0) {		/*		 * Schedule us to run later.  The only reason we are not		 * running is because the whole controller Q is frozen.		 */		if (ahd->platform_data->qfrozen != 0) {			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,					  dev, links);			dev->flags |= AHD_DEV_ON_RUN_LIST;			return;		}		/*		 * Get an scb to use.		 */		if ((scb = ahd_get_scb(ahd)) == NULL) {			TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq,					 dev, links);			dev->flags |= AHD_DEV_ON_RUN_LIST;			ahd->flags |= AHD_RESOURCE_SHORTAGE;			return;		}		TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);		cmd = &acmd_scsi_cmd(acmd);		scb->io_ctx = cmd;		scb->platform_data->dev = dev;		hscb = scb->hscb;		cmd->host_scribble = (char *)scb;		/*		 * Fill out basics of the HSCB.		 */		hscb->control = 0;		hscb->scsiid = BUILD_SCSIID(ahd, cmd);		hscb->lun = cmd->lun;		mask = SCB_GET_TARGET_MASK(ahd, scb);		tinfo = ahd_fetch_transinfo(ahd, SCB_GET_CHANNEL(ahd, scb),					    SCB_GET_OUR_ID(scb),					    SCB_GET_TARGET(ahd, scb), &tstate);		if ((ahd->user_discenable & mask) != 0)			hscb->control |= DISCENB;		if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)			scb->flags |= SCB_PACKETIZED;		if ((tstate->auto_negotiate & mask) != 0) {			scb->flags |= SCB_AUTO_NEGOTIATE;			scb->hscb->control |= MK_MESSAGE;		}		if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {			if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH			 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {				hscb->control |= MSG_ORDERED_TASK;				dev->commands_since_idle_or_otag = 0;			} else {				hscb->control |= MSG_SIMPLE_TASK;			}		}		hscb->cdb_len = cmd->cmd_len;		memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);		scb->sg_count = 0;		ahd_set_residual(scb, 0);		ahd_set_sense_residual(scb, 0);		if (cmd->use_sg != 0) {			void	*sg;			struct	 scatterlist *cur_seg;			u_int	 nseg;			int	 dir;			cur_seg = (struct scatterlist *)cmd->request_buffer;			dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);			nseg = pci_map_sg(ahd->dev_softc, cur_seg,					  cmd->use_sg, dir);			scb->platform_data->xfer_len = 0;			for (sg = scb->sg_list; nseg > 0; nseg--, cur_seg++) {				bus_addr_t addr;				bus_size_t len;				addr = sg_dma_address(cur_seg);				len = sg_dma_len(cur_seg);				scb->platform_data->xfer_len += len;				sg = ahd_sg_setup(ahd, scb, sg, addr, len,						  /*last*/nseg == 1);			}		} else if (cmd->request_bufflen != 0) {			void *sg;			bus_addr_t addr;			int dir;			sg = scb->sg_list;			dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);			addr = pci_map_single(ahd->dev_softc,					      cmd->request_buffer,					      cmd->request_bufflen, dir);			scb->platform_data->xfer_len = cmd->request_bufflen;			scb->platform_data->buf_busaddr = addr;			sg = ahd_sg_setup(ahd, scb, sg, addr,					  cmd->request_bufflen, /*last*/TRUE);		}		LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);		dev->openings--;		dev->active++;		dev->commands_issued++;		if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)			dev->commands_since_idle_or_otag++;		scb->flags |= SCB_ACTIVE;		ahd_queue_scb(ahd, scb);	}}/* * SCSI controller interrupt handler. */voidahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs){	struct	ahd_softc *ahd;	struct	ahd_cmd *acmd;	u_long	flags;	struct	ahd_linux_device *next_dev;	ahd = (struct ahd_softc *) dev_id;	ahd_lock(ahd, &flags); 	ahd_intr(ahd);	acmd = TAILQ_FIRST(&ahd->platform_data->completeq);	TAILQ_INIT(&ahd->platform_data->completeq);	next_dev = ahd_linux_next_device_to_run(ahd);	ahd_unlock(ahd, &flags);	if (next_dev) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		tasklet_schedule(&ahd->platform_data->runq_tasklet);#else		ahd_runq_tasklet((unsigned long)ahd);#endif	}	if (acmd != NULL)		ahd_linux_run_complete_queue(ahd, acmd);}voidahd_platform_flushwork(struct ahd_softc *ahd){	struct ahd_cmd *acmd;	acmd = TAILQ_FIRST(&ahd->platform_data->completeq);	TAILQ_INIT(&ahd->platform_data->completeq);	if (acmd != NULL)		ahd_linux_run_complete_queue(ahd, acmd);}static struct ahd_linux_target*ahd_linux_alloc_target(struct ahd_softc *ahd, u_int channel, u_int target){	struct ahd_linux_target *targ;	u_int target_offset;	targ = malloc(sizeof(*targ), M_DEVBUG, M_NOWAIT);	if (targ == NULL)		return (NULL);	memset(targ, 0, sizeof(*targ));	targ->channel = channel;	targ->target = target;	targ->ahd = ahd;	target_offset = target;	if (channel != 0)		target_offset += 8;	ahd->platform_data->targets[target_offset] = targ;	return (targ);}static voidahd_linux_free_target(struct ahd_softc *ahd, struct ahd_linux_target *targ){	u_int target_offset;	target_offset = targ->target;	if (targ->channel != 0)		target_offset += 8;	ahd->platform_data->targets[target_offset] = NULL;	free(targ, M_DEVBUF);}static struct ahd_linux_device*ahd_linux_alloc_device(struct ahd_softc *ahd,		 struct ahd_linux_target *targ, u_int lun){	struct ahd_linux_device *dev;	dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);	if (dev == NULL)		return (NULL);	memset(dev, 0, sizeof(*dev));	init_timer(&dev->timer);	TAILQ_INIT(&dev->busyq);	dev->flags = AHD_DEV_UNCONFIGURED;	dev->lun = lun;	dev->target = targ;	/*	 * 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->refcount++;	targ->devices[lun] = dev;	return (dev);}static voidahd_linux_free_device(struct ahd_softc *ahd, struct ahd_linux_device *dev){	struct ahd_linux_target *targ;	del_timer(&dev->timer);	targ = dev->target;	targ->devices[dev->lun] = NULL;	free(dev, M_DEVBUF);	targ->refcount--;	if (targ->refcount == 0)		ahd_linux_free_target(ahd, targ);}/* * Return a string describing the driver. */const char *ahd_linux_info(struct Scsi_Host *host){	static char buffer[512];	char	ahd_info[256];	char   *bp;	struct ahd_softc *ahd;	bp = &buffer[0];	ahd = *(struct ahd_softc **)host->hostdata;	memset(bp, 0, sizeof(buffer));	strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev ");	strcat(bp, AIC79XX_DRIVER_VERSION);	strcat(bp, "\n");	strcat(bp, "        <");	strcat(bp, ahd->description);	strcat(bp, ">\n");	strcat(bp, "        ");	ahd_controller_info(ahd, ahd_info);	strcat(bp, ahd_info);	strcat(bp, "\n");	return (bp);}

⌨️ 快捷键说明

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