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

📄 aic7xxx_osm.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	switch (rvalue) {	case AHC_PCI:	{		char primary_channel;		if (aic7xxx_reverse_scan != 0)			value = ahc_get_pci_bus(rahc->dev_softc)			      - ahc_get_pci_bus(lahc->dev_softc);		else			value = ahc_get_pci_bus(lahc->dev_softc)			      - ahc_get_pci_bus(rahc->dev_softc);		if (value != 0)			break;		if (aic7xxx_reverse_scan != 0)			value = ahc_get_pci_slot(rahc->dev_softc)			      - ahc_get_pci_slot(lahc->dev_softc);		else			value = ahc_get_pci_slot(lahc->dev_softc)			      - ahc_get_pci_slot(rahc->dev_softc);		if (value != 0)			break;		/*		 * On multi-function devices, the user can choose		 * to have function 1 probed before function 0.		 * Give whichever channel is the primary channel		 * the lowest priority.		 */		primary_channel = (lahc->flags & AHC_PRIMARY_CHANNEL) + 'A';		value = 1;		if (lahc->channel == primary_channel)			value = -1;		break;	}	case AHC_EISA:		if ((rahc->flags & AHC_BIOS_ENABLED) != 0) {			value = lahc->platform_data->bios_address			      - rahc->platform_data->bios_address; 		} else {			value = lahc->bsh.ioport			      - rahc->bsh.ioport; 		}		break;	default:		panic("ahc_softc_sort: invalid bus type");	}	return (value);}static voidahc_linux_setup_tag_info(char *p, char *end){	char	*base;	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;		}	}	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;	/*	 * 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 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#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.	 */	ahc_list_lockinit();#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.	 */	spin_lock_irq(&io_request_lock);	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->irq = AHC_LINUX_NOIRQ;	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#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,		     (unsigned long)ahc);#endif	ahc->seltime = (aic7xxx_seltime & 0x3) << 4;	ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;	if (TAILQ_EMPTY(&ahc_tailq))		register_reboot_notifier(&ahc_linux_notifier);	return (0);}voidahc_platform_free(struct ahc_softc *ahc)

⌨️ 快捷键说明

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