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

📄 aic79xx_pci.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		/*		 * Fetch VPD for this function and parse it.		 */		if (bootverbose) 			printf("%s: Reading VPD from SEEPROM...",			       ahd_name(ahd));		/* Address is always in units of 16bit words */		start_addr = ((2 * sizeof(*sc))			    + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;		error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,					 start_addr, sizeof(vpd)/2,					 /*bytestream*/TRUE);		if (error == 0)			error = ahd_parse_vpddata(ahd, &vpd);		if (bootverbose) 			printf("%s: VPD parsing %s\n",			       ahd_name(ahd),			       error == 0 ? "successful" : "failed");		if (bootverbose) 			printf("%s: Reading SEEPROM...", ahd_name(ahd));		/* Address is always in units of 16bit words */		start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');		error = ahd_read_seeprom(ahd, (uint16_t *)sc,					 start_addr, sizeof(*sc)/2,					 /*bytestream*/FALSE);		if (error != 0) {			printf("Unable to read SEEPROM\n");			have_seeprom = 0;		} else {			have_seeprom = ahd_verify_cksum(sc);			if (bootverbose) {				if (have_seeprom == 0)					printf ("checksum error\n");				else					printf ("done.\n");			}		}		ahd_release_seeprom(ahd);	}	if (!have_seeprom) {		u_int	  nvram_scb;		/*		 * Pull scratch ram settings and treat them as		 * if they are the contents of an seeprom if		 * the 'ADPT', 'BIOS', or 'ASPI' signature is found		 * in SCB 0xFF.  We manually compose the data as 16bit		 * values to avoid endian issues.		 */		ahd_set_scbptr(ahd, 0xFF);		nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);		if (nvram_scb != 0xFF		 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {			uint16_t *sc_data;			int	  i;			ahd_set_scbptr(ahd, nvram_scb);			sc_data = (uint16_t *)sc;			for (i = 0; i < 64; i += 2)				*sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);			have_seeprom = ahd_verify_cksum(sc);			if (have_seeprom)				ahd->flags |= AHD_SCB_CONFIG_USED;		}	}#ifdef AHD_DEBUG	if (have_seeprom != 0	 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {		uint16_t *sc_data;		int	  i;		printf("%s: Seeprom Contents:", ahd_name(ahd));		sc_data = (uint16_t *)sc;		for (i = 0; i < (sizeof(*sc)); i += 2)			printf("\n\t0x%.4x", sc_data[i]);		printf("\n");	}#endif	if (!have_seeprom) {		if (bootverbose)			printf("%s: No SEEPROM available.\n", ahd_name(ahd));		ahd->flags |= AHD_USEDEFAULTS;		error = ahd_default_config(ahd);		adapter_control = CFAUTOTERM|CFSEAUTOTERM;		free(ahd->seep_config, M_DEVBUF);		ahd->seep_config = NULL;	} else {		error = ahd_parse_cfgdata(ahd, sc);		adapter_control = sc->adapter_control;	}	if (error != 0)		return (error);	ahd_configure_termination(ahd, adapter_control);	return (0);}static voidahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control){	int	 error;	u_int	 sxfrctl1;	uint8_t	 termctl;	uint32_t devconfig;	devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);	devconfig &= ~STPWLEVEL;	if ((ahd->flags & AHD_STPWLEVEL_A) != 0)		devconfig |= STPWLEVEL;	if (bootverbose)		printf("%s: STPWLEVEL is %s\n",		       ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");	ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 	/* Make sure current sensing is off. */	if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {		(void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);	}	/*	 * Read to sense.  Write to set.	 */	error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);	if ((adapter_control & CFAUTOTERM) == 0) {		if (bootverbose)			printf("%s: Manual Primary Termination\n",			       ahd_name(ahd));		termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);		if ((adapter_control & CFSTERM) != 0)			termctl |= FLX_TERMCTL_ENPRILOW;		if ((adapter_control & CFWSTERM) != 0)			termctl |= FLX_TERMCTL_ENPRIHIGH;	} else if (error != 0) {		printf("%s: Primary Auto-Term Sensing failed! "		       "Using Defaults.\n", ahd_name(ahd));		termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;	}	if ((adapter_control & CFSEAUTOTERM) == 0) {		if (bootverbose)			printf("%s: Manual Secondary Termination\n",			       ahd_name(ahd));		termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);		if ((adapter_control & CFSELOWTERM) != 0)			termctl |= FLX_TERMCTL_ENSECLOW;		if ((adapter_control & CFSEHIGHTERM) != 0)			termctl |= FLX_TERMCTL_ENSECHIGH;	} else if (error != 0) {		printf("%s: Secondary Auto-Term Sensing failed! "		       "Using Defaults.\n", ahd_name(ahd));		termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;	}	/*	 * Now set the termination based on what we found.	 */	sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;	if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {		ahd->flags |= AHD_TERM_ENB_A;		sxfrctl1 |= STPWEN;	}	/* Must set the latch once in order to be effective. */	ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);	ahd_outb(ahd, SXFRCTL1, sxfrctl1);	error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);	if (error != 0) {		printf("%s: Unable to set termination settings!\n",		       ahd_name(ahd));	} else if (bootverbose) {		printf("%s: Primary High byte termination %sabled\n",		       ahd_name(ahd),		       (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");		printf("%s: Primary Low byte termination %sabled\n",		       ahd_name(ahd),		       (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");		printf("%s: Secondary High byte termination %sabled\n",		       ahd_name(ahd),		       (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");		printf("%s: Secondary Low byte termination %sabled\n",		       ahd_name(ahd),		       (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");	}	return;}#define	DPE	0x80#define SSE	0x40#define	RMA	0x20#define	RTA	0x10#define STA	0x08#define DPR	0x01static const char *split_status_source[] ={	"DFF0",	"DFF1",	"OVLY",	"CMC",};static const char *pci_status_source[] ={	"DFF0",	"DFF1",	"SG",	"CMC",	"OVLY",	"NONE",	"MSI",	"TARG"};static const char *split_status_strings[] ={	"%s: Received split response in %s.\n",	"%s: Received split completion error message in %s\n",	"%s: Receive overrun in %s\n",	"%s: Count not complete in %s\n",	"%s: Split completion data bucket in %s\n",	"%s: Split completion address error in %s\n",	"%s: Split completion byte count error in %s\n",	"%s: Signaled Target-abort to early terminate a split in %s\n"};static const char *pci_status_strings[] ={	"%s: Data Parity Error has been reported via PERR# in %s\n",	"%s: Target initial wait state error in %s\n",	"%s: Split completion read data parity error in %s\n",	"%s: Split completion address attribute parity error in %s\n",	"%s: Received a Target Abort in %s\n",	"%s: Received a Master Abort in %s\n",	"%s: Signal System Error Detected in %s\n",	"%s: Address or Write Phase Parity Error Detected in %s.\n"};voidahd_pci_intr(struct ahd_softc *ahd){	uint8_t		pci_status[8];	ahd_mode_state	saved_modes;	u_int		pci_status1;	u_int		intstat;	u_int		i;	u_int		reg;		intstat = ahd_inb(ahd, INTSTAT);	if ((intstat & SPLTINT) != 0)		ahd_pci_split_intr(ahd, intstat);	if ((intstat & PCIINT) == 0)		return;	printf("%s: PCI error Interrupt\n", ahd_name(ahd));	saved_modes = ahd_save_modes(ahd);	ahd_dump_card_state(ahd);	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);	for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {		if (i == 5)			continue;		pci_status[i] = ahd_inb(ahd, reg);		/* Clear latched errors.  So our interrupt deasserts. */		ahd_outb(ahd, reg, pci_status[i]);	}	for (i = 0; i < 8; i++) {		u_int bit;			if (i == 5)			continue;		for (bit = 0; bit < 8; bit++) {			if ((pci_status[i] & (0x1 << bit)) != 0) {				static const char *s;				s = pci_status_strings[bit];				if (i == 7/*TARG*/ && bit == 3)					s = "%s: Signaled Target Abort\n";				printf(s, ahd_name(ahd), pci_status_source[i]);			}		}		}	pci_status1 = ahd_pci_read_config(ahd->dev_softc,					  PCIR_STATUS + 1, /*bytes*/1);	ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,			     pci_status1, /*bytes*/1);	ahd_restore_modes(ahd, saved_modes);	ahd_outb(ahd, CLRINT, CLRPCIINT);	ahd_unpause(ahd);}static voidahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat){	uint8_t		split_status[4];	uint8_t		split_status1[4];	uint8_t		sg_split_status[2];	uint8_t		sg_split_status1[2];	ahd_mode_state	saved_modes;	u_int		i;	uint16_t	pcix_status;	/*	 * Check for splits in all modes.  Modes 0 and 1	 * additionally have SG engine splits to look at.	 */	pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS,					  /*bytes*/2);	printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",	       ahd_name(ahd), pcix_status);	saved_modes = ahd_save_modes(ahd);	for (i = 0; i < 4; i++) {		ahd_set_modes(ahd, i, i);		split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);		split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);		/* Clear latched errors.  So our interrupt deasserts. */		ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);		ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);		if (i > 1)			continue;		sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);		sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);		/* Clear latched errors.  So our interrupt deasserts. */		ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);		ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);	}	for (i = 0; i < 4; i++) {		u_int bit;		for (bit = 0; bit < 8; bit++) {			if ((split_status[i] & (0x1 << bit)) != 0) {				static const char *s;				s = split_status_strings[bit];				printf(s, ahd_name(ahd),				       split_status_source[i]);			}			if (i > 1)				continue;			if ((sg_split_status[i] & (0x1 << bit)) != 0) {				static const char *s;				s = split_status_strings[bit];				printf(s, ahd_name(ahd), "SG");			}		}	}	/*	 * Clear PCI-X status bits.	 */	ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS,			     pcix_status, /*bytes*/2);	ahd_outb(ahd, CLRINT, CLRSPLTINT);	ahd_restore_modes(ahd, saved_modes);}static intahd_aic7901_setup(struct ahd_softc *ahd){	ahd->chip = AHD_AIC7901;	ahd->features = AHD_AIC7901_FE;	return (ahd_aic790X_setup(ahd));}static intahd_aic7901A_setup(struct ahd_softc *ahd){	ahd->chip = AHD_AIC7901A;	ahd->features = AHD_AIC7901A_FE;	return (ahd_aic790X_setup(ahd));}static intahd_aic7902_setup(struct ahd_softc *ahd){	ahd->chip = AHD_AIC7902;	ahd->features = AHD_AIC7902_FE;	return (ahd_aic790X_setup(ahd));}static intahd_aic790X_setup(struct ahd_softc *ahd){	ahd_dev_softc_t pci;	u_int rev;	pci = ahd->dev_softc;	rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1);	if (rev < ID_AIC7902_PCI_REV_A4) {		printf("%s: Unable to attach to unsupported chip revision %d\n",		       ahd_name(ahd), rev);		ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);		return (ENXIO);	}	ahd->channel = ahd_get_pci_function(pci) + 'A';	if (rev < ID_AIC7902_PCI_REV_B0) {		/*		 * Enable A series workarounds.		 */		ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG			  |  AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG			  |  AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG			  |  AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG			  |  AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG			  |  AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG			  |  AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG			  |  AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG			  |  AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG			  |  AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG			  |  AHD_FAINT_LED_BUG;		/*		 * IO Cell paramter setup.		 */		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);		if ((ahd->flags & AHD_HP_BOARD) == 0)			AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);	} else {		u_int devconfig1;		ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS			      |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;		ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;		/*		 * Some issues have been resolved in the 7901B.		 */		if ((ahd->features & AHD_MULTI_FUNC) != 0)			ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;		/*		 * IO Cell paramter setup.		 */		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);		AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);		AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);		/*		 * Set the PREQDIS bit for H2B which disables some workaround		 * that doesn't work on regular PCI busses.		 * XXX - Find out exactly what this does from the hardware		 * 	 folks!		 */		devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);		ahd_pci_write_config(pci, DEVCONFIG1,				     devconfig1|PREQDIS, /*bytes*/1);		devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);	}	return (0);}

⌨️ 快捷键说明

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