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

📄 aic7xxx_pci.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
static void ahc_parse_pci_eeprom(struct ahc_softc *ahc,				 struct seeprom_config *sc);static void configure_termination(struct ahc_softc *ahc,				  struct seeprom_descriptor *sd,				  u_int adapter_control,	 			  u_int *sxfrctl1);static void ahc_new_term_detect(struct ahc_softc *ahc,				int *enableSEC_low,				int *enableSEC_high,				int *enablePRI_low,				int *enablePRI_high,				int *eeprom_present);static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,				 int *internal68_present,				 int *externalcable_present,				 int *eeprom_present);static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,				 int *externalcable_present,				 int *eeprom_present);static void    write_brdctl(struct ahc_softc *ahc, uint8_t value);static uint8_t read_brdctl(struct ahc_softc *ahc);static void ahc_pci_intr(struct ahc_softc *ahc);static int  ahc_pci_chip_init(struct ahc_softc *ahc);static int  ahc_pci_suspend(struct ahc_softc *ahc);static int  ahc_pci_resume(struct ahc_softc *ahc);static intahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,			  uint16_t subdevice, uint16_t subvendor){	int result;	/* Default to invalid. */	result = 0;	if (vendor == 0x9005	 && subvendor == 0x9005         && subdevice != device         && SUBID_9005_TYPE_KNOWN(subdevice) != 0) {		switch (SUBID_9005_TYPE(subdevice)) {		case SUBID_9005_TYPE_MB:			break;		case SUBID_9005_TYPE_CARD:		case SUBID_9005_TYPE_LCCARD:			/*			 * Currently only trust Adaptec cards to			 * get the sub device info correct.			 */			if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)				result = 1;			break;		case SUBID_9005_TYPE_RAID:			break;		default:			break;		}	}	return (result);}struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t pci){	uint64_t  full_id;	uint16_t  device;	uint16_t  vendor;	uint16_t  subdevice;	uint16_t  subvendor;	struct	  ahc_pci_identity *entry;	u_int	  i;	vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);	device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);	subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);	subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);	full_id = ahc_compose_id(device, vendor, subdevice, subvendor);	/*	 * If the second function is not hooked up, ignore it.	 * Unfortunately, not all MB vendors implement the	 * subdevice ID as per the Adaptec spec, so do our best	 * to sanity check it prior to accepting the subdevice	 * ID as valid.	 */	if (ahc_get_pci_function(pci) > 0	 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice)	 && SUBID_9005_MFUNCENB(subdevice) == 0)		return (NULL);	for (i = 0; i < ahc_num_pci_devs; i++) {		entry = &ahc_pci_ident_table[i];		if (entry->full_id == (full_id & entry->id_mask)) {			/* Honor exclusion entries. */			if (entry->name == NULL)				return (NULL);			return (entry);		}	}	return (NULL);}intahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry){	u_int	 command;	u_int	 our_id;	u_int	 sxfrctl1;	u_int	 scsiseq;	u_int	 dscommand0;	uint32_t devconfig;	int	 error;	uint8_t	 sblkctl;	our_id = 0;	error = entry->setup(ahc);	if (error != 0)		return (error);	ahc->chip |= AHC_PCI;	ahc->description = entry->name;	pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);	error = ahc_pci_map_registers(ahc);	if (error != 0)		return (error);	/*	 * Before we continue probing the card, ensure that	 * its interrupts are *disabled*.  We don't want	 * a misstep to hang the machine in an interrupt	 * storm.	 */	ahc_intr_enable(ahc, FALSE);	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);	/*	 * If we need to support high memory, enable dual	 * address cycles.  This bit must be set to enable	 * high address bit generation even if we are on a	 * 64bit bus (PCI64BIT set in devconfig).	 */	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {		if (bootverbose)			printf("%s: Enabling 39Bit Addressing\n",			       ahc_name(ahc));		devconfig |= DACEN;	}		/* Ensure that pci error generation, a test feature, is disabled. */	devconfig |= PCIERRGENDIS;	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);	/* Ensure busmastering is enabled */	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);	command |= PCIM_CMD_BUSMASTEREN;	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);	/* On all PCI adapters, we allow SCB paging */	ahc->flags |= AHC_PAGESCBS;	error = ahc_softc_init(ahc);	if (error != 0)		return (error);	/*	 * Disable PCI parity error checking.  Users typically	 * do this to work around broken PCI chipsets that get	 * the parity timing wrong and thus generate lots of spurious	 * errors.  The chip only allows us to disable *all* parity	 * error reporting when doing this, so CIO bus, scb ram, and	 * scratch ram parity errors will be ignored too.	 */	if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)		ahc->seqctl |= FAILDIS;	ahc->bus_intr = ahc_pci_intr;	ahc->bus_chip_init = ahc_pci_chip_init;	ahc->bus_suspend = ahc_pci_suspend;	ahc->bus_resume = ahc_pci_resume;	/* Remeber how the card was setup in case there is no SEEPROM */	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {		ahc_pause(ahc);		if ((ahc->features & AHC_ULTRA2) != 0)			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;		else			our_id = ahc_inb(ahc, SCSIID) & OID;		sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;		scsiseq = ahc_inb(ahc, SCSISEQ);	} else {		sxfrctl1 = STPWEN;		our_id = 7;		scsiseq = 0;	}	error = ahc_reset(ahc, /*reinit*/FALSE);	if (error != 0)		return (ENXIO);	if ((ahc->features & AHC_DT) != 0) {		u_int sfunct;		/* Perform ALT-Mode Setup */		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);		ahc_outb(ahc, OPTIONMODE,			 OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);		ahc_outb(ahc, SFUNCT, sfunct);		/* Normal mode setup */		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN					  |TARGCRCENDEN);	}	dscommand0 = ahc_inb(ahc, DSCOMMAND0);	dscommand0 |= MPARCKEN|CACHETHEN;	if ((ahc->features & AHC_ULTRA2) != 0) {		/*		 * DPARCKEN doesn't work correctly on		 * some MBs so don't use it.		 */		dscommand0 &= ~DPARCKEN;	}	/*	 * Handle chips that must have cache line	 * streaming (dis/en)abled.	 */	if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)		dscommand0 |= CACHETHEN;	if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)		dscommand0 &= ~CACHETHEN;	ahc_outb(ahc, DSCOMMAND0, dscommand0);	ahc->pci_cachesize =	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,				/*bytes*/1) & CACHESIZE;	ahc->pci_cachesize *= 4;	if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0	 && ahc->pci_cachesize == 4) {		ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,				     0, /*bytes*/1);		ahc->pci_cachesize = 0;	}	/*	 * We cannot perform ULTRA speeds without the presense	 * of the external precision resistor.	 */	if ((ahc->features & AHC_ULTRA) != 0) {		uint32_t devconfig;		devconfig = ahc_pci_read_config(ahc->dev_softc,						DEVCONFIG, /*bytes*/4);		if ((devconfig & REXTVALID) == 0)			ahc->features &= ~AHC_ULTRA;	}	/* See if we have a SEEPROM and perform auto-term */	check_extport(ahc, &sxfrctl1);	/*	 * Take the LED out of diagnostic mode	 */	sblkctl = ahc_inb(ahc, SBLKCTL);	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));	if ((ahc->features & AHC_ULTRA2) != 0) {		ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX);	} else {		ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);	}	if (ahc->flags & AHC_USEDEFAULTS) {		/*		 * PCI Adapter default setup		 * Should only be used if the adapter does not have		 * a SEEPROM.		 */		/* See if someone else set us up already */		if ((ahc->flags & AHC_NO_BIOS_INIT) == 0		 && scsiseq != 0) {			printf("%s: Using left over BIOS settings\n",				ahc_name(ahc));			ahc->flags &= ~AHC_USEDEFAULTS;			ahc->flags |= AHC_BIOS_ENABLED;		} else {			/*			 * Assume only one connector and always turn			 * on termination.			 */ 			our_id = 0x07;			sxfrctl1 = STPWEN;		}		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);		ahc->our_id = our_id;	}	/*	 * Take a look to see if we have external SRAM.	 * We currently do not attempt to use SRAM that is	 * shared among multiple controllers.	 */	ahc_probe_ext_scbram(ahc);	/*	 * Record our termination setting for the	 * generic initialization routine.	 */	if ((sxfrctl1 & STPWEN) != 0)		ahc->flags |= AHC_TERM_ENB_A;	/*	 * Save chip register configuration data for chip resets	 * that occur during runtime and resume events.	 */	ahc->bus_softc.pci_softc.devconfig =	    ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);	ahc->bus_softc.pci_softc.command =	    ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);	ahc->bus_softc.pci_softc.csize_lattime =	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);	if ((ahc->features & AHC_DT) != 0) {		u_int sfunct;		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);		ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);		ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);		ahc_outb(ahc, SFUNCT, sfunct);		ahc->bus_softc.pci_softc.crccontrol1 =		    ahc_inb(ahc, CRCCONTROL1);	}	if ((ahc->features & AHC_MULTI_FUNC) != 0)		ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);	if ((ahc->features & AHC_ULTRA2) != 0)		ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);	/* Core initialization */	error = ahc_init(ahc);	if (error != 0)		return (error);	/*	 * Allow interrupts now that we are completely setup.	 */	error = ahc_pci_map_int(ahc);	if (error != 0)		return (error);	ahc->init_level++;	return (0);}/* * Test for the presense of external sram in an * "unshared" configuration. */static intahc_ext_scbram_present(struct ahc_softc *ahc){	u_int chip;	int ramps;	int single_user;	uint32_t devconfig;	chip = ahc->chip & AHC_CHIPID_MASK;	devconfig = ahc_pci_read_config(ahc->dev_softc,					DEVCONFIG, /*bytes*/4);	single_user = (devconfig & MPORTMODE) != 0;	if ((ahc->features & AHC_ULTRA2) != 0)		ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;	else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C)		/*		 * External SCBRAM arbitration is flakey		 * on these chips.  Unfortunately this means		 * we don't use the extra SCB ram space on the		 * 3940AUW.		 */		ramps = 0;	else if (chip >= AHC_AIC7870)		ramps = (devconfig & RAMPSM) != 0;	else		ramps = 0;	if (ramps && single_user)		return (1);	return (0);}/* * Enable external scbram. */static voidahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,		  int fast, int large){	uint32_t devconfig;	if (ahc->features & AHC_MULTI_FUNC) {		/*		 * Set the SCB Base addr (highest address bit)		 * depending on which channel we are.		 */		ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));	}	ahc->flags &= ~AHC_LSCBS_ENABLED;	if (large)		ahc->flags |= AHC_LSCBS_ENABLED;	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);	if ((ahc->features & AHC_ULTRA2) != 0) {		u_int dscommand0;		dscommand0 = ahc_inb(ahc, DSCOMMAND0);		if (enable)			dscommand0 &= ~INTSCBRAMSEL;		else			dscommand0 |= INTSCBRAMSEL;		if (large)			dscommand0 &= ~USCBSIZE32;		else			dscommand0 |= USCBSIZE32;		ahc_outb(ahc, DSCOMMAND0, dscommand0);	} else {		if (fast)			devconfig &= ~EXTSCBTIME;		else			devconfig |= EXTSCBTIME;		if (enable)			devconfig &= ~SCBRAMSEL;		else			devconfig |= SCBRAMSEL;		if (large)			devconfig &= ~SCBSIZE32;		else			devconfig |= SCBSIZE32;	}	if (pcheck)		devconfig |= EXTSCBPEN;	else		devconfig &= ~EXTSCBPEN;	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);}/* * Take a look to see if we have external SRAM. * We currently do not attempt to use SRAM that is * shared among multiple controllers. */static voidahc_probe_ext_scbram(struct ahc_softc *ahc){	int num_scbs;	int test_num_scbs;	int enable;	int pcheck;	int fast;	int large;	enable = FALSE;	pcheck = FALSE;	fast = FALSE;	large = FALSE;	num_scbs = 0;		if (ahc_ext_scbram_present(ahc) == 0)		goto done;	/*	 * Probe for the best parameters to use.	 */	ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);	num_scbs = ahc_probe_scbs(ahc);	if (num_scbs == 0) {		/* The SRAM wasn't really present. */		goto done;	}	enable = TRUE;	/*	 * Clear any outstanding parity error	 * and ensure that parity error reporting	 * is enabled.	 */	ahc_outb(ahc, SEQCTL, 0);	ahc_outb(ahc, CLRINT, CLRPARERR);	ahc_outb(ahc, CLRINT, CLRBRKADRINT);	/* Now see if we can do parity */	ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);	num_scbs = ahc_probe_scbs(ahc);	if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0	 || (ahc_inb(ahc, ERROR) & MPARERR) == 0)		pcheck = TRUE;	/* Clear any resulting parity error */	ahc_outb(ahc, CLRINT, CLRPARERR);	ahc_outb(ahc, CLRINT, CLRBRKADRINT);	/* Now see if we can do fast timing */	ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);	test_num_scbs = ahc_probe_scbs(ahc);	if (test_num_scbs == num_scbs	 && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0	  || (ahc_inb(ahc, ERROR) & MPARERR) == 0))		fast = TRUE;	/*	 * See if we can use large SCBs and still maintain	 * the same overall count of SCBs.	 */	if ((ahc->features & AHC_LARGE_SCBS) != 0) {		ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);		test_num_scbs = ahc_probe_scbs(ahc);		if (test_num_scbs >= num_scbs) {			large = TRUE;			num_scbs = test_num_scbs;	 		if (num_scbs >= 64) {				/*				 * We have enough space to move the				 * "busy targets table" into SCB space				 * and make it qualify all the way to the				 * lun level.				 */				ahc->flags |= AHC_SCB_BTT;			}		}	}done:	/*	 * Disable parity error reporting until we	 * can load instruction ram.	 */	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);	/* Clear any latched parity error */	ahc_outb(ahc, CLRINT, CLRPARERR);	ahc_outb(ahc, CLRINT, CLRBRKADRINT);	if (bootverbose && enable) {		printf("%s: External SRAM, %s access%s, %dbytes/SCB\n",		       ahc_name(ahc), fast ? "fast" : "slow", 		       pcheck ? ", parity checking enabled" : "",		       large ? 64 : 32);	}	ahc_scbram_config(ahc, enable, pcheck, fast, large);}/* * Perform some simple tests that should catch situations where * our registers are invalidly mapped. */intahc_pci_test_register_access(struct ahc_softc *ahc){	int	 error;	u_int	 status1;	uint32_t cmd;	uint8_t	 hcntrl;	error = EIO;	/*	 * Enable PCI error interrupt status, but suppress NMIs	 * generated by SERR raised due to target aborts.	 */	cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);	/*	 * First a simple test to see if any	 * registers can be read.  Reading	 * HCNTRL has no side effects and has	 * at least one bit that is guaranteed to	 * be zero so it is a good register to	 * use for this test.	 */	hcntrl = ahc_inb(ahc, HCNTRL);	if (hcntrl == 0xFF)		goto fail;	/*	 * Next create a situation where write combining	 * or read prefetching could be initiated by the	 * CPU or host bridge.  Our device does not support

⌨️ 快捷键说明

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