3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore/*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * CDDL HEADER START
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * The contents of this file are subject to the terms of the
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Common Development and Distribution License (the "License").
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * You may not use this file except in compliance with the License.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * or http://www.opensolaris.org/os/licensing.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * See the License for the specific language governing permissions
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * and limitations under the License.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * CDDL HEADER END
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore/*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
679ac1565a070e343ccb5d6dcff1231cc6011ce4Alexey Zaytsev * Copyright 2012 Alexey Zaytsev <alexey.zaytsev@gmail.com> All rights reserved.
1a3a6dee3c970f347783cae39e1f3536e3116a96Hans Rosenfeld * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore */
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/types.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/ksynch.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/kmem.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/file.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/errno.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/open.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/buf.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/uio.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/aio_req.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/cred.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/modctl.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/cmlb.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/conf.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/devops.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/list.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/sysmacros.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/dkio.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/vtoc.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/scsi/scsi.h> /* for DTYPE_DIRECT */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/kstat.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/fs/dv_node.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/ddi.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/sunddi.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/note.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#include <sys/blkdev.h>
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld#include <sys/scsi/impl/inquiry.h>
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define BD_MAXPART 64
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define BDINST(dev) (getminor(dev) / BD_MAXPART)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define BDPART(dev) (getminor(dev) % BD_MAXPART)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoretypedef struct bd bd_t;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoretypedef struct bd_xfer_impl bd_xfer_impl_t;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestruct bd {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore void *d_private;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dev_info_t *d_dip;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmutex_t d_ocmutex;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmutex_t d_iomutex;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kmutex_t *d_errmutex;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmutex_t d_statemutex;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kcondvar_t d_statecv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore enum dkio_state d_state;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmlb_handle_t d_cmlbh;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore unsigned d_open_lyr[BD_MAXPART]; /* open count */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint64_t d_open_excl; /* bit mask indexed by partition */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint64_t d_open_reg[OTYPCNT]; /* bit mask */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t d_qsize;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t d_qactive;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t d_maxxfer;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t d_blkshift;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld uint32_t d_pblkshift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint64_t d_numblks;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_devid_t d_devid;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_cache_t *d_cache;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_t d_runq;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_t d_waitq;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_t *d_ksp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_io_t *d_kiop;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_t *d_errstats;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld struct bd_errstats *d_kerr;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t d_rdonly;
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore boolean_t d_ssd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t d_removable;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t d_hotpluggable;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t d_use_dma;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_attr_t d_dma;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_ops_t d_ops;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_handle_t d_handle;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestruct bd_handle {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_ops_t h_ops;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_attr_t *h_dma;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dev_info_t *h_parent;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dev_info_t *h_child;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore void *h_private;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *h_bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore char *h_name;
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld char h_addr[30]; /* enough for w%0.16x,%X */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestruct bd_xfer_impl {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_t i_public;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_node_t i_linkage;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *i_bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore buf_t *i_bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint_t i_num_win;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint_t i_cur_win;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore off_t i_offset;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int (*i_func)(void *, bd_xfer_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t i_blkshift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore size_t i_len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore size_t i_resid;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define i_dmah i_public.x_dmah
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define i_dmac i_public.x_dmac
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define i_ndmac i_public.x_ndmac
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define i_kaddr i_public.x_kaddr
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define i_nblks i_public.x_nblks
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore#define i_blkno i_public.x_blkno
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore#define i_flags i_public.x_flags
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore/*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Private prototypes.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeldstatic void bd_prop_update_inqstring(dev_info_t *, char *, char *, size_t);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeldstatic void bd_create_inquiry_props(dev_info_t *, bd_drive_t *);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldstatic void bd_create_errstats(bd_t *, int, bd_drive_t *);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldstatic void bd_errstats_setstr(kstat_named_t *, char *, size_t, char *);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldstatic void bd_init_errstats(bd_t *, bd_drive_t *);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_attach(dev_info_t *, ddi_attach_cmd_t);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_detach(dev_info_t *, ddi_detach_cmd_t);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_open(dev_t *, int, int, cred_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_close(dev_t, int, int, cred_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_strategy(struct buf *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amorestatic int bd_dump(dev_t, caddr_t, daddr_t, int);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_read(dev_t, struct uio *, cred_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_write(dev_t, struct uio *, cred_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_aread(dev_t, struct aio_req *, cred_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_awrite(dev_t, struct aio_req *, cred_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore caddr_t, int *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_tg_rdwr(dev_info_t *, uchar_t, void *, diskaddr_t, size_t,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore void *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_tg_getinfo(dev_info_t *, int, void *, void *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_xfer_ctor(void *, void *, int);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void bd_xfer_dtor(void *, void *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void bd_sched(bd_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void bd_submit(bd_t *, bd_xfer_impl_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void bd_runq_exit(bd_xfer_impl_t *, int);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void bd_update_state(bd_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_check_state(bd_t *, enum dkio_state *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int bd_flush_write_cache(bd_t *, struct dk_callback *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestruct cmlb_tg_ops bd_tg_ops = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore TG_DK_OPS_VERSION_1,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_tg_rdwr,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_tg_getinfo,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic struct cb_ops bd_cb_ops = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_open, /* open */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_close, /* close */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_strategy, /* strategy */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nodev, /* print */
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd_dump, /* dump */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_read, /* read */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_write, /* write */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_ioctl, /* ioctl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nodev, /* devmap */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nodev, /* mmap */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nodev, /* segmap */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nochpoll, /* poll */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_prop_op, /* cb_prop_op */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore 0, /* streamtab */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore D_64BIT | D_MP, /* Driver comaptibility flag */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore CB_REV, /* cb_rev */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_aread, /* async read */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_awrite /* async write */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestruct dev_ops bd_dev_ops = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore DEVO_REV, /* devo_rev, */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore 0, /* refcnt */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_getinfo, /* getinfo */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nulldev, /* identify */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nulldev, /* probe */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_attach, /* attach */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_detach, /* detach */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nodev, /* reset */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &bd_cb_ops, /* driver operations */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus operations */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* power */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_quiesce_not_needed, /* quiesce */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic struct modldrv modldrv = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &mod_driverops,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "Generic Block Device",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &bd_dev_ops,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic struct modlinkage modlinkage = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore MODREV_1, { &modldrv, NULL }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore};
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void *bd_state;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic krwlock_t bd_lock;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoreint
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore_init(void)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ddi_soft_state_init(&bd_state, sizeof (struct bd), 2);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_init(&bd_lock, NULL, RW_DRIVER, NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = mod_install(&modlinkage);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_destroy(&bd_lock);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_soft_state_fini(&bd_state);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoreint
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore_fini(void)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = mod_remove(&modlinkage);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv == DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_destroy(&bd_lock);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_soft_state_fini(&bd_state);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoreint
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore_info(struct modinfo *modinfop)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (mod_info(&modlinkage, modinfop));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore inst = BDINST((dev_t)arg);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (cmd) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_INFO_DEVT2DEVINFO:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd = ddi_get_soft_state(bd_state, inst);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *resultp = (void *)bd->d_dip;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_INFO_DEVT2INSTANCE:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *resultp = (void *)(intptr_t)inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeldstatic void
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeldbd_prop_update_inqstring(dev_info_t *dip, char *name, char *data, size_t len)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld{
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld int ilen;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld char *data_string;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld ilen = scsi_ascii_inquiry_len(data, len);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld ASSERT3U(ilen, <=, len);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld if (ilen <= 0)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld return;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld /* ensure null termination */
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld data_string = kmem_zalloc(ilen + 1, KM_SLEEP);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bcopy(data, data_string, ilen);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, name, data_string);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld kmem_free(data_string, ilen + 1);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld}
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeldstatic void
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeldbd_create_inquiry_props(dev_info_t *dip, bd_drive_t *drive)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld{
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld if (drive->d_vendor_len > 0)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bd_prop_update_inqstring(dip, INQUIRY_VENDOR_ID,
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_vendor, drive->d_vendor_len);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld if (drive->d_product_len > 0)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bd_prop_update_inqstring(dip, INQUIRY_PRODUCT_ID,
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_product, drive->d_product_len);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld if (drive->d_serial_len > 0)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bd_prop_update_inqstring(dip, INQUIRY_SERIAL_NO,
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_serial, drive->d_serial_len);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld if (drive->d_revision_len > 0)
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bd_prop_update_inqstring(dip, INQUIRY_REVISION_ID,
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld drive->d_revision, drive->d_revision_len);
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld}
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldstatic void
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldbd_create_errstats(bd_t *bd, int inst, bd_drive_t *drive)
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld{
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld char ks_module[KSTAT_STRLEN];
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld char ks_name[KSTAT_STRLEN];
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld int ndata = sizeof (struct bd_errstats) / sizeof (kstat_named_t);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (bd->d_errstats != NULL)
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld return;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld (void) snprintf(ks_module, sizeof (ks_module), "%serr",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld ddi_driver_name(bd->d_dip));
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld (void) snprintf(ks_name, sizeof (ks_name), "%s%d,err",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld ddi_driver_name(bd->d_dip), inst);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_errstats = kstat_create(ks_module, inst, ks_name, "device_error",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_TYPE_NAMED, ndata, KSTAT_FLAG_PERSISTENT);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (bd->d_errstats == NULL) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld /*
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld * Even if we cannot create the kstat, we create a
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld * scratch kstat. The reason for this is to ensure
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld * that we can update the kstat all of the time,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld * without adding an extra branch instruction.
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld */
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_kerr = kmem_zalloc(sizeof (struct bd_errstats),
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KM_SLEEP);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_errmutex = kmem_zalloc(sizeof (kmutex_t), KM_SLEEP);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld mutex_init(bd->d_errmutex, NULL, MUTEX_DRIVER, NULL);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld } else {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (bd->d_errstats->ks_lock == NULL) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_errstats->ks_lock = kmem_zalloc(sizeof (kmutex_t),
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KM_SLEEP);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld mutex_init(bd->d_errstats->ks_lock, NULL, MUTEX_DRIVER,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld NULL);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_errmutex = bd->d_errstats->ks_lock;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_kerr = (struct bd_errstats *)bd->d_errstats->ks_data;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_softerrs, "Soft Errors",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_harderrs, "Hard Errors",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_transerrs, "Transport Errors",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (drive->d_model_len > 0) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_model, "Model",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_STRING);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld } else {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_vid, "Vendor",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_STRING);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_pid, "Product",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_STRING);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_revision, "Revision",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_STRING);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_serial, "Serial No",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_STRING);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_capacity, "Size",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_ULONGLONG);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_rq_media_err, "Media Error",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_rq_ntrdy_err, "Device Not Ready",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_rq_nodev_err, "No Device",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_rq_recov_err, "Recoverable",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_rq_illrq_err, "Illegal Request",
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_init(&bd->d_kerr->bd_rq_pfa_err,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld "Predictive Failure Analysis", KSTAT_DATA_UINT32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_errstats->ks_private = bd;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_install(bd->d_errstats);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld}
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldstatic void
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldbd_errstats_setstr(kstat_named_t *k, char *str, size_t len, char *alt)
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld{
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld char *tmp;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (KSTAT_NAMED_STR_PTR(k) == NULL) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (len > 0) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld tmp = kmem_alloc(len + 1, KM_SLEEP);
1a3a6dee3c970f347783cae39e1f3536e3116a96Hans Rosenfeld (void) strlcpy(tmp, str, len + 1);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld } else {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld tmp = alt;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_named_setstr(k, tmp);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld}
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldstatic void
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldbd_init_errstats(bd_t *bd, bd_drive_t *drive)
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld{
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld struct bd_errstats *est = bd->d_kerr;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld mutex_enter(bd->d_errmutex);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (drive->d_model_len > 0 &&
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld KSTAT_NAMED_STR_PTR(&est->bd_model) == NULL) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_errstats_setstr(&est->bd_model, drive->d_model,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld drive->d_model_len, NULL);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld } else {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_errstats_setstr(&est->bd_vid, drive->d_vendor,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld drive->d_vendor_len, "Unknown ");
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_errstats_setstr(&est->bd_pid, drive->d_product,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld drive->d_product_len, "Unknown ");
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_errstats_setstr(&est->bd_revision, drive->d_revision,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld drive->d_revision_len, "0001");
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_errstats_setstr(&est->bd_serial, drive->d_serial,
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld drive->d_serial_len, "0 ");
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld mutex_exit(bd->d_errmutex);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld}
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_handle_t hdl;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_drive_t drive;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore char name[16];
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore char kcache[32];
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (cmd) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_ATTACH:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_RESUME:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* We don't do anything native for suspend/resume */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore inst = ddi_get_instance(dip);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl = ddi_get_parent_data(dip);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) snprintf(name, sizeof (name), "%s%d",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_driver_name(dip), ddi_get_instance(dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) snprintf(kcache, sizeof (kcache), "%s_xfer", name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (hdl == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN, "%s: missing parent data!", name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_soft_state_zalloc(bd_state, inst) != DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN, "%s: unable to zalloc soft state!", name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd = ddi_get_soft_state(bd_state, inst);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (hdl->h_dma) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_dma = *(hdl->h_dma);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_dma.dma_attr_granular =
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore max(DEV_BSIZE, bd->d_dma.dma_attr_granular);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_use_dma = B_TRUE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_maxxfer &&
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (bd->d_maxxfer != bd->d_dma.dma_attr_maxxfer)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "%s: inconsistent maximum transfer size!",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* We force it */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_use_dma = B_FALSE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_maxxfer == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_maxxfer = 1024 * 1024;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_ops = hdl->h_ops;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_private = hdl->h_private;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_blkshift = 9; /* 512 bytes, to start */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_maxxfer % DEV_BSIZE) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN, "%s: maximum transfer misaligned!", name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_maxxfer &= ~(DEV_BSIZE - 1);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_maxxfer < DEV_BSIZE) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN, "%s: maximum transfer size too small!", name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_soft_state_free(bd_state, inst);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_dip = dip;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_handle = hdl;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_bd = bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_set_driver_private(dip, bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_init(&bd->d_iomutex, NULL, MUTEX_DRIVER, NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_init(&bd->d_ocmutex, NULL, MUTEX_DRIVER, NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_init(&bd->d_statemutex, NULL, MUTEX_DRIVER, NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cv_init(&bd->d_statecv, NULL, CV_DRIVER, NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_create(&bd->d_waitq, sizeof (bd_xfer_impl_t),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore offsetof(struct bd_xfer_impl, i_linkage));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_create(&bd->d_runq, sizeof (bd_xfer_impl_t),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore offsetof(struct bd_xfer_impl, i_linkage));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_cache = kmem_cache_create(kcache, sizeof (bd_xfer_impl_t), 8,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_ctor, bd_xfer_dtor, NULL, bd, NULL, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_ksp = kstat_create(ddi_driver_name(dip), inst, NULL, "disk",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_ksp != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_ksp->ks_lock = &bd->d_iomutex;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_install(bd->d_ksp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_kiop = bd->d_ksp->ks_data;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Even if we cannot create the kstat, we create a
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * scratch kstat. The reason for this is to ensure
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * that we can update the kstat all of the time,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * without adding an extra branch instruction.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_kiop = kmem_zalloc(sizeof (kstat_io_t), KM_SLEEP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmlb_alloc_handle(&bd->d_cmlbh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_state = DKIO_NONE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bzero(&drive, sizeof (drive));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_ops.o_drive_info(bd->d_private, &drive);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_qsize = drive.d_qsize;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_removable = drive.d_removable;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_hotpluggable = drive.d_hotpluggable;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
bc220884124d127a3046646c2c9fb8d86fe654a9Alexey Zaytsev if (drive.d_maxxfer && drive.d_maxxfer < bd->d_maxxfer)
bc220884124d127a3046646c2c9fb8d86fe654a9Alexey Zaytsev bd->d_maxxfer = drive.d_maxxfer;
bc220884124d127a3046646c2c9fb8d86fe654a9Alexey Zaytsev
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bd_create_inquiry_props(dip, &drive);
bc220884124d127a3046646c2c9fb8d86fe654a9Alexey Zaytsev
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_create_errstats(bd, inst, &drive);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_init_errstats(bd, &drive);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_update_state(bd);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = cmlb_attach(dip, &bd_tg_ops, DTYPE_DIRECT,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_removable, bd->d_hotpluggable,
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld /*LINTED: E_BAD_PTR_CAST_ALIGN*/
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld *(uint64_t *)drive.d_eui64 != 0 ? DDI_NT_BLOCK_BLKDEV :
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore drive.d_lun >= 0 ? DDI_NT_BLOCK_CHAN : DDI_NT_BLOCK,
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore CMLB_FAKE_LABEL_ONE_PARTITION, bd->d_cmlbh, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmlb_free_handle(&bd->d_cmlbh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_cache_destroy(bd->d_cache);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_destroy(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_destroy(&bd->d_ocmutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_destroy(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cv_destroy(&bd->d_statecv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_destroy(&bd->d_waitq);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_destroy(&bd->d_runq);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_ksp != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_delete(bd->d_ksp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_ksp = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_free(bd->d_kiop, sizeof (kstat_io_t));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_soft_state_free(bd_state, inst);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_ops.o_devid_init != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = bd->d_ops.o_devid_init(bd->d_private, dip, &bd->d_devid);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv == DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_devid_register(dip, bd->d_devid) !=
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "%s: unable to register devid", name);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Add a zero-length attribute to tell the world we support
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * kernel ioctls (for layered drivers). Also set up properties
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * used by HAL to identify removable media.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore DDI_KERNEL_IOCTL, NULL, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_removable) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "removable-media", NULL, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_hotpluggable) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "hotpluggable", NULL, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_report_dev(dip);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd = ddi_get_driver_private(dip);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (cmd) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DETACH:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_SUSPEND:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* We don't suspend, but our parent does */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_ksp != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_delete(bd->d_ksp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_ksp = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_free(bd->d_kiop, sizeof (kstat_io_t));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld if (bd->d_errstats != NULL) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kstat_delete(bd->d_errstats);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_errstats = NULL;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld } else {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld kmem_free(bd->d_kerr, sizeof (struct bd_errstats));
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld mutex_destroy(bd->d_errmutex);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore cmlb_detach(bd->d_cmlbh, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmlb_free_handle(&bd->d_cmlbh);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_devid)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_devid_free(bd->d_devid);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_cache_destroy(bd->d_cache);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_destroy(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_destroy(&bd->d_ocmutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_destroy(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cv_destroy(&bd->d_statecv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_destroy(&bd->d_waitq);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_destroy(&bd->d_runq);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_soft_state_free(bd_state, ddi_get_instance(dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_xfer_ctor(void *buf, void *arg, int kmflag)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd = arg;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int (*dcb)(caddr_t);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
679ac1565a070e343ccb5d6dcff1231cc6011ce4Alexey Zaytsev if (kmflag == KM_PUSHPAGE || kmflag == KM_SLEEP) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dcb = DDI_DMA_SLEEP;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dcb = DDI_DMA_DONTWAIT;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi = buf;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bzero(xi, sizeof (*xi));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_bd = bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_use_dma) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_dma_alloc_handle(bd->d_dip, &bd->d_dma, dcb, NULL,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &xi->i_dmah) != DDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (-1);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_xfer_dtor(void *buf, void *arg)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi = buf;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(arg));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi->i_dmah)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_free_handle(&xi->i_dmah);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_dmah = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic bd_xfer_impl_t *
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_xfer_alloc(bd_t *bd, struct buf *bp, int (*func)(void *, bd_xfer_t *),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int kmflag)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi;
a0cb694bef8ce5b375d89d042945f0e24bbd4026Steve Ma int rv = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int status;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore unsigned dir;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int (*cb)(caddr_t);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore size_t len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (kmflag == KM_SLEEP) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cb = DDI_DMA_SLEEP;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cb = DDI_DMA_DONTWAIT;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi = kmem_cache_alloc(bd->d_cache, kmflag);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, ENOMEM);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ASSERT(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_bp = bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_func = func;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_blkno = bp->b_lblkno;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bp->b_bcount == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_len = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_nblks = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_kaddr = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_resid = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_num_win = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bp->b_flags & B_READ) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dir = DDI_DMA_READ;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_func = bd->d_ops.o_read;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dir = DDI_DMA_WRITE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_func = bd->d_ops.o_write;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore shift = bd->d_blkshift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_blkshift = shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (!bd->d_use_dma) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp_mapin(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_offset = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_num_win =
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (bp->b_bcount + (bd->d_maxxfer - 1)) / bd->d_maxxfer;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_cur_win = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_len = min(bp->b_bcount, bd->d_maxxfer);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_nblks = xi->i_len >> shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_kaddr = bp->b_un.b_addr;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_resid = bp->b_bcount;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * We have to use consistent DMA if the address is misaligned.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (((bp->b_flags & (B_PAGEIO | B_REMAPPED)) != B_PAGEIO) &&
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dir |= DDI_DMA_CONSISTENT | DDI_DMA_PARTIAL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dir |= DDI_DMA_STREAMING | DDI_DMA_PARTIAL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore status = ddi_dma_buf_bind_handle(xi->i_dmah, bp, dir, cb,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, &xi->i_dmac, &xi->i_ndmac);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (status) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DMA_MAPPED:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_num_win = 1;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_cur_win = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_offset = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_len = bp->b_bcount;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_nblks = xi->i_len >> shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_resid = bp->b_bcount;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DMA_PARTIAL_MAP:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_cur_win = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((ddi_dma_numwin(xi->i_dmah, &xi->i_num_win) !=
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore DDI_SUCCESS) ||
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (ddi_dma_getwin(xi->i_dmah, 0, &xi->i_offset,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &len, &xi->i_dmac, &xi->i_ndmac) !=
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore DDI_SUCCESS) ||
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (P2PHASE(len, shift) != 0)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ddi_dma_unbind_handle(xi->i_dmah);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EFAULT;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_len = len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_nblks = xi->i_len >> shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_resid = bp->b_bcount;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DMA_NORESOURCES:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EAGAIN;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DMA_TOOBIG:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EINVAL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DMA_NOMAPPING:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_DMA_INUSE:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EFAULT;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoredone:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_cache_free(bd->d_cache, xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_xfer_free(bd_xfer_impl_t *xi)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi->i_dmah) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ddi_dma_unbind_handle(xi->i_dmah);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_cache_free(xi->i_bd->d_cache, xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dev_t dev = *devp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t part;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint64_t mask;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t ndelay;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore diskaddr_t nblks;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore diskaddr_t lba;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(credp));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore part = BDPART(dev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore inst = BDINST(dev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (otyp >= OTYPCNT)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EINVAL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ndelay = (flag & (FNDELAY | FNONBLOCK)) ? B_TRUE : B_FALSE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Block any DR events from changing the set of registered
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * devices while we function.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_enter(&bd_lock, RW_READER);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_exit(&bd_lock);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENXIO);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_enter(&bd->d_ocmutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ASSERT(part < 64);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mask = (1U << part);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_update_state(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if (cmlb_validate(bd->d_cmlbh, 0, 0) != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* non-blocking opens are allowed to succeed */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (!ndelay) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ENXIO;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else if (cmlb_partinfo(bd->d_cmlbh, part, &nblks, &lba,
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore NULL, NULL, 0) == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * We read the partinfo, verify valid ranges. If the
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * partition is invalid, and we aren't blocking or
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * doing a raw access, then fail. (Non-blocking and
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * raw accesses can still succeed to allow a disk with
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * bad partition data to opened by format and fdisk.)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((!nblks) && ((!ndelay) || (otyp != OTYP_CHR))) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ENXIO;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else if (!ndelay) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * cmlb_partinfo failed -- invalid partition or no
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * disk label.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ENXIO;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((flag & FWRITE) && bd->d_rdonly) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EROFS;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bd->d_open_excl) & (mask)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EBUSY;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (flag & FEXCL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_open_lyr[part]) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EBUSY;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore for (int i = 0; i < OTYP_LYR; i++) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_open_reg[i] & mask) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = EBUSY;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore goto done;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (otyp == OTYP_LYR) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_open_lyr[part]++;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_open_reg[otyp] |= mask;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (flag & FEXCL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_open_excl |= mask;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoredone:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_ocmutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_exit(&bd_lock);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_close(dev_t dev, int flag, int otyp, cred_t *credp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t part;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint64_t mask;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t last = B_TRUE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(flag));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(credp));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore part = BDPART(dev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore inst = BDINST(dev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ASSERT(part < 64);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mask = (1U << part);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_enter(&bd_lock, RW_READER);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_exit(&bd_lock);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENXIO);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_enter(&bd->d_ocmutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_open_excl & mask) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_open_excl &= ~mask;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (otyp == OTYP_LYR) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_open_lyr[part]--;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_open_reg[otyp] &= ~mask;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore for (int i = 0; i < 64; i++) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_open_lyr[part]) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore last = B_FALSE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore for (int i = 0; last && (i < OTYP_LYR); i++) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_open_reg[i]) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore last = B_FALSE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_ocmutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (last) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore cmlb_invalidate(bd->d_cmlbh, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rw_exit(&bd_lock);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amorestatic int
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amorebd_dump(dev_t dev, caddr_t caddr, daddr_t blkno, int nblk)
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore{
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore minor_t inst;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore minor_t part;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore diskaddr_t pstart;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore diskaddr_t psize;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd_t *bd;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd_xfer_impl_t *xi;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore buf_t *bp;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore int rv;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_enter(&bd_lock, RW_READER);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore part = BDPART(dev);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore inst = BDINST(dev);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_exit(&bd_lock);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (ENXIO);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore /*
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * do cmlb, but do it synchronously unless we already have the
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * partition (which we probably should.)
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore */
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if (cmlb_partinfo(bd->d_cmlbh, part, &psize, &pstart, NULL, NULL,
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore (void *)1)) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_exit(&bd_lock);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (ENXIO);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if ((blkno + nblk) > psize) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_exit(&bd_lock);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (EINVAL);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bp = getrbuf(KM_NOSLEEP);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if (bp == NULL) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_exit(&bd_lock);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (ENOMEM);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bp->b_bcount = nblk << bd->d_blkshift;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bp->b_resid = bp->b_bcount;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bp->b_lblkno = blkno;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bp->b_un.b_addr = caddr;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_write, KM_NOSLEEP);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if (xi == NULL) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_exit(&bd_lock);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore freerbuf(bp);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (ENOMEM);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore xi->i_blkno = blkno + pstart;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore xi->i_flags = BD_XFER_POLL;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd_submit(bd, xi);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rw_exit(&bd_lock);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore /*
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * Generally, we should have run this entirely synchronously
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * at this point and the biowait call should be a no-op. If
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * it didn't happen this way, it's a bug in the underlying
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * driver not honoring BD_XFER_POLL.
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore */
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore (void) biowait(bp);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rv = geterror(bp);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore freerbuf(bp);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (rv);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore}
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsevvoid
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsevbd_minphys(struct buf *bp)
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev{
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev minor_t inst;
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev bd_t *bd;
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev inst = BDINST(bp->b_edev);
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev bd = ddi_get_soft_state(bd_state, inst);
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev /*
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev * In a non-debug kernel, bd_strategy will catch !bd as
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev * well, and will fail nicely.
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev */
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev ASSERT(bd);
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev if (bp->b_bcount > bd->d_maxxfer)
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev bp->b_bcount = bd->d_maxxfer;
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev}
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_read(dev_t dev, struct uio *uio, cred_t *credp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(credp));
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev return (physio(bd_strategy, NULL, dev, B_READ, bd_minphys, uio));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_write(dev_t dev, struct uio *uio, cred_t *credp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(credp));
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev return (physio(bd_strategy, NULL, dev, B_WRITE, bd_minphys, uio));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_aread(dev_t dev, struct aio_req *aio, cred_t *credp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(credp));
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev return (aphysio(bd_strategy, anocancel, dev, B_READ, bd_minphys, aio));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_awrite(dev_t dev, struct aio_req *aio, cred_t *credp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore _NOTE(ARGUNUSED(credp));
9d75dfda4910937c194437c3e1e45ca07c889ee5Alexey Zaytsev return (aphysio(bd_strategy, anocancel, dev, B_WRITE, bd_minphys, aio));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_strategy(struct buf *bp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t part;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore diskaddr_t p_lba;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore diskaddr_t p_nblks;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore diskaddr_t b_nblks;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint32_t shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int (*func)(void *, bd_xfer_t *);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore part = BDPART(bp->b_edev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore inst = BDINST(bp->b_edev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ASSERT(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid = bp->b_bcount;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, ENXIO);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (cmlb_partinfo(bd->d_cmlbh, part, &p_nblks, &p_lba,
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore NULL, NULL, 0)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, ENXIO);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore shift = bd->d_blkshift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((P2PHASE(bp->b_bcount, (1U << shift)) != 0) ||
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (bp->b_lblkno > p_nblks)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, ENXIO);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore b_nblks = bp->b_bcount >> shift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bp->b_lblkno == p_nblks) || (bp->b_bcount == 0)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((b_nblks + bp->b_lblkno) > p_nblks) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid = ((bp->b_lblkno + b_nblks - p_nblks) << shift);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_bcount -= bp->b_resid;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore func = (bp->b_flags & B_READ) ? bd->d_ops.o_read : bd->d_ops.o_write;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi = bd_xfer_alloc(bd, bp, func, KM_NOSLEEP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi = bd_xfer_alloc(bd, bp, func, KM_PUSHPAGE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* bd_request_alloc will have done bioerror */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_blkno = bp->b_lblkno + p_lba;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_submit(bd, xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minor_t inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore uint16_t part;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore void *ptr = (void *)arg;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore part = BDPART(dev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore inst = BDINST(dev);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bd = ddi_get_soft_state(bd_state, inst)) == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENXIO);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore rv = cmlb_ioctl(bd->d_cmlbh, dev, cmd, arg, flag, credp, rvalp, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != ENOTTY)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
a0cb694bef8ce5b375d89d042945f0e24bbd4026Steve Ma if (rvalp != NULL) {
a0cb694bef8ce5b375d89d042945f0e24bbd4026Steve Ma /* the return value of the ioctl is 0 by default */
a0cb694bef8ce5b375d89d042945f0e24bbd4026Steve Ma *rvalp = 0;
a0cb694bef8ce5b375d89d042945f0e24bbd4026Steve Ma }
a0cb694bef8ce5b375d89d042945f0e24bbd4026Steve Ma
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (cmd) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCGMEDIAINFO: {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore struct dk_minfo minfo;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* make sure our state information is current */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_update_state(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bzero(&minfo, sizeof (minfo));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minfo.dki_media_type = DK_FIXED_DISK;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minfo.dki_lbsize = (1U << bd->d_blkshift);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore minfo.dki_capacity = bd->d_numblks;
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald if (ddi_copyout(&minfo, ptr, sizeof (minfo), flag)) {
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald return (EFAULT);
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald }
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald return (0);
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald }
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald case DKIOCGMEDIAINFOEXT: {
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald struct dk_minfo_ext miext;
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald /* make sure our state information is current */
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald bd_update_state(bd);
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald bzero(&miext, sizeof (miext));
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald miext.dki_media_type = DK_FIXED_DISK;
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald miext.dki_lbsize = (1U << bd->d_blkshift);
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld miext.dki_pbsize = (1U << bd->d_pblkshift);
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald miext.dki_capacity = bd->d_numblks;
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald if (ddi_copyout(&miext, ptr, sizeof (miext), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCINFO: {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore struct dk_cinfo cinfo;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bzero(&cinfo, sizeof (cinfo));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_ctype = DKC_BLKDEV;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_cnum = ddi_get_instance(ddi_get_parent(bd->d_dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) snprintf(cinfo.dki_cname, sizeof (cinfo.dki_cname),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "%s", ddi_driver_name(ddi_get_parent(bd->d_dip)));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) snprintf(cinfo.dki_dname, sizeof (cinfo.dki_dname),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "%s", ddi_driver_name(bd->d_dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_unit = inst;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_flags = DKI_FMTVOL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_partition = part;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_maxtransfer = bd->d_maxxfer / DEV_BSIZE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_addr = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_slave = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_space = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_prio = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cinfo.dki_vec = 0;
dba604f95b3742920553aafd90c5b67721b07723Dan McDonald if (ddi_copyout(&cinfo, ptr, sizeof (cinfo), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCREMOVABLE: {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int i;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore i = bd->d_removable ? 1 : 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCHOTPLUGGABLE: {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int i;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore i = bd->d_hotpluggable ? 1 : 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCREADONLY: {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int i;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore i = bd->d_rdonly ? 1 : 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore case DKIOCSOLIDSTATE: {
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore int i;
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore i = bd->d_ssd ? 1 : 0;
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore if (ddi_copyout(&i, ptr, sizeof (i), flag)) {
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore return (EFAULT);
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore }
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore return (0);
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCSTATE: {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore enum dkio_state state;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_copyin(ptr, &state, sizeof (state), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((rv = bd_check_state(bd, &state)) != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ddi_copyout(&state, ptr, sizeof (state), flag)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DKIOCFLUSHWRITECACHE: {
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev struct dk_callback *dkc = NULL;
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev if (flag & FKIOCTL)
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev dkc = (void *)arg;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = bd_flush_write_cache(bd, dkc);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENOTTY);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore char *name, caddr_t valuep, int *lengthp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd == NULL)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ddi_prop_op(dev, dip, prop_op, mod_flags,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore name, valuep, lengthp));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (cmlb_prop_op(bd->d_cmlbh, dev, dip, prop_op, mod_flags, name,
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore valuep, lengthp, BDPART(dev), 0));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_tg_rdwr(dev_info_t *dip, uchar_t cmd, void *bufaddr, diskaddr_t start,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore size_t length, void *tg_cookie)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore buf_t *bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int (*func)(void *, bd_xfer_t *);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore int kmflag;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore /*
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * If we are running in polled mode (such as during dump(9e)
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * execution), then we cannot sleep for kernel allocations.
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore */
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore kmflag = tg_cookie ? KM_NOSLEEP : KM_SLEEP;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (P2PHASE(length, (1U << bd->d_blkshift)) != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* We can only transfer whole blocks at a time! */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EINVAL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore if ((bp = getrbuf(kmflag)) == NULL) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore return (ENOMEM);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (cmd) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_READ:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_flags = B_READ;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore func = bd->d_ops.o_read;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_WRITE:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_flags = B_WRITE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore func = bd->d_ops.o_write;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore freerbuf(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EINVAL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_un.b_addr = bufaddr;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_bcount = length;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore xi = bd_xfer_alloc(bd, bp, func, kmflag);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = geterror(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore freerbuf(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore xi->i_flags = tg_cookie ? BD_XFER_POLL : 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_blkno = start;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_submit(bd, xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) biowait(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = geterror(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore freerbuf(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_tg_getinfo(dev_info_t *dip, int cmd, void *arg, void *tg_cookie)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore _NOTE(ARGUNUSED(tg_cookie));
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd = ddi_get_soft_state(bd_state, ddi_get_instance(dip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (cmd) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_GETPHYGEOM:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_GETVIRTGEOM:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * We don't have any "geometry" as such, let cmlb
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * fabricate something.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENOTTY);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_GETCAPACITY:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_update_state(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *(diskaddr_t *)arg = bd->d_numblks;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_GETBLOCKSIZE:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *(uint32_t *)arg = (1U << bd->d_blkshift);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case TG_GETATTR:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * It turns out that cmlb really doesn't do much for
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * non-writable media, but lets make the information
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * available for it in case it does more in the
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * future. (The value is currently used for
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * triggering special behavior for CD-ROMs.)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_update_state(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ((tg_attribute_t *)arg)->media_is_writable =
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_rdonly ? B_FALSE : B_TRUE;
59d8f1005b65ef8ad2c9ce040497daf81dd65085Garrett D'Amore ((tg_attribute_t *)arg)->media_is_solid_state = bd->d_ssd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EINVAL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_sched(bd_t *bd)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore struct buf *bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore mutex_enter(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore while ((bd->d_qactive < bd->d_qsize) &&
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ((xi = list_remove_head(&bd->d_waitq)) != NULL)) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_qactive++;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_waitq_to_runq(bd->d_kiop);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_insert_tail(&bd->d_runq, xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore /*
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * Submit the job to the driver. We drop the I/O mutex
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * so that we can deal with the case where the driver
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore * completion routine calls back into us synchronously.
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore */
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore mutex_exit(&bd->d_iomutex);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = xi->i_func(bd->d_private, &xi->i_public);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp = xi->i_bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_transerrs.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore mutex_enter(&bd->d_iomutex);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd->d_qactive--;
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore kstat_runq_exit(bd->d_kiop);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore list_remove(&bd->d_runq, xi);
dd3928f816b8d87f7ecc81d6ec1eec1257ed0cdaHans Rosenfeld bd_xfer_free(xi);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_enter(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore mutex_exit(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_submit(bd_t *bd, bd_xfer_impl_t *xi)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_enter(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore list_insert_tail(&bd->d_waitq, xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_waitq_enter(bd->d_kiop);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_iomutex);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore bd_sched(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_runq_exit(bd_xfer_impl_t *xi, int err)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd = xi->i_bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore buf_t *bp = xi->i_bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore mutex_enter(&bd->d_iomutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_qactive--;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kstat_runq_exit(bd->d_kiop);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore list_remove(&bd->d_runq, xi);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore mutex_exit(&bd->d_iomutex);
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (err == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bp->b_flags & B_READ) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_kiop->reads++;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_kiop->nread += (bp->b_bcount - xi->i_resid);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_kiop->writes++;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_kiop->nwritten += (bp->b_bcount - xi->i_resid);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_sched(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic void
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_update_state(bd_t *bd)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld enum dkio_state state = DKIO_INSERTED;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore boolean_t docmlb = B_FALSE;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd_media_t media;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bzero(&media, sizeof (media));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_enter(&bd->d_statemutex);
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld if (bd->d_ops.o_media_info(bd->d_private, &media) != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_numblks = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore state = DKIO_EJECTED;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld goto done;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld }
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld if ((media.m_blksize < 512) ||
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld (!ISP2(media.m_blksize)) ||
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld (P2PHASE(bd->d_maxxfer, media.m_blksize))) {
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld cmn_err(CE_WARN, "%s%d: Invalid media block size (%d)",
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld ddi_driver_name(bd->d_dip), ddi_get_instance(bd->d_dip),
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld media.m_blksize);
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld /*
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld * We can't use the media, treat it as not present.
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld */
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld state = DKIO_EJECTED;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_numblks = 0;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld goto done;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld }
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld if (((1U << bd->d_blkshift) != media.m_blksize) ||
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld (bd->d_numblks != media.m_nblks)) {
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld /* Device size changed */
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld docmlb = B_TRUE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_blkshift = ddi_ffs(media.m_blksize) - 1;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_pblkshift = bd->d_blkshift;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_numblks = media.m_nblks;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_rdonly = media.m_readonly;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_ssd = media.m_solidstate;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld /*
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld * Only use the supplied physical block size if it is non-zero,
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld * greater or equal to the block size, and a power of 2. Ignore it
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld * if not, it's just informational and we can still use the media.
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld */
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld if ((media.m_pblksize != 0) &&
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld (media.m_pblksize >= media.m_blksize) &&
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld (ISP2(media.m_pblksize)))
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld bd->d_pblkshift = ddi_ffs(media.m_pblksize) - 1;
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfeld
32ce6b819524e8719d4ce58db40a00e9f17843e2Hans Rosenfelddone:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (state != bd->d_state) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd->d_state = state;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cv_broadcast(&bd->d_statecv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore docmlb = B_TRUE;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd->d_kerr->bd_capacity.value.ui64 = bd->d_numblks << bd->d_blkshift;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (docmlb) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (state == DKIO_INSERTED) {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore (void) cmlb_validate(bd->d_cmlbh, 0, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
86e3bca69f59096fa71848f8e8614c38ac86a24aGarrett D'Amore cmlb_invalidate(bd->d_cmlbh, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_check_state(bd_t *bd, enum dkio_state *state)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore clock_t when;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore for (;;) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_update_state(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_enter(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_state != *state) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *state = bd->d_state;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore when = drv_usectohz(1000000);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (cv_reltimedwait_sig(&bd->d_statecv, &bd->d_statemutex,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore when, TR_CLOCK_TICK) == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (EINTR);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore mutex_exit(&bd->d_statemutex);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_flush_write_cache_done(struct buf *bp)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore struct dk_callback *dc = (void *)bp->b_private;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (*dc->dkc_callback)(dc->dkc_cookie, geterror(bp));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_free(dc, sizeof (*dc));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore freerbuf(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorestatic int
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_flush_write_cache(bd_t *bd, struct dk_callback *dkc)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore buf_t *bp;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore struct dk_callback *dc;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_ops.o_sync_cache == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENOTSUP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bp = getrbuf(KM_SLEEP)) == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ENOMEM);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_bcount = 0;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi = bd_xfer_alloc(bd, bp, bd->d_ops.o_sync_cache, KM_SLEEP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = geterror(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore freerbuf(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev /* Make an asynchronous flush, but only if there is a callback */
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev if (dkc != NULL && dkc->dkc_callback != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* Make a private copy of the callback structure */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dc = kmem_alloc(sizeof (*dc), KM_SLEEP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore *dc = *dkc;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_private = dc;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_iodone = bd_flush_write_cache_done;
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev bd_submit(bd, xi);
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev return (0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev /* In case there is no callback, perform a synchronous flush */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_submit(bd, xi);
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev (void) biowait(bp);
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev rv = geterror(bp);
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev freerbuf(bp);
f097ef9c335ca15d17a8caba066fb2da38a3a1beAlexey Zaytsev
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore/*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Nexus support.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoreint
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore void *arg, void *result)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_handle_t hdl;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore switch (ctlop) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_CTLOPS_REPORTDEV:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_CONT, "?Block device: %s@%s, %s%d\n",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_node_name(rdip), ddi_get_name_addr(rdip),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_driver_name(rdip), ddi_get_instance(rdip));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_CTLOPS_INITCHILD:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl = ddi_get_parent_data((dev_info_t *)arg);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (hdl == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_NOT_WELL_FORMED);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_set_name_addr((dev_info_t *)arg, hdl->h_addr);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case DDI_CTLOPS_UNINITCHILD:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_set_name_addr((dev_info_t *)arg, NULL);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ndi_prop_remove_all((dev_info_t *)arg);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore default:
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (ddi_ctlops(dip, rdip, ctlop, arg, result));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore/*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * Functions for device drivers.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_handle_t
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_alloc_handle(void *private, bd_ops_t *ops, ddi_dma_attr_t *dma, int kmflag)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_handle_t hdl;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl = kmem_zalloc(sizeof (*hdl), kmflag);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (hdl != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_ops = *ops;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_dma = dma;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_private = private;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (hdl);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorevoid
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_free_handle(bd_handle_t hdl)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_free(hdl, sizeof (*hdl));
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoreint
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_attach_handle(dev_info_t *dip, bd_handle_t hdl)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore dev_info_t *child;
510a68476ba6e33759b7603130d76db4cec783d1Hans Rosenfeld bd_drive_t drive = { 0 };
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* if drivers don't override this, make it assume none */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore drive.d_lun = -1;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_ops.o_drive_info(hdl->h_private, &drive);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_parent = dip;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_name = "blkdev";
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld /*LINTED: E_BAD_PTR_CAST_ALIGN*/
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld if (*(uint64_t *)drive.d_eui64 != 0) {
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld if (drive.d_lun >= 0) {
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld "w%02X%02X%02X%02X%02X%02X%02X%02X,%X",
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[0], drive.d_eui64[1],
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[2], drive.d_eui64[3],
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[4], drive.d_eui64[5],
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[6], drive.d_eui64[7], drive.d_lun);
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld } else {
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld "w%02X%02X%02X%02X%02X%02X%02X%02X",
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[0], drive.d_eui64[1],
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[2], drive.d_eui64[3],
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[4], drive.d_eui64[5],
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld drive.d_eui64[6], drive.d_eui64[7]);
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld if (drive.d_lun >= 0) {
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld "%X,%X", drive.d_target, drive.d_lun);
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld } else {
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld (void) snprintf(hdl->h_addr, sizeof (hdl->h_addr),
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld "%X", drive.d_target);
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
df8c228748280860358d01a3d32ce256aeb51c38Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ndi_devi_alloc(dip, hdl->h_name, (pnode_t)DEVI_SID_NODEID,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &child) != NDI_SUCCESS) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN, "%s%d: unable to allocate node %s@%s",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_driver_name(dip), ddi_get_instance(dip),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore "blkdev", hdl->h_addr);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_set_parent_data(child, hdl);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_child = child;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (ndi_devi_online(child, 0) == NDI_FAILURE) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore cmn_err(CE_WARN, "%s%d: failed bringing node %s@%s online",
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_driver_name(dip), ddi_get_instance(dip),
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_name, hdl->h_addr);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ndi_devi_free(child);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amoreint
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_detach_handle(bd_handle_t hdl)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int circ;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore int rv;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore char *devnm;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (hdl->h_child == NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return (DDI_SUCCESS);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ndi_devi_enter(hdl->h_parent, &circ);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (i_ddi_node_state(hdl->h_child) < DS_INITIALIZED) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ddi_remove_child(hdl->h_child, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) ddi_deviname(hdl->h_child, devnm);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (void) devfs_clean(hdl->h_parent, devnm + 1, DV_CLEAN_FORCE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ndi_devi_unconfig_one(hdl->h_parent, devnm + 1, NULL,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NDI_DEVI_REMOVE | NDI_UNCONFIG);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore kmem_free(devnm, MAXNAMELEN + 1);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore hdl->h_child = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ndi_devi_exit(hdl->h_parent, circ);
aad3a4472fe05e2634744298e937a4070b663517Hans Rosenfeld return (rv == NDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorevoid
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_xfer_done(bd_xfer_t *xfer, int err)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_impl_t *xi = (void *)xfer;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore buf_t *bp = xi->i_bp;
06711e0cbc5503c70ec7dc43e2ddc6a2e6a5fe8bDmitry Yusupov int rv = DDI_SUCCESS;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd = xi->i_bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore size_t len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (err != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_runq_exit(xi, err);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_harderrs.value.ui32);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid += xi->i_resid;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_free(xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, err);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_cur_win++;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_resid -= xi->i_len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (xi->i_resid == 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* Job completed succcessfully! */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_runq_exit(xi, 0);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_free(xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_blkno += xi->i_nblks;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (bd->d_use_dma) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* More transfer still pending... advance to next DMA window. */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = ddi_dma_getwin(xi->i_dmah, xi->i_cur_win,
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore &xi->i_offset, &len, &xi->i_dmac, &xi->i_ndmac);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore } else {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* Advance memory window. */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_kaddr += xi->i_len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_offset += xi->i_len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore len = min(bp->b_bcount - xi->i_offset, bd->d_maxxfer);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((rv != DDI_SUCCESS) ||
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore (P2PHASE(len, (1U << xi->i_blkshift) != 0))) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_runq_exit(xi, EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid += xi->i_resid;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_free(xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, EFAULT);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore return;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_len = len;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore xi->i_nblks = len >> xi->i_blkshift;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /* Submit next window to hardware. */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore rv = xi->i_func(bd->d_private, &xi->i_public);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if (rv != 0) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_runq_exit(xi, rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_transerrs.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bp->b_resid += xi->i_resid;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_xfer_free(xi);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bioerror(bp, rv);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore biodone(bp);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldvoid
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeldbd_error(bd_xfer_t *xfer, int error)
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld{
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_xfer_impl_t *xi = (void *)xfer;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld bd_t *bd = xi->i_bd;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld switch (error) {
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld case BD_ERR_MEDIA:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_rq_media_err.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld case BD_ERR_NTRDY:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_rq_ntrdy_err.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld case BD_ERR_NODEV:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_rq_nodev_err.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld case BD_ERR_RECOV:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_rq_recov_err.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld case BD_ERR_ILLRQ:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_rq_illrq_err.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld case BD_ERR_PFA:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld atomic_inc_32(&bd->d_kerr->bd_rq_pfa_err.value.ui32);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld default:
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld cmn_err(CE_PANIC, "bd_error: unknown error type %d", error);
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld break;
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld }
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld}
bef9e21af8ac4992b7dfef56530c7b0ed9184096Hans Rosenfeld
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorevoid
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_state_change(bd_handle_t hdl)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_t *bd;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore if ((bd = hdl->h_bd) != NULL) {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_update_state(bd);
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore }
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorevoid
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_mod_init(struct dev_ops *devops)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore static struct bus_ops bd_bus_ops = {
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore BUSO_REV, /* busops_rev */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore nullbusmap, /* bus_map */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_get_intrspec (OBSOLETE) */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_add_intrspec (OBSOLETE) */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_remove_intrspec (OBSOLETE) */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore i_ddi_map_fault, /* bus_map_fault */
cd21e7c548ae2a3b5e522244bf798f2a6b4ba02dGarrett D'Amore NULL, /* bus_dma_map (OBSOLETE) */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_allochdl, /* bus_dma_allochdl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_freehdl, /* bus_dma_freehdl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_bindhdl, /* bus_dma_bindhdl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_unbindhdl, /* bus_dma_unbindhdl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_flush, /* bus_dma_flush */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_win, /* bus_dma_win */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_dma_mctl, /* bus_dma_ctl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore bd_bus_ctl, /* bus_ctl */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore ddi_bus_prop_op, /* bus_prop_op */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_get_eventcookie */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_add_eventcall */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_remove_eventcall */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_post_event */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_intr_ctl (OBSOLETE) */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_config */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_unconfig */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_fm_init */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_fm_fini */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_fm_access_enter */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_fm_access_exit */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_power */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore NULL, /* bus_intr_op */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore };
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore devops->devo_bus_ops = &bd_bus_ops;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore /*
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * NB: The device driver is free to supply its own
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * character entry device support.
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore */
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorevoid
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amorebd_mod_fini(struct dev_ops *devops)
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore{
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore devops->devo_bus_ops = NULL;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore}