diff options
author | non <non@FreeBSD.org> | 2000-10-23 12:55:51 +0000 |
---|---|---|
committer | non <non@FreeBSD.org> | 2000-10-23 12:55:51 +0000 |
commit | 8e8d8815fad836120f63c84071f89cb9552db1e2 (patch) | |
tree | a86ab047759aa8e4af097dccf6d2615932b9bc7e /sys/cam/scsi/scsi_low.h | |
parent | 7885ad000050949f99433ec9baa0babf83709052 (diff) | |
download | FreeBSD-src-8e8d8815fad836120f63c84071f89cb9552db1e2.zip FreeBSD-src-8e8d8815fad836120f63c84071f89cb9552db1e2.tar.gz |
Add PC-Card/ISA SCSI host adpater drivers from NetBSD/pc98
(a NetBSD port for NEC PC-98x1 machines). They are ncv for NCR 53C500,
nsp for Workbit Ninja SCSI-3, and stg for TMC 18C30 and 18C50.
I thank NetBSD/pc98 and bsd-nomads people.
Obtained from: NetBSD/pc98
Diffstat (limited to 'sys/cam/scsi/scsi_low.h')
-rw-r--r-- | sys/cam/scsi/scsi_low.h | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/sys/cam/scsi/scsi_low.h b/sys/cam/scsi/scsi_low.h new file mode 100644 index 0000000..0d8f996 --- /dev/null +++ b/sys/cam/scsi/scsi_low.h @@ -0,0 +1,615 @@ +/* $FreeBSD$ */ +/* $NecBSD: scsi_low.h,v 1.24 1999/07/23 21:00:05 honda Exp $ */ +/* $NetBSD$ */ + +#define SCSI_LOW_DIAGNOSTIC + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1995, 1996, 1997, 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * Copyright (c) 1995, 1996, 1997, 1998 + * Naofumi HONDA. 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. + * 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. + * 3. 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 ``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 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. + */ + +#ifndef _SCSI_LOW_H_ +#define _SCSI_LOW_H_ + +#ifdef __NetBSD__ +#include <i386/Cbus/dev/scsi_dvcfg.h> +#endif +#ifdef __FreeBSD__ +#include <sys/device_port.h> +#define CAM +#include <cam/cam.h> +#include <cam/cam_ccb.h> +#include <cam/cam_sim.h> +#include <cam/cam_xpt_sim.h> +#include <cam/cam_debug.h> + +#include <cam/scsi/scsi_dvcfg.h> +#endif + +/* user configuration flags defs */ +#define SCSI_LOW_SYNC DVF_SCSI_SYNC +#define SCSI_LOW_DISC DVF_SCSI_DISC +#define SCSI_LOW_WAIT DVF_SCSI_WAIT +#define SCSI_LOW_LINK DVF_SCSI_LINK +#define SCSI_LOW_QTAG DVF_SCSI_QTAG +#define SCSI_LOW_NOPARITY DVF_SCSI_NOPARITY +#define SCSI_LOW_SAVESP DVF_SCSI_SAVESP +#define SCSI_LOW_DEFCFG DVF_SCSI_DEFCFG +#define SCSI_LOW_BITS DVF_SCSI_BITS + +#define SCSI_LOW_PERIOD(n) DVF_SCSI_PERIOD(n) +#define SCSI_LOW_OFFSET(n) DVF_SCSI_OFFSET(n) + +/* host scsi id and targets macro */ +#ifndef SCSI_LOW_NTARGETS +#define SCSI_LOW_NTARGETS 8 +#endif /* SCSI_LOW_NTARGETS */ +#define SCSI_LOW_NCCB 32 + +#define SCSI_LOW_MAX_MSGLEN 16 +#define SCSI_LOW_MAX_RETRY 3 + +/* timeout control macro */ +#define SCSI_LOW_MIN_TOUT 24 +#define SCSI_LOW_TIMEOUT_CHECK_INTERVAL 4 +#define SCSI_LOW_POWDOWN_TC 15 +#define SCSI_LOW_MAX_PHCHANGES 256 + +/* max synch period */ +#ifndef SCSI_LOW_MAX_SYNCH_SPEED +#define SCSI_LOW_MAX_SYNCH_SPEED (100) /* 10.0M */ +#endif /* !SCSI_LOW_MAX_SYNCH_SPEED */ + +/************************************************* + * Scsi Data Pointer + *************************************************/ +/* scsi pointer */ +struct sc_p { + u_int8_t *scp_data; + int scp_datalen; + + u_int8_t *scp_cmd; + int scp_cmdlen; + + u_int scp_direction; +#define SCSI_LOW_RWUNK (-1) +#define SCSI_LOW_WRITE 0 +#define SCSI_LOW_READ 1 +}; + +#define SCSI_LOW_SETUP_PHASE(ti, phase) \ +{ \ + if ((ti)->ti_phase != (phase)) \ + { \ + (ti)->ti_ophase = ti->ti_phase; \ + (ti)->ti_phase = (phase); \ + } \ +} + +#define SCSI_LOW_SETUP_MSGPHASE(slp, PHASE) \ +{ \ + (slp)->sl_msgphase = (PHASE); \ +} + +#define SCSI_LOW_TARGET_ASSERT_ATN(slp) \ +{ \ + (ti)->ti_tflags |= TARG_ASSERT_ATN; \ +} + +/************************************************* + * Command Control Block Structure + *************************************************/ +typedef int scsi_low_tag_t; +struct targ_info; + +#define SCSI_LOW_UNKLUN ((u_int) -1) +#define SCSI_LOW_UNKTAG ((scsi_low_tag_t) -1) + +struct slccb { + TAILQ_ENTRY(slccb) ccb_chain; + +#ifdef CAM + union ccb *ccb; + struct buf *bp; +#else + struct scsipi_xfer *xs; /* scsi upper */ +#endif + struct targ_info *ti; /* targ_info */ + struct lun_info *li; /* lun info */ + scsi_low_tag_t ccb_tag; /* tag */ + + /***************************************** + * Scsi data pointers (original and saved) + *****************************************/ + struct sc_p ccb_scp; /* given */ + struct sc_p ccb_sscp; /* saved scsi data pointer */ + +#ifdef SCSI_LOW_SUPPORT_USER_MSGOUT + u_int8_t msgout[SCSI_LOW_MAX_MSGLEN]; /* scsi msgout */ + u_int msgoutlen; +#endif /* SCSI_LOW_SUPPORT_USER_MSGOUT */ + + /***************************************** + * Error or Timeout counters + *****************************************/ + u_int ccb_flags; +#define CCB_SENSE 0x01 + u_int ccb_error; + + int ccb_rcnt; /* retry counter */ + int ccb_tc; /* timer counter */ + int ccb_tcmax; /* max timeout */ + + /***************************************** + * Sense data buffer + *****************************************/ +#ifdef __NetBSD__ + struct scsipi_sense ccb_sense_cmd; + struct scsipi_sense_data ccb_sense; +#endif +#ifdef __FreeBSD__ + struct scsi_sense ccb_sense_cmd; + struct scsi_sense_data ccb_sense; +#endif +}; + +/* ccb assert */ +#ifdef __NetBSD__ +#include <dev/isa/ccbque.h> +#endif +#ifdef __FreeBSD__ +#include <i386/isa/ccbque.h> +#endif +GENERIC_CCB_ASSERT(scsi_low, slccb) + +/************************************************* + * Target structures + *************************************************/ +struct scsi_low_softc; +TAILQ_HEAD(targ_info_tab, targ_info); +LIST_HEAD(lun_info_tab, lun_info); + +struct lun_info { + int li_lun; + struct targ_info *li_ti; /* my target */ + + LIST_ENTRY(lun_info) lun_chain; /* targ_info link */ + + int li_disc; /* num disconnects */ + int li_maxnexus; + + /* + * lun state + */ +#define UNIT_SLEEP 0x00 +#define UNIT_START 0x01 +#define UNIT_SYNCH 0x02 +#define UNIT_WIDE 0x03 +#define UNIT_OK 0x04 +#define UNIT_NEGSTART UNIT_SYNCH + u_int li_state; /* target lun state */ + u_int li_maxstate; /* max state */ + + /* + * lun control flags + */ + u_int li_flags; /* real control flags */ + u_int li_cfgflags; /* given target cfgflags */ + u_int li_quirks; /* given target quirk */ + + /* + * lun synch and wide data + */ + struct synch { + u_int8_t offset; + u_int8_t period; + } li_maxsynch; /* synch data */ + + u_int li_width; +}; + +struct targ_info { + TAILQ_ENTRY(targ_info) ti_chain; /* targ_info link */ + + struct scsi_low_softc *ti_sc; /* our softc */ + u_int ti_id; /* scsi id */ + + /* + * Lun chain + */ + struct lun_info_tab ti_litab; /* lun chain */ + + /* + * Nexus + */ + struct slccb *ti_nexus; /* current nexus */ + struct lun_info *ti_li; /* current nexus lun_info */ + + /* + * Target status + */ +#define TARG_ASSERT_ATN 0x01 + u_int ti_tflags; /* target state I */ + + /* + * Scsi phase control + */ + struct slccbtab ti_discq; /* disconnect queue */ + +#define PH_NULL 0x00 +#define PH_ARBSTART 0x01 +#define PH_SELSTART 0x02 +#define PH_SELECTED 0x03 +#define PH_CMD 0x04 +#define PH_DATA 0x05 +#define PH_MSGIN 0x06 +#define PH_MSGOUT 0x07 +#define PH_STAT 0x08 +#define PH_DISC 0x09 +#define PH_RESEL 0x0a + u_int ti_phase; /* scsi phase */ + u_int ti_ophase; /* old scsi phase */ + + /* + * Status in + */ + u_int8_t ti_status; /* status in */ + + /* + * Msg in + */ + u_int ti_msginptr; /* msgin ptr */ + u_int ti_msginlen; /* expected msg length */ + u_int8_t ti_msgin[SCSI_LOW_MAX_MSGLEN]; /* msgin buffer */ + u_int ti_sphase; + +#ifdef SCSI_LOW_DIAGNOSTIC +#define MSGIN_HISTORY_LEN 5 + u_int8_t ti_msgin_history[MSGIN_HISTORY_LEN]; + int ti_msgin_hist_pointer; +#endif /* SCSI_LOW_DIAGNOSTIC */ + + /* + * Msg out + */ + u_int ti_msgflags; /* msgs to be asserted */ + u_int ti_omsgflags; /* msgs asserted */ + u_int ti_emsgflags; /* a msg currently asserted */ +#define SCSI_LOW_MSG_RESET 0x00000001 +#define SCSI_LOW_MSG_ABORT 0x00000002 +#define SCSI_LOW_MSG_REJECT 0x00000004 +#define SCSI_LOW_MSG_PARITY 0x00000008 +#define SCSI_LOW_MSG_ERROR 0x00000010 +#define SCSI_LOW_MSG_IDENTIFY 0x00000020 +#define SCSI_LOW_MSG_SYNCH 0x00000040 +#define SCSI_LOW_MSG_WIDE 0x00000080 +#define SCSI_LOW_MSG_USER 0x00000100 +#define SCSI_LOW_MSG_NOOP 0x00000200 +#define SCSI_LOW_MSG_ALL 0xffffffff + + /* msgout buffer */ + u_int8_t ti_msgoutstr[SCSI_LOW_MAX_MSGLEN]; /* scsi msgout */ + u_int ti_msgoutlen; /* msgout strlen */ + + /* + * lun info size. + */ + int ti_lunsize; +}; + +/************************************************* + * COMMON HEADER STRUCTURE + *************************************************/ +struct scsi_low_softc; +typedef struct scsi_low_softc *sc_low_t; + +#define SCSI_LOW_START_OK 0 +#define SCSI_LOW_START_FAIL 1 + +#define SC_LOW_INIT_T (int (*) __P((sc_low_t, int))) +#define SC_LOW_BUSRST_T (void (*) __P((sc_low_t))) +#define SC_LOW_LUN_INIT_T (int (*) __P((sc_low_t, struct targ_info *, struct lun_info *))) +#define SC_LOW_SELECT_T (int (*) __P((sc_low_t, struct slccb *))) +#define SC_LOW_ATTEN_T (void (*) __P((sc_low_t))) +#define SC_LOW_NEXUS_T (int (*) __P((sc_low_t, struct targ_info *))) +#define SC_LOW_MSG_T (int (*) __P((sc_low_t, struct targ_info *, u_int))) +#define SC_LOW_POLL_T (int (*) __P((void *))) +#define SC_LOW_POWER_T (int (*) __P((sc_low_t, u_int))) + +struct scsi_low_funcs { + int (*scsi_low_init) __P((sc_low_t, int)); + void (*scsi_low_bus_reset) __P((sc_low_t)); + int (*scsi_low_lun_init) __P((sc_low_t, struct targ_info *, struct lun_info *)); + + int (*scsi_low_start_bus) __P((sc_low_t, struct slccb *)); + int (*scsi_low_establish_nexus) __P((sc_low_t, struct targ_info *)); + + void (*scsi_low_attention) __P((sc_low_t)); + int (*scsi_low_msg) __P((sc_low_t, struct targ_info *, u_int)); + + int (*scsi_low_poll) __P((void *)); + +#define SCSI_LOW_POWDOWN 1 +#define SCSI_LOW_ENGAGE 2 + int (*scsi_low_power) __P((sc_low_t, u_int)); +}; + +/************************************************* + * SCSI LOW SOFTC + *************************************************/ +struct scsi_low_softc { + DEVPORT_DEVICE sl_dev; + u_char sl_xname[16]; + + /* upper interface */ +#ifdef CAM + struct cam_sim *sim; + struct cam_path *path; +#else + struct scsipi_link sl_link; +#endif + + /* my targets */ + struct targ_info *sl_ti[SCSI_LOW_NTARGETS]; + struct targ_info_tab sl_titab; + + /* current active nexus */ + int sl_nexus_call; + struct targ_info *sl_nexus; + + /* ccb start queue */ + struct slccbtab sl_start; + + /* retry limit and phase change counter */ + int sl_max_retry; + int sl_ph_count; + + /* selection & total num disconnect targets */ + int sl_disc; + struct targ_info *sl_selid; + + /* scsi phased suggested by scsi msg */ + u_int sl_msgphase; +#define MSGPH_NULL 0x00 /* no msg */ +#define MSGPH_DISC 0x01 /* disconnect msg */ +#define MSGPH_CMDC 0x02 /* cmd complete msg */ + + /* error */ +#define FATALIO 0x01 /* generic io error & retry io */ +#define ABORTIO 0x02 /* generic io error & terminate io */ +#define TIMEOUTIO 0x04 /* watch dog timeout */ +#define SELTIMEOUTIO 0x08 /* selection timeout */ +#define PDMAERR 0x10 /* dma xfer error */ +#define MSGERR 0x20 /* msgsys error */ +#define PARITYERR 0x40 /* parity error */ +#define BUSYERR 0x80 /* target busy error */ +#define CMDREJECT 0x100 /* cmd reject error */ +#define SCSI_LOW_ERRORBITS "\020\009cmdrej\008busy\007parity\006msgerr\005pdmaerr\004seltimeout\003timeout\002abort\001fatal" + u_int sl_error; /* error flags */ + + /* current scsi data pointer */ + struct sc_p sl_scp; + + /* power control */ + u_int sl_active; /* host is busy state */ + int sl_powc; /* power down timer counter */ + u_int sl_rstep; /* resume step */ + + /* configuration flags */ + u_int sl_flags; +#define HW_POWDOWN 0x01 +#define HW_RESUME 0x02 +#define HW_PDMASTART 0x04 +#define HW_INACTIVE 0x08 +#define HW_POWERCTRL 0x10 + + u_int sl_cfgflags; +#define CFG_NODISC 0x01 +#define CFG_NOPARITY 0x02 +#define CFG_NOATTEN 0x04 +#define CFG_ASYNC 0x08 +#define CFG_MSGUNIFY 0x10 + + /* host informations */ + u_int sl_hostid; + int sl_nluns; + int sl_ntargs; + int sl_openings; + + /* interface functions */ + struct scsi_low_funcs *sl_funcs; + +#if defined(i386) + u_int sl_irq; /* XXX */ +#endif /* i386 */ +#ifdef __FreeBSD__ + struct callout_handle engage_ch; + struct callout_handle timeout_ch; +#ifdef SCSI_LOW_POWFUNC + struct callout_handle recover_ch; +#endif +#endif /* __FreeBSD__ */ +}; + +/************************************************* + * SCSI LOW service functions + *************************************************/ +/* + * Scsi low attachment function. + */ +int scsi_low_attach __P((struct scsi_low_softc *, int, int, int, int)); +int scsi_low_dettach __P((struct scsi_low_softc *)); + +/* + * Scsi phase "bus service" functions. + * These functions are corresponding to each scsi bus phaeses. + */ +/* nexus abort (selection failed) */ +void scsi_low_clear_nexus __P((struct scsi_low_softc *, struct targ_info *)); +/* msgout phase */ +int scsi_low_msgout __P((struct scsi_low_softc *, struct targ_info *)); +/* msgin phase */ +void scsi_low_msgin __P((struct scsi_low_softc *, struct targ_info *, u_int8_t)); +/* data phase */ +int scsi_low_data __P((struct scsi_low_softc *, struct targ_info *, struct buf **, int)); +/* cmd phase */ +int scsi_low_cmd __P((struct scsi_low_softc *, struct targ_info *)); + +/* reselection phase */ +struct targ_info *scsi_low_reselected __P((struct scsi_low_softc *, u_int)); +/* disconnection phase */ +int scsi_low_disconnected __P((struct scsi_low_softc *, struct targ_info *)); + +/* + * Scsi bus restart function. + * Canncel all established nexuses => scsi system initialized => restart jobs. + */ +#define SCSI_LOW_RESTART_HARD 1 +#define SCSI_LOW_RESTART_SOFT 0 +int scsi_low_restart __P((struct scsi_low_softc *, int, u_char *)); + +/* + * Scsi utility fucntions + */ +/* print current status */ +void scsi_low_print __P((struct scsi_low_softc *, struct targ_info *)); +/* timeout utility (only in used scsi_low_pisa) */ +void scsi_low_timeout __P((void *)); +#define SCSI2_RESET_DELAY 5000000 +#define TWIDDLEWAIT 10000 +/* bus reset utility */ +void scsi_low_bus_reset __P((struct scsi_low_softc *)); + +/************************************************* + * Inline utility + *************************************************/ +static __inline u_int8_t scsi_low_identify __P((struct targ_info *ti)); +static __inline void scsi_low_attention __P((struct scsi_low_softc *, struct targ_info *)); +static __inline int scsi_low_is_msgout_continue __P((struct targ_info *)); +static __inline int scsi_low_assert_msg __P((struct scsi_low_softc *, struct targ_info *, u_int, int)); +static __inline void scsi_low_arbit_win __P((struct scsi_low_softc *, struct targ_info *)); + +static __inline int +scsi_low_is_msgout_continue(ti) + struct targ_info *ti; +{ + + return (ti->ti_msgflags != 0); +} + +static __inline u_int8_t +scsi_low_identify(ti) + struct targ_info *ti; +{ + u_int8_t msg; + struct lun_info *li = ti->ti_li; + + msg = (li->li_flags & SCSI_LOW_DISC) ? 0xc0 : 0x80; + msg |= li->li_lun; + return msg; +} + +#define ID_MSG_SETUP(ti) (scsi_low_identify(ti)) + +static __inline void +scsi_low_attention(slp, ti) + struct scsi_low_softc *slp; + struct targ_info *ti; +{ + + (*slp->sl_funcs->scsi_low_attention) (slp); + SCSI_LOW_TARGET_ASSERT_ATN(slp); +} + +static __inline int +scsi_low_assert_msg(slp, ti, msg, now) + struct scsi_low_softc *slp; + struct targ_info *ti; + u_int msg; + int now; +{ + + ti->ti_msgflags |= msg; + if (now != 0) + scsi_low_attention(slp, ti); + return 0; +} + +static __inline void +scsi_low_arbit_win(slp, ti) + struct scsi_low_softc *slp; + struct targ_info *ti; +{ + + slp->sl_selid = NULL; +} + +/************************************************* + * Message out defs + *************************************************/ +/* XXX: use scsi_message.h */ +#define ST_GOOD 0x00 +#define ST_CHKCOND 0x02 +#define ST_MET 0x04 +#define ST_BUSY 0x08 +#define ST_INTERGOOD 0x10 +#define ST_INTERMET 0x14 +#define ST_CONFLICT 0x18 +#define ST_QUEFULL 0x28 + +#define MSG_COMP 0x00 +#define MSG_EXTEND 0x01 + +#define MKMSG_EXTEND(XLEN, XCODE) ((((u_int)(XLEN)) << NBBY) | ((u_int)(XCODE))) +#define MSG_EXTEND_MDPCODE 0x00 +#define MSG_EXTEND_MDPLEN 0x05 +#define MSG_EXTEND_SYNCHCODE 0x01 +#define MSG_EXTEND_SYNCHLEN 0x03 +#define MSG_EXTEND_WIDECODE 0x03 +#define MSG_EXTEND_WIDELEN 0x02 + +#define MSG_SAVESP 0x02 +#define MSG_RESTORESP 0x03 +#define MSG_DISCON 0x04 +#define MSG_I_ERROR 0x05 +#define MSG_ABORT 0x06 +#define MSG_REJECT 0x07 +#define MSG_NOOP 0x08 +#define MSG_PARITY 0x09 +#define MSG_LCOMP 0x0a +#define MSG_LCOMP_F 0x0b +#define MSG_RESET 0x0c +#ifdef __FreeBSD__ +#undef MSG_IDENTIFY +#endif +#define MSG_IDENTIFY 0x80 + +#define OS_DEPEND(s) (s) +#endif /* !_SCSI_LOW_H_ */ |