isp_freebsd.h revision 66189
150477Speter/* $FreeBSD: head/sys/dev/isp/isp_freebsd.h 66189 2000-09-21 20:16:04Z mjacob $ */ 235388Smjacob/* 348487Smjacob * Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions (CAM version) 465140Smjacob * Copyright (c) 1997, 1998, 1999, 2000 by Matthew Jacob 535388Smjacob * 635388Smjacob * Redistribution and use in source and binary forms, with or without 735388Smjacob * modification, are permitted provided that the following conditions 835388Smjacob * are met: 935388Smjacob * 1. Redistributions of source code must retain the above copyright 1035388Smjacob * notice immediately at the beginning of the file, without modification, 1135388Smjacob * this list of conditions, and the following disclaimer. 1266189Smjacob * 2. The name of the author may not be used to endorse or promote products 1366189Smjacob * derived from this software without specific prior written permission. 1435388Smjacob * 1535388Smjacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1635388Smjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1735388Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1835388Smjacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 1935388Smjacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2035388Smjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2135388Smjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2235388Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2335388Smjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2435388Smjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2535388Smjacob * SUCH DAMAGE. 2635388Smjacob */ 2735388Smjacob#ifndef _ISP_FREEBSD_H 2835388Smjacob#define _ISP_FREEBSD_H 2935388Smjacob 3058100Smjacob#define ISP_PLATFORM_VERSION_MAJOR 5 3164092Smjacob#define ISP_PLATFORM_VERSION_MINOR 3 3239235Sgibbs 3348487Smjacob 3439445Smjacob#include <sys/param.h> 3548487Smjacob#include <sys/param.h> 3648487Smjacob#include <sys/systm.h> 3748487Smjacob#include <sys/kernel.h> 3848487Smjacob#include <sys/queue.h> 3959452Smjacob#include <sys/malloc.h> 4062496Smjacob#include <sys/proc.h> 4139445Smjacob 4248487Smjacob#include <machine/bus_memio.h> 4348487Smjacob#include <machine/bus_pio.h> 4448487Smjacob#include <machine/bus.h> 4548487Smjacob#include <machine/clock.h> 4662496Smjacob#include <machine/cpu.h> 4739445Smjacob 4848487Smjacob#include <cam/cam.h> 4948487Smjacob#include <cam/cam_debug.h> 5048487Smjacob#include <cam/cam_ccb.h> 5148487Smjacob#include <cam/cam_sim.h> 5248487Smjacob#include <cam/cam_xpt.h> 5348487Smjacob#include <cam/cam_xpt_sim.h> 5448487Smjacob#include <cam/cam_debug.h> 5548487Smjacob#include <cam/scsi/scsi_all.h> 5648487Smjacob#include <cam/scsi/scsi_message.h> 5748487Smjacob 5852348Smjacob#include "opt_ddb.h" 5948487Smjacob#include "opt_isp.h" 6039235Sgibbs 6161773Smjacobtypedef void ispfwfunc __P((int, int, int, const u_int16_t **)); 6255366Smjacob 6355366Smjacob#ifdef ISP_TARGET_MODE 6455366Smjacobtypedef struct tstate { 6555366Smjacob struct tstate *next; 6655366Smjacob struct cam_path *owner; 6755366Smjacob struct ccb_hdr_slist atios; 6855366Smjacob struct ccb_hdr_slist inots; 6955366Smjacob lun_id_t lun; 7055366Smjacob u_int32_t hold; 7155366Smjacob} tstate_t; 7255366Smjacob 7355366Smjacob/* 7455366Smjacob * This should work very well for 100% of parallel SCSI cases, 100% 7555366Smjacob * of non-SCCLUN FC cases, and hopefully some larger fraction of the 7655366Smjacob * SCCLUN FC cases. Basically, we index by the low 5 bits of lun and 7755366Smjacob * then linear search. This has to be reasonably zippy, but not crucially 7855366Smjacob * so. 7955366Smjacob */ 8055366Smjacob#define LUN_HASH_SIZE 32 8155366Smjacob#define LUN_HASH_FUNC(lun) ((lun) & 0x1f) 8255366Smjacob 8355366Smjacob#endif 8455366Smjacob 8535388Smjacobstruct isposinfo { 8655366Smjacob struct ispsoftc * next; 8753489Smjacob u_int64_t default_wwn; 8835388Smjacob char name[8]; 8935388Smjacob int unit; 9048487Smjacob struct cam_sim *sim; 9148487Smjacob struct cam_path *path; 9248487Smjacob struct cam_sim *sim2; 9348487Smjacob struct cam_path *path2; 9462496Smjacob struct intr_config_hook ehook; 9562496Smjacob u_int8_t mboxwaiting; 9662496Smjacob u_int8_t simqfrozen; 9765140Smjacob u_int8_t drain; 9865140Smjacob#ifdef SERVICING_INTERRUPT 9965140Smjacob u_int8_t intsok; 10065140Smjacob#else 10165140Smjacob u_int8_t padding; 10265140Smjacob#endif 10365140Smjacob volatile u_int32_t islocked; 10462496Smjacob int splsaved; 10555366Smjacob#ifdef ISP_TARGET_MODE 10655366Smjacob#define TM_WANTED 0x01 10755366Smjacob#define TM_BUSY 0x02 10855366Smjacob#define TM_TMODE_ENABLED 0x80 10955366Smjacob u_int8_t tmflags; 11055366Smjacob u_int8_t rstatus; 11155366Smjacob u_int16_t rollinfo; 11255366Smjacob tstate_t tsdflt; 11355366Smjacob tstate_t *lun_hash[LUN_HASH_SIZE]; 11455366Smjacob#endif 11535388Smjacob}; 11639235Sgibbs 11764092Smjacob/* 11864092Smjacob * Required Macros/Defines 11964092Smjacob */ 12048487Smjacob 12164092Smjacob#define INLINE __inline 12248487Smjacob 12364092Smjacob#define ISP2100_FABRIC 1 12464092Smjacob#define ISP2100_SCRLEN 0x400 12545284Smjacob 12664092Smjacob#define MEMZERO bzero 12764092Smjacob#define MEMCPY(dst, src, amt) bcopy((src), (dst), (amt)) 12864092Smjacob#define SNPRINTF snprintf 12964092Smjacob#define STRNCAT strncat 13064092Smjacob#define USEC_DELAY DELAY 13135388Smjacob 13264092Smjacob#define NANOTIME_T struct timespec 13364092Smjacob#define GET_NANOTIME nanotime 13464092Smjacob#define GET_NANOSEC(x) ((x)->tv_sec * 1000000000 + (x)->tv_nsec) 13564092Smjacob#define NANOTIME_SUB nanotime_sub 13662496Smjacob 13764092Smjacob#define MAXISPREQUEST(isp) 256 13862496Smjacob 13964092Smjacob#ifdef __alpha__ 14064092Smjacob#define MEMORYBARRIER(isp, type, offset, size) alpha_mb() 14164092Smjacob#else 14264092Smjacob#define MEMORYBARRIER(isp, type, offset, size) 14363387Smjacob#endif 14462496Smjacob 14564092Smjacob#define MBOX_ACQUIRE(isp) 14664092Smjacob#define MBOX_WAIT_COMPLETE isp_mbox_wait_complete 14762496Smjacob#define MBOX_NOTIFY_COMPLETE(isp) \ 14862496Smjacob if (isp->isp_osinfo.mboxwaiting) { \ 14962496Smjacob isp->isp_osinfo.mboxwaiting = 0; \ 15062496Smjacob wakeup(&isp->isp_osinfo.mboxwaiting); \ 15162496Smjacob } \ 15262496Smjacob isp->isp_mboxbsy = 0 15364092Smjacob#define MBOX_RELEASE(isp) 15462496Smjacob 15564092Smjacob#ifndef SCSI_GOOD 15664092Smjacob#define SCSI_GOOD SCSI_STATUS_OK 15764092Smjacob#endif 15864092Smjacob#ifndef SCSI_CHECK 15964092Smjacob#define SCSI_CHECK SCSI_STATUS_CHECK_COND 16064092Smjacob#endif 16164092Smjacob#ifndef SCSI_BUSY 16264092Smjacob#define SCSI_BUSY SCSI_STATUS_BUSY 16364092Smjacob#endif 16464092Smjacob#ifndef SCSI_QFULL 16564092Smjacob#define SCSI_QFULL SCSI_STATUS_QUEUE_FULL 16664092Smjacob#endif 16764092Smjacob 16864092Smjacob#define XS_T struct ccb_scsiio 16948487Smjacob#define XS_ISP(ccb) ((struct ispsoftc *) (ccb)->ccb_h.spriv_ptr1) 17064092Smjacob#define XS_CHANNEL(ccb) cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path)) 17164092Smjacob#define XS_TGT(ccb) (ccb)->ccb_h.target_id 17264092Smjacob#define XS_LUN(ccb) (ccb)->ccb_h.target_lun 17335388Smjacob 17464092Smjacob#define XS_CDBP(ccb) \ 17564092Smjacob (((ccb)->ccb_h.flags & CAM_CDB_POINTER)? \ 17664092Smjacob (ccb)->cdb_io.cdb_ptr : (ccb)->cdb_io.cdb_bytes) 17764092Smjacob 17864092Smjacob#define XS_CDBLEN(ccb) (ccb)->cdb_len 17948487Smjacob#define XS_XFRLEN(ccb) (ccb)->dxfer_len 18048487Smjacob#define XS_TIME(ccb) (ccb)->ccb_h.timeout 18164092Smjacob#define XS_RESID(ccb) (ccb)->resid 18264092Smjacob#define XS_STSP(ccb) (&(ccb)->scsi_status) 18348487Smjacob#define XS_SNSP(ccb) (&(ccb)->sense_data) 18464092Smjacob 18552348Smjacob#define XS_SNSLEN(ccb) \ 18652348Smjacob imin((sizeof((ccb)->sense_data)), ccb->sense_len) 18764092Smjacob 18848487Smjacob#define XS_SNSKEY(ccb) ((ccb)->sense_data.flags & 0xf) 18964092Smjacob#define XS_TAG_P(ccb) \ 19064092Smjacob (((ccb)->ccb_h.flags & CAM_TAG_ACTION_VALID) && \ 19164092Smjacob (ccb)->tag_action != CAM_TAG_ACTION_NONE) 19235388Smjacob 19364092Smjacob#define XS_TAG_TYPE(ccb) \ 19464092Smjacob ((ccb->tag_action == MSG_SIMPLE_Q_TAG)? REQFLAG_STAG : \ 19564092Smjacob ((ccb->tag_action == MSG_HEAD_OF_Q_TAG)? REQFLAG_HTAG : REQFLAG_OTAG)) 19664092Smjacob 19764092Smjacob 19864092Smjacob#define XS_SETERR(ccb, v) (ccb)->ccb_h.status &= ~CAM_STATUS_MASK, \ 19964092Smjacob (ccb)->ccb_h.status |= v, \ 20064092Smjacob (ccb)->ccb_h.spriv_field0 |= ISP_SPRIV_ERRSET 20164092Smjacob 20264092Smjacob# define HBA_NOERROR CAM_REQ_INPROG 20364092Smjacob# define HBA_BOTCH CAM_UNREC_HBA_ERROR 20464092Smjacob# define HBA_CMDTIMEOUT CAM_CMD_TIMEOUT 20564092Smjacob# define HBA_SELTIMEOUT CAM_SEL_TIMEOUT 20664092Smjacob# define HBA_TGTBSY CAM_SCSI_STATUS_ERROR 20764092Smjacob# define HBA_BUSRESET CAM_SCSI_BUS_RESET 20864092Smjacob# define HBA_ABORTED CAM_REQ_ABORTED 20964092Smjacob# define HBA_DATAOVR CAM_DATA_RUN_ERR 21064092Smjacob# define HBA_ARQFAIL CAM_AUTOSENSE_FAIL 21164092Smjacob 21264092Smjacob 21364092Smjacob#define XS_ERR(ccb) ((ccb)->ccb_h.status & CAM_STATUS_MASK) 21464092Smjacob 21564092Smjacob#define XS_NOERR(ccb) \ 21664092Smjacob (((ccb)->ccb_h.spriv_field0 & ISP_SPRIV_ERRSET) == 0 || \ 21764092Smjacob ((ccb)->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) 21864092Smjacob 21964092Smjacob#define XS_INITERR(ccb) \ 22064092Smjacob XS_SETERR(ccb, CAM_REQ_INPROG), (ccb)->ccb_h.spriv_field0 = 0 22164092Smjacob 22264092Smjacob#define XS_SAVE_SENSE(xs, sp) \ 22364092Smjacob bcopy(sp->req_sense_data, &(xs)->sense_data, \ 22464092Smjacob imin(XS_SNSLEN(xs), sp->req_sense_len)) 22564092Smjacob 22664092Smjacob#define XS_SET_STATE_STAT(a, b, c) 22764092Smjacob 22864092Smjacob#define DEFAULT_IID(x) 7 22964092Smjacob#define DEFAULT_LOOPID(x) 109 23064092Smjacob#define DEFAULT_NODEWWN(isp) (isp)->isp_osinfo.default_wwn 23164092Smjacob#define DEFAULT_PORTWWN(isp) \ 23264092Smjacob isp_port_from_node_wwn((isp), (isp)->isp_osinfo.default_wwn) 23364092Smjacob#define PORT_FROM_NODE_WWN isp_port_from_node_wwn 23464092Smjacob 23564092Smjacob#define ISP_UNSWIZZLE_AND_COPY_PDBP(isp, dest, src) \ 23664092Smjacob if((void *)src != (void *)dest) bcopy(src, dest, sizeof (isp_pdb_t)) 23764092Smjacob#define ISP_SWIZZLE_ICB(a, b) 23864092Smjacob#define ISP_SWIZZLE_REQUEST(a, b) 23964092Smjacob#define ISP_UNSWIZZLE_RESPONSE(a, b, c) 24064092Smjacob#define ISP_SWIZZLE_SNS_REQ(a, b) 24164092Smjacob#define ISP_UNSWIZZLE_SNS_RSP(a, b, c) 24264092Smjacob#define ISP_SWIZZLE_NVRAM_WORD(isp, x) 24364092Smjacob 24448487Smjacob/* 24564092Smjacob * Includes of common header files 24648487Smjacob */ 24735388Smjacob 24864092Smjacob#include <dev/isp/ispreg.h> 24964092Smjacob#include <dev/isp/ispvar.h> 25064092Smjacob#include <dev/isp/ispmbox.h> 25135388Smjacob 25264092Smjacob/* 25364092Smjacob * isp_osinfo definiitions && shorthand 25464092Smjacob */ 25564092Smjacob#define SIMQFRZ_RESOURCE 0x1 25664092Smjacob#define SIMQFRZ_LOOPDOWN 0x2 25764092Smjacob#define SIMQFRZ_TIMED 0x4 25864092Smjacob 25964092Smjacob#define isp_sim isp_osinfo.sim 26064092Smjacob#define isp_path isp_osinfo.path 26164092Smjacob#define isp_sim2 isp_osinfo.sim2 26264092Smjacob#define isp_path2 isp_osinfo.path2 26364092Smjacob#define isp_unit isp_osinfo.unit 26464092Smjacob#define isp_name isp_osinfo.name 26564092Smjacob 26664092Smjacob/* 26764092Smjacob * prototypes for isp_pci && isp_freebsd to share 26864092Smjacob */ 26964092Smjacobextern void isp_attach(struct ispsoftc *); 27064092Smjacobextern void isp_uninit(struct ispsoftc *); 27164092Smjacob 27264092Smjacob/* 27364092Smjacob * Locking macros... 27464092Smjacob */ 27564092Smjacob 27664092Smjacob#define ISP_LOCK isp_lock 27764092Smjacob#define ISP_UNLOCK isp_unlock 27864092Smjacob 27964092Smjacob/* not safely working yet */ 28064092Smjacob#if 0 28164092Smjacob#define SERVICING_INTERRUPT(isp) (intr_nesting_level != 0) 28264092Smjacob#endif 28364092Smjacob 28464092Smjacob/* 28564092Smjacob * Platform private flags 28664092Smjacob */ 28762172Smjacob#define ISP_SPRIV_ERRSET 0x1 28862172Smjacob#define ISP_SPRIV_INWDOG 0x2 28962172Smjacob#define ISP_SPRIV_GRACE 0x4 29062172Smjacob#define ISP_SPRIV_DONE 0x8 29162172Smjacob 29262172Smjacob#define XS_CMD_S_WDOG(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_INWDOG 29362172Smjacob#define XS_CMD_C_WDOG(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_INWDOG 29462172Smjacob#define XS_CMD_WDOG_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_INWDOG) 29562172Smjacob 29662172Smjacob#define XS_CMD_S_GRACE(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_GRACE 29762172Smjacob#define XS_CMD_C_GRACE(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_GRACE 29862172Smjacob#define XS_CMD_GRACE_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_GRACE) 29962172Smjacob 30062172Smjacob#define XS_CMD_S_DONE(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_DONE 30162172Smjacob#define XS_CMD_C_DONE(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_DONE 30262172Smjacob#define XS_CMD_DONE_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_DONE) 30362172Smjacob 30462172Smjacob#define XS_CMD_S_CLEAR(sccb) (sccb)->ccb_h.spriv_field0 = 0 30539235Sgibbs/* 30664092Smjacob * Platform specific inline functions 30739235Sgibbs */ 30835388Smjacob 30964092Smjacobstatic INLINE void isp_lock(struct ispsoftc *); 31064092Smjacobstatic INLINE void 31164092Smjacobisp_lock(struct ispsoftc *isp) 31264092Smjacob{ 31364092Smjacob int s = splcam(); 31465140Smjacob if (isp->isp_osinfo.islocked++ == 0) { 31564092Smjacob isp->isp_osinfo.splsaved = s; 31664092Smjacob } else { 31764092Smjacob splx(s); 31864092Smjacob } 31964092Smjacob} 32044819Smjacob 32164092Smjacobstatic INLINE void isp_unlock(struct ispsoftc *); 32264092Smjacobstatic INLINE void 32364092Smjacobisp_unlock(struct ispsoftc *isp) 32464092Smjacob{ 32565140Smjacob if (--isp->isp_osinfo.islocked == 0) { 32664092Smjacob splx(isp->isp_osinfo.splsaved); 32764092Smjacob } 32864092Smjacob} 32964092Smjacob 33064092Smjacobstatic INLINE void isp_mbox_wait_complete(struct ispsoftc *); 33164092Smjacobstatic INLINE void 33264092Smjacobisp_mbox_wait_complete(struct ispsoftc *isp) 33364092Smjacob{ 33464092Smjacob#ifdef SERVICING_INTERRUPT 33564092Smjacob if (isp->isp_osinfo.intsok == 0 || SERVICING_INTERRUPT(isp)) { 33664092Smjacob int j; 33764092Smjacob for (j = 0; j < 60 * 2000; j++) { 33864092Smjacob if (isp_intr(isp) == 0) { 33964092Smjacob USEC_DELAY(500); 34064092Smjacob } 34164092Smjacob if (isp->isp_mboxbsy == 0) { 34264092Smjacob break; 34364092Smjacob } 34464092Smjacob } 34564092Smjacob if (isp->isp_mboxbsy != 0) { 34664092Smjacob isp_prt(isp, ISP_LOGWARN, "mailbox timeout"); 34764092Smjacob } 34864092Smjacob } else { 34964092Smjacob isp->isp_osinfo.mboxwaiting = 1; 35064092Smjacob while (isp->isp_mboxbsy != 0) { 35164092Smjacob (void) tsleep(&isp->isp_osinfo.mboxwaiting, PRIBIO, 35264092Smjacob "isp_mailbox", 0); 35364092Smjacob } 35464092Smjacob } 35544819Smjacob#else 35664092Smjacob int j; 35764092Smjacob for (j = 0; j < 60 * 2000; j++) { 35864092Smjacob if (isp_intr(isp) == 0) { 35964092Smjacob USEC_DELAY(500); 36064092Smjacob } 36164092Smjacob if (isp->isp_mboxbsy == 0) { 36264092Smjacob break; 36364092Smjacob } 36464092Smjacob } 36564092Smjacob if (isp->isp_mboxbsy != 0) { 36664092Smjacob isp_prt(isp, ISP_LOGWARN, "mailbox timeout"); 36764092Smjacob } 36844819Smjacob#endif 36964092Smjacob} 37044819Smjacob 37164092Smjacobstatic INLINE u_int64_t nanotime_sub(struct timespec *, struct timespec *); 37264092Smjacobstatic INLINE u_int64_t 37364092Smjacobnanotime_sub(struct timespec *b, struct timespec *a) 37464092Smjacob{ 37564092Smjacob u_int64_t elapsed; 37664092Smjacob struct timespec x = *b; 37764092Smjacob timespecsub(&x, a); 37864092Smjacob elapsed = GET_NANOSEC(&x); 37964092Smjacob if (elapsed == 0) 38064092Smjacob elapsed++; 38164092Smjacob return (elapsed); 38264092Smjacob} 38344819Smjacob 38464092Smjacobstatic INLINE char *strncat(char *, const char *, size_t); 38564092Smjacobstatic INLINE char * 38662496Smjacobstrncat(char *d, const char *s, size_t c) 38762496Smjacob{ 38862496Smjacob char *t = d; 38944819Smjacob 39062496Smjacob if (c) { 39162496Smjacob while (*d) 39262496Smjacob d++; 39362496Smjacob while ((*d++ = *s++)) { 39462496Smjacob if (--c == 0) { 39562496Smjacob *d = '\0'; 39662496Smjacob break; 39762496Smjacob } 39862496Smjacob } 39962496Smjacob } 40062496Smjacob return (t); 40162496Smjacob} 40262496Smjacob 40364092Smjacobstatic INLINE u_int64_t isp_port_from_node_wwn(struct ispsoftc *, u_int64_t); 40464092Smjacobstatic INLINE u_int64_t 40564092Smjacobisp_port_from_node_wwn(struct ispsoftc *isp, u_int64_t node_wwn) 40664092Smjacob{ 40764092Smjacob u_int64_t rv = node_wwn; 40864092Smjacob if ((node_wwn >> 60) == 2) { 40964092Smjacob rv = node_wwn | 41064092Smjacob (((u_int64_t)(isp->isp_unit+1)) << 48); 41164092Smjacob } 41264092Smjacob return (rv); 41364092Smjacob} 41444819Smjacob 41564092Smjacob/* 41664092Smjacob * Common inline functions 41764092Smjacob */ 41844819Smjacob 41952348Smjacob#include <dev/isp/isp_inline.h> 42035388Smjacob#endif /* _ISP_FREEBSD_H */ 421