#ifndef _SCSI_SCSICONF_H
#define _SCSI_SCSICONF_H
#include <sys/queue.h>
#include <sys/timeout.h>
#include <sys/mutex.h>
static __inline void _lto2b(u_int32_t val, u_int8_t *bytes);
static __inline void _lto3b(u_int32_t val, u_int8_t *bytes);
static __inline void _lto4b(u_int32_t val, u_int8_t *bytes);
static __inline void _lto8b(u_int64_t val, u_int8_t *bytes);
static __inline u_int32_t _2btol(u_int8_t *bytes);
static __inline u_int32_t _3btol(u_int8_t *bytes);
static __inline u_int32_t _4btol(u_int8_t *bytes);
static __inline u_int64_t _5btol(u_int8_t *bytes);
static __inline u_int64_t _8btol(u_int8_t *bytes);
static __inline void
_lto2b(u_int32_t val, u_int8_t *bytes)
{
bytes[0] = (val >> 8) & 0xff;
bytes[1] = val & 0xff;
}
static __inline void
_lto3b(u_int32_t val, u_int8_t *bytes)
{
bytes[0] = (val >> 16) & 0xff;
bytes[1] = (val >> 8) & 0xff;
bytes[2] = val & 0xff;
}
static __inline void
_lto4b(u_int32_t val, u_int8_t *bytes)
{
bytes[0] = (val >> 24) & 0xff;
bytes[1] = (val >> 16) & 0xff;
bytes[2] = (val >> 8) & 0xff;
bytes[3] = val & 0xff;
}
static __inline void
_lto8b(u_int64_t val, u_int8_t *bytes)
{
bytes[0] = (val >> 56) & 0xff;
bytes[1] = (val >> 48) & 0xff;
bytes[2] = (val >> 40) & 0xff;
bytes[3] = (val >> 32) & 0xff;
bytes[4] = (val >> 24) & 0xff;
bytes[5] = (val >> 16) & 0xff;
bytes[6] = (val >> 8) & 0xff;
bytes[7] = val & 0xff;
}
static __inline u_int32_t
_2btol(u_int8_t *bytes)
{
u_int32_t rv;
rv = (bytes[0] << 8) | bytes[1];
return rv;
}
static __inline u_int32_t
_3btol(u_int8_t *bytes)
{
u_int32_t rv;
rv = (bytes[0] << 16) | (bytes[1] << 8) | bytes[2];
return rv;
}
static __inline u_int32_t
_4btol(u_int8_t *bytes)
{
u_int32_t rv;
rv = (bytes[0] << 24) | (bytes[1] << 16) |
(bytes[2] << 8) | bytes[3];
return rv;
}
static __inline u_int64_t
_5btol(u_int8_t *bytes)
{
u_int64_t rv;
rv = ((u_int64_t)bytes[0] << 32) |
((u_int64_t)bytes[1] << 24) |
((u_int64_t)bytes[2] << 16) |
((u_int64_t)bytes[3] << 8) |
(u_int64_t)bytes[4];
return rv;
}
static __inline u_int64_t
_8btol(u_int8_t *bytes)
{
u_int64_t rv;
rv = (((u_int64_t)bytes[0]) << 56) |
(((u_int64_t)bytes[1]) << 48) |
(((u_int64_t)bytes[2]) << 40) |
(((u_int64_t)bytes[3]) << 32) |
(((u_int64_t)bytes[4]) << 24) |
(((u_int64_t)bytes[5]) << 16) |
(((u_int64_t)bytes[6]) << 8) |
((u_int64_t)bytes[7]);
return rv;
}
#ifdef _KERNEL
#define DEVID_NONE 0
#define DEVID_NAA 1
#define DEVID_EUI 2
#define DEVID_T10 3
#define DEVID_SERIAL 4
#define DEVID_WWN 5
struct devid {
u_int8_t d_type;
u_int8_t d_flags;
#define DEVID_F_PRINT (1<<0)
u_int8_t d_refcount;
u_int8_t d_len;
};
#define DEVID_CMP(_a, _b) ( \
(_a) != NULL && (_b) != NULL && \
((_a) == (_b) || \
((_a)->d_type != DEVID_NONE && \
(_a)->d_type == (_b)->d_type && \
(_a)->d_len == (_b)->d_len && \
bcmp((_a) + 1, (_b) + 1, (_a)->d_len) == 0)) \
)
struct devid * devid_alloc(u_int8_t, u_int8_t, u_int8_t, u_int8_t *);
struct devid * devid_copy(struct devid *);
void devid_free(struct devid *);
struct scsi_xfer;
struct scsi_link;
struct scsibus_softc;
extern int scsi_autoconf;
struct scsi_adapter {
void (*scsi_cmd)(struct scsi_xfer *);
void (*dev_minphys)(struct buf *, struct scsi_link *);
int (*dev_probe)(struct scsi_link *);
void (*dev_free)(struct scsi_link *);
int (*ioctl)(struct scsi_link *, u_long, caddr_t, int);
};
struct scsi_iopool;
struct scsi_iohandler {
TAILQ_ENTRY(scsi_iohandler) q_entry;
u_int q_state;
struct scsi_iopool *pool;
void (*handler)(void *, void *);
void *cookie;
};
TAILQ_HEAD(scsi_runq, scsi_iohandler);
struct scsi_iopool {
void *iocookie;
void *(*io_get)(void *);
void (*io_put)(void *, void *);
struct scsi_runq queue;
u_int running;
struct mutex mtx;
};
struct scsi_xshandler {
struct scsi_iohandler ioh;
struct scsi_link *link;
void (*handler)(struct scsi_xfer *);
};
struct scsi_link {
SLIST_ENTRY(scsi_link) bus_list;
u_int state;
#define SDEV_S_DYING (1<<1)
u_int16_t target;
u_int16_t lun;
u_int16_t openings;
u_int64_t port_wwn;
u_int64_t node_wwn;
u_int16_t flags;
#define SDEV_REMOVABLE 0x0001
#define SDEV_MEDIA_LOADED 0x0002
#define SDEV_READONLY 0x0004
#define SDEV_OPEN 0x0008
#define SDEV_DBX 0x00f0
#define SDEV_EJECTING 0x0100
#define SDEV_ATAPI 0x0200
#define SDEV_UMASS 0x0400
#define SDEV_VIRTUAL 0x0800
#define SDEV_OWN_IOPL 0x1000
#define SDEV_UFI 0x2000
u_int16_t quirks;
#define SDEV_AUTOSAVE 0x0001
#define SDEV_NOSYNC 0x0002
#define SDEV_NOWIDE 0x0004
#define SDEV_NOTAGS 0x0008
#define SDEV_NOSYNCCACHE 0x0010
#define ADEV_NOSENSE 0x0020
#define ADEV_LITTLETOC 0x0040
#define ADEV_NOCAPACITY 0x0080
#define ADEV_NODOORLOCK 0x0100
int (*interpret_sense)(struct scsi_xfer *);
void *device_softc;
struct scsibus_softc *bus;
struct scsi_inquiry_data inqdata;
struct devid *id;
struct scsi_runq queue;
u_int running;
u_short pending;
struct scsi_iopool *pool;
};
int scsiprint(void *, const char *);
struct scsi_inquiry_pattern {
u_int8_t type;
int removable;
char *vendor;
char *product;
char *revision;
};
struct scsibus_attach_args {
const struct scsi_adapter *saa_adapter;
void *saa_adapter_softc;
struct scsi_iopool *saa_pool;
u_int64_t saa_wwpn;
u_int64_t saa_wwnn;
u_int16_t saa_quirks;
u_int16_t saa_flags;
u_int16_t saa_openings;
u_int16_t saa_adapter_target;
#define SDEV_NO_ADAPTER_TARGET 0xffff
u_int16_t saa_adapter_buswidth;
u_int8_t saa_luns;
};
struct scsibus_softc {
struct device sc_dev;
SLIST_HEAD(, scsi_link) sc_link_list;
void *sb_adapter_softc;
const struct scsi_adapter *sb_adapter;
struct scsi_iopool *sb_pool;
u_int16_t sb_quirks;
u_int16_t sb_flags;
u_int16_t sb_openings;
u_int16_t sb_adapter_buswidth;
u_int16_t sb_adapter_target;
u_int8_t sb_luns;
};
struct scsi_attach_args {
struct scsi_link *sa_sc_link;
};
struct scsi_xfer {
SIMPLEQ_ENTRY(scsi_xfer) xfer_list;
int flags;
struct scsi_link *sc_link;
int retries;
int timeout;
struct scsi_generic cmd;
int cmdlen;
u_char *data;
int datalen;
size_t resid;
int error;
struct buf *bp;
struct scsi_sense_data sense;
u_int8_t status;
struct timeout stimeout;
void *cookie;
void (*done)(struct scsi_xfer *);
void *io;
};
SIMPLEQ_HEAD(scsi_xfer_list, scsi_xfer);
#define SCSI_NOSLEEP 0x00001
#define SCSI_POLL 0x00002
#define SCSI_AUTOCONF 0x00003
#define ITSDONE 0x00008
#define SCSI_SILENT 0x00020
#define SCSI_IGNORE_NOT_READY 0x00040
#define SCSI_IGNORE_MEDIA_CHANGE 0x00080
#define SCSI_IGNORE_ILLEGAL_REQUEST 0x00100
#define SCSI_RESET 0x00200
#define SCSI_DATA_IN 0x00800
#define SCSI_DATA_OUT 0x01000
#define SCSI_TARGET 0x02000
#define SCSI_ESCAPE 0x04000
#define SCSI_PRIVATE 0xf0000
#define SCSI_OP_TARGET 0x0001
#define SCSI_OP_RESET 0x0002
#define SCSI_OP_BDINFO 0x0003
#define XS_NOERROR 0
#define XS_SENSE 1
#define XS_DRIVER_STUFFUP 2
#define XS_SELTIMEOUT 3
#define XS_TIMEOUT 4
#define XS_BUSY 5
#define XS_SHORTSENSE 6
#define XS_RESET 8
#define TEST_READY_RETRIES 5
#define SCSI_RETRIES 4
const void *scsi_inqmatch(struct scsi_inquiry_data *, const void *, int,
int, int *);
void scsi_init(void);
int scsi_test_unit_ready(struct scsi_link *, int, int);
int scsi_inquire(struct scsi_link *, struct scsi_inquiry_data *, int);
int scsi_read_cap_10(struct scsi_link *, struct scsi_read_cap_data *, int);
int scsi_read_cap_16(struct scsi_link *, struct scsi_read_cap_data_16 *,
int);
int scsi_inquire_vpd(struct scsi_link *, void *, u_int, u_int8_t, int);
void scsi_init_inquiry(struct scsi_xfer *, u_int8_t, u_int8_t,
void *, size_t);
int scsi_prevent(struct scsi_link *, int, int);
int scsi_start(struct scsi_link *, int, int);
void scsi_parse_blkdesc(struct scsi_link *, union scsi_mode_sense_buf *, int,
u_int32_t *, u_int64_t *, u_int32_t *);
int scsi_do_mode_sense(struct scsi_link *, int,
union scsi_mode_sense_buf *, void **, int, int, int *);
void scsi_parse_blkdesc(struct scsi_link *, union scsi_mode_sense_buf *, int,
u_int32_t *, u_int64_t *, u_int32_t *);
int scsi_mode_select(struct scsi_link *, int, struct scsi_mode_header *,
int, int);
int scsi_mode_select_big(struct scsi_link *, int,
struct scsi_mode_header_big *, int, int);
void scsi_copy_internal_data(struct scsi_xfer *, void *, size_t);
void scsi_done(struct scsi_xfer *);
int scsi_do_ioctl(struct scsi_link *, u_long, caddr_t, int);
void sc_print_addr(struct scsi_link *);
int scsi_report_luns(struct scsi_link *, int,
struct scsi_report_luns_data *, u_int32_t, int, int);
int scsi_interpret_sense(struct scsi_xfer *);
void scsi_print_sense(struct scsi_xfer *);
void scsi_strvis(u_char *, u_char *, int);
int scsi_delay(struct scsi_xfer *, int);
int scsi_probe(struct scsibus_softc *, int, int);
int scsi_probe_bus(struct scsibus_softc *);
int scsi_probe_target(struct scsibus_softc *, int);
int scsi_probe_lun(struct scsibus_softc *, int, int);
int scsi_detach(struct scsibus_softc *, int, int, int);
int scsi_detach_target(struct scsibus_softc *, int, int);
int scsi_detach_lun(struct scsibus_softc *, int, int, int);
int scsi_req_probe(struct scsibus_softc *, int, int);
int scsi_req_detach(struct scsibus_softc *, int, int, int);
int scsi_activate(struct scsibus_softc *, int, int, int);
struct scsi_link * scsi_get_link(struct scsibus_softc *, int, int);
#define SID_ANSII_REV(x) ((x)->version & SID_ANSII)
#define SID_RESPONSE_FORMAT(x) ((x)->response_format & SID_RESPONSE_DATA_FMT)
#define SCSI_REV_0 0x00
#define SCSI_REV_1 0x01
#define SCSI_REV_2 0x02
#define SCSI_REV_SPC 0x03
#define SCSI_REV_SPC2 0x04
#define SCSI_REV_SPC3 0x05
#define SCSI_REV_SPC4 0x06
#define SCSI_REV_SPC5 0x07
struct scsi_xfer * scsi_xs_get(struct scsi_link *, int);
void scsi_xs_exec(struct scsi_xfer *);
int scsi_xs_sync(struct scsi_xfer *);
void scsi_xs_put(struct scsi_xfer *);
void scsi_iopool_init(struct scsi_iopool *, void *,
void *(*)(void *), void (*)(void *, void *));
void scsi_iopool_run(struct scsi_iopool *);
void scsi_iopool_destroy(struct scsi_iopool *);
void scsi_link_shutdown(struct scsi_link *);
void * scsi_io_get(struct scsi_iopool *, int);
void scsi_io_put(struct scsi_iopool *, void *);
#define SCSI_IOPOOL_POISON ((void *)0x5c5)
void * scsi_default_get(void *);
void scsi_default_put(void *, void *);
void scsi_ioh_set(struct scsi_iohandler *, struct scsi_iopool *,
void (*)(void *, void *), void *);
int scsi_ioh_add(struct scsi_iohandler *);
int scsi_ioh_del(struct scsi_iohandler *);
void scsi_xsh_set(struct scsi_xshandler *, struct scsi_link *,
void (*)(struct scsi_xfer *));
int scsi_xsh_add(struct scsi_xshandler *);
int scsi_xsh_del(struct scsi_xshandler *);
int scsi_pending_start(struct mutex *, u_int *);
int scsi_pending_finish(struct mutex *, u_int *);
void scsi_cmd_rw_decode(struct scsi_generic *, u_int64_t *, u_int32_t *);
#endif
#endif