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

📄 aic79xx_osm.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		return;	instance = -1;	targ = -1;	done = FALSE;	base = p;	/* Forward us just past the ':' */	tok = base + 1;	tok_end = strchr(tok, '\0');	if (tok_end < end)		*tok_end = ',';	while (!done) {		switch (*tok) {		case '{':			if (instance == -1)				instance = 0;			tok++;			break;		case '}':			if (instance != -1)				instance = -1;			tok++;			break;		case ',':		case '.':			if (instance == -1)				done = TRUE;			else if (instance >= 0)				instance++;			if (instance >= NUM_ELEMENTS(aic79xx_rd_strm_info))				done = TRUE;			tok++;			if (!done) {				base = tok;			}			break;		case '\0':			done = TRUE;			break;		default:			done = TRUE;			tok_end = strchr(tok, '\0');			for (i = 0; tok_list[i]; i++) {				tok_end2 = strchr(tok, tok_list[i]);				if ((tok_end2) && (tok_end2 < tok_end)) {					tok_end = tok_end2;					done = FALSE;				}			}			if ((instance >= 0)			 && (instance < NUM_ELEMENTS(aic79xx_tag_info))) {				aic79xx_rd_strm_info[instance] =				    simple_strtoul(tok, NULL, 0) & 0xffff;			}			tok = tok_end;			break;		}	}	while ((p != base) && (p != NULL))		p = strtok(NULL, ",.");}/* * Handle Linux boot parameters. This routine allows for assigning a value * to a parameter with a ':' between the parameter and the value. * ie. aic79xx=stpwlev:1,extended */intaic79xx_setup(char *s){	int	i, n;	char   *p;	char   *end;	static struct {		const char *name;		uint32_t *flag;	} options[] = {		{ "extended", &aic79xx_extended },		{ "no_reset", &aic79xx_no_reset },		{ "verbose", &aic79xx_verbose },#ifdef AHD_DEBUG		{ "debug", &ahd_debug },#endif		{ "reverse_scan", &aic79xx_reverse_scan },		{ "periodic_otag", &aic79xx_periodic_otag },		{ "pci_parity", &aic79xx_pci_parity },		{ "seltime", &aic79xx_seltime },		{ "tag_info", NULL },		{ "rd_strm", NULL }	};	end = strchr(s, '\0');	for (p = strtok(s, ",."); p; p = strtok(NULL, ",.")) {		for (i = 0; i < NUM_ELEMENTS(options); i++) {			n = strlen(options[i].name);			if (strncmp(options[i].name, p, n) != 0)				continue;			if (strncmp(p, "tag_info", n) == 0) {				ahd_linux_setup_tag_info(p + n, end);			} else if (strncmp(p, "rd_strm", n) == 0) {				ahd_linux_setup_rd_strm_info(p + n, end);			} else if (p[n] == ':') {				*(options[i].flag) =				    simple_strtoul(p + n + 1, NULL, 0);			} else if (!strncmp(p, "verbose", n)) {				*(options[i].flag) = 1;			} else {				*(options[i].flag) = ~(*(options[i].flag));			}			break;		}	}	return 1;}#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)__setup("aic79xx=", aic79xx_setup);#endifint aic79xx_verbose;/* * Try to detect an Adaptec 79XX controller. */intahd_linux_detect(Scsi_Host_Template *template){	struct	ahd_softc *ahd;	int     found;	/*	 * It is a bug that the upper layer takes	 * this lock just prior to calling us.	 */	spin_unlock_irq(&io_request_lock);	/*	 * Sanity checking of Linux SCSI data structures so	 * that some of our hacks^H^H^H^H^Hassumptions aren't	 * violated.	 */	if (offsetof(struct ahd_cmd_internal, end)	  > offsetof(struct scsi_cmnd, host_scribble)) {		printf("ahd_linux_detect: SCSI data structures changed.\n");		printf("ahd_linux_detect: Unable to attach\n");		return (0);	}#ifdef MODULE	/*	 * If we've been passed any parameters, process them now.	 */	if (aic79xx)		aic79xx_setup(aic79xx);	if (dummy_buffer[0] != 'P')		printk(KERN_WARNING"aic79xx: Please read the file /usr/src/linux/drivers/scsi/README.aic79xx\n""aic79xx: to see the proper way to specify options to the aic79xx module\n""aic79xx: Specifically, don't use any commas when passing arguments to\n""aic79xx: insmod or else it might trash certain memory areas.\n");#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)	template->proc_name = "aic79xx";#else	template->proc_dir = &proc_scsi_aic79xx;#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)	/*	 * We can only map 16MB per-SG	 * so create a sector limit of	 * "16MB" in 2K sectors.	 */	template->max_sectors = 8192;#endif	/*	 * Initialize our softc list lock prior to	 * probing for any adapters.	 */	ahd_list_lockinit();#ifdef CONFIG_PCI	ahd_linux_pci_probe(template);#endif	/*	 * Register with the SCSI layer all	 * controllers we've found.	 */	spin_lock_irq(&io_request_lock);	found = 0;	TAILQ_FOREACH(ahd, &ahd_tailq, links) {		if (ahd_linux_register_host(ahd, template) == 0)			found++;	}	aic79xx_detect_complete++;	return (found);}intahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template){	char  buf[80];	struct Scsi_Host *host;	char *new_name;	u_long s;	template->name = ahd->description;	host = scsi_register(template, sizeof(struct ahd_softc *));	if (host == NULL)		return (ENOMEM);	ahd_lock(ahd, &s);	*((struct ahd_softc **)host->hostdata) = ahd;	ahd->platform_data->host = host;	host->can_queue = AHD_MAX_QUEUE;	host->cmd_per_lun = 2;	host->sg_tablesize = AHD_NSEG;	host->select_queue_depths = ahd_linux_select_queue_depth;	host->this_id = ahd->our_id;	host->irq = ahd->platform_data->irq;	host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;	host->max_lun = AHD_NUM_LUNS;	host->max_channel = 0;	ahd_set_unit(ahd, ahd_linux_next_unit());	sprintf(buf, "scsi%d", host->host_no);	new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);	if (new_name != NULL) {		strcpy(new_name, buf);		ahd_set_name(ahd, new_name);	}	host->unique_id = ahd->unit;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)	scsi_set_pci_device(host, ahd->dev_softc);#endif	ahd_linux_initialize_scsi_bus(ahd);	ahd_unlock(ahd, &s);	return (0);}uint64_tahd_linux_get_memsize(){	struct sysinfo si;	si_meminfo(&si);	return (si.totalram << PAGE_SHIFT);}/* * Find the smallest available unit number to use * for a new device.  We don't just use a static * count to handle the "repeated hot-(un)plug" * scenario. */static intahd_linux_next_unit(){	struct ahd_softc *ahd;	int unit;	unit = 0;retry:	TAILQ_FOREACH(ahd, &ahd_tailq, links) {		if (ahd->unit == unit) {			unit++;			goto retry;		}	}	return (unit);}/* * Place the SCSI bus into a known state by either resetting it, * or forcing transfer negotiations on the next command to any * target. */voidahd_linux_initialize_scsi_bus(struct ahd_softc *ahd){	int i;	int numtarg;	i = 0;	numtarg = 0;	if (aic79xx_no_reset != 0)		ahd->flags &= ~AHD_RESET_BUS_A;	if ((ahd->flags & AHD_RESET_BUS_A) != 0)		ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE);	else		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;	for (; i < numtarg; i++) {		struct ahd_devinfo devinfo;		struct ahd_initiator_tinfo *tinfo;		struct ahd_tmode_tstate *tstate;		u_int our_id;		u_int target_id;		char channel;		channel = 'A';		our_id = ahd->our_id;		target_id = i;		tinfo = ahd_fetch_transinfo(ahd, channel, our_id,					    target_id, &tstate);		tinfo->goal = tinfo->user;		/*		 * Don't try negotiations that require PPR messages		 * until we successfully retrieve Inquiry data.		 */		tinfo->goal.ppr_options = 0;		if (tinfo->goal.transport_version > SCSI_REV_2)			tinfo->goal.transport_version = SCSI_REV_2;		ahd_compile_devinfo(&devinfo, our_id, target_id,				   CAM_LUN_WILDCARD, channel, ROLE_INITIATOR);		ahd_update_neg_request(ahd, &devinfo, tstate,				       tinfo, /*force*/FALSE);	}	/* Give the bus some time to recover */	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {		ahd_freeze_simq(ahd);		init_timer(&ahd->platform_data->reset_timer);		ahd->platform_data->reset_timer.data = (u_long)ahd;		ahd->platform_data->reset_timer.expires =		    jiffies + (AIC79XX_RESET_DELAY * HZ)/1000;		ahd->platform_data->reset_timer.function =		    (ahd_linux_callback_t *)ahd_release_simq;		add_timer(&ahd->platform_data->reset_timer);	}}intahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg){	ahd->platform_data =	    malloc(sizeof(struct ahd_platform_data), M_DEVBUF, M_NOWAIT);	if (ahd->platform_data == NULL)		return (ENOMEM);	memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data));	TAILQ_INIT(&ahd->platform_data->completeq);	TAILQ_INIT(&ahd->platform_data->device_runq);	ahd->platform_data->irq = AHD_LINUX_NOIRQ;	ahd->platform_data->hw_dma_mask = 0xFFFFFFFF;	ahd_lockinit(ahd);	ahd_done_lockinit(ahd);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)	init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);#else	ahd->platform_data->eh_sem = MUTEX_LOCKED;#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	tasklet_init(&ahd->platform_data->runq_tasklet, ahd_runq_tasklet,		     (unsigned long)ahd);#endif	ahd->seltime = (aic79xx_seltime & 0x3) << 4;		if (TAILQ_EMPTY(&ahd_tailq))		register_reboot_notifier(&ahd_linux_notifier);	return (0);}voidahd_platform_free(struct ahd_softc *ahd){	if (ahd->platform_data != NULL) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		tasklet_kill(&ahd->platform_data->runq_tasklet);#endif		if (ahd->platform_data->host != NULL)			scsi_unregister(ahd->platform_data->host);		if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)			free_irq(ahd->platform_data->irq, ahd);		if (ahd->tags[0] == BUS_SPACE_PIO		 && ahd->bshs[0].ioport != 0)			release_region(ahd->bshs[0].ioport, 256);		if (ahd->tags[1] == BUS_SPACE_PIO		 && ahd->bshs[1].ioport != 0)			release_region(ahd->bshs[1].ioport, 256);		if (ahd->tags[0] == BUS_SPACE_MEMIO		 && ahd->bshs[0].maddr != NULL) {			u_long base_addr;			base_addr = (u_long)ahd->bshs[0].maddr;			base_addr &= PAGE_MASK;			iounmap((void *)base_addr);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			release_mem_region(ahd->platform_data->mem_busaddr,					   0x1000);#endif		}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		/* XXX Need an instance detach in the PCI code */		if (ahd->dev_softc != NULL)			ahd->dev_softc->driver = NULL;#endif		free(ahd->platform_data, M_DEVBUF);	}	if (TAILQ_EMPTY(&ahd_tailq)) {		unregister_reboot_notifier(&ahd_linux_notifier);#ifdef CONFIG_PCI#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		pci_unregister_driver(&aic79xx_pci_driver);#endif#endif	}}voidahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb){	ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),				SCB_GET_CHANNEL(ahd, scb),				SCB_GET_LUN(scb), SCB_LIST_NULL,				ROLE_UNKNOWN, CAM_REQUEUE_REQ);}voidahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,		      ahd_queue_alg alg){	struct ahd_linux_device *dev;	int was_queuing;	int now_queuing;	dev = ahd_linux_get_device(ahd, devinfo->channel - 'A',				   devinfo->target,				   devinfo->lun, /*alloc*/FALSE);	if (dev == NULL)		return;	was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);	now_queuing = alg != AHD_QUEUE_NONE;	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0	 && (was_queuing != now_queuing)	 && (dev->active != 0)) {		dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;		dev->qfrozen++;	}	dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);	if (now_queuing) {		u_int usertags;		usertags = ahd_linux_user_tagdepth(ahd, devinfo);		if (!was_queuing) {			/*			 * Start out agressively and allow our			 * dynamic queue depth algorithm to take			 * care of the rest.			 */			dev->maxtags = usertags;			dev->openings = dev->maxtags - dev->active;		}		if (alg == AHD_QUEUE_TAGGED) {			dev->flags |= AHD_DEV_Q_TAGGED;			if (aic79xx_periodic_otag != 0)				dev->flags |= AHD_DEV_PERIODIC_OTAG;		} else			dev->flags |= AHD_DEV_Q_BASIC;	} else {		/* We can only have one opening. */		dev->maxtags = 0;

⌨️ 快捷键说明

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