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

📄 aic7xxx_pci.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * either, so look for data corruption and/or flagged	 * PCI errors.  First pause without causing another	 * chip reset.	 */	hcntrl &= ~CHIPRST;	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);	while (ahc_is_paused(ahc) == 0)		;	/* Clear any PCI errors that occurred before our driver attached. */	status1 = ahc_pci_read_config(ahc->dev_softc,				      PCIR_STATUS + 1, /*bytes*/1);	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,			     status1, /*bytes*/1);	ahc_outb(ahc, CLRINT, CLRPARERR);	ahc_outb(ahc, SEQCTL, PERRORDIS);	ahc_outb(ahc, SCBPTR, 0);	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)		goto fail;	status1 = ahc_pci_read_config(ahc->dev_softc,				      PCIR_STATUS + 1, /*bytes*/1);	if ((status1 & STA) != 0)		goto fail;	error = 0;fail:	/* Silently clear any latched errors. */	status1 = ahc_pci_read_config(ahc->dev_softc,				      PCIR_STATUS + 1, /*bytes*/1);	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,			     status1, /*bytes*/1);	ahc_outb(ahc, CLRINT, CLRPARERR);	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);	return (error);}/* * Check the external port logic for a serial eeprom * and termination/cable detection contrls. */static voidcheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1){	struct	seeprom_descriptor sd;	struct	seeprom_config *sc;	int	have_seeprom;	int	have_autoterm;	sd.sd_ahc = ahc;	sd.sd_control_offset = SEECTL;			sd.sd_status_offset = SEECTL;			sd.sd_dataout_offset = SEECTL;			sc = ahc->seep_config;	/*	 * For some multi-channel devices, the c46 is simply too	 * small to work.  For the other controller types, we can	 * get our information from either SEEPROM type.  Set the	 * type to start our probe with accordingly.	 */	if (ahc->flags & AHC_LARGE_SEEPROM)		sd.sd_chip = C56_66;	else		sd.sd_chip = C46;	sd.sd_MS = SEEMS;	sd.sd_RDY = SEERDY;	sd.sd_CS = SEECS;	sd.sd_CK = SEECK;	sd.sd_DO = SEEDO;	sd.sd_DI = SEEDI;	have_seeprom = ahc_acquire_seeprom(ahc, &sd);	if (have_seeprom) {		if (bootverbose) 			printf("%s: Reading SEEPROM...", ahc_name(ahc));		for (;;) {			u_int start_addr;			start_addr = 32 * (ahc->channel - 'A');			have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,							start_addr,							sizeof(*sc)/2);			if (have_seeprom)				have_seeprom = ahc_verify_cksum(sc);			if (have_seeprom != 0 || sd.sd_chip == C56_66) {				if (bootverbose) {					if (have_seeprom == 0)						printf ("checksum error\n");					else						printf ("done.\n");				}				break;			}			sd.sd_chip = C56_66;		}		ahc_release_seeprom(&sd);	}	if (!have_seeprom) {		/*		 * Pull scratch ram settings and treat them as		 * if they are the contents of an seeprom if		 * the 'ADPT' signature is found in SCB2.		 * We manually compose the data as 16bit values		 * to avoid endian issues.		 */		ahc_outb(ahc, SCBPTR, 2);		if (ahc_inb(ahc, SCB_BASE) == 'A'		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {			uint16_t *sc_data;			int	  i;			sc_data = (uint16_t *)sc;			for (i = 0; i < 32; i++, sc_data++) {				int	j;				j = i * 2;				*sc_data = ahc_inb(ahc, SRAM_BASE + j)					 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;			}			have_seeprom = ahc_verify_cksum(sc);			if (have_seeprom)				ahc->flags |= AHC_SCB_CONFIG_USED;		}		/*		 * Clear any SCB parity errors in case this data and		 * its associated parity was not initialized by the BIOS		 */		ahc_outb(ahc, CLRINT, CLRPARERR);		ahc_outb(ahc, CLRINT, CLRBRKADRINT);	}	if (!have_seeprom) {		if (bootverbose)			printf("%s: No SEEPROM available.\n", ahc_name(ahc));		ahc->flags |= AHC_USEDEFAULTS;		free(ahc->seep_config, M_DEVBUF);		ahc->seep_config = NULL;		sc = NULL;	} else {		ahc_parse_pci_eeprom(ahc, sc);	}	/*	 * Cards that have the external logic necessary to talk to	 * a SEEPROM, are almost certain to have the remaining logic	 * necessary for auto-termination control.  This assumption	 * hasn't failed yet...	 */	have_autoterm = have_seeprom;	/*	 * Some low-cost chips have SEEPROM and auto-term control built	 * in, instead of using a GAL.  They can tell us directly	 * if the termination logic is enabled.	 */	if ((ahc->features & AHC_SPIOCAP) != 0) {		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)			have_autoterm = FALSE;	}	if (have_autoterm) {		ahc->flags |= AHC_HAS_TERM_LOGIC;		ahc_acquire_seeprom(ahc, &sd);		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);		ahc_release_seeprom(&sd);	} else if (have_seeprom) {		*sxfrctl1 &= ~STPWEN;		if ((sc->adapter_control & CFSTERM) != 0)			*sxfrctl1 |= STPWEN;		if (bootverbose)			printf("%s: Low byte termination %sabled\n",			       ahc_name(ahc),			       (*sxfrctl1 & STPWEN) ? "en" : "dis");	}}static voidahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc){	/*	 * Put the data we've collected down into SRAM	 * where ahc_init will find it.	 */	int	 i;	int	 max_targ = sc->max_targets & CFMAXTARG;	u_int	 scsi_conf;	uint16_t discenable;	uint16_t ultraenb;	discenable = 0;	ultraenb = 0;	if ((sc->adapter_control & CFULTRAEN) != 0) {		/*		 * Determine if this adapter has a "newstyle"		 * SEEPROM format.		 */		for (i = 0; i < max_targ; i++) {			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {				ahc->flags |= AHC_NEWEEPROM_FMT;				break;			}		}	}	for (i = 0; i < max_targ; i++) {		u_int     scsirate;		uint16_t target_mask;		target_mask = 0x01 << i;		if (sc->device_flags[i] & CFDISC)			discenable |= target_mask;		if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)				ultraenb |= target_mask;		} else if ((sc->adapter_control & CFULTRAEN) != 0) {			ultraenb |= target_mask;		}		if ((sc->device_flags[i] & CFXFER) == 0x04		 && (ultraenb & target_mask) != 0) {			/* Treat 10MHz as a non-ultra speed */			sc->device_flags[i] &= ~CFXFER;		 	ultraenb &= ~target_mask;		}		if ((ahc->features & AHC_ULTRA2) != 0) {			u_int offset;			if (sc->device_flags[i] & CFSYNCH)				offset = MAX_OFFSET_ULTRA2;			else 				offset = 0;			ahc_outb(ahc, TARG_OFFSET + i, offset);			/*			 * The ultra enable bits contain the			 * high bit of the ultra2 sync rate			 * field.			 */			scsirate = (sc->device_flags[i] & CFXFER)				 | ((ultraenb & target_mask) ? 0x8 : 0x0);			if (sc->device_flags[i] & CFWIDEB)				scsirate |= WIDEXFER;		} else {			scsirate = (sc->device_flags[i] & CFXFER) << 4;			if (sc->device_flags[i] & CFSYNCH)				scsirate |= SOFS;			if (sc->device_flags[i] & CFWIDEB)				scsirate |= WIDEXFER;		}		ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);	}	ahc->our_id = sc->brtime_id & CFSCSIID;	scsi_conf = (ahc->our_id & 0x7);	if (sc->adapter_control & CFSPARITY)		scsi_conf |= ENSPCHK;	if (sc->adapter_control & CFRESETB)		scsi_conf |= RESET_SCSI;	ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;	if (sc->bios_control & CFEXTEND)		ahc->flags |= AHC_EXTENDED_TRANS_A;	if (sc->bios_control & CFBIOSEN)		ahc->flags |= AHC_BIOS_ENABLED;	if (ahc->features & AHC_ULTRA	 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {		/* Should we enable Ultra mode? */		if (!(sc->adapter_control & CFULTRAEN))			/* Treat us as a non-ultra card */			ultraenb = 0;	}	if (sc->signature == CFSIGNATURE	 || sc->signature == CFSIGNATURE2) {		uint32_t devconfig;		/* Honor the STPWLEVEL settings */		devconfig = ahc_pci_read_config(ahc->dev_softc,						DEVCONFIG, /*bytes*/4);		devconfig &= ~STPWLEVEL;		if ((sc->bios_control & CFSTPWLEVEL) != 0)			devconfig |= STPWLEVEL;		ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,				     devconfig, /*bytes*/4);	}	/* Set SCSICONF info */	ahc_outb(ahc, SCSICONF, scsi_conf);	ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));	ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));	ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);	ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);}static voidconfigure_termination(struct ahc_softc *ahc,		      struct seeprom_descriptor *sd,		      u_int adapter_control,		      u_int *sxfrctl1){	uint8_t brddat;		brddat = 0;	/*	 * Update the settings in sxfrctl1 to match the	 * termination settings 	 */	*sxfrctl1 = 0;		/*	 * SEECS must be on for the GALS to latch	 * the data properly.  Be sure to leave MS	 * on or we will release the seeprom.	 */	SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);	if ((adapter_control & CFAUTOTERM) != 0	 || (ahc->features & AHC_NEW_TERMCTL) != 0) {		int internal50_present;		int internal68_present;		int externalcable_present;		int eeprom_present;		int enableSEC_low;		int enableSEC_high;		int enablePRI_low;		int enablePRI_high;		int sum;		enableSEC_low = 0;		enableSEC_high = 0;		enablePRI_low = 0;		enablePRI_high = 0;		if ((ahc->features & AHC_NEW_TERMCTL) != 0) {			ahc_new_term_detect(ahc, &enableSEC_low,					    &enableSEC_high,					    &enablePRI_low,					    &enablePRI_high,					    &eeprom_present);			if ((adapter_control & CFSEAUTOTERM) == 0) {				if (bootverbose)					printf("%s: Manual SE Termination\n",					       ahc_name(ahc));				enableSEC_low = (adapter_control & CFSELOWTERM);				enableSEC_high =				    (adapter_control & CFSEHIGHTERM);			}			if ((adapter_control & CFAUTOTERM) == 0) {				if (bootverbose)					printf("%s: Manual LVD Termination\n",					       ahc_name(ahc));				enablePRI_low = (adapter_control & CFSTERM);				enablePRI_high = (adapter_control & CFWSTERM);			}			/* Make the table calculations below happy */			internal50_present = 0;			internal68_present = 1;			externalcable_present = 1;		} else if ((ahc->features & AHC_SPIOCAP) != 0) {			aic785X_cable_detect(ahc, &internal50_present,					     &externalcable_present,					     &eeprom_present);			/* Can never support a wide connector. */			internal68_present = 0;		} else {			aic787X_cable_detect(ahc, &internal50_present,					     &internal68_present,					     &externalcable_present,					     &eeprom_present);		}		if ((ahc->features & AHC_WIDE) == 0)			internal68_present = 0;		if (bootverbose		 && (ahc->features & AHC_ULTRA2) == 0) {			printf("%s: internal 50 cable %s present",			       ahc_name(ahc),			       internal50_present ? "is":"not");			if ((ahc->features & AHC_WIDE) != 0)				printf(", internal 68 cable %s present",				       internal68_present ? "is":"not");			printf("\n%s: external cable %s present\n",			       ahc_name(ahc),			       externalcable_present ? "is":"not");		}		if (bootverbose)			printf("%s: BIOS eeprom %s present\n",			       ahc_name(ahc), eeprom_present ? "is" : "not");		if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {			/*			 * The 50 pin connector is a separate bus,			 * so force it to always be terminated.			 * In the future, perform current sensing			 * to determine if we are in the middle of			 * a properly terminated bus.			 */			internal50_present = 0;		}		/*		 * Now set the termination based on what		 * we found.		 * Flash Enable = BRDDAT7		 * Secondary High Term Enable = BRDDAT6		 * Secondary Low Term Enable = BRDDAT5 (7890)		 * Primary High Term Enable = BRDDAT4 (7890)		 */		if ((ahc->features & AHC_ULTRA2) == 0		 && (internal50_present != 0)		 && (internal68_present != 0)		 && (externalcable_present != 0)) {			printf("%s: Illegal cable configuration!!. "			       "Only two connectors on the "			       "adapter may be used at a "			       "time!\n", ahc_name(ahc));			/*			 * Pretend there are no cables in the hope			 * that having all of the termination on			 * gives us a more stable bus.			 */		 	internal50_present = 0;			internal68_present = 0;			externalcable_present = 0;		}		if ((ahc->features & AHC_WIDE) != 0		 && ((externalcable_present == 0)		  || (internal68_present == 0)		  || (enableSEC_high != 0))) {			brddat |= BRDDAT6;			if (bootverbose) {				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)					printf("%s: 68 pin termination "					       "Enabled\n", ahc_name(ahc));				else					printf("%s: %sHigh byte termination "					       "Enabled\n", ahc_name(ahc),					       enableSEC_high ? "Secondary "							      : "");			}		}		sum = internal50_present + internal68_present		    + externalcable_present;		if (sum < 2 || (enableSEC_low != 0)) {			if ((ahc->features & AHC_ULTRA2) != 0)				brddat |= BRDDAT5;			else				*sxfrctl1 |= STPWEN;			if (bootverbose) {				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)					printf("%s: 50 pin termination "					       "Enabled\n", ahc_name(ahc));				else					printf("%s: %sLow byte termination "					       "Enabled\n", ahc_name(ahc),					       enableSEC_low ? "Secondary "							     : "");			}		}		if (enablePRI_low != 0) {			*sxfrctl1 |= STPWEN;			if (bootverbose)				printf("%s: Primary Low Byte termination "				       "Enabled\n", ahc_name(ahc));		}		/*		 * Setup STPWEN before setting up the rest of		 * the termination per the tech note on the U160 cards.		 */		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);		if (enablePRI_high != 0) {			brddat |= BRDDAT4;			if (bootverbose)				printf("%s: Primary High Byte "				       "termination Enabled\n",				       ahc_name(ahc));		}				write_brdctl(ahc, brddat);	} else {		if ((adapter_control & CFSTERM) != 0) {			*sxfrctl1 |= STPWEN;			if (bootverbose)				printf("%s: %sLow byte termination Enabled\n",				       ahc_name(ahc),				       (ahc->features & AHC_ULTRA2) ? "Primary "								    : "");		}		if ((adapter_control & CFWSTERM) != 0		 && (ahc->features & AHC_WIDE) != 0) {			brddat |= BRDDAT6;			if (bootverbose)				printf("%s: %sHigh byte termination Enabled\n",				       ahc_name(ahc),				       (ahc->features & AHC_ULTRA2)				     ? "Secondary " : "");		}		/*		 * Setup STPWEN before setting up the rest of		 * the termination per the tech note on the U160 cards.		 */		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);		if ((ahc->features & AHC_WIDE) != 0)			write_brdctl(ahc, brddat);	}	SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */}static voidahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,		    int *enableSEC_high, int *enablePRI_low,		    int *enablePRI_high, int *eeprom_present){	uint8_t brdctl;	/*	 * BRDDAT7 = Eeprom	 * BRDDAT6 = Enable Secondary High Byte termination	 * BRDDAT5 = Enable Secondary Low Byte termination	 * BRDDAT4 = Enable Primary high byte termination	 * BRDDAT3 = Enable Primary low byte termination	 */	brdctl = read_brdctl(ahc);	*eeprom_present = brdctl & BRDDAT7;	*enableSEC_high = (brdctl & BRDDAT6);	*enableSEC_low = (brdctl & BRDDAT5);	*enablePRI_high = (brdctl & BRDDAT4);	*enablePRI_low = (brdctl & BRDDAT3);}static voidaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,		     int *internal68_present, int *externalcable_present,		     int *eeprom_present){	uint8_t brdctl;	/*	 * First read the status of our cables.	 * Set the rom bank to 0 since the	 * bank setting serves as a multiplexor	 * for the cable detection logic.	 * BRDDAT5 controls the bank switch.	 */	write_brdctl(ahc, 0);	/*	 * Now read the state of the internal	 * connectors.  BRDDAT6 is INT50 and	 * BRDDAT7 is INT68.	 */	brdctl = read_brdctl(ahc);	*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;	*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;	/*	 * Set the rom bank to 1 and determine	 * the other signals.	 */	write_brdctl(ahc, BRDDAT5);	/*	 * Now read the state of the external	 * connectors.  BRDDAT6 is EXT68 and	 * BRDDAT7 is EPROMPS.	 */	brdctl = read_brdctl(ahc);	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;	*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;}static voidaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,		     int *externalcable_present, int *eeprom_present){

⌨️ 快捷键说明

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