617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Use is subject to license terms.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Part of Intel(R) Manageability Engine Interface Linux driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Copyright (c) 2003 - 2008 Intel Corp.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * All rights reserved.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Redistribution and use in source and binary forms, with or without
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * modification, are permitted provided that the following conditions
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * are met:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * 1. Redistributions of source code must retain the above copyright
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * notice, this list of conditions, and the following disclaimer,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * without modification.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * 2. Redistributions in binary form must reproduce at minimum a disclaimer
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * substantially similar to the "NO WARRANTY" disclaimer below
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * ("Disclaimer") and any redistribution must be conditioned upon
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * including a substantially similar Disclaimer requirement for further
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * binary redistribution.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * 3. Neither the names of the above-listed copyright holders nor the names
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * of any contributors may be used to endorse or promote products derived
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * from this software without specific prior written permission.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Alternatively, this software may be distributed under the terms of the
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * GNU General Public License ("GPL") version 2 as published by the Free
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Software Foundation.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * NO WARRANTY
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * POSSIBILITY OF SUCH DAMAGES.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#pragma ident "@(#)heci_main.c 1.7 08/03/07 SMI"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/types.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/note.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/cmn_err.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/conf.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/ddi.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/ddi_impldefs.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/devops.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/instance.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/modctl.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/open.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/stat.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/sunddi.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/file.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/priv.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/systm.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/mkdev.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/list.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/pci.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci_data_structures.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "heci_interface.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define MAJOR_VERSION 5
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define MINOR_VERSION 0
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define QUICK_FIX_NUMBER 0
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define VER_BUILD 30
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define str(s) name(s)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define name(s) #s
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define HECI_DRIVER_VERSION str(MAJOR_VERSION) "." str(MINOR_VERSION) \
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "." str(QUICK_FIX_NUMBER) "." str(VER_BUILD)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define HECI_READ_TIMEOUT 45
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define HECI_DRIVER_NAME "heci"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci driver strings
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganchar heci_driver_name[] = HECI_DRIVER_NAME;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganchar heci_driver_string[] = "Intel(R) Management Engine Interface";
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganchar heci_driver_version[] = HECI_DRIVER_VERSION;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganchar heci_copyright[] = "Copyright (c) 2003 - 2008 Intel Corporation.";
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid * heci_soft_state_p = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#ifdef DEBUG
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint heci_debug = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#endif
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Local Function Prototypes
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_initialize(dev_info_t *dip, struct iamt_heci_device *device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan void *arg, void **result);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_quiesce(dev_info_t *dip);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_close(dev_t dev, int flag, int otyp, struct cred *cred);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_read(dev_t dev, struct uio *uio_p, cred_t *cred_p);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cred_t *cr, int *rval);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_write(dev_t dev, struct uio *uio_p, struct cred *cred);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_poll(dev_t dev, short events, int anyyet,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan short *reventsp, struct pollhead **phpp);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic struct heci_cb_private *find_read_list_entry(
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic inline int heci_fe_same_id(struct heci_file_private *fe1,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *fe2);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void heci_resume(dev_info_t *dip);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int heci_suspend(dev_info_t *dip);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic uint16_t g_sus_wd_timeout;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic struct cb_ops heci_cb_ops = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_open, /* open */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_close, /* close */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* strategy */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* print */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* dump */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_read, /* read */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_write, /* write */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_ioctl, /* ioctl */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* devmap */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* mmap */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* segmap */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_poll, /* poll */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_prop_op, /* cb_prop op */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan NULL, /* stream tab */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan D_MP /* Driver Compatability Flags */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic struct dev_ops heci_dev_ops = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DEVO_REV, /* devo_rev */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan 0, /* refcnt */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_getinfo, /* get_dev_info */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nulldev, /* identify */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nulldev, /* probe */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_attach, /* attach */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_detach, /* detach */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan nodev, /* reset */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &heci_cb_ops, /* Driver Ops */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (struct bus_ops *)NULL, /* Bus Operations */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan NULL, /* power */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_quiesce /* devo_quiesce */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Module linkage information for the kernel
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic struct modldrv modldrv = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &mod_driverops, /* Type of Module = Driver */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_driver_string, /* Driver Identifier string. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &heci_dev_ops, /* Driver Ops. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic struct modlinkage modlinkage = {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan MODREV_1, (void *)&modldrv, NULL
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan};
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Module Initialization functions.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_init(void)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int stat;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Allocate soft state */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((stat = ddi_soft_state_init(&heci_soft_state_p,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct iamt_heci_device), 1)) != DDI_SUCCESS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (stat);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((stat = mod_install(&modlinkage)) != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_soft_state_fini(&heci_soft_state_p);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (stat);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_info(struct modinfo *infop)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (mod_info(&modlinkage, infop));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganint
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan_fini(void)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int stat;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((stat = mod_remove(&modlinkage)) != 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (stat);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_soft_state_fini(&heci_soft_state_p);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (stat);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_attach - Driver Attach Routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int instance, status;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (cmd) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case DDI_ATTACH:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case DDI_RESUME:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_resume(dip);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_SUCCESS);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan default:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("%s - version %s\n", heci_driver_string, heci_driver_version);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("%s\n", heci_copyright);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = ddi_get_instance(dip); /* find out which unit */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan status = ddi_soft_state_zalloc(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (status != DDI_SUCCESS)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(device != NULL); /* can't fail - we only just allocated it */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->dip = dip;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan status = heci_initialize(dip, device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (status != DDI_SUCCESS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_soft_state_free(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan status = ddi_create_minor_node(dip, "AMT", S_IFCHR,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan MAKE_MINOR_NUM(HECI_MINOR_NUMBER, instance),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DDI_PSEUDO, 0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (status != DDI_SUCCESS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_remove_minor_node(dip, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_soft_state_free(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (status);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_probe - Device Initialization Routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_initialize(dev_info_t *dip, struct iamt_heci_device *device)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_device_acc_attr_t attr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = ddi_get_iblock_cookie(dip, 0, &device->sc_iblk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err != DDI_SUCCESS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "heci_probe():"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan " ddi_get_iblock_cookie() failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto end;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* initializes the heci device structure */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan init_heci_device(dip, device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ddi_regs_map_setup(dip, 1, (caddr_t *)&device->mem_addr, 0, 0,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &attr, &device->io_handle) != DDI_SUCCESS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "heci%d: unable to map PCI regs\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_get_instance(dip));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fini_heci_device;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = ddi_add_intr(dip, 0, &device->sc_iblk, NULL,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_isr_interrupt, (caddr_t)device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err != DDI_SUCCESS) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "heci_probe(): ddi_add_intr() failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto unmap_memory;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_hw_init(device)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "init hw failure.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto release_irq;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) heci_initialize_clients(device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto release_hw;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->wd_timeout)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_timer = timeout(heci_wd_timer, device, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci driver initialization successful.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganrelease_hw:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* disable interrupts */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->host_hw_state = read_heci_register(device, H_CSR);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_disable_interrupts(device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganrelease_irq:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_remove_intr(dip, 0, device->sc_iblk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganunmap_memory:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->mem_addr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_regs_map_free(&device->io_handle);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganfini_heci_device:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan fini_heci_device(device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganend:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cmn_err(CE_WARN, "heci driver initialization failed.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_destroy_locks(struct iamt_heci_device *device_object)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->iamthif_file_ext.file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->iamthif_file_ext.read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->iamthif_file_ext.write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->wd_file_ext.file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->wd_file_ext.read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->wd_file_ext.write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_destroy(&device_object->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&device_object->iamthif_file_ext.rx_wait);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&device_object->wd_file_ext.rx_wait);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&device_object->wait_recvd_msg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan cv_destroy(&device_object->wait_stop_wd);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_remove - Device Removal Routine
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @pdev: PCI device information struct
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_remove is called by the PCI subsystem to alert the driver
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * that it should release a PCI device.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, ddi_get_instance(dip));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(dev != NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (cmd) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case DDI_SUSPEND:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = heci_suspend(dip);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_SUCCESS);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case DDI_DETACH:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan default:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_timer)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) untimeout(dev->wd_timer);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_file_ext.state == HECI_FILE_CONNECTED &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timeout) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timeout = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(dev->wd_data, stop_wd_params,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->stop = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->host_buffer_is_empty &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_creds(dev, &dev->wd_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_wd(dev)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("send stop WD failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(dev, &dev->wd_file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_pending = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_stoped = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (!dev->wd_stoped && err != -1) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&dev->wait_stop_wd,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &dev->device_lock, 10*HZ, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!dev->wd_stoped) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("stop wd failed to complete.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("stop wd complete.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) heci_disconnect_host_client(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->iamthif_file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_file_ext.state = HECI_FILE_DISCONNECTING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) heci_disconnect_host_client(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->wd_file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* remove entry if already in list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("list del iamthif and wd file list.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev, dev->wd_file_ext.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.file = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* disable interrupts */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_disable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_remove_intr(dip, 0, dev->sc_iblk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->work)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_taskq_destroy(dev->work);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->reinit_tsk)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_taskq_destroy(dev->reinit_tsk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->mem_addr)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_regs_map_free(&dev->io_handle);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->me_clients && dev->num_heci_me_clients > 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(dev->me_clients, sizeof (struct heci_me_client) *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->num_heci_me_clients);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
8afb13749167915c9ce99a2351e2085dd1935e64Vincent Wang dev->num_heci_me_clients = 0;
8afb13749167915c9ce99a2351e2085dd1935e64Vincent Wang
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_destroy_locks(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_remove_minor_node(dip, NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_soft_state_free(heci_soft_state_p, ddi_get_instance(dip));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_SUCCESS);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int error = DDI_SUCCESS;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int minor, instance;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(dip))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (cmd) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case DDI_INFO_DEVT2DEVINFO:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor((dev_t)arg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!(device = ddi_get_soft_state(heci_soft_state_p, instance)))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *result = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *result = device->dip;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case DDI_INFO_DEVT2INSTANCE:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor((dev_t)arg);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *result = (void *)((long)minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan default:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan error = DDI_FAILURE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (error);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_clear_list - remove all callbacks associated with file
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * from heci_cb_list
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: file information struct
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @heci_cb_list: callbacks list
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_clear_list is called to clear resources associated with file
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * when application calls close function or Ctrl-C was pressed
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 1 if callback removed from the list, 0 otherwise
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_clear_list(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file, struct list_node *heci_cb_list)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file_temp;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* list all list member */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_cb_list, cb_list, struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_temp = (struct heci_file *)priv_cb_pos->file_object;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check if list member associated with a file */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_temp == file) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* remove member from the list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check if cb equal to current iamthif cb */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_current_cb == priv_cb_pos) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* send flow control to iamthif client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_flow_control(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->iamthif_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("sending flow control failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* free all allocated buffers */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_cb_pos);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_clear_lists - remove all callbacks associated with file
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @dev: device information struct
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @file: file information struct
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_clear_lists is called to clear resources associated with file
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * when application calls close function or Ctrl-C was pressed
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return 1 if callback removed from the list, 0 otherwise
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_clear_lists(struct iamt_heci_device *dev, struct heci_file *file)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* remove callbacks associated with a file */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) heci_clear_list(dev, file, &dev->pthi_cmd_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_clear_list(dev, file,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->pthi_read_complete_list.heci_cb.cb_list))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) heci_clear_list(dev, file, &dev->ctrl_rd_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_clear_list(dev, file, &dev->ctrl_wr_list.heci_cb.cb_list))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_clear_list(dev, file,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_waiting_list.heci_cb.cb_list))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_clear_list(dev, file, &dev->write_list.heci_cb.cb_list))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check if iamthif_current_cb not NULL */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_current_cb && (!rets)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* check file and iamthif current cb association */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_current_cb->file_object == file) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* remove cb */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(dev->iamthif_current_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_current_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_open - the open function
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int minor, if_num, instance;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(flags, credp))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor(*devp);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_open: enter...\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Make sure the open is for the right file type.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (otyp != OTYP_CHR)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (EINVAL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if_num = HECI_MINOR_TO_IFNUM(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((if_num < HECI_MINOR_NUMBER) || (!dev))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = heci_alloc_file_private(NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == NULL)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENOMEM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(file_ext, sizeof (struct heci_file_private));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->open_handle_count >= HECI_MAX_OPEN_HANDLE_COUNT) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(file_ext, sizeof (struct heci_file_private));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENFILE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->open_handle_count++;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&file_ext->link, &dev->file_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while ((dev->heci_host_clients[dev->current_host_client_id / 8]
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan & (1 << (dev->current_host_client_id % 8))) != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->current_host_client_id++;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->current_host_client_id %= HECI_MAX_OPEN_HANDLE_COUNT;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("current_host_client_id = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->current_host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("dev->open_handle_count = %lu\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->open_handle_count);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("current_host_client_id = %d\n", dev->current_host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id = dev->current_host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *devp = makedevice(getmajor(*devp),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan MAKE_MINOR_NUM(dev->current_host_client_id, instance));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file = &dev->files[dev->current_host_client_id];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_host_clients[file_ext->host_client_id / 8] |=
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (1 << (file_ext->host_client_id % 8));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state = HECI_FILE_INITIALIZING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->sm_state = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file->private_data = file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_close - the close function
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_close(dev_t devt, int flag, int otyp, struct cred *cred)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int minor, if_num, instance;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(flag, otyp, cred))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor(devt);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if_num = HECI_MINOR_TO_IFNUM(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file = &dev->files[if_num];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = file->private_data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((if_num < HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext != &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->state == HECI_FILE_CONNECTED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->state = HECI_FILE_DISCONNECTING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("disconnecting client host client = %d, "
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "ME client = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_disconnect_host_client(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_flush_queues(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("remove client host client = %d, ME client = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->open_handle_count > 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->heci_host_clients[file_ext->host_client_id / 8] &=
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ~(1 << (file_ext->host_client_id % 8));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->open_handle_count--;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_remove_client_from_file_list(dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* free read cb */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->read_cb != NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = find_read_list_entry(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Remove entry from read list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_cb != NULL)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = file_ext->read_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file->private_data = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_cb != NULL)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_file_private(file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->open_handle_count > 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->open_handle_count--;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_file_object == file &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state != HECI_IAMTHIF_IDLE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("pthi canceled iamthif state %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_canceled = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("run next pthi iamthif cb\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan run_next_iamthif_cmd(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_clear_lists(dev, file))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state = HECI_IAMTHIF_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic struct heci_cb_private *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganfind_read_list_entry(struct iamt_heci_device *dev,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_next = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext_list_temp;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->read_list.status == 0 &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan !list_empty(&dev->read_list.heci_cb.cb_list)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("remove read_list CB \n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_for_each_entry_safe(priv_cb_pos,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_next,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->read_list.heci_cb.cb_list, cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext_list_temp = (struct heci_file_private *)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos->file_private;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((file_ext_list_temp != NULL) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_fe_same_id(file_ext, file_ext_list_temp))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (priv_cb_pos);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_read - the read client message function.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_read(dev_t devt, struct uio *uio_p, cred_t *cred_p)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan size_t length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb_pos = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int instance, minor, if_num, err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(cred_p))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor(devt);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if_num = HECI_MINOR_TO_IFNUM(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file = &dev->files[if_num];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = file->private_data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((if_num < HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!file_ext)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((file_ext->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Do not allow to read watchdog client */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (memcmp(&heci_wd_guid,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->me_clients[i].props.protocol_name,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct guid)) == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->me_client_id ==
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_clients[i].client_id)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-EBADF);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = pthi_read(dev, if_num, file, uio_p);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto out;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->read_cb &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_cb->information > UIO_OFFSET(uio_p)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = file_ext->read_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto copy_buffer;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (file_ext->read_cb && file_ext->read_cb->information > 0 &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_cb->information <= UIO_OFFSET(uio_p)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = file_ext->read_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto free;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (!file_ext->read_cb || file_ext->read_cb->information == 0) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan UIO_OFFSET(uio_p) > 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Offset needs to be cleaned for contingous reads */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan UIO_OFFSET(uio_p) = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto out;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = heci_start_read(dev, if_num, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err != 0 && err != -EBUSY) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci start read failure with status = %d\n", err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto out;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (HECI_READ_COMPLETE != file_ext->reading_state &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_INITIALIZING != file_ext->state &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_DISCONNECTED != file_ext->state &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_DISCONNECTING != file_ext->state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (cv_wait_sig(&file_ext->rx_wait, &dev->device_lock) == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = file_ext->read_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EINTR;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto free;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_FILE_INITIALIZING == file_ext->state ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_DISCONNECTED == file_ext->state ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_FILE_DISCONNECTING == file_ext->state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EBUSY;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto out;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb = file_ext->read_cb;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!priv_cb) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->reading_state != HECI_READ_COMPLETE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* now copy the data to user space */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logancopy_buffer:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb->response_buffer size - %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb->response_buffer.size);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("priv_cb->information - %lu\n", priv_cb->information);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (uio_p->uio_resid == 0 || uio_p->uio_resid < priv_cb->information) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EMSGSIZE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto free;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan length = (uio_p->uio_resid <
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (priv_cb->information - uio_p->uio_offset) ?
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uio_p->uio_resid : (priv_cb->information - uio_p->uio_offset));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (uiomove(priv_cb->response_buffer.data,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan length, UIO_READ, uio_p)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EFAULT;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto free;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganfree:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_cb_pos = find_read_list_entry(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Remove entry from read list */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_cb_pos != NULL)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_cb_pos->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->reading_state = HECI_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganout: DBG("end heci read rets= %d\n", rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_write - the write function.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_write(dev_t devt, struct uio *uio_p, struct cred *cred)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint8_t i;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan size_t length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_cb_private *priv_write_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_msg_hdr heci_hdr;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan unsigned long currtime = ddi_get_time();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int instance, minor, if_num, err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(cred))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_write enter...\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor(devt);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if_num = HECI_MINOR_TO_IFNUM(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file = &dev->files[if_num];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = file->private_data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((if_num < HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb = find_pthi_read_list_entry(dev, file);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((priv_write_cb != NULL) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (((currtime - priv_write_cb->read_time) >
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan IAMTHIF_READ_TIMER) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (file_ext->reading_state == HECI_READ_COMPLETE))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan UIO_OFFSET(uio_p) = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_write_cb->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_write_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* free entry used in read */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->reading_state == HECI_READ_COMPLETE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan UIO_OFFSET(uio_p) = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb = find_read_list_entry(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (priv_write_cb != NULL) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_del(&priv_write_cb->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_write_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->reading_state = HECI_IDLE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_cb = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->read_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if (file_ext->reading_state == HECI_IDLE &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->read_pending == 0)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan UIO_OFFSET(uio_p) = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb = kmem_zalloc(sizeof (struct heci_cb_private), KM_SLEEP);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!priv_write_cb)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENOMEM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->file_object = file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->file_private = file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->request_buffer.data =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_zalloc(uio_p->uio_resid, KM_SLEEP);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!priv_write_cb->request_buffer.data) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_free(priv_write_cb, sizeof (struct heci_cb_private));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENOMEM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan length = (int)uio_p->uio_resid;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("length =%d\n", (int)length);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = uiomove(priv_write_cb->request_buffer.data,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan length, UIO_WRITE, uio_p);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (err) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = err;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#define UBUFF UIO_BUFF(uio_p)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->sm_state = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((length == 4) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ((memcmp(heci_wd_state_independence_msg[0], UBUFF, 4) == 0) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (memcmp(heci_wd_state_independence_msg[1], UBUFF, 4) == 0) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (memcmp(heci_wd_state_independence_msg[2], UBUFF, 4) == 0)))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan LIST_INIT_HEAD(&priv_write_cb->cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext == &dev->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->response_buffer.data =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kmem_zalloc(IAMTHIF_MTU, KM_SLEEP);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!priv_write_cb->response_buffer.data) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENOMEM;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->me_clients[i].client_id ==
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.me_client_id)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(dev->me_clients[i].client_id == file_ext->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((i == dev->num_heci_me_clients) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (dev->me_clients[i].client_id !=
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_file_ext.me_client_id)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else if ((length >
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->me_clients[i].props.max_msg_length) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (length == 0)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EMSGSIZE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->response_buffer.size = IAMTHIF_MTU;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->major_file_operations = HECI_IOCTL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->request_buffer.size = (uint32_t)length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!list_empty(&dev->pthi_cmd_list.heci_cb.cb_list) ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->iamthif_state != HECI_IAMTHIF_IDLE) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("pthi_state = %d\n", (int)dev->iamthif_state);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("add PTHI cb to pthi cmd waiting list\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_write_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->pthi_cmd_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 0; /* length; */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call pthi write\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = pthi_write(dev, priv_write_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (rets != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("pthi write failed with status = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto fail;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = 0; /* length; */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->major_file_operations = HECI_WRITE;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* make sure information is zero before we start */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->request_buffer.size = (uint32_t)length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_ext->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host client = %d, ME client = %d\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id, file_ext->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_ext->state != HECI_FILE_CONNECTED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("host client = %d, is not connected to ME client = %d",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->host_client_id,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto unlock;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for (i = 0; i < dev->num_heci_me_clients; i++) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->me_clients[i].client_id ==
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->me_client_id)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(dev->me_clients[i].client_id == file_ext->me_client_id);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (i == dev->num_heci_me_clients) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto unlock;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (length > dev->me_clients[i].props.max_msg_length || length == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EINVAL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan goto unlock;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->file_private = file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (flow_ctrl_creds(dev, file_ext) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->host_buffer_is_empty = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (uint32_t)) - sizeof (struct heci_msg_hdr))) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.length =
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (((dev->host_hw_state & H_CBD) >> 24) *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (uint32_t)) -
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sizeof (struct heci_msg_hdr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.msg_complete = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.length = (uint32_t)length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.msg_complete = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.host_addr = file_ext->host_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.me_addr = file_ext->me_client_id;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.reserved = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("call heci_write_message header=%08x.\n",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *((uint32_t *)(void *)&heci_hdr));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* protect heci low level write */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_write_message(dev, &heci_hdr,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (unsigned char *)(priv_write_cb->request_buffer.data),
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_hdr.length)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_write_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -ENODEV;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->writing_state = HECI_WRITING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->information = heci_hdr.length;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (heci_hdr.msg_complete) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(dev, file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_write_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_waiting_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_write_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan priv_write_cb->information = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext->writing_state = HECI_WRITING;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan list_add_tail(&priv_write_cb->cb_list,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &dev->write_list.heci_cb.cb_list);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganunlock:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_ext->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganfail:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_free_cb_private(priv_write_cb);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_ioctl - the IOCTL function
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_ioctl(dev_t devt, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int rets = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_ext;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* in user space */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_message_data *u_msg = (struct heci_message_data *)arg;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_message_data k_msg; /* all in kernel on the stack */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int instance, minor, if_num;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(cr, rval))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor(devt);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if_num = HECI_MINOR_TO_IFNUM(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file = &dev->files[if_num];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext = file->private_data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((if_num < HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&dev->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* first copy from user all data needed */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ddi_copyin(u_msg, &k_msg, sizeof (k_msg), mode)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("first copy from user all data needed filled\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-EFAULT);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#ifdef _LP64
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan uint32_t addr32 = (uint32_t)(uint64_t)k_msg.data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan k_msg.data = (char *)(uint64_t)addr32;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("IPL32: k_msg.data=%p\n", (void *)k_msg.data);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#endif
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("user message size is %d, cmd = 0x%x\n", k_msg.size, cmd);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (cmd) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case IOCTL_HECI_GET_VERSION:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG(": IOCTL_HECI_GET_VERSION\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_ioctl_get_version(dev, if_num, u_msg, k_msg,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_ext, mode);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case IOCTL_HECI_CONNECT_CLIENT:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG(": IOCTL_HECI_CONNECT_CLIENT.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_ioctl_connect_client(dev, if_num, u_msg, k_msg,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file, mode);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case IOCTL_HECI_WD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG(": IOCTL_HECI_WD.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_ioctl_wd(dev, if_num, k_msg, file_ext, mode);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case IOCTL_HECI_BYPASS_WD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG(": IOCTL_HECI_BYPASS_WD.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = heci_ioctl_bypass_wd(dev, if_num, k_msg, file_ext, mode);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan default:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan rets = -EINVAL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (rets);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_poll - the poll function
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_poll(dev_t devt, short events, int anyyet,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan short *reventsp, struct pollhead **phpp)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file *file;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *file_extension;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device = NULL;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int instance, minor, if_num;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan _NOTE(ARGUNUSED(events))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan minor = getminor(devt);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan instance = HECI_MINOR_TO_INSTANCE(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if_num = HECI_MINOR_TO_IFNUM(minor);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device = ddi_get_soft_state(heci_soft_state_p, instance);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file = &device->files[if_num];
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan file_extension = file->private_data;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((if_num < HECI_MINOR_NUMBER) || (!device) || (!file_extension))
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENODEV);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->heci_state != HECI_ENABLED) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (-ENXIO);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (file_extension == &device->iamthif_file_ext) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&device->iamthif_file_ext.file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->iamthif_state == HECI_IAMTHIF_READ_COMPLETE &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->iamthif_file_object == file) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *reventsp |= (POLLIN | POLLRDNORM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_poll: run next pthi cb\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan run_next_iamthif_cmd(device);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_poll: iamthif no event\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *reventsp = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!anyyet)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *phpp = &device->iamthif_file_ext.pollwait;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->iamthif_file_ext.file_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&file_extension->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (HECI_WRITE_COMPLETE == file_extension->writing_state) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *reventsp |= (POLLIN | POLLRDNORM);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_poll: file_extension poll event\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("heci_poll: file_extension no event\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *reventsp = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!anyyet)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *phpp = &file_extension->tx_pollwait;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&file_extension->write_io_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * heci_fe_same_id - tell if file private data have same id
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @fe1: private data of 1. file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @fe2: private data of 2. file object
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * @return !=0 - if ids are the same, 0 - if differ.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic inline int heci_fe_same_id(struct heci_file_private *fe1,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct heci_file_private *fe2)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return ((fe1->host_client_id == fe2->host_client_id) &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (fe1->me_client_id == fe2->me_client_id));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Since the ME firmware won't reset itself during OS reboot, it's not enough
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * to only disable interrupts in quiesce(), here we do a full hand-shake
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * with the firmware.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_quiesce(dev_info_t *dip)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *dev;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev = ddi_get_soft_state(heci_soft_state_p, ddi_get_instance(dip));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ASSERT(dev != NULL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (dev->wd_file_ext.state == HECI_FILE_CONNECTED &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timeout) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_timeout = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan dev->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(dev->wd_data, stop_wd_params,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE);
7aaf98066df428a8994a75623f04675d31685df7Vincent Wang if (!heci_send_wd(dev)) {
7aaf98066df428a8994a75623f04675d31685df7Vincent Wang DBG("send stop WD failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* disable interrupts */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_csr_disable_interrupts(dev);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (DDI_SUCCESS);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic int
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_suspend(dev_info_t *dip)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan int err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device = ddi_get_soft_state(heci_soft_state_p, ddi_get_instance(dip));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->reinit_tsk)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan ddi_taskq_wait(device->reinit_tsk);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Stop watchdog if exists */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->wd_timer)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) untimeout(device->wd_timer);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->wd_file_ext.state == HECI_FILE_CONNECTED &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_timeout) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan g_sus_wd_timeout = device->wd_timeout;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_timeout = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_due_counter = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(device->wd_data, stop_wd_params,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->stop = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->host_buffer_is_empty &&
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_creds(device, &device->wd_file_ext)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->host_buffer_is_empty = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!heci_send_wd(device)) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("send stop WD failed\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan else
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan flow_ctrl_reduce(device, &device->wd_file_ext);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_pending = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_pending = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_stoped = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan while (!device->wd_stoped && err != -1) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni err = cv_reltimedwait(&device->wait_stop_wd,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni &device->device_lock, 10*HZ, TR_CLOCK_TICK);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (!device->wd_stoped) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("stop wd failed to complete.\n");
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan } else {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan DBG("stop wd complete %d.\n", err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan err = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Set new heci state */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->heci_state == HECI_ENABLED ||
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->heci_state == HECI_RECOVERING_FROM_RESET) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->heci_state = HECI_POWER_DOWN;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset(device, 0);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Here interrupts are already disabled by heci_reset() */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan return (err);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic void
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganheci_resume(dev_info_t *dip)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct iamt_heci_device *device;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device = ddi_get_soft_state(heci_soft_state_p, ddi_get_instance(dip));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_enter(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->heci_state = HECI_POWER_UP;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan heci_reset(device, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan mutex_exit(&device->device_lock);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Start watchdog if stopped in suspend */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (g_sus_wd_timeout != 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_timeout = g_sus_wd_timeout;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(device->wd_data, start_wd_params,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan HECI_WD_PARAMS_SIZE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan (void) memcpy(device->wd_data + HECI_WD_PARAMS_SIZE,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan &device->wd_timeout, sizeof (uint16_t));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_due_counter = 1;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (device->wd_timeout)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan device->wd_timer = timeout(heci_wd_timer, device, 1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan g_sus_wd_timeout = 0;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}