brintos

brintos / linux-shallow public Read only

0
0
Text · 26.8 KiB · 5fad41b Raw
1005 lines · c
1/*2 * Product specific probe and attach routines for:3 *	aic7901 and aic7902 SCSI controllers4 *5 * Copyright (c) 1994-2001 Justin T. Gibbs.6 * Copyright (c) 2000-2002 Adaptec Inc.7 * All rights reserved.8 *9 * Redistribution and use in source and binary forms, with or without10 * modification, are permitted provided that the following conditions11 * are met:12 * 1. Redistributions of source code must retain the above copyright13 *    notice, this list of conditions, and the following disclaimer,14 *    without modification.15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer16 *    substantially similar to the "NO WARRANTY" disclaimer below17 *    ("Disclaimer") and any redistribution must be conditioned upon18 *    including a substantially similar Disclaimer requirement for further19 *    binary redistribution.20 * 3. Neither the names of the above-listed copyright holders nor the names21 *    of any contributors may be used to endorse or promote products derived22 *    from this software without specific prior written permission.23 *24 * Alternatively, this software may be distributed under the terms of the25 * GNU General Public License ("GPL") version 2 as published by the Free26 * Software Foundation.27 *28 * NO WARRANTY29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT33 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING38 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE39 * POSSIBILITY OF SUCH DAMAGES.40 *41 * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#92 $42 */43 44#include "aic79xx_osm.h"45#include "aic79xx_inline.h"46#include "aic79xx_pci.h"47 48static inline uint64_t49ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)50{51	uint64_t id;52 53	id = subvendor54	   | (subdevice << 16)55	   | ((uint64_t)vendor << 32)56	   | ((uint64_t)device << 48);57 58	return (id);59}60 61#define ID_AIC7902_PCI_REV_A4		0x362#define ID_AIC7902_PCI_REV_B0		0x1063#define SUBID_HP			0x0E1164 65#define DEVID_9005_HOSTRAID(id) ((id) & 0x80)66 67#define DEVID_9005_TYPE(id) ((id) & 0xF)68#define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */69#define		DEVID_9005_TYPE_HBA_2EXT	0x1	/* 2 External Ports */70#define		DEVID_9005_TYPE_IROC		0x8	/* Raid(0,1,10) Card */71#define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */72 73#define DEVID_9005_MFUNC(id) ((id) & 0x10)74 75#define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)76 77#define SUBID_9005_TYPE(id) ((id) & 0xF)78#define		SUBID_9005_TYPE_HBA		0x0	/* Standard Card */79#define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */80 81#define SUBID_9005_AUTOTERM(id)	(((id) & 0x10) == 0)82 83#define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)84 85#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6)86#define		SUBID_9005_SEEPTYPE_NONE	0x087#define		SUBID_9005_SEEPTYPE_4K		0x188 89static ahd_device_setup_t ahd_aic7901_setup;90static ahd_device_setup_t ahd_aic7901A_setup;91static ahd_device_setup_t ahd_aic7902_setup;92static ahd_device_setup_t ahd_aic790X_setup;93 94static const struct ahd_pci_identity ahd_pci_ident_table[] =95{96	/* aic7901 based controllers */97	{98		ID_AHA_29320A,99		ID_ALL_MASK,100		"Adaptec 29320A Ultra320 SCSI adapter",101		ahd_aic7901_setup102	},103	{104		ID_AHA_29320ALP,105		ID_ALL_MASK,106		"Adaptec 29320ALP PCIx Ultra320 SCSI adapter",107		ahd_aic7901_setup108	},109	{110		ID_AHA_29320LPE,111		ID_ALL_MASK,112		"Adaptec 29320LPE PCIe Ultra320 SCSI adapter",113		ahd_aic7901_setup114	},115	/* aic7901A based controllers */116	{117		ID_AHA_29320LP,118		ID_ALL_MASK,119		"Adaptec 29320LP Ultra320 SCSI adapter",120		ahd_aic7901A_setup121	},122	/* aic7902 based controllers */	123	{124		ID_AHA_29320,125		ID_ALL_MASK,126		"Adaptec 29320 Ultra320 SCSI adapter",127		ahd_aic7902_setup128	},129	{130		ID_AHA_29320B,131		ID_ALL_MASK,132		"Adaptec 29320B Ultra320 SCSI adapter",133		ahd_aic7902_setup134	},135	{136		ID_AHA_39320,137		ID_ALL_MASK,138		"Adaptec 39320 Ultra320 SCSI adapter",139		ahd_aic7902_setup140	},141	{142		ID_AHA_39320_B,143		ID_ALL_MASK,144		"Adaptec 39320 Ultra320 SCSI adapter",145		ahd_aic7902_setup146	},147	{148		ID_AHA_39320_B_DELL,149		ID_ALL_MASK,150		"Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",151		ahd_aic7902_setup152	},153	{154		ID_AHA_39320A,155		ID_ALL_MASK,156		"Adaptec 39320A Ultra320 SCSI adapter",157		ahd_aic7902_setup158	},159	{160		ID_AHA_39320D,161		ID_ALL_MASK,162		"Adaptec 39320D Ultra320 SCSI adapter",163		ahd_aic7902_setup164	},165	{166		ID_AHA_39320D_HP,167		ID_ALL_MASK,168		"Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",169		ahd_aic7902_setup170	},171	{172		ID_AHA_39320D_B,173		ID_ALL_MASK,174		"Adaptec 39320D Ultra320 SCSI adapter",175		ahd_aic7902_setup176	},177	{178		ID_AHA_39320D_B_HP,179		ID_ALL_MASK,180		"Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",181		ahd_aic7902_setup182	},183	/* Generic chip probes for devices we don't know 'exactly' */184	{185		ID_AIC7901 & ID_9005_GENERIC_MASK,186		ID_9005_GENERIC_MASK,187		"Adaptec AIC7901 Ultra320 SCSI adapter",188		ahd_aic7901_setup189	},190	{191		ID_AIC7901A & ID_DEV_VENDOR_MASK,192		ID_DEV_VENDOR_MASK,193		"Adaptec AIC7901A Ultra320 SCSI adapter",194		ahd_aic7901A_setup195	},196	{197		ID_AIC7902 & ID_9005_GENERIC_MASK,198		ID_9005_GENERIC_MASK,199		"Adaptec AIC7902 Ultra320 SCSI adapter",200		ahd_aic7902_setup201	}202};203 204static const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table);205		206#define	DEVCONFIG		0x40207#define		PCIXINITPAT	0x0000E000ul208#define			PCIXINIT_PCI33_66	0x0000E000ul209#define			PCIXINIT_PCIX50_66	0x0000C000ul210#define			PCIXINIT_PCIX66_100	0x0000A000ul211#define			PCIXINIT_PCIX100_133	0x00008000ul212#define	PCI_BUS_MODES_INDEX(devconfig)	\213	(((devconfig) & PCIXINITPAT) >> 13)214static const char *pci_bus_modes[] =215{216	"PCI bus mode unknown",217	"PCI bus mode unknown",218	"PCI bus mode unknown",219	"PCI bus mode unknown",220	"PCI-X 101-133MHz",221	"PCI-X 67-100MHz",222	"PCI-X 50-66MHz",223	"PCI 33 or 66MHz"224};225 226#define		TESTMODE	0x00000800ul227#define		IRDY_RST	0x00000200ul228#define		FRAME_RST	0x00000100ul229#define		PCI64BIT	0x00000080ul230#define		MRDCEN		0x00000040ul231#define		ENDIANSEL	0x00000020ul232#define		MIXQWENDIANEN	0x00000008ul233#define		DACEN		0x00000004ul234#define		STPWLEVEL	0x00000002ul235#define		QWENDIANSEL	0x00000001ul236 237#define	DEVCONFIG1		0x44238#define		PREQDIS		0x01239 240#define	CSIZE_LATTIME		0x0c241#define		CACHESIZE	0x000000fful242#define		LATTIME		0x0000ff00ul243 244static int	ahd_check_extport(struct ahd_softc *ahd);245static void	ahd_configure_termination(struct ahd_softc *ahd,246					  u_int adapter_control);247static void	ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);248static void	ahd_pci_intr(struct ahd_softc *ahd);249 250const struct ahd_pci_identity *251ahd_find_pci_device(ahd_dev_softc_t pci)252{253	uint64_t  full_id;254	uint16_t  device;255	uint16_t  vendor;256	uint16_t  subdevice;257	uint16_t  subvendor;258	const struct ahd_pci_identity *entry;259	u_int	  i;260 261	vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);262	device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);263	subvendor = ahd_pci_read_config(pci, PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);264	subdevice = ahd_pci_read_config(pci, PCI_SUBSYSTEM_ID, /*bytes*/2);265	full_id = ahd_compose_id(device,266				 vendor,267				 subdevice,268				 subvendor);269 270	/*271	 * Controllers, mask out the IROC/HostRAID bit272	 */273	274	full_id &= ID_ALL_IROC_MASK;275 276	for (i = 0; i < ahd_num_pci_devs; i++) {277		entry = &ahd_pci_ident_table[i];278		if (entry->full_id == (full_id & entry->id_mask)) {279			/* Honor exclusion entries. */280			if (entry->name == NULL)281				return (NULL);282			return (entry);283		}284	}285	return (NULL);286}287 288int289ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)290{291	u_int		 command;292	uint32_t	 devconfig;293	uint16_t	 subvendor; 294	int		 error;295 296	ahd->description = entry->name;297	/*298	 * Record if this is an HP board.299	 */300	subvendor = ahd_pci_read_config(ahd->dev_softc,301					PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2);302	if (subvendor == SUBID_HP)303		ahd->flags |= AHD_HP_BOARD;304 305	error = entry->setup(ahd);306	if (error != 0)307		return (error);308	309	devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);310	if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {311		ahd->chip |= AHD_PCI;312		/* Disable PCIX workarounds when running in PCI mode. */313		ahd->bugs &= ~AHD_PCIX_BUG_MASK;314	} else {315		ahd->chip |= AHD_PCIX;316	}317	ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];318 319	ahd_power_state_change(ahd, AHD_POWER_STATE_D0);320 321	error = ahd_pci_map_registers(ahd);322	if (error != 0)323		return (error);324 325	/*326	 * If we need to support high memory, enable dual327	 * address cycles.  This bit must be set to enable328	 * high address bit generation even if we are on a329	 * 64bit bus (PCI64BIT set in devconfig).330	 */331	if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {332		if (bootverbose)333			printk("%s: Enabling 39Bit Addressing\n",334			       ahd_name(ahd));335		devconfig = ahd_pci_read_config(ahd->dev_softc,336						DEVCONFIG, /*bytes*/4);337		devconfig |= DACEN;338		ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,339				     devconfig, /*bytes*/4);340	}341	342	/* Ensure busmastering is enabled */343	command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);344	command |= PCIM_CMD_BUSMASTEREN;345	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2);346 347	error = ahd_softc_init(ahd);348	if (error != 0)349		return (error);350 351	ahd->bus_intr = ahd_pci_intr;352 353	error = ahd_reset(ahd, /*reinit*/FALSE);354	if (error != 0)355		return (ENXIO);356 357	ahd->pci_cachesize =358	    ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME,359				/*bytes*/1) & CACHESIZE;360	ahd->pci_cachesize *= 4;361 362	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);363	/* See if we have a SEEPROM and perform auto-term */364	error = ahd_check_extport(ahd);365	if (error != 0)366		return (error);367 368	/* Core initialization */369	error = ahd_init(ahd);370	if (error != 0)371		return (error);372	ahd->init_level++;373 374	/*375	 * Allow interrupts now that we are completely setup.376	 */377	return ahd_pci_map_int(ahd);378}379 380void __maybe_unused381ahd_pci_suspend(struct ahd_softc *ahd)382{383	/*384	 * Save chip register configuration data for chip resets385	 * that occur during runtime and resume events.386	 */387	ahd->suspend_state.pci_state.devconfig =388	    ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);389	ahd->suspend_state.pci_state.command =390	    ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);391	ahd->suspend_state.pci_state.csize_lattime =392	    ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);393 394}395 396void __maybe_unused397ahd_pci_resume(struct ahd_softc *ahd)398{399	ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,400			     ahd->suspend_state.pci_state.devconfig, /*bytes*/4);401	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,402			     ahd->suspend_state.pci_state.command, /*bytes*/1);403	ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,404			     ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);405}406 407/*408 * Perform some simple tests that should catch situations where409 * our registers are invalidly mapped.410 */411int412ahd_pci_test_register_access(struct ahd_softc *ahd)413{414	uint32_t cmd;415	u_int	 targpcistat;416	u_int	 pci_status1;417	int	 error;418	uint8_t	 hcntrl;419 420	error = EIO;421 422	/*423	 * Enable PCI error interrupt status, but suppress NMIs424	 * generated by SERR raised due to target aborts.425	 */426	cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);427	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,428			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);429 430	/*431	 * First a simple test to see if any432	 * registers can be read.  Reading433	 * HCNTRL has no side effects and has434	 * at least one bit that is guaranteed to435	 * be zero so it is a good register to436	 * use for this test.437	 */438	hcntrl = ahd_inb(ahd, HCNTRL);439	if (hcntrl == 0xFF)440		goto fail;441 442	/*443	 * Next create a situation where write combining444	 * or read prefetching could be initiated by the445	 * CPU or host bridge.  Our device does not support446	 * either, so look for data corruption and/or flaged447	 * PCI errors.  First pause without causing another448	 * chip reset.449	 */450	hcntrl &= ~CHIPRST;451	ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);452	while (ahd_is_paused(ahd) == 0)453		;454 455	/* Clear any PCI errors that occurred before our driver attached. */456	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);457	targpcistat = ahd_inb(ahd, TARGPCISTAT);458	ahd_outb(ahd, TARGPCISTAT, targpcistat);459	pci_status1 = ahd_pci_read_config(ahd->dev_softc,460					  PCIR_STATUS + 1, /*bytes*/1);461	ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,462			     pci_status1, /*bytes*/1);463	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);464	ahd_outb(ahd, CLRINT, CLRPCIINT);465 466	ahd_outb(ahd, SEQCTL0, PERRORDIS);467	ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);468	if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)469		goto fail;470 471	if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {472		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);473		targpcistat = ahd_inb(ahd, TARGPCISTAT);474		if ((targpcistat & STA) != 0)475			goto fail;476	}477 478	error = 0;479 480fail:481	if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {482 483		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);484		targpcistat = ahd_inb(ahd, TARGPCISTAT);485 486		/* Silently clear any latched errors. */487		ahd_outb(ahd, TARGPCISTAT, targpcistat);488		pci_status1 = ahd_pci_read_config(ahd->dev_softc,489						  PCIR_STATUS + 1, /*bytes*/1);490		ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,491				     pci_status1, /*bytes*/1);492		ahd_outb(ahd, CLRINT, CLRPCIINT);493	}494	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);495	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);496	return (error);497}498 499/*500 * Check the external port logic for a serial eeprom501 * and termination/cable detection contrls.502 */503static int504ahd_check_extport(struct ahd_softc *ahd)505{506	struct	vpd_config vpd;507	struct	seeprom_config *sc;508	u_int	adapter_control;509	int	have_seeprom;510	int	error;511 512	sc = ahd->seep_config;513	have_seeprom = ahd_acquire_seeprom(ahd);514	if (have_seeprom) {515		u_int start_addr;516 517		/*518		 * Fetch VPD for this function and parse it.519		 */520		if (bootverbose) 521			printk("%s: Reading VPD from SEEPROM...",522			       ahd_name(ahd));523 524		/* Address is always in units of 16bit words */525		start_addr = ((2 * sizeof(*sc))526			    + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;527 528		error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,529					 start_addr, sizeof(vpd)/2,530					 /*bytestream*/TRUE);531		if (error == 0)532			error = ahd_parse_vpddata(ahd, &vpd);533		if (bootverbose) 534			printk("%s: VPD parsing %s\n",535			       ahd_name(ahd),536			       error == 0 ? "successful" : "failed");537 538		if (bootverbose) 539			printk("%s: Reading SEEPROM...", ahd_name(ahd));540 541		/* Address is always in units of 16bit words */542		start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');543 544		error = ahd_read_seeprom(ahd, (uint16_t *)sc,545					 start_addr, sizeof(*sc)/2,546					 /*bytestream*/FALSE);547 548		if (error != 0) {549			printk("Unable to read SEEPROM\n");550			have_seeprom = 0;551		} else {552			have_seeprom = ahd_verify_cksum(sc);553 554			if (bootverbose) {555				if (have_seeprom == 0)556					printk ("checksum error\n");557				else558					printk ("done.\n");559			}560		}561		ahd_release_seeprom(ahd);562	}563 564	if (!have_seeprom) {565		u_int	  nvram_scb;566 567		/*568		 * Pull scratch ram settings and treat them as569		 * if they are the contents of an seeprom if570		 * the 'ADPT', 'BIOS', or 'ASPI' signature is found571		 * in SCB 0xFF.  We manually compose the data as 16bit572		 * values to avoid endian issues.573		 */574		ahd_set_scbptr(ahd, 0xFF);575		nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);576		if (nvram_scb != 0xFF577		 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'578		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'579		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'580		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')581		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'582		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'583		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'584		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')585		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'586		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'587		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'588		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {589			uint16_t *sc_data;590			int	  i;591 592			ahd_set_scbptr(ahd, nvram_scb);593			sc_data = (uint16_t *)sc;594			for (i = 0; i < 64; i += 2)595				*sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);596			have_seeprom = ahd_verify_cksum(sc);597			if (have_seeprom)598				ahd->flags |= AHD_SCB_CONFIG_USED;599		}600	}601 602#ifdef AHD_DEBUG603	if (have_seeprom != 0604	 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {605		uint16_t *sc_data;606		int	  i;607 608		printk("%s: Seeprom Contents:", ahd_name(ahd));609		sc_data = (uint16_t *)sc;610		for (i = 0; i < (sizeof(*sc)); i += 2)611			printk("\n\t0x%.4x", sc_data[i]);612		printk("\n");613	}614#endif615 616	if (!have_seeprom) {617		if (bootverbose)618			printk("%s: No SEEPROM available.\n", ahd_name(ahd));619		ahd->flags |= AHD_USEDEFAULTS;620		error = ahd_default_config(ahd);621		adapter_control = CFAUTOTERM|CFSEAUTOTERM;622		kfree(ahd->seep_config);623		ahd->seep_config = NULL;624	} else {625		error = ahd_parse_cfgdata(ahd, sc);626		adapter_control = sc->adapter_control;627	}628	if (error != 0)629		return (error);630 631	ahd_configure_termination(ahd, adapter_control);632 633	return (0);634}635 636static void637ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)638{639	int	 error;640	u_int	 sxfrctl1;641	uint8_t	 termctl;642	uint32_t devconfig;643 644	devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);645	devconfig &= ~STPWLEVEL;646	if ((ahd->flags & AHD_STPWLEVEL_A) != 0)647		devconfig |= STPWLEVEL;648	if (bootverbose)649		printk("%s: STPWLEVEL is %s\n",650		       ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");651	ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);652 653	/* Make sure current sensing is off. */654	if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {655		(void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);656	}657 658	/*659	 * Read to sense.  Write to set.660	 */661	error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);662	if ((adapter_control & CFAUTOTERM) == 0) {663		if (bootverbose)664			printk("%s: Manual Primary Termination\n",665			       ahd_name(ahd));666		termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);667		if ((adapter_control & CFSTERM) != 0)668			termctl |= FLX_TERMCTL_ENPRILOW;669		if ((adapter_control & CFWSTERM) != 0)670			termctl |= FLX_TERMCTL_ENPRIHIGH;671	} else if (error != 0) {672		printk("%s: Primary Auto-Term Sensing failed! "673		       "Using Defaults.\n", ahd_name(ahd));674		termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;675	}676 677	if ((adapter_control & CFSEAUTOTERM) == 0) {678		if (bootverbose)679			printk("%s: Manual Secondary Termination\n",680			       ahd_name(ahd));681		termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);682		if ((adapter_control & CFSELOWTERM) != 0)683			termctl |= FLX_TERMCTL_ENSECLOW;684		if ((adapter_control & CFSEHIGHTERM) != 0)685			termctl |= FLX_TERMCTL_ENSECHIGH;686	} else if (error != 0) {687		printk("%s: Secondary Auto-Term Sensing failed! "688		       "Using Defaults.\n", ahd_name(ahd));689		termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;690	}691 692	/*693	 * Now set the termination based on what we found.694	 */695	sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;696	ahd->flags &= ~AHD_TERM_ENB_A;697	if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {698		ahd->flags |= AHD_TERM_ENB_A;699		sxfrctl1 |= STPWEN;700	}701	/* Must set the latch once in order to be effective. */702	ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);703	ahd_outb(ahd, SXFRCTL1, sxfrctl1);704 705	error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);706	if (error != 0) {707		printk("%s: Unable to set termination settings!\n",708		       ahd_name(ahd));709	} else if (bootverbose) {710		printk("%s: Primary High byte termination %sabled\n",711		       ahd_name(ahd),712		       (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");713 714		printk("%s: Primary Low byte termination %sabled\n",715		       ahd_name(ahd),716		       (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");717 718		printk("%s: Secondary High byte termination %sabled\n",719		       ahd_name(ahd),720		       (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");721 722		printk("%s: Secondary Low byte termination %sabled\n",723		       ahd_name(ahd),724		       (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");725	}726	return;727}728 729#define	DPE	0x80730#define SSE	0x40731#define	RMA	0x20732#define	RTA	0x10733#define STA	0x08734#define DPR	0x01735 736static const char *split_status_source[] =737{738	"DFF0",739	"DFF1",740	"OVLY",741	"CMC",742};743 744static const char *pci_status_source[] =745{746	"DFF0",747	"DFF1",748	"SG",749	"CMC",750	"OVLY",751	"NONE",752	"MSI",753	"TARG"754};755 756static const char *split_status_strings[] =757{758	"%s: Received split response in %s.\n",759	"%s: Received split completion error message in %s\n",760	"%s: Receive overrun in %s\n",761	"%s: Count not complete in %s\n",762	"%s: Split completion data bucket in %s\n",763	"%s: Split completion address error in %s\n",764	"%s: Split completion byte count error in %s\n",765	"%s: Signaled Target-abort to early terminate a split in %s\n"766};767 768static const char *pci_status_strings[] =769{770	"%s: Data Parity Error has been reported via PERR# in %s\n",771	"%s: Target initial wait state error in %s\n",772	"%s: Split completion read data parity error in %s\n",773	"%s: Split completion address attribute parity error in %s\n",774	"%s: Received a Target Abort in %s\n",775	"%s: Received a Master Abort in %s\n",776	"%s: Signal System Error Detected in %s\n",777	"%s: Address or Write Phase Parity Error Detected in %s.\n"778};779 780static void781ahd_pci_intr(struct ahd_softc *ahd)782{783	uint8_t		pci_status[8];784	ahd_mode_state	saved_modes;785	u_int		pci_status1;786	u_int		intstat;787	u_int		i;788	u_int		reg;789	790	intstat = ahd_inb(ahd, INTSTAT);791 792	if ((intstat & SPLTINT) != 0)793		ahd_pci_split_intr(ahd, intstat);794 795	if ((intstat & PCIINT) == 0)796		return;797 798	printk("%s: PCI error Interrupt\n", ahd_name(ahd));799	saved_modes = ahd_save_modes(ahd);800	ahd_dump_card_state(ahd);801	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);802	for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {803 804		if (i == 5)805			continue;806		pci_status[i] = ahd_inb(ahd, reg);807		/* Clear latched errors.  So our interrupt deasserts. */808		ahd_outb(ahd, reg, pci_status[i]);809	}810 811	for (i = 0; i < 8; i++) {812		u_int bit;813	814		if (i == 5)815			continue;816 817		for (bit = 0; bit < 8; bit++) {818 819			if ((pci_status[i] & (0x1 << bit)) != 0) {820				const char *s;821 822				s = pci_status_strings[bit];823				if (i == 7/*TARG*/ && bit == 3)824					s = "%s: Signaled Target Abort\n";825				printk(s, ahd_name(ahd), pci_status_source[i]);826			}827		}	828	}829	pci_status1 = ahd_pci_read_config(ahd->dev_softc,830					  PCIR_STATUS + 1, /*bytes*/1);831	ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,832			     pci_status1, /*bytes*/1);833	ahd_restore_modes(ahd, saved_modes);834	ahd_outb(ahd, CLRINT, CLRPCIINT);835	ahd_unpause(ahd);836}837 838static void839ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)840{841	uint8_t		split_status[4];842	uint8_t		split_status1[4];843	uint8_t		sg_split_status[2];844	uint8_t		sg_split_status1[2];845	ahd_mode_state	saved_modes;846	u_int		i;847	uint16_t	pcix_status;848 849	/*850	 * Check for splits in all modes.  Modes 0 and 1851	 * additionally have SG engine splits to look at.852	 */853	pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS,854					  /*bytes*/2);855	printk("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",856	       ahd_name(ahd), pcix_status);857	saved_modes = ahd_save_modes(ahd);858	for (i = 0; i < 4; i++) {859		ahd_set_modes(ahd, i, i);860 861		split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);862		split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);863		/* Clear latched errors.  So our interrupt deasserts. */864		ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);865		ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);866		if (i > 1)867			continue;868		sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);869		sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);870		/* Clear latched errors.  So our interrupt deasserts. */871		ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);872		ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);873	}874 875	for (i = 0; i < 4; i++) {876		u_int bit;877 878		for (bit = 0; bit < 8; bit++) {879 880			if ((split_status[i] & (0x1 << bit)) != 0)881				printk(split_status_strings[bit], ahd_name(ahd),882				       split_status_source[i]);883 884			if (i > 1)885				continue;886 887			if ((sg_split_status[i] & (0x1 << bit)) != 0)888				printk(split_status_strings[bit], ahd_name(ahd), "SG");889		}890	}891	/*892	 * Clear PCI-X status bits.893	 */894	ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS,895			     pcix_status, /*bytes*/2);896	ahd_outb(ahd, CLRINT, CLRSPLTINT);897	ahd_restore_modes(ahd, saved_modes);898}899 900static int901ahd_aic7901_setup(struct ahd_softc *ahd)902{903 904	ahd->chip = AHD_AIC7901;905	ahd->features = AHD_AIC7901_FE;906	return (ahd_aic790X_setup(ahd));907}908 909static int910ahd_aic7901A_setup(struct ahd_softc *ahd)911{912 913	ahd->chip = AHD_AIC7901A;914	ahd->features = AHD_AIC7901A_FE;915	return (ahd_aic790X_setup(ahd));916}917 918static int919ahd_aic7902_setup(struct ahd_softc *ahd)920{921	ahd->chip = AHD_AIC7902;922	ahd->features = AHD_AIC7902_FE;923	return (ahd_aic790X_setup(ahd));924}925 926static int927ahd_aic790X_setup(struct ahd_softc *ahd)928{929	ahd_dev_softc_t pci;930	u_int rev;931 932	pci = ahd->dev_softc;933	rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1);934	if (rev < ID_AIC7902_PCI_REV_A4) {935		printk("%s: Unable to attach to unsupported chip revision %d\n",936		       ahd_name(ahd), rev);937		ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);938		return (ENXIO);939	}940	ahd->channel = ahd_get_pci_function(pci) + 'A';941	if (rev < ID_AIC7902_PCI_REV_B0) {942		/*943		 * Enable A series workarounds.944		 */945		ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG946			  |  AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG947			  |  AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG948			  |  AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG949			  |  AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG950			  |  AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG951			  |  AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG952			  |  AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG953			  |  AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG954			  |  AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG955			  |  AHD_FAINT_LED_BUG;956 957		/*958		 * IO Cell parameter setup.959		 */960		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);961 962		if ((ahd->flags & AHD_HP_BOARD) == 0)963			AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);964	} else {965		/* This is revision B and newer. */966		extern uint32_t aic79xx_slowcrc;967		u_int devconfig1;968 969		ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS970			      |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY971			      |  AHD_BUSFREEREV_BUG;972		ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;973 974		/* If the user requested that the SLOWCRC bit to be set. */975		if (aic79xx_slowcrc)976			ahd->features |= AHD_AIC79XXB_SLOWCRC;977 978		/*979		 * Some issues have been resolved in the 7901B.980		 */981		if ((ahd->features & AHD_MULTI_FUNC) != 0)982			ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;983 984		/*985		 * IO Cell parameter setup.986		 */987		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);988		AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);989		AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);990 991		/*992		 * Set the PREQDIS bit for H2B which disables some workaround993		 * that doesn't work on regular PCI busses.994		 * XXX - Find out exactly what this does from the hardware995		 * 	 folks!996		 */997		devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);998		ahd_pci_write_config(pci, DEVCONFIG1,999				     devconfig1|PREQDIS, /*bytes*/1);1000		devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);1001	}1002 1003	return (0);1004}1005