8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * CDDL HEADER START
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * The contents of this file are subject to the terms of the
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * Common Development and Distribution License (the "License").
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * You may not use this file except in compliance with the License.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * See the License for the specific language governing permissions
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * and limitations under the License.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * When distributing Covered Code, include this CDDL HEADER in each
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * If applicable, add the following below this CDDL HEADER, with the
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * fields enclosed by brackets "[]" replaced with your own identifying
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * information: Portions Copyright [yyyy] [name of copyright owner]
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * CDDL HEADER END
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * Use is subject to license terms.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusstatic int ioat_open(dev_t *devp, int flag, int otyp, cred_t *cred);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusstatic int ioat_close(dev_t devp, int flag, int otyp, cred_t *cred);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusstatic int ioat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusstatic int ioat_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusstatic int ioat_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus 0, /* devo_refcnt */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus &mod_driverops, /* Type of module. This one is a driver */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus/* dcopy callback interface */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus 0, /* reserved */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = ddi_soft_state_init(&ioat_statep, sizeof (ioat_state_t), 1);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus if (e != 0) {
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (e);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus if (e != 0) {
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (e);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (0);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus if (e != 0) {
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (e);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (0);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_attach()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* setup the registers, save away some device info */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* initialize driver state, must be after chip init */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* create the minor node (for the ioctl) */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = ddi_create_minor_node(dip, "ioat", S_IFCHR, instance, DDI_PSEUDO,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* Enable device interrupts */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* Report that driver was loaded */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* register with dcopy */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = dcopy_device_register(state, &state->is_deviceinfo,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_detach()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * try to unregister from dcopy. Since this driver doesn't follow the
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * traditional parent/child model, we may still be in use so we can't
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * detach yet.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = dcopy_device_unregister(&state->is_device_handle);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus cmn_err(CE_NOTE, "device busy, performing asynchronous"
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus " detach\n");
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_getinfo()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus/*ARGSUSED*/
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusioat_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (e);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_open()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus/*ARGSUSED*/
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusioat_open(dev_t *devp, int flag, int otyp, cred_t *cred)
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (0);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_close()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus/*ARGSUSED*/
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusioat_close(dev_t devp, int flag, int otyp, cred_t *cred)
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (0);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_chip_init()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = ddi_regs_map_setup(state->is_dip, 1, (caddr_t *)&state->is_genregs,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* save away ioat chip info */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_num_channels = (uint_t)ddi_get8(state->is_reg_handle,
e6beb20cc8b2b323c3efa99bffc570d547089a7cmrj * If we get a bogus value, something is wrong with the H/W, fail to
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_maxxfer = (uint_t)ddi_get8(state->is_reg_handle,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_chanoff = (uintptr_t)ddi_get16(state->is_reg_handle,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_cbver = (uint_t)ddi_get8(state->is_reg_handle,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_intrdelay = (uint_t)ddi_get16(state->is_reg_handle,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_status = (uint_t)ddi_get16(state->is_reg_handle,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_capabilities = (uint_t)ddi_get32(state->is_reg_handle,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_chip_fini()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_drv_init()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus mutex_init(&state->is_mutex, NULL, MUTEX_DRIVER, NULL);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_num_dma = state->is_num_channels;
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_capabilities = state->is_capabilities;
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* read in Vendor ID */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_id = (uint64_t)pci_config_get16(handle, 0);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_id = state->is_deviceinfo.di_id << 16;
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* read in Device ID */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_id |= (uint64_t)pci_config_get16(handle, 2);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_id = state->is_deviceinfo.di_id << 32;
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* Add in chipset version */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus state->is_deviceinfo.di_id |= (uint64_t)state->is_cbver;
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus if (e != 0) {
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus cmn_err(CE_WARN, "hilevel interrupt not supported\n");
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* we don't support MSIs for v2 yet */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = ddi_add_intr(state->is_dip, 0, NULL, NULL, ioat_isr,
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus e = ddi_get_iblock_cookie(state->is_dip, 0, &state->is_iblock_cookie);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus ddi_remove_intr(state->is_dip, 0, state->is_iblock_cookie);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_drv_fini()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus ddi_remove_intr(state->is_dip, 0, state->is_iblock_cookie);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_unregister_complete()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutusioat_unregister_complete(void *device_private, int status)
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_detach_finish()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus (void) ddi_soft_state_free(ioat_statep, state->is_instance);
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_intr_enable()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* Clear any pending interrupts */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* Enable interrupts on the device */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus ddi_put8(state->is_reg_handle, &state->is_genregs[IOAT_INTRCTL],
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_intr_disable()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * disable interrupts on the device. A read of the interrupt control
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * register clears the enable bit.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * ioat_isr()
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* master interrupt enable should always be set */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* If the interrupt status bit isn't set, it's not ours */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* re-set master interrupt enable (since it clears on read) */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* see which channels generated the interrupt */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* call the intr handler for the channels */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * if interrupt status bit was set, there should have been an
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus * attention status bit set too.
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus /* re-set master interrupt enable (since it clears on read) */
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus ddi_put8(state->is_reg_handle, &state->is_genregs[IOAT_INTRCTL],
8e50dcc9f00b393d43e6aa42b820bcbf1d3e1ce4brutus return (r);