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

📄 aic7xxx_linux.c

📁 自己根据lkd和情境分析
💻 C
📖 第 1 页 / 共 5 页
字号:
	char	*tok;	char	*tok_end;	char	*tok_end2;	int      i;	int      instance;	int	 targ;	int	 done;	char	 tok_list[] = {'.', ',', '{', '}', '\0'};	if (*p != ':')		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;			else if (targ == -1)				targ = 0;			tok++;			break;		case '}':			if (targ != -1)				targ = -1;			else if (instance != -1)				instance = -1;			tok++;			break;		case ',':		case '.':			if (instance == -1)				done = TRUE;			else if (targ >= 0)				targ++;			else if (instance >= 0)				instance++;			if ((targ >= AHC_NUM_TARGETS) ||			    (instance >= NUM_ELEMENTS(aic7xxx_tag_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) && (targ >= 0)			 && (instance < NUM_ELEMENTS(aic7xxx_tag_info))			 && (targ < AHC_NUM_TARGETS)) {				aic7xxx_tag_info[instance].tag_commands[targ] =				    simple_strtoul(tok, NULL, 0) & 0xff;			}			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. aic7xxx=stpwlev:1,extended */intaic7xxx_setup(char *s){	int	i, n;	char   *p;	char   *end;	static struct {		const char *name;		uint32_t *flag;	} options[] = {		{ "extended", &aic7xxx_extended },		{ "no_reset", &aic7xxx_no_reset },		{ "verbose", &aic7xxx_verbose },		{ "reverse_scan", &aic7xxx_reverse_scan },		{ "no_probe", &aic7xxx_no_probe },		{ "periodic_otag", &aic7xxx_periodic_otag },		{ "pci_parity", &aic7xxx_pci_parity },		{ "seltime", &aic7xxx_seltime },		{ "tag_info", 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) {				ahc_linux_setup_tag_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;		}	}	register_reboot_notifier(&ahc_linux_notifier);	return 1;}#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)__setup("aic7xxx=", aic7xxx_setup);#endifint aic7xxx_verbose;/* * Try to detect an Adaptec 7XXX controller. */intahc_linux_detect(Scsi_Host_Template *template){	struct	ahc_softc *ahc;	int     found;	/*	 * Sanity checking of Linux SCSI data structures so	 * that some of our hacks^H^H^H^H^Hassumptions aren't	 * violated.	 */	if (offsetof(struct ahc_cmd_internal, end)	  > offsetof(struct scsi_cmnd, host_scribble)) {		printf("ahc_linux_detect: SCSI data structures changed.\n");		printf("ahc_linux_detect: Unable to attach\n");		return (0);	}#ifdef MODULE	/*	 * If we've been passed any parameters, process them now.	 */	if (aic7xxx)		aic7xxx_setup(aic7xxx);	if (dummy_buffer[0] != 'P')		printk(KERN_WARNING"aic7xxx: Please read the file /usr/src/linux/drivers/scsi/README.aic7xxx\n""aic7xxx: to see the proper way to specify options to the aic7xxx module\n""aic7xxx: Specifically, don't use any commas when passing arguments to\n""aic7xxx: insmod or else it might trash certain memory areas.\n");#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)	template->proc_name = "aic7xxx";#else	template->proc_dir = &proc_scsi_aic7xxx;#endif	template->sg_tablesize = AHC_NSEG;#ifdef CONFIG_PCI	ahc_linux_pci_probe(template);#endif	if (aic7xxx_no_probe == 0)		aic7770_linux_probe(template);	/*	 * Register with the SCSI layer all	 * controllers we've found.	 */	found = 0;	TAILQ_FOREACH(ahc, &ahc_tailq, links) {		if (ahc_linux_register_host(ahc, template) == 0)			found++;	}	aic7xxx_detect_complete++;	return (found);}intahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template){	char  buf[80];	struct Scsi_Host *host;	char *new_name;	u_long s;	template->name = ahc->description;	host = scsi_register(template, sizeof(struct ahc_softc *));	if (host == NULL)		return (ENOMEM);	ahc_lock(ahc, &s);	*((struct ahc_softc **)host->hostdata) = ahc;	ahc->platform_data->host = host;	host->can_queue = AHC_MAX_QUEUE;	host->cmd_per_lun = 2;	host->sg_tablesize = AHC_NSEG;	host->select_queue_depths = ahc_linux_select_queue_depth;	/* XXX No way to communicate the ID for multiple channels */	host->this_id = ahc->our_id;	host->irq = ahc->platform_data->irq;	host->max_id = (ahc->features & AHC_WIDE) ? 16 : 8;	host->max_lun = AHC_NUM_LUNS;	host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0;	ahc_set_unit(ahc, ahc_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);		ahc_set_name(ahc, new_name);	}	host->unique_id = ahc->unit;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)	scsi_set_pci_device(host, ahc->dev_softc);#endif	ahc_linux_initialize_scsi_bus(ahc);	ahc_unlock(ahc, &s);	return (0);}uint64_tahc_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 intahc_linux_next_unit(){	struct ahc_softc *ahc;	int unit;	unit = 0;retry:	TAILQ_FOREACH(ahc, &ahc_tailq, links) {		if (ahc->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. */voidahc_linux_initialize_scsi_bus(struct ahc_softc *ahc){	int i;	int numtarg;	i = 0;	numtarg = 0;	if (aic7xxx_no_reset != 0)		ahc->flags &= ~(AHC_RESET_BUS_A|AHC_RESET_BUS_B);	if ((ahc->flags & AHC_RESET_BUS_A) != 0)		ahc_reset_channel(ahc, 'A', /*initiate_reset*/TRUE);	else		numtarg = (ahc->features & AHC_WIDE) ? 16 : 8;	if ((ahc->features & AHC_TWIN) != 0) {		if ((ahc->flags & AHC_RESET_BUS_B) != 0) {			ahc_reset_channel(ahc, 'B', /*initiate_reset*/TRUE);		} else {			if (numtarg == 0)				i = 8;			numtarg += 8;		}	}	for (; i < numtarg; i++) {		struct ahc_devinfo devinfo;		struct ahc_initiator_tinfo *tinfo;		struct ahc_tmode_tstate *tstate;		u_int our_id;		u_int target_id;		char channel;		channel = 'A';		our_id = ahc->our_id;		target_id = i;		if (i > 7 && (ahc->features & AHC_TWIN) != 0) {			channel = 'B';			our_id = ahc->our_id_b;			target_id = i % 8;		}		tinfo = ahc_fetch_transinfo(ahc, 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;		ahc_compile_devinfo(&devinfo, our_id, target_id,				   CAM_LUN_WILDCARD, channel, ROLE_INITIATOR);		ahc_update_neg_request(ahc, &devinfo, tstate,				       tinfo, /*force*/FALSE);	}	/* Give the bus some time to recover */	if ((ahc->flags & (AHC_RESET_BUS_A|AHC_RESET_BUS_B)) != 0) {		ahc_linux_freeze_sim_queue(ahc);		init_timer(&ahc->platform_data->reset_timer);		ahc->platform_data->reset_timer.data = (u_long)ahc;		ahc->platform_data->reset_timer.expires =		    jiffies + (AIC7XXX_RESET_DELAY * HZ)/1000;		ahc->platform_data->reset_timer.function =		    ahc_linux_release_sim_queue;		add_timer(&ahc->platform_data->reset_timer);	}}intahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg){	ahc->platform_data =	    malloc(sizeof(struct ahc_platform_data), M_DEVBUF, M_NOWAIT);	if (ahc->platform_data == NULL)		return (ENOMEM);	memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));	TAILQ_INIT(&ahc->platform_data->completeq);	TAILQ_INIT(&ahc->platform_data->device_runq);	ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;	ahc_lockinit(ahc);	ahc_done_lockinit(ahc);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)	init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);#else	ahc->platform_data->eh_sem = MUTEX_LOCKED;#endif	ahc->seltime = (aic7xxx_seltime & 0x3) << 4;	ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;	return (0);}voidahc_platform_free(struct ahc_softc *ahc){	if (ahc->platform_data != NULL) {		if (ahc->platform_data->host != NULL)			scsi_unregister(ahc->platform_data->host);		if (ahc->platform_data->irq)			free_irq(ahc->platform_data->irq, ahc);		if (ahc->tag == BUS_SPACE_PIO		 && ahc->bsh.ioport != 0)			release_region(ahc->bsh.ioport, 256);		if (ahc->tag == BUS_SPACE_MEMIO		 && ahc->bsh.maddr != NULL) {			u_long base_addr;			base_addr = (u_long)ahc->bsh.maddr;			base_addr &= PAGE_MASK;			iounmap((void *)base_addr);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			release_mem_region(ahc->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 (ahc->dev_softc != NULL)			ahc->dev_softc->driver = NULL;#endif		free(ahc->platform_data, M_DEVBUF);	}}voidahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb){	ahc_platform_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb),				SCB_GET_CHANNEL(ahc, scb),				SCB_GET_LUN(scb), SCB_LIST_NULL,				ROLE_UNKNOWN, CAM_REQUEUE_REQ);}voidahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,		      ahc_queue_alg alg){	struct ahc_linux_device *dev;	int was_queuing;	int now_queuing;	dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',				   devinfo->target,				   devinfo->lun, /*alloc*/FALSE);	if (dev == NULL)		return;	was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);	now_queuing = alg != AHC_QUEUE_NONE;	if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) == 0	 && (was_queuing != now_queuing)	 && (dev->active != 0)) {		dev->flags |= AHC_DEV_FREEZE_TIL_EMPTY;		dev->qfrozen++;	}	dev->flags &= ~(AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED|AHC_DEV_PERIODIC_OTAG);	if (now_queuing) {		if (!was_queuing) {			/*			 * Start out agressively and allow our			 * dynamic queue depth algorithm to take			 * care of the rest.			 */			dev->maxtags = AHC_MAX_QUEUE;			dev->openings = dev->maxtags - dev->active;		}		if (alg == AHC_QUEUE_TAGGED) {			dev->flags |= AHC_DEV_Q_TAGGED;			if (aic7xxx_periodic_otag != 0)				dev->flags |= AHC_DEV_PERIODIC_OTAG;

⌨️ 快捷键说明

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