rem: MHCR_MASK_PCI_INT_OUTPUT |
context: bge_chip_cfg_init(bge_t *bgep, chip_id_t *cidp, boolean_t enable_dma){	ddi_acc_handle_t handle;	uint16_t command;	uint32_t mhcr;	uint16_t value16;	int i;	BGE_TRACE(("bge_chip_cfg_init($%p, $%p, %d)",		(void *)bgep, (void *)cidp, enable_dma));	/*	 * Step 3: save PCI cache line size and subsystem vendor ID	 *	 * Read all the config-space registers that characterise the	 * chip, specifically vendor/device/revision/subsystem vendor	 * and subsystem device id.  We expect (but don't check) that	 * (vendor == VENDOR_ID_BROADCOM) && (device == DEVICE_ID_5704)	 *	 * Also save all bus-transation related registers (cache-line	 * size, bus-grant/latency parameters, etc).  Some of these are	 * cleared by reset, so we'll have to restore them later.  This	 * comes from the Broadcom document 570X-PG102-R ...	 *	 * Note: Broadcom document 570X-PG102-R seems to be in error	 * here w.r.t. the offsets of the Subsystem Vendor ID and	 * Subsystem (Device) ID registers, which are the opposite way	 * round according to the PCI standard.  For good measure, we	 * save/restore both anyway.	 */	handle = bgep->cfg_handle;	mhcr = pci_config_get32(handle, PCI_CONF_BGE_MHCR);	cidp->asic_rev = mhcr & MHCR_CHIP_REV_MASK;	cidp->businfo = pci_config_get32(handle, PCI_CONF_BGE_PCISTATE);	cidp->command = pci_config_get16(handle, PCI_CONF_COMM);	cidp->vendor = pci_config_get16(handle, PCI_CONF_VENID);	cidp->device = pci_config_get16(handle, PCI_CONF_DEVID);	cidp->subven = pci_config_get16(handle, PCI_CONF_SUBVENID);	cidp->subdev = pci_config_get16(handle, PCI_CONF_SUBSYSID);	cidp->revision = pci_config_get8(handle, PCI_CONF_REVID);	cidp->clsize = pci_config_get8(handle, PCI_CONF_CACHE_LINESZ);	cidp->latency = pci_config_get8(handle, PCI_CONF_LATENCY_TIMER);	BGE_DEBUG(("bge_chip_cfg_init: %s bus is %s and %s; #INTA is %s",		cidp->businfo & PCISTATE_BUS_IS_PCI ? "PCI" : "PCI-X",		cidp->businfo & PCISTATE_BUS_IS_FAST ? "fast" : "slow",		cidp->businfo & PCISTATE_BUS_IS_32_BIT ? "narrow" : "wide",		cidp->businfo & PCISTATE_INTA_STATE ? "high" : "low"));	BGE_DEBUG(("bge_chip_cfg_init: vendor 0x%x device 0x%x revision 0x%x",		cidp->vendor, cidp->device, cidp->revision));	BGE_DEBUG(("bge_chip_cfg_init: subven 0x%x subdev 0x%x asic_rev 0x%x",		cidp->subven, cidp->subdev, cidp->asic_rev));	BGE_DEBUG(("bge_chip_cfg_init: clsize %d latency %d command 0x%x",		cidp->clsize, cidp->latency, cidp->command));	/*	 * Step 2 (also step 6): disable and clear interrupts.	 * Steps 11-13: configure PIO endianness options, and enable	 * indirect register access.  We'll also select any other	 * options controlled by the MHCR (eg tagged status, mask	 * interrupt mode) at this stage ...	 *	 * Note: internally, the chip is 64-bit and BIG-endian, but	 * since it talks to the host over a (LITTLE-endian) PCI bus,	 * it normally swaps bytes around at the PCI interface.	 * However, the PCI host bridge on SPARC systems normally	 * swaps the byte lanes around too, since SPARCs are also	 * BIG-endian.  So it turns out that on SPARC, the right	 * option is to tell the chip to swap (and the host bridge	 * will swap back again), whereas on x86 we ask the chip	 * NOT to swap, so the natural little-endianness of the	 * PCI bus is assumed.  Then the only thing that doesn't	 * automatically work right is access to an 8-byte register	 * by a little-endian host; but we don't want to set the	 * MHCR_ENABLE_REGISTER_WORD_SWAP bit because then 4-byte	 * accesses don't go where expected ;-(  So we live with	 * that, and perform word-swaps in software in the few cases	 * where a chip register is defined as an 8-byte value --	 * see the code below for details ...	 *	 * Note: the meaning of the 'MASK_INTERRUPT_MODE' bit isn't	 * very clear in the register description in the PRM, but	 * Broadcom document 570X-PG104-R page 248 explains a little	 * more (under "Broadcom Mask Mode").  The bit changes the way	 * the MASK_PCI_INT_OUTPUT bit works: with MASK_INTERRUPT_MODE	 * clear, the chip interprets MASK_PCI_INT_OUTPUT in the same	 * way as the 5700 did, which isn't very convenient.  Setting	 * the MASK_INTERRUPT_MODE bit makes the MASK_PCI_INT_OUTPUT	 * bit do just what its name says -- MASK the PCI #INTA output	 * (i.e. deassert the signal at the pin) leaving all internal	 * state unchanged.  This is much more convenient for our	 * interrupt handler, so we set MASK_INTERRUPT_MODE here.	 *	 * Note: the inconvenient semantics of the interrupt mailbox	 * (nonzero disables and acknowledges/clears the interrupt,	 * zero enables AND CLEARS it) would make race conditions	 * likely in the interrupt handler:	 *	 * (1)	acknowledge & disable interrupts	 * (2)	while (more to do)	 * 		process packets	 * (3)	enable interrupts -- also clears pending	 *	 * If the chip received more packets and internally generated	 * an interrupt between the check at (2) and the mbox write	 * at (3), this interrupt would be lost :-(	 *	 * The best way to avoid this is to use TAGGED STATUS mode,	 * where the chip includes a unique tag in each status block	 * update, and the host, when re-enabling interrupts, passes	 * the last tag it saw back to the chip; then the chip can	 * see whether the host is truly up to date, and regenerate	 * its interrupt if not.	 */	mhcr =	MHCR_ENABLE_INDIRECT_ACCESS |		MHCR_ENABLE_TAGGED_STATUS_MODE |		MHCR_MASK_INTERRUPT_MODE |		MHCR_MASK_PCI_INT_OUTPUT |		MHCR_CLEAR_INTERRUPT_INTA;#ifdef	_BIG_ENDIAN	mhcr |= MHCR_ENABLE_ENDIAN_WORD_SWAP | MHCR_ENABLE_ENDIAN_BYTE_SWAP;#endif	/* _BIG_ENDIAN */	pci_config_put32(handle, PCI_CONF_BGE_MHCR, mhcr);	/*	 * Step 1 (also step 7): Enable PCI Memory Space accesses	 *			 Disable Memory Write/Invalidate	 *			 Enable or disable Bus Mastering	 *	 * Note that all other bits are taken from the original value saved	 * the first time through here, rather than from the current register	 * value, 'cos that will have been cleared by a soft RESET since.	 * In this way we preserve the OBP/nexus-parent's preferred settings	 * of the parity-error and system-error enable bits across multiple	 * chip RESETs.	 *	 * Step 8: Disable PCI-X Relaxed Ordering -- doesn't apply	 */	command = bgep->chipid.command | PCI_COMM_MAE;	command &= ~(PCI_COMM_ME|PCI_COMM_MEMWR_INVAL);	if (enable_dma)		command |= PCI_COMM_ME;	/*	 * on BCM5714 revision A0, false parity error gets generated	 * due to a logic bug. Provide a workaround by disabling parrity	 * error.	 */	if (((cidp->device == DEVICE_ID_5714C) ||	    (cidp->device == DEVICE_ID_5714S)) &&	    (cidp->revision == REVISION_ID_5714_A0)) {		command &= ~PCI_COMM_PARITY_DETECT;	}	pci_config_put16(handle, PCI_CONF_COMM, command);	/*	 * On some PCI-E device, there were instances when	 * the device was still link training.	 */	if (bgep->chipid.pci_type == BGE_PCI_E) {		i = 0;		value16 = pci_config_get16(handle, PCI_CONF_COMM);		while ((value16 != command) && (i < 100)) {			drv_usecwait(200);			value16 = pci_config_get16(handle, PCI_CONF_COMM);			++i;		}	}	/*	 * Clear any remaining error status bits	 */	pci_config_put16(handle, PCI_CONF_STAT, ~0);	/*	 * Make sure these indirect-access registers are sane	 * rather than random after power-up or reset	 */	pci_config_put32(handle, PCI_CONF_BGE_RIAAR, 0);	pci_config_put32(handle, PCI_CONF_BGE_MWBAR, 0);}