/* $NetBSD: scsipiconf.h,v 1.133 2024/10/29 15:50:07 nat Exp $ */ /*- * Copyright (c) 1998, 1999, 2000, 2004 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace * Simulation Facility, NASA Ames Research Center. * * 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. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. */ /* * Originally 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. * * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 */ #ifndef _DEV_SCSIPI_SCSIPICONF_H_ #define _DEV_SCSIPI_SCSIPICONF_H_ typedef int boolean; #include #include #include #include #include struct buf; struct proc; struct device; struct scsipi_channel; struct scsipi_periph; struct scsipi_xfer; /* * The following defines the scsipi_xfer queue. */ TAILQ_HEAD(scsipi_xfer_queue, scsipi_xfer); struct scsipi_generic { u_int8_t opcode; u_int8_t bytes[15]; }; /* * scsipi_async_event_t: * * Asynchronous events from the adapter to the mid-layer and * peripheral. * * Arguments: * * ASYNC_EVENT_MAX_OPENINGS scsipi_max_openings * -- max * openings, device specified in * parameters * * ASYNC_EVENT_XFER_MODE scsipi_xfer_mode * -- xfer mode * parameters changed for I_T Nexus * ASYNC_EVENT_RESET NULL - channel has been reset */ typedef enum { ASYNC_EVENT_MAX_OPENINGS, /* set max openings on periph */ ASYNC_EVENT_XFER_MODE, /* xfer mode update for I_T */ ASYNC_EVENT_RESET /* channel reset */ } scsipi_async_event_t; /* * scsipi_max_openings: * * Argument for an ASYNC_EVENT_MAX_OPENINGS event. */ struct scsipi_max_openings { int mo_target; /* openings are for this target... */ int mo_lun; /* ...and this lun */ int mo_openings; /* openings value */ }; /* * scsipi_xfer_mode: * * Argument for an ASYNC_EVENT_XFER_MODE event. */ struct scsipi_xfer_mode { int xm_target; /* target, for I_T Nexus */ int xm_mode; /* PERIPH_CAP* bits */ int xm_period; /* sync period */ int xm_offset; /* sync offset */ }; /* * scsipi_adapter_req_t: * * Requests that can be made of an adapter. * * Arguments: * * ADAPTER_REQ_RUN_XFER scsipi_xfer * -- the xfer which * is to be run * * ADAPTER_REQ_GROW_RESOURCES no argument * * ADAPTER_REQ_SET_XFER_MODE scsipi_xfer_mode * -- set the xfer * mode for the I_T Nexus according to * this */ typedef enum { ADAPTER_REQ_RUN_XFER, /* run a scsipi_xfer */ ADAPTER_REQ_GROW_RESOURCES, /* grow xfer execution resources */ ADAPTER_REQ_SET_XFER_MODE /* set xfer mode */ } scsipi_adapter_req_t; #ifdef _KERNEL /* * scsipi_periphsw: * * Callbacks into periph driver from midlayer. * * psw_error Called by the bustype's interpret-sense routine * to do periph-specific sense handling. * * psw_start Called by midlayer to restart a device once * more command openings become available. * * psw_async Called by midlayer when an asynchronous event * from the adapter occurs. * * psw_done Called by the midlayer when an xfer has completed. */ struct scsipi_periphsw { int (*psw_error)(struct scsipi_xfer *); void (*psw_start)(struct scsipi_periph *); int (*psw_async)(struct scsipi_periph *, scsipi_async_event_t, void *); void (*psw_done)(struct scsipi_xfer *, int); }; struct disk_parms; struct scsipi_inquiry_pattern; /* * scsipi_adapter: * * This structure describes an instance of a SCSIPI adapter. * * Note that `adapt_openings' is used by (the common case of) adapters * which have per-adapter resources. If an adapter's command resources * are associated with a channel, then the `chan_openings' below will * be used instead. * * Note that all adapter entry points take a pointer to a channel, * as an adapter may have more than one channel, and the channel * structure contains the channel number. */ struct scsipi_adapter { device_t adapt_dev; /* pointer to adapter's device */ int adapt_nchannels; /* number of adapter channels */ volatile int adapt_refcnt; /* adapter's reference count */ int adapt_openings; /* total # of command openings */ int adapt_max_periph; /* max openings per periph */ int adapt_flags; void (*adapt_request)(struct scsipi_channel *, scsipi_adapter_req_t, void *); void (*adapt_minphys)(struct buf *); int (*adapt_ioctl)(struct scsipi_channel *, u_long, void *, int, struct proc *); int (*adapt_enable)(device_t, int); int (*adapt_getgeom)(struct scsipi_periph *, struct disk_parms *, u_long); int (*adapt_accesschk)(struct scsipi_periph *, struct scsipi_inquiry_pattern *); kmutex_t adapt_mtx; volatile int adapt_running; /* how many users of mutex */ }; /* adapt_flags */ #define SCSIPI_ADAPT_POLL_ONLY 0x01 /* Adaptor can't do interrupts. */ #define SCSIPI_ADAPT_MPSAFE 0x02 /* Adaptor doesn't need kernel lock */ void scsipi_adapter_minphys(struct scsipi_channel *, struct buf *); void scsipi_adapter_request(struct scsipi_channel *, scsipi_adapter_req_t, void *); int scsipi_adapter_ioctl(struct scsipi_channel *, u_long, void *, int, struct proc *); int scsipi_adapter_enable(struct scsipi_adapter *, int); #endif /* * scsipi_bustype: * * This structure describes a SCSIPI bus type. * The bustype_type member is shared with struct ata_bustype * (because we can ata, atapi or scsi busses to the same controller) */ struct scsipi_bustype { int bustype_type; /* symbolic name of type */ void (*bustype_cmd)(struct scsipi_xfer *); int (*bustype_interpret_sense)(struct scsipi_xfer *); void (*bustype_printaddr)(struct scsipi_periph *); void (*bustype_kill_pending)(struct scsipi_periph *); void (*bustype_async_event_xfer_mode)(struct scsipi_channel *, void *); }; /* bustype_type */ /* type is stored in the first byte */ #define SCSIPI_BUSTYPE_TYPE_SHIFT 0 #define SCSIPI_BUSTYPE_TYPE(x) (((x) >> SCSIPI_BUSTYPE_TYPE_SHIFT) & 0xff) #define SCSIPI_BUSTYPE_SCSI 0 /* parallel SCSI */ #define SCSIPI_BUSTYPE_ATAPI 1 /* #define SCSIPI_BUSTYPE_ATA 2 */ /* subtype is stored in the second byte */ #define SCSIPI_BUSTYPE_SUBTYPE_SHIFT 8 #define SCSIPI_BUSTYPE_SUBTYPE(x) (((x) >> SCSIPI_BUSTYPE_SUBTYPE_SHIFT) & 0xff) #define SCSIPI_BUSTYPE_BUSTYPE(t, s) \ ((t) << SCSIPI_BUSTYPE_TYPE_SHIFT | (s) << SCSIPI_BUSTYPE_SUBTYPE_SHIFT) /* subtypes are defined in each bus type headers */ /* * scsipi_channel: * * This structure describes a single channel of a SCSIPI adapter. * An adapter may have one or more channels. See the comment above * regarding the resource counter. * Note: chan_bustype has to be first member, as its bustype_type member * is shared with the aa_bustype member of struct ata_atapi_attach. */ #define SCSIPI_CHAN_PERIPH_BUCKETS 16 #define SCSIPI_CHAN_PERIPH_HASHMASK (SCSIPI_CHAN_PERIPH_BUCKETS - 1) #ifdef _KERNEL struct scsipi_channel { const struct scsipi_bustype *chan_bustype; /* channel's bus type */ const char *chan_name; /* this channel's name */ struct scsipi_adapter *chan_adapter; /* pointer to our adapter */ /* Periphs for this channel. */ LIST_HEAD(, scsipi_periph) chan_periphtab[SCSIPI_CHAN_PERIPH_BUCKETS]; int chan_channel; /* channel number */ int chan_flags; /* channel flags */ int chan_openings; /* number of command openings */ int chan_max_periph; /* max openings per periph */ int chan_ntargets; /* number of targets */ int chan_nluns; /* number of luns */ int chan_id; /* adapter's ID for this channel */ int chan_defquirks; /* default device's quirks */ struct lwp *chan_dthread; /* discovery thread */ struct lwp *chan_thread; /* completion thread */ int chan_tflags; /* flags for the completion thread */ int chan_qfreeze; /* freeze count for queue */ /* Job queue for this channel. */ struct scsipi_xfer_queue chan_queue; /* Completed (async) jobs. */ struct scsipi_xfer_queue chan_complete; /* callback we may have to call from completion thread */ void (*chan_callback)(struct scsipi_channel *, void *); void *chan_callback_arg; /* callback we may have to call after forking the kthread */ void (*chan_init_cb)(struct scsipi_channel *, void *); void *chan_init_cb_arg; kcondvar_t chan_cv_comp; kcondvar_t chan_cv_thr; kcondvar_t chan_cv_xs; #define chan_cv_complete(ch) (&(ch)->chan_cv_comp) #define chan_cv_thread(ch) (&(ch)->chan_cv_thr) }; #define chan_running(ch) ((ch)->chan_adapter->adapt_running) #define chan_mtx(ch) (&(ch)->chan_adapter->adapt_mtx) #endif /* chan_flags */ #define SCSIPI_CHAN_OPENINGS 0x01 /* use chan_openings */ #define SCSIPI_CHAN_CANGROW 0x02 /* channel can grow resources */ #define SCSIPI_CHAN_NOSETTLE 0x04 /* don't wait for devices to settle */ #define SCSIPI_CHAN_TACTIVE 0x08 /* completion thread is active */ /* chan thread flags (chan_tflags) */ #define SCSIPI_CHANT_SHUTDOWN 0x01 /* channel is shutting down */ #define SCSIPI_CHANT_CALLBACK 0x02 /* has to call chan_callback() */ #define SCSIPI_CHANT_KICK 0x04 /* need to run queues */ #define SCSIPI_CHANT_GROWRES 0x08 /* call ADAPTER_REQ_GROW_RESOURCES */ #define SCSIPI_CHAN_MAX_PERIPH(chan) \ (((chan)->chan_flags & SCSIPI_CHAN_OPENINGS) ? \ (chan)->chan_max_periph : (chan)->chan_adapter->adapt_max_periph) #define scsipi_printaddr(periph) \ (*(periph)->periph_channel->chan_bustype->bustype_printaddr)((periph)) #define scsipi_periph_bustype(periph) \ (periph)->periph_channel->chan_bustype->bustype_type /* * Number of tag words in a periph structure: * * n_tag_words = ((256 / NBBY) / sizeof(u_int32_t)) */ #define PERIPH_NTAGWORDS ((256 / 8) / sizeof(u_int32_t)) #ifdef _KERNEL /* * scsipi_opcodes: * This optionally allocated structure documents * valid opcodes and timeout values for the respective * opcodes overriding the requested timeouts. * It is created when SCSI_MAINTENANCE_IN/ * RSOC_REPORT_SUPPORTED_OPCODES can provide information * at attach time. */ struct scsipi_opcodes { struct scsipi_opinfo { long ti_timeout; /* timeout in seconds (> 0 => VALID) */ unsigned long ti_flags; #define SCSIPI_TI_VALID 0x0001 /* valid op code */ #define SCSIPI_TI_LOGGED 0x8000 /* override logged during debug */ } opcode_info[0x100]; }; /* * scsipi_periph: * * This structure describes the path between a peripheral device * and an adapter. It contains a pointer to the adapter channel * which in turn contains a pointer to the adapter. * * XXX Given the way NetBSD's autoconfiguration works, this is ... * XXX nasty. * * Well, it's a lot nicer than it used to be, but there could * still be an improvement. */ struct scsipi_periph { device_t periph_dev; /* pointer to peripheral's device */ struct scsipi_channel *periph_channel; /* channel we're connected to */ /* link in channel's table of periphs */ LIST_ENTRY(scsipi_periph) periph_hash; const struct scsipi_periphsw *periph_switch; /* peripheral's entry points */ int periph_openings; /* max # of outstanding commands */ int periph_active; /* current # of outstanding commands */ int periph_sent; /* current # of commands sent to adapt*/ int periph_mode; /* operation modes, CAP bits */ int periph_period; /* sync period (factor) */ int periph_offset; /* sync offset */ /* * Information gleaned from the inquiry data. */ u_int8_t periph_type; /* basic device type */ int periph_cap; /* capabilities */ int periph_quirks; /* device's quirks */ int periph_flags; /* misc. flags */ int periph_dbflags; /* debugging flags */ int periph_target; /* target ID (drive # on ATAPI) */ int periph_lun; /* LUN (not used on ATAPI) */ int periph_version; /* ANSI SCSI version */ int periph_qfreeze; /* queue freeze count */ /* available opcodes and timeout information */ struct scsipi_opcodes *periph_opcs; /* Bitmap of free command tags. */ u_int32_t periph_freetags[PERIPH_NTAGWORDS]; /* Pending scsipi_xfers on this peripheral. */ struct scsipi_xfer_queue periph_xferq; callout_t periph_callout; /* xfer which has a pending CHECK_CONDITION */ struct scsipi_xfer *periph_xscheck; kcondvar_t periph_cv; #define periph_cv_periph(p) (&(p)->periph_cv) #define periph_cv_active(p) (&(p)->periph_cv) }; #endif /* * Macro to return the current xfer mode of a periph. */ #define PERIPH_XFER_MODE(periph) \ (((periph)->periph_flags & PERIPH_MODE_VALID) ? \ (periph)->periph_mode : 0) /* periph_cap */ #define PERIPH_CAP_ANEC 0x0001 /* async event notification */ #define PERIPH_CAP_TERMIOP 0x0002 /* terminate i/o proc. messages */ #define PERIPH_CAP_RELADR 0x0004 /* relative addressing */ #define PERIPH_CAP_WIDE32 0x0008 /* wide-32 transfers */ #define PERIPH_CAP_WIDE16 0x0010 /* wide-16 transfers */ /* XXX 0x0020 reserved for ATAPI_CFG_DRQ_MASK */ /* XXX 0x0040 reserved for ATAPI_CFG_DRQ_MASK */ #define PERIPH_CAP_SYNC 0x0080 /* synchronous transfers */ #define PERIPH_CAP_LINKCMDS 0x0100 /* linked commands */ #define PERIPH_CAP_TQING 0x0200 /* tagged queueing */ #define PERIPH_CAP_SFTRESET 0x0400 /* soft RESET condition response */ #define PERIPH_CAP_CMD16 0x0800 /* 16 byte commands (ATAPI) */ #define PERIPH_CAP_DT 0x1000 /* supports DT clock */ #define PERIPH_CAP_QAS 0x2000 /* supports quick arbit. and select. */ #define PERIPH_CAP_IUS 0x4000 /* supports information unit xfers */ /* periph_flags */ #define PERIPH_REMOVABLE 0x0001 /* media is removable */ #define PERIPH_MEDIA_LOADED 0x0002 /* media is loaded */ #define PERIPH_WAITING 0x0004 /* process waiting for opening */ #define PERIPH_OPEN 0x0008 /* device is open */ #define PERIPH_WAITDRAIN 0x0010 /* waiting for pending xfers to drain */ #define PERIPH_GROW_OPENINGS 0x0020 /* allow openings to grow */ #define PERIPH_MODE_VALID 0x0040 /* periph_mode is valid */ #define PERIPH_RECOVERING 0x0080 /* periph is recovering */ #define PERIPH_RECOVERY_ACTIVE 0x0100 /* a recovery command is active */ #define PERIPH_KEEP_LABEL 0x0200 /* retain label after 'full' close */ #define PERIPH_SENSE 0x0400 /* periph has sense pending */ #define PERIPH_UNTAG 0x0800 /* untagged command running */ /* periph_quirks */ #define PQUIRK_AUTOSAVE 0x00000001 /* do implicit SAVE POINTERS */ #define PQUIRK_NOSYNC 0x00000002 /* does not grok SDTR */ #define PQUIRK_NOWIDE 0x00000004 /* does not grok WDTR */ #define PQUIRK_NOTAG 0x00000008 /* does not grok tagged cmds */ #define PQUIRK_NOLUNS 0x00000010 /* DTWT with LUNs */ #define PQUIRK_FORCELUNS 0x00000020 /* prehistoric device groks LUNs */ #define PQUIRK_NOMODESENSE 0x00000040 /* device doesn't do MODE SENSE properly */ #define PQUIRK_NOSYNCCACHE 0x00000100 /* do not issue SYNC CACHE */ #define PQUIRK_LITTLETOC 0x00000400 /* audio TOC is little-endian */ #define PQUIRK_NOCAPACITY 0x00000800 /* no READ CD CAPACITY */ #define PQUIRK_NOTUR 0x00001000 /* no TEST UNIT READY */ #define PQUIRK_NODOORLOCK 0x00002000 /* can't lock door */ #define PQUIRK_NOSENSE 0x00004000 /* can't REQUEST SENSE */ #define PQUIRK_ONLYBIG 0x00008000 /* only use SCSI_{R,W}_BIG */ #define PQUIRK_NOBIGMODESENSE 0x00040000 /* has no big mode-sense op */ #define PQUIRK_CAP_SYNC 0x00080000 /* SCSI device with ST sync op*/ #define PQUIRK_CAP_WIDE16 0x00100000 /* SCSI device with ST wide op*/ #define PQUIRK_CAP_NODT 0x00200000 /* signals DT, but can't. */ #define PQUIRK_START 0x00400000 /* needs start before tur */ #define PQUIRK_NOFUA 0x00800000 /* does not grok FUA */ #define PQUIRK_NOREPSUPPOPC 0x01000000 /* does not grok REPORT SUPPORTED OPCODES to fetch device timeouts */ #define PQUIRK_NOREADDISCINFO 0x02000000 /* device doesn't do READ_DISCINFO properly */ /* * Error values an adapter driver may return */ typedef enum { XS_NOERROR, /* there is no error, (sense is invalid) */ XS_SENSE, /* Check the returned sense for the error */ XS_SHORTSENSE, /* Check the ATAPI sense for the error */ XS_DRIVER_STUFFUP, /* Driver failed to perform operation */ XS_RESOURCE_SHORTAGE, /* adapter resource shortage */ XS_SELTIMEOUT, /* The device timed out.. turned off? */ XS_TIMEOUT, /* The Timeout reported was caught by SW */ XS_BUSY, /* The device busy, try again later? */ XS_RESET, /* bus was reset; possible retry command */ XS_REQUEUE /* requeue this command */ } scsipi_xfer_result_t; #ifdef _KERNEL /* * Each scsipi transaction is fully described by one of these structures * It includes information about the source of the command and also the * device and adapter for which the command is destined. * * Before the HBA is given this transaction, channel_q is the linkage on * the related channel's chan_queue. * * When the this transaction is taken off the channel's chan_queue and * the HBA's request entry point is called with this transaction, the * HBA can use the channel_q tag for whatever it likes until it calls * scsipi_done for this transaction, at which time it has to stop * using channel_q. * * After scsipi_done is called with this transaction and if there was an * error on it, channel_q then becomes the linkage on the related channel's * chan_complete cqueue. * * The device_q member is maintained by the scsipi middle layer. When * a device issues a command, the xfer is placed on that device's * pending commands queue. When an xfer is done and freed, it is taken * off the device's queue. This allows for a device to wait for all of * its pending commands to complete. */ struct scsipi_xfer { TAILQ_ENTRY(scsipi_xfer) channel_q; /* entry on channel queue */ TAILQ_ENTRY(scsipi_xfer) device_q; /* device's pending xfers */ callout_t xs_callout; /* callout for adapter use */ int xs_control; /* control flags */ volatile int xs_status; /* status flags */ struct scsipi_periph *xs_periph;/* peripheral doing the xfer */ int xs_retries; /* the number of times to retry */ int xs_requeuecnt; /* number of requeues */ int timeout; /* in milliseconds */ struct scsipi_generic *cmd; /* The scsipi command to execute */ int cmdlen; /* how long it is */ u_char *data; /* DMA address OR a uio address */ int datalen; /* data len (blank if uio) */ int resid; /* how much buffer was not touched */ scsipi_xfer_result_t error; /* an error value */ struct buf *bp; /* If we need to associate with */ /* a buf */ union { struct scsi_sense_data scsi_sense; /* 32 bytes */ u_int32_t atapi_sense; } sense; struct scsipi_xfer *xs_sensefor;/* we are requesting sense for this */ /* xfer */ u_int8_t status; /* SCSI status */ /* * Info for tagged command queueing. This may or may not * be used by a given adapter driver. These are the same * as the bytes in the tag message. */ u_int8_t xs_tag_type; /* tag type */ u_int8_t xs_tag_id; /* tag ID */ struct scsipi_generic cmdstore __aligned(4); /* stash the command in here */ #define xs_cv(xs) (&(xs)->xs_periph->periph_channel->chan_cv_xs) }; #endif /* * scsipi_xfer control flags * * To do: * * - figure out what to do with XS_CTL_ESCAPE * * - replace XS_CTL_URGENT with an `xs_priority' field? */ #define XS_CTL_NOSLEEP 0x00000001 /* don't sleep */ #define XS_CTL_POLL 0x00000002 /* poll for completion */ #define XS_CTL_DISCOVERY 0x00000004 /* doing device discovery */ #define XS_CTL_ASYNC 0x00000008 /* command completes asynchronously */ #define XS_CTL_USERCMD 0x00000010 /* user issued command */ #define XS_CTL_SILENT 0x00000020 /* don't print sense info */ #define XS_CTL_IGNORE_NOT_READY 0x00000040 /* ignore NOT READY */ #define XS_CTL_IGNORE_MEDIA_CHANGE \ 0x00000080 /* ignore media change */ #define XS_CTL_IGNORE_ILLEGAL_REQUEST \ 0x00000100 /* ignore ILLEGAL REQUEST */ #define XS_CTL_SILENT_NODEV 0x00000200 /* don't print sense info if sense info is nodev */ #define XS_CTL_RESET 0x00000400 /* reset the device */ #define XS_CTL_DATA_UIO 0x00000800 /* xs_data points to uio */ #define XS_CTL_DATA_IN 0x00001000 /* data coming into memory */ #define XS_CTL_DATA_OUT 0x00002000 /* data going out of memory */ #define XS_CTL_TARGET 0x00004000 /* target mode operation */ #define XS_CTL_ESCAPE 0x00008000 /* escape operation */ #define XS_CTL_URGENT 0x00010000 /* urgent (recovery) operation */ #define XS_CTL_SIMPLE_TAG 0x00020000 /* use a Simple Tag */ #define XS_CTL_ORDERED_TAG 0x00040000 /* use an Ordered Tag */ #define XS_CTL_HEAD_TAG 0x00080000 /* use a Head of Queue Tag */ #define XS_CTL_THAW_PERIPH 0x00100000 /* thaw periph once enqueued */ #define XS_CTL_FREEZE_PERIPH 0x00200000 /* freeze periph when done */ #define XS_CTL_REQSENSE 0x00800000 /* xfer is a request sense */ #define XS_CTL_TAGMASK (XS_CTL_SIMPLE_TAG|XS_CTL_ORDERED_TAG|XS_CTL_HEAD_TAG) #define XS_CTL_TAGTYPE(xs) ((xs)->xs_control & XS_CTL_TAGMASK) /* * scsipi_xfer status flags */ #define XS_STS_DONE 0x00000001 /* scsipi_xfer is done */ #define XS_STS_PRIVATE 0xf0000000 /* reserved for HBA's use */ /* * This describes matching information for scsipi_inqmatch(). The more things * match, the higher the configuration priority. */ struct scsipi_inquiry_pattern { u_int8_t type; boolean removable; const char *vendor; const char *product; const char *revision; }; /* * This is used to pass information from the high-level configuration code * to the device-specific drivers. */ struct scsipibus_attach_args { struct scsipi_periph *sa_periph; struct scsipi_inquiry_pattern sa_inqbuf; struct scsipi_inquiry_data *sa_inqptr; union { /* bus-type specific infos */ u_int8_t scsi_version; /* SCSI version */ } scsipi_info; }; /* * this describes a quirk entry */ struct scsi_quirk_inquiry_pattern { struct scsipi_inquiry_pattern pattern; int quirks; }; /* * Default number of retries, used for generic routines. */ #define SCSIPIRETRIES 4 #ifdef _KERNEL void scsipi_init(void); void scsipi_ioctl_init(void); void scsipi_load_verbose(void); int scsipi_command(struct scsipi_periph *, struct scsipi_generic *, int, u_char *, int, int, int, struct buf *, int); void scsipi_create_completion_thread(void *); const void *scsipi_inqmatch(struct scsipi_inquiry_pattern *, const void *, size_t, size_t, int *); const char *scsipi_dtype(int); int scsipi_execute_xs(struct scsipi_xfer *); int scsipi_test_unit_ready(struct scsipi_periph *, int); int scsipi_prevent(struct scsipi_periph *, int, int); int scsipi_inquire(struct scsipi_periph *, struct scsipi_inquiry_data *, int); int scsipi_mode_select(struct scsipi_periph *, int, struct scsi_mode_parameter_header_6 *, int, int, int, int); int scsipi_mode_select_big(struct scsipi_periph *, int, struct scsi_mode_parameter_header_10 *, int, int, int, int); int scsipi_mode_sense(struct scsipi_periph *, int, int, struct scsi_mode_parameter_header_6 *, int, int, int, int); int scsipi_mode_sense_big(struct scsipi_periph *, int, int, struct scsi_mode_parameter_header_10 *, int, int, int, int); int scsipi_start(struct scsipi_periph *, int, int); void scsipi_done(struct scsipi_xfer *); void scsipi_user_done(struct scsipi_xfer *); int scsipi_interpret_sense(struct scsipi_xfer *); void scsipi_wait_drain(struct scsipi_periph *); void scsipi_kill_pending(struct scsipi_periph *); void scsipi_get_opcodeinfo(struct scsipi_periph *periph); void scsipi_free_opcodeinfo(struct scsipi_periph *periph); struct scsipi_periph *scsipi_alloc_periph(int); void scsipi_free_periph(struct scsipi_periph *); /* Function pointers for scsiverbose module */ extern int (*scsipi_print_sense)(struct scsipi_xfer *, int); extern void (*scsipi_print_sense_data)(struct scsi_sense_data *, int); int scsipi_print_sense_stub(struct scsipi_xfer *, int); void scsipi_print_sense_data_stub(struct scsi_sense_data *, int); extern int scsi_verbose_loaded; void scsipi_print_cdb(struct scsipi_generic *cmd); int scsipi_thread_call_callback(struct scsipi_channel *, void (*callback)(struct scsipi_channel *, void *), void *); void scsipi_async_event(struct scsipi_channel *, scsipi_async_event_t, void *); int scsipi_do_ioctl(struct scsipi_periph *, dev_t, u_long, void *, int, struct lwp *); void scsipi_set_xfer_mode(struct scsipi_channel *, int, int); int scsipi_channel_init(struct scsipi_channel *); void scsipi_channel_shutdown(struct scsipi_channel *); void scsipi_insert_periph(struct scsipi_channel *, struct scsipi_periph *); void scsipi_remove_periph(struct scsipi_channel *, struct scsipi_periph *); struct scsipi_periph *scsipi_lookup_periph(struct scsipi_channel *, int, int); struct scsipi_periph *scsipi_lookup_periph_locked(struct scsipi_channel *, int, int); int scsipi_target_detach(struct scsipi_channel *, int, int, int); int scsipi_adapter_addref(struct scsipi_adapter *); void scsipi_adapter_delref(struct scsipi_adapter *); void scsipi_channel_freeze(struct scsipi_channel *, int); void scsipi_channel_thaw(struct scsipi_channel *, int); void scsipi_channel_timed_thaw(void *); void scsipi_periph_freeze(struct scsipi_periph *, int); void scsipi_periph_thaw(struct scsipi_periph *, int); void scsipi_periph_timed_thaw(void *); void scsipi_periph_freeze_locked(struct scsipi_periph *, int); void scsipi_periph_thaw_locked(struct scsipi_periph *, int); int scsipi_sync_period_to_factor(int); int scsipi_sync_factor_to_period(int); int scsipi_sync_factor_to_freq(int); void show_scsipi_xs(struct scsipi_xfer *); void show_scsipi_cmd(struct scsipi_xfer *); void show_mem(u_char *, int); #endif /* _KERNEL */ 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(const u_int8_t *bytes) { u_int32_t rv; rv = (bytes[0] << 8) | bytes[1]; return (rv); } static __inline u_int32_t _3btol(const 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(const u_int8_t *bytes) { u_int32_t rv; rv = ((u_int32_t)bytes[0] << 24) | ((u_int32_t)bytes[1] << 16) | ((u_int32_t)bytes[2] << 8) | (u_int32_t)bytes[3]; return (rv); } static __inline u_int64_t _5btol(const 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(const 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); } static __inline void _lto2l(u_int32_t val, u_int8_t *bytes) { bytes[0] = val & 0xff; bytes[1] = (val >> 8) & 0xff; } static __inline void _lto3l(u_int32_t val, u_int8_t *bytes) { bytes[0] = val & 0xff; bytes[1] = (val >> 8) & 0xff; bytes[2] = (val >> 16) & 0xff; } static __inline void _lto4l(u_int32_t val, u_int8_t *bytes) { bytes[0] = val & 0xff; bytes[1] = (val >> 8) & 0xff; bytes[2] = (val >> 16) & 0xff; bytes[3] = (val >> 24) & 0xff; } static __inline u_int32_t _2ltol(const u_int8_t *bytes) { u_int32_t rv; rv = bytes[0] | (bytes[1] << 8); return (rv); } static __inline u_int32_t _3ltol(const u_int8_t *bytes) { u_int32_t rv; rv = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16); return (rv); } static __inline u_int32_t _4ltol(const u_int8_t *bytes) { u_int32_t rv; rv = (u_int32_t)bytes[0] | ((u_int32_t)bytes[1] << 8) | ((u_int32_t)bytes[2] << 16) | ((u_int32_t)bytes[3] << 24); return (rv); } #endif /* _DEV_SCSIPI_SCSIPICONF_H_ */