CAM Transport Layer (XPT).
Submitted by: The CAM Team
This commit is contained in:
parent
bbc0682d67
commit
855593c295
108
sys/cam/cam.c
Normal file
108
sys/cam/cam.c
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Generic utility routines for the Common Access Method layer.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
|
||||
void
|
||||
cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
|
||||
{
|
||||
|
||||
/* Trim leading/trailing spaces. */
|
||||
while (srclen > 0 && src[0] == ' ')
|
||||
src++, srclen--;
|
||||
while (srclen > 0 && src[srclen-1] == ' ')
|
||||
srclen--;
|
||||
|
||||
while (srclen > 0 && dstlen > 1) {
|
||||
u_int8_t *cur_pos = dst;
|
||||
|
||||
if (*src < 0x20 || *src >= 0x80) {
|
||||
/* SCSI-II Specifies that these should never occur. */
|
||||
/* non-printable character */
|
||||
if (dstlen > 4) {
|
||||
*cur_pos++ = '\\';
|
||||
*cur_pos++ = ((*src & 0300) >> 6) + '0';
|
||||
*cur_pos++ = ((*src & 0070) >> 3) + '0';
|
||||
*cur_pos++ = ((*src & 0007) >> 0) + '0';
|
||||
} else {
|
||||
*cur_pos++ = '?';
|
||||
}
|
||||
} else {
|
||||
/* normal character */
|
||||
*cur_pos++ = *src;
|
||||
}
|
||||
src++;
|
||||
srclen--;
|
||||
dstlen -= cur_pos - dst;
|
||||
dst = cur_pos;
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare string with pattern, returning 0 on match.
|
||||
* Short pattern matches trailing blanks in name,
|
||||
* wildcard '*' in pattern matches rest of name,
|
||||
* wildcard '?' matches a single non-space character.
|
||||
*/
|
||||
int
|
||||
cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len)
|
||||
{
|
||||
|
||||
while (*pattern != '\0'&& str_len > 0) {
|
||||
|
||||
if (*pattern == '*') {
|
||||
return (0);
|
||||
}
|
||||
if ((*pattern != *str)
|
||||
&& (*pattern != '?' || *str == ' ')) {
|
||||
return (1);
|
||||
}
|
||||
pattern++;
|
||||
str++;
|
||||
str_len--;
|
||||
}
|
||||
while (str_len > 0 && *str++ == ' ')
|
||||
str_len--;
|
||||
|
||||
return (str_len);
|
||||
}
|
||||
|
||||
caddr_t
|
||||
cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
|
||||
int entry_size, cam_quirkmatch_t *comp_func)
|
||||
{
|
||||
for (; num_entries > 0; num_entries--, quirk_table += entry_size) {
|
||||
if ((*comp_func)(target, quirk_table) == 0)
|
||||
return (quirk_table);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
165
sys/cam/cam.h
Normal file
165
sys/cam/cam.h
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Data structures and definitions for the CAM system.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_H
|
||||
#define _CAM_CAM_H 1
|
||||
|
||||
#ifdef KERNEL
|
||||
#include <opt_cam.h>
|
||||
#endif /* KERNEL */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
typedef u_int path_id_t;
|
||||
typedef u_int target_id_t;
|
||||
typedef u_int lun_id_t;
|
||||
|
||||
#define CAM_XPT_PATH_ID ((path_id_t)~0)
|
||||
#define CAM_BUS_WILDCARD ((path_id_t)~0)
|
||||
#define CAM_TARGET_WILDCARD ((target_id_t)~0)
|
||||
#define CAM_LUN_WILDCARD ((lun_id_t)~0)
|
||||
|
||||
/*
|
||||
* Maximum length for a CAM CDB.
|
||||
*/
|
||||
#define CAM_MAX_CDBLEN 16
|
||||
|
||||
/*
|
||||
* Definition of a CAM peripheral driver entry. Peripheral drivers instantiate
|
||||
* one of these for each device they wish to communicate with and pass it into
|
||||
* the xpt layer when they wish to schedule work on that device via the
|
||||
* xpt_schecule API.
|
||||
*/
|
||||
struct cam_periph;
|
||||
|
||||
/*
|
||||
* Priority information for a CAM structure. The generation number is
|
||||
* incremented everytime a new entry is entered into the queue giving round
|
||||
* robin per priority level scheduling.
|
||||
*/
|
||||
typedef struct {
|
||||
u_int32_t priority;
|
||||
#define CAM_PRIORITY_NONE (u_int32_t)-1
|
||||
u_int32_t generation;
|
||||
int index;
|
||||
#define CAM_UNQUEUED_INDEX -1
|
||||
#define CAM_ACTIVE_INDEX -2
|
||||
#define CAM_DONEQ_INDEX -3
|
||||
} cam_pinfo;
|
||||
|
||||
/* CAM flags */
|
||||
typedef enum {
|
||||
CAM_FLAG_NONE = 0x00,
|
||||
CAM_EXPECT_INQ_CHANGE = 0x01
|
||||
} cam_flags;
|
||||
|
||||
/* CAM Status field values */
|
||||
typedef enum {
|
||||
CAM_REQ_INPROG, /* CCB request is in progress */
|
||||
CAM_REQ_CMP, /* CCB request completed without error */
|
||||
CAM_REQ_ABORTED, /* CCB request aborted by the host */
|
||||
CAM_UA_ABORT, /* Unable to abort CCB request */
|
||||
CAM_REQ_CMP_ERR, /* CCB request completed with an error */
|
||||
CAM_BUSY, /* CAM subsytem is busy */
|
||||
CAM_REQ_INVALID, /* CCB request was invalid */
|
||||
CAM_PATH_INVALID, /* Supplied Path ID is invalid */
|
||||
CAM_DEV_NOT_THERE, /* SCSI Device Not Installed/there */
|
||||
CAM_UA_TERMIO, /* Unable to terminate I/O CCB request */
|
||||
CAM_SEL_TIMEOUT, /* Target Selection Timeout */
|
||||
CAM_CMD_TIMEOUT, /* Command timeout */
|
||||
CAM_SCSI_STATUS_ERROR, /* SCSI error, look at error code in CCB */
|
||||
CAM_MSG_REJECT_REC, /* Message Reject Reveived */
|
||||
CAM_SCSI_BUS_RESET, /* SCSI Bus Reset Sent/Received */
|
||||
CAM_UNCOR_PARITY, /* Uncorrectable parity error occurred */
|
||||
CAM_AUTOSENSE_FAIL = 0x10,/* Autosense: request sense cmd fail */
|
||||
CAM_NO_HBA, /* No HBA Detected error */
|
||||
CAM_DATA_RUN_ERR, /* Data Overrun error */
|
||||
CAM_UNEXP_BUSFREE, /* Unexpected Bus Free */
|
||||
CAM_SEQUENCE_FAIL, /* Target Bus Phase Sequence Failure */
|
||||
CAM_CCB_LEN_ERR, /* CCB length supplied is inadequate */
|
||||
CAM_PROVIDE_FAIL, /* Unable to provide requested capability */
|
||||
CAM_BDR_SENT, /* A SCSI BDR msg was sent to target */
|
||||
CAM_REQ_TERMIO, /* CCB request terminated by the host */
|
||||
CAM_UNREC_HBA_ERROR, /* Unrecoverable Host Bus Adapter Error */
|
||||
CAM_REQ_TOO_BIG, /* The request was too large for this host */
|
||||
CAM_REQUEUE_REQ, /*
|
||||
* This request should be requeued to preserve
|
||||
* transaction ordering. This typically occurs
|
||||
* when the SIM recognizes an error that should
|
||||
* freeze the queue and must place additional
|
||||
* requests for the target at the sim level
|
||||
* back into the XPT queue.
|
||||
*/
|
||||
CAM_IDE = 0x33, /* Initiator Detected Error */
|
||||
CAM_RESRC_UNAVAIL, /* Resource Unavailable */
|
||||
CAM_UNACKED_EVENT, /* Unacknowledged Event by Host */
|
||||
CAM_MESSAGE_RECV, /* Message Received in Host Target Mode */
|
||||
CAM_INVALID_CDB, /* Invalid CDB received in Host Target Mode */
|
||||
CAM_LUN_INVALID, /* Lun supplied is invalid */
|
||||
CAM_TID_INVALID, /* Target ID supplied is invalid */
|
||||
CAM_FUNC_NOTAVAIL, /* The requested function is not available */
|
||||
CAM_NO_NEXUS, /* Nexus is not established */
|
||||
CAM_IID_INVALID, /* The initiator ID is invalid */
|
||||
CAM_CDB_RECVD, /* The SCSI CDB has been received */
|
||||
CAM_LUN_ALRDY_ENA, /* The LUN is already eanbeld for target mode */
|
||||
CAM_SCSI_BUSY, /* SCSI Bus Busy */
|
||||
|
||||
CAM_DEV_QFRZN = 0x40, /* The DEV queue is frozen w/this err */
|
||||
|
||||
/* Autosense data valid for target */
|
||||
CAM_AUTOSNS_VALID = 0x80,
|
||||
CAM_RELEASE_SIMQ = 0x100,/* SIM ready to take more commands */
|
||||
CAM_SIM_QUEUED = 0x200,/* SIM has this command in it's queue */
|
||||
|
||||
CAM_STATUS_MASK = 0x3F, /* Mask bits for just the status # */
|
||||
} cam_status;
|
||||
|
||||
__BEGIN_DECLS
|
||||
typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
|
||||
|
||||
caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
|
||||
int entry_size, cam_quirkmatch_t *comp_func);
|
||||
|
||||
void cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
|
||||
|
||||
int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len);
|
||||
__END_DECLS
|
||||
|
||||
#ifdef KERNEL
|
||||
static __inline void cam_init_pinfo(cam_pinfo *pinfo);
|
||||
|
||||
static __inline void cam_init_pinfo(cam_pinfo *pinfo)
|
||||
{
|
||||
pinfo->priority = CAM_PRIORITY_NONE;
|
||||
pinfo->index = CAM_UNQUEUED_INDEX;
|
||||
}
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* _CAM_CAM_H */
|
779
sys/cam/cam_ccb.h
Normal file
779
sys/cam/cam_ccb.h
Normal file
@ -0,0 +1,779 @@
|
||||
/*
|
||||
* Data structures and definitions for CAM Control Blocks (CCBs).
|
||||
*
|
||||
* Copyright (c) 1997, 1998 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_CCB_H
|
||||
#define _CAM_CAM_CCB_H 1
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef KERNEL
|
||||
#include <sys/callout.h>
|
||||
#endif
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
|
||||
/* General allocation length definitions for CCB structures */
|
||||
#define IOCDBLEN CAM_MAX_CDBLEN /* Space for CDB bytes/pointer */
|
||||
#define VUHBALEN 14 /* Vendor Unique HBA length */
|
||||
#define SIM_IDLEN 16 /* ASCII string len for SIM ID */
|
||||
#define HBA_IDLEN 16 /* ASCII string len for HBA ID */
|
||||
#define DEV_IDLEN 16 /* ASCII string len for device names */
|
||||
#define CCB_PERIPH_PRIV_SIZE 2 /* size of peripheral private area */
|
||||
#define CCB_SIM_PRIV_SIZE 2 /* size of sim private area */
|
||||
|
||||
/* Struct definitions for CAM control blocks */
|
||||
|
||||
/* Common CCB header */
|
||||
/* CAM CCB flags */
|
||||
typedef enum {
|
||||
CAM_CDB_POINTER = 0x00000001,/* The CDB field is a pointer */
|
||||
CAM_QUEUE_ENABLE = 0x00000002,/* SIM queue actions are enabled */
|
||||
CAM_CDB_LINKED = 0x00000004,/* CCB contains a linked CDB */
|
||||
CAM_SCATTER_VALID = 0x00000010,/* Scatter/gather list is valid */
|
||||
CAM_DIS_AUTOSENSE = 0x00000020,/* Disable autosense feature */
|
||||
CAM_DIR_RESV = 0x00000000,/* Data direction (00:reserved) */
|
||||
CAM_DIR_IN = 0x00000040,/* Data direction (01:DATA IN) */
|
||||
CAM_DIR_OUT = 0x00000080,/* Data direction (10:DATA OUT) */
|
||||
CAM_DIR_NONE = 0x000000C0,/* Data direction (11:no data) */
|
||||
CAM_DIR_MASK = 0x000000C0,/* Data direction Mask */
|
||||
CAM_SOFT_RST_OP = 0x00000100,/* Use Soft reset alternative */
|
||||
CAM_ENG_SYNC = 0x00000200,/* Flush resid bytes on complete */
|
||||
CAM_DEV_QFRZDIS = 0x00000400,/* Disable DEV Q freezing */
|
||||
CAM_DEV_QFREEZE = 0x00000800,/* Freeze DEV Q on execution */
|
||||
CAM_HIGH_POWER = 0x00001000,/* Command takes a lot of power */
|
||||
CAM_SENSE_PTR = 0x00002000,/* Sense data is a pointer */
|
||||
CAM_SENSE_PHYS = 0x00004000,/* Sense pointer is physical addr*/
|
||||
CAM_TAG_ACTION_VALID = 0x00008000,/* Use the tag action in this ccb*/
|
||||
CAM_PASS_ERR_RECOVER = 0x00010000,/* Pass driver does err. recovery*/
|
||||
CAM_DIS_DISCONNECT = 0x00020000,/* Disable disconnect */
|
||||
CAM_SG_LIST_PHYS = 0x00040000,/* SG list has physical addrs. */
|
||||
CAM_MSG_BUF_PHYS = 0x00080000,/* Message buffer ptr is physical*/
|
||||
CAM_SNS_BUF_PHYS = 0x00100000,/* Autosense data ptr is physical*/
|
||||
CAM_DATA_PHYS = 0x00200000,/* SG/Buffer data ptrs are phys. */
|
||||
CAM_CDB_PHYS = 0x00400000,/* CDB poiner is physical */
|
||||
CAM_ENG_SGLIST = 0x00800000,/* SG list is for the HBA engine */
|
||||
|
||||
/* Phase cognizant mode flags */
|
||||
CAM_DIS_AUTOSRP = 0x01000000,/* Diable autosave/restore ptrs */
|
||||
CAM_DIS_AUTODISC = 0x02000000,/* Disable auto disconnect */
|
||||
CAM_TGT_CCB_AVAIL = 0x04000000,/* Target CCB available */
|
||||
CAM_TGT_PHASE_MODE = 0x08000000,/* The SIM runs in phase mode */
|
||||
CAM_MSGB_VALID = 0x20000000,/* Message buffer valid */
|
||||
CAM_STATUS_VALID = 0x40000000,/* Status buffer valid */
|
||||
CAM_DATAB_VALID = 0x80000000,/* Data buffer valid */
|
||||
|
||||
/* Host target Mode flags */
|
||||
CAM_TERM_IO = 0x20000000,/* Terminate I/O Message sup. */
|
||||
CAM_DISCONNECT = 0x40000000,/* Disconnects are mandatory */
|
||||
CAM_SEND_STATUS = 0x80000000,/* Send status after data phase */
|
||||
} ccb_flags;
|
||||
|
||||
/* XPT Opcodes for xpt_action */
|
||||
typedef enum {
|
||||
/* Common function commands: 0x00->0x0F */
|
||||
XPT_NOOP, /* Execute Nothing */
|
||||
XPT_SCSI_IO, /* Execute the requested I/O operation */
|
||||
XPT_GDEV_TYPE, /* Get type information for specified device */
|
||||
XPT_GDEVLIST, /* Get a list of peripheral devices */
|
||||
XPT_PATH_INQ, /* Path routing inquiry */
|
||||
XPT_REL_SIMQ, /* Release a frozen SIM queue */
|
||||
XPT_SASYNC_CB, /* Set Asynchronous Callback Parameters */
|
||||
XPT_SDEV_TYPE, /* Set device type information */
|
||||
XPT_SCAN_BUS, /* (Re)Scan the SCSI Bus */
|
||||
XPT_DEV_MATCH, /* Get EDT entries matching the given pattern */
|
||||
XPT_DEBUG, /* Turn on debugging for a bus, target or lun */
|
||||
/* SCSI Control Functions: 0x10->0x1F */
|
||||
XPT_ABORT = 0x10, /* Abort the specified CCB */
|
||||
XPT_RESET_BUS, /* Reset the specified SCSI bus */
|
||||
XPT_RESET_DEV, /* Bus Device Reset the specified SCSI device */
|
||||
XPT_TERM_IO, /* Terminate the I/O process */
|
||||
XPT_SCAN_LUN, /* Scan Logical Unit */
|
||||
XPT_GET_TRAN_SETTINGS, /*
|
||||
* Get default/user transfer settings
|
||||
* for the target
|
||||
*/
|
||||
XPT_SET_TRAN_SETTINGS, /*
|
||||
* Set transfer rate/width
|
||||
* negotiation settings
|
||||
*/
|
||||
XPT_CALC_GEOMETRY, /*
|
||||
* Calculate the geometry parameters for
|
||||
* a device give the sector size and
|
||||
* volume size.
|
||||
*/
|
||||
|
||||
/* HBA engine commands 0x20->0x2F */
|
||||
XPT_ENG_INQ = 0x20, /* HBA engine feature inquiry */
|
||||
XPT_ENG_EXEC, /* HBA execute engine request */
|
||||
|
||||
/* Target mode commands: 0x30->0x3F */
|
||||
XPT_EN_LUN = 0x30, /* Enable LUN as a target */
|
||||
XPT_TARGET_IO, /* Execute target I/O request */
|
||||
XPT_ACCEPT_TARGET_IO, /* Accept Host Target Mode CDB */
|
||||
XPT_CONT_TARGET_IO, /* Continue Host Target I/O Connection */
|
||||
XPT_IMMED_NOTIFY, /* Notify Host Target driver of event */
|
||||
XPT_NOTIFY_ACK, /* Acknowledgement of event */
|
||||
|
||||
/* Vendor Unique codes: 0x80->0x8F */
|
||||
XPT_VUNIQUE = 0x80
|
||||
} xpt_opcode;
|
||||
|
||||
typedef union {
|
||||
LIST_ENTRY(ccb_hdr) le;
|
||||
SLIST_ENTRY(ccb_hdr) sle;
|
||||
TAILQ_ENTRY(ccb_hdr) tqe;
|
||||
STAILQ_ENTRY(ccb_hdr) stqe;
|
||||
} camq_entry;
|
||||
|
||||
typedef union {
|
||||
void *ptr;
|
||||
u_long field;
|
||||
u_int8_t bytes[sizeof(void *) > sizeof(u_long)
|
||||
? sizeof(void *) : sizeof(u_long)];
|
||||
} ccb_priv_entry;
|
||||
|
||||
typedef union {
|
||||
ccb_priv_entry entries[CCB_PERIPH_PRIV_SIZE];
|
||||
u_int8_t bytes[CCB_PERIPH_PRIV_SIZE * sizeof(ccb_priv_entry)];
|
||||
} ccb_ppriv_area;
|
||||
|
||||
typedef union {
|
||||
ccb_priv_entry entries[CCB_SIM_PRIV_SIZE];
|
||||
u_int8_t bytes[CCB_SIM_PRIV_SIZE * sizeof(ccb_priv_entry)];
|
||||
} ccb_spriv_area;
|
||||
|
||||
struct ccb_hdr {
|
||||
cam_pinfo pinfo; /* Info for priority scheduling */
|
||||
camq_entry xpt_links; /* For chaining in the XPT layer */
|
||||
camq_entry sim_links; /* For chaining in the SIM layer */
|
||||
camq_entry periph_links;/* For chaining in the type driver */
|
||||
u_int32_t retry_count;
|
||||
/* Callback on completion function */
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *);
|
||||
xpt_opcode func_code; /* XPT function code */
|
||||
u_int32_t status; /* Status returned by CAM subsystem */
|
||||
/* Compiled path for this ccb */
|
||||
struct cam_path *path;
|
||||
path_id_t path_id; /* Path ID for the request */
|
||||
target_id_t target_id; /* Target device ID */
|
||||
lun_id_t target_lun; /* Target LUN number */
|
||||
u_int32_t flags;
|
||||
ccb_ppriv_area periph_priv;
|
||||
ccb_spriv_area sim_priv;
|
||||
u_int32_t timeout; /* Timeout value */
|
||||
/* Callout handle used for timeouts */
|
||||
struct callout_handle timeout_ch;
|
||||
};
|
||||
|
||||
/* Get Device Information CCB */
|
||||
struct ccb_getdev {
|
||||
struct ccb_hdr ccb_h;
|
||||
struct scsi_inquiry_data inq_data;
|
||||
u_int8_t serial_num[252];
|
||||
u_int8_t serial_num_len;
|
||||
u_int8_t pd_type; /* returned peripheral device type */
|
||||
int dev_openings; /* Space left for more work on device*/
|
||||
int dev_active; /* Transactions running on the device */
|
||||
int devq_openings;/* Space left for more queued work */
|
||||
int devq_queued; /* Transactions queued to be sent */
|
||||
int held; /*
|
||||
* CCBs held by peripheral drivers
|
||||
* for this device
|
||||
*/
|
||||
u_int8_t maxtags; /*
|
||||
* Boundary conditions for number of
|
||||
* tagged operations
|
||||
*/
|
||||
u_int8_t mintags;
|
||||
};
|
||||
|
||||
|
||||
typedef enum {
|
||||
CAM_GDEVLIST_LAST_DEVICE,
|
||||
CAM_GDEVLIST_LIST_CHANGED,
|
||||
CAM_GDEVLIST_MORE_DEVS,
|
||||
CAM_GDEVLIST_ERROR
|
||||
} ccb_getdevlist_status_e;
|
||||
|
||||
struct ccb_getdevlist {
|
||||
struct ccb_hdr ccb_h;
|
||||
char periph_name[DEV_IDLEN];
|
||||
u_int32_t unit_number;
|
||||
unsigned int generation;
|
||||
u_int32_t index;
|
||||
ccb_getdevlist_status_e status;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
PERIPH_MATCH_NONE = 0x000,
|
||||
PERIPH_MATCH_PATH = 0x001,
|
||||
PERIPH_MATCH_TARGET = 0x002,
|
||||
PERIPH_MATCH_LUN = 0x004,
|
||||
PERIPH_MATCH_NAME = 0x008,
|
||||
PERIPH_MATCH_UNIT = 0x010,
|
||||
PERIPH_MATCH_ANY = 0x01f
|
||||
} periph_pattern_flags;
|
||||
|
||||
struct periph_match_pattern {
|
||||
char periph_name[DEV_IDLEN];
|
||||
u_int32_t unit_number;
|
||||
path_id_t path_id;
|
||||
target_id_t target_id;
|
||||
lun_id_t target_lun;
|
||||
periph_pattern_flags flags;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DEV_MATCH_NONE = 0x000,
|
||||
DEV_MATCH_PATH = 0x001,
|
||||
DEV_MATCH_TARGET = 0x002,
|
||||
DEV_MATCH_LUN = 0x004,
|
||||
DEV_MATCH_INQUIRY = 0x008,
|
||||
DEV_MATCH_ANY = 0x00f
|
||||
} dev_pattern_flags;
|
||||
|
||||
struct device_match_pattern {
|
||||
path_id_t path_id;
|
||||
target_id_t target_id;
|
||||
lun_id_t target_lun;
|
||||
struct scsi_static_inquiry_pattern inq_pat;
|
||||
dev_pattern_flags flags;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
BUS_MATCH_NONE = 0x000,
|
||||
BUS_MATCH_PATH = 0x001,
|
||||
BUS_MATCH_NAME = 0x002,
|
||||
BUS_MATCH_UNIT = 0x004,
|
||||
BUS_MATCH_BUS_ID = 0x008,
|
||||
BUS_MATCH_ANY = 0x00f
|
||||
} bus_pattern_flags;
|
||||
|
||||
struct bus_match_pattern {
|
||||
path_id_t path_id;
|
||||
char dev_name[DEV_IDLEN];
|
||||
u_int32_t unit_number;
|
||||
u_int32_t bus_id;
|
||||
bus_pattern_flags flags;
|
||||
};
|
||||
|
||||
union match_pattern {
|
||||
struct periph_match_pattern periph_pattern;
|
||||
struct device_match_pattern device_pattern;
|
||||
struct bus_match_pattern bus_pattern;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DEV_MATCH_PERIPH,
|
||||
DEV_MATCH_DEVICE,
|
||||
DEV_MATCH_BUS
|
||||
} dev_match_type;
|
||||
|
||||
struct dev_match_pattern {
|
||||
dev_match_type type;
|
||||
union match_pattern pattern;
|
||||
};
|
||||
|
||||
struct periph_match_result {
|
||||
char periph_name[DEV_IDLEN];
|
||||
u_int32_t unit_number;
|
||||
path_id_t path_id;
|
||||
target_id_t target_id;
|
||||
lun_id_t target_lun;
|
||||
};
|
||||
|
||||
struct device_match_result {
|
||||
path_id_t path_id;
|
||||
target_id_t target_id;
|
||||
lun_id_t target_lun;
|
||||
struct scsi_inquiry_data inq_data;
|
||||
};
|
||||
|
||||
struct bus_match_result {
|
||||
path_id_t path_id;
|
||||
char dev_name[DEV_IDLEN];
|
||||
u_int32_t unit_number;
|
||||
u_int32_t bus_id;
|
||||
};
|
||||
|
||||
union match_result {
|
||||
struct periph_match_result periph_result;
|
||||
struct device_match_result device_result;
|
||||
struct bus_match_result bus_result;
|
||||
};
|
||||
|
||||
struct dev_match_result {
|
||||
dev_match_type type;
|
||||
union match_result result;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CAM_DEV_MATCH_LAST,
|
||||
CAM_DEV_MATCH_MORE,
|
||||
CAM_DEV_MATCH_LIST_CHANGED,
|
||||
CAM_DEV_MATCH_SIZE_ERROR,
|
||||
CAM_DEV_MATCH_ERROR
|
||||
} ccb_dev_match_status;
|
||||
|
||||
typedef enum {
|
||||
CAM_DEV_POS_NONE = 0x000,
|
||||
CAM_DEV_POS_BUS = 0x001,
|
||||
CAM_DEV_POS_TARGET = 0x002,
|
||||
CAM_DEV_POS_DEVICE = 0x004,
|
||||
CAM_DEV_POS_PERIPH = 0x008,
|
||||
CAM_DEV_POS_PDPTR = 0x010,
|
||||
CAM_DEV_POS_TYPEMASK = 0xf00,
|
||||
CAM_DEV_POS_EDT = 0x100,
|
||||
CAM_DEV_POS_PDRV = 0x200
|
||||
} dev_pos_type;
|
||||
|
||||
struct ccb_dm_cookie {
|
||||
void *bus;
|
||||
void *target;
|
||||
void *device;
|
||||
void *periph;
|
||||
void *pdrv;
|
||||
};
|
||||
|
||||
struct ccb_dev_position {
|
||||
u_int generations[4];
|
||||
#define CAM_BUS_GENERATION 0x00
|
||||
#define CAM_TARGET_GENERATION 0x01
|
||||
#define CAM_DEV_GENERATION 0x02
|
||||
#define CAM_PERIPH_GENERATION 0x03
|
||||
dev_pos_type position_type;
|
||||
struct ccb_dm_cookie cookie;
|
||||
};
|
||||
|
||||
struct ccb_dev_match {
|
||||
struct ccb_hdr ccb_h;
|
||||
ccb_dev_match_status status;
|
||||
u_int32_t num_patterns;
|
||||
u_int32_t pattern_buf_len;
|
||||
struct dev_match_pattern *patterns;
|
||||
u_int32_t num_matches;
|
||||
u_int32_t match_buf_len;
|
||||
struct dev_match_result *matches;
|
||||
struct ccb_dev_position pos;
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions for the path inquiry CCB fields.
|
||||
*/
|
||||
#define CAM_VERSION 0x10 /* Hex value for current version */
|
||||
|
||||
typedef enum {
|
||||
PI_MDP_ABLE = 0x80, /* Supports MDP message */
|
||||
PI_WIDE_32 = 0x40, /* Supports 32 bit wide SCSI */
|
||||
PI_WIDE_16 = 0x20, /* Supports 16 bit wide SCSI */
|
||||
PI_SDTR_ABLE = 0x10, /* Supports SDTR message */
|
||||
PI_LINKED_CDB = 0x08, /* Supports linked CDBs */
|
||||
PI_TAG_ABLE = 0x02, /* Supports tag queue messages */
|
||||
PI_SOFT_RST = 0x01, /* Supports soft reset alternative */
|
||||
} pi_inqflag;
|
||||
|
||||
typedef enum {
|
||||
PIT_PROCESSOR = 0x80, /* Target mode processor mode */
|
||||
PIT_PHASE = 0x40, /* Target mode phase cog. mode */
|
||||
PIT_DISCONNECT = 0x20, /* Disconnects supported in target mode */
|
||||
PIT_TERM_IO = 0x10, /* Terminate I/O message supported in TM */
|
||||
PIT_GRP_6 = 0x08, /* Group 6 commands supported */
|
||||
PIT_GRP_7 = 0x04, /* Group 7 commands supported */
|
||||
} pi_tmflag;
|
||||
|
||||
typedef enum {
|
||||
PIM_SCANHILO = 0x80, /* Bus scans from high ID to low ID */
|
||||
PIM_NOREMOVE = 0x40, /* Removeable devices not included in scan */
|
||||
PIM_NOINQUIRY = 0x20, /* Inquiry data not kept by XPT */
|
||||
} pi_miscflag;
|
||||
|
||||
/* Path Inquiry CCB */
|
||||
struct ccb_pathinq {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int8_t version_num; /* Version number for the SIM/HBA */
|
||||
u_int8_t hba_inquiry; /* Mimic of INQ byte 7 for the HBA */
|
||||
u_int8_t target_sprt; /* Flags for target mode support */
|
||||
u_int8_t hba_misc; /* Misc HBA features */
|
||||
u_int16_t hba_eng_cnt; /* HBA engine count */
|
||||
/* Vendor Unique capabilities */
|
||||
u_int8_t vuhba_flags[VUHBALEN];
|
||||
u_int32_t max_target; /* Maximum supported Target */
|
||||
u_int32_t max_lun; /* Maximum supported Lun */
|
||||
u_int32_t async_flags; /* Installed Async handlers */
|
||||
path_id_t hpath_id; /* Highest Path ID in the subsystem */
|
||||
target_id_t initiator_id; /* ID of the HBA on the SCSI bus */
|
||||
char sim_vid[SIM_IDLEN]; /* Vendor ID of the SIM */
|
||||
char hba_vid[HBA_IDLEN]; /* Vendor ID of the HBA */
|
||||
char dev_name[DEV_IDLEN];/* Device name for SIM */
|
||||
u_int32_t unit_number; /* Unit number for SIM */
|
||||
u_int32_t bus_id; /* Bus ID for SIM */
|
||||
};
|
||||
|
||||
typedef union {
|
||||
u_int8_t *sense_ptr; /*
|
||||
* Pointer to storage
|
||||
* for sense information
|
||||
*/
|
||||
/* Storage Area for sense information */
|
||||
struct scsi_sense_data sense_buf;
|
||||
} sense_t;
|
||||
|
||||
typedef union {
|
||||
u_int8_t *cdb_ptr; /* Pointer to the CDB bytes to send */
|
||||
/* Area for the CDB send */
|
||||
u_int8_t cdb_bytes[IOCDBLEN];
|
||||
} cdb_t;
|
||||
|
||||
/*
|
||||
* SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO
|
||||
* function codes.
|
||||
*/
|
||||
struct ccb_scsiio {
|
||||
struct ccb_hdr ccb_h;
|
||||
union ccb *next_ccb; /* Ptr for next CCB for action */
|
||||
u_int8_t *req_map; /* Ptr to mapping info */
|
||||
u_int8_t *data_ptr; /* Ptr to the data buf/SG list */
|
||||
u_int32_t dxfer_len; /* Data transfer length */
|
||||
/* Autosense storage */
|
||||
struct scsi_sense_data sense_data;
|
||||
u_int8_t sense_len; /* Number of bytes to autosense */
|
||||
u_int8_t cdb_len; /* Number of bytes for the CDB */
|
||||
u_int16_t sglist_cnt; /* Number of SG list entries */
|
||||
u_int8_t scsi_status; /* Returned SCSI status */
|
||||
u_int8_t sense_resid; /* Autosense resid length: 2's comp */
|
||||
u_int32_t resid; /* Transfer residual length: 2's comp */
|
||||
cdb_t cdb_io; /* Union for CDB bytes/pointer */
|
||||
u_int8_t *msg_ptr; /* Pointer to the message buffer */
|
||||
u_int16_t msg_len; /* Number of bytes for the Message */
|
||||
u_int8_t tag_action; /* What to do for tag queueing */
|
||||
u_int8_t tag_id; /* tag id from initator (target mode) */
|
||||
u_int8_t init_id; /* initiator id of who selected */
|
||||
};
|
||||
|
||||
struct ccb_accept_tio {
|
||||
struct ccb_hdr ccb_h;
|
||||
cdb_t cdb_io; /* Union for CDB bytes/pointer */
|
||||
u_int8_t cdb_len; /* Number of bytes for the CDB */
|
||||
u_int8_t tag_action; /* What to do for tag queueing */
|
||||
u_int8_t tag_id; /* tag id from initator (target mode) */
|
||||
u_int8_t init_id; /* initiator id of who selected */
|
||||
};
|
||||
|
||||
/* Release SIM Queue */
|
||||
struct ccb_relsim {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int32_t release_flags;
|
||||
#define RELSIM_ADJUST_OPENINGS 0x01
|
||||
#define RELSIM_RELEASE_AFTER_TIMEOUT 0x02
|
||||
#define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04
|
||||
#define RELSIM_RELEASE_AFTER_QEMPTY 0x08
|
||||
u_int32_t openings;
|
||||
u_int32_t release_timeout;
|
||||
u_int32_t qfrozen_cnt;
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions for the asynchronous callback CCB fields.
|
||||
*/
|
||||
typedef enum {
|
||||
AC_GETDEV_CHANGED = 0x800,/* Getdev info might have changed */
|
||||
AC_INQ_CHANGED = 0x400,/* Inquiry info might have changed */
|
||||
AC_TRANSFER_NEG = 0x200,/* New transfer settings in effect */
|
||||
AC_LOST_DEVICE = 0x100,/* A device went away */
|
||||
AC_FOUND_DEVICE = 0x080,/* A new device was found */
|
||||
AC_PATH_DEREGISTERED = 0x040,/* A path has de-registered */
|
||||
AC_PATH_REGISTERED = 0x020,/* A new path has been registered */
|
||||
AC_SENT_BDR = 0x010,/* A BDR message was sent to target */
|
||||
AC_SCSI_AEN = 0x008,/* A SCSI AEN has been received */
|
||||
AC_UNSOL_RESEL = 0x002,/* Unsolicited reselection occurred */
|
||||
AC_BUS_RESET = 0x001 /* A SCSI bus reset occurred */
|
||||
} ac_code;
|
||||
|
||||
typedef void ac_callback_t (void *softc, u_int32_t code,
|
||||
struct cam_path *path, void *args);
|
||||
|
||||
/* Set Asynchronous Callback CCB */
|
||||
struct ccb_setasync {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int32_t event_enable; /* Async Event enables */
|
||||
ac_callback_t *callback;
|
||||
void *callback_arg;
|
||||
};
|
||||
|
||||
/* Set Device Type CCB */
|
||||
struct ccb_setdev {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int8_t dev_type; /* Value for dev type field in EDT */
|
||||
};
|
||||
|
||||
/* SCSI Control Functions */
|
||||
|
||||
/* Abort XPT request CCB */
|
||||
struct ccb_abort {
|
||||
struct ccb_hdr ccb_h;
|
||||
union ccb *abort_ccb; /* Pointer to CCB to abort */
|
||||
};
|
||||
|
||||
/* Reset SCSI Bus CCB */
|
||||
struct ccb_resetbus {
|
||||
struct ccb_hdr ccb_h;
|
||||
};
|
||||
|
||||
/* Reset SCSI Device CCB */
|
||||
struct ccb_resetdev {
|
||||
struct ccb_hdr ccb_h;
|
||||
};
|
||||
|
||||
/* Terminate I/O Process Request CCB */
|
||||
struct ccb_termio {
|
||||
struct ccb_hdr ccb_h;
|
||||
union ccb *termio_ccb; /* Pointer to CCB to terminate */
|
||||
};
|
||||
|
||||
/* Get/Set transfer rate/width/disconnection/tag queueing settings */
|
||||
struct ccb_trans_settings {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int valid; /* Which fields to honor */
|
||||
#define CCB_TRANS_SYNC_RATE_VALID 0x01
|
||||
#define CCB_TRANS_SYNC_OFFSET_VALID 0x02
|
||||
#define CCB_TRANS_BUS_WIDTH_VALID 0x04
|
||||
#define CCB_TRANS_DISC_VALID 0x08
|
||||
#define CCB_TRANS_TQ_VALID 0x10
|
||||
u_int flags;
|
||||
#define CCB_TRANS_CURRENT_SETTINGS 0x01
|
||||
#define CCB_TRANS_USER_SETTINGS 0x02
|
||||
#define CCB_TRANS_DISC_ENB 0x04
|
||||
#define CCB_TRANS_TAG_ENB 0x08
|
||||
u_int sync_period;
|
||||
u_int sync_offset;
|
||||
u_int bus_width;
|
||||
};
|
||||
|
||||
/*
|
||||
* Calculate the geometry parameters for a device
|
||||
* give the block size and volume size in blocks.
|
||||
*/
|
||||
struct ccb_calc_geometry {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int32_t block_size;
|
||||
u_int32_t volume_size;
|
||||
u_int16_t cylinders;
|
||||
u_int8_t heads;
|
||||
u_int8_t secs_per_track;
|
||||
};
|
||||
|
||||
/*
|
||||
* Rescan the given bus, or bus/target/lun
|
||||
*/
|
||||
struct ccb_rescan {
|
||||
struct ccb_hdr ccb_h;
|
||||
cam_flags flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* Turn on debugging for the given bus, bus/target, or bus/target/lun.
|
||||
*/
|
||||
struct ccb_debug {
|
||||
struct ccb_hdr ccb_h;
|
||||
cam_debug_flags flags;
|
||||
};
|
||||
|
||||
/* Target mode structures. */
|
||||
|
||||
struct ccb_en_lun {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int16_t grp6_len; /* Group 6 VU CDB length */
|
||||
u_int16_t grp7_len; /* Group 7 VU CDB length */
|
||||
u_int8_t enable;
|
||||
};
|
||||
|
||||
struct ccb_immed_notify {
|
||||
struct ccb_hdr ccb_h;
|
||||
struct scsi_sense_data sense_data;
|
||||
u_int8_t sense_len; /* Number of bytes in sese buffer */
|
||||
u_int8_t initiator_id; /* Id of initiator that selected */
|
||||
u_int16_t seq_id; /* Sequence Identifier */
|
||||
u_int8_t message_code; /* Message Code */
|
||||
u_int8_t message_args[7]; /* Message Arguments */
|
||||
};
|
||||
|
||||
struct ccb_notify_ack {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int16_t seq_id; /* Sequence identifier */
|
||||
u_int8_t event; /* Event flags */
|
||||
};
|
||||
|
||||
/* HBA engine structures. */
|
||||
|
||||
typedef enum {
|
||||
EIT_BUFFER, /* Engine type: buffer memory */
|
||||
EIT_LOSSLESS, /* Engine type: lossless compression */
|
||||
EIT_LOSSY, /* Engine type: lossy compression */
|
||||
EIT_ENCRYPT /* Engine type: encryption */
|
||||
} ei_type;
|
||||
|
||||
typedef enum {
|
||||
EAD_VUNIQUE, /* Engine algorithm ID: vendor unique */
|
||||
EAD_LZ1V1, /* Engine algorithm ID: LZ1 var.1 */
|
||||
EAD_LZ2V1, /* Engine algorithm ID: LZ2 var.1 */
|
||||
EAD_LZ2V2, /* Engine algorithm ID: LZ2 var.2 */
|
||||
} ei_algo;
|
||||
|
||||
struct ccb_eng_inq {
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int16_t eng_num; /* The engine number for this inquiry */
|
||||
ei_type eng_type; /* Returned engine type */
|
||||
ei_algo eng_algo; /* Returned engine algorithm type */
|
||||
u_int32_t eng_memeory; /* Returned engine memory size */
|
||||
};
|
||||
|
||||
struct ccb_eng_exec { /* This structure must match SCSIIO size */
|
||||
struct ccb_hdr ccb_h;
|
||||
u_int8_t *pdrv_ptr; /* Ptr used by the peripheral driver */
|
||||
u_int8_t *req_map; /* Ptr for mapping info on the req. */
|
||||
u_int8_t *data_ptr; /* Pointer to the data buf/SG list */
|
||||
u_int32_t dxfer_len; /* Data transfer length */
|
||||
u_int8_t *engdata_ptr; /* Pointer to the engine buffer data */
|
||||
u_int16_t sglist_cnt; /* Num of scatter gather list entries */
|
||||
u_int32_t dmax_len; /* Destination data maximum length */
|
||||
u_int32_t dest_len; /* Destination data length */
|
||||
int32_t src_resid; /* Source residual length: 2's comp */
|
||||
u_int32_t timeout; /* Timeout value */
|
||||
u_int16_t eng_num; /* Engine number for this request */
|
||||
u_int16_t vu_flags; /* Vendor Unique flags */
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions for the timeout field in the SCSI I/O CCB.
|
||||
*/
|
||||
#define CAM_TIME_DEFAULT 0x00000000 /* Use SIM default value */
|
||||
#define CAM_TIME_INFINITY 0xFFFFFFFF /* Infinite timeout */
|
||||
|
||||
#define CAM_SUCCESS 0 /* For signaling general success */
|
||||
#define CAM_FAILURE 1 /* For signaling general failure */
|
||||
|
||||
#define CAM_FALSE 0
|
||||
#define CAM_TRUE 1
|
||||
|
||||
#define XPT_CCB_INVALID -1 /* for signaling a bad CCB to free */
|
||||
|
||||
/*
|
||||
* Union of all CCB types for kernel space allocation. This union should
|
||||
* never be used for manipulating CCBs - its only use is for the allocation
|
||||
* and deallocation of raw CCB space and is the return type of xpt_ccb_alloc
|
||||
* and the argument to xpt_ccb_free.
|
||||
*/
|
||||
union ccb {
|
||||
struct ccb_hdr ccb_h; /* For convenience */
|
||||
struct ccb_scsiio csio;
|
||||
struct ccb_getdev cgd;
|
||||
struct ccb_getdevlist cgdl;
|
||||
struct ccb_pathinq cpi;
|
||||
struct ccb_relsim crs;
|
||||
struct ccb_setasync csa;
|
||||
struct ccb_setdev csd;
|
||||
struct ccb_dev_match cdm;
|
||||
struct ccb_trans_settings cts;
|
||||
struct ccb_calc_geometry ccg;
|
||||
struct ccb_abort cab;
|
||||
struct ccb_resetbus crb;
|
||||
struct ccb_resetdev crd;
|
||||
struct ccb_termio tio;
|
||||
struct ccb_accept_tio atio;
|
||||
struct ccb_scsiio ctio;
|
||||
struct ccb_en_lun cel;
|
||||
struct ccb_immed_notify cin;
|
||||
struct ccb_notify_ack cna;
|
||||
struct ccb_eng_inq cei;
|
||||
struct ccb_eng_exec cee;
|
||||
struct ccb_rescan crcn;
|
||||
struct ccb_debug cdbg;
|
||||
};
|
||||
|
||||
__BEGIN_DECLS
|
||||
static __inline void
|
||||
cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int32_t flags, u_int8_t tag_action,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len,
|
||||
u_int8_t sense_len, u_int8_t cdb_len,
|
||||
u_int32_t timeout);
|
||||
|
||||
static __inline void
|
||||
cam_fill_ctio(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int32_t flags, u_int tag_action, u_int tag_id,
|
||||
u_int init_id, u_int scsi_status, u_int8_t *data_ptr,
|
||||
u_int32_t dxfer_len, u_int32_t timeout);
|
||||
|
||||
static __inline void
|
||||
cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int32_t flags, u_int8_t tag_action,
|
||||
u_int8_t *data_ptr, u_int32_t dxfer_len,
|
||||
u_int8_t sense_len, u_int8_t cdb_len,
|
||||
u_int32_t timeout)
|
||||
{
|
||||
csio->ccb_h.func_code = XPT_SCSI_IO;
|
||||
csio->ccb_h.flags = flags;
|
||||
csio->ccb_h.retry_count = retries;
|
||||
csio->ccb_h.cbfcnp = cbfcnp;
|
||||
csio->ccb_h.timeout = timeout;
|
||||
csio->data_ptr = data_ptr;
|
||||
csio->dxfer_len = dxfer_len;
|
||||
csio->sense_len = sense_len;
|
||||
csio->cdb_len = cdb_len;
|
||||
csio->tag_action = tag_action;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_fill_ctio(struct ccb_scsiio *csio, u_int32_t retries,
|
||||
void (*cbfcnp)(struct cam_periph *, union ccb *),
|
||||
u_int32_t flags, u_int tag_action, u_int tag_id,
|
||||
u_int init_id, u_int scsi_status, u_int8_t *data_ptr,
|
||||
u_int32_t dxfer_len, u_int32_t timeout)
|
||||
{
|
||||
csio->ccb_h.func_code = XPT_CONT_TARGET_IO;
|
||||
csio->ccb_h.flags = flags;
|
||||
csio->ccb_h.retry_count = retries;
|
||||
csio->ccb_h.cbfcnp = cbfcnp;
|
||||
csio->ccb_h.timeout = timeout;
|
||||
csio->data_ptr = data_ptr;
|
||||
csio->dxfer_len = dxfer_len;
|
||||
csio->scsi_status = scsi_status;
|
||||
csio->tag_action = tag_action;
|
||||
csio->tag_id = tag_id;
|
||||
csio->init_id = init_id;
|
||||
}
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _CAM_CAM_CCB_H */
|
67
sys/cam/cam_conf.h
Normal file
67
sys/cam/cam_conf.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Data structures and definitions for linking CAM into the autoconf system.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_CONF_H
|
||||
#define _CAM_CAM_CONF_H 1
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
#define CAMCONF_UNSPEC 255
|
||||
#define CAMCONF_ANY 254
|
||||
|
||||
/*
|
||||
* Macro that lets us know something is specified.
|
||||
*/
|
||||
#define IS_SPECIFIED(ARG) (ARG != CAMCONF_UNSPEC && ARG != CAMCONF_ANY)
|
||||
|
||||
struct cam_sim_config
|
||||
{
|
||||
int pathid;
|
||||
char *sim_name;
|
||||
int sim_unit;
|
||||
int sim_bus;
|
||||
};
|
||||
|
||||
struct cam_periph_config
|
||||
{
|
||||
char *periph_name;
|
||||
int periph_unit; /* desired device unit */
|
||||
int pathid; /* Controller unit */
|
||||
int target;
|
||||
int lun;
|
||||
int flags; /* Flags from config */
|
||||
};
|
||||
|
||||
extern struct cam_sim_config cam_sinit[];
|
||||
extern struct cam_periph_config cam_pinit[];
|
||||
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* _CAM_CAM_CONF_H */
|
77
sys/cam/cam_debug.h
Normal file
77
sys/cam/cam_debug.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Macros for tracing/loging information in the CAM layer
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#ifndef _CAM_CAM_DEBUG_H
|
||||
#define _CAM_CAM_DEBUG_H 1
|
||||
|
||||
#if defined(CAMDEBUG) && defined(KERNEL)
|
||||
#include <machine/clock.h>
|
||||
#endif /* CAMDEBUG && KERNEL */
|
||||
|
||||
/*
|
||||
* Debugging flags.
|
||||
*/
|
||||
typedef enum {
|
||||
CAM_DEBUG_NONE = 0x00, /* no debugging */
|
||||
CAM_DEBUG_INFO = 0x01, /* scsi commands, errors, data */
|
||||
CAM_DEBUG_TRACE = 0x02, /* routine flow tracking */
|
||||
CAM_DEBUG_SUBTRACE = 0x04, /* internal to routine flows */
|
||||
} cam_debug_flags;
|
||||
|
||||
#if defined(CAMDEBUG) && defined(KERNEL)
|
||||
|
||||
/* Path we want to debug */
|
||||
extern struct cam_path *cam_dpath;
|
||||
/* Current debug levels set */
|
||||
extern u_int32_t cam_dflags;
|
||||
|
||||
/* Debugging macros. */
|
||||
#define CAM_DEBUG(path, flag, printfargs) \
|
||||
if ((cam_dflags & (flag)) \
|
||||
&& (cam_dpath != NULL) \
|
||||
&& (xpt_path_comp(path, cam_dpath) >= 0)) { \
|
||||
xpt_print_path(path); \
|
||||
printf printfargs; \
|
||||
DELAY(100000); \
|
||||
}
|
||||
#define CAM_DEBUG_PRINT(flag, printfargs) \
|
||||
if (cam_dflags & (flag)) { \
|
||||
printf("cam_debug: "); \
|
||||
printf printfargs; \
|
||||
DELAY(100000); \
|
||||
}
|
||||
|
||||
#else /* !CAMDEBUG || !KERNEL */
|
||||
|
||||
#define CAM_DEBUG(A, B, C)
|
||||
#define CAM_DEBUG_PRINT(A, B)
|
||||
|
||||
#endif /* CAMDEBUG && KERNEL */
|
||||
|
||||
#endif /* _CAM_CAM_DEBUG_H */
|
115
sys/cam/cam_extend.c
Normal file
115
sys/cam/cam_extend.c
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Written by Julian Elischer (julian@tfs.com)
|
||||
* for TRW Financial Systems for use under the MACH(2.5) operating system.
|
||||
*
|
||||
* TRW Financial Systems, in accordance with their agreement with Carnegie
|
||||
* Mellon University, makes this software available to CMU to distribute
|
||||
* or use in any manner that they see fit as long as this message is kept with
|
||||
* the software. For this reason TFS also grants any other persons or
|
||||
* organisations permission to use or modify this software.
|
||||
*
|
||||
* TFS supplies this software to be publicly redistributed
|
||||
* on the understanding that TFS is not responsible for the correct
|
||||
* functioning of this software in any circumstances.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
/*
|
||||
* XXX XXX XXX XXX We should get DEVFS working so that we
|
||||
* don't have to do this, possibly sparse, array based junk.
|
||||
*/
|
||||
/*
|
||||
* Extensible arrays: Use a realloc like implementation to permit
|
||||
* the arrays to be extend.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <cam/cam_extend.h>
|
||||
|
||||
struct extend_array
|
||||
{
|
||||
int nelem;
|
||||
void **ps;
|
||||
};
|
||||
|
||||
static void *
|
||||
cam_extend_alloc(size_t s)
|
||||
{
|
||||
void *p = malloc(s, M_DEVBUF, M_NOWAIT);
|
||||
if (!p)
|
||||
panic("extend_alloc: malloc failed.");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
cam_extend_free(void *p)
|
||||
{
|
||||
free(p, M_DEVBUF);
|
||||
}
|
||||
|
||||
/* EXTEND_CHUNK: Number of extend slots to allocate whenever we need a new
|
||||
* one.
|
||||
*/
|
||||
#ifndef EXTEND_CHUNK
|
||||
#define EXTEND_CHUNK 8
|
||||
#endif
|
||||
|
||||
struct extend_array *
|
||||
cam_extend_new(void)
|
||||
{
|
||||
struct extend_array *p = cam_extend_alloc(sizeof(*p));
|
||||
if (p) {
|
||||
p->nelem = 0;
|
||||
p->ps = 0;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *
|
||||
cam_extend_set(struct extend_array *ea, int index, void *value)
|
||||
{
|
||||
if (index >= ea->nelem) {
|
||||
void **space;
|
||||
space = cam_extend_alloc(sizeof(void *) * (index + EXTEND_CHUNK));
|
||||
bzero(space, sizeof(void *) * (index + EXTEND_CHUNK));
|
||||
|
||||
/* Make sure we have something to copy before we copy it */
|
||||
if (ea->nelem) {
|
||||
bcopy(ea->ps, space, sizeof(void *) * ea->nelem);
|
||||
cam_extend_free(ea->ps);
|
||||
}
|
||||
|
||||
ea->ps = space;
|
||||
ea->nelem = index + EXTEND_CHUNK;
|
||||
}
|
||||
if (ea->ps[index]) {
|
||||
printf("extend_set: entry %d already has storage.\n", index);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
ea->ps[index] = value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void *
|
||||
cam_extend_get(struct extend_array *ea,
|
||||
int index)
|
||||
{
|
||||
if (ea == NULL || index >= ea->nelem || index < 0)
|
||||
return NULL;
|
||||
return ea->ps[index];
|
||||
}
|
||||
|
||||
void
|
||||
cam_extend_release(struct extend_array *ea, int index)
|
||||
{
|
||||
void *p = cam_extend_get(ea, index);
|
||||
if (p) {
|
||||
ea->ps[index] = 0;
|
||||
}
|
||||
}
|
30
sys/cam/cam_extend.h
Normal file
30
sys/cam/cam_extend.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Written by Julian Elischer (julian@tfs.com)
|
||||
* for TRW Financial Systems for use under the MACH(2.5) operating system.
|
||||
*
|
||||
* TRW Financial Systems, in accordance with their agreement with Carnegie
|
||||
* Mellon University, makes this software available to CMU to distribute
|
||||
* or use in any manner that they see fit as long as this message is kept with
|
||||
* the software. For this reason TFS also grants any other persons or
|
||||
* organisations permission to use or modify this software.
|
||||
*
|
||||
* TFS supplies this software to be publicly redistributed
|
||||
* on the understanding that TFS is not responsible for the correct
|
||||
* functioning of this software in any circumstances.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_EXTEND_H
|
||||
#define _CAM_CAM_EXTEND_H 1
|
||||
|
||||
#ifdef KERNEL
|
||||
struct extend_array;
|
||||
|
||||
void *cam_extend_get(struct extend_array *ea, int index);
|
||||
struct extend_array *cam_extend_new(void);
|
||||
void *cam_extend_set(struct extend_array *ea, int index, void *value);
|
||||
void cam_extend_release(struct extend_array *ea, int index);
|
||||
|
||||
#endif /* KERNEL */
|
||||
#endif /* _CAM_CAM_EXTEND_H */
|
1493
sys/cam/cam_periph.c
Normal file
1493
sys/cam/cam_periph.c
Normal file
File diff suppressed because it is too large
Load Diff
135
sys/cam/cam_periph.h
Normal file
135
sys/cam/cam_periph.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Data structures and definitions for CAM peripheral ("type") drivers.
|
||||
*
|
||||
* Copyright (c) 1997, 1998 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_PERIPH_H
|
||||
#define _CAM_CAM_PERIPH_H 1
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
extern struct linker_set periphdriver_set;
|
||||
|
||||
typedef void (periph_init_t)(void); /*
|
||||
* Callback informing the peripheral driver
|
||||
* it can perform it's initialization since
|
||||
* the XPT is now fully initialized.
|
||||
*/
|
||||
typedef periph_init_t *periph_init_func_t;
|
||||
|
||||
struct periph_driver {
|
||||
periph_init_func_t init;
|
||||
char *driver_name;
|
||||
TAILQ_HEAD(,cam_periph) units;
|
||||
u_int generation;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CAM_PERIPH_BIO,
|
||||
CAM_PERIPH_NET
|
||||
} cam_periph_type;
|
||||
|
||||
/* Generically usefull offsets into the peripheral private area */
|
||||
#define ppriv_ptr0 periph_priv.entries[0].ptr
|
||||
#define ppriv_ptr1 periph_priv.entries[1].ptr
|
||||
#define ppriv_field0 periph_priv.entries[0].field
|
||||
#define ppriv_field1 periph_priv.entries[1].field
|
||||
|
||||
typedef void periph_start_t (struct cam_periph *periph,
|
||||
union ccb *start_ccb);
|
||||
typedef cam_status periph_ctor_t (struct cam_periph *periph,
|
||||
void *arg);
|
||||
typedef void periph_dtor_t (struct cam_periph *periph);
|
||||
|
||||
struct cam_periph {
|
||||
cam_pinfo pinfo;
|
||||
periph_start_t *periph_start;
|
||||
periph_dtor_t *periph_dtor;
|
||||
char *periph_name;
|
||||
struct cam_path *path; /* Compiled path to device */
|
||||
void *softc;
|
||||
u_int32_t unit_number;
|
||||
cam_periph_type type;
|
||||
u_int32_t flags;
|
||||
#define CAM_PERIPH_RUNNING 0x01
|
||||
#define CAM_PERIPH_LOCKED 0x02
|
||||
#define CAM_PERIPH_LOCK_WANTED 0x04
|
||||
#define CAM_PERIPH_INVALID 0x08
|
||||
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
|
||||
u_int32_t immediate_priority;
|
||||
u_int32_t refcount;
|
||||
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
|
||||
SLIST_ENTRY(cam_periph) periph_links;
|
||||
TAILQ_ENTRY(cam_periph) unit_links;
|
||||
ac_callback_t *deferred_callback;
|
||||
ac_code deferred_ac;
|
||||
};
|
||||
|
||||
#define CAM_PERIPH_MAXMAPS 2
|
||||
|
||||
struct cam_periph_map_info {
|
||||
int num_bufs_used;
|
||||
struct buf *bp[CAM_PERIPH_MAXMAPS];
|
||||
};
|
||||
|
||||
cam_status cam_periph_alloc(periph_ctor_t*, periph_dtor_t*, periph_start_t*,
|
||||
char *name, cam_periph_type type, struct cam_path *, ac_callback_t *, ac_code, void *arg);
|
||||
struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
|
||||
int cam_periph_lock(struct cam_periph *periph, int priority);
|
||||
void cam_periph_unlock(struct cam_periph *periph);
|
||||
cam_status cam_periph_acquire(struct cam_periph *periph);
|
||||
void cam_periph_release(struct cam_periph *periph);
|
||||
void cam_periph_invalidate(struct cam_periph *periph);
|
||||
int cam_periph_mapmem(union ccb *ccb,
|
||||
struct cam_periph_map_info *mapinfo);
|
||||
void cam_periph_unmapmem(union ccb *ccb,
|
||||
struct cam_periph_map_info *mapinfo);
|
||||
union ccb *cam_periph_getccb(struct cam_periph *periph,
|
||||
u_int32_t priority);
|
||||
void cam_periph_ccbwait(union ccb *ccb);
|
||||
int cam_periph_runccb(union ccb *ccb,
|
||||
int (*error_routine)(union ccb *ccb,
|
||||
cam_flags camflags,
|
||||
u_int32_t sense_flags),
|
||||
cam_flags camflags, u_int32_t sense_flags,
|
||||
struct devstat *ds);
|
||||
int cam_periph_ioctl(struct cam_periph *periph, int cmd,
|
||||
caddr_t addr,
|
||||
int (*error_routine)(union ccb *ccb,
|
||||
cam_flags camflags,
|
||||
u_int32_t sense_flags));
|
||||
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
|
||||
u_int32_t opening_reduction, u_int32_t timeout,
|
||||
int getcount_only);
|
||||
int cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
u_int32_t sense_flags, union ccb *save_ccb);
|
||||
|
||||
#endif /* KERNEL */
|
||||
#endif /* _CAM_CAM_PERIPH_H */
|
441
sys/cam/cam_queue.c
Normal file
441
sys/cam/cam_queue.c
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* CAM request queue management functions.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_queue.h>
|
||||
#include <cam/cam_debug.h>
|
||||
|
||||
static __inline int
|
||||
queue_cmp(cam_pinfo **queue_array, int i, int j);
|
||||
static __inline void
|
||||
swap(cam_pinfo **queue_array, int i, int j);
|
||||
static void heap_up(cam_pinfo **queue_array, int new_index);
|
||||
static void heap_down(cam_pinfo **queue_array, int index,
|
||||
int last_index);
|
||||
|
||||
struct camq *
|
||||
camq_alloc(int size)
|
||||
{
|
||||
struct camq *camq;
|
||||
|
||||
camq = (struct camq *)malloc(sizeof(*camq), M_DEVBUF, M_NOWAIT);
|
||||
if (camq != NULL) {
|
||||
if (camq_init(camq, size) != 0) {
|
||||
free(camq, M_DEVBUF);
|
||||
camq = NULL;
|
||||
}
|
||||
}
|
||||
return (camq);
|
||||
}
|
||||
|
||||
int
|
||||
camq_init(struct camq *camq, int size)
|
||||
{
|
||||
bzero(camq, sizeof(*camq));
|
||||
camq->array_size = size;
|
||||
if (camq->array_size != 0) {
|
||||
camq->queue_array = (cam_pinfo**)malloc(size*sizeof(cam_pinfo*),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (camq->queue_array == NULL) {
|
||||
printf("camq_init: - cannot malloc array!\n");
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a camq structure. This should only be called if a controller
|
||||
* driver failes somehow during its attach routine or is unloaded and has
|
||||
* obtained a camq structure. The XPT should ensure that the queue
|
||||
* is empty before calling this routine.
|
||||
*/
|
||||
void
|
||||
camq_free(struct camq *queue)
|
||||
{
|
||||
if (queue != NULL) {
|
||||
camq_fini(queue);
|
||||
free(queue, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
camq_fini(struct camq *queue)
|
||||
{
|
||||
if (queue->queue_array != NULL) {
|
||||
free(queue->queue_array, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
camq_resize(struct camq *queue, int new_size)
|
||||
{
|
||||
cam_pinfo **new_array;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (new_size < queue->entries)
|
||||
panic("camq_resize: New queue size can't accomodate "
|
||||
"queued entries.");
|
||||
#endif
|
||||
new_array = (cam_pinfo **)malloc(new_size * sizeof(cam_pinfo *),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (new_array == NULL) {
|
||||
/* Couldn't satisfy request */
|
||||
return (CAM_RESRC_UNAVAIL);
|
||||
}
|
||||
if (queue->queue_array != NULL) {
|
||||
bcopy(queue->queue_array, new_array,
|
||||
queue->entries * sizeof(cam_pinfo *));
|
||||
free(queue->queue_array, M_DEVBUF);
|
||||
}
|
||||
queue->queue_array = new_array;
|
||||
queue->array_size = new_size;
|
||||
return (CAM_REQ_CMP);
|
||||
}
|
||||
|
||||
/*
|
||||
* camq_regen: Given an array of cam_pinfo* elements with the
|
||||
* Heap(0, num_elements) property, perform the second half of
|
||||
* a heap sort, and assign new generation numbers to all entries.
|
||||
* It is assumed that the starting generation number plus the
|
||||
* number of entries in the queue is smaller than the wrap point
|
||||
* of the generation number.
|
||||
*/
|
||||
void
|
||||
camq_regen(struct camq *queue)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < queue->entries; index++) {
|
||||
|
||||
heap_down(queue->queue_array, index, queue->entries);
|
||||
queue->queue_array[index]->generation = queue->generation++;
|
||||
}
|
||||
/* A sorted array is still a heap, so we are done */
|
||||
}
|
||||
|
||||
/*
|
||||
* camq_insert: Given an array of cam_pinfo* elememnts with
|
||||
* the Heap(0, num_elements) property and array_size - num_elements >= 1,
|
||||
* output Heap(0, num_elements+1) including new_entry in the array.
|
||||
*/
|
||||
void
|
||||
camq_insert(struct camq *queue, cam_pinfo *new_entry)
|
||||
{
|
||||
#ifdef DIAGNOSTIC
|
||||
if (queue->entries >= queue->array_size)
|
||||
panic("camq_insert: Attempt to insert into a full queue");
|
||||
#endif
|
||||
queue->queue_array[queue->entries] = new_entry;
|
||||
new_entry->index = queue->entries;
|
||||
if (queue->entries != 0)
|
||||
heap_up(queue->queue_array, queue->entries);
|
||||
queue->entries++;
|
||||
}
|
||||
|
||||
/*
|
||||
* camq_remove: Given an array of cam_pinfo* elevements with the
|
||||
* Heap(0, num_elements) property and an index such that 0 <= index <=
|
||||
* num_elements, remove that entry and restore the Heap(0, num_elements-1)
|
||||
* property.
|
||||
*/
|
||||
cam_pinfo *
|
||||
camq_remove(struct camq *queue, int index)
|
||||
{
|
||||
cam_pinfo *removed_entry;
|
||||
|
||||
if ((queue->entries - index) <= 0)
|
||||
return (NULL);
|
||||
removed_entry = queue->queue_array[index];
|
||||
queue->entries--;
|
||||
if (queue->entries != index) {
|
||||
queue->queue_array[index] = queue->queue_array[queue->entries];
|
||||
queue->queue_array[index]->index = index;
|
||||
heap_down(queue->queue_array, index, queue->entries);
|
||||
}
|
||||
removed_entry->index = CAM_UNQUEUED_INDEX;
|
||||
return (removed_entry);
|
||||
}
|
||||
|
||||
/*
|
||||
* camq_change_priority: Given an array of cam_pinfo* elements with the
|
||||
* Heap(0, num_entries) property, an index such that 0 <= index <= num_elements,
|
||||
* and an new priority for the element at index, change the priority of
|
||||
* element index and restore the Heap(0, num_elements) property.
|
||||
*/
|
||||
void
|
||||
camq_change_priority(struct camq *queue, int index, u_int32_t new_priority)
|
||||
{
|
||||
if (new_priority > queue->queue_array[index]->priority) {
|
||||
queue->queue_array[index]->priority = new_priority;
|
||||
heap_down(queue->queue_array, index, queue->entries);
|
||||
} else {
|
||||
/* new_priority <= old_priority */
|
||||
queue->queue_array[index]->priority = new_priority;
|
||||
heap_up(queue->queue_array, index);
|
||||
}
|
||||
}
|
||||
|
||||
struct cam_devq *
|
||||
cam_devq_alloc(int devices, int openings)
|
||||
{
|
||||
struct cam_devq *devq;
|
||||
|
||||
devq = (struct cam_devq *)malloc(sizeof(*devq), M_DEVBUF, M_NOWAIT);
|
||||
if (devq == NULL) {
|
||||
printf("cam_devq_alloc: - cannot malloc!\n");
|
||||
return (NULL);
|
||||
}
|
||||
if (cam_devq_init(devq, devices, openings) != 0) {
|
||||
free(devq, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (devq);
|
||||
}
|
||||
|
||||
int
|
||||
cam_devq_init(struct cam_devq *devq, int devices, int openings)
|
||||
{
|
||||
bzero(devq, sizeof(*devq));
|
||||
if (camq_init(&devq->alloc_queue, devices) != 0) {
|
||||
return (1);
|
||||
}
|
||||
if (camq_init(&devq->send_queue, devices) != 0) {
|
||||
camq_fini(&devq->alloc_queue);
|
||||
return (1);
|
||||
}
|
||||
devq->alloc_openings = openings;
|
||||
devq->alloc_active = 0;
|
||||
devq->send_openings = openings;
|
||||
devq->send_active = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
cam_devq_free(struct cam_devq *devq)
|
||||
{
|
||||
camq_free(&devq->alloc_queue);
|
||||
camq_free(&devq->send_queue);
|
||||
free(devq, M_DEVBUF);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
cam_devq_resize(struct cam_devq *camq, int devices)
|
||||
{
|
||||
u_int32_t retval;
|
||||
|
||||
retval = camq_resize(&camq->alloc_queue, devices);
|
||||
|
||||
if (retval == CAM_REQ_CMP)
|
||||
retval = camq_resize(&camq->send_queue, devices);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
struct cam_ccbq *
|
||||
cam_ccbq_alloc(int openings)
|
||||
{
|
||||
struct cam_ccbq *ccbq;
|
||||
|
||||
ccbq = (struct cam_ccbq *)malloc(sizeof(*ccbq), M_DEVBUF, M_NOWAIT);
|
||||
if (ccbq == NULL) {
|
||||
printf("cam_ccbq_alloc: - cannot malloc!\n");
|
||||
return (NULL);
|
||||
}
|
||||
if (cam_ccbq_init(ccbq, openings) != 0) {
|
||||
free(ccbq, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (ccbq);
|
||||
}
|
||||
|
||||
void
|
||||
cam_ccbq_free(struct cam_ccbq *ccbq)
|
||||
{
|
||||
if (ccbq) {
|
||||
camq_fini(&ccbq->queue);
|
||||
free(ccbq, M_DEVBUF);
|
||||
}
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
cam_ccbq_resize(struct cam_ccbq *ccbq, int new_size)
|
||||
{
|
||||
int delta;
|
||||
int space_left;
|
||||
|
||||
delta = new_size - (ccbq->dev_active + ccbq->dev_openings);
|
||||
space_left = new_size
|
||||
- ccbq->queue.entries
|
||||
- ccbq->held
|
||||
- ccbq->dev_active;
|
||||
|
||||
/*
|
||||
* Only attempt to change the underlying queue size if we are
|
||||
* shrinking it and there is space for all outstanding entries
|
||||
* in the new array or we have been requested to grow the array.
|
||||
* We don't fail in the case where we can't reduce the array size,
|
||||
* but clients that care that the queue be "garbage collected"
|
||||
* should detect this condition and call us again with the
|
||||
* same size once the outstanding entries have been processed.
|
||||
*/
|
||||
if (space_left < 0
|
||||
|| camq_resize(&ccbq->queue, new_size) == CAM_REQ_CMP) {
|
||||
ccbq->devq_openings += delta;
|
||||
ccbq->dev_openings += delta;
|
||||
return (CAM_REQ_CMP);
|
||||
} else {
|
||||
return (CAM_RESRC_UNAVAIL);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cam_ccbq_init(struct cam_ccbq *ccbq, int openings)
|
||||
{
|
||||
bzero(ccbq, sizeof(*ccbq));
|
||||
if (camq_init(&ccbq->queue, openings) != 0) {
|
||||
return (1);
|
||||
}
|
||||
ccbq->devq_openings = openings;
|
||||
ccbq->dev_openings = openings;
|
||||
TAILQ_INIT(&ccbq->active_ccbs);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
cam_ccbq_regen(struct cam_ccbq *ccbq)
|
||||
{
|
||||
struct ccb_hdr *ccbh;
|
||||
|
||||
/* First get all of the guys down at a device */
|
||||
ccbh = ccbq->active_ccbs.tqh_first;
|
||||
|
||||
while (ccbh != NULL) {
|
||||
ccbh->pinfo.generation = ccbq->queue.generation++;
|
||||
ccbh = ccbh->xpt_links.tqe.tqe_next;
|
||||
}
|
||||
|
||||
/* Now get everyone in our CAM queue */
|
||||
camq_regen(&ccbq->queue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Heap routines for manipulating CAM queues.
|
||||
*/
|
||||
/*
|
||||
* queue_cmp: Given an array of cam_pinfo* elements and indexes i
|
||||
* and j, return less than 0, 0, or greater than 0 if i is less than,
|
||||
* equal too, or greater than j respectively.
|
||||
*/
|
||||
static __inline int
|
||||
queue_cmp(cam_pinfo **queue_array, int i, int j)
|
||||
{
|
||||
if (queue_array[i]->priority == queue_array[j]->priority)
|
||||
return ( queue_array[i]->generation
|
||||
- queue_array[j]->generation );
|
||||
else
|
||||
return ( queue_array[i]->priority
|
||||
- queue_array[j]->priority );
|
||||
}
|
||||
|
||||
/*
|
||||
* swap: Given an array of cam_pinfo* elements and indexes i and j,
|
||||
* exchange elements i and j.
|
||||
*/
|
||||
static __inline void
|
||||
swap(cam_pinfo **queue_array, int i, int j)
|
||||
{
|
||||
cam_pinfo *temp_qentry;
|
||||
|
||||
temp_qentry = queue_array[j];
|
||||
queue_array[j] = queue_array[i];
|
||||
queue_array[i] = temp_qentry;
|
||||
queue_array[j]->index = j;
|
||||
queue_array[i]->index = i;
|
||||
}
|
||||
|
||||
/*
|
||||
* heap_up: Given an array of cam_pinfo* elements with the
|
||||
* Heap(0, new_index-1) property and a new element in location
|
||||
* new_index, output Heap(0, new_index).
|
||||
*/
|
||||
static void
|
||||
heap_up(cam_pinfo **queue_array, int new_index)
|
||||
{
|
||||
int child;
|
||||
int parent;
|
||||
|
||||
child = new_index;
|
||||
|
||||
while (child != 0) {
|
||||
|
||||
parent = child >> 1;
|
||||
if (queue_cmp(queue_array, parent, child) <= 0)
|
||||
break;
|
||||
swap(queue_array, parent, child);
|
||||
child = parent;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* heap_down: Given an array of cam_pinfo* elements with the
|
||||
* Heap(1, num_entries - 1) property with index 0 containing an unsorted
|
||||
* entry, output Heap(0, num_entries - 1).
|
||||
*/
|
||||
static void
|
||||
heap_down(cam_pinfo **queue_array, int index, int num_entries)
|
||||
{
|
||||
int child;
|
||||
int parent;
|
||||
|
||||
parent = index;
|
||||
child = parent == 0 ? 1 : parent << 1;
|
||||
for (; child < num_entries; child = parent << 1) {
|
||||
|
||||
if (child + 1 < num_entries) {
|
||||
/* child+1 is the right child of parent */
|
||||
if (queue_cmp(queue_array, child + 1, child) < 0)
|
||||
child++;
|
||||
}
|
||||
/* child is now the least child of parent */
|
||||
if (queue_cmp(queue_array, parent, child) <= 0)
|
||||
break;
|
||||
swap(queue_array, child, parent);
|
||||
parent = child;
|
||||
}
|
||||
}
|
||||
|
236
sys/cam/cam_queue.h
Normal file
236
sys/cam/cam_queue.h
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* CAM request queue management definitions.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_QUEUE_H
|
||||
#define _CAM_CAM_QUEUE_H 1
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
/*
|
||||
* This structure implements a heap based priority queue. The queue
|
||||
* assumes that the objects stored in it begin with a cam_qentry
|
||||
* structure holding the priority information used to sort the objects.
|
||||
* This structure is opaque to clients (outside of the XPT layer) to allow
|
||||
* the implementation to change without affecting them.
|
||||
*/
|
||||
struct camq {
|
||||
cam_pinfo **queue_array;
|
||||
int array_size;
|
||||
int entries;
|
||||
u_int32_t generation;
|
||||
u_int32_t qfrozen_cnt;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(ccb_hdr_list, ccb_hdr);
|
||||
|
||||
struct cam_ccbq {
|
||||
struct camq queue;
|
||||
int devq_openings;
|
||||
int dev_openings;
|
||||
int dev_active;
|
||||
int held;
|
||||
struct ccb_hdr_list active_ccbs;
|
||||
};
|
||||
|
||||
struct cam_ed;
|
||||
|
||||
struct cam_devq {
|
||||
struct camq alloc_queue;
|
||||
struct camq send_queue;
|
||||
struct cam_ed *active_dev;
|
||||
int alloc_openings;
|
||||
int alloc_active;
|
||||
int send_openings;
|
||||
int send_active;
|
||||
};
|
||||
|
||||
|
||||
struct cam_devq *cam_devq_alloc(int devices, int openings);
|
||||
|
||||
int cam_devq_init(struct cam_devq *devq, int devices,
|
||||
int openings);
|
||||
|
||||
void cam_devq_free(struct cam_devq *devq);
|
||||
|
||||
u_int32_t cam_devq_resize(struct cam_devq *camq, int openings);
|
||||
|
||||
/*
|
||||
* Allocate a cam_ccb_queue structure and initialize it.
|
||||
*/
|
||||
struct cam_ccbq *cam_ccbq_alloc(int openings);
|
||||
|
||||
u_int32_t cam_ccbq_resize(struct cam_ccbq *ccbq, int devices);
|
||||
|
||||
int cam_ccbq_init(struct cam_ccbq *ccbq, int openings);
|
||||
|
||||
void cam_ccbq_free(struct cam_ccbq *ccbq);
|
||||
|
||||
void cam_ccbq_fini(struct cam_ccbq *ccbq);
|
||||
|
||||
void cam_ccbq_regen(struct cam_ccbq *ccbq);
|
||||
|
||||
/*
|
||||
* Allocate and initialize a cam_queue structure.
|
||||
*/
|
||||
struct camq *camq_alloc(int size);
|
||||
|
||||
/*
|
||||
* Resize a cam queue
|
||||
*/
|
||||
u_int32_t camq_resize(struct camq *queue, int new_size);
|
||||
|
||||
/*
|
||||
* Initialize a camq structure. Return 0 on success, 1 on failure.
|
||||
*/
|
||||
int camq_init(struct camq *camq, int size);
|
||||
|
||||
/*
|
||||
* Free a cam_queue structure. This should only be called if a controller
|
||||
* driver failes somehow during its attach routine or is unloaded and has
|
||||
* obtained a cam_queue structure.
|
||||
*/
|
||||
void camq_free(struct camq *queue);
|
||||
|
||||
/*
|
||||
* Finialize any internal storage or state of a cam_queue.
|
||||
*/
|
||||
void camq_fini(struct camq *queue);
|
||||
|
||||
/*
|
||||
* cam_queue_insert: Given a CAM queue with at least one open spot,
|
||||
* insert the new entry maintaining order.
|
||||
*/
|
||||
void camq_insert(struct camq *queue, cam_pinfo *new_entry);
|
||||
|
||||
/*
|
||||
* camq_remove: Remove and arbitrary entry from the queue maintaining
|
||||
* queue order.
|
||||
*/
|
||||
cam_pinfo *camq_remove(struct camq *queue, int index);
|
||||
|
||||
/*
|
||||
* camq_change_priority: Raise or lower the priority of an entry
|
||||
* maintaining queue order.
|
||||
*/
|
||||
void camq_change_priority(struct camq *queue, int index,
|
||||
u_int32_t new_priority);
|
||||
|
||||
void camq_regen(struct camq *queue);
|
||||
|
||||
static __inline int
|
||||
cam_ccbq_pending_ccb_count(struct cam_ccbq *ccbq);
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_take_opening(struct cam_ccbq *ccbq);
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb);
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb);
|
||||
|
||||
static __inline union ccb *
|
||||
cam_ccbq_peek_ccb(struct cam_ccbq *ccbq, int index);
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_send_ccb(struct cam_ccbq *queue, union ccb *send_ccb);
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_ccb_done(struct cam_ccbq *ccbq, union ccb *done_ccb);
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_release_opening(struct cam_ccbq *ccbq);
|
||||
|
||||
|
||||
static __inline int
|
||||
cam_ccbq_pending_ccb_count(struct cam_ccbq *ccbq)
|
||||
{
|
||||
return (ccbq->queue.entries);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_take_opening(struct cam_ccbq *ccbq)
|
||||
{
|
||||
ccbq->devq_openings--;
|
||||
ccbq->held++;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb)
|
||||
{
|
||||
ccbq->held--;
|
||||
camq_insert(&ccbq->queue, &new_ccb->ccb_h.pinfo);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb)
|
||||
{
|
||||
camq_remove(&ccbq->queue, ccb->ccb_h.pinfo.index);
|
||||
}
|
||||
|
||||
static __inline union ccb *
|
||||
cam_ccbq_peek_ccb(struct cam_ccbq *ccbq, int index)
|
||||
{
|
||||
return((union ccb *)ccbq->queue.queue_array[index]);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_send_ccb(struct cam_ccbq *ccbq, union ccb *send_ccb)
|
||||
{
|
||||
|
||||
TAILQ_INSERT_TAIL(&ccbq->active_ccbs,
|
||||
&(send_ccb->ccb_h),
|
||||
xpt_links.tqe);
|
||||
send_ccb->ccb_h.pinfo.index = CAM_ACTIVE_INDEX;
|
||||
ccbq->dev_active++;
|
||||
ccbq->dev_openings--;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_ccb_done(struct cam_ccbq *ccbq, union ccb *done_ccb)
|
||||
{
|
||||
TAILQ_REMOVE(&ccbq->active_ccbs, &done_ccb->ccb_h,
|
||||
xpt_links.tqe);
|
||||
ccbq->dev_active--;
|
||||
ccbq->dev_openings++;
|
||||
ccbq->held++;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
cam_ccbq_release_opening(struct cam_ccbq *ccbq)
|
||||
{
|
||||
ccbq->held--;
|
||||
ccbq->devq_openings++;
|
||||
}
|
||||
|
||||
#endif /* KERNEL */
|
||||
#endif /* _CAM_CAM_QUEUE_H */
|
112
sys/cam/cam_sim.c
Normal file
112
sys/cam/cam_sim.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Common functions for SCSI Interface Modules (SIMs).
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_queue.h>
|
||||
|
||||
#define CAM_PATH_ANY (u_int32_t)-1
|
||||
|
||||
struct cam_devq *
|
||||
cam_simq_alloc(u_int32_t max_sim_transactions)
|
||||
{
|
||||
return (cam_devq_alloc(/*size*/0, max_sim_transactions));
|
||||
}
|
||||
|
||||
void
|
||||
cam_simq_free(struct cam_devq *devq)
|
||||
{
|
||||
cam_devq_free(devq);
|
||||
}
|
||||
|
||||
struct cam_sim *
|
||||
cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
|
||||
char *sim_name, void *softc, u_int32_t unit,
|
||||
u_int32_t max_dev_transactions,
|
||||
u_int32_t max_tagged_dev_transactions, struct cam_devq *queue)
|
||||
{
|
||||
struct cam_sim *sim;
|
||||
|
||||
/*
|
||||
* If this is the xpt layer creating a sim, then it's OK
|
||||
* to wait for an allocation.
|
||||
*
|
||||
* XXX Should we pass in a flag to indicate that wait is OK?
|
||||
*/
|
||||
if (strcmp(sim_name, "xpt") == 0)
|
||||
sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
|
||||
M_DEVBUF, M_WAITOK);
|
||||
else
|
||||
sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
|
||||
if (sim != NULL) {
|
||||
sim->sim_action = sim_action;
|
||||
sim->sim_poll = sim_poll;
|
||||
sim->sim_name = sim_name;
|
||||
sim->softc = softc;
|
||||
sim->path_id = CAM_PATH_ANY;
|
||||
sim->unit_number = unit;
|
||||
sim->bus_id = 0; /* set in xpt_bus_register */
|
||||
sim->base_transfer_speed = 3300; /* asynchronous 3300 kB/sec */
|
||||
sim->max_tagged_dev_openings = max_tagged_dev_transactions;
|
||||
sim->max_dev_openings = max_dev_transactions;
|
||||
sim->flags = 0;
|
||||
callout_handle_init(&sim->c_handle);
|
||||
sim->devq = queue;
|
||||
}
|
||||
|
||||
return (sim);
|
||||
}
|
||||
|
||||
void
|
||||
cam_sim_free(struct cam_sim *sim, int free_devq)
|
||||
{
|
||||
if (free_devq)
|
||||
cam_simq_free(sim->devq);
|
||||
free(sim, M_DEVBUF);
|
||||
}
|
||||
|
||||
void
|
||||
cam_sim_set_basexfer_speed(struct cam_sim *sim, u_int32_t base_xfer_speed)
|
||||
{
|
||||
sim->base_transfer_speed = base_xfer_speed;
|
||||
}
|
||||
|
||||
void
|
||||
cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id)
|
||||
{
|
||||
sim->path_id = path_id;
|
||||
}
|
138
sys/cam/cam_sim.h
Normal file
138
sys/cam/cam_sim.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Data structures and definitions for SCSI Interface Modules (SIMs).
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_SIM_H
|
||||
#define _CAM_CAM_SIM_H 1
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
/*
|
||||
* The sim driver creates a sim for each controller. The sim device
|
||||
* queue is separately created in order to allow resource sharing between
|
||||
* sims. For instance, a driver may create one sim for each channel of
|
||||
* a multi-channel controller and use the same queue for each channel.
|
||||
* In this way, the queue resources are shared across all the channels
|
||||
* of the multi-channel controller.
|
||||
*/
|
||||
|
||||
struct cam_sim;
|
||||
struct cam_devq;
|
||||
|
||||
typedef void (*sim_action_func)(struct cam_sim *sim, union ccb *ccb);
|
||||
typedef void (*sim_poll_func)(struct cam_sim *sim);
|
||||
|
||||
struct cam_devq * cam_simq_alloc(u_int32_t max_sim_transactions);
|
||||
void cam_simq_free(struct cam_devq *devq);
|
||||
|
||||
struct cam_sim * cam_sim_alloc(sim_action_func sim_action,
|
||||
sim_poll_func sim_poll,
|
||||
char *sim_name,
|
||||
void *softc,
|
||||
u_int32_t unit,
|
||||
u_int32_t max_dev_transactions,
|
||||
u_int32_t max_tagged_dev_transactions,
|
||||
struct cam_devq *queue);
|
||||
void cam_sim_free(struct cam_sim *sim, int free_devq);
|
||||
|
||||
/* Optional sim attributes may be set with these. */
|
||||
void cam_sim_set_basexfer_speed(struct cam_sim *sim,
|
||||
u_int32_t base_xfer_speed);
|
||||
void cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id);
|
||||
|
||||
|
||||
|
||||
/* Convenience routines for accessing sim attributes. */
|
||||
static __inline u_int32_t cam_sim_path(struct cam_sim *sim);
|
||||
static __inline char * cam_sim_name(struct cam_sim *sim);
|
||||
static __inline void * cam_sim_softc(struct cam_sim *sim);
|
||||
static __inline u_int32_t cam_sim_unit(struct cam_sim *sim);
|
||||
static __inline u_int32_t cam_sim_bus(struct cam_sim *sim);
|
||||
|
||||
|
||||
|
||||
/* Generically useful offsets into the sim private area */
|
||||
#define spriv_ptr0 sim_priv.entries[0].ptr
|
||||
#define spriv_ptr1 sim_priv.entries[1].ptr
|
||||
#define spriv_field0 sim_priv.entries[0].field
|
||||
#define spriv_field1 sim_priv.entries[1].field
|
||||
|
||||
/*
|
||||
* The sim driver should not access anything directly from this
|
||||
* structure.
|
||||
*/
|
||||
struct cam_sim {
|
||||
sim_action_func sim_action;
|
||||
sim_poll_func sim_poll;
|
||||
char *sim_name;
|
||||
void *softc;
|
||||
u_int32_t path_id;/* The Boot device may set this to 0? */
|
||||
u_int32_t unit_number;
|
||||
u_int32_t bus_id;
|
||||
u_int32_t base_transfer_speed; /* in kB/s */
|
||||
u_int32_t max_tagged_dev_openings;
|
||||
u_int32_t max_dev_openings;
|
||||
u_int32_t flags;
|
||||
#define CAM_SIM_REL_TIMEOUT_PENDING 0x01
|
||||
struct callout_handle c_handle;
|
||||
struct cam_devq *devq; /* Device Queue to use for this SIM */
|
||||
};
|
||||
|
||||
static __inline u_int32_t
|
||||
cam_sim_path(struct cam_sim *sim)
|
||||
{
|
||||
return (sim->path_id);
|
||||
}
|
||||
|
||||
static __inline char *
|
||||
cam_sim_name(struct cam_sim *sim)
|
||||
{
|
||||
return (sim->sim_name);
|
||||
}
|
||||
|
||||
static __inline void *
|
||||
cam_sim_softc(struct cam_sim *sim)
|
||||
{
|
||||
return (sim->softc);
|
||||
}
|
||||
|
||||
static __inline u_int32_t
|
||||
cam_sim_unit(struct cam_sim *sim)
|
||||
{
|
||||
return (sim->unit_number);
|
||||
}
|
||||
|
||||
static __inline u_int32_t
|
||||
cam_sim_bus(struct cam_sim *sim)
|
||||
{
|
||||
return (sim->bus_id);
|
||||
}
|
||||
|
||||
#endif /* KERNEL */
|
||||
#endif /* _CAM_CAM_SIM_H */
|
5610
sys/cam/cam_xpt.c
Normal file
5610
sys/cam/cam_xpt.c
Normal file
File diff suppressed because it is too large
Load Diff
75
sys/cam/cam_xpt.h
Normal file
75
sys/cam/cam_xpt.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Data structures and definitions for dealing with the
|
||||
* Common Access Method Transport (xpt) layer.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_XPT_H
|
||||
#define _CAM_CAM_XPT_H 1
|
||||
|
||||
/* Forward Declarations */
|
||||
union ccb;
|
||||
struct cam_periph;
|
||||
struct cam_sim;
|
||||
|
||||
/*
|
||||
* Definition of a CAM path. Paths are created from bus, target, and lun ids
|
||||
* via xpt_create_path and allow for reference to devices without recurring
|
||||
* lookups in the edt.
|
||||
*/
|
||||
struct cam_path;
|
||||
|
||||
/* Path functions */
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
void xpt_action(union ccb *new_ccb);
|
||||
void xpt_setup_ccb(struct ccb_hdr *ccb_h,
|
||||
struct cam_path *path,
|
||||
u_int32_t priority);
|
||||
void xpt_merge_ccb(union ccb *master_ccb,
|
||||
union ccb *slave_ccb);
|
||||
cam_status xpt_create_path(struct cam_path **new_path_ptr,
|
||||
struct cam_periph *perph,
|
||||
path_id_t path_id,
|
||||
target_id_t target_id, lun_id_t lun_id);
|
||||
void xpt_free_path(struct cam_path *path);
|
||||
int xpt_path_comp(struct cam_path *path1,
|
||||
struct cam_path *path2);
|
||||
void xpt_print_path(struct cam_path *path);
|
||||
path_id_t xpt_path_path_id(struct cam_path *path);
|
||||
target_id_t xpt_path_target_id(struct cam_path *path);
|
||||
lun_id_t xpt_path_lun_id(struct cam_path *path);
|
||||
struct cam_sim *xpt_path_sim(struct cam_path *path);
|
||||
struct cam_periph *xpt_path_periph(struct cam_path *path);
|
||||
void xpt_async(u_int32_t async_code, struct cam_path *path,
|
||||
void *async_arg);
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* _CAM_CAM_XPT_H */
|
||||
|
51
sys/cam/cam_xpt_periph.h
Normal file
51
sys/cam/cam_xpt_periph.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Data structures and definitions for dealing with the
|
||||
* Common Access Method Transport (xpt) layer from peripheral
|
||||
* drivers.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_XPT_PERIPH_H
|
||||
#define _CAM_CAM_XPT_PERIPH_H 1
|
||||
|
||||
#include <cam/cam_xpt.h>
|
||||
|
||||
/* Functions accessed by the peripheral drivers */
|
||||
#ifdef KERNEL
|
||||
void xpt_polled_action(union ccb *ccb);
|
||||
union ccb *xpt_alloc_ccb(void);
|
||||
void xpt_free_ccb(union ccb *free_ccb);
|
||||
void xpt_release_ccb(union ccb *released_ccb);
|
||||
void xpt_schedule(struct cam_periph *perph, u_int32_t new_priority);
|
||||
int32_t xpt_add_periph(struct cam_periph *periph);
|
||||
void xpt_remove_periph(struct cam_periph *periph);
|
||||
void xpt_announce_periph(struct cam_periph *periph,
|
||||
char *announce_string);
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* _CAM_CAM_XPT_PERIPH_H */
|
50
sys/cam/cam_xpt_sim.h
Normal file
50
sys/cam/cam_xpt_sim.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Data structures and definitions for dealing with the
|
||||
* Common Access Method Transport (xpt) layer.
|
||||
*
|
||||
* Copyright (c) 1997 Justin T. Gibbs.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions, and the following disclaimer,
|
||||
* without modification, immediately at the beginning of the file.
|
||||
* 2. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _CAM_CAM_XPT_SIM_H
|
||||
#define _CAM_CAM_XPT_SIM_H 1
|
||||
|
||||
#include <cam/cam_xpt.h>
|
||||
#include <cam/cam_queue.h>
|
||||
|
||||
/* Functions accessed by SIM drivers */
|
||||
#ifdef KERNEL
|
||||
int32_t xpt_bus_register(struct cam_sim *sim, u_int32_t bus);
|
||||
int32_t xpt_bus_deregister(u_int8_t path_id);
|
||||
u_int32_t xpt_freeze_simq(struct cam_sim *sim, u_int count);
|
||||
void xpt_release_simq(struct cam_sim *sim, int run_queue);
|
||||
u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
|
||||
void xpt_release_devq(struct cam_ed *dev, int run_queue);
|
||||
void xpt_done(union ccb *done_ccb);
|
||||
#endif /* KERNEL */
|
||||
|
||||
#endif /* _CAM_CAM_XPT_SIM_H */
|
||||
|
Loading…
Reference in New Issue
Block a user