17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5f5488aa8Sbharding  * Common Development and Distribution License (the "License").
6f5488aa8Sbharding  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22f5488aa8Sbharding  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
2448bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * hci1394_ohci.c
297c478bd9Sstevel@tonic-gate  *    Provides access routines to the OpenHCI HW.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/conf.h>
337c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
347c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
357c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
367c478bd9Sstevel@tonic-gate #include <sys/types.h>
377c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
387c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
397c478bd9Sstevel@tonic-gate #include <sys/pci.h>
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
427c478bd9Sstevel@tonic-gate #include <sys/1394/adapters/hci1394_extern.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate  * Data swap macros used to swap config rom data that is going to be placed
477c478bd9Sstevel@tonic-gate  * in OpenHCI registers.  The config rom is treated like a byte stream.  When
487c478bd9Sstevel@tonic-gate  * the services layer calls into us to update the config rom, they pass us a
497c478bd9Sstevel@tonic-gate  * byte stream of data.  This works well except for the the fact that the
507c478bd9Sstevel@tonic-gate  * hardware uses its internal registers for the first 5 quadlets.  We have to
517c478bd9Sstevel@tonic-gate  * copy the cfgrom header and bus options into their corresponding OpenHCI
527c478bd9Sstevel@tonic-gate  * registers.  On an x86 machine, this means we have to byte swap them first.
537c478bd9Sstevel@tonic-gate  */
547c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
557c478bd9Sstevel@tonic-gate #define	OHCI_SWAP32(DATA)	(ddi_swap32(DATA))
567c478bd9Sstevel@tonic-gate #else
577c478bd9Sstevel@tonic-gate #define	OHCI_SWAP32(DATA)	(DATA)
587c478bd9Sstevel@tonic-gate #endif
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static int hci1394_ohci_selfid_init(hci1394_ohci_handle_t ohci_hdl);
627c478bd9Sstevel@tonic-gate static int hci1394_ohci_cfgrom_init(hci1394_ohci_handle_t ohci_hdl);
637c478bd9Sstevel@tonic-gate static int hci1394_ohci_chip_init(hci1394_ohci_handle_t ohci_hdl);
647c478bd9Sstevel@tonic-gate static int hci1394_ohci_phy_resume(hci1394_ohci_handle_t ohci_hdl);
657c478bd9Sstevel@tonic-gate static int hci1394_ohci_1394a_init(hci1394_ohci_handle_t ohci_hdl);
667c478bd9Sstevel@tonic-gate static int hci1394_ohci_1394a_resume(hci1394_ohci_handle_t ohci_hdl);
677c478bd9Sstevel@tonic-gate static int hci1394_ohci_phy_read_no_lock(hci1394_ohci_handle_t ohci_hdl,
687c478bd9Sstevel@tonic-gate     uint_t address, uint_t *data);
697c478bd9Sstevel@tonic-gate static int hci1394_ohci_phy_write_no_lock(hci1394_ohci_handle_t ohci_hdl,
707c478bd9Sstevel@tonic-gate     uint_t address, uint_t data);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate  * hci1394_ohci_init()
757c478bd9Sstevel@tonic-gate  *    Initialize the OpenHCI hardware.
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate int
hci1394_ohci_init(hci1394_state_t * soft_state,hci1394_drvinfo_t * drvinfo,hci1394_ohci_handle_t * ohci_hdl)787c478bd9Sstevel@tonic-gate hci1394_ohci_init(hci1394_state_t *soft_state, hci1394_drvinfo_t *drvinfo,
797c478bd9Sstevel@tonic-gate     hci1394_ohci_handle_t *ohci_hdl)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	int status;
827c478bd9Sstevel@tonic-gate 	uint32_t version;
837c478bd9Sstevel@tonic-gate 	hci1394_ohci_t *ohci;
847c478bd9Sstevel@tonic-gate #if defined(__x86)
857c478bd9Sstevel@tonic-gate 	uint16_t cmdreg;
867c478bd9Sstevel@tonic-gate #endif
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	/* alloc the space for ohci */
927c478bd9Sstevel@tonic-gate 	ohci = kmem_alloc(sizeof (hci1394_ohci_t), KM_SLEEP);
937c478bd9Sstevel@tonic-gate 	*ohci_hdl = ohci;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/*
967c478bd9Sstevel@tonic-gate 	 * Start with the cycle timer rollover interrupt disabled.  When it is
977c478bd9Sstevel@tonic-gate 	 * enabled, we will get an interrupt every 64 seconds, even if we have
987c478bd9Sstevel@tonic-gate 	 * nothing plugged into the bus.  This interrupt is used to keep track
997c478bd9Sstevel@tonic-gate 	 * of the bus time.  We will enable the interrupt when the bus manager
1007c478bd9Sstevel@tonic-gate 	 * writes to the bus_time CSR register (Currently there are not known
1017c478bd9Sstevel@tonic-gate 	 * implementations that write to the bus_time register)
1027c478bd9Sstevel@tonic-gate 	 */
1037c478bd9Sstevel@tonic-gate 	ohci->ohci_bustime_enabled = B_FALSE;
1047c478bd9Sstevel@tonic-gate 	ohci->ohci_bustime_count = 0;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	ohci->ohci_set_root_holdoff = B_FALSE;
1077c478bd9Sstevel@tonic-gate 	ohci->ohci_set_gap_count = B_FALSE;
1087c478bd9Sstevel@tonic-gate 	ohci->ohci_gap_count = 0;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	mutex_init(&ohci->ohci_mutex, NULL, MUTEX_DRIVER,
1117c478bd9Sstevel@tonic-gate 	    drvinfo->di_iblock_cookie);
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* Map OpenHCI Registers */
1147c478bd9Sstevel@tonic-gate 	status = ddi_regs_map_setup(drvinfo->di_dip, OHCI_REG_SET,
1157c478bd9Sstevel@tonic-gate 	    (caddr_t *)&ohci->ohci_regs, 0, 0, &drvinfo->di_reg_attr,
1167c478bd9Sstevel@tonic-gate 	    &ohci->ohci_reg_handle);
1177c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
1187c478bd9Sstevel@tonic-gate 		mutex_destroy(&ohci->ohci_mutex);
1197c478bd9Sstevel@tonic-gate 		kmem_free(ohci, sizeof (hci1394_ohci_t));
1207c478bd9Sstevel@tonic-gate 		*ohci_hdl = NULL;
1217c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	ohci->soft_state = soft_state;
1257c478bd9Sstevel@tonic-gate 	ohci->ohci_drvinfo = drvinfo;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/*
1287c478bd9Sstevel@tonic-gate 	 * make sure PCI Master and PCI Memory Access are enabled on x86
1297c478bd9Sstevel@tonic-gate 	 * platforms. This may not be the case if plug and play OS is
1307c478bd9Sstevel@tonic-gate 	 * set in the BIOS
1317c478bd9Sstevel@tonic-gate 	 */
1327c478bd9Sstevel@tonic-gate #if defined(__x86)
1337c478bd9Sstevel@tonic-gate 	cmdreg = pci_config_get16(soft_state->pci_config, PCI_CONF_COMM);
1347c478bd9Sstevel@tonic-gate 	if ((cmdreg & (PCI_COMM_MAE | PCI_COMM_ME)) != (PCI_COMM_MAE |
1357c478bd9Sstevel@tonic-gate 	    PCI_COMM_ME)) {
1367c478bd9Sstevel@tonic-gate 		cmdreg |= PCI_COMM_MAE | PCI_COMM_ME;
1377c478bd9Sstevel@tonic-gate 		pci_config_put16(soft_state->pci_config, PCI_CONF_COMM, cmdreg);
1387c478bd9Sstevel@tonic-gate 	}
1397c478bd9Sstevel@tonic-gate #endif
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/*
1427c478bd9Sstevel@tonic-gate 	 * Initialize the openHCI chip.  This is broken out because we need to
1437c478bd9Sstevel@tonic-gate 	 * do this when resuming too.
1447c478bd9Sstevel@tonic-gate 	 */
1457c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_chip_init(ohci);
1467c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
1477c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&ohci->ohci_reg_handle);
1487c478bd9Sstevel@tonic-gate 		mutex_destroy(&ohci->ohci_mutex);
1497c478bd9Sstevel@tonic-gate 		kmem_free(ohci, sizeof (hci1394_ohci_t));
1507c478bd9Sstevel@tonic-gate 		*ohci_hdl = NULL;
1517c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* Init the 1394 PHY */
1557c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_init(ohci);
1567c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
1577c478bd9Sstevel@tonic-gate 		(void) hci1394_ohci_soft_reset(ohci);
1587c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&ohci->ohci_reg_handle);
1597c478bd9Sstevel@tonic-gate 		mutex_destroy(&ohci->ohci_mutex);
1607c478bd9Sstevel@tonic-gate 		kmem_free(ohci, sizeof (hci1394_ohci_t));
1617c478bd9Sstevel@tonic-gate 		*ohci_hdl = NULL;
1627c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/* Init 1394a features if present */
1667c478bd9Sstevel@tonic-gate 	if (ohci->ohci_phy == H1394_PHY_1394A) {
1677c478bd9Sstevel@tonic-gate 		status = hci1394_ohci_1394a_init(ohci);
1687c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
1697c478bd9Sstevel@tonic-gate 			(void) hci1394_ohci_soft_reset(ohci);
1707c478bd9Sstevel@tonic-gate 			ddi_regs_map_free(&ohci->ohci_reg_handle);
1717c478bd9Sstevel@tonic-gate 			mutex_destroy(&ohci->ohci_mutex);
1727c478bd9Sstevel@tonic-gate 			kmem_free(ohci, sizeof (hci1394_ohci_t));
1737c478bd9Sstevel@tonic-gate 			*ohci_hdl = NULL;
1747c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
1757c478bd9Sstevel@tonic-gate 		}
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	/* save away guid, phy type, and vendor info */
1797c478bd9Sstevel@tonic-gate 	soft_state->halinfo.guid = hci1394_ohci_guid(ohci);
1807c478bd9Sstevel@tonic-gate 	soft_state->halinfo.phy = ohci->ohci_phy;
1817c478bd9Sstevel@tonic-gate 	soft_state->vendor_info.ohci_vendor_id =
1827c478bd9Sstevel@tonic-gate 	    ddi_get32(ohci->ohci_reg_handle, &ohci->ohci_regs->vendor_id);
1837c478bd9Sstevel@tonic-gate 	version = ddi_get32(ohci->ohci_reg_handle, &ohci->ohci_regs->version);
1847c478bd9Sstevel@tonic-gate 	soft_state->vendor_info.ohci_version = version;
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	/* We do not support version < 1.0 */
1877c478bd9Sstevel@tonic-gate 	if (OHCI_VERSION(version) == 0) {
1887c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE,
1897c478bd9Sstevel@tonic-gate 		    "hci1394(%d): OpenHCI version %x.%x is not supported",
1907c478bd9Sstevel@tonic-gate 		    drvinfo->di_instance, OHCI_VERSION(version),
1917c478bd9Sstevel@tonic-gate 		    OHCI_REVISION(version));
1927c478bd9Sstevel@tonic-gate 		(void) hci1394_ohci_soft_reset(ohci);
1937c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&ohci->ohci_reg_handle);
1947c478bd9Sstevel@tonic-gate 		mutex_destroy(&ohci->ohci_mutex);
1957c478bd9Sstevel@tonic-gate 		kmem_free(ohci, sizeof (hci1394_ohci_t));
1967c478bd9Sstevel@tonic-gate 		*ohci_hdl = NULL;
1977c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	/* Initialize the selfid buffer */
2017c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_selfid_init(ohci);
2027c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2037c478bd9Sstevel@tonic-gate 		(void) hci1394_ohci_soft_reset(ohci);
2047c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&ohci->ohci_reg_handle);
2057c478bd9Sstevel@tonic-gate 		mutex_destroy(&ohci->ohci_mutex);
2067c478bd9Sstevel@tonic-gate 		kmem_free(ohci, sizeof (hci1394_ohci_t));
2077c478bd9Sstevel@tonic-gate 		*ohci_hdl = NULL;
2087c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	/* Initialize the config rom buffer */
2127c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_cfgrom_init(ohci);
2137c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2147c478bd9Sstevel@tonic-gate 		(void) hci1394_ohci_soft_reset(ohci);
2157c478bd9Sstevel@tonic-gate 		hci1394_buf_free(&ohci->ohci_selfid_handle);
2167c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&ohci->ohci_reg_handle);
2177c478bd9Sstevel@tonic-gate 		mutex_destroy(&ohci->ohci_mutex);
2187c478bd9Sstevel@tonic-gate 		kmem_free(ohci, sizeof (hci1394_ohci_t));
2197c478bd9Sstevel@tonic-gate 		*ohci_hdl = NULL;
2207c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate /*
2287c478bd9Sstevel@tonic-gate  * hci1394_ohci_fini()
2297c478bd9Sstevel@tonic-gate  *    Cleanup after OpenHCI init.  This should be called during detach.
2307c478bd9Sstevel@tonic-gate  */
2317c478bd9Sstevel@tonic-gate void
hci1394_ohci_fini(hci1394_ohci_handle_t * ohci_hdl)2327c478bd9Sstevel@tonic-gate hci1394_ohci_fini(hci1394_ohci_handle_t *ohci_hdl)
2337c478bd9Sstevel@tonic-gate {
2347c478bd9Sstevel@tonic-gate 	hci1394_ohci_t *ohci;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	ohci = *ohci_hdl;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/* reset chip */
2427c478bd9Sstevel@tonic-gate 	(void) hci1394_ohci_soft_reset(ohci);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	/* Free config rom space */
2457c478bd9Sstevel@tonic-gate 	hci1394_buf_free(&ohci->ohci_cfgrom_handle);
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	/* Free selfid buffer space */
2487c478bd9Sstevel@tonic-gate 	hci1394_buf_free(&ohci->ohci_selfid_handle);
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	/* Free up the OpenHCI registers */
2517c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&ohci->ohci_reg_handle);
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 	mutex_destroy(&ohci->ohci_mutex);
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/* Free the OpenHCI state space */
2567c478bd9Sstevel@tonic-gate 	kmem_free(ohci, sizeof (hci1394_ohci_t));
2577c478bd9Sstevel@tonic-gate 	*ohci_hdl = NULL;
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate  * hci1394_ohci_chip_init()
2637c478bd9Sstevel@tonic-gate  *    Initialize the OpenHCI registers.  This contains the bulk of the initial
2647c478bd9Sstevel@tonic-gate  *    register setup.
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate static int
hci1394_ohci_chip_init(hci1394_ohci_handle_t ohci_hdl)2677c478bd9Sstevel@tonic-gate hci1394_ohci_chip_init(hci1394_ohci_handle_t ohci_hdl)
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate 	int status;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	/* Reset 1394 OHCI HW */
2757c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_soft_reset(ohci_hdl);
2767c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
2777c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	/*
2817c478bd9Sstevel@tonic-gate 	 * Setup Host Control Register. The software reset does not put all
2827c478bd9Sstevel@tonic-gate 	 * registers in a known state. The Host Control Register is one of these
2837c478bd9Sstevel@tonic-gate 	 * registers. First make sure noByteSwapData and postedWriteEnable and
2847c478bd9Sstevel@tonic-gate 	 * are cleared.
2857c478bd9Sstevel@tonic-gate 	 */
2867c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
2877c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_clr, OHCI_HC_NO_BSWAP |
2887c478bd9Sstevel@tonic-gate 	    OHCI_HC_POSTWR_ENBL);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	/*
2917c478bd9Sstevel@tonic-gate 	 * the determination if we should swap data is made during the PCI
2927c478bd9Sstevel@tonic-gate 	 * initialization.
2937c478bd9Sstevel@tonic-gate 	 */
2947c478bd9Sstevel@tonic-gate 	if (ohci_hdl->soft_state->swap_data == B_FALSE) {
2957c478bd9Sstevel@tonic-gate 		/*
2967c478bd9Sstevel@tonic-gate 		 * most hba's don't swap data.  It will be swapped in the
2977c478bd9Sstevel@tonic-gate 		 * global swap for SPARC.  Enable Link Power(LPS). Enable
2987c478bd9Sstevel@tonic-gate 		 * Posted Writes
2997c478bd9Sstevel@tonic-gate 		 */
3007c478bd9Sstevel@tonic-gate 		ddi_put32(ohci_hdl->ohci_reg_handle,
3017c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->hc_ctrl_set, OHCI_HC_NO_BSWAP |
3027c478bd9Sstevel@tonic-gate 		    OHCI_HC_LPS | OHCI_HC_POSTWR_ENBL);
3037c478bd9Sstevel@tonic-gate 	} else {
3047c478bd9Sstevel@tonic-gate 		/*
3057c478bd9Sstevel@tonic-gate 		 * Swap Data. Enable Link Power(LPS). Enable Posted Writes
3067c478bd9Sstevel@tonic-gate 		 */
3077c478bd9Sstevel@tonic-gate 		ddi_put32(ohci_hdl->ohci_reg_handle,
3087c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->hc_ctrl_set, OHCI_HC_LPS |
3097c478bd9Sstevel@tonic-gate 		    OHCI_HC_POSTWR_ENBL);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/*
3137c478bd9Sstevel@tonic-gate 	 * Wait for PHY to come up. There does not seem to be standard time for
3147c478bd9Sstevel@tonic-gate 	 * how long wait for the PHY to come up. The problem is that the PHY
3157c478bd9Sstevel@tonic-gate 	 * provides a clock to the link layer and if that is not stable, we
3167c478bd9Sstevel@tonic-gate 	 * could get a PCI timeout error when reading/writing a phy register
3177c478bd9Sstevel@tonic-gate 	 * (and maybe an OpenHCI register?)  This used to be set to 10mS which
3187c478bd9Sstevel@tonic-gate 	 * works for just about every adapter we tested on.  We got a new TI
3197c478bd9Sstevel@tonic-gate 	 * adapter which would crash the system once in a while if nothing
3207c478bd9Sstevel@tonic-gate 	 * (1394 device) was pluged into the adapter.  Changing this delay to
3217c478bd9Sstevel@tonic-gate 	 * 50mS made that problem go away. This value is set via a patchable
3227c478bd9Sstevel@tonic-gate 	 * variable located in hci1394_extern.c
3237c478bd9Sstevel@tonic-gate 	 */
3247c478bd9Sstevel@tonic-gate 	delay(drv_usectohz(hci1394_phy_stabilization_delay_uS));
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/* Clear Isochrounous receive multi-chan mode registers */
3277c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3287c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_multi_maskhi_clr, 0xFFFFFFFF);
3297c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3307c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_multi_masklo_clr, 0xFFFFFFFF);
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	/*
3337c478bd9Sstevel@tonic-gate 	 * Setup async retry on busy or ack_data_error
3347c478bd9Sstevel@tonic-gate 	 *   secondlimit = 0 <= bits 31-29
3357c478bd9Sstevel@tonic-gate 	 *   cycleLimit = 0 <= bits 28-16
3367c478bd9Sstevel@tonic-gate 	 *   maxPhysRespRetries = 0 <= bits 11-8
3377c478bd9Sstevel@tonic-gate 	 *   maxARRespRetries = 0 <= bits 7-4
3387c478bd9Sstevel@tonic-gate 	 *   maxATReqRetries = 2 <= bits 3-0
3397c478bd9Sstevel@tonic-gate 	 */
3407c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3417c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_retries, 0x00000002);
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	/*
3447c478bd9Sstevel@tonic-gate 	 * Setup Link Control
3457c478bd9Sstevel@tonic-gate 	 *   Enable cycleMaster, cycleTimerEnable, and rcvPhyPkt.
3467c478bd9Sstevel@tonic-gate 	 */
3477c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3487c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->link_ctrl_clr, 0xFFFFFFFF);
3497c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3507c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->link_ctrl_set, OHCI_LC_CYC_MAST |
3517c478bd9Sstevel@tonic-gate 	    OHCI_LC_CTIME_ENBL | OHCI_LC_RCV_PHY);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	/*
3547c478bd9Sstevel@tonic-gate 	 * Set the Physical address map boundary to 0x0000FFFFFFFF. The
3557c478bd9Sstevel@tonic-gate 	 * phys_upper_bound is the upper 32-bits of the 48-bit 1394 address. The
3567c478bd9Sstevel@tonic-gate 	 * lower 16 bits are assumed to be 0xFFFF.
3577c478bd9Sstevel@tonic-gate 	 */
3587c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3597c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phys_upper_bound, (uint32_t)0x0000FFFF);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/*
3627c478bd9Sstevel@tonic-gate 	 * Enable all async requests.
3637c478bd9Sstevel@tonic-gate 	 * The asyncReqResourceAll bit (0x80000000) does not get cleared during
3647c478bd9Sstevel@tonic-gate 	 * a bus reset.  If this code is changed to selectively allow nodes to
3657c478bd9Sstevel@tonic-gate 	 * perform ARREQ's, the ARREQ filter bits will need to be updated after
3667c478bd9Sstevel@tonic-gate 	 * every bus reset.
3677c478bd9Sstevel@tonic-gate 	 */
3687c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3697c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_req_filterhi_set, (uint32_t)0x80000000);
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	/*
3727c478bd9Sstevel@tonic-gate 	 * clear isochronous interrupt event and mask registers clearing the
3737c478bd9Sstevel@tonic-gate 	 * mask registers disable all isoc tx & rx ints
3747c478bd9Sstevel@tonic-gate 	 */
3757c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3767c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_event_clr, (uint32_t)0xFFFFFFFF);
3777c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3787c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_mask_clr, (uint32_t)0xFFFFFFFF);
3797c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3807c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_event_clr, (uint32_t)0xFFFFFFFF);
3817c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3827c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_mask_clr, (uint32_t)0xFFFFFFFF);
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	/* Clear interrupt event/mask register */
3857c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3867c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_event_clr, (uint32_t)0xFFFFFFFF);
3877c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
3887c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_mask_clr, (uint32_t)0xFFFFFFFF);
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate /*
3957c478bd9Sstevel@tonic-gate  * hci1394_ohci_soft_reset()
3967c478bd9Sstevel@tonic-gate  *    Reset OpenHCI HW.
3977c478bd9Sstevel@tonic-gate  */
3987c478bd9Sstevel@tonic-gate int
hci1394_ohci_soft_reset(hci1394_ohci_handle_t ohci_hdl)3997c478bd9Sstevel@tonic-gate hci1394_ohci_soft_reset(hci1394_ohci_handle_t ohci_hdl)
4007c478bd9Sstevel@tonic-gate {
4017c478bd9Sstevel@tonic-gate 	uint32_t resetStatus;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 	/* Reset 1394 HW - Reset is bit 16 in HCControl */
4077c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
4087c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_set, OHCI_HC_SOFT_RESET);
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	/* Wait for reset to complete */
4117c478bd9Sstevel@tonic-gate 	drv_usecwait(OHCI_CHIP_RESET_TIME_IN_uSEC);
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	/* Verify reset is complete */
4147c478bd9Sstevel@tonic-gate 	resetStatus = ddi_get32(ohci_hdl->ohci_reg_handle,
4157c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_set);
4167c478bd9Sstevel@tonic-gate 	resetStatus = resetStatus & OHCI_HC_SOFT_RESET;
4177c478bd9Sstevel@tonic-gate 	if (resetStatus != 0) {
4187c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
4197c478bd9Sstevel@tonic-gate 	}
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate  * hci1394_ohci_reg_read()
4277c478bd9Sstevel@tonic-gate  *    Read OpenHCI register.  This is called from the test ioctl interface
4287c478bd9Sstevel@tonic-gate  *    through devctl.
4297c478bd9Sstevel@tonic-gate  */
4307c478bd9Sstevel@tonic-gate void
hci1394_ohci_reg_read(hci1394_ohci_handle_t ohci_hdl,uint_t offset,uint32_t * data)4317c478bd9Sstevel@tonic-gate hci1394_ohci_reg_read(hci1394_ohci_handle_t ohci_hdl,
4327c478bd9Sstevel@tonic-gate     uint_t offset, uint32_t *data)
4337c478bd9Sstevel@tonic-gate {
4347c478bd9Sstevel@tonic-gate 	uint32_t *addr;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
4387c478bd9Sstevel@tonic-gate 	ASSERT(data != NULL);
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	addr = (uint32_t *)((uintptr_t)ohci_hdl->ohci_regs +
4417c478bd9Sstevel@tonic-gate 	    (uintptr_t)(offset & OHCI_REG_ADDR_MASK));
4427c478bd9Sstevel@tonic-gate 	*data = ddi_get32(ohci_hdl->ohci_reg_handle, addr);
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  * hci1394_ohci_reg_write()
4487c478bd9Sstevel@tonic-gate  *    Write OpenHCI register.  This is called from the test ioctl interface
4497c478bd9Sstevel@tonic-gate  *    through devctl.
4507c478bd9Sstevel@tonic-gate  */
4517c478bd9Sstevel@tonic-gate void
hci1394_ohci_reg_write(hci1394_ohci_handle_t ohci_hdl,uint_t offset,uint32_t data)4527c478bd9Sstevel@tonic-gate hci1394_ohci_reg_write(hci1394_ohci_handle_t ohci_hdl,
4537c478bd9Sstevel@tonic-gate     uint_t offset, uint32_t data)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	uint32_t *addr;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	addr = (uint32_t *)((uintptr_t)ohci_hdl->ohci_regs +
4617c478bd9Sstevel@tonic-gate 	    (uintptr_t)(offset & OHCI_REG_ADDR_MASK));
4627c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle, addr, data);
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate  * hci1394_ohci_intr_master_enable()
4687c478bd9Sstevel@tonic-gate  *    Enable interrupts to be passed on from OpenHCI.  This is a global mask.
4697c478bd9Sstevel@tonic-gate  *    Individual interrupts still need to be enabled for interrupts to be
4707c478bd9Sstevel@tonic-gate  *    generated.
4717c478bd9Sstevel@tonic-gate  */
4727c478bd9Sstevel@tonic-gate void
hci1394_ohci_intr_master_enable(hci1394_ohci_handle_t ohci_hdl)4737c478bd9Sstevel@tonic-gate hci1394_ohci_intr_master_enable(hci1394_ohci_handle_t ohci_hdl)
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
4787c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_mask_set, OHCI_INTR_MASTER_INTR_ENBL);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate /*
4837c478bd9Sstevel@tonic-gate  * hci1394_ohci_intr_master_disable()
4847c478bd9Sstevel@tonic-gate  *    Disable all OpenHCI interrupts from being passed on.  This does not affect
4857c478bd9Sstevel@tonic-gate  *    the individual interrupt mask settings.  When interrupts are enabled
4867c478bd9Sstevel@tonic-gate  *    again, the same individual interrupts will still be enabled.
4877c478bd9Sstevel@tonic-gate  */
4887c478bd9Sstevel@tonic-gate void
hci1394_ohci_intr_master_disable(hci1394_ohci_handle_t ohci_hdl)4897c478bd9Sstevel@tonic-gate hci1394_ohci_intr_master_disable(hci1394_ohci_handle_t ohci_hdl)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
4947c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_mask_clr, OHCI_INTR_MASTER_INTR_ENBL);
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate /*
4997c478bd9Sstevel@tonic-gate  * hci1394_ohci_intr_asserted()
5007c478bd9Sstevel@tonic-gate  *    Return which ENABLED interrupts are asserted.  If an interrupt is disabled
5017c478bd9Sstevel@tonic-gate  *    via its mask bit, it will not be returned from here.
5027c478bd9Sstevel@tonic-gate  *
5037c478bd9Sstevel@tonic-gate  * NOTE: we may want to make this a macro at some point.
5047c478bd9Sstevel@tonic-gate  */
5057c478bd9Sstevel@tonic-gate uint32_t
hci1394_ohci_intr_asserted(hci1394_ohci_handle_t ohci_hdl)5067c478bd9Sstevel@tonic-gate hci1394_ohci_intr_asserted(hci1394_ohci_handle_t ohci_hdl)
5077c478bd9Sstevel@tonic-gate {
5087c478bd9Sstevel@tonic-gate 	uint32_t interrupts_asserted;
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	/*
5137c478bd9Sstevel@tonic-gate 	 * Only look at interrupts which are enabled by reading the
5147c478bd9Sstevel@tonic-gate 	 * intr_event_clr register.
5157c478bd9Sstevel@tonic-gate 	 */
5167c478bd9Sstevel@tonic-gate 	interrupts_asserted = ddi_get32(ohci_hdl->ohci_reg_handle,
5177c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_event_clr);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	return (interrupts_asserted);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate /*
5247c478bd9Sstevel@tonic-gate  * hci1394_ohci_intr_enable()
5257c478bd9Sstevel@tonic-gate  *    Enable an individual interrupt or set of interrupts. This does not affect
5267c478bd9Sstevel@tonic-gate  *    the global interrupt mask.
5277c478bd9Sstevel@tonic-gate  */
5287c478bd9Sstevel@tonic-gate void
hci1394_ohci_intr_enable(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)5297c478bd9Sstevel@tonic-gate hci1394_ohci_intr_enable(hci1394_ohci_handle_t ohci_hdl,
5307c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
5357c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_mask_set, interrupt_mask);
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate  * hci1394_ohci_intr_disable()
5417c478bd9Sstevel@tonic-gate  *    Disable an individual interrupt or set of interrupts. This does not affect
5427c478bd9Sstevel@tonic-gate  *    the global interrupt mask.
5437c478bd9Sstevel@tonic-gate  */
5447c478bd9Sstevel@tonic-gate void
hci1394_ohci_intr_disable(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)5457c478bd9Sstevel@tonic-gate hci1394_ohci_intr_disable(hci1394_ohci_handle_t ohci_hdl,
5467c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
5517c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_mask_clr, interrupt_mask);
5527c478bd9Sstevel@tonic-gate }
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate /*
5567c478bd9Sstevel@tonic-gate  * hci1394_ohci_intr_clear()
5577c478bd9Sstevel@tonic-gate  *    Clear a set of interrupts so that they are not asserted anymore.
5587c478bd9Sstevel@tonic-gate  *
5597c478bd9Sstevel@tonic-gate  * NOTE: we may want to make this a macro at some point.
5607c478bd9Sstevel@tonic-gate  */
5617c478bd9Sstevel@tonic-gate void
hci1394_ohci_intr_clear(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)5627c478bd9Sstevel@tonic-gate hci1394_ohci_intr_clear(hci1394_ohci_handle_t ohci_hdl,
5637c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
5687c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_event_clr, interrupt_mask);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate /*
5737c478bd9Sstevel@tonic-gate  * hci1394_ohci_it_intr_asserted()
5747c478bd9Sstevel@tonic-gate  *    Return which ENABLED isoch TX interrupts are asserted.  If an interrupt is
5757c478bd9Sstevel@tonic-gate  *    disabled via its mask bit, it will not be returned from here.
5767c478bd9Sstevel@tonic-gate  *
5777c478bd9Sstevel@tonic-gate  * NOTE: we may want to make this a macro at some point.
5787c478bd9Sstevel@tonic-gate  */
5797c478bd9Sstevel@tonic-gate uint32_t
hci1394_ohci_it_intr_asserted(hci1394_ohci_handle_t ohci_hdl)5807c478bd9Sstevel@tonic-gate hci1394_ohci_it_intr_asserted(hci1394_ohci_handle_t ohci_hdl)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate 	uint32_t interrupts_asserted;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	/* Only look at interrupts which are enabled */
5877c478bd9Sstevel@tonic-gate 	interrupts_asserted = ddi_get32(ohci_hdl->ohci_reg_handle,
5887c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_event_clr);
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	return (interrupts_asserted);
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate /*
5957c478bd9Sstevel@tonic-gate  * hci1394_ohci_it_intr_enable()
5967c478bd9Sstevel@tonic-gate  *    Enable an individual isoch TX interrupt. This does not affect the general
5977c478bd9Sstevel@tonic-gate  *    isoch interrupt mask in the OpenHCI Mask register.  That is enabled/
5987c478bd9Sstevel@tonic-gate  *    disabled via hci1394_ohci_intr_enable/hci1394_ohci_intr_disable.
5997c478bd9Sstevel@tonic-gate  */
6007c478bd9Sstevel@tonic-gate void
hci1394_ohci_it_intr_enable(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)6017c478bd9Sstevel@tonic-gate hci1394_ohci_it_intr_enable(hci1394_ohci_handle_t ohci_hdl,
6027c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
6037c478bd9Sstevel@tonic-gate {
6047c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
6077c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_mask_set, interrupt_mask);
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate /*
6127c478bd9Sstevel@tonic-gate  * hci1394_ohci_it_intr_disable()
6137c478bd9Sstevel@tonic-gate  *    Disable an individual isoch TX interrupt. This does not affect the general
6147c478bd9Sstevel@tonic-gate  *    isoch interrupt mask in the OpenHCI Mask register.  That is enabled/
6157c478bd9Sstevel@tonic-gate  *    disabled via hci1394_ohci_intr_enable/hci1394_ohci_intr_disable.
6167c478bd9Sstevel@tonic-gate  */
6177c478bd9Sstevel@tonic-gate void
hci1394_ohci_it_intr_disable(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)6187c478bd9Sstevel@tonic-gate hci1394_ohci_it_intr_disable(hci1394_ohci_handle_t ohci_hdl,
6197c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
6207c478bd9Sstevel@tonic-gate {
6217c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
6247c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_mask_clr, interrupt_mask);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate /*
6297c478bd9Sstevel@tonic-gate  * hci1394_ohci_it_intr_clear()
6307c478bd9Sstevel@tonic-gate  *    Clear an individual isoch TX interrupt so that it is not asserted anymore.
6317c478bd9Sstevel@tonic-gate  *
6327c478bd9Sstevel@tonic-gate  * NOTE: we may want to make this a macro at some point.
6337c478bd9Sstevel@tonic-gate  */
6347c478bd9Sstevel@tonic-gate void
hci1394_ohci_it_intr_clear(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)6357c478bd9Sstevel@tonic-gate hci1394_ohci_it_intr_clear(hci1394_ohci_handle_t ohci_hdl,
6367c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
6377c478bd9Sstevel@tonic-gate {
6387c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
6417c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_event_clr, interrupt_mask);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate /*
6467c478bd9Sstevel@tonic-gate  * hci1394_ohci_it_ctxt_count_get()
6477c478bd9Sstevel@tonic-gate  *    Determine the number of supported isochronous transmit contexts.
6487c478bd9Sstevel@tonic-gate  */
6497c478bd9Sstevel@tonic-gate int
hci1394_ohci_it_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl)6507c478bd9Sstevel@tonic-gate hci1394_ohci_it_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl)
6517c478bd9Sstevel@tonic-gate {
6527c478bd9Sstevel@tonic-gate 	uint32_t channel_mask;
6537c478bd9Sstevel@tonic-gate 	int count;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	/*
6587c478bd9Sstevel@tonic-gate 	 * hw is required to support contexts 0 to N, where N <= 31
6597c478bd9Sstevel@tonic-gate 	 * the interrupt mask bits are wired to ground for unsupported
6607c478bd9Sstevel@tonic-gate 	 * contexts.  Write 1's to all it mask bits, then read the mask.
6617c478bd9Sstevel@tonic-gate 	 * Implemented contexts will read (sequentially) as 1
6627c478bd9Sstevel@tonic-gate 	 */
6637c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
6647c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_mask_set, 0xFFFFFFFF);
6657c478bd9Sstevel@tonic-gate 	channel_mask = ddi_get32(ohci_hdl->ohci_reg_handle,
6667c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it_intr_mask_set);
6677c478bd9Sstevel@tonic-gate 	count = 0;
6687c478bd9Sstevel@tonic-gate 	while (channel_mask != 0) {
6697c478bd9Sstevel@tonic-gate 		channel_mask = channel_mask >> 1;
6707c478bd9Sstevel@tonic-gate 		count++;
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	return (count);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate /*
6787c478bd9Sstevel@tonic-gate  * hci1394_ohci_it_cmd_ptr_set()
6797c478bd9Sstevel@tonic-gate  *    Set the context pointer for a given isoch TX context.  This is the IO
6807c478bd9Sstevel@tonic-gate  *    address for the HW to fetch the first descriptor.  The context should
6817c478bd9Sstevel@tonic-gate  *    not be running when this routine is called.
6827c478bd9Sstevel@tonic-gate  */
6837c478bd9Sstevel@tonic-gate void
hci1394_ohci_it_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl,uint_t context_number,uint32_t io_addr)6847c478bd9Sstevel@tonic-gate hci1394_ohci_it_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl,
6857c478bd9Sstevel@tonic-gate     uint_t context_number, uint32_t io_addr)
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
6907c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->it[context_number].cmd_ptrlo,
6917c478bd9Sstevel@tonic-gate 	    io_addr);
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate /*
6967c478bd9Sstevel@tonic-gate  * hci1394_ohci_ir_intr_asserted()
6977c478bd9Sstevel@tonic-gate  *    Return which ENABLED isoch RX interrupts are asserted.  If an interrupt is
6987c478bd9Sstevel@tonic-gate  *    disabled via its mask bit, it will not be returned from here.
6997c478bd9Sstevel@tonic-gate  *
7007c478bd9Sstevel@tonic-gate  * NOTE: we may want to make this a macro at some point.
7017c478bd9Sstevel@tonic-gate  */
7027c478bd9Sstevel@tonic-gate uint32_t
hci1394_ohci_ir_intr_asserted(hci1394_ohci_handle_t ohci_hdl)7037c478bd9Sstevel@tonic-gate hci1394_ohci_ir_intr_asserted(hci1394_ohci_handle_t ohci_hdl)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate 	uint32_t interrupts_asserted;
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	/* Only look at interrupts which are enabled */
7107c478bd9Sstevel@tonic-gate 	interrupts_asserted = ddi_get32(ohci_hdl->ohci_reg_handle,
7117c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_event_clr);
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	return (interrupts_asserted);
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate /*
7187c478bd9Sstevel@tonic-gate  * hci1394_ohci_ir_intr_enable()
7197c478bd9Sstevel@tonic-gate  *    Enable an individual isoch RX interrupt. This does not affect the isoch
7207c478bd9Sstevel@tonic-gate  *    interrupt mask in the OpenHCI Mask register.  That is enabled/disabled
7217c478bd9Sstevel@tonic-gate  *    via hci1394_ohci_intr_enable/hci1394_ohci_intr_disable.
7227c478bd9Sstevel@tonic-gate  */
7237c478bd9Sstevel@tonic-gate void
hci1394_ohci_ir_intr_enable(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)7247c478bd9Sstevel@tonic-gate hci1394_ohci_ir_intr_enable(hci1394_ohci_handle_t ohci_hdl,
7257c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
7267c478bd9Sstevel@tonic-gate {
7277c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
7307c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_mask_set, interrupt_mask);
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate /*
7357c478bd9Sstevel@tonic-gate  * hci1394_ohci_ir_intr_disable()
7367c478bd9Sstevel@tonic-gate  *    Disable an individual isoch RX interrupt. This does not affect the isoch
7377c478bd9Sstevel@tonic-gate  *    interrupt mask in the OpenHCI Mask register.  That is enabled/disabled
7387c478bd9Sstevel@tonic-gate  *    via hci1394_ohci_intr_enable/hci1394_ohci_intr_disable.
7397c478bd9Sstevel@tonic-gate  */
7407c478bd9Sstevel@tonic-gate void
hci1394_ohci_ir_intr_disable(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)7417c478bd9Sstevel@tonic-gate hci1394_ohci_ir_intr_disable(hci1394_ohci_handle_t ohci_hdl,
7427c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
7437c478bd9Sstevel@tonic-gate {
7447c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
7477c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_mask_clr, interrupt_mask);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate /*
7527c478bd9Sstevel@tonic-gate  * hci1394_ohci_ir_intr_clear()
7537c478bd9Sstevel@tonic-gate  *    Clear an individual isoch RX interrupt so that it is not asserted anymore.
7547c478bd9Sstevel@tonic-gate  *
7557c478bd9Sstevel@tonic-gate  * NOTE: we may want to make this a macro at some point.
7567c478bd9Sstevel@tonic-gate  */
7577c478bd9Sstevel@tonic-gate void
hci1394_ohci_ir_intr_clear(hci1394_ohci_handle_t ohci_hdl,uint32_t interrupt_mask)7587c478bd9Sstevel@tonic-gate hci1394_ohci_ir_intr_clear(hci1394_ohci_handle_t ohci_hdl,
7597c478bd9Sstevel@tonic-gate     uint32_t interrupt_mask)
7607c478bd9Sstevel@tonic-gate {
7617c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
7647c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_event_clr, interrupt_mask);
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate /*
7697c478bd9Sstevel@tonic-gate  * hci1394_ohci_ir_ctxt_count_get()
7707c478bd9Sstevel@tonic-gate  *    Determine the number of supported isochronous receive contexts.
7717c478bd9Sstevel@tonic-gate  */
7727c478bd9Sstevel@tonic-gate int
hci1394_ohci_ir_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl)7737c478bd9Sstevel@tonic-gate hci1394_ohci_ir_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl)
7747c478bd9Sstevel@tonic-gate {
7757c478bd9Sstevel@tonic-gate 	uint32_t channel_mask;
7767c478bd9Sstevel@tonic-gate 	int count;
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	/*
7817c478bd9Sstevel@tonic-gate 	 * hw is required to support contexts 0 to N, where N <= 31
7827c478bd9Sstevel@tonic-gate 	 * the interrupt mask bits are wired to ground for unsupported
7837c478bd9Sstevel@tonic-gate 	 * contexts.  Write 1's to all ir mask bits, then read the mask.
7847c478bd9Sstevel@tonic-gate 	 * Implemented contexts will read (sequentially) as 1
7857c478bd9Sstevel@tonic-gate 	 */
7867c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
7877c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_mask_set, 0xFFFFFFFF);
7887c478bd9Sstevel@tonic-gate 	channel_mask = ddi_get32(ohci_hdl->ohci_reg_handle,
7897c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir_intr_mask_set);
7907c478bd9Sstevel@tonic-gate 	count = 0;
7917c478bd9Sstevel@tonic-gate 	while (channel_mask != 0) {
7927c478bd9Sstevel@tonic-gate 		channel_mask = channel_mask >> 1;
7937c478bd9Sstevel@tonic-gate 		count++;
7947c478bd9Sstevel@tonic-gate 	}
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 	return (count);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate  * hci1394_ohci_ir_cmd_ptr_set()
8027c478bd9Sstevel@tonic-gate  *    Set the context pointer for a given isoch RX context.  This is the IO
8037c478bd9Sstevel@tonic-gate  *    address for the HW to fetch the first descriptor.  The context should
8047c478bd9Sstevel@tonic-gate  *    not be running when this routine is called.
8057c478bd9Sstevel@tonic-gate  */
8067c478bd9Sstevel@tonic-gate void
hci1394_ohci_ir_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl,uint_t context_number,uint32_t io_addr)8077c478bd9Sstevel@tonic-gate hci1394_ohci_ir_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl,
8087c478bd9Sstevel@tonic-gate     uint_t context_number, uint32_t io_addr)
8097c478bd9Sstevel@tonic-gate {
8107c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
8137c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ir[context_number].cmd_ptrlo,
8147c478bd9Sstevel@tonic-gate 	    io_addr);
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate  * hci1394_ohci_link_enable()
8207c478bd9Sstevel@tonic-gate  *    Enable the 1394 link layer.  When the link is enabled, the PHY will pass
8217c478bd9Sstevel@tonic-gate  *    up any 1394 bus transactions which would normally come up to the link.
8227c478bd9Sstevel@tonic-gate  */
8237c478bd9Sstevel@tonic-gate void
hci1394_ohci_link_enable(hci1394_ohci_handle_t ohci_hdl)8247c478bd9Sstevel@tonic-gate hci1394_ohci_link_enable(hci1394_ohci_handle_t ohci_hdl)
8257c478bd9Sstevel@tonic-gate {
8267c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
8297c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_set, OHCI_HC_LINK_ENBL);
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate  * hci1394_ohci_link_disable()
8357c478bd9Sstevel@tonic-gate  *    Disable the 1394 link layer.  When the link is disabled, the PHY will NOT
8367c478bd9Sstevel@tonic-gate  *    pass up any 1394 bus transactions which would normally come up to the
8377c478bd9Sstevel@tonic-gate  *    link.  This "logically" disconnects us from the 1394 bus.
8387c478bd9Sstevel@tonic-gate  */
8397c478bd9Sstevel@tonic-gate void
hci1394_ohci_link_disable(hci1394_ohci_handle_t ohci_hdl)8407c478bd9Sstevel@tonic-gate hci1394_ohci_link_disable(hci1394_ohci_handle_t ohci_hdl)
8417c478bd9Sstevel@tonic-gate {
8427c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
8457c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_clr, OHCI_HC_LINK_ENBL);
8467c478bd9Sstevel@tonic-gate }
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate /*
8507c478bd9Sstevel@tonic-gate  * hci1394_ohci_bus_reset()
8517c478bd9Sstevel@tonic-gate  *     Reset the 1394 bus. This performs a "long" bus reset and can be called
8527c478bd9Sstevel@tonic-gate  *     when the adapter has either a 1394-1995 or 1394A PHY.
8537c478bd9Sstevel@tonic-gate  */
8547c478bd9Sstevel@tonic-gate int
hci1394_ohci_bus_reset(hci1394_ohci_handle_t ohci_hdl)8557c478bd9Sstevel@tonic-gate hci1394_ohci_bus_reset(hci1394_ohci_handle_t ohci_hdl)
8567c478bd9Sstevel@tonic-gate {
8577c478bd9Sstevel@tonic-gate 	int status;
8587c478bd9Sstevel@tonic-gate 	uint_t reg;
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 	/*
8647c478bd9Sstevel@tonic-gate 	 * We want to reset the bus.  We also handle the root_holdoff and gap
8657c478bd9Sstevel@tonic-gate 	 * count cacheing explained at the top of this file.
8667c478bd9Sstevel@tonic-gate 	 */
8677c478bd9Sstevel@tonic-gate 	reg = OHCI_PHY_IBR;
8687c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_set_root_holdoff == B_TRUE) {
8697c478bd9Sstevel@tonic-gate 		reg = reg | OHCI_PHY_RHB;
8707c478bd9Sstevel@tonic-gate 	}
8717c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_set_gap_count == B_TRUE) {
8727c478bd9Sstevel@tonic-gate 		reg = reg | ohci_hdl->ohci_gap_count;
8737c478bd9Sstevel@tonic-gate 	} else {
8747c478bd9Sstevel@tonic-gate 		reg = reg | OHCI_PHY_MAX_GAP;
8757c478bd9Sstevel@tonic-gate 	}
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	/*
8787c478bd9Sstevel@tonic-gate 	 * Reset the bus. We intentionally do NOT do a PHY read here.  A PHY
8797c478bd9Sstevel@tonic-gate 	 * read could introduce race conditions and would be more likely to fail
8807c478bd9Sstevel@tonic-gate 	 * due to a timeout.
8817c478bd9Sstevel@tonic-gate 	 */
8827c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_write(ohci_hdl, 0x1, reg);
8837c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
8847c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	/* clear the root holdoff and gap count state bits */
8887c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_set_root_holdoff = B_FALSE;
8897c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_set_gap_count = B_FALSE;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate 
894f5488aa8Sbharding /*
895f5488aa8Sbharding  *
896f5488aa8Sbharding  * hci1394_ohci_bus_reset_nroot()
897f5488aa8Sbharding  *     Reset the 1394 bus. This performs a "long" bus reset with out a root.
898f5488aa8Sbharding  */
899f5488aa8Sbharding int
hci1394_ohci_bus_reset_nroot(hci1394_ohci_handle_t ohci_hdl)900f5488aa8Sbharding hci1394_ohci_bus_reset_nroot(hci1394_ohci_handle_t ohci_hdl)
901f5488aa8Sbharding {
902f5488aa8Sbharding 	int status;
903f5488aa8Sbharding 	uint_t reg;
904f5488aa8Sbharding 
905f5488aa8Sbharding 	ASSERT(ohci_hdl != NULL);
906f5488aa8Sbharding 
907f5488aa8Sbharding 	/*
908f5488aa8Sbharding 	 * We want to reset the bus.  We don't care about any holdoff
909f5488aa8Sbharding 	 * we are suspending need no root...
910f5488aa8Sbharding 	 */
911f5488aa8Sbharding 	(void) hci1394_ohci_phy_read(ohci_hdl, 0x1, &reg);
912f5488aa8Sbharding 	reg = reg | OHCI_PHY_IBR;
913f5488aa8Sbharding 	reg = reg & ~OHCI_PHY_RHB;
914f5488aa8Sbharding 
915f5488aa8Sbharding 	/*
916f5488aa8Sbharding 	 * Reset the bus. We intentionally do NOT do a PHY read here.  A PHY
917f5488aa8Sbharding 	 * read could introduce race conditions and would be more likely to fail
918f5488aa8Sbharding 	 * due to a timeout.
919f5488aa8Sbharding 	 */
920f5488aa8Sbharding 	status = hci1394_ohci_phy_write(ohci_hdl, 0x1, reg);
921f5488aa8Sbharding 	if (status != DDI_SUCCESS) {
922f5488aa8Sbharding 		return (DDI_FAILURE);
923f5488aa8Sbharding 	}
924f5488aa8Sbharding 
925f5488aa8Sbharding 	return (DDI_SUCCESS);
926f5488aa8Sbharding }
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate /*
9297c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_init()
9307c478bd9Sstevel@tonic-gate  *    Setup the PHY.  This should be called during attach and performs any PHY
9317c478bd9Sstevel@tonic-gate  *    initialization required including figuring out what kind of PHY we have.
9327c478bd9Sstevel@tonic-gate  */
9337c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_init(hci1394_ohci_handle_t ohci_hdl)9347c478bd9Sstevel@tonic-gate hci1394_ohci_phy_init(hci1394_ohci_handle_t ohci_hdl)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	int status;
9377c478bd9Sstevel@tonic-gate 	uint_t phy_reg;
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	/*
9437c478bd9Sstevel@tonic-gate 	 * if the phy has extended set to 7, the phy is a not a 1394-1995 PHY.
9447c478bd9Sstevel@tonic-gate 	 * It could be a 1394a phy or beyond.  The PHY type can be found in PHY
9457c478bd9Sstevel@tonic-gate 	 * register page 1 in the compliance_level register.
9467c478bd9Sstevel@tonic-gate 	 *
9477c478bd9Sstevel@tonic-gate 	 * Since there are not any current standards beyond 1394A, we are going
9487c478bd9Sstevel@tonic-gate 	 * to consider the PHY to be a 1394A phy if the extended bit is set.
9497c478bd9Sstevel@tonic-gate 	 *
9507c478bd9Sstevel@tonic-gate 	 * phy registers are byte wide registers and are addressed as 0, 1, 2,
9517c478bd9Sstevel@tonic-gate 	 * 3, ...  Phy register 0 may not be read or written.
9527c478bd9Sstevel@tonic-gate 	 *
9537c478bd9Sstevel@tonic-gate 	 * Phy register 0x2 (bit 0 MSB, 7 LSB)
9547c478bd9Sstevel@tonic-gate 	 *   Extended    - bits 0 - 2
9557c478bd9Sstevel@tonic-gate 	 *   Total Ports - bits 4 - 7
9567c478bd9Sstevel@tonic-gate 	 */
9577c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read(ohci_hdl, 2, &phy_reg);
9587c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
9597c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
9607c478bd9Sstevel@tonic-gate 	}
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	if ((phy_reg & OHCI_PHY_EXTND_MASK) != OHCI_PHY_EXTND) {
9637c478bd9Sstevel@tonic-gate 		/*
9647c478bd9Sstevel@tonic-gate 		 * if the extended bit is not set, we have to be a 1394-1995
9657c478bd9Sstevel@tonic-gate 		 * PHY
9667c478bd9Sstevel@tonic-gate 		 */
9677c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_phy = H1394_PHY_1995;
9687c478bd9Sstevel@tonic-gate 	} else {
9697c478bd9Sstevel@tonic-gate 		/* Treat all other PHY's as a 1394A PHY */
9707c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_phy = H1394_PHY_1394A;
9717c478bd9Sstevel@tonic-gate 	}
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate /*
9787c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_resume()
9797c478bd9Sstevel@tonic-gate  *    re-initialize the PHY. This routine should be called during a resume after
9807c478bd9Sstevel@tonic-gate  *    a successful suspend has been done.
9817c478bd9Sstevel@tonic-gate  */
9827c478bd9Sstevel@tonic-gate /* ARGSUSED */
9837c478bd9Sstevel@tonic-gate static int
hci1394_ohci_phy_resume(hci1394_ohci_handle_t ohci_hdl)9847c478bd9Sstevel@tonic-gate hci1394_ohci_phy_resume(hci1394_ohci_handle_t ohci_hdl)
9857c478bd9Sstevel@tonic-gate {
9867c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	/* There is currently nothing to re-initialize here */
9897c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
9907c478bd9Sstevel@tonic-gate }
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_set()
9957c478bd9Sstevel@tonic-gate  *    Perform bitset operation on PHY register.
9967c478bd9Sstevel@tonic-gate  */
9977c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_set(hci1394_ohci_handle_t ohci_hdl,uint_t address,uint_t bits)9987c478bd9Sstevel@tonic-gate hci1394_ohci_phy_set(hci1394_ohci_handle_t ohci_hdl, uint_t address,
9997c478bd9Sstevel@tonic-gate     uint_t bits)
10007c478bd9Sstevel@tonic-gate {
10017c478bd9Sstevel@tonic-gate 	int status;
10027c478bd9Sstevel@tonic-gate 	uint_t reg;
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	mutex_enter(&ohci_hdl->ohci_mutex);
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	/* read the PHY register */
10107c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read_no_lock(ohci_hdl, address, &reg);
10117c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
10127c478bd9Sstevel@tonic-gate 		mutex_exit(&ohci_hdl->ohci_mutex);
10137c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	/* Set the bits and write the result back */
10177c478bd9Sstevel@tonic-gate 	reg = reg | bits;
10187c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_write_no_lock(ohci_hdl, address, reg);
10197c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
10207c478bd9Sstevel@tonic-gate 		mutex_exit(&ohci_hdl->ohci_mutex);
10217c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10227c478bd9Sstevel@tonic-gate 	}
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	mutex_exit(&ohci_hdl->ohci_mutex);
10257c478bd9Sstevel@tonic-gate 
10267c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate /*
10317c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_clr()
10327c478bd9Sstevel@tonic-gate  *    Perform bitclr operation on PHY register.
10337c478bd9Sstevel@tonic-gate  */
10347c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_clr(hci1394_ohci_handle_t ohci_hdl,uint_t address,uint_t bits)10357c478bd9Sstevel@tonic-gate hci1394_ohci_phy_clr(hci1394_ohci_handle_t ohci_hdl, uint_t address,
10367c478bd9Sstevel@tonic-gate     uint_t bits)
10377c478bd9Sstevel@tonic-gate {
10387c478bd9Sstevel@tonic-gate 	int status;
10397c478bd9Sstevel@tonic-gate 	uint_t reg;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 	mutex_enter(&ohci_hdl->ohci_mutex);
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 	/* read the PHY register */
10477c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read_no_lock(ohci_hdl, address, &reg);
10487c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
10497c478bd9Sstevel@tonic-gate 		mutex_exit(&ohci_hdl->ohci_mutex);
10507c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10517c478bd9Sstevel@tonic-gate 	}
10527c478bd9Sstevel@tonic-gate 
10537c478bd9Sstevel@tonic-gate 	/* Set the bits and write the result back */
10547c478bd9Sstevel@tonic-gate 	reg = reg & ~bits;
10557c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_write_no_lock(ohci_hdl, address, reg);
10567c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
10577c478bd9Sstevel@tonic-gate 		mutex_exit(&ohci_hdl->ohci_mutex);
10587c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
10597c478bd9Sstevel@tonic-gate 	}
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	mutex_exit(&ohci_hdl->ohci_mutex);
10627c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate /*
10677c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_read()
10687c478bd9Sstevel@tonic-gate  *    Atomic PHY register read
10697c478bd9Sstevel@tonic-gate  */
10707c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_read(hci1394_ohci_handle_t ohci_hdl,uint_t address,uint_t * data)10717c478bd9Sstevel@tonic-gate hci1394_ohci_phy_read(hci1394_ohci_handle_t ohci_hdl, uint_t address,
10727c478bd9Sstevel@tonic-gate     uint_t *data)
10737c478bd9Sstevel@tonic-gate {
10747c478bd9Sstevel@tonic-gate 	int status;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
10777c478bd9Sstevel@tonic-gate 	mutex_enter(&ohci_hdl->ohci_mutex);
10787c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read_no_lock(ohci_hdl, address, data);
10797c478bd9Sstevel@tonic-gate 	mutex_exit(&ohci_hdl->ohci_mutex);
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	return (status);
10827c478bd9Sstevel@tonic-gate }
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate /*
10867c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_write()
10877c478bd9Sstevel@tonic-gate  *    Atomic PHY register write
10887c478bd9Sstevel@tonic-gate  */
10897c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_write(hci1394_ohci_handle_t ohci_hdl,uint_t address,uint_t data)10907c478bd9Sstevel@tonic-gate hci1394_ohci_phy_write(hci1394_ohci_handle_t ohci_hdl, uint_t address,
10917c478bd9Sstevel@tonic-gate     uint_t data)
10927c478bd9Sstevel@tonic-gate {
10937c478bd9Sstevel@tonic-gate 	int status;
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
10967c478bd9Sstevel@tonic-gate 	mutex_enter(&ohci_hdl->ohci_mutex);
10977c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_write_no_lock(ohci_hdl, address, data);
10987c478bd9Sstevel@tonic-gate 	mutex_exit(&ohci_hdl->ohci_mutex);
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 	return (status);
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate /*
11057c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_read_no_lock()
11067c478bd9Sstevel@tonic-gate  *    This routine actually performs the PHY register read.  It is seperated
11077c478bd9Sstevel@tonic-gate  *    out from phy_read so set & clr lock can perform an atomic PHY register
11087c478bd9Sstevel@tonic-gate  *    operation.  It assumes the OpenHCI mutex is held.
11097c478bd9Sstevel@tonic-gate  */
11107c478bd9Sstevel@tonic-gate static int
hci1394_ohci_phy_read_no_lock(hci1394_ohci_handle_t ohci_hdl,uint_t address,uint_t * data)11117c478bd9Sstevel@tonic-gate hci1394_ohci_phy_read_no_lock(hci1394_ohci_handle_t ohci_hdl, uint_t address,
11127c478bd9Sstevel@tonic-gate     uint_t *data)
11137c478bd9Sstevel@tonic-gate {
11147c478bd9Sstevel@tonic-gate 	uint32_t ohci_reg;
11157c478bd9Sstevel@tonic-gate 	int count;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
11197c478bd9Sstevel@tonic-gate 	ASSERT(data != NULL);
11207c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ohci_hdl->ohci_mutex));
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 	/* You can't read or write PHY register #0 */
11237c478bd9Sstevel@tonic-gate 	if (address == 0) {
11247c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
11257c478bd9Sstevel@tonic-gate 	}
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 	/* Verify phy access not in progress */
11287c478bd9Sstevel@tonic-gate 	ohci_reg = ddi_get32(ohci_hdl->ohci_reg_handle,
11297c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phy_ctrl);
11307c478bd9Sstevel@tonic-gate 	if ((ohci_reg & (OHCI_PHYC_RDREG | OHCI_PHYC_WRREG)) != 0) {
11317c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
11327c478bd9Sstevel@tonic-gate 	}
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 	/* Start the PHY register read */
11357c478bd9Sstevel@tonic-gate 	ohci_reg = OHCI_PHYC_RDREG | ((address & 0xF) <<
11367c478bd9Sstevel@tonic-gate 	    OHCI_PHYC_REGADDR_SHIFT);
11377c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle, &ohci_hdl->ohci_regs->phy_ctrl,
11387c478bd9Sstevel@tonic-gate 	    ohci_reg);
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 	/*
11417c478bd9Sstevel@tonic-gate 	 * The PHY read usually takes less than 1uS.  It is not worth having
11427c478bd9Sstevel@tonic-gate 	 * this be interrupt driven. Having this be interrupt driven would also
11437c478bd9Sstevel@tonic-gate 	 * make the bus reset and self id processing much more complex for
11447c478bd9Sstevel@tonic-gate 	 * 1995 PHY's.  We will wait up to hci1394_phy_delay_uS for the read
11457c478bd9Sstevel@tonic-gate 	 * to complete (this was initially set to 10).  I have yet to see
11467c478bd9Sstevel@tonic-gate 	 * count > 1.  The delay is a patchable variable.
11477c478bd9Sstevel@tonic-gate 	 */
11487c478bd9Sstevel@tonic-gate 	count = 0;
11497c478bd9Sstevel@tonic-gate 	while (count < hci1394_phy_delay_uS) {
11507c478bd9Sstevel@tonic-gate 		/* See if the read is done yet */
11517c478bd9Sstevel@tonic-gate 		ohci_reg = ddi_get32(ohci_hdl->ohci_reg_handle,
11527c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->phy_ctrl);
11537c478bd9Sstevel@tonic-gate 		if ((ohci_reg & OHCI_PHYC_RDDONE) != 0) {
11547c478bd9Sstevel@tonic-gate 			/*
11557c478bd9Sstevel@tonic-gate 			 * The read is done. clear the phyRegRecv interrupt. We
11567c478bd9Sstevel@tonic-gate 			 * do not have this interrupt enabled but this keeps
11577c478bd9Sstevel@tonic-gate 			 * things clean in case someone in the future does.
11587c478bd9Sstevel@tonic-gate 			 * Break out of the loop, we are done.
11597c478bd9Sstevel@tonic-gate 			 */
11607c478bd9Sstevel@tonic-gate 			ddi_put32(ohci_hdl->ohci_reg_handle,
11617c478bd9Sstevel@tonic-gate 			    &ohci_hdl->ohci_regs->intr_event_clr,
11627c478bd9Sstevel@tonic-gate 			    OHCI_INTR_PHY_REG_RCVD);
11637c478bd9Sstevel@tonic-gate 			break;
11647c478bd9Sstevel@tonic-gate 		}
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 		/*
11677c478bd9Sstevel@tonic-gate 		 * the phy read did not yet complete, wait 1uS, increment the
11687c478bd9Sstevel@tonic-gate 		 * count and try again.
11697c478bd9Sstevel@tonic-gate 		 */
11707c478bd9Sstevel@tonic-gate 		drv_usecwait(1);
11717c478bd9Sstevel@tonic-gate 		count++;
11727c478bd9Sstevel@tonic-gate 	}
11737c478bd9Sstevel@tonic-gate 
11747c478bd9Sstevel@tonic-gate 	/* Check to see if we timed out */
11757c478bd9Sstevel@tonic-gate 	if (count >= hci1394_phy_delay_uS) {
11767c478bd9Sstevel@tonic-gate 		/* we timed out, return failure */
11777c478bd9Sstevel@tonic-gate 		*data = 0;
11787c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
11797c478bd9Sstevel@tonic-gate 	}
11807c478bd9Sstevel@tonic-gate 
11817c478bd9Sstevel@tonic-gate 	/* setup the PHY read data to be returned */
11827c478bd9Sstevel@tonic-gate 	*data = (ddi_get32(ohci_hdl->ohci_reg_handle,
11837c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phy_ctrl) & OHCI_PHYC_RDDATA_MASK) >>
11847c478bd9Sstevel@tonic-gate 	    OHCI_PHYC_RDDATA_SHIFT;
11857c478bd9Sstevel@tonic-gate 
11867c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
11877c478bd9Sstevel@tonic-gate }
11887c478bd9Sstevel@tonic-gate 
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate /*
11917c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_write_no_lock()
11927c478bd9Sstevel@tonic-gate  *    This routine actually performs the PHY register write.  It is separated
11937c478bd9Sstevel@tonic-gate  *    out from phy_write so set & clr lock can perform an atomic PHY register
11947c478bd9Sstevel@tonic-gate  *    operation.  It assumes the OpenHCI mutex is held.
11957c478bd9Sstevel@tonic-gate  */
11967c478bd9Sstevel@tonic-gate static int
hci1394_ohci_phy_write_no_lock(hci1394_ohci_handle_t ohci_hdl,uint_t address,uint_t data)11977c478bd9Sstevel@tonic-gate hci1394_ohci_phy_write_no_lock(hci1394_ohci_handle_t ohci_hdl, uint_t address,
11987c478bd9Sstevel@tonic-gate     uint_t data)
11997c478bd9Sstevel@tonic-gate {
12007c478bd9Sstevel@tonic-gate 	uint32_t ohci_reg;
12017c478bd9Sstevel@tonic-gate 	int count;
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
12057c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ohci_hdl->ohci_mutex));
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	/* You can't read or write PHY register #0 */
12087c478bd9Sstevel@tonic-gate 	if (address == 0) {
12097c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12107c478bd9Sstevel@tonic-gate 	}
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate 	/* Verify phy access not in progress */
12137c478bd9Sstevel@tonic-gate 	ohci_reg = ddi_get32(ohci_hdl->ohci_reg_handle,
12147c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phy_ctrl);
12157c478bd9Sstevel@tonic-gate 	if ((ohci_reg & (OHCI_PHYC_RDREG | OHCI_PHYC_WRREG)) != 0) {
12167c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12177c478bd9Sstevel@tonic-gate 	}
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate 	/* Start the PHY register write */
12207c478bd9Sstevel@tonic-gate 	ohci_reg = OHCI_PHYC_WRREG | ((address & 0xF) <<
12217c478bd9Sstevel@tonic-gate 	    OHCI_PHYC_REGADDR_SHIFT) | (data & OHCI_PHYC_WRDATA_MASK);
12227c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
12237c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phy_ctrl, ohci_reg);
12247c478bd9Sstevel@tonic-gate 
12257c478bd9Sstevel@tonic-gate 	/*
12267c478bd9Sstevel@tonic-gate 	 * The PHY write usually takes less than 1uS.  It is not worth having
12277c478bd9Sstevel@tonic-gate 	 * this be interrupt driven. Having this be interrupt driven would also
12287c478bd9Sstevel@tonic-gate 	 * make the bus reset and self id processing much more complex. We will
12297c478bd9Sstevel@tonic-gate 	 * wait up to hci1394_phy_delay_uS for the write to complete (this was
12307c478bd9Sstevel@tonic-gate 	 * initially set to 10).  I have yet to see count > 0.  The delay is a
12317c478bd9Sstevel@tonic-gate 	 * patchable variable.
12327c478bd9Sstevel@tonic-gate 	 */
12337c478bd9Sstevel@tonic-gate 	count = 0;
12347c478bd9Sstevel@tonic-gate 	while (count < hci1394_phy_delay_uS) {
12357c478bd9Sstevel@tonic-gate 		/* See if the write is done yet */
12367c478bd9Sstevel@tonic-gate 		ohci_reg = ddi_get32(ohci_hdl->ohci_reg_handle,
12377c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->phy_ctrl);
12387c478bd9Sstevel@tonic-gate 		if ((ohci_reg & OHCI_PHYC_WRREG) == 0) {
12397c478bd9Sstevel@tonic-gate 			/*
12407c478bd9Sstevel@tonic-gate 			 * The write completed. Break out of the loop, we are
12417c478bd9Sstevel@tonic-gate 			 * done.
12427c478bd9Sstevel@tonic-gate 			 */
12437c478bd9Sstevel@tonic-gate 			break;
12447c478bd9Sstevel@tonic-gate 		}
12457c478bd9Sstevel@tonic-gate 
12467c478bd9Sstevel@tonic-gate 		/*
12477c478bd9Sstevel@tonic-gate 		 * the phy write did not yet complete, wait 1uS, increment the
12487c478bd9Sstevel@tonic-gate 		 * count and try again.
12497c478bd9Sstevel@tonic-gate 		 */
12507c478bd9Sstevel@tonic-gate 		drv_usecwait(1);
12517c478bd9Sstevel@tonic-gate 		count++;
12527c478bd9Sstevel@tonic-gate 	}
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 	/* Check to see if we timed out */
12557c478bd9Sstevel@tonic-gate 	if (count >= hci1394_phy_delay_uS) {
12567c478bd9Sstevel@tonic-gate 		/* we timed out, return failure */
12577c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
12587c478bd9Sstevel@tonic-gate 	}
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate /*
12657c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_info()
12667c478bd9Sstevel@tonic-gate  *    Return selfid word for our PHY.  This routine should ONLY be called for
12677c478bd9Sstevel@tonic-gate  *    adapters with a 1394-1995 PHY. These PHY's do not embed their own selfid
12687c478bd9Sstevel@tonic-gate  *    information in the selfid buffer so we need to do it for them in the
12697c478bd9Sstevel@tonic-gate  *    selfid complete interrupt handler.  This routine only supports building
12707c478bd9Sstevel@tonic-gate  *    selfid info for a 3 port PHY.  Since we will probably not ever see a
12717c478bd9Sstevel@tonic-gate  *    1394-1995 PHY in any production system, and if we do it will have 3 ports
12727c478bd9Sstevel@tonic-gate  *    or less, this is a pretty safe assumption.
12737c478bd9Sstevel@tonic-gate  */
12747c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_info(hci1394_ohci_handle_t ohci_hdl,uint32_t * info)12757c478bd9Sstevel@tonic-gate hci1394_ohci_phy_info(hci1394_ohci_handle_t ohci_hdl, uint32_t *info)
12767c478bd9Sstevel@tonic-gate {
12777c478bd9Sstevel@tonic-gate 	int status;
12787c478bd9Sstevel@tonic-gate 	uint32_t phy_info;
12797c478bd9Sstevel@tonic-gate 	uint32_t reg;
12807c478bd9Sstevel@tonic-gate 	int index;
12817c478bd9Sstevel@tonic-gate 	int num_ports;
12827c478bd9Sstevel@tonic-gate 	int count;
12837c478bd9Sstevel@tonic-gate 	uint32_t port_status;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
12877c478bd9Sstevel@tonic-gate 	ASSERT(info != NULL);
12887c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl->ohci_phy == H1394_PHY_1995);
12897c478bd9Sstevel@tonic-gate 
12907c478bd9Sstevel@tonic-gate 	/*
12917c478bd9Sstevel@tonic-gate 	 * Set Link on. We are using power class 0 since we have no idea what
12927c478bd9Sstevel@tonic-gate 	 * our real power class is.
12937c478bd9Sstevel@tonic-gate 	 */
12947c478bd9Sstevel@tonic-gate 	phy_info = 0x80400000;
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 	/* Add in Physical ID */
12977c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
12987c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->node_id);
12997c478bd9Sstevel@tonic-gate 	phy_info = phy_info | ((reg << IEEE1394_SELFID_PHYID_SHIFT) &
13007c478bd9Sstevel@tonic-gate 	    IEEE1394_SELFID_PHYID_MASK);
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 	/* Add in Gap Count */
13037c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read(ohci_hdl, 1, &reg);
13047c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
13057c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
13067c478bd9Sstevel@tonic-gate 	}
13077c478bd9Sstevel@tonic-gate 	phy_info = phy_info | ((reg << IEEE1394_SELFID_GAP_CNT_SHIFT) &
13087c478bd9Sstevel@tonic-gate 	    IEEE1394_SELFID_GAP_CNT_MASK);
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	/* Add in speed & ports */
13117c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read(ohci_hdl, 2, &reg);
13127c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
13137c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
13147c478bd9Sstevel@tonic-gate 	}
13157c478bd9Sstevel@tonic-gate 	phy_info = phy_info | ((reg & 0xC0) << 8);
13167c478bd9Sstevel@tonic-gate 	num_ports = reg & 0x1F;
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 	/* PHY reports that it has 0 ports?? */
13197c478bd9Sstevel@tonic-gate 	if (num_ports == 0) {
13207c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
13217c478bd9Sstevel@tonic-gate 	}
13227c478bd9Sstevel@tonic-gate 
13237c478bd9Sstevel@tonic-gate 	/* Build up the port information for each port in the PHY */
13247c478bd9Sstevel@tonic-gate 	count = 0;
13257c478bd9Sstevel@tonic-gate 	for (index = 0; index < 3; index++) {
13267c478bd9Sstevel@tonic-gate 		if (num_ports > 0) {
13277c478bd9Sstevel@tonic-gate 			status = hci1394_ohci_phy_read(ohci_hdl,
13287c478bd9Sstevel@tonic-gate 			    count + 3, &reg);
13297c478bd9Sstevel@tonic-gate 			if (status != DDI_SUCCESS) {
13307c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
13317c478bd9Sstevel@tonic-gate 			}
13327c478bd9Sstevel@tonic-gate 			/* if port is not connected */
13337c478bd9Sstevel@tonic-gate 			if ((reg & 0x04) == 0) {
13347c478bd9Sstevel@tonic-gate 				port_status =
13357c478bd9Sstevel@tonic-gate 				    IEEE1394_SELFID_PORT_NOT_CONNECTED;
13367c478bd9Sstevel@tonic-gate 
13377c478bd9Sstevel@tonic-gate 			/* else if port is connected to parent */
13387c478bd9Sstevel@tonic-gate 			} else if ((reg & 0x08) == 0) {
13397c478bd9Sstevel@tonic-gate 				port_status = IEEE1394_SELFID_PORT_TO_PARENT;
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 			/* else port is connected to child */
13427c478bd9Sstevel@tonic-gate 			} else {
13437c478bd9Sstevel@tonic-gate 				port_status = IEEE1394_SELFID_PORT_TO_CHILD;
13447c478bd9Sstevel@tonic-gate 			}
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate 			num_ports--;
13477c478bd9Sstevel@tonic-gate 		} else {
13487c478bd9Sstevel@tonic-gate 			port_status = IEEE1394_SELFID_PORT_NO_PORT;
13497c478bd9Sstevel@tonic-gate 		}
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate 		/* add in the port information */
13527c478bd9Sstevel@tonic-gate 		phy_info = phy_info | (port_status << (6 - (index * 2)));
13537c478bd9Sstevel@tonic-gate 		count++;
13547c478bd9Sstevel@tonic-gate 	}
13557c478bd9Sstevel@tonic-gate 
13567c478bd9Sstevel@tonic-gate 	/* Copy the PHY selfid info to the return parameter */
13577c478bd9Sstevel@tonic-gate 	*info = phy_info;
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate /*
13647c478bd9Sstevel@tonic-gate  * hci1394_ohci_current_busgen()
13657c478bd9Sstevel@tonic-gate  *    return the current bus generation.
13667c478bd9Sstevel@tonic-gate  */
13677c478bd9Sstevel@tonic-gate uint_t
hci1394_ohci_current_busgen(hci1394_ohci_handle_t ohci_hdl)13687c478bd9Sstevel@tonic-gate hci1394_ohci_current_busgen(hci1394_ohci_handle_t ohci_hdl)
13697c478bd9Sstevel@tonic-gate {
13707c478bd9Sstevel@tonic-gate 	uint32_t reg;
13717c478bd9Sstevel@tonic-gate 	uint_t generation_count;
13727c478bd9Sstevel@tonic-gate 
13737c478bd9Sstevel@tonic-gate 
13747c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
13777c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->self_id_count);
13787c478bd9Sstevel@tonic-gate 	generation_count = (reg & OHCI_SLFC_GEN_MASK) >> OHCI_SLFC_GEN_SHIFT;
13797c478bd9Sstevel@tonic-gate 
13807c478bd9Sstevel@tonic-gate 	return (generation_count);
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate /*
13857c478bd9Sstevel@tonic-gate  * hci1394_ohci_startup()
13867c478bd9Sstevel@tonic-gate  *    Startup the 1394 nexus driver.  This is called after all of the HW has
13877c478bd9Sstevel@tonic-gate  *    been initialized (in both attach and resume) and we are ready to
13887c478bd9Sstevel@tonic-gate  *    participate on the bus.
13897c478bd9Sstevel@tonic-gate  */
13907c478bd9Sstevel@tonic-gate int
hci1394_ohci_startup(hci1394_ohci_handle_t ohci_hdl)13917c478bd9Sstevel@tonic-gate hci1394_ohci_startup(hci1394_ohci_handle_t ohci_hdl)
13927c478bd9Sstevel@tonic-gate {
13937c478bd9Sstevel@tonic-gate 	int status;
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 
13967c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate 	/*
13997c478bd9Sstevel@tonic-gate 	 * Turn on 1394 link. This allows us to receive 1394 traffic off the
14007c478bd9Sstevel@tonic-gate 	 * bus
14017c478bd9Sstevel@tonic-gate 	 */
14027c478bd9Sstevel@tonic-gate 	hci1394_ohci_link_enable(ohci_hdl);
14037c478bd9Sstevel@tonic-gate 
14047c478bd9Sstevel@tonic-gate 	/*
14057c478bd9Sstevel@tonic-gate 	 * Reset the 1394 Bus.
14067c478bd9Sstevel@tonic-gate 	 * Need to do this so that the link layer can collect all of the self-id
14077c478bd9Sstevel@tonic-gate 	 * packets.  The Interrupt routine will cause further initialization
14087c478bd9Sstevel@tonic-gate 	 * after the bus reset has completed
14097c478bd9Sstevel@tonic-gate 	 */
14107c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_bus_reset(ohci_hdl);
14117c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
14127c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
14137c478bd9Sstevel@tonic-gate 	}
14147c478bd9Sstevel@tonic-gate 
14157c478bd9Sstevel@tonic-gate 	/* setup out initial interrupt mask and enable interrupts */
14167c478bd9Sstevel@tonic-gate 	hci1394_isr_mask_setup(ohci_hdl->soft_state);
14177c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_master_enable(ohci_hdl);
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate /*
14247c478bd9Sstevel@tonic-gate  * hci1394_ohci_postwr_addr()
14257c478bd9Sstevel@tonic-gate  *    Read the Posted Write Address registers.  This should be read when a
14267c478bd9Sstevel@tonic-gate  *    posted write error is detected to find out what transaction had an error.
14277c478bd9Sstevel@tonic-gate  */
14287c478bd9Sstevel@tonic-gate void
hci1394_ohci_postwr_addr(hci1394_ohci_handle_t ohci_hdl,uint64_t * addr)14297c478bd9Sstevel@tonic-gate hci1394_ohci_postwr_addr(hci1394_ohci_handle_t ohci_hdl, uint64_t *addr)
14307c478bd9Sstevel@tonic-gate {
14317c478bd9Sstevel@tonic-gate 	uint32_t reg;
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
14357c478bd9Sstevel@tonic-gate 	ASSERT(addr != NULL);
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 	/* read in the errored address */
14387c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
14397c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->posted_write_addrhi);
14407c478bd9Sstevel@tonic-gate 	*addr = ((uint64_t)reg) << 32;
14417c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
14427c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->posted_write_addrlo);
14437c478bd9Sstevel@tonic-gate 	*addr = *addr | (uint64_t)reg;
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate 	/*
14467c478bd9Sstevel@tonic-gate 	 * Interrupt should be cleared after reading the posted write address.
14477c478bd9Sstevel@tonic-gate 	 * See 13.2.8.1 in OpenHCI spec v1.0.
14487c478bd9Sstevel@tonic-gate 	 */
14497c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(ohci_hdl, OHCI_INTR_POST_WR_ERR);
14507c478bd9Sstevel@tonic-gate }
14517c478bd9Sstevel@tonic-gate 
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate /*
14547c478bd9Sstevel@tonic-gate  * hci1394_ohci_guid()
14557c478bd9Sstevel@tonic-gate  *    Return the adapter's GUID
14567c478bd9Sstevel@tonic-gate  */
14577c478bd9Sstevel@tonic-gate uint64_t
hci1394_ohci_guid(hci1394_ohci_handle_t ohci_hdl)14587c478bd9Sstevel@tonic-gate hci1394_ohci_guid(hci1394_ohci_handle_t ohci_hdl)
14597c478bd9Sstevel@tonic-gate {
14607c478bd9Sstevel@tonic-gate 	uint32_t reg;
14617c478bd9Sstevel@tonic-gate 	uint64_t guid;
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
14677c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->guid_hi);
14687c478bd9Sstevel@tonic-gate 	guid = ((uint64_t)reg) << 32;
14697c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
14707c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->guid_lo);
14717c478bd9Sstevel@tonic-gate 	guid = guid | (uint64_t)reg;
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	return (guid);
14747c478bd9Sstevel@tonic-gate }
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate 
14777c478bd9Sstevel@tonic-gate /*
14787c478bd9Sstevel@tonic-gate  * hci1394_ohci_csr_read()
14797c478bd9Sstevel@tonic-gate  *    Read one of the HW implemented CSR registers.  These include
14807c478bd9Sstevel@tonic-gate  *    bus_manager_id, bandwidth_available, channels_available_hi, and
14817c478bd9Sstevel@tonic-gate  *    channels_available_lo. Offset should be set to
14827c478bd9Sstevel@tonic-gate  *    OHCI_CSR_SEL_BUS_MGR_ID, OHCI_CSR_SEL_BANDWIDTH_AVAIL
14837c478bd9Sstevel@tonic-gate  *    OHCI_CSR_SEL_CHANS_AVAIL_HI, or OHCI_CSR_SEL_CHANS_AVAIL_LO.
14847c478bd9Sstevel@tonic-gate  */
14857c478bd9Sstevel@tonic-gate int
hci1394_ohci_csr_read(hci1394_ohci_handle_t ohci_hdl,uint_t offset,uint32_t * data)14867c478bd9Sstevel@tonic-gate hci1394_ohci_csr_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset,
14877c478bd9Sstevel@tonic-gate     uint32_t *data)
14887c478bd9Sstevel@tonic-gate {
14897c478bd9Sstevel@tonic-gate 	uint_t generation;
14907c478bd9Sstevel@tonic-gate 	int status;
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
14947c478bd9Sstevel@tonic-gate 	ASSERT(data != NULL);
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 	/*
14977c478bd9Sstevel@tonic-gate 	 * read the CSR register by doing a cswap with the same compare and
14987c478bd9Sstevel@tonic-gate 	 * swap value.
14997c478bd9Sstevel@tonic-gate 	 */
15007c478bd9Sstevel@tonic-gate 	generation = hci1394_ohci_current_busgen(ohci_hdl);
15017c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_csr_cswap(ohci_hdl, generation, offset, 0, 0,
15027c478bd9Sstevel@tonic-gate 	    data);
15037c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
15047c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
15057c478bd9Sstevel@tonic-gate 	}
15067c478bd9Sstevel@tonic-gate 
15077c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
15087c478bd9Sstevel@tonic-gate }
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate /*
15127c478bd9Sstevel@tonic-gate  * hci1394_ohci_csr_cswap()
15137c478bd9Sstevel@tonic-gate  *    Perform a compare/swap on one of the HW implemented CSR registers. These
15147c478bd9Sstevel@tonic-gate  *    include bus_manager_id, bandwidth_available, channels_available_hi, and
15157c478bd9Sstevel@tonic-gate  *    channels_available_lo. Offset should be set to
15167c478bd9Sstevel@tonic-gate  *    OHCI_CSR_SEL_BUS_MGR_ID, OHCI_CSR_SEL_BANDWIDTH_AVAIL
15177c478bd9Sstevel@tonic-gate  *    OHCI_CSR_SEL_CHANS_AVAIL_HI, or OHCI_CSR_SEL_CHANS_AVAIL_LO.
15187c478bd9Sstevel@tonic-gate  */
15197c478bd9Sstevel@tonic-gate int
hci1394_ohci_csr_cswap(hci1394_ohci_handle_t ohci_hdl,uint_t generation,uint_t offset,uint32_t compare,uint32_t swap,uint32_t * old)15207c478bd9Sstevel@tonic-gate hci1394_ohci_csr_cswap(hci1394_ohci_handle_t ohci_hdl, uint_t generation,
15217c478bd9Sstevel@tonic-gate     uint_t offset, uint32_t compare, uint32_t swap, uint32_t *old)
15227c478bd9Sstevel@tonic-gate {
15237c478bd9Sstevel@tonic-gate 	int count;
15247c478bd9Sstevel@tonic-gate 	uint32_t ohci_reg;
15257c478bd9Sstevel@tonic-gate 
15267c478bd9Sstevel@tonic-gate 
15277c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
15287c478bd9Sstevel@tonic-gate 	ASSERT(old != NULL);
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 	/*
15317c478bd9Sstevel@tonic-gate 	 * Make sure we have not gotten a bus reset since this action was
15327c478bd9Sstevel@tonic-gate 	 * started.
15337c478bd9Sstevel@tonic-gate 	 */
15347c478bd9Sstevel@tonic-gate 	if (generation != hci1394_ohci_current_busgen(ohci_hdl)) {
15357c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
15367c478bd9Sstevel@tonic-gate 	}
15377c478bd9Sstevel@tonic-gate 
15387c478bd9Sstevel@tonic-gate 	mutex_enter(&ohci_hdl->ohci_mutex);
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 	/* init csrData and csrCompare */
15417c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
15427c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->csr_data, swap);
15437c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
15447c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->csr_compare_data, compare);
15457c478bd9Sstevel@tonic-gate 
15467c478bd9Sstevel@tonic-gate 	/* start the compare swap */
15477c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
15487c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->csr_ctrl, offset & OHCI_CSR_SELECT);
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 	/*
15517c478bd9Sstevel@tonic-gate 	 * The CSR access should be immediate.  There in nothing that officially
15527c478bd9Sstevel@tonic-gate 	 * states this so we will wait up to 2uS just in case before we timeout.
15537c478bd9Sstevel@tonic-gate 	 * We actually perform a compare swap with both compare and swap set
15547c478bd9Sstevel@tonic-gate 	 * to the same value.  This will return the old value which is in
15557c478bd9Sstevel@tonic-gate 	 * essence, a read.
15567c478bd9Sstevel@tonic-gate 	 */
15577c478bd9Sstevel@tonic-gate 	count = 0;
15587c478bd9Sstevel@tonic-gate 	while (count < 2) {
15597c478bd9Sstevel@tonic-gate 		/* See if the compare swap is done */
15607c478bd9Sstevel@tonic-gate 		ohci_reg = ddi_get32(ohci_hdl->ohci_reg_handle,
15617c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->csr_ctrl);
15627c478bd9Sstevel@tonic-gate 		if ((ohci_reg & OHCI_CSR_DONE) != 0) {
15637c478bd9Sstevel@tonic-gate 			/* The compare swap is done, break out of the loop */
15647c478bd9Sstevel@tonic-gate 			break;
15657c478bd9Sstevel@tonic-gate 		}
15667c478bd9Sstevel@tonic-gate 		/*
15677c478bd9Sstevel@tonic-gate 		 * The compare swap has not completed yet, wait 1uS, increment
15687c478bd9Sstevel@tonic-gate 		 * the count and try again
15697c478bd9Sstevel@tonic-gate 		 */
15707c478bd9Sstevel@tonic-gate 		drv_usecwait(1);
15717c478bd9Sstevel@tonic-gate 		count++;
15727c478bd9Sstevel@tonic-gate 	}
15737c478bd9Sstevel@tonic-gate 
15747c478bd9Sstevel@tonic-gate 	/* If we timed out, return an error */
15757c478bd9Sstevel@tonic-gate 	if (count >= 2) {
15767c478bd9Sstevel@tonic-gate 		*old = 0;
15777c478bd9Sstevel@tonic-gate 		mutex_exit(&ohci_hdl->ohci_mutex);
15787c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
15797c478bd9Sstevel@tonic-gate 	}
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 	/* Copy the old data into the return parameter */
15827c478bd9Sstevel@tonic-gate 	*old = ddi_get32(ohci_hdl->ohci_reg_handle,
15837c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->csr_data);
15847c478bd9Sstevel@tonic-gate 
15857c478bd9Sstevel@tonic-gate 	mutex_exit(&ohci_hdl->ohci_mutex);
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 	/*
15887c478bd9Sstevel@tonic-gate 	 * There is a race condition in the OpenHCI design here. After checking
15897c478bd9Sstevel@tonic-gate 	 * the generation and before performing the cswap, we could get a bus
15907c478bd9Sstevel@tonic-gate 	 * reset and incorrectly set something like the bus manager.  This would
15917c478bd9Sstevel@tonic-gate 	 * put us into a condition where we would not have a bus manager and
15927c478bd9Sstevel@tonic-gate 	 * we would think there was one. If it is possible that this race
15937c478bd9Sstevel@tonic-gate 	 * condition occured, we will reset the bus to clean things up. We only
15947c478bd9Sstevel@tonic-gate 	 * care about this if the compare swap was successful.
15957c478bd9Sstevel@tonic-gate 	 */
15967c478bd9Sstevel@tonic-gate 	if (generation != hci1394_ohci_current_busgen(ohci_hdl)) {
15977c478bd9Sstevel@tonic-gate 		if (*old == compare) {
15987c478bd9Sstevel@tonic-gate 			(void) hci1394_ohci_bus_reset(ohci_hdl);
15997c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
16007c478bd9Sstevel@tonic-gate 		}
16017c478bd9Sstevel@tonic-gate 	}
16027c478bd9Sstevel@tonic-gate 
16037c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
16047c478bd9Sstevel@tonic-gate }
16057c478bd9Sstevel@tonic-gate 
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate /*
16087c478bd9Sstevel@tonic-gate  * hci1394_ohci_contender_enable()
16097c478bd9Sstevel@tonic-gate  *    Set the contender bit in the PHY.  This routine should only be called
16107c478bd9Sstevel@tonic-gate  *    if our PHY is 1394A compliant. (i.e. this routine should not be called
16117c478bd9Sstevel@tonic-gate  *    for a 1394-1995 PHY).
16127c478bd9Sstevel@tonic-gate  */
16137c478bd9Sstevel@tonic-gate int
hci1394_ohci_contender_enable(hci1394_ohci_handle_t ohci_hdl)16147c478bd9Sstevel@tonic-gate hci1394_ohci_contender_enable(hci1394_ohci_handle_t ohci_hdl)
16157c478bd9Sstevel@tonic-gate {
16167c478bd9Sstevel@tonic-gate 	int status;
16177c478bd9Sstevel@tonic-gate 
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
16207c478bd9Sstevel@tonic-gate 
16217c478bd9Sstevel@tonic-gate 	/*
16227c478bd9Sstevel@tonic-gate 	 * Make sure that phy is not a 1394-1995 phy. Those phy's do not have a
16237c478bd9Sstevel@tonic-gate 	 * contender bit to set.
16247c478bd9Sstevel@tonic-gate 	 */
16257c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_phy == H1394_PHY_1995) {
16267c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
16277c478bd9Sstevel@tonic-gate 	}
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	/* Set the Contender Bit */
16307c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_set(ohci_hdl, 0x4, OHCI_PHY_CNTDR);
16317c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
16327c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
16337c478bd9Sstevel@tonic-gate 	}
16347c478bd9Sstevel@tonic-gate 
16357c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
16367c478bd9Sstevel@tonic-gate }
16377c478bd9Sstevel@tonic-gate 
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate /*
16407c478bd9Sstevel@tonic-gate  * hci1394_ohci_root_holdoff_enable()
16417c478bd9Sstevel@tonic-gate  *    Set the root holdoff bit in the PHY. Since there are race conditions when
16427c478bd9Sstevel@tonic-gate  *    writing to PHY register 1 (which can get updated from a PHY packet off the
16437c478bd9Sstevel@tonic-gate  *    bus), we cache this state until a "long" bus reset is issued.
16447c478bd9Sstevel@tonic-gate  */
16457c478bd9Sstevel@tonic-gate int
hci1394_ohci_root_holdoff_enable(hci1394_ohci_handle_t ohci_hdl)16467c478bd9Sstevel@tonic-gate hci1394_ohci_root_holdoff_enable(hci1394_ohci_handle_t ohci_hdl)
16477c478bd9Sstevel@tonic-gate {
16487c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_set_root_holdoff = B_TRUE;
16517c478bd9Sstevel@tonic-gate 
16527c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 
16567c478bd9Sstevel@tonic-gate /*
16577c478bd9Sstevel@tonic-gate  * hci1394_ohci_gap_count_set()
16587c478bd9Sstevel@tonic-gate  *    Set the gap count in the PHY. Since there are race conditions when writing
16597c478bd9Sstevel@tonic-gate  *    to PHY register 1 (which can get updated from a PHY packet off the bus),
16607c478bd9Sstevel@tonic-gate  *    we cache this gap count until a "long" bus reset is issued.
16617c478bd9Sstevel@tonic-gate  */
16627c478bd9Sstevel@tonic-gate int
hci1394_ohci_gap_count_set(hci1394_ohci_handle_t ohci_hdl,uint_t gap_count)16637c478bd9Sstevel@tonic-gate hci1394_ohci_gap_count_set(hci1394_ohci_handle_t ohci_hdl, uint_t gap_count)
16647c478bd9Sstevel@tonic-gate {
16657c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_set_gap_count = B_TRUE;
16687c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_gap_count = gap_count & OHCI_PHY_MAX_GAP;
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate 
16747c478bd9Sstevel@tonic-gate /*
16757c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_filter_set()
16767c478bd9Sstevel@tonic-gate  *    Enable a node (or nodes) to perform transactions to our physical
16777c478bd9Sstevel@tonic-gate  *    memory. OpenHCI allows you to disable/enable physical requests on a node
16787c478bd9Sstevel@tonic-gate  *    per node basis.  A physical request is basically a read/write to 1394
16797c478bd9Sstevel@tonic-gate  *    address space 0x0 - 0xFFFFFFFF.  This address goes out to the IO MMU (in
16807c478bd9Sstevel@tonic-gate  *    the case of a SPARC machine).  The HAL starts with all nodes unable to
16817c478bd9Sstevel@tonic-gate  *    read/write physical memory.  The Services Layer will call down and enable
16827c478bd9Sstevel@tonic-gate  *    nodes via setting a physical filter bit for that given node.  Since node
16837c478bd9Sstevel@tonic-gate  *    numbers change every bus reset, the services layer has to call down after
16847c478bd9Sstevel@tonic-gate  *    every bus reset to re-enable physical accesses. (NOTE: the hardware
16857c478bd9Sstevel@tonic-gate  *    automatically clears these bits.
16867c478bd9Sstevel@tonic-gate  */
16877c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_filter_set(hci1394_ohci_handle_t ohci_hdl,uint64_t mask,uint_t generation)16887c478bd9Sstevel@tonic-gate hci1394_ohci_phy_filter_set(hci1394_ohci_handle_t ohci_hdl, uint64_t mask,
16897c478bd9Sstevel@tonic-gate     uint_t generation)
16907c478bd9Sstevel@tonic-gate {
16917c478bd9Sstevel@tonic-gate 	uint32_t data;
16927c478bd9Sstevel@tonic-gate 
16937c478bd9Sstevel@tonic-gate 
16947c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
16957c478bd9Sstevel@tonic-gate 
16967c478bd9Sstevel@tonic-gate 	/*
16977c478bd9Sstevel@tonic-gate 	 * Make sure we have not gotten a bus reset since this action was
16987c478bd9Sstevel@tonic-gate 	 * started.
16997c478bd9Sstevel@tonic-gate 	 */
17007c478bd9Sstevel@tonic-gate 	if (generation != hci1394_ohci_current_busgen(ohci_hdl)) {
17017c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17027c478bd9Sstevel@tonic-gate 	}
17037c478bd9Sstevel@tonic-gate 
17047c478bd9Sstevel@tonic-gate 	data = (uint32_t)((mask >> 32) & 0xFFFFFFFF);
17057c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
17067c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phys_req_filterhi_set, data);
17077c478bd9Sstevel@tonic-gate 	data = (uint32_t)(mask & 0xFFFFFFFF);
17087c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
17097c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phys_req_filterlo_set, data);
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	/*
17127c478bd9Sstevel@tonic-gate 	 * There is a race condition in the OpenHCI design here. After checking
17137c478bd9Sstevel@tonic-gate 	 * the generation and before setting the physical filter bits, we could
17147c478bd9Sstevel@tonic-gate 	 * get a bus reset and incorrectly set the physical filter bits.  If it
17157c478bd9Sstevel@tonic-gate 	 * is possible that this race condition occured, we will reset the bus
17167c478bd9Sstevel@tonic-gate 	 * to clean things up.
17177c478bd9Sstevel@tonic-gate 	 */
17187c478bd9Sstevel@tonic-gate 	if (generation != hci1394_ohci_current_busgen(ohci_hdl)) {
17197c478bd9Sstevel@tonic-gate 		(void) hci1394_ohci_bus_reset(ohci_hdl);
17207c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
17217c478bd9Sstevel@tonic-gate 	}
17227c478bd9Sstevel@tonic-gate 
17237c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
17247c478bd9Sstevel@tonic-gate }
17257c478bd9Sstevel@tonic-gate 
17267c478bd9Sstevel@tonic-gate 
17277c478bd9Sstevel@tonic-gate /*
17287c478bd9Sstevel@tonic-gate  * hci1394_ohci_phy_filter_clr()
17297c478bd9Sstevel@tonic-gate  *    Disable a node (or nodes) from performing transactions to our physical
17307c478bd9Sstevel@tonic-gate  *    memory. See hci1394_ohci_phy_filter_set() above for more info.
17317c478bd9Sstevel@tonic-gate  */
17327c478bd9Sstevel@tonic-gate int
hci1394_ohci_phy_filter_clr(hci1394_ohci_handle_t ohci_hdl,uint64_t mask,uint_t generation)17337c478bd9Sstevel@tonic-gate hci1394_ohci_phy_filter_clr(hci1394_ohci_handle_t ohci_hdl,
17347c478bd9Sstevel@tonic-gate     uint64_t mask, uint_t generation)
17357c478bd9Sstevel@tonic-gate {
17367c478bd9Sstevel@tonic-gate 	uint32_t data;
17377c478bd9Sstevel@tonic-gate 
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 	/*
17427c478bd9Sstevel@tonic-gate 	 * Make sure we have not gotten a bus reset since this action was
17437c478bd9Sstevel@tonic-gate 	 * started.
17447c478bd9Sstevel@tonic-gate 	 */
17457c478bd9Sstevel@tonic-gate 	if (generation != hci1394_ohci_current_busgen(ohci_hdl)) {
17467c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17477c478bd9Sstevel@tonic-gate 	}
17487c478bd9Sstevel@tonic-gate 
17497c478bd9Sstevel@tonic-gate 	data = (uint32_t)((mask >> 32) & 0xFFFFFFFF);
17507c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
17517c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phys_req_filterhi_clr, data);
17527c478bd9Sstevel@tonic-gate 	data = (uint32_t)(mask & 0xFFFFFFFF);
17537c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
17547c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->phys_req_filterlo_clr, data);
17557c478bd9Sstevel@tonic-gate 
17567c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
17577c478bd9Sstevel@tonic-gate }
17587c478bd9Sstevel@tonic-gate 
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate /*
17617c478bd9Sstevel@tonic-gate  * hci1394_ohci_bus_reset_short()
17627c478bd9Sstevel@tonic-gate  *    Perform a 1394A short bus reset.  This function should only be called
17637c478bd9Sstevel@tonic-gate  *    on an adapter with a 1394A PHY (or later).
17647c478bd9Sstevel@tonic-gate  */
17657c478bd9Sstevel@tonic-gate int
hci1394_ohci_bus_reset_short(hci1394_ohci_handle_t ohci_hdl)17667c478bd9Sstevel@tonic-gate hci1394_ohci_bus_reset_short(hci1394_ohci_handle_t ohci_hdl)
17677c478bd9Sstevel@tonic-gate {
17687c478bd9Sstevel@tonic-gate 	int status;
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
17717c478bd9Sstevel@tonic-gate 
17727c478bd9Sstevel@tonic-gate 	/*
17737c478bd9Sstevel@tonic-gate 	 * Make sure that phy is not a 1394-1995 phy. Those phy's do not have a
17747c478bd9Sstevel@tonic-gate 	 * contender bit to set.
17757c478bd9Sstevel@tonic-gate 	 */
17767c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_phy == H1394_PHY_1995) {
17777c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17787c478bd9Sstevel@tonic-gate 	}
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 	/* Initiate the short bus reset */
17817c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_set(ohci_hdl, 0x5, OHCI_PHY_ISBR);
17827c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
17837c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
17847c478bd9Sstevel@tonic-gate 	}
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate 	return (status);
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate 
17907c478bd9Sstevel@tonic-gate /*
17917c478bd9Sstevel@tonic-gate  * hci1394_ohci_cfgrom_update()
17927c478bd9Sstevel@tonic-gate  *    Update the config rom with the provided contents.  The config rom is
17937c478bd9Sstevel@tonic-gate  *    provided as a byte stream which is multiple of 4 bytes large.  The
17947c478bd9Sstevel@tonic-gate  *    size is passed as a quadlet (4 bytes) count.  The entire contents
17957c478bd9Sstevel@tonic-gate  *    of the config rom is updated at once.  We do not provide a partial
17967c478bd9Sstevel@tonic-gate  *    update interface.
17977c478bd9Sstevel@tonic-gate  */
17987c478bd9Sstevel@tonic-gate void
hci1394_ohci_cfgrom_update(hci1394_ohci_handle_t ohci_hdl,void * local_buf,uint_t quadlet_count)17997c478bd9Sstevel@tonic-gate hci1394_ohci_cfgrom_update(hci1394_ohci_handle_t ohci_hdl, void *local_buf,
18007c478bd9Sstevel@tonic-gate     uint_t quadlet_count)
18017c478bd9Sstevel@tonic-gate {
18027c478bd9Sstevel@tonic-gate 	uint32_t *data;
18037c478bd9Sstevel@tonic-gate 
18047c478bd9Sstevel@tonic-gate 
18057c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
18067c478bd9Sstevel@tonic-gate 	ASSERT(local_buf != NULL);
18077c478bd9Sstevel@tonic-gate 
18087c478bd9Sstevel@tonic-gate 	data = (uint32_t *)local_buf;
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate 	/* zero out the config ROM header to start */
18117c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
18127c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->config_rom_hdr, 0);
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 	/* copy Services Layer buffer into config rom buffer */
18157c478bd9Sstevel@tonic-gate 	ddi_rep_put8(ohci_hdl->ohci_cfgrom.bi_handle, local_buf,
18167c478bd9Sstevel@tonic-gate 	    (uint8_t *)ohci_hdl->ohci_cfgrom.bi_kaddr, quadlet_count << 2,
18177c478bd9Sstevel@tonic-gate 	    DDI_DEV_AUTOINCR);
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate 	(void) ddi_dma_sync(ohci_hdl->ohci_cfgrom.bi_dma_handle, 0,
18207c478bd9Sstevel@tonic-gate 	    quadlet_count << 2, DDI_DMA_SYNC_FORDEV);
18217c478bd9Sstevel@tonic-gate 
18227c478bd9Sstevel@tonic-gate 	/*
18237c478bd9Sstevel@tonic-gate 	 * setup OHCI bus options and config rom hdr registers. We need to swap
18247c478bd9Sstevel@tonic-gate 	 * the config rom header and bus options on an X86 machine since the
18257c478bd9Sstevel@tonic-gate 	 * data is provided to us as a byte stream and the OHCI registers expect
18267c478bd9Sstevel@tonic-gate 	 * a big endian 32-bit number.
18277c478bd9Sstevel@tonic-gate 	 */
18287c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
18297c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->bus_options, OHCI_SWAP32(data[2]));
18307c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
18317c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->config_rom_hdr, OHCI_SWAP32(data[0]));
18327c478bd9Sstevel@tonic-gate }
18337c478bd9Sstevel@tonic-gate 
18347c478bd9Sstevel@tonic-gate 
18357c478bd9Sstevel@tonic-gate /*
18367c478bd9Sstevel@tonic-gate  * hci1394_ohci_nodeid_get()
18377c478bd9Sstevel@tonic-gate  *    Return our current nodeid (bus #/Node #)
18387c478bd9Sstevel@tonic-gate  */
18397c478bd9Sstevel@tonic-gate void
hci1394_ohci_nodeid_get(hci1394_ohci_handle_t ohci_hdl,uint_t * nodeid)18407c478bd9Sstevel@tonic-gate hci1394_ohci_nodeid_get(hci1394_ohci_handle_t ohci_hdl, uint_t *nodeid)
18417c478bd9Sstevel@tonic-gate {
18427c478bd9Sstevel@tonic-gate 	uint32_t reg;
18437c478bd9Sstevel@tonic-gate 
18447c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
18457c478bd9Sstevel@tonic-gate 	ASSERT(nodeid != NULL);
18467c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
18477c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->node_id);
18487c478bd9Sstevel@tonic-gate 	*nodeid = (reg & 0xFFFF) << 16;
18497c478bd9Sstevel@tonic-gate }
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 
18527c478bd9Sstevel@tonic-gate /*
18537c478bd9Sstevel@tonic-gate  * hci1394_ohci_nodeid_set()
18547c478bd9Sstevel@tonic-gate  *    Set our current nodeid (bus #/Node #).  This actually sets our bus number.
18557c478bd9Sstevel@tonic-gate  *    Our node number cannot be set by software.  This is usually trigered via
18567c478bd9Sstevel@tonic-gate  *    a write to the CSR NODEIDS register.
18577c478bd9Sstevel@tonic-gate  */
18587c478bd9Sstevel@tonic-gate void
hci1394_ohci_nodeid_set(hci1394_ohci_handle_t ohci_hdl,uint_t nodeid)18597c478bd9Sstevel@tonic-gate hci1394_ohci_nodeid_set(hci1394_ohci_handle_t ohci_hdl, uint_t nodeid)
18607c478bd9Sstevel@tonic-gate {
18617c478bd9Sstevel@tonic-gate 	uint32_t reg;
18627c478bd9Sstevel@tonic-gate 
18637c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
18647c478bd9Sstevel@tonic-gate 
18657c478bd9Sstevel@tonic-gate 	reg = ((nodeid & 0xFFC00000) >> 16);
18667c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
18677c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->node_id, reg);
18687c478bd9Sstevel@tonic-gate }
18697c478bd9Sstevel@tonic-gate 
18707c478bd9Sstevel@tonic-gate 
18717c478bd9Sstevel@tonic-gate /*
18727c478bd9Sstevel@tonic-gate  * hci1394_ohci_nodeid_info()
18737c478bd9Sstevel@tonic-gate  *    Return our current nodeid (bus #/Node #).  This also returns whether or
18747c478bd9Sstevel@tonic-gate  *    not our nodeid error bit is set.  This is useful in determining if the
18757c478bd9Sstevel@tonic-gate  *    bus reset completed without errors in the selfid complete interrupt
18767c478bd9Sstevel@tonic-gate  *    processing.
18777c478bd9Sstevel@tonic-gate  */
18787c478bd9Sstevel@tonic-gate void
hci1394_ohci_nodeid_info(hci1394_ohci_handle_t ohci_hdl,uint_t * nodeid,boolean_t * error)18797c478bd9Sstevel@tonic-gate hci1394_ohci_nodeid_info(hci1394_ohci_handle_t ohci_hdl, uint_t *nodeid,
18807c478bd9Sstevel@tonic-gate     boolean_t *error)
18817c478bd9Sstevel@tonic-gate {
18827c478bd9Sstevel@tonic-gate 	uint32_t reg;
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
18857c478bd9Sstevel@tonic-gate 	ASSERT(nodeid != NULL);
18867c478bd9Sstevel@tonic-gate 
18877c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
18887c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->node_id);
18897c478bd9Sstevel@tonic-gate 	*nodeid = reg & 0xFFFF;
18907c478bd9Sstevel@tonic-gate 	if ((reg & OHCI_NDID_IDVALID) == 0) {
18917c478bd9Sstevel@tonic-gate 		*error = B_TRUE;
18927c478bd9Sstevel@tonic-gate 	} else {
18937c478bd9Sstevel@tonic-gate 		*error = B_FALSE;
18947c478bd9Sstevel@tonic-gate 	}
18957c478bd9Sstevel@tonic-gate }
18967c478bd9Sstevel@tonic-gate 
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate /*
18997c478bd9Sstevel@tonic-gate  * hci1394_ohci_cycletime_get()
19007c478bd9Sstevel@tonic-gate  *    Return the current cycle time
19017c478bd9Sstevel@tonic-gate  */
19027c478bd9Sstevel@tonic-gate void
hci1394_ohci_cycletime_get(hci1394_ohci_handle_t ohci_hdl,uint32_t * cycle_time)19037c478bd9Sstevel@tonic-gate hci1394_ohci_cycletime_get(hci1394_ohci_handle_t ohci_hdl,
19047c478bd9Sstevel@tonic-gate     uint32_t *cycle_time)
19057c478bd9Sstevel@tonic-gate {
19067c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
19077c478bd9Sstevel@tonic-gate 	ASSERT(cycle_time != NULL);
19087c478bd9Sstevel@tonic-gate 	*cycle_time = ddi_get32(ohci_hdl->ohci_reg_handle,
19097c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->isoch_cycle_timer);
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate 
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate /*
19147c478bd9Sstevel@tonic-gate  * hci1394_ohci_cycletime_get()
19157c478bd9Sstevel@tonic-gate  *    Set the cycle time
19167c478bd9Sstevel@tonic-gate  */
19177c478bd9Sstevel@tonic-gate void
hci1394_ohci_cycletime_set(hci1394_ohci_handle_t ohci_hdl,uint32_t cycle_time)19187c478bd9Sstevel@tonic-gate hci1394_ohci_cycletime_set(hci1394_ohci_handle_t ohci_hdl,
19197c478bd9Sstevel@tonic-gate     uint32_t cycle_time)
19207c478bd9Sstevel@tonic-gate {
19217c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
19227c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
19237c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->isoch_cycle_timer, cycle_time);
19247c478bd9Sstevel@tonic-gate }
19257c478bd9Sstevel@tonic-gate 
19267c478bd9Sstevel@tonic-gate 
19277c478bd9Sstevel@tonic-gate /*
19287c478bd9Sstevel@tonic-gate  * hci1394_ohci_bustime_get()
19297c478bd9Sstevel@tonic-gate  *    Return the current bus time.
19307c478bd9Sstevel@tonic-gate  */
19317c478bd9Sstevel@tonic-gate void
hci1394_ohci_bustime_get(hci1394_ohci_handle_t ohci_hdl,uint32_t * bus_time)19327c478bd9Sstevel@tonic-gate hci1394_ohci_bustime_get(hci1394_ohci_handle_t ohci_hdl, uint32_t *bus_time)
19337c478bd9Sstevel@tonic-gate {
19347c478bd9Sstevel@tonic-gate 	uint32_t bus_time1;
19357c478bd9Sstevel@tonic-gate 	uint32_t bus_time2;
19367c478bd9Sstevel@tonic-gate 	uint32_t cycle_time;
19377c478bd9Sstevel@tonic-gate 
19387c478bd9Sstevel@tonic-gate 
19397c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
19407c478bd9Sstevel@tonic-gate 	ASSERT(bus_time != NULL);
19417c478bd9Sstevel@tonic-gate 
19427c478bd9Sstevel@tonic-gate 	/*
19437c478bd9Sstevel@tonic-gate 	 * The bus time is composed of a portion of the cycle time and the
19447c478bd9Sstevel@tonic-gate 	 * cycle time rollover count (ohci_bustime_count). There is a race
19457c478bd9Sstevel@tonic-gate 	 * condition where we read the rollover count and then the cycle
19467c478bd9Sstevel@tonic-gate 	 * timer rolls over.  This is the reason for the double read of the
19477c478bd9Sstevel@tonic-gate 	 * rollover count.
19487c478bd9Sstevel@tonic-gate 	 */
19497c478bd9Sstevel@tonic-gate 	do {
19507c478bd9Sstevel@tonic-gate 		bus_time1 = ohci_hdl->ohci_bustime_count;
19517c478bd9Sstevel@tonic-gate 		cycle_time = ddi_get32(ohci_hdl->ohci_reg_handle,
19527c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->isoch_cycle_timer);
19537c478bd9Sstevel@tonic-gate 		bus_time2 = ohci_hdl->ohci_bustime_count;
19547c478bd9Sstevel@tonic-gate 	} while (bus_time1 != bus_time2);
19557c478bd9Sstevel@tonic-gate 
19567c478bd9Sstevel@tonic-gate 	*bus_time = (bus_time2 << 7) | (cycle_time >> 25);
19577c478bd9Sstevel@tonic-gate }
19587c478bd9Sstevel@tonic-gate 
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate /*
19617c478bd9Sstevel@tonic-gate  * hci1394_ohci_bustime_set()
19627c478bd9Sstevel@tonic-gate  *    Set the cycle timer rollover portion of the bus time.
19637c478bd9Sstevel@tonic-gate  */
19647c478bd9Sstevel@tonic-gate void
hci1394_ohci_bustime_set(hci1394_ohci_handle_t ohci_hdl,uint32_t bus_time)19657c478bd9Sstevel@tonic-gate hci1394_ohci_bustime_set(hci1394_ohci_handle_t ohci_hdl, uint32_t bus_time)
19667c478bd9Sstevel@tonic-gate {
19677c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
19687c478bd9Sstevel@tonic-gate 
19697c478bd9Sstevel@tonic-gate 	/*
19707c478bd9Sstevel@tonic-gate 	 * we will start with the cycle 64 seconds interrupt disabled. If this
19717c478bd9Sstevel@tonic-gate 	 * is the first write to bus time, enable the interrupt.
19727c478bd9Sstevel@tonic-gate 	 */
19737c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_bustime_enabled == B_FALSE) {
19747c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_bustime_enabled = B_TRUE;
19757c478bd9Sstevel@tonic-gate 		/* Clear the cycle64Seconds interrupt then enable it */
19767c478bd9Sstevel@tonic-gate 		hci1394_ohci_intr_clear(ohci_hdl, OHCI_INTR_CYC_64_SECS);
19777c478bd9Sstevel@tonic-gate 		hci1394_ohci_intr_enable(ohci_hdl, OHCI_INTR_CYC_64_SECS);
19787c478bd9Sstevel@tonic-gate 	}
19797c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_bustime_count = (bus_time >> 7);
19807c478bd9Sstevel@tonic-gate }
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate 
19837c478bd9Sstevel@tonic-gate /*
19847c478bd9Sstevel@tonic-gate  * hci1394_ohci_atreq_retries_get()
19857c478bd9Sstevel@tonic-gate  *    Get the number of atreq retries we will perform.
19867c478bd9Sstevel@tonic-gate  */
19877c478bd9Sstevel@tonic-gate void
hci1394_ohci_atreq_retries_get(hci1394_ohci_handle_t ohci_hdl,uint_t * atreq_retries)19887c478bd9Sstevel@tonic-gate hci1394_ohci_atreq_retries_get(hci1394_ohci_handle_t ohci_hdl,
19897c478bd9Sstevel@tonic-gate     uint_t *atreq_retries)
19907c478bd9Sstevel@tonic-gate {
19917c478bd9Sstevel@tonic-gate 	uint32_t reg;
19927c478bd9Sstevel@tonic-gate 
19937c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
19947c478bd9Sstevel@tonic-gate 	ASSERT(atreq_retries != NULL);
19957c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
19967c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_retries);
19977c478bd9Sstevel@tonic-gate 	*atreq_retries = reg & OHCI_RET_MAX_ATREQ_MASK;
19987c478bd9Sstevel@tonic-gate }
19997c478bd9Sstevel@tonic-gate 
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate /*
20027c478bd9Sstevel@tonic-gate  * hci1394_ohci_atreq_retries_get()
20037c478bd9Sstevel@tonic-gate  *    Set the number of atreq retries we will perform.
20047c478bd9Sstevel@tonic-gate  */
20057c478bd9Sstevel@tonic-gate void
hci1394_ohci_atreq_retries_set(hci1394_ohci_handle_t ohci_hdl,uint_t atreq_retries)20067c478bd9Sstevel@tonic-gate hci1394_ohci_atreq_retries_set(hci1394_ohci_handle_t ohci_hdl,
20077c478bd9Sstevel@tonic-gate     uint_t atreq_retries)
20087c478bd9Sstevel@tonic-gate {
20097c478bd9Sstevel@tonic-gate 	uint32_t reg;
20107c478bd9Sstevel@tonic-gate 
20117c478bd9Sstevel@tonic-gate 
20127c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
20137c478bd9Sstevel@tonic-gate 
20147c478bd9Sstevel@tonic-gate 	mutex_enter(&ohci_hdl->ohci_mutex);
20157c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
20167c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_retries);
20177c478bd9Sstevel@tonic-gate 	reg = reg & ~OHCI_RET_MAX_ATREQ_MASK;
20187c478bd9Sstevel@tonic-gate 	reg = reg | (atreq_retries & OHCI_RET_MAX_ATREQ_MASK);
20197c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
20207c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_retries, reg);
20217c478bd9Sstevel@tonic-gate 	mutex_exit(&ohci_hdl->ohci_mutex);
20227c478bd9Sstevel@tonic-gate }
20237c478bd9Sstevel@tonic-gate 
20247c478bd9Sstevel@tonic-gate 
20257c478bd9Sstevel@tonic-gate /*
20267c478bd9Sstevel@tonic-gate  * hci1394_ohci_isr_cycle64seconds()
20277c478bd9Sstevel@tonic-gate  *    Interrupt handler for the cycle64seconds interrupt.
20287c478bd9Sstevel@tonic-gate  */
20297c478bd9Sstevel@tonic-gate void
hci1394_ohci_isr_cycle64seconds(hci1394_ohci_handle_t ohci_hdl)20307c478bd9Sstevel@tonic-gate hci1394_ohci_isr_cycle64seconds(hci1394_ohci_handle_t ohci_hdl)
20317c478bd9Sstevel@tonic-gate {
20327c478bd9Sstevel@tonic-gate 	uint32_t cycle_time;
20337c478bd9Sstevel@tonic-gate 
20347c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(ohci_hdl, OHCI_INTR_CYC_64_SECS);
20377c478bd9Sstevel@tonic-gate 	cycle_time = ddi_get32(ohci_hdl->ohci_reg_handle,
20387c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->isoch_cycle_timer);
20397c478bd9Sstevel@tonic-gate 
20407c478bd9Sstevel@tonic-gate 	/*
20417c478bd9Sstevel@tonic-gate 	 * cycle64second interrupts when the MSBit in the cycle timer changes
20427c478bd9Sstevel@tonic-gate 	 * state.  We only care about rollover so we will increment only when
20437c478bd9Sstevel@tonic-gate 	 * the MSBit is set to 0.
20447c478bd9Sstevel@tonic-gate 	 */
20457c478bd9Sstevel@tonic-gate 	if ((cycle_time & 0x80000000) == 0) {
20467c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_bustime_count++;
20477c478bd9Sstevel@tonic-gate 	}
20487c478bd9Sstevel@tonic-gate }
20497c478bd9Sstevel@tonic-gate 
20507c478bd9Sstevel@tonic-gate 
20517c478bd9Sstevel@tonic-gate /*
20527c478bd9Sstevel@tonic-gate  * hci1394_ohci_isr_phy()
20537c478bd9Sstevel@tonic-gate  *    Interrupt handler for a PHY event
20547c478bd9Sstevel@tonic-gate  */
20557c478bd9Sstevel@tonic-gate void
hci1394_ohci_isr_phy(hci1394_ohci_handle_t ohci_hdl)20567c478bd9Sstevel@tonic-gate hci1394_ohci_isr_phy(hci1394_ohci_handle_t ohci_hdl)
20577c478bd9Sstevel@tonic-gate {
20587c478bd9Sstevel@tonic-gate 	uint_t phy_status;
20597c478bd9Sstevel@tonic-gate 	int status;
20607c478bd9Sstevel@tonic-gate 
20617c478bd9Sstevel@tonic-gate 
20627c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
20637c478bd9Sstevel@tonic-gate 
20647c478bd9Sstevel@tonic-gate 	/* clear the interrupt */
20657c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_clear(ohci_hdl, OHCI_INTR_PHY);
20667c478bd9Sstevel@tonic-gate 
20677c478bd9Sstevel@tonic-gate 	/* increment the statistics count */
20687c478bd9Sstevel@tonic-gate 	ohci_hdl->ohci_drvinfo->di_stats.st_phy_isr++;
20697c478bd9Sstevel@tonic-gate 
20707c478bd9Sstevel@tonic-gate 	/*
20717c478bd9Sstevel@tonic-gate 	 * If the PHY is a 1995 phy, just return since there are no status bits
20727c478bd9Sstevel@tonic-gate 	 * to read.
20737c478bd9Sstevel@tonic-gate 	 */
20747c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_phy == H1394_PHY_1995) {
20757c478bd9Sstevel@tonic-gate 		return;
20767c478bd9Sstevel@tonic-gate 	}
20777c478bd9Sstevel@tonic-gate 
20787c478bd9Sstevel@tonic-gate 	/* See why we got this interrupt */
20797c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_read(ohci_hdl, 5, &phy_status);
20807c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
20817c478bd9Sstevel@tonic-gate 		return;
20827c478bd9Sstevel@tonic-gate 	}
20837c478bd9Sstevel@tonic-gate 
20847c478bd9Sstevel@tonic-gate 	if (phy_status & OHCI_PHY_LOOP_ERR) {
20857c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_drvinfo->di_stats.st_phy_loop_err++;
20867c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "hci1394(%d): ERROR - bus loop detected",
20877c478bd9Sstevel@tonic-gate 		    ohci_hdl->ohci_drvinfo->di_instance);
20887c478bd9Sstevel@tonic-gate 	}
20897c478bd9Sstevel@tonic-gate 	if (phy_status & OHCI_PHY_PWRFAIL_ERR) {
20907c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_drvinfo->di_stats.st_phy_pwrfail_err++;
20917c478bd9Sstevel@tonic-gate 	}
20927c478bd9Sstevel@tonic-gate 	if (phy_status & OHCI_PHY_TIMEOUT_ERR) {
20937c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_drvinfo->di_stats.st_phy_timeout_err++;
20947c478bd9Sstevel@tonic-gate 	}
20957c478bd9Sstevel@tonic-gate 	if (phy_status & OHCI_PHY_PORTEVT_ERR) {
20967c478bd9Sstevel@tonic-gate 		ohci_hdl->ohci_drvinfo->di_stats.st_phy_portevt_err++;
20977c478bd9Sstevel@tonic-gate 	}
20987c478bd9Sstevel@tonic-gate 
20997c478bd9Sstevel@tonic-gate 	/* clear any set status bits */
21007c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_write(ohci_hdl, 5, phy_status);
21017c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
21027c478bd9Sstevel@tonic-gate 		return;
21037c478bd9Sstevel@tonic-gate 	}
21047c478bd9Sstevel@tonic-gate 
21057c478bd9Sstevel@tonic-gate 	/*
21067c478bd9Sstevel@tonic-gate 	 * Disable the PHY interrupt. We are getting stuck in this ISR in
21077c478bd9Sstevel@tonic-gate 	 * certain PHY implementations so we will disable the interrupt until
21087c478bd9Sstevel@tonic-gate 	 * we see a selfid complete.
21097c478bd9Sstevel@tonic-gate 	 */
21107c478bd9Sstevel@tonic-gate 	hci1394_ohci_intr_disable(ohci_hdl, OHCI_INTR_PHY);
21117c478bd9Sstevel@tonic-gate }
21127c478bd9Sstevel@tonic-gate 
21137c478bd9Sstevel@tonic-gate 
21147c478bd9Sstevel@tonic-gate /*
21157c478bd9Sstevel@tonic-gate  * hci1394_ohci_root_check
21167c478bd9Sstevel@tonic-gate  *    Returns status about if we are currently the root node on the 1394 bus.
21177c478bd9Sstevel@tonic-gate  *    returns B_TRUE if we are the root,  B_FALSE if we are not the root.
21187c478bd9Sstevel@tonic-gate  */
21197c478bd9Sstevel@tonic-gate boolean_t
hci1394_ohci_root_check(hci1394_ohci_handle_t ohci_hdl)21207c478bd9Sstevel@tonic-gate hci1394_ohci_root_check(hci1394_ohci_handle_t ohci_hdl)
21217c478bd9Sstevel@tonic-gate {
21227c478bd9Sstevel@tonic-gate 	uint32_t reg;
21237c478bd9Sstevel@tonic-gate 	int status;
21247c478bd9Sstevel@tonic-gate 
21257c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
21267c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
21277c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->node_id);
21287c478bd9Sstevel@tonic-gate 	if ((reg & OHCI_REG_NODEID_ROOT) && (reg & OHCI_NDID_IDVALID)) {
21297c478bd9Sstevel@tonic-gate 		status = B_TRUE;
21307c478bd9Sstevel@tonic-gate 	} else {
21317c478bd9Sstevel@tonic-gate 		status = B_FALSE;
21327c478bd9Sstevel@tonic-gate 	}
21337c478bd9Sstevel@tonic-gate 
21347c478bd9Sstevel@tonic-gate 	return (status);
21357c478bd9Sstevel@tonic-gate }
21367c478bd9Sstevel@tonic-gate 
21377c478bd9Sstevel@tonic-gate 
21387c478bd9Sstevel@tonic-gate /*
21397c478bd9Sstevel@tonic-gate  * hci1394_ohci_cmc_check()
21407c478bd9Sstevel@tonic-gate  *    Returns status about if we are cycle master capable. Returns
21417c478bd9Sstevel@tonic-gate  *    B_TRUE if we are the cycle master capable, B_FALSE if we are not the cycle
21427c478bd9Sstevel@tonic-gate  *    master capable.
21437c478bd9Sstevel@tonic-gate  */
21447c478bd9Sstevel@tonic-gate boolean_t
hci1394_ohci_cmc_check(hci1394_ohci_handle_t ohci_hdl)21457c478bd9Sstevel@tonic-gate hci1394_ohci_cmc_check(hci1394_ohci_handle_t ohci_hdl)
21467c478bd9Sstevel@tonic-gate {
21477c478bd9Sstevel@tonic-gate 	uint32_t reg;
21487c478bd9Sstevel@tonic-gate 	int status;
21497c478bd9Sstevel@tonic-gate 
21507c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
21517c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
21527c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->bus_options);
21537c478bd9Sstevel@tonic-gate 	if (reg & OHCI_REG_BUSOPTIONS_CMC) {
21547c478bd9Sstevel@tonic-gate 		status = B_TRUE;
21557c478bd9Sstevel@tonic-gate 	} else {
21567c478bd9Sstevel@tonic-gate 		status = B_FALSE;
21577c478bd9Sstevel@tonic-gate 	}
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 	return (status);
21607c478bd9Sstevel@tonic-gate }
21617c478bd9Sstevel@tonic-gate 
21627c478bd9Sstevel@tonic-gate 
21637c478bd9Sstevel@tonic-gate /*
21647c478bd9Sstevel@tonic-gate  * hci1394_ohci_cycle_master_enable()
21657c478bd9Sstevel@tonic-gate  *    Enables us to be cycle master.  If we are root, we will start generating
21667c478bd9Sstevel@tonic-gate  *    cycle start packets.
21677c478bd9Sstevel@tonic-gate  */
21687c478bd9Sstevel@tonic-gate void
hci1394_ohci_cycle_master_enable(hci1394_ohci_handle_t ohci_hdl)21697c478bd9Sstevel@tonic-gate hci1394_ohci_cycle_master_enable(hci1394_ohci_handle_t ohci_hdl)
21707c478bd9Sstevel@tonic-gate {
21717c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 	/* First make sure that cycleTooLong is clear */
21747c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
21757c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->intr_event_clr, OHCI_INTR_CYC_TOO_LONG);
21767c478bd9Sstevel@tonic-gate 
21777c478bd9Sstevel@tonic-gate 	/* Enable Cycle Master */
21787c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
21797c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->link_ctrl_set, OHCI_LC_CYC_MAST);
21807c478bd9Sstevel@tonic-gate }
21817c478bd9Sstevel@tonic-gate 
21827c478bd9Sstevel@tonic-gate 
21837c478bd9Sstevel@tonic-gate /*
21847c478bd9Sstevel@tonic-gate  * hci1394_ohci_cycle_master_disable()
21857c478bd9Sstevel@tonic-gate  *    Disabled us from being cycle master. If we are root, we will stop
21867c478bd9Sstevel@tonic-gate  *    generating cycle start packets.
21877c478bd9Sstevel@tonic-gate  */
21887c478bd9Sstevel@tonic-gate void
hci1394_ohci_cycle_master_disable(hci1394_ohci_handle_t ohci_hdl)21897c478bd9Sstevel@tonic-gate hci1394_ohci_cycle_master_disable(hci1394_ohci_handle_t ohci_hdl)
21907c478bd9Sstevel@tonic-gate {
21917c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 	/* disable cycle master */
21947c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
21957c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->link_ctrl_clr, OHCI_LC_CYC_MAST);
21967c478bd9Sstevel@tonic-gate }
21977c478bd9Sstevel@tonic-gate 
21987c478bd9Sstevel@tonic-gate 
21997c478bd9Sstevel@tonic-gate /*
22007c478bd9Sstevel@tonic-gate  * hci1394_ohci_resume()
22017c478bd9Sstevel@tonic-gate  *    Re-initialize the openHCI HW during a resume. (after a power suspend)
22027c478bd9Sstevel@tonic-gate  */
22037c478bd9Sstevel@tonic-gate int
hci1394_ohci_resume(hci1394_ohci_handle_t ohci_hdl)22047c478bd9Sstevel@tonic-gate hci1394_ohci_resume(hci1394_ohci_handle_t ohci_hdl)
22057c478bd9Sstevel@tonic-gate {
22067c478bd9Sstevel@tonic-gate 	uint32_t quadlet;
22077c478bd9Sstevel@tonic-gate 	int status;
22087c478bd9Sstevel@tonic-gate 
22097c478bd9Sstevel@tonic-gate 
22107c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
22117c478bd9Sstevel@tonic-gate 
22127c478bd9Sstevel@tonic-gate 	/* Re-initialize the OpenHCI chip */
22137c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_chip_init(ohci_hdl);
22147c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
22157c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
22167c478bd9Sstevel@tonic-gate 	}
22177c478bd9Sstevel@tonic-gate 
22187c478bd9Sstevel@tonic-gate 	/* Re-initialize the PHY */
22197c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_phy_resume(ohci_hdl);
22207c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
22217c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
22227c478bd9Sstevel@tonic-gate 	}
22237c478bd9Sstevel@tonic-gate 
22247c478bd9Sstevel@tonic-gate 	/* Re-initialize any 1394A features we are using */
22257c478bd9Sstevel@tonic-gate 	status = hci1394_ohci_1394a_resume(ohci_hdl);
22267c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
22277c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
22287c478bd9Sstevel@tonic-gate 	}
22297c478bd9Sstevel@tonic-gate 
22307c478bd9Sstevel@tonic-gate 	/* Tell OpenHCI where the Config ROM buffer is */
22317c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
22327c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->config_rom_maplo,
22337c478bd9Sstevel@tonic-gate 	    (uint32_t)ohci_hdl->ohci_cfgrom.bi_cookie.dmac_address);
22347c478bd9Sstevel@tonic-gate 
22357c478bd9Sstevel@tonic-gate 	/* Tell OpenHCI where the SelfId buffer is */
22367c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
22377c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->self_id_buflo,
22387c478bd9Sstevel@tonic-gate 	    (uint32_t)ohci_hdl->ohci_selfid.bi_cookie.dmac_address);
22397c478bd9Sstevel@tonic-gate 
22407c478bd9Sstevel@tonic-gate 	/* Enable selfid DMA engine */
22417c478bd9Sstevel@tonic-gate 	hci1394_ohci_selfid_enable(ohci_hdl);
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 	/*
22447c478bd9Sstevel@tonic-gate 	 * re-setup OHCI bus options and config rom hdr registers. We need to
22457c478bd9Sstevel@tonic-gate 	 * read from the config rom using ddi_rep_get8 since it is stored as
224648bbca81SDaniel Hoffman 	 * a byte stream. We need to swap the config rom header and bus options
22477c478bd9Sstevel@tonic-gate 	 * on an X86 machine since the data is a byte stream and the OHCI
22487c478bd9Sstevel@tonic-gate 	 *  registers expect a big endian 32-bit number.
22497c478bd9Sstevel@tonic-gate 	 */
22507c478bd9Sstevel@tonic-gate 	ddi_rep_get8(ohci_hdl->ohci_cfgrom.bi_handle, (uint8_t *)&quadlet,
22517c478bd9Sstevel@tonic-gate 	    &((uint8_t *)ohci_hdl->ohci_cfgrom.bi_kaddr)[8], 4,
22527c478bd9Sstevel@tonic-gate 	    DDI_DEV_AUTOINCR);
22537c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
22547c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->bus_options, OHCI_SWAP32(quadlet));
22557c478bd9Sstevel@tonic-gate 	ddi_rep_get8(ohci_hdl->ohci_cfgrom.bi_handle, (uint8_t *)&quadlet,
22567c478bd9Sstevel@tonic-gate 	    &((uint8_t *)ohci_hdl->ohci_cfgrom.bi_kaddr)[0], 4,
22577c478bd9Sstevel@tonic-gate 	    DDI_DEV_AUTOINCR);
22587c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
22597c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->config_rom_hdr, OHCI_SWAP32(quadlet));
22607c478bd9Sstevel@tonic-gate 
22617c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
22627c478bd9Sstevel@tonic-gate }
22637c478bd9Sstevel@tonic-gate 
22647c478bd9Sstevel@tonic-gate 
22657c478bd9Sstevel@tonic-gate /*
22667c478bd9Sstevel@tonic-gate  * hci1394_ohci_selfid_init()
22677c478bd9Sstevel@tonic-gate  *    Initialize the selfid buffer
22687c478bd9Sstevel@tonic-gate  */
22697c478bd9Sstevel@tonic-gate static int
hci1394_ohci_selfid_init(hci1394_ohci_handle_t ohci_hdl)22707c478bd9Sstevel@tonic-gate hci1394_ohci_selfid_init(hci1394_ohci_handle_t ohci_hdl)
22717c478bd9Sstevel@tonic-gate {
22727c478bd9Sstevel@tonic-gate 	hci1394_buf_parms_t parms;
22737c478bd9Sstevel@tonic-gate 	int status;
22747c478bd9Sstevel@tonic-gate 
22757c478bd9Sstevel@tonic-gate 
22767c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
22777c478bd9Sstevel@tonic-gate 
22787c478bd9Sstevel@tonic-gate 	/*
22797c478bd9Sstevel@tonic-gate 	 * Setup for 2K buffer, aligned on a 2Kbyte address boundary. Make sure
22807c478bd9Sstevel@tonic-gate 	 * that the buffer is not broken up into multiple cookies.  OpenHCI can
22817c478bd9Sstevel@tonic-gate 	 * only handle one address for the selfid buffer location.
22827c478bd9Sstevel@tonic-gate 	 */
22837c478bd9Sstevel@tonic-gate 	parms.bp_length = 2048;
22847c478bd9Sstevel@tonic-gate 	parms.bp_max_cookies = 1;
22857c478bd9Sstevel@tonic-gate 	parms.bp_alignment = 2048;
22867c478bd9Sstevel@tonic-gate 	status = hci1394_buf_alloc(ohci_hdl->ohci_drvinfo, &parms,
22877c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_selfid, &ohci_hdl->ohci_selfid_handle);
22887c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
22897c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
22907c478bd9Sstevel@tonic-gate 	}
22917c478bd9Sstevel@tonic-gate 
22927c478bd9Sstevel@tonic-gate 	/* Tell OpenHCI where the buffer is */
22937c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
22947c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->self_id_buflo,
22957c478bd9Sstevel@tonic-gate 	    (uint32_t)ohci_hdl->ohci_selfid.bi_cookie.dmac_address);
22967c478bd9Sstevel@tonic-gate 
22977c478bd9Sstevel@tonic-gate 	/* Enable selfid DMA engine */
22987c478bd9Sstevel@tonic-gate 	hci1394_ohci_selfid_enable(ohci_hdl);
22997c478bd9Sstevel@tonic-gate 
23007c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
23017c478bd9Sstevel@tonic-gate }
23027c478bd9Sstevel@tonic-gate 
23037c478bd9Sstevel@tonic-gate 
23047c478bd9Sstevel@tonic-gate /*
23057c478bd9Sstevel@tonic-gate  * hci1394_ohci_selfid_enable()
23067c478bd9Sstevel@tonic-gate  *    Allow selfid packets to be placed into the selfid buffer.  This should be
23077c478bd9Sstevel@tonic-gate  *    called after the selfid buffer address has been setup in the HW.
23087c478bd9Sstevel@tonic-gate  */
23097c478bd9Sstevel@tonic-gate void
hci1394_ohci_selfid_enable(hci1394_ohci_handle_t ohci_hdl)23107c478bd9Sstevel@tonic-gate hci1394_ohci_selfid_enable(hci1394_ohci_handle_t ohci_hdl)
23117c478bd9Sstevel@tonic-gate {
23127c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
23137c478bd9Sstevel@tonic-gate 
23147c478bd9Sstevel@tonic-gate 	/*
23157c478bd9Sstevel@tonic-gate 	 * Allow selfid packets to be received.  This should be called during
23167c478bd9Sstevel@tonic-gate 	 * driver attach after the selfid buffer address has been initialized.
23177c478bd9Sstevel@tonic-gate 	 *
23187c478bd9Sstevel@tonic-gate 	 * Link Control Register
23197c478bd9Sstevel@tonic-gate 	 *   rscSelfId = 1 <= bit 9
23207c478bd9Sstevel@tonic-gate 	 */
23217c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
23227c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->link_ctrl_set, OHCI_LC_RCV_SELF);
23237c478bd9Sstevel@tonic-gate }
23247c478bd9Sstevel@tonic-gate 
23257c478bd9Sstevel@tonic-gate 
23267c478bd9Sstevel@tonic-gate /*
23277c478bd9Sstevel@tonic-gate  * hci1394_ohci_selfid_read()
23287c478bd9Sstevel@tonic-gate  *    Read a word out of the selfid buffer.
23297c478bd9Sstevel@tonic-gate  */
23307c478bd9Sstevel@tonic-gate void
hci1394_ohci_selfid_read(hci1394_ohci_handle_t ohci_hdl,uint_t offset,uint32_t * data)23317c478bd9Sstevel@tonic-gate hci1394_ohci_selfid_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset,
23327c478bd9Sstevel@tonic-gate     uint32_t *data)
23337c478bd9Sstevel@tonic-gate {
23347c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
23357c478bd9Sstevel@tonic-gate 	ASSERT(data != NULL);
23367c478bd9Sstevel@tonic-gate 	*data = ddi_get32(ohci_hdl->ohci_selfid.bi_handle,
23377c478bd9Sstevel@tonic-gate 	    &((uint32_t *)ohci_hdl->ohci_selfid.bi_kaddr)[offset]);
23387c478bd9Sstevel@tonic-gate }
23397c478bd9Sstevel@tonic-gate 
23407c478bd9Sstevel@tonic-gate 
23417c478bd9Sstevel@tonic-gate /*
23427c478bd9Sstevel@tonic-gate  * hci1394_ohci_selfid_info()
23437c478bd9Sstevel@tonic-gate  *    Return the current bus generation, the number of bytes currently in the
23447c478bd9Sstevel@tonic-gate  *    selfid buffer, and if we have seen any selfid errors.
23457c478bd9Sstevel@tonic-gate  */
23467c478bd9Sstevel@tonic-gate void
hci1394_ohci_selfid_info(hci1394_ohci_handle_t ohci_hdl,uint_t * busgen,uint_t * size,boolean_t * error)23477c478bd9Sstevel@tonic-gate hci1394_ohci_selfid_info(hci1394_ohci_handle_t ohci_hdl, uint_t *busgen,
23487c478bd9Sstevel@tonic-gate     uint_t *size, boolean_t *error)
23497c478bd9Sstevel@tonic-gate {
23507c478bd9Sstevel@tonic-gate 	uint32_t reg;
23517c478bd9Sstevel@tonic-gate 
23527c478bd9Sstevel@tonic-gate 
23537c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
23547c478bd9Sstevel@tonic-gate 	ASSERT(busgen != NULL);
23557c478bd9Sstevel@tonic-gate 	ASSERT(size != NULL);
23567c478bd9Sstevel@tonic-gate 	ASSERT(error != NULL);
23577c478bd9Sstevel@tonic-gate 
23587c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
23597c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->self_id_count);
23607c478bd9Sstevel@tonic-gate 	*busgen = (reg & OHCI_SLFC_GEN_MASK) >> OHCI_SLFC_GEN_SHIFT;
23617c478bd9Sstevel@tonic-gate 	*size = reg & OHCI_SLFC_NUM_QUADS_MASK;
23627c478bd9Sstevel@tonic-gate 	if ((reg & OHCI_SLFC_ERROR) == 0) {
23637c478bd9Sstevel@tonic-gate 		*error = B_FALSE;
23647c478bd9Sstevel@tonic-gate 	} else {
23657c478bd9Sstevel@tonic-gate 		*error = B_TRUE;
23667c478bd9Sstevel@tonic-gate 	}
23677c478bd9Sstevel@tonic-gate }
23687c478bd9Sstevel@tonic-gate 
23697c478bd9Sstevel@tonic-gate 
23707c478bd9Sstevel@tonic-gate /*
23717c478bd9Sstevel@tonic-gate  * hci1394_ohci_selfid_buf_current()
23727c478bd9Sstevel@tonic-gate  *    Test if the selfid buffer is current.  Return B_TRUE if it is current and
23737c478bd9Sstevel@tonic-gate  *    B_FALSE if it is not current.
23747c478bd9Sstevel@tonic-gate  */
23757c478bd9Sstevel@tonic-gate boolean_t
hci1394_ohci_selfid_buf_current(hci1394_ohci_handle_t ohci_hdl)23767c478bd9Sstevel@tonic-gate hci1394_ohci_selfid_buf_current(hci1394_ohci_handle_t ohci_hdl)
23777c478bd9Sstevel@tonic-gate {
23787c478bd9Sstevel@tonic-gate 	uint32_t reg;
23797c478bd9Sstevel@tonic-gate 	int status;
23807c478bd9Sstevel@tonic-gate 
23817c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
23827c478bd9Sstevel@tonic-gate 
23837c478bd9Sstevel@tonic-gate 	/*
23847c478bd9Sstevel@tonic-gate 	 * if the generation stored in the selfid buffer is not equal to the
23857c478bd9Sstevel@tonic-gate 	 * generation we have previously stored, the selfid buffer is not
23867c478bd9Sstevel@tonic-gate 	 * current. (It maybe older or it maybe newer)
23877c478bd9Sstevel@tonic-gate 	 */
23887c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_selfid.bi_handle,
23897c478bd9Sstevel@tonic-gate 	    &((uint32_t *)ohci_hdl->ohci_selfid.bi_kaddr)[0]);
23907c478bd9Sstevel@tonic-gate 	if (ohci_hdl->ohci_drvinfo->di_gencnt != ((reg & OHCI_SLFC_GEN_MASK) >>
23917c478bd9Sstevel@tonic-gate 	    OHCI_SLFC_GEN_SHIFT)) {
23927c478bd9Sstevel@tonic-gate 		status = B_FALSE;
23937c478bd9Sstevel@tonic-gate 	} else {
23947c478bd9Sstevel@tonic-gate 		status = B_TRUE;
23957c478bd9Sstevel@tonic-gate 	}
23967c478bd9Sstevel@tonic-gate 
23977c478bd9Sstevel@tonic-gate 	return (status);
23987c478bd9Sstevel@tonic-gate }
23997c478bd9Sstevel@tonic-gate 
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate /*
24027c478bd9Sstevel@tonic-gate  * hci1394_ohci_selfid_sync()
24037c478bd9Sstevel@tonic-gate  *    Perform a ddi_dma_sync on the selfid buffer
24047c478bd9Sstevel@tonic-gate  */
24057c478bd9Sstevel@tonic-gate void
hci1394_ohci_selfid_sync(hci1394_ohci_handle_t ohci_hdl)24067c478bd9Sstevel@tonic-gate hci1394_ohci_selfid_sync(hci1394_ohci_handle_t ohci_hdl)
24077c478bd9Sstevel@tonic-gate {
24087c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
24097c478bd9Sstevel@tonic-gate 	(void) ddi_dma_sync(ohci_hdl->ohci_selfid.bi_dma_handle, 0,
24107c478bd9Sstevel@tonic-gate 	    ohci_hdl->ohci_selfid.bi_length, DDI_DMA_SYNC_FORKERNEL);
24117c478bd9Sstevel@tonic-gate }
24127c478bd9Sstevel@tonic-gate 
24137c478bd9Sstevel@tonic-gate 
24147c478bd9Sstevel@tonic-gate /*
24157c478bd9Sstevel@tonic-gate  * hci1394_ohci_cfgrom_init()
24167c478bd9Sstevel@tonic-gate  *    Initialize the configuration ROM buffer
24177c478bd9Sstevel@tonic-gate  */
24187c478bd9Sstevel@tonic-gate static int
hci1394_ohci_cfgrom_init(hci1394_ohci_handle_t ohci_hdl)24197c478bd9Sstevel@tonic-gate hci1394_ohci_cfgrom_init(hci1394_ohci_handle_t ohci_hdl)
24207c478bd9Sstevel@tonic-gate {
24217c478bd9Sstevel@tonic-gate 	hci1394_buf_parms_t parms;
24227c478bd9Sstevel@tonic-gate 	int status;
24237c478bd9Sstevel@tonic-gate 
24247c478bd9Sstevel@tonic-gate 
24257c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
24267c478bd9Sstevel@tonic-gate 
24277c478bd9Sstevel@tonic-gate 	/*
24287c478bd9Sstevel@tonic-gate 	 * Setup for 1K buffer, aligned at 1K address boundary, and allow no
24297c478bd9Sstevel@tonic-gate 	 * less than 4 byte data transfers. Create the Buffer.  Make sure that
24307c478bd9Sstevel@tonic-gate 	 * the buffer is not broken up into multiple cookies.  OpenHCI can only
24317c478bd9Sstevel@tonic-gate 	 * handle one address for the config ROM buffer location.
24327c478bd9Sstevel@tonic-gate 	 */
24337c478bd9Sstevel@tonic-gate 	parms.bp_length = 1024;
24347c478bd9Sstevel@tonic-gate 	parms.bp_max_cookies = 1;
24357c478bd9Sstevel@tonic-gate 	parms.bp_alignment = 1024;
24367c478bd9Sstevel@tonic-gate 	status = hci1394_buf_alloc(ohci_hdl->ohci_drvinfo, &parms,
24377c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_cfgrom, &ohci_hdl->ohci_cfgrom_handle);
24387c478bd9Sstevel@tonic-gate 	if (status != DDI_SUCCESS) {
24397c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
24407c478bd9Sstevel@tonic-gate 	}
24417c478bd9Sstevel@tonic-gate 
24427c478bd9Sstevel@tonic-gate 	/* Tell OpenHCI where the buffer is */
24437c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
24447c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->config_rom_maplo,
24457c478bd9Sstevel@tonic-gate 	    (uint32_t)ohci_hdl->ohci_cfgrom.bi_cookie.dmac_address);
24467c478bd9Sstevel@tonic-gate 
24477c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
24487c478bd9Sstevel@tonic-gate }
24497c478bd9Sstevel@tonic-gate 
24507c478bd9Sstevel@tonic-gate 
24517c478bd9Sstevel@tonic-gate /*
24527c478bd9Sstevel@tonic-gate  * hci1394_ohci_bus_capabilities()
24537c478bd9Sstevel@tonic-gate  *    Return our current bus capabilities
24547c478bd9Sstevel@tonic-gate  */
24557c478bd9Sstevel@tonic-gate void
hci1394_ohci_bus_capabilities(hci1394_ohci_handle_t ohci_hdl,uint32_t * bus_capabilities)24567c478bd9Sstevel@tonic-gate hci1394_ohci_bus_capabilities(hci1394_ohci_handle_t ohci_hdl,
24577c478bd9Sstevel@tonic-gate     uint32_t *bus_capabilities)
24587c478bd9Sstevel@tonic-gate {
24597c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
2460*2570281cSToomas Soome 
24617c478bd9Sstevel@tonic-gate 	/*
24627c478bd9Sstevel@tonic-gate 	 * read in the bus options register.  Set bits saying that we are isoch
24637c478bd9Sstevel@tonic-gate 	 * resource manager capable, Cycle master capable, and Isoch capable
24647c478bd9Sstevel@tonic-gate 	 */
24657c478bd9Sstevel@tonic-gate 	*bus_capabilities = ddi_get32(ohci_hdl->ohci_reg_handle,
24667c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->bus_options) | (OHCI_BOPT_IRMC |
24677c478bd9Sstevel@tonic-gate 	    OHCI_BOPT_CMC | OHCI_BOPT_ISC);
24687c478bd9Sstevel@tonic-gate }
24697c478bd9Sstevel@tonic-gate 
24707c478bd9Sstevel@tonic-gate 
24717c478bd9Sstevel@tonic-gate /*
24727c478bd9Sstevel@tonic-gate  * hci1394_ohci_at_active()
24737c478bd9Sstevel@tonic-gate  *    Returns status one if either of the AT engines are active.  If either AT
24747c478bd9Sstevel@tonic-gate  *    engine is active, we return B_TRUE.  If both AT engines are not active, we
24757c478bd9Sstevel@tonic-gate  *    return B_FALSE.
24767c478bd9Sstevel@tonic-gate  */
24777c478bd9Sstevel@tonic-gate boolean_t
hci1394_ohci_at_active(hci1394_ohci_handle_t ohci_hdl)24787c478bd9Sstevel@tonic-gate hci1394_ohci_at_active(hci1394_ohci_handle_t ohci_hdl)
24797c478bd9Sstevel@tonic-gate {
24807c478bd9Sstevel@tonic-gate 	uint32_t reg;
24817c478bd9Sstevel@tonic-gate 
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
24847c478bd9Sstevel@tonic-gate 
24857c478bd9Sstevel@tonic-gate 	/* see if atreq active bit set */
24867c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
24877c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_req.ctxt_ctrl_set);
24887c478bd9Sstevel@tonic-gate 	if (reg & OHCI_CC_ACTIVE_MASK) {
24897c478bd9Sstevel@tonic-gate 		/* atreq engine is still active */
24907c478bd9Sstevel@tonic-gate 		return (B_TRUE);
24917c478bd9Sstevel@tonic-gate 	}
24927c478bd9Sstevel@tonic-gate 
24937c478bd9Sstevel@tonic-gate 	/* see if atresp active bit set */
24947c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
24957c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_resp.ctxt_ctrl_set);
24967c478bd9Sstevel@tonic-gate 	if (reg & OHCI_CC_ACTIVE_MASK) {
24977c478bd9Sstevel@tonic-gate 		/* atresp engine is still active */
24987c478bd9Sstevel@tonic-gate 		return (B_TRUE);
24997c478bd9Sstevel@tonic-gate 	}
25007c478bd9Sstevel@tonic-gate 
25017c478bd9Sstevel@tonic-gate 	/* both atreq and atresp active bits are cleared */
25027c478bd9Sstevel@tonic-gate 	return (B_FALSE);
25037c478bd9Sstevel@tonic-gate }
25047c478bd9Sstevel@tonic-gate 
25057c478bd9Sstevel@tonic-gate 
25067c478bd9Sstevel@tonic-gate /*
25077c478bd9Sstevel@tonic-gate  * hci1394_ohci_atreq_start()
25087c478bd9Sstevel@tonic-gate  *    Start the atreq dma engine.  Set the address of the first descriptor
25097c478bd9Sstevel@tonic-gate  *    to read in equal to cmdptr.
25107c478bd9Sstevel@tonic-gate  */
25117c478bd9Sstevel@tonic-gate void
hci1394_ohci_atreq_start(hci1394_ohci_handle_t ohci_hdl,uint32_t cmdptr)25127c478bd9Sstevel@tonic-gate hci1394_ohci_atreq_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr)
25137c478bd9Sstevel@tonic-gate {
25147c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
25157c478bd9Sstevel@tonic-gate 
25167c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25177c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_req.cmd_ptrlo, cmdptr);
25187c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25197c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_req.ctxt_ctrl_set, OHCI_CC_RUN_MASK);
25207c478bd9Sstevel@tonic-gate }
25217c478bd9Sstevel@tonic-gate 
25227c478bd9Sstevel@tonic-gate 
25237c478bd9Sstevel@tonic-gate /*
25247c478bd9Sstevel@tonic-gate  * hci1394_ohci_atreq_wake()
25257c478bd9Sstevel@tonic-gate  *    Wake up the atreq dma engine.  This should be called when a new descriptor
25267c478bd9Sstevel@tonic-gate  *    is added to the Q and the dma engine has already be started.  It it OK to
25277c478bd9Sstevel@tonic-gate  *    call this when the DMA engine is active.
25287c478bd9Sstevel@tonic-gate  */
25297c478bd9Sstevel@tonic-gate void
hci1394_ohci_atreq_wake(hci1394_ohci_handle_t ohci_hdl)25307c478bd9Sstevel@tonic-gate hci1394_ohci_atreq_wake(hci1394_ohci_handle_t ohci_hdl)
25317c478bd9Sstevel@tonic-gate {
25327c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
25337c478bd9Sstevel@tonic-gate 
25347c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25357c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_req.ctxt_ctrl_set, OHCI_CC_WAKE_MASK);
25367c478bd9Sstevel@tonic-gate }
25377c478bd9Sstevel@tonic-gate 
25387c478bd9Sstevel@tonic-gate 
25397c478bd9Sstevel@tonic-gate /*
25407c478bd9Sstevel@tonic-gate  * hci1394_ohci_atreq_stop()
25417c478bd9Sstevel@tonic-gate  *    Stop the atreq dma engine.  No further descriptors will be read until
25427c478bd9Sstevel@tonic-gate  *    it dma engine is started again.
25437c478bd9Sstevel@tonic-gate  */
25447c478bd9Sstevel@tonic-gate void
hci1394_ohci_atreq_stop(hci1394_ohci_handle_t ohci_hdl)25457c478bd9Sstevel@tonic-gate hci1394_ohci_atreq_stop(hci1394_ohci_handle_t ohci_hdl)
25467c478bd9Sstevel@tonic-gate {
25477c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
25487c478bd9Sstevel@tonic-gate 
25497c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25507c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_req.ctxt_ctrl_clr, OHCI_CC_RUN_MASK);
25517c478bd9Sstevel@tonic-gate }
25527c478bd9Sstevel@tonic-gate 
25537c478bd9Sstevel@tonic-gate 
25547c478bd9Sstevel@tonic-gate /*
25557c478bd9Sstevel@tonic-gate  * hci1394_ohci_arresp_start()
25567c478bd9Sstevel@tonic-gate  *    Start the arresp dma engine.  Set the address of the first descriptor
25577c478bd9Sstevel@tonic-gate  *    to read in equal to cmdptr.
25587c478bd9Sstevel@tonic-gate  */
25597c478bd9Sstevel@tonic-gate void
hci1394_ohci_arresp_start(hci1394_ohci_handle_t ohci_hdl,uint32_t cmdptr)25607c478bd9Sstevel@tonic-gate hci1394_ohci_arresp_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr)
25617c478bd9Sstevel@tonic-gate {
25627c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
25637c478bd9Sstevel@tonic-gate 
25647c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25657c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_resp.cmd_ptrlo, cmdptr);
25667c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25677c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_resp.ctxt_ctrl_set, OHCI_CC_RUN_MASK);
25687c478bd9Sstevel@tonic-gate }
25697c478bd9Sstevel@tonic-gate 
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate /*
25727c478bd9Sstevel@tonic-gate  * hci1394_ohci_arresp_wake()
25737c478bd9Sstevel@tonic-gate  *    Wake up the arresp dma engine.  This should be called when a new
25747c478bd9Sstevel@tonic-gate  *    descriptor is added to the Q and the dma engine has already be started.
25757c478bd9Sstevel@tonic-gate  *    It is OK to call this when the DMA engine is active.
25767c478bd9Sstevel@tonic-gate  */
25777c478bd9Sstevel@tonic-gate void
hci1394_ohci_arresp_wake(hci1394_ohci_handle_t ohci_hdl)25787c478bd9Sstevel@tonic-gate hci1394_ohci_arresp_wake(hci1394_ohci_handle_t ohci_hdl)
25797c478bd9Sstevel@tonic-gate {
25807c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
25817c478bd9Sstevel@tonic-gate 
25827c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25837c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_resp.ctxt_ctrl_set, OHCI_CC_WAKE_MASK);
25847c478bd9Sstevel@tonic-gate }
25857c478bd9Sstevel@tonic-gate 
25867c478bd9Sstevel@tonic-gate 
25877c478bd9Sstevel@tonic-gate /*
25887c478bd9Sstevel@tonic-gate  * hci1394_ohci_atreq_stop()
25897c478bd9Sstevel@tonic-gate  *    Stop the arresp dma engine.  No further data will be received after any
25907c478bd9Sstevel@tonic-gate  *    current packets being received have finished.
25917c478bd9Sstevel@tonic-gate  */
25927c478bd9Sstevel@tonic-gate void
hci1394_ohci_arresp_stop(hci1394_ohci_handle_t ohci_hdl)25937c478bd9Sstevel@tonic-gate hci1394_ohci_arresp_stop(hci1394_ohci_handle_t ohci_hdl)
25947c478bd9Sstevel@tonic-gate {
25957c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
25967c478bd9Sstevel@tonic-gate 
25977c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
25987c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_resp.ctxt_ctrl_clr, OHCI_CC_RUN_MASK);
25997c478bd9Sstevel@tonic-gate }
26007c478bd9Sstevel@tonic-gate 
26017c478bd9Sstevel@tonic-gate 
26027c478bd9Sstevel@tonic-gate /*
26037c478bd9Sstevel@tonic-gate  * hci1394_ohci_arreq_start()
26047c478bd9Sstevel@tonic-gate  *    Start the arreq dma engine.  Set the address of the first descriptor
26057c478bd9Sstevel@tonic-gate  *    to read in equal to cmdptr.
26067c478bd9Sstevel@tonic-gate  */
26077c478bd9Sstevel@tonic-gate void
hci1394_ohci_arreq_start(hci1394_ohci_handle_t ohci_hdl,uint32_t cmdptr)26087c478bd9Sstevel@tonic-gate hci1394_ohci_arreq_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr)
26097c478bd9Sstevel@tonic-gate {
26107c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
26117c478bd9Sstevel@tonic-gate 
26127c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26137c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_req.cmd_ptrlo, cmdptr);
26147c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26157c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_req.ctxt_ctrl_set, OHCI_CC_RUN_MASK);
26167c478bd9Sstevel@tonic-gate }
26177c478bd9Sstevel@tonic-gate 
26187c478bd9Sstevel@tonic-gate 
26197c478bd9Sstevel@tonic-gate /*
26207c478bd9Sstevel@tonic-gate  * hci1394_ohci_arreq_wake()
26217c478bd9Sstevel@tonic-gate  *    Wake up the arreq dma engine.  This should be called when a new descriptor
26227c478bd9Sstevel@tonic-gate  *    is added to the Q and the dma engine has already be started.  It is OK to
26237c478bd9Sstevel@tonic-gate  *    call this when the DMA engine is active.
26247c478bd9Sstevel@tonic-gate  */
26257c478bd9Sstevel@tonic-gate void
hci1394_ohci_arreq_wake(hci1394_ohci_handle_t ohci_hdl)26267c478bd9Sstevel@tonic-gate hci1394_ohci_arreq_wake(hci1394_ohci_handle_t ohci_hdl)
26277c478bd9Sstevel@tonic-gate {
26287c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
26297c478bd9Sstevel@tonic-gate 
26307c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26317c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_req.ctxt_ctrl_set, OHCI_CC_WAKE_MASK);
26327c478bd9Sstevel@tonic-gate }
26337c478bd9Sstevel@tonic-gate 
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate /*
26367c478bd9Sstevel@tonic-gate  * hci1394_ohci_arreq_stop()
26377c478bd9Sstevel@tonic-gate  *    Stop the arreq dma engine.  No further data will be received after any
26387c478bd9Sstevel@tonic-gate  *    current packets being received have finished.
26397c478bd9Sstevel@tonic-gate  */
26407c478bd9Sstevel@tonic-gate void
hci1394_ohci_arreq_stop(hci1394_ohci_handle_t ohci_hdl)26417c478bd9Sstevel@tonic-gate hci1394_ohci_arreq_stop(hci1394_ohci_handle_t ohci_hdl)
26427c478bd9Sstevel@tonic-gate {
26437c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
26447c478bd9Sstevel@tonic-gate 
26457c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26467c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->ar_req.ctxt_ctrl_clr, OHCI_CC_RUN_MASK);
26477c478bd9Sstevel@tonic-gate }
26487c478bd9Sstevel@tonic-gate 
26497c478bd9Sstevel@tonic-gate 
26507c478bd9Sstevel@tonic-gate /*
26517c478bd9Sstevel@tonic-gate  * hci1394_ohci_atresp_start()
26527c478bd9Sstevel@tonic-gate  *    Start the atresp dma engine.  Set the address of the first descriptor
26537c478bd9Sstevel@tonic-gate  *    to read in equal to cmdptr.
26547c478bd9Sstevel@tonic-gate  */
26557c478bd9Sstevel@tonic-gate void
hci1394_ohci_atresp_start(hci1394_ohci_handle_t ohci_hdl,uint32_t cmdptr)26567c478bd9Sstevel@tonic-gate hci1394_ohci_atresp_start(hci1394_ohci_handle_t ohci_hdl, uint32_t cmdptr)
26577c478bd9Sstevel@tonic-gate {
26587c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
26597c478bd9Sstevel@tonic-gate 
26607c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26617c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_resp.cmd_ptrlo, cmdptr);
26627c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26637c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_resp.ctxt_ctrl_set, OHCI_CC_RUN_MASK);
26647c478bd9Sstevel@tonic-gate }
26657c478bd9Sstevel@tonic-gate 
26667c478bd9Sstevel@tonic-gate 
26677c478bd9Sstevel@tonic-gate /*
26687c478bd9Sstevel@tonic-gate  * hci1394_ohci_atresp_wake()
26697c478bd9Sstevel@tonic-gate  *    Wake up the atresp dma engine.  This should be called when a new
26707c478bd9Sstevel@tonic-gate  *    descriptor is added to the Q and the dma engine has already be started.
26717c478bd9Sstevel@tonic-gate  *    It is OK to call this when the DMA engine is active.
26727c478bd9Sstevel@tonic-gate  */
26737c478bd9Sstevel@tonic-gate void
hci1394_ohci_atresp_wake(hci1394_ohci_handle_t ohci_hdl)26747c478bd9Sstevel@tonic-gate hci1394_ohci_atresp_wake(hci1394_ohci_handle_t ohci_hdl)
26757c478bd9Sstevel@tonic-gate {
26767c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
26777c478bd9Sstevel@tonic-gate 
26787c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26797c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_resp.ctxt_ctrl_set, OHCI_CC_WAKE_MASK);
26807c478bd9Sstevel@tonic-gate }
26817c478bd9Sstevel@tonic-gate 
26827c478bd9Sstevel@tonic-gate 
26837c478bd9Sstevel@tonic-gate /*
26847c478bd9Sstevel@tonic-gate  * hci1394_ohci_atresp_stop()
26857c478bd9Sstevel@tonic-gate  *    Stop the atresp dma engine.  No further descriptors will be read until
26867c478bd9Sstevel@tonic-gate  *    it dma engine is started again.
26877c478bd9Sstevel@tonic-gate  */
26887c478bd9Sstevel@tonic-gate void
hci1394_ohci_atresp_stop(hci1394_ohci_handle_t ohci_hdl)26897c478bd9Sstevel@tonic-gate hci1394_ohci_atresp_stop(hci1394_ohci_handle_t ohci_hdl)
26907c478bd9Sstevel@tonic-gate {
26917c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
26927c478bd9Sstevel@tonic-gate 
26937c478bd9Sstevel@tonic-gate 	ddi_put32(ohci_hdl->ohci_reg_handle,
26947c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->at_resp.ctxt_ctrl_clr, OHCI_CC_RUN_MASK);
26957c478bd9Sstevel@tonic-gate }
26967c478bd9Sstevel@tonic-gate 
26977c478bd9Sstevel@tonic-gate 
26987c478bd9Sstevel@tonic-gate /*
26997c478bd9Sstevel@tonic-gate  * hci1394_ohci_1394a_init()
27007c478bd9Sstevel@tonic-gate  *    Initialize any 1394a features that we are using.
27017c478bd9Sstevel@tonic-gate  */
27027c478bd9Sstevel@tonic-gate /* ARGSUSED */
27037c478bd9Sstevel@tonic-gate int
hci1394_ohci_1394a_init(hci1394_ohci_handle_t ohci_hdl)27047c478bd9Sstevel@tonic-gate hci1394_ohci_1394a_init(hci1394_ohci_handle_t ohci_hdl)
27057c478bd9Sstevel@tonic-gate {
27067c478bd9Sstevel@tonic-gate 	uint32_t reg;
27077c478bd9Sstevel@tonic-gate 	int status;
27087c478bd9Sstevel@tonic-gate 
27097c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
27107c478bd9Sstevel@tonic-gate 
27117c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
27127c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_set);
27137c478bd9Sstevel@tonic-gate 	if (reg & OHCI_HC_PROG_PHY_ENBL) {
27147c478bd9Sstevel@tonic-gate 		ddi_put32(ohci_hdl->ohci_reg_handle,
27157c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->hc_ctrl_set, OHCI_HC_APHY_ENBL);
27167c478bd9Sstevel@tonic-gate 		status = hci1394_ohci_phy_set(ohci_hdl, 5,
27177c478bd9Sstevel@tonic-gate 		    (OHCI_PHY_ENBL_ACCEL | OHCI_PHY_ENBL_MULTI));
27187c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
27197c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
27207c478bd9Sstevel@tonic-gate 		}
27217c478bd9Sstevel@tonic-gate 	}
27227c478bd9Sstevel@tonic-gate 
27237c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
27247c478bd9Sstevel@tonic-gate }
27257c478bd9Sstevel@tonic-gate 
27267c478bd9Sstevel@tonic-gate 
27277c478bd9Sstevel@tonic-gate /*
27287c478bd9Sstevel@tonic-gate  * hci1394_ohci_1394a_init()
27297c478bd9Sstevel@tonic-gate  *    Re-initialize any 1394a features that we are using.
27307c478bd9Sstevel@tonic-gate  */
27317c478bd9Sstevel@tonic-gate /* ARGSUSED */
27327c478bd9Sstevel@tonic-gate int
hci1394_ohci_1394a_resume(hci1394_ohci_handle_t ohci_hdl)27337c478bd9Sstevel@tonic-gate hci1394_ohci_1394a_resume(hci1394_ohci_handle_t ohci_hdl)
27347c478bd9Sstevel@tonic-gate {
27357c478bd9Sstevel@tonic-gate 	uint32_t reg;
27367c478bd9Sstevel@tonic-gate 	int status;
27377c478bd9Sstevel@tonic-gate 
27387c478bd9Sstevel@tonic-gate 	ASSERT(ohci_hdl != NULL);
27397c478bd9Sstevel@tonic-gate 
27407c478bd9Sstevel@tonic-gate 	reg = ddi_get32(ohci_hdl->ohci_reg_handle,
27417c478bd9Sstevel@tonic-gate 	    &ohci_hdl->ohci_regs->hc_ctrl_set);
27427c478bd9Sstevel@tonic-gate 	if (reg & OHCI_HC_PROG_PHY_ENBL) {
27437c478bd9Sstevel@tonic-gate 		ddi_put32(ohci_hdl->ohci_reg_handle,
27447c478bd9Sstevel@tonic-gate 		    &ohci_hdl->ohci_regs->hc_ctrl_set, OHCI_HC_APHY_ENBL);
27457c478bd9Sstevel@tonic-gate 		status = hci1394_ohci_phy_set(ohci_hdl, 5,
27467c478bd9Sstevel@tonic-gate 		    (OHCI_PHY_ENBL_ACCEL | OHCI_PHY_ENBL_MULTI));
27477c478bd9Sstevel@tonic-gate 		if (status != DDI_SUCCESS) {
27487c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
27497c478bd9Sstevel@tonic-gate 		}
27507c478bd9Sstevel@tonic-gate 	}
27517c478bd9Sstevel@tonic-gate 
27527c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
27537c478bd9Sstevel@tonic-gate }
2754