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

📄 aic79xx_osm.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		free(map, M_DEVBUF);}intahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map){	/* Nothing to do */	return (0);}/********************* Platform Dependent Functions ***************************//* * Compare "left hand" softc with "right hand" softc, returning: * < 0 - lahd has a lower priority than rahd *   0 - Softcs are equal * > 0 - lahd has a higher priority than rahd */intahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd){	int	value;	/*	 * Under Linux, cards are ordered as follows:	 *	1) PCI devices that are marked as the boot controller.	 *	2) PCI devices with BIOS enabled sorted by bus/slot/func.	 *	3) All remaining PCI devices sorted by bus/slot/func.	 */#if 0	value = (lahd->flags & AHD_BOOT_CHANNEL)	      - (rahd->flags & AHD_BOOT_CHANNEL);	if (value != 0)		/* Controllers set for boot have a *higher* priority */		return (value);#endif	value = (lahd->flags & AHD_BIOS_ENABLED)	      - (rahd->flags & AHD_BIOS_ENABLED);	if (value != 0)		/* Controllers with BIOS enabled have a *higher* priority */		return (value);	/* Still equal.  Sort by bus/slot/func. */	if (aic79xx_reverse_scan != 0)		value = ahd_get_pci_bus(lahd->dev_softc)		      - ahd_get_pci_bus(rahd->dev_softc);	else		value = ahd_get_pci_bus(rahd->dev_softc)		      - ahd_get_pci_bus(lahd->dev_softc);	if (value != 0)		return (value);	if (aic79xx_reverse_scan != 0)		value = ahd_get_pci_slot(lahd->dev_softc)		      - ahd_get_pci_slot(rahd->dev_softc);	else		value = ahd_get_pci_slot(rahd->dev_softc)		      - ahd_get_pci_slot(lahd->dev_softc);	if (value != 0)		return (value);	value = rahd->channel - lahd->channel;	return (value);}static voidahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value){	if ((instance >= 0) && (targ >= 0)	 && (instance < NUM_ELEMENTS(aic79xx_tag_info))	 && (targ < AHD_NUM_TARGETS)) {		aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;		if (bootverbose)			printf("tag_info[%d:%d] = %d\n", instance, targ, value);	}}static voidahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value){	if ((instance >= 0)	 && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) {		aic79xx_rd_strm_info[instance] = value & 0xFFFF;		if (bootverbose)			printf("rd_strm[%d] = 0x%x\n", instance, value);	}}static voidahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value){	if ((instance >= 0)	 && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) {		aic79xx_dv_settings[instance] = value;		if (bootverbose)			printf("dv[%d] = %d\n", instance, value);	}}static voidahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value){	if ((instance >= 0)	 && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) {		uint8_t *iocell_info;		iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];		iocell_info[index] = value & 0xFFFF;		if (bootverbose)			printf("iocell[%d:%ld] = %d\n", instance, index, value);	}}static voidahd_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(aic79xx_tag_info); i++) {		for (j = 0; j < AHD_NUM_TARGETS; j++) {			aic79xx_tag_info[i].tag_commands[j] = tags;		}	}}/* * 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 */static 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 },		{ "allow_memio", &aic79xx_allow_memio},#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 },		{ "global_tag_depth", NULL},		{ "rd_strm", NULL },		{ "dv", NULL },		{ "slewrate", NULL },		{ "precomp", NULL },		{ "amplitude", NULL },	};	end = strchr(s, '\0');	/*	 * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS	 * will never be 0 in this case.	 */      	n = 0;  	while ((p = strsep(&s, ",.")) != NULL) {		if (*p == '\0')			continue;		for (i = 0; i < NUM_ELEMENTS(options); i++) {			n = strlen(options[i].name);			if (strncmp(options[i].name, p, n) == 0)				break;		}		if (i == NUM_ELEMENTS(options))			continue;		if (strncmp(p, "global_tag_depth", n) == 0) {			ahd_linux_setup_tag_info_global(p + n);		} else if (strncmp(p, "tag_info", n) == 0) {			s = aic_parse_brace_option("tag_info", p + n, end,			    2, ahd_linux_setup_tag_info, 0);		} else if (strncmp(p, "rd_strm", n) == 0) {			s = aic_parse_brace_option("rd_strm", p + n, end,			    1, ahd_linux_setup_rd_strm_info, 0);		} else if (strncmp(p, "dv", n) == 0) {			s = aic_parse_brace_option("dv", p + n, end, 1,			    ahd_linux_setup_dv, 0);		} else if (strncmp(p, "slewrate", n) == 0) {			s = aic_parse_brace_option("slewrate",			    p + n, end, 1, ahd_linux_setup_iocell_info,			    AIC79XX_SLEWRATE_INDEX);		} else if (strncmp(p, "precomp", n) == 0) {			s = aic_parse_brace_option("precomp",			    p + n, end, 1, ahd_linux_setup_iocell_info,			    AIC79XX_PRECOMP_INDEX);		} else if (strncmp(p, "amplitude", n) == 0) {			s = aic_parse_brace_option("amplitude",			    p + n, end, 1, ahd_linux_setup_iocell_info,			    AIC79XX_AMPLITUDE_INDEX);		} 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) ^= 0xFFFFFFFF;		}	}	return 1;}__setup("aic79xx=", aic79xx_setup);uint32_t aic79xx_verbose;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;	u_long	target;	template->name = ahd->description;	host = scsi_host_alloc(template, sizeof(struct ahd_softc *));	if (host == NULL)		return (ENOMEM);	*((struct ahd_softc **)host->hostdata) = ahd;	ahd_lock(ahd, &s);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)	scsi_assign_lock(host, &ahd->platform_data->spin_lock);#elif AHD_SCSI_HAS_HOST_LOCK != 0	host->lock = &ahd->platform_data->spin_lock;#endif	ahd->platform_data->host = host;	host->can_queue = AHD_MAX_QUEUE;	host->cmd_per_lun = 2;	host->sg_tablesize = AHD_NSEG;	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;	host->sg_tablesize = AHD_NSEG;	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,5,0)	scsi_set_pci_device(host, ahd->dev_softc);#endif	ahd_linux_setup_user_rd_strm_settings(ahd);	ahd_linux_initialize_scsi_bus(ahd);	ahd_unlock(ahd, &s);	ahd->platform_data->dv_pid = kernel_thread(ahd_linux_dv_thread, ahd, 0);	ahd_lock(ahd, &s);	if (ahd->platform_data->dv_pid < 0) {		printf("%s: Failed to create DV thread, error= %d\n",		       ahd_name(ahd), ahd->platform_data->dv_pid);		return (-ahd->platform_data->dv_pid);	}	/*	 * Initially allocate *all* of our linux target objects	 * so that the DV thread will scan them all in parallel	 * just after driver initialization.  Any device that	 * does not exist will have its target object destroyed	 * by the selection timeout handler.  In the case of a	 * device that appears after the initial DV scan, async	 * negotiation will occur for the first command, and DV	 * will comence should that first command be successful.	 */	for (target = 0; target < host->max_id; target++) {		/*		 * Skip our own ID.  Some Compaq/HP storage devices		 * have enclosure management devices that respond to		 * single bit selection (i.e. selecting ourselves).		 * It is expected that either an external application		 * or a modified kernel will be used to probe this		 * ID if it is appropriate.  To accommodate these		 * installations, ahc_linux_alloc_target() will allocate		 * for our ID if asked to do so.		 */		if (target == ahd->our_id) 			continue;		ahd_linux_alloc_target(ahd, 0, target);	}	ahd_intr_enable(ahd, TRUE);	ahd_linux_start_dv(ahd);	ahd_unlock(ahd, &s);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)	scsi_add_host(host, &ahd->dev_softc->dev); /* XXX handle failure */	scsi_scan_host(host);#endif	return (0);}uint64_tahd_linux_get_memsize(void){	struct sysinfo si;	si_meminfo(&si);	return ((uint64_t)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(void){	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. */static voidahd_linux_initialize_scsi_bus(struct ahd_softc *ahd){	u_int target_id;	u_int numtarg;	target_id = 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;	/*	 * Force negotiation to async for all targets that	 * will not see an initial bus reset.	 */	for (; target_id < numtarg; target_id++) {		struct ahd_devinfo devinfo;		struct ahd_initiator_tinfo *tinfo;		struct ahd_tmode_tstate *tstate;		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,					    target_id, &tstate);		ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,				    CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);		ahd_update_neg_request(ahd, &devinfo, tstate,				       tinfo, AHD_NEG_ALWAYS);	}	/* 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);	init_timer(&ahd->platform_data->completeq_timer);	ahd->platform_data->completeq_timer.data = (u_long)ahd;	ahd->platform_data->completeq_timer.function =	    (ahd_linux_callback_t *)ahd_linux_thread_run_complete_queue;	init_MUTEX_LOCKED(&ahd->platform_data->eh_sem);	init_MUTEX_LOCKED(&ahd->platform_data->dv_sem);	init_MUTEX_LOCKED(&ahd->platform_data->dv_cmd_sem);	ahd_setup_runq_tasklet(ahd);	ahd->seltime = (aic79xx_seltime & 0x3) << 4;	return (0);}voidahd_platform_free(struct ahd_softc *ahd){	struct ahd_linux_target *targ;	struct ahd_linux_device *dev;	int i, j;	if (ahd->platform_data != NULL) {		del_timer_sync(&ahd->platform_data->completeq_timer);		ahd_linux_kill_dv_thread(ahd);		ahd_teardown_runq_tasklet(ahd);		if (ahd->platform_data->host != NULL) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)			scsi_remove_host(ahd->platform_data->host);#endif			scsi_h

⌨️ 快捷键说明

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