1/* $FreeBSD: head/sys/dev/isp/isp_freebsd.h 257381 2013-10-30 14:04:47Z nwhitehorn $ */
2/*-
3 * Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions
4 *
5 * Copyright (c) 1997-2008 by Matthew Jacob
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice immediately at the beginning of the file, without modification,
13 * this list of conditions, and the following disclaimer.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#ifndef _ISP_FREEBSD_H
30#define _ISP_FREEBSD_H
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/endian.h>
35#include <sys/lock.h>
36#include <sys/kernel.h>
37#include <sys/queue.h>
38#include <sys/malloc.h>
39#include <sys/mutex.h>
40#include <sys/condvar.h>
41#include <sys/sysctl.h>
42
43#include <sys/proc.h>
44#include <sys/bus.h>
45#include <sys/taskqueue.h>
46
47#include <machine/bus.h>
48#include <machine/cpu.h>
49#include <machine/stdarg.h>
50
51#include <cam/cam.h>
52#include <cam/cam_debug.h>
53#include <cam/cam_ccb.h>
54#include <cam/cam_sim.h>
55#include <cam/cam_xpt.h>
56#include <cam/cam_xpt_sim.h>
57#include <cam/cam_debug.h>
58#include <cam/scsi/scsi_all.h>
59#include <cam/scsi/scsi_message.h>
60
61#include "opt_ddb.h"
62#include "opt_isp.h"
63
64#define ISP_PLATFORM_VERSION_MAJOR 7
65#define ISP_PLATFORM_VERSION_MINOR 10
66
67/*
68 * Efficiency- get rid of SBus code && tests unless we need them.
69 */
70#ifdef __sparc64__
71#define ISP_SBUS_SUPPORTED 1
72#else
73#define ISP_SBUS_SUPPORTED 0
74#endif
75
76#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
77
78#define N_XCMDS 64
79#define XCMD_SIZE 512
80struct ispsoftc;
81typedef union isp_ecmd {
82 union isp_ecmd * next;
83 uint8_t data[XCMD_SIZE];
84} isp_ecmd_t;
85isp_ecmd_t * isp_get_ecmd(struct ispsoftc *);
86void isp_put_ecmd(struct ispsoftc *, isp_ecmd_t *);
87
88#ifdef ISP_TARGET_MODE
89/* Not quite right, but there was no bump for this change */
90#if __FreeBSD_version < 225469
91#define SDFIXED(x) (&x)
92#else
93#define SDFIXED(x) ((struct scsi_sense_data_fixed *)(&x))
94#endif
95
96#define ISP_TARGET_FUNCTIONS 1
97#define ATPDPSIZE 4096
98#define ATPDPHASHSIZE 16
99#define ATPDPHASH(x) ((((x) >> 24) ^ ((x) >> 16) ^ ((x) >> 8) ^ (x)) & \
100 ((ATPDPHASHSIZE) - 1))
101
102#include <dev/isp/isp_target.h>
103typedef struct atio_private_data {
104 LIST_ENTRY(atio_private_data) next;
105 uint32_t orig_datalen;
106 uint32_t bytes_xfered;
107 uint32_t bytes_in_transit;
108 uint32_t tag; /* typically f/w RX_ID */
109 uint32_t lun;
110 uint32_t nphdl;
111 uint32_t sid;
112 uint32_t portid;
113 uint16_t rxid; /* wire rxid */
114 uint16_t oxid; /* wire oxid */
115 uint16_t word3; /* PRLI word3 params */
116 uint16_t ctcnt; /* number of CTIOs currently active */
117 uint8_t seqno; /* CTIO sequence number */
118 uint32_t
119 srr_notify_rcvd : 1,
120 cdb0 : 8,
121 sendst : 1,
122 dead : 1,
123 tattr : 3,
124 state : 3;
125 void * ests;
126 /*
127 * The current SRR notify copy
128 */
129 uint8_t srr[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
130 void * srr_ccb;
131 uint32_t nsrr;
132} atio_private_data_t;
133#define ATPD_STATE_FREE 0
134#define ATPD_STATE_ATIO 1
135#define ATPD_STATE_CAM 2
136#define ATPD_STATE_CTIO 3
137#define ATPD_STATE_LAST_CTIO 4
138#define ATPD_STATE_PDON 5
139
140#define ATPD_CCB_OUTSTANDING 16
141
142#define ATPD_SEQ_MASK 0x7f
143#define ATPD_SEQ_NOTIFY_CAM 0x80
144#define ATPD_SET_SEQNO(hdrp, atp) ((isphdr_t *)hdrp)->rqs_seqno &= ~ATPD_SEQ_MASK, ((isphdr_t *)hdrp)->rqs_seqno |= (atp)->seqno
145#define ATPD_GET_SEQNO(hdrp) (((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_MASK)
146#define ATPD_GET_NCAM(hdrp) ((((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0)
147
148typedef union inot_private_data inot_private_data_t;
149union inot_private_data {
150 inot_private_data_t *next;
151 struct {
152 isp_notify_t nt; /* must be first! */
153 uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
154 uint32_t tag_id, seq_id;
155 } rd;
156};
157typedef struct isp_timed_notify_ack {
158 void *isp;
159 void *not;
160 uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
161} isp_tna_t;
162
163TAILQ_HEAD(isp_ccbq, ccb_hdr);
164typedef struct tstate {
165 SLIST_ENTRY(tstate) next;
166 struct cam_path *owner;
167 struct isp_ccbq waitq; /* waiting CCBs */
168 struct ccb_hdr_slist atios;
169 struct ccb_hdr_slist inots;
170 uint32_t hold;
171 uint32_t
172 enabled : 1,
173 atio_count : 15,
174 inot_count : 15;
175 inot_private_data_t * restart_queue;
176 inot_private_data_t * ntfree;
177 inot_private_data_t ntpool[ATPDPSIZE];
178 LIST_HEAD(, atio_private_data) atfree;
179 LIST_HEAD(, atio_private_data) atused[ATPDPHASHSIZE];
180 atio_private_data_t atpool[ATPDPSIZE];
181} tstate_t;
182
183#define LUN_HASH_SIZE 32
184#define LUN_HASH_FUNC(lun) ((lun) & (LUN_HASH_SIZE - 1))
185
186#endif
187
188/*
189 * Per command info.
190 */
191struct isp_pcmd {
192 struct isp_pcmd * next;
193 bus_dmamap_t dmap; /* dma map for this command */
194 struct ispsoftc * isp; /* containing isp */
195 struct callout wdog; /* watchdog timer */
196 uint32_t datalen; /* data length for this command (target mode only) */
197 uint8_t totslen; /* sense length on status response */
198 uint8_t cumslen; /* sense length on status response */
199 uint8_t crn; /* command reference number */
200};
201#define ISP_PCMD(ccb) (ccb)->ccb_h.spriv_ptr1
202#define PISP_PCMD(ccb) ((struct isp_pcmd *)ISP_PCMD(ccb))
203
204/*
205 * Per nexus info.
206 */
207struct isp_nexus {
208 struct isp_nexus * next;
209 uint32_t
210 crnseed : 8; /* next command reference number */
211 uint32_t
212 tgt : 16, /* TGT for target */
213 lun : 16; /* LUN for target */
214};
215#define NEXUS_HASH_WIDTH 32
216#define INITIAL_NEXUS_COUNT MAX_FC_TARG
217#define NEXUS_HASH(tgt, lun) ((tgt + lun) % NEXUS_HASH_WIDTH)
218
219/*
220 * Per channel information
221 */
222SLIST_HEAD(tslist, tstate);
223
224struct isp_fc {
225 struct cam_sim *sim;
226 struct cam_path *path;
227 struct ispsoftc *isp;
228 struct proc *kproc;
229 bus_dma_tag_t tdmat;
230 bus_dmamap_t tdmap;
231 uint64_t def_wwpn;
232 uint64_t def_wwnn;
233 uint32_t loop_down_time;
234 uint32_t loop_down_limit;
235 uint32_t gone_device_time;
236 /*
237 * Per target/lun info- just to keep a per-ITL nexus crn count
238 */
239 struct isp_nexus *nexus_hash[NEXUS_HASH_WIDTH];
240 struct isp_nexus *nexus_free_list;
241 uint32_t
242#ifdef ISP_TARGET_MODE
243#ifdef ISP_INTERNAL_TARGET
244 proc_active : 1,
245#endif
246 tm_luns_enabled : 1,
247 tm_enable_defer : 1,
248 tm_enabled : 1,
249#endif
250 simqfrozen : 3,
251 default_id : 8,
252 hysteresis : 8,
253 def_role : 2, /* default role */
254 gdt_running : 1,
255 loop_dead : 1,
256 fcbsy : 1,
257 ready : 1;
258 struct callout ldt; /* loop down timer */
259 struct callout gdt; /* gone device timer */
260 struct task ltask;
261 struct task gtask;
262#ifdef ISP_TARGET_MODE
263 struct tslist lun_hash[LUN_HASH_SIZE];
264#ifdef ISP_INTERNAL_TARGET
265 struct proc * target_proc;
266#endif
267#if defined(DEBUG)
268 unsigned int inject_lost_data_frame;
269#endif
270#endif
271};
272
273struct isp_spi {
274 struct cam_sim *sim;
275 struct cam_path *path;
276 uint32_t
277#ifdef ISP_TARGET_MODE
278#ifdef ISP_INTERNAL_TARGET
279 proc_active : 1,
280#endif
281 tm_luns_enabled : 1,
282 tm_enable_defer : 1,
283 tm_enabled : 1,
284#endif
285 simqfrozen : 3,
286 def_role : 2,
287 iid : 4;
288#ifdef ISP_TARGET_MODE
289 struct tslist lun_hash[LUN_HASH_SIZE];
290#ifdef ISP_INTERNAL_TARGET
291 struct proc * target_proc;
292#endif
293#endif
294};
295
296struct isposinfo {
297 /*
298 * Linkage, locking, and identity
299 */
300 struct mtx lock;
301 device_t dev;
302 struct cdev * cdev;
303 struct intr_config_hook ehook;
304 struct cam_devq * devq;
305
306 /*
307 * Firmware pointer
308 */
309 const struct firmware * fw;
310
311 /*
312 * DMA related sdtuff
313 */
314 bus_space_tag_t bus_tag;
315 bus_dma_tag_t dmat;
316 bus_space_handle_t bus_handle;
317 bus_dma_tag_t cdmat;
318 bus_dmamap_t cdmap;
319
320 /*
321 * Command and transaction related related stuff
322 */
323 struct isp_pcmd * pcmd_pool;
324 struct isp_pcmd * pcmd_free;
325
326 uint32_t
327#ifdef ISP_TARGET_MODE
328 tmwanted : 1,
329 tmbusy : 1,
330#else
331 : 2,
332#endif
333 sixtyfourbit : 1, /* sixtyfour bit platform */
334 timer_active : 1,
335 autoconf : 1,
336 ehook_active : 1,
337 disabled : 1,
338 mbox_sleeping : 1,
339 mbox_sleep_ok : 1,
340 mboxcmd_done : 1,
341 mboxbsy : 1;
342
343 struct callout tmo; /* general timer */
344
345 /*
346 * misc- needs to be sorted better XXXXXX
347 */
348 int framesize;
349 int exec_throttle;
350 int cont_max;
351
352#ifdef ISP_TARGET_MODE
353 cam_status * rptr;
354#endif
355
356 bus_addr_t ecmd_dma;
357 isp_ecmd_t * ecmd_base;
358 isp_ecmd_t * ecmd_free;
359
360 /*
361 * Per-type private storage...
362 */
363 union {
364 struct isp_fc *fc;
365 struct isp_spi *spi;
366 void *ptr;
367 } pc;
368};
369#define ISP_FC_PC(isp, chan) (&(isp)->isp_osinfo.pc.fc[(chan)])
370#define ISP_SPI_PC(isp, chan) (&(isp)->isp_osinfo.pc.spi[(chan)])
371#define ISP_GET_PC(isp, chan, tag, rslt) \
372 if (IS_SCSI(isp)) { \
373 rslt = ISP_SPI_PC(isp, chan)-> tag; \
374 } else { \
375 rslt = ISP_FC_PC(isp, chan)-> tag; \
376 }
377#define ISP_GET_PC_ADDR(isp, chan, tag, rp) \
378 if (IS_SCSI(isp)) { \
379 rp = &ISP_SPI_PC(isp, chan)-> tag; \
380 } else { \
381 rp = &ISP_FC_PC(isp, chan)-> tag; \
382 }
383#define ISP_SET_PC(isp, chan, tag, val) \
384 if (IS_SCSI(isp)) { \
385 ISP_SPI_PC(isp, chan)-> tag = val; \
386 } else { \
387 ISP_FC_PC(isp, chan)-> tag = val; \
388 }
389
390#define FCP_NEXT_CRN isp_fcp_next_crn
391#define isp_lock isp_osinfo.lock
392#define isp_bus_tag isp_osinfo.bus_tag
393#define isp_bus_handle isp_osinfo.bus_handle
394
395/*
396 * Locking macros...
397 */
398#define ISP_LOCK(isp) mtx_lock(&isp->isp_osinfo.lock)
399#define ISP_UNLOCK(isp) mtx_unlock(&isp->isp_osinfo.lock)
400
401/*
402 * Required Macros/Defines
403 */
404#define ISP_FC_SCRLEN 0x1000
405
406#define ISP_MEMZERO(a, b) memset(a, 0, b)
407#define ISP_MEMCPY memcpy
408#define ISP_SNPRINTF snprintf
409#define ISP_DELAY DELAY
410#define ISP_SLEEP(isp, x) DELAY(x)
411
412#define ISP_MIN imin
413
414#ifndef DIAGNOSTIC
415#define ISP_INLINE __inline
416#else
417#define ISP_INLINE
418#endif
419
420#define NANOTIME_T struct timespec
421#define GET_NANOTIME nanotime
422#define GET_NANOSEC(x) ((x)->tv_sec * 1000000000 + (x)->tv_nsec)
423#define NANOTIME_SUB isp_nanotime_sub
424
425#define MAXISPREQUEST(isp) ((IS_FC(isp) || IS_ULTRA2(isp))? 1024 : 256)
426
427#define MEMORYBARRIER(isp, type, offset, size, chan) \
428switch (type) { \
429case SYNC_SFORDEV: \
430{ \
431 struct isp_fc *fc = ISP_FC_PC(isp, chan); \
432 bus_dmamap_sync(fc->tdmat, fc->tdmap, \
433 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \
434 break; \
435} \
436case SYNC_REQUEST: \
437 bus_dmamap_sync(isp->isp_osinfo.cdmat, \
438 isp->isp_osinfo.cdmap, \
439 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \
440 break; \
441case SYNC_SFORCPU: \
442{ \
443 struct isp_fc *fc = ISP_FC_PC(isp, chan); \
444 bus_dmamap_sync(fc->tdmat, fc->tdmap, \
445 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \
446 break; \
447} \
448case SYNC_RESULT: \
449 bus_dmamap_sync(isp->isp_osinfo.cdmat, \
450 isp->isp_osinfo.cdmap, \
451 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \
452 break; \
453case SYNC_REG: \
454 bus_space_barrier(isp->isp_osinfo.bus_tag, \
455 isp->isp_osinfo.bus_handle, offset, size, \
456 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \
457 break; \
458default: \
459 break; \
460}
461
462#define MBOX_ACQUIRE isp_mbox_acquire
463#define MBOX_WAIT_COMPLETE isp_mbox_wait_complete
464#define MBOX_NOTIFY_COMPLETE isp_mbox_notify_done
465#define MBOX_RELEASE isp_mbox_release
466
467#define FC_SCRATCH_ACQUIRE isp_fc_scratch_acquire
468#define FC_SCRATCH_RELEASE(isp, chan) isp->isp_osinfo.pc.fc[chan].fcbsy = 0
469
470#ifndef SCSI_GOOD
471#define SCSI_GOOD SCSI_STATUS_OK
472#endif
473#ifndef SCSI_CHECK
474#define SCSI_CHECK SCSI_STATUS_CHECK_COND
475#endif
476#ifndef SCSI_BUSY
477#define SCSI_BUSY SCSI_STATUS_BUSY
478#endif
479#ifndef SCSI_QFULL
480#define SCSI_QFULL SCSI_STATUS_QUEUE_FULL
481#endif
482
483#define XS_T struct ccb_scsiio
484#define XS_DMA_ADDR_T bus_addr_t
485#define XS_GET_DMA64_SEG(a, b, c) \
486{ \
487 ispds64_t *d = a; \
488 bus_dma_segment_t *e = b; \
489 uint32_t f = c; \
490 e += f; \
491 d->ds_base = DMA_LO32(e->ds_addr); \
492 d->ds_basehi = DMA_HI32(e->ds_addr); \
493 d->ds_count = e->ds_len; \
494}
495#define XS_GET_DMA_SEG(a, b, c) \
496{ \
497 ispds_t *d = a; \
498 bus_dma_segment_t *e = b; \
499 uint32_t f = c; \
500 e += f; \
501 d->ds_base = DMA_LO32(e->ds_addr); \
502 d->ds_count = e->ds_len; \
503}
504#define XS_ISP(ccb) cam_sim_softc(xpt_path_sim((ccb)->ccb_h.path))
505#define XS_CHANNEL(ccb) cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
506#define XS_TGT(ccb) (ccb)->ccb_h.target_id
507#define XS_LUN(ccb) (uint32_t)((ccb)->ccb_h.target_lun)
508
509#define XS_CDBP(ccb) \
510 (((ccb)->ccb_h.flags & CAM_CDB_POINTER)? \
511 (ccb)->cdb_io.cdb_ptr : (ccb)->cdb_io.cdb_bytes)
512
513#define XS_CDBLEN(ccb) (ccb)->cdb_len
514#define XS_XFRLEN(ccb) (ccb)->dxfer_len
515#define XS_TIME(ccb) (ccb)->ccb_h.timeout
516#define XS_GET_RESID(ccb) (ccb)->resid
517#define XS_SET_RESID(ccb, r) (ccb)->resid = r
518#define XS_STSP(ccb) (&(ccb)->scsi_status)
519#define XS_SNSP(ccb) (&(ccb)->sense_data)
520
521#define XS_TOT_SNSLEN(ccb) ccb->sense_len
522#define XS_CUR_SNSLEN(ccb) (ccb->sense_len - ccb->sense_resid)
523
524#define XS_SNSKEY(ccb) (scsi_get_sense_key(&(ccb)->sense_data, \
525 ccb->sense_len - ccb->sense_resid, 1))
526
527#define XS_SNSASC(ccb) (scsi_get_asc(&(ccb)->sense_data, \
528 ccb->sense_len - ccb->sense_resid, 1))
529
530#define XS_SNSASCQ(ccb) (scsi_get_ascq(&(ccb)->sense_data, \
531 ccb->sense_len - ccb->sense_resid, 1))
532#define XS_TAG_P(ccb) \
533 (((ccb)->ccb_h.flags & CAM_TAG_ACTION_VALID) && \
534 (ccb)->tag_action != CAM_TAG_ACTION_NONE)
535
536#define XS_TAG_TYPE(ccb) \
537 ((ccb->tag_action == MSG_SIMPLE_Q_TAG)? REQFLAG_STAG : \
538 ((ccb->tag_action == MSG_HEAD_OF_Q_TAG)? REQFLAG_HTAG : REQFLAG_OTAG))
539
540
541#define XS_SETERR(ccb, v) (ccb)->ccb_h.status &= ~CAM_STATUS_MASK, \
542 (ccb)->ccb_h.status |= v
543
544# define HBA_NOERROR CAM_REQ_INPROG
545# define HBA_BOTCH CAM_UNREC_HBA_ERROR
546# define HBA_CMDTIMEOUT CAM_CMD_TIMEOUT
547# define HBA_SELTIMEOUT CAM_SEL_TIMEOUT
548# define HBA_TGTBSY CAM_SCSI_STATUS_ERROR
549# define HBA_BUSRESET CAM_SCSI_BUS_RESET
550# define HBA_ABORTED CAM_REQ_ABORTED
551# define HBA_DATAOVR CAM_DATA_RUN_ERR
552# define HBA_ARQFAIL CAM_AUTOSENSE_FAIL
553
554
555#define XS_ERR(ccb) ((ccb)->ccb_h.status & CAM_STATUS_MASK)
556
557#define XS_NOERR(ccb) (((ccb)->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)
558
559#define XS_INITERR(ccb) XS_SETERR(ccb, CAM_REQ_INPROG), ccb->sense_resid = ccb->sense_len
560
561#define XS_SAVE_SENSE(xs, sense_ptr, totslen, slen) do { \
562 uint32_t tlen = slen; \
563 if (tlen > (xs)->sense_len) \
564 tlen = (xs)->sense_len; \
565 PISP_PCMD(xs)->totslen = imin((xs)->sense_len, totslen); \
566 PISP_PCMD(xs)->cumslen = tlen; \
567 memcpy(&(xs)->sense_data, sense_ptr, tlen); \
568 (xs)->sense_resid = (xs)->sense_len - tlen; \
569 (xs)->ccb_h.status |= CAM_AUTOSNS_VALID; \
570 } while (0)
571
572#define XS_SENSE_APPEND(xs, xsnsp, xsnsl) do { \
573 uint32_t off = PISP_PCMD(xs)->cumslen; \
574 uint8_t *ptr = &((uint8_t *)(&(xs)->sense_data))[off]; \
575 uint32_t amt = imin(xsnsl, PISP_PCMD(xs)->totslen - off); \
576 if (amt) { \
577 memcpy(ptr, xsnsp, amt); \
578 (xs)->sense_resid -= amt; \
579 PISP_PCMD(xs)->cumslen += amt; \
580 } \
581 } while (0)
582
583#define XS_SENSE_VALID(xs) (((xs)->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
584
585#define DEFAULT_FRAMESIZE(isp) isp->isp_osinfo.framesize
586#define DEFAULT_EXEC_THROTTLE(isp) isp->isp_osinfo.exec_throttle
587
588#define GET_DEFAULT_ROLE(isp, chan) \
589 (IS_FC(isp)? ISP_FC_PC(isp, chan)->def_role : ISP_SPI_PC(isp, chan)->def_role)
590#define SET_DEFAULT_ROLE(isp, chan, val) \
591 if (IS_FC(isp)) { \
592 ISP_FC_PC(isp, chan)->def_role = val; \
593 } else { \
594 ISP_SPI_PC(isp, chan)->def_role = val; \
595 }
596
597#define DEFAULT_IID(isp, chan) isp->isp_osinfo.pc.spi[chan].iid
598
599#define DEFAULT_LOOPID(x, chan) isp->isp_osinfo.pc.fc[chan].default_id
600
601#define DEFAULT_NODEWWN(isp, chan) isp_default_wwn(isp, chan, 0, 1)
602#define DEFAULT_PORTWWN(isp, chan) isp_default_wwn(isp, chan, 0, 0)
603#define ACTIVE_NODEWWN(isp, chan) isp_default_wwn(isp, chan, 1, 1)
604#define ACTIVE_PORTWWN(isp, chan) isp_default_wwn(isp, chan, 1, 0)
605
606
607#if BYTE_ORDER == BIG_ENDIAN
608#ifdef ISP_SBUS_SUPPORTED
609#define ISP_IOXPUT_8(isp, s, d) *(d) = s
610#define ISP_IOXPUT_16(isp, s, d) \
611 *(d) = (isp->isp_bustype == ISP_BT_SBUS)? s : bswap16(s)
612#define ISP_IOXPUT_32(isp, s, d) \
613 *(d) = (isp->isp_bustype == ISP_BT_SBUS)? s : bswap32(s)
614#define ISP_IOXGET_8(isp, s, d) d = (*((uint8_t *)s))
615#define ISP_IOXGET_16(isp, s, d) \
616 d = (isp->isp_bustype == ISP_BT_SBUS)? \
617 *((uint16_t *)s) : bswap16(*((uint16_t *)s))
618#define ISP_IOXGET_32(isp, s, d) \
619 d = (isp->isp_bustype == ISP_BT_SBUS)? \
620 *((uint32_t *)s) : bswap32(*((uint32_t *)s))
621
622#else /* ISP_SBUS_SUPPORTED */
623#define ISP_IOXPUT_8(isp, s, d) *(d) = s
624#define ISP_IOXPUT_16(isp, s, d) *(d) = bswap16(s)
625#define ISP_IOXPUT_32(isp, s, d) *(d) = bswap32(s)
626#define ISP_IOXGET_8(isp, s, d) d = (*((uint8_t *)s))
627#define ISP_IOXGET_16(isp, s, d) d = bswap16(*((uint16_t *)s))
628#define ISP_IOXGET_32(isp, s, d) d = bswap32(*((uint32_t *)s))
629#endif
630#define ISP_SWIZZLE_NVRAM_WORD(isp, rp) *rp = bswap16(*rp)
631#define ISP_SWIZZLE_NVRAM_LONG(isp, rp) *rp = bswap32(*rp)
632
633#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)s))
634#define ISP_IOZGET_16(isp, s, d) d = (*((uint16_t *)s))
635#define ISP_IOZGET_32(isp, s, d) d = (*((uint32_t *)s))
636#define ISP_IOZPUT_8(isp, s, d) *(d) = s
637#define ISP_IOZPUT_16(isp, s, d) *(d) = s
638#define ISP_IOZPUT_32(isp, s, d) *(d) = s
639
640
641#else
642#define ISP_IOXPUT_8(isp, s, d) *(d) = s
643#define ISP_IOXPUT_16(isp, s, d) *(d) = s
644#define ISP_IOXPUT_32(isp, s, d) *(d) = s
645#define ISP_IOXGET_8(isp, s, d) d = *(s)
646#define ISP_IOXGET_16(isp, s, d) d = *(s)
647#define ISP_IOXGET_32(isp, s, d) d = *(s)
648#define ISP_SWIZZLE_NVRAM_WORD(isp, rp)
649#define ISP_SWIZZLE_NVRAM_LONG(isp, rp)
650
651#define ISP_IOZPUT_8(isp, s, d) *(d) = s
652#define ISP_IOZPUT_16(isp, s, d) *(d) = bswap16(s)
653#define ISP_IOZPUT_32(isp, s, d) *(d) = bswap32(s)
654
655#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)(s)))
656#define ISP_IOZGET_16(isp, s, d) d = bswap16(*((uint16_t *)(s)))
657#define ISP_IOZGET_32(isp, s, d) d = bswap32(*((uint32_t *)(s)))
658
659#endif
660
661#define ISP_SWAP16(isp, s) bswap16(s)
662#define ISP_SWAP32(isp, s) bswap32(s)
663
664/*
665 * Includes of common header files
666 */
667
668#include <dev/isp/ispreg.h>
669#include <dev/isp/ispvar.h>
670#include <dev/isp/ispmbox.h>
671
672/*
673 * isp_osinfo definiitions && shorthand
674 */
675#define SIMQFRZ_RESOURCE 0x1
676#define SIMQFRZ_LOOPDOWN 0x2
677#define SIMQFRZ_TIMED 0x4
678
679#define isp_dev isp_osinfo.dev
680
681/*
682 * prototypes for isp_pci && isp_freebsd to share
683 */
684extern int isp_attach(ispsoftc_t *);
685extern int isp_detach(ispsoftc_t *);
686extern void isp_uninit(ispsoftc_t *);
687extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int);
688
689/*
690 * driver global data
691 */
692extern int isp_announced;
693extern int isp_fabric_hysteresis;
694extern int isp_loop_down_limit;
695extern int isp_gone_device_time;
696extern int isp_quickboot_time;
697extern int isp_autoconfig;
698
699/*
700 * Platform private flags
701 */
702
703/*
704 * Platform Library Functions
705 */
706void isp_prt(ispsoftc_t *, int level, const char *, ...) __printflike(3, 4);
707void isp_xs_prt(ispsoftc_t *, XS_T *, int level, const char *, ...) __printflike(4, 5);
708uint64_t isp_nanotime_sub(struct timespec *, struct timespec *);
709int isp_mbox_acquire(ispsoftc_t *);
710void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
711void isp_mbox_notify_done(ispsoftc_t *);
712void isp_mbox_release(ispsoftc_t *);
713int isp_fc_scratch_acquire(ispsoftc_t *, int);
714int isp_mstohz(int);
715void isp_platform_intr(void *);
716void isp_common_dmateardown(ispsoftc_t *, struct ccb_scsiio *, uint32_t);
717int isp_fcp_next_crn(ispsoftc_t *, uint8_t *, XS_T *);
718
719/*
720 * Platform Version specific defines
721 */
722#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x)
723#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
724 bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
725 busdma_lock_mutex, &isp->isp_osinfo.lock, z)
726
727#define isp_setup_intr bus_setup_intr
728
729#define isp_sim_alloc(a, b, c, d, e, f, g, h) \
730 cam_sim_alloc(a, b, c, d, e, &(d)->isp_osinfo.lock, f, g, h)
731
732#define ISP_PATH_PRT(i, l, p, ...) \
733 if ((l) == ISP_LOGALL || ((l)& (i)->isp_dblev) != 0) { \
734 xpt_print(p, __VA_ARGS__); \
735 }
736
737/*
738 * Platform specific inline functions
739 */
740
741/*
742 * ISP General Library functions
743 */
744
745#include <dev/isp/isp_library.h>
746
747#endif /* _ISP_FREEBSD_H */
2/*-
3 * Qlogic ISP SCSI Host Adapter FreeBSD Wrapper Definitions
4 *
5 * Copyright (c) 1997-2008 by Matthew Jacob
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice immediately at the beginning of the file, without modification,
13 * this list of conditions, and the following disclaimer.
14 * 2. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29#ifndef _ISP_FREEBSD_H
30#define _ISP_FREEBSD_H
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/endian.h>
35#include <sys/lock.h>
36#include <sys/kernel.h>
37#include <sys/queue.h>
38#include <sys/malloc.h>
39#include <sys/mutex.h>
40#include <sys/condvar.h>
41#include <sys/sysctl.h>
42
43#include <sys/proc.h>
44#include <sys/bus.h>
45#include <sys/taskqueue.h>
46
47#include <machine/bus.h>
48#include <machine/cpu.h>
49#include <machine/stdarg.h>
50
51#include <cam/cam.h>
52#include <cam/cam_debug.h>
53#include <cam/cam_ccb.h>
54#include <cam/cam_sim.h>
55#include <cam/cam_xpt.h>
56#include <cam/cam_xpt_sim.h>
57#include <cam/cam_debug.h>
58#include <cam/scsi/scsi_all.h>
59#include <cam/scsi/scsi_message.h>
60
61#include "opt_ddb.h"
62#include "opt_isp.h"
63
64#define ISP_PLATFORM_VERSION_MAJOR 7
65#define ISP_PLATFORM_VERSION_MINOR 10
66
67/*
68 * Efficiency- get rid of SBus code && tests unless we need them.
69 */
70#ifdef __sparc64__
71#define ISP_SBUS_SUPPORTED 1
72#else
73#define ISP_SBUS_SUPPORTED 0
74#endif
75
76#define ISP_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
77
78#define N_XCMDS 64
79#define XCMD_SIZE 512
80struct ispsoftc;
81typedef union isp_ecmd {
82 union isp_ecmd * next;
83 uint8_t data[XCMD_SIZE];
84} isp_ecmd_t;
85isp_ecmd_t * isp_get_ecmd(struct ispsoftc *);
86void isp_put_ecmd(struct ispsoftc *, isp_ecmd_t *);
87
88#ifdef ISP_TARGET_MODE
89/* Not quite right, but there was no bump for this change */
90#if __FreeBSD_version < 225469
91#define SDFIXED(x) (&x)
92#else
93#define SDFIXED(x) ((struct scsi_sense_data_fixed *)(&x))
94#endif
95
96#define ISP_TARGET_FUNCTIONS 1
97#define ATPDPSIZE 4096
98#define ATPDPHASHSIZE 16
99#define ATPDPHASH(x) ((((x) >> 24) ^ ((x) >> 16) ^ ((x) >> 8) ^ (x)) & \
100 ((ATPDPHASHSIZE) - 1))
101
102#include <dev/isp/isp_target.h>
103typedef struct atio_private_data {
104 LIST_ENTRY(atio_private_data) next;
105 uint32_t orig_datalen;
106 uint32_t bytes_xfered;
107 uint32_t bytes_in_transit;
108 uint32_t tag; /* typically f/w RX_ID */
109 uint32_t lun;
110 uint32_t nphdl;
111 uint32_t sid;
112 uint32_t portid;
113 uint16_t rxid; /* wire rxid */
114 uint16_t oxid; /* wire oxid */
115 uint16_t word3; /* PRLI word3 params */
116 uint16_t ctcnt; /* number of CTIOs currently active */
117 uint8_t seqno; /* CTIO sequence number */
118 uint32_t
119 srr_notify_rcvd : 1,
120 cdb0 : 8,
121 sendst : 1,
122 dead : 1,
123 tattr : 3,
124 state : 3;
125 void * ests;
126 /*
127 * The current SRR notify copy
128 */
129 uint8_t srr[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
130 void * srr_ccb;
131 uint32_t nsrr;
132} atio_private_data_t;
133#define ATPD_STATE_FREE 0
134#define ATPD_STATE_ATIO 1
135#define ATPD_STATE_CAM 2
136#define ATPD_STATE_CTIO 3
137#define ATPD_STATE_LAST_CTIO 4
138#define ATPD_STATE_PDON 5
139
140#define ATPD_CCB_OUTSTANDING 16
141
142#define ATPD_SEQ_MASK 0x7f
143#define ATPD_SEQ_NOTIFY_CAM 0x80
144#define ATPD_SET_SEQNO(hdrp, atp) ((isphdr_t *)hdrp)->rqs_seqno &= ~ATPD_SEQ_MASK, ((isphdr_t *)hdrp)->rqs_seqno |= (atp)->seqno
145#define ATPD_GET_SEQNO(hdrp) (((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_MASK)
146#define ATPD_GET_NCAM(hdrp) ((((isphdr_t *)hdrp)->rqs_seqno & ATPD_SEQ_NOTIFY_CAM) != 0)
147
148typedef union inot_private_data inot_private_data_t;
149union inot_private_data {
150 inot_private_data_t *next;
151 struct {
152 isp_notify_t nt; /* must be first! */
153 uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
154 uint32_t tag_id, seq_id;
155 } rd;
156};
157typedef struct isp_timed_notify_ack {
158 void *isp;
159 void *not;
160 uint8_t data[64]; /* sb QENTRY_LEN, but order of definitions is wrong */
161} isp_tna_t;
162
163TAILQ_HEAD(isp_ccbq, ccb_hdr);
164typedef struct tstate {
165 SLIST_ENTRY(tstate) next;
166 struct cam_path *owner;
167 struct isp_ccbq waitq; /* waiting CCBs */
168 struct ccb_hdr_slist atios;
169 struct ccb_hdr_slist inots;
170 uint32_t hold;
171 uint32_t
172 enabled : 1,
173 atio_count : 15,
174 inot_count : 15;
175 inot_private_data_t * restart_queue;
176 inot_private_data_t * ntfree;
177 inot_private_data_t ntpool[ATPDPSIZE];
178 LIST_HEAD(, atio_private_data) atfree;
179 LIST_HEAD(, atio_private_data) atused[ATPDPHASHSIZE];
180 atio_private_data_t atpool[ATPDPSIZE];
181} tstate_t;
182
183#define LUN_HASH_SIZE 32
184#define LUN_HASH_FUNC(lun) ((lun) & (LUN_HASH_SIZE - 1))
185
186#endif
187
188/*
189 * Per command info.
190 */
191struct isp_pcmd {
192 struct isp_pcmd * next;
193 bus_dmamap_t dmap; /* dma map for this command */
194 struct ispsoftc * isp; /* containing isp */
195 struct callout wdog; /* watchdog timer */
196 uint32_t datalen; /* data length for this command (target mode only) */
197 uint8_t totslen; /* sense length on status response */
198 uint8_t cumslen; /* sense length on status response */
199 uint8_t crn; /* command reference number */
200};
201#define ISP_PCMD(ccb) (ccb)->ccb_h.spriv_ptr1
202#define PISP_PCMD(ccb) ((struct isp_pcmd *)ISP_PCMD(ccb))
203
204/*
205 * Per nexus info.
206 */
207struct isp_nexus {
208 struct isp_nexus * next;
209 uint32_t
210 crnseed : 8; /* next command reference number */
211 uint32_t
212 tgt : 16, /* TGT for target */
213 lun : 16; /* LUN for target */
214};
215#define NEXUS_HASH_WIDTH 32
216#define INITIAL_NEXUS_COUNT MAX_FC_TARG
217#define NEXUS_HASH(tgt, lun) ((tgt + lun) % NEXUS_HASH_WIDTH)
218
219/*
220 * Per channel information
221 */
222SLIST_HEAD(tslist, tstate);
223
224struct isp_fc {
225 struct cam_sim *sim;
226 struct cam_path *path;
227 struct ispsoftc *isp;
228 struct proc *kproc;
229 bus_dma_tag_t tdmat;
230 bus_dmamap_t tdmap;
231 uint64_t def_wwpn;
232 uint64_t def_wwnn;
233 uint32_t loop_down_time;
234 uint32_t loop_down_limit;
235 uint32_t gone_device_time;
236 /*
237 * Per target/lun info- just to keep a per-ITL nexus crn count
238 */
239 struct isp_nexus *nexus_hash[NEXUS_HASH_WIDTH];
240 struct isp_nexus *nexus_free_list;
241 uint32_t
242#ifdef ISP_TARGET_MODE
243#ifdef ISP_INTERNAL_TARGET
244 proc_active : 1,
245#endif
246 tm_luns_enabled : 1,
247 tm_enable_defer : 1,
248 tm_enabled : 1,
249#endif
250 simqfrozen : 3,
251 default_id : 8,
252 hysteresis : 8,
253 def_role : 2, /* default role */
254 gdt_running : 1,
255 loop_dead : 1,
256 fcbsy : 1,
257 ready : 1;
258 struct callout ldt; /* loop down timer */
259 struct callout gdt; /* gone device timer */
260 struct task ltask;
261 struct task gtask;
262#ifdef ISP_TARGET_MODE
263 struct tslist lun_hash[LUN_HASH_SIZE];
264#ifdef ISP_INTERNAL_TARGET
265 struct proc * target_proc;
266#endif
267#if defined(DEBUG)
268 unsigned int inject_lost_data_frame;
269#endif
270#endif
271};
272
273struct isp_spi {
274 struct cam_sim *sim;
275 struct cam_path *path;
276 uint32_t
277#ifdef ISP_TARGET_MODE
278#ifdef ISP_INTERNAL_TARGET
279 proc_active : 1,
280#endif
281 tm_luns_enabled : 1,
282 tm_enable_defer : 1,
283 tm_enabled : 1,
284#endif
285 simqfrozen : 3,
286 def_role : 2,
287 iid : 4;
288#ifdef ISP_TARGET_MODE
289 struct tslist lun_hash[LUN_HASH_SIZE];
290#ifdef ISP_INTERNAL_TARGET
291 struct proc * target_proc;
292#endif
293#endif
294};
295
296struct isposinfo {
297 /*
298 * Linkage, locking, and identity
299 */
300 struct mtx lock;
301 device_t dev;
302 struct cdev * cdev;
303 struct intr_config_hook ehook;
304 struct cam_devq * devq;
305
306 /*
307 * Firmware pointer
308 */
309 const struct firmware * fw;
310
311 /*
312 * DMA related sdtuff
313 */
314 bus_space_tag_t bus_tag;
315 bus_dma_tag_t dmat;
316 bus_space_handle_t bus_handle;
317 bus_dma_tag_t cdmat;
318 bus_dmamap_t cdmap;
319
320 /*
321 * Command and transaction related related stuff
322 */
323 struct isp_pcmd * pcmd_pool;
324 struct isp_pcmd * pcmd_free;
325
326 uint32_t
327#ifdef ISP_TARGET_MODE
328 tmwanted : 1,
329 tmbusy : 1,
330#else
331 : 2,
332#endif
333 sixtyfourbit : 1, /* sixtyfour bit platform */
334 timer_active : 1,
335 autoconf : 1,
336 ehook_active : 1,
337 disabled : 1,
338 mbox_sleeping : 1,
339 mbox_sleep_ok : 1,
340 mboxcmd_done : 1,
341 mboxbsy : 1;
342
343 struct callout tmo; /* general timer */
344
345 /*
346 * misc- needs to be sorted better XXXXXX
347 */
348 int framesize;
349 int exec_throttle;
350 int cont_max;
351
352#ifdef ISP_TARGET_MODE
353 cam_status * rptr;
354#endif
355
356 bus_addr_t ecmd_dma;
357 isp_ecmd_t * ecmd_base;
358 isp_ecmd_t * ecmd_free;
359
360 /*
361 * Per-type private storage...
362 */
363 union {
364 struct isp_fc *fc;
365 struct isp_spi *spi;
366 void *ptr;
367 } pc;
368};
369#define ISP_FC_PC(isp, chan) (&(isp)->isp_osinfo.pc.fc[(chan)])
370#define ISP_SPI_PC(isp, chan) (&(isp)->isp_osinfo.pc.spi[(chan)])
371#define ISP_GET_PC(isp, chan, tag, rslt) \
372 if (IS_SCSI(isp)) { \
373 rslt = ISP_SPI_PC(isp, chan)-> tag; \
374 } else { \
375 rslt = ISP_FC_PC(isp, chan)-> tag; \
376 }
377#define ISP_GET_PC_ADDR(isp, chan, tag, rp) \
378 if (IS_SCSI(isp)) { \
379 rp = &ISP_SPI_PC(isp, chan)-> tag; \
380 } else { \
381 rp = &ISP_FC_PC(isp, chan)-> tag; \
382 }
383#define ISP_SET_PC(isp, chan, tag, val) \
384 if (IS_SCSI(isp)) { \
385 ISP_SPI_PC(isp, chan)-> tag = val; \
386 } else { \
387 ISP_FC_PC(isp, chan)-> tag = val; \
388 }
389
390#define FCP_NEXT_CRN isp_fcp_next_crn
391#define isp_lock isp_osinfo.lock
392#define isp_bus_tag isp_osinfo.bus_tag
393#define isp_bus_handle isp_osinfo.bus_handle
394
395/*
396 * Locking macros...
397 */
398#define ISP_LOCK(isp) mtx_lock(&isp->isp_osinfo.lock)
399#define ISP_UNLOCK(isp) mtx_unlock(&isp->isp_osinfo.lock)
400
401/*
402 * Required Macros/Defines
403 */
404#define ISP_FC_SCRLEN 0x1000
405
406#define ISP_MEMZERO(a, b) memset(a, 0, b)
407#define ISP_MEMCPY memcpy
408#define ISP_SNPRINTF snprintf
409#define ISP_DELAY DELAY
410#define ISP_SLEEP(isp, x) DELAY(x)
411
412#define ISP_MIN imin
413
414#ifndef DIAGNOSTIC
415#define ISP_INLINE __inline
416#else
417#define ISP_INLINE
418#endif
419
420#define NANOTIME_T struct timespec
421#define GET_NANOTIME nanotime
422#define GET_NANOSEC(x) ((x)->tv_sec * 1000000000 + (x)->tv_nsec)
423#define NANOTIME_SUB isp_nanotime_sub
424
425#define MAXISPREQUEST(isp) ((IS_FC(isp) || IS_ULTRA2(isp))? 1024 : 256)
426
427#define MEMORYBARRIER(isp, type, offset, size, chan) \
428switch (type) { \
429case SYNC_SFORDEV: \
430{ \
431 struct isp_fc *fc = ISP_FC_PC(isp, chan); \
432 bus_dmamap_sync(fc->tdmat, fc->tdmap, \
433 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \
434 break; \
435} \
436case SYNC_REQUEST: \
437 bus_dmamap_sync(isp->isp_osinfo.cdmat, \
438 isp->isp_osinfo.cdmap, \
439 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); \
440 break; \
441case SYNC_SFORCPU: \
442{ \
443 struct isp_fc *fc = ISP_FC_PC(isp, chan); \
444 bus_dmamap_sync(fc->tdmat, fc->tdmap, \
445 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \
446 break; \
447} \
448case SYNC_RESULT: \
449 bus_dmamap_sync(isp->isp_osinfo.cdmat, \
450 isp->isp_osinfo.cdmap, \
451 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); \
452 break; \
453case SYNC_REG: \
454 bus_space_barrier(isp->isp_osinfo.bus_tag, \
455 isp->isp_osinfo.bus_handle, offset, size, \
456 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); \
457 break; \
458default: \
459 break; \
460}
461
462#define MBOX_ACQUIRE isp_mbox_acquire
463#define MBOX_WAIT_COMPLETE isp_mbox_wait_complete
464#define MBOX_NOTIFY_COMPLETE isp_mbox_notify_done
465#define MBOX_RELEASE isp_mbox_release
466
467#define FC_SCRATCH_ACQUIRE isp_fc_scratch_acquire
468#define FC_SCRATCH_RELEASE(isp, chan) isp->isp_osinfo.pc.fc[chan].fcbsy = 0
469
470#ifndef SCSI_GOOD
471#define SCSI_GOOD SCSI_STATUS_OK
472#endif
473#ifndef SCSI_CHECK
474#define SCSI_CHECK SCSI_STATUS_CHECK_COND
475#endif
476#ifndef SCSI_BUSY
477#define SCSI_BUSY SCSI_STATUS_BUSY
478#endif
479#ifndef SCSI_QFULL
480#define SCSI_QFULL SCSI_STATUS_QUEUE_FULL
481#endif
482
483#define XS_T struct ccb_scsiio
484#define XS_DMA_ADDR_T bus_addr_t
485#define XS_GET_DMA64_SEG(a, b, c) \
486{ \
487 ispds64_t *d = a; \
488 bus_dma_segment_t *e = b; \
489 uint32_t f = c; \
490 e += f; \
491 d->ds_base = DMA_LO32(e->ds_addr); \
492 d->ds_basehi = DMA_HI32(e->ds_addr); \
493 d->ds_count = e->ds_len; \
494}
495#define XS_GET_DMA_SEG(a, b, c) \
496{ \
497 ispds_t *d = a; \
498 bus_dma_segment_t *e = b; \
499 uint32_t f = c; \
500 e += f; \
501 d->ds_base = DMA_LO32(e->ds_addr); \
502 d->ds_count = e->ds_len; \
503}
504#define XS_ISP(ccb) cam_sim_softc(xpt_path_sim((ccb)->ccb_h.path))
505#define XS_CHANNEL(ccb) cam_sim_bus(xpt_path_sim((ccb)->ccb_h.path))
506#define XS_TGT(ccb) (ccb)->ccb_h.target_id
507#define XS_LUN(ccb) (uint32_t)((ccb)->ccb_h.target_lun)
508
509#define XS_CDBP(ccb) \
510 (((ccb)->ccb_h.flags & CAM_CDB_POINTER)? \
511 (ccb)->cdb_io.cdb_ptr : (ccb)->cdb_io.cdb_bytes)
512
513#define XS_CDBLEN(ccb) (ccb)->cdb_len
514#define XS_XFRLEN(ccb) (ccb)->dxfer_len
515#define XS_TIME(ccb) (ccb)->ccb_h.timeout
516#define XS_GET_RESID(ccb) (ccb)->resid
517#define XS_SET_RESID(ccb, r) (ccb)->resid = r
518#define XS_STSP(ccb) (&(ccb)->scsi_status)
519#define XS_SNSP(ccb) (&(ccb)->sense_data)
520
521#define XS_TOT_SNSLEN(ccb) ccb->sense_len
522#define XS_CUR_SNSLEN(ccb) (ccb->sense_len - ccb->sense_resid)
523
524#define XS_SNSKEY(ccb) (scsi_get_sense_key(&(ccb)->sense_data, \
525 ccb->sense_len - ccb->sense_resid, 1))
526
527#define XS_SNSASC(ccb) (scsi_get_asc(&(ccb)->sense_data, \
528 ccb->sense_len - ccb->sense_resid, 1))
529
530#define XS_SNSASCQ(ccb) (scsi_get_ascq(&(ccb)->sense_data, \
531 ccb->sense_len - ccb->sense_resid, 1))
532#define XS_TAG_P(ccb) \
533 (((ccb)->ccb_h.flags & CAM_TAG_ACTION_VALID) && \
534 (ccb)->tag_action != CAM_TAG_ACTION_NONE)
535
536#define XS_TAG_TYPE(ccb) \
537 ((ccb->tag_action == MSG_SIMPLE_Q_TAG)? REQFLAG_STAG : \
538 ((ccb->tag_action == MSG_HEAD_OF_Q_TAG)? REQFLAG_HTAG : REQFLAG_OTAG))
539
540
541#define XS_SETERR(ccb, v) (ccb)->ccb_h.status &= ~CAM_STATUS_MASK, \
542 (ccb)->ccb_h.status |= v
543
544# define HBA_NOERROR CAM_REQ_INPROG
545# define HBA_BOTCH CAM_UNREC_HBA_ERROR
546# define HBA_CMDTIMEOUT CAM_CMD_TIMEOUT
547# define HBA_SELTIMEOUT CAM_SEL_TIMEOUT
548# define HBA_TGTBSY CAM_SCSI_STATUS_ERROR
549# define HBA_BUSRESET CAM_SCSI_BUS_RESET
550# define HBA_ABORTED CAM_REQ_ABORTED
551# define HBA_DATAOVR CAM_DATA_RUN_ERR
552# define HBA_ARQFAIL CAM_AUTOSENSE_FAIL
553
554
555#define XS_ERR(ccb) ((ccb)->ccb_h.status & CAM_STATUS_MASK)
556
557#define XS_NOERR(ccb) (((ccb)->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)
558
559#define XS_INITERR(ccb) XS_SETERR(ccb, CAM_REQ_INPROG), ccb->sense_resid = ccb->sense_len
560
561#define XS_SAVE_SENSE(xs, sense_ptr, totslen, slen) do { \
562 uint32_t tlen = slen; \
563 if (tlen > (xs)->sense_len) \
564 tlen = (xs)->sense_len; \
565 PISP_PCMD(xs)->totslen = imin((xs)->sense_len, totslen); \
566 PISP_PCMD(xs)->cumslen = tlen; \
567 memcpy(&(xs)->sense_data, sense_ptr, tlen); \
568 (xs)->sense_resid = (xs)->sense_len - tlen; \
569 (xs)->ccb_h.status |= CAM_AUTOSNS_VALID; \
570 } while (0)
571
572#define XS_SENSE_APPEND(xs, xsnsp, xsnsl) do { \
573 uint32_t off = PISP_PCMD(xs)->cumslen; \
574 uint8_t *ptr = &((uint8_t *)(&(xs)->sense_data))[off]; \
575 uint32_t amt = imin(xsnsl, PISP_PCMD(xs)->totslen - off); \
576 if (amt) { \
577 memcpy(ptr, xsnsp, amt); \
578 (xs)->sense_resid -= amt; \
579 PISP_PCMD(xs)->cumslen += amt; \
580 } \
581 } while (0)
582
583#define XS_SENSE_VALID(xs) (((xs)->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
584
585#define DEFAULT_FRAMESIZE(isp) isp->isp_osinfo.framesize
586#define DEFAULT_EXEC_THROTTLE(isp) isp->isp_osinfo.exec_throttle
587
588#define GET_DEFAULT_ROLE(isp, chan) \
589 (IS_FC(isp)? ISP_FC_PC(isp, chan)->def_role : ISP_SPI_PC(isp, chan)->def_role)
590#define SET_DEFAULT_ROLE(isp, chan, val) \
591 if (IS_FC(isp)) { \
592 ISP_FC_PC(isp, chan)->def_role = val; \
593 } else { \
594 ISP_SPI_PC(isp, chan)->def_role = val; \
595 }
596
597#define DEFAULT_IID(isp, chan) isp->isp_osinfo.pc.spi[chan].iid
598
599#define DEFAULT_LOOPID(x, chan) isp->isp_osinfo.pc.fc[chan].default_id
600
601#define DEFAULT_NODEWWN(isp, chan) isp_default_wwn(isp, chan, 0, 1)
602#define DEFAULT_PORTWWN(isp, chan) isp_default_wwn(isp, chan, 0, 0)
603#define ACTIVE_NODEWWN(isp, chan) isp_default_wwn(isp, chan, 1, 1)
604#define ACTIVE_PORTWWN(isp, chan) isp_default_wwn(isp, chan, 1, 0)
605
606
607#if BYTE_ORDER == BIG_ENDIAN
608#ifdef ISP_SBUS_SUPPORTED
609#define ISP_IOXPUT_8(isp, s, d) *(d) = s
610#define ISP_IOXPUT_16(isp, s, d) \
611 *(d) = (isp->isp_bustype == ISP_BT_SBUS)? s : bswap16(s)
612#define ISP_IOXPUT_32(isp, s, d) \
613 *(d) = (isp->isp_bustype == ISP_BT_SBUS)? s : bswap32(s)
614#define ISP_IOXGET_8(isp, s, d) d = (*((uint8_t *)s))
615#define ISP_IOXGET_16(isp, s, d) \
616 d = (isp->isp_bustype == ISP_BT_SBUS)? \
617 *((uint16_t *)s) : bswap16(*((uint16_t *)s))
618#define ISP_IOXGET_32(isp, s, d) \
619 d = (isp->isp_bustype == ISP_BT_SBUS)? \
620 *((uint32_t *)s) : bswap32(*((uint32_t *)s))
621
622#else /* ISP_SBUS_SUPPORTED */
623#define ISP_IOXPUT_8(isp, s, d) *(d) = s
624#define ISP_IOXPUT_16(isp, s, d) *(d) = bswap16(s)
625#define ISP_IOXPUT_32(isp, s, d) *(d) = bswap32(s)
626#define ISP_IOXGET_8(isp, s, d) d = (*((uint8_t *)s))
627#define ISP_IOXGET_16(isp, s, d) d = bswap16(*((uint16_t *)s))
628#define ISP_IOXGET_32(isp, s, d) d = bswap32(*((uint32_t *)s))
629#endif
630#define ISP_SWIZZLE_NVRAM_WORD(isp, rp) *rp = bswap16(*rp)
631#define ISP_SWIZZLE_NVRAM_LONG(isp, rp) *rp = bswap32(*rp)
632
633#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)s))
634#define ISP_IOZGET_16(isp, s, d) d = (*((uint16_t *)s))
635#define ISP_IOZGET_32(isp, s, d) d = (*((uint32_t *)s))
636#define ISP_IOZPUT_8(isp, s, d) *(d) = s
637#define ISP_IOZPUT_16(isp, s, d) *(d) = s
638#define ISP_IOZPUT_32(isp, s, d) *(d) = s
639
640
641#else
642#define ISP_IOXPUT_8(isp, s, d) *(d) = s
643#define ISP_IOXPUT_16(isp, s, d) *(d) = s
644#define ISP_IOXPUT_32(isp, s, d) *(d) = s
645#define ISP_IOXGET_8(isp, s, d) d = *(s)
646#define ISP_IOXGET_16(isp, s, d) d = *(s)
647#define ISP_IOXGET_32(isp, s, d) d = *(s)
648#define ISP_SWIZZLE_NVRAM_WORD(isp, rp)
649#define ISP_SWIZZLE_NVRAM_LONG(isp, rp)
650
651#define ISP_IOZPUT_8(isp, s, d) *(d) = s
652#define ISP_IOZPUT_16(isp, s, d) *(d) = bswap16(s)
653#define ISP_IOZPUT_32(isp, s, d) *(d) = bswap32(s)
654
655#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)(s)))
656#define ISP_IOZGET_16(isp, s, d) d = bswap16(*((uint16_t *)(s)))
657#define ISP_IOZGET_32(isp, s, d) d = bswap32(*((uint32_t *)(s)))
658
659#endif
660
661#define ISP_SWAP16(isp, s) bswap16(s)
662#define ISP_SWAP32(isp, s) bswap32(s)
663
664/*
665 * Includes of common header files
666 */
667
668#include <dev/isp/ispreg.h>
669#include <dev/isp/ispvar.h>
670#include <dev/isp/ispmbox.h>
671
672/*
673 * isp_osinfo definiitions && shorthand
674 */
675#define SIMQFRZ_RESOURCE 0x1
676#define SIMQFRZ_LOOPDOWN 0x2
677#define SIMQFRZ_TIMED 0x4
678
679#define isp_dev isp_osinfo.dev
680
681/*
682 * prototypes for isp_pci && isp_freebsd to share
683 */
684extern int isp_attach(ispsoftc_t *);
685extern int isp_detach(ispsoftc_t *);
686extern void isp_uninit(ispsoftc_t *);
687extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int);
688
689/*
690 * driver global data
691 */
692extern int isp_announced;
693extern int isp_fabric_hysteresis;
694extern int isp_loop_down_limit;
695extern int isp_gone_device_time;
696extern int isp_quickboot_time;
697extern int isp_autoconfig;
698
699/*
700 * Platform private flags
701 */
702
703/*
704 * Platform Library Functions
705 */
706void isp_prt(ispsoftc_t *, int level, const char *, ...) __printflike(3, 4);
707void isp_xs_prt(ispsoftc_t *, XS_T *, int level, const char *, ...) __printflike(4, 5);
708uint64_t isp_nanotime_sub(struct timespec *, struct timespec *);
709int isp_mbox_acquire(ispsoftc_t *);
710void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
711void isp_mbox_notify_done(ispsoftc_t *);
712void isp_mbox_release(ispsoftc_t *);
713int isp_fc_scratch_acquire(ispsoftc_t *, int);
714int isp_mstohz(int);
715void isp_platform_intr(void *);
716void isp_common_dmateardown(ispsoftc_t *, struct ccb_scsiio *, uint32_t);
717int isp_fcp_next_crn(ispsoftc_t *, uint8_t *, XS_T *);
718
719/*
720 * Platform Version specific defines
721 */
722#define BUS_DMA_ROOTARG(x) bus_get_dma_tag(x)
723#define isp_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, z) \
724 bus_dma_tag_create(a, b, c, d, e, f, g, h, i, j, k, \
725 busdma_lock_mutex, &isp->isp_osinfo.lock, z)
726
727#define isp_setup_intr bus_setup_intr
728
729#define isp_sim_alloc(a, b, c, d, e, f, g, h) \
730 cam_sim_alloc(a, b, c, d, e, &(d)->isp_osinfo.lock, f, g, h)
731
732#define ISP_PATH_PRT(i, l, p, ...) \
733 if ((l) == ISP_LOGALL || ((l)& (i)->isp_dblev) != 0) { \
734 xpt_print(p, __VA_ARGS__); \
735 }
736
737/*
738 * Platform specific inline functions
739 */
740
741/*
742 * ISP General Library functions
743 */
744
745#include <dev/isp/isp_library.h>
746
747#endif /* _ISP_FREEBSD_H */