hba.c revision 0167b58cea98965c58fab4be4e690b6e456f7440
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 1394 mass storage HBA driver
*/
#include <sys/byteorder.h>
static int scsa1394_power(dev_info_t *, int, int);
/* configuration routines */
static void scsa1394_cleanup(scsa1394_state_t *, int);
static int scsa1394_attach_1394(scsa1394_state_t *);
static void scsa1394_detach_1394(scsa1394_state_t *);
static int scsa1394_attach_threads(scsa1394_state_t *);
static void scsa1394_detach_threads(scsa1394_state_t *);
static int scsa1394_attach_scsa(scsa1394_state_t *);
static void scsa1394_detach_scsa(scsa1394_state_t *);
static int scsa1394_create_cmd_cache(scsa1394_state_t *);
static void scsa1394_destroy_cmd_cache(scsa1394_state_t *);
static int scsa1394_add_events(scsa1394_state_t *);
static void scsa1394_remove_events(scsa1394_state_t *);
/* device configuration */
ddi_bus_config_op_t, void *, dev_info_t **);
ddi_bus_config_op_t, void *);
static void scsa1394_create_children(scsa1394_state_t *);
void *);
void *);
void *);
/* SCSA HBA entry points */
scsi_hba_tran_t *, struct scsi_device *);
scsi_hba_tran_t *, struct scsi_device *);
static int scsa1394_scsi_tgt_probe(struct scsi_device *, int (*)());
static int scsa1394_probe_g0_nodata(struct scsi_device *, int (*)(),
static int scsa1394_probe_tran(struct scsi_pkt *);
static void scsa1394_scsi_destroy_pkt(struct scsi_address *,
struct scsi_pkt *);
static int scsa1394_scsi_reset(struct scsi_address *, int);
static int scsa1394_scsi_getcap(struct scsi_address *, char *, int);
static int scsa1394_scsi_setcap(struct scsi_address *, char *, int, int);
static void scsa1394_scsi_sync_pkt(struct scsi_address *,
struct scsi_pkt *);
/* pkt resource allocation routines */
static int scsa1394_cmd_cache_constructor(void *, void *, int);
static void scsa1394_cmd_cache_destructor(void *, void *);
int);
int, int (*)(), caddr_t);
ddi_dma_cookie_t *, uint_t, int);
int (*)(), caddr_t, int);
static int scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *,
scsa1394_cmd_t *);
static void scsa1394_cmd_buf_addr_free(scsa1394_state_t *,
scsa1394_cmd_t *);
/* pkt and data transfer routines */
static void scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *, int);
static void scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *, int);
static void scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *, int);
static void scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *, int);
static int scsa1394_cmd_read_cd_blk_size(uchar_t);
static int scsa1394_cmd_fake_mode_sense(scsa1394_state_t *,
scsa1394_cmd_t *);
static int scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *,
scsa1394_cmd_t *);
/* other routines */
static void * scsa1394_kmem_realloc(void *, int, int, size_t, int);
static void *scsa1394_statep;
static struct cb_ops scsa1394_cb_ops = {
nodev, /* open */
nodev, /* close */
nodev, /* strategy */
nodev, /* print */
nodev, /* dump */
nodev, /* read */
nodev, /* write */
NULL, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
ddi_prop_op, /* prop_op */
NULL, /* stream */
D_MP, /* cb_flag */
CB_REV, /* rev */
nodev, /* aread */
nodev /* awrite */
};
static struct dev_ops scsa1394_ops = {
DEVO_REV, /* devo_rev, */
0, /* refcnt */
ddi_no_info, /* info */
nulldev, /* identify */
nulldev, /* probe */
scsa1394_attach, /* attach */
scsa1394_detach, /* detach */
nodev, /* reset */
&scsa1394_cb_ops, /* driver operations */
NULL, /* bus operations */
scsa1394_power /* power */
};
static struct modldrv scsa1394_modldrv = {
&mod_driverops, /* module type */
"1394 Mass Storage HBA Driver %I%", /* name of the module */
&scsa1394_ops, /* driver ops */
};
static struct modlinkage scsa1394_modlinkage = {
};
/* tunables */
int scsa1394_bus_config_debug = 0;
/* workarounds */
int scsa1394_wrka_rbc2direct = 1;
int scsa1394_wrka_fake_rmb = 0;
int scsa1394_wrka_fake_prin = 1;
int scsa1394_wrka_symbios = 1;
/*
*
*
*/
int
_init(void)
{
int ret;
sizeof (scsa1394_state_t), 1)) != 0)) {
return (ret);
}
return (ret);
}
return (ret);
}
return (ret);
}
int
_fini(void)
{
int ret;
}
return (ret);
}
int
{
}
static int
{
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
#ifndef __lock_lint
#endif
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
#ifndef __lock_lint
#endif
return (DDI_SUCCESS);
}
static int
{
return (DDI_FAILURE);
}
switch (cmd) {
case DDI_DETACH:
return (DDI_SUCCESS);
case DDI_SUSPEND:
return (DDI_FAILURE);
default:
return (DDI_FAILURE);
}
}
/*ARGSUSED*/
static int
{
return (DDI_SUCCESS);
}
/*
*
* --- configuration routines
*
*/
static void
{
switch (level) {
default:
/* FALLTHRU */
case 6:
/* FALLTHRU */
case 5:
/* FALLTHRU */
case 4:
/* FALLTHRU */
case 3:
/* FALLTHRU */
case 2:
/* FALLTHRU */
case 1:
}
}
static int
{
int ret;
return (ret);
}
/* DMA attributes for data buffers */
/* DMA attributes for page tables */
return (ret);
}
return (DDI_SUCCESS);
}
static void
{
}
static int
{
char name[16];
int nthr;
TASKQ_DEFAULTPRI, 0)) == NULL) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
{
}
static int
{
int ret;
tran, 0)) != DDI_SUCCESS) {
return (ret);
}
return (DDI_SUCCESS);
}
static void
{
int ret;
}
static int
{
char name[64];
sizeof (scsa1394_cmd_t), sizeof (void *),
}
static void
{
}
static int
{
&br_evc) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
&rem_evc) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
&ins_evc) != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
{
&evc) == DDI_SUCCESS) {
}
&evc) == DDI_SUCCESS) {
}
&evc) == DDI_SUCCESS) {
}
}
/*
*
* --- device configuration
*
*/
static int
{
int circ;
int ret;
if (scsa1394_bus_config_debug) {
flag |= NDI_DEVI_DEBUG;
}
}
return (ret);
}
static int
void *arg)
{
int circ;
int ret;
if (scsa1394_bus_config_debug) {
flag |= NDI_DEVI_DEBUG;
}
/*
* First offline and if offlining successful, then remove children.
*/
if (op == BUS_UNCONFIG_ALL) {
}
/*
* If previous step was successful and not part of modunload daemon,
* attempt to remove children.
*/
((flag & NDI_AUTODETACH) == 0)) {
flag |= NDI_DEVI_REMOVE;
}
((saved_flag & NDI_DEVI_REMOVE) != 0)) {
if (!sp->s_disconnect_warned) {
"Disconnected device was busy, please reconnect.\n",
sp->s_instance);
}
}
return (ret);
}
void
{
static struct {
char *node_name;
char *driver_name;
} dtype2name[] = {
{ "disk", "sd" }, /* DTYPE_DIRECT 0x00 */
{ "tape", "st" }, /* DTYPE_SEQUENTIAL 0x01 */
{ "disk", "sd" }, /* DTYPE_RODIRECT 0x05 */
{ "disk", "sd" }, /* DTYPE_OPTICAL 0x07 */
{ "esi", "ses" }, /* DTYPE_ESI 0x0D */
{ "disk", "sd" } /* DTYPE_RBC 0x0E */
};
} else {
*node_name = "generic";
*driver_name = NULL;
}
}
static void
{
char *compatible[SCSA1394_COMPAT_MAX];
int i;
int dtype;
char *node_name;
char *driver_name;
int ret;
for (i = 0; i < SCSA1394_COMPAT_MAX; i++) {
compatible[i] = name[i];
}
if (ret != DDI_PROP_SUCCESS) {
(void) ndi_devi_free(cdip);
continue;
}
if (ret != DDI_PROP_SUCCESS) {
(void) ndi_devi_free(cdip);
continue;
}
/*
* Some devices don't support LOG SENSE, so tell
* sd driver not to send this command.
*/
"pm-capable", 1);
if (ret != DDI_PROP_SUCCESS) {
(void) ndi_devi_free(cdip);
continue;
}
"hotpluggable");
if (ret != DDI_PROP_SUCCESS) {
(void) ndi_devi_free(cdip);
continue;
}
if (driver_name) {
compatible[0] = driver_name;
"compatible", (char **)compatible,
if (ret != DDI_PROP_SUCCESS) {
(void) ndi_devi_free(cdip);
continue;
}
}
/*
* add property "scsa1394" to distinguish from others' children
*/
if (ret != DDI_PROP_SUCCESS) {
(void) ndi_devi_free(cdip);
continue;
}
}
}
/*ARGSUSED*/
static void
void *data)
{
return;
}
}
}
/*ARGSUSED*/
static void
void *data)
{
int circ;
return;
}
}
}
/*ARGSUSED*/
static void
void *data)
{
int circ;
return;
}
}
}
/*
*
* --- SCSA entry points
*
*/
/*ARGSUSED*/
static int
struct scsi_device *sd)
{
int lun;
int plen = sizeof (int);
int ret = DDI_FAILURE;
&plen) != DDI_PROP_SUCCESS) {
return (DDI_FAILURE);
}
if (!scsa1394_is_my_child(cdip)) {
/*
* add property "scsa1394" to distinguish from others' children
*/
if (ret != DDI_PROP_SUCCESS) {
return (DDI_FAILURE);
}
if (scsa1394_dev_is_online(sp)) {
} else {
return (DDI_FAILURE);
}
}
!scsa1394_dev_is_online(sp)) {
return (DDI_FAILURE);
}
}
return (ret);
}
/*ARGSUSED*/
static void
struct scsi_device *sd)
{
int lun;
int plen = sizeof (int);
if (!scsa1394_is_my_child(cdip)) {
return;
}
&plen) != DDI_PROP_SUCCESS) {
return;
}
if (scsa1394_dev_is_online(sp)) {
}
}
}
static int
{
if (!scsa1394_dev_is_online(sp)) {
return (SCSIPROBE_FAILURE);
}
SCMD_TEST_UNIT_READY, 0, 0) != SCSIPROBE_EXISTS) {
}
}
/* standard probe issues INQUIRY, which some devices may not support */
#ifndef __lock_lint
#endif
}
if (scsa1394_wrka_fake_rmb) {
}
return (SCSIPROBE_EXISTS);
}
static int
{
int ret = SCSIPROBE_EXISTS;
return (SCSIPROBE_NOMEM);
}
0);
if (scsa1394_probe_tran(pkt) < 0) {
} else {
}
}
return (ret);
}
static int
{
return (-1);
return (-1);
return (-1);
return (0);
}
return (0);
}
/*ARGSUSED*/
static int
{
return (0);
}
static int
{
int ret;
switch (level) {
case RESET_ALL:
case RESET_TARGET:
break;
case RESET_LUN:
break;
default:
return (DDI_FAILURE);
}
}
/*ARGSUSED*/
static int
{
int ret = -1;
if (!scsa1394_dev_is_online(sp)) {
return (-1);
}
return (-1);
}
switch (scsi_hba_lookup_capstr(cap)) {
case SCSI_CAP_DMA_MAX:
break;
case SCSI_CAP_SCSI_VERSION:
break;
case SCSI_CAP_ARQ:
ret = 1;
break;
case SCSI_CAP_UNTAGGED_QING:
ret = 1;
break;
case SCSI_CAP_GEOMETRY:
}
/* unlabeled floppy, 18k per cylinder */
/* 1024k per cylinder */
/* ~8m per cylinder */
} else { /* .. 8TB */
/* 64m per cylinder */
}
break;
default:
break;
}
return (ret);
}
/*ARGSUSED*/
static int
{
int ret = -1;
if (!scsa1394_dev_is_online(sp)) {
return (-1);
}
switch (scsi_hba_lookup_capstr(cap)) {
case SCSI_CAP_ARQ:
ret = 1;
break;
case SCSI_CAP_DMA_MAX:
case SCSI_CAP_SCSI_VERSION:
case SCSI_CAP_UNTAGGED_QING:
/* supported but not settable */
ret = 0;
break;
case SCSI_CAP_SECTOR_SIZE:
if (value) {
}
break;
case SCSI_CAP_TOTAL_SECTORS:
if (value) {
}
break;
default:
break;
}
return (ret);
}
/*ARGSUSED*/
static void
{
}
}
/*
*
* --- pkt resource allocation routines
*
*/
static struct scsi_pkt *
{
return (NULL);
}
/*
* allocate cmd space
*/
return (NULL);
}
/* initialize cmd */
/* need external space? */
DDI_SUCCESS) {
return (NULL);
}
}
/* allocate DMA resources for CDB */
DDI_SUCCESS) {
return (NULL);
}
} else {
}
if (is_new) {
}
return (NULL);
}
} else {
return (NULL);
}
}
}
/*
* kernel virtual address may be required for certain workarounds
* and in case of B_PHYS or B_PAGEIO, bp_mapin() will get it for us
*/
}
return (pkt);
}
static void
{
}
}
}
}
}
static void
{
}
}
}
/*ARGSUSED*/
static int
{
return (0);
}
/*ARGSUSED*/
static void
{
}
/*
* allocate and deallocate external cmd space (ie. not part of scsa1394_cmd_t)
* for non-standard length cdb, pkt_private, status areas
*/
static int
{
void *buf;
return (DDI_FAILURE);
}
}
return (DDI_FAILURE);
}
}
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static void
{
}
}
}
}
/*ARGSUSED*/
static int
{
sizeof (scsa1394_cmd_orb_t)) != SBP2_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static void
{
}
/*
* buffer resources
*/
static int
{
int dma_flags;
int error;
int ret;
return (DDI_FAILURE);
}
} else {
}
if (flags & PKT_CONSISTENT) {
}
if (flags & PKT_DMA_PARTIAL) {
}
switch (ret) {
case DDI_DMA_MAPPED:
cmd->sc_win_offset = 0;
break;
case DDI_DMA_PARTIAL_MAP:
/* retrieve number of windows and first window cookie */
DDI_SUCCESS) ||
DDI_SUCCESS)) {
return (DDI_FAILURE);
}
break;
case DDI_DMA_NORESOURCES:
error = 0;
goto map_error;
case DDI_DMA_BADATTR:
case DDI_DMA_NOMAPPING:
goto map_error;
default:
return (DDI_FAILURE);
}
/*
* setup page table if needed
*/
} else {
/* break window into segments */
DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* allocate DMA resources for page table */
return (DDI_FAILURE);
}
}
/* allocate 1394 addresses for segments */
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
{
}
}
}
/*
* Break a set DMA cookies into segments suitable for SBP-2 page table.
* This routine can reuse/reallocate segment array from previous calls.
*/
static int
{
int i;
int nsegs;
/*
* Number of segments is unknown at this point. Start with
* a reasonable estimate and grow it later if needed.
*/
} else {
/*
* For Symbios workaround we know exactly the number of segments
* Additional segment may be needed if buffer is not aligned.
*/
nsegs =
}
cmd->sc_buf_nsegs_alloc = 0;
return (DDI_FAILURE);
}
}
/* each cookie maps into one or more segments */
cmd->sc_buf_nsegs = 0;
i = ccount;
for (;;) {
while (dmac_resid > 0) {
/* grow array if needed */
return (DDI_FAILURE);
}
}
cmd->sc_buf_nsegs++;
}
ASSERT(dmac_resid == 0);
/* grab next cookie */
if (--i <= 0) {
break;
}
}
}
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static void
{
if (cmd->sc_buf_nsegs_alloc > 0) {
sizeof (scsa1394_cmd_seg_t));
}
cmd->sc_buf_nsegs = 0;
cmd->sc_buf_nsegs_alloc = 0;
}
static int
{
int result;
/* allocate DMA memory for page table */
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
/* allocate 1394 address for page table */
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static void
{
}
/*
* allocate 1394 addresses for all buffer segments
*/
static int
{
int result;
int i;
} else {
}
for (i = 0; i < cmd->sc_buf_nsegs; i++) {
/* segment bus address */
DDI_SUCCESS) {
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
static void
{
int i;
for (i = 0; i < cmd->sc_buf_nsegs; i++) {
}
}
}
/*
* move to next DMA window
*/
static int
{
/* scsa1394_lun_t *lp = cmd->sc_lun; */
/* for small pkts, leave things where they are (says WDD) */
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
DDI_SUCCESS) {
return (DDI_FAILURE);
}
/*
* setup page table if needed
*/
/* but first, free old resources */
}
} else {
/* break window into segments */
DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* allocate DMA resources */
return (DDI_FAILURE);
}
}
/* allocate 1394 addresses for segments */
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
*
* --- pkt and data transfer routines
*
*/
static int
{
int ret;
/*
* since we don't support polled I/O, just accept the packet
* so the rest of the file systems get synced properly
*/
if (ddi_in_panic()) {
return (TRAN_ACCEPT);
}
/* polling not supported yet */
return (TRAN_BADPKT);
}
/*
* If device is temporarily gone due to bus reset,
* return busy to prevent prevent scary console messages.
* If permanently gone, leave it to scsa1394_cmd_fake_comp().
*/
return (TRAN_BUSY);
}
}
return (TRAN_BADPKT);
}
/* some commands may require fake completion */
return (TRAN_ACCEPT);
}
}
}
return (ret);
}
/*ARGSUSED*/
static void
{
pkt->pkt_statistics = 0;
if (cmd) {
/* workarounds */
/*
* sd does START_STOP_UNIT during attach with a 200 sec timeout.
* at this time devi_lock is held, prtconf will be stuck.
* reduce timeout for the time being.
*/
case SCMD_START_STOP:
break;
default:
break;
}
}
}
static void
{
switch (lp->l_dtype_orig) {
case DTYPE_DIRECT:
case DTYPE_RODIRECT:
case DTYPE_OPTICAL:
case SCSA1394_DTYPE_RBC:
break;
default:
break;
}
}
static void
{
int sz;
switch (opcode) {
case SCMD_READ:
break;
case SCMD_WRITE:
break;
case SCMD_READ_G1:
case SCMD_READ_LONG:
break;
case SCMD_WRITE_G1:
case SCMD_WRITE_LONG:
if (SCSA1394_VALID_CDRW_BLKSZ(sz)) {
}
}
break;
case SCMD_READ_CD:
break;
case SCMD_READ_G5:
break;
case SCMD_WRITE_G5:
break;
default:
/* no special mapping for other commands */
return;
}
/* limit xfer length for Symbios workaround */
}
/* finalize new CDB */
switch (opcode) {
case SCMD_READ_CD:
break;
case SCMD_WRITE_G5:
case SCMD_READ_G5:
break;
default:
break;
}
}
/*ARGSUSED*/
static void
{
}
/*
* fill up parts of CDB
*/
static void
{
}
static void
{
}
static void
{
}
static void
{
}
/*
* For SCMD_READ_CD, figure out the block size based on expected sector type.
* See MMC SCSI Specs section 6.1.15
*/
static int
{
int blk_size;
switch (expected_sector_type) {
case READ_CD_EST_CDDA:
break;
case READ_CD_EST_MODE2:
break;
case READ_CD_EST_MODE2FORM2:
break;
case READ_CD_EST_MODE2FORM1:
case READ_CD_EST_ALLTYPE:
case READ_CD_EST_MODE1:
default:
}
return (blk_size);
}
/*ARGSUSED*/
static int
{
arqp->sts_rqpkt_resid = 0;
arqp->sts_rqpkt_statistics = 0;
}
return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
{
struct scsi_inquiry *inq;
/* copy fabricated inquiry data */
}
return (DDI_SUCCESS);
}
/*
* If command allows fake completion (without actually being transported),
* call completion callback and return DDI_SUCCESS.
* Otherwise return DDI_FAILURE.
*/
static int
{
int ret = DDI_SUCCESS;
/*
* agreement with sd in case of device hot removal
* is to fake completion with CMD_DEV_GONE
*/
}
return (DDI_SUCCESS);
}
/*
*/
case SCMD_PRIN:
case SCMD_PROUT:
if (!scsa1394_wrka_fake_prin) {
ret = DDI_FAILURE;
}
break;
/*
* Some fixed disks don't like doorlock cmd. And they don't need it.
*/
case SCMD_DOORLOCK:
if (lp->l_rmb_orig != 0) {
ret = DDI_FAILURE;
}
break;
case SCMD_TEST_UNIT_READY:
if (!lp->l_nosup_tur) {
ret = DDI_FAILURE;
}
break;
case SCMD_START_STOP:
if (!lp->l_nosup_start_stop) {
ret = DDI_FAILURE;
}
break;
case SCMD_INQUIRY:
if (!lp->l_nosup_inquiry) {
ret = DDI_FAILURE;
} else {
}
break;
case SCMD_MODE_SENSE:
if (!lp->l_mode_sense_fake) {
ret = DDI_FAILURE;
} else {
}
default:
ret = DDI_FAILURE;
}
if (ret != DDI_SUCCESS) {
return (ret);
}
}
return (DDI_SUCCESS);
}
/*
* Returns DDI_SUCCESS if next xfer setup successfully, DDI_FAILURE otherwise.
*/
static int
{
if (cmd->sc_resid_blks <= 0) {
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* new lba = current lba + previous xfer len
*/
/*ARGSUSED*/
static void
{
int len;
/* limit xfer length for Symbios workaround */
}
case SCMD_READ_CD:
break;
case SCMD_WRITE_G5:
case SCMD_READ_G5:
break;
case SCMD_WRITE_G1:
case SCMD_WRITE_LONG:
default:
}
}
void
{
/* next iteration of partial xfer? */
return;
}
}
/* apply workarounds */
}
/* mode sense workaround */
lp->l_mode_sense_fail_cnt = 0;
} else if (++lp->l_mode_sense_fail_cnt >=
}
} else {
lp->l_mode_sense_fail_cnt = 0;
}
}
}
static void
{
case SCMD_INQUIRY: {
struct scsi_inquiry *inq;
/* change dtype RBC to DIRECT, sd doesn't support RBC */
}
/* force RMB to 1 */
if (scsa1394_wrka_fake_rmb) {
}
break;
}
case SCMD_READ_CAPACITY: {
if (lp->l_lba_size == 0) {
"possibly broken device");
}
} else {
}
}
default:
break;
}
}
/*
* --- thread management
*
* dispatch a thread
*/
int
{
int ret;
KM_SLEEP);
return (ret);
}
/*
* cancel thread
*/
void
{
/* wait until the thread actually exits */
do {
break;
}
}
/*
* wake thread
*/
void
{
}
void
{
}
/*
*
* --- other routines
*
*/
static boolean_t
{
}
{
return (ret);
}
static void *
int kf)
{
void *new_buf;
if (old_size > 0) {
}
}
return (new_buf);
}