sbp2_driver.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 1394 mass storage SBP-2 driver routines
*/
static void scsa1394_sbp2_detect_symbios(scsa1394_state_t *);
static void scsa1394_sbp2_worker_thread(void *);
static void scsa1394_sbp2_status_cb(void *, sbp2_task_t *);
static void scsa1394_sbp2_req_bus_reset(scsa1394_lun_t *);
static void scsa1394_sbp2_req_reconnect(scsa1394_lun_t *);
static void scsa1394_sbp2_seg2pt_default(scsa1394_lun_t *,
scsa1394_cmd_t *);
static void scsa1394_sbp2_seg2pt_symbios(scsa1394_lun_t *,
scsa1394_cmd_t *);
static void scsa1394_sbp2_req_status(scsa1394_lun_t *);
static int scsa1394_sbp2_conv_status(scsa1394_cmd_t *,
static void scsa1394_sbp2_reset_proc(scsa1394_lun_t *, int,
scsa1394_cmd_t *);
extern sbp2_bus_t scsa1394_sbp2_bus;
/* tunables */
extern int scsa1394_symbios_size_max;
extern int scsa1394_symbios_page_size;
extern int scsa1394_wrka_symbios;
/* symbios workaround will be applied unless device is on this list */
};
/*
*
* --- SBP-2 routines
*
*/
int
{
sbp2_tgt_t *tp;
int i;
/*
* target
*/
return (DDI_FAILURE);
}
/*
* luns
*/
KM_SLEEP);
}
return (DDI_SUCCESS);
}
void
{
int i;
}
}
}
static void
{
int vid;
int i;
if (!scsa1394_wrka_symbios) {
return;
} else {
}
/* get device's vendor ID */
IEEE1212_MODULE_VENDOR_ID, 0)) == NULL) {
return;
}
/* find a match in the whitelist */
for (i = 0; i < NELEM(scsa1394_sbp2_symbios_whitelist); i++) {
break;
}
}
}
/*
* functional equivalent of ddi_rep_get32() with big endian access handle
*/
static void
{
int i;
for (i = 0; i < count; i++) {
}
}
/*
* Build an inquiry for a given device that doesn't like inquiry commands.
*/
void
{
int i, len;
/*
*/
for (i = 0; i < 256; i++) {
if ((e = sbp2_cfgrom_ent_by_key(r, IEEE1212_LEAF_TYPE,
IEEE1212_TEXTUAL_DESCRIPTOR, i)) == NULL) {
break;
}
continue;
}
evid = e;
}
}
}
int
{
int i;
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
void
{
int i;
/* if thread wasn't initialized, thr_lun will be NULL */
}
}
}
int
{
}
int
{
int berr;
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
void
{
int berr;
if (scsa1394_sbp2_logged_in(lp)) {
}
}
void
{
}
}
static void
{
int berr = 0;
goto disconnect;
}
goto disconnect;
}
if (!scsa1394_sbp2_logged_in(lp)) {
/* reconnect procedure is only for logged in hosts */
return;
}
/*
* Try SBP-2 RECONNECT procedure first. Note that we're passing
* local Node ID, which might have changed during bus reset.
* sbp2_ses_reconnect() will use it to update the ORBs.
*/
/* resume task processing */
return;
}
if (berr == CMD1394_EDEVICE_REMOVED) {
goto disconnect;
}
/* reconnect failed, try to logout and login again */
goto disconnect;
}
return;
if (scsa1394_sbp2_logged_in(lp)) {
}
}
/*ARGSUSED*/
static void
{
return;
}
goto disconnect;
}
goto disconnect;
}
return;
}
void
{
int berr;
}
/*
* convert segment array into DMA-mapped SBP-2 page table
*/
void
{
} else {
}
}
/*ARGSUSED*/
static void
{
int i;
for (i = 0; i < cmd->sc_buf_nsegs; i++) {
pt++;
seg++;
}
}
/*
* fill page table for Symbios workaround
*/
/*ARGSUSED*/
static void
{
int start_page;
int nsegs;
/* calculate page table address and size */
} else {
offset = 0;
}
nsegs = 0;
while (resid > 0) {
nsegs++;
pt++;
seg++;
}
}
/*
* convert command into DMA-mapped SBP-2 ORB
*/
void
{
/* CDB */
/*
* ORB parameters
*
* use max speed and max payload for this speed.
* max async data transfer for a given speed is 512<<speed
* SBP-2 defines (see 5.1.2) max data transfer as 2^(max_payload+2),
* hence max_payload = 7 + speed
*/
/* direction: initiator's read is target's write (and vice versa) */
}
/*
* data_size and data_descriptor
*/
if (cmd->sc_buf_nsegs == 0) {
/* no data */
orb->co_data_size = 0;
/* contiguous buffer - use direct addressing */
} else {
/* non-contiguous s/g list - page table */
}
}
/*ARGSUSED*/
int
{
int ret;
task->ts_bus_error = 0;
if (ret == SBP2_SUCCESS) {
return (TRAN_ACCEPT);
return (TRAN_BUSY);
} else {
return (TRAN_FATAL_ERROR);
}
} else {
return (TRAN_FATAL_ERROR);
}
}
/*
* This function is called by SBP-2 layer when task status is received,
* typically from interrupt handler. Just wake the thread to do the actual work.
*/
/*ARGSUSED*/
static void
{
}
void
{
}
/*
* worker thread
*/
static void
scsa1394_sbp2_worker_thread(void *arg)
{
for (;;) {
}
break;
}
continue;
}
continue;
}
continue;
}
if (scsa1394_sbp2_logged_in(lp)) {
}
continue;
}
}
}
/*
* task status handler
*/
static void
{
return;
}
/*
* Process all tasks that received status.
* This algorithm preserves callback order.
*/
NULL) {
}
}
static void
{
uint64_t *p;
}
case SBP2_TASK_ERR_ABORT:
break;
case SBP2_TASK_ERR_LUN_RESET:
break;
case SBP2_TASK_ERR_TGT_RESET:
break;
case SBP2_TASK_ERR_TIMEOUT:
return;
case SBP2_TASK_ERR_DEAD:
case SBP2_TASK_ERR_BUS:
default:
break;
}
/*
* SBP-2 status block has been received, now look at sbp_status.
*
* Note: ANSI NCITS 325-1998 B.2 requires that when status is
* GOOD, length must be one, but some devices do not comply
*/
STATUS_GOOD) {
/* request complete */
} else {
}
} else {
/* transport or serial bus failure */
}
/* save the command */
}
/* generic HBA status processing */
}
/*
* Convert SBP-2 status block into SCSA status.
*
* Note: (ref: B.2) "SBP-2 permits the return of a status block between two
* and quadlets in length. When a truncated status block is stored, the
* omitted quadlets shall be interpreted as if zero values were stored."
* We expect the sbp2 layer to do the zeroing for us.
*/
static int
{
arqp->sts_rqpkt_resid = 0;
arqp->sts_rqpkt_statistics = 0;
return (DDI_SUCCESS);
}
/*
* Sends appropriate reset command to the target. LUN reset is optional, so it
* can fail, in which case the SCSA target driver will use RESET_TARGET/ALL.
* Target reset support is mandatory in SBP-2, if it fails, it means something's
* terribly wrong with the device - blow away outstanding tasks in that case.
*/
int
{
int berr;
int ret = DDI_FAILURE;
if (scsa1394_dev_is_online(sp)) {
switch (level) {
case RESET_LUN:
if (ret != SBP2_SUCCESS) {
return (ret);
}
break;
case RESET_TARGET:
case RESET_ALL:
break;
}
}
}
if (scsa1394_sbp2_logged_in(lp)) {
}
}
return (ret);
}
static void
{
int ts_error;
} else {
}
} else {
}
}
/*
* Cancel commands immediately.
*
* Caller's responsibility to set device state such that no new tasks are added.
*/
void
int statistics)
{
return;
}
}
}
static boolean_t
{
}