summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun/sys/scsi/adapters/fasvar.h
blob: da2d38ae32ef76054cad5b0180328a70a983e16c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_SCSI_ADAPTERS_FASVAR_H
#define	_SYS_SCSI_ADAPTERS_FASVAR_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * QLogic FAS (Enhanced	Scsi Processor)	Definitions,
 * Software && Hardware.
 */

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/note.h>

/*
 * Compile options
 */
#if DEBUG
#define	FASDEBUG		/* turn	on debugging code */
#define	FASTEST
#endif /* DEBUG	*/

/*
 * Software Definitions
 */
#define	POLL_TIMEOUT		(2 * SCSI_POLL_TIMEOUT * 1000000)
#define	SHORT_POLL_TIMEOUT	(1000000) /* in	usec, about 1 secs */
#define	FAS_MUTEX(fas)		(&(fas)->f_mutex)
#define	FAS_CV(fas)		(&(fas)->f_cv)
#define	FAS_INITIAL_SOFT_SPACE	4	/* Used	for the	softstate_init func */
#define	FAS_QUIESCE_TIMEOUT	1	/* 1 sec */

/*
 * Data	Structure for this Host	Adapter.
 *
 * structure to	hold active outstanding	cmds
 */
struct f_slots {
	ushort_t		f_dups;
	ushort_t		f_tags;
	int			f_timeout;
	int			f_timebase;
				/* t_slot size is 1 for	non-tagged, and	*/
				/* 256 for tagged targets		*/
	ushort_t		f_n_slots; /* number of	a_slots		*/
	ushort_t		f_size;
	struct fas_cmd		*f_slot[1];	/* may be for 256 for TQ */
};

#define	FAS_F_SLOTS_SIZE_TQ	(sizeof	(struct	f_slots) + \
			(sizeof	(struct	fas_cmd	*) * (NTAGS -1)))
#define	FAS_F_SLOT_SIZE		(sizeof	(struct	f_slots))

/*
 * HBA interface macros
 */
#define	SDEV2TRAN(sd)		((sd)->sd_address.a_hba_tran)
#define	SDEV2ADDR(sd)		(&((sd)->sd_address))
#define	PKT2TRAN(pkt)		((pkt)->pkt_address.a_hba_tran)
#define	ADDR2TRAN(ap)		((ap)->a_hba_tran)

#define	TRAN2FAS(tran)		((struct fas *)(tran)->tran_hba_private)
#define	SDEV2FAS(sd)		(TRAN2FAS(SDEV2TRAN(sd)))
#define	PKT2FAS(pkt)		(TRAN2FAS(PKT2TRAN(pkt)))
#define	ADDR2FAS(ap)		(TRAN2FAS(ADDR2TRAN(ap)))


/*
 * soft	state information for this host	adapter
 */
#define	N_SLOTS			(NTARGETS_WIDE*NLUNS_PER_TARGET)
#define	REG_TRACE_BUF_SIZE	1024

struct fas {
	int		f_instance;
	/*
	 * Transport structure for this	instance of the	hba
	 */
	scsi_hba_tran_t	*f_tran;

	/*
	 * dev_info_t reference
	 */
	dev_info_t	*f_dev;

	/*
	 * mutex to protect softstate and hw regs
	 */
	kmutex_t	f_mutex;

	/*
	 * Interrupt block cookie
	 */
	ddi_iblock_cookie_t	f_iblock;

	/*
	 * Next	in a linked list of host adapters
	 */
	struct fas	*f_next;

	/*
	 * Type	byte for this host adapter
	 * and rev of the FEPS chip
	 */
	uchar_t		f_type;
	uchar_t		f_hm_rev;

	/*
	 * value for configuration register 1.
	 * Also	contains Initiator Id.
	 */
	uint8_t		f_fasconf;

	/*
	 * value for configuration register 2
	 */
	uint8_t		f_fasconf2;

	/*
	 * value for configuration register 3
	 */
	uint8_t		f_fasconf3[NTARGETS_WIDE];
	uint8_t		f_fasconf3_reg_last;

	/*
	 * clock conversion register value for this host adapter.
	 * clock cycle value * 1000 for	this host adapter,
	 * to retain 5 significant digits.
	 */
	uchar_t		f_clock_conv;
	ushort_t	f_clock_cycle;

	/*
	 * selection timeout register value
	 */
	uint8_t		f_stval;

	/*
	 * State of the	host adapter
	 */
	uchar_t	f_sdtr_sent;	/* Count of sync data negotiation messages: */
				/* zeroed for every selection attempt, */
				/* every reconnection, and every disconnect */
				/* interrupt. Each SYNCHRONOUS DATA TRANSFER */
				/* message, both coming	from the target, and */
				/* sent	to the target, causes this tag to be */
				/* incremented.	This allows the	received */
				/* message handling to determine whether */
				/* a received SYNCHRONOUS DATA TRANSFER	*/
				/* message is in response to one that we */
				/* sent. */
	uchar_t	f_wdtr_sent;	/* same	for wide negotations */
	uchar_t	f_stat;		/* soft	copy of	status register	*/
	uchar_t	f_stat2;	/* soft	copy of	status2	register */
	uchar_t	f_intr;		/* soft	copy of	interrupt register */
	uchar_t	f_step;		/* soft	copy of	step register */
	uchar_t	f_abort_msg_sent; /* indicates that abort message went out */
	uchar_t	f_reset_msg_sent; /* indicates that device reset message */
				/* went	out */
	uchar_t	f_last_cmd;	/* last	cmd sent to fas	chip */

	ushort_t f_state;	/* state of the	driver */
	ushort_t f_laststate;	/* last	state of the driver */
	uchar_t	f_suspended;	/* true	if driver is suspended */
	uchar_t	f_dslot;	/* delta to next slot */
	uchar_t	f_idcode;	/* chips idcode	*/
	uchar_t	f_polled_intr;	/* current interrupt was polled. */

	/*
	 * Message handling: enough space is reserved for the expected length
	 * of all messages we could either send	or receive.
	 *
	 * For sending,	we expect to send only SYNCHRONOUS extended messages
	 * (5 bytes). We keep a	history	of the last message sent, and in order
	 * to control which message to send, an	output message length is set
	 * to indicate whether and how much of the message area	is to be used
	 * in sending a	message. If a target shifts to message out phase
	 * unexpectedly, the default action will be to send a MSG_NOP message.
	 *
	 * After the successful	transmission of	a message, the initial message
	 * byte	is moved to the	f_last_msgout area for tracking	what was the
	 * last	message	sent.
	 */

#define	OMSGSIZE	12
	uchar_t		f_cur_msgout[OMSGSIZE];
	uchar_t		f_last_msgout;
	uchar_t		f_omsglen;


	/*
	 * We expect, at, most,	to receive a maximum of	7 bytes
	 * of an incoming extended message (MODIFY DATA	POINTER),
	 * and thus reserve enough space for that.
	 */
#define	IMSGSIZE	8
	uchar_t		f_imsgarea[IMSGSIZE];

	/*
	 * These are used to index how far we've
	 * gone	in receiving incoming  messages.
	 */
	uchar_t		f_imsglen;
	uchar_t		f_imsgindex;

	/*
	 * Saved last msgin.
	 */
	uchar_t		f_last_msgin;

	/*
	 * round robin scheduling of requests in fas_ustart()
	 */
	uchar_t		f_next_slot;

	/*
	 * save	reselecting slot when waiting for tag bytes
	 */
	uchar_t		f_resel_slot;

	/*
	 * Target information
	 *	Synchronous SCSI Information,
	 *	Disconnect/reconnect capabilities
	 *	Noise Susceptibility
	 */
	uchar_t	f_offset[NTARGETS_WIDE]; /* synch offset + req-ack delay */
	uchar_t	f_sync_period[NTARGETS_WIDE]; /* synch period reg val */
	uchar_t	f_neg_period[NTARGETS_WIDE]; /*	synch periods (negotiated) */
	ushort_t f_backoff;		/* sync/wide backoff bit mask */
	uchar_t	f_req_ack_delay;	/* req ack delay in offset reg */
	uchar_t	f_offset_reg_last;	/* save	last offset value */
	uchar_t	f_period_reg_last;	/* save	last period value */

	/*
	 * fifo	length and fifo	contents stored	here before reading intr reg
	 */
	uchar_t		f_fifolen;
	uchar_t		f_fifo[2*FIFOSIZE];

	/*
	 * These ushort_t's are  bit maps	for targets
	 */
	ushort_t	f_wide_known;	/* wide	negotiate on	next cmd */
	ushort_t	f_nowide;	/* no wide for this target */
	ushort_t	f_wide_enabled;	/* wide	enabled	for this target	*/

	ushort_t	f_sync_known;	/* sync	negotiate on next cmd */
	ushort_t	f_nosync;	/* no sync for this target */
	ushort_t	f_sync_enabled;	/* sync	enabled	for this target	*/

	/*
	 * This ushort_t is a bit map for targets to
	 * disable sync on request from the target driver
	 */
	ushort_t	f_force_async;
	ushort_t	f_force_narrow;

	/*
	 * This	ushort_t is a bit map for targets who don't appear
	 * to be able to support tagged	commands.
	 */
	ushort_t	f_notag;

	/*
	 * This ushort_t is a bit map for targets who need to have
	 * their properties update deferred.
	 */
	ushort_t	f_props_update;

	/*
	 * scsi_options	for bus	and per	target
	 */
	int		f_target_scsi_options_defined;
	int		f_scsi_options;
	int		f_target_scsi_options[NTARGETS_WIDE];

	/*
	 * tag age limit per bus
	 */
	int		f_scsi_tag_age_limit;

	/*
	 * scsi	reset delay per	bus
	 */
	uint_t		f_scsi_reset_delay;

	/*
	 * Scratch Buffer, allocated out of iopbmap for	commands
	 * The same size as the	FAS's fifo.
	 */
	uchar_t		*f_cmdarea;

	/*
	 * shadow copy of dma_csr to avoid unnecessary I/O reads which are
	 * expensive
	 */
	uint32_t	f_dma_csr;

	/*
	 * Scratch Buffer DMA cookie and handle	for cmdarea
	 */
	ddi_dma_cookie_t	f_dmacookie;
	ddi_dma_handle_t	f_dmahandle;

	/*
	 * dma attrs for fas scsi engine
	 */
	ddi_dma_attr_t		*f_dma_attr;

	/*
	 * critical counters
	 */
	short	f_ncmds;	/* number of commands stored here at present */
	short	f_ndisc;	/* number of disconnected cmds at present */

	/*
	 * Hardware pointers
	 *
	 * Pointer to mapped in	FAS registers
	 */
	volatile struct	fasreg *f_reg;

	/*
	 * Pointer to mapped in	DMA Gate Array registers
	 */

	volatile struct	dma    *f_dma;

	/*
	 * last	and current state, queues
	 */
	uint32_t		f_lastdma;	/* last	dma address */
	uint32_t		f_lastcount;	/* last	dma count */

	struct fas_cmd		*f_current_sp;	/* currently active cmd	*/
	struct f_slots		*f_active[N_SLOTS]; /* outstanding cmds	*/

	struct fas_cmd		*f_readyf[N_SLOTS]; /* waiting cmds */
	struct fas_cmd		*f_readyb[N_SLOTS];

				/*
				 * if throttle >= 0 then
				 * continue submitting cmds
				 * if throttle == 0 then hold cmds
				 * if throttle == -1 then drain
				 * if throttle == -2 do special handling
				 * for queue full
				 * f_throttle and f_tcmds are not part of
				 * f_active so fas_ustart() can	walk thru
				 * these more efficiently
				 */
	short			f_throttle[N_SLOTS];

				/*
				 * number of disconnected + active commands
				 * (i.e. stored in the f_active list) for
				 * the slot
				 */
	short			f_tcmds[N_SLOTS];

				/*
				 * if a	device reset has been performed, a
				 * delay is required before accessing the target
				 * again; reset	delays are in milli secs
				 * (assuming that reset	watchdog runs every
				 * scsi-watchdog-tick  milli secs;
				 * the watchdog	decrements the reset delay)
				 */
	int			f_reset_delay[NTARGETS_WIDE];

	/*
	 * list	for auto request sense packets
	 */
	struct fas_cmd		*f_arq_pkt[N_SLOTS];

	/*
	 * queue of packets that need callback and other callback info
	 */
	struct fas_cmd		*f_c_qf;
	struct fas_cmd		*f_c_qb;
	kmutex_t		f_c_mutex;
	int			f_c_in_callback;

	/*
	 * a queue for packets in case the fas mutex is	locked
	 */
	kmutex_t		f_waitQ_mutex;
	struct fas_cmd		*f_waitf;
	struct fas_cmd		*f_waitb;

	/*
	 * list	of reset notification requests
	 */
	struct scsi_reset_notify_entry	 *f_reset_notify_listf;

	/*
	 * qfull handling
	 */
	uchar_t			f_qfull_retries[NTARGETS_WIDE];
	ushort_t		f_qfull_retry_interval[NTARGETS_WIDE];
	timeout_id_t		f_restart_cmd_timeid;

	/*
	 * kmem	cache for packets
	 */
	struct kmem_cache	*f_kmem_cache;

	/*
	 * data access handle for register mapping
	 */
	ddi_acc_handle_t	f_regs_acc_handle;
	/*
	 * data access handle for cmd area
	 */
	ddi_acc_handle_t	f_cmdarea_acc_handle;
	/*
	 * data access handle for dma
	 */
	ddi_acc_handle_t	f_dmar_acc_handle;

	/*
	 * state flags
	 */
	uint_t			f_flags;

	/*
	 * cv for bus quiesce/unquiesce
	 */
	kcondvar_t		f_cv;

	/*
	 * soft state flags
	 */
	uint_t			f_softstate;

	/*
	 * quiesce timeout ID
	 */
	timeout_id_t		f_quiesce_timeid;

	/*
	 * kstat_intr support
	 */
	struct kstat		*f_intr_kstat;

#ifdef FASDEBUG
	/*
	 * register trace for debugging
	 */
	uint_t			f_reg_trace_index;
	uint_t			f_reg_trace[REG_TRACE_BUF_SIZE+1];

	uint_t			f_reserved[256];

	uint_t			f_reg_reads;
	uint_t			f_reg_dma_reads;
	uint_t			f_reg_writes;
	uint_t			f_reg_dma_writes;
	uint_t			f_reg_cmds;
	uint_t			f_total_cmds;
#endif
};
_NOTE(MUTEX_PROTECTS_DATA(fas::f_mutex,	fas))
_NOTE(MUTEX_PROTECTS_DATA(fas::f_waitQ_mutex, fas::f_waitf fas::f_waitb))
_NOTE(MUTEX_PROTECTS_DATA(fas::f_c_mutex, fas::f_c_qf fas::f_c_qb
	fas::f_c_in_callback))
_NOTE(DATA_READABLE_WITHOUT_LOCK(fas::f_flags))

_NOTE(SCHEME_PROTECTS_DATA("unique per packet or safe sharing",
    scsi_cdb scsi_status scsi_pkt buf))
_NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
_NOTE(SCHEME_PROTECTS_DATA("safe sharing", fas::f_next fas::f_state))
_NOTE(SCHEME_PROTECTS_DATA("safe sharing",
	fas::f_dma fas::f_dma_attr fas::f_hm_rev))
_NOTE(SCHEME_PROTECTS_DATA("stable data",
	fas::f_target_scsi_options fas::f_scsi_options))
_NOTE(SCHEME_PROTECTS_DATA("stable data", fas::f_instance))
_NOTE(SCHEME_PROTECTS_DATA("only debugging",
	fas::f_reg_trace_index fas::f_reg_trace))
_NOTE(SCHEME_PROTECTS_DATA("protected by kmem lock", fas::f_kmem_cache))
_NOTE(SCHEME_PROTECTS_DATA("safe sharing",
	fas::f_notag fas::f_suspended fas::f_ndisc))
_NOTE(SCHEME_PROTECTS_DATA("stable data", fas::f_dev fas::f_tran))
_NOTE(SCHEME_PROTECTS_DATA("only debugging", fas::f_reg_dma_reads))
_NOTE(SCHEME_PROTECTS_DATA("safe sharing", fas::f_quiesce_timeid))

/*
 * kstat_intr support
 */

#define	FAS_KSTAT_INTR(fas)  KSTAT_INTR_PTR(fas->f_intr_kstat)->\
					intrs[KSTAT_INTR_HARD]++

/*
 * defaults for	the global properties
 */
#define	DEFAULT_SCSI_OPTIONS	SCSI_OPTIONS_DR
#define	DEFAULT_TAG_AGE_LIMIT	2
#define	DEFAULT_WD_TICK		10

/*
 * define for f_flags
 */
#define	FAS_FLG_NOTIMEOUTS	0x0001	/* disallow timeout rescheduling */

#define	FAS_CAN_SCHED	((fas->f_flags & FAS_FLG_NOTIMEOUTS) == 0)

/*
 * f_req_ack_delay:
 */
#define	DEFAULT_REQ_ACK_DELAY	0x50	/* delay assert	period by 1/2 cycle */

/*
 * Representations of Driver states (stored in tags f_state && f_laststate).
 *
 * Totally idle. There may or may not disconnected commands still
 * running on targets.
 */
#define	STATE_FREE	0x00

/*
 * Selecting States. These states represent a selection	attempt
 * for a target.
 */
#define	STATE_SELECT_NORMAL	0x0100
#define	STATE_SELECT_N_STOP	0x0200
#define	STATE_SELECT_N_SENDMSG	0x0400
#define	STATE_SYNC_ASKING	0x0800
#define	STATE_SELECT_N_TAG	0x1000
#define	STATE_SELECTING		0xFF00	/* Select mask */


/*
 * When	the driver is neither idle nor selecting, it is	in one of
 * the information transfer phases. These states are not unique
 * bit patterns- they are simple numbers used to mark transitions.
 * They	must start at 1	and proceed sequentially upwards and
 * match the indexing of function vectors declared in the function
 * fas_phasemanage().
 */
#define	STATE_ITPHASES		0x00FF	/* Phase mask */

/*
 * These states	cover finishing	sending	a command out (if it wasn't
 * sent	as a side-effect of selecting),	or the case of starting
 * a command that was linked to	the previous command (i.e., no
 * selection phase for this particular command as the target
 * remained connected when the previous	command	completed).
 */
#define	ACTS_CMD_START		0x01
#define	ACTS_CMD_DONE		0x02

/*
 * These states	are the	begin and end of sending out a message.
 * The message to be sent is stored in the field f_msgout (see above).
 */
#define	ACTS_MSG_OUT		0x03
#define	ACTS_MSG_OUT_DONE	0x04

/*
 * These states	are the	beginning, middle, and end of incoming messages.
 *
 */
#define	ACTS_MSG_IN		0x05
#define	ACTS_MSG_IN_MORE	0x06
#define	ACTS_MSG_IN_DONE	0x07

/*
 * This	state is reached when the target may be	getting
 * ready to clear the bus (disconnect or command complete).
 */
#define	ACTS_CLEARING		0x08

/*
 * These states	elide the begin	and end	of a DATA phase
 */
#define	ACTS_DATA		0x09
#define	ACTS_DATA_DONE		0x0A

/*
 * This	state indicates	that we	were in	status phase. We handle	status
 * phase by issuing the	FAS command 'CMD_COMP_SEQ' which causes	the
 * FAS to read the status byte,	and then to read a message in (presumably
 * one of COMMAND COMPLETE, LINKED COMMAND COMPLETE or LINKED COMMAND
 * COMPLETE WITH FLAG).
 *
 * This	state is what is expected to follow after the issuance of the
 * FAS command 'CMD_COMP_SEQ'.
 */
#define	ACTS_C_CMPLT		0x0B

/*
 * This	state is used by the driver to indicate	that it
 * is in the middle of processing a reselection	attempt.
 */
#define	ACTS_RESEL		0x0C

/*
 * This	state is used by the driver to indicate	that it	doesn't	know
 * what	the next state is, and that it should look at the FAS's	status
 * register to find out	what SCSI bus phase we are in in order to select
 * the next state to transition	to.
 */
#define	ACTS_UNKNOWN		0x0D

/*
 * This	state is used by the driver to indicate	that a self-inititated
 * Bus reset is	in progress.
 */
#define	ACTS_RESET		0x0E

/*
 * Hiwater mark	of vectored states
 */
#define	ACTS_ENDVEC		0x0E

/*
 * XXX - needs to distinguish between bus states and internal states
 */

/*
 * This	state is used by the driver to indicate	to itself that it is
 * in the middle of aborting things.
 */
#define	ACTS_ABORTING		0x1D

/*
 * This	state is used by the driver to just hold the state of
 * the softc structure while it	is either aborting or resetting
 * everything.
 */
#define	ACTS_FROZEN		0x1F


/*
 * Interrupt dispatch actions
 */
#define	ACTION_RETURN		-1	/* return from interrupt */
#define	ACTION_FINSEL		0x00	/* finish selection */
#define	ACTION_RESEL		0x01	/* handle reselection */
#define	ACTION_PHASEMANAGE	0x02	/* manage phases */
#define	ACTION_FINISH		0x03	/* this	command	done */
#define	ACTION_FINRST		0x04	/* finish reset	recovery */
#define	ACTION_SEARCH		0x05	/* search for new command to start */
#define	ACTION_ABORT_CURCMD	0x06	/* abort current command */
#define	ACTION_ABORT_ALLCMDS	0x07	/* abort all commands */
#define	ACTION_RESET		0x08	/* reset bus */
#define	ACTION_SELECT		0x09	/* handle selection */

/*
 * Proxy command definitions.
 *
 * At certain times, we	need to	run a proxy command for	a target
 * (if only to select a	target and send	a message).
 *
 * We use the tail end of the cdb that is internal to the fas_cmd
 * structure to	store the proxy	code, the proxy	data (e.g., the
 * message to send).
 *
 * We also store a boolean result code in this area so that the
 * user	of a proxy command knows whether it succeeded.
 */

/*
 * Offsets into	the cmd_cdb[] array (in fas_cmd) for proxy data
 */
#define	FAS_PROXY_TYPE		CDB_GROUP0
#define	FAS_PROXY_RESULT	FAS_PROXY_TYPE+1
#define	FAS_PROXY_DATA		FAS_PROXY_RESULT+1

/*
 * Currently supported proxy types
 */

#define	FAS_PROXY_SNDMSG	1

/*
 * Reset actions
 */
#define	FAS_RESET_FAS		0x1	/* reset FAS chip */
#define	FAS_RESET_DMA		0x2	/* reset DMA gate array	*/
#define	FAS_RESET_BRESET	0x4	/* reset SCSI bus */
#define	FAS_RESET_IGNORE_BRESET	0x8	/* ignore SCSI Bus RESET interrupt */
					/* while resetting bus.	*/
#define	FAS_RESET_SCSIBUS	(FAS_RESET_BRESET|FAS_RESET_IGNORE_BRESET)
#define	FAS_RESET_SOFTC		0x10	/* reset SOFTC structure */

#define	FAS_RESET_HW		(FAS_RESET_FAS|FAS_RESET_DMA|FAS_RESET_SCSIBUS)
#define	FAS_RESET_ALL		(FAS_RESET_HW|FAS_RESET_SOFTC)

#define	FAS_RESET_MSG		0x20

#define	FAS_RESET_SPIN_DELAY_USEC	20
#define	FAS_RESET_SPIN_MAX_LOOP		1000

/*
 * f_softstate flags
 */
#define	FAS_SS_DRAINING		0x02
#define	FAS_SS_QUIESCED		0x04

/*
 * Debugging macros and	defines
 */
#ifdef	FASDEBUG
/*PRINTFLIKE2*/
extern void fas_dprintf(struct fas *fas, const char *fmt, ...)
	__KPRINTFLIKE(2);

#define	INFORMATIVE	(fasdebug)
#define	IDEBUGGING	((fasdebug) && \
			((fas->f_instance == fasdebug_instance)	|| \
			(fasdebug_instance == -1)))
#define	DDEBUGGING	((fasdebug > 1)	&& \
			((fas->f_instance == fasdebug_instance)	|| \
			(fasdebug_instance == -1)))

#define	EDEBUGGING	((fasdebug > 2)	&& \
			((fas->f_instance == fasdebug_instance)	|| \
			(fasdebug_instance == -1)))

#define	EPRINTF(str)		if (EDEBUGGING)	fas_dprintf(fas, str)
#define	EPRINTF1(str, a)	if (EDEBUGGING)	fas_dprintf(fas, str, a)
#define	EPRINTF2(str, a, b)	if (EDEBUGGING)	fas_dprintf(fas, str, a, b)
#define	EPRINTF3(str, a, b, c)	if (EDEBUGGING)	fas_dprintf(fas, str, a, b, c)
#define	EPRINTF4(str, a, b, c, d)	\
	if (EDEBUGGING)	fas_dprintf(fas, str, a, b, c, d)
#define	EPRINTF5(str, a, b, c, d, e)	\
	if (EDEBUGGING)	fas_dprintf(fas, str, a, b, c, d, e)
#define	EPRINTF6(str, a, b, c, d, e, f)	\
	if (EDEBUGGING)	fas_dprintf(fas, str, a, b, c, d, e, f)

#define	DPRINTF(str)		if (DDEBUGGING)	fas_dprintf(fas, str)
#define	DPRINTF1(str, a)	if (DDEBUGGING)	fas_dprintf(fas, str, a)
#define	DPRINTF2(str, a, b)	if (DDEBUGGING)	fas_dprintf(fas, str, a, b)
#define	DPRINTF3(str, a, b, c)	if (DDEBUGGING)	fas_dprintf(fas, str, a, b, c)
#define	DPRINTF4(str, a, b, c, d)	\
	if (DDEBUGGING)	fas_dprintf(fas, str, a, b, c, d)
#define	DPRINTF5(str, a, b, c, d, e)	\
	if (DDEBUGGING)	fas_dprintf(fas, str, a, b, c, d, e)
#define	DPRINTF6(str, a, b, c, d, e, f)	\
	if (DDEBUGGING)	fas_dprintf(fas, str, a, b, c, d, e, f)

#define	IPRINTF(str)		if (IDEBUGGING)	fas_dprintf(fas, str)
#define	IPRINTF1(str, a)	if (IDEBUGGING)	fas_dprintf(fas, str, a)
#define	IPRINTF2(str, a, b)	if (IDEBUGGING)	fas_dprintf(fas, str, a, b)
#define	IPRINTF3(str, a, b, c)	if (IDEBUGGING)	fas_dprintf(fas, str, a, b, c)
#define	IPRINTF4(str, a, b, c, d)	\
	if (IDEBUGGING)	fas_dprintf(fas, str, a, b, c, d)
#define	IPRINTF5(str, a, b, c, d, e)	\
	if (IDEBUGGING)	fas_dprintf(fas, str, a, b, c, d, e)
#define	IPRINTF6(str, a, b, c, d, e, f)	\
	if (IDEBUGGING)	fas_dprintf(fas, str, a, b, c, d, e, f)

#else	/* FASDEBUG */

#define	EPRINTF(str)
#define	EPRINTF1(str, a)
#define	EPRINTF2(str, a, b)
#define	EPRINTF3(str, a, b, c)
#define	EPRINTF4(str, a, b, c, d)
#define	EPRINTF5(str, a, b, c, d, e)
#define	EPRINTF6(str, a, b, c, d, e, f)
#define	DPRINTF(str)
#define	DPRINTF1(str, a)
#define	DPRINTF2(str, a, b)
#define	DPRINTF3(str, a, b, c)
#define	DPRINTF4(str, a, b, c, d)
#define	DPRINTF5(str, a, b, c, d, e)
#define	DPRINTF6(str, a, b, c, d, e, f)
#define	IPRINTF(str)
#define	IPRINTF1(str, a)
#define	IPRINTF2(str, a, b)
#define	IPRINTF3(str, a, b, c)
#define	IPRINTF4(str, a, b, c, d)
#define	IPRINTF5(str, a, b, c, d, e)
#define	IPRINTF6(str, a, b, c, d, e, f)

#endif	/* FASDEBUG */

/*
 * Shorthand macros and	defines
 */

/*
 * Short hand defines
 */
#define	ALL_TARGETS	0xffff

#define	MAX_THROTTLE	254	/* 1 tag used for non-tagged cmds, 1 rsvd */
#define	HOLD_THROTTLE	0
#define	DRAIN_THROTTLE	-1
#define	QFULL_THROTTLE	-2

#define	NODISC(tgt)		(fas->f_nodisc & (1<<(tgt)))
#define	NOTAG(tgt)		(fas->f_notag &	(1<<(tgt)))
#define	TAGGED(tgt)		((fas->f_notag & (1<<(tgt))) ==	0)
#define	SYNC_KNOWN(tgt)		(fas->f_sync_known & (1<<(tgt)))

#define	NEXTSLOT(slot, d)	((slot)+(d)) & ((N_SLOTS)-1)
#define	MY_ID(fas)		((fas)->f_fasconf & FAS_CONF_BUSID)
#define	INTPENDING(fas)		(fas_dma_reg_read((fas), \
				    &((fas)->f_dma->dma_csr))&DMA_INT_MASK)

#define	Tgt(sp)	((sp)->cmd_pkt->pkt_address.a_target)
#define	Lun(sp)	((sp)->cmd_pkt->pkt_address.a_lun)

#define	New_state(fas, state)\
	(fas)->f_laststate = (fas)->f_state, (fas)->f_state = (state)

#define	CNUM		(fas->f_instance)
#define	TRUE		1
#define	FALSE		0
#define	UNDEFINED	-1
#define	INVALID_MSG	0x7f

/*
 * Default is to have 10 retries on receiving QFULL status and
 * each retry to be after 100 ms.
 */
#define	QFULL_RETRIES		10
#define	QFULL_RETRY_INTERVAL	100

/*
 * FEPS chip revision
 */
#define	FAS_HM_REV(fas)		(fas)->f_hm_rev

/*
 * Some	manifest miscellaneous constants
 */

#define	MEG		(1000 *	1000)
#define	FIVE_MEG	(5 * MEG)
#define	TEN_MEG		(10 * MEG)
#define	TWENTY_MEG	(20 * MEG)
#define	TWENTYFIVE_MEG	(25 * MEG)
#define	FORTY_MEG	(40 * MEG)
#define	FAS_FREQ_SLOP	(25000)

/*
 * wide	support
 */
#define	FAS_XFER_WIDTH	1

#define	FAS_EMPTY_CALLBACKQ(fas)  fas_empty_callbackQ(fas)

#define	FAS_CHECK_WAITQ_AND_FAS_MUTEX_EXIT(fas)	\
	mutex_enter(&fas->f_waitQ_mutex); \
	if (fas->f_waitf) { \
		fas_empty_waitQ(fas); \
	} \
	mutex_exit(FAS_MUTEX(fas)); \
	mutex_exit(&fas->f_waitQ_mutex);

/*
 * flags for fas_accept_pkt
 */
#define	NO_TRAN_BUSY	0	/* fas_accept_pkt may not bounce these pkts */
#define	TRAN_BUSY_OK	1	/* fas_accept_pkt may bounce these pkts */

/*
 * reset delay tick
 */
#define	FAS_WATCH_RESET_DELAY_TICK 50	/* specified in	milli seconds */

/*
 * 2 ms timeout on receiving tag on reconnect
 */
#define	RECONNECT_TAG_RCV_TIMEOUT 2000	/* allow up to 2 ms */


/*
 * auto	request	sense
 */
#define	RQ_MAKECOM_COMMON(pktp,	flag, cmd)   \
	(pktp)->pkt_flags = (flag), \
	((union	scsi_cdb *)(pktp)->pkt_cdbp)->scc_cmd =	(cmd), \
	((union	scsi_cdb *)(pktp)->pkt_cdbp)->scc_lun =	\
	    (pktp)->pkt_address.a_lun

#define	RQ_MAKECOM_G0(pktp, flag, cmd, addr, cnt)    \
	RQ_MAKECOM_COMMON((pktp), (flag), (cmd)), \
	FORMG0ADDR(((union scsi_cdb *)(pktp)->pkt_cdbp), (addr)), \
	FORMG0COUNT(((union scsi_cdb *)(pktp)->pkt_cdbp), (cnt))

#define	NEW_TIMEOUT	1

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SCSI_ADAPTERS_FASVAR_H */